mirror of
https://github.com/CHOMPStation2/CHOMPStation2.git
synced 2025-12-09 16:12:17 +00:00
[MIRROR] up ports a bunch of TGS commands (#11173)
Co-authored-by: Kashargul <144968721+Kashargul@users.noreply.github.com>
This commit is contained in:
committed by
GitHub
parent
42b68b856b
commit
0160eb3e68
@@ -46,7 +46,7 @@
|
||||
#define R_DEFAULT R_NONE
|
||||
|
||||
#define R_EVERYTHING (1<<17)-1 //the sum of all other rank permissions, used for +EVERYTHING
|
||||
#define R_HOLDER ((R_EVERYTHING) & (~R_MENTOR))
|
||||
#define R_HOLDER ((R_EVERYTHING) & (~(R_MENTOR | R_STEALTH)))
|
||||
|
||||
#define SMITE_BREAKLEGS "Break Legs"
|
||||
#define SMITE_BLUESPACEARTILLERY "Bluespace Artillery"
|
||||
|
||||
@@ -432,7 +432,7 @@ so as to remain in compliance with the most up-to-date laws."
|
||||
name = "Admin Chat Request"
|
||||
desc = "A Administrator would like to chat with you. \
|
||||
Click here to begin."
|
||||
icon_state = "32x32"
|
||||
icon_state = "nt_logo"
|
||||
|
||||
/obj/screen/alert/open_ticket/Click()
|
||||
if(!usr || !usr.client) return
|
||||
|
||||
@@ -744,6 +744,45 @@
|
||||
/datum/config_entry/flag/discord_ahelps_disabled
|
||||
default = FALSE
|
||||
|
||||
/// So, nodebot is a supplement to the TGS discord bot pretty much. For things likes faxes and the manifest it's very helpful because it's able to render html into an image and post it.
|
||||
/datum/config_entry/flag/nodebot_enabled
|
||||
default = FALSE
|
||||
|
||||
/// We need to print the manifest to this location so nodebot can render it to chat.
|
||||
/// NOTE: TO BE REPLACED BY BETTER CODE FOR FETCHING MANIFEST
|
||||
/datum/config_entry/string/nodebot_location
|
||||
|
||||
/datum/config_entry/string/fax_channel_tag
|
||||
|
||||
/datum/config_entry/string/role_request_channel_tag
|
||||
|
||||
/// These are for the role request TGS discord bot. Role IDs to ping.
|
||||
/datum/config_entry/string/role_request_id_command
|
||||
|
||||
/datum/config_entry/string/role_request_id_security
|
||||
|
||||
/datum/config_entry/string/role_request_id_engineering
|
||||
|
||||
/datum/config_entry/string/role_request_id_medical
|
||||
|
||||
/datum/config_entry/string/role_request_id_research
|
||||
|
||||
/datum/config_entry/string/role_request_id_supply
|
||||
|
||||
/datum/config_entry/string/role_request_id_service
|
||||
|
||||
/datum/config_entry/string/role_request_id_expedition
|
||||
|
||||
/datum/config_entry/string/role_request_id_silicon
|
||||
|
||||
/// Only turn this on if you're not using the nodebot.
|
||||
/datum/config_entry/flag/discord_faxes_autoprint
|
||||
default = FALSE
|
||||
|
||||
/// Turn this off if you don't want the TGS bot sending you messages whenever a fax is sent to central.
|
||||
/datum/config_entry/flag/discord_faxes_disabled
|
||||
default = FALSE
|
||||
|
||||
/// Turn this on if you want all admin-PMs to go to be sent to discord, and not only the first message of a ticket.
|
||||
/datum/config_entry/flag/discord_ahelps_all
|
||||
default = FALSE
|
||||
|
||||
@@ -61,5 +61,5 @@ SUBSYSTEM_DEF(inactivity)
|
||||
return ..()
|
||||
|
||||
/datum/controller/subsystem/inactivity/proc/can_kick(var/client/C)
|
||||
if(C.holder) return FALSE //VOREStation Add - Don't kick admins.
|
||||
if(check_rights_for(C, R_HOLDER|R_MENTOR)) return FALSE //VOREStation Add - Don't kick admins.
|
||||
return TRUE
|
||||
|
||||
@@ -199,8 +199,11 @@ var/list/runechat_image_cache = list()
|
||||
|
||||
// Translate any existing messages upwards, apply exponential decay factors to timers
|
||||
message_loc = target.runechat_holder(src)
|
||||
if(!owned_by)
|
||||
qdel(src)
|
||||
return
|
||||
RegisterSignal(message_loc, COMSIG_PARENT_QDELETING, PROC_REF(qdel_self))
|
||||
if(owned_by && owned_by.seen_messages)
|
||||
if(owned_by.seen_messages)
|
||||
var/idx = 1
|
||||
var/combined_height = approx_lines
|
||||
for(var/datum/chatmessage/m as anything in owned_by.seen_messages[message_loc])
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
var/static/list/locked = list()
|
||||
|
||||
|
||||
/datum/datacore/proc/get_manifest(monochrome, OOC,var/snowflake = FALSE) //CHOMPStation Edit
|
||||
/datum/datacore/proc/get_manifest(monochrome, OOC,var/snowflake = FALSE)
|
||||
var/list/heads = new()
|
||||
var/list/sec = new()
|
||||
var/list/eng = new()
|
||||
|
||||
@@ -116,5 +116,5 @@
|
||||
peeb += dat
|
||||
peeb += span_notice("For more detailed information on the patient's condition, utilize a body scanner at the closest medical bay.")
|
||||
|
||||
user.show_message(peeb, 1)
|
||||
user.show_message(peeb, 1)
|
||||
//CHOMPedit end.
|
||||
|
||||
@@ -867,7 +867,7 @@
|
||||
message_admins(span_blue("[usr.client.ckey] has banned [M.ckey].\nReason: [reason]\nThis will be removed in [mins] minutes."))
|
||||
var/datum/ticket/T = M.client ? M.client.current_ticket : null
|
||||
if(T)
|
||||
T.Resolve()
|
||||
T.Resolve(usr)
|
||||
qdel(M.client)
|
||||
// CHOMPedit End
|
||||
//qdel(M) // See no reason why to delete mob. Important stuff can be lost. And ban can be lifted before round ends.
|
||||
@@ -896,7 +896,7 @@
|
||||
DB_ban_record(BANTYPE_PERMA, M, -1, reason)
|
||||
var/datum/ticket/T = M.client ? M.client.current_ticket : null
|
||||
if(T)
|
||||
T.Resolve()
|
||||
T.Resolve(usr)
|
||||
qdel(M.client)
|
||||
//qdel(M)
|
||||
if("Cancel")
|
||||
|
||||
@@ -213,8 +213,11 @@
|
||||
if(!istype(target))
|
||||
return
|
||||
|
||||
var/real_user = user ? user : usr
|
||||
var/user_name = real_user ? key_name(real_user) : "Remotely (Discord)"
|
||||
|
||||
to_chat(target,"You've been hit by bluespace artillery!")
|
||||
log_and_message_admins("has been hit by Bluespace Artillery fired by [key_name(user ? user : usr)]", target)
|
||||
log_and_message_admins("has been hit by Bluespace Artillery fired by [user_name]", target)
|
||||
|
||||
target.setMoveCooldown(2 SECONDS)
|
||||
|
||||
|
||||
@@ -213,7 +213,7 @@ var/list/gear_datums = list()
|
||||
return TOPIC_REFRESH_UPDATE_PREVIEW
|
||||
|
||||
if("clear_loadout")
|
||||
active_gear_list.Cut()
|
||||
active_gear_list?.Cut()
|
||||
return TOPIC_REFRESH_UPDATE_PREVIEW
|
||||
|
||||
if("copy_loadout")
|
||||
|
||||
@@ -153,9 +153,12 @@ vorestation edit end */
|
||||
return
|
||||
|
||||
to_chat(user, span_notice("The crate is locked with a Deca-code lock."))
|
||||
var/input = tgui_input_text(user, "Enter [codelen] digits. All digits must be unique.", "Deca-Code Lock", "")
|
||||
var/input = tgui_input_text(user, "Enter [codelen] digits. All digits must be unique.", "Deca-Code Lock", "", codelen)
|
||||
if(!Adjacent(user))
|
||||
return
|
||||
if(input == null)
|
||||
to_chat(user, span_notice("You leave the crate alone."))
|
||||
return
|
||||
var/list/sanitised = list()
|
||||
var/sanitycheck = 1
|
||||
for(var/i=1,i<=length(input),i++) //put the guess into a list
|
||||
@@ -165,9 +168,11 @@ vorestation edit end */
|
||||
if(sanitised[i] == sanitised[j])
|
||||
sanitycheck = null //if a digit is repeated, reject the input
|
||||
|
||||
if(input == null || sanitycheck == null || length(input) != codelen)
|
||||
to_chat(user, span_notice("You leave the crate alone."))
|
||||
else if(check_input(input))
|
||||
if(sanitycheck == null || length(input) != codelen)
|
||||
to_chat(user, span_notice("You aren't sure this input is a good idea."))
|
||||
return
|
||||
|
||||
if(check_input(input))
|
||||
to_chat(user, span_notice("The crate unlocks!"))
|
||||
playsound(src, 'sound/machines/lockreset.ogg', 50, 1)
|
||||
set_locked(0)
|
||||
|
||||
@@ -6,7 +6,8 @@
|
||||
update_client_z(null)
|
||||
log_access_out(src)
|
||||
unset_machine()
|
||||
if(GLOB.admin_datums[src.ckey] && check_rights(R_HOLDER, FALSE))
|
||||
var/datum/admins/is_admin = GLOB.admin_datums[src.ckey]
|
||||
if(is_admin && is_admin.check_for_rights(R_HOLDER))
|
||||
message_admins("Staff logout: [key_name(src)]") // Staff logout notice displays no matter what
|
||||
if (ticker && ticker.current_state == GAME_STATE_PLAYING) //Only report this stuff if we are currently playing.
|
||||
var/admins_number = GLOB.admins.len
|
||||
|
||||
@@ -1,130 +0,0 @@
|
||||
/datum/tgs_chat_command/sharktest
|
||||
name = "flip"
|
||||
help_text = "babies first TGS command"
|
||||
admin_only = FALSE
|
||||
|
||||
/datum/tgs_chat_command/sharktest/Run(datum/tgs_chat_user/sender, params)
|
||||
var/x
|
||||
if(params != "tails" && params != "heads")
|
||||
return "```You need to guess!\n either heads or tails!```"
|
||||
if(prob(50))
|
||||
if(params == "tails")
|
||||
x = "correct"
|
||||
else
|
||||
x = "wrong"
|
||||
return "```Tails. [x]!```"
|
||||
|
||||
if(params == "tails")
|
||||
x = "wrong"
|
||||
else
|
||||
x = "correct"
|
||||
return "```Heads. [x]!```"
|
||||
|
||||
/datum/tgs_chat_command/sharktest/alias
|
||||
name = "coin"
|
||||
|
||||
/datum/tgs_chat_command/manifest
|
||||
name = "manifest"
|
||||
help_text = "Shows the current crew manifest"
|
||||
admin_only = FALSE
|
||||
|
||||
/proc/ManifestToHtml()
|
||||
var/html = ""
|
||||
if(GLOB.data_core)
|
||||
html = GLOB.data_core.get_manifest(FALSE,TRUE,snowflake = TRUE)
|
||||
else
|
||||
html = span_bold("ERROR: NO DATACORE") //Could make the error more fancy later
|
||||
rustg_file_write(html,"[CONFIG_GET(string/nodebot_location)]\\html.html")
|
||||
|
||||
/datum/tgs_chat_command/manifest/Run(datum/tgs_chat_user/sender, params)
|
||||
if(CONFIG_GET(flag/nodebot_enabled))
|
||||
ManifestToHtml()
|
||||
return "http://manifest.chompstation13.net/"
|
||||
else
|
||||
var/outp = "Crew Manifest:"
|
||||
var/list/total = list()
|
||||
if(GLOB.data_core)
|
||||
GLOB.data_core.get_manifest_list()
|
||||
for(var/list/item in GLOB.PDA_Manifest)
|
||||
outp += "\n__**[item["cat"]]:**__"
|
||||
for(var/list/person in item["elems"])
|
||||
total |= person
|
||||
outp += "\n[person["name"]] -:- [person["rank"]]"
|
||||
|
||||
return "**Total crew members:** [total.len]\n" + outp
|
||||
|
||||
|
||||
/datum/tgs_chat_command/discordping
|
||||
name = "discordping"
|
||||
help_text = "Pings the discord associated with the associated ckey"
|
||||
admin_only = TRUE
|
||||
|
||||
/datum/tgs_chat_command/discordping/Run(datum/tgs_chat_user/sender, params)
|
||||
var/key_to_find = "[ckey(params)]"
|
||||
|
||||
// They didn't provide anything worth looking up.
|
||||
if(!length(key_to_find))
|
||||
return "[sender.friendly_name], you need to provide a Byond username at the end of the command. It can be in 'key' format (with spaces and characters) or 'ckey' format (without spaces or special characters)."
|
||||
|
||||
var/datum/db_query/query = SSdbcore.NewQuery("SELECT discord_id FROM erro_player WHERE ckey = :t_ckey",list("t_ckey" = key_to_find))
|
||||
query.Execute()
|
||||
|
||||
if(!query.NextRow())
|
||||
qdel(query)
|
||||
return "[sender.friendly_name], the server's database is either not responding or there's no such ckey in the database."
|
||||
|
||||
if(!query.item[1])
|
||||
qdel(query)
|
||||
return "[sender.friendly_name], [key_to_find] is in the database, but has no discord ID associated with them."
|
||||
var/discord_id = query.item[1]
|
||||
qdel(query)
|
||||
return "[key_to_find]'s discord is <@[discord_id]>"
|
||||
|
||||
/datum/tgs_chat_command/getkey
|
||||
name = "getkey"
|
||||
help_text = "Finds the key associated with a discord id"
|
||||
admin_only = TRUE
|
||||
|
||||
/datum/tgs_chat_command/getkey/Run(datum/tgs_chat_user/sender, params)
|
||||
if(!params)
|
||||
return "[sender.friendly_name], you need to provide a Discord ID at the end of the command. To obtain someone's Discord ID, you need to enable developer mode on discord, and then right click on their name and click Copy ID."
|
||||
|
||||
var/datum/db_query/query = SSdbcore.NewQuery("SELECT ckey FROM erro_player WHERE discord_id = :t_discord", list("t_discord"=params))
|
||||
query.Execute()
|
||||
|
||||
if(!query.NextRow())
|
||||
qdel(query)
|
||||
return "[sender.friendly_name], the server's database is either not responding or there's no such Discord ID in the database."
|
||||
|
||||
var/user_key = query.item[1]
|
||||
qdel(query)
|
||||
return "<@[params]>'s ckey is [user_key]"
|
||||
|
||||
//modded fax code to properly handle non existing files before accessing the void
|
||||
/datum/tgs_chat_command/readfax/Run(sender, params)
|
||||
var/list/all_params = splittext(params, " ")
|
||||
var/faxid = all_params[1]
|
||||
if(!all_params[1] || !fexists("[CONFIG_GET(string/fax_export_dir)]/fax_[faxid].html"))
|
||||
return "I’m sorry Dave, I’m afraid I can’t do that"
|
||||
var/faxmsg = return_file_text("[CONFIG_GET(string/fax_export_dir)]/fax_[faxid].html")
|
||||
return "FAX: ```[strip_html_properly(faxmsg)]```"
|
||||
|
||||
/datum/tgs_chat_command/vore
|
||||
name = "vore"
|
||||
help_text = "vore"
|
||||
admin_only = FALSE
|
||||
|
||||
/datum/tgs_chat_command/vore/Run(datum/tgs_chat_user/sender, params)
|
||||
return "vore"
|
||||
|
||||
// - FAX
|
||||
/datum/tgs_chat_command/readfax
|
||||
name = "readfax"
|
||||
help_text = "Reads a fax with specified faxid"
|
||||
admin_only = TRUE
|
||||
|
||||
/datum/tgs_chat_command/readfax/Run(sender, params)
|
||||
var/list/all_params = splittext(params, " ")
|
||||
var/faxid = all_params[1]
|
||||
var/faxmsg = return_file_text("[CONFIG_GET(string/fax_export_dir)]/fax_[faxid].html")
|
||||
return "FAX: ```[strip_html_properly(faxmsg)]```"
|
||||
@@ -138,3 +138,243 @@ GLOBAL_LIST_EMPTY(pending_discord_registrations)
|
||||
GLOB.pending_discord_registrations[GLOB.pending_discord_registrations.len] = list("ckey" = key_to_find, "id" = sender.id, "time" = world.realtime)
|
||||
|
||||
return "[sender.friendly_name], I've sent you a message in-game. Please verify your username there to complete your registration within 10 minutes."
|
||||
|
||||
// Coin flip
|
||||
/datum/tgs_chat_command/coinflip
|
||||
name = "flip"
|
||||
help_text = "babies first TGS command"
|
||||
admin_only = FALSE
|
||||
|
||||
/datum/tgs_chat_command/coinflip/Run(datum/tgs_chat_user/sender, params)
|
||||
var/x
|
||||
if(params != "tails" && params != "heads")
|
||||
return "```You need to guess!\n either heads or tails!```"
|
||||
if(prob(50))
|
||||
if(params == "tails")
|
||||
x = "correct"
|
||||
else
|
||||
x = "wrong"
|
||||
return "```Tails. [x]!```"
|
||||
|
||||
if(params == "tails")
|
||||
x = "wrong"
|
||||
else
|
||||
x = "correct"
|
||||
return "```Heads. [x]!```"
|
||||
|
||||
/datum/tgs_chat_command/coinflip/alias
|
||||
name = "coin"
|
||||
|
||||
// Manifest
|
||||
/datum/tgs_chat_command/manifest
|
||||
name = "manifest"
|
||||
help_text = "Shows the current crew manifest"
|
||||
admin_only = FALSE
|
||||
|
||||
/proc/ManifestToHtml()
|
||||
var/html = ""
|
||||
if(GLOB.data_core)
|
||||
html = GLOB.data_core.get_manifest(FALSE,TRUE,snowflake = TRUE)
|
||||
else
|
||||
html = span_bold("ERROR: NO DATACORE") //Could make the error more fancy later
|
||||
rustg_file_write(html,"[CONFIG_GET(string/nodebot_location)]\\html.html")
|
||||
|
||||
/datum/tgs_chat_command/manifest/Run(datum/tgs_chat_user/sender, params)
|
||||
if(CONFIG_GET(flag/nodebot_enabled))
|
||||
ManifestToHtml()
|
||||
return "http://manifest.chompstation13.net/"
|
||||
else
|
||||
var/outp = "Crew Manifest:"
|
||||
var/list/total = list()
|
||||
if(GLOB.data_core)
|
||||
GLOB.data_core.get_manifest_list()
|
||||
for(var/list/item in GLOB.PDA_Manifest)
|
||||
outp += "\n__**[item["cat"]]:**__"
|
||||
for(var/list/person in item["elems"])
|
||||
total |= person
|
||||
outp += "\n[person["name"]] -:- [person["rank"]]"
|
||||
|
||||
return "**Total crew members:** [total.len]\n" + outp
|
||||
|
||||
// Discord ping
|
||||
/datum/tgs_chat_command/discordping
|
||||
name = "discordping"
|
||||
help_text = "Pings the discord associated with the associated ckey"
|
||||
admin_only = TRUE
|
||||
|
||||
/datum/tgs_chat_command/discordping/Run(datum/tgs_chat_user/sender, params)
|
||||
var/key_to_find = "[ckey(params)]"
|
||||
|
||||
// They didn't provide anything worth looking up.
|
||||
if(!length(key_to_find))
|
||||
return "[sender.friendly_name], you need to provide a Byond username at the end of the command. It can be in 'key' format (with spaces and characters) or 'ckey' format (without spaces or special characters)."
|
||||
|
||||
var/datum/db_query/query = SSdbcore.NewQuery("SELECT discord_id FROM erro_player WHERE ckey = :t_ckey",list("t_ckey" = key_to_find))
|
||||
query.Execute()
|
||||
|
||||
if(!query.NextRow())
|
||||
qdel(query)
|
||||
return "[sender.friendly_name], the server's database is either not responding or there's no such ckey in the database."
|
||||
|
||||
if(!query.item[1])
|
||||
qdel(query)
|
||||
return "[sender.friendly_name], [key_to_find] is in the database, but has no discord ID associated with them."
|
||||
var/discord_id = query.item[1]
|
||||
qdel(query)
|
||||
return "[key_to_find]'s discord is <@[discord_id]>"
|
||||
|
||||
/datum/tgs_chat_command/getkey
|
||||
name = "getkey"
|
||||
help_text = "Finds the key associated with a discord id"
|
||||
admin_only = TRUE
|
||||
|
||||
/datum/tgs_chat_command/getkey/Run(datum/tgs_chat_user/sender, params)
|
||||
if(!params)
|
||||
return "[sender.friendly_name], you need to provide a Discord ID at the end of the command. To obtain someone's Discord ID, you need to enable developer mode on discord, and then right click on their name and click Copy ID."
|
||||
|
||||
var/datum/db_query/query = SSdbcore.NewQuery("SELECT ckey FROM erro_player WHERE discord_id = :t_discord", list("t_discord"=params))
|
||||
query.Execute()
|
||||
|
||||
if(!query.NextRow())
|
||||
qdel(query)
|
||||
return "[sender.friendly_name], the server's database is either not responding or there's no such Discord ID in the database."
|
||||
|
||||
var/user_key = query.item[1]
|
||||
qdel(query)
|
||||
return "<@[params]>'s ckey is [user_key]"
|
||||
|
||||
/datum/tgs_chat_command/vore
|
||||
name = "vore"
|
||||
help_text = "vore"
|
||||
admin_only = FALSE
|
||||
|
||||
/datum/tgs_chat_command/vore/Run(datum/tgs_chat_user/sender, params)
|
||||
return "vore"
|
||||
|
||||
// - FAX
|
||||
/datum/tgs_chat_command/readfax
|
||||
name = "readfax"
|
||||
help_text = "Reads a fax with specified faxid"
|
||||
admin_only = TRUE
|
||||
|
||||
/datum/tgs_chat_command/readfax/Run(sender, params)
|
||||
var/list/all_params = splittext(params, " ")
|
||||
if(!LAZYLEN(all_params))
|
||||
return "```Invalid command, missing fax id```"
|
||||
var/faxid = all_params[1]
|
||||
if(!all_params[1] || !fexists("[CONFIG_GET(string/fax_export_dir)]/fax_[faxid].html"))
|
||||
return "I’m sorry Dave, I’m afraid I can’t do that"
|
||||
var/faxmsg = return_file_text("[CONFIG_GET(string/fax_export_dir)]/fax_[faxid].html")
|
||||
return "FAX: ```[strip_html_properly(faxmsg)]```"
|
||||
|
||||
// Reply to admin tickets
|
||||
/datum/tgs_chat_command/ticketreply
|
||||
name = "ticket"
|
||||
help_text = "allows admins to reply to open tickets. Usage: ticket id \[reply, reject, icissue, close, resolve, handle, reopen\] message"
|
||||
admin_only = TRUE
|
||||
|
||||
/datum/tgs_chat_command/ticketreply/Run(datum/tgs_chat_user/sender, params)
|
||||
var/list/message_as_list = splittext(params, " ")
|
||||
if(!LAZYLEN(message_as_list))
|
||||
return "```Invalid command usage: ticket id \[reply, reject, icissue, close, resolve, handle, reopen\] message```"
|
||||
|
||||
var/id = text2num(message_as_list[1])
|
||||
if(!isnum(id))
|
||||
return "```First param must be the ticket ID.```"
|
||||
message_as_list.Cut(1, 2)
|
||||
if(!LAZYLEN(message_as_list))
|
||||
return "```Invalid command usage: ticket id \[reply, reject, icissue, close, resolve, handle, reopen\] message```"
|
||||
|
||||
var/action = message_as_list[1]
|
||||
if(isnum(action))
|
||||
return "```Second param must be the action type.```"
|
||||
message_as_list.Cut(1, 2)
|
||||
|
||||
if(!LAZYLEN(message_as_list) && action == "reply")
|
||||
return "```Invalid command usage: ticket id \[reply, reject, icissue, close, resolve, handle, reopen\] message```"
|
||||
|
||||
if(!(action in list("reply", "reject", "icissue", "close", "resolve", "handle", "reopen")))
|
||||
return "```Invalid command usage: ticket id \[reply, reject, icissue, close, resolve, handle, reopen\] message```"
|
||||
|
||||
var/text_message
|
||||
if(LAZYLEN(message_as_list))
|
||||
text_message = message_as_list.Join(" ")
|
||||
|
||||
var/datum/ticket/found
|
||||
if(action == "reopen")
|
||||
for(var/datum/ticket/ticket in GLOB.tickets.closed_tickets)
|
||||
if(ticket.id == id)
|
||||
found = ticket
|
||||
if(!found)
|
||||
return "```Ticket with id #[id] was not found in closed tickets!```"
|
||||
else
|
||||
for(var/datum/ticket/ticket in GLOB.tickets.active_tickets)
|
||||
if(ticket.id == id)
|
||||
found = ticket
|
||||
if(!found)
|
||||
return "```Ticket with id #[id] was not found in active tickets!```"
|
||||
|
||||
if(text_message)
|
||||
to_chat(found.initiator, span_admin_pm_warning("Admin PM from-" + span_bold("Discord Relay") + ": [text_message]"))
|
||||
found.AddInteraction("Discord Relay: [text_message]")
|
||||
switch(action)
|
||||
if("reject")
|
||||
found.Reject("Remote (Discord)")
|
||||
if("icissue")
|
||||
found.ICIssue("Remote (Discord)")
|
||||
if("close")
|
||||
found.Close("Remote (Discord)")
|
||||
if("resolve")
|
||||
found.Resolve("Remote (Discord)")
|
||||
if("handle")
|
||||
found.HandleIssue("Remote (Discord)")
|
||||
if("reopen")
|
||||
found.Reopen("Remote (Discord)")
|
||||
return "Ticket command ([action]) sent!"
|
||||
|
||||
// Remote smite
|
||||
/datum/tgs_chat_command/remote_smite
|
||||
name = "smite"
|
||||
help_text = "allows admins to remotely smite players. Usage: smite \[bsa, lightning, pie, gib, dust\] name"
|
||||
admin_only = TRUE
|
||||
|
||||
/datum/tgs_chat_command/remote_smite/Run(datum/tgs_chat_user/sender, params)
|
||||
var/list/message_as_list = splittext(params, " ")
|
||||
if(!LAZYLEN(message_as_list))
|
||||
return "```Invalid command usage: smite \[bsa, lightning, pie, gib, dust\] name```"
|
||||
var/smite_name = message_as_list[1]
|
||||
if(!istext(smite_name))
|
||||
return "```First param must be the smite name.```"
|
||||
|
||||
message_as_list.Cut(1, 2)
|
||||
if(!LAZYLEN(message_as_list))
|
||||
return "```Invalid command usage: smite \[bsa, lightning, pie, gib, dust\] name```"
|
||||
|
||||
var/player_name = message_as_list.Join(" ")
|
||||
var/mob/living/real_target
|
||||
for(var/mob/living/target in player_list)
|
||||
if(target.real_name == player_name)
|
||||
real_target = target
|
||||
break
|
||||
|
||||
if(!real_target)
|
||||
return "Smite [smite_name] failed to find player ([player_name]), validate their name and try again."
|
||||
|
||||
switch(smite_name)
|
||||
if("bsa")
|
||||
bluespace_artillery(real_target)
|
||||
if("lightning")
|
||||
var/turf/T = get_step(get_step(real_target, NORTH), NORTH)
|
||||
T.Beam(real_target, icon_state="lightning[rand(1,12)]", time = 5)
|
||||
real_target.electrocute_act(75,def_zone = BP_HEAD)
|
||||
real_target.visible_message(span_danger("[real_target] is struck by lightning!"))
|
||||
if("pie")
|
||||
new/obj/effect/decal/cleanable/pie_smudge(get_turf(real_target))
|
||||
playsound(real_target, 'sound/effects/slime_squish.ogg', 100, 1, get_rand_frequency(), falloff = 5)
|
||||
real_target.Weaken(1)
|
||||
real_target.visible_message(span_danger("[real_target] is struck by pie!"))
|
||||
if("gib")
|
||||
real_target.gib()
|
||||
if("dust")
|
||||
real_target.dust()
|
||||
return "Smite [smite_name] sent!"
|
||||
|
||||
@@ -7,7 +7,6 @@
|
||||
GLOBAL_DATUM_INIT(tgui_ticket_state, /datum/tgui_state/ticket_state, new)
|
||||
|
||||
/datum/tgui_state/ticket_state/can_use_topic(src_object, mob/user)
|
||||
//if (user.client.current_ticket)
|
||||
// return STATUS_INTERACTIVE
|
||||
//return STATUS_CLOSE
|
||||
return STATUS_INTERACTIVE
|
||||
if(user.client.current_ticket)
|
||||
return STATUS_INTERACTIVE
|
||||
return STATUS_CLOSE
|
||||
|
||||
@@ -36,7 +36,7 @@
|
||||
to_chat(src, span_warning("Ticket not found, creating new one..."))
|
||||
else
|
||||
current_ticket.AddInteraction("[usr.ckey] opened a new ticket.")
|
||||
current_ticket.Resolve()
|
||||
current_ticket.Resolve(usr)
|
||||
|
||||
new /datum/ticket(msg, src, FALSE, 0)
|
||||
|
||||
@@ -116,7 +116,7 @@ ADMIN_VERB(cmd_mentor_ticket_panel, (R_ADMIN|R_SERVER|R_MOD|R_MENTOR), "Mentor T
|
||||
to_chat(src, span_warning("Ticket not found, creating new one..."))
|
||||
else if(current_ticket)
|
||||
current_ticket.AddInteraction("[key_name_admin(usr)] opened a new ticket.")
|
||||
current_ticket.Close()
|
||||
current_ticket.Close(usr)
|
||||
|
||||
new /datum/ticket(msg, src, FALSE, 1)
|
||||
|
||||
|
||||
@@ -162,14 +162,14 @@ GLOBAL_DATUM_INIT(tickets, /datum/tickets, new)
|
||||
if(C.current_ticket)
|
||||
C.current_ticket.AddInteraction("Client reconnected.")
|
||||
C.current_ticket.initiator = C
|
||||
// C.current_ticket.initiator.mob.throw_alert("open ticket", /obj/screen/alert/open_ticket) // Uncomment this line to enable player-side ticket ui
|
||||
C.current_ticket.initiator.mob.throw_alert("open ticket", /obj/screen/alert/open_ticket)
|
||||
|
||||
//Dissasociate ticket
|
||||
/datum/tickets/proc/ClientLogout(client/C)
|
||||
if(C.current_ticket)
|
||||
var/datum/ticket/T = C.current_ticket
|
||||
T.AddInteraction("Client disconnected.")
|
||||
// T.initiator.mob.clear_alert("open ticket") // Uncomment this line to enable player-side ticket ui
|
||||
T.initiator.mob.clear_alert("open ticket")
|
||||
T.initiator = null
|
||||
T = null
|
||||
|
||||
@@ -227,6 +227,7 @@ INITIALIZE_IMMEDIATE(/obj/effect/statclick/ticket_list)
|
||||
var/closed_at
|
||||
|
||||
var/client/initiator //semi-misnomer, it's the person who ahelped/was bwoinked
|
||||
var/datum/weakref/handler_ref
|
||||
var/handler = "/Unassigned\\" // The admin handling the ticket
|
||||
var/initiator_ckey
|
||||
var/initiator_key_name
|
||||
@@ -287,7 +288,7 @@ INITIALIZE_IMMEDIATE(/obj/effect/statclick/ticket_list)
|
||||
if(initiator.current_ticket) //This is a bug
|
||||
log_debug("Multiple ahelp current_tickets")
|
||||
initiator.current_ticket.AddInteraction("Ticket erroneously left open by code")
|
||||
initiator.current_ticket.Close()
|
||||
initiator.current_ticket.Close(usr)
|
||||
initiator.current_ticket = src
|
||||
|
||||
var/parsed_message = keywords_lookup(msg)
|
||||
@@ -340,12 +341,13 @@ INITIALIZE_IMMEDIATE(/obj/effect/statclick/ticket_list)
|
||||
//TC.T = src
|
||||
//TC.tgui_interact(C.mob)
|
||||
|
||||
// C.mob.throw_alert("open ticket", /obj/screen/alert/open_ticket) // Uncomment this line to enable player-side ticket ui
|
||||
C.mob.throw_alert("open ticket", /obj/screen/alert/open_ticket)
|
||||
|
||||
/datum/ticket/Destroy()
|
||||
RemoveActive()
|
||||
GLOB.tickets.closed_tickets -= src
|
||||
GLOB.tickets.resolved_tickets -= src
|
||||
handler_ref = null
|
||||
return ..()
|
||||
|
||||
/datum/ticket/proc/AddInteraction(formatted_message)
|
||||
@@ -440,7 +442,7 @@ INITIALIZE_IMMEDIATE(/obj/effect/statclick/ticket_list)
|
||||
*/
|
||||
|
||||
//Reopen a closed ticket
|
||||
/datum/ticket/proc/Reopen()
|
||||
/datum/ticket/proc/Reopen(user)
|
||||
if(state == AHELP_ACTIVE)
|
||||
to_chat(usr, span_warning("This ticket is already open."))
|
||||
return
|
||||
@@ -463,20 +465,22 @@ INITIALIZE_IMMEDIATE(/obj/effect/statclick/ticket_list)
|
||||
if(initiator)
|
||||
initiator.current_ticket = src
|
||||
|
||||
AddInteraction(span_purple("Reopened by [key_name_admin(usr)]"))
|
||||
var/admin_reopener_name = ismob(user) ? key_name_admin(user) : user
|
||||
AddInteraction(span_purple("Reopened by [admin_reopener_name]"))
|
||||
if(initiator)
|
||||
to_chat(initiator, span_filter_adminlog("[span_purple("Ticket [TicketHref("#[id]")] was reopened by [key_name(usr,FALSE,FALSE)].")]"))
|
||||
var/msg = span_adminhelp("Ticket [TicketHref("#[id]")] reopened by [key_name_admin(usr)].")
|
||||
to_chat(initiator, span_filter_adminlog("[span_purple("Ticket [TicketHref("#[id]")] was reopened by [ismob(user) ? key_name(usr,FALSE,FALSE) : user].")]"))
|
||||
var/msg = span_adminhelp("Ticket [TicketHref("#[id]")] reopened by [admin_reopener_name].")
|
||||
message_admins(msg)
|
||||
log_admin(msg)
|
||||
feedback_inc("ticket_reopen")
|
||||
initiator.mob.throw_alert("open ticket", /obj/screen/alert/open_ticket)
|
||||
//TicketPanel() //can only be done from here, so refresh it
|
||||
|
||||
SSwebhooks.send(
|
||||
WEBHOOK_AHELP_SENT,
|
||||
list(
|
||||
"name" = "Ticket ([id]) (Round ID: [GLOB.round_id ? GLOB.round_id : "No database"]) reopened.",
|
||||
"body" = "Reopened by [key_name(usr)]."
|
||||
"body" = "Reopened by [ismob(user) ? key_name(user) : user]."
|
||||
)
|
||||
)
|
||||
|
||||
@@ -491,44 +495,46 @@ INITIALIZE_IMMEDIATE(/obj/effect/statclick/ticket_list)
|
||||
initiator.current_ticket = null
|
||||
|
||||
//Mark open ticket as closed/meme
|
||||
/datum/ticket/proc/Close(silent = FALSE)
|
||||
/datum/ticket/proc/Close(user, silent = FALSE)
|
||||
if(state != AHELP_ACTIVE)
|
||||
return
|
||||
RemoveActive()
|
||||
state = AHELP_CLOSED
|
||||
GLOB.tickets.ListInsert(src)
|
||||
AddInteraction(span_filter_adminlog(span_red("Closed by [key_name_admin(usr)].")))
|
||||
var/admin_closer_name = ismob(user) ? key_name_admin(user) : user
|
||||
AddInteraction(span_filter_adminlog(span_red("Closed by [admin_closer_name].")))
|
||||
if(initiator)
|
||||
to_chat(initiator, span_filter_adminlog("[span_red("Ticket [TicketHref("#[id]")] was closed by [key_name(usr,FALSE,FALSE)].")]"))
|
||||
to_chat(initiator, span_filter_adminlog("[span_red("Ticket [TicketHref("#[id]")] was closed by [ismob(user) ? key_name(usr,FALSE,FALSE) : user].")]"))
|
||||
if(!silent)
|
||||
feedback_inc("ahelp_close")
|
||||
var/msg = "Ticket [TicketHref("#[id]")] closed by [key_name_admin(usr)]."
|
||||
var/msg = "Ticket [TicketHref("#[id]")] closed by [admin_closer_name]."
|
||||
message_admins(msg)
|
||||
log_admin(msg)
|
||||
SSwebhooks.send(
|
||||
WEBHOOK_AHELP_SENT,
|
||||
list(
|
||||
"name" = "Ticket ([id]) (Round ID: [GLOB.round_id ? GLOB.round_id : "No database"]) closed.",
|
||||
"body" = "Closed by [key_name(usr)].",
|
||||
"body" = "Closed by [ismob(user) ? key_name(user) : user].",
|
||||
"color" = COLOR_WEBHOOK_BAD
|
||||
)
|
||||
)
|
||||
// initiator?.mob?.clear_alert("open ticket") // Uncomment this line to enable player-side ticket ui
|
||||
initiator?.mob?.clear_alert("open ticket")
|
||||
|
||||
//Mark open ticket as resolved/legitimate, returns ahelp verb
|
||||
/datum/ticket/proc/Resolve(silent = FALSE)
|
||||
/datum/ticket/proc/Resolve(user, silent = FALSE)
|
||||
if(state != AHELP_ACTIVE)
|
||||
return
|
||||
RemoveActive()
|
||||
state = AHELP_RESOLVED
|
||||
GLOB.tickets.ListInsert(src)
|
||||
|
||||
AddInteraction(span_filter_adminlog(span_green("Resolved by [key_name_admin(usr)].")))
|
||||
var/admin_resolver_name = ismob(user) ? key_name_admin(user) : user
|
||||
AddInteraction(span_filter_adminlog(span_green("Resolved by [admin_resolver_name].")))
|
||||
if(initiator)
|
||||
to_chat(initiator, span_filter_adminlog("[span_green("Ticket [TicketHref("#[id]")] was marked resolved by [key_name(usr,FALSE,FALSE)].")]"))
|
||||
to_chat(initiator, span_filter_adminlog("[span_green("Ticket [TicketHref("#[id]")] was marked resolved by [ismob(user) ? key_name(usr,FALSE,FALSE) : user].")]"))
|
||||
if(!silent)
|
||||
feedback_inc("ticket_resolve")
|
||||
var/msg = "Ticket [TicketHref("#[id]")] resolved by [key_name_admin(usr)]"
|
||||
var/msg = "Ticket [TicketHref("#[id]")] resolved by [admin_resolver_name]"
|
||||
if(type == 1)
|
||||
message_mentors(msg)
|
||||
else if (type == 0)
|
||||
@@ -540,14 +546,14 @@ INITIALIZE_IMMEDIATE(/obj/effect/statclick/ticket_list)
|
||||
WEBHOOK_AHELP_SENT,
|
||||
list(
|
||||
"name" = "Ticket ([id]) (Round ID: [GLOB.round_id ? GLOB.round_id : "No database"]) resolved.",
|
||||
"body" = "Marked as Resolved by [key_name(usr)].",
|
||||
"body" = "Marked as Resolved by [ismob(user) ? key_name(user) : user].",
|
||||
"color" = COLOR_WEBHOOK_GOOD
|
||||
)
|
||||
)
|
||||
// initiator?.mob?.clear_alert("open ticket") // Uncomment this line to enable player-side ticket ui
|
||||
initiator?.mob?.clear_alert("open ticket")
|
||||
|
||||
//Close and return ahelp verb, use if ticket is incoherent
|
||||
/datum/ticket/proc/Reject(key_name = key_name_admin(usr))
|
||||
/datum/ticket/proc/Reject(mob/user)
|
||||
if(state != AHELP_ACTIVE)
|
||||
return
|
||||
|
||||
@@ -559,23 +565,24 @@ INITIALIZE_IMMEDIATE(/obj/effect/statclick/ticket_list)
|
||||
[span_red(span_bold("Your admin help was rejected."))]<br>\
|
||||
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."))
|
||||
|
||||
var/admin_rejecter_name = ismob(user) ? key_name_admin(user) : user
|
||||
feedback_inc("ahelp_reject")
|
||||
var/msg = "Ticket [TicketHref("#[id]")] rejected by [key_name_admin(usr)]"
|
||||
var/msg = "Ticket [TicketHref("#[id]")] rejected by [admin_rejecter_name]"
|
||||
message_admins(msg)
|
||||
log_admin(msg)
|
||||
AddInteraction("Rejected by [key_name_admin(usr)].")
|
||||
Close(silent = TRUE)
|
||||
AddInteraction("Rejected by [admin_rejecter_name].")
|
||||
Close(user, silent = TRUE)
|
||||
SSwebhooks.send(
|
||||
WEBHOOK_AHELP_SENT,
|
||||
list(
|
||||
"name" = "Ticket ([id]) (Round ID: [GLOB.round_id ? GLOB.round_id : "No database"]) rejected.",
|
||||
"body" = "Rejected by [key_name(usr)].",
|
||||
"body" = "Rejected by [ismob(user) ? key_name(user) : user].",
|
||||
"color" = COLOR_WEBHOOK_BAD
|
||||
)
|
||||
)
|
||||
|
||||
//Resolve ticket with IC Issue message
|
||||
/datum/ticket/proc/ICIssue(key_name = key_name_admin(usr))
|
||||
/datum/ticket/proc/ICIssue(user)
|
||||
if(state != AHELP_ACTIVE)
|
||||
return
|
||||
|
||||
@@ -586,51 +593,57 @@ INITIALIZE_IMMEDIATE(/obj/effect/statclick/ticket_list)
|
||||
if(initiator)
|
||||
to_chat(initiator, span_filter_pm(msg))
|
||||
|
||||
var/admin_resolve_name = ismob(user) ? key_name_admin(user) : user
|
||||
feedback_inc("ahelp_icissue")
|
||||
msg = "Ticket [TicketHref("#[id]")] marked as IC by [key_name_admin(usr)]"
|
||||
msg = "Ticket [TicketHref("#[id]")] marked as IC by [admin_resolve_name]"
|
||||
message_admins(msg)
|
||||
log_admin(msg)
|
||||
AddInteraction("Marked as IC issue by [key_name_admin(usr)]")
|
||||
Resolve(silent = TRUE)
|
||||
AddInteraction("Marked as IC issue by [admin_resolve_name]")
|
||||
Resolve(user, silent = TRUE)
|
||||
SSwebhooks.send(
|
||||
WEBHOOK_AHELP_SENT,
|
||||
list(
|
||||
"name" = "Ticket ([id]) (Round ID: [GLOB.round_id ? GLOB.round_id : "No database"]) marked as IC issue.",
|
||||
"body" = "Marked as IC Issue by [key_name(usr)].",
|
||||
"body" = "Marked as IC Issue by [ismob(user) ? key_name(user) : user].",
|
||||
"color" = COLOR_WEBHOOK_BAD
|
||||
)
|
||||
)
|
||||
|
||||
//Resolve ticket with IC Issue message
|
||||
/datum/ticket/proc/HandleIssue()
|
||||
//Handle ticket
|
||||
/datum/ticket/proc/HandleIssue(user)
|
||||
if(state != AHELP_ACTIVE)
|
||||
return
|
||||
|
||||
if(handler == key_name(usr, FALSE, TRUE))
|
||||
to_chat(usr, span_red("You are already handling this ticket."))
|
||||
var/handler_name = ismob(user) ? key_name(user, FALSE, TRUE) : user
|
||||
if(handler == handler_name)
|
||||
to_chat(user, span_red("You are already handling this ticket."))
|
||||
return
|
||||
|
||||
var/handler_shown_name = ismob(user) ? key_name_admin(user) : user
|
||||
var/msg
|
||||
switch(level)
|
||||
if(0)
|
||||
msg = span_green("Your MentorHelp is being handled by [key_name(usr,FALSE,FALSE)] please be patient.")
|
||||
msg = span_green("Your MentorHelp is being handled by [handler_shown_name] please be patient.")
|
||||
if(1)
|
||||
msg = span_red("Your AdminHelp is being handled by [key_name(usr,FALSE,FALSE)] please be patient.")
|
||||
msg = span_red("Your AdminHelp is being handled by [handler_shown_name] please be patient.")
|
||||
|
||||
if(initiator)
|
||||
to_chat(initiator, msg)
|
||||
|
||||
feedback_inc("ahelp_handling")
|
||||
msg = "Ticket [TicketHref("#[id]")] being handled by [key_name(usr,FALSE,FALSE)]"
|
||||
msg = "Ticket [TicketHref("#[id]")] being handled by [handler_shown_name]"
|
||||
message_admins(msg)
|
||||
log_admin(msg)
|
||||
AddInteraction("[key_name_admin(usr)] is now handling this ticket.")
|
||||
handler = key_name(usr, FALSE, TRUE)
|
||||
AddInteraction("[handler_shown_name] is now handling this ticket.")
|
||||
handler = handler_name
|
||||
if(ismob(user))
|
||||
var/mob/our_handler_mob = user
|
||||
handler_ref = WEAKREF(our_handler_mob.client)
|
||||
SSwebhooks.send(
|
||||
WEBHOOK_AHELP_SENT,
|
||||
list(
|
||||
"name" = "Ticket ([id]) (Round ID: [GLOB.round_id ? GLOB.round_id : "No database"]) being handled.",
|
||||
"body" = "[key_name(usr)] is now handling the ticket."
|
||||
"body" = "[ismob(user) ? key_name(user) : user] is now handling the ticket."
|
||||
)
|
||||
)
|
||||
|
||||
@@ -681,7 +694,7 @@ INITIALIZE_IMMEDIATE(/obj/effect/statclick/ticket_list)
|
||||
if("retitle")
|
||||
Retitle()
|
||||
if("reject")
|
||||
Reject()
|
||||
Reject(usr)
|
||||
if("reply")
|
||||
switch(level)
|
||||
if(0)
|
||||
@@ -689,15 +702,15 @@ INITIALIZE_IMMEDIATE(/obj/effect/statclick/ticket_list)
|
||||
if(1)
|
||||
usr.client.cmd_ahelp_reply(initiator)
|
||||
if("icissue")
|
||||
ICIssue()
|
||||
ICIssue(usr)
|
||||
if("close")
|
||||
Close()
|
||||
Close(usr)
|
||||
if("resolve")
|
||||
Resolve()
|
||||
Resolve(usr)
|
||||
if("handleissue")
|
||||
HandleIssue()
|
||||
HandleIssue(usr)
|
||||
if("reopen")
|
||||
Reopen()
|
||||
Reopen(usr)
|
||||
if("escalate")
|
||||
Escalate()
|
||||
|
||||
|
||||
@@ -6,22 +6,19 @@
|
||||
var/datum/ticket/T
|
||||
|
||||
/datum/ticket_chat/tgui_interact(mob/user, datum/tgui/ui)
|
||||
return // Remove this line to enable player-side ticket ui
|
||||
//ui = SStgui.try_update_ui(user, src, ui)
|
||||
//if(!ui)
|
||||
// ui = new(user, src, "TicketChat", "Ticket #[T.id] - [T.LinkedReplyName("\ref[T]")]")
|
||||
// ui.open()
|
||||
// user.clear_alert("open ticket")
|
||||
ui = SStgui.try_update_ui(user, src, ui)
|
||||
if(!ui)
|
||||
ui = new(user, src, "TicketChat", "Ticket #[T.id] - [T.LinkedReplyName("\ref[T]")]")
|
||||
ui.open()
|
||||
user.clear_alert("open ticket")
|
||||
|
||||
/datum/ticket_chat/tgui_close(mob/user)
|
||||
. = ..()
|
||||
return // Remove this line to enable player-side ticket ui
|
||||
//if(user.client.current_ticket)
|
||||
// user.throw_alert("open ticket", /obj/screen/alert/open_ticket)
|
||||
if(user.client.current_ticket)
|
||||
user.throw_alert("open ticket", /obj/screen/alert/open_ticket)
|
||||
|
||||
/datum/ticket_chat/tgui_state(mob/user)
|
||||
return ADMIN_STATE(R_ADMIN|R_EVENT|R_DEBUG) // Remove this line to enable player-side ticket ui
|
||||
//return GLOB.tgui_ticket_state
|
||||
return GLOB.tgui_ticket_state
|
||||
|
||||
/datum/ticket_chat/tgui_data(mob/user)
|
||||
var/list/data = list()
|
||||
@@ -29,9 +26,9 @@
|
||||
data["id"] = T.id
|
||||
|
||||
data["level"] = T.level
|
||||
// data["handler"] = T.handler // Uncomment this line to enable player-side ticket ui
|
||||
data["handler"] = T.handler
|
||||
|
||||
// data["log"] = T._interactions // Uncomment this line to enable player-side ticket ui
|
||||
data["log"] = T._interactions
|
||||
|
||||
return data
|
||||
|
||||
@@ -43,10 +40,27 @@
|
||||
if(!params["msg"])
|
||||
return
|
||||
|
||||
var/sane_message = sanitize(params["msg"])
|
||||
switch(T.level)
|
||||
if (0)
|
||||
ui.user.client.cmd_mentor_pm(ui.user.client, sanitize(params["msg"]), T)
|
||||
if(T.initiator == ui.user.client)
|
||||
var/client/handler = T.handler_ref?.resolve()
|
||||
if(handler)
|
||||
ui.user.client.cmd_mentor_pm(handler, sane_message, T)
|
||||
return TRUE
|
||||
T.AddInteraction("[T.initiator_key_name]: [sane_message]")
|
||||
return TRUE
|
||||
ui.user.client.cmd_mentor_pm(T.initiator, sane_message, T)
|
||||
return TRUE
|
||||
if (1)
|
||||
ui.user.client.cmd_admin_pm(ui.user.client, sanitize(params["msg"]), T)
|
||||
if(T.initiator == ui.user.client)
|
||||
var/client/handler = T.handler_ref?.resolve()
|
||||
if(handler)
|
||||
ui.user.client.cmd_admin_pm(handler, sane_message, T)
|
||||
return TRUE
|
||||
T.AddInteraction("[key_name_admin(ui.user)]: [sane_message]")
|
||||
return TRUE
|
||||
ui.user.client.cmd_admin_pm(T.initiator, sane_message, T)
|
||||
return TRUE
|
||||
|
||||
. = TRUE
|
||||
|
||||
@@ -57,6 +57,7 @@
|
||||
"state" = get_ticket_state(T.state),
|
||||
"level" = T.level,
|
||||
"handler" = T.handler,
|
||||
"ishandled" = !!T.handler_ref?.resolve(),
|
||||
"opened_at" = (world.time - T.opened_at),
|
||||
"closed_at" = (world.time - T.closed_at),
|
||||
"opened_at_date" = gameTimestamp(wtime = T.opened_at),
|
||||
@@ -71,6 +72,7 @@
|
||||
"state" = get_ticket_state(T.state),
|
||||
"level" = T.level,
|
||||
"handler" = T.handler,
|
||||
"ishandled" = !!T.handler_ref?.resolve(),
|
||||
"opened_at" = (world.time - T.opened_at),
|
||||
"closed_at" = (world.time - T.closed_at),
|
||||
"opened_at_date" = gameTimestamp(wtime = T.opened_at),
|
||||
@@ -85,6 +87,7 @@
|
||||
"state" = get_ticket_state(T.state),
|
||||
"level" = T.level,
|
||||
"handler" = T.handler,
|
||||
"ishandled" = !!T.handler_ref?.resolve(),
|
||||
"opened_at" = (world.time - T.opened_at),
|
||||
"closed_at" = (world.time - T.closed_at),
|
||||
"opened_at_date" = gameTimestamp(wtime = T.opened_at),
|
||||
@@ -145,7 +148,7 @@
|
||||
to_chat(ui.user, span_warning("Ticket not found, creating new one..."))
|
||||
else
|
||||
player.current_ticket.AddInteraction("[key_name_admin(ui.user)] opened a new ticket.")
|
||||
player.current_ticket.Close()
|
||||
player.current_ticket.Close(ui.user)
|
||||
|
||||
// Create a new ticket and handle it. You created it afterall!
|
||||
var/datum/ticket/T = new /datum/ticket(ticket_text, player, TRUE, level)
|
||||
@@ -153,7 +156,7 @@
|
||||
T.level = 1
|
||||
else
|
||||
T.level = 0
|
||||
T.HandleIssue()
|
||||
T.HandleIssue(ui.user)
|
||||
switch(T.level)
|
||||
if (0)
|
||||
ui.user.client.cmd_mentor_pm(player, ticket_text, T)
|
||||
@@ -168,7 +171,7 @@
|
||||
ui.user.client.selected_ticket.Retitle()
|
||||
. = TRUE
|
||||
if("reopen_ticket")
|
||||
ui.user.client.selected_ticket.Reopen()
|
||||
ui.user.client.selected_ticket.Reopen(ui.user)
|
||||
. = TRUE
|
||||
if("undock_ticket")
|
||||
ui.user.client.selected_ticket.tgui_interact(ui.user)
|
||||
@@ -249,7 +252,7 @@
|
||||
Retitle()
|
||||
. = TRUE
|
||||
if("reopen")
|
||||
Reopen()
|
||||
Reopen(ui.user)
|
||||
. = TRUE
|
||||
if("legacy")
|
||||
TicketPanelLegacy(ui.user)
|
||||
|
||||
BIN
icons/logo.dmi
BIN
icons/logo.dmi
Binary file not shown.
|
Before Width: | Height: | Size: 2.4 KiB After Width: | Height: | Size: 4.5 KiB |
@@ -792,22 +792,12 @@ macro "hotkeymode"
|
||||
elem "ctrlshiftsubtract"
|
||||
name = "CTRL+SHIFT+SUBTRACT"
|
||||
command = "planedown"
|
||||
<<<<<<< HEAD
|
||||
// elem // CHOMPREMOVE Start
|
||||
// name = "Space"
|
||||
// command = ".throwon"
|
||||
// elem
|
||||
// name = "Space+UP"
|
||||
// command = ".throwoff" // CHOMPREMOVE End
|
||||
=======
|
||||
elem "space"
|
||||
name = "Space"
|
||||
command = ".throwon"
|
||||
elem "spaceup"
|
||||
name = "Space+UP"
|
||||
command = ".throwoff"
|
||||
|
||||
>>>>>>> b7969a971d (Replace the alt click menu with the RPG Lootpanel (#17938))
|
||||
macro "borgmacro"
|
||||
elem "tab"
|
||||
name = "TAB"
|
||||
|
||||
@@ -5,7 +5,6 @@ import { Window } from 'tgui/layouts';
|
||||
import {
|
||||
Box,
|
||||
Button,
|
||||
Divider,
|
||||
Input,
|
||||
LabeledList,
|
||||
Section,
|
||||
@@ -104,18 +103,34 @@ export const Ticket = (props) => {
|
||||
<Section
|
||||
title={'Ticket #' + id}
|
||||
buttons={
|
||||
<Box nowrap>
|
||||
<Button icon="pen" onClick={() => act('retitle')}>
|
||||
Rename Ticket
|
||||
</Button>
|
||||
<Button onClick={() => act('legacy')}>Legacy UI</Button>
|
||||
<Button color={LevelColor[level]}>{Level[level]}</Button>
|
||||
</Box>
|
||||
<Stack>
|
||||
<Stack.Item>
|
||||
<Button icon="pen" onClick={() => act('retitle')}>
|
||||
Rename Ticket
|
||||
</Button>
|
||||
</Stack.Item>
|
||||
<Stack.Item>
|
||||
<Button onClick={() => act('legacy')}>Legacy UI</Button>
|
||||
</Stack.Item>
|
||||
<Stack.Item>
|
||||
<Box
|
||||
className="TicketPanel__Label"
|
||||
backgroundColor={LevelColor[level]}
|
||||
>
|
||||
{Level[level]}
|
||||
</Box>
|
||||
</Stack.Item>
|
||||
</Stack>
|
||||
}
|
||||
>
|
||||
<LabeledList>
|
||||
<LabeledList.Item label="Ticket ID">
|
||||
#{id}: <div dangerouslySetInnerHTML={{ __html: name }} />
|
||||
<Stack>
|
||||
<Stack.Item>#{id}:</Stack.Item>
|
||||
<Stack.Item>
|
||||
<div dangerouslySetInnerHTML={{ __html: name }} />
|
||||
</Stack.Item>
|
||||
</Stack>
|
||||
</LabeledList.Item>
|
||||
<LabeledList.Item label="Type">{Level[level]}</LabeledList.Item>
|
||||
<LabeledList.Item label="State">
|
||||
@@ -131,23 +146,28 @@ export const Ticket = (props) => {
|
||||
</LabeledList.Item>
|
||||
) : (
|
||||
<LabeledList.Item label="Closed At">
|
||||
{closed_at_date +
|
||||
' (' +
|
||||
toFixed(round((closed_at / 600) * 10, 0) / 10, 1) +
|
||||
' minutes ago.)'}
|
||||
<Button onClick={() => act('reopen')}>Reopen</Button>
|
||||
<Stack>
|
||||
<Stack.Item>
|
||||
{closed_at_date +
|
||||
' (' +
|
||||
toFixed(round((closed_at / 600) * 10, 0) / 10, 1) +
|
||||
' minutes ago.)'}
|
||||
</Stack.Item>
|
||||
<Stack.Item>
|
||||
<Button onClick={() => act('reopen')}>Reopen</Button>
|
||||
</Stack.Item>
|
||||
</Stack>
|
||||
</LabeledList.Item>
|
||||
)}
|
||||
<LabeledList.Item label="Actions">
|
||||
<div dangerouslySetInnerHTML={{ __html: actions }} />
|
||||
</LabeledList.Item>
|
||||
<LabeledList.Item label="Log" />
|
||||
</LabeledList>
|
||||
</Section>
|
||||
<Divider />
|
||||
<Stack.Divider />
|
||||
</Stack.Item>
|
||||
<Stack.Item grow>
|
||||
<Section scrollable ref={messagesEndRef} fill>
|
||||
<Section scrollable ref={messagesEndRef} fill title="Log">
|
||||
<Stack fill direction="column">
|
||||
<Stack.Item grow>
|
||||
{Object.keys(log)
|
||||
|
||||
@@ -3,8 +3,8 @@ import { type RefObject, useEffect, useRef, useState } from 'react';
|
||||
import { useBackend } from 'tgui/backend';
|
||||
import { Window } from 'tgui/layouts';
|
||||
import {
|
||||
Box,
|
||||
Button,
|
||||
Divider,
|
||||
Input,
|
||||
LabeledList,
|
||||
Section,
|
||||
@@ -76,18 +76,22 @@ export const TicketChat = (props) => {
|
||||
<Section
|
||||
title={'Ticket #' + id}
|
||||
buttons={
|
||||
<Button color={LevelColor[level]}>{Level[level]}</Button>
|
||||
<Box
|
||||
className="TicketPanel__Label"
|
||||
backgroundColor={LevelColor[level]}
|
||||
>
|
||||
{Level[level]}
|
||||
</Box>
|
||||
}
|
||||
>
|
||||
<LabeledList>
|
||||
<LabeledList.Item label="Assignee">{handler}</LabeledList.Item>
|
||||
<LabeledList.Item label="Log" />
|
||||
</LabeledList>
|
||||
</Section>
|
||||
<Divider />
|
||||
<Stack.Divider />
|
||||
</Stack.Item>
|
||||
<Stack.Item grow>
|
||||
<Section fill ref={messagesEndRef} scrollable>
|
||||
<Section fill ref={messagesEndRef} scrollable title="Log">
|
||||
<Stack fill direction="column">
|
||||
<Stack.Item grow>
|
||||
{Object.keys(log)
|
||||
@@ -101,6 +105,8 @@ export const TicketChat = (props) => {
|
||||
</Stack.Item>
|
||||
</Stack>
|
||||
</Section>
|
||||
</Stack.Item>
|
||||
<Stack.Item>
|
||||
<Section fill>
|
||||
<Stack fill>
|
||||
<Stack.Item grow>
|
||||
|
||||
@@ -3,6 +3,7 @@ import { type RefObject, useEffect, useRef, useState } from 'react';
|
||||
import { useBackend } from 'tgui/backend';
|
||||
import { Window } from 'tgui/layouts';
|
||||
import {
|
||||
Blink,
|
||||
Box,
|
||||
Button,
|
||||
Divider,
|
||||
@@ -67,6 +68,7 @@ type Ticket = {
|
||||
state: string;
|
||||
level: number;
|
||||
handler: string;
|
||||
ishandled: BooleanLike;
|
||||
opened_at: number;
|
||||
closed_at: number;
|
||||
opened_at_date: string;
|
||||
@@ -138,65 +140,88 @@ export const TicketsPanel = (props) => {
|
||||
<Window width={1000} height={600}>
|
||||
<Window.Content>
|
||||
<Stack fill>
|
||||
<Stack.Item shrink>
|
||||
<Section title="Filter">
|
||||
<Dropdown
|
||||
width="100%"
|
||||
maxHeight="160px"
|
||||
options={Object.values(State)}
|
||||
selected={State[stateFilter]}
|
||||
onSelected={(val) =>
|
||||
setStateFilter(
|
||||
Object.keys(State)[Object.values(State).indexOf(val)],
|
||||
)
|
||||
}
|
||||
/>
|
||||
<Divider />
|
||||
<Dropdown
|
||||
width="100%"
|
||||
maxHeight="160px"
|
||||
options={Object.values(availableLevel)}
|
||||
selected={availableLevel[levelFilter]}
|
||||
onSelected={(val) =>
|
||||
setLevelFilter(Object.values(availableLevel).indexOf(val))
|
||||
}
|
||||
/>
|
||||
</Section>
|
||||
<Section
|
||||
title="Tickets"
|
||||
scrollable
|
||||
fill
|
||||
height="450px"
|
||||
width="300px"
|
||||
>
|
||||
<Tabs vertical>
|
||||
<Tabs.Tab onClick={() => act('new_ticket')}>
|
||||
New Ticket
|
||||
<Icon name="plus" ml={0.5} />
|
||||
</Tabs.Tab>
|
||||
<Divider />
|
||||
{filtered_tickets.map((ticket) => (
|
||||
<Tabs.Tab
|
||||
key={ticket.id}
|
||||
selected={ticket.id === selected_ticket?.id}
|
||||
onClick={() => act('pick_ticket', { ticket_id: ticket.id })}
|
||||
>
|
||||
<Box inline>
|
||||
<Box>
|
||||
<Button color={LevelColor[ticket.level]}>
|
||||
{availableLevel[ticket.level]}
|
||||
</Button>
|
||||
{ticket.name}
|
||||
</Box>
|
||||
<Box fontSize={0.9} textColor={StateColor[ticket.state]}>
|
||||
State: {State[ticket.state]} | Assignee:
|
||||
{ticket.handler}
|
||||
</Box>
|
||||
</Box>
|
||||
</Tabs.Tab>
|
||||
))}
|
||||
</Tabs>
|
||||
</Section>
|
||||
<Stack.Item basis="25%">
|
||||
<Stack vertical fill>
|
||||
<Stack.Item>
|
||||
<Section title="Filter">
|
||||
<Dropdown
|
||||
options={Object.values(State)}
|
||||
selected={State[stateFilter]}
|
||||
onSelected={(val) =>
|
||||
setStateFilter(
|
||||
Object.keys(State)[Object.values(State).indexOf(val)],
|
||||
)
|
||||
}
|
||||
/>
|
||||
<Divider />
|
||||
<Dropdown
|
||||
options={Object.values(availableLevel)}
|
||||
selected={availableLevel[levelFilter]}
|
||||
onSelected={(val) =>
|
||||
setLevelFilter(Object.values(availableLevel).indexOf(val))
|
||||
}
|
||||
/>
|
||||
</Section>
|
||||
</Stack.Item>
|
||||
<Stack.Item grow>
|
||||
<Section title="Tickets" scrollable fill>
|
||||
<Tabs vertical>
|
||||
<Tabs.Tab onClick={() => act('new_ticket')}>
|
||||
New Ticket
|
||||
<Icon name="plus" ml={0.5} />
|
||||
</Tabs.Tab>
|
||||
<Divider />
|
||||
{filtered_tickets.map((ticket) => (
|
||||
<Tabs.Tab
|
||||
key={ticket.id}
|
||||
selected={ticket.id === selected_ticket?.id}
|
||||
onClick={() =>
|
||||
act('pick_ticket', { ticket_id: ticket.id })
|
||||
}
|
||||
>
|
||||
<Stack vertical>
|
||||
<Stack.Item>
|
||||
<Stack align="center">
|
||||
<Stack.Item>
|
||||
{ticket.ishandled ? (
|
||||
<Box
|
||||
textColor="white"
|
||||
className="TicketPanel__Label"
|
||||
backgroundColor={LevelColor[ticket.level]}
|
||||
>
|
||||
{availableLevel[ticket.level]}
|
||||
</Box>
|
||||
) : (
|
||||
<Blink>
|
||||
<Box
|
||||
textColor="white"
|
||||
className="TicketPanel__Label"
|
||||
backgroundColor={LevelColor[ticket.level]}
|
||||
>
|
||||
{availableLevel[ticket.level]}
|
||||
</Box>
|
||||
</Blink>
|
||||
)}
|
||||
</Stack.Item>
|
||||
<Stack.Item>{ticket.name}</Stack.Item>
|
||||
</Stack>
|
||||
</Stack.Item>
|
||||
<Stack.Item>
|
||||
<Box
|
||||
fontSize={0.9}
|
||||
textColor={StateColor[ticket.state]}
|
||||
>
|
||||
State: {State[ticket.state]} | Assignee:
|
||||
{ticket.handler}
|
||||
</Box>
|
||||
</Stack.Item>
|
||||
</Stack>
|
||||
</Tabs.Tab>
|
||||
))}
|
||||
</Tabs>
|
||||
</Section>
|
||||
</Stack.Item>
|
||||
</Stack>
|
||||
</Stack.Item>
|
||||
<Stack.Item grow>
|
||||
{(selected_ticket && (
|
||||
@@ -205,34 +230,51 @@ export const TicketsPanel = (props) => {
|
||||
<Section
|
||||
title={'Ticket #' + selected_ticket.id}
|
||||
buttons={
|
||||
<Box nowrap>
|
||||
<Button
|
||||
icon="arrow-up"
|
||||
onClick={() => act('undock_ticket')}
|
||||
>
|
||||
Undock
|
||||
</Button>
|
||||
<Button
|
||||
icon="pen"
|
||||
onClick={() => act('retitle_ticket')}
|
||||
>
|
||||
Rename Ticket
|
||||
</Button>
|
||||
<Button onClick={() => act('legacy')}>Legacy UI</Button>
|
||||
<Button color={LevelColor[selected_ticket.level]}>
|
||||
{availableLevel[selected_ticket.level]}
|
||||
</Button>
|
||||
</Box>
|
||||
<Stack>
|
||||
<Stack.Item>
|
||||
<Button
|
||||
icon="arrow-up"
|
||||
onClick={() => act('undock_ticket')}
|
||||
>
|
||||
Undock
|
||||
</Button>
|
||||
</Stack.Item>
|
||||
<Stack.Item>
|
||||
<Button
|
||||
icon="pen"
|
||||
onClick={() => act('retitle_ticket')}
|
||||
>
|
||||
Rename Ticket
|
||||
</Button>
|
||||
</Stack.Item>
|
||||
<Stack.Item>
|
||||
<Button onClick={() => act('legacy')}>
|
||||
Legacy UI
|
||||
</Button>
|
||||
</Stack.Item>
|
||||
<Stack.Item>
|
||||
<Box
|
||||
className="TicketPanel__Label"
|
||||
backgroundColor={LevelColor[selected_ticket.level]}
|
||||
>
|
||||
{availableLevel[selected_ticket.level]}
|
||||
</Box>
|
||||
</Stack.Item>
|
||||
</Stack>
|
||||
}
|
||||
>
|
||||
<LabeledList>
|
||||
<LabeledList.Item label="Ticket ID">
|
||||
#{selected_ticket.id}:
|
||||
<div
|
||||
dangerouslySetInnerHTML={{
|
||||
__html: selected_ticket.name,
|
||||
}}
|
||||
/>
|
||||
<Stack>
|
||||
<Stack.Item>#{selected_ticket.id}:</Stack.Item>
|
||||
<Stack.Item>
|
||||
<div
|
||||
dangerouslySetInnerHTML={{
|
||||
__html: selected_ticket.name,
|
||||
}}
|
||||
/>
|
||||
</Stack.Item>
|
||||
</Stack>
|
||||
</LabeledList.Item>
|
||||
<LabeledList.Item label="Type">
|
||||
{availableLevel[selected_ticket.level]}
|
||||
@@ -256,17 +298,25 @@ export const TicketsPanel = (props) => {
|
||||
</LabeledList.Item>
|
||||
) : (
|
||||
<LabeledList.Item label="Closed At">
|
||||
{selected_ticket.closed_at_date +
|
||||
' (' +
|
||||
toFixed(
|
||||
round((selected_ticket.closed_at / 600) * 10, 0) /
|
||||
10,
|
||||
1,
|
||||
) +
|
||||
' minutes ago.)'}
|
||||
<Button onClick={() => act('reopen_ticket')}>
|
||||
Reopen
|
||||
</Button>
|
||||
<Stack>
|
||||
<Stack.Item>
|
||||
{selected_ticket.closed_at_date +
|
||||
' (' +
|
||||
toFixed(
|
||||
round(
|
||||
(selected_ticket.closed_at / 600) * 10,
|
||||
0,
|
||||
) / 10,
|
||||
1,
|
||||
) +
|
||||
' minutes ago.)'}
|
||||
</Stack.Item>
|
||||
<Stack.Item>
|
||||
<Button onClick={() => act('reopen_ticket')}>
|
||||
Reopen
|
||||
</Button>
|
||||
</Stack.Item>
|
||||
</Stack>
|
||||
</LabeledList.Item>
|
||||
)}
|
||||
<LabeledList.Item label="Actions">
|
||||
@@ -276,13 +326,12 @@ export const TicketsPanel = (props) => {
|
||||
}}
|
||||
/>
|
||||
</LabeledList.Item>
|
||||
<LabeledList.Item label="Log" />
|
||||
</LabeledList>
|
||||
</Section>
|
||||
<Divider />
|
||||
<Stack.Divider />
|
||||
</Stack.Item>
|
||||
<Stack.Item grow>
|
||||
<Section fill ref={messagesEndRef} scrollable>
|
||||
<Section fill ref={messagesEndRef} scrollable title="Log">
|
||||
<Stack fill direction="column">
|
||||
<Stack.Item grow>
|
||||
{Object.keys(selected_ticket.log)
|
||||
@@ -336,23 +385,29 @@ export const TicketsPanel = (props) => {
|
||||
<Section
|
||||
title="No ticket selected"
|
||||
buttons={
|
||||
<Box nowrap>
|
||||
<Button
|
||||
disabled
|
||||
icon="arrow-up"
|
||||
onClick={() => act('undock_ticket')}
|
||||
>
|
||||
Undock
|
||||
</Button>
|
||||
<Button
|
||||
disabled
|
||||
icon="pen"
|
||||
onClick={() => act('retitle_ticket')}
|
||||
>
|
||||
Rename Ticket
|
||||
</Button>
|
||||
<Button onClick={() => act('legacy')}>Legacy UI</Button>
|
||||
</Box>
|
||||
<Stack>
|
||||
<Stack.Item>
|
||||
<Button
|
||||
disabled
|
||||
icon="arrow-up"
|
||||
onClick={() => act('undock_ticket')}
|
||||
>
|
||||
Undock
|
||||
</Button>
|
||||
</Stack.Item>
|
||||
<Stack.Item>
|
||||
<Button
|
||||
disabled
|
||||
icon="pen"
|
||||
onClick={() => act('retitle_ticket')}
|
||||
>
|
||||
Rename Ticket
|
||||
</Button>
|
||||
</Stack.Item>
|
||||
<Stack.Item>
|
||||
<Button onClick={() => act('legacy')}>Legacy UI</Button>
|
||||
</Stack.Item>
|
||||
</Stack>
|
||||
}
|
||||
>
|
||||
Please select a ticket on the left to view its details.
|
||||
|
||||
@@ -112,7 +112,7 @@ const VoreSoulcatcherSection = (props: {
|
||||
title={'Soulcatcher (' + name + ')'}
|
||||
fill
|
||||
buttons={
|
||||
<Stack>
|
||||
<Stack align="center">
|
||||
<Stack.Item>
|
||||
<VorePanelEditSwitch
|
||||
action="soulcatcher_toggle"
|
||||
|
||||
12
tgui/packages/tgui/styles/interfaces/TicketPanel.scss
Normal file
12
tgui/packages/tgui/styles/interfaces/TicketPanel.scss
Normal file
@@ -0,0 +1,12 @@
|
||||
.TicketPanel__Label {
|
||||
display: inline-block;
|
||||
line-height: 1.667em;
|
||||
padding: 0 var(--space-m);
|
||||
outline: 0;
|
||||
border-radius: var(--button-border-radius);
|
||||
transition-property: background-color, color, opacity;
|
||||
transition-duration: var(--button-transition);
|
||||
transition-timing-function: var(--button-transition-timing);
|
||||
user-select: none;
|
||||
background-color: var(--button-background-default);
|
||||
}
|
||||
@@ -52,6 +52,7 @@
|
||||
@include meta.load-css('./interfaces/IDCard.scss');
|
||||
@include meta.load-css('./interfaces/TinderMessaging.scss');
|
||||
@include meta.load-css('./interfaces/Turbolift.scss');
|
||||
@include meta.load-css('./interfaces/TicketPanel.scss');
|
||||
@include meta.load-css('./interfaces/VorePanel.scss');
|
||||
@include meta.load-css('./interfaces/Wires.scss');
|
||||
|
||||
|
||||
@@ -14,6 +14,6 @@
|
||||
background-image: none;
|
||||
}
|
||||
.TitleBar__title {
|
||||
left: 12px;
|
||||
margin-left: 12px;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4561,7 +4561,6 @@
|
||||
#include "code\modules\tgchat\message.dm"
|
||||
#include "code\modules\tgchat\to_chat.dm"
|
||||
#include "code\modules\tgs\includes.dm"
|
||||
#include "code\modules\tgs_commands\chompstation.dm"
|
||||
#include "code\modules\tgs_commands\vorestation.dm"
|
||||
#include "code\modules\tgui\external.dm"
|
||||
#include "code\modules\tgui\modal.dm"
|
||||
|
||||
Reference in New Issue
Block a user