diff --git a/code/modules/admin/verbs/adminhelp.dm b/code/modules/admin/verbs/adminhelp.dm index 09f99aa8f38..ac7cdcc4646 100644 --- a/code/modules/admin/verbs/adminhelp.dm +++ b/code/modules/admin/verbs/adminhelp.dm @@ -195,6 +195,8 @@ GLOBAL_DATUM_INIT(ahelp_tickets, /datum/admin_help_tickets, new) var/list/opening_responders /// Whether this ahelp has sent a webhook or not, and what type var/webhook_sent = WEBHOOK_NONE + /// List of player interactions + var/list/player_interactions /** * Call this on its own to create a ticket, don't manually assign current_ticket @@ -228,9 +230,10 @@ GLOBAL_DATUM_INIT(ahelp_tickets, /datum/admin_help_tickets, new) statclick = new(null, src) ticket_interactions = list() + player_interactions = list() if(is_bwoink) - AddInteraction("[key_name_admin(usr)] PM'd [LinkedReplyName()]") + AddInteraction("[key_name_admin(usr)] PM'd [LinkedReplyName()]", player_message = "[key_name_admin(usr, include_name = FALSE)] PM'd [LinkedReplyName()]") message_admins("Ticket [TicketHref("#[id]")] created") else MessageNoRecipient(msg_raw, urgent) @@ -342,11 +345,13 @@ GLOBAL_DATUM_INIT(ahelp_tickets, /datum/admin_help_tickets, new) GLOB.ahelp_tickets.resolved_tickets -= src return ..() -/datum/admin_help/proc/AddInteraction(formatted_message) +/datum/admin_help/proc/AddInteraction(formatted_message, player_message) if(heard_by_no_admins && usr && usr.ckey != initiator_ckey) heard_by_no_admins = FALSE send2adminchat(initiator_ckey, "Ticket #[id]: Answered by [key_name(usr)]") ticket_interactions += "[time_stamp()]: [formatted_message]" + if (!isnull(player_message)) + player_interactions += "[time_stamp()]: [player_message]" //Removes the ahelp verb and returns it after 2 minutes /datum/admin_help/proc/TimeoutVerb() @@ -392,7 +397,7 @@ GLOBAL_DATUM_INIT(ahelp_tickets, /datum/admin_help_tickets, new) //Message to be sent to all admins var/admin_msg = span_adminnotice(span_adminhelp("Ticket [TicketHref("#[id]", ref_src)]: [LinkedReplyName(ref_src)] [FullMonty(ref_src)]: [keywords_lookup(msg)]")) - AddInteraction("[LinkedReplyName(ref_src)]: [msg]") + AddInteraction("[LinkedReplyName(ref_src)]: [msg]", player_message = "[LinkedReplyName(ref_src)]: [msg]") log_admin_private("Ticket #[id]: [key_name(initiator)]: [msg]") //send this msg to all admins @@ -436,7 +441,7 @@ GLOBAL_DATUM_INIT(ahelp_tickets, /datum/admin_help_tickets, new) if(initiator) initiator.current_ticket = src - AddInteraction("Reopened by [key_name_admin(usr)]") + AddInteraction("Reopened by [key_name_admin(usr)]", player_message = "Ticket reopened!") var/msg = span_adminhelp("Ticket [TicketHref("#[id]")] reopened by [key_name_admin(usr)].") message_admins(msg) log_admin_private(msg) @@ -463,7 +468,7 @@ GLOBAL_DATUM_INIT(ahelp_tickets, /datum/admin_help_tickets, new) RemoveActive() state = AHELP_CLOSED GLOB.ahelp_tickets.ListInsert(src) - AddInteraction("Closed by [key_name].") + AddInteraction("Closed by [key_name].", player_message = "Ticket closed!") if(!silent) SSblackbox.record_feedback("tally", "ahelp_stats", 1, "closed") var/msg = "Ticket [TicketHref("#[id]")] closed by [key_name]." @@ -481,7 +486,7 @@ GLOBAL_DATUM_INIT(ahelp_tickets, /datum/admin_help_tickets, new) addtimer(CALLBACK(initiator, /client/proc/giveadminhelpverb), 50) - AddInteraction("Resolved by [key_name].") + AddInteraction("Resolved by [key_name].", player_message = "Ticket resolved!") to_chat(initiator, span_adminhelp("Your ticket has been resolved by an admin. The Adminhelp verb will be returned to you shortly."), confidential = TRUE) if(!silent) SSblackbox.record_feedback("tally", "ahelp_stats", 1, "resolved") @@ -508,7 +513,7 @@ GLOBAL_DATUM_INIT(ahelp_tickets, /datum/admin_help_tickets, new) var/msg = "Ticket [TicketHref("#[id]")] rejected by [key_name]" message_admins(msg) log_admin_private(msg) - AddInteraction("Rejected by [key_name].") + AddInteraction("Rejected by [key_name].", player_message = "Ticket rejected!") SSblackbox.LogAhelp(id, "Rejected", "Rejected by [usr.key]", null, usr.ckey) Close(silent = TRUE) @@ -527,7 +532,7 @@ GLOBAL_DATUM_INIT(ahelp_tickets, /datum/admin_help_tickets, new) 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]") + AddInteraction("Marked as IC issue by [key_name]", player_message = "Marked as IC issue!") SSblackbox.LogAhelp(id, "IC Issue", "Marked as IC issue by [usr.key]", null, usr.ckey) Resolve(silent = TRUE) @@ -622,6 +627,32 @@ GLOBAL_DATUM_INIT(ahelp_tickets, /datum/admin_help_tickets, new) if("reopen") Reopen() +/datum/admin_help/proc/player_ticket_panel() + var/list/dat = list("Player Ticket") + dat += "State: " + switch(state) + if(AHELP_ACTIVE) + dat += "OPEN" + if(AHELP_RESOLVED) + dat += "RESOLVED" + if(AHELP_CLOSED) + dat += "CLOSED" + else + dat += "UNKNOWN" + dat += "\n[FOURSPACES]Refresh" + dat += "

