Merge pull request #9231 from MrStonedOne/step-aside-aran-im-here-to-touch-your-precious

Massive MC and subsystem rewrite
This commit is contained in:
Jordie
2015-05-02 23:58:17 +10:00
114 changed files with 1043 additions and 755 deletions
+17 -3
View File
@@ -20,9 +20,7 @@ Pipelines + Other Objects -> Pipe network
var/initialize_directions = 0
var/pipe_color
var/obj/item/pipe/stored
var/welded = 0 //Used on pumps and scrubbers
var/global/list/iconsetids = list()
var/global/list/pipeimages = list()
@@ -36,11 +34,27 @@ Pipelines + Other Objects -> Pipe network
/obj/machinery/atmospherics/New()
..()
SSair.atmos_machinery += src
SetInitDirections()
if(can_unwrench)
stored = new(src, make_from=src)
/obj/machinery/atmospherics/Destroy()
SSair.atmos_machinery -= src
if (stored)
qdel(stored)
stored = null
..()
//this is called just after the air controller sets up turfs
/obj/machinery/atmospherics/proc/atmosinit()
return
//object initializion. done well after air is setup (build_network needs all pipes to be init'ed with atmosinit before hand)
/obj/machinery/atmospherics/initialize()
..()
build_network() //make sure to build our pipe nets
/obj/machinery/atmospherics/proc/SetInitDirections()
return
@@ -74,7 +74,7 @@
nullifyPipenet(parent2)
..()
/obj/machinery/atmospherics/binary/initialize()
/obj/machinery/atmospherics/binary/atmosinit()
var/node2_connect = dir
var/node1_connect = turn(dir, 180)
@@ -93,6 +93,7 @@
showpipe = 1
update_icon()
..()
/obj/machinery/atmospherics/binary/construction()
..()
@@ -50,7 +50,7 @@
else
last_pressure_delta = 0
/obj/machinery/atmospherics/binary/circulator/process()
/obj/machinery/atmospherics/binary/circulator/process_atmos()
..()
update_icon()
@@ -53,7 +53,7 @@
else
icon_state = "vent_in"
/obj/machinery/atmospherics/binary/dp_vent_pump/process()
/obj/machinery/atmospherics/binary/dp_vent_pump/process_atmos()
..()
if(!on)
@@ -133,11 +133,15 @@
return 1
/obj/machinery/atmospherics/binary/dp_vent_pump/initialize()
/obj/machinery/atmospherics/binary/dp_vent_pump/atmosinit()
..()
if(frequency)
set_frequency(frequency)
/obj/machinery/atmospherics/binary/dp_vent_pump/initialize()
..()
broadcast_status()
/obj/machinery/atmospherics/binary/dp_vent_pump/receive_signal(datum/signal/signal)
if(!signal.data["tag"] || (signal.data["tag"] != id) || (signal.data["sigtype"]!="command"))
@@ -32,7 +32,7 @@ Passive gate is similar to the regular pump except:
if(on & !(stat & NOPOWER))
overlays += getpipeimage('icons/obj/atmospherics/binary_devices.dmi', "passgate_on")
/obj/machinery/atmospherics/binary/passive_gate/process()
/obj/machinery/atmospherics/binary/passive_gate/process_atmos()
..()
if(!on)
return 0
@@ -108,7 +108,7 @@ Passive gate is similar to the regular pump except:
else
ui.push_data(data)
/obj/machinery/atmospherics/binary/passive_gate/initialize()
/obj/machinery/atmospherics/binary/passive_gate/atmosinit()
..()
if(frequency)
set_frequency(frequency)
@@ -41,7 +41,7 @@ Thus, the two variables affect pump operation are set in New():
icon_state = "pump_[on?"on":"off"]"
/obj/machinery/atmospherics/binary/pump/process()
/obj/machinery/atmospherics/binary/pump/process_atmos()
// ..()
if(stat & (NOPOWER|BROKEN))
return 0
@@ -116,7 +116,7 @@ Thus, the two variables affect pump operation are set in New():
else
ui.push_data(data)
/obj/machinery/atmospherics/binary/pump/initialize()
/obj/machinery/atmospherics/binary/pump/atmosinit()
..()
if(frequency)
set_frequency(frequency)
@@ -41,7 +41,7 @@ Thus, the two variables affect pump operation are set in New():
icon_state = "volpump_[on?"on":"off"]"
/obj/machinery/atmospherics/binary/volume_pump/process()
/obj/machinery/atmospherics/binary/volume_pump/process_atmos()
// ..()
if(stat & (NOPOWER|BROKEN))
return
@@ -112,7 +112,7 @@ Thus, the two variables affect pump operation are set in New():
else
ui.push_data(data)
/obj/machinery/atmospherics/binary/volume_pump/initialize()
/obj/machinery/atmospherics/binary/volume_pump/atmosinit()
..()
set_frequency(frequency)
@@ -24,7 +24,7 @@
state = "pipe_exposed"
underlays += getpipeimage('icons/obj/atmospherics/binary_devices.dmi', state, initialize_directions, col)
/obj/machinery/atmospherics/unary/portables_connector/process()
/obj/machinery/atmospherics/unary/portables_connector/process_atmos()
if(!connected_device)
return
parent.update = 1
@@ -69,7 +69,7 @@ Filter types:
if(old_stat != stat)
update_icon()
/obj/machinery/atmospherics/trinary/filter/process()
/obj/machinery/atmospherics/trinary/filter/process_atmos()
..()
if(!on)
return 0
@@ -143,7 +143,7 @@ Filter types:
return 1
/obj/machinery/atmospherics/trinary/filter/initialize()
/obj/machinery/atmospherics/trinary/filter/atmosinit()
set_frequency(frequency)
return ..()
@@ -216,4 +216,4 @@ Filter types:
if ((M.client && M.machine == src))
src.attack_hand(M)
*/
return
return
@@ -40,7 +40,7 @@
..()
air3.volume = 300
/obj/machinery/atmospherics/trinary/mixer/process()
/obj/machinery/atmospherics/trinary/mixer/process_atmos()
..()
if(!on)
return 0
@@ -94,7 +94,7 @@ Housekeeping and pipe network stuff below
nullifyPipenet(parent3)
..()
/obj/machinery/atmospherics/trinary/initialize()
/obj/machinery/atmospherics/trinary/atmosinit()
//Mixer:
//1 and 2 is input
@@ -131,6 +131,7 @@ Housekeeping and pipe network stuff below
break
update_icon()
..()
/obj/machinery/atmospherics/trinary/construction()
..()
@@ -22,7 +22,7 @@
return
/obj/machinery/atmospherics/unary/cold_sink/process()
/obj/machinery/atmospherics/unary/cold_sink/process_atmos()
..()
if(!on)
return 0
@@ -20,7 +20,7 @@
return
/obj/machinery/atmospherics/unary/heat_exchanger/initialize()
/obj/machinery/atmospherics/unary/heat_exchanger/atmosinit()
if(!partner)
var/partner_connect = turn(dir,180)
@@ -32,7 +32,7 @@
..()
/obj/machinery/atmospherics/unary/heat_exchanger/process()
/obj/machinery/atmospherics/unary/heat_exchanger/process_atmos()
..()
if(!partner)
return 0
@@ -24,7 +24,7 @@
return
/obj/machinery/atmospherics/unary/heat_reservoir/process()
/obj/machinery/atmospherics/unary/heat_reservoir/process_atmos()
..()
if(!on)
return 0
@@ -38,7 +38,7 @@
update_icon()
/obj/machinery/atmospherics/unary/outlet_injector/process()
/obj/machinery/atmospherics/unary/outlet_injector/process_atmos()
..()
injecting = 0
@@ -101,12 +101,14 @@
return 1
/obj/machinery/atmospherics/unary/outlet_injector/initialize()
/obj/machinery/atmospherics/unary/outlet_injector/atmosinit()
set_frequency(frequency)
..()
set_frequency(frequency)
spawn(rand(25,50))
broadcast_status()
/obj/machinery/atmospherics/unary/outlet_injector/initialize()
..()
broadcast_status()
/obj/machinery/atmospherics/unary/outlet_injector/receive_signal(datum/signal/signal)
if(!signal.data["tag"] || (signal.data["tag"] != id) || (signal.data["sigtype"]!="command"))
@@ -28,7 +28,7 @@
air_contents.volume = 50
/obj/machinery/atmospherics/unary/oxygen_generator/process()
/obj/machinery/atmospherics/unary/oxygen_generator/process_atmos()
..()
if(!on)
return 0
@@ -60,7 +60,7 @@ Housekeeping and pipe network stuff below
..()
/obj/machinery/atmospherics/unary/initialize()
/obj/machinery/atmospherics/unary/atmosinit()
for(var/obj/machinery/atmospherics/target in get_step(src, dir))
if(target.initialize_directions & get_dir(target,src))
node = target
@@ -68,6 +68,7 @@ Housekeeping and pipe network stuff below
if(level == 2)
showpipe = 1
update_icon()
..()
/obj/machinery/atmospherics/unary/construction()
..()
@@ -84,7 +84,7 @@
else
icon_state = "vent_in"
/obj/machinery/atmospherics/unary/vent_pump/process()
/obj/machinery/atmospherics/unary/vent_pump/process_atmos()
..()
if(stat & (NOPOWER|BROKEN))
return
@@ -181,14 +181,16 @@
return 1
/obj/machinery/atmospherics/unary/vent_pump/initialize()
..()
/obj/machinery/atmospherics/unary/vent_pump/atmosinit()
//some vents work his own spesial way
radio_filter_in = frequency==1439?(RADIO_FROM_AIRALARM):null
radio_filter_out = frequency==1439?(RADIO_TO_AIRALARM):null
if(frequency)
set_frequency(frequency)
..()
/obj/machinery/atmospherics/unary/vent_pump/initialize()
..()
broadcast_status()
/obj/machinery/atmospherics/unary/vent_pump/receive_signal(datum/signal/signal)
if(stat & (NOPOWER|BROKEN))
@@ -98,14 +98,18 @@
return 1
/obj/machinery/atmospherics/unary/vent_scrubber/initialize()
..()
/obj/machinery/atmospherics/unary/vent_scrubber/atmosinit()
radio_filter_in = frequency==initial(frequency)?(RADIO_FROM_AIRALARM):null
radio_filter_out = frequency==initial(frequency)?(RADIO_TO_AIRALARM):null
if (frequency)
set_frequency(frequency)
..()
/obj/machinery/atmospherics/unary/vent_scrubber/initialize()
..()
broadcast_status()
/obj/machinery/atmospherics/unary/vent_scrubber/process()
/obj/machinery/atmospherics/unary/vent_scrubber/process_atmos()
..()
if(stat & (NOPOWER|BROKEN))
return
+2 -1
View File
@@ -38,6 +38,7 @@
update_icon_nopipes()
parent1.update = 0
parent2.update = 0
parent1.reconcile_air()
investigate_log("was opened by [usr ? key_name(usr) : "a remote signal"]", "atmos")
return
@@ -64,7 +65,7 @@
close()
else
open()
parent1.reconcile_air()
/obj/machinery/atmospherics/binary/valve/digital // can be controlled by AI
name = "digital valve"
+4 -3
View File
@@ -10,10 +10,10 @@
var/alert_pressure = 0
/datum/pipeline/New()
SSpipe.networks += src
SSair.networks += src
/datum/pipeline/Destroy()
SSpipe.networks -= src
SSair.networks -= src
if(air && air.volume)
temporarily_store_air()
for(var/obj/machinery/atmospherics/pipe/P in members)
@@ -22,10 +22,11 @@
A.nullifyPipenet(src)
..()
/datum/pipeline/process()//This use to be called called from the pipe networks
/datum/pipeline/process()
if(update)
update = 0
reconcile_air()
return
/*
//Check to see if pressure is within acceptable limits
+10 -6
View File
@@ -36,7 +36,7 @@
if(SOUTHWEST)
initialize_directions_he = SOUTH|WEST
/obj/machinery/atmospherics/pipe/simple/heat_exchanging/initialize()
/obj/machinery/atmospherics/pipe/simple/heat_exchanging/atmosinit()
normalize_dir()
var/N = 2
for(var/D in cardinal)
@@ -51,8 +51,9 @@
node2 = target
break
update_icon()
..()
/obj/machinery/atmospherics/pipe/simple/heat_exchanging/process()
/obj/machinery/atmospherics/pipe/simple/heat_exchanging/process_atmos()
var/environment_temperature = 0
var/datum/gas_mixture/pipe_air = return_air()
@@ -69,15 +70,18 @@
parent.temperature_interact(loc, volume, thermal_conductivity)
//Burn any mobs buckled to ourselves based on our temperature
//heatup/cooldown any mobs buckled to ourselves based on our temperature
if(buckled_mob)
var/hc = pipe_air.heat_capacity()
var/avg_temp = (pipe_air.temperature * hc + buckled_mob.bodytemperature * 3500) / (hc + 3500)
pipe_air.temperature = avg_temp
buckled_mob.bodytemperature = avg_temp
/obj/machinery/atmospherics/pipe/simple/heat_exchanging/process()
var/datum/gas_mixture/pipe_air = return_air()
//Burn any mobs buckled to ourselves based on our temperature
if(buckled_mob)
var/heat_limit = 1000
if(pipe_air.temperature > heat_limit + 1)
buckled_mob.apply_damage(4 * log(pipe_air.temperature - heat_limit), BURN, "chest")
@@ -131,7 +135,7 @@
var/have_node2 = node2?1:0
icon_state = "exposed[have_node1][have_node2]"
/obj/machinery/atmospherics/pipe/simple/heat_exchanging/junction/initialize()
/obj/machinery/atmospherics/pipe/simple/heat_exchanging/junction/atmosinit()
for(var/obj/machinery/atmospherics/target in get_step(src,initialize_directions))
if(target.initialize_directions & get_dir(target,src))
node1 = target
@@ -141,4 +145,4 @@
node2 = target
break
update_icon()
return
..()
+2 -1
View File
@@ -38,7 +38,7 @@
if(WEST)
initialize_directions = NORTH|EAST|SOUTH
/obj/machinery/atmospherics/pipe/manifold/initialize()
/obj/machinery/atmospherics/pipe/manifold/atmosinit()
for(var/D in cardinal)
if(D == dir)
continue
@@ -54,6 +54,7 @@
var/turf/T = src.loc // hide if turf is not intact
hide(T.intact)
update_icon()
..()
/obj/machinery/atmospherics/pipe/manifold/Destroy()
if(node1)
+2 -1
View File
@@ -28,7 +28,7 @@
/obj/machinery/atmospherics/pipe/manifold4w/SetInitDirections()
return
/obj/machinery/atmospherics/pipe/manifold4w/initialize()
/obj/machinery/atmospherics/pipe/manifold4w/atmosinit()
for(var/D in cardinal)
for(var/obj/machinery/atmospherics/target in get_step(src, D))
if(target.initialize_directions & get_dir(target,src))
@@ -45,6 +45,7 @@
var/turf/T = src.loc // hide if turf is not intact
hide(T.intact)
update_icon()
..()
/obj/machinery/atmospherics/pipe/manifold4w/hide(var/i)
if(level == 1 && istype(loc, /turf/simulated))
+2 -1
View File
@@ -53,7 +53,7 @@ The regular pipe you see everywhere, including bent ones.
if(SOUTHWEST)
initialize_directions = SOUTH|WEST
/obj/machinery/atmospherics/pipe/simple/initialize()
/obj/machinery/atmospherics/pipe/simple/atmosinit()
normalize_dir()
var/N = 2
for(var/D in cardinal)
@@ -70,6 +70,7 @@ The regular pipe you see everywhere, including bent ones.
var/turf/T = loc // hide if turf is not intact
hide(T.intact)
update_icon()
..()
/obj/machinery/atmospherics/pipe/simple/Destroy()
if(node1)
View File
+5 -4
View File
@@ -30,7 +30,7 @@
if(air_contents.oxygen < 0.5 || air_contents.toxins < 0.5)
return 0
active_hotspot = new(src)
active_hotspot = PoolOrNew(/obj/effect/hotspot, src)
active_hotspot.temperature = exposed_temperature
active_hotspot.volume = exposed_volume
@@ -142,16 +142,17 @@
// Garbage collect itself by nulling reference to it
/obj/effect/hotspot/proc/Kill()
SSair.hotspots -= src
DestroyTurf()
qdel(src)
PlaceInPool(src)
/obj/effect/hotspot/Destroy()
SSair.hotspots -= src
DestroyTurf()
if(istype(loc, /turf/simulated))
var/turf/simulated/T = loc
if(T.active_hotspot == src)
T.active_hotspot = null
loc = null
return QDEL_HINT_PUTINPOOL
/obj/effect/hotspot/proc/DestroyTurf()
+3 -3
View File
@@ -66,7 +66,7 @@ turf/simulated/New()
turf/simulated/Del()
if(active_hotspot)
qdel(active_hotspot)
active_hotspot.Kill()
..()
turf/simulated/assume_air(datum/gas_mixture/giver)
@@ -274,11 +274,11 @@ atom/movable/var/pressure_resistance = 5
atom/movable/var/last_forced_movement = 0
atom/movable/proc/experience_pressure_difference(pressure_difference, direction)
if(last_forced_movement >= SSair.times_fired)
if(last_forced_movement >= world.time-10)
return 0
else if(!anchored)
if(pressure_difference > pressure_resistance)
last_forced_movement = SSair.times_fired
last_forced_movement = world.time
spawn step(src, direction)
return 1
+10
View File
@@ -0,0 +1,10 @@
//defines that give qdel hints. these can be given as a return in destory() or by calling
#define QDEL_HINT_QUEUE 0 //qdel should queue the object for deletion.
#define QDEL_HINT_LETMELIVE 1 //qdel should let the object live after calling destory.
#define QDEL_HINT_IWILLGC 2 //functionally the same as the above. qdel should assume the object will gc on its own, and not check it.
#define QDEL_HINT_HARDDEL 3 //qdel should assume this object won't gc, and queue a hard delete using a hard reference.
#define QDEL_HINT_HARDDEL_NOW 4 //qdel should assume this object won't gc, and hard del it post haste.
#define QDEL_HINT_PUTINPOOL 5 //qdel will put this object in the atom pool.
+1 -2
View File
@@ -200,5 +200,4 @@ Reharging stations are available in robotics, the dormitory's bathrooms. and the
return usr.client.Click(master, location, control, params)
/obj/screen/alert/Destroy()
PlaceInPool(src)
return 1 // Don't destroy me, I have a family!
return QDEL_HINT_PUTINPOOL //Don't destroy me, I have a family!
+23 -12
View File
@@ -23,22 +23,31 @@ var/global/datum/controller/game_controller/master_controller = new()
init_subtypes(/datum/subsystem, subsystems)
master_controller = src
calculateGCD()
/*
calculate the longest number of ticks the MC can wait between each cycle without causing subsystems to not fire on schedule
Note: you can set the datum's defined processing_interval to some integer to set an -absolute- minimum wait duration.
*/
/datum/controller/game_controller/proc/calculateGCD()
var/GCD
for(var/datum/subsystem/SS in subsystems)
if(SS.wait)
GCD = Gcd(SS.wait, GCD)
GCD = Gcd(round(SS.wait*10), GCD)
GCD = round(GCD)
if(GCD > processing_interval)
processing_interval = GCD
if(GCD < world.tick_lag*10)
GCD = world.tick_lag*10
processing_interval = GCD/10
/datum/controller/game_controller/proc/setup()
/datum/controller/game_controller/proc/setup(zlevel)
if (zlevel && zlevel > 0 && zlevel <= world.maxz)
for(var/datum/subsystem/S in subsystems)
S.Initialize(world.timeofday, zlevel)
sleep(-1)
return
world << "<span class='boldannounce'>Initializing Subsystems...</span>"
//sort subsystems by priority, so they initialize in the correct order
sortTim(subsystems, /proc/cmp_subsystem_priority)
@@ -49,7 +58,7 @@ Note: you can set the datum's defined processing_interval to some integer to set
//Eventually all this other setup stuff should be contained in subsystems and done in subsystem.Initialize()
for(var/datum/subsystem/S in subsystems)
S.Initialize(world.timeofday)
S.Initialize(world.timeofday, zlevel)
sleep(-1)
world << "<span class='boldannounce'>Initializations complete</span>"
@@ -74,7 +83,6 @@ Note: you can set the datum's defined processing_interval to some integer to set
SS.next_fire = timer
var/start_time
var/cpu
while(1) //far more efficient than recursively calling ourself
if(processing_interval > 0)
@@ -85,16 +93,19 @@ Note: you can set the datum's defined processing_interval to some integer to set
for(var/datum/subsystem/SS in subsystems)
if(SS.can_fire > 0)
if(SS.next_fire <= world.time)
SS.next_fire += SS.wait
timer = world.timeofday
cpu = world.cpu
last_thing_processed = SS.type
SS.last_fire = world.time
SS.fire()
SS.cpu = MC_AVERAGE(SS.cpu, world.cpu - cpu)
SS.cost = MC_AVERAGE(SS.cost, world.timeofday - timer)
if (SS.dynamic_wait)
var/oldwait = SS.wait
SS.wait = min(max(round(SS.cost*SS.dwait_delta, 0.1),SS.dwait_lower),SS.dwait_upper)
if (oldwait != SS.wait)
calculateGCD()
SS.next_fire += SS.wait
++SS.times_fired
sleep(-1)
cost = MC_AVERAGE(cost, world.timeofday - start_time)
@@ -108,7 +119,7 @@ Note: you can set the datum's defined processing_interval to some integer to set
/datum/controller/game_controller/proc/roundHasStarted()
for(var/datum/subsystem/SS in subsystems)
SS.can_fire = 1
SS.next_fire = world.time
SS.next_fire = world.time + rand(0,SS.wait)
/datum/controller/game_controller/proc/Recover()
var/msg = "## DEBUG: [time2text(world.timeofday)] MC restarted. Reports:\n"
+81 -12
View File
@@ -3,12 +3,19 @@ var/datum/subsystem/air/SSair
/datum/subsystem/air
name = "Air"
priority = 20
cost = 5
wait = 5
dynamic_wait = 1
dwait_lower = 5
dwait_upper = 50
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/obj/effect/overlay/plasma_overlay //overlay for plasma
var/obj/effect/overlay/sleeptoxin_overlay //overlay for sleeptoxin
@@ -16,6 +23,9 @@ var/datum/subsystem/air/SSair
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/simulated/active_super_conductivity = list()
@@ -28,14 +38,39 @@ var/datum/subsystem/air/SSair
plasma_overlay = new /obj/effect/overlay{icon='icons/effects/tile_effects.dmi';mouse_opacity=0;layer=5;icon_state="plasma"}()
sleeptoxin_overlay = new /obj/effect/overlay{icon='icons/effects/tile_effects.dmi';mouse_opacity=0;layer=5;icon_state="sleeping_agent"}()
/datum/subsystem/air/stat_entry(msg)
msg += "C:{"
msg += "AT:[round(cost_turfs,0.01)]|"
msg += "EG:[round(cost_groups,0.01)]|"
msg += "HP:[round(cost_highpressure,0.01)]|"
msg += "HS:[round(cost_hotspots,0.01)]|"
msg += "SC:[round(cost_superconductivity,0.01)]|"
msg += "PN:[round(cost_pipenets,0.01)]|"
msg += "AM:[round(cost_atmos_machinery,0.01)]"
msg += "} "
msg += "AT:[active_turfs.len]|"
msg += "EG:[excited_groups.len]|"
msg += "HS:[hotspots.len]|"
msg += "AS:[active_super_conductivity.len]"
..(msg)
/datum/subsystem/air/Initialize()
setup_allturfs()
/datum/subsystem/air/Initialize(timeofday, zlevel)
setup_allturfs(zlevel)
setup_atmos_machinery(zlevel)
..()
#define MC_AVERAGE(average, current) (0.8*(average) + 0.2*(current))
/datum/subsystem/air/fire()
var/timer = world.timeofday
process_pipenets()
cost_pipenets = MC_AVERAGE(cost_pipenets, (world.timeofday - timer))
timer = world.timeofday
process_atmos_machinery()
cost_atmos_machinery = MC_AVERAGE(cost_atmos_machinery, (world.timeofday - timer))
timer = world.timeofday
process_active_turfs()
cost_turfs = MC_AVERAGE(cost_turfs, (world.timeofday - timer))
@@ -55,9 +90,29 @@ var/datum/subsystem/air/SSair
process_super_conductivity()
cost_superconductivity = MC_AVERAGE(cost_superconductivity, (world.timeofday - timer))
#undef MC_AVERAGE
/datum/subsystem/air/proc/process_pipenets()
var/i=1
for(var/thing in networks)
if(thing)
thing:process()
++i
continue
networks.Cut(i, i+1)
/datum/subsystem/air/proc/process_atmos_machinery()
var/seconds = wait * 0.1
for(var/obj/machinery/M in atmos_machinery)
if(M && (M.process_atmos(seconds) != PROCESS_KILL))
continue
atmos_machinery.Remove(M)
/datum/subsystem/air/proc/process_super_conductivity()
for(var/turf/simulated/T in active_super_conductivity)
T.super_conduct()
@@ -102,9 +157,26 @@ var/datum/subsystem/air/SSair
if(istype(S))
add_to_active(S)
/datum/subsystem/air/proc/process_excited_groups()
for(var/datum/excited_group/EG in excited_groups)
EG.breakdown_cooldown ++
if(EG.breakdown_cooldown == 10)
EG.self_breakdown()
return
if(EG.breakdown_cooldown > 20)
EG.dismantle()
/datum/subsystem/air/proc/setup_allturfs()
for(var/turf/simulated/T in world)
/datum/subsystem/air/proc/setup_allturfs(z_level)
var/z_start = 1
var/z_finish = world.maxz
if(1 <= z_level && z_level <= world.maxz)
z_level = round(z_level)
z_start = z_level
z_finish = z_level
var/list/turfs_to_init = block(locate(1, 1, z_start), locate(world.maxx, world.maxy, z_finish))
for(var/turf/simulated/T in turfs_to_init)
T.CalculateAdjacentTurfs()
if(!T.blocks_air)
if(T.air.check_tile_graphic())
@@ -124,11 +196,8 @@ var/datum/subsystem/air/SSair
T.excited = 1
active_turfs |= T
/datum/subsystem/air/proc/process_excited_groups()
for(var/datum/excited_group/EG in excited_groups)
EG.breakdown_cooldown ++
if(EG.breakdown_cooldown == 10)
EG.self_breakdown()
return
if(EG.breakdown_cooldown > 20)
EG.dismantle()
/datum/subsystem/air/proc/setup_atmos_machinery(z_level)
for (var/obj/machinery/atmospherics/AM in atmos_machinery)
if (z_level && AM.z != z_level)
continue
AM.atmosinit()
+3
View File
@@ -9,6 +9,9 @@ var/datum/subsystem/bots/SSbot
/datum/subsystem/bots/New()
NEW_SS_GLOBAL(SSbot)
/datum/subsystem/bots/stat_entry(msg)
..("P:[processing.len]")
/datum/subsystem/bots/fire()
var/seconds = wait * 0.1
var/i=1
+2
View File
@@ -9,6 +9,8 @@ var/datum/subsystem/diseases/SSdisease
/datum/subsystem/diseases/New()
NEW_SS_GLOBAL(SSdisease)
/datum/subsystem/diseases/stat_entry(msg)
..("P:[processing.len]")
/datum/subsystem/diseases/fire()
var/i=1
+3 -1
View File
@@ -19,7 +19,9 @@ var/datum/subsystem/events/SSevent
NEW_SS_GLOBAL(SSevent)
/datum/subsystem/events/Initialize()
/datum/subsystem/events/Initialize(time, zlevel)
if (zlevel)
return ..()
for(var/type in typesof(/datum/round_event_control))
var/datum/round_event_control/E = new type()
if(!E.typepath)
+87 -44
View File
@@ -3,79 +3,122 @@ var/datum/subsystem/garbage_collector/SSgarbage
/datum/subsystem/garbage_collector
name = "Garbage"
can_fire = 1
wait = 60
priority = 21
wait = 5
priority = -1
var/collection_timeout = 300 //deciseconds to wait to let running procs finish before we just say fuck it and force del() the object
var/max_checks_multiplier = 5 //multiplier (per-decisecond) for calculating max number of tests per SS tick. These tests check if our GC'd objects are actually GC'd
var/max_forcedel_multiplier = 1 //multiplier (per-decisecond) for calculating max number of force del() calls per SS tick.
var/collection_timeout = 300// deciseconds to wait to let running procs finish before we just say fuck it and force del() the object
var/max_run_time = 2 // how long, in deciseconds, can we run before waiting for the next tick
var/delslasttick = 0 // number of del()'s we've done this tick
var/gcedlasttick = 0 // number of things that gc'ed last tick
var/totaldels = 0
var/totalgcs = 0
var/dels = 0 // number of del()'s we've done this tick
var/list/destroyed = list() // list of refID's of things that should be garbage collected
var/list/queue = list() // list of refID's of things that should be garbage collected
// refID's are associated with the time at which they time out and need to be manually del()
// we do this so we aren't constantly locating them and preventing them from being gc'd
var/list/logging = list() // list of all types that have failed to GC associated with the number of times that's happened.
var/list/didntgc = list() // list of all types that have failed to GC associated with the number of times that's happened.
// the types are stored as strings
/datum/subsystem/garbage_collector/New()
NEW_SS_GLOBAL(SSgarbage)
/datum/subsystem/garbage_collector/stat_entry(msg)
msg += "Q:[queue.len]|D:[delslasttick]|G:[gcedlasttick]|"
msg += "GR:"
if (!(delslasttick+gcedlasttick))
msg += "n/a|"
else
msg += "[round((gcedlasttick/(delslasttick+gcedlasttick))*100, 0.01)]%|"
msg += "TD:[totaldels]|TG:[totalgcs]|"
if (!(totaldels+totalgcs))
msg += "n/a|"
else
msg += "TGR:[round((totalgcs/(totaldels+totalgcs))*100, 0.01)]%"
..(msg)
/datum/subsystem/garbage_collector/fire()
dels = 0
delslasttick = 0
gcedlasttick = 0
var/time_to_stop = world.timeofday + max_run_time
var/time_to_kill = world.time - collection_timeout // Anything qdel() but not GC'd BEFORE this time needs to be manually del()
var/checkRemain = max_checks_multiplier * wait
var/maxDels = max_forcedel_multiplier * wait
while(destroyed.len && --checkRemain >= 0)
if(dels >= maxDels)
// testing("GC: Reached max force dels per tick [dels] vs [GC_FORCE_DEL_PER_TICK]")
break // Server's already pretty pounded, everything else can wait 2 seconds
var/refID = destroyed[1]
var/GCd_at_time = destroyed[refID]
while(queue.len && world.timeofday < time_to_stop)
var/refID = queue[1]
if (!refID)
queue.Cut(1, 2)
continue
var/GCd_at_time = queue[refID]
if(GCd_at_time > time_to_kill)
// testing("GC: [refID] not old enough, breaking at [world.time] for [GCd_at_time - time_to_kill] deciseconds until [GCd_at_time + GC_COLLECTION_TIMEOUT]")
break // Everything else is newer, skip them
var/atom/A = locate(refID)
// testing("GC: [refID] old enough to test: GCd_at_time: [GCd_at_time] time_to_kill: [time_to_kill] current: [world.time]")
if(A && A.gc_destroyed == GCd_at_time) // So if something else coincidently gets the same ref, it's not deleted by mistake
// Something's still referring to the qdel'd object. Kill it.
testing("GC: -- \ref[A] | [A.type] was unable to be GC'd and was deleted --")
logging["[A.type]"]++
var/atom/A
if (!istext(refID))
del(A)
++dels
// else
// testing("GC: [refID] properly GC'd at [world.time] with timeout [GCd_at_time]")
destroyed.Cut(1, 2)
else
A = locate(refID)
if (A && A.gc_destroyed == GCd_at_time) // So if something else coincidently gets the same ref, it's not deleted by mistake
// Something's still referring to the qdel'd object. Kill it.
testing("GC: -- \ref[A] | [A.type] was unable to be GC'd and was deleted --")
didntgc["[A.type]"]++
del(A)
++delslasttick
++totaldels
else
++gcedlasttick
++totalgcs
queue.Cut(1, 2)
/datum/subsystem/garbage_collector/proc/AddTrash(datum/A)
if(!istype(A) || !isnull(A.gc_destroyed))
/datum/subsystem/garbage_collector/proc/Queue(datum/A, harddel = 0)
if (!istype(A) || !isnull(A.gc_destroyed))
return
// testing("GC: AddTrash([A.type])")
A.gc_destroyed = world.time
destroyed -= "\ref[A]" // Removing any previous references that were GC'd so that the current object will be at the end of the list.
destroyed["\ref[A]"] = world.time
queue -= "\ref[A]" // Removing any previous references that were GC'd so that the current object will be at the end of the list.
queue["\ref[A]"] = world.time
/datum/subsystem/garbage_collector/proc/HardQueue(datum/A, harddel = 0)
if (!istype(A) || !isnull(A.gc_destroyed))
return
A.gc_destroyed = world.time
queue -= A // Removing any previous references that were GC'd so that the current object will be at the end of the list.
queue[A] = world.time
// Should be treated as a replacement for the 'del' keyword.
// Datums passed to this will be given a chance to clean up references to allow the GC to collect them.
/proc/qdel(var/datum/A)
if(!A)
if (!A)
return
if(!istype(A))
if (!istype(A))
//warning("qdel() passed object of type [A.type]. qdel() can only handle /datum types.")
del(A)
SSgarbage.dels++
else if(isnull(A.gc_destroyed))
else if (isnull(A.gc_destroyed))
// Let our friend know they're about to get fucked up.
. = !A.Destroy()
if(. && A)
if(!isturf(A))
SSgarbage.AddTrash(A)
else
var/hint = A.Destroy()
if (!A)
return
switch (hint)
if (QDEL_HINT_QUEUE) //qdel should queue the object for deletion.
SSgarbage.Queue(A)
if (QDEL_HINT_LETMELIVE) //qdel should let the object live after calling destory.
return
if (QDEL_HINT_IWILLGC) //functionally the same as the above. qdel should assume the object will gc on its own, and not check it.
return
if (QDEL_HINT_HARDDEL) //qdel should assume this object won't gc, and queue a hard delete using a hard reference to save time from the locate()
SSgarbage.HardQueue(A)
if (QDEL_HINT_HARDDEL_NOW) //qdel should assume this object won't gc, and hard del it post haste.
del(A)
if (QDEL_HINT_PUTINPOOL) //qdel will put this object in the pool.
PlaceInPool(A,0)
else
SSgarbage.Queue(A)
// Default implementation of clean-up code.
// This should be overridden to remove all references pointing to the object being destroyed.
@@ -83,7 +126,7 @@ var/datum/subsystem/garbage_collector/SSgarbage
/datum/proc/Destroy()
//del(src)
tag = null
return 0
return QDEL_HINT_QUEUE
/datum/var/gc_destroyed //Time when this object was destroyed.
+3 -1
View File
@@ -13,7 +13,9 @@ var/datum/subsystem/job/SSjob
NEW_SS_GLOBAL(SSjob)
/datum/subsystem/job/Initialize()
/datum/subsystem/job/Initialize(timeofday, zlevel)
if (zlevel)
return ..()
SetupOccupations()
LoadJobs("config/jobs.txt")
..()
+2 -1
View File
@@ -6,6 +6,7 @@ var/datum/subsystem/lighting/SSlighting
name = "Lighting"
wait = 5
priority = 1
dynamic_wait = 1
var/list/changed_lights = list() //list of all datum/light_source that need updating
var/changed_lights_workload = 0 //stats on the largest number of lights (max changed_lights.len)
@@ -20,7 +21,7 @@ var/datum/subsystem/lighting/SSlighting
/datum/subsystem/lighting/stat_entry()
stat(name, "[round(cost,0.001)]ds (CPU:[round(cpu,1)]%) L:[round(changed_lights_workload,1)]/T:[round(changed_turfs_workload,1)]")
..("L:[round(changed_lights_workload,1)]|T:[round(changed_turfs_workload,1)]")
//Workhorse of lighting. It cycles through each light that needs updating. It updates their
+1 -1
View File
@@ -17,7 +17,7 @@ var/datum/subsystem/machines/SSmachine
/datum/subsystem/machines/stat_entry()
stat(name, "[round(cost,0.001)]ds (CPU:[round(cpu,1)]%)\t[processing.len]")
..("P:[processing.len]")
/datum/subsystem/machines/fire()
+1 -1
View File
@@ -10,7 +10,7 @@ var/datum/subsystem/mobs/SSmob
/datum/subsystem/mobs/stat_entry()
stat(name, "[round(cost,0.001)]ds (CPU:[round(cpu,1)]%) [mob_list.len]")
..("P:[mob_list.len]")
/datum/subsystem/mobs/fire()
+2 -2
View File
@@ -30,11 +30,11 @@ var/datum/subsystem/nano/SSnano
//Ignore directories
if(copytext(filename, length(filename)) != "/")
if(fexists(path + filename))
asset_files.Add(fcopy_rsc(path + filename))
asset_files.Add(fcopy_rsc(path + filename))
/datum/subsystem/nano/stat_entry()
stat(name, "[round(cost,0.001)]ds (CPU:[round(cpu,1)]%) [processing_uis.len]")
..("P:[processing_uis.len]")
/datum/subsystem/nano/fire()
+20 -3
View File
@@ -23,7 +23,7 @@ var/datum/subsystem/npcpool/SSbp
/datum/subsystem/npcpool/stat_entry()
stat(name, "[round(cost,0.001)]ds (CPU:[round(cpu,1)]%) (T:[botPool_l.len + botPool_l_non.len] | D: [needsDelegate.len] | A: [needsAssistant.len + needsHelp_non.len] | U: [canBeUsed.len + canBeUsed_non.len])")
..("T:[botPool_l.len + botPool_l_non.len]|D:[needsDelegate.len]|A:[needsAssistant.len + needsHelp_non.len]|U:[canBeUsed.len + canBeUsed_non.len]")
/datum/subsystem/npcpool/fire()
@@ -40,7 +40,7 @@ var/datum/subsystem/npcpool/SSbp
for(var/obj/machinery/bot/check in botPool_l_non)
if(!check)
botPool_l_non.Cut(npcCount,npcCount+1)
continue
if(check.hacked)
needsHelp_non |= check
else if(check.frustration > 5) //average for most bots
@@ -53,9 +53,10 @@ var/datum/subsystem/npcpool/SSbp
//SNPC handling
for(var/mob/living/carbon/human/interactive/check in botPool_l)
var/checkInRange = view(MAX_RANGE_FIND,check)
if(!check)
botPool_l.Cut(npcCount,npcCount+1)
continue
var/checkInRange = view(MAX_RANGE_FIND,check)
if(!(locate(check.TARGET) in checkInRange))
needsDelegate |= check
@@ -70,7 +71,11 @@ var/datum/subsystem/npcpool/SSbp
npcCount++
if(needsDelegate.len)
npcCount = 1 //reset the count
for(var/mob/living/carbon/human/interactive/check in needsDelegate)
if(!check)
needsDelegate.Cut(npcCount,npcCount+1)
continue
if(canBeUsed.len)
var/mob/living/carbon/human/interactive/candidate = pick(canBeUsed)
var/facCount = 0
@@ -87,9 +92,14 @@ var/datum/subsystem/npcpool/SSbp
needsDelegate -= check
canBeUsed -= candidate
candidate.eye_color = "red"
npcCount++
if(needsAssistant.len)
npcCount = 1 //reset the count
for(var/mob/living/carbon/human/interactive/check in needsAssistant)
if(!check)
needsAssistant.Cut(npcCount,npcCount+1)
continue
if(canBeUsed.len)
var/mob/living/carbon/human/interactive/candidate = pick(canBeUsed)
var/facCount = 0
@@ -106,11 +116,18 @@ var/datum/subsystem/npcpool/SSbp
needsAssistant -= check
canBeUsed -= candidate
candidate.eye_color = "yellow"
npcCount++
if(needsHelp_non.len)
npcCount = 1 //reset the count
for(var/obj/machinery/bot/B in needsHelp_non)
if (!B)
needsHelp_non.Cut(npcCount,npcCount+1)
continue
if(canBeUsed_non.len)
var/obj/machinery/bot/candidate = pick(canBeUsed_non)
candidate.call_bot(B,get_turf(B),FALSE)
canBeUsed_non -= B
needsHelp_non -= candidate
npcCount++
+6 -11
View File
@@ -13,16 +13,20 @@ var/datum/subsystem/objects/SSobj
/datum/subsystem/objects/New()
NEW_SS_GLOBAL(SSobj)
/datum/subsystem/objects/Initialize()
/datum/subsystem/objects/Initialize(timeofday, zlevel)
for(var/atom/movable/AM in world)
if (zlevel && AM.z != zlevel)
continue
AM.initialize()
if (zlevel)
return ..()
for(var/turf/simulated/floor/F in world)
F.MakeDirty()
..()
/datum/subsystem/objects/stat_entry()
stat(name, "[round(cost,0.001)]ds\t(CPU:[round(cpu,1)]%)\t[processing.len]")
..("P:[processing.len]")
/datum/subsystem/objects/fire()
@@ -35,12 +39,3 @@ var/datum/subsystem/objects/SSobj
SSobj.processing.Cut(i, i+1)
/* This is FPSS13 code, has not yet been ported/implemented
/obj/New()
..()
if(map_ready)
spawn(0)
if(garbage_collecting)
return
initialize()
*/
-36
View File
@@ -1,36 +0,0 @@
var/datum/subsystem/pipenets/SSpipe
/datum/subsystem/pipenets
name = "Pipenets"
priority = 11
var/list/networks = list()
/datum/subsystem/pipenets/New()
NEW_SS_GLOBAL(SSpipe)
/datum/subsystem/pipenets/Initialize()
set background = BACKGROUND_ENABLED
//is it possible to combine all these procs into initialize() ??
for(var/obj/machinery/atmospherics/M in world)
M.build_network()
for(var/obj/machinery/atmospherics/unary/U in world)
if(istype(U, /obj/machinery/atmospherics/unary/vent_pump))
var/obj/machinery/atmospherics/unary/vent_pump/V = U
V.broadcast_status()
else if(istype(U, /obj/machinery/atmospherics/unary/vent_scrubber))
var/obj/machinery/atmospherics/unary/vent_scrubber/V = U
V.broadcast_status()
..()
/datum/subsystem/pipenets/fire()
var/i=1
for(var/thing in networks)
if(thing)
thing:process()
++i
continue
networks.Cut(i, i+1)
+17 -2
View File
@@ -9,10 +9,25 @@ var/datum/subsystem/power/SSpower
/datum/subsystem/power/New()
NEW_SS_GLOBAL(SSpower)
/datum/subsystem/power/Initialize()
makepowernets()
/datum/subsystem/power/stat_entry(msg)
..("P:[powernets.len]")
/datum/subsystem/power/Initialize(timeofday, zlevel)
makepowernets(zlevel)
..()
// rebuild all power networks from scratch - only called at world creation or by the admin verb
/datum/subsystem/power/proc/makepowernets(zlevel)
for(var/datum/powernet/PN in powernets)
qdel(PN)
powernets.Cut()
for(var/obj/structure/cable/PC in cable_list)
if(!PC.powernet)
var/datum/powernet/NewPN = new()
NewPN.add_cable(PC)
propagate_network(PC,PC.powernet)
/datum/subsystem/power/fire()
for(var/datum/powernet/Powernet in powernets)
Powernet.reset()
+3 -1
View File
@@ -39,7 +39,9 @@ var/datum/subsystem/shuttle/SSshuttle
NEW_SS_GLOBAL(SSshuttle)
/datum/subsystem/shuttle/Initialize()
/datum/subsystem/shuttle/Initialize(timeofday, zlevel)
if (zlevel)
return ..()
if(!emergency)
WARNING("No /obj/docking_port/mobile/emergency placed on the map!")
if(!supply)
+3
View File
@@ -19,6 +19,9 @@ var/datum/subsystem/sun/SSsun
if(prob(50)) // same chance to rotate clockwise than counter-clockwise
rate = -rate
/datum/subsystem/sun/stat_entry(msg)
..("P:[solars.len]")
/datum/subsystem/sun/fire()
angle = (360 + angle + rate * 6) % 360 // increase/decrease the angle to the sun, adjusted by the rate
+3 -1
View File
@@ -51,7 +51,9 @@ var/datum/subsystem/ticker/ticker
if(SSevent.holidays && SSevent.holidays[APRIL_FOOLS])
login_music = 'sound/ambience/clown.ogg'
/datum/subsystem/ticker/Initialize()
/datum/subsystem/ticker/Initialize(timeofday, zlevel)
if (zlevel)
return ..()
if(!syndicate_code_phrase) syndicate_code_phrase = generate_code_phrase()
if(!syndicate_code_response) syndicate_code_response = generate_code_phrase()
setupGenetics()
+22 -12
View File
@@ -2,17 +2,20 @@
/datum/subsystem
//things you will want to define
var/name //name of the subsystem
var/priority = 0 //priority affects order of initialization. Higher priorities are initialized first, lower priorities later. Can be decimal and negative values.
var/wait = 20 //time to wait (in deciseconds) between each call to fire(). Must be a positive integer.
var/name //name of the subsystem
var/priority = 0 //priority affects order of initialization. Higher priorities are initialized first, lower priorities later. Can be decimal and negative values.
var/wait = 20 //time to wait (in deciseconds) between each call to fire(). Must be a positive integer.
var/dynamic_wait = 0 //changes the wait based on the amount of time it took to process
var/dwait_upper = 20 //longest wait can be under dynamic_wait
var/dwait_lower = 5 //shortest wait can be under dynamic_wait
var/dwait_delta = 3 //How much should processing time effect dwait. or basically: wait = cost*dwait_delta
//things you will probably want to leave alone
var/can_fire = 0 //prevent fire() calls
var/last_fire = 0 //last world.time we called fire()
var/next_fire = 0 //scheduled world.time for next fire()
var/cpu = 0 //cpu-usage stats (somewhat vague)
var/cost = 0 //average time to execute
var/times_fired = 0 //number of times we have called fire()
var/can_fire = 0 //prevent fire() calls
var/last_fire = 0 //last world.time we called fire()
var/next_fire = 0 //scheduled world.time for next fire()
var/cost = 0 //average time to execute
var/times_fired = 0 //number of times we have called fire()
//used to initialize the subsystem BEFORE the map has loaded
/datum/subsystem/New()
@@ -25,15 +28,22 @@
can_fire = 0
//used to initialize the subsystem AFTER the map has loaded
/datum/subsystem/proc/Initialize(start_timeofday)
/datum/subsystem/proc/Initialize(start_timeofday, zlevel)
var/time = (world.timeofday - start_timeofday) / 10
var/msg = "Initialized [name] SubSystem within [time] seconds"
if (zlevel)
testing(msg)
return
world << "<span class='boldannounce'>[msg]</span>"
world.log << msg
//hook for printing stats to the "MC" statuspanel for admins to see performance and related stats etc.
/datum/subsystem/proc/stat_entry()
stat(name, "[round(cost,0.001)]ds\t(CPU:[round(cpu,1)]%)")
/datum/subsystem/proc/stat_entry(msg)
var/dwait = ""
if (dynamic_wait)
dwait = "DWait:[wait]ds "
stat(name, "[round(cost,0.001)]ds\t[dwait][msg]")
//could be used to postpone a costly subsystem for one cycle
//for instance, during cpu intensive operations like explosions
+2
View File
@@ -0,0 +1,2 @@
/datum/debug
var/list/debuglist
-30
View File
@@ -1,30 +0,0 @@
/datum/powernet
var/list/cables = list() // all cables & junctions
var/list/nodes = list() // all connected machines
var/load = 0 // the current load on the powernet, increased by each machine at processing
var/newavail = 0 // what available power was gathered last tick, then becomes...
var/avail = 0 //...the current available power in the powernet
var/viewload = 0 // the load as it appears on the power console (gradually updated)
var/number = 0 // Unused //TODEL
var/netexcess = 0 // excess power on the powernet (typically avail-load)
/*Powernet procs :
In modules/power/power.dm :
/datum/powernet/New()
/datum/powernet/Destroy()
/datum/powernet/proc/is_empty()
/datum/powernet/proc/remove_cable(var/obj/structure/cable/C)
/datum/powernet/proc/add_cable(var/obj/structure/cable/C)
/datum/powernet/proc/remove_machine(var/obj/machinery/power/M)
/datum/powernet/proc/add_machine(var/obj/machinery/power/M)
/datum/powernet/proc/reset()
/datum/powernet/proc/get_electrocute_damage()
*/
/datum/debug
var/list/debuglist
+3 -2
View File
@@ -12,10 +12,11 @@
var/spell_to_add = text2path(spell)
new spell_to_add(src) //should result in adding to contents, needs testing
/obj/effect/proc_holder/spell/targeted/trigger/Destroy() //I think this entire proc is unnecessary but ok
/obj/effect/proc_holder/spell/targeted/trigger/Destroy()
for(var/spell in contents)
qdel(spell)
linked_spells = null
starting_spells = null
..()
/obj/effect/proc_holder/spell/targeted/trigger/cast(list/targets)
+5
View File
@@ -82,6 +82,11 @@
qdel(AM)
loc = null
invisibility = 101
if (pulledby)
if (pulledby.pulling == src)
pulledby.pulling = null
pulledby = null
// Previously known as HasEntered()
// This is automatically called when something enters your square
@@ -113,6 +113,7 @@
/mob/living/simple_animal/hostile/blob/blobspore/Destroy()
if(factory)
factory.spores -= src
factory = null
if(contents)
for(var/mob/M in contents)
M.loc = src.loc
+1
View File
@@ -38,6 +38,7 @@
blob_cores -= src
if(overmind)
overmind.blob_core = null
overmind = null
SSobj.processing.Remove(src)
..()
@@ -17,6 +17,7 @@
for(var/mob/living/simple_animal/hostile/blob/blobspore/spore in spores)
if(spore.factory == src)
spore.factory = null
spores = null
..()
/obj/effect/blob/factory/PulseAnimation(var/activate = 0)
+2 -2
View File
@@ -192,7 +192,7 @@
var/mob/living/simple_animal/hostile/blob/blobbernaut/blobber = new /mob/living/simple_animal/hostile/blob/blobbernaut (get_turf(B))
if(blobber)
B.Destroy()
qdel(B)
blobber.color = blob_reagent_datum.color
blobber.overmind = src
blob_mobs.Add(blobber)
@@ -243,7 +243,7 @@
src << "Unable to remove this blob."
return
B.Destroy()
qdel(B)
return
+3 -3
View File
@@ -258,7 +258,7 @@ This is here to make the tiles around the station mininuke change when it's arme
var/turf/disk_loc = get_turf(src)
if(disk_loc.z > ZLEVEL_CENTCOM)
get(src, /mob) << "<span class='danger'>You can't help but feel that you just lost something back there...</span>"
Destroy()
qdel(src)
/obj/item/weapon/disk/nuclear/Destroy()
if(blobstart.len > 0)
@@ -267,7 +267,7 @@ This is here to make the tiles around the station mininuke change when it's arme
var/turf/diskturf = get_turf(src)
message_admins("[src] has been destroyed in ([diskturf.x], [diskturf.y] ,[diskturf.z] - <A HREF='?_src_=holder;adminplayerobservecoodjump=1;X=[diskturf.x];Y=[diskturf.y];Z=[diskturf.z]'>JMP</a>). Moving it to ([NEWDISK.x], [NEWDISK.y], [NEWDISK.z] - <A HREF='?_src_=holder;adminplayerobservecoodjump=1;X=[NEWDISK.x];Y=[NEWDISK.y];Z=[NEWDISK.z]'>JMP</a>).")
log_game("[src] has been destroyed in ([diskturf.x], [diskturf.y] ,[diskturf.z]). Moving it to ([NEWDISK.x], [NEWDISK.y], [NEWDISK.z]).")
del(src) //Needed to clear all references to it
return QDEL_HINT_HARDDEL_NOW
else
ERROR("[src] was supposed to be destroyed, but we were unable to locate a blobstart landmark to spawn a new one.")
return 1 // Cancel destruction.
return QDEL_HINT_LETMELIVE // Cancel destruction.
+1
View File
@@ -23,6 +23,7 @@
/obj/machinery/bluespace_beacon/Destroy()
if(Beacon)
qdel(Beacon)
Beacon = null
..()
// update the invisibility and icon
+1
View File
@@ -113,6 +113,7 @@
..()
src.updateUsrDialog()
/obj/machinery/atmospherics/unary/cold_sink/freezer/power_change()
..()
if(stat & NOPOWER)
+2 -2
View File
@@ -29,7 +29,7 @@ obj/machinery/air_sensor
obj/machinery/air_sensor/update_icon()
icon_state = "gsensor[on]"
obj/machinery/air_sensor/process()
obj/machinery/air_sensor/process_atmos()
if(on)
var/datum/signal/signal = new
signal.transmission_method = 1 //radio signal
@@ -73,7 +73,7 @@ obj/machinery/air_sensor/initialize()
obj/machinery/air_sensor/New()
..()
SSair.atmos_machinery += src
if(radio_controller)
set_frequency(frequency)
+6 -4
View File
@@ -18,6 +18,7 @@
var/release_log = ""
var/update_flag = 0
/obj/machinery/portable_atmospherics/canister/sleeping_agent
name = "canister: \[N2O\]"
icon_state = "redws"
@@ -123,6 +124,7 @@ update_flag
if (src.health <= 10)
var/atom/location = src.loc
location.assume_air(air_contents)
air_update_turf()
src.destroyed = 1
playsound(src.loc, 'sound/effects/spray.ogg', 10, 1, -3)
@@ -138,9 +140,9 @@ update_flag
else
return 1
/obj/machinery/portable_atmospherics/canister/process()
/obj/machinery/portable_atmospherics/canister/process_atmos()
if (destroyed)
return
return PROCESS_KILL
..()
@@ -174,9 +176,9 @@ update_flag
can_label = 1
else
can_label = 0
/obj/machinery/portable_atmospherics/canister/process()
src.updateDialog()
return
return ..()
/obj/machinery/portable_atmospherics/canister/return_air()
return air_contents
+3 -1
View File
@@ -14,6 +14,7 @@
/obj/machinery/meter/New()
..()
SSair.atmos_machinery += src
src.target = locate(/obj/machinery/atmospherics/pipe) in loc
return 1
@@ -21,7 +22,7 @@
if (!target)
src.target = locate(/obj/machinery/atmospherics/pipe) in loc
/obj/machinery/meter/process()
/obj/machinery/meter/process_atmos()
if(!target)
icon_state = "meterX"
return 0
@@ -114,6 +115,7 @@
return 1
// TURF METER - REPORTS A TILE'S AIR CONTENTS
// why are you yelling?
/obj/machinery/meter/turf/New()
..()
@@ -10,25 +10,26 @@
var/destroyed = 0
var/maximum_pressure = 90*ONE_ATMOSPHERE
var/lastupdate = 0
/obj/machinery/portable_atmospherics/New()
..()
SSair.atmos_machinery += src
air_contents.volume = volume
air_contents.temperature = T20C
return 1
/obj/machinery/portable_atmospherics/process()
if(!connected_port) //only react when pipe_network will ont it do it for you
/obj/machinery/portable_atmospherics/process_atmos()
if(!connected_port) //only react when pipe_network will not it do it for you
//Allow for reactions
air_contents.react()
else
update_icon()
/obj/machinery/portable_atmospherics/process()
return
/obj/machinery/portable_atmospherics/Destroy()
del(air_contents)
qdel(air_contents)
SSair.atmos_machinery -= src
..()
/obj/machinery/portable_atmospherics/update_icon()
+3 -2
View File
@@ -43,7 +43,7 @@
..(severity)
/obj/machinery/portable_atmospherics/pump/process()
/obj/machinery/portable_atmospherics/pump/process_atmos()
..()
if(on)
var/datum/gas_mixture/environment
@@ -85,7 +85,8 @@
air_contents.merge(removed)
//src.update_icon()
/obj/machinery/portable_atmospherics/pump/process()
..()
src.updateDialog()
return
+7 -2
View File
@@ -89,7 +89,7 @@
return
/obj/machinery/portable_atmospherics/scrubber/process()
/obj/machinery/portable_atmospherics/scrubber/process_atmos()
..()
if(on)
@@ -139,10 +139,15 @@
environment.merge(removed)
else
loc.assume_air(removed)
//src.update_icon()
/obj/machinery/portable_atmospherics/scrubber/process_atmos()
..()
src.updateDialog()
return
/obj/machinery/portable_atmospherics/scrubber/return_air()
return air_contents
+1 -1
View File
@@ -9,7 +9,7 @@
var/on = 0
var/volume_rate = 800
/obj/machinery/zvent/process()
/obj/machinery/zvent/process_atmos()
//all this object does, is make its turf share air with the ones above and below it, if they have a vent too.
if (istype(loc,/turf/simulated)) //if we're not on a valid turf, forget it
+2
View File
@@ -108,6 +108,8 @@
if(radio_controller)
radio_controller.remove_object(src,beacon_freq)
radio_controller.remove_object(src,control_freq)
qdel(Radio)
qdel(botcard)
..()
/obj/machinery/bot/proc/add_to_beacons() //Master radio control for bots. Must be placed in the bot's local New() to support map spawned bots.
+15 -12
View File
@@ -25,7 +25,7 @@
component_parts += new /obj/item/weapon/stock_parts/console_screen(null)
component_parts += new /obj/item/weapon/stock_parts/console_screen(null)
component_parts += new /obj/item/stack/cable_coil(null, 1)
RefreshParts()
/obj/machinery/atmospherics/unary/cryo_cell/construction()
..(dir,dir)
@@ -40,10 +40,19 @@
/obj/machinery/atmospherics/unary/cryo_cell/Destroy()
var/turf/T = loc
T.contents += contents
var/obj/item/weapon/reagent_containers/glass/B = beaker
if(beaker)
B.loc = get_step(loc, SOUTH) //Beaker is carefully ejected from the wreckage of the cryotube
beaker.loc = get_step(loc, SOUTH) //Beaker is carefully ejected from the wreckage of the cryotube
beaker = null
..()
/obj/machinery/atmospherics/unary/cryo_cell/process_atmos()
..()
if(air_contents)
temperature_archived = air_contents.temperature
heat_gas_contents()
expel_gas()
if(abs(temperature_archived-air_contents.temperature) > 1)
parent.update = 1
/obj/machinery/atmospherics/unary/cryo_cell/process()
..()
@@ -54,19 +63,13 @@
playsound(src.loc, 'sound/machines/ding.ogg', 50, 1)
if(!node || !is_operational())
return
if(!on)
updateDialog()
return
if(air_contents)
temperature_archived = air_contents.temperature
heat_gas_contents()
expel_gas()
if(occupant)
process_occupant()
if(abs(temperature_archived-air_contents.temperature) > 1)
parent.update = 1
if(air_contents && occupant)
process_occupant()
updateDialog()
return 1
+1
View File
@@ -17,6 +17,7 @@
/obj/machinery/door/airlock/alarmlock/Destroy()
if(radio_controller)
radio_controller.remove_object(src,air_frequency)
air_connection = null
..()
/obj/machinery/door/airlock/alarmlock/initialize()
+2
View File
@@ -22,9 +22,11 @@
density = 0
if(health == 0)
playsound(src, "shatter", 70, 1)
electronics = null
..()
/obj/machinery/door/window/proc/open_and_close()
open()
if(src.check_access(null))
+8 -2
View File
@@ -82,9 +82,12 @@ Class Procs:
Called by machine to assign a value to the uid variable.
process() 'game/machinery/machine.dm'
Called by the 'master_controller' once per game tick for each machine that is listed in the 'machines' list.
Called by the 'machinery subsystem' once per machinery tick for each machine that is listed in its 'machines' list.
is_operational()
process_atmos()
Called by the 'air subsystem' once per atmos tick for each machine that is listed in its 'atmos_machines' list.
is_operational()
Returns 0 if the machine is unpowered, broken or undergoing maintenance, something else if not
Compiled by Aygar
@@ -132,6 +135,9 @@ Class Procs:
/obj/machinery/process()//If you dont use process or power why are you here
return PROCESS_KILL
/obj/machinery/proc/process_atmos()//If you dont use process why are you here
return PROCESS_KILL
/obj/machinery/emp_act(severity)
if(use_power && stat == 0)
use_power(7500/severity)
+3
View File
@@ -46,6 +46,7 @@
if(radio_controller)
radio_controller.remove_object(src, freq)
..()
center = null
// update the invisibility and icon
/obj/machinery/magnetic_module/hide(var/intact)
@@ -244,6 +245,8 @@
if(radio_controller)
radio_controller.remove_object(src, frequency)
..()
magnets = null
rpath = null
/obj/machinery/magnetic_controller/process()
if(magnets.len == 0 && autolink)
+2
View File
@@ -184,6 +184,8 @@ var/list/obj/machinery/newscaster/allCasters = list() //Global list that will co
/obj/machinery/newscaster/Destroy()
allCasters -= src
viewing_channel = null
photo = null
..()
/obj/machinery/newscaster/update_icon()
+1
View File
@@ -143,6 +143,7 @@
/obj/machinery/porta_turret/Destroy()
//deletes its own cover with it
qdel(cover)
cover = null
..()
+1
View File
@@ -142,6 +142,7 @@
/obj/machinery/shieldgen/Destroy()
for(var/obj/machinery/shield/shield_tile in deployed_shields)
qdel(shield_tile)
deployed_shields = null
..()
+15
View File
@@ -20,6 +20,11 @@
/obj/machinery/computer/teleporter/initialize()
link_power_station()
/obj/machinery/computer/teleporter/Destroy()
if (power_station)
power_station.teleporter_console = null
power_station = null
/obj/machinery/computer/teleporter/proc/link_power_station()
if(power_station)
return
@@ -258,6 +263,11 @@
/obj/machinery/teleport/hub/initialize()
link_power_station()
/obj/machinery/teleport/hub/Destroy()
if (power_station)
power_station.teleporter_hub = null
power_station = null
/obj/machinery/teleport/hub/RefreshParts()
var/A = 0
for(var/obj/item/weapon/stock_parts/matter_bin/M in component_parts)
@@ -372,7 +382,12 @@
/obj/machinery/teleport/station/Destroy()
if(teleporter_hub)
teleporter_hub.power_station = null
teleporter_hub.update_icon()
teleporter_hub = null
if (teleporter_console)
teleporter_console.power_station = null
teleporter_console = null
..()
/obj/machinery/teleport/station/attackby(var/obj/item/weapon/W, mob/user, params)
+1
View File
@@ -82,6 +82,7 @@
coin = null
..()
/obj/machinery/vending/snack/Destroy()
for(var/obj/item/weapon/reagent_containers/food/snacks/S in contents)
S.loc = get_turf(src)
+1
View File
@@ -23,6 +23,7 @@
/obj/mecha/combat/marauder/Destroy()
qdel(smoke_system)
smoke_system = null
..()
/obj/mecha/combat/marauder/seraph
+1
View File
@@ -187,6 +187,7 @@
loc = null
for (var/obj/structure/alien/weeds/W in range(1,T))
W.updateWeedOverlays()
linked_node = null
..()
/obj/structure/alien/weeds/proc/Life()
@@ -16,6 +16,7 @@
/obj/effect/decal/cleanable/xenoblood/Destroy()
for(var/datum/disease/D in viruses)
D.cure(0)
viruses = null
..()
/obj/effect/decal/cleanable/xenoblood/xgibs/proc/streak(var/list/directions)
@@ -14,6 +14,7 @@
/obj/effect/decal/cleanable/blood/Destroy()
for(var/datum/disease/D in viruses)
D.cure(0)
viruses = null
..()
/obj/effect/decal/cleanable/blood/New()
@@ -106,6 +106,7 @@
/obj/effect/decal/cleanable/vomit/Destroy()
for(var/datum/disease/D in viruses)
D.cure(0)
viruses = null
..()
/obj/effect/decal/cleanable/tomato_smudge
@@ -58,6 +58,7 @@
/obj/effect/decal/cleanable/oil/Destroy()
for(var/datum/disease/D in viruses)
D.cure(0)
viruses = null
..()
/obj/effect/decal/cleanable/oil/streak
@@ -15,8 +15,7 @@ would spawn and follow the beaker, even if it is carried or thrown.
/obj/effect/effect/Destroy()
..()
PlaceInPool(src)
return 1
return QDEL_HINT_PUTINPOOL
/datum/effect/effect/proc/fadeOut(var/atom/A, var/frames = 16)
if(A.alpha == 0) //Handle already transparent case
@@ -227,9 +227,9 @@
R.my_atom = chemholder
/datum/effect/effect/system/chem_smoke_spread/Destroy()
PlaceInPool(chemholder)
chemholder = null
..()
return QDEL_HINT_PUTINPOOL
/datum/effect/effect/system/chem_smoke_spread/set_up(var/datum/reagents/carry = null, n = 5, c = 0, loca, direct, silent = 0)
if(n > 20)
+3
View File
@@ -83,6 +83,9 @@
start_landmarks_list += src
return 1
/obj/effect/landmark/start/Destroy()
..()
start_landmarks_list -= src
//Costume spawner landmarks
+1
View File
@@ -33,6 +33,7 @@
else if(istype(creator, /obj/item/weapon/gun/energy/wormhole_projector))
var/obj/item/weapon/gun/energy/wormhole_projector/P = creator
P.portal_destroyed(src)
creator = null
return ..()
/obj/effect/portal/proc/teleport(atom/movable/M as mob|obj)
+1 -1
View File
@@ -103,7 +103,7 @@ proc/explosion(turf/epicenter, devastation_range, heavy_impact_range, light_impa
if(T)
if(flame_dist && prob(40) && !istype(T, /turf/space) && !T.density)
new/obj/effect/hotspot(T) //Mostly for ambience!
PoolOrNew(/obj/effect/hotspot, T) //Mostly for ambience!
if(dist > 0)
T.ex_act(dist)
+1
View File
@@ -26,6 +26,7 @@
H.med_hud_set_status()
spawn(0)
RemoveInfectionImages(affected_mob)
affected_mob = null
..()
/obj/item/body_egg/process()
@@ -49,7 +49,8 @@
qdel(expansion)
expansion = null
del(src)
/* Easier to just call del() than this nonsense
//Easier to just call del() than this nonsense
// ya no, del() takes 0.8ds to run on avg. this takes less than 0.01
get_cameras()
for(var/cam_tag in bugged_cameras)
var/obj/machinery/camera/camera = bugged_cameras[cam_tag]
@@ -59,7 +60,7 @@
if(tracking)
tracking = null
..()
*/
/obj/item/device/camera_bug/interact(var/mob/user = usr)
var/datum/browser/popup = new(user, "camerabug","Camera Bug",nref=src)
-2
View File
@@ -25,8 +25,6 @@
return
/obj/item/stack/Destroy()
if (is_cyborg)
return // Not supposed to be destroyed
if (usr && usr.machine==src)
usr << browse(null, "window=stack")
src.loc = null
+15 -2
View File
@@ -9,6 +9,17 @@ Creation/Deletion is laggy, so let's reduce reuse and recycle!
Locked to /atom/movable and it's subtypes due to Loc being a const var on /atom
but being read&write on /movable due to how they... move.
Usage:
To get a object, just called PoolOrNew(type, list of args to pass to New)
To put a object back in the pool, call place in pool.
This will call destroy on the object, set its loc to null,
and reset all of its vars to their default
You can override your object's destroy to return QDEL_HINT_PLACEINPOOL
to ensure its always placed in this pool (this will only be acted on if qdel calls destroy, and destroy will not get called twice)
*/
var/global/list/GlobalPool = list()
@@ -67,7 +78,7 @@ var/global/list/GlobalPool = list()
/proc/PlaceInPool(var/atom/movable/AM)
/proc/PlaceInPool(var/atom/movable/AM, destroy = 1)
if(!istype(AM))
return
@@ -79,7 +90,9 @@ var/global/list/GlobalPool = list()
GlobalPool[AM.type] |= AM
AM.Destroy()
if (destroy)
AM.Destroy()
AM.ResetVars()
+2
View File
@@ -18,6 +18,8 @@
if(config)
if(config.starlight)
update_starlight()
/turf/space/Destroy()
return QDEL_HINT_LETMELIVE
/turf/space/proc/update_starlight()
if(config)
+2
View File
@@ -28,6 +28,8 @@
for(var/atom/movable/AM in src)
Entered(AM)
return
/turf/Destroy()
return QDEL_HINT_HARDDEL_NOW
// Adds the adjacent turfs to the current atmos processing
/turf/Del()
+1 -1
View File
@@ -581,7 +581,7 @@ var/global/floorIsLava = 0
set name="Start Now"
if(ticker.current_state == GAME_STATE_PREGAME)
ticker.can_fire = 1
ticker.current_state = GAME_STATE_SETTING_UP
ticker.timeLeft = 0
log_admin("[usr.key] has started the game.")
message_admins("<font color='blue'>[usr.key] has started the game.</font>")
feedback_add_details("admin_verb","SN") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
+2 -2
View File
@@ -1079,8 +1079,8 @@ var/global/list/g_fancy_list_of_types = null
var/dat = "<B>List of things that failed to GC this round</B><BR><BR>"
for(var/path in SSgarbage.logging)
dat += "[path] - [SSgarbage.logging[path]] times<BR>"
for(var/path in SSgarbage.didntgc)
dat += "[path] - [SSgarbage.didntgc[path]] times<BR>"
usr << browse(dat, "window=dellog")
+1 -1
View File
@@ -63,7 +63,7 @@
new_holder.mind.objectives += O
new_holder.attack_log += "\[[time_stamp()]\] <font color='green'>Won with greentext!!!</font>"
color_altered_mobs -= new_holder
Destroy()
qdel(src)
if(last_holder && last_holder != new_holder) //Somehow it was swiped without ever getting dropped
last_holder << "<span class='warning'>A sudden wave of failure washes over you...</span>"
+1 -1
View File
@@ -224,7 +224,7 @@
anchored = 1
/atom/movable/light/Destroy()
return 1
return QDEL_HINT_LETMELIVE
/atom/movable/light/Move()
return 0

Some files were not shown because too many files have changed in this diff Show More