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 @@ + +
+
diff --git a/html/statbrowser.js b/html/statbrowser.js new file mode 100644 index 0000000000..2572d121ef --- /dev/null +++ b/html/statbrowser.js @@ -0,0 +1,1084 @@ +// Polyfills and compatibility ------------------------------------------------ +var decoder = decodeURIComponent || unescape; +if (!Array.prototype.includes) { + Array.prototype.includes = function (thing) { + for (var i = 0; i < this.length; i++) { + if (this[i] == thing) return true; + } + return false; + } +} +if (!String.prototype.trim) { + String.prototype.trim = function () { + return this.replace(/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g, ''); + }; +} + +// Status panel implementation ------------------------------------------------ +var status_tab_parts = ["Loading..."]; +var current_tab = null; +var mc_tab_parts = [["Loading...", ""]]; +var href_token = null; +var spells = []; +var spell_tabs = []; +var verb_tabs = []; +var verbs = [["", ""]]; // list with a list inside +var examine = []; +var tickets = []; +var misc = new Map(); +var sdql2 = []; +var permanent_tabs = []; // tabs that won't be cleared by wipes +var turfcontents = []; +var turfname = ""; +var imageRetryDelay = 500; +var imageRetryLimit = 50; +var menu = document.getElementById('menu'); +var under_menu = document.getElementById('under_menu'); +var statcontentdiv = document.getElementById('statcontent'); +var storedimages = []; +var split_admin_tabs = false; + +// Any BYOND commands that could result in the client's focus changing go through this +// to ensure that when we relinquish our focus, we don't do it after the result of +// a command has already taken focus for itself. +function run_after_focus(callback) { + setTimeout(callback, 0); +} + +function createStatusTab(name) { + if (name.indexOf(".") != -1) { + var splitName = name.split("."); + if (split_admin_tabs && splitName[0] === "Admin") + name = splitName[1]; + else + name = splitName[0]; + } + if (document.getElementById(name) || name.trim() == "") { + return; + } + if (!verb_tabs.includes(name) && !permanent_tabs.includes(name)) { + return; + } + var B = document.createElement("BUTTON"); + B.onclick = function () { + tab_change(name); + this.blur(); + }; + B.id = name; + B.textContent = name; + B.className = "button"; + //ORDERING ALPHABETICALLY + B.style.order = name.charCodeAt(0); + if (name == "Status" || name == "MC") { + B.style.order = name == "Status" ? 1 : 2; + } + if (name == "Tickets") { + B.style.order = 3; + } + //END ORDERING + menu.appendChild(B); + SendTabToByond(name); + under_menu.style.height = menu.clientHeight + 'px'; +} + +function removeStatusTab(name) { + if (!document.getElementById(name) || permanent_tabs.includes(name)) { + return; + } + for (var i = verb_tabs.length - 1; i >= 0; --i) { + if (verb_tabs[i] == name) { + verb_tabs.splice(i, 1); + } + } + menu.removeChild(document.getElementById(name)); + TakeTabFromByond(name); + under_menu.style.height = menu.clientHeight + 'px'; +} + +function sortVerbs() { + verbs.sort(function (a, b) { + var selector = a[0] == b[0] ? 1 : 0; + if (a[selector].toUpperCase() < b[selector].toUpperCase()) { + return 1; + } + else if (a[selector].toUpperCase() > b[selector].toUpperCase()) { + return -1; + } + return 0; + }) +} + +window.onresize = function () { + under_menu.style.height = menu.clientHeight + 'px'; +} + +function addPermanentTab(name) { + if (!permanent_tabs.includes(name)) { + permanent_tabs.push(name); + } + createStatusTab(name); +} + +function removePermanentTab(name) { + for (var i = permanent_tabs.length - 1; i >= 0; --i) { + if (permanent_tabs[i] == name) { + permanent_tabs.splice(i, 1); + } + } + removeStatusTab(name); +} + +function checkStatusTab() { + for (var i = 0; i < menu.children.length; i++) { + if (!verb_tabs.includes(menu.children[i].id) && !permanent_tabs.includes(menu.children[i].id)) { + menu.removeChild(menu.children[i]); + } + } +} + +function remove_verb(v) { + var verb_to_remove = v; // to_remove = [verb:category, verb:name] + for (var i = verbs.length - 1; i >= 0; i--) { + var part_to_remove = verbs[i]; + if (part_to_remove[1] == verb_to_remove[1]) { + verbs.splice(i, 1); + } + } +} + +function check_verbs() { + for (var v = verb_tabs.length - 1; v >= 0; v--) { + verbs_cat_check(verb_tabs[v]); + } +} + +function verbs_cat_check(cat) { + var tabCat = cat; + if (cat.indexOf(".") != -1) { + var splitName = cat.split("."); + if (split_admin_tabs && splitName[0] === "Admin") + tabCat = splitName[1]; + else + tabCat = splitName[0]; + } + var verbs_in_cat = 0; + var verbcat = ""; + if (!verb_tabs.includes(tabCat)) { + removeStatusTab(tabCat); + return; + } + for (var v = 0; v < verbs.length; v++) { + var part = verbs[v]; + verbcat = part[0]; + if (verbcat.indexOf(".") != -1) { + var splitName = verbcat.split("."); + if (split_admin_tabs && splitName[0] === "Admin") + verbcat = splitName[1]; + else + verbcat = splitName[0]; + } + if (verbcat != tabCat || verbcat.trim() == "") { + continue; + } + else { + verbs_in_cat = 1; + break; // we only need one + } + } + if (verbs_in_cat != 1) { + removeStatusTab(tabCat); + if (current_tab == tabCat) + tab_change("Status"); + } +} + +function findVerbindex(name, verblist) { + for (var i = 0; i < verblist.length; i++) { + var part = verblist[i]; + if (part[1] == name) + return i; + } +} +function wipe_verbs() { + verbs = [["", ""]]; + verb_tabs = []; + checkStatusTab(); // remove all empty verb tabs +} + +function update_verbs() { + wipe_verbs(); + Byond.sendMessage("Update-Verbs"); +} + +function SendTabsToByond() { + var tabstosend = []; + tabstosend = tabstosend.concat(permanent_tabs, verb_tabs); + for (var i = 0; i < tabstosend.length; i++) { + SendTabToByond(tabstosend[i]); + } +} + +function SendTabToByond(tab) { + Byond.sendMessage("Send-Tabs", {tab: tab}); +} + +//Byond can't have this tab anymore since we're removing it +function TakeTabFromByond(tab) { + Byond.sendMessage("Remove-Tabs", {tab: tab}); +} + +function spell_cat_check(cat) { + var spells_in_cat = 0; + var spellcat = ""; + for (var s = 0; s < spells.length; s++) { + var spell = spells[s]; + spellcat = spell[0]; + if (spellcat == cat) { + spells_in_cat++; + } + } + if (spells_in_cat < 1) { + removeStatusTab(cat); + } +} + +function tab_change(tab) { + if (tab == current_tab) return; + if (document.getElementById(current_tab)) + document.getElementById(current_tab).className = "button"; // disable active on last button + current_tab = tab; + set_byond_tab(tab); + if (document.getElementById(tab)) + document.getElementById(tab).className = "button active"; // make current button active + var spell_tabs_thingy = (spell_tabs.includes(tab)); + var verb_tabs_thingy = (verb_tabs.includes(tab)); + if (tab == "Status") { + draw_status(); + } else if (tab == "MC") { + draw_mc(); + } else if (spell_tabs_thingy) { + draw_spells(tab); + } else if (verb_tabs_thingy) { + draw_verbs(tab); + } else if (tab == "Debug Stat Panel") { + draw_debug(); + } else if (tab == "Tickets") { + draw_tickets(); + } else if (misc.has(tab)) { + draw_misc(tab); + } else if (tab == "Examine") { + draw_examine(); + } else if (tab == "SDQL2") { + draw_sdql2(); + } else if (tab == turfname) { + draw_listedturf(); + } else { + statcontentdiv.textContext = "Loading..."; + } + Byond.winset(Byond.windowId, { + 'is-visible': true, + }); +} + +function set_byond_tab(tab) { + Byond.sendMessage("Set-Tab", {tab: tab}); +} + +function draw_examine() { + statcontentdiv.textContent = ""; + var div_content = document.createElement("div"); + for (var i = 0; i < examine.length; i++) { + var parameter = document.createElement('p'); + parameter.innerHTML = examine[i]; + div_content.appendChild(parameter); + } + var images = div_content.querySelectorAll("img"); + for (var i = 0; i < images.length; i++) { + images[i].addEventListener("error", iconError); + } + document.getElementById("statcontent").appendChild(div_content); +} + +function draw_debug() { + statcontentdiv.textContent = ""; + var wipeverbstabs = document.createElement("div"); + var link = document.createElement("a"); + link.onclick = function () { wipe_verbs() }; + link.textContent = "Wipe All Verbs"; + wipeverbstabs.appendChild(link); + document.getElementById("statcontent").appendChild(wipeverbstabs); + var wipeUpdateVerbsTabs = document.createElement("div"); + var updateLink = document.createElement("a"); + updateLink.onclick = function () { update_verbs() }; + updateLink.textContent = "Wipe and Update All Verbs"; + wipeUpdateVerbsTabs.appendChild(updateLink); + document.getElementById("statcontent").appendChild(wipeUpdateVerbsTabs); + var text = document.createElement("div"); + text.textContent = "Verb Tabs:"; + document.getElementById("statcontent").appendChild(text); + var table1 = document.createElement("table"); + for (var i = 0; i < verb_tabs.length; i++) { + var part = verb_tabs[i]; + // Hide subgroups except admin subgroups if they are split + if (verb_tabs[i].lastIndexOf(".") != -1) { + var splitName = verb_tabs[i].split("."); + if (split_admin_tabs && splitName[0] === "Admin") + part = splitName[1]; + else + continue; + } + var tr = document.createElement("tr"); + var td1 = document.createElement("td"); + td1.textContent = part; + var a = document.createElement("a"); + a.onclick = function (part) { + return function () { removeStatusTab(part) }; + }(part); + a.textContent = " Delete Tab " + part; + td1.appendChild(a); + tr.appendChild(td1); + table1.appendChild(tr); + } + document.getElementById("statcontent").appendChild(table1); + var header2 = document.createElement("div"); + header2.textContent = "Verbs:"; + document.getElementById("statcontent").appendChild(header2); + var table2 = document.createElement("table"); + for (var v = 0; v < verbs.length; v++) { + var part2 = verbs[v]; + var trr = document.createElement("tr"); + var tdd1 = document.createElement("td"); + tdd1.textContent = part2[0]; + var tdd2 = document.createElement("td"); + tdd2.textContent = part2[1]; + trr.appendChild(tdd1); + trr.appendChild(tdd2); + table2.appendChild(trr); + } + document.getElementById("statcontent").appendChild(table2); + var text3 = document.createElement("div"); + text3.textContent = "Permanent Tabs:"; + document.getElementById("statcontent").appendChild(text3); + var table3 = document.createElement("table"); + for (var i = 0; i < permanent_tabs.length; i++) { + var part3 = permanent_tabs[i]; + var trrr = document.createElement("tr"); + var tddd1 = document.createElement("td"); + tddd1.textContent = part3; + trrr.appendChild(tddd1); + table3.appendChild(trrr); + } + document.getElementById("statcontent").appendChild(table3); + +} +function draw_status() { + if (!document.getElementById("Status")) { + createStatusTab("Status"); + current_tab = "Status"; + } + statcontentdiv.textContent = ''; + for (var i = 0; i < status_tab_parts.length; i++) { + if (status_tab_parts[i].trim() == "") { + document.getElementById("statcontent").appendChild(document.createElement("br")); + } else { + var div = document.createElement("div"); + div.textContent = status_tab_parts[i]; + document.getElementById("statcontent").appendChild(div); + } + } + if (verb_tabs.length == 0 || !verbs) { + Byond.command("Fix-Stat-Panel"); + } +} + +function draw_mc() { + statcontentdiv.textContent = ""; + var table = document.createElement("table"); + for (var i = 0; i < mc_tab_parts.length; i++) { + var part = mc_tab_parts[i]; + var tr = document.createElement("tr"); + var td1 = document.createElement("td"); + td1.textContent = part[0]; + var td2 = document.createElement("td"); + if (part[2]) { + var a = document.createElement("a"); + a.href = "?_src_=vars;admin_token=" + href_token + ";Vars=" + part[2]; + a.textContent = part[1]; + td2.appendChild(a); + } else { + td2.textContent = part[1]; + } + tr.appendChild(td1); + tr.appendChild(td2); + table.appendChild(tr); + } + document.getElementById("statcontent").appendChild(table); +} + +function remove_tickets() { + if (tickets) { + tickets = []; + removePermanentTab("Tickets"); + if (current_tab == "Tickets") + tab_change("Status"); + } + checkStatusTab(); +} + +function remove_sdql2() { + if (sdql2) { + sdql2 = []; + removePermanentTab("SDQL2"); + if (current_tab == "SDQL2") + tab_change("Status"); + } + checkStatusTab(); +} + +function iconError(e) { + setTimeout(function () { + if(current_tab != turfname && current_tab != "Examine") { + return; + } + var node = e.target; + var current_attempts = Number(node.getAttribute("data-attempts")) || 0; + if (current_attempts > imageRetryLimit) { + return; + } + var src = node.src; + node.src = null; + node.src = src + '#' + current_attempts; + node.setAttribute("data-attempts", current_attempts + 1); + }, imageRetryDelay); +} + +function draw_listedturf() { + statcontentdiv.textContent = ""; + var table = document.createElement("table"); + for (var i = 0; i < turfcontents.length; i++) { + var part = turfcontents[i]; + if (storedimages[part[1]] == null && part[2]) { + var img = document.createElement("img"); + img.src = part[2]; + img.id = part[1]; + storedimages[part[1]] = part[2]; + img.onerror = iconError; + table.appendChild(img); + } else { + var img = document.createElement("img"); + img.onerror = iconError; + img.src = storedimages[part[1]]; + img.id = part[1]; + table.appendChild(img); + } + var b = document.createElement("div"); + var clickcatcher = ""; + b.className = "link"; + b.onmousedown = function (part) { + // The outer function is used to close over a fresh "part" variable, + // rather than every onmousedown getting the "part" of the last entry. + return function (e) { + e.preventDefault(); + clickcatcher = "?src=" + part[1]; + switch (e.button) { + case 1: + clickcatcher += ";statpanel_item_click=middle"; + break; + case 2: + clickcatcher += ";statpanel_item_click=right"; + break; + default: + clickcatcher += ";statpanel_item_click=left"; + } + if (e.shiftKey) { + clickcatcher += ";statpanel_item_shiftclick=1"; + } + if (e.ctrlKey) { + clickcatcher += ";statpanel_item_ctrlclick=1"; + } + if (e.altKey) { + clickcatcher += ";statpanel_item_altclick=1"; + } + window.location.href = clickcatcher; + } + }(part); + b.textContent = part[0]; + table.appendChild(b); + table.appendChild(document.createElement("br")); + } + document.getElementById("statcontent").appendChild(table); +} + +function remove_listedturf() { + removePermanentTab(turfname); + checkStatusTab(); + if (current_tab == turfname) { + tab_change("Status"); + } +} + +function remove_mc() { + removePermanentTab("MC"); + if (current_tab == "MC") { + tab_change("Status"); + } +}; + +function draw_sdql2() { + statcontentdiv.textContent = ""; + var table = document.createElement("table"); + for (var i = 0; i < sdql2.length; i++) { + var part = sdql2[i]; + var tr = document.createElement("tr"); + var td1 = document.createElement("td"); + td1.textContent = part[0]; + var td2 = document.createElement("td"); + if (part[2]) { + var a = document.createElement("a"); + a.href = "?src=" + part[2] + ";statpanel_item_click=left"; + a.textContent = part[1]; + td2.appendChild(a); + } else { + td2.textContent = part[1]; + } + tr.appendChild(td1); + tr.appendChild(td2); + table.appendChild(tr); + } + document.getElementById("statcontent").appendChild(table); +} + +function draw_tickets() { + statcontentdiv.textContent = ""; + var table = document.createElement("table"); + if (!tickets) { + return; + } + for (var i = 0; i < tickets.length; i++) { + var part = tickets[i]; + var tr = document.createElement("tr"); + var td1 = document.createElement("td"); + td1.textContent = part[0]; + var td2 = document.createElement("td"); + if (part[2]) { + var a = document.createElement("a"); + a.href = "?_src_=holder;admin_token=" + href_token + ";ahelp=" + part[2] + ";ahelp_action=ticket;statpanel_item_click=left;action=ticket"; + a.textContent = part[1]; + td2.appendChild(a); + } else if (part[3]) { + var a = document.createElement("a"); + a.href = "?src=" + part[3] + ";statpanel_item_click=left"; + a.textContent = part[1]; + td2.appendChild(a); + } else { + td2.textContent = part[1]; + } + tr.appendChild(td1); + tr.appendChild(td2); + table.appendChild(tr); + } + document.getElementById("statcontent").appendChild(table); +} + +function draw_misc(tab) { + statcontentdiv.textContent = ""; + var table = document.createElement("table"); + table.className = "elemcontainer"; + let data = misc.get(tab); + if (!data) { + return; + } + for (var i = 0; i < data.length; i++) { + var tr = document.createElement("tr"); + var part = data[i]; + + var td1 = document.createElement("td"); + if(part[0]) { + td1.className = "elem"; + td1.textContent = part[0]; + } + + var td2 = null; + if (part[1] && storedimages[part[1]] == null && part[2]) { + td2 = document.createElement("td"); + var img = document.createElement("img"); + img.src = part[2]; + img.id = part[1]; + storedimages[part[1]] = part[2]; + td2.appendChild(img); + } else if(part[1]) { + td2 = document.createElement("td"); + var img = document.createElement("img"); + img.src = storedimages[part[1]]; + img.id = part[1]; + td2.appendChild(img); + } + var td3 = null; + var b = document.createElement("div"); + var clickcatcher = ""; + if (part[4]) { + b.className = "linkelem"; + b.onmousedown = function (part) { + // The outer function is used to close over a fresh "part" variable, + // rather than every onmousedown getting the "part" of the last entry. + return function (e) { + e.preventDefault(); + clickcatcher = "?src=" + part[4]; + switch (e.button) { + case 1: + clickcatcher += ";statpanel_item_click=middle"; + break; + case 2: + clickcatcher += ";statpanel_item_click=right"; + break; + default: + clickcatcher += ";statpanel_item_click=left"; + } + if (e.shiftKey) { + clickcatcher += ";statpanel_item_shiftclick=1"; + } + if (e.ctrlKey) { + clickcatcher += ";statpanel_item_ctrlclick=1"; + } + if (e.altKey) { + clickcatcher += ";statpanel_item_altclick=1"; + } + window.location.href = clickcatcher; + } + }(part); + } + if(part[3]) { + td3 = document.createElement("td"); + b.textContent = part[3]; + td3.appendChild(b); + } + if(!td2 && !td3) { + td1.className = "elem_span3"; + td1.colSpan += 2; + } + else if (!td2) { + td1.className = "elem_span2"; + td1.colSpan += 1; + } else if (!td3) { + td2.colSpan += 1; + } + tr.appendChild(td1); + if(td2) { + tr.appendChild(td2); + } + if(td3) { + tr.appendChild(td3); + } + table.appendChild(tr); + } + document.getElementById("statcontent").appendChild(table); +} + +function draw_spells(cat) { + statcontentdiv.textContent = ""; + var table = document.createElement("table"); + for (var i = 0; i < spells.length; i++) { + var part = spells[i]; + if (part[0] != cat) continue; + var tr = document.createElement("tr"); + var td1 = document.createElement("td"); + td1.textContent = part[1]; + var td2 = document.createElement("td"); + if (part[3]) { + var a = document.createElement("a"); + a.href = "?src=" + part[3] + ";statpanel_item_click=left"; + a.textContent = part[2]; + td2.appendChild(a); + } else { + td2.textContent = part[2]; + } + tr.appendChild(td1); + tr.appendChild(td2); + table.appendChild(tr); + } + document.getElementById("statcontent").appendChild(table); +} + +function make_verb_onclick(command) { + return function () { + run_after_focus(function () { + Byond.command(command); + }); + }; +} + +function draw_verbs(cat) { + statcontentdiv.textContent = ""; + var table = document.createElement("div"); + var additions = {}; // additional sub-categories to be rendered + table.className = "grid-container"; + sortVerbs(); + if (split_admin_tabs && cat.lastIndexOf(".") != -1) { + var splitName = cat.split("."); + if (splitName[0] === "Admin") + cat = splitName[1]; + } + verbs.reverse(); // sort verbs backwards before we draw + for (var i = 0; i < verbs.length; ++i) { + var part = verbs[i]; + var name = part[0]; + if (split_admin_tabs && name.lastIndexOf(".") != -1) { + var splitName = name.split("."); + if (splitName[0] === "Admin") + name = splitName[1]; + } + var command = part[1]; + var desc = part[2]; + + if (command && name.lastIndexOf(cat, 0) != -1 && (name.length == cat.length || name.charAt(cat.length) == ".")) { + var subCat = name.lastIndexOf(".") != -1 ? name.split(".")[1] : null; + if (subCat && !additions[subCat]) { + var newTable = document.createElement("div"); + newTable.className = "grid-container"; + additions[subCat] = newTable; + } + + var a = document.createElement("a"); + a.href = "#"; + a.onclick = make_verb_onclick(command.replace(/\s/g, "-")); + a.className = "grid-item"; + a.title = desc || "No description"; + var t = document.createElement("span"); + t.textContent = command; + t.className = "grid-item-text"; + a.appendChild(t); + (subCat ? additions[subCat] : table).appendChild(a); + } + } + + // Append base table to view + var content = document.getElementById("statcontent"); + content.appendChild(table); + + // Append additional sub-categories if relevant + for (var cat in additions) { + if (additions.hasOwnProperty(cat)) { + // do addition here + var header = document.createElement("h3"); + header.textContent = cat; + content.appendChild(header); + content.appendChild(additions[cat]); + } + } +} + +function set_theme(which) { + if (which == "light" || which == "vchatlight") { + document.body.className = ""; + set_style_sheet("browserOutput_white"); + } else if (which == "dark" || which == "vchatdark") { + document.body.className = "dark"; + set_style_sheet("browserOutput"); + } +} + +function set_style_sheet(sheet) { + if (document.getElementById("goonStyle")) { + var currentSheet = document.getElementById("goonStyle"); + currentSheet.parentElement.removeChild(currentSheet); + } + var head = document.getElementsByTagName('head')[0]; + var sheetElement = document.createElement("link"); + sheetElement.id = "goonStyle"; + sheetElement.rel = "stylesheet"; + sheetElement.type = "text/css"; + sheetElement.href = sheet + ".css"; + sheetElement.media = 'all'; + head.appendChild(sheetElement); +} + +function restoreFocus() { + run_after_focus(function () { + Byond.winset('map', { + focus: true, + }); + }); +} + +function getCookie(cname) { + var name = cname + '='; + var ca = document.cookie.split(';'); + for (var i = 0; i < ca.length; i++) { + var c = ca[i]; + while (c.charAt(0) == ' ') c = c.substring(1); + if (c.indexOf(name) === 0) { + return decoder(c.substring(name.length, c.length)); + } + } + return ''; +} + +function add_verb_list(payload) { + var to_add = payload; // list of a list with category and verb inside it + to_add.sort(); // sort what we're adding + for (var i = 0; i < to_add.length; i++) { + var part = to_add[i]; + if (!part[0]) + continue; + var category = part[0]; + if (category.indexOf(".") != -1) { + var splitName = category.split("."); + if (split_admin_tabs && splitName[0] === "Admin") + category = splitName[1]; + else + category = splitName[0]; + } + if (findVerbindex(part[1], verbs)) + continue; + if (verb_tabs.includes(category)) { + verbs.push(part); + if (current_tab == category) { + draw_verbs(category); // redraw if we added a verb to the tab we're currently in + } + } else if (category) { + verb_tabs.push(category); + verbs.push(part); + createStatusTab(category); + } + } +}; + +function init_spells() { + var cat = ""; + for (var i = 0; i < spell_tabs.length; i++) { + cat = spell_tabs[i]; + if (cat.length > 0) { + verb_tabs.push(cat); + createStatusTab(cat); + } + } +} + +document.addEventListener("mouseup", restoreFocus); +document.addEventListener("keyup", restoreFocus); + +if (!current_tab) { + addPermanentTab("Status"); + tab_change("Status"); +} + +window.onload = function () { + Byond.sendMessage("Update-Verbs"); +}; + +Byond.subscribeTo('update_spells', function (payload) { + spell_tabs = payload.spell_tabs; + var do_update = false; + if (spell_tabs.includes(current_tab)) { + do_update = true; + } + init_spells(); + if (payload.actions) { + spells = payload.actions; + if (do_update) { + draw_spells(current_tab); + } + } else { + remove_spells(); + } +}); + +Byond.subscribeTo('remove_verb_list', function (v) { + var to_remove = v; + for (var i = 0; i < to_remove.length; i++) { + remove_verb(to_remove[i]); + } + check_verbs(); + sortVerbs(); + if (verb_tabs.includes(current_tab)) + draw_verbs(current_tab); +}); + +// passes a 2D list of (verbcategory, verbname) creates tabs and adds verbs to respective list +// example (IC, Say) +Byond.subscribeTo('init_verbs', function (payload) { + wipe_verbs(); // remove all verb categories so we can replace them + checkStatusTab(); // remove all status tabs + verb_tabs = payload.panel_tabs; + verb_tabs.sort(); // sort it + var do_update = false; + var cat = ""; + for (var i = 0; i < verb_tabs.length; i++) { + cat = verb_tabs[i]; + createStatusTab(cat); // create a category if the verb doesn't exist yet + } + if (verb_tabs.includes(current_tab)) { + do_update = true; + } + if (payload.verblist) { + add_verb_list(payload.verblist); + sortVerbs(); // sort them + if (do_update) { + draw_verbs(current_tab); + } + } + SendTabsToByond(); +}); + +Byond.subscribeTo('update_stat', function (payload) { + status_tab_parts = [payload.ping_str]; + var parsed = payload.global_data; + + for (var i = 0; i < parsed.length; i++) if (parsed[i] != null) status_tab_parts.push(parsed[i]); + + parsed = payload.other_str; + + for (var i = 0; i < parsed.length; i++) if (parsed[i] != null) status_tab_parts.push(parsed[i]); + + if (current_tab == "Status") { + draw_status(); + } else if (current_tab == "Debug Stat Panel") { + draw_debug(); + } +}); + +Byond.subscribeTo('update_mc', function (payload) { + mc_tab_parts = payload.mc_data; + mc_tab_parts.splice(0, 0, ["Location:", payload.coord_entry]); + + if (!verb_tabs.includes("MC")) { + verb_tabs.push("MC"); + } + + createStatusTab("MC"); + + if (current_tab == "MC") { + draw_mc(); + } +}); + +Byond.subscribeTo('remove_spells', function () { + for (var s = 0; s < spell_tabs.length; s++) { + removeStatusTab(spell_tabs[s]); + } +}); + +Byond.subscribeTo('init_spells', function () { + var cat = ""; + for (var i = 0; i < spell_tabs.length; i++) { + cat = spell_tabs[i]; + if (cat.length > 0) { + verb_tabs.push(cat); + createStatusTab(cat); + } + } +}); + +Byond.subscribeTo('check_spells', function () { + for (var v = 0; v < spell_tabs.length; v++) { + spell_cat_check(spell_tabs[v]); + } +}); + +Byond.subscribeTo('create_debug', function () { + if (!document.getElementById("Debug Stat Panel")) { + addPermanentTab("Debug Stat Panel"); + } else { + removePermanentTab("Debug Stat Panel"); + } +}); + +Byond.subscribeTo('create_listedturf', function (TN) { + remove_listedturf(); // remove the last one if we had one + turfname = TN; + addPermanentTab(turfname); + tab_change(turfname); +}); + +Byond.subscribeTo('create_misc', function (TN) { + addPermanentTab(TN); +}); + +Byond.subscribeTo('remove_misc', function (TN) { + removePermanentTab(TN); +}); + +Byond.subscribeTo('remove_admin_tabs', function () { + href_token = null; + remove_mc(); + remove_tickets(); + remove_sdql2(); +}); + +Byond.subscribeTo('update_listedturf', function (TC) { + turfcontents = TC; + if (current_tab == turfname) { + draw_listedturf(); + } +}); + +Byond.subscribeTo('update_misc', function (payload) { + let TN = payload.TN + let TC = payload.TC + misc.set(TN,TC); + if (current_tab == TN) { + draw_misc(TN); + } +}); + +Byond.subscribeTo('update_split_admin_tabs', function (status) { + status = (status == true); + + if (split_admin_tabs !== status) { + if (split_admin_tabs === true) { + removeStatusTab("Events"); + removeStatusTab("Fun"); + removeStatusTab("Game"); + } + update_verbs(); + } + split_admin_tabs = status; +}); + +Byond.subscribeTo('add_admin_tabs', function (ht) { + href_token = ht; + addPermanentTab("MC"); + addPermanentTab("Tickets"); +}); + +Byond.subscribeTo('update_examine', function (S) { + examine = S; + if (examine.length > 0 && !verb_tabs.includes("Examine")) { + verb_tabs.push("Examine"); + addPermanentTab("Examine") + } + if (current_tab == "Examine") { + draw_examine(); + } + //tab_change("Examine"); //This is handled by DM code and a pref setting already +}) + +Byond.subscribeTo('update_sdql2', function (S) { + sdql2 = S; + if (sdql2.length > 0 && !verb_tabs.includes("SDQL2")) { + verb_tabs.push("SDQL2"); + addPermanentTab("SDQL2"); + } + if (current_tab == "SDQL2") { + draw_sdql2(); + } +}); + +Byond.subscribeTo('update_tickets', function (T) { + tickets = T; + if (!verb_tabs.includes("Tickets")) { + verb_tabs.push("Tickets"); + addPermanentTab("Tickets"); + } + if (current_tab == "Tickets") { + draw_tickets(); + } +}); + +Byond.subscribeTo('remove_listedturf', remove_listedturf); + +Byond.subscribeTo('remove_sdql2', remove_sdql2); + +Byond.subscribeTo('remove_mc', remove_mc); + +Byond.subscribeTo('add_verb_list', add_verb_list); diff --git a/interface/skin.dmf b/interface/skin.dmf index 8316b0f669..af4281a1a2 100644 --- a/interface/skin.dmf +++ b/interface/skin.dmf @@ -1346,19 +1346,17 @@ window "rpane" size = 640x480 anchor1 = -1,-1 anchor2 = -1,-1 - background-color = none saved-params = "pos;size;is-minimized;is-maximized" is-pane = true - outer-size = 656x538 - inner-size = 640x499 elem "rpanewindow" type = CHILD - pos = 0,-3 - size = 640x499 + pos = 0,30 + size = 640x445 anchor1 = 0,0 anchor2 = 100,100 background-color = none saved-params = "splitter" + left = "statwindow" right = "outputwindow" is-vert = false elem "patreon" @@ -1463,7 +1461,7 @@ window "rpane" is-visible = false saved-params = "is-checked" text = "Info" - command = ".winset \"rpanewindow.left=infowindow\"" + command = ".winset \"rpanewindow.left=statwindow\"" group = "rpanemode" button-type = pushbox elem "mediapanel" @@ -1520,28 +1518,6 @@ window "ooc_notes" anchor2 = 80,100 saved-params = "" -window "infowindow" - elem "infowindow" - type = MAIN - pos = 281,0 - size = 640x480 - anchor1 = -1,-1 - anchor2 = -1,-1 - saved-params = "pos;size;is-minimized;is-maximized" - title = "Info" - is-pane = true - elem "info" - type = INFO - pos = 0,0 - size = 638x477 - anchor1 = 0,0 - anchor2 = 100,100 - is-default = true - saved-params = "" - highlight-color = #00aa00 - on-show = ".winset\"rpane.infob.is-visible=true;rpane.browseb.is-visible=true?rpane.infob.pos=130,0:rpane.infob.pos=65,0 rpane.textb.is-visible=true rpane.infob.is-checked=true rpane.rpanewindow.pos=0,30 rpane.rpanewindow.size=0x0 rpane.rpanewindow.left=infowindow\"" - on-hide = ".winset\"rpane.infob.is-visible=false;rpane.browseb.is-visible=true?rpane.browseb.is-checked=true rpane.rpanewindow.left=browserwindow:rpane.textb.is-visible=true rpane.rpanewindow.pos=0,30 rpane.rpanewindow.size=0x0 rpane.rpanewindow.left=\"" - window "text_editor" elem "text_editor" type = MAIN @@ -1610,3 +1586,21 @@ window "tgui_say" anchor1 = 0,0 anchor2 = 0,0 saved-params = "" + +window "statwindow" + elem "statwindow" + type = MAIN + pos = 281,0 + size = 640x480 + anchor1 = -1,-1 + anchor2 = -1,-1 + saved-params = "pos;size;is-minimized;is-maximized" + is-pane = true + elem "statbrowser" + type = BROWSER + pos = 0,0 + size = 638x477 + anchor1 = 0,0 + anchor2 = 100,100 + is-visible = false + saved-params = "" diff --git a/maps/gateway_archive_vr/wildwest.dm b/maps/gateway_archive_vr/wildwest.dm index 155e1d8af3..909480877c 100644 --- a/maps/gateway_archive_vr/wildwest.dm +++ b/maps/gateway_archive_vr/wildwest.dm @@ -69,7 +69,7 @@ if("Immortality") to_chat(user, "Your wish is granted, but at a terrible cost...") to_chat(user, "The Wish Granter punishes you for your selfishness, claiming your soul and warping your body to match the darkness in your heart.") - user.verbs += /mob/living/carbon/proc/immortality + add_verb(user, /mob/living/carbon/proc/immortality) user.dna.mutantrace = "shadow" user.update_mutantrace() if("To Kill") diff --git a/maps/gateway_vr/wildwest.dm b/maps/gateway_vr/wildwest.dm index f7c14b2dde..008607253c 100644 --- a/maps/gateway_vr/wildwest.dm +++ b/maps/gateway_vr/wildwest.dm @@ -73,7 +73,7 @@ if("Immortality") to_chat(user, "Your wish is granted, but at a terrible cost...") to_chat(user, "The Wish Granter punishes you for your selfishness, claiming your soul and warping your body to match the darkness in your heart.") - user.verbs += /mob/living/carbon/proc/immortality + add_verb(user, /mob/living/carbon/proc/immortality) user.dna.mutantrace = "shadow" user.update_mutantrace() if("To Kill") diff --git a/vorestation.dme b/vorestation.dme index 9ad0ec151a..7ce92707d3 100644 --- a/vorestation.dme +++ b/vorestation.dme @@ -128,6 +128,7 @@ #include "code\__defines\sprite_sheets.dm" #include "code\__defines\sqlite_defines.dm" #include "code\__defines\stat_tracking.dm" +#include "code\__defines\statpanel.dm" #include "code\__defines\subsystems.dm" #include "code\__defines\supply.dm" #include "code\__defines\targeting.dm" @@ -196,6 +197,7 @@ #include "code\_helpers\type2type.dm" #include "code\_helpers\unsorted.dm" #include "code\_helpers\unsorted_vr.dm" +#include "code\_helpers\verbs.dm" #include "code\_helpers\view.dm" #include "code\_helpers\visual_filters.dm" #include "code\_helpers\icons\flatten.dm" @@ -345,6 +347,7 @@ #include "code\controllers\subsystems\sounds.dm" #include "code\controllers\subsystems\sqlite.dm" #include "code\controllers\subsystems\SSvote.dm" +#include "code\controllers\subsystems\statpanel.dm" #include "code\controllers\subsystems\sun.dm" #include "code\controllers\subsystems\supply.dm" #include "code\controllers\subsystems\tgui.dm" @@ -361,6 +364,7 @@ #include "code\controllers\subsystems\processing\fastprocess.dm" #include "code\controllers\subsystems\processing\instruments.dm" #include "code\controllers\subsystems\processing\obj.dm" +#include "code\controllers\subsystems\processing\obj_tab_items.dm" #include "code\controllers\subsystems\processing\processing.dm" #include "code\controllers\subsystems\processing\projectiles.dm" #include "code\controllers\subsystems\processing\turfs.dm" @@ -415,6 +419,7 @@ #include "code\datums\autolathe\tools.dm" #include "code\datums\autolathe\tools_vr.dm" #include "code\datums\components\_component.dm" +#include "code\datums\components\connect_mob_behalf.dm" #include "code\datums\components\material_container.dm" #include "code\datums\components\overlay_lighting.dm" #include "code\datums\components\recursive_move.dm"