Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions code/__HELPERS/unsorted.dm
Original file line number Diff line number Diff line change
Expand Up @@ -1588,6 +1588,7 @@ GLOBAL_DATUM_INIT(dview_mob, /mob/dview, new)

//gives us the stack trace from CRASH() without ending the current proc.
/proc/stack_trace(msg)
message_admins(msg)
CRASH(msg)

// \ref behaviour got changed in 512 so this is necesary to replicate old behaviour.
Expand Down
32 changes: 14 additions & 18 deletions code/datums/autocells/auto_cell.dm
Original file line number Diff line number Diff line change
Expand Up @@ -21,20 +21,19 @@
// This affects what neighbors you'll get passed in update_state()
var/neighbor_type = NEIGHBORS_CARDINAL

/datum/automata_cell/New(turf/T)
/datum/automata_cell/New(turf/location)
..()

if(!istype(T))
if(!isturf(location))
qdel(src)
return

// Attempt to merge the two cells if they end up in the same turf
var/datum/automata_cell/C = T.get_cell(type)
if(C && merge(C))
qdel(src)
return
// Attempt to merge two cells if they end up in the same turf
var/datum/automata_cell/existing_cell = location.get_cell(type)
if(!merge(existing_cell))
return // We didn't survive

in_turf = T
in_turf = location
LAZYADD(in_turf.autocells, src)

GLOB.cellauto_cells += src
Expand All @@ -44,9 +43,8 @@
/datum/automata_cell/Destroy()
. = ..()

if(!QDELETED(in_turf))
LAZYREMOVE(in_turf.autocells, src)
in_turf = null
LAZYREMOVE(in_turf?.autocells, src)
in_turf = null

GLOB.cellauto_cells -= src

Expand All @@ -65,17 +63,15 @@
if(QDELETED(new_turf))
return

if(!QDELETED(in_turf))
LAZYREMOVE(in_turf.autocells, src)
in_turf = null
LAZYREMOVE(in_turf?.autocells, src)

in_turf = new_turf
LAZYADD(in_turf.autocells, src)

// Use this proc to merge this cell with another one if the other cell enters the same turf
// Return TRUE if this cell should survive the merge (the other one will die/be qdeleted)
// Return FALSE if this cell should die and be replaced by the other cell
/datum/automata_cell/proc/merge(datum/automata_cell/other_cell)
/// Use this proc to merge this cell with another one if the other cell enters the same turf
/// Returns TRUE if this cell should survive the merge (the other one will die/be qdeleted)
/// Returns FALSE if this cell died and is replaced by the other cell
/datum/automata_cell/proc/merge(datum/automata_cell/other)
return TRUE

// Returns a list of neighboring cells
Expand Down
60 changes: 37 additions & 23 deletions code/datums/autocells/explosion.dm
Original file line number Diff line number Diff line change
Expand Up @@ -79,20 +79,31 @@
/datum/automata_cell/explosion/death()
if(shockwave)
qdel(shockwave)
exploded_atoms.Cut()

/datum/automata_cell/explosion/propagate(dir)
var/datum/automata_cell/explosion/new_cell = ..()
new_cell?.exploded_atoms += exploded_atoms
return new_cell

// Attempts to merge explosions. Will compare directions to determine effects on power.
// If the other explosion is traveling in the same direction, the explosion is amplified.
// If not, it's weakened
// Returns TRUE if this explosion survived.
/datum/automata_cell/explosion/merge(datum/automata_cell/explosion/other)
if(QDELETED(other))
return TRUE

// Compare directions. If the other explosion is traveling in the same direction,
// the explosion is amplified. If not, it's weakened
/datum/automata_cell/explosion/merge(datum/automata_cell/explosion/E)
// Non-merging explosions take priority
if(!should_merge)
if(!should_merge || !other.should_merge)
return TRUE

// The strongest of the two explosions should survive the merge
// This prevents a weaker explosion merging with a strong one,
// the strong one removing all the weaker one's power and just killing the explosion
var/is_stronger = (power >= E.power)
var/datum/automata_cell/explosion/survivor = is_stronger ? src : E
var/datum/automata_cell/explosion/dying = is_stronger ? E : src
var/is_stronger = (power >= other.power)
var/datum/automata_cell/explosion/survivor = is_stronger ? src : other
var/datum/automata_cell/explosion/dying = is_stronger ? other : src

