Removes goonchat, adds TGChat and TG Stat Panels (#16514)

* tgui the beginning

* binaries and the like

* Bring in the last of it

* Example radio UI

* delete example

* NTOS Main Menu, start on manifest, tgui states

* tasks.json

* gunnery ui pt 1

* okay

* fix everything

* scss update

* oops

* manifest gigablast

* downloader part 1

* download prt 2

* NTOSDownloader final

* mfw committing to_worlds

* gunnery console pt2

* i cooked

* targeting (finished)

* one vueui down

* voting ui almost done

* MY MIND FEELS LIKE AN ARCH ENEMYYYY

* voting ui down

* photocopier

* ntos config + download fixes

* photocopier 2

* refactor define

* NTOS client manager + fixes

* fax machine final (it also uses toner now)

* marching forwards... left behind...

* ntnrc part 1

* canister

* add quotes

* portable pumps pt1 + more backgrounds

* oops

* finish the portable pump

* freezers

so I'll keep on pushing forward... you haven't seen the last of me... oooooooh...

* doors ui pt1

* finish doors UI (forgive me wildkins it's a bit of shitcode)

* vitals monitor, make things use labeled lists, new backgrounds

* mais j'envoyé aucun mayday...

* maglock pt1

* pour ça je me suis perdu...

* infrared

* fix that

* prox sensor pt1

* prox sensor

* signaler (this was actually pretty hard)

* atmos control pt1

* atmos control pt1.1

* atmos pt 2

* fuel injector

* multitool UI

* jammer

* list viewer

* APC

* portgen

* targeting console updates + SMES ui

* new themes, shield generator

* supermatter

* Add ore detector and (shitty) NTNet Relay

* orderterminal pt1

* orderterminal pt2

* smartfridge

* Add (air-)tank GUI update ore detector size

* Adds Transfer Valves

* Add AtmoScrubber

* analyzer pt1

* weapons analyzer pt2

* bodyscanner pt1

* bodyscanner pt2

* fix this shitcode

* seed storage

* appearance changer

* appearance changer final

* sleeper pt1

* sleeper

* gps

* vehicles

* chem dispenser

* lily request

* holopad

* tgui modules pt1

* ppanel

* damage menu

* fixes

* im here too now

* follow menu, search bars

* quikpay

* quikpay fixes

* circuit printer

* ppanel

* ppanel updates

* pai

* turret controls (i want to kill myself)

* tweak

* remove the boardgame

* guntracker

* implant tracker

* penal mechs

come close to me, come close to me

* chem codex

* pai radio

* doorjack

* pai directives

* signaler removal, sensors

* ghost spawner

* spawnpoint

* fixes

* teleporter

* one more to the chopping block

* account database

* remove divider

* scanner, atmos

* latejoin ui pt1

* latejoin

* records pt1

* RECORDS UI DONE

* delete interpreter & records

* CHAT FUCKING CLIENT

* data updates

* fix some things

* final UI, log

* basic nanoui fix

* antag panel

* remove vueui

* atm update

* vending update

* warrants, cameras

* ntmonitor

* time comes for all

* preserve this legacy

* bring that back (oops)

* rcon, ui auto update for computer UIs, remove rcon computers

* alarm monitoring (a bit broke and also todo: add custom alarm monitoring programs to a few consoles)

* A LIKE SUPREME

* a

* power monitor

* lights on

* fuck this code, fuck nanoui modules, and fuck nanoui

* LEAVE IT OH SO FAR BEHIND

* fix alarm monitoring for synths

* I SAW IN YOU WHAT LIFE WAS MISSING

* comms console

* idcard and record updates

* turn the light on

* arcade

* pt2

* news browser

* static

* crusher

* f

* COULD I JUST SLEIGH THE GOLD FROM THE BALLS? I'M SO FRUSTRATED OH COULD YOU TELL? IF I HEAR ONE MORE VUEUI OR ONE NANOUI I'M GONNA LOSE IT SO LET ME GOOOOOOOOOOOOOOOOO

* codeowners & suit sensors

* html ui style removal

* make lint happy

* tgchat

* tgpanels pt1

* THE SOUL LONGS FOR OBLIVION!!!!!!!!!!!!!!!!!

* figure out why stat isnt working

* goodbye ping

* shhh

* stat updates

* An oath sworn in scors! Omni vortex lies!

* final almost edits

* fix that

* last skin adjustments

* resist and disorder

* i slowly get up and turn off the noise, already fed up...

* pleaseeeeeeeeeeeeeee

* THE CREDIT LARP IS NECESSARY

* i hold the keys

* RISE UP

* fix that?

* harry's suggestions xoxo

* runtime fix pt2

* You are the only thing that I still care about

* fix runtimes and cl

* whoops

* misc fixes

* fix that too

* adds build workflow

* f

* Update update_tgui.yml

* adds some needed steps

* ATM

* misc fixes and tweaks

* fixes 2

* make newscasters usable and fix use power on freezers

* turret control is clearer

* remove duplicate

* makes some verb tabs work properly

* makes verbs work properly for real

* sans moi

* fixes pt2

* fix the chat unnecessarily reloading

* fixes

* epic

* fixes

* fix missing consoles

---------

Co-authored-by: John Wildkins <john.wildkins@gmail.com>
Co-authored-by: Matt Atlas <liermattia@gmail.com>
Co-authored-by: harryob <55142896+harryob@users.noreply.github.com>
Co-authored-by: Werner <Arrow768@users.noreply.github.com>
Co-authored-by: Geeves <ggrobler447@gmail.com>
Co-authored-by: harryob <me@harryob.live>
This commit is contained in:
Matt Atlas
2023-06-26 02:00:14 +02:00
committed by GitHub
co-authored by John Wildkins Matt Atlas harryob Werner Geeves harryob
parent 3cc846c1fe
commit 659752e2ea
266 changed files with 4277 additions and 5936 deletions
+2 -2
View File
@@ -10,11 +10,11 @@
/datum/controller/proc/Recover()
/datum/controller/proc/stat_entry()
/datum/controller/proc/stat_entry(msg)
// Called when SSexplosives begins processing explosions.
/datum/controller/proc/ExplosionStart()
// Called when SSexplosives finishes processing all queued explosions.
/datum/controller/proc/ExplosionEnd()
+3 -5
View File
@@ -97,10 +97,8 @@ var/datum/controller/failsafe/Failsafe
/datum/controller/failsafe/proc/defcon_pretty()
return defcon
/datum/controller/failsafe/stat_entry()
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])"))
/datum/controller/failsafe/stat_entry(msg)
msg = "Defcon: [defcon_pretty()] (Interval: [Failsafe.processing_interval] | Iteration: [Failsafe.master_iteration])"
return msg
#undef FAILSAFE_MSG
+6 -7
View File
@@ -576,13 +576,12 @@ var/CURRENT_TICKLIMIT = TICK_LIMIT_RUNNING
if(!skip_ticks)
skip_ticks = 1
/datum/controller/master/stat_entry()
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)]%)) (Internal Tick Usage: [round(MAPTICK_LAST_TICK_USAGE,0.1)]%)")
stat("Master Controller:", statclick.update("(TickRate:[Master.processing]) (Iteration:[Master.iteration]) (TickLimit: [round(CURRENT_TICKLIMIT, 0.1)])"))
/datum/controller/master/stat_entry(msg)
msg = "(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_TICK_USAGE,0.1)]%) (TickRate:[Master.processing]) \
(Iteration:[Master.iteration]) (TickLimit: [round(CURRENT_TICKLIMIT, 0.1)])"
return msg
/datum/controller/master/ExplosionStart()
for (var/thing in subsystems)
+5 -29
View File
@@ -181,36 +181,12 @@
return time
//hook for printing stats to the "MC" statuspanel for admins to see performance and related stats etc.
/datum/controller/subsystem/stat_entry(var/msg)
if(!statclick)
statclick = new/obj/effect/statclick/debug(null, "Initializing...", src)
var/title = name
if (Master.initializing)
msg = "[stat_entry_init()]\t[msg]"
var/letter = init_state_letter()
if (letter)
title = "\[[letter]] [title]"
/datum/controller/subsystem/stat_entry(msg)
if(can_fire && !(SS_NO_FIRE & flags) && !Master.initializing)
msg = "[round(cost,1)]ms|[round(tick_usage,1)]%([round(tick_overrun,1)]%)|[round(ticks,0.1)]\t[msg]"
else
msg = "[stat_entry_run()]\t[msg]"
if (can_fire && !suspended && !(flags & SS_NO_FIRE))
title = "\[[state_letter()]] [title]"
stat(title, statclick.update(msg))
// Generates the message shown before a subsystem during MC initialization.
/datum/controller/subsystem/proc/stat_entry_init()
if (init_state == SS_INITSTATE_DONE)
. = "DONE ([init_time]s)"
else if (flags & SS_NO_INIT)
. = "NO INIT"
else if (init_state == SS_INITSTATE_STARTED)
if (init_start)
. = "LOAD ([(REALTIMEOFDAY - init_start)/10]s)"
else
. = "LOAD"
else
. = "WAIT"
msg = "OFFLINE\t[msg]"
return msg
// Generates the message shown before a subsystem during normal MC operation.
/datum/controller/subsystem/proc/stat_entry_run()
+3 -7
View File
@@ -121,13 +121,9 @@ Class Procs:
next_fire = world.time + wait
can_fire = TRUE
/datum/controller/subsystem/air/stat_entry()
var/out = "TtU:[tiles_to_update.len] "
out += "ZtU:[zones_to_update.len] "
out += "AFZ:[active_fire_zones.len] "
out += "AH:[active_hotspots.len] "
out += "AE:[active_edges.len]"
..(out)
/datum/controller/subsystem/air/stat_entry(msg)
msg = "TtU:[tiles_to_update.len] ZtU:[zones_to_update.len] AFZ:[active_fire_zones.len] AH:[active_hotspots.len] AE:[active_edges.len]"
return msg
/datum/controller/subsystem/air/New()
NEW_SS_GLOBAL(SSair)
+4 -3
View File
@@ -22,7 +22,7 @@ var/datum/controller/subsystem/alarm/SSalarm
/datum/controller/subsystem/alarm/Initialize(timeofday)
all_handlers = list(atmosphere_alarm, camera_alarm, fire_alarm, motion_alarm, power_alarm)
/datum/controller/subsystem/alarm/fire(resumed = FALSE)
if (!resumed)
current = all_handlers.Copy()
@@ -45,5 +45,6 @@ var/datum/controller/subsystem/alarm/SSalarm
/datum/controller/subsystem/alarm/proc/number_of_active_alarms()
return active_alarm_cache.len
/datum/controller/subsystem/alarm/stat_entry()
..("A:[active_alarm_cache.len]")
/datum/controller/subsystem/alarm/stat_entry(msg)
msg = "A:[active_alarm_cache.len]"
return ..()
+3 -2
View File
@@ -12,8 +12,9 @@
/datum/controller/subsystem/ao/New()
NEW_SS_GLOBAL(SSocclusion)
/datum/controller/subsystem/ao/stat_entry()
..("P:[queue.len]")
/datum/controller/subsystem/ao/stat_entry(msg)
msg = "P:[queue.len]"
return ..()
/datum/controller/subsystem/ao/Initialize()
fire(FALSE, TRUE)
+28 -69
View File
@@ -1,83 +1,42 @@
var/regex/is_http_protocol = regex("^https?://")
/*!
* Copyright (c) 2020 Aleksej Komarov
* SPDX-License-Identifier: MIT
*/
var/datum/controller/subsystem/chat/SSchat
/datum/controller/subsystem/chat
name = "Chat"
flags = SS_TICKER
wait = 1
runlevels = RUNLEVELS_DEFAULT | RUNLEVEL_LOBBY
priority = SS_PRIORITY_CHAT
init_order = SS_INIT_CHAT
var/list/payload = list()
/datum/controller/subsystem/chat/Initialize()
NEW_SS_GLOBAL(SSchat)
var/list/payload_by_client = list()
/datum/controller/subsystem/chat/fire()
for(var/i in payload)
var/client/C = i
to_target(C, output(payload[C], "browseroutput:output"))
payload -= C
for(var/key in payload_by_client)
var/client/client = key
var/payload = payload_by_client[key]
payload_by_client -= key
if(client)
// Send to tgchat
client.tgui_panel?.window.send_message("chat/message", payload)
// Send to old chat
for(var/message in payload)
to_target(client, message_to_html(message))
if(MC_TICK_CHECK)
return
/datum/controller/subsystem/chat/proc/queue(target, message, handle_whitespace = TRUE, trailing_newline = TRUE)
if(!target || !message)
return
if(!istext(message))
CRASH("to_chat called with invalid input type")
if(target == world)
target = clients
//Some macros remain in the string even after parsing and fuck up the eventual output
var/original_message = message
message = replacetext(message, "\improper", "")
message = replacetext(message, "\proper", "")
if(handle_whitespace)
message = replacetext(message, "\n", "<br>")
message = replacetext(message, "\t", "[FOURSPACES][FOURSPACES]")
if (trailing_newline)
message += "<br>"
//url_encode it TWICE, this way any UTF-8 characters are able to be decoded by the Javascript.
//Do the double-encoding here to save nanoseconds
var/twiceEncoded = url_encode(url_encode(message))
/datum/controller/subsystem/chat/proc/queue(target, message)
if(islist(target))
for(var/I in target)
var/client/C = CLIENT_FROM_VAR(I) //Grab us a client if possible
if(!C)
return
//Send it to the old style output window.
legacy_chat(C, original_message)
if(!C?.chatOutput || C.chatOutput.broken) //A player who hasn't updated his skin file.
continue
if(!C.chatOutput.loaded) //Client still loading, put their messages in a queue
C.chatOutput.messageQueue += message
continue
payload[C] += twiceEncoded
else
var/client/C = CLIENT_FROM_VAR(target) //Grab us a client if possible
if(!C)
return
//Send it to the old style output window.
legacy_chat(C, original_message)
if(!C?.chatOutput || C.chatOutput.broken) //A player who hasn't updated his skin file.
return
if(!C.chatOutput.loaded) //Client still loading, put their messages in a queue
C.chatOutput.messageQueue += message
return
payload[C] += twiceEncoded
for(var/_target in target)
var/client/client = CLIENT_FROM_VAR(_target)
if(client)
LAZYADD(payload_by_client[client], list(message))
return
var/client/client = CLIENT_FROM_VAR(target)
if(client)
LAZYADD(payload_by_client[client], list(message))
+3 -2
View File
@@ -77,8 +77,9 @@ var/datum/controller/subsystem/chemistry/SSchemistry
for(var/_R in subtypesof(/singleton/reagent/))
check_specific_heat(_R)
/datum/controller/subsystem/chemistry/stat_entry()
..("AH:[active_holders.len]")
/datum/controller/subsystem/chemistry/stat_entry(msg)
msg = "AH:[active_holders.len]"
return ..()
/datum/controller/subsystem/chemistry/New()
NEW_SS_GLOBAL(SSchemistry)
+4 -3
View File
@@ -65,12 +65,13 @@ var/datum/controller/subsystem/effects/SSeffects
if (EFFECT_DESTROY)
STOP_VISUAL(V)
qdel(V)
if (MC_TICK_CHECK)
return
/datum/controller/subsystem/effects/stat_entry()
..("E:[effect_systems.len] V:[visuals.len]")
/datum/controller/subsystem/effects/stat_entry(msg)
msg = "E:[effect_systems.len] V:[visuals.len]"
return ..()
/datum/controller/subsystem/effects/Recover()
if (istype(SSeffects))
+3 -2
View File
@@ -72,8 +72,9 @@ var/datum/controller/subsystem/events/SSevents
if (MC_TICK_CHECK)
return
/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/proc/event_complete(datum/event/E)
if(!E.event_meta || !E.severity) // datum/event is used here and there for random reasons, maintaining "backwards compatibility"
+4 -3
View File
@@ -146,7 +146,7 @@ var/datum/controller/subsystem/explosives/SSexplosives
var/dist = get_dist(M_turf, epicenter)
var/explosion_dir = angle2text(Get_Angle(M_turf, epicenter))
if (reception == 2 && (M.ear_deaf <= 0 || !M.ear_deaf)) //Dont play sounds to deaf people
// Anyone with sensitive hearing gets a bonus to hearing explosions
var/extendeddist = closedist
if(ishuman(M))
@@ -427,8 +427,9 @@ var/datum/controller/subsystem/explosives/SSexplosives
if (suspended)
wake()
/datum/controller/subsystem/explosives/stat_entry()
..("P:[work_queue.len]")
/datum/controller/subsystem/explosives/stat_entry(msg)
msg ="P:[work_queue.len]"
return ..()
// The data datum for explosions.
/datum/explosiondata
+3 -2
View File
@@ -17,8 +17,9 @@
/datum/controller/subsystem/falling/New()
NEW_SS_GLOBAL(SSfalling)
/datum/controller/subsystem/falling/stat_entry()
..("F:[falling.len]")
/datum/controller/subsystem/falling/stat_entry(msg)
msg = "F:[falling.len]"
return ..()
/datum/controller/subsystem/falling/fire(resumed = 0)
if (!resumed)
+2 -2
View File
@@ -43,7 +43,7 @@ var/datum/controller/subsystem/garbage_collector/SSgarbage
NEW_SS_GLOBAL(SSgarbage)
/datum/controller/subsystem/garbage_collector/stat_entry(msg)
msg += "W:[tobequeued.len]|Q:[queue.len]|D:[delslasttick]|G:[gcedlasttick]|"
msg = "W:[tobequeued.len]|Q:[queue.len]|D:[delslasttick]|G:[gcedlasttick]|"
msg += "GR:"
if (!(delslasttick+gcedlasttick))
msg += "n/a|"
@@ -55,7 +55,7 @@ var/datum/controller/subsystem/garbage_collector/SSgarbage
msg += "n/a|"
else
msg += "TGR:[round((totalgcs/(totaldels+totalgcs))*100, 0.01)]%"
..(msg)
return ..()
/datum/controller/subsystem/garbage_collector/fire()
HandleToBeQueued()
@@ -12,8 +12,9 @@ var/datum/controller/subsystem/listener/SSlistener
/datum/controller/subsystem/listener/Recover()
listeners = SSlistener.listeners
/datum/controller/subsystem/listener/stat_entry()
..("L:[listeners.len]")
/datum/controller/subsystem/listener/stat_entry(msg)
msg = "L:[listeners.len]"
return ..()
/datum/controller/subsystem/listener/proc/register(listener/L)
LAZYINITLIST(listeners[L.channel])
@@ -22,7 +23,7 @@ var/datum/controller/subsystem/listener/SSlistener
/datum/controller/subsystem/listener/proc/unregister(listener/L)
if (listeners[L.channel])
listeners[L.channel] -= L
if (!LAZYLEN(listeners[L.channel]))
listeners -= L.channel
+4 -3
View File
@@ -19,13 +19,14 @@ var/datum/controller/subsystem/icon_smooth/SSicon_smooth
/datum/controller/subsystem/icon_smooth/Recover()
smooth_queue = SSicon_smooth.smooth_queue
/datum/controller/subsystem/icon_smooth/stat_entry()
..("Q:[smooth_queue.len]")
/datum/controller/subsystem/icon_smooth/stat_entry(msg)
msg = "Q:[smooth_queue.len]"
return ..()
/datum/controller/subsystem/icon_smooth/fire()
if (explosion_in_progress)
return
while(smooth_queue.len)
var/atom/A = smooth_queue[smooth_queue.len]
smooth_queue.len--
+4 -3
View File
@@ -6,14 +6,15 @@
flags = SS_TICKER
priority = SS_PRIORITY_ICON_UPDATE
init_order = SS_INIT_ICON_UPDATE
var/list/queue = list()
/datum/controller/subsystem/icon/New()
NEW_SS_GLOBAL(SSicon_update)
/datum/controller/subsystem/icon/stat_entry()
..("QU:[queue.len]")
/datum/controller/subsystem/icon/stat_entry(msg)
msg = "QU:[queue.len]"
return ..()
/datum/controller/subsystem/icon/Initialize()
fire(FALSE, TRUE)
@@ -136,8 +136,9 @@ var/datum/controller/subsystem/atlas/SSatlas
)
)
/datum/controller/subsystem/atlas/stat_entry()
..("W:{X:[world.maxx] Y:[world.maxy] Z:[world.maxz]} ZL:[z_levels]")
/datum/controller/subsystem/atlas/stat_entry(msg)
msg = "W:{X:[world.maxx] Y:[world.maxy] Z:[world.maxz]} ZL:[z_levels]"
return ..()
/datum/controller/subsystem/atlas/New()
NEW_SS_GLOBAL(SSatlas)
@@ -323,4 +324,4 @@ var/datum/controller/subsystem/atlas/SSatlas
/proc/commstation_name()
ASSERT(current_map)
return current_map.dock_name
return current_map.dock_name
+4 -3
View File
@@ -37,7 +37,7 @@ var/datum/controller/subsystem/lighting/SSlighting
/datum/controller/subsystem/lighting/New()
NEW_SS_GLOBAL(SSlighting)
/datum/controller/subsystem/lighting/stat_entry()
/datum/controller/subsystem/lighting/stat_entry(msg)
var/list/out = list(
#ifdef USE_INTELLIGENT_LIGHTING_UPDATES
"IUR: [total_ss_updates ? round(total_instant_updates/(total_instant_updates+total_ss_updates)*100, 0.1) : "NaN"]%\n",
@@ -46,7 +46,8 @@ var/datum/controller/subsystem/lighting/SSlighting
"\tP:{L:[light_queue.len - (lq_idex - 1)]|C:[corner_queue.len - (cq_idex - 1)]|O:[overlay_queue.len - (oq_idex - 1)]}\n",
"\tL:{L:[processed_lights]|C:[processed_corners]|O:[processed_overlays]}\n"
)
..(out.Join())
msg = out.Join()
return ..()
#ifdef USE_INTELLIGENT_LIGHTING_UPDATES
@@ -181,7 +182,7 @@ var/datum/controller/subsystem/lighting/SSlighting
O.needs_update = FALSE
processed_overlays++
if (no_mc_tick)
CHECK_TICK
else if (MC_TICK_CHECK)
+4 -3
View File
@@ -234,8 +234,8 @@ if(Datum.isprocessing) {\
queue.Cut(i)
return
/datum/controller/subsystem/machinery/stat_entry()
..({"\n\
/datum/controller/subsystem/machinery/stat_entry(msg)
msg = {"\n\
Queues: \
Pipes [pipenets.len] \
Machines [processing.len] \
@@ -247,7 +247,8 @@ if(Datum.isprocessing) {\
Networks [round(cost_powernets, 1)] \
Objects [round(cost_power_objects, 1)]\n\
Overall [round(cost ? processing.len / cost : 0, 0.1)]
"})
"}
return ..()
/datum/controller/subsystem/machinery/ExplosionStart()
suspend()
+3 -2
View File
@@ -62,8 +62,9 @@
mtl_incorporeal = typecacheof(mtl_incorporeal)
/datum/controller/subsystem/mobs/stat_entry()
..("P:[mob_list.len]")
/datum/controller/subsystem/mobs/stat_entry(msg)
msg = "P:[mob_list.len]"
return ..()
/datum/controller/subsystem/mobs/fire(resumed = 0)
if (!resumed)
+3 -2
View File
@@ -13,8 +13,9 @@
/datum/controller/subsystem/mob_ai/New()
NEW_SS_GLOBAL(SSmob_ai)
/datum/controller/subsystem/mob_ai/stat_entry()
..("P:[processing.len]")
/datum/controller/subsystem/mob_ai/stat_entry(msg)
msg = "P:[processing.len]"
return ..()
/datum/controller/subsystem/mob_ai/fire(resumed = FALSE)
if (!resumed)
@@ -13,8 +13,9 @@ var/datum/controller/subsystem/nightlight/SSnightlight
/datum/controller/subsystem/nightlight/New()
NEW_SS_GLOBAL(SSnightlight)
/datum/controller/subsystem/nightlight/stat_entry()
..("A:[isactive] T:[worldtime2hours()] D:[disable_type]")
/datum/controller/subsystem/nightlight/stat_entry(msg)
msg = "A:[isactive] T:[worldtime2hours()] D:[disable_type]"
return ..()
/datum/controller/subsystem/nightlight/Recover()
src.isactive = SSnightlight.isactive
+3 -3
View File
@@ -16,9 +16,9 @@ var/datum/controller/subsystem/orbit/SSorbit
/datum/controller/subsystem/orbit/Recover()
src.processing = SSorbit.processing
/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)
if (!resumed)
+5 -4
View File
@@ -15,8 +15,9 @@ var/datum/controller/subsystem/overlays/SSoverlays
var/list/overlay_icon_cache = list()
var/initialized = FALSE
/datum/controller/subsystem/overlays/stat_entry()
..("Ov:[processing.len - (idex - 1)]")
/datum/controller/subsystem/overlays/stat_entry(msg)
msg = "Ov:[processing.len - (idex - 1)]"
return ..()
/datum/controller/subsystem/overlays/New()
NEW_SS_GLOBAL(SSoverlays)
@@ -79,7 +80,7 @@ var/datum/controller/subsystem/overlays/SSoverlays
/proc/iconstate2appearance(icon, iconstate)
var/static/image/stringbro = new()
var/list/icon_states_cache = SSoverlays.overlay_icon_state_caches
var/list/icon_states_cache = SSoverlays.overlay_icon_state_caches
var/list/cached_icon = icon_states_cache[icon]
if (cached_icon)
var/cached_appearance = cached_icon["[iconstate]"]
@@ -136,7 +137,7 @@ var/datum/controller/subsystem/overlays/SSoverlays
/atom/proc/cut_overlays(priority = FALSE, force_compile = FALSE)
var/list/cached_overlays = our_overlays
var/list/cached_priority = priority_overlays
var/need_compile = FALSE
if(LAZYLEN(cached_overlays)) //don't queue empty lists, don't cut priority overlays
+17 -14
View File
@@ -1,33 +1,36 @@
/datum/controller/subsystem/ping
name = "Ping"
priority = SS_PRIORITY_PING
wait = 3 SECONDS
init_order = SS_INIT_MISC_FIRST
wait = 4 SECONDS
flags = SS_NO_INIT
runlevels = RUNLEVELS_DEFAULT | RUNLEVEL_LOBBY
runlevels = RUNLEVEL_LOBBY | RUNLEVEL_SETUP | RUNLEVEL_GAME | RUNLEVEL_POSTGAME
var/list/currentrun = list()
/datum/controller/subsystem/ping/stat_entry()
..("P:[clients.len]")
/datum/controller/subsystem/ping/stat_entry(msg)
msg = "P:[clients.len]"
return ..()
/datum/controller/subsystem/ping/fire(resumed = 0)
/datum/controller/subsystem/ping/fire(resumed = FALSE)
// Prepare the new batch of clients
if (!resumed)
src.currentrun = clients.Copy()
//cache for sanic speed (lists are references anyways)
// De-reference the list for sanic speeds
var/list/currentrun = src.currentrun
while (currentrun.len)
var/client/C = currentrun[currentrun.len]
var/client/client = currentrun[currentrun.len]
currentrun.len--
if (!C || !C.chatOutput || !C.chatOutput.loaded)
if (MC_TICK_CHECK)
return
continue
if (client?.tgui_panel?.is_ready())
// Send a soft ping
client.tgui_panel.window.send_message("ping/soft", list(
// Slightly less than the subsystem timer (somewhat arbitrary)
// to prevent incoming pings from resetting the afk state
"afk" = client.is_afk(3.5 SECONDS),
))
// softPang isn't handled anywhere but it'll always reset the opts.lastPang.
C.chatOutput.ehjax_send(data = C.is_afk(29) ? "softPang" : "pang")
if (MC_TICK_CHECK)
return
+3 -2
View File
@@ -24,8 +24,9 @@
/datum/controller/subsystem/plants/New()
NEW_SS_GLOBAL(SSplants)
/datum/controller/subsystem/plants/stat_entry()
..("P:[processing.len]")
/datum/controller/subsystem/plants/stat_entry(msg)
msg = "P:[processing.len]"
return ..()
/datum/controller/subsystem/plants/Initialize(timeofday)
// Build the icon lists.
@@ -0,0 +1,29 @@
var/datum/controller/subsystem/processing/obj_tab_items/SSobj_tab_items
/datum/controller/subsystem/processing/obj_tab_items
name = "Obj Tab Items"
flags = SS_NO_INIT
runlevels = RUNLEVEL_LOBBY | RUNLEVELS_DEFAULT
wait = 0.1 SECONDS
/datum/controller/subsystem/processing/obj_tab_items/New()
NEW_SS_GLOBAL(SSobj_tab_items)
// 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--
@@ -13,8 +13,9 @@ var/datum/controller/subsystem/processing/SSprocessing
/datum/controller/subsystem/processing/New()
NEW_SS_GLOBAL(SSprocessing)
/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)
@@ -121,7 +121,7 @@ var/datum/controller/subsystem/shuttle/SSshuttle
for(var/landmark_tag in given_sector.initial_generic_waypoints)
if(!try_add_landmark_tag(landmark_tag, given_sector))
landmarks_still_needed[landmark_tag] = given_sector
for(var/shuttle_name in given_sector.initial_restricted_waypoints)
for(var/landmark_tag in given_sector.initial_restricted_waypoints[shuttle_name])
if(!try_add_landmark_tag(landmark_tag, given_sector))
@@ -174,8 +174,9 @@ var/datum/controller/subsystem/shuttle/SSshuttle
var/obj/effect/overmap/visitable/ship/ship_effect = ship
overmap_halted ? ship_effect.halt() : ship_effect.unhalt()
/datum/controller/subsystem/shuttle/stat_entry()
..("Shuttles:[shuttles.len], Ships:[ships.len], L:[registered_shuttle_landmarks.len][overmap_halted ? ", HALT" : ""]")
/datum/controller/subsystem/shuttle/stat_entry(msg)
msg = "Shuttles:[shuttles.len], Ships:[ships.len], L:[registered_shuttle_landmarks.len][overmap_halted ? ", HALT" : ""]"
return ..()
/datum/controller/subsystem/shuttle/proc/ship_by_type(type)
for (var/obj/effect/overmap/visitable/ship/ship in ships)
+3 -2
View File
@@ -107,8 +107,9 @@ var/datum/controller/subsystem/radio/SSradio
/datum/controller/subsystem/radio/New()
NEW_SS_GLOBAL(SSradio)
/datum/controller/subsystem/radio/stat_entry()
..("F:[frequencies.len]")
/datum/controller/subsystem/radio/stat_entry(msg)
msg = "F:[frequencies.len]"
return ..()
/datum/controller/subsystem/radio/proc/add_object(obj/device, new_frequency, filter = null)
var/f_text = num2text(new_frequency)
+4 -4
View File
@@ -32,9 +32,9 @@
available_teams += ert
all_ert_teams += ert
/datum/controller/subsystem/distress/stat_entry()
var/out = "CC:[can_call_ert]"
..(out)
/datum/controller/subsystem/distress/stat_entry(msg)
msg = "CC:[can_call_ert]"
return ..()
/datum/controller/subsystem/distress/proc/pick_random_team()
var/list/datum/responseteam/possible_teams = list()
@@ -181,4 +181,4 @@
/datum/distress_beacon/Destroy()
caller = null
user = null
return ..()
return ..()
+3 -2
View File
@@ -288,5 +288,6 @@
return FALSE
S.increment_value(key)
/datum/controller/subsystem/statistics/stat_entry()
..("Kicked: [kicked_clients]")
/datum/controller/subsystem/statistics/stat_entry(msg)
msg = "Kicked: [kicked_clients]"
return ..()
+330
View File
@@ -0,0 +1,330 @@
var/datum/controller/subsystem/statpanels/SSstatpanels
/datum/controller/subsystem/statpanels
name = "Stat Panels"
wait = 4
init_order = SS_INIT_MISC_FIRST
priority = SS_PRIORITY_STATPANELS
runlevels = RUNLEVELS_DEFAULT | RUNLEVEL_LOBBY
var/list/currentrun = list()
var/list/global_data
var/list/mc_data
///how many subsystem fires between most tab updates
var/default_wait = 10
///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/New()
NEW_SS_GLOBAL(SSstatpanels)
/datum/controller/subsystem/statpanels/fire(resumed = FALSE)
if (!resumed)
num_fires++
var/current_month = text2num(time2text(world.realtime, "MM"))
var/current_day = text2num(time2text(world.realtime, "DD"))
var/eta_status = "No ETA"
if(evacuation_controller)
eta_status = evacuation_controller.get_status_panel_eta()
global_data = list(
"Map: [current_map.name]",
"Round ID: [game_id ? game_id : "NULL"]",
"Server Time: [time2text(world.timeofday, "YYYY-MM-DD hh:mm:ss")]",
"Current Date: [game_year]-[current_month]-[current_day]",
"Round Time: [get_round_duration_formatted()]",
"Ship Time: [worldtime2text()]",
"Current Space Sector: [SSatlas.current_sector.name]",
"Last Transfer Vote: [SSvote.last_transfer_vote ? time2text(SSvote.last_transfer_vote, "hh:mm") : "Never"]"
)
if(eta_status)
global_data += eta_status
src.currentrun = 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())
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
/// This should be implemented eventually, but for now we don't need it - Aurora admins are used to suffering.
target.stat_panel.send_message("update_split_admin_tabs", FALSE)
if(!("MC" in target.panel_tabs))
target.stat_panel.send_message("add_admin_tabs")
if(target.stat_tab == "MC" && ((num_fires % mc_wait == 0)))
set_MC_tab(target)
if(target.mob)
var/mob/target_mob = target.mob
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 something fitting.
if(!length(target.spell_tabs) && locate(/obj/item/rig) in target_mob.contents)
update_actions = TRUE
if(update_actions && num_fires % default_wait == 0)
set_action_tabs(target, target_mob)
// Handle the examined turf of the stat panel, if it's been long enough, or if we've generated new images for it
var/turf/listed_turf = target_mob?.listed_turf
if(listed_turf && num_fires % default_wait == 0)
if(target.stat_tab == listed_turf.name || !(listed_turf.name in target.panel_tabs))
set_turf_examine_tab(target, target_mob)
if(MC_TICK_CHECK)
return
/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,
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))
/// Set up the various action tabs.
/datum/controller/subsystem/statpanels/proc/set_action_tabs (client/target, mob/target_mob)
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)
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 == 0)
continue
if(turf_content.invisibility > target_mob.see_invisible)
continue
if(turf_content in overrides)
continue
atoms_to_display += turf_content
/// Set the atoms we're meant to display
var/datum/object_window_info/obj_window = target.obj_window
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)
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("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_TICK_USAGE,0.1)]%)"),
list("Master Controller:", Master.stat_entry(), text_ref(Master)),
list("Failsafe Controller:", Failsafe.stat_entry(), text_ref(Failsafe)),
list("","")
)
for(var/datum/controller/subsystem/sub_system in Master.subsystems)
mc_data[++mc_data.len] = list("\[[sub_system.state_letter()]][sub_system.name]", sub_system.stat_entry(), text_ref(sub_system))
mc_data[++mc_data.len] = list("Camera Net", "Cameras: [cameranet.cameras.len] | Chunks: [cameranet.chunks.len]", text_ref(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 == "Status")
set_status_tab(target)
return TRUE
var/mob/target_mob = target.mob
// Handle turfs
if(target_mob?.listed_turf)
if(!target_mob.TurfAdjacent(target_mob.listed_turf))
target_mob.set_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
/// 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
/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(delta_time)
// 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]
var/generated_string
if(ismob(thing) || length(thing.overlays) > 2)
generated_string = costly_icon2html(thing, parent, sourceonly=TRUE)
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)
actively_tracking = TRUE
/datum/object_window_info/proc/stop_turf_tracking()
qdel(GetComponent(/datum/component/connect_mob_behalf))
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)
/// 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)
listed_turf = new_turf
if(!client)
return
if(!client.obj_window)
client.obj_window = new(client)
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")
client.obj_window.stop_turf_tracking()
+3 -2
View File
@@ -25,8 +25,9 @@ var/datum/controller/subsystem/sun/sun
solar_next_update = world.time // init the timer
angle = rand (0,360)
/datum/controller/subsystem/sun/stat_entry()
..("A:[angle] R:[rate] S:[LAZYLEN(solars)]")
/datum/controller/subsystem/sun/stat_entry(msg)
msg = "A:[angle] R:[rate] S:[LAZYLEN(solars)]"
return ..()
/datum/controller/subsystem/sun/fire(resumed = 0)
if (!resumed)
+3 -2
View File
@@ -15,8 +15,9 @@
/datum/controller/subsystem/sunlight/New()
NEW_SS_GLOBAL(SSsunlight)
/datum/controller/subsystem/sunlight/stat_entry()
..("A:[config.sun_accuracy] LP:[light_points.len] Z:[config.sun_target_z]")
/datum/controller/subsystem/sunlight/stat_entry(msg)
msg = "A:[config.sun_accuracy] LP:[light_points.len] Z:[config.sun_target_z]"
return ..()
/datum/controller/subsystem/sunlight/Initialize()
+4 -3
View File
@@ -74,7 +74,7 @@ var/datum/controller/subsystem/ticker/SSticker
pregame()
restart_timeout = config.restart_timeout
/datum/controller/subsystem/ticker/stat_entry()
/datum/controller/subsystem/ticker/stat_entry(msg)
var/state = ""
switch (current_state)
if (GAME_STATE_PREGAME)
@@ -87,7 +87,8 @@ var/datum/controller/subsystem/ticker/SSticker
state = "FIN"
else
state = "UNK"
..("State: [state]")
msg = "State: [state]"
return ..()
/datum/controller/subsystem/ticker/Recover()
// Copy stuff over so we don't lose any state.
@@ -618,7 +619,7 @@ var/datum/controller/subsystem/ticker/SSticker
icon = 'icons/effects/station_explosion.dmi';
icon_state = "station_intact";
layer = CINEMA_LAYER;
mouse_opacity = 0;
mouse_opacity = MOUSE_OPACITY_TRANSPARENT;
screen_loc = "1,0"
}
+2 -1
View File
@@ -62,7 +62,8 @@ var/datum/controller/subsystem/timer/SStimer
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)] RST:[bucket_reset_count]")
msg = "B:[bucket_count] P:[length(second_queue)] H:[length(hashes)] C:[length(clienttime_timers)] S:[length(timer_id_dict)] RST:[bucket_reset_count]"
return ..()
/datum/controller/subsystem/timer/proc/dump_timer_buckets(full = TRUE)
var/list/to_log = list("Timer bucket reset. world.time: [world.time], head_offset: [head_offset], practical_offset: [practical_offset]")
+1 -1
View File
@@ -146,7 +146,7 @@ Updated 09/10/2022 to include chatbar using Spookerton's SStyping system from Po
/atom/movable/typing_indicator
icon = 'icons/mob/talk.dmi'
icon_state = "typing"
mouse_opacity = 0
mouse_opacity = MOUSE_OPACITY_TRANSPARENT
vis_flags = VIS_INHERIT_ID
var/atom/movable/master
@@ -131,7 +131,7 @@
M.vr_mob = target
target.ckey = new_ckey
M.ckey = "@[new_ckey]"
target.verbs += /mob/proc/body_return
add_verb(target, /mob/proc/body_return)
target.get_vr_name(M)
M.swap_languages(target)
@@ -145,6 +145,7 @@
var/mob/living/simple_animal/spiderbot/SB = target
SB.internal_id.access = original_id.access
target.client.init_verbs()
to_chat(target, SPAN_NOTICE("Connection established, system suite active and calibrated."))
to_chat(target, SPAN_WARNING("To exit this mode, use the \"Return to Body\" verb in the IC tab."))
+1 -1
View File
@@ -297,9 +297,9 @@ var/datum/controller/subsystem/vote/SSvote
text += "\n[sanitizeSafe(question)]"
log_vote(text)
to_world("<span class='vote'><b>[text]</b>\nType <b>vote</b> or click <a href='?src=\ref[src];open=1'>here</a> to place your votes.\nYou have [config.vote_period/10] seconds to vote.</span>")
for(var/cc in clients)
var/client/C = cc
to_chat(C, "<span class='vote'><b>[text]</b>\nType <b>vote</b> or click <a href='?src=\ref[src];open=1'>here</a> to place your votes.\nYou have [config.vote_period/10] seconds to vote.</span>")
if(C.prefs.sfx_toggles & ASFX_VOTE) //Personal mute
switch(vote_type)
if("crew_transfer")
+6 -7
View File
@@ -87,20 +87,19 @@
enable()
/datum/controller/subsystem/zcopy/stat_entry(text, force)
..("\
[text]\n\
Mx: [json_encode(zlev_maximums)]\n\
/datum/controller/subsystem/zcopy/stat_entry(msg)
msg = "Mx: [json_encode(zlev_maximums)] | \
Queues: \
Turfs [queued_turfs.len - (qt_idex - 1)] \
Overlays [queued_overlays.len - (qo_idex - 1)]\n\
Overlays [queued_overlays.len - (qo_idex - 1)] | \
Open Turfs: \
Turfs [openspace_turfs] \
Overlays [openspace_overlays]\n\
Overlays [openspace_overlays] | \
Skips: \
Turfs [multiqueue_skips_turf] \
Objects [multiqueue_skips_object]\
")
"
return ..()
/datum/controller/subsystem/zcopy/Initialize(timeofday)
calculate_zstack_limits()