diff --git a/.vscode/settings.json b/.vscode/settings.json
index d7c1bfc1d1e..0ef2ce67760 100644
--- a/.vscode/settings.json
+++ b/.vscode/settings.json
@@ -13,6 +13,8 @@
},
"files.eol": "\n",
"files.insertFinalNewline": true,
+ "files.trimTrailingWhitespace": true,
+ "editor.insertSpaces": false,
"git.branchProtection": ["master"],
"gitlens.advanced.blame.customArguments": ["-w"],
"tgstationTestExplorer.project.resultsType": "json",
diff --git a/code/__DEFINES/_protect.dm b/code/__DEFINES/_protect.dm
index 9152cfcb570..a1202ebaf32 100644
--- a/code/__DEFINES/_protect.dm
+++ b/code/__DEFINES/_protect.dm
@@ -11,7 +11,7 @@
return FALSE;\
}\
##Path/Read(savefile/savefile){\
- qdel(src);\
+ del(src);\
}\
##Path/Write(savefile/savefile){\
return;\
@@ -19,3 +19,4 @@
#else
#define GENERAL_PROTECT_DATUM(Path)
#endif
+// we del instead of qdel because for security reasons we must ensure the datum does not exist if Read is called. qdel will not enforce this.
diff --git a/code/__DEFINES/admin.dm b/code/__DEFINES/admin.dm
index c7274638e79..19b76a4c991 100644
--- a/code/__DEFINES/admin.dm
+++ b/code/__DEFINES/admin.dm
@@ -26,6 +26,8 @@
#define BANTYPE_ANY_JOB 9
//Admin Permissions
+/// Used for signifying that all admins can use this regardless of actual permissions
+#define R_NONE NONE
#define R_BUILD (1<<0)
#define R_ADMIN (1<<1)
#define R_BAN (1<<2)
@@ -177,4 +179,3 @@ GLOBAL_VAR_INIT(ghost_role_flags, ALL)
/// Used in logging uses of admin verbs (and sometimes some non-admin or debug verbs) to the blackbox
/// Only pass it a string key, the verb being used.
#define BLACKBOX_LOG_ADMIN_VERB(the_verb) SSblackbox.record_feedback("tally", "admin_verb", 1, the_verb)
-
diff --git a/code/__DEFINES/admin_verb.dm b/code/__DEFINES/admin_verb.dm
new file mode 100644
index 00000000000..cbf856bf436
--- /dev/null
+++ b/code/__DEFINES/admin_verb.dm
@@ -0,0 +1,92 @@
+/client/CanProcCall(procname)
+ if(findtext(procname, "__avd_") == 1)
+ message_admins("[key_name_admin(usr)] attempted to directly call admin verb '[procname]'.")
+ log_admin("[key_name(usr)] attempted to directly call admin verb '[procname]'.")
+ return FALSE
+ return ..()
+
+/**
+ * This is the only macro you should use to define admin verbs.
+ * It will define the verb and the verb holder for you.
+ * Using it is very simple:
+ * ADMIN_VERB(verb_path, R_PERM, "Name", "Description", "Admin.Category", args...)
+ * This sets up all of the above and also acts as syntatic sugar as a verb delcaration for the verb itself.
+ * Note that the verb args have an injected `client/user` argument that is the user that called the verb.
+ * Do not use usr in your verb; technically you can but I'll kill you.
+ */
+#define _ADMIN_VERB(verb_path_name, verb_permissions, verb_name, verb_desc, verb_category, show_in_context_menu, verb_args...) \
+/datum/admin_verb/##verb_path_name \
+{ \
+ name = ##verb_name; \
+ description = ##verb_desc; \
+ category = ##verb_category; \
+ permissions = ##verb_permissions; \
+ verb_path = /client/proc/__avd_##verb_path_name; \
+}; \
+/client/proc/__avd_##verb_path_name(##verb_args) \
+{ \
+ set name = ##verb_name; \
+ set desc = ##verb_desc; \
+ set hidden = FALSE; /* this is explicitly needed as the proc begins with an underscore */ \
+ set popup_menu = ##show_in_context_menu; \
+ set category = ##verb_category; \
+ var/list/_verb_args = list(usr, /datum/admin_verb/##verb_path_name); \
+ _verb_args += args; \
+ SSadmin_verbs.dynamic_invoke_verb(arglist(_verb_args)); \
+}; \
+/datum/admin_verb/##verb_path_name/__avd_do_verb(client/user, ##verb_args)
+
+#define ADMIN_VERB(verb_path_name, verb_permissions, verb_name, verb_desc, verb_category, verb_args...) \
+_ADMIN_VERB(verb_path_name, verb_permissions, verb_name, verb_desc, verb_category, FALSE, ##verb_args)
+
+#define ADMIN_VERB_ONLY_CONTEXT_MENU(verb_path_name, verb_permissions, verb_name, verb_args...) \
+_ADMIN_VERB(verb_path_name, verb_permissions, verb_name, ADMIN_VERB_NO_DESCRIPTION, ADMIN_CATEGORY_HIDDEN, TRUE, ##verb_args)
+
+#define ADMIN_VERB_AND_CONTEXT_MENU(verb_path_name, verb_permissions, verb_name, verb_desc, verb_category, verb_args...) \
+_ADMIN_VERB(verb_path_name, verb_permissions, verb_name, verb_desc, verb_category, TRUE, ##verb_args)
+
+/// Used to define a special check to determine if the admin verb should exist at all. Useful for verbs such as play sound which require configuration.
+#define ADMIN_VERB_CUSTOM_EXIST_CHECK(verb_path_name) \
+/datum/admin_verb/##verb_path_name/__avd_check_should_exist()
+
+/// Used to define the visibility flag of the verb. If the admin does not have this flag enabled they will not see the verb.
+#define ADMIN_VERB_VISIBILITY(verb_path_name, verb_visibility) /datum/admin_verb/##verb_path_name/visibility_flag = ##verb_visibility
+
+// These are put here to prevent the "procedure override precedes definition" error.
+/datum/admin_verb/proc/__avd_get_verb_path()
+ CRASH("__avd_get_verb_path not defined. use the macro")
+/datum/admin_verb/proc/__avd_do_verb(...)
+ CRASH("__avd_do_verb not defined. use the macro")
+/datum/admin_verb/proc/__avd_check_should_exist()
+ return TRUE
+
+/*
+ * This is an example of how to use the above macro:
+ * ```
+ * ADMIN_VERB(name_of_verb, R_ADMIN, "Verb Name", "Verb Desc", "Verb Category", mob/target in world)
+ * to_chat(user, "Hello!")
+ * ```
+ * Note the implied `client/user` argument that is injected into the verb.
+ * Also note that byond is shit and you cannot multi-line the macro call.
+ */
+
+/// Use this to mark your verb as not having a description. Should ONLY be used if you are also hiding the verb!
+#define ADMIN_VERB_NO_DESCRIPTION ""
+/// Used to verbs you do not want to show up in the master verb panel.
+#define ADMIN_CATEGORY_HIDDEN null
+
+// Admin verb categories
+#define ADMIN_CATEGORY_MAIN "Admin"
+#define ADMIN_CATEGORY_EVENTS "Admin.Events"
+#define ADMIN_CATEGORY_FUN "Admin.Fun"
+#define ADMIN_CATEGORY_GAME "Admin.Game"
+
+// Special categories that are seperated
+#define ADMIN_CATEGORY_DEBUG "Debug"
+#define ADMIN_CATEGORY_SERVER "Server"
+#define ADMIN_CATEGORY_OBJECT "Object"
+#define ADMIN_CATEGORY_MAPPING "Mapping"
+#define ADMIN_CATEGORY_PROFILE "Profile"
+
+// Visibility flags
+#define ADMIN_VERB_VISIBLITY_FLAG_MAPPING_DEBUG "Map-Debug"
diff --git a/code/__DEFINES/subsystems.dm b/code/__DEFINES/subsystems.dm
index c4a96d3db97..f667fa8e2df 100644
--- a/code/__DEFINES/subsystems.dm
+++ b/code/__DEFINES/subsystems.dm
@@ -136,8 +136,9 @@
#define INIT_ORDER_DBCORE 95
#define INIT_ORDER_BLACKBOX 94
#define INIT_ORDER_SERVER_MAINT 93
+#define INIT_ORDER_PLAYER_RANKS 86 // NOVA EDIT ADDITION - Player Ranks Subsystem
#define INIT_ORDER_INPUT 85
-#define INIT_ORDER_PLAYER_RANKS 84 // NOVA EDIT - Player Ranks Subsystem
+#define INIT_ORDER_ADMIN_VERBS 84 // needs to be pretty high, admins cant do much without it
#define INIT_ORDER_SOUNDS 83
#define INIT_ORDER_INSTRUMENTS 82
#define INIT_ORDER_GREYSCALE 81
diff --git a/code/__HELPERS/hallucinations.dm b/code/__HELPERS/hallucinations.dm
index 525114cea28..1eeab08d876 100644
--- a/code/__HELPERS/hallucinations.dm
+++ b/code/__HELPERS/hallucinations.dm
@@ -113,11 +113,7 @@ GLOBAL_LIST_INIT(random_hallucination_weighted_list, generate_hallucination_weig
to_chat(usr, span_boldnotice("The total weight of the hallucination weighted list is [total_weight]."))
return total_weight
-/// Debug verb for getting the weight of each distinct type within the random_hallucination_weighted_list
-/client/proc/debug_hallucination_weighted_list_per_type()
- set name = "Show Hallucination Weights"
- set category = "Debug"
-
+ADMIN_VERB(debug_hallucination_weighted_list_per_type, R_DEBUG, "Show Hallucination Weights", "View the weight of each hallucination subtype in the random weighted list.", ADMIN_CATEGORY_DEBUG)
var/header = "
Type | Weight | Percent | "
var/total_weight = debug_hallucination_weighted_list()
@@ -153,7 +149,7 @@ GLOBAL_LIST_INIT(random_hallucination_weighted_list, generate_hallucination_weig
var/page_style = ""
var/page_contents = "[page_style][header][jointext(assoc_to_keys(all_weights), "")]
"
- var/datum/browser/popup = new(mob, "hallucinationdebug", "Hallucination Weights", 600, 400)
+ var/datum/browser/popup = new(user.mob, "hallucinationdebug", "Hallucination Weights", 600, 400)
popup.set_content(page_contents)
popup.open()
diff --git a/code/_onclick/hud/movable_screen_objects.dm b/code/_onclick/hud/movable_screen_objects.dm
index b1f40f76294..e0a6c6873bd 100644
--- a/code/_onclick/hud/movable_screen_objects.dm
+++ b/code/_onclick/hud/movable_screen_objects.dm
@@ -44,40 +44,30 @@
offset[2] += y_off
return offset_to_screen_loc(offset[1], offset[2], our_client?.view)
-//Debug procs
-/client/proc/test_movable_UI()
- set category = "Debug"
- set name = "Spawn Movable UI Object"
-
- var/atom/movable/screen/movable/M = new()
+ADMIN_VERB(test_movable_UI, R_DEBUG, "Spawn Movable UI Object", "Spawn a movable UI object for testing.", ADMIN_CATEGORY_DEBUG)
+ var/atom/movable/screen/movable/M = new
M.name = "Movable UI Object"
M.icon_state = "block"
M.maptext = MAPTEXT("Movable")
M.maptext_width = 64
- var/screen_l = input(usr,"Where on the screen? (Formatted as 'X,Y' e.g: '1,1' for bottom left)","Spawn Movable UI Object") as text|null
+ var/screen_l = input(user, "Where on the screen? (Formatted as 'X,Y' e.g: '1,1' for bottom left)","Spawn Movable UI Object") as text|null
if(!screen_l)
return
M.screen_loc = screen_l
+ user.screen += M
- screen += M
-
-
-/client/proc/test_snap_UI()
- set category = "Debug"
- set name = "Spawn Snap UI Object"
-
- var/atom/movable/screen/movable/snap/S = new()
+ADMIN_VERB(test_snap_ui, R_DEBUG, "Spawn Snap UI Object", "Spawn a snap UI object for testing.", ADMIN_CATEGORY_DEBUG)
+ var/atom/movable/screen/movable/snap/S = new
S.name = "Snap UI Object"
S.icon_state = "block"
S.maptext = MAPTEXT("Snap")
S.maptext_width = 64
- var/screen_l = input(usr,"Where on the screen? (Formatted as 'X,Y' e.g: '1,1' for bottom left)","Spawn Snap UI Object") as text|null
+ var/screen_l = input(user,"Where on the screen? (Formatted as 'X,Y' e.g: '1,1' for bottom left)","Spawn Snap UI Object") as text|null
if(!screen_l)
return
S.screen_loc = screen_l
-
- screen += S
+ user.screen += S
diff --git a/code/controllers/admin.dm b/code/controllers/admin.dm
index 421712d5ad4..5056e3804ef 100644
--- a/code/controllers/admin.dm
+++ b/code/controllers/admin.dm
@@ -44,15 +44,7 @@ INITIALIZE_IMMEDIATE(/obj/effect/statclick)
usr.client.debug_variables(target)
message_admins("Admin [key_name_admin(usr)] is debugging the [target] [class].")
-
-// Debug verbs.
-/client/proc/restart_controller(controller in list("Master", "Failsafe"))
- set category = "Debug"
- set name = "Restart Controller"
- set desc = "Restart one of the various periodic loop controllers for the game (be careful!)"
-
- if(!holder)
- return
+ADMIN_VERB(restart_controller, R_DEBUG, "Restart Controller", "Restart one of the various periodic loop controllers for the game (be careful!)", ADMIN_CATEGORY_DEBUG, controller in list("Master", "Failsafe"))
switch(controller)
if("Master")
Recreate_MC()
@@ -61,16 +53,9 @@ INITIALIZE_IMMEDIATE(/obj/effect/statclick)
new /datum/controller/failsafe()
BLACKBOX_LOG_ADMIN_VERB("Restart Failsafe Controller")
- message_admins("Admin [key_name_admin(usr)] has restarted the [controller] controller.")
-
-/client/proc/debug_controller()
- set category = "Debug"
- set name = "Debug Controller"
- set desc = "Debug the various periodic loop controllers for the game (be careful!)"
-
- if(!holder)
- return
+ message_admins("Admin [key_name_admin(user)] has restarted the [controller] controller.")
+ADMIN_VERB(debug_controller, R_DEBUG, "Debug Controller", "Debug the various periodic loop controllers for the game (be careful!)", ADMIN_CATEGORY_DEBUG)
var/list/controllers = list()
var/list/controller_choices = list()
@@ -85,7 +70,7 @@ INITIALIZE_IMMEDIATE(/obj/effect/statclick)
if (!istype(controller))
return
- debug_variables(controller)
+ SSadmin_verbs.dynamic_invoke_verb(user, /datum/admin_verb/debug_variables, controller)
BLACKBOX_LOG_ADMIN_VERB("Debug Controller")
- message_admins("Admin [key_name_admin(usr)] is debugging the [controller] controller.")
+ message_admins("Admin [key_name_admin(user)] is debugging the [controller] controller.")
diff --git a/code/controllers/subsystem/admin_verbs.dm b/code/controllers/subsystem/admin_verbs.dm
new file mode 100644
index 00000000000..9496b95d998
--- /dev/null
+++ b/code/controllers/subsystem/admin_verbs.dm
@@ -0,0 +1,150 @@
+GENERAL_PROTECT_DATUM(/datum/controller/subsystem/admin_verbs)
+
+SUBSYSTEM_DEF(admin_verbs)
+ name = "Admin Verbs"
+ flags = SS_NO_FIRE
+ init_order = INIT_ORDER_ADMIN_VERBS
+ /// A list of all admin verbs indexed by their type.
+ var/list/datum/admin_verb/admin_verbs_by_type = list()
+ /// A list of all admin verbs indexed by their visibility flag.
+ var/list/list/datum/admin_verb/admin_verbs_by_visibility_flag = list()
+ /// A map of all assosciated admins and their visibility flags.
+ var/list/admin_visibility_flags = list()
+ /// A list of all admins that are pending initialization of this SS.
+ var/list/admins_pending_subsytem_init = list()
+
+/datum/controller/subsystem/admin_verbs/Initialize()
+ setup_verb_list()
+ process_pending_admins()
+ return SS_INIT_SUCCESS
+
+/datum/controller/subsystem/admin_verbs/Recover()
+ admin_verbs_by_type = SSadmin_verbs.admin_verbs_by_type
+
+/datum/controller/subsystem/admin_verbs/stat_entry(msg)
+ return "[..()] | V: [length(admin_verbs_by_type)]"
+
+/datum/controller/subsystem/admin_verbs/proc/process_pending_admins()
+ var/list/pending_admins = admins_pending_subsytem_init
+ admins_pending_subsytem_init = null
+ for(var/admin_ckey in pending_admins)
+ assosciate_admin(GLOB.directory[admin_ckey])
+
+/datum/controller/subsystem/admin_verbs/proc/setup_verb_list()
+ if(length(admin_verbs_by_type))
+ CRASH("Attempting to setup admin verbs twice!")
+ for(var/datum/admin_verb/verb_type as anything in subtypesof(/datum/admin_verb))
+ var/datum/admin_verb/verb_singleton = new verb_type
+ if(!verb_singleton.__avd_check_should_exist())
+ qdel(verb_singleton, force = TRUE)
+ continue
+
+ admin_verbs_by_type[verb_type] = verb_singleton
+ if(verb_singleton.visibility_flag)
+ if(!(verb_singleton.visibility_flag in admin_verbs_by_visibility_flag))
+ admin_verbs_by_visibility_flag[verb_singleton.visibility_flag] = list()
+ admin_verbs_by_visibility_flag[verb_singleton.visibility_flag] |= list(verb_singleton)
+
+/datum/controller/subsystem/admin_verbs/proc/get_valid_verbs_for_admin(client/admin)
+ if(isnull(admin.holder))
+ CRASH("Why are we checking a non-admin for their valid... ahem... admin verbs?")
+
+ var/list/has_permission = list()
+ for(var/permission_flag in GLOB.bitflags)
+ if(admin.holder.check_for_rights(permission_flag))
+ has_permission["[permission_flag]"] = TRUE
+
+ var/list/valid_verbs = list()
+ for(var/datum/admin_verb/verb_type as anything in admin_verbs_by_type)
+ var/datum/admin_verb/verb_singleton = admin_verbs_by_type[verb_type]
+ if(!verify_visibility(admin, verb_singleton))
+ continue
+
+ var/verb_permissions = verb_singleton.permissions
+ if(verb_permissions == R_NONE)
+ valid_verbs |= list(verb_singleton)
+ else for(var/permission_flag in bitfield_to_list(verb_permissions))
+ if(!has_permission["[permission_flag]"])
+ continue
+ valid_verbs |= list(verb_singleton)
+
+ return valid_verbs
+
+/datum/controller/subsystem/admin_verbs/proc/verify_visibility(client/admin, datum/admin_verb/verb_singleton)
+ var/needed_flag = verb_singleton.visibility_flag
+ return !needed_flag || (needed_flag in admin_visibility_flags[admin.ckey])
+
+/datum/controller/subsystem/admin_verbs/proc/update_visibility_flag(client/admin, flag, state)
+ if(state)
+ admin_visibility_flags[admin.ckey] |= list(flag)
+ assosciate_admin(admin)
+ return
+
+ admin_visibility_flags[admin.ckey] -= list(flag)
+ // they lost the flag, iterate over verbs with that flag and yoink em
+ for(var/datum/admin_verb/verb_singleton as anything in admin_verbs_by_visibility_flag[flag])
+ verb_singleton.unassign_from_client(admin)
+ admin.init_verbs()
+
+/datum/controller/subsystem/admin_verbs/proc/dynamic_invoke_verb(client/admin, datum/admin_verb/verb_type, ...)
+ if(IsAdminAdvancedProcCall())
+ message_admins("PERMISSION ELEVATION: [key_name_admin(admin)] attempted to dynamically invoke admin verb '[verb_type]'.")
+ return
+
+ if(ismob(admin))
+ var/mob/mob = admin
+ admin = mob.client
+
+ if(!ispath(verb_type, /datum/admin_verb) || verb_type == /datum/admin_verb)
+ CRASH("Attempted to dynamically invoke admin verb with invalid typepath '[verb_type]'.")
+ if(isnull(admin.holder))
+ CRASH("Attempted to dynamically invoke admin verb '[verb_type]' with a non-admin.")
+
+ var/list/verb_args = args.Copy()
+ verb_args.Cut(2, 3)
+ var/datum/admin_verb/verb_singleton = admin_verbs_by_type[verb_type] // this cannot be typed because we need to use `:`
+ if(isnull(verb_singleton))
+ CRASH("Attempted to dynamically invoke admin verb '[verb_type]' that doesn't exist.")
+
+ if(!admin.holder.check_for_rights(verb_singleton.permissions))
+ to_chat(admin, span_adminnotice("You lack the permissions to do this."))
+ return
+
+ var/old_usr = usr
+ usr = admin.mob
+ // THE MACRO ENSURES THIS EXISTS. IF IT EVER DOESNT EXIST SOMEONE DIDNT USE THE DAMN MACRO!
+ verb_singleton.__avd_do_verb(arglist(verb_args))
+ usr = old_usr
+ SSblackbox.record_feedback("tally", "dynamic_admin_verb_invocation", 1, "[verb_type]")
+
+/**
+ * Assosciates and/or resyncs an admin with their accessible admin verbs.
+ */
+/datum/controller/subsystem/admin_verbs/proc/assosciate_admin(client/admin)
+ if(IsAdminAdvancedProcCall())
+ return
+
+ if(!isnull(admins_pending_subsytem_init)) // if the list exists we are still initializing
+ to_chat(admin, span_big(span_green("Admin Verbs are still initializing. Please wait and you will be automatically assigned your verbs when it is complete.")))
+ admins_pending_subsytem_init |= list(admin.ckey)
+ return
+
+ // refresh their verbs
+ admin_visibility_flags[admin.ckey] ||= list()
+ for(var/datum/admin_verb/verb_singleton as anything in get_valid_verbs_for_admin(admin))
+ verb_singleton.assign_to_client(admin)
+ admin.init_verbs()
+
+/**
+ * Unassosciates an admin from their admin verbs.
+ * Goes over all admin verbs because we don't know which ones are assigned to the admin's mob without a bunch of extra bookkeeping.
+ * This might be a performance issue in the future if we have a lot of admin verbs.
+ */
+/datum/controller/subsystem/admin_verbs/proc/deassosciate_admin(client/admin)
+ if(IsAdminAdvancedProcCall())
+ return
+
+ UnregisterSignal(admin, COMSIG_CLIENT_MOB_LOGIN)
+ for(var/datum/admin_verb/verb_type as anything in admin_verbs_by_type)
+ admin_verbs_by_type[verb_type].unassign_from_client(admin)
+ admin_visibility_flags -= list(admin.ckey)
diff --git a/code/controllers/subsystem/explosions.dm b/code/controllers/subsystem/explosions.dm
index ec6a00badcb..6cd4fb54d2a 100644
--- a/code/controllers/subsystem/explosions.dm
+++ b/code/controllers/subsystem/explosions.dm
@@ -87,12 +87,9 @@ SUBSYSTEM_DEF(explosions)
throwturf -= T
held_throwturf -= T
-/client/proc/check_bomb_impacts()
- set name = "Check Bomb Impact"
- set category = "Debug"
-
- var/newmode = tgui_alert(usr, "Use reactionary explosions?","Check Bomb Impact", list("Yes", "No"))
- var/turf/epicenter = get_turf(mob)
+ADMIN_VERB(check_bomb_impacts, R_DEBUG, "Check Bomb Impact", "See what the effect of a bomb would be.", ADMIN_CATEGORY_DEBUG)
+ var/newmode = tgui_alert(user, "Use reactionary explosions?","Check Bomb Impact", list("Yes", "No"))
+ var/turf/epicenter = get_turf(user.mob)
if(!epicenter)
return
@@ -100,7 +97,7 @@ SUBSYSTEM_DEF(explosions)
var/heavy = 0
var/light = 0
var/list/choices = list("Small Bomb","Medium Bomb","Big Bomb","Custom Bomb")
- var/choice = tgui_input_list(usr, "Pick the bomb size", "Bomb Size?", choices)
+ var/choice = tgui_input_list(user, "Pick the bomb size", "Bomb Size?", choices)
switch(choice)
if(null)
return 0
@@ -117,9 +114,9 @@ SUBSYSTEM_DEF(explosions)
heavy = 5
light = 7
if("Custom Bomb")
- dev = input("Devastation range (Tiles):") as num
- heavy = input("Heavy impact range (Tiles):") as num
- light = input("Light impact range (Tiles):") as num
+ dev = input(user, "Devastation range (Tiles):") as num
+ heavy = input(user, "Heavy impact range (Tiles):") as num
+ light = input(user, "Light impact range (Tiles):") as num
var/max_range = max(dev, heavy, light)
var/x0 = epicenter.x
diff --git a/code/controllers/subsystem/mapping.dm b/code/controllers/subsystem/mapping.dm
index 7dd40a87a50..ca753a05321 100644
--- a/code/controllers/subsystem/mapping.dm
+++ b/code/controllers/subsystem/mapping.dm
@@ -651,46 +651,38 @@ GLOBAL_LIST_EMPTY(the_station_areas)
holodeck_templates[holo_template.template_id] = holo_template
-//Manual loading of away missions.
-/client/proc/admin_away()
- set name = "Load Away Mission"
- set category = "Admin.Events"
-
- if(!holder || !check_rights(R_FUN))
- return
-
-
+ADMIN_VERB(load_away_mission, R_FUN, "Load Away Mission", "Load a specific away mission for the station.", ADMIN_CATEGORY_EVENTS)
if(!GLOB.the_gateway)
- if(tgui_alert(usr, "There's no home gateway on the station. You sure you want to continue ?", "Uh oh", list("Yes", "No")) != "Yes")
+ if(tgui_alert(user, "There's no home gateway on the station. You sure you want to continue ?", "Uh oh", list("Yes", "No")) != "Yes")
return
var/list/possible_options = GLOB.potentialRandomZlevels + "Custom"
var/away_name
var/datum/space_level/away_level
var/secret = FALSE
- if(tgui_alert(usr, "Do you want your mission secret? (This will prevent ghosts from looking at your map in any way other than through a living player's eyes.)", "Are you $$$ekret?", list("Yes", "No")) == "Yes")
+ if(tgui_alert(user, "Do you want your mission secret? (This will prevent ghosts from looking at your map in any way other than through a living player's eyes.)", "Are you $$$ekret?", list("Yes", "No")) == "Yes")
secret = TRUE
- var/answer = input("What kind?","Away") as null|anything in possible_options
+ var/answer = input(user, "What kind?","Away") as null|anything in possible_options
switch(answer)
if("Custom")
- var/mapfile = input("Pick file:", "File") as null|file
+ var/mapfile = input(user, "Pick file:", "File") as null|file
if(!mapfile)
return
away_name = "[mapfile] custom"
- to_chat(usr,span_notice("Loading [away_name]..."))
+ to_chat(user,span_notice("Loading [away_name]..."))
var/datum/map_template/template = new(mapfile, "Away Mission")
away_level = template.load_new_z(secret)
else
if(answer in GLOB.potentialRandomZlevels)
away_name = answer
- to_chat(usr,span_notice("Loading [away_name]..."))
+ to_chat(user,span_notice("Loading [away_name]..."))
var/datum/map_template/template = new(away_name, "Away Mission")
away_level = template.load_new_z(secret)
else
return
- message_admins("Admin [key_name_admin(usr)] has loaded [away_name] away mission.")
- log_admin("Admin [key_name(usr)] has loaded [away_name] away mission.")
+ message_admins("Admin [key_name_admin(user)] has loaded [away_name] away mission.")
+ log_admin("Admin [key_name(user)] has loaded [away_name] away mission.")
if(!away_level)
message_admins("Loading [away_name] failed!")
return
diff --git a/code/controllers/subsystem/weather.dm b/code/controllers/subsystem/weather.dm
index 78c99f47903..b8496a623eb 100644
--- a/code/controllers/subsystem/weather.dm
+++ b/code/controllers/subsystem/weather.dm
@@ -86,15 +86,9 @@ SUBSYSTEM_DEF(weather)
/datum/controller/subsystem/weather/proc/get_weather_by_type(type)
return locate(type) in processing
-/**
- * Calls end() on all current weather effects that are currently processing in the weather subsystem.
- */
-/client/proc/stop_weather()
- set category = "Debug"
- set name = "Stop All Active Weather"
-
- log_admin("[key_name(src)] stopped all currently active weather.")
- message_admins("[key_name_admin(src)] stopped all currently active weather.")
+ADMIN_VERB(stop_weather, R_DEBUG|R_ADMIN, "Stop All Active Weather", "Stop all currently active weather.", ADMIN_CATEGORY_DEBUG)
+ log_admin("[key_name(user)] stopped all currently active weather.")
+ message_admins("[key_name_admin(user)] stopped all currently active weather.")
for(var/datum/weather/current_weather as anything in SSweather.processing)
if(current_weather in SSweather.processing)
current_weather.end()
diff --git a/code/datums/brain_damage/imaginary_friend.dm b/code/datums/brain_damage/imaginary_friend.dm
index 18ca8172968..e3891392d1a 100644
--- a/code/datums/brain_damage/imaginary_friend.dm
+++ b/code/datums/brain_damage/imaginary_friend.dm
@@ -217,11 +217,11 @@
message = capitalize(message)
if(message_mods[RADIO_EXTENSION] == MODE_ADMIN)
- client?.cmd_admin_say(message)
+ SSadmin_verbs.dynamic_invoke_verb(client, /datum/admin_verb/cmd_admin_say, message)
return
if(message_mods[RADIO_EXTENSION] == MODE_DEADMIN)
- client?.dsay(message)
+ SSadmin_verbs.dynamic_invoke_verb(client, /datum/admin_verb/dsay, message)
return
if(check_emote(message, forced))
diff --git a/code/datums/components/puzzgrid.dm b/code/datums/components/puzzgrid.dm
index e91bcdb3002..d7e264f651f 100644
--- a/code/datums/components/puzzgrid.dm
+++ b/code/datums/components/puzzgrid.dm
@@ -280,12 +280,7 @@
var/list/answers = list()
var/description
-/// Debug verb for validating that all puzzgrids can be created successfully.
-/// Locked behind a verb because it's fairly slow and memory intensive.
-/client/proc/validate_puzzgrids()
- set name = "Validate Puzzgrid Config"
- set category = "Debug"
-
+ADMIN_VERB(validate_puzzgrids, R_DEBUG, "Validate Puzzgrid Config", "Validate the puzzgrid config to ensure it's set up correctly.", ADMIN_CATEGORY_DEBUG)
var/line_number = 0
for (var/line in world.file2list(PUZZGRID_CONFIG))
@@ -296,16 +291,16 @@
var/line_json_decoded = safe_json_decode(line)
if (isnull(line_json_decoded))
- to_chat(src, span_warning("Line [line_number] in puzzgrids.txt is not a JSON: [line]"))
+ to_chat(user, span_warning("Line [line_number] in puzzgrids.txt is not a JSON: [line]"))
continue
var/datum/puzzgrid/puzzgrid = new
var/populate_result = puzzgrid.populate(line_json_decoded)
if (populate_result != TRUE)
- to_chat(src, span_warning("Line [line_number] in puzzgrids.txt is not formatted correctly: [populate_result]"))
+ to_chat(user, span_warning("Line [line_number] in puzzgrids.txt is not formatted correctly: [populate_result]"))
- to_chat(src, span_notice("Validated. If you did not see any errors, you're in the clear."))
+ to_chat(user, span_notice("Validated. If you did not see any errors, you're in the clear."))
#undef PUZZGRID_CONFIG
#undef PUZZGRID_GROUP_COUNT
diff --git a/code/datums/keybinding/admin.dm b/code/datums/keybinding/admin.dm
index 80936aa41e7..1e94f71e58a 100644
--- a/code/datums/keybinding/admin.dm
+++ b/code/datums/keybinding/admin.dm
@@ -23,7 +23,7 @@
. = ..()
if(.)
return
- user.admin_ghost()
+ SSadmin_verbs.dynamic_invoke_verb(user, /datum/admin_verb/admin_ghost)
return TRUE
/datum/keybinding/admin/player_panel_new
@@ -51,7 +51,7 @@
. = ..()
if(.)
return
- user.togglebuildmodeself()
+ SSadmin_verbs.dynamic_invoke_verb(user, /datum/admin_verb/build_mode_self)
return TRUE
/datum/keybinding/admin/stealthmode
@@ -65,7 +65,7 @@
. = ..()
if(.)
return
- user.stealth()
+ SSadmin_verbs.dynamic_invoke_verb(user, /datum/admin_verb/stealth)
return TRUE
/datum/keybinding/admin/invisimin
@@ -79,7 +79,7 @@
. = ..()
if(.)
return
- user.invisimin()
+ SSadmin_verbs.dynamic_invoke_verb(user, /datum/admin_verb/invisimin)
return TRUE
/datum/keybinding/admin/deadsay
@@ -107,7 +107,7 @@
. = ..()
if(.)
return
- user.deadmin()
+ SSadmin_verbs.dynamic_invoke_verb(user, /datum/admin_verb/deadmin)
return TRUE
/datum/keybinding/admin/readmin
@@ -135,5 +135,5 @@
. = ..()
if(.)
return
- user.holder?.display_tags()
+ SSadmin_verbs.dynamic_invoke_verb(user, /datum/admin_verb/display_tags)
return TRUE
diff --git a/code/datums/station_traits/admin_panel.dm b/code/datums/station_traits/admin_panel.dm
index 02eca48b54f..67669027c54 100644
--- a/code/datums/station_traits/admin_panel.dm
+++ b/code/datums/station_traits/admin_panel.dm
@@ -1,10 +1,6 @@
-/// Opens the station traits admin panel
-/datum/admins/proc/station_traits_panel()
- set name = "Modify Station Traits"
- set category = "Admin.Events"
-
+ADMIN_VERB(station_traits_panel, R_FUN, "Modify Station Traits", "Modify the station traits for the next round.", ADMIN_CATEGORY_EVENTS)
var/static/datum/station_traits_panel/station_traits_panel = new
- station_traits_panel.ui_interact(usr)
+ station_traits_panel.ui_interact(user.mob)
/datum/station_traits_panel
var/static/list/future_traits
diff --git a/code/game/atom/atom_vv.dm b/code/game/atom/atom_vv.dm
index 8830a4af2f4..10a6cbff24a 100644
--- a/code/game/atom/atom_vv.dm
+++ b/code/game/atom/atom_vv.dm
@@ -67,14 +67,10 @@
message_admins(span_notice("[key_name(usr)] has added [amount] units of [chosen_id] to [src]"))
if(href_list[VV_HK_TRIGGER_EXPLOSION])
- if(!check_rights(R_FUN))
- return
- usr.client.cmd_admin_explosion(src)
+ return SSadmin_verbs.dynamic_invoke_verb(usr, /datum/admin_verb/admin_explosion, src)
if(href_list[VV_HK_TRIGGER_EMP])
- if(!check_rights(R_FUN))
- return
- usr.client.cmd_admin_emp(src)
+ return SSadmin_verbs.dynamic_invoke_verb(usr, /datum/admin_verb/admin_emp, src)
if(href_list[VV_HK_SHOW_HIDDENPRINTS])
if(!check_rights(R_ADMIN))
diff --git a/code/game/objects/objs.dm b/code/game/objects/objs.dm
index 71bc78fa4c4..b6946dffc9a 100644
--- a/code/game/objects/objs.dm
+++ b/code/game/objects/objs.dm
@@ -147,9 +147,7 @@ GLOBAL_LIST_EMPTY(objects_by_id_tag)
return
if(href_list[VV_HK_OSAY])
- if(!check_rights(R_FUN, FALSE))
- return
- usr.client.object_say(src)
+ return SSadmin_verbs.dynamic_invoke_verb(usr, /datum/admin_verb/object_say, src)
if(href_list[VV_HK_MASS_DEL_TYPE])
if(!check_rights(R_DEBUG|R_SERVER))
diff --git a/code/modules/admin/admin.dm b/code/modules/admin/admin.dm
index 99aa63325ad..10b9a58b870 100644
--- a/code/modules/admin/admin.dm
+++ b/code/modules/admin/admin.dm
@@ -48,14 +48,9 @@
////////////////////////////////////////////////////////////////////////////////////////////////ADMIN HELPER PROCS
-/datum/admins/proc/spawn_atom(object as text)
- set category = "Debug"
- set desc = "(atom path) Spawn an atom"
- set name = "Spawn"
-
- if(!check_rights(R_SPAWN) || !object)
+ADMIN_VERB(spawn_atom, R_SPAWN, "Spawn", "Spawn an atom.", ADMIN_CATEGORY_DEBUG, object as text)
+ if(!object)
return
-
var/list/preparsed = splittext(object,":")
var/path = preparsed[1]
var/amount = 1
@@ -65,7 +60,7 @@
var/chosen = pick_closest_path(path)
if(!chosen)
return
- var/turf/T = get_turf(usr)
+ var/turf/T = get_turf(user.mob)
if(ispath(chosen, /turf))
T.ChangeTurf(chosen)
@@ -74,21 +69,14 @@
var/atom/A = new chosen(T)
A.flags_1 |= ADMIN_SPAWNED_1
- log_admin("[key_name(usr)] spawned [amount] x [chosen] at [AREACOORD(usr)]")
+ log_admin("[key_name(user)] spawned [amount] x [chosen] at [AREACOORD(user.mob)]")
BLACKBOX_LOG_ADMIN_VERB("Spawn Atom")
-/datum/admins/proc/podspawn_atom(object as text)
- set category = "Debug"
- set desc = "(atom path) Spawn an atom via supply drop"
- set name = "Podspawn"
-
- if(!check_rights(R_SPAWN))
- return
-
+ADMIN_VERB(spawn_atom_pod, R_SPAWN, "PodSpawn", "Spawn an atom via supply drop.", ADMIN_CATEGORY_DEBUG, object as text)
var/chosen = pick_closest_path(object)
if(!chosen)
return
- var/turf/target_turf = get_turf(usr)
+ var/turf/target_turf = get_turf(user.mob)
if(ispath(chosen, /turf))
target_turf.ChangeTurf(chosen)
@@ -101,25 +89,18 @@
var/atom/A = new chosen(pod)
A.flags_1 |= ADMIN_SPAWNED_1
- log_admin("[key_name(usr)] pod-spawned [chosen] at [AREACOORD(usr)]")
+ log_admin("[key_name(user)] pod-spawned [chosen] at [AREACOORD(user.mob)]")
BLACKBOX_LOG_ADMIN_VERB("Podspawn Atom")
-/datum/admins/proc/spawn_cargo(object as text)
- set category = "Debug"
- set desc = "(atom path) Spawn a cargo crate"
- set name = "Spawn Cargo"
-
- if(!check_rights(R_SPAWN))
- return
-
+ADMIN_VERB(spawn_cargo, R_SPAWN, "Spawn Cargo", "Spawn a cargo crate.", ADMIN_CATEGORY_DEBUG, object as text)
var/chosen = pick_closest_path(object, make_types_fancy(subtypesof(/datum/supply_pack)))
if(!chosen)
return
var/datum/supply_pack/S = new chosen
S.admin_spawned = TRUE
- S.generate(get_turf(usr))
+ S.generate(get_turf(user.mob))
- log_admin("[key_name(usr)] spawned cargo pack [chosen] at [AREACOORD(usr)]")
+ log_admin("[key_name(user)] spawned cargo pack [chosen] at [AREACOORD(user.mob)]")
BLACKBOX_LOG_ADMIN_VERB("Spawn Cargo")
/datum/admins/proc/dynamic_mode_options(mob/user)
@@ -246,10 +227,8 @@
log_admin(logged_message)
message_admins(logged_message)
-/datum/admins/proc/create_or_modify_area()
- set category = "Debug"
- set name = "Create or modify area"
- create_area(usr)
+ADMIN_VERB(create_or_modify_area, R_DEBUG, "Create Or Modify Area", "Create of modify an area. wow.", ADMIN_CATEGORY_DEBUG)
+ create_area(user.mob)
//Kicks all the clients currently in the lobby. The second parameter (kick_only_afk) determins if an is_afk() check is ran, or if all clients are kicked
//defaults to kicking everyone (afk + non afk clients in the lobby)
diff --git a/code/modules/admin/admin_fax_panel.dm b/code/modules/admin/admin_fax_panel.dm
index fe1f03d7d7e..8874b6f38eb 100644
--- a/code/modules/admin/admin_fax_panel.dm
+++ b/code/modules/admin/admin_fax_panel.dm
@@ -1,15 +1,6 @@
-/**
- * If client have R_ADMIN flag, opens an admin fax panel.
- */
-/client/proc/fax_panel()
- set category = "Admin.Events"
- set name = "Fax Panel"
-
- if(!check_rights(R_ADMIN))
- return
-
- var/datum/fax_panel_interface/ui = new(usr)
- ui.ui_interact(usr)
+ADMIN_VERB(fax_panel, R_ADMIN, "Fax Panel", "View and respond to faxes sent to CC.", ADMIN_CATEGORY_EVENTS)
+ var/datum/fax_panel_interface/ui = new /datum/fax_panel_interface(user.mob)
+ ui.ui_interact(user.mob)
/// Admin Fax Panel. Tool for sending fax messages faster.
/datum/fax_panel_interface
@@ -97,15 +88,15 @@
switch(action)
if("follow")
- if(!isobserver(usr))
- usr.client?.admin_ghost()
+ if(!isobserver(ui.user))
+ SSadmin_verbs.dynamic_invoke_verb(ui.user, /datum/admin_verb/admin_ghost)
- usr.client?.admin_follow(action_fax)
+ ui.user.client?.admin_follow(action_fax)
if("preview") // see saved variant
if(!fax_paper)
return
- fax_paper.ui_interact(usr)
+ fax_paper.ui_interact(ui.user)
if("save") // save paper
if(params["paperName"])
@@ -129,7 +120,7 @@
if(stamp)
fax_paper.add_stamp(stamp_class, params["stampX"], params["stampY"], params["stampAngle"], stamp)
- fax_paper.update_static_data(usr) // OK, it's work, and update UI.
+ fax_paper.update_static_data(ui.user) // OK, it's work, and update UI.
if("send")
//copy
@@ -137,9 +128,9 @@
our_fax.name = fax_paper.name
//send
action_fax.receive(our_fax, sending_fax_name)
- message_admins("[key_name_admin(usr)] has sent a custom fax message to [action_fax.name][ADMIN_FLW(action_fax)][ADMIN_SHOW_PAPER(fax_paper)].")
- log_admin("[key_name(usr)] has sent a custom fax message to [action_fax.name]")
+ message_admins("[key_name_admin(ui.user)] has sent a custom fax message to [action_fax.name][ADMIN_FLW(action_fax)][ADMIN_SHOW_PAPER(fax_paper)].")
+ log_admin("[key_name(ui.user)] has sent a custom fax message to [action_fax.name]")
if("createPaper")
- var/obj/item/paper/our_paper = fax_paper.copy(/obj/item/paper, usr.loc)
+ var/obj/item/paper/our_paper = fax_paper.copy(/obj/item/paper, ui.user.loc)
our_paper.name = fax_paper.name
diff --git a/code/modules/admin/admin_investigate.dm b/code/modules/admin/admin_investigate.dm
index 94ea182891f..edc3525bf2f 100644
--- a/code/modules/admin/admin_investigate.dm
+++ b/code/modules/admin/admin_investigate.dm
@@ -10,13 +10,8 @@
WRITE_FILE(F, "[time_stamp(format = "YYYY-MM-DD hh:mm:ss")] [REF(src)] ([x],[y],[z]) || [source] [message]
")
-/client/proc/investigate_show()
- set name = "Investigate"
- set category = "Admin.Game"
- if(!holder)
- return
-
- var/list/investigates = list(
+ADMIN_VERB(investigate_show, R_NONE, "Investigate", "Browse various detailed logs.", ADMIN_CATEGORY_GAME)
+ var/static/list/investigates = list(
INVESTIGATE_ACCESSCHANGES,
INVESTIGATE_ATMOS,
INVESTIGATE_BOTANY,
@@ -48,7 +43,7 @@
var/list/combined = sort_list(logs_present) + sort_list(logs_missing)
- var/selected = tgui_input_list(src, "Investigate what?", "Investigation", combined)
+ var/selected = tgui_input_list(user, "Investigate what?", "Investigation", combined)
if(isnull(selected))
return
if(!(selected in combined) || selected == "---")
@@ -62,6 +57,6 @@
var/F = file("[GLOB.log_directory]/[selected].html")
if(!fexists(F))
- to_chat(src, span_danger("No [selected] logfile was found."), confidential = TRUE)
+ to_chat(user, span_danger("No [selected] logfile was found."), confidential = TRUE)
return
- src << browse(F,"window=investigate[selected];size=800x300")
+ user << browse(F,"window=investigate[selected];size=800x300")
diff --git a/code/modules/admin/admin_pda_message.dm b/code/modules/admin/admin_pda_message.dm
index 44ca86f893e..c1c4fef0b57 100644
--- a/code/modules/admin/admin_pda_message.dm
+++ b/code/modules/admin/admin_pda_message.dm
@@ -1,12 +1,6 @@
-///Allows an admin to send messages on PDA
-/client/proc/message_pda()
- set name = "PDA Message"
- set category = "Admin.Events"
- if(!holder || !check_rights(R_ADMIN))
- return
-
- holder.message_pda()
+ADMIN_VERB(message_pda, R_ADMIN, "PDA Message", "Send a message to a user's PDA.", ADMIN_CATEGORY_EVENTS)
+ user.holder.message_pda()
///Opens up the PDA Message Panel
/datum/admins/proc/message_pda()
diff --git a/code/modules/admin/admin_verbs.dm b/code/modules/admin/admin_verbs.dm
index 73951cfddbc..352ccab297a 100644
--- a/code/modules/admin/admin_verbs.dm
+++ b/code/modules/admin/admin_verbs.dm
@@ -1,506 +1,103 @@
-//admin verb groups - They can overlap if you so wish. Only one of each verb will exist in the verbs list regardless
-//the procs are cause you can't put the comments in the GLOB var define
-GLOBAL_LIST_INIT(admin_verbs_default, world.AVerbsDefault())
-GLOBAL_PROTECT(admin_verbs_default)
-/world/proc/AVerbsDefault()
- return list(
- /client/proc/cmd_admin_pm_context, /*right-click adminPM interface*/
- /client/proc/cmd_admin_pm_panel, /*admin-pm list*/
- /client/proc/cmd_admin_say, /*admin-only ooc chat*/
- /client/proc/deadmin, /*destroys our own admin datum so we can play as a regular player*/
- /client/proc/debugstatpanel,
- /client/proc/debug_variables, /*allows us to -see- the variables of any instance in the game. +VAREDIT needed to modify*/
- /client/proc/dsay, /*talk in deadchat using our ckey/fakekey*/
- /client/proc/fix_air, /*resets air in designated radius to its default atmos composition*/
- /client/proc/hide_verbs, /*hides all our adminverbs*/
- /client/proc/investigate_show, /*various admintools for investigation. Such as a singulo grief-log*/
- /client/proc/mark_datum_mapview,
- /client/proc/reestablish_db_connection, /*reattempt a connection to the database*/
- /client/proc/reload_admins,
- /client/proc/requests,
- /client/proc/secrets,
- /client/proc/stop_sounds,
- /client/proc/tag_datum_mapview,
-
- /client/proc/addbunkerbypass, /*NOVA EDIT ADDITION - PANICBUNKER*/
- /client/proc/cmd_loud_admin_say, /*admin-only chat except its annoying - NOVA EDIT ADDITION - ADMIN*/
- /client/proc/remove_liquid, /*NOVA EDIT ADDITION*/
- /client/proc/revokebunkerbypass, /*NOVA EDIT ADDITION - PANICBUNKER*/
- )
-GLOBAL_LIST_INIT(admin_verbs_admin, world.AVerbsAdmin())
-GLOBAL_PROTECT(admin_verbs_admin)
-/world/proc/AVerbsAdmin()
- return list(
-// Admin datums
- /datum/admins/proc/access_news_network, /*allows access of newscasters*/
- /datum/admins/proc/announce, /*priority announce something to all clients.*/
- /datum/admins/proc/display_tags,
- /datum/admins/proc/fishing_calculator,
- /datum/admins/proc/known_alts_panel,
- /datum/admins/proc/show_lag_switch_panel,
- /datum/admins/proc/open_borgopanel,
- /datum/admins/proc/open_shuttlepanel, /* Opens shuttle manipulator UI */
- /datum/admins/proc/paintings_manager,
- /datum/admins/proc/set_admin_notice, /*announcement all clients see when joining the server.*/
- /datum/admins/proc/show_player_panel, /*shows an interface for individual players, with various links (links require additional flags*/
- /datum/admins/proc/toggleenter, /*toggles whether people can join the current game*/
- /datum/admins/proc/toggleguests, /*toggles whether guests can join the current game*/
- /datum/admins/proc/toggleooc, /*toggles ooc on/off for everyone*/
- /datum/admins/proc/toggleoocdead, /*toggles ooc on/off for everyone who is dead*/
- /datum/admins/proc/trophy_manager,
- /datum/admins/proc/view_all_circuits,
- /datum/verbs/menu/Admin/verb/playerpanel, /* It isn't /datum/admin but it fits no less */
- /datum/admins/proc/change_shuttle_events, //allows us to change the shuttle events
- /datum/admins/proc/reset_tram, //tram related admin actions
-// Client procs
- /client/proc/admin_call_shuttle, /*allows us to call the emergency shuttle*/
- /client/proc/admin_cancel_shuttle, /*allows us to cancel the emergency shuttle, sending it back to centcom*/
- /client/proc/admin_disable_shuttle, /*allows us to disable the emergency shuttle admin-wise so that it cannot be called*/
- /client/proc/admin_enable_shuttle, /*undoes the above*/
- /client/proc/admin_ghost, /*allows us to ghost/reenter body at will*/
- /client/proc/admin_hostile_environment, /*Allows admins to prevent the emergency shuttle from leaving, also lets admins clear hostile environments if theres one stuck*/
- /client/proc/centcom_podlauncher,/*Open a window to launch a Supplypod and configure it or it's contents*/
- /client/proc/check_ai_laws, /*shows AI and borg laws*/
- /client/proc/check_antagonists, /*shows all antags*/
- /client/proc/cmd_admin_check_contents, /*displays the contents of an instance*/
- /client/proc/cmd_admin_check_player_exp, /* shows players by playtime */
- /client/proc/cmd_admin_create_centcom_report,
- /client/proc/cmd_admin_delete, /*delete an instance/object/mob/etc*/
- /client/proc/cmd_admin_direct_narrate, /*send text directly to a player with no padding. Useful for narratives and fluff-text*/
- /client/proc/cmd_admin_headset_message, /*send a message to somebody through their headset as CentCom*/
- /client/proc/cmd_admin_local_narrate, /*sends text to all mobs within view of atom*/
- /client/proc/cmd_admin_subtle_message, /*send a message to somebody as a 'voice in their head'*/
- /client/proc/cmd_admin_world_narrate, /*sends text to all players with no padding*/
- /client/proc/cmd_change_command_name,
- /client/proc/create_mob_worm,
- /client/proc/fax_panel, /*send a paper to fax*/
- /client/proc/force_load_lazy_template,
- /client/proc/game_panel, /*game panel, allows to change game-mode etc*/
- /client/proc/Getmob, /*teleports a mob to our location*/
- /client/proc/Getkey, /*teleports a mob with a certain ckey to our location*/
- /client/proc/getserverlogs, /*for accessing server logs*/
- /client/proc/getcurrentlogs, /*for accessing server logs for the current round*/
- /client/proc/ghost_pool_protection, /*opens a menu for toggling ghost roles*/
- /client/proc/invisimin, /*allows our mob to go invisible/visible*/
- /client/proc/jumptoarea,
- /client/proc/jumptokey, /*allows us to jump to the location of a mob with a certain ckey*/
- /client/proc/jumptomob, /*allows us to jump to a specific mob*/
- /client/proc/jumptoturf, /*allows us to jump to a specific turf*/
- /client/proc/jumptocoord, /*we ghost and jump to a coordinate*/
- /client/proc/list_bombers,
- /client/proc/list_dna,
- /client/proc/list_fingerprints,
- /client/proc/list_law_changes,
- /client/proc/list_signalers,
- /client/proc/manage_sect, /*manage chaplain religious sect*/
- /client/proc/message_pda, /*send a message to somebody on PDA*/
- /client/proc/respawn_character,
- /client/proc/show_manifest,
- /client/proc/toggle_AI_interact, /*toggle admin ability to interact with machines as an AI*/
- /client/proc/toggle_combo_hud, /* toggle display of the combination pizza antag and taco sci/med/eng hud */
- /client/proc/toggle_view_range, /*changes how far we can see*/
- /client/proc/cmd_admin_law_panel,
- /client/proc/log_viewer_new,
- /client/proc/player_ticket_history,
- /datum/admins/proc/toggleaooc, /*Toggle Antag OOC - NOVA EDIT ADDITION*/
- /datum/admins/proc/toggledchat, /*NOVA EDIT ADDITION*/
- /datum/admins/proc/togglesooc, /*Toggle Security OOC - NOVA EDIT ADDITION*/
- /client/proc/admin_open_event_spawners_menu, /*EVENTS - NOVA EDIT ADDITION*/
- /client/proc/request_help, /*NOVA EDIT ADDITION*/
- /client/proc/view_opfors, /*OPFOR - NOVA EDIT ADDITION*/
- /client/proc/lorecaster_story_manager, /* NOVA EDIT ADDITION */
- )
-GLOBAL_LIST_INIT(admin_verbs_ban, list(/client/proc/unban_panel, /client/proc/ban_panel, /client/proc/stickybanpanel, /client/proc/library_control))
-GLOBAL_PROTECT(admin_verbs_ban)
-GLOBAL_LIST_INIT(admin_verbs_sounds, list(/client/proc/play_local_sound, /client/proc/play_direct_mob_sound, /client/proc/play_sound, /client/proc/set_round_end_sound))
-GLOBAL_PROTECT(admin_verbs_sounds)
-GLOBAL_LIST_INIT(admin_verbs_fun, list(
-// Admin datums
- /datum/admins/proc/station_traits_panel,
-// Client procs
- /client/proc/admin_away,
- /client/proc/add_marked_mob_ability,
- /client/proc/admin_change_sec_level,
- /client/proc/cinematic,
- /client/proc/cmd_admin_add_freeform_ai_law,
- /client/proc/cmd_admin_gib_self,
- /client/proc/cmd_select_equipment,
- /client/proc/command_report_footnote,
- /client/proc/delay_command_report,
- /client/proc/drop_bomb,
- /client/proc/drop_dynex_bomb,
- /client/proc/forceEvent,
- /client/proc/mass_zombie_cure,
- /client/proc/mass_zombie_infection,
- /client/proc/object_say,
- /client/proc/polymorph_all,
- /client/proc/remove_marked_mob_ability,
- /client/proc/reset_ooc,
- /client/proc/run_weather,
- /client/proc/set_dynex_scale,
- /client/proc/set_ooc,
- /client/proc/show_tip,
- /client/proc/smite,
- /client/proc/summon_ert,
- /client/proc/toggle_nuke,
- /client/proc/toggle_random_events,
- /client/proc/admin_change_title_screen, /*NOVA EDIT ADDITION*/
- /client/proc/change_title_screen_html, /*NOVA EDIT ADDITION*/
- /client/proc/change_title_screen_notice, /*NOVA EDIT ADDITION*/
- /client/proc/fix_say, /*NOVA EDIT ADDITION*/
- /client/proc/one_click_antag, /*ONE CLICK ANTAG - NOVA EDIT ADDITION*/
- /client/proc/request_more_opfor, /*NOVA EDIT ADDITION*/
- /client/proc/spawn_liquid, /*NOVA EDIT ADDITION*/
- /client/proc/spawn_mob_spawner, /*NOVA EDIT ADDITION*/
- /client/proc/spawn_pollution, /*NOVA EDIT ADDITION*/
- /client/proc/intensity_credits_panel, /*NOVA EDIT ADDITION*/
- /client/proc/toggle_bsa, /*NOVA EDIT ADDITION*/
- /client/proc/try_stop_delam, /*NOVA EDIT ADDITION*/
- /client/proc/toggle_delam_suppression, /*NOVA EDIT ADDITION*/
- ))
-GLOBAL_PROTECT(admin_verbs_fun)
-GLOBAL_LIST_INIT(admin_verbs_spawn, list(/datum/admins/proc/spawn_atom, /datum/admins/proc/podspawn_atom, /datum/admins/proc/spawn_cargo, /datum/admins/proc/spawn_objasmob, /client/proc/respawn_character, /datum/admins/proc/beaker_panel))
-GLOBAL_PROTECT(admin_verbs_spawn)
-GLOBAL_LIST_INIT(admin_verbs_server, world.AVerbsServer())
-GLOBAL_PROTECT(admin_verbs_server)
-/world/proc/AVerbsServer()
- return list(
-// Admin datums
- /datum/admins/proc/delay,
- /datum/admins/proc/delay_round_end,
- /datum/admins/proc/end_round,
- /datum/admins/proc/restart,
- /datum/admins/proc/startnow,
- /datum/admins/proc/toggleaban,
- /datum/admins/proc/toggleAI,
-// Client procs
- /client/proc/adminchangemap,
- /client/proc/cmd_admin_delete, /*delete an instance/object/mob/etc*/
- /client/proc/cmd_debug_del_all,
- /client/proc/cmd_debug_force_del_all,
- /client/proc/cmd_debug_hard_del_all,
- /client/proc/everyone_random,
- /client/proc/forcerandomrotate,
- /client/proc/generate_job_config,
- /client/proc/panicbunker,
- /client/proc/toggle_cdn,
- /client/proc/toggle_hub,
- /client/proc/toggle_interviews,
- /client/proc/toggle_random_events,
- )
-GLOBAL_LIST_INIT(admin_verbs_debug, world.AVerbsDebug())
-GLOBAL_PROTECT(admin_verbs_debug)
-/world/proc/AVerbsDebug()
- return list(
- #ifdef TESTING /* Keep these at the top to not make the list look fugly */
- /client/proc/check_missing_sprites,
- #endif
- /proc/machine_upgrade,
- /datum/admins/proc/create_or_modify_area,
- /client/proc/adventure_manager,
- /client/proc/atmos_control,
- /client/proc/callproc,
- /client/proc/callproc_datum,
- /client/proc/check_bomb_impacts,
- /client/proc/check_timer_sources,
- /client/proc/clear_dynamic_transit,
- /client/proc/cmd_admin_debug_traitor_objectives,
- /client/proc/cmd_admin_delete,
- /client/proc/cmd_admin_list_open_jobs,
- /client/proc/cmd_admin_toggle_fov,
- /client/proc/cmd_debug_del_all,
- /client/proc/cmd_debug_force_del_all,
- /client/proc/cmd_debug_hard_del_all,
- /client/proc/cmd_debug_make_powernets,
- /client/proc/cmd_debug_mob_lists,
- /client/proc/cmd_display_del_log,
- /client/proc/cmd_display_init_log,
- /client/proc/cmd_display_overlay_log,
- /client/proc/Debug2,
- /client/proc/debug_controller,
- /client/proc/debug_hallucination_weighted_list_per_type,
- /client/proc/debug_huds,
- /client/proc/debugNatureMapGenerator,
- /client/proc/debug_plane_masters,
- /client/proc/debug_spell_requirements,
- /client/proc/display_sendmaps,
- /client/proc/enable_mapping_verbs,
- /client/proc/generate_wikichem_list,
- /client/proc/get_dynex_power, /*debug verbs for dynex explosions.*/
- /client/proc/get_dynex_range, /*debug verbs for dynex explosions.*/
- /client/proc/jump_to_ruin,
- /client/proc/load_circuit,
- /client/proc/map_export,
- /client/proc/map_template_load,
- /client/proc/map_template_upload,
- /client/proc/modify_goals,
- /client/proc/open_colorblind_test,
- /client/proc/open_lua_editor,
- /client/proc/outfit_manager,
- /client/proc/populate_world,
- /client/proc/pump_random_event,
- /client/proc/print_cards,
- /client/proc/reestablish_tts_connection,
- /client/proc/reload_cards,
- /client/proc/reload_configuration,
- /client/proc/restart_controller,
- /client/proc/run_empty_query,
- /client/proc/SDQL2_query,
- /client/proc/set_dynex_scale,
- /client/proc/spawn_debug_full_crew,
- /client/proc/test_cardpack_distribution,
- /client/proc/test_movable_UI,
- /client/proc/test_snap_UI,
- /client/proc/toggle_cdn,
- /client/proc/toggle_medal_disable,
- /client/proc/unload_ctf,
- /client/proc/validate_cards,
- /client/proc/validate_puzzgrids,
- /client/proc/GeneratePipeSpritesheet,
- /client/proc/view_runtimes,
- /client/proc/stop_weather,
- /client/proc/reload_interactions, /*NOVA EDIT ADDITION*/
- /client/proc/test_area_spawner, /*AUTOMAPPER - NOVA EDIT ADDITION*/
- /client/proc/toggle_liquid_debug, /*NOVA EDIT ADDITION*/
-
- /datum/admins/proc/delay, /*FLUFFY FRONTIER ADDITION - EVENTMAKER QOL*/
- /datum/admins/proc/end_round, /*FLUFFY FRONTIER ADDITION - EVENTMAKER QOL*/
- /client/proc/adminchangemap, /*FLUFFY FRONTIER ADDITION - EVENTMAKER QOL*/
- )
-GLOBAL_LIST_INIT(admin_verbs_possess, list(/proc/possess, GLOBAL_PROC_REF(release)))
-GLOBAL_PROTECT(admin_verbs_possess)
-/// NOVA EDIT BEGIN - Player Rank Manager - ORIGINAL: GLOBAL_LIST_INIT(admin_verbs_permissions, list(/client/proc/edit_admin_permissions))
-GLOBAL_LIST_INIT(admin_verbs_permissions, list(
- /client/proc/edit_admin_permissions,
- /client/proc/manage_player_ranks,
- /client/proc/migrate_player_ranks,
- ))
-/// NOVA EDIT END
-GLOBAL_PROTECT(admin_verbs_permissions)
-GLOBAL_LIST_INIT(admin_verbs_poll, list(/client/proc/poll_panel))
-GLOBAL_PROTECT(admin_verbs_poll)
-
/client/proc/add_admin_verbs()
- if(holder)
- control_freak = CONTROL_FREAK_SKIN | CONTROL_FREAK_MACROS
-
- var/rights = holder.rank_flags()
- add_verb(src, GLOB.admin_verbs_default)
- if(rights & R_BUILD)
- add_verb(src, /client/proc/togglebuildmodeself)
- if(rights & R_ADMIN)
- add_verb(src, GLOB.admin_verbs_admin)
- if(rights & R_BAN)
- add_verb(src, GLOB.admin_verbs_ban)
- if(rights & R_FUN)
- add_verb(src, GLOB.admin_verbs_fun)
- if(rights & R_SERVER)
- add_verb(src, GLOB.admin_verbs_server)
- if(rights & R_DEBUG)
- add_verb(src, GLOB.admin_verbs_debug)
- if(rights & R_POSSESS)
- add_verb(src, GLOB.admin_verbs_possess)
- if(rights & R_PERMISSIONS)
- add_verb(src, GLOB.admin_verbs_permissions)
- if(rights & R_STEALTH)
- add_verb(src, /client/proc/stealth)
- if(rights & R_POLL)
- add_verb(src, GLOB.admin_verbs_poll)
- if(rights & R_SOUND)
- add_verb(src, GLOB.admin_verbs_sounds)
- if(CONFIG_GET(string/invoke_youtubedl))
- add_verb(src, /client/proc/play_web_sound)
- if(rights & R_SPAWN)
- add_verb(src, GLOB.admin_verbs_spawn)
-#ifdef MAP_TEST
- remove_verb(src, /client/proc/enable_mapping_verbs)
- add_verb(src, list(/client/proc/disable_mapping_verbs, GLOB.admin_verbs_debug_mapping))
-#endif
+ control_freak = CONTROL_FREAK_SKIN | CONTROL_FREAK_MACROS
+ SSadmin_verbs.assosciate_admin(src)
/client/proc/remove_admin_verbs()
- remove_verb(src, list(
- GLOB.admin_verbs_default,
- /client/proc/togglebuildmodeself,
- GLOB.admin_verbs_admin,
- GLOB.admin_verbs_ban,
- GLOB.admin_verbs_fun,
- GLOB.admin_verbs_server,
- GLOB.admin_verbs_debug,
- GLOB.admin_verbs_possess,
- GLOB.admin_verbs_permissions,
- /client/proc/stealth,
- GLOB.admin_verbs_poll,
- GLOB.admin_verbs_sounds,
- /client/proc/play_web_sound,
- GLOB.admin_verbs_spawn,
- /*Debug verbs added by "show debug verbs"*/
- GLOB.admin_verbs_debug_mapping,
- /client/proc/disable_mapping_verbs,
- /client/proc/readmin
- ))
-
-/client/proc/hide_verbs()
- set name = "Adminverbs - Hide All"
- set category = "Admin"
-
- remove_admin_verbs()
- add_verb(src, /client/proc/show_verbs)
-
- to_chat(src, span_interface("Almost all of your adminverbs have been hidden."), confidential = TRUE)
- BLACKBOX_LOG_ADMIN_VERB("Hide All Adminverbs")
- return
-
-/client/proc/show_verbs()
- set name = "Adminverbs - Show"
- set category = "Admin"
-
- remove_verb(src, /client/proc/show_verbs)
- add_admin_verbs()
-
- to_chat(src, span_interface("All of your adminverbs are now visible."), confidential = TRUE)
- BLACKBOX_LOG_ADMIN_VERB("Show Adminverbs")
-
+ control_freak = initial(control_freak)
+ SSadmin_verbs.deassosciate_admin(src)
+ADMIN_VERB(hide_verbs, R_NONE, "Adminverbs - Hide All", "Hide most of your admin verbs.", ADMIN_CATEGORY_MAIN)
+ user.remove_admin_verbs()
+ add_verb(user, /client/proc/show_verbs)
+ to_chat(user, span_interface("Almost all of your adminverbs have been hidden."), confidential = TRUE)
+ BLACKBOX_LOG_ADMIN_VERB("Hide All Adminverbs")
-/client/proc/admin_ghost()
- set category = "Admin.Game"
- set name = "Aghost"
- if(!holder)
- return
+ADMIN_VERB(admin_ghost, R_ADMIN, "AGhost", "Become a ghost without DNR.", ADMIN_CATEGORY_GAME)
. = TRUE
- if(isobserver(mob))
+ if(isobserver(user.mob))
//re-enter
- var/mob/dead/observer/ghost = mob
+ var/mob/dead/observer/ghost = user.mob
if(!ghost.mind || !ghost.mind.current) //won't do anything if there is no body
return FALSE
if(!ghost.can_reenter_corpse)
- log_admin("[key_name(usr)] re-entered corpse")
- message_admins("[key_name_admin(usr)] re-entered corpse")
+ log_admin("[key_name(user)] re-entered corpse")
+ message_admins("[key_name_admin(user)] re-entered corpse")
ghost.can_reenter_corpse = 1 //force re-entering even when otherwise not possible
ghost.reenter_corpse()
BLACKBOX_LOG_ADMIN_VERB("Admin Reenter")
- else if(isnewplayer(mob))
- to_chat(src, "Error: Aghost: Can't admin-ghost whilst in the lobby. Join or Observe first.", confidential = TRUE)
+ else if(isnewplayer(user.mob))
+ to_chat(user, "Error: Aghost: Can't admin-ghost whilst in the lobby. Join or Observe first.", confidential = TRUE)
return FALSE
else
//ghostize
- log_admin("[key_name(usr)] admin ghosted.")
- message_admins("[key_name_admin(usr)] admin ghosted.")
- var/mob/body = mob
+ log_admin("[key_name(user)] admin ghosted.")
+ message_admins("[key_name_admin(user)] admin ghosted.")
+ var/mob/body = user.mob
body.ghostize(TRUE)
- init_verbs()
+ user.init_verbs()
if(body && !body.key)
- body.key = "@[key]" //Haaaaaaaack. But the people have spoken. If it breaks; blame adminbus
+ body.key = "@[user.key]" //Haaaaaaaack. But the people have spoken. If it breaks; blame adminbus
BLACKBOX_LOG_ADMIN_VERB("Admin Ghost")
-/client/proc/invisimin()
- set name = "Invisimin"
- set category = "Admin.Game"
- set desc = "Toggles ghost-like invisibility (Don't abuse this)"
-
- if(isnull(holder) || isnull(mob))
+ADMIN_VERB(invisimin, R_ADMIN, "Inisimin", "Toggles ghost-like invisibility.", ADMIN_CATEGORY_GAME)
+ if(HAS_TRAIT(user.mob, TRAIT_INVISIMIN))
+ REMOVE_TRAIT(user.mob, TRAIT_INVISIMIN, ADMIN_TRAIT)
+ user.mob.add_to_all_human_data_huds()
+ user.mob.RemoveInvisibility(INVISIBILITY_SOURCE_INVISIMIN)
+ to_chat(user, span_adminnotice(span_bold("Invisimin off. Invisibility reset.")), confidential = TRUE)
return
- if(HAS_TRAIT(mob, TRAIT_INVISIMIN))
- REMOVE_TRAIT(mob, TRAIT_INVISIMIN, ADMIN_TRAIT)
- mob.add_to_all_human_data_huds()
- mob.RemoveInvisibility(INVISIBILITY_SOURCE_INVISIMIN)
- to_chat(mob, span_adminnotice(span_bold("Invisimin off. Invisibility reset.")), confidential = TRUE)
- return
+ ADD_TRAIT(user.mob, TRAIT_INVISIMIN, ADMIN_TRAIT)
+ user.mob.remove_from_all_data_huds()
+ user.mob.SetInvisibility(INVISIBILITY_OBSERVER, INVISIBILITY_SOURCE_INVISIMIN, INVISIBILITY_PRIORITY_ADMIN)
+ to_chat(user, span_adminnotice(span_bold("Invisimin on. You are now as invisible as a ghost.")), confidential = TRUE)
- ADD_TRAIT(mob, TRAIT_INVISIMIN, ADMIN_TRAIT)
- mob.remove_from_all_data_huds()
- mob.SetInvisibility(INVISIBILITY_OBSERVER, INVISIBILITY_SOURCE_INVISIMIN, INVISIBILITY_PRIORITY_ADMIN)
- to_chat(mob, span_adminnotice(span_bold("Invisimin on. You are now as invisible as a ghost.")), confidential = TRUE)
-
-/client/proc/check_antagonists()
- set name = "Check Antagonists"
- set category = "Admin.Game"
- if(holder)
- holder.check_antagonists()
- log_admin("[key_name(usr)] checked antagonists.") //for tsar~
- if(!isobserver(usr) && SSticker.HasRoundStarted())
- message_admins("[key_name_admin(usr)] checked antagonists.")
+ADMIN_VERB(check_antagonists, R_ADMIN, "Check Antagonists", "See all antagonists for the round.", ADMIN_CATEGORY_GAME)
+ user.holder.check_antagonists()
+ log_admin("[key_name(user)] checked antagonists.")
+ if(!isobserver(user.mob) && SSticker.HasRoundStarted())
+ message_admins("[key_name_admin(user)] checked antagonists.")
BLACKBOX_LOG_ADMIN_VERB("Check Antagonists")
-/client/proc/list_bombers()
- set name = "List Bombers"
- set category = "Admin.Game"
- if(!holder)
- return
- holder.list_bombers()
+ADMIN_VERB(list_bombers, R_ADMIN, "List Bombers", "Look at all bombs and their likely culprit.", ADMIN_CATEGORY_GAME)
+ user.holder.list_bombers()
BLACKBOX_LOG_ADMIN_VERB("List Bombers")
-/client/proc/list_signalers()
- set name = "List Signalers"
- set category = "Admin.Game"
- if(!holder)
- return
- holder.list_signalers()
+ADMIN_VERB(list_signalers, R_ADMIN, "List Signalers", "View all signalers.", ADMIN_CATEGORY_GAME)
+ user.holder.list_signalers()
BLACKBOX_LOG_ADMIN_VERB("List Signalers")
-/client/proc/list_law_changes()
- set name = "List Law Changes"
- set category = "Debug"
- if(!holder)
- return
- holder.list_law_changes()
+ADMIN_VERB(list_law_changes, R_ADMIN, "List Law Changes", "View all AI law changes.", ADMIN_CATEGORY_DEBUG)
+ user.holder.list_law_changes()
BLACKBOX_LOG_ADMIN_VERB("List Law Changes")
-/client/proc/show_manifest()
- set name = "Show Manifest"
- set category = "Debug"
- if(!holder)
- return
- holder.show_manifest()
+ADMIN_VERB(show_manifest, R_ADMIN, "Show Manifest", "View the shift's Manifest.", ADMIN_CATEGORY_DEBUG)
+ user.holder.show_manifest()
BLACKBOX_LOG_ADMIN_VERB("Show Manifest")
-/client/proc/list_dna()
- set name = "List DNA"
- set category = "Debug"
- if(!holder)
- return
- holder.list_dna()
+ADMIN_VERB(list_dna, R_ADMIN, "List DNA", "View DNA.", ADMIN_CATEGORY_DEBUG)
+ user.holder.list_dna()
BLACKBOX_LOG_ADMIN_VERB("List DNA")
-/client/proc/list_fingerprints()
- set name = "List Fingerprints"
- set category = "Debug"
- if(!holder)
- return
- holder.list_fingerprints()
+ADMIN_VERB(list_fingerprints, R_ADMIN, "List Fingerprints", "View fingerprints.", ADMIN_CATEGORY_DEBUG)
+ user.holder.list_fingerprints()
BLACKBOX_LOG_ADMIN_VERB("List Fingerprints")
-/client/proc/ban_panel()
- set name = "Banning Panel"
- set category = "Admin"
- if(!check_rights(R_BAN))
- return
- holder.ban_panel()
+ADMIN_VERB(ban_panel, R_BAN, "Banning Panel", "Ban players here.", ADMIN_CATEGORY_MAIN)
+ user.holder.ban_panel()
BLACKBOX_LOG_ADMIN_VERB("Banning Panel")
-/client/proc/unban_panel()
- set name = "Unbanning Panel"
- set category = "Admin"
- if(!check_rights(R_BAN))
- return
- holder.unban_panel()
+ADMIN_VERB(unban_panel, R_BAN, "Unbanning Panel", "Unban players here.", ADMIN_CATEGORY_MAIN)
+ user.holder.unban_panel()
BLACKBOX_LOG_ADMIN_VERB("Unbanning Panel")
-/client/proc/game_panel()
- set name = "Game Panel"
- set category = "Admin.Game"
- if(holder)
- holder.Game()
+ADMIN_VERB(game_panel, R_ADMIN, "Game Panel", "Look at the state of the game.", ADMIN_CATEGORY_GAME)
+ user.holder.Game()
BLACKBOX_LOG_ADMIN_VERB("Game Panel")
-/client/proc/poll_panel()
- set name = "Server Poll Management"
- set category = "Admin"
- if(!check_rights(R_POLL))
- return
- holder.poll_list_panel()
+ADMIN_VERB(poll_panel, R_POLL, "Server Poll Management", "View and manage polls.", ADMIN_CATEGORY_MAIN)
+ user.holder.poll_list_panel()
BLACKBOX_LOG_ADMIN_VERB("Server Poll Management")
/// Returns this client's stealthed ckey
@@ -536,16 +133,11 @@ GLOBAL_PROTECT(admin_verbs_poll)
/client/proc/createStealthKey()
GLOB.stealthminID["[ckey]"] = generateStealthCkey()
-/client/proc/stealth()
- set category = "Admin"
- set name = "Stealth Mode"
- if(!holder)
- return
-
- if(holder.fakekey)
- disable_stealth_mode()
+ADMIN_VERB(stealth, R_STEALTH, "Stealth Mode", "Toggle stealth.", ADMIN_CATEGORY_MAIN)
+ if(user.holder.fakekey)
+ user.disable_stealth_mode()
else
- enable_stealth_mode()
+ user.enable_stealth_mode()
BLACKBOX_LOG_ADMIN_VERB("Stealth Mode")
@@ -590,117 +182,86 @@ GLOBAL_PROTECT(admin_verbs_poll)
#undef STEALTH_MODE_TRAIT
-/client/proc/drop_bomb()
- set category = "Admin.Fun"
- set name = "Drop Bomb"
- set desc = "Cause an explosion of varying strength at your location."
-
+ADMIN_VERB(drop_bomb, R_FUN, "Drop Bomb", "Cause an explosion of varying strength at your location", ADMIN_CATEGORY_FUN)
var/list/choices = list("Small Bomb (1, 2, 3, 3)", "Medium Bomb (2, 3, 4, 4)", "Big Bomb (3, 5, 7, 5)", "Maxcap", "Custom Bomb")
- var/choice = tgui_input_list(src, "What size explosion would you like to produce? NOTE: You can do all this rapidly and in an IC manner (using cruise missiles!) with the Config/Launch Supplypod verb. WARNING: These ignore the maxcap", "Drop Bomb", choices)
+ var/choice = tgui_input_list(user, "What size explosion would you like to produce? NOTE: You can do all this rapidly and in an IC manner (using cruise missiles!) with the Config/Launch Supplypod verb. WARNING: These ignore the maxcap", "Drop Bomb", choices)
if(isnull(choice))
return
- var/turf/epicenter = mob.loc
+ var/turf/epicenter = user.mob.loc
switch(choice)
if("Small Bomb (1, 2, 3, 3)")
- explosion(epicenter, devastation_range = 1, heavy_impact_range = 2, light_impact_range = 3, flash_range = 3, adminlog = TRUE, ignorecap = TRUE, explosion_cause = mob)
+ explosion(epicenter, devastation_range = 1, heavy_impact_range = 2, light_impact_range = 3, flash_range = 3, adminlog = TRUE, ignorecap = TRUE, explosion_cause = user.mob)
if("Medium Bomb (2, 3, 4, 4)")
- explosion(epicenter, devastation_range = 2, heavy_impact_range = 3, light_impact_range = 4, flash_range = 4, adminlog = TRUE, ignorecap = TRUE, explosion_cause = mob)
+ explosion(epicenter, devastation_range = 2, heavy_impact_range = 3, light_impact_range = 4, flash_range = 4, adminlog = TRUE, ignorecap = TRUE, explosion_cause = user.mob)
if("Big Bomb (3, 5, 7, 5)")
- explosion(epicenter, devastation_range = 3, heavy_impact_range = 5, light_impact_range = 7, flash_range = 5, adminlog = TRUE, ignorecap = TRUE, explosion_cause = mob)
+ explosion(epicenter, devastation_range = 3, heavy_impact_range = 5, light_impact_range = 7, flash_range = 5, adminlog = TRUE, ignorecap = TRUE, explosion_cause = user.mob)
if("Maxcap")
- explosion(epicenter, devastation_range = GLOB.MAX_EX_DEVESTATION_RANGE, heavy_impact_range = GLOB.MAX_EX_HEAVY_RANGE, light_impact_range = GLOB.MAX_EX_LIGHT_RANGE, flash_range = GLOB.MAX_EX_FLASH_RANGE, adminlog = TRUE, ignorecap = TRUE, explosion_cause = mob)
+ explosion(epicenter, devastation_range = GLOB.MAX_EX_DEVESTATION_RANGE, heavy_impact_range = GLOB.MAX_EX_HEAVY_RANGE, light_impact_range = GLOB.MAX_EX_LIGHT_RANGE, flash_range = GLOB.MAX_EX_FLASH_RANGE, adminlog = TRUE, ignorecap = TRUE, explosion_cause = user.mob)
if("Custom Bomb")
- var/range_devastation = input("Devastation range (in tiles):") as null|num
+ var/range_devastation = input(user, "Devastation range (in tiles):") as null|num
if(range_devastation == null)
return
- var/range_heavy = input("Heavy impact range (in tiles):") as null|num
+ var/range_heavy = input(user, "Heavy impact range (in tiles):") as null|num
if(range_heavy == null)
return
- var/range_light = input("Light impact range (in tiles):") as null|num
+ var/range_light = input(user, "Light impact range (in tiles):") as null|num
if(range_light == null)
return
- var/range_flash = input("Flash range (in tiles):") as null|num
+ var/range_flash = input(user, "Flash range (in tiles):") as null|num
if(range_flash == null)
return
if(range_devastation > GLOB.MAX_EX_DEVESTATION_RANGE || range_heavy > GLOB.MAX_EX_HEAVY_RANGE || range_light > GLOB.MAX_EX_LIGHT_RANGE || range_flash > GLOB.MAX_EX_FLASH_RANGE)
- if(tgui_alert(usr, "Bomb is bigger than the maxcap. Continue?",,list("Yes","No")) != "Yes")
+ if(tgui_alert(user, "Bomb is bigger than the maxcap. Continue?",,list("Yes","No")) != "Yes")
return
- epicenter = mob.loc //We need to reupdate as they may have moved again
- explosion(epicenter, devastation_range = range_devastation, heavy_impact_range = range_heavy, light_impact_range = range_light, flash_range = range_flash, adminlog = TRUE, ignorecap = TRUE, explosion_cause = mob)
- message_admins("[ADMIN_LOOKUPFLW(usr)] creating an admin explosion at [epicenter.loc].")
- log_admin("[key_name(usr)] created an admin explosion at [epicenter.loc].")
+ epicenter = get_turf(user.mob) //We need to reupdate as they may have moved again
+ explosion(epicenter, devastation_range = range_devastation, heavy_impact_range = range_heavy, light_impact_range = range_light, flash_range = range_flash, adminlog = TRUE, ignorecap = TRUE, explosion_cause = user.mob)
+ message_admins("[ADMIN_LOOKUPFLW(user.mob)] creating an admin explosion at [epicenter.loc].")
+ log_admin("[key_name(user)] created an admin explosion at [epicenter.loc].")
BLACKBOX_LOG_ADMIN_VERB("Drop Bomb")
-/client/proc/drop_dynex_bomb()
- set category = "Admin.Fun"
- set name = "Drop DynEx Bomb"
- set desc = "Cause an explosion of varying strength at your location."
-
- var/ex_power = input("Explosive Power:") as null|num
- var/turf/epicenter = mob.loc
- if(ex_power && epicenter)
- dyn_explosion(epicenter, ex_power)
- message_admins("[ADMIN_LOOKUPFLW(usr)] creating an admin explosion at [epicenter.loc].")
- log_admin("[key_name(usr)] created an admin explosion at [epicenter.loc].")
- BLACKBOX_LOG_ADMIN_VERB("Drop Dynamic Bomb")
-
-/client/proc/get_dynex_range()
- set category = "Debug"
- set name = "Get DynEx Range"
- set desc = "Get the estimated range of a bomb, using explosive power."
-
- var/ex_power = input("Explosive Power:") as null|num
+ADMIN_VERB(drop_bomb_dynex, R_FUN, "Drop DynEx Bomb", "Cause an explosion of varying strength at your location.", ADMIN_CATEGORY_FUN)
+ var/ex_power = input(user, "Explosive Power:") as null|num
+ var/turf/epicenter = get_turf(user.mob)
+ if(!ex_power || !epicenter)
+ return
+ dyn_explosion(epicenter, ex_power)
+ message_admins("[ADMIN_LOOKUPFLW(user.mob)] creating an admin explosion at [epicenter.loc].")
+ log_admin("[key_name(user)] created an admin explosion at [epicenter.loc].")
+ BLACKBOX_LOG_ADMIN_VERB("Drop Dynamic Bomb")
+
+ADMIN_VERB(get_dynex_range, R_FUN, "Get DynEx Range", "Get the estimated range of a bomb using explosive power.", ADMIN_CATEGORY_DEBUG)
+ var/ex_power = input(user, "Explosive Power:") as null|num
if (isnull(ex_power))
return
var/range = round((2 * ex_power)**GLOB.DYN_EX_SCALE)
- to_chat(usr, "Estimated Explosive Range: (Devastation: [round(range*0.25)], Heavy: [round(range*0.5)], Light: [round(range)])", confidential = TRUE)
-
-/client/proc/get_dynex_power()
- set category = "Debug"
- set name = "Get DynEx Power"
- set desc = "Get the estimated required power of a bomb, to reach a specific range."
+ to_chat(user, "Estimated Explosive Range: (Devastation: [round(range*0.25)], Heavy: [round(range*0.5)], Light: [round(range)])", confidential = TRUE)
- var/ex_range = input("Light Explosion Range:") as null|num
+ADMIN_VERB(get_dynex_power, R_FUN, "Get DynEx Power", "Get the estimated required power of a bomb to reach the given range.", ADMIN_CATEGORY_DEBUG)
+ var/ex_range = input(user, "Light Explosion Range:") as null|num
if (isnull(ex_range))
return
var/power = (0.5 * ex_range)**(1/GLOB.DYN_EX_SCALE)
- to_chat(usr, "Estimated Explosive Power: [power]", confidential = TRUE)
-
-/client/proc/set_dynex_scale()
- set category = "Debug"
- set name = "Set DynEx Scale"
- set desc = "Set the scale multiplier of dynex explosions. The default is 0.5."
+ to_chat(user, "Estimated Explosive Power: [power]", confidential = TRUE)
- var/ex_scale = input("New DynEx Scale:") as null|num
+ADMIN_VERB(set_dynex_scale, R_FUN, "Set DynEx Scale", "Set the scale multiplier on dynex explosions. Default 0.5.", ADMIN_CATEGORY_DEBUG)
+ var/ex_scale = input(user, "New DynEx Scale:") as null|num
if(!ex_scale)
return
GLOB.DYN_EX_SCALE = ex_scale
- log_admin("[key_name(usr)] has modified Dynamic Explosion Scale: [ex_scale]")
- message_admins("[key_name_admin(usr)] has modified Dynamic Explosion Scale: [ex_scale]")
+ log_admin("[key_name(user)] has modified Dynamic Explosion Scale: [ex_scale]")
+ message_admins("[key_name_admin(user)] has modified Dynamic Explosion Scale: [ex_scale]")
-/client/proc/atmos_control()
- set name = "Atmos Control Panel"
- set category = "Debug"
- if(!check_rights(R_DEBUG))
- return
- SSair.ui_interact(mob)
+ADMIN_VERB(atmos_control, R_DEBUG|R_SERVER, "Atmos Control Panel", "Open the atmospherics control panel.", ADMIN_CATEGORY_DEBUG)
+ SSair.ui_interact(user.mob)
-/client/proc/reload_cards()
- set name = "Reload Cards"
- set category = "Debug"
- if(!check_rights(R_DEBUG))
- return
+ADMIN_VERB(reload_cards, R_DEBUG, "Reload Cards", "Reload all TCG cards.", ADMIN_CATEGORY_DEBUG)
if(!SStrading_card_game.loaded)
message_admins("The card subsystem is not currently loaded")
return
SStrading_card_game.reloadAllCardFiles()
-/client/proc/validate_cards()
- set name = "Validate Cards"
- set category = "Debug"
- if(!check_rights(R_DEBUG))
- return
+ADMIN_VERB(validate_cards, R_DEBUG, "Validate Cards", "Validate the card settings.", ADMIN_CATEGORY_DEBUG)
if(!SStrading_card_game.loaded)
message_admins("The card subsystem is not currently loaded")
return
@@ -711,66 +272,55 @@ GLOBAL_PROTECT(admin_verbs_poll)
else
message_admins("No errors found in card rarities or overrides.")
-/client/proc/test_cardpack_distribution()
- set name = "Test Cardpack Distribution"
- set category = "Debug"
- if(!check_rights(R_DEBUG))
- return
+ADMIN_VERB(test_cardpack_distribution, R_DEBUG, "Test Cardpack Distribution", "Test the distribution of a card pack.", ADMIN_CATEGORY_DEBUG)
if(!SStrading_card_game.loaded)
message_admins("The card subsystem is not currently loaded")
return
- var/pack = tgui_input_list(usr, "Which pack should we test?", "You fucked it didn't you", sort_list(SStrading_card_game.card_packs))
+ var/pack = tgui_input_list(user, "Which pack should we test?", "You fucked it didn't you", sort_list(SStrading_card_game.card_packs))
if(!pack)
return
- var/batch_count = tgui_input_number(usr, "How many times should we open it?", "Don't worry, I understand")
- var/batch_size = tgui_input_number(usr, "How many cards per batch?", "I hope you remember to check the validation")
- var/guar = tgui_input_number(usr, "Should we use the pack's guaranteed rarity? If so, how many?", "We've all been there. Man you should have seen the old system")
-
+ var/batch_count = tgui_input_number(user, "How many times should we open it?", "Don't worry, I understand")
+ var/batch_size = tgui_input_number(user, "How many cards per batch?", "I hope you remember to check the validation")
+ var/guar = tgui_input_number(user, "Should we use the pack's guaranteed rarity? If so, how many?", "We've all been there. Man you should have seen the old system")
SStrading_card_game.check_card_distribution(pack, batch_size, batch_count, guar)
-/client/proc/print_cards()
- set name = "Print Cards"
- set category = "Debug"
+ADMIN_VERB(print_cards, R_DEBUG, "Print Cards", "Print all cards to chat.", ADMIN_CATEGORY_DEBUG)
SStrading_card_game.printAllCards()
-/client/proc/give_mob_action(mob/ability_recipient in GLOB.mob_list)
- set category = "Admin.Fun"
- set name = "Give Mob Action"
- set desc = "Gives a mob ability to a mob."
-
+ADMIN_VERB(give_mob_action, R_FUN, "Give Mob Action", ADMIN_VERB_NO_DESCRIPTION, ADMIN_CATEGORY_HIDDEN, mob/ability_recipient)
var/static/list/all_mob_actions = sort_list(subtypesof(/datum/action/cooldown/mob_cooldown), GLOBAL_PROC_REF(cmp_typepaths_asc))
var/static/list/actions_by_name = list()
if (!length(actions_by_name))
for (var/datum/action/cooldown/mob_cooldown as anything in all_mob_actions)
actions_by_name["[initial(mob_cooldown.name)] ([mob_cooldown])"] = mob_cooldown
- var/ability = tgui_input_list(usr, "Choose an ability", "Ability", actions_by_name)
+ var/ability = tgui_input_list(user, "Choose an ability", "Ability", actions_by_name)
if(isnull(ability))
return
var/ability_type = actions_by_name[ability]
var/datum/action/cooldown/mob_cooldown/add_ability
- var/make_sequence = tgui_alert(usr, "Would you like this action to be a sequence of multiple abilities?", "Sequence Ability", list("Yes", "No"))
+ var/make_sequence = tgui_alert(user, "Would you like this action to be a sequence of multiple abilities?", "Sequence Ability", list("Yes", "No"))
if(make_sequence == "Yes")
add_ability = new /datum/action/cooldown/mob_cooldown(ability_recipient)
add_ability.sequence_actions = list()
while(!isnull(ability_type))
- var/ability_delay = tgui_input_number(usr, "Enter the delay in seconds before the next ability in the sequence is used", "Ability Delay", 2)
+ var/ability_delay = tgui_input_number(user, "Enter the delay in seconds before the next ability in the sequence is used", "Ability Delay", 2)
if(isnull(ability_delay) || ability_delay < 0)
ability_delay = 0
add_ability.sequence_actions[ability_type] = ability_delay * 1 SECONDS
- ability = tgui_input_list(usr, "Choose a new sequence ability", "Sequence Ability", actions_by_name)
+ ability = tgui_input_list(user, "Choose a new sequence ability", "Sequence Ability", actions_by_name)
ability_type = actions_by_name[ability]
- var/ability_cooldown = tgui_input_number(usr, "Enter the sequence abilities cooldown in seconds", "Ability Cooldown", 2)
+ var/ability_cooldown = tgui_input_number(user, "Enter the sequence abilities cooldown in seconds", "Ability Cooldown", 2)
if(isnull(ability_cooldown) || ability_cooldown < 0)
ability_cooldown = 2
add_ability.cooldown_time = ability_cooldown * 1 SECONDS
- var/ability_melee_cooldown = tgui_input_number(usr, "Enter the abilities melee cooldown in seconds", "Melee Cooldown", 2)
+ var/ability_melee_cooldown = tgui_input_number(user, "Enter the abilities melee cooldown in seconds", "Melee Cooldown", 2)
if(isnull(ability_melee_cooldown) || ability_melee_cooldown < 0)
ability_melee_cooldown = 2
add_ability.melee_cooldown_time = ability_melee_cooldown * 1 SECONDS
- add_ability.name = tgui_input_text(usr, "Choose ability name", "Ability name", "Generic Ability")
+ add_ability.name = tgui_input_text(user, "Choose ability name", "Ability name", "Generic Ability")
add_ability.create_sequence_actions()
else
add_ability = new ability_type(ability_recipient)
@@ -779,15 +329,11 @@ GLOBAL_PROTECT(admin_verbs_poll)
return
add_ability.Grant(ability_recipient)
- message_admins("[key_name_admin(usr)] added mob ability [ability_type] to mob [ability_recipient].")
- log_admin("[key_name(usr)] added mob ability [ability_type] to mob [ability_recipient].")
+ message_admins("[key_name_admin(user)] added mob ability [ability_type] to mob [ability_recipient].")
+ log_admin("[key_name(user)] added mob ability [ability_type] to mob [ability_recipient].")
BLACKBOX_LOG_ADMIN_VERB("Add Mob Ability")
-/client/proc/remove_mob_action(mob/removal_target in GLOB.mob_list)
- set category = "Admin.Fun"
- set name = "Remove Mob Action"
- set desc = "Remove a special ability from the selected mob."
-
+ADMIN_VERB(remove_mob_action, R_FUN, "Remove Mob Action", ADMIN_VERB_NO_DESCRIPTION, ADMIN_CATEGORY_HIDDEN, mob/removal_target)
var/list/target_abilities = list()
for(var/datum/action/cooldown/mob_cooldown/ability in removal_target.actions)
target_abilities[ability.name] = ability
@@ -795,7 +341,7 @@ GLOBAL_PROTECT(admin_verbs_poll)
if(!length(target_abilities))
return
- var/chosen_ability = tgui_input_list(usr, "Choose the spell to remove from [removal_target]", "Depower", sort_list(target_abilities))
+ var/chosen_ability = tgui_input_list(user, "Choose the spell to remove from [removal_target]", "Depower", sort_list(target_abilities))
if(isnull(chosen_ability))
return
var/datum/action/cooldown/mob_cooldown/to_remove = target_abilities[chosen_ability]
@@ -803,20 +349,16 @@ GLOBAL_PROTECT(admin_verbs_poll)
return
qdel(to_remove)
- log_admin("[key_name(usr)] removed the ability [chosen_ability] from [key_name(removal_target)].")
- message_admins("[key_name_admin(usr)] removed the ability [chosen_ability] from [key_name_admin(removal_target)].")
+ log_admin("[key_name(user)] removed the ability [chosen_ability] from [key_name(removal_target)].")
+ message_admins("[key_name_admin(user)] removed the ability [chosen_ability] from [key_name_admin(removal_target)].")
BLACKBOX_LOG_ADMIN_VERB("Remove Mob Ability")
-/client/proc/give_spell(mob/spell_recipient in GLOB.mob_list)
- set category = "Admin.Fun"
- set name = "Give Spell"
- set desc = "Gives a spell to a mob."
-
- var/which = tgui_alert(usr, "Chose by name or by type path?", "Chose option", list("Name", "Typepath"))
+ADMIN_VERB(give_spell, R_FUN, "Give Spell", ADMIN_VERB_NO_DESCRIPTION, ADMIN_CATEGORY_HIDDEN, mob/spell_recipient)
+ var/which = tgui_alert(user, "Chose by name or by type path?", "Chose option", list("Name", "Typepath"))
if(!which)
return
if(QDELETED(spell_recipient))
- to_chat(usr, span_warning("The intended spell recipient no longer exists."))
+ to_chat(user, span_warning("The intended spell recipient no longer exists."))
return
var/list/spell_list = list()
@@ -830,22 +372,22 @@ GLOBAL_PROTECT(admin_verbs_poll)
else
spell_list += to_add
- var/chosen_spell = tgui_input_list(usr, "Choose the spell to give to [spell_recipient]", "ABRAKADABRA", sort_list(spell_list))
+ var/chosen_spell = tgui_input_list(user, "Choose the spell to give to [spell_recipient]", "ABRAKADABRA", sort_list(spell_list))
if(isnull(chosen_spell))
return
var/datum/action/cooldown/spell/spell_path = which == "Typepath" ? chosen_spell : spell_list[chosen_spell]
if(!ispath(spell_path))
return
- var/robeless = (tgui_alert(usr, "Would you like to force this spell to be robeless?", "Robeless Casting?", list("Force Robeless", "Use Spell Setting")) == "Force Robeless")
+ var/robeless = (tgui_alert(user, "Would you like to force this spell to be robeless?", "Robeless Casting?", list("Force Robeless", "Use Spell Setting")) == "Force Robeless")
if(QDELETED(spell_recipient))
- to_chat(usr, span_warning("The intended spell recipient no longer exists."))
+ to_chat(user, span_warning("The intended spell recipient no longer exists."))
return
BLACKBOX_LOG_ADMIN_VERB("Give Spell")
- log_admin("[key_name(usr)] gave [key_name(spell_recipient)] the spell [chosen_spell][robeless ? " (Forced robeless)" : ""].")
- message_admins("[key_name_admin(usr)] gave [key_name_admin(spell_recipient)] the spell [chosen_spell][robeless ? " (Forced robeless)" : ""].")
+ log_admin("[key_name(user)] gave [key_name(spell_recipient)] the spell [chosen_spell][robeless ? " (Forced robeless)" : ""].")
+ message_admins("[key_name_admin(user)] gave [key_name_admin(spell_recipient)] the spell [chosen_spell][robeless ? " (Forced robeless)" : ""].")
var/datum/action/cooldown/spell/new_spell = new spell_path(spell_recipient.mind || spell_recipient)
@@ -855,14 +397,10 @@ GLOBAL_PROTECT(admin_verbs_poll)
new_spell.Grant(spell_recipient)
if(!spell_recipient.mind)
- to_chat(usr, span_userdanger("Spells given to mindless mobs will belong to the mob and not their mind, \
+ to_chat(user, span_userdanger("Spells given to mindless mobs will belong to the mob and not their mind, \
and as such will not be transferred if their mind changes body (Such as from Mindswap)."))
-/client/proc/remove_spell(mob/removal_target in GLOB.mob_list)
- set category = "Admin.Fun"
- set name = "Remove Spell"
- set desc = "Remove a spell from the selected mob."
-
+ADMIN_VERB(remove_spell, R_FUN, "Remove Spell", ADMIN_VERB_NO_DESCRIPTION, ADMIN_CATEGORY_HIDDEN, mob/removal_target)
var/list/target_spell_list = list()
for(var/datum/action/cooldown/spell/spell in removal_target.actions)
target_spell_list[spell.name] = spell
@@ -870,7 +408,7 @@ GLOBAL_PROTECT(admin_verbs_poll)
if(!length(target_spell_list))
return
- var/chosen_spell = tgui_input_list(usr, "Choose the spell to remove from [removal_target]", "ABRAKADABRA", sort_list(target_spell_list))
+ var/chosen_spell = tgui_input_list(user, "Choose the spell to remove from [removal_target]", "ABRAKADABRA", sort_list(target_spell_list))
if(isnull(chosen_spell))
return
var/datum/action/cooldown/spell/to_remove = target_spell_list[chosen_spell]
@@ -878,58 +416,39 @@ GLOBAL_PROTECT(admin_verbs_poll)
return
qdel(to_remove)
- log_admin("[key_name(usr)] removed the spell [chosen_spell] from [key_name(removal_target)].")
- message_admins("[key_name_admin(usr)] removed the spell [chosen_spell] from [key_name_admin(removal_target)].")
+ log_admin("[key_name(user)] removed the spell [chosen_spell] from [key_name(removal_target)].")
+ message_admins("[key_name_admin(user)] removed the spell [chosen_spell] from [key_name_admin(removal_target)].")
BLACKBOX_LOG_ADMIN_VERB("Remove Spell")
-/client/proc/give_disease(mob/living/T in GLOB.mob_living_list)
- set category = "Admin.Fun"
- set name = "Give Disease"
- set desc = "Gives a Disease to a mob."
- if(!istype(T))
- to_chat(src, span_notice("You can only give a disease to a mob of type /mob/living."), confidential = TRUE)
- return
- var/datum/disease/D = input("Choose the disease to give to that guy", "ACHOO") as null|anything in sort_list(SSdisease.diseases, GLOBAL_PROC_REF(cmp_typepaths_asc))
+ADMIN_VERB(give_disease, R_FUN, "Give Disease", ADMIN_VERB_NO_DESCRIPTION, ADMIN_CATEGORY_HIDDEN, mob/living/victim)
+ var/datum/disease/D = input(user, "Choose the disease to give to that guy", "ACHOO") as null|anything in sort_list(SSdisease.diseases, GLOBAL_PROC_REF(cmp_typepaths_asc))
if(!D)
return
- T.ForceContractDisease(new D, FALSE, TRUE)
+ victim.ForceContractDisease(new D, FALSE, TRUE)
BLACKBOX_LOG_ADMIN_VERB("Give Disease")
- log_admin("[key_name(usr)] gave [key_name(T)] the disease [D].")
- message_admins(span_adminnotice("[key_name_admin(usr)] gave [key_name_admin(T)] the disease [D]."))
-
-/client/proc/object_say(obj/O in world)
- set category = "Admin.Events"
- set name = "OSay"
- set desc = "Makes an object say something."
- var/message = tgui_input_text(usr, "What do you want the message to be?", "Make Sound", encode = FALSE)
+ log_admin("[key_name(user)] gave [key_name(victim)] the disease [D].")
+ message_admins(span_adminnotice("[key_name_admin(user)] gave [key_name_admin(victim)] the disease [D]."))
+
+ADMIN_VERB_AND_CONTEXT_MENU(object_say, R_FUN, "OSay", ADMIN_VERB_NO_DESCRIPTION, ADMIN_CATEGORY_HIDDEN, obj/speaker in world)
+ var/message = tgui_input_text(user, "What do you want the message to be?", "Make Sound", encode = FALSE)
if(!message)
return
- O.say(message, sanitize = FALSE)
- log_admin("[key_name(usr)] made [O] at [AREACOORD(O)] say \"[message]\"")
- message_admins(span_adminnotice("[key_name_admin(usr)] made [O] at [AREACOORD(O)]. say \"[message]\""))
+ speaker.say(message, sanitize = FALSE)
+ log_admin("[key_name(user)] made [speaker] at [AREACOORD(speaker)] say \"[message]\"")
+ message_admins(span_adminnotice("[key_name_admin(user)] made [speaker] at [AREACOORD(speaker)]. say \"[message]\""))
BLACKBOX_LOG_ADMIN_VERB("Object Say")
-/client/proc/togglebuildmodeself()
- set name = "Toggle Build Mode Self"
- set category = "Admin.Events"
- if (!(holder.rank_flags() & R_BUILD))
- return
- if(src.mob)
- togglebuildmode(src.mob)
- BLACKBOX_LOG_ADMIN_VERB("Toggle Build Mode")
-/client/proc/check_ai_laws()
- set name = "Check AI Laws"
- set category = "Admin.Game"
- if(holder)
- src.holder.output_ai_laws()
+ADMIN_VERB(build_mode_self, R_BUILD, "Toggle Build Mode Self", "Toggle build mode for yourself.", ADMIN_CATEGORY_EVENTS)
+ togglebuildmode(user.mob) // why is this a global proc???
+ BLACKBOX_LOG_ADMIN_VERB("Toggle Build Mode")
-/client/proc/manage_sect()
- set name = "Manage Religious Sect"
- set category = "Admin.Game"
+ADMIN_VERB(check_ai_laws, R_ADMIN, "Check AI Laws", "View the current AI laws.", ADMIN_CATEGORY_GAME)
+ user.holder.output_ai_laws()
+ADMIN_VERB(manage_sect, R_ADMIN, "Manage Religious Sect", "Manages the chaplain's religion.", ADMIN_CATEGORY_GAME)
if (!isnull(GLOB.religious_sect))
var/you_sure = tgui_alert(
- usr,
+ user,
"The Chaplain has already chosen [GLOB.religious_sect.name], override their selection?",
"Replace God?",
list("Yes", "Cancel"),
@@ -942,7 +461,7 @@ GLOBAL_PROTECT(admin_verbs_poll)
choices["nothing"] = null
for(var/datum/religion_sect/sect as anything in subtypesof(/datum/religion_sect))
choices[initial(sect.name)] = sect
- var/choice = tgui_input_list(usr, "Set new Chaplain sect", "God Picker", choices)
+ var/choice = tgui_input_list(user, "Set new Chaplain sect", "God Picker", choices)
if(isnull(choice))
return
if(choice == "nothing")
@@ -950,122 +469,51 @@ GLOBAL_PROTECT(admin_verbs_poll)
return
set_new_religious_sect(choices[choice], reset_existing = TRUE)
-/client/proc/deadmin()
- set name = "Deadmin"
- set category = "Admin"
- set desc = "Shed your admin powers."
-
- if(!holder)
- return
-
- holder.deactivate()
-
- to_chat(src, span_interface("You are now a normal player."))
- log_admin("[src] deadminned themselves.")
- message_admins("[src] deadminned themselves.")
+ADMIN_VERB(deadmin, R_NONE, "DeAdmin", "Shed your admin powers.", ADMIN_CATEGORY_MAIN)
+ user.holder.deactivate()
+ to_chat(user, span_interface("You are now a normal player."))
+ log_admin("[key_name(user)] deadminned themselves.")
+ message_admins("[key_name_admin(user)] deadminned themselves.")
BLACKBOX_LOG_ADMIN_VERB("Deadmin")
-/client/proc/readmin()
- set name = "Readmin"
- set category = "Admin"
- set desc = "Regain your admin powers."
-
- var/datum/admins/A = GLOB.deadmins[ckey]
-
- if(!A)
- A = GLOB.admin_datums[ckey]
- if (!A)
- var/msg = " is trying to readmin but they have no deadmin entry"
- message_admins("[key_name_admin(src)][msg]")
- log_admin_private("[key_name(src)][msg]")
- return
-
- A.associate(src)
-
- if (!holder)
- return //This can happen if an admin attempts to vv themself into somebody elses's deadmin datum by getting ref via brute force
-
- to_chat(src, span_interface("You are now an admin."), confidential = TRUE)
- message_admins("[src] re-adminned themselves.")
- log_admin("[src] re-adminned themselves.")
- BLACKBOX_LOG_ADMIN_VERB("Readmin")
-
-/client/proc/populate_world(amount = 50)
- set name = "Populate World"
- set category = "Debug"
- set desc = "(\"Amount of mobs to create\") Populate the world with test mobs."
-
+ADMIN_VERB(populate_world, R_DEBUG, "Populate World", "Populate the world with test mobs.", ADMIN_CATEGORY_DEBUG, amount = 50 as num)
for (var/i in 1 to amount)
var/turf/tile = get_safe_random_station_turf()
var/mob/living/carbon/human/hooman = new(tile)
hooman.equipOutfit(pick(subtypesof(/datum/outfit)))
testing("Spawned test mob at [get_area_name(tile, TRUE)] ([tile.x],[tile.y],[tile.z])")
-/client/proc/toggle_AI_interact()
- set name = "Toggle Admin AI Interact"
- set category = "Admin.Game"
- set desc = "Allows you to interact with most machines as an AI would as a ghost"
-
- AI_Interact = !AI_Interact
- if(mob && isAdminGhostAI(mob))
- mob.has_unlimited_silicon_privilege = AI_Interact
-
- log_admin("[key_name(usr)] has [AI_Interact ? "activated" : "deactivated"] Admin AI Interact")
- message_admins("[key_name_admin(usr)] has [AI_Interact ? "activated" : "deactivated"] their AI interaction")
-
-/client/proc/debugstatpanel()
- set name = "Debug Stat Panel"
- set category = "Debug"
-
- src.stat_panel.send_message("create_debug")
-
-/client/proc/admin_2fa_verify()
- set name = "Verify Admin"
- set category = "Admin"
-
- var/datum/admins/admin = GLOB.admin_datums[ckey]
- admin?.associate(src)
-
-/client/proc/display_sendmaps()
- set name = "Send Maps Profile"
- set category = "Debug"
+ADMIN_VERB(toggle_ai_interact, R_ADMIN, "Toggle Admin AI Interact", "Allows you to interact with most machines as an AI would as a ghost.", ADMIN_CATEGORY_GAME)
+ user.AI_Interact = !user.AI_Interact
+ if(user.mob && isAdminGhostAI(user.mob))
+ user.mob.has_unlimited_silicon_privilege = user.AI_Interact
- src << link("?debug=profile&type=sendmaps&window=test")
+ log_admin("[key_name(user)] has [user.AI_Interact ? "activated" : "deactivated"] Admin AI Interact")
+ message_admins("[key_name_admin(user)] has [user.AI_Interact ? "activated" : "deactivated"] their AI interaction")
-/**
- * Debug verb that spawns human crewmembers
- * of each job type, gives them a mind and assigns the role,
- * and injects them into the manifest, as if they were a "player".
- *
- * This spawns humans with minds and jobs, but does NOT make them 'players'.
- * They're all clientles mobs with minds / jobs.
- */
-/client/proc/spawn_debug_full_crew()
- set name = "Spawn Debug Full Crew"
- set desc = "Creates a full crew for the station, filling the datacore and assigning them all minds / jobs. Don't do this on live"
- set category = "Debug"
+ADMIN_VERB(debug_statpanel, R_DEBUG, "Debug Stat Panel", "Toggles local debug of the stat panel", ADMIN_CATEGORY_DEBUG)
+ user.stat_panel.send_message("create_debug")
- if(!check_rights(R_DEBUG))
- return
-
- var/mob/admin = usr
+ADMIN_VERB(display_sendmaps, R_DEBUG, "Send Maps Profile", "View the profile.", ADMIN_CATEGORY_DEBUG)
+ user << link("?debug=profile&type=sendmaps&window=test")
+ADMIN_VERB(spawn_debug_full_crew, R_DEBUG, "Spawn Debug Full Crew", "Creates a full crew for the station, flling datacore and assigning minds and jobs.", ADMIN_CATEGORY_DEBUG)
if(SSticker.current_state != GAME_STATE_PLAYING)
- to_chat(admin, "You should only be using this after a round has setup and started.")
+ to_chat(user, "You should only be using this after a round has setup and started.")
return
// Two input checks here to make sure people are certain when they're using this.
- if(tgui_alert(admin, "This command will create a bunch of dummy crewmembers with minds, job, and datacore entries, which will take a while and fill the manifest.", "Spawn Crew", list("Yes", "Cancel")) != "Yes")
+ if(tgui_alert(user, "This command will create a bunch of dummy crewmembers with minds, job, and datacore entries, which will take a while and fill the manifest.", "Spawn Crew", list("Yes", "Cancel")) != "Yes")
return
- if(tgui_alert(admin, "I sure hope you aren't doing this on live. Are you sure?", "Spawn Crew (Be certain)", list("Yes", "Cancel")) != "Yes")
+ if(tgui_alert(user, "I sure hope you aren't doing this on live. Are you sure?", "Spawn Crew (Be certain)", list("Yes", "Cancel")) != "Yes")
return
// Find the observer spawn, so we have a place to dump the dummies.
var/obj/effect/landmark/observer_start/observer_point = locate(/obj/effect/landmark/observer_start) in GLOB.landmarks_list
var/turf/destination = get_turf(observer_point)
if(!destination)
- to_chat(admin, "Failed to find the observer spawn to send the dummies.")
+ to_chat(user, "Failed to find the observer spawn to send the dummies.")
return
// Okay, now go through all nameable occupations.
@@ -1087,7 +535,7 @@ GLOBAL_PROTECT(admin_verbs_poll)
// Assign the rank to the new player dummy.
if(!SSjob.AssignRole(new_guy, job, do_eligibility_checks = FALSE))
qdel(new_guy)
- to_chat(admin, "[rank] wasn't able to be spawned.")
+ to_chat(user, "[rank] wasn't able to be spawned.")
continue
// It's got a job, spawn in a human and shove it in the human.
@@ -1108,13 +556,9 @@ GLOBAL_PROTECT(admin_verbs_poll)
number_made++
CHECK_TICK
- to_chat(admin, "[number_made] crewmembers have been created.")
-
-/// Debug verb for seeing at a glance what all spells have as set requirements
-/client/proc/debug_spell_requirements()
- set name = "Show Spell Requirements"
- set category = "Debug"
+ to_chat(user, "[number_made] crewmembers have been created.")
+ADMIN_VERB(debug_spell_requirements, R_DEBUG, "Debug Spell Requirements", "View all spells and their requirements.", ADMIN_CATEGORY_DEBUG)
var/header = "
---|
Name | Requirements | "
var/all_requirements = list()
for(var/datum/action/cooldown/spell/spell as anything in typesof(/datum/action/cooldown/spell))
@@ -1142,69 +586,52 @@ GLOBAL_PROTECT(admin_verbs_poll)
var/page_style = ""
var/page_contents = "[page_style][header][jointext(all_requirements, "")]
"
- var/datum/browser/popup = new(mob, "spellreqs", "Spell Requirements", 600, 400)
+ var/datum/browser/popup = new(user.mob, "spellreqs", "Spell Requirements", 600, 400)
popup.set_content(page_contents)
popup.open()
-/client/proc/force_load_lazy_template()
- set name = "Load/Jump Lazy Template"
- set category = "Admin.Events"
- if(!check_rights(R_ADMIN))
- return
-
+ADMIN_VERB(load_lazy_template, R_ADMIN, "Load/Jump Lazy Template", "Loads a lazy template and/or jumps to it.", ADMIN_CATEGORY_EVENTS)
var/list/choices = LAZY_TEMPLATE_KEY_LIST_ALL()
- var/choice = tgui_input_list(usr, "Key?", "Lazy Loader", choices)
+ var/choice = tgui_input_list(user, "Key?", "Lazy Loader", choices)
if(!choice)
return
choice = choices[choice]
if(!choice)
- to_chat(usr, span_warning("No template with that key found, report this!"))
+ to_chat(user, span_warning("No template with that key found, report this!"))
return
var/already_loaded = LAZYACCESS(SSmapping.loaded_lazy_templates, choice)
var/force_load = FALSE
- if(already_loaded && (tgui_alert(usr, "Template already loaded.", "", list("Jump", "Load Again")) == "Load Again"))
+ if(already_loaded && (tgui_alert(user, "Template already loaded.", "", list("Jump", "Load Again")) == "Load Again"))
force_load = TRUE
var/datum/turf_reservation/reservation = SSmapping.lazy_load_template(choice, force = force_load)
if(!reservation)
- to_chat(usr, span_boldwarning("Failed to load template!"))
+ to_chat(user, span_boldwarning("Failed to load template!"))
return
- if(!isobserver(usr))
- admin_ghost()
- usr.forceMove(reservation.bottom_left_turfs[1])
+ if(!isobserver(user.mob))
+ SSadmin_verbs.dynamic_invoke_verb(user, /datum/admin_verb/admin_ghost)
+ user.mob.forceMove(reservation.bottom_left_turfs[1])
- message_admins("[key_name_admin(usr)] has loaded lazy template '[choice]'")
- to_chat(usr, span_boldnicegreen("Template loaded, you have been moved to the bottom left of the reservation."))
+ message_admins("[key_name_admin(user)] has loaded lazy template '[choice]'")
+ to_chat(user, span_boldnicegreen("Template loaded, you have been moved to the bottom left of the reservation."))
-/client/proc/library_control()
- set name = "Library Management"
- set category = "Admin"
- if(!check_rights(R_BAN))
- return
-
- if(!holder.library_manager)
- holder.library_manager = new()
- holder.library_manager.ui_interact(usr)
+ADMIN_VERB(library_control, R_BAN, "Library Management", "List and manage the Library.", ADMIN_CATEGORY_MAIN)
+ if(!user.holder.library_manager)
+ user.holder.library_manager = new
+ user.holder.library_manager.ui_interact(user.mob)
BLACKBOX_LOG_ADMIN_VERB("Library Management")
-/client/proc/create_mob_worm()
- set category = "Admin.Fun"
- set name = "Create Mob Worm"
- set desc = "Attached a linked list of mobs to a marked mob"
- if (!check_rights(R_FUN))
- return
- if(isnull(holder))
- return
- if(!isliving(holder.marked_datum))
- to_chat(usr, span_warning("Error: Please mark a mob to attach mobs to."))
+ADMIN_VERB(create_mob_worm, R_FUN, "Create Mob Worm", "Attach a linked list of mobs to your marked mob.", ADMIN_CATEGORY_FUN)
+ if(!isliving(user.holder.marked_datum))
+ to_chat(user, span_warning("Error: Please mark a mob to attach mobs to."))
return
- var/mob/living/head = holder.marked_datum
+ var/mob/living/head = user.holder.marked_datum
var/attempted_target_path = tgui_input_text(
- usr,
+ user,
"Enter typepath of a mob you'd like to make your chain from.",
"Typepath",
"[/mob/living/basic/pet/dog/corgi/ian]",
@@ -1219,7 +646,7 @@ GLOBAL_PROTECT(admin_verbs_poll)
if(isnull(desired_mob) || !ispath(desired_mob) || QDELETED(head))
return //The user pressed "Cancel"
- var/amount = tgui_input_number(usr, "How long should our tail be?", "Worm Configurator", default = 3, min_value = 1)
+ var/amount = tgui_input_number(user, "How long should our tail be?", "Worm Configurator", default = 3, min_value = 1)
if (isnull(amount) || amount < 1 || QDELETED(head))
return
head.AddComponent(/datum/component/mob_chain)
diff --git a/code/modules/admin/callproc/callproc.dm b/code/modules/admin/callproc/callproc.dm
index 1680304679e..823a4a9e64b 100644
--- a/code/modules/admin/callproc/callproc.dm
+++ b/code/modules/admin/callproc/callproc.dm
@@ -92,11 +92,8 @@ GLOBAL_PROTECT(AdminProcCallHandler)
usr = lastusr
handler.remove_caller(user)
-/client/proc/callproc()
- set category = "Debug"
- set name = "Advanced ProcCall"
- set waitfor = FALSE
- callproc_blocking()
+ADMIN_VERB(advanced_proc_call, R_DEBUG, "Advanced ProcCall", "Call a proc on any datum in the server.", ADMIN_CATEGORY_DEBUG)
+ user.callproc_blocking()
/client/proc/callproc_blocking(list/get_retval)
if(!check_rights(R_DEBUG))
@@ -230,37 +227,30 @@ GLOBAL_PROTECT(LastAdminCalledProc)
return (GLOB.AdminProcCaller && GLOB.AdminProcCaller == usr?.client?.ckey) || (GLOB.AdminProcCallHandler && usr == GLOB.AdminProcCallHandler)
#endif
-/client/proc/callproc_datum(datum/A as null|area|mob|obj|turf)
- set category = "Debug"
- set name = "Atom ProcCall"
- set waitfor = FALSE
-
- if(!check_rights(R_DEBUG))
- return
-
- var/procname = input("Proc name, eg: fake_blood","Proc:", null) as text|null
+ADMIN_VERB_ONLY_CONTEXT_MENU(call_proc_datum, R_DEBUG, "Atom ProcCall", datum/thing as null|area|mob|obj|turf)
+ var/procname = input(user, "Proc name, eg: fake_blood","Proc:", null) as text|null
if(!procname)
return
- if(!hascall(A,procname))
- to_chat(usr, "Error: callproc_datum(): type [A.type] has no proc named [procname].", confidential = TRUE)
+ if(!hascall(thing, procname))
+ to_chat(user, "Error: callproc_datum(): type [thing.type] has no proc named [procname].", confidential = TRUE)
return
- var/list/lst = get_callproc_args()
+ var/list/lst = user.get_callproc_args()
if(!lst)
return
- if(!A || !is_valid_src(A))
- to_chat(usr, span_warning("Error: callproc_datum(): owner of proc no longer exists."), confidential = TRUE)
+ if(!thing || !is_valid_src(thing))
+ to_chat(user, span_warning("Error: callproc_datum(): owner of proc no longer exists."), confidential = TRUE)
return
- log_admin("[key_name(src)] called [A]'s [procname]() with [lst.len ? "the arguments [list2params(lst)]":"no arguments"].")
- var/msg = "[key_name(src)] called [A]'s [procname]() with [lst.len ? "the arguments [list2params(lst)]":"no arguments"]."
+ log_admin("[key_name(user)] called [thing]'s [procname]() with [lst.len ? "the arguments [list2params(lst)]":"no arguments"].")
+ var/msg = "[key_name(user)] called [thing]'s [procname]() with [lst.len ? "the arguments [list2params(lst)]":"no arguments"]."
message_admins(msg)
- admin_ticket_log(A, msg)
+ admin_ticket_log(thing, msg)
BLACKBOX_LOG_ADMIN_VERB("Atom ProcCall")
- var/returnval = WrapAdminProcCall(A, procname, lst) // Pass the lst as an argument list to the proc
- . = get_callproc_returnval(returnval,procname)
+ var/returnval = WrapAdminProcCall(thing, procname, lst) // Pass the lst as an argument list to the proc
+ . = user.get_callproc_returnval(returnval,procname)
if(.)
- to_chat(usr, ., confidential = TRUE)
+ to_chat(user, ., confidential = TRUE)
/client/proc/get_callproc_args()
var/argnum = input("Number of arguments","Number:",0) as num|null
diff --git a/code/modules/admin/force_event.dm b/code/modules/admin/force_event.dm
index 20066547de9..519adbd8a9e 100644
--- a/code/modules/admin/force_event.dm
+++ b/code/modules/admin/force_event.dm
@@ -1,12 +1,6 @@
-///Allows an admin to force an event
-/client/proc/forceEvent()
- set name = "Trigger Event"
- set category = "Admin.Events"
- if(!holder || !check_rights(R_FUN))
- return
-
- holder.forceEvent()
+ADMIN_VERB(force_event, R_FUN, "Trigger Event", "Forces an event to occur.", ADMIN_CATEGORY_EVENTS)
+ user.holder.forceEvent()
///Opens up the Force Event Panel
/datum/admins/proc/forceEvent()
diff --git a/code/modules/admin/known_alts.dm b/code/modules/admin/known_alts.dm
index d6486f77bd7..4105c7f4edc 100644
--- a/code/modules/admin/known_alts.dm
+++ b/code/modules/admin/known_alts.dm
@@ -187,8 +187,5 @@ GLOBAL_DATUM_INIT(known_alts, /datum/known_alts, new)
client << browse(html, "window=known_alts;size=700x400")
-/datum/admins/proc/known_alts_panel()
- set name = "Known Alts Panel"
- set category = "Admin"
-
- GLOB.known_alts.show_panel(usr.client)
+ADMIN_VERB(known_alts_panel, R_ADMIN, "Known Alts Panel", "View a panel of known alts.", ADMIN_CATEGORY_MAIN)
+ GLOB.known_alts.show_panel(user)
diff --git a/code/modules/admin/outfit_manager.dm b/code/modules/admin/outfit_manager.dm
index fcb41b3f2f1..f3ef7d2685c 100644
--- a/code/modules/admin/outfit_manager.dm
+++ b/code/modules/admin/outfit_manager.dm
@@ -1,18 +1,8 @@
-/client/proc/outfit_manager()
- set category = "Debug"
- set name = "Outfit Manager"
-
- if(!check_rights(R_DEBUG))
- return
- var/datum/outfit_manager/ui = new(usr)
- ui.ui_interact(usr)
-
+ADMIN_VERB(outfit_manager, R_DEBUG|R_ADMIN, "Outfit Manager", "View and edit outfits.", ADMIN_CATEGORY_DEBUG)
+ var/static/datum/outfit_manager/ui = new
+ ui.ui_interact(user.mob)
/datum/outfit_manager
- var/client/owner
-
-/datum/outfit_manager/New(user)
- owner = CLIENT_FROM_VAR(user)
/datum/outfit_manager/ui_state(mob/user)
return GLOB.admin_state
@@ -53,24 +43,24 @@
switch(action)
if("new")
- owner.open_outfit_editor(new /datum/outfit)
+ ui.user.client.open_outfit_editor(new /datum/outfit)
if("load")
- owner.holder.load_outfit(owner.mob)
+ ui.user.client.holder.load_outfit(ui.user)
if("copy")
- var/datum/outfit/outfit = tgui_input_list(owner, "Pick an outfit to copy from", "Outfit Manager", subtypesof(/datum/outfit))
+ var/datum/outfit/outfit = tgui_input_list(ui.user, "Pick an outfit to copy from", "Outfit Manager", subtypesof(/datum/outfit))
if(isnull(outfit))
return
if(!ispath(outfit))
return
- owner.open_outfit_editor(new outfit)
+ ui.user.client.open_outfit_editor(new outfit)
var/datum/outfit/target_outfit = locate(params["outfit"])
if(!istype(target_outfit))
return
switch(action) //wow we're switching through action again this is horrible optimization smh
if("edit")
- owner.open_outfit_editor(target_outfit)
+ ui.user.client.open_outfit_editor(target_outfit)
if("save")
- owner.holder.save_outfit(owner.mob, target_outfit)
+ ui.user.client.holder.save_outfit(ui.user, target_outfit)
if("delete")
- owner.holder.delete_outfit(owner.mob, target_outfit)
+ ui.user.client.holder.delete_outfit(ui.user, target_outfit)
diff --git a/code/modules/admin/painting_manager.dm b/code/modules/admin/painting_manager.dm
index bd7d28fb73f..7a8bd7127a4 100644
--- a/code/modules/admin/painting_manager.dm
+++ b/code/modules/admin/painting_manager.dm
@@ -1,11 +1,6 @@
-/datum/admins/proc/paintings_manager()
- set name = "Paintings Manager"
- set category = "Admin"
-
- if(!check_rights(R_ADMIN))
- return
- var/datum/paintings_manager/ui = new(usr)
- ui.ui_interact(usr)
+ADMIN_VERB(painting_manager, R_ADMIN, "Paintings Manager", "View and redact paintings.", ADMIN_CATEGORY_MAIN)
+ var/static/datum/paintings_manager/ui = new
+ ui.ui_interact(user.mob)
/// Painting Admin Management Panel
/datum/paintings_manager
diff --git a/code/modules/admin/permissionedit.dm b/code/modules/admin/permissionedit.dm
index cf816fef8a7..e92ab1729e2 100644
--- a/code/modules/admin/permissionedit.dm
+++ b/code/modules/admin/permissionedit.dm
@@ -1,10 +1,6 @@
-/client/proc/edit_admin_permissions()
- set category = "Admin"
- set name = "Permissions Panel"
- set desc = "Edit admin permissions"
- if(!check_rights(R_PERMISSIONS))
- return
- usr.client.holder.edit_admin_permissions()
+
+ADMIN_VERB(edit_admin_permissions, R_PERMISSIONS, "Permissions Panel", "Edit admin permissions.", ADMIN_CATEGORY_MAIN)
+ user.holder.edit_admin_permissions()
/datum/admins/proc/edit_admin_permissions(action, target, operation, page)
if(!check_rights(R_PERMISSIONS))
diff --git a/code/modules/admin/stickyban.dm b/code/modules/admin/stickyban.dm
index 537e0b92acb..fede9724ab1 100644
--- a/code/modules/admin/stickyban.dm
+++ b/code/modules/admin/stickyban.dm
@@ -481,10 +481,5 @@
. = list2params(.)
-
-/client/proc/stickybanpanel()
- set name = "Sticky Ban Panel"
- set category = "Admin"
- if (!holder)
- return
- holder.stickyban_show()
+ADMIN_VERB(panel_sticky_ban, R_BAN, "Sticky Ban Panel", "List and manage sticky bans.", ADMIN_CATEGORY_MAIN)
+ user.holder.stickyban_show()
diff --git a/code/modules/admin/tag.dm b/code/modules/admin/tag.dm
index 64c6c16fc40..e52112eba14 100644
--- a/code/modules/admin/tag.dm
+++ b/code/modules/admin/tag.dm
@@ -49,21 +49,14 @@
[X.getToxLoss()] \
[X.getOxyLoss()]"
-/// Display all of the tagged datums
-/datum/admins/proc/display_tags()
- set category = "Admin.Game"
- set name = "View Tags"
-
- if (!istype(src, /datum/admins))
- src = usr.client.holder
- if (!istype(src, /datum/admins))
- to_chat(usr, "Error: you are not an admin!", confidential = TRUE)
- return
-
+ADMIN_VERB(display_tags, R_ADMIN, "View Tags", "Display all of the tagged datums.", ADMIN_CATEGORY_GAME)
var/index = 0
var/list/dat = list("Tag Menu
")
- dat += "
Refresh
"
+ var/list/tagged_datums = user.holder.tagged_datums
+ var/list/marked_datum = user.holder.marked_datum
+
+ dat += "
Refresh
"
if(LAZYLEN(tagged_datums))
for(var/datum/iter_datum as anything in tagged_datums)
index++
@@ -71,7 +64,7 @@
if(isnull(iter_datum))
dat += "\t[index]: Null reference - Check runtime logs!"
- stack_trace("Null datum found in tagged datum menu! User: [usr]")
+ stack_trace("Null datum found in tagged datum menu! User: [user]")
continue
else if(iscarbon(iter_datum))
var/mob/living/carbon/resolved_carbon = iter_datum
@@ -99,7 +92,7 @@
dat += "No datums tagged :("
dat = dat.Join("
")
- usr << browse(dat, "window=tag;size=800x480")
+ user << browse(dat, "window=tag;size=800x480")
#undef TAG_DEL
#undef TAG_MARK
diff --git a/code/modules/admin/topic.dm b/code/modules/admin/topic.dm
index ce5ea7bb4f5..137409e573c 100644
--- a/code/modules/admin/topic.dm
+++ b/code/modules/admin/topic.dm
@@ -173,8 +173,7 @@
to_chat(usr, "[shuttle_console] was [shuttle_console.admin_controlled ? "locked" : "unlocked"].", confidential = TRUE)
else if(href_list["delay_round_end"])
- // Permissions are checked in delay_round_end
- delay_round_end()
+ return SSadmin_verbs.dynamic_invoke_verb(usr, /datum/admin_verb/delay_round_end)
else if(href_list["undelay_round_end"])
if(!check_rights(R_SERVER))
@@ -769,21 +768,10 @@
our_mob.AIize(our_mob.client, move)
else if(href_list["makerobot"])
- if(!check_rights(R_SPAWN))
- return
-
- var/mob/our_mob = locate(href_list["makerobot"])
- if(!istype(our_mob))
- return
- if(iscyborg(our_mob))
- to_chat(usr, "That's already a cyborg.", confidential = TRUE)
- return
-
- usr.client.cmd_admin_robotize(our_mob)
+ return SSadmin_verbs.dynamic_invoke_verb(usr, /datum/admin_verb/cmd_admin_robotize, locate(href_list["makerobot"]))
else if(href_list["adminplayeropts"])
- var/mob/M = locate(href_list["adminplayeropts"])
- show_player_panel(M)
+ return SSadmin_verbs.dynamic_invoke_verb(usr, /datum/admin_verb/show_player_panel, locate(href_list["adminplayeropts"]))
else if(href_list["ppbyckey"])
var/target_ckey = href_list["ppbyckey"]
@@ -798,7 +786,7 @@
return
to_chat(usr, span_notice("Jumping to [target_ckey]'s new mob: [target_mob]!"))
- show_player_panel(target_mob)
+ return SSadmin_verbs.dynamic_invoke_verb(usr, /datum/admin_verb/show_player_panel, target_mob)
else if(href_list["adminplayerobservefollow"])
if(!isobserver(usr) && !check_rights(R_ADMIN))
@@ -815,20 +803,13 @@
AM.forceMove(get_turf(usr))
else if(href_list["adminplayerobservecoodjump"])
- if(!isobserver(usr) && !check_rights(R_ADMIN))
- return
- if(isnewplayer(usr))
- return
-
- var/x = text2num(href_list["X"])
- var/y = text2num(href_list["Y"])
- var/z = text2num(href_list["Z"])
-
- var/client/C = usr.client
- if(!isobserver(usr))
- C.admin_ghost()
- sleep(0.2 SECONDS)
- C.jumptocoord(x,y,z)
+ return SSadmin_verbs.dynamic_invoke_verb(
+ usr,
+ /datum/admin_verb/jump_to_coord,
+ text2num(href_list["X"]),
+ text2num(href_list["Y"]),
+ text2num(href_list["Z"]),
+ )
else if(href_list["adminchecklaws"])
if(!check_rights(R_ADMIN))
@@ -1028,15 +1009,7 @@
give_admin_popup(target, owner, message)
else if(href_list["adminsmite"])
- if(!check_rights(R_ADMIN|R_FUN))
- return
-
- var/mob/living/carbon/human/H = locate(href_list["adminsmite"]) in GLOB.mob_list
- if(!H || !istype(H))
- to_chat(usr, "This can only be used on instances of type /mob/living/carbon/human", confidential = TRUE)
- return
-
- usr.client.smite(H)
+ return SSadmin_verbs.dynamic_invoke_verb(usr, /datum/admin_verb/admin_smite, locate(href_list["adminsmite"]))
else if(href_list["CentComReply"])
if(!check_rights(R_ADMIN))
@@ -1065,42 +1038,21 @@
var/obj/item/station_charter/charter = locate(href_list["reject_custom_name"])
if(istype(charter))
charter.reject_proposed(usr)
- else if(href_list["jumpto"])
- if(!isobserver(usr) && !check_rights(R_ADMIN))
- return
- var/mob/M = locate(href_list["jumpto"])
- usr.client.jumptomob(M)
+ else if(href_list["jumpto"])
+ return SSadmin_verbs.dynamic_invoke_verb(usr, /datum/admin_verb/jump_to_mob, locate(href_list["jumpto"]))
else if(href_list["getmob"])
- if(!check_rights(R_ADMIN))
- return
-
- if(tgui_alert(usr, "Confirm?", "Message", list("Yes", "No")) != "Yes")
- return
- var/mob/M = locate(href_list["getmob"])
- usr.client.Getmob(M)
+ return SSadmin_verbs.dynamic_invoke_verb(usr, /datum/admin_verb/get_mob, locate(href_list["getmob"]))
else if(href_list["sendmob"])
- if(!check_rights(R_ADMIN))
- return
-
- var/mob/M = locate(href_list["sendmob"])
- usr.client.sendmob(M)
+ return SSadmin_verbs.dynamic_invoke_verb(usr, /datum/admin_verb/send_mob, locate(href_list["sendmob"]))
else if(href_list["narrateto"])
- if(!check_rights(R_ADMIN))
- return
-
- var/mob/M = locate(href_list["narrateto"])
- usr.client.cmd_admin_direct_narrate(M)
+ return SSadmin_verbs.dynamic_invoke_verb(usr, /datum/admin_verb/cmd_admin_direct_narrate, locate(href_list["narrateto"]))
else if(href_list["subtlemessage"])
- if(!check_rights(R_ADMIN))
- return
-
- var/mob/M = locate(href_list["subtlemessage"])
- usr.client.cmd_admin_subtle_message(M)
+ return SSadmin_verbs.dynamic_invoke_verb(usr, /datum/admin_verb/cmd_admin_subtle_message, locate(href_list["subtlemessage"]))
else if(href_list["playsoundto"])
if(!check_rights(R_SOUND))
@@ -1109,7 +1061,7 @@
var/mob/M = locate(href_list["playsoundto"])
var/S = input("", "Select a sound file",) as null|sound
if(S)
- usr.client.play_direct_mob_sound(S, M)
+ SSadmin_verbs.dynamic_invoke_verb(usr.client, /datum/admin_verb/play_direct_mob_sound, S, M)
else if(href_list["individuallog"])
if(!check_rights(R_ADMIN))
@@ -1148,7 +1100,8 @@
else
D.traitor_panel()
else
- show_traitor_panel(M)
+ SSadmin_verbs.dynamic_invoke_verb(usr, /datum/admin_verb/show_traitor_panel, M)
+ return
else if(href_list["skill"])
if(!check_rights(R_ADMIN))
@@ -1168,17 +1121,11 @@
else
to_chat(usr, "This can only be used on instances of type /mob and /mind", confidential = TRUE)
return
- show_skill_panel(target_mind)
+ SSadmin_verbs.dynamic_invoke_verb(usr, /datum/admin_verb/show_skill_panel, target_mind)
+ return
else if(href_list["borgpanel"])
- if(!check_rights(R_ADMIN))
- return
-
- var/mob/M = locate(href_list["borgpanel"])
- if(!iscyborg(M))
- to_chat(usr, "This can only be used on cyborgs", confidential = TRUE)
- else
- open_borgopanel(M)
+ return SSadmin_verbs.dynamic_invoke_verb(usr, /datum/admin_verb/borg_panel, locate(href_list["borgpanel"]))
else if(href_list["initmind"])
if(!check_rights(R_ADMIN))
@@ -1350,9 +1297,7 @@
return
else if(href_list["check_antagonist"])
- if(!check_rights(R_ADMIN))
- return
- usr.client.check_antagonists()
+ SSadmin_verbs.dynamic_invoke_verb(usr, /datum/admin_verb/check_antagonists)
else if(href_list["kick_all_from_lobby"])
if(!check_rights(R_ADMIN))
@@ -1422,7 +1367,7 @@
log_admin("[key_name(usr)] turned a Lag Switch measure at index ([switch_index]) [LAZYACCESS(SSlag_switch.measures, switch_index) ? "ON" : "OFF"]")
message_admins("[key_name_admin(usr)] turned a Lag Switch measure [LAZYACCESS(SSlag_switch.measures, switch_index) ? "ON" : "OFF"]")
- src.show_lag_switch_panel()
+ SSadmin_verbs.dynamic_invoke_verb(usr, /datum/admin_verb/lag_switch_panel)
else if(href_list["change_lag_switch_option"])
if(!check_rights(R_ADMIN))
@@ -1451,7 +1396,7 @@
log_admin("[key_name(usr)] set the Lag Switch slowmode cooldown to [new_num] seconds.")
message_admins("[key_name_admin(usr)] set the Lag Switch slowmode cooldown to [new_num] seconds.")
- src.show_lag_switch_panel()
+ SSadmin_verbs.dynamic_invoke_verb(usr, /datum/admin_verb/lag_switch_panel)
else if(href_list["viewruntime"])
var/datum/error_viewer/error_viewer = locate(href_list["viewruntime"])
@@ -1567,13 +1512,7 @@
toggle_id_ctf(usr, CTF_GHOST_CTF_GAME_ID)
else if(href_list["rebootworld"])
- if(!check_rights(R_ADMIN))
- return
- var/confirm = tgui_alert(usr,"Are you sure you want to reboot the server?", "Confirm Reboot", list("Yes", "No"))
- if(confirm == "No")
- return
- if(confirm == "Yes")
- restart()
+ SSadmin_verbs.dynamic_invoke_verb(usr, /datum/admin_verb/restart)
else if(href_list["check_teams"])
if(!check_rights(R_ADMIN))
@@ -1792,9 +1731,7 @@
return remove_tagged_datum(datum_to_remove)
else if(href_list["show_tags"])
- if(!check_rights(R_ADMIN))
- return
- return display_tags()
+ return SSadmin_verbs.dynamic_invoke_verb(usr, /datum/admin_verb/display_tags)
else if(href_list["mark_datum"])
if(!check_rights(R_ADMIN))
@@ -1850,7 +1787,4 @@
web_sound(usr, link_url, credit)
else if(href_list["debug_z_levels"])
- if(!check_rights(R_DEBUG))
- return
-
- owner.debug_z_levels()
+ return SSadmin_verbs.dynamic_invoke_verb(usr, /datum/admin_verb/debug_z_levels)
diff --git a/code/modules/admin/trophy_manager.dm b/code/modules/admin/trophy_manager.dm
index 6a45afb8e45..5ad703b0994 100644
--- a/code/modules/admin/trophy_manager.dm
+++ b/code/modules/admin/trophy_manager.dm
@@ -1,11 +1,6 @@
-/datum/admins/proc/trophy_manager()
- set name = "Trophy Manager"
- set category = "Admin"
-
- if(!check_rights(R_ADMIN))
- return
- var/datum/trophy_manager/ui = new(usr)
- ui.ui_interact(usr)
+ADMIN_VERB(trophy_manager, R_ADMIN, "Trophy Manager", "View all trophies.", ADMIN_CATEGORY_MAIN)
+ var/static/datum/trophy_manager/ui = new
+ ui.ui_interact(user.mob)
/// Trophy Admin Management Panel
/datum/trophy_manager
diff --git a/code/modules/admin/verb_datums/_admin_verb_datum.dm b/code/modules/admin/verb_datums/_admin_verb_datum.dm
new file mode 100644
index 00000000000..6255d962c40
--- /dev/null
+++ b/code/modules/admin/verb_datums/_admin_verb_datum.dm
@@ -0,0 +1,27 @@
+GENERAL_PROTECT_DATUM(/datum/admin_verb)
+
+/**
+ * This is the admin verb datum. It is used to store the verb's information and handle the verb's functionality.
+ * All of this is setup for you, and you should not be defining this manually.
+ * That means you reader.
+ */
+/datum/admin_verb
+ var/name //! The name of the verb.
+ var/description //! The description of the verb.
+ var/category //! The category of the verb.
+ var/permissions //! The permissions required to use the verb.
+ var/visibility_flag //! The flag that determines if the verb is visible.
+ VAR_PROTECTED/verb_path //! The path to the verb proc.
+
+/datum/admin_verb/Destroy(force)
+ if(!force)
+ return QDEL_HINT_LETMELIVE
+ return ..()
+
+/// Assigns the verb to the admin.
+/datum/admin_verb/proc/assign_to_client(client/admin)
+ add_verb(admin, verb_path)
+
+/// Unassigns the verb from the admin.
+/datum/admin_verb/proc/unassign_from_client(client/admin)
+ remove_verb(admin, verb_path)
diff --git a/code/modules/admin/verb_datums/_admin_verb_holder.dm b/code/modules/admin/verb_datums/_admin_verb_holder.dm
new file mode 100644
index 00000000000..e69de29bb2d
diff --git a/code/modules/admin/verbs/SDQL2/SDQL_2.dm b/code/modules/admin/verbs/SDQL2/SDQL_2.dm
index 50da67115ea..36db4fa8bc4 100644
--- a/code/modules/admin/verbs/SDQL2/SDQL_2.dm
+++ b/code/modules/admin/verbs/SDQL2/SDQL_2.dm
@@ -195,20 +195,15 @@
state = SDQL2_STATE_ERROR;\
CRASH("SDQL2 fatal error");};
-/client/proc/SDQL2_query(query_text as message)
- set category = "Debug"
- if(!check_rights(R_DEBUG)) //Shouldn't happen... but just to be safe.
- message_admins(span_danger("ERROR: Non-admin [key_name(usr)] attempted to execute a SDQL query!"))
- usr.log_message("non-admin attempted to execute a SDQL query!", LOG_ADMIN)
- return FALSE
- var/prompt = tgui_alert(usr, "Run SDQL2 Query?", "SDQL2", list("Yes", "Cancel"))
+ADMIN_VERB(sdql2_query, R_DEBUG, "SDQL2 Query", "Run a SDQL2 query.", ADMIN_CATEGORY_DEBUG, query_text as message)
+ var/prompt = tgui_alert(user, "Run SDQL2 Query?", "SDQL2", list("Yes", "Cancel"))
if (prompt != "Yes")
return
- var/list/results = world.SDQL2_query(query_text, key_name_admin(usr), "[key_name(usr)]")
+ var/list/results = world.SDQL2_query(query_text, key_name_admin(user), "[key_name(user)]")
if(length(results) == 3)
for(var/I in 1 to 3)
- to_chat(usr, span_admin(results[I]), confidential = TRUE)
- SSblackbox.record_feedback("nested tally", "SDQL query", 1, list(ckey, query_text))
+ to_chat(user, span_admin(results[I]), confidential = TRUE)
+ SSblackbox.record_feedback("nested tally", "SDQL query", 1, list(user.ckey, query_text))
/world/proc/SDQL2_query(query_text, log_entry1, log_entry2, silent = FALSE)
var/query_log = "executed SDQL query(s): \"[query_text]\"."
diff --git a/code/modules/admin/verbs/admin.dm b/code/modules/admin/verbs/admin.dm
index d78014e84d2..93028ac9e5e 100644
--- a/code/modules/admin/verbs/admin.dm
+++ b/code/modules/admin/verbs/admin.dm
@@ -1,15 +1,5 @@
-// Admin Tab - Admin Verbs
-
-/client/proc/show_tip()
- set category = "Admin"
- set name = "Show Tip"
- set desc = "Sends a tip (that you specify) to all players. After all \
- you're the experienced player here."
-
- if(!check_rights(R_ADMIN))
- return
-
- var/input = input(usr, "Please specify your tip that you want to send to the players.", "Tip", "") as message|null
+ADMIN_VERB(show_tip, R_ADMIN, "Show Tip", "Sends a tip to all players.", ADMIN_CATEGORY_MAIN)
+ var/input = input(user, "Please specify your tip that you want to send to the players.", "Tip", "") as message|null
if(!input)
return
@@ -22,44 +12,34 @@
else
SSticker.selected_tip = input
- message_admins("[key_name_admin(usr)] sent a tip of the round.")
- log_admin("[key_name(usr)] sent \"[input]\" as the Tip of the Round.")
+ message_admins("[key_name_admin(user)] sent a tip of the round.")
+ log_admin("[key_name(user)] sent \"[input]\" as the Tip of the Round.")
BLACKBOX_LOG_ADMIN_VERB("Show Tip")
-/datum/admins/proc/announce()
- set category = "Admin"
- set name = "Announce"
- set desc="Announce your desires to the world"
- if(!check_rights(0))
+ADMIN_VERB(announce, R_ADMIN, "Announce", "Announce your desires to the world.", ADMIN_CATEGORY_MAIN)
+ var/message = input(user, "Global message to send:", "Admin Announce") as message|null
+ if(!message)
return
- var/message = input("Global message to send:", "Admin Announce", null, null) as message|null
- if(message)
- if(!check_rights(R_SERVER,0))
- message = adminscrub(message,500)
- send_ooc_announcement(message, "From [usr.client.holder.fakekey ? "Administrator" : usr.key]")
- log_admin("Announce: [key_name(usr)] : [message]")
+ if(!user.holder.check_for_rights(R_SERVER))
+ message = adminscrub(message,500)
+ send_ooc_announcement(message, "From [user.holder.fakekey ? "Administrator" : user.key]")
+ log_admin("Announce: [key_name(user)] : [message]")
BLACKBOX_LOG_ADMIN_VERB("Announce")
-/datum/admins/proc/unprison(mob/M in GLOB.mob_list)
- set category = "Admin"
- set name = "Unprison"
- if (is_centcom_level(M.z))
- SSjob.SendToLateJoin(M)
- message_admins("[key_name_admin(usr)] has unprisoned [key_name_admin(M)]")
- log_admin("[key_name(usr)] has unprisoned [key_name(M)]")
- else
- tgui_alert(usr,"[M.name] is not prisoned.")
- BLACKBOX_LOG_ADMIN_VERB("Unprison")
-
-/client/proc/cmd_admin_check_player_exp() //Allows admins to determine who the newer players are.
- set category = "Admin"
- set name = "Player Playtime"
- if(!check_rights(R_ADMIN))
+ADMIN_VERB(unprison, R_ADMIN, "UnPrison", ADMIN_VERB_NO_DESCRIPTION, ADMIN_CATEGORY_HIDDEN, mob/prisoner)
+ if(!is_centcom_level(prisoner.z))
+ tgui_alert(user, "[prisoner.name] is not prisoned.")
return
+ SSjob.SendToLateJoin(prisoner)
+ message_admins("[key_name_admin(user)] has unprisoned [key_name_admin(prisoner)]")
+ log_admin("[key_name(user)] has unprisoned [key_name(prisoner)]")
+ BLACKBOX_LOG_ADMIN_VERB("Unprison")
+
+ADMIN_VERB(cmd_admin_check_player_exp, R_ADMIN, "Player Playtime", "View player playtime.", ADMIN_CATEGORY_MAIN)
if(!CONFIG_GET(flag/use_exp_tracking))
- to_chat(usr, span_warning("Tracking is disabled in the server configuration file."), confidential = TRUE)
+ to_chat(user, span_warning("Tracking is disabled in the server configuration file."), confidential = TRUE)
return
var/list/msg = list()
@@ -67,7 +47,7 @@
for(var/client/client in sort_list(GLOB.clients, GLOBAL_PROC_REF(cmp_playtime_asc)))
msg += " [ADMIN_PP(client.mob)] [key_name_admin(client)]: " + client.get_exp_living() + ""
msg += "
---|