// Two epicenters merging, or a new epicenter merging with a traveling wave
if((!survivor.direction && !dying.direction) || (survivor.direction && !dying.direction))
Expand All @@ -109,11 +120,14 @@
// Two waves traveling the same direction amplifies the explosion
if(survivor.direction == dying.direction)
survivor.power += dying.power
survivor.exploded_atoms |= dying.exploded_atoms

// Two waves travling towards each other weakens the explosion
if(survivor.direction == GLOB.reverse_dir[dying.direction])
survivor.power -= dying.power

qdel(dying)

return is_stronger

// Get a list of all directions the explosion should propagate to before dying
Expand Down Expand Up @@ -145,19 +159,19 @@
return
// The resistance here will affect the damage taken and the falloff in the propagated explosion
var/resistance = max(0, in_turf.get_explosion_resistance(direction))
for(var/atom/A in in_turf)
resistance += max(0, A.get_explosion_resistance())
for(var/atom/thing in in_turf)
resistance += max(0, thing.get_explosion_resistance())

// Blow stuff up
INVOKE_ASYNC(in_turf, TYPE_PROC_REF(/atom, ex_act), power, direction, explosion_cause_data, 0, enviro)
for(var/atom/A in in_turf)
if(A in exploded_atoms)
for(var/atom/thing in in_turf)
if(thing.gc_destroyed)
continue
if(A.gc_destroyed)
if(thing in exploded_atoms)
continue
INVOKE_ASYNC(A, TYPE_PROC_REF(/atom, ex_act), power, direction, explosion_cause_data, 0, enviro)
exploded_atoms += A
log_explosion(A, src)
exploded_atoms += thing
INVOKE_ASYNC(thing, TYPE_PROC_REF(/atom, ex_act), power, direction, explosion_cause_data, 0, enviro)
log_explosion(thing, src)

var/reflected = FALSE

Expand Down Expand Up @@ -231,20 +245,20 @@ When the cell processes, we simply don't blow up atoms that were tracked
as having entered the turf.
*/

/datum/automata_cell/explosion/proc/on_turf_entered(atom/movable/A)
/datum/automata_cell/explosion/proc/on_turf_entered(atom/movable/thing)
// Once is enough
if(A in exploded_atoms)
if(thing.gc_destroyed)
return
if(thing in exploded_atoms)
return

exploded_atoms += A
exploded_atoms += thing

// Note that we don't want to make it a directed ex_act because
// it could toss them back and make them get hit by the explosion again
if(A.gc_destroyed)
return

INVOKE_ASYNC(A, TYPE_PROC_REF(/atom, ex_act), power, null, explosion_cause_data, 0, enviro)
log_explosion(A, src)
// so we indicate this with a direction < 0
INVOKE_ASYNC(thing, TYPE_PROC_REF(/atom, ex_act), power, -1, explosion_cause_data, 0, enviro)
log_explosion(thing, src)

// I'll admit most of the code from here on out is basically just copypasta from DOREC

Expand Down
6 changes: 3 additions & 3 deletions code/datums/components/_component.dm
Original file line number Diff line number Diff line change
Expand Up @@ -197,10 +197,10 @@
else if(lookup[sig_type] == src) // We already registered here
continue
else if(!length(lookup[sig_type])) // One other thing registered here
lookup[sig_type] = list(lookup[sig_type]=TRUE)
lookup[sig_type][src] = TRUE
lookup[sig_type] = list(lookup[sig_type])
lookup[sig_type] += src
else // Many other things have registered here
lookup[sig_type][src] = TRUE
lookup[sig_type] += src

signal_enabled = TRUE

Expand Down
4 changes: 4 additions & 0 deletions code/datums/components/weed_food.dm
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@
RegisterSignal(parent_mob, COMSIG_LIVING_PREIGNITION, PROC_REF(on_preignition))
RegisterSignal(SSdcs, COMSIG_GLOB_GROUNDSIDE_FORSAKEN_HANDLING, PROC_REF(on_forsaken))
if(parent_turf)
message_admins("[\ref(src)] at [COORD(parent_mob)] RegisterWithParent: Registered [parent_turf] [\ref(parent_turf)] at [COORD(parent_turf)]")
RegisterSignal(parent_turf, COMSIG_WEEDNODE_GROWTH, PROC_REF(on_update))

