Merge branch 'master' of https://github.com/Citadel-Station-13/Citadel-Station-13 into cache-locality-experiments

This commit is contained in:
Putnam
2020-09-21 03:31:35 -07:00
292 changed files with 17020 additions and 10519 deletions
+1 -1
View File
@@ -1,6 +1,6 @@
// Defines for managed input/keybinding system.
/// Max length of a keypress command before it's considered to be a forged packet/bogus command
#define MAX_KEYPRESS_COMMANDLENGTH 32
#define MAX_KEYPRESS_COMMANDLENGTH 64
/// Maximum keys that can be bound to one button
#define MAX_COMMANDS_PER_KEY 5
/// Maximum keys per keybind
+6
View File
@@ -246,6 +246,8 @@
#define COMPONENT_BLOCK_SWAP 1
#define COMSIG_PROCESS_BORGCHARGER_OCCUPANT "living_charge"
///from base of mob/AltClickOn(): (atom/A)
#define COMSIG_MOB_ALTCLICKON "mob_altclickon"
// /client signals
#define COMSIG_MOB_CLIENT_LOGIN "mob_client_login" //sent when a mob/login() finishes: (client)
@@ -290,6 +292,10 @@
#define COMPONENT_INTERRUPT_LIFE_BIOLOGICAL 1 // interrupt biological processes
#define COMPONENT_INTERRUPT_LIFE_PHYSICAL 2 // interrupt physical handling
#define COMSIG_LIVING_BIOLOGICAL_LIFE "biological_life" //from base of mob/living/BiologicalLife() (seconds, times_fired)
#define COMSIG_LIVING_PHYSICAL_LIFE "physical_life" //from base of mob/living/PhysicalLife() (seconds, times_fired)
// /mob/living/carbon physiology signals
#define COMSIG_CARBON_GAIN_WOUND "carbon_gain_wound" //from /datum/wound/proc/apply_wound() (/mob/living/carbon/C, /datum/wound/W, /obj/item/bodypart/L)
#define COMSIG_CARBON_LOSE_WOUND "carbon_lose_wound" //from /datum/wound/proc/remove_wound() (/mob/living/carbon/C, /datum/wound/W, /obj/item/bodypart/L)
+1
View File
@@ -12,6 +12,7 @@
#define TOXIC (1<<11)
#define PINEAPPLE (1<<12)
#define BREAKFAST (1<<13)
#define ANTITOXIC (1<<14)
#define DRINK_NICE 1
#define DRINK_GOOD 2
+13
View File
@@ -54,3 +54,16 @@
//donator items
#define LOADOUT_CATEGORY_DONATOR "Donator"
//how many prosthetics can we have
#define MAXIMUM_LOADOUT_PROSTHETICS 2
//what limbs can be amputated or be prosthetic
#define LOADOUT_ALLOWED_LIMB_TARGETS list(BODY_ZONE_L_ARM,BODY_ZONE_R_ARM,BODY_ZONE_L_LEG,BODY_ZONE_R_LEG)
//options for modifiying limbs
#define LOADOUT_LIMB_NORMAL "Normal"
#define LOADOUT_LIMB_PROSTHETIC "Prosthetic"
#define LOADOUT_LIMB_AMPUTATED "Amputated"
#define LOADOUT_LIMBS list(LOADOUT_LIMB_NORMAL,LOADOUT_LIMB_PROSTHETIC,LOADOUT_LIMB_AMPUTATED) //you can amputate your legs/arms though
+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
+3 -1
View File
@@ -51,7 +51,8 @@
#define INIT_ORDER_FAIL2TOPIC 99
#define INIT_ORDER_TITLE 98
#define INIT_ORDER_GARBAGE 95
#define INIT_ORDER_DBCORE 93
#define INIT_ORDER_DBCORE 94
#define INIT_ORDER_STATPANELS 93
#define INIT_ORDER_BLACKBOX 92
#define INIT_ORDER_SERVER_MAINT 91
#define INIT_ORDER_INPUT 90
@@ -86,6 +87,7 @@
#define INIT_ORDER_MINOR_MAPPING -40
#define INIT_ORDER_PATH -50
#define INIT_ORDER_PERSISTENCE -95
#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
@@ -205,18 +205,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")
+3 -2
View File
@@ -279,7 +279,8 @@ GLOBAL_LIST_INIT(unlocked_mutant_parts, list("horns", "insect_fluff"))
//parts in either of the above two lists that require a second option that allows them to be coloured
GLOBAL_LIST_INIT(colored_mutant_parts, list("insect_wings" = "wings_color", "deco_wings" = "wings_color", "horns" = "horns_color"))
//species ids that have greyscale sprites
//body ids that have greyscale sprites
GLOBAL_LIST_INIT(greyscale_limb_types, list("human","moth","lizard","pod","plant","jelly","slime","golem","lum","stargazer","mush","ethereal","snail","c_golem","b_golem","mammal","xeno","ipc","insect","synthliz","avian","aquatic"))
//species ids that need snowflake coloring applied
//body ids that have prosthetic sprites
GLOBAL_LIST_INIT(prosthetic_limb_types, list("xion","bishop","cybersolutions","grayson","hephaestus","nanotrasen","talon"))
+2 -2
View File
@@ -112,8 +112,8 @@
/mob/living/silicon/ai/CtrlClickOn(var/atom/A)
A.AICtrlClick(src)
/mob/living/silicon/ai/AltClickOn(var/atom/A)
if(!A.AIAltClick(src))
altclick_listed_turf(A)
A.AIAltClick(src)
/*
The following criminally helpful code is just the previous code cleaned up;
+17 -13
View File
@@ -319,20 +319,13 @@
return ..()
/*
Alt click
Unused except for AI
Used as an alternate way to interact with things.
*/
/mob/proc/AltClickOn(atom/A)
if(!A.AltClick(src))
altclick_listed_turf(A)
/mob/proc/altclick_listed_turf(atom/A)
var/turf/T = get_turf(A)
if(T == A.loc || T == A)
if(T == listed_turf)
listed_turf = null
else if(TurfAdjacent(T))
listed_turf = T
client.statpanel = T.name
. = SEND_SIGNAL(src, COMSIG_MOB_ALTCLICKON, A)
if(. & COMSIG_MOB_CANCEL_CLICKON)
return
A.AltClick(src)
/mob/living/carbon/AltClickOn(atom/A)
if(!stat && mind && iscarbon(A) && A != src)
@@ -344,7 +337,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)
+1 -2
View File
@@ -98,8 +98,7 @@
/mob/living/silicon/robot/CtrlClickOn(atom/A)
A.BorgCtrlClick(src)
/mob/living/silicon/robot/AltClickOn(atom/A)
if(!A.BorgAltClick(src))
altclick_listed_turf(A)
A.BorgAltClick(src)
/atom/proc/BorgCtrlShiftClick(mob/living/silicon/robot/user) //forward to human click if not overridden
CtrlShiftClick(user)
+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 -1
View File
@@ -31,7 +31,7 @@
ShiftClickOn(A)
return
if(modifiers["alt"])
altclick_listed_turf(A)
AltClickNoInteract(src, A)
return
if(modifiers["ctrl"])
CtrlClickOn(A)
@@ -197,10 +197,9 @@
var/list/banned_edits = list(NAMEOF(src, entries_by_type), NAMEOF(src, entries), NAMEOF(src, directory))
return !(var_name in banned_edits) && ..()
/datum/controller/configuration/stat_entry()
if(!statclick)
statclick = new/obj/effect/statclick/debug(null, "Edit", src)
stat("[name]:", statclick)
/datum/controller/configuration/stat_entry(msg)
msg = "Edit"
return msg
/// Your typical GET but returns a config.
/datum/controller/configuration/proc/GetEntryDatum(entry_type)
+1 -1
View File
@@ -16,4 +16,4 @@
/datum/controller/proc/Recover()
/datum/controller/proc/stat_entry()
/datum/controller/proc/stat_entry(msg)
+3 -5
View File
@@ -95,8 +95,6 @@ GLOBAL_REAL(Failsafe, /datum/controller/failsafe)
/datum/controller/failsafe/proc/defcon_pretty()
return defcon
/datum/controller/failsafe/stat_entry()
if(!statclick)
statclick = new/obj/effect/statclick/debug(null, "Initializing...", src)
stat("Failsafe Controller:", statclick.update("Defcon: [defcon_pretty()] (Interval: [Failsafe.processing_interval] | Iteration: [Failsafe.master_iteration])"))
/datum/controller/failsafe/stat_entry(msg)
msg = "Defcon: [defcon_pretty()] (Interval: [Failsafe.processing_interval] | Iteration: [Failsafe.master_iteration])"
return msg
+3 -5
View File
@@ -24,11 +24,9 @@ GLOBAL_REAL(GLOB, /datum/controller/global_vars)
//fuck off kevinz
return QDEL_HINT_IWILLGC
/datum/controller/global_vars/stat_entry()
if(!statclick)
statclick = new/obj/effect/statclick/debug(null, "Initializing...", src)
stat("Globals:", statclick.update("Edit"))
/datum/controller/global_vars/stat_entry(msg)
msg = "Edit"
return msg
/datum/controller/global_vars/vv_edit_var(var_name, var_value)
if(gvars_datum_protected_varlist[var_name])
+3 -6
View File
@@ -615,13 +615,10 @@ GLOBAL_REAL(Master, /datum/controller/master) = new
skip_ticks = 1
/datum/controller/master/stat_entry()
if(!statclick)
statclick = new/obj/effect/statclick/debug(null, "Initializing...", src)
/datum/controller/master/stat_entry(msg)
msg = "(TickRate:[Master.processing]) (Iteration:[Master.iteration]) (TickLimit: [round(Master.current_ticklimit, 0.1)])"
return msg
stat("Byond:", "(FPS:[world.fps]) (TickCount:[world.time/world.tick_lag]) (TickDrift:[round(Master.tickdrift,1)]([round((Master.tickdrift/(world.time/world.tick_lag))*100,0.1)]%)) (Internal Tick Usage: [round(MAPTICK_LAST_INTERNAL_TICK_USAGE,0.1)]%)")
stat("Master Controller:", statclick.update("(TickRate:[Master.processing]) (Iteration:[Master.iteration]) (TickLimit: [round(Master.current_ticklimit, 0.1)])"))
stat("Misc Subsystems", misc_statclick)
/datum/controller/master/StartLoadingMap()
//disallow more than one map to load at once, multithreading it will just cause race conditions
+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
@@ -63,7 +63,7 @@ SUBSYSTEM_DEF(air)
msg += "GA:[get_amt_gas_mixes()]|"
msg += "MG:[get_max_gas_mixes()]|"
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
+10 -11
View File
@@ -1,3 +1,8 @@
/**
* Copyright (c) 2020 Aleksej Komarov
* SPDX-License-Identifier: MIT
*/
SUBSYSTEM_DEF(chat)
name = "Chat"
flags = SS_TICKER
@@ -16,24 +21,18 @@ SUBSYSTEM_DEF(chat)
// Send to tgchat
client.tgui_panel?.window.send_message("chat/message", payload)
// Send to old chat
for(var/msg in payload)
SEND_TEXT(client, msg["text"])
for(var/message in payload)
SEND_TEXT(client, message_to_html(message))
if(MC_TICK_CHECK)
return
/datum/controller/subsystem/chat/proc/queue(target, text, flags)
/datum/controller/subsystem/chat/proc/queue(target, message)
if(islist(target))
for(var/_target in target)
var/client/client = CLIENT_FROM_VAR(_target)
if(client)
LAZYADD(payload_by_client[client], list(list(
"text" = text,
"flags" = flags,
)))
LAZYADD(payload_by_client[client], list(message))
return
var/client/client = CLIENT_FROM_VAR(target)
if(client)
LAZYADD(payload_by_client[client], list(list(
"text" = text,
"flags" = flags,
)))
LAZYADD(payload_by_client[client], list(message))
+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()
-19
View File
@@ -48,25 +48,6 @@ SUBSYSTEM_DEF(persistence)
/datum/controller/subsystem/persistence/proc/LoadSatchels()
var/placed_satchel = 0
var/path
if(fexists("data/npc_saves/SecretSatchels.sav")) //legacy conversion. Will only ever run once.
var/savefile/secret_satchels = new /savefile("data/npc_saves/SecretSatchels.sav")
for(var/map in secret_satchels)
var/json_file = file("data/npc_saves/SecretSatchels[map].json")
var/list/legacy_secret_satchels = splittext(secret_satchels[map],"#")
var/list/satchels = list()
for(var/i=1,i<=legacy_secret_satchels.len,i++)
var/satchel_string = legacy_secret_satchels[i]
var/list/chosen_satchel = splittext(satchel_string,"|")
if(chosen_satchel.len == 3)
var/list/data = list()
data["x"] = text2num(chosen_satchel[1])
data["y"] = text2num(chosen_satchel[2])
data["saved_obj"] = chosen_satchel[3]
satchels += list(data)
var/list/file_data = list()
file_data["data"] = satchels
WRITE_FILE(json_file, json_encode(file_data))
fdel("data/npc_saves/SecretSatchels.sav")
var/json_file = file("data/npc_saves/SecretSatchels[SSmapping.config.map_name].json")
var/list/json = list()
@@ -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)
+1 -1
View File
@@ -12,7 +12,7 @@ SUBSYSTEM_DEF(profiler)
/datum/controller/subsystem/profiler/stat_entry(msg)
msg += "F:[round(fetch_cost,1)]ms"
msg += "|W:[round(write_cost,1)]ms"
..(msg)
return msg
/datum/controller/subsystem/profiler/Initialize()
if(CONFIG_GET(flag/auto_profile))
+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
+119
View File
@@ -0,0 +1,119 @@
SUBSYSTEM_DEF(statpanels)
name = "Stat Panels"
wait = 4
init_order = INIT_ORDER_STATPANELS //Really early so we can debug MC roundstart
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/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"]",
"[SStime_track.stat_time_text]",
"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:", GLOB.stat_entry(), "\ref[GLOB]"),
list("[config]:", config.stat_entry(), "\ref[config]"),
list("Byond:", "(FPS:[world.fps]) (TickCount:[world.time/world.tick_lag]) (TickDrift:[round(Master.tickdrift,1)]([round((Master.tickdrift/(world.time/world.tick_lag))*100,0.1)]%)) (Internal Tick Usage: [round(MAPTICK_LAST_INTERNAL_TICK_USAGE,0.1)]%)"),
list("Master Controller:", Master.stat_entry(), "\ref[Master]"),
list("Failsafe Controller:", Failsafe.stat_entry(), "\ref[Failsafe]"),
list("","")
)
for(var/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_sdql2")
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_sdql2")
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
if(!(REF(target_mob.listed_turf) in cached_images))
target << browse_rsc(getFlatIcon(target_mob.listed_turf, no_anim = TRUE), "[REF(target_mob.listed_turf)].png")
cached_images += REF(target_mob.listed_turf)
turfitems[++turfitems.len] = list("[target_mob.listed_turf]", REF(target_mob.listed_turf), "[REF(target_mob.listed_turf)].png")
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)
+2
View File
@@ -396,6 +396,7 @@ SUBSYSTEM_DEF(ticker)
SSjob.EquipRank(N, player.mind.assigned_role, 0)
if(CONFIG_GET(flag/roundstart_traits) && ishuman(N.new_character))
SSquirks.AssignQuirks(N.new_character, N.client, TRUE, TRUE, SSjob.GetJob(player.mind.assigned_role), FALSE, N)
N.client.prefs.post_copy_to(player)
CHECK_TICK
if(captainless)
for(var/mob/dead/new_player/N in GLOB.player_list)
@@ -416,6 +417,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
@@ -99,7 +99,6 @@ Bonus
*/
/datum/symptom/alkali
name = "Alkali perspiration"
desc = "The virus attaches to sudoriparous glands, synthesizing a chemical that bursts into flames when reacting with water, leading to self-immolation."
stealth = 2
+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))
+10 -1
View File
@@ -61,7 +61,7 @@
A.AddElement(/datum/element/update_icon_updates_onmob)
RegisterSignal(A, COMSIG_ITEM_WORN_OVERLAYS, .proc/apply_worn_overlays)
if(suits_with_helmet_typecache[A.type])
RegisterSignal(A, COMSIG_SUIT_MADE_HELMET, .proc/register_helmet)
RegisterSignal(A, COMSIG_SUIT_MADE_HELMET, .proc/register_helmet) //you better work now you slut
else if(_flags & POLYCHROMIC_ACTION && ismob(A)) //in the event mob update icon procs are ever standarized.
var/datum/action/polychromic/P = new(A)
RegisterSignal(P, COMSIG_ACTION_TRIGGER, .proc/activate_action)
@@ -166,6 +166,15 @@
examine_list += "<span class='notice'>Alt-click to recolor it.</span>"
/datum/element/polychromic/proc/register_helmet(atom/source, obj/item/clothing/head/H)
if(!isitem(H)) //backup in case if it messes up somehow
if(istype(source,/obj/item/clothing/suit/hooded)) //so how come it be like this, where toggleable headslots are named separately (helmet/hood) anyways?
var/obj/item/clothing/suit/hooded/sourcesuit = source
H = sourcesuit.hood
else if(istype(source,/obj/item/clothing/suit/space/hardsuit))
var/obj/item/clothing/suit/space/hardsuit/sourcesuit = source
H = sourcesuit.helmet
else
return
suit_by_helmet[H] = source
helmet_by_suit[source] = H
colors_by_atom[H] = colors_by_atom[source]
+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.
+11
View File
@@ -285,6 +285,17 @@ Unless you know what you're doing, only use the first three numbers. They're in
beauty_modifier = -0.15
texture_layer_icon_state = "runed"
/datum/material/brass
name = "brass"
desc = "Tybel gb-Ratvar"
color = "#917010"
categories = list(MAT_CATEGORY_RIGID = TRUE, MAT_CATEGORY_BASE_RECIPES = TRUE)
strength_modifier = 1.3 // Replicant Alloy is very good for skull beatings..
sheet_type = /obj/item/stack/tile/brass
value_per_unit = 0.75
armor_modifiers = list("melee" = 1.4, "bullet" = 1.4, "laser" = 0, "energy" = 0, "bomb" = 1.4, "bio" = 1.2, "rad" = 1.5, "fire" = 1.5, "acid" = 1.5) //But it has.. a few problems that can't easily be compensated for.
beauty_modifier = 0.3 //It really beats the cold plain plating of the station, doesn't it?
/datum/material/bronze
name = "bronze"
desc = "Clock Cult? Never heard of it."
+2
View File
@@ -132,6 +132,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
@@ -693,6 +694,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)
@@ -204,6 +204,11 @@
mood_change = -1
timeout = 2 MINUTES
/datum/mood_event/plush_bite
description = "<span class='warning'>IT BIT ME!! OW!</span>\n"
mood_change = -3
timeout = 2 MINUTES
//Cursed stuff below
/datum/mood_event/emptypred
+1 -1
View File
@@ -11,7 +11,7 @@
var/lowest_value = 256 * 8
var/text_gain_indication = ""
var/text_lose_indication = ""
var/list/mutable_appearance/visual_indicators = list()
var/list/visual_indicators = list()
var/obj/effect/proc_holder/spell/power
var/layer_used = MUTATIONS_LAYER //which mutation layer to use
var/list/species_allowed = list() //to restrict mutation to only certain species
+16 -49
View File
@@ -211,24 +211,27 @@ GLOBAL_LIST_EMPTY(family_heirlooms)
H.gain_trauma(T, TRAUMA_RESILIENCE_ABSOLUTE)
/datum/quirk/paraplegic/on_spawn()
if(quirk_holder.buckled) // Handle late joins being buckled to arrival shuttle chairs.
quirk_holder.buckled.unbuckle_mob(quirk_holder)
if(quirk_holder.client)
var/modified_limbs = quirk_holder.client.prefs.modified_limbs
if(!(modified_limbs[BODY_ZONE_L_LEG] == LOADOUT_LIMB_AMPUTATED && modified_limbs[BODY_ZONE_R_LEG] == LOADOUT_LIMB_AMPUTATED && !isjellyperson(quirk_holder)))
if(quirk_holder.buckled) // Handle late joins being buckled to arrival shuttle chairs.
quirk_holder.buckled.unbuckle_mob(quirk_holder)
var/turf/T = get_turf(quirk_holder)
var/obj/structure/chair/spawn_chair = locate() in T
var/turf/T = get_turf(quirk_holder)
var/obj/structure/chair/spawn_chair = locate() in T
var/obj/vehicle/ridden/wheelchair/wheels = new(T)
if(spawn_chair) // Makes spawning on the arrivals shuttle more consistent looking
wheels.setDir(spawn_chair.dir)
var/obj/vehicle/ridden/wheelchair/wheels = new(T)
if(spawn_chair) // Makes spawning on the arrivals shuttle more consistent looking
wheels.setDir(spawn_chair.dir)
wheels.buckle_mob(quirk_holder)
wheels.buckle_mob(quirk_holder)
// During the spawning process, they may have dropped what they were holding, due to the paralysis
// So put the things back in their hands.
// During the spawning process, they may have dropped what they were holding, due to the paralysis
// So put the things back in their hands.
for(var/obj/item/I in T)
if(I.fingerprintslast == quirk_holder.ckey)
quirk_holder.put_in_hands(I)
for(var/obj/item/I in T)
if(I.fingerprintslast == quirk_holder.ckey)
quirk_holder.put_in_hands(I)
/datum/quirk/poor_aim
name = "Poor Aim"
@@ -244,42 +247,6 @@ GLOBAL_LIST_EMPTY(family_heirlooms)
mob_trait = TRAIT_PROSOPAGNOSIA
medical_record_text = "Patient suffers from prosopagnosia and cannot recognize faces."
/datum/quirk/prosthetic_limb
name = "Prosthetic Limb"
desc = "An accident caused you to lose one of your limbs. Because of this, you now have a random prosthetic!"
value = -1
var/slot_string = "limb"
/datum/quirk/prosthetic_limb/on_spawn()
var/mob/living/carbon/human/H = quirk_holder
var/limb_slot
if(HAS_TRAIT(H, TRAIT_PARA))//Prevent paraplegic legs being replaced
limb_slot = pick(BODY_ZONE_L_ARM, BODY_ZONE_R_ARM)
else
limb_slot = pick(BODY_ZONE_L_ARM, BODY_ZONE_R_ARM, BODY_ZONE_L_LEG, BODY_ZONE_R_LEG)
var/obj/item/bodypart/old_part = H.get_bodypart(limb_slot)
var/obj/item/bodypart/prosthetic
switch(limb_slot)
if(BODY_ZONE_L_ARM)
prosthetic = new/obj/item/bodypart/l_arm/robot/surplus(quirk_holder)
slot_string = "left arm"
if(BODY_ZONE_R_ARM)
prosthetic = new/obj/item/bodypart/r_arm/robot/surplus(quirk_holder)
slot_string = "right arm"
if(BODY_ZONE_L_LEG)
prosthetic = new/obj/item/bodypart/l_leg/robot/surplus(quirk_holder)
slot_string = "left leg"
if(BODY_ZONE_R_LEG)
prosthetic = new/obj/item/bodypart/r_leg/robot/surplus(quirk_holder)
slot_string = "right leg"
prosthetic.replace_limb(H)
qdel(old_part)
H.regenerate_icons()
/datum/quirk/prosthetic_limb/post_add()
to_chat(quirk_holder, "<span class='boldannounce'>Your [slot_string] has been replaced with a surplus prosthetic. It is fragile and will easily come apart under duress. Additionally, \
you need to use a welding tool and cables to repair it, instead of bruise packs and ointment.</span>")
/datum/quirk/insanity
name = "Reality Dissociation Syndrome"
desc = "You suffer from a severe disorder that causes very vivid hallucinations. Mindbreaker toxin can suppress its effects, and you are immune to mindbreaker's hallucinogenic properties. <b>This is not a license to grief.</b>"
+2 -2
View File
@@ -71,7 +71,7 @@
/datum/wires/airlock/on_pulse(wire)
set waitfor = FALSE
var/obj/machinery/door/airlock/A = holder
if(!A.hasSiliconAccessInArea(usr) && A.isElectrified() && A.shock(usr, 100))
if(usr && !A.hasSiliconAccessInArea(usr) && A.isElectrified() && A.shock(usr, 100))
return FALSE
switch(wire)
if(WIRE_POWER1, WIRE_POWER2) // Pulse to loose power.
@@ -127,7 +127,7 @@
/datum/wires/airlock/on_cut(wire, mend)
var/obj/machinery/door/airlock/A = holder
if(!A.hasSiliconAccessInArea(usr) && A.isElectrified() && A.shock(usr, 100))
if(usr && !A.hasSiliconAccessInArea(usr) && A.isElectrified() && A.shock(usr, 100))
return FALSE
switch(wire)
if(WIRE_POWER1, WIRE_POWER2) // Cut to loose power, repair all to gain power.
+2 -2
View File
@@ -40,7 +40,7 @@
new_ai = select_active_ai(R)
R.notify_ai(DISCONNECT)
if(new_ai && (new_ai != R.connected_ai))
R.connected_ai = new_ai
R.set_connected_ai(new_ai)
if(R.shell)
R.undeploy() //If this borg is an AI shell, disconnect the controlling AI and assign ti to a new AI
R.notify_ai(AI_SHELL)
@@ -69,7 +69,7 @@
R.notify_ai(DISCONNECT)
if(R.shell)
R.undeploy()
R.connected_ai = null
R.set_connected_ai(null)
if(WIRE_LAWSYNC) // Cut the law wire, and the borg will no longer receive law updates from its AI. Repair and it will re-sync.
if(mend)
if(!R.emagged)
+2 -1
View File
@@ -43,6 +43,7 @@ NOTE: there are two lists of areas in the end of this file: centcom and station
outdoors = TRUE
ambientsounds = SPACE
blob_allowed = FALSE //Eating up space doesn't count for victory as a blob.
considered_hull_exterior = TRUE
/area/space/nearstation
icon_state = "space_near"
@@ -1592,4 +1593,4 @@ NOTE: there are two lists of areas in the end of this file: centcom and station
valid_territory = FALSE
outdoors = TRUE
ambientsounds = SPACE
blob_allowed = FALSE //While part of the station, what good will it do you?
blob_allowed = FALSE //While part of the station, what good will it do you?
+3
View File
@@ -34,6 +34,9 @@
/// If megafauna can be spawned by natural random generation
var/megafauna_spawn_allowed = FALSE
/// Considered space for hull shielding
var/considered_hull_exterior = FALSE
var/fire = null
var/atmos = TRUE
var/atmosalm = FALSE
+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)
@@ -178,9 +178,12 @@
table[y1][x1] += 10
if(href_list["same_board"]) //Reset the board... kinda
if(game_status != MINESWEEPER_GAME_PLAYING)
mine_sound = TRUE
game_status = MINESWEEPER_GAME_PLAYING
if(table[y1][x1] >= 10) //If revealed, become unrevealed!
playsound(loc, 'sound/arcade/minesweeper_menuselect.ogg', 50, 0, extrarange = -3, falloff = 10)
if(mine_sound)
playsound(loc, 'sound/arcade/minesweeper_menuselect.ogg', 50, 0, extrarange = -3, falloff = 10)
mine_sound = FALSE
table[y1][x1] -= 10
if(table[y1][x1] > 10 && !reset_board)
safe_squares_revealed += 1
+11
View File
@@ -38,3 +38,14 @@
if(stat & (BROKEN|NOPOWER))
return
drive()
/obj/machinery/mass_driver/pressure_plate
name = "pressure plated mass driver"
var/drive_delay = 10
/obj/machinery/mass_driver/pressure_plate/Crossed(atom/movable/O)
. = ..()
if(isliving(O))
var/mob/living/L = O
to_chat(L, "<span class='warning'>You feel something click beneath you!</span>")
addtimer(CALLBACK(src, .proc/drive), drive_delay)
+1 -1
View File
@@ -100,7 +100,7 @@
// So he can't jump out the gate right away.
R.SetLockdown()
if(masterAI)
R.connected_ai = masterAI
R.set_connected_ai(masterAI)
R.lawsync()
R.lawupdate = 1
addtimer(CALLBACK(src, .proc/unlock_new_robot, R), 50)
@@ -113,8 +113,7 @@
if (loc != user)
return ..()
if(SEND_SIGNAL(src, COMSIG_IS_STORAGE_LOCKED))
ui_interact(user)
return
INVOKE_ASYNC(src, /datum.proc/ui_interact, user)
/obj/item/storage/portable_chem_mixer/attack_self(mob/user)
if(loc == user)
+1 -2
View File
@@ -255,7 +255,7 @@
/obj/item/choice_beacon/box/plushie/generate_display_names()
var/list/plushie_list = list()
//plushie set 1: just subtypes of /obj/item/toy/plush
var/list/plushies_set_one = subtypesof(/obj/item/toy/plush) - list(/obj/item/toy/plush/narplush, /obj/item/toy/plush/awakenedplushie, /obj/item/toy/plush/random_snowflake, /obj/item/toy/plush/random) //don't allow these special ones (you can still get narplush/hugbox)
var/list/plushies_set_one = subtypesof(/obj/item/toy/plush) - list(/obj/item/toy/plush/narplush, /obj/item/toy/plush/awakenedplushie, /obj/item/toy/plush/random_snowflake, /obj/item/toy/plush/plushling, /obj/item/toy/plush/random) //don't allow these special ones (you can still get narplush/hugbox)
for(var/V in plushies_set_one)
var/atom/A = V
plushie_list[initial(A.name)] = A
@@ -272,4 +272,3 @@
icon_state = "skub"
w_class = WEIGHT_CLASS_BULKY
attack_verb = list("skubbed")
+78 -3
View File
@@ -167,7 +167,7 @@
return
log_game("[key_name(user)] activated a hidden grenade in [src].")
grenade.preprime(user, msg = FALSE, volume = 10)
SEND_SIGNAL(user, COMSIG_ADD_MOOD_EVENT,"plushpet", /datum/mood_event/plushpet)
SEND_SIGNAL(user, COMSIG_ADD_MOOD_EVENT,"plushpet", /datum/mood_event/plushpet)
else
to_chat(user, "<span class='notice'>You try to pet [src], but it has no stuffing. Aww...</span>")
SEND_SIGNAL(user, COMSIG_ADD_MOOD_EVENT,"plush_nostuffing", /datum/mood_event/plush_nostuffing)
@@ -754,8 +754,8 @@ GLOBAL_LIST_INIT(valid_plushie_paths, valid_plushie_paths())
attack_verb = list("headbutt", "scritched", "bit")
squeak_override = list('modular_citadel/sound/voice/nya.ogg' = 1)
can_random_spawn = FALSE
/obj/item/toy/plush/hairball
name = "Hairball"
desc = "A bundle of undigested fibers and scales. Yuck."
@@ -765,3 +765,78 @@ GLOBAL_LIST_INIT(valid_plushie_paths, valid_plushie_paths())
squeak_override = list('sound/misc/splort.ogg'=1)
attack_verb = list("sploshed", "splorted", "slushed")
can_random_spawn = FALSE
/obj/item/toy/plush/plushling
name = "peculiar plushie"
desc = "An adorable stuffed toy- wait, did it just move?"
can_random_spawn = FALSE
var/absorb_cooldown = 100 //ticks cooldown between absorbs
var/next_absorb = 0 //When can it absorb another plushie
var/check_interval = 20
var/next_check = 0
//Overrides parent proc
/obj/item/toy/plush/plushling/attack_self(mob/user)
if(!user) //hmmmmm
return
to_chat(user, "<span class='warning'>You try to pet the plushie, but recoil as it bites your hand instead! OW!</span>")
SEND_SIGNAL(user, COMSIG_ADD_MOOD_EVENT,"plush_bite", /datum/mood_event/plush_bite)
var/mob/living/carbon/human/H = user
if(!H)
return //Type safety.
H.apply_damage(5, BRUTE, pick(BODY_ZONE_L_ARM, BODY_ZONE_R_ARM))
addtimer(CALLBACK(H, /mob/living/carbon/human.proc/dropItemToGround, src, TRUE), 1)
/obj/item/toy/plush/plushling/New()
var/initial_state = pick("plushie_lizard", "plushie_snake", "plushie_slime", "fox")
icon_state = initial_state
item_state = initial_state
START_PROCESSING(SSobj, src)
. = ..()
/obj/item/toy/plush/plushling/Destroy()
STOP_PROCESSING(SSobj, src)
. = ..()
/obj/item/toy/plush/plushling/process()
if(world.time < next_absorb || world.time < next_check)
return
next_check = world.time + check_interval
var/obj/item/toy/plush/target
for(var/obj/item/toy/plush/possible_target in loc) //First, it tries to get anything in its same location, be it a tile or a backpack
if(possible_target == src || istype(possible_target, /obj/item/toy/plush/plushling))
continue
target = possible_target
break
if(!target)
if(!isturf(loc))
return
for(var/obj/item/toy/plush/P in oview(1, src)) //If that doesn't work, it hunts for plushies adjacent to its own tile
if(istype(P, /obj/item/toy/plush/plushling)) //These do not hunt their own kind
continue
src.throw_at(P, 1, 2)
visible_message("<span class='danger'>[src] leaps at [P]!</span>")
break
return
if(istype(target, /obj/item/toy/plush/plushling)) //These do not consume their own.
return
next_absorb = world.time + absorb_cooldown
plushie_absorb(target)
/obj/item/toy/plush/plushling/proc/plushie_absorb(obj/item/toy/plush/victim)
if(!victim)
return
visible_message("<span class='warning'>[src] gruesomely mutilliates [victim], leaving nothing more than dust!</span>")
name = victim.name
desc = victim.desc + " Wait, did it just move..?"
icon_state = victim.icon_state
item_state = victim.item_state
squeak_override = victim.squeak_override
attack_verb = victim.attack_verb
new /obj/effect/decal/cleanable/ash(get_turf(victim))
qdel(victim)
/obj/item/toy/plush/plushling/love(obj/item/toy/plush/Kisser, mob/living/user) //You shouldn't have come here, poor plush.
if(!Kisser)
return
plushie_absorb(Kisser)
+5 -5
View File
@@ -281,12 +281,12 @@
O.custom_name = created_name
O.locked = panel_locked
if(!aisync)
lawsync = 0
O.connected_ai = null
lawsync = FALSE
O.set_connected_ai(null)
else
O.notify_ai(NEW_BORG)
if(forced_ai)
O.connected_ai = forced_ai
O.set_connected_ai(forced_ai)
if(!lawsync)
O.lawupdate = 0
if(M.laws.id == DEFAULT_AI_LAWID)
@@ -337,10 +337,10 @@
if(!aisync)
lawsync = FALSE
O.connected_ai = null
O.set_connected_ai(null)
else
if(forced_ai)
O.connected_ai = forced_ai
O.set_connected_ai(forced_ai)
O.notify_ai(AI_SHELL)
if(!lawsync)
O.lawupdate = FALSE
+2 -2
View File
@@ -269,8 +269,8 @@
to_chat(user, "<span class='notice'>[M] is at full health.</span>")
return FALSE
user.visible_message("<span class='green'>[user] applies \the [src] on [M].</span>", "<span class='green'>You apply \the [src] on [M].</span>")
return heal_carbon(M, user, heal_brute, heal_burn)
M.heal_bodypart_damage(heal_brute)
return TRUE
to_chat(user, "<span class='warning'>You can't heal [M] with \the [src]!</span>")
/obj/item/stack/medical/ointment
@@ -636,7 +636,7 @@ GLOBAL_LIST_INIT(brass_recipes, list ( \
null, \
new/datum/stack_recipe("brass flask", /obj/item/reagent_containers/food/drinks/bottle/holyoil/empty), \
new/datum/stack_recipe("brass smith's hammer", /obj/item/melee/smith/hammer/ratvar, 6), \
new/datum/stack_recipe("brass ingot", /obj/item/ingot/bronze/ratvar, 6, time = 100), \
new/datum/stack_recipe("brass ingot", /obj/item/ingot/ratvar, 6, time = 100), \
))
/obj/item/stack/tile/brass
-3
View File
@@ -204,9 +204,6 @@ GLOBAL_DATUM_INIT(acid_overlay, /mutable_appearance, mutable_appearance('icons/e
/obj/proc/acid_processing()
. = 1
if(!(resistance_flags & ACID_PROOF))
for(var/armour_value in armor)
if(armour_value != "acid" && armour_value != "fire")
armor = armor.modifyAllRatings(0 - round(sqrt(acid_level)*0.1))
if(prob(33))
playsound(loc, 'sound/items/welder.ogg', 150, 1)
take_damage(min(1 + round(sqrt(acid_level)*0.3), 300), BURN, "acid", 0)
+1 -1
View File
@@ -138,7 +138,7 @@
if(prob(hardness))
playsound(src, 'sound/effects/meteorimpact.ogg', 100, TRUE)
user.say(pick(";RAAAAAAAARGH!", ";HNNNNNNNNNGGGGGGH!", ";GWAAAAAAAARRRHHH!", "NNNNNNNNGGGGGGGGHH!", ";AAAAAAARRRGH!" ), forced = "hulk")
hulk_recoil(arm, user)
//hulk_recoil(arm, user) // citadel edit - no, hulks are already subject to stamina combat
dismantle_wall(1)
else
+29 -21
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,15 @@ 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
remove_verb(src, GLOB.admin_verbs_hideable)
remove_verb(src, /client/proc/hide_most_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 +328,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 +338,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 +726,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
+2 -2
View File
@@ -199,7 +199,7 @@
borg.notify_ai(DISCONNECT)
if(borg.shell)
borg.undeploy()
borg.connected_ai = newai
borg.set_connected_ai(newai)
borg.notify_ai(TRUE)
message_admins("[key_name_admin(user)] slaved [ADMIN_LOOKUPFLW(borg)] to the AI [ADMIN_LOOKUPFLW(newai)].")
log_admin("[key_name(user)] slaved [key_name(borg)] to the AI [key_name(newai)].")
@@ -207,7 +207,7 @@
borg.notify_ai(DISCONNECT)
if(borg.shell)
borg.undeploy()
borg.connected_ai = null
borg.set_connected_ai(null)
message_admins("[key_name_admin(user)] freed [ADMIN_LOOKUPFLW(borg)] from being slaved to an AI.")
log_admin("[key_name(user)] freed [key_name(borg)] from being slaved to an AI.")
if (borg.lawupdate)
+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!
@@ -138,7 +138,7 @@
if(owner.current.gender == MALE)
if(prob(10)) // Gender override
bloodsucker_reputation = pick("King of the Damned", "Blood King", "Emperor of Blades", "Sinlord", "God-King")
else
else if(owner.current.gender == FEMALE)
if(prob(10)) // Gender override
bloodsucker_reputation = pick("Queen of the Damned", "Blood Queen", "Empress of Blades", "Sinlady", "God-Queen")
@@ -341,10 +341,12 @@
//This handles the application of antag huds/special abilities
/datum/antagonist/bloodsucker/apply_innate_effects(mob/living/mob_override)
RegisterSignal(owner.current,COMSIG_LIVING_BIOLOGICAL_LIFE,.proc/LifeTick)
return
//This handles the removal of antag huds/special abilities
/datum/antagonist/bloodsucker/remove_innate_effects(mob/living/mob_override)
UnregisterSignal(owner.current,COMSIG_LIVING_BIOLOGICAL_LIFE)
return
//Assign default team and creates one for one of a kind team antagonists
@@ -1,7 +1,7 @@
/datum/action/bloodsucker/targeted/brawn
name = "Brawn"//"Cellular Emporium"
name = "Brawn"
desc = "Snap restraints with ease, or deal terrible damage with your bare hands."
button_icon_state = "power_strength"
bloodcost = 10
@@ -107,8 +107,6 @@
if(user_C.handcuffed)
var/obj/O = user_C.get_item_by_slot(SLOT_HANDCUFFED)
if(istype(O))
//user_C.visible_message("<span class='warning'>[user_C] attempts to remove [O]!</span>", \
// "<span class='warning'>You snap [O] like it's nothing!</span>")
user_C.clear_cuffs(O,TRUE)
playsound(get_turf(usr), 'sound/effects/grillehit.ogg', 80, 1, -1)
return TRUE
@@ -128,8 +126,6 @@
if(user_C.legcuffed)
var/obj/O = user_C.get_item_by_slot(SLOT_LEGCUFFED)
if(istype(O))
//user_C.visible_message("<span class='warning'>[user_C] attempts to remove [O]!</span>", \
// "<span class='warning'>You snap [O] like it's nothing!</span>")
user_C.clear_cuffs(O,TRUE)
playsound(get_turf(usr), 'sound/effects/grillehit.ogg', 80, 1, -1)
return TRUE
@@ -165,8 +165,8 @@
// Broadcast Message
if(amSilent)
//if (!iscarbon(target))
// user.visible_message("<span class='notice'>[user] shifts [target] closer to [user.p_their()] mouth.</span>", \
// "<span class='notice'>You secretly slip your fangs into [target]'s flesh.</span>", \
// user.visible_message("<span class='notice'>[user] shifts [target] closer to [user.p_their()] mouth.</span>",
// "<span class='notice'>You secretly slip your fangs into [target]'s flesh.</span>",
// vision_distance = 2, ignored_mobs=target) // Only people who AREN'T the target will notice this action.
//else
var/deadmessage = target.stat == DEAD ? "" : " <i>[target.p_they(TRUE)] looks dazed, and will not remember this.</i>"
@@ -94,6 +94,7 @@
B.decoy_override = FALSE
remove_changeling_powers()
owner.special_role = null
owner.current.hud_used?.lingchemdisplay?.invisibility = INVISIBILITY_ABSTRACT
. = ..()
/datum/antagonist/changeling/proc/remove_clownmut()
@@ -225,6 +226,8 @@
else //not dead? no chem/geneticdamage caps.
chem_charges = min(max(0, chem_charges + chem_recharge_rate - chem_recharge_slowdown), chem_storage)
geneticdamage = max(0, geneticdamage-1)
owner.current.hud_used?.lingchemdisplay?.invisibility = 0
owner.current.hud_used?.lingchemdisplay?.maptext = "<div align='center' valign='middle' style='position:relative; top:0px; left:6px'><font color='#dd66dd'>[round(chem_charges)]</font></div>"
/datum/antagonist/changeling/proc/get_dna(dna_owner)
@@ -357,10 +360,12 @@
B.organ_flags &= ~ORGAN_VITAL
B.decoy_override = TRUE
update_changeling_icons_added()
RegisterSignal(owner.current,COMSIG_LIVING_BIOLOGICAL_LIFE,.proc/regenerate)
return
/datum/antagonist/changeling/remove_innate_effects()
update_changeling_icons_removed()
UnregisterSignal(owner.current,COMSIG_LIVING_BIOLOGICAL_LIFE)
return
@@ -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)
@@ -5,7 +5,7 @@
ShiftClickOn(A)
return
if(modifiers["alt"])
altclick_listed_turf(A)
AltClickNoInteract(src, A)
return
if(ishuman(A))
+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)
@@ -13,7 +13,9 @@ GLOBAL_LIST_INIT(blacklisted_malf_machines, typecacheof(list(
/obj/machinery/syndicatebomb/badmin/clown,
/obj/machinery/syndicatebomb/empty,
/obj/machinery/syndicatebomb/self_destruct,
/obj/machinery/syndicatebomb/training
/obj/machinery/syndicatebomb/training,
/obj/machinery/gravity_generator,
/obj/machinery/gravity_generator/main
)))
//The malf AI action subtype. All malf actions are subtypes of this.
+2 -2
View File
@@ -11,7 +11,7 @@
var/hidden_socks = FALSE
//Mob procs
/mob/living/carbon/human/proc/underwear_toggle()
/mob/living/carbon/human/verb/underwear_toggle()
set name = "Toggle undergarments"
set category = "IC"
@@ -68,7 +68,7 @@
R.reaction(turfing ? target : target.loc, TOUCH, 1, 0)
if(!turfing)
R.trans_to(target, R.total_volume * (spill ? G.fluid_transfer_factor : 1))
G.time_since_last_orgasm = 0
G.last_orgasmed = world.time
R.clear_reagents()
/mob/living/carbon/human/proc/mob_climax_outside(obj/item/organ/genital/G, mb_time = 30) //This is used for forced orgasms and other hands-free climaxes
+7 -17
View File
@@ -16,7 +16,7 @@
var/fluid_efficiency = 1
var/fluid_rate = CUM_RATE
var/fluid_mult = 1
var/time_since_last_orgasm = 500
var/last_orgasmed = 0
var/aroused_state = FALSE //Boolean used in icon_state strings
var/obj/item/organ/genital/linked_organ
var/linked_organ_slot //used for linking an apparatus' organ to its other half on update_link().
@@ -24,10 +24,6 @@
/obj/item/organ/genital/Initialize(mapload, do_update = TRUE)
. = ..()
if(fluid_id)
create_reagents(fluid_max_volume, NONE, NO_REAGENTS_VALUE)
if(CHECK_BITFIELD(genital_flags, GENITAL_FUID_PRODUCTION))
reagents.add_reagent(fluid_id, fluid_max_volume)
if(do_update)
update()
@@ -140,8 +136,6 @@
/obj/item/organ/genital/proc/modify_size(modifier, min = -INFINITY, max = INFINITY)
fluid_max_volume += modifier*2.5
fluid_rate += modifier/10
if(reagents)
reagents.maximum_volume = fluid_max_volume
return
/obj/item/organ/genital/proc/update_size()
@@ -151,18 +145,14 @@
if(!owner || owner.stat == DEAD)
aroused_state = FALSE
/obj/item/organ/genital/on_life()
. = ..()
if(!reagents || !.)
return
reagents.maximum_volume = fluid_max_volume
if(fluid_id && CHECK_BITFIELD(genital_flags, GENITAL_FUID_PRODUCTION))
time_since_last_orgasm++
/obj/item/organ/genital/proc/generate_fluid(datum/reagents/R)
var/amount = clamp(fluid_rate * time_since_last_orgasm * fluid_mult,0,fluid_max_volume)
var/amount = clamp((fluid_rate * ((world.time - last_orgasmed) / SSmobs.wait) * fluid_mult),0,fluid_max_volume)
R.clear_reagents()
R.add_reagent(fluid_id,amount)
R.maximum_volume = fluid_max_volume
if(fluid_id)
R.add_reagent(fluid_id,amount)
else if(linked_organ?.fluid_id)
R.add_reagent(linked_organ.fluid_id,amount)
return TRUE
/obj/item/organ/genital/proc/update_link()
+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
@@ -40,6 +40,9 @@
/datum/gas_reaction/proc/react(datum/gas_mixture/air, atom/location)
return NO_REACTION
/datum/gas_reaction/proc/test()
return list("success" = TRUE)
/datum/gas_reaction/nobliumsupression
priority = INFINITY
name = "Hyper-Noblium Reaction Suppression"
@@ -70,6 +73,8 @@
air.adjust_moles(/datum/gas/water_vapor,-MOLES_GAS_VISIBLE)
. = REACTING
// no test cause it's entirely based on location
//tritium combustion: combustion of oxygen and tritium (treated as hydrocarbons). creates hotspots. exothermic
/datum/gas_reaction/tritfire
priority = -1 //fire should ALWAYS be last, but tritium fires happen before plasma fires
@@ -126,6 +131,18 @@
return cached_results["fire"] ? REACTING : NO_REACTION
/datum/gas_reaction/tritfire/test()
var/datum/gas_mixture/G = new
G.set_moles(/datum/gas/tritium,50)
G.set_moles(/datum/gas/oxygen,50)
G.set_temperature(500)
var/result = G.react()
if(result != REACTING)
return list("success" = FALSE, "message" = "Reaction didn't go at all!")
if(!G.reaction_results["fire"])
return list("success" = FALSE, "message" = "Trit fires aren't setting fire results correctly!")
return ..()
//plasma combustion: combustion of oxygen and plasma (treated as hydrocarbons). creates hotspots. exothermic
/datum/gas_reaction/plasmafire
priority = -2 //fire should ALWAYS be last, but plasma fires happen after tritium fires
@@ -198,6 +215,28 @@
return cached_results["fire"] ? REACTING : NO_REACTION
/datum/gas_reaction/plasmafire/test()
var/datum/gas_mixture/G = new
G.set_moles(/datum/gas/plasma,50)
G.set_moles(/datum/gas/oxygen,50)
G.set_volume(1000)
G.set_temperature(500)
var/result = G.react()
if(result != REACTING)
return list("success" = FALSE, "message" = "Reaction didn't go at all!")
if(!G.reaction_results["fire"])
return list("success" = FALSE, "message" = "Plasma fires aren't setting fire results correctly!")
if(!G.get_moles(/datum/gas/carbon_dioxide))
return list("success" = FALSE, "message" = "Plasma fires aren't making CO2!")
G.clear()
G.set_moles(/datum/gas/plasma,10)
G.set_moles(/datum/gas/oxygen,1000)
G.set_temperature(500)
result = G.react()
if(!G.get_moles(/datum/gas/tritium))
return list("success" = FALSE, "message" = "Plasma fires aren't making trit!")
return ..()
//fusion: a terrible idea that was fun but broken. Now reworked to be less broken and more interesting. Again (and again, and again). Again!
//Fusion Rework Counter: Please increment this if you make a major overhaul to this system again.
//6 reworks
@@ -282,6 +321,31 @@
air.set_temperature(clamp(((air.return_temperature()*old_heat_capacity + reaction_energy)/new_heat_capacity),TCMB,INFINITY))
return REACTING
/datum/gas_reaction/fusion/test()
var/datum/gas_mixture/G = new
G.set_moles(/datum/gas/carbon_dioxide,300)
G.set_moles(/datum/gas/plasma,1000)
G.set_moles(/datum/gas/tritium,100.61)
G.set_moles(/datum/gas/nitryl,1)
G.set_temperature(15000)
G.set_volume(1000)
var/result = G.react()
if(result != REACTING)
return list("success" = FALSE, "message" = "Reaction didn't go at all!")
if(abs(G.analyzer_results["fusion"] - 3) > 0.0000001)
var/instability = G.analyzer_results["fusion"]
return list("success" = FALSE, "message" = "Fusion is not calculating analyzer results correctly, should be 3.000000045, is instead [instability]")
if(abs(G.get_moles(/datum/gas/plasma) - 850.616) > 0.5)
var/plas = G.get_moles(/datum/gas/plasma)
return list("success" = FALSE, "message" = "Fusion is not calculating plasma correctly, should be 850.616, is instead [plas]")
if(abs(G.get_moles(/datum/gas/carbon_dioxide) - 1699.384) > 0.5)
var/co2 = G.get_moles(/datum/gas/carbon_dioxide)
return list("success" = FALSE, "message" = "Fusion is not calculating co2 correctly, should be 1699.384, is instead [co2]")
if(abs(G.return_temperature() - 27600) > 200) // calculating this manually sucks dude
var/temp = G.return_temperature()
return list("success" = FALSE, "message" = "Fusion is not calculating temperature correctly, should be around 27600, is instead [temp]")
return ..()
/datum/gas_reaction/nitrylformation //The formation of nitryl. Endothermic. Requires N2O as a catalyst.
priority = 3
name = "Nitryl formation"
@@ -313,6 +377,20 @@
air.set_temperature(max(((temperature*old_heat_capacity - energy_used)/new_heat_capacity),TCMB))
return REACTING
/datum/gas_reaction/nitrylformation/test()
var/datum/gas_mixture/G = new
G.set_moles(/datum/gas/oxygen,30)
G.set_moles(/datum/gas/nitrogen,30)
G.set_moles(/datum/gas/nitrous_oxide,10)
G.set_volume(1000)
G.set_temperature(150000)
var/result = G.react()
if(result != REACTING)
return list("success" = FALSE, "message" = "Reaction didn't go at all!")
if(!G.get_moles(/datum/gas/nitryl) < 0.8)
return list("success" = FALSE, "message" = "Nitryl isn't being generated correctly!")
return ..()
/datum/gas_reaction/bzformation //Formation of BZ by combining plasma and tritium at low pressures. Exothermic.
priority = 4
name = "BZ Gas formation"
@@ -348,6 +426,19 @@
air.set_temperature(max(((temperature*old_heat_capacity + energy_released)/new_heat_capacity),TCMB))
return REACTING
/datum/gas_reaction/bzformation/test()
var/datum/gas_mixture/G = new
G.set_moles(/datum/gas/plasma,15)
G.set_moles(/datum/gas/nitrous_oxide,15)
G.set_volume(1000)
G.set_temperature(10)
var/result = G.react()
if(result != REACTING)
return list("success" = FALSE, "message" = "Reaction didn't go at all!")
if(!G.get_moles(/datum/gas/bz) < 4) // efficiency is 4.0643 and bz generation == efficiency
return list("success" = FALSE, "message" = "Nitryl isn't being generated correctly!")
return ..()
/datum/gas_reaction/stimformation //Stimulum formation follows a strange pattern of how effective it will be at a given temperature, having some multiple peaks and some large dropoffs. Exo and endo thermic.
priority = 5
name = "Stimulum formation"
@@ -380,6 +471,23 @@
air.set_temperature(max(((air.return_temperature()*old_heat_capacity + stim_energy_change)/new_heat_capacity),TCMB))
return REACTING
/datum/gas_reaction/stimformation/test()
//above mentioned "strange pattern" is a basic quintic polynomial, it's fine, can calculate it manually
var/datum/gas_mixture/G = new
G.set_moles(/datum/gas/bz,30)
G.set_moles(/datum/gas/plasma,1000)
G.set_moles(/datum/gas/tritium,1000)
G.set_moles(/datum/gas/nitryl,1000)
G.set_volume(1000)
G.set_temperature(12998000) // yeah, really
var/result = G.react()
if(result != REACTING)
return list("success" = FALSE, "message" = "Reaction didn't go at all!")
if(!G.get_moles(/datum/gas/stimulum) < 900)
return list("success" = FALSE, "message" = "Stimulum isn't being generated correctly!")
return ..()
/datum/gas_reaction/nobliumformation //Hyper-Noblium formation is extrememly endothermic, but requires high temperatures to start. Due to its high mass, hyper-nobelium uses large amounts of nitrogen and tritium. BZ can be used as a catalyst to make it less endothermic.
priority = 6
name = "Hyper-Noblium condensation"
@@ -408,6 +516,19 @@
if(new_heat_capacity > MINIMUM_HEAT_CAPACITY)
air.set_temperature(max(((air.return_temperature()*old_heat_capacity - energy_taken)/new_heat_capacity),TCMB))
/datum/gas_reaction/nobliumformation/test()
var/datum/gas_mixture/G = new
G.set_moles(/datum/gas/nitrogen,100)
G.set_moles(/datum/gas/tritium,500)
G.set_volume(1000)
G.set_temperature(5000000) // yeah, really
var/result = G.react()
if(result != REACTING)
return list("success" = FALSE, "message" = "Reaction didn't go at all!")
if(abs(G.thermal_energy() - 23000000000) > 1000000) // god i hate floating points
return list("success" = FALSE, "message" = "Hyper-nob formation isn't removing the right amount of heat! Should be 23,000,000,000, is instead [G.thermal_energy()]")
return ..()
/datum/gas_reaction/miaster //dry heat sterilization: clears out pathogens in the air
priority = -10 //after all the heating from fires etc. is done
@@ -433,3 +554,20 @@
//Possibly burning a bit of organic matter through maillard reaction, so a *tiny* bit more heat would be understandable
air.set_temperature(air.return_temperature() + cleaned_air * 0.002)
SSresearch.science_tech.add_point_type(TECHWEB_POINT_TYPE_DEFAULT, cleaned_air*MIASMA_RESEARCH_AMOUNT)//Turns out the burning of miasma is kinda interesting to scientists
/datum/gas_reaction/miaster/test()
var/datum/gas_mixture/G = new
G.set_moles(/datum/gas/miasma,1)
G.set_volume(1000)
G.set_temperature(450)
var/result = G.react()
if(result != REACTING)
return list("success" = FALSE, "message" = "Reaction didn't go at all!")
G.clear()
G.set_moles(/datum/gas/miasma,1)
G.set_temperature(450)
G.set_moles(/datum/gas/water_vapor,0.5)
result = G.react()
if(result != NO_REACTION)
return list("success" = FALSE, "message" = "Miasma sterilization not stopping due to water vapor correctly!")
return ..()
+10 -12
View File
@@ -11,15 +11,15 @@ GLOBAL_LIST_EMPTY(gateway_destinations)
/datum/gateway_destination
var/name = "Unknown Destination"
var/wait = 0 /// How long after roundstart this destination becomes active
var/enabled = TRUE /// If disabled, the destination won't be availible
var/enabled = TRUE /// If disabled, the destination won't be available
var/hidden = FALSE /// Will not show on gateway controls at all.
/* Can a gateway link to this destination right now. */
/datum/gateway_destination/proc/is_availible()
/datum/gateway_destination/proc/is_available()
return enabled && (world.time - SSticker.round_start_time >= wait)
/* Returns user-friendly description why you can't connect to this destination, displayed in UI */
/datum/gateway_destination/proc/get_availible_reason()
/datum/gateway_destination/proc/get_available_reason()
. = "Unreachable"
if(world.time - SSticker.round_start_time < wait)
. = "Connection desynchronized. Recalibration in progress."
@@ -52,8 +52,8 @@ GLOBAL_LIST_EMPTY(gateway_destinations)
. = list()
.["ref"] = REF(src)
.["name"] = name
.["availible"] = is_availible()
.["reason"] = get_availible_reason()
.["available"] = is_available()
.["reason"] = get_available_reason()
if(wait)
.["timeout"] = max(1 - (wait - (world.time - SSticker.round_start_time)) / wait, 0)
@@ -72,10 +72,10 @@ GLOBAL_LIST_EMPTY(gateway_destinations)
if(target_gateway.target == deactivated.destination)
target_gateway.deactivate()
/datum/gateway_destination/gateway/is_availible()
/datum/gateway_destination/gateway/is_available()
return ..() && target_gateway.calibrated && !target_gateway.target && target_gateway.powered()
/datum/gateway_destination/gateway/get_availible_reason()
/datum/gateway_destination/gateway/get_available_reason()
. = ..()
if(!target_gateway.calibrated)
. = "Exit gateway malfunction. Manual recalibration required."
@@ -217,8 +217,7 @@ GLOBAL_LIST_EMPTY(gateway_destinations)
target = D
target.activate(destination)
generate_bumper()
if(use_power == IDLE_POWER_USE)
use_power = ACTIVE_POWER_USE
use_power = ACTIVE_POWER_USE
update_icon()
/obj/machinery/gateway/proc/Transfer(atom/movable/AM)
@@ -261,8 +260,7 @@ GLOBAL_LIST_EMPTY(gateway_destinations)
if(!GLOB.the_gateway)
to_chat(user,"<span class='warning'>Home gateway is not responding!</span>")
if(GLOB.the_gateway.target)
to_chat(user,"<span class='warning'>Home gateway already in use!</span>")
return
GLOB.the_gateway.deactivate() //this will turn the home gateway off so that it's free for us to connect to
activate(GLOB.the_gateway.destination)
else
deactivate()
@@ -319,7 +317,7 @@ GLOBAL_LIST_EMPTY(gateway_destinations)
/obj/machinery/computer/gateway_control/proc/try_to_connect(datum/gateway_destination/D)
if(!D || !G)
return
if(!D.is_availible() || G.target)
if(!D.is_available() || G.target)
return
G.activate(D)
@@ -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")
+76 -2
View File
@@ -163,6 +163,7 @@ GLOBAL_LIST_EMPTY(preferences_datums)
)
var/custom_speech_verb = "default" //if your say_mod is to be something other than your races
var/custom_tongue = "default" //if your tongue is to be something other than your races
var/modified_limbs = list() //prosthetic/amputated limbs
var/chosen_limb_id //body sprite selected to load for the users limbs, null means default, is sanitized when loaded
/// Security record note section
@@ -429,12 +430,19 @@ GLOBAL_LIST_EMPTY(preferences_datums)
dat += "<b>Gender:</b><a style='display:block;width:100px' href='?_src_=prefs;preference=gender;task=input'>[gender == MALE ? "Male" : (gender == FEMALE ? "Female" : (gender == PLURAL ? "Non-binary" : "Object"))]</a><BR>"
if(gender != NEUTER && pref_species.sexes)
dat += "<b>Body Model:</b><a style='display:block;width:100px' href='?_src_=prefs;preference=body_model'>[features["body_model"] == MALE ? "Masculine" : "Feminine"]</a><BR>"
dat += "<b>Limb Modification:</b><BR>"
dat += "<a href='?_src_=prefs;preference=modify_limbs;task=input'>Modify Limbs</a><BR>"
for(var/modification in modified_limbs)
if(modified_limbs[modification][1] == LOADOUT_LIMB_PROSTHETIC)
dat += "<b>[modification]: [modified_limbs[modification][2]]</b><BR>"
else
dat += "<b>[modification]: [modified_limbs[modification][1]]</b><BR>"
dat += "<BR>"
dat += "<b>Species:</b><a style='display:block;width:100px' href='?_src_=prefs;preference=species;task=input'>[pref_species.name]</a><BR>"
dat += "<b>Custom Species Name:</b><a style='display:block;width:100px' href='?_src_=prefs;preference=custom_species;task=input'>[custom_species ? custom_species : "None"]</a><BR>"
dat += "<b>Random Body:</b><a style='display:block;width:100px' href='?_src_=prefs;preference=all;task=random'>Randomize!</A><BR>"
dat += "<b>Always Random Body:</b><a href='?_src_=prefs;preference=all'>[be_random_body ? "Yes" : "No"]</A><BR>"
dat += "<br><b>Cycle background:</b><a style='display:block;width:100px' href='?_src_=prefs;preference=cycle_bg;task=input'>[bgstate]</a><BR>"
var/use_skintones = pref_species.use_skintones
if(use_skintones)
dat += APPEARANCE_CATEGORY_COLUMN
@@ -1235,6 +1243,9 @@ GLOBAL_LIST_EMPTY(preferences_datums)
for(var/V in all_quirks)
var/datum/quirk/T = SSquirks.quirks[V]
bal -= initial(T.value)
for(var/modification in modified_limbs)
if(modified_limbs[modification][1] == LOADOUT_LIMB_PROSTHETIC)
return bal + 1 //max 1 point regardless of how many prosthetics
return bal
/datum/preferences/proc/GetPositiveQuirkCount()
@@ -1492,6 +1503,29 @@ GLOBAL_LIST_EMPTY(preferences_datums)
if("cycle_bg")
bgstate = next_list_item(bgstate, bgstate_options)
if("modify_limbs")
var/limb_type = input(user, "Choose the limb to modify:", "Character Preference") as null|anything in LOADOUT_ALLOWED_LIMB_TARGETS
if(limb_type)
var/modification_type = input(user, "Choose the modification to the limb:", "Character Preference") as null|anything in LOADOUT_LIMBS
if(modification_type)
if(modification_type == LOADOUT_LIMB_PROSTHETIC)
var/prosthetic_type = input(user, "Choose the type of prosthetic", "Character Preference") as null|anything in (list("prosthetic") + GLOB.prosthetic_limb_types)
if(prosthetic_type)
var/number_of_prosthetics = 0
for(var/modification in modified_limbs)
if(modified_limbs[modification][1] == LOADOUT_LIMB_PROSTHETIC)
number_of_prosthetics += 1
if(number_of_prosthetics >= MAXIMUM_LOADOUT_PROSTHETICS && !(limb_type in modified_limbs && modified_limbs[limb_type][1] == LOADOUT_LIMB_PROSTHETIC))
to_chat(user, "<span class='danger'>You can only have up to two prosthetic limbs!</span>")
else
//save the actual prosthetic data
modified_limbs[limb_type] = list(modification_type, prosthetic_type)
else
if(modification_type == LOADOUT_LIMB_NORMAL)
modified_limbs -= limb_type
else
modified_limbs[limb_type] = list(modification_type)
if("underwear")
var/new_underwear = input(user, "Choose your character's underwear:", "Character Preference") as null|anything in GLOB.underwear_list
if(new_underwear)
@@ -2478,7 +2512,7 @@ GLOBAL_LIST_EMPTY(preferences_datums)
ShowChoices(user)
return 1
/datum/preferences/proc/copy_to(mob/living/carbon/human/character, icon_updates = 1, roundstart_checks = TRUE)
/datum/preferences/proc/copy_to(mob/living/carbon/human/character, icon_updates = 1, roundstart_checks = TRUE, initial_spawn = FALSE)
if(be_random_name)
real_name = pref_species.random_name(gender)
@@ -2573,6 +2607,34 @@ GLOBAL_LIST_EMPTY(preferences_datums)
if(custom_speech_verb != "default")
character.dna.species.say_mod = custom_speech_verb
//limb stuff, only done when initially spawning in
if(initial_spawn)
//delete any existing prosthetic limbs to make sure no remnant prosthetics are left over
for(var/obj/item/bodypart/part in character.bodyparts)
if(part.status == BODYPART_ROBOTIC)
qdel(part)
character.regenerate_limbs() //regenerate limbs so now you only have normal limbs
for(var/modified_limb in modified_limbs)
var/modification = modified_limbs[modified_limb][1]
var/obj/item/bodypart/old_part = character.get_bodypart(modified_limb)
if(modification == LOADOUT_LIMB_PROSTHETIC)
var/obj/item/bodypart/new_limb
switch(modified_limb)
if(BODY_ZONE_L_ARM)
new_limb = new/obj/item/bodypart/l_arm/robot/surplus(character)
if(BODY_ZONE_R_ARM)
new_limb = new/obj/item/bodypart/r_arm/robot/surplus(character)
if(BODY_ZONE_L_LEG)
new_limb = new/obj/item/bodypart/l_leg/robot/surplus(character)
if(BODY_ZONE_R_LEG)
new_limb = new/obj/item/bodypart/r_leg/robot/surplus(character)
var/prosthetic_type = modified_limbs[modified_limb][2]
if(prosthetic_type != "prosthetic") //lets just leave the old sprites as they are
new_limb.icon = file("icons/mob/augmentation/cosmetic_prosthetic/[prosthetic_type].dmi")
new_limb.replace_limb(character)
qdel(old_part)
character.regenerate_icons()
SEND_SIGNAL(character, COMSIG_HUMAN_PREFS_COPIED_TO, src, icon_updates, roundstart_checks)
@@ -2581,6 +2643,18 @@ GLOBAL_LIST_EMPTY(preferences_datums)
character.update_body()
character.update_hair()
/datum/preferences/proc/post_copy_to(mob/living/carbon/human/character)
//if no legs, and not a paraplegic or a slime, give them a free wheelchair
if(modified_limbs[BODY_ZONE_L_LEG] == LOADOUT_LIMB_AMPUTATED && modified_limbs[BODY_ZONE_R_LEG] == LOADOUT_LIMB_AMPUTATED && !character.has_quirk(/datum/quirk/paraplegic) && !isjellyperson(character))
if(character.buckled)
character.buckled.unbuckle_mob(character)
var/turf/T = get_turf(character)
var/obj/structure/chair/spawn_chair = locate() in T
var/obj/vehicle/ridden/wheelchair/wheels = new(T)
if(spawn_chair) // Makes spawning on the arrivals shuttle more consistent looking
wheels.setDir(spawn_chair.dir)
wheels.buckle_mob(character)
/datum/preferences/proc/get_default_name(name_id)
switch(name_id)
if("human")
+9 -2
View File
@@ -514,6 +514,12 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
S["scars3"] >> scars_list["3"]
S["scars4"] >> scars_list["4"]
S["scars5"] >> scars_list["5"]
var/limbmodstr
S["modified_limbs"] >> limbmodstr
if(length(limbmodstr))
modified_limbs = safe_json_decode(limbmodstr)
else
modified_limbs = list()
S["chosen_limb_id"] >> chosen_limb_id
S["hide_ckey"] >> hide_ckey //saved per-character
@@ -845,8 +851,6 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
WRITE_FILE(S["feature_ooc_notes"], features["ooc_notes"])
WRITE_FILE(S["chosen_limb_id"], chosen_limb_id)
//Custom names
for(var/custom_name_id in GLOB.preferences_custom_names)
var/savefile_slot_name = custom_name_id + "_name" //TODO remove this
@@ -874,6 +878,9 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
WRITE_FILE(S["scars3"] , scars_list["3"])
WRITE_FILE(S["scars4"] , scars_list["4"])
WRITE_FILE(S["scars5"] , scars_list["5"])
if(islist(modified_limbs))
WRITE_FILE(S["modified_limbs"] , safe_json_encode(modified_limbs))
WRITE_FILE(S["chosen_limb_id"], chosen_limb_id)
//gear loadout
+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()
+4 -4
View File
@@ -5,9 +5,9 @@
var/obj/item/clothing/head/hooded/hood
var/hoodtype = /obj/item/clothing/head/hooded/winterhood //so the chaplain hoodie or other hoodies can override this
/obj/item/clothing/suit/hooded/New()
/obj/item/clothing/suit/hooded/Initialize()
. = ..()
hood = MakeHelmet()
..()
/obj/item/clothing/suit/hooded/Destroy()
. = ..()
@@ -48,7 +48,7 @@
/obj/item/clothing/suit/hooded/update_icon_state()
icon_state = "[initial(icon_state)]"
if(ishuman(hood.loc))
if(ishuman(hood?.loc))
var/mob/living/carbon/human/H = hood.loc
if(H.head == hood)
icon_state += "_t"
@@ -131,8 +131,8 @@
//Hardsuit toggle code
/obj/item/clothing/suit/space/hardsuit/Initialize()
helmet = MakeHelmet()
. = ..()
helmet = MakeHelmet()
/obj/item/clothing/suit/space/hardsuit/Destroy()
if(helmet)

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