TGUI updates + statpanel

This commit is contained in:
Artur
2020-09-02 17:52:47 +03:00
parent d97d9f564b
commit 3bef4ba35e
175 changed files with 12354 additions and 7980 deletions
+2
View File
@@ -22,3 +22,5 @@
var/category as text
/// Only clients/mobs with `see_invisibility` higher can use the verb.
var/invisibility as num
/// Whether or not the verb appears in statpanel and commandbar when you press space
var/hidden as num
+2
View File
@@ -86,6 +86,8 @@
#define INIT_ORDER_MINOR_MAPPING -40
#define INIT_ORDER_PATH -50
#define INIT_ORDER_PERSISTENCE -95
#define INIT_ORDER_STATPANELS -98
#define INIT_ORDER_DEMO -99 // o avoid a bunch of changes related to initialization being written, do this last
#define INIT_ORDER_CHAT -100 //Should be last to ensure chat remains smooth during init.
+28 -10
View File
@@ -200,18 +200,36 @@
/proc/start_log(log)
WRITE_LOG(log, "Starting up round ID [GLOB.round_id].\n-------------------------")
/* ui logging */
/proc/log_tgui(user_or_client, text)
/**
* Appends a tgui-related log entry. All arguments are optional.
*/
/proc/log_tgui(user, message, context,
datum/tgui_window/window,
datum/src_object)
var/entry = ""
if(!user_or_client)
entry += "no user"
else if(istype(user_or_client, /mob))
var/mob/user = user_or_client
entry += "[user.ckey] (as [user])"
else if(istype(user_or_client, /client))
var/client/client = user_or_client
// Insert user info
if(!user)
entry += "<nobody>"
else if(istype(user, /mob))
var/mob/mob = user
entry += "[mob.ckey] (as [mob] at [mob.x],[mob.y],[mob.z])"
else if(istype(user, /client))
var/client/client = user
entry += "[client.ckey]"
entry += ":\n[text]"
// Insert context
if(context)
entry += " in [context]"
else if(window)
entry += " in [window.id]"
// Resolve src_object
if(!src_object && window && window.locked_by)
src_object = window.locked_by.src_object
// Insert src_object info
if(src_object)
entry += "\nUsing: [src_object.type] [REF(src_object)]"
// Insert message
if(message)
entry += "\n[message]"
WRITE_LOG(GLOB.tgui_log, entry)
/* Close open log handles. This should be called as late as possible, and no logging should hapen after. */
+1 -1
View File
@@ -349,7 +349,7 @@
if(!previous)
var/list/report_parts = list(personal_report(C), GLOB.common_report)
content = report_parts.Join()
C.verbs -= /client/proc/show_previous_roundend_report
remove_verb(C, /client/proc/show_previous_roundend_report)
fdel(filename)
text2file(content, filename)
else
+96
View File
@@ -0,0 +1,96 @@
/**
* 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)
output_list = url_encode(json_encode(output_list))
target << output("[output_list];", "statbrowser:add_verb_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)
output_list = url_encode(json_encode(output_list))
target << output("[output_list];", "statbrowser:remove_verb_list")
+12 -1
View File
@@ -344,7 +344,18 @@
..()
/atom/proc/AltClick(mob/user)
. = SEND_SIGNAL(src, COMSIG_CLICK_ALT, user)
SEND_SIGNAL(src, COMSIG_CLICK_ALT, user)
var/turf/T = get_turf(src)
if(T && (isturf(loc) || isturf(src)) && user.TurfAdjacent(T))
user.listed_turf = T
user.client << output("[url_encode(json_encode(T.name))];", "statbrowser:create_listedturf")
/// Use this instead of [/mob/proc/AltClickOn] where you only want turf content listing without additional atom alt-click interaction
/atom/proc/AltClickNoInteract(mob/user, atom/A)
var/turf/T = get_turf(A)
if(T && user.TurfAdjacent(T))
user.listed_turf = T
user.client << output("[url_encode(json_encode(T.name))];", "statbrowser:create_listedturf")
/mob/proc/TurfAdjacent(turf/T)
return T.Adjacent(src)
+3 -3
View File
@@ -11,7 +11,7 @@
var/icon/credits_icon = new(CREDITS_PATH)
LAZYINITLIST(credits)
var/list/_credits = credits
verbs += /client/proc/ClearCredits
add_verb(src, /client/proc/ClearCredits)
var/static/list/credit_order_for_this_round
if(isnull(credit_order_for_this_round))
credit_order_for_this_round = list("Thanks for playing!") + (shuffle(icon_states(credits_icon)) - "Thanks for playing!")
@@ -21,13 +21,13 @@
_credits += new /obj/screen/credit(null, I, src, credits_icon)
sleep(CREDIT_SPAWN_SPEED)
sleep(CREDIT_ROLL_SPEED - CREDIT_SPAWN_SPEED)
verbs -= /client/proc/ClearCredits
remove_verb(src, /client/proc/ClearCredits)
qdel(credits_icon)
/client/proc/ClearCredits()
set name = "Hide Credits"
set category = "OOC"
verbs -= /client/proc/ClearCredits
remove_verb(src, /client/proc/ClearCredits)
QDEL_LIST(credits)
credits = null
+1 -12
View File
@@ -223,23 +223,12 @@
log_subsystem("INIT", msg)
return time
//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(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]"
else
msg = "OFFLINE\t[msg]"
var/title = name
if (can_fire)
title = "\[[state_letter()]][title]"
stat(title, statclick.update(msg))
return msg
/datum/controller/subsystem/proc/state_letter()
switch (state)
+3 -2
View File
@@ -7,8 +7,9 @@ SUBSYSTEM_DEF(acid)
var/list/currentrun = list()
var/list/processing = list()
/datum/controller/subsystem/acid/stat_entry()
..("P:[processing.len]")
/datum/controller/subsystem/acid/stat_entry(msg)
msg = "P:[length(processing)]"
return ..()
/datum/controller/subsystem/acid/fire(resumed = 0)
+4 -3
View File
@@ -6,12 +6,13 @@ SUBSYSTEM_DEF(adjacent_air)
priority = FIRE_PRIORITY_ATMOS_ADJACENCY
var/list/queue = list()
/datum/controller/subsystem/adjacent_air/stat_entry()
/datum/controller/subsystem/adjacent_air/stat_entry(msg)
#ifdef TESTING
..("P:[length(queue)], S:[GLOB.atmos_adjacent_savings[1]], T:[GLOB.atmos_adjacent_savings[2]]")
msg = "P:[length(queue)], S:[GLOB.atmos_adjacent_savings[1]], T:[GLOB.atmos_adjacent_savings[2]]"
#else
..("P:[length(queue)]")
msg = "P:[length(queue)]"
#endif
return ..()
/datum/controller/subsystem/adjacent_air/Initialize()
while(length(queue))
+1 -1
View File
@@ -61,7 +61,7 @@ SUBSYSTEM_DEF(air)
msg += "HP:[high_pressure_delta.len]|"
msg += "AS:[active_super_conductivity.len]|"
msg += "AT/MS:[round((cost ? active_turfs.len/cost : 0),0.1)]"
..(msg)
return ..()
/datum/controller/subsystem/air/Initialize(timeofday)
extools_update_ssair()
+2 -1
View File
@@ -9,7 +9,8 @@ SUBSYSTEM_DEF(augury)
var/list/observers_given_action = list()
/datum/controller/subsystem/augury/stat_entry(msg)
..("W:[watchers.len]|D:[doombringers.len]")
msg = "W:[watchers.len]|D:[length(doombringers)]"
return ..()
/datum/controller/subsystem/augury/proc/register_doom(atom/A, severity)
doombringers[A] = severity
+2 -1
View File
@@ -20,7 +20,8 @@ SUBSYSTEM_DEF(disease)
return ..()
/datum/controller/subsystem/disease/stat_entry(msg)
..("P:[active_diseases.len]")
msg = "P:[length(active_diseases)]"
return ..()
/datum/controller/subsystem/disease/proc/get_disease_name(id)
var/datum/disease/advance/A = archive_diseases[id]
+3 -3
View File
@@ -7,8 +7,9 @@ SUBSYSTEM_DEF(fire_burning)
var/list/currentrun = list()
var/list/processing = list()
/datum/controller/subsystem/fire_burning/stat_entry()
..("P:[processing.len]")
/datum/controller/subsystem/fire_burning/stat_entry(msg)
msg = "P:[length(processing)]"
return ..()
/datum/controller/subsystem/fire_burning/fire(resumed = 0)
@@ -34,4 +35,3 @@ SUBSYSTEM_DEF(fire_burning)
if (MC_TICK_CHECK)
return
+1 -1
View File
@@ -58,7 +58,7 @@ SUBSYSTEM_DEF(garbage)
msg += "TGR:[round((totalgcs/(totaldels+totalgcs))*100, 0.01)]%"
msg += " P:[pass_counts.Join(",")]"
msg += "|F:[fail_counts.Join(",")]"
..(msg)
return ..()
/datum/controller/subsystem/garbage/Shutdown()
//Adds the del() log to the qdel log file
+3 -2
View File
@@ -8,10 +8,11 @@ SUBSYSTEM_DEF(idlenpcpool)
var/list/currentrun = list()
var/static/list/idle_mobs_by_zlevel[][]
/datum/controller/subsystem/idlenpcpool/stat_entry()
/datum/controller/subsystem/idlenpcpool/stat_entry(msg)
var/list/idlelist = GLOB.simple_animals[AI_IDLE]
var/list/zlist = GLOB.simple_animals[AI_Z_OFF]
..("IdleNPCS:[idlelist.len]|Z:[zlist.len]")
msg = "IdleNPCS:[length(idlelist)]|Z:[length(zlist)]"
return ..()
/datum/controller/subsystem/idlenpcpool/proc/MaxZChanged()
if (!islist(idle_mobs_by_zlevel))
+3 -2
View File
@@ -7,8 +7,9 @@ SUBSYSTEM_DEF(lighting)
wait = 2
init_order = INIT_ORDER_LIGHTING
/datum/controller/subsystem/lighting/stat_entry()
..("L:[GLOB.lighting_update_lights.len]|C:[GLOB.lighting_update_corners.len]|O:[GLOB.lighting_update_objects.len]")
/datum/controller/subsystem/lighting/stat_entry(msg)
msg = "L:[length(GLOB.lighting_update_lights)]|C:[length(GLOB.lighting_update_corners)]|O:[length(GLOB.lighting_update_objects)]"
return ..()
/datum/controller/subsystem/lighting/Initialize(timeofday)
+3 -2
View File
@@ -22,8 +22,9 @@ SUBSYSTEM_DEF(machines)
NewPN.add_cable(PC)
propagate_network(PC,PC.powernet)
/datum/controller/subsystem/machines/stat_entry()
..("M:[processing.len]|PN:[powernets.len]")
/datum/controller/subsystem/machines/stat_entry(msg)
msg = "M:[length(processing)]|PN:[length(powernets)]"
return ..()
/datum/controller/subsystem/machines/fire(resumed = 0)
+3 -2
View File
@@ -10,8 +10,9 @@ SUBSYSTEM_DEF(mobs)
var/static/list/cubemonkeys = list()
var/static/list/cheeserats = list()
/datum/controller/subsystem/mobs/stat_entry()
..("P:[GLOB.mob_living_list.len]")
/datum/controller/subsystem/mobs/stat_entry(msg)
msg = "P:[length(GLOB.mob_living_list)]"
return ..()
/datum/controller/subsystem/mobs/proc/MaxZChanged()
if (!islist(clients_by_zlevel))
+3 -2
View File
@@ -6,9 +6,10 @@ SUBSYSTEM_DEF(npcpool)
var/list/currentrun = list()
/datum/controller/subsystem/npcpool/stat_entry()
/datum/controller/subsystem/npcpool/stat_entry(msg)
var/list/activelist = GLOB.simple_animals[AI_ON]
..("NPCS:[activelist.len]")
msg = "NPCS:[length(activelist)]"
return ..()
/datum/controller/subsystem/npcpool/fire(resumed = FALSE)
+3 -2
View File
@@ -22,8 +22,9 @@ SUBSYSTEM_DEF(overlays)
return ..()
/datum/controller/subsystem/overlays/stat_entry()
..("Ov:[length(queue)]")
/datum/controller/subsystem/overlays/stat_entry(msg)
msg = "Ov:[length(queue)]"
return ..()
/datum/controller/subsystem/overlays/Shutdown()
@@ -10,8 +10,9 @@ SUBSYSTEM_DEF(processing)
var/list/processing = list()
var/list/currentrun = list()
/datum/controller/subsystem/processing/stat_entry()
..("[stat_tag]:[processing.len]")
/datum/controller/subsystem/processing/stat_entry(msg)
msg = "[stat_tag]:[length(processing)]"
return ..()
/datum/controller/subsystem/processing/fire(resumed = 0)
if (!resumed)
+3 -3
View File
@@ -8,8 +8,9 @@ SUBSYSTEM_DEF(spacedrift)
var/list/currentrun = list()
var/list/processing = list()
/datum/controller/subsystem/spacedrift/stat_entry()
..("P:[processing.len]")
/datum/controller/subsystem/spacedrift/stat_entry(msg)
msg = "P:[length(processing)]"
return ..()
/datum/controller/subsystem/spacedrift/fire(resumed = 0)
@@ -56,4 +57,3 @@ SUBSYSTEM_DEF(spacedrift)
AM.inertia_last_loc = AM.loc
if (MC_TICK_CHECK)
return
+117
View File
@@ -0,0 +1,117 @@
SUBSYSTEM_DEF(statpanels)
name = "Stat Panels"
wait = 4
init_order = INIT_ORDER_STATPANELS
runlevels = RUNLEVELS_DEFAULT | RUNLEVEL_LOBBY
var/list/currentrun = list()
var/encoded_global_data
var/mc_data_encoded
var/list/cached_images = list()
/datum/controller/subsystem/statpanels/fire(resumed = FALSE)
if(!resumed)
var/datum/map_config/cached = SSmapping.next_map_config
var/round_time = world.time - SSticker.round_start_time
var/list/global_data = list(
"Map: [SSmapping.config?.map_name || "Loading..."]",
cached ? "Next Map: [cached.map_name]" : null,
"Round ID: [GLOB.round_id ? GLOB.round_id : "NULL"]",
"Server Time: [time2text(world.timeofday, "YYYY-MM-DD hh:mm:ss")]",
"Round Time: [round_time > MIDNIGHT_ROLLOVER ? "[round(round_time/MIDNIGHT_ROLLOVER)]:[worldtime2text()]" : worldtime2text()]",
"Station Time: [STATION_TIME_TIMESTAMP("hh:mm:ss", world.time)]",
"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(SSshuttle.emergency)
var/ETA = SSshuttle.emergency.getModeStr()
if(ETA)
global_data += "[ETA] [SSshuttle.emergency.getTimerStr()]"
encoded_global_data = url_encode(json_encode(global_data))
var/list/mc_data = list(
list("CPU:", world.cpu),
list("Instances:", "[num2text(world.contents.len, 10)]"),
list("World Time:", "[world.time]"),
list("Globals:", "Edit", "\ref[GLOB]"),
list("[config]:", "Edit", "\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)]%))"),
list("Master Controller:", Master ? "(TickRate:[Master.processing]) (Iteration:[Master.iteration])" : "ERROR", "\ref[Master]"),
list("Failsafe Controller:", Failsafe ? "Defcon: [Failsafe.defcon_pretty()] (Interval: [Failsafe.processing_interval] | Iteration: [Failsafe.master_iteration])" : "ERROR", "\ref[Failsafe]"),
list("","")
)
for(var/ss in Master.subsystems)
var/datum/controller/subsystem/sub_system = ss
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: [GLOB.cameranet.cameras.len] | Chunks: [GLOB.cameranet.chunks.len]", "\ref[GLOB.cameranet]")
mc_data_encoded = url_encode(json_encode(mc_data))
src.currentrun = GLOB.clients.Copy()
var/list/currentrun = src.currentrun
while(length(currentrun))
var/client/target = currentrun[length(currentrun)]
currentrun.len--
var/ping_str = url_encode("Ping: [round(target.lastping, 1)]ms (Average: [round(target.avgping, 1)]ms)")
var/other_str = url_encode(json_encode(target.mob.get_status_tab_items()))
target << output("[encoded_global_data];[ping_str];[other_str]", "statbrowser:update")
if(!target.holder)
target << output("", "statbrowser:remove_admin_tabs")
else
var/turf/eye_turf = get_turf(target.eye)
var/coord_entry = url_encode(COORD(eye_turf))
target << output("[mc_data_encoded];[coord_entry];[url_encode(target.holder.href_token)]", "statbrowser:update_mc")
var/list/ahelp_tickets = GLOB.ahelp_tickets.stat_entry()
target << output("[url_encode(json_encode(ahelp_tickets))];", "statbrowser:update_tickets")
if(!length(GLOB.sdql2_queries))
target << output("", "statbrowser:remove_sqdl2")
else
var/list/sqdl2A = list()
sqdl2A[++sqdl2A.len] = list("", "Access Global SDQL2 List", REF(GLOB.sdql2_vv_statobj))
var/list/sqdl2B = list()
for(var/i in GLOB.sdql2_queries)
var/datum/SDQL2_query/Q = i
sqdl2B = Q.generate_stat()
sqdl2A += sqdl2B
target << output(url_encode(json_encode(sqdl2A)), "statbrowser:update_sqdl2")
var/list/proc_holders = target.mob.get_proc_holders()
target.spell_tabs.Cut()
for(var/phl in proc_holders)
var/list/proc_holder_list = phl
target.spell_tabs |= proc_holder_list[1]
var/proc_holders_encoded = ""
if(length(proc_holders))
proc_holders_encoded = url_encode(json_encode(proc_holders))
target << output("[url_encode(json_encode(target.spell_tabs))];[proc_holders_encoded]", "statbrowser:update_spells")
if(target.mob?.listed_turf)
var/mob/target_mob = target.mob
if(!target_mob.TurfAdjacent(target_mob.listed_turf))
target << output("", "statbrowser:remove_listedturf")
target_mob.listed_turf = null
else
var/list/overrides = list()
var/list/turfitems = list()
for(var/img in target.images)
var/image/target_image = img
if(!target_image.loc || target_image.loc.loc != target_mob.listed_turf || !target_image.override)
continue
overrides += target_image.loc
for(var/tc in target_mob.listed_turf)
var/atom/movable/turf_content = tc
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
if(length(turfitems) < 30) // only create images for the first 30 items on the turf, for performance reasons
if(!(REF(turf_content) in cached_images))
target << browse_rsc(getFlatIcon(turf_content, no_anim = TRUE), "[REF(turf_content)].png")
cached_images += REF(turf_content)
turfitems[++turfitems.len] = list("[turf_content.name]", REF(turf_content), "[REF(turf_content)].png")
else
turfitems[++turfitems.len] = list("[turf_content.name]", REF(turf_content))
turfitems = url_encode(json_encode(turfitems))
target << output("[turfitems];", "statbrowser:update_listedturf")
if(MC_TICK_CHECK)
return
+9 -7
View File
@@ -24,15 +24,16 @@ SUBSYSTEM_DEF(tgui)
var/basehtml
/datum/controller/subsystem/tgui/PreInit()
basehtml = file2text('tgui/packages/tgui/public/tgui.html')
basehtml = file2text('tgui/public/tgui.html')
/datum/controller/subsystem/tgui/Shutdown()
close_all_uis()
/datum/controller/subsystem/tgui/stat_entry()
..("P:[open_uis.len]")
/datum/controller/subsystem/tgui/stat_entry(msg)
msg = "P:[length(open_uis)]"
return ..()
/datum/controller/subsystem/tgui/fire(resumed = 0)
/datum/controller/subsystem/tgui/fire(resumed = FALSE)
if(!resumed)
src.current_run = open_uis.Copy()
// Cache for sanic speed (lists are references anyways)
@@ -81,7 +82,8 @@ SUBSYSTEM_DEF(tgui)
window_found = TRUE
break
if(!window_found)
log_tgui(user, "Error: Pool exhausted")
log_tgui(user, "Error: Pool exhausted",
context = "SStgui/request_pooled_window")
return null
return window
@@ -93,7 +95,7 @@ SUBSYSTEM_DEF(tgui)
* required user mob
*/
/datum/controller/subsystem/tgui/proc/force_close_all_windows(mob/user)
log_tgui(user, "force_close_all_windows")
log_tgui(user, context = "SStgui/force_close_all_windows")
if(user.client)
user.client.tgui_windows = list()
for(var/i in 1 to TGUI_WINDOW_HARD_LIMIT)
@@ -109,7 +111,7 @@ SUBSYSTEM_DEF(tgui)
* required window_id string
*/
/datum/controller/subsystem/tgui/proc/force_close_window(mob/user, window_id)
log_tgui(user, "force_close_window")
log_tgui(user, context = "SStgui/force_close_window")
// Close all tgui datums based on window_id.
for(var/datum/tgui/ui in user.tgui_open_uis)
if(ui.window && ui.window.id == window_id)
+3 -2
View File
@@ -11,8 +11,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:[length(processing)]"
return ..()
/datum/controller/subsystem/throwing/fire(resumed = 0)
+1
View File
@@ -416,6 +416,7 @@ SUBSYSTEM_DEF(ticker)
living.client.prefs.chat_toggles ^= CHAT_OOC
var/obj/screen/splash/S = new(living.client, TRUE)
S.Fade(TRUE)
living.client.init_verbs()
livings += living
if(livings.len)
addtimer(CALLBACK(src, .proc/release_characters, livings), 30, TIMER_CLIENT_TIME)
+2 -1
View File
@@ -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
+1 -1
View File
@@ -51,7 +51,7 @@ GLOBAL_LIST_EMPTY(mobs_with_editable_flavor_text) //et tu, hacky code
LAZYREMOVE(GLOB.mobs_with_editable_flavor_text[M], src)
if(!GLOB.mobs_with_editable_flavor_text[M])
GLOB.mobs_with_editable_flavor_text -= M
M.verbs -= /mob/proc/manage_flavor_tests
remove_verb(M, /mob/proc/manage_flavor_tests)
/datum/element/flavor_text/proc/show_flavor(atom/target, mob/user, list/examine_list)
if(!always_show && isliving(target))
+2 -2
View File
@@ -64,7 +64,7 @@
else if(make_temporary)
base = H.mind.default_martial_art
if(help_verb)
H.verbs += help_verb
add_verb(H, help_verb)
H.mind.martial_art = src
if(pugilist)
ADD_TRAIT(H, TRAIT_PUGILIST, MARTIAL_ARTIST_TRAIT)
@@ -90,7 +90,7 @@
/datum/martial_art/proc/on_remove(mob/living/carbon/human/H)
if(help_verb)
H.verbs -= help_verb
remove_verb(H, help_verb)
return
///Gets called when a projectile hits the owner. Returning anything other than BULLET_ACT_HIT will stop the projectile from hitting the mob.
+2
View File
@@ -129,6 +129,7 @@
new_character.key = key //now transfer the key to link the client to our new body
if(new_character.client)
LAZYCLEARLIST(new_character.client.recent_examines)
new_character.client.init_verbs() // re-initialize character specific verbs
current.update_atom_languages()
//CIT CHANGE - makes arousal update when transfering bodies
@@ -688,6 +689,7 @@
if(istype(S, spell))
spell_list -= S
qdel(S)
current?.client << output(null, "statbrowser:check_spells")
/datum/mind/proc/RemoveAllSpells()
for(var/obj/effect/proc_holder/S in spell_list)
+18
View File
@@ -1127,3 +1127,21 @@
*/
/atom/proc/rust_heretic_act()
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_shiftclick"])
paramslist["shift"] = "1"
if(href_list["statpanel_item_ctrlclick"])
paramslist["ctrl"] = "1"
if(href_list["statpanel_item_altclick"])
paramslist["alt"] = "1"
if(href_list["statpanel_item_click"])
// first of all make sure we valid
var/mouseparams = list2params(paramslist)
usr_client.Click(src, loc, null, mouseparams)
+2 -1
View File
@@ -8,7 +8,8 @@ GLOBAL_VAR_INIT(hsboxspawn, TRUE)
sandbox.owner = src.ckey
if(src.client.holder)
sandbox.admin = 1
verbs += new/mob/proc/sandbox_panel
add_verb(src, /mob/proc/sandbox_panel)
/mob/proc/sandbox_panel()
set name = "Sandbox Panel"
if(sandbox)
+27 -20
View File
@@ -11,7 +11,8 @@ GLOBAL_PROTECT(admin_verbs_default)
/client/proc/investigate_show, /*various admintools for investigation. Such as a singulo grief-log*/
/client/proc/debug_variables, /*allows us to -see- the variables of any instance in the game. +VAREDIT needed to modify*/
/client/proc/toggleprayers,
/client/proc/toggleadminhelpsound
/client/proc/toggleadminhelpsound,
/client/proc/debugstatpanel,
)
GLOBAL_LIST_INIT(admin_verbs_admin, world.AVerbsAdmin())
GLOBAL_PROTECT(admin_verbs_admin)
@@ -260,36 +261,36 @@ GLOBAL_PROTECT(admin_verbs_hideable)
control_freak = CONTROL_FREAK_SKIN | CONTROL_FREAK_MACROS
var/rights = holder.rank.rights
verbs += GLOB.admin_verbs_default
add_verb(src, GLOB.admin_verbs_default)
if(rights & R_BUILDMODE)
verbs += /client/proc/togglebuildmodeself
add_verb(src, /client/proc/togglebuildmodeself)
if(rights & R_ADMIN)
verbs += GLOB.admin_verbs_admin
add_verb(src, GLOB.admin_verbs_admin)
if(rights & R_BAN)
verbs += GLOB.admin_verbs_ban
add_verb(src, GLOB.admin_verbs_ban)
if(rights & R_FUN)
verbs += GLOB.admin_verbs_fun
add_verb(src, GLOB.admin_verbs_fun)
if(rights & R_SERVER)
verbs += GLOB.admin_verbs_server
add_verb(src, GLOB.admin_verbs_server)
if(rights & R_DEBUG)
verbs += GLOB.admin_verbs_debug
add_verb(src, GLOB.admin_verbs_debug)
if(rights & R_POSSESS)
verbs += GLOB.admin_verbs_possess
add_verb(src, GLOB.admin_verbs_possess)
if(rights & R_PERMISSIONS)
verbs += GLOB.admin_verbs_permissions
add_verb(src, GLOB.admin_verbs_permissions)
if(rights & R_STEALTH)
verbs += /client/proc/stealth
add_verb(src, /client/proc/stealth)
if(rights & R_ADMIN)
verbs += GLOB.admin_verbs_poll
add_verb(src, GLOB.admin_verbs_poll)
if(rights & R_SOUNDS)
verbs += GLOB.admin_verbs_sounds
add_verb(src, GLOB.admin_verbs_sounds)
if(CONFIG_GET(string/invoke_youtubedl))
verbs += /client/proc/play_web_sound
add_verb(src, /client/proc/play_web_sound)
if(rights & R_SPAWN)
verbs += GLOB.admin_verbs_spawn
add_verb(src, GLOB.admin_verbs_spawn)
/client/proc/remove_admin_verbs()
verbs.Remove(
remove_verb(src, list(
GLOB.admin_verbs_default,
/client/proc/togglebuildmodeself,
GLOB.admin_verbs_admin,
@@ -308,14 +309,14 @@ GLOBAL_PROTECT(admin_verbs_hideable)
GLOB.admin_verbs_debug_mapping,
/client/proc/disable_debug_verbs,
/client/proc/readmin
)
))
/client/proc/hide_most_verbs()//Allows you to keep some functionality while hiding some verbs
set name = "Adminverbs - Hide Most"
set category = "Admin"
verbs.Remove(/client/proc/hide_most_verbs, GLOB.admin_verbs_hideable)
verbs += /client/proc/show_verbs
add_verb(src, /client/proc/show_verbs)
to_chat(src, "<span class='interface'>Most of your adminverbs have been hidden.</span>")
SSblackbox.record_feedback("tally", "admin_verb", 1, "Hide Most Adminverbs") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
@@ -326,7 +327,7 @@ GLOBAL_PROTECT(admin_verbs_hideable)
set category = "Admin"
remove_admin_verbs()
verbs += /client/proc/show_verbs
add_verb(src, /client/proc/show_verbs)
to_chat(src, "<span class='interface'>Almost all of your adminverbs have been hidden.</span>")
SSblackbox.record_feedback("tally", "admin_verb", 1, "Hide All Adminverbs") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
@@ -336,7 +337,7 @@ GLOBAL_PROTECT(admin_verbs_hideable)
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 class='interface'>All of your adminverbs are now visible.</span>")
@@ -724,3 +725,9 @@ GLOBAL_PROTECT(admin_verbs_hideable)
log_admin("[key_name(usr)] has [AI_Interact ? "activated" : "deactivated"] Admin AI Interact")
message_admins("[key_name_admin(usr)] has [AI_Interact ? "activated" : "deactivated"] their AI interaction")
/client/proc/debugstatpanel()
set name = "Debug Stat Panel"
set category = "Debug"
src << output("", "statbrowser:create_debug")
+4 -2
View File
@@ -91,7 +91,7 @@ GLOBAL_PROTECT(href_token)
var/client/C
if ((C = owner) || (C = GLOB.directory[target]))
disassociate()
C.verbs += /client/proc/readmin
add_verb(C, /client/proc/readmin)
/datum/admins/proc/associate(client/C)
if(IsAdminAdvancedProcCall())
@@ -111,7 +111,8 @@ GLOBAL_PROTECT(href_token)
owner = C
owner.holder = src
owner.add_admin_verbs() //TODO <--- todo what? the proc clearly exists and works since its the backbone to our entire admin system
owner.verbs -= /client/proc/readmin
remove_verb(owner, /client/proc/readmin)
owner.init_verbs() //re-initialize the verb list
GLOB.admins |= C
/datum/admins/proc/disassociate()
@@ -123,6 +124,7 @@ GLOBAL_PROTECT(href_token)
if(owner)
GLOB.admins -= owner
owner.remove_admin_verbs()
owner.init_verbs()
owner.holder = null
owner = null
+18 -4
View File
@@ -397,11 +397,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)
@@ -1189,15 +1191,27 @@ GLOBAL_DATUM_INIT(sdql2_vv_statobj, /obj/effect/statclick/SDQL2_VV_all, new(null
return query_list
/obj/effect/statclick/SDQL2_delete/Click()
if(!usr.client?.holder)
message_admins("[key_name_admin(usr)] non-holder clicked on a statclick! ([src])")
log_game("[key_name(usr)] non-holder clicked on a statclick! ([src])")
return
var/datum/SDQL2_query/Q = target
Q.delete_click()
/obj/effect/statclick/SDQL2_action/Click()
if(!usr.client?.holder)
message_admins("[key_name_admin(usr)] non-holder clicked on a statclick! ([src])")
log_game("[key_name(usr)] non-holder clicked on a statclick! ([src])")
return
var/datum/SDQL2_query/Q = target
Q.action_click()
/obj/effect/statclick/SDQL2_VV_all
name = "VIEW VARIABLES"
/obj/effect/statclick/SDQL2_VV_all/Click()
/obj/effect/statclick/sdql2_vv_all/Click()
if(!usr.client?.holder)
message_admins("[key_name_admin(usr)] non-holder clicked on a statclick! ([src])")
log_game("[key_name(usr)] non-holder clicked on a statclick! ([src])")
return
usr.client.debug_variables(GLOB.sdql2_queries)
+16 -7
View File
@@ -89,18 +89,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("Active Tickets:", astatclick.update("[active_tickets.len]"))
L[++L.len] = list("Active Tickets:", "[astatclick.update("[active_tickets.len]")]", null, REF(astatclick))
astatclick.update("[active_tickets.len]")
for(var/I in active_tickets)
var/datum/admin_help/AH = I
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)
@@ -137,6 +142,10 @@ 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
//
@@ -218,7 +227,7 @@ GLOBAL_DATUM_INIT(ahelp_tickets, /datum/admin_help_tickets, new)
//Removes the ahelp verb and returns it after 2 minutes
/datum/admin_help/proc/TimeoutVerb()
initiator.verbs -= /client/verb/adminhelp
remove_verb(initiator, /client/verb/adminhelp)
initiator.adminhelptimerid = addtimer(CALLBACK(initiator, /client/proc/giveadminhelpverb), 1200, TIMER_STOPPABLE) //2 minute cooldown of admin helps
//private
@@ -490,7 +499,7 @@ GLOBAL_DATUM_INIT(ahelp_tickets, /datum/admin_help_tickets, new)
//
/client/proc/giveadminhelpverb()
src.verbs |= /client/verb/adminhelp
add_verb(src, /client/verb/adminhelp)
deltimer(adminhelptimerid)
adminhelptimerid = 0
+4 -4
View File
@@ -205,15 +205,15 @@ GLOBAL_LIST_EMPTY(dirty_vars)
set name = "Debug verbs - Enable"
if(!check_rights(R_DEBUG))
return
verbs -= /client/proc/enable_debug_verbs
verbs.Add(/client/proc/disable_debug_verbs, GLOB.admin_verbs_debug_mapping)
remove_verb(src, /client/proc/enable_debug_verbs)
add_verb(src, list(/client/proc/disable_debug_verbs, GLOB.admin_verbs_debug_mapping))
SSblackbox.record_feedback("tally", "admin_verb", 1, "Enable Debug Verbs") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
/client/proc/disable_debug_verbs()
set category = "Debug"
set name = "Debug verbs - Disable"
verbs.Remove(/client/proc/disable_debug_verbs, GLOB.admin_verbs_debug_mapping)
verbs += /client/proc/enable_debug_verbs
remove_verb(src, list(/client/proc/disable_debug_verbs, GLOB.admin_verbs_debug_mapping))
add_verb(src, /client/proc/enable_debug_verbs)
SSblackbox.record_feedback("tally", "admin_verb", 1, "Disable Debug Verbs") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
/client/proc/count_objects_on_z_level()
+2 -2
View File
@@ -48,6 +48,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
add_verb(M, /proc/possess)
add_verb(M, /proc/release)
SSblackbox.record_feedback("tally", "admin_verb", 1, "Give Possessing Verbs") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
@@ -83,17 +83,16 @@ the new instance inside the host to be updated to the template's stats.
to_chat(src, "<span class='warning'>You have [DisplayTimeText(freemove_end - world.time)] to select your first host. Click on a human to select your host.</span>")
/mob/camera/disease/Stat()
/mob/camera/disease/get_status_tab_items()
..()
if(statpanel("Status"))
if(freemove)
stat("Host Selection Time: [round((freemove_end - world.time)/10)]s")
else
stat("Adaptation Points: [points]/[total_points]")
stat("Hosts: [disease_instances.len]")
var/adapt_ready = next_adaptation_time - world.time
if(adapt_ready > 0)
stat("Adaptation Ready: [round(adapt_ready/10, 0.1)]s")
if(freemove)
. += "Host Selection Time: [round((freemove_end - world.time)/10)]s"
else
. += "Adaptation Points: [points]/[total_points]"
. += "Hosts: [disease_instances.len]"
var/adapt_ready = next_adaptation_time - world.time
if(adapt_ready > 0)
. += "Adaptation Ready: [round(adapt_ready/10, 0.1)]s"
/mob/camera/disease/examine(mob/user)
@@ -130,12 +130,11 @@
update_spooky_icon()
update_health_hud()
/mob/living/simple_animal/revenant/Stat()
..()
if(statpanel("Status"))
stat(null, "Current essence: [essence]/[essence_regen_cap]E")
stat(null, "Stolen essence: [essence_accumulated]E")
stat(null, "Stolen perfect souls: [perfectsouls]")
/mob/living/simple_animal/revenant/get_status_tab_items()
. = ..()
. += "Current essence: [essence]/[essence_regen_cap]E"
. += "Stolen essence: [essence_accumulated]E"
. += "Stolen perfect souls: [perfectsouls]"
/mob/living/simple_animal/revenant/update_health_hud()
if(hud_used)
+1 -1
View File
@@ -109,7 +109,7 @@
/mob/living/simple_animal/hostile/swarmer/Initialize()
. = ..()
verbs -= /mob/living/verb/pulled
remove_verb(src, /mob/living/verb/pulled)
for(var/datum/atom_hud/data/diagnostic/diag_hud in GLOB.huds)
diag_hud.add_to_hud(src)
@@ -49,7 +49,7 @@
/datum/traitor_class/ai/on_removal(datum/antagonist/traitor/T)
var/mob/living/silicon/ai/A = T.owner.current
A.set_zeroth_law("")
A.verbs -= /mob/living/silicon/ai/proc/choose_modules
remove_verb(A, /mob/living/silicon/ai/proc/choose_modules)
A.malf_picker.remove_malf_verbs(A)
qdel(A.malf_picker)
+11 -11
View File
@@ -3,21 +3,21 @@
/datum/asset/simple/tgui_common
keep_local_name = TRUE
assets = list(
"tgui-common.chunk.js" = 'tgui/packages/tgui/public/tgui-common.chunk.js',
"tgui-common.chunk.js" = 'tgui/public/tgui-common.chunk.js',
)
/datum/asset/simple/tgui
keep_local_name = TRUE
assets = list(
"tgui.bundle.js" = 'tgui/packages/tgui/public/tgui.bundle.js',
"tgui.bundle.css" = 'tgui/packages/tgui/public/tgui.bundle.css',
"tgui.bundle.js" = 'tgui/public/tgui.bundle.js',
"tgui.bundle.css" = 'tgui/public/tgui.bundle.css',
)
/datum/asset/simple/tgui_panel
keep_local_name = TRUE
assets = list(
"tgui-panel.bundle.js" = 'tgui/packages/tgui/public/tgui-panel.bundle.js',
"tgui-panel.bundle.css" = 'tgui/packages/tgui/public/tgui-panel.bundle.css',
"tgui-panel.bundle.js" = 'tgui/public/tgui-panel.bundle.js',
"tgui-panel.bundle.css" = 'tgui/public/tgui-panel.bundle.css',
)
/datum/asset/simple/headers
@@ -113,15 +113,15 @@
)
/datum/asset/simple/IRV
/datum/asset/simple/irv
assets = list(
"jquery-ui.custom-core-widgit-mouse-sortable-min.js" = 'html/IRV/jquery-ui.custom-core-widgit-mouse-sortable-min.js',
)
/datum/asset/group/IRV
/datum/asset/group/irv
children = list(
/datum/asset/simple/jquery,
/datum/asset/simple/IRV
/datum/asset/simple/irv
)
/datum/asset/simple/namespaced/changelog
@@ -247,6 +247,7 @@
"clownthanks" = 'icons/UI_Icons/Achievements/Misc/clownthanks.png',
"rule8" = 'icons/UI_Icons/Achievements/Misc/rule8.png',
"snail" = 'icons/UI_Icons/Achievements/Misc/snail.png',
"ascension" = 'icons/UI_Icons/Achievements/Misc/ascension.png',
"mining" = 'icons/UI_Icons/Achievements/Skills/mining.png',
"assistant" = 'icons/UI_Icons/Achievements/Mafia/assistant.png',
"changeling" = 'icons/UI_Icons/Achievements/Mafia/changeling.png',
@@ -263,7 +264,8 @@
"psychologist" = 'icons/UI_Icons/Achievements/Mafia/psychologist.png',
"thoughtfeeder" = 'icons/UI_Icons/Achievements/Mafia/thoughtfeeder.png',
"traitor" = 'icons/UI_Icons/Achievements/Mafia/traitor.png',
"basemafia" ='icons/UI_Icons/Achievements/basemafia.png'
"basemafia" ='icons/UI_Icons/Achievements/basemafia.png',
"frenching" = 'icons/UI_Icons/Achievements/Misc/frenchingthebubble.png'
)
*/
@@ -447,11 +449,9 @@
Insert("polycrystal", 'icons/obj/telescience.dmi', "polycrystal")
..()
/datum/asset/spritesheet/mafia
name = "mafia"
/datum/asset/spritesheet/mafia/register()
InsertAll("", 'icons/obj/mafia.dmi')
..()
@@ -43,10 +43,10 @@
return "[url][get_asset_suffex(asset_cache_item)]"
/datum/asset_transport/webroot/proc/get_asset_suffex(datum/asset_cache_item/asset_cache_item)
var/base = ""
var/base = "[copytext(asset_cache_item.hash, 1, 3)]/"
var/filename = "asset.[asset_cache_item.hash][asset_cache_item.ext]"
if (length(asset_cache_item.namespace))
base = "namespaces/[asset_cache_item.namespace]/"
base = "namespaces/[copytext(asset_cache_item.namespace, 1, 3)]/[asset_cache_item.namespace]/"
if (!asset_cache_item.namespace_parent)
filename = "[asset_cache_item.name]"
return base + filename
@@ -105,7 +105,7 @@
if("Immortality")
to_chat(user, "<B>Your wish is granted, but at a terrible cost...</B>")
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.set_species(/datum/species/shadow)
if("To Kill")
to_chat(user, "<B>Your wish is granted, but at a terrible cost...</B>")
+12
View File
@@ -7,6 +7,9 @@
////////////////
//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/click_intercept = null // Needs to implement InterceptClickOn(user,params,atom) proc
var/AI_Interact = 0
@@ -123,6 +126,14 @@
/// Messages currently seen by this client
var/list/seen_messages
/// datum wrapper for client view
var/datum/view_data/view_size
/// list of tabs containing spells and abilities
var/list/spell_tabs = list()
/// list of tabs containing verbs
var/list/verb_tabs = list()
///A lazy list of atoms we've examined in the last EXAMINE_MORE_TIME (default 1.5) seconds, so that we will call [atom/proc/examine_more()] instead of [atom/proc/examine()] on them when examining
var/list/recent_examines
///When was the last time we warned them about not cryoing without an ahelp, set to -5 minutes so that rounstart cryo still warns
@@ -152,3 +163,4 @@
//world.time of when the crew manifest can be accessed
var/crew_manifest_delay
+24 -4
View File
@@ -237,7 +237,7 @@ GLOBAL_LIST_INIT(blacklisted_builds, list(
debug_tools_allowed = TRUE
//END CITADEL EDIT
else if(GLOB.deadmins[ckey])
verbs += /client/proc/readmin
add_verb(src, /client/proc/readmin)
connecting_admin = TRUE
if(CONFIG_GET(flag/autoadmin))
if(!GLOB.admin_datums[ckey])
@@ -275,7 +275,7 @@ GLOBAL_LIST_INIT(blacklisted_builds, list(
fps = prefs.clientfps //(prefs.clientfps < 0) ? RECOMMENDED_FPS : prefs.clientfps
if(fexists(roundend_report_file()))
verbs += /client/proc/show_previous_roundend_report
add_verb(src, /client/proc/show_previous_roundend_report)
var/full_version = "[byond_version].[byond_build ? byond_build : "xxx"]"
log_access("Login: [key_name(src)] from [address ? address : "localhost"]-[computer_id] || BYOND v[full_version]")
@@ -342,6 +342,8 @@ GLOBAL_LIST_INIT(blacklisted_builds, list(
// Initialize tgui panel
tgui_panel.initialize()
src << browse(file('html/statbrowser.html'), "window=statbrowser")
if(alert_mob_dupe_login)
spawn()
@@ -857,9 +859,9 @@ GLOBAL_LIST_INIT(blacklisted_builds, list(
/client/proc/add_verbs_from_config()
if(CONFIG_GET(flag/see_own_notes))
verbs += /client/proc/self_notes
add_verb(src, /client/proc/self_notes)
if(CONFIG_GET(flag/use_exp_tracking))
verbs += /client/proc/self_playtime
add_verb(src, /client/proc/self_playtime)
#undef UPLOAD_LIMIT
@@ -1001,3 +1003,21 @@ GLOBAL_LIST_INIT(blacklisted_builds, list(
/client/proc/can_have_part(part_name)
return prefs.pref_species.mutant_bodyparts[part_name] || (part_name in GLOB.unlocked_mutant_parts)
/// compiles a full list of verbs and sends it to the browser
/client/proc/init_verbs()
if(IsAdminAdvancedProcCall())
return
var/list/verblist = list()
verb_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
verb_tabs |= verb_to_init.category
verblist[++verblist.len] = list(verb_to_init.category, verb_to_init.name)
src << output("[url_encode(json_encode(verb_tabs))];[url_encode(json_encode(verblist))]", "statbrowser:init_verbs")
+6
View File
@@ -280,3 +280,9 @@ GLOBAL_VAR_INIT(normal_ooc_colour, "#002eb8")
pct += delta
winset(src, "mainwindow.split", "splitter=[pct]")
/client/verb/fix_stat_panel()
set name = "Fix Stat Panel"
set hidden = TRUE
init_verbs()
+2 -2
View File
@@ -307,7 +307,7 @@
F = S
update_icon()
update_helmlight(user)
verbs += /obj/item/clothing/head/helmet/proc/toggle_helmlight
add_verb(user, /obj/item/clothing/head/helmet/proc/toggle_helmlight)
var/datum/action/A = new /datum/action/item_action/toggle_helmet_flashlight(src)
if(loc == user)
A.Grant(user)
@@ -323,7 +323,7 @@
S.update_brightness(user)
update_icon()
usr.update_inv_head()
verbs -= /obj/item/clothing/head/helmet/proc/toggle_helmlight
remove_verb(src, /obj/item/clothing/head/helmet/proc/toggle_helmlight)
for(var/datum/action/item_action/toggle_helmet_flashlight/THL in actions)
qdel(THL)
return
+2 -2
View File
@@ -21,6 +21,6 @@
/datum/round_event/wizard/possession/start()
for(var/mob/dead/observer/G in GLOB.player_list)
G.verbs += /mob/dead/observer/verb/boo
G.verbs += /mob/dead/observer/verb/possess
add_verb(G, /mob/dead/observer/verb/boo)
add_verb(G, /mob/dead/observer/verb/possess)
to_chat(G, "You suddenly feel a welling of new spooky powers...")
+11 -13
View File
@@ -17,7 +17,7 @@ INITIALIZE_IMMEDIATE(/mob/dead)
prepare_huds()
if(length(CONFIG_GET(keyed_list/cross_server)))
verbs += /mob/dead/proc/server_hop
add_verb(src, /mob/dead/proc/server_hop)
set_focus(src)
return INITIALIZE_HINT_NORMAL
@@ -42,27 +42,25 @@ INITIALIZE_IMMEDIATE(/mob/dead)
loc = destination
Moved(oldloc, NONE, TRUE)
/mob/dead/Stat()
..()
if(!statpanel("Status"))
return
//stat(null, "Game Mode: [SSticker.hide_mode ? "Secret" : "[GLOB.master_mode]"]")
/mob/dead/get_status_tab_items()
. = ..()
. += ""
. += "Game Mode: [SSticker.hide_mode ? "Secret" : "[GLOB.master_mode]"]"
if(SSticker.HasRoundStarted())
return
var/time_remaining = SSticker.GetTimeLeft()
if(time_remaining > 0)
stat(null, "Time To Start: [round(time_remaining/10)]s")
. += "Time To Start: [round(time_remaining/10)]s"
else if(time_remaining == -10)
stat(null, "Time To Start: DELAYED")
. += "Time To Start: DELAYED"
else
stat(null, "Time To Start: SOON")
. += "Time To Start: SOON"
stat(null, "Players: [SSticker.totalPlayers]")
. += "Players: [SSticker.totalPlayers]"
if(client.holder)
stat(null, "Players Ready: [SSticker.totalPlayersReady]")
. += "Players Ready: [SSticker.totalPlayersReady]"
/mob/dead/proc/server_hop()
set category = "OOC"
@@ -74,7 +72,7 @@ INITIALIZE_IMMEDIATE(/mob/dead)
var/pick
switch(csa.len)
if(0)
verbs -= /mob/dead/proc/server_hop
remove_verb(src, /mob/dead/proc/server_hop)
to_chat(src, "<span class='notice'>Server Hop has been disabled.</span>")
if(1)
pick = csa[0]
@@ -295,6 +295,7 @@
if(observer.client && observer.client.prefs)
observer.real_name = observer.client.prefs.real_name
observer.name = observer.real_name
observer.client.init_verbs()
observer.update_icon()
observer.stop_sound_channel(CHANNEL_LOBBYMUSIC)
QDEL_NULL(mind)
@@ -392,7 +393,7 @@
job.standard_assign_skills(character.mind)
SSticker.minds += character.mind
character.client.init_verbs() // init verbs for the late join
var/mob/living/carbon/human/humanc
if(ishuman(character))
humanc = character //Let's retypecast the var to be human,
@@ -577,7 +578,7 @@
mind.original_character = H
H.name = real_name
client.init_verbs()
. = H
new_character = .
if(transfer_after)
+1 -1
View File
@@ -229,7 +229,7 @@
src << browse(null ,"window=playerpolllist")
src << browse(output,"window=playerpoll;size=500x250")
if(POLLTYPE_IRV)
var/datum/asset/irv_assets = get_asset_datum(/datum/asset/group/IRV)
var/datum/asset/irv_assets = get_asset_datum(/datum/asset/group/irv)
irv_assets.send(src)
var/datum/DBQuery/query_irv_get_votes = SSdbcore.NewQuery("SELECT optionid FROM [format_table_name("poll_vote")] WHERE pollid = [pollid] AND ckey = '[ckey]'")
+10 -10
View File
@@ -60,10 +60,10 @@ GLOBAL_VAR_INIT(observer_default_invisibility, INVISIBILITY_OBSERVER)
/mob/dead/observer/Initialize(mapload, mob/body)
set_invisibility(GLOB.observer_default_invisibility)
verbs += list(
add_verb(src, list(
/mob/dead/observer/proc/dead_tele,
/mob/dead/observer/proc/open_spawners_menu,
/mob/dead/observer/proc/view_gas)
/mob/dead/observer/proc/view_gas))
if(icon_state in GLOB.ghost_forms_with_directions_list)
ghostimage_default = image(src.icon,src,src.icon_state + "_nodir")
@@ -118,8 +118,8 @@ GLOBAL_VAR_INIT(observer_default_invisibility, INVISIBILITY_OBSERVER)
real_name = name
if(!fun_verbs)
verbs -= /mob/dead/observer/verb/boo
verbs -= /mob/dead/observer/verb/possess
remove_verb(src, /mob/dead/observer/verb/boo)
remove_verb(src, /mob/dead/observer/verb/possess)
animate(src, pixel_y = 2, time = 10, loop = -1)
@@ -409,8 +409,8 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
return
client.change_view(CONFIG_GET(string/default_view))
SStgui.on_transfer(src, mind.current) // Transfer NanoUIs.
transfer_ckey(mind.current, FALSE)
return 1
mind.current.client.init_verbs()
return TRUE
/mob/dead/observer/verb/stay_dead()
set category = "Ghost"
@@ -847,11 +847,11 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
ghostimage_simple.icon_state = icon_state
if(NAMEOF(src, fun_verbs))
if(fun_verbs)
verbs += /mob/dead/observer/verb/boo
verbs += /mob/dead/observer/verb/possess
add_verb(src, /mob/dead/observer/verb/boo)
add_verb(src, /mob/dead/observer/verb/possess)
else
verbs -= /mob/dead/observer/verb/boo
verbs -= /mob/dead/observer/verb/possess
remove_verb(src, /mob/dead/observer/verb/boo)
remove_verb(src, /mob/dead/observer/verb/possess)
/mob/dead/observer/reset_perspective(atom/A)
if(client)
@@ -33,8 +33,8 @@
var/static/regex/alien_name_regex = new("alien (larva|sentinel|drone|hunter|praetorian|queen)( \\(\\d+\\))?")
/mob/living/carbon/alien/Initialize()
verbs += /mob/living/proc/mob_sleep
verbs += /mob/living/proc/lay_down
add_verb(src, /mob/living/proc/mob_sleep)
add_verb(src, /mob/living/proc/lay_down)
create_bodyparts() //initialize bodyparts
@@ -93,11 +93,9 @@
/mob/living/carbon/alien/IsAdvancedToolUser()
return has_fine_manipulation
/mob/living/carbon/alien/Stat()
..()
if(statpanel("Status"))
stat(null, "Intent: [a_intent]")
/mob/living/carbon/alien/get_status_tab_items()
. = ..()
. += "Intent: [a_intent]"
/mob/living/carbon/alien/getTrail()
if(getBruteLoss() < 200)
@@ -148,10 +148,10 @@ Doesn't work on other aliens/AI.*/
action_icon_state = "alien_acid"
/obj/effect/proc_holder/alien/acid/on_gain(mob/living/carbon/user)
user.verbs.Add(/mob/living/carbon/proc/corrosive_acid)
add_verb(user, /mob/living/carbon/proc/corrosive_acid)
/obj/effect/proc_holder/alien/acid/on_lose(mob/living/carbon/user)
user.verbs.Remove(/mob/living/carbon/proc/corrosive_acid)
remove_verb(user, /mob/living/carbon/proc/corrosive_acid)
/obj/effect/proc_holder/alien/acid/proc/corrode(atom/target,mob/living/carbon/user = usr)
if(target in oview(1,user))
@@ -30,10 +30,9 @@
..()
//This needs to be fixed
/mob/living/carbon/alien/larva/Stat()
..()
if(statpanel("Status"))
stat(null, "Progress: [amount_grown]/[max_grown]")
/mob/living/carbon/alien/larva/get_status_tab_items()
. = ..()
. += "Progress: [amount_grown]/[max_grown]"
/mob/living/carbon/alien/larva/adjustPlasma(amount)
if(stat != DEAD && amount > 0)
+10 -9
View File
@@ -481,16 +481,17 @@
var/turf/target = get_turf(loc)
I.safe_throw_at(target,I.throw_range,I.throw_speed,src, force = move_force)
/mob/living/carbon/Stat()
..()
if(statpanel("Status"))
var/obj/item/organ/alien/plasmavessel/vessel = getorgan(/obj/item/organ/alien/plasmavessel)
if(vessel)
stat(null, "Plasma Stored: [vessel.storedPlasma]/[vessel.max_plasma]")
if(locate(/obj/item/assembly/health) in src)
stat(null, "Health: [health]")
/mob/living/carbon/get_status_tab_items()
. = ..()
var/obj/item/organ/alien/plasmavessel/vessel = getorgan(/obj/item/organ/alien/plasmavessel)
if(vessel)
. += "Plasma Stored: [vessel.storedPlasma]/[vessel.max_plasma]"
if(locate(/obj/item/assembly/health) in src)
. += "Health: [health]"
add_abilities_to_panel()
/mob/living/carbon/get_proc_holders()
. = ..()
. += add_abilities_to_panel()
/mob/living/carbon/attack_ui(slot)
if(!has_hand_for_held_index(active_hand_index))
+43 -48
View File
@@ -6,9 +6,8 @@
appearance_flags = KEEP_TOGETHER|TILE_BOUND|PIXEL_SCALE
/mob/living/carbon/human/Initialize()
verbs += /mob/living/proc/mob_sleep
verbs += /mob/living/proc/lay_down
verbs += /mob/living/carbon/human/proc/underwear_toggle //fwee
add_verb(src, /mob/living/proc/mob_sleep)
add_verb(src, /mob/living/proc/lay_down)
//initialize limbs first
create_bodyparts()
@@ -61,55 +60,51 @@
//...and display them.
add_to_all_human_data_huds()
/mob/living/carbon/human/Stat()
..()
if(statpanel("Status"))
stat(null, "Intent: [a_intent]")
stat(null, "Move Mode: [m_intent]")
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(mind)
var/datum/antagonist/changeling/changeling = mind.has_antag_datum(/datum/antagonist/changeling)
if(changeling)
stat("Chemical Storage", "[changeling.chem_charges]/[changeling.chem_storage]")
stat("Absorbed DNA", changeling.absorbedcount)
/mob/living/carbon/human/get_status_tab_items()
. = ..()
. += "Intent: [a_intent]"
. += "Move Mode: [m_intent]"
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]"
if(mind)
var/datum/antagonist/changeling/changeling = mind.has_antag_datum(/datum/antagonist/changeling)
if(changeling)
. += ""
. += "Chemical Storage: [changeling.chem_charges]/[changeling.chem_storage]"
. += "Absorbed DNA: [changeling.absorbedcount]"
//NINJACODE
if(istype(wear_suit, /obj/item/clothing/suit/space/space_ninja)) //Only display if actually a ninja.
var/obj/item/clothing/suit/space/space_ninja/SN = wear_suit
if(statpanel("SpiderOS"))
stat("SpiderOS Status:","[SN.s_initialized ? "Initialized" : "Disabled"]")
stat("Current Time:", "[STATION_TIME_TIMESTAMP("hh:mm:ss", world.time)]")
if(SN.s_initialized)
//Suit gear
stat("Energy Charge:", "[round(SN.cell.charge/100)]%")
stat("Smoke Bombs:", "\Roman [SN.s_bombs]")
//Ninja status
stat("Fingerprints:", "[md5(dna.uni_identity)]")
stat("Unique Identity:", "[dna.unique_enzymes]")
stat("Overall Status:", "[stat > 1 ? "dead" : "[health]% healthy"]")
stat("Nutrition Status:", "[nutrition]")
stat("Oxygen Loss:", "[getOxyLoss()]")
stat("Toxin Levels:", "[getToxLoss()]")
stat("Burn Severity:", "[getFireLoss()]")
stat("Brute Trauma:", "[getBruteLoss()]")
stat("Radiation Levels:","[radiation] rad")
stat("Body Temperature:","[bodytemperature-T0C] degrees C ([bodytemperature*1.8-459.67] degrees F)")
. += "SpiderOS Status: [SN.s_initialized ? "Initialized" : "Disabled"]"
. += "Current Time: [STATION_TIME_TIMESTAMP("hh:mm:ss", world.time)]"
if(SN.s_initialized)
//Suit gear
. += "Energy Charge: [round(SN.cell.charge/100)]%"
. += "Smoke Bombs: \Roman [SN.s_bombs]"
//Ninja status
. += "Fingerprints: [md5(dna.uni_identity)]"
. += "Unique Identity: [dna.unique_enzymes]"
. += "Overall Status: [stat > 1 ? "dead" : "[health]% healthy"]"
. += "Nutrition Status: [nutrition]"
. += "Oxygen Loss: [getOxyLoss()]"
. += "Toxin Levels: [getToxLoss()]"
. += "Burn Severity: [getFireLoss()]"
. += "Brute Trauma: [getBruteLoss()]"
. += "Radiation Levels: [radiation] rad"
. += "Body Temperature: [bodytemperature-T0C] degrees C ([bodytemperature*1.8-459.67] degrees F)"
//Diseases
if(diseases.len)
stat("Viruses:", null)
for(var/thing in diseases)
var/datum/disease/D = thing
stat("*", "[D.name], Type: [D.spread_text], Stage: [D.stage]/[D.max_stages], Possible Cure: [D.cure_text]")
//Diseases
if(length(diseases))
. += "Viruses:"
for(var/thing in diseases)
var/datum/disease/D = thing
. += "* [D.name], Type: [D.spread_text], Stage: [D.stage]/[D.max_stages], Possible Cure: [D.cure_text]"
/mob/living/carbon/human/show_inv(mob/user)
@@ -114,6 +114,14 @@
#undef VAMP_DRAIN_AMOUNT
/mob/living/carbon/get_status_tab_items()
. = ..()
var/obj/item/organ/heart/vampire/darkheart = getorgan(/obj/item/organ/heart/vampire)
if(darkheart)
. += "<span class='notice'>Current blood level: [blood_volume]/[BLOOD_VOLUME_MAXIMUM].</span>"
/obj/item/organ/heart/vampire
name = "vampire heart"
actions_types = list(/datum/action/item_action/organ_action/vampire_heart)
+12 -12
View File
@@ -18,8 +18,8 @@
hud_type = /datum/hud/monkey
/mob/living/carbon/monkey/Initialize(mapload, cubespawned=FALSE, mob/spawner)
verbs += /mob/living/proc/mob_sleep
verbs += /mob/living/proc/lay_down
add_verb(src, /mob/living/proc/mob_sleep)
add_verb(src, /mob/living/proc/lay_down)
if(unique_name) //used to exclude pun pun
gender = pick(MALE, FEMALE)
@@ -90,16 +90,16 @@
return
add_or_update_variable_movespeed_modifier(/datum/movespeed_modifier/monkey_temperature_speedmod, TRUE, slow)
/mob/living/carbon/monkey/Stat()
..()
if(statpanel("Status"))
stat(null, "Intent: [a_intent]")
stat(null, "Move Mode: [m_intent]")
if(client && mind)
var/datum/antagonist/changeling/changeling = mind.has_antag_datum(/datum/antagonist/changeling)
if(changeling)
stat("Chemical Storage", "[changeling.chem_charges]/[changeling.chem_storage]")
stat("Absorbed DNA", changeling.absorbedcount)
/mob/living/carbon/monkey/get_status_tab_items()
. = ..()
. += "Intent: [a_intent]"
. += "Move Mode: [m_intent]"
if(client && mind)
var/datum/antagonist/changeling/changeling = mind.has_antag_datum(/datum/antagonist/changeling)
if(changeling)
. += ""
. += "Chemical Storage: [changeling.chem_charges]/[changeling.chem_storage]"
. += "Absorbed DNA: [changeling.absorbedcount]"
/mob/living/carbon/monkey/verb/removeinternal()
+3 -1
View File
@@ -1163,8 +1163,10 @@
A.action.Remove(src)
/mob/living/proc/add_abilities_to_panel()
var/list/L = list()
for(var/obj/effect/proc_holder/A in abilities)
statpanel("[A.panel]",A.get_panel_text(),A)
L[++L.len] = list("[A.panel]",A.get_panel_text(),A.name,"[REF(A)]")
return L
/mob/living/lingcheck()
if(mind)
+24 -24
View File
@@ -139,7 +139,7 @@
spark_system.set_up(5, 0, src)
spark_system.attach(src)
verbs += /mob/living/silicon/ai/proc/show_laws_verb
add_verb(src, /mob/living/silicon/ai/proc/show_laws_verb)
aiPDA = new/obj/item/pda/ai(src)
aiPDA.owner = name
@@ -153,10 +153,10 @@
deploy_action.Grant(src)
if(isturf(loc))
verbs.Add(/mob/living/silicon/ai/proc/ai_network_change, \
add_verb(src, list(/mob/living/silicon/ai/proc/ai_network_change, \
/mob/living/silicon/ai/proc/ai_statuschange, /mob/living/silicon/ai/proc/ai_hologram_change, \
/mob/living/silicon/ai/proc/botcall, /mob/living/silicon/ai/proc/control_integrated_radio, \
/mob/living/silicon/ai/proc/set_automatic_say_channel)
/mob/living/silicon/ai/proc/set_automatic_say_channel))
GLOB.ai_list += src
GLOB.shuttle_caller_list += src
@@ -208,26 +208,26 @@
display_icon_override = ai_core_icon
set_core_display_icon(ai_core_icon)
/mob/living/silicon/ai/Stat()
..()
if(statpanel("Status"))
if(!stat)
stat(null, text("System integrity: [(health+100)/2]%"))
stat(null, text("Connected cyborgs: [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.designation] | 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 != CONSCIOUS)
. += text("Systems nonfunctional")
return
. += text("System integrity: [(health + 100) * 0.5]%")
. += text("Connected cyborgs: [length(connected_robots)]")
for(var/r in connected_robots)
var/mob/living/silicon/robot/connected_robot = r
var/robot_status = "Nominal"
if(connected_robot.shell)
robot_status = "AI SHELL"
else if(connected_robot.stat != CONSCIOUS || !connected_robot.client)
robot_status = "OFFLINE"
else if(!connected_robot.cell || connected_robot.cell.charge <= 0)
robot_status = "DEPOWERED"
//Name, Health, Battery, Module, Area, and Status! Everything an AI wants to know about its borgies!
. += text("[connected_robot.name] | S.Integrity: [connected_robot.health]% | Cell: [connected_robot.cell ? "[connected_robot.cell.charge]/[connected_robot.cell.maxcharge]" : "Empty"] | \
Module: [connected_robot.designation] | Loc: [get_area_name(connected_robot, TRUE)] | Status: [robot_status]")
. += text("AI shell beacons detected: [LAZYLEN(GLOB.available_ai_shells)]") //Count of total AI shells
/mob/living/silicon/ai/proc/ai_alerts()
var/dat = "<HEAD><TITLE>Current Station Alerts</TITLE><META HTTP-EQUIV='Refresh' CONTENT='10'></HEAD><BODY>\n"
@@ -858,7 +858,7 @@
to_chat(src, "In the top right corner of the screen you will find the Malfunctions tab, where you can purchase various abilities, from upgraded surveillance to station ending doomsday devices.")
to_chat(src, "You are also capable of hacking APCs, which grants you more points to spend on your Malfunction powers. The drawback is that a hacked APC will give you away if spotted by the crew. Hacking an APC takes 60 seconds.")
view_core() //A BYOND bug requires you to be viewing your core before your verbs update
verbs += /mob/living/silicon/ai/proc/choose_modules
add_verb(src, /mob/living/silicon/ai/proc/choose_modules)
malf_picker = new /datum/module_picker
+6 -7
View File
@@ -184,13 +184,12 @@
else
client.eye = card
/mob/living/silicon/pai/Stat()
..()
if(statpanel("Status"))
if(!stat)
stat(null, text("Emitter Integrity: [emitterhealth * (100/emittermaxhealth)]"))
else
stat(null, text("Systems nonfunctional"))
/mob/living/silicon/pai/get_status_tab_items()
. += ..()
if(!stat)
. += text("Emitter Integrity: [emitterhealth * (100/emittermaxhealth)]")
else
. += text("Systems nonfunctional")
/mob/living/silicon/pai/restrained(ignore_grab)
. = FALSE
+14 -14
View File
@@ -72,8 +72,8 @@
toner = tonermax
diag_hud_set_borgcell()
verbs += /mob/living/proc/lay_down //CITADEL EDIT gimmie rest verb kthx
verbs += /mob/living/silicon/robot/proc/rest_style
add_verb(src, /mob/living/proc/lay_down) //CITADEL EDIT gimmie rest verb kthx
add_verb(src, /mob/living/silicon/robot/proc/rest_style)
//If there's an MMI in the robot, have it ejected when the mob goes away. --NEO
/mob/living/silicon/robot/Destroy()
@@ -222,19 +222,19 @@
if(thruster_button)
thruster_button.icon_state = "ionpulse[ionpulse_on]"
/mob/living/silicon/robot/Stat()
..()
if(statpanel("Status"))
if(cell)
stat("Charge Left:", "[cell.charge]/[cell.maxcharge]")
else
stat(null, text("No Cell Inserted!"))
/mob/living/silicon/robot/get_status_tab_items()
. = ..()
. += ""
if(cell)
. += "Charge Left: [cell.charge]/[cell.maxcharge]"
else
. += text("No Cell Inserted!")
if(module)
for(var/datum/robot_energy_storage/st in module.storages)
stat("[st.name]:", "[st.energy]/[st.max_energy]")
if(connected_ai)
stat("Master AI:", connected_ai.name)
if(module)
for(var/datum/robot_energy_storage/st in module.storages)
. += "[st.name]: [st.energy]/[st.max_energy]"
if(connected_ai)
. += "Master AI: [connected_ai.name]"
/mob/living/silicon/robot/restrained(ignore_grab)
. = 0
@@ -438,6 +438,16 @@
/mob/living/simple_animal/bot/mulebot/get_status_tab_items()
. = ..()
if(cell)
. += "Charge Left: [cell.charge]/[cell.maxcharge]"
else
. += text("No Cell Inserted!")
if(load)
. += "Current Load: [load.name]"
/mob/living/simple_animal/bot/mulebot/call_bot()
..()
if(path && path.len)
@@ -34,7 +34,7 @@
/mob/living/simple_animal/pet/bumbles/Initialize()
. = ..()
verbs += /mob/living/proc/lay_down
add_verb(src, /mob/living/proc/lay_down)
/mob/living/simple_animal/pet/bumbles/ComponentInitialize()
. = ..()
@@ -39,7 +39,7 @@
/mob/living/simple_animal/pet/cat/Initialize()
. = ..()
verbs += /mob/living/proc/lay_down
add_verb(src, /mob/living/proc/lay_down)
/mob/living/simple_animal/pet/cat/ComponentInitialize()
. = ..()
@@ -142,8 +142,8 @@
set_light(2, 0.5)
qdel(access_card) //we don't have free access
access_card = null
verbs -= /mob/living/simple_animal/drone/verb/check_laws
verbs -= /mob/living/simple_animal/drone/verb/drone_ping
remove_verb(src, /mob/living/simple_animal/drone/verb/check_laws)
remove_verb(src, /mob/living/simple_animal/drone/verb/drone_ping)
/mob/living/simple_animal/drone/cogscarab/Login()
..()
@@ -196,18 +196,17 @@ GLOBAL_LIST_EMPTY(parasites) //all currently existing/living guardians
REMOVE_TRAIT(summoner, TRAIT_NODEATH, "memento_mori")
to_chat(summoner,"<span class='danger'>You feel incredibly vulnerable as the memento mori pulls your life force in one too many directions!")
/mob/living/simple_animal/hostile/guardian/Stat()
..()
if(statpanel("Status"))
if(summoner)
var/resulthealth
if(iscarbon(summoner))
resulthealth = round((abs(HEALTH_THRESHOLD_DEAD - summoner.health) / abs(HEALTH_THRESHOLD_DEAD - summoner.maxHealth)) * 100)
else
resulthealth = round((summoner.health / summoner.maxHealth) * 100, 0.5)
stat(null, "Summoner Health: [resulthealth]%")
if(cooldown >= world.time)
stat(null, "Manifest/Recall Cooldown Remaining: [DisplayTimeText(cooldown - world.time)]")
/mob/living/simple_animal/hostile/guardian/get_status_tab_items()
. += ..()
if(summoner)
var/resulthealth
if(iscarbon(summoner))
resulthealth = round((abs(HEALTH_THRESHOLD_DEAD - summoner.health) / abs(HEALTH_THRESHOLD_DEAD - summoner.maxHealth)) * 100)
else
resulthealth = round((summoner.health / summoner.maxHealth) * 100, 0.5)
. += "Summoner Health: [resulthealth]%"
if(cooldown >= world.time)
. += "Manifest/Recall Cooldown Remaining: [DisplayTimeText(cooldown - world.time)]"
/mob/living/simple_animal/hostile/guardian/Move() //Returns to summoner if they move out of range
. = ..()
@@ -477,13 +476,13 @@ GLOBAL_LIST_EMPTY(parasites) //all currently existing/living guardians
to_chat(src, "<span class='holoparasite'><font color=\"[G.guardiancolor]\"><b>[G.real_name]</b></font> has been caught!</span>")
guardians -= G
if(!guardians.len)
verbs -= /mob/living/proc/guardian_reset
remove_verb(src, /mob/living/proc/guardian_reset)
else
to_chat(src, "<span class='holoparasite'>There were no ghosts willing to take control of <font color=\"[G.guardiancolor]\"><b>[G.real_name]</b></font>. Looks like you're stuck with it for now.</span>")
else
to_chat(src, "<span class='holoparasite'>You decide not to reset [guardians.len > 1 ? "any of your guardians":"your guardian"].</span>")
else
verbs -= /mob/living/proc/guardian_reset
remove_verb(src, /mob/living/proc/guardian_reset)
////////parasite tracking/finding procs
@@ -608,9 +607,9 @@ GLOBAL_LIST_EMPTY(parasites) //all currently existing/living guardians
if("carp")
to_chat(user, "[G.carp_fluff_string]")
to_chat(user, "<span class='holoparasite'><b>[G.real_name]</b> has been caught!</span>")
user.verbs += /mob/living/proc/guardian_comm
user.verbs += /mob/living/proc/guardian_recall
user.verbs += /mob/living/proc/guardian_reset
add_verb(user, list(/mob/living/proc/guardian_comm, \
/mob/living/proc/guardian_recall, \
/mob/living/proc/guardian_reset))
/obj/item/guardiancreator/choose
random = FALSE
@@ -26,11 +26,10 @@
if(loc == summoner && toggle)
ToggleMode(0)
/mob/living/simple_animal/hostile/guardian/assassin/Stat()
..()
if(statpanel("Status"))
if(stealthcooldown >= world.time)
stat(null, "Stealth Cooldown Remaining: [DisplayTimeText(stealthcooldown - world.time)]")
/mob/living/simple_animal/hostile/guardian/assassin/get_status_tab_items()
. = ..()
if(stealthcooldown >= world.time)
. += "Stealth Cooldown Remaining: [DisplayTimeText(stealthcooldown - world.time)]"
/mob/living/simple_animal/hostile/guardian/assassin/AttackingTarget()
. = ..()
@@ -7,11 +7,10 @@
carp_fluff_string = "<span class='holoparasite'>CARP CARP CARP! Caught one! It's an explosive carp! Boom goes the fishy.</span>"
var/bomb_cooldown = 0
/mob/living/simple_animal/hostile/guardian/bomb/Stat()
..()
if(statpanel("Status"))
if(bomb_cooldown >= world.time)
stat(null, "Bomb Cooldown Remaining: [DisplayTimeText(bomb_cooldown - world.time)]")
/mob/living/simple_animal/hostile/guardian/bomb/get_status_tab_items()
. = ..()
if(bomb_cooldown >= world.time)
. += "Bomb Cooldown Remaining: [DisplayTimeText(bomb_cooldown - world.time)]"
/mob/living/simple_animal/hostile/guardian/bomb/AttackingTarget()
. = ..()
@@ -18,11 +18,10 @@
var/datum/atom_hud/medsensor = GLOB.huds[DATA_HUD_MEDICAL_ADVANCED]
medsensor.add_hud_to(src)
/mob/living/simple_animal/hostile/guardian/healer/Stat()
..()
if(statpanel("Status"))
if(beacon_cooldown >= world.time)
stat(null, "Beacon Cooldown Remaining: [DisplayTimeText(beacon_cooldown - world.time)]")
/mob/living/simple_animal/hostile/guardian/healer/get_status_tab_items()
. = ..()
if(beacon_cooldown >= world.time)
. += "Beacon Cooldown Remaining: [DisplayTimeText(beacon_cooldown - world.time)]"
/mob/living/simple_animal/hostile/guardian/healer/AttackingTarget()
. = ..()
@@ -128,7 +128,7 @@
/mob/living/simple_animal/hostile/jungle/leaper/Initialize()
. = ..()
verbs -= /mob/living/verb/pulled
remove_verb(src, /mob/living/verb/pulled)
/mob/living/simple_animal/hostile/jungle/leaper/CtrlClickOn(atom/A)
face_atom(A)
@@ -642,8 +642,8 @@ Difficulty: Very Hard
/mob/living/simple_animal/hostile/lightgeist/Initialize()
. = ..()
verbs -= /mob/living/verb/pulled
verbs -= /mob/verb/me_verb
remove_verb(src, /mob/living/verb/pulled)
remove_verb(src, /mob/verb/me_verb)
var/datum/atom_hud/medsensor = GLOB.huds[DATA_HUD_MEDICAL_ADVANCED]
medsensor.add_hud_to(src)
@@ -732,7 +732,7 @@ Difficulty: Very Hard
L.mind.transfer_to(holder_animal)
var/obj/effect/proc_holder/spell/targeted/exit_possession/P = new /obj/effect/proc_holder/spell/targeted/exit_possession
holder_animal.mind.AddSpell(P)
holder_animal.verbs -= /mob/living/verb/pulled
remove_verb(holder_animal, /mob/living/verb/pulled)
/obj/structure/closet/stasis/dump_contents(override = TRUE, kill = 1)
STOP_PROCESSING(SSobj, src)
@@ -115,12 +115,12 @@
parrot_sleep_dur = parrot_sleep_max //In case someone decides to change the max without changing the duration var
verbs.Add(/mob/living/simple_animal/parrot/proc/steal_from_ground, \
add_verb(src, list(/mob/living/simple_animal/parrot/proc/steal_from_ground, \
/mob/living/simple_animal/parrot/proc/steal_from_mob, \
/mob/living/simple_animal/parrot/verb/drop_held_item_player, \
/mob/living/simple_animal/parrot/proc/perch_player, \
/mob/living/simple_animal/parrot/proc/toggle_mode,
/mob/living/simple_animal/parrot/proc/perch_mob_player)
/mob/living/simple_animal/parrot/proc/perch_mob_player))
/mob/living/simple_animal/parrot/examine(mob/user)
@@ -142,11 +142,11 @@
..(gibbed)
/mob/living/simple_animal/parrot/Stat()
..()
if(statpanel("Status"))
stat("Held Item", held_item)
stat("Mode",a_intent)
/mob/living/simple_animal/parrot/get_status_tab_items()
. = ..()
. += ""
. += "Held Item: [held_item]"
. += "Mode: [a_intent]"
/mob/living/simple_animal/parrot/Hear(message, atom/movable/speaker, message_langs, raw_message, radio_freq, list/spans, message_mode, atom/movable/source)
. = ..()
@@ -345,11 +345,10 @@
remove_movespeed_modifier(/datum/movespeed_modifier/simplemob_varspeed)
add_or_update_variable_movespeed_modifier(/datum/movespeed_modifier/simplemob_varspeed, multiplicative_slowdown = speed)
/mob/living/simple_animal/Stat()
..()
if(statpanel("Status"))
stat(null, "Health: [round((health / maxHealth) * 100)]%")
return 1
/mob/living/simple_animal/get_status_tab_items()
. = ..()
. += ""
. += "Health: [round((health / maxHealth) * 100)]%"
/mob/living/simple_animal/proc/drop_loot()
if(loot.len)
@@ -208,21 +208,20 @@
/mob/living/simple_animal/slime/Process_Spacemove(movement_dir = 0)
return 2
/mob/living/simple_animal/slime/Stat()
if(..())
if(!docile)
stat(null, "Nutrition: [nutrition]/[get_max_nutrition()]")
if(amount_grown >= SLIME_EVOLUTION_THRESHOLD)
if(is_adult)
stat(null, "You can reproduce!")
else
stat(null, "You can evolve!")
/mob/living/simple_animal/slime/get_status_tab_items()
. = ..()
if(!docile)
. += "Nutrition: [nutrition]/[get_max_nutrition()]"
if(amount_grown >= SLIME_EVOLUTION_THRESHOLD)
if(is_adult)
. += "You can reproduce!"
else
. += "You can evolve!"
if(stat == UNCONSCIOUS)
stat(null,"You are knocked out by high levels of BZ!")
. += "You are knocked out by high levels of BZ!"
else
stat(null,"Power Level: [powerlevel]")
. += "Power Level: [powerlevel]"
/mob/living/simple_animal/slime/adjustFireLoss(amount, updating_health = TRUE, forced = FALSE)
+21 -72
View File
@@ -586,87 +586,34 @@ GLOBAL_VAR_INIT(exploit_warn_spam_prevention, 0)
/mob/proc/is_muzzled()
return FALSE
/mob/Stat()
..()
/// Adds this list to the output to the stat browser
/mob/proc/get_status_tab_items()
. = list()
SSvote?.render_statpanel(src)
//This is only called from client/Stat(), let's assume client exists.
if(statpanel("Status"))
var/list/L = list()
L += "Ping: [round(client.lastping,1)]ms (Avg: [round(client.avgping,1)]ms)"
L += SSmapping.stat_map_name
L += "Round ID: [GLOB.round_id || "NULL"]"
L += SStime_track.stat_time_text
L += SSshuttle.emergency_shuttle_stat_text
stat(null, "[L.Join("\n\n")]")
if(client.holder)
if(statpanel("MC"))
var/turf/T = get_turf(client.eye)
stat("Location:", COORD(T))
stat("CPU:", "[world.cpu]")
stat("Instances:", "[num2text(world.contents.len, 10)]")
stat("World Time:", "[world.time]")
GLOB.stat_entry()
config.stat_entry()
stat(null)
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.statworthy_subsystems)
SS.stat_entry()
GLOB.cameranet.stat_entry()
if(statpanel("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/i in GLOB.sdql2_queries)
var/datum/SDQL2_query/Q = i
Q.generate_stat()
if(listed_turf && client)
if(!TurfAdjacent(listed_turf))
listed_turf = null
else
statpanel(listed_turf.name, null, listed_turf)
var/list/overrides = list()
for(var/image/I in client.images)
if(I.loc && I.loc.loc == listed_turf && I.override)
overrides += I.loc
for(var/atom/A in listed_turf)
if(!A.mouse_opacity)
continue
if(A.invisibility > see_invisible)
continue
if(overrides.len && (A in overrides))
continue
statpanel(listed_turf.name, null, A)
/// Gets all relevant proc holders for the browser statpenl
/mob/proc/get_proc_holders()
. = list()
if(mind)
add_spells_to_statpanel(mind.spell_list)
var/datum/antagonist/changeling/changeling = mind.has_antag_datum(/datum/antagonist/changeling)
if(changeling)
add_stings_to_statpanel(changeling.purchasedpowers)
add_spells_to_statpanel(mob_spell_list)
. += get_spells_for_statpanel(mind.spell_list)
. += get_spells_for_statpanel(mob_spell_list)
/mob/proc/add_spells_to_statpanel(list/spells)
/**
* Convert a list of spells into a displyable list for the statpanel
*
* Shows charge and other important info
*/
/mob/proc/get_spells_for_statpanel(list/spells)
var/list/L = list()
for(var/obj/effect/proc_holder/spell/S in spells)
if((!S.mobs_blacklist || !S.mobs_blacklist[src]) && (!S.mobs_whitelist || S.mobs_whitelist[src]))
switch(S.charge_type)
if("recharge")
statpanel("[S.panel]","[S.charge_counter/10.0]/[S.charge_max/10]",S)
L[++L.len] = list("[S.panel]", "[S.charge_counter/10.0]/[S.charge_max/10]", S.name, REF(S))
if("charges")
statpanel("[S.panel]","[S.charge_counter]/[S.charge_max]",S)
L[++L.len] = list("[S.panel]", "[S.charge_counter]/[S.charge_max]", S.name, REF(S))
if("holdervar")
statpanel("[S.panel]","[S.holder_var_type] [S.holder_var_amount]",S)
L[++L.len] = list("[S.panel]", "[S.holder_var_type] [S.holder_var_amount]", S.name, REF(S))
return L
/mob/proc/add_stings_to_statpanel(list/stings)
for(var/obj/effect/proc_holder/changeling/S in stings)
@@ -798,6 +745,8 @@ GLOBAL_VAR_INIT(exploit_warn_spam_prevention, 0)
if(istype(S, spell))
mob_spell_list -= S
qdel(S)
if(client)
client << output(null, "statbrowser:check_spells")
/mob/proc/anti_magic_check(magic = TRUE, holy = FALSE, tinfoil = FALSE, chargecost = 1, self = FALSE)
if(!magic && !holy && !tinfoil)
+1 -1
View File
@@ -195,7 +195,7 @@
/obj/item/ticket_machine_ticket
name = "Ticket"
desc = "A ticket which shows your place in the Head of Personnel's line. Made from Nanotrasen patented NanoPaper®. Though solid, its form seems to shimmer slightly. Feels (and burns) just like the real thing."
desc = "A ticket which shows your place in the Head of Personnel's line. Made from Nanotrasen patented NanoPaper. Though solid, its form seems to shimmer slightly. Feels (and burns) just like the real thing."
icon = 'icons/obj/bureaucracy.dmi'
icon_state = "ticket"
maptext_x = 7
+2 -2
View File
@@ -1161,7 +1161,7 @@
occupier.eyeobj.name = "[occupier.name] (AI Eye)"
if(malf.parent)
qdel(malf)
occupier.verbs += /mob/living/silicon/ai/proc/corereturn
add_verb(occupier, /mob/living/silicon/ai/proc/corereturn)
occupier.cancel_camera()
@@ -1173,7 +1173,7 @@
occupier.parent.shunted = 0
occupier.parent.setOxyLoss(occupier.getOxyLoss())
occupier.parent.cancel_camera()
occupier.parent.verbs -= /mob/living/silicon/ai/proc/corereturn
remove_verb(occupier.parent, /mob/living/silicon/ai/proc/corereturn)
qdel(occupier)
else
to_chat(occupier, "<span class='danger'>Primary core damaged, unable to return core processes.</span>")
@@ -8,7 +8,7 @@
/obj/item/gun/ballistic/revolver/Initialize()
. = ..()
if(!istype(magazine, /obj/item/ammo_box/magazine/internal/cylinder))
verbs -= /obj/item/gun/ballistic/revolver/verb/spin
remove_verb(src, /obj/item/gun/ballistic/revolver/verb/spin)
/obj/item/gun/ballistic/revolver/chamber_round(spin = 1)
if(spin)
@@ -60,7 +60,7 @@
if(do_spin())
usr.visible_message("[usr] spins [src]'s chamber.", "<span class='notice'>You spin [src]'s chamber.</span>")
else
verbs -= /obj/item/gun/ballistic/revolver/verb/spin
remove_verb(src, /obj/item/gun/ballistic/revolver/verb/spin)
/obj/item/gun/ballistic/revolver/proc/do_spin()
var/obj/item/ammo_box/magazine/internal/cylinder/C = magazine
+1 -1
View File
@@ -22,7 +22,7 @@
if(isnum(vol) && vol > 0)
volume = vol
if(container_flags & APTFT_VERB && length(possible_transfer_amounts))
verbs += /obj/item/reagent_containers/proc/set_APTFT
add_verb(src, /obj/item/reagent_containers/proc/set_APTFT)
create_reagents(volume, reagent_flags, reagent_value)
if(spawned_disease)
var/datum/disease/F = new spawned_disease()
+17
View File
@@ -0,0 +1,17 @@
/**
* Message-related procs
*
* Message format (/list):
* - type - Message type, must be one of defines in `code/__DEFINES/chat.dm`
* - text - Plain message text
* - html - HTML message text
* - Optional metadata, can be any key/value pair.
*
* Copyright (c) 2020 Aleksej Komarov
* SPDX-License-Identifier: MIT
*/
/proc/message_to_html(message)
// Here it is possible to add a switch statement
// to custom-handle various message types.
return message["html"] || message["text"]
+75
View File
@@ -0,0 +1,75 @@
/**
* Copyright (c) 2020 Aleksej Komarov
* SPDX-License-Identifier: MIT
*/
/**
* Circumvents the message queue and sends the message
* to the recipient (target) as soon as possible.
*/
/proc/to_chat_immediate(target, html,
type = null,
text = null,
avoid_highlighting = FALSE,
// FIXME: These flags are now pointless and have no effect
handle_whitespace = TRUE,
trailing_newline = TRUE,
confidential = FALSE)
if(!target || (!html && !text))
return
if(target == world)
target = GLOB.clients
// Build a message
var/message = list()
if(type) message["type"] = type
if(text) message["text"] = text
if(html) message["html"] = html
if(avoid_highlighting) message["avoidHighlighting"] = avoid_highlighting
var/message_blob = TGUI_CREATE_MESSAGE("chat/message", message)
var/message_html = message_to_html(message)
if(islist(target))
for(var/_target in target)
var/client/client = CLIENT_FROM_VAR(_target)
if(client)
// Send to tgchat
client.tgui_panel?.window.send_raw_message(message_blob)
// Send to old chat
SEND_TEXT(client, message_html)
return
var/client/client = CLIENT_FROM_VAR(target)
if(client)
// Send to tgchat
client.tgui_panel?.window.send_raw_message(message_blob)
// Send to old chat
SEND_TEXT(client, message_html)
/**
* Sends the message to the recipient (target).
*
* Recommended way to write to_chat calls:
* to_chat(client,
* type = MESSAGE_TYPE_INFO,
* html = "You have found <strong>[object]</strong>")
*/
/proc/to_chat(target, html,
type = null,
text = null,
avoid_highlighting = FALSE,
// FIXME: These flags are now pointless and have no effect
handle_whitespace = TRUE,
trailing_newline = TRUE,
confidential = FALSE)
if(Master.current_runlevel == RUNLEVEL_INIT || !SSchat?.initialized)
to_chat_immediate(target, html, type, text)
return
if(!target || (!html && !text))
return
if(target == world)
target = GLOB.clients
// Build a message
var/message = list()
if(type) message["type"] = type
if(text) message["text"] = text
if(html) message["html"] = html
if(avoid_highlighting) message["avoidHighlighting"] = avoid_highlighting
SSchat.queue(target, message)
+8 -2
View File
@@ -175,7 +175,11 @@
var/type = href_list["type"]
// Unconditionally collect tgui logs
if(type == "log")
log_tgui(usr, href_list["message"])
var/context = href_list["window_id"]
if (href_list["ns"])
context += " ([href_list["ns"]])"
log_tgui(usr, href_list["message"],
context = context)
// Reload all tgui windows
if(type == "cacheReloaded")
if(!check_rights(R_ADMIN) || usr.client.tgui_cache_reloaded)
@@ -195,7 +199,9 @@
if(window_id)
window = usr.client.tgui_windows[window_id]
if(!window)
log_tgui(usr, "Error: Couldn't find the window datum, force closing.")
log_tgui(usr,
"Error: Couldn't find the window datum, force closing.",
context = window_id)
SStgui.force_close_window(usr, window_id)
return TRUE
// Decode payload
+11 -7
View File
@@ -49,7 +49,9 @@
* return datum/tgui The requested UI.
*/
/datum/tgui/New(mob/user, datum/src_object, interface, title, ui_x, ui_y)
log_tgui(user, "new [interface] fancy [user.client.prefs.tgui_fancy]")
log_tgui(user,
"new [interface] fancy [user.client.prefs.tgui_fancy]",
src_object = src_object)
src.user = user
src.src_object = src_object
src.window_key = "[REF(src_object)]-main"
@@ -245,11 +247,9 @@
return
// Validate ping
if(!initialized && world.time - opened_at > TGUI_PING_TIMEOUT)
log_tgui(user, \
"Error: Zombie window detected, killing it with fire.\n" \
+ "window_id: [window.id]\n" \
+ "opened_at: [opened_at]\n" \
+ "world.time: [world.time]")
log_tgui(user, "Error: Zombie window detected, closing.",
window = window,
src_object = src_object)
close(can_be_suspended = FALSE)
return
// Update through a normal call to ui_interact
@@ -282,8 +282,12 @@
/datum/tgui/proc/on_message(type, list/payload, list/href_list)
// Pass act type messages to ui_act
if(type && copytext(type, 1, 5) == "act/")
var/act_type = copytext(type, 5)
log_tgui(user, "Action: [act_type] [href_list["payload"]]",
window = window,
src_object = src_object)
process_status()
if(src_object.ui_act(copytext(type, 5), payload, src, state))
if(src_object.ui_act(act_type, payload, src, state))
SStgui.update_uis(src_object)
return FALSE
switch(type)
+9 -3
View File
@@ -52,7 +52,9 @@
inline_assets = list(),
inline_html = "",
fancy = FALSE)
log_tgui(client, "[id]/initialize")
log_tgui(client,
context = "[id]/initialize",
window = src)
if(!client)
return
src.inline_assets = inline_assets
@@ -177,11 +179,15 @@
if(!client)
return
if(can_be_suspended && can_be_suspended())
log_tgui(client, "[id]/close: suspending")
log_tgui(client,
context = "[id]/close (suspending)",
window = src)
status = TGUI_WINDOW_READY
send_message("suspend")
return
log_tgui(client, "[id]/close")
log_tgui(client,
context = "[id]/close",
window = src)
release_lock()
status = TGUI_WINDOW_CLOSED
message_queue = null
+20 -26
View File
@@ -8,46 +8,40 @@
/**
* tgui panel / chat troubleshooting verb
*/
/client/verb/fix_chat()
/client/verb/fix_tgui_panel()
set name = "Fix chat"
set category = "OOC"
var/action
log_tgui(src, "tgui_panel: Started fix_chat.")
// Not initialized
if(!tgui_panel || !istype(tgui_panel))
log_tgui(src, "tgui_panel: datum is missing")
action = alert(src, "tgui panel was not initialized!\nSet it up again?", "", "OK", "Cancel")
if(action != "OK")
return
tgui_panel = new(src)
tgui_panel.initialize()
action = alert(src, "Wait a bit and tell me if it's fixed", "", "Fixed", "Nope")
if(action == "Fixed")
log_tgui(src, "tgui_panel: Fixed by calling 'new' + 'initialize'")
return
log_tgui(src, "Started fixing.",
context = "verb/fix_tgui_panel")
// Not ready
if(!tgui_panel?.is_ready())
log_tgui(src, "tgui_panel: not ready")
action = alert(src, "tgui panel looks like it's waiting for something.\nSend it a ping?", "", "OK", "Cancel")
if(action != "OK")
return
log_tgui(src, "Panel is not ready",
context = "verb/fix_tgui_panel")
tgui_panel.window.send_message("ping", force = TRUE)
action = alert(src, "Wait a bit and tell me if it's fixed", "", "Fixed", "Nope")
action = alert(src, "Method: Pinging the panel.\nWait a bit and tell me if it's fixed", "", "Fixed", "Nope")
if(action == "Fixed")
log_tgui(src, "tgui_panel: Fixed by sending a ping")
log_tgui(src, "Fixed by sending a ping",
context = "verb/fix_tgui_panel")
return
// Catch all solution
action = alert(src, "Looks like tgui panel was already setup, but we can always try again.\nSet it up again?", "", "OK", "Cancel")
if(action != "OK")
return
if(!tgui_panel || !istype(tgui_panel))
log_tgui(src, "tgui_panel datum is missing",
context = "verb/fix_tgui_panel")
tgui_panel = new(src)
tgui_panel.initialize(force = TRUE)
action = alert(src, "Wait a bit and tell me if it's fixed", "", "Fixed", "Nope")
// Force show the panel to see if there are any errors
winset(src, "output", "is-disabled=1&is-visible=0")
winset(src, "browseroutput", "is-disabled=0;is-visible=1")
action = alert(src, "Method: Reinitializing the panel.\nWait a bit and tell me if it's fixed", "", "Fixed", "Nope")
if(action == "Fixed")
log_tgui(src, "tgui_panel: Fixed by calling 'initialize'")
log_tgui(src, "Fixed by calling 'initialize'",
context = "verb/fix_tgui_panel")
return
// Failed to fix
action = alert(src, "Welp, I'm all out of ideas. Try closing BYOND and reconnecting.\nWe could also disable tgui_panel and re-enable the old UI", "", "Thanks anyways", "Switch to old UI")
if (action == "Switch to old UI")
winset(src, "output", "on-show=&is-disabled=0&is-visible=1")
winset(src, "browseroutput", "is-disabled=1;is-visible=0")
log_tgui(src, "tgui_panel: Failed to fix.")
log_tgui(src, "Failed to fix.",
context = "verb/fix_tgui_panel")
-71
View File
@@ -1,71 +0,0 @@
/**
* Copyright (c) 2020 Aleksej Komarov
* SPDX-License-Identifier: MIT
*/
/**
* global
*
* Circumvents the message queue and sends the message
* to the recipient (target) as soon as possible.
*/
/proc/to_chat_immediate(
target,
text,
handle_whitespace = TRUE,
trailing_newline = TRUE,
confidential = FALSE)
if(!target || !text)
return
if(target == world)
target = GLOB.clients
var/flags = handle_whitespace \
| trailing_newline << 1 \
| confidential << 2
var/message = TGUI_CREATE_MESSAGE("chat/message", list(
"text" = text,
"flags" = flags,
))
if(islist(target))
for(var/_target in target)
var/client/client = CLIENT_FROM_VAR(_target)
if(client)
// Send to tgchat
client.tgui_panel?.window.send_raw_message(message)
// Send to old chat
SEND_TEXT(client, text)
return
var/client/client = CLIENT_FROM_VAR(target)
if(client)
// Send to tgchat
client.tgui_panel?.window.send_raw_message(message)
// Send to old chat
SEND_TEXT(client, text)
/**
* global
*
* Sends the message to the recipient (target).
*/
/proc/to_chat(
target,
text,
handle_whitespace = TRUE,
trailing_newline = TRUE,
confidential = FALSE)
if(Master.current_runlevel == RUNLEVEL_INIT || !SSchat?.initialized)
to_chat_immediate(
target,
text,
handle_whitespace,
trailing_newline,
confidential)
return
if(!target || !text)
return
if(target == world)
target = GLOB.clients
var/flags = handle_whitespace \
| trailing_newline << 1 \
| confidential << 2
SSchat.queue(target, text, flags)
+2 -4
View File
@@ -11,13 +11,11 @@
// Hook for generic creation of stuff on new creatures
//
/hook/living_new/proc/vore_setup(mob/living/M)
M.verbs += /mob/living/proc/preyloop_refresh
M.verbs += /mob/living/proc/lick
M.verbs += /mob/living/proc/escapeOOC
add_verb(M, list(/mob/living/proc/preyloop_refresh, /mob/living/proc/lick, /mob/living/proc/escapeOOC))
if(M.vore_flags & NO_VORE) //If the mob isn't supposed to have a stomach, let's not give it an insidepanel so it can make one for itself, or a stomach.
return TRUE
M.verbs += /mob/living/proc/insidePanel
add_verb(M, /mob/living/proc/insidePanel)
//Tries to load prefs if a client is present otherwise gives freebie stomach
spawn(2 SECONDS) // long delay because the server delays in its startup. just on the safe side.
+882
View File
@@ -0,0 +1,882 @@
<!DOCTYPE html>
<html>
<head>
<title>Stat Browser</title>
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<link id="goonStyle" rel="stylesheet" type="text/css" href="browserOutput_white.css" media="all" />
<style>
body {
font-family: Verdana, Geneva, Tahoma, sans-serif;
font-size: 12px !important;
margin: 5px !important;
padding: 2px !important;
}
body.dark {
background-color: #131313;
color: #abc6ec;
}
#menu {
background-color: white;
}
.dark #menu {
background-color: #131313;
}
a {
color: black;
text-decoration: none
}
.dark a {
color: #abc6ec;
}
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;
flex-direction: row;
justify-content: flex-start;
align-items: flex-start;
min-width: 0;
min-height: 0;
white-space: pre-wrap;
}
.button {
background-color: #FFFFFE;
border-color: rgba(255, 255, 254, 0.5);
border-width: 1px;
color: black;
padding: 7px 14px;
text-align: center;
text-decoration: none;
font-size: 12px;
margin: 2px 2px;
cursor: pointer;
border-radius: 10%;
transition-duration: 0.25s;
order: 3;
}
.dark button {
background-color: #252525;
border-color: rgba(37, 37, 36, 0.5);
color: white;
}
.button:hover {
border-color: rgba(255, 255, 254, 0.5);
background-color: #252525;
color: white;
}
.dark button:hover {
border-color: rgba(37, 37, 36, 0.5);
background-color: #FFFFFE;
color: #252525;
}
.button:active, .button.active {
text-decoration: underline;
}
.grid-container {
display: inline-flex;
flex-wrap: wrap;
justify-content: flex-start;
align-items: flex-start;
min-width: 0;
min-height: 0;
white-space: pre-wrap;
}
.grid-item {
color: black;
width: 150px;
font-size: 11px;
line-height: 24px;
text-align: left;
min-width: 0;
min-height: 0;
white-space: pre-wrap;
padding-right: 12px; /* A little more than two spaces, to look good in IE8 where flex-justify does nothing */
}
.link {
display: inline;
background: none;
border: none;
padding: 7px 14px;
color: black;
text-decoration: none;
cursor: pointer;
font-size: 13px;
margin: 2px 2px;
}
.dark .link {
color: #abc6ec;
}
.link:hover {
text-decoration: underline;
}
</style>
</head>
<body>
<ul id="menu" class="button-container"></ul>
<div id="statcontent"></div>
<script>
// Polyfills and compatibility ------------------------------------------------
var decoder = decodeURIComponent || unescape;
var addEventListenerKey = (document.addEventListener ? 'addEventListener' : 'attachEvent'); // IE8 handling for Wine users
var textContentKey = (typeof document.body.textContent != 'undefined') ? 'textContent' : 'innerText';
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, '');
};
}
// Browser passthrough code ---------------------------------------------------
if (window.location) {
var anti_spam = []; // wow I wish I could use e.repeat but IE is dumb and doesn't have it.
document[addEventListenerKey]("keydown", function(e) {
if(e.target && (e.target.localName == "input" || e.target.localName == "textarea"))
return;
if(e.defaultPrevented)
return; // do e.preventDefault() to prevent this behavior.
if(e.which) {
if(!anti_spam[e.which]) {
anti_spam[e.which] = true;
var href = "?__keydown=" + e.which;
if(e.ctrlKey === false) href += "&ctrlKey=0"
else if(e.ctrlKey === true) href += "&ctrlKey=1"
window.location.href = href;
}
}
});
document[addEventListenerKey]("keyup", function(e) {
if(e.target && (e.target.localName == "input" || e.target.localName == "textarea"))
return;
if(e.defaultPrevented)
return;
if(e.which) {
anti_spam[e.which] = false;
var href = "?__keyup=" + e.which;
if(e.ctrlKey === false) href += "&ctrlKey=0"
else if(e.ctrlKey === true) href += "&ctrlKey=1"
window.location.href = href;
}
});
}
/* document.addEventListener("mousedown", function(e){
var shiftPressed=0;
var evt = e?e:window.event;
shiftPressed=evt.shiftKey;
if (shiftPressed) {
return false;
}
return true;
}); */
// 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 inner = "";
var tickets = [];
var sqdl2 = [];
var permanent_tabs = []; // tabs that won't be cleared by wipes
var turfcontents = [];
var turfname = "";
var menu = document.querySelector('#menu');
function createStatusTab(name) {
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)};
B.id = name;
B[textContentKey] = name;
B.className = "button";
//ORDERING ALPHABETICALLY
B.style.order = name.charCodeAt(0);
if(name == "Status" || name == "MC") {
if(name == "Status")
B.style.order = 1;
else
B.style.order = 2;
}
//END ORDERING
menu.appendChild(B);
}
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));
if(document.getElementById(name)) // repeat for duplicates
removeStatusTab(name);
}
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))
removeStatusTab(menu.children[i].id);
}
function add_verb(v) {
var to_add = JSON.parse(v);
var cat = "";
cat = to_add[0];
if(verb_tabs.includes(cat)){ // we have the category already
verbs.push(to_add); // add it to verb list and we done
} else if(cat.trim() != "") { // we don't have the category
verb_tabs.push(cat);
verbs.push(to_add); // add verb
createStatusTab(cat); // create the category
}
if(current_tab == cat) {
draw_verbs(cat); // redraw if we added a verb to the tab we're currently in
}
}
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]);
}
//checkStatusTab(); // removes any empty status tabs
}
function verbs_cat_check(cat) {
var verbs_in_cat = 0;
var verbcat = "";
if(!verb_tabs.includes(cat)){
removeStatusTab(cat);
return;
}
for(var v = 0; v < verbs.length; v++){
var part = verbs[v];
verbcat = part[0];
if(verbcat != cat || verbcat.trim() == ""){
continue;
}
else{
verbs_in_cat = 1;
break; // we only need one
}
}
if(verbs_in_cat != 1) {
removeStatusTab(cat);
if(current_tab == cat)
tab_change("Status");
}
}
function wipe_verbs() {
verbs = [["", ""]];
verb_tabs = [];
checkStatusTab(); // remove all empty verb tabs
}
function add_verb_list(v) {
var to_add = JSON.parse(v); // 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(verb_tabs.includes(part[0])){
verbs.push(part);
if(current_tab == part[0]) {
draw_verbs(part[0]); // redraw if we added a verb to the tab we're currently in
}
} else if(part[0]) {
verb_tabs.push(part[0]);
verbs.push(part);
createStatusTab(part[0]);
}
}
}
function remove_verb_list(v) {
var to_remove = JSON.parse(v);
for(var i = 0; i < to_remove.length; i++) {
remove_verb(to_remove[i]);
}
check_verbs();
verbs.sort();
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)
function init_verbs(c, v) {
wipe_verbs(); // remove all verb categories so we can replace them
checkStatusTab(); // remove all status tabs
verb_tabs = JSON.parse(c);
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(v) {
verbs = JSON.parse(v);
verbs.sort(); // sort them
if(do_update) {
draw_verbs(current_tab);
}
}
}
function update(global_data, ping_entry, other_entries) {
status_tab_parts = [ping_entry];
var parsed = JSON.parse(global_data);
for(var i = 0; i < parsed.length; i++) if(parsed[i] != null) status_tab_parts.push(parsed[i]);
parsed = JSON.parse(other_entries);
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();
}
function update_mc(global_mc_data, coords_entry, ht) {
mc_tab_parts = JSON.parse(global_mc_data);
mc_tab_parts.splice(0,0,["Location:",coords_entry]);
href_token = ht;
if(!verb_tabs.includes("MC"))
verb_tabs.push("MC");
createStatusTab("MC");
if(current_tab == "MC")
draw_mc();
}
function remove_mc() {
removeStatusTab("MC");
if(current_tab == "MC")
tab_change("Status");
}
function remove_spells() {
for(var s = 0; s < spell_tabs.length; s++){
removeStatusTab(spell_tabs[s]);
}
}
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);
}
}
}
function check_spells() {
for(var v = 0; v < spell_tabs.length; v++)
spell_cat_check(spell_tabs[v]);
}
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 update_spells(t, s) {
spell_tabs = JSON.parse(t);
var do_update = false;
if(spell_tabs.includes(current_tab)) {
do_update = true;
}
init_spells();
if(s) {
spells = JSON.parse(s);
if(do_update) {
draw_spells(current_tab);
}
} else {
remove_spells();
}
}
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;
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(tab == "SQDL2") {
draw_sqdl2();
}else if(tab == turfname) {
draw_listedturf();
} else {
var statcontentdiv = document.getElementById("statcontent");
statcontentdiv[textContentKey] = "loading...";
}
window.location.href = "byond://winset?statbrowser.is-visible=true";
}
function draw_debug() {
var statcontentdiv = document.getElementById("statcontent");
statcontentdiv[textContentKey] = "";
var wipeverbstabs = document.createElement("div");
var link = document.createElement("a");
link.onclick = function() {wipe_verbs()};
link[textContentKey] = "Wipe All Verbs";
wipeverbstabs.appendChild(link);
document.getElementById("statcontent").appendChild(wipeverbstabs);
var text = document.createElement("div");
text[textContentKey] = "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];
var tr = document.createElement("tr");
var td1 = document.createElement("td");
td1[textContentKey] = part;
var a = document.createElement("a");
a.onclick = function (part) {
return function() {removeStatusTab(part)};
}(part);
a[textContentKey] = " Delete Tab " + part;
td1.appendChild(a);
tr.appendChild(td1);
table1.appendChild(tr);
}
document.getElementById("statcontent").appendChild(table1);
var header2 = document.createElement("div");
header2[textContentKey] = "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[textContentKey] = part2[0];
var tdd2 = document.createElement("td");
tdd2[textContentKey] = part2[1];
trr.appendChild(tdd1);
trr.appendChild(tdd2);
table2.appendChild(trr);
}
document.getElementById("statcontent").appendChild(table2);
var text3 = document.createElement("div");
text3[textContentKey] = "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[textContentKey] = part3;
trrr.appendChild(tddd1);
table3.appendChild(trrr);
}
document.getElementById("statcontent").appendChild(table3);
}
function draw_status() {
var statcontentdiv = document.getElementById("statcontent");
if(!document.getElementById("Status")) {
createStatusTab("Status");
current_tab = "Status";
}
statcontentdiv[textContentKey] = inner;
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[textContentKey] = status_tab_parts[i];
document.getElementById("statcontent").appendChild(div);
}
}
if(verb_tabs.length == 0 || !verbs)
{
window.location.href = "byond://winset?command=Fix-Stat-Panel";
}
}
function draw_mc() {
var statcontentdiv = document.getElementById("statcontent");
statcontentdiv[textContentKey] = "";
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[textContentKey] = 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[textContentKey] = part[1];
td2.appendChild(a);
} else {
td2[textContentKey] = part[1];
}
tr.appendChild(td1);
tr.appendChild(td2);
table.appendChild(tr);
}
document.getElementById("statcontent").appendChild(table);
}
function update_tickets(T){
tickets = JSON.parse(T);
if(!verb_tabs.includes("Tickets")) {
verb_tabs.push("Tickets");
addPermanentTab("Tickets");
}
if(current_tab == "Tickets")
draw_tickets();
}
function update_sqdl2(S) {
sqdl2 = JSON.parse(S);
if(sqdl2.length > 0 && !verb_tabs.includes("SQDL2")) {
verb_tabs.push("SQDL2");
addPermanentTab("SQDL2");
}
if(current_tab == "SQDL2")
draw_sqdl2();
}
function remove_sqdl2() {
if(sqdl2) {
sqdl2 = [];
removePermanentTab("SQDL2");
if(current_tab == "SQDL2")
tab_change("Status");
}
checkStatusTab();
}
function remove_tickets() {
if(tickets) {
tickets = [];
removePermanentTab("Tickets");
if(current_tab == "Tickets")
tab_change("Status");
}
checkStatusTab();
}
// removes MC, Tickets and MC tabs.
function remove_admin_tabs() {
remove_mc();
remove_tickets();
remove_sqdl2();
}
function create_listedturf(TN) {
remove_listedturf(); // remove the last one if we had one
turfname = JSON.parse(TN);
addPermanentTab(turfname);
tab_change(turfname);
}
function update_listedturf(TC) {
turfcontents = JSON.parse(TC);
if(current_tab == turfname)
draw_listedturf();
}
function draw_listedturf() {
var statcontentdiv = document.getElementById("statcontent");
statcontentdiv[textContentKey] = "";
var table = document.createElement("table");
for(var i = 0; i < turfcontents.length; i++) {
var part = turfcontents[i];
if(part[2]) {
var img = document.createElement("img");
img.src = part[2];
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] + ";statpanel_item_click=1";
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[textContentKey] = 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 draw_sqdl2(){
var statcontentdiv = document.getElementById("statcontent");
statcontentdiv[textContentKey] = "";
var table = document.createElement("table");
for(var i = 0; i < sqdl2.length; i++) {
var part = sqdl2[i];
var tr = document.createElement("tr");
var td1 = document.createElement("td");
td1[textContentKey] = part[0];
var td2 = document.createElement("td");
if(part[2]) {
var a = document.createElement("a");
a.href = "?src=" + part[2] + ";statpanel_item_click=1";
a[textContentKey] = part[1];
td2.appendChild(a);
} else {
td2[textContentKey] = part[1];
}
tr.appendChild(td1);
tr.appendChild(td2);
table.appendChild(tr);
}
document.getElementById("statcontent").appendChild(table);
}
function draw_tickets() {
var statcontentdiv = document.getElementById("statcontent");
statcontentdiv[textContentKey] = "";
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[textContentKey] = 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=1;action=ticket" ;
a[textContentKey] = part[1];
td2.appendChild(a);
} else if(part[3]){
var a = document.createElement("a");
a.href = "?src=" + part[3] + ";statpanel_item_click=1";
a[textContentKey] = part[1];
td2.appendChild(a);
} else {
td2[textContentKey] = part[1];
}
tr.appendChild(td1);
tr.appendChild(td2);
table.appendChild(tr);
}
document.getElementById("statcontent").appendChild(table);
}
function draw_spells(cat) {
var statcontentdiv = document.getElementById("statcontent");
statcontentdiv[textContentKey] = "";
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[textContentKey] = part[1];
var td2 = document.createElement("td");
if(part[3]) {
var a = document.createElement("a");
a.href = "?src=" + part[3] + ";statpanel_item_click=1";
a[textContentKey] = part[2];
td2.appendChild(a);
} else {
td2[textContentKey] = part[2];
}
tr.appendChild(td1);
tr.appendChild(td2);
table.appendChild(tr);
}
document.getElementById("statcontent").appendChild(table);
}
function draw_verbs(cat){
var statcontentdiv = document.getElementById("statcontent");
statcontentdiv[textContentKey] = "";
var table = document.createElement("newdiv");
table.className = "grid-container";
var command = ""; // typecast name to string
verbs.sort();
verbs.reverse(); // sort verbs backwards before we draw
for(var i = verbs.length - 1; i >= 0; i--) {
var part = verbs[i]; // should be a list containing category and command
if(!part[1]) continue;
if(part[0] != cat){
continue;
}
if(part[0].trim() == ""){
verbs.splice(i, 1);
continue;
}
command = part[1];
var a = document.createElement("a");
a.href = "byond://winset?command=" + command.replace(/\s/g, "-");
a[textContentKey] = command;
a.className = "grid-item";
table.appendChild(a);
}
document.getElementById("statcontent").appendChild(table);
}
function set_theme(which) {
if (which == "light") {
document.body.className = "";
set_style_sheet("browserOutput_white");
} else if (which == "dark") {
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);
}
document[addEventListenerKey]("click", function(e) {
window.location.href = "byond://winset?map.focus=true";
});
if(!current_tab) {
addPermanentTab("Status");
tab_change("Status");
}
function create_debug(){
if(!document.getElementById("Debug Stat Panel")) {
addPermanentTab("Debug Stat Panel");
} else {
removePermanentTab("Debug Stat Panel");
}
}
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 '';
}
</script>
</body>
</html>
+15 -16
View File
@@ -2,21 +2,21 @@ macro "default"
menu "menu"
elem
elem
name = "&File"
command = ""
saved-params = "is-checked"
elem
elem
name = "&Quick screenshot\tF2"
command = ".screenshot auto"
category = "&File"
saved-params = "is-checked"
elem
elem
name = "&Save screenshot as...\tShift+F2"
command = ".screenshot"
category = "&File"
saved-params = "is-checked"
elem
elem
name = ""
command = ""
category = "&File"
@@ -26,26 +26,27 @@ menu "menu"
command = ".reconnect"
category = "&File"
saved-params = "is-checked"
elem
elem
name = "&Quit\tAlt-F4"
command = ".quit"
category = "&File"
saved-params = "is-checked"
elem
elem
name = "&Help"
command = ""
saved-params = "is-checked"
elem
elem
name = "&Admin Help\tF1"
command = "adminhelp"
category = "&Help"
saved-params = "is-checked"
elem
elem
name = "&Hotkeys"
command = "hotkeys-help"
category = "&Help"
saved-params = "is-checked"
window "mainwindow"
elem "mainwindow"
type = MAIN
@@ -75,7 +76,6 @@ window "mainwindow"
anchor1 = none
anchor2 = none
is-visible = false
auto-format = false
saved-params = ""
elem "tooltip"
type = BROWSER
@@ -105,7 +105,8 @@ window "mapwindow"
font-size = 7
text-color = none
is-default = true
style=".center { text-align: center; } .maptext { font-family: 'Small Fonts'; font-size: 7px; -dm-text-outline: 1px black; color: white; line-height: 1.1; } .command_headset { font-weight: bold; font-size: 8px; } .small { font-size: 6px; } .big { font-size: 8px; } .reallybig { font-size: 8px; } .extremelybig { font-size: 8px; } .greentext { color: #00FF00; font-size: 7px; } .redtext { color: #FF0000; font-size: 7px; } .clown { color: #FF69Bf; font-size: 7px; font-weight: bold; } .his_grace { color: #15D512; } .hypnophrase { color: #0d0d0d; font-weight: bold; } .yell { font-weight: bold; } .italics { font-size: 6px; }"
saved-params = "zoom;letterbox;zoom-mode"
style = ".center { text-align: center; } .maptext { font-family: 'Small Fonts'; font-size: 7px; -dm-text-outline: 1px black; color: white; line-height: 1.1; } .command_headset { font-weight: bold;\tfont-size: 8px; } .small { font-size: 6px; } .big { font-size: 8px; } .reallybig { font-size: 8px; } .extremelybig { font-size: 8px; } .greentext { color: #00FF00; font-size: 7px; } .redtext { color: #FF0000; font-size: 7px; } .clown { color: #FF69Bf; font-size: 7px; font-weight: bold; } .his_grace { color: #15D512; } .hypnophrase { color: #0d0d0d; font-weight: bold; } .yell { font-weight: bold; } .italics { font-size: 6px; }"
window "infowindow"
elem "infowindow"
@@ -221,7 +222,6 @@ window "outputwindow"
is-visible = false
is-disabled = true
saved-params = ""
auto-format = false
elem "output"
type = OUTPUT
pos = 0,0
@@ -238,7 +238,6 @@ window "popupwindow"
size = 120x120
anchor1 = none
anchor2 = none
background-color = none
is-visible = false
saved-params = "pos;size;is-minimized;is-maximized"
statusbar = false
@@ -273,18 +272,18 @@ window "preferences_window"
window "statwindow"
elem "statwindow"
type = MAIN
pos = 281,0
pos = 372,0
size = 640x480
anchor1 = none
anchor2 = none
saved-params = "pos;size;is-minimized;is-maximized"
is-pane = true
elem "stat"
type = INFO
elem "statbrowser"
type = BROWSER
pos = 0,0
size = 640x480
anchor1 = 0,0
anchor2 = 100,100
is-default = true
is-visible = false
saved-params = ""
@@ -7,7 +7,7 @@
if (/client/proc/mentor_unfollow in verbs)
mentor_unfollow()
GLOB.mentors -= src
verbs += /client/proc/cmd_mentor_rementor
add_verb(src, /client/proc/cmd_mentor_rementor)
/client/proc/cmd_mentor_rementor()
set category = "Mentor"
@@ -16,4 +16,4 @@
return
add_mentor_verbs()
GLOB.mentors += src
verbs -= /client/proc/cmd_mentor_rementor
remove_verb(src, /client/proc/cmd_mentor_rementor)
@@ -5,7 +5,7 @@
if(!isobserver(usr))
mentor_datum.following = M
usr.reset_perspective(M)
verbs += /client/proc/mentor_unfollow
add_verb(usr, /client/proc/mentor_unfollow)
to_chat(usr, "<span class='info'>Click the <a href='?_src_=mentor;mentor_unfollow=[REF(M)];[MentorHrefToken(TRUE)]'>\"Stop Following\"</a> button here or in the Mentor tab to stop following [key_name(M)].</span>")
orbiting = FALSE
else
@@ -22,7 +22,7 @@
if(!is_mentor())
return
usr.reset_perspective()
verbs -= /client/proc/mentor_unfollow
remove_verb(usr, /client/proc/mentor_unfollow)
to_chat(GLOB.admins, "<span class='mentor'><span class='prefix'>MENTOR:</span> <EM>[key_name(usr)]</EM> is no longer following <EM>[key_name(mentor_datum.following)].</span>")
log_mentor("[key_name(usr)] stopped following [key_name(mentor_datum.following)].")
mentor_datum.following = null
mentor_datum.following = null
@@ -7,7 +7,7 @@ GLOBAL_PROTECT(mentor_verbs)
/client/proc/add_mentor_verbs()
if(mentor_datum)
verbs += GLOB.mentor_verbs
add_verb(src, GLOB.mentor_verbs)
/client/proc/remove_mentor_verbs()
verbs -= GLOB.mentor_verbs
remove_verb(src, GLOB.mentor_verbs)
@@ -3,12 +3,12 @@
set name = "Mentorhelp"
//clean the input msg
if(!msg) return
if(!msg)
return
//remove out mentorhelp verb temporarily to prevent spamming of mentors.
verbs -= /client/verb/mentorhelp
spawn(300)
verbs += /client/verb/mentorhelp // 30 second cool-down for mentorhelp
remove_verb(src, /client/verb/mentorhelp)
addtimer(CALLBACK(GLOBAL_PROC, /proc/add_verb, src, /client/verb/mentorhelp), 30 SECONDS)
msg = sanitize(copytext_char(msg, 1, MAX_MESSAGE_LEN))
if(!msg || !mob)
@@ -95,4 +95,4 @@
if(include_follow)
. += " (<a href='?_src_=mentor;mentor_follow=[REF(M)];[MentorHrefToken(TRUE)]'>F</a>)"
return .
return .
+4 -1
View File
@@ -188,6 +188,7 @@
#include "code\__HELPERS\typelists.dm"
#include "code\__HELPERS\unsorted.dm"
#include "code\__HELPERS\vector.dm"
#include "code\__HELPERS\verbs.dm"
#include "code\__HELPERS\view.dm"
#include "code\__HELPERS\sorts\__main.dm"
#include "code\__HELPERS\sorts\InsertSort.dm"
@@ -337,6 +338,7 @@
#include "code\controllers\subsystem\shuttle.dm"
#include "code\controllers\subsystem\sounds.dm"
#include "code\controllers\subsystem\spacedrift.dm"
#include "code\controllers\subsystem\statpanel.dm"
#include "code\controllers\subsystem\stickyban.dm"
#include "code\controllers\subsystem\sun.dm"
#include "code\controllers\subsystem\tgui.dm"
@@ -3423,6 +3425,8 @@
#include "code\modules\surgery\organs\tails.dm"
#include "code\modules\surgery\organs\tongue.dm"
#include "code\modules\surgery\organs\vocal_cords.dm"
#include "code\modules\tgchat\message.dm"
#include "code\modules\tgchat\to_chat.dm"
#include "code\modules\tgs\includes.dm"
#include "code\modules\tgui\external.dm"
#include "code\modules\tgui\states.dm"
@@ -3449,7 +3453,6 @@
#include "code\modules\tgui_panel\external.dm"
#include "code\modules\tgui_panel\telemetry.dm"
#include "code\modules\tgui_panel\tgui_panel.dm"
#include "code\modules\tgui_panel\to_chat.dm"
#include "code\modules\tooltip\tooltip.dm"
#include "code\modules\unit_tests\_unit_tests.dm"
#include "code\modules\uplink\uplink_devices.dm"
+16
View File
@@ -1,7 +1,23 @@
## NPM garbage
node_modules
*.log
package-lock.json
## Yarn stuff
/.pnp.*
/.yarn/*
!/.yarn/releases
!/.yarn/plugins
!/.yarn/sdks
!/.yarn/versions
## Build artifacts
/public/.tmp/**/*
/public/**/*.hot-update.*
/public/**/*.map
## Previously ignored locations that are kept to avoid confusing git
## while transitioning to a new project structure.
/packages/tgui/public/.tmp/**/*
/packages/tgui/public/**/*.hot-update.*
/packages/tgui/public/**/*.map

Some files were not shown because too many files have changed in this diff Show More