diff --git a/code/__DEFINES/_atoms.dm b/code/__DEFINES/_atoms.dm
index 3c7b67070f88..450a1e55b006 100644
--- a/code/__DEFINES/_atoms.dm
+++ b/code/__DEFINES/_atoms.dm
@@ -2,3 +2,7 @@
#define BAD_INIT_DIDNT_INIT 2
#define BAD_INIT_SLEPT 4
#define BAD_INIT_NO_HINT 8
+
+#define LOOT_ICON_ICON_TO_HTML 0
+#define LOOT_ICON_FLAT_ICON 1
+#define LOOT_ICON_FLAT_ICON_TYPE_CACHABLE 2
diff --git a/code/__DEFINES/_span.dm b/code/__DEFINES/_span.dm
index 405d07303ecd..077e7657ee7e 100644
--- a/code/__DEFINES/_span.dm
+++ b/code/__DEFINES/_span.dm
@@ -8,214 +8,233 @@
* MARK: Without CSS
* Are these chat selectors?
*/
-#define span_emojienabled(str) ("" + str + "")
-#define span_header(str) ("")
-#define span_linkoff(str) ("" + str + "")
-#define span_linkon(str) ("" + str + "")
-#define span_error(str) ("" + str + "")
-#define span_gamesay(str) ("" + str + "")
-#define span_message(str) ("" + str + "")
-#define span_boldmessage(str) ("" + str + "")
-#define span_combatdanger(str) ("" + str + "")
-#define span_combatuserdanger(str) ("" + str + "")
-#define span_game_emote(str) ("" + str + "")
-#define span_vnimanie(str) ("" + str + "")
-#define span_caution(str) ("" + str + "")
-#define span_typing(str) ("" + str + "")
-#define span_value(str) ("" + str + "")
-#define span_body(str) ("" + str + "")
+#define span_emojienabled(str) ("[str]")
+#define span_header(str) ("")
+#define span_linkoff(str) ("[str]")
+#define span_linkon(str) ("[str]")
+#define span_error(str) ("[str]")
+#define span_gamesay(str) ("[str]")
+#define span_message(str) ("[str]")
+#define span_boldmessage(str) ("[str]")
+#define span_combatdanger(str) ("[str]")
+#define span_combatuserdanger(str) ("[str]")
+#define span_game_emote(str) ("[str]")
+#define span_vnimanie(str) ("[str]")
+#define span_caution(str) ("[str]")
+#define span_typing(str) ("[str]")
+#define span_value(str) ("[str]")
+#define span_body(str) ("[str]")
/**
* MARK: General Stuff
*/
-#define span_italics(str) ("" + str + "")
-#define span_emote(str) ("" + str + "")
-#define span_bold(str) ("" + str + "")
-#define span_bolditalics(str) ("" + str + "")
-#define span_small(str) ("" + str + "")
-#define span_big(str) ("" + str + "")
-#define span_bigbold(str) ("" + str + "")
-#define span_reallybig(str) ("" + str + "")
-#define span_sans(str) ("" + str + "")
-#define span_wingdings(str) ("" + str + "")
-#define span_robot(str) ("" + str + "")
+#define span_italics(str) ("[str]")
+#define span_emote(str) ("[str]")
+#define span_bold(str) ("[str]")
+#define span_bolditalics(str) ("[str]")
+#define span_small(str) ("[str]")
+#define span_big(str) ("[str]")
+#define span_bigbold(str) ("[str]")
+#define span_reallybig(str) ("[str]")
+#define span_sans(str) ("[str]")
+#define span_sans_alt(str) ("" + str + "")
+#define span_wingdings(str) ("[str]")
+#define span_wingdings_alt(str) ("" + str + "")
+#define span_robot(str) ("[str]")
/**
* MARK: MOTD & MEMO
*/
-#define span_motd(str) ("" + str + "")
-#define span_memo(str) ("" + str + "")
-#define span_memoedit(str) ("" + str + "")
+#define span_motd(str) ("[str]")
+#define span_memo(str) ("[str]")
+#define span_memoedit(str) ("[str]")
/**
* MARK: General colors
* TODO: Combine everything just bold fonts (prefix, yell, name, ooc etc.).
*/
-#define span_ooc(str) ("" + str + "")
-#define span_looc(str) ("" + str + "")
-#define span_discordpm(str) ("" + str + "")
-#define span_debug(str) ("" + str + "")
-#define span_deadsay(str) ("" + str + "")
-#define span_darkmblue(str) ("" + str + "")
-#define span_prefix(str) ("" + str + "")
-#define span_name(str) ("" + str + "")
-#define span_yell(str) ("" + str + "")
+#define span_ooc(str) ("[str]")
+#define span_looc(str) ("[str]")
+#define span_discordpm(str) ("[str]")
+#define span_debug(str) ("[str]")
+#define span_deadsay(str) ("[str]")
+#define span_darkmblue(str) ("[str]")
+#define span_prefix(str) ("[str]")
+#define span_name(str) ("[str]")
+#define span_yell(str) ("[str]")
/**
* MARK: Base colors
* All new style colors must be converted to the corresponding span and written as class.
*/
-#define span_red(str) ("" + str + "")
-#define span_green(str) ("" + str + "")
-#define span_purple(str) ("" + str + "")
-#define span_orange(str) ("" + str + "")
-#define span_blue(str) ("" + str + "")
-#define span_yellow(str) ("" + str + "")
+#define span_red(str) ("[str]")
+#define span_green(str) ("[str]")
+#define span_purple(str) ("[str]")
+#define span_orange(str) ("[str]")
+#define span_blue(str) ("[str]")
+#define span_yellow(str) ("[str]")
/**
* MARK: Other colors
*/
-#define span_rose(str) ("" + str + "")
-#define span_interface(str) ("" + str + "")
-#define span_greentext(str) ("" + str + "")
-#define span_redtext(str) ("" + str + "")
-#define span_resonate(str) ("" + str + "")
-#define span_specialnotice(str) ("" + str + "")
-#define span_whisper(str) ("" + str + "")
-#define span_clown(str) ("" + str + "")
-#define span_bad(str) ("" + str + "")
-#define span_average(str) ("" + str + "")
-#define span_good(str) ("" + str + "")
+#define span_rose(str) ("[str]")
+#define span_interface(str) ("[str]")
+#define span_greentext(str) ("[str]")
+#define span_redtext(str) ("[str]")
+#define span_resonate(str) ("[str]")
+#define span_specialnotice(str) ("[str]")
+#define span_whisper(str) ("[str]")
+#define span_clown(str) ("[str]")
+#define span_bad(str) ("[str]")
+#define span_average(str) ("[str]")
+#define span_good(str) ("[str]")
/**
* MARK: Admin/Mentor
*/
-#define span_mentorhelp(str) (" " + str + "")
-#define span_admin(str) ("" + str + "")
-#define span_adminhelp(str) ("" + str + "")
-#define span_adminticket(str) ("" + str + "")
-#define span_adminticketalt(str) ("" + str + "")
-#define span_admin_channel(str) ("" + str + "")
-#define span_dev_channel(str) ("" + str + "")
-#define span_mentor_channel(str) ("" + str + "")
-#define span_all_admin_ping(str) ("" + str + "")
+#define span_mentorhelp(str) (" [str]")
+#define span_admin(str) ("[str]")
+#define span_adminhelp(str) ("[str]")
+#define span_adminticket(str) ("[str]")
+#define span_adminticketalt(str) ("[str]")
+#define span_admin_channel(str) ("[str]")
+#define span_dev_channel(str) ("[str]")
+#define span_mentor_channel(str) ("[str]")
+#define span_all_admin_ping(str) ("[str]")
/**
* MARK: Radio
* TODO: Check and delete if it can be replaced.
*/
-#define span_deptradio(str) ("" + str + "")
-#define span_syndradio(str) ("" + str + "")
-#define span_sciradio(str) ("" + str + "")
+#define span_deptradio(str) ("[str]")
+#define span_syndradio(str) ("[str]")
+#define span_sciradio(str) ("[str]")
/**
* MARK: Alerts
*/
-#define span_alert(str) ("" + str + "")
-#define span_ghostalert(str) ("" + str + "")
-#define span_warning(str) ("" + str + "")
-#define span_boldwarning(str) ("" + str + "")
-#define span_announce(str) ("" + str + "")
-#define span_warningbig(str) ("" + str + "")
-#define span_danger(str) ("" + str + "")
-#define span_bolddanger(str) ("" + str + "")
-#define span_biggerdanger(str) ("" + str + "")
-#define span_userdanger(str) ("" + str + "")
-#define span_disarm(str) ("" + str + "")
-#define span_notice(str) ("" + str + "")
-#define span_boldnotice(str) ("" + str + "")
-#define span_hear(str) ("" + str + "")
-#define span_adminnotice(str) ("" + str + "")
-#define span_unconscious(str) ("" + str + "")
-#define span_suicide(str) ("" + str + "")
+#define span_alert(str) ("[str]")
+#define span_alert_alt(str) ("" + str + "")
+#define span_ghostalert(str) ("[str]")
+#define span_warning(str) ("[str]")
+#define span_warning_alt(str) ("" + str + "")
+#define span_boldwarning(str) ("[str]")
+#define span_boldwarning_alt(str) ("" + str + "")
+#define span_announce(str) ("[str]")
+#define span_warningbig(str) ("[str]")
+#define span_danger(str) ("[str]")
+#define span_danger_alt(str) ("" + str + "")
+#define span_bolddanger(str) ("[str]")
+#define span_biggerdanger(str) ("[str]")
+#define span_userdanger(str) ("[str]")
+#define span_userdanger_alt(str) ("" + str + "")
+#define span_disarm(str) ("[str]")
+#define span_notice(str) ("[str]")
+#define span_notice_alt(str) ("" + str + "")
+#define span_boldnotice(str) ("[str]")
+#define span_boldnotice_alt(str) ("" + str + "")
+#define span_hear(str) ("[str]")
+#define span_adminnotice(str) ("[str]")
+#define span_unconscious(str) ("[str]")
+#define span_suicide(str) ("[str]")
/**
* MARK: Announcements
*/
-#define span_boldannounceic(str) ("" + str + "")
-#define span_boldannounceooc(str) ("" + str + "")
-#define span_greenannounce(str) ("" + str + "")
+#define span_boldannounceic(str) ("[str]")
+#define span_boldannounceic_alt(str) ("" + str + "")
+#define span_boldannounceooc(str) ("[str]")
+#define span_greenannounce(str) ("[str]")
/**
* MARK: Antagonists
*/
-#define span_alien(str) ("" + str + "")
-#define span_noticealien(str) ("" + str + "")
-#define span_alertalien(str) ("" + str + "")
-#define span_terrorspider(str) ("" + str + "")
-#define span_dantalion(str) ("" + str + "")
-#define span_sinister(str) ("" + str + "")
-#define span_blob(str) ("" + str + "")
-#define span_revennotice(str) ("" + str + "")
-#define span_revenboldnotice(str) ("" + str + "")
-#define span_revenbignotice(str) ("" + str + "")
-#define span_revenminor(str) ("" + str + "")
-#define span_revenwarning(str) ("" + str + "")
-#define span_revendanger(str) ("" + str + "")
-#define span_changeling(str) ("" + str + "")
-#define span_abductor(str) ("" + str + "")
-#define span_mind_control(str) ("" + str + "")
-#define span_his_grace(str) ("" + str + "")
-#define span_shadowling(str) ("" + str + "")
-#define span_holoparasite(str) ("" + str + "")
+#define span_alien(str) ("[str]")
+#define span_noticealien(str) ("[str]")
+#define span_noticealien_alt(str) ("" + str + "")
+#define span_alertalien(str) ("[str]")
+#define span_terrorspider(str) ("[str]")
+#define span_dantalion(str) ("[str]")
+#define span_sinister(str) ("[str]")
+#define span_sinister_alt(str) ("" + str + "")
+#define span_blob(str) ("[str]")
+#define span_revennotice(str) ("[str]")
+#define span_revennotice_alt(str) ("" + str + "")
+#define span_revenboldnotice(str) ("[str]")
+#define span_revenbignotice(str) ("[str]")
+#define span_revenminor(str) ("[str]")
+#define span_revenwarning(str) ("[str]")
+#define span_revendanger(str) ("[str]")
+#define span_changeling(str) ("[str]")
+#define span_abductor(str) ("[str]")
+#define span_mind_control(str) ("[str]")
+#define span_his_grace(str) ("[str]")
+#define span_shadowling(str) ("[str]")
+#define span_shadowling_alt(str) ("" + str + "")
+#define span_holoparasite(str) ("[str]")
/**
* MARK: Cults
*/
-#define span_cult(str) ("" + str + "")
-#define span_cultspeech(str) ("" + str + "")
-#define span_cultitalic(str) ("" + str + "")
-#define span_cultlarge(str) ("" + str + "")
-#define span_narsie(str) ("" + str + "")
-#define span_narsiesmall(str) ("" + str + "")
-#define span_clock(str) ("" + str + "")
-#define span_clockspeech(str) ("" + str + "")
-#define span_clockitalic(str) ("" + str + "")
-#define span_clocklarge(str) ("" + str + "")
-#define span_ratvar(str) ("" + str + "")
+#define span_cult(str) ("[str]")
+#define span_cultspeech(str) ("[str]")
+#define span_cultitalic(str) ("[str]")
+#define span_cultitalic_alt(str) ("" + str + "")
+#define span_cultlarge(str) ("[str]")
+#define span_cultlarge_alt(str) ("" + str + "")
+#define span_narsie(str) ("[str]")
+#define span_narsiesmall(str) ("[str]")
+#define span_clock(str) ("[str]")
+#define span_clockspeech(str) ("[str]")
+#define span_clockitalic(str) ("[str]")
+#define span_clocklarge(str) ("[str]")
+#define span_ratvar(str) ("[str]")
/**
* MARK: Syndicate codewords
*/
-#define span_codephrases(str) ("" + str + "")
-#define span_coderesponses(str) ("" + str + "")
+#define span_codephrases(str) ("[str]")
+#define span_coderesponses(str) ("[str]")
/**
* MARK: Megafauna
*/
-#define span_colossus(str) ("" + str + "")
-#define span_hierophant(str) ("" + str + "")
-#define span_hierophant_warning(str) ("" + str + "")
+#define span_colossus(str) ("[str]")
+#define span_colossus_alt(str) ("" + str + "")
+#define span_hierophant(str) ("[str]")
+#define span_hierophant_warning(str) ("[str]")
/**
* MARK: Anomaly
*/
-#define span_bluespace_anomaly(str) ("" + str + "")
-#define span_energetic_anomaly(str) ("" + str + "")
-#define span_atmospferic_anomaly(str) ("" + str + "")
-#define span_gravitational_anomaly(str) ("" + str + "")
-#define span_vortex_anomaly(str) ("" + str + "")
+#define span_bluespace_anomaly(str) ("[str]")
+#define span_energetic_anomaly(str) ("[str]")
+#define span_atmospferic_anomaly(str) ("[str]")
+#define span_gravitational_anomaly(str) ("[str]")
+#define span_vortex_anomaly(str) ("[str]")
/**
* MARK: Gases
*/
-#define span_oxygen(str) ("" + str + "")
-#define span_nitrogen(str) ("" + str + "")
-#define span_carbon_dioxide(str) ("" + str + "")
-#define span_plasma(str) ("" + str + "")
-#define span_sleeping_agent(str) ("" + str + "")
-#define span_agent_b(str) ("" + str + "")
-#define span_hydrogen(str) ("" + str + "")
-#define span_water_vapor(str) ("" + str + "")
+#define span_oxygen(str) ("[str]")
+#define span_nitrogen(str) ("[str]")
+#define span_carbon_dioxide(str) ("[str]")
+#define span_plasma(str) ("[str]")
+#define span_sleeping_agent(str) ("[str]")
+#define span_agent_b(str) ("[str]")
+#define span_hydrogen(str) ("[str]")
+#define span_water_vapor(str) ("[str]")
/**
* MARK: Font sizes
* Don't rename it. Each numbered span corresponds to the numbered font style.
*/
-#define span_fontsize1(str) ("" + str + "")
-#define span_fontsize2(str) ("" + str + "")
-#define span_fontsize3(str) ("" + str + "")
-#define span_fontsize4(str) ("" + str + "")
-#define span_fontsize5(str) ("" + str + "")
-#define span_fontsize6(str) ("" + str + "")
-#define span_fontsize7(str) ("" + str + "")
+#define span_fontsize1(str) ("[str]")
+#define span_fontsize2(str) ("[str]")
+#define span_fontsize3(str) ("[str]")
+#define span_fontsize4(str) ("[str]")
+#define span_fontsize5(str) ("[str]")
+#define span_fontsize5_alt(str) ("" + str + "")
+#define span_fontsize6(str) ("[str]")
+#define span_fontsize7(str) ("[str]")
+
diff --git a/code/__DEFINES/ghost.dm b/code/__DEFINES/ghost.dm
index 5d2130774a27..9354804ce832 100644
--- a/code/__DEFINES/ghost.dm
+++ b/code/__DEFINES/ghost.dm
@@ -1,2 +1,4 @@
#define GHOST_CAN_REENTER 1
#define GHOST_IS_OBSERVER 2
+
+#define IS_FAKE_KEY(key) (key && key[1] == "@")
diff --git a/code/__DEFINES/is_helpers.dm b/code/__DEFINES/is_helpers.dm
index b6c73e55363c..7eb1cf59879c 100644
--- a/code/__DEFINES/is_helpers.dm
+++ b/code/__DEFINES/is_helpers.dm
@@ -87,6 +87,8 @@
#define isammocasing(A) (istype(A, /obj/item/ammo_casing))
+#define isammobox(A) (istype(A, /obj/item/ammo_box))
+
#define ismachinery(A) (istype(A, /obj/machinery))
#define isapc(A) (istype(A, /obj/machinery/power/apc))
diff --git a/code/__DEFINES/math.dm b/code/__DEFINES/math.dm
index 1be32e3c6216..bbf61eaf87d1 100644
--- a/code/__DEFINES/math.dm
+++ b/code/__DEFINES/math.dm
@@ -140,3 +140,9 @@
/// Tests if the value is in the given range.
#define IS_IN_BOUNDS(val, lower, upper) ((val) >= (lower) && (val) <= (upper))
+
+#define POW2(x) ((x) * (x))
+
+#define POW3(x) ((x) * (x) * (x))
+
+#define MAGNITUDE(dx, dy) (sqrt(POW2(dx) + POW2(dy)))
diff --git a/code/__HELPERS/_logging.dm b/code/__HELPERS/_logging.dm
index b4cb001f8c29..aadb6ea5e070 100644
--- a/code/__HELPERS/_logging.dm
+++ b/code/__HELPERS/_logging.dm
@@ -164,11 +164,11 @@ GLOBAL_PROTECT(log_end)
count++
WRITE_LOG(GLOB.world_game_log, "GAME: End objective log for [html_decode(Mind.key)]/[html_decode(Mind.name)][GLOB.log_end]")
-/proc/log_world(text)
+/proc/log_world(text, root_log = FALSE)
#if defined(GAME_TESTS) || defined(MAP_TESTS) || defined(TESTING)
SEND_TEXT(world.log, text)
#else
- if(config && CONFIG_GET(flag/enable_root_log))
+ if(config && CONFIG_GET(flag/enable_root_log) || root_log)
SEND_TEXT(world.log, text)
#endif
@@ -221,7 +221,7 @@ GLOBAL_PROTECT(log_end)
* Standardized method for tracking startup times.
*/
/proc/log_startup_progress_global(prefix, message)
- to_chat(world, span_danger("\[[prefix]] [message]"))
+ to_chat(world, span_danger("\[[prefix]\] [message]"))
log_world("\[[prefix]] [message]")
// A logging proc that only outputs after setup is done, to
@@ -431,7 +431,7 @@ GLOBAL_PROTECT(log_end)
return "(UNKNOWN (?, ?, ?))"
#if defined(REFERENCE_TRACKING) // Doing it locally
-#define log_reftracker(msg) log_world("## REF SEARCH [msg]")
+#define log_reftracker(msg) log_gc("## REF SEARCH [msg]")
#else //Not tracking at all
#define log_reftracker(msg)
diff --git a/code/__HELPERS/areas.dm b/code/__HELPERS/areas.dm
index 79be860c5eb1..e253477bf1c9 100644
--- a/code/__HELPERS/areas.dm
+++ b/code/__HELPERS/areas.dm
@@ -40,7 +40,7 @@
return FALSE
var/static/list/cardinal_directions = list("[NORTH]" = TRUE, "[EAST]" = TRUE, "[SOUTH]" = TRUE, "[WEST]" = TRUE)
- if(!cardinal_directions["[direction]"] || adjacent_turf.blocks_air || !current_turf.CanAtmosPass(adjacent_turf))
+ if(!cardinal_directions["[direction]"] || adjacent_turf.blocks_air || !current_turf.CanAtmosPass(direction))
continue
turfs_to_process += adjacent_turf
@@ -251,7 +251,7 @@
copiedobjs += DuplicateObject(M, perfect_copy, newloc = X)
for(var/V in T.vars)
- if(!(V in list("type","loc","locs","vars", "parent", "parent_type","verbs","ckey","key","x","y","z","destination_z", "destination_x", "destination_y","contents", "luminosity", "group")))
+ if(!(V in list("type","loc","locs","vars", "parent", "parent_type", "pixloc", "verbs", "ckey", "key", "x", "y", "z","destination_z", "destination_x", "destination_y","contents", "luminosity", "group")))
X.vars[V] = T.vars[V]
toupdate += X
diff --git a/code/__HELPERS/data_struct/priority_queue.dm b/code/__HELPERS/data_struct/priority_queue.dm
index 6468dc7fab99..456914c523dd 100644
--- a/code/__HELPERS/data_struct/priority_queue.dm
+++ b/code/__HELPERS/data_struct/priority_queue.dm
@@ -21,6 +21,7 @@
var/priority_node/top = heap[1]
var/bottom = heap[length(heap)]
var/item = top.item
+ top.item = null
heap -= bottom
if(!length(heap))
return item
diff --git a/code/__HELPERS/data_struct/queue.dm b/code/__HELPERS/data_struct/queue.dm
index b771f0a17a4d..74683c480b2b 100644
--- a/code/__HELPERS/data_struct/queue.dm
+++ b/code/__HELPERS/data_struct/queue.dm
@@ -17,6 +17,11 @@
/// Number of elements in queue
var/count = 0
+/queue/Destroy(force)
+ head = null
+ tail = null
+ . = ..()
+
/*
* Adding an element to the end of the queue
*/
diff --git a/code/__HELPERS/icons.dm b/code/__HELPERS/icons.dm
index 8b00c838a6ef..8443f32e25e7 100644
--- a/code/__HELPERS/icons.dm
+++ b/code/__HELPERS/icons.dm
@@ -674,7 +674,7 @@ The _flatIcons list is a cache for generated icon files.
var/render_icon = curicon
if(render_icon)
- var/curstates = icon_states(curicon)
+ var/curstates = icon_states_fast(curicon)
if(!(icon_exists(curicon, curstate)))
if("" in curstates)
curstate = ""
@@ -687,9 +687,9 @@ The _flatIcons list is a cache for generated icon files.
//Determines if there's directionals.
if(render_icon && curdir != SOUTH)
if(
- !length(icon_states(icon(curicon, curstate, NORTH))) \
- && !length(icon_states(icon(curicon, curstate, EAST))) \
- && !length(icon_states(icon(curicon, curstate, WEST))) \
+ !length(icon_states_fast(icon(curicon, curstate, NORTH))) \
+ && !length(icon_states_fast(icon(curicon, curstate, EAST))) \
+ && !length(icon_states_fast(icon(curicon, curstate, WEST))) \
)
base_icon_dir = SOUTH
@@ -829,8 +829,8 @@ The _flatIcons list is a cache for generated icon files.
/proc/rand_hex_color()
var/list/colors = list("0","1","2","3","4","5","6","7","8","9","a","b","c","d","e","f")
var/color=""
- for(var/i=0;i<6;i++)
- color = color+pick(colors)
+ for(var/i in 1 to 6)
+ color = color + pick(colors)
return "#[color]"
//Imagine removing pixels from the main icon that are covered by pixels from the mask icon.
@@ -1209,9 +1209,35 @@ GLOBAL_LIST_EMPTY(bicon_cache)
if(isicon(thing))
return icon2html(thing, target)
+ return flat_icon2html(thing, target, sourceonly = FALSE)
+
+/proc/flat_icon2html(thing, target, sourceonly = FALSE, name = md5("[thing]"))
+ if(!thing)
+ return
var/icon/flat_icon = getFlatIcon(thing)
return icon2html(flat_icon, target, sourceonly = sourceonly)
+/proc/get_icon_from_uni_icon(datum/universal_icon/flat_icon, name, dmi_icon = FALSE)
+ var/entries_json = json_encode(list(name = flat_icon.to_list()))
+ var/data_out = rustlib_iconforge_generate("tmp/icons/", name, entries_json, FALSE, dmi_icon, TRUE)
+ if(data_out == RUSTLIBS_JOB_ERROR)
+ CRASH("Icon [name] JOB PANIC")
+ else if(!findtext(data_out, "{", 1, 2))
+ rustlib_file_write(entries_json, "[GLOB.log_directory]/spritesheet_debug_[name].json")
+ CRASH("Icon [name] UNKNOWN ERROR: [data_out]")
+ var/data = json_decode(data_out)
+ var/list/sizes = data["sizes"]
+ if(!length(sizes))
+ CRASH("Icon [name] UNKNOWN ERROR: [data_out]")
+ var/size = sizes[1]
+ if(!size)
+ CRASH("Icon [name] UNKNOWN ERROR: [data_out]")
+
+ var/png_name = "[name]_[size].png"
+ var/file_directory = "tmp/icons/[png_name]"
+ return file(file_directory)
+
+
#define CACHED_WIDTH_INDEX "width"
#define CACHED_HEIGHT_INDEX "height"
diff --git a/code/__HELPERS/spatial_info.dm b/code/__HELPERS/spatial_info.dm
index 8d1ab0af9fc9..b958ff39a4de 100644
--- a/code/__HELPERS/spatial_info.dm
+++ b/code/__HELPERS/spatial_info.dm
@@ -303,7 +303,7 @@
var/dx = first_location.x - second_location.x
var/dy = first_location.y - second_location.y
- var/dist = sqrt(dx ** 2 + dy ** 2)
+ var/dist = MAGNITUDE(dx, dy)
return dist
diff --git a/code/_onclick/hud/hud.dm b/code/_onclick/hud/hud.dm
index 01c2633ac13e..5ca05caaffea 100644
--- a/code/_onclick/hud/hud.dm
+++ b/code/_onclick/hud/hud.dm
@@ -101,6 +101,61 @@
RegisterSignal(mymob, COMSIG_MOB_SIGHT_CHANGE, PROC_REF(update_sightflags), override = TRUE)
update_sightflags(mymob, mymob.sight, NONE)
+/datum/hud/Destroy()
+ if(mymob.hud_used == src)
+ mymob.hud_used = null
+
+ QDEL_NULL(toggle_palette)
+ QDEL_NULL(palette_down)
+ QDEL_NULL(palette_up)
+ QDEL_NULL(palette_actions)
+ QDEL_NULL(listed_actions)
+ QDEL_LIST(floating_actions)
+
+ QDEL_NULL(module_store_icon)
+
+ QDEL_LIST(static_inventory)
+
+ inv_slots.Cut()
+ action_intent = null
+ zone_select = null
+ move_intent = null
+ hand_slots.Cut()
+
+ QDEL_LIST(toggleable_inventory)
+
+ QDEL_LIST(hotkeybuttons)
+
+ QDEL_LIST(infodisplay)
+
+ //clear mob refs to screen objects
+ mymob.throw_icon = null
+ mymob.healths = null
+ mymob.healthdoll = null
+ mymob.pullin = null
+ mymob.stamina_bar = null
+ mymob.nutrition_bar = null
+
+ //clear the rest of our reload_fullscreen
+ QDEL_NULL(lingchemdisplay)
+ QDEL_NULL(lingstingdisplay)
+ QDEL_NULL(blobpwrdisplay)
+ QDEL_NULL(alien_plasma_display)
+ QDEL_NULL(vampire_blood_display)
+ QDEL_NULL(ninja_energy_display)
+ QDEL_NULL(ninja_focus_display)
+ QDEL_NULL(wind_up_timer)
+ QDEL_NULL(nightvisionicon)
+ QDEL_NULL(devilsouldisplay)
+ QDEL_NULL(combo_display)
+
+ QDEL_LIST_ASSOC_VAL(master_groups)
+ QDEL_LIST_ASSOC_VAL(plane_master_controllers)
+
+ mymob = null
+ QDEL_NULL(screentip_text)
+ . = ..()
+
/datum/hud/proc/client_refresh(datum/source)
SIGNAL_HANDLER
var/client/client = mymob.canon_client
@@ -158,61 +213,6 @@
var/datum/plane_master_group/group = master_groups[group_key]
group.build_planes_offset(src, new_offset)
-/datum/hud/Destroy()
- if(mymob.hud_used == src)
- mymob.hud_used = null
-
- QDEL_NULL(toggle_palette)
- QDEL_NULL(palette_down)
- QDEL_NULL(palette_up)
- QDEL_NULL(palette_actions)
- QDEL_NULL(listed_actions)
- QDEL_LIST(floating_actions)
-
- QDEL_NULL(module_store_icon)
-
- QDEL_LIST(static_inventory)
-
- inv_slots.Cut()
- action_intent = null
- zone_select = null
- move_intent = null
- hand_slots.Cut()
-
- QDEL_LIST(toggleable_inventory)
-
- QDEL_LIST(hotkeybuttons)
-
- QDEL_LIST(infodisplay)
-
- //clear mob refs to screen objects
- mymob.throw_icon = null
- mymob.healths = null
- mymob.healthdoll = null
- mymob.pullin = null
- mymob.stamina_bar = null
- mymob.nutrition_bar = null
-
- //clear the rest of our reload_fullscreen
- lingchemdisplay = null
- lingstingdisplay = null
- blobpwrdisplay = null
- alien_plasma_display = null
- vampire_blood_display = null
- ninja_energy_display = null
- ninja_focus_display = null
- wind_up_timer = null
- nightvisionicon = null
- devilsouldisplay = null
- combo_display = null
-
- QDEL_LIST_ASSOC_VAL(master_groups)
- QDEL_LIST_ASSOC_VAL(plane_master_controllers)
-
- mymob = null
- QDEL_NULL(screentip_text)
- return ..()
-
/datum/hud/proc/on_plane_increase(datum/source, old_max_offset, new_max_offset)
SIGNAL_HANDLER
build_plane_groups(old_max_offset + 1, new_max_offset)
diff --git a/code/_onclick/hud/plane_master/plane_master_controller.dm b/code/_onclick/hud/plane_master/plane_master_controller.dm
index 1436f41581bc..57319bf5680c 100644
--- a/code/_onclick/hud/plane_master/plane_master_controller.dm
+++ b/code/_onclick/hud/plane_master/plane_master_controller.dm
@@ -12,6 +12,10 @@
. = ..()
owner_hud = hud
+/atom/movable/plane_master_controller/Destroy(force)
+ owner_hud = null
+ . = ..()
+
/atom/movable/plane_master_controller/proc/get_planes()
var/returned_planes = list()
for(var/true_plane in controlled_planes)
diff --git a/code/controllers/controller.dm b/code/controllers/controller.dm
index 543e34d51d93..e220ab740a53 100644
--- a/code/controllers/controller.dm
+++ b/code/controllers/controller.dm
@@ -29,5 +29,5 @@
*/
/datum/controller/proc/log_startup_progress(message)
Master.last_init_info = "([name]): [message]"
- to_chat(world, span_danger("\[[name]] [message]"), MESSAGE_TYPE_DEBUG, confidential = TRUE)
+ to_chat(world, span_danger("\[[name]\] [message]"), MESSAGE_TYPE_DEBUG, confidential = TRUE)
log_world("\[[name]] [message]")
diff --git a/code/controllers/globals.dm b/code/controllers/globals.dm
index 3c73230c7d51..20b9a3834afd 100644
--- a/code/controllers/globals.dm
+++ b/code/controllers/globals.dm
@@ -1,9 +1,10 @@
+// See initialization order in /code/game/world.dm
GLOBAL_REAL(GLOB, /datum/controller/global_vars)
/datum/controller/global_vars
name = "Global Variables"
- var/list/gvars_datum_protected_varlist
+ var/static/list/gvars_datum_protected_varlist
var/list/gvars_datum_in_built_vars
var/list/gvars_datum_init_order
@@ -13,21 +14,29 @@ GLOBAL_REAL(GLOB, /datum/controller/global_vars)
GLOB = src
var/datum/controller/exclude_these = new
- gvars_datum_in_built_vars = exclude_these.vars + list("gvars_datum_protected_varlist", "gvars_datum_in_built_vars", "gvars_datum_init_order")
+ // I know this is dumb but the nested vars list hangs a ref to the datum. This fixes that
+ // I have an issue report open, lummox has not responded. It might be a FeaTuRE
+ // Sooo we gotta be dumb
+ var/list/controller_vars = exclude_these.vars.Copy()
+ controller_vars["vars"] = null
+ gvars_datum_in_built_vars = controller_vars + list(NAMEOF(src, gvars_datum_protected_varlist), NAMEOF(src, gvars_datum_in_built_vars), NAMEOF(src, gvars_datum_init_order))
+
+ ASYNC
+ qdel(exclude_these) //signal logging isn't ready
Initialize()
/datum/controller/global_vars/Destroy(force)
+ // This is done to prevent an exploit where admins can get around protected vars
+ SHOULD_CALL_PARENT(FALSE)
stack_trace("Some fucker qdel'd the global holder!")
if(!force)
return QDEL_HINT_LETMELIVE
-
gvars_datum_protected_varlist.Cut()
gvars_datum_in_built_vars.Cut()
GLOB = null
-
- return ..()
+ return QDEL_HINT_IWILLGC
/datum/controller/global_vars/stat_entry(msg)
msg += "Edit"
@@ -58,9 +67,9 @@ GLOBAL_REAL(GLOB, /datum/controller/global_vars)
/datum/controller/global_vars/Initialize()
gvars_datum_init_order = list()
- gvars_datum_protected_varlist = list("gvars_datum_protected_varlist" = TRUE)
+ gvars_datum_protected_varlist = list(NAMEOF(src, gvars_datum_protected_varlist) = TRUE)
var/list/global_procs = typesof(/datum/controller/global_vars/proc)
- var/expected_len = length(vars) - gvars_datum_in_built_vars.len
+ var/expected_len = length(vars) - length(gvars_datum_in_built_vars)
if(length(global_procs) != expected_len)
warning("Unable to detect all global initialization procs! Expected [expected_len] got [length(global_procs)]!")
if(length(global_procs))
@@ -68,9 +77,11 @@ GLOBAL_REAL(GLOB, /datum/controller/global_vars)
for(var/I in global_procs)
expected_global_procs -= replacetext("[I]", "InitGlobal", "")
log_world("Missing procs: [expected_global_procs.Join(", ")]")
+
for(var/I in global_procs)
var/start_tick = world.time
call(src, I)()
var/end_tick = world.time
if(end_tick - start_tick)
warning("Global [replacetext("[I]", "InitGlobal", "")] slept during initialization!")
+
diff --git a/code/controllers/master.dm b/code/controllers/master.dm
index b8ff39f8afed..2bae0ddaddbd 100644
--- a/code/controllers/master.dm
+++ b/code/controllers/master.dm
@@ -483,7 +483,7 @@ ADMIN_VERB(cmd_controller_view_ui, R_SERVER|R_DEBUG|R_VIEWRUNTIMES, "Controller
last_init_info = "([subsystem.name]): [message]"
if(result != SS_INIT_NO_MESSAGE)
- to_chat(world, span_danger("\[[subsystem.name]] [chat_message]"))
+ to_chat(world, span_danger("\[[subsystem.name]\] [chat_message]"))
log_world("\[[subsystem.name]] [message]")
diff --git a/code/controllers/subsystem/events.dm b/code/controllers/subsystem/events.dm
index 3cff1a54f735..2fd0198d6b56 100644
--- a/code/controllers/subsystem/events.dm
+++ b/code/controllers/subsystem/events.dm
@@ -1,3 +1,6 @@
+#define EVENTS_STAGE_EVENTS 1
+#define EVENTS_STAGE_CONTAINER 2
+
SUBSYSTEM_DEF(events)
name = "Events"
init_order = INIT_ORDER_EVENTS
@@ -6,6 +9,8 @@ SUBSYSTEM_DEF(events)
offline_implications = "Random events will no longer happen. No immediate action is needed."
cpu_display = SS_CPUDISPLAY_LOW
ss_id = "events"
+ var/list/current_run
+ var/stage = EVENTS_STAGE_EVENTS
// Report events at the end of the rouund
var/report_at_round_end = 0
@@ -35,13 +40,57 @@ SUBSYSTEM_DEF(events)
allEvents = subtypesof(/datum/event)
return SS_INIT_SUCCESS
-/datum/controller/subsystem/events/fire()
- for(var/datum/event/E as anything in active_events)
- E.process()
+/datum/controller/subsystem/events/fire(resumed)
+ switch(stage)
+ if(EVENTS_STAGE_EVENTS)
+ if(length(active_events))
+ fire_events(resumed)
+ else
+ stage = EVENTS_STAGE_CONTAINER
+ return
+
+ if(EVENTS_STAGE_CONTAINER)
+ fire_containers(resumed)
+
+/datum/controller/subsystem/events/proc/fire_events(resumed)
+ if(!resumed)
+ current_run = active_events.Copy()
+
+ var/list/cached_current_run = current_run
+ var/index = length(cached_current_run)
+
+ while(index > 0)
+ var/datum/event/event = cached_current_run[index]
+ if(QDELETED(event))
+ index--
+ continue
+ event.process()
+ if(MC_TICK_CHECK)
+ cached_current_run.Cut(index)
+ return
+ index--
- for(var/i = EVENT_LEVEL_MUNDANE to EVENT_LEVEL_MAJOR)
- var/datum/event_container/EC = event_containers[i]
- EC.process()
+ stage = EVENTS_STAGE_CONTAINER
+
+/datum/controller/subsystem/events/proc/fire_containers(resumed)
+ if(!resumed)
+ current_run = event_containers.Copy()
+
+ var/list/cached_current_run = current_run
+ var/index = length(cached_current_run)
+
+ while(index > 0)
+ var/datum/event_container/event = cached_current_run[index]
+ if(QDELETED(event))
+ index--
+ continue
+ event.process()
+ if(MC_TICK_CHECK)
+ cached_current_run.Cut(index)
+ return
+ index--
+
+ stage = EVENTS_STAGE_EVENTS
/datum/controller/subsystem/events/proc/event_complete(datum/event/E)
if(!E.event_meta) // datum/event is used here and there for random reasons, maintaining "backwards compatibility"
@@ -295,3 +344,6 @@ SUBSYSTEM_DEF(events)
EC.next_event = null
Interact(usr)
+
+#undef EVENTS_STAGE_EVENTS
+#undef EVENTS_STAGE_CONTAINER
diff --git a/code/controllers/subsystem/explosions.dm b/code/controllers/subsystem/explosions.dm
index f87c9897ca40..c548882c0175 100644
--- a/code/controllers/subsystem/explosions.dm
+++ b/code/controllers/subsystem/explosions.dm
@@ -233,13 +233,14 @@ SUBSYSTEM_DEF(explosions)
watch = start_watch()
/datum/explosion_data/Destroy()
- qdel(affected_turfs_queue)
+ QDEL_NULL(affected_turfs_queue)
LAZYCLEARLIST(cached_exp_block)
LAZYNULL(cached_exp_block)
LAZYCLEARLIST(cached_turf_exp_block)
LAZYNULL(cached_turf_exp_block)
LAZYCLEARLIST(cached_turf_vert_exp_block)
LAZYNULL(cached_turf_vert_exp_block)
+ epicenter = null
. = ..()
/datum/explosion_data/proc/clamp_ranges()
diff --git a/code/controllers/subsystem/garbage.dm b/code/controllers/subsystem/garbage.dm
index 012f65c9d7e5..34066ceae832 100644
--- a/code/controllers/subsystem/garbage.dm
+++ b/code/controllers/subsystem/garbage.dm
@@ -446,14 +446,13 @@ SUBSYSTEM_DEF(garbage)
#define REFSEARCH_RECURSE_LIMIT 64
/datum/proc/find_references(references_to_clear = INFINITY)
- running_find_references = type
- if(usr?.client)
+ if(usr && usr.client)
if(tgui_alert(usr,"Running this will lock everything up for about 5 minutes. Would you like to begin the search?", "Find References", list("Yes", "No")) != "Yes")
return
src.references_to_clear = references_to_clear
//this keeps the garbage collector from failing to collect objects being searched for in here
- SSgarbage.can_fire = 0
+ SSgarbage.can_fire = FALSE
_search_references()
//restart the garbage collector
@@ -461,13 +460,13 @@ SUBSYSTEM_DEF(garbage)
SSgarbage.update_nextfire(reset_time = TRUE)
/datum/proc/_search_references()
- log_gc("Beginning search for references to a [type], looking for [references_to_clear] refs.")
+ log_reftracker("Beginning search for references to a [type], looking for [references_to_clear] refs.")
var/starting_time = world.time
-
+ //Time to search the whole game for our ref
DoSearchVar(GLOB, "GLOB", starting_time) //globals
- log_gc("Finished searching globals")
- if(references_to_clear == 0)
+ log_reftracker("Finished searching globals")
+ if(src.references_to_clear == 0)
return
//Yes we do actually need to do this. The searcher refuses to read weird lists
@@ -477,43 +476,42 @@ SUBSYSTEM_DEF(garbage)
global_vars[key] = global.vars[key]
DoSearchVar(global_vars, "Native Global", starting_time)
- log_gc("Finished searching native globals")
-
- if(references_to_clear == 0)
+ log_reftracker("Finished searching native globals")
+ if(src.references_to_clear == 0)
return
- for(var/datum/thing in world) //atoms (don't beleive it's lies)
+ for(var/datum/thing in world) //atoms (don't beleive its lies)
DoSearchVar(thing, "World -> [thing.type]", starting_time)
- if(references_to_clear == 0)
+ if(src.references_to_clear == 0)
break
-
- log_gc("Finished searching atoms")
- if(references_to_clear == 0)
+ log_reftracker("Finished searching atoms")
+ if(src.references_to_clear == 0)
return
for(var/datum/thing) //datums
DoSearchVar(thing, "Datums -> [thing.type]", starting_time)
- if(references_to_clear == 0)
+ if(src.references_to_clear == 0)
break
-
- log_gc("Finished searching datums")
- if(references_to_clear == 0)
+ log_reftracker("Finished searching datums")
+ if(src.references_to_clear == 0)
return
+ //Warning, attempting to search clients like this will cause crashes if done on live. Watch yourself
+#ifndef REFERENCE_DOING_IT_LIVE
for(var/client/thing) //clients
DoSearchVar(thing, "Clients -> [thing.type]", starting_time)
- if(references_to_clear == 0)
+ if(src.references_to_clear == 0)
break
-
- log_gc("Finished searching clients")
- if(references_to_clear == 0)
+ log_reftracker("Finished searching clients")
+ if(src.references_to_clear == 0)
return
+#endif
- log_gc("Completed search for references to a [type].")
+ log_reftracker("Completed search for references to a [type].")
/datum/proc/DoSearchVar(potential_container, container_name, search_time, recursion_count, is_special_list)
if(recursion_count >= REFSEARCH_RECURSE_LIMIT)
- log_gc("Recursion limit reached. [container_name]")
+ log_reftracker("Recursion limit reached. [container_name]")
return
if(references_to_clear == 0)
@@ -531,6 +529,7 @@ SUBSYSTEM_DEF(garbage)
datum_container.last_find_references = search_time
var/list/vars_list = datum_container.vars
+
var/is_atom = FALSE
var/is_area = FALSE
if(isatom(datum_container))
@@ -538,9 +537,7 @@ SUBSYSTEM_DEF(garbage)
if(isarea(datum_container))
is_area = TRUE
for(var/varname in vars_list)
-
var/variable = vars_list[varname]
-
if(islist(variable))
//Fun fact, vis_locs don't count for references
if(varname == "vars" || (is_atom && (varname == "vis_locs" || varname == "overlays" || varname == "underlays" || varname == "filters" || varname == "verbs" || (is_area && varname == "contents"))))
@@ -561,19 +558,16 @@ SUBSYSTEM_DEF(garbage)
found_refs[varname] = TRUE
continue //End early, don't want these logging
else
- log_gc("Found [type] [text_ref(src)] in [datum_container.type]'s [datum_container.ref_search_details()] [varname] var. [container_name]")
+ log_reftracker("Found [type] [text_ref(src)] in [datum_container.type]'s [datum_container.ref_search_details()] [varname] var. [container_name]")
#else
- log_gc("Found [type] [text_ref(src)] in [datum_container.type]'s [datum_container.ref_search_details()] [varname] var. [container_name]")
+ log_reftracker("Found [type] [text_ref(src)] in [datum_container.type]'s [datum_container.ref_search_details()] [varname] var. [container_name]")
#endif
references_to_clear -= 1
if(references_to_clear == 0)
- log_gc("All references to [type] [text_ref(src)] found, exiting.")
+ log_reftracker("All references to [type] [text_ref(src)] found, exiting.")
return
continue
- if(islist(variable))
- DoSearchVar(variable, "[container_name] \ref[datum_container] -> [varname] (list)", recursive_limit - 1, search_time)
-
else if(islist(potential_container))
var/list/potential_cache = potential_container
for(var/element_in_list in potential_cache)
@@ -582,7 +576,7 @@ SUBSYSTEM_DEF(garbage)
if(length(element_in_list))
DoSearchVar(element_in_list, "[container_name] -> [element_in_list] (list)", search_time, recursion_count + 1)
//Check normal entrys
- if(element_in_list == src)
+ else if(element_in_list == src)
#ifdef REFERENCE_TRACKING_DEBUG
if(SSgarbage.should_save_refs)
if(!found_refs)
@@ -590,10 +584,11 @@ SUBSYSTEM_DEF(garbage)
found_refs[potential_cache] = TRUE
continue
else
- log_gc("Found [type] [text_ref(src)] in list [container_name].")
+ log_reftracker("Found [type] [text_ref(src)] in list [container_name].")
#else
- log_gc("Found [type] [text_ref(src)] in list [container_name].")
+ log_reftracker("Found [type] [text_ref(src)] in list [container_name].")
#endif
+
// This is dumb as hell I'm sorry
// I don't want the garbage subsystem to count as a ref for the purposes of this number
// If we find all other refs before it I want to early exit, and if we don't I want to keep searching past it
@@ -604,11 +599,11 @@ SUBSYSTEM_DEF(garbage)
ignore_ref = TRUE
break
if(ignore_ref)
- log_gc("[container_name] does not count as a ref for our count")
+ log_reftracker("[container_name] does not count as a ref for our count")
else
references_to_clear -= 1
if(references_to_clear == 0)
- log_gc("All references to [type] [text_ref(src)] found, exiting.")
+ log_reftracker("All references to [type] [text_ref(src)] found, exiting.")
return
if(!isnum(element_in_list) && !is_special_list)
@@ -629,18 +624,18 @@ SUBSYSTEM_DEF(garbage)
found_refs[potential_cache] = TRUE
continue
else
- log_gc("Found [type] [text_ref(src)] in list [container_name]\[[element_in_list]\]")
+ log_reftracker("Found [type] [text_ref(src)] in list [container_name]\[[element_in_list]\]")
#else
- log_gc("Found [type] [text_ref(src)] in list [container_name]\[[element_in_list]\]")
+ log_reftracker("Found [type] [text_ref(src)] in list [container_name]\[[element_in_list]\]")
#endif
references_to_clear -= 1
if(references_to_clear == 0)
- log_gc("All references to [type] [text_ref(src)] found, exiting.")
+ log_reftracker("All references to [type] [text_ref(src)] found, exiting.")
return
catch
// So if it goes wrong we kill it
is_special_list = TRUE
- log_gc("Curiosity: [container_name] lead to an error when acessing [element_in_list], what is it?")
+ log_reftracker("Curiosity: [container_name] lead to an error when acessing [element_in_list], what is it?")
#undef REFSEARCH_RECURSE_LIMIT
@@ -655,4 +650,13 @@ ADMIN_VERB(qdel_then_find_references, R_DEBUG, "qdel() then Find References", "q
ADMIN_VERB(qdel_then_if_fail_find_references, R_DEBUG, "qdel() then Find References if GC failure", "qdel() then Find References if GC failure", ADMIN_CATEGORY_DEBUG, datum/target in world)
qdel_and_find_ref_if_fail(target, TRUE)
+// Kept outside the ifdef so overrides are easy to implement
+
+/// Return info about us for reference searching purposes
+/// Will be logged as a representation of this datum if it's a part of a search chain
+/datum/proc/ref_search_details()
+ return text_ref(src)
+
+/datum/callback/ref_search_details()
+ return "[text_ref(src)] (obj: [object] proc: [delegate] args: [json_encode(arguments)] user: [user?.resolve() || "null"])"
#endif
diff --git a/code/controllers/subsystem/http.dm b/code/controllers/subsystem/http.dm
index bd31fbc542a7..2601a1236b69 100644
--- a/code/controllers/subsystem/http.dm
+++ b/code/controllers/subsystem/http.dm
@@ -14,6 +14,8 @@ SUBSYSTEM_DEF(http)
var/logging_errors_only = TRUE
/// Total requests the SS has processed in a round
var/total_requests
+ var/list/current_run
+ var/current_index
/datum/controller/subsystem/http/PreInit()
. = ..()
@@ -23,8 +25,15 @@ SUBSYSTEM_DEF(http)
return "P: [length(active_async_requests)] | T: [total_requests]"
/datum/controller/subsystem/http/fire(resumed)
- for(var/r in active_async_requests)
- var/datum/http_request/req = r
+ if(!resumed)
+ current_run = active_async_requests.Copy()
+ current_index = 1
+
+ var/list/cached_current_run = current_run
+ var/length = length(cached_current_run)
+ var/index = current_index
+ while(index <= length)
+ var/datum/http_request/req = cached_current_run[index]
// Check if we are complete
if(req.is_complete())
// If so, take it out the processing list
@@ -38,7 +47,8 @@ SUBSYSTEM_DEF(http)
// And log the result
if(logging_enabled)
if(logging_errors_only && (!res.errored || res.status_code != 200))
- return
+ index++
+ continue
var/list/log_data = list()
log_data += "BEGIN ASYNC REQUEST (ID: [req.id])"
log_data += "\t[uppertext(req.method)] [req.url]"
@@ -56,6 +66,10 @@ SUBSYSTEM_DEF(http)
log_data += "\tResponse headers: [json_encode(res.headers)]"
log_data += "END ASYNC RESPONSE (ID: [req.id])"
WRITE_LOG(GLOB.http_log, replacetext_char(log_data.Join("\n[GLOB.log_end]"), CONFIG_GET(string/tts_token_silero), "TOKEN"))
+ index++
+ if(MC_TICK_CHECK)
+ current_index = index
+ return
/**
* Async request creator
diff --git a/code/controllers/subsystem/jobs.dm b/code/controllers/subsystem/jobs.dm
index ee73158edc16..4c93dc711ec7 100644
--- a/code/controllers/subsystem/jobs.dm
+++ b/code/controllers/subsystem/jobs.dm
@@ -16,7 +16,7 @@ SUBSYSTEM_DEF(jobs)
/// List of jobs set to priority by HoP/Captain
var/list/prioritized_jobs = list()
/// List of all job transfer records
- var/list/id_change_records = list()
+ var/alist/id_change_records = alist()
var/id_change_counter = 1
//Players who need jobs
var/list/unassigned = list()
@@ -826,7 +826,7 @@ SUBSYSTEM_DEF(jobs)
return jobs_to_formats
/datum/controller/subsystem/jobs/proc/log_job_transfer(transferee, oldvalue, newvalue, whodidit, reason)
- id_change_records["[id_change_counter]"] = list(
+ id_change_records[id_change_counter] = list(
"transferee" = transferee,
"oldvalue" = oldvalue,
"newvalue" = newvalue,
@@ -904,14 +904,14 @@ SUBSYSTEM_DEF(jobs)
. = 0
if(!sourceuser)
return
- var/list/new_id_change_records = list()
+ var/alist/new_id_change_records = alist()
for(var/thisid in id_change_records)
var/thisrecord = id_change_records[thisid]
if(!thisrecord["deletedby"])
if(delete_all || thisrecord["whodidit"] == sourceuser)
thisrecord["deletedby"] = sourceuser
.++
- new_id_change_records["[id_change_counter]"] = thisrecord
+ new_id_change_records[id_change_counter] = thisrecord
id_change_counter++
id_change_records = new_id_change_records
diff --git a/code/controllers/subsystem/non-firing/radio.dm b/code/controllers/subsystem/non-firing/radio.dm
index d348c2922933..7ec50cb8d293 100644
--- a/code/controllers/subsystem/non-firing/radio.dm
+++ b/code/controllers/subsystem/non-firing/radio.dm
@@ -40,6 +40,11 @@ SUBSYSTEM_DEF(radio)
// This is a disgusting hack to stop this tripping CI when this thing needs to FUCKING DIE
/datum/controller/subsystem/radio/Initialize()
+ for(var/name,new_frequency in radiochannels)
+ var/f_text = num2text(new_frequency)
+ var/datum/radio_frequency/frequency = new
+ frequency.frequency = new_frequency
+ frequencies[f_text] = frequency
return SS_INIT_SUCCESS
// This is fucking disgusting and needs to die
@@ -107,6 +112,7 @@ SUBSYSTEM_DEF(radio)
if(!frequency)
frequency = new
+ frequency.custom = TRUE
frequency.frequency = new_frequency
frequencies[f_text] = frequency
@@ -125,7 +131,7 @@ SUBSYSTEM_DEF(radio)
frequency.remove_listener(device)
remove_radio(device, old_frequency)
- if(length(frequency.devices) != 0)
+ if(!frequency.custom || length(frequency.devices) != 0)
return 1
qdel(frequency)
diff --git a/code/controllers/subsystem/spatial_gridmap.dm b/code/controllers/subsystem/spatial_gridmap.dm
index acdef9ade38e..63b516193037 100644
--- a/code/controllers/subsystem/spatial_gridmap.dm
+++ b/code/controllers/subsystem/spatial_gridmap.dm
@@ -640,7 +640,7 @@ SUBSYSTEM_DEF(spatial_grid)
var/x_cell_count = world.maxx / SPATIAL_GRID_CELLSIZE
var/y_cell_count = world.maxy / SPATIAL_GRID_CELLSIZE
- var/total_cells = x_cell_count ** 2
+ var/total_cells = POW2(x_cell_count)
var/average_clients_per_cell = 0
var/average_hearables_per_cell = 0
diff --git a/code/controllers/subsystem/timer.dm b/code/controllers/subsystem/timer.dm
index 968c9e4d1c2a..622d6559111f 100644
--- a/code/controllers/subsystem/timer.dm
+++ b/code/controllers/subsystem/timer.dm
@@ -437,7 +437,8 @@ SUBSYSTEM_DEF(timer)
if(callBack?.object && callBack.object != GLOBAL_PROC && callBack.object.active_timers)
callBack.object.active_timers -= src
UNSETEMPTY(callBack.object.active_timers)
-
+ callBack.object = null
+ LAZYCLEARLIST(callBack?.arguments)
callBack = null
if(flags & TIMER_STOPPABLE)
diff --git a/code/datums/actions/action.dm b/code/datums/actions/action.dm
index f84ed5c1742a..793dd5e6fdcf 100644
--- a/code/datums/actions/action.dm
+++ b/code/datums/actions/action.dm
@@ -404,7 +404,7 @@
if(action == src) // This could be us, which is dumb
continue
var/atom/movable/screen/movable/action_button/button = action.viewers[owner.hud_used]
- if(action.name == name && button.id)
+ if(action.name == name && button?.id)
bitfield |= button.id
bitfield = ~bitfield // Flip our possible ids, so we can check if we've found a unique one
diff --git a/code/datums/actions/item_action.dm b/code/datums/actions/item_action.dm
index 82fc1974a941..2e07a4a70ba0 100644
--- a/code/datums/actions/item_action.dm
+++ b/code/datums/actions/item_action.dm
@@ -494,7 +494,7 @@
var/charge_max = 100 //recharge time in deciseconds if charge_type = "recharge" or "toggle_recharge", alternatively counts as starting charges if charge_type = "charges"
var/charge_counter = 0 //can only use if it equals "recharge" or "toggle_recharge", ++ each decisecond if charge_type = "recharge" or -- each cast if charge_type = "charges"
var/starts_charged = TRUE //Does this action start ready to go?
- var/still_recharging_msg = span_notice(" действие всё ещё перезаряжается.")
+ var/still_recharging_msg = span_notice_alt(" действие всё ещё перезаряжается.")
//toggle and toggle_recharge stuff
var/action_ready = TRUE //Only for toggle and toggle_recharge charge_type. Toggle it via code yourself. Haha 'toggle', get it?
var/icon_state_active = "bg_default_on" //What icon_state we switch to when we toggle action active in "toggle" actions
diff --git a/code/datums/armor.dm b/code/datums/armor.dm
index 5f228025453a..00d542524e43 100644
--- a/code/datums/armor.dm
+++ b/code/datums/armor.dm
@@ -1,11 +1,16 @@
#define ARMORID "armor-[melee]-[bullet]-[laser]-[energy]-[bomb]-[bio]-[rad]-[fire]-[acid]-[magic]"
/// Assosciative list of type -> armor. Used to ensure we always hold a reference to default armor datums
GLOBAL_LIST_INIT(armor_by_type, generate_armor_type_cache())
+GLOBAL_LIST_EMPTY(armor_cache)
/proc/getArmor(melee = 0, bullet = 0, laser = 0, energy = 0, bomb = 0, bio = 0, rad = 0, fire = 0, acid = 0, magic = 0)
- . = locate(ARMORID)
+ var/armor_id = ARMORID
+ var/list/cached_armor_cache = GLOB.armor_cache
+ . = cached_armor_cache[armor_id]
if(!.)
- . = new /datum/armor(melee, bullet, laser, energy, bomb, bio, rad, fire, acid, magic)
+ var/datum/armor/new_armor = new (melee, bullet, laser, energy, bomb, bio, rad, fire, acid, magic)
+ cached_armor_cache[armor_id] = new_armor
+ . = new_armor
/proc/generate_armor_type_cache()
var/list/armor_cache = list()
@@ -27,10 +32,11 @@ GLOBAL_LIST_INIT(armor_by_type, generate_armor_type_cache())
/// Sets the armor of this atom to the specified armor
/obj/proc/set_armor(datum/armor/armor)
- if(src.armor == armor)
+ var/datum/armor/obj_armor = src.armor
+ if(obj_armor == armor)
return
- if(!(src.armor?.type in GLOB.armor_by_type))
- qdel(src.armor)
+ if(obj_armor && !((obj_armor.type in GLOB.armor_by_type) || (obj_armor.tag in GLOB.armor_cache)))
+ qdel(obj_armor)
src.armor = ispath(armor) ? get_armor_by_type(armor) : armor
/datum/armor
@@ -58,6 +64,13 @@ GLOBAL_LIST_INIT(armor_by_type, generate_armor_type_cache())
magic = magic_value || magic || 0
tag = ARMORID
+/datum/armor/Destroy(force)
+ GLOB.armor_cache -= tag
+ GLOB.armor_by_type -= type
+ tag = null
+ . = ..()
+
+
/datum/armor/proc/modifyRating(melee_value = 0, bullet_value = 0, laser_value = 0, energy_value = 0, bomb_value = 0, bio_value = 0, rad_value = 0, fire_value = 0, acid_value = 0, magic_value = 0)
return getArmor(melee + melee_value, bullet + bullet_value, laser + laser_value, energy + energy_value, bomb + bomb_value, bio + bio_value, rad + rad_value, fire + fire_value, acid + acid_value, magic + magic_value)
diff --git a/code/datums/beam.dm b/code/datums/beam.dm
index ab9d5b53009d..7aff3841c6b1 100644
--- a/code/datums/beam.dm
+++ b/code/datums/beam.dm
@@ -109,7 +109,9 @@
/datum/beam/Destroy()
QDEL_LIST(elements)
- QDEL_NULL(visuals)
+ if(visuals)
+ visuals.vis_contents.Cut()
+ QDEL_NULL(visuals)
UnregisterSignal(origin, COMSIG_MOVABLE_MOVED)
UnregisterSignal(target, COMSIG_MOVABLE_MOVED)
target = null
@@ -192,6 +194,19 @@
owner = beam_owner
return ..()
+/obj/effect/ebeam/Destroy()
+ if(owner)
+ if(owner.elements)
+ owner.elements -= src
+ if(owner.visuals == src)
+ owner.visuals = null
+ owner = null
+
+ vis_contents.Cut()
+ transform = null
+ color = null
+ return ..()
+
/obj/effect/ebeam/update_overlays()
. = ..()
if(!emissive)
@@ -201,10 +216,6 @@
emissive_overlay.alpha = alpha
. += emissive_overlay
-/obj/effect/ebeam/Destroy()
- owner = null
- return ..()
-
/obj/effect/ebeam/singularity_pull()
return
diff --git a/code/datums/components/deadchat_control.dm b/code/datums/components/deadchat_control.dm
index 1de81f176fa0..2bf9091a65ac 100644
--- a/code/datums/components/deadchat_control.dm
+++ b/code/datums/components/deadchat_control.dm
@@ -205,7 +205,7 @@
return
if(!(user in orbiters))
- examine_list += span_deadsay(span_bold("Прыгнете на н[GEND_HIS_HER(object)]] и осмотрите снова, чтобы увидеть список доступных команд."))
+ examine_list += span_deadsay(span_bold("Прыгнете на н[GEND_HIS_HER(object)] и осмотрите снова, чтобы увидеть список доступных команд."))
return
var/input_cooldown_s = input_cooldown * 0.1
diff --git a/code/datums/components/pellet_cloud.dm b/code/datums/components/pellet_cloud.dm
index d93770de6405..4758eb11c81b 100644
--- a/code/datums/components/pellet_cloud.dm
+++ b/code/datums/components/pellet_cloud.dm
@@ -169,35 +169,37 @@
var/list/martyrs = list()
var/self_harm_radius_mult = 3
+ var/cached_radius = radius
if(punishable_triggerer && prob(60))
to_chat(punishable_triggerer, span_userdanger("Your plan to whack someone with a grenade on a stick backfires on you, literally!"))
- self_harm_radius_mult = 1 // we'll still give the guy who got hit some extra shredding, but not 3*radius
- pellet_delta += radius
- for(var/i in 1 to radius)
+ self_harm_radius_mult = 1 // we'll still give the guy who got hit some extra shredding, but not 3*cached_radius
+ pellet_delta += cached_radius
+ for(var/i in 1 to cached_radius)
pew(punishable_triggerer) // thought you could be tricky and lance someone with no ill effects!!
for(var/mob/living/body in get_turf(parent))
if(body == shooter)
- pellet_delta += radius * self_harm_radius_mult
- for(var/i in 1 to radius * self_harm_radius_mult)
+ pellet_delta += cached_radius * self_harm_radius_mult
+ for(var/i in 1 to cached_radius * self_harm_radius_mult)
pew(body) // free shrapnel if it goes off in your hand, and it doesn't even count towards the absorbed. fun!
else if(!(body in bodies))
martyrs += body // promoted from a corpse to a hero
for(var/M in martyrs)
var/mob/living/martyr = M
- if(radius > 4)
+ if(cached_radius > 4)
martyr.visible_message("[span_danger("[martyr] heroically covers \the [parent] with [martyr.p_their()] body, absorbing a load of the shrapnel!")]", span_userdanger("You heroically cover \the [parent] with your body, absorbing a load of the shrapnel!"))
- magnitude_absorbed += round(radius * 0.5)
- else if(radius >= 2)
+ magnitude_absorbed += round(cached_radius * 0.5)
+ else if(cached_radius >= 2)
martyr.visible_message("[span_danger("[martyr] heroically covers \the [parent] with [martyr.p_their()] body, absorbing some of the shrapnel!")]", span_userdanger("You heroically cover \the [parent] with your body, absorbing some of the shrapnel!"))
magnitude_absorbed += 2
else
martyr.visible_message("[span_danger("[martyr] heroically covers \the [parent] with [martyr.p_their()] body, snuffing out the shrapnel!")]", span_userdanger("You heroically cover \the [parent] with your body, snuffing out the shrapnel!"))
- magnitude_absorbed = radius
-
- var/pellets_absorbed = (radius ** 2) - ((radius - magnitude_absorbed - 1) ** 2)
+ magnitude_absorbed = cached_radius
+
+ var/remaining_buffer = cached_radius - magnitude_absorbed - 1
+ var/pellets_absorbed = (POW2(cached_radius)) - POW2(remaining_buffer)
radius -= magnitude_absorbed
pellet_delta -= round(pellets_absorbed * 0.5)
diff --git a/code/datums/diseases/viruses/advance/symptoms/limb_throw.dm b/code/datums/diseases/viruses/advance/symptoms/limb_throw.dm
index aa0c21eb0843..b289cae7e922 100644
--- a/code/datums/diseases/viruses/advance/symptoms/limb_throw.dm
+++ b/code/datums/diseases/viruses/advance/symptoms/limb_throw.dm
@@ -38,8 +38,8 @@ Limb Rejection
need_active_overlay = TRUE
invocation = ""
- selection_activated_message = span_notice("Вы готовитесь бросить конечность!! ЛКМ, чтобы бросить в цель!")
- selection_deactivated_message = span_notice("Вы решили не бросать конечность... пока что.")
+ selection_activated_message = span_notice_alt("Вы готовитесь бросить конечность!! ЛКМ, чтобы бросить в цель!")
+ selection_deactivated_message = span_notice_alt("Вы решили не бросать конечность... пока что.")
action_icon_state = "limb_throw"
action_background_icon_state = "bg_changeling"
diff --git a/code/datums/diseases/viruses/transformation.dm b/code/datums/diseases/viruses/transformation.dm
index 3755400fd025..7be92a4bd70c 100644
--- a/code/datums/diseases/viruses/transformation.dm
+++ b/code/datums/diseases/viruses/transformation.dm
@@ -92,8 +92,8 @@
stage1 = null
stage2 = null
stage3 = null
- stage4 = list(span_warning("Ваша спина болит."), span_warning("Вы дышите через рот."), span_warning("У вас возникает тяга к бананам."), span_warning("Ваш разум затуманен."))
- stage5 = list(span_warning("Вам хочется вести себя как обезьяна."))
+ stage4 = list(span_warning_alt("Ваша спина болит."),span_warning_alt("Вы дышите через рот."), span_warning_alt("У вас возникает тяга к бананам."), span_warning_alt("Ваш разум затуманен."))
+ stage5 = list(span_warning_alt("Вам хочется вести себя как обезьяна."))
new_form = /mob/living/carbon/human/lesser/monkey
/datum/disease/virus/transformation/jungle_fever/do_disease_transformation()
@@ -137,10 +137,10 @@
cure_prob = 5
is_new_mind = TRUE
stage1 = null
- stage2 = list(span_notice("Ваши суставы кажутся скованными."), span_danger("Бип... буп..."))
- stage3 = list(span_danger("Ваши суставы кажутся очень скованными."), span_notice("Ваша кожа кажется дряблой."), span_danger("Вы чувствуете, как что-то движется... внутри."))
- stage4 = list(span_danger("Ваша кожа кажется очень дряблой."), span_danger("Вы чувствуете... что-то... внутри вас."))
- transform_message = list(span_danger("Ваша кожа будто вот-вот лопнет!"))
+ stage2 = list(span_notice_alt("Ваши суставы кажутся скованными."), span_danger_alt("Бип... буп..."))
+ stage3 = list(span_danger_alt("Ваши суставы кажутся очень скованными."), span_notice_alt("Ваша кожа кажется дряблой."), span_danger_alt("Вы чувствуете, как что-то движется... внутри."))
+ stage4 = list(span_danger_alt("Ваша кожа кажется очень дряблой."), span_danger_alt("Вы чувствуете... что-то... внутри вас."))
+ transform_message = list(span_danger_alt("Ваша кожа будто вот-вот лопнет!"))
new_form = /mob/living/silicon/robot
/datum/disease/virus/transformation/robot/stage_act()
@@ -166,10 +166,10 @@
severity = DISEASE_SEVERITY_BIOHAZARD
cure_prob = 5
stage1 = null
- stage2 = list("Ваше горло першит.", span_danger("Убить..."))
- stage3 = list(span_danger("Ваше горло сильно першит."), "Ваша кожа кажется тугой.", span_danger("Вы чувствуете, как что-то движется... внутри."))
- stage4 = list(span_danger("Ваша кожа кажется очень тугой."), span_danger("Ваша кровь кипит!"), span_danger("Вы чувствуете... что-то... внутри вас."))
- transform_message = list(span_danger(span_fontsize5("Теперь вы ксеноморф.") + "\n\
+ stage2 = list("Ваше горло першит.", span_danger_alt("Убить..."))
+ stage3 = list(span_danger_alt("Ваше горло сильно першит."), "Ваша кожа кажется тугой.", span_danger_alt("Вы чувствуете, как что-то движется... внутри."))
+ stage4 = list(span_danger_alt("Ваша кожа кажется очень тугой."), span_danger_alt("Ваша кровь кипит!"), span_danger_alt("Вы чувствуете... что-то... внутри вас."))
+ transform_message = list(span_danger_alt(span_fontsize5_alt("Теперь вы ксеноморф.") + "\n\
Вы чувствуете боль от превращения! Вы желаете укусить того, кто с вами это сделал, благо, память вас не покинула и вы всё помните."))
new_form = null
@@ -192,7 +192,7 @@
/datum/disease/virus/transformation/xeno/phantom
name = "dangerous xenomorph transformation"
- transform_message = list(span_danger(span_fontsize5("Теперь вы ксеноморф.") + "\n\
+ transform_message = list(span_danger_alt(span_fontsize5_alt("Теперь вы ксеноморф.") + "\n\
Вы чувствуете боль от превращения! Вы утратили всю память и первобытная жажда убийства охватила вас!"))
/datum/disease/virus/transformation/xeno/phantom/New()
@@ -215,11 +215,11 @@
desc = "Этот высококонцентрированный экстракт превращает всё в большее количество себя."
cures = list("frostoil")
cure_prob = 80
- stage1 = list(span_notice("Вы чувствуете себя не очень хорошо."))
- stage2 = list(span_notice("Ваша кожа кажется немного скользкой."))
- stage3 = list(span_danger("Ваши конечности тают."), span_danger("Ваши конечности начинают терять форму."))
- stage4 = list(span_danger("Вы превращаетесь в слайма."))
- transform_message = list(span_danger("Вы превратились в слайма."))
+ stage1 = list(span_notice_alt("Вы чувствуете себя не очень хорошо."))
+ stage2 = list(span_notice_alt("Ваша кожа кажется немного скользкой."))
+ stage3 = list(span_danger_alt("Ваши конечности тают."), span_danger_alt("Ваши конечности начинают терять форму."))
+ stage4 = list(span_danger_alt("Вы превращаетесь в слайма."))
+ transform_message = list(span_danger_alt("Вы превратились в слайма."))
new_form = /mob/living/simple_animal/slime/random
/datum/disease/virus/transformation/slime/stage_act()
@@ -243,11 +243,11 @@
cure_text = "Смерть"
cures = list("adminordrazine")
severity = DISEASE_SEVERITY_UNCURABLE
- stage1 = list(span_notice("ГАВ."))
- stage2 = list(span_notice("Вам хочется надеть глупую шляпу."))
- stage3 = list(span_danger("Нужно... съесть... шоколад...."), span_danger("ТЯФ"))
- stage4 = list(span_danger("Видения стиральных машин атакуют ваш разум!"))
- transform_message = list(span_danger("АУУУУУУ!!!"))
+ stage1 = list(span_notice_alt("ГАВ."))
+ stage2 = list(span_notice_alt("Вам хочется надеть глупую шляпу."))
+ stage3 = list(span_danger_alt("Нужно... съесть... шоколад...."), span_danger_alt("ТЯФ"))
+ stage4 = list(span_danger_alt("Видения стиральных машин атакуют ваш разум!"))
+ transform_message = list(span_danger_alt("АУУУУУУ!!!"))
new_form = /mob/living/simple_animal/pet/dog/corgi
is_new_mind = TRUE
@@ -270,11 +270,11 @@
cures = list("adminordrazine")
severity = DISEASE_SEVERITY_UNCURABLE
stage_prob = 20
- stage1 = list(span_notice("Ваш желудок урчит."))
- stage2 = list(span_notice("Ваша кожа кажется обвисшей."))
- stage3 = list(span_danger("Ваши конечности тают."), span_danger("Ваши конечности начинают терять форму."))
- stage4 = list(span_danger("Вы ненасытны!"))
- transform_message = list(span_danger(span_fontsize5("ТЕПЕРЬ ВЫ МОРФ!") + "\n\
+ stage1 = list(span_notice_alt("Ваш желудок урчит."))
+ stage2 = list(span_notice_alt("Ваша кожа кажется обвисшей."))
+ stage3 = list(span_danger_alt("Ваши конечности тают."), span_danger_alt("Ваши конечности начинают терять форму."))
+ stage4 = list(span_danger_alt("Вы ненасытны!"))
+ transform_message = list(span_danger_alt(span_fontsize5_alt("ТЕПЕРЬ ВЫ МОРФ!") + "\n\
Хоть Вы и трансформировались в отвратительную зелёную жижу, но это не повлияло на Ваше сознание \
и память. Вы не являетесь антагонистом."))
new_form = /mob/living/simple_animal/hostile/morph
@@ -286,11 +286,11 @@
cure_text = "Смерть"
cures = list("adminordrazine")
severity = DISEASE_SEVERITY_UNCURABLE
- stage1 = list(span_notice("ХРЮ."))
- stage2 = list(span_notice("Вам хочется валяться в грязи."))
- stage3 = list(span_danger("Нужно... валяться... в грязи...."), span_danger("ХРЮ"))
- stage4 = list(span_danger("Видения грязевых луж атакуют ваш разум!"))
- transform_message = list(span_danger("ХРЮЮЮЮЮ!!!"))
+ stage1 = list(span_notice_alt("ХРЮ."))
+ stage2 = list(span_notice_alt("Вам хочется валяться в грязи."))
+ stage3 = list(span_danger_alt("Нужно... валяться... в грязи...."), span_danger_alt("ХРЮ"))
+ stage4 = list(span_danger_alt("Видения грязевых луж атакуют ваш разум!"))
+ transform_message = list(span_danger_alt("ХРЮЮЮЮЮ!!!"))
new_form = /mob/living/simple_animal/pig
is_new_mind = TRUE
diff --git a/code/datums/dog_fashion.dm b/code/datums/dog_fashion.dm
index 2f2e18e99ad0..9fdf6eaad704 100644
--- a/code/datums/dog_fashion.dm
+++ b/code/datums/dog_fashion.dm
@@ -31,14 +31,14 @@
D.name = name
if(desc)
D.desc = desc
- if(emote_see)
- D.emote_see = emote_see
- if(emote_hear)
- D.emote_hear = emote_hear
- if(speak)
- D.speak = speak
- if(speak_emote)
- D.speak_emote = speak_emote
+ if(LAZYLEN(emote_see))
+ D.emote_see = string_list(emote_see)
+ if(LAZYLEN(emote_hear))
+ D.emote_hear = string_list(emote_hear)
+ if(LAZYLEN(speak))
+ D.speak = string_list(speak)
+ if(LAZYLEN(speak_emote))
+ D.speak_emote = string_list(speak_emote)
/datum/dog_fashion/proc/get_overlay(dir)
if(icon_file && obj_icon_state)
diff --git a/code/datums/helper_datums/construction_datum.dm b/code/datums/helper_datums/construction_datum.dm
index 55b391865e67..e9b9426d7ac4 100644
--- a/code/datums/helper_datums/construction_datum.dm
+++ b/code/datums/helper_datums/construction_datum.dm
@@ -10,11 +10,15 @@
..()
holder = atom
if(!holder) //don't want this without a holder
- spawn
- qdel(src)
+ qdel(src)
+ return
set_desc(length(steps))
return
+/datum/construction/Destroy(force)
+ holder = null
+ . = ..()
+
/datum/construction/proc/next_step(mob/user as mob)
steps.len--
if(!length(steps))
@@ -64,7 +68,7 @@
return 1
/datum/construction/proc/check_all_steps(atom/used_atom,mob/user as mob) //check all steps, remove matching one.
- for(var/i=1;i<=length(steps);i++)
+ for(var/i in 1 to length(steps))
var/list/L = steps[i]
if(do_tool_or_atom_check(used_atom, L["key"]) && custom_action(i, used_atom, user))
steps[i]=null;//stupid byond list from list removal...
diff --git a/code/datums/hud.dm b/code/datums/hud.dm
index c7bea3227f3d..ddb3fcffe77c 100644
--- a/code/datums/hud.dm
+++ b/code/datums/hud.dm
@@ -82,6 +82,9 @@ GLOBAL_LIST_INIT(huds, list( \
hud_atoms += list(list())
hud_users += list(list())
+ if(LAZYLEN(hud_icons))
+ hud_icons = string_list(hud_icons)
+
RegisterSignal(SSdcs, COMSIG_GLOB_NEW_Z, PROC_REF(add_z_level_huds))
if(uses_global_hud_category)
@@ -249,6 +252,9 @@ GLOBAL_LIST_INIT(huds, list( \
var/turf/atom_turf = get_turf(hud_atom_to_remove)
if(!atom_turf)
+ for(var/z, list in hud_atoms)
+ var/list/huds_list = list
+ LAZYREMOVE(huds_list, hud_atom_to_remove)
return TRUE
hud_atoms[atom_turf.z] -= hud_atom_to_remove
diff --git a/code/datums/position_point_vector.dm b/code/datums/position_point_vector.dm
index 851bd67d9c63..79b86fc8037c 100644
--- a/code/datums/position_point_vector.dm
+++ b/code/datums/position_point_vector.dm
@@ -6,7 +6,9 @@
return P
/proc/pixel_length_between_points(datum/point_precise/a, datum/point_precise/b)
- return sqrt(((b.x - a.x) ** 2) + ((b.y - a.y) ** 2))
+ var/dx = (b.x - a.x)
+ var/dy = (b.y - a.y)
+ return MAGNITUDE(dx, dy)
/proc/angle_between_points(datum/point_precise/a, datum/point_precise/b)
return ATAN2((b.y - a.y), (b.x - a.x))
diff --git a/code/datums/proximity_monitor/proximity_monitor.dm b/code/datums/proximity_monitor/proximity_monitor.dm
index 55e29b9d88ae..bb6c2e8914e0 100644
--- a/code/datums/proximity_monitor/proximity_monitor.dm
+++ b/code/datums/proximity_monitor/proximity_monitor.dm
@@ -23,6 +23,12 @@
current_range = range
set_host(_host)
+/datum/proximity_monitor/Destroy()
+ host?.proximity_monitor = null
+ host = null
+ hasprox_receiver = null
+ return ..()
+
/datum/proximity_monitor/proc/set_host(atom/new_host, atom/new_receiver)
if(new_host == host)
return
@@ -52,11 +58,6 @@
qdel(src)
-/datum/proximity_monitor/Destroy()
- host = null
- hasprox_receiver = null
- return ..()
-
/datum/proximity_monitor/proc/set_range(range, force_rebuild = FALSE)
if(!force_rebuild && range == current_range)
return FALSE
diff --git a/code/datums/radio.dm b/code/datums/radio.dm
index f7b6009851d6..0147bfac47a6 100644
--- a/code/datums/radio.dm
+++ b/code/datums/radio.dm
@@ -25,6 +25,7 @@ GLOBAL_LIST_EMPTY(all_radios)
/datum/radio_frequency
var/frequency as num
var/list/obj/devices = list()
+ var/custom = FALSE
/datum/radio_frequency/proc/post_signal(obj/source as obj|null, datum/signal/signal, filter = null as text|null, range = null as num|null)
var/turf/start_point
diff --git a/code/datums/spell.dm b/code/datums/spell.dm
index 573da409c207..8118e304acf6 100644
--- a/code/datums/spell.dm
+++ b/code/datums/spell.dm
@@ -90,7 +90,7 @@ GLOBAL_LIST_INIT(spells, typesof(/obj/effect/proc_holder/spell))
/// Whether an ability should start cooldown after cast or not.
var/should_recharge_after_cast = TRUE
/// Messace user get when clicks on rechargins spell button.
- var/still_recharging_msg = span_notice("The spell is still recharging.")
+ var/still_recharging_msg = span_notice_alt("The spell is still recharging.")
/// Spell can only be cast with special wizard garb, equipped in appropriete slots.
var/clothes_req = TRUE
@@ -163,9 +163,9 @@ GLOBAL_LIST_INIT(spells, typesof(/obj/effect/proc_holder/spell))
var/gain_desc = null
/// The message displayed when a click based spell gets activated
- var/selection_activated_message = span_notice("Click on a target to cast the spell.")
+ var/selection_activated_message = span_notice_alt("Click on a target to cast the spell.")
/// The message displayed when a click based spell gets deactivated
- var/selection_deactivated_message = span_notice("You choose to not cast this spell.")
+ var/selection_deactivated_message = span_notice_alt("You choose to not cast this spell.")
/// does this spell generate attack logs?
var/create_attack_logs = TRUE
diff --git a/code/datums/spells/alien_spells/corrosive_acid_spit.dm b/code/datums/spells/alien_spells/corrosive_acid_spit.dm
index 4b4177b498f5..b6e568b95a28 100644
--- a/code/datums/spells/alien_spells/corrosive_acid_spit.dm
+++ b/code/datums/spells/alien_spells/corrosive_acid_spit.dm
@@ -3,8 +3,8 @@
desc = "Spit acid on someone in range, this acid melts through nearly anything and heavily damages anyone lacking proper safety equipment."
hand_path = "/obj/item/melee/touch_attack/alien/corrosive_acid"
action_icon_state = "alien_acid"
- on_gain_message = span_noticealien("You vomit acid in your hand and prepare to use it.")
- on_withdraw_message = span_noticealien("You decide not to use acid for now...")
+ on_gain_message = span_noticealien_alt("You vomit acid in your hand and prepare to use it.")
+ on_withdraw_message = span_noticealien_alt("You decide not to use acid for now...")
plasma_cost = 200
/obj/effect/proc_holder/spell/touch/alien_spell/corrosive_acid/sentinel
diff --git a/code/datums/spells/alien_spells/neurotoxin_spit.dm b/code/datums/spells/alien_spells/neurotoxin_spit.dm
index bd5dd43ded4b..c274c38263b7 100644
--- a/code/datums/spells/alien_spells/neurotoxin_spit.dm
+++ b/code/datums/spells/alien_spells/neurotoxin_spit.dm
@@ -3,8 +3,8 @@
desc = "This ability allows you to fire some neurotoxin. Knocks down anyone you hit, applies a small amount of stamina damage as well."
base_cooldown = 1 SECONDS
plasma_cost = 50
- selection_activated_message = span_noticealien("Your prepare some neurotoxin!")
- selection_deactivated_message = span_noticealien("You swallow your prepared neurotoxin.")
+ selection_activated_message = span_noticealien_alt("Your prepare some neurotoxin!")
+ selection_deactivated_message = span_noticealien_alt("You swallow your prepared neurotoxin.")
var/neurotoxin_type = /obj/projectile/bullet/neurotoxin
action_icon_state = "alien_neurotoxin_0"
sound = 'sound/creatures/terrorspiders/spit2.ogg'
diff --git a/code/datums/spells/alien_spells/transfer_plasma.dm b/code/datums/spells/alien_spells/transfer_plasma.dm
index 9075232173a2..49e38f1a5bfd 100644
--- a/code/datums/spells/alien_spells/transfer_plasma.dm
+++ b/code/datums/spells/alien_spells/transfer_plasma.dm
@@ -3,8 +3,8 @@
desc = "Transfers plasma to a nearby alien"
hand_path = "/obj/item/melee/touch_attack/alien/transfer_plasma"
action_icon_state = "alien_transfer"
- on_gain_message = span_noticealien("You vomit some plasma in your hand and prepare to transfer it.")
- on_withdraw_message = span_noticealien("You decide not to use plasma for now...")
+ on_gain_message = span_noticealien_alt("You vomit some plasma in your hand and prepare to transfer it.")
+ on_withdraw_message = span_noticealien_alt("You decide not to use plasma for now...")
/obj/effect/proc_holder/spell/touch/alien_spell/transfer_plasma/Click(mob/living/carbon/user = usr)
if(HAS_TRAIT(user, TRAIT_HANDS_BLOCKED))
diff --git a/code/datums/spells/chaplain.dm b/code/datums/spells/chaplain.dm
index db6a2f893c3b..0126444deab2 100644
--- a/code/datums/spells/chaplain.dm
+++ b/code/datums/spells/chaplain.dm
@@ -5,8 +5,8 @@
school = "transmutation"
base_cooldown = 6 SECONDS
clothes_req = FALSE
- selection_activated_message = span_notice("You prepare a blessing. Click on a target to start blessing.")
- selection_deactivated_message = span_notice("The crew will be blessed another time.")
+ selection_activated_message = span_notice_alt("You prepare a blessing. Click on a target to start blessing.")
+ selection_deactivated_message = span_notice_alt("The crew will be blessed another time.")
cooldown_min = 2 SECONDS
action_icon_state = "shield"
need_active_overlay = TRUE
diff --git a/code/datums/spells/devil.dm b/code/datums/spells/devil.dm
index 60725f35911c..971723eb9a81 100644
--- a/code/datums/spells/devil.dm
+++ b/code/datums/spells/devil.dm
@@ -51,8 +51,8 @@
invocation_type = "whisper"
invocation = "Iustus signum in linea punctata."
- selection_activated_message = span_notice("Вы приготавливаете подробный контракт. ЛКМ по цели, чтобы призвать контракт ей в руку.")
- selection_deactivated_message = span_notice("Вы сохраняете контракт до лучших времен.")
+ selection_activated_message = span_notice_alt("Вы приготавливаете подробный контракт. ЛКМ по цели, чтобы призвать контракт ей в руку.")
+ selection_deactivated_message = span_notice_alt("Вы сохраняете контракт до лучших времен.")
clothes_req = FALSE
human_req = FALSE
@@ -104,8 +104,8 @@
invocation_type = "shout"
invocation = "Ille porcus est meus!"
- selection_activated_message = span_notice("Вы готовы забрать душу. Просто клините на свою жертву.")
- selection_deactivated_message = span_notice("Вы передумали забирать чью-то душу.")
+ selection_activated_message = span_notice_alt("Вы готовы забрать душу. Просто клините на свою жертву.")
+ selection_deactivated_message = span_notice_alt("Вы передумали забирать чью-то душу.")
clothes_req = FALSE
human_req = FALSE
diff --git a/code/datums/spells/horsemask.dm b/code/datums/spells/horsemask.dm
index bc5579b2a013..133af5c47478 100644
--- a/code/datums/spells/horsemask.dm
+++ b/code/datums/spells/horsemask.dm
@@ -9,8 +9,8 @@
invocation = "KN'A FTAGHU, PUCK 'BTHNK!"
invocation_type = "shout"
- selection_activated_message = span_notice("You start to quietly neigh an incantation. Click on or near a target to cast the spell.")
- selection_deactivated_message = span_notice("You stop neighing to yourself.")
+ selection_activated_message = span_notice_alt("You start to quietly neigh an incantation. Click on or near a target to cast the spell.")
+ selection_deactivated_message = span_notice_alt("You stop neighing to yourself.")
action_icon_state = "barn"
sound = 'sound/magic/HorseHead_curse.ogg'
diff --git a/code/datums/spells/mime.dm b/code/datums/spells/mime.dm
index ec73cd4d90c2..960d6484ac22 100644
--- a/code/datums/spells/mime.dm
+++ b/code/datums/spells/mime.dm
@@ -4,7 +4,7 @@
school = "mime"
summon_type = list(/obj/effect/forcefield/mime)
invocation_type = "emote"
- invocation_emote_self = span_notice("Вы создаёте стену перед cобой.")
+ invocation_emote_self = span_notice_alt("Вы создаёте стену перед cобой.")
summon_lifespan = 30 SECONDS
base_cooldown = 30 SECONDS
clothes_req = FALSE
@@ -77,7 +77,7 @@
school = "mime"
wall_type = /obj/effect/forcefield/mime/advanced
invocation_type = "emote"
- invocation_emote_self = span_notice("Вы создаёте стену перед cобой.")
+ invocation_emote_self = span_notice_alt("Вы создаёте стену перед cобой.")
base_cooldown = 60 SECONDS
sound = null
diff --git a/code/datums/spells/mimic.dm b/code/datums/spells/mimic.dm
index d8df8d3fa90b..48974b7ac160 100644
--- a/code/datums/spells/mimic.dm
+++ b/code/datums/spells/mimic.dm
@@ -5,7 +5,7 @@
human_req = FALSE
base_cooldown = 3 SECONDS
action_icon_state = "genetic_morph"
- selection_activated_message = span_sinister("Кликните на цель, чтобы запомнить её форму. Кликните на себя, чтобы изменить свою форму.")
+ selection_activated_message = span_sinister_alt("Кликните на цель, чтобы запомнить её форму. Кликните на себя, чтобы изменить свою форму.")
create_attack_logs = FALSE
action_icon_state = "morph_mimic"
need_active_overlay = TRUE
diff --git a/code/datums/spells/mind_transfer.dm b/code/datums/spells/mind_transfer.dm
index f3eb462dc81a..cc42ba43b10a 100644
--- a/code/datums/spells/mind_transfer.dm
+++ b/code/datums/spells/mind_transfer.dm
@@ -8,8 +8,8 @@
human_req = FALSE
invocation = "GIN'YU CAPAN"
invocation_type = "whisper"
- selection_activated_message = span_notice("You prepare to transfer your mind. Click on a target to cast the spell.")
- selection_deactivated_message = span_notice("You decide that your current form is good enough.")
+ selection_activated_message = span_notice_alt("You prepare to transfer your mind. Click on a target to cast the spell.")
+ selection_deactivated_message = span_notice_alt("You decide that your current form is good enough.")
cooldown_min = 20 SECONDS //100 deciseconds reduction per rank
var/list/protected_roles = list("Wizard","Changeling","Cultist") //which roles are immune to the spell
var/paralysis_amount_caster = 40 SECONDS //how much the caster is paralysed for after the spell
diff --git a/code/datums/spells/night_vision.dm b/code/datums/spells/night_vision.dm
index 8e107d1f9f23..306b26d4536c 100644
--- a/code/datums/spells/night_vision.dm
+++ b/code/datums/spells/night_vision.dm
@@ -6,7 +6,7 @@
clothes_req = FALSE
human_req = FALSE
- message = span_notice("You toggle your night vision!")
+ message = span_notice_alt("You toggle your night vision!")
/obj/effect/proc_holder/spell/night_vision/create_new_targeting()
return new /datum/spell_targeting/self
diff --git a/code/datums/spells/touch_attacks.dm b/code/datums/spells/touch_attacks.dm
index 5f76a2ff797c..6dc3e83d0671 100644
--- a/code/datums/spells/touch_attacks.dm
+++ b/code/datums/spells/touch_attacks.dm
@@ -4,9 +4,9 @@
/// Link to the spawned item
var/obj/item/melee/touch_attack/attached_hand = null
/// Special message shown on item gain
- var/on_gain_message = span_notice("You channel the power of the spell to your hand.")
+ var/on_gain_message = span_notice_alt("You channel the power of the spell to your hand.")
/// Special message shown on item withdrowal
- var/on_withdraw_message = span_notice("You draw the power out of your hand.")
+ var/on_withdraw_message = span_notice_alt("You draw the power out of your hand.")
/obj/effect/proc_holder/spell/touch/create_new_targeting()
return new /datum/spell_targeting/self
diff --git a/code/datums/spells/wizard.dm b/code/datums/spells/wizard.dm
index e7e631941619..45c6511f5f08 100644
--- a/code/datums/spells/wizard.dm
+++ b/code/datums/spells/wizard.dm
@@ -89,7 +89,7 @@
cooldown_min = 30 SECONDS //25 deciseconds reduction per rank
invocation = "BIRUZ BENNAR"
invocation_type = "shout"
- message = span_notice("You feel strong! You feel a pressure building behind your eyes!")
+ message = span_notice_alt("You feel strong! You feel a pressure building behind your eyes!")
centcom_cancast = FALSE
traits = list(TRAIT_LASEREYES)
@@ -286,7 +286,7 @@
human_req = FALSE
invocation = "STI KALY"
invocation_type = "whisper"
- message = span_notice("Your eyes cry out in pain!")
+ message = span_notice_alt("Your eyes cry out in pain!")
base_cooldown = 30 SECONDS
cooldown_min = 5 SECONDS //12 deciseconds reduction per rank
need_active_overlay = TRUE
@@ -323,8 +323,8 @@
invocation = "ONI SOMA"
invocation_type = "shout"
- selection_activated_message = span_notice("Your prepare to cast your fireball spell! Left-click to cast at a target!")
- selection_deactivated_message = span_notice("You extinguish your fireball...for now.")
+ selection_activated_message = span_notice_alt("Your prepare to cast your fireball spell! Left-click to cast at a target!")
+ selection_deactivated_message = span_notice_alt("You extinguish your fireball...for now.")
var/fireball_type = /obj/projectile/magic/fireball
action_icon_state = "fireball0"
diff --git a/code/datums/status_effects/buffs.dm b/code/datums/status_effects/buffs.dm
index e4ab7712895a..137670d5e50b 100644
--- a/code/datums/status_effects/buffs.dm
+++ b/code/datums/status_effects/buffs.dm
@@ -268,7 +268,7 @@
/datum/status_effect/hippocraticOath
id = "Hippocratic Oath"
tick_interval = 25
- examine_text = span_notice("Кажется, они окружены аурой исцеления и доброжелательности.")
+ examine_text = span_notice_alt("Кажется, они окружены аурой исцеления и доброжелательности.")
alert_type = null
var/datum/component/aura_healing/aura_healing
diff --git a/code/datums/weather/weather.dm b/code/datums/weather/weather.dm
index be8a1d4e1b10..13a1b1527de1 100644
--- a/code/datums/weather/weather.dm
+++ b/code/datums/weather/weather.dm
@@ -4,7 +4,7 @@
var/name = "space wind"
var/desc = "Heavy gusts of wind blanket the area, periodically knocking down anyone caught in the open."
- var/telegraph_message = span_warning("The wind begins to pick up.") //The message displayed in chat to foreshadow the weather's beginning
+ var/telegraph_message = span_warning_alt("The wind begins to pick up.") //The message displayed in chat to foreshadow the weather's beginning
var/telegraph_duration = 30 SECONDS //In deciseconds, how long from the beginning of the telegraph until the weather begins
/// The sound file played to everyone on an affected z-level
var/telegraph_sound
@@ -12,7 +12,7 @@
var/telegraph_sound_vol
var/telegraph_overlay //The overlay applied to all tiles on the z-level
- var/weather_message = span_userdanger("The wind begins to blow ferociously!") //Displayed in chat once the weather begins in earnest
+ var/weather_message = span_userdanger_alt("The wind begins to blow ferociously!") //Displayed in chat once the weather begins in earnest
var/weather_duration = 120 SECONDS //In deciseconds, how long the weather lasts once it begins
var/weather_duration_lower = 120 SECONDS //See above - this is the lowest possible duration
var/weather_duration_upper = 150 SECONDS //See above - this is the highest possible duration
@@ -20,7 +20,7 @@
var/weather_overlay
var/weather_color = null
- var/end_message = span_danger("The wind relents its assault.") //Displayed once the wather is over
+ var/end_message = span_danger_alt("The wind relents its assault.") //Displayed once the wather is over
var/end_duration = 30 SECONDS //In deciseconds, how long the "wind-down" graphic will appear before vanishing entirely
var/end_sound
/// Volume of the sound that plays while weather is ending
diff --git a/code/datums/weather/weather_types/ash_storm.dm b/code/datums/weather/weather_types/ash_storm.dm
index 9ee9ba1410c4..8b80324ef203 100644
--- a/code/datums/weather/weather_types/ash_storm.dm
+++ b/code/datums/weather/weather_types/ash_storm.dm
@@ -3,15 +3,15 @@
name = "ash storm"
desc = "Мощная атмосферная буря поднимает пепел с поверхности планеты, обрушивая его на землю и нанося сильные ожоги незащищённым существам."
- telegraph_message = span_boldwarning("Глухой рокот нарастает вдали, превращаясь в оглушительный рёв. Горизонт застилают мрачные волны пепла. Ищите убежище!")
+ telegraph_message = span_boldwarning_alt("Глухой рокот нарастает вдали, превращаясь в оглушительный рёв. Горизонт застилают мрачные волны пепла. Ищите убежище!")
telegraph_overlay = "light_ash"
- weather_message = span_userdanger("Раскалённый пепел обжигает кожу! Воздух наполняется гарью — прячьтесь в убежище!")
+ weather_message = span_userdanger_alt("Раскалённый пепел обжигает кожу! Воздух наполняется гарью — прячьтесь в убежище!")
weather_duration_lower = 60 SECONDS
weather_duration_upper = 120 SECONDS
weather_overlay = "ash_storm"
- end_message = span_boldannounceic("Буря отступила, оставив после себя лишь опалённую тишину. Можно выходить...")
+ end_message = span_boldannounceic_alt("Буря отступила, оставив после себя лишь опалённую тишину. Можно выходить...")
end_overlay = "light_ash"
area_type = /area/lavaland/surface/outdoors
@@ -123,10 +123,10 @@
name = "emberfall"
desc = "Проходящая пепельная буря покрывает землю безвредными угольками."
- weather_message = span_notice("Мягкие угольки опадают вокруг, словно уродливый снег. Кажется, буря обошла вас стороной...")
+ weather_message = span_notice_alt("Мягкие угольки опадают вокруг, словно уродливый снег. Кажется, буря обошла вас стороной...")
weather_overlay = "light_ash"
- end_message = span_notice("Пеплопад ослабевает и прекращается. Ещё один слой затвердевшей сажи ложится на базальт под ногами.")
+ end_message = span_notice_alt("Пеплопад ослабевает и прекращается. Ещё один слой затвердевшей сажи ложится на базальт под ногами.")
end_sound = null
aesthetic = TRUE
diff --git a/code/datums/weather/weather_types/blob_storm.dm b/code/datums/weather/weather_types/blob_storm.dm
index bf097e4401ba..0045b29a2c8c 100644
--- a/code/datums/weather/weather_types/blob_storm.dm
+++ b/code/datums/weather/weather_types/blob_storm.dm
@@ -4,9 +4,9 @@
desc = "Плотное облако из мельчайших спор блоба, проникающих через любую одежду."
telegraph_duration = 2 SECONDS
- telegraph_message = span_danger("Вы замечаете мелкие частицы в воздухе")
+ telegraph_message = span_danger_alt("Вы замечаете мелкие частицы в воздухе")
- weather_message = span_userdanger("Вы ощущаете поток неизвестных мелких частиц, которые проникают сквозь любую одежду. Спасти вас может только чудо.")
+ weather_message = span_userdanger_alt("Вы ощущаете поток неизвестных мелких частиц, которые проникают сквозь любую одежду. Спасти вас может только чудо.")
weather_overlay = "blob_storm"
weather_duration_lower = 30 SECONDS
weather_duration_upper = 1 MINUTES
@@ -16,7 +16,7 @@
weather_sound = 'sound/magic/mutate.ogg'
end_duration = 10 SECONDS
- end_message = span_notice("Поток частиц осел.")
+ end_message = span_notice_alt("Поток частиц осел.")
area_type = /area
protected_areas = list(/area/space, /area/crew_quarters/sleep)
diff --git a/code/datums/weather/weather_types/floor_is_lava.dm b/code/datums/weather/weather_types/floor_is_lava.dm
index f4e90f64f873..e91f3235948e 100644
--- a/code/datums/weather/weather_types/floor_is_lava.dm
+++ b/code/datums/weather/weather_types/floor_is_lava.dm
@@ -3,15 +3,15 @@
name = "the floor is lava"
desc = "The ground turns into surprisingly cool lava, lightly damaging anything on the floor."
- telegraph_message = span_warning("You feel the ground beneath you getting hot. Waves of heat distort the air.")
+ telegraph_message = span_warning_alt("You feel the ground beneath you getting hot. Waves of heat distort the air.")
telegraph_duration = 150
- weather_message = span_userdanger("The floor is lava! Get on top of something!")
+ weather_message = span_userdanger_alt("The floor is lava! Get on top of something!")
weather_duration_lower = 300
weather_duration_upper = 600
weather_overlay = "lava"
- end_message = span_danger("The ground cools and returns to its usual form.")
+ end_message = span_danger_alt("The ground cools and returns to its usual form.")
end_duration = 0
area_type = /area
diff --git a/code/datums/weather/weather_types/radiation_storm.dm b/code/datums/weather/weather_types/radiation_storm.dm
index 9655591e759c..0da73fa81a64 100644
--- a/code/datums/weather/weather_types/radiation_storm.dm
+++ b/code/datums/weather/weather_types/radiation_storm.dm
@@ -4,16 +4,16 @@
desc = "A cloud of intense radiation passes through the area dealing rad damage to those who are unprotected."
telegraph_duration = 400
- telegraph_message = span_danger("The air begins to grow warm.")
+ telegraph_message = span_danger_alt("The air begins to grow warm.")
- weather_message = span_userdanger("You feel waves of heat wash over you! Find shelter!")
+ weather_message = span_userdanger_alt("You feel waves of heat wash over you! Find shelter!")
weather_overlay = "ash_storm"
weather_duration_lower = 600
weather_color = "green"
weather_sound = 'sound/misc/bloblarm.ogg'
end_duration = 100
- end_message = span_notice("The air seems to be cooling off again.")
+ end_message = span_notice_alt("The air seems to be cooling off again.")
var/pre_maint_all_access
area_type = /area
protected_areas = list(/area/maintenance, /area/turret_protected/ai_upload, /area/turret_protected/ai_upload_foyer,
diff --git a/code/datums/weather/weather_types/snow_storm.dm b/code/datums/weather/weather_types/snow_storm.dm
index b43e5434db80..8a6b0388ac5d 100644
--- a/code/datums/weather/weather_types/snow_storm.dm
+++ b/code/datums/weather/weather_types/snow_storm.dm
@@ -3,19 +3,19 @@
desc = "Harsh snowstorms roam the topside of this arctic planet, burying any area unfortunate enough to be in its path."
probability = 99
- telegraph_message = span_warning("Drifting particles of snow begin to dust the surrounding area...")
+ telegraph_message = span_warning_alt("Drifting particles of snow begin to dust the surrounding area...")
telegraph_duration = 40 SECONDS
telegraph_overlay = "light_snow"
telegraph_sound = 'sound/ambience/weather/snowstorm/snow_start.ogg'
telegraph_sound_vol = /datum/looping_sound/snowstorm::volume + 10
- weather_message = span_userdanger("Harsh winds pick up as dense snow begins to fall from the sky! Seek shelter!")
+ weather_message = span_userdanger_alt("Harsh winds pick up as dense snow begins to fall from the sky! Seek shelter!")
weather_overlay = "snow_storm"
weather_duration_lower = 60 SECONDS
weather_duration_upper = 120 SECONDS
end_duration = 10 SECONDS
- end_message = span_boldannounceic("The snowfall dies down, it should be safe to go outside again.")
+ end_message = span_boldannounceic_alt("The snowfall dies down, it should be safe to go outside again.")
end_overlay = "light_snow"
end_sound = 'sound/ambience/weather/snowstorm/snow_end.ogg'
end_sound_vol = /datum/looping_sound/snowstorm::volume + 10
diff --git a/code/datums/weather/weather_types/solar_flare.dm b/code/datums/weather/weather_types/solar_flare.dm
index 33b568a6645d..487010253107 100644
--- a/code/datums/weather/weather_types/solar_flare.dm
+++ b/code/datums/weather/weather_types/solar_flare.dm
@@ -4,7 +4,7 @@
telegraph_message = null // handled via event announcement
- weather_message = span_userdanger("Началась солнечная вспышка! Найдите укрытие!")
+ weather_message = span_userdanger_alt("Началась солнечная вспышка! Найдите укрытие!")
weather_overlay = "light_ash"
weather_duration_lower = 5 MINUTES
weather_duration_upper = 10 MINUTES
diff --git a/code/datums/weather/weather_types/web_storm.dm b/code/datums/weather/weather_types/web_storm.dm
index 3848f215cc4c..479829872986 100644
--- a/code/datums/weather/weather_types/web_storm.dm
+++ b/code/datums/weather/weather_types/web_storm.dm
@@ -3,9 +3,9 @@
desc = "Плотное облако из мельчайших частичек паутины, липнущих ко всему вокруг."
telegraph_duration = 2 SECONDS
- telegraph_message = span_danger("Вы замечаете мелкие частицы паутины в воздухе.")
+ telegraph_message = span_danger_alt("Вы замечаете мелкие частицы паутины в воздухе.")
- weather_message = span_userdanger("Вы ощущаете поток мельчайших частиц паутины, липнуших ко всему вокруг.")
+ weather_message = span_userdanger_alt("Вы ощущаете поток мельчайших частиц паутины, липнуших ко всему вокруг.")
weather_overlay = "web_storm"
weather_duration_lower = 30 SECONDS
weather_duration_upper = 1 MINUTES
@@ -14,7 +14,7 @@
weather_sound = 'sound/creatures/terrorspiders/queen_shriek.ogg'
end_duration = 10 SECONDS
- end_message = span_notice("Поток паутины прекращается.")
+ end_message = span_notice_alt("Поток паутины прекращается.")
area_type = /area
protected_areas = list(/area/space, /area/crew_quarters/sleep)
diff --git a/code/game/atoms.dm b/code/game/atoms.dm
index ba3fadc4ddad..f540a576a2d9 100644
--- a/code/game/atoms.dm
+++ b/code/game/atoms.dm
@@ -186,6 +186,8 @@
/// Do we care about temperature at all? Saves us a ton of proc calls during big fires.
var/cares_about_temperature = FALSE
+ var/looting_icon_mode
+
/atom/New(loc, ...)
SHOULD_CALL_PARENT(TRUE)
if(GLOB.use_preloader && (src.type == GLOB._preloader.target_path))//in case the instanciated atom is creating other atoms in New()
@@ -250,6 +252,9 @@
ComponentInitialize()
InitializeAIController()
+ if(LAZYLEN(hud_possible))
+ hud_possible = string_assoc_list(hud_possible)
+
return INITIALIZE_HINT_NORMAL
//called if Initialize returns INITIALIZE_HINT_LATELOAD
@@ -677,6 +682,7 @@
/// Checks if this atom uses the GAS system and if so updates the icon
/atom/proc/update_greyscale()
icon = SSgreyscale.get_colored_icon_by_type(greyscale_config, greyscale_colors)
+ looting_icon_mode = LOOT_ICON_ICON_TO_HTML
/// Updates atom's emissive block if present.
/atom/proc/get_emissive_block()
diff --git a/code/game/dna/dna_modifier.dm b/code/game/dna/dna_modifier.dm
index 0bf801669a4e..85677f7e223c 100644
--- a/code/game/dna/dna_modifier.dm
+++ b/code/game/dna/dna_modifier.dm
@@ -654,9 +654,11 @@
irradiating = 0
connected.locked = lock_state
+
+ var/precision_coeff = connected.precision_coeff
if(connected.occupant)
- if(prob((80 + ((radiation_duration / 2) + (connected.precision_coeff ** 3)))))
+ if(prob((80 + ((radiation_duration / 2) + POW3(precision_coeff)))))
var/radiation = ((radiation_intensity + radiation_duration) / connected.damage_coeff)
connected.occupant.apply_effect(radiation, IRRADIATE, 0)
diff --git a/code/game/dna/genes/disabilities.dm b/code/game/dna/genes/disabilities.dm
index 95f32ce03523..813919728d55 100644
--- a/code/game/dna/genes/disabilities.dm
+++ b/code/game/dna/genes/disabilities.dm
@@ -211,7 +211,7 @@
/datum/dna/gene/disability/comic
name = "Комик"
desc = "Это принесет только смерть и разрушение."
- activation_message = list(span_sans("Ой-йо!"))
+ activation_message = list(span_sans_alt("Ой-йо!"))
deactivation_message = list("Слава Святой Хонкоматери, с этим покончено.")
traits_to_add = list(TRAIT_COMIC)
@@ -222,7 +222,7 @@
/datum/dna/gene/disability/wingdings
name = "Голос инопланетян"
desc = "Искажает голос субъекта, превращая его в непонятную речь."
- activation_message = list(span_wingdings("Vashi golosovyye svyazki kazhutsya chuzhimi."))
+ activation_message = list(span_wingdings_alt("Vashi golosovyye svyazki kazhutsya chuzhimi."))
deactivation_message = list("Ваши голосовые связки больше не кажутся инородными.")
instability = -GENE_INSTABILITY_MINOR
traits_to_add = list(TRAIT_WINGDINGS)
diff --git a/code/game/dna/genes/goon_powers.dm b/code/game/dna/genes/goon_powers.dm
index a87b8e077df7..2a61b4532bda 100644
--- a/code/game/dna/genes/goon_powers.dm
+++ b/code/game/dna/genes/goon_powers.dm
@@ -122,8 +122,8 @@
base_cooldown = 120 SECONDS
clothes_req = FALSE
- selection_activated_message = span_notice("Ваш разум становится холодным. Нажмите на цель, чтобы произнести заклинание.")
- selection_deactivated_message = span_notice("Ваш разум возвращается в нормальное состояние.")
+ selection_activated_message = span_notice_alt("Ваш разум становится холодным. Нажмите на цель, чтобы произнести заклинание.")
+ selection_deactivated_message = span_notice_alt("Ваш разум возвращается в нормальное состояние.")
var/list/compatible_mobs = list(/mob/living/carbon/human)
@@ -399,8 +399,8 @@
clothes_req = FALSE
- selection_activated_message = span_notice("Ваше тело становится нестабильным.")
- selection_deactivated_message = span_notice("Ваше тело возвращается в норму.")
+ selection_activated_message = span_notice_alt("Ваше тело становится нестабильным.")
+ selection_deactivated_message = span_notice_alt("Ваше тело возвращается в норму.")
action_icon_state = "genetic_poly"
need_active_overlay = TRUE
diff --git a/code/game/gamemodes/clockwork/clockheart.dm b/code/game/gamemodes/clockwork/clockheart.dm
index 6753af1b5206..95d25356a378 100644
--- a/code/game/gamemodes/clockwork/clockheart.dm
+++ b/code/game/gamemodes/clockwork/clockheart.dm
@@ -259,7 +259,7 @@ GLOBAL_DATUM(heart, /obj/structure/clockwork/functional/heart)
if(istype(did_not_stand_back, /obj/structure/clockwork/functional/heart) || istype(did_not_stand_back, /obj/structure/heart_filler) || istype(did_not_stand_back, /obj/effect/temp_visual/ratvar/reconstruct/heart))
return -1
if(ISDIAGONALDIR(dir_to_center))
- throw_dist = ceil(sqrt(base_x_throw_distance ** 2 + base_y_throw_distance ** 2) - (sqrt(x_component ** 2 + y_component ** 2)))
+ throw_dist = ceil(MAGNITUDE(base_x_throw_distance, base_y_throw_distance) - MAGNITUDE(x_component, y_component))
did_not_stand_back.forceMove(get_ranged_target_turf(loc, dir_to_center, throw_dist))
else if(dir_to_center & (NORTH|SOUTH))
throw_dist = base_y_throw_distance - y_component + 1
diff --git a/code/game/gamemodes/clockwork/clockwork_structures.dm b/code/game/gamemodes/clockwork/clockwork_structures.dm
index dfcd445b7d06..35ca28c33df6 100644
--- a/code/game/gamemodes/clockwork/clockwork_structures.dm
+++ b/code/game/gamemodes/clockwork/clockwork_structures.dm
@@ -18,7 +18,7 @@
/obj/structure/clockwork/functional
max_integrity = 100
var/cooldowntime = 0
- var/death_message = span_danger("The structure falls apart.")
+ var/death_message = span_danger_alt("The structure falls apart.")
var/death_sound = 'sound/effects/forge_destroy.ogg'
var/canbehidden = FALSE
var/hidden = FALSE
@@ -130,7 +130,7 @@
desc = "An imposing spire formed of brass. It somewhat pulsates."
icon_state = "beacon"
max_integrity = 250 // A very important one
- death_message = span_danger("The beacon crumbles and falls in parts to the ground relaesing it's power!")
+ death_message = span_danger_alt("The beacon crumbles and falls in parts to the ground relaesing it's power!")
death_sound = 'sound/effects/creepyshriek.ogg'
var/heal_delay = 6 SECONDS
var/last_heal = 0
@@ -199,7 +199,7 @@
desc = "A strange brass platform with spinning cogs inside. It demands something in exchange for goods..."
icon_state = "altar"
density = FALSE
- death_message = span_danger("The credence breaks in pieces as it dusts into nothing!")
+ death_message = span_danger_alt("The credence breaks in pieces as it dusts into nothing!")
canbehidden = TRUE
choosable_items = list(
"potted plant" = /obj/item/twohanded/required/kirbyplants,
@@ -440,7 +440,7 @@
name = "cogscarab fabricator"
desc = "House for a tons of little cogscarabs, self-producing and maintaining itself."
icon_state = "fabricator"
- death_message = span_danger("Fabricator crumbles and dusts, leaving nothing behind!")
+ death_message = span_danger_alt("Fabricator crumbles and dusts, leaving nothing behind!")
var/list/cogscarab_list = list()
canbehidden = TRUE
var/cog_slots = 0
diff --git a/code/game/gamemodes/clockwork/clockwork_workshop.dm b/code/game/gamemodes/clockwork/clockwork_workshop.dm
index 211f09054bd7..ff54e1c1391e 100644
--- a/code/game/gamemodes/clockwork/clockwork_workshop.dm
+++ b/code/game/gamemodes/clockwork/clockwork_workshop.dm
@@ -18,7 +18,7 @@
desc = "A workshop of elder god. Has unique brass tools to manipulate both power and metal to make fine clockwork pieces."
icon_state = "workshop"
max_integrity = 400
- death_message = span_danger("The workshop begins to crumble in pieces as the tools and the gears on table starts to dust!")
+ death_message = span_danger_alt("The workshop begins to crumble in pieces as the tools and the gears on table starts to dust!")
var/temp_search
var/datum/clockwork_design/being_built = null
var/list/item_list
diff --git a/code/game/gamemodes/cult/blood_magic.dm b/code/game/gamemodes/cult/blood_magic.dm
index 1f61352f0694..ca8c5fbe5e81 100644
--- a/code/game/gamemodes/cult/blood_magic.dm
+++ b/code/game/gamemodes/cult/blood_magic.dm
@@ -893,10 +893,11 @@
if(T)
for(var/obj/effect/decal/cleanable/blood/B in view(T, 2))
if(B.blood_state == BLOOD_STATE_HUMAN && (B.can_bloodcrawl_in() || istype(B, /obj/effect/decal/cleanable/blood/slime) || istype(B, /obj/effect/decal/cleanable/blood/drask)))
- if(B.bloodiness == 100) //Bonus for "pristine" bloodpools, also to prevent cheese with footprint spam
+ var/bloodiness = B.bloodiness
+ if(bloodiness == 100) //Bonus for "pristine" bloodpools, also to prevent cheese with footprint spam
temp += 30
else
- temp += max((B.bloodiness ** 2) / 800, 1)
+ temp += max(POW2(bloodiness) / 800, 1)
new /obj/effect/temp_visual/cult/turf/open/floor(get_turf(B))
qdel(B)
for(var/obj/effect/decal/cleanable/trail_holder/TH in view(T, 2))
diff --git a/code/game/gamemodes/cult/cult_structures.dm b/code/game/gamemodes/cult/cult_structures.dm
index d747dae0e059..8bc8524c7aa2 100644
--- a/code/game/gamemodes/cult/cult_structures.dm
+++ b/code/game/gamemodes/cult/cult_structures.dm
@@ -36,7 +36,7 @@
/obj/structure/cult/functional
max_integrity = 100
var/cooldowntime = 0
- var/death_message = span_danger("The structure falls apart.") //The message shown when the structure is destroyed
+ var/death_message = span_danger_alt("The structure falls apart.") //The message shown when the structure is destroyed
var/death_sound = 'sound/items/bikehorn.ogg'
var/heathen_message = "You're a huge nerd, go away. Also, a coder forgot to put a message here."
var/selection_title = "Oops"
@@ -143,12 +143,12 @@
desc = "A bloodstained altar dedicated to a cult."
icon_state = "altar"
max_integrity = 150 //Sturdy
- death_message = span_danger("The altar breaks into splinters, releasing a cascade of spirits into the air!")
+ death_message = span_danger_alt("The altar breaks into splinters, releasing a cascade of spirits into the air!")
death_sound = 'sound/effects/altar_break.ogg'
- heathen_message = span_warning("There is a foreboding aura to the altar and you want nothing to do with it.")
+ heathen_message = span_warning_alt("There is a foreboding aura to the altar and you want nothing to do with it.")
selection_prompt = "You study the rituals on the altar..."
selection_title = "Altar"
- creation_message = span_cultitalic("You kneel before the altar and your faith is rewarded with a %ITEM%!")
+ creation_message = span_cultitalic_alt("You kneel before the altar and your faith is rewarded with a %ITEM%!")
choosable_items = list("Eldritch Whetstone" = /obj/item/whetstone/cult, "Flask of Unholy Water" = /obj/item/reagent_containers/food/drinks/bottle/unholywater,
"Construct Shell" = /obj/structure/constructshell)
@@ -159,12 +159,12 @@
light_range = 2
light_color = LIGHT_COLOR_LAVA
max_integrity = 300 //Made of metal
- death_message = span_danger("The forge falls apart, its lava cooling and winking away!")
+ death_message = span_danger_alt("The forge falls apart, its lava cooling and winking away!")
death_sound = 'sound/effects/forge_destroy.ogg'
- heathen_message = span_warning("Your hand feels like it's melting off as you try to touch the forge.")
+ heathen_message = span_warning_alt("Your hand feels like it's melting off as you try to touch the forge.")
selection_prompt = "You study the schematics etched on the forge..."
selection_title = "Forge"
- creation_message = span_cultitalic("You work the forge as dark knowledge guides your hands, creating a %ITEM%!")
+ creation_message = span_cultitalic_alt("You work the forge as dark knowledge guides your hands, creating a %ITEM%!")
choosable_items = list("Shielded Robe" = /obj/item/clothing/suit/hooded/cultrobes/cult_shield, "Flagellant's Robe" = /obj/item/clothing/suit/hooded/cultrobes/flagellant_robe,
"Mirror Shield" = /obj/item/shield/mirror)
@@ -211,7 +211,7 @@ GLOBAL_LIST_INIT(blacklisted_pylon_turfs, typecacheof(list(
light_range = 1.5
light_color = LIGHT_COLOR_FLARE
max_integrity = 50 //Very fragile
- death_message = span_danger("The pylon's crystal vibrates and glows fiercely before violently shattering!")
+ death_message = span_danger_alt("The pylon's crystal vibrates and glows fiercely before violently shattering!")
death_sound = 'sound/effects/pylon_shatter.ogg'
/// Length of the cooldown in between tile corruptions. Doubled if no turfs are found.
var/corruption_cooldown_duration = 5 SECONDS
@@ -316,12 +316,12 @@ GLOBAL_LIST_INIT(blacklisted_pylon_turfs, typecacheof(list(
light_range = 1.5
light_color = LIGHT_COLOR_FIRE
max_integrity = 125 //Slightly sturdy
- death_message = span_danger("The desk breaks apart, its books falling to the floor.")
+ death_message = span_danger_alt("The desk breaks apart, its books falling to the floor.")
death_sound = 'sound/effects/wood_break.ogg'
- heathen_message = span_cultlarge("What do you hope to seek?")
+ heathen_message = span_cultlarge_alt("What do you hope to seek?")
selection_prompt = "You flip through the black pages of the archives..."
selection_title = "Archives"
- creation_message = span_cultitalic("You invoke the dark magic of the tomes creating a %ITEM%!")
+ creation_message = span_cultitalic_alt("You invoke the dark magic of the tomes creating a %ITEM%!")
choosable_items = list("Shuttle Curse" = /obj/item/shuttle_curse, "Zealot's Blindfold" = /obj/item/clothing/glasses/hud/health/night/cultblind,
"Veil Shifter" = /obj/item/cult_shift) //Add void torch to veil shifter spawn
diff --git a/code/game/gamemodes/miniantags/bot_swarm/swarmer.dm b/code/game/gamemodes/miniantags/bot_swarm/swarmer.dm
index f59d9eb36db6..d7cec25a28d1 100644
--- a/code/game/gamemodes/miniantags/bot_swarm/swarmer.dm
+++ b/code/game/gamemodes/miniantags/bot_swarm/swarmer.dm
@@ -225,7 +225,7 @@
return 0
/obj/item/IntegrateAmount() //returns the amount of resources gained when eating this item
- if(materials[MAT_METAL] || materials[MAT_GLASS])
+ if(materials && (materials[MAT_METAL] || materials[MAT_GLASS]))
return 1
return ..()
diff --git a/code/game/gamemodes/miniantags/demons/shadow_demon/shadow_demon.dm b/code/game/gamemodes/miniantags/demons/shadow_demon/shadow_demon.dm
index 348a395164dd..2a92f82f6781 100644
--- a/code/game/gamemodes/miniantags/demons/shadow_demon/shadow_demon.dm
+++ b/code/game/gamemodes/miniantags/demons/shadow_demon/shadow_demon.dm
@@ -197,8 +197,8 @@
invocation = null
sound = null
need_active_overlay = TRUE
- selection_activated_message = span_notice("Вы поднимаете руку, наполненную демонической энергией! ЛКМ, чтобы применить к цели!")
- selection_deactivated_message = span_notice("Вы поглощаете энергию обратно... пока что.")
+ selection_activated_message = span_notice_alt("Вы поднимаете руку, наполненную демонической энергией! ЛКМ, чтобы применить к цели!")
+ selection_deactivated_message = span_notice_alt("Вы поглощаете энергию обратно... пока что.")
base_cooldown = 10 SECONDS
fireball_type = /obj/projectile/magic/shadow_hand
diff --git a/code/game/gamemodes/miniantags/morph/spells/pass_airlock.dm b/code/game/gamemodes/miniantags/morph/spells/pass_airlock.dm
index f0f0458ae6d6..858c404d523d 100644
--- a/code/game/gamemodes/miniantags/morph/spells/pass_airlock.dm
+++ b/code/game/gamemodes/miniantags/morph/spells/pass_airlock.dm
@@ -3,7 +3,7 @@
name = "Пройти через шлюз"
desc = "Изменяйте свою форму, чтобы пройти через незаблокированный шлюз. Это занимает некоторое время и может быть использовано только в вашей истинной форме."
action_icon_state = "morph_airlock"
- selection_activated_message = span_sinister("ЛКМ на шлюз, чтобы попытаться пройти через него.")
+ selection_activated_message = span_sinister_alt("ЛКМ на шлюз, чтобы попытаться пройти через него.")
need_active_overlay = TRUE
/obj/effect/proc_holder/spell/morph_spell/pass_airlock/create_new_targeting()
diff --git a/code/game/gamemodes/miniantags/revenant/revenant_abilities.dm b/code/game/gamemodes/miniantags/revenant/revenant_abilities.dm
index 7377b95e7fd6..fccceaa7dfe8 100644
--- a/code/game/gamemodes/miniantags/revenant/revenant_abilities.dm
+++ b/code/game/gamemodes/miniantags/revenant/revenant_abilities.dm
@@ -125,7 +125,7 @@
*/
/obj/effect/proc_holder/spell/night_vision/revenant
base_cooldown = 0
- message = span_revennotice("Вы переключаете ночное зрение.")
+ message = span_revennotice_alt("Вы переключаете ночное зрение.")
action_icon_state = "r_nightvision"
action_background_icon_state = "bg_revenant"
diff --git a/code/game/gamemodes/shadowling/shadowling_abilities.dm b/code/game/gamemodes/shadowling/shadowling_abilities.dm
index 88d3c9f7c616..c7bd53244bc6 100644
--- a/code/game/gamemodes/shadowling/shadowling_abilities.dm
+++ b/code/game/gamemodes/shadowling/shadowling_abilities.dm
@@ -33,8 +33,8 @@
action_icon_state = "glare"
- selection_activated_message = span_notice("Вы приготовились к тому, что ваши глаза станут ослепительно яркими! ЛКМ по цели, чтобы применить!")
- selection_deactivated_message = span_notice("Ваши глаза расслабляются... пока что.")
+ selection_activated_message = span_notice_alt("Вы приготовились к тому, что ваши глаза станут ослепительно яркими! ЛКМ по цели, чтобы применить!")
+ selection_deactivated_message = span_notice_alt("Ваши глаза расслабляются... пока что.")
need_active_overlay = TRUE
/obj/effect/proc_holder/spell/shadowling_glare/create_new_targeting()
@@ -253,8 +253,8 @@
base_cooldown = 3 SECONDS
clothes_req = FALSE
action_icon_state = "enthrall"
- selection_activated_message = span_notice("Вы готовите свой разум к тому, чтобы проникнуть в чужое сознание. ЛКМ по цели, чтобы применить!")
- selection_deactivated_message = span_notice("Ваш разум расслабляется.")
+ selection_activated_message = span_notice_alt("Вы готовите свой разум к тому, чтобы проникнуть в чужое сознание. ЛКМ по цели, чтобы применить!")
+ selection_deactivated_message = span_notice_alt("Ваш разум расслабляется.")
need_active_overlay = TRUE
var/enthralling = FALSE
@@ -638,8 +638,8 @@
base_cooldown = 1 MINUTES
clothes_req = FALSE
action_icon_state = "revive_thrall"
- selection_activated_message = span_notice("Вы начинаете направлять свои силы на заживление ран ваших союзников. ")
- selection_deactivated_message = span_notice("Ваш разум расслабляется.")
+ selection_activated_message = span_notice_alt("Вы начинаете направлять свои силы на заживление ран ваших союзников. ")
+ selection_deactivated_message = span_notice_alt("Ваш разум расслабляется.")
need_active_overlay = TRUE
/// Whether the EMPOWERED_THRALL_LIMIT limit is ignored or not
var/ignore_prer = FALSE
@@ -755,8 +755,8 @@
desc = "Extends the time of the emergency shuttle's arrival by ten minutes using a life force of our enemy. Shuttle will be unable to be recalled. This can only be used once."
clothes_req = FALSE
base_cooldown = 3 SECONDS
- selection_activated_message = span_notice("Вы начинаете накапливать силы, чтобы задержать шаттл. ЛКМ по цели, чтобы применить!")
- selection_deactivated_message = span_notice("Ваш разум расслабляется.")
+ selection_activated_message = span_notice_alt("Вы начинаете накапливать силы, чтобы задержать шаттл. ЛКМ по цели, чтобы применить!")
+ selection_deactivated_message = span_notice_alt("Ваш разум расслабляется.")
action_icon_state = "extend_shuttle"
need_active_overlay = TRUE
var/global/extend_limit_pressed = FALSE
@@ -829,8 +829,8 @@
clothes_req = FALSE
human_req = FALSE
action_icon_state = "annihilate"
- selection_activated_message = span_notice("Вы готовите свой разум к разрушительной атаке. ЛКМ по цели, чтобы применить!")
- selection_deactivated_message = span_notice("Ваш разум расслабляется.")
+ selection_activated_message = span_notice_alt("Вы готовите свой разум к разрушительной атаке. ЛКМ по цели, чтобы применить!")
+ selection_deactivated_message = span_notice_alt("Ваш разум расслабляется.")
need_active_overlay = TRUE
/obj/effect/proc_holder/spell/ascendant_annihilate/create_new_targeting()
@@ -881,8 +881,8 @@
clothes_req = FALSE
human_req = FALSE
action_icon_state = "enthrall"
- selection_activated_message = span_notice("Вы готовите свой разум к тому, чтобы промыть чужое сознание. ЛКМ по цели, чтобы применить!")
- selection_deactivated_message = span_notice("Ваш разум расслабляется.")
+ selection_activated_message = span_notice_alt("Вы готовите свой разум к тому, чтобы промыть чужое сознание. ЛКМ по цели, чтобы применить!")
+ selection_deactivated_message = span_notice_alt("Ваш разум расслабляется.")
need_active_overlay = TRUE
/obj/effect/proc_holder/spell/ascendant_hypnosis/create_new_targeting()
diff --git a/code/game/machinery/computer/crew.dm b/code/game/machinery/computer/crew.dm
index 27b1802424b0..99b9bc9532e1 100644
--- a/code/game/machinery/computer/crew.dm
+++ b/code/game/machinery/computer/crew.dm
@@ -78,6 +78,12 @@
var/obj/machinery/computer/crew/attached_console
+/obj/item/circuit_component/medical_console_data/Destroy()
+ if(attached_console)
+ unregister_usb_parent(attached_console)
+ records = null
+ . = ..()
+
/obj/item/circuit_component/medical_console_data/populate_ports()
records = add_output_port("Данные мониторинга экипажа", PORT_TYPE_TABLE)
diff --git a/code/game/machinery/computer/message.dm b/code/game/machinery/computer/message.dm
index fc6fdb574202..92a17f21bf21 100644
--- a/code/game/machinery/computer/message.dm
+++ b/code/game/machinery/computer/message.dm
@@ -10,15 +10,15 @@
//Server linked to.
var/obj/machinery/message_server/linkedServer = null
//Messages - Saves me time if I want to change something.
- var/noserver = span_alert("ALERT: No server detected.")
- var/incorrectkey = span_warning("ALERT: Incorrect decryption key!")
- var/defaultmsg = span_notice("Welcome. Please select an option.")
- var/rebootmsg = span_warning("%$&(�: Critical %$$@ Error // !RestArting! - ?pLeaSe wAit!")
+ var/noserver = span_alert_alt("ALERT: No server detected.")
+ var/incorrectkey = span_warning_alt("ALERT: Incorrect decryption key!")
+ var/defaultmsg = span_notice_alt("Welcome. Please select an option.")
+ var/rebootmsg = span_warning_alt("%$&(�: Critical %$$@ Error // !RestArting! - ?pLeaSe wAit!")
//Computer properties
var/screen = 0 // 0 = Main menu, 1 = Message Logs, 2 = Hacked screen, 3 = Custom Message
var/hacking = 0 // Is it being hacked into by the AI/Cyborg
var/emag = 0 // When it is emagged.
- var/message = span_notice("System bootup complete. Please select an option.") // The message that shows on the main menu.
+ var/message = span_notice_alt("System bootup complete. Please select an option.") // The message that shows on the main menu.
var/auth = 0 // Are they authenticated?
var/optioncount = 8
// Custom Message Properties
diff --git a/code/game/machinery/doors/spacepod.dm b/code/game/machinery/doors/spacepod.dm
index be00efb6308e..7a2dfb45b61a 100644
--- a/code/game/machinery/doors/spacepod.dm
+++ b/code/game/machinery/doors/spacepod.dm
@@ -4,14 +4,14 @@
icon = 'icons/effects/beam.dmi'
icon_state = "n_beam"
anchored = TRUE
- var/id = 1.0
+ var/id = 1
/obj/structure/spacepoddoor/Initialize(mapload)
. = ..()
recalculate_atmos_connectivity()
-/obj/structure/spacepoddoor/CanAtmosPass(turf/T, vertical)
- return 0
+/obj/structure/spacepoddoor/CanAtmosPass(direction)
+ return FALSE
/obj/structure/spacepoddoor/Destroy()
var/turf/T = get_turf(src)
diff --git a/code/game/machinery/firealarm.dm b/code/game/machinery/firealarm.dm
index ce34e21c084c..3edc21dcd520 100644
--- a/code/game/machinery/firealarm.dm
+++ b/code/game/machinery/firealarm.dm
@@ -370,6 +370,16 @@ Just a object used in constructing fire alarms
var/obj/machinery/firealarm/attached_alarm
+/obj/item/circuit_component/firealarm/Destroy()
+ if(attached_alarm)
+ unregister_usb_parent(attached_alarm)
+ alarm_trigger = null
+ reset_trigger = null
+ is_on = null
+ triggered = null
+ reset = null
+ . = ..()
+
/obj/item/circuit_component/firealarm/populate_ports()
alarm_trigger = add_input_port("Тревога", PORT_TYPE_SIGNAL)
reset_trigger = add_input_port("Отбой", PORT_TYPE_SIGNAL)
diff --git a/code/game/machinery/lightswitch.dm b/code/game/machinery/lightswitch.dm
index 2b0f72e85163..42090ad47e4d 100644
--- a/code/game/machinery/lightswitch.dm
+++ b/code/game/machinery/lightswitch.dm
@@ -138,6 +138,13 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/machinery/light_switch, 26)
var/obj/machinery/light_switch/attached_switch
+/obj/item/circuit_component/light_switch/Destroy()
+ if(attached_switch)
+ unregister_usb_parent(attached_switch)
+ on_setting = null
+ is_on = null
+ . = ..()
+
/obj/item/circuit_component/light_switch/populate_ports()
on_setting = add_input_port("Вкл", PORT_TYPE_NUMBER)
is_on = add_output_port("Включено", PORT_TYPE_NUMBER)
diff --git a/code/game/machinery/quantum_pad.dm b/code/game/machinery/quantum_pad.dm
index ce7e7df97e93..30b5fad73f89 100644
--- a/code/game/machinery/quantum_pad.dm
+++ b/code/game/machinery/quantum_pad.dm
@@ -166,6 +166,13 @@
var/obj/machinery/quantumpad/attached_pad
+/obj/item/circuit_component/quantumpad/Destroy()
+ if(attached_pad)
+ unregister_usb_parent(attached_pad)
+ target_pad = null
+ failed = null
+ . = ..()
+
/obj/item/circuit_component/quantumpad/populate_ports()
target_pad = add_input_port("Платформа", PORT_TYPE_ATOM)
failed = add_output_port("Ошибка", PORT_TYPE_SIGNAL)
diff --git a/code/game/mecha/equipment/tools/work_tools.dm b/code/game/mecha/equipment/tools/work_tools.dm
index 409069d44423..baef3e3fc601 100644
--- a/code/game/mecha/equipment/tools/work_tools.dm
+++ b/code/game/mecha/equipment/tools/work_tools.dm
@@ -145,7 +145,7 @@
/obj/item/mecha_parts/mecha_equipment/rcd/Initialize(mapload)
GLOB.rcd_list += src
- rcd_holder = new(rcd_holder)
+ rcd_holder = new(loc)
rcd_holder.power_use_multiplier = energy_drain
rcd_holder.canRwall = TRUE
. = ..()
@@ -153,7 +153,7 @@
/obj/item/mecha_parts/mecha_equipment/rcd/Destroy()
GLOB.rcd_list -= src
rcd_holder.chassis = null
- qdel(rcd_holder)
+ QDEL_NULL(rcd_holder)
return ..()
/obj/item/mecha_parts/mecha_equipment/rcd/attach_act(obj/mecha/M)
@@ -283,6 +283,15 @@
var/obj/item/mecha_parts/mecha_equipment/new_module = new module(src)
modules[module] = new_module
+/obj/item/mecha_parts/mecha_equipment/multimodule/Destroy()
+ for(var/key, value in modules)
+ if(!value)
+ return
+ qdel(value)
+ modules -= key
+ targeted_module = null
+ . = ..()
+
/obj/item/mecha_parts/mecha_equipment/multimodule/is_ranged()//add a distance restricted equipment. Why not?
return targeted_module?.is_ranged()
@@ -382,8 +391,6 @@
name = "cable layer"
desc = "Equipment for engineering exosuits. Lays cable along the exosuit's path."
icon_state = "mecha_wire"
- var/datum/event/event
- var/turf/old_turf
var/obj/structure/cable/last_piece
var/obj/item/stack/cable_coil/cable
var/max_cable = 1000
@@ -392,6 +399,11 @@
cable = new(src, 0)
. = ..()
+/obj/item/mecha_parts/mecha_equipment/cable_layer/Destroy()
+ QDEL_NULL(cable)
+ last_piece = null
+ . = ..()
+
/obj/item/mecha_parts/mecha_equipment/cable_layer/can_attach(obj/mecha/M)
if(..())
if(istype(M, /obj/mecha/working) || istype(M, /obj/mecha/combat/lockersyndie))
@@ -540,35 +552,46 @@
var/turf/T1 = get_step(T,turn(direction, 90))
var/turf/T2 = get_step(T,turn(direction, -90))
- var/list/the_targets = list(T,T1,T2)
+ var/list/the_targets = list(T, T1, T2)
start_cooldown()
- spawn(0)
- for(var/a = 0 to 5)
- var/obj/effect/particle_effect/water/W = new (get_turf(chassis))
- if(!W)
- return
- var/turf/my_target = pick(the_targets)
- var/datum/reagents/R = new/datum/reagents(5)
- W.reagents = R
- R.my_atom = W
- reagents.trans_to(W,1)
- for(var/b=0, b<4, b++)
- if(!W)
- return
- step_towards(W,my_target)
- if(!W)
- return
- var/turf/W_turf = get_turf(W)
- W.reagents.reaction(W_turf)
- for(var/atom/atm in W_turf)
- W.reagents.reaction(atm)
- if(isliving(atm)) //For extinguishing mobs on fire
- var/mob/living/M = atm
- M.ExtinguishMob()
-
- if(W.loc == my_target)
- break
- sleep(2)
+ water_effect(the_targets)
+
+/obj/item/mecha_parts/mecha_equipment/extinguisher/proc/water_effect(list/the_targets)
+ set waitfor = FALSE
+
+ for(var/i in 0 to 5)
+ var/obj/effect/particle_effect/water/water_effect = new (get_turf(chassis))
+
+ if(!water_effect)
+ return
+
+ var/turf/my_target = pick(the_targets)
+ var/datum/reagents/reagents = new (5)
+ water_effect.reagents = reagents
+ reagents.my_atom = water_effect
+ reagents.trans_to(water_effect, 1)
+
+ for(var/j in 0 to 3)
+ if(!water_effect)
+ return
+
+ step_towards(water_effect, my_target)
+
+ if(!water_effect)
+ return
+
+ var/turf/water_turf = get_turf(water_effect)
+ water_effect.reagents.reaction(water_turf)
+ for(var/atom/atom in water_turf)
+ water_effect.reagents.reaction(atom)
+ if(isliving(atom)) //For extinguishing mobs on fire
+ var/mob/living/living_mob = atom
+ living_mob.ExtinguishMob()
+
+ if(water_effect.loc == my_target)
+ break
+
+ sleep(2)
/obj/item/mecha_parts/mecha_equipment/extinguisher/on_reagent_change()
return
@@ -598,6 +621,10 @@
var/creation_time = 0 //time to create a holosbarriers in deciseconds.
var/holocreator_busy = FALSE //to prevent placing multiple holo barriers at once
+/obj/item/mecha_parts/mecha_equipment/holowall/Destroy()
+ QDEL_LIST(barriers)
+ . = ..()
+
/obj/item/mecha_parts/mecha_equipment/holowall/action(atom/target) //copypasted from extinguisher. TODO: Rewrite from scratch.
if(!action_checks(target) || get_dist(chassis, target) > 5)
return FALSE
diff --git a/code/game/mecha/mecha.dm b/code/game/mecha/mecha.dm
index 7f1ae1ec1725..3cc79fbf9cc9 100644
--- a/code/game/mecha/mecha.dm
+++ b/code/game/mecha/mecha.dm
@@ -196,6 +196,48 @@
AddElement(/datum/element/falling_hazard, damage = 100, hardhat_safety = FALSE, crushes = TRUE)
+/obj/mecha/Destroy()
+
+ for(var/atom/movable/cargo_thing as anything in cargo)
+ cargo -= cargo_thing
+ cargo_thing.forceMove(drop_location())
+ step_rand(cargo_thing)
+
+ if(occupant)
+ occupant.SetSleeping(destruction_sleep_duration)
+ go_out()
+ var/mob/living/silicon/ai/AI
+ for(var/mob/M in src) //Let's just be ultra sure
+ if(isAI(M))
+ occupant = null
+ AI = M //AIs are loaded into the mech computer itself. When the mech dies, so does the AI. They can be recovered with an AI card from the wreck.
+ else
+ M.forceMove(loc)
+ for(var/obj/item/mecha_parts/mecha_equipment/E in equipment)
+ E.detach(loc)
+ qdel(E)
+ equipment.Cut()
+ QDEL_NULL(cell)
+ QDEL_NULL(internal_tank)
+ if(AI)
+ AI.gib() //No wreck, no AI to recover
+ STOP_PROCESSING(SSobj, src)
+ GLOB.poi_list.Remove(src)
+ var/turf/location = get_turf(src)
+ if(location)
+ location.blind_release_air(cabin_air)
+ else
+ qdel(cabin_air)
+ cabin_air = null
+ QDEL_NULL(spark_system)
+ QDEL_NULL(smoke_system)
+ QDEL_LIST(trackers)
+ QDEL_NULL(ui_view)
+ QDEL_NULL(radio)
+ lose_hearing_sensitivity(trait_source = ROUNDSTART_TRAIT)
+ GLOB.mechas_list -= src //global mech list
+ return ..()
+
////////////////////////
////// Helpers /////////
////////////////////////
@@ -815,46 +857,6 @@
if(A in trackers)
trackers -= A
-/obj/mecha/Destroy()
-
- for(var/atom/movable/cargo_thing as anything in cargo)
- cargo -= cargo_thing
- cargo_thing.forceMove(drop_location())
- step_rand(cargo_thing)
-
- if(occupant)
- occupant.SetSleeping(destruction_sleep_duration)
- go_out()
- var/mob/living/silicon/ai/AI
- for(var/mob/M in src) //Let's just be ultra sure
- if(isAI(M))
- occupant = null
- AI = M //AIs are loaded into the mech computer itself. When the mech dies, so does the AI. They can be recovered with an AI card from the wreck.
- else
- M.forceMove(loc)
- for(var/obj/item/mecha_parts/mecha_equipment/E in equipment)
- E.detach(loc)
- qdel(E)
- equipment.Cut()
- QDEL_NULL(cell)
- QDEL_NULL(internal_tank)
- if(AI)
- AI.gib() //No wreck, no AI to recover
- STOP_PROCESSING(SSobj, src)
- GLOB.poi_list.Remove(src)
- var/turf/location = get_turf(src)
- if(location)
- location.blind_release_air(cabin_air)
- else
- qdel(cabin_air)
- cabin_air = null
- QDEL_NULL(spark_system)
- QDEL_NULL(smoke_system)
- QDEL_LIST(trackers)
- QDEL_NULL(ui_view)
- GLOB.mechas_list -= src //global mech list
- return ..()
-
//TODO
/obj/mecha/emp_act(severity)
if(get_charge())
diff --git a/code/game/mecha/mecha_parts.dm b/code/game/mecha/mecha_parts.dm
index 41e3c1dd5faa..34a782e0ed6f 100644
--- a/code/game/mecha/mecha_parts.dm
+++ b/code/game/mecha/mecha_parts.dm
@@ -17,7 +17,7 @@
/obj/item/mecha_parts/chassis/Destroy()
QDEL_NULL(construct)
- return ..()
+ . = ..()
/obj/item/mecha_parts/chassis/attackby(obj/item/I, mob/user, params)
if(construct?.action(I, user))
diff --git a/code/game/objects/effects/decals/Cleanable/humans.dm b/code/game/objects/effects/decals/Cleanable/humans.dm
index 119559fc2f93..3139655eaa1d 100644
--- a/code/game/objects/effects/decals/Cleanable/humans.dm
+++ b/code/game/objects/effects/decals/Cleanable/humans.dm
@@ -311,6 +311,7 @@
/obj/effect/decal/cleanable/blood/gibs/proc/streak(list/directions)
set waitfor = 0
+
var/direction = pick(directions)
for(var/i = 0, i < pick(1, 200; 2, 150; 3, 50; 4), i++)
sleep(3)
diff --git a/code/game/objects/effects/temporary_visuals/projectile/tracer.dm b/code/game/objects/effects/temporary_visuals/projectile/tracer.dm
index 9a4cb163f285..8e03aeabbaa1 100644
--- a/code/game/objects/effects/temporary_visuals/projectile/tracer.dm
+++ b/code/game/objects/effects/temporary_visuals/projectile/tracer.dm
@@ -48,11 +48,13 @@
return
var/list/turf/line_of_sight = get_line(starting_position.return_turf(), ending_position.return_turf())
- for(var/turf/current_turf as anything in line_of_sight)
- for(var/obj/effect/projectile_lighting/existing_lighting in current_turf)
- if(existing_lighting.owner == locateUID(lighting_instance_key))
- continue
- QDEL_IN(new /obj/effect/projectile_lighting(current_turf, lighting_color_override, lighting_range, lighting_intensity, lighting_instance_key), deletion_delay > 0 ? deletion_delay : 5)
+
+ tracing_line:
+ for(var/turf/current_turf as anything in line_of_sight)
+ for(var/obj/effect/projectile_lighting/existing_lighting in current_turf)
+ if(existing_lighting.owner == lighting_instance_key)
+ continue tracing_line
+ QDEL_IN(new /obj/effect/projectile_lighting(current_turf, lighting_color_override, lighting_range, lighting_intensity, lighting_instance_key), deletion_delay > 0 ? deletion_delay : 5)
line_of_sight = null
if(deletion_delay)
diff --git a/code/game/objects/items.dm b/code/game/objects/items.dm
index 265b4c2944b7..fd86842574b0 100644
--- a/code/game/objects/items.dm
+++ b/code/game/objects/items.dm
@@ -291,6 +291,11 @@ GLOBAL_DATUM_INIT(fire_overlay, /mutable_appearance, mutable_appearance('icons/g
if(isstorage(loc))
item_flags |= IN_STORAGE
+ var/list/attack_verb_cached = attack_verb
+
+ if(islist(attack_verb_cached))
+ attack_verb = string_list(attack_verb_cached)
+
if(!hitsound)
if(damtype == FIRE)
hitsound = 'sound/items/welder.ogg'
diff --git a/code/game/objects/items/devices/camera_bug.dm b/code/game/objects/items/devices/camera_bug.dm
index a3680f634c72..667583847e77 100644
--- a/code/game/objects/items/devices/camera_bug.dm
+++ b/code/game/objects/items/devices/camera_bug.dm
@@ -35,6 +35,7 @@
integrated_console.network = list("SS13")
/obj/item/camera_bug/Destroy()
+ integrated_console.parent = null
QDEL_NULL(integrated_console)
return ..()
diff --git a/code/game/objects/items/devices/radio/radio.dm b/code/game/objects/items/devices/radio/radio.dm
index d76ff575228c..8130cfc8e095 100644
--- a/code/game/objects/items/devices/radio/radio.dm
+++ b/code/game/objects/items/devices/radio/radio.dm
@@ -152,6 +152,7 @@ GLOBAL_LIST_INIT(default_pirate_channels, list(
set_on(FALSE)
SSradio?.remove_object_all(src)
LAZYCLEARLIST(secure_radio_connections)
+ radio_connection = null
GLOB.global_radios -= src
return ..()
diff --git a/code/game/objects/items/devices/scanners/t_scanner.dm b/code/game/objects/items/devices/scanners/t_scanner.dm
index 82aa07569924..9ef657e86fef 100644
--- a/code/game/objects/items/devices/scanners/t_scanner.dm
+++ b/code/game/objects/items/devices/scanners/t_scanner.dm
@@ -154,6 +154,10 @@
spark_system.set_up(5, 0, src)
spark_system.attach(src)
+/obj/item/t_scanner/security/Destroy()
+ QDEL_NULL(spark_system)
+ . = ..()
+
/obj/item/t_scanner/security/update_icon_state()
if(burnt)
icon_state = "[base_icon_state]_burnt"
diff --git a/code/game/objects/items/devices/voice.dm b/code/game/objects/items/devices/voice.dm
index 0b6e9902260a..80eb3b41ed56 100644
--- a/code/game/objects/items/devices/voice.dm
+++ b/code/game/objects/items/devices/voice.dm
@@ -25,7 +25,7 @@
/obj/item/voice_changer/Destroy()
if(isitem(parent))
LAZYREMOVE(parent.actions, actions)
-
+ parent = null
return ..()
/obj/item/voice_changer/attack_self(mob/user)
diff --git a/code/game/objects/items/misc.dm b/code/game/objects/items/misc.dm
index c0968276e28b..a528807fea5f 100644
--- a/code/game/objects/items/misc.dm
+++ b/code/game/objects/items/misc.dm
@@ -236,7 +236,7 @@
return
var/datum/effect_system/fluid_spread/smoke/chem/quick/vapor/smoke = new
- smoke.set_up(range = round(clamp(cycle_count/10, 0, 4)), location = loc)
+ smoke.set_up(range = round(clamp(cycle_count / 10, 0, 4)), location = get_turf(usr))
smoke.start()
/obj/item/ecig/syndi
diff --git a/code/game/objects/items/weapons/RCD.dm b/code/game/objects/items/weapons/RCD.dm
index c3bfa7fc3ae3..884dcd9884fe 100644
--- a/code/game/objects/items/weapons/RCD.dm
+++ b/code/game/objects/items/weapons/RCD.dm
@@ -480,6 +480,12 @@
power_use_multiplier = 250
var/obj/mecha/chassis = null
+/obj/item/rcd/mecha_ref/Destroy()
+ var/obj/item/mecha_parts/mecha_equipment/rcd/holder = loc
+ if(istype(holder))
+ holder.rcd_holder = null
+ . = ..()
+
/obj/item/rcd/mecha_ref/useResource(amount, mob/user)
if(!chassis)
return
diff --git a/code/game/objects/items/weapons/cards_ids.dm b/code/game/objects/items/weapons/cards_ids.dm
index 6079f8bd408a..5c8e9f6defda 100644
--- a/code/game/objects/items/weapons/cards_ids.dm
+++ b/code/game/objects/items/weapons/cards_ids.dm
@@ -137,18 +137,21 @@
var/obj/item/card/id/guest/guest_pass = null // Guest pass attached to the ID
+
/obj/item/card/id/Initialize(mapload)
. = ..()
RegisterSignal(src, COMSIG_FREEZE_LINKED_ACCOUNT, PROC_REF(freeze_linked_account))
- spawn(30)
- if(ishuman(loc) && blood_type == "\[UNSET\]")
- var/mob/living/carbon/human/H = loc
- SetOwnerInfo(H)
+ addtimer(CALLBACK(src, PROC_REF(set_info)), 3 SECONDS)
/obj/item/card/id/Destroy()
UnregisterSignal(src, COMSIG_FREEZE_LINKED_ACCOUNT)
. = ..()
+/obj/item/card/id/proc/set_info()
+ if(ishuman(loc) && blood_type == "\[UNSET\]")
+ var/mob/living/carbon/human/human = loc
+ SetOwnerInfo(human)
+
/obj/item/card/id/proc/freeze_linked_account(datum/source)
SIGNAL_HANDLER
diff --git a/code/game/objects/items/weapons/dna_injector.dm b/code/game/objects/items/weapons/dna_injector.dm
index 79599d0a2996..e4b4e740bcee 100644
--- a/code/game/objects/items/weapons/dna_injector.dm
+++ b/code/game/objects/items/weapons/dna_injector.dm
@@ -117,8 +117,11 @@
)
else
to_chat(user, span_notice("You inject yourself with [src]."))
+
+ var/cached_damage_coeff = damage_coeff
+ var/damage_coeff_squared = POW2(cached_damage_coeff)
- target.apply_effect(rand(20 / (damage_coeff ** 2), 50 / (damage_coeff ** 2)), IRRADIATE, 0, 1)
+ target.apply_effect(rand(20 / damage_coeff_squared, 50 / damage_coeff_squared), IRRADIATE, 0, 1)
add_attack_logs(user, target, attack_log, ATKLOG_ALL)
used = TRUE
diff --git a/code/game/objects/items/weapons/grenades/atmosgrenade.dm b/code/game/objects/items/weapons/grenades/atmosgrenade.dm
index fb670276be5a..59285bcd8484 100644
--- a/code/game/objects/items/weapons/grenades/atmosgrenade.dm
+++ b/code/game/objects/items/weapons/grenades/atmosgrenade.dm
@@ -10,7 +10,7 @@
. = ..()
var/turf/simulated/target_turf = get_turf(src)
if(istype(target_turf))
- src.release_air(target_turf)
+ release_air(target_turf)
/obj/item/grenade/gas/proc/release_air(turf/simulated/target_turf)
// Any proc that wants MILLA to be synchronous should not sleep.
@@ -46,12 +46,10 @@
/obj/item/grenade/gluon/prime()
update_mob()
playsound(loc, 'sound/effects/empulse.ogg', 50, TRUE)
- for(var/turf/T in view(range, loc))
- if(isfloorturf(T))
- var/turf/simulated/F = T
- F.MakeSlippery(TURF_WET_PERMAFROST, 120 SECONDS)
- for(var/mob/living/carbon/L in T)
- L.apply_damage(stamina_damage, STAMINA)
- L.apply_effect(rad_damage, IRRADIATE)
- L.adjust_bodytemperature(-230)
+ for(var/turf/simulated/floor/floor_turf in view(range, loc))
+ floor_turf.MakeSlippery(TURF_WET_PERMAFROST, 120 SECONDS)
+ for(var/mob/living/carbon/carbon in floor_turf)
+ carbon.apply_damage(stamina_damage, STAMINA)
+ carbon.apply_effect(rad_damage, IRRADIATE)
+ carbon.adjust_bodytemperature(-230)
qdel(src)
diff --git a/code/game/objects/items/weapons/storage/internal.dm b/code/game/objects/items/weapons/storage/internal.dm
index ecc0c462490b..b127c450bea2 100644
--- a/code/game/objects/items/weapons/storage/internal.dm
+++ b/code/game/objects/items/weapons/storage/internal.dm
@@ -5,15 +5,17 @@
/obj/item/storage/internal
var/obj/item/master_item
-/obj/item/storage/internal/New(obj/item/MI)
- master_item = MI
- loc = master_item
+/obj/item/storage/internal/Initialize(mapload)
+ . = ..()
+ var/obj/item/master_item = loc
+ if(!istype(master_item))
+ return
+ src.master_item = master_item
name = master_item.name
- ..()
/obj/item/storage/internal/Destroy()
master_item = null
- return ..()
+ . = ..()
/obj/item/storage/internal/attack_hand()
return //make sure this is never picked up
diff --git a/code/game/objects/items/weapons/storage/storage.dm b/code/game/objects/items/weapons/storage/storage.dm
index 75950b873c51..1b117eb66096 100644
--- a/code/game/objects/items/weapons/storage/storage.dm
+++ b/code/game/objects/items/weapons/storage/storage.dm
@@ -187,7 +187,7 @@
L += F.contents
return L
-/obj/item/storage/proc/show_to(mob/user)
+/obj/item/storage/proc/show_to(mob/user, from_inv_observers = FALSE)
if(!user.client)
return
if(QDELETED(src))
@@ -215,13 +215,18 @@
user.s_active = src
LAZYOR(mobs_viewing, user)
+ RegisterSignal(user, COMSIG_QDELETING, PROC_REF(on_mob_qdeleting), TRUE)
+
+ if(from_inv_observers)
+ return
+
for(var/mob/dead/observer/observe in user.inventory_observers)
if(!observe.client)
LAZYREMOVE(user.inventory_observers, observe)
continue
- show_to(observe)
+ show_to(observe, TRUE)
-/obj/item/storage/proc/hide_from(mob/user)
+/obj/item/storage/proc/hide_from(mob/user, from_inv_observers = FALSE)
LAZYREMOVE(mobs_viewing, user) // Remove clientless mobs too
if(!user.client)
return
@@ -235,11 +240,20 @@
if(user.s_active == src)
user.s_active = null
+ UnregisterSignal(user, COMSIG_QDELETING)
+
+ if(from_inv_observers)
+ return
+
for(var/mob/dead/observer/observe in user.inventory_observers)
if(!observe.client)
LAZYREMOVE(user.inventory_observers, observe)
continue
- hide_from(observe)
+ hide_from(observe, TRUE)
+
+/obj/item/storage/proc/on_mob_qdeleting(mob/source, force)
+ SIGNAL_HANDLER
+ hide_from(source)
/obj/item/storage/proc/hide_from_all_viewers()
if(!LAZYLEN(mobs_viewing))
diff --git a/code/game/objects/items/weapons/tanks/watertank.dm b/code/game/objects/items/weapons/tanks/watertank.dm
index d85cad70bb7a..47a0129a95c0 100644
--- a/code/game/objects/items/weapons/tanks/watertank.dm
+++ b/code/game/objects/items/weapons/tanks/watertank.dm
@@ -16,11 +16,16 @@
var/on = 0
var/volume = 500
-/obj/item/watertank/New()
- ..()
+/obj/item/watertank/Initialize(mapload)
+ . = ..()
create_reagents(volume)
noz = make_noz()
+/obj/item/watertank/Destroy()
+ remove_noz()
+ QDEL_NULL(noz)
+ return ..()
+
/obj/item/watertank/ui_action_click(mob/user, datum/action/action, leftclick)
toggle_mister()
@@ -71,12 +76,6 @@
var/mob/user = noz.loc
user.drop_item_ground(noz, force = TRUE)
-/obj/item/watertank/Destroy()
- if(on)
- remove_noz()
- QDEL_NULL(noz)
- return ..()
-
/obj/item/watertank/attack_hand(mob/user)
if(loc == user)
ui_action_click()
@@ -106,14 +105,21 @@
var/obj/item/watertank/tank
-/obj/item/reagent_containers/spray/mister/New(parent_tank)
- ..()
- if(check_tank_exists(parent_tank, src))
- tank = parent_tank
+/obj/item/reagent_containers/spray/mister/Initialize(mapload)
+ . = ..()
+ if(check_tank_exists(loc, usr, src))
+ tank = loc
reagents = tank.reagents //This mister is really just a proxy for the tank's reagents
loc = tank
return
+/obj/item/reagent_containers/spray/mister/Destroy()
+ if(tank)
+ tank.remove_noz()
+ tank.noz = null
+ tank = null
+ . = ..()
+
/obj/item/reagent_containers/spray/mister/dropped(mob/user, slot, silent = FALSE)
. = ..()
to_chat(user, span_notice("The mister snaps back onto the watertank."))
@@ -123,13 +129,14 @@
/obj/item/reagent_containers/spray/mister/attack_self()
return
-/proc/check_tank_exists(parent_tank, mob/living/carbon/human/M, obj/O)
+/proc/check_tank_exists(parent_tank, mob/living/carbon/M, obj/O)
if(!parent_tank || !istype(parent_tank, /obj/item/watertank)) //To avoid weird issues from admin spawns
- M.temporarily_remove_item_from_inventory(O)
+ if(istype(M))
+ M.temporarily_remove_item_from_inventory(O)
qdel(O)
- return 0
+ return FALSE
else
- return 1
+ return TRUE
/obj/item/reagent_containers/spray/mister/Move(atom/newloc, direct = NONE, glide_size_override = 0, update_dir = TRUE)
. = ..()
@@ -147,8 +154,8 @@
icon_state = "waterbackpackjani"
item_state = "waterbackpackjani"
-/obj/item/watertank/janitor/New()
- ..()
+/obj/item/watertank/janitor/Initialize(mapload)
+ . = ..()
reagents.add_reagent("cleaner", 500)
/obj/item/reagent_containers/spray/mister/janitor
@@ -223,10 +230,11 @@
var/metal_synthesis_cooldown = 0
var/nanofrost_cooldown = 0
-/obj/item/extinguisher/mini/nozzle/New(parent_tank)
+/obj/item/extinguisher/mini/nozzle/Initialize(mapload)
. = ..()
- if(check_tank_exists(parent_tank, src))
- tank = parent_tank
+ if(check_tank_exists(loc, usr, src))
+ tank = loc
+ qdel(reagents)
reagents = tank.reagents
max_water = tank.volume
loc = tank
@@ -235,6 +243,11 @@
. = ..()
ADD_TRAIT(src, TRAIT_NODROP, INNATE_TRAIT)
+/obj/item/extinguisher/mini/nozzle/Destroy()
+ tank = null
+ reagents = null
+ . = ..()
+
/obj/item/extinguisher/mini/nozzle/Move(atom/newloc, direct = NONE, glide_size_override = 0, update_dir = TRUE)
. = ..()
if(tank && loc != tank.loc)
diff --git a/code/game/objects/items/weapons/twohanded.dm b/code/game/objects/items/weapons/twohanded.dm
index eeac032127f9..ac96118f98b5 100644
--- a/code/game/objects/items/weapons/twohanded.dm
+++ b/code/game/objects/items/weapons/twohanded.dm
@@ -701,7 +701,7 @@
/obj/item/twohanded/chainsaw_handmade/doomslayer
name = "OOOH BABY"
- desc = span_warning("VRRRRRRR!!!")
+ desc = span_warning_alt("VRRRRRRR!!!")
armour_penetration = 100
force_wielded = 30
diff --git a/code/game/objects/objs.dm b/code/game/objects/objs.dm
index bfbfa0ab3874..8751de68baf1 100644
--- a/code/game/objects/objs.dm
+++ b/code/game/objects/objs.dm
@@ -75,6 +75,16 @@
add_debris_element()
+/obj/Destroy(force)
+ if(!ismachinery(src))
+ if(!speed_process)
+ STOP_PROCESSING(SSobj, src) // TODO: Have a processing bitflag to reduce on unnecessary loops through the processing lists
+ else
+ STOP_PROCESSING(SSfastprocess, src)
+ SStgui.close_uis(src)
+ QDEL_NULL(multitool_menu)
+ return ..()
+
/obj/Topic(href, href_list, nowindow = FALSE, datum/ui_state/state = GLOB.default_state)
// Calling Topic without a corresponding window open causes runtime errors
if(!nowindow && ..())
@@ -97,16 +107,6 @@
// Nada
return
-/obj/Destroy(force)
- if(!ismachinery(src))
- if(!speed_process)
- STOP_PROCESSING(SSobj, src) // TODO: Have a processing bitflag to reduce on unnecessary loops through the processing lists
- else
- STOP_PROCESSING(SSfastprocess, src)
- SStgui.close_uis(src)
- QDEL_NULL(multitool_menu)
- return ..()
-
//user: The mob that is suiciding
//damagetype: The type of damage the item will inflict on the user
//BRUTELOSS = 1
diff --git a/code/game/objects/structures/false_walls.dm b/code/game/objects/structures/false_walls.dm
index 96b498bd68c0..f5aea93dfb33 100644
--- a/code/game/objects/structures/false_walls.dm
+++ b/code/game/objects/structures/false_walls.dm
@@ -55,7 +55,7 @@
recalculate_atmos_connectivity()
return ..()
-/obj/structure/falsewall/CanAtmosPass(turf/T, vertical)
+/obj/structure/falsewall/CanAtmosPass(direction)
return !density
/obj/structure/falsewall/attack_ghost(mob/user)
diff --git a/code/game/objects/structures/reflector.dm b/code/game/objects/structures/reflector.dm
index 1ccd6058fe88..27900bda123d 100644
--- a/code/game/objects/structures/reflector.dm
+++ b/code/game/objects/structures/reflector.dm
@@ -268,6 +268,12 @@
var/obj/structure/reflector/attached_reflector
+/obj/item/circuit_component/reflector/Destroy()
+ if(attached_reflector)
+ unregister_usb_parent(attached_reflector)
+ angle = null
+ . = ..()
+
/obj/item/circuit_component/reflector/populate_ports()
angle = add_input_port("Угол", PORT_TYPE_NUMBER)
diff --git a/code/game/objects/structures/statues.dm b/code/game/objects/structures/statues.dm
index 24b246c936d1..5cd82959a20b 100644
--- a/code/game/objects/structures/statues.dm
+++ b/code/game/objects/structures/statues.dm
@@ -59,7 +59,7 @@
span_notice("You rub some dust off from the [name]'s surface.")
)
-/obj/structure/statue/CanAtmosPass(turf/T, vertical)
+/obj/structure/statue/CanAtmosPass(direction)
return !density
/obj/structure/statue/deconstruct(disassembled = TRUE)
diff --git a/code/game/objects/structures/window.dm b/code/game/objects/structures/window.dm
index f9ebe28a36c9..ea8a1f8d4f2b 100644
--- a/code/game/objects/structures/window.dm
+++ b/code/game/objects/structures/window.dm
@@ -756,7 +756,7 @@ GLOBAL_LIST_INIT(wcCommon, pick(list("#379963", "#0d8395", "#58b5c3", "#49e46e",
flags = PREVENT_CLICK_UNDER | NO_SCREENTIPS
obj_flags = BLOCK_Z_IN_DOWN | BLOCK_Z_IN_UP
-/obj/structure/window/full/CanAtmosPass(turf/T, vertical)
+/obj/structure/window/full/CanAtmosPass(direction)
if(!anchored || !density)
return TRUE
return FALSE
diff --git a/code/game/objects/structures/wryn.dm b/code/game/objects/structures/wryn.dm
index 8f8ce5e9d8cc..42feca99d393 100644
--- a/code/game/objects/structures/wryn.dm
+++ b/code/game/objects/structures/wryn.dm
@@ -48,7 +48,7 @@
. = ..()
move_update_air(T)
-/obj/structure/wryn/wax/CanAtmosPass(turf/T, vertical)
+/obj/structure/wryn/wax/CanAtmosPass(direction)
return !density
// Structure themself
diff --git a/code/game/turfs/simulated/walls.dm b/code/game/turfs/simulated/walls.dm
index 4a4b435b647c..cd4bc39286be 100644
--- a/code/game/turfs/simulated/walls.dm
+++ b/code/game/turfs/simulated/walls.dm
@@ -11,7 +11,7 @@
var/damage_cap = 100 //Wall will break down to girders if damage reaches this point
var/damage_overlay
- var/global/damage_overlays[8]
+ var/static/damage_overlays[8]
var/max_temperature = 1800 //K, walls will take damage if they're next to a fire hotter than this
diff --git a/code/game/turfs/space/openspace.dm b/code/game/turfs/space/openspace.dm
index bb8443880f2c..666fd3dd436f 100644
--- a/code/game/turfs/space/openspace.dm
+++ b/code/game/turfs/space/openspace.dm
@@ -56,7 +56,7 @@
SIGNAL_HANDLER
if(ismovable(created_atom))
//Drop it only when it's finished initializing, not before.
- addtimer(CALLBACK(src, PROC_REF(zfall_if_on_turf), created_atom), 0 SECONDS)
+ zfall_if_on_turf(created_atom)
/turf/space/openspace/proc/zfall_if_on_turf(atom/movable/movable)
if(QDELETED(movable) || movable.loc != src)
diff --git a/code/game/turfs/turf.dm b/code/game/turfs/turf.dm
index dd0108b43621..22920f216cd0 100644
--- a/code/game/turfs/turf.dm
+++ b/code/game/turfs/turf.dm
@@ -502,7 +502,7 @@
for(var/dir in GLOB.cardinal)
T = get_step(src, dir)
if(istype(T) && !T.density)
- if(!CanAtmosPass(T, FALSE))
+ if(!CanAtmosPass(dir))
L.Add(T)
return L
@@ -1000,7 +1000,11 @@
air = get_readonly_air()
else
air = bound_air
- var/wind = sqrt(wind_x ** 2 + wind_y ** 2)
+
+ var/wind_x_cached = wind_x
+ var/wind_y_cached = wind_y
+
+ var/wind = MAGNITUDE(wind_x_cached, wind_y_cached)
var/wind_strength = wind * air.total_moles() / MOLES_CELLSTANDARD
current_wind.alpha = min(255, 5 + wind_strength * 25)
return TRUE
diff --git a/code/game/world.dm b/code/game/world.dm
index 16dc7e00d556..ab414a4b792b 100644
--- a/code/game/world.dm
+++ b/code/game/world.dm
@@ -1,5 +1,14 @@
GLOBAL_LIST_INIT(map_transition_config, MAP_TRANSITION_CONFIG)
-#define CLEAR_RUST_CACHE rustlib_clear_uuid_storage(); rustlib_iconforge_cleanup_all(); milla_reset();
+#define CLEAR_RUST_CACHE \
+ log_world("Starting UUID clear", TRUE); \
+ var/uuid_start = world.timeofday; \
+ rustlib_clear_uuid_storage(); \
+ log_world("UUID clear took [world.timeofday - uuid_start]ms", TRUE); \
+ \
+ log_world("Starting icon cache clear", TRUE); \
+ var/icon_start = world.timeofday; \
+ rustlib_iconforge_cleanup_all(); \
+ log_world("Icon cache clear took [world.timeofday - icon_start]ms", TRUE); \
#ifdef TEST_RUNNER
GLOBAL_DATUM(test_runner, /datum/test_runner)
@@ -129,8 +138,8 @@ GLOBAL_LIST_EMPTY(world_topic_handlers)
return
log_and_message_admins("has requested an immediate world restart via client side debugging tools")
to_chat(world, span_boldannounceooc("Rebooting world immediately due to host request"))
- rustg_log_close_all() // Past this point, no logging procs can be used, at risk of data loss.
CLEAR_RUST_CACHE
+ rustg_log_close_all() // Past this point, no logging procs can be used, at risk of data loss.
// Now handle a reboot
if(config && CONFIG_GET(flag/shutdown_on_reboot))
sleep(0)
@@ -165,8 +174,8 @@ GLOBAL_LIST_EMPTY(world_topic_handlers)
C << link("byond://[CONFIG_GET(string/server)]")
// And begin the real shutdown
- rustg_log_close_all() // Past this point, no logging procs can be used, at risk of data loss.
CLEAR_RUST_CACHE
+ rustg_log_close_all() // Past this point, no logging procs can be used, at risk of data loss.
if(config && CONFIG_GET(flag/shutdown_on_reboot))
sleep(0)
if(GLOB.shutdown_shell_command)
@@ -312,7 +321,6 @@ GLOBAL_LIST_EMPTY(world_topic_handlers)
/world/Del()
rustg_close_async_http_client() // Close the HTTP client. If you dont do this, youll get phantom threads which can crash DD from memory access violations
- CLEAR_RUST_CACHE
var/debug_server = world.GetConfig("env", "AUXTOOLS_DEBUG_DLL")
if(debug_server)
CALL_EXT(debug_server, "auxtools_shutdown")()
diff --git a/code/modules/antagonists/_common/antag_spawner.dm b/code/modules/antagonists/_common/antag_spawner.dm
index 862d4f08a331..1d679f88dd70 100644
--- a/code/modules/antagonists/_common/antag_spawner.dm
+++ b/code/modules/antagonists/_common/antag_spawner.dm
@@ -167,9 +167,9 @@
desc = "A magically infused bottle of blood, distilled from countless murder victims. Used in unholy rituals to attract horrifying creatures."
icon = 'icons/obj/wizard.dmi'
icon_state = "vial"
- var/shatter_msg = span_notice("You shatter the bottle, no \
+ var/shatter_msg = span_notice_alt("You shatter the bottle, no \
turning back now!")
- var/veil_msg = span_warning("You sense a dark presence lurking \
+ var/veil_msg = span_warning_alt("You sense a dark presence lurking \
just beyond the veil...")
var/objective_verb = "Kill"
var/mob/living/demon_type = /mob/living/simple_animal/demon/slaughter
@@ -232,7 +232,7 @@
countless hugging attacks. Used in funny rituals to attract \
adorable creatures."
icon_state = "vialtickles"
- veil_msg = span_warning("You sense an adorable presence \
+ veil_msg = span_warning_alt("You sense an adorable presence \
lurking just beyond the veil...")
objective_verb = "Hug and tickle"
demon_type = /mob/living/simple_animal/demon/slaughter/laughter
@@ -243,7 +243,7 @@
ground up shadowling bones. Used in dark rituals to attract \
dark creatures."
icon_state = "vialshadows"
- veil_msg = span_warning("You sense a dark presence \
+ veil_msg = span_warning_alt("You sense a dark presence \
lurking in the shadows...")
demon_type = /mob/living/simple_animal/demon/shadow
@@ -254,9 +254,9 @@
desc = "A magically infused bottle of ooze, distilled by methods rather not be spoken of. Used to awaken an all-consuming monstrosity."
icon = 'icons/obj/wizard.dmi'
icon_state = "vialooze"
- var/shatter_msg = span_notice("You shatter the bottle, no \
+ var/shatter_msg = span_notice_alt("You shatter the bottle, no \
turning back now!")
- var/veil_msg = span_warning("The sludge is awake and seeps \
+ var/veil_msg = span_warning_alt("The sludge is awake and seeps \
away...")
var/objective_verb = "Eat"
var/mob/living/morph_type = /mob/living/simple_animal/hostile/morph
@@ -316,8 +316,8 @@
desc = "A magically sealed lightbulb confining some manner of electricity based creature."
icon = 'icons/obj/lighting.dmi'
icon_state = "lbulb"
- var/shatter_msg = span_notice("You shatter the bulb, no turning back now!")
- var/veil_msg = span_warning("The creature sparks energetically and zips away...")
+ var/shatter_msg = span_notice_alt("You shatter the bulb, no turning back now!")
+ var/veil_msg = span_warning_alt("The creature sparks energetically and zips away...")
var/objective_verb = "Electrocute"
var/mob/living/demon_type = /mob/living/simple_animal/demon/pulse_demon
diff --git a/code/modules/antagonists/blob/structures/_blob.dm b/code/modules/antagonists/blob/structures/_blob.dm
index d511e3906720..8aa03fd2c4c6 100644
--- a/code/modules/antagonists/blob/structures/_blob.dm
+++ b/code/modules/antagonists/blob/structures/_blob.dm
@@ -90,7 +90,7 @@
result++
. -= result - 1
-/obj/structure/blob/CanAtmosPass(turf/T, vertical)
+/obj/structure/blob/CanAtmosPass(direction)
return !atmosblock
/obj/structure/blob/get_superconductivity(direction)
diff --git a/code/modules/antagonists/borer/borer_spell.dm b/code/modules/antagonists/borer/borer_spell.dm
index 5f983903b7a3..856e9068ee25 100644
--- a/code/modules/antagonists/borer/borer_spell.dm
+++ b/code/modules/antagonists/borer/borer_spell.dm
@@ -5,8 +5,8 @@
clothes_req = FALSE
action_icon_state = "infest"
action_background_icon_state = "bg_alien"
- selection_activated_message = span_notice("Вы приготовились заразить жертву. Left-click чтобы применить способность!")
- selection_deactivated_message = span_notice("Вы прекратили свои попытки заразить жертву.")
+ selection_activated_message = span_notice_alt("Вы приготовились заразить жертву. Left-click чтобы применить способность!")
+ selection_deactivated_message = span_notice_alt("Вы прекратили свои попытки заразить жертву.")
need_active_overlay = TRUE
human_req = FALSE
var/infesting = FALSE
@@ -68,8 +68,8 @@
clothes_req = FALSE
action_icon_state = "genetic_cryo"
action_background_icon_state = "bg_alien"
- selection_activated_message = span_notice("Вы приготовились поразить жертву. Left-click чтобы применить способность!")
- selection_deactivated_message = span_notice("Вы решили дать своей жертве шанс. Пока что.")
+ selection_activated_message = span_notice_alt("Вы приготовились поразить жертву. Left-click чтобы применить способность!")
+ selection_deactivated_message = span_notice_alt("Вы решили дать своей жертве шанс. Пока что.")
need_active_overlay = TRUE
human_req = FALSE
diff --git a/code/modules/antagonists/malf_ai/Malf_Modules.dm b/code/modules/antagonists/malf_ai/Malf_Modules.dm
index cbafc478394e..ebfb2eb87757 100644
--- a/code/modules/antagonists/malf_ai/Malf_Modules.dm
+++ b/code/modules/antagonists/malf_ai/Malf_Modules.dm
@@ -73,8 +73,8 @@
//The actual ranged proc holder.
/obj/effect/proc_holder/ranged_ai
- var/enable_text = span_notice("Hello World!") //Appears when the user activates the ability
- var/disable_text = span_danger("Goodbye Cruel World!") //Context clues!
+ var/enable_text = span_notice_alt("Hello World!") //Appears when the user activates the ability
+ var/disable_text = span_danger_alt("Goodbye Cruel World!") //Context clues!
var/datum/action/innate/ai/ranged/attached_action
/obj/effect/proc_holder/ranged_ai/proc/toggle(mob/user)
@@ -206,7 +206,7 @@
var/one_purchase = FALSE //If this module can only be purchased once. This always applies to upgrades, even if the variable is set to false.
var/power_type = /datum/action/innate/ai //If the module gives an active ability, use this. Mutually exclusive with upgrade.
var/upgrade //If the module gives a passive upgrade, use this. Mutually exclusive with power_type.
- var/unlock_text = span_notice("Hello World!") //Text shown when an ability is unlocked
+ var/unlock_text = span_notice_alt("Hello World!") //Text shown when an ability is unlocked
var/unlock_sound //Sound played when an ability is unlocked
var/uses
@@ -225,7 +225,7 @@
cost = 130
one_purchase = TRUE
power_type = /datum/action/innate/ai/nuke_station
- unlock_text = span_notice("You slowly, carefully, establish a connection with the on-station self-destruct. You can now activate it at any time.")
+ unlock_text = span_notice_alt("You slowly, carefully, establish a connection with the on-station self-destruct. You can now activate it at any time.")
unlock_sound = 'sound/items/timer.ogg'
/datum/action/innate/ai/nuke_station
@@ -337,7 +337,7 @@
description = "Improves the power and health of all AI turrets. This effect is permanent."
cost = 30
upgrade = TRUE
- unlock_text = span_notice("You establish a power diversion to your turrets, upgrading their health and damage.")
+ unlock_text = span_notice_alt("You establish a power diversion to your turrets, upgrading their health and damage.")
unlock_sound = 'sound/items/rped.ogg'
/datum/AI_Module/large/upgrade_turrets/upgrade(mob/living/silicon/ai/AI)
@@ -357,7 +357,7 @@
cost = 30
one_purchase = TRUE
power_type = /datum/action/innate/ai/lockdown
- unlock_text = span_notice("You upload a sleeper trojan into the door control systems. You can send a signal to set it off at any time.")
+ unlock_text = span_notice_alt("You upload a sleeper trojan into the door control systems. You can send a signal to set it off at any time.")
/datum/action/innate/ai/lockdown
name = "Lockdown"
@@ -377,7 +377,7 @@
cost = 25
one_purchase = TRUE
power_type = /datum/action/innate/ai/destroy_rcds
- unlock_text = span_notice("After some improvisation, you rig your onboard radio to be able to send a signal to detonate all RCDs.")
+ unlock_text = span_notice_alt("After some improvisation, you rig your onboard radio to be able to send a signal to detonate all RCDs.")
/datum/action/innate/ai/destroy_rcds
name = "Destroy RCDs"
@@ -402,7 +402,7 @@
Do not allow the mech to leave the station's vicinity or allow it to be destroyed."
cost = 30
upgrade = TRUE
- unlock_text = span_notice("Virus package compiled. Select a target mech at any time. You must remain on the station at all times. Loss of signal will result in total system lockout.")
+ unlock_text = span_notice_alt("Virus package compiled. Select a target mech at any time. You must remain on the station at all times. Loss of signal will result in total system lockout.")
unlock_sound = 'sound/mecha/nominal.ogg'
/datum/AI_Module/large/mecha_domination/upgrade(mob/living/silicon/ai/AI)
@@ -417,7 +417,7 @@
one_purchase = TRUE
cost = 25
power_type = /datum/action/innate/ai/break_fire_alarms
- unlock_text = span_notice("You replace the thermal sensing capabilities of all fire alarms with a manual override, allowing you to turn them off at will.")
+ unlock_text = span_notice_alt("You replace the thermal sensing capabilities of all fire alarms with a manual override, allowing you to turn them off at will.")
/datum/action/innate/ai/break_fire_alarms
name = "Override Thermal Sensors"
@@ -442,7 +442,7 @@
one_purchase = TRUE
cost = 50
power_type = /datum/action/innate/ai/break_air_alarms
- unlock_text = span_notice("You remove the safety overrides on all air alarms, but you leave the confirm prompts open. You can hit 'Yes' at any time... you bastard.")
+ unlock_text = span_notice_alt("You remove the safety overrides on all air alarms, but you leave the confirm prompts open. You can hit 'Yes' at any time... you bastard.")
/datum/action/innate/ai/break_air_alarms
name = "Override Air Alarm Safeties"
@@ -465,7 +465,7 @@
description = "Overheats an electrical machine, causing a small explosion and destroying it. Two uses per purchase."
cost = 20
power_type = /datum/action/innate/ai/ranged/overload_machine
- unlock_text = span_notice("You enable the ability for the station's APCs to direct intense energy into machinery.")
+ unlock_text = span_notice_alt("You enable the ability for the station's APCs to direct intense energy into machinery.")
/datum/action/innate/ai/ranged/overload_machine
name = "Overload Machine"
@@ -486,8 +486,8 @@
/obj/effect/proc_holder/ranged_ai/overload_machine
ranged_mousepointer = 'icons/effects/overload_machine_target.dmi'
- enable_text = span_notice("You tap into the station's powernet. Click on a machine to detonate it, or use the ability again to cancel.")
- disable_text = span_notice("You release your hold on the powernet.")
+ enable_text = span_notice_alt("You tap into the station's powernet. Click on a machine to detonate it, or use the ability again to cancel.")
+ disable_text = span_notice_alt("You release your hold on the powernet.")
/obj/effect/proc_holder/ranged_ai/overload_machine/InterceptClickOn(mob/living/requester, params, obj/machinery/target)
if(..())
@@ -519,7 +519,7 @@
description = "Overrides a machine's programming, causing it to rise up and attack everyone except other machines. Four uses."
cost = 30
power_type = /datum/action/innate/ai/ranged/override_machine
- unlock_text = span_notice("You procure a virus from the Space Dark Web and distribute it to the station's machines.")
+ unlock_text = span_notice_alt("You procure a virus from the Space Dark Web and distribute it to the station's machines.")
/datum/action/innate/ai/ranged/override_machine
name = "Override Machine"
@@ -538,8 +538,8 @@
/obj/effect/proc_holder/ranged_ai/override_machine
ranged_mousepointer = 'icons/effects/override_machine_target.dmi'
- enable_text = span_notice("You tap into the station's powernet. Click on a machine to animate it, or use the ability again to cancel.")
- disable_text = span_notice("You release your hold on the powernet.")
+ enable_text = span_notice_alt("You tap into the station's powernet. Click on a machine to animate it, or use the ability again to cancel.")
+ disable_text = span_notice_alt("You release your hold on the powernet.")
/obj/effect/proc_holder/ranged_ai/override_machine/InterceptClickOn(mob/living/requester, params, obj/machinery/target)
if(..())
@@ -572,7 +572,7 @@
cost = 100
one_purchase = TRUE
power_type = /datum/action/innate/ai/place_transformer
- unlock_text = span_notice("You prepare a robotics factory for deployment.")
+ unlock_text = span_notice_alt("You prepare a robotics factory for deployment.")
unlock_sound = 'sound/machines/ping.ogg'
/datum/action/innate/ai/place_transformer
@@ -645,7 +645,7 @@
description = "Attempts to overload the lighting circuits on the station, destroying some bulbs. Three uses."
cost = 15
power_type = /datum/action/innate/ai/blackout
- unlock_text = span_notice("You hook into the powernet and route bonus power towards the station's lighting.")
+ unlock_text = span_notice_alt("You hook into the powernet and route bonus power towards the station's lighting.")
/datum/action/innate/ai/blackout
name = "Blackout"
@@ -680,7 +680,7 @@
cost = 10
one_purchase = TRUE
power_type = /datum/action/innate/ai/reactivate_cameras
- unlock_text = span_notice("You deploy nanomachines to the cameranet.")
+ unlock_text = span_notice_alt("You deploy nanomachines to the cameranet.")
/datum/action/innate/ai/reactivate_cameras
name = "Reactivate Cameras"
@@ -721,7 +721,7 @@
one_purchase = TRUE
cost = 35 //Decent price for omniscience!
upgrade = TRUE
- unlock_text = span_notice("OTA firmware distribution complete! Cameras upgraded: CAMSUPGRADED. Light amplification system online.")
+ unlock_text = span_notice_alt("OTA firmware distribution complete! Cameras upgraded: CAMSUPGRADED. Light amplification system online.")
unlock_sound = 'sound/items/rped.ogg'
/datum/AI_Module/large/upgrade_cameras/upgrade(mob/living/silicon/ai/AI)
@@ -753,7 +753,7 @@
cost = 30
one_purchase = TRUE
upgrade = TRUE
- unlock_text = span_notice("OTA firmware distribution complete! Cameras upgraded: Enhanced surveillance package online.")
+ unlock_text = span_notice_alt("OTA firmware distribution complete! Cameras upgraded: Enhanced surveillance package online.")
unlock_sound = 'sound/items/rped.ogg'
/datum/AI_Module/large/eavesdrop/upgrade(mob/living/silicon/ai/AI)
@@ -767,7 +767,7 @@
cost = 10
one_purchase = TRUE
upgrade = TRUE
- unlock_text = span_notice("Network chip short circuited. Internal camera disconected from network. Minimal damage to other internal components.")
+ unlock_text = span_notice_alt("Network chip short circuited. Internal camera disconected from network. Minimal damage to other internal components.")
unlock_sound = 'sound/items/wirecutter.ogg'
/datum/AI_Module/large/cameracrack/upgrade(mob/living/silicon/ai/AI)
diff --git a/code/modules/antagonists/vampire/vampire_powers/gargantua_powers.dm b/code/modules/antagonists/vampire/vampire_powers/gargantua_powers.dm
index 5097f3a555ad..fefa4aa339e8 100644
--- a/code/modules/antagonists/vampire/vampire_powers/gargantua_powers.dm
+++ b/code/modules/antagonists/vampire/vampire_powers/gargantua_powers.dm
@@ -121,8 +121,8 @@
base_cooldown = 15 SECONDS
fireball_type = /obj/projectile/magic/demonic_grasp
- selection_activated_message = span_notice("Вы поднимаете руку, полную демонической энергии!")
- selection_deactivated_message = span_notice("Вы возвращаете себе энергию... пока что.")
+ selection_activated_message = span_notice_alt("Вы поднимаете руку, полную демонической энергии!")
+ selection_deactivated_message = span_notice_alt("Вы возвращаете себе энергию... пока что.")
action_icon_state = "demonic_grasp"
diff --git a/code/modules/antagonists/vampire/vampire_powers/hemomancer_powers.dm b/code/modules/antagonists/vampire/vampire_powers/hemomancer_powers.dm
index 6d91ad074656..d07083088130 100644
--- a/code/modules/antagonists/vampire/vampire_powers/hemomancer_powers.dm
+++ b/code/modules/antagonists/vampire/vampire_powers/hemomancer_powers.dm
@@ -126,8 +126,8 @@
var/area_of_affect = 1
need_active_overlay = TRUE
- selection_activated_message = span_notice("Вы используете магию крови, чтобы ослабить завесу блюспейса.")
- selection_deactivated_message = span_notice("Ваша магия ослабевает.")
+ selection_activated_message = span_notice_alt("Вы используете магию крови, чтобы ослабить завесу блюспейса.")
+ selection_deactivated_message = span_notice_alt("Ваша магия ослабевает.")
/obj/effect/proc_holder/spell/vampire/blood_tendrils/create_new_targeting()
var/datum/spell_targeting/click/T = new
diff --git a/code/modules/antagonists/vampire/vampire_powers/umbrae_powers.dm b/code/modules/antagonists/vampire/vampire_powers/umbrae_powers.dm
index 79bc00e276e4..2ba7398fd39f 100644
--- a/code/modules/antagonists/vampire/vampire_powers/umbrae_powers.dm
+++ b/code/modules/antagonists/vampire/vampire_powers/umbrae_powers.dm
@@ -197,7 +197,7 @@
/proc/shadow_to_animation(turf/start_turf, turf/end_turf, mob/user)
var/x_difference = end_turf.x - start_turf.x
var/y_difference = end_turf.y - start_turf.y
- var/distance = sqrt(x_difference ** 2 + y_difference ** 2) // pythag baby
+ var/distance = MAGNITUDE(x_difference, y_difference) // pythag baby
var/obj/effect/immortality_talisman/effect = new(start_turf)
effect.dir = user.dir
diff --git a/code/modules/assembly/voice.dm b/code/modules/assembly/voice.dm
index 97523e54f971..9467411d0c50 100644
--- a/code/modules/assembly/voice.dm
+++ b/code/modules/assembly/voice.dm
@@ -14,6 +14,10 @@
. = ..()
become_hearing_sensitive(ROUNDSTART_TRAIT)
+/obj/item/assembly/voice/Destroy()
+ lose_hearing_sensitivity(ROUNDSTART_TRAIT)
+ . = ..()
+
/obj/item/assembly/voice/examine(mob/user)
. = ..()
if(recorded || listening)
diff --git a/code/modules/asset_cache/assets/spritesheet/batched/universal_icon.dm b/code/modules/asset_cache/assets/spritesheet/batched/universal_icon.dm
index 884968709595..1c5e6dc5002b 100644
--- a/code/modules/asset_cache/assets/spritesheet/batched/universal_icon.dm
+++ b/code/modules/asset_cache/assets/spritesheet/batched/universal_icon.dm
@@ -458,7 +458,7 @@
var/curstate = appearance.icon_state || defstate
// Filter out 'runtime' icons (server-generated RSC cache icons)
// Write the icon to the filesystem so it can be used by iconforge
- if(!isfile(curicon) || !length(string_curicon))
+ if(curicon &&(!isfile(curicon) || !length(string_curicon)))
var/file_path_tmp = "tmp/uni_icon-tmp-[rand(1, 999)].dmi" // this filename is temporary.
fcopy(curicon, file_path_tmp)
var/file_hash = rustlib_hash_file(RUSTLIB_HASH_MD5, file_path_tmp)
diff --git a/code/modules/atmospherics/enviromental/LINDA_turf_tile.dm b/code/modules/atmospherics/enviromental/LINDA_turf_tile.dm
index 9a03f6c03e70..77615284230c 100644
--- a/code/modules/atmospherics/enviromental/LINDA_turf_tile.dm
+++ b/code/modules/atmospherics/enviromental/LINDA_turf_tile.dm
@@ -125,7 +125,7 @@
var/datum/gas_mixture/my_air = my_turf.get_readonly_air()
var/air = my_air.total_moles() / MOLES_CELLSTANDARD
- var/wind = sqrt(flow_x ** 2 + flow_y ** 2)
+ var/wind = MAGNITUDE(flow_x, flow_y)
var/force = wind * air * (MOVE_FORCE_DEFAULT / 5)
if(force < force_needed)
@@ -214,10 +214,10 @@
return list(milla_atmos_airtight, milla_superconductivity)
var/milla_atmos_airtight = list(
- !CanAtmosPass(NORTH, FALSE),
- !CanAtmosPass(EAST, FALSE),
- !CanAtmosPass(SOUTH, FALSE),
- !CanAtmosPass(WEST, FALSE))
+ !CanAtmosPass(NORTH),
+ !CanAtmosPass(EAST),
+ !CanAtmosPass(SOUTH),
+ !CanAtmosPass(WEST))
var/milla_superconductivity = list(
OPEN_HEAT_TRANSFER_COEFFICIENT,
diff --git a/code/modules/atmospherics/gasmixtures/gas_mixture.dm b/code/modules/atmospherics/gasmixtures/gas_mixture.dm
index 59d7a6741174..ac9920c41423 100644
--- a/code/modules/atmospherics/gasmixtures/gas_mixture.dm
+++ b/code/modules/atmospherics/gasmixtures/gas_mixture.dm
@@ -206,14 +206,15 @@ What are the archived variables for?
/datum/gas_mixture/proc/return_visuals(z)
var/list/result = list()
+ var/z_plane_offset = GET_Z_PLANE_OFFSET(z)
if(private_toxins > MOLES_PLASMA_VISIBLE)
- result += GLOB.plmaster["[GET_Z_PLANE_OFFSET(z)]"]
+ result += GLOB.plmaster["[z_plane_offset]"]
if(private_sleeping_agent > 1)
- result += GLOB.slmaster["[GET_Z_PLANE_OFFSET(z)]"]
+ result += GLOB.slmaster["[z_plane_offset]"]
if(private_water_vapor > MOLES_WATER_VAPOR_VISIBLE)
- result += GLOB.wvmaster["[GET_Z_PLANE_OFFSET(z)]"]
+ result += GLOB.wvmaster["[z_plane_offset]"]
return result
//Procedures used for very specific events
@@ -236,7 +237,8 @@ What are the archived variables for?
var/energy_released = 0
var/old_heat_capacity = heat_capacity()
var/burned_fuel = 0
- burned_fuel = min((1 - (N2O_DECOMPOSITION_COEFFICIENT_A / ((private_temperature + N2O_DECOMPOSITION_COEFFICIENT_C) ** 2))) * private_sleeping_agent, private_sleeping_agent)
+ var/temperature_no2_decompression = private_temperature + N2O_DECOMPOSITION_COEFFICIENT_C
+ burned_fuel = min((1 - (N2O_DECOMPOSITION_COEFFICIENT_A / POW2(temperature_no2_decompression))) * private_sleeping_agent, private_sleeping_agent)
private_sleeping_agent -= burned_fuel
if(burned_fuel)
energy_released += (N2O_DECOMPOSITION_ENERGY_RELEASED * burned_fuel)
diff --git a/code/modules/atmospherics/machinery/components/binary_devices/pump.dm b/code/modules/atmospherics/machinery/components/binary_devices/pump.dm
index b731d7705f1a..e40cfe28c324 100644
--- a/code/modules/atmospherics/machinery/components/binary_devices/pump.dm
+++ b/code/modules/atmospherics/machinery/components/binary_devices/pump.dm
@@ -282,6 +282,23 @@ Thus, the two variables affect pump operation are set in New():
///The component parent object
var/obj/machinery/atmospherics/binary/pump/connected_pump
+/obj/item/circuit_component/atmos_pump/Destroy()
+ if(connected_pump)
+ unregister_usb_parent(connected_pump)
+
+ pressure_value = null
+ on = null
+ off = null
+ request_data = null
+ input_pressure = null
+ output_pressure = null
+ input_temperature = null
+ output_temperature = null
+ is_active = null
+ turned_on = null
+ turned_off = null
+ . = ..()
+
/obj/item/circuit_component/atmos_pump/populate_ports()
pressure_value = add_input_port("Новое давление", PORT_TYPE_NUMBER, trigger = PROC_REF(set_pump_pressure))
on = add_input_port("Включить", PORT_TYPE_SIGNAL, trigger = PROC_REF(set_pump_on))
diff --git a/code/modules/atmospherics/machinery/components/binary_devices/valve.dm b/code/modules/atmospherics/machinery/components/binary_devices/valve.dm
index 33352bc4839e..b5f38ccbb79d 100644
--- a/code/modules/atmospherics/machinery/components/binary_devices/valve.dm
+++ b/code/modules/atmospherics/machinery/components/binary_devices/valve.dm
@@ -168,6 +168,16 @@
/// Sent when the valve is closed
var/datum/port/output/closed
+/obj/item/circuit_component/digital_valve/Destroy()
+ if(attached_valve)
+ unregister_usb_parent(attached_valve)
+ open = null
+ close = null
+ is_open = null
+ opened = null
+ closed = null
+ . = ..()
+
/obj/item/circuit_component/digital_valve/populate_ports()
open = add_input_port("Открыть", PORT_TYPE_SIGNAL)
close = add_input_port("Закрыть", PORT_TYPE_SIGNAL)
diff --git a/code/modules/atmospherics/machinery/components/binary_devices/volume_pump.dm b/code/modules/atmospherics/machinery/components/binary_devices/volume_pump.dm
index 0e873c6991c0..bbe8d52cc9cf 100644
--- a/code/modules/atmospherics/machinery/components/binary_devices/volume_pump.dm
+++ b/code/modules/atmospherics/machinery/components/binary_devices/volume_pump.dm
@@ -262,6 +262,22 @@ Thus, the two variables affect pump operation are set in New():
///The component parent object
var/obj/machinery/atmospherics/binary/volume_pump/connected_pump
+/obj/item/circuit_component/atmos_volume_pump/Destroy()
+ if(connected_pump)
+ unregister_usb_parent(connected_pump)
+ transfer_rate = null
+ on = null
+ off = null
+ request_data = null
+ input_pressure = null
+ output_pressure = null
+ input_temperature = null
+ output_temperature = null
+ is_active = null
+ turned_on = null
+ turned_off = null
+ . = ..()
+
/obj/item/circuit_component/atmos_volume_pump/populate_ports()
transfer_rate = add_input_port("Новая скорость передачи", PORT_TYPE_NUMBER, trigger = PROC_REF(set_transfer_rate))
on = add_input_port("Включить", PORT_TYPE_SIGNAL, trigger = PROC_REF(set_pump_on))
diff --git a/code/modules/atmospherics/machinery/components/unary_devices/thermomachine.dm b/code/modules/atmospherics/machinery/components/unary_devices/thermomachine.dm
index 460a9fb4c4f0..e13cdf2fdc91 100644
--- a/code/modules/atmospherics/machinery/components/unary_devices/thermomachine.dm
+++ b/code/modules/atmospherics/machinery/components/unary_devices/thermomachine.dm
@@ -67,7 +67,8 @@
var/calculated_bin_rating
for(var/obj/item/stock_parts/matter_bin/bin in component_parts)
calculated_bin_rating += bin.rating
- heat_capacity = 5000 * ((calculated_bin_rating - 1) ** 2)
+ var/bin_rating_fixed = (calculated_bin_rating - 1)
+ heat_capacity = 5000 * POW2(bin_rating_fixed)
min_temperature = T20C
max_temperature = T20C
if(cooling)
diff --git a/code/modules/atmospherics/machinery/other/meter.dm b/code/modules/atmospherics/machinery/other/meter.dm
index 443506a1c2e5..4cb28630c690 100644
--- a/code/modules/atmospherics/machinery/other/meter.dm
+++ b/code/modules/atmospherics/machinery/other/meter.dm
@@ -181,6 +181,14 @@
///The component parent object
var/obj/machinery/atmospherics/meter/connected_meter
+/obj/item/circuit_component/atmos_meter/Destroy()
+ if(connected_meter)
+ unregister_usb_parent(connected_meter)
+ request_data = null
+ pressure = null
+ temperature = null
+ . = ..()
+
/obj/item/circuit_component/atmos_meter/populate_ports()
request_data = add_input_port("Запрос данных счётчика", PORT_TYPE_SIGNAL, trigger = PROC_REF(request_meter_data))
diff --git a/code/modules/awaymissions/corpse.dm b/code/modules/awaymissions/corpse.dm
index e574d76eef7a..c67c29b27d39 100644
--- a/code/modules/awaymissions/corpse.dm
+++ b/code/modules/awaymissions/corpse.dm
@@ -175,7 +175,7 @@ GLOBAL_VAR_INIT(off_mob_spawns, FALSE)
mob.gender = mob_gender
if(faction)
- mob.faction = list(faction)
+ mob.faction = string_list(list(faction))
if(disease)
var/datum/disease/D = new disease
diff --git a/code/modules/clothing/chameleon/_chameleon_actions.dm b/code/modules/clothing/chameleon/_chameleon_actions.dm
index ae18f20568e2..4e3cf4582edb 100644
--- a/code/modules/clothing/chameleon/_chameleon_actions.dm
+++ b/code/modules/clothing/chameleon/_chameleon_actions.dm
@@ -186,6 +186,7 @@
/datum/action/item_action/chameleon/change/Destroy()
STOP_PROCESSING(SSprocessing, src)
+ holder = null
return ..()
/datum/action/item_action/chameleon/change/ui_host()
diff --git a/code/modules/clothing/chameleon/generic_chameleon_clothing.dm b/code/modules/clothing/chameleon/generic_chameleon_clothing.dm
index 93141bc7c727..4253dd19bfcc 100644
--- a/code/modules/clothing/chameleon/generic_chameleon_clothing.dm
+++ b/code/modules/clothing/chameleon/generic_chameleon_clothing.dm
@@ -208,7 +208,7 @@ do { \
/obj/item/clothing/mask/chameleon/Destroy()
QDEL_NULL(voice_changer)
- return ..()
+ . = ..()
/obj/item/clothing/mask/chameleon/broken
diff --git a/code/modules/clothing/clothing.dm b/code/modules/clothing/clothing.dm
index 0628610b03dd..00e575d8ac69 100644
--- a/code/modules/clothing/clothing.dm
+++ b/code/modules/clothing/clothing.dm
@@ -48,6 +48,11 @@
var/obj/item/radio/spy_spider/spy_spider_attached = null
+/obj/item/clothing/Initialize(mapload)
+ if(LAZYLEN(clothing_traits))
+ clothing_traits = string_list(clothing_traits)
+ . = ..()
+
/obj/item/clothing/examine(mob/user)
. = ..()
var/healthpercent = (obj_integrity/max_integrity) * 100
@@ -1381,6 +1386,8 @@
trait_or_traits = list(trait_or_traits)
LAZYOR(clothing_traits, trait_or_traits)
+ if(clothing_traits) // because we might be null
+ clothing_traits = string_list(clothing_traits)
var/mob/wearer = loc
if(istype(wearer) && (wearer.get_slot_by_item(src) & slot_flags))
for(var/new_trait in trait_or_traits)
diff --git a/code/modules/economy/quests/_base_quests.dm b/code/modules/economy/quests/_base_quests.dm
index e7f5e5fa6795..8a9f2e546df5 100644
--- a/code/modules/economy/quests/_base_quests.dm
+++ b/code/modules/economy/quests/_base_quests.dm
@@ -42,6 +42,7 @@
/datum/cargo_quests_storage/Destroy(force)
QDEL_LIST(current_quests)
SScargo_quests.quest_storages -= src
+ SScargo_quests.plasma_quests -= src
customer = null
. = ..()
diff --git a/code/modules/economy/quests/quest_console.dm b/code/modules/economy/quests/quest_console.dm
index e42775064c4c..ff527203c961 100644
--- a/code/modules/economy/quests/quest_console.dm
+++ b/code/modules/economy/quests/quest_console.dm
@@ -368,7 +368,9 @@
integrated_console.parent = src
/obj/item/qm_quest_tablet/Destroy()
- QDEL_NULL(integrated_console)
+ if(integrated_console)
+ integrated_console.parent = null
+ QDEL_NULL(integrated_console)
return ..()
/obj/item/qm_quest_tablet/attack_self(mob/user as mob)
diff --git a/code/modules/events/event_procs.dm b/code/modules/events/event_procs.dm
index 3d8e0f907724..5425c7b90f75 100644
--- a/code/modules/events/event_procs.dm
+++ b/code/modules/events/event_procs.dm
@@ -8,7 +8,7 @@ ADMIN_VERB(trigger_event, R_EVENT, "Trigger Event", "Trigger Event.", ADMIN_CATE
ADMIN_VERB(event_manager_panel, R_EVENT, "Event Manager Panel", "Event Manager Panel.", ADMIN_CATEGORY_EVENTS)
if(SSevents)
- SSevents.Interact(user)
+ SSevents.Interact(user.mob)
BLACKBOX_LOG_ADMIN_VERB("Event Manager")
return
diff --git a/code/modules/events/spacevine.dm b/code/modules/events/spacevine.dm
index acff607e9413..2f92653d22cc 100644
--- a/code/modules/events/spacevine.dm
+++ b/code/modules/events/spacevine.dm
@@ -612,7 +612,8 @@
// 1 mutativeness at 10 potency
// 4 mutativeness at 100 potency
if(potency)
- mutativeness = log(10, potency) ** 2
+ var/potency_log10 = log(10, potency)
+ mutativeness = POW2(potency_log10)
if(production != null)
// 1 production is crazy powerful
diff --git a/code/modules/fish/fishtank.dm b/code/modules/fish/fishtank.dm
index d4fc8e3c2c5a..f55265a5ff46 100644
--- a/code/modules/fish/fishtank.dm
+++ b/code/modules/fish/fishtank.dm
@@ -173,7 +173,7 @@
//////////////////////////////
//Stops atmos from passing wall tanks, since they are effectively full-windows.
-/obj/machinery/fishtank/wall/CanAtmosPass(turf/T, vertical)
+/obj/machinery/fishtank/wall/CanAtmosPass(direction)
return FALSE
/obj/machinery/fishtank/process()
diff --git a/code/modules/flufftext/Hallucination.dm b/code/modules/flufftext/Hallucination.dm
index e1ed186a21f6..bad75b51edd0 100644
--- a/code/modules/flufftext/Hallucination.dm
+++ b/code/modules/flufftext/Hallucination.dm
@@ -137,7 +137,7 @@ GLOBAL_LIST_INIT(major_hallutinations, list("fake"=20,"death"=10,"xeno"=10,"sing
for(var/turf/FT in flood_turfs)
for(var/dir in GLOB.cardinal)
var/turf/T = get_step(FT, dir)
- if((T in flood_turfs) || !FT.CanAtmosPass(T, FALSE))
+ if((T in flood_turfs) || !FT.CanAtmosPass(dir))
continue
flood_images += image(image_icon,T,image_state,MOB_LAYER)
flood_turfs += T
diff --git a/code/modules/food_and_drinks/drinks/drinks/drinkingglass.dm b/code/modules/food_and_drinks/drinks/drinks/drinkingglass.dm
index c5c793903276..67d97d00b60a 100644
--- a/code/modules/food_and_drinks/drinks/drinks/drinkingglass.dm
+++ b/code/modules/food_and_drinks/drinks/drinks/drinkingglass.dm
@@ -25,14 +25,6 @@
PREPOSITIONAL = "стакане",
)
-/obj/item/reagent_containers/food/drinks/set_APTFT()
- set hidden = FALSE
- ..()
-
-/obj/item/reagent_containers/food/drinks/empty()
- set hidden = FALSE
- ..()
-
/obj/item/reagent_containers/food/drinks/drinkingglass/attackby(obj/item/I, mob/user, params)
if(istype(I, /obj/item/reagent_containers/food/snacks/egg)) //breaking eggs
add_fingerprint(user)
diff --git a/code/modules/food_and_drinks/food.dm b/code/modules/food_and_drinks/food.dm
index c53eb64fc844..0b13bc0cc13d 100644
--- a/code/modules/food_and_drinks/food.dm
+++ b/code/modules/food_and_drinks/food.dm
@@ -61,11 +61,11 @@
/obj/item/reagent_containers/food/set_APTFT()
set hidden = TRUE
- ..()
+ return
/obj/item/reagent_containers/food/empty()
set hidden = TRUE
- ..()
+ return
/obj/item/reagent_containers/food/proc/check_for_ants()
var/turf/T = get_turf(src)
diff --git a/code/modules/food_and_drinks/food/condiment.dm b/code/modules/food_and_drinks/food/condiment.dm
index 92ed06e5c759..c02cda139938 100644
--- a/code/modules/food_and_drinks/food/condiment.dm
+++ b/code/modules/food_and_drinks/food/condiment.dm
@@ -33,14 +33,6 @@
/obj/item/reagent_containers/food/condiment/attack_self(mob/user)
return
-/obj/item/reagent_containers/food/condiment/set_APTFT()
- set hidden = FALSE
- ..()
-
-/obj/item/reagent_containers/food/condiment/empty()
- set hidden = FALSE
- ..()
-
/obj/item/reagent_containers/food/condiment/attack(mob/living/carbon/target, mob/living/user, params, def_zone, skip_attack_anim = FALSE)
if(!iscarbon(target))
return ..()
diff --git a/code/modules/food_and_drinks/food/foods/pizza.dm b/code/modules/food_and_drinks/food/foods/pizza.dm
index 30060af0ce87..e33babf3e668 100644
--- a/code/modules/food_and_drinks/food/foods/pizza.dm
+++ b/code/modules/food_and_drinks/food/foods/pizza.dm
@@ -231,6 +231,11 @@
. = ..()
update_appearance(UPDATE_DESC|UPDATE_ICON)
+/obj/item/pizzabox/Destroy()
+ QDEL_NULL(pizza)
+ LAZYCLEARLIST(boxes)
+ . = ..()
+
/obj/item/pizzabox/update_desc(updates = ALL)
. = ..()
if(open && pizza)
diff --git a/code/modules/food_and_drinks/food/snacks.dm b/code/modules/food_and_drinks/food/snacks.dm
index c9dfa20f8c74..deec74b1ff8b 100644
--- a/code/modules/food_and_drinks/food/snacks.dm
+++ b/code/modules/food_and_drinks/food/snacks.dm
@@ -20,6 +20,8 @@
var/opened = TRUE // FALSE if it needed to be opened first
/obj/item/reagent_containers/food/snacks/add_initial_reagents()
+ if(tastes)
+ tastes = string_assoc_list(tastes)
if(tastes && length(tastes))
if(list_reagents)
for(var/rid in list_reagents)
diff --git a/code/modules/hydroponics/gene_modder.dm b/code/modules/hydroponics/gene_modder.dm
index 07b97fdc2377..b0c9996a1753 100644
--- a/code/modules/hydroponics/gene_modder.dm
+++ b/code/modules/hydroponics/gene_modder.dm
@@ -53,12 +53,13 @@
/obj/machinery/plantgenes/RefreshParts() // Comments represent the max you can set per tier, respectively. seeds.dm [219] clamps these for us but we don't want to mislead the viewer.
for(var/obj/item/stock_parts/manipulator/M in component_parts)
- if(M.rating > 4)
+ var/rating = M.rating
+ if(rating > 4)
max_potency = 100
- else if(M.rating > 3)
+ else if(rating > 3)
max_potency = 95
else
- max_potency = initial(max_potency) + (M.rating**3) // 51,58,77,95,100 Clamps at 100
+ max_potency = initial(max_potency) + (POW3(rating)) // 51,58,77,95,100 Clamps at 100
max_yield = min(initial(max_yield) + (M.rating*2), 10) // 4,6,8,10 Clamps at 10
diff --git a/code/modules/hydroponics/plant_genes.dm b/code/modules/hydroponics/plant_genes.dm
index 6876f3a8ab2e..279535398a29 100644
--- a/code/modules/hydroponics/plant_genes.dm
+++ b/code/modules/hydroponics/plant_genes.dm
@@ -227,7 +227,7 @@
// Also splashes everything in target turf with reagents and applies other trait effects (teleporting, etc) to the target by on_squash.
// For code, see grown.dm
name = "Liquid Contents"
- examine_line = span_notice("It has a lot of liquid contents inside.")
+ examine_line = span_notice_alt("It has a lot of liquid contents inside.")
origin_tech = list(RESEARCH_TREE_BIOTECH = 5)
dangerous = TRUE
@@ -236,7 +236,7 @@
// Applies other trait effects (teleporting, etc) to the target by on_slip.
name = "Slippery Skin"
rate = 0.1
- examine_line = span_notice("It has a very slippery skin.")
+ examine_line = span_notice_alt("It has a very slippery skin.")
dangerous = TRUE
/datum/plant_gene/trait/slip/on_new(obj/item/reagent_containers/food/snacks/grown/our_plant)
@@ -315,7 +315,7 @@
// Adds (20+potency)*rate light range and potency*rate light_power to products.
name = "Bioluminescence"
rate = 0.02
- examine_line = span_notice("It emits a soft glow.")
+ examine_line = span_notice_alt("It emits a soft glow.")
trait_id = "glow"
var/glow_color = "#C3E381"
diff --git a/code/modules/instruments/objs/items/piano_synth.dm b/code/modules/instruments/objs/items/piano_synth.dm
index f176854ba479..8ec13b9d805d 100644
--- a/code/modules/instruments/objs/items/piano_synth.dm
+++ b/code/modules/instruments/objs/items/piano_synth.dm
@@ -51,6 +51,26 @@
/// The synthesizer this circut is attached to.
var/obj/item/instrument/piano_synth/synth
+/obj/item/circuit_component/synth/Destroy()
+ if(synth)
+ unregister_usb_parent(synth)
+ song = null
+ play = null
+ stop = null
+ repetitions = null
+ beats_per_min = null
+ volume = null
+ volume_dropoff = null
+ note_shift = null
+ sustain_mode = null
+ sustain_value = null
+ note_decay = null
+ selected_instrument = null
+ is_playing = null
+ started_playing = null
+ stopped_playing = null
+ . = ..()
+
/obj/item/circuit_component/synth/populate_ports()
song = add_input_port("Песня", PORT_TYPE_LIST(PORT_TYPE_STRING), trigger = PROC_REF(import_song))
play = add_input_port("Играть", PORT_TYPE_SIGNAL, trigger = PROC_REF(start_playing))
diff --git a/code/modules/instruments/songs/_song.dm b/code/modules/instruments/songs/_song.dm
index cc0fc5b47418..a0998567b7ed 100644
--- a/code/modules/instruments/songs/_song.dm
+++ b/code/modules/instruments/songs/_song.dm
@@ -149,9 +149,11 @@
stop_playing()
SSinstruments.on_song_del(src)
lines = null
- using_instrument = null
+ set_instrument(null)
allowed_instrument_ids = null
parent = null
+ LAZYCLEARLIST(hearing_mobs)
+ music_player = null
return ..()
/**
diff --git a/code/modules/lighting/lighting_source.dm b/code/modules/lighting/lighting_source.dm
index 1f152c79126a..67c5ee8d1ad0 100644
--- a/code/modules/lighting/lighting_source.dm
+++ b/code/modules/lighting/lighting_source.dm
@@ -52,13 +52,18 @@
remove_lum()
if(source_atom)
LAZYREMOVE(source_atom.light_sources, src)
+ source_atom = null
if(top_atom)
LAZYREMOVE(top_atom.light_sources, src)
+ top_atom = null
+
+ source_turf = null
+ pixel_turf = null
if(needs_update)
SSlighting.sources_queue -= src
-
+ LAZYCLEARLIST(effect_str)
. = ..()
// Yes this doesn't align correctly on anything other than 4 width tabs.
diff --git a/code/modules/lootpanel/search_object.dm b/code/modules/lootpanel/search_object.dm
index dc35275eea34..0bf2a691565a 100644
--- a/code/modules/lootpanel/search_object.dm
+++ b/code/modules/lootpanel/search_object.dm
@@ -14,11 +14,16 @@
/// Typepath of the original object for ui grouping
var/path
+ var/looting_icon_mode
+
+ var/static/alist/icon_cache = alist()
+
/datum/search_object/New(client/owner, atom/item)
. = ..()
src.item = item
name = item.declent_ru(NOMINATIVE)
+ looting_icon_mode = item.looting_icon_mode
if(isobj(item))
path = item.type
@@ -31,9 +36,13 @@
COMSIG_QDELETING,
), PROC_REF(on_item_moved))
+ if(looting_icon_mode)
+ return
+
// Icon generation conditions //////////////
// Condition 1: Icon is complex
- if(ismob(item) || length(item.overlays) > 2)
+ if(length(item.overlays) > 1)
+ looting_icon_mode = LOOT_ICON_FLAT_ICON_TYPE_CACHABLE
return
// Condition 2: Can't get icon path
@@ -45,13 +54,6 @@
return
#endif
- // Condition 4: Using older byond version
- var/build = owner.byond_build
- var/version = owner.byond_version
- if(build < 515 || (build == 515 && version < 1635))
- icon = "n/a"
- return
-
icon = "[item.icon]"
icon_state = item.icon_state
@@ -62,7 +64,18 @@
/// Generates the icon for the search object. This is the expensive part.
/datum/search_object/proc/generate_icon(client/owner)
- icon = costly_icon2html(item, owner, sourceonly = TRUE)
+ switch(looting_icon_mode)
+ if(LOOT_ICON_ICON_TO_HTML)
+ icon = icon2html(item, owner, sourceonly = TRUE)
+
+ if(LOOT_ICON_FLAT_ICON_TYPE_CACHABLE)
+ var/hash = md5("[item.type]")
+ if(!(hash in icon_cache))
+ icon_cache[hash] = flat_icon2html(item, owner, sourceonly = TRUE, name = hash)
+ icon = icon_cache[hash]
+
+ if(LOOT_ICON_FLAT_ICON)
+ icon = flat_icon2html(item, owner, sourceonly = TRUE)
/// Parent item has been altered, search object no longer valid
/datum/search_object/proc/on_item_moved(atom/source)
diff --git a/code/modules/martial_arts/judo.dm b/code/modules/martial_arts/judo.dm
index feb68b34580c..2dae92e7c8cd 100644
--- a/code/modules/martial_arts/judo.dm
+++ b/code/modules/martial_arts/judo.dm
@@ -11,7 +11,7 @@
/datum/martial_combo/judo/goldenblast,
)
weight = 8
- no_baton_reason = span_warning("Из-за занятий дзюдо у вас не получается крепко держать дубинку!")
+ no_baton_reason = span_warning_alt("Из-за занятий дзюдо у вас не получается крепко держать дубинку!")
change_musculs = FALSE
can_horizontally_grab = FALSE
diff --git a/code/modules/martial_arts/martial.dm b/code/modules/martial_arts/martial.dm
index b1818f3c77b7..1b42bc7beb08 100644
--- a/code/modules/martial_arts/martial.dm
+++ b/code/modules/martial_arts/martial.dm
@@ -51,7 +51,7 @@
/// Set to TRUE to prevent users of this style from using stun batons (and stunprods)
var/no_baton = FALSE
/// Message displayed when someone uses a baton when its forbidden by a martial art
- var/no_baton_reason = span_warning("Из-за занятий по боевым искусствам вы не можете крепко схватиться за станбатон!")
+ var/no_baton_reason = span_warning_alt("Из-за занятий по боевым искусствам вы не можете крепко схватиться за станбатон!")
/// Whether or not you can grab someone while horizontal with this Martial Art
var/can_horizontally_grab = TRUE
/// If falce, doesn't change strength and strength limit.
diff --git a/code/modules/mining/equipment/survival_pod.dm b/code/modules/mining/equipment/survival_pod.dm
index f9653559fc96..7462b662ea32 100644
--- a/code/modules/mining/equipment/survival_pod.dm
+++ b/code/modules/mining/equipment/survival_pod.dm
@@ -110,7 +110,7 @@
var/x_component = abs(did_not_stand_back.x - deploy_location.x)
var/y_component = abs(did_not_stand_back.y - deploy_location.y)
if(ISDIAGONALDIR(dir_to_center))
- throw_dist = ceil(sqrt(base_x_throw_distance ** 2 + base_y_throw_distance ** 2) - (sqrt(x_component ** 2 + y_component ** 2)))
+ throw_dist = ceil(MAGNITUDE(base_x_throw_distance, base_y_throw_distance) - MAGNITUDE(x_component, y_component))
did_not_stand_back.forceMove(get_ranged_target_turf(deploy_location, dir_to_center, throw_dist))
else if(dir_to_center & (NORTH|SOUTH))
throw_dist = base_y_throw_distance - y_component + 1
diff --git a/code/modules/mining/lavaland/loot/ashdragon_loot.dm b/code/modules/mining/lavaland/loot/ashdragon_loot.dm
index c653282af63a..33a0465b1306 100644
--- a/code/modules/mining/lavaland/loot/ashdragon_loot.dm
+++ b/code/modules/mining/lavaland/loot/ashdragon_loot.dm
@@ -226,9 +226,9 @@
severity = DISEASE_SEVERITY_BIOHAZARD
stage1 = list("Ваши кости ноют.")
stage2 = list("Ваша кожа кажется чешуйчатой.")
- stage3 = list(span_danger("Вы чувствуете непреодолимое желание напугать пару крестьян."), span_danger("Ваши зубы кажутся острее."))
- stage4 = list(span_danger("Ваша кровь кипит!"))
- stage5 = list(span_danger("Вы, блять, дракон! Однако любые прежние обязательства всё ещё действуют. Было бы крайне невежливо съесть своих всё ещё человеческих друзей без причины."))
+ stage3 = list(span_danger_alt("Вы чувствуете непреодолимое желание напугать пару крестьян."), span_danger_alt("Ваши зубы кажутся острее."))
+ stage4 = list(span_danger_alt("Ваша кровь кипит!"))
+ stage5 = list(span_danger_alt("Вы, блять, дракон! Однако любые прежние обязательства всё ещё действуют. Было бы крайне невежливо съесть своих всё ещё человеческих друзей без причины."))
new_form = /mob/living/simple_animal/hostile/megafauna/dragon/lesser
//Lava Staff
diff --git a/code/modules/mob/dead/observer/observer.dm b/code/modules/mob/dead/observer/observer.dm
index e80e8ca9f93e..d09fcc88e9be 100644
--- a/code/modules/mob/dead/observer/observer.dm
+++ b/code/modules/mob/dead/observer/observer.dm
@@ -25,6 +25,7 @@ GLOBAL_VAR_INIT(observer_default_invisibility, INVISIBILITY_OBSERVER)
invisibility = INVISIBILITY_OBSERVER
pass_flags = PASSEVERYTHING
hud_type = /datum/hud/ghost
+ looting_icon_mode = LOOT_ICON_FLAT_ICON
var/can_reenter_corpse
var/bootime = FALSE
var/started_as_observer //This variable is set to 1 when you enter the game as an observer.
@@ -120,6 +121,7 @@ GLOBAL_VAR_INIT(observer_default_invisibility, INVISIBILITY_OBSERVER)
UnregisterSignal(src, COMSIG_MOB_HUD_CREATED)
if(ghostimage)
GLOB.ghost_images -= ghostimage
+ ghostimage.loc = null
QDEL_NULL(ghostimage)
updateallghostimages()
if(orbit_menu)
@@ -666,7 +668,7 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
if(target && target != usr)
spawn(0)
var/turf/pos = get_turf(A)
- var/turf/T=get_turf(target)
+ var/turf/T = get_turf(target)
if(T != pos)
if(!T)
return
diff --git a/code/modules/mob/dead/observer/spells.dm b/code/modules/mob/dead/observer/spells.dm
index 34fd81684638..cc6923f5bcaa 100644
--- a/code/modules/mob/dead/observer/spells.dm
+++ b/code/modules/mob/dead/observer/spells.dm
@@ -16,8 +16,8 @@ GLOBAL_LIST_INIT(boo_phrases, list(
/obj/effect/proc_holder/spell/boo
name = "Буу!"
desc = "К черту живых."
- selection_deactivated_message = span_shadowling("Ваше присутствие останется незамеченным. Пока что.")
- selection_activated_message = span_shadowling("Вы готовы протянуть руку сквозь завесу. ЛКМ по цели для воздействия!")
+ selection_deactivated_message = span_shadowling_alt("Ваше присутствие останется незамеченным. Пока что.")
+ selection_activated_message = span_shadowling_alt("Вы готовы протянуть руку сквозь завесу. ЛКМ по цели для воздействия!")
ghost = TRUE
diff --git a/code/modules/mob/living/carbon/brain/MMI.dm b/code/modules/mob/living/carbon/brain/MMI.dm
index ed9867994805..20a516cf7947 100644
--- a/code/modules/mob/living/carbon/brain/MMI.dm
+++ b/code/modules/mob/living/carbon/brain/MMI.dm
@@ -29,6 +29,15 @@
var/list/skin_permissions = list()
+/obj/item/mmi/Destroy()
+ QDEL_NULL(brainmob)
+ robot = null
+ mecha = null
+ QDEL_NULL(radio)
+ QDEL_NULL(radio_action)
+ QDEL_NULL(held_brain)
+ . = ..()
+
/obj/item/mmi/update_icon_state()
if(held_brain)
icon = held_brain.mmi_icon
diff --git a/code/modules/mob/living/carbon/brain/brain.dm b/code/modules/mob/living/carbon/brain/brain.dm
index 4eb3caeb2ff9..219da462f7a8 100644
--- a/code/modules/mob/living/carbon/brain/brain.dm
+++ b/code/modules/mob/living/carbon/brain/brain.dm
@@ -6,8 +6,8 @@
icon = 'icons/obj/surgery.dmi'
icon_state = "brain1"
-/mob/living/carbon/brain/New()
- ..()
+/mob/living/carbon/brain/Initialize(mapload)
+ . = ..()
add_language(LANGUAGE_GALACTIC_COMMON)
/mob/living/carbon/brain/Destroy()
@@ -15,6 +15,7 @@
if(stat != DEAD) //If not dead.
death(gibbed = TRUE) //Brains can die again. AND THEY SHOULD AHA HA HA HA HA HA
ghostize() //Ghostize checks for key so nothing else is necessary.
+ container = null
return ..()
/mob/living/carbon/brain/ex_act() //you cant blow up brainmobs because it makes transfer_to() freak out when borgs blow up.
diff --git a/code/modules/mob/living/carbon/brain/brain_item.dm b/code/modules/mob/living/carbon/brain/brain_item.dm
index 92a6a73dcf9a..a99236f5cef4 100644
--- a/code/modules/mob/living/carbon/brain/brain_item.dm
+++ b/code/modules/mob/living/carbon/brain/brain_item.dm
@@ -8,11 +8,11 @@
throw_range = 5
origin_tech = "biotech=5"
attack_verb = list("атаковал", "шлёпнул", "огрел")
- var/mob/living/carbon/brain/brainmob = null
parent_organ_zone = BODY_ZONE_HEAD
slot = INTERNAL_ORGAN_BRAIN
vital = TRUE
hidden_pain = TRUE //the brain has no pain receptors, and brain damage is meant to be a stealthy damage type.
+ var/mob/living/carbon/brain/brainmob = null
var/mmi_icon = 'icons/obj/assemblies.dmi'
var/mmi_icon_state = "mmi_full"
/// If it's a fake brain without a mob assigned that should still be treated like a real brain.
@@ -20,7 +20,7 @@
/// TRUE giving to a user sci hud and active research scanner
var/smart_mind = FALSE
/// The original body for this brain, if this valriable is null - brain can apply any body without desease.
- var/original_body = null
+ var/datum/weakref/original_body = null
/obj/item/organ/internal/brain/get_ru_names()
return list(
@@ -34,6 +34,7 @@
/obj/item/organ/internal/brain/Destroy()
QDEL_NULL(brainmob)
+ original_body = null
return ..()
/obj/item/organ/internal/brain/proc/transfer_identity(mob/living/carbon/H)
diff --git a/code/modules/mob/living/carbon/brain/robotic_brain.dm b/code/modules/mob/living/carbon/brain/robotic_brain.dm
index acab8b614f88..715ab8c917cc 100644
--- a/code/modules/mob/living/carbon/brain/robotic_brain.dm
+++ b/code/modules/mob/living/carbon/brain/robotic_brain.dm
@@ -24,6 +24,7 @@
dead_icon = "boris_blank"
+
/obj/item/mmi/robotic_brain/syndicate
name = "suspicious robotic brain"
syndicate = 1
@@ -45,7 +46,8 @@
/obj/item/mmi/robotic_brain/Destroy()
imprinted_master = null
- return ..()
+ LAZYCLEARLIST(ghost_volunteers)
+ . = ..()
/obj/item/mmi/robotic_brain/update_icon_state()
if(brainmob?.key)
diff --git a/code/modules/mob/living/carbon/carbon_defines.dm b/code/modules/mob/living/carbon/carbon_defines.dm
index 676884bda0f4..90e3422165ac 100644
--- a/code/modules/mob/living/carbon/carbon_defines.dm
+++ b/code/modules/mob/living/carbon/carbon_defines.dm
@@ -7,6 +7,7 @@
rotate_on_lying = TRUE
pull_hand = null
throw_range = 3
+ looting_icon_mode = LOOT_ICON_FLAT_ICON
var/list/stomach_contents
var/list/processing_patches
var/list/internal_organs = list()
diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm
index d50fa8aedf5a..aca248388336 100644
--- a/code/modules/mob/living/carbon/human/human.dm
+++ b/code/modules/mob/living/carbon/human/human.dm
@@ -1840,14 +1840,15 @@ Eyes need to have significantly high darksight to shine unless the mob has the X
var/obj/item/organ/external/chest/self_chest = get_organ(BODY_ZONE_CHEST)
if(!self_chest || !istype(self_chest))
return
- if(brains.original_body == self_chest)
+ var/body = brains.original_body?.resolve()
+ if(body == self_chest)
return
- if(brains.original_body)
+ if(body)
//this is not original body for brain, apply brain transplantation disease
var/datum/disease/brain_transplant_syndrome/disease = new
disease.Contract(src)
//now this body are original for brain
- brains.original_body = self_chest
+ brains.original_body = WEAKREF(self_chest)
/mob/living/carbon/human/is_literate()
return getBrainLoss() < 100
diff --git a/code/modules/mob/living/carbon/superheroes.dm b/code/modules/mob/living/carbon/superheroes.dm
index 15902376ad65..ae9d8d4d8453 100644
--- a/code/modules/mob/living/carbon/superheroes.dm
+++ b/code/modules/mob/living/carbon/superheroes.dm
@@ -140,8 +140,8 @@
action_icon_state = "spell_greytide"
var/recruiting = 0
- selection_activated_message = span_notice("You start preparing a mindblowing monologue. ЛКМ по цели, чтобы применить!")
- selection_deactivated_message = span_notice("You decide to save your brilliance for another day.")
+ selection_activated_message = span_notice_alt("You start preparing a mindblowing monologue. ЛКМ по цели, чтобы применить!")
+ selection_deactivated_message = span_notice_alt("You decide to save your brilliance for another day.")
need_active_overlay = TRUE
/obj/effect/proc_holder/spell/recruit/create_new_targeting()
diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm
index 300d9b028633..b61139774817 100644
--- a/code/modules/mob/living/living.dm
+++ b/code/modules/mob/living/living.dm
@@ -53,6 +53,7 @@
else
S.be_replaced()
GLOB.mob_living_list -= src
+ GLOB.respawnable_list -= src
return ..()
// Used to determine the forces dependend on the mob size
diff --git a/code/modules/mob/living/silicon/robot/robot.dm b/code/modules/mob/living/silicon/robot/robot.dm
index 49abc068fa89..89ac059f08ef 100644
--- a/code/modules/mob/living/silicon/robot/robot.dm
+++ b/code/modules/mob/living/silicon/robot/robot.dm
@@ -202,6 +202,56 @@ GLOBAL_LIST_INIT(robot_verbs_default, list(
add_strippable_element()
+//If there's an MMI in the robot, have it ejected when the mob goes away. --NEO
+//Improved /N
+/mob/living/silicon/robot/Destroy()
+ SStgui.close_uis(wires)
+
+ if(mmi && mind)//Safety for when a cyborg gets dust()ed. Or there is no MMI inside.
+ var/turf/T = get_turf(loc)//To hopefully prevent run time errors.
+
+ if(T)
+ mmi.forceMove(T)
+
+ if(mmi.brainmob)
+ mind.transfer_to(mmi.brainmob)
+ mmi.update_icon()
+ else
+ to_chat(src, span_boldannounceooc("Oops! Something went very wrong, your MMI was unable to receive your mind. You have been ghosted. Please make a bug report so we can fix this bug."))
+ ghostize()
+ error("A borg has been destroyed, but its MMI lacked a brainmob, so the mind could not be transferred. Player: [ckey].")
+
+ mmi = null
+
+ if(connected_ai)
+ connected_ai.connected_robots -= src
+ connected_ai = null
+
+ selected_skin = null
+
+ QDEL_NULL(wires)
+ QDEL_NULL(module)
+ QDEL_NULL(camera)
+ QDEL_NULL(cell)
+ QDEL_NULL(robot_suit)
+ QDEL_NULL(spark_system)
+ QDEL_NULL(self_diagnosis)
+ QDEL_NULL(ion_trail)
+ QDEL_NULL(scanner)
+ QDEL_NULL(rbPDA)
+ QDEL_NULL(radio)
+ QDEL_NULL(inv1)
+ QDEL_NULL(inv2)
+ QDEL_NULL(inv3)
+ QDEL_NULL(lamp_button)
+ QDEL_NULL(thruster_button)
+ QDEL_NULL(robot_modules_background)
+ QDEL_LIST(components)
+ QDEL_LIST(upgrades)
+ QDEL_LIST(module_actions)
+
+ return ..()
+
/mob/living/silicon/robot/proc/add_strippable_element()
AddElement(/datum/element/strippable, create_strippable_list(list(/datum/strippable_item/borg_head)))
@@ -300,41 +350,6 @@ GLOBAL_LIST_INIT(robot_verbs_default, list(
return FALSE
-//If there's an MMI in the robot, have it ejected when the mob goes away. --NEO
-//Improved /N
-/mob/living/silicon/robot/Destroy()
- SStgui.close_uis(wires)
-
- if(mmi && mind)//Safety for when a cyborg gets dust()ed. Or there is no MMI inside.
- var/turf/T = get_turf(loc)//To hopefully prevent run time errors.
-
- if(T)
- mmi.loc = T
-
- if(mmi.brainmob)
- mind.transfer_to(mmi.brainmob)
- mmi.update_icon()
- else
- to_chat(src, span_boldannounceooc("Oops! Something went very wrong, your MMI was unable to receive your mind. You have been ghosted. Please make a bug report so we can fix this bug."))
- ghostize()
- error("A borg has been destroyed, but its MMI lacked a brainmob, so the mind could not be transferred. Player: [ckey].")
-
- mmi = null
-
- if(connected_ai)
- connected_ai.connected_robots -= src
-
- QDEL_NULL(wires)
- QDEL_NULL(module)
- QDEL_NULL(camera)
- QDEL_NULL(cell)
- QDEL_NULL(robot_suit)
- QDEL_NULL(spark_system)
- QDEL_NULL(self_diagnosis)
- QDEL_NULL(ion_trail)
-
- return ..()
-
/mob/living/silicon/robot/proc/pick_module(forced_module = null)
if(module)
return
diff --git a/code/modules/mob/living/silicon/silicon.dm b/code/modules/mob/living/silicon/silicon.dm
index 13cc4036634c..c1c7225aaa10 100644
--- a/code/modules/mob/living/silicon/silicon.dm
+++ b/code/modules/mob/living/silicon/silicon.dm
@@ -4,6 +4,7 @@
has_unlimited_silicon_privilege = TRUE
weather_immunities = list(TRAIT_WEATHER_IMMUNE)
abstract_type = /mob/living/silicon
+ looting_icon_mode = LOOT_ICON_FLAT_ICON
var/syndicate = 0
var/obj/item/gps/cyborg/gps
var/const/MAIN_CHANNEL = "Main Frequency"
diff --git a/code/modules/mob/living/simple_animal/bot/bot.dm b/code/modules/mob/living/simple_animal/bot/bot.dm
index a45247e35ec6..daf2dc8bbd86 100644
--- a/code/modules/mob/living/simple_animal/bot/bot.dm
+++ b/code/modules/mob/living/simple_animal/bot/bot.dm
@@ -151,6 +151,32 @@
minbodytemp = 0, \
)
+/mob/living/simple_animal/bot/Destroy()
+ if(paicard)
+ ejectpai()
+ set_path(null)
+
+ if(path_hud)
+ QDEL_NULL(path_hud)
+ path_hud = null
+
+ GLOB.bots_list -= src
+
+ QDEL_NULL(path)
+ QDEL_NULL(Radio)
+ QDEL_NULL(access_card)
+
+ if(reset_access_timer_id)
+ deltimer(reset_access_timer_id)
+ reset_access_timer_id = null
+
+ if(SSradio && bot_filter)
+ SSradio.remove_object(bot_core, control_freq)
+
+ QDEL_NULL(bot_core)
+
+ . = ..()
+
/obj/item/radio/headset/bot
requires_tcomms = FALSE
@@ -254,32 +280,6 @@
/mob/living/simple_animal/bot/med_hud_set_status()
return diag_hud_set_botstat() //we use a different hud
-/mob/living/simple_animal/bot/Destroy()
- if(paicard)
- ejectpai()
- set_path(null)
-
- if(path_hud)
- QDEL_NULL(path_hud)
- path_hud = null
-
- GLOB.bots_list -= src
-
- QDEL_NULL(path)
- QDEL_NULL(Radio)
- QDEL_NULL(access_card)
-
- if(reset_access_timer_id)
- deltimer(reset_access_timer_id)
- reset_access_timer_id = null
-
- if(SSradio && bot_filter)
- SSradio.remove_object(bot_core, control_freq)
-
- QDEL_NULL(bot_core)
-
- return ..()
-
/mob/living/simple_animal/bot/death(gibbed)
// Only execute the below if we successfully died
. = ..()
@@ -1079,12 +1079,16 @@ Pass the desired type path itself, declaring a temporary var beforehand is not r
use_power = NO_POWER_USE
var/mob/living/simple_animal/bot/owner = null
-/obj/machinery/bot_core/New(loc)
- ..()
+/obj/machinery/bot_core/Initialize(mapload)
+ . = ..()
owner = loc
if(!istype(owner))
qdel(src)
+/obj/machinery/bot_core/Destroy()
+ owner = null
+ . = ..()
+
/**
* Access check proc for bot topics! Remember to place in a bot's individual Topic if desired.
*/
diff --git a/code/modules/mob/living/simple_animal/bot/mulebot.dm b/code/modules/mob/living/simple_animal/bot/mulebot.dm
index fa0d9f0a75f8..61ea82a627fd 100644
--- a/code/modules/mob/living/simple_animal/bot/mulebot.dm
+++ b/code/modules/mob/living/simple_animal/bot/mulebot.dm
@@ -89,6 +89,8 @@
unload(0)
QDEL_NULL(wires)
QDEL_NULL(cell)
+ passenger = null
+ target = null
return ..()
/mob/living/simple_animal/bot/mulebot/get_cell()
diff --git a/code/modules/mob/living/simple_animal/hostile/megafauna/blood_drunk_miner.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/blood_drunk_miner.dm
index ac3a66ee9978..b7c5bc99bea7 100644
--- a/code/modules/mob/living/simple_animal/hostile/megafauna/blood_drunk_miner.dm
+++ b/code/modules/mob/living/simple_animal/hostile/megafauna/blood_drunk_miner.dm
@@ -176,21 +176,21 @@ Difficulty: Medium
name = "Рывок к цели"
button_icon = 'icons/mob/actions/actions.dmi'
button_icon_state = "sniper_zoom"
- chosen_message = span_colossus("Вы рывком движетесь к цели.")
+ chosen_message = span_colossus_alt("Вы рывком движетесь к цели.")
chosen_attack_num = 1
/datum/action/innate/megafauna_attack/kinetic_accelerator
name = "Стрелять из кинетического ускорителя"
button_icon = 'icons/obj/weapons/energy.dmi'
button_icon_state = "kineticgun"
- chosen_message = span_colossus("Вы стреляете из кинетического ускорителя.")
+ chosen_message = span_colossus_alt("Вы стреляете из кинетического ускорителя.")
chosen_attack_num = 2
/datum/action/innate/megafauna_attack/transform_weapon
name = "Трансформировать оружие"
button_icon = 'icons/obj/lavaland/artefacts.dmi'
button_icon_state = "cleaving_saw"
- chosen_message = span_colossus("Вы трансформируете своё оружие.")
+ chosen_message = span_colossus_alt("Вы трансформируете своё оружие.")
chosen_attack_num = 3
/mob/living/simple_animal/hostile/megafauna/blood_drunk_miner/OpenFire()
diff --git a/code/modules/mob/living/simple_animal/hostile/megafauna/bubblegum.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/bubblegum.dm
index 187848b76420..7c16aaacfb3b 100644
--- a/code/modules/mob/living/simple_animal/hostile/megafauna/bubblegum.dm
+++ b/code/modules/mob/living/simple_animal/hostile/megafauna/bubblegum.dm
@@ -102,28 +102,28 @@ Difficulty: Hard
name = "Тройной заряд"
button_icon = 'icons/mob/actions/actions.dmi'
button_icon_state = "sniper_zoom"
- chosen_message = span_colossus("Вы трижды атакуете цель, на которую нажмёте.")
+ chosen_message = span_colossus_alt("Вы трижды атакуете цель, на которую нажмёте.")
chosen_attack_num = 1
/datum/action/innate/megafauna_attack/hallucination_charge
name = "Заряд галлюцинаций"
button_icon = 'icons/effects/bubblegum.dmi'
button_icon_state = "smack ya one"
- chosen_message = span_colossus("Вы атакуете цель, на которую нажмёте, с галлюцинациями.")
+ chosen_message = span_colossus_alt("Вы атакуете цель, на которую нажмёте, с галлюцинациями.")
chosen_attack_num = 2
/datum/action/innate/megafauna_attack/hallucination_surround
name = "Окружение цели"
button_icon = 'icons/turf/walls/wall.dmi'
button_icon_state = "wall"
- chosen_message = span_colossus("Вы окружаете цель, на которую нажмёте, с галлюцинациями.")
+ chosen_message = span_colossus_alt("Вы окружаете цель, на которую нажмёте, с галлюцинациями.")
chosen_attack_num = 3
/datum/action/innate/megafauna_attack/blood_warp
name = "Кровавый варп"
button_icon = 'icons/effects/blood.dmi'
button_icon_state = "floor1"
- chosen_message = span_colossus("Вы телепортируетесь к крови вокруг выбранной позиции.")
+ chosen_message = span_colossus_alt("Вы телепортируетесь к крови вокруг выбранной позиции.")
chosen_attack_num = 4
/mob/living/simple_animal/hostile/megafauna/bubblegum/enrage()
diff --git a/code/modules/mob/living/simple_animal/hostile/megafauna/colossus.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/colossus.dm
index 6cc6f1903ca0..ed60cdd27ac1 100644
--- a/code/modules/mob/living/simple_animal/hostile/megafauna/colossus.dm
+++ b/code/modules/mob/living/simple_animal/hostile/megafauna/colossus.dm
@@ -90,28 +90,28 @@ Difficulty: Very Hard
name = "Спиральные выстрелы"
button_icon = 'icons/mob/actions/actions.dmi'
button_icon_state = "sniper_zoom"
- chosen_message = span_colossus("Вы стреляете по спирали.")
+ chosen_message = span_colossus_alt("Вы стреляете по спирали.")
chosen_attack_num = 1
/datum/action/innate/megafauna_attack/aoe_attack
name = "Во всех направлениях"
button_icon = 'icons/effects/effects.dmi'
button_icon_state = "at_shield2"
- chosen_message = span_colossus("Вы стреляете во всех направлениях.")
+ chosen_message = span_colossus_alt("Вы стреляете во всех направлениях.")
chosen_attack_num = 2
/datum/action/innate/megafauna_attack/shotgun
name = "Выстрел дробью"
button_icon = 'icons/obj/weapons/projectile.dmi'
button_icon_state = "shotgun"
- chosen_message = span_colossus("Вы выстрелите дробью туда, куда нажмёте.")
+ chosen_message = span_colossus_alt("Вы выстрелите дробью туда, куда нажмёте.")
chosen_attack_num = 3
/datum/action/innate/megafauna_attack/alternating_cardinals
name = "Чередующиеся выстрелы"
button_icon = 'icons/obj/weapons/projectile.dmi'
button_icon_state = "pistol"
- chosen_message = span_colossus("Вы стреляете в чередующихся кардинальных направлениях.")
+ chosen_message = span_colossus_alt("Вы стреляете в чередующихся кардинальных направлениях.")
chosen_attack_num = 4
/mob/living/simple_animal/hostile/megafauna/colossus/say(message, bubble_type, list/spans = list(), sanitize = TRUE, datum/language/language = null, ignore_spam = FALSE, forced = null, filterproof = null)
diff --git a/code/modules/mob/living/simple_animal/hostile/megafauna/drake.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/drake.dm
index 08504766c938..1c358d8e63e7 100644
--- a/code/modules/mob/living/simple_animal/hostile/megafauna/drake.dm
+++ b/code/modules/mob/living/simple_animal/hostile/megafauna/drake.dm
@@ -90,28 +90,28 @@ Difficulty: Medium
name = "Огненный конус"
button_icon = 'icons/obj/wizard.dmi'
button_icon_state = "fireball"
- chosen_message = span_colossus("Вы стреляете огнём в цель.")
+ chosen_message = span_colossus_alt("Вы стреляете огнём в цель.")
chosen_attack_num = 1
/datum/action/innate/megafauna_attack/fire_cone_meteors
name = "Огненный конус с метеорами"
button_icon = 'icons/mob/actions/actions.dmi'
button_icon_state = "sniper_zoom"
- chosen_message = span_colossus("Вы стреляете огнём в цель и обрушиваете огонь вокруг себя.")
+ chosen_message = span_colossus_alt("Вы стреляете огнём в цель и обрушиваете огонь вокруг себя.")
chosen_attack_num = 2
/datum/action/innate/megafauna_attack/mass_fire
name = "Массовая огненная атака"
button_icon = 'icons/effects/fire.dmi'
button_icon_state = "1"
- chosen_message = span_colossus("Вы обрушиваете массовый огонь на цель.")
+ chosen_message = span_colossus_alt("Вы обрушиваете массовый огонь на цель.")
chosen_attack_num = 3
/datum/action/innate/megafauna_attack/lava_swoop
name = "Пикирующий удар"
button_icon = 'icons/effects/effects.dmi'
button_icon_state = "lavastaff_warn"
- chosen_message = span_colossus("Вы пикируете и обрушиваете лаву на цель.")
+ chosen_message = span_colossus_alt("Вы пикируете и обрушиваете лаву на цель.")
chosen_attack_num = 4
/mob/living/simple_animal/hostile/megafauna/dragon/OpenFire()
diff --git a/code/modules/mob/living/simple_animal/hostile/megafauna/hierophant.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/hierophant.dm
index 287c6ccb25ea..67f63d49aa3c 100644
--- a/code/modules/mob/living/simple_animal/hostile/megafauna/hierophant.dm
+++ b/code/modules/mob/living/simple_animal/hostile/megafauna/hierophant.dm
@@ -109,28 +109,28 @@ Difficulty: Hard
name = "Прыжок к цели"
button_icon = 'icons/mob/actions/actions.dmi'
button_icon_state = "sniper_zoom"
- chosen_message = span_colossus("Вы мгновенно переместитесь к цели.")
+ chosen_message = span_colossus_alt("Вы мгновенно переместитесь к цели.")
chosen_attack_num = 1
/datum/action/innate/megafauna_attack/chaser_swarm
name = "Рой преследователей"
button_icon = 'icons/effects/effects.dmi'
button_icon_state = "hierophant_squares_indefinite"
- chosen_message = span_colossus("Вы выпустите рой энергетических преследователей в цель.")
+ chosen_message = span_colossus_alt("Вы выпустите рой энергетических преследователей в цель.")
chosen_attack_num = 2
/datum/action/innate/megafauna_attack/cross_blasts
name = "Перекрёстные взрывы"
button_icon = 'icons/effects/effects.dmi'
button_icon_state = "hierophant_blast_indefinite"
- chosen_message = span_colossus("Вы атакуете цель перекрёстными взрывами.")
+ chosen_message = span_colossus_alt("Вы атакуете цель перекрёстными взрывами.")
chosen_attack_num = 3
/datum/action/innate/megafauna_attack/blink_spam
name = "Преследующий прыжок"
button_icon = 'icons/obj/lavaland/artefacts.dmi'
button_icon_state = "hierophant_club_ready_beacon"
- chosen_message = span_colossus("Вы многократно телепортируетесь к цели.")
+ chosen_message = span_colossus_alt("Вы многократно телепортируетесь к цели.")
chosen_attack_num = 4
/mob/living/simple_animal/hostile/megafauna/hierophant/enrage()
@@ -584,6 +584,10 @@ Difficulty: Hard
if(new_caster)
caster = new_caster
+/obj/effect/temp_visual/hierophant/Destroy()
+ caster = null
+ . = ..()
+
/obj/effect/temp_visual/hierophant/squares
icon_state = "hierophant_squares"
duration = 3
@@ -665,6 +669,11 @@ Difficulty: Hard
speed = new_speed
addtimer(CALLBACK(src, PROC_REF(seek_target)), 1)
+/obj/effect/temp_visual/hierophant/chaser/Destroy()
+ target = null
+ targetturf = null
+ . = ..()
+
/obj/effect/temp_visual/hierophant/chaser/proc/get_target_dir()
. = get_cardinal_dir(src, targetturf)
if((. != previous_moving_dir && . == more_previouser_moving_dir) || . == 0) //we're alternating, recalculate
@@ -763,6 +772,10 @@ Difficulty: Hard
)
AddElement(/datum/element/connect_loc, loc_connections)
+/obj/effect/temp_visual/hierophant/blast/Destroy()
+ LAZYCLEARLIST(hit_things)
+ . = ..()
+
/obj/effect/temp_visual/hierophant/blast/proc/blast()
var/turf/T = get_turf(src)
if(!T)
diff --git a/code/modules/mob/living/simple_animal/hostile/megafauna/megafauna.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/megafauna.dm
index 2e42563f8fea..02fe42a95092 100644
--- a/code/modules/mob/living/simple_animal/hostile/megafauna/megafauna.dm
+++ b/code/modules/mob/living/simple_animal/hostile/megafauna/megafauna.dm
@@ -61,6 +61,8 @@
. = ..()
if(internal_type && true_spawn)
internal = new internal_type(src)
+ if(islist(crusher_loot))
+ crusher_loot = string_list(crusher_loot)
for(var/action_type in attack_action_types)
var/datum/action/innate/megafauna_attack/attack_action = new action_type()
attack_action.Grant(src)
diff --git a/code/modules/mob/living/simple_animal/hostile/mining/elites/elite.dm b/code/modules/mob/living/simple_animal/hostile/mining/elites/elite.dm
index a91ae8e79437..0a9f2b52044b 100644
--- a/code/modules/mob/living/simple_animal/hostile/mining/elites/elite.dm
+++ b/code/modules/mob/living/simple_animal/hostile/mining/elites/elite.dm
@@ -332,6 +332,7 @@ While using this makes the system rely on OnFire, it still gives options for tim
/obj/structure/elite_tumor/Initialize(mapload)
. = ..()
START_PROCESSING(SSobj, src)
+ potentialspawns = string_list(potentialspawns)
/obj/structure/elite_tumor/Destroy()
STOP_PROCESSING(SSobj, src)
diff --git a/code/modules/mob/living/simple_animal/hostile/mining/elites/goliath_broodmother.dm b/code/modules/mob/living/simple_animal/hostile/mining/elites/goliath_broodmother.dm
index 23381623f3c4..e4e4d4efb30f 100644
--- a/code/modules/mob/living/simple_animal/hostile/mining/elites/goliath_broodmother.dm
+++ b/code/modules/mob/living/simple_animal/hostile/mining/elites/goliath_broodmother.dm
@@ -62,25 +62,25 @@
/datum/action/innate/elite_attack/tentacle_patch
name = "Поле из щупалец"
button_icon_state = "tentacle_patch"
- chosen_message = span_boldwarning("Теперь вы атакуете щупальцами!")
+ chosen_message = span_boldwarning_alt("Теперь вы атакуете щупальцами!")
chosen_attack_num = TENTACLE_PATCH
/datum/action/innate/elite_attack/spawn_children
name = "Выпуск выводка"
button_icon_state = "spawn_children"
- chosen_message = span_boldwarning("Вы создаёте двух детёнышей для помощи в бою. Максимум – .")
+ chosen_message = span_boldwarning_alt("Вы создаёте двух детёнышей для помощи в бою. Максимум – .")
chosen_attack_num = SPAWN_CHILDREN
/datum/action/innate/elite_attack/rage
name = "Бешенство"
button_icon_state = "rage"
- chosen_message = span_boldwarning("Вы временно увеличиваете скорость передвижения.")
+ chosen_message = span_boldwarning_alt("Вы временно увеличиваете скорость передвижения.")
chosen_attack_num = RAGE
/datum/action/innate/elite_attack/call_children
name = "Зов"
button_icon_state = "call_children"
- chosen_message = span_boldwarning("Вы призываете своих детёнышей к себе.")
+ chosen_message = span_boldwarning_alt("Вы призываете своих детёнышей к себе.")
chosen_attack_num = CALL_CHILDREN
/mob/living/simple_animal/hostile/asteroid/elite/broodmother/Destroy()
diff --git a/code/modules/mob/living/simple_animal/hostile/mining/elites/herald.dm b/code/modules/mob/living/simple_animal/hostile/mining/elites/herald.dm
index 7d1fe2a99b9e..8c37e8787b53 100644
--- a/code/modules/mob/living/simple_animal/hostile/mining/elites/herald.dm
+++ b/code/modules/mob/living/simple_animal/hostile/mining/elites/herald.dm
@@ -84,25 +84,25 @@
/datum/action/innate/elite_attack/herald_trishot
name = "Тройной залп"
button_icon_state = "herald_trishot"
- chosen_message = span_boldwarning("Теперь вы выпускаете три снаряда в выбранном направлении.")
+ chosen_message = span_boldwarning_alt("Теперь вы выпускаете три снаряда в выбранном направлении.")
chosen_attack_num = HERALD_TRISHOT
/datum/action/innate/elite_attack/herald_directionalshot
name = "Круговой залп"
button_icon_state = "herald_directionalshot"
- chosen_message = span_boldwarning("Вы выпускаете снаряды во всех направлениях.")
+ chosen_message = span_boldwarning_alt("Вы выпускаете снаряды во всех направлениях.")
chosen_attack_num = HERALD_DIRECTIONALSHOT
/datum/action/innate/elite_attack/herald_teleshot
name = "Телепортирующий выстрел"
button_icon_state = "herald_teleshot"
- chosen_message = span_boldwarning("Следующий снаряд телепортирует вас к месту попадания.")
+ chosen_message = span_boldwarning_alt("Следующий снаряд телепортирует вас к месту попадания.")
chosen_attack_num = HERALD_TELESHOT
/datum/action/innate/elite_attack/herald_mirror
name = "Призыв зеркала"
button_icon_state = "herald_mirror"
- chosen_message = span_boldwarning("Вы создадите зеркало, дублирующее ваши атаки.")
+ chosen_message = span_boldwarning_alt("Вы создадите зеркало, дублирующее ваши атаки.")
chosen_attack_num = HERALD_MIRROR
/mob/living/simple_animal/hostile/asteroid/elite/herald/OpenFire()
diff --git a/code/modules/mob/living/simple_animal/hostile/mining/elites/legionnaire.dm b/code/modules/mob/living/simple_animal/hostile/mining/elites/legionnaire.dm
index dca8f0a676fe..54c45a4de5e0 100644
--- a/code/modules/mob/living/simple_animal/hostile/mining/elites/legionnaire.dm
+++ b/code/modules/mob/living/simple_animal/hostile/mining/elites/legionnaire.dm
@@ -72,26 +72,26 @@
/datum/action/innate/elite_attack/legionnaire_charge
name = "Рывок"
button_icon_state = "legionnaire_charge"
- chosen_message = span_boldwarning("Вы попытаетесь схватить противника и отбросить его.")
+ chosen_message = span_boldwarning_alt("Вы попытаетесь схватить противника и отбросить его.")
chosen_attack_num = LEGIONNAIRE_CHARGE
/datum/action/innate/elite_attack/head_detach
name = "Освободить череп"
button_icon_state = "head_detach"
- chosen_message = span_boldwarning("Вы теперь можете отделить свою голову или уничтожить её, если она уже отделена.")
+ chosen_message = span_boldwarning_alt("Вы теперь можете отделить свою голову или уничтожить её, если она уже отделена.")
chosen_attack_num = HEAD_DETACH
/datum/action/innate/elite_attack/bonfire_teleport
name = "Костяное кострище"
button_icon_state = "bonfire_teleport"
- chosen_message = span_boldwarning("Вы оставите костёр. Повторное использование позволит бесконечно меняться с ним местами. Использование на той же клетке, что и активный костёр, уберёт его.")
+ chosen_message = span_boldwarning_alt("Вы оставите костёр. Повторное использование позволит бесконечно меняться с ним местами. Использование на той же клетке, что и активный костёр, уберёт его.")
chosen_attack_num = BONFIRE_TELEPORT
/datum/action/innate/elite_attack/throw_bone
name = "Бросок кости"
button_icon = 'icons/obj/mining.dmi'
button_icon_state = "bone"
- chosen_message = span_boldwarning("Вы бросаете тяжёлую кость.")
+ chosen_message = span_boldwarning_alt("Вы бросаете тяжёлую кость.")
chosen_attack_num = THROW_BONE
/mob/living/simple_animal/hostile/asteroid/elite/legionnaire/Destroy()
diff --git a/code/modules/mob/living/simple_animal/hostile/mining/elites/pandora.dm b/code/modules/mob/living/simple_animal/hostile/mining/elites/pandora.dm
index 57107a8c02a3..e510c932a0a5 100644
--- a/code/modules/mob/living/simple_animal/hostile/mining/elites/pandora.dm
+++ b/code/modules/mob/living/simple_animal/hostile/mining/elites/pandora.dm
@@ -66,25 +66,25 @@
/datum/action/innate/elite_attack/chaser_burst
name = "Преследователь"
button_icon_state = "singular_shot"
- chosen_message = span_boldwarning("Вы выпускаете преследующий снаряд за всеми мобами в поле зрения.")
+ chosen_message = span_boldwarning_alt("Вы выпускаете преследующий снаряд за всеми мобами в поле зрения.")
chosen_attack_num = CHASER_BURST
/datum/action/innate/elite_attack/magic_box
name = "Волшебная клетка"
button_icon_state = "magic_box"
- chosen_message = span_boldwarning("Теперь вы атакуете магическими квадратами.")
+ chosen_message = span_boldwarning_alt("Теперь вы атакуете магическими квадратами.")
chosen_attack_num = MAGIC_BOX
/datum/action/innate/elite_attack/pandora_teleport
name = "Телепорт"
button_icon_state = "pandora_teleport"
- chosen_message = span_boldwarning("Теперь вы будете телепортироваться к цели.")
+ chosen_message = span_boldwarning_alt("Теперь вы будете телепортироваться к цели.")
chosen_attack_num = PANDORA_TELEPORT
/datum/action/innate/elite_attack/aoe_squares
name = "Взрыв по площади"
button_icon_state = "aoe_squares"
- chosen_message = span_boldwarning("Ваши атаки будут создавать взрыв по области в месте попадания.")
+ chosen_message = span_boldwarning_alt("Ваши атаки будут создавать взрыв по области в месте попадания.")
chosen_attack_num = AOE_SQUARES
/mob/living/simple_animal/hostile/asteroid/elite/pandora/OpenFire()
diff --git a/code/modules/mob/living/simple_animal/hostile/statue.dm b/code/modules/mob/living/simple_animal/hostile/statue.dm
index f8cf3fe8d3cf..ebd5dc34955e 100644
--- a/code/modules/mob/living/simple_animal/hostile/statue.dm
+++ b/code/modules/mob/living/simple_animal/hostile/statue.dm
@@ -187,7 +187,7 @@
name = "Blindness"
desc = "Your prey will be momentarily blind for you to advance on them."
- message = span_notice("You glare your eyes.")
+ message = span_notice_alt("You glare your eyes.")
base_cooldown = 60 SECONDS
clothes_req = FALSE
human_req = FALSE
diff --git a/code/modules/mob/living/simple_animal/hostile/terror_spiders/abillities.dm b/code/modules/mob/living/simple_animal/hostile/terror_spiders/abillities.dm
index 60bb9517bed7..64c7b8bc93b6 100644
--- a/code/modules/mob/living/simple_animal/hostile/terror_spiders/abillities.dm
+++ b/code/modules/mob/living/simple_animal/hostile/terror_spiders/abillities.dm
@@ -75,8 +75,8 @@
invocation_type = "none"
action_icon_state = "fake_death"
action_background_icon_state = "bg_terror"
- selection_activated_message = span_notice("Вы подготавливаете свой ядовитый плевок! ЛКМ, чтобы плюнуть в цель.")
- selection_deactivated_message = span_notice("Вы отменяете свой плевок.")
+ selection_activated_message = span_notice_alt("Вы подготавливаете свой ядовитый плевок! ЛКМ, чтобы плюнуть в цель.")
+ selection_deactivated_message = span_notice_alt("Вы отменяете свой плевок.")
sound = 'sound/creatures/terrorspiders/spit2.ogg'
need_active_overlay = TRUE
base_cooldown = 25 SECONDS
@@ -111,8 +111,8 @@
invocation_type = "none"
action_icon_state = "smoke"
action_background_icon_state = "bg_terror"
- selection_activated_message = span_notice("Вы подготавливаете дымный плевок! ЛКМ, чтобы плюнуть в цель")
- selection_deactivated_message = span_notice("Вы отменяете свой плевок.")
+ selection_activated_message = span_notice_alt("Вы подготавливаете дымный плевок! ЛКМ, чтобы плюнуть в цель")
+ selection_deactivated_message = span_notice_alt("Вы отменяете свой плевок.")
sound = 'sound/creatures/terrorspiders/spit2.ogg'
need_active_overlay = TRUE
base_cooldown = 10 SECONDS
diff --git a/code/modules/mob/living/simple_animal/hostile/winter_mobs.dm b/code/modules/mob/living/simple_animal/hostile/winter_mobs.dm
index 673232695d67..5835d5e6157c 100644
--- a/code/modules/mob/living/simple_animal/hostile/winter_mobs.dm
+++ b/code/modules/mob/living/simple_animal/hostile/winter_mobs.dm
@@ -115,7 +115,7 @@
/mob/living/simple_animal/hostile/winter/santa/stage_1 //stage 1: slow melee
desc = "GET THE FAT MAN!"
next_stage = /mob/living/simple_animal/hostile/winter/santa/stage_2
- death_message = span_danger("HO HO HO! YOU THOUGHT IT WOULD BE THIS EASY?!?")
+ death_message = span_danger_alt("HO HO HO! YOU THOUGHT IT WOULD BE THIS EASY?!?")
speed = 2
melee_damage_lower = 10
melee_damage_upper = 20
@@ -123,7 +123,7 @@
/mob/living/simple_animal/hostile/winter/santa/stage_2 //stage 2: slow ranged
desc = "GET THE FAT MAN AGAIN!"
next_stage = /mob/living/simple_animal/hostile/winter/santa/stage_3
- death_message = span_danger("YOU'VE BEEN VERY NAUGHTY! PREPARE TO DIE!")
+ death_message = span_danger_alt("YOU'VE BEEN VERY NAUGHTY! PREPARE TO DIE!")
maxHealth = 200 //DID YOU REALLY BELIEVE IT WOULD BE THIS EASY!??!!
health = 200
ranged = 1
@@ -134,7 +134,7 @@
/mob/living/simple_animal/hostile/winter/santa/stage_3 //stage 3: fast rapidfire ranged
desc = "WHY WON'T HE DIE ALREADY!?"
next_stage = /mob/living/simple_animal/hostile/winter/santa/stage_4
- death_message = span_danger("FACE MY FINAL FORM AND KNOW DESPAIR!")
+ death_message = span_danger_alt("FACE MY FINAL FORM AND KNOW DESPAIR!")
maxHealth = 250
health = 250
ranged = 1
diff --git a/code/modules/mob/living/simple_animal/hulk_power.dm b/code/modules/mob/living/simple_animal/hulk_power.dm
index a794e2a70787..db876c6fe046 100644
--- a/code/modules/mob/living/simple_animal/hulk_power.dm
+++ b/code/modules/mob/living/simple_animal/hulk_power.dm
@@ -455,8 +455,8 @@
invocation_type = "none"
action_icon_state = "harchok_hulk"
action_background_icon_state = "bg_hulk"
- selection_activated_message = span_notice("Your prepare to spit fire! Left-click to spit at a target!")
- selection_deactivated_message = span_notice("You swallow your spit...for now.")
+ selection_activated_message = span_notice_alt("Your prepare to spit fire! Left-click to spit at a target!")
+ selection_deactivated_message = span_notice_alt("You swallow your spit...for now.")
fireball_type = /obj/projectile/energy/hulkspit
base_cooldown = 25 SECONDS
need_active_overlay = TRUE
@@ -475,8 +475,8 @@
name = "LazorZ"
desc = "Вы стреляете из глаз слабеньким лазером. Может помочь, если хитрые СБшники прячутся за стеклами."
action_icon_state = "lazer_hulk"
- selection_activated_message = span_notice("You strained your eyes preparing the LAZOR! Left-click to fire at a target!")
- selection_deactivated_message = span_notice("You relax your eyes...for now.")
+ selection_activated_message = span_notice_alt("You strained your eyes preparing the LAZOR! Left-click to fire at a target!")
+ selection_deactivated_message = span_notice_alt("You relax your eyes...for now.")
fireball_type = /obj/projectile/beam
base_cooldown = 7 SECONDS
sound = 'sound/weapons/laser.ogg'
diff --git a/code/modules/mob/living/simple_animal/simple_animal.dm b/code/modules/mob/living/simple_animal/simple_animal.dm
index f945e7740545..1c639db337d6 100644
--- a/code/modules/mob/living/simple_animal/simple_animal.dm
+++ b/code/modules/mob/living/simple_animal/simple_animal.dm
@@ -192,6 +192,19 @@
if(pcollar)
pcollar = new(src)
regenerate_icons()
+ if(LAZYLEN(speak))
+ speak = string_list(speak)
+ if(LAZYLEN(speak_emote))
+ speak_emote = string_list(speak_emote)
+ if(LAZYLEN(emote_hear))
+ emote_hear = string_list(emote_hear)
+ if(LAZYLEN(emote_see))
+ emote_see = string_list(emote_see)
+ if(LAZYLEN(loot))
+ loot = string_list(loot)
+ damage_coeff = string_assoc_list(damage_coeff)
+ if(LAZYLEN(atmos_requirements))
+ atmos_requirements = string_assoc_list(atmos_requirements)
if(footstep_type)
AddElement(/datum/element/footstep, footstep_type)
add_strippable_element()
diff --git a/code/modules/mob/mob.dm b/code/modules/mob/mob.dm
index 63172039f3ca..29bba1fbeeb3 100644
--- a/code/modules/mob/mob.dm
+++ b/code/modules/mob/mob.dm
@@ -10,6 +10,7 @@
observe.stop_orbit()
observe.reset_perspective(null)
QDEL_NULL(hud_used)
+ lose_hearing_sensitivity()
if(mind && mind.current == src)
spellremove(src)
mobspellremove(src)
@@ -17,8 +18,7 @@
for(var/alert in alerts)
clear_alert(alert)
if(client)
- var/client/client_ = client
- client_.movingmob = null
+ clear_client_in_contents()
ghostize()
QDEL_LIST_ASSOC_VAL(tkgrabbed_objects)
if(buckled)
@@ -29,7 +29,8 @@
if(mind?.current == src)
mind.current = null
-
+ key = null
+ ckey = null
return ..()
/mob/Initialize(mapload)
diff --git a/code/modules/mod/modules/_modules.dm b/code/modules/mod/modules/_modules.dm
index d97157ab3884..d2ed87f1562b 100644
--- a/code/modules/mod/modules/_modules.dm
+++ b/code/modules/mod/modules/_modules.dm
@@ -94,6 +94,7 @@
/obj/item/mod/module/Destroy()
mod?.uninstall(src)
+ mod = null
if(device)
UnregisterSignal(device, COMSIG_QDELETING)
QDEL_NULL(device)
diff --git a/code/modules/mod/modules/modules_general.dm b/code/modules/mod/modules/modules_general.dm
index e8a28dcfcb11..fbe8be6efd06 100644
--- a/code/modules/mod/modules/modules_general.dm
+++ b/code/modules/mod/modules/modules_general.dm
@@ -49,8 +49,10 @@
bag.source = src
/obj/item/mod/module/storage/Destroy()
+ if(mod && mod.bag == bag)
+ mod.bag = null
QDEL_NULL(bag)
- return ..()
+ . = ..()
/obj/item/mod/module/storage/on_install()
. = ..()
@@ -65,6 +67,8 @@
bag.forceMove(src)
mod.bag = null
return
+ if(mod && mod.bag == bag)
+ mod.bag = null
qdel(bag)
var/obj/item/clothing/suit = mod.get_part_from_slot(ITEM_SLOT_CLOTH_OUTER)
if(istype(suit))
@@ -174,7 +178,14 @@
/obj/item/storage/backpack/modstorage/Destroy()
STOP_PROCESSING(SSobj, src)
- return ..()
+ if(source)
+ var/obj/item/mod/module/storage/cached_source = source
+ if(cached_source.bag == src)
+ source.bag = null
+ if(cached_source.mod?.bag == src)
+ source.bag = null
+ source = null
+ . = ..()
/obj/item/storage/backpack/modstorage/process()
update_viewers()
diff --git a/code/modules/mod/modules/modules_supply.dm b/code/modules/mod/modules/modules_supply.dm
index 28283a272bed..96e845ccdd1a 100644
--- a/code/modules/mod/modules/modules_supply.dm
+++ b/code/modules/mod/modules/modules_supply.dm
@@ -478,7 +478,7 @@
if(traveled_tiles == max_traveled_tiles - 1) // Just lost our speed buff
mod.update_speed()
for(var/obj/item/part as anything in mod.get_parts(all = TRUE))
- part.armor = part.armor.detachArmor(armor_mod_1.armor)
+ part.armor = part.armor?.detachArmor(armor_mod_1.armor)
if(traveled_tiles <= 0)
balloon_alert(mod.wearer, "недостаточно пепла!")
return
@@ -487,7 +487,7 @@
return
traveled_tiles++
for(var/obj/item/part as anything in mod.get_parts(all = TRUE))
- part.armor = part.armor.attachArmor(armor_mod_1.armor)
+ part.armor = part.armor?.attachArmor(armor_mod_1.armor)
if(traveled_tiles < max_traveled_tiles)
return
balloon_alert(mod.wearer, "полное покрытие пеплом")
diff --git a/code/modules/paperwork/photography/camera.dm b/code/modules/paperwork/photography/camera.dm
index e2bac4f1f4db..57072e382e64 100644
--- a/code/modules/paperwork/photography/camera.dm
+++ b/code/modules/paperwork/photography/camera.dm
@@ -376,6 +376,17 @@
/// The camera this circut is attached to.
var/obj/item/camera/camera
+/obj/item/circuit_component/camera/Destroy()
+ if(camera)
+ unregister_usb_parent(camera)
+ photographed_atom = null
+ picture_taken = null
+ picture_target = null
+ picture_coord_x = null
+ picture_coord_y = null
+ adjust_size = null
+ . = ..()
+
/obj/item/circuit_component/camera/populate_ports()
picture_taken = add_output_port("Снимок сделан", PORT_TYPE_SIGNAL)
photographed_atom = add_output_port("Цель", PORT_TYPE_ATOM)
diff --git a/code/modules/power/singularity/singularity.dm b/code/modules/power/singularity/singularity.dm
index 6f1f3e72b6ff..72680992203b 100644
--- a/code/modules/power/singularity/singularity.dm
+++ b/code/modules/power/singularity/singularity.dm
@@ -509,7 +509,7 @@
qdel(projectile)
return
- projectile_angle += angle_to_singulo / (distance_to_singulo ** 2)
+ projectile_angle += angle_to_singulo / POW2(distance_to_singulo)
projectile.damage += 10 / distance_to_singulo
projectile.set_angle(projectile_angle)
diff --git a/code/modules/power/solar.dm b/code/modules/power/solar.dm
index dc64422e144f..30bb10af7d42 100644
--- a/code/modules/power/solar.dm
+++ b/code/modules/power/solar.dm
@@ -131,8 +131,10 @@
if(p_angle > 90) // if facing more than 90deg from sun, zero output
sunfrac = 0
return
+
+ var/cos_p_angle = cos(p_angle)
- sunfrac = cos(p_angle) ** 2
+ sunfrac = POW2(cos_p_angle)
//isn't the power received from the incoming light proportionnal to cos(p_angle) (Lambert's cosine law) rather than cos(p_angle)^2 ?
/obj/machinery/power/solar/process()//TODO: remove/add this from machines to save on processing as needed ~Carn PRIORITY
diff --git a/code/modules/power/supermatter/supermatter.dm b/code/modules/power/supermatter/supermatter.dm
index f834caa0fbbb..8e9e7b999c86 100644
--- a/code/modules/power/supermatter/supermatter.dm
+++ b/code/modules/power/supermatter/supermatter.dm
@@ -609,7 +609,7 @@
var/crush_ratio = combined_gas / MOLE_CRUNCH_THRESHOLD
- gas_coefficient = 1 + (crush_ratio ** 2 * (crush_ratio <= 1) + (crush_ratio > 1) * 2 * crush_ratio / (crush_ratio + 1)) * (plasmacomp * PLASMA_CRUNCH + o2comp * O2_CRUNCH + co2comp * CO2_CRUNCH + n2comp * N2_CRUNCH + n2ocomp * N2O_CRUNCH + h2comp * HYDROGEN_CRUNCH + h2ocomp * H2O_CRUNCH)
+ gas_coefficient = 1 + (POW2(crush_ratio) * (crush_ratio <= 1) + (crush_ratio > 1) * 2 * crush_ratio / (crush_ratio + 1)) * (plasmacomp * PLASMA_CRUNCH + o2comp * O2_CRUNCH + co2comp * CO2_CRUNCH + n2comp * N2_CRUNCH + n2ocomp * N2O_CRUNCH + h2comp * HYDROGEN_CRUNCH + h2ocomp * H2O_CRUNCH)
//radiation_pulse(src, power * (gas_coefficient + max(0, ((power_transmission_bonus / 10)))))
@@ -648,7 +648,8 @@
//Transitions between one function and another, one we use for the fast inital startup, the other is used to prevent errors with fusion temperatures.
//Use of the second function improves the power gain imparted by using co2
if(power_changes)
- power = max((power - min(((power / 500) ** 3) * powerloss_inhibitor, power * 0.83 * powerloss_inhibitor) + power_additive), 0)
+ var/power_fixed = (power / 500)
+ power = max((power - min(POW3(power_fixed) * powerloss_inhibitor, power * 0.83 * powerloss_inhibitor) + power_additive), 0)
//After this point power is lowered
//This wraps around to the begining of the function
//Handle high power zaps/anomaly generation
diff --git a/code/modules/power/turbine.dm b/code/modules/power/turbine.dm
index 213638c73f5a..331f473d0261 100644
--- a/code/modules/power/turbine.dm
+++ b/code/modules/power/turbine.dm
@@ -403,6 +403,8 @@
// We just changed our composition
gas_heat_capacity = compressor_gas.heat_capacity()
+
+ var/bearing_damage_ratio = (1 - compressor.bearing_damage / BEARING_DAMAGE_MAX)
// The portion of the thermal energy of the gas converted to kinetic energy
compressor.thermal_efficiency = (compressor_gas.return_pressure() + output_side.return_pressure()) <= 0 ? 0 : \
@@ -411,7 +413,7 @@
((THERMAL_EFF_PART_BASE + compressor.efficiency) / (THERMAL_EFF_PART_BASE + 4)) * \
(compressor_gas.temperature() / (compressor_gas.temperature() + THERMAL_EFF_TEMP_CURVE)) * \
(compressor_gas.return_pressure() / (compressor_gas.return_pressure() + output_side.return_pressure())) * \
- ((1 - compressor.bearing_damage / BEARING_DAMAGE_MAX) ** 3)
+ (POW3(bearing_damage_ratio))
var/kinetic_energy_gain = compressor_gas.thermal_energy() * compressor.thermal_efficiency
diff --git a/code/modules/projectiles/ammunition.dm b/code/modules/projectiles/ammunition.dm
index af08c8e3dd63..6ac43d4346e7 100644
--- a/code/modules/projectiles/ammunition.dm
+++ b/code/modules/projectiles/ammunition.dm
@@ -58,6 +58,9 @@
/obj/item/ammo_casing/Destroy()
QDEL_NULL(BB)
+ if(isammobox(loc))
+ var/obj/item/ammo_box/box = loc
+ box.stored_ammo?.RemoveAll(src)
if(!isgun(loc))
return ..()
var/obj/item/gun/gun = loc
diff --git a/code/modules/projectiles/gun.dm b/code/modules/projectiles/gun.dm
index 0fe49aa004c8..8e6dffce6264 100644
--- a/code/modules/projectiles/gun.dm
+++ b/code/modules/projectiles/gun.dm
@@ -135,8 +135,10 @@
if(!attachments_by_slot[attachment])
continue
qdel(attachments_by_slot[attachment])
- attachments_by_slot.Cut()
- attachment_overlays.Cut()
+ LAZYCLEARLIST(attachments_by_slot)
+ LAZYCLEARLIST(attachment_overlays)
+ QDEL_NULL(azoom)
+ QDEL_NULL(chambered)
if(accuracy)
QDEL_NULL(accuracy)
if(recoil)
diff --git a/code/modules/projectiles/guns/projectile.dm b/code/modules/projectiles/guns/projectile.dm
index dcdd55f62812..d3512d9efd05 100644
--- a/code/modules/projectiles/guns/projectile.dm
+++ b/code/modules/projectiles/guns/projectile.dm
@@ -23,6 +23,7 @@
update_icon()
/obj/item/gun/projectile/Destroy()
+ QDEL_NULL(magazine)
. = ..()
UnregisterSignal(src, COMSIG_ITEM_ATTACK_SELF)
diff --git a/code/modules/reagents/chemistry/holder.dm b/code/modules/reagents/chemistry/holder.dm
index fd9500f1a4fc..ab5b3f88ed9a 100644
--- a/code/modules/reagents/chemistry/holder.dm
+++ b/code/modules/reagents/chemistry/holder.dm
@@ -21,6 +21,16 @@
if(temperature_maximum)
temperature_max = temperature_maximum
+/datum/reagents/Destroy()
+ . = ..()
+ QDEL_LIST(reagent_list)
+ reagent_list = null
+ QDEL_LIST(addiction_list)
+ addiction_list = null
+ if(my_atom && my_atom.reagents == src)
+ my_atom.reagents = null
+ my_atom = null
+
/datum/reagents/proc/remove_any(amount = 1)
var/list/cached_reagents = reagent_list
var/total_transfered = 0
@@ -940,14 +950,5 @@
return clothing_pen
-/datum/reagents/Destroy()
- . = ..()
- QDEL_LIST(reagent_list)
- reagent_list = null
- QDEL_LIST(addiction_list)
- addiction_list = null
- if(my_atom && my_atom.reagents == src)
- my_atom.reagents = null
-
#undef ADDICTION_TIME
#undef MINOR_ADDICTION_TIME
diff --git a/code/modules/reagents/chemistry/reagents/alcohol.dm b/code/modules/reagents/chemistry/reagents/alcohol.dm
index b896be91ff97..d252d60f6aec 100644
--- a/code/modules/reagents/chemistry/reagents/alcohol.dm
+++ b/code/modules/reagents/chemistry/reagents/alcohol.dm
@@ -1096,7 +1096,7 @@
description = "Производство этого напитка вероятно, нарушает Женевскую конвенцию."
color = "#DC0000"
can_synth = FALSE
- taste_description = span_userdanger("ЖИДКОЙ БЛЯДЬ СМЕРТИ СУКА ПИЗДЕЦ НАХУЙ КАКОГО ХУЯ")
+ taste_description = span_userdanger_alt("ЖИДКОЙ БЛЯДЬ СМЕРТИ СУКА ПИЗДЕЦ НАХУЙ КАКОГО ХУЯ")
/datum/reagent/consumable/ethanol/dragons_breath/reaction_mob(mob/living/M, method=REAGENT_TOUCH, volume)
if(method == REAGENT_INGEST && prob(20))
diff --git a/code/modules/reagents/chemistry/reagents/food.dm b/code/modules/reagents/chemistry/reagents/food.dm
index 250d64d256a9..07aeebc44c80 100644
--- a/code/modules/reagents/chemistry/reagents/food.dm
+++ b/code/modules/reagents/chemistry/reagents/food.dm
@@ -242,7 +242,7 @@
description = "Именно это делает чили острым."
reagent_state = LIQUID
color = "#B31008" // rgb: 179, 16, 8
- taste_description = span_warning("ОСТРОТЫ")
+ taste_description = span_warning_alt("ОСТРОТЫ")
taste_mult = 1.5
/datum/reagent/consumable/capsaicin/on_mob_life(mob/living/M)
@@ -279,7 +279,7 @@
description = "Ещё острее."
reagent_state = LIQUID
color = "#B31008" // rgb: 179, 16, 8
- taste_description = span_userdanger("НЕРЕАЛЬНОЙ ОСТРОТЫ")
+ taste_description = span_userdanger_alt("НЕРЕАЛЬНОЙ ОСТРОТЫ")
/datum/reagent/consumable/condensedcapsaicin/reaction_mob(mob/living/M, method=REAGENT_TOUCH, volume)
if(method == REAGENT_TOUCH)
diff --git a/code/modules/reagents/chemistry/reagents/medicine.dm b/code/modules/reagents/chemistry/reagents/medicine.dm
index 882ce570a7fd..f7ea654aee22 100644
--- a/code/modules/reagents/chemistry/reagents/medicine.dm
+++ b/code/modules/reagents/chemistry/reagents/medicine.dm
@@ -1063,7 +1063,7 @@
color = "#C8A5DC"
harmless = FALSE
can_synth = FALSE
- taste_description = span_userdanger("нереальной бодрости")
+ taste_description = span_userdanger_alt("нереальной бодрости")
var/absorption_applied = FALSE
/datum/reagent/medicine/stimulants/on_mob_life(mob/living/M)
diff --git a/code/modules/reagents/chemistry/reagents/toxins.dm b/code/modules/reagents/chemistry/reagents/toxins.dm
index efdfa157c27c..fee355630f8d 100644
--- a/code/modules/reagents/chemistry/reagents/toxins.dm
+++ b/code/modules/reagents/chemistry/reagents/toxins.dm
@@ -341,7 +341,7 @@
reagent_state = LIQUID
color = "#00FF32"
process_flags = ORGANIC | SYNTHETIC
- taste_description = span_userdanger("РАЗЪЕДАЮЩЕЙ КИСЛОТЫ")
+ taste_description = span_userdanger_alt("РАЗЪЕДАЮЩЕЙ КИСЛОТЫ")
//acid is not using permeability_coefficient to calculate protection, but armour["acid"]
clothing_penetration = 1
var/acidpwr = 10 //the amount of protection removed from the armour
@@ -1335,7 +1335,7 @@
description = "Образец потерянной породы космических муравьёв (Formicidae bastardium tyrannus). Они известны тем, что способны поглотить практически всё."
color = "#993333"
process_flags = ORGANIC | SYNTHETIC
- taste_description = span_warning("МУРАВЬЁВ")
+ taste_description = span_warning_alt("МУРАВЬЁВ")
/datum/reagent/ants/on_mob_life(mob/living/M)
var/update_flags = STATUS_UPDATE_NONE
@@ -1450,7 +1450,7 @@
color = "#353434"
process_flags = ORGANIC | SYNTHETIC
metabolization_rate = 5
- taste_description = span_warning("МЕТАЛЛИЧЕСКОЙ ПЫЛИ И МАСЛА, БЛЯДЬ!")
+ taste_description = span_warning_alt("МЕТАЛЛИЧЕСКОЙ ПЫЛИ И МАСЛА, БЛЯДЬ!")
/datum/reagent/metalic_dust/on_mob_life(mob/living/M)
M.emote("scream")
diff --git a/code/modules/reagents/chemistry/recipes/drinks.dm b/code/modules/reagents/chemistry/recipes/drinks.dm
index 0b4b74c7dbb1..e9b5b4c2241b 100644
--- a/code/modules/reagents/chemistry/recipes/drinks.dm
+++ b/code/modules/reagents/chemistry/recipes/drinks.dm
@@ -881,7 +881,7 @@
result = "bacchus_blessing"
required_reagents = list("hooch" = 1, "absinthe" = 1, "manlydorf" = 1, "syndicatebomb" = 1)
result_amount = 4
- mix_message = span_warning("The mixture turns to a sickening froth.")
+ mix_message = span_warning_alt("The mixture turns to a sickening froth.")
/datum/chemical_reaction/fernet_cola
name = "Fernet Cola"
diff --git a/code/modules/reagents/chemistry/recipes/pyrotechnics.dm b/code/modules/reagents/chemistry/recipes/pyrotechnics.dm
index 68031fc4619d..d5c86135ad86 100644
--- a/code/modules/reagents/chemistry/recipes/pyrotechnics.dm
+++ b/code/modules/reagents/chemistry/recipes/pyrotechnics.dm
@@ -393,7 +393,7 @@
result = null
required_reagents = list("teslium" = 5, "uranium" = 5) //uranium to this so it can't be spammed like no tomorrow without mining help.
result_amount = 1
- mix_message = span_danger("The reaction releases an electrical blast!")
+ mix_message = span_danger_alt("The reaction releases an electrical blast!")
mix_sound = 'sound/magic/lightningbolt.ogg'
/atom/proc/do_shock_ex(radius, damage = 3.5, animate = FALSE)
diff --git a/code/modules/reagents/chemistry/recipes/toxins.dm b/code/modules/reagents/chemistry/recipes/toxins.dm
index 2848610ae3c5..7b370bcfa852 100644
--- a/code/modules/reagents/chemistry/recipes/toxins.dm
+++ b/code/modules/reagents/chemistry/recipes/toxins.dm
@@ -130,7 +130,7 @@
result = "teslium"
required_reagents = list("plasma" = 1, "silver" = 1, "blackpowder" = 1)
result_amount = 3
- mix_message = span_danger("A jet of sparks flies from the mixture as it merges into a flickering slurry.")
+ mix_message = span_danger_alt("A jet of sparks flies from the mixture as it merges into a flickering slurry.")
min_temp = T0C + 50
mix_sound = null
@@ -165,4 +165,4 @@
result = "rotatium"
required_reagents = list("lsd" = 1, "teslium" = 1, "methamphetamine" = 1)
result_amount = 3
- mix_message = span_danger("After sparks, fire, and the smell of LSD, the mix is constantly spinning with no stop in sight.")
+ mix_message = span_danger_alt("After sparks, fire, and the smell of LSD, the mix is constantly spinning with no stop in sight.")
diff --git a/code/modules/reagents/reagent_containers.dm b/code/modules/reagents/reagent_containers.dm
index dcf9fc83c8cd..28ac060fb753 100644
--- a/code/modules/reagents/reagent_containers.dm
+++ b/code/modules/reagents/reagent_containers.dm
@@ -97,6 +97,8 @@
var/datum/disease/F = new spawned_disease
var/list/data = list("diseases" = list(F), "blood_color" = BLOOD_COLOR_RED)
reagents.add_reagent("blood", disease_amount, data)
+ if(list_reagents)
+ list_reagents = string_assoc_list(list_reagents)
add_initial_reagents()
update_icon()
diff --git a/code/modules/reagents/reagent_containers/hypospray.dm b/code/modules/reagents/reagent_containers/hypospray.dm
index e8fc457dde20..ddda1bc785df 100644
--- a/code/modules/reagents/reagent_containers/hypospray.dm
+++ b/code/modules/reagents/reagent_containers/hypospray.dm
@@ -614,7 +614,7 @@
/obj/item/reagent_containers/hypospray/autoinjector/survival
name = "survival medipen"
- desc = "Маленький инъектор в форме ручки, содержащий внутри дозу веществ для спасения во время экстренных ситуаций, которые могут произойти на пустошах Лазиса.\n" + span_boldwarning("ПРЕДУПРЕЖДЕНИЕ: Не используйте более одного за раз!")
+ desc = "Маленький инъектор в форме ручки, содержащий внутри дозу веществ для спасения во время экстренных ситуаций, которые могут произойти на пустошах Лазиса.\n" + span_boldwarning_alt("ПРЕДУПРЕЖДЕНИЕ: Не используйте более одного за раз!")
icon_state = "stimpen"
belt_icon = "survival_medipen"
volume = 42
@@ -633,7 +633,7 @@
/obj/item/reagent_containers/hypospray/autoinjector/survival/luxury
name = "luxury medipen"
- desc = "Улучшенная версия стандартного автоинъектора выживания, вмещающая в себя до 40 единиц мощных медикаментов." + span_boldwarning("ПРЕДУПРЕЖДЕНИЕ: Не используйте более одного за раз!")
+ desc = "Улучшенная версия стандартного автоинъектора выживания, вмещающая в себя до 40 единиц мощных медикаментов." + span_boldwarning_alt("ПРЕДУПРЕЖДЕНИЕ: Не используйте более одного за раз!")
icon_state = "redinjector"
volume = 40
amount_per_transfer_from_this = 40
diff --git a/code/modules/recycling/conveyor2.dm b/code/modules/recycling/conveyor2.dm
index 8df8b8d15a66..1c26c8501e1a 100644
--- a/code/modules/recycling/conveyor2.dm
+++ b/code/modules/recycling/conveyor2.dm
@@ -692,6 +692,15 @@ GLOBAL_LIST_EMPTY(conveyors_by_id)
/// The switch this conveyor switch component is attached to.
var/obj/machinery/conveyor_switch/attached_switch
+/obj/item/circuit_component/conveyor_switch/Destroy()
+ if(attached_switch)
+ unregister_usb_parent(attached_switch)
+ stop = null
+ active = null
+ reverse = null
+ direction = null
+ . = ..()
+
/obj/item/circuit_component/conveyor_switch/populate_ports()
active = add_input_port("Старт", PORT_TYPE_SIGNAL, trigger = PROC_REF(activate))
stop = add_input_port("Стоп", PORT_TYPE_SIGNAL, trigger = PROC_REF(stop))
diff --git a/code/modules/research/designs.dm b/code/modules/research/designs.dm
index 8fa7e43e10b2..9c1892b8f174 100644
--- a/code/modules/research/designs.dm
+++ b/code/modules/research/designs.dm
@@ -75,6 +75,10 @@ other types of metals and chemistry for reagents).
build_object_name = design_name
return
+ var/list/category_cached = category
+ if(islist(category_cached))
+ category = string_list(category_cached)
+
var/obj/item/design_item = new build_path
design_name = DECLENT_RU_CAP(design_item, NOMINATIVE)
qdel(design_item)
diff --git a/code/modules/shuttle/shuttle_smash.dm b/code/modules/shuttle/shuttle_smash.dm
index 38f350a1046c..53a7d2e64a50 100644
--- a/code/modules/shuttle/shuttle_smash.dm
+++ b/code/modules/shuttle/shuttle_smash.dm
@@ -25,8 +25,9 @@
if(!length(viewers_by_turf[turf]) || !length(things_by_turf[turf]))
continue
var/destroyed = capitalize(english_list(things_by_turf[turf]))
- for(var/mob/viewer as anything in viewers_by_turf[turf])
- viewer.show_message(span_warning("[destroyed] gets crushed by a hyperspace ripple!"), EMOTE_VISIBLE)
+ var/message = span_warning("[destroyed] gets crushed by a hyperspace ripple!")
+ for(var/mob/viewer in viewers_by_turf[turf])
+ viewer.show_message(message, EMOTE_VISIBLE)
/**
* Atom crushed by shuttle feedback.
diff --git a/code/modules/space_management/zlevel_manager.dm b/code/modules/space_management/zlevel_manager.dm
index f4695af037bd..5fad4ed4e8b4 100644
--- a/code/modules/space_management/zlevel_manager.dm
+++ b/code/modules/space_management/zlevel_manager.dm
@@ -17,6 +17,7 @@ GLOBAL_DATUM_INIT(space_manager, /datum/zlev_manager, new())
/datum/zlev_manager/proc/initialize()
var/num_official_z_levels = GLOB.map_transition_config.len
var/k = 1
+ milla_reset()
// First take care of "Official" z levels, without visiting levels outside of the list
for(var/list/features in GLOB.map_transition_config)
diff --git a/code/modules/spacepods/equipment.dm b/code/modules/spacepods/equipment.dm
index fd34a2c957d3..ec001c756952 100644
--- a/code/modules/spacepods/equipment.dm
+++ b/code/modules/spacepods/equipment.dm
@@ -55,10 +55,21 @@
var/obj/item/spacepod_equipment/weaponry/weapon_system // weapons system
var/obj/item/spacepod_equipment/misc/misc_system // misc system
var/obj/item/spacepod_equipment/cargo/cargo_system // cargo system
- var/obj/item/spacepod_equipment/cargo/sec_cargo_system // secondary cargo system
+ var/obj/item/spacepod_equipment/sec_cargo/sec_cargo_system // secondary cargo system
var/obj/item/spacepod_equipment/lock/lock_system // lock system
var/obj/item/spacepod_equipment/locators/locator_system //locator_system
+/datum/spacepod/equipment/Destroy(force)
+ my_atom = null
+ QDEL_LIST(installed_modules)
+ weapon_system = null
+ misc_system = null
+ cargo_system = null
+ sec_cargo_system = null
+ lock_system = null
+ locator_system = null
+ . = ..()
+
/datum/spacepod/equipment/New(obj/spacepod/SP)
..()
if(istype(SP))
@@ -71,6 +82,11 @@
var/occupant_mod = 0 // so any module can modify occupancy
var/list/storage_mod = list("slots" = 0, "w_class" = 0) // so any module can modify storage slots
+/obj/item/spacepod_equipment/Destroy()
+ my_atom?.equipment_system?.installed_modules -= src
+ my_atom = null
+ . = ..()
+
/obj/item/spacepod_equipment/proc/removed(mob/user) // So that you can unload cargo when you remove the module
return
@@ -91,6 +107,11 @@
var/fire_delay = 15
var/harmful = TRUE
+/obj/item/spacepod_equipment/weaponry/Destroy()
+ if(my_atom?.equipment_system?.weapon_system == src)
+ my_atom.equipment_system.weapon_system = null
+ . = ..()
+
/obj/item/spacepod_equipment/weaponry/taser
name = "disabler system"
desc = "A weak disabler system for space pods, fires disabler beams."
@@ -176,6 +197,8 @@ GLOBAL_LIST_EMPTY(pod_trackers)
/obj/item/spacepod_equipment/misc/tracker/Destroy()
GLOB.pod_trackers -= src
+ if(my_atom?.equipment_system?.misc_system == src)
+ my_atom.equipment_system.misc_system = null
return ..()
/*
@@ -190,6 +213,12 @@ GLOBAL_LIST_EMPTY(pod_trackers)
icon_state = "cargo_blank"
var/obj/storage = null
+/obj/item/spacepod_equipment/cargo/Destroy()
+ if(my_atom?.equipment_system?.cargo_system == src)
+ my_atom.equipment_system.cargo_system = null
+ QDEL_NULL(storage)
+ . = ..()
+
/obj/item/spacepod_equipment/cargo/proc/passover(obj/item/I)
return
@@ -229,6 +258,11 @@ GLOBAL_LIST_EMPTY(pod_trackers)
desc = "you shouldn't be seeing this"
icon_state = null
+/obj/item/spacepod_equipment/sec_cargo/Destroy()
+ if(my_atom?.equipment_system?.sec_cargo_system == src)
+ my_atom.equipment_system.sec_cargo_system = null
+ . = ..()
+
// Passenger Seat
/obj/item/spacepod_equipment/sec_cargo/chair
name = "passenger seat"
@@ -256,6 +290,11 @@ GLOBAL_LIST_EMPTY(pod_trackers)
var/mode = 0
var/id = null
+/obj/item/spacepod_equipment/lock/Destroy()
+ if(my_atom?.equipment_system?.lock_system == src)
+ my_atom.equipment_system.lock_system = null
+ . = ..()
+
// Key and Tumbler System
/obj/item/spacepod_equipment/lock/keyed
name = "spacepod tumbler lock"
@@ -298,6 +337,11 @@ GLOBAL_LIST_EMPTY(pod_trackers)
var/can_ignore_z = FALSE
var/can_found_all = FALSE
+/obj/item/spacepod_equipment/locators/Destroy()
+ if(my_atom?.equipment_system?.locator_system == src)
+ my_atom.equipment_system.locator_system = null
+ . = ..()
+
/obj/item/spacepod_equipment/locators/proc/scan(mob/user)
var/message_user = ""
diff --git a/code/modules/spacepods/spacepod.dm b/code/modules/spacepods/spacepod.dm
index 359be86e6219..9c906832695d 100644
--- a/code/modules/spacepods/spacepod.dm
+++ b/code/modules/spacepods/spacepod.dm
@@ -174,6 +174,12 @@
QDEL_NULL(cabin_air)
QDEL_NULL(internal_tank)
QDEL_NULL(ion_trail)
+ QDEL_NULL(eject_action)
+ QDEL_NULL(passanger_eject)
+ QDEL_NULL(internals_action)
+ QDEL_NULL(lights_action)
+ QDEL_NULL(fire_action)
+ QDEL_NULL(misc_action)
occupant_sanity_check()
if(pilot)
eject_pilot()
diff --git a/code/modules/station_goals/shield.dm b/code/modules/station_goals/shield.dm
index 2da6b365cba0..8a8c116fdbc1 100644
--- a/code/modules/station_goals/shield.dm
+++ b/code/modules/station_goals/shield.dm
@@ -172,6 +172,15 @@
/// A list of "proxy" objects used for multi-z coverage.
var/list/obj/effect/abstract/meteor_shield_proxy/proxies = list()
+/obj/machinery/satellite/meteor_shield/Destroy()
+ QDEL_NULL(proximity_monitor)
+ LAZYCLEARLIST(proxies)
+ if(!(active && emagged))
+ return ..()
+
+ change_meteor_chance(0.5)
+ return ..()
+
/obj/machinery/satellite/meteor_shield/examine(mob/user)
. = ..()
if(active)
@@ -196,14 +205,6 @@
proximity_monitor = new(src, kill_range)
setup_proxies()
-/obj/machinery/satellite/meteor_shield/Destroy()
- QDEL_NULL(proximity_monitor)
- if(!(active && emagged))
- return ..()
-
- change_meteor_chance(0.5)
- return ..()
-
/obj/machinery/satellite/meteor_shield/on_changed_z_level(turf/old_turf, turf/new_turf, same_z_layer, notify_contents)
. = ..()
setup_proxies()
@@ -303,9 +304,9 @@
/obj/effect/abstract/meteor_shield_proxy/Destroy(force)
QDEL_NULL(proximity_monitor)
- parent.proxies -= src
+ parent.proxies.RemoveAll(src)
parent = null
- return ..()
+ . = ..()
/obj/effect/abstract/meteor_shield_proxy/HasProximity(atom/movable/AM)
parent.shoot_meteor(AM)
diff --git a/code/modules/surgery/organs/augments_arms.dm b/code/modules/surgery/organs/augments_arms.dm
index 151518162451..aca45dfea743 100644
--- a/code/modules/surgery/organs/augments_arms.dm
+++ b/code/modules/surgery/organs/augments_arms.dm
@@ -27,6 +27,7 @@
/obj/item/organ/internal/cyberimp/arm/Destroy()
QDEL_NULL(active_item)
+ QDEL_LIST(items_list)
hand = null
return ..()
@@ -296,7 +297,8 @@
/obj/item/organ/internal/cyberimp/arm/flash/Extend(obj/item/item)
. = ..()
- active_item.set_light(7, l_on = TRUE)
+ active_item.set_light_range(7)
+ active_item.set_light_on(TRUE)
/obj/item/organ/internal/cyberimp/arm/flash/Retract()
if(!active_item || (active_item in src))
diff --git a/code/modules/surgery/organs/augments_internal.dm b/code/modules/surgery/organs/augments_internal.dm
index 823288fe17d0..9d51cc1fc5d5 100644
--- a/code/modules/surgery/organs/augments_internal.dm
+++ b/code/modules/surgery/organs/augments_internal.dm
@@ -227,7 +227,7 @@
/obj/item/organ/internal/cyberimp/brain/clown_voice
name = "Comical implant"
- desc = span_sans("Uh oh.")
+ desc = span_sans_alt("Uh oh.")
implant_color = "#DEDE00"
slot = INTERNAL_ORGAN_BRAIN_CLOWNVOICE
origin_tech = "materials=2;biotech=2"
diff --git a/code/modules/tgui/tgui_window.dm b/code/modules/tgui/tgui_window.dm
index c1b48e794a5c..27613813a5c0 100644
--- a/code/modules/tgui/tgui_window.dm
+++ b/code/modules/tgui/tgui_window.dm
@@ -17,7 +17,7 @@
var/subscriber_delegate
var/fatally_errored = FALSE
var/message_queue
- var/sent_assets = list()
+ var/list/sent_assets = list()
// Vars passed to initialize proc (and saved for later)
var/initial_strict_mode
var/initial_fancy
@@ -49,6 +49,9 @@
subscriber_object = null
client.tgui_windows[id] = null
client = null
+ message_queue = null
+ oversized_payloads = null
+ sent_assets = null
. = ..()
/**
diff --git a/code/modules/wiremod/components/abstract/compare.dm b/code/modules/wiremod/components/abstract/compare.dm
index be5b49a19a71..44b5f5858ebb 100644
--- a/code/modules/wiremod/components/abstract/compare.dm
+++ b/code/modules/wiremod/components/abstract/compare.dm
@@ -16,6 +16,13 @@
/// The result from the output
var/datum/port/output/result
+/obj/item/circuit_component/compare/Destroy()
+ compare = null
+ true = null
+ false = null
+ result = null
+ . = ..()
+
/obj/item/circuit_component/compare/populate_ports()
populate_custom_ports()
compare = add_input_port("Вызов", PORT_TYPE_SIGNAL)
diff --git a/code/modules/wiremod/components/abstract/variable.dm b/code/modules/wiremod/components/abstract/variable.dm
index f3911baf2b09..8ba3d79dcf0f 100644
--- a/code/modules/wiremod/components/abstract/variable.dm
+++ b/code/modules/wiremod/components/abstract/variable.dm
@@ -15,6 +15,11 @@
var/should_listen = FALSE
+/obj/item/circuit_component/variable/Destroy()
+ variable_name = null
+ remove_current_variable()
+ . = ..()
+
/obj/item/circuit_component/variable/populate_options()
variable_name = add_option_port("Переменная", null)
diff --git a/code/modules/wiremod/components/action/equpiment_action.dm b/code/modules/wiremod/components/action/equpiment_action.dm
index d08a4737ba4a..16d62d80beff 100644
--- a/code/modules/wiremod/components/action/equpiment_action.dm
+++ b/code/modules/wiremod/components/action/equpiment_action.dm
@@ -69,6 +69,11 @@
/obj/item/circuit_component/equipment_action/Destroy()
QDEL_LIST_ASSOC_VAL(granted_to)
+ icon_options = null
+ button_name = null
+ user = null
+ signal = null
+ options_map = null
return ..()
/obj/item/circuit_component/equipment_action/populate_options()
diff --git a/code/modules/wiremod/components/action/laserpointer.dm b/code/modules/wiremod/components/action/laserpointer.dm
index 62f993be6336..d1c3a7ffc51b 100644
--- a/code/modules/wiremod/components/action/laserpointer.dm
+++ b/code/modules/wiremod/components/action/laserpointer.dm
@@ -20,6 +20,13 @@
var/laser_cooldown = 1 SECONDS
+/obj/item/circuit_component/laserpointer/Destroy()
+ target_input = null
+ image_pixel_x = null
+ image_pixel_y = null
+ lasercolour_option = null
+ . = ..()
+
/obj/item/circuit_component/laserpointer/get_ui_notices()
. = ..()
. += create_ui_notice("Максимальная дальность: [max_range] тайл[DECL_CREDIT(max_range)]", "orange", "info")
diff --git a/code/modules/wiremod/components/action/light.dm b/code/modules/wiremod/components/action/light.dm
index 1a573c27b655..15f0298f0b4a 100644
--- a/code/modules/wiremod/components/action/light.dm
+++ b/code/modules/wiremod/components/action/light.dm
@@ -23,6 +23,14 @@
var/min_lightness = 40
var/shell_light_color
+/obj/item/circuit_component/light/Destroy()
+ red = null
+ green = null
+ blue = null
+ brightness = null
+ on = null
+ . = ..()
+
/obj/item/circuit_component/light/get_ui_notices()
. = ..()
. += create_ui_notice("Максимальная яркость: [max_power]", "orange", "lightbulb")
diff --git a/code/modules/wiremod/components/action/mmi.dm b/code/modules/wiremod/components/action/mmi.dm
index 141e1efc7a9e..6d6b3e744502 100644
--- a/code/modules/wiremod/components/action/mmi.dm
+++ b/code/modules/wiremod/components/action/mmi.dm
@@ -59,6 +59,16 @@
/obj/item/circuit_component/mmi/Destroy()
remove_current_brain()
+ message = null
+ send = null
+ eject = null
+ north = null
+ east = null
+ south = null
+ west = null
+ attack = null
+ alt_attack = null
+ clicked_atom = null
return ..()
/obj/item/circuit_component/mmi/input_received(datum/port/input/port)
diff --git a/code/modules/wiremod/components/action/pathfind.dm b/code/modules/wiremod/components/action/pathfind.dm
index 172024d98e5c..10f882092265 100644
--- a/code/modules/wiremod/components/action/pathfind.dm
+++ b/code/modules/wiremod/components/action/pathfind.dm
@@ -30,6 +30,20 @@
var/max_range = 60
+/obj/item/circuit_component/pathfind/Destroy()
+ input_X = null
+ input_Y = null
+ id_card = null
+ output = null
+ finished = null
+ failed = null
+ reason_failed = null
+ LAZYCLEARLIST(path)
+ path = null
+ old_dest = null
+ next_turf = null
+ . = ..()
+
/obj/item/circuit_component/pathfind/get_ui_notices()
. = ..()
// Not necessary to show the same path cooldown, since it doesn't change much for the player
diff --git a/code/modules/wiremod/components/action/pull.dm b/code/modules/wiremod/components/action/pull.dm
index 42caa98b2992..d6d74bdd53c2 100644
--- a/code/modules/wiremod/components/action/pull.dm
+++ b/code/modules/wiremod/components/action/pull.dm
@@ -13,6 +13,10 @@
var/datum/port/input/target
circuit_flags = CIRCUIT_FLAG_INPUT_SIGNAL|CIRCUIT_FLAG_OUTPUT_SIGNAL
+/obj/item/circuit_component/pull/Destroy()
+ target = null
+ . = ..()
+
/obj/item/circuit_component/pull/populate_ports()
target = add_input_port("Цель", PORT_TYPE_ATOM)
diff --git a/code/modules/wiremod/components/action/radio.dm b/code/modules/wiremod/components/action/radio.dm
index 59eb66de1b82..ef9b8b7d1470 100644
--- a/code/modules/wiremod/components/action/radio.dm
+++ b/code/modules/wiremod/components/action/radio.dm
@@ -36,6 +36,16 @@
/// How long of a cooldown we have before we can send another signal.
var/signal_cooldown_time = 1 SECONDS
+/obj/item/circuit_component/radio/Destroy(force)
+ if(parent_shell)
+ unregister_shell(parent_shell)
+ SSradio.remove_object(src, current_freq)
+ radio_connection = null
+ public_options = null
+ freq = null
+ code = null
+ . = ..()
+
/obj/item/circuit_component/radio/examine(mob/user)
. = ..()
if(!signal_cooldown_time)
@@ -69,10 +79,6 @@
trigger_input = add_input_port("Вызов", PORT_TYPE_SIGNAL)
trigger_output = add_output_port("Вызвано", PORT_TYPE_SIGNAL)
-/obj/item/circuit_component/radio/Destroy(force)
- SSradio.remove_object(src, current_freq)
- return ..()
-
/obj/item/circuit_component/radio/pre_input_received(datum/port/input/port)
freq.set_value(sanitize_frequency(freq.value, TRUE))
diff --git a/code/modules/wiremod/components/action/soundemitter.dm b/code/modules/wiremod/components/action/soundemitter.dm
index bb82eafb1c0e..76e6b333401c 100644
--- a/code/modules/wiremod/components/action/soundemitter.dm
+++ b/code/modules/wiremod/components/action/soundemitter.dm
@@ -34,6 +34,14 @@
var/list/options_map
+/obj/item/circuit_component/soundemitter/Destroy()
+ options_map = null
+ sound_file = null
+ volume = null
+ backwards = null
+ frequency = null
+ . = ..()
+
/obj/item/circuit_component/soundemitter/get_ui_notices()
. = ..()
. += create_ui_notice("Перезарядка звука: [DisplayTimeText(sound_emitter_cooldown)]", "orange", "stopwatch")
diff --git a/code/modules/wiremod/components/action/speech.dm b/code/modules/wiremod/components/action/speech.dm
index bbc730442804..71f9ceac1546 100644
--- a/code/modules/wiremod/components/action/speech.dm
+++ b/code/modules/wiremod/components/action/speech.dm
@@ -15,6 +15,10 @@
/// The cooldown for this component of how often it can send speech messages.
var/speech_cooldown = 1 SECONDS
+/obj/item/circuit_component/speech/Destroy()
+ message = null
+ . = ..()
+
/obj/item/circuit_component/speech/get_ui_notices()
. = ..()
. += create_ui_notice("Перезарядка произношения: [DisplayTimeText(speech_cooldown)]", "orange", "stopwatch")
diff --git a/code/modules/wiremod/components/atom/direction.dm b/code/modules/wiremod/components/atom/direction.dm
index 8f07f9d879ac..d21b8eddd515 100644
--- a/code/modules/wiremod/components/atom/direction.dm
+++ b/code/modules/wiremod/components/atom/direction.dm
@@ -26,6 +26,16 @@
/// Maximum range for a valid direction to be returned
var/max_range = 7
+/obj/item/circuit_component/direction/Destroy()
+ input_port = null
+ output = null
+ distance = null
+ north = null
+ south = null
+ east = null
+ west = null
+ . = ..()
+
/obj/item/circuit_component/direction/get_ui_notices()
. = ..()
. += create_ui_notice("Максимальная дальность: [max_range] тайл[DECL_CREDIT(max_range)]", "orange", "info")
diff --git a/code/modules/wiremod/components/atom/gps.dm b/code/modules/wiremod/components/atom/gps.dm
index 349b176a5189..7abfb31c7176 100644
--- a/code/modules/wiremod/components/atom/gps.dm
+++ b/code/modules/wiremod/components/atom/gps.dm
@@ -15,6 +15,12 @@
circuit_flags = CIRCUIT_FLAG_INPUT_SIGNAL|CIRCUIT_FLAG_OUTPUT_SIGNAL
+/obj/item/circuit_component/gps/Destroy()
+ x_pos = null
+ y_pos = null
+ z_pos = null
+ . = ..()
+
/obj/item/circuit_component/gps/populate_ports()
x_pos = add_output_port("X", PORT_TYPE_NUMBER)
y_pos = add_output_port("Y", PORT_TYPE_NUMBER)
diff --git a/code/modules/wiremod/components/atom/health.dm b/code/modules/wiremod/components/atom/health.dm
index 890bd3f812ee..5d232c1e3551 100644
--- a/code/modules/wiremod/components/atom/health.dm
+++ b/code/modules/wiremod/components/atom/health.dm
@@ -26,6 +26,15 @@
var/max_range = 5
+/obj/item/circuit_component/health/Destroy()
+ input_port = null
+ brute = null
+ burn = null
+ toxin = null
+ oxy = null
+ health = null
+ . = ..()
+
/obj/item/circuit_component/health/get_ui_notices()
. = ..()
. += create_ui_notice("Максимальная дальность: [max_range] тайл[DECL_CREDIT(max_range)]", "orange", "info")
diff --git a/code/modules/wiremod/components/atom/health_state.dm b/code/modules/wiremod/components/atom/health_state.dm
index 593e813909be..35ad4bd40013 100644
--- a/code/modules/wiremod/components/atom/health_state.dm
+++ b/code/modules/wiremod/components/atom/health_state.dm
@@ -22,6 +22,11 @@
var/max_range = 5
+/obj/item/circuit_component/compare/health_state/Destroy()
+ input_port = null
+ state_option = null
+ . = ..()
+
/obj/item/circuit_component/compare/health_state/get_ui_notices()
. = ..()
. += create_ui_notice("Максимальная дальность: [max_range] тайл[DECL_CREDIT(max_range)]", "orange", "info")
diff --git a/code/modules/wiremod/components/atom/hear.dm b/code/modules/wiremod/components/atom/hear.dm
index 0f708feb6b25..6fbefb487458 100644
--- a/code/modules/wiremod/components/atom/hear.dm
+++ b/code/modules/wiremod/components/atom/hear.dm
@@ -20,6 +20,14 @@
/// The trigger sent when this event occurs
var/datum/port/output/trigger_port
+/obj/item/circuit_component/hear/Destroy()
+ on = null
+ message_port = null
+ speaker_name = null
+ speaker_port = null
+ trigger_port = null
+ . = ..()
+
/obj/item/circuit_component/hear/populate_ports()
on = add_input_port("Вкл", PORT_TYPE_NUMBER, default = 1)
message_port = add_output_port("Сообщение", PORT_TYPE_STRING)
diff --git a/code/modules/wiremod/components/atom/pinpointer.dm b/code/modules/wiremod/components/atom/pinpointer.dm
index 76505e5d541c..c2e670a7340a 100644
--- a/code/modules/wiremod/components/atom/pinpointer.dm
+++ b/code/modules/wiremod/components/atom/pinpointer.dm
@@ -19,6 +19,14 @@
circuit_flags = CIRCUIT_FLAG_INPUT_SIGNAL|CIRCUIT_FLAG_OUTPUT_SIGNAL
+/obj/item/circuit_component/pinpointer/Destroy()
+ target = null
+ x_pos = null
+ y_pos = null
+ z_pos = null
+ on_error = null
+ . = ..()
+
/obj/item/circuit_component/pinpointer/get_ui_notices()
. = ..()
. += create_ui_notice("Максимальная дальность: [max_range] тайл[DECL_CREDIT(max_range)]", "orange", "info")
diff --git a/code/modules/wiremod/components/atom/reagentscanner.dm b/code/modules/wiremod/components/atom/reagentscanner.dm
index 281e2457a308..8a8938e5a5a0 100644
--- a/code/modules/wiremod/components/atom/reagentscanner.dm
+++ b/code/modules/wiremod/components/atom/reagentscanner.dm
@@ -17,6 +17,11 @@
var/max_range = 5
+/obj/item/circuit_component/reagentscanner/Destroy()
+ input_port = null
+ result = null
+ . = ..()
+
/obj/item/circuit_component/reagentscanner/get_ui_notices()
. = ..()
. += create_ui_notice("Максимальная дальность: [max_range] тайл[DECL_CREDIT(max_range)]", "orange", "info")
diff --git a/code/modules/wiremod/components/atom/remotecam.dm b/code/modules/wiremod/components/atom/remotecam.dm
index fc6dda8c9454..d5b940c4631d 100644
--- a/code/modules/wiremod/components/atom/remotecam.dm
+++ b/code/modules/wiremod/components/atom/remotecam.dm
@@ -53,6 +53,16 @@
/// Used to store the last string used for the camera network
var/current_camera_network = ""
+/obj/item/circuit_component/remotecam/Destroy()
+ stop_process()
+ remove_camera()
+ shell_parent = null
+ start = null
+ stop = null
+ camera_range = null
+ network = null
+ return ..()
+
/obj/item/circuit_component/remotecam/get_ui_notices()
. = ..()
if(camera_range_settable)
@@ -85,12 +95,6 @@
remove_camera()
shell_parent = null
-/obj/item/circuit_component/remotecam/Destroy()
- stop_process()
- remove_camera()
- shell_parent = null
- return ..()
-
/obj/item/circuit_component/remotecam/input_received(datum/port/input/port)
if(!shell_parent || !shell_camera)
return
diff --git a/code/modules/wiremod/components/atom/self.dm b/code/modules/wiremod/components/atom/self.dm
index cb8ed633e304..71360bf74506 100644
--- a/code/modules/wiremod/components/atom/self.dm
+++ b/code/modules/wiremod/components/atom/self.dm
@@ -15,6 +15,11 @@
/// The signal sent when the status is updated.
var/datum/port/output/shell_received
+/obj/item/circuit_component/self/Destroy()
+ output = null
+ shell_received = null
+ . = ..()
+
/obj/item/circuit_component/self/populate_ports()
output = add_output_port("Оболочка", PORT_TYPE_ATOM)
shell_received = add_output_port("Вызвано", PORT_TYPE_SIGNAL)
diff --git a/code/modules/wiremod/components/atom/species.dm b/code/modules/wiremod/components/atom/species.dm
index c8b9ed6c1e28..577ecbd492f2 100644
--- a/code/modules/wiremod/components/atom/species.dm
+++ b/code/modules/wiremod/components/atom/species.dm
@@ -16,6 +16,11 @@
circuit_flags = CIRCUIT_FLAG_INPUT_SIGNAL|CIRCUIT_FLAG_OUTPUT_SIGNAL
+/obj/item/circuit_component/species/Destroy()
+ input_port = null
+ output = null
+ . = ..()
+
/obj/item/circuit_component/species/populate_ports()
input_port = add_input_port("Организм", PORT_TYPE_ATOM)
diff --git a/code/modules/wiremod/components/bci/hud/bar_overlay.dm b/code/modules/wiremod/components/bci/hud/bar_overlay.dm
index 22ba06f6177d..8472eff23fdc 100644
--- a/code/modules/wiremod/components/bci/hud/bar_overlay.dm
+++ b/code/modules/wiremod/components/bci/hud/bar_overlay.dm
@@ -15,6 +15,10 @@
var/datum/port/input/bar_number
+/obj/item/circuit_component/object_overlay/bar/Destroy()
+ bar_number = null
+ . = ..()
+
/obj/item/circuit_component/object_overlay/bar/populate_ports()
. = ..()
bar_number = add_input_port("Число", PORT_TYPE_NUMBER)
diff --git a/code/modules/wiremod/components/bci/hud/counter_overlay.dm b/code/modules/wiremod/components/bci/hud/counter_overlay.dm
index ec5fc9c2d43c..52138933a602 100644
--- a/code/modules/wiremod/components/bci/hud/counter_overlay.dm
+++ b/code/modules/wiremod/components/bci/hud/counter_overlay.dm
@@ -24,6 +24,17 @@
var/list/numbers
var/datum/weakref/counter_appearance
+/obj/item/circuit_component/counter_overlay/Destroy(force)
+ if(bci)
+ unregister_shell(bci)
+ counter_number = null
+ signal_update = null
+ image_pixel_x = null
+ image_pixel_y = null
+ QDEL_LIST(numbers)
+ QDEL_NULL(counter_appearance)
+ . = ..()
+
/obj/item/circuit_component/counter_overlay/populate_ports()
counter_number = add_input_port("Число", PORT_TYPE_NUMBER)
signal_update = add_input_port("Обновление", PORT_TYPE_SIGNAL)
@@ -117,9 +128,3 @@
QDEL_LIST(numbers)
QDEL_NULL(counter_appearance)
-
-/obj/item/circuit_component/counter_overlay/Destroy(force)
- QDEL_LIST(numbers)
- QDEL_NULL(counter_appearance)
-
- return ..()
diff --git a/code/modules/wiremod/components/bci/hud/object_overlay.dm b/code/modules/wiremod/components/bci/hud/object_overlay.dm
index c6e80769b75a..9a0ece54004c 100644
--- a/code/modules/wiremod/components/bci/hud/object_overlay.dm
+++ b/code/modules/wiremod/components/bci/hud/object_overlay.dm
@@ -51,6 +51,21 @@
var/list/options_map
+/obj/item/circuit_component/object_overlay/Destroy()
+ QDEL_LIST_ASSOC_VAL(active_overlays)
+ if(bci)
+ unregister_shell(bci)
+ target = null
+ signal_on = null
+ signal_off = null
+ signal_off_all = null
+ image_pixel_x = null
+ image_pixel_y = null
+ image_rotation = null
+ object_overlay_options = null
+ LAZYCLEARLIST(options_map)
+ return ..()
+
/obj/item/circuit_component/object_overlay/populate_ports()
target = add_input_port("Цель", PORT_TYPE_ATOM)
@@ -63,9 +78,6 @@
image_pixel_y = add_input_port("Y", PORT_TYPE_NUMBER)
image_rotation = add_input_port("Разворот", PORT_TYPE_NUMBER)
-/obj/item/circuit_component/object_overlay/Destroy()
- QDEL_LIST_ASSOC_VAL(active_overlays)
- return ..()
/obj/item/circuit_component/object_overlay/populate_options()
var/static/component_options = list(
diff --git a/code/modules/wiremod/components/bci/hud/target_intercept.dm b/code/modules/wiremod/components/bci/hud/target_intercept.dm
index 243fcaae098c..a073a6626fbe 100644
--- a/code/modules/wiremod/components/bci/hud/target_intercept.dm
+++ b/code/modules/wiremod/components/bci/hud/target_intercept.dm
@@ -18,6 +18,12 @@
var/obj/item/organ/internal/cyberimp/brain/bci/bci
var/intercept_cooldown = 1 SECONDS
+/obj/item/circuit_component/target_intercept/Destroy()
+ if(bci)
+ unregister_shell(bci)
+ clicked_atom = null
+ . = ..()
+
/obj/item/circuit_component/target_intercept/populate_ports()
trigger_input = add_input_port("Вызов", PORT_TYPE_SIGNAL)
trigger_output = add_output_port("Вызвано", PORT_TYPE_SIGNAL)
diff --git a/code/modules/wiremod/components/bci/install_detector.dm b/code/modules/wiremod/components/bci/install_detector.dm
index 1c36068a1e51..bbcd5e2eaacc 100644
--- a/code/modules/wiremod/components/bci/install_detector.dm
+++ b/code/modules/wiremod/components/bci/install_detector.dm
@@ -18,6 +18,14 @@
var/obj/item/organ/internal/cyberimp/brain/bci/bci
+/obj/item/circuit_component/install_detector/Destroy()
+ if(bci)
+ unregister_shell(bci)
+ implanted = null
+ removed = null
+ current_state = null
+ . = ..()
+
/obj/item/circuit_component/install_detector/populate_ports()
. = ..()
current_state = add_output_port("Состояние", PORT_TYPE_NUMBER)
diff --git a/code/modules/wiremod/components/bci/reagent_injector.dm b/code/modules/wiremod/components/bci/reagent_injector.dm
index a3554c414749..324b2ed96860 100644
--- a/code/modules/wiremod/components/bci/reagent_injector.dm
+++ b/code/modules/wiremod/components/bci/reagent_injector.dm
@@ -24,6 +24,14 @@
container_type = OPENCONTAINER
create_reagents(15) //This is mostly used in the case of a BCI still having reagents in it when the component is removed.
+/obj/item/circuit_component/reagent_injector/Destroy()
+ if(bci)
+ unregister_shell(bci)
+ inject = null
+ transfer_amounts = null
+ injected = null
+ . = ..()
+
/obj/item/circuit_component/reagent_injector/populate_ports()
. = ..()
inject = add_input_port("Вызов", PORT_TYPE_SIGNAL, trigger = PROC_REF(trigger_inject))
diff --git a/code/modules/wiremod/components/bci/thought_listener.dm b/code/modules/wiremod/components/bci/thought_listener.dm
index 11a483295f3d..9eb425652676 100644
--- a/code/modules/wiremod/components/bci/thought_listener.dm
+++ b/code/modules/wiremod/components/bci/thought_listener.dm
@@ -24,6 +24,16 @@
var/obj/item/organ/internal/cyberimp/brain/bci/bci
var/ready = TRUE
+/obj/item/circuit_component/thought_listener/Destroy()
+ if(bci)
+ unregister_shell(bci)
+ input_name = null
+ input_desc = null
+
+ output = null
+ failure = null
+ . = ..()
+
/obj/item/circuit_component/thought_listener/populate_ports()
input_name = add_input_port("Название", PORT_TYPE_STRING)
input_desc = add_input_port("Описание", PORT_TYPE_STRING)
diff --git a/code/modules/wiremod/components/bci/vox.dm b/code/modules/wiremod/components/bci/vox.dm
index 520ae6258edc..97d4e2b3b3a0 100644
--- a/code/modules/wiremod/components/bci/vox.dm
+++ b/code/modules/wiremod/components/bci/vox.dm
@@ -22,6 +22,13 @@
var/obj/item/organ/internal/cyberimp/brain/bci/bci
+/obj/item/circuit_component/vox/Destroy()
+ if(bci)
+ unregister_shell(bci)
+ type_option = null
+ word_list = null
+ . = ..()
+
/obj/item/circuit_component/vox/populate_options()
type_option = add_option_port("тип ВОКС-а", list(PORT_TYPE_LIST(PORT_TYPE_STRING), PORT_TYPE_STRING))
diff --git a/code/modules/wiremod/components/id/access_checker.dm b/code/modules/wiremod/components/id/access_checker.dm
index 2dcb31c389cf..33824aadc646 100644
--- a/code/modules/wiremod/components/id/access_checker.dm
+++ b/code/modules/wiremod/components/id/access_checker.dm
@@ -16,6 +16,12 @@
"id-card" = "access",
)
+/obj/item/circuit_component/compare/access/Destroy()
+ subject_accesses = null
+ required_accesses = null
+ check_any = null
+ . = ..()
+
/obj/item/circuit_component/compare/access/get_ui_notices()
. = ..()
. += create_ui_notice("Когда поле \"Любой\" истинно, возвращает истину если поле \"ID-карта\" содержит любой доступ из поля \"Доступ\".", "orange", "info")
diff --git a/code/modules/wiremod/components/id/access_reader.dm b/code/modules/wiremod/components/id/access_reader.dm
index 18d733732e2d..2575aeb5224f 100644
--- a/code/modules/wiremod/components/id/access_reader.dm
+++ b/code/modules/wiremod/components/id/access_reader.dm
@@ -13,6 +13,11 @@
var/max_range = 1
+/obj/item/circuit_component/id_access_reader/Destroy()
+ target = null
+ access_port = null
+ . = ..()
+
/obj/item/circuit_component/id_access_reader/get_ui_notices()
. = ..()
. += create_ui_notice("Максимальная дальность: [max_range] тайл[DECL_CREDIT(max_range)].", "orange", "info")
diff --git a/code/modules/wiremod/components/id/getter.dm b/code/modules/wiremod/components/id/getter.dm
index 9aeaed0b3c79..678dcbb4c6fb 100644
--- a/code/modules/wiremod/components/id/getter.dm
+++ b/code/modules/wiremod/components/id/getter.dm
@@ -13,6 +13,11 @@
var/max_range = 1
+/obj/item/circuit_component/id_getter/Destroy()
+ target = null
+ id_port = null
+ . = ..()
+
/obj/item/circuit_component/id_getter/get_ui_notices()
. = ..()
. += create_ui_notice("Максимальная дальность: [max_range] тайл[DECL_CREDIT(max_range)].", "orange", "info")
diff --git a/code/modules/wiremod/components/id/info_reader.dm b/code/modules/wiremod/components/id/info_reader.dm
index d8a4efcaadc8..8dc4b33314ee 100644
--- a/code/modules/wiremod/components/id/info_reader.dm
+++ b/code/modules/wiremod/components/id/info_reader.dm
@@ -19,6 +19,13 @@
var/max_range = 1
+/obj/item/circuit_component/id_info_reader/Destroy()
+ target = null
+ name_port = null
+ rank_port = null
+ age_port = null
+ . = ..()
+
/obj/item/circuit_component/id_info_reader/get_ui_notices()
. = ..()
. += create_ui_notice("Максимальная дальность: [max_range] тайл[DECL_CREDIT(max_range)].", "orange", "info")
diff --git a/code/modules/wiremod/components/list/assoc_list_remove.dm b/code/modules/wiremod/components/list/assoc_list_remove.dm
index 2c1555754809..b2c32106de92 100644
--- a/code/modules/wiremod/components/list/assoc_list_remove.dm
+++ b/code/modules/wiremod/components/list/assoc_list_remove.dm
@@ -13,6 +13,10 @@
circuit_flags = CIRCUIT_FLAG_INPUT_SIGNAL|CIRCUIT_FLAG_OUTPUT_SIGNAL
+/obj/item/circuit_component/variable/assoc_list/list_remove/Destroy()
+ to_remove = null
+ . = ..()
+
/obj/item/circuit_component/variable/assoc_list/list_remove/populate_ports()
to_remove = add_input_port("Удалить", PORT_TYPE_STRING)
diff --git a/code/modules/wiremod/components/list/assoc_list_set.dm b/code/modules/wiremod/components/list/assoc_list_set.dm
index 9be70f9451a3..e41bf16c9d9e 100644
--- a/code/modules/wiremod/components/list/assoc_list_set.dm
+++ b/code/modules/wiremod/components/list/assoc_list_set.dm
@@ -19,6 +19,12 @@
circuit_flags = CIRCUIT_FLAG_INPUT_SIGNAL|CIRCUIT_FLAG_OUTPUT_SIGNAL
+/obj/item/circuit_component/variable/assoc_list/list_set/Destroy()
+ key = null
+ value = null
+ failed = null
+ . = ..()
+
/obj/item/circuit_component/variable/assoc_list/list_set/get_ui_notices()
. = ..()
. += create_ui_notice("Максимальный размер списка: [max_list_size]", "orange", "sitemap")
diff --git a/code/modules/wiremod/components/list/assoc_literal.dm b/code/modules/wiremod/components/list/assoc_literal.dm
index 0133f7614a2e..79663348a235 100644
--- a/code/modules/wiremod/components/list/assoc_literal.dm
+++ b/code/modules/wiremod/components/list/assoc_literal.dm
@@ -27,6 +27,13 @@
var/max_list_count = 100
+/obj/item/circuit_component/assoc_literal/Destroy()
+ list_options = null
+ LAZYCLEARLIST(entry_ports)
+ LAZYCLEARLIST(key_ports)
+ list_output = null
+ . = ..()
+
/obj/item/circuit_component/assoc_literal/pre_input_received(datum/port/input/port)
if(port != list_options)
return
diff --git a/code/modules/wiremod/components/list/concat.dm b/code/modules/wiremod/components/list/concat.dm
index 321eb0b47a0d..a76fb46dabb9 100644
--- a/code/modules/wiremod/components/list/concat.dm
+++ b/code/modules/wiremod/components/list/concat.dm
@@ -18,6 +18,12 @@
var/datum/port/output/output
circuit_flags = CIRCUIT_FLAG_INPUT_SIGNAL|CIRCUIT_FLAG_OUTPUT_SIGNAL
+/obj/item/circuit_component/concat_list/Destroy()
+ list_port = null
+ separator = null
+ output = null
+ . = ..()
+
/obj/item/circuit_component/concat_list/populate_ports()
list_port = add_input_port("Ввод", PORT_TYPE_LIST(PORT_TYPE_ANY))
separator = add_input_port("Разделитель", PORT_TYPE_STRING)
diff --git a/code/modules/wiremod/components/list/filter.dm b/code/modules/wiremod/components/list/filter.dm
index 79ad3a6f6672..ab2175841124 100644
--- a/code/modules/wiremod/components/list/filter.dm
+++ b/code/modules/wiremod/components/list/filter.dm
@@ -37,6 +37,18 @@
/// The limit of iterations before it breaks. Used to prevent from someone iterating a massive list constantly
var/limit = 300
+/obj/item/circuit_component/filter_list/Destroy()
+ list_options = null
+ accept_entry = null
+ list_to_filter = null
+ element = null
+ current_index = null
+ on_next_index = null
+ finished_list = null
+ on_finished = null
+ on_failed = null
+ . = ..()
+
/obj/item/circuit_component/filter_list/populate_options()
list_options = add_option_port("Тип", GLOB.wiremod_basic_types)
diff --git a/code/modules/wiremod/components/list/foreach.dm b/code/modules/wiremod/components/list/foreach.dm
index 0542051ad821..5da1dda87dd3 100644
--- a/code/modules/wiremod/components/list/foreach.dm
+++ b/code/modules/wiremod/components/list/foreach.dm
@@ -29,6 +29,16 @@
var/current_actual_index = 1
+/obj/item/circuit_component/foreach/Destroy()
+ list_options = null
+ list_to_iterate = null
+ next_index = null
+ reset_index = null
+ element = null
+ current_index = null
+ on_next_index = null
+ on_finished = null
+ . = ..()
/obj/item/circuit_component/foreach/populate_options()
list_options = add_option_port("Тип", GLOB.wiremod_basic_types)
diff --git a/code/modules/wiremod/components/list/format.dm b/code/modules/wiremod/components/list/format.dm
index 4d4aee0b041f..c67838cbd585 100644
--- a/code/modules/wiremod/components/list/format.dm
+++ b/code/modules/wiremod/components/list/format.dm
@@ -29,6 +29,14 @@
. = ..()
param_regex = list_param_regex
+/obj/item/circuit_component/format/Destroy()
+ param_regex?.context = null
+ param_regex = null
+ format_port = null
+ param_list_port = null
+ output = null
+ . = ..()
+
/obj/item/circuit_component/format/proc/make_params_port()
param_list_port = add_input_port("Параметры", PORT_TYPE_LIST(PORT_TYPE_ANY))
@@ -88,6 +96,7 @@
/regex/format_component
var/obj/item/circuit_component/format/context
+
/**
* Replace %n with the actual param, as a string.
* Arguments:
diff --git a/code/modules/wiremod/components/list/index.dm b/code/modules/wiremod/components/list/index.dm
index fd1d8386a69c..815fa5805a1b 100644
--- a/code/modules/wiremod/components/list/index.dm
+++ b/code/modules/wiremod/components/list/index.dm
@@ -21,6 +21,13 @@
var/index_type = PORT_TYPE_NUMBER
+/obj/item/circuit_component/index/Destroy()
+ list_options = null
+ list_port = null
+ index_port = null
+ output = null
+ . = ..()
+
/obj/item/circuit_component/index/populate_options()
list_options = add_option_port("Тип", GLOB.wiremod_basic_types)
diff --git a/code/modules/wiremod/components/list/list_add.dm b/code/modules/wiremod/components/list/list_add.dm
index b218d616987e..922a7bd69ba7 100644
--- a/code/modules/wiremod/components/list/list_add.dm
+++ b/code/modules/wiremod/components/list/list_add.dm
@@ -19,6 +19,12 @@
circuit_flags = CIRCUIT_FLAG_INPUT_SIGNAL|CIRCUIT_FLAG_OUTPUT_SIGNAL
+/obj/item/circuit_component/variable/list/listadd/Destroy()
+ to_add = null
+ allow_duplicate = null
+ failed = null
+ . = ..()
+
/obj/item/circuit_component/variable/list/listadd/get_ui_notices()
. = ..()
. += create_ui_notice("Максимальный размер списка: [max_list_size]", "orange", "sitemap")
diff --git a/code/modules/wiremod/components/list/list_find.dm b/code/modules/wiremod/components/list/list_find.dm
index 2949a890e1a8..6907db418b82 100644
--- a/code/modules/wiremod/components/list/list_find.dm
+++ b/code/modules/wiremod/components/list/list_find.dm
@@ -28,6 +28,16 @@
circuit_flags = CIRCUIT_FLAG_INPUT_SIGNAL
+/obj/item/circuit_component/listin/Destroy()
+ list_type = null
+ list_to_check = null
+ to_check = null
+ found = null
+ not_found = null
+ result = null
+ index = null
+ . = ..()
+
/obj/item/circuit_component/listin/populate_options()
list_type = add_option_port("Тип", GLOB.wiremod_basic_types)
diff --git a/code/modules/wiremod/components/list/list_literal.dm b/code/modules/wiremod/components/list/list_literal.dm
index 60b139bee491..2a6b046c142b 100644
--- a/code/modules/wiremod/components/list/list_literal.dm
+++ b/code/modules/wiremod/components/list/list_literal.dm
@@ -24,6 +24,12 @@
var/max_list_count = 100
+/obj/item/circuit_component/list_literal/Destroy()
+ list_options = null
+ LAZYCLEARLIST(entry_ports)
+ list_output = null
+ . = ..()
+
/obj/item/circuit_component/list_literal/populate_options()
list_options = add_option_port("Тип", GLOB.wiremod_basic_types)
diff --git a/code/modules/wiremod/components/list/list_pick.dm b/code/modules/wiremod/components/list/list_pick.dm
index 60fa2690b37b..1b3f2d25daa4 100644
--- a/code/modules/wiremod/components/list/list_pick.dm
+++ b/code/modules/wiremod/components/list/list_pick.dm
@@ -28,6 +28,16 @@
circuit_flags = CIRCUIT_FLAG_INPUT_SIGNAL
+/obj/item/circuit_component/list_pick/Destroy()
+ list_options = null
+ input_list = null
+ user = null
+ input_name = null
+ output = null
+ success = null
+ failure = null
+ . = ..()
+
/obj/item/circuit_component/list_pick/proc/make_list_port()
input_list = add_input_port("Список", PORT_TYPE_LIST(PORT_TYPE_STRING))
diff --git a/code/modules/wiremod/components/list/list_remove.dm b/code/modules/wiremod/components/list/list_remove.dm
index 4a63b3dfdf17..4b634bd74df6 100644
--- a/code/modules/wiremod/components/list/list_remove.dm
+++ b/code/modules/wiremod/components/list/list_remove.dm
@@ -13,6 +13,10 @@
circuit_flags = CIRCUIT_FLAG_INPUT_SIGNAL|CIRCUIT_FLAG_OUTPUT_SIGNAL
+/obj/item/circuit_component/variable/list/listremove/Destroy()
+ to_remove = null
+ . = ..()
+
/obj/item/circuit_component/variable/list/listremove/populate_ports()
to_remove = add_input_port("Удалить", PORT_TYPE_ANY)
diff --git a/code/modules/wiremod/components/list/split.dm b/code/modules/wiremod/components/list/split.dm
index 701861405dd5..e84da3a78ace 100644
--- a/code/modules/wiremod/components/list/split.dm
+++ b/code/modules/wiremod/components/list/split.dm
@@ -19,6 +19,12 @@
circuit_flags = CIRCUIT_FLAG_INPUT_SIGNAL|CIRCUIT_FLAG_OUTPUT_SIGNAL
+/obj/item/circuit_component/split/Destroy()
+ input_port = null
+ separator = null
+ output = null
+ . = ..()
+
/obj/item/circuit_component/split/populate_ports()
input_port = add_input_port("Ввод", PORT_TYPE_STRING)
separator = add_input_port("Разделитель", PORT_TYPE_STRING)
diff --git a/code/modules/wiremod/components/math/arctan2.dm b/code/modules/wiremod/components/math/arctan2.dm
index d6b90697d318..efe2b61016c3 100644
--- a/code/modules/wiremod/components/math/arctan2.dm
+++ b/code/modules/wiremod/components/math/arctan2.dm
@@ -17,6 +17,12 @@
circuit_flags = CIRCUIT_FLAG_INPUT_SIGNAL|CIRCUIT_FLAG_OUTPUT_SIGNAL
+/obj/item/circuit_component/arctan2/Destroy()
+ input_port_x = null
+ input_port_y = null
+ output = null
+ . = ..()
+
/obj/item/circuit_component/arctan2/populate_ports()
input_port_x = add_input_port("X", PORT_TYPE_NUMBER)
input_port_y = add_input_port("Y", PORT_TYPE_NUMBER)
diff --git a/code/modules/wiremod/components/math/arithmetic.dm b/code/modules/wiremod/components/math/arithmetic.dm
index aadd290a3262..cb2a05a4397a 100644
--- a/code/modules/wiremod/components/math/arithmetic.dm
+++ b/code/modules/wiremod/components/math/arithmetic.dm
@@ -30,6 +30,12 @@
"minus" = "remove",
)
+/obj/item/circuit_component/arithmetic/Destroy()
+ arithmetic_option = null
+ output = null
+ LAZYCLEARLIST(arithmetic_ports)
+ . = ..()
+
/obj/item/circuit_component/arithmetic/populate_options()
var/static/component_options = list(
COMP_ARITHMETIC_ADD,
diff --git a/code/modules/wiremod/components/math/binary_conversion.dm b/code/modules/wiremod/components/math/binary_conversion.dm
index ab6bd5be8135..c20b0754d452 100644
--- a/code/modules/wiremod/components/math/binary_conversion.dm
+++ b/code/modules/wiremod/components/math/binary_conversion.dm
@@ -21,6 +21,10 @@
"minus" = "remove",
)
+/obj/item/circuit_component/binary_conversion/Destroy()
+ number = null
+ LAZYCLEARLIST(bit_array)
+ . = ..()
/obj/item/circuit_component/binary_conversion/populate_ports()
AddComponent(/datum/component/circuit_component_add_port, \
diff --git a/code/modules/wiremod/components/math/comparison.dm b/code/modules/wiremod/components/math/comparison.dm
index 661c52670073..fe5b243999b3 100644
--- a/code/modules/wiremod/components/math/comparison.dm
+++ b/code/modules/wiremod/components/math/comparison.dm
@@ -17,6 +17,12 @@
var/current_type = PORT_TYPE_ANY
+/obj/item/circuit_component/compare/comparison/Destroy()
+ comparison_option = null
+ first_port = null
+ second_port = null
+ . = ..()
+
/obj/item/circuit_component/compare/comparison/populate_options()
var/static/component_options = list(
COMP_COMPARISON_EQUAL,
diff --git a/code/modules/wiremod/components/math/decimal_conversion.dm b/code/modules/wiremod/components/math/decimal_conversion.dm
index f96d58ed9cc5..6733dca25508 100644
--- a/code/modules/wiremod/components/math/decimal_conversion.dm
+++ b/code/modules/wiremod/components/math/decimal_conversion.dm
@@ -21,6 +21,11 @@
"minus" = "remove",
)
+/obj/item/circuit_component/decimal_conversion/Destroy()
+ number = null
+ LAZYCLEARLIST(bit_array)
+ . = ..()
+
/obj/item/circuit_component/decimal_conversion/populate_ports()
AddComponent(/datum/component/circuit_component_add_port, \
port_list = bit_array, \
diff --git a/code/modules/wiremod/components/math/length.dm b/code/modules/wiremod/components/math/length.dm
index aaa1df8e3510..1496af17244d 100644
--- a/code/modules/wiremod/components/math/length.dm
+++ b/code/modules/wiremod/components/math/length.dm
@@ -15,6 +15,11 @@
var/datum/port/output/output
circuit_flags = CIRCUIT_FLAG_INPUT_SIGNAL|CIRCUIT_FLAG_OUTPUT_SIGNAL
+/obj/item/circuit_component/length/Destroy()
+ input_port = null
+ output = null
+ . = ..()
+
/obj/item/circuit_component/length/populate_ports()
input_port = add_input_port("Ввод", PORT_TYPE_ANY)
diff --git a/code/modules/wiremod/components/math/logic.dm b/code/modules/wiremod/components/math/logic.dm
index 0337fd00cc5a..59fc076c1293 100644
--- a/code/modules/wiremod/components/math/logic.dm
+++ b/code/modules/wiremod/components/math/logic.dm
@@ -22,6 +22,11 @@
"minus" = "remove",
)
+/obj/item/circuit_component/compare/logic/Destroy()
+ logic_options = null
+ LAZYCLEARLIST(comparison_ports)
+ . = ..()
+
/obj/item/circuit_component/compare/logic/populate_options()
var/static/component_options = list(
COMP_LOGIC_AND,
diff --git a/code/modules/wiremod/components/math/not.dm b/code/modules/wiremod/components/math/not.dm
index 78667f23d5e4..4ff0f83f02c0 100644
--- a/code/modules/wiremod/components/math/not.dm
+++ b/code/modules/wiremod/components/math/not.dm
@@ -15,6 +15,11 @@
var/datum/port/output/result
circuit_flags = CIRCUIT_FLAG_INPUT_SIGNAL|CIRCUIT_FLAG_OUTPUT_SIGNAL
+/obj/item/circuit_component/not/Destroy()
+ input_port = null
+ result = null
+ . = ..()
+
/obj/item/circuit_component/not/populate_ports()
input_port = add_input_port("Ввод", PORT_TYPE_ANY)
diff --git a/code/modules/wiremod/components/math/random.dm b/code/modules/wiremod/components/math/random.dm
index 8a7257a0931c..05150a6d03f5 100644
--- a/code/modules/wiremod/components/math/random.dm
+++ b/code/modules/wiremod/components/math/random.dm
@@ -18,6 +18,13 @@
/// The result from the output
var/datum/port/output/output
+/obj/item/circuit_component/random/Destroy()
+ minimum = null
+ maximum = null
+ output = null
+ . = ..()
+
+
/obj/item/circuit_component/random/populate_ports()
minimum = add_input_port("Минимум", PORT_TYPE_NUMBER, trigger = null)
maximum = add_input_port("Максимум", PORT_TYPE_NUMBER, trigger = null)
diff --git a/code/modules/wiremod/components/math/toggle.dm b/code/modules/wiremod/components/math/toggle.dm
index 92571d8769ff..6fa611a86eb3 100644
--- a/code/modules/wiremod/components/math/toggle.dm
+++ b/code/modules/wiremod/components/math/toggle.dm
@@ -16,6 +16,11 @@
var/toggle_state = FALSE
+/obj/item/circuit_component/compare/toggle/Destroy()
+ toggle_set = null
+ toggle_and_compare = null
+ . = ..()
+
/obj/item/circuit_component/compare/toggle/populate_custom_ports()
toggle_set = add_input_port("Целевое состояние", PORT_TYPE_NUMBER)
toggle_and_compare = add_input_port("Переключить и сравнить", PORT_TYPE_SIGNAL)
diff --git a/code/modules/wiremod/components/math/trigonometry.dm b/code/modules/wiremod/components/math/trigonometry.dm
index 2acd17e9a2fc..6c228f203bcd 100644
--- a/code/modules/wiremod/components/math/trigonometry.dm
+++ b/code/modules/wiremod/components/math/trigonometry.dm
@@ -27,6 +27,12 @@
circuit_flags = CIRCUIT_FLAG_INPUT_SIGNAL|CIRCUIT_FLAG_OUTPUT_SIGNAL
+/obj/item/circuit_component/trigonometry/Destroy()
+ trigonometric_function = null
+ input_port = null
+ output = null
+ . = ..()
+
/obj/item/circuit_component/trigonometry/populate_options()
var/static/component_functions = list(
COMP_TRIGONOMETRY_SINE,
diff --git a/code/modules/wiremod/components/ntnet/ntnet_receive.dm b/code/modules/wiremod/components/ntnet/ntnet_receive.dm
index 530d28721e96..59e6e14cae01 100644
--- a/code/modules/wiremod/components/ntnet/ntnet_receive.dm
+++ b/code/modules/wiremod/components/ntnet/ntnet_receive.dm
@@ -20,6 +20,12 @@
/// Encryption key
var/datum/port/input/enc_key
+/obj/item/circuit_component/ntnet_receive/Destroy()
+ list_options = null
+ data_package = null
+ enc_key = null
+ . = ..()
+
/obj/item/circuit_component/ntnet_receive/populate_options()
list_options = add_option_port("Тип списка", GLOB.wiremod_basic_types)
diff --git a/code/modules/wiremod/components/ntnet/ntnet_send.dm b/code/modules/wiremod/components/ntnet/ntnet_send.dm
index 0201a72f3df2..c14a908e0f89 100644
--- a/code/modules/wiremod/components/ntnet/ntnet_send.dm
+++ b/code/modules/wiremod/components/ntnet/ntnet_send.dm
@@ -22,6 +22,12 @@
/// Encryption key
var/datum/port/input/enc_key
+/obj/item/circuit_component/ntnet_send/Destroy()
+ list_options = null
+ data_package = null
+ enc_key = null
+ . = ..()
+
/obj/item/circuit_component/ntnet_send/populate_options()
list_options = add_option_port("Тип списка", GLOB.wiremod_basic_types)
diff --git a/code/modules/wiremod/components/ntnet/ntnet_send_literal.dm b/code/modules/wiremod/components/ntnet/ntnet_send_literal.dm
index 3ea9abf661c9..7da6e1ebf3ec 100644
--- a/code/modules/wiremod/components/ntnet/ntnet_send_literal.dm
+++ b/code/modules/wiremod/components/ntnet/ntnet_send_literal.dm
@@ -18,6 +18,10 @@
/// Encryption key
var/datum/port/input/enc_key
+/obj/item/circuit_component/list_literal/ntnet_send/Destroy()
+ enc_key = null
+ . = ..()
+
/obj/item/circuit_component/list_literal/ntnet_send/populate_ports()
. = ..()
enc_key = add_input_port("Ключ", PORT_TYPE_STRING)
diff --git a/code/modules/wiremod/components/sensors/pressuresensor.dm b/code/modules/wiremod/components/sensors/pressuresensor.dm
index 57e5f99e74d9..43585619126c 100644
--- a/code/modules/wiremod/components/sensors/pressuresensor.dm
+++ b/code/modules/wiremod/components/sensors/pressuresensor.dm
@@ -14,6 +14,10 @@
/// The result from the output
var/datum/port/output/result
+/obj/item/circuit_component/pressuresensor/Destroy()
+ result = null
+ . = ..()
+
/obj/item/circuit_component/pressuresensor/populate_ports()
result = add_output_port("Результат", PORT_TYPE_NUMBER)
diff --git a/code/modules/wiremod/components/sensors/tempsensor.dm b/code/modules/wiremod/components/sensors/tempsensor.dm
index a340b9adadd9..f69cf93bde61 100644
--- a/code/modules/wiremod/components/sensors/tempsensor.dm
+++ b/code/modules/wiremod/components/sensors/tempsensor.dm
@@ -14,6 +14,10 @@
/// The result from the output
var/datum/port/output/result
+/obj/item/circuit_component/tempsensor/Destroy()
+ result = null
+ . = ..()
+
/obj/item/circuit_component/tempsensor/populate_ports()
result = add_output_port("Результат", PORT_TYPE_NUMBER)
diff --git a/code/modules/wiremod/components/sensors/view_sensor.dm b/code/modules/wiremod/components/sensors/view_sensor.dm
index 4ad9b80471eb..7a99734f744a 100644
--- a/code/modules/wiremod/components/sensors/view_sensor.dm
+++ b/code/modules/wiremod/components/sensors/view_sensor.dm
@@ -25,6 +25,12 @@
var/view_cooldown = 1 SECONDS
var/maximum_range = 5 //Variablised incase admins want to increase it.
+/obj/item/circuit_component/view_sensor/Destroy()
+ range = null
+ result = null
+ cooldown = null
+ . = ..()
+
/obj/item/circuit_component/view_sensor/populate_ports()
range = add_input_port("Дальность", PORT_TYPE_NUMBER, default = maximum_range)
result = add_output_port("Результат", PORT_TYPE_LIST(PORT_TYPE_ATOM))
diff --git a/code/modules/wiremod/components/string/concat.dm b/code/modules/wiremod/components/string/concat.dm
index def4e682a73d..5ebaf5ccd2d9 100644
--- a/code/modules/wiremod/components/string/concat.dm
+++ b/code/modules/wiremod/components/string/concat.dm
@@ -19,6 +19,11 @@
"minus" = "remove",
)
+/obj/item/circuit_component/concat/Destroy()
+ LAZYCLEARLIST(concat_ports)
+ output = null
+ . = ..()
+
/obj/item/circuit_component/concat/populate_ports()
AddComponent(/datum/component/circuit_component_add_port, \
port_list = concat_ports, \
diff --git a/code/modules/wiremod/components/string/contains.dm b/code/modules/wiremod/components/string/contains.dm
index a7dffe4e6daa..b4bf61a60242 100644
--- a/code/modules/wiremod/components/string/contains.dm
+++ b/code/modules/wiremod/components/string/contains.dm
@@ -11,14 +11,14 @@
var/datum/port/input/needle
var/datum/port/input/haystack
-/obj/item/circuit_component/compare/contains/populate_custom_ports()
- haystack = add_input_port("Строка", PORT_TYPE_STRING)
- needle = add_input_port("Подстрока", PORT_TYPE_STRING)
-
/obj/item/circuit_component/compare/contains/Destroy()
needle = null
haystack = null
- return ..()
+ . = ..()
+
+/obj/item/circuit_component/compare/contains/populate_custom_ports()
+ haystack = add_input_port("Строка", PORT_TYPE_STRING)
+ needle = add_input_port("Подстрока", PORT_TYPE_STRING)
/obj/item/circuit_component/compare/contains/do_comparisons()
var/to_find = needle.value
diff --git a/code/modules/wiremod/components/string/textcase.dm b/code/modules/wiremod/components/string/textcase.dm
index 331926381dbf..237365751b1c 100644
--- a/code/modules/wiremod/components/string/textcase.dm
+++ b/code/modules/wiremod/components/string/textcase.dm
@@ -21,6 +21,12 @@
circuit_flags = CIRCUIT_FLAG_INPUT_SIGNAL|CIRCUIT_FLAG_OUTPUT_SIGNAL
+/obj/item/circuit_component/textcase/Destroy()
+ textcase_options = null
+ input_port = null
+ output = null
+ . = ..()
+
/obj/item/circuit_component/textcase/populate_options()
var/static/component_options = list(
COMP_TEXT_LOWER,
diff --git a/code/modules/wiremod/components/string/tonumber.dm b/code/modules/wiremod/components/string/tonumber.dm
index 1e370cf11321..f1eb5891b44d 100644
--- a/code/modules/wiremod/components/string/tonumber.dm
+++ b/code/modules/wiremod/components/string/tonumber.dm
@@ -18,6 +18,11 @@
circuit_flags = CIRCUIT_FLAG_INPUT_SIGNAL|CIRCUIT_FLAG_OUTPUT_SIGNAL
+/obj/item/circuit_component/tonumber/Destroy()
+ input_port = null
+ output = null
+ . = ..()
+
/obj/item/circuit_component/tonumber/populate_ports()
input_port = add_input_port("Ввод", PORT_TYPE_STRING)
output = add_output_port("Результат", PORT_TYPE_NUMBER)
diff --git a/code/modules/wiremod/components/string/tostring.dm b/code/modules/wiremod/components/string/tostring.dm
index 4be1bbb4bd5d..a1a569cf7fdd 100644
--- a/code/modules/wiremod/components/string/tostring.dm
+++ b/code/modules/wiremod/components/string/tostring.dm
@@ -18,6 +18,11 @@
var/max_range = 7
+/obj/item/circuit_component/tostring/Destroy()
+ input_port = null
+ output = null
+ . = ..()
+
/obj/item/circuit_component/tostring/populate_ports()
input_port = add_input_port("Ввод", PORT_TYPE_ANY)
output = add_output_port("Результат", PORT_TYPE_STRING)
diff --git a/code/modules/wiremod/components/table/get_column.dm b/code/modules/wiremod/components/table/get_column.dm
index 3d5bf5221de0..b1ef31f3e14c 100644
--- a/code/modules/wiremod/components/table/get_column.dm
+++ b/code/modules/wiremod/components/table/get_column.dm
@@ -18,6 +18,12 @@
/// The filtered list
var/datum/port/output/output_list
+/obj/item/circuit_component/get_column/Destroy()
+ received_table = null
+ column_name = null
+ output_list = null
+ . = ..()
+
/obj/item/circuit_component/get_column/populate_ports()
received_table = add_input_port("Ввод", PORT_TYPE_TABLE)
column_name = add_input_port("Название", PORT_TYPE_STRING)
diff --git a/code/modules/wiremod/components/table/index_table.dm b/code/modules/wiremod/components/table/index_table.dm
index ef8a48b4f1cd..c78f7728ff51 100644
--- a/code/modules/wiremod/components/table/index_table.dm
+++ b/code/modules/wiremod/components/table/index_table.dm
@@ -19,6 +19,12 @@
/// The filtered list
var/datum/port/output/output_list
+/obj/item/circuit_component/index_table/Destroy()
+ received_table = null
+ target_index = null
+ output_list = null
+ . = ..()
+
/obj/item/circuit_component/index_table/populate_ports()
received_table = add_input_port("Ввод", PORT_TYPE_TABLE)
target_index = add_input_port("Индекс", PORT_TYPE_NUMBER)
diff --git a/code/modules/wiremod/components/table/select.dm b/code/modules/wiremod/components/table/select.dm
index 48a82178ad71..24e3625aeb6f 100644
--- a/code/modules/wiremod/components/table/select.dm
+++ b/code/modules/wiremod/components/table/select.dm
@@ -27,6 +27,14 @@
var/current_type = PORT_TYPE_ANY
+/obj/item/circuit_component/select/Destroy()
+ comparison_options = null
+ received_table = null
+ column_name = null
+ comparison_input = null
+ filtered_table = null
+ . = ..()
+
/obj/item/circuit_component/select/populate_options()
var/static/component_options = list(
COMP_COMPARISON_EQUAL,
diff --git a/code/modules/wiremod/components/utility/clock.dm b/code/modules/wiremod/components/utility/clock.dm
index 6aa8fb5f44a6..c5f417430f42 100644
--- a/code/modules/wiremod/components/utility/clock.dm
+++ b/code/modules/wiremod/components/utility/clock.dm
@@ -14,6 +14,12 @@
/// The signal from this clock component
var/datum/port/output/signal
+/obj/item/circuit_component/clock/Destroy()
+ stop_process()
+ on = null
+ signal = null
+ . = ..()
+
/obj/item/circuit_component/clock/get_ui_notices()
. = ..()
. += create_ui_notice("Интервал часов: [DisplayTimeText(COMP_CLOCK_DELAY)]", "orange", "clock")
@@ -30,10 +36,6 @@
else
stop_process()
-/obj/item/circuit_component/clock/Destroy()
- stop_process()
- return ..()
-
/obj/item/circuit_component/clock/process(seconds_per_tick)
signal.set_output(COMPONENT_SIGNAL)
diff --git a/code/modules/wiremod/components/utility/delay.dm b/code/modules/wiremod/components/utility/delay.dm
index e3e9ce6df22b..0b82fd3fb5e0 100644
--- a/code/modules/wiremod/components/utility/delay.dm
+++ b/code/modules/wiremod/components/utility/delay.dm
@@ -24,6 +24,13 @@
/// The output of the signal
var/datum/port/output/output
+/obj/item/circuit_component/delay/Destroy()
+ delay_amount = null
+ trigger = null
+ output = null
+ interrupt = null
+ . = ..()
+
/obj/item/circuit_component/delay/populate_ports()
delay_amount = add_input_port("Задержка", PORT_TYPE_NUMBER, trigger = null)
trigger = add_input_port("Вызов", PORT_TYPE_SIGNAL, trigger = PROC_REF(trigger_delay))
diff --git a/code/modules/wiremod/components/utility/nfc_receive.dm b/code/modules/wiremod/components/utility/nfc_receive.dm
index 2c98c0dd2f33..55fef96652a3 100644
--- a/code/modules/wiremod/components/utility/nfc_receive.dm
+++ b/code/modules/wiremod/components/utility/nfc_receive.dm
@@ -23,6 +23,12 @@
/// Encryption key
var/datum/port/input/enc_key
+/obj/item/circuit_component/nfc_receive/Destroy()
+ list_options = null
+ data_package = null
+ enc_key = null
+ . = ..()
+
/obj/item/circuit_component/nfc_receive/populate_options()
list_options = add_option_port("Тип", GLOB.wiremod_basic_types)
diff --git a/code/modules/wiremod/components/utility/nfc_send.dm b/code/modules/wiremod/components/utility/nfc_send.dm
index f3255590e575..d6ded22c3ac2 100644
--- a/code/modules/wiremod/components/utility/nfc_send.dm
+++ b/code/modules/wiremod/components/utility/nfc_send.dm
@@ -25,6 +25,13 @@
/// Encryption key
var/datum/port/input/enc_key
+/obj/item/circuit_component/nfc_send/Destroy()
+ list_options = null
+ target = null
+ data_package = null
+ enc_key = null
+ . = ..()
+
/obj/item/circuit_component/nfc_send/populate_options()
list_options = add_option_port("Тип списка", GLOB.wiremod_basic_types)
diff --git a/code/modules/wiremod/components/utility/nfc_send_literal.dm b/code/modules/wiremod/components/utility/nfc_send_literal.dm
index 28245dda9bbc..f08efc13b381 100644
--- a/code/modules/wiremod/components/utility/nfc_send_literal.dm
+++ b/code/modules/wiremod/components/utility/nfc_send_literal.dm
@@ -20,6 +20,11 @@
/// The targeted circuit
var/datum/port/input/target
+/obj/item/circuit_component/list_literal/nfc_send/Destroy()
+ enc_key = null
+ target = null
+ . = ..()
+
/obj/item/circuit_component/list_literal/nfc_send/populate_ports()
. = ..()
enc_key = add_input_port("Ключ", PORT_TYPE_STRING)
diff --git a/code/modules/wiremod/components/utility/router.dm b/code/modules/wiremod/components/utility/router.dm
index e882c89c7aca..99dcdf34587a 100644
--- a/code/modules/wiremod/components/utility/router.dm
+++ b/code/modules/wiremod/components/utility/router.dm
@@ -27,6 +27,16 @@
var/list/datum/port/input/ins
var/list/datum/port/output/outs
+/obj/item/circuit_component/router/Destroy()
+ input_selector = null
+ output_selector = null
+ LAZYCLEARLIST(ins)
+ ins = null
+ LAZYCLEARLIST(outs)
+ outs = null
+ router_options = null
+ return ..()
+
/obj/item/circuit_component/router/populate_options()
router_options = add_option_port("Параметры", GLOB.wiremod_basic_types)
@@ -43,15 +53,6 @@
for(var/port_id in 1 to output_port_amount)
outs += add_output_port(output_port_amount > 1 ? "Вывод [port_id]" : "Вывод", current_type)
-/obj/item/circuit_component/router/Destroy()
- input_selector = null
- output_selector = null
- ins.Cut()
- ins = null
- outs.Cut()
- outs = null
- return ..()
-
// If I is in range, L[I]. If I is out of range, wrap around.
#define WRAPACCESS(L, I) L[(((I || 1)-1)%length(L)+length(L))%length(L)+1]
diff --git a/code/modules/wiremod/components/utility/timepiece.dm b/code/modules/wiremod/components/utility/timepiece.dm
index 7d775a8004f1..bfdce593f850 100644
--- a/code/modules/wiremod/components/utility/timepiece.dm
+++ b/code/modules/wiremod/components/utility/timepiece.dm
@@ -25,6 +25,13 @@
/// seconds, minutes, hours.
var/datum/port/output/num_output
+/obj/item/circuit_component/timepiece/Destroy()
+ format = null
+ time_unit = null
+ text_output = null
+ num_output = null
+ . = ..()
+
/obj/item/circuit_component/timepiece/populate_ports()
text_output = add_output_port("Формат", PORT_TYPE_STRING)
num_output = add_output_port("Единица", PORT_TYPE_NUMBER)
diff --git a/code/modules/wiremod/components/utility/typecast.dm b/code/modules/wiremod/components/utility/typecast.dm
index 61af2d8db5c6..288477e06635 100644
--- a/code/modules/wiremod/components/utility/typecast.dm
+++ b/code/modules/wiremod/components/utility/typecast.dm
@@ -17,6 +17,12 @@
var/current_type
+/obj/item/circuit_component/typecast/Destroy()
+ typecast_options = null
+ input_value = null
+ output_value = null
+ . = ..()
+
/obj/item/circuit_component/typecast/populate_ports()
current_type = typecast_options.value
input_value = add_input_port("Ввод", PORT_TYPE_ANY)
diff --git a/code/modules/wiremod/components/utility/typecheck.dm b/code/modules/wiremod/components/utility/typecheck.dm
index 922f27cb581e..c5d53246b9a0 100644
--- a/code/modules/wiremod/components/utility/typecheck.dm
+++ b/code/modules/wiremod/components/utility/typecheck.dm
@@ -16,6 +16,11 @@
/// Object to typecheck
var/datum/port/input/thing_to_check
+/obj/item/circuit_component/compare/typecheck/Destroy()
+ typecheck_options = null
+ thing_to_check = null
+ . = ..()
+
/obj/item/circuit_component/compare/typecheck/populate_options()
var/static/component_options = list(
PORT_TYPE_STRING,
diff --git a/code/modules/wiremod/components/variables/getter.dm b/code/modules/wiremod/components/variables/getter.dm
index 383a6940b339..661497c33675 100644
--- a/code/modules/wiremod/components/variables/getter.dm
+++ b/code/modules/wiremod/components/variables/getter.dm
@@ -11,6 +11,10 @@
var/datum/port/output/value
should_listen = TRUE
+/obj/item/circuit_component/variable/getter/Destroy()
+ value = null
+ . = ..()
+
/obj/item/circuit_component/variable/getter/populate_ports()
value = add_output_port("Значение", PORT_TYPE_ANY)
diff --git a/code/modules/wiremod/components/variables/setter.dm b/code/modules/wiremod/components/variables/setter.dm
index fa866af0b489..ef9c2ab202bc 100644
--- a/code/modules/wiremod/components/variables/setter.dm
+++ b/code/modules/wiremod/components/variables/setter.dm
@@ -10,6 +10,10 @@
/// The input to store
var/datum/port/input/input_port
+/obj/item/circuit_component/variable/setter/Destroy()
+ input_port = null
+ . = ..()
+
/obj/item/circuit_component/variable/setter/trigger
display_name = "Установщик переменной вызова"
desc = "Компонент, который задаёт переменную глобально в схеме. \
diff --git a/code/modules/wiremod/components/wirenet/wirenet_receive.dm b/code/modules/wiremod/components/wirenet/wirenet_receive.dm
index 13b5310b3af5..969ac4f0599a 100644
--- a/code/modules/wiremod/components/wirenet/wirenet_receive.dm
+++ b/code/modules/wiremod/components/wirenet/wirenet_receive.dm
@@ -15,6 +15,12 @@
/// Encryption key
var/datum/port/input/enc_key
+/obj/item/circuit_component/wirenet_receive/Destroy()
+ list_options = null
+ data_package = null
+ enc_key = null
+ . = ..()
+
/obj/item/circuit_component/wirenet_receive/Initialize(mapload)
. = ..()
AddComponent(\
diff --git a/code/modules/wiremod/components/wirenet/wirenet_send.dm b/code/modules/wiremod/components/wirenet/wirenet_send.dm
index ae64f52ebd6c..2edb2b6a096b 100644
--- a/code/modules/wiremod/components/wirenet/wirenet_send.dm
+++ b/code/modules/wiremod/components/wirenet/wirenet_send.dm
@@ -18,6 +18,13 @@
/// Encryption key
var/datum/port/input/enc_key
+/obj/item/circuit_component/wirenet_send/Destroy()
+ list_options = null
+ data_package = null
+ enc_key = null
+ connected_powernet = null
+ . = ..()
+
/obj/item/circuit_component/wirenet_send/Initialize(mapload)
. = ..()
AddComponent(\
@@ -26,10 +33,6 @@
disconnection_callback = CALLBACK(src, PROC_REF(on_powernet_disconnection)),\
)
-/obj/item/circuit_component/wirenet_send/Destroy()
- . = ..()
- connected_powernet = null
-
/obj/item/circuit_component/wirenet_send/proc/on_powernet_connection(datum/powernet/new_powernet)
connected_powernet = new_powernet
diff --git a/code/modules/wiremod/components/wirenet/wirenet_send_literal.dm b/code/modules/wiremod/components/wirenet/wirenet_send_literal.dm
index 31d506e641fe..83a0839d80b5 100644
--- a/code/modules/wiremod/components/wirenet/wirenet_send_literal.dm
+++ b/code/modules/wiremod/components/wirenet/wirenet_send_literal.dm
@@ -11,6 +11,11 @@
/// Encryption key
var/datum/port/input/enc_key
+/obj/item/circuit_component/list_literal/wirenet_send/Destroy()
+ connected_powernet = null
+ enc_key = null
+ . = ..()
+
/obj/item/circuit_component/list_literal/wirenet_send/Initialize(mapload)
. = ..()
AddComponent(\
@@ -19,10 +24,6 @@
disconnection_callback = CALLBACK(src, PROC_REF(on_powernet_disconnection)),\
)
-/obj/item/circuit_component/list_literal/wirenet_send/Destroy()
- . = ..()
- connected_powernet = null
-
/obj/item/circuit_component/list_literal/wirenet_send/proc/on_powernet_connection(datum/powernet/new_powernet)
connected_powernet = new_powernet
diff --git a/code/modules/wiremod/shell/airlock.dm b/code/modules/wiremod/shell/airlock.dm
index cc5b12903dda..15b803f6e1ef 100644
--- a/code/modules/wiremod/shell/airlock.dm
+++ b/code/modules/wiremod/shell/airlock.dm
@@ -78,6 +78,21 @@
/// Called when the airlock is unbolted
var/datum/port/output/unbolted
+/obj/item/circuit_component/airlock/Destroy()
+ if(attached_airlock)
+ unregister_shell(attached_airlock)
+ bolt = null
+ unbolt = null
+ open = null
+ close = null
+ is_open = null
+ is_bolted = null
+ opened = null
+ closed = null
+ bolted = null
+ unbolted = null
+ . = ..()
+
/obj/item/circuit_component/airlock/populate_ports()
// Input Signals
bolt = add_input_port("Болтировать", PORT_TYPE_SIGNAL)
@@ -165,6 +180,14 @@
/// The signal sent when this event is triggered
var/datum/port/output/event_triggered
+/obj/item/circuit_component/airlock_access_event/Destroy()
+ if(attached_airlock)
+ unregister_shell(attached_airlock)
+ open_airlock = null
+ accessing_entity = null
+ event_triggered = null
+ . = ..()
+
/obj/item/circuit_component/airlock_access_event/register_shell(atom/movable/shell)
. = ..()
if(!is_airlock(shell))
diff --git a/code/modules/wiremod/shell/assembly.dm b/code/modules/wiremod/shell/assembly.dm
index 3344c464e190..084a79578dcc 100644
--- a/code/modules/wiremod/shell/assembly.dm
+++ b/code/modules/wiremod/shell/assembly.dm
@@ -33,6 +33,10 @@
var/datum/port/output/signal
+/obj/item/circuit_component/assembly_input/Destroy()
+ signal = null
+ . = ..()
+
/obj/item/circuit_component/assembly_input/populate_ports()
signal = add_output_port("Вызвано", PORT_TYPE_SIGNAL)
@@ -54,6 +58,12 @@
var/datum/port/input/signal
+/obj/item/circuit_component/assembly_output/Destroy()
+ if(attached_assembly)
+ unregister_shell(attached_assembly)
+ signal = null
+ . = ..()
+
/obj/item/circuit_component/assembly_output/populate_ports()
signal = add_input_port("Вызов", PORT_TYPE_SIGNAL)
diff --git a/code/modules/wiremod/shell/bot.dm b/code/modules/wiremod/shell/bot.dm
index b7e5c8a47ef2..af536353a45a 100644
--- a/code/modules/wiremod/shell/bot.dm
+++ b/code/modules/wiremod/shell/bot.dm
@@ -40,6 +40,11 @@
/// The user who used the bot
var/datum/port/output/entity
+/obj/item/circuit_component/bot/Destroy()
+ signal = null
+ entity = null
+ . = ..()
+
/obj/item/circuit_component/bot/populate_ports()
entity = add_output_port("Пользователь", PORT_TYPE_USER)
signal = add_output_port("Вызвано", PORT_TYPE_SIGNAL)
diff --git a/code/modules/wiremod/shell/brain_computer_interface.dm b/code/modules/wiremod/shell/brain_computer_interface.dm
index 58fde6ad2d02..25a454c043fa 100644
--- a/code/modules/wiremod/shell/brain_computer_interface.dm
+++ b/code/modules/wiremod/shell/brain_computer_interface.dm
@@ -99,6 +99,16 @@
var/obj/item/organ/internal/cyberimp/brain/bci/bci
+/obj/item/circuit_component/bci_core/Destroy()
+ if(bci)
+ unregister_shell(bci)
+ QDEL_NULL(charge_action)
+ message = null
+ send_message_signal = null
+ show_charge_meter = null
+ user_port = null
+ return ..()
+
/obj/item/circuit_component/bci_core/populate_ports()
message = add_input_port("Сообщение", PORT_TYPE_STRING, trigger = null)
@@ -107,9 +117,6 @@
user_port = add_output_port("Пользователь", PORT_TYPE_USER)
-/obj/item/circuit_component/bci_core/Destroy()
- QDEL_NULL(charge_action)
- return ..()
/obj/item/circuit_component/bci_core/proc/update_charge_action()
CIRCUIT_TRIGGER
diff --git a/code/modules/wiremod/shell/compact_remote.dm b/code/modules/wiremod/shell/compact_remote.dm
index 22b68422aa6f..866dfc39392f 100644
--- a/code/modules/wiremod/shell/compact_remote.dm
+++ b/code/modules/wiremod/shell/compact_remote.dm
@@ -38,6 +38,11 @@
/// The user who used the bot
var/datum/port/output/entity
+/obj/item/circuit_component/compact_remote/Destroy()
+ signal = null
+ entity = null
+ . = ..()
+
/obj/item/circuit_component/compact_remote/populate_ports()
entity = add_output_port("Пользователь", PORT_TYPE_USER)
signal = add_output_port("Вызвано", PORT_TYPE_SIGNAL)
diff --git a/code/modules/wiremod/shell/controller.dm b/code/modules/wiremod/shell/controller.dm
index d839fd04c733..3251c3b18309 100644
--- a/code/modules/wiremod/shell/controller.dm
+++ b/code/modules/wiremod/shell/controller.dm
@@ -42,6 +42,13 @@
/// The entity output
var/datum/port/output/entity
+/obj/item/circuit_component/controller/Destroy()
+ signal = null
+ alt = null
+ ctrl = null
+ entity = null
+ . = ..()
+
/obj/item/circuit_component/controller/examine(mob/user)
. = ..()
. += "Используйте ALT+ЛКМ для подачи альтернативного сигнала, CTRL+ЛКМ для дополнительного."
diff --git a/code/modules/wiremod/shell/dispenser.dm b/code/modules/wiremod/shell/dispenser.dm
index 7b958f3b8041..750626753075 100644
--- a/code/modules/wiremod/shell/dispenser.dm
+++ b/code/modules/wiremod/shell/dispenser.dm
@@ -133,6 +133,13 @@
var/max_vendor_components = 20
+/obj/item/circuit_component/dispenser_bot/Destroy()
+ item_list = null
+ item = null
+ on_item_added = null
+ on_item_removed = null
+ . = ..()
+
/obj/item/circuit_component/dispenser_bot/populate_ports()
item_list = add_output_port("Объекты", PORT_TYPE_LIST(PORT_TYPE_ATOM))
item = add_output_port("Объект", PORT_TYPE_ATOM)
@@ -204,6 +211,13 @@
circuit_size = 0
+/obj/item/circuit_component/vendor_component/Destroy()
+ if(attached_bot)
+ unregister_shell(attached_bot)
+ item_to_vend = null
+ vend_item = null
+ . = ..()
+
/obj/item/circuit_component/vendor_component/register_shell(atom/movable/shell)
. = ..()
if(!istype(shell, /obj/structure/dispenser_bot))
diff --git a/code/modules/wiremod/shell/drone.dm b/code/modules/wiremod/shell/drone.dm
index fc990fcfb766..227dc3424a8e 100644
--- a/code/modules/wiremod/shell/drone.dm
+++ b/code/modules/wiremod/shell/drone.dm
@@ -91,6 +91,13 @@
/// Delay between each movement
var/move_delay = 0.4 SECONDS
+/obj/item/circuit_component/bot_circuit/Destroy()
+ north = null
+ east = null
+ south = null
+ west = null
+ . = ..()
+
/obj/item/circuit_component/bot_circuit/register_shell(atom/movable/shell)
. = ..()
if(!ismob(shell))
diff --git a/code/modules/wiremod/shell/gun.dm b/code/modules/wiremod/shell/gun.dm
index 5b679aeb8193..5dc51326c261 100644
--- a/code/modules/wiremod/shell/gun.dm
+++ b/code/modules/wiremod/shell/gun.dm
@@ -57,6 +57,12 @@
/// The entity being shot
var/datum/port/output/shot
+/obj/item/circuit_component/wiremod_gun/Destroy()
+ signal = null
+ shooter = null
+ shot = null
+ . = ..()
+
/obj/item/circuit_component/wiremod_gun/Initialize(mapload)
. = ..()
shooter = add_output_port("Пользователь", PORT_TYPE_ATOM)
diff --git a/code/modules/wiremod/shell/keyboard.dm b/code/modules/wiremod/shell/keyboard.dm
index 1d3f65928c9c..0b3ac9280b03 100644
--- a/code/modules/wiremod/shell/keyboard.dm
+++ b/code/modules/wiremod/shell/keyboard.dm
@@ -34,6 +34,12 @@
/// The string, entity typed and submitted
var/datum/port/output/output
+/obj/item/circuit_component/keyboard_shell/Destroy()
+ signal = null
+ entity = null
+ output = null
+ . = ..()
+
/obj/item/circuit_component/keyboard_shell/examine(mob/user)
. = ..()
. += span_notice("Используйте в руке, чтобы открыть панель ввода.")
diff --git a/code/modules/wiremod/shell/manipulator.dm b/code/modules/wiremod/shell/manipulator.dm
index 46a68afc1835..e359cd1db49a 100644
--- a/code/modules/wiremod/shell/manipulator.dm
+++ b/code/modules/wiremod/shell/manipulator.dm
@@ -2,7 +2,7 @@
* # Manipulator
*
* Immobile shells that can move objects
- *
+ *
*/
/obj/structure/wiremod_manipulator
name = "manipulator"
@@ -47,6 +47,14 @@
var/obj/structure/wiremod_manipulator/attached_bot
+/obj/item/circuit_component/wiremod_manipulator/Destroy()
+ if(attached_bot)
+ unregister_shell(attached_bot)
+ image_pixel_x = null
+ image_pixel_y = null
+ target = null
+ . = ..()
+
/obj/item/circuit_component/wiremod_manipulator/populate_ports()
target = add_input_port("Цель", PORT_TYPE_ATOM)
image_pixel_x = add_input_port("X", PORT_TYPE_NUMBER)
@@ -78,7 +86,7 @@
var/target_y = image_pixel_y.value
if(!target_atom || !target_x || !target_y)
return
-
+
var/turf/target_turf = locate(target_x, target_y, target_atom.z)
if(get_dist(attached_bot, target_atom) > 1 || attached_bot.z != target_atom.z || iswallturf(target_turf))
return
@@ -94,7 +102,7 @@
/obj/item/circuit_component/wiremod_manipulator/proc/finish_move(atom/movable/target_atom, turf/target_turf)
if(!target_atom || target_atom.anchored || !attached_bot?.anchored || get_dist(attached_bot, target_atom) > 1)
return
-
+
attached_bot.visible_message(span_danger("[attached_bot] с громким жужжанием перемещает [target_atom]"))
target_atom.forceMove(target_turf)
target_atom.SpinAnimation(speed = 5, loops = 1, parallel = FALSE)
diff --git a/code/modules/wiremod/shell/module.dm b/code/modules/wiremod/shell/module.dm
index 3cbeaa34ce09..80855a1a8336 100644
--- a/code/modules/wiremod/shell/module.dm
+++ b/code/modules/wiremod/shell/module.dm
@@ -34,6 +34,11 @@
capacity = SHELL_CAPACITY_LARGE, \
)
+/obj/item/mod/module/circuit/Destroy()
+ shell = null
+ LAZYCLEARLIST(action_comps)
+ . = ..()
+
/obj/item/mod/module/circuit/proc/override_power_usage(datum/source, amount)
SIGNAL_HANDLER
if(drain_power(amount))
@@ -200,6 +205,23 @@
/// The signal that is triggered when the suit has finished toggling itself after being activated by a signal
var/datum/port/output/on_toggle_finish
+/obj/item/circuit_component/mod_adapter_core/Destroy()
+ if(attached_module)
+ unregister_shell(attached_module)
+ module_to_select = null
+ toggle_deploy = null
+ toggle_suit = null
+ select_module = null
+ wearer = null
+ deployed = null
+ activated = null
+ selected_module = null
+ deployed_parts = null
+ on_module_selected = null
+ on_deploy = null
+ on_toggle_finish = null
+ . = ..()
+
/obj/item/circuit_component/mod_adapter_core/populate_options()
module_to_select = add_option_port("Выбор модуля", list())
diff --git a/code/modules/wiremod/shell/moneybot.dm b/code/modules/wiremod/shell/moneybot.dm
index 7e89b9f7b534..9ec63fcd30f2 100644
--- a/code/modules/wiremod/shell/moneybot.dm
+++ b/code/modules/wiremod/shell/moneybot.dm
@@ -62,6 +62,13 @@
/// Attached shell
var/obj/structure/money_bot/attached_bot
+/obj/item/circuit_component/money_dispenser/Destroy()
+ if(attached_bot)
+ unregister_shell(attached_bot)
+ dispense_amount = null
+ on_fail = null
+ . = ..()
+
/obj/item/circuit_component/money_dispenser/populate_ports()
dispense_amount = add_input_port("Количество", PORT_TYPE_NUMBER)
on_fail = add_output_port("Провал", PORT_TYPE_SIGNAL)
@@ -105,6 +112,15 @@
/// Attached shell
var/obj/structure/money_bot/attached_bot
+/obj/item/circuit_component/money_bot/Destroy()
+ if(attached_bot)
+ unregister_shell(attached_bot)
+ total_money = null
+ money_input = null
+ money_trigger = null
+ entity = null
+ . = ..()
+
/obj/item/circuit_component/money_bot/populate_ports()
total_money = add_output_port("Всего денег", PORT_TYPE_NUMBER)
money_input = add_output_port("Последняя транзакция", PORT_TYPE_NUMBER)
diff --git a/code/modules/wiremod/shell/scanner.dm b/code/modules/wiremod/shell/scanner.dm
index 5775ff4504b2..323259a40565 100644
--- a/code/modules/wiremod/shell/scanner.dm
+++ b/code/modules/wiremod/shell/scanner.dm
@@ -41,6 +41,11 @@
/// The entity being attacked
var/datum/port/output/attacking
+/obj/item/circuit_component/wiremod_scanner/Destroy()
+ signal = null
+ attacker = null
+ attacking = null
+ . = ..()
/obj/item/circuit_component/wiremod_scanner/populate_ports()
attacker = add_output_port("Пользователь", PORT_TYPE_USER)
diff --git a/librustlibs.so b/librustlibs.so
index 946d131192c9..b81aa7a29146 100755
Binary files a/librustlibs.so and b/librustlibs.so differ
diff --git a/librustlibs_prod.so b/librustlibs_prod.so
index fc054f6af803..b445e7271109 100755
Binary files a/librustlibs_prod.so and b/librustlibs_prod.so differ
diff --git a/rust/src/milla/api.rs b/rust/src/milla/api.rs
index 3ee263d7f735..fe42dfa0b9ce 100644
--- a/rust/src/milla/api.rs
+++ b/rust/src/milla/api.rs
@@ -766,9 +766,9 @@ fn milla_set_zlevel_frozen(
#[byondapi::bind]
fn milla_reset() -> eyre::Result {
- let buffers = BUFFERS.get().ok_or(eyre!("BUFFERS not initialized."))?;
- buffers.clear_and_free_z_levels();
-
+ if let Some(buffers) = BUFFERS.get() {
+ buffers.clear_and_free_z_levels();
+ }
{
let mut interesting = INTERESTING_TILES.lock().unwrap();
interesting.clear();
diff --git a/rustlibs.dll b/rustlibs.dll
index 0da435fa47da..0e66f439efe9 100644
Binary files a/rustlibs.dll and b/rustlibs.dll differ
diff --git a/tools/ci/librustlibs.so b/tools/ci/librustlibs.so
index 946d131192c9..b81aa7a29146 100755
Binary files a/tools/ci/librustlibs.so and b/tools/ci/librustlibs.so differ