Skip to content

Commit

Permalink
Add Requests Manager to View All Prayers, Centcom/Syndicate Requests …
Browse files Browse the repository at this point in the history
…& Nuke Code Requests in Round (tgstation#60905)

Implements the Requests Manager, a new admin tool used to view all prayers, Centcom/Syndicate requests, and nuke code requests within the span of a round.

The verb can be found under Admin.Game, or alternatively just use the verb directly Requests Manager. The requests can be filtered by type (using the type filter button), or using a text search which searches both the message text as well as the request owner's name.
  • Loading branch information
bobbah authored Aug 26, 2021
1 parent 04a441f commit 8549cc0
Show file tree
Hide file tree
Showing 10 changed files with 559 additions and 6 deletions.
3 changes: 2 additions & 1 deletion code/modules/admin/admin_verbs.dm
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@ GLOBAL_PROTECT(admin_verbs_default)
/client/proc/stop_sounds,
/client/proc/mark_datum_mapview,
/client/proc/debugstatpanel,
/client/proc/fix_air /*resets air in designated radius to its default atmos composition*/
/client/proc/fix_air, /*resets air in designated radius to its default atmos composition*/
/client/proc/requests
)
GLOBAL_LIST_INIT(admin_verbs_admin, world.AVerbsAdmin())
GLOBAL_PROTECT(admin_verbs_admin)
Expand Down
10 changes: 5 additions & 5 deletions code/modules/admin/verbs/pray.dm
Original file line number Diff line number Diff line change
Expand Up @@ -40,22 +40,20 @@
prayer_type = "SPIRITUAL PRAYER"

var/msg_tmp = msg
GLOB.requests.pray(usr.client, msg, usr.job == "Chaplain")
msg = span_adminnotice("[icon2html(cross, GLOB.admins)]<b><font color=[font_color]>[prayer_type][deity ? " (to [deity])" : ""]: </font>[ADMIN_FULLMONTY(src)] [ADMIN_SC(src)]:</b> <span class='linkify'>[msg]</span>")

for(var/client/C in GLOB.admins)
if(C.prefs.chat_toggles & CHAT_PRAYER)
to_chat(C, msg, confidential = TRUE)
if(C.prefs.toggles & SOUND_PRAYERS)
if(usr.job == "Chaplain")
SEND_SOUND(C, sound('sound/effects/pray.ogg'))
to_chat(usr, span_info("You pray to the gods: \"[msg_tmp]\""), confidential = TRUE)

SSblackbox.record_feedback("tally", "admin_verb", 1, "Prayer") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
//log_admin("HELP: [key_name(src)]: [msg]")


