From d38246bb69f84d49334dadf99131792506278134 Mon Sep 17 00:00:00 2001
From: Letter N <24603524+LetterN@users.noreply.github.com>
Date: Mon, 4 Nov 2024 02:06:10 +0800
Subject: [PATCH] Init-&-co (#6833)
## About The Pull Request
update init code, LateInitialize now complains if it doesnt have
anything in it
## Why It's Good For The Game
## Changelog
:cl:
code: update how init does things
code: update matrix helpers
/:cl:
---
citadel.dme | 7 +-
code/__DEFINES/_atoms.dm | 12 +
code/__DEFINES/_core.dm | 4 +
code/__DEFINES/controllers/_subsystems.dm | 5 +-
code/__DEFINES/matrices.dm | 27 ++
code/__DEFINES/vv.dm | 2 +
code/__HELPERS/matrices/color_matrix.dm | 302 +++++++-----------
code/__HELPERS/matrices/transform_matrix.dm | 76 +++--
code/__HELPERS/sorts/comparators.dm | 3 +
code/__HELPERS/type2type/color.dm | 4 +-
code/__HELPERS/vfx/appearance_cloning.dm | 2 +-
code/controllers/subsystem/atoms.dm | 234 ++++++++------
code/datums/holograms/hologram.dm | 4 +-
code/game/atoms/{atom.dm => _atom.dm} | 149 ++-------
code/game/atoms/{vv.dm => atom_vv.dm} | 268 +++++++++-------
.../atoms/atoms_initializing_EXPENSIVE.dm | 159 +++++++++
code/game/atoms/movement.dm | 3 +-
code/game/dna/dna_modifier.dm | 1 -
code/game/landmarks/landmarks.dm | 43 ++-
code/game/machinery/Sleeper.dm | 1 -
code/game/machinery/adv_med.dm | 1 -
code/game/machinery/computer/message.dm | 1 -
code/game/machinery/doors/door_timer.dm | 1 -
code/game/machinery/doors/firedoor.dm | 1 -
code/game/machinery/holopad.dm | 4 +-
code/game/machinery/lightswitch.dm | 8 +-
code/game/machinery/newscaster.dm | 1 -
code/game/machinery/telecomms/_telecomms.dm | 1 -
code/game/machinery/teleporter/pad.dm | 1 -
code/game/machinery/teleporter/projector.dm | 1 -
code/game/objects/items/stacks/sandbag.dm | 1 -
.../structures/crates_lockers/__closet.dm | 1 -
.../structures/crates_lockers/largecrate.dm | 1 -
.../structures/stool_bed_chair_nest/chairs.dm | 1 -
code/game/objects/structures/tables/table.dm | 1 -
code/game/objects/structures/transit_tubes.dm | 1 -
.../game/turfs/simulated/floor_types/glass.dm | 1 -
code/game/turfs/space/space.dm | 28 +-
code/game/turfs/turf.dm | 7 +-
.../view_variables/color_matrix_editor.dm | 2 +-
code/modules/assembly/signaler.dm | 1 -
.../portable/portable_atmospherics.dm | 1 -
.../industry/disposals/disposal/chute.dm | 1 -
.../industry/disposals/disposal_pipe/trunk.dm | 2 +-
code/modules/mapping/dmm_suite/dmm_parsed.dm | 16 +-
.../planet_station_turfs/_lythios43c.dm | 9 +-
code/modules/mob/freelook/ai/eye.dm | 1 -
.../mob/living/bot/medibot_construction.dm | 1 -
code/modules/mob/living/carbon/human/human.dm | 1 -
code/modules/mob/living/silicon/ai/ai.dm | 5 +-
.../modules/organs/external/external_icons.dm | 2 +-
.../overmap/legacy/ships/computers/helm.dm | 1 -
.../overmap/legacy/ships/computers/sensors.dm | 1 -
code/modules/power/breaker_box.dm | 1 -
code/modules/power/geothermal_power.dm | 1 -
code/modules/power/gravitygenerator.dm | 3 +-
code/modules/power/smes/smes.dm | 1 -
tools/read_init_times.py | 9 +-
58 files changed, 771 insertions(+), 656 deletions(-)
create mode 100644 code/__DEFINES/_atoms.dm
create mode 100644 code/__DEFINES/matrices.dm
rename code/game/atoms/{atom.dm => _atom.dm} (88%)
rename code/game/atoms/{vv.dm => atom_vv.dm} (71%)
create mode 100644 code/game/atoms/atoms_initializing_EXPENSIVE.dm
diff --git a/citadel.dme b/citadel.dme
index df14c808d5e6..d3fee73206d0 100644
--- a/citadel.dme
+++ b/citadel.dme
@@ -19,6 +19,7 @@
#include "code\__global_init.dm"
#include "code\_macros.dm"
#include "code\global.dm"
+#include "code\__DEFINES\_atoms.dm"
#include "code\__DEFINES\_bitfields.dm"
#include "code\__DEFINES\_cooldowns.dm"
#include "code\__DEFINES\_core.dm"
@@ -62,6 +63,7 @@
#include "code\__DEFINES\machinery.dm"
#include "code\__DEFINES\maps.dm"
#include "code\__DEFINES\math.dm"
+#include "code\__DEFINES\matrices.dm"
#include "code\__DEFINES\MC.dm"
#include "code\__DEFINES\misc.dm"
#include "code\__DEFINES\move_force.dm"
@@ -1034,18 +1036,19 @@
#include "code\game\area\Tether_areas.dm"
#include "code\game\area\station\exporation.dm"
#include "code\game\area\station\security_areas.dm"
+#include "code\game\atoms\_atom.dm"
#include "code\game\atoms\action_feedback.dm"
#include "code\game\atoms\appearance.dm"
#include "code\game\atoms\atom-construction.dm"
#include "code\game\atoms\atom-damage.dm"
#include "code\game\atoms\atom-defense.dm"
-#include "code\game\atoms\atom.dm"
+#include "code\game\atoms\atom_vv.dm"
+#include "code\game\atoms\atoms_initializing_EXPENSIVE.dm"
#include "code\game\atoms\buckling.dm"
#include "code\game\atoms\defense_old.dm"
#include "code\game\atoms\materials.dm"
#include "code\game\atoms\movement.dm"
#include "code\game\atoms\say.dm"
-#include "code\game\atoms\vv.dm"
#include "code\game\atoms\movable\movable-movement.dm"
#include "code\game\atoms\movable\movable-throw.dm"
#include "code\game\atoms\movable\movable.dm"
diff --git a/code/__DEFINES/_atoms.dm b/code/__DEFINES/_atoms.dm
new file mode 100644
index 000000000000..abc4d805170c
--- /dev/null
+++ b/code/__DEFINES/_atoms.dm
@@ -0,0 +1,12 @@
+#define BAD_INIT_QDEL_BEFORE 1
+#define BAD_INIT_DIDNT_INIT 2
+#define BAD_INIT_SLEPT 4
+#define BAD_INIT_NO_HINT 8
+
+#ifdef PROFILE_MAPLOAD_INIT_ATOM
+#define PROFILE_INIT_ATOM_BEGIN(...) var/__profile_stat_time = TICK_USAGE
+#define PROFILE_INIT_ATOM_END(atom) mapload_init_times[##atom.type] += TICK_USAGE_TO_MS(__profile_stat_time)
+#else
+#define PROFILE_INIT_ATOM_BEGIN(...)
+#define PROFILE_INIT_ATOM_END(...)
+#endif
diff --git a/code/__DEFINES/_core.dm b/code/__DEFINES/_core.dm
index 2a6a70722d89..086fb81f6281 100644
--- a/code/__DEFINES/_core.dm
+++ b/code/__DEFINES/_core.dm
@@ -17,3 +17,7 @@
/// byond bug https://secure.byond.com/forum/?post=2072419
#define BLOCK_BYOND_BUG_2072419
+
+/// A null statement to guard against EmptyBlock lint without necessitating the use of pass()
+/// Used to avoid proc-call overhead. But use sparingly. Probably pointless in most places.
+#define EMPTY_BLOCK_GUARD ;
diff --git a/code/__DEFINES/controllers/_subsystems.dm b/code/__DEFINES/controllers/_subsystems.dm
index 80abb3939ab0..61115e157901 100644
--- a/code/__DEFINES/controllers/_subsystems.dm
+++ b/code/__DEFINES/controllers/_subsystems.dm
@@ -34,8 +34,11 @@
#define INITIALIZE_IMMEDIATE(X) ##X/New(loc, ...){\
..();\
if(!(atom_flags & ATOM_INITIALIZED)) {\
+ var/previous_initialized_value = SSatoms.initialized;\
+ SSatoms.initialized = INITIALIZATION_INNEW_MAPLOAD;\
args[1] = TRUE;\
- SSatoms.InitAtom(src, args);\
+ SSatoms.InitAtom(src, FALSE, args);\
+ SSatoms.initialized = previous_initialized_value;\
}\
}
diff --git a/code/__DEFINES/matrices.dm b/code/__DEFINES/matrices.dm
new file mode 100644
index 000000000000..26ff5a7232a2
--- /dev/null
+++ b/code/__DEFINES/matrices.dm
@@ -0,0 +1,27 @@
+/// Helper macro for creating a matrix at the given offsets.
+/// Works at compile time.
+#define TRANSLATE_MATRIX(offset_x, offset_y) matrix(1, 0, (offset_x), 0, 1, (offset_y))
+/// The color matrix of an image which colors haven't been altered. Does nothing.
+#define COLOR_MATRIX_IDENTITY list(1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1, 0,0,0,0)
+/// Color inversion
+#define COLOR_MATRIX_INVERT list(-1,0,0,0, 0,-1,0,0, 0,0,-1,0, 0,0,0,1, 1,1,1,0)
+///Sepiatone
+#define COLOR_MATRIX_SEPIATONE list(0.393,0.349,0.272,0, 0.769,0.686,0.534,0, 0.189,0.168,0.131,0, 0,0,0,1, 0,0,0,0)
+///Grayscale
+#define COLOR_MATRIX_GRAYSCALE list(0.33,0.33,0.33,0, 0.59,0.59,0.59,0, 0.11,0.11,0.11,0, 0,0,0,1, 0,0,0,0)
+///Polaroid colors
+#define COLOR_MATRIX_POLAROID list(1.438,-0.062,-0.062,0, -0.122,1.378,-0.122,0, -0.016,-0.016,1.483,0, 0,0,0,1, 0,0,0,0)
+/// Converts reds to blue, green to red and blue to green.
+#define COLOR_MATRIX_BRG list(0,0,1,0, 0,1,0,0, 1,0,0,0, 0,0,0,1, 0,0,0,0)
+/// Black & White
+#define COLOR_MATRIX_BLACK_WHITE list(1.5,1.5,1.5,0, 1.5,1.5,1.5,0, 1.5,1.5,1.5,0, 0,0,0,1, -1,-1,-1,0)
+/**
+ * Adds/subtracts overall lightness
+ * 0 is identity, 1 makes everything white, -1 makes everything black
+ */
+#define COLOR_MATRIX_LIGHTNESS(power) list(1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1, power,power,power,0)
+/**
+ * Changes distance colors have from rgb(127,127,127) grey
+ * 1 is identity. 0 makes everything grey >1 blows out colors and greys
+ */
+#define COLOR_MATRIX_CONTRAST(val) list(val,0,0,0, 0,val,0,0, 0,0,val,0, 0,0,0,1, (1-val)*0.5,(1-val)*0.5,(1-val)*0.5,0)
diff --git a/code/__DEFINES/vv.dm b/code/__DEFINES/vv.dm
index c58f5cb50db4..0ba4477f7b8b 100644
--- a/code/__DEFINES/vv.dm
+++ b/code/__DEFINES/vv.dm
@@ -89,6 +89,8 @@
// /atom
#define VV_HK_MODIFY_TRANSFORM "atom_transform"
+#define VV_HK_SPIN_ANIMATION "atom_spin"
+#define VV_HK_STOP_ALL_ANIMATIONS "stop_animations"
#define VV_HK_ADD_REAGENT "addreagent"
#define VV_HK_TRIGGER_EMP "empulse"
#define VV_HK_TRIGGER_EXPLOSION "explode"
diff --git a/code/__HELPERS/matrices/color_matrix.dm b/code/__HELPERS/matrices/color_matrix.dm
index 0a4763076937..73ba29b2284d 100644
--- a/code/__HELPERS/matrices/color_matrix.dm
+++ b/code/__HELPERS/matrices/color_matrix.dm
@@ -2,7 +2,7 @@
// COLOUR MATRICES //
/////////////////////
-/* Documenting a couple of potentially useful color matrices here to inspire ideas.
+/* Documenting a couple of potentially useful color matrices here to inspire ideas
// Greyscale - indentical to saturation @ 0
list(LUMA_R,LUMA_R,LUMA_R,0, LUMA_G,LUMA_G,LUMA_G,0, LUMA_B,LUMA_B,LUMA_B,0, 0,0,0,1, 0,0,0,0)
@@ -13,21 +13,8 @@ list(-1,0,0,0, 0,-1,0,0, 0,0,-1,0, 0,0,0,1, 1,1,1,0)
list(0.393,0.349,0.272,0, 0.769,0.686,0.534,0, 0.189,0.168,0.131,0, 0,0,0,1, 0,0,0,0)
*/
-/// Does nothing.
-/proc/color_matrix_identity()
- return list(1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1, 0,0,0,0)
-
-/**
- * Adds/subtracts overall lightness.
- * 0 is identity, 1 makes everything white, -1 makes everything black.
- */
-/proc/color_matrix_lightness(power)
- return list(1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1, power,power,power,0)
-
-/**
- * Changes distance hues have from grey while maintaining the overall lightness. Greys are unaffected.
- * 1 is identity, 0 is greyscale, >1 oversaturates colors.
- */
+//Changes distance hues have from grey while maintaining the overall lightness. Greys are unaffected.
+//1 is identity, 0 is greyscale, >1 oversaturates colors
/proc/color_matrix_saturation(value)
var/inv = 1 - value
var/R = round(LUMA_R * inv, 0.001)
@@ -36,164 +23,115 @@ list(0.393,0.349,0.272,0, 0.769,0.686,0.534,0, 0.189,0.168,0.131,0, 0,0,0,1, 0,0
return list(R + value,R,R,0, G,G + value,G,0, B,B,B + value,0, 0,0,0,1, 0,0,0,0)
-/**
- * Exxagerates or removes colors.
- */
-/proc/color_matrix_saturation_percent(percent)
- if(percent == 0)
- return color_matrix_identity()
- percent = clamp(percent, -100, 100)
- if(percent > 0)
- percent *= 3
- var/x = 1 + percent / 100
- var/inv = 1 - x
- var/R = LUMA_R * inv
- var/G = LUMA_G * inv
- var/B = LUMA_B * inv
-
- return list(R + x,R,R, G,G + x,G, B,B,B + x)
-
-/**
- * Greyscale matrix.
- */
-/proc/color_matrix_greyscale()
- return list(LUMA_R, LUMA_R, LUMA_R, LUMA_G, LUMA_G, LUMA_G, LUMA_B, LUMA_B, LUMA_B)
-
-/**
- * Changes distance colors have from rgb(127,127,127) grey.
- * 1 is identity. 0 makes everything grey >1 blows out colors and greys.
- */
-/proc/color_matrix_contrast(value)
- var/add = (1 - value) / 2
- return list(value,0,0,0, 0,value,0,0, 0,0,value,0, 0,0,0,1, add,add,add,0)
-
-/**
- * Exxagerates or removes brightness.
- */
-/proc/color_matrix_contrast_percent(percent)
- var/static/list/delta_index = list(
- 0, 0.01, 0.02, 0.04, 0.05, 0.06, 0.07, 0.08, 0.1, 0.11,
- 0.12, 0.14, 0.15, 0.16, 0.17, 0.18, 0.20, 0.21, 0.22, 0.24,
- 0.25, 0.27, 0.28, 0.30, 0.32, 0.34, 0.36, 0.38, 0.40, 0.42,
- 0.44, 0.46, 0.48, 0.5, 0.53, 0.56, 0.59, 0.62, 0.65, 0.68,
- 0.71, 0.74, 0.77, 0.80, 0.83, 0.86, 0.89, 0.92, 0.95, 0.98,
- 1.0, 1.06, 1.12, 1.18, 1.24, 1.30, 1.36, 1.42, 1.48, 1.54,
- 1.60, 1.66, 1.72, 1.78, 1.84, 1.90, 1.96, 2.0, 2.12, 2.25,
- 2.37, 2.50, 2.62, 2.75, 2.87, 3.0, 3.2, 3.4, 3.6, 3.8,
- 4.0, 4.3, 4.7, 4.9, 5.0, 5.5, 6.0, 6.5, 6.8, 7.0,
- 7.3, 7.5, 7.8, 8.0, 8.4, 8.7, 9.0, 9.4, 9.6, 9.8,
- 10.0)
- percent = clamp(percent, -100, 100)
- if(percent == 0)
- return color_matrix_identity()
-
- var/x = 0
- if (percent < 0)
- x = 127 + percent / 100 * 127;
- else
- x = percent % 1
- if(x == 0)
- x = delta_index[percent]
- else
- x = delta_index[percent] * (1-x) + delta_index[percent+1] * x//use linear interpolation for more granularity.
- x = x * 127 + 127
-
- var/mult = x / 127
- var/add = 0.5 * (127-x) / 255
- return list(mult,0,0, 0,mult,0, 0,0,mult, add,add,add)
-
-/**
- * Moves all colors angle degrees around the color wheel while maintaining intensity of the color and not affecting greys.
- * 0 is identity, 120 moves reds to greens, 240 moves reds to blues.
- */
-//
-//
+//Moves all colors angle degrees around the color wheel while maintaining intensity of the color and not affecting greys
+//0 is identity, 120 moves reds to greens, 240 moves reds to blues
/proc/color_matrix_rotate_hue(angle)
var/sin = sin(angle)
var/cos = cos(angle)
var/cos_inv_third = 0.333*(1-cos)
var/sqrt3_sin = sqrt(3)*sin
return list(
- round(cos+cos_inv_third, 0.001), round(cos_inv_third+sqrt3_sin, 0.001), round(cos_inv_third-sqrt3_sin, 0.001), 0,
- round(cos_inv_third-sqrt3_sin, 0.001), round(cos+cos_inv_third, 0.001), round(cos_inv_third+sqrt3_sin, 0.001), 0,
- round(cos_inv_third+sqrt3_sin, 0.001), round(cos_inv_third-sqrt3_sin, 0.001), round(cos+cos_inv_third, 0.001), 0,
- 0,0,0,1,
- 0,0,0,0,
- )
-
-/**
- * Moves all colors angle degrees around the color wheel while maintaining intensity of the color and not affecting whites.
- * TODO: Need a version that only affects one color (ie shift red to blue but leave greens and blues alone)
- */
-/proc/color_matrix_rotation(angle)
- if(angle == 0)
- return color_matrix_identity()
- angle = clamp(angle, -180, 180)
- var/cos = cos(angle)
- var/sin = sin(angle)
-
- var/constA = 0.143
- var/constB = 0.140
- var/constC = -0.283
- return list(
- LUMA_R + cos * (1-LUMA_R) + sin * -LUMA_R, LUMA_R + cos * -LUMA_R + sin * constA, LUMA_R + cos * -LUMA_R + sin * -(1-LUMA_R),
- LUMA_G + cos * -LUMA_G + sin * -LUMA_G, LUMA_G + cos * (1-LUMA_G) + sin * constB, LUMA_G + cos * -LUMA_G + sin * LUMA_G,
- LUMA_B + cos * -LUMA_B + sin * (1-LUMA_B), LUMA_B + cos * -LUMA_B + sin * constC, LUMA_B + cos * (1-LUMA_B) + sin * LUMA_B
- )
-
-/**
- * These next three rotate values about one axis only.
- * x is the red axis, y is the green axis, z is the blue axis.
- */
+round(cos+cos_inv_third, 0.001), round(cos_inv_third+sqrt3_sin, 0.001), round(cos_inv_third-sqrt3_sin, 0.001), 0,
+round(cos_inv_third-sqrt3_sin, 0.001), round(cos+cos_inv_third, 0.001), round(cos_inv_third+sqrt3_sin, 0.001), 0,
+round(cos_inv_third+sqrt3_sin, 0.001), round(cos_inv_third-sqrt3_sin, 0.001), round(cos+cos_inv_third, 0.001), 0,
+0,0,0,1,
+0,0,0,0)
+
+//These next three rotate values about one axis only
+//x is the red axis, y is the green axis, z is the blue axis.
/proc/color_matrix_rotate_x(angle)
- var/sinval = round(sin(angle), 0.001)
- var/cosval = round(cos(angle), 0.001)
+ var/sinval = round(sin(angle), 0.001); var/cosval = round(cos(angle), 0.001)
return list(1,0,0,0, 0,cosval,sinval,0, 0,-sinval,cosval,0, 0,0,0,1, 0,0,0,0)
/proc/color_matrix_rotate_y(angle)
- var/sinval = round(sin(angle), 0.001)
- var/cosval = round(cos(angle), 0.001)
+ var/sinval = round(sin(angle), 0.001); var/cosval = round(cos(angle), 0.001)
return list(cosval,0,-sinval,0, 0,1,0,0, sinval,0,cosval,0, 0,0,0,1, 0,0,0,0)
/proc/color_matrix_rotate_z(angle)
- var/sinval = round(sin(angle), 0.001)
- var/cosval = round(cos(angle), 0.001)
+ var/sinval = round(sin(angle), 0.001); var/cosval = round(cos(angle), 0.001)
return list(cosval,sinval,0,0, -sinval,cosval,0,0, 0,0,1,0, 0,0,0,1, 0,0,0,0)
-/**
- * Builds a color matrix that transforms the hue, saturation, and value, all in one operation.
- */
-/proc/color_matrix_hsv(hue, saturation, value)
- hue = clamp(360 - hue, 0, 360)
-
- // This is very much a rough approximation of hueshifting. This carries some artifacting, such as negative values that simply shouldn't exist, but it does get the job done, and that's what matters.
- var/cos_a = cos(hue) // These have to be inverted from 360, otherwise the hue's inverted
- var/sin_a = sin(hue)
- var/rot_x = cos_a + (1 - cos_a) / 3
- var/rot_y = (1 - cos_a) / 3 - 0.5774 * sin_a // 0.5774 is sqrt(1/3)
- var/rot_z = (1 - cos_a) / 3 + 0.5774 * sin_a
-
- return list(
- round((((1-saturation) * LUMA_R) + (rot_x * saturation)) * value, 0.01), round((((1-saturation) * LUMA_R) + (rot_y * saturation)) * value, 0.01), round((((1-saturation) * LUMA_R) + (rot_z * saturation)) * value, 0.01),
- round((((1-saturation) * LUMA_G) + (rot_z * saturation)) * value, 0.01), round((((1-saturation) * LUMA_G) + (rot_x * saturation)) * value, 0.01), round((((1-saturation) * LUMA_G) + (rot_y * saturation)) * value, 0.01),
- round((((1-saturation) * LUMA_B) + (rot_y * saturation)) * value, 0.01), round((((1-saturation) * LUMA_B) + (rot_z * saturation)) * value, 0.01), round((((1-saturation) * LUMA_B) + (rot_x * saturation)) * value, 0.01),
- 0, 0, 0
- )
-/**
- * Returns a matrix addition of A with B.
- */
+//Returns a matrix addition of A with B
/proc/color_matrix_add(list/A, list/B)
if(!istype(A) || !istype(B))
- return color_matrix_identity()
+ return COLOR_MATRIX_IDENTITY
if(A.len != 20 || B.len != 20)
- return color_matrix_identity()
+ return COLOR_MATRIX_IDENTITY
var/list/output = list()
output.len = 20
for(var/value in 1 to 20)
output[value] = A[value] + B[value]
return output
+//Returns a matrix multiplication of A with B
+/proc/color_matrix_multiply(list/A, list/B)
+ if(!istype(A) || !istype(B))
+ return COLOR_MATRIX_IDENTITY
+ if(A.len != 20 || B.len != 20)
+ return COLOR_MATRIX_IDENTITY
+ var/list/output = list()
+ output.len = 20
+ var/x = 1
+ var/y = 1
+ var/offset = 0
+ for(y in 1 to 5)
+ offset = (y-1)*4
+ for(x in 1 to 4)
+ output[offset+x] = round(A[offset+1]*B[x] + A[offset+2]*B[x+4] + A[offset+3]*B[x+8] + A[offset+4]*B[x+12]+(y == 5?B[x+16]:0), 0.001)
+ return output
+
+/**
+ * Converts RGB shorthands into RGBA matrices complete of constants rows (ergo a 20 keys list in byond).
+ * if return_identity_on_fail is true, stack_trace is called instead of CRASH, and an identity is returned.
+ */
+/proc/color_to_full_rgba_matrix(color, return_identity_on_fail = TRUE)
+ if(!color)
+ return COLOR_MATRIX_IDENTITY
+ if(istext(color))
+ var/list/L = rgb2num(color)
+ if(!L)
+ var/message = "Invalid/unsupported color ([color]) argument in color_to_full_rgba_matrix()"
+ if(return_identity_on_fail)
+ stack_trace(message)
+ return COLOR_MATRIX_IDENTITY
+ CRASH(message)
+ return list(L[1]/255,0,0,0, 0,L[2]/255,0,0, 0,0,L[3]/255,0, 0,0,0,L.len>3?L[4]/255:1, 0,0,0,0)
+ if(!islist(color)) //invalid format
+ CRASH("Invalid/unsupported color ([color]) argument in color_to_full_rgba_matrix()")
+ var/list/L = color
+ switch(L.len)
+ if(3 to 5) // row-by-row hexadecimals
+ . = list()
+ for(var/a in 1 to L.len)
+ var/list/rgb = rgb2num(L[a])
+ for(var/b in rgb)
+ . += b/255
+ if(length(rgb) % 4) // RGB has no alpha instruction
+ . += a != 4 ? 0 : 1
+ if(L.len < 4) //missing both alphas and constants rows
+ . += list(0,0,0,1, 0,0,0,0)
+ else if(L.len < 5) //missing constants row
+ . += list(0,0,0,0)
+ if(9 to 12) //RGB
+ . = list(L[1],L[2],L[3],0, L[4],L[5],L[6],0, L[7],L[8],L[9],0, 0,0,0,1)
+ for(var/b in 1 to 3) //missing constants row
+ . += L.len < 9+b ? 0 : L[9+b]
+ . += 0
+ if(16 to 20) // RGBA
+ . = L.Copy()
+ if(L.len < 20) //missing constants row
+ for(var/b in 1 to 20-L.len)
+ . += 0
+ else
+ var/message = "Invalid/unsupported color (list of length [L.len]) argument in color_to_full_rgba_matrix()"
+ if(return_identity_on_fail)
+ stack_trace(message)
+ return COLOR_MATRIX_IDENTITY
+ CRASH(message)
+
+//! legacy
+
/**
* Force a matrix to be a full 20 value rgba matrix.
*/
@@ -217,37 +155,28 @@ list(0.393,0.349,0.272,0, 0.769,0.686,0.534,0, 0.189,0.168,0.131,0, 0,0,0,1, 0,0
if(16) // rgba without constant
expanding.Insert(17, 0, 0, 0, 0) // inject cr to ca
else
- . = color_matrix_identity()
+ . = COLOR_MATRIX_IDENTITY
CRASH("what?")
/**
- * Returns a matrix multiplication of A with B.
- *
- * todo: support rgb instead of rgba.
+ * Builds a color matrix that transforms the hue, saturation, and value, all in one operation.
*/
-/proc/color_matrix_multiply(list/A, list/B)
- if(!istype(A) || !istype(B))
- return color_matrix_identity()
- if(A.len < 20)
- A = color_matrix_expand(A)
- if(B.len < 20)
- B = color_matrix_expand(B)
- var/list/output = list()
- output.len = 20
- var/x = 1
- var/y = 1
- var/offset = 0
- for(y in 1 to 5)
- offset = (y-1)*4
- for(x in 1 to 4)
- output[offset+x] = round(A[offset+1]*B[x] + A[offset+2]*B[x+4] + A[offset+3]*B[x+8] + A[offset+4]*B[x+12]+(y==5?B[x+16]:0), 0.001)
- return output
+/proc/color_matrix_hsv(hue, saturation, value)
+ hue = clamp(360 - hue, 0, 360)
-/**
- * Assembles a color matrix, defaulting to identity.
- */
-/proc/construct_rgb_color_matrix(rr = 1, rg = 0, rb = 0, gr = 0, gg = 1, gb = 0, br = 0, bg = 0, bb = 1, cr = 0, cg = 0, cb = 0)
- return list(rr, rg, rb, gr, gg, gb, br, bg, bb, cr, cg, cb)
+ // This is very much a rough approximation of hueshifting. This carries some artifacting, such as negative values that simply shouldn't exist, but it does get the job done, and that's what matters.
+ var/cos_a = cos(hue) // These have to be inverted from 360, otherwise the hue's inverted
+ var/sin_a = sin(hue)
+ var/rot_x = cos_a + (1 - cos_a) / 3
+ var/rot_y = (1 - cos_a) / 3 - 0.5774 * sin_a // 0.5774 is sqrt(1/3)
+ var/rot_z = (1 - cos_a) / 3 + 0.5774 * sin_a
+
+ return list(
+ round((((1-saturation) * LUMA_R) + (rot_x * saturation)) * value, 0.01), round((((1-saturation) * LUMA_R) + (rot_y * saturation)) * value, 0.01), round((((1-saturation) * LUMA_R) + (rot_z * saturation)) * value, 0.01),
+ round((((1-saturation) * LUMA_G) + (rot_z * saturation)) * value, 0.01), round((((1-saturation) * LUMA_G) + (rot_x * saturation)) * value, 0.01), round((((1-saturation) * LUMA_G) + (rot_y * saturation)) * value, 0.01),
+ round((((1-saturation) * LUMA_B) + (rot_y * saturation)) * value, 0.01), round((((1-saturation) * LUMA_B) + (rot_z * saturation)) * value, 0.01), round((((1-saturation) * LUMA_B) + (rot_x * saturation)) * value, 0.01),
+ 0, 0, 0
+ )
/**
* Assembles a color matrix, defaulting to identity.
@@ -256,23 +185,10 @@ list(0.393,0.349,0.272,0, 0.769,0.686,0.534,0, 0.189,0.168,0.131,0, 0,0,0,1, 0,0
return list(rr, rg, rb, ra, gr, gg, gb, ga, br, bg, bb, ba, ar, ag, ab, aa, cr, cg, cb, ca)
/**
- * Assemble a color matrix from a rgb(a) string.
+ * Assembles a color matrix, defaulting to identity.
*/
-/proc/color_matrix_from_rgb(color)
- var/list/L1 = ReadRGB(color)
- if(length(L1) == 3) // rgb
- return construct_rgb_color_matrix(
- rr = L1[1] / 255,
- gg = L1[2] / 255,
- bb = L1[3] / 255,
- )
- else // rgba
- return construct_rgba_color_matrix(
- rr = L1[1] / 255,
- gg = L1[2] / 255,
- bb = L1[3] / 255,
- aa = L1[4] / 255,
- )
+/proc/construct_rgb_color_matrix(rr = 1, rg = 0, rb = 0, gr = 0, gg = 1, gb = 0, br = 0, bg = 0, bb = 1, cr = 0, cg = 0, cb = 0)
+ return list(rr, rg, rb, gr, gg, gb, br, bg, bb, cr, cg, cb)
/**
* Constructs a colored greyscale matrix.
@@ -280,6 +196,6 @@ list(0.393,0.349,0.272,0, 0.769,0.686,0.534,0, 0.189,0.168,0.131,0, 0,0,0,1, 0,0
*/
/proc/rgba_auto_greyscale_matrix(rgba_string)
return color_matrix_multiply(
- color_matrix_greyscale(),
- color_matrix_from_rgb(rgba_string)
+ COLOR_MATRIX_GRAYSCALE,
+ color_to_full_rgba_matrix(rgba_string)
)
diff --git a/code/__HELPERS/matrices/transform_matrix.dm b/code/__HELPERS/matrices/transform_matrix.dm
index b36b94a7d7e9..51288a51b7de 100644
--- a/code/__HELPERS/matrices/transform_matrix.dm
+++ b/code/__HELPERS/matrices/transform_matrix.dm
@@ -1,8 +1,51 @@
+/// Datum which stores information about a matrix decomposed with decompose().
+/datum/decompose_matrix
+ ///?
+ var/scale_x = 1
+ ///?
+ var/scale_y = 1
+ ///?
+ var/rotation = 0
+ ///?
+ var/shift_x = 0
+ ///?
+ var/shift_y = 0
+
+/// Decomposes a matrix into scale, shift and rotation.
+///
+/// If other operations were applied on the matrix, such as shearing, the result
+/// will not be precise.
+///
+/// Negative scales are now supported. =)
+/matrix/proc/decompose()
+ var/datum/decompose_matrix/decompose_matrix = new
+ . = decompose_matrix
+ var/flip_sign = (a*e - b*d < 0)? -1 : 1 // Det < 0 => only 1 axis is flipped - start doing some sign flipping
+ // If both axis are flipped, nothing bad happens and Det >= 0, it just treats it like a 180° rotation
+ // If only 1 axis is flipped, we need to flip one direction - in this case X, so we flip a, b and the x scaling
+ decompose_matrix.scale_x = sqrt(a * a + d * d) * flip_sign
+ decompose_matrix.scale_y = sqrt(b * b + e * e)
+ decompose_matrix.shift_x = c
+ decompose_matrix.shift_y = f
+ if(!decompose_matrix.scale_x || !decompose_matrix.scale_y)
+ return
+ // If only translated, scaled and rotated, a/xs == e/ys and -d/xs == b/xy
+ var/cossine = (a/decompose_matrix.scale_x + e/decompose_matrix.scale_y) / 2
+ var/sine = (b/decompose_matrix.scale_y - d/decompose_matrix.scale_x) / 2 * flip_sign
+ decompose_matrix.rotation = arctan(cossine, sine) * flip_sign
+
/matrix/proc/TurnTo(old_angle, new_angle)
- . = new_angle - old_angle
- Turn(.) //BYOND handles cases such as -270, 360, 540 etc. DOES NOT HANDLE 180 TURNS WELL, THEY TWEEN AND LOOK LIKE SHIT
+ return Turn(new_angle - old_angle) //BYOND handles cases such as -270, 360, 540 etc. DOES NOT HANDLE 180 TURNS WELL, THEY TWEEN AND LOOK LIKE SHIT
-/atom/proc/SpinAnimation(speed = 10, loops = -1, clockwise = 1, segments = 3, parallel = TRUE)
+/**
+ * Shear the transform on either or both axes.
+ * * x - X axis shearing
+ * * y - Y axis shearing
+ */
+/matrix/proc/Shear(x, y)
+ return Multiply(matrix(1, x, 0, y, 1, 0))
+
+/atom/proc/SpinAnimation(speed = 1 SECONDS, loops = -1, clockwise = 1, segments = 3, parallel = TRUE)
if(!segments)
return
var/segment = 360/segments
@@ -28,9 +71,8 @@
//doesn't have an object argument because this is "Stacking" with the animate call above
//3 billion% intentional
-/**
- * Dumps the matrix data in format a-f.
- */
+
+//Dumps the matrix data in format a-f
/matrix/proc/tolist()
. = list()
. += a
@@ -40,13 +82,12 @@
. += e
. += f
-/**
- * Dumps the matrix data in a matrix-grid format.
- *
- * a d 0
- * b e 0
- * c f 1
- */
+//Dumps the matrix data in a matrix-grid format
+/*
+a d 0
+b e 0
+c f 1
+*/
/matrix/proc/togrid()
. = list()
. += a
@@ -59,15 +100,12 @@
. += f
. += 1
-/**
- * The X pixel offset of this matrix.
- */
+
+///The X pixel offset of this matrix
/matrix/proc/get_x_shift()
. = c
-/**
- * The Y pixel offset of this matrix.
- */
+///The Y pixel offset of this matrix
/matrix/proc/get_y_shift()
. = f
diff --git a/code/__HELPERS/sorts/comparators.dm b/code/__HELPERS/sorts/comparators.dm
index 0214226acb59..ace8dd066988 100644
--- a/code/__HELPERS/sorts/comparators.dm
+++ b/code/__HELPERS/sorts/comparators.dm
@@ -210,3 +210,6 @@ GLOBAL_VAR_INIT(cmp_field, "name")
/proc/cmp_planelayer(atom/A, atom/B)
return (B.plane - A.plane) || (B.layer - A.layer)
+
+/proc/cmp_typepaths_asc(A, B)
+ return sorttext("[B]","[A]")
diff --git a/code/__HELPERS/type2type/color.dm b/code/__HELPERS/type2type/color.dm
index eb3d3e315048..71a4644b0e4e 100644
--- a/code/__HELPERS/type2type/color.dm
+++ b/code/__HELPERS/type2type/color.dm
@@ -142,7 +142,7 @@
/proc/color_hex2color_matrix(string)
var/length = length(string)
if((length != 7 && length != 9) || length != length_char(string))
- return color_matrix_identity()
+ return COLOR_MATRIX_IDENTITY
var/r = hex2num(copytext(string, 2, 4)) / 255
var/g = hex2num(copytext(string, 4, 6)) / 255
var/b = hex2num(copytext(string, 6, 8)) / 255
@@ -150,7 +150,7 @@
if(length == 9)
a = hex2num(copytext(string, 8, 10)) / 255
if(!isnum(r) || !isnum(g) || !isnum(b) || !isnum(a))
- return color_matrix_identity()
+ return COLOR_MATRIX_IDENTITY
return list(
r,0,0,0,0,
g,0,0,0,0,
diff --git a/code/__HELPERS/vfx/appearance_cloning.dm b/code/__HELPERS/vfx/appearance_cloning.dm
index 1d437be29f32..fc9f8148759f 100644
--- a/code/__HELPERS/vfx/appearance_cloning.dm
+++ b/code/__HELPERS/vfx/appearance_cloning.dm
@@ -25,7 +25,7 @@
* clones us as a high-resolution greyscale
*/
/atom/proc/vfx_clone_as_greyscale(alpha = 127)
- var/static/list/static_greyscale_matrix = color_matrix_greyscale()
+ var/static/list/static_greyscale_matrix = COLOR_MATRIX_GRAYSCALE
var/mutable_appearance/MA = new
MA.appearance = src
MA.color = static_greyscale_matrix
diff --git a/code/controllers/subsystem/atoms.dm b/code/controllers/subsystem/atoms.dm
index dec55fa76c4a..74ebf6cd6021 100644
--- a/code/controllers/subsystem/atoms.dm
+++ b/code/controllers/subsystem/atoms.dm
@@ -1,97 +1,126 @@
-#define BAD_INIT_QDEL_BEFORE 1
-#define BAD_INIT_DIDNT_INIT 2
-#define BAD_INIT_SLEPT 4
-#define BAD_INIT_NO_HINT 8
-
SUBSYSTEM_DEF(atoms)
name = "Atoms"
init_order = INIT_ORDER_ATOMS
subsystem_flags = SS_NO_FIRE
- var/old_subsystem_initialized
+ /// A stack of list(source, desired initialized state)
+ /// We read the source of init changes from the last entry, and assert that all changes will come with a reset
+ var/list/initialized_state = list()
+ var/base_initialized
var/list/late_loaders = list()
var/list/BadInitializeCalls = list()
+ ///initAtom() adds the atom its creating to this list iff InitializeAtoms() has been given a list to populate as an argument
+ var/list/created_atoms
+
+ /// Atoms that will be deleted once the subsystem is initialized
+ var/list/queued_deletions = list()
+
+ var/init_start_time
+
+ #ifdef PROFILE_MAPLOAD_INIT_ATOM
+ var/list/mapload_init_times = list()
+ #endif
+
+ initialized = INITIALIZATION_INSSATOMS
+
/datum/controller/subsystem/atoms/Initialize(timeofday)
- //GLOB.fire_overlay.appearance_flags = RESET_COLOR
- //setupGenetics() //to set the mutations' sequence
+ init_start_time = world.time
+
initialized = INITIALIZATION_INNEW_MAPLOAD
InitializeAtoms()
+ initialized = INITIALIZATION_INNEW_REGULAR
+
return ..()
-/datum/controller/subsystem/atoms/proc/InitializeAtoms(list/atoms)
+/datum/controller/subsystem/atoms/proc/InitializeAtoms(list/atoms, list/atoms_to_return)
if(initialized == INITIALIZATION_INSSATOMS)
return
- initialized = INITIALIZATION_INNEW_MAPLOAD
-
- LAZYINITLIST(late_loaders)
+ // Generate a unique mapload source for this run of InitializeAtoms
+ var/static/uid = 0
+ uid = (uid + 1) % (SHORT_REAL_LIMIT - 1)
+ var/source = "subsystem init [uid]"
+ set_tracked_initalized(INITIALIZATION_INNEW_MAPLOAD, source)
- var/count
- var/list/mapload_arg = list(TRUE)
- if(atoms)
- count = atoms.len
- for(var/I in atoms)
- var/atom/A = I
- if(!(A.atom_flags & ATOM_INITIALIZED))
- InitAtom(I, mapload_arg)
- CHECK_TICK
- else
- count = 0
- for(var/atom/A in world)
- if(!(A.atom_flags & ATOM_INITIALIZED))
- InitAtom(A, mapload_arg)
- ++count
- CHECK_TICK
-
- testing("Initialized [count] atoms")
- pass(count)
-
- initialized = INITIALIZATION_INNEW_REGULAR
+ // This may look a bit odd, but if the actual atom creation runtimes for some reason, we absolutely need to set initialized BACK
+ CreateAtoms(atoms, atoms_to_return, source)
+ clear_tracked_initalize(source)
if(late_loaders.len)
- for(var/I in late_loaders)
- var/atom/A = I
+ for(var/I in 1 to late_loaders.len)
+ var/atom/A = late_loaders[I]
+ //I hate that we need this
+ if(QDELETED(A))
+ continue
A.LateInitialize()
testing("Late initialized [late_loaders.len] atoms")
late_loaders.Cut()
-/datum/controller/subsystem/atoms/proc/InitAtom(atom/A, list/arguments)
- var/the_type = A.type
- if(QDELING(A))
- BadInitializeCalls[the_type] |= BAD_INIT_QDEL_BEFORE
- return TRUE
+ if (created_atoms)
+ atoms_to_return += created_atoms
+ created_atoms = null
+
+ for (var/queued_deletion in queued_deletions)
+ qdel(queued_deletion)
- var/start_tick = world.time
+ testing("[queued_deletions.len] atoms were queued for deletion.")
+ queued_deletions.Cut()
- var/result = A.Initialize(arglist(arguments))
+ #ifdef PROFILE_MAPLOAD_INIT_ATOM
+ rustg_file_write(json_encode(mapload_init_times), "[GLOB.log_directory]/init_times.json")
+ #endif
- if(start_tick != world.time)
- BadInitializeCalls[the_type] |= BAD_INIT_SLEPT
+/// Actually creates the list of atoms. Exists solely so a runtime in the creation logic doesn't cause initialized to totally break
+/datum/controller/subsystem/atoms/proc/CreateAtoms(list/atoms, list/atoms_to_return = null, mapload_source = null)
+ if (atoms_to_return)
+ LAZYINITLIST(created_atoms)
- var/qdeleted = FALSE
+ #ifdef TESTING
+ var/count
+ #endif
+
+ var/list/mapload_arg = list(TRUE)
- if(result != INITIALIZE_HINT_NORMAL)
- switch(result)
- if(INITIALIZE_HINT_LATELOAD)
- if(arguments[1]) //mapload
- late_loaders += A
- else
- A.LateInitialize()
- if(INITIALIZE_HINT_QDEL)
- qdel(A)
- qdeleted = TRUE
- else
- BadInitializeCalls[the_type] |= BAD_INIT_NO_HINT
+ if(atoms)
+ #ifdef TESTING
+ count = atoms.len
+ #endif
+
+ for(var/I in 1 to atoms.len)
+ var/atom/A = atoms[I]
+ if(!(A.atom_flags & ATOM_INITIALIZED))
+ // Unrolled CHECK_TICK setup to let us enable/disable mapload based off source
+ if(TICK_CHECK)
+ clear_tracked_initalize(mapload_source)
+ stoplag()
+ if(mapload_source)
+ set_tracked_initalized(INITIALIZATION_INNEW_MAPLOAD, mapload_source)
+ PROFILE_INIT_ATOM_BEGIN()
+ InitAtom(A, TRUE, mapload_arg)
+ PROFILE_INIT_ATOM_END(A)
+ else
+ #ifdef TESTING
+ count = 0
+ #endif
- if(!A) //possible harddel
- qdeleted = TRUE
- else if(!(A.atom_flags & ATOM_INITIALIZED))
- BadInitializeCalls[the_type] |= BAD_INIT_DIDNT_INIT
+ for(var/atom/A as anything in world)
+ if(!(A.atom_flags & ATOM_INITIALIZED))
+ PROFILE_INIT_ATOM_BEGIN()
+ InitAtom(A, FALSE, mapload_arg)
+ PROFILE_INIT_ATOM_END(A)
+ #ifdef TESTING
+ ++count
+ #endif
+ if(TICK_CHECK)
+ clear_tracked_initalize(mapload_source)
+ stoplag()
+ if(mapload_source)
+ set_tracked_initalized(INITIALIZATION_INNEW_MAPLOAD, mapload_source)
- return qdeleted || QDELING(A)
+ testing("Initialized [count] atoms")
/**
* immediately creates and inits an atom
@@ -109,12 +138,44 @@ SUBSYSTEM_DEF(atoms)
initialized = old_initialized
return created
-/datum/controller/subsystem/atoms/proc/map_loader_begin()
- old_subsystem_initialized = initialized
- initialized = INITIALIZATION_INSSATOMS
+/datum/controller/subsystem/atoms/proc/map_loader_begin(source)
+ set_tracked_initalized(INITIALIZATION_INSSATOMS, source)
+
+/datum/controller/subsystem/atoms/proc/map_loader_stop(source)
+ clear_tracked_initalize(source)
+
+/// Returns the source currently modifying SSatom's init behavior
+/datum/controller/subsystem/atoms/proc/get_initialized_source()
+ var/state_length = length(initialized_state)
+ if(!state_length)
+ return null
+ return initialized_state[state_length][1]
+
+/// Use this to set initialized to prevent error states where the old initialized is overridden, and we end up losing all context
+/// Accepts a state and a source, the most recent state is used, sources exist to prevent overriding old values accidentally
+/datum/controller/subsystem/atoms/proc/set_tracked_initalized(state, source)
+ if(!length(initialized_state))
+ base_initialized = initialized
+ initialized_state += list(list(source, state))
+ initialized = state
+
+/datum/controller/subsystem/atoms/proc/clear_tracked_initalize(source)
+ if(!length(initialized_state))
+ return
+ for(var/i in length(initialized_state) to 1 step -1)
+ if(initialized_state[i][1] == source)
+ initialized_state.Cut(i, i+1)
+ break
+
+ if(!length(initialized_state))
+ initialized = base_initialized
+ base_initialized = INITIALIZATION_INNEW_REGULAR
+ return
+ initialized = initialized_state[length(initialized_state)][2]
-/datum/controller/subsystem/atoms/proc/map_loader_stop()
- initialized = old_subsystem_initialized
+/// Returns TRUE if anything is currently being initialized
+/datum/controller/subsystem/atoms/proc/initializing_something()
+ return length(initialized_state) > 1
/datum/controller/subsystem/atoms/proc/init_map_bounds(list/bounds)
if (initialized == INITIALIZATION_INSSATOMS)
@@ -165,51 +226,36 @@ SUBSYSTEM_DEF(atoms)
admin_notice("Submap initializations finished.", R_DEBUG)
+
/datum/controller/subsystem/atoms/Recover()
initialized = SSatoms.initialized
if(initialized == INITIALIZATION_INNEW_MAPLOAD)
InitializeAtoms()
- old_subsystem_initialized = SSatoms.old_subsystem_initialized
+ initialized_state = SSatoms.initialized_state
BadInitializeCalls = SSatoms.BadInitializeCalls
-/*
-/datum/controller/subsystem/atoms/proc/setupGenetics()
- var/list/mutations = subtypesof(/datum/mutation/human)
- shuffle_inplace(mutations)
- for(var/A in subtypesof(/datum/generecipe))
- var/datum/generecipe/GR = A
- GLOB.mutation_recipes[initial(GR.required)] = initial(GR.result)
- for(var/i in 1 to LAZYLEN(mutations))
- var/path = mutations[i] //byond gets pissy when we do it in one line
- var/datum/mutation/human/B = new path ()
- B.alias = "Mutation #[i]"
- GLOB.all_mutations[B.type] = B
- GLOB.full_sequences[B.type] = generate_gene_sequence(B.blocks)
- if(B.locked)
- continue
- if(B.quality == POSITIVE)
- GLOB.good_mutations |= B
- else if(B.quality == NEGATIVE)
- GLOB.bad_mutations |= B
- else if(B.quality == MINOR_NEGATIVE)
- GLOB.not_good_mutations |= B
- CHECK_TICK
-*/
-
/datum/controller/subsystem/atoms/proc/InitLog()
. = ""
for(var/path in BadInitializeCalls)
. += "Path : [path] \n"
var/fails = BadInitializeCalls[path]
if(fails & BAD_INIT_DIDNT_INIT)
- . += "- Didn't call atom/Initialize()\n"
+ . += "- Didn't call atom/Initialize(mapload)\n"
if(fails & BAD_INIT_NO_HINT)
. += "- Didn't return an Initialize hint\n"
if(fails & BAD_INIT_QDEL_BEFORE)
- . += "- Qdel'd in New()\n"
+ . += "- Qdel'd before Initialize proc ran\n"
if(fails & BAD_INIT_SLEPT)
. += "- Slept during Initialize()\n"
+/// Prepares an atom to be deleted once the atoms SS is initialized.
+/datum/controller/subsystem/atoms/proc/prepare_deletion(atom/target)
+ if (initialized == INITIALIZATION_INNEW_REGULAR)
+ // Atoms SS has already completed, just kill it now.
+ qdel(target)
+ else
+ queued_deletions += WEAKREF(target)
+
/datum/controller/subsystem/atoms/Shutdown()
var/initlog = InitLog()
if(initlog)
diff --git a/code/datums/holograms/hologram.dm b/code/datums/holograms/hologram.dm
index eeeef5374ad5..536f0b17a6f4 100644
--- a/code/datums/holograms/hologram.dm
+++ b/code/datums/holograms/hologram.dm
@@ -57,10 +57,10 @@ GLOBAL_LIST_INIT(holograms, __init_holograms())
/datum/hologram/proc/render_greyscale(cheap, alpha = 140 / 255)
if(cheap)
var/mutable_appearance/rendering = make_hologram_appearance(image(icon = icon, icon_state = icon_state), alpha)
- rendering.color = color_matrix_greyscale()
+ rendering.color = COLOR_MATRIX_GRAYSCALE
return rendering
else
var/icon/rendering = render_hologram_icon(image(icon = icon, icon_state = icon_state), alpha)
- rendering.MapColors(arglist(color_matrix_greyscale()))
+ rendering.MapColors(arglist(COLOR_MATRIX_GRAYSCALE))
return rendering
diff --git a/code/game/atoms/atom.dm b/code/game/atoms/_atom.dm
similarity index 88%
rename from code/game/atoms/atom.dm
rename to code/game/atoms/_atom.dm
index d01dc169e376..0bdec7cb8c73 100644
--- a/code/game/atoms/atom.dm
+++ b/code/game/atoms/_atom.dm
@@ -205,128 +205,6 @@
/// Default sound played on a burn type impact. This is usually null for default.
var/hit_sound_burn
-/proc/lint__check_atom_new_doesnt_sleep()
- SHOULD_NOT_SLEEP(TRUE)
- var/atom/target
- target.New()
-
-/**
- * Called when an atom is created in byond (built in engine proc)
- *
- * Not a lot happens here in SS13 code, as we offload most of the work to the
- * [Intialization][/atom/proc/Initialize] proc, mostly we run the preloader
- * if the preloader is being used and then call [InitAtom][/datum/controller/subsystem/atoms/proc/InitAtom] of which the ultimate
- * result is that the Intialize proc is called.
- *
- * We also generate a tag here if the DF_USE_TAG flag is set on the atom
- */
-/atom/New(loc, ...)
- // atom creation method that preloads variables at creation
- // todo: we shouldn't need a type check here.
- if(global.dmm_preloader_active && global.dmm_preloader_target == type)
- world.preloader_load(src)
-
- if(datum_flags & DF_USE_TAG)
- generate_tag()
-
- var/do_initialize = SSatoms.initialized
- if(do_initialize != INITIALIZATION_INSSATOMS)
- args[1] = do_initialize == INITIALIZATION_INNEW_MAPLOAD
- if(SSatoms.InitAtom(src, args))
- //we were deleted
- return
-
-/**
- * Called by the maploader if a dmm_context is set
- */
-/atom/proc/preloading_instance(datum/dmm_context/context)
- return
-
-/**
- * hook for abstract direction sets from the maploader
- *
- * return FALSE to override maploader automatic rotation
- */
-/atom/proc/preloading_dir(datum/dmm_context/context)
- return TRUE
-
-/**
- * The primary method that objects are setup in SS13 with
- *
- * we don't use New as we have better control over when this is called and we can choose
- * to delay calls or hook other logic in and so forth
- *
- * During roundstart map parsing, atoms are queued for intialization in the base atom/New(),
- * After the map has loaded, then Initalize is called on all atoms one by one. NB: this
- * is also true for loading map templates as well, so they don't Initalize until all objects
- * in the map file are parsed and present in the world
- *
- * If you're creating an object at any point after SSInit has run then this proc will be
- * immediately be called from New.
- *
- * mapload: This parameter is true if the atom being loaded is either being intialized during
- * the Atom subsystem intialization, or if the atom is being loaded from the map template.
- * If the item is being created at runtime any time after the Atom subsystem is intialized then
- * it's false.
- *
- * The mapload argument occupies the same position as loc when Initialize() is called by New().
- * loc will no longer be needed after it passed New(), and thus it is being overwritten
- * with mapload at the end of atom/New() before this proc (atom/Initialize()) is called.
- *
- * You must always call the parent of this proc, otherwise failures will occur as the item
- * will not be seen as initalized (this can lead to all sorts of strange behaviour, like
- * the item being completely unclickable)
- *
- * !Note: Ignore the note below until the first two lines of the proc are uncommented. -Zandario
- * You must not sleep in this proc, or any subprocs
- *
- * Any parameters from new are passed through (excluding loc), naturally if you're loading from a map
- * there are no other arguments
- *
- * Must return an [initialization hint][INITIALIZE_HINT_NORMAL] or a runtime will occur.
- *
- * !Note: the following functions don't call the base for optimization and must copypasta handling:
- * * [/turf/proc/Initialize]
- */
-/atom/proc/Initialize(mapload, ...)
- SHOULD_NOT_SLEEP(TRUE)
- SHOULD_CALL_PARENT(TRUE)
- if(atom_flags & ATOM_INITIALIZED)
- stack_trace("Warning: [src]([type]) initialized multiple times!")
- atom_flags |= ATOM_INITIALIZED
-
- if (is_datum_abstract())
- log_debug("Abstract atom [type] created!")
- return INITIALIZE_HINT_QDEL
-
- if(loc)
- SEND_SIGNAL(loc, COMSIG_ATOM_INITIALIZED_ON, src) /// Sends a signal that the new atom `src`, has been created at `loc`
-
- if(light_power && light_range)
- update_light()
-
- SETUP_SMOOTHING()
-
- if(opacity && isturf(loc))
- var/turf/T = loc
- T.has_opaque_atom = TRUE // No need to recalculate it in this case, it's guranteed to be on afterwards anyways.
-
- return INITIALIZE_HINT_NORMAL
-
-/**
- * Late Intialization, for code that should run after all atoms have run Intialization
- *
- * To have your LateIntialize proc be called, your atoms [Initalization][/atom/proc/Initialize]
- * proc must return the hint
- * [INITIALIZE_HINT_LATELOAD] otherwise you will never be called.
- *
- * useful for doing things like finding other machines on GLOB.machines because you can guarantee
- * that all atoms will actually exist in the "WORLD" at this time and that all their Intialization
- * code has been run
- */
-/atom/proc/LateInitialize()
- set waitfor = FALSE
-
/**
* Top level of the destroy chain for most atoms
*
@@ -357,6 +235,20 @@
return ..()
+/**
+ * Called by the maploader if a dmm_context is set
+ */
+/atom/proc/preloading_instance(datum/dmm_context/context)
+ return
+
+/**
+ * hook for abstract direction sets from the maploader
+ *
+ * return FALSE to override maploader automatic rotation
+ */
+/atom/proc/preloading_dir(datum/dmm_context/context)
+ return TRUE
+
/atom/proc/reveal_blood()
return
@@ -531,12 +423,13 @@
/atom/proc/relaymove_from_contents(mob/user, direction)
return relaymove(user, direction)
-// Called to set the atom's density and used to add behavior to density changes.
-/atom/proc/set_density(var/new_density)
- if(density == new_density)
- return FALSE
- density = !!new_density // Sanitize to be strictly 0 or 1
- return TRUE
+///Setter for the `density` variable to append behavior related to its changing.
+/atom/proc/set_density(new_value)
+ SHOULD_CALL_PARENT(TRUE)
+ if(density == new_value)
+ return
+ . = density
+ density = new_value
// Called to set the atom's invisibility and usd to add behavior to invisibility changes.
/atom/proc/set_invisibility(var/new_invisibility)
diff --git a/code/game/atoms/vv.dm b/code/game/atoms/atom_vv.dm
similarity index 71%
rename from code/game/atoms/vv.dm
rename to code/game/atoms/atom_vv.dm
index f36655a135e7..4937bb3e97c2 100644
--- a/code/game/atoms/vv.dm
+++ b/code/game/atoms/atom_vv.dm
@@ -1,97 +1,8 @@
/**
- * call back when a var is edited on this atom
- *
- * Can be used to implement special handling of vars
- *
- * At the atom level, if you edit a var named "color" it will add the atom colour with
- * admin level priority to the atom colours list
- *
- * Also, if GLOB.Debug2 is FALSE, it sets the ADMIN_SPAWNED_1 flag on flags_1, which signifies
- * the object has been admin edited
- */
-/atom/vv_edit_var(var_name, var_value, mass_edit, raw_edit)
- if(raw_edit)
- return ..()
-
- switch(var_name)
- if(NAMEOF(src, smoothing_junction))
- set_smoothed_icon_state(var_value)
- . = TRUE
- if(NAMEOF(src, opacity))
- set_opacity(var_value)
- . = TRUE
- if(NAMEOF(src, base_pixel_x))
- set_base_pixel_x(var_value)
- . = TRUE
- if(NAMEOF(src, base_pixel_y))
- set_base_pixel_y(var_value)
- . = TRUE
- if(NAMEOF(src, integrity))
- if(!isnum(var_value))
- return FALSE
- if(var_value > integrity_max)
- integrity_max = var_value
- var_value = max(0, var_value)
- if(integrity_enabled)
- set_integrity(var_value)
- . = TRUE
- if(NAMEOF(src, integrity_failure))
- if(!isnum(var_value) || var_value < 0)
- return FALSE
- if(NAMEOF(src, integrity_max))
- if(!isnum(var_value))
- return FALSE
- var_value = max(0, var_value)
- if(NAMEOF(src, contents))
- var/list/O = contents
- var/list/N = var_value
- for(var/atom/movable/AM in O - N)
- // these go away
- AM.moveToNullspace()
- for(var/atom/movable/AM in N - O)
- // these go in
- AM.forceMove(src)
-
- if(!isnull(.))
- datum_flags |= DF_VAR_EDITED
- return
-
- . = ..()
- if(!.)
- return
-
- switch(var_name)
- if(NAMEOF(src, color))
- add_atom_colour(color, ADMIN_COLOUR_PRIORITY)
- if(NAMEOF(src, base_layer), NAMEOF(src, layer))
- set_base_layer(var_value)
- if(NAMEOF(src, relative_layer))
- set_relative_layer(var_value)
- if(NAMEOF(src, integrity_max))
- integrity = min(integrity_max, integrity)
- if(NAMEOF(src, integrity_failure))
- if(integrity_enabled)
- var/was_failing = integrity_failure >= integrity
- var/now_failing = var_value >= integrity
- if(!was_failing && now_failing)
- atom_break()
- else if(was_failing && !now_failing)
- atom_fix()
-
-/atom/vv_get_var(var_name, resolve)
- switch(var_name)
- if(NAMEOF(src, base_layer))
- if(isnull(base_layer))
- return debug_variable(NAMEOF(src, base_layer), layer, 0, src)
- else
- return debug_variable(NAMEOF(src, base_layer), base_layer, 0, src)
- return ..()
-
-/**
- * Return the markup to for the dropdown list for the VV panel for this atom
- *
- * Override in subtypes to add custom VV handling in the VV panel
- */
+ * Return the markup to for the dropdown list for the VV panel for this atom
+ *
+ * Override in subtypes to add custom VV handling in the VV panel
+ */
/atom/vv_get_dropdown()
. = ..()
VV_DROPDOWN_OPTION("", "---------")
@@ -99,22 +10,30 @@
var/turf/curturf = get_turf(src)
if(curturf)
. += ""
+ VV_DROPDOWN_OPTION(VV_HK_MODIFY_TRANSFORM, "Modify Transform")
+ VV_DROPDOWN_OPTION(VV_HK_SPIN_ANIMATION, "SpinAnimation")
+ VV_DROPDOWN_OPTION(VV_HK_STOP_ALL_ANIMATIONS, "Stop All Animations")
+ // VV_DROPDOWN_OPTION(VV_HK_SHOW_HIDDENPRINTS, "Show Hiddenprint log")
VV_DROPDOWN_OPTION(VV_HK_ADD_REAGENT, "Add Reagent")
- VV_DROPDOWN_OPTION(VV_HK_EDIT_ARMOR, "Edit Armor")
+ VV_DROPDOWN_OPTION(VV_HK_TRIGGER_EMP, "EMP Pulse")
+ VV_DROPDOWN_OPTION(VV_HK_TRIGGER_EXPLOSION, "Explosion")
VV_DROPDOWN_OPTION(VV_HK_EDIT_FILTERS, "Edit Filters")
VV_DROPDOWN_OPTION(VV_HK_EDIT_COLOR_MATRIX, "Edit Color as Matrix")
- VV_DROPDOWN_OPTION(VV_HK_MODIFY_TRANSFORM, "Modify Transform")
- VV_DROPDOWN_OPTION(VV_HK_TRIGGER_EXPLOSION, "Explosion")
- VV_DROPDOWN_OPTION(VV_HK_TRIGGER_EMP, "EMP Pulse")
+ // VV_DROPDOWN_OPTION(VV_HK_TEST_MATRIXES, "Test Matrices")
+ // VV_DROPDOWN_OPTION(VV_HK_ADD_AI, "Add AI controller")
+ VV_DROPDOWN_OPTION(VV_HK_EDIT_ARMOR, "Edit Armor")
/atom/vv_do_topic(list/href_list)
. = ..()
+
+ if(!.)
+ return
+
if(href_list[VV_HK_ADD_REAGENT] && check_rights(R_VAREDIT))
if(!reagents)
var/amount = input(usr, "Specify the reagent size of [src]", "Set Reagent Size", 50) as num|null
if(amount)
create_reagents(amount)
-
if(reagents)
var/chosen_id
switch(alert(usr, "Choose a method.", "Add Reagents", "Search", "Choose from a list", "I'm feeling lucky"))
@@ -133,7 +52,7 @@
if(!valid_id)
to_chat(usr, "A reagent with that ID doesn't exist!")
if("Choose from a list")
- chosen_id = input(usr, "Choose a reagent to add.", "Choose a reagent.") as null|anything in subtypesof(/datum/reagent)
+ chosen_id = input(usr, "Choose a reagent to add.", "Choose a reagent.") as null|anything in sortList(subtypesof(/datum/reagent), GLOBAL_PROC_REF(cmp_typepaths_asc))
if("I'm feeling lucky")
chosen_id = pick(subtypesof(/datum/reagent))
if(chosen_id)
@@ -141,35 +60,84 @@
if(amount)
reagents.add_reagent(chosen_id, amount)
log_admin("[key_name(usr)] has added [amount] units of [chosen_id] to [src]")
- message_admins("[key_name(usr)] has added [amount] units of [chosen_id] to [src]")
+ message_admins(SPAN_NOTICE("[key_name(usr)] has added [amount] units of [chosen_id] to [src]"))
+
if(href_list[VV_HK_TRIGGER_EXPLOSION] && check_rights(R_FUN))
usr.client.cmd_admin_explosion(src)
+
if(href_list[VV_HK_TRIGGER_EMP] && check_rights(R_FUN))
usr.client.cmd_admin_emp(src)
+
if(href_list[VV_HK_MODIFY_TRANSFORM] && check_rights(R_VAREDIT))
- var/result = input(usr, "Choose the transformation to apply","Transform Mod") as null|anything in list("Scale","Translate","Rotate")
+ var/result = input(usr, "Choose the transformation to apply","Transform Mod") as null|anything in list("Scale","Translate","Rotate","Shear")
var/matrix/M = transform
+ if(!result)
+ return
switch(result)
if("Scale")
var/x = input(usr, "Choose x mod","Transform Mod") as null|num
var/y = input(usr, "Choose y mod","Transform Mod") as null|num
- if(!isnull(x) && !isnull(y))
- transform = M.Scale(x,y)
+ if(isnull(x) || isnull(y))
+ return
+ transform = M.Scale(x,y)
if("Translate")
+ var/x = input(usr, "Choose x mod (negative = left, positive = right)","Transform Mod") as null|num
+ var/y = input(usr, "Choose y mod (negative = down, positive = up)","Transform Mod") as null|num
+ if(isnull(x) || isnull(y))
+ return
+ transform = M.Translate(x,y)
+ if("Shear")
var/x = input(usr, "Choose x mod","Transform Mod") as null|num
var/y = input(usr, "Choose y mod","Transform Mod") as null|num
- if(!isnull(x) && !isnull(y))
- transform = M.Translate(x,y)
+ if(isnull(x) || isnull(y))
+ return
+ transform = M.Shear(x,y)
if("Rotate")
var/angle = input(usr, "Choose angle to rotate","Transform Mod") as null|num
- if(!isnull(angle))
- transform = M.Turn(angle)
+ if(isnull(angle))
+ return
+ transform = M.Turn(angle)
+ // SEND_SIGNAL(src, COMSIG_ATOM_VV_MODIFY_TRANSFORM)
+
+ if(href_list[VV_HK_SPIN_ANIMATION])
+ if(!check_rights(R_VAREDIT))
+ return
+ var/num_spins = input(usr, "Do you want infinite spins?", "Spin Animation") in list("Yes", "No")
+ if(num_spins == "No")
+ num_spins = input(usr, "How many spins?", "Spin Animation") as null|num
+ else
+ num_spins = -1
+ if(!num_spins)
+ return
+ var/spin_speed = input(usr, "How fast?", "Spin Animation") as null|num
+ if(!spin_speed)
+ return
+ var/direction = input(usr, "Which direction?", "Spin Animation") in list("Clockwise", "Counter-clockwise")
+ switch(direction)
+ if("Clockwise")
+ direction = 1
+ if("Counter-clockwise")
+ direction = 0
+ else
+ return
+ SpinAnimation(spin_speed, num_spins, direction)
+
+ if(href_list[VV_HK_STOP_ALL_ANIMATIONS])
+ if(!check_rights(R_VAREDIT))
+ return
+ var/result = input(usr, "Are you sure?", "Stop Animating") in list("Yes", "No")
+ if(result == "Yes")
+ animate(src, transform = null, flags = ANIMATION_END_NOW) // Literally just fucking stop animating entirely because admin said so
+ return
+
if(href_list[VV_HK_EDIT_FILTERS] && check_rights(R_VAREDIT))
var/client/C = usr.client
C?.open_filter_editor(src)
+
if(href_list[VV_HK_EDIT_COLOR_MATRIX] && check_rights(R_VAREDIT))
var/client/C = usr.client
C?.open_color_matrix_editor(src)
+
if(href_list[VV_HK_EDIT_ARMOR] && check_rights(R_VAREDIT))
// todo: tgui armor editor?
var/list/pickerlist = list()
@@ -193,3 +161,89 @@
var/refid = REF(src)
. += "[VV_HREF_TARGETREF_1V(refid, VV_HK_BASIC_EDIT, "[src]", NAMEOF(src, name))]"
. += "
<< [dir2text(dir) || dir] >>"
+
+/**
+ * call back when a var is edited on this atom
+ *
+ * Can be used to implement special handling of vars
+ *
+ * At the atom level, if you edit a var named "color" it will add the atom colour with
+ * admin level priority to the atom colours list
+ */
+/atom/vv_edit_var(var_name, var_value, mass_edit, raw_edit)
+ if(raw_edit)
+ return ..()
+
+ switch(var_name)
+ if(NAMEOF(src, smoothing_junction))
+ set_smoothed_icon_state(var_value)
+ . = TRUE
+ if(NAMEOF(src, opacity))
+ set_opacity(var_value)
+ . = TRUE
+ if(NAMEOF(src, base_pixel_x))
+ set_base_pixel_x(var_value)
+ . = TRUE
+ if(NAMEOF(src, base_pixel_y))
+ set_base_pixel_y(var_value)
+ . = TRUE
+ if(NAMEOF(src, integrity))
+ if(!isnum(var_value))
+ return FALSE
+ if(var_value > integrity_max)
+ integrity_max = var_value
+ var_value = max(0, var_value)
+ if(integrity_enabled)
+ set_integrity(var_value)
+ . = TRUE
+ if(NAMEOF(src, integrity_failure))
+ if(!isnum(var_value) || var_value < 0)
+ return FALSE
+ if(NAMEOF(src, integrity_max))
+ if(!isnum(var_value))
+ return FALSE
+ var_value = max(0, var_value)
+ if(NAMEOF(src, contents))
+ var/list/O = contents
+ var/list/N = var_value
+ for(var/atom/movable/AM in O - N)
+ // these go away
+ AM.moveToNullspace()
+ for(var/atom/movable/AM in N - O)
+ // these go in
+ AM.forceMove(src)
+
+ if(!isnull(.))
+ datum_flags |= DF_VAR_EDITED
+ return
+
+ . = ..()
+ if(!.)
+ return
+
+ switch(var_name)
+ if(NAMEOF(src, color))
+ add_atom_colour(color, ADMIN_COLOUR_PRIORITY)
+ if(NAMEOF(src, base_layer), NAMEOF(src, layer))
+ set_base_layer(var_value)
+ if(NAMEOF(src, relative_layer))
+ set_relative_layer(var_value)
+ if(NAMEOF(src, integrity_max))
+ integrity = min(integrity_max, integrity)
+ if(NAMEOF(src, integrity_failure))
+ if(integrity_enabled)
+ var/was_failing = integrity_failure >= integrity
+ var/now_failing = var_value >= integrity
+ if(!was_failing && now_failing)
+ atom_break()
+ else if(was_failing && !now_failing)
+ atom_fix()
+
+/atom/vv_get_var(var_name, resolve)
+ switch(var_name)
+ if(NAMEOF(src, base_layer))
+ if(isnull(base_layer))
+ return debug_variable(NAMEOF(src, base_layer), layer, 0, src)
+ else
+ return debug_variable(NAMEOF(src, base_layer), base_layer, 0, src)
+ return ..()
diff --git a/code/game/atoms/atoms_initializing_EXPENSIVE.dm b/code/game/atoms/atoms_initializing_EXPENSIVE.dm
new file mode 100644
index 000000000000..3c1dbacb0149
--- /dev/null
+++ b/code/game/atoms/atoms_initializing_EXPENSIVE.dm
@@ -0,0 +1,159 @@
+/// Init this specific atom
+/datum/controller/subsystem/atoms/proc/InitAtom(atom/A, from_template = FALSE, list/arguments)
+
+ var/the_type = A.type
+
+ if(QDELING(A))
+ // Check init_start_time to not worry about atoms created before the atoms SS that are cleaned up before this
+ if (A.gc_destroyed > init_start_time)
+ BadInitializeCalls[the_type] |= BAD_INIT_QDEL_BEFORE
+ return TRUE
+
+ // This is handled and battle tested by dreamchecker. Limit to UNIT_TESTS just in case that ever fails.
+ #ifdef UNIT_TESTS
+ var/start_tick = world.time
+ #endif
+
+ var/result = A.Initialize(arglist(arguments))
+
+ #ifdef UNIT_TESTS
+ if(start_tick != world.time)
+ BadInitializeCalls[the_type] |= BAD_INIT_SLEPT
+ #endif
+
+ var/qdeleted = FALSE
+
+ switch(result)
+ if (INITIALIZE_HINT_NORMAL)
+ EMPTY_BLOCK_GUARD // Pass
+ if(INITIALIZE_HINT_LATELOAD)
+ if(arguments[1]) //mapload
+ late_loaders += A
+ else
+ A.LateInitialize()
+ if(INITIALIZE_HINT_QDEL)
+ qdel(A)
+ qdeleted = TRUE
+ else
+ BadInitializeCalls[the_type] |= BAD_INIT_NO_HINT
+
+ if(!A) //possible harddel
+ qdeleted = TRUE
+ else if(!(A.atom_flags & ATOM_INITIALIZED))
+ BadInitializeCalls[the_type] |= BAD_INIT_DIDNT_INIT
+ else
+ SEND_SIGNAL(A, COMSIG_ATOM_AFTER_SUCCESSFUL_INITIALIZE)
+ // SEND_GLOBAL_SIGNAL(COMSIG_GLOB_ATOM_AFTER_POST_INIT, A)
+ var/atom/location = A.loc
+ if(location)
+ /// Sends a signal that the new atom `src`, has been created at `loc`
+ SEND_SIGNAL(location, COMSIG_ATOM_INITIALIZED_ON, A, arguments[1])
+ if(created_atoms && from_template && ispath(the_type, /atom/movable))//we only want to populate the list with movables
+ created_atoms += A.get_all_contents()
+
+ return qdeleted || QDELING(A)
+
+/**
+ * Called when an atom is created in byond (built in engine proc)
+ *
+ * Not a lot happens here in SS13 code, as we offload most of the work to the
+ * [Initialization][/atom/proc/Initialize] proc, mostly we run the preloader
+ * if the preloader is being used and then call [InitAtom][/datum/controller/subsystem/atoms/proc/InitAtom] of which the ultimate
+ * result is that the Initialize proc is called.
+ *
+ */
+/atom/New(loc, ...)
+ //atom creation method that preloads variables at creation
+ if(global.dmm_preloader_active && global.dmm_preloader_target == type)//in case the instantiated atom is creating other atoms in New()
+ world.preloader_load(src)
+
+ if(datum_flags & DF_USE_TAG)
+ generate_tag()
+
+ var/do_initialize = SSatoms.initialized
+ if(do_initialize != INITIALIZATION_INSSATOMS)
+ args[1] = do_initialize == INITIALIZATION_INNEW_MAPLOAD
+ if(SSatoms.InitAtom(src, FALSE, args))
+ //we were deleted
+ return
+
+/**
+ * The primary method that objects are setup in SS13 with
+ *
+ * we don't use New as we have better control over when this is called and we can choose
+ * to delay calls or hook other logic in and so forth
+ *
+ * During roundstart map parsing, atoms are queued for initialization in the base atom/New(),
+ * After the map has loaded, then Initialize is called on all atoms one by one. NB: this
+ * is also true for loading map templates as well, so they don't Initialize until all objects
+ * in the map file are parsed and present in the world
+ *
+ * If you're creating an object at any point after SSInit has run then this proc will be
+ * immediately be called from New.
+ *
+ * mapload: This parameter is true if the atom being loaded is either being initialized during
+ * the Atom subsystem initialization, or if the atom is being loaded from the map template.
+ * If the item is being created at runtime any time after the Atom subsystem is initialized then
+ * it's false.
+ *
+ * The mapload argument occupies the same position as loc when Initialize() is called by New().
+ * loc will no longer be needed after it passed New(), and thus it is being overwritten
+ * with mapload at the end of atom/New() before this proc (atom/Initialize()) is called.
+ *
+ * You must always call the parent of this proc, otherwise failures will occur as the item
+ * will not be seen as initialized (this can lead to all sorts of strange behaviour, like
+ * the item being completely unclickable)
+ *
+ * You must not sleep in this proc, or any subprocs
+ *
+ * Any parameters from new are passed through (excluding loc), naturally if you're loading from a map
+ * there are no other arguments
+ *
+ * Must return an [initialization hint][INITIALIZE_HINT_NORMAL] or a runtime will occur.
+ *
+ * Note: the following functions don't call the base for optimization and must copypasta handling:
+ * * [/turf/proc/Initialize]
+ * * [/turf/open/space/proc/Initialize]
+ */
+/atom/proc/Initialize(mapload, ...)
+ SHOULD_NOT_SLEEP(TRUE)
+ SHOULD_CALL_PARENT(TRUE)
+
+ if(atom_flags & ATOM_INITIALIZED)
+ stack_trace("Warning: [src]([type]) initialized multiple times!")
+ atom_flags |= ATOM_INITIALIZED
+
+ if (is_datum_abstract())
+ log_debug("Abstract atom [type] created!")
+ return INITIALIZE_HINT_QDEL
+
+ //atom color stuff
+ if(color)
+ add_atom_colour(color, FIXED_COLOUR_PRIORITY)
+
+ if(light_power && light_range)
+ update_light()
+
+ SETUP_SMOOTHING()
+
+ if(opacity && isturf(loc))
+ var/turf/T = loc
+ T.has_opaque_atom = TRUE // No need to recalculate it in this case, it's guranteed to be on afterwards anyways.
+
+ return INITIALIZE_HINT_NORMAL
+
+/**
+ * Late Initialization, for code that should run after all atoms have run Initialization
+ *
+ * To have your LateIntialize proc be called, your atoms [Initialization][/atom/proc/Initialize]
+ * proc must return the hint
+ * [INITIALIZE_HINT_LATELOAD] otherwise it will never be called.
+ *
+ * useful for doing things like finding other machines on GLOB.machines because you can guarantee
+ * that all atoms will actually exist in the "WORLD" at this time and that all their Initialization
+ * code has been run
+ */
+/atom/proc/LateInitialize()
+ set waitfor = FALSE
+ SHOULD_CALL_PARENT(FALSE)
+ stack_trace("[src] ([type]) called LateInitialize but has nothing on it!")
diff --git a/code/game/atoms/movement.dm b/code/game/atoms/movement.dm
index 4910477e5325..4eaa8a24b887 100644
--- a/code/game/atoms/movement.dm
+++ b/code/game/atoms/movement.dm
@@ -33,9 +33,8 @@
///Can the mover object pass this atom, while heading for the target turf
/atom/proc/CanPass(atom/movable/mover, turf/target)
- // SHOULD_NOT_OVERRIDE(TRUE)
- // SHOULD_BE_PURE(TRUE)
// SHOULD_CALL_PARENT(TRUE)
+ // SHOULD_BE_PURE(TRUE)
if(mover.movement_type & MOVEMENT_UNSTOPPABLE)
return TRUE
. = CanAllowThrough(mover, target)
diff --git a/code/game/dna/dna_modifier.dm b/code/game/dna/dna_modifier.dm
index 7fd8de7c9530..f3dfb5f75fad 100644
--- a/code/game/dna/dna_modifier.dm
+++ b/code/game/dna/dna_modifier.dm
@@ -256,7 +256,6 @@
return INITIALIZE_HINT_LATELOAD
/obj/machinery/computer/scan_consolenew/LateInitialize()
- . = ..()
scan_for_scanner()
addtimer(CALLBACK(src, PROC_REF(recharge_injector)), 25 SECONDS)
diff --git a/code/game/landmarks/landmarks.dm b/code/game/landmarks/landmarks.dm
index d00ae3343d8f..d17eddaade7d 100644
--- a/code/game/landmarks/landmarks.dm
+++ b/code/game/landmarks/landmarks.dm
@@ -36,29 +36,10 @@ INITIALIZE_IMMEDIATE(/obj/landmark)
else
GLOB.landmarks_keyed[landmark_key] += src
-/obj/landmark/Destroy()
- GLOB.landmarks_list -= src
- if(landmark_key && GLOB.landmarks_keyed[landmark_key])
- GLOB.landmarks_keyed[landmark_key] -= src
- if(!length(GLOB.landmarks_keyed[landmark_key]))
- GLOB.landmarks_keyed -= landmark_key
- return ..()
-
-/**
- * Called when the round is finished setting up directly from SSticker
- */
-/obj/landmark/proc/OnRoundstart()
- if(QDELETED(src))
- CRASH("already deleted")
- if(delete_on_roundstart)
- qdel(src)
-
-// everything below here are subtypes
-// no no no, ftfy: everything below here needs to be nuked from orbit ~silicons
-/obj/landmark/Initialize(mapload)
- . = ..()
+ // everything below here are subtypes
+ // no no no, ftfy: everything below here needs to be nuked from orbit ~silicons
tag = "landmark*[name]"
- invisibility = 101
+ invisibility = INVISIBILITY_ABSTRACT
switch(name) //some of these are probably obsolete
if("monkey")
@@ -111,7 +92,23 @@ INITIALIZE_IMMEDIATE(/obj/landmark)
lavaland_exit += loc
delete_on_roundstart = 1
return
- return 1
+
+/obj/landmark/Destroy()
+ GLOB.landmarks_list -= src
+ if(landmark_key && GLOB.landmarks_keyed[landmark_key])
+ GLOB.landmarks_keyed[landmark_key] -= src
+ if(!length(GLOB.landmarks_keyed[landmark_key]))
+ GLOB.landmarks_keyed -= landmark_key
+ return ..()
+
+/**
+ * Called when the round is finished setting up directly from SSticker
+ */
+/obj/landmark/proc/OnRoundstart()
+ if(QDELETED(src))
+ CRASH("already deleted")
+ if(delete_on_roundstart)
+ qdel(src)
/obj/landmark/observer_spawn
name = "observer start"
diff --git a/code/game/machinery/Sleeper.dm b/code/game/machinery/Sleeper.dm
index 88b51467ac46..080b7d55293b 100644
--- a/code/game/machinery/Sleeper.dm
+++ b/code/game/machinery/Sleeper.dm
@@ -16,7 +16,6 @@
return INITIALIZE_HINT_LATELOAD
/obj/machinery/sleep_console/LateInitialize()
- . = ..()
findsleeper()
/obj/machinery/sleep_console/Destroy()
diff --git a/code/game/machinery/adv_med.dm b/code/game/machinery/adv_med.dm
index f5780aa48c7d..ae3898fc44ea 100644
--- a/code/game/machinery/adv_med.dm
+++ b/code/game/machinery/adv_med.dm
@@ -177,7 +177,6 @@
return INITIALIZE_HINT_LATELOAD
/obj/machinery/body_scanconsole/LateInitialize()
- . = ..()
findscanner()
/obj/machinery/body_scanconsole/Destroy()
diff --git a/code/game/machinery/computer/message.dm b/code/game/machinery/computer/message.dm
index b14ff4229d32..1d660d6d83f2 100644
--- a/code/game/machinery/computer/message.dm
+++ b/code/game/machinery/computer/message.dm
@@ -513,7 +513,6 @@
return INITIALIZE_HINT_LATELOAD
/obj/item/paper/monitorkey/LateInitialize()
- . = ..()
if(message_servers)
for(var/obj/machinery/message_server/server in message_servers)
if(!isnull(server))
diff --git a/code/game/machinery/doors/door_timer.dm b/code/game/machinery/doors/door_timer.dm
index cd5690419e7b..e1f1dfba8c79 100644
--- a/code/game/machinery/doors/door_timer.dm
+++ b/code/game/machinery/doors/door_timer.dm
@@ -48,7 +48,6 @@
return INITIALIZE_HINT_LATELOAD
/obj/machinery/door_timer/LateInitialize()
- . = ..()
if(id != null)
for(var/obj/machinery/door/window/brigdoor/M in urange(20, src))
if (M.id == id)
diff --git a/code/game/machinery/doors/firedoor.dm b/code/game/machinery/doors/firedoor.dm
index ebe353bb3e0d..423e176d4d09 100644
--- a/code/game/machinery/doors/firedoor.dm
+++ b/code/game/machinery/doors/firedoor.dm
@@ -85,7 +85,6 @@ GLOBAL_LIST_INIT(firelock_align_types, typecacheof(list(
return INITIALIZE_HINT_LATELOAD
/obj/machinery/door/firedoor/LateInitialize()
- . = ..()
if(autoset_dir)
for (var/cardinal in GLOB.cardinal)
var/turf/step_turf = get_step(src, cardinal)
diff --git a/code/game/machinery/holopad.dm b/code/game/machinery/holopad.dm
index ab12b2c4607b..43d4ec6d8773 100644
--- a/code/game/machinery/holopad.dm
+++ b/code/game/machinery/holopad.dm
@@ -1,7 +1,7 @@
GLOBAL_LIST_EMPTY(holopad_lookup)
-#define HOLO_NORMAL_COLOR color_matrix_from_rgb("#ccccff")
-#define HOLO_VORE_COLOR color_matrix_from_rgb("#d97de0")
+#define HOLO_NORMAL_COLOR color_to_full_rgba_matrix("#ccccff")
+#define HOLO_VORE_COLOR color_to_full_rgba_matrix("#d97de0")
#define HOLO_NORMAL_ALPHA 140
#define HOLO_VORE_ALPHA 210
diff --git a/code/game/machinery/lightswitch.dm b/code/game/machinery/lightswitch.dm
index 4a44849248b9..1b2cb611e5fb 100644
--- a/code/game/machinery/lightswitch.dm
+++ b/code/game/machinery/lightswitch.dm
@@ -18,19 +18,15 @@
var/image/overlay
/obj/machinery/light_switch/Initialize(mapload, newdir)
- . = ..()
- return INITIALIZE_HINT_LATELOAD
-
-/obj/machinery/light_switch/LateInitialize()
. = ..()
area = get_area(src)
-
if(otherarea)
area = locate(text2path("/area/[otherarea]"))
-
if(!name)
name = "light switch ([area.name])"
+ return INITIALIZE_HINT_LATELOAD
+/obj/machinery/light_switch/LateInitialize()
on = area.lightswitch
updateicon()
diff --git a/code/game/machinery/newscaster.dm b/code/game/machinery/newscaster.dm
index d3b48657543d..44386e2dcd30 100644
--- a/code/game/machinery/newscaster.dm
+++ b/code/game/machinery/newscaster.dm
@@ -189,7 +189,6 @@ var/list/obj/machinery/newscaster/allCasters = list() //Global list that will co
return INITIALIZE_HINT_LATELOAD
/obj/machinery/newscaster/LateInitialize()
- . = ..()
node = get_exonet_node()
/obj/machinery/newscaster/Destroy()
diff --git a/code/game/machinery/telecomms/_telecomms.dm b/code/game/machinery/telecomms/_telecomms.dm
index 65a6994ea967..55cb28f8a702 100644
--- a/code/game/machinery/telecomms/_telecomms.dm
+++ b/code/game/machinery/telecomms/_telecomms.dm
@@ -141,7 +141,6 @@
else
for(var/obj/machinery/telecomms/T in GLOB.telecomms_list)
add_link(T)
- return ..()
/obj/machinery/telecomms/Destroy()
GLOB.telecomms_list -= src
diff --git a/code/game/machinery/teleporter/pad.dm b/code/game/machinery/teleporter/pad.dm
index c87279c0206f..07aaac186824 100644
--- a/code/game/machinery/teleporter/pad.dm
+++ b/code/game/machinery/teleporter/pad.dm
@@ -17,7 +17,6 @@
return INITIALIZE_HINT_LATELOAD
/obj/machinery/tele_pad/LateInitialize()
- . = ..()
update_icon()
/obj/machinery/tele_pad/update_icon()
diff --git a/code/game/machinery/teleporter/projector.dm b/code/game/machinery/teleporter/projector.dm
index 5d2922237cc6..594bf591400f 100644
--- a/code/game/machinery/teleporter/projector.dm
+++ b/code/game/machinery/teleporter/projector.dm
@@ -58,7 +58,6 @@
/obj/machinery/tele_projector/LateInitialize()
- . = ..()
for(var/target_dir in GLOB.cardinal)
var/obj/machinery/tele_pad/found_pad = locate() in get_step(src, target_dir)
if(found_pad)
diff --git a/code/game/objects/items/stacks/sandbag.dm b/code/game/objects/items/stacks/sandbag.dm
index 06915faf9048..b7d9b67d49ab 100644
--- a/code/game/objects/items/stacks/sandbag.dm
+++ b/code/game/objects/items/stacks/sandbag.dm
@@ -128,7 +128,6 @@
update_icon()
/obj/structure/sandbag/LateInitialize()
- . = ..()
//update_connections(FALSE)
update_icon()
diff --git a/code/game/objects/structures/crates_lockers/__closet.dm b/code/game/objects/structures/crates_lockers/__closet.dm
index d1c3e2fcb82b..d3597b1c215e 100644
--- a/code/game/objects/structures/crates_lockers/__closet.dm
+++ b/code/game/objects/structures/crates_lockers/__closet.dm
@@ -70,7 +70,6 @@
return INITIALIZE_HINT_LATELOAD
/obj/structure/closet/LateInitialize()
- . = ..()
if(starts_with)
create_objects_in_loc(src, starts_with)
starts_with = null
diff --git a/code/game/objects/structures/crates_lockers/largecrate.dm b/code/game/objects/structures/crates_lockers/largecrate.dm
index 678e7fb73aa3..55812aecb098 100644
--- a/code/game/objects/structures/crates_lockers/largecrate.dm
+++ b/code/game/objects/structures/crates_lockers/largecrate.dm
@@ -20,7 +20,6 @@
return INITIALIZE_HINT_LATELOAD
/obj/structure/largecrate/LateInitialize()
- . = ..()
if(starts_with)
create_objects_in_loc(src, starts_with)
starts_with = null
diff --git a/code/game/objects/structures/stool_bed_chair_nest/chairs.dm b/code/game/objects/structures/stool_bed_chair_nest/chairs.dm
index 6810f3fe6fa1..53e1acc87f96 100644
--- a/code/game/objects/structures/stool_bed_chair_nest/chairs.dm
+++ b/code/game/objects/structures/stool_bed_chair_nest/chairs.dm
@@ -18,7 +18,6 @@
return INITIALIZE_HINT_LATELOAD
/obj/structure/bed/chair/LateInitialize()
- . = ..()
update_layer()
/obj/structure/bed/chair/OnMouseDrop(atom/over, mob/user)
diff --git a/code/game/objects/structures/tables/table.dm b/code/game/objects/structures/tables/table.dm
index 7e87919bb7e9..b18d03b6ce89 100644
--- a/code/game/objects/structures/tables/table.dm
+++ b/code/game/objects/structures/tables/table.dm
@@ -70,7 +70,6 @@ var/list/table_icon_cache = list()
update_appearance()
/obj/structure/table/LateInitialize() // CURSE YOU DUMB AS ROCKS MATERIAL SYSTEM
- . = ..()
update_connections(FALSE)
update_appearance()
diff --git a/code/game/objects/structures/transit_tubes.dm b/code/game/objects/structures/transit_tubes.dm
index b365c2d1f606..3bbac7db0104 100644
--- a/code/game/objects/structures/transit_tubes.dm
+++ b/code/game/objects/structures/transit_tubes.dm
@@ -71,7 +71,6 @@
return INITIALIZE_HINT_LATELOAD
/obj/structure/transit_tube_pod/LateInitialize()
- . = ..()
follow_tube()
/obj/structure/transit_tube/Initialize(mapload)
diff --git a/code/game/turfs/simulated/floor_types/glass.dm b/code/game/turfs/simulated/floor_types/glass.dm
index 49b59058f3e8..a155b45c48fa 100644
--- a/code/game/turfs/simulated/floor_types/glass.dm
+++ b/code/game/turfs/simulated/floor_types/glass.dm
@@ -23,7 +23,6 @@ CREATE_STANDARD_TURFS(/turf/simulated/floor/glass)
return INITIALIZE_HINT_LATELOAD
/turf/simulated/floor/glass/LateInitialize()
- . = ..()
layer = base_layer
diff --git a/code/game/turfs/space/space.dm b/code/game/turfs/space/space.dm
index f673d08940e2..1f1cc5f2231c 100644
--- a/code/game/turfs/space/space.dm
+++ b/code/game/turfs/space/space.dm
@@ -9,7 +9,7 @@
permit_ao = FALSE
initial_gas_mix = GAS_STRING_VACUUM
- temperature = 2.7
+ temperature = TCMB
can_build_into_floor = TRUE
z_eventually_space = TRUE
@@ -28,12 +28,17 @@
// turn preloader off so it doesn't hit something else
global.dmm_preloader_active = FALSE
+/**
+ * Space Initialize
+ *
+ * Doesn't call parent, see [/atom/proc/Initialize].
+ * When adding new stuff to /atom/Initialize, /turf/Initialize, etc
+ * don't just add it here unless space actually needs it.
+ */
/turf/space/Initialize(mapload)
SHOULD_CALL_PARENT(FALSE)
- atom_flags |= ATOM_INITIALIZED
- // we have parallax and don't need this anymore
- // icon_state = SPACE_ICON_STATE(x, y, z)
+ atom_flags |= ATOM_INITIALIZED
if (CONFIG_GET(flag/starlight))
update_starlight()
@@ -43,21 +48,6 @@
// we don't need to manually check all this in initialize
return INITIALIZE_HINT_NORMAL
- // var/turf/below = below()
- // if(isnull(below))
- // return INITIALIZE_HINT_NORMAL
-
- // if(isspaceturf(below))
- // return INITIALIZE_HINT_NORMAL
-
- // var/area/A = below.loc
- // if(!below.density && (A.area_flags & AREA_FLAG_EXTERNAL))
- // return INITIALIZE_HINT_NORMAL
-
- // return INITIALIZE_HINT_NORMAL
- // todo: wtf happened there..?
- // return INITIALIZE_HINT_LATELOAD // oh no! we need to switch to being a different kind of turf!
-
/turf/space/Destroy()
// Cleanup cached z_eventually_space values above us.
if (above)
diff --git a/code/game/turfs/turf.dm b/code/game/turfs/turf.dm
index af7bc1cc1e4d..56be854724af 100644
--- a/code/game/turfs/turf.dm
+++ b/code/game/turfs/turf.dm
@@ -153,7 +153,6 @@
SETUP_SMOOTHING()
- // queue if necessary; QUEUE_SMOOTH implicitly checks IS_SMOOTH so don't check again
QUEUE_SMOOTH(src)
//atom color stuff
@@ -165,8 +164,8 @@
// this is to trigger entered effects
// bad news is this is not necessarily currently idempotent
// we probably have to deal with this at.. some point.
- for(var/atom/movable/AM in src)
- Entered(AM)
+ for(var/atom/movable/content as anything in src)
+ Entered(content)
var/area/A = loc
@@ -231,7 +230,7 @@
// clear vis contents here instead of in Init
if(length(vis_contents))
- vis_contents.len = 0
+ vis_contents.Cut()
..()
diff --git a/code/modules/admin/view_variables/color_matrix_editor.dm b/code/modules/admin/view_variables/color_matrix_editor.dm
index f8db04662751..29158035c1cb 100644
--- a/code/modules/admin/view_variables/color_matrix_editor.dm
+++ b/code/modules/admin/view_variables/color_matrix_editor.dm
@@ -60,7 +60,7 @@ INITIALIZE_IMMEDIATE(/atom/movable/screen/color_matrix_proxy_view)
else if(istext(_target?.color))
current_color = color_hex2color_matrix(_target.color)
else
- current_color = color_matrix_identity()
+ current_color = COLOR_MATRIX_IDENTITY
proxy_view = new
if(_target)
target = WEAKREF(_target)
diff --git a/code/modules/assembly/signaler.dm b/code/modules/assembly/signaler.dm
index 58e91d6e34a6..ab9f5f05d489 100644
--- a/code/modules/assembly/signaler.dm
+++ b/code/modules/assembly/signaler.dm
@@ -23,7 +23,6 @@
return INITIALIZE_HINT_LATELOAD
/obj/item/assembly/signaler/LateInitialize()
- . = ..()
set_frequency(frequency)
/obj/item/assembly/signaler/activate()
diff --git a/code/modules/atmospherics/machinery/portable/portable_atmospherics.dm b/code/modules/atmospherics/machinery/portable/portable_atmospherics.dm
index 07e76b1e7ed7..15320033a757 100644
--- a/code/modules/atmospherics/machinery/portable/portable_atmospherics.dm
+++ b/code/modules/atmospherics/machinery/portable/portable_atmospherics.dm
@@ -59,7 +59,6 @@
if(port)
connect(port)
update_icon()
- return ..()
/obj/machinery/portable_atmospherics/process(delta_time)
flow_current = 0
diff --git a/code/modules/industry/disposals/disposal/chute.dm b/code/modules/industry/disposals/disposal/chute.dm
index 7fd8681bffb5..29fdecbfa936 100644
--- a/code/modules/industry/disposals/disposal/chute.dm
+++ b/code/modules/industry/disposals/disposal/chute.dm
@@ -39,7 +39,6 @@
return INITIALIZE_HINT_LATELOAD
/obj/machinery/disposal/LateInitialize()
- . = ..()
trunk = locate() in src.loc
if(!trunk)
mode = 0
diff --git a/code/modules/industry/disposals/disposal_pipe/trunk.dm b/code/modules/industry/disposals/disposal_pipe/trunk.dm
index 3d0b03a73a16..65647cf0efa8 100644
--- a/code/modules/industry/disposals/disposal_pipe/trunk.dm
+++ b/code/modules/industry/disposals/disposal_pipe/trunk.dm
@@ -9,8 +9,8 @@
return INITIALIZE_HINT_LATELOAD
/obj/structure/disposalpipe/trunk/LateInitialize()
- . = ..()
getlinked()
+
/obj/structure/disposalpipe/trunk/proc/getlinked()
linked = null
var/obj/machinery/disposal/D = locate() in src.loc
diff --git a/code/modules/mapping/dmm_suite/dmm_parsed.dm b/code/modules/mapping/dmm_suite/dmm_parsed.dm
index 387a674526b1..8e1e7ee3f26b 100644
--- a/code/modules/mapping/dmm_suite/dmm_parsed.dm
+++ b/code/modules/mapping/dmm_suite/dmm_parsed.dm
@@ -299,8 +299,9 @@
var/static/loading = FALSE
UNTIL(!loading)
- loading = TRUE
Master.StartLoadingMap()
+ loading = TRUE
+ SSatoms.map_loader_begin(REF(src))
_populate_orientation(context, orientation)
context.loaded_dmm = src
@@ -312,8 +313,9 @@
context.loaded_bounds = loaded_bounds
context.success = !isnull(loaded_bounds)
- Master.StopLoadingMap()
+ SSatoms.map_loader_stop(REF(src))
loading = FALSE
+ Master.StopLoadingMap()
/datum/dmm_parsed/proc/_populate_orientation(datum/dmm_context/context,orientation)
var/datum/dmm_orientation/orientation_pattern = GLOB.dmm_orientations["[orientation]"]
@@ -523,9 +525,6 @@
//Instanciation
////////////////
- //turn off base new Initialization until the whole thing is loaded
- SSatoms.map_loader_begin()
-
//The next part of the code assumes there's ALWAYS an /area AND a /turf on a given tile
//first instance the /area and remove it from the members list
index = members.len
@@ -578,9 +577,6 @@
for(index in 1 to first_turf_index-1)
instance_atom(members[index],members_attributes[index],crds,no_changeturf,placeOnTop)
- //Restore initialization to the previous value
- SSatoms.map_loader_stop()
-
////////////////
//Helpers procs
////////////////
@@ -605,9 +601,9 @@
//custom CHECK_TICK here because we don't want things created while we're sleeping to not initialize
if(TICK_CHECK)
- SSatoms.map_loader_stop()
+ SSatoms.map_loader_stop(REF(src))
stoplag()
- SSatoms.map_loader_begin()
+ SSatoms.map_loader_begin(REF(src))
/**
* create an atom at a location
diff --git a/code/modules/maps/turf_makers/planet_station_turfs/_lythios43c.dm b/code/modules/maps/turf_makers/planet_station_turfs/_lythios43c.dm
index 8e02d42d5e69..1af1c55feef9 100644
--- a/code/modules/maps/turf_makers/planet_station_turfs/_lythios43c.dm
+++ b/code/modules/maps/turf_makers/planet_station_turfs/_lythios43c.dm
@@ -3,10 +3,11 @@
#define LYTHIOS43C_TURF_CREATE(x) x/lythios43c/initial_gas_mix=ATMOSPHERE_ID_LYTHIOS43C;x/lythios43c/outdoors=TRUE
#define LYTHIOS43C_TURF_CREATE_UN(x) x/lythios43c/initial_gas_mix=ATMOSPHERE_ID_LYTHIOS43C;x/lythios43c/outdoors=FALSE
-/turf/simulated/open/lythios43c/Initialize(mapload)
- . = ..()
- if(outdoors)
- SSplanets.addTurf(src)
+// usless init, check [/turf/simulated/Initialize()]
+// /turf/simulated/open/lythios43c/Initialize(mapload)
+// . = ..()
+// if(outdoors)
+// SSplanets.addTurf(src)
LYTHIOS43C_TURF_CREATE(/turf/simulated/open)
diff --git a/code/modules/mob/freelook/ai/eye.dm b/code/modules/mob/freelook/ai/eye.dm
index c0fb5e2c9d5f..214b063ce9b2 100644
--- a/code/modules/mob/freelook/ai/eye.dm
+++ b/code/modules/mob/freelook/ai/eye.dm
@@ -53,7 +53,6 @@
return INITIALIZE_HINT_LATELOAD
/mob/living/silicon/ai/LateInitialize()
- . = ..()
if(eyeobj && loc)
eyeobj.forceMove(loc)
diff --git a/code/modules/mob/living/bot/medibot_construction.dm b/code/modules/mob/living/bot/medibot_construction.dm
index 945266b09022..9f24f995dffd 100644
--- a/code/modules/mob/living/bot/medibot_construction.dm
+++ b/code/modules/mob/living/bot/medibot_construction.dm
@@ -19,7 +19,6 @@
return INITIALIZE_HINT_LATELOAD
/obj/item/bot_assembly/medibot/LateInitialize()
- . = ..()
update_appearance()
/obj/item/bot_assembly/medibot/update_overlays()
diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm
index c2005c49631d..f64d28e2f48d 100644
--- a/code/modules/mob/living/carbon/human/human.dm
+++ b/code/modules/mob/living/carbon/human/human.dm
@@ -57,7 +57,6 @@
//! WARNING SHITCODE REMOVE LATER
/mob/living/carbon/human/LateInitialize()
- . = ..()
regenerate_icons()
update_transform()
diff --git a/code/modules/mob/living/silicon/ai/ai.dm b/code/modules/mob/living/silicon/ai/ai.dm
index 03cde2178079..4339cc4497ac 100644
--- a/code/modules/mob/living/silicon/ai/ai.dm
+++ b/code/modules/mob/living/silicon/ai/ai.dm
@@ -190,8 +190,7 @@ var/list/ai_verbs_default = list(
if(!safety)//Only used by AIize() to successfully spawn an AI.
if (!B)//If there is no player/brain inside.
GLOB.empty_playable_ai_cores += new /obj/structure/AIcore/deactivated(loc)//New empty terminal.
- qdel(src)//Delete AI.
- return
+ return INITIALIZE_HINT_QDEL //Delete AI
else
if (B.brainmob.mind)
B.brainmob.mind.transfer(src)
@@ -346,8 +345,8 @@ var/list/ai_verbs_default = list(
use_power(USE_POWER_IDLE) // Just incase we need to wake up the power system.
/obj/machinery/ai_powersupply/Destroy()
- . = ..()
powered_ai = null
+ return ..()
/obj/machinery/ai_powersupply/process(delta_time)
if(!powered_ai || powered_ai.stat == DEAD)
diff --git a/code/modules/organs/external/external_icons.dm b/code/modules/organs/external/external_icons.dm
index 1af4e4b43306..a421cd26de5d 100644
--- a/code/modules/organs/external/external_icons.dm
+++ b/code/modules/organs/external/external_icons.dm
@@ -214,7 +214,7 @@ GLOBAL_LIST_EMPTY(limb_icon_cache)
else if(s_col && s_col.len >= 3)
// Support for species.color_mult
if(species.color_force_greyscale)
- applying.MapColors(arglist(color_matrix_greyscale()))
+ applying.MapColors(arglist(COLOR_MATRIX_GRAYSCALE))
icon_cache_key += "_ags"
if(species && species.color_mult)
applying.Blend(rgb(s_col[1], s_col[2], s_col[3]), ICON_MULTIPLY)
diff --git a/code/modules/overmap/legacy/ships/computers/helm.dm b/code/modules/overmap/legacy/ships/computers/helm.dm
index c7ccf8a01be9..15355e7e554a 100644
--- a/code/modules/overmap/legacy/ships/computers/helm.dm
+++ b/code/modules/overmap/legacy/ships/computers/helm.dm
@@ -45,7 +45,6 @@ GLOBAL_LIST_EMPTY(all_waypoints)
return INITIALIZE_HINT_LATELOAD
/obj/machinery/computer/ship/helm/LateInitialize()
- . = ..()
get_known_sectors()
/obj/machinery/computer/ship/helm/proc/get_known_sectors()
diff --git a/code/modules/overmap/legacy/ships/computers/sensors.dm b/code/modules/overmap/legacy/ships/computers/sensors.dm
index f142942fcc8b..4898d391f8a9 100644
--- a/code/modules/overmap/legacy/ships/computers/sensors.dm
+++ b/code/modules/overmap/legacy/ships/computers/sensors.dm
@@ -24,7 +24,6 @@
return INITIALIZE_HINT_LATELOAD
/obj/machinery/computer/ship/sensors/planet/LateInitialize()
- . = ..()
var/area/overmap/map = locate() in world
for(var/obj/overmap/entity/visitable/sector/S in map)
if(istype(S,planet_type))
diff --git a/code/modules/power/breaker_box.dm b/code/modules/power/breaker_box.dm
index 8314a7a6f63a..1ff84485f96c 100644
--- a/code/modules/power/breaker_box.dm
+++ b/code/modules/power/breaker_box.dm
@@ -43,7 +43,6 @@
/obj/machinery/power/breakerbox/activated/LateInitialize()
set_state(1)
- return ..()
/obj/machinery/power/breakerbox/examine(mob/user, dist)
. = ..()
diff --git a/code/modules/power/geothermal_power.dm b/code/modules/power/geothermal_power.dm
index 0fcc9139fd29..8842ccdaf919 100644
--- a/code/modules/power/geothermal_power.dm
+++ b/code/modules/power/geothermal_power.dm
@@ -29,7 +29,6 @@
return INITIALIZE_HINT_LATELOAD
/obj/machinery/power/geothermal_controller/prepared/LateInitialize()
- . = ..()
scan_for_collectors(scanner?.range)
/obj/machinery/power/geothermal_controller/examine(mob/user, dist)
diff --git a/code/modules/power/gravitygenerator.dm b/code/modules/power/gravitygenerator.dm
index c602f9b35e71..8c494ad9b372 100644
--- a/code/modules/power/gravitygenerator.dm
+++ b/code/modules/power/gravitygenerator.dm
@@ -129,13 +129,12 @@ GLOBAL_LIST_EMPTY(gravity_generators)
var/list/areas = list()
/obj/machinery/gravity_generator/main/Initialize(mapload)
- ..()
+ . = ..()
return INITIALIZE_HINT_LATELOAD
/obj/machinery/gravity_generator/main/LateInitialize() //Needs to happen after overmap sectors are initialized so we can figure out where we are
update_list()
update_areas()
- return ..()
/obj/machinery/gravity_generator/main/set_fix()
. = ..()
diff --git a/code/modules/power/smes/smes.dm b/code/modules/power/smes/smes.dm
index bde57b6dd623..2c2bce4fdd0e 100644
--- a/code/modules/power/smes/smes.dm
+++ b/code/modules/power/smes/smes.dm
@@ -73,7 +73,6 @@ GLOBAL_LIST_EMPTY(smeses)
return INITIALIZE_HINT_LATELOAD
/obj/machinery/power/smes/LateInitialize()
- . = ..()
if(!powernet)
connect_to_network()
diff --git a/tools/read_init_times.py b/tools/read_init_times.py
index 4dca61c40f79..c95af704a0aa 100644
--- a/tools/read_init_times.py
+++ b/tools/read_init_times.py
@@ -1,5 +1,6 @@
# When passed an `init_times.json` file (received from enabling `PROFILE_MAPLOAD_INIT_ATOM`),
# and an optional max-depth level, this will output init times from worst to best.
+import errno
import json
import sys
@@ -19,4 +20,10 @@
init_times_per_type[type] = init_times_per_type.get(type, 0) + time
for (type, time) in sorted(init_times_per_type.items(), key = lambda x: x[1], reverse = True):
- print(type, time)
+ try:
+ print(type, time)
+ except IOError as error:
+ # Prevents broken pipe error if you do something like `read_init_times.py init_times.json | head`
+ if error.errno == errno.EPIPE:
+ sys.stderr.close()
+ sys.exit(0)