diff --git a/byond-extools.dll b/byond-extools.dll
index 7c45514fe2..ec50515705 100644
Binary files a/byond-extools.dll and b/byond-extools.dll differ
diff --git a/code/__DEFINES/atmospherics.dm b/code/__DEFINES/atmospherics.dm
index c609bdd230..47b0b65967 100644
--- a/code/__DEFINES/atmospherics.dm
+++ b/code/__DEFINES/atmospherics.dm
@@ -281,12 +281,12 @@ GLOBAL_LIST_INIT(atmos_adjacent_savings, list(0,0))
#define CALCULATE_ADJACENT_TURFS(T) SSadjacent_air.queue[T] = 1
#endif
-GLOBAL_VAR(atmos_extools_initialized) // this must be an uninitialized (null) one or init_fastmos will be called twice because reasons
+GLOBAL_VAR(atmos_extools_initialized) // this must be an uninitialized (null) one or init_monstermos will be called twice because reasons
#define ATMOS_EXTOOLS_CHECK if(!GLOB.atmos_extools_initialized){\
GLOB.atmos_extools_initialized=TRUE;\
var/extools = world.GetConfig("env", "EXTOOLS_DLL") || "./byond-extools.dll";\
if(fexists(extools)){\
- var/result = call(extools,"init_fastmos")();\
+ var/result = call(extools,"init_monstermos")();\
if(result != "ok") {CRASH(result);}\
} else {\
CRASH("byond-extools.dll does not exist!");\
diff --git a/code/__DEFINES/subsystems.dm b/code/__DEFINES/subsystems.dm
index 3abef3a61c..4e0d636ae4 100644
--- a/code/__DEFINES/subsystems.dm
+++ b/code/__DEFINES/subsystems.dm
@@ -135,12 +135,13 @@
// SSair run section
#define SSAIR_PIPENETS 1
#define SSAIR_ATMOSMACHINERY 2
-#define SSAIR_REACTQUEUE 3
-#define SSAIR_EXCITEDGROUPS 4
-#define SSAIR_HIGHPRESSURE 5
-#define SSAIR_HOTSPOTS 6
-#define SSAIR_SUPERCONDUCTIVITY 7
-#define SSAIR_REBUILD_PIPENETS 8
+#define SSAIR_EXCITEDGROUPS 3
+#define SSAIR_HIGHPRESSURE 4
+#define SSAIR_HOTSPOTS 5
+#define SSAIR_SUPERCONDUCTIVITY 6
+#define SSAIR_REBUILD_PIPENETS 7
+#define SSAIR_EQUALIZE 8
+#define SSAIR_ACTIVETURFS 9
#define COMPILE_OVERLAYS(A)\
if (TRUE) {\
diff --git a/code/controllers/subsystem/air.dm b/code/controllers/subsystem/air.dm
index d8c7724333..21a919cc45 100644
--- a/code/controllers/subsystem/air.dm
+++ b/code/controllers/subsystem/air.dm
@@ -6,7 +6,7 @@ SUBSYSTEM_DEF(air)
flags = SS_BACKGROUND
runlevels = RUNLEVEL_GAME | RUNLEVEL_POSTGAME
- var/cost_turf_reactions = 0
+ var/cost_turfs = 0
var/cost_groups = 0
var/cost_highpressure = 0
var/cost_hotspots = 0
@@ -14,10 +14,9 @@ SUBSYSTEM_DEF(air)
var/cost_pipenets = 0
var/cost_rebuilds = 0
var/cost_atmos_machinery = 0
+ var/cost_equalize = 0
- var/list/excited_groups = list()
var/list/active_turfs = list()
- var/list/turf_react_queue = list()
var/list/hotspots = list()
var/list/networks = list()
var/list/pipenets_needing_rebuilt = list()
@@ -38,20 +37,21 @@ SUBSYSTEM_DEF(air)
var/map_loading = TRUE
var/list/queued_for_activation
+ var/log_explosive_decompression = TRUE // If things get spammy, admemes can turn this off.
+
/datum/controller/subsystem/air/stat_entry(msg)
msg += "C:{"
- msg += "RQ:[round(cost_turf_reactions,1)]|"
+ msg += "EQ:[round(cost_equalize,1)]|"
+ msg += "AT:[round(cost_turfs,1)]|"
msg += "EG:[round(cost_groups,1)]|"
msg += "HP:[round(cost_highpressure,1)]|"
msg += "HS:[round(cost_hotspots,1)]|"
msg += "SC:[round(cost_superconductivity,1)]|"
msg += "PN:[round(cost_pipenets,1)]|"
- msg += "RB:[round(cost_rebuilds,1)]|"
msg += "AM:[round(cost_atmos_machinery,1)]"
msg += "} "
msg += "AT:[active_turfs.len]|"
- msg += "RQ:[turf_react_queue.len]|"
- msg += "EG:[excited_groups.len]|"
+ msg += "EG:[get_amt_excited_groups()]|"
msg += "HS:[hotspots.len]|"
msg += "PN:[networks.len]|"
msg += "HP:[high_pressure_delta.len]|"
@@ -59,8 +59,8 @@ SUBSYSTEM_DEF(air)
msg += "AT/MS:[round((cost ? active_turfs.len/cost : 0),0.1)]"
..(msg)
-
/datum/controller/subsystem/air/Initialize(timeofday)
+ extools_update_ssair()
map_loading = FALSE
setup_allturfs()
setup_atmos_machinery()
@@ -68,6 +68,7 @@ SUBSYSTEM_DEF(air)
gas_reactions = init_gas_reactions()
return ..()
+/datum/controller/subsystem/air/proc/extools_update_ssair()
/datum/controller/subsystem/air/fire(resumed = 0)
var/timer = TICK_USAGE_REAL
@@ -99,12 +100,21 @@ SUBSYSTEM_DEF(air)
if(state != SS_RUNNING)
return
resumed = 0
- currentpart = SSAIR_REACTQUEUE
+ currentpart = SSAIR_ACTIVETURFS // set this to EQUALIZE for monstermos
- if(currentpart == SSAIR_REACTQUEUE)
+ if(currentpart == SSAIR_EQUALIZE)
timer = TICK_USAGE_REAL
- process_react_queue(resumed)
- cost_turf_reactions = MC_AVERAGE(cost_turf_reactions, TICK_DELTA_TO_MS(TICK_USAGE_REAL - timer))
+ process_turf_equalize(resumed)
+ cost_equalize = MC_AVERAGE(cost_equalize, TICK_DELTA_TO_MS(TICK_USAGE_REAL - timer))
+ if(state != SS_RUNNING)
+ return
+ resumed = 0
+ currentpart = SSAIR_ACTIVETURFS
+
+ if(currentpart == SSAIR_ACTIVETURFS)
+ timer = TICK_USAGE_REAL
+ process_active_turfs(resumed)
+ cost_turfs = MC_AVERAGE(cost_turfs, TICK_DELTA_TO_MS(TICK_USAGE_REAL - timer))
if(state != SS_RUNNING)
return
resumed = 0
@@ -146,6 +156,8 @@ SUBSYSTEM_DEF(air)
resumed = 0
currentpart = SSAIR_REBUILD_PIPENETS
+
+
/datum/controller/subsystem/air/proc/process_pipenets(resumed = 0)
if (!resumed)
src.currentrun = networks.Copy()
@@ -180,19 +192,6 @@ SUBSYSTEM_DEF(air)
return
-/datum/controller/subsystem/air/proc/process_react_queue(resumed = 0)
- if(!resumed)
- src.currentrun = turf_react_queue.Copy()
- var/list/currentrun = src.currentrun
- while(currentrun.len)
- var/turf/open/T = currentrun[currentrun.len]
- currentrun.len--
- if(T)
- T.process_cell_reaction()
- if(MC_TICK_CHECK)
- return
-
-
/datum/controller/subsystem/air/proc/process_super_conductivity(resumed = 0)
if (!resumed)
src.currentrun = active_super_conductivity.Copy()
@@ -227,10 +226,45 @@ SUBSYSTEM_DEF(air)
high_pressure_delta.len--
T.high_pressure_movements()
T.pressure_difference = 0
+ T.pressure_specific_target = null
if(MC_TICK_CHECK)
return
+/datum/controller/subsystem/air/proc/process_turf_equalize(resumed = 0)
+ //cache for sanic speed
+ var/fire_count = times_fired
+ if (!resumed)
+ src.currentrun = active_turfs.Copy()
+ //cache for sanic speed (lists are references anyways)
+ var/list/currentrun = src.currentrun
+ while(currentrun.len)
+ var/turf/open/T = currentrun[currentrun.len]
+ currentrun.len--
+ if (T)
+ T.equalize_pressure_in_zone(fire_count)
+ //equalize_pressure_in_zone(T, fire_count)
+ if (MC_TICK_CHECK)
+ return
+
+/datum/controller/subsystem/air/proc/process_active_turfs(resumed = 0)
+ //cache for sanic speed
+ var/fire_count = times_fired
+ if (!resumed)
+ src.currentrun = active_turfs.Copy()
+ //cache for sanic speed (lists are references anyways)
+ var/list/currentrun = src.currentrun
+ while(currentrun.len)
+ var/turf/open/T = currentrun[currentrun.len]
+ currentrun.len--
+ if (T)
+ T.process_cell(fire_count)
+ if (MC_TICK_CHECK)
+ return
+
/datum/controller/subsystem/air/proc/process_excited_groups(resumed = 0)
+ if(process_excited_groups_extools(resumed, (Master.current_ticklimit - TICK_USAGE) * 0.01 * world.tick_lag))
+ sleep()
+ /*
if (!resumed)
src.currentrun = excited_groups.Copy()
//cache for sanic speed (lists are references anyways)
@@ -246,29 +280,33 @@ SUBSYSTEM_DEF(air)
EG.dismantle()
if (MC_TICK_CHECK)
return
+ */
+
+/datum/controller/subsystem/air/proc/process_excited_groups_extools()
+/datum/controller/subsystem/air/proc/get_amt_excited_groups()
/datum/controller/subsystem/air/proc/remove_from_active(turf/open/T)
active_turfs -= T
- SSair_turfs.currentrun -= T
+ if(currentpart == SSAIR_ACTIVETURFS)
+ currentrun -= T
#ifdef VISUALIZE_ACTIVE_TURFS
T.remove_atom_colour(TEMPORARY_COLOUR_PRIORITY, "#00ff00")
#endif
if(istype(T))
- T.excited = 0
- if(T.excited_group)
- T.excited_group.garbage_collect()
- remove_from_react_queue(T)
+ T.set_excited(FALSE)
+ T.eg_garbage_collect()
/datum/controller/subsystem/air/proc/add_to_active(turf/open/T, blockchanges = 1)
if(istype(T) && T.air)
#ifdef VISUALIZE_ACTIVE_TURFS
T.add_atom_colour("#00ff00", TEMPORARY_COLOUR_PRIORITY)
#endif
- T.excited = TRUE
- active_turfs[T] = SSair_turfs.currentrun[T] = TRUE
- if(blockchanges && T.excited_group)
- T.excited_group.garbage_collect()
- add_to_react_queue(T)
+ T.set_excited(TRUE)
+ active_turfs |= T
+ if(currentpart == SSAIR_ACTIVETURFS)
+ currentrun |= T
+ if(blockchanges)
+ T.eg_garbage_collect()
else if(T.flags_1 & INITIALIZED_1)
for(var/turf/S in T.atmos_adjacent_turfs)
add_to_active(S)
@@ -279,17 +317,6 @@ SUBSYSTEM_DEF(air)
else
T.requires_activation = TRUE
-/datum/controller/subsystem/air/proc/add_to_react_queue(turf/open/T)
- if(istype(T) && T.air)
- turf_react_queue[T] = TRUE
- if(currentpart == SSAIR_REACTQUEUE)
- currentrun[T] = TRUE
-
-/datum/controller/subsystem/air/proc/remove_from_react_queue(turf/open/T)
- turf_react_queue -= T
- if(currentpart == SSAIR_REACTQUEUE)
- currentrun -= T
-
/datum/controller/subsystem/air/StartLoadingMap()
LAZYINITLIST(queued_for_activation)
map_loading = TRUE
@@ -337,11 +364,11 @@ SUBSYSTEM_DEF(air)
while (turfs_to_check.len)
var/ending_ats = active_turfs.len
- for(var/thing in excited_groups)
+ /*for(var/thing in excited_groups)
var/datum/excited_group/EG = thing
- EG.self_breakdown(space_is_all_consuming = 1)
- EG.dismantle()
- CHECK_TICK
+ //EG.self_breakdown(space_is_all_consuming = 1)
+ //EG.dismantle()
+ CHECK_TICK*/
var/msg = "HEY! LISTEN! [DisplayTimeText(world.timeofday - timer)] were wasted processing [starting_ats] turf(s) (connected to [ending_ats] other turfs) with atmos differences at round start."
to_chat(world, "[msg]")
@@ -349,6 +376,7 @@ SUBSYSTEM_DEF(air)
/turf/open/proc/resolve_active_graph()
. = list()
+ /*
var/datum/excited_group/EG = excited_group
if (blocks_air || !air)
return
@@ -369,7 +397,8 @@ SUBSYSTEM_DEF(air)
EG.add_turf(ET)
if (!ET.excited)
ET.excited = 1
- . += ET
+ . += ET*/
+
/turf/open/space/resolve_active_graph()
return list()
@@ -387,9 +416,8 @@ SUBSYSTEM_DEF(air)
CHECK_TICK
/datum/controller/subsystem/air/proc/setup_template_machinery(list/atmos_machines)
- if(!initialized)
- return
-
+ if(!initialized) // yogs - fixes randomized bars
+ return // yogs
for(var/A in atmos_machines)
var/obj/machinery/atmospherics/AM = A
AM.atmosinit()
@@ -413,6 +441,7 @@ SUBSYSTEM_DEF(air)
#undef SSAIR_PIPENETS
#undef SSAIR_ATMOSMACHINERY
+#undef SSAIR_ACTIVETURFS
#undef SSAIR_EXCITEDGROUPS
#undef SSAIR_HIGHPRESSURE
#undef SSAIR_HOTSPOTS
diff --git a/code/controllers/subsystem/air_turfs.dm b/code/controllers/subsystem/air_turfs.dm
index 9dd41aede5..7320defcae 100644
--- a/code/controllers/subsystem/air_turfs.dm
+++ b/code/controllers/subsystem/air_turfs.dm
@@ -1,5 +1,5 @@
//WHAT IF WE TAKE THE ACTIVE TURF PROCESSING AND PUSH IT SOMEWHERE ELSE!!!
-
+/*
SUBSYSTEM_DEF(air_turfs)
name = "Atmospherics - Turfs"
init_order = INIT_ORDER_AIR_TURFS
@@ -24,3 +24,4 @@ SUBSYSTEM_DEF(air_turfs)
return
resumed = 0
return
+*/
diff --git a/code/game/machinery/doors/airlock.dm b/code/game/machinery/doors/airlock.dm
index 3bc8aff809..5665edfba2 100644
--- a/code/game/machinery/doors/airlock.dm
+++ b/code/game/machinery/doors/airlock.dm
@@ -93,7 +93,7 @@
var/shuttledocked = 0
var/delayed_close_requested = FALSE // TRUE means the door will automatically close the next time it's opened.
- var/air_tight = FALSE //TRUE means density will be set as soon as the door begins to close
+ air_tight = FALSE
var/prying_so_hard = FALSE
rad_flags = RAD_PROTECT_CONTENTS | RAD_NO_CONTAMINATE
diff --git a/code/game/machinery/doors/door.dm b/code/game/machinery/doors/door.dm
index c4c712ca25..5934658ba3 100644
--- a/code/game/machinery/doors/door.dm
+++ b/code/game/machinery/doors/door.dm
@@ -16,6 +16,7 @@
interaction_flags_atom = INTERACT_ATOM_UI_INTERACT
var/secondsElectrified = 0
+ var/air_tight = FALSE //TRUE means density will be set as soon as the door begins to close
var/shockedby
var/visible = TRUE
var/operating = FALSE
@@ -160,7 +161,7 @@
open()
else
close()
- return
+ return TRUE
if(density)
do_animate("deny")
@@ -180,11 +181,36 @@
/obj/machinery/door/proc/try_to_crowbar(obj/item/I, mob/user)
return
+/obj/machinery/door/proc/is_holding_pressure()
+ var/turf/open/T = loc
+ if(!T)
+ return FALSE
+ if(!density)
+ return FALSE
+ // alrighty now we check for how much pressure we're holding back
+ var/min_moles = T.air.total_moles()
+ var/max_moles = min_moles
+ // okay this is a bit hacky. First, we set density to 0 and recalculate our adjacent turfs
+ density = FALSE
+ T.ImmediateCalculateAdjacentTurfs()
+ // then we use those adjacent turfs to figure out what the difference between the lowest and highest pressures we'd be holding is
+ for(var/turf/open/T2 in T.atmos_adjacent_turfs)
+ if((flags_1 & ON_BORDER_1) && get_dir(src, T2) != dir)
+ continue
+ var/moles = T2.air.total_moles()
+ if(moles < min_moles)
+ min_moles = moles
+ if(moles > max_moles)
+ max_moles = moles
+ density = TRUE
+ T.ImmediateCalculateAdjacentTurfs() // alright lets put it back
+ return max_moles - min_moles > 20
+
/obj/machinery/door/attackby(obj/item/I, mob/user, params)
- if(user.a_intent != INTENT_HARM && (istype(I, /obj/item/crowbar) || istype(I, /obj/item/twohanded/fireaxe)))
+ if(user.a_intent != INTENT_HARM && (I.tool_behaviour == TOOL_CROWBAR || istype(I, /obj/item/twohanded/fireaxe)))
try_to_crowbar(I, user)
return 1
- else if(istype(I, /obj/item/weldingtool))
+ else if(I.tool_behaviour == TOOL_WELDER)
try_to_weld(I, user)
return 1
else if(!(I.item_flags & NOBLUDGEON) && user.a_intent != INTENT_HARM)
@@ -292,6 +318,8 @@
layer = closingLayer
if(!safe)
crush()
+ if(air_tight)
+ density = TRUE
sleep(5)
density = TRUE
sleep(5)
diff --git a/code/game/machinery/doors/firedoor.dm b/code/game/machinery/doors/firedoor.dm
index 28b9796bb6..eed6f2a040 100644
--- a/code/game/machinery/doors/firedoor.dm
+++ b/code/game/machinery/doors/firedoor.dm
@@ -23,6 +23,7 @@
assemblytype = /obj/structure/firelock_frame
armor = list("melee" = 30, "bullet" = 30, "laser" = 20, "energy" = 20, "bomb" = 10, "bio" = 100, "rad" = 100, "fire" = 95, "acid" = 70)
interaction_flags_machine = INTERACT_MACHINE_WIRES_IF_OPEN | INTERACT_MACHINE_ALLOW_SILICON | INTERACT_MACHINE_OPEN_SILICON | INTERACT_MACHINE_REQUIRES_SILICON | INTERACT_MACHINE_OPEN
+ var/emergency_close_timer = 0
var/nextstate = null
var/boltslocked = TRUE
var/list/affecting_areas
@@ -100,7 +101,7 @@
return
if(welded)
- if(istype(C, /obj/item/wrench))
+ if(C.tool_behaviour == TOOL_WRENCH)
if(boltslocked)
to_chat(user, "There are screws locking the bolts in place!")
return
@@ -114,7 +115,7 @@
"You undo [src]'s floor bolts.")
deconstruct(TRUE)
return
- if(istype(C, /obj/item/screwdriver))
+ if(C.tool_behaviour == TOOL_SCREWDRIVER)
user.visible_message("[user] [boltslocked ? "unlocks" : "locks"] [src]'s bolts.", \
"You [boltslocked ? "unlock" : "lock"] [src]'s floor bolts.")
C.play_tool_sound(src)
@@ -140,6 +141,17 @@
return
if(density)
+ if(is_holding_pressure())
+ // tell the user that this is a bad idea, and have a do_after as well
+ to_chat(user, "As you begin crowbarring \the [src] a gush of air blows in your face... maybe you should reconsider?")
+ if(!do_after(user, 15, TRUE, src)) // give them a few seconds to reconsider their decision.
+ return
+ log_game("[key_name_admin(user)] has opened a firelock with a pressure difference at [AREACOORD(loc)]") // there bibby I made it logged just for you. Enjoy.
+ // since we have high-pressure-ness, close all other firedoors on the tile
+ whack_a_mole()
+ if(welded || operating || !density)
+ return // in case things changed during our do_after
+ emergency_close_timer = world.time + 60 // prevent it from instaclosing again if in space
open()
else
close()
@@ -194,6 +206,61 @@
. = ..()
latetoggle()
+/obj/machinery/door/firedoor/proc/whack_a_mole(reconsider_immediately = FALSE)
+ set waitfor = 0
+ for(var/cdir in GLOB.cardinals)
+ if((flags_1 & ON_BORDER_1) && cdir != dir)
+ continue
+ whack_a_mole_part(get_step(src, cdir), reconsider_immediately)
+ if(flags_1 & ON_BORDER_1)
+ whack_a_mole_part(get_turf(src), reconsider_immediately)
+
+/obj/machinery/door/firedoor/proc/whack_a_mole_part(turf/start_point, reconsider_immediately)
+ set waitfor = 0
+ var/list/doors_to_close = list()
+ var/list/turfs = list()
+ turfs[start_point] = 1
+ for(var/i = 1; (i <= turfs.len && i <= 11); i++) // check up to 11 turfs.
+ var/turf/open/T = turfs[i]
+ if(istype(T, /turf/open/space))
+ return -1
+ for(var/T2 in T.atmos_adjacent_turfs)
+ if(turfs[T2])
+ continue
+ var/is_cut_by_unopen_door = FALSE
+ for(var/obj/machinery/door/firedoor/FD in T2)
+ if((FD.flags_1 & ON_BORDER_1) && get_dir(T2, T) != FD.dir)
+ continue
+ if(FD.operating || FD == src || FD.welded || FD.density)
+ continue
+ doors_to_close += FD
+ is_cut_by_unopen_door = TRUE
+
+ for(var/obj/machinery/door/firedoor/FD in T)
+ if((FD.flags_1 & ON_BORDER_1) && get_dir(T, T2) != FD.dir)
+ continue
+ if(FD.operating || FD == src || FD.welded || FD.density)
+ continue
+ doors_to_close += FD
+ is_cut_by_unopen_door= TRUE
+ if(!is_cut_by_unopen_door)
+ turfs[T2] = 1
+ if(turfs.len > 10)
+ return // too big, don't bother
+ for(var/obj/machinery/door/firedoor/FD in doors_to_close)
+ FD.emergency_pressure_stop(FALSE)
+ if(reconsider_immediately)
+ var/turf/open/T = FD.loc
+ if(istype(T))
+ T.ImmediateCalculateAdjacentTurfs()
+
+/obj/machinery/door/firedoor/proc/emergency_pressure_stop(consider_timer = TRUE)
+ set waitfor = 0
+ if(density || operating || welded)
+ return
+ if(world.time >= emergency_close_timer || !consider_timer)
+ close()
+
/obj/machinery/door/firedoor/deconstruct(disassembled = TRUE)
if(!(flags_1 & NODECONSTRUCT_1))
var/obj/structure/firelock_frame/F = new assemblytype(get_turf(src))
@@ -227,6 +294,30 @@
opacity = TRUE
density = TRUE
+/obj/machinery/door/firedoor/border_only/close()
+ if(density)
+ return TRUE
+ if(operating || welded)
+ return
+ var/turf/T1 = get_turf(src)
+ var/turf/T2 = get_step(T1, dir)
+ for(var/mob/living/M in T1)
+ if(M.stat == CONSCIOUS && M.pulling && M.pulling.loc == T2 && !M.pulling.anchored && M.pulling.move_resist <= M.move_force)
+ var/mob/living/M2 = M.pulling
+ if(!istype(M2) || !M2.buckled || !M2.buckled.buckle_prevents_pull)
+ to_chat(M, "You pull [M.pulling] through [src] right as it closes")
+ M.pulling.forceMove(T1)
+ M.start_pulling(M2)
+
+ for(var/mob/living/M in T2)
+ if(M.stat == CONSCIOUS && M.pulling && M.pulling.loc == T1 && !M.pulling.anchored && M.pulling.move_resist <= M.move_force)
+ var/mob/living/M2 = M.pulling
+ if(!istype(M2) || !M2.buckled || !M2.buckled.buckle_prevents_pull)
+ to_chat(M, "You pull [M.pulling] through [src] right as it closes")
+ M.pulling.forceMove(T2)
+ M.start_pulling(M2)
+ . = ..()
+
/obj/machinery/door/firedoor/border_only/CanPass(atom/movable/mover, turf/target)
if(istype(mover) && (mover.pass_flags & PASSGLASS))
return TRUE
@@ -293,7 +384,7 @@
/obj/structure/firelock_frame/attackby(obj/item/C, mob/user)
switch(constructionStep)
if(CONSTRUCTION_PANEL_OPEN)
- if(istype(C, /obj/item/crowbar))
+ if(C.tool_behaviour == TOOL_CROWBAR)
C.play_tool_sound(src)
user.visible_message("[user] starts prying something out from [src]...", \
"You begin prying out the wire cover...")
@@ -307,7 +398,7 @@
constructionStep = CONSTRUCTION_WIRES_EXPOSED
update_icon()
return
- if(istype(C, /obj/item/wrench))
+ if(C.tool_behaviour == TOOL_WRENCH)
if(locate(/obj/machinery/door/firedoor) in get_turf(src))
to_chat(user, "There's already a firelock there.")
return
@@ -349,7 +440,7 @@
return
if(CONSTRUCTION_WIRES_EXPOSED)
- if(istype(C, /obj/item/wirecutters))
+ if(C.tool_behaviour == TOOL_WIRECUTTER)
C.play_tool_sound(src)
user.visible_message("[user] starts cutting the wires from [src]...", \
"You begin removing [src]'s wires...")
@@ -363,7 +454,7 @@
constructionStep = CONSTRUCTION_GUTTED
update_icon()
return
- if(istype(C, /obj/item/crowbar))
+ if(C.tool_behaviour == TOOL_CROWBAR)
C.play_tool_sound(src)
user.visible_message("[user] starts prying a metal plate into [src]...", \
"You begin prying the cover plate back onto [src]...")
@@ -378,7 +469,7 @@
update_icon()
return
if(CONSTRUCTION_GUTTED)
- if(istype(C, /obj/item/crowbar))
+ if(C.tool_behaviour == TOOL_CROWBAR)
user.visible_message("[user] begins removing the circuit board from [src]...", \
"You begin prying out the circuit board from [src]...")
if(!C.use_tool(src, user, 50, volume=50))
@@ -400,7 +491,7 @@
"You begin adding wires to [src]...")
playsound(get_turf(src), 'sound/items/deconstruct.ogg', 50, 1)
if(do_after(user, 60, target = src))
- if(constructionStep != CONSTRUCTION_GUTTED || !B.use_tool(src, user, 0, 5))
+ if(constructionStep != CONSTRUCTION_GUTTED || B.get_amount() < 5 || !B)
return
user.visible_message("[user] adds wires to [src].", \
"You wire [src].")
@@ -409,7 +500,7 @@
update_icon()
return
if(CONSTRUCTION_NOCIRCUIT)
- if(istype(C, /obj/item/weldingtool))
+ if(C.tool_behaviour == TOOL_WELDER)
if(!C.tool_start_check(user, amount=1))
return
user.visible_message("[user] begins cutting apart [src]'s frame...", \
diff --git a/code/game/objects/effects/temporary_visuals/miscellaneous.dm b/code/game/objects/effects/temporary_visuals/miscellaneous.dm
index 53adc46239..396f463136 100644
--- a/code/game/objects/effects/temporary_visuals/miscellaneous.dm
+++ b/code/game/objects/effects/temporary_visuals/miscellaneous.dm
@@ -486,4 +486,15 @@
addtimer(CALLBACK(src, .proc/end), 15)
/obj/effect/constructing_effect/proc/end()
- qdel(src)
\ No newline at end of file
+ qdel(src)
+
+/obj/effect/temp_visual/dir_setting/space_wind
+ icon = 'icons/effects/atmospherics.dmi'
+ icon_state = "space_wind"
+ layer = FLY_LAYER
+ duration = 20
+ mouse_opacity = 0
+
+/obj/effect/temp_visual/dir_setting/space_wind/Initialize(mapload, set_dir, set_alpha = 255)
+ . = ..()
+ alpha = set_alpha
diff --git a/code/game/objects/structures/holosign.dm b/code/game/objects/structures/holosign.dm
index 7ac3aba246..c49159a992 100644
--- a/code/game/objects/structures/holosign.dm
+++ b/code/game/objects/structures/holosign.dm
@@ -94,7 +94,7 @@
alpha = 150
resistance_flags = FIRE_PROOF
-/obj/structure/holosign/barrier/firelock/blocksTemperature()
+/obj/structure/holosign/barrier/firelock/BlockSuperconductivity()
return TRUE
/obj/structure/holosign/barrier/combifan
@@ -110,7 +110,7 @@
CanAtmosPass = ATMOS_PASS_NO
resistance_flags = FIRE_PROOF
-/obj/structure/holosign/barrier/combifan/blocksTemperature()
+/obj/structure/holosign/barrier/combifan/BlockSuperconductivity()
return TRUE
/obj/structure/holosign/barrier/combifan/Initialize()
diff --git a/code/game/turfs/change_turf.dm b/code/game/turfs/change_turf.dm
index 80e542dad8..3f1a681246 100644
--- a/code/game/turfs/change_turf.dm
+++ b/code/game/turfs/change_turf.dm
@@ -142,6 +142,7 @@ GLOBAL_LIST_INIT(blacklisted_automated_baseturfs, typecacheof(list(
. = ..()
if (!.) // changeturf failed or didn't do anything
QDEL_NULL(stashed_air)
+ update_air_ref()
return
var/turf/open/newTurf = .
newTurf.air.copy_from(stashed_air)
diff --git a/code/game/turfs/closed.dm b/code/game/turfs/closed.dm
index 99c7ed8231..0c2fd98aba 100644
--- a/code/game/turfs/closed.dm
+++ b/code/game/turfs/closed.dm
@@ -6,9 +6,14 @@
rad_flags = RAD_PROTECT_CONTENTS | RAD_NO_CONTAMINATE
rad_insulation = RAD_MEDIUM_INSULATION
+/turf/closed/Initialize()
+ . = ..()
+ update_air_ref()
+
/turf/closed/AfterChange()
. = ..()
SSair.high_pressure_delta -= src
+ update_air_ref()
/turf/closed/get_smooth_underlay_icon(mutable_appearance/underlay_appearance, turf/asking_turf, adjacency_dir)
return FALSE
diff --git a/code/game/turfs/open.dm b/code/game/turfs/open.dm
index 6a17b02d66..6552e29246 100644
--- a/code/game/turfs/open.dm
+++ b/code/game/turfs/open.dm
@@ -199,7 +199,7 @@
flash_color(L, flash_color = "#C80000", flash_time = 10)
/turf/open/Initalize_Atmos(times_fired)
- excited = 0
+ set_excited(FALSE)
update_visuals()
current_cycle = times_fired
@@ -207,9 +207,9 @@
for(var/i in atmos_adjacent_turfs)
var/turf/open/enemy_tile = i
var/datum/gas_mixture/enemy_air = enemy_tile.return_air()
- if(!excited && air.compare(enemy_air))
+ if(!get_excited() && air.compare(enemy_air))
//testing("Active turf found. Return value of compare(): [is_active]")
- excited = TRUE
+ set_excited(TRUE)
SSair.active_turfs |= src
/turf/open/proc/GetHeatCapacity()
diff --git a/code/game/turfs/space/space.dm b/code/game/turfs/space/space.dm
index 26daa32107..b131a1ed70 100644
--- a/code/game/turfs/space/space.dm
+++ b/code/game/turfs/space/space.dm
@@ -27,6 +27,7 @@
/turf/open/space/Initialize()
icon_state = SPACE_ICON_STATE
air = space_gas
+ update_air_ref()
vis_contents.Cut() //removes inherited overlays
visibilityChanged()
diff --git a/code/game/world.dm b/code/game/world.dm
index 10431e4af9..7f6b2c5da7 100644
--- a/code/game/world.dm
+++ b/code/game/world.dm
@@ -262,6 +262,15 @@ GLOBAL_LIST(topic_status_cache)
shutdown_logging() // Past this point, no logging procs can be used, at risk of data loss.
..()
+/world/Del()
+ // memory leaks bad
+ var/num_deleted = 0
+ for(var/datum/gas_mixture/GM)
+ GM.__gasmixture_unregister()
+ num_deleted++
+ log_world("Deallocated [num_deleted] gas mixtures")
+ ..()
+
/world/proc/update_status()
var/list/features = list()
@@ -330,3 +339,6 @@ GLOBAL_LIST(topic_status_cache)
maxz++
SSmobs.MaxZChanged()
SSidlenpcpool.MaxZChanged()
+ world.refresh_atmos_grid()
+
+/world/proc/refresh_atmos_grid()
diff --git a/code/modules/atmospherics/environmental/LINDA_fire.dm b/code/modules/atmospherics/environmental/LINDA_fire.dm
index 40b91ed74c..81e103fba2 100644
--- a/code/modules/atmospherics/environmental/LINDA_fire.dm
+++ b/code/modules/atmospherics/environmental/LINDA_fire.dm
@@ -9,46 +9,31 @@
return
-/turf/open/hotspot_expose(exposed_temperature, exposed_volume, soh = FALSE, holo = FALSE)
- var/datum/gas_mixture/air_contents = return_air()
- if(!air_contents)
- return 0
+/turf/open/hotspot_expose(exposed_temperature, exposed_volume, soh)
+ if(!air)
+ return
- var/oxy = air_contents.get_moles(/datum/gas/oxygen)
- var/tox = air_contents.get_moles(/datum/gas/plasma)
- var/trit = air_contents.get_moles(/datum/gas/tritium)
+ var/oxy = air.get_moles(/datum/gas/oxygen)
+ if (oxy < 0.5)
+ return
+ var/tox = air.get_moles(/datum/gas/plasma)
+ var/trit = air.get_moles(/datum/gas/tritium)
if(active_hotspot)
if(soh)
- if((tox > 0.5 || trit > 0.5) && oxy > 0.5)
- if(active_hotspot.temperature < exposed_temperature*50)
- active_hotspot.temperature = exposed_temperature*50
+ if(tox > 0.5 || trit > 0.5)
+ if(active_hotspot.temperature < exposed_temperature)
+ active_hotspot.temperature = exposed_temperature
if(active_hotspot.volume < exposed_volume)
active_hotspot.volume = exposed_volume
- return 1
-
- var/igniting = 0
+ return
if((exposed_temperature > PLASMA_MINIMUM_BURN_TEMPERATURE) && (tox > 0.5 || trit > 0.5))
- igniting = 1
- if(igniting)
- if(oxy < 0.5)
- return 0
-
- active_hotspot = new /obj/effect/hotspot(src, holo)
- active_hotspot.temperature = exposed_temperature*50
- active_hotspot.volume = exposed_volume*25
+ active_hotspot = new /obj/effect/hotspot(src, exposed_volume*25, exposed_temperature)
active_hotspot.just_spawned = (current_cycle < SSair.times_fired)
//remove just_spawned protection if no longer processing this cell
SSair.add_to_active(src, 0)
- else
- var/datum/gas_mixture/heating = air_contents.remove_ratio(exposed_volume/air_contents.return_volume())
- heating.set_temperature(exposed_temperature)
- heating.react()
- assume_air(heating)
- air_update_turf()
- return igniting
//This is the icon for fire on turfs, also helps for nurturing small fires until they are full tile
/obj/effect/hotspot
@@ -67,11 +52,13 @@
var/bypassing = FALSE
var/visual_update_tick = 0
-/obj/effect/hotspot/Initialize(mapload, holo = FALSE)
+/obj/effect/hotspot/Initialize(mapload, starting_volume, starting_temperature)
. = ..()
- if(holo)
- flags_1 |= HOLOGRAM_1
SSair.hotspots += src
+ if(!isnull(starting_volume))
+ volume = starting_volume
+ if(!isnull(starting_temperature))
+ temperature = starting_temperature
perform_exposure()
setDir(pick(GLOB.cardinals))
air_update_turf()
@@ -83,22 +70,19 @@
location.active_hotspot = src
- if(volume > CELL_VOLUME*0.95)
- bypassing = TRUE
- else
- bypassing = FALSE
+ bypassing = !just_spawned && (volume > CELL_VOLUME*0.95)
if(bypassing)
- if(!just_spawned)
- volume = location.air.reaction_results["fire"]*FIRE_GROWTH_RATE
- temperature = location.air.return_temperature()
+ volume = location.air.reaction_results["fire"]*FIRE_GROWTH_RATE
+ temperature = location.air.return_temperature()
else
var/datum/gas_mixture/affected = location.air.remove_ratio(volume/location.air.return_volume())
- affected.set_temperature(temperature)
- affected.react(src)
- temperature = affected.return_temperature()
- volume = affected.reaction_results["fire"]*FIRE_GROWTH_RATE
- location.assume_air(affected)
+ if(affected) //in case volume is 0
+ affected.set_temperature(temperature)
+ affected.react(src)
+ temperature = affected.return_temperature()
+ volume = affected.reaction_results["fire"]*FIRE_GROWTH_RATE
+ location.assume_air(affected)
for(var/A in location)
var/atom/AT = A
@@ -175,8 +159,7 @@
qdel(src)
return
- if(location.excited_group)
- location.excited_group.reset_cooldowns()
+ location.eg_reset_cooldowns()
if((temperature < FIRE_MINIMUM_TEMPERATURE_TO_EXIST) || (volume <= 1))
qdel(src)
@@ -185,12 +168,17 @@
qdel(src)
return
+ //Not enough to burn
+ // god damn it previous coder you made the INSUFFICIENT macro for a fucking reason why didn't you use it here smh
+ if((INSUFFICIENT(/datum/gas/plasma) && INSUFFICIENT(/datum/gas/tritium)) || INSUFFICIENT(/datum/gas/oxygen))
+ qdel(src)
+ return
+
perform_exposure()
if(bypassing)
icon_state = "3"
- if(!(flags_1 & HOLOGRAM_1))
- location.burn_tile()
+ location.burn_tile()
//Possible spread due to radiated heat
if(location.air.return_temperature() > FIRE_MINIMUM_TEMPERATURE_TO_SPREAD)
@@ -198,7 +186,7 @@
for(var/t in location.atmos_adjacent_turfs)
var/turf/open/T = t
if(!T.active_hotspot)
- T.hotspot_expose(radiated_temperature, CELL_VOLUME/4, flags_1 & HOLOGRAM_1)
+ T.hotspot_expose(radiated_temperature, CELL_VOLUME/4)
else
if(volume > CELL_VOLUME*0.4)
@@ -222,14 +210,13 @@
var/turf/open/T = loc
if(istype(T) && T.active_hotspot == src)
T.active_hotspot = null
- if(!(flags_1 & HOLOGRAM_1))
- DestroyTurf()
+ DestroyTurf()
return ..()
/obj/effect/hotspot/proc/DestroyTurf()
if(isturf(loc))
var/turf/T = loc
- if(T.to_be_destroyed)
+ if(T.to_be_destroyed && !T.changing_turf)
var/chance_of_deletion
if (T.heat_capacity) //beware of division by zero
chance_of_deletion = T.max_fire_temperature_sustained / T.heat_capacity * 8 //there is no problem with prob(23456), min() was redundant --rastaf0
diff --git a/code/modules/atmospherics/environmental/LINDA_system.dm b/code/modules/atmospherics/environmental/LINDA_system.dm
index 760e4e22da..21dc6069a6 100644
--- a/code/modules/atmospherics/environmental/LINDA_system.dm
+++ b/code/modules/atmospherics/environmental/LINDA_system.dm
@@ -44,25 +44,32 @@
return FALSE
/turf/proc/ImmediateCalculateAdjacentTurfs()
- var/canpass = CANATMOSPASS(src, src)
+ var/canpass = CANATMOSPASS(src, src)
var/canvpass = CANVERTICALATMOSPASS(src, src)
for(var/direction in GLOB.cardinals_multiz)
var/turf/T = get_step_multiz(src, direction)
+ var/opp_dir = dir_inverse_multiz(direction)
if(!isopenturf(T))
continue
if(!(blocks_air || T.blocks_air) && ((direction & (UP|DOWN))? (canvpass && CANVERTICALATMOSPASS(T, src)) : (canpass && CANATMOSPASS(T, src))) )
LAZYINITLIST(atmos_adjacent_turfs)
LAZYINITLIST(T.atmos_adjacent_turfs)
- atmos_adjacent_turfs[T] = TRUE
- T.atmos_adjacent_turfs[src] = TRUE
+ atmos_adjacent_turfs[T] = direction
+ T.atmos_adjacent_turfs[src] = opp_dir
+ T.__update_extools_adjacent_turfs()
else
if (atmos_adjacent_turfs)
atmos_adjacent_turfs -= T
if (T.atmos_adjacent_turfs)
T.atmos_adjacent_turfs -= src
+ T.__update_extools_adjacent_turfs()
UNSETEMPTY(T.atmos_adjacent_turfs)
UNSETEMPTY(atmos_adjacent_turfs)
src.atmos_adjacent_turfs = atmos_adjacent_turfs
+ __update_extools_adjacent_turfs()
+
+/turf/proc/__update_extools_adjacent_turfs()
+
//returns a list of adjacent turfs that can share air with this one.
//alldir includes adjacent diagonal tiles that can share
@@ -111,9 +118,9 @@
SSair.add_to_active(src,command)
/atom/movable/proc/move_update_air(turf/T)
- if(isturf(T))
- T.air_update_turf(1)
- air_update_turf(1)
+ if(isturf(T))
+ T.air_update_turf(1)
+ air_update_turf(1)
/atom/proc/atmos_spawn_air(text) //because a lot of people loves to copy paste awful code lets just make an easy proc to spawn your plasma fires
var/turf/open/T = get_turf(src)
diff --git a/code/modules/atmospherics/environmental/LINDA_turf_tile.dm b/code/modules/atmospherics/environmental/LINDA_turf_tile.dm
index 5a2c46a6dc..dd1b0b4778 100644
--- a/code/modules/atmospherics/environmental/LINDA_turf_tile.dm
+++ b/code/modules/atmospherics/environmental/LINDA_turf_tile.dm
@@ -8,6 +8,7 @@
var/list/atmos_adjacent_turfs
//bitfield of dirs in which we are superconducitng
var/atmos_supeconductivity = NONE
+ var/is_openturf = FALSE // used by extools shizz.
//used to determine whether we should archive
var/archived_cycle = 0
@@ -23,21 +24,21 @@
//used for spacewind
var/pressure_difference = 0
var/pressure_direction = 0
+ var/turf/pressure_specific_target
- var/datum/excited_group/excited_group
- var/excited = FALSE
var/datum/gas_mixture/turf/air
var/obj/effect/hotspot/active_hotspot
- var/atmos_cooldown = 0
var/planetary_atmos = FALSE //air will revert to initial_gas_mix over time
var/list/atmos_overlay_types //gas IDs of current active gas overlays
+ is_openturf = TRUE
/turf/open/Initialize()
if(!blocks_air)
air = new
air.copy_from_turf(src)
+ update_air_ref()
. = ..()
/turf/open/Destroy()
@@ -48,6 +49,8 @@
SSair.add_to_active(T)
return ..()
+/turf/proc/update_air_ref()
+
/////////////////GAS MIXTURE PROCS///////////////////
/turf/open/assume_air(datum/gas_mixture/giver) //use this for machines to adjust air
@@ -93,11 +96,33 @@
archived_cycle = SSair.times_fired
temperature_archived = temperature
+/turf/open/proc/eg_reset_cooldowns()
+/turf/open/proc/eg_garbage_collect()
+/turf/open/proc/get_excited()
+/turf/open/proc/set_excited()
+
/////////////////////////GAS OVERLAYS//////////////////////////////
+
/turf/open/proc/update_visuals()
- var/list/new_overlay_types = tile_graphic()
+
var/list/atmos_overlay_types = src.atmos_overlay_types // Cache for free performance
+ var/list/new_overlay_types = list()
+ var/static/list/nonoverlaying_gases = typecache_of_gases_with_no_overlays()
+
+ if(!air) // 2019-05-14: was not able to get this path to fire in testing. Consider removing/looking at callers -Naksu
+ if (atmos_overlay_types)
+ for(var/overlay in atmos_overlay_types)
+ vis_contents -= overlay
+ src.atmos_overlay_types = null
+ return
+
+ for(var/id in air.get_gases())
+ if (nonoverlaying_gases[id])
+ continue
+ var/gas_overlay = GLOB.meta_gas_overlays[id]
+ if(gas_overlay && air.get_moles(id) > GLOB.meta_gas_visibility[META_GAS_MOLES_VISIBLE])
+ new_overlay_types += gas_overlay[min(FACTOR_GAS_VISIBLE_MAX, CEILING(air.get_moles(id) / MOLES_GAS_VISIBLE_STEP, 1))]
if (atmos_overlay_types)
for(var/overlay in atmos_overlay_types-new_overlay_types) //doesn't remove overlays that would only be added
@@ -112,18 +137,18 @@
UNSETEMPTY(new_overlay_types)
src.atmos_overlay_types = new_overlay_types
-/turf/open/proc/tile_graphic()
- var/static/list/nonoverlaying_gases = typecache_of_gases_with_no_overlays()
- if(!air)
- return
- . = new /list
- for(var/id in air.get_gases())
- if (nonoverlaying_gases[id])
- continue
- var/gas = air.get_moles(id)
- var/gas_overlay = GLOB.meta_gas_overlays[id]
- if(gas_overlay && gas > GLOB.meta_gas_visibility[id])
- . += gas_overlay[min(FACTOR_GAS_VISIBLE_MAX, CEILING(gas / MOLES_GAS_VISIBLE_STEP, 1))]
+/turf/open/proc/set_visuals(list/new_overlay_types)
+ if (atmos_overlay_types)
+ for(var/overlay in atmos_overlay_types-new_overlay_types) //doesn't remove overlays that would only be added
+ vis_contents -= overlay
+
+ if (length(new_overlay_types))
+ if (atmos_overlay_types)
+ vis_contents += new_overlay_types - atmos_overlay_types //don't add overlays that already exist
+ else
+ vis_contents += new_overlay_types
+ UNSETEMPTY(new_overlay_types)
+ src.atmos_overlay_types = new_overlay_types
/proc/typecache_of_gases_with_no_overlays()
. = list()
@@ -134,7 +159,7 @@
/////////////////////////////SIMULATION///////////////////////////////////
-#define LAST_SHARE_CHECK \
+/*#define LAST_SHARE_CHECK \
var/last_share = our_air.get_last_share();\
if(last_share > MINIMUM_AIR_TO_SUSPEND){\
our_excited_group.reset_cooldowns();\
@@ -143,102 +168,32 @@
our_excited_group.dismantle_cooldown = 0;\
cached_atmos_cooldown = 0;\
}
-
+*/
/turf/proc/process_cell(fire_count)
SSair.remove_from_active(src)
-/turf/open/process_cell(fire_count)
- if(archived_cycle < fire_count) //archive self if not already done
- archive()
-
- current_cycle = fire_count
-
- //cache for sanic speed
- var/list/adjacent_turfs = atmos_adjacent_turfs
- var/datum/excited_group/our_excited_group = excited_group
- var/adjacent_turfs_length = LAZYLEN(adjacent_turfs)
- var/cached_atmos_cooldown = atmos_cooldown + 1
-
- var/planet_atmos = planetary_atmos
- if (planet_atmos)
- adjacent_turfs_length++
-
- var/datum/gas_mixture/our_air = air
-
- for(var/t in adjacent_turfs)
- var/turf/open/enemy_tile = t
-
- if(fire_count <= enemy_tile.current_cycle)
+/turf/open/proc/equalize_pressure_in_zone(cyclenum)
+/turf/open/proc/consider_firelocks(turf/T2)
+ var/reconsider_adj = FALSE
+ for(var/obj/machinery/door/firedoor/FD in T2)
+ if((FD.flags_1 & ON_BORDER_1) && get_dir(T2, src) != FD.dir)
continue
- enemy_tile.archive()
+ FD.emergency_pressure_stop()
+ reconsider_adj = TRUE
+ for(var/obj/machinery/door/firedoor/FD in src)
+ if((FD.flags_1 & ON_BORDER_1) && get_dir(src, T2) != FD.dir)
+ continue
+ FD.emergency_pressure_stop()
+ reconsider_adj = TRUE
+ if(reconsider_adj)
+ T2.ImmediateCalculateAdjacentTurfs() // We want those firelocks closed yesterday.
- /******************* GROUP HANDLING START *****************************************************************/
+/turf/proc/handle_decompression_floor_rip()
+/turf/open/floor/handle_decompression_floor_rip(sum)
+ if(sum > 20 && prob(clamp(sum / 10, 0, 30)))
+ remove_tile()
- var/should_share_air = FALSE
- var/datum/gas_mixture/enemy_air = enemy_tile.air
-
- //cache for sanic speed
- var/datum/excited_group/enemy_excited_group = enemy_tile.excited_group
-
- if(our_excited_group && enemy_excited_group)
- if(our_excited_group != enemy_excited_group)
- //combine groups (this also handles updating the excited_group var of all involved turfs)
- our_excited_group.merge_groups(enemy_excited_group)
- our_excited_group = excited_group //update our cache
- should_share_air = TRUE
-
- else if(our_air.compare(enemy_air))
- if(!enemy_tile.excited)
- SSair.add_to_active(enemy_tile)
- var/datum/excited_group/EG = our_excited_group || enemy_excited_group || new
- if(!our_excited_group)
- EG.add_turf(src)
- if(!enemy_excited_group)
- EG.add_turf(enemy_tile)
- our_excited_group = excited_group
- should_share_air = TRUE
-
- //air sharing
- if(should_share_air)
- var/difference = our_air.share(enemy_air, adjacent_turfs_length)
- if(difference)
- if(difference > 0)
- consider_pressure_difference(enemy_tile, difference)
- else
- enemy_tile.consider_pressure_difference(src, -difference)
- LAST_SHARE_CHECK
-
-
- /******************* GROUP HANDLING FINISH *********************************************************************/
-
- if (planet_atmos) //share our air with the "atmosphere" "above" the turf
- var/datum/gas_mixture/G = new
- G.copy_from_turf(src)
- G.archive()
- if(our_air.compare(G))
- if(!our_excited_group)
- var/datum/excited_group/EG = new
- EG.add_turf(src)
- our_excited_group = excited_group
- our_air.share(G, adjacent_turfs_length)
- LAST_SHARE_CHECK
-
- SSair.add_to_react_queue(src)
-
- if((!our_excited_group && !(our_air.return_temperature() > MINIMUM_TEMPERATURE_START_SUPERCONDUCTION && consider_superconductivity(starting = TRUE))) \
- || (cached_atmos_cooldown > (EXCITED_GROUP_DISMANTLE_CYCLES * 2)))
- SSair.remove_from_active(src)
-
- atmos_cooldown = cached_atmos_cooldown
-
-/turf/proc/process_cell_reaction()
- SSair.remove_from_react_queue(src)
-
-/turf/open/process_cell_reaction()
- air.react(src)
- update_visuals()
- SSair.remove_from_react_queue(src)
- return
+/turf/open/process_cell(fire_count)
//////////////////////////SPACEWIND/////////////////////////////
@@ -250,17 +205,24 @@
/turf/open/proc/high_pressure_movements()
var/atom/movable/M
+ var/multiplier = 1
+ if(locate(/obj/structure/rack) in src)
+ multiplier *= 0.1
+ else if(locate(/obj/structure/table) in src)
+ multiplier *= 0.2
for(var/thing in src)
M = thing
if (!M.anchored && !M.pulledby && M.last_high_pressure_movement_air_cycle < SSair.times_fired)
- M.experience_pressure_difference(pressure_difference, pressure_direction)
+ M.experience_pressure_difference(pressure_difference * multiplier, pressure_direction, 0, pressure_specific_target)
+ if(pressure_difference > 100)
+ new /obj/effect/temp_visual/dir_setting/space_wind(src, pressure_direction, clamp(round(sqrt(pressure_difference) * 2), 10, 255))
/atom/movable/var/pressure_resistance = 10
/atom/movable/var/last_high_pressure_movement_air_cycle = 0
-/atom/movable/proc/experience_pressure_difference(pressure_difference, direction, pressure_resistance_prob_delta = 0)
+/atom/movable/proc/experience_pressure_difference(pressure_difference, direction, pressure_resistance_prob_delta = 0, throw_target)
var/const/PROBABILITY_OFFSET = 25
- var/const/PROBABILITY_BASE_PRECENT = 75
+ var/const/PROBABILITY_BASE_PRECENT = 10
var/max_force = sqrt(pressure_difference)*(MOVE_FORCE_DEFAULT / 5)
set waitfor = 0
var/move_prob = 100
@@ -268,91 +230,19 @@
move_prob = (pressure_difference/pressure_resistance*PROBABILITY_BASE_PRECENT)-PROBABILITY_OFFSET
move_prob += pressure_resistance_prob_delta
if (move_prob > PROBABILITY_OFFSET && prob(move_prob) && (move_resist != INFINITY) && (!anchored && (max_force >= (move_resist * MOVE_FORCE_PUSH_RATIO))) || (anchored && (max_force >= (move_resist * MOVE_FORCE_FORCEPUSH_RATIO))))
- step(src, direction)
+ var/move_force = max_force * clamp(move_prob, 0, 100) / 100
+ if(move_force > 4000)
+ // WALLSLAM HELL TIME OH BOY
+ var/turf/throw_turf = get_ranged_target_turf(get_turf(src), direction, round(move_force / 2000))
+ if(throw_target && (get_dir(src, throw_target) & direction))
+ throw_turf = get_turf(throw_target)
+ var/throw_speed = clamp(round(move_force / 2000), 1, 10)
+ throw_at(throw_turf, move_force / 2000, throw_speed)
+ else
+ step(src, direction)
last_high_pressure_movement_air_cycle = SSair.times_fired
-///////////////////////////EXCITED GROUPS/////////////////////////////
-
-/datum/excited_group
- var/list/turf_list = list()
- var/breakdown_cooldown = 0
- var/dismantle_cooldown = 0
-
-/datum/excited_group/New()
- SSair.excited_groups += src
-
-/datum/excited_group/proc/add_turf(turf/open/T)
- turf_list += T
- T.excited_group = src
- reset_cooldowns()
-
-/datum/excited_group/proc/merge_groups(datum/excited_group/E)
- if(turf_list.len > E.turf_list.len)
- SSair.excited_groups -= E
- for(var/t in E.turf_list)
- var/turf/open/T = t
- T.excited_group = src
- turf_list += T
- reset_cooldowns()
- else
- SSair.excited_groups -= src
- for(var/t in turf_list)
- var/turf/open/T = t
- T.excited_group = E
- E.turf_list += T
- E.reset_cooldowns()
-
-/datum/excited_group/proc/reset_cooldowns()
- breakdown_cooldown = 0
- dismantle_cooldown = 0
-
-//argument is so world start can clear out any turf differences quickly.
-/datum/excited_group/proc/self_breakdown(space_is_all_consuming = FALSE)
- var/datum/gas_mixture/A = new
-
- //make local for sanic speed
- var/list/turf_list = src.turf_list
- var/turflen = turf_list.len
- var/space_in_group = FALSE
-
- for(var/t in turf_list)
- var/turf/open/T = t
- if (space_is_all_consuming && !space_in_group && istype(T.air, /datum/gas_mixture/immutable/space))
- space_in_group = TRUE
- qdel(A)
- A = new /datum/gas_mixture/immutable/space()
- break
- A.merge(T.air)
-
- A.multiply(1/turflen)
-
- for(var/t in turf_list)
- var/turf/open/T = t
- T.air.copy_from(A)
- T.atmos_cooldown = 0
- T.update_visuals()
-
- breakdown_cooldown = 0
-
-/datum/excited_group/proc/dismantle()
- for(var/t in turf_list)
- var/turf/open/T = t
- T.excited = FALSE
- T.excited_group = null
- SSair.active_turfs -= T
- garbage_collect()
-
-/datum/excited_group/proc/garbage_collect()
- for(var/t in turf_list)
- var/turf/open/T = t
- T.excited_group = null
- turf_list.Cut()
- SSair.excited_groups -= src
-
////////////////////////SUPERCONDUCTIVITY/////////////////////////////
-/atom/movable/proc/blocksTemperature()
- return FALSE
-
/turf/proc/conductivity_directions()
if(archived_cycle < SSair.times_fired)
archive()
@@ -367,9 +257,6 @@
. |= direction
/turf/proc/neighbor_conduct_with_src(turf/open/other)
- for (var/atom/movable/G in src)
- if (G.blocksTemperature())
- return
if(!other.blocks_air) //Open but neighbor is solid
other.temperature_share_open_to_solid(src)
else //Both tiles are solid
@@ -380,9 +267,7 @@
if(blocks_air)
..()
return
- for (var/atom/movable/G in src)
- if (G.blocksTemperature())
- return
+
if(!other.blocks_air) //Both tiles are open
var/turf/open/T = other
T.air.temperature_share(air, WINDOW_HEAT_TRANSFER_COEFFICIENT)
@@ -401,8 +286,10 @@
if(!neighbor.thermal_conductivity)
continue
+
if(neighbor.archived_cycle < SSair.times_fired)
neighbor.archive()
+
neighbor.neighbor_conduct_with_src(src)
neighbor.consider_superconductivity()
diff --git a/code/modules/atmospherics/machinery/components/binary_devices/dp_vent_pump.dm b/code/modules/atmospherics/machinery/components/binary_devices/dp_vent_pump.dm
index f5c6048b14..d1bb58b99a 100644
--- a/code/modules/atmospherics/machinery/components/binary_devices/dp_vent_pump.dm
+++ b/code/modules/atmospherics/machinery/components/binary_devices/dp_vent_pump.dm
@@ -81,20 +81,17 @@
parent1.update = 1
else //external -> output
- var/pressure_delta = 10000
+ if(environment.return_pressure() > 0)
+ var/our_multiplier = air2.return_volume() / (environment.return_temperature() * R_IDEAL_GAS_EQUATION)
+ var/moles_delta = 10000 * our_multiplier
+ if(pressure_checks&EXT_BOUND)
+ moles_delta = min(moles_delta, (environment_pressure - output_pressure_max) * environment.return_volume() / (environment.return_temperature() * R_IDEAL_GAS_EQUATION))
+ if(pressure_checks&INPUT_MIN)
+ moles_delta = min(moles_delta, (input_pressure_min - air2.return_pressure()) * our_multiplier)
- if(pressure_checks&EXT_BOUND)
- pressure_delta = min(pressure_delta, (environment_pressure - external_pressure_bound))
- if(pressure_checks&INPUT_MIN)
- pressure_delta = min(pressure_delta, (output_pressure_max - air2.return_pressure()))
-
- if(pressure_delta > 0)
- if(environment.return_temperature() > 0)
- var/transfer_moles = pressure_delta*air2.return_volume()/(environment.return_temperature() * R_IDEAL_GAS_EQUATION)
-
- var/datum/gas_mixture/removed = loc.remove_air(transfer_moles)
- //removed can be null if there is no air in the location
- if(!removed)
+ if(moles_delta > 0)
+ var/datum/gas_mixture/removed = loc.remove_air(moles_delta)
+ if (isnull(removed)) // in space
return
air2.merge(removed)
diff --git a/code/modules/atmospherics/machinery/components/unary_devices/vent_pump.dm b/code/modules/atmospherics/machinery/components/unary_devices/vent_pump.dm
index b6534f5cf7..1a86898f1f 100644
--- a/code/modules/atmospherics/machinery/components/unary_devices/vent_pump.dm
+++ b/code/modules/atmospherics/machinery/components/unary_devices/vent_pump.dm
@@ -113,21 +113,21 @@
air_update_turf()
else // external -> internal
- var/pressure_delta = 10000
- if(pressure_checks&EXT_BOUND)
- pressure_delta = min(pressure_delta, (environment_pressure - external_pressure_bound))
- if(pressure_checks&INT_BOUND)
- pressure_delta = min(pressure_delta, (internal_pressure_bound - air_contents.return_pressure()))
+ if(environment.return_pressure() > 0)
+ var/our_multiplier = air_contents.return_volume() / (environment.return_temperature() * R_IDEAL_GAS_EQUATION)
+ var/moles_delta = 10000 * our_multiplier
+ if(pressure_checks&EXT_BOUND)
+ moles_delta = min(moles_delta, (environment_pressure - external_pressure_bound) * environment.return_volume() / (environment.return_temperature() * R_IDEAL_GAS_EQUATION))
+ if(pressure_checks&INT_BOUND)
+ moles_delta = min(moles_delta, (internal_pressure_bound - air_contents.return_pressure()) * our_multiplier)
- if(pressure_delta > 0 && environment.return_temperature() > 0)
- var/transfer_moles = pressure_delta * air_contents.return_volume() / (environment.return_temperature() * R_IDEAL_GAS_EQUATION)
+ if(moles_delta > 0)
+ var/datum/gas_mixture/removed = loc.remove_air(moles_delta)
+ if (isnull(removed)) // in space
+ return
- var/datum/gas_mixture/removed = loc.remove_air(transfer_moles)
- if (isnull(removed)) // in space
- return
-
- air_contents.merge(removed)
- air_update_turf()
+ air_contents.merge(removed)
+ air_update_turf()
update_parents()
//Radio remote control
diff --git a/code/modules/mapping/reader.dm b/code/modules/mapping/reader.dm
index a792ee280f..11bcc0ffcf 100644
--- a/code/modules/mapping/reader.dm
+++ b/code/modules/mapping/reader.dm
@@ -213,6 +213,7 @@
var/list/modelCache = build_cache(no_changeturf)
var/space_key = modelCache[SPACE_KEY]
var/list/bounds
+ var/did_expand = FALSE
src.bounds = bounds = list(1.#INF, 1.#INF, 1.#INF, -1.#INF, -1.#INF, -1.#INF)
var/datum/map_orientation_pattern/mode = forced_pattern || GLOB.map_orientation_patterns["[orientation]"] || GLOB.map_orientation_patterns["[SOUTH]"]
var/invert_y = mode.invert_y
@@ -235,6 +236,7 @@
else
while(parsed_z > world.maxz)
world.incrementMaxZ()
+ did_expand = TRUE
if(!no_changeturf)
WARNING("Z-level expansion occurred without no_changeturf set, this may cause problems when /turf/AfterChange is called")
//these values are the same until a new gridset is reached.
@@ -256,11 +258,13 @@
continue
else
world.maxx = placement_x
+ did_expand = TRUE
if(placement_y > world.maxy)
if(cropMap)
break
else
world.maxy = placement_y
+ did_expand = TRUE
if(placement_x < 1)
actual_x += xi
continue
@@ -301,6 +305,9 @@
testing("Skipped loading [turfsSkipped] default turfs")
#endif
+ if(did_expand)
+ world.refresh_atmos_grid()
+
return TRUE
/datum/parsed_map/proc/build_cache(no_changeturf, bad_paths=null)