Files
Bubberstation/code/datums/elements/can_shatter.dm
SyncIt21 e8d93d32a7 Fixes shatter element dropping stuff on blocked turfs (#88739)
## About The Pull Request
- Fixes #88727

Now when an atom shatters if that turf is blocked by a dense object
(e.g. wall, closed airlock, window etc) such that no air can pass
through it then we drop stuff on the thrown object's location and not on
the hit target location.

In laymen's terms if you throw a plate on the wall, window, closed
airlock etc then the shattered contents drop on the plate's last
location & not on the wall itself

## Changelog
🆑
fix: Fixes shattering element dropping stuff on blocked turfs
/🆑
2024-12-28 10:06:42 +00:00

82 lines
2.9 KiB
Plaintext

/**
* When attached to something, will make that thing shatter into shards on throw impact or z level falling
* Or even when used as a weapon if the 'shatters_as_weapon' arg is TRUE
*/
/datum/element/can_shatter
element_flags = ELEMENT_BESPOKE
argument_hash_start_idx = 2
/// What type of item is spawned as a 'shard' once the shattering happens
var/obj/item/shard_type
/// How many shards total are made when the thing we're attached to shatters
var/number_of_shards
/// What sound plays when the thing we're attached to shatters
var/shattering_sound
/datum/element/can_shatter/Attach(datum/target,
shard_type = /obj/item/plate_shard,
number_of_shards = 5,
shattering_sound = 'sound/items/ceramic_break.ogg',
shatters_as_weapon = FALSE,
)
. = ..()
if(!ismovable(target))
return ELEMENT_INCOMPATIBLE
src.shard_type = shard_type
src.number_of_shards = number_of_shards
src.shattering_sound = shattering_sound
RegisterSignal(target, COMSIG_MOVABLE_IMPACT, PROC_REF(on_throw_impact))
RegisterSignal(target, COMSIG_ATOM_ON_Z_IMPACT, PROC_REF(on_z_impact))
if(shatters_as_weapon)
RegisterSignal(target, COMSIG_ITEM_AFTERATTACK, PROC_REF(on_post_attack_atom))
/datum/element/can_shatter/Detach(datum/target)
. = ..()
UnregisterSignal(target, list(COMSIG_MOVABLE_IMPACT, COMSIG_ATOM_ON_Z_IMPACT))
/// Tells the parent to shatter if we impact a lower zlevel
/datum/element/can_shatter/proc/on_z_impact(datum/source, turf/impacted_turf, levels)
SIGNAL_HANDLER
shatter(source, impacted_turf)
/// Tells the parent to shatter if we are thrown and impact something
/datum/element/can_shatter/proc/on_throw_impact(datum/source, atom/hit_atom, datum/thrownthing/throwing_datum, caught)
SIGNAL_HANDLER
if(caught)
return
shatter(source, hit_atom)
/// Handles the actual shattering part, throwing shards of whatever is defined on the component everywhere
/datum/element/can_shatter/proc/shatter(atom/movable/source, atom/hit_atom)
var/turf/scatter_turf = get_turf(hit_atom)
if(!hit_atom.CanPass(source, get_dir(source, hit_atom))) //Object is too dense to fall apart on
scatter_turf = get_turf(source)
var/generator/scatter_gen = generator(GEN_CIRCLE, 0, 48, NORMAL_RAND)
for(var/obj/item/scattered_item as anything in source.contents)
scattered_item.forceMove(scatter_turf)
var/list/scatter_vector = scatter_gen.Rand()
scattered_item.pixel_x = scatter_vector[1]
scattered_item.pixel_y = scatter_vector[2]
for(var/iteration in 1 to number_of_shards)
var/obj/item/shard = new shard_type(scatter_turf)
shard.pixel_x = rand(-6, 6)
shard.pixel_y = rand(-6, 6)
playsound(scatter_turf, shattering_sound, 60, TRUE)
if(isobj(source))
var/obj/obj_source = source
obj_source.deconstruct(FALSE)
return
else
qdel(source)
/datum/element/can_shatter/proc/on_post_attack_atom(obj/item/source, atom/attacked_atom, mob/living/user)
SIGNAL_HANDLER
shatter(source, attacked_atom)