/// Used by communications consoles to message CentCom
/proc/message_centcom(text, mob/sender)
var/msg = copytext_char(sanitize(text), 1, MAX_MESSAGE_LEN)
GLOB.requests.message_centcom(sender.client, msg)
msg = span_adminnotice("<b><font color=orange>CENTCOM:</font>[ADMIN_FULLMONTY(sender)] [ADMIN_CENTCOM_REPLY(sender)]:</b> [msg]")
to_chat(GLOB.admins, msg, confidential = TRUE)
for(var/obj/machinery/computer/communications/console in GLOB.machines)
Expand All @@ -64,6 +62,7 @@
/// Used by communications consoles to message the Syndicate
/proc/message_syndicate(text, mob/sender)
var/msg = copytext_char(sanitize(text), 1, MAX_MESSAGE_LEN)
GLOB.requests.message_syndicate(sender.client, msg)
msg = span_adminnotice("<b><font color=crimson>SYNDICATE:</font>[ADMIN_FULLMONTY(sender)] [ADMIN_SYNDICATE_REPLY(sender)]:</b> [msg]")
to_chat(GLOB.admins, msg, confidential = TRUE)
for(var/obj/machinery/computer/communications/console in GLOB.machines)
Expand All @@ -72,6 +71,7 @@
/// Used by communications consoles to request the nuclear launch codes
/proc/nuke_request(text, mob/sender)
var/msg = copytext_char(sanitize(text), 1, MAX_MESSAGE_LEN)
GLOB.requests.nuke_request(sender.client, msg)
msg = span_adminnotice("<b><font color=orange>NUKE CODE REQUEST:</font>[ADMIN_FULLMONTY(sender)] [ADMIN_CENTCOM_REPLY(sender)] [ADMIN_SET_SD_CODE]:</b> [msg]")
to_chat(GLOB.admins, msg, confidential = TRUE)
for(var/obj/machinery/computer/communications/console in GLOB.machines)
Expand Down
7 changes: 7 additions & 0 deletions code/modules/admin/verbs/requests.dm
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
/// Verb for opening the requests manager panel
/client/proc/requests()
set name = "Requests Manager"
set desc = "Open the request manager panel to view all requests during this round"
set category = "Admin.Game"
SSblackbox.record_feedback("tally", "admin_verb", 1, "Request Manager") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
GLOB.requests.ui_interact(usr)
2 changes: 2 additions & 0 deletions code/modules/client/client_procs.dm
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,7 @@ GLOBAL_LIST_INIT(blacklisted_builds, list(

GLOB.ahelp_tickets.ClientLogin(src)
GLOB.interviews.client_login(src)
GLOB.requests.client_login(src)
var/connecting_admin = FALSE //because de-admined admins connecting should be treated like admins.
//Admin Authorisation
var/datum/admins/admin_datum = GLOB.admin_datums[ckey]
Expand Down Expand Up @@ -494,6 +495,7 @@ GLOBAL_LIST_INIT(blacklisted_builds, list(
log_access("Logout: [key_name(src)]")
GLOB.ahelp_tickets.ClientLogout(src)
GLOB.interviews.client_logout(src)
GLOB.requests.client_logout(src)
SSserver_maint.UpdateHubStatus()
if(credits)
QDEL_LIST(credits)
Expand Down
43 changes: 43 additions & 0 deletions code/modules/requests/request.dm
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
/// Requests from prayers
#define REQUEST_PRAYER "request_prayer"
/// Requests for Centcom
#define REQUEST_CENTCOM "request_centcom"
/// Requests for the Syndicate
#define REQUEST_SYNDICATE "request_syndicate"
/// Requests for the nuke code
#define REQUEST_NUKE "request_nuke"

/**
* # Request
*
* A representation of an in-game request, such as a prayer.
*/
/datum/request
/// Unique ID of the request
var/id
/// Atomic ID for increment unique request IDs
var/static/atomic_id = 0
/// The type of request
var/req_type
/// The owner of the request, the player who created it
var/client/owner
/// The ckey of the owner, used for re-binding variables on login
var/owner_ckey
/// The name of the owner, in format <key>/<name>, assigned at time of request creation
var/owner_name
/// The message associated with the request
var/message
/// When the request was created
var/timestamp

/datum/request/New(client/requestee, type, request)
if (!requestee)
qdel(src)
return
id = ++atomic_id
owner = requestee
owner_ckey = owner.ckey
req_type = type
message = request
timestamp = world.time
owner_name = key_name(requestee, FALSE)
213 changes: 213 additions & 0 deletions code/modules/requests/request_manager.dm
Original file line number Diff line number Diff line change
@@ -0,0 +1,213 @@
GLOBAL_DATUM_INIT(requests, /datum/request_manager, new)

/**
* # Request Manager
*
* Handles all player requests (prayers, centcom requests, syndicate requests)
* that occur in the duration of a round.
*/
/datum/request_manager
/// Associative list of ckey -> list of requests
var/list/requests = list()
/// List where requests can be accessed by ID
var/list/requests_by_id = list()

/datum/request_manager/Destroy(force, ...)
QDEL_LIST(requests)
return ..()

/**
* Used in the new client pipeline to catch when clients are reconnecting and need to have their
* reference re-assigned to the 'owner' variable of any requests
*
* Arguments:
* * C - The client who is logging in
*/
/datum/request_manager/proc/client_login(client/C)
if (!requests[C.ckey])
return
for (var/datum/request/request as anything in requests[C.ckey])
request.owner = C

/**
* Used in the destroy client pipeline to catch when clients are disconnecting and need to have their
* reference nulled on the 'owner' variable of any requests
*
* Arguments:
* * C - The client who is logging out
*/
/datum/request_manager/proc/client_logout(client/C)
if (!requests[C.ckey])
return
for (var/datum/request/request as anything in requests[C.ckey])
request.owner = null

/**
* Creates a request for a prayer, and notifies admins who have the sound notifications enabled when appropriate
*
* Arguments:
* * C - The client who is praying
* * message - The prayer
* * is_chaplain - Boolean operator describing if the prayer is from a chaplain
*/
/datum/request_manager/proc/pray(client/C, message, is_chaplain)
request_for_client(C, REQUEST_PRAYER, message)
for(var/client/admin in GLOB.admins)
if(is_chaplain && admin.prefs.chat_toggles & CHAT_PRAYER && admin.prefs.toggles & SOUND_PRAYERS)
SEND_SOUND(admin, sound('sound/effects/pray.ogg'))

/**
* Creates a request for a Centcom message
*
* Arguments:
* * C - The client who is sending the request
* * message - The message
*/
/datum/request_manager/proc/message_centcom(client/C, message)
request_for_client(C, REQUEST_CENTCOM, message)

/**
* Creates a request for a Syndicate message
*
* Arguments:
* * C - The client who is sending the request
* * message - The message
*/
/datum/request_manager/proc/message_syndicate(client/C, message)
request_for_client(C, REQUEST_SYNDICATE, message)

/**
* Creates a request for the nuclear self destruct codes
*
* Arguments:
* * C - The client who is sending the request
* * message - The message
*/
/datum/request_manager/proc/nuke_request(client/C, message)
request_for_client(C, REQUEST_NUKE, message)

/**
* Creates a request and registers the request with all necessary internal tracking lists
*
* Arguments:
* * C - The client who is sending the request
* * type - The type of request, see defines
* * message - The message
*/
/datum/request_manager/proc/request_for_client(client/C, type, message)
var/datum/request/request = new(C, type, message)
if (!requests[C.ckey])
requests[C.ckey] = list()
requests[C.ckey] += request
requests_by_id.len++
requests_by_id[request.id] = request

/datum/request_manager/ui_interact(mob/user, datum/tgui/ui = null)
ui = SStgui.try_update_ui(user, src, ui)
if (!ui)
ui = new(user, src, "RequestManager")
ui.open()

/datum/request_manager/ui_state(mob/user)
return GLOB.admin_state

/datum/request_manager/ui_act(action, list/params, datum/tgui/ui, datum/ui_state/state)
if (..())
return

// Only admins should be sending actions
if (!check_rights(R_ADMIN))
to_chat(usr, "You do not have permission to do this, you require +ADMIN", confidential = TRUE)
return

// Get the request this relates to
var/id = params["id"] != null ? text2num(params["id"]) : null
if (!id)
to_chat(usr, "Failed to find a request ID in your action, please report this", confidential = TRUE)
CRASH("Received an action without a request ID, this shouldn't happen!")
var/datum/request/request = !id ? null : requests_by_id[id]

switch(action)
if ("pp")
var/mob/M = request.owner?.mob
usr.client.holder.show_player_panel(M)
return TRUE
if ("vv")
var/mob/M = request.owner?.mob
usr.client.debug_variables(M)
return TRUE
if ("sm")
var/mob/M = request.owner?.mob
usr.client.cmd_admin_subtle_message(M)
return TRUE
if ("flw")
var/mob/M = request.owner?.mob
usr.client.admin_follow(M)
return TRUE
if ("tp")
if(!SSticker.HasRoundStarted())
tgui_alert(usr,"The game hasn't started yet!")
return TRUE
var/mob/M = request.owner?.mob
if(!ismob(M))
var/datum/mind/D = M
if(!istype(D))
to_chat(usr, "This can only be used on instances of type /mob and /mind", confidential = TRUE)
return TRUE
else
D.traitor_panel()
return TRUE
else
usr.client.holder.show_traitor_panel(M)
return TRUE
if ("logs")
var/mob/M = request.owner?.mob
if(!ismob(M))
to_chat(usr, "This can only be used on instances of type /mob.", confidential = TRUE)
return TRUE
show_individual_logging_panel(M, null, null)
return TRUE
if ("smite")
if(!check_rights(R_FUN))
to_chat(usr, "Insufficient permissions to smite, you require +FUN", confidential = TRUE)
return TRUE
var/mob/living/carbon/human/H = request.owner?.mob
if (!H || !istype(H))
to_chat(usr, "This can only be used on instances of type /mob/living/carbon/human", confidential = TRUE)
return TRUE
usr.client.smite(H)
return TRUE
if ("rply")
if (request.req_type == REQUEST_PRAYER)
to_chat(usr, "Cannot reply to a prayer", confidential = TRUE)
return TRUE
var/mob/M = request.owner?.mob
usr.client.admin_headset_message(M, request.req_type == REQUEST_SYNDICATE ? RADIO_CHANNEL_SYNDICATE : RADIO_CHANNEL_CENTCOM)
return TRUE
if ("setcode")
if (request.req_type != REQUEST_NUKE)
to_chat(usr, "You cannot set the nuke code for a non-nuke-code-request request!", confidential = TRUE)
return TRUE
var/code = random_nukecode()
for(var/obj/machinery/nuclearbomb/selfdestruct/SD in GLOB.nuke_list)
SD.r_code = code
message_admins("[key_name_admin(usr)] has set the self-destruct code to \"[code]\".")
return TRUE

/datum/request_manager/ui_data(mob/user)
. = list(
"requests" = list()
)
for (var/ckey in requests)
for (var/datum/request/request as anything in requests[ckey])
var/list/data = list(
"id" = request.id,
"req_type" = request.req_type,
"owner" = request.owner ? "[REF(request.owner)]" : null,
"owner_ckey" = request.owner_ckey,
"owner_name" = request.owner_name,
"message" = request.message,
"timestamp" = request.timestamp,
"timestamp_str" = gameTimestamp(wtime = request.timestamp)
)
.["requests"] += list(data)
3 changes: 3 additions & 0 deletions tgstation.dme
Original file line number Diff line number Diff line change
Expand Up @@ -1654,6 +1654,7 @@
#include "code\modules\admin\verbs\possess.dm"
#include "code\modules\admin\verbs\pray.dm"
#include "code\modules\admin\verbs\reestablish_db_connection.dm"
#include "code\modules\admin\verbs\requests.dm"
#include "code\modules\admin\verbs\secrets.dm"
#include "code\modules\admin\verbs\selectequipment.dm"
#include "code\modules\admin\verbs\server.dm"
Expand Down Expand Up @@ -3340,6 +3341,8 @@
#include "code\modules\religion\religion_sects.dm"
#include "code\modules\religion\religion_structures.dm"
#include "code\modules\religion\rites.dm"
#include "code\modules\requests\request.dm"
#include "code\modules\requests\request_manager.dm"
#include "code\modules\research\bepis.dm"
#include "code\modules\research\designs.dm"
#include "code\modules\research\destructive_analyzer.dm"
Expand Down
Loading

0 comments on commit 8549cc0

Please sign in to comment.