Opened at: [gameTimestamp("hh:mm:ss", opened_at)] (Approx [DisplayTimeText(world.time - opened_at)] ago)" + if(closed_at) + dat += "
Closed at: [gameTimestamp("hh:mm:ss", closed_at)] (Approx [DisplayTimeText(world.time - closed_at)] ago)" + dat += "

" + dat += "
Log:

" + for (var/interaction in player_interactions) + dat += "[interaction]
" + + var/datum/browser/player_panel = new(usr, "ahelp[id]", 0, 620, 480) + player_panel.set_content(dat.Join()) + player_panel.open() + + // // TICKET STATCLICK // @@ -752,34 +783,68 @@ GLOBAL_DATUM_INIT(admin_help_ui_handler, /datum/admin_help_ui_handler, new) GLOB.admin_help_ui_handler.ui_interact(mob) to_chat(src, span_boldnotice("Adminhelp failing to open or work? Click here")) +/client/verb/view_latest_ticket() + set category = "Admin" + set name = "View Latest Ticket" + + if(!current_ticket) + // Check if the client had previous tickets, and show the latest one + var/list/prev_tickets = list() + var/datum/admin_help/last_ticket + // Check all resolved tickets for this player + for(var/datum/admin_help/resolved_ticket in GLOB.ahelp_tickets.resolved_tickets) + if(resolved_ticket.initiator_ckey == ckey) // Initiator is a misnomer, it's always the non-admin player even if an admin bwoinks first + prev_tickets += resolved_ticket + // Check all closed tickets for this player + for(var/datum/admin_help/closed_ticket in GLOB.ahelp_tickets.closed_tickets) + if(closed_ticket.initiator_ckey == ckey) + prev_tickets += closed_ticket + // Take the most recent entry of prev_tickets and open the panel on it + if(LAZYLEN(prev_tickets)) + last_ticket = pop(prev_tickets) + last_ticket.player_ticket_panel() + return + + // client had no tickets this round + to_chat(src, span_warning("You have not had an ahelp ticket this round.")) + return + + current_ticket.player_ticket_panel() // // 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 -//log_in_blackbox: Whether or not this message with the blackbox system. -//If disabled, this message should be logged with a different proc call -/proc/admin_ticket_log(what, message, log_in_blackbox = TRUE) - var/client/C +/// 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 +/// player_message: If the message should be shown in the player ticket panel, fill this out +/// log_in_blackbox: Whether or not this message with the blackbox system. +/// If disabled, this message should be logged with a different proc call +/proc/admin_ticket_log(what, message, player_message, log_in_blackbox = TRUE) + var/client/mob_client var/mob/Mob = what if(istype(Mob)) - C = Mob.client + mob_client = Mob.client else - C = what - if(istype(C) && C.current_ticket) - C.current_ticket.AddInteraction(message) + mob_client = what + if(istype(mob_client) && mob_client.current_ticket) + if (isnull(player_message)) + mob_client.current_ticket.AddInteraction(message) + else + mob_client.current_ticket.AddInteraction(message, player_message) if(log_in_blackbox) - SSblackbox.LogAhelp(C.current_ticket.id, "Interaction", message, C.ckey, usr.ckey) - return C.current_ticket + SSblackbox.LogAhelp(mob_client.current_ticket.id, "Interaction", message, mob_client.ckey, usr.ckey) + return mob_client.current_ticket if(istext(what)) //ckey - var/datum/admin_help/AH = GLOB.ahelp_tickets.CKey2ActiveTicket(what) - if(AH) - AH.AddInteraction(message) + var/datum/admin_help/active_admin_help = GLOB.ahelp_tickets.CKey2ActiveTicket(what) + if(active_admin_help) + if (isnull(player_message)) + active_admin_help.AddInteraction(message) + else + active_admin_help.AddInteraction(message, player_message) if(log_in_blackbox) - SSblackbox.LogAhelp(AH.id, "Interaction", message, what, usr.ckey) - return AH + SSblackbox.LogAhelp(active_admin_help.id, "Interaction", message, what, usr.ckey) + return active_admin_help // // HELPER PROCS diff --git a/code/modules/admin/verbs/adminpm.dm b/code/modules/admin/verbs/adminpm.dm index 0fb00e2ec69..44688da482b 100644 --- a/code/modules/admin/verbs/adminpm.dm +++ b/code/modules/admin/verbs/adminpm.dm @@ -214,9 +214,9 @@ type = MESSAGE_TYPE_ADMINPM, html = span_notice("PM to-Admins: [rawmsg]"), confidential = TRUE) - var/datum/admin_help/AH = admin_ticket_log(src, "Reply PM from-[key_name(src, TRUE, TRUE)] to External: [keywordparsedmsg]") + var/datum/admin_help/new_admin_help = admin_ticket_log(src, "Reply PM from-[key_name(src, TRUE, TRUE)] to External: [keywordparsedmsg]", player_message = "Reply PM from-[key_name(src, TRUE, FALSE)] to External: [msg]") externalreplyamount-- - send2adminchat("[AH ? "#[AH.id] " : ""]Reply: [ckey]", rawmsg) + send2adminchat("[new_admin_help ? "#[new_admin_help.id] " : ""]Reply: [ckey]", rawmsg) else var/badmin = FALSE //Lets figure out if an admin is getting bwoinked. if(holder && recipient.holder && !current_ticket) //Both are admins, and this is not a reply to our own ticket. @@ -234,14 +234,16 @@ html = span_notice("Admin PM to-[key_name(recipient, src, 1)]: [keywordparsedmsg]"), confidential = TRUE) //omg this is dumb, just fill in both their tickets - var/interaction_message = "PM from-[key_name(src, recipient, 1)] to-[key_name(recipient, src, 1)]: [keywordparsedmsg]" - admin_ticket_log(src, interaction_message, log_in_blackbox = FALSE) + var/interaction_message = "PM from-[key_name(src, recipient, TRUE)] to-[key_name(recipient, src, TRUE)]: [keywordparsedmsg]" + var/player_interaction_message = "PM from-[key_name(src, recipient, FALSE)] to-[key_name(recipient, src, FALSE)]: [msg]" + admin_ticket_log(src, interaction_message, log_in_blackbox = FALSE, player_message = player_interaction_message) if(recipient != src) //reeee - admin_ticket_log(recipient, interaction_message, log_in_blackbox = FALSE) + admin_ticket_log(recipient, interaction_message, log_in_blackbox = FALSE, player_message = player_interaction_message) SSblackbox.LogAhelp(current_ticket.id, "Reply", msg, recipient.ckey, src.ckey) else //recipient is an admin but sender is not - var/replymsg = "Reply PM from-[key_name(src, recipient, 1)]: [keywordparsedmsg]" - admin_ticket_log(src, "[replymsg]", log_in_blackbox = FALSE) + var/replymsg = "Reply PM from-[key_name(src, recipient, TRUE)]: [keywordparsedmsg]" + var/player_replymsg = "Reply PM from-[key_name(src, recipient, FALSE)]: [msg]" + admin_ticket_log(src, "[replymsg]", log_in_blackbox = FALSE, player_message = player_replymsg) to_chat(recipient, type = MESSAGE_TYPE_ADMINPM, html = span_danger("[replymsg]"), @@ -280,7 +282,7 @@ html = span_notice("Admin PM to-[key_name(recipient, src, 1)]: [msg]"), confidential = TRUE) - admin_ticket_log(recipient, "PM From [key_name_admin(src)]: [keywordparsedmsg]", log_in_blackbox = FALSE) + admin_ticket_log(recipient, "PM From [key_name_admin(src)]: [keywordparsedmsg]", log_in_blackbox = FALSE, player_message = "PM From [key_name_admin(src, include_name = FALSE)]: [msg]") if(!already_logged) //Reply to an existing ticket SSblackbox.LogAhelp(recipient.current_ticket.id, "Reply", msg, recipient.ckey, src.ckey) diff --git a/code/modules/client/client_procs.dm b/code/modules/client/client_procs.dm index 982648b6f13..fad493d9ee4 100644 --- a/code/modules/client/client_procs.dm +++ b/code/modules/client/client_procs.dm @@ -100,6 +100,9 @@ GLOBAL_LIST_INIT(blacklisted_builds, list( if(href_list["priv_msg"]) cmd_admin_pm(href_list["priv_msg"],null) return + if (href_list["player_ticket_panel"]) + view_latest_ticket() + return // TGUIless adminhelp if(href_list["tguiless_adminhelp"]) no_tgui_adminhelp(input(src, "Enter your ahelp", "Ahelp") as null|message)