/datum/component/weed_food/UnregisterFromParent()
Expand All @@ -108,6 +109,7 @@
if(absorbing_weeds)
UnregisterSignal(absorbing_weeds, COMSIG_PARENT_QDELETING)
if(parent_turf)
message_admins("[\ref(src)] at [COORD(parent_mob)] UnregisterFromParent: Unregistered [parent_turf] [\ref(parent_turf)] at [COORD(parent_turf)]")
UnregisterSignal(parent_turf, COMSIG_WEEDNODE_GROWTH)
if(parent_buckle)
UnregisterSignal(parent_buckle, COMSIG_OBJ_AFTER_BUCKLE)
Expand All @@ -124,11 +126,13 @@
absorbing_weeds = null

if(parent_turf)
message_admins("[\ref(src)] at [COORD(parent_mob)] on_move: Unregistered [parent_turf] [\ref(parent_turf)] at [COORD(parent_turf)]")
UnregisterSignal(parent_turf, COMSIG_WEEDNODE_GROWTH)
parent_turf = get_turf(parent_mob)
if(parent_turf != parent_mob.loc)
parent_turf = null // if our location is actually a container, we want to be safe from weeds
else
message_admins("[\ref(src)] at [COORD(parent_mob)] on_move: Registered [parent_turf] [\ref(parent_turf)] at [COORD(parent_turf)]")
RegisterSignal(parent_turf, COMSIG_WEEDNODE_GROWTH, PROC_REF(on_update))

// We moved, restart or start the proccess
Expand Down
4 changes: 2 additions & 2 deletions code/game/machinery/medical_pod/bodyscanner.dm
Original file line number Diff line number Diff line change
Expand Up @@ -46,10 +46,10 @@
return
go_out()

/obj/structure/machinery/medical_pod/bodyscanner/ex_act(severity, datum/cause_data/cause_data)
/obj/structure/machinery/medical_pod/bodyscanner/ex_act(severity, direction, datum/cause_data/cause_data)
for(var/atom/movable/A as mob|obj in src)
A.forceMove(loc)
A.ex_act(severity, , cause_data)
A.ex_act(severity, cause_data=cause_data)
switch(severity)
if(0 to EXPLOSION_THRESHOLD_LOW)
if (prob(25))
Expand Down
2 changes: 1 addition & 1 deletion code/game/machinery/vending/vendor_types/medical.dm
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
unacidable = TRUE

/obj/structure/medical_supply_link/ex_act(severity, direction)
return FALSE
return

/obj/structure/medical_supply_link/Initialize()
. = ..()
Expand Down
69 changes: 60 additions & 9 deletions code/game/objects/explosion_recursive.dm
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,54 @@ For explosion resistance, an explosion should never go through a wall or window
explosion resistance exactly as much as their health
*/

GLOBAL_VAR_INIT(create_and_destroy_ignore_paths2, generate_ignore_paths2())
/proc/generate_ignore_paths2()
. = list(
//Never meant to be created, errors out the ass for mobcode reasons
/mob/living/carbon,
/obj/effect/node,
/obj/item/seeds/cutting,
//lighting singleton
/mob/dview,
// These use walk_away() after initialization, which causes false positives
/obj/item/explosive/grenade/flashbang/cluster/segment,
/obj/item/explosive/grenade/flashbang/cluster_piece,
/mob/living/simple_animal/hostile/retaliate/giant_lizard,
/obj/effect/landmark/lizard_spawn,
/obj/effect/fake_attacker,
/atom/movable/lighting_mask, //leave it alone
//This is meant to fail extremely loud every single time it occurs in any environment in any context, and it falsely alarms when this unit test iterates it. Let's not spawn it in.
/obj/merge_conflict_marker,
/obj/effect/projector_anchor, // Needs a link ID set to work as intended
/obj/effect/projector/linked, // Needs a link ID set to work as intended
)
//This turf existing is an error in and of itself
. += typesof(/turf/baseturf_skipover)
. += typesof(/turf/baseturf_bottom)
//Our system doesn't support it without warning spam from unregister calls on things that never registered
. += typesof(/obj/docking_port)
. += typesof(/obj/item/storage/internal)
// fuck interiors
. += typesof(/obj/vehicle)
. += typesof(/obj/effect/vehicle_spawner)
// Always ought to have an associated escape menu. Any references it could possibly hold would need one regardless.
. += subtypesof(/atom/movable/screen/escape_menu)
. += typesof(/obj/effect/timed_event)
// Need a defined ID, mapping-only, will and should fail loudly if spawned without one
. += typesof(/obj/effect/landmark/dispersal_initiator)

