Merge branch 'master' into upstream-merge-30056

This commit is contained in:
LetterJay
2017-09-13 06:08:59 -05:00
committed by GitHub
545 changed files with 23622 additions and 13702 deletions
+1 -1
View File
@@ -122,7 +122,7 @@
/proc/SDQL_gen_vv_href(t)
var/text = ""
text += "<A HREF='?_src_=vars;Vars=\ref[t]'>\ref[t]</A>"
text += "<A HREF='?_src_=vars;[HrefToken()];Vars=\ref[t]'>\ref[t]</A>"
if(istype(t, /atom))
var/atom/a = t
var/turf/T = a.loc
@@ -170,5 +170,13 @@
return
L -= args.Copy(2)
/proc/_list_set(list/L, key, value)
L[key] = value
/proc/_list_numerical_add(L, key, num)
L[key] += num
/proc/_list_swap(list/L, Index1, Index2)
L.Swap(Index1, Index2)
+10 -11
View File
@@ -80,10 +80,10 @@ GLOBAL_DATUM_INIT(ahelp_tickets, /datum/admin_help_tickets, new)
if(!l2b)
return
var/list/dat = list("<html><head><title>[title]</title></head>")
dat += "<A HREF='?_src_=holder;ahelp_tickets=[state]'>Refresh</A><br><br>"
dat += "<A href='?_src_=holder;[HrefToken()];ahelp_tickets=[state]'>Refresh</A><br><br>"
for(var/I in l2b)
var/datum/admin_help/AH = I
dat += "<span class='adminnotice'><span class='adminhelp'>Ticket #[AH.id]</span>: <A HREF='?_src_=holder;ahelp=\ref[AH];ahelp_action=ticket'>[AH.initiator_key_name]: [AH.name]</A></span><br>"
dat += "<span class='adminnotice'><span class='adminhelp'>Ticket #[AH.id]</span>: <A href='?_src_=holder;[HrefToken()];ahelp=\ref[AH];ahelp_action=ticket'>[AH.initiator_key_name]: [AH.name]</A></span><br>"
usr << browse(dat.Join(), "window=ahelp_list[state];size=600x480")
@@ -228,22 +228,22 @@ GLOBAL_DATUM_INIT(ahelp_tickets, /datum/admin_help_tickets, new)
/datum/admin_help/proc/ClosureLinks(ref_src)
if(!ref_src)
ref_src = "\ref[src]"
. = " (<A HREF='?_src_=holder;ahelp=[ref_src];ahelp_action=reject'>REJT</A>)"
. += " (<A HREF='?_src_=holder;ahelp=[ref_src];ahelp_action=icissue'>IC</A>)"
. += " (<A HREF='?_src_=holder;ahelp=[ref_src];ahelp_action=close'>CLOSE</A>)"
. += " (<A HREF='?_src_=holder;ahelp=[ref_src];ahelp_action=resolve'>RSLVE</A>)"
. = " (<A HREF='?_src_=holder;[HrefToken(TRUE)];ahelp=[ref_src];ahelp_action=reject'>REJT</A>)"
. += " (<A HREF='?_src_=holder;[HrefToken(TRUE)];ahelp=[ref_src];ahelp_action=icissue'>IC</A>)"
. += " (<A HREF='?_src_=holder;[HrefToken(TRUE)];ahelp=[ref_src];ahelp_action=close'>CLOSE</A>)"
. += " (<A HREF='?_src_=holder;[HrefToken(TRUE)];ahelp=[ref_src];ahelp_action=resolve'>RSLVE</A>)"
//private
/datum/admin_help/proc/LinkedReplyName(ref_src)
if(!ref_src)
ref_src = "\ref[src]"
return "<A HREF='?_src_=holder;ahelp=[ref_src];ahelp_action=reply'>[initiator_key_name]</A>"
return "<A HREF='?_src_=holder;[HrefToken()];ahelp=[ref_src];ahelp_action=reply'>[initiator_key_name]</A>"
//private
/datum/admin_help/proc/TicketHref(msg, ref_src, action = "ticket")
if(!ref_src)
ref_src = "\ref[src]"
return "<A HREF='?_src_=holder;ahelp=[ref_src];ahelp_action=[action]'>[msg]</A>"
return "<A HREF='?_src_=holder;[HrefToken()];ahelp=[ref_src];ahelp_action=[action]'>[msg]</A>"
//message from the initiator without a target, all admins will see this
//won't bug irc
@@ -327,8 +327,7 @@ GLOBAL_DATUM_INIT(ahelp_tickets, /datum/admin_help_tickets, new)
state = AHELP_RESOLVED
GLOB.ahelp_tickets.ListInsert(src)
if(initiator)
initiator.giveadminhelpverb()
addtimer(CALLBACK(initiator, /client/proc/giveadminhelpverb), 50)
AddInteraction("<font color='green'>Resolved by [key_name].</font>")
if(!silent)
@@ -675,7 +674,7 @@ GLOBAL_DATUM_INIT(ahelp_tickets, /datum/admin_help_tickets, new)
if(found.mind && found.mind.special_role)
is_antag = 1
founds += "Name: [found.name]([found.real_name]) Ckey: [found.ckey] [is_antag ? "(Antag)" : null] "
msg += "[original_word]<font size='1' color='[is_antag ? "red" : "black"]'>(<A HREF='?_src_=holder;adminmoreinfo=\ref[found]'>?</A>|<A HREF='?_src_=holder;adminplayerobservefollow=\ref[found]'>F</A>)</font> "
msg += "[original_word]<font size='1' color='[is_antag ? "red" : "black"]'>(<A HREF='?_src_=holder;[HrefToken()];adminmoreinfo=\ref[found]'>?</A>|<A HREF='?_src_=holder;[HrefToken()];adminplayerobservefollow=\ref[found]'>F</A>)</font> "
continue
msg += "[original_word] "
if(irc)
+1 -1
View File
@@ -12,7 +12,7 @@
log_talk(mob,"[key_name(src)] : [msg]",LOGASAY)
msg = keywords_lookup(msg)
if(check_rights(R_ADMIN,0))
msg = "<span class='admin'><span class='prefix'>ADMIN:</span> <EM>[key_name(usr, 1)]</EM> (<a href='?_src_=holder;adminplayerobservefollow=\ref[mob]'>FLW</A>): <span class='message'>[msg]</span></span>"
msg = "<span class='admin'><span class='prefix'>ADMIN:</span> <EM>[key_name(usr, 1)]</EM> [ADMIN_FLW(mob)]: <span class='message'>[msg]</span></span>"
to_chat(GLOB.admins, msg)
else
msg = "<span class='adminobserver'><span class='prefix'>ADMIN:</span> <EM>[key_name(usr, 1)]:</EM> <span class='message'>[msg]</span></span>"
+22 -12
View File
@@ -743,21 +743,31 @@ GLOBAL_PROTECT(AdminProcCallCount)
/client/proc/cmd_display_del_log()
set category = "Debug"
set name = "Display del() Log"
set desc = "Displays a list of things that have failed to GC this round"
set desc = "Display del's log of everything that's passed through it."
var/dat = "<B>List of things that failed to GC this round</B><BR><BR>"
for(var/path in SSgarbage.didntgc)
dat += "[path] - [SSgarbage.didntgc[path]] times<BR>"
var/list/dellog = list("<B>List of things that have gone through qdel this round</B><BR><BR><ol>")
sortTim(SSgarbage.items, cmp=/proc/cmp_qdel_item_time, associative = TRUE)
for(var/path in SSgarbage.items)
var/datum/qdel_item/I = SSgarbage.items[path]
dellog += "<li><u>[path]</u><ul>"
if (I.failures)
dellog += "<li>Failures: [I.failures]</li>"
dellog += "<li>qdel() Count: [I.qdels]</li>"
dellog += "<li>Destroy() Cost: [I.destroy_time]ms</li>"
if (I.hard_deletes)
dellog += "<li>Total Hard Deletes [I.hard_deletes]</li>"
dellog += "<li>Time Spent Hard Deleting: [I.hard_delete_time]ms</li>"
if (I.slept_destroy)
dellog += "<li>Sleeps: [I.slept_destroy]</li>"
if (I.no_respect_force)
dellog += "<li>Ignored force: [I.no_respect_force]</li>"
if (I.no_hint)
dellog += "<li>No hint: [I.no_hint]</li>"
dellog += "</ul></li>"
dat += "<B>List of paths that did not return a qdel hint in Destroy()</B><BR><BR>"
for(var/path in SSgarbage.noqdelhint)
dat += "[path]<BR>"
dellog += "</ol>"
dat += "<B>List of paths that slept in Destroy()</B><BR><BR>"
for(var/path in SSgarbage.sleptDestroy)
dat += "[path]<BR>"
usr << browse(dat, "window=dellog")
usr << browse(dellog.Join(), "window=dellog")
/client/proc/cmd_display_init_log()
set category = "Debug"
@@ -1,12 +1,12 @@
/proc/show_individual_logging_panel(mob/M, type = INDIVIDUAL_ATTACK_LOG)
if(!M || !ismob(M))
return
var/dat = "<center><a href='?_src_=holder;individuallog=\ref[M];log_type=[INDIVIDUAL_ATTACK_LOG]'>Attack log</a> | "
dat += "<a href='?_src_=holder;individuallog=\ref[M];log_type=[INDIVIDUAL_SAY_LOG]'>Say log</a> | "
dat += "<a href='?_src_=holder;individuallog=\ref[M];log_type=[INDIVIDUAL_EMOTE_LOG]'>Emote log</a> | "
dat += "<a href='?_src_=holder;individuallog=\ref[M];log_type=[INDIVIDUAL_OOC_LOG]'>OOC log</a> | "
dat += "<a href='?_src_=holder;individuallog=\ref[M];log_type=[INDIVIDUAL_SHOW_ALL_LOG]'>Show all</a> | "
dat += "<a href='?_src_=holder;individuallog=\ref[M];log_type=[type]'>Refresh</a></center>"
var/dat = "<center><a href='?_src_=holder;[HrefToken()];individuallog=\ref[M];log_type=[INDIVIDUAL_ATTACK_LOG]'>Attack log</a> | "
dat += "<a href='?_src_=holder;[HrefToken()];individuallog=\ref[M];log_type=[INDIVIDUAL_SAY_LOG]'>Say log</a> | "
dat += "<a href='?_src_=holder;[HrefToken()];individuallog=\ref[M];log_type=[INDIVIDUAL_EMOTE_LOG]'>Emote log</a> | "
dat += "<a href='?_src_=holder;[HrefToken()];individuallog=\ref[M];log_type=[INDIVIDUAL_OOC_LOG]'>OOC log</a> | "
dat += "<a href='?_src_=holder;[HrefToken()];individuallog=\ref[M];log_type=[INDIVIDUAL_SHOW_ALL_LOG]'>Show all</a> | "
dat += "<a href='?_src_=holder;[HrefToken()];individuallog=\ref[M];log_type=[type]'>Refresh</a></center>"
dat += "<hr style='background:#000000; border:0; height:1px'>"
+12 -12
View File
@@ -11,17 +11,17 @@
/datum/admins/proc/one_click_antag()
var/dat = {"
<a href='?src=\ref[src];makeAntag=traitors'>Make Traitors</a><br>
<a href='?src=\ref[src];makeAntag=changelings'>Make Changelings</a><br>
<a href='?src=\ref[src];makeAntag=revs'>Make Revs</a><br>
<a href='?src=\ref[src];makeAntag=cult'>Make Cult</a><br>
<a href='?src=\ref[src];makeAntag=clockcult'>Make Clockwork Cult</a><br>
<a href='?src=\ref[src];makeAntag=blob'>Make Blob</a><br>
<a href='?src=\ref[src];makeAntag=wizard'>Make Wizard (Requires Ghosts)</a><br>
<a href='?src=\ref[src];makeAntag=nukeops'>Make Nuke Team (Requires Ghosts)</a><br>
<a href='?src=\ref[src];makeAntag=centcom'>Make CentCom Response Team (Requires Ghosts)</a><br>
<a href='?src=\ref[src];makeAntag=abductors'>Make Abductor Team (Requires Ghosts)</a><br>
<a href='?src=\ref[src];makeAntag=revenant'>Make Revenant (Requires Ghost)</a><br>
<a href='?src=\ref[src];[HrefToken()];makeAntag=traitors'>Make Traitors</a><br>
<a href='?src=\ref[src];[HrefToken()];makeAntag=changelings'>Make Changelings</a><br>
<a href='?src=\ref[src];[HrefToken()];makeAntag=revs'>Make Revs</a><br>
<a href='?src=\ref[src];[HrefToken()];makeAntag=cult'>Make Cult</a><br>
<a href='?src=\ref[src];[HrefToken()];makeAntag=clockcult'>Make Clockwork Cult</a><br>
<a href='?src=\ref[src];[HrefToken()];makeAntag=blob'>Make Blob</a><br>
<a href='?src=\ref[src];[HrefToken()];makeAntag=wizard'>Make Wizard (Requires Ghosts)</a><br>
<a href='?src=\ref[src];[HrefToken()];makeAntag=nukeops'>Make Nuke Team (Requires Ghosts)</a><br>
<a href='?src=\ref[src];[HrefToken()];makeAntag=centcom'>Make CentCom Response Team (Requires Ghosts)</a><br>
<a href='?src=\ref[src];[HrefToken()];makeAntag=abductors'>Make Abductor Team (Requires Ghosts)</a><br>
<a href='?src=\ref[src];[HrefToken()];makeAntag=revenant'>Make Revenant (Requires Ghost)</a><br>
"}
var/datum/browser/popup = new(usr, "oneclickantag", "Quick-Create Antagonist", 400, 400)
@@ -356,7 +356,7 @@
return 0
return
/datum/admins/proc/makeOfficial()
var/mission = input("Assign a task for the official", "Assign Task", "Conduct a routine preformance review of [station_name()] and its Captain.")
var/list/mob/dead/observer/candidates = pollGhostCandidates("Do you wish to be considered to be a CentCom Official?", "deathsquad")
+63
View File
@@ -36,7 +36,11 @@
for(var/mob/M in GLOB.player_list)
if(M.client.prefs.toggles & SOUND_MIDI)
var/user_vol = M.client.chatOutput.adminMusicVolume
if(user_vol)
admin_sound.volume = vol * (user_vol / 100)
SEND_SOUND(M, admin_sound)
admin_sound.volume = vol
SSblackbox.add_details("admin_verb","Play Global Sound") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
@@ -52,6 +56,62 @@
playsound(get_turf(src.mob), S, 50, 0, 0)
SSblackbox.add_details("admin_verb","Play Local Sound") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
/client/proc/play_web_sound()
set category = "Fun"
set name = "Play Internet Sound"
if(!check_rights(R_SOUNDS))
return
if(!config.invoke_youtubedl)
to_chat(src, "<span class='boldwarning'>Youtube-dl was not configured, action unavailable</span>") //Check config.txt for the INVOKE_YOUTUBEDL value
return
var/web_sound_input = input("Enter content URL (supported sites only, leave blank to stop playing)", "Play Internet Sound via youtube-dl") as text|null
if(istext(web_sound_input))
var/web_sound_url = ""
var/pitch
if(length(web_sound_input))
web_sound_input = trim(web_sound_input)
var/static/regex/html_protocol_regex = regex("https?://")
if(findtext(web_sound_input, ":") && !findtext(web_sound_input, html_protocol_regex))
to_chat(src, "<span class='boldwarning'>Non-http(s) URIs are not allowed.</span>")
to_chat(src, "<span class='warning'>For youtube-dl shortcuts like ytsearch: please use the appropriate full url from the website.</span>")
return
var/shell_scrubbed_input = shell_url_scrub(web_sound_input)
var/list/output = world.shelleo("[config.invoke_youtubedl] --format \"bestaudio\[ext=mp3]/best\[ext=mp4]\[height<=360]/bestaudio\[ext=m4a]/bestaudio\[ext=aac]\" --get-url \"[shell_scrubbed_input]\"")
var/errorlevel = output[SHELLEO_ERRORLEVEL]
var/stdout = output[SHELLEO_STDOUT]
var/stderr = output[SHELLEO_STDERR]
if(!errorlevel)
var/static/regex/content_url_regex = regex("https?://\\S+")
if(content_url_regex.Find(stdout))
web_sound_url = content_url_regex.match
if(SSevents.holidays && SSevents.holidays[APRIL_FOOLS])
pitch = pick(0.5, 0.7, 0.8, 0.85, 0.9, 0.95, 1.1, 1.2, 1.4, 1.6, 2.0, 2.5)
to_chat(src, "You feel the Honkmother messing with your song...")
log_admin("[key_name(src)] played web sound: [web_sound_input]")
message_admins("[key_name(src)] played web sound: [web_sound_input]")
else
to_chat(src, "<span class='boldwarning'>Youtube-dl URL retrieval FAILED:</span>")
to_chat(src, "<span class='warning'>[stderr]</span>")
else //pressed ok with blank
log_admin("[key_name(src)] stopped web sound")
message_admins("[key_name(src)] stopped web sound")
web_sound_url = " "
if(web_sound_url)
for(var/m in GLOB.player_list)
var/mob/M = m
var/client/C = M.client
if((C.prefs.toggles & SOUND_MIDI) && C.chatOutput && !C.chatOutput.broken && C.chatOutput.loaded)
C.chatOutput.sendMusic(web_sound_url, pitch)
SSblackbox.add_details("admin_verb","Play Internet Sound")
/client/proc/set_round_end_sound(S as sound)
set category = "Fun"
set name = "Set Round End Sound"
@@ -75,4 +135,7 @@
for(var/mob/M in GLOB.player_list)
if(M.client)
SEND_SOUND(M, sound(null))
var/client/C = M.client
if(C && C.chatOutput && !C.chatOutput.broken && C.chatOutput.loaded)
C.chatOutput.sendMusic(" ")
SSblackbox.add_details("admin_verb","Stop All Playing Sounds") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
+51 -2
View File
@@ -1144,8 +1144,8 @@ GLOBAL_LIST_EMPTY(custom_outfits) //Admin created outfits
/datum/admins/proc/modify_goals()
var/dat = ""
for(var/datum/station_goal/S in SSticker.mode.station_goals)
dat += "[S.name] - <a href='?src=\ref[S];announce=1'>Announce</a> | <a href='?src=\ref[S];remove=1'>Remove</a><br>"
dat += "<br><a href='?src=\ref[src];add_station_goal=1'>Add New Goal</a>"
dat += "[S.name] - <a href='?src=\ref[S];[HrefToken()];announce=1'>Announce</a> | <a href='?src=\ref[S];[HrefToken()];remove=1'>Remove</a><br>"
dat += "<br><a href='?src=\ref[src];[HrefToken()];add_station_goal=1'>Add New Goal</a>"
usr << browse(dat, "window=goals;size=400x400")
@@ -1207,3 +1207,52 @@ GLOBAL_LIST_EMPTY(custom_outfits) //Admin created outfits
message_admins("[key_name_admin(usr)] triggered a CentCom recall, with the admiral message of: [message]")
log_game("[key_name(usr)] triggered a CentCom recall, with the message of: [message]")
SSshuttle.centcom_recall(SSshuttle.emergency.timer, message)
/client/proc/cmd_admin_check_player_exp() //Allows admins to determine who the newer players are.
set category = "Admin"
set name = "Player Playtime"
if(!check_rights(R_ADMIN))
return
var/list/msg = list()
msg += "<html><head><title>Playtime Report</title></head><body>Playtime:<BR><UL>"
for(var/client/C in GLOB.clients)
msg += "<LI> - [key_name_admin(C)]: <A href='?_src_=holder;[HrefToken()];getplaytimewindow=\ref[C.mob]'>" + C.get_exp_living() + "</a></LI>"
msg += "</UL></BODY></HTML>"
src << browse(msg.Join(), "window=Player_playtime_check")
/datum/admins/proc/cmd_show_exp_panel(client/C)
if(!check_rights(R_ADMIN))
return
if(!C)
to_chat(usr, "<span class='danger'>ERROR: Client not found.</span>")
return
var/list/body = list()
body += "<html><head><title>Playtime for [C.key]</title></head><BODY><BR>Playtime:"
body += C.get_exp_report()
body += "<A href='?_src_=holder;[HrefToken()];toggleexempt=\ref[C]'>Toggle Exempt status</a>"
body += "</BODY></HTML>"
usr << browse(body.Join(), "window=playerplaytime[C.ckey];size=550x615")
/datum/admins/proc/toggle_exempt_status(client/C)
if(!check_rights(R_ADMIN))
return
if(!C)
to_chat(usr, "<span class='danger'>ERROR: Client not found.</span>")
return
if(!C.set_db_player_flags())
to_chat(usr, "<span class='danger'>ERROR: Unable read player flags from database. Please check logs.</span>")
var/dbflags = C.prefs.db_flags
var/newstate = FALSE
if(dbflags & DB_FLAG_EXEMPT)
newstate = FALSE
else
newstate = TRUE
if(C.update_flag_db(DB_FLAG_EXEMPT, newstate))
to_chat(usr, "<span class='danger'>ERROR: Unable to update player flags. Please check logs.</span>")
else
message_admins("[key_name_admin(usr)] has [newstate ? "activated" : "deactivated"] job exp exempt status on [key_name_admin(C)]")
log_admin("[key_name(usr)] has [newstate ? "activated" : "deactivated"] job exp exempt status on [key_name(C)]")
+22 -7
View File
@@ -1,10 +1,25 @@
diff a/code/modules/admin/verbs/randomverbs.dm b/code/modules/admin/verbs/randomverbs.dm (rejected hunks)
@@ -1214,7 +1214,7 @@ GLOBAL_LIST_EMPTY(custom_outfits) //Admin created outfits
/client/proc/cmd_admin_check_player_exp() //Allows admins to determine who the newer players are.
set category = "Admin"
- set name = "Check Player Playtime"
+ set name = "Player Playtime"
if(!check_rights(R_ADMIN))
@@ -1246,7 +1246,8 @@ GLOBAL_LIST_EMPTY(custom_outfits) //Admin created outfits
to_chat(usr, "<span class='danger'>ERROR: Client not found.</span>")
return
- C.set_db_player_flags()
+ if(!C.set_db_player_flags())
+ to_chat(usr, "<span class='danger'>ERROR: Unable read player flags from database. Please check logs.</span>")
var/dbflags = C.prefs.db_flags
var/newstate = FALSE
if(dbflags & DB_FLAG_EXEMPT)
@@ -1254,6 +1255,8 @@ GLOBAL_LIST_EMPTY(custom_outfits) //Admin created outfits
else
newstate = TRUE
- message_admins("[key_name_admin(usr)] has [newstate ? "activated" : "deactivated"] job exp exempt status on [key_name_admin(C)]")
- log_admin("[key_name(usr)] has [newstate ? "activated" : "deactivated"] job exp exempt status on [key_name(C)]")
- C.update_flag_db(DB_FLAG_EXEMPT, newstate)
\ No newline at end of file
+ if(C.update_flag_db(DB_FLAG_EXEMPT, newstate))
+ to_chat(usr, "<span class='danger'>ERROR: Unable to update player flags. Please check logs.</span>")
+ else
+ message_admins("[key_name_admin(usr)] has [newstate ? "activated" : "deactivated"] job exp exempt status on [key_name_admin(C)]")
+ log_admin("[key_name(usr)] has [newstate ? "activated" : "deactivated"] job exp exempt status on [key_name(C)]")
\ No newline at end of file