Files
Bubberstation/code/datums/elements/blocks_explosives.dm
LemonInTheDark 858da9f19a Optimizes explosions (very slightly) (#71763)
## About The Pull Request

We do two major things here.
First, instead of having every turf need to ask all the turfs in "front"
of it for its blast resistance, we have blast resistance carry back in a
cache, so they only need to ask the one directly in front of them.
Much faster, such wow

The other thing we do is totally remove the idea of "building" a turf's
explosion resistance. Instead, a turf's full resistance is stored on it
at all times.
We use an element to manage objects that want to block explosives, and
that's it simple as.
As an optimization, turfs handle block differently, using a system where
we imply that a turf's own block is just the initial of their
explosive_resistance, unless proven otherwise
This also saves a significant amount of time

To be honest with you, I did this mostly cause I wanted to well make
explosions faster
This doesn't really fufil that. They are faster, but not by much
The bulk of explosion cost comes from actually exploding things, rather
then figuring out what/how to delete.
This code is much faster for larger blastwave sizes, because calculating
protection is constant.

We save maybe 60% of propogate_blastwave, but unfortunately
propogate_blastwave for one maxcap on the top left of icebox's chapel is
only 28ms, so while 11ms is good, it's not everything I could want when
the cost of explosion/fire is 555ms.

I'm happy about it still tho, because doing things like this means I can
expand on how explosive blocking works without needing to make things
seriously expensive in here.
Also it's faster for meme admin explosions and mega burgers

## Why It's Good For The Game

Speeds up explosives slightly, opens the door to better blast resistance
projection
2023-01-09 22:29:03 -08:00

57 lines
2.4 KiB
Plaintext

/// Apply this element to a movable atom when you want it to block explosions
/// It will mirror the blocking down to that movable's turf, keeping explosion work cheap
/datum/element/blocks_explosives
/datum/element/blocks_explosives/Attach(datum/target)
if(!ismovable(target))
return
. = ..()
ADD_TRAIT(target, TRAIT_BLOCKING_EXPLOSIVES, TRAIT_GENERIC)
var/atom/movable/moving_target = target
RegisterSignal(moving_target, COMSIG_MOVABLE_MOVED, PROC_REF(blocker_moved))
RegisterSignal(moving_target, COMSIG_MOVABLE_EXPLOSION_BLOCK_CHANGED, PROC_REF(blocking_changed))
moving_target.explosive_resistance = moving_target.explosion_block
if(length(moving_target.locs) > 1)
for(var/atom/location as anything in moving_target.locs)
block_loc(location, moving_target.explosion_block)
else if(moving_target.loc)
block_loc(moving_target.loc, moving_target.explosion_block)
/datum/element/blocks_explosives/Detach(datum/source)
. = ..()
REMOVE_TRAIT(source, TRAIT_BLOCKING_EXPLOSIVES, TRAIT_GENERIC)
/// Call this when our blocking well, changes. we'll update our turf(s) with the details
/datum/element/blocks_explosives/proc/blocking_changed(atom/movable/target, old_block, new_block)
if(length(target.locs) > 1)
for(var/atom/location as anything in target.locs)
unblock_loc(location, old_block)
block_loc(location, new_block)
else if(target.loc)
unblock_loc(target.loc, old_block)
block_loc(target.loc, new_block)
/// Applies a block amount to a turf. proc for convenince
/datum/element/blocks_explosives/proc/block_loc(atom/location, block_amount)
location.explosive_resistance += block_amount
/// Removes a block amount from a turf. proc for convenince
/datum/element/blocks_explosives/proc/unblock_loc(atom/location, block_amount)
location.explosive_resistance -= block_amount
/// Essentially just blocking_changed except we remove from the old loc, and add to the new one
/datum/element/blocks_explosives/proc/blocker_moved(atom/movable/target, atom/old_loc, dir, forced, list/old_locs)
if(length(old_locs) > 1)
for(var/atom/location as anything in old_locs)
unblock_loc(location, target.explosion_block)
else if(old_loc)
unblock_loc(old_loc, target.explosion_block)
if(length(target.locs) > 1)
for(var/atom/location as anything in target.locs)
block_loc(location, target.explosion_block)
else if(target.loc)
block_loc(target.loc, target.explosion_block)