/mob/verb/explosion_test()
set name = "Explosion Test"
set category = "Debug"

var/turf/location = get_turf(usr)
var/mob/living/carbon/human/body = new(location)
body.death()
cell_explosion(location, 60, 20, EXPLOSION_FALLOFF_SHAPE_LINEAR, SOUTH, create_cause_data("testing"))
cell_explosion(location, 60, 20, EXPLOSION_FALLOFF_SHAPE_LINEAR, SOUTH, create_cause_data("testing"))
for(var/turf/turf_path as anything in subtypesof(/turf) - GLOB.create_and_destroy_ignore_paths2)
location = location.ChangeTurf(turf_path)

/proc/explosion_rec(turf/epicenter, power, falloff = 20, datum/cause_data/explosion_cause_data)
var/obj/effect/explosion/Controller = new /obj/effect/explosion(epicenter)
Controller.initiate_explosion(epicenter, power, falloff, explosion_cause_data)
Expand Down Expand Up @@ -325,40 +373,43 @@ explosion resistance exactly as much as their health
if(anchored)
return

if(!istype(src.loc, /turf))
if(!isturf(loc))
return

if(direction < 0)
return // Don't do anything if explicitly directionless

var/range = min(round(severity/w_class * 0.2, 1), 14)

if(!direction)
direction = pick(GLOB.alldirs)
var/range = min(round(severity/src.w_class * 0.2, 1), 14)
if(!direction)
range = round( range/2 ,1)
range = round(range/2, 1)

if(range < 1)
return


var/speed = max(range*2.5, SPEED_SLOW)
var/atom/target = get_ranged_target_turf(src, direction, range)

if(range >= 2)
var/scatter = range/4 * scatter_multiplier
var/scatter_x = rand(-scatter,scatter)
var/scatter_y = rand(-scatter,scatter)
target = locate(target.x + round( scatter_x , 1),target.y + round( scatter_y , 1),target.z) //Locate an adjacent turf.
target = locate(target.x + round(scatter_x , 1), target.y + round(scatter_y , 1), target.z) //Locate an adjacent turf.

//time for the explosion to destroy windows, walls, etc which might be in the way
INVOKE_ASYNC(src, TYPE_PROC_REF(/atom/movable, throw_atom), target, range, speed, null, TRUE)

return

/mob/proc/explosion_throw(severity, direction)
if(anchored)
return

if(!istype(src.loc, /turf))
if(!isturf(loc))
return

if(direction < 0)
return // Don't do anything if explicitly directionless

var/weight = 1
switch(mob_size)
if(MOB_SIZE_SMALL)
Expand Down
2 changes: 2 additions & 0 deletions code/game/objects/shrapnel.dm
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@

/proc/create_shrapnel(turf/epicenter, shrapnel_number = 10, shrapnel_direction, shrapnel_spread = 45, datum/ammo/shrapnel_type = /datum/ammo/bullet/shrapnel, datum/cause_data/cause_data, ignore_source_mob = FALSE, on_hit_coefficient = 0.15, use_shrapnel_angle = FALSE)
if(shrapnel_direction < 0)
return // Don't do anything if explicitly directionless

epicenter = get_turf(epicenter)

Expand Down
2 changes: 1 addition & 1 deletion code/game/turfs/closed.dm
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@
thing.forceMove(above_current)
return

/turf/closed/Enter(atom/movable/mover, atom/forget)
/turf/closed/Enter(atom/movable/mover, atom/old_loc)
. = ..()
if(!mover.move_intentionally || !istype(mover,/mob/living))
return
Expand Down
Loading