Admin ticket tgstyle (#493)

* some porting

* other changes
This commit is contained in:
Poojawa
2017-04-20 22:00:47 -05:00
committed by GitHub
parent 03ed17649c
commit f866139c52
19 changed files with 835 additions and 843 deletions
+21 -17
View File
@@ -6,7 +6,7 @@
if(!check_rights(R_BAN))
return
if(!SSdbcore.Connect())
if(!SSdbcore.Connect())
to_chat(src, "<span class='danger'>Failed to establish database connection.</span>")
return
@@ -71,7 +71,7 @@
computerid = bancid
ip = banip
var/datum/DBQuery/query_add_ban_get_id = SSdbcore.NewQuery("SELECT id FROM [format_table_name("player")] WHERE ckey = '[ckey]'")
var/datum/DBQuery/query_add_ban_get_id = SSdbcore.NewQuery("SELECT id FROM [format_table_name("player")] WHERE ckey = '[ckey]'")
if(!query_add_ban_get_id.warn_execute())
return
var/validckey = 0
@@ -113,7 +113,7 @@
reason = sanitizeSQL(reason)
if(maxadminbancheck)
var/datum/DBQuery/query_check_adminban_amt = SSdbcore.NewQuery("SELECT count(id) AS num FROM [format_table_name("ban")] WHERE (a_ckey = '[a_ckey]') AND (bantype = 'ADMIN_PERMABAN' OR (bantype = 'ADMIN_TEMPBAN' AND expiration_time > Now())) AND isnull(unbanned)")
var/datum/DBQuery/query_check_adminban_amt = SSdbcore.NewQuery("SELECT count(id) AS num FROM [format_table_name("ban")] WHERE (a_ckey = '[a_ckey]') AND (bantype = 'ADMIN_PERMABAN' OR (bantype = 'ADMIN_TEMPBAN' AND expiration_time > Now())) AND isnull(unbanned)")
if(!query_check_adminban_amt.warn_execute())
return
if(query_check_adminban_amt.NextRow())
@@ -126,16 +126,20 @@
if(!ip)
ip = "0.0.0.0"
var/sql = "INSERT INTO [format_table_name("ban")] (`bantime`,`server_ip`,`server_port`,`bantype`,`reason`,`job`,`duration`,`expiration_time`,`ckey`,`computerid`,`ip`,`a_ckey`,`a_computerid`,`a_ip`,`who`,`adminwho`) VALUES (Now(), INET_ATON('[world.internet_address]'), '[world.port]', '[bantype_str]', '[reason]', '[job]', [(duration)?"[duration]":"0"], Now() + INTERVAL [(duration>0) ? duration : 0] MINUTE, '[ckey]', '[computerid]', INET_ATON('[ip]'), '[a_ckey]', '[a_computerid]', INET_ATON('[a_ip]'), '[who]', '[adminwho]')"
var/datum/DBQuery/query_add_ban = SSdbcore.NewQuery(sql)
var/datum/DBQuery/query_add_ban = SSdbcore.NewQuery(sql)
if(!query_add_ban.warn_execute())
return
to_chat(usr, "<span class='adminnotice'>Ban saved to database.</span>")
message_admins("[key_name_admin(usr)] has added a [bantype_str] for [ckey] [(job)?"([job])":""] [(duration > 0)?"([duration] minutes)":""] with the reason: \"[reason]\" to the ban database.",1)
var/msg = "[key_name_admin(usr)] has added a [bantype_str] for [ckey] [(job)?"([job])":""] [(duration > 0)?"([duration] minutes)":""] with the reason: \"[reason]\" to the ban database."
message_admins(msg,1)
var/datum/admin_help/AH = admin_ticket_log(ckey, msg)
if(announceinirc)
send2irc("BAN ALERT","[a_ckey] applied a [bantype_str] on [ckey]")
if(kickbannedckey)
if(AH)
AH.Resolve() //with prejudice
if(banned_mob && banned_mob.client && banned_mob.client.ckey == banckey)
qdel(banned_mob.client)
return 1
@@ -187,13 +191,13 @@
if(job)
sql += " AND job = '[job]'"
if(!SSdbcore.Connect())
if(!SSdbcore.Connect())
return
var/ban_id
var/ban_number = 0 //failsafe
var/datum/DBQuery/query_unban_get_id = SSdbcore.NewQuery(sql)
var/datum/DBQuery/query_unban_get_id = SSdbcore.NewQuery(sql)
if(!query_unban_get_id.warn_execute())
return
while(query_unban_get_id.NextRow())
@@ -225,7 +229,7 @@
to_chat(usr, "Cancelled")
return
var/datum/DBQuery/query_edit_ban_get_details = SSdbcore.NewQuery("SELECT ckey, duration, reason FROM [format_table_name("ban")] WHERE id = [banid]")
var/datum/DBQuery/query_edit_ban_get_details = SSdbcore.NewQuery("SELECT ckey, duration, reason FROM [format_table_name("ban")] WHERE id = [banid]")
if(!query_edit_ban_get_details.warn_execute())
return
@@ -254,7 +258,7 @@
to_chat(usr, "Cancelled")
return
var/datum/DBQuery/query_edit_ban_reason = SSdbcore.NewQuery("UPDATE [format_table_name("ban")] SET reason = '[value]', edits = CONCAT(edits,'- [eckey] changed ban reason from <cite><b>\\\"[reason]\\\"</b></cite> to <cite><b>\\\"[value]\\\"</b></cite><BR>') WHERE id = [banid]")
var/datum/DBQuery/query_edit_ban_reason = SSdbcore.NewQuery("UPDATE [format_table_name("ban")] SET reason = '[value]', edits = CONCAT(edits,'- [eckey] changed ban reason from <cite><b>\\\"[reason]\\\"</b></cite> to <cite><b>\\\"[value]\\\"</b></cite><BR>') WHERE id = [banid]")
if(!query_edit_ban_reason.warn_execute())
return
message_admins("[key_name_admin(usr)] has edited a ban for [pckey]'s reason from [reason] to [value]",1)
@@ -265,7 +269,7 @@
to_chat(usr, "Cancelled")
return
var/datum/DBQuery/query_edit_ban_duration = SSdbcore.NewQuery("UPDATE [format_table_name("ban")] SET duration = [value], edits = CONCAT(edits,'- [eckey] changed ban duration from [duration] to [value]<br>'), expiration_time = DATE_ADD(bantime, INTERVAL [value] MINUTE) WHERE id = [banid]")
var/datum/DBQuery/query_edit_ban_duration = SSdbcore.NewQuery("UPDATE [format_table_name("ban")] SET duration = [value], edits = CONCAT(edits,'- [eckey] changed ban duration from [duration] to [value]<br>'), expiration_time = DATE_ADD(bantime, INTERVAL [value] MINUTE) WHERE id = [banid]")
if(!query_edit_ban_duration.warn_execute())
return
message_admins("[key_name_admin(usr)] has edited a ban for [pckey]'s duration from [duration] to [value]",1)
@@ -287,13 +291,13 @@
var/sql = "SELECT ckey FROM [format_table_name("ban")] WHERE id = [id]"
if(!SSdbcore.Connect())
if(!SSdbcore.Connect())
return
var/ban_number = 0 //failsafe
var/pckey
var/datum/DBQuery/query_unban_get_ckey = SSdbcore.NewQuery(sql)
var/datum/DBQuery/query_unban_get_ckey = SSdbcore.NewQuery(sql)
if(!query_unban_get_ckey.warn_execute())
return
while(query_unban_get_ckey.NextRow())
@@ -316,7 +320,7 @@
var/unban_ip = src.owner:address
var/sql_update = "UPDATE [format_table_name("ban")] SET unbanned = 1, unbanned_datetime = Now(), unbanned_ckey = '[unban_ckey]', unbanned_computerid = '[unban_computerid]', unbanned_ip = INET_ATON('[unban_ip]') WHERE id = [id]"
var/datum/DBQuery/query_unban = SSdbcore.NewQuery(sql_update)
var/datum/DBQuery/query_unban = SSdbcore.NewQuery(sql_update)
if(!query_unban.warn_execute())
return
message_admins("[key_name_admin(usr)] has lifted [pckey]'s ban.",1)
@@ -339,7 +343,7 @@
if(!check_rights(R_BAN))
return
if(!SSdbcore.Connect())
if(!SSdbcore.Connect())
to_chat(usr, "<span class='danger'>Failed to establish database connection.</span>")
return
@@ -405,7 +409,7 @@
var/bansperpage = 15
var/pagecount = 0
page = text2num(page)
var/datum/DBQuery/query_count_bans = SSdbcore.NewQuery("SELECT COUNT(id) FROM [format_table_name("ban")] WHERE 1 [playersearch] [adminsearch]")
var/datum/DBQuery/query_count_bans = SSdbcore.NewQuery("SELECT COUNT(id) FROM [format_table_name("ban")] WHERE 1 [playersearch] [adminsearch]")
if(!query_count_bans.warn_execute())
return
if(query_count_bans.NextRow())
@@ -431,7 +435,7 @@
output += "<th width='15%'><b>OPTIONS</b></th>"
output += "</tr>"
var/limit = " LIMIT [bansperpage * page], [bansperpage]"
var/datum/DBQuery/query_search_bans = SSdbcore.NewQuery("SELECT id, bantime, bantype, reason, job, duration, expiration_time, ckey, a_ckey, unbanned, unbanned_ckey, unbanned_datetime, edits FROM [format_table_name("ban")] WHERE 1 [playersearch] [adminsearch] ORDER BY bantime DESC[limit]")
var/datum/DBQuery/query_search_bans = SSdbcore.NewQuery("SELECT id, bantime, bantype, reason, job, duration, expiration_time, ckey, a_ckey, unbanned, unbanned_ckey, unbanned_datetime, edits FROM [format_table_name("ban")] WHERE 1 [playersearch] [adminsearch] ORDER BY bantime DESC[limit]")
if(!query_search_bans.warn_execute())
return
@@ -498,4 +502,4 @@
output += "</table></div>"
usr << browse(output,"window=lookupbans;size=900x500")
usr << browse(output,"window=lookupbans;size=900x500")
+1
View File
@@ -24,6 +24,7 @@ GLOBAL_LIST_INIT(admin_verbs_default, AVerbsDefault())
/client/proc/cmd_admin_pm_context, /*right-click adminPM interface*/
/client/proc/cmd_admin_pm_panel, /*admin-pm list*/
// /client/proc/mentor_memo, /*mentor memo system. show/delete/write. +SERVER needed to delete mentor memos of others*/
/client/proc/cmd_admin_ticket_panel,
/client/proc/stop_sounds
)
GLOBAL_PROTECT(admin_verbs_admin)
+5 -2
View File
@@ -49,7 +49,10 @@
return
if(logged)
log_admin_private("[key_name(usr)] has created a [type][(type == "note" || type == "message" || type == "watchlist entry") ? " for [target_ckey]" : ""]: [text]")
message_admins("[key_name_admin(usr)] has created a [type][(type == "note" || type == "message" || type == "watchlist entry") ? " for [target_ckey]" : ""]:<br>[text]")
var/header = "[key_name_admin(usr)] has created a [type][(type == "note" || type == "message" || type == "watchlist entry") ? " for [target_ckey]" : ""]"
message_admins("[header]:<br>[text]")
admin_ticket_log(target_ckey, "<font color='blue'>[header]</font>")
admin_ticket_log(target_ckey, text)
if(browse)
browse_messages("[type]")
else
@@ -357,4 +360,4 @@ this proc can take several minutes to execute fully if converting and cause DD t
to_chat(world, "Deleting NOTESFILE")
fdel(NOTESFILE)
to_chat(world, "Finished mass note conversion, remember to turn off AUTOCONVERT_NOTES")*/
#undef NOTESFILE
#undef NOTESFILE
+21 -55
View File
@@ -5,60 +5,19 @@
message_admins("[usr.key] has attempted to override the admin panel!")
log_admin("[key_name(usr)] tried to use the admin panel without authorization.")
return
if(href_list["rejectadminhelp"])
if(world.time && (spamcooldown > world.time))
to_chat(usr, "Please wait [max(round((spamcooldown - world.time)*0.1, 0.1), 0)] seconds.")
return
if(href_list["ahelp"])
if(!check_rights(R_ADMIN))
return
var/client/C = locate(href_list["rejectadminhelp"]) in GLOB.clients
if(!C)
return
if (deltimer(C.adminhelptimerid))
C.giveadminhelpverb()
C << 'sound/effects/adminhelp.ogg'
var/ahelp_ref = href_list["ahelp"]
var/datum/admin_help/AH = locate(ahelp_ref)
if(AH)
AH.Action(href_list["ahelp_action"])
else
to_chat(usr, "Ticket [ahelp_ref] has been deleted!")
to_chat(C, "<font color='red' size='4'><b>- AdminHelp Rejected! -</b></font>")
to_chat(C, "<font color='red'><b>Your admin help was rejected.</b> The adminhelp verb has been returned to you so that you may try again.</font>")
to_chat(C, "Please try to be calm, clear, and descriptive in admin helps, do not assume the admin has seen any related events, and clearly state the names of anybody you are reporting.")
message_admins("[key_name_admin(usr)] Rejected [C.key]'s admin help. [C.key]'s Adminhelp verb has been returned to them.")
log_admin_private("[key_name(usr)] Rejected [C.key]'s admin help.")
spamcooldown = world.time + 150 // 15 seconds
else if(href_list["icissue"])
if(world.time && spamcooldown > world.time)
to_chat(usr, "Please wait [max(round((spamcooldown - world.time)*0.1, 0.1), 0)] seconds.")
return
var/client/C = locate(href_list["icissue"]) in GLOB.clients
if(!C)
return
var/msg = "<font color='red' size='4'><b>- AdminHelp marked as IC issue! -</b></font><br>"
msg += "<font color='red'><b>Losing is part of the game!</b></font><br>"
msg += "<font color='red'>Your character will frequently die, sometimes without even a possibility of avoiding it. Events will often be out of your control. No matter how good or prepared you are, sometimes you just lose.</font>"
to_chat(C, msg)
message_admins("[key_name_admin(usr)] marked [C.key]'s admin help as an IC issue.")
log_admin_private("[key_name(usr)] marked [C.key]'s admin help as an IC issue.")
spamcooldown = world.time + 150 // 15 seconds
else if(href_list["markedread"])
if(world.time && spamcooldown > world.time)
to_chat(usr, "Please wait [max(round((spamcooldown - world.time)*0.1, 0.1), 0)] seconds.")
return
var/client/C = locate(href_list["markedread"]) in GLOB.clients
if(!C)
return
var/msg = "<font color='green' size='2'><b>Your Adminhelp has been marked as read and is under investigation.</b></font>"
to_chat(C, msg)
message_admins("[key_name_admin(usr)] marked [C.key]'s admin help as read and under investigation.")
log_admin_private("[key_name(usr)] marked [C.key]'s admin help as read and under investigation.")
spamcooldown = world.time + 150 // 15 seconds
else if(href_list["ahelp_tickets"])
GLOB.ahelp_tickets.BrowseTickets(text2num(href_list["ahelp_tickets"]))
else if(href_list["stickyban"])
stickyban(href_list["stickyban"],href_list)
@@ -1124,7 +1083,7 @@
else if(href_list["messageedits"])
var/message_id = sanitizeSQL("[href_list["messageedits"]]")
var/datum/DBQuery/query_get_message_edits = SSdbcore.NewQuery("SELECT edits FROM [format_table_name("messages")] WHERE id = '[message_id]'")
var/datum/DBQuery/query_get_message_edits = SSdbcore.NewQuery("SELECT edits FROM [format_table_name("messages")] WHERE id = '[message_id]'")
if(!query_get_message_edits.warn_execute())
return
if(query_get_message_edits.NextRow())
@@ -1164,8 +1123,11 @@
else
to_chat(M, "<span class='danger'>No ban appeals URL has been set.</span>")
log_admin_private("[key_name(usr)] has banned [M.ckey].\nReason: [key_name(M)]\nThis will be removed in [mins] minutes.")
message_admins("<span class='adminnotice'>[key_name_admin(usr)] has banned [key_name_admin(M)].\nReason: [reason]\nThis will be removed in [mins] minutes.</span>")
var/msg = "<span class='adminnotice'>[key_name_admin(usr)] has banned [key_name_admin(M)].\nReason: [reason]\nThis will be removed in [mins] minutes.</span>"
message_admins(msg)
var/datum/admin_help/AH = M.client ? M.client.current_ticket : null
if(AH)
AH.Resolve()
qdel(M.client)
if("No")
var/reason = input(usr,"Please State Reason.","Reason") as message|null
@@ -1189,7 +1151,11 @@
return
ban_unban_log_save("[key_name(usr)] has permabanned [key_name(M)]. - Reason: [reason] - This is a permanent ban.")
log_admin_private("[key_name(usr)] has banned [key_name_admin(M)].\nReason: [reason]\nThis is a permanent ban.")
message_admins("<span class='adminnotice'>[key_name_admin(usr)] has banned [key_name_admin(M)].\nReason: [reason]\nThis is a permanent ban.</span>")
var/msg = "<span class='adminnotice'>[key_name_admin(usr)] has banned [key_name_admin(M)].\nReason: [reason]\nThis is a permanent ban.</span>"
message_admins(msg)
var/datum/admin_help/AH = M.client ? M.client.current_ticket : null
if(AH)
AH.Resolve()
feedback_inc("ban_perma",1)
qdel(M.client)
if("Cancel")
@@ -2276,4 +2242,4 @@
if(href_list["viewruntime_backto"])
error_viewer.show_to(owner, locate(href_list["viewruntime_backto"]), href_list["viewruntime_linear"])
else
error_viewer.show_to(owner, null, href_list["viewruntime_linear"])
error_viewer.show_to(owner, null, href_list["viewruntime_linear"])
+600 -125
View File
@@ -1,3 +1,602 @@
/client/var/adminhelptimerid = 0 //a timer id for returning the ahelp verb
/client/var/datum/admin_help/current_ticket //the current ticket the (usually) not-admin client is dealing with
//
//TICKET MANAGER
//
GLOBAL_DATUM_INIT(ahelp_tickets, /datum/admin_help_tickets, new)
/datum/admin_help_tickets
var/list/active_tickets = list()
var/list/closed_tickets = list()
var/list/resolved_tickets = list()
var/obj/effect/statclick/ticket_list/astatclick = new(null, null, AHELP_ACTIVE)
var/obj/effect/statclick/ticket_list/cstatclick = new(null, null, AHELP_CLOSED)
var/obj/effect/statclick/ticket_list/rstatclick = new(null, null, AHELP_RESOLVED)
/datum/admin_help_tickets/Destroy()
QDEL_LIST(active_tickets)
QDEL_LIST(closed_tickets)
QDEL_LIST(resolved_tickets)
QDEL_NULL(astatclick)
QDEL_NULL(cstatclick)
QDEL_NULL(rstatclick)
return ..()
//private
/datum/admin_help_tickets/proc/ListInsert(datum/admin_help/new_ticket)
var/list/ticket_list
switch(new_ticket.state)
if(AHELP_ACTIVE)
ticket_list = active_tickets
if(AHELP_CLOSED)
ticket_list = closed_tickets
if(AHELP_RESOLVED)
ticket_list = resolved_tickets
else
CRASH("Invalid ticket state: [new_ticket.state]")
var/num_closed = ticket_list.len
if(num_closed)
for(var/I in 1 to num_closed)
var/datum/admin_help/AH = ticket_list[I]
if(AH.id > new_ticket.id)
ticket_list.Insert(I, new_ticket)
return
ticket_list += new_ticket
//opens the ticket listings for one of the 3 states
/datum/admin_help_tickets/proc/BrowseTickets(state)
var/list/l2b
var/title
switch(state)
if(AHELP_ACTIVE)
l2b = active_tickets
title = "Active Tickets"
if(AHELP_CLOSED)
l2b = closed_tickets
title = "Closed Tickets"
if(AHELP_RESOLVED)
l2b = resolved_tickets
title = "Resolved Tickets"
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>"
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>"
usr << browse(dat.Join(), "window=ahelp_list[state];size=600x480")
//Tickets statpanel
/datum/admin_help_tickets/proc/stat_entry()
var/num_disconnected = 0
stat("Active Tickets:", astatclick.update("[active_tickets.len]"))
for(var/I in active_tickets)
var/datum/admin_help/AH = I
if(AH.initiator)
stat("#[AH.id]. [AH.initiator_key_name]:", AH.statclick.update())
else
++num_disconnected
if(num_disconnected)
stat("Disconnected:", astatclick.update("[num_disconnected]"))
stat("Closed Tickets:", cstatclick.update("[closed_tickets.len]"))
stat("Resolved Tickets:", rstatclick.update("[resolved_tickets.len]"))
//Reassociate still open ticket if one exists
/datum/admin_help_tickets/proc/ClientLogin(client/C)
C.current_ticket = CKey2ActiveTicket(C.ckey)
if(C.current_ticket)
C.current_ticket.AddInteraction("Client reconnected.")
//Dissasociate ticket
/datum/admin_help_tickets/proc/ClientLogout(client/C)
if(C.current_ticket)
C.current_ticket.AddInteraction("Client disconnected.")
C.current_ticket.initiator = null
C.current_ticket = null
//Get a ticket given a ckey
/datum/admin_help_tickets/proc/CKey2ActiveTicket(ckey)
for(var/I in active_tickets)
var/datum/admin_help/AH = I
if(AH.initiator_ckey == ckey)
return AH
//
//TICKET LIST STATCLICK
//
/obj/effect/statclick/ticket_list
var/current_state
/obj/effect/statclick/ticket_list/New(loc, name, state)
current_state = state
..()
/obj/effect/statclick/ticket_list/Click()
GLOB.ahelp_tickets.BrowseTickets(current_state)
//
//TICKET DATUM
//
/datum/admin_help
var/id
var/name
var/state = AHELP_ACTIVE
var/opened_at
var/closed_at
var/client/initiator //semi-misnomer, it's the person who ahelped/was bwoinked
var/initiator_ckey
var/initiator_key_name
var/list/_interactions //use AddInteraction() or, preferably, admin_ticket_log()
var/obj/effect/statclick/ahelp/statclick
var/static/ticket_counter = 0
//call this on its own to create a ticket, don't manually assign current_ticket
//msg is the title of the ticket: usually the ahelp text
//is_bwoink is TRUE if this ticket was started by an admin PM
/datum/admin_help/New(msg, client/C, is_bwoink)
//clean the input msg
msg = sanitize(copytext(msg,1,MAX_MESSAGE_LEN))
if(!msg || !C || !C.mob)
qdel(src)
return
id = ++ticket_counter
opened_at = world.time
name = msg
initiator = C
initiator_ckey = initiator.ckey
initiator_key_name = key_name(initiator, FALSE, TRUE)
if(initiator.current_ticket) //This is a bug
stack_trace("Multiple ahelp current_tickets")
initiator.current_ticket.AddInteraction("Ticket erroneously left open by code")
initiator.current_ticket.Close()
initiator.current_ticket = src
TimeoutVerb()
var/parsed_message = keywords_lookup(msg)
statclick = new(null, src)
_interactions = list()
if(is_bwoink)
AddInteraction("<font color='blue'>[key_name_admin(usr)] PM'd [LinkedReplyName()]</font>")
message_admins("<font color='blue'>Ticket [TicketHref("#[id]")] created</font>")
else
MessageNoRecipient(parsed_message)
//show it to the person adminhelping too
to_chat(C, "<span class='adminnotice'>PM to-<b>Admins</b>: [name]</span>")
//send it to irc if nobody is on and tell us how many were on
var/admin_number_present = send2irc_adminless_only(initiator_ckey, name)
log_admin_private("Ticket #[id]: [key_name(initiator)]: [name] - heard by [admin_number_present] non-AFK admins who have +BAN.")
if(admin_number_present <= 0)
to_chat(C, "<span class='notice'>No active admins are online, your adminhelp was sent to the admin irc.</span>")
GLOB.ahelp_tickets.active_tickets += src
/datum/admin_help/Destroy()
RemoveActive()
GLOB.ahelp_tickets.closed_tickets -= src
GLOB.ahelp_tickets.resolved_tickets -= src
return ..()
/datum/admin_help/proc/AddInteraction(formatted_message)
_interactions += "[gameTimestamp()]: [formatted_message]"
//Removes the ahelp verb and returns it after 2 minutes
/datum/admin_help/proc/TimeoutVerb()
initiator.verbs -= /client/verb/adminhelp
initiator.adminhelptimerid = addtimer(CALLBACK(initiator, /client/proc/giveadminhelpverb), 1200, TIMER_STOPPABLE) //2 minute cooldown of admin helps
//private
/datum/admin_help/proc/FullMonty(ref_src)
if(!ref_src)
ref_src = "\ref[src]"
. = ADMIN_FULLMONTY_NONAME(initiator.mob)
if(state == AHELP_ACTIVE)
. += ClosureLinks(ref_src)
//private
/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>)"
//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>"
//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>"
//message from the initiator without a target, all admins will see this
//won't bug irc
/datum/admin_help/proc/MessageNoRecipient(msg)
var/ref_src = "\ref[src]"
var/chat_msg = "<span class='adminnotice'><span class='adminhelp'>Ticket [TicketHref("#[id]", ref_src)]</span><b>: [LinkedReplyName(ref_src)] [FullMonty(ref_src)]:</b> [msg]</span>"
AddInteraction("<font color='red'>[LinkedReplyName(ref_src)]: [msg]</font>")
//send this msg to all admins
for(var/client/X in GLOB.admins)
if(X.prefs.toggles & SOUND_ADMINHELP)
X << 'sound/effects/adminhelp.ogg'
window_flash(X, ignorepref = TRUE)
to_chat(X, chat_msg)
//Reopen a closed ticket
/datum/admin_help/proc/Reopen()
if(state == AHELP_ACTIVE)
to_chat(usr, "<span class='warning'>This ticket is already open.</span>")
return
if(GLOB.ahelp_tickets.CKey2ActiveTicket(initiator_ckey))
to_chat(usr, "<span class='warning'>This user already has an active ticket, cannot reopen this one.</span>")
return
statclick = new(null, src)
GLOB.ahelp_tickets.active_tickets += src
GLOB.ahelp_tickets.closed_tickets -= src
GLOB.ahelp_tickets.resolved_tickets -= src
switch(state)
if(AHELP_CLOSED)
feedback_dec("ahelp_close")
if(AHELP_RESOLVED)
feedback_dec("ahelp_resolve")
state = AHELP_ACTIVE
closed_at = null
if(initiator)
initiator.current_ticket = src
AddInteraction("<font color='purple'>Reopened by [key_name_admin(usr)]</font>")
var/msg = "<span class='adminhelp'>Ticket [TicketHref("#[id]")] reopened by [key_name_admin(usr)].</span>"
message_admins(msg)
log_admin_private(msg)
feedback_inc("ahelp_reopen")
TicketPanel() //can only be done from here, so refresh it
//private
/datum/admin_help/proc/RemoveActive()
if(state != AHELP_ACTIVE)
return
closed_at = world.time
QDEL_NULL(statclick)
GLOB.ahelp_tickets.active_tickets -= src
if(initiator && initiator.current_ticket == src)
initiator.current_ticket = null
//Mark open ticket as closed/meme
/datum/admin_help/proc/Close(key_name = key_name_admin(usr), silent = FALSE)
if(state != AHELP_ACTIVE)
return
RemoveActive()
state = AHELP_CLOSED
GLOB.ahelp_tickets.ListInsert(src)
AddInteraction("<font color='red'>Closed by [key_name].</font>")
if(!silent)
feedback_inc("ahelp_close")
var/msg = "Ticket [TicketHref("#[id]")] closed by [key_name]."
message_admins(msg)
log_admin_private(msg)
//Mark open ticket as resolved/legitimate, returns ahelp verb
/datum/admin_help/proc/Resolve(key_name = key_name_admin(usr), silent = FALSE)
if(state != AHELP_ACTIVE)
return
RemoveActive()
state = AHELP_RESOLVED
GLOB.ahelp_tickets.ListInsert(src)
if(initiator)
initiator.giveadminhelpverb()
AddInteraction("<font color='green'>Resolved by [key_name].</font>")
if(!silent)
feedback_inc("ahelp_resolve")
var/msg = "Ticket [TicketHref("#[id]")] resolved by [key_name]"
message_admins(msg)
log_admin_private(msg)
//Close and return ahelp verb, use if ticket is incoherent
/datum/admin_help/proc/Reject(key_name = key_name_admin(usr))
if(state != AHELP_ACTIVE)
return
if(initiator)
initiator.giveadminhelpverb()
initiator << 'sound/effects/adminhelp.ogg'
to_chat(initiator, "<font color='red' size='4'><b>- AdminHelp Rejected! -</b></font>")
to_chat(initiator, "<font color='red'><b>Your admin help was rejected.</b> The adminhelp verb has been returned to you so that you may try again.</font>")
to_chat(initiator, "Please try to be calm, clear, and descriptive in admin helps, do not assume the admin has seen any related events, and clearly state the names of anybody you are reporting.")
feedback_inc("ahelp_reject")
var/msg = "Ticket [TicketHref("#[id]")] rejected by [key_name]"
message_admins(msg)
log_admin_private(msg)
AddInteraction("Rejected by [key_name].")
Close(silent = TRUE)
//Resolve ticket with IC Issue message
/datum/admin_help/proc/ICIssue(key_name = key_name_admin(usr))
if(state != AHELP_ACTIVE)
return
var/msg = "<font color='red' size='4'><b>- AdminHelp marked as IC issue! -</b></font><br>"
msg += "<font color='red'><b>Losing is part of the game!</b></font><br>"
msg += "<font color='red'>Your character will frequently die, sometimes without even a possibility of avoiding it. Events will often be out of your control. No matter how good or prepared you are, sometimes you just lose.</font>"
if(initiator)
to_chat(initiator, msg)
feedback_inc("ahelp_icissue")
msg = "Ticket [TicketHref("#[id]")] marked as IC by [key_name]"
message_admins(msg)
log_admin_private(msg)
AddInteraction("Marked as IC issue by [key_name]")
Resolve(silent = TRUE)
//Show the ticket panel
/datum/admin_help/proc/TicketPanel()
var/list/dat = list("<html><head><title>Ticket #[id]</title></head>")
var/ref_src = "\ref[src]"
dat += "<h4>Admin Help Ticket #[id]: [LinkedReplyName(ref_src)]</h4>"
dat += "<b>State: "
switch(state)
if(AHELP_ACTIVE)
dat += "<font color='red'>OPEN</font>"
if(AHELP_RESOLVED)
dat += "<font color='green'>RESOLVED</font>"
if(AHELP_CLOSED)
dat += "CLOSED"
else
dat += "UNKNOWN"
dat += "</b>[GLOB.TAB][TicketHref("Refresh", ref_src)][GLOB.TAB][TicketHref("Re-Title", ref_src, "retitle")]"
if(state != AHELP_ACTIVE)
dat += "[GLOB.TAB][TicketHref("Reopen", ref_src, "reopen")]"
dat += "<br><br>Opened at: [gameTimestamp(wtime = opened_at)] (Approx [(world.time - opened_at) / 600] minutes ago)"
if(closed_at)
dat += "<br>Closed at: [gameTimestamp(wtime = closed_at)] (Approx [(world.time - closed_at) / 600] minutes ago)"
dat += "<br><br>"
if(initiator)
dat += "<b>Actions:</b> [FullMonty(ref_src)]<br>"
else
dat += "<b>DISCONNECTED</b>[GLOB.TAB][ClosureLinks(ref_src)]<br>"
dat += "<br><b>Log:</b><br><br>"
for(var/I in _interactions)
dat += "[I]<br>"
usr << browse(dat.Join(), "window=ahelp[id];size=620x480")
/datum/admin_help/proc/Retitle()
var/new_title = input(usr, "Enter a title for the ticket", "Rename Ticket", name) as text|null
if(new_title)
name = new_title
//not saying the original name cause it could be a long ass message
var/msg = "Ticket [TicketHref("#[id]")] titled [name] by [key_name_admin(usr)]"
message_admins(msg)
log_admin_private(msg)
TicketPanel() //we have to be here to do this
//Forwarded action from admin/Topic
/datum/admin_help/proc/Action(action)
testing("Ahelp action: [action]")
switch(action)
if("ticket")
TicketPanel()
if("retitle")
Retitle()
if("reject")
Reject()
if("reply")
usr.client.cmd_ahelp_reply(initiator)
if("icissue")
ICIssue()
if("close")
Close()
if("resolve")
Resolve()
if("reopen")
Reopen()
//
// TICKET STATCLICK
//
/obj/effect/statclick/ahelp
var/datum/admin_help/ahelp_datum
/obj/effect/statclick/ahelp/New(loc, datum/admin_help/AH)
ahelp_datum = AH
..(loc)
/obj/effect/statclick/ahelp/update()
return ..(ahelp_datum.name)
/obj/effect/statclick/ahelp/Click()
ahelp_datum.TicketPanel()
/obj/effect/statclick/ahelp/Destroy()
ahelp_datum = null
return ..()
//
// CLIENT PROCS
//
/client/proc/giveadminhelpverb()
src.verbs |= /client/verb/adminhelp
deltimer(adminhelptimerid)
adminhelptimerid = 0
/client/verb/adminhelp(msg as text)
set category = "Admin"
set name = "Adminhelp"
if(GLOB.say_disabled) //This is here to try to identify lag problems
to_chat(usr, "<span class='danger'>Speech is currently admin-disabled.</span>")
return
//handle muting and automuting
if(prefs.muted & MUTE_ADMINHELP)
to_chat(src, "<span class='danger'>Error: Admin-PM: You cannot send adminhelps (Muted).</span>")
return
if(handle_spam_prevention(msg,MUTE_ADMINHELP))
return
if(!msg)
return
feedback_add_details("admin_verb","Adminhelp") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
if(current_ticket)
if(alert(usr, "You already have a ticket open. Is this for the same issue?",,"Yes","No") != "No")
if(current_ticket)
current_ticket.MessageNoRecipient(msg)
current_ticket.TimeoutVerb()
return
else
to_chat(usr, "<span class='warning'>Ticket not found, creating new one...</span>")
else
current_ticket.AddInteraction("[key_name_admin(usr)] opened a new ticket.")
current_ticket.Close()
new /datum/admin_help(msg, src, FALSE)
//admin proc
/client/proc/cmd_admin_ticket_panel()
set name = "Show Ticket List"
set category = "Admin"
if(!check_rights(R_ADMIN, TRUE))
return
var/browse_to
switch(input("Display which ticket list?") as null|anything in list("Active Tickets", "Closed Tickets", "Resolved Tickets"))
if("Active Tickets")
browse_to = AHELP_ACTIVE
if("Closed Tickets")
browse_to = AHELP_CLOSED
if("Resolved Tickets")
browse_to = AHELP_RESOLVED
else
return
GLOB.ahelp_tickets.BrowseTickets(browse_to)
//
// LOGGING
//
//Use this proc when an admin takes action that may be related to an open ticket on what
//what can be a client, ckey, or mob
/proc/admin_ticket_log(what, message)
var/client/C
var/mob/Mob = what
if(istype(Mob))
C = Mob.client
else
C = what
if(istype(C) && C.current_ticket)
C.current_ticket.AddInteraction(message)
return C.current_ticket
if(istext(what)) //ckey
var/datum/admin_help/AH = GLOB.ahelp_tickets.CKey2ActiveTicket(what)
if(AH)
AH.AddInteraction(message)
return AH
//
// HELPER PROCS
//
/proc/get_admin_counts(requiredflags = R_BAN)
. = list("total" = list(), "noflags" = list(), "afk" = list(), "stealth" = list(), "present" = list())
for(var/client/X in GLOB.admins)
.["total"] += X
if(requiredflags != 0 && !check_rights_for(X, requiredflags))
.["noflags"] += X
else if(X.is_afk())
.["afk"] += X
else if(X.holder.fakekey)
.["stealth"] += X
else
.["present"] += X
/proc/send2irc_adminless_only(source, msg, requiredflags = R_BAN)
var/list/adm = get_admin_counts(requiredflags)
var/list/activemins = adm["present"]
. = activemins.len
if(. <= 0)
var/final = ""
var/list/afkmins = adm["afk"]
var/list/stealthmins = adm["stealth"]
var/list/powerlessmins = adm["noflags"]
var/list/allmins = adm["total"]
if(!afkmins.len && !stealthmins.len && !powerlessmins.len)
final = "[msg] - No admins online"
else
final = "[msg] - All admins stealthed\[[english_list(stealthmins)]\], AFK\[[english_list(afkmins)]\], or lacks +BAN\[[english_list(powerlessmins)]\]! Total: [allmins.len] "
send2irc(source,final)
send2otherserver(source,final)
/proc/send2irc(msg,msg2)
if(config.useircbot)
shell("python nudge.py [msg] [msg2]")
return
/proc/send2otherserver(source,msg,type = "Ahelp")
if(config.cross_allowed)
var/list/message = list()
message["message_sender"] = source
message["message"] = msg
message["source"] = "([config.cross_name])"
message["key"] = global.comms_key
message["crossmessage"] = type
world.Export("[config.cross_address]?[list2params(message)]")
/proc/ircadminwho()
var/list/message = list("Admins: ")
var/list/admin_keys = list()
for(var/adm in GLOB.admins)
var/client/C = adm
admin_keys += "[C][C.holder.fakekey ? "(Stealth)" : ""][C.is_afk() ? "(AFK)" : ""]"
for(var/admin in admin_keys)
if(LAZYLEN(admin_keys) > 1)
message += ", [admin]"
else
message += "[admin]"
return jointext(message, "")
/proc/keywords_lookup(msg,irc)
//This is a list of words which are ignored by the parser when comparing message contents for names. MUST BE IN LOWER CASE!
@@ -67,128 +666,4 @@
else
return founds
return msg
/client/var/adminhelptimerid = 0
/client/proc/giveadminhelpverb()
src.verbs |= /client/verb/adminhelp
adminhelptimerid = 0
/client/verb/adminhelp(msg as text)
set category = "Admin"
set name = "Adminhelp"
if(GLOB.say_disabled) //This is here to try to identify lag problems
to_chat(usr, "<span class='danger'>Speech is currently admin-disabled.</span>")
return
//handle muting and automuting
if(prefs.muted & MUTE_ADMINHELP)
to_chat(src, "<span class='danger'>Error: Admin-PM: You cannot send adminhelps (Muted).</span>")
return
if(src.handle_spam_prevention(msg,MUTE_ADMINHELP))
return
//clean the input msg
if(!msg)
return
msg = sanitize(copytext(msg,1,MAX_MESSAGE_LEN))
if(!msg) return
var/original_msg = msg
//remove our adminhelp verb temporarily to prevent spamming of admins.
src.verbs -= /client/verb/adminhelp
adminhelptimerid = addtimer(CALLBACK(src, .proc/giveadminhelpverb), 1200, TIMER_STOPPABLE) //2 minute cooldown of admin helps
msg = keywords_lookup(msg)
if(!mob)
return //this doesn't happen
var/ref_client = "\ref[src]"
msg = "<span class='adminnotice'><b><font color=red>HELP: </font><A HREF='?priv_msg=[ckey];ahelp_reply=1'>[key_name(src)]</A> [ADMIN_FULLMONTY_NONAME(mob)] [ADMIN_SMITE(mob)] (<A HREF='?_src_=holder;rejectadminhelp=[ref_client]'>REJT</A>) (<A HREF='?_src_=holder;icissue=[ref_client]'>IC</A>):</b> [msg]</span>"
//send this msg to all admins
for(var/client/X in GLOB.admins)
if(X.prefs.toggles & SOUND_ADMINHELP)
X << 'sound/effects/adminhelp.ogg'
window_flash(X, ignorepref = TRUE)
to_chat(X, msg)
//show it to the person adminhelping too
to_chat(src, "<span class='adminnotice'>PM to-<b>Admins</b>: [original_msg]</span>")
//send it to irc if nobody is on and tell us how many were on
var/admin_number_present = send2irc_adminless_only(ckey,original_msg)
log_admin_private("HELP: [key_name(src)]: [original_msg] - heard by [admin_number_present] non-AFK admins who have +BAN.")
if(admin_number_present <= 0)
to_chat(src, "<span class='notice'>No active admins are online, your adminhelp was sent to the admin irc.</span>")
feedback_add_details("admin_verb","Adminhelp") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
return
/proc/get_admin_counts(requiredflags = R_BAN)
. = list("total" = list(), "noflags" = list(), "afk" = list(), "stealth" = list(), "present" = list())
for(var/client/X in GLOB.admins)
.["total"] += X
if(requiredflags != 0 && !check_rights_for(X, requiredflags))
.["noflags"] += X
else if(X.is_afk())
.["afk"] += X
else if(X.holder.fakekey)
.["stealth"] += X
else
.["present"] += X
/proc/send2irc_adminless_only(source, msg, requiredflags = R_BAN)
var/list/adm = get_admin_counts(requiredflags)
var/list/activemins = adm["present"]
. = activemins.len
if(. <= 0)
var/final = ""
var/list/afkmins = adm["afk"]
var/list/stealthmins = adm["stealth"]
var/list/powerlessmins = adm["noflags"]
var/list/allmins = adm["total"]
if(!afkmins.len && !stealthmins.len && !powerlessmins.len)
final = "[msg] - No admins online"
else
final = "[msg] - All admins stealthed\[[english_list(stealthmins)]\], AFK\[[english_list(afkmins)]\], or lacks +BAN\[[english_list(powerlessmins)]\]! Total: [allmins.len] "
send2irc(source,final)
send2otherserver(source,final)
/proc/send2irc(msg,msg2)
if(config.useircbot)
shell("python nudge.py [msg] [msg2]")
return
/proc/send2otherserver(source,msg,type = "Ahelp")
if(config.cross_allowed)
var/list/message = list()
message["message_sender"] = source
message["message"] = msg
message["source"] = "([config.cross_name])"
message["key"] = global.comms_key
message["crossmessage"] = type
world.Export("[config.cross_address]?[list2params(message)]")
/proc/ircadminwho()
var/list/message = list("Admins: ")
var/list/admin_keys = list()
for(var/adm in GLOB.admins)
var/client/C = adm
admin_keys += "[C][C.holder.fakekey ? "(Stealth)" : ""][C.is_afk() ? "(AFK)" : ""]"
for(var/admin in admin_keys)
if(LAZYLEN(admin_keys) > 1)
message += ", [admin]"
else
message += "[admin]"
return jointext(message, "")
return msg
+15 -8
View File
@@ -104,9 +104,12 @@
to_chat(src, "Only administrators may use this command.")
return
log_admin("[key_name(usr)] teleported [key_name(M)]")
message_admins("[key_name_admin(usr)] teleported [key_name_admin(M)]")
M.forceMove(get_turf(usr))
var/atom/loc = get_turf(usr)
log_admin("[key_name(usr)] teleported [key_name(M)] to [COORD(loc)]")
var/msg = "[key_name_admin(usr)] teleported [key_name_admin(M)] to [ADMIN_COORDJMP(loc)]"
message_admins(msg)
admin_ticket_log(M, msg)
M.forceMove(loc)
feedback_add_details("admin_verb","Get Mob") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
/client/proc/Getkey()
@@ -121,15 +124,17 @@
var/list/keys = list()
for(var/mob/M in GLOB.player_list)
keys += M.client
var/client/selection = input("Please, select a player!", "Admin Jumping", null, null) as null|anything in sortKey(keys)
var/selection = input("Please, select a player!", "Admin Jumping", null, null) as null|anything in sortKey(keys)
if(!selection)
return
var/mob/M = selection.mob
var/mob/M = selection:mob
if(!M)
return
log_admin("[key_name(usr)] teleported [key_name(M)]")
message_admins("[key_name_admin(usr)] teleported [key_name(M)]")
var/msg = "[key_name_admin(usr)] teleported [key_name_admin(M)]"
message_admins(msg)
admin_ticket_log(M, msg)
if(M)
M.forceMove(get_turf(usr))
usr.loc = M.loc
@@ -146,7 +151,9 @@
if(M.forceMove(safepick(get_area_turfs(A))))
log_admin("[key_name(usr)] teleported [key_name(M)] to [A]")
message_admins("[key_name_admin(usr)] teleported [key_name_admin(M)] to [A]")
var/msg = "[key_name_admin(usr)] teleported [key_name_admin(M)] to [A]"
message_admins(msg)
admin_ticket_log(M, msg)
else
to_chat(src, "Failed to move mob to a valid location.")
feedback_add_details("admin_verb","Send Mob") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
feedback_add_details("admin_verb","Send Mob") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
+88 -36
View File
@@ -50,22 +50,30 @@
if(holder)
to_chat(src, "<font color='red'>Error: Admin-PM: Client not found.</font>")
return
message_admins("[key_name_admin(src)] has started replying to [key_name(C, 0, 0)]'s admin help.")
var/list/replace_chars = list("\n"=" ","\t"=" ")
var/msg = copytext(sanitize((input(src,"Message:", "Private message to [key_name(C, 0, 0)]") as message|null), replace_chars), 1, MAX_MESSAGE_LEN)
if (!msg|| msg == " ")//if they hit enter and didn't hit cancel, don't send it
var/datum/admin_help/AH = C.current_ticket
if(AH)
message_admins("[key_name_admin(src)] has started replying to [key_name(C, 0, 0)]'s admin help.")
var/msg = input(src,"Message:", "Private message to [key_name(C, 0, 0)]") as text|null
if (!msg)
message_admins("[key_name_admin(src)] has cancelled their reply to [key_name(C, 0, 0)]'s admin help.")
return
cmd_admin_pm(whom, msg)
cmd_admin_pm(whom, msg, AH)
//takes input from cmd_admin_pm_context, cmd_admin_pm_panel or /client/Topic and sends them a PM.
//Fetching a message if needed. src is the sender and C is the target client
/client/proc/cmd_admin_pm(whom, msg)
/client/proc/cmd_admin_pm(whom, msg, datum/admin_help/AH)
if(prefs.muted & MUTE_ADMINHELP)
to_chat(src, "<font color='red'>Error: Admin-PM: You are unable to use admin PM-s (muted).</font>")
return
var/client/C
if(!holder && !current_ticket) //no ticket? https://www.youtube.com/watch?v=iHSPf6x1Fdo
to_chat(src, "<font color='red'>You can no longer reply to this ticket, please open another one by using the Adminhelp verb if need be.</font>")
to_chat(src, "<font color='blue'>Message: [msg]</font>")
return
var/client/recipient
var/irc = 0
if(istext(whom))
if(cmptext(copytext(whom,1,2),"@"))
@@ -73,14 +81,16 @@
if(whom == "IRCKEY")
irc = 1
else
C = GLOB.directory[whom]
recipient = GLOB.directory[whom]
else if(istype(whom,/client))
C = whom
recipient = whom
if(irc)
if(!ircreplyamount) //to prevent people from spamming irc
return
if(!msg)
msg = input(src,"Message:", "Private message to Administrator") as message|null
msg = input(src,"Message:", "Private message to Administrator") as text|null
if(!msg)
return
@@ -90,16 +100,16 @@
else
if(!C)
if(!recipient)
if(holder)
to_chat(src, "<font color='red'>Error: Admin-PM: Client not found.</font>")
else
adminhelp(msg) //admin we are replying to left. adminhelp instead
current_ticket.MessageNoRecipient(msg)
return
//get message text, limit it's length.and clean/escape html
if(!msg)
msg = input(src,"Message:", "Private message to [key_name(C, 0, 0)]") as message|null
msg = input(src,"Message:", "Private message to [key_name(recipient, 0, 0)]") as text|null
if(!msg)
return
@@ -108,11 +118,11 @@
to_chat(src, "<font color='red'>Error: Admin-PM: You are unable to use admin PM-s (muted).</font>")
return
if(!C)
if(!recipient)
if(holder)
to_chat(src, "<font color='red'>Error: Admin-PM: Client not found.</font>")
else
adminhelp(msg) //admin we are replying to has vanished, adminhelp instead
current_ticket.MessageNoRecipient(msg)
return
if (src.handle_spam_prevention(msg,MUTE_ADMINHELP))
@@ -133,41 +143,55 @@
if(irc)
to_chat(src, "<font color='blue'>PM to-<b>Admins</b>: [rawmsg]</font>")
admin_ticket_log(src, "<font color='red'>Reply PM from-<b>[key_name(src, TRUE, TRUE)] to <i>IRC</i>: [keywordparsedmsg]</font>")
ircreplyamount--
send2irc("Reply: [ckey]",rawmsg)
else
if(C.holder)
if(recipient.holder)
if(holder) //both are admins
to_chat(C, "<font color='red'>Admin PM from-<b>[key_name(src, C, 1)]</b>: [keywordparsedmsg]</font>")
to_chat(src, "<font color='blue'>Admin PM to-<b>[key_name(C, src, 1)]</b>: [keywordparsedmsg]</font>")
to_chat(recipient, "<font color='red'>Admin PM from-<b>[key_name(src, recipient, 1)]</b>: [keywordparsedmsg]</font>")
to_chat(src, "<font color='blue'>Admin PM to-<b>[key_name(recipient, src, 1)]</b>: [keywordparsedmsg]</font>")
//omg this is dumb, just fill in both their tickets
var/interaction_message = "<font color='purple'>PM from-<b>[key_name(src, recipient, 1)]</b> to-<b>[key_name(recipient, src, 1)]</b>: [keywordparsedmsg]</font>"
admin_ticket_log(src, interaction_message)
if(recipient != src) //reeee
admin_ticket_log(recipient, interaction_message)
else //recipient is an admin but sender is not
to_chat(C, "<font color='red'>Reply PM from-<b>[key_name(src, C, 1)]</b>: [keywordparsedmsg]</font>")
var/replymsg = "<font color='red'>Reply PM from-<b>[key_name(src, recipient, 1)]</b>: [keywordparsedmsg]</font>"
admin_ticket_log(src, replymsg)
to_chat(recipient, replymsg)
to_chat(src, "<font color='blue'>PM to-<b>Admins</b>: [msg]</font>")
//play the recieving admin the adminhelp sound (if they have them enabled)
if(C.prefs.toggles & SOUND_ADMINHELP)
C << 'sound/effects/adminhelp.ogg'
if(recipient.prefs.toggles & SOUND_ADMINHELP)
recipient << 'sound/effects/adminhelp.ogg'
else
if(holder) //sender is an admin but recipient is not. Do BIG RED TEXT
to_chat(C, "<font color='red' size='4'><b>-- Administrator private message --</b></font>")
to_chat(C, "<font color='red'>Admin PM from-<b>[key_name(src, C, 0)]</b>: [msg]</font>")
to_chat(C, "<font color='red'><i>Click on the administrator's name to reply.</i></font>")
to_chat(src, "<font color='blue'>Admin PM to-<b>[key_name(C, src, 1)]</b>: [msg]</font>")
if(!recipient.current_ticket)
new /datum/admin_help(msg, recipient, TRUE)
to_chat(recipient, "<font color='red' size='4'><b>-- Administrator private message --</b></font>")
to_chat(recipient, "<font color='red'>Admin PM from-<b>[key_name(src, recipient, 0)]</b>: [msg]</font>")
to_chat(recipient, "<font color='red'><i>Click on the administrator's name to reply.</i></font>")
to_chat(src, "<font color='blue'>Admin PM to-<b>[key_name(recipient, src, 1)]</b>: [msg]</font>")
admin_ticket_log(recipient, "<font color='blue'>PM From [key_name_admin(src)]: [keywordparsedmsg]</font>")
//always play non-admin recipients the adminhelp sound
C << 'sound/effects/adminhelp.ogg'
recipient << 'sound/effects/adminhelp.ogg'
//AdminPM popup for ApocStation and anybody else who wants to use it. Set it with POPUP_ADMIN_PM in config.txt ~Carn
if(config.popup_admin_pm)
spawn() //so we don't hold the caller proc up
var/sender = src
var/sendername = key
var/reply = input(C, msg,"Admin PM from-[sendername]", "") as message|null //show message and await a reply
if(C && reply)
var/reply = input(recipient, msg,"Admin PM from-[sendername]", "") as text|null //show message and await a reply
if(recipient && reply)
if(sender)
C.cmd_admin_pm(sender,reply) //sender is still about, let's reply to them
recipient.cmd_admin_pm(sender,reply) //sender is still about, let's reply to them
else
adminhelp(reply) //sender has left, adminhelp instead
return
@@ -181,22 +205,47 @@
for(var/client/X in GLOB.admins)
to_chat(X, "<B><font color='blue'>PM: [key_name(src, X, 0)]-&gt;IRC:</B> \blue [keywordparsedmsg]</font>" )
else
window_flash(C, ignorepref = TRUE)
log_admin_private("PM: [key_name(src)]->[key_name(C)]: [rawmsg]")
window_flash(recipient, ignorepref = TRUE)
log_admin_private("PM: [key_name(src)]->[key_name(recipient)]: [rawmsg]")
//we don't use message_admins here because the sender/receiver might get it too
for(var/client/X in GLOB.admins)
if(X.key!=key && X.key!=C.key) //check client/X is an admin and isn't the sender or recipient
to_chat(X, "<B><font color='blue'>PM: [key_name(src, X, 0)]-&gt;[key_name(C, X, 0)]:</B> \blue [keywordparsedmsg]</font>" )
if(X.key!=key && X.key!=recipient.key) //check client/X is an admin and isn't the sender or recipient
to_chat(X, "<B><font color='blue'>PM: [key_name(src, X, 0)]-&gt;[key_name(recipient, X, 0)]:</B> \blue [keywordparsedmsg]</font>" )
/proc/IrcPm(target,msg,sender)
var/client/C = GLOB.directory[target]
var/datum/admin_help/ticket = C ? C.current_ticket : GLOB.ahelp_tickets.CKey2ActiveTicket(target)
var/compliant_msg = trim(lowertext(msg))
var/unhandled = FALSE
var/irc_tagged = "[sender](IRC)"
switch(compliant_msg)
if("ticket close")
if(ticket)
ticket.Close(irc_tagged)
return "Ticket #[ticket.id] successfully closed"
if("ticket resolve")
if(ticket)
ticket.Resolve(irc_tagged)
return "Ticket #[ticket.id] successfully resolved"
if("ticket ic")
if(ticket)
ticket.ICIssue(irc_tagged)
return "Ticket #[ticket.id] successfully marked as IC issue"
if("ticket reject")
if(ticket)
ticket.Reject(irc_tagged)
return "Ticket #[ticket.id] successfully rejected"
else
unhandled = TRUE
if(!unhandled)
return "Ticket could not be found"
var/static/stealthkey
var/adminname = config.showircname ? "[sender](IRC)" : "Administrator"
var/adminname = config.showircname ? irc_tagged : "Administrator"
if(!C)
return "No client"
@@ -215,6 +264,9 @@
to_chat(C, "<font color='red' size='4'><b>-- Administrator private message --</b></font>")
to_chat(C, "<font color='red'>Admin PM from-<b><a href='?priv_msg=[stealthkey]'>[adminname]</A></b>: [msg]</font>")
to_chat(C, "<font color='red'><i>Click on the administrator's name to reply.</i></font>")
admin_ticket_log(C, "<font color='blue'>PM From [irc_tagged]: [msg]</font>")
window_flash(C, ignorepref = TRUE)
//always play non-admin recipients the adminhelp sound
C << 'sound/effects/adminhelp.ogg'
@@ -238,4 +290,4 @@
GLOB.stealthminID["IRCKEY"] = stealth
return stealth
#undef IRCREPLYCOUNT
#undef IRCREPLYCOUNT
+16 -11
View File
@@ -68,8 +68,10 @@ But you can call procs that are of type /mob/living/carbon/human/proc/ for that
if(!target)
to_chat(usr, "<font color='red'>Error: callproc(): owner of proc no longer exists.</font>")
return
log_admin("[key_name(src)] called [target]'s [procname]() with [lst.len ? "the arguments [list2params(lst)]":"no arguments"].")
message_admins("[key_name(src)] called [target]'s [procname]() with [lst.len ? "the arguments [list2params(lst)]":"no arguments"].")
var/msg = "[key_name(src)] called [target]'s [procname]() with [lst.len ? "the arguments [list2params(lst)]":"no arguments"]."
log_admin(msg)
message_admins(msg)
admin_ticket_log(target, msg)
returnval = WrapAdminProcCall(target, procname, lst) // Pass the lst as an argument list to the proc
else
//this currently has no hascall protection. wasn't able to get it working.
@@ -90,15 +92,16 @@ GLOBAL_PROTECT(AdminProcCall)
UNTIL(!GLOB.AdminProcCall)
to_chat(usr, "<span class='adminnotice'>Running your proc</span>")
GLOB.AdminProcCall = usr.client.ckey //if this runtimes, too bad for you
try
if(target == GLOBAL_PROC)
. = call(procname)(arglist(arguments))
else
. = call(procname)(arglist(arguments))
catch()
//intentionally left blank
world.WrapAdminProcCall(target, procname, arguments)
GLOB.AdminProcCall = null
//adv proc call this, ya nerds
/world/proc/WrapAdminProcCall(target, procname, list/arguments)
if(target == GLOBAL_PROC)
return call(procname)(arglist(arguments))
else
return call(procname)(arglist(arguments))
/proc/IsAdminAdvancedProcCall()
return usr && usr.client && GLOB.AdminProcCall == usr.client.ckey
@@ -124,7 +127,9 @@ GLOBAL_PROTECT(AdminProcCall)
to_chat(usr, "<span class='warning'>Error: callproc_datum(): owner of proc no longer exists.</span>")
return
log_admin("[key_name(src)] called [A]'s [procname]() with [lst.len ? "the arguments [list2params(lst)]":"no arguments"].")
message_admins("[key_name(src)] called [A]'s [procname]() with [lst.len ? "the arguments [list2params(lst)]":"no arguments"].")
var/msg = "[key_name(src)] called [A]'s [procname]() with [lst.len ? "the arguments [list2params(lst)]":"no arguments"]."
message_admins(msg)
admin_ticket_log(A, msg)
feedback_add_details("admin_verb","Atom ProcCall") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
var/returnval = WrapAdminProcCall(A, procname, lst) // Pass the lst as an argument list to the proc
@@ -803,4 +808,4 @@ GLOBAL_PROTECT(AdminProcCall)
message_admins("<span class='adminnotice'>[key_name_admin(src)] pumped a random event.</span>")
feedback_add_details("admin_verb","Pump Random Event")
log_admin("[key_name(src)] pumped a random event.")
log_admin("[key_name(src)] pumped a random event.")
-315
View File
@@ -1,315 +0,0 @@
/datum/adminticket
var/active = TICKET_INACTIVE //Is the adminhelp active, eg admin responded?
var/admin = TICKET_UNASSIGNED //The handling admin? Like come on.
var/id = "" //ID of the ticket, very important as its used to find adminhelps.
var/ticket_logs = list() //The logs of the adminhelp.
var/mob //The mob adminhelping mob.
var/msg = "" //The adminhelp message.
var/permckey = "" //The perm ckey, never removed essentially.
var/permuser = "" //Same as above!
var/replying = TICKET_UNREPLIED //Is someone responding to the adminhelp?
var/resolved = TICKET_UNRESOLVED //Is it resolved? Its much easier to have a "Yes" or a "No", as you can directly concat it into strings making life that much easier.
var/uckey //The saved ckey of the adminhelping user.
var/uID = "" //The UNIQUE id, made by putting part of the ckey and the ID together. Used internally in code.
var/user = "" //The user of the ahelp.
/client/proc/list_ahelps(user, resolved)
if(!check_rights(R_ADMIN))
src << "<font color='red'>Error: Only administrators may use this command.</font>"
return
for(var/I in admintickets)
var/datum/adminticket/T = I
if(resolved)
user << "Resolved Ahelps:"
usr << "<span class='adminnotice'><b><font color='red'>#[T.id] By:</font> <A HREF='?priv_msg=[T.permckey];ahelp_reply=1'>[key_name(T.permuser)]</A></b><b> Ckey:</b> [T.permckey] <b>Name:</b> [T.permuser] <b>Unique id:</b> [T.uID]</span>"
usr << " <b>Controls:</b> [ADMIN_QUE(mob)] [ADMIN_PP(mob)] [ADMIN_VV(mob)] [ADMIN_SM(mob)] [ADMIN_FLW(mob)] [ADMIN_TP(mob)]"
usr << " <b>Message:</b> [T.msg]"
usr << " <b>Handling Admin:</b> [T.admin]"
usr << " <b>Replied To:</b> [T.active]/<b><a href='?src=\ref[T];view_logs=\ref[T]'>(LOGS)</a></b>"
if(T.resolved == TICKET_UNRESOLVED)
usr << " <b>Resolved:</b> [T.resolved] <a href='?src=\ref[T];resolve=\ref[T]'>(Resolve)</a>"
else
usr << " <b>Resolved:</b> [T.resolved] <a href='?src=\ref[T];resolve=\ref[T]'>(Unresolve)</a>"
else
user << "Current Unresolved Ahelps:"
if(T.resolved == TICKET_UNRESOLVED)
usr << "<span class='adminnotice'><b><font color=red>#[T.id] By:</font> <A HREF='?priv_msg=[T.permckey];ahelp_reply=1'>[key_name(T.permuser)]</A></b><b> Ckey:</b> [T.permckey] <b>Name:</b> [T.permuser] <b>Unique ID:</b> [T.uID]</span>"
usr << " <b>Controls:</b> [ADMIN_QUE(mob)] [ADMIN_PP(mob)] [ADMIN_VV(mob)] [ADMIN_SM(mob)] [ADMIN_FLW(mob)] [ADMIN_TP(mob)]"
usr << " <b>Message:</b> [T.msg]"
usr << " <b>Handling Admin:</b> [T.admin]"
usr << " <b>Replied To:</b> [T.active]/<b><a href='?src=\ref[T];view_logs=\ref[T]'>(LOGS)</a></b>"
if(T.resolved == TICKET_UNRESOLVED)
usr << " <b>Resolved:</b> [T.resolved] <a href='?src=\ref[T];resolve=\ref[T]'>(Resolve)</a>"
else
usr << " <b>Resolved:</b> [T.resolved] <a href='?src=\ref[T];resolve=\ref[T]'>(Unresolve)</a>"
/client/proc/ahelp_count(modifier)
var/amount
for(var/I in admintickets)
var/datum/adminticket/T = I
if(T.resolved == TICKET_UNRESOLVED)
amount++
if(T.resolved == TICKET_RESOLVED)
amount++
return amount
/datum/adminticket/proc/listtickets()
set category = "Admin Help"
set name = "List Adminhelps"
set desc = "List all current adminhelps"
if(!check_rights(R_ADMIN))
src << "<font color='red'>Error: Only administrators may use this command.</font>"
return
var/count = 0
for(var/datum/adminticket/T in admintickets)
count++
usr << "<b>Current Ahelps:</b>"
if(count < 1)
usr << " None"
return
for(var/I in admintickets)
var/datum/adminticket/T = I
usr << "<span class='adminnotice'><b><font color=red>#[T.id] By:</font> <A HREF='?priv_msg=[T.permckey];ahelp_reply=1'>[key_name(T.permuser)]</b></A><b> Ckey:</b> [T.permckey] <b>Name:</b> [T.permuser] <b>Unique ID:</b> [T.uID]</span>"
usr << " <b>Controls:</b> [ADMIN_QUE(mob)] [ADMIN_PP(mob)] [ADMIN_VV(mob)] [ADMIN_SM(mob)] [ADMIN_FLW(mob)] [ADMIN_TP(mob)]"
usr << " <b>Message:</b> [T.msg]"
usr << " <b>Handling Admin:</b> [T.admin]"
usr << " <b>Replied To:</b> [T.active]/<b><a href='?src=\ref[T];view_logs=\ref[T]'>(LOGS)</a></b>"
if(T.resolved == TICKET_UNRESOLVED)
usr << " <b>Resolved:</b> [T.resolved] <a href='?src=\ref[T];resolve=\ref[T]'>(Resolve)</a>"
else
usr << " <b>Resolved:</b> [T.resolved] <a href='?src=\ref[T];resolve=\ref[T]'>(Unresolve)</a>"
/datum/adminticket/proc/listunresolvedtickets()
set category = "Admin Help"
set name = "List Unresolved Adminhelps"
set desc = "List all current unresolved adminhelps"
if(!check_rights(R_ADMIN))
src << "<font color='red'>Error: Only administrators may use this command.</font>"
return
var/count = 0
for(var/I in admintickets)
var/datum/adminticket/T = I
if(T.resolved == TICKET_UNRESOLVED)
count++
usr << "<b>Current Unresolved Ahelps:</b>"
if(count < 1)
usr << " None"
return
for(var/I in admintickets)
var/datum/adminticket/T = I
if(T.resolved == TICKET_UNRESOLVED)
usr << "<span class='adminnotice'><b><font color=red>#[T.id] By:</font> <A HREF='?priv_msg=[T.permckey];ahelp_reply=1'>[key_name(T.permuser)]</b></A><b> Ckey:</b> [T.permckey] <b>Name:</b> [T.permuser] <b>Unique ID:</b> [T.uID]</span>"
usr << " <b>Controls:</b> [ADMIN_QUE(mob)] [ADMIN_PP(mob)] [ADMIN_VV(mob)] [ADMIN_SM(mob)] [ADMIN_FLW(mob)] [ADMIN_TP(mob)]"
usr << " <b>Message:</b> [T.msg]"
usr << " <b>Handling Admin:</b> [T.admin]"
usr << " <b>Replied To:</b> [T.active]/<b><a href='?src=\ref[T];view_logs=\ref[T]'>(LOGS)</a></b>"
if(T.resolved == TICKET_UNRESOLVED)
usr << " <b>Resolved:</b> [T.resolved] <a href='?src=\ref[T];resolve=\ref[T]'>(Resolve)</a>"
else
usr << " <b>Resolved:</b> [T.resolved] <a href='?src=\ref[T];resolve=\ref[T]'>(Unresolve)</a>"
/client/proc/listhandlingahelp()
set category = "Admin Help"
set name = "View Handling Ahelps"
set desc = "List all current handling ahelps"
if(!check_rights(R_ADMIN))
src << "<font color='red'>Error: Only administrators may use this command.</font>"
return
var/count = 0
for(var/I in admintickets)
var/datum/adminticket/T = I
if(T.resolved == TICKET_UNRESOLVED && T.admin == ckey)
count++
if(count < 1)
usr << "<b>You don't have any ACTIVE ahelps!</b>"
return
for(var/I in admintickets)
var/datum/adminticket/T = I
if(T.resolved == TICKET_UNRESOLVED && T.admin == ckey)
usr << "<span class='adminnotice'><b><font color=red>#[T.id] By:</font> <A HREF='?priv_msg=[T.permckey];ahelp_reply=1'>[key_name(T.permuser)]</A></b><b> Ckey:</b> [T.permckey] <b>Name:</b> [T.permuser] <b>Unique ID:</b> [T.uID]</span>"
usr << " <b>Controls:</b> [ADMIN_QUE(mob)] [ADMIN_PP(mob)] [ADMIN_VV(mob)] [ADMIN_SM(mob)] [ADMIN_FLW(mob)] [ADMIN_TP(mob)]"
usr << " <b>Message:</b> [T.msg]"
usr << " <b>Handling Admin:</b> [T.admin]"
usr << " <b>Replied To:</b> [T.active]/<b><a href='?src=\ref[T];view_logs=\ref[T]'>(LOGS)</a></b>"
if(T.resolved == TICKET_UNRESOLVED)
usr << " <b>Resolved:</b> [T.resolved] <a href='?src=\ref[T];resolve=\ref[T]'>(Resolve)</a>"
else
usr << " <b>Resolved:</b> [T.resolved] <a href='?src=\ref[T];resolve=\ref[T]'>(Unresolve)</a>"
/client/verb/viewmyahelp()
set category = "Admin"
set name = "View my Ahelps"
set desc = "List your ahelps"
var/count = 0
for(var/I in admintickets)
var/datum/adminticket/T = I
if(T.permckey == ckey)
count++
if(count < 1)
usr << "<b>You don't have any ahelps!</b>"
return
usr << "<b>Resolved Ahelps</b>"
var/rpass = FALSE
for(var/I in admintickets)
var/datum/adminticket/T = I
if(T.permckey == ckey && T.resolved == TICKET_RESOLVED)
rpass = TRUE
usr << "<span class='adminnotice'><b><font color=red>Adminhelp ID: #[T.id] </font></b></span>"
usr << " <b>Message:</b> [T.msg]"
usr << " <b>Handling Admin:</b> [T.admin]"
usr << " <b>Replied To:</b> [T.active]/<b><a href='?src=\ref[T];view_logs=\ref[T]'>(LOGS)</a></b>"
usr << " <b>Resolved:</b> [T.resolved]"
if(rpass == FALSE)
usr << " None"
usr << "<b>Unresolved Ahelps</b>"
var/upass = FALSE
for(var/I in admintickets)
var/datum/adminticket/T = I
if(T.permckey == ckey && T.resolved == TICKET_UNRESOLVED)
upass = TRUE
usr << "<span class='adminnotice'><b><font color=red>Adminhelp ID: #[T.id] </font></b></span>"
usr << " <b>Message:</b> [T.msg]"
usr << " <b>Handling Admin:</b> [T.admin]"
usr << " <b>Replied To:</b> [T.active]/<b><a href='?src=\ref[T];view_logs=\ref[T]'>(LOGS)</a></b>"
usr << " <b>Resolved:</b> [T.resolved]"
if(upass == FALSE)
usr << " None"
/client/proc/createticket(player, message, uckey, mob)
var/datum/adminticket/A = new()
A.user = player
A.msg = message
A.uckey = uckey
A.permckey = uckey
A.permuser = A.user
admintickets += A
A.ticket_logs += "<b>ADMINHELP:</b> [A.permckey]([A.permuser]): [A.msg]"
A.mob = mob
var/index = 0
for(var/I in admintickets)
var/datum/adminticket/T = I
index++
T.id = index
T.uID = "[T.permckey][T.id]"
/client/verb/resolveticketself()
set category = "Admin"
set name = "Resolve My Adminhelp"
set desc = "Resolve my own adminhelp"
var/pass = 0
var/datum/adminticket/ticket
for(var/I in admintickets)
var/datum/adminticket/T = I
if(T.permckey == ckey && T.resolved != TICKET_RESOLVED)
T.resolved = TICKET_RESOLVED
pass = 1
switch(pass)
if(1)
src << "<b>You have resolved your current adminhelp.</b>"
message_admins("[src] has resolved his adminhelp (#[ticket.id])")
if(0)
src << "<b>Error, you do not have any active adminhelps.</b>"
/client/proc/resolvehandlingahelp()
set category = "Admin Help"
set name = "Resolve Handling Ahelp"
set desc = "Resolve my own adminhelp"
if(!check_rights(R_ADMIN))
src << "<font color='red'>Error: Only administrators may use this command.</font>"
return
var/count = 0
var/datum/adminticket/ticket
for(var/I in admintickets)
var/datum/adminticket/T = I
if(T.admin == ckey && T.resolved != TICKET_RESOLVED)
count++
if(count >= 1)
usr << "<b>Adminhelp #[T.id]([T.uID]) resolved.</b>"
message_admins("Adminhelp ID: #[T.id]([T.uID]) was resolved by [usr.ckey]")
ticket.user << "<b>Your adminhelp (#[T.id]) has been resolved by [usr.ckey]</b>"
ticket.user << 'sound/machines/twobeep.ogg'
ticket.resolved = TICKET_RESOLVED
if(count < 1)
usr << "<b>You are not currently handling any adminhelps!</b>"
/datum/adminticket/proc/viewlogs(NuID, mob/user)
var/dat = "<h3>View Logs for ahelp [NuID]</h3>"
var/datum/adminticket/ticket
var/pass = 0
for(var/datum/adminticket/T in admintickets)
if(NuID == T.uID)
ticket = T
pass = 1
if(pass == 0)
src << "Error, log system not found for [NuID]... "
return
dat += "<table>"
for(var/text in ticket.ticket_logs)
dat += "<tr><td>[text]</td></tr>"
dat += "</table>"
var/datum/browser/popup = new(user, "ahelp logs", ticket.permuser, 500, 500)
popup.set_content(dat)
popup.open()
/datum/adminticket/Topic(href, href_list)
if (!istype(src,/datum/admins))
src = usr.client.holder
if (!istype(src,/datum/admins))
usr << "Error: you are not an admin!"
return
if(href_list["view_logs"])
var/datum/adminticket/T = locate(href_list["view_logs"])
viewlogs(T.uID, usr)
if(href_list["resolve"])
var/datum/adminticket/T = locate(href_list["resolve"]) in admintickets
if(T && istype(T))
message_admins("Adminhelp ID: #[T.id]([T.uID]) was [T.resolved == "Yes" ? "unresolved" : "resolved"] by [usr.ckey]")
T.user << "<b>Your adminhelp (#[T.id]) has been [T.resolved == "Yes" ? "unresolved" : "resolved"] by [usr.ckey]</b>"
T.user << 'sound/machines/twobeep.ogg'
T.resolved = "[T.resolved == "Yes" ? "No" : "Yes"]"
+4 -2
View File
@@ -528,7 +528,7 @@ GLOBAL_PROTECT(VVpixelmovement)
variable = input("Which var?","Var") as null|anything in names
if(!variable)
return
if(!O.can_vv_get(variable))
return
@@ -614,4 +614,6 @@ GLOBAL_PROTECT(VVpixelmovement)
return
log_world("### VarEdit by [src]: [O.type] [variable]=[html_encode("[O.vars[variable]]")]")
log_admin("[key_name(src)] modified [original_name]'s [variable] to [O.vars[variable]]")
message_admins("[key_name_admin(src)] modified [original_name]'s [variable] to [O.vars[variable]]")
var/msg = "[key_name_admin(src)] modified [original_name]'s [variable] to [O.vars[variable]]"
message_admins(msg)
admin_ticket_log(O, msg)
+5 -5
View File
@@ -33,7 +33,7 @@
prayer_type = "CULTIST PRAYER"
deity = "Nar-Sie"
msg = "<span class='adminnotice'>\icon[cross]<b><font color=[font_color]>[prayer_type][deity ? " (to [deity])" : ""]: </font>[ADMIN_FULLMONTY(src)] [ADMIN_SC(src)] [ADMIN_SMITE(src)]:</b> [msg]</span>"
msg = "<span class='adminnotice'>\icon[cross]<b><font color=[font_color]>[prayer_type][deity ? " (to [deity])" : ""]: </font>[ADMIN_FULLMONTY(src)] [ADMIN_SC(src)]:</b> [msg]</span>"
for(var/client/C in GLOB.admins)
if(C.prefs.chat_toggles & CHAT_PRAYER)
@@ -48,21 +48,21 @@
/proc/Centcomm_announce(text , mob/Sender)
var/msg = copytext(sanitize(text), 1, MAX_MESSAGE_LEN)
msg = "<span class='adminnotice'><b><font color=orange>CENTCOM:</font>[ADMIN_FULLMONTY(Sender)] [ADMIN_SMITE(Sender)] [ADMIN_CENTCOM_REPLY(Sender)]:</b> [msg]</span>"
msg = "<span class='adminnotice'><b><font color=orange>CENTCOM:</font>[ADMIN_FULLMONTY(Sender)] [ADMIN_CENTCOM_REPLY(Sender)]:</b> [msg]</span>"
to_chat(GLOB.admins, msg)
for(var/obj/machinery/computer/communications/C in GLOB.machines)
C.overrideCooldown()
/proc/Syndicate_announce(text , mob/Sender)
var/msg = copytext(sanitize(text), 1, MAX_MESSAGE_LEN)
msg = "<span class='adminnotice'><b><font color=crimson>SYNDICATE:</font>[ADMIN_FULLMONTY(Sender)] [ADMIN_SMITE(Sender)] [ADMIN_SYNDICATE_REPLY(Sender)]:</b> [msg]</span>"
msg = "<span class='adminnotice'><b><font color=crimson>SYNDICATE:</font>[ADMIN_FULLMONTY(Sender)] [ADMIN_SYNDICATE_REPLY(Sender)]:</b> [msg]</span>"
to_chat(GLOB.admins, msg)
for(var/obj/machinery/computer/communications/C in GLOB.machines)
C.overrideCooldown()
/proc/Nuke_request(text , mob/Sender)
var/msg = copytext(sanitize(text), 1, MAX_MESSAGE_LEN)
msg = "<span class='adminnotice'><b><font color=orange>NUKE CODE REQUEST:</font>[ADMIN_FULLMONTY(Sender)] [ADMIN_SMITE(Sender)] [ADMIN_CENTCOM_REPLY(Sender)] [ADMIN_SET_SD_CODE]:</b> [msg]</span>"
msg = "<span class='adminnotice'><b><font color=orange>NUKE CODE REQUEST:</font>[ADMIN_FULLMONTY(Sender)] [ADMIN_CENTCOM_REPLY(Sender)] [ADMIN_SET_SD_CODE]:</b> [msg]</span>"
to_chat(GLOB.admins, msg)
for(var/obj/machinery/computer/communications/C in GLOB.machines)
C.overrideCooldown()
C.overrideCooldown()
+31 -12
View File
@@ -15,10 +15,11 @@
M.regenerate_icons()
log_admin("[key_name(usr)] made [key_name(M)] drop everything!")
message_admins("[key_name_admin(usr)] made [key_name_admin(M)] drop everything!")
var/msg = "[key_name_admin(usr)] made [key_name_admin(M)] drop everything!"
message_admins(msg)
admin_ticket_log(M, msg)
feedback_add_details("admin_verb","Drop Everything") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
/client/proc/cmd_admin_subtle_message(mob/M in GLOB.mob_list)
set category = "Special Verbs"
set name = "Subtle Message"
@@ -41,7 +42,9 @@
to_chat(M, "<i>You hear a voice in your head... <b>[msg]</i></b>")
log_admin("SubtlePM: [key_name(usr)] -> [key_name(M)] : [msg]")
message_admins("<span class='adminnotice'><b> SubtleMessage: [key_name_admin(usr)] -> [key_name_admin(M)] :</b> [msg]</span>")
msg = "<span class='adminnotice'><b> SubtleMessage: [key_name_admin(usr)] -> [key_name_admin(M)] :</b> [msg]</span>"
message_admins(msg)
admin_ticket_log(M, msg)
feedback_add_details("admin_verb","Subtle Message") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
/client/proc/cmd_admin_world_narrate()
@@ -82,7 +85,9 @@
to_chat(M, msg)
log_admin("DirectNarrate: [key_name(usr)] to ([M.name]/[M.key]): [msg]")
message_admins("<span class='adminnotice'><b> DirectNarrate: [key_name(usr)] to ([M.name]/[M.key]):</b> [msg]<BR></span>")
msg = "<span class='adminnotice'><b> DirectNarrate: [key_name(usr)] to ([M.name]/[M.key]):</b> [msg]<BR></span>"
message_admins(msg)
admin_ticket_log(M, msg)
feedback_add_details("admin_verb","Direct Narrate") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
/client/proc/cmd_admin_local_narrate(atom/A)
@@ -117,7 +122,9 @@
to_chat(usr, "<span class='adminnotice'>Toggled [(M.status_flags & GODMODE) ? "ON" : "OFF"]</span>")
log_admin("[key_name(usr)] has toggled [key_name(M)]'s nodamage to [(M.status_flags & GODMODE) ? "On" : "Off"]")
message_admins("[key_name_admin(usr)] has toggled [key_name_admin(M)]'s nodamage to [(M.status_flags & GODMODE) ? "On" : "Off"]")
var/msg = "[key_name_admin(usr)] has toggled [key_name_admin(M)]'s nodamage to [(M.status_flags & GODMODE) ? "On" : "Off"]"
message_admins(msg)
admin_ticket_log(M, msg)
feedback_add_details("admin_toggle","Godmode|[M.status_flags & GODMODE]") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
@@ -238,7 +245,9 @@
return 0
new_xeno.ckey = ckey
message_admins("<span class='notice'>[key_name_admin(usr)] has spawned [ckey] as a filthy xeno [alien_caste].</span>")
var/msg = "<span class='notice'>[key_name_admin(usr)] has spawned [ckey] as a filthy xeno [alien_caste].</span>"
message_admins(msg)
admin_ticket_log(new_xeno, msg)
return 1
/*
@@ -297,7 +306,9 @@ Traitors and the like can also be revived with the previous role mostly intact.
G_found.mind.transfer_to(new_xeno) //be careful when doing stuff like this! I've already checked the mind isn't in use
new_xeno.key = G_found.key
to_chat(new_xeno, "You have been fully respawned. Enjoy the game.")
message_admins("<span class='adminnotice'>[key_name_admin(usr)] has respawned [new_xeno.key] as a filthy xeno.</span>")
var/msg = "<span class='adminnotice'>[key_name_admin(usr)] has respawned [new_xeno.key] as a filthy xeno.</span>"
message_admins(msg)
admin_ticket_log(new_xeno, msg)
return //all done. The ghost is auto-deleted
//check if they were a monkey
@@ -307,7 +318,9 @@ Traitors and the like can also be revived with the previous role mostly intact.
G_found.mind.transfer_to(new_monkey) //be careful when doing stuff like this! I've already checked the mind isn't in use
new_monkey.key = G_found.key
to_chat(new_monkey, "You have been fully respawned. Enjoy the game.")
message_admins("<span class='adminnotice'>[key_name_admin(usr)] has respawned [new_monkey.key] as a filthy xeno.</span>")
var/msg = "<span class='adminnotice'>[key_name_admin(usr)] has respawned [new_monkey.key] as a filthy xeno.</span>"
message_admins(msg)
admin_ticket_log(new_monkey, msg)
return //all done. The ghost is auto-deleted
@@ -404,7 +417,9 @@ Traitors and the like can also be revived with the previous role mostly intact.
if(alert(new_character,"Would you like an active AI to announce this character?",,"No","Yes")=="Yes")
AnnounceArrival(new_character, new_character.mind.assigned_role)
message_admins("<span class='adminnotice'>[admin] has respawned [player_key] as [new_character.real_name].</span>")
var/msg = "<span class='adminnotice'>[admin] has respawned [player_key] as [new_character.real_name].</span>"
message_admins(msg)
admin_ticket_log(new_character, msg)
to_chat(new_character, "You have been fully respawned. Enjoy the game.")
@@ -447,7 +462,9 @@ Traitors and the like can also be revived with the previous role mostly intact.
M.revive(full_heal = 1, admin_revive = 1)
log_admin("[key_name(usr)] healed / revived [key_name(M)]")
message_admins("<span class='danger'>Admin [key_name_admin(usr)] healed / revived [key_name_admin(M)]!</span>")
var/msg = "<span class='danger'>Admin [key_name_admin(usr)] healed / revived [key_name_admin(M)]!</span>"
message_admins(msg)
admin_ticket_log(M, msg)
feedback_add_details("admin_verb","Rejuvinate") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
/client/proc/cmd_admin_create_centcom_report()
@@ -1169,5 +1186,7 @@ GLOBAL_LIST_EMPTY(custom_outfits) //Admin created outfits
if(ADMIN_PUNISHMENT_BSA)
bluespace_artillery(target)
message_admins("[key_name_admin(usr)] punished [key_name_admin(target)] with [punishment].")
log_admin("[key_name(usr)] punished [key_name(target)] with [punishment].")
var/msg = "[key_name_admin(usr)] punished [key_name_admin(target)] with [punishment]."
message_admins(msg)
admin_ticket_log(target, msg)
log_admin("[key_name(usr)] punished [key_name(target)] with [punishment].")