diff --git a/code/__HELPERS/unsorted.dm b/code/__HELPERS/unsorted.dm
index ea3811085b..28a0dc7889 100644
--- a/code/__HELPERS/unsorted.dm
+++ b/code/__HELPERS/unsorted.dm
@@ -1079,18 +1079,17 @@ B --><-- A
return L
//similar function to RANGE_TURFS(), but will search spiralling outwards from the center (like the above, but only turfs)
-/proc/spiral_range_turfs(dist=0, center=usr, orange=0)
+/proc/spiral_range_turfs(dist=0, center=usr, orange=0, list/outlist = list(), tick_checked)
+ outlist.Cut()
if(!dist)
- if(!orange)
- return list(center)
- else
- return list()
+ outlist += center
+ return outlist
var/turf/t_center = get_turf(center)
if(!t_center)
- return list()
+ return outlist
- var/list/L = list()
+ var/list/L = outlist
var/turf/T
var/y
var/x
@@ -1128,6 +1127,8 @@ B --><-- A
if(T)
L += T
c_dist++
+ if(tick_checked)
+ CHECK_TICK
return L
diff --git a/code/_globalvars/configuration.dm b/code/_globalvars/configuration.dm
index 23bfdd3987..b001b84255 100644
--- a/code/_globalvars/configuration.dm
+++ b/code/_globalvars/configuration.dm
@@ -22,12 +22,12 @@ GLOBAL_VAR_INIT(tinted_weldhelh, TRUE)
// Debug2 is used in conjunction with a lot of admin verbs and therefore is actually legit.
GLOBAL_VAR_INIT(Debug, FALSE) // global debug switch
GLOBAL_VAR_INIT(Debug2, FALSE)
-
-//This was a define, but I changed it to a variable so it can be changed in-game.(kept the all-caps definition because... code...) -Errorage
-GLOBAL_VAR_INIT(MAX_EX_DEVESTATION_RANGE, 3)
-GLOBAL_VAR_INIT(MAX_EX_HEAVY_RANGE, 7)
-GLOBAL_VAR_INIT(MAX_EX_LIGHT_RANGE, 14)
-GLOBAL_VAR_INIT(MAX_EX_FLASH_RANGE, 14)
-GLOBAL_VAR_INIT(MAX_EX_FLAME_RANGE, 14)
-GLOBAL_VAR_INIT(DYN_EX_SCALE, 0.5)
-
+
+//This was a define, but I changed it to a variable so it can be changed in-game.(kept the all-caps definition because... code...) -Errorage
+GLOBAL_VAR_INIT(MAX_EX_DEVESTATION_RANGE, 3)
+GLOBAL_VAR_INIT(MAX_EX_HEAVY_RANGE, 7)
+GLOBAL_VAR_INIT(MAX_EX_LIGHT_RANGE, 14)
+GLOBAL_VAR_INIT(MAX_EX_FLASH_RANGE, 14)
+GLOBAL_VAR_INIT(MAX_EX_FLAME_RANGE, 14)
+GLOBAL_VAR_INIT(DYN_EX_SCALE, 0.5)
+
diff --git a/code/controllers/subsystem/explosion.dm b/code/controllers/subsystem/explosion.dm
new file mode 100644
index 0000000000..fe6657644f
--- /dev/null
+++ b/code/controllers/subsystem/explosion.dm
@@ -0,0 +1,510 @@
+SUBSYSTEM_DEF(explosion)
+ priority = 99
+ wait = 1
+ flags = SS_TICKER|SS_NO_INIT
+
+ var/list/explosions
+
+ var/rebuild_tick_split_count = FALSE
+ var/tick_portions_required = 0
+
+ var/list/logs
+
+ var/list/zlevels_that_ignore_bombcap
+ var/list/doppler_arrays
+
+ //legacy caps, set by config
+ var/devastation_cap = 3
+ var/heavy_cap = 7
+ var/light_cap = 14
+ var/flash_cap = 14
+ var/flame_cap = 14
+ var/dyn_ex_scale = 0.5
+
+ var/id_counter = 0
+
+/datum/controller/subsystem/explosion/PreInit()
+ doppler_arrays = list()
+ logs = list()
+ explosions = list()
+ zlevels_that_ignore_bombcap = list("[ZLEVEL_MINING]")
+
+/datum/controller/subsystem/explosion/Shutdown()
+ QDEL_LIST(explosions)
+ QDEL_LIST(logs)
+ zlevels_that_ignore_bombcap.Cut()
+
+/datum/controller/subsystem/explosion/Recover()
+ explosions = SSexplosion.explosions
+ logs = SSexplosion.logs
+ id_counter = SSexplosion.id_counter
+ rebuild_tick_split_count = TRUE
+ zlevels_that_ignore_bombcap = SSexplosion.zlevels_that_ignore_bombcap
+ doppler_arrays = SSexplosion.doppler_arrays
+
+ devastation_cap = SSexplosion.devastation_cap
+ heavy_cap = SSexplosion.heavy_cap
+ light_cap = SSexplosion.light_cap
+ flash_cap = SSexplosion.flash_cap
+ flame_cap = SSexplosion.flame_cap
+ dyn_ex_scale = SSexplosion.dyn_ex_scale
+
+/datum/controller/subsystem/explosion/fire()
+ var/list/cached_explosions = explosions
+ var/num_explosions = cached_explosions.len
+ if(!num_explosions)
+ return
+
+ //figure exactly how many tick splits are required
+ var/num_splits
+ if(rebuild_tick_split_count)
+ var/reactionary = config.reactionary_explosions
+ num_splits = num_explosions
+ for(var/I in cached_explosions)
+ var/datum/explosion/E = I
+ if(!E.turfs_processed)
+ ++num_splits
+ if(reactionary && !E.densities_processed)
+ ++num_splits
+ tick_portions_required = num_splits
+ else
+ num_splits = tick_portions_required
+
+ MC_SPLIT_TICK_INIT(num_splits)
+
+ for(var/I in cached_explosions)
+ var/datum/explosion/E = I
+
+ var/etp = E.turfs_processed
+ if(!etp)
+ if(GatherTurfs(E))
+ --tick_portions_required
+ etp = TRUE
+ MC_SPLIT_TICK
+
+ var/edp = E.densities_processed
+ if(!edp)
+ if(DensityCalculate(E, etp))
+ --tick_portions_required
+ edp = TRUE
+ MC_SPLIT_TICK
+
+ if(ProcessExplosion(E, edp)) //splits the tick
+ --tick_portions_required
+ explosions -= E
+ logs += E
+ NotifyDopplers(E)
+ MC_SPLIT_TICK
+
+/datum/controller/subsystem/explosion/proc/NotifyDopplers(datum/explosion/E)
+ for(var/array in doppler_arrays)
+ var/obj/machinery/doppler_array/A = array
+ A.sense_explosion(E.epicenter, E.devastation, E.heavy, E.light, E.finished_at - E.started_at, E.orig_dev_range, E.orig_heavy_range, E.orig_light_range)
+
+/datum/controller/subsystem/explosion/proc/Create(atom/epicenter, devastation_range, heavy_impact_range, light_impact_range, flash_range, adminlog = TRUE, ignorecap = FALSE, flame_range = 0 , silent = FALSE, smoke = FALSE)
+ epicenter = get_turf(epicenter)
+ if(!epicenter)
+ return
+
+ if(adminlog)
+ message_admins("Explosion with size ([devastation_range], [heavy_impact_range], [light_impact_range], [flame_range]) in area: [get_area(epicenter)] [ADMIN_COORDJMP(epicenter)]")
+ log_game("Explosion with size ([devastation_range], [heavy_impact_range], [light_impact_range], [flame_range]) in area [epicenter.loc.name] ([epicenter.x],[epicenter.y],[epicenter.z])")
+
+ var/datum/explosion/E = new(++id_counter, epicenter, devastation_range, heavy_impact_range, light_impact_range, flash_range, flame_range, silent, smoke, ignorecap)
+
+ if(heavy_impact_range > 1)
+ var/datum/effect_system/explosion/Eff
+ if(smoke)
+ Eff = new /datum/effect_system/explosion/smoke
+ else
+ Eff = new
+ Eff.set_up(epicenter)
+ Eff.start()
+
+ //flash mobs
+ if(flash_range)
+ for(var/mob/living/L in viewers(flash_range, epicenter))
+ L.flash_act()
+
+ if(!silent)
+ ExplosionSound(epicenter, devastation_range, heavy_impact_range, E.extent)
+
+ //add to SS
+ if(E.extent)
+ tick_portions_required += 2 + (config.reactionary_explosions ? 1 : 0)
+ explosions += E
+ else
+ logs += E //Already done processing
+
+/datum/controller/subsystem/explosion/proc/CreateDynamic(atom/epicenter, power, flash_range, adminlog = TRUE, ignorecap = TRUE, flame_range = 0 , silent = FALSE, smoke = TRUE)
+ if(!power)
+ return
+ var/range = round((2 * power) ** dyn_ex_scale)
+ Create(epicenter, round(range * 0.25), round(range * 0.5), round(range), flash_range*range, adminlog, ignorecap, flame_range*range, silent, smoke)
+
+// Using default dyn_ex scale:
+// 100 explosion power is a (5, 10, 20) explosion.
+// 75 explosion power is a (4, 8, 17) explosion.
+// 50 explosion power is a (3, 7, 14) explosion.
+// 25 explosion power is a (2, 5, 10) explosion.
+// 10 explosion power is a (1, 3, 6) explosion.
+// 5 explosion power is a (0, 1, 3) explosion.
+// 1 explosion power is a (0, 0, 1) explosion.
+
+/datum/explosion
+ var/explosion_id
+ var/turf/epicenter
+
+ var/started_at
+ var/finished_at
+ var/tick_started
+ var/tick_finished
+
+ var/turfs_processed = FALSE
+ var/densities_processed = FALSE
+
+ var/orig_dev_range
+ var/orig_heavy_range
+ var/orig_light_range
+ var/orig_flash_range
+ var/orig_flame_range
+
+ var/devastation
+ var/heavy
+ var/light
+ var/extent
+
+ var/flash
+ var/flame
+
+ var/gather_dist = 0
+
+ var/list/gathered_turfs
+ var/list/calculated_turfs
+
+ var/list/unsafe_turfs
+
+/datum/explosion/New(id, turf/epi, devastation_range, heavy_impact_range, light_impact_range, flash_range, flame_range, silent, smoke, ignorecap)
+ explosion_id = id
+ epicenter = epi
+
+ densities_processed = !config.reactionary_explosions
+
+ orig_dev_range = devastation_range
+ orig_heavy_range = heavy_impact_range
+ orig_light_range = light_impact_range
+ orig_flash_range = flash_range
+ orig_flame_range = flame_range
+
+ if(!ignorecap && !("[epicenter.z]" in SSexplosion.zlevels_that_ignore_bombcap))
+ //Clamp all values
+ devastation_range = min(SSexplosion.devastation_cap, devastation_range)
+ heavy_impact_range = min(SSexplosion.heavy_cap, heavy_impact_range)
+ light_impact_range = min(SSexplosion.light_cap, light_impact_range)
+ flash_range = min(SSexplosion.flash_cap, flash_range)
+ flame_range = min(SSexplosion.flame_cap, flame_range)
+
+ //store this
+ devastation = devastation_range
+ heavy = heavy_impact_range
+ light = light_impact_range
+
+ extent = max(devastation_range, heavy_impact_range, light_impact_range, flame_range)
+
+ flash = flash_range
+ flame = flame_range
+
+ started_at = REALTIMEOFDAY
+ tick_started = world.time
+
+ gathered_turfs = list()
+ calculated_turfs = list()
+ unsafe_turfs = list()
+
+// Play sounds; we want sounds to be different depending on distance so we will manually do it ourselves.
+// Stereo users will also hear the direction of the explosion!
+
+// Calculate far explosion sound range. Only allow the sound effect for heavy/devastating explosions.
+// 3/7/14 will calculate to 80 + 35
+/proc/ExplosionSound(turf/epicenter, devastation_range, heavy_impact_range, extent)
+ var/far_dist = 0
+ far_dist += heavy_impact_range * 5
+ far_dist += devastation_range * 20
+
+ var/z0 = epicenter.z
+
+ var/frequency = get_rand_frequency()
+ var/ex_sound = get_sfx("explosion")
+ for(var/mob/M in GLOB.player_list)
+ // Double check for client
+ var/turf/M_turf = get_turf(M)
+ if(M_turf && M_turf.z == z0)
+ var/dist = get_dist(M_turf, epicenter)
+ // If inside the blast radius + world.view - 2
+ if(dist <= round(extent + world.view - 2, 1))
+ M.playsound_local(epicenter, ex_sound, 100, 1, frequency, falloff = 5)
+ // You hear a far explosion if you're outside the blast radius. Small bombs shouldn't be heard all over the station.
+ else if(dist <= far_dist)
+ var/far_volume = Clamp(far_dist, 30, 50) // Volume is based on explosion size and dist
+ far_volume += (dist <= far_dist * 0.5 ? 50 : 0) // add 50 volume if the mob is pretty close to the explosion
+ M.playsound_local(epicenter, 'sound/effects/explosionfar.ogg', far_volume, 1, frequency, falloff = 5)
+
+/datum/explosion/Destroy()
+ SSexplosion.explosions -= src
+ SSexplosion.logs -= src
+ LAZYCLEARLIST(gathered_turfs)
+ LAZYCLEARLIST(calculated_turfs)
+ LAZYCLEARLIST(unsafe_turfs)
+ return ..()
+
+/datum/controller/subsystem/explosion/proc/GatherTurfs(datum/explosion/E)
+ var/turf/epicenter = E.epicenter
+
+ var/x0 = epicenter.x
+ var/y0 = epicenter.y
+ var/z0 = epicenter.z
+
+ var/c_dist = E.gather_dist
+ var/dist = E.extent
+
+ var/list/L = E.gathered_turfs
+
+ if(!c_dist)
+ L += epicenter
+ ++c_dist
+
+ while( c_dist <= dist )
+ var/y = y0 + c_dist
+ var/x = x0 - c_dist + 1
+ for(x in x to x0 + c_dist)
+ var/turf/T = locate(x, y, z0)
+ if(T)
+ L += T
+
+ y = y0 + c_dist - 1
+ x = x0 + c_dist
+ for(y in y0 - c_dist to y)
+ var/turf/T = locate(x, y, z0)
+ if(T)
+ L += T
+
+ y = y0 - c_dist
+ x = x0 + c_dist - 1
+ for(x in x0 - c_dist to x)
+ var/turf/T = locate(x, y, z0)
+ if(T)
+ L += T
+
+ y = y0 - c_dist + 1
+ x = x0 - c_dist
+ for(y in y to y0 + c_dist)
+ var/turf/T = locate(x, y, z0)
+ if(T)
+ L += T
+ ++c_dist
+
+ if(MC_TICK_CHECK)
+ break
+
+ if(c_dist > dist)
+ E.turfs_processed = TRUE
+ return TRUE
+ else
+ E.gather_dist = c_dist
+ return FALSE
+
+/datum/controller/subsystem/explosion/proc/DensityCalculate(datum/explosion/E, done_gathering_turfs)
+ var/list/L = E.calculated_turfs
+ var/cut_to = 1
+ for(var/I in E.gathered_turfs) // we cache the explosion block rating of every turf in the explosion area
+ var/turf/T = I
+ ++cut_to
+
+ var/current_exp_block = T.density ? T.explosion_block : 0
+
+ for(var/obj/machinery/door/D in T)
+ if(D.density)
+ current_exp_block += D.explosion_block
+
+ for(var/obj/structure/window/W in T)
+ if(W.reinf && W.fulltile)
+ current_exp_block += W.explosion_block
+
+ for(var/obj/structure/blob/B in T)
+ current_exp_block += B.explosion_block
+
+ L[T] = current_exp_block
+
+ if(MC_TICK_CHECK)
+ E.gathered_turfs.Cut(1, cut_to)
+ return FALSE
+
+ E.gathered_turfs.Cut()
+ return done_gathering_turfs
+
+/datum/controller/subsystem/explosion/proc/ProcessExplosion(datum/explosion/E, done_calculating_turfs)
+ //cache shit for speed
+ var/id = E.explosion_id
+
+ var/list/cached_unsafe = E.unsafe_turfs
+ var/list/cached_exp_block = E.calculated_turfs
+ var/list/affected_turfs = cached_exp_block ? cached_exp_block : E.gathered_turfs
+
+ var/devastation_range = E.devastation
+ var/heavy_impact_range = E.heavy
+ var/light_impact_range = E.light
+
+ var/flame_range = E.flame
+ var/throw_range_max = E.extent
+
+ var/turf/epi = E.epicenter
+
+ var/x0 = epi.x
+ var/y0 = epi.y
+
+ var/cut_to = 1
+ for(var/TI in affected_turfs)
+ var/turf/T = TI
+ ++cut_to
+
+ var/init_dist = cheap_hypotenuse(T.x, T.y, x0, y0)
+ var/dist = init_dist
+
+ if(cached_exp_block)
+ var/turf/Trajectory = T
+ while(Trajectory != epi)
+ Trajectory = get_step_towards(Trajectory, epi)
+ dist += cached_exp_block[Trajectory]
+
+ var/flame_dist = dist < flame_range
+ var/throw_dist = dist
+
+ if(dist < devastation_range)
+ dist = 1
+ else if(dist < heavy_impact_range)
+ dist = 2
+ else if(dist < light_impact_range)
+ dist = 3
+ else
+ dist = 0
+
+ //------- EX_ACT AND TURF FIRES -------
+
+ if(flame_dist && prob(40) && !isspaceturf(T) && !T.density)
+ new /obj/effect/hotspot(T) //Mostly for ambience!
+
+ if(dist > 0)
+ T.explosion_level = max(T.explosion_level, dist) //let the bigger one have it
+ T.explosion_id = id
+ T.ex_act(dist)
+ cached_unsafe += T
+
+ //--- THROW ITEMS AROUND ---
+
+ var/throw_dir = get_dir(epi, T)
+ for(var/obj/item/I in T)
+ if(!I.anchored)
+ var/throw_range = rand(throw_dist, throw_range_max)
+ var/turf/throw_at = get_ranged_target_turf(I, throw_dir, throw_range)
+ I.throw_speed = 4 //Temporarily change their throw_speed for embedding purposes (Resets when it finishes throwing, regardless of hitting anything)
+ I.throw_at(throw_at, throw_range, 4)
+
+ if(MC_TICK_CHECK)
+ var/circumference = (PI * (init_dist + 4) * 2) //+4 to radius to prevent shit gaps
+ if(cached_unsafe.len > circumference) //only do this every revolution
+ for(var/Unexplode in cached_unsafe)
+ var/turf/UnexplodeT = Unexplode
+ UnexplodeT.explosion_level = 0
+ cached_unsafe.Cut()
+ done_calculating_turfs = FALSE
+ break
+
+ affected_turfs.Cut(1, cut_to)
+
+ if(!done_calculating_turfs)
+ return FALSE
+
+ //unfuck the shit
+ for(var/Unexplode in cached_unsafe)
+ var/turf/UnexplodeT = Unexplode
+ UnexplodeT.explosion_level = 0
+ cached_unsafe.Cut()
+
+ E.finished_at = REALTIMEOFDAY
+ E.tick_finished = world.time
+
+ return TRUE
+
+/client/proc/check_bomb_impacts()
+ set name = "Check Bomb Impact"
+ set category = "Debug"
+
+ var/newmode = alert("Use reactionary explosions?","Check Bomb Impact", "Yes", "No")
+ var/turf/epicenter = get_turf(mob)
+ if(!epicenter)
+ return
+
+ var/x0 = epicenter.x
+ var/y0 = epicenter.y
+
+ var/dev = 0
+ var/heavy = 0
+ var/light = 0
+ var/list/choices = list("Small Bomb","Medium Bomb","Big Bomb","Custom Bomb")
+ var/choice = input("Bomb Size?") in choices
+ switch(choice)
+ if(null)
+ return 0
+ if("Small Bomb")
+ dev = 1
+ heavy = 2
+ light = 3
+ if("Medium Bomb")
+ dev = 2
+ heavy = 3
+ light = 4
+ if("Big Bomb")
+ dev = 3
+ heavy = 5
+ light = 7
+ if("Custom Bomb")
+ dev = input("Devestation range (Tiles):") as num
+ heavy = input("Heavy impact range (Tiles):") as num
+ light = input("Light impact range (Tiles):") as num
+ else
+ return
+
+ var/datum/explosion/E = new(null, epicenter, dev, heavy, light, ignorecap = TRUE)
+
+ while(!SSexplosion.GatherTurfs(E))
+ stoplag()
+ var/list/turfs
+ if(newmode)
+ while(!SSexplosion.DensityCalculate(E, TRUE))
+ stoplag()
+ turfs = E.calculated_turfs.Copy()
+ else
+ turfs = E.gathered_turfs.Copy()
+
+ qdel(E)
+
+ for(var/I in turfs)
+ var/turf/T = I
+ var/dist = cheap_hypotenuse(T.x, T.y, x0, y0) + turfs[T]
+
+ if(dist < dev)
+ T.color = "red"
+ T.maptext = "Dev"
+ else if (dist < heavy)
+ T.color = "yellow"
+ T.maptext = "Heavy"
+ else if (dist < light)
+ T.color = "blue"
+ T.maptext = "Light"
+ CHECK_TICK
+
+ sleep(100)
+ for(var/I in turfs)
+ var/turf/T = I
+ T.color = null
+ T.maptext = null
diff --git a/code/game/objects/explosion.dm b/code/datums/explosion.dm
similarity index 52%
rename from code/game/objects/explosion.dm
rename to code/datums/explosion.dm
index 11079bf847..86ab021191 100644
--- a/code/game/objects/explosion.dm
+++ b/code/datums/explosion.dm
@@ -1,10 +1,48 @@
-/proc/explosion(turf/epicenter, devastation_range, heavy_impact_range, light_impact_range, flash_range, adminlog = 1, ignorecap = 0, flame_range, silent = 0, smoke = 1)
- set waitfor = 0
- src = null //so we don't abort once src is deleted
+#define EXPLOSION_THROW_SPEED 4
+
+GLOBAL_LIST_EMPTY(explosions)
+//Against my better judgement, I will return the explosion datum
+//If I see any GC errors for it I will find you
+//and I will gib you
+/proc/explosion(atom/epicenter, devastation_range, heavy_impact_range, light_impact_range, flash_range, adminlog = TRUE, ignorecap = FALSE, flame_range = 0 , silent = FALSE, smoke = FALSE)
+ return new /datum/explosion(epicenter, devastation_range, heavy_impact_range, light_impact_range, flash_range, adminlog, ignorecap, flame_range, silent, smoke)
+
+//This datum creates 3 async tasks
+//1 GatherSpiralTurfsProc runs spiral_range_turfs(tick_checked = TRUE) to populate the affected_turfs list
+//2 CaculateExplosionBlock adds the blockings to the cached_exp_block list
+//3 The main thread explodes the prepared turfs
+
+/datum/explosion
+ var/explosion_id
+ var/started_at
+ var/running = TRUE
+ var/stopped = 0 //This is the number of threads stopped !DOESN'T COUNT THREAD 2!
+ var/static/id_counter = 0
+
+#define EX_PREPROCESS_EXIT_CHECK \
+ if(!running) {\
+ stopped = 2;\
+ qdel(src);\
+ return;\
+ }
+
+#define EX_PREPROCESS_CHECK_TICK \
+ if(TICK_CHECK) {\
+ stoplag();\
+ EX_PREPROCESS_EXIT_CHECK\
+ }
+
+/datum/explosion/New(atom/epicenter, devastation_range, heavy_impact_range, light_impact_range, flash_range, adminlog, ignorecap, flame_range, silent, smoke)
+ set waitfor = FALSE
+
+ var/id = ++id_counter
+ explosion_id = id
+
epicenter = get_turf(epicenter)
if(!epicenter)
return
+ GLOB.explosions += src
if(isnull(flame_range))
flame_range = light_impact_range
if(isnull(flash_range))
@@ -30,14 +68,13 @@
//I would make this not ex_act the thing that triggered the explosion,
//but everything that explodes gives us their loc or a get_turf()
//and somethings expect us to ex_act them so they can qdel()
- sleep(1) //tldr, let the calling proc call qdel(src) before we explode
+ stoplag() //tldr, let the calling proc call qdel(src) before we explode
- var/static/explosionid = 1
- var/id = explosionid++
- var/start = world.timeofday
+ EX_PREPROCESS_EXIT_CHECK
+
+ started_at = REALTIMEOFDAY
var/max_range = max(devastation_range, heavy_impact_range, light_impact_range, flame_range)
- var/list/cached_exp_block = list()
if(adminlog)
message_admins("Explosion with size ([devastation_range], [heavy_impact_range], [light_impact_range], [flame_range]) in area: [get_area(epicenter)] [ADMIN_COORDJMP(epicenter)]")
@@ -53,23 +90,27 @@
far_dist += heavy_impact_range * 5
far_dist += devastation_range * 20
+ var/x0 = epicenter.x
+ var/y0 = epicenter.y
+ var/z0 = epicenter.z
+
if(!silent)
var/frequency = get_rand_frequency()
var/ex_sound = get_sfx("explosion")
for(var/mob/M in GLOB.player_list)
// Double check for client
- if(M && M.client)
- var/turf/M_turf = get_turf(M)
- if(M_turf && M_turf.z == epicenter.z)
- var/dist = get_dist(M_turf, epicenter)
- // If inside the blast radius + world.view - 2
- if(dist <= round(max_range + world.view - 2, 1))
- M.playsound_local(epicenter, ex_sound, 100, 1, frequency, falloff = 5)
- // You hear a far explosion if you're outside the blast radius. Small bombs shouldn't be heard all over the station.
- else if(dist <= far_dist)
- var/far_volume = Clamp(far_dist, 30, 50) // Volume is based on explosion size and dist
- far_volume += (dist <= far_dist * 0.5 ? 50 : 0) // add 50 volume if the mob is pretty close to the explosion
- M.playsound_local(epicenter, 'sound/effects/explosionfar.ogg', far_volume, 1, frequency, falloff = 5)
+ var/turf/M_turf = get_turf(M)
+ if(M_turf && M_turf.z == z0)
+ var/dist = get_dist(M_turf, epicenter)
+ // If inside the blast radius + world.view - 2
+ if(dist <= round(max_range + world.view - 2, 1))
+ M.playsound_local(epicenter, ex_sound, 100, 1, frequency, falloff = 5)
+ // You hear a far explosion if you're outside the blast radius. Small bombs shouldn't be heard all over the station.
+ else if(dist <= far_dist)
+ var/far_volume = Clamp(far_dist, 30, 50) // Volume is based on explosion size and dist
+ far_volume += (dist <= far_dist * 0.5 ? 50 : 0) // add 50 volume if the mob is pretty close to the explosion
+ M.playsound_local(epicenter, 'sound/effects/explosionfar.ogg', far_volume, 1, frequency, falloff = 5)
+ EX_PREPROCESS_CHECK_TICK
//postpone processing for a bit
var/postponeCycles = max(round(devastation_range/8),1)
@@ -77,66 +118,52 @@
SSmachines.postpone(postponeCycles)
if(heavy_impact_range > 1)
+ var/datum/effect_system/explosion/E
if(smoke)
- var/datum/effect_system/explosion/smoke/E = new/datum/effect_system/explosion/smoke()
- E.set_up(epicenter)
- E.start()
+ E = new /datum/effect_system/explosion/smoke
else
- var/datum/effect_system/explosion/E = new/datum/effect_system/explosion()
- E.set_up(epicenter)
- E.start()
+ E = new
+ E.set_up(epicenter)
+ E.start()
- var/x0 = epicenter.x
- var/y0 = epicenter.y
- var/z0 = epicenter.z
-
- var/list/affected_turfs = spiral_range_turfs(max_range, epicenter)
-
- if(config.reactionary_explosions)
- for(var/turf/T in affected_turfs) // we cache the explosion block rating of every turf in the explosion area
- cached_exp_block[T] = 0
- if(T.density && T.explosion_block)
- cached_exp_block[T] += T.explosion_block
-
- for(var/obj/machinery/door/D in T)
- if(D.density && D.explosion_block)
- cached_exp_block[T] += D.explosion_block
-
- for(var/obj/structure/window/W in T)
- if(W.reinf && W.fulltile)
- cached_exp_block[T] += W.explosion_block
-
- for(var/obj/structure/blob/B in T)
- cached_exp_block[T] += B.explosion_block
- CHECK_TICK
+ EX_PREPROCESS_CHECK_TICK
//flash mobs
if(flash_range)
for(var/mob/living/L in viewers(flash_range, epicenter))
L.flash_act()
- CHECK_TICK
+ EX_PREPROCESS_CHECK_TICK
var/list/exploded_this_tick = list() //open turfs that need to be blocked off while we sleep
- for(var/turf/T in affected_turfs)
+ var/list/affected_turfs = GatherSpiralTurfs(max_range, epicenter)
- if (!T)
- continue
+ var/reactionary = config.reactionary_explosions
+ var/list/cached_exp_block
+
+ if(reactionary)
+ cached_exp_block = CaculateExplosionBlock(affected_turfs)
+
+ //lists are guaranteed to contain at least 1 turf at this point
+
+ var/iteration = 0
+ var/affTurfLen = affected_turfs.len
+ var/expBlockLen = cached_exp_block.len
+ for(var/TI in affected_turfs)
+ var/turf/T = TI
+ ++iteration
var/init_dist = cheap_hypotenuse(T.x, T.y, x0, y0)
var/dist = init_dist
- if(config.reactionary_explosions)
+ if(reactionary)
var/turf/Trajectory = T
while(Trajectory != epicenter)
Trajectory = get_step_towards(Trajectory, epicenter)
dist += cached_exp_block[Trajectory]
- var/flame_dist = 0
+ var/flame_dist = dist < flame_range
var/throw_dist = dist
- if(dist < flame_range)
- flame_dist = 1
-
if(dist < devastation_range)
dist = 1
else if(dist < heavy_impact_range)
@@ -148,27 +175,61 @@
//------- EX_ACT AND TURF FIRES -------
- if(T)
- if(flame_dist && prob(40) && !isspaceturf(T) && !T.density)
- new /obj/effect/hotspot(T) //Mostly for ambience!
- if(dist > 0)
- T.explosion_level = max(T.explosion_level, dist) //let the bigger one have it
- T.explosion_id = id
- T.ex_act(dist)
- exploded_this_tick += T
+ if(flame_dist && prob(40) && !isspaceturf(T) && !T.density)
+ new /obj/effect/hotspot(T) //Mostly for ambience!
+
+ if(dist > 0)
+ T.explosion_level = max(T.explosion_level, dist) //let the bigger one have it
+ T.explosion_id = id
+ T.ex_act(dist)
+ exploded_this_tick += T
//--- THROW ITEMS AROUND ---
var/throw_dir = get_dir(epicenter,T)
for(var/obj/item/I in T)
- if(I && !I.anchored)
+ if(!I.anchored)
var/throw_range = rand(throw_dist, max_range)
var/turf/throw_at = get_ranged_target_turf(I, throw_dir, throw_range)
- I.throw_speed = 4 //Temporarily change their throw_speed for embedding purposes (Reset when it finishes throwing, regardless of hitting anything)
- I.throw_at(throw_at, throw_range, I.throw_speed)
+ I.throw_speed = EXPLOSION_THROW_SPEED //Temporarily change their throw_speed for embedding purposes (Reset when it finishes throwing, regardless of hitting anything)
+ I.throw_at(throw_at, throw_range, EXPLOSION_THROW_SPEED)
- if(TICK_CHECK)
+ //wait for the lists to repop
+ var/break_condition
+ if(reactionary)
+ //If we've caught up to the density checker thread and there are no more turfs to process
+ break_condition = iteration == expBlockLen && iteration < affTurfLen
+ else
+ //If we've caught up to the turf gathering thread and it's still running
+ break_condition = iteration == affTurfLen && !stopped
+
+ if(break_condition || TICK_CHECK)
stoplag()
+
+ if(!running)
+ break
+
+ //update the trackers
+ affTurfLen = affected_turfs.len
+ expBlockLen = cached_exp_block.len
+
+ if(break_condition)
+ if(reactionary)
+ //until there are more block checked turfs than what we are currently at
+ //or the explosion has stopped
+ UNTIL(iteration < affTurfLen || !running)
+ else
+ //until there are more gathered turfs than what we are currently at
+ //or there are no more turfs to gather/the explosion has stopped
+ UNTIL(iteration < expBlockLen || stopped)
+
+ if(!running)
+ break
+
+ //update the trackers
+ affTurfLen = affected_turfs.len
+ expBlockLen = cached_exp_block.len
+
var/circumference = (PI * (init_dist + 4) * 2) //+4 to radius to prevent shit gaps
if(exploded_this_tick.len > circumference) //only do this every revolution
for(var/Unexplode in exploded_this_tick)
@@ -182,24 +243,67 @@
UnexplodeT.explosion_level = 0
exploded_this_tick.Cut()
- var/took = (world.timeofday-start)/10
- //You need to press the DebugGame verb to see these now....they were getting annoying and we've collected a fair bit of data. Just -test- changes to explosion code using this please so we can compare
+ var/took = (REALTIMEOFDAY - started_at) / 10
+
+ //You need to press the DebugGame verb to see these now....they were getting annoying and we've collected a fair bit of data. Just -test- changes to explosion code using this please so we can compare
if(GLOB.Debug2)
log_world("## DEBUG: Explosion([x0],[y0],[z0])(d[devastation_range],h[heavy_impact_range],l[light_impact_range]): Took [took] seconds.")
- //Machines which report explosions.
- for(var/array in GLOB.doppler_arrays)
- var/obj/machinery/doppler_array/A = array
- A.sense_explosion(epicenter,devastation_range,heavy_impact_range,light_impact_range,took,orig_dev_range,orig_heavy_range,orig_light_range)
+ if(!stopped) //if we aren't in a hurry
+ //Machines which report explosions.
+ for(var/array in GLOB.doppler_arrays)
+ var/obj/machinery/doppler_array/A = array
+ A.sense_explosion(epicenter, devastation_range, heavy_impact_range, light_impact_range, took,orig_dev_range, orig_heavy_range, orig_light_range)
- return 1
+ ++stopped
+ qdel(src)
+#undef EX_PREPROCESS_EXIT_CHECK
+#undef EX_PREPROCESS_CHECK_TICK
+//asyncly populate the affected_turfs list
+/datum/explosion/proc/GatherSpiralTurfs(range, turf/epicenter)
+ set waitfor = FALSE
+ . = list()
+ spiral_range_turfs(range, epicenter, outlist = ., tick_checked = TRUE)
+ ++stopped
-/proc/secondaryexplosion(turf/epicenter, range)
- for(var/turf/tile in spiral_range_turfs(range, epicenter))
- tile.ex_act(2)
+/datum/explosion/proc/CaculateExplosionBlock(list/affected_turfs)
+ set waitfor = FALSE
+ . = list()
+ var/processed = 0
+ while(!stopped && running)
+ var/I
+ for(I in (processed + 1) to affected_turfs.len) // we cache the explosion block rating of every turf in the explosion area
+ var/turf/T = affected_turfs[I]
+ var/current_exp_block = T.density ? T.explosion_block : 0
+
+ for(var/obj/machinery/door/D in T)
+ if(D.density)
+ current_exp_block += D.explosion_block
+
+ for(var/obj/structure/window/W in T)
+ if(W.reinf && W.fulltile)
+ current_exp_block += W.explosion_block
+
+ for(var/obj/structure/blob/B in T)
+ current_exp_block += B.explosion_block
+
+ .[T] = current_exp_block
+
+ if(TICK_CHECK)
+ break
+
+ processed = I
+ stoplag()
+
+/datum/explosion/Destroy()
+ running = FALSE
+ if(stopped < 2) //wait for main thread and spiral_range thread
+ return QDEL_HINT_IWILLGC
+ GLOB.explosions -= src
+ return ..()
/client/proc/check_bomb_impacts()
set name = "Check Bomb Impact"
diff --git a/code/game/atoms.dm b/code/game/atoms.dm
index 65d4cf1449..d7422429ff 100644
--- a/code/game/atoms.dm
+++ b/code/game/atoms.dm
@@ -28,8 +28,8 @@
var/list/our_overlays //our local copy of (non-priority) overlays without byond magic. Use procs in SSoverlays to manipulate
var/list/priority_overlays //overlays that should remain on top and not normally removed when using cut_overlay functions, like c4.
- var/datum/proximity_monitor/proximity_monitor
-
+ var/datum/proximity_monitor/proximity_monitor
+
/atom/New(loc, ...)
//atom creation method that preloads variables at creation
if(GLOB.use_preloader && (src.type == GLOB._preloader.target_path))//in case the instanciated atom is creating other atoms in New()
@@ -39,21 +39,21 @@
var/do_initialize = SSatoms.initialized
if(do_initialize > INITIALIZATION_INSSATOMS)
- args[1] = do_initialize == INITIALIZATION_INNEW_MAPLOAD
- if(SSatoms.InitAtom(src, args))
- //we were deleted
- return
-
- var/list/created = SSatoms.created_atoms
- if(created)
- created += src
+ args[1] = do_initialize == INITIALIZATION_INNEW_MAPLOAD
+ if(SSatoms.InitAtom(src, args))
+ //we were deleted
+ return
+
+ var/list/created = SSatoms.created_atoms
+ if(created)
+ created += src
//Called after New if the map is being loaded. mapload = TRUE
//Called from base of New if the map is being loaded. mapload = FALSE
-//This base must be called or derivatives must set initialized to TRUE
-//must not sleep
+//This base must be called or derivatives must set initialized to TRUE
+//must not sleep
//Other parameters are passed from New (excluding loc), this does not happen if mapload is TRUE
-//Must return an Initialize hint. Defined in __DEFINES/subsystems.dm
+//Must return an Initialize hint. Defined in __DEFINES/subsystems.dm
//Note: the following functions don't call the base for optimization and must copypasta:
// /turf/Initialize
@@ -76,23 +76,23 @@
if (opacity && isturf(loc))
var/turf/T = loc
T.has_opaque_atom = TRUE // No need to recalculate it in this case, it's guaranteed to be on afterwards anyways.
- return INITIALIZE_HINT_NORMAL
+ return INITIALIZE_HINT_NORMAL
-//called if Initialize returns INITIALIZE_HINT_LATELOAD
-//This version shouldn't be called
-/atom/proc/LateInitialize()
- var/static/list/warned_types = list()
- if(!warned_types[type])
- WARNING("Old style LateInitialize behaviour detected in [type]!")
- warned_types[type] = TRUE
- Initialize(FALSE)
+//called if Initialize returns INITIALIZE_HINT_LATELOAD
+//This version shouldn't be called
+/atom/proc/LateInitialize()
+ var/static/list/warned_types = list()
+ if(!warned_types[type])
+ WARNING("Old style LateInitialize behaviour detected in [type]!")
+ warned_types[type] = TRUE
+ Initialize(FALSE)
/atom/Destroy()
if(alternate_appearances)
- for(var/K in alternate_appearances)
- var/datum/atom_hud/alternate_appearance/AA = alternate_appearances[K]
- AA.remove_from_hud(src)
-
+ for(var/K in alternate_appearances)
+ var/datum/atom_hud/alternate_appearance/AA = alternate_appearances[K]
+ AA.remove_from_hud(src)
+
if(reagents)
qdel(reagents)
@@ -100,8 +100,8 @@
LAZYCLEARLIST(priority_overlays)
//SSoverlays.processing -= src //we COULD do this, but it's better to just let it fall out of the processing queue
- QDEL_NULL(light)
-
+ QDEL_NULL(light)
+
return ..()
/atom/proc/handle_ricochet(obj/item/projectile/P)
@@ -277,7 +277,6 @@
return
/atom/proc/ex_act(severity, target)
- set waitfor = FALSE
contents_explosion(severity, target)
/atom/proc/blob_act(obj/structure/blob/B)
@@ -509,10 +508,10 @@ GLOBAL_LIST_EMPTY(blood_splatter_icons)
/atom/proc/mech_melee_attack(obj/mecha/M)
return
-//If a mob logouts/logins in side of an object you can use this proc
-/atom/proc/on_log(login)
- if(loc)
- loc.on_log(login)
+//If a mob logouts/logins in side of an object you can use this proc
+/atom/proc/on_log(login)
+ if(loc)
+ loc.on_log(login)
/*
diff --git a/code/game/machinery/doppler_array.dm b/code/game/machinery/doppler_array.dm
index 48dc35da4b..4053e9755c 100644
--- a/code/game/machinery/doppler_array.dm
+++ b/code/game/machinery/doppler_array.dm
@@ -1,5 +1,5 @@
-GLOBAL_LIST_EMPTY(doppler_arrays)
-
+GLOBAL_LIST_EMPTY(doppler_arrays)
+
/obj/machinery/doppler_array
name = "tachyon-doppler array"
desc = "A highly precise directional sensor array which measures the release of quants from decaying tachyons. The doppler shifting of the mirror-image formed by these quants can reveal the size, location and temporal affects of energetic disturbances within a large radius ahead of the array.\nAlt-click to rotate it clockwise."
@@ -13,10 +13,10 @@ GLOBAL_LIST_EMPTY(doppler_arrays)
/obj/machinery/doppler_array/New()
..()
- GLOB.doppler_arrays += src
+ GLOB.doppler_arrays += src
/obj/machinery/doppler_array/Destroy()
- GLOB.doppler_arrays -= src
+ GLOB.doppler_arrays -= src
return ..()
/obj/machinery/doppler_array/process()
diff --git a/code/game/mecha/mecha.dm b/code/game/mecha/mecha.dm
index 66cc6be38a..1e6fd57b1d 100644
--- a/code/game/mecha/mecha.dm
+++ b/code/game/mecha/mecha.dm
@@ -154,7 +154,7 @@
M.forceMove(loc)
if(prob(30))
- explosion(get_turf(loc), 0, 0, 1, 3)
+ explosion(get_turf(loc), 0, 0, 1, 3)
if(wreckage)
var/obj/structure/mecha_wreckage/WR = new wreckage(loc, AI)
diff --git a/code/game/objects/effects/mines.dm b/code/game/objects/effects/mines.dm
index 46c2306a79..74459cc85d 100644
--- a/code/game/objects/effects/mines.dm
+++ b/code/game/objects/effects/mines.dm
@@ -39,7 +39,7 @@
var/range_flash = 3
/obj/effect/mine/explosive/mineEffect(mob/victim)
- explosion(loc, range_devastation, range_heavy, range_light, range_flash)
+ explosion(loc, range_devastation, range_heavy, range_light, range_flash)
/obj/effect/mine/stun
diff --git a/code/game/objects/items/devices/PDA/PDA.dm b/code/game/objects/items/devices/PDA/PDA.dm
index f3c32d3d68..c86d0dff85 100644
--- a/code/game/objects/items/devices/PDA/PDA.dm
+++ b/code/game/objects/items/devices/PDA/PDA.dm
@@ -897,9 +897,9 @@ GLOBAL_LIST_EMPTY(PDAs)
if(T)
T.hotspot_expose(700,125)
if(istype(cartridge, /obj/item/weapon/cartridge/syndicate))
- explosion(T, -1, 1, 3, 4)
+ explosion(T, -1, 1, 3, 4)
else
- explosion(T, -1, -1, 2, 3)
+ explosion(T, -1, -1, 2, 3)
qdel(src)
return
diff --git a/code/game/objects/items/devices/powersink.dm b/code/game/objects/items/devices/powersink.dm
index e03c85c09a..a4e1a45814 100644
--- a/code/game/objects/items/devices/powersink.dm
+++ b/code/game/objects/items/devices/powersink.dm
@@ -141,5 +141,5 @@
if(power_drained >= max_power)
STOP_PROCESSING(SSobj, src)
- explosion(src.loc, 4,8,16,32)
+ explosion(src.loc, 4,8,16,32)
qdel(src)
diff --git a/code/game/objects/items/weapons/grenades/ghettobomb.dm b/code/game/objects/items/weapons/grenades/ghettobomb.dm
index f4d573e3ba..76f3c8ac73 100644
--- a/code/game/objects/items/weapons/grenades/ghettobomb.dm
+++ b/code/game/objects/items/weapons/grenades/ghettobomb.dm
@@ -59,7 +59,7 @@
/obj/item/weapon/grenade/iedcasing/prime() //Blowing that can up
update_mob()
- explosion(src.loc,-1,-1,2, flame_range = 4) // small explosion, plus a very large fireball.
+ explosion(src.loc,-1,-1,2, flame_range = 4) // small explosion, plus a very large fireball.
qdel(src)
/obj/item/weapon/grenade/iedcasing/examine(mob/user)
diff --git a/code/game/objects/items/weapons/grenades/syndieminibomb.dm b/code/game/objects/items/weapons/grenades/syndieminibomb.dm
index 67b0dcddeb..6b260d366a 100644
--- a/code/game/objects/items/weapons/grenades/syndieminibomb.dm
+++ b/code/game/objects/items/weapons/grenades/syndieminibomb.dm
@@ -9,7 +9,7 @@
/obj/item/weapon/grenade/syndieminibomb/prime()
update_mob()
- explosion(src.loc,1,2,4,flame_range = 2)
+ explosion(src.loc,1,2,4,flame_range = 2)
qdel(src)
/obj/item/weapon/grenade/syndieminibomb/concussion
@@ -20,7 +20,7 @@
/obj/item/weapon/grenade/syndieminibomb/concussion/prime()
update_mob()
- explosion(src.loc,0,2,3,flame_range = 3)
+ explosion(src.loc,0,2,3,flame_range = 3)
qdel(src)
/obj/item/weapon/grenade/syndieminibomb/concussion/frag
diff --git a/code/game/objects/items/weapons/storage/backpack.dm b/code/game/objects/items/weapons/storage/backpack.dm
index 0fd70e7ac3..ed502e17cd 100644
--- a/code/game/objects/items/weapons/storage/backpack.dm
+++ b/code/game/objects/items/weapons/storage/backpack.dm
@@ -83,7 +83,7 @@
/obj/item/weapon/storage/backpack/holding/singularity_act(current_size)
var/dist = max((current_size - 2),1)
- explosion(src.loc,(dist),(dist*2),(dist*4))
+ explosion(src.loc,(dist),(dist*2),(dist*4))
return
diff --git a/code/game/objects/structures/crates_lockers/crates/secure.dm b/code/game/objects/structures/crates_lockers/crates/secure.dm
index 603dce4358..75096209f5 100644
--- a/code/game/objects/structures/crates_lockers/crates/secure.dm
+++ b/code/game/objects/structures/crates_lockers/crates/secure.dm
@@ -38,7 +38,7 @@
log_game("[key_name(user)] has detonated [src.name].")
for(var/atom/movable/AM in src)
qdel(AM)
- explosion(get_turf(src), 0, 1, 5, 5)
+ explosion(get_turf(src), 0, 1, 5, 5)
qdel(src)
/obj/structure/closet/crate/secure/weapon
diff --git a/code/modules/awaymissions/bluespaceartillery.dm b/code/modules/awaymissions/bluespaceartillery.dm
index e3aeec62cd..2e7ce98510 100644
--- a/code/modules/awaymissions/bluespaceartillery.dm
+++ b/code/modules/awaymissions/bluespaceartillery.dm
@@ -53,7 +53,7 @@
for(var/turf/T in get_area_turfs(thearea.type))
L+=T
var/loc = pick(L)
- explosion(loc,explosiondev,explosionmed,explosionlight)
+ explosion(loc,explosiondev,explosionmed,explosionlight)
reload = 0
/*/mob/proc/openfire()
diff --git a/code/modules/awaymissions/mission_code/wildwest.dm b/code/modules/awaymissions/mission_code/wildwest.dm
index 5847b8de8e..395344ce4c 100644
--- a/code/modules/awaymissions/mission_code/wildwest.dm
+++ b/code/modules/awaymissions/mission_code/wildwest.dm
@@ -107,7 +107,7 @@
var/datum/effect_system/spark_spread/s = new /datum/effect_system/spark_spread
s.set_up(3, 1, src)
s.start()
- explosion(M, 1, 0, 0, 0)
+ explosion(M, 1, 0, 0, 0)
qdel(src)
/////For the Wishgranter///////////
diff --git a/code/modules/events/brand_intelligence.dm b/code/modules/events/brand_intelligence.dm
index cf7b12b139..cb07cdfd9e 100644
--- a/code/modules/events/brand_intelligence.dm
+++ b/code/modules/events/brand_intelligence.dm
@@ -57,7 +57,7 @@
M.speak = rampant_speeches.Copy()
M.speak_chance = 7
else
- explosion(upriser.loc, -1, 1, 2, 4, 0)
+ explosion(upriser.loc, -1, 1, 2, 4, 0)
qdel(upriser)
kill()
diff --git a/code/modules/events/processor_overload.dm b/code/modules/events/processor_overload.dm
index e0673cb741..329e887379 100644
--- a/code/modules/events/processor_overload.dm
+++ b/code/modules/events/processor_overload.dm
@@ -32,7 +32,7 @@
var/obj/machinery/telecomms/processor/P = T
if(prob(10))
// Damage the surrounding area to indicate that it popped
- explosion(get_turf(P), 0, 0, 2)
+ explosion(get_turf(P), 0, 0, 2)
// Only a level 1 explosion actually damages the machine
// at all
P.ex_act(1)
diff --git a/code/modules/mining/ores_coins.dm b/code/modules/mining/ores_coins.dm
index b1ba6680c2..9a9fefac03 100644
--- a/code/modules/mining/ores_coins.dm
+++ b/code/modules/mining/ores_coins.dm
@@ -263,11 +263,11 @@
spawn(det_time)
if(primed)
if(quality == 3)
- explosion(src.loc,2,4,9,adminlog = notify_admins)
+ explosion(src.loc,2,4,9,adminlog = notify_admins)
if(quality == 2)
- explosion(src.loc,1,2,5,adminlog = notify_admins)
+ explosion(src.loc,1,2,5,adminlog = notify_admins)
if(quality == 1)
- explosion(src.loc,-1,1,3,adminlog = notify_admins)
+ explosion(src.loc,-1,1,3,adminlog = notify_admins)
qdel(src)
/obj/item/weapon/ore/Initialize()
diff --git a/code/modules/mob/living/silicon/ai/death.dm b/code/modules/mob/living/silicon/ai/death.dm
index c78084335f..d21f0a221c 100644
--- a/code/modules/mob/living/silicon/ai/death.dm
+++ b/code/modules/mob/living/silicon/ai/death.dm
@@ -23,7 +23,7 @@
if(explosive)
spawn(10)
- explosion(src.loc, 3, 6, 12, 15)
+ explosion(src.loc, 3, 6, 12, 15)
for(var/obj/machinery/ai_status_display/O in world) //change status
if(src.key)
diff --git a/code/modules/power/antimatter/containment_jar.dm b/code/modules/power/antimatter/containment_jar.dm
index 0d2be23114..73fd2af580 100644
--- a/code/modules/power/antimatter/containment_jar.dm
+++ b/code/modules/power/antimatter/containment_jar.dm
@@ -18,12 +18,12 @@
/obj/item/weapon/am_containment/ex_act(severity, target)
switch(severity)
if(1)
- explosion(get_turf(src), 1, 2, 3, 5)//Should likely be larger but this works fine for now I guess
+ explosion(get_turf(src), 1, 2, 3, 5)//Should likely be larger but this works fine for now I guess
if(src)
qdel(src)
if(2)
if(prob((fuel/10)-stability))
- explosion(get_turf(src), 1, 2, 3, 5)
+ explosion(get_turf(src), 1, 2, 3, 5)
if(src)
qdel(src)
return
diff --git a/code/modules/power/antimatter/control.dm b/code/modules/power/antimatter/control.dm
index 647f838311..a1e448d282 100644
--- a/code/modules/power/antimatter/control.dm
+++ b/code/modules/power/antimatter/control.dm
@@ -46,7 +46,7 @@
/obj/machinery/power/am_control_unit/process()
if(exploding)
- explosion(get_turf(src),8,12,18,12)
+ explosion(get_turf(src),8,12,18,12)
if(src)
qdel(src)
diff --git a/code/modules/power/cell.dm b/code/modules/power/cell.dm
index 64d4077a12..a4b994e0cf 100644
--- a/code/modules/power/cell.dm
+++ b/code/modules/power/cell.dm
@@ -123,7 +123,7 @@
corrupt()
return
//explosion(T, 0, 1, 2, 2)
- explosion(T, devastation_range, heavy_impact_range, light_impact_range, flash_range)
+ explosion(T, devastation_range, heavy_impact_range, light_impact_range, flash_range)
qdel(src)
/obj/item/weapon/stock_parts/cell/proc/corrupt()
diff --git a/code/modules/power/port_gen.dm b/code/modules/power/port_gen.dm
index c02c13caf1..f1f251338e 100644
--- a/code/modules/power/port_gen.dm
+++ b/code/modules/power/port_gen.dm
@@ -167,7 +167,7 @@
src.updateDialog()
/obj/machinery/power/port_gen/pacman/proc/overheat()
- explosion(src.loc, 2, 5, 2, -1)
+ explosion(src.loc, 2, 5, 2, -1)
/obj/machinery/power/port_gen/pacman/attackby(obj/item/O, mob/user, params)
if(istype(O, sheet_path))
@@ -294,7 +294,7 @@
board_path = /obj/item/weapon/circuitboard/machine/pacman/super
/obj/machinery/power/port_gen/pacman/super/overheat()
- explosion(src.loc, 3, 3, 3, -1)
+ explosion(src.loc, 3, 3, 3, -1)
/obj/machinery/power/port_gen/pacman/mrs
name = "\improper M.R.S.P.A.C.M.A.N.-type portable generator"
@@ -305,4 +305,4 @@
board_path = /obj/item/weapon/circuitboard/machine/pacman/mrs
/obj/machinery/power/port_gen/pacman/mrs/overheat()
- explosion(src.loc, 4, 4, 4, -1)
+ explosion(src.loc, 4, 4, 4, -1)
diff --git a/code/modules/projectiles/guns/magic/wand.dm b/code/modules/projectiles/guns/magic/wand.dm
index 247273e3f4..dfc6351c3c 100644
--- a/code/modules/projectiles/guns/magic/wand.dm
+++ b/code/modules/projectiles/guns/magic/wand.dm
@@ -166,5 +166,5 @@
/obj/item/weapon/gun/magic/wand/fireball/zap_self(mob/living/user)
..()
- explosion(user.loc, -1, 0, 2, 3, 0, flame_range = 2)
+ explosion(user.loc, -1, 0, 2, 3, 0, flame_range = 2)
charges--
\ No newline at end of file
diff --git a/code/modules/projectiles/projectile/bullets.dm b/code/modules/projectiles/projectile/bullets.dm
index 0594c17469..5ffebf33b3 100644
--- a/code/modules/projectiles/projectile/bullets.dm
+++ b/code/modules/projectiles/projectile/bullets.dm
@@ -61,10 +61,10 @@
/obj/item/projectile/bullet/pellet/overload/on_hit(atom/target, blocked = 0)
..()
- explosion(target, 0, 0, 2)
+ explosion(target, 0, 0, 2)
/obj/item/projectile/bullet/pellet/overload/on_range()
- explosion(src, 0, 0, 2)
+ explosion(src, 0, 0, 2)
do_sparks(3, TRUE, src)
..()
diff --git a/code/modules/reagents/reagent_dispenser.dm b/code/modules/reagents/reagent_dispenser.dm
index 1844dc53ab..be13516d3c 100644
--- a/code/modules/reagents/reagent_dispenser.dm
+++ b/code/modules/reagents/reagent_dispenser.dm
@@ -66,7 +66,7 @@
reagent_id = "welding_fuel"
/obj/structure/reagent_dispensers/fueltank/boom()
- explosion(get_turf(src), 0, 1, 5, flame_range = 5)
+ explosion(get_turf(src), 0, 1, 5, flame_range = 5)
qdel(src)
/obj/structure/reagent_dispensers/fueltank/blob_act(obj/structure/blob/B)
@@ -165,7 +165,7 @@
reagent_id = "beer"
/obj/structure/reagent_dispensers/beerkeg/blob_act(obj/structure/blob/B)
- explosion(src.loc,0,3,5,7,10)
+ explosion(src.loc,0,3,5,7,10)
if(!QDELETED(src))
qdel(src)
diff --git a/code/modules/research/experimentor.dm b/code/modules/research/experimentor.dm
index 8db05a0c4f..fa58de0964 100644
--- a/code/modules/research/experimentor.dm
+++ b/code/modules/research/experimentor.dm
@@ -683,7 +683,7 @@
spawn(rand(35,100))
if(src.loc == user)
visible_message("The [src]'s top opens, releasing a powerful blast!")
- explosion(user.loc, -1, rand(1,5), rand(1,5), rand(1,5), rand(1,5), flame_range = 2)
+ explosion(user.loc, -1, rand(1,5), rand(1,5), rand(1,5), rand(1,5), flame_range = 2)
warn_admins(user, "Explosion")
qdel(src) //Comment this line to produce a light grenade (the bomb that keeps on exploding when used)!!
diff --git a/code/modules/spells/spell_types/explosion.dm b/code/modules/spells/spell_types/explosion.dm
index a19a9582ba..443546d12f 100644
--- a/code/modules/spells/spell_types/explosion.dm
+++ b/code/modules/spells/spell_types/explosion.dm
@@ -10,6 +10,6 @@
/obj/effect/proc_holder/spell/targeted/explosion/cast(list/targets,mob/user = usr)
for(var/mob/living/target in targets)
- explosion(target.loc,ex_severe,ex_heavy,ex_light,ex_flash)
+ explosion(target.loc,ex_severe,ex_heavy,ex_light,ex_flash)
return
\ No newline at end of file
diff --git a/tgstation.dme b/tgstation.dme
index 73383cbebd..050e661dc5 100644
--- a/tgstation.dme
+++ b/tgstation.dme
@@ -245,6 +245,7 @@
#include "code\datums\dna.dm"
#include "code\datums\dog_fashion.dm"
#include "code\datums\emotes.dm"
+#include "code\datums\explosion.dm"
#include "code\datums\forced_movement.dm"
#include "code\datums\holocall.dm"
#include "code\datums\hud.dm"
@@ -686,7 +687,6 @@
#include "code\game\mecha\working\working.dm"
#include "code\game\objects\buckling.dm"
#include "code\game\objects\empulse.dm"
-#include "code\game\objects\explosion.dm"
#include "code\game\objects\items.dm"
#include "code\game\objects\obj_defense.dm"
#include "code\game\objects\objs.dm"