3a577221d0
* Adds new debug verb for highlighting roundstart ATs Debug -> Debug Verbs enable then Mapping -> Show roundstart AT markers Will highlight AT turfs, for easier location and comprehension rather than looking at the list of coords. List of coords still works fine though.
385 lines
11 KiB
Plaintext
385 lines
11 KiB
Plaintext
#define SSAIR_PIPENETS 1
|
|
#define SSAIR_ATMOSMACHINERY 2
|
|
#define SSAIR_ACTIVETURFS 3
|
|
#define SSAIR_EXCITEDGROUPS 4
|
|
#define SSAIR_HIGHPRESSURE 5
|
|
#define SSAIR_HOTSPOTS 6
|
|
#define SSAIR_SUPERCONDUCTIVITY 7
|
|
|
|
SUBSYSTEM_DEF(air)
|
|
name = "Air"
|
|
init_order = INIT_ORDER_AIR
|
|
priority = 20
|
|
wait = 5
|
|
flags = SS_BACKGROUND
|
|
|
|
var/cost_turfs = 0
|
|
var/cost_groups = 0
|
|
var/cost_highpressure = 0
|
|
var/cost_hotspots = 0
|
|
var/cost_superconductivity = 0
|
|
var/cost_pipenets = 0
|
|
var/cost_atmos_machinery = 0
|
|
|
|
var/list/excited_groups = list()
|
|
var/list/active_turfs = list()
|
|
var/list/hotspots = list()
|
|
var/list/networks = list()
|
|
var/list/obj/machinery/atmos_machinery = list()
|
|
|
|
|
|
|
|
//Special functions lists
|
|
var/list/turf/active_super_conductivity = list()
|
|
var/list/turf/open/high_pressure_delta = list()
|
|
|
|
|
|
var/list/currentrun = list()
|
|
var/currentpart = SSAIR_PIPENETS
|
|
|
|
var/map_loading = TRUE
|
|
var/list/queued_for_activation
|
|
|
|
/datum/controller/subsystem/air/stat_entry(msg)
|
|
msg += "C:{"
|
|
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 += "AM:[round(cost_atmos_machinery,1)]"
|
|
msg += "} "
|
|
msg += "AT:[active_turfs.len]|"
|
|
msg += "EG:[excited_groups.len]|"
|
|
msg += "HS:[hotspots.len]|"
|
|
msg += "PN:[networks.len]|"
|
|
msg += "HP:[high_pressure_delta.len]|"
|
|
msg += "AS:[active_super_conductivity.len]|"
|
|
msg += "AT/MS:[round((cost ? active_turfs.len/cost : 0),0.1)]"
|
|
..(msg)
|
|
|
|
|
|
/datum/controller/subsystem/air/Initialize(timeofday)
|
|
map_loading = FALSE
|
|
setup_allturfs()
|
|
setup_atmos_machinery()
|
|
setup_pipenets()
|
|
gas_reactions = init_gas_reactions()
|
|
..()
|
|
|
|
|
|
/datum/controller/subsystem/air/fire(resumed = 0)
|
|
var/timer = world.tick_usage
|
|
|
|
if(currentpart == SSAIR_PIPENETS || !resumed)
|
|
process_pipenets(resumed)
|
|
cost_pipenets = MC_AVERAGE(cost_pipenets, TICK_DELTA_TO_MS(world.tick_usage - timer))
|
|
if(state != SS_RUNNING)
|
|
return
|
|
resumed = 0
|
|
currentpart = SSAIR_ATMOSMACHINERY
|
|
|
|
if(currentpart == SSAIR_ATMOSMACHINERY)
|
|
timer = world.tick_usage
|
|
process_atmos_machinery(resumed)
|
|
cost_atmos_machinery = MC_AVERAGE(cost_atmos_machinery, TICK_DELTA_TO_MS(world.tick_usage - timer))
|
|
if(state != SS_RUNNING)
|
|
return
|
|
resumed = 0
|
|
currentpart = SSAIR_ACTIVETURFS
|
|
|
|
if(currentpart == SSAIR_ACTIVETURFS)
|
|
timer = world.tick_usage
|
|
process_active_turfs(resumed)
|
|
cost_turfs = MC_AVERAGE(cost_turfs, TICK_DELTA_TO_MS(world.tick_usage - timer))
|
|
if(state != SS_RUNNING)
|
|
return
|
|
resumed = 0
|
|
currentpart = SSAIR_EXCITEDGROUPS
|
|
|
|
if(currentpart == SSAIR_EXCITEDGROUPS)
|
|
timer = world.tick_usage
|
|
process_excited_groups(resumed)
|
|
cost_groups = MC_AVERAGE(cost_groups, TICK_DELTA_TO_MS(world.tick_usage - timer))
|
|
if(state != SS_RUNNING)
|
|
return
|
|
resumed = 0
|
|
currentpart = SSAIR_HIGHPRESSURE
|
|
|
|
if(currentpart == SSAIR_HIGHPRESSURE)
|
|
timer = world.tick_usage
|
|
process_high_pressure_delta(resumed)
|
|
cost_highpressure = MC_AVERAGE(cost_highpressure, TICK_DELTA_TO_MS(world.tick_usage - timer))
|
|
if(state != SS_RUNNING)
|
|
return
|
|
resumed = 0
|
|
currentpart = SSAIR_HOTSPOTS
|
|
|
|
if(currentpart == SSAIR_HOTSPOTS)
|
|
timer = world.tick_usage
|
|
process_hotspots(resumed)
|
|
cost_hotspots = MC_AVERAGE(cost_hotspots, TICK_DELTA_TO_MS(world.tick_usage - timer))
|
|
if(state != SS_RUNNING)
|
|
return
|
|
resumed = 0
|
|
currentpart = SSAIR_SUPERCONDUCTIVITY
|
|
|
|
if(currentpart == SSAIR_SUPERCONDUCTIVITY)
|
|
timer = world.tick_usage
|
|
process_super_conductivity(resumed)
|
|
cost_superconductivity = MC_AVERAGE(cost_superconductivity, TICK_DELTA_TO_MS(world.tick_usage - timer))
|
|
if(state != SS_RUNNING)
|
|
return
|
|
resumed = 0
|
|
currentpart = SSAIR_PIPENETS
|
|
|
|
|
|
|
|
/datum/controller/subsystem/air/proc/process_pipenets(resumed = 0)
|
|
if (!resumed)
|
|
src.currentrun = networks.Copy()
|
|
//cache for sanic speed (lists are references anyways)
|
|
var/list/currentrun = src.currentrun
|
|
while(currentrun.len)
|
|
var/datum/thing = currentrun[currentrun.len]
|
|
currentrun.len--
|
|
if(thing)
|
|
thing.process()
|
|
else
|
|
networks.Remove(thing)
|
|
if(MC_TICK_CHECK)
|
|
return
|
|
|
|
|
|
/datum/controller/subsystem/air/proc/process_atmos_machinery(resumed = 0)
|
|
var/seconds = wait * 0.1
|
|
if (!resumed)
|
|
src.currentrun = atmos_machinery.Copy()
|
|
//cache for sanic speed (lists are references anyways)
|
|
var/list/currentrun = src.currentrun
|
|
while(currentrun.len)
|
|
var/obj/machinery/M = currentrun[currentrun.len]
|
|
currentrun.len--
|
|
if(!M || (M.process_atmos(seconds) == PROCESS_KILL))
|
|
atmos_machinery.Remove(M)
|
|
if(MC_TICK_CHECK)
|
|
return
|
|
|
|
|
|
/datum/controller/subsystem/air/proc/process_super_conductivity(resumed = 0)
|
|
if (!resumed)
|
|
src.currentrun = active_super_conductivity.Copy()
|
|
//cache for sanic speed (lists are references anyways)
|
|
var/list/currentrun = src.currentrun
|
|
while(currentrun.len)
|
|
var/turf/T = currentrun[currentrun.len]
|
|
currentrun.len--
|
|
T.super_conduct()
|
|
if(MC_TICK_CHECK)
|
|
return
|
|
|
|
/datum/controller/subsystem/air/proc/process_hotspots(resumed = 0)
|
|
if (!resumed)
|
|
src.currentrun = hotspots.Copy()
|
|
//cache for sanic speed (lists are references anyways)
|
|
var/list/currentrun = src.currentrun
|
|
while(currentrun.len)
|
|
var/obj/effect/hotspot/H = currentrun[currentrun.len]
|
|
currentrun.len--
|
|
if (H)
|
|
H.process()
|
|
else
|
|
hotspots -= H
|
|
if(MC_TICK_CHECK)
|
|
return
|
|
|
|
|
|
/datum/controller/subsystem/air/proc/process_high_pressure_delta(resumed = 0)
|
|
while (high_pressure_delta.len)
|
|
var/turf/open/T = high_pressure_delta[high_pressure_delta.len]
|
|
high_pressure_delta.len--
|
|
T.high_pressure_movements()
|
|
T.pressure_difference = 0
|
|
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 (!resumed)
|
|
src.currentrun = excited_groups.Copy()
|
|
//cache for sanic speed (lists are references anyways)
|
|
var/list/currentrun = src.currentrun
|
|
while(currentrun.len)
|
|
var/datum/excited_group/EG = currentrun[currentrun.len]
|
|
currentrun.len--
|
|
EG.breakdown_cooldown++
|
|
EG.dismantle_cooldown++
|
|
if(EG.breakdown_cooldown >= EXCITED_GROUP_BREAKDOWN_CYCLES)
|
|
EG.self_breakdown()
|
|
else if(EG.dismantle_cooldown >= EXCITED_GROUP_DISMANTLE_CYCLES)
|
|
EG.dismantle()
|
|
if (MC_TICK_CHECK)
|
|
return
|
|
|
|
|
|
/datum/controller/subsystem/air/proc/remove_from_active(turf/open/T)
|
|
active_turfs -= 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()
|
|
|
|
/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 = 1
|
|
active_turfs |= T
|
|
if(currentpart == SSAIR_ACTIVETURFS)
|
|
currentrun |= T
|
|
if(blockchanges && T.excited_group)
|
|
T.excited_group.garbage_collect()
|
|
else if(T.initialized)
|
|
for(var/turf/S in T.atmos_adjacent_turfs)
|
|
add_to_active(S)
|
|
else if(map_loading)
|
|
if(queued_for_activation)
|
|
queued_for_activation[T] = T
|
|
return
|
|
else
|
|
T.requires_activation = TRUE
|
|
|
|
/datum/controller/subsystem/air/StartLoadingMap()
|
|
LAZYINITLIST(queued_for_activation)
|
|
map_loading = TRUE
|
|
|
|
/datum/controller/subsystem/air/StopLoadingMap()
|
|
map_loading = FALSE
|
|
for(var/T in queued_for_activation)
|
|
add_to_active(T)
|
|
queued_for_activation.Cut()
|
|
|
|
/datum/controller/subsystem/air/proc/setup_allturfs()
|
|
var/list/turfs_to_init = block(locate(1, 1, 1), locate(world.maxx, world.maxy, world.maxz))
|
|
var/list/active_turfs = src.active_turfs
|
|
var/times_fired = ++src.times_fired
|
|
|
|
for(var/thing in turfs_to_init)
|
|
var/turf/T = thing
|
|
active_turfs -= T
|
|
if (T.blocks_air)
|
|
continue
|
|
T.Initalize_Atmos(times_fired)
|
|
CHECK_TICK
|
|
|
|
if(active_turfs.len)
|
|
var/starting_ats = active_turfs.len
|
|
sleep(world.tick_lag)
|
|
var/timer = world.timeofday
|
|
warning("There are [starting_ats] active turfs at roundstart, this is a mapping error caused by a difference of the air between the adjacent turfs. You can see its coordinates using \"Mapping -> Show roundstart AT list\" verb (debug verbs required)")
|
|
for(var/turf/T in active_turfs)
|
|
GLOB.active_turfs_startlist += T
|
|
|
|
//now lets clear out these active turfs
|
|
var/list/turfs_to_check = active_turfs.Copy()
|
|
do
|
|
var/list/new_turfs_to_check = list()
|
|
for(var/turf/open/T in turfs_to_check)
|
|
new_turfs_to_check += T.resolve_active_graph()
|
|
CHECK_TICK
|
|
|
|
active_turfs += new_turfs_to_check
|
|
turfs_to_check = new_turfs_to_check
|
|
|
|
while (turfs_to_check.len)
|
|
var/ending_ats = active_turfs.len
|
|
for(var/thing in excited_groups)
|
|
var/datum/excited_group/EG = thing
|
|
EG.self_breakdown(space_is_all_consuming = 1)
|
|
EG.dismantle()
|
|
CHECK_TICK
|
|
|
|
var/msg = "HEY! LISTEN! [(world.timeofday - timer)/10] Seconds were wasted processing [starting_ats] turf(s) (connected to [ending_ats] other turfs) with atmos differences at round start."
|
|
to_chat(world, "<span class='boldannounce'>[msg]</span>")
|
|
warning(msg)
|
|
|
|
/turf/open/proc/resolve_active_graph()
|
|
. = list()
|
|
var/datum/excited_group/EG = excited_group
|
|
if (blocks_air || !air)
|
|
return
|
|
if (!EG)
|
|
EG = new
|
|
EG.add_turf(src)
|
|
|
|
for (var/turf/open/ET in atmos_adjacent_turfs)
|
|
if ( ET.blocks_air || !ET.air)
|
|
continue
|
|
|
|
var/ET_EG = ET.excited_group
|
|
if (ET_EG)
|
|
if (ET_EG != EG)
|
|
EG.merge_groups(ET_EG)
|
|
EG = excited_group //merge_groups() may decide to replace our current EG
|
|
else
|
|
EG.add_turf(ET)
|
|
if (!ET.excited)
|
|
ET.excited = 1
|
|
. += ET
|
|
/turf/open/space/resolve_active_graph()
|
|
return list()
|
|
|
|
/datum/controller/subsystem/air/proc/setup_atmos_machinery()
|
|
for (var/obj/machinery/atmospherics/AM in atmos_machinery)
|
|
AM.atmosinit()
|
|
CHECK_TICK
|
|
|
|
//this can't be done with setup_atmos_machinery() because
|
|
// all atmos machinery has to initalize before the first
|
|
// pipenet can be built.
|
|
/datum/controller/subsystem/air/proc/setup_pipenets()
|
|
for (var/obj/machinery/atmospherics/AM in atmos_machinery)
|
|
AM.build_network()
|
|
CHECK_TICK
|
|
|
|
/datum/controller/subsystem/air/proc/setup_template_machinery(list/atmos_machines)
|
|
for(var/A in atmos_machines)
|
|
var/obj/machinery/atmospherics/AM = A
|
|
AM.atmosinit()
|
|
CHECK_TICK
|
|
|
|
for(var/A in atmos_machines)
|
|
var/obj/machinery/atmospherics/AM = A
|
|
AM.build_network()
|
|
CHECK_TICK
|
|
|
|
|
|
#undef SSAIR_PIPENETS
|
|
#undef SSAIR_ATMOSMACHINERY
|
|
#undef SSAIR_ACTIVETURFS
|
|
#undef SSAIR_EXCITEDGROUPS
|
|
#undef SSAIR_HIGHPRESSURE
|
|
#undef SSAIR_HOTSPOT
|
|
#undef SSAIR_SUPERCONDUCTIVITY
|