diff --git a/_maps/RandomZLevels/Cabin.dmm b/_maps/RandomZLevels/Cabin.dmm
index f4a18fd8..d2c0ca6f 100644
--- a/_maps/RandomZLevels/Cabin.dmm
+++ b/_maps/RandomZLevels/Cabin.dmm
@@ -205,16 +205,16 @@
/area/awaymission/cabin)
"aJ" = (
/obj/machinery/shower{
- icon_state = "shower";
- dir = 8
+ dir = 8;
+ icon_state = "shower"
},
/obj/machinery/door/window/northright,
/turf/open/floor/plasteel/freezer,
/area/awaymission/cabin)
"aK" = (
/obj/machinery/shower{
- icon_state = "shower";
- dir = 4
+ dir = 4;
+ icon_state = "shower"
},
/obj/machinery/door/window/northleft,
/turf/open/floor/plasteel/freezer,
@@ -466,13 +466,13 @@
/area/awaymission/cabin)
"bI" = (
/obj/machinery/shower{
- icon_state = "shower";
- dir = 4
+ dir = 4;
+ icon_state = "shower"
},
/obj/machinery/door/window/eastright,
/obj/structure/window{
- icon_state = "window";
- dir = 1
+ dir = 1;
+ icon_state = "window"
},
/turf/open/floor/plasteel/freezer,
/area/awaymission/cabin)
@@ -967,10 +967,6 @@
},
/turf/open/floor/plating,
/area/awaymission/cabin)
-"dw" = (
-/obj/effect/mapping_helpers/planet_z,
-/turf/closed/indestructible/rock/snow,
-/area/space)
(1,1,1) = {"
aa
@@ -1227,7 +1223,7 @@ aa
aa
aa
aa
-dw
+aa
"}
(2,1,1) = {"
aa
diff --git a/_maps/RandomZLevels/VR/snowdin_VR.dmm b/_maps/RandomZLevels/VR/snowdin_VR.dmm
index 0e67b722..22261561 100644
--- a/_maps/RandomZLevels/VR/snowdin_VR.dmm
+++ b/_maps/RandomZLevels/VR/snowdin_VR.dmm
@@ -4,9 +4,15 @@
/turf/closed/indestructible/rock/snow,
/area/awaymission/snowdin/cave/mountain)
"ab" = (
-/obj/effect/mapping_helpers/planet_z,
-/turf/closed/indestructible/rock/snow,
-/area/awaymission/snowdin/cave/mountain)
+/obj/effect/turf_decal/tile/neutral{
+ dir = 1
+ },
+/obj/effect/turf_decal/tile/neutral{
+ dir = 8
+ },
+/mob/living/simple_animal/hostile/netherworld/migo,
+/turf/open/floor/plasteel,
+/area/awaymission/snowdin/post/mining_dock)
"ac" = (
/turf/closed/indestructible/rock/snow,
/area/awaymission/snowdin/cave/mountain)
@@ -10267,16 +10273,6 @@
/obj/item/shard,
/turf/open/floor/plating,
/area/awaymission/snowdin/post/mining_dock)
-"xA" = (
-/mob/living/simple_animal/hostile/netherworld/migo,
-/obj/effect/turf_decal/tile/neutral{
- dir = 1
- },
-/obj/effect/turf_decal/tile/neutral{
- dir = 8
- },
-/turf/open/floor/plasteel,
-/area/awaymission/snowdin/post/mining_dock)
"xB" = (
/obj/effect/turf_decal/stripes/line{
dir = 4
@@ -16013,7 +16009,7 @@ ac
ac
"}
(2,1,1) = {"
-ab
+ac
ac
ac
ac
@@ -66518,7 +66514,7 @@ wD
wT
xe
xs
-xA
+ab
xI
xN
wL
diff --git a/_maps/RandomZLevels/caves.dmm b/_maps/RandomZLevels/caves.dmm
index 92373463..913de081 100644
--- a/_maps/RandomZLevels/caves.dmm
+++ b/_maps/RandomZLevels/caves.dmm
@@ -2251,10 +2251,6 @@
initial_gas_mix = "n2=23;o2=14"
},
/area/awaymission/caves/BMP_asteroid)
-"gW" = (
-/obj/effect/mapping_helpers/planet_z,
-/turf/closed/indestructible/rock,
-/area/space/nearstation)
"gX" = (
/obj/effect/baseturf_helper/lava,
/turf/closed/mineral/volcanic,
@@ -2536,7 +2532,7 @@ aa
aa
aa
aa
-gW
+aa
"}
(2,1,1) = {"
aa
diff --git a/_maps/RandomZLevels/moonoutpost19.dmm b/_maps/RandomZLevels/moonoutpost19.dmm
index c251a338..837adbf7 100644
--- a/_maps/RandomZLevels/moonoutpost19.dmm
+++ b/_maps/RandomZLevels/moonoutpost19.dmm
@@ -7212,10 +7212,6 @@
heat_capacity = 1e+006
},
/area/awaymission/moonoutpost19/research)
-"oV" = (
-/obj/effect/mapping_helpers/planet_z,
-/turf/open/space,
-/area/space)
"vV" = (
/obj/machinery/door/airlock/external,
/obj/effect/mapping_helpers/airlock/cyclelink_helper{
@@ -7509,7 +7505,7 @@ aa
aa
aa
aa
-oV
+aa
"}
(2,1,1) = {"
aa
diff --git a/_maps/RandomZLevels/snowdin.dmm b/_maps/RandomZLevels/snowdin.dmm
index 354b8725..f81e6a1f 100644
--- a/_maps/RandomZLevels/snowdin.dmm
+++ b/_maps/RandomZLevels/snowdin.dmm
@@ -4,9 +4,15 @@
/turf/closed/indestructible/rock/snow,
/area/awaymission/snowdin/cave/mountain)
"ab" = (
-/obj/effect/mapping_helpers/planet_z,
-/turf/closed/indestructible/rock/snow,
-/area/awaymission/snowdin/cave/mountain)
+/obj/effect/turf_decal/tile/neutral{
+ dir = 1
+ },
+/obj/effect/turf_decal/tile/neutral{
+ dir = 8
+ },
+/mob/living/simple_animal/hostile/netherworld/migo,
+/turf/open/floor/plasteel,
+/area/awaymission/snowdin/post/mining_dock)
"ac" = (
/turf/closed/indestructible/rock/snow,
/area/awaymission/snowdin/cave/mountain)
@@ -10361,16 +10367,6 @@
/obj/item/shard,
/turf/open/floor/plating,
/area/awaymission/snowdin/post/mining_dock)
-"xA" = (
-/mob/living/simple_animal/hostile/netherworld/migo,
-/obj/effect/turf_decal/tile/neutral{
- dir = 1
- },
-/obj/effect/turf_decal/tile/neutral{
- dir = 8
- },
-/turf/open/floor/plasteel,
-/area/awaymission/snowdin/post/mining_dock)
"xB" = (
/obj/effect/turf_decal/stripes/line{
dir = 4
@@ -16211,7 +16207,7 @@ ac
ac
"}
(2,1,1) = {"
-ab
+ac
ac
ac
ac
@@ -66716,7 +66712,7 @@ wD
wT
xe
xs
-xA
+ab
xI
xN
wL
diff --git a/_maps/RandomZLevels/spacebattle.dmm b/_maps/RandomZLevels/spacebattle.dmm
index 21cd37f7..66d7f556 100644
--- a/_maps/RandomZLevels/spacebattle.dmm
+++ b/_maps/RandomZLevels/spacebattle.dmm
@@ -5,6 +5,16 @@
"ab" = (
/turf/open/space,
/area/space)
+"ac" = (
+/obj/effect/turf_decal/tile/blue{
+ dir = 1
+ },
+/obj/effect/turf_decal/tile/blue{
+ dir = 8
+ },
+/mob/living/simple_animal/hostile/syndicate/melee/sword,
+/turf/open/floor/plasteel,
+/area/awaymission/spacebattle/cruiser)
"ad" = (
/obj/structure/shuttle/engine/propulsion/right{
dir = 1
@@ -2597,16 +2607,6 @@
/obj/effect/spawner/lootdrop/armory_contraband,
/turf/open/floor/plating,
/area/awaymission/spacebattle/cruiser)
-"jK" = (
-/mob/living/simple_animal/hostile/syndicate/melee/sword,
-/obj/effect/turf_decal/tile/blue{
- dir = 1
- },
-/obj/effect/turf_decal/tile/blue{
- dir = 8
- },
-/turf/open/floor/plasteel,
-/area/awaymission/spacebattle/cruiser)
"jL" = (
/obj/machinery/door/poddoor{
id = "spacebattlearmory";
@@ -2894,10 +2894,6 @@
/obj/item/mecha_parts/mecha_equipment/weapon/energy/ion,
/turf/open/floor/plating,
/area/awaymission/spacebattle/cruiser)
-"kM" = (
-/obj/effect/mapping_helpers/planet_z,
-/turf/closed/mineral/random,
-/area/space/nearstation)
"vw" = (
/turf/closed/wall/mineral/plastitanium/nodiagonal,
/area/awaymission/spacebattle/syndicate5)
@@ -3175,7 +3171,7 @@ aa
aa
aa
aa
-kM
+aa
"}
(2,1,1) = {"
aa
@@ -35686,10 +35682,10 @@ eC
cn
fL
cp
-jK
+ac
fs
fO
-jK
+ac
eM
eM
eM
diff --git a/_maps/RandomZLevels/undergroundoutpost45.dmm b/_maps/RandomZLevels/undergroundoutpost45.dmm
index f6d46ef9..56018b94 100644
--- a/_maps/RandomZLevels/undergroundoutpost45.dmm
+++ b/_maps/RandomZLevels/undergroundoutpost45.dmm
@@ -25,6 +25,9 @@
"ag" = (
/turf/closed/wall/mineral/titanium,
/area/awaymission/undergroundoutpost45/central)
+"ah" = (
+/turf/open/space,
+/area/space/nearstation)
"aj" = (
/obj/effect/decal/cleanable/dirt,
/turf/open/floor/plasteel{
@@ -13945,10 +13948,6 @@
temperature = 363.9
},
/area/awaymission/undergroundoutpost45/caves)
-"zi" = (
-/obj/effect/mapping_helpers/planet_z,
-/turf/open/space,
-/area/space/nearstation)
"KE" = (
/obj/machinery/atmospherics/components/unary/vent_pump/on{
dir = 4
@@ -14211,7 +14210,7 @@ aa
aa
aa
aa
-zi
+ah
"}
(2,1,1) = {"
aa
diff --git a/_maps/map_files/Mining/Lavaland.dmm b/_maps/map_files/Mining/Lavaland.dmm
index d9e45bf4..cbce562a 100644
--- a/_maps/map_files/Mining/Lavaland.dmm
+++ b/_maps/map_files/Mining/Lavaland.dmm
@@ -4069,10 +4069,6 @@
},
/turf/open/floor/plating,
/area/mine/laborcamp)
-"ut" = (
-/obj/effect/baseturf_helper/lava_land/surface,
-/turf/closed/wall,
-/area/mine/laborcamp)
"uM" = (
/obj/machinery/light/small{
dir = 8
@@ -4294,10 +4290,6 @@
/obj/structure/ore_box,
/turf/open/floor/plating/asteroid/basalt/lava_land_surface,
/area/lavaland/surface/outdoors)
-"Ay" = (
-/obj/effect/baseturf_helper/lava_land/surface,
-/turf/closed/wall,
-/area/mine/laborcamp/security)
"AH" = (
/obj/machinery/computer/secure_data{
dir = 1
@@ -4358,10 +4350,6 @@
},
/turf/open/floor/plasteel,
/area/mine/production)
-"BU" = (
-/obj/effect/baseturf_helper/lava_land/surface,
-/turf/closed/wall,
-/area/mine/eva)
"BW" = (
/obj/effect/spawner/structure/window/reinforced,
/turf/open/floor/plating,
@@ -4380,10 +4368,6 @@
/obj/structure/sign/warning/electricshock,
/turf/closed/wall,
/area/mine/living_quarters)
-"Df" = (
-/obj/effect/baseturf_helper/lava_land/surface,
-/turf/closed/wall,
-/area/mine/production)
"Di" = (
/obj/structure/reagent_dispensers/fueltank,
/turf/open/floor/plating,
@@ -4613,10 +4597,6 @@
"PQ" = (
/turf/closed/wall,
/area/mine/living_quarters)
-"Qk" = (
-/obj/effect/baseturf_helper/lava_land/surface,
-/turf/closed/wall,
-/area/mine/living_quarters)
"QZ" = (
/turf/open/floor/plating/asteroid/basalt/lava_land_surface,
/area/lavaland/surface/outdoors/unexplored/danger)
@@ -4626,10 +4606,6 @@
"Rg" = (
/turf/open/floor/plating/asteroid/basalt/lava_land_surface,
/area/lavaland/surface/outdoors/unexplored)
-"Ro" = (
-/obj/effect/mapping_helpers/planet_z,
-/turf/open/lava/smooth/lava_land_surface,
-/area/lavaland/surface/outdoors)
"Sd" = (
/turf/open/floor/plasteel,
/area/mine/living_quarters)
@@ -4648,10 +4624,6 @@
"Wp" = (
/turf/open/lava/smooth/lava_land_surface,
/area/lavaland/surface/outdoors)
-"WJ" = (
-/obj/effect/baseturf_helper/lava_land/surface,
-/turf/closed/wall/r_wall,
-/area/mine/maintenance)
"Xs" = (
/turf/closed/mineral/random/volcanic,
/area/lavaland/surface/outdoors)
@@ -4923,7 +4895,7 @@ Wp
Wp
Wp
Wp
-Ro
+Wp
"}
(2,1,1) = {"
Zx
@@ -9768,7 +9740,7 @@ Py
rN
Py
tz
-ut
+Py
vd
Py
yu
@@ -10029,7 +10001,7 @@ nh
nh
Py
yw
-Ay
+yw
yw
Wp
Wp
@@ -13381,7 +13353,7 @@ cX
cX
PQ
cQ
-Qk
+PQ
cX
cX
bQ
@@ -18518,7 +18490,7 @@ Wp
em
XJ
Fx
-WJ
+em
dk
er
PQ
@@ -21844,7 +21816,7 @@ pa
wh
ak
at
-BU
+ob
aH
pa
wh
@@ -22365,7 +22337,7 @@ ob
wv
bj
wv
-Df
+dN
Gq
GN
GN
@@ -22618,7 +22590,7 @@ aI
aV
bc
bi
-BU
+ob
bu
bE
bZ
diff --git a/code/__DEFINES/atmospherics.dm b/code/__DEFINES/atmospherics.dm
index eeb56608..4a73523a 100644
--- a/code/__DEFINES/atmospherics.dm
+++ b/code/__DEFINES/atmospherics.dm
@@ -149,6 +149,13 @@
#define CANATMOSPASS(A, O) ( A.CanAtmosPass == ATMOS_PASS_PROC ? A.CanAtmosPass(O) : ( A.CanAtmosPass == ATMOS_PASS_DENSITY ? !A.density : A.CanAtmosPass ) )
#define CANVERTICALATMOSPASS(A, O) ( A.CanAtmosPassVertical == ATMOS_PASS_PROC ? A.CanAtmosPass(O, TRUE) : ( A.CanAtmosPassVertical == ATMOS_PASS_DENSITY ? !A.density : A.CanAtmosPassVertical ) )
+//OPEN TURF ATMOS
+#define OPENTURF_DEFAULT_ATMOS "o2=22;n2=82;TEMP=293.15" //the default air mix that open turfs spawn
+#define TCOMMS_ATMOS "n2=100;TEMP=80" //-193,15degC telecommunications. also used for xenobiology slime killrooms
+#define AIRLESS_ATMOS "TEMP=2.7" //space
+#define FROZEN_ATMOS "o2=22;n2=82;TEMP=180" //-93.15degC snow and ice turfs
+#define BURNMIX_ATMOS "o2=2500;plasma=5000;TEMP=370" //used in the holodeck burn test program
+
//LAVALAND
#define LAVALAND_EQUIPMENT_EFFECT_PRESSURE 50 //what pressure you have to be under to increase the effect of equipment meant for lavaland
#define LAVALAND_DEFAULT_ATMOS "o2=14;n2=23;TEMP=300"
@@ -299,4 +306,4 @@ GLOBAL_LIST_INIT(pipe_paint_colors, list(
))
#define MIASMA_CORPSE_MOLES 0.02
-#define MIASMA_GIBS_MOLES 0.005
\ No newline at end of file
+#define MIASMA_GIBS_MOLES 0.005
diff --git a/code/__DEFINES/maps.dm b/code/__DEFINES/maps.dm
index 3288c96a..d6f1097a 100644
--- a/code/__DEFINES/maps.dm
+++ b/code/__DEFINES/maps.dm
@@ -39,8 +39,6 @@ require only minor tweaks.
#define ZTRAIT_LAVA_RUINS "Lava Ruins"
#define ZTRAIT_LAVA_UNDERGROUND "Lava Underground"
#define ZTRAIT_ISOLATED_RUINS "Isolated Ruins" //Placing ruins on z levels with this trait will use turf reservation instead of usual placement.
-// prevents certain turfs from being stripped by a singularity
-#define ZTRAIT_PLANET "Planet"
// number - bombcap is multiplied by this before being applied to bombs
#define ZTRAIT_BOMBCAP_MULTIPLIER "Bombcap Multiplier"
@@ -61,6 +59,9 @@ require only minor tweaks.
// CROSSLINKED - mixed in with the cross-linked space pool
#define CROSSLINKED "Cross"
+// string - type path of the z-level's baseturf (defaults to space)
+#define ZTRAIT_BASETURF "Baseturf"
+
// default trait definitions, used by SSmapping
#define ZTRAITS_CENTCOM list(ZTRAIT_CENTCOM = TRUE)
#define ZTRAITS_STATION list(ZTRAIT_LINKAGE = CROSSLINKED, ZTRAIT_STATION = TRUE)
diff --git a/code/__HELPERS/_logging.dm b/code/__HELPERS/_logging.dm
index 774b8768..928346d5 100644
--- a/code/__HELPERS/_logging.dm
+++ b/code/__HELPERS/_logging.dm
@@ -160,6 +160,8 @@
WRITE_LOG(GLOB.config_error_log, text)
SEND_TEXT(world.log, text)
+/proc/log_mapping(text)
+ WRITE_LOG(GLOB.world_map_error_log, text)
/* For logging round startup. */
/proc/start_log(log)
diff --git a/code/__HELPERS/level_traits.dm b/code/__HELPERS/level_traits.dm
index 55ee0693..3e6e88c8 100644
--- a/code/__HELPERS/level_traits.dm
+++ b/code/__HELPERS/level_traits.dm
@@ -12,6 +12,3 @@
#define is_reserved_level(z) SSmapping.level_trait(z, ZTRAIT_RESERVED)
#define is_away_level(z) SSmapping.level_trait(z, ZTRAIT_AWAY)
-
-// If true, the singularity cannot strip away asteroid turf on this Z
-#define is_planet_level(z) SSmapping.level_trait(z, ZTRAIT_PLANET)
diff --git a/code/_globalvars/logging.dm b/code/_globalvars/logging.dm
index 485e67e2..5ca3513e 100644
--- a/code/_globalvars/logging.dm
+++ b/code/_globalvars/logging.dm
@@ -1,60 +1,62 @@
-GLOBAL_VAR(log_directory)
-GLOBAL_PROTECT(log_directory)
-GLOBAL_VAR(world_game_log)
-GLOBAL_PROTECT(world_game_log)
-GLOBAL_VAR(world_runtime_log)
-GLOBAL_PROTECT(world_runtime_log)
-GLOBAL_VAR(world_qdel_log)
-GLOBAL_PROTECT(world_qdel_log)
-GLOBAL_VAR(world_attack_log)
-GLOBAL_PROTECT(world_attack_log)
-GLOBAL_VAR(world_href_log)
-GLOBAL_PROTECT(world_href_log)
-GLOBAL_VAR(round_id)
-GLOBAL_PROTECT(round_id)
-GLOBAL_VAR(config_error_log)
-GLOBAL_PROTECT(config_error_log)
-GLOBAL_VAR(sql_error_log)
-GLOBAL_PROTECT(sql_error_log)
-GLOBAL_VAR(world_pda_log)
-GLOBAL_PROTECT(world_pda_log)
-GLOBAL_VAR(world_telecomms_log)
-GLOBAL_PROTECT(world_telecomms_log)
-GLOBAL_VAR(world_manifest_log)
-GLOBAL_PROTECT(world_manifest_log)
-GLOBAL_VAR(query_debug_log)
-GLOBAL_PROTECT(query_debug_log)
-GLOBAL_VAR(world_job_debug_log)
-GLOBAL_PROTECT(world_job_debug_log)
-GLOBAL_VAR(world_virus_log)
-GLOBAL_PROTECT(world_virus_log)
-
-GLOBAL_LIST_EMPTY(bombers)
-GLOBAL_PROTECT(bombers)
-GLOBAL_LIST_EMPTY(admin_log)
-GLOBAL_PROTECT(admin_log)
-GLOBAL_LIST_EMPTY(lastsignalers) //keeps last 100 signals here in format: "[src] used [REF(src)] @ location [src.loc]: [freq]/[code]"
-GLOBAL_PROTECT(lastsignalers)
-GLOBAL_LIST_EMPTY(lawchanges) //Stores who uploaded laws to which silicon-based lifeform, and what the law was
-GLOBAL_PROTECT(lawchanges)
-
-GLOBAL_LIST_EMPTY(combatlog)
-GLOBAL_PROTECT(combatlog)
-GLOBAL_LIST_EMPTY(IClog)
-GLOBAL_PROTECT(IClog)
-GLOBAL_LIST_EMPTY(OOClog)
-GLOBAL_PROTECT(OOClog)
-GLOBAL_LIST_EMPTY(adminlog)
-GLOBAL_PROTECT(adminlog)
-
-GLOBAL_LIST_EMPTY(active_turfs_startlist)
-
-/////Picture logging
-GLOBAL_VAR(picture_log_directory)
-GLOBAL_PROTECT(picture_log_directory)
-
-GLOBAL_VAR_INIT(picture_logging_id, 1)
-GLOBAL_PROTECT(picture_logging_id)
-GLOBAL_VAR(picture_logging_prefix)
-GLOBAL_PROTECT(picture_logging_prefix)
-/////
+GLOBAL_VAR(log_directory)
+GLOBAL_PROTECT(log_directory)
+GLOBAL_VAR(world_game_log)
+GLOBAL_PROTECT(world_game_log)
+GLOBAL_VAR(world_runtime_log)
+GLOBAL_PROTECT(world_runtime_log)
+GLOBAL_VAR(world_qdel_log)
+GLOBAL_PROTECT(world_qdel_log)
+GLOBAL_VAR(world_attack_log)
+GLOBAL_PROTECT(world_attack_log)
+GLOBAL_VAR(world_href_log)
+GLOBAL_PROTECT(world_href_log)
+GLOBAL_VAR(round_id)
+GLOBAL_PROTECT(round_id)
+GLOBAL_VAR(config_error_log)
+GLOBAL_PROTECT(config_error_log)
+GLOBAL_VAR(sql_error_log)
+GLOBAL_PROTECT(sql_error_log)
+GLOBAL_VAR(world_pda_log)
+GLOBAL_PROTECT(world_pda_log)
+GLOBAL_VAR(world_telecomms_log)
+GLOBAL_PROTECT(world_telecomms_log)
+GLOBAL_VAR(world_manifest_log)
+GLOBAL_PROTECT(world_manifest_log)
+GLOBAL_VAR(query_debug_log)
+GLOBAL_PROTECT(query_debug_log)
+GLOBAL_VAR(world_job_debug_log)
+GLOBAL_PROTECT(world_job_debug_log)
+GLOBAL_VAR(world_virus_log)
+GLOBAL_PROTECT(world_virus_log)
+GLOBAL_VAR(world_map_error_log)
+GLOBAL_PROTECT(world_map_error_log)
+
+GLOBAL_LIST_EMPTY(bombers)
+GLOBAL_PROTECT(bombers)
+GLOBAL_LIST_EMPTY(admin_log)
+GLOBAL_PROTECT(admin_log)
+GLOBAL_LIST_EMPTY(lastsignalers) //keeps last 100 signals here in format: "[src] used [REF(src)] @ location [src.loc]: [freq]/[code]"
+GLOBAL_PROTECT(lastsignalers)
+GLOBAL_LIST_EMPTY(lawchanges) //Stores who uploaded laws to which silicon-based lifeform, and what the law was
+GLOBAL_PROTECT(lawchanges)
+
+GLOBAL_LIST_EMPTY(combatlog)
+GLOBAL_PROTECT(combatlog)
+GLOBAL_LIST_EMPTY(IClog)
+GLOBAL_PROTECT(IClog)
+GLOBAL_LIST_EMPTY(OOClog)
+GLOBAL_PROTECT(OOClog)
+GLOBAL_LIST_EMPTY(adminlog)
+GLOBAL_PROTECT(adminlog)
+
+GLOBAL_LIST_EMPTY(active_turfs_startlist)
+
+/////Picture logging
+GLOBAL_VAR(picture_log_directory)
+GLOBAL_PROTECT(picture_log_directory)
+
+GLOBAL_VAR_INIT(picture_logging_id, 1)
+GLOBAL_PROTECT(picture_logging_id)
+GLOBAL_VAR(picture_logging_prefix)
+GLOBAL_PROTECT(picture_logging_prefix)
+/////
diff --git a/code/controllers/subsystem/air.dm b/code/controllers/subsystem/air.dm
index 1bfdc79d..2a59558b 100644
--- a/code/controllers/subsystem/air.dm
+++ b/code/controllers/subsystem/air.dm
@@ -315,7 +315,7 @@ SUBSYSTEM_DEF(air)
var/starting_ats = active_turfs.len
sleep(world.tick_lag)
var/timer = world.timeofday
- warning("There are [starting_ats] active turfs at roundstart, this is a mapping error caused by a difference of the air between the adjacent turfs. You can see its coordinates using \"Mapping -> Show roundstart AT list\" verb (debug verbs required)")
+ log_mapping("There are [starting_ats] active turfs at roundstart caused by a difference of the air between the adjacent turfs. You can see its coordinates using \"Mapping -> Show roundstart AT list\" verb (debug verbs required).")
for(var/turf/T in active_turfs)
GLOB.active_turfs_startlist += T
diff --git a/code/game/atoms.dm b/code/game/atoms.dm
index 00614f91..e40fabd9 100644
--- a/code/game/atoms.dm
+++ b/code/game/atoms.dm
@@ -53,7 +53,7 @@
/atom/New(loc, ...)
//atom creation method that preloads variables at creation
if(GLOB.use_preloader && (src.type == GLOB._preloader.target_path))//in case the instanciated atom is creating other atoms in New()
- GLOB._preloader.load(src)
+ world.preloader_load(src)
if(datum_flags & DF_USE_TAG)
GenerateTag()
diff --git a/code/game/machinery/doors/airlock.dm b/code/game/machinery/doors/airlock.dm
index 7a2f1fd3..c31c52c5 100644
--- a/code/game/machinery/doors/airlock.dm
+++ b/code/game/machinery/doors/airlock.dm
@@ -179,7 +179,7 @@
limit--
while(!FoundDoor && limit)
if (!FoundDoor)
- log_world("### MAP WARNING, [src] at [AREACOORD(src)] failed to find a valid airlock to cyclelink with!")
+ log_mapping("[src] at [AREACOORD(src)] failed to find a valid airlock to cyclelink with!")
return
FoundDoor.cyclelinkedairlock = src
cyclelinkedairlock = FoundDoor
diff --git a/code/game/objects/items/stunbaton.dm b/code/game/objects/items/stunbaton.dm
index a2435d6f..3a2b9d57 100644
--- a/code/game/objects/items/stunbaton.dm
+++ b/code/game/objects/items/stunbaton.dm
@@ -1,251 +1,251 @@
-#define STUNBATON_CHARGE_LENIENCY 0.3
-
-/obj/item/melee/baton
- name = "stunbaton"
- desc = "A stun baton for incapacitating people with."
- icon_state = "stunbaton"
- item_state = "baton"
- lefthand_file = 'icons/mob/inhands/equipment/security_lefthand.dmi'
- righthand_file = 'icons/mob/inhands/equipment/security_righthand.dmi'
- slot_flags = ITEM_SLOT_BELT
- force = 10
- throwforce = 7
- w_class = WEIGHT_CLASS_NORMAL
- attack_verb = list("beaten")
- armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 50, "bio" = 0, "rad" = 0, "fire" = 80, "acid" = 80)
-
- var/stunforce = 140
- var/status = FALSE
- var/obj/item/stock_parts/cell/cell
- var/hitcost = 1000
- var/throw_hit_chance = 35
- var/preload_cell_type //if not empty the baton starts with this type of cell
-
-/obj/item/melee/baton/get_cell()
- . = cell
- if(iscyborg(loc))
- var/mob/living/silicon/robot/R = loc
- . = R.get_cell()
-
-/obj/item/melee/baton/suicide_act(mob/user)
- user.visible_message("[user] is putting the live [name] in [user.p_their()] mouth! It looks like [user.p_theyre()] trying to commit suicide!")
- return (FIRELOSS)
-
-/obj/item/melee/baton/Initialize()
- . = ..()
- if(preload_cell_type)
- if(!ispath(preload_cell_type,/obj/item/stock_parts/cell))
- log_world("### MAP WARNING, [src] at [AREACOORD(src)] had an invalid preload_cell_type: [preload_cell_type].")
- else
- cell = new preload_cell_type(src)
- update_icon()
-
-/obj/item/melee/baton/throw_impact(atom/hit_atom, datum/thrownthing/throwingdatum)
- ..()
- //Only mob/living types have stun handling
- if(status && prob(throw_hit_chance) && iscarbon(hit_atom))
- baton_stun(hit_atom)
-
-/obj/item/melee/baton/loaded //this one starts with a cell pre-installed.
- preload_cell_type = /obj/item/stock_parts/cell/high
-
-/obj/item/melee/baton/proc/deductcharge(chrgdeductamt, chargecheck = TRUE, explode = TRUE)
- var/obj/item/stock_parts/cell/copper_top = get_cell()
- if(!copper_top)
- switch_status(FALSE, TRUE)
- return FALSE
- //Note this value returned is significant, as it will determine
- //if a stun is applied or not
-
- copper_top.use(min(chrgdeductamt, copper_top.charge), explode)
- if(QDELETED(src))
- return FALSE
- if(status && (!copper_top || !copper_top.charge || (chargecheck && copper_top.charge < (hitcost * STUNBATON_CHARGE_LENIENCY))))
- //we're below minimum, turn off
- switch_status(FALSE)
-
-/obj/item/melee/baton/proc/switch_status(new_status = FALSE, silent = FALSE)
- if(status != new_status)
- status = new_status
- if(!silent)
- playsound(loc, "sparks", 75, 1, -1)
- if(status)
- START_PROCESSING(SSobj, src)
- else
- STOP_PROCESSING(SSobj, src)
- update_icon()
-
-/obj/item/melee/baton/process()
- deductcharge(hitcost * 0.004, FALSE, FALSE)
-
-/obj/item/melee/baton/update_icon()
- if(status)
- icon_state = "[initial(name)]_active"
- else if(!cell)
- icon_state = "[initial(name)]_nocell"
- else
- icon_state = "[initial(name)]"
-
-/obj/item/melee/baton/examine(mob/user)
- . = ..()
- var/obj/item/stock_parts/cell/copper_top = get_cell()
- if(copper_top)
- . += "\The [src] is [round(copper_top.percent())]% charged."
- else
- . += "\The [src] does not have a power source installed."
-
-/obj/item/melee/baton/attackby(obj/item/W, mob/user, params)
- if(istype(W, /obj/item/stock_parts/cell))
- var/obj/item/stock_parts/cell/C = W
- if(cell)
- to_chat(user, "[src] already has a cell.")
- else
- if(C.maxcharge < (hitcost * STUNBATON_CHARGE_LENIENCY))
- to_chat(user, "[src] requires a higher capacity cell.")
- return
- if(!user.transferItemToLoc(W, src))
- return
- cell = W
- to_chat(user, "You install a cell in [src].")
- update_icon()
-
- else if(istype(W, /obj/item/screwdriver))
- if(cell)
- cell.update_icon()
- cell.forceMove(get_turf(src))
- cell = null
- to_chat(user, "You remove the cell from [src].")
- switch_status(FALSE, TRUE)
- else
- return ..()
-
-/obj/item/melee/baton/attack_self(mob/user)
- var/obj/item/stock_parts/cell/copper_top = get_cell()
- if(!copper_top || copper_top.charge < (hitcost * STUNBATON_CHARGE_LENIENCY))
- switch_status(FALSE, TRUE)
- if(!copper_top)
- to_chat(user, "[src] does not have a power source!")
- else
- to_chat(user, "[src] is out of charge.")
- else
- switch_status(!status)
- to_chat(user, "[src] is now [status ? "on" : "off"].")
- add_fingerprint(user)
-
-/obj/item/melee/baton/attack(mob/M, mob/living/carbon/human/user)
- if(status && HAS_TRAIT(user, TRAIT_CLUMSY) && prob(50))
- clowning_around(user)
- return
-
- if(user.getStaminaLoss() >= STAMINA_SOFTCRIT)//CIT CHANGE - makes it impossible to baton in stamina softcrit
- to_chat(user, "You're too exhausted for that.")//CIT CHANGE - ditto
- return //CIT CHANGE - ditto
-
- if(iscyborg(M))
- ..()
- return
-
-
- if(ishuman(M))
- var/mob/living/carbon/human/L = M
- if(check_martial_counter(L, user))
- return
-
- if(user.a_intent != INTENT_HARM)
- if(status)
- if(baton_stun(M, user))
- user.do_attack_animation(M)
- user.adjustStaminaLossBuffered(getweight())//CIT CHANGE - makes stunbatonning others cost stamina
- return
- else
- M.visible_message("[user] has prodded [M] with [src]. Luckily it was off.", \
- "[user] has prodded you with [src]. Luckily it was off")
- else
- if(status)
- baton_stun(M, user)
- ..()
-
-
-/obj/item/melee/baton/proc/baton_stun(mob/living/L, mob/user)
- if(L.check_shields(src, 0, "[user]'s [name]", MELEE_ATTACK)) //No message; check_shields() handles that
- playsound(L, 'sound/weapons/genhit.ogg', 50, 1)
- return FALSE
- var/stunpwr = stunforce
- var/obj/item/stock_parts/cell/our_cell = get_cell()
- if(!our_cell)
- switch_status(FALSE)
- return FALSE
- var/stuncharge = our_cell.charge
- deductcharge(hitcost, FALSE)
- if(QDELETED(src) || QDELETED(our_cell)) //it was rigged
- return FALSE
- if(stuncharge < hitcost)
- if(stuncharge < (hitcost * STUNBATON_CHARGE_LENIENCY))
- L.visible_message("[user] has prodded [L] with [src]. Luckily it was out of charge.", \
- "[user] has prodded you with [src]. Luckily it was out of charge.")
- return FALSE
- stunpwr *= round(stuncharge/hitcost, 0.1)
-
-
- L.Knockdown(stunpwr)
- L.adjustStaminaLoss(stunpwr*0.1, affected_zone = (istype(user) ? user.zone_selected : BODY_ZONE_CHEST))//CIT CHANGE - makes stunbatons deal extra staminaloss. Todo: make this also deal pain when pain gets implemented.
- L.apply_effect(EFFECT_STUTTER, stunforce)
- SEND_SIGNAL(L, COMSIG_LIVING_MINOR_SHOCK)
- if(user)
- L.lastattacker = user.real_name
- L.lastattackerckey = user.ckey
- L.visible_message("[user] has stunned [L] with [src]!", \
- "[user] has stunned you with [src]!")
- log_combat(user, L, "stunned")
-
- playsound(loc, 'sound/weapons/egloves.ogg', 50, 1, -1)
-
- if(ishuman(L))
- var/mob/living/carbon/human/H = L
- H.forcesay(GLOB.hit_appends)
-
-
- return TRUE
-
-/obj/item/melee/baton/proc/clowning_around(mob/living/user)
- user.visible_message("[user] accidentally hits [user.p_them()]self with [src]!", \
- "You accidentally hit yourself with [src]!")
- SEND_SIGNAL(user, COMSIG_LIVING_MINOR_SHOCK)
- user.Knockdown(stunforce*3)
- playsound(loc, 'sound/weapons/egloves.ogg', 50, 1, -1)
- deductcharge(hitcost)
-
-/obj/item/melee/baton/emp_act(severity)
- . = ..()
- if (!(. & EMP_PROTECT_SELF))
- switch_status(FALSE)
- if(!iscyborg(loc))
- deductcharge(1000 / severity, TRUE, FALSE)
-
-//Makeshift stun baton. Replacement for stun gloves.
-/obj/item/melee/baton/cattleprod
- name = "stunprod"
- desc = "An improvised stun baton."
- icon_state = "stunprod_nocell"
- item_state = "prod"
- lefthand_file = 'icons/mob/inhands/weapons/melee_lefthand.dmi'
- righthand_file = 'icons/mob/inhands/weapons/melee_righthand.dmi'
- w_class = WEIGHT_CLASS_BULKY
- force = 3
- throwforce = 5
- stunforce = 100
- hitcost = 2000
- throw_hit_chance = 10
- slot_flags = ITEM_SLOT_BACK
- var/obj/item/assembly/igniter/sparkler
-
-/obj/item/melee/baton/cattleprod/Initialize()
- . = ..()
- sparkler = new (src)
- sparkler.activate_cooldown = 5
-
-/obj/item/melee/baton/cattleprod/baton_stun()
- sparkler?.activate()
- . = ..()
-
-#undef STUNBATON_CHARGE_LENIENCY
+#define STUNBATON_CHARGE_LENIENCY 0.3
+
+/obj/item/melee/baton
+ name = "stunbaton"
+ desc = "A stun baton for incapacitating people with."
+ icon_state = "stunbaton"
+ item_state = "baton"
+ lefthand_file = 'icons/mob/inhands/equipment/security_lefthand.dmi'
+ righthand_file = 'icons/mob/inhands/equipment/security_righthand.dmi'
+ slot_flags = ITEM_SLOT_BELT
+ force = 10
+ throwforce = 7
+ w_class = WEIGHT_CLASS_NORMAL
+ attack_verb = list("beaten")
+ armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 50, "bio" = 0, "rad" = 0, "fire" = 80, "acid" = 80)
+
+ var/stunforce = 140
+ var/status = FALSE
+ var/obj/item/stock_parts/cell/cell
+ var/hitcost = 1000
+ var/throw_hit_chance = 35
+ var/preload_cell_type //if not empty the baton starts with this type of cell
+
+/obj/item/melee/baton/get_cell()
+ . = cell
+ if(iscyborg(loc))
+ var/mob/living/silicon/robot/R = loc
+ . = R.get_cell()
+
+/obj/item/melee/baton/suicide_act(mob/user)
+ user.visible_message("[user] is putting the live [name] in [user.p_their()] mouth! It looks like [user.p_theyre()] trying to commit suicide!")
+ return (FIRELOSS)
+
+/obj/item/melee/baton/Initialize()
+ . = ..()
+ if(preload_cell_type)
+ if(!ispath(preload_cell_type,/obj/item/stock_parts/cell))
+ log_mapping("[src] at [AREACOORD(src)] had an invalid preload_cell_type: [preload_cell_type].")
+ else
+ cell = new preload_cell_type(src)
+ update_icon()
+
+/obj/item/melee/baton/throw_impact(atom/hit_atom, datum/thrownthing/throwingdatum)
+ ..()
+ //Only mob/living types have stun handling
+ if(status && prob(throw_hit_chance) && iscarbon(hit_atom))
+ baton_stun(hit_atom)
+
+/obj/item/melee/baton/loaded //this one starts with a cell pre-installed.
+ preload_cell_type = /obj/item/stock_parts/cell/high
+
+/obj/item/melee/baton/proc/deductcharge(chrgdeductamt, chargecheck = TRUE, explode = TRUE)
+ var/obj/item/stock_parts/cell/copper_top = get_cell()
+ if(!copper_top)
+ switch_status(FALSE, TRUE)
+ return FALSE
+ //Note this value returned is significant, as it will determine
+ //if a stun is applied or not
+
+ copper_top.use(min(chrgdeductamt, copper_top.charge), explode)
+ if(QDELETED(src))
+ return FALSE
+ if(status && (!copper_top || !copper_top.charge || (chargecheck && copper_top.charge < (hitcost * STUNBATON_CHARGE_LENIENCY))))
+ //we're below minimum, turn off
+ switch_status(FALSE)
+
+/obj/item/melee/baton/proc/switch_status(new_status = FALSE, silent = FALSE)
+ if(status != new_status)
+ status = new_status
+ if(!silent)
+ playsound(loc, "sparks", 75, 1, -1)
+ if(status)
+ START_PROCESSING(SSobj, src)
+ else
+ STOP_PROCESSING(SSobj, src)
+ update_icon()
+
+/obj/item/melee/baton/process()
+ deductcharge(hitcost * 0.004, FALSE, FALSE)
+
+/obj/item/melee/baton/update_icon()
+ if(status)
+ icon_state = "[initial(name)]_active"
+ else if(!cell)
+ icon_state = "[initial(name)]_nocell"
+ else
+ icon_state = "[initial(name)]"
+
+/obj/item/melee/baton/examine(mob/user)
+ . = ..()
+ var/obj/item/stock_parts/cell/copper_top = get_cell()
+ if(copper_top)
+ . += "\The [src] is [round(copper_top.percent())]% charged."
+ else
+ . += "\The [src] does not have a power source installed."
+
+/obj/item/melee/baton/attackby(obj/item/W, mob/user, params)
+ if(istype(W, /obj/item/stock_parts/cell))
+ var/obj/item/stock_parts/cell/C = W
+ if(cell)
+ to_chat(user, "[src] already has a cell.")
+ else
+ if(C.maxcharge < (hitcost * STUNBATON_CHARGE_LENIENCY))
+ to_chat(user, "[src] requires a higher capacity cell.")
+ return
+ if(!user.transferItemToLoc(W, src))
+ return
+ cell = W
+ to_chat(user, "You install a cell in [src].")
+ update_icon()
+
+ else if(istype(W, /obj/item/screwdriver))
+ if(cell)
+ cell.update_icon()
+ cell.forceMove(get_turf(src))
+ cell = null
+ to_chat(user, "You remove the cell from [src].")
+ switch_status(FALSE, TRUE)
+ else
+ return ..()
+
+/obj/item/melee/baton/attack_self(mob/user)
+ var/obj/item/stock_parts/cell/copper_top = get_cell()
+ if(!copper_top || copper_top.charge < (hitcost * STUNBATON_CHARGE_LENIENCY))
+ switch_status(FALSE, TRUE)
+ if(!copper_top)
+ to_chat(user, "[src] does not have a power source!")
+ else
+ to_chat(user, "[src] is out of charge.")
+ else
+ switch_status(!status)
+ to_chat(user, "[src] is now [status ? "on" : "off"].")
+ add_fingerprint(user)
+
+/obj/item/melee/baton/attack(mob/M, mob/living/carbon/human/user)
+ if(status && HAS_TRAIT(user, TRAIT_CLUMSY) && prob(50))
+ clowning_around(user)
+ return
+
+ if(user.getStaminaLoss() >= STAMINA_SOFTCRIT)//CIT CHANGE - makes it impossible to baton in stamina softcrit
+ to_chat(user, "You're too exhausted for that.")//CIT CHANGE - ditto
+ return //CIT CHANGE - ditto
+
+ if(iscyborg(M))
+ ..()
+ return
+
+
+ if(ishuman(M))
+ var/mob/living/carbon/human/L = M
+ if(check_martial_counter(L, user))
+ return
+
+ if(user.a_intent != INTENT_HARM)
+ if(status)
+ if(baton_stun(M, user))
+ user.do_attack_animation(M)
+ user.adjustStaminaLossBuffered(getweight())//CIT CHANGE - makes stunbatonning others cost stamina
+ return
+ else
+ M.visible_message("[user] has prodded [M] with [src]. Luckily it was off.", \
+ "[user] has prodded you with [src]. Luckily it was off")
+ else
+ if(status)
+ baton_stun(M, user)
+ ..()
+
+
+/obj/item/melee/baton/proc/baton_stun(mob/living/L, mob/user)
+ if(L.check_shields(src, 0, "[user]'s [name]", MELEE_ATTACK)) //No message; check_shields() handles that
+ playsound(L, 'sound/weapons/genhit.ogg', 50, 1)
+ return FALSE
+ var/stunpwr = stunforce
+ var/obj/item/stock_parts/cell/our_cell = get_cell()
+ if(!our_cell)
+ switch_status(FALSE)
+ return FALSE
+ var/stuncharge = our_cell.charge
+ deductcharge(hitcost, FALSE)
+ if(QDELETED(src) || QDELETED(our_cell)) //it was rigged
+ return FALSE
+ if(stuncharge < hitcost)
+ if(stuncharge < (hitcost * STUNBATON_CHARGE_LENIENCY))
+ L.visible_message("[user] has prodded [L] with [src]. Luckily it was out of charge.", \
+ "[user] has prodded you with [src]. Luckily it was out of charge.")
+ return FALSE
+ stunpwr *= round(stuncharge/hitcost, 0.1)
+
+
+ L.Knockdown(stunpwr)
+ L.adjustStaminaLoss(stunpwr*0.1, affected_zone = (istype(user) ? user.zone_selected : BODY_ZONE_CHEST))//CIT CHANGE - makes stunbatons deal extra staminaloss. Todo: make this also deal pain when pain gets implemented.
+ L.apply_effect(EFFECT_STUTTER, stunforce)
+ SEND_SIGNAL(L, COMSIG_LIVING_MINOR_SHOCK)
+ if(user)
+ L.lastattacker = user.real_name
+ L.lastattackerckey = user.ckey
+ L.visible_message("[user] has stunned [L] with [src]!", \
+ "[user] has stunned you with [src]!")
+ log_combat(user, L, "stunned")
+
+ playsound(loc, 'sound/weapons/egloves.ogg', 50, 1, -1)
+
+ if(ishuman(L))
+ var/mob/living/carbon/human/H = L
+ H.forcesay(GLOB.hit_appends)
+
+
+ return TRUE
+
+/obj/item/melee/baton/proc/clowning_around(mob/living/user)
+ user.visible_message("[user] accidentally hits [user.p_them()]self with [src]!", \
+ "You accidentally hit yourself with [src]!")
+ SEND_SIGNAL(user, COMSIG_LIVING_MINOR_SHOCK)
+ user.Knockdown(stunforce*3)
+ playsound(loc, 'sound/weapons/egloves.ogg', 50, 1, -1)
+ deductcharge(hitcost)
+
+/obj/item/melee/baton/emp_act(severity)
+ . = ..()
+ if (!(. & EMP_PROTECT_SELF))
+ switch_status(FALSE)
+ if(!iscyborg(loc))
+ deductcharge(1000 / severity, TRUE, FALSE)
+
+//Makeshift stun baton. Replacement for stun gloves.
+/obj/item/melee/baton/cattleprod
+ name = "stunprod"
+ desc = "An improvised stun baton."
+ icon_state = "stunprod_nocell"
+ item_state = "prod"
+ lefthand_file = 'icons/mob/inhands/weapons/melee_lefthand.dmi'
+ righthand_file = 'icons/mob/inhands/weapons/melee_righthand.dmi'
+ w_class = WEIGHT_CLASS_BULKY
+ force = 3
+ throwforce = 5
+ stunforce = 100
+ hitcost = 2000
+ throw_hit_chance = 10
+ slot_flags = ITEM_SLOT_BACK
+ var/obj/item/assembly/igniter/sparkler
+
+/obj/item/melee/baton/cattleprod/Initialize()
+ . = ..()
+ sparkler = new (src)
+ sparkler.activate_cooldown = 5
+
+/obj/item/melee/baton/cattleprod/baton_stun()
+ sparkler?.activate()
+ . = ..()
+
+#undef STUNBATON_CHARGE_LENIENCY
diff --git a/code/game/turfs/baseturf_skipover.dm b/code/game/turfs/baseturf_skipover.dm
index 644714f8..4df8c86e 100644
--- a/code/game/turfs/baseturf_skipover.dm
+++ b/code/game/turfs/baseturf_skipover.dm
@@ -10,4 +10,9 @@
/turf/baseturf_skipover/shuttle
name = "Shuttle baseturf skipover"
- desc = "Acts as the bottom of the shuttle, if this isn't here the shuttle floor is broken through."
\ No newline at end of file
+ desc = "Acts as the bottom of the shuttle, if this isn't here the shuttle floor is broken through."
+
+/turf/baseturf_bottom
+ name = "Z-level baseturf placeholder"
+ desc = "Marker for z-level baseturf, usually resolves to space."
+ baseturfs = /turf/baseturf_bottom
diff --git a/code/game/turfs/change_turf.dm b/code/game/turfs/change_turf.dm
index 6a055bbd..84b6cbb3 100644
--- a/code/game/turfs/change_turf.dm
+++ b/code/game/turfs/change_turf.dm
@@ -1,6 +1,7 @@
// This is a list of turf types we dont want to assign to baseturfs unless through initialization or explicitly
GLOBAL_LIST_INIT(blacklisted_automated_baseturfs, typecacheof(list(
/turf/open/space,
+ /turf/baseturf_bottom
)))
/turf/proc/empty(turf_type=/turf/open/space, baseturf_type, list/ignore_typecache, flags)
@@ -56,12 +57,20 @@ GLOBAL_LIST_INIT(blacklisted_automated_baseturfs, typecacheof(list(
// Creates a new turf
// new_baseturfs can be either a single type or list of types, formated the same as baseturfs. see turf.dm
/turf/proc/ChangeTurf(path, list/new_baseturfs, flags)
- if(!path)
- return
- if(path == /turf/open/space/basic)
- // basic doesn't initialize and this will cause issues
- // no warning though because this can happen naturaly as a result of it being built on top of
- path = /turf/open/space
+ switch(path)
+ if(null)
+ return
+ if(/turf/baseturf_bottom)
+ path = SSmapping.level_trait(z, ZTRAIT_BASETURF) || /turf/open/space
+ if (!ispath(path))
+ path = text2path(path)
+ if (!ispath(path))
+ warning("Z-level [z] has invalid baseturf '[SSmapping.level_trait(z, ZTRAIT_BASETURF)]'")
+ path = /turf/open/space
+ if(/turf/open/space/basic)
+ // basic doesn't initialize and this will cause issues
+ // no warning though because this can happen naturaly as a result of it being built on top of
+ path = /turf/open/space
if(!GLOB.use_preloader && path == type && !(flags & CHANGETURF_FORCEOP)) // Don't no-op if the map loader requires it to be reconstructed
return src
if(flags & CHANGETURF_SKIP)
@@ -215,7 +224,7 @@ GLOBAL_LIST_INIT(blacklisted_automated_baseturfs, typecacheof(list(
newT.assemble_baseturfs(initial(fake_turf_type.baseturfs)) // The baseturfs list is created like roundstart
if(!length(newT.baseturfs))
newT.baseturfs = list(baseturfs)
- newT.baseturfs -= newT.baseturfs & GLOB.blacklisted_automated_baseturfs
+ newT.baseturfs -= GLOB.blacklisted_automated_baseturfs
newT.baseturfs.Insert(1, old_baseturfs) // The old baseturfs are put underneath
return newT
if(!length(baseturfs))
diff --git a/code/game/turfs/simulated/floor/plating.dm b/code/game/turfs/simulated/floor/plating.dm
index 47db413e..ad18316c 100644
--- a/code/game/turfs/simulated/floor/plating.dm
+++ b/code/game/turfs/simulated/floor/plating.dm
@@ -11,7 +11,7 @@
name = "plating"
icon_state = "plating"
intact = FALSE
- baseturfs = /turf/open/space
+ baseturfs = /turf/baseturf_bottom
footstep = FOOTSTEP_PLATING
barefootstep = FOOTSTEP_HARD_BAREFOOT
clawfootstep = FOOTSTEP_HARD_CLAW
diff --git a/code/game/turfs/simulated/floor/plating/asteroid.dm b/code/game/turfs/simulated/floor/plating/asteroid.dm
index c66905cd..2533973c 100644
--- a/code/game/turfs/simulated/floor/plating/asteroid.dm
+++ b/code/game/turfs/simulated/floor/plating/asteroid.dm
@@ -76,11 +76,6 @@
for(var/obj/item/stack/ore/O in src)
SEND_SIGNAL(W, COMSIG_PARENT_ATTACKBY, O)
-/turf/open/floor/plating/asteroid/singularity_act()
- if(is_planet_level(z))
- return ..()
- ScrapeAway()
-
/turf/open/floor/plating/asteroid/ex_act(severity, target)
. = SEND_SIGNAL(src, COMSIG_ATOM_EX_ACT, severity, target)
contents_explosion(severity, target)
@@ -131,7 +126,8 @@
/turf/open/floor/plating/asteroid/airless
- initial_gas_mix = "TEMP=2.7"
+ initial_gas_mix = AIRLESS_ATMOS
+ baseturfs = /turf/open/floor/plating/asteroid/airless
turf_type = /turf/open/floor/plating/asteroid/airless
diff --git a/code/game/turfs/turf.dm b/code/game/turfs/turf.dm
index 5652e067..d1394e7c 100644
--- a/code/game/turfs/turf.dm
+++ b/code/game/turfs/turf.dm
@@ -9,7 +9,7 @@
// A list will be created in initialization that figures out the baseturf's baseturf etc.
// In the case of a list it is sorted from bottom layer to top.
// This shouldn't be modified directly, use the helper procs.
- var/list/baseturfs = /turf/open/space
+ var/list/baseturfs = /turf/baseturf_bottom
var/temperature = T20C
var/to_be_destroyed = 0 //Used for fire, if a melting temperature was reached, it will be destroyed
diff --git a/code/game/world.dm b/code/game/world.dm
index 64ebce37..9ed3940b 100644
--- a/code/game/world.dm
+++ b/code/game/world.dm
@@ -1,332 +1,333 @@
-#define RESTART_COUNTER_PATH "data/round_counter.txt"
-#define TOPIC_LENGTH_LIMIT 8192 //The reason why this is so large is to allow TGS topic calls to function without issue.
-#define TOPIC_COOLDOWN 1 //90% sure there isnt anything that does multiple topic calls in a single decisecond.
-
-GLOBAL_VAR(restart_counter)
-
-//This happens after the Master subsystem new(s) (it's a global datum)
-//So subsystems globals exist, but are not initialised
-/world/New()
- var/extools = world.GetConfig("env", "EXTOOLS_DLL") || (world.system_type == MS_WINDOWS ? "./byond-extools.dll" : "./libbyond-extools.so")
- if (fexists(extools))
- call(extools, "maptick_initialize")()
- enable_debugger()
-
- log_world("World loaded at [TIME_STAMP("hh:mm:ss", FALSE)]!")
-
- SetupExternalRSC()
-
- GLOB.config_error_log = GLOB.world_manifest_log = GLOB.world_pda_log = GLOB.world_job_debug_log = GLOB.sql_error_log = GLOB.world_href_log = GLOB.world_runtime_log = GLOB.world_attack_log = GLOB.world_game_log = "data/logs/config_error.[GUID()].log" //temporary file used to record errors with loading config, moved to log directory once logging is set bl
-
- make_datum_references_lists() //initialises global lists for referencing frequently used datums (so that we only ever do it once)
-
- TgsNew()
-
- GLOB.revdata = new
-
- config.Load(params[OVERRIDE_CONFIG_DIRECTORY_PARAMETER])
-
- //SetupLogs depends on the RoundID, so lets check
- //DB schema and set RoundID if we can
- SSdbcore.CheckSchemaVersion()
- SSdbcore.SetRoundID()
- SetupLogs()
-
-#ifndef USE_CUSTOM_ERROR_HANDLER
- world.log = file("[GLOB.log_directory]/dd.log")
-#endif
-
- load_admins()
- load_patreons()
- LoadVerbs(/datum/verbs/menu)
- if(CONFIG_GET(flag/usewhitelist))
- load_whitelist()
- LoadBans()
- reload_custom_roundstart_items_list()//Cit change - loads donator items. Remind me to remove when I port over bay's loadout system
-
- GLOB.timezoneOffset = text2num(time2text(0,"hh")) * 36000
-
- if(fexists(RESTART_COUNTER_PATH))
- GLOB.restart_counter = text2num(trim(file2text(RESTART_COUNTER_PATH)))
- fdel(RESTART_COUNTER_PATH)
-
- if(NO_INIT_PARAMETER in params)
- return
-
- cit_initialize()
-
- Master.Initialize(10, FALSE, TRUE)
-
- if(TEST_RUN_PARAMETER in params)
- HandleTestRun()
-
-/world/proc/HandleTestRun()
- //trigger things to run the whole process
- Master.sleep_offline_after_initializations = FALSE
- SSticker.start_immediately = TRUE
- CONFIG_SET(number/round_end_countdown, 0)
- var/datum/callback/cb
-#ifdef UNIT_TESTS
- cb = CALLBACK(GLOBAL_PROC, /proc/RunUnitTests)
-#else
- cb = VARSET_CALLBACK(SSticker, force_ending, TRUE)
-#endif
- SSticker.OnRoundstart(CALLBACK(GLOBAL_PROC, /proc/addtimer, cb, 10 SECONDS))
-
-/world/proc/SetupExternalRSC()
-#if (PRELOAD_RSC == 0)
- GLOB.external_rsc_urls = world.file2list("[global.config.directory]/external_rsc_urls.txt","\n")
- var/i=1
- while(i<=GLOB.external_rsc_urls.len)
- if(GLOB.external_rsc_urls[i])
- i++
- else
- GLOB.external_rsc_urls.Cut(i,i+1)
-#endif
-
-/world/proc/SetupLogs()
- var/override_dir = params[OVERRIDE_LOG_DIRECTORY_PARAMETER]
- if(!override_dir)
- var/realtime = world.realtime
- var/texttime = time2text(realtime, "YYYY/MM/DD")
- GLOB.log_directory = "data/logs/[texttime]/round-"
- GLOB.picture_logging_prefix = "L_[time2text(realtime, "YYYYMMDD")]_"
- GLOB.picture_log_directory = "data/picture_logs/[texttime]/round-"
- if(GLOB.round_id)
- GLOB.log_directory += "[GLOB.round_id]"
- GLOB.picture_logging_prefix += "R_[GLOB.round_id]_"
- GLOB.picture_log_directory += "[GLOB.round_id]"
- else
- var/timestamp = replacetext(TIME_STAMP("hh:mm:ss", FALSE), ":", ".")
- GLOB.log_directory += "[timestamp]"
- GLOB.picture_log_directory += "[timestamp]"
- GLOB.picture_logging_prefix += "T_[timestamp]_"
- else
- GLOB.log_directory = "data/logs/[override_dir]"
- GLOB.picture_logging_prefix = "O_[override_dir]_"
- GLOB.picture_log_directory = "data/picture_logs/[override_dir]"
-
- GLOB.world_game_log = "[GLOB.log_directory]/game.log"
- GLOB.world_virus_log = "[GLOB.log_directory]/virus.log"
- GLOB.world_attack_log = "[GLOB.log_directory]/attack.log"
- GLOB.world_pda_log = "[GLOB.log_directory]/pda.log"
- GLOB.world_telecomms_log = "[GLOB.log_directory]/telecomms.log"
- GLOB.world_manifest_log = "[GLOB.log_directory]/manifest.log"
- GLOB.world_href_log = "[GLOB.log_directory]/hrefs.log"
- GLOB.sql_error_log = "[GLOB.log_directory]/sql.log"
- GLOB.world_qdel_log = "[GLOB.log_directory]/qdel.log"
- GLOB.world_runtime_log = "[GLOB.log_directory]/runtime.log"
- GLOB.query_debug_log = "[GLOB.log_directory]/query_debug.log"
- GLOB.world_job_debug_log = "[GLOB.log_directory]/job_debug.log"
-
-#ifdef UNIT_TESTS
- GLOB.test_log = file("[GLOB.log_directory]/tests.log")
- start_log(GLOB.test_log)
-#endif
- start_log(GLOB.world_game_log)
- start_log(GLOB.world_attack_log)
- start_log(GLOB.world_pda_log)
- start_log(GLOB.world_telecomms_log)
- start_log(GLOB.world_manifest_log)
- start_log(GLOB.world_href_log)
- start_log(GLOB.world_qdel_log)
- start_log(GLOB.world_runtime_log)
- start_log(GLOB.world_job_debug_log)
-
- GLOB.changelog_hash = md5('html/changelog.html') //for telling if the changelog has changed recently
- if(fexists(GLOB.config_error_log))
- fcopy(GLOB.config_error_log, "[GLOB.log_directory]/config_error.log")
- fdel(GLOB.config_error_log)
-
- if(GLOB.round_id)
- log_game("Round ID: [GLOB.round_id]")
-
- // This was printed early in startup to the world log and config_error.log,
- // but those are both private, so let's put the commit info in the runtime
- // log which is ultimately public.
- log_runtime(GLOB.revdata.get_log_message())
-
-/world/Topic(T, addr, master, key)
- var/static/list/bannedsourceaddrs = list()
- var/static/list/lasttimeaddr = list()
-
- if(addr in bannedsourceaddrs)
- return
-
- if(length(T) >= TOPIC_LENGTH_LIMIT)
- log_topic("Oversized topic, banning address. from:[addr]")
- bannedsourceaddrs |= addr
- return
-
- if(addr in lasttimeaddr && world.time < (lasttimeaddr["[addr]"] + TOPIC_COOLDOWN))
- log_topic("Too many topic calls from address in [TOPIC_COOLDOWN] ds, banning address. from:[addr]")
- bannedsourceaddrs |= addr
- return
-
- lasttimeaddr["[addr]"] = world.time
-
-
- TGS_TOPIC //redirect to server tools if necessary
-
- var/static/list/topic_handlers = TopicHandlers()
-
- var/list/input = params2list(T)
- var/datum/world_topic/handler
- for(var/I in topic_handlers)
- if(I in input)
- handler = topic_handlers[I]
- break
-
- if((!handler || initial(handler.log)) && config && CONFIG_GET(flag/log_world_topic))
- log_topic("\"[T]\", from:[addr], master:[master], key:[key]")
-
- if(!handler)
- return
-
- handler = new handler()
- return handler.TryRun(input)
-
-/world/proc/AnnouncePR(announcement, list/payload)
- var/static/list/PRcounts = list() //PR id -> number of times announced this round
- var/id = "[payload["pull_request"]["id"]]"
- if(!PRcounts[id])
- PRcounts[id] = 1
- else
- ++PRcounts[id]
- if(PRcounts[id] > PR_ANNOUNCEMENTS_PER_ROUND)
- return
-
- var/final_composed = "PR: [announcement]"
- for(var/client/C in GLOB.clients)
- C.AnnouncePR(final_composed)
-
-/world/proc/FinishTestRun()
- set waitfor = FALSE
- var/list/fail_reasons
- if(GLOB)
- if(GLOB.total_runtimes != 0)
- fail_reasons = list("Total runtimes: [GLOB.total_runtimes]")
-#ifdef UNIT_TESTS
- if(GLOB.failed_any_test)
- LAZYADD(fail_reasons, "Unit Tests failed!")
-#endif
- if(!GLOB.log_directory)
- LAZYADD(fail_reasons, "Missing GLOB.log_directory!")
- else
- fail_reasons = list("Missing GLOB!")
- if(!fail_reasons)
- text2file("Success!", "[GLOB.log_directory]/clean_run.lk")
- else
- log_world("Test run failed!\n[fail_reasons.Join("\n")]")
- sleep(0) //yes, 0, this'll let Reboot finish and prevent byond memes
- qdel(src) //shut it down
-
-/world/Reboot(reason = 0, fast_track = FALSE)
- TgsReboot()
- if (reason || fast_track) //special reboot, do none of the normal stuff
- if (usr)
- log_admin("[key_name(usr)] Has requested an immediate world restart via client side debugging tools")
- message_admins("[key_name_admin(usr)] Has requested an immediate world restart via client side debugging tools")
- to_chat(world, "Rebooting World immediately due to host request")
- else
- to_chat(world, "Rebooting world...")
- Master.Shutdown() //run SS shutdowns
-
- if(TEST_RUN_PARAMETER in params)
- FinishTestRun()
- return
-
- if(TgsAvailable())
- var/do_hard_reboot
- // check the hard reboot counter
- var/ruhr = CONFIG_GET(number/rounds_until_hard_restart)
- switch(ruhr)
- if(-1)
- do_hard_reboot = FALSE
- if(0)
- do_hard_reboot = TRUE
- else
- if(GLOB.restart_counter >= ruhr)
- do_hard_reboot = TRUE
- else
- text2file("[++GLOB.restart_counter]", RESTART_COUNTER_PATH)
- do_hard_reboot = FALSE
-
- if(do_hard_reboot)
- log_world("World hard rebooted at [TIME_STAMP("hh:mm:ss", FALSE)]")
- shutdown_logging() // See comment below.
- TgsEndProcess()
-
- log_world("World rebooted at [TIME_STAMP("hh:mm:ss", FALSE)]")
- shutdown_logging() // Past this point, no logging procs can be used, at risk of data loss.
- ..()
-
-/world/proc/update_status()
-
- var/list/features = list()
-
- /*if(GLOB.master_mode) CIT CHANGE - hides the gamemode from the hub entry, removes some useless info from the hub entry
- features += GLOB.master_mode
-
- if (!GLOB.enter_allowed)
- features += "closed"*/
-
- var/s = ""
- var/hostedby
- if(config)
- var/server_name = CONFIG_GET(string/servername)
- if (server_name)
- s += "[server_name] — "
- /*features += "[CONFIG_GET(flag/norespawn) ? "no " : ""]respawn" CIT CHANGE - removes some useless info from the hub entry
- if(CONFIG_GET(flag/allow_vote_mode))
- features += "vote"
- if(CONFIG_GET(flag/allow_ai))
- features += "AI allowed"*/
- hostedby = CONFIG_GET(string/hostedby)
-
- s += "[station_name()]";
- s += " ("
- s += "" //Change this to wherever you want the hub to link to. CIT CHANGE - links to cit's website on the hub
- s += "Website" //Replace this with something else. Or ever better, delete it and uncomment the game version. CIT CHANGE - modifies the hub entry link
- s += ""
- s += ")\]" //CIT CHANGE - encloses the server title in brackets to make the hub entry fancier
- s += "
[CONFIG_GET(string/servertagline)]
" //CIT CHANGE - adds a tagline!
-
- var/n = 0
- for (var/mob/M in GLOB.player_list)
- if (M.client)
- n++
-
- if(SSmapping.config) // this just stops the runtime, honk.
- features += "[SSmapping.config.map_name]" //CIT CHANGE - makes the hub entry display the current map
-
- if(get_security_level())//CIT CHANGE - makes the hub entry show the security level
- features += "[get_security_level()] alert"
-
- if (n > 1)
- features += "~[n] players"
- else if (n > 0)
- features += "~[n] player"
-
- if (!host && hostedby)
- features += "hosted by [hostedby]"
-
- if (features)
- s += "\[[jointext(features, ", ")]" //CIT CHANGE - replaces the colon here with a left bracket
-
- status = s
-
-/world/proc/update_hub_visibility(new_visibility)
- if(new_visibility == GLOB.hub_visibility)
- return
- GLOB.hub_visibility = new_visibility
- if(GLOB.hub_visibility)
- hub_password = "kMZy3U5jJHSiBQjr"
- else
- hub_password = "SORRYNOPASSWORD"
-
-/world/proc/incrementMaxZ()
- maxz++
- SSmobs.MaxZChanged()
- SSidlenpcpool.MaxZChanged()
-
+#define RESTART_COUNTER_PATH "data/round_counter.txt"
+#define TOPIC_LENGTH_LIMIT 8192 //The reason why this is so large is to allow TGS topic calls to function without issue.
+#define TOPIC_COOLDOWN 1 //90% sure there isnt anything that does multiple topic calls in a single decisecond.
+
+GLOBAL_VAR(restart_counter)
+
+//This happens after the Master subsystem new(s) (it's a global datum)
+//So subsystems globals exist, but are not initialised
+/world/New()
+ var/extools = world.GetConfig("env", "EXTOOLS_DLL") || (world.system_type == MS_WINDOWS ? "./byond-extools.dll" : "./libbyond-extools.so")
+ if (fexists(extools))
+ call(extools, "maptick_initialize")()
+ enable_debugger()
+
+ log_world("World loaded at [TIME_STAMP("hh:mm:ss", FALSE)]!")
+
+ SetupExternalRSC()
+
+ GLOB.config_error_log = GLOB.world_manifest_log = GLOB.world_pda_log = GLOB.world_job_debug_log = GLOB.sql_error_log = GLOB.world_href_log = GLOB.world_runtime_log = GLOB.world_attack_log = GLOB.world_game_log = "data/logs/config_error.[GUID()].log" //temporary file used to record errors with loading config, moved to log directory once logging is set bl
+
+ make_datum_references_lists() //initialises global lists for referencing frequently used datums (so that we only ever do it once)
+
+ TgsNew()
+
+ GLOB.revdata = new
+
+ config.Load(params[OVERRIDE_CONFIG_DIRECTORY_PARAMETER])
+
+ //SetupLogs depends on the RoundID, so lets check
+ //DB schema and set RoundID if we can
+ SSdbcore.CheckSchemaVersion()
+ SSdbcore.SetRoundID()
+ SetupLogs()
+
+#ifndef USE_CUSTOM_ERROR_HANDLER
+ world.log = file("[GLOB.log_directory]/dd.log")
+#endif
+
+ load_admins()
+ load_patreons()
+ LoadVerbs(/datum/verbs/menu)
+ if(CONFIG_GET(flag/usewhitelist))
+ load_whitelist()
+ LoadBans()
+ reload_custom_roundstart_items_list()//Cit change - loads donator items. Remind me to remove when I port over bay's loadout system
+
+ GLOB.timezoneOffset = text2num(time2text(0,"hh")) * 36000
+
+ if(fexists(RESTART_COUNTER_PATH))
+ GLOB.restart_counter = text2num(trim(file2text(RESTART_COUNTER_PATH)))
+ fdel(RESTART_COUNTER_PATH)
+
+ if(NO_INIT_PARAMETER in params)
+ return
+
+ cit_initialize()
+
+ Master.Initialize(10, FALSE, TRUE)
+
+ if(TEST_RUN_PARAMETER in params)
+ HandleTestRun()
+
+/world/proc/HandleTestRun()
+ //trigger things to run the whole process
+ Master.sleep_offline_after_initializations = FALSE
+ SSticker.start_immediately = TRUE
+ CONFIG_SET(number/round_end_countdown, 0)
+ var/datum/callback/cb
+#ifdef UNIT_TESTS
+ cb = CALLBACK(GLOBAL_PROC, /proc/RunUnitTests)
+#else
+ cb = VARSET_CALLBACK(SSticker, force_ending, TRUE)
+#endif
+ SSticker.OnRoundstart(CALLBACK(GLOBAL_PROC, /proc/addtimer, cb, 10 SECONDS))
+
+/world/proc/SetupExternalRSC()
+#if (PRELOAD_RSC == 0)
+ GLOB.external_rsc_urls = world.file2list("[global.config.directory]/external_rsc_urls.txt","\n")
+ var/i=1
+ while(i<=GLOB.external_rsc_urls.len)
+ if(GLOB.external_rsc_urls[i])
+ i++
+ else
+ GLOB.external_rsc_urls.Cut(i,i+1)
+#endif
+
+/world/proc/SetupLogs()
+ var/override_dir = params[OVERRIDE_LOG_DIRECTORY_PARAMETER]
+ if(!override_dir)
+ var/realtime = world.realtime
+ var/texttime = time2text(realtime, "YYYY/MM/DD")
+ GLOB.log_directory = "data/logs/[texttime]/round-"
+ GLOB.picture_logging_prefix = "L_[time2text(realtime, "YYYYMMDD")]_"
+ GLOB.picture_log_directory = "data/picture_logs/[texttime]/round-"
+ if(GLOB.round_id)
+ GLOB.log_directory += "[GLOB.round_id]"
+ GLOB.picture_logging_prefix += "R_[GLOB.round_id]_"
+ GLOB.picture_log_directory += "[GLOB.round_id]"
+ else
+ var/timestamp = replacetext(TIME_STAMP("hh:mm:ss", FALSE), ":", ".")
+ GLOB.log_directory += "[timestamp]"
+ GLOB.picture_log_directory += "[timestamp]"
+ GLOB.picture_logging_prefix += "T_[timestamp]_"
+ else
+ GLOB.log_directory = "data/logs/[override_dir]"
+ GLOB.picture_logging_prefix = "O_[override_dir]_"
+ GLOB.picture_log_directory = "data/picture_logs/[override_dir]"
+
+ GLOB.world_game_log = "[GLOB.log_directory]/game.log"
+ GLOB.world_virus_log = "[GLOB.log_directory]/virus.log"
+ GLOB.world_attack_log = "[GLOB.log_directory]/attack.log"
+ GLOB.world_pda_log = "[GLOB.log_directory]/pda.log"
+ GLOB.world_telecomms_log = "[GLOB.log_directory]/telecomms.log"
+ GLOB.world_manifest_log = "[GLOB.log_directory]/manifest.log"
+ GLOB.world_href_log = "[GLOB.log_directory]/hrefs.log"
+ GLOB.sql_error_log = "[GLOB.log_directory]/sql.log"
+ GLOB.world_qdel_log = "[GLOB.log_directory]/qdel.log"
+ GLOB.world_map_error_log = "[GLOB.log_directory]/map_errors.log"
+ GLOB.world_runtime_log = "[GLOB.log_directory]/runtime.log"
+ GLOB.query_debug_log = "[GLOB.log_directory]/query_debug.log"
+ GLOB.world_job_debug_log = "[GLOB.log_directory]/job_debug.log"
+
+#ifdef UNIT_TESTS
+ GLOB.test_log = file("[GLOB.log_directory]/tests.log")
+ start_log(GLOB.test_log)
+#endif
+ start_log(GLOB.world_game_log)
+ start_log(GLOB.world_attack_log)
+ start_log(GLOB.world_pda_log)
+ start_log(GLOB.world_telecomms_log)
+ start_log(GLOB.world_manifest_log)
+ start_log(GLOB.world_href_log)
+ start_log(GLOB.world_qdel_log)
+ start_log(GLOB.world_runtime_log)
+ start_log(GLOB.world_job_debug_log)
+
+ GLOB.changelog_hash = md5('html/changelog.html') //for telling if the changelog has changed recently
+ if(fexists(GLOB.config_error_log))
+ fcopy(GLOB.config_error_log, "[GLOB.log_directory]/config_error.log")
+ fdel(GLOB.config_error_log)
+
+ if(GLOB.round_id)
+ log_game("Round ID: [GLOB.round_id]")
+
+ // This was printed early in startup to the world log and config_error.log,
+ // but those are both private, so let's put the commit info in the runtime
+ // log which is ultimately public.
+ log_runtime(GLOB.revdata.get_log_message())
+
+/world/Topic(T, addr, master, key)
+ var/static/list/bannedsourceaddrs = list()
+ var/static/list/lasttimeaddr = list()
+
+ if(addr in bannedsourceaddrs)
+ return
+
+ if(length(T) >= TOPIC_LENGTH_LIMIT)
+ log_topic("Oversized topic, banning address. from:[addr]")
+ bannedsourceaddrs |= addr
+ return
+
+ if(addr in lasttimeaddr && world.time < (lasttimeaddr["[addr]"] + TOPIC_COOLDOWN))
+ log_topic("Too many topic calls from address in [TOPIC_COOLDOWN] ds, banning address. from:[addr]")
+ bannedsourceaddrs |= addr
+ return
+
+ lasttimeaddr["[addr]"] = world.time
+
+
+ TGS_TOPIC //redirect to server tools if necessary
+
+ var/static/list/topic_handlers = TopicHandlers()
+
+ var/list/input = params2list(T)
+ var/datum/world_topic/handler
+ for(var/I in topic_handlers)
+ if(I in input)
+ handler = topic_handlers[I]
+ break
+
+ if((!handler || initial(handler.log)) && config && CONFIG_GET(flag/log_world_topic))
+ log_topic("\"[T]\", from:[addr], master:[master], key:[key]")
+
+ if(!handler)
+ return
+
+ handler = new handler()
+ return handler.TryRun(input)
+
+/world/proc/AnnouncePR(announcement, list/payload)
+ var/static/list/PRcounts = list() //PR id -> number of times announced this round
+ var/id = "[payload["pull_request"]["id"]]"
+ if(!PRcounts[id])
+ PRcounts[id] = 1
+ else
+ ++PRcounts[id]
+ if(PRcounts[id] > PR_ANNOUNCEMENTS_PER_ROUND)
+ return
+
+ var/final_composed = "PR: [announcement]"
+ for(var/client/C in GLOB.clients)
+ C.AnnouncePR(final_composed)
+
+/world/proc/FinishTestRun()
+ set waitfor = FALSE
+ var/list/fail_reasons
+ if(GLOB)
+ if(GLOB.total_runtimes != 0)
+ fail_reasons = list("Total runtimes: [GLOB.total_runtimes]")
+#ifdef UNIT_TESTS
+ if(GLOB.failed_any_test)
+ LAZYADD(fail_reasons, "Unit Tests failed!")
+#endif
+ if(!GLOB.log_directory)
+ LAZYADD(fail_reasons, "Missing GLOB.log_directory!")
+ else
+ fail_reasons = list("Missing GLOB!")
+ if(!fail_reasons)
+ text2file("Success!", "[GLOB.log_directory]/clean_run.lk")
+ else
+ log_world("Test run failed!\n[fail_reasons.Join("\n")]")
+ sleep(0) //yes, 0, this'll let Reboot finish and prevent byond memes
+ qdel(src) //shut it down
+
+/world/Reboot(reason = 0, fast_track = FALSE)
+ TgsReboot()
+ if (reason || fast_track) //special reboot, do none of the normal stuff
+ if (usr)
+ log_admin("[key_name(usr)] Has requested an immediate world restart via client side debugging tools")
+ message_admins("[key_name_admin(usr)] Has requested an immediate world restart via client side debugging tools")
+ to_chat(world, "Rebooting World immediately due to host request")
+ else
+ to_chat(world, "Rebooting world...")
+ Master.Shutdown() //run SS shutdowns
+
+ if(TEST_RUN_PARAMETER in params)
+ FinishTestRun()
+ return
+
+ if(TgsAvailable())
+ var/do_hard_reboot
+ // check the hard reboot counter
+ var/ruhr = CONFIG_GET(number/rounds_until_hard_restart)
+ switch(ruhr)
+ if(-1)
+ do_hard_reboot = FALSE
+ if(0)
+ do_hard_reboot = TRUE
+ else
+ if(GLOB.restart_counter >= ruhr)
+ do_hard_reboot = TRUE
+ else
+ text2file("[++GLOB.restart_counter]", RESTART_COUNTER_PATH)
+ do_hard_reboot = FALSE
+
+ if(do_hard_reboot)
+ log_world("World hard rebooted at [TIME_STAMP("hh:mm:ss", FALSE)]")
+ shutdown_logging() // See comment below.
+ TgsEndProcess()
+
+ log_world("World rebooted at [TIME_STAMP("hh:mm:ss", FALSE)]")
+ shutdown_logging() // Past this point, no logging procs can be used, at risk of data loss.
+ ..()
+
+/world/proc/update_status()
+
+ var/list/features = list()
+
+ /*if(GLOB.master_mode) CIT CHANGE - hides the gamemode from the hub entry, removes some useless info from the hub entry
+ features += GLOB.master_mode
+
+ if (!GLOB.enter_allowed)
+ features += "closed"*/
+
+ var/s = ""
+ var/hostedby
+ if(config)
+ var/server_name = CONFIG_GET(string/servername)
+ if (server_name)
+ s += "[server_name] — "
+ /*features += "[CONFIG_GET(flag/norespawn) ? "no " : ""]respawn" CIT CHANGE - removes some useless info from the hub entry
+ if(CONFIG_GET(flag/allow_vote_mode))
+ features += "vote"
+ if(CONFIG_GET(flag/allow_ai))
+ features += "AI allowed"*/
+ hostedby = CONFIG_GET(string/hostedby)
+
+ s += "[station_name()]";
+ s += " ("
+ s += "" //Change this to wherever you want the hub to link to. CIT CHANGE - links to cit's website on the hub
+ s += "Website" //Replace this with something else. Or ever better, delete it and uncomment the game version. CIT CHANGE - modifies the hub entry link
+ s += ""
+ s += ")\]" //CIT CHANGE - encloses the server title in brackets to make the hub entry fancier
+ s += "
[CONFIG_GET(string/servertagline)]
" //CIT CHANGE - adds a tagline!
+
+ var/n = 0
+ for (var/mob/M in GLOB.player_list)
+ if (M.client)
+ n++
+
+ if(SSmapping.config) // this just stops the runtime, honk.
+ features += "[SSmapping.config.map_name]" //CIT CHANGE - makes the hub entry display the current map
+
+ if(get_security_level())//CIT CHANGE - makes the hub entry show the security level
+ features += "[get_security_level()] alert"
+
+ if (n > 1)
+ features += "~[n] players"
+ else if (n > 0)
+ features += "~[n] player"
+
+ if (!host && hostedby)
+ features += "hosted by [hostedby]"
+
+ if (features)
+ s += "\[[jointext(features, ", ")]" //CIT CHANGE - replaces the colon here with a left bracket
+
+ status = s
+
+/world/proc/update_hub_visibility(new_visibility)
+ if(new_visibility == GLOB.hub_visibility)
+ return
+ GLOB.hub_visibility = new_visibility
+ if(GLOB.hub_visibility)
+ hub_password = "kMZy3U5jJHSiBQjr"
+ else
+ hub_password = "SORRYNOPASSWORD"
+
+/world/proc/incrementMaxZ()
+ maxz++
+ SSmobs.MaxZChanged()
+ SSidlenpcpool.MaxZChanged()
+
diff --git a/code/modules/admin/verbs/mapping.dm b/code/modules/admin/verbs/mapping.dm
index 0fe8859c..3a0b1e97 100644
--- a/code/modules/admin/verbs/mapping.dm
+++ b/code/modules/admin/verbs/mapping.dm
@@ -1,358 +1,377 @@
-//- Are all the floors with or without air, as they should be? (regular or airless)
-//- Does the area have an APC?
-//- Does the area have an Air Alarm?
-//- Does the area have a Request Console?
-//- Does the area have lights?
-//- Does the area have a light switch?
-//- Does the area have enough intercoms?
-//- Does the area have enough security cameras? (Use the 'Camera Range Display' verb under Debug)
-//- Is the area connected to the scrubbers air loop?
-//- Is the area connected to the vent air loop? (vent pumps)
-//- Is everything wired properly?
-//- Does the area have a fire alarm and firedoors?
-//- Do all pod doors work properly?
-//- Are accesses set properly on doors, pod buttons, etc.
-//- Are all items placed properly? (not below vents, scrubbers, tables)
-//- Does the disposal system work properly from all the disposal units in this room and all the units, the pipes of which pass through this room?
-//- Check for any misplaced or stacked piece of pipe (air and disposal)
-//- Check for any misplaced or stacked piece of wire
-//- Identify how hard it is to break into the area and where the weak points are
-//- Check if the area has too much empty space. If so, make it smaller and replace the rest with maintenance tunnels.
-
-GLOBAL_PROTECT(admin_verbs_debug_mapping)
-GLOBAL_LIST_INIT(admin_verbs_debug_mapping, list(
- /client/proc/camera_view, //-errorage
- /client/proc/sec_camera_report, //-errorage
- /client/proc/intercom_view, //-errorage
- /client/proc/air_status, //Air things
- /client/proc/Cell, //More air things
- /client/proc/atmosscan, //check plumbing
- /client/proc/powerdebug, //check power
- /client/proc/count_objects_on_z_level,
- /client/proc/count_objects_all,
- /client/proc/cmd_assume_direct_control, //-errorage
- /client/proc/startSinglo,
- /client/proc/set_server_fps, //allows you to set the ticklag.
- /client/proc/cmd_admin_grantfullaccess,
- /client/proc/cmd_admin_areatest_all,
- /client/proc/cmd_admin_areatest_station,
- /client/proc/cmd_admin_test_atmos_controllers,
- /client/proc/cmd_admin_rejuvenate,
- /datum/admins/proc/show_traitor_panel,
- /client/proc/disable_communication,
- /client/proc/cmd_show_at_list,
- /client/proc/cmd_show_at_markers,
- /client/proc/manipulate_organs,
- /client/proc/start_line_profiling,
- /client/proc/stop_line_profiling,
- /client/proc/show_line_profiling,
- /client/proc/create_mapping_job_icons,
- /client/proc/debug_z_levels,
- /client/proc/place_ruin
-))
-
-/obj/effect/debugging/mapfix_marker
- name = "map fix marker"
- icon = 'icons/mob/screen_gen.dmi'
- icon_state = "mapfixmarker"
- desc = "I am a mappers mistake."
-
-/obj/effect/debugging/marker
- icon = 'icons/turf/areas.dmi'
- icon_state = "yellow"
-
-/obj/effect/debugging/marker/Move()
- return 0
-
-/client/proc/camera_view()
- set category = "Mapping"
- set name = "Camera Range Display"
-
- var/on = FALSE
- for(var/turf/T in world)
- if(T.maptext)
- on = TRUE
- T.maptext = null
-
- if(!on)
- var/list/seen = list()
- for(var/obj/machinery/camera/C in GLOB.cameranet.cameras)
- for(var/turf/T in C.can_see())
- seen[T]++
- for(var/turf/T in seen)
- T.maptext = "[seen[T]]"
- SSblackbox.record_feedback("tally", "admin_verb", 1, "Show Camera Range") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
- SSblackbox.record_feedback("tally", "admin_verb", 1, "Show Camera Range")
-
-
-
-/client/proc/sec_camera_report()
- set category = "Mapping"
- set name = "Camera Report"
-
- if(!Master)
- alert(usr,"Master_controller not found.","Sec Camera Report")
- return 0
-
- var/list/obj/machinery/camera/CL = list()
-
- for(var/obj/machinery/camera/C in GLOB.cameranet.cameras)
- CL += C
-
- var/output = {"Camera Abnormalities Report
-The following abnormalities have been detected. The ones in red need immediate attention: Some of those in black may be intentional.
"}
-
- for(var/obj/machinery/camera/C1 in CL)
- for(var/obj/machinery/camera/C2 in CL)
- if(C1 != C2)
- if(C1.c_tag == C2.c_tag)
- output += "- c_tag match for cameras at [ADMIN_VERBOSEJMP(C1)] and [ADMIN_VERBOSEJMP(C2)] - c_tag is [C1.c_tag]
"
- if(C1.loc == C2.loc && C1.dir == C2.dir && C1.pixel_x == C2.pixel_x && C1.pixel_y == C2.pixel_y)
- output += "- FULLY overlapping cameras at [ADMIN_VERBOSEJMP(C1)] Networks: [json_encode(C1.network)] and [json_encode(C2.network)]
"
- if(C1.loc == C2.loc)
- output += "- Overlapping cameras at [ADMIN_VERBOSEJMP(C1)] Networks: [json_encode(C1.network)] and [json_encode(C2.network)]
"
- var/turf/T = get_step(C1,turn(C1.dir,180))
- if(!T || !isturf(T) || !T.density )
- if(!(locate(/obj/structure/grille) in T))
- var/window_check = 0
- for(var/obj/structure/window/W in T)
- if (W.dir == turn(C1.dir,180) || W.dir in list(5,6,9,10) )
- window_check = 1
- break
- if(!window_check)
- output += "- Camera not connected to wall at [ADMIN_VERBOSEJMP(C1)] Network: [json_encode(C1.network)]
"
-
- output += "
"
- usr << browse(output,"window=airreport;size=1000x500")
- SSblackbox.record_feedback("tally", "admin_verb", 1, "Show Camera Report") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
-
-/client/proc/intercom_view()
- set category = "Mapping"
- set name = "Intercom Range Display"
-
- var/static/intercom_range_display_status = FALSE
- intercom_range_display_status = !intercom_range_display_status //blame cyberboss if this breaks something
-
- for(var/obj/effect/debugging/marker/M in world)
- qdel(M)
-
- if(intercom_range_display_status)
- for(var/obj/item/radio/intercom/I in world)
- for(var/turf/T in orange(7,I))
- var/obj/effect/debugging/marker/F = new/obj/effect/debugging/marker(T)
- if (!(F in view(7,I.loc)))
- qdel(F)
- SSblackbox.record_feedback("tally", "admin_verb", 1, "Show Intercom Range") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
-
-/client/proc/cmd_show_at_list()
- set category = "Mapping"
- set name = "Show roundstart AT list"
- set desc = "Displays a list of active turfs coordinates at roundstart"
-
- var/dat = {"Coordinate list of Active Turfs at Roundstart
-
Real-time Active Turfs list you can see in Air Subsystem at active_turfs var
"}
-
- for(var/t in GLOB.active_turfs_startlist)
- var/turf/T = t
- dat += "[ADMIN_VERBOSEJMP(T)]\n"
- dat += "
"
-
- usr << browse(dat, "window=at_list")
-
- SSblackbox.record_feedback("tally", "admin_verb", 1, "Show Roundstart Active Turfs") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
-
-/client/proc/cmd_show_at_markers()
- set category = "Mapping"
- set name = "Show roundstart AT markers"
- set desc = "Places a marker on all active-at-roundstart turfs"
-
- var/count = 0
- for(var/obj/effect/abstract/marker/at/AT in GLOB.all_abstract_markers)
- qdel(AT)
- count++
-
- if(count)
- to_chat(usr, "[count] AT markers removed.")
- else
- for(var/t in GLOB.active_turfs_startlist)
- new /obj/effect/abstract/marker/at(t)
- count++
- to_chat(usr, "[count] AT markers placed.")
-
- SSblackbox.record_feedback("tally", "admin_verb", 1, "Show Roundstart Active Turf Markers")
-
-/client/proc/enable_debug_verbs()
- set category = "Debug"
- set name = "Debug verbs - Enable"
- if(!check_rights(R_DEBUG))
- return
- verbs -= /client/proc/enable_debug_verbs
- verbs.Add(/client/proc/disable_debug_verbs, GLOB.admin_verbs_debug_mapping)
- SSblackbox.record_feedback("tally", "admin_verb", 1, "Enable Debug Verbs") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
-
-/client/proc/disable_debug_verbs()
- set category = "Debug"
- set name = "Debug verbs - Disable"
- verbs.Remove(/client/proc/disable_debug_verbs, GLOB.admin_verbs_debug_mapping)
- verbs += /client/proc/enable_debug_verbs
- SSblackbox.record_feedback("tally", "admin_verb", 1, "Disable Debug Verbs") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
-
-/client/proc/count_objects_on_z_level()
- set category = "Mapping"
- set name = "Count Objects On Level"
- var/level = input("Which z-level?","Level?") as text
- if(!level)
- return
- var/num_level = text2num(level)
- if(!num_level)
- return
- if(!isnum(num_level))
- return
-
- var/type_text = input("Which type path?","Path?") as text
- if(!type_text)
- return
- var/type_path = text2path(type_text)
- if(!type_path)
- return
-
- var/count = 0
-
- var/list/atom/atom_list = list()
-
- for(var/atom/A in world)
- if(istype(A,type_path))
- var/atom/B = A
- while(!(isturf(B.loc)))
- if(B && B.loc)
- B = B.loc
- else
- break
- if(B)
- if(B.z == num_level)
- count++
- atom_list += A
-
- to_chat(world, "There are [count] objects of type [type_path] on z-level [num_level]")
- SSblackbox.record_feedback("tally", "admin_verb", 1, "Count Objects Zlevel") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
-
-/client/proc/count_objects_all()
- set category = "Mapping"
- set name = "Count Objects All"
-
- var/type_text = input("Which type path?","") as text
- if(!type_text)
- return
- var/type_path = text2path(type_text)
- if(!type_path)
- return
-
- var/count = 0
-
- for(var/atom/A in world)
- if(istype(A,type_path))
- count++
-
- to_chat(world, "There are [count] objects of type [type_path] in the game world")
- SSblackbox.record_feedback("tally", "admin_verb", 1, "Count Objects All") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
-
-
-//This proc is intended to detect lag problems relating to communication procs
-GLOBAL_VAR_INIT(say_disabled, FALSE)
-/client/proc/disable_communication()
- set category = "Mapping"
- set name = "Disable all communication verbs"
-
- GLOB.say_disabled = !GLOB.say_disabled
- if(GLOB.say_disabled)
- message_admins("[key] used 'Disable all communication verbs', killing all communication methods.")
- else
- message_admins("[key] used 'Disable all communication verbs', restoring all communication methods.")
-
-//This generates the icon states for job starting location landmarks.
-/client/proc/create_mapping_job_icons()
- set name = "Generate job landmarks icons"
- set category = "Mapping"
- var/icon/final = icon()
- var/mob/living/carbon/human/dummy/D = new(locate(1,1,1)) //spawn on 1,1,1 so we don't have runtimes when items are deleted
- D.setDir(SOUTH)
- for(var/job in subtypesof(/datum/job))
- var/datum/job/JB = new job
- switch(JB.title)
- if("AI")
- final.Insert(icon('icons/mob/ai.dmi', "ai", SOUTH, 1), "AI")
- if("Cyborg")
- final.Insert(icon('icons/mob/robots.dmi', "robot", SOUTH, 1), "Cyborg")
- else
- for(var/obj/item/I in D)
- qdel(I)
- randomize_human(D)
- JB.equip(D, TRUE, FALSE)
- COMPILE_OVERLAYS(D)
- var/icon/I = icon(getFlatIcon(D), frame = 1)
- final.Insert(I, JB.title)
- qdel(D)
- //Also add the x
- for(var/x_number in 1 to 4)
- final.Insert(icon('icons/mob/screen_gen.dmi', "x[x_number == 1 ? "" : x_number]"), "x[x_number == 1 ? "" : x_number]")
- fcopy(final, "icons/mob/landmarks.dmi")
-
-/client/proc/debug_z_levels()
- set name = "Debug Z-Levels"
- set category = "Mapping"
-
- var/list/z_list = SSmapping.z_list
- var/list/messages = list()
- messages += "World: [world.maxx] x [world.maxy] x [world.maxz]
"
-
- var/list/linked_levels = list()
- var/min_x = INFINITY
- var/min_y = INFINITY
- var/max_x = -INFINITY
- var/max_y = -INFINITY
-
- for(var/z in 1 to max(world.maxz, z_list.len))
- if (z > z_list.len)
- messages += "[z]: Unmanaged (out of bounds)
"
- continue
- var/datum/space_level/S = z_list[z]
- if (!S)
- messages += "[z]: Unmanaged (null)
"
- continue
- var/linkage
- switch (S.linkage)
- if (UNAFFECTED)
- linkage = "no linkage"
- if (SELFLOOPING)
- linkage = "self-looping"
- if (CROSSLINKED)
- linkage = "linked at ([S.xi], [S.yi])"
- linked_levels += S
- min_x = min(min_x, S.xi)
- min_y = min(min_y, S.yi)
- max_x = max(max_x, S.xi)
- max_y = max(max_y, S.yi)
- else
- linkage = "unknown linkage '[S.linkage]'"
-
- messages += "[z]: [S.name], [linkage], traits: [json_encode(S.traits)]
"
- if (S.z_value != z)
- messages += "-- z_value is [S.z_value], should be [z]
"
- if (S.name == initial(S.name))
- messages += "-- name not set
"
- if (z > world.maxz)
- messages += "-- exceeds max z"
-
- var/grid[max_x - min_x + 1][max_y - min_y + 1]
- for(var/datum/space_level/S in linked_levels)
- grid[S.xi - min_x + 1][S.yi - min_y + 1] = S.z_value
-
- messages += ""
- for(var/y in max_y to min_y step -1)
- var/list/part = list()
- for(var/x in min_x to max_x)
- part += "[grid[x - min_x + 1][y - min_y + 1]]"
- messages += "| [part.Join(" | ")] |
"
- messages += "
"
-
- to_chat(src, messages.Join(""))
+//- Are all the floors with or without air, as they should be? (regular or airless)
+//- Does the area have an APC?
+//- Does the area have an Air Alarm?
+//- Does the area have a Request Console?
+//- Does the area have lights?
+//- Does the area have a light switch?
+//- Does the area have enough intercoms?
+//- Does the area have enough security cameras? (Use the 'Camera Range Display' verb under Debug)
+//- Is the area connected to the scrubbers air loop?
+//- Is the area connected to the vent air loop? (vent pumps)
+//- Is everything wired properly?
+//- Does the area have a fire alarm and firedoors?
+//- Do all pod doors work properly?
+//- Are accesses set properly on doors, pod buttons, etc.
+//- Are all items placed properly? (not below vents, scrubbers, tables)
+//- Does the disposal system work properly from all the disposal units in this room and all the units, the pipes of which pass through this room?
+//- Check for any misplaced or stacked piece of pipe (air and disposal)
+//- Check for any misplaced or stacked piece of wire
+//- Identify how hard it is to break into the area and where the weak points are
+//- Check if the area has too much empty space. If so, make it smaller and replace the rest with maintenance tunnels.
+
+GLOBAL_PROTECT(admin_verbs_debug_mapping)
+GLOBAL_LIST_INIT(admin_verbs_debug_mapping, list(
+ /client/proc/camera_view, //-errorage
+ /client/proc/sec_camera_report, //-errorage
+ /client/proc/intercom_view, //-errorage
+ /client/proc/air_status, //Air things
+ /client/proc/Cell, //More air things
+ /client/proc/atmosscan, //check plumbing
+ /client/proc/powerdebug, //check power
+ /client/proc/count_objects_on_z_level,
+ /client/proc/count_objects_all,
+ /client/proc/cmd_assume_direct_control, //-errorage
+ /client/proc/startSinglo,
+ /client/proc/set_server_fps, //allows you to set the ticklag.
+ /client/proc/cmd_admin_grantfullaccess,
+ /client/proc/cmd_admin_areatest_all,
+ /client/proc/cmd_admin_areatest_station,
+ #ifdef TESTING
+ /client/proc/see_dirty_varedits,
+ #endif
+ /client/proc/cmd_admin_test_atmos_controllers,
+ /client/proc/cmd_admin_rejuvenate,
+ /datum/admins/proc/show_traitor_panel,
+ /client/proc/disable_communication,
+ /client/proc/cmd_show_at_list,
+ /client/proc/cmd_show_at_markers,
+ /client/proc/manipulate_organs,
+ /client/proc/start_line_profiling,
+ /client/proc/stop_line_profiling,
+ /client/proc/show_line_profiling,
+ /client/proc/create_mapping_job_icons,
+ /client/proc/debug_z_levels,
+ /client/proc/place_ruin
+))
+
+/obj/effect/debugging/mapfix_marker
+ name = "map fix marker"
+ icon = 'icons/mob/screen_gen.dmi'
+ icon_state = "mapfixmarker"
+ desc = "I am a mappers mistake."
+
+/obj/effect/debugging/marker
+ icon = 'icons/turf/areas.dmi'
+ icon_state = "yellow"
+
+/obj/effect/debugging/marker/Move()
+ return 0
+
+/client/proc/camera_view()
+ set category = "Mapping"
+ set name = "Camera Range Display"
+
+ var/on = FALSE
+ for(var/turf/T in world)
+ if(T.maptext)
+ on = TRUE
+ T.maptext = null
+
+ if(!on)
+ var/list/seen = list()
+ for(var/obj/machinery/camera/C in GLOB.cameranet.cameras)
+ for(var/turf/T in C.can_see())
+ seen[T]++
+ for(var/turf/T in seen)
+ T.maptext = "[seen[T]]"
+ SSblackbox.record_feedback("tally", "admin_verb", 1, "Show Camera Range") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
+ SSblackbox.record_feedback("tally", "admin_verb", 1, "Show Camera Range")
+
+#ifdef TESTING
+GLOBAL_LIST_EMPTY(dirty_vars)
+
+
+/client/proc/see_dirty_varedits()
+ set category = "Mapping"
+ set name = "Dirty Varedits"
+
+ var/list/dat = list()
+ dat += "Abandon all hope ye who enter here
"
+ for(var/thing in GLOB.dirty_vars)
+ dat += "[thing]
"
+ CHECK_TICK
+ var/datum/browser/popup = new(usr, "dirty_vars", "Dirty Varedits", 900, 750)
+ popup.set_content(dat.Join())
+ popup.open()
+#endif
+
+/client/proc/sec_camera_report()
+ set category = "Mapping"
+ set name = "Camera Report"
+
+ if(!Master)
+ alert(usr,"Master_controller not found.","Sec Camera Report")
+ return 0
+
+ var/list/obj/machinery/camera/CL = list()
+
+ for(var/obj/machinery/camera/C in GLOB.cameranet.cameras)
+ CL += C
+
+ var/output = {"Camera Abnormalities Report
+The following abnormalities have been detected. The ones in red need immediate attention: Some of those in black may be intentional.
"}
+
+ for(var/obj/machinery/camera/C1 in CL)
+ for(var/obj/machinery/camera/C2 in CL)
+ if(C1 != C2)
+ if(C1.c_tag == C2.c_tag)
+ output += "- c_tag match for cameras at [ADMIN_VERBOSEJMP(C1)] and [ADMIN_VERBOSEJMP(C2)] - c_tag is [C1.c_tag]
"
+ if(C1.loc == C2.loc && C1.dir == C2.dir && C1.pixel_x == C2.pixel_x && C1.pixel_y == C2.pixel_y)
+ output += "- FULLY overlapping cameras at [ADMIN_VERBOSEJMP(C1)] Networks: [json_encode(C1.network)] and [json_encode(C2.network)]
"
+ if(C1.loc == C2.loc)
+ output += "- Overlapping cameras at [ADMIN_VERBOSEJMP(C1)] Networks: [json_encode(C1.network)] and [json_encode(C2.network)]
"
+ var/turf/T = get_step(C1,turn(C1.dir,180))
+ if(!T || !isturf(T) || !T.density )
+ if(!(locate(/obj/structure/grille) in T))
+ var/window_check = 0
+ for(var/obj/structure/window/W in T)
+ if (W.dir == turn(C1.dir,180) || W.dir in list(5,6,9,10) )
+ window_check = 1
+ break
+ if(!window_check)
+ output += "- Camera not connected to wall at [ADMIN_VERBOSEJMP(C1)] Network: [json_encode(C1.network)]
"
+
+ output += "
"
+ usr << browse(output,"window=airreport;size=1000x500")
+ SSblackbox.record_feedback("tally", "admin_verb", 1, "Show Camera Report") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
+
+/client/proc/intercom_view()
+ set category = "Mapping"
+ set name = "Intercom Range Display"
+
+ var/static/intercom_range_display_status = FALSE
+ intercom_range_display_status = !intercom_range_display_status //blame cyberboss if this breaks something
+
+ for(var/obj/effect/debugging/marker/M in world)
+ qdel(M)
+
+ if(intercom_range_display_status)
+ for(var/obj/item/radio/intercom/I in world)
+ for(var/turf/T in orange(7,I))
+ var/obj/effect/debugging/marker/F = new/obj/effect/debugging/marker(T)
+ if (!(F in view(7,I.loc)))
+ qdel(F)
+ SSblackbox.record_feedback("tally", "admin_verb", 1, "Show Intercom Range") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
+
+/client/proc/cmd_show_at_list()
+ set category = "Mapping"
+ set name = "Show roundstart AT list"
+ set desc = "Displays a list of active turfs coordinates at roundstart"
+
+ var/dat = {"Coordinate list of Active Turfs at Roundstart
+
Real-time Active Turfs list you can see in Air Subsystem at active_turfs var
"}
+
+ for(var/t in GLOB.active_turfs_startlist)
+ var/turf/T = t
+ dat += "[ADMIN_VERBOSEJMP(T)]\n"
+ dat += "
"
+
+ usr << browse(dat, "window=at_list")
+
+ SSblackbox.record_feedback("tally", "admin_verb", 1, "Show Roundstart Active Turfs") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
+
+/client/proc/cmd_show_at_markers()
+ set category = "Mapping"
+ set name = "Show roundstart AT markers"
+ set desc = "Places a marker on all active-at-roundstart turfs"
+
+ var/count = 0
+ for(var/obj/effect/abstract/marker/at/AT in GLOB.all_abstract_markers)
+ qdel(AT)
+ count++
+
+ if(count)
+ to_chat(usr, "[count] AT markers removed.")
+ else
+ for(var/t in GLOB.active_turfs_startlist)
+ new /obj/effect/abstract/marker/at(t)
+ count++
+ to_chat(usr, "[count] AT markers placed.")
+
+ SSblackbox.record_feedback("tally", "admin_verb", 1, "Show Roundstart Active Turf Markers")
+
+/client/proc/enable_debug_verbs()
+ set category = "Debug"
+ set name = "Debug verbs - Enable"
+ if(!check_rights(R_DEBUG))
+ return
+ verbs -= /client/proc/enable_debug_verbs
+ verbs.Add(/client/proc/disable_debug_verbs, GLOB.admin_verbs_debug_mapping)
+ SSblackbox.record_feedback("tally", "admin_verb", 1, "Enable Debug Verbs") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
+
+/client/proc/disable_debug_verbs()
+ set category = "Debug"
+ set name = "Debug verbs - Disable"
+ verbs.Remove(/client/proc/disable_debug_verbs, GLOB.admin_verbs_debug_mapping)
+ verbs += /client/proc/enable_debug_verbs
+ SSblackbox.record_feedback("tally", "admin_verb", 1, "Disable Debug Verbs") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
+
+/client/proc/count_objects_on_z_level()
+ set category = "Mapping"
+ set name = "Count Objects On Level"
+ var/level = input("Which z-level?","Level?") as text
+ if(!level)
+ return
+ var/num_level = text2num(level)
+ if(!num_level)
+ return
+ if(!isnum(num_level))
+ return
+
+ var/type_text = input("Which type path?","Path?") as text
+ if(!type_text)
+ return
+ var/type_path = text2path(type_text)
+ if(!type_path)
+ return
+
+ var/count = 0
+
+ var/list/atom/atom_list = list()
+
+ for(var/atom/A in world)
+ if(istype(A,type_path))
+ var/atom/B = A
+ while(!(isturf(B.loc)))
+ if(B && B.loc)
+ B = B.loc
+ else
+ break
+ if(B)
+ if(B.z == num_level)
+ count++
+ atom_list += A
+
+ to_chat(world, "There are [count] objects of type [type_path] on z-level [num_level]")
+ SSblackbox.record_feedback("tally", "admin_verb", 1, "Count Objects Zlevel") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
+
+/client/proc/count_objects_all()
+ set category = "Mapping"
+ set name = "Count Objects All"
+
+ var/type_text = input("Which type path?","") as text
+ if(!type_text)
+ return
+ var/type_path = text2path(type_text)
+ if(!type_path)
+ return
+
+ var/count = 0
+
+ for(var/atom/A in world)
+ if(istype(A,type_path))
+ count++
+
+ to_chat(world, "There are [count] objects of type [type_path] in the game world")
+ SSblackbox.record_feedback("tally", "admin_verb", 1, "Count Objects All") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
+
+
+//This proc is intended to detect lag problems relating to communication procs
+GLOBAL_VAR_INIT(say_disabled, FALSE)
+/client/proc/disable_communication()
+ set category = "Mapping"
+ set name = "Disable all communication verbs"
+
+ GLOB.say_disabled = !GLOB.say_disabled
+ if(GLOB.say_disabled)
+ message_admins("[key] used 'Disable all communication verbs', killing all communication methods.")
+ else
+ message_admins("[key] used 'Disable all communication verbs', restoring all communication methods.")
+
+//This generates the icon states for job starting location landmarks.
+/client/proc/create_mapping_job_icons()
+ set name = "Generate job landmarks icons"
+ set category = "Mapping"
+ var/icon/final = icon()
+ var/mob/living/carbon/human/dummy/D = new(locate(1,1,1)) //spawn on 1,1,1 so we don't have runtimes when items are deleted
+ D.setDir(SOUTH)
+ for(var/job in subtypesof(/datum/job))
+ var/datum/job/JB = new job
+ switch(JB.title)
+ if("AI")
+ final.Insert(icon('icons/mob/ai.dmi', "ai", SOUTH, 1), "AI")
+ if("Cyborg")
+ final.Insert(icon('icons/mob/robots.dmi', "robot", SOUTH, 1), "Cyborg")
+ else
+ for(var/obj/item/I in D)
+ qdel(I)
+ randomize_human(D)
+ JB.equip(D, TRUE, FALSE)
+ COMPILE_OVERLAYS(D)
+ var/icon/I = icon(getFlatIcon(D), frame = 1)
+ final.Insert(I, JB.title)
+ qdel(D)
+ //Also add the x
+ for(var/x_number in 1 to 4)
+ final.Insert(icon('icons/mob/screen_gen.dmi', "x[x_number == 1 ? "" : x_number]"), "x[x_number == 1 ? "" : x_number]")
+ fcopy(final, "icons/mob/landmarks.dmi")
+
+/client/proc/debug_z_levels()
+ set name = "Debug Z-Levels"
+ set category = "Mapping"
+
+ var/list/z_list = SSmapping.z_list
+ var/list/messages = list()
+ messages += "World: [world.maxx] x [world.maxy] x [world.maxz]
"
+
+ var/list/linked_levels = list()
+ var/min_x = INFINITY
+ var/min_y = INFINITY
+ var/max_x = -INFINITY
+ var/max_y = -INFINITY
+
+ for(var/z in 1 to max(world.maxz, z_list.len))
+ if (z > z_list.len)
+ messages += "[z]: Unmanaged (out of bounds)
"
+ continue
+ var/datum/space_level/S = z_list[z]
+ if (!S)
+ messages += "[z]: Unmanaged (null)
"
+ continue
+ var/linkage
+ switch (S.linkage)
+ if (UNAFFECTED)
+ linkage = "no linkage"
+ if (SELFLOOPING)
+ linkage = "self-looping"
+ if (CROSSLINKED)
+ linkage = "linked at ([S.xi], [S.yi])"
+ linked_levels += S
+ min_x = min(min_x, S.xi)
+ min_y = min(min_y, S.yi)
+ max_x = max(max_x, S.xi)
+ max_y = max(max_y, S.yi)
+ else
+ linkage = "unknown linkage '[S.linkage]'"
+
+ messages += "[z]: [S.name], [linkage], traits: [json_encode(S.traits)]
"
+ if (S.z_value != z)
+ messages += "-- z_value is [S.z_value], should be [z]
"
+ if (S.name == initial(S.name))
+ messages += "-- name not set
"
+ if (z > world.maxz)
+ messages += "-- exceeds max z"
+
+ var/grid[max_x - min_x + 1][max_y - min_y + 1]
+ for(var/datum/space_level/S in linked_levels)
+ grid[S.xi - min_x + 1][S.yi - min_y + 1] = S.z_value
+
+ messages += ""
+ for(var/y in max_y to min_y step -1)
+ var/list/part = list()
+ for(var/x in min_x to max_x)
+ part += "[grid[x - min_x + 1][y - min_y + 1]]"
+ messages += "| [part.Join(" | ")] |
"
+ messages += "
"
+
+ to_chat(src, messages.Join(""))
diff --git a/code/modules/atmospherics/machinery/datum_pipeline.dm b/code/modules/atmospherics/machinery/datum_pipeline.dm
index 4998db56..899b6212 100644
--- a/code/modules/atmospherics/machinery/datum_pipeline.dm
+++ b/code/modules/atmospherics/machinery/datum_pipeline.dm
@@ -57,10 +57,10 @@
if(item.parent)
var/static/pipenetwarnings = 10
if(pipenetwarnings > 0)
- warning("build_pipeline(): [item.type] added to a pipenet while still having one. (pipes leading to the same spot stacking in one turf) Nearby: ([item.x], [item.y], [item.z])")
+ log_mapping("build_pipeline(): [item.type] added to a pipenet while still having one. (pipes leading to the same spot stacking in one turf) Nearby: ([item.x], [item.y], [item.z]).")
pipenetwarnings -= 1
if(pipenetwarnings == 0)
- warning("build_pipeline(): further messages about pipenets will be suppressed")
+ log_mapping("build_pipeline(): further messages about pipenets will be suppressed")
members += item
possible_expansions += item
diff --git a/code/modules/atmospherics/machinery/other/meter.dm b/code/modules/atmospherics/machinery/other/meter.dm
index 5853bc72..9870a895 100644
--- a/code/modules/atmospherics/machinery/other/meter.dm
+++ b/code/modules/atmospherics/machinery/other/meter.dm
@@ -1,147 +1,147 @@
-/obj/machinery/meter
- name = "gas flow meter"
- desc = "It measures something."
- icon = 'icons/obj/atmospherics/pipes/meter.dmi'
- icon_state = "meterX"
- layer = GAS_PUMP_LAYER
- power_channel = ENVIRON
- use_power = IDLE_POWER_USE
- idle_power_usage = 2
- active_power_usage = 4
- max_integrity = 150
- armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 100, "bomb" = 0, "bio" = 100, "rad" = 100, "fire" = 40, "acid" = 0)
- var/frequency = 0
- var/atom/target
- var/id_tag
- var/target_layer = PIPING_LAYER_DEFAULT
-
-/obj/machinery/meter/atmos
- frequency = FREQ_ATMOS_STORAGE
-
-/obj/machinery/meter/atmos/atmos_waste_loop
- name = "waste loop gas flow meter"
- id_tag = ATMOS_GAS_MONITOR_LOOP_ATMOS_WASTE
-
-/obj/machinery/meter/atmos/distro_loop
- name = "distribution loop gas flow meter"
- id_tag = ATMOS_GAS_MONITOR_LOOP_DISTRIBUTION
-
-/obj/machinery/meter/Destroy()
- SSair.atmos_machinery -= src
- target = null
- return ..()
-
-/obj/machinery/meter/Initialize(mapload, new_piping_layer)
- if(!isnull(new_piping_layer))
- target_layer = new_piping_layer
- SSair.atmos_machinery += src
- if(!target)
- reattach_to_layer()
- return ..()
-
-/obj/machinery/meter/proc/reattach_to_layer()
- var/obj/machinery/atmospherics/candidate
- for(var/obj/machinery/atmospherics/pipe/pipe in loc)
- if(pipe.piping_layer == target_layer)
- candidate = pipe
- if(pipe.level == 2)
- break
- if(candidate)
- target = candidate
- setAttachLayer(candidate.piping_layer)
-
-/obj/machinery/meter/proc/setAttachLayer(new_layer)
- target_layer = new_layer
- PIPING_LAYER_DOUBLE_SHIFT(src, target_layer)
-
-/obj/machinery/meter/process_atmos()
- if(!target)
- icon_state = "meterX"
- return 0
-
- if(stat & (BROKEN|NOPOWER))
- icon_state = "meter0"
- return 0
-
- use_power(5)
-
- var/datum/gas_mixture/environment = target.return_air()
- if(!environment)
- icon_state = "meterX"
- return 0
-
- var/env_pressure = environment.return_pressure()
- if(env_pressure <= 0.15*ONE_ATMOSPHERE)
- icon_state = "meter0"
- else if(env_pressure <= 1.8*ONE_ATMOSPHERE)
- var/val = round(env_pressure/(ONE_ATMOSPHERE*0.3) + 0.5)
- icon_state = "meter1_[val]"
- else if(env_pressure <= 30*ONE_ATMOSPHERE)
- var/val = round(env_pressure/(ONE_ATMOSPHERE*5)-0.35) + 1
- icon_state = "meter2_[val]"
- else if(env_pressure <= 59*ONE_ATMOSPHERE)
- var/val = round(env_pressure/(ONE_ATMOSPHERE*5) - 6) + 1
- icon_state = "meter3_[val]"
- else
- icon_state = "meter4"
-
- if(frequency)
- var/datum/radio_frequency/radio_connection = SSradio.return_frequency(frequency)
-
- if(!radio_connection)
- return
-
- var/datum/signal/signal = new(list(
- "id_tag" = id_tag,
- "device" = "AM",
- "pressure" = round(env_pressure),
- "sigtype" = "status"
- ))
- radio_connection.post_signal(src, signal)
-
-/obj/machinery/meter/proc/status()
- if (target)
- var/datum/gas_mixture/environment = target.return_air()
- if(environment)
- . = "The pressure gauge reads [round(environment.return_pressure(), 0.01)] kPa; [round(environment.temperature,0.01)] K ([round(environment.temperature-T0C,0.01)]°C)."
- else
- . = "The sensor error light is blinking."
- else
- . = "The connect error light is blinking."
-
-/obj/machinery/meter/examine(mob/user)
- . = ..()
- . += status()
-
-/obj/machinery/meter/wrench_act(mob/user, obj/item/I)
- to_chat(user, "You begin to unfasten \the [src]...")
- if (I.use_tool(src, user, 40, volume=50))
- user.visible_message(
- "[user] unfastens \the [src].",
- "You unfasten \the [src].",
- "You hear ratchet.")
- deconstruct()
- return TRUE
-
-/obj/machinery/meter/deconstruct(disassembled = TRUE)
- if(!(flags_1 & NODECONSTRUCT_1))
- new /obj/item/pipe_meter(loc)
- qdel(src)
-
-/obj/machinery/meter/interact(mob/user)
- if(stat & (NOPOWER|BROKEN))
- return
- else
- to_chat(user, status())
-
-/obj/machinery/meter/singularity_pull(S, current_size)
- ..()
- if(current_size >= STAGE_FIVE)
- deconstruct()
-
-// TURF METER - REPORTS A TILE'S AIR CONTENTS
-// why are you yelling?
-/obj/machinery/meter/turf
-
-/obj/machinery/meter/turf/reattach_to_layer()
- target = loc
+/obj/machinery/meter
+ name = "gas flow meter"
+ desc = "It measures something."
+ icon = 'icons/obj/atmospherics/pipes/meter.dmi'
+ icon_state = "meterX"
+ layer = GAS_PUMP_LAYER
+ power_channel = ENVIRON
+ use_power = IDLE_POWER_USE
+ idle_power_usage = 2
+ active_power_usage = 4
+ max_integrity = 150
+ armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 100, "bomb" = 0, "bio" = 100, "rad" = 100, "fire" = 40, "acid" = 0)
+ var/frequency = 0
+ var/atom/target
+ var/id_tag
+ var/target_layer = PIPING_LAYER_DEFAULT
+
+/obj/machinery/meter/atmos
+ frequency = FREQ_ATMOS_STORAGE
+
+/obj/machinery/meter/atmos/atmos_waste_loop
+ name = "waste loop gas flow meter"
+ id_tag = ATMOS_GAS_MONITOR_LOOP_ATMOS_WASTE
+
+/obj/machinery/meter/atmos/distro_loop
+ name = "distribution loop gas flow meter"
+ id_tag = ATMOS_GAS_MONITOR_LOOP_DISTRIBUTION
+
+/obj/machinery/meter/Destroy()
+ SSair.atmos_machinery -= src
+ target = null
+ return ..()
+
+/obj/machinery/meter/Initialize(mapload, new_piping_layer)
+ if(!isnull(new_piping_layer))
+ target_layer = new_piping_layer
+ SSair.atmos_machinery += src
+ if(!target)
+ reattach_to_layer()
+ return ..()
+
+/obj/machinery/meter/proc/reattach_to_layer()
+ var/obj/machinery/atmospherics/candidate
+ for(var/obj/machinery/atmospherics/pipe/pipe in loc)
+ if(pipe.piping_layer == target_layer)
+ candidate = pipe
+ if(pipe.level == 2)
+ break
+ if(candidate)
+ target = candidate
+ setAttachLayer(candidate.piping_layer)
+
+/obj/machinery/meter/proc/setAttachLayer(new_layer)
+ target_layer = new_layer
+ PIPING_LAYER_DOUBLE_SHIFT(src, target_layer)
+
+/obj/machinery/meter/process_atmos()
+ if(!(target?.flags_1 & INITIALIZED_1))
+ icon_state = "meterX"
+ return 0
+
+ if(stat & (BROKEN|NOPOWER))
+ icon_state = "meter0"
+ return 0
+
+ use_power(5)
+
+ var/datum/gas_mixture/environment = target.return_air()
+ if(!environment)
+ icon_state = "meterX"
+ return 0
+
+ var/env_pressure = environment.return_pressure()
+ if(env_pressure <= 0.15*ONE_ATMOSPHERE)
+ icon_state = "meter0"
+ else if(env_pressure <= 1.8*ONE_ATMOSPHERE)
+ var/val = round(env_pressure/(ONE_ATMOSPHERE*0.3) + 0.5)
+ icon_state = "meter1_[val]"
+ else if(env_pressure <= 30*ONE_ATMOSPHERE)
+ var/val = round(env_pressure/(ONE_ATMOSPHERE*5)-0.35) + 1
+ icon_state = "meter2_[val]"
+ else if(env_pressure <= 59*ONE_ATMOSPHERE)
+ var/val = round(env_pressure/(ONE_ATMOSPHERE*5) - 6) + 1
+ icon_state = "meter3_[val]"
+ else
+ icon_state = "meter4"
+
+ if(frequency)
+ var/datum/radio_frequency/radio_connection = SSradio.return_frequency(frequency)
+
+ if(!radio_connection)
+ return
+
+ var/datum/signal/signal = new(list(
+ "id_tag" = id_tag,
+ "device" = "AM",
+ "pressure" = round(env_pressure),
+ "sigtype" = "status"
+ ))
+ radio_connection.post_signal(src, signal)
+
+/obj/machinery/meter/proc/status()
+ if (target)
+ var/datum/gas_mixture/environment = target.return_air()
+ if(environment)
+ . = "The pressure gauge reads [round(environment.return_pressure(), 0.01)] kPa; [round(environment.temperature,0.01)] K ([round(environment.temperature-T0C,0.01)]°C)."
+ else
+ . = "The sensor error light is blinking."
+ else
+ . = "The connect error light is blinking."
+
+/obj/machinery/meter/examine(mob/user)
+ . = ..()
+ . += status()
+
+/obj/machinery/meter/wrench_act(mob/user, obj/item/I)
+ to_chat(user, "You begin to unfasten \the [src]...")
+ if (I.use_tool(src, user, 40, volume=50))
+ user.visible_message(
+ "[user] unfastens \the [src].",
+ "You unfasten \the [src].",
+ "You hear ratchet.")
+ deconstruct()
+ return TRUE
+
+/obj/machinery/meter/deconstruct(disassembled = TRUE)
+ if(!(flags_1 & NODECONSTRUCT_1))
+ new /obj/item/pipe_meter(loc)
+ qdel(src)
+
+/obj/machinery/meter/interact(mob/user)
+ if(stat & (NOPOWER|BROKEN))
+ return
+ else
+ to_chat(user, status())
+
+/obj/machinery/meter/singularity_pull(S, current_size)
+ ..()
+ if(current_size >= STAGE_FIVE)
+ deconstruct()
+
+// TURF METER - REPORTS A TILE'S AIR CONTENTS
+// why are you yelling?
+/obj/machinery/meter/turf
+
+/obj/machinery/meter/turf/reattach_to_layer()
+ target = loc
diff --git a/code/modules/holodeck/computer.dm b/code/modules/holodeck/computer.dm
index 3009e5ee..f4df6dc6 100644
--- a/code/modules/holodeck/computer.dm
+++ b/code/modules/holodeck/computer.dm
@@ -59,9 +59,7 @@
return
var/area/AS = get_area(src)
if(istype(AS, /area/holodeck))
- log_world("### MAPPING ERROR")
- log_world("Holodeck computer cannot be in a holodeck.")
- log_world("This would cause circular power dependency.")
+ log_mapping("Holodeck computer cannot be in a holodeck, This would cause circular power dependency.")
qdel(src)
return
else
diff --git a/code/modules/mapping/map_template.dm b/code/modules/mapping/map_template.dm
index 1f55f188..3e361179 100644
--- a/code/modules/mapping/map_template.dm
+++ b/code/modules/mapping/map_template.dm
@@ -70,7 +70,7 @@
//initialize things that are normally initialized after map load
parsed.initTemplateBounds()
smooth_zlevel(world.maxz)
- log_game("Z-level [name] loaded at at [x],[y],[world.maxz]")
+ log_game("Z-level [name] loaded at [x],[y],[world.maxz]")
return level
@@ -84,6 +84,13 @@
if(T.y+height > world.maxy)
return
+ var/list/border = block(locate(max(T.x-1, 1), max(T.y-1, 1), T.z),
+ locate(min(T.x+width+1, world.maxx), min(T.y+height+1, world.maxy), T.z))
+ for(var/L in border)
+ var/turf/turf_to_disable = L
+ SSair.remove_from_active(turf_to_disable) //stop processing turfs along the border to prevent runtimes, we return it in initTemplateBounds()
+ turf_to_disable.atmos_adjacent_turfs?.Cut()
+
// Accept cached maps, but don't save them automatically - we don't want
// ruins clogging up memory for the whole round.
var/datum/parsed_map/parsed = cached_map || new(file(mappath))
@@ -100,7 +107,7 @@
//initialize things that are normally initialized after map load
parsed.initTemplateBounds()
- log_game("[name] loaded at at [T.x],[T.y],[T.z]")
+ log_game("[name] loaded at [T.x],[T.y],[T.z]")
return bounds
/datum/map_template/proc/get_affected_turfs(turf/T, centered = FALSE)
diff --git a/code/modules/mapping/mapping_helpers.dm b/code/modules/mapping/mapping_helpers.dm
index 7a875ccf..5f0df36d 100644
--- a/code/modules/mapping/mapping_helpers.dm
+++ b/code/modules/mapping/mapping_helpers.dm
@@ -18,7 +18,7 @@
/obj/effect/baseturf_helper/LateInitialize()
if(!baseturf_to_replace)
- baseturf_to_replace = typecacheof(/turf/open/space)
+ baseturf_to_replace = typecacheof(list(/turf/open/space,/turf/baseturf_bottom))
else if(!length(baseturf_to_replace))
baseturf_to_replace = list(baseturf_to_replace = TRUE)
else if(baseturf_to_replace[baseturf_to_replace[1]] != TRUE) // It's not associative
@@ -45,7 +45,6 @@
thing.PlaceOnBottom(null, baseturf)
else if(baseturf_to_replace[thing.baseturfs])
thing.assemble_baseturfs(baseturf)
- return
else
thing.PlaceOnBottom(null, baseturf)
@@ -107,16 +106,16 @@
/obj/effect/mapping_helpers/airlock/cyclelink_helper/Initialize(mapload)
. = ..()
if(!mapload)
- log_world("### MAP WARNING, [src] spawned outside of mapload!")
+ log_mapping("[src] spawned outside of mapload!")
return
var/obj/machinery/door/airlock/airlock = locate(/obj/machinery/door/airlock) in loc
if(airlock)
if(airlock.cyclelinkeddir)
- log_world("### MAP WARNING, [src] at [AREACOORD(src)] tried to set [airlock] cyclelinkeddir, but it's already set!")
+ log_mapping("[src] at [AREACOORD(src)] tried to set [airlock] cyclelinkeddir, but it's already set!")
else
airlock.cyclelinkeddir = dir
else
- log_world("### MAP WARNING, [src] failed to find an airlock at [AREACOORD(src)]")
+ log_mapping("[src] failed to find an airlock at [AREACOORD(src)]")
/obj/effect/mapping_helpers/airlock/locked
@@ -126,16 +125,16 @@
/obj/effect/mapping_helpers/airlock/locked/Initialize(mapload)
. = ..()
if(!mapload)
- log_world("### MAP WARNING, [src] spawned outside of mapload!")
+ log_mapping("[src] spawned outside of mapload!")
return
var/obj/machinery/door/airlock/airlock = locate(/obj/machinery/door/airlock) in loc
if(airlock)
if(airlock.locked)
- log_world("### MAP WARNING, [src] at [AREACOORD(src)] tried to bolt [airlock] but it's already locked!")
+ log_mapping("[src] at [AREACOORD(src)] tried to bolt [airlock] but it's already locked!")
else
airlock.locked = TRUE
else
- log_world("### MAP WARNING, [src] failed to find an airlock at [AREACOORD(src)]")
+ log_mapping("[src] failed to find an airlock at [AREACOORD(src)]")
/obj/effect/mapping_helpers/airlock/unres
name = "airlock unresctricted side helper"
@@ -144,13 +143,13 @@
/obj/effect/mapping_helpers/airlock/unres/Initialize(mapload)
. = ..()
if(!mapload)
- log_world("### MAP WARNING, [src] spawned outside of mapload!")
+ log_mapping("[src] spawned outside of mapload!")
return
var/obj/machinery/door/airlock/airlock = locate(/obj/machinery/door/airlock) in loc
if(airlock)
airlock.unres_sides ^= dir
else
- log_world("### MAP WARNING, [src] failed to find an airlock at [AREACOORD(src)]")
+ log_mapping("[src] failed to find an airlock at [AREACOORD(src)]")
//needs to do its thing before spawn_rivers() is called
@@ -164,17 +163,6 @@ INITIALIZE_IMMEDIATE(/obj/effect/mapping_helpers/no_lava)
var/turf/T = get_turf(src)
T.flags_1 |= NO_LAVA_GEN_1
-/// Adds the map it is on to the z_is_planet list
-/obj/effect/mapping_helpers/planet_z
- name = "planet z helper"
- layer = POINT_LAYER
-
-/obj/effect/mapping_helpers/planet_z/Initialize()
- . = ..()
- var/datum/space_level/S = SSmapping.get_level(z)
- S.traits[ZTRAIT_PLANET] = TRUE
-
-
//This helper applies components to things on the map directly.
/obj/effect/mapping_helpers/component_injector
name = "Component Injector"
diff --git a/code/modules/mapping/preloader.dm b/code/modules/mapping/preloader.dm
index e6fa2421..4b61663f 100644
--- a/code/modules/mapping/preloader.dm
+++ b/code/modules/mapping/preloader.dm
@@ -8,18 +8,26 @@ GLOBAL_DATUM_INIT(_preloader, /datum/map_preloader, new)
var/list/attributes
var/target_path
-/datum/map_preloader/proc/setup(list/the_attributes, path)
+/world/proc/preloader_setup(list/the_attributes, path)
if(the_attributes.len)
GLOB.use_preloader = TRUE
- attributes = the_attributes
- target_path = path
+ var/datum/map_preloader/preloader_local = GLOB._preloader
+ preloader_local.attributes = the_attributes
+ preloader_local.target_path = path
-/datum/map_preloader/proc/load(atom/what)
+/world/proc/preloader_load(atom/what)
GLOB.use_preloader = FALSE
- for(var/attribute in attributes)
- var/value = attributes[attribute]
+ var/datum/map_preloader/preloader_local = GLOB._preloader
+ for(var/attribute in preloader_local.attributes)
+ var/value = preloader_local.attributes[attribute]
if(islist(value))
value = deepCopyList(value)
+ #ifdef TESTING
+ if(what.vars[attribute] == value)
+ var/message = "[what.type] at [AREACOORD(what)] - VAR: [attribute] = [isnull(value) ? "null" : (isnum(value) ? value : "\"[value]\"")]"
+ log_mapping("DIRTY VAR: [message]")
+ GLOB.dirty_vars += message
+ #endif
what.vars[attribute] = value
/area/template_noop
diff --git a/code/modules/mapping/reader.dm b/code/modules/mapping/reader.dm
index 22be4aa2..9b27691d 100644
--- a/code/modules/mapping/reader.dm
+++ b/code/modules/mapping/reader.dm
@@ -306,8 +306,8 @@
//first instance the /area and remove it from the members list
index = members.len
if(members[index] != /area/template_noop)
- GLOB._preloader.setup(members_attributes[index])//preloader for assigning set variables on atom creation
var/atype = members[index]
+ world.preloader_setup(members_attributes[index], atype)//preloader for assigning set variables on atom creation
var/atom/instance = areaCache[atype]
if (!instance)
instance = GLOB.areas_by_type[atype]
@@ -318,7 +318,7 @@
instance.contents.Add(crds)
if(GLOB.use_preloader && instance)
- GLOB._preloader.load(instance)
+ world.preloader_load(instance)
//then instance the /turf and, if multiple tiles are presents, simulates the DMM underlays piling effect
@@ -354,7 +354,7 @@
//Instance an atom at (x,y,z) and gives it the variables in attributes
/datum/parsed_map/proc/instance_atom(path,list/attributes, turf/crds, no_changeturf, placeOnTop)
- GLOB._preloader.setup(attributes, path)
+ world.preloader_setup(attributes, path)
if(crds)
if(ispath(path, /turf))
@@ -368,7 +368,7 @@
. = create_atom(path, crds)//first preloader pass
if(GLOB.use_preloader && .)//second preloader pass, for those atoms that don't ..() in New()
- GLOB._preloader.load(.)
+ world.preloader_load(.)
//custom CHECK_TICK here because we don't want things created while we're sleeping to not initialize
if(TICK_CHECK)
diff --git a/code/modules/recycling/conveyor2.dm b/code/modules/recycling/conveyor2.dm
index 5875e821..d684b2ed 100644
--- a/code/modules/recycling/conveyor2.dm
+++ b/code/modules/recycling/conveyor2.dm
@@ -31,7 +31,7 @@ GLOBAL_LIST_EMPTY(conveyors_by_id)
/obj/machinery/conveyor/inverted/Initialize(mapload)
. = ..()
if(mapload && !(dir in GLOB.diagonals))
- log_game("### MAPPING ERROR: [src] at [AREACOORD(src)] spawned without using a diagonal dir. Please replace with a normal version.")
+ log_mapping("[src] at [AREACOORD(src)] spawned without using a diagonal dir. Please replace with a normal version.")
// Auto conveyour is always on unless unpowered