[MIRROR] Makes sure COMSIG_ATOM_EX_ACT is always called. [MDB IGNORE] (#10498)

* Makes sure COMSIG_ATOM_EX_ACT is always called. (#63685)

Creates a wrapper macro for ex_act() and moves the signal and contents explosion calls to there. This way we can ensure the signal is always fired. Also desnowflakes reagents responding to explosions.

Ensures that a signal is always called when the attendant proc is called.

* Makes sure COMSIG_ATOM_EX_ACT is always called.

Co-authored-by: TemporalOroboros <TemporalOroboros@gmail.com>
This commit is contained in:
SkyratBot
2022-01-07 15:23:12 -05:00
committed by GitHub
co-authored by TemporalOroboros
parent 47f0ee4368
commit 01080dfe0a
29 changed files with 113 additions and 71 deletions
@@ -2,7 +2,7 @@
// When the signal is called: (signal arguments)
// All signals send the source datum of the signal as the first argument
///from base of atom/ex_act(): (severity, target)
///from the [EX_ACT] wrapper macro: (severity, target)
#define COMSIG_ATOM_EX_ACT "atom_ex_act"
///from base of atom/emp_act(): (severity)
#define COMSIG_ATOM_EMP_ACT "atom_emp_act"
+16
View File
@@ -8,6 +8,14 @@
/// The default explosion severity used to mark that an object is beyond the impact range of the explosion.
#define EXPLODE_NONE 0
/// A wrapper for [/atom/proc/ex_act] to ensure that the explosion propagation and attendant signal are always handled.
#define EX_ACT(target, args...)\
if(!(target.flags_1 & PREVENT_CONTENTS_EXPLOSION_1)) { \
target.contents_explosion(##args);\
};\
SEND_SIGNAL(target, COMSIG_ATOM_EX_ACT, ##args);\
target.ex_act(##args);
// Internal explosion argument list keys.
// Must match the arguments to [/datum/controller/subsystem/explosions/proc/propagate_blastwave]
/// The origin atom of the explosion.
@@ -32,3 +40,11 @@
#define EXARG_KEY_SILENT STRINGIFY(silent)
/// Whether or not the explosion should produce smoke if it is large enough to warrant it.
#define EXARG_KEY_SMOKE STRINGIFY(smoke)
// Explodable component deletion values
/// Makes the explodable component queue to reset its exploding status when it detonates.
#define EXPLODABLE_NO_DELETE 0
/// Makes the explodable component delete itself when it detonates.
#define EXPLODABLE_DELETE_SELF 1
/// Makes the explodable component delete its parent when it detonates.
#define EXPLODABLE_DELETE_PARENT 2
+6 -6
View File
@@ -646,7 +646,7 @@ SUBSYSTEM_DEF(explosions)
lowturf = list()
for(var/thing in low_turf)
var/turf/turf_thing = thing
turf_thing.ex_act(EXPLODE_LIGHT)
EX_ACT(turf_thing, EXPLODE_LIGHT)
cost_lowturf = MC_AVERAGE(cost_lowturf, TICK_DELTA_TO_MS(TICK_USAGE_REAL - timer))
timer = TICK_USAGE_REAL
@@ -654,7 +654,7 @@ SUBSYSTEM_DEF(explosions)
medturf = list()
for(var/thing in med_turf)
var/turf/turf_thing = thing
turf_thing.ex_act(EXPLODE_HEAVY)
EX_ACT(turf_thing, EXPLODE_HEAVY)
cost_medturf = MC_AVERAGE(cost_medturf, TICK_DELTA_TO_MS(TICK_USAGE_REAL - timer))
timer = TICK_USAGE_REAL
@@ -662,7 +662,7 @@ SUBSYSTEM_DEF(explosions)
highturf = list()
for(var/thing in high_turf)
var/turf/turf_thing = thing
turf_thing.ex_act(EXPLODE_DEVASTATE)
EX_ACT(turf_thing, EXPLODE_DEVASTATE)
cost_highturf = MC_AVERAGE(cost_highturf, TICK_DELTA_TO_MS(TICK_USAGE_REAL - timer))
timer = TICK_USAGE_REAL
@@ -687,7 +687,7 @@ SUBSYSTEM_DEF(explosions)
var/atom/movable/movable_thing = thing
if(QDELETED(movable_thing))
continue
movable_thing.ex_act(EXPLODE_DEVASTATE)
EX_ACT(movable_thing, EXPLODE_DEVASTATE)
cost_high_mov_atom = MC_AVERAGE(cost_high_mov_atom, TICK_DELTA_TO_MS(TICK_USAGE_REAL - timer))
timer = TICK_USAGE_REAL
@@ -697,7 +697,7 @@ SUBSYSTEM_DEF(explosions)
var/atom/movable/movable_thing = thing
if(QDELETED(movable_thing))
continue
movable_thing.ex_act(EXPLODE_HEAVY)
EX_ACT(movable_thing, EXPLODE_HEAVY)
cost_med_mov_atom = MC_AVERAGE(cost_med_mov_atom, TICK_DELTA_TO_MS(TICK_USAGE_REAL - timer))
timer = TICK_USAGE_REAL
@@ -707,7 +707,7 @@ SUBSYSTEM_DEF(explosions)
var/atom/movable/movable_thing = thing
if(QDELETED(movable_thing))
continue
movable_thing.ex_act(EXPLODE_LIGHT)
EX_ACT(movable_thing, EXPLODE_LIGHT)
cost_low_mov_atom = MC_AVERAGE(cost_low_mov_atom, TICK_DELTA_TO_MS(TICK_USAGE_REAL - timer))
+40 -20
View File
@@ -10,12 +10,16 @@
var/flame_range = 0
/// The flash range of the resulting explosion.
var/flash_range = 3
/// Whether this explosion ignores the bombcap.
var/uncapped
/// Whether we always delete. Useful for nukes turned plasma and such, so they don't default delete and can survive
var/delete_after
/// For items, lets us determine where things should be hit.
var/equipped_slot
/// Whether we always delete. Useful for nukes turned plasma and such, so they don't default delete and can survive
var/always_delete
/// Whether this component is currently in the process of exploding.
var/tmp/exploding = FALSE
/datum/component/explodable/Initialize(devastation_range_override, heavy_impact_range_override, light_impact_range_override, flame_range_override, flash_range_override, _always_delete = TRUE)
/datum/component/explodable/Initialize(devastation_range, heavy_impact_range, light_impact_range, flame_range, flash_range, uncapped = FALSE, delete_after = EXPLODABLE_DELETE_PARENT)
if(!isatom(parent))
return COMPONENT_INCOMPATIBLE
@@ -31,19 +35,18 @@
RegisterSignal(parent, COMSIG_ITEM_EQUIPPED, .proc/on_equip)
RegisterSignal(parent, COMSIG_ITEM_DROPPED, .proc/on_drop)
if(devastation_range_override)
devastation_range = devastation_range_override
if(heavy_impact_range_override)
heavy_impact_range = heavy_impact_range_override
if(light_impact_range_override)
light_impact_range = light_impact_range_override
if(flame_range_override)
flame_range = flame_range_override
if(flash_range_override)
flash_range = flash_range_override
always_delete = _always_delete
if (devastation_range)
src.devastation_range = devastation_range
if (heavy_impact_range)
src.heavy_impact_range = heavy_impact_range
if (light_impact_range)
src.light_impact_range = light_impact_range
if (flame_range)
src.flame_range = flame_range
if (flash_range)
src.flash_range = flash_range
src.uncapped = uncapped
src.delete_after = delete_after
/datum/component/explodable/proc/explodable_insert_item(datum/source, obj/item/I, mob/M, silent = FALSE, force = FALSE)
SIGNAL_HANDLER
@@ -134,11 +137,28 @@
/// Explode and remove the object
/datum/component/explodable/proc/detonate()
SIGNAL_HANDLER
if (exploding)
return // If we don't do this and this doesn't delete it can lock the MC into only processing Input, Timers, and Explosions.
var/atom/A = parent
var/atom/bomb = parent
var/log = TRUE
if(light_impact_range < 1)
log = FALSE
explosion(A, devastation_range, heavy_impact_range, light_impact_range, flame_range, flash_range, log) //epic explosion time
if(always_delete)
qdel(A)
exploding = TRUE
explosion(bomb, devastation_range, heavy_impact_range, light_impact_range, flame_range, flash_range, log, uncapped) //epic explosion time
switch(delete_after)
if(EXPLODABLE_DELETE_SELF)
qdel(src)
if(EXPLODABLE_DELETE_PARENT)
qdel(bomb)
else
addtimer(CALLBACK(src, .proc/reset_exploding), 0.1 SECONDS)
/**
* Resets the expoding flag
*/
/datum/component/explodable/proc/reset_exploding()
SIGNAL_HANDLER
src.exploding = FALSE
+3 -3
View File
@@ -305,11 +305,11 @@ If you make a derivative work from this code, you must include this notification
if (2)
D.adjustBruteLoss(rand(20,30))
if (3)
D.ex_act(EXPLODE_LIGHT)
EX_ACT(D, EXPLODE_LIGHT)
else
D.adjustBruteLoss(rand(10,20))
else
D.ex_act(EXPLODE_LIGHT)
EX_ACT(D, EXPLODE_LIGHT)
else
if (A)
@@ -427,7 +427,7 @@ If you make a derivative work from this code, you must include this notification
if (falling == 1)
if (prob(33) || D.stat)
D.ex_act(EXPLODE_LIGHT)
EX_ACT(D, EXPLODE_LIGHT)
else
D.adjustBruteLoss(rand(20,30))
else
+1 -1
View File
@@ -138,7 +138,7 @@ Unless you know what you're doing, only use the first three numbers. They're in
if(ismovable(source))
source.AddElement(/datum/element/firestacker, amount=1)
// Ideally exploding plasma objects should delete themselves but we still have the flooder and SSexplosions to rely on deleting it asynchronously so it's not that bad.
source.AddComponent(/datum/component/explodable, 0, 0, amount / 2500, 0, amount / 1250, FALSE)
source.AddComponent(/datum/component/explodable, 0, 0, amount / 2500, 0, amount / 1250, delete_after = EXPLODABLE_NO_DELETE)
source.AddComponent(/datum/component/combustible_flooder, "plasma", amount*0.05) //Empty temp arg, fully dependent on whatever ignited it.
/datum/material/plasma/on_removed(atom/source, amount, material_flags)
+3 -3
View File
@@ -801,12 +801,12 @@
/**
* React to being hit by an explosion
*
* Default behaviour is to call [contents_explosion][/atom/proc/contents_explosion] and send the [COMSIG_ATOM_EX_ACT] signal
* Should be called through the [EX_ACT] wrapper macro.
* The wrapper takes care of the [COMSIG_ATOM_EX_ACT] signal.
* as well as calling [/atom/proc/contents_explosion].
*/
/atom/proc/ex_act(severity, target)
set waitfor = FALSE
contents_explosion(severity, target)
SEND_SIGNAL(src, COMSIG_ATOM_EX_ACT, severity, target)
/**
* React to a hit by a blob objecd
+1
View File
@@ -278,6 +278,7 @@
lefthand_file = 'icons/mob/inhands/equipment/shields_lefthand.dmi'
righthand_file = 'icons/mob/inhands/equipment/shields_righthand.dmi'
w_class = WEIGHT_CLASS_NORMAL
flags_1 = PREVENT_CONTENTS_EXPLOSION_1 // We detonate upon being exploded.
resistance_flags = FLAMMABLE //Burnable (but the casing isn't)
var/adminlog = null
//SKYRAT EDIT CHANGE BEGIN
@@ -73,12 +73,6 @@
else
return ..()
/obj/effect/decal/cleanable/ex_act(severity)
if(reagents)
for(var/datum/reagent/R in reagents.reagent_list)
R.on_ex_act(severity)
return ..()
/obj/effect/decal/cleanable/fire_act(exposed_temperature, exposed_volume)
if(reagents)
reagents.expose_temperature(exposed_temperature)
@@ -146,7 +146,6 @@
master.disrupt()
/obj/effect/dummy/chameleon/ex_act(S, T)
contents_explosion(S, T)
master.disrupt()
/obj/effect/dummy/chameleon/bullet_act()
+2 -2
View File
@@ -13,7 +13,7 @@
righthand_file = 'icons/mob/inhands/equipment/security_righthand.dmi'
throw_speed = 3
throw_range = 7
flags_1 = CONDUCT_1
flags_1 = CONDUCT_1 | PREVENT_CONTENTS_EXPLOSION_1 // We detonate upon being exploded.
slot_flags = ITEM_SLOT_BELT
resistance_flags = FLAMMABLE
max_integrity = 40
@@ -192,7 +192,7 @@
log_game("A projectile ([hitby]) detonated a grenade held by [key_name(owner)] at [COORD(source_turf)]")
message_admins("A projectile ([hitby]) detonated a grenade held by [key_name_admin(owner)] at [ADMIN_COORDJMP(source_turf)]")
detonate()
if(!QDELETED(src)) // some grenades don't detonate but we want them destroyed
qdel(src)
return TRUE //It hit the grenade, not them
+1 -1
View File
@@ -53,7 +53,7 @@
location = get_turf(target)
target.cut_overlay(plastic_overlay, TRUE)
if(!ismob(target) || full_damage_on_mobs)
target.ex_act(EXPLODE_HEAVY, target)
EX_ACT(target, EXPLODE_HEAVY, target)
else
location = get_turf(src)
if(location)
@@ -84,8 +84,7 @@
SEND_SIGNAL(W, COMSIG_PARENT_ATTACKBY, O)
/turf/open/floor/plating/asteroid/ex_act(severity, target)
. = SEND_SIGNAL(src, COMSIG_ATOM_EX_ACT, severity, target)
contents_explosion(severity, target)
return
/turf/open/floor/plating/lavaland_baseturf
baseturfs = /turf/open/floor/plating/asteroid/basalt/lava_land_surface
@@ -130,7 +130,7 @@
return
/turf/open/floor/plating/beach/ex_act(severity, target)
contents_explosion(severity, target)
return
/turf/open/floor/plating/beach/sand
gender = PLURAL
@@ -54,7 +54,6 @@
return ..()
/turf/open/floor/engine/ex_act(severity, target)
contents_explosion(severity, target)
if(target == src)
ScrapeAway(flags = CHANGETURF_INHERIT_AIR)
return TRUE
+1 -1
View File
@@ -28,7 +28,7 @@
var/immunity_resistance_flags = LAVA_PROOF
/turf/open/lava/ex_act(severity, target)
contents_explosion(severity, target)
return
/turf/open/lava/MakeSlippery(wet_setting, min_wet_time, wet_time_to_add, max_wet_time, permanent)
return
+1 -1
View File
@@ -257,7 +257,7 @@ In my current plan for it, 'solid' will be defined as anything with density == 1
penetrated_chest?.receive_damage(60, wound_bonus = 20, sharpness=SHARP_POINTY)
if(smeared_mob.density || prob(10))
smeared_mob.ex_act(EXPLODE_HEAVY)
EX_ACT(smeared_mob, EXPLODE_HEAVY)
/obj/effect/immovablerod/attack_hand(mob/living/user, list/modifiers)
. = ..()
+1 -1
View File
@@ -314,7 +314,7 @@ GLOBAL_LIST_INIT(meteorsC, list(/obj/effect/meteor/dust=1)) //for space dust eve
new /obj/effect/decal/cleanable/blood(T)
/obj/effect/meteor/meaty/Bump(atom/A)
A.ex_act(hitpwr)
EX_ACT(A, hitpwr)
get_hit()
//Meaty Ore Xeno edition
@@ -64,7 +64,7 @@
var/turf/T = get_turf(source)
playsound(T,'sound/effects/explosion2.ogg', 200, TRUE)
new /obj/effect/temp_visual/explosion(T)
explodee.ex_act(EXPLODE_HEAVY)
EX_ACT(explodee, EXPLODE_HEAVY)
UNREGISTER_BOMB_SIGNALS(source)
/mob/living/simple_animal/hostile/guardian/bomb/proc/disable(atom/A)
@@ -198,7 +198,7 @@ Difficulty: Extremely Hard
/obj/projectile/colossus/frost_orb/on_hit(atom/target, blocked = FALSE)
. = ..()
if(isturf(target) || isobj(target))
target.ex_act(EXPLODE_HEAVY)
EX_ACT(target, EXPLODE_HEAVY)
/obj/projectile/colossus/snowball
name = "machine-gun snowball"
@@ -220,7 +220,7 @@ Difficulty: Extremely Hard
/obj/projectile/colossus/ice_blast/on_hit(atom/target, blocked = FALSE)
. = ..()
if(isturf(target) || isobj(target))
target.ex_act(EXPLODE_HEAVY)
EX_ACT(target, EXPLODE_HEAVY)
/obj/item/resurrection_crystal
name = "resurrection crystal"
+1 -3
View File
@@ -242,9 +242,7 @@
new_reagent.purity = added_purity
new_reagent.creation_purity = added_purity
new_reagent.ph = added_ph
if(data)
new_reagent.data = data
new_reagent.on_new(data)
new_reagent.on_new(data)
if(isliving(my_atom))
new_reagent.on_mob_add(my_atom, amount) //Must occur before it could posibly run on_mob_delete
+2 -5
View File
@@ -209,7 +209,8 @@ Primarily used in reagents/reaction_agents
/// Called after add_reagents creates a new reagent.
/datum/reagent/proc/on_new(data)
return
if(data)
src.data = data
/// Called when two reagents of the same are mixing.
/datum/reagent/proc/on_merge(data, amount)
@@ -219,10 +220,6 @@ Primarily used in reagents/reaction_agents
/datum/reagent/proc/on_update(atom/A)
return
/// Called when the reagent container is hit by an explosion
/datum/reagent/proc/on_ex_act(severity)
return
/// Called if the reagent has passed the overdose threshold and is set to be triggering overdose effects
/datum/reagent/proc/overdose_process(mob/living/M, delta_time, times_fired)
return
@@ -2176,6 +2176,10 @@ All effects don't start immediately, but rather get worse over time; the rate is
ph = 4
/datum/reagent/consumable/ethanol/fruit_wine/on_new(list/data)
if(!data)
return
src.data = data
names = data["names"]
tastes = data["tastes"]
boozepwr = data["boozepwr"]
@@ -73,6 +73,9 @@
..()
/datum/reagent/consumable/nutriment/on_new(list/supplied_data)
. = ..()
if(!data)
return
// taste data can sometimes be ("salt" = 3, "chips" = 1)
// and we want it to be in the form ("salt" = 0.75, "chips" = 0.25)
// which is called "normalizing"
@@ -278,8 +278,10 @@ Basically, we fill the time between now and 2s from now with hands based off the
..()
/datum/reagent/inverse/hercuri/on_new(data)
. = ..()
if(!data)
return
method |= data["method"]
..()
/datum/reagent/inverse/hercuri/on_mob_life(mob/living/carbon/owner, delta_time, times_fired)
var/heating = rand(creation_purity * REM * 3, creation_purity * REM * 6)
@@ -42,6 +42,7 @@
/datum/reagent/blood/on_new(list/data)
. = ..()
if(istype(data))
SetViruses(src, data)
@@ -107,6 +107,16 @@
taste_description = "salt"
chemical_flags = REAGENT_CAN_BE_SYNTHESIZED
/datum/reagent/gunpowder/on_new(data)
. = ..()
if(holder?.my_atom)
RegisterSignal(holder.my_atom, COMSIG_ATOM_EX_ACT, .proc/on_ex_act)
/datum/reagent/gunpowder/Destroy()
if(holder?.my_atom)
UnregisterSignal(holder.my_atom, COMSIG_ATOM_EX_ACT)
return ..()
/datum/reagent/gunpowder/on_mob_life(mob/living/carbon/M, delta_time, times_fired)
. = TRUE
..()
@@ -116,7 +126,10 @@
if(M.hallucination < volume)
M.hallucination += 5 * REM * delta_time
/datum/reagent/gunpowder/on_ex_act()
/datum/reagent/gunpowder/proc/on_ex_act(atom/source, severity, target)
SIGNAL_HANDLER
if(source.flags_1 & PREVENT_CONTENTS_EXPLOSION_1)
return
var/location = get_turf(holder.my_atom)
var/datum/effect_system/reagents_explosion/e = new()
e.set_up(1 + round(volume/6, 1), location, 0, 0, message = 0)
@@ -33,6 +33,9 @@
var/turf/open/location_return = null
/datum/reagent/eigenstate/on_new(list/data)
. = ..()
if(!data)
return
location_created = data["location_created"]
/datum/reagent/eigenstate/expose_mob(mob/living/living_mob, methods, reac_volume, show_message, touch_protection)
@@ -194,13 +194,6 @@
return ..()
/obj/item/reagent_containers/ex_act(severity)
if(reagents)
for(var/datum/reagent/R in reagents.reagent_list)
R.on_ex_act(severity)
if(!QDELETED(src))
return ..()
/obj/item/reagent_containers/fire_act(exposed_temperature, exposed_volume)
reagents.expose_temperature(exposed_temperature)
..()