Adds ticket escalation

This commit is contained in:
Casey
2022-08-15 21:10:51 -04:00
committed by CHOMPStation2
parent 724ccf89bd
commit 296d2e902c
3 changed files with 662 additions and 0 deletions

View File

@@ -178,6 +178,7 @@
GLOB.directory[ckey] = src
GLOB.ahelp_tickets.ClientLogin(src)
GLOB.mhelp_tickets.ClientLogin(src)
//Admin Authorisation
holder = admin_datums[ckey]
@@ -263,6 +264,7 @@
holder.owner = null
GLOB.admins -= src
GLOB.ahelp_tickets.ClientLogout(src)
GLOB.mhelp_tickets.ClientLogout(src)
GLOB.directory -= ckey
GLOB.clients -= src
return ..()

View File

@@ -0,0 +1,245 @@
/client
var/datum/mentor/mentorholder = null
var/list/mentor_datums = list()
var/list/mentor_verbs_default = list(
/client/proc/cmd_mentor_ticket_panel,
/client/proc/cmd_mentor_say,
/client/proc/cmd_dementor
)
/datum/mentor
var/client/owner = null
/datum/mentor/New(ckey)
if(!ckey)
error("Mentor datum created without a ckey argument. Datum has been deleted")
qdel(src)
return
mentor_datums[ckey] = src
/datum/mentor/proc/associate(client/C)
if(istype(C))
owner = C
owner.mentorholder = src
owner.add_mentor_verbs()
GLOB.mentors |= C
/datum/mentor/proc/disassociate()
if(owner)
GLOB.mentors -= owner
owner.remove_mentor_verbs()
owner.mentorholder = null
mentor_datums[owner.ckey] = null
qdel(src)
/client/proc/add_mentor_verbs()
if(mentorholder)
verbs += mentor_verbs_default
/client/proc/remove_mentor_verbs()
if(mentorholder)
verbs -= mentor_verbs_default
/client/proc/make_mentor()
set category = "Special Verbs"
set name = "Make Mentor"
if(!holder)
to_chat(src, "<span class='pm warning'>Error: Only administrators may use this command.</span>")
return
var/list/client/targets[0]
for(var/client/T in GLOB.clients)
targets["[T.key]"] = T
var/target = tgui_input_list(src,"Who do you want to make a mentor?","Make Mentor", sortList(targets))
if(!target)
return
var/client/C = targets[target]
if(has_mentor_powers(C) || C.deadmin_holder) // If an admin is deadminned you could mentor them and that will cause fuckery if they readmin
to_chat(src, "<span class='pm warning'>Error: They already have mentor powers.</span>")
return
var/datum/mentor/M = new /datum/mentor(C.ckey)
M.associate(C)
to_chat(C, "<span class='pm notice'>You have been granted mentorship.</span>")
to_chat(src, "<span class='pm notice'>You have made [C] a mentor.</span>")
log_admin("[key_name(src)] made [key_name(C)] a mentor.")
feedback_add_details("admin_verb","Make Mentor") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
/client/proc/unmake_mentor()
set category = "Special Verbs"
set name = "Unmake Mentor"
if(!holder)
to_chat(src, "<span class='pm warning'>Error: Only administrators may use this command.</span>")
return
var/list/client/targets[0]
for(var/client/T in GLOB.mentors)
targets["[T.key]"] = T
var/target = tgui_input_list(src,"Which mentor do you want to unmake?","Unmake Mentor", sortList(targets))
if(!target)
return
var/client/C = targets[target]
C.mentorholder.disassociate()
to_chat(C, "<span class='pm warning'>Your mentorship has been revoked.</span>")
to_chat(src, "<span class='pm notice'>You have revoked [C]'s mentorship.</span>")
log_admin("[key_name(src)] revoked [key_name(C)]'s mentorship.")
feedback_add_details("admin_verb","Unmake Mentor") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
/client/proc/cmd_mentor_say(msg as text)
set category = "Admin"
set name ="Mentorsay"
//check rights
if (!has_mentor_powers(src))
return
msg = sanitize(msg)
if (!msg)
return
log_admin("Mentorsay: [key_name(src)]: [msg]")
for(var/client/C in GLOB.mentors)
to_chat(C, create_text_tag("mentor", "MENTOR:", C) + " <span class='mentor_channel'><span class='name'>[src]</span>: <span class='message'>[msg]</span></span>")
for(var/client/C in GLOB.admins)
to_chat(C, create_text_tag("mentor", "MENTOR:", C) + " <span class='mentor_channel'><span class='name'>[src]</span>: <span class='message'>[msg]</span></span>")
/proc/mentor_commands(href, href_list, client/C)
if(href_list["mhelp"])
var/mhelp_ref = href_list["mhelp"]
var/datum/mentor_help/MH = locate(mhelp_ref)
if (MH && istype(MH, /datum/mentor_help))
MH.Action(href_list["mhelp_action"])
else
to_chat(C, "Ticket [mhelp_ref] has been deleted!")
if (href_list["mhelp_tickets"])
GLOB.mhelp_tickets.BrowseTickets(text2num(href_list["mhelp_tickets"]))
/datum/mentor/Topic(href, href_list)
..()
if (usr.client != src.owner || (!usr.client.mentorholder))
log_admin("[key_name(usr)] tried to illegally use mentor functions.")
message_admins("[usr.key] tried to illegally use mentor functions.")
return
mentor_commands(href, href_list, usr)
/client/proc/cmd_dementor()
set category = "Admin"
set name = "De-mentor"
if(tgui_alert(usr, "Confirm self-dementor for the round? You can't re-mentor yourself without someone promoting you.","Dementor",list("Yes","No")) == "Yes")
src.mentorholder.disassociate()
/client/proc/cmd_mhelp_reply(whom)
if(prefs.muted & MUTE_ADMINHELP)
to_chat(src, "<span class='pm warning'>Error: Mentor-PM: You are unable to use admin PM-s (muted).</span>")
return
var/client/C
if(istext(whom))
C = GLOB.directory[whom]
else if(istype(whom,/client))
C = whom
if(!C)
if(has_mentor_powers(src))
to_chat(src, "<span class='pm warning'>Error: Mentor-PM: Client not found.</span>")
return
var/datum/mentor_help/MH = C.current_mentorhelp
if(MH)
message_mentors("<span class='mentor_channel'>[src] has started replying to [C]'s mentor help.</span>")
var/msg = tgui_input_text(src,"Message:", "Private message to [C]")
if (!msg)
message_mentors("<span class='mentor_channel'>[src] has cancelled their reply to [C]'s mentor help.</span>")
return
cmd_mentor_pm(whom, msg, MH)
/proc/has_mentor_powers(client/C)
return C.holder || C.mentorholder
/client/proc/cmd_mentor_pm(whom, msg, datum/mentor_help/MH)
set category = "Admin"
set name = "Mentor-PM"
set hidden = 1
if(prefs.muted & MUTE_ADMINHELP)
to_chat(src, "<span class='pm warning'>Error: Mentor-PM: You are unable to use admin PM-s (muted).</span>")
return
//Not a mentor and no open ticket
if(!has_mentor_powers(src) && !current_mentorhelp)
to_chat(src, "<span class='pm warning'>You can no longer reply to this ticket, please open another one by using the Mentorhelp verb if need be.</span>")
to_chat(src, "<span class='pm notice'>Message: [msg]</span>")
return
var/client/recipient
if(istext(whom))
recipient = GLOB.directory[whom]
else if(istype(whom,/client))
recipient = whom
//get message text, limit it's length.and clean/escape html
if(!msg)
msg = tgui_input_text(src,"Message:", "Mentor-PM to [whom]")
if(!msg)
return
if(prefs.muted & MUTE_ADMINHELP)
to_chat(src, "<span class='pm warning'>Error: Mentor-PM: You are unable to use admin PM-s (muted).</span>")
return
if(!recipient)
if(has_mentor_powers(src))
to_chat(src, "<span class='pm warning'>Error:Mentor-PM: Client not found.</span>")
to_chat(src, msg)
else
log_admin("Mentorhelp: [key_name(src)]: [msg]")
current_mentorhelp.MessageNoRecipient(msg)
return
//Has mentor powers but the recipient no longer has an open ticket
if(has_mentor_powers(src) && !recipient.current_mentorhelp)
to_chat(src, "<span class='pm warning'>You can no longer reply to this ticket.</span>")
to_chat(src, "<span class='pm notice'>Message: [msg]</span>")
return
if (src.handle_spam_prevention(msg,MUTE_ADMINHELP))
return
msg = trim(sanitize(copytext(msg,1,MAX_MESSAGE_LEN)))
if(!msg)
return
var/interaction_message = "<span class='pm notice'>Mentor-PM from-<b>[src]</b> to-<b>[recipient]</b>: [msg]</span>"
if (recipient.current_mentorhelp && !has_mentor_powers(recipient))
recipient.current_mentorhelp.AddInteraction(interaction_message)
if (src.current_mentorhelp && !has_mentor_powers(src))
src.current_mentorhelp.AddInteraction(interaction_message)
// It's a little fucky if they're both mentors, but while admins may need to adminhelp I don't really see any reason a mentor would have to mentorhelp since you can literally just ask any other mentors online
if (has_mentor_powers(recipient) && has_mentor_powers(src))
if (recipient.current_mentorhelp)
recipient.current_mentorhelp.AddInteraction(interaction_message)
if (src.current_mentorhelp)
src.current_mentorhelp.AddInteraction(interaction_message)
to_chat(recipient, "<i><span class='mentor'>Mentor-PM from-<b><a href='?mentorhelp_msg=\ref[src]'>[src]</a></b>: [msg]</span></i>")
to_chat(src, "<i><span class='mentor'>Mentor-PM to-<b>[recipient]</b>: [msg]</span></i>")
log_admin("[key_name(src)]->[key_name(recipient)]: [msg]")
if(recipient.is_preference_enabled(/datum/client_preference/play_mentorhelp_ping))
recipient << 'sound/effects/mentorhelp.mp3'
for(var/client/C in GLOB.mentors)
if (C != recipient && C != src)
to_chat(C, interaction_message)
for(var/client/C in GLOB.admins)
if (C != recipient && C != src)
to_chat(C, interaction_message)

