diff --git a/code/__defines/MC.dm b/code/__defines/MC.dm
index 57161ffac8..5173da844c 100644
--- a/code/__defines/MC.dm
+++ b/code/__defines/MC.dm
@@ -63,6 +63,10 @@
#define SS_PAUSED 3 /// paused by mc_tick_check
#define SS_SLEEPING 4 /// fire() slept.
#define SS_PAUSING 5 /// in the middle of pausing
+// Subsystem init stages
+#define INITSTAGE_EARLY 1 //! Early init stuff that doesn't need to wait for mapload
+#define INITSTAGE_MAIN 2 //! Main init stage
+#define INITSTAGE_MAX 2 //! Highest initstage.
#define SUBSYSTEM_DEF(X) GLOBAL_REAL(SS##X, /datum/controller/subsystem/##X);\
/datum/controller/subsystem/##X/New(){\
diff --git a/code/__defines/_tick.dm b/code/__defines/_tick.dm
index 54ac7d398d..f336c2e27b 100644
--- a/code/__defines/_tick.dm
+++ b/code/__defines/_tick.dm
@@ -1,15 +1,27 @@
+/// Percentage of tick to leave for master controller to run
+#define MAPTICK_MC_MIN_RESERVE 70
+#define MAPTICK_LAST_INTERNAL_TICK_USAGE (world.map_cpu)
#define TICK_LIMIT_RUNNING 80
+/// Tick limit used to resume things in stoplag
#define TICK_LIMIT_TO_RUN 70
+/// Tick limit for MC while running
#define TICK_LIMIT_MC 70
#define TICK_LIMIT_MC_INIT_DEFAULT 98
+/// for general usage of tick_usage
#define TICK_USAGE world.tick_usage
+/// to be used where the result isn't checked
+#define TICK_USAGE_REAL world.tick_usage
+/// Returns true if tick_usage is above the limit
#define TICK_CHECK ( TICK_USAGE > Master.current_ticklimit )
+/// runs stoplag if tick_usage is above the limit
#define CHECK_TICK ( TICK_CHECK ? stoplag() : 0 )
+/// Returns true if tick usage is above 95, for high priority usage
#define TICK_CHECK_HIGH_PRIORITY ( TICK_USAGE > 95 )
+/// runs stoplag if tick_usage is above 95, for high priority usage
#define CHECK_TICK_HIGH_PRIORITY ( TICK_CHECK_HIGH_PRIORITY? stoplag() : 0 )
-#define UNTIL(X) while(!(X)) stoplag()
\ No newline at end of file
+#define UNTIL(X) while(!(X)) stoplag()
diff --git a/code/__defines/statpanel.dm b/code/__defines/statpanel.dm
new file mode 100644
index 0000000000..1c304d7fb3
--- /dev/null
+++ b/code/__defines/statpanel.dm
@@ -0,0 +1,2 @@
+#define TURFLIST_UPDATED (1 << 0)
+#define TURFLIST_UPDATE_QUEUED (1 << 1)
diff --git a/code/__defines/subsystems.dm b/code/__defines/subsystems.dm
index 84c6fbd8a7..b2838f79a2 100644
--- a/code/__defines/subsystems.dm
+++ b/code/__defines/subsystems.dm
@@ -109,6 +109,7 @@ var/global/list/runlevel_flags = list(RUNLEVEL_LOBBY, RUNLEVEL_SETUP, RUNLEVEL_G
#define INIT_ORDER_SKYBOX -30 //Visual only, irrelevant to gameplay, but needs to be late enough to have overmap populated fully
#define INIT_ORDER_TICKER -50
#define INIT_ORDER_MAPRENAME -60 //Initiating after Ticker to ensure everything is loaded and everything we rely on us working
+#define INIT_ORDER_STATPANELS -98
#define INIT_ORDER_CHAT -100 //Should be last to ensure chat remains smooth during init.
@@ -140,6 +141,7 @@ var/global/list/runlevel_flags = list(RUNLEVEL_LOBBY, RUNLEVEL_SETUP, RUNLEVEL_G
#define FIRE_PRIORITY_MACHINES 100
#define FIRE_PRIORITY_TGUI 110
#define FIRE_PRIORITY_PROJECTILES 150
+#define FIRE_PRIORITY_STATPANEL 390
#define FIRE_PRIORITY_CHAT 400
#define FIRE_PRIORITY_OVERLAYS 500
#define FIRE_PRIORITY_INPUT 1000 // This must always always be the max highest priority. Player input must never be lost.
diff --git a/code/__defines/time.dm b/code/__defines/time.dm
index 9b3c384cfb..857e2fa155 100644
--- a/code/__defines/time.dm
+++ b/code/__defines/time.dm
@@ -1,3 +1,6 @@
+///displays the current time into the round, with a lot of extra code just there for ensuring it looks okay after an entire day passes
+#define ROUND_TIME(...) ( "[world.time - SSticker.round_start_time > MIDNIGHT_ROLLOVER ? "[round((world.time - SSticker.round_start_time)/MIDNIGHT_ROLLOVER)]:[worldtime2text()]" : worldtime2text()]" )
+
/// Define that just has the current in-universe year for use in whatever context you might want to display that in. (For example, 2022 -> 2562 given a 540 year offset)
#define CURRENT_STATION_YEAR (GLOB.year_integer + STATION_YEAR_OFFSET)
diff --git a/code/_helpers/icons.dm b/code/_helpers/icons.dm
index a81c09b314..ae73126472 100644
--- a/code/_helpers/icons.dm
+++ b/code/_helpers/icons.dm
@@ -97,203 +97,205 @@
// Ported from /tg/station
// Creates a single icon from a given /atom or /image. Only the first argument is required.
-/proc/getFlatIcon(image/A, defdir, deficon, defstate, defblend, start = TRUE, no_anim = FALSE)
- //Define... defines.
+// appearance_flags indicates whether appearance_flags should be respected (at the cost of about 10-20% perf)
+/proc/getFlatIcon(image/appearance, defdir, deficon, defstate, defblend, start = TRUE, no_anim = FALSE, force_south = FALSE, appearance_flags = FALSE)
+ // Loop through the underlays, then overlays, sorting them into the layers list
+ #define PROCESS_OVERLAYS_OR_UNDERLAYS(flat, process, base_layer) \
+ for (var/i in 1 to process.len) { \
+ var/image/current = process[i]; \
+ if (!current) { \
+ continue; \
+ } \
+ if (current.plane != FLOAT_PLANE && current.plane != appearance.plane) { \
+ continue; \
+ } \
+ var/current_layer = current.layer; \
+ if (current_layer < 0) { \
+ if (current_layer <= -1000) { \
+ return flat; \
+ } \
+ current_layer = base_layer + appearance.layer + current_layer / 1000; \
+ } \
+ for (var/index_to_compare_to in 1 to layers.len) { \
+ var/compare_to = layers[index_to_compare_to]; \
+ if (current_layer < layers[compare_to]) { \
+ layers.Insert(index_to_compare_to, current); \
+ break; \
+ } \
+ } \
+ layers[current] = current_layer; \
+ }
+
var/static/icon/flat_template = icon('icons/effects/effects.dmi', "nothing")
- #define BLANK icon(flat_template)
- #define SET_SELF(SETVAR) do { \
- var/icon/SELF_ICON=icon(icon(curicon, curstate, base_icon_dir),"",SOUTH,no_anim?1:null); \
- if(A.alpha<255) { \
- SELF_ICON.Blend(rgb(255,255,255,A.alpha),ICON_MULTIPLY);\
- } \
- if(A.color) { \
- if(islist(A.color)){ \
- SELF_ICON.MapColors(arglist(A.color))} \
- else{ \
- SELF_ICON.Blend(A.color,ICON_MULTIPLY)} \
- } \
- ##SETVAR=SELF_ICON;\
- } while (0)
- #define INDEX_X_LOW 1
- #define INDEX_X_HIGH 2
- #define INDEX_Y_LOW 3
- #define INDEX_Y_HIGH 4
-
- #define flatX1 flat_size[INDEX_X_LOW]
- #define flatX2 flat_size[INDEX_X_HIGH]
- #define flatY1 flat_size[INDEX_Y_LOW]
- #define flatY2 flat_size[INDEX_Y_HIGH]
- #define addX1 add_size[INDEX_X_LOW]
- #define addX2 add_size[INDEX_X_HIGH]
- #define addY1 add_size[INDEX_Y_LOW]
- #define addY2 add_size[INDEX_Y_HIGH]
-
- if(!A || A.alpha <= 0)
- return BLANK
-
- var/noIcon = FALSE
+ if(!appearance || appearance.alpha <= 0)
+ return icon(flat_template)
if(start)
if(!defdir)
- defdir = A.dir
+ defdir = appearance.dir
if(!deficon)
- deficon = A.icon
+ deficon = appearance.icon
if(!defstate)
- defstate = A.icon_state
+ defstate = appearance.icon_state
if(!defblend)
- defblend = A.blend_mode
+ defblend = appearance.blend_mode
- var/curicon = A.icon || deficon
- var/curstate = A.icon_state || defstate
+ var/curicon = appearance.icon || deficon
+ var/curstate = appearance.icon_state || defstate
+ var/curdir = (!appearance.dir || appearance.dir == SOUTH) ? defdir : appearance.dir
- if(!((noIcon = (!curicon))))
- var/curstates = cached_icon_states(curicon)
+ if(force_south)
+ curdir = SOUTH
+
+ var/render_icon = curicon
+
+ if (render_icon)
+ var/curstates = icon_states(curicon)
if(!(curstate in curstates))
- if("" in curstates)
+ if ("" in curstates)
curstate = ""
else
- noIcon = TRUE // Do not render this object.
+ render_icon = FALSE
- var/curdir
- var/base_icon_dir //We'll use this to get the icon state to display if not null BUT NOT pass it to overlays as the dir we have
+ var/base_icon_dir //We'll use this to get the icon state to display if not null BUT NOT pass it to overlays as the dir we have
- // Use the requested dir or the atom's current dir
- curdir = defdir || A.dir
-
- //Try to remove/optimize this section ASAP, CPU hog. //Slightly mitigated by implementing caching using cached_icon_states
+ //Try to remove/optimize this section ASAP, CPU hog.
//Determines if there's directionals.
- if(!noIcon && curdir != SOUTH)
- var/exist = FALSE
- var/static/list/checkdirs = list(NORTH, EAST, WEST)
- for(var/i in checkdirs) //Not using GLOB for a reason.
- if(length(cached_icon_states(icon(curicon, curstate, i))))
- exist = TRUE
- break
- if(!exist)
+ if(render_icon && curdir != SOUTH)
+ if (
+ !length(icon_states(icon(curicon, curstate, NORTH))) \
+ && !length(icon_states(icon(curicon, curstate, EAST))) \
+ && !length(icon_states(icon(curicon, curstate, WEST))) \
+ )
base_icon_dir = SOUTH
- //
if(!base_icon_dir)
base_icon_dir = curdir
- ASSERT(!BLEND_DEFAULT) //I might just be stupid but lets make sure this define is 0.
+ var/curblend = appearance.blend_mode || defblend
- var/curblend = A.blend_mode || defblend
-
- if(A.overlays.len || A.underlays.len)
- var/icon/flat = BLANK
+ if(appearance.overlays.len || appearance.underlays.len)
+ var/icon/flat = icon(flat_template)
// Layers will be a sorted list of icons/overlays, based on the order in which they are displayed
var/list/layers = list()
var/image/copy
// Add the atom's icon itself, without pixel_x/y offsets.
- if(!noIcon)
- copy = image(icon=curicon, icon_state=curstate, layer=A.layer, dir=base_icon_dir)
- copy.color = A.color
- copy.alpha = A.alpha
+ if(render_icon)
+ copy = image(icon=curicon, icon_state=curstate, layer=appearance.layer, dir=base_icon_dir)
+ copy.color = appearance.color
+ copy.alpha = appearance.alpha
copy.blend_mode = curblend
- layers[copy] = A.layer
+ layers[copy] = appearance.layer
- // Loop through the underlays, then overlays, sorting them into the layers list
- for(var/process_set in 0 to 1)
- var/list/process = process_set? A.overlays : A.underlays
- for(var/i in 1 to process.len)
- var/image/current = process[i]
- if(!current)
- continue
- if(current.plane != FLOAT_PLANE && current.plane != A.plane)
- continue
- var/current_layer = current.layer
- if(current_layer < 0)
- //if(current_layer <= -1000)
- //return flat
- current_layer = process_set + A.layer + current_layer / 1000
-
- for(var/p in 1 to layers.len)
- var/image/cmp = layers[p]
- if(current_layer < layers[cmp])
- layers.Insert(p, current)
- break
- layers[current] = current_layer
-
- //sortTim(layers, GLOBAL_PROC_REF(cmp_image_layer_asc))
+ PROCESS_OVERLAYS_OR_UNDERLAYS(flat, appearance.underlays, 0)
+ PROCESS_OVERLAYS_OR_UNDERLAYS(flat, appearance.overlays, 1)
var/icon/add // Icon of overlay being added
- // Current dimensions of flattened icon
- var/list/flat_size = list(1, flat.Width(), 1, flat.Height())
- // Dimensions of overlay being added
- var/list/add_size[4]
+ var/flatX1 = 1
+ var/flatX2 = flat.Width()
+ var/flatY1 = 1
+ var/flatY2 = flat.Height()
- for(var/V in layers)
- var/image/I = V
- if(I.alpha == 0)
+ var/addX1 = 0
+ var/addX2 = 0
+ var/addY1 = 0
+ var/addY2 = 0
+
+ for(var/image/layer_image as anything in layers)
+ if(layer_image.alpha == 0)
continue
- if(I == copy) // 'I' is an /image based on the object being flattened.
+ // variables only relevant when accounting for appearance_flags:
+ var/apply_color = TRUE
+ var/apply_alpha = TRUE
+
+ if(layer_image == copy) // 'layer_image' is an /image based on the object being flattened.
curblend = BLEND_OVERLAY
- add = icon(I.icon, I.icon_state, base_icon_dir)
+ add = icon(layer_image.icon, layer_image.icon_state, base_icon_dir)
else // 'I' is an appearance object.
- add = getFlatIcon(image(I), curdir, curicon, curstate, curblend, FALSE, no_anim)
+ var/image/layer_as_image = image(layer_image)
+ if(appearance_flags)
+ if(layer_as_image.appearance_flags & RESET_COLOR)
+ apply_color = FALSE
+ if(layer_as_image.appearance_flags & RESET_ALPHA)
+ apply_alpha = FALSE
+ add = getFlatIcon(layer_as_image, curdir, curicon, curstate, curblend, FALSE, no_anim, force_south, appearance_flags)
if(!add)
continue
- // Find the new dimensions of the flat icon to fit the added overlay
- add_size = list(
- min(flatX1, I.pixel_x+1),
- max(flatX2, I.pixel_x+add.Width()),
- min(flatY1, I.pixel_y+1),
- max(flatY2, I.pixel_y+add.Height())
- )
- if(flat_size ~! add_size)
+ // Find the new dimensions of the flat icon to fit the added overlay
+ addX1 = min(flatX1, layer_image.pixel_x + 1)
+ addX2 = max(flatX2, layer_image.pixel_x + add.Width())
+ addY1 = min(flatY1, layer_image.pixel_y + 1)
+ addY2 = max(flatY2, layer_image.pixel_y + add.Height())
+
+ if (
+ addX1 != flatX1 \
+ || addX2 != flatX2 \
+ || addY1 != flatY1 \
+ || addY2 != flatY2 \
+ )
// Resize the flattened icon so the new icon fits
flat.Crop(
- addX1 - flatX1 + 1,
- addY1 - flatY1 + 1,
- addX2 - flatX1 + 1,
- addY2 - flatY1 + 1
+ addX1 - flatX1 + 1,
+ addY1 - flatY1 + 1,
+ addX2 - flatX1 + 1,
+ addY2 - flatY1 + 1
)
- flat_size = add_size.Copy()
+
+ flatX1 = addX1
+ flatX2 = addX2
+ flatY1 = addY1
+ flatY2 = addY2
+
+ if(appearance_flags)
+ // apply parent's color/alpha to the added layers if the layer didn't opt
+ if(apply_color && appearance.color)
+ if(islist(appearance.color))
+ add.MapColors(arglist(appearance.color))
+ else
+ add.Blend(appearance.color, ICON_MULTIPLY)
+
+ if(apply_alpha && appearance.alpha < 255)
+ add.Blend(rgb(255, 255, 255, appearance.alpha), ICON_MULTIPLY)
// Blend the overlay into the flattened icon
- flat.Blend(add, blendMode2iconMode(curblend), I.pixel_x + 2 - flatX1, I.pixel_y + 2 - flatY1)
+ flat.Blend(add, blendMode2iconMode(curblend), layer_image.pixel_x + 2 - flatX1, layer_image.pixel_y + 2 - flatY1)
- if(A.color)
- if(islist(A.color))
- flat.MapColors(arglist(A.color))
- else
- flat.Blend(A.color, ICON_MULTIPLY)
+ if(!appearance_flags)
+ // If we didn't apply parent colors individually per layer respecting appearance_flags, then do it just the one time now
+ if(appearance.color)
+ if(islist(appearance.color))
+ flat.MapColors(arglist(appearance.color))
+ else
+ flat.Blend(appearance.color, ICON_MULTIPLY)
- if(A.alpha < 255)
- flat.Blend(rgb(255, 255, 255, A.alpha), ICON_MULTIPLY)
+ if(appearance.alpha < 255)
+ flat.Blend(rgb(255, 255, 255, appearance.alpha), ICON_MULTIPLY)
if(no_anim)
//Clean up repeated frames
var/icon/cleaned = new /icon()
cleaned.Insert(flat, "", SOUTH, 1, 0)
- . = cleaned
+ return cleaned
else
- . = icon(flat, "", SOUTH)
- else //There's no overlays.
- if(!noIcon)
- SET_SELF(.)
+ return icon(flat, "", SOUTH)
+ else if (render_icon) // There's no overlays.
+ var/icon/final_icon = icon(icon(curicon, curstate, base_icon_dir), "", SOUTH, no_anim ? TRUE : null)
- //Clear defines
- #undef flatX1
- #undef flatX2
- #undef flatY1
- #undef flatY2
- #undef addX1
- #undef addX2
- #undef addY1
- #undef addY2
+ if (appearance.alpha < 255)
+ final_icon.Blend(rgb(255,255,255, appearance.alpha), ICON_MULTIPLY)
- #undef INDEX_X_LOW
- #undef INDEX_X_HIGH
- #undef INDEX_Y_LOW
- #undef INDEX_Y_HIGH
+ if (appearance.color)
+ if (islist(appearance.color))
+ final_icon.MapColors(arglist(appearance.color))
+ else
+ final_icon.Blend(appearance.color, ICON_MULTIPLY)
- #undef BLANK
- #undef SET_SELF
+ return final_icon
+
+ #undef PROCESS_OVERLAYS_OR_UNDERLAYS
/proc/getIconMask(atom/A)//By yours truly. Creates a dynamic mask for a mob/whatever. /N
var/icon/alpha_mask = new(A.icon,A.icon_state)//So we want the default icon and icon state of A.
@@ -676,7 +678,7 @@ GLOBAL_LIST_EMPTY(cached_examine_icons)
icon_state = thing.icon_state
//Despite casting to atom, this code path supports mutable appearances, so let's be nice to them
//if(isnull(icon_state) || (isatom(thing) && thing.flags_1 & HTML_USE_INITAL_ICON_1))
- if(isnull(icon_state) || isatom(thing))
+ if(isnull(icon_state) && isatom(thing))
icon_state = initial(thing.icon_state)
if (isnull(dir))
dir = initial(thing.dir)
@@ -745,7 +747,7 @@ GLOBAL_LIST_EMPTY(cached_examine_icons)
return ""
//Costlier version of icon2html() that uses getFlatIcon() to account for overlays, underlays, etc. Use with extreme moderation, ESPECIALLY on mobs.
-/proc/costly_icon2html(thing, target, sourceonly = FALSE)
+/proc/costly_icon2html(thing, target, sourceonly = FALSE, force_south = FALSE)
if (!thing)
return
//if(SSlag_switch.measures[DISABLE_USR_ICON2HTML] && usr && !HAS_TRAIT(usr, TRAIT_BYPASS_MEASURES))
@@ -754,5 +756,5 @@ GLOBAL_LIST_EMPTY(cached_examine_icons)
if (isicon(thing))
return icon2html(thing, target)
- var/icon/I = getFlatIcon(thing)
+ var/icon/I = getFlatIcon(thing, force_south = force_south)
return icon2html(I, target, sourceonly = sourceonly)
diff --git a/code/_helpers/time.dm b/code/_helpers/time.dm
index 802359a1b7..b1d372f435 100644
--- a/code/_helpers/time.dm
+++ b/code/_helpers/time.dm
@@ -1,3 +1,7 @@
+//Returns the world time in english
+/proc/worldtime2text()
+ return gameTimestamp("hh:mm:ss", world.time)
+
#define TimeOfGame (get_game_time())
#define TimeOfTick (TICK_USAGE*0.01*world.tick_lag)
diff --git a/code/_helpers/verbs.dm b/code/_helpers/verbs.dm
new file mode 100644
index 0000000000..8a35bb9c6c
--- /dev/null
+++ b/code/_helpers/verbs.dm
@@ -0,0 +1,94 @@
+/**
+ * handles adding verbs and updating the stat panel browser
+ *
+ * pass the verb type path to this instead of adding it directly to verbs so the statpanel can update
+ * Arguments:
+ * * target - Who the verb is being added to, client or mob typepath
+ * * verb - typepath to a verb, or a list of verbs, supports lists of lists
+ */
+/proc/add_verb(client/target, verb_or_list_to_add)
+ if(!target)
+ CRASH("add_verb called without a target")
+ if(IsAdminAdvancedProcCall())
+ return
+ var/mob/mob_target = null
+
+ if(ismob(target))
+ mob_target = target
+ target = mob_target.client
+ else if(!istype(target, /client))
+ CRASH("add_verb called on a non-mob and non-client")
+ var/list/verbs_list = list()
+ if(!islist(verb_or_list_to_add))
+ verbs_list += verb_or_list_to_add
+ else
+ var/list/verb_listref = verb_or_list_to_add
+ var/list/elements_to_process = verb_listref.Copy()
+ while(length(elements_to_process))
+ var/element_or_list = elements_to_process[length(elements_to_process)] //Last element
+ elements_to_process.len--
+ if(islist(element_or_list))
+ elements_to_process += element_or_list //list/a += list/b adds the contents of b into a, not the reference to the list itself
+ else
+ verbs_list += element_or_list
+
+ if(mob_target)
+ mob_target.verbs += verbs_list
+ if(!target)
+ return //Our work is done.
+ else
+ target.verbs += verbs_list
+
+ var/list/output_list = list()
+ for(var/thing in verbs_list)
+ var/procpath/verb_to_add = thing
+ output_list[++output_list.len] = list(verb_to_add.category, verb_to_add.name, verb_to_add.desc)
+
+ target.stat_panel.send_message("add_verb_list", output_list)
+
+/**
+ * handles removing verb and sending it to browser to update, use this for removing verbs
+ *
+ * pass the verb type path to this instead of removing it from verbs so the statpanel can update
+ * Arguments:
+ * * target - Who the verb is being removed from, client or mob typepath
+ * * verb - typepath to a verb, or a list of verbs, supports lists of lists
+ */
+/proc/remove_verb(client/target, verb_or_list_to_remove)
+ if(IsAdminAdvancedProcCall())
+ return
+
+ var/mob/mob_target = null
+ if(ismob(target))
+ mob_target = target
+ target = mob_target.client
+ else if(!istype(target, /client))
+ CRASH("remove_verb called on a non-mob and non-client")
+
+ var/list/verbs_list = list()
+ if(!islist(verb_or_list_to_remove))
+ verbs_list += verb_or_list_to_remove
+ else
+ var/list/verb_listref = verb_or_list_to_remove
+ var/list/elements_to_process = verb_listref.Copy()
+ while(length(elements_to_process))
+ var/element_or_list = elements_to_process[length(elements_to_process)] //Last element
+ elements_to_process.len--
+ if(islist(element_or_list))
+ elements_to_process += element_or_list //list/a += list/b adds the contents of b into a, not the reference to the list itself
+ else
+ verbs_list += element_or_list
+
+ if(mob_target)
+ mob_target.verbs -= verbs_list
+ if(!target)
+ return //Our work is done.
+ else
+ target.verbs -= verbs_list
+
+ var/list/output_list = list()
+ for(var/thing in verbs_list)
+ var/procpath/verb_to_remove = thing
+ output_list[++output_list.len] = list(verb_to_remove.category, verb_to_remove.name)
+
+ target.stat_panel.send_message("remove_verb_list", output_list)
diff --git a/code/_onclick/click.dm b/code/_onclick/click.dm
index d303529c1e..3562ed09a7 100644
--- a/code/_onclick/click.dm
+++ b/code/_onclick/click.dm
@@ -286,16 +286,9 @@
/atom/proc/AltClick(var/mob/user)
var/turf/T = get_turf(src)
if(T && user.TurfAdjacent(T))
- user.ToggleTurfTab(T)
+ user.set_listed_turf(T)
return 1
-/mob/proc/ToggleTurfTab(var/turf/T)
- if(listed_turf == T)
- listed_turf = null
- else
- listed_turf = T
- client.statpanel = "Turf"
-
/mob/proc/TurfAdjacent(var/turf/T)
return T.AdjacentQuick(src)
diff --git a/code/_onclick/observer.dm b/code/_onclick/observer.dm
index 75d1208a40..f8dc673b5f 100644
--- a/code/_onclick/observer.dm
+++ b/code/_onclick/observer.dm
@@ -41,7 +41,7 @@
if(modifiers["alt"]) // alt and alt-gr (rightalt)
var/turf/T = get_turf(A)
if(T && TurfAdjacent(T))
- ToggleTurfTab(T)
+ set_listed_turf(T)
return
// You are responsible for checking config.ghost_interaction when you override this function
// Not all of them require checking, see below
diff --git a/code/controllers/controller.dm b/code/controllers/controller.dm
index c9d5f1e565..1f0a01a072 100644
--- a/code/controllers/controller.dm
+++ b/code/controllers/controller.dm
@@ -16,4 +16,4 @@
/datum/controller/proc/Recover()
-/datum/controller/proc/stat_entry()
+/datum/controller/proc/stat_entry(msg)
diff --git a/code/controllers/failsafe.dm b/code/controllers/failsafe.dm
index 3022944ec3..dfe8bc7234 100644
--- a/code/controllers/failsafe.dm
+++ b/code/controllers/failsafe.dm
@@ -96,8 +96,9 @@ var/datum/controller/failsafe/Failsafe
/datum/controller/failsafe/proc/defcon_pretty()
return defcon
-/datum/controller/failsafe/stat_entry()
+/datum/controller/failsafe/stat_entry(msg)
if(!statclick)
statclick = new/obj/effect/statclick/debug(null, "Initializing...", src)
- stat("Failsafe Controller:", statclick.update("Defcon: [defcon_pretty()] (Interval: [Failsafe.processing_interval] | Iteration: [Failsafe.master_iteration])"))
+ msg = "Failsafe Controller: [statclick.update("Defcon: [defcon_pretty()] (Interval: [Failsafe.processing_interval] | Iteration: [Failsafe.master_iteration])")]"
+ return msg
diff --git a/code/controllers/globals.dm b/code/controllers/globals.dm
index cd6e7544dd..bf9c7e1e9c 100644
--- a/code/controllers/globals.dm
+++ b/code/controllers/globals.dm
@@ -32,11 +32,12 @@ GLOBAL_REAL(GLOB, /datum/controller/global_vars)
return ..()
-/datum/controller/global_vars/stat_entry()
+/datum/controller/global_vars/stat_entry(msg)
if(!statclick)
statclick = new/obj/effect/statclick/debug(null, "Initializing...", src)
- stat("GLOB:", statclick.update("Edit"))
+ msg = "GLOB: [statclick.update("Edit")]"
+ return msg
/datum/controller/global_vars/vv_edit_var(var_name, var_value)
if(gvars_datum_protected_varlist[var_name])
diff --git a/code/controllers/master.dm b/code/controllers/master.dm
index 49f34a5c97..049e687a95 100644
--- a/code/controllers/master.dm
+++ b/code/controllers/master.dm
@@ -582,12 +582,14 @@ GLOBAL_REAL(Master, /datum/controller/master) = new
-/datum/controller/master/stat_entry()
+/datum/controller/master/stat_entry(msg)
if(!statclick)
statclick = new/obj/effect/statclick/debug(null, "Initializing...", src)
- stat("Byond:", "(FPS:[world.fps]) (TickCount:[world.time/world.tick_lag]) (TickDrift:[round(Master.tickdrift,1)]([round((Master.tickdrift/(world.time/world.tick_lag))*100,0.1)]%))")
- stat("Master Controller:", statclick.update("(TickRate:[Master.processing]) (Iteration:[Master.iteration])"))
+ msg = "Byond: (FPS:[world.fps]) (TickCount:[world.time/world.tick_lag]) (TickDrift:[round(Master.tickdrift,1)]([round((Master.tickdrift/(world.time/world.tick_lag))*100,0.1)]%))"
+ msg += "Master Controller: [statclick.update("(TickRate:[Master.processing]) (Iteration:[Master.iteration])")]"
+
+ return msg
/datum/controller/master/StartLoadingMap(var/quiet = TRUE)
if(map_loading)
diff --git a/code/controllers/subsystem.dm b/code/controllers/subsystem.dm
index 5297314ab1..9c5fcbe5cb 100644
--- a/code/controllers/subsystem.dm
+++ b/code/controllers/subsystem.dm
@@ -164,22 +164,11 @@
//hook for printing stats to the "MC" statuspanel for admins to see performance and related stats etc.
/datum/controller/subsystem/stat_entry(msg)
- if(!statclick)
- statclick = new/obj/effect/statclick/debug(null, "Initializing...", src)
-
-
- if(SS_NO_FIRE & flags)
- msg = "NO FIRE\t[msg]"
- else if(can_fire <= 0)
- msg = "OFFLINE\t[msg]"
- else
+ if(can_fire && !(SS_NO_FIRE & flags))
msg = "[round(cost,1)]ms|[round(tick_usage,1)]%([round(tick_overrun,1)]%)|[round(ticks,0.1)]\t[msg]"
-
- var/title = name
- if (can_fire)
- title = "\[[state_letter()]][title]"
-
- stat(title, statclick.update(msg))
+ else
+ msg = "OFFLINE\t[msg]"
+ return msg
/datum/controller/subsystem/proc/state_letter()
switch (state)
diff --git a/code/controllers/subsystems/ai.dm b/code/controllers/subsystems/ai.dm
index eb29e2fec2..4e5256d949 100644
--- a/code/controllers/subsystems/ai.dm
+++ b/code/controllers/subsystems/ai.dm
@@ -12,8 +12,9 @@ SUBSYSTEM_DEF(ai)
var/slept_mobs = 0
var/list/process_z = list()
-/datum/controller/subsystem/ai/stat_entry(msg_prefix)
- ..("P: [processing.len] | S: [slept_mobs]")
+/datum/controller/subsystem/ai/stat_entry(msg)
+ msg = "P: [processing.len] | S: [slept_mobs]"
+ return ..()
/datum/controller/subsystem/ai/fire(resumed = 0)
if (!resumed)
diff --git a/code/controllers/subsystems/aifast.dm b/code/controllers/subsystems/aifast.dm
index f045a7fd35..2580c156ac 100644
--- a/code/controllers/subsystems/aifast.dm
+++ b/code/controllers/subsystems/aifast.dm
@@ -9,10 +9,9 @@ SUBSYSTEM_DEF(aifast)
var/list/processing = list()
var/list/currentrun = list()
-/datum/controller/subsystem/aifast/stat_entry(msg_prefix)
- var/list/msg = list(msg_prefix)
- msg += "P:[processing.len]"
- ..(msg.Join())
+/datum/controller/subsystem/aifast/stat_entry(msg)
+ msg = "P:[processing.len]"
+ return ..()
/datum/controller/subsystem/aifast/fire(resumed = 0)
if (!resumed)
diff --git a/code/controllers/subsystems/air.dm b/code/controllers/subsystems/air.dm
index 4886a11c27..1e5f1506ec 100644
--- a/code/controllers/subsystems/air.dm
+++ b/code/controllers/subsystems/air.dm
@@ -244,9 +244,8 @@ Total Unsimulated Turfs: [world.maxx*world.maxy*world.maxz - simulated_turf_coun
if(MC_TICK_CHECK)
return
-/datum/controller/subsystem/air/stat_entry(msg_prefix)
- var/list/msg = list(msg_prefix)
- msg += "S:[current_step ? part_names[current_step] : ""] "
+/datum/controller/subsystem/air/stat_entry(msg)
+ msg = "S:[current_step ? part_names[current_step] : ""] "
msg += "C:{"
msg += "T [round(cost_turfs, 1)] | "
msg += "E [round(cost_edges, 1)] | "
@@ -263,7 +262,7 @@ Total Unsimulated Turfs: [world.maxx*world.maxy*world.maxz - simulated_turf_coun
msg += "H [active_hotspots.len] | "
msg += "Z [zones_to_update.len] "
msg += "}"
- ..(msg.Join())
+ return ..()
// ZAS might displace objects as the map loads if an air tick is processed mid-load.
/datum/controller/subsystem/air/StartLoadingMap(var/quiet = TRUE)
diff --git a/code/controllers/subsystems/alarm.dm b/code/controllers/subsystems/alarm.dm
index 868025eca3..e3507a34e4 100644
--- a/code/controllers/subsystems/alarm.dm
+++ b/code/controllers/subsystems/alarm.dm
@@ -41,5 +41,6 @@ SUBSYSTEM_DEF(alarm)
/datum/controller/subsystem/alarm/proc/number_of_active_alarms()
return active_alarm_cache.len
-/datum/controller/subsystem/alarm/stat_entry()
- ..("[number_of_active_alarms()] alarm\s")
+/datum/controller/subsystem/alarm/stat_entry(msg)
+ msg = "[number_of_active_alarms()] alarm\s"
+ return ..()
diff --git a/code/controllers/subsystems/chemistry.dm b/code/controllers/subsystems/chemistry.dm
index 148e975542..6f0c5959eb 100644
--- a/code/controllers/subsystems/chemistry.dm
+++ b/code/controllers/subsystems/chemistry.dm
@@ -20,8 +20,9 @@ SUBSYSTEM_DEF(chemistry)
initialize_chemical_reactions()
..()
-/datum/controller/subsystem/chemistry/stat_entry()
- ..("C: [chemical_reagents.len] | R: [chemical_reactions.len]")
+/datum/controller/subsystem/chemistry/stat_entry(msg)
+ msg = "C: [chemical_reagents.len] | R: [chemical_reactions.len]"
+ return ..()
//Chemical Reactions - Initialises all /decl/chemical_reaction into a list
// It is filtered into multiple lists within a list.
@@ -43,7 +44,7 @@ SUBSYSTEM_DEF(chemistry)
// add_to = fusion_reactions_by_reagent
if(istype(D, /decl/chemical_reaction/distilling))
add_to = distilled_reactions_by_reagent
-
+
LAZYINITLIST(add_to[reagent_id])
add_to[reagent_id] += D
diff --git a/code/controllers/subsystems/events.dm b/code/controllers/subsystems/events.dm
index 83ab2fa00c..5bdf83fdec 100644
--- a/code/controllers/subsystems/events.dm
+++ b/code/controllers/subsystems/events.dm
@@ -41,8 +41,9 @@ SUBSYSTEM_DEF(events)
var/datum/event_container/EC = event_containers[i]
EC.process()
-/datum/controller/subsystem/events/stat_entry()
- ..("E:[active_events.len]")
+/datum/controller/subsystem/events/stat_entry(msg)
+ msg = "E:[active_events.len]"
+ return ..()
/datum/controller/subsystem/events/Recover()
if(SSevents.active_events)
diff --git a/code/controllers/subsystems/inactivity.dm b/code/controllers/subsystems/inactivity.dm
index 3795468f84..c921cff022 100644
--- a/code/controllers/subsystems/inactivity.dm
+++ b/code/controllers/subsystems/inactivity.dm
@@ -56,8 +56,9 @@ SUBSYSTEM_DEF(inactivity)
if (MC_TICK_CHECK)
return
-/datum/controller/subsystem/inactivity/stat_entry()
- ..("Kicked: [number_kicked]")
+/datum/controller/subsystem/inactivity/stat_entry(msg)
+ msg = "Kicked: [number_kicked]"
+ return ..()
/datum/controller/subsystem/inactivity/proc/can_kick(var/client/C)
if(C.holder) return FALSE //VOREStation Add - Don't kick admins.
diff --git a/code/controllers/subsystems/machines.dm b/code/controllers/subsystems/machines.dm
index 6721002555..dea5b7ccc3 100644
--- a/code/controllers/subsystems/machines.dm
+++ b/code/controllers/subsystems/machines.dm
@@ -82,9 +82,8 @@ SUBSYSTEM_DEF(machines)
T.broadcast_status()
CHECK_TICK
-/datum/controller/subsystem/machines/stat_entry()
- var/msg = list()
- msg += "C:{"
+/datum/controller/subsystem/machines/stat_entry(msg)
+ msg = "C:{"
msg += "PI:[round(cost_pipenets,1)]|"
msg += "MC:[round(cost_machinery,1)]|"
msg += "PN:[round(cost_powernets,1)]|"
@@ -95,7 +94,7 @@ SUBSYSTEM_DEF(machines)
msg += "PN:[SSmachines.powernets.len]|"
msg += "PO:[SSmachines.powerobjs.len]|"
msg += "MC/MS:[round((cost ? SSmachines.processing_machines.len/cost_machinery : 0),0.1)]"
- ..(jointext(msg, null))
+ return ..()
/datum/controller/subsystem/machines/proc/process_pipenets(resumed = 0)
if (!resumed)
diff --git a/code/controllers/subsystems/mobs.dm b/code/controllers/subsystems/mobs.dm
index c124b5573e..8fec502f21 100644
--- a/code/controllers/subsystems/mobs.dm
+++ b/code/controllers/subsystems/mobs.dm
@@ -19,8 +19,9 @@ SUBSYSTEM_DEF(mobs)
var/slept_mobs = 0
var/list/process_z = list()
-/datum/controller/subsystem/mobs/stat_entry()
- ..("P: [global.mob_list.len] | S: [slept_mobs]")
+/datum/controller/subsystem/mobs/stat_entry(msg)
+ msg = "P: [global.mob_list.len] | S: [slept_mobs]"
+ return ..()
/datum/controller/subsystem/mobs/fire(resumed = 0)
if (!resumed)
@@ -90,4 +91,4 @@ SUBSYSTEM_DEF(mobs)
/datum/controller/subsystem/mobs/critfail()
..()
- log_recent()
\ No newline at end of file
+ log_recent()
diff --git a/code/controllers/subsystems/orbits.dm b/code/controllers/subsystems/orbits.dm
index 5cda1ce9dc..af7a5ab7ea 100644
--- a/code/controllers/subsystems/orbits.dm
+++ b/code/controllers/subsystems/orbits.dm
@@ -7,8 +7,9 @@ SUBSYSTEM_DEF(orbit)
var/list/currentrun = list()
var/list/processing = list()
-/datum/controller/subsystem/orbit/stat_entry()
- ..("P:[processing.len]")
+/datum/controller/subsystem/orbit/stat_entry(msg)
+ msg = "P:[processing.len]"
+ return ..()
/datum/controller/subsystem/orbit/fire(resumed = 0)
@@ -40,5 +41,3 @@ SUBSYSTEM_DEF(orbit)
O.Check(targetloc)
if (MC_TICK_CHECK)
return
-
-
diff --git a/code/controllers/subsystems/overlays.dm b/code/controllers/subsystems/overlays.dm
index 9d840933cb..0a953e9782 100644
--- a/code/controllers/subsystems/overlays.dm
+++ b/code/controllers/subsystems/overlays.dm
@@ -32,8 +32,9 @@ SUBSYSTEM_DEF(overlays)
fire(FALSE, TRUE)
..()
-/datum/controller/subsystem/overlays/stat_entry()
- ..("Queued Atoms: [queue.len], Cache Size: [cache_size]")
+/datum/controller/subsystem/overlays/stat_entry(msg)
+ msg = "Queued Atoms: [queue.len], Cache Size: [cache_size]"
+ return ..()
/datum/controller/subsystem/overlays/fire(resumed, no_mc_tick)
diff --git a/code/controllers/subsystems/ping.dm b/code/controllers/subsystems/ping.dm
index 20cf8dd446..8f4836290a 100644
--- a/code/controllers/subsystems/ping.dm
+++ b/code/controllers/subsystems/ping.dm
@@ -12,8 +12,9 @@ SUBSYSTEM_DEF(ping)
runlevels = RUNLEVEL_LOBBY | RUNLEVELS_DEFAULT
var/list/currentrun = list()
-/datum/controller/subsystem/ping/stat_entry()
- ..("P:[GLOB.clients.len]")
+/datum/controller/subsystem/ping/stat_entry(msg)
+ msg = "P:[GLOB.clients.len]"
+ return ..()
/datum/controller/subsystem/ping/fire(resumed = FALSE)
// Prepare the new batch of clients
diff --git a/code/controllers/subsystems/plants.dm b/code/controllers/subsystems/plants.dm
index 42622b217d..af4815395e 100644
--- a/code/controllers/subsystems/plants.dm
+++ b/code/controllers/subsystems/plants.dm
@@ -22,8 +22,9 @@ SUBSYSTEM_DEF(plants)
var/list/processing = list()
var/list/currentrun = list()
-/datum/controller/subsystem/plants/stat_entry()
- ..("P:[processing.len]|S:[seeds.len]")
+/datum/controller/subsystem/plants/stat_entry(msg)
+ msg = "P:[processing.len]|S:[seeds.len]"
+ return ..()
/datum/controller/subsystem/plants/Initialize(timeofday)
setup()
diff --git a/code/controllers/subsystems/processing/obj_tab_items.dm b/code/controllers/subsystems/processing/obj_tab_items.dm
new file mode 100644
index 0000000000..53786daf01
--- /dev/null
+++ b/code/controllers/subsystems/processing/obj_tab_items.dm
@@ -0,0 +1,24 @@
+PROCESSING_SUBSYSTEM_DEF(obj_tab_items)
+ name = "Obj Tab Items"
+ flags = SS_NO_INIT
+ runlevels = RUNLEVEL_LOBBY | RUNLEVELS_DEFAULT
+ wait = 0.1 SECONDS
+
+// I know this is mostly copypasta, but I want to change the processing logic
+// Sorry bestie :(
+/datum/controller/subsystem/processing/obj_tab_items/fire(resumed = FALSE)
+ if (!resumed)
+ currentrun = processing.Copy()
+ //cache for sanic speed (lists are references anyways)
+ var/list/current_run = currentrun
+
+ while(current_run.len)
+ var/datum/thing = current_run[current_run.len]
+ if(QDELETED(thing))
+ processing -= thing
+ else if(thing.process(wait * 0.1) == PROCESS_KILL)
+ // fully stop so that a future START_PROCESSING will work
+ STOP_PROCESSING(src, thing)
+ if (MC_TICK_CHECK)
+ return
+ current_run.len--
diff --git a/code/controllers/subsystems/processing/processing.dm b/code/controllers/subsystems/processing/processing.dm
index 16b4da021b..51c1afe015 100644
--- a/code/controllers/subsystems/processing/processing.dm
+++ b/code/controllers/subsystems/processing/processing.dm
@@ -24,8 +24,9 @@ SUBSYSTEM_DEF(processing)
if(CHECK_BITFIELD(D.datum_flags, DF_ISPROCESSING))
processing |= D
-/datum/controller/subsystem/processing/stat_entry()
- ..("[stat_tag]:[processing.len]")
+/datum/controller/subsystem/processing/stat_entry(msg)
+ msg = "[stat_tag]:[processing.len]"
+ return ..()
/datum/controller/subsystem/processing/fire(resumed = 0)
if (!resumed)
@@ -69,14 +70,14 @@ SUBSYSTEM_DEF(processing)
log_world(msg)
return
msg += "Lists: current_run: [currentrun.len], processing: [processing.len]\n"
-
+
if(!currentrun.len)
msg += "!!The subsystem just finished the processing list, and currentrun is empty (or has never run).\n"
msg += "!!The info below is the tail of processing instead of currentrun.\n"
-
+
var/datum/D = currentrun.len ? currentrun[currentrun.len] : processing[processing.len]
msg += "Tail entry: [describeThis(D)] (this is likely the item AFTER the problem item)\n"
-
+
var/position = processing.Find(D)
if(!position)
msg += "Unable to find context of tail entry in processing list.\n"
diff --git a/code/controllers/subsystems/radiation.dm b/code/controllers/subsystems/radiation.dm
index 8f140a5fc8..967c21992f 100644
--- a/code/controllers/subsystems/radiation.dm
+++ b/code/controllers/subsystems/radiation.dm
@@ -54,8 +54,9 @@ SUBSYSTEM_DEF(radiation)
if (MC_TICK_CHECK)
return
-/datum/controller/subsystem/radiation/stat_entry()
- ..("S:[sources.len], RC:[resistance_cache.len]")
+/datum/controller/subsystem/radiation/stat_entry(msg)
+ msg = "S:[sources.len], RC:[resistance_cache.len]"
+ return ..()
// Ray trace from all active radiation sources to T and return the strongest effect.
/datum/controller/subsystem/radiation/proc/get_rads_at_turf(var/turf/T)
@@ -144,4 +145,4 @@ SUBSYSTEM_DEF(radiation)
if(!(power && source))
return
var/turf/epicentre = locate(round(world.maxx / 2), round(world.maxy / 2), source.z)
- flat_radiate(epicentre, power, world.maxx, respect_maint)
\ No newline at end of file
+ flat_radiate(epicentre, power, world.maxx, respect_maint)
diff --git a/code/controllers/subsystems/shuttles.dm b/code/controllers/subsystems/shuttles.dm
index 38ec9e5c83..02f9cb91eb 100644
--- a/code/controllers/subsystems/shuttles.dm
+++ b/code/controllers/subsystems/shuttles.dm
@@ -172,5 +172,6 @@ SUBSYSTEM_DEF(shuttles)
for(var/obj/effect/overmap/visitable/ship/ship_effect as anything in ships)
overmap_halted ? ship_effect.halt() : ship_effect.unhalt()
-/datum/controller/subsystem/shuttles/stat_entry()
- ..("Shuttles:[process_shuttles.len]/[shuttles.len], Ships:[ships.len], L:[registered_shuttle_landmarks.len][overmap_halted ? ", HALT" : ""]")
+/datum/controller/subsystem/shuttles/stat_entry(msg)
+ msg = "Shuttles:[process_shuttles.len]/[shuttles.len], Ships:[ships.len], L:[registered_shuttle_landmarks.len][overmap_halted ? ", HALT" : ""]"
+ return ..()
diff --git a/code/controllers/subsystems/statpanel.dm b/code/controllers/subsystems/statpanel.dm
new file mode 100644
index 0000000000..c80e7cd1fb
--- /dev/null
+++ b/code/controllers/subsystems/statpanel.dm
@@ -0,0 +1,481 @@
+SUBSYSTEM_DEF(statpanels)
+ name = "Stat Panels"
+ wait = 4
+ init_order = INIT_ORDER_STATPANELS
+ //init_stage = INITSTAGE_EARLY
+ priority = FIRE_PRIORITY_STATPANEL
+ runlevels = RUNLEVELS_DEFAULT | RUNLEVEL_LOBBY
+ flags = SS_NO_INIT
+ var/list/currentrun = list()
+ var/list/global_data
+ var/list/mc_data
+ var/list/cached_images = list()
+
+ ///how many subsystem fires between most tab updates
+ var/default_wait = 10
+ ///how many subsystem fires between updates of misc tabs
+ var/misc_wait = 3
+ ///how many subsystem fires between updates of the status tab
+ var/status_wait = 2
+ ///how many subsystem fires between updates of the MC tab
+ var/mc_wait = 5
+ ///how many full runs this subsystem has completed. used for variable rate refreshes.
+ var/num_fires = 0
+
+/datum/controller/subsystem/statpanels/fire(resumed = FALSE)
+ if (!resumed)
+ num_fires++
+ //var/datum/map_config/cached = SSmapping.next_map_config
+ global_data = list(
+ //"Map: [SSmapping.config?.map_name || "Loading..."]",
+ "Map: [using_map.name]",
+ //cached ? "Next Map: [cached.map_name]" : null,
+ //"Next Map: -- Not Available --",
+ // "Round ID: [GLOB.round_id ? GLOB.round_id : "NULL"]",
+ "Server Time: [time2text(world.timeofday, "YYYY-MM-DD hh:mm:ss")]",
+ "Round Time: [ROUND_TIME()]",
+ "Station Date: [stationdate2text()]", // [capitalize(GLOB.world_time_season)]",
+ "Station Time: [stationtime2text()]",
+ "Time Dilation: [round(SStime_track.time_dilation_current,1)]% AVG:([round(SStime_track.time_dilation_avg_fast,1)]%, [round(SStime_track.time_dilation_avg,1)]%, [round(SStime_track.time_dilation_avg_slow,1)]%)"
+ )
+
+ if(emergency_shuttle.evac)
+ var/ETA = emergency_shuttle.get_status_panel_eta()
+ if(ETA)
+ global_data += "[ETA]"
+ src.currentrun = GLOB.clients.Copy()
+ mc_data = null
+
+ var/list/currentrun = src.currentrun
+ while(length(currentrun))
+ var/client/target = currentrun[length(currentrun)]
+ currentrun.len--
+
+ if(!target?.stat_panel?.is_ready()) // Null target client, client has null stat panel, or stat panel isn't ready
+ continue
+
+ if(target.stat_tab == "Status" && num_fires % status_wait == 0)
+ set_status_tab(target)
+
+ if(!target.holder)
+ target.stat_panel.send_message("remove_admin_tabs")
+ else
+ //target.stat_panel.send_message("update_split_admin_tabs", !!(target.prefs.toggles & SPLIT_ADMIN_TABS))
+ target.stat_panel.send_message("update_split_admin_tabs", FALSE)
+
+ if(!("MC" in target.panel_tabs) || !("Tickets" in target.panel_tabs))
+ target.stat_panel.send_message("add_admin_tabs", target.holder.href_token)
+
+ //if(target.stat_tab == "MC" && ((num_fires % mc_wait == 0) || target?.prefs.read_preference(/datum/preference/toggle/fast_mc_refresh)))
+ //set_MC_tab(target)
+ if(target.stat_tab == "MC" && ((num_fires % mc_wait == 0)))
+ set_MC_tab(target)
+
+ if(target.stat_tab == "Tickets" && num_fires % default_wait == 0)
+ set_tickets_tab(target)
+
+ if(!length(GLOB.sdql2_queries) && ("SDQL2" in target.panel_tabs))
+ target.stat_panel.send_message("remove_sdql2")
+
+ else if(length(GLOB.sdql2_queries) && (target.stat_tab == "SDQL2" || !("SDQL2" in target.panel_tabs)) && num_fires % default_wait == 0)
+ set_SDQL2_tab(target)
+
+ if(target.mob)
+ var/mob/target_mob = target.mob
+
+ // Handle the action panels of the stat panel
+
+ var/update_actions = FALSE
+ // We're on a spell tab, update the tab so we can see cooldowns progressing and such
+ if(target.stat_tab in target.spell_tabs)
+ update_actions = TRUE
+ // We're not on a spell tab per se, but we have cooldown actions, and we've yet to
+ // set up our spell tabs at all
+ //if(!length(target.spell_tabs) && locate(/datum/action/cooldown) in target_mob.actions)
+ //update_actions = TRUE
+
+ if(update_actions && num_fires % default_wait == 0)
+ set_action_tabs(target, target_mob)
+ //Update every fire if tab is open, otherwise update every 7 fires
+ if((num_fires % misc_wait == 0))
+ update_misc_tabs(target,target_mob)
+
+ var/datum/object_window_info/obj_window = target.obj_window
+ if(obj_window)
+ if(obj_window.flags & TURFLIST_UPDATE_QUEUED)
+ immediate_send_stat_data(target)
+ obj_window.flags = 0
+
+ if(MC_TICK_CHECK)
+ return
+
+/datum/controller/subsystem/statpanels/proc/update_misc_tabs(var/client/target,var/mob/target_mob)
+ target_mob.update_misc_tabs()
+ for(var/tab in target_mob.misc_tabs)
+ if(target_mob.misc_tabs[tab].len == 0 && (tab in target.misc_tabs))
+ target.misc_tabs -= tab
+ target.stat_panel.send_message("remove_misc",tab)
+
+ if(target_mob.misc_tabs[tab].len > 0)
+ if(!(tab in target.misc_tabs))
+ target.misc_tabs += tab
+ target.stat_panel.send_message("create_misc",tab)
+ target.stat_panel.send_message("update_misc",list(
+ TN = tab, \
+ TC = target_mob.misc_tabs[tab], \
+ ))
+
+ for(var/tab in target.misc_tabs)
+ if(!(tab in target_mob.misc_tabs))
+ target.misc_tabs -= tab
+ target.stat_panel.send_message("remove_misc",tab)
+
+/datum/controller/subsystem/statpanels/proc/set_status_tab(client/target)
+ if(!global_data)//statbrowser hasnt fired yet and we were called from immediate_send_stat_data()
+ return
+
+ target.stat_panel.send_message("update_stat", list(
+ global_data = global_data,
+ ping_str = "Ping: -- Not Available --", // [round(target.lastping, 1)]ms (Average: [round(target.avgping, 1)]ms)",
+ other_str = target.mob?.get_status_tab_items(),
+ ))
+
+/datum/controller/subsystem/statpanels/proc/set_MC_tab(client/target)
+ var/turf/eye_turf = get_turf(target.eye)
+ var/coord_entry = COORD(eye_turf)
+ if(!mc_data)
+ generate_mc_data()
+ target.stat_panel.send_message("update_mc", list(mc_data = mc_data, coord_entry = coord_entry))
+
+/datum/controller/subsystem/statpanels/proc/set_examine_tab(client/target)
+ var/description_holders = target.description_holders
+ var/list/examine_update = list()
+
+ if(!target.obj_window)
+ target.obj_window = new(target)
+ if(!target.examine_icon && !target.obj_window.examine_target && target.stat_tab == "Examine")
+ target.obj_window.examine_target = description_holders["icon"]
+ target.obj_window.atoms_to_show += target.obj_window.examine_target
+ START_PROCESSING(SSobj_tab_items, target.obj_window)
+ refresh_client_obj_view(target)
+ examine_update += "[target.examine_icon] [description_holders["name"]]" //The name, written in big letters.
+ examine_update += "[description_holders["desc"]]" //the default examine text.
+ if(description_holders["info"])
+ examine_update += "" + span_bold("[replacetext(description_holders["info"], "\n", "
")]") + "
" //Blue, informative text.
+ if(description_holders["interactions"])
+ for(var/line in description_holders["interactions"])
+ examine_update += "" + span_bold("[line]") + "
"
+ if(description_holders["fluff"])
+ examine_update += "" + span_bold("[replacetext(description_holders["fluff"], "\n", "
")]") + "
" //Green, fluff-related text.
+ if(description_holders["antag"])
+ examine_update += "" + span_bold("[description_holders["antag"]]") + "
" //Red, malicious antag-related text
+
+ target.stat_panel.send_message("update_examine", examine_update)
+
+/datum/controller/subsystem/statpanels/proc/set_tickets_tab(client/target)
+ var/list/tickets = GLOB.ahelp_tickets.stat_entry(target)
+ tickets += GLOB.mhelp_tickets.stat_entry(target)
+ target.stat_panel.send_message("update_tickets", tickets)
+
+/datum/controller/subsystem/statpanels/proc/set_SDQL2_tab(client/target)
+ var/list/sdql2A = list()
+ sdql2A[++sdql2A.len] = list("", "Access Global SDQL2 List", REF(GLOB.sdql2_vv_statobj))
+ var/list/sdql2B = list()
+ for(var/datum/SDQL2_query/query as anything in GLOB.sdql2_queries)
+ sdql2B = query.generate_stat()
+
+ sdql2A += sdql2B
+ target.stat_panel.send_message("update_sdql2", sdql2A)
+
+/// Set up the various action tabs.
+/datum/controller/subsystem/statpanels/proc/set_action_tabs(client/target, mob/target_mob)
+ return
+ //var/list/actions = target_mob.get_actions_for_statpanel()
+ //target.spell_tabs.Cut()
+
+ //for(var/action_data in actions)
+ // target.spell_tabs |= action_data[1]
+
+ //target.stat_panel.send_message("update_spells", list(spell_tabs = target.spell_tabs, actions = actions))
+
+/datum/controller/subsystem/statpanels/proc/set_turf_examine_tab(client/target, mob/target_mob)
+ if(!target)//statbrowser hasnt fired yet and we were called from immediate_send_stat_data()
+ return
+ var/list/overrides = list()
+ for(var/image/target_image as anything in target.images)
+ if(!target_image.loc || target_image.loc.loc != target_mob.listed_turf || !target_image.override)
+ continue
+ overrides += target_image.loc
+
+ var/list/atoms_to_display = list(target_mob.listed_turf)
+ for(var/atom/movable/turf_content as anything in target_mob.listed_turf)
+ if(turf_content.mouse_opacity == MOUSE_OPACITY_TRANSPARENT)
+ continue
+ if(turf_content.invisibility > target_mob.see_invisible)
+ continue
+ if(turf_content in overrides)
+ continue
+ //if(turf_content.IsObscured())
+ //continue
+ atoms_to_display += turf_content
+
+ /// Set the atoms we're meant to display
+ var/datum/object_window_info/obj_window = target.obj_window
+ if(!obj_window)
+ return // previous one no longer exists
+ obj_window.atoms_to_show = atoms_to_display
+ START_PROCESSING(SSobj_tab_items, obj_window)
+ refresh_client_obj_view(target)
+
+/datum/controller/subsystem/statpanels/proc/refresh_client_obj_view(client/refresh)
+ var/list/turf_items = return_object_images(refresh)
+ if(!length(turf_items)/* || !refresh.mob?.listed_turf*/)
+ return
+ refresh.stat_panel.send_message("update_listedturf", turf_items)
+
+#define OBJ_IMAGE_LOADING "statpanels obj loading temporary"
+/// Returns all our ready object tab images
+/// Returns a list in the form list(list(object_name, object_ref, loaded_image), ...)
+/datum/controller/subsystem/statpanels/proc/return_object_images(client/load_from)
+ // You might be inclined to think that this is a waste of cpu time, since we
+ // A: Double iterate over atoms in the build case, or
+ // B: Generate these lists over and over in the refresh case
+ // It's really not very hot. The hot portion of this code is genuinely mostly in the image generation
+ // So it's ok to pay a performance cost for cleanliness here
+
+ // No turf? go away
+ /*if(!load_from.mob?.listed_turf)
+ return list()*/
+ var/datum/object_window_info/obj_window = load_from.obj_window
+ var/list/already_seen = obj_window.atoms_to_images
+ var/list/to_make = obj_window.atoms_to_imagify
+ var/list/turf_items = list()
+ for(var/atom/turf_item as anything in obj_window.atoms_to_show)
+ // First, we fill up the list of refs to display
+ // If we already have one, just use that
+ var/existing_image = already_seen[turf_item]
+ if(existing_image == OBJ_IMAGE_LOADING)
+ continue
+ // We already have it. Success!
+ if(existing_image)
+ if(turf_item == obj_window.examine_target) //not actually a turf item get trolled
+ load_from.examine_icon = ""
+ obj_window.examine_target = null
+ set_examine_tab(load_from)
+ continue
+ turf_items[++turf_items.len] = list("[turf_item.name]", REF(turf_item), existing_image)
+ continue
+ // Now, we're gonna queue image generation out of those refs
+ to_make += turf_item
+ already_seen[turf_item] = OBJ_IMAGE_LOADING
+ obj_window.RegisterSignal(turf_item, COMSIG_PARENT_QDELETING, TYPE_PROC_REF(/datum/object_window_info,viewing_atom_deleted)) // we reset cache if anything in it gets deleted
+ return turf_items
+
+#undef OBJ_IMAGE_LOADING
+
+/datum/controller/subsystem/statpanels/proc/generate_mc_data()
+ mc_data = list(
+ list("CPU:", world.cpu),
+ list("Instances:", "[num2text(world.contents.len, 10)]"),
+ list("World Time:", "[world.time]"),
+ list("Globals:", GLOB.stat_entry(), "\ref[GLOB]"),
+ // list("[config]:", config.stat_entry(), "\ref[config]"),
+ list("Byond:", "(FPS:[world.fps]) (TickCount:[world.time/world.tick_lag]) (TickDrift:[round(Master.tickdrift,1)]([round((Master.tickdrift/(world.time/world.tick_lag))*100,0.1)]%)) (Internal Tick Usage: [round(MAPTICK_LAST_INTERNAL_TICK_USAGE,0.1)]%)"),
+ list("Master Controller:", Master.stat_entry(), "\ref[Master]"),
+ list("Failsafe Controller:", Failsafe.stat_entry(), "\ref[Failsafe]"),
+ list("","")
+ )
+ for(var/datum/controller/subsystem/sub_system as anything in Master.subsystems)
+ mc_data[++mc_data.len] = list("\[[sub_system.state_letter()]][sub_system.name]", sub_system.stat_entry(), "\ref[sub_system]")
+ mc_data[++mc_data.len] = list("Camera Net", "Cameras: [global.cameranet.cameras.len] | Chunks: [global.cameranet.chunks.len]", "\ref[global.cameranet]")
+
+///immediately update the active statpanel tab of the target client
+/datum/controller/subsystem/statpanels/proc/immediate_send_stat_data(client/target)
+ if(!target.stat_panel.is_ready())
+ return FALSE
+
+ if(target.stat_tab == "Examine")
+ set_examine_tab(target)
+ return TRUE
+
+ if(target.stat_tab == "Status")
+ set_status_tab(target)
+ return TRUE
+
+ var/mob/target_mob = target.mob
+
+ // Handle actions
+
+ var/update_actions = FALSE
+ if(target.stat_tab in target.spell_tabs)
+ update_actions = TRUE
+
+ //if(!length(target.spell_tabs) && locate(/datum/action/cooldown) in target_mob.actions)
+ //update_actions = TRUE
+
+ if(update_actions)
+ set_action_tabs(target, target_mob)
+ return TRUE
+
+ // Handle turfs
+
+ if(target_mob?.listed_turf)
+ if(!target_mob.TurfAdjacent(target_mob.listed_turf))
+ target.stat_panel.send_message("removed_listedturf")
+ target_mob.listed_turf = null
+
+ else if(target.stat_tab == target_mob?.listed_turf.name || !(target_mob?.listed_turf.name in target.panel_tabs))
+ set_turf_examine_tab(target, target_mob)
+ return TRUE
+
+ if(!target.holder)
+ return FALSE
+
+ if(target.stat_tab == "MC")
+ set_MC_tab(target)
+ return TRUE
+
+ if(target.stat_tab == "Tickets")
+ set_tickets_tab(target)
+ return TRUE
+
+ if(!length(GLOB.sdql2_queries) && ("SDQL2" in target.panel_tabs))
+ target.stat_panel.send_message("remove_sdql2")
+
+ else if(length(GLOB.sdql2_queries) && target.stat_tab == "SDQL2")
+ set_SDQL2_tab(target)
+
+/atom/proc/remove_from_cache()
+ SIGNAL_HANDLER
+ SSstatpanels.cached_images -= REF(src)
+
+/// Stat panel window declaration
+/client/var/datum/tgui_window/stat_panel
+
+/// Datum that holds and tracks info about a client's object window
+/// Really only exists because I want to be able to do logic with signals
+/// And need a safe place to do the registration
+/datum/object_window_info
+ /// list of atoms to show to our client via the object tab, at least currently
+ var/list/atoms_to_show = list()
+ /// list of atom -> image string for objects we have had in the right click tab
+ /// this is our caching
+ var/list/atoms_to_images = list()
+ /// list of atoms to turn into images for the object tab
+ var/list/atoms_to_imagify = list()
+ /// Our owner client
+ var/client/parent
+ /// Are we currently tracking a turf?
+ var/actively_tracking = FALSE
+ ///For reusing this logic for examines
+ var/atom/examine_target
+ var/flags = 0
+
+/datum/object_window_info/New(client/parent)
+ . = ..()
+ src.parent = parent
+
+/datum/object_window_info/Destroy(force, ...)
+ atoms_to_show = null
+ atoms_to_images = null
+ atoms_to_imagify = null
+ parent.obj_window = null
+ parent = null
+ STOP_PROCESSING(SSobj_tab_items, src)
+ return ..()
+
+/// Takes a client, attempts to generate object images for it
+/// We will update the client with any improvements we make when we're done
+/datum/object_window_info/process(seconds_per_tick)
+ // Cache the datum access for sonic speed
+ var/list/to_make = atoms_to_imagify
+ var/list/newly_seen = atoms_to_images
+ var/index = 0
+ for(index in 1 to length(to_make))
+ var/atom/thing = to_make[index]
+
+ if(!thing) // A null thing snuck in somehow
+ continue
+
+ var/generated_string
+ if(ismob(thing) || length(thing.overlays) > 0)
+ var/force_south = FALSE
+ if(isliving(thing))
+ force_south = TRUE
+ generated_string = costly_icon2html(thing, parent, sourceonly=TRUE, force_south = force_south)
+ else
+ generated_string = icon2html(thing, parent, sourceonly=TRUE)
+
+ newly_seen[thing] = generated_string
+ if(TICK_CHECK)
+ to_make.Cut(1, index + 1)
+ index = 0
+ break
+ // If we've not cut yet, do it now
+ if(index)
+ to_make.Cut(1, index + 1)
+ SSstatpanels.refresh_client_obj_view(parent)
+ if(!length(to_make))
+ return PROCESS_KILL
+
+/datum/object_window_info/proc/start_turf_tracking()
+ if(actively_tracking)
+ stop_turf_tracking()
+ var/static/list/connections = list(
+ COMSIG_MOVABLE_MOVED = PROC_REF(on_mob_move),
+ COMSIG_MOB_LOGOUT = PROC_REF(on_mob_logout),
+ )
+ AddComponent(/datum/component/connect_mob_behalf, parent, connections)
+ RegisterSignal(parent.mob.listed_turf, COMSIG_ATOM_ENTERED, PROC_REF(turflist_changed))
+ RegisterSignal(parent.mob.listed_turf, COMSIG_ATOM_EXITED, PROC_REF(turflist_changed))
+ actively_tracking = TRUE
+
+/datum/object_window_info/proc/stop_turf_tracking()
+ qdel(GetComponent(/datum/component/connect_mob_behalf))
+ UnregisterSignal(parent.mob.listed_turf, COMSIG_ATOM_ENTERED)
+ UnregisterSignal(parent.mob.listed_turf, COMSIG_ATOM_EXITED)
+ actively_tracking = FALSE
+
+/datum/object_window_info/proc/on_mob_move(mob/source)
+ SIGNAL_HANDLER
+ var/turf/listed = source.listed_turf
+ if(!listed || !source.TurfAdjacent(listed))
+ source.set_listed_turf(null)
+
+/datum/object_window_info/proc/on_mob_logout(mob/source)
+ SIGNAL_HANDLER
+ on_mob_move(parent.mob)
+
+/datum/object_window_info/proc/turflist_changed(mob/source)
+ if(!parent)//statbrowser hasnt fired yet and we still have a pending action
+ return
+ SIGNAL_HANDLER
+ if(!(flags & TURFLIST_UPDATED)) //Limit updates to 1 per tick
+ SSstatpanels.immediate_send_stat_data(parent)
+ flags |= TURFLIST_UPDATED
+ else if(!(flags & TURFLIST_UPDATE_QUEUED))
+ flags |= TURFLIST_UPDATE_QUEUED
+
+/// Clears any cached object window stuff
+/// We use hard refs cause we'd need a signal for this anyway. Cleaner this way
+/datum/object_window_info/proc/viewing_atom_deleted(atom/deleted)
+ SIGNAL_HANDLER
+ atoms_to_show -= deleted
+ atoms_to_imagify -= deleted
+ atoms_to_images -= deleted
+
+/mob/proc/set_listed_turf(turf/new_turf)
+ if(!client)
+ listed_turf = new_turf
+ return
+ if(!client.obj_window)
+ client.obj_window = new(client)
+ if(!new_turf)
+ client.obj_window.stop_turf_tracking() //Needs to go before listed_turf is set to null so signals can be removed
+ listed_turf = new_turf
+
+ if(listed_turf)
+ client.stat_panel.send_message("create_listedturf", listed_turf.name)
+ client.obj_window.start_turf_tracking()
+ else
+ client.stat_panel.send_message("remove_listedturf")
diff --git a/code/controllers/subsystems/supply.dm b/code/controllers/subsystems/supply.dm
index 84d4d4ee9c..e7ead3b770 100644
--- a/code/controllers/subsystems/supply.dm
+++ b/code/controllers/subsystems/supply.dm
@@ -39,8 +39,9 @@ SUBSYSTEM_DEF(supply)
/datum/controller/subsystem/supply/fire()
points += points_per_process
-/datum/controller/subsystem/supply/stat_entry()
- ..("Points: [points]")
+/datum/controller/subsystem/supply/stat_entry(msg)
+ msg = "Points: [points]"
+ return ..()
//To stop things being sent to CentCom which should not be sent to centcomm. Recursively checks for these types.
/datum/controller/subsystem/supply/proc/forbidden_atoms_check(atom/A)
diff --git a/code/controllers/subsystems/tgui.dm b/code/controllers/subsystems/tgui.dm
index 46b3ae90c2..9f0baf12e6 100644
--- a/code/controllers/subsystems/tgui.dm
+++ b/code/controllers/subsystems/tgui.dm
@@ -35,8 +35,9 @@ SUBSYSTEM_DEF(tgui)
/datum/controller/subsystem/tgui/Shutdown()
close_all_uis()
-/datum/controller/subsystem/tgui/stat_entry()
- ..("P:[all_uis.len]")
+/datum/controller/subsystem/tgui/stat_entry(msg)
+ msg = "P:[all_uis.len]"
+ return ..()
/datum/controller/subsystem/tgui/fire(resumed = FALSE)
if(!resumed)
diff --git a/code/controllers/subsystems/throwing.dm b/code/controllers/subsystems/throwing.dm
index 797c5f88fb..037970ef93 100644
--- a/code/controllers/subsystems/throwing.dm
+++ b/code/controllers/subsystems/throwing.dm
@@ -9,8 +9,9 @@ SUBSYSTEM_DEF(throwing)
var/list/currentrun
var/list/processing = list()
-/datum/controller/subsystem/throwing/stat_entry()
- ..("P:[processing.len]")
+/datum/controller/subsystem/throwing/stat_entry(msg)
+ msg = "P:[processing.len]"
+ return ..()
/datum/controller/subsystem/throwing/fire(resumed = 0)
if (!resumed)
diff --git a/code/controllers/subsystems/ticker.dm b/code/controllers/subsystems/ticker.dm
index 8886957202..d8492dbd33 100644
--- a/code/controllers/subsystems/ticker.dm
+++ b/code/controllers/subsystems/ticker.dm
@@ -41,6 +41,10 @@ SUBSYSTEM_DEF(ticker)
//Now we have a general cinematic centrally held within the gameticker....far more efficient!
var/obj/screen/cinematic = null
+ var/round_start_time = 0
+
+
+
// This global variable exists for legacy support so we don't have to rename every 'ticker' to 'SSticker' yet.
var/global/datum/controller/subsystem/ticker/ticker
/datum/controller/subsystem/ticker/PreInit()
@@ -101,6 +105,7 @@ var/global/datum/controller/subsystem/ticker/ticker
// Called during GAME_STATE_SETTING_UP (RUNLEVEL_SETUP)
/datum/controller/subsystem/ticker/proc/setup_tick(resumed = FALSE)
+ round_start_time = world.time // otherwise round_start_time would be 0 for the signals
if(!setup_choose_gamemode())
// It failed, go back to lobby state and re-send the welcome message
pregame_timeleft = config.pregame_time
@@ -418,6 +423,7 @@ var/global/datum/controller/subsystem/ticker/ticker
if(new_char.client)
var/obj/screen/splash/S = new(new_char.client, TRUE)
S.Fade(TRUE)
+ new_char.client.init_verbs()
// If they're a carbon, they can get manifested
if(J?.mob_type & JOB_CARBON)
@@ -542,28 +548,29 @@ var/global/datum/controller/subsystem/ticker/ticker
return 1
-/datum/controller/subsystem/ticker/stat_entry()
+/datum/controller/subsystem/ticker/stat_entry(msg)
switch(current_state)
if(GAME_STATE_INIT)
..()
if(GAME_STATE_PREGAME) // RUNLEVEL_LOBBY
- ..("START [round_progressing ? "[round(pregame_timeleft)]s" : "(PAUSED)"]")
+ msg = "START [round_progressing ? "[round(pregame_timeleft)]s" : "(PAUSED)"]"
if(GAME_STATE_SETTING_UP) // RUNLEVEL_SETUP
- ..("SETUP")
+ msg = "SETUP"
if(GAME_STATE_PLAYING) // RUNLEVEL_GAME
- ..("GAME")
+ msg = "GAME"
if(GAME_STATE_FINISHED) // RUNLEVEL_POSTGAME
switch(end_game_state)
if(END_GAME_MODE_FINISHED)
- ..("MODE OVER, WAITING")
+ msg = "MODE OVER, WAITING"
if(END_GAME_READY_TO_END)
- ..("ENDGAME PROCESSING")
+ msg = "ENDGAME PROCESSING"
if(END_GAME_ENDING)
- ..("END IN [round(restart_timeleft/10)]s")
+ msg = "END IN [round(restart_timeleft/10)]s"
if(END_GAME_DELAYED)
- ..("END PAUSED")
+ msg = "END PAUSED"
else
- ..("ENDGAME ERROR:[end_game_state]")
+ msg = "ENDGAME ERROR:[end_game_state]"
+ return ..()
/datum/controller/subsystem/ticker/Recover()
flags |= SS_NO_INIT // Don't initialize again
@@ -579,3 +586,5 @@ var/global/datum/controller/subsystem/ticker/ticker
minds = SSticker.minds
random_players = SSticker.random_players
+
+ round_start_time = SSticker.round_start_time
diff --git a/code/controllers/subsystems/timer.dm b/code/controllers/subsystems/timer.dm
index 701307c627..fc43b81fd3 100644
--- a/code/controllers/subsystems/timer.dm
+++ b/code/controllers/subsystems/timer.dm
@@ -34,7 +34,8 @@ SUBSYSTEM_DEF(timer)
bucket_resolution = world.tick_lag
/datum/controller/subsystem/timer/stat_entry(msg)
- ..("B:[bucket_count] P:[length(second_queue)] H:[length(hashes)] C:[length(clienttime_timers)] S:[length(timer_id_dict)]")
+ msg = "B:[bucket_count] P:[length(second_queue)] H:[length(hashes)] C:[length(clienttime_timers)] S:[length(timer_id_dict)]"
+ return ..()
/datum/controller/subsystem/timer/fire(resumed = FALSE)
var/lit = last_invoke_tick
diff --git a/code/controllers/subsystems/transcore_vr.dm b/code/controllers/subsystems/transcore_vr.dm
index d2292c32d8..13a4632b8d 100644
--- a/code/controllers/subsystems/transcore_vr.dm
+++ b/code/controllers/subsystems/transcore_vr.dm
@@ -122,9 +122,8 @@ SUBSYSTEM_DEF(transcore)
if(MC_TICK_CHECK)
return
-/datum/controller/subsystem/transcore/stat_entry()
- var/msg = list()
- msg += "$:{"
+/datum/controller/subsystem/transcore/stat_entry(msg)
+ msg = "$:{"
msg += "IM:[round(cost_implants,1)]|"
msg += "BK:[round(cost_backups,1)]"
msg += "} "
@@ -137,7 +136,7 @@ SUBSYSTEM_DEF(transcore)
msg += "DFB:[default_db.body_scans.len]|"
msg += "DFI:[default_db.implants.len]"
msg += "} "
- ..(jointext(msg, null))
+ return ..()
/datum/controller/subsystem/transcore/Recover()
for(var/key in SStranscore.databases)
diff --git a/code/datums/components/connect_mob_behalf.dm b/code/datums/components/connect_mob_behalf.dm
new file mode 100644
index 0000000000..1c1a8a6523
--- /dev/null
+++ b/code/datums/components/connect_mob_behalf.dm
@@ -0,0 +1,59 @@
+/// This component behaves similar to connect_loc_behalf, but working off clients and mobs instead of loc
+/// To be clear, we hook into a signal on a tracked client's mob
+/// We retain the ability to react to that signal on a seperate listener, which makes this quite powerful
+/datum/component/connect_mob_behalf
+ dupe_mode = COMPONENT_DUPE_UNIQUE
+
+ /// An assoc list of signal -> procpath to register to the mob our client "owns"
+ var/list/connections
+ /// The master client we're working with
+ var/client/tracked
+ /// The mob we're currently tracking
+ var/mob/tracked_mob
+
+/datum/component/connect_mob_behalf/Initialize(client/tracked, list/connections)
+ . = ..()
+ if (!istype(tracked))
+ return COMPONENT_INCOMPATIBLE
+ src.connections = connections
+ src.tracked = tracked
+
+/datum/component/connect_mob_behalf/RegisterWithParent()
+ RegisterSignal(tracked, COMSIG_PARENT_QDELETING, PROC_REF(handle_tracked_qdel))
+ update_signals()
+
+/datum/component/connect_mob_behalf/UnregisterFromParent()
+ unregister_signals()
+ UnregisterSignal(tracked, COMSIG_PARENT_QDELETING)
+
+ tracked = null
+ tracked_mob = null
+
+/datum/component/connect_mob_behalf/proc/handle_tracked_qdel()
+ SIGNAL_HANDLER
+ qdel(src)
+
+/datum/component/connect_mob_behalf/proc/update_signals()
+ unregister_signals()
+ // Yes this is a runtime silencer
+ // We could be in a position where logout is sent to two things, one thing intercepts it, then deletes the client's new mob
+ // It's rare, and the same check in connect_loc_behalf is more fruitful, but it's still worth doing
+ if(QDELETED(tracked?.mob))
+ return
+ tracked_mob = tracked.mob
+ RegisterSignal(tracked_mob, COMSIG_MOB_LOGOUT, PROC_REF(on_logout))
+ for (var/signal in connections)
+ parent.RegisterSignal(tracked_mob, signal, connections[signal])
+
+/datum/component/connect_mob_behalf/proc/unregister_signals()
+ if(isnull(tracked_mob))
+ return
+
+ parent.UnregisterSignal(tracked_mob, connections)
+ UnregisterSignal(tracked_mob, COMSIG_MOB_LOGOUT)
+
+ tracked_mob = null
+
+/datum/component/connect_mob_behalf/proc/on_logout(mob/source)
+ SIGNAL_HANDLER
+ update_signals()
diff --git a/code/datums/mind.dm b/code/datums/mind.dm
index 5c8367c5d9..7b80ed9991 100644
--- a/code/datums/mind.dm
+++ b/code/datums/mind.dm
@@ -88,7 +88,7 @@
if(current) //remove ourself from our old body's mind variable
if(changeling)
current.remove_changeling_powers()
- current.verbs -= /datum/changeling/proc/EvolutionMenu
+ remove_verb(current, /datum/changeling/proc/EvolutionMenu)
current.mind = null
if(new_character.mind) //remove any mind currently in our new body's mind variable
@@ -103,6 +103,9 @@
if(active)
new_character.key = key //now transfer the key to link the client to our new body
+ if(new_character.client)
+ new_character.client.init_verbs() // re-initialize character specific verbs
+
/datum/mind/proc/store_memory(new_text)
memory += "[new_text]
"
@@ -516,7 +519,7 @@
if(!mind.name) mind.name = real_name
mind.current = src
if(player_is_antag(mind))
- src.client.verbs += /client/proc/aooc
+ add_verb(src.client, /client/proc/aooc)
//HUMAN
/mob/living/carbon/human/mind_initialize()
diff --git a/code/game/antagonist/antagonist_add.dm b/code/game/antagonist/antagonist_add.dm
index 2a1e206760..76781e5def 100644
--- a/code/game/antagonist/antagonist_add.dm
+++ b/code/game/antagonist/antagonist_add.dm
@@ -28,16 +28,16 @@
current_antagonists |= player
if(faction_verb && player.current)
- player.current.verbs |= faction_verb
+ add_verb(player.current, faction_verb)
spawn(1 SECOND) //Added a delay so that this should pop up at the bottom and not the top of the text flood the new antag gets.
to_chat(player.current, span_notice("Once you decide on a goal to pursue, you can optionally display it to \
everyone at the end of the shift with the " + span_bold("Set Ambition") + " verb, located in the IC tab. You can change this at any time, \
and it otherwise has no bearing on your round."))
- player.current.verbs |= /mob/living/proc/write_ambition
+ add_verb(player.current, /mob/living/proc/write_ambition)
if(can_speak_aooc)
- player.current.client.verbs += /client/proc/aooc
+ add_verb(player.current.client, /client/proc/aooc)
// Handle only adding a mind and not bothering with gear etc.
if(nonstandard_role_type)
@@ -51,7 +51,7 @@
/datum/antagonist/proc/remove_antagonist(var/datum/mind/player, var/show_message, var/implanted)
if(player.current && faction_verb)
- player.current.verbs -= faction_verb
+ remove_verb(player.current, faction_verb)
if(player in current_antagonists)
to_chat(player.current, span_danger(span_large("You are no longer a [role_text]!")))
current_antagonists -= player
@@ -60,8 +60,8 @@
update_icons_removed(player)
BITSET(player.current.hud_updateflag, SPECIALROLE_HUD)
if(!is_special_character(player))
- player.current.verbs -= /mob/living/proc/write_ambition
- player.current.client.verbs -= /client/proc/aooc
+ remove_verb(player.current, /mob/living/proc/write_ambition)
+ remove_verb(player.current.client, /client/proc/aooc)
player.ambitions = ""
return 1
return 0
diff --git a/code/game/atoms.dm b/code/game/atoms.dm
index 38f066ad7b..55730da2a4 100644
--- a/code/game/atoms.dm
+++ b/code/game/atoms.dm
@@ -247,7 +247,7 @@
// Don't make these call bicon or anything, these are what bicon uses. They need to return an icon.
/atom/proc/examine_icon()
- return icon(icon=src.icon, icon_state=src.icon_state, dir=SOUTH, frame=1, moving=0)
+ return src // 99% of the time just returning src will be sufficient. More complex examine icon things are available where they are needed
// called by mobs when e.g. having the atom as their machine, pulledby, loc (AKA mob being inside the atom) or buckled var set.
// see code/modules/mob/mob_movement.dm for more.
@@ -786,3 +786,33 @@
else if(C)
color = C
return
+
+///Passes Stat Browser Panel clicks to the game and calls client click on an atom
+/atom/Topic(href, list/href_list)
+ . = ..()
+ if(!usr?.client)
+ return
+ var/client/usr_client = usr.client
+ var/list/paramslist = list()
+
+ if(href_list["statpanel_item_click"])
+ switch(href_list["statpanel_item_click"])
+ if("left")
+ paramslist["left"] = "1"
+ if("right")
+ paramslist["right"] = "1"
+ if("middle")
+ paramslist["middle"] = "1"
+ else
+ return
+
+ if(href_list["statpanel_item_shiftclick"])
+ paramslist["shift"] = "1"
+ if(href_list["statpanel_item_ctrlclick"])
+ paramslist["ctrl"] = "1"
+ if(href_list["statpanel_item_altclick"])
+ paramslist["alt"] = "1"
+
+ var/mouseparams = list2params(paramslist)
+ usr_client.Click(src, loc, null, mouseparams)
+ return TRUE
diff --git a/code/game/dna/genes/powers.dm b/code/game/dna/genes/powers.dm
index 5c1120c734..7617682b36 100644
--- a/code/game/dna/genes/powers.dm
+++ b/code/game/dna/genes/powers.dm
@@ -20,7 +20,7 @@
/datum/dna/gene/basic/remoteview/activate(var/mob/M, var/connected, var/flags)
..(M,connected,flags)
- M.verbs += /mob/living/carbon/human/proc/remoteobserve
+ add_verb(M, /mob/living/carbon/human/proc/remoteobserve)
/datum/dna/gene/basic/regenerate
name="Regenerate"
@@ -48,7 +48,7 @@
/datum/dna/gene/basic/remotetalk/activate(var/mob/M, var/connected, var/flags)
..(M,connected,flags)
- M.verbs += /mob/living/carbon/human/proc/remotesay
+ add_verb(M, /mob/living/carbon/human/proc/remotesay)
/datum/dna/gene/basic/morph
name="Morph"
@@ -60,7 +60,7 @@
/datum/dna/gene/basic/morph/activate(var/mob/M)
..(M)
- M.verbs += /mob/living/carbon/human/proc/morph
+ add_verb(M, /mob/living/carbon/human/proc/morph)
/datum/dna/gene/basic/cold_resist
name="Cold Resistance"
diff --git a/code/game/gamemodes/changeling/changeling_powers.dm b/code/game/gamemodes/changeling/changeling_powers.dm
index a8ea905576..de15c8a535 100644
--- a/code/game/gamemodes/changeling/changeling_powers.dm
+++ b/code/game/gamemodes/changeling/changeling_powers.dm
@@ -65,8 +65,8 @@ var/global/list/possible_changeling_IDs = list("Alpha","Beta","Gamma","Delta","E
if(!mind) return
if(!mind.changeling) mind.changeling = new /datum/changeling(gender)
- verbs.Add(/datum/changeling/proc/EvolutionMenu)
- verbs.Add(/mob/proc/changeling_respec)
+ add_verb(src, /datum/changeling/proc/EvolutionMenu)
+ add_verb(src, /mob/proc/changeling_respec)
add_language("Changeling")
var/lesser_form = !ishuman(src)
@@ -85,7 +85,7 @@ var/global/list/possible_changeling_IDs = list("Alpha","Beta","Gamma","Delta","E
if(P.isVerb)
if(lesser_form && !P.allowduringlesserform) continue
if(!(P in src.verbs))
- verbs.Add(P.verbpath)
+ add_verb(src, P.verbpath)
if(P.make_hud_button)
if(!src.ability_master)
src.ability_master = new /obj/screen/movable/ability_master(src)
@@ -113,7 +113,7 @@ var/global/list/possible_changeling_IDs = list("Alpha","Beta","Gamma","Delta","E
if(!mind || !mind.changeling) return
for(var/datum/power/changeling/P in mind.changeling.purchased_powers)
if(P.isVerb)
- verbs.Remove(P.verbpath)
+ remove_verb(src, P.verbpath)
var/obj/screen/ability/verb_based/changeling/C = ability_master.get_ability_by_proc_ref(P.verbpath)
if(C)
ability_master.remove_ability(C)
@@ -235,8 +235,8 @@ var/global/list/possible_changeling_IDs = list("Alpha","Beta","Gamma","Delta","E
changeling.chem_charges -= required_chems
changeling.sting_range = 1
- src.verbs -= verb_path
- spawn(10) src.verbs += verb_path
+ remove_verb(src, verb_path)
+ spawn(10) add_verb(src, verb_path)
to_chat(src, span_notice("We stealthily sting [T]."))
if(!T.mind || !T.mind.changeling) return T //T will be affected by the sting
diff --git a/code/game/gamemodes/changeling/powers/boost_range.dm b/code/game/gamemodes/changeling/powers/boost_range.dm
index 8ffcd8ce35..1b818a1f03 100644
--- a/code/game/gamemodes/changeling/powers/boost_range.dm
+++ b/code/game/gamemodes/changeling/powers/boost_range.dm
@@ -24,8 +24,8 @@
range = range + 3
to_chat(src, span_notice("We can fire our next sting from five squares away."))
changeling.sting_range = range
- src.verbs -= /mob/proc/changeling_boost_range
+ remove_verb(src, /mob/proc/changeling_boost_range)
spawn(5)
- src.verbs += /mob/proc/changeling_boost_range
+ add_verb(src, /mob/proc/changeling_boost_range)
feedback_add_details("changeling_powers","RS")
return 1
diff --git a/code/game/gamemodes/changeling/powers/cryo_sting.dm b/code/game/gamemodes/changeling/powers/cryo_sting.dm
index 3a80b2bbb5..adf6cc0751 100644
--- a/code/game/gamemodes/changeling/powers/cryo_sting.dm
+++ b/code/game/gamemodes/changeling/powers/cryo_sting.dm
@@ -24,8 +24,8 @@
if(T.reagents)
T.reagents.add_reagent("cryotoxin", inject_amount)
feedback_add_details("changeling_powers","CS")
- src.verbs -= /mob/proc/changeling_cryo_sting
+ remove_verb(src, /mob/proc/changeling_cryo_sting)
spawn(3 MINUTES)
to_chat(src, span_notice("Our cryogenic string is ready to be used once more."))
- src.verbs |= /mob/proc/changeling_cryo_sting
+ add_verb(src, /mob/proc/changeling_cryo_sting)
return 1
diff --git a/code/game/gamemodes/changeling/powers/digital_camo.dm b/code/game/gamemodes/changeling/powers/digital_camo.dm
index 70312efcdf..cca4f054ae 100644
--- a/code/game/gamemodes/changeling/powers/digital_camo.dm
+++ b/code/game/gamemodes/changeling/powers/digital_camo.dm
@@ -29,8 +29,8 @@
C.mind.changeling.chem_charges = max(C.mind.changeling.chem_charges - 1, 0)
sleep(40)
- src.verbs -= /mob/proc/changeling_digitalcamo
+ remove_verb(src, /mob/proc/changeling_digitalcamo)
spawn(5)
- src.verbs += /mob/proc/changeling_digitalcamo
+ add_verb(src, /mob/proc/changeling_digitalcamo)
feedback_add_details("changeling_powers","CAM")
return 1
diff --git a/code/game/gamemodes/changeling/powers/fake_death.dm b/code/game/gamemodes/changeling/powers/fake_death.dm
index 696402f37f..45b06c615f 100644
--- a/code/game/gamemodes/changeling/powers/fake_death.dm
+++ b/code/game/gamemodes/changeling/powers/fake_death.dm
@@ -43,7 +43,7 @@
spawn(rand(2 MINUTES, 4 MINUTES))
//The ling will now be able to choose when to revive
- verbs.Add(/mob/proc/changeling_revive)
+ add_verb(src, /mob/proc/changeling_revive)
new /obj/changeling_revive_holder(src)
diff --git a/code/game/gamemodes/changeling/powers/fleshmend.dm b/code/game/gamemodes/changeling/powers/fleshmend.dm
index 743a8202e3..cf4c8d8a2a 100644
--- a/code/game/gamemodes/changeling/powers/fleshmend.dm
+++ b/code/game/gamemodes/changeling/powers/fleshmend.dm
@@ -33,9 +33,9 @@
C.adjustFireLoss(-heal_amount)
sleep(1 SECOND)
- src.verbs -= /mob/proc/changeling_fleshmend
+ remove_verb(src, /mob/proc/changeling_fleshmend)
spawn(50 SECONDS)
to_chat(src, span_notice("Our regeneration has slowed to normal levels."))
- src.verbs += /mob/proc/changeling_fleshmend
+ add_verb(src, /mob/proc/changeling_fleshmend)
feedback_add_details("changeling_powers","FM")
return 1
diff --git a/code/game/gamemodes/changeling/powers/revive.dm b/code/game/gamemodes/changeling/powers/revive.dm
index ebf53d4a1c..d3ebd820c3 100644
--- a/code/game/gamemodes/changeling/powers/revive.dm
+++ b/code/game/gamemodes/changeling/powers/revive.dm
@@ -82,7 +82,7 @@
C.set_stat(CONSCIOUS)
C.forbid_seeing_deadchat = FALSE
C.timeofdeath = null
- verbs.Remove(/mob/proc/changeling_revive)
+ remove_verb(src, /mob/proc/changeling_revive)
// re-add our changeling powers
C.make_changeling()
diff --git a/code/game/gamemodes/changeling/powers/transform.dm b/code/game/gamemodes/changeling/powers/transform.dm
index e94e9393ad..4bf04341ef 100644
--- a/code/game/gamemodes/changeling/powers/transform.dm
+++ b/code/game/gamemodes/changeling/powers/transform.dm
@@ -56,9 +56,9 @@
for(var/datum/modifier/mod in chosen_dna.genMods)
self.modifiers.Add(mod.type)
- src.verbs -= /mob/proc/changeling_transform
+ remove_verb(src, /mob/proc/changeling_transform)
spawn(10)
- src.verbs += /mob/proc/changeling_transform
+ add_verb(src, /mob/proc/changeling_transform)
src.regenerate_icons()
feedback_add_details("changeling_powers","TR")
diff --git a/code/game/gamemodes/events/holidays/Holidays.dm b/code/game/gamemodes/events/holidays/Holidays.dm
index 9b9fe5b086..6b728bef2f 100644
--- a/code/game/gamemodes/events/holidays/Holidays.dm
+++ b/code/game/gamemodes/events/holidays/Holidays.dm
@@ -238,7 +238,7 @@ var/global/list/Holiday = list() //Holidays are lists now, so we can have more t
//Allows GA and GM to set the Holiday variable
/client/proc/Set_Holiday()
- set name = ".Set Holiday"
+ set name = "Set Holiday"
set category = "Fun"
set desc = "Force-set the Holiday variable to make the game think it's a certain day."
if(!check_rights(R_SERVER)) return
diff --git a/code/game/gamemodes/malfunction/malf_hardware.dm b/code/game/gamemodes/malfunction/malf_hardware.dm
index 526327664d..a0aa1ec7b6 100644
--- a/code/game/gamemodes/malfunction/malf_hardware.dm
+++ b/code/game/gamemodes/malfunction/malf_hardware.dm
@@ -8,7 +8,7 @@
if(owner && istype(owner))
owner.hardware = src
if(driver)
- owner.verbs += driver
+ add_verb(owner, driver)
/datum/malf_hardware/proc/get_examine_desc()
return "It has some sort of hardware attached to its core"
diff --git a/code/game/gamemodes/malfunction/malf_research.dm b/code/game/gamemodes/malfunction/malf_research.dm
index 37475a0a41..5237d6db1a 100644
--- a/code/game/gamemodes/malfunction/malf_research.dm
+++ b/code/game/gamemodes/malfunction/malf_research.dm
@@ -32,7 +32,7 @@
if(!focus)
return
to_chat(owner, "Research Completed: [focus.name]")
- owner.verbs.Add(focus.ability)
+ add_verb(owner, focus.ability)
available_abilities -= focus
if(focus.next)
available_abilities += focus.next
@@ -62,8 +62,3 @@
focus.process(cpu_gained)
if(focus.unlocked)
finish_research()
-
-
-
-
-
diff --git a/code/game/gamemodes/malfunction/newmalf_ability_trees/tree_networking.dm b/code/game/gamemodes/malfunction/newmalf_ability_trees/tree_networking.dm
index cbf305302d..65a86da317 100644
--- a/code/game/gamemodes/malfunction/newmalf_ability_trees/tree_networking.dm
+++ b/code/game/gamemodes/malfunction/newmalf_ability_trees/tree_networking.dm
@@ -203,7 +203,7 @@
user.hack_can_fail = 0
user.hacking = 0
user.system_override = 2
- user.verbs += new/datum/game_mode/malfunction/verb/ai_destroy_station()
+ add_verb(user, new /datum/game_mode/malfunction/verb/ai_destroy_station())
// END ABILITY VERBS
diff --git a/code/game/gamemodes/sandbox/h_sandbox.dm b/code/game/gamemodes/sandbox/h_sandbox.dm
index 2dc568aec3..e8cde4b59d 100644
--- a/code/game/gamemodes/sandbox/h_sandbox.dm
+++ b/code/game/gamemodes/sandbox/h_sandbox.dm
@@ -24,7 +24,7 @@ mob
sandbox.owner = src.ckey
if(src.client.holder)
sandbox.admin = 1
- verbs += new/mob/proc/sandbox_panel
+ add_verb(src, /mob/proc/sandbox_panel)
sandbox_panel()
if(sandbox)
sandbox.update()
diff --git a/code/game/gamemodes/technomancer/core_obj.dm b/code/game/gamemodes/technomancer/core_obj.dm
index 0c7c1ea13f..354cceeb92 100644
--- a/code/game/gamemodes/technomancer/core_obj.dm
+++ b/code/game/gamemodes/technomancer/core_obj.dm
@@ -160,23 +160,24 @@
/obj/spellbutton/DblClick()
return Click()
-/mob/living/carbon/human/Stat()
+/mob/living/carbon/human/get_status_tab_items()
. = ..()
if(. && istype(back,/obj/item/technomancer_core))
var/obj/item/technomancer_core/core = back
- setup_technomancer_stat(core)
+ . += setup_technomancer_stat(core)
/mob/living/carbon/human/proc/setup_technomancer_stat(var/obj/item/technomancer_core/core)
- if(core && statpanel("Spell Core"))
+ . = list()
+ if(core)
var/charge_status = "[core.energy]/[core.max_energy] ([round( (core.energy / core.max_energy) * 100)]%) \
([round(core.energy_delta)]/s)"
var/instability_delta = instability - last_instability
var/instability_status = "[src.instability] ([round(instability_delta, 0.1)]/s)"
- stat("Core charge", charge_status)
- stat("User instability", instability_status)
+ . += "Core charge: [charge_status]"
+ . += "User instability: [instability_status]"
for(var/obj/spellbutton/button in core.spells)
- stat(button)
+ . += button
/obj/item/technomancer_core/proc/add_spell(var/path, var/new_name, var/ability_icon_state)
if(!path || !ispath(path))
diff --git a/code/game/machinery/computer/computer.dm b/code/game/machinery/computer/computer.dm
index 5d250853c4..1d43173d5a 100644
--- a/code/game/machinery/computer/computer.dm
+++ b/code/game/machinery/computer/computer.dm
@@ -49,12 +49,12 @@
return
if (prob(50))
for(var/x in verbs)
- verbs -= x
+ src.verbs -= x
set_broken()
if(3.0)
if (prob(25))
for(var/x in verbs)
- verbs -= x
+ src.verbs -= x
set_broken()
else
return
diff --git a/code/game/machinery/virtual_reality/vr_console.dm b/code/game/machinery/virtual_reality/vr_console.dm
index e62604f5e6..d61472742d 100644
--- a/code/game/machinery/virtual_reality/vr_console.dm
+++ b/code/game/machinery/virtual_reality/vr_console.dm
@@ -257,7 +257,7 @@
//Yes, I am using a aheal just so your markings transfer over, I could not get .prefs.copy_to working. This is very stupid, and I can't be assed to rewrite this. Too bad!
avatar.revive()
avatar.revive()
- avatar.verbs += /mob/living/carbon/human/proc/exit_vr //ahealing removes the prommie verbs and the VR verbs, giving it back
+ add_verb(avatar, /mob/living/carbon/human/proc/exit_vr) //ahealing removes the prommie verbs and the VR verbs, giving it back
avatar.Sleeping(1)
// Prompt for username after they've enterred the body.
diff --git a/code/game/mecha/mecha.dm b/code/game/mecha/mecha.dm
index f51cb68083..b709eeed93 100644
--- a/code/game/mecha/mecha.dm
+++ b/code/game/mecha/mecha.dm
@@ -423,10 +423,10 @@
////////////////////////
/obj/mecha/proc/removeVerb(verb_path)
- verbs -= verb_path
+ src.verbs -= verb_path
/obj/mecha/proc/addVerb(verb_path)
- verbs += verb_path
+ src.verbs += verb_path
/obj/mecha/proc/add_airtank()
internal_tank = new /obj/machinery/portable_atmospherics/canister/air(src)
diff --git a/code/game/objects/effects/decals/Cleanable/humans.dm b/code/game/objects/effects/decals/Cleanable/humans.dm
index b85714049b..18660273f7 100644
--- a/code/game/objects/effects/decals/Cleanable/humans.dm
+++ b/code/game/objects/effects/decals/Cleanable/humans.dm
@@ -135,7 +135,7 @@ var/global/list/image/splatter_cache=list()
user.bloody_hands += taken
user.hand_blood_color = basecolor
user.update_inv_gloves(1)
- user.verbs += /mob/living/carbon/human/proc/bloody_doodle
+ add_verb(user, /mob/living/carbon/human/proc/bloody_doodle)
/obj/effect/decal/cleanable/blood/splatter
random_icon_states = list("mgibbl1", "mgibbl2", "mgibbl3", "mgibbl4", "mgibbl5")
diff --git a/code/game/objects/items/devices/communicator/integrated.dm b/code/game/objects/items/devices/communicator/integrated.dm
index ae7a2b7873..41990e30f2 100644
--- a/code/game/objects/items/devices/communicator/integrated.dm
+++ b/code/game/objects/items/devices/communicator/integrated.dm
@@ -20,7 +20,7 @@
// Parameters: None
// Description: Lets synths use their communicators without hands.
/obj/item/communicator/integrated/verb/activate()
- set category = "AI IM"
+ set category = "Abilities.AI_IM"
set name = "Use Communicator"
set desc = "Utilizes your built-in communicator."
set src in usr
@@ -29,4 +29,4 @@
to_chat(usr, "You can't do that because you are dead!")
return
- src.attack_self(usr)
\ No newline at end of file
+ src.attack_self(usr)
diff --git a/code/game/objects/items/robot/robot_upgrades.dm b/code/game/objects/items/robot/robot_upgrades.dm
index ed8f10ea8c..3fb0b42893 100644
--- a/code/game/objects/items/robot/robot_upgrades.dm
+++ b/code/game/objects/items/robot/robot_upgrades.dm
@@ -119,7 +119,7 @@
to_chat(usr, "It'd be unwise to plug another vtec module in!")
return 0
- R.verbs += /mob/living/silicon/robot/proc/toggle_vtec
+ add_verb(R, /mob/living/silicon/robot/proc/toggle_vtec)
R.vtec_active = TRUE
R.hud_used.toggle_vtec_control()
return 1
@@ -139,7 +139,7 @@
to_chat(usr, "There's no space for another size alteration module!")
return 0
- R.verbs += /mob/living/proc/set_size
+ add_verb(R, /mob/living/proc/set_size)
return 1
/obj/item/borg/upgrade/basic/syndicate
diff --git a/code/game/objects/items/weapons/implants/implantreagent_vr.dm b/code/game/objects/items/weapons/implants/implantreagent_vr.dm
index 39e693b457..2188e08ff1 100644
--- a/code/game/objects/items/weapons/implants/implantreagent_vr.dm
+++ b/code/game/objects/items/weapons/implants/implantreagent_vr.dm
@@ -47,7 +47,7 @@
else
return
else
- imp_in.verbs -= assigned_proc
+ remove_verb(imp_in, assigned_proc)
return
if(reagents)
diff --git a/code/game/objects/items/weapons/traps_vr.dm b/code/game/objects/items/weapons/traps_vr.dm
index 6940135d82..07530e8361 100644
--- a/code/game/objects/items/weapons/traps_vr.dm
+++ b/code/game/objects/items/weapons/traps_vr.dm
@@ -8,11 +8,11 @@
if(ishuman(src.loc))
var/mob/living/carbon/human/H = src.loc
if(H.wear_mask == src)
- H.verbs |= /mob/living/proc/shred_limb_temp
+ add_verb(H, /mob/living/proc/shred_limb_temp)
else
- H.verbs -= /mob/living/proc/shred_limb_temp
+ remove_verb(H, /mob/living/proc/shred_limb_temp)
..()
/obj/item/beartrap/dropped(var/mob/user)
- user.verbs -= /mob/living/proc/shred_limb_temp
- ..()
\ No newline at end of file
+ remove_verb(user, /mob/living/proc/shred_limb_temp)
+ ..()
diff --git a/code/game/objects/items_vr.dm b/code/game/objects/items_vr.dm
index 4b8dbcaae5..c2bd92cbea 100644
--- a/code/game/objects/items_vr.dm
+++ b/code/game/objects/items_vr.dm
@@ -23,5 +23,5 @@
new_voice.real_name = "[new_voice.real_name]" //We still know their real name though!
possessed_voice.Add(new_voice)
listening_objects |= src
- new_voice.verbs -= /mob/living/voice/verb/change_name //No changing your name! Bad!
- new_voice.verbs -= /mob/living/voice/verb/hang_up //Also you can't hang up. You are the item!
\ No newline at end of file
+ remove_verb(new_voice, /mob/living/voice/verb/change_name) //No changing your name! Bad!
+ remove_verb(new_voice, /mob/living/voice/verb/hang_up) //Also you can't hang up. You are the item!
diff --git a/code/game/vehicles/vehicle.dm b/code/game/vehicles/vehicle.dm
index 729cadb2c4..1ce4a71c24 100644
--- a/code/game/vehicles/vehicle.dm
+++ b/code/game/vehicles/vehicle.dm
@@ -69,10 +69,10 @@
/obj/vehicle/proc/removeVerb(verb_path)
- verbs -= verb_path
+ src.verbs -= verb_path
/obj/vehicle/proc/addVerb(verb_path)
- verbs += verb_path
+ src.verbs += verb_path
/obj/vehicle/proc/add_cell(var/obj/item/cell/C=null)
if(C)
diff --git a/code/modules/admin/admin_verb_lists.dm b/code/modules/admin/admin_verb_lists.dm
index a39fc3b102..c0c031d244 100644
--- a/code/modules/admin/admin_verb_lists.dm
+++ b/code/modules/admin/admin_verb_lists.dm
@@ -13,6 +13,7 @@ var/list/admin_verbs_default = list(
// /client/proc/cmd_mod_say,
// /client/proc/deadchat //toggles deadchat on/off,
// /client/proc/toggle_ahelp_sound,
+ /client/proc/debugstatpanel,
)
var/list/admin_verbs_admin = list(
@@ -507,27 +508,27 @@ var/list/admin_verbs_event_manager = list(
/client/proc/add_admin_verbs()
if(holder)
- verbs += admin_verbs_default
- if(holder.rights & R_BUILDMODE) verbs += /client/proc/togglebuildmodeself
- if(holder.rights & R_ADMIN) verbs += admin_verbs_admin
- if(holder.rights & R_BAN) verbs += admin_verbs_ban
- if(holder.rights & R_FUN) verbs += admin_verbs_fun
- if(holder.rights & R_SERVER) verbs += admin_verbs_server
+ add_verb(src, admin_verbs_default)
+ if(holder.rights & R_BUILDMODE) add_verb(src, /client/proc/togglebuildmodeself)
+ if(holder.rights & R_ADMIN) add_verb(src, admin_verbs_admin)
+ if(holder.rights & R_BAN) add_verb(src, admin_verbs_ban)
+ if(holder.rights & R_FUN) add_verb(src, admin_verbs_fun)
+ if(holder.rights & R_SERVER) add_verb(src, admin_verbs_server)
if(holder.rights & R_DEBUG)
- verbs += admin_verbs_debug
+ add_verb(src, admin_verbs_debug)
if(config.debugparanoid && !(holder.rights & R_ADMIN))
- verbs.Remove(admin_verbs_paranoid_debug) //Right now it's just callproc but we can easily add others later on.
- if(holder.rights & R_POSSESS) verbs += admin_verbs_possess
- if(holder.rights & R_PERMISSIONS) verbs += admin_verbs_permissions
- if(holder.rights & R_STEALTH) verbs += /client/proc/stealth
- if(holder.rights & R_REJUVINATE) verbs += admin_verbs_rejuv
- if(holder.rights & R_SOUNDS) verbs += admin_verbs_sounds
- if(holder.rights & R_SPAWN) verbs += admin_verbs_spawn
- if(holder.rights & R_MOD) verbs += admin_verbs_mod
- if(holder.rights & R_EVENT) verbs += admin_verbs_event_manager
+ remove_verb(src, admin_verbs_paranoid_debug) //Right now it's just callproc but we can easily add others later on.
+ if(holder.rights & R_POSSESS) add_verb(src, admin_verbs_possess)
+ if(holder.rights & R_PERMISSIONS) add_verb(src, admin_verbs_permissions)
+ if(holder.rights & R_STEALTH) add_verb(src, /client/proc/stealth)
+ if(holder.rights & R_REJUVINATE) add_verb(src, admin_verbs_rejuv)
+ if(holder.rights & R_SOUNDS) add_verb(src, admin_verbs_sounds)
+ if(holder.rights & R_SPAWN) add_verb(src, admin_verbs_spawn)
+ if(holder.rights & R_MOD) add_verb(src, admin_verbs_mod)
+ if(holder.rights & R_EVENT) add_verb(src, admin_verbs_event_manager)
/client/proc/remove_admin_verbs()
- verbs.Remove(
+ remove_verb(src, list(
admin_verbs_default,
/client/proc/togglebuildmodeself,
admin_verbs_admin,
@@ -542,4 +543,4 @@ var/list/admin_verbs_event_manager = list(
admin_verbs_sounds,
admin_verbs_spawn,
debug_verbs
- )
+ ))
diff --git a/code/modules/admin/admin_verb_lists_vr.dm b/code/modules/admin/admin_verb_lists_vr.dm
index 3add1b7408..4ab7d8c6e6 100644
--- a/code/modules/admin/admin_verb_lists_vr.dm
+++ b/code/modules/admin/admin_verb_lists_vr.dm
@@ -18,6 +18,7 @@ var/list/admin_verbs_default = list(
// /client/proc/cmd_mod_say,
// /client/proc/deadchat //toggles deadchat on/off,
// /client/proc/toggle_ahelp_sound,
+ /client/proc/debugstatpanel,
)
var/list/admin_verbs_admin = list(
@@ -568,27 +569,27 @@ var/list/admin_verbs_event_manager = list(
/client/proc/add_admin_verbs()
if(holder)
- verbs += admin_verbs_default
- if(holder.rights & R_BUILDMODE) verbs += /client/proc/togglebuildmodeself
- if(holder.rights & R_ADMIN) verbs += admin_verbs_admin
- if(holder.rights & R_BAN) verbs += admin_verbs_ban
- if(holder.rights & R_FUN) verbs += admin_verbs_fun
- if(holder.rights & R_SERVER) verbs += admin_verbs_server
+ add_verb(src, admin_verbs_default)
+ if(holder.rights & R_BUILDMODE) add_verb(src, /client/proc/togglebuildmodeself)
+ if(holder.rights & R_ADMIN) add_verb(src, admin_verbs_admin)
+ if(holder.rights & R_BAN) add_verb(src, admin_verbs_ban)
+ if(holder.rights & R_FUN) add_verb(src, admin_verbs_fun)
+ if(holder.rights & R_SERVER) add_verb(src, admin_verbs_server)
if(holder.rights & R_DEBUG)
- verbs += admin_verbs_debug
+ add_verb(src, admin_verbs_debug)
if(config.debugparanoid && !(holder.rights & R_ADMIN))
- verbs.Remove(admin_verbs_paranoid_debug) //Right now it's just callproc but we can easily add others later on.
- if(holder.rights & R_POSSESS) verbs += admin_verbs_possess
- if(holder.rights & R_PERMISSIONS) verbs += admin_verbs_permissions
- if(holder.rights & R_STEALTH) verbs += /client/proc/stealth
- if(holder.rights & R_REJUVINATE) verbs += admin_verbs_rejuv
- if(holder.rights & R_SOUNDS) verbs += admin_verbs_sounds
- if(holder.rights & R_SPAWN) verbs += admin_verbs_spawn
- if(holder.rights & R_MOD) verbs += admin_verbs_mod
- if(holder.rights & R_EVENT) verbs += admin_verbs_event_manager
+ remove_verb(src, admin_verbs_paranoid_debug) //Right now it's just callproc but we can easily add others later on.
+ if(holder.rights & R_POSSESS) add_verb(src, admin_verbs_possess)
+ if(holder.rights & R_PERMISSIONS) add_verb(src, admin_verbs_permissions)
+ if(holder.rights & R_STEALTH) add_verb(src, /client/proc/stealth)
+ if(holder.rights & R_REJUVINATE) add_verb(src, admin_verbs_rejuv)
+ if(holder.rights & R_SOUNDS) add_verb(src, admin_verbs_sounds)
+ if(holder.rights & R_SPAWN) add_verb(src, admin_verbs_spawn)
+ if(holder.rights & R_MOD) add_verb(src, admin_verbs_mod)
+ if(holder.rights & R_EVENT) add_verb(src, admin_verbs_event_manager)
/client/proc/remove_admin_verbs()
- verbs.Remove(
+ remove_verb(src, list(
admin_verbs_default,
/client/proc/togglebuildmodeself,
admin_verbs_admin,
@@ -603,4 +604,4 @@ var/list/admin_verbs_event_manager = list(
admin_verbs_sounds,
admin_verbs_spawn,
debug_verbs
- )
+ ))
diff --git a/code/modules/admin/admin_verbs.dm b/code/modules/admin/admin_verbs.dm
index 659905aac7..45eb00e5f9 100644
--- a/code/modules/admin/admin_verbs.dm
+++ b/code/modules/admin/admin_verbs.dm
@@ -2,8 +2,8 @@
set name = "Adminverbs - Hide Most"
set category = "Admin"
- verbs.Remove(/client/proc/hide_most_verbs, admin_verbs_hideable)
- verbs += /client/proc/show_verbs
+ remove_verb(src, list(/client/proc/hide_most_verbs, admin_verbs_hideable))
+ add_verb(src, /client/proc/show_verbs)
to_chat(src, span_filter_system(span_interface("Most of your adminverbs have been hidden.")))
feedback_add_details("admin_verb","HMV") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
@@ -14,7 +14,7 @@
set category = "Admin"
remove_admin_verbs()
- verbs += /client/proc/show_verbs
+ add_verb(src, /client/proc/show_verbs)
to_chat(src, span_filter_system(span_interface("Almost all of your adminverbs have been hidden.")))
feedback_add_details("admin_verb","TAVVH") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
@@ -24,7 +24,7 @@
set name = "Adminverbs - Show"
set category = "Admin"
- verbs -= /client/proc/show_verbs
+ remove_verb(src, /client/proc/show_verbs)
add_admin_verbs()
to_chat(src, span_filter_adminlog(span_interface("All of your adminverbs are now visible.")))
@@ -32,7 +32,7 @@
/client/proc/admin_ghost()
- set category = "Admin"
+ set category = "Admin.Game"
set name = "Aghost"
if(!holder) return
@@ -74,6 +74,7 @@
else
ghost = body.ghostize(1)
ghost.admin_ghosted = 1
+ init_verbs()
if(body)
body.teleop = ghost
if(!body.key)
@@ -82,7 +83,7 @@
/client/proc/invisimin()
set name = "Invisimin"
- set category = "Admin"
+ set category = "Admin.Game"
set desc = "Toggles ghost-like invisibility (Don't abuse this)"
if(holder && mob)
if(mob.invisibility == INVISIBILITY_OBSERVER)
@@ -144,7 +145,7 @@
/client/proc/game_panel()
set name = "Game Panel"
- set category = "Admin"
+ set category = "Admin.Game"
if(holder)
holder.Game()
feedback_add_details("admin_verb","GP") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
@@ -255,7 +256,7 @@
#undef AUTOBANTIME
/client/proc/drop_bomb() // Some admin dickery that can probably be done better -- TLE
- set category = "Special Verbs"
+ set category = "Special Verbs.Fun"
set name = "Drop Bomb"
set desc = "Cause an explosion of varying strength at your location."
@@ -338,7 +339,7 @@
log_and_message_admins("has given [key_name(L)] the modifer [new_modifier_type], with a duration of [duration ? "[duration / 600] minutes" : "forever"].")
/client/proc/make_sound(var/obj/O in world) // -- TLE
- set category = "Special Verbs"
+ set category = "Special Verbs.Events"
set name = "Make Sound"
set desc = "Display a message to everyone who can hear the target"
if(O)
@@ -353,13 +354,13 @@
/client/proc/togglebuildmodeself()
set name = "Toggle Build Mode Self"
- set category = "Special Verbs"
+ set category = "Special Verbs.Events"
if(src.mob)
togglebuildmode(src.mob)
feedback_add_details("admin_verb","TBMS") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
/client/proc/object_talk(var/msg as text) // -- TLE
- set category = "Special Verbs"
+ set category = "Special Verbs.Events"
set name = "oSay"
set desc = "Display a message to everyone who can hear the target"
if(mob.control_object)
@@ -388,7 +389,7 @@
log_admin("[src] re-admined themself.")
message_admins("[src] re-admined themself.", 1)
to_chat(src, span_filter_system(span_interface("You now have the keys to control the planet, or at least a small space station")))
- verbs -= /client/proc/readmin_self
+ remove_verb(src, /client/proc/readmin_self)
/client/proc/deadmin_self()
set name = "De-admin self"
@@ -400,7 +401,7 @@
message_admins("[src] deadmined themself.", 1)
deadmin()
to_chat(src, span_filter_system(span_interface("You are now a normal player.")))
- verbs |= /client/proc/readmin_self
+ add_verb(src, /client/proc/readmin_self)
feedback_add_details("admin_verb","DAS") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
/client/proc/toggle_log_hrefs()
@@ -413,7 +414,7 @@
/client/proc/check_ai_laws()
set name = "Check AI Laws"
- set category = "Admin"
+ set category = "Admin.Game"
if(holder)
src.holder.output_ai_laws()
@@ -449,7 +450,7 @@
/client/proc/change_security_level()
set name = "Set security level"
set desc = "Sets the station security level"
- set category = "Admin"
+ set category = "Admin.Events"
if(!check_rights(R_ADMIN|R_EVENT)) return
var/sec_level = tgui_input_list(usr, "It's currently code [get_security_level()].", "Select Security Level", (list("green","yellow","violet","orange","blue","red","delta")-get_security_level()))
@@ -559,3 +560,9 @@
feedback_add_details("admin_verb","GS") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
log_admin("[key_name(usr)] gave [key_name(T)] the spell [S].")
message_admins(span_blue("[key_name_admin(usr)] gave [key_name(T)] the spell [S]."), 1)
+
+/client/proc/debugstatpanel()
+ set name = "Debug Stat Panel"
+ set category = "Debug"
+
+ src.stat_panel.send_message("create_debug")
diff --git a/code/modules/admin/holder2.dm b/code/modules/admin/holder2.dm
index 3f90050b57..9c8f05ceea 100644
--- a/code/modules/admin/holder2.dm
+++ b/code/modules/admin/holder2.dm
@@ -37,12 +37,14 @@ var/list/admin_datums = list()
owner = C
owner.holder = src
owner.add_admin_verbs() //TODO
+ owner.init_verbs() //re-initialize the verb list
GLOB.admins |= C
/datum/admins/proc/disassociate()
if(owner)
GLOB.admins -= owner
owner.remove_admin_verbs()
+ owner.init_verbs() //re-initialize the verb list
owner.deadmin_holder = owner.holder
owner.holder = null
diff --git a/code/modules/admin/player_effects.dm b/code/modules/admin/player_effects.dm
index d3141861d9..e723123453 100644
--- a/code/modules/admin/player_effects.dm
+++ b/code/modules/admin/player_effects.dm
@@ -494,7 +494,7 @@
var/mob/living/Tar = target
if(!istype(Tar))
return
- Tar.verbs |= /mob/living/proc/ventcrawl
+ add_verb(Tar, /mob/living/proc/ventcrawl)
if("darksight")
var/mob/living/carbon/human/Tar = target
@@ -509,26 +509,26 @@
var/mob/living/carbon/human/Tar = target
if(!istype(Tar))
return
- Tar.verbs |= /mob/living/carbon/human/proc/enter_cocoon
+ add_verb(Tar, /mob/living/carbon/human/proc/enter_cocoon)
if("transformation")
var/mob/living/carbon/human/Tar = target
if(!istype(Tar))
return
- Tar.verbs |= /mob/living/carbon/human/proc/shapeshifter_select_hair
- Tar.verbs |= /mob/living/carbon/human/proc/shapeshifter_select_hair_colors
- Tar.verbs |= /mob/living/carbon/human/proc/shapeshifter_select_gender
- Tar.verbs |= /mob/living/carbon/human/proc/shapeshifter_select_wings
- Tar.verbs |= /mob/living/carbon/human/proc/shapeshifter_select_tail
- Tar.verbs |= /mob/living/carbon/human/proc/shapeshifter_select_ears
- Tar.verbs |= /mob/living/carbon/human/proc/lleill_select_shape //designed for non-shapeshifter mobs
- Tar.verbs |= /mob/living/carbon/human/proc/lleill_select_colour
+ add_verb(Tar, /mob/living/carbon/human/proc/shapeshifter_select_hair)
+ add_verb(Tar, /mob/living/carbon/human/proc/shapeshifter_select_hair_colors)
+ add_verb(Tar, /mob/living/carbon/human/proc/shapeshifter_select_gender)
+ add_verb(Tar, /mob/living/carbon/human/proc/shapeshifter_select_wings)
+ add_verb(Tar, /mob/living/carbon/human/proc/shapeshifter_select_tail)
+ add_verb(Tar, /mob/living/carbon/human/proc/shapeshifter_select_ears)
+ add_verb(Tar, /mob/living/carbon/human/proc/lleill_select_shape) //designed for non-shapeshifter mobs
+ add_verb(Tar, /mob/living/carbon/human/proc/lleill_select_colour)
if("set_size")
var/mob/living/Tar = target
if(!istype(Tar))
return
- Tar.verbs |= /mob/living/proc/set_size
+ add_verb(Tar, /mob/living/proc/set_size)
if("lleill_energy")
var/mob/living/carbon/human/Tar = target
@@ -543,44 +543,44 @@
var/mob/living/carbon/human/Tar = target
if(!istype(Tar))
return
- Tar.verbs |= /mob/living/carbon/human/proc/lleill_invisibility
+ add_verb(Tar, /mob/living/carbon/human/proc/lleill_invisibility)
if("beast_form")
var/mob/living/carbon/human/Tar = target
if(!istype(Tar))
return
- Tar.verbs |= /mob/living/carbon/human/proc/lleill_beast_form
+ add_verb(Tar, /mob/living/carbon/human/proc/lleill_beast_form)
if("lleill_transmute")
var/mob/living/carbon/human/Tar = target
if(!istype(Tar))
return
- Tar.verbs |= /mob/living/carbon/human/proc/lleill_transmute
+ add_verb(Tar, /mob/living/carbon/human/proc/lleill_transmute)
if("lleill_alchemy")
var/mob/living/carbon/human/Tar = target
if(!istype(Tar))
return
- Tar.verbs |= /mob/living/carbon/human/proc/lleill_alchemy
+ add_verb(Tar, /mob/living/carbon/human/proc/lleill_alchemy)
if("lleill_drain")
var/mob/living/carbon/human/Tar = target
if(!istype(Tar))
return
- Tar.verbs |= /mob/living/carbon/human/proc/lleill_contact
+ add_verb(Tar, /mob/living/carbon/human/proc/lleill_contact)
if("brutal_pred")
var/mob/living/Tar = target
if(!istype(Tar))
return
- Tar.verbs |= /mob/living/proc/shred_limb
+ add_verb(Tar, /mob/living/proc/shred_limb)
if("trash_eater")
var/mob/living/carbon/human/Tar = target
if(!istype(Tar))
return
- Tar.verbs |= /mob/living/proc/eat_trash
- Tar.verbs |= /mob/living/proc/toggle_trash_catching
+ add_verb(Tar, /mob/living/proc/eat_trash)
+ add_verb(Tar, /mob/living/proc/toggle_trash_catching)
////////INVENTORY//////////////
diff --git a/code/modules/admin/verbs/SDQL2/SDQL_2.dm b/code/modules/admin/verbs/SDQL2/SDQL_2.dm
index 651f34dd53..d2a59f7af1 100644
--- a/code/modules/admin/verbs/SDQL2/SDQL_2.dm
+++ b/code/modules/admin/verbs/SDQL2/SDQL_2.dm
@@ -384,11 +384,13 @@ GLOBAL_DATUM_INIT(sdql2_vv_statobj, /obj/effect/statclick/SDQL2_VV_all, new(null
delete_click = new(null, "INITIALIZING", src)
if(!action_click)
action_click = new(null, "INITIALIZNG", src)
- stat("[id] ", delete_click.update("DELETE QUERY | STATE : [text_state()] | ALL/ELIG/FIN \
+ var/list/L = list()
+ L[++L.len] = list("[id] ", "[delete_click.update("DELETE QUERY | STATE : [text_state()] | ALL/ELIG/FIN \
[islist(obj_count_all)? length(obj_count_all) : (isnull(obj_count_all)? "0" : obj_count_all)]/\
[islist(obj_count_eligible)? length(obj_count_eligible) : (isnull(obj_count_eligible)? "0" : obj_count_eligible)]/\
- [islist(obj_count_finished)? length(obj_count_finished) : (isnull(obj_count_finished)? "0" : obj_count_finished)] - [get_query_text()]"))
- stat(" ", action_click.update("[SDQL2_IS_RUNNING? "HALT" : "RUN"]"))
+ [islist(obj_count_finished)? length(obj_count_finished) : (isnull(obj_count_finished)? "0" : obj_count_finished)] - [get_query_text()]")]", REF(delete_click))
+ L[++L.len] = list(" ", "[action_click.update("[SDQL2_IS_RUNNING? "HALT" : "RUN"]")]", REF(action_click))
+ return L
/datum/SDQL2_query/proc/delete_click()
admin_del(usr)
diff --git a/code/modules/admin/verbs/adminhelp.dm b/code/modules/admin/verbs/adminhelp.dm
index a0c8d13712..356e3ecc01 100644
--- a/code/modules/admin/verbs/adminhelp.dm
+++ b/code/modules/admin/verbs/adminhelp.dm
@@ -72,18 +72,23 @@ GLOBAL_DATUM_INIT(ahelp_tickets, /datum/admin_help_tickets, new)
//Tickets statpanel
/datum/admin_help_tickets/proc/stat_entry()
+ SHOULD_CALL_PARENT(TRUE)
+ SHOULD_NOT_SLEEP(TRUE)
+ var/list/L = list()
var/num_disconnected = 0
- stat("== Admin Tickets ==")
- stat("Active Tickets:", astatclick.update("[active_tickets.len]"))
+ L[++L.len] = list("== Admin Tickets ==", "", null, null)
+ L[++L.len] = list("Active Tickets:", "[astatclick.update("[active_tickets.len]")]", null, REF(astatclick))
+ astatclick.update("[active_tickets.len]")
for(var/datum/admin_help/AH as anything in active_tickets)
if(AH.initiator)
- stat("#[AH.id]. [AH.initiator_key_name]:", AH.statclick.update())
+ L[++L.len] = list("#[AH.id]. [AH.initiator_key_name]:", "[AH.statclick.update()]", REF(AH))
else
++num_disconnected
if(num_disconnected)
- stat("Disconnected:", astatclick.update("[num_disconnected]"))
- stat("Closed Tickets:", cstatclick.update("[closed_tickets.len]"))
- stat("Resolved Tickets:", rstatclick.update("[resolved_tickets.len]"))
+ L[++L.len] = list("Disconnected:", "[astatclick.update("[num_disconnected]")]", null, REF(astatclick))
+ L[++L.len] = list("Closed Tickets:", "[cstatclick.update("[closed_tickets.len]")]", null, REF(cstatclick))
+ L[++L.len] = list("Resolved Tickets:", "[rstatclick.update("[resolved_tickets.len]")]", null, REF(rstatclick))
+ return L
//Reassociate still open ticket if one exists
/datum/admin_help_tickets/proc/ClientLogin(client/C)
@@ -119,6 +124,9 @@ GLOBAL_DATUM_INIT(ahelp_tickets, /datum/admin_help_tickets, new)
/obj/effect/statclick/ticket_list/Click()
GLOB.ahelp_tickets.BrowseTickets(current_state)
+//called by admin topic
+/obj/effect/statclick/ticket_list/proc/Action()
+ Click()
//
//TICKET DATUM
//
@@ -606,9 +614,9 @@ GLOBAL_DATUM_INIT(ahelp_tickets, /datum/admin_help_tickets, new)
return
//remove out adminhelp verb temporarily to prevent spamming of admins.
- src.verbs -= /client/verb/adminhelp
+ remove_verb(src, /client/verb/adminhelp)
spawn(1200)
- src.verbs += /client/verb/adminhelp // 2 minute cool-down for adminhelps
+ add_verb(src, /client/verb/adminhelp) // 2 minute cool-down for adminhelps
feedback_add_details("admin_verb","Adminhelp") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
if(current_ticket)
diff --git a/code/modules/admin/verbs/adminhelp_vr.dm b/code/modules/admin/verbs/adminhelp_vr.dm
index 1784e22701..4f694ee1b9 100644
--- a/code/modules/admin/verbs/adminhelp_vr.dm
+++ b/code/modules/admin/verbs/adminhelp_vr.dm
@@ -33,7 +33,7 @@
return
//if they requested spice, then remove spice verb temporarily to prevent spamming
- usr.verbs -= /client/verb/adminspice
+ remove_verb(usr, /client/verb/adminspice)
spawn(10 MINUTES)
if(usr) // In case we left in the 10 minute cooldown
- usr.verbs += /client/verb/adminspice // 10 minute cool-down for spice request
+ add_verb(usr, /client/verb/adminspice) // 10 minute cool-down for spice request
diff --git a/code/modules/admin/verbs/getlogs.dm b/code/modules/admin/verbs/getlogs.dm
index 6d79548df3..236fbef7a6 100644
--- a/code/modules/admin/verbs/getlogs.dm
+++ b/code/modules/admin/verbs/getlogs.dm
@@ -32,7 +32,7 @@
to_chat(src, span_red("Error: giveruntimelog(): Client not found."))
return
- target.verbs |= /client/proc/getruntimelog
+ add_verb(target, /client/proc/getruntimelog)
to_chat(target, span_red("You have been granted access to runtime logs. Please use them responsibly or risk being banned."))
return
diff --git a/code/modules/admin/verbs/mapping.dm b/code/modules/admin/verbs/mapping.dm
index daec7c4c8b..c51b131b8e 100644
--- a/code/modules/admin/verbs/mapping.dm
+++ b/code/modules/admin/verbs/mapping.dm
@@ -172,7 +172,7 @@ var/list/debug_verbs = list (
if(!check_rights(R_DEBUG)) return
- verbs += debug_verbs
+ add_verb(src, debug_verbs)
feedback_add_details("admin_verb","mDV") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
@@ -182,7 +182,7 @@ var/list/debug_verbs = list (
if(!check_rights(R_DEBUG)) return
- verbs -= debug_verbs
+ remove_verb(src, debug_verbs)
feedback_add_details("admin_verb","hDV") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
diff --git a/code/modules/admin/verbs/possess.dm b/code/modules/admin/verbs/possess.dm
index 5e4a3d0ce7..9324583bac 100644
--- a/code/modules/admin/verbs/possess.dm
+++ b/code/modules/admin/verbs/possess.dm
@@ -47,6 +47,6 @@
set desc = "Give this guy possess/release verbs"
set category = "Debug"
set name = "Give Possessing Verbs"
- M.verbs += /proc/possess
- M.verbs += /proc/release
- feedback_add_details("admin_verb","GPV") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
\ No newline at end of file
+ add_verb(M, /proc/possess)
+ add_verb(M, /proc/release)
+ feedback_add_details("admin_verb","GPV") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
diff --git a/code/modules/admin/verbs/randomverbs.dm b/code/modules/admin/verbs/randomverbs.dm
index e1e1c0245a..bcd3bd8958 100644
--- a/code/modules/admin/verbs/randomverbs.dm
+++ b/code/modules/admin/verbs/randomverbs.dm
@@ -324,7 +324,7 @@ Ccomp's first proc.
if(config.antag_hud_allowed)
for(var/mob/observer/dead/g in get_ghosts())
if(!g.client.holder) //Remove the verb from non-admin ghosts
- g.verbs -= /mob/observer/dead/verb/toggle_antagHUD
+ remove_verb(g, /mob/observer/dead/verb/toggle_antagHUD)
if(g.antagHUD)
g.antagHUD = 0 // Disable it on those that have it enabled
g.has_enabled_antagHUD = 2 // We'll allow them to respawn
@@ -335,7 +335,7 @@ Ccomp's first proc.
else
for(var/mob/observer/dead/g in get_ghosts())
if(!g.client.holder) // Add the verb back for all non-admin ghosts
- g.verbs += /mob/observer/dead/verb/toggle_antagHUD
+ add_verb(g, /mob/observer/dead/verb/toggle_antagHUD)
to_chat(g, span_blue("The Administrator has enabled AntagHUD ")) // Notify all observers they can now use AntagHUD
config.antag_hud_allowed = 1
action = "enabled"
diff --git a/code/modules/admin/view_variables/topic.dm b/code/modules/admin/view_variables/topic.dm
index dd33214c1c..fc2b918989 100644
--- a/code/modules/admin/view_variables/topic.dm
+++ b/code/modules/admin/view_variables/topic.dm
@@ -449,7 +449,7 @@
if(!verb || verb == "Cancel")
return
else
- H.verbs += verb
+ add_verb(H, verb)
else if(href_list["remverb"])
if(!check_rights(R_DEBUG)) return
@@ -466,7 +466,7 @@
if(!verb)
return
else
- H.verbs -= verb
+ remove_verb(H, verb)
else if(href_list["addorgan"])
if(!check_rights(R_SPAWN)) return
diff --git a/code/modules/blob2/overmind/overmind.dm b/code/modules/blob2/overmind/overmind.dm
index 7973a8b0b3..993a4126ac 100644
--- a/code/modules/blob2/overmind/overmind.dm
+++ b/code/modules/blob2/overmind/overmind.dm
@@ -70,13 +70,14 @@ var/list/overminds = list()
overminds -= src
return ..()
-/mob/observer/blob/Stat()
- ..()
- if(statpanel("Status"))
- if(blob_core)
- stat(null, "Core Health: [blob_core.integrity]")
- stat(null, "Power Stored: [blob_points]/[max_blob_points]")
- stat(null, "Total Blobs: [GLOB.all_blobs.len]")
+/mob/observer/blob/get_status_tab_items()
+ . = ..()
+ . += ""
+ . += "BLOB STATUS"
+ if(blob_core)
+ . += "Core Health: [blob_core.integrity]"
+ . += "Power Stored: [blob_points]/[max_blob_points]"
+ . += "Total Blobs: [GLOB.all_blobs.len]"
/mob/observer/blob/Move(var/atom/NewLoc, Dir = 0)
if(placed)
diff --git a/code/modules/client/client defines.dm b/code/modules/client/client defines.dm
index 457b6d0fce..155950ae43 100644
--- a/code/modules/client/client defines.dm
+++ b/code/modules/client/client defines.dm
@@ -36,6 +36,8 @@
////////////////
//ADMIN THINGS//
////////////////
+ /// hides the byond verb panel as we use our own custom version
+ show_verb_panel = FALSE
///Contains admin info. Null if client is not an admin.
var/datum/admins/holder = null
var/datum/admins/deadmin_holder = null
@@ -113,6 +115,23 @@
// Runechat messages
var/list/seen_messages
+ /// our current tab
+ var/stat_tab
+
+ /// list of all tabs
+ var/list/panel_tabs = list()
+ /// list of tabs containing spells and abilities
+ var/list/spell_tabs = list()
+ /// list of misc tabs from mob
+ var/list/misc_tabs = list()
+ ///A lazy list of atoms we've examined in the last RECENT_EXAMINE_MAX_WINDOW (default 2) seconds, so that we will call [/atom/proc/examine_more] instead of [/atom/proc/examine] on them when examining
+ var/list/recent_examines
+ ///Our object window datum. It stores info about and handles behavior for the object tab
+ var/datum/object_window_info/obj_window
+
+ var/list/misc_cache = list()
+
+ var/atom/examine_icon //Holder for examine icon, useful for statpanel
//Hide top bars
var/fullscreen = FALSE
diff --git a/code/modules/client/client procs.dm b/code/modules/client/client procs.dm
index 54f210cf67..c0bb68e10b 100644
--- a/code/modules/client/client procs.dm
+++ b/code/modules/client/client procs.dm
@@ -113,6 +113,8 @@
log_and_message_admins("[ckey] failed to register their Discord ID. Their Discord snowflake ID is: [their_id]. Is the database connected?")
return
//VOREStation Add End
+ if(href_list["reload_statbrowser"])
+ stat_panel.reinitialize()
//Logs all hrefs
if(config && config.log_hrefs && href_logfile)
@@ -181,6 +183,10 @@
GLOB.clients += src
GLOB.directory[ckey] = src
+ // Instantiate stat panel
+ stat_panel = new(src, "statbrowser")
+ stat_panel.subscribe(src, .proc/on_stat_panel_message)
+
// Instantiate tgui panel
tgui_say = new(src, "tgui_say")
initialize_commandbar_spy()
@@ -218,6 +224,14 @@
if(prefs)
prefs.selecting_slots = FALSE
+ // Initialize stat panel
+ stat_panel.initialize(
+ inline_html = file2text('html/statbrowser.html'),
+ inline_js = file2text('html/statbrowser.js'),
+ inline_css = file2text('html/statbrowser.css'),
+ )
+ addtimer(CALLBACK(src, PROC_REF(check_panel_loaded)), 30 SECONDS)
+
// Initialize tgui panel
tgui_say.initialize()
tgui_panel.initialize()
@@ -652,3 +666,43 @@
to_chat(src, span_warning("No recorded playtime found!"))
return
to_chat(src, span_info("Your department hours:" + department_hours))
+
+/// compiles a full list of verbs and sends it to the browser
+/client/proc/init_verbs()
+ if(IsAdminAdvancedProcCall())
+ return
+ var/list/verblist = list()
+ panel_tabs.Cut()
+ for(var/thing in (verbs + mob?.verbs))
+ var/procpath/verb_to_init = thing
+ if(!verb_to_init)
+ continue
+ if(verb_to_init.hidden)
+ continue
+ if(!istext(verb_to_init.category))
+ continue
+ panel_tabs |= verb_to_init.category
+ verblist[++verblist.len] = list(verb_to_init.category, verb_to_init.name, verb_to_init.desc)
+ src.stat_panel.send_message("init_verbs", list(panel_tabs = panel_tabs, verblist = verblist))
+
+/client/proc/check_panel_loaded()
+ if(stat_panel && stat_panel.is_ready())
+ return
+ to_chat(src, "Statpanel failed to load, click here to reload the panel. If this does not work, reconnecting will reassign a new panel.")
+
+/**
+ * Handles incoming messages from the stat-panel TGUI.
+ */
+/client/proc/on_stat_panel_message(type, payload)
+ switch(type)
+ if("Update-Verbs")
+ init_verbs()
+ if("Remove-Tabs")
+ panel_tabs -= payload["tab"]
+ if("Send-Tabs")
+ panel_tabs |= payload["tab"]
+ if("Reset-Tabs")
+ panel_tabs = list()
+ if("Set-Tab")
+ stat_tab = payload["tab"]
+ SSstatpanels.immediate_send_stat_data(src)
diff --git a/code/modules/client/verbs/ooc.dm b/code/modules/client/verbs/ooc.dm
index 794ef10472..9f9441be4b 100644
--- a/code/modules/client/verbs/ooc.dm
+++ b/code/modules/client/verbs/ooc.dm
@@ -275,3 +275,9 @@
INVOKE_ASYNC(src, VERB_REF(fit_viewport))
else //Delayed to avoid wingets from Login calls.
addtimer(CALLBACK(src, VERB_REF(fit_viewport), 1 SECONDS))
+
+/client/verb/fix_stat_panel()
+ set name = "Fix Stat Panel"
+ set hidden = TRUE
+
+ init_verbs()
diff --git a/code/modules/clothing/spacesuits/rig/modules/modules.dm b/code/modules/clothing/spacesuits/rig/modules/modules.dm
index 128cc19a54..e42e135049 100644
--- a/code/modules/clothing/spacesuits/rig/modules/modules.dm
+++ b/code/modules/clothing/spacesuits/rig/modules/modules.dm
@@ -234,28 +234,6 @@
/obj/item/rig_module/proc/accepts_item(var/obj/item/input_device)
return 0
-/mob/living/carbon/human/Stat()
- . = ..()
-
- if(. && istype(back,/obj/item/rig))
- var/obj/item/rig/R = back
- SetupStat(R)
-
- else if(. && istype(belt,/obj/item/rig))
- var/obj/item/rig/R = belt
- SetupStat(R)
-
-/mob/proc/SetupStat(var/obj/item/rig/R)
- if(R && !R.canremove && R.installed_modules.len && statpanel("Hardsuit Modules"))
- var/cell_status = R.cell ? "[R.cell.charge]/[R.cell.maxcharge]" : "ERROR"
- stat("Suit charge", cell_status)
- for(var/obj/item/rig_module/module in R.installed_modules)
- {
- for(var/stat_rig_module/SRM in module.stat_modules)
- if(SRM.CanUse())
- stat(SRM.module.interface_name,SRM)
- }
-
/stat_rig_module
parent_type = /atom/movable
var/module_mode = ""
diff --git a/code/modules/clothing/spacesuits/rig/modules/specific/ai_container.dm b/code/modules/clothing/spacesuits/rig/modules/specific/ai_container.dm
index e8fb600238..b65417f3ec 100644
--- a/code/modules/clothing/spacesuits/rig/modules/specific/ai_container.dm
+++ b/code/modules/clothing/spacesuits/rig/modules/specific/ai_container.dm
@@ -46,13 +46,6 @@
else
integrated_ai.get_rig_stats = 0
-/mob/living/Stat()
- . = ..()
- if(. && get_rig_stats)
- var/obj/item/rig/rig = get_rig()
- if(rig)
- SetupStat(rig)
-
/obj/item/rig_module/ai_container/proc/update_verb_holder()
if(!verb_holder)
verb_holder = new(src)
diff --git a/code/modules/examine/examine.dm b/code/modules/examine/examine.dm
index 7131536d73..16f1b305ab 100644
--- a/code/modules/examine/examine.dm
+++ b/code/modules/examine/examine.dm
@@ -5,7 +5,6 @@
This means that this file can be unchecked, along with the other examine files, and can be removed entirely with no effort.
*/
-#define EXAMINE_PANEL_PADDING " "
/atom/
var/description_info = null //Helpful blue text.
@@ -34,7 +33,7 @@
// Quickly adds the boilerplate code to add an image and padding for the image.
/proc/desc_panel_image(var/icon_state)
- return "[bicon(description_icons[icon_state])][EXAMINE_PANEL_PADDING]"
+ return "[icon2html(description_icons[icon_state], usr)] "
/mob/living/get_description_fluff()
if(flavor_text) //Get flavor text for the green text.
@@ -50,50 +49,16 @@
/client/var/description_holders[0]
/client/proc/update_description_holders(atom/A, update_antag_info=0)
+ examine_icon = null
description_holders["info"] = A.get_description_info()
description_holders["fluff"] = A.get_description_fluff()
description_holders["antag"] = (update_antag_info)? A.get_description_antag() : ""
description_holders["interactions"] = A.get_description_interaction()
description_holders["name"] = "[A.name]"
- description_holders["icon"] = "[icon2html(A.examine_icon(),src)]"
+ description_holders["icon"] = A
description_holders["desc"] = A.desc
-/mob/Stat()
- . = ..()
- if(client && statpanel("Examine"))
- var/description_holders = client.description_holders
- stat(null,"[description_holders["icon"]] [description_holders["name"]]") //The name, written in big letters.
- stat(null,"[description_holders["desc"]]") //the default examine text.
-
-
- var/color_i = "#084B8A"
- var/color_f = "#298A08"
- var/color_a = "#8A0808"
-/*
- The infowindow colours are set in code\modules\vchat\js\vchat.js file
- Unfortunately, I cannot think of a way to do this elegantly where there's this central define that we can easily track.
- As of 2023/08/05 13:10, the lightmode colour for vchat tabBackgroundColor is "none", this is also defined in interface\skin.dmf .
- The darkmode colour for vchat tabBackgroundColor is "#272727".
- Since it's possible that one day we'll have option to modify the user's preferred tabBackgroundColor
- I will assume the lightmode colour will be left untouched - therefore, we are checking for none.
-*/
- if(!(winget(src, "infowindow", "background-color") == "none"))
- color_i = "#709ec9d8"
- color_f = "#76d357"
- color_a = "#c94d4d"
-
-
- if(description_holders["info"])
- stat(null,"[description_holders["info"]]") //Blue, informative text.
- if(description_holders["interactions"])
- for(var/line in description_holders["interactions"])
- stat(null, "[line]")
- if(description_holders["fluff"])
- stat(null,"[description_holders["fluff"]]") //Yellow, fluff-related text.
- if(description_holders["antag"])
- stat(null,"[description_holders["antag"]]") //Red, malicious antag-related text
-
//override examinate verb to update description holders when things are examined
//mob verbs are faster than object verbs. See http://www.byond.com/forum/?post=1326139&page=2#comment8198716 for why this isn't atom/verb/examine()
/mob/verb/examinate(atom/A as mob|obj|turf in _validate_atom(A))
@@ -122,6 +87,7 @@
if(client)
var/is_antag = ((mind && mind.special_role) || isobserver(src)) //ghosts don't have minds
client.update_description_holders(A, is_antag)
+ SSstatpanels.set_examine_tab(client)
/mob/verb/mob_examine()
@@ -198,5 +164,3 @@
results = list("You were unable to examine that. Tell a developer!")
to_chat(src, jointext(results, "
"))
update_examine_panel(B)
-
-#undef EXAMINE_PANEL_PADDING
diff --git a/code/modules/mentor/mentor.dm b/code/modules/mentor/mentor.dm
index 66b9597395..f35b79cfbb 100644
--- a/code/modules/mentor/mentor.dm
+++ b/code/modules/mentor/mentor.dm
@@ -36,11 +36,11 @@ var/list/mentor_verbs_default = list(
/client/proc/add_mentor_verbs()
if(mentorholder)
- verbs += mentor_verbs_default
+ add_verb(src, mentor_verbs_default)
/client/proc/remove_mentor_verbs()
if(mentorholder)
- verbs -= mentor_verbs_default
+ remove_verb(src, mentor_verbs_default)
/client/proc/make_mentor()
set category = "Special Verbs"
diff --git a/code/modules/mentor/mentorhelp.dm b/code/modules/mentor/mentorhelp.dm
index 7bf6ef57db..42ebc73116 100644
--- a/code/modules/mentor/mentorhelp.dm
+++ b/code/modules/mentor/mentorhelp.dm
@@ -61,17 +61,22 @@ GLOBAL_DATUM_INIT(mhelp_tickets, /datum/mentor_help_tickets, new)
//Tickets statpanel
/datum/mentor_help_tickets/proc/stat_entry()
+ SHOULD_CALL_PARENT(TRUE)
+ SHOULD_NOT_SLEEP(TRUE)
+ var/list/L = list()
var/num_disconnected = 0
- stat("== Mentor Tickets ==")
- stat("Active Tickets:", astatclick.update("[active_tickets.len]"))
+ L[++L.len] = list("== Mentor Tickets ==", "", null, null)
+ L[++L.len] = list("Active Tickets:", "[astatclick.update("[active_tickets.len]")]", null, REF(astatclick))
+ astatclick.update("[active_tickets.len]")
for(var/datum/mentor_help/MH as anything in active_tickets)
if(MH.initiator)
- stat("#[MH.id]. [MH.initiator_ckey]:", MH.statclick.update())
+ L[++L.len] = list("#[MH.id]. [MH.initiator_ckey]:", "[MH.statclick.update()]", REF(MH))
else
++num_disconnected
if(num_disconnected)
- stat("Disconnected:", astatclick.update("[num_disconnected]"))
- stat("Resolved Tickets:", rstatclick.update("[resolved_tickets.len]"))
+ L[++L.len] = list("Disconnected:", "[astatclick.update("[num_disconnected]")]", null, REF(astatclick))
+ L[++L.len] = list("Resolved Tickets:", "[rstatclick.update("[resolved_tickets.len]")]", null, REF(rstatclick))
+ return L
//Reassociate still open ticket if one exists
/datum/mentor_help_tickets/proc/ClientLogin(client/C)
@@ -439,9 +444,9 @@ GLOBAL_DATUM_INIT(mhelp_tickets, /datum/mentor_help_tickets, new)
"Send to discord?", list("Admin-help!", "Still mentorhelp!", "Cancel"))
if(choice == "Admin-help!")
usr.client.adminhelp(msg)
- src.verbs -= /client/verb/mentorhelp
+ remove_verb(src, /client/verb/mentorhelp)
spawn(1200)
- src.verbs += /client/verb/mentorhelp // 2 minute cd to prevent abusing this to spam admins.
+ add_verb(src, /client/verb/mentorhelp) // 2 minute cd to prevent abusing this to spam admins.
return
else if(!choice || choice == "Cancel")
return
@@ -449,9 +454,9 @@ GLOBAL_DATUM_INIT(mhelp_tickets, /datum/mentor_help_tickets, new)
//remove out adminhelp verb temporarily to prevent spamming of admins.
- src.verbs -= /client/verb/mentorhelp
+ remove_verb(src, /client/verb/mentorhelp)
spawn(600)
- src.verbs += /client/verb/mentorhelp // 1 minute cool-down for mentorhelps
+ add_verb(src, /client/verb/mentorhelp) // 1 minute cool-down for mentorhelps
feedback_add_details("admin_verb","Mentorhelp") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
if(current_mentorhelp)
diff --git a/code/modules/mob/dead/observer/observer.dm b/code/modules/mob/dead/observer/observer.dm
index 9a817a3b22..3697ac4d25 100644
--- a/code/modules/mob/dead/observer/observer.dm
+++ b/code/modules/mob/dead/observer/observer.dm
@@ -208,7 +208,7 @@ Works together with spawning an observer, noted above.
if(ghost.client)
ghost.client.time_died_as_mouse = ghost.timeofdeath
if(ghost.client && !ghost.client.holder && !config.antag_hud_allowed) // For new ghosts we remove the verb from even showing up if it's not allowed.
- ghost.verbs -= /mob/observer/dead/verb/toggle_antagHUD // Poor guys, don't know what they are missing!
+ remove_verb(ghost, /mob/observer/dead/verb/toggle_antagHUD) // Poor guys, don't know what they are missing!
return ghost
/*
@@ -249,13 +249,13 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
/mob/observer/dead/can_use_hands() return 0
/mob/observer/dead/is_active() return 0
-/mob/observer/dead/Stat()
- ..()
- if(statpanel("Status"))
- if(emergency_shuttle)
- var/eta_status = emergency_shuttle.get_status_panel_eta()
- if(eta_status)
- stat(null, eta_status)
+/mob/observer/dead/get_status_tab_items()
+ . = ..()
+ if(emergency_shuttle)
+ var/eta_status = emergency_shuttle.get_status_panel_eta()
+ if(eta_status)
+ . += ""
+ . += "[eta_status]"
/mob/observer/dead/verb/reenter_corpse()
set category = "Ghost"
@@ -798,8 +798,8 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
/mob/observer/dead/proc/manifest(mob/user)
is_manifest = TRUE
- verbs |= /mob/observer/dead/proc/toggle_visibility
- verbs |= /mob/observer/dead/proc/ghost_whisper
+ add_verb(src, /mob/observer/dead/proc/toggle_visibility)
+ add_verb(src, /mob/observer/dead/proc/ghost_whisper)
to_chat(src, span_filter_notice("[span_purple("As you are now in the realm of the living, you can whisper to the living with the Spectral Whisper verb, inside the IC tab.")]"))
if(plane != PLANE_WORLD)
user.visible_message( \
diff --git a/code/modules/mob/language/language.dm b/code/modules/mob/language/language.dm
index ca21339f8e..fdce772f99 100644
--- a/code/modules/mob/language/language.dm
+++ b/code/modules/mob/language/language.dm
@@ -130,7 +130,7 @@
/datum/language/proc/broadcast(var/mob/living/speaker,var/message,var/speaker_mask)
log_say("(HIVE) [message]", speaker)
- speaker.verbs |= /mob/proc/adjust_hive_range
+ add_verb(speaker, /mob/proc/adjust_hive_range)
if(!speaker_mask) speaker_mask = speaker.real_name
message = "[get_spoken_verb(message)], \"[format_message(message, get_spoken_verb(message))]\""
@@ -205,7 +205,7 @@
languages.Add(new_language)
//VOREStation Addition Start
if(new_language.flags & HIVEMIND)
- verbs |= /mob/proc/adjust_hive_range
+ add_verb(src, /mob/proc/adjust_hive_range)
//VOREStation Addition End
return 1
diff --git a/code/modules/mob/living/bot/bot.dm b/code/modules/mob/living/bot/bot.dm
index c8acdb6759..41844ed5f8 100644
--- a/code/modules/mob/living/bot/bot.dm
+++ b/code/modules/mob/living/bot/bot.dm
@@ -562,13 +562,13 @@
/mob/living/bot/Login()
no_vore = FALSE // ROBOT VORE
init_vore() // ROBOT VORE
- verbs |= /mob/proc/insidePanel
+ add_verb(src, /mob/proc/insidePanel)
return ..()
/mob/living/bot/Logout()
release_vore_contents()
- verbs -= /mob/proc/insidePanel
+ remove_verb(src, /mob/proc/insidePanel)
no_vore = TRUE
devourable = FALSE
feeding = FALSE
diff --git a/code/modules/mob/living/carbon/alien/alien.dm b/code/modules/mob/living/carbon/alien/alien.dm
index 1629913c76..882ed51453 100644
--- a/code/modules/mob/living/carbon/alien/alien.dm
+++ b/code/modules/mob/living/carbon/alien/alien.dm
@@ -27,8 +27,8 @@
time_of_birth = world.time
- verbs += /mob/living/proc/ventcrawl
- verbs += /mob/living/proc/hide
+ add_verb(src, /mob/living/proc/ventcrawl)
+ add_verb(src, /mob/living/proc/hide)
instance_num = rand(1, 1000)
name = "[initial(name)] ([instance_num])"
@@ -66,4 +66,3 @@
else if(ending == "?")
verb = "hisses curiously"
return verb
-
diff --git a/code/modules/mob/living/carbon/alien/diona/diona.dm b/code/modules/mob/living/carbon/alien/diona/diona.dm
index 9fa713936f..434d02617b 100644
--- a/code/modules/mob/living/carbon/alien/diona/diona.dm
+++ b/code/modules/mob/living/carbon/alien/diona/diona.dm
@@ -54,7 +54,7 @@ var/list/_nymph_default_emotes = list(
species = GLOB.all_species[SPECIES_DIONA]
add_language(LANGUAGE_ROOTGLOBAL)
add_language(LANGUAGE_GALCOM)
- verbs += /mob/living/carbon/alien/diona/proc/merge
+ add_verb(src, /mob/living/carbon/alien/diona/proc/merge)
/mob/living/carbon/alien/diona/put_in_hands(var/obj/item/W) // No hands.
W.loc = get_turf(src)
diff --git a/code/modules/mob/living/carbon/alien/diona/diona_powers.dm b/code/modules/mob/living/carbon/alien/diona/diona_powers.dm
index 0f4b69501d..492a590793 100644
--- a/code/modules/mob/living/carbon/alien/diona/diona_powers.dm
+++ b/code/modules/mob/living/carbon/alien/diona/diona_powers.dm
@@ -9,7 +9,7 @@
return
if(istype(src.loc,/mob/living/carbon))
- src.verbs -= /mob/living/carbon/alien/diona/proc/merge
+ remove_verb(src, /mob/living/carbon/alien/diona/proc/merge)
return
var/list/choices = list()
@@ -35,8 +35,8 @@
to_chat(H, "You feel your being twine with that of \the [src] as it merges with your biomass.")
to_chat(src, "You feel your being twine with that of \the [H] as you merge with its biomass.")
loc = H
- verbs += /mob/living/carbon/alien/diona/proc/split
- verbs -= /mob/living/carbon/alien/diona/proc/merge
+ add_verb(src, /mob/living/carbon/alien/diona/proc/split)
+ remove_verb(src, /mob/living/carbon/alien/diona/proc/merge)
return 1
/mob/living/carbon/alien/diona/proc/split()
@@ -49,7 +49,7 @@
return
if(!(istype(src.loc,/mob/living/carbon)))
- src.verbs -= /mob/living/carbon/alien/diona/proc/split
+ remove_verb(src, /mob/living/carbon/alien/diona/proc/split)
return
to_chat(src.loc, "You feel a pang of loss as [src] splits away from your biomass.")
@@ -58,8 +58,8 @@
var/mob/living/M = src.loc
src.loc = get_turf(src)
- src.verbs -= /mob/living/carbon/alien/diona/proc/split
- src.verbs += /mob/living/carbon/alien/diona/proc/merge
+ remove_verb(src, /mob/living/carbon/alien/diona/proc/split)
+ add_verb(src, /mob/living/carbon/alien/diona/proc/merge)
if(istype(M))
for(var/atom/A in M.contents)
diff --git a/code/modules/mob/living/carbon/alien/diona/progression.dm b/code/modules/mob/living/carbon/alien/diona/progression.dm
index c8f9baaba6..45a33d4ebb 100644
--- a/code/modules/mob/living/carbon/alien/diona/progression.dm
+++ b/code/modules/mob/living/carbon/alien/diona/progression.dm
@@ -1,7 +1,8 @@
-/mob/living/carbon/alien/diona/Stat() //Specified where progression is at, doesn't work right for some things in carbon/alien
+/mob/living/carbon/alien/diona/get_status_tab_items() //Specified where progression is at, doesn't work right for some things in carbon/alien
. = ..()
- if(. && statpanel("Status"))
- stat("Growth", "[round(amount_grown)]/[max_grown]")
+ if(.)
+ . += ""
+ . += "Diona Growth: [round(amount_grown)]/[max_grown]"
/mob/living/carbon/alien/diona/confirm_evolution()
diff --git a/code/modules/mob/living/carbon/alien/larva/progression.dm b/code/modules/mob/living/carbon/alien/larva/progression.dm
index e671ac3aac..8762d710c1 100644
--- a/code/modules/mob/living/carbon/alien/larva/progression.dm
+++ b/code/modules/mob/living/carbon/alien/larva/progression.dm
@@ -1,7 +1,8 @@
-/mob/living/carbon/alien/larva/Stat() //Specified where progression stats come from, because for some reason it doesn't work right in carbon/alien
+/mob/living/carbon/alien/larva/get_status_tab_items() //Specified where progression stats come from, because for some reason it doesn't work right in carbon/alien
. = ..()
- if(. && statpanel("Status"))
- stat("Growth", "[round(amount_grown)]/[max_grown]")
+ if(.)
+ . += ""
+ . += "Larva Growth: [round(amount_grown)]/[max_grown]"
/mob/living/carbon/alien/larva/confirm_evolution()
diff --git a/code/modules/mob/living/carbon/alien/progression.dm b/code/modules/mob/living/carbon/alien/progression.dm
index 001c111139..e59688646e 100644
--- a/code/modules/mob/living/carbon/alien/progression.dm
+++ b/code/modules/mob/living/carbon/alien/progression.dm
@@ -8,7 +8,7 @@
return
if(!adult_form)
- verbs -= /mob/living/carbon/alien/verb/evolve
+ remove_verb(src, /mob/living/carbon/alien/verb/evolve)
return
if(handcuffed || legcuffed)
diff --git a/code/modules/mob/living/carbon/carbon_powers.dm b/code/modules/mob/living/carbon/carbon_powers.dm
index 04b85db770..f805968d40 100644
--- a/code/modules/mob/living/carbon/carbon_powers.dm
+++ b/code/modules/mob/living/carbon/carbon_powers.dm
@@ -12,9 +12,9 @@
B.detatch()
- verbs -= /mob/living/carbon/proc/release_control
- verbs -= /mob/living/carbon/proc/punish_host
- verbs -= /mob/living/carbon/proc/spawn_larvae
+ remove_verb(src, /mob/living/carbon/proc/release_control)
+ remove_verb(src, /mob/living/carbon/proc/punish_host)
+ remove_verb(src, /mob/living/carbon/proc/spawn_larvae)
else
to_chat(src, span_danger("ERROR NO BORER OR BRAINMOB DETECTED IN THIS MOB, THIS IS A BUG !"))
diff --git a/code/modules/mob/living/carbon/human/death.dm b/code/modules/mob/living/carbon/human/death.dm
index 038b5f6cf8..379cc3ce0e 100644
--- a/code/modules/mob/living/carbon/human/death.dm
+++ b/code/modules/mob/living/carbon/human/death.dm
@@ -77,7 +77,7 @@
B.host_brain.name = "host brain"
B.host_brain.real_name = "host brain"
- verbs -= /mob/living/carbon/proc/release_control
+ remove_verb(src, /mob/living/carbon/proc/release_control)
callHook("death", list(src, gibbed))
diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm
index b632dce012..76021e60ed 100644
--- a/code/modules/mob/living/carbon/human/human.dm
+++ b/code/modules/mob/living/carbon/human/human.dm
@@ -66,7 +66,6 @@
dna.real_name = real_name
sync_organ_dna()
- //verbs |= /mob/living/proc/toggle_selfsurgery //VOREStation Removal
AddComponent(/datum/component/personal_crafting)
/mob/living/carbon/human/Destroy()
@@ -84,42 +83,76 @@
QDEL_NULL(vessel)
return ..()
-/mob/living/carbon/human/Stat()
- ..()
- if(statpanel("Status"))
- stat("Intent:", "[a_intent]")
- stat("Move Mode:", "[m_intent]")
- if(emergency_shuttle)
- var/eta_status = emergency_shuttle.get_status_panel_eta()
- if(eta_status)
- stat(null, eta_status)
+/mob/living/carbon/human/get_status_tab_items()
+ . = ..()
+ . += ""
+ . += "Intent: [a_intent]"
+ . += "Move Mode: [m_intent]"
+ if(emergency_shuttle)
+ var/eta_status = emergency_shuttle.get_status_panel_eta()
+ if(eta_status)
+ . += "[eta_status]"
- if (internal)
- if (!internal.air_contents)
- qdel(internal)
- else
- stat("Internal Atmosphere Info", internal.name)
- stat("Tank Pressure", internal.air_contents.return_pressure())
- stat("Distribution Pressure", internal.distribute_pressure)
+ if (internal)
+ if (!internal.air_contents)
+ qdel(internal)
+ else
+ . += "Internal Atmosphere Info: [internal.name]"
+ . += "Tank Pressure: [internal.air_contents.return_pressure()]"
+ . += "Distribution Pressure: [internal.distribute_pressure]"
- var/obj/item/organ/internal/xenos/plasmavessel/P = internal_organs_by_name[O_PLASMA] //Xenomorphs. Mech.
- if(P)
- stat(null, "Phoron Stored: [P.stored_plasma]/[P.max_plasma]")
+ var/obj/item/organ/internal/xenos/plasmavessel/P = internal_organs_by_name[O_PLASMA] //Xenomorphs. Mech.
+ if(P)
+ . += "Phoron Stored: [P.stored_plasma]/[P.max_plasma]"
- if(back && istype(back,/obj/item/rig))
- var/obj/item/rig/suit = back
- var/cell_status = "ERROR"
- if(suit.cell) cell_status = "[suit.cell.charge]/[suit.cell.maxcharge]"
- stat(null, "Suit charge: [cell_status]")
+ if(back && istype(back,/obj/item/rig))
+ var/obj/item/rig/suit = back
+ var/cell_status = "ERROR"
+ if(suit.cell) cell_status = "[suit.cell.charge]/[suit.cell.maxcharge]"
+ . += "Suit charge: [cell_status]"
+
+ if(mind)
+ if(mind.changeling)
+ . += "Chemical Storage: [mind.changeling.chem_charges]"
+ . += "Genetic Damage Time: [mind.changeling.geneticdamage]"
+ . += "Re-Adaptations: [mind.changeling.readapts]/[mind.changeling.max_readapts]"
- if(mind)
- if(mind.changeling)
- stat("Chemical Storage", mind.changeling.chem_charges)
- stat("Genetic Damage Time", mind.changeling.geneticdamage)
- stat("Re-Adaptations", "[mind.changeling.readapts]/[mind.changeling.max_readapts]")
if(species)
- species.Stat(src)
+ species.get_status_tab_items(src)
+
+/mob/proc/RigPanel(var/obj/item/rig/R)
+ if(R && !R.canremove && R.installed_modules.len)
+ var/list/L = list()
+ var/cell_status = R.cell ? "[R.cell.charge]/[R.cell.maxcharge]" : "ERROR"
+ L[++L.len] = list("Suit charge: [cell_status]", null, null, null, null)
+ for(var/obj/item/rig_module/module in R.installed_modules)
+ {
+ for(var/stat_rig_module/SRM in module.stat_modules)
+ if(SRM.CanUse())
+ L[++L.len] = list(SRM.module.interface_name,null,null,SRM.name,REF(SRM))
+ }
+ misc_tabs["Hardsuit Modules"] = L
+
+/mob/living/update_misc_tabs()
+ ..()
+ if(get_rig_stats)
+ var/obj/item/rig/rig = get_rig()
+ if(rig)
+ RigPanel(rig)
+
+/mob/living/carbon/human/update_misc_tabs()
+ ..()
+ if(species)
+ species.update_misc_tabs(src)
+
+ if(istype(back,/obj/item/rig))
+ var/obj/item/rig/R = back
+ RigPanel(R)
+
+ else if(istype(belt,/obj/item/rig))
+ var/obj/item/rig/R = belt
+ RigPanel(R)
/mob/living/carbon/human/ex_act(severity)
if(!blinded)
@@ -847,7 +880,7 @@
return
if(!(mMorph in mutations))
- src.verbs -= /mob/living/carbon/human/proc/morph
+ remove_verb(src, /mob/living/carbon/human/proc/morph)
return
var/new_facial = input(usr, "Please select facial hair color.", "Character Generation",rgb(r_facial,g_facial,b_facial)) as color
@@ -922,7 +955,7 @@
return
if(!(mRemotetalk in src.mutations))
- src.verbs -= /mob/living/carbon/human/proc/remotesay
+ remove_verb(src, /mob/living/carbon/human/proc/remotesay)
return
var/list/creatures = list()
for(var/mob/living/carbon/h in mob_list)
@@ -953,7 +986,7 @@
if(!(mRemote in src.mutations))
remoteview_target = null
reset_view(0)
- src.verbs -= /mob/living/carbon/human/proc/remoteobserve
+ remove_verb(src, /mob/living/carbon/human/proc/remoteobserve)
return
if(client.eye != client.mob)
@@ -1088,7 +1121,7 @@
blood_DNA[M.dna.unique_enzymes] = M.dna.b_type
hand_blood_color = blood_color
update_bloodied()
- verbs += /mob/living/carbon/human/proc/bloody_doodle
+ add_verb(src, /mob/living/carbon/human/proc/bloody_doodle)
return 1 //we applied blood to the item
/mob/living/carbon/human/proc/get_full_print()
@@ -1317,7 +1350,7 @@
return 0 //something is terribly wrong
if (!bloody_hands)
- verbs -= /mob/living/carbon/human/proc/bloody_doodle
+ remove_verb(src, /mob/living/carbon/human/proc/bloody_doodle)
if (src.gloves)
to_chat(src, span_warning("Your [src.gloves] are getting in the way."))
@@ -1682,7 +1715,7 @@
/mob/living/carbon/human/examine_icon()
var/icon/I = get_cached_examine_icon(src)
if(!I)
- I = getFlatIcon(src, defdir = SOUTH, no_anim = TRUE)
+ I = getFlatIcon(src, defdir = SOUTH, no_anim = TRUE, force_south = TRUE)
set_cached_examine_icon(src, I, 50 SECONDS)
return I
diff --git a/code/modules/mob/living/carbon/human/human_modular_limbs.dm b/code/modules/mob/living/carbon/human/human_modular_limbs.dm
index c2ec856423..7e1d4e1e40 100644
--- a/code/modules/mob/living/carbon/human/human_modular_limbs.dm
+++ b/code/modules/mob/living/carbon/human/human_modular_limbs.dm
@@ -73,13 +73,13 @@
// Called in robotize(), replaced() and removed() to update our modular limb verbs.
/mob/living/carbon/human/proc/refresh_modular_limb_verbs()
if(length(get_modular_limbs(return_first_found = TRUE, validate_proc = /obj/item/organ/external/proc/can_attach_modular_limb_here)))
- verbs |= /mob/living/carbon/human/proc/attach_limb_verb
+ add_verb(src, /mob/living/carbon/human/proc/attach_limb_verb)
else
- verbs -= /mob/living/carbon/human/proc/attach_limb_verb
+ remove_verb(src, /mob/living/carbon/human/proc/attach_limb_verb)
if(length(get_modular_limbs(return_first_found = TRUE, validate_proc = /obj/item/organ/external/proc/can_remove_modular_limb)))
- verbs |= /mob/living/carbon/human/proc/detach_limb_verb
+ add_verb(src, /mob/living/carbon/human/proc/detach_limb_verb)
else
- verbs -= /mob/living/carbon/human/proc/detach_limb_verb
+ remove_verb(src, /mob/living/carbon/human/proc/detach_limb_verb)
// Proc helper for attachment verb.
/mob/living/carbon/human/proc/check_can_attach_modular_limb(var/obj/item/organ/external/E)
diff --git a/code/modules/mob/living/carbon/human/human_powers.dm b/code/modules/mob/living/carbon/human/human_powers.dm
index 1391f47ca9..14f876a703 100644
--- a/code/modules/mob/living/carbon/human/human_powers.dm
+++ b/code/modules/mob/living/carbon/human/human_powers.dm
@@ -191,8 +191,8 @@
qdel(Org)
// Purge the diona verbs.
- verbs -= /mob/living/carbon/human/proc/diona_split_nymph
- verbs -= /mob/living/carbon/human/proc/regenerate
+ remove_verb(src, /mob/living/carbon/human/proc/diona_split_nymph)
+ remove_verb(src, /mob/living/carbon/human/proc/regenerate)
for(var/obj/item/organ/external/E in organs) // Just fall apart.
E.droplimb(TRUE)
diff --git a/code/modules/mob/living/carbon/human/species/lleill/hanner.dm b/code/modules/mob/living/carbon/human/species/lleill/hanner.dm
index f63369d232..8b7e2b98f8 100644
--- a/code/modules/mob/living/carbon/human/species/lleill/hanner.dm
+++ b/code/modules/mob/living/carbon/human/species/lleill/hanner.dm
@@ -114,7 +114,7 @@
H.ability_master = new /obj/screen/movable/ability_master/lleill(H)
for(var/datum/power/lleill/P in lleill_ability_datums)
if(!(P.verbpath in H.verbs))
- H.verbs += P.verbpath
+ add_verb(H, P.verbpath)
H.ability_master.add_lleill_ability(
object_given = H,
verb_given = P.verbpath,
diff --git a/code/modules/mob/living/carbon/human/species/lleill/lleill.dm b/code/modules/mob/living/carbon/human/species/lleill/lleill.dm
index 4072e5af05..8c6e206555 100644
--- a/code/modules/mob/living/carbon/human/species/lleill/lleill.dm
+++ b/code/modules/mob/living/carbon/human/species/lleill/lleill.dm
@@ -206,7 +206,7 @@
H.ability_master = new /obj/screen/movable/ability_master/lleill(H)
for(var/datum/power/lleill/P in lleill_ability_datums)
if(!(P.verbpath in H.verbs))
- H.verbs += P.verbpath
+ add_verb(H, P.verbpath)
H.ability_master.add_lleill_ability(
object_given = H,
verb_given = P.verbpath,
@@ -239,4 +239,3 @@
/datum/species/lleill/add_inherent_verbs(var/mob/living/carbon/human/H)
..()
add_lleill_abilities(H)
-
diff --git a/code/modules/mob/living/carbon/human/species/lleill/lleill_abilities.dm b/code/modules/mob/living/carbon/human/species/lleill/lleill_abilities.dm
index 5e68449f25..4655695fc9 100644
--- a/code/modules/mob/living/carbon/human/species/lleill/lleill_abilities.dm
+++ b/code/modules/mob/living/carbon/human/species/lleill/lleill_abilities.dm
@@ -476,8 +476,8 @@
new_mob.vore_organs = list()
new_mob.name = M.name
new_mob.real_name = M.real_name
- new_mob.verbs |= /mob/living/proc/revert_beast_form
- new_mob.verbs |= /mob/living/proc/set_size
+ add_verb(new_mob, /mob/living/proc/revert_beast_form)
+ add_verb(new_mob, /mob/living/proc/set_size)
for(var/lang in M.languages)
new_mob.languages |= lang
M.copy_vore_prefs_to_mob(new_mob)
@@ -654,8 +654,8 @@
new_mob.vore_organs = list()
new_mob.name = M.name
new_mob.real_name = M.real_name
- new_mob.verbs |= /mob/living/proc/revert_beast_form
- new_mob.verbs |= /mob/living/proc/set_size
+ add_verb(new_mob, /mob/living/proc/revert_beast_form)
+ add_verb(new_mob, /mob/living/proc/set_size)
new_mob.hasthermals = 0
new_mob.health = M.health
new_mob.maxHealth = M.health
diff --git a/code/modules/mob/living/carbon/human/species/lleill/lleill_items.dm b/code/modules/mob/living/carbon/human/species/lleill/lleill_items.dm
index 5121d8c842..13b9a06968 100644
--- a/code/modules/mob/living/carbon/human/species/lleill/lleill_items.dm
+++ b/code/modules/mob/living/carbon/human/species/lleill/lleill_items.dm
@@ -61,7 +61,7 @@
/datum/reagent/glamour_scaling/affect_blood(var/mob/living/carbon/target, var/removed)
if(!(/mob/living/proc/set_size in target.verbs))
to_chat(target, span_warning("You feel as though you could change size at any moment."))
- target.verbs |= /mob/living/proc/set_size
+ add_verb(target, /mob/living/proc/set_size)
target.bloodstr.clear_reagents() //instantly clears reagents afterwards
target.ingested.clear_reagents()
target.touching.clear_reagents()
diff --git a/code/modules/mob/living/carbon/human/species/shadekin/shadekin.dm b/code/modules/mob/living/carbon/human/species/shadekin/shadekin.dm
index 032a76628d..c1de18c498 100644
--- a/code/modules/mob/living/carbon/human/species/shadekin/shadekin.dm
+++ b/code/modules/mob/living/carbon/human/species/shadekin/shadekin.dm
@@ -144,7 +144,7 @@
H.ability_master = new /obj/screen/movable/ability_master/shadekin(H)
for(var/datum/power/shadekin/P in shadekin_ability_datums)
if(!(P.verbpath in H.verbs))
- H.verbs += P.verbpath
+ add_verb(H, P.verbpath)
H.ability_master.add_shadekin_ability(
object_given = H,
verb_given = P.verbpath,
@@ -341,4 +341,4 @@
new_copy.energy_dark = energy_dark
- return new_copy
\ No newline at end of file
+ return new_copy
diff --git a/code/modules/mob/living/carbon/human/species/shadekin/shadekin_abilities.dm b/code/modules/mob/living/carbon/human/species/shadekin/shadekin_abilities.dm
index 696af416c4..3d62d0d033 100644
--- a/code/modules/mob/living/carbon/human/species/shadekin/shadekin_abilities.dm
+++ b/code/modules/mob/living/carbon/human/species/shadekin/shadekin_abilities.dm
@@ -29,7 +29,7 @@
/mob/living/carbon/human/proc/phase_shift()
set name = "Phase Shift (100)"
set desc = "Shift yourself out of alignment with realspace to travel quickly to different areas."
- set category = "Shadekin"
+ set category = "Abilities.Shadekin"
var/ability_cost = 100
@@ -181,7 +181,7 @@
/mob/living/carbon/human/proc/regenerate_other()
set name = "Regenerate Other (50)"
set desc = "Spend energy to heal physical wounds in another creature."
- set category = "Shadekin"
+ set category = "Abilities.Shadekin"
var/ability_cost = 50
@@ -250,7 +250,7 @@
/mob/living/carbon/human/proc/create_shade()
set name = "Create Shade (25)"
set desc = "Create a field of darkness that follows you."
- set category = "Shadekin"
+ set category = "Abilities.Shadekin"
var/ability_cost = 25
diff --git a/code/modules/mob/living/carbon/human/species/species.dm b/code/modules/mob/living/carbon/human/species/species.dm
index 296b9e386c..252b42fd21 100644
--- a/code/modules/mob/living/carbon/human/species/species.dm
+++ b/code/modules/mob/living/carbon/human/species/species.dm
@@ -458,13 +458,13 @@
/datum/species/proc/remove_inherent_verbs(var/mob/living/carbon/human/H)
if(inherent_verbs)
for(var/verb_path in inherent_verbs)
- H.verbs -= verb_path
+ remove_verb(H, verb_path)
return
/datum/species/proc/add_inherent_verbs(var/mob/living/carbon/human/H)
if(inherent_verbs)
for(var/verb_path in inherent_verbs)
- H.verbs |= verb_path
+ add_verb(H, verb_path)
return
/datum/species/proc/handle_post_spawn(var/mob/living/carbon/human/H) //Handles anything not already covered by basic species assignment.
@@ -556,8 +556,8 @@
return FALSE
// Allow species to display interesting information in the human stat panels
-/datum/species/proc/Stat(var/mob/living/carbon/human/H)
- return
+/datum/species/proc/get_status_tab_items(var/mob/living/carbon/human/H)
+ return ""
/datum/species/proc/handle_water_damage(var/mob/living/carbon/human/H, var/amount = 0)
amount *= 1 - H.get_water_protection()
@@ -584,3 +584,6 @@
/datum/species/proc/post_spawn_special(mob/living/carbon/human/H)
return
+
+/datum/species/proc/update_misc_tabs(var/mob/living/carbon/human/H)
+ return
diff --git a/code/modules/mob/living/carbon/human/species/station/alraune.dm b/code/modules/mob/living/carbon/human/species/station/alraune.dm
index 2c2089e57b..38fbfa66f0 100644
--- a/code/modules/mob/living/carbon/human/species/station/alraune.dm
+++ b/code/modules/mob/living/carbon/human/species/station/alraune.dm
@@ -393,8 +393,8 @@
var/selection = tgui_input_list(src, "Choose your character's fruit type. Choosing nothing will result in a default of apples.", "Fruit Type", acceptable_fruit_types)
if(selection)
fruit_gland.fruit_type = selection
- verbs |= /mob/living/carbon/human/proc/alraune_fruit_pick
- verbs -= /mob/living/carbon/human/proc/alraune_fruit_select
+ add_verb(src, /mob/living/carbon/human/proc/alraune_fruit_pick)
+ remove_verb(src, /mob/living/carbon/human/proc/alraune_fruit_select)
fruit_gland.organ_owner = src
fruit_gland.emote_descriptor = list("fruit right off of [fruit_gland.organ_owner]!", "a fruit from [fruit_gland.organ_owner]!")
diff --git a/code/modules/mob/living/carbon/human/species/station/prommie_blob.dm b/code/modules/mob/living/carbon/human/species/station/prommie_blob.dm
index 9bdf64f4f2..4b84372797 100644
--- a/code/modules/mob/living/carbon/human/species/station/prommie_blob.dm
+++ b/code/modules/mob/living/carbon/human/species/station/prommie_blob.dm
@@ -42,15 +42,14 @@
/decl/emote/visible/floorspin
)
/mob/living/simple_mob/slime/promethean/Initialize(mapload, null)
- //verbs -= /mob/living/proc/ventcrawl
- verbs += /mob/living/simple_mob/slime/promethean/proc/prommie_blobform
- verbs += /mob/living/proc/set_size
- verbs += /mob/living/proc/hide
- verbs += /mob/living/simple_mob/proc/animal_nom
- verbs += /mob/living/proc/shred_limb
- verbs += /mob/living/simple_mob/slime/promethean/proc/toggle_expand
- verbs += /mob/living/simple_mob/slime/promethean/proc/prommie_select_colour
- verbs += /mob/living/simple_mob/slime/promethean/proc/toggle_shine
+ add_verb(src, /mob/living/simple_mob/slime/promethean/proc/prommie_blobform)
+ add_verb(src, /mob/living/proc/set_size)
+ add_verb(src, /mob/living/proc/hide)
+ add_verb(src, /mob/living/simple_mob/proc/animal_nom)
+ add_verb(src, /mob/living/proc/shred_limb)
+ add_verb(src, /mob/living/simple_mob/slime/promethean/proc/toggle_expand)
+ add_verb(src, /mob/living/simple_mob/slime/promethean/proc/prommie_select_colour)
+ add_verb(src, /mob/living/simple_mob/slime/promethean/proc/toggle_shine)
update_mood()
if(rad_glow)
rad_glow = CLAMP(rad_glow,0,250)
@@ -81,11 +80,6 @@
QDEL_NULL(stored_blob)
return ..()
-/mob/living/simple_mob/slime/promethean/Stat()
- ..()
- if(humanform)
- humanform.species.Stat(humanform)
-
/mob/living/simple_mob/slime/promethean/handle_special() // Should disable default slime healing, we'll use nutrition based heals instead.
if(rad_glow)
rad_glow = CLAMP(rad_glow,0,250)
@@ -409,8 +403,8 @@
new_hat.forceMove(src)
blob.update_icon()
- blob.verbs -= /mob/living/proc/ventcrawl // Absolutely not.
- blob.verbs -= /mob/living/simple_mob/proc/set_name // We already have a name.
+ remove_verb(blob, /mob/living/proc/ventcrawl) // Absolutely not.
+ remove_verb(blob, /mob/living/simple_mob/proc/set_name) // We already have a name.
temporary_form = blob
//Mail them to nullspace
moveToNullspace()
diff --git a/code/modules/mob/living/carbon/human/species/station/protean_vr/protean_blob.dm b/code/modules/mob/living/carbon/human/species/station/protean_vr/protean_blob.dm
index fb1b1366e4..81878965fc 100644
--- a/code/modules/mob/living/carbon/human/species/station/protean_vr/protean_blob.dm
+++ b/code/modules/mob/living/carbon/human/species/station/protean_vr/protean_blob.dm
@@ -63,8 +63,8 @@
humanform = H
updatehealth()
refactory = locate() in humanform.internal_organs
- verbs |= /mob/living/proc/ventcrawl
- verbs |= /mob/living/proc/hide
+ add_verb(src, /mob/living/proc/ventcrawl)
+ add_verb(src, /mob/living/proc/hide)
else
update_icon()
@@ -99,10 +99,10 @@
/mob/living/simple_mob/protean_blob/isSynthetic()
return TRUE // yup
-/mob/living/simple_mob/protean_blob/Stat()
- ..()
+/mob/living/simple_mob/protean_blob/update_misc_tabs()
+ . = ..()
if(humanform)
- humanform.species.Stat(humanform)
+ humanform.species.update_misc_tabs(src)
/mob/living/simple_mob/protean_blob/update_icon()
if(humanform)
@@ -323,10 +323,6 @@ var/global/list/disallowed_protean_accessories = list(
to_chat(src,span_warning("You can't change forms while inside something."))
return
- var/panel_was_up = FALSE
- if(client?.statpanel == "Protean")
- panel_was_up = TRUE
-
handle_grasp() //It's possible to blob out before some key parts of the life loop. This results in things getting dropped at null. TODO: Fix the code so this can be done better.
remove_micros(src, src) //Living things don't fare well in roblobs.
if(buckled)
@@ -405,9 +401,6 @@ var/global/list/disallowed_protean_accessories = list(
//We can still speak our languages!
blob.languages = languages.Copy()
- //Flip them to the protean panel
- if(panel_was_up)
- client?.statpanel = "Protean"
//Return our blob in case someone wants it
return blob
@@ -427,10 +420,6 @@ var/global/list/disallowed_protean_accessories = list(
to_chat(blob,span_warning("You can't change forms while inside something."))
return
- var/panel_was_up = FALSE
- if(client?.statpanel == "Protean")
- panel_was_up = TRUE
-
if(buckled)
buckled.unbuckle_mob()
if(LAZYLEN(buckled_mobs))
@@ -483,10 +472,6 @@ var/global/list/disallowed_protean_accessories = list(
//Get rid of friend blob
qdel(blob)
- //Flip them to the protean panel
- if(panel_was_up)
- client?.statpanel = "Protean"
-
//Return ourselves in case someone wants it
return src
diff --git a/code/modules/mob/living/carbon/human/species/station/protean_vr/protean_species.dm b/code/modules/mob/living/carbon/human/species/station/protean_vr/protean_species.dm
index d106ec4eb4..525db79de4 100755
--- a/code/modules/mob/living/carbon/human/species/station/protean_vr/protean_species.dm
+++ b/code/modules/mob/living/carbon/human/species/station/protean_vr/protean_species.dm
@@ -212,22 +212,32 @@
/datum/species/protean/get_additional_examine_text(var/mob/living/carbon/human/H)
return ..() //Hmm, what could be done here?
-/datum/species/protean/Stat(var/mob/living/carbon/human/H)
+/datum/species/protean/update_misc_tabs(var/mob/living/carbon/human/H)
..()
- if(statpanel("Protean"))
- var/obj/item/organ/internal/nano/refactory/refactory = H.nano_get_refactory()
- if(refactory && !(refactory.status & ORGAN_DEAD))
- stat(null, "- -- --- Refactory Metal Storage --- -- -")
- var/max = refactory.max_storage
- for(var/material in refactory.materials)
- var/amount = refactory.get_stored_material(material)
- stat("[capitalize(material)]", "[amount]/[max]")
- else
- stat(null, "- -- --- REFACTORY ERROR! --- -- -")
+ var/list/L = list()
+ var/obj/item/organ/internal/nano/refactory/refactory = H.nano_get_refactory()
+ if(refactory && !(refactory.status & ORGAN_DEAD))
+ L[++L.len] = list("- -- --- Refactory Metal Storage --- -- -", null, null, null, null)
+ var/max = refactory.max_storage
+ for(var/material in refactory.materials)
+ var/amount = refactory.get_stored_material(material)
+ L[++L.len] = list("[capitalize(material)]: [amount]/[max]", null, null, null, null)
+ else
+ L[++L.len] = list("- -- --- REFACTORY ERROR! --- -- -", null, null, null, null)
- stat(null, "- -- --- Abilities (Shift+LMB Examines) --- -- -")
- for(var/obj/effect/protean_ability/A as anything in abilities)
- stat("[A.ability_name]",A.atom_button_text())
+ L[++L.len] = list("- -- --- Abilities (Shift+LMB Examines) --- -- -", null, null, null, null)
+ for(var/obj/effect/protean_ability/A as anything in abilities)
+ var/client/C = H.client
+ var/img
+ if(C && istype(C)) //sanity checks
+ if(A.ability_name in C.misc_cache)
+ img = C.misc_cache[A.ability_name]
+ else
+ img = icon2html(A,C,sourceonly=TRUE)
+ C.misc_cache[A.ability_name] = img
+
+ L[++L.len] = list("[A.ability_name]", A.ability_name, img, A.atom_button_text(), REF(A))
+ H.misc_tabs["Protean"] = L
// Various modifiers
/datum/modifier/protean
diff --git a/code/modules/mob/living/carbon/human/species/station/station.dm b/code/modules/mob/living/carbon/human/species/station/station.dm
index fda555edd8..c2d52b273b 100644
--- a/code/modules/mob/living/carbon/human/species/station/station.dm
+++ b/code/modules/mob/living/carbon/human/species/station/station.dm
@@ -633,8 +633,8 @@
qdel(Org)
// Purge the diona verbs.
- H.verbs -= /mob/living/carbon/human/proc/diona_split_nymph
- H.verbs -= /mob/living/carbon/human/proc/regenerate
+ remove_verb(H, /mob/living/carbon/human/proc/diona_split_nymph)
+ remove_verb(H, /mob/living/carbon/human/proc/regenerate)
return
diff --git a/code/modules/mob/living/carbon/human/species/station/station_special_abilities_vr.dm b/code/modules/mob/living/carbon/human/species/station/station_special_abilities_vr.dm
index 4c7b12a130..4ac3e5a50f 100644
--- a/code/modules/mob/living/carbon/human/species/station/station_special_abilities_vr.dm
+++ b/code/modules/mob/living/carbon/human/species/station/station_special_abilities_vr.dm
@@ -57,7 +57,7 @@
// Was dead, still dead.
else
to_chat(src, span_notice("Consciousness begins to stir as your new body awakens, ready to hatch."))
- verbs |= /mob/living/carbon/human/proc/hatch
+ add_verb(src, /mob/living/carbon/human/proc/hatch)
revive_ready = REVIVING_DONE
src << sound('sound/effects/mob_effects/xenochimera/hatch_notification.ogg',0,0,0,30)
clear_alert("regen")
@@ -79,7 +79,7 @@
to_chat(src, span_notice("Consciousness begins to stir as your new body awakens, ready to hatch.."))
else
to_chat(src, span_warning("Consciousness begins to stir as your battered body struggles to recover from its ordeal.."))
- verbs |= /mob/living/carbon/human/proc/hatch
+ add_verb(src, /mob/living/carbon/human/proc/hatch)
revive_ready = REVIVING_DONE
src << sound('sound/effects/mob_effects/xenochimera/hatch_notification.ogg',0,0,0,30)
clear_alert("regen")
@@ -110,7 +110,7 @@
if(revive_ready != REVIVING_DONE)
//Hwhat?
- verbs -= /mob/living/carbon/human/proc/hatch
+ remove_verb(src, /mob/living/carbon/human/proc/hatch)
return
var/confirm = tgui_alert(usr, "Are you sure you want to hatch right now? This will be very obvious to anyone in view.", "Confirm Regeneration", list("Yes", "No"))
@@ -138,7 +138,7 @@
clear_alert("hatch")
/mob/living/carbon/human/proc/chimera_hatch()
- verbs -= /mob/living/carbon/human/proc/hatch
+ remove_verb(src, /mob/living/carbon/human/proc/hatch)
to_chat(src, span_notice("Your new body awakens, bursting free from your old skin."))
//Modify and record values (half nutrition and braindamage)
var/old_nutrition = nutrition
diff --git a/code/modules/mob/living/carbon/human/species/station/traits_vr/neutral.dm b/code/modules/mob/living/carbon/human/species/station/traits_vr/neutral.dm
index d2257ee669..441fddafa0 100644
--- a/code/modules/mob/living/carbon/human/species/station/traits_vr/neutral.dm
+++ b/code/modules/mob/living/carbon/human/species/station/traits_vr/neutral.dm
@@ -108,7 +108,7 @@
/datum/trait/neutral/bloodsucker/apply(var/datum/species/S,var/mob/living/carbon/human/H)
..()
- H.verbs |= /mob/living/carbon/human/proc/bloodsuck
+ add_verb(H, /mob/living/carbon/human/proc/bloodsuck)
/datum/trait/neutral/bloodsucker_freeform
name = "Bloodsucker"
@@ -129,7 +129,7 @@
/datum/trait/neutral/bloodsucker_freeform/apply(var/datum/species/S,var/mob/living/carbon/human/H)
..()
- H.verbs |= /mob/living/carbon/human/proc/bloodsuck
+ add_verb(H, /mob/living/carbon/human/proc/bloodsuck)
/datum/trait/neutral/succubus_drain
name = "Succubus Drain"
@@ -139,9 +139,9 @@
/datum/trait/neutral/succubus_drain/apply(var/datum/species/S,var/mob/living/carbon/human/H)
..()
- H.verbs |= /mob/living/carbon/human/proc/succubus_drain
- H.verbs |= /mob/living/carbon/human/proc/succubus_drain_finalize
- H.verbs |= /mob/living/carbon/human/proc/succubus_drain_lethal
+ add_verb(H, /mob/living/carbon/human/proc/succubus_drain)
+ add_verb(H, /mob/living/carbon/human/proc/succubus_drain_finalize)
+ add_verb(H, /mob/living/carbon/human/proc/succubus_drain_lethal)
/datum/trait/neutral/venom_bite
name = "Venomous Injection"
@@ -169,7 +169,7 @@
/datum/trait/neutral/venom_bite/apply(var/datum/species/S,var/mob/living/carbon/human/H)
..()
- H.verbs |= /mob/living/proc/injection
+ add_verb(H, /mob/living/proc/injection)
H.trait_injection_reagents += "microcillin" // get small
H.trait_injection_reagents += "macrocillin" // get BIG
H.trait_injection_reagents += "normalcillin" // normal
@@ -201,7 +201,7 @@
/datum/trait/neutral/long_vore/apply(var/datum/species/S,var/mob/living/carbon/human/H)
..()
- H.verbs |= /mob/living/proc/long_vore
+ add_verb(H, /mob/living/proc/long_vore)
/datum/trait/neutral/feeder
name = "Feeder"
@@ -211,7 +211,7 @@
/datum/trait/neutral/feeder/apply(var/datum/species/S,var/mob/living/carbon/human/H)
..()
- H.verbs |= /mob/living/carbon/human/proc/slime_feed
+ add_verb(H, /mob/living/carbon/human/proc/slime_feed)
/datum/trait/neutral/stuffing_feeder
name = "Food Stuffer"
@@ -222,7 +222,7 @@
/datum/trait/neutral/stuffing_feeder/apply(var/datum/species/S,var/mob/living/carbon/human/H)
..()
- H.verbs |= /mob/living/proc/toggle_stuffing_mode
+ add_verb(H, /mob/living/proc/toggle_stuffing_mode)
/datum/trait/neutral/hard_vore
name = "Brutal Predation"
@@ -232,7 +232,7 @@
/datum/trait/neutral/hard_vore/apply(var/datum/species/S,var/mob/living/carbon/human/H)
..()
- H.verbs |= /mob/living/proc/shred_limb
+ add_verb(H, /mob/living/proc/shred_limb)
/datum/trait/neutral/trashcan
name = "Trash Can"
@@ -243,8 +243,8 @@
/datum/trait/neutral/trashcan/apply(var/datum/species/S,var/mob/living/carbon/human/H)
..()
- H.verbs |= /mob/living/proc/eat_trash
- H.verbs |= /mob/living/proc/toggle_trash_catching //Ported from chompstation
+ add_verb(H, /mob/living/proc/eat_trash)
+ add_verb(H, /mob/living/proc/toggle_trash_catching) //Ported from chompstation
/datum/trait/neutral/gem_eater
name = "Expensive Taste"
@@ -255,7 +255,7 @@
/datum/trait/neutral/gem_eater/apply(var/datum/species/S,var/mob/living/carbon/human/H)
..()
- H.verbs |= /mob/living/proc/eat_minerals
+ add_verb(H, /mob/living/proc/eat_minerals)
/datum/trait/neutral/synth_chemfurnace
name = "Biofuel Processor"
@@ -292,7 +292,7 @@
/datum/trait/neutral/glowing_eyes/apply(var/datum/species/S,var/mob/living/carbon/human/H)
..()
- H.verbs |= /mob/living/carbon/human/proc/toggle_eye_glow
+ add_verb(H, /mob/living/carbon/human/proc/toggle_eye_glow)
/datum/trait/neutral/glowing_body
name = "Glowing Body"
@@ -304,8 +304,8 @@
/datum/trait/neutral/glowing_body/apply(var/datum/species/S,var/mob/living/carbon/human/H)
..()
- H.verbs |= /mob/living/proc/glow_toggle
- H.verbs |= /mob/living/proc/glow_color
+ add_verb(H, /mob/living/proc/glow_toggle)
+ add_verb(H, /mob/living/proc/glow_color)
//Allergen traits! Not available to any species with a base allergens var.
/datum/trait/neutral/allergy
@@ -733,7 +733,7 @@
/datum/trait/neutral/dominate_predator/apply(var/datum/species/S,var/mob/living/carbon/human/H)
..()
- H.verbs |= /mob/proc/dominate_predator
+ add_verb(H, /mob/proc/dominate_predator)
/datum/trait/neutral/dominate_prey
name = "Dominate Prey"
@@ -743,7 +743,7 @@
/datum/trait/neutral/dominate_prey/apply(var/datum/species/S,var/mob/living/carbon/human/H)
..()
- H.verbs |= /mob/living/proc/dominate_prey
+ add_verb(H, /mob/living/proc/dominate_prey)
/datum/trait/neutral/submit_to_prey
name = "Submit To Prey"
@@ -753,7 +753,7 @@
/datum/trait/neutral/submit_to_prey/apply(var/datum/species/S,var/mob/living/carbon/human/H)
..()
- H.verbs |= /mob/living/proc/lend_prey_control
+ add_verb(H, /mob/living/proc/lend_prey_control)
/datum/trait/neutral/vertical_nom
name = "Vertical Nom"
@@ -763,7 +763,7 @@
/datum/trait/neutral/vertical_nom/apply(var/datum/species/S,var/mob/living/carbon/human/H)
..()
- H.verbs |= /mob/living/proc/vertical_nom
+ add_verb(H, /mob/living/proc/vertical_nom)
/datum/trait/neutral/micro_size_down
name = "Light Frame"
@@ -859,7 +859,7 @@
/datum/trait/neutral/synth_cosmetic_pain/apply(var/datum/species/S,var/mob/living/carbon/human/H, var/trait_prefs = null)
..()
- H.verbs |= /mob/living/carbon/human/proc/toggle_pain_module
+ add_verb(H, /mob/living/carbon/human/proc/toggle_pain_module)
//Food preferences ported from RogueStar
diff --git a/code/modules/mob/living/carbon/human/species/station/traits_vr/positive.dm b/code/modules/mob/living/carbon/human/species/station/traits_vr/positive.dm
index 72b3f49626..7551915c9d 100644
--- a/code/modules/mob/living/carbon/human/species/station/traits_vr/positive.dm
+++ b/code/modules/mob/living/carbon/human/species/station/traits_vr/positive.dm
@@ -125,9 +125,9 @@
/datum/trait/positive/winged_flight/apply(var/datum/species/S,var/mob/living/carbon/human/H)
..()
- H.verbs |= /mob/living/proc/flying_toggle
- H.verbs |= /mob/living/proc/flying_vore_toggle
- H.verbs |= /mob/living/proc/start_wings_hovering
+ add_verb(H, /mob/living/proc/flying_toggle)
+ add_verb(H, /mob/living/proc/flying_vore_toggle)
+ add_verb(H, /mob/living/proc/start_wings_hovering)
/datum/trait/positive/soft_landing
name = "Soft Landing"
@@ -151,7 +151,7 @@
/datum/trait/positive/antiseptic_saliva/apply(var/datum/species/S,var/mob/living/carbon/human/H)
..()
- H.verbs |= /mob/living/carbon/human/proc/lick_wounds
+ add_verb(H, /mob/living/carbon/human/proc/lick_wounds)
/datum/trait/positive/traceur
name = "Traceur"
@@ -179,11 +179,11 @@
/datum/trait/positive/weaver/apply(var/datum/species/S,var/mob/living/carbon/human/H)
..()
- H.verbs |= /mob/living/carbon/human/proc/check_silk_amount
- H.verbs |= /mob/living/carbon/human/proc/toggle_silk_production
- H.verbs |= /mob/living/carbon/human/proc/weave_structure
- H.verbs |= /mob/living/carbon/human/proc/weave_item
- H.verbs |= /mob/living/carbon/human/proc/set_silk_color
+ add_verb(H, /mob/living/carbon/human/proc/check_silk_amount)
+ add_verb(H, /mob/living/carbon/human/proc/toggle_silk_production)
+ add_verb(H, /mob/living/carbon/human/proc/weave_structure)
+ add_verb(H, /mob/living/carbon/human/proc/weave_item)
+ add_verb(H, /mob/living/carbon/human/proc/set_silk_color)
/datum/trait/positive/aquatic
name = "Aquatic"
@@ -195,8 +195,8 @@
/datum/trait/positive/aquatic/apply(var/datum/species/S,var/mob/living/carbon/human/H)
..()
- H.verbs |= /mob/living/carbon/human/proc/water_stealth
- H.verbs |= /mob/living/carbon/human/proc/underwater_devour
+ add_verb(H, /mob/living/carbon/human/proc/water_stealth)
+ add_verb(H, /mob/living/carbon/human/proc/underwater_devour)
/datum/trait/positive/cocoon_tf
name = "Cocoon Spinner"
@@ -207,7 +207,7 @@
/datum/trait/positive/cocoon_tf/apply(var/datum/species/S,var/mob/living/carbon/human/H)
..()
- H.verbs |= /mob/living/carbon/human/proc/enter_cocoon
+ add_verb(H, /mob/living/carbon/human/proc/enter_cocoon)
/datum/trait/positive/linguist
name = "Linguist"
diff --git a/code/modules/mob/living/carbon/human/species/station/traits_vr/trait.dm b/code/modules/mob/living/carbon/human/species/station/traits_vr/trait.dm
index 6239f89428..d47eda0a34 100644
--- a/code/modules/mob/living/carbon/human/species/station/traits_vr/trait.dm
+++ b/code/modules/mob/living/carbon/human/species/station/traits_vr/trait.dm
@@ -33,7 +33,7 @@
S.vars[trait] = trait_prefs[trait]
if(TRAIT_VAREDIT_TARGET_MOB)
H.vars[trait] = trait_prefs[trait]
- H.verbs |= /mob/living/carbon/human/proc/trait_tutorial
+ add_verb(H, /mob/living/carbon/human/proc/trait_tutorial)
return
//Applying trait to preferences rather than just us.
diff --git a/code/modules/mob/living/carbon/human/species/xenomorphs/alien_powers.dm b/code/modules/mob/living/carbon/human/species/xenomorphs/alien_powers.dm
index 9f87c39208..5ba47ab357 100644
--- a/code/modules/mob/living/carbon/human/species/xenomorphs/alien_powers.dm
+++ b/code/modules/mob/living/carbon/human/species/xenomorphs/alien_powers.dm
@@ -85,7 +85,7 @@
if(!config.aliens_allowed)
to_chat(src, "You begin to lay an egg, but hesitate. You suspect it isn't allowed.")
- verbs -= /mob/living/carbon/human/proc/lay_egg
+ remove_verb(src, /mob/living/carbon/human/proc/lay_egg)
return
if(locate(/obj/structure/ghost_pod/automatic/xenomorph_egg) in get_turf(src))
diff --git a/code/modules/mob/living/carbon/human/update_icons.dm b/code/modules/mob/living/carbon/human/update_icons.dm
index 912cef600b..a592afd1c2 100644
--- a/code/modules/mob/living/carbon/human/update_icons.dm
+++ b/code/modules/mob/living/carbon/human/update_icons.dm
@@ -1387,8 +1387,8 @@ var/global/list/damage_icon_parts = list() //see UpdateDamageIcon()
working.pixel_y = tail_style.offset_y
if(taurtype.can_ride && !riding_datum)
riding_datum = new /datum/riding/taur(src)
- verbs |= /mob/living/carbon/human/proc/taur_mount
- verbs |= /mob/living/proc/toggle_rider_reins
+ add_verb(src, /mob/living/carbon/human/proc/taur_mount)
+ add_verb(src, /mob/living/proc/toggle_rider_reins)
else if(islongtail(tail_style))
working.pixel_x = tail_style.offset_x
working.pixel_y = tail_style.offset_y
diff --git a/code/modules/mob/living/living_defense.dm b/code/modules/mob/living/living_defense.dm
index aa34f5669d..ce27814d7d 100644
--- a/code/modules/mob/living/living_defense.dm
+++ b/code/modules/mob/living/living_defense.dm
@@ -365,7 +365,7 @@
/mob/living/proc/embed(var/obj/O, var/def_zone=null)
O.loc = src
src.embedded += O
- src.verbs += /mob/proc/yank_out_object
+ add_verb(src, /mob/proc/yank_out_object)
throw_alert("embeddedobject", /obj/screen/alert/embeddedobject)
//This is called when the mob is thrown into a dense turf
diff --git a/code/modules/mob/living/login.dm b/code/modules/mob/living/login.dm
index cd2672f97d..94819c56c9 100644
--- a/code/modules/mob/living/login.dm
+++ b/code/modules/mob/living/login.dm
@@ -15,14 +15,14 @@
AddComponent(/datum/component/character_setup)
// Vore stuff
- verbs |= /mob/living/proc/escapeOOC
- verbs |= /mob/living/proc/lick
- verbs |= /mob/living/proc/smell
- verbs |= /mob/living/proc/switch_scaling
- verbs |= /mob/living/proc/center_offset
+ add_verb(src, /mob/living/proc/escapeOOC)
+ add_verb(src, /mob/living/proc/lick)
+ add_verb(src, /mob/living/proc/smell)
+ add_verb(src, /mob/living/proc/switch_scaling)
+ add_verb(src, /mob/living/proc/center_offset)
if(!no_vore)
- verbs |= /mob/living/proc/vorebelly_printout
+ add_verb(src, /mob/living/proc/vorebelly_printout)
if(!vorePanel)
AddComponent(/datum/component/vore_panel)
//VOREStation Add Start
diff --git a/code/modules/mob/living/silicon/ai/ai.dm b/code/modules/mob/living/silicon/ai/ai.dm
index 47bae9304a..a84a0dd80e 100644
--- a/code/modules/mob/living/silicon/ai/ai.dm
+++ b/code/modules/mob/living/silicon/ai/ai.dm
@@ -99,12 +99,12 @@ var/list/ai_verbs_default = list(
can_be_antagged = TRUE
/mob/living/silicon/ai/proc/add_ai_verbs()
- src.verbs |= ai_verbs_default
- src.verbs |= silicon_subsystems
+ add_verb(src, ai_verbs_default)
+ add_verb(src, silicon_subsystems)
/mob/living/silicon/ai/proc/remove_ai_verbs()
- src.verbs -= ai_verbs_default
- src.verbs -= silicon_subsystems
+ remove_verb(src, ai_verbs_default)
+ remove_verb(src, silicon_subsystems)
/mob/living/silicon/ai/New(loc, var/datum/ai_laws/L, var/obj/item/mmi/B, var/safety = 0)
announcement = new()
@@ -238,26 +238,27 @@ var/list/ai_verbs_default = list(
return ..()
-/mob/living/silicon/ai/Stat()
- ..()
- if(statpanel("Status"))
- if(!stat) // Make sure we're not unconscious/dead.
- stat(null, text("System integrity: [(health+100)/2]%"))
- stat(null, text("Connected synthetics: [connected_robots.len]"))
- for(var/mob/living/silicon/robot/R in connected_robots)
- var/robot_status = "Nominal"
- if(R.shell)
- robot_status = "AI SHELL"
- else if(R.stat || !R.client)
- robot_status = "OFFLINE"
- else if(!R.cell || R.cell.charge <= 0)
- robot_status = "DEPOWERED"
- //Name, Health, Battery, Module, Area, and Status! Everything an AI wants to know about its borgies!
- stat(null, text("[R.name] | S.Integrity: [R.health]% | Cell: [R.cell ? "[R.cell.charge]/[R.cell.maxcharge]" : "Empty"] | \
- Module: [R.modtype] | Loc: [get_area_name(R, TRUE)] | Status: [robot_status]"))
- stat(null, text("AI shell beacons detected: [LAZYLEN(GLOB.available_ai_shells)]")) //Count of total AI shells
- else
- stat(null, text("Systems nonfunctional"))
+
+/mob/living/silicon/ai/get_status_tab_items()
+ . = ..()
+ . += ""
+ if(!stat) // Make sure we're not unconscious/dead.
+ . += "System integrity: [(health+100)/2]%"
+ . += "Connected synthetics: [connected_robots.len]"
+ for(var/mob/living/silicon/robot/R in connected_robots)
+ var/robot_status = "Nominal"
+ if(R.shell)
+ robot_status = "AI SHELL"
+ else if(R.stat || !R.client)
+ robot_status = "OFFLINE"
+ else if(!R.cell || R.cell.charge <= 0)
+ robot_status = "DEPOWERED"
+ //Name, Health, Battery, Module, Area, and Status! Everything an AI wants to know about its borgies!
+ . += "[R.name] | S.Integrity: [R.health]% | Cell: [R.cell ? "[R.cell.charge]/[R.cell.maxcharge]" : "Empty"] | \
+ Module: [R.modtype] | Loc: [get_area_name(R, TRUE)] | Status: [robot_status]"
+ . += "AI shell beacons detected: [LAZYLEN(GLOB.available_ai_shells)]" //Count of total AI shells
+ else
+ . += "Systems nonfunctional"
/mob/living/silicon/ai/proc/setup_icon()
diff --git a/code/modules/mob/living/silicon/ai/ai_remote_control.dm b/code/modules/mob/living/silicon/ai/ai_remote_control.dm
index 53d1a3de35..adb410ab45 100644
--- a/code/modules/mob/living/silicon/ai/ai_remote_control.dm
+++ b/code/modules/mob/living/silicon/ai/ai_remote_control.dm
@@ -3,7 +3,7 @@
/mob/living/silicon/ai/Initialize()
if(config.allow_ai_shells)
- verbs += /mob/living/silicon/ai/proc/deploy_to_shell_act
+ add_verb(src, /mob/living/silicon/ai/proc/deploy_to_shell_act)
return ..()
/mob/living/silicon/ai/proc/deploy_to_shell(var/mob/living/silicon/robot/target)
diff --git a/code/modules/mob/living/silicon/ai/malf.dm b/code/modules/mob/living/silicon/ai/malf.dm
index a6034d649c..6727a983fa 100644
--- a/code/modules/mob/living/silicon/ai/malf.dm
+++ b/code/modules/mob/living/silicon/ai/malf.dm
@@ -10,9 +10,9 @@
hacked_apcs = list()
recalc_cpu()
- verbs += new/datum/game_mode/malfunction/verb/ai_select_hardware()
- verbs += new/datum/game_mode/malfunction/verb/ai_select_research()
- verbs += new/datum/game_mode/malfunction/verb/ai_help()
+ add_verb(src, new/datum/game_mode/malfunction/verb/ai_select_hardware())
+ add_verb(src, new/datum/game_mode/malfunction/verb/ai_select_research())
+ add_verb(src, new/datum/game_mode/malfunction/verb/ai_help())
// And greet user with some OOC info.
to_chat(user, "You are malfunctioning, you do not have to follow any laws.")
@@ -109,29 +109,31 @@
// Shows capacitor charge and hardware integrity information to the AI in Status tab.
/mob/living/silicon/ai/show_system_integrity()
+ . = ""
if(!src.stat)
- stat(null, text("Hardware integrity: [hardware_integrity()]%"))
- stat(null, text("Internal capacitor: [backup_capacitor()]%"))
+ . += "Hardware integrity: [hardware_integrity()]%"
+ . += "Internal capacitor: [backup_capacitor()]%"
else
- stat(null, text("Systems nonfunctional"))
+ . += "Systems nonfunctional"
// Shows AI Malfunction related information to the AI.
/mob/living/silicon/ai/show_malf_ai()
+ . = ""
if(src.is_malf())
if(src.hacked_apcs)
- stat(null, "Hacked APCs: [src.hacked_apcs.len]")
- stat(null, "System Status: [src.hacking ? "Busy" : "Stand-By"]")
+ . += "Hacked APCs: [src.hacked_apcs.len]"
+ . += "System Status: [src.hacking ? "Busy" : "Stand-By"]"
if(src.research)
- stat(null, "Available CPU: [src.research.stored_cpu] TFlops")
- stat(null, "Maximal CPU: [src.research.max_cpu] TFlops")
- stat(null, "CPU generation rate: [src.research.cpu_increase_per_tick * 10] TFlops/s")
- stat(null, "Current research focus: [src.research.focus ? src.research.focus.name : "None"]")
+ . += "Available CPU: [src.research.stored_cpu] TFlops"
+ . += "Maximal CPU: [src.research.max_cpu] TFlops"
+ . += "CPU generation rate: [src.research.cpu_increase_per_tick * 10] TFlops/s"
+ . += "Current research focus: [src.research.focus ? src.research.focus.name : "None"]"
if(src.research.focus)
- stat(null, "Research completed: [round(src.research.focus.invested, 0.1)]/[round(src.research.focus.price)]")
+ . += "Research completed: [round(src.research.focus.invested, 0.1)]/[round(src.research.focus.price)]"
if(system_override == 1)
- stat(null, "SYSTEM OVERRIDE INITIATED")
+ . += "SYSTEM OVERRIDE INITIATED"
else if(system_override == 2)
- stat(null, "SYSTEM OVERRIDE COMPLETED")
+ . += "SYSTEM OVERRIDE COMPLETED"
// Cleaner proc for creating powersupply for an AI.
/mob/living/silicon/ai/proc/create_powersupply()
diff --git a/code/modules/mob/living/silicon/pai/pai.dm b/code/modules/mob/living/silicon/pai/pai.dm
index 693bf7e0a3..01e37e9fa5 100644
--- a/code/modules/mob/living/silicon/pai/pai.dm
+++ b/code/modules/mob/living/silicon/pai/pai.dm
@@ -130,8 +130,8 @@
add_language(LANGUAGE_TERMINUS, 1)
add_language(LANGUAGE_SIGN, 1)
- verbs += /mob/living/silicon/pai/proc/choose_chassis
- verbs += /mob/living/silicon/pai/proc/choose_verbs
+ add_verb(src, /mob/living/silicon/pai/proc/choose_chassis)
+ add_verb(src, /mob/living/silicon/pai/proc/choose_verbs)
//PDA
pda = new(src)
@@ -157,16 +157,16 @@
// this function shows the information about being silenced as a pAI in the Status panel
/mob/living/silicon/pai/proc/show_silenced()
+ . = ""
if(src.silence_time)
var/timeleft = round((silence_time - world.timeofday)/10 ,1)
- stat(null, "Communications system reboot in -[(timeleft / 60) % 60]:[add_zero(num2text(timeleft % 60), 2)]")
+ . += "Communications system reboot in -[(timeleft / 60) % 60]:[add_zero(num2text(timeleft % 60), 2)]"
-/mob/living/silicon/pai/Stat()
- ..()
- statpanel("Status")
- if (src.client.statpanel == "Status")
- show_silenced()
+/mob/living/silicon/pai/get_status_tab_items()
+ . = ..()
+ . += ""
+ . += show_silenced()
/mob/living/silicon/pai/check_eye(var/mob/user as mob)
if (!src.current)
@@ -304,8 +304,8 @@
var/turf/T = get_turf(src)
if(istype(T)) T.visible_message(span_filter_notice("[src] folds outwards, expanding into a mobile form."))
- verbs |= /mob/living/silicon/pai/proc/pai_nom
- verbs |= /mob/living/proc/vertical_nom
+ add_verb(src, /mob/living/silicon/pai/proc/pai_nom)
+ add_verb(src, /mob/living/proc/vertical_nom)
update_icon()
/mob/living/silicon/pai/verb/fold_up()
@@ -340,7 +340,7 @@
finalized = tgui_alert(usr, "Look at your sprite. Is this what you wish to use?","Choose Chassis",list("No","Yes"))
chassis = possible_chassis[choice]
- verbs |= /mob/living/proc/hide
+ add_verb(src, /mob/living/proc/hide)
//VOREStation Removal End
*/
@@ -477,8 +477,8 @@
icon_state = "[chassis]"
if(isopenspace(card.loc))
fall()
- verbs -= /mob/living/silicon/pai/proc/pai_nom
- verbs -= /mob/living/proc/vertical_nom
+ remove_verb(src, /mob/living/silicon/pai/proc/pai_nom)
+ remove_verb(src, /mob/living/proc/vertical_nom)
// No binary for pAIs.
/mob/living/silicon/pai/binarycheck()
diff --git a/code/modules/mob/living/silicon/pai/pai_vr.dm b/code/modules/mob/living/silicon/pai/pai_vr.dm
index 22da511922..2e3c1ed1fe 100644
--- a/code/modules/mob/living/silicon/pai/pai_vr.dm
+++ b/code/modules/mob/living/silicon/pai/pai_vr.dm
@@ -71,10 +71,10 @@
/mob/living/silicon/pai/Initialize()
. = ..()
- verbs |= /mob/proc/dominate_predator
- verbs |= /mob/living/proc/dominate_prey
- verbs |= /mob/living/proc/set_size
- verbs |= /mob/living/proc/shred_limb
+ add_verb(src, /mob/proc/dominate_predator)
+ add_verb(src, /mob/living/proc/dominate_prey)
+ add_verb(src, /mob/living/proc/set_size)
+ add_verb(src, /mob/living/proc/shred_limb)
/mob/living/silicon/pai/Login()
. = ..()
diff --git a/code/modules/mob/living/silicon/robot/drone/drone.dm b/code/modules/mob/living/silicon/robot/drone/drone.dm
index 2379310a6e..ae1853ba9f 100644
--- a/code/modules/mob/living/silicon/robot/drone/drone.dm
+++ b/code/modules/mob/living/silicon/robot/drone/drone.dm
@@ -104,8 +104,8 @@ var/list/mob_hat_cache = list()
/mob/living/silicon/robot/drone/New()
..()
- verbs += /mob/living/proc/ventcrawl
- verbs += /mob/living/proc/hide
+ add_verb(src, /mob/living/proc/ventcrawl)
+ add_verb(src, /mob/living/proc/hide)
remove_language("Robot Talk")
add_language("Robot Talk", 0)
add_language("Drone Talk", 1)
@@ -123,7 +123,7 @@ var/list/mob_hat_cache = list()
var/datum/robot_component/C = components[V]
C.max_damage = 10
- verbs -= /mob/living/silicon/robot/verb/namepick
+ remove_verb(src, /mob/living/silicon/robot/verb/namepick)
if(can_pick_shell)
var/random = pick(shell_types)
@@ -146,7 +146,7 @@ var/list/mob_hat_cache = list()
/mob/living/silicon/robot/drone/Login()
. = ..()
if(can_pick_shell)
- to_chat(src, "You can select a shell using the 'Robot Commands' > 'Customize Appearance'")
+ to_chat(src, "You can select a shell using the 'Abilities.Silicon' > 'Customize Appearance'")
//Redefining some robot procs...
/mob/living/silicon/robot/drone/SetName(pickedName as text)
@@ -172,7 +172,7 @@ var/list/mob_hat_cache = list()
/mob/living/silicon/robot/drone/verb/pick_shell()
set name = "Customize Appearance"
- set category = "Robot Commands"
+ set category = "Abilities.Silicon"
if(!can_pick_shell)
to_chat(src, span_warning("You already selected a shell or this drone type isn't customizable."))
@@ -395,10 +395,10 @@ var/list/mob_hat_cache = list()
to_chat(src, "Use say ;Hello to talk to other drones and say Hello to speak silently to your nearby fellows.")
/mob/living/silicon/robot/drone/add_robot_verbs()
- src.verbs |= silicon_subsystems
+ add_verb(src, silicon_subsystems)
/mob/living/silicon/robot/drone/remove_robot_verbs()
- src.verbs -= silicon_subsystems
+ remove_verb(src, silicon_subsystems)
/mob/living/silicon/robot/drone/construction/welcome_drone()
to_chat(src, "You are a construction drone, an autonomous engineering and fabrication system..")
diff --git a/code/modules/mob/living/silicon/robot/drone/drone_abilities.dm b/code/modules/mob/living/silicon/robot/drone/drone_abilities.dm
index deaf9fb8b7..3a4bf3e0e2 100644
--- a/code/modules/mob/living/silicon/robot/drone/drone_abilities.dm
+++ b/code/modules/mob/living/silicon/robot/drone/drone_abilities.dm
@@ -2,7 +2,7 @@
/mob/living/silicon/robot/drone/verb/set_mail_tag()
set name = "Set Mail Tag"
set desc = "Tag yourself for delivery through the disposals system."
- set category = "Robot Commands"
+ set category = "Abilities.Silicon"
var/new_tag = tgui_input_list(usr, "Select the desired destination.", "Set Mail Tag", GLOB.tagger_locations)
diff --git a/code/modules/mob/living/silicon/robot/drone/drone_items.dm b/code/modules/mob/living/silicon/robot/drone/drone_items.dm
index 130716af91..aa5a5d6934 100644
--- a/code/modules/mob/living/silicon/robot/drone/drone_items.dm
+++ b/code/modules/mob/living/silicon/robot/drone/drone_items.dm
@@ -267,7 +267,7 @@
set name = "Drop Item"
set desc = "Release an item from your magnetic gripper."
- set category = "Robot Commands"
+ set category = "Abilities.Silicon"
drop_item()
diff --git a/code/modules/mob/living/silicon/robot/laws.dm b/code/modules/mob/living/silicon/robot/laws.dm
index 59a7160d4c..dec2b46875 100644
--- a/code/modules/mob/living/silicon/robot/laws.dm
+++ b/code/modules/mob/living/silicon/robot/laws.dm
@@ -1,5 +1,5 @@
/mob/living/silicon/robot/verb/cmd_show_laws()
- set category = "Robot Commands"
+ set category = "Abilities.Silicon"
set name = "Show Laws"
show_laws()
@@ -51,6 +51,6 @@
return
/mob/living/silicon/robot/proc/robot_checklaws()
- set category = "Robot Commands"
+ set category = "Abilities.Silicon"
set name = "State Laws"
subsystem_law_manager()
diff --git a/code/modules/mob/living/silicon/robot/robot.dm b/code/modules/mob/living/silicon/robot/robot.dm
index 20868b6d3e..8e8422e4fc 100644
--- a/code/modules/mob/living/silicon/robot/robot.dm
+++ b/code/modules/mob/living/silicon/robot/robot.dm
@@ -280,11 +280,13 @@
if (!rbPDA)
rbPDA = new/obj/item/pda/ai(src)
rbPDA.set_name_and_job(name,"[modtype] [braintype]")
+ add_verb(src, /obj/item/pda/ai/verb/cmd_pda_open_ui)
/mob/living/silicon/robot/proc/setup_communicator()
if (!communicator)
communicator = new/obj/item/communicator/integrated(src)
communicator.register_device(name, "[modtype] [braintype]")
+ add_verb(src, /obj/item/communicator/integrated/verb/activate)
//If there's an MMI in the robot, have it ejected when the mob goes away. --NEO
//Improved /N
@@ -424,7 +426,7 @@
/mob/living/silicon/robot/verb/namepick()
set name = "Pick Name"
- set category = "Robot Commands"
+ set category = "Abilities.Silicon"
if(custom_name)
to_chat(usr, "You can't pick another custom name. [isshell(src) ? "" : "Go ask for a name change."]")
@@ -442,7 +444,7 @@
/mob/living/silicon/robot/verb/extra_customization()
set name = "Customize Appearance"
- set category = "Robot Commands"
+ set category = "Abilities.Silicon"
set desc = "Customize your appearance (assuming your chosen sprite allows)."
if(!sprite_datum || !sprite_datum.has_extra_customization)
@@ -463,7 +465,7 @@
return dat
/mob/living/silicon/robot/verb/toggle_lights()
- set category = "Robot Commands"
+ set category = "Abilities.Silicon"
set name = "Toggle Lights"
lights_on = !lights_on
@@ -472,7 +474,7 @@
update_icon()
/mob/living/silicon/robot/verb/self_diagnosis_verb()
- set category = "Robot Commands"
+ set category = "Abilities.Silicon"
set name = "Self Diagnosis"
if(!is_component_functioning("diagnosis unit"))
@@ -486,7 +488,7 @@
/mob/living/silicon/robot/verb/toggle_component()
- set category = "Robot Commands"
+ set category = "Abilities.Silicon"
set name = "Toggle Component"
set desc = "Toggle a component, conserving power."
@@ -510,7 +512,7 @@
to_chat(src, span_red("You enable [C.name]."))
/mob/living/silicon/robot/verb/spark_plug() //So you can still sparkle on demand without violence.
- set category = "Robot Commands"
+ set category = "Abilities.Silicon"
set name = "Emit Sparks"
to_chat(src, span_filter_notice("You harmlessly spark."))
spark_system.start()
@@ -520,8 +522,8 @@
// if you have a jetpack, show the internal tank pressure
var/obj/item/tank/jetpack/current_jetpack = installed_jetpack()
if (current_jetpack)
- stat("Internal Atmosphere Info", current_jetpack.name)
- stat("Tank Pressure", current_jetpack.air_contents.return_pressure())
+ . = "Internal Atmosphere Info: [current_jetpack.name]"
+ . += "Tank Pressure: [current_jetpack.air_contents.return_pressure()]"
// this function returns the robots jetpack, if one is installed
@@ -534,11 +536,11 @@
// this function displays the cyborgs current cell charge in the stat panel
/mob/living/silicon/robot/proc/show_cell_power()
if(cell)
- stat(null, text("Charge Left: [round(cell.percent())]%"))
- stat(null, text("Cell Rating: [round(cell.maxcharge)]")) // Round just in case we somehow get crazy values
- stat(null, text("Power Cell Load: [round(used_power_this_tick)]W"))
+ . = "Charge Left: [round(cell.percent())]%"
+ . += "Cell Rating: [round(cell.maxcharge)]" // Round just in case we somehow get crazy values
+ . += "Power Cell Load: [round(used_power_this_tick)]W"
else
- stat(null, text("No Cell Inserted!"))
+ . = "No Cell Inserted!"
// function to toggle VTEC once installed
/mob/living/silicon/robot/proc/toggle_vtec()
@@ -549,15 +551,15 @@
to_chat(src, span_filter_notice("VTEC module [vtec_active ? "enabled" : "disabled"]."))
// update the status screen display
-/mob/living/silicon/robot/Stat()
- ..()
- if (statpanel("Status"))
- show_cell_power()
- show_jetpack_pressure()
- stat(null, text("Lights: [lights_on ? "ON" : "OFF"]"))
- if(module)
- for(var/datum/matter_synth/ms in module.synths)
- stat("[ms.name]: [ms.energy]/[ms.max_energy]")
+/mob/living/silicon/robot/get_status_tab_items()
+ . = ..()
+ . += ""
+ . += show_cell_power()
+ . += show_jetpack_pressure()
+ . += "Lights: [lights_on ? "ON" : "OFF"]"
+ if(module)
+ for(var/datum/matter_synth/ms in module.synths)
+ . += "[ms.name]: [ms.energy]/[ms.max_energy]"
/mob/living/silicon/robot/restrained()
return 0
@@ -843,7 +845,7 @@
/mob/living/silicon/robot/proc/ColorMate()
set name = "Recolour Module"
- set category = "Robot Commands"
+ set category = "Abilities.Silicon"
set desc = "Allows to recolour once."
if(!has_recoloured)
@@ -1191,7 +1193,7 @@
/mob/living/silicon/robot/proc/ResetSecurityCodes()
- set category = "Robot Commands"
+ set category = "Abilities.Silicon"
set name = "Reset Identity Codes"
set desc = "Scrambles your security and identification codes and resets your current buffers. Unlocks you and permenantly severs you from your AI and the robotics console and will deactivate your camera system."
@@ -1200,7 +1202,7 @@
if(R)
R.UnlinkSelf()
to_chat(R, span_filter_notice("Buffers flushed and reset. Camera system shutdown. All systems operational."))
- src.verbs -= /mob/living/silicon/robot/proc/ResetSecurityCodes
+ remove_verb(src, /mob/living/silicon/robot/proc/ResetSecurityCodes)
/mob/living/silicon/robot/proc/SetLockdown(var/state = 1)
// They stay locked down if their wire is cut.
@@ -1289,7 +1291,7 @@
/mob/living/silicon/robot/proc/sensor_mode() //Medical/Security HUD controller for borgs
set name = "Toggle Sensor Augmentation" //VOREStation Add
- set category = "Robot Commands"
+ set category = "Abilities.Silicon"
set desc = "Augment visual feed with internal sensor overlays."
sensor_type = !sensor_type //VOREStation Add
to_chat(usr, "You [sensor_type ? "enable" : "disable"] your sensors.") //VOREStation Add
@@ -1299,16 +1301,16 @@
return
/mob/living/silicon/robot/proc/add_robot_verbs()
- src.verbs |= robot_verbs_default
- src.verbs |= silicon_subsystems
+ add_verb(src, robot_verbs_default)
+ add_verb(src, silicon_subsystems)
if(config.allow_robot_recolor)
- src.verbs |= /mob/living/silicon/robot/proc/ColorMate
+ add_verb(src, /mob/living/silicon/robot/proc/ColorMate)
/mob/living/silicon/robot/proc/remove_robot_verbs()
- src.verbs -= robot_verbs_default
- src.verbs -= silicon_subsystems
+ remove_verb(src, robot_verbs_default)
+ remove_verb(src, silicon_subsystems)
if(config.allow_robot_recolor)
- src.verbs |= /mob/living/silicon/robot/proc/ColorMate
+ remove_verb(src, /mob/living/silicon/robot/proc/ColorMate)
// Uses power from cyborg's cell. Returns 1 on success or 0 on failure.
// Properly converts using CELLRATE now! Amount is in Joules.
diff --git a/code/modules/mob/living/silicon/robot/robot_modules/station.dm b/code/modules/mob/living/silicon/robot/robot_modules/station.dm
index def75b1dad..8f8c0757e0 100644
--- a/code/modules/mob/living/silicon/robot/robot_modules/station.dm
+++ b/code/modules/mob/living/silicon/robot/robot_modules/station.dm
@@ -167,10 +167,10 @@ var/global/list/robot_modules = list(
added_networks.Cut()
/obj/item/robot_module/proc/add_subsystems(var/mob/living/silicon/robot/R)
- R.verbs |= subsystems
+ add_verb(R, subsystems)
/obj/item/robot_module/proc/remove_subsystems(var/mob/living/silicon/robot/R)
- R.verbs -= subsystems
+ remove_verb(R, subsystems)
/obj/item/robot_module/proc/apply_status_flags(var/mob/living/silicon/robot/R)
if(!can_be_pushed)
diff --git a/code/modules/mob/living/silicon/robot/robot_remote_control.dm b/code/modules/mob/living/silicon/robot/robot_remote_control.dm
index a768b1f7b7..4f38630848 100644
--- a/code/modules/mob/living/silicon/robot/robot_remote_control.dm
+++ b/code/modules/mob/living/silicon/robot/robot_remote_control.dm
@@ -65,7 +65,7 @@ GLOBAL_LIST_EMPTY(available_ai_shells)
lawsync()
// Give button to leave.
- verbs += /mob/living/silicon/robot/proc/undeploy_act
+ add_verb(src, /mob/living/silicon/robot/proc/undeploy_act)
to_chat(AI, span_notice("You have connected to an AI Shell remotely, and are now in control of it.
\
To return to your core, use the Release Control verb."))
@@ -110,7 +110,7 @@ GLOBAL_LIST_EMPTY(available_ai_shells)
/mob/living/silicon/robot/proc/undeploy_act()
set name = "Release Control"
set desc = "Release control of a remote drone."
- set category = "Robot Commands"
+ set category = "Abilities.Silicon"
undeploy("Remote session terminated.")
diff --git a/code/modules/mob/living/silicon/robot/subtypes/thinktank/thinktank_module.dm b/code/modules/mob/living/silicon/robot/subtypes/thinktank/thinktank_module.dm
index 2175bb1db4..ebe112a4e8 100644
--- a/code/modules/mob/living/silicon/robot/subtypes/thinktank/thinktank_module.dm
+++ b/code/modules/mob/living/silicon/robot/subtypes/thinktank/thinktank_module.dm
@@ -25,7 +25,7 @@
/obj/item/robot_module/robot/platform/verb/set_eye_colour()
set name = "Set Eye Colour"
set desc = "Select an eye colour to use."
- set category = "Robot Commands"
+ set category = "Abilities.Silicon"
set src in usr
var/new_pupil_color = input(usr, "Select a pupil colour.", "Pupil Colour Selection") as color|null
diff --git a/code/modules/mob/living/silicon/robot/subtypes/thinktank/thinktank_storage.dm b/code/modules/mob/living/silicon/robot/subtypes/thinktank/thinktank_storage.dm
index c1cc9e770e..2a6c715edb 100644
--- a/code/modules/mob/living/silicon/robot/subtypes/thinktank/thinktank_storage.dm
+++ b/code/modules/mob/living/silicon/robot/subtypes/thinktank/thinktank_storage.dm
@@ -106,7 +106,7 @@
/mob/living/silicon/robot/platform/verb/drop_stored_atom_verb()
set name = "Eject Cargo"
- set category = "Robot Commands"
+ set category = "Abilities.Silicon"
set desc = "Drop something from your internal storage."
if(incapacitated())
diff --git a/code/modules/mob/living/silicon/silicon.dm b/code/modules/mob/living/silicon/silicon.dm
index e7f297b7fd..0e6540085e 100644
--- a/code/modules/mob/living/silicon/silicon.dm
+++ b/code/modules/mob/living/silicon/silicon.dm
@@ -130,30 +130,30 @@
// this function shows the health of the AI in the Status panel
/mob/living/silicon/proc/show_system_integrity()
if(!src.stat)
- stat(null, text("System integrity: [round((health/getMaxHealth())*100)]%"))
+ . = "System integrity: [round((health/getMaxHealth())*100)]%"
else
- stat(null, text("Systems nonfunctional"))
+ . = "Systems nonfunctional"
// This is a pure virtual function, it should be overwritten by all subclasses
/mob/living/silicon/proc/show_malf_ai()
- return 0
+ return ""
// this function displays the shuttles ETA in the status panel if the shuttle has been called
/mob/living/silicon/proc/show_emergency_shuttle_eta()
if(emergency_shuttle)
var/eta_status = emergency_shuttle.get_status_panel_eta()
if(eta_status)
- stat(null, eta_status)
+ . = "[eta_status]"
// This adds the basic clock, shuttle recall timer, and malf_ai info to all silicon lifeforms
-/mob/living/silicon/Stat()
- if(statpanel("Status"))
- show_emergency_shuttle_eta()
- show_system_integrity()
- show_malf_ai()
- ..()
+/mob/living/silicon/get_status_tab_items()
+ . = ..()
+ . += ""
+ . += show_emergency_shuttle_eta()
+ . += show_system_integrity()
+ . += show_malf_ai()
/* VOREStation Removal
// this function displays the stations manifest in a separate window
diff --git a/code/modules/mob/living/silicon/subystems.dm b/code/modules/mob/living/silicon/subystems.dm
index 6c46ecb2e8..e2d82f6fdf 100644
--- a/code/modules/mob/living/silicon/subystems.dm
+++ b/code/modules/mob/living/silicon/subystems.dm
@@ -51,7 +51,7 @@
********************/
/mob/living/silicon/proc/subsystem_alarm_monitor()
set name = "Alarm Monitor"
- set category = "Subystems"
+ set category = "Abilities.Silicon"
alarm_monitor.tgui_interact(usr)
@@ -59,7 +59,7 @@
* Atmos Control *
********************/
/mob/living/silicon/proc/subsystem_atmos_control()
- set category = "Subystems"
+ set category = "Abilities.Silicon"
set name = "Atmospherics Control"
atmos_control.tgui_interact(usr)
@@ -68,7 +68,7 @@
* Crew Manifest *
********************/
/mob/living/silicon/proc/subsystem_crew_manifest()
- set category = "Subystems"
+ set category = "Abilities.Silicon"
set name = "Crew Manifest"
crew_manifest.tgui_interact(usr)
@@ -77,7 +77,7 @@
* Crew Monitor *
********************/
/mob/living/silicon/proc/subsystem_crew_monitor()
- set category = "Subystems"
+ set category = "Abilities.Silicon"
set name = "Crew Monitor"
crew_monitor.tgui_interact(usr)
@@ -87,7 +87,7 @@
****************/
/mob/living/silicon/proc/subsystem_law_manager()
set name = "Law Manager"
- set category = "Subystems"
+ set category = "Abilities.Silicon"
law_manager.tgui_interact(usr)
@@ -95,7 +95,7 @@
* Power Monitor *
********************/
/mob/living/silicon/proc/subsystem_power_monitor()
- set category = "Subystems"
+ set category = "Abilities.Silicon"
set name = "Power Monitor"
power_monitor.tgui_interact(usr)
@@ -104,7 +104,7 @@
* RCON *
************/
/mob/living/silicon/proc/subsystem_rcon()
- set category = "Subystems"
+ set category = "Abilities.Silicon"
set name = "RCON"
rcon.tgui_interact(usr)
diff --git a/code/modules/mob/living/simple_mob/simple_mob.dm b/code/modules/mob/living/simple_mob/simple_mob.dm
index 8808f30f4b..929834fd52 100644
--- a/code/modules/mob/living/simple_mob/simple_mob.dm
+++ b/code/modules/mob/living/simple_mob/simple_mob.dm
@@ -180,7 +180,7 @@
var/isthermal = 0
/mob/living/simple_mob/Initialize()
- verbs -= /mob/verb/observe
+ remove_verb(src, /mob/verb/observe)
health = maxHealth
if(ID_provided) //VOREStation Edit
@@ -199,7 +199,7 @@
organ_names = GET_DECL(organ_names)
if(config.allow_simple_mob_recolor)
- verbs |= /mob/living/simple_mob/proc/ColorMate
+ add_verb(src, /mob/living/simple_mob/proc/ColorMate)
return ..()
@@ -226,7 +226,7 @@
. = ..()
to_chat(src,"You are \the [src]. [player_msg]")
if(hasthermals)
- verbs |= /mob/living/simple_mob/proc/hunting_vision //So that maint preds can see prey through walls, to make it easier to find them.
+ add_verb(src, /mob/living/simple_mob/proc/hunting_vision) //So that maint preds can see prey through walls, to make it easier to find them.
/mob/living/simple_mob/SelfMove(turf/n, direct, movetime)
var/turf/old_turf = get_turf(src)
@@ -286,11 +286,10 @@
. += ..()
-
-/mob/living/simple_mob/Stat()
- ..()
- if(statpanel("Status") && show_stat_health)
- stat(null, "Health: [round((health / getMaxHealth()) * 100)]%")
+/mob/living/simple_mob/get_status_tab_items()
+ . = ..()
+ . += ""
+ . += "Health: [round((health / getMaxHealth()) * 100)]%"
/mob/living/simple_mob/lay_down()
..()
diff --git a/code/modules/mob/living/simple_mob/simple_mob_vr.dm b/code/modules/mob/living/simple_mob/simple_mob_vr.dm
index c2d9f723d3..0b3c1214a2 100644
--- a/code/modules/mob/living/simple_mob/simple_mob_vr.dm
+++ b/code/modules/mob/living/simple_mob/simple_mob_vr.dm
@@ -212,16 +212,16 @@
return
if(!IsAdvancedToolUser())
- verbs |= /mob/living/simple_mob/proc/animal_nom
- verbs |= /mob/living/proc/shred_limb
+ add_verb(src, /mob/living/simple_mob/proc/animal_nom)
+ add_verb(src, /mob/living/proc/shred_limb)
if(LAZYLEN(vore_organs))
return
// Since they have bellies, add verbs to toggle settings on them.
- verbs |= /mob/living/simple_mob/proc/toggle_digestion
- verbs |= /mob/living/simple_mob/proc/toggle_fancygurgle
- verbs |= /mob/living/proc/vertical_nom
+ add_verb(src, /mob/living/simple_mob/proc/toggle_digestion)
+ add_verb(src, /mob/living/simple_mob/proc/toggle_fancygurgle)
+ add_verb(src, /mob/living/proc/vertical_nom)
//A much more detailed version of the default /living implementation
var/obj/belly/B = new /obj/belly(src)
diff --git a/code/modules/mob/living/simple_mob/subtypes/animal/alien animals/catslug.dm b/code/modules/mob/living/simple_mob/subtypes/animal/alien animals/catslug.dm
index 164257a4c7..b475967713 100644
--- a/code/modules/mob/living/simple_mob/subtypes/animal/alien animals/catslug.dm
+++ b/code/modules/mob/living/simple_mob/subtypes/animal/alien animals/catslug.dm
@@ -137,9 +137,9 @@
/mob/living/simple_mob/vore/alienanimals/catslug/Initialize()
. = ..()
- verbs += /mob/living/proc/ventcrawl
- verbs += /mob/living/proc/hide
- verbs += /mob/living/simple_mob/vore/alienanimals/catslug/proc/catslug_color
+ add_verb(src, /mob/living/proc/ventcrawl)
+ add_verb(src, /mob/living/proc/hide)
+ add_verb(src, /mob/living/simple_mob/vore/alienanimals/catslug/proc/catslug_color)
/mob/living/simple_mob/vore/alienanimals/catslug/Destroy()
if(hat)
@@ -358,9 +358,9 @@
/mob/living/simple_mob/vore/alienanimals/catslug/custom/Initialize()
. = ..()
- verbs += /mob/living/proc/ventcrawl
- verbs += /mob/living/proc/hide
- verbs -= /mob/living/simple_mob/vore/alienanimals/catslug/proc/catslug_color //Most of these have custom sprites with colour already, so we'll not let them have this.
+ add_verb(src, /mob/living/proc/ventcrawl)
+ add_verb(src, /mob/living/proc/hide)
+ remove_verb(src, /mob/living/simple_mob/vore/alienanimals/catslug/proc/catslug_color) //Most of these have custom sprites with colour already, so we'll not let them have this.
/datum/category_item/catalogue/fauna/catslug/custom/spaceslug
@@ -1080,7 +1080,7 @@
/mob/living/simple_mob/vore/alienanimals/catslug/suslug/Initialize()
. = ..()
- verbs += /mob/living/simple_mob/vore/alienanimals/catslug/suslug/proc/assussinate
+ add_verb(src, /mob/living/simple_mob/vore/alienanimals/catslug/suslug/proc/assussinate)
update_icon()
/mob/living/simple_mob/vore/alienanimals/catslug/suslug/update_icon()
diff --git a/code/modules/mob/living/simple_mob/subtypes/animal/alien animals/stardog.dm b/code/modules/mob/living/simple_mob/subtypes/animal/alien animals/stardog.dm
index 05e52f6676..d46e5f0e37 100644
--- a/code/modules/mob/living/simple_mob/subtypes/animal/alien animals/stardog.dm
+++ b/code/modules/mob/living/simple_mob/subtypes/animal/alien animals/stardog.dm
@@ -69,8 +69,8 @@
/mob/living/simple_mob/vore/overmap/stardog/Login()
. = ..()
- verbs -= /mob/living/simple_mob/proc/set_name
- verbs -= /mob/living/simple_mob/proc/set_desc
+ remove_verb(src, /mob/living/simple_mob/proc/set_name)
+ remove_verb(src, /mob/living/simple_mob/proc/set_desc)
/mob/living/simple_mob/vore/overmap/stardog/attack_hand(mob/living/user)
if(!(user.pickup_pref && user.pickup_active))
@@ -164,10 +164,10 @@
weather_areas -= anything
return ..()
-/mob/living/simple_mob/vore/overmap/stardog/Stat()
- ..()
- if(statpanel("Status"))
- stat(null, "Affinity: [round(affinity)]")
+/mob/living/simple_mob/vore/overmap/stardog/get_status_tab_items()
+ . = ..()
+ . += ""
+ . += "Affinity: [round(affinity)]"
/mob/living/simple_mob/vore/overmap/stardog/start_pulling(var/atom/movable/AM)
if(!istype(loc, /turf/unsimulated/map)) //Don't pull stuff on the overmap
diff --git a/code/modules/mob/living/simple_mob/subtypes/animal/alien animals/teppi.dm b/code/modules/mob/living/simple_mob/subtypes/animal/alien animals/teppi.dm
index 28c824dc51..70c907aed4 100644
--- a/code/modules/mob/living/simple_mob/subtypes/animal/alien animals/teppi.dm
+++ b/code/modules/mob/living/simple_mob/subtypes/animal/alien animals/teppi.dm
@@ -333,11 +333,11 @@ GLOBAL_VAR_INIT(teppi_count, 0) // How mant teppi DO we have?
real_name = name
if(!teppi_adult)
nutrition = 0
- verbs += /mob/living/proc/ventcrawl
- verbs += /mob/living/proc/hide
+ add_verb(src, /mob/living/proc/ventcrawl)
+ add_verb(src, /mob/living/proc/hide)
else
- verbs += /mob/living/simple_mob/vore/alienanimals/teppi/proc/produce_offspring
- verbs += /mob/living/simple_mob/vore/alienanimals/teppi/proc/toggle_producing_offspring
+ add_verb(src, /mob/living/simple_mob/vore/alienanimals/teppi/proc/produce_offspring)
+ add_verb(src, /mob/living/simple_mob/vore/alienanimals/teppi/proc/toggle_producing_offspring)
// teppi_id = rand(1,100000)
diff --git a/code/modules/mob/living/simple_mob/subtypes/animal/borer/borer.dm b/code/modules/mob/living/simple_mob/subtypes/animal/borer/borer.dm
index 19c817dc67..779e871695 100644
--- a/code/modules/mob/living/simple_mob/subtypes/animal/borer/borer.dm
+++ b/code/modules/mob/living/simple_mob/subtypes/animal/borer/borer.dm
@@ -57,8 +57,8 @@
/mob/living/simple_mob/animal/borer/Initialize()
add_language("Cortical Link")
- verbs += /mob/living/proc/ventcrawl
- verbs += /mob/living/proc/hide
+ add_verb(src, /mob/living/proc/ventcrawl)
+ add_verb(src, /mob/living/proc/hide)
true_name = "[pick("Primary","Secondary","Tertiary","Quaternary")] [rand(1000,9999)]"
@@ -99,15 +99,9 @@
if(prob(host.brainloss/20))
host.say("*[pick(list("blink","blink_r","choke","aflap","drool","twitch","twitch_v","gasp"))]")
-/mob/living/simple_mob/animal/borer/Stat()
- ..()
- if(client.statpanel == "Status")
- statpanel("Status")
- if(emergency_shuttle)
- var/eta_status = emergency_shuttle.get_status_panel_eta()
- if(eta_status)
- stat(null, eta_status)
- stat("Chemicals", chemicals)
+/mob/living/simple_mob/animal/borer/get_status_tab_items()
+ . = ..()
+ . += "Chemicals: [chemicals]"
/mob/living/simple_mob/animal/borer/proc/detatch()
if(!host || !controlling)
@@ -122,9 +116,9 @@
controlling = FALSE
host.remove_language("Cortical Link")
- host.verbs -= /mob/living/carbon/proc/release_control
- host.verbs -= /mob/living/carbon/proc/punish_host
- host.verbs -= /mob/living/carbon/proc/spawn_larvae
+ remove_verb(host, /mob/living/carbon/proc/release_control)
+ remove_verb(host, /mob/living/carbon/proc/punish_host)
+ remove_verb(host, /mob/living/carbon/proc/spawn_larvae)
if(host_brain)
// these are here so bans and multikey warnings are not triggered on the wrong people when ckey is changed.
diff --git a/code/modules/mob/living/simple_mob/subtypes/animal/borer/borer_captive.dm b/code/modules/mob/living/simple_mob/subtypes/animal/borer/borer_captive.dm
index 0053f4207d..208a52ac37 100644
--- a/code/modules/mob/living/simple_mob/subtypes/animal/borer/borer_captive.dm
+++ b/code/modules/mob/living/simple_mob/subtypes/animal/borer/borer_captive.dm
@@ -55,9 +55,9 @@
to_chat(H, span_danger("With an immense exertion of will, you regain control of your body!"))
to_chat(B.host, span_danger("You feel control of the host brain ripped from your grasp, and retract your probosci before the wild neural impulses can damage you."))
B.detatch()
- verbs -= /mob/living/carbon/proc/release_control
- verbs -= /mob/living/carbon/proc/punish_host
- verbs -= /mob/living/carbon/proc/spawn_larvae
+ remove_verb(src, /mob/living/carbon/proc/release_control)
+ remove_verb(src, /mob/living/carbon/proc/punish_host)
+ remove_verb(src, /mob/living/carbon/proc/spawn_larvae)
return
diff --git a/code/modules/mob/living/simple_mob/subtypes/animal/borer/borer_powers.dm b/code/modules/mob/living/simple_mob/subtypes/animal/borer/borer_powers.dm
index b31f8d0dcb..d5e25461f1 100644
--- a/code/modules/mob/living/simple_mob/subtypes/animal/borer/borer_powers.dm
+++ b/code/modules/mob/living/simple_mob/subtypes/animal/borer/borer_powers.dm
@@ -165,12 +165,12 @@
H.add_language("Cortical Link")
if(host.stat == 2)
- H.verbs |= /mob/living/carbon/human/proc/jumpstart
+ add_verb(H, /mob/living/carbon/human/proc/jumpstart)
- H.verbs |= /mob/living/carbon/human/proc/psychic_whisper
- H.verbs |= /mob/living/carbon/human/proc/tackle
+ add_verb(H, /mob/living/carbon/human/proc/psychic_whisper)
+ add_verb(H, /mob/living/carbon/human/proc/tackle)
if(antag)
- H.verbs |= /mob/living/carbon/proc/spawn_larvae
+ add_verb(H, /mob/living/carbon/proc/spawn_larvae)
if(H.client)
H.ghostize(0)
@@ -331,10 +331,10 @@
controlling = 1
- host.verbs += /mob/living/carbon/proc/release_control
- host.verbs += /mob/living/carbon/proc/punish_host
+ add_verb(host, /mob/living/carbon/proc/release_control)
+ add_verb(host, /mob/living/carbon/proc/punish_host)
if(antag)
- host.verbs += /mob/living/carbon/proc/spawn_larvae
+ add_verb(host, /mob/living/carbon/proc/spawn_larvae)
return
@@ -347,7 +347,7 @@
to_chat(usr, "Your host is already alive.")
return
- verbs -= /mob/living/carbon/human/proc/jumpstart
+ remove_verb(src, /mob/living/carbon/human/proc/jumpstart)
visible_message(span_warning("With a hideous, rattling moan, [src] shudders back to life!"))
rejuvenate()
diff --git a/code/modules/mob/living/simple_mob/subtypes/animal/passive/mouse.dm b/code/modules/mob/living/simple_mob/subtypes/animal/passive/mouse.dm
index 844cd29559..b3bb907c9c 100644
--- a/code/modules/mob/living/simple_mob/subtypes/animal/passive/mouse.dm
+++ b/code/modules/mob/living/simple_mob/subtypes/animal/passive/mouse.dm
@@ -47,8 +47,8 @@
/mob/living/simple_mob/animal/passive/mouse/New()
..()
- verbs += /mob/living/proc/ventcrawl
- verbs += /mob/living/proc/hide
+ add_verb(src, /mob/living/proc/ventcrawl)
+ add_verb(src, /mob/living/proc/hide)
if(name == initial(name))
name = "[name] ([rand(1, 1000)])"
diff --git a/code/modules/mob/living/simple_mob/subtypes/animal/passive/possum.dm b/code/modules/mob/living/simple_mob/subtypes/animal/passive/possum.dm
index f3696edd33..5a78b61690 100644
--- a/code/modules/mob/living/simple_mob/subtypes/animal/passive/possum.dm
+++ b/code/modules/mob/living/simple_mob/subtypes/animal/passive/possum.dm
@@ -185,8 +185,8 @@
/mob/living/simple_mob/animal/passive/opossum/Initialize()
. = ..()
- verbs += /mob/living/proc/ventcrawl
- verbs += /mob/living/proc/hide
+ add_verb(src, /mob/living/proc/ventcrawl)
+ add_verb(src, /mob/living/proc/hide)
/mob/living/simple_mob/animal/passive/opossum/poppy
name = "Poppy the Safety Possum"
diff --git a/code/modules/mob/living/simple_mob/subtypes/animal/sif/frostfly.dm b/code/modules/mob/living/simple_mob/subtypes/animal/sif/frostfly.dm
index 0a5b21b0da..9e9f4782d6 100644
--- a/code/modules/mob/living/simple_mob/subtypes/animal/sif/frostfly.dm
+++ b/code/modules/mob/living/simple_mob/subtypes/animal/sif/frostfly.dm
@@ -85,8 +85,8 @@
/mob/living/simple_mob/animal/sif/frostfly/Initialize()
. = ..()
smoke_special = new
- verbs += /mob/living/proc/ventcrawl
- verbs += /mob/living/proc/hide
+ add_verb(src, /mob/living/proc/ventcrawl)
+ add_verb(src, /mob/living/proc/hide)
/datum/say_list/frostfly
speak = list("Zzzz.", "Kss.", "Zzt?")
@@ -110,15 +110,9 @@
if(energy < max_energy)
energy++
-/mob/living/simple_mob/animal/sif/frostfly/Stat()
- ..()
- if(client.statpanel == "Status")
- statpanel("Status")
- if(emergency_shuttle)
- var/eta_status = emergency_shuttle.get_status_panel_eta()
- if(eta_status)
- stat(null, eta_status)
- stat("Energy", energy)
+/mob/living/simple_mob/animal/sif/frostfly/get_status_tab_items()
+ . = ..()
+ . += "Energy: [energy]"
/mob/living/simple_mob/animal/sif/frostfly/should_special_attack(atom/A)
if(energy >= 20)
diff --git a/code/modules/mob/living/simple_mob/subtypes/animal/sif/grafadreka.dm b/code/modules/mob/living/simple_mob/subtypes/animal/sif/grafadreka.dm
index cf1ec313cd..7e3d0c2ab7 100644
--- a/code/modules/mob/living/simple_mob/subtypes/animal/sif/grafadreka.dm
+++ b/code/modules/mob/living/simple_mob/subtypes/animal/sif/grafadreka.dm
@@ -526,11 +526,10 @@ var/global/list/wounds_being_tended_by_drakes = list()
else
remove_modifiers_of_type(/datum/modifier/ace)
-/mob/living/simple_mob/animal/sif/grafadreka/Stat()
+/mob/living/simple_mob/animal/sif/grafadreka/get_status_tab_items()
. = ..()
- if(statpanel("Status"))
- stat("Nutrition:", "[nutrition]/[max_nutrition]")
- stat("Stored sap:", "[stored_sap]/[max_stored_sap]")
+ . += "Nutrition: [nutrition]/[max_nutrition]"
+ . += "Stored sap: [stored_sap]/[max_stored_sap]"
/mob/living/simple_mob/animal/sif/grafadreka/proc/can_bite(var/mob/living/M)
return istype(M) && (M.lying || M.confused || M.incapacitated())
diff --git a/code/modules/mob/living/simple_mob/subtypes/animal/sif/leech.dm b/code/modules/mob/living/simple_mob/subtypes/animal/sif/leech.dm
index 73403e6c76..5e45548393 100644
--- a/code/modules/mob/living/simple_mob/subtypes/animal/sif/leech.dm
+++ b/code/modules/mob/living/simple_mob/subtypes/animal/sif/leech.dm
@@ -119,18 +119,12 @@
/mob/living/simple_mob/animal/sif/leech/Initialize()
. = ..()
- verbs += /mob/living/proc/ventcrawl
- verbs += /mob/living/proc/hide
+ add_verb(src, /mob/living/proc/ventcrawl)
+ add_verb(src, /mob/living/proc/hide)
-/mob/living/simple_mob/animal/sif/leech/Stat()
- ..()
- if(client.statpanel == "Status")
- statpanel("Status")
- if(emergency_shuttle)
- var/eta_status = emergency_shuttle.get_status_panel_eta()
- if(eta_status)
- stat(null, eta_status)
- stat("Chemicals", chemicals)
+/mob/living/simple_mob/animal/sif/leech/get_status_tab_items()
+ . = ..()
+ . += "Chemicals: [chemicals]"
/mob/living/simple_mob/animal/sif/leech/do_special_attack(atom/A)
. = TRUE
diff --git a/code/modules/mob/living/simple_mob/subtypes/animal/sif/moth.dm b/code/modules/mob/living/simple_mob/subtypes/animal/sif/moth.dm
index 12d8d9e0fe..5c59c2b7b1 100644
--- a/code/modules/mob/living/simple_mob/subtypes/animal/sif/moth.dm
+++ b/code/modules/mob/living/simple_mob/subtypes/animal/sif/moth.dm
@@ -119,8 +119,8 @@
/mob/living/simple_mob/animal/sif/tymisian/Initialize()
. = ..()
smoke_spore = new
- verbs += /mob/living/proc/ventcrawl
- verbs += /mob/living/proc/hide
+ add_verb(src, /mob/living/proc/ventcrawl)
+ add_verb(src, /mob/living/proc/hide)
/mob/living/simple_mob/animal/sif/tymisian/handle_special()
..()
@@ -128,15 +128,9 @@
if(energy < max_energy)
energy++
-/mob/living/simple_mob/animal/sif/tymisian/Stat()
- ..()
- if(client.statpanel == "Status")
- statpanel("Status")
- if(emergency_shuttle)
- var/eta_status = emergency_shuttle.get_status_panel_eta()
- if(eta_status)
- stat(null, eta_status)
- stat("Energy", energy)
+/mob/living/simple_mob/animal/sif/tymisian/get_status_tab_items()
+ . = ..()
+ . += "Energy: [energy]"
/mob/living/simple_mob/animal/sif/tymisian/should_special_attack(atom/A)
if(energy >= 20)
diff --git a/code/modules/mob/living/simple_mob/subtypes/animal/sif/racoon.dm b/code/modules/mob/living/simple_mob/subtypes/animal/sif/racoon.dm
index 02baeeda89..a2ba7d3431 100644
--- a/code/modules/mob/living/simple_mob/subtypes/animal/sif/racoon.dm
+++ b/code/modules/mob/living/simple_mob/subtypes/animal/sif/racoon.dm
@@ -153,8 +153,8 @@
/mob/living/simple_mob/animal/sif/sakimm/Initialize()
. = ..()
- verbs += /mob/living/proc/ventcrawl
- verbs += /mob/living/proc/hide
+ add_verb(src, /mob/living/proc/ventcrawl)
+ add_verb(src, /mob/living/proc/hide)
if(randomize_size)
adjust_scale(rand(8, 11) / 10)
diff --git a/code/modules/mob/living/simple_mob/subtypes/slime/slime.dm b/code/modules/mob/living/simple_mob/subtypes/slime/slime.dm
index 383c25a395..861bb28582 100644
--- a/code/modules/mob/living/simple_mob/subtypes/slime/slime.dm
+++ b/code/modules/mob/living/simple_mob/subtypes/slime/slime.dm
@@ -91,7 +91,7 @@ var/list/_slime_default_emotes = list(
emote_hear = list("squishes")
/mob/living/simple_mob/slime/Initialize()
- verbs += /mob/living/proc/ventcrawl
+ add_verb(src, /mob/living/proc/ventcrawl)
update_mood()
glow_color = color
handle_light()
diff --git a/code/modules/mob/living/simple_mob/subtypes/vore/bigdragon.dm b/code/modules/mob/living/simple_mob/subtypes/vore/bigdragon.dm
index b22b06e29f..d3fc35c3c3 100644
--- a/code/modules/mob/living/simple_mob/subtypes/vore/bigdragon.dm
+++ b/code/modules/mob/living/simple_mob/subtypes/vore/bigdragon.dm
@@ -240,15 +240,15 @@ I think I covered everything.
. = ..()
if(!riding_datum)
riding_datum = new /datum/riding/simple_mob(src)
- verbs |= /mob/living/simple_mob/proc/animal_mount
- verbs |= /mob/living/proc/toggle_rider_reins
- verbs |= /mob/living/simple_mob/vore/bigdragon/proc/set_style
- verbs |= /mob/living/simple_mob/vore/bigdragon/proc/toggle_glow
- verbs |= /mob/living/simple_mob/vore/bigdragon/proc/sprite_toggle
- verbs |= /mob/living/simple_mob/vore/bigdragon/proc/flame_toggle
- verbs |= /mob/living/simple_mob/vore/bigdragon/proc/special_toggle
- //verbs |= /mob/living/simple_mob/vore/bigdragon/proc/set_name //Implemented upstream
- //verbs |= /mob/living/simple_mob/vore/bigdragon/proc/set_desc //Implemented upstream
+ add_verb(src, /mob/living/simple_mob/proc/animal_mount)
+ add_verb(src, /mob/living/proc/toggle_rider_reins)
+ add_verb(src, /mob/living/simple_mob/vore/bigdragon/proc/set_style)
+ add_verb(src, /mob/living/simple_mob/vore/bigdragon/proc/toggle_glow)
+ add_verb(src, /mob/living/simple_mob/vore/bigdragon/proc/sprite_toggle)
+ add_verb(src, /mob/living/simple_mob/vore/bigdragon/proc/flame_toggle)
+ add_verb(src, /mob/living/simple_mob/vore/bigdragon/proc/special_toggle)
+ //add_verb(src, /mob/living/simple_mob/vore/bigdragon/proc/set_name) //Implemented upstream
+ //add_verb(src, /mob/living/simple_mob/vore/bigdragon/proc/set_desc) //Implemented upstream
faction = FACTION_NEUTRAL
/mob/living/simple_mob/vore/bigdragon/Initialize()
diff --git a/code/modules/mob/living/simple_mob/subtypes/vore/corrupt_hounds.dm b/code/modules/mob/living/simple_mob/subtypes/vore/corrupt_hounds.dm
index 4326d048dd..abd7cdf105 100644
--- a/code/modules/mob/living/simple_mob/subtypes/vore/corrupt_hounds.dm
+++ b/code/modules/mob/living/simple_mob/subtypes/vore/corrupt_hounds.dm
@@ -113,8 +113,8 @@
. = ..()
if(!riding_datum)
riding_datum = new /datum/riding/simple_mob(src)
- verbs |= /mob/living/simple_mob/proc/animal_mount
- verbs |= /mob/living/proc/toggle_rider_reins
+ add_verb(src, /mob/living/simple_mob/proc/animal_mount)
+ add_verb(src, /mob/living/proc/toggle_rider_reins)
movement_cooldown = 0
/mob/living/simple_mob/vore/aggressive/corrupthound/MouseDrop_T(mob/living/M, mob/living/user)
diff --git a/code/modules/mob/living/simple_mob/subtypes/vore/cryptdrake.dm b/code/modules/mob/living/simple_mob/subtypes/vore/cryptdrake.dm
index bad9f2dde3..0e931f9832 100644
--- a/code/modules/mob/living/simple_mob/subtypes/vore/cryptdrake.dm
+++ b/code/modules/mob/living/simple_mob/subtypes/vore/cryptdrake.dm
@@ -64,8 +64,8 @@
. = ..()
if(!riding_datum)
riding_datum = new /datum/riding/simple_mob(src)
- verbs |= /mob/living/simple_mob/proc/animal_mount
- verbs |= /mob/living/proc/toggle_rider_reins
+ add_verb(src, /mob/living/simple_mob/proc/animal_mount)
+ add_verb(src, /mob/living/proc/toggle_rider_reins)
movement_cooldown = -1
/mob/living/simple_mob/vore/cryptdrake/init_vore()
diff --git a/code/modules/mob/living/simple_mob/subtypes/vore/deathclaw.dm b/code/modules/mob/living/simple_mob/subtypes/vore/deathclaw.dm
index 133e29d632..dbb629cbdd 100644
--- a/code/modules/mob/living/simple_mob/subtypes/vore/deathclaw.dm
+++ b/code/modules/mob/living/simple_mob/subtypes/vore/deathclaw.dm
@@ -74,8 +74,8 @@
. = ..()
if(!riding_datum)
riding_datum = new /datum/riding/simple_mob(src)
- verbs |= /mob/living/simple_mob/proc/animal_mount
- verbs |= /mob/living/proc/toggle_rider_reins
+ add_verb(src, /mob/living/simple_mob/proc/animal_mount)
+ add_verb(src, /mob/living/proc/toggle_rider_reins)
movement_cooldown = 0
/mob/living/simple_mob/vore/aggressive/deathclaw/MouseDrop_T(mob/living/M, mob/living/user)
diff --git a/code/modules/mob/living/simple_mob/subtypes/vore/dominated_brain.dm b/code/modules/mob/living/simple_mob/subtypes/vore/dominated_brain.dm
index fed12356a1..79f2432c44 100644
--- a/code/modules/mob/living/simple_mob/subtypes/vore/dominated_brain.dm
+++ b/code/modules/mob/living/simple_mob/subtypes/vore/dominated_brain.dm
@@ -32,7 +32,7 @@
return
. = ..()
lets_register_our_signals()
- verbs |= /mob/living/dominated_brain/proc/resist_control
+ add_verb(src, /mob/living/dominated_brain/proc/resist_control)
/mob/living/dominated_brain/Life()
. = ..()
@@ -114,7 +114,7 @@
prey_goes_here.ooc_notes = prey_ooc_notes
prey_goes_here.ooc_notes_likes = prey_ooc_likes
prey_goes_here.ooc_notes_dislikes = prey_ooc_dislikes
- prey_goes_here.verbs |= /mob/living/dominated_brain/proc/cease_this_foolishness
+ add_verb(prey_goes_here, /mob/living/dominated_brain/proc/cease_this_foolishness)
else //The prey body does not exist, let's put them in the back seat instead!
@@ -134,7 +134,7 @@
///////////////////
// Handle Pred
- pred_body.verbs -= /mob/proc/release_predator
+ remove_verb(pred_body, /mob/proc/release_predator)
//Now actually put the people in the mobs
prey_goes_here.ckey = src.prey_ckey
@@ -166,7 +166,7 @@
langlist -= languages
for(var/datum/language/L in langlist)
if(L.flags & HIVEMIND)
- verbs |= /mob/proc/adjust_hive_range
+ add_verb(src, /mob/proc/adjust_hive_range)
temp_languages |= langlist
languages |= langlist
@@ -259,7 +259,7 @@
pred.ooc_notes_likes = pred_brain.prey_ooc_likes
pred.ooc_notes_dislikes = pred_brain.prey_ooc_dislikes
- pred.verbs |= /mob/proc/release_predator
+ add_verb(pred, /mob/proc/release_predator)
//Now actually put the people in the mobs
pred_brain.ckey = pred_brain.pred_ckey
@@ -286,7 +286,7 @@
else
continue
to_chat(src, span_danger("You haven't been taken over, and shouldn't have this verb. I'll clean that up for you. Report this on the github, it is a bug."))
- verbs -= /mob/proc/release_predator
+ remove_verb(src, /mob/proc/release_predator)
/mob/living/dominated_brain/proc/resist_control()
set category = "Abilities"
@@ -368,7 +368,7 @@
db.ooc_notes_dislikes = M.ooc_notes_dislikes
db.prey_ooc_likes = M.ooc_notes_likes
db.prey_ooc_dislikes = M.ooc_notes_dislikes
- db.verbs |= /mob/living/dominated_brain/proc/cease_this_foolishness
+ add_verb(db, /mob/living/dominated_brain/proc/cease_this_foolishness)
absorb_langs()
@@ -402,7 +402,7 @@
to_chat(src, span_warning("You can sense your body... but it is not contained within [pred_body]... You cannot return to it at this time."))
else
to_chat(src, span_warning("Your body seems to no longer exist, so, you cannot return to it."))
- verbs -= /mob/living/dominated_brain/proc/cease_this_foolishness
+ remove_verb(src, /mob/living/dominated_brain/proc/cease_this_foolishness)
/mob/living/proc/lend_prey_control()
set category = "Abilities"
@@ -489,7 +489,7 @@
pred.ooc_notes_likes = pred_brain.prey_ooc_likes
pred.ooc_notes_dislikes = pred_brain.prey_ooc_dislikes
- pred.verbs |= /mob/proc/release_predator
+ add_verb(pred, /mob/proc/release_predator)
//Now actually put the people in the mobs
pred_brain.ckey = pred_brain.pred_ckey
diff --git a/code/modules/mob/living/simple_mob/subtypes/vore/dragon.dm b/code/modules/mob/living/simple_mob/subtypes/vore/dragon.dm
index aac50f5c00..9915d171b0 100644
--- a/code/modules/mob/living/simple_mob/subtypes/vore/dragon.dm
+++ b/code/modules/mob/living/simple_mob/subtypes/vore/dragon.dm
@@ -105,8 +105,8 @@
. = ..()
if(!riding_datum)
riding_datum = new /datum/riding/simple_mob(src)
- verbs |= /mob/living/simple_mob/proc/animal_mount
- verbs |= /mob/living/proc/toggle_rider_reins
+ add_verb(src, /mob/living/simple_mob/proc/animal_mount)
+ add_verb(src, /mob/living/proc/toggle_rider_reins)
movement_cooldown = 0
/mob/living/simple_mob/vore/aggressive/dragon/MouseDrop_T(mob/living/M, mob/living/user)
diff --git a/code/modules/mob/living/simple_mob/subtypes/vore/greatwolf.dm b/code/modules/mob/living/simple_mob/subtypes/vore/greatwolf.dm
index 3251532c59..1d0e18733c 100644
--- a/code/modules/mob/living/simple_mob/subtypes/vore/greatwolf.dm
+++ b/code/modules/mob/living/simple_mob/subtypes/vore/greatwolf.dm
@@ -93,8 +93,8 @@
. = ..()
if(!riding_datum)
riding_datum = new /datum/riding/simple_mob(src)
- verbs |= /mob/living/simple_mob/proc/animal_mount
- verbs |= /mob/living/proc/toggle_rider_reins
+ add_verb(src, /mob/living/simple_mob/proc/animal_mount)
+ add_verb(src, /mob/living/proc/toggle_rider_reins)
movement_cooldown = -1.5
/mob/living/simple_mob/vore/greatwolf/MouseDrop_T(mob/living/M, mob/living/user)
diff --git a/code/modules/mob/living/simple_mob/subtypes/vore/hippo.dm b/code/modules/mob/living/simple_mob/subtypes/vore/hippo.dm
index 412a7ec8e5..725d48590f 100644
--- a/code/modules/mob/living/simple_mob/subtypes/vore/hippo.dm
+++ b/code/modules/mob/living/simple_mob/subtypes/vore/hippo.dm
@@ -70,8 +70,8 @@
. = ..()
if(!riding_datum)
riding_datum = new /datum/riding/simple_mob(src)
- verbs |= /mob/living/simple_mob/proc/animal_mount
- verbs |= /mob/living/proc/toggle_rider_reins
+ add_verb(src, /mob/living/simple_mob/proc/animal_mount)
+ add_verb(src, /mob/living/proc/toggle_rider_reins)
movement_cooldown = 0
/mob/living/simple_mob/vore/hippo/MouseDrop_T(mob/living/M, mob/living/user)
diff --git a/code/modules/mob/living/simple_mob/subtypes/vore/horse.dm b/code/modules/mob/living/simple_mob/subtypes/vore/horse.dm
index 51511ebcc8..4432da92be 100644
--- a/code/modules/mob/living/simple_mob/subtypes/vore/horse.dm
+++ b/code/modules/mob/living/simple_mob/subtypes/vore/horse.dm
@@ -72,8 +72,8 @@
. = ..()
if(!riding_datum)
riding_datum = new /datum/riding/simple_mob(src)
- verbs |= /mob/living/simple_mob/proc/animal_mount
- verbs |= /mob/living/proc/toggle_rider_reins
+ add_verb(src, /mob/living/simple_mob/proc/animal_mount)
+ add_verb(src, /mob/living/proc/toggle_rider_reins)
movement_cooldown = -2
/mob/living/simple_mob/vore/horse/MouseDrop_T(mob/living/M, mob/living/user)
diff --git a/code/modules/mob/living/simple_mob/subtypes/vore/leopardmander.dm b/code/modules/mob/living/simple_mob/subtypes/vore/leopardmander.dm
index 5a808e65ec..5b35207b54 100644
--- a/code/modules/mob/living/simple_mob/subtypes/vore/leopardmander.dm
+++ b/code/modules/mob/living/simple_mob/subtypes/vore/leopardmander.dm
@@ -66,8 +66,8 @@
. = ..()
if(!riding_datum)
riding_datum = new /datum/riding/simple_mob(src)
- verbs |= /mob/living/simple_mob/proc/animal_mount
- verbs |= /mob/living/proc/toggle_rider_reins
+ add_verb(src, /mob/living/simple_mob/proc/animal_mount)
+ add_verb(src, /mob/living/proc/toggle_rider_reins)
movement_cooldown = -1
/mob/living/simple_mob/vore/leopardmander/Initialize()
@@ -141,7 +141,7 @@
/mob/living/simple_mob/vore/leopardmander/exotic/New()
..()
- verbs |= /mob/living/simple_mob/vore/leopardmander/exotic/proc/toggle_glow
+ add_verb(src, /mob/living/simple_mob/vore/leopardmander/exotic/proc/toggle_glow)
/mob/living/simple_mob/vore/leopardmander/exotic/init_vore()
. = ..()
diff --git a/code/modules/mob/living/simple_mob/subtypes/vore/mobs_monsters/clowns/bus.dm b/code/modules/mob/living/simple_mob/subtypes/vore/mobs_monsters/clowns/bus.dm
index 75782e987a..ad73462e29 100644
--- a/code/modules/mob/living/simple_mob/subtypes/vore/mobs_monsters/clowns/bus.dm
+++ b/code/modules/mob/living/simple_mob/subtypes/vore/mobs_monsters/clowns/bus.dm
@@ -4,4 +4,4 @@
/mob/living/simple_mob/clowns/big/c_shift/New()
..()
- verbs += /mob/living/simple_mob/clowns/big/c_shift/proc/phase_shift
+ add_verb(src, /mob/living/simple_mob/clowns/big/c_shift/proc/phase_shift)
diff --git a/code/modules/mob/living/simple_mob/subtypes/vore/morph/morph.dm b/code/modules/mob/living/simple_mob/subtypes/vore/morph/morph.dm
index 92071f6f87..6eb6187f49 100644
--- a/code/modules/mob/living/simple_mob/subtypes/vore/morph/morph.dm
+++ b/code/modules/mob/living/simple_mob/subtypes/vore/morph/morph.dm
@@ -62,10 +62,10 @@
/obj/effect))
/mob/living/simple_mob/vore/morph/Initialize()
- verbs += /mob/living/proc/ventcrawl
- verbs += /mob/living/simple_mob/vore/morph/proc/take_over_prey
+ add_verb(src, /mob/living/proc/ventcrawl)
+ add_verb(src, /mob/living/simple_mob/vore/morph/proc/take_over_prey)
if(!istype(src, /mob/living/simple_mob/vore/morph/dominated_prey))
- verbs += /mob/living/simple_mob/vore/morph/proc/morph_color
+ add_verb(src, /mob/living/simple_mob/vore/morph/proc/morph_color)
return ..()
diff --git a/code/modules/mob/living/simple_mob/subtypes/vore/otie.dm b/code/modules/mob/living/simple_mob/subtypes/vore/otie.dm
index ad3abb09ef..e02408e979 100644
--- a/code/modules/mob/living/simple_mob/subtypes/vore/otie.dm
+++ b/code/modules/mob/living/simple_mob/subtypes/vore/otie.dm
@@ -313,8 +313,8 @@
. = ..()
if(!riding_datum)
riding_datum = new /datum/riding/simple_mob(src)
- verbs |= /mob/living/simple_mob/proc/animal_mount
- verbs |= /mob/living/proc/toggle_rider_reins
+ add_verb(src, /mob/living/simple_mob/proc/animal_mount)
+ add_verb(src, /mob/living/proc/toggle_rider_reins)
movement_cooldown = 0
/mob/living/simple_mob/vore/otie/MouseDrop_T(mob/living/M, mob/living/user)
diff --git a/code/modules/mob/living/simple_mob/subtypes/vore/panther.dm b/code/modules/mob/living/simple_mob/subtypes/vore/panther.dm
index a67f6c33b9..fb8e27e3c0 100644
--- a/code/modules/mob/living/simple_mob/subtypes/vore/panther.dm
+++ b/code/modules/mob/living/simple_mob/subtypes/vore/panther.dm
@@ -55,8 +55,8 @@
. = ..()
if(!riding_datum)
riding_datum = new /datum/riding/simple_mob(src)
- verbs |= /mob/living/simple_mob/proc/animal_mount
- verbs |= /mob/living/proc/toggle_rider_reins
+ add_verb(src, /mob/living/simple_mob/proc/animal_mount)
+ add_verb(src, /mob/living/proc/toggle_rider_reins)
movement_cooldown = 0
/mob/living/simple_mob/vore/aggressive/panther/MouseDrop_T(mob/living/M, mob/living/user)
diff --git a/code/modules/mob/living/simple_mob/subtypes/vore/raptor.dm b/code/modules/mob/living/simple_mob/subtypes/vore/raptor.dm
index 76e9d0a297..4495c32034 100644
--- a/code/modules/mob/living/simple_mob/subtypes/vore/raptor.dm
+++ b/code/modules/mob/living/simple_mob/subtypes/vore/raptor.dm
@@ -78,8 +78,8 @@
. = ..()
if(!riding_datum)
riding_datum = new /datum/riding/simple_mob(src)
- verbs |= /mob/living/simple_mob/proc/animal_mount
- verbs |= /mob/living/proc/toggle_rider_reins
+ add_verb(src, /mob/living/simple_mob/proc/animal_mount)
+ add_verb(src, /mob/living/proc/toggle_rider_reins)
movement_cooldown = -1
/mob/living/simple_mob/vore/raptor/init_vore()
diff --git a/code/modules/mob/living/simple_mob/subtypes/vore/rat.dm b/code/modules/mob/living/simple_mob/subtypes/vore/rat.dm
index a52519d0a4..17ac3dd682 100644
--- a/code/modules/mob/living/simple_mob/subtypes/vore/rat.dm
+++ b/code/modules/mob/living/simple_mob/subtypes/vore/rat.dm
@@ -214,8 +214,8 @@
. = ..()
if(!riding_datum)
riding_datum = new /datum/riding/simple_mob(src)
- verbs |= /mob/living/simple_mob/proc/animal_mount
- verbs |= /mob/living/proc/toggle_rider_reins
+ add_verb(src, /mob/living/simple_mob/proc/animal_mount)
+ add_verb(src, /mob/living/proc/toggle_rider_reins)
movement_cooldown = 0
/mob/living/simple_mob/vore/aggressive/rat/MouseDrop_T(mob/living/M, mob/living/user)
diff --git a/code/modules/mob/living/simple_mob/subtypes/vore/scel.dm b/code/modules/mob/living/simple_mob/subtypes/vore/scel.dm
index 4215931467..ce4ff0fe93 100644
--- a/code/modules/mob/living/simple_mob/subtypes/vore/scel.dm
+++ b/code/modules/mob/living/simple_mob/subtypes/vore/scel.dm
@@ -86,12 +86,12 @@
. = ..()
if(!riding_datum)
riding_datum = new /datum/riding/simple_mob(src)
- verbs |= /mob/living/simple_mob/proc/animal_mount
- verbs |= /mob/living/proc/toggle_rider_reins
- verbs |= /mob/living/proc/glow_toggle
- verbs |= /mob/living/proc/glow_color
- verbs |= /mob/living/proc/long_vore
- verbs |= /mob/living/proc/target_lunge
+ add_verb(src, /mob/living/simple_mob/proc/animal_mount)
+ add_verb(src, /mob/living/proc/toggle_rider_reins)
+ add_verb(src, /mob/living/proc/glow_toggle)
+ add_verb(src, /mob/living/proc/glow_color)
+ add_verb(src, /mob/living/proc/long_vore)
+ add_verb(src, /mob/living/proc/target_lunge)
movement_cooldown = -1
/mob/living/simple_mob/vore/scel/init_vore()
diff --git a/code/modules/mob/living/simple_mob/subtypes/vore/sect_drone.dm b/code/modules/mob/living/simple_mob/subtypes/vore/sect_drone.dm
index 532bbdc5ff..0c0adcc0a2 100644
--- a/code/modules/mob/living/simple_mob/subtypes/vore/sect_drone.dm
+++ b/code/modules/mob/living/simple_mob/subtypes/vore/sect_drone.dm
@@ -88,7 +88,7 @@
/mob/living/simple_mob/vore/sect_drone/Login()
. = ..()
- verbs |= /mob/living/simple_mob/vore/sect_drone/proc/set_abdomen_color
+ add_verb(src, /mob/living/simple_mob/vore/sect_drone/proc/set_abdomen_color)
/mob/living/simple_mob/vore/sect_drone/proc/set_abdomen_color()
set name = "Set Glow Color"
diff --git a/code/modules/mob/living/simple_mob/subtypes/vore/sect_queen.dm b/code/modules/mob/living/simple_mob/subtypes/vore/sect_queen.dm
index 1ce4592765..15dfcf1368 100644
--- a/code/modules/mob/living/simple_mob/subtypes/vore/sect_queen.dm
+++ b/code/modules/mob/living/simple_mob/subtypes/vore/sect_queen.dm
@@ -89,7 +89,7 @@
/mob/living/simple_mob/vore/sect_queen/Login()
. = ..()
- verbs |= /mob/living/simple_mob/vore/sect_queen/proc/set_abdomen_color
+ add_verb(src, /mob/living/simple_mob/vore/sect_queen/proc/set_abdomen_color)
/mob/living/simple_mob/vore/sect_queen/proc/set_abdomen_color()
set name = "Set Glow Color"
diff --git a/code/modules/mob/living/simple_mob/subtypes/vore/shadekin/shadekin.dm b/code/modules/mob/living/simple_mob/subtypes/vore/shadekin/shadekin.dm
index b7108a9ae3..d23eb01589 100644
--- a/code/modules/mob/living/simple_mob/subtypes/vore/shadekin/shadekin.dm
+++ b/code/modules/mob/living/simple_mob/subtypes/vore/shadekin/shadekin.dm
@@ -131,7 +131,7 @@
update_icon()
- verbs |= /mob/proc/adjust_hive_range
+ add_verb(src, /mob/proc/adjust_hive_range)
return ..()
@@ -225,14 +225,21 @@
add_overlay(tailimage)
add_overlay(eye_icon_state)
-/mob/living/simple_mob/shadekin/Stat()
- . = ..()
- if(statpanel("Shadekin"))
- abilities_stat()
+/mob/living/simple_mob/shadekin/update_misc_tabs()
+ ..()
+ var/list/L = list()
+ for(var/obj/effect/shadekin_ability/A as anything in shadekin_abilities)
+ var/client/C = client
+ var/img
+ if(C && istype(C)) //sanity checks
+ if(A.ability_name in C.misc_cache)
+ img = C.misc_cache[A.ability_name]
+ else
+ img = icon2html(A,C,sourceonly=TRUE)
+ C.misc_cache[A.ability_name] = img
-/mob/living/simple_mob/shadekin/proc/abilities_stat()
- for(var/obj/effect/shadekin_ability/ability as anything in shadekin_abilities)
- stat("[ability.ability_name]",ability.atom_button_text())
+ L[++L.len] = list("[A.ability_name]", A.ability_name, img, "Activate", REF(A))
+ misc_tabs["Shadekin"] = L
//They phase back to the dark when killed
/mob/living/simple_mob/shadekin/death(gibbed, deathmessage = "phases to somewhere far away!")
diff --git a/code/modules/mob/living/simple_mob/subtypes/vore/sheep.dm b/code/modules/mob/living/simple_mob/subtypes/vore/sheep.dm
index 30ac297628..ad58c3a43f 100644
--- a/code/modules/mob/living/simple_mob/subtypes/vore/sheep.dm
+++ b/code/modules/mob/living/simple_mob/subtypes/vore/sheep.dm
@@ -48,8 +48,8 @@
. = ..()
if(!riding_datum)
riding_datum = new /datum/riding/simple_mob(src)
- verbs |= /mob/living/simple_mob/proc/animal_mount
- verbs |= /mob/living/proc/toggle_rider_reins
+ add_verb(src, /mob/living/simple_mob/proc/animal_mount)
+ add_verb(src, /mob/living/proc/toggle_rider_reins)
movement_cooldown = -1
/mob/living/simple_mob/vore/sheep/MouseDrop_T(mob/living/M, mob/living/user)
diff --git a/code/modules/mob/living/simple_mob/subtypes/vore/softdog.dm b/code/modules/mob/living/simple_mob/subtypes/vore/softdog.dm
index aaf4ccfd7c..23d4260cec 100644
--- a/code/modules/mob/living/simple_mob/subtypes/vore/softdog.dm
+++ b/code/modules/mob/living/simple_mob/subtypes/vore/softdog.dm
@@ -57,8 +57,8 @@
/mob/living/simple_mob/vore/woof/New()
..()
- verbs += /mob/living/proc/ventcrawl
- verbs += /mob/living/proc/hide
+ add_verb(src, /mob/living/proc/ventcrawl)
+ add_verb(src, /mob/living/proc/hide)
/datum/say_list/softdog
speak = list("Woof~", "Woof!", "Yip!", "Yap!", "Yip~", "Yap~", "Awoooooo~", "Awoo!", "AwooooooooooOOOOOOoOooOoooOoOOoooo!")
diff --git a/code/modules/mob/living/simple_mob/subtypes/vore/solargrub_larva.dm b/code/modules/mob/living/simple_mob/subtypes/vore/solargrub_larva.dm
index 1f91fdb592..763e7386ab 100644
--- a/code/modules/mob/living/simple_mob/subtypes/vore/solargrub_larva.dm
+++ b/code/modules/mob/living/simple_mob/subtypes/vore/solargrub_larva.dm
@@ -60,7 +60,7 @@ var/global/list/grub_machine_overlays = list()
sparks = new(src)
sparks.set_up()
sparks.attach(src)
- verbs += /mob/living/proc/ventcrawl
+ add_verb(src, /mob/living/proc/ventcrawl)
/mob/living/simple_mob/animal/solargrub_larva/death()
powermachine.draining = 0
diff --git a/code/modules/mob/living/simple_mob/subtypes/vore/vore.dm b/code/modules/mob/living/simple_mob/subtypes/vore/vore.dm
index 195480b680..62a4ac73b5 100644
--- a/code/modules/mob/living/simple_mob/subtypes/vore/vore.dm
+++ b/code/modules/mob/living/simple_mob/subtypes/vore/vore.dm
@@ -9,8 +9,8 @@
/mob/living/simple_mob/Login()
. = ..()
- verbs |= /mob/living/simple_mob/proc/set_name
- verbs |= /mob/living/simple_mob/proc/set_desc
+ add_verb(src, /mob/living/simple_mob/proc/set_name)
+ add_verb(src, /mob/living/simple_mob/proc/set_desc)
if(copy_prefs_to_mob)
login_prefs()
diff --git a/code/modules/mob/living/simple_mob/subtypes/vore/wolf.dm b/code/modules/mob/living/simple_mob/subtypes/vore/wolf.dm
index d59a89b163..bf2535cd49 100644
--- a/code/modules/mob/living/simple_mob/subtypes/vore/wolf.dm
+++ b/code/modules/mob/living/simple_mob/subtypes/vore/wolf.dm
@@ -102,8 +102,8 @@
. = ..()
if(!riding_datum)
riding_datum = new /datum/riding/simple_mob(src)
- verbs |= /mob/living/simple_mob/proc/animal_mount
- verbs |= /mob/living/proc/toggle_rider_reins
+ add_verb(src, /mob/living/simple_mob/proc/animal_mount)
+ add_verb(src, /mob/living/proc/toggle_rider_reins)
movement_cooldown = -1
/mob/living/simple_mob/vore/wolf/direwolf/MouseDrop_T(mob/living/M, mob/living/user)
diff --git a/code/modules/mob/login.dm b/code/modules/mob/login.dm
index 4ff396fd0a..fd3e92dfd6 100644
--- a/code/modules/mob/login.dm
+++ b/code/modules/mob/login.dm
@@ -83,4 +83,5 @@
if(cloaked && cloaked_selfimage)
client.images += cloaked_selfimage
+ client.init_verbs()
SEND_SIGNAL(src, COMSIG_MOB_CLIENT_LOGIN, client)
diff --git a/code/modules/mob/mob.dm b/code/modules/mob/mob.dm
index 044f2ecd1f..c5aef76542 100644
--- a/code/modules/mob/mob.dm
+++ b/code/modules/mob/mob.dm
@@ -694,86 +694,19 @@
for(var/mob/M in viewers())
M.see(message)
-/mob/Stat()
- ..()
- . = (is_client_active(10 MINUTES))
+/// Adds this list to the output to the stat browser
+/mob/proc/get_status_tab_items()
+ . = list()
- if(.)
- if(statpanel("Status"))
- stat(null, "Time Dilation: [round(SStime_track.time_dilation_current,1)]% AVG:([round(SStime_track.time_dilation_avg_fast,1)]%, [round(SStime_track.time_dilation_avg,1)]%, [round(SStime_track.time_dilation_avg_slow,1)]%)")
- if(ticker && ticker.current_state != GAME_STATE_PREGAME)
- stat("Station Time", stationtime2text())
- var/date = "[stationdate2text()], [capitalize(world_time_season)]"
- stat("Station Date", date)
- stat("Round Duration", roundduration2text())
-
- if(client.holder)
- if(statpanel("Status"))
- stat("Location:", "([x], [y], [z]) [loc]")
- stat("CPU:","[world.cpu]")
- stat("Instances:","[world.contents.len]")
- stat(null, "Time Dilation: [round(SStime_track.time_dilation_current,1)]% AVG:([round(SStime_track.time_dilation_avg_fast,1)]%, [round(SStime_track.time_dilation_avg,1)]%, [round(SStime_track.time_dilation_avg_slow,1)]%)")
- stat("Keys Held", keys2text(client.move_keys_held | client.mod_keys_held))
- stat("Next Move ADD", dirs2text(client.next_move_dir_add))
- stat("Next Move SUB", dirs2text(client.next_move_dir_sub))
- stat("Current size:", size_multiplier * 100)
-
- if(statpanel("MC"))
- stat("Location:", "([x], [y], [z]) [loc]")
- stat("CPU:","[world.cpu]")
- stat("Instances:","[world.contents.len]")
- stat("World Time:", world.time)
- stat("Real time of day:", REALTIMEOFDAY)
- stat(null)
- if(GLOB)
- GLOB.stat_entry()
- else
- stat("Globals:", "ERROR")
- if(Master)
- Master.stat_entry()
- else
- stat("Master Controller:", "ERROR")
- if(Failsafe)
- Failsafe.stat_entry()
- else
- stat("Failsafe Controller:", "ERROR")
- if(Master)
- stat(null)
- for(var/datum/controller/subsystem/SS in Master.subsystems)
- SS.stat_entry()
-
- if(statpanel("Tickets"))
- if(check_rights(R_ADMIN|R_SERVER,FALSE)) //Prevents non-staff from opening the list of ahelp tickets
- GLOB.ahelp_tickets.stat_entry()
-
-
- if(length(GLOB.sdql2_queries))
- if(statpanel("SDQL2"))
- stat("Access Global SDQL2 List", GLOB.sdql2_vv_statobj)
- for(var/datum/SDQL2_query/Q as anything in GLOB.sdql2_queries)
- Q.generate_stat()
-
- if(has_mentor_powers(client))
- if(statpanel("Tickets"))
- GLOB.mhelp_tickets.stat_entry()
-
- if(listed_turf && client)
- if(!TurfAdjacent(listed_turf))
- listed_turf = null
- else
- if(statpanel("Turf"))
- stat(listed_turf)
- for(var/atom/A in listed_turf)
- if(!A.mouse_opacity)
- continue
- if(A.invisibility > see_invisible)
- continue
- if(is_type_in_list(A, shouldnt_see))
- continue
- if(A.plane > plane)
- continue
- stat(A)
+/// Gets all relevant proc holders for the browser statpenl
+/mob/proc/get_proc_holders()
+ . = list()
+ //if(mind)
+ //. += get_spells_for_statpanel(mind.spell_list)
+ //. += get_spells_for_statpanel(mob_spell_list)
+/mob/proc/update_misc_tabs()
+ misc_tabs = list() //Reset misc_tabs every Stat() to prevent old shit sticking around
// facing verbs
/mob/proc/canface()
@@ -1008,7 +941,7 @@
visible_message(span_warning("[usr] rips [selection] out of [src]'s body."),span_warning("[usr] rips [selection] out of your body."))
valid_objects = get_visible_implants(0)
if(valid_objects.len == 1) //Yanking out last object - removing verb.
- src.verbs -= /mob/proc/yank_out_object
+ remove_verb(src, /mob/proc/yank_out_object)
clear_alert("embeddedobject")
if(ishuman(src))
diff --git a/code/modules/mob/mob_defines.dm b/code/modules/mob/mob_defines.dm
index 83cea738c4..050738cb95 100644
--- a/code/modules/mob/mob_defines.dm
+++ b/code/modules/mob/mob_defines.dm
@@ -236,3 +236,5 @@
var/list/progressbars = null //VOREStation Edit
var/datum/focus //What receives our keyboard inputs. src by default
+ /// dict of custom stat tabs with data
+ var/list/list/misc_tabs = list()
diff --git a/code/modules/mob/new_player/login.dm b/code/modules/mob/new_player/login.dm
index cfbcebbf42..e6d8d9fcc1 100644
--- a/code/modules/mob/new_player/login.dm
+++ b/code/modules/mob/new_player/login.dm
@@ -50,6 +50,7 @@ var/obj/effect/lobby_image = new /obj/effect/lobby_image
created_for = ckey
new_player_panel()
+ client.init_verbs()
spawn(40)
if(client)
handle_privacy_poll()
diff --git a/code/modules/mob/new_player/new_player.dm b/code/modules/mob/new_player/new_player.dm
index 8e4030ca39..7b2d7228db 100644
--- a/code/modules/mob/new_player/new_player.dm
+++ b/code/modules/mob/new_player/new_player.dm
@@ -22,7 +22,7 @@
/mob/new_player/New()
mob_list += src
- verbs |= /mob/proc/insidePanel
+ add_verb(src, /mob/proc/insidePanel)
initialized = TRUE // Explicitly don't use Initialize(). New players join super early and use New()
@@ -111,36 +111,37 @@
panel.open()
return
-/mob/new_player/Stat()
- ..()
+/mob/new_player/get_status_tab_items()
+ . = ..()
+ . += ""
- if(statpanel("Lobby") && SSticker)
- stat("Game Mode:", SSticker.hide_mode ? "Secret" : "[config.mode_names[master_mode]]")
+ . += "Game Mode: [SSticker.hide_mode ? "Secret" : "[config.mode_names[master_mode]]"]"
- // if(SSvote.mode)
- // stat("Vote: [capitalize(SSvote.mode)]", "Time Left: [SSvote.time_remaining] s")
+ // if(SSvote.mode)
+ // . += "Vote: [capitalize(SSvote.mode)] Time Left: [SSvote.time_remaining] s"
- if(SSticker.current_state == GAME_STATE_INIT)
- stat("Time To Start:", "Server Initializing")
+ if(SSticker.current_state == GAME_STATE_INIT)
+ . += "Time To Start: Server Initializing"
- else if(SSticker.current_state == GAME_STATE_PREGAME)
- stat("Time To Start:", "[round(SSticker.pregame_timeleft,1)][round_progressing ? "" : " (DELAYED)"]")
- stat("Players: [totalPlayers]", "Players Ready: [totalPlayersReady]")
- totalPlayers = 0
- totalPlayersReady = 0
- var/datum/job/refJob = null
- for(var/mob/new_player/player in player_list)
- refJob = player.client.prefs.get_highest_job()
- if(player.client.prefs.obfuscate_key && player.client.prefs.obfuscate_job)
- stat("Anonymous User", (player.ready)?("Ready!"):(null))
- else if(player.client.prefs.obfuscate_key)
- stat("Anonymous User", (player.ready)?("(Playing as: [(refJob)?(refJob.title):("Unknown")])"):(null))
- else if(player.client.prefs.obfuscate_job)
- stat("[player.key]", (player.ready)?("Ready!"):(null))
- else
- stat("[player.key]", (player.ready)?("(Playing as: [(refJob)?(refJob.title):("Unknown")])"):(null))
- totalPlayers++
- if(player.ready)totalPlayersReady++
+ else if(SSticker.current_state == GAME_STATE_PREGAME)
+ . += "Time To Start: [round(SSticker.pregame_timeleft,1)][round_progressing ? "" : " (DELAYED)"]"
+ . += "Players: [totalPlayers]"
+ . += "Players Ready: [totalPlayersReady]"
+ totalPlayers = 0
+ totalPlayersReady = 0
+ var/datum/job/refJob = null
+ for(var/mob/new_player/player in player_list)
+ refJob = player.client.prefs.get_highest_job()
+ if(player.client.prefs.obfuscate_key && player.client.prefs.obfuscate_job)
+ . += "Anonymous User [player.ready ? "Ready!" : null]"
+ else if(player.client.prefs.obfuscate_key)
+ . += "Anonymous User [player.ready ? "(Playing as: [refJob ? refJob.title : "Unknown"])" : null]"
+ else if(player.client.prefs.obfuscate_job)
+ . += "[player.key] [player.ready ? "Ready!" : null]"
+ else
+ . += "[player.key] [player.ready ? "(Playing as: [refJob ? refJob.title : "Unknown"])" : null]"
+ totalPlayers++
+ if(player.ready)totalPlayersReady++
/mob/new_player/Topic(href, href_list[])
if(!client) return 0
@@ -191,9 +192,10 @@
observer.real_name = client.prefs.real_name
observer.name = observer.real_name
if(!client.holder && !config.antag_hud_allowed) // For new ghosts we remove the verb from even showing up if it's not allowed.
- observer.verbs -= /mob/observer/dead/verb/toggle_antagHUD // Poor guys, don't know what they are missing!
+ remove_verb(observer, /mob/observer/dead/verb/toggle_antagHUD) // Poor guys, don't know what they are missing!
observer.key = key
observer.set_respawn_timer(time_till_respawn()) // Will keep their existing time if any, or return 0 and pass 0 into set_respawn_timer which will use the defaults
+ observer.client.init_verbs()
qdel(src)
return 1
@@ -517,6 +519,7 @@
if(imp.handle_implant(character,character.zone_sel.selecting))
imp.post_implant(character)
+ character.client.init_verbs()
qdel(src) // Delete new_player mob
/mob/new_player/proc/AnnounceCyborg(var/mob/living/character, var/rank, var/join_message, var/channel, var/zlevel)
@@ -621,6 +624,7 @@
mind.transfer_to(new_character) //won't transfer key since the mind is not active
new_character.name = real_name
+ client.init_verbs()
new_character.dna.ready_dna(new_character)
new_character.dna.b_type = client.prefs.b_type
new_character.sync_organ_dna()
diff --git a/code/modules/nifsoft/nif.dm b/code/modules/nifsoft/nif.dm
index 76967fbf98..04dc280ffb 100644
--- a/code/modules/nifsoft/nif.dm
+++ b/code/modules/nifsoft/nif.dm
@@ -126,7 +126,7 @@ You can also set the stat of a NIF to NIF_TEMPFAIL without any issues to disable
human = H
human.nif = src
stat = NIF_INSTALLING
- H.verbs |= /mob/living/carbon/human/proc/set_nif_examine
+ add_verb(H, /mob/living/carbon/human/proc/set_nif_examine)
menu = H.AddComponent(/datum/component/nif_menu)
if(starting_software)
for(var/path in starting_software)
@@ -171,7 +171,7 @@ You can also set the stat of a NIF to NIF_TEMPFAIL without any issues to disable
stat = NIF_PREINSTALL
vis_update()
if(H)
- H.verbs -= /mob/living/carbon/human/proc/set_nif_examine
+ remove_verb(H, /mob/living/carbon/human/proc/set_nif_examine)
H.nif = null
qdel_null(menu)
human = null
@@ -691,7 +691,7 @@ You can also set the stat of a NIF to NIF_TEMPFAIL without any issues to disable
set category = "OOC"
if(!nif)
- verbs -= /mob/living/carbon/human/proc/set_nif_examine
+ remove_verb(src, /mob/living/carbon/human/proc/set_nif_examine)
to_chat(src,span_warning("You don't have a NIF, not sure why this was here."))
return
diff --git a/code/modules/nifsoft/nif_tgui.dm b/code/modules/nifsoft/nif_tgui.dm
index 4b57d57739..2c9227e5ad 100644
--- a/code/modules/nifsoft/nif_tgui.dm
+++ b/code/modules/nifsoft/nif_tgui.dm
@@ -46,7 +46,7 @@
UnregisterSignal(screen_icon, COMSIG_CLICK)
qdel_null(screen_icon)
if(ishuman(parent))
- owner.verbs -= /mob/living/carbon/human/proc/nif_menu
+ remove_verb(owner, /mob/living/carbon/human/proc/nif_menu)
/datum/component/nif_menu/proc/create_mob_button(mob/user)
@@ -60,7 +60,7 @@
LAZYADD(HUD.other_important, screen_icon)
user.client?.screen += screen_icon
- user.verbs |= /mob/living/carbon/human/proc/nif_menu
+ add_verb(user, /mob/living/carbon/human/proc/nif_menu)
/datum/component/nif_menu/proc/nif_menu_click(source, location, control, params, user)
var/mob/living/carbon/human/H = user
diff --git a/code/modules/nifsoft/software/13_soulcatcher.dm b/code/modules/nifsoft/software/13_soulcatcher.dm
index bf9eca000a..8c2d842c89 100644
--- a/code/modules/nifsoft/software/13_soulcatcher.dm
+++ b/code/modules/nifsoft/software/13_soulcatcher.dm
@@ -46,14 +46,14 @@
if((. = ..()))
//nif.set_flag(NIF_O_SCOTHERS,NIF_FLAGS_OTHER) //Only required on install if the flag is in the default setting_flags list defined few lines above.
if(nif?.human)
- nif.human.verbs |= /mob/proc/nsay
- nif.human.verbs |= /mob/proc/nme
+ add_verb(nif.human, /mob/proc/nsay)
+ add_verb(nif.human, /mob/proc/nme)
/datum/nifsoft/soulcatcher/uninstall()
QDEL_LIST_NULL(brainmobs)
if((. = ..()) && nif?.human) //Sometimes NIFs are deleted outside of a human
- nif.human.verbs -= /mob/proc/nsay
- nif.human.verbs -= /mob/proc/nme
+ remove_verb(nif.human, /mob/proc/nsay)
+ remove_verb(nif.human, /mob/proc/nme)
/datum/nifsoft/soulcatcher/proc/save_settings()
if(!nif)
diff --git a/code/modules/organs/organ.dm b/code/modules/organs/organ.dm
index dd4d9e97b0..1ef703cc9f 100644
--- a/code/modules/organs/organ.dm
+++ b/code/modules/organs/organ.dm
@@ -548,11 +548,11 @@ var/list/organ_cache = list()
if(!removed && organ_verbs && check_verb_compatability())
for(var/verb_path in organ_verbs)
- owner.verbs |= verb_path
+ add_verb(owner, verb_path)
else if(organ_verbs)
for(var/verb_path in organ_verbs)
if(!(verb_path in save_verbs))
- owner.verbs -= verb_path
+ remove_verb(owner, verb_path)
return
/obj/item/organ/proc/handle_organ_proc_special() // Called when processed.
diff --git a/code/modules/organs/organ_external.dm b/code/modules/organs/organ_external.dm
index 9ec1dc24b5..3dd68bcc9c 100644
--- a/code/modules/organs/organ_external.dm
+++ b/code/modules/organs/organ_external.dm
@@ -221,7 +221,7 @@
dislocated = 1
if(istype(owner))
- owner.verbs |= /mob/living/carbon/human/proc/relocate
+ add_verb(owner, /mob/living/carbon/human/proc/relocate)
/obj/item/organ/external/proc/relocate()
if(dislocated == -1)
@@ -235,7 +235,7 @@
for(var/obj/item/organ/external/limb in owner.organs)
if(limb.dislocated == 1)
return
- owner.verbs -= /mob/living/carbon/human/proc/relocate
+ remove_verb(owner, /mob/living/carbon/human/proc/relocate)
/obj/item/organ/external/update_health()
damage = min(max_damage, (brute_dam + burn_dam))
@@ -1223,7 +1223,7 @@ Note that amputating the affected organ does in fact remove the infection from t
owner.visible_message(span_danger("\The [W] sticks in the wound!"))
implants += W
owner.embedded_flag = 1
- owner.verbs += /mob/proc/yank_out_object
+ add_verb(owner, /mob/proc/yank_out_object)
owner.throw_alert("embeddedobject", /obj/screen/alert/embeddedobject)
W.add_blood(owner)
if(ismob(W.loc))
diff --git a/code/modules/paperwork/silicon_photography.dm b/code/modules/paperwork/silicon_photography.dm
index 85853eee2c..dd648c119c 100644
--- a/code/modules/paperwork/silicon_photography.dm
+++ b/code/modules/paperwork/silicon_photography.dm
@@ -119,7 +119,7 @@
aiCamera.deletepicture()
/mob/living/silicon/robot/proc/take_image()
- set category ="Robot Commands"
+ set category ="Abilities.Silicon"
set name = "Take Image"
set desc = "Takes an image"
@@ -127,7 +127,7 @@
aiCamera.toggle_camera_mode()
/mob/living/silicon/robot/proc/view_images()
- set category ="Robot Commands"
+ set category ="Abilities.Silicon"
set name = "View Images"
set desc = "View images"
@@ -135,7 +135,7 @@
aiCamera.viewpictures()
/mob/living/silicon/robot/proc/delete_images()
- set category = "Robot Commands"
+ set category = "Abilities.Silicon"
set name = "Delete Image"
set desc = "Delete a local image"
diff --git a/code/modules/pda/ai.dm b/code/modules/pda/ai.dm
index a67d469d4e..b3f889f02f 100644
--- a/code/modules/pda/ai.dm
+++ b/code/modules/pda/ai.dm
@@ -22,7 +22,7 @@
//AI verb and proc for sending PDA messages.
/obj/item/pda/ai/verb/cmd_pda_open_ui()
- set category = "AI IM"
+ set category = "Abilities.AI_IM"
set name = "Use PDA"
set src in usr
diff --git a/code/modules/reagents/reagents/medicine_vr.dm b/code/modules/reagents/reagents/medicine_vr.dm
index 88da82e573..ffffacd0a3 100644
--- a/code/modules/reagents/reagents/medicine_vr.dm
+++ b/code/modules/reagents/reagents/medicine_vr.dm
@@ -324,7 +324,7 @@
scannable = 1
/datum/reagent/glamour/affect_blood(var/mob/living/carbon/target, var/removed)
- target.verbs |= /mob/living/carbon/human/proc/enter_cocoon
+ add_verb(target, /mob/living/carbon/human/proc/enter_cocoon)
target.bloodstr.clear_reagents() //instantly clears reagents afterwards
target.ingested.clear_reagents()
target.touching.clear_reagents()
diff --git a/code/modules/spells/spellbook.dm b/code/modules/spells/spellbook.dm
index 4324ec8d12..0449d781c3 100644
--- a/code/modules/spells/spellbook.dm
+++ b/code/modules/spells/spellbook.dm
@@ -344,11 +344,11 @@
if(user.mind.special_verbs.len)
for(var/V in user.mind.special_verbs)
- user.verbs -= V
+ remove_verb(user, V)
if(stored_swap.mind.special_verbs.len)
for(var/V in stored_swap.mind.special_verbs)
- stored_swap.verbs -= V
+ remove_verb(stored_swap, V)
var/mob/observer/dead/ghost = stored_swap.ghostize(0)
ghost.spell_list = stored_swap.spell_list
@@ -358,7 +358,7 @@
if(stored_swap.mind.special_verbs.len)
for(var/V in user.mind.special_verbs)
- user.verbs += V
+ add_verb(user, V)
ghost.mind.transfer_to(user)
user.key = ghost.key
@@ -366,7 +366,7 @@
if(user.mind.special_verbs.len)
for(var/V in user.mind.special_verbs)
- user.verbs += V
+ add_verb(user, V)
to_chat(stored_swap, span_warning("You're suddenly somewhere else... and someone else?!"))
to_chat(user, span_warning("Suddenly you're staring at [src] again... where are you, who are you?!"))
diff --git a/code/modules/spells/spells.dm b/code/modules/spells/spells.dm
index f98eba1678..eba1e7055f 100644
--- a/code/modules/spells/spells.dm
+++ b/code/modules/spells/spells.dm
@@ -14,19 +14,20 @@
spell_master.toggle_open(1)
client.screen -= spell_master
-/mob/Stat()
- . = ..()
- if(. && spell_list && spell_list.len)
- for(var/spell/S in spell_list)
- if((!S.connected_button) || !statpanel(S.panel))
- continue //Not showing the noclothes spell
- switch(S.charge_type)
- if(Sp_RECHARGE)
- statpanel(S.panel,"[S.charge_counter/10.0]/[S.charge_max/10]",S.connected_button)
- if(Sp_CHARGES)
- statpanel(S.panel,"[S.charge_counter]/[S.charge_max]",S.connected_button)
- if(Sp_HOLDVAR)
- statpanel(S.panel,"[S.holder_var_type] [S.holder_var_amount]",S.connected_button)
+// TODO: Investigate if this matters
+// /mob/Stat()
+// . = ..()
+// if(. && spell_list && spell_list.len)
+// for(var/spell/S in spell_list)
+// if((!S.connected_button) || !statpanel(S.panel))
+// continue //Not showing the noclothes spell
+// switch(S.charge_type)
+// if(Sp_RECHARGE)
+// statpanel(S.panel,"[S.charge_counter/10.0]/[S.charge_max/10]",S.connected_button)
+// if(Sp_CHARGES)
+// statpanel(S.panel,"[S.charge_counter]/[S.charge_max]",S.connected_button)
+// if(Sp_HOLDVAR)
+// statpanel(S.panel,"[S.holder_var_type] [S.holder_var_amount]",S.connected_button)
/hook/clone/proc/restore_spells(var/mob/H)
if(H.mind && H.mind.learned_spells)
diff --git a/code/modules/spells/targeted/mind_transfer.dm b/code/modules/spells/targeted/mind_transfer.dm
index 4ccd7354c6..1d4a81f3a0 100644
--- a/code/modules/spells/targeted/mind_transfer.dm
+++ b/code/modules/spells/targeted/mind_transfer.dm
@@ -41,11 +41,11 @@
//MIND TRANSFER BEGIN
if(caster.mind.special_verbs.len)//If the caster had any special verbs, remove them from the mob verb list.
for(var/V in caster.mind.special_verbs)//Since the caster is using an object spell system, this is mostly moot.
- caster.verbs -= V//But a safety nontheless.
+ remove_verb(caster, V)//But a safety nontheless.
if(victim.mind.special_verbs.len)//Now remove all of the victim's verbs.
for(var/V in victim.mind.special_verbs)
- victim.verbs -= V
+ remove_verb(victim, V)
var/mob/observer/dead/ghost = victim.ghostize(0)
ghost.spell_list += victim.spell_list//If they have spells, transfer them. Now we basically have a backup mob.
@@ -60,7 +60,7 @@
if(victim.mind.special_verbs.len)//To add all the special verbs for the original caster.
for(var/V in caster.mind.special_verbs)//Not too important but could come into play.
- caster.verbs += V
+ add_verb(caster, V)
ghost.mind.transfer_to(caster)
caster.key = ghost.key //have to transfer the key since the mind was not active
@@ -70,7 +70,7 @@
if(caster.mind.special_verbs.len)//If they had any special verbs, we add them here.
for(var/V in caster.mind.special_verbs)
- caster.verbs += V
+ add_verb(caster, V)
//MIND TRANSFER END
//Target is handled in ..(), so we handle the caster here
diff --git a/code/modules/surgery/robotics.dm b/code/modules/surgery/robotics.dm
index 40276dece2..0973230b13 100644
--- a/code/modules/surgery/robotics.dm
+++ b/code/modules/surgery/robotics.dm
@@ -598,8 +598,8 @@
target.species = GLOB.all_species[SPECIES_DIONA]
- target.verbs |= /mob/living/carbon/human/proc/diona_split_nymph
- target.verbs |= /mob/living/carbon/human/proc/regenerate
+ add_verb(target, /mob/living/carbon/human/proc/diona_split_nymph)
+ add_verb(target, /mob/living/carbon/human/proc/regenerate)
spawn(0) //Name yourself on your own damn time
var/new_name = ""
diff --git a/code/modules/vchat/vchat_client.dm b/code/modules/vchat/vchat_client.dm
index 054fd14773..5c4b0e1617 100644
--- a/code/modules/vchat/vchat_client.dm
+++ b/code/modules/vchat/vchat_client.dm
@@ -132,7 +132,7 @@ GLOBAL_DATUM_INIT(iconCache, /savefile, new("data/iconCache.sav")) //Cache of ic
send_playerinfo()
load_database()
- owner.verbs += /client/proc/vchat_export_log
+ add_verb(owner, /client/proc/vchat_export_log)
//Perform DB shenanigans
/datum/chatOutput/proc/load_database()
diff --git a/code/modules/vore/eating/living_vr.dm b/code/modules/vore/eating/living_vr.dm
index aae7862a50..778c735451 100644
--- a/code/modules/vore/eating/living_vr.dm
+++ b/code/modules/vore/eating/living_vr.dm
@@ -1400,7 +1400,7 @@
var/mob/living/owner = parent
if(owner.client)
create_mob_button(parent)
- owner.verbs |= /mob/proc/insidePanel
+ add_verb(owner, /mob/proc/insidePanel)
owner.vorePanel = new(owner)
/datum/component/vore_panel/UnregisterFromParent()
@@ -1411,7 +1411,7 @@
owner?.client?.screen -= screen_icon
UnregisterSignal(screen_icon, COMSIG_CLICK)
qdel_null(screen_icon)
- owner.verbs -= /mob/proc/insidePanel
+ remove_verb(owner, /mob/proc/insidePanel)
qdel_null(owner.vorePanel)
/datum/component/vore_panel/proc/create_mob_button(mob/user)
diff --git a/code/modules/vore/fluffstuff/custom_implants_vr.dm b/code/modules/vore/fluffstuff/custom_implants_vr.dm
index 345359cb30..1ad8493b1d 100644
--- a/code/modules/vore/fluffstuff/custom_implants_vr.dm
+++ b/code/modules/vore/fluffstuff/custom_implants_vr.dm
@@ -112,7 +112,7 @@
/obj/item/implant/reagent_generator/roiz/post_implant(mob/living/carbon/source)
START_PROCESSING(SSobj, src)
to_chat(source, span_notice("You implant [source] with \the [src]."))
- source.verbs |= assigned_proc
+ add_verb(source, assigned_proc)
return 1
/obj/item/implanter/reagent_generator/roiz
@@ -181,7 +181,7 @@
/obj/item/implant/reagent_generator/jasmine/post_implant(mob/living/carbon/source)
START_PROCESSING(SSobj, src)
to_chat(source, span_notice("You implant [source] with \the [src]."))
- source.verbs |= assigned_proc
+ add_verb(source, assigned_proc)
return 1
/obj/item/implanter/reagent_generator/jasmine
@@ -250,7 +250,7 @@
/obj/item/implant/reagent_generator/yonra/post_implant(mob/living/carbon/source)
START_PROCESSING(SSobj, src)
to_chat(source, span_notice("You implant [source] with \the [src]."))
- source.verbs |= assigned_proc
+ add_verb(source, assigned_proc)
return 1
/obj/item/implanter/reagent_generator/yonra
@@ -335,7 +335,7 @@
/obj/item/implant/reagent_generator/rischi/post_implant(mob/living/carbon/source)
START_PROCESSING(SSobj, src)
to_chat(source, span_notice("You implant [source] with \the [src]."))
- source.verbs |= assigned_proc
+ add_verb(source, assigned_proc)
return 1
/obj/item/implanter/reagent_generator/rischi
@@ -486,7 +486,7 @@
/obj/item/implant/reagent_generator/evian/post_implant(mob/living/carbon/source)
START_PROCESSING(SSobj, src)
to_chat(source, span_notice("You implant [source] with \the [src]."))
- source.verbs |= assigned_proc
+ add_verb(source, assigned_proc)
return 1
/obj/item/implanter/reagent_generator/evian
diff --git a/code/modules/vore/fluffstuff/custom_items_vr.dm b/code/modules/vore/fluffstuff/custom_items_vr.dm
index 7993be8e43..296dd6808d 100644
--- a/code/modules/vore/fluffstuff/custom_items_vr.dm
+++ b/code/modules/vore/fluffstuff/custom_items_vr.dm
@@ -754,7 +754,7 @@
/obj/item/fluff/dragor_dot/attack_self(mob/user as mob)
if(user.ckey == "pontifexminimus")
- user.verbs |= /mob/living/carbon/human/proc/shapeshifter_select_gender
+ add_verb(user, /mob/living/carbon/human/proc/shapeshifter_select_gender)
else
return
diff --git a/code/modules/vore/resizing/resize_vr.dm b/code/modules/vore/resizing/resize_vr.dm
index 54b3bff78a..33a152492b 100644
--- a/code/modules/vore/resizing/resize_vr.dm
+++ b/code/modules/vore/resizing/resize_vr.dm
@@ -166,7 +166,7 @@
/*
//Add the set_size() proc to usable verbs. By commenting this out, we can leave the proc and hand it to species that need it.
/hook/living_new/proc/resize_setup(mob/living/H)
- H.verbs += /mob/living/proc/set_size
+ add_verb(H, /mob/living/proc/set_size)
return 1
*/
diff --git a/code/modules/xenobio/items/slimepotions_vr.dm b/code/modules/xenobio/items/slimepotions_vr.dm
index 1de0ee69f8..da55f7e9ca 100644
--- a/code/modules/xenobio/items/slimepotions_vr.dm
+++ b/code/modules/xenobio/items/slimepotions_vr.dm
@@ -165,7 +165,7 @@
M.ghostjoin = 1
active_ghost_pods |= M
if(!M.vore_active)
- M.verbs += /mob/living/simple_mob/proc/animal_nom
+ add_verb(M, /mob/living/simple_mob/proc/animal_nom)
M.ghostjoin_icon()
log_and_message_admins("[key_name_admin(user)] used a sapience potion on a simple mob: [M]. [ADMIN_FLW(src)]")
playsound(src, 'sound/effects/bubbles.ogg', 50, 1)
diff --git a/html/statbrowser.css b/html/statbrowser.css
new file mode 100644
index 0000000000..0e20233b47
--- /dev/null
+++ b/html/statbrowser.css
@@ -0,0 +1,261 @@
+body {
+ font-family: Verdana, Geneva, Tahoma, sans-serif;
+ font-size: 12px !important;
+ margin: 0 !important;
+ padding: 0 !important;
+ overflow-x: hidden;
+ overflow-y: scroll;
+}
+
+body.dark {
+ background-color: #131313;
+ color: #b2c4dd;
+ scrollbar-base-color: #1c1c1c;
+ scrollbar-face-color: #3b3b3b;
+ scrollbar-3dlight-color: #252525;
+ scrollbar-highlight-color: #252525;
+ scrollbar-track-color: #1c1c1c;
+ scrollbar-arrow-color: #929292;
+ scrollbar-shadow-color: #3b3b3b;
+}
+
+#menu {
+ background-color: #F0F0F0;
+ position: fixed;
+ width: 100%;
+ z-index: 100;
+}
+
+.dark #menu {
+ background-color: #202020;
+}
+
+#statcontent {
+ padding: 7px 7px 7px 7px;
+}
+
+a {
+ color: black;
+ text-decoration: none
+}
+
+.dark a {
+ color: #b2c4dd;
+}
+
+a:hover,
+.dark a:hover {
+ text-decoration: underline;
+}
+
+ul {
+ list-style-type: none;
+ margin: 0;
+ padding: 0;
+ background-color: #333;
+}
+
+li {
+ float: left;
+}
+
+li a {
+ display: block;
+ color: white;
+ text-align: center;
+ padding: 14px 16px;
+ text-decoration: none;
+}
+
+li a:hover:not(.active) {
+ background-color: #111;
+}
+
+.button-container {
+ display: inline-flex;
+ flex-wrap: wrap-reverse;
+ flex-direction: row;
+ align-items: flex-start;
+ overflow-x: hidden;
+ white-space: pre-wrap;
+ padding: 0 4px;
+}
+
+.button {
+ background-color: #dfdfdf;
+ border: 1px solid #cecece;
+ border-bottom-width: 2px;
+ color: rgba(0, 0, 0, 0.7);
+ padding: 6px 4px 4px;
+ text-align: center;
+ text-decoration: none;
+ font-size: 12px;
+ margin: 0;
+ cursor: pointer;
+ transition-duration: 100ms;
+ order: 3;
+ min-width: 40px;
+}
+
+.dark button {
+ background-color: #222222;
+ border-color: #343434;
+ color: rgba(255, 255, 255, 0.5);
+}
+
+.button:hover {
+ background-color: #ececec;
+ transition-duration: 0;
+}
+
+.dark button:hover {
+ background-color: #2e2e2e;
+}
+
+.button:active,
+.button.active {
+ background-color: #ffffff;
+ color: black;
+ border-top-color: #cecece;
+ border-left-color: #cecece;
+ border-right-color: #cecece;
+ border-bottom-color: #ffffff;
+}
+
+.dark .button:active,
+.dark .button.active {
+ background-color: #444444;
+ color: white;
+ border-top-color: #343434;
+ border-left-color: #343434;
+ border-right-color: #343434;
+ border-bottom-color: #ffffff;
+}
+
+.grid-container {
+ margin: -2px;
+ margin-right: -15px;
+}
+
+.grid-item {
+ position: relative;
+ display: inline-block;
+ width: 100%;
+ box-sizing: border-box;
+ overflow: visible;
+ padding: 3px 2px;
+ text-decoration: none;
+}
+
+@media only screen and (min-width: 300px) {
+ .grid-item {
+ width: 50%;
+ }
+}
+
+@media only screen and (min-width: 430px) {
+ .grid-item {
+ width: 33%;
+ }
+}
+
+@media only screen and (min-width: 560px) {
+ .grid-item {
+ width: 25%;
+ }
+}
+
+@media only screen and (min-width: 770px) {
+ .grid-item {
+ width: 20%;
+ }
+}
+
+.grid-item:hover {
+ z-index: 1;
+}
+
+.grid-item:hover .grid-item-text {
+ width: auto;
+ text-decoration: underline;
+}
+
+.grid-item-text {
+ display: inline-block;
+ width: 100%;
+ background-color: #ffffff;
+ margin: 0 -6px;
+ padding: 0 6px;
+ white-space: nowrap;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ pointer-events: none;
+}
+
+.dark .grid-item-text {
+ background-color: #131313;
+}
+
+.link {
+ display: inline;
+ background: none;
+ border: none;
+ padding: 7px 14px;
+ color: black;
+ text-decoration: none;
+ cursor: pointer;
+ font-size: 13px;
+ margin: 2px 2px;
+}
+
+.linkelem {
+ display: inline;
+ background: none;
+ border: none;
+ padding: 0px 14px;
+ color: black;
+ text-decoration: none;
+ cursor: pointer;
+ font-size: 13px;
+ margin: 2px 2px;
+}
+
+.elemcontainer {
+ border-collapse: separate;
+ border-spacing: 0 5px;
+ display: flex;
+}
+
+.elem {
+ background: none;
+ border: none;
+ padding: 0px 14px;
+ font-size: 13px;
+ margin: 2px 2px;
+}
+
+.dark .link {
+ color: #abc6ec;
+}
+
+.dark .linkelem {
+ color: #abc6ec;
+}
+
+.link:hover {
+ text-decoration: underline;
+}
+
+.linkelem:hover {
+ text-decoration: underline;
+}
+
+img {
+ -ms-interpolation-mode: nearest-neighbor;
+ image-rendering: pixelated;
+}
+
+.interview_panel_controls,
+.interview_panel_stats {
+ margin-bottom: 10px;
+}
diff --git a/html/statbrowser.html b/html/statbrowser.html
new file mode 100644
index 0000000000..1aea8811d5
--- /dev/null
+++ b/html/statbrowser.html
@@ -0,0 +1,3 @@
+