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)