View File

@@ -0,0 +1,415 @@
/client/var/datum/mentor_help/current_mentorhelp
//
//TICKET MANAGER
//
GLOBAL_DATUM_INIT(mhelp_tickets, /datum/mentor_help_tickets, new)
/datum/mentor_help_tickets
var/list/active_tickets = list()
var/list/resolved_tickets = list()
var/obj/effect/statclick/mticket_list/astatclick = new(null, null, AHELP_ACTIVE)
var/obj/effect/statclick/mticket_list/rstatclick = new(null, null, AHELP_RESOLVED)
/datum/mentor_help_tickets/Destroy()
QDEL_LIST(active_tickets)
QDEL_LIST(resolved_tickets)
QDEL_NULL(astatclick)
QDEL_NULL(rstatclick)
return ..()
//private
/datum/mentor_help_tickets/proc/ListInsert(datum/mentor_help/new_ticket)
var/list/mticket_list
switch(new_ticket.state)
if(AHELP_ACTIVE)
mticket_list = active_tickets
if(AHELP_RESOLVED)
mticket_list = resolved_tickets
else
CRASH("Invalid ticket state: [new_ticket.state]")
var/num_closed = mticket_list.len
if(num_closed)
for(var/I in 1 to num_closed)
var/datum/mentor_help/MH = mticket_list[I]
if(MH.id > new_ticket.id)
mticket_list.Insert(I, new_ticket)
return
mticket_list += new_ticket
//opens the ticket listings, only two states here
/datum/mentor_help_tickets/proc/BrowseTickets(state)
var/list/l2b
var/title
switch(state)
if(AHELP_ACTIVE)
l2b = active_tickets
title = "Active 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_=mentorholder;mhelp_tickets=[state]'>Refresh</A><br><br>"
for(var/datum/mentor_help/MH as anything in l2b)
dat += "<span class='adminnotice'><span class='adminhelp'>Ticket #[MH.id]</span>: <A HREF='?_src_=mentorholder;mhelp=\ref[MH];mhelp_action=ticket'>[MH.initiator_ckey]: [MH.name]</A></span><br>"
usr << browse(dat.Join(), "window=mhelp_list[state];size=600x480")
//Tickets statpanel
/datum/mentor_help_tickets/proc/stat_entry()
var/num_disconnected = 0
stat("Active Tickets:", astatclick.update("[active_tickets.len]"))
for(var/datum/mentor_help/MH as anything in active_tickets)
if(MH.initiator)
stat("#[MH.id]. [MH.initiator_ckey]:", MH.statclick.update())
else
++num_disconnected
if(num_disconnected)
stat("Disconnected:", astatclick.update("[num_disconnected]"))
stat("Resolved Tickets:", rstatclick.update("[resolved_tickets.len]"))
//Reassociate still open ticket if one exists
/datum/mentor_help_tickets/proc/ClientLogin(client/C)
C.current_mentorhelp = CKey2ActiveTicket(C.ckey)
if(C.current_mentorhelp)
C.current_mentorhelp.AddInteraction("Client reconnected.")
C.current_mentorhelp.initiator = C
//Dissasociate ticket
/datum/mentor_help_tickets/proc/ClientLogout(client/C)
if(C.current_mentorhelp)
C.current_mentorhelp.AddInteraction("Client disconnected.")
C.current_mentorhelp.initiator = null
C.current_mentorhelp = null
//Get a ticket given a ckey
/datum/mentor_help_tickets/proc/CKey2ActiveTicket(ckey)
for(var/datum/admin_help/MH as anything in active_tickets)
if(MH.initiator_ckey == ckey)
return MH
//
//TICKET LIST STATCLICK
//
/obj/effect/statclick/mticket_list
var/current_state
/obj/effect/statclick/mticket_list/New(loc, name, state)
current_state = state
..()
/obj/effect/statclick/mticket_list/Click()
GLOB.mhelp_tickets.BrowseTickets(current_state)
//
//TICKET DATUM
//
/datum/mentor_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_mentorhelp
//msg is the title of the ticket: usually the ahelp text
/datum/mentor_help/New(msg, client/C)
//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 = C.ckey
initiator_key_name = key_name(initiator, FALSE, TRUE)
if(initiator.current_mentorhelp) //This is a bug
log_debug("Ticket erroneously left open by code")
initiator.current_mentorhelp.AddInteraction("Ticket erroneously left open by code")
initiator.current_mentorhelp.Resolve()
initiator.current_mentorhelp = src
statclick = new(null, src)
_interactions = list()
log_admin("Mentorhelp: [key_name(C)]: [msg]")
MessageNoRecipient(msg)
//show it to the person adminhelping too
to_chat(C, "<i><span class='mentor'>Mentor-PM to-<b>Mentors</b>: [name]</span></i>")
GLOB.mhelp_tickets.active_tickets += src
/datum/mentor_help/Destroy()
RemoveActive()
GLOB.mhelp_tickets.resolved_tickets -= src
return ..()
/datum/mentor_help/proc/AddInteraction(formatted_message)
_interactions += "[gameTimestamp()]: [formatted_message]"
//private
/datum/mentor_help/proc/ClosureLinks(ref_src)
if(!ref_src)
ref_src = "\ref[src]"
. = " (<A HREF='?_src_=mentorholder;mhelp=[ref_src];mhelp_action=resolve'>RSLVE</A>)"
//private
/datum/mentor_help/proc/LinkedReplyName(ref_src)
if(!ref_src)
ref_src = "\ref[src]"
return "<A HREF='?_src_=mentorholder;mhelp=[ref_src];mhelp_action=reply'>[initiator_ckey]</A>"
//private
/datum/mentor_help/proc/TicketHref(msg, ref_src, action = "ticket")
if(!ref_src)
ref_src = "\ref[src]"
return "<A HREF='?_src_=mentorholder;mhelp=[ref_src];mhelp_action=[action]'>[msg]</A>"
//message from the initiator without a target, all people with mentor powers will see this
/datum/mentor_help/proc/MessageNoRecipient(msg)
var/ref_src = "\ref[src]"
var/chat_msg = "<span class='notice'>(<A HREF='?_src_=mentorholder;mhelp=[ref_src];mhelp_action=escalate'>ESCALATE</A>) Ticket [TicketHref("#[id]", ref_src)]<b>: [LinkedReplyName(ref_src)]:</b> [msg]</span>"
AddInteraction("<font color='red'>[LinkedReplyName(ref_src)]: [msg]</font>")
for (var/client/C in GLOB.mentors)
if (C.is_preference_enabled(/datum/client_preference/play_mentorhelp_ping))
C << 'sound/effects/mentorhelp.mp3'
for (var/client/C in GLOB.admins)
if (C.is_preference_enabled(/datum/client_preference/play_mentorhelp_ping))
C << 'sound/effects/mentorhelp.mp3'
message_mentors(chat_msg)
//Reopen a closed ticket
/datum/mentor_help/proc/Reopen()
if(state == AHELP_ACTIVE)
to_chat(usr, "<span class='warning'>This ticket is already open.</span>")
return
if(GLOB.mhelp_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.mhelp_tickets.active_tickets += src
GLOB.mhelp_tickets.resolved_tickets -= src
switch(state)
if(AHELP_RESOLVED)
feedback_dec("mhelp_resolve")
state = AHELP_ACTIVE
closed_at = null
if(initiator)
initiator.current_mentorhelp = src
AddInteraction("<font color='purple'>Reopened by [usr.ckey]</font>")
if(initiator)
to_chat(initiator, "<span class='filter_adminlog'><font color='purple'>Ticket [TicketHref("#[id]")] was reopened by [usr.ckey].</font></span>")
var/msg = "<span class='adminhelp'>Ticket [TicketHref("#[id]")] reopened by [usr.ckey].</span>"
message_mentors(msg)
log_admin(msg)
feedback_inc("mhelp_reopen")
TicketPanel() //can only be done from here, so refresh it
//private
/datum/mentor_help/proc/RemoveActive()
if(state != AHELP_ACTIVE)
return
closed_at = world.time
QDEL_NULL(statclick)
GLOB.mhelp_tickets.active_tickets -= src
if(initiator && initiator.current_mentorhelp == src)
initiator.current_mentorhelp = null
//Mark open ticket as resolved/legitimate, returns mentorhelp verb
/datum/mentor_help/proc/Resolve(silent = FALSE)
if(state != AHELP_ACTIVE)
return
RemoveActive()
state = AHELP_RESOLVED
GLOB.mhelp_tickets.ListInsert(src)
AddInteraction("<span class='filter_adminlog'><font color='green'>Resolved by [usr.ckey].</font></span>")
if(initiator)
to_chat(initiator, "<span class='filter_adminlog'><font color='green'>Ticket [TicketHref("#[id]")] was marked resolved by [usr.ckey].</font></span>")
if(!silent)
feedback_inc("mhelp_resolve")
var/msg = "Ticket [TicketHref("#[id]")] resolved by [usr.ckey]"
message_mentors(msg)
log_admin(msg)
//Show the ticket panel
/datum/mentor_help/proc/TicketPanel()
var/list/dat = list("<html><head><title>Ticket #[id]</title></head>")
var/ref_src = "\ref[src]"
dat += "<h4>Mentor 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>"
else
dat += "UNKNOWN"
dat += "</b>[GLOB.TAB][TicketHref("Refresh", ref_src)]"
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> [Context(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=mhelp[id];size=620x480")
//Kick ticket to admins
/datum/mentor_help/proc/Escalate()
if(tgui_alert(usr, "Really escalate this ticket to admins? No mentors will ever be able to interact with it again if you do.","Escalate",list("Yes","No")) != "Yes")
return
if (src.initiator == null) // You can't escalate a mentorhelp of someone who's logged out because it won't create the adminhelp properly
to_chat(usr, "<span class='pm warning'>Error: client not found, unable to escalate.</span>")
return
var/datum/admin_help/AH = new /datum/admin_help(src.name, src.initiator, FALSE)
message_mentors("[usr.ckey] escalated Ticket [TicketHref("#[id]")]")
log_admin("[key_name(usr)] escalated mentorhelp [src.name]")
to_chat(src.initiator, "<span class='mentor'>[usr.ckey] escalated your mentorhelp to admins.</span>")
AH._interactions = src._interactions
GLOB.mhelp_tickets.active_tickets -= src
GLOB.mhelp_tickets.resolved_tickets -= src
qdel(src)
/datum/mentor_help/proc/Context(ref_src)
if(!ref_src)
ref_src = "\ref[src]"
if(state == AHELP_ACTIVE)
. += ClosureLinks(ref_src)
if(state != AHELP_RESOLVED)
. += " (<A HREF='?_src_=mentorholder;mhelp=[ref_src];mhelp_action=escalate'>ESCALATE</A>)"
//Forwarded action from admin/Topic OR mentor/Topic depending on which rank the caller has
/datum/mentor_help/proc/Action(action)
switch(action)
if("ticket")
TicketPanel()
if("reply")
usr.client.cmd_mhelp_reply(initiator)
if("resolve")
Resolve()
if("reopen")
Reopen()
if("escalate")
Escalate()
//
// TICKET STATCLICK
//
/obj/effect/statclick/mhelp
var/datum/mentor_help/mhelp_datum
/obj/effect/statclick/mhelp/New(loc, datum/mentor_help/MH)
mhelp_datum = MH
..(loc)
/obj/effect/statclick/mhelp/update()
return ..(mhelp_datum.name)
/obj/effect/statclick/mhelp/Click()
mhelp_datum.TicketPanel()
/obj/effect/statclick/mhelp/Destroy()
mhelp_datum = null
return ..()
//
// CLIENT PROCS
//
/client/verb/mentorhelp(msg as text)
set category = "Admin"
set name = "Mentorhelp"
if(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: Mentor-PM: You cannot send adminhelps (Muted).</span>")
return
if(handle_spam_prevention(msg,MUTE_ADMINHELP))
return
if(!msg)
return
//remove out adminhelp verb temporarily to prevent spamming of admins.
src.verbs -= /client/verb/mentorhelp
spawn(600)
src.verbs += /client/verb/mentorhelp // 1 minute cool-down for mentorhelps
feedback_add_details("admin_verb","Mentorhelp") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
if(current_mentorhelp)
if(tgui_alert(usr, "You already have a ticket open. Is this for the same issue?","Duplicate?",list("Yes","No")) != "No")
if(current_mentorhelp)
log_admin("Mentorhelp: [key_name(src)]: [msg]")
current_mentorhelp.MessageNoRecipient(msg)
to_chat(usr, "<span class='adminnotice'><span class='mentor'>Mentor-PM to-<b>Mentors</b>: [msg]</span></span>")
return
else
to_chat(usr, "<span class='warning'>Ticket not found, creating new one...</span>")
else
current_mentorhelp.AddInteraction("[usr.ckey] opened a new ticket.")
current_mentorhelp.Resolve()
new /datum/mentor_help(msg, src, FALSE)
//admin proc
/client/proc/cmd_mentor_ticket_panel()
set name = "Mentor Ticket List"
set category = "Admin"
var/browse_to
switch(tgui_input_list(usr, "Display which ticket list?", "List Choice", list("Active Tickets", "Resolved Tickets")))
if("Active Tickets")
browse_to = AHELP_ACTIVE
if("Resolved Tickets")
browse_to = AHELP_RESOLVED
else
return
GLOB.mhelp_tickets.BrowseTickets(browse_to)
/proc/message_mentors(var/msg)
msg = "<span class='mentor_channel'><span class='prefix'>Mentor:</span> <span class=\"message\">[msg]</span></span>"
for(var/client/C in GLOB.mentors)
to_chat(C, msg)
for(var/client/C in GLOB.admins)
to_chat(C, msg)