Replaces flamethrower unique hit_reaction handling with the bullet_intercepting component (#92731)

## About The Pull Request

Flamethrower exploding when shot was handled by hit_reaction previously,
and will now use the generic bullet_intercepting component. Also adds
handling for multiple projectile types in the bullet_intercepting
component, as well as a check for whether the object currently can block
bullets. Should have no gameplay changes.

## Why It's Good For The Game

closes #81863 , they said it'd be better consistency
This commit is contained in:
Leland Kemble
2025-08-29 16:25:26 -04:00
committed by GitHub
parent 319bd8303a
commit 69f21ff997
2 changed files with 32 additions and 18 deletions

View File

@@ -4,8 +4,8 @@
/datum/component/bullet_intercepting
/// Chance to intercept a projectile
var/block_chance
/// Type of bullet to intercept
var/block_type
/// List of types of bullets to intercept
var/list/block_type
/// Slots in which effect can be active
var/active_slots
/// Person currently wearing us
@@ -14,8 +14,10 @@
var/datum/callback/on_intercepted
/// Number of things we can block before we delete ourself (stop being able to block)
var/block_charges = INFINITY
/// Callback to check if the object is currently able to block
var/datum/callback/is_blocking_check
/datum/component/bullet_intercepting/Initialize(block_chance = 2, block_type = BULLET, active_slots, datum/callback/on_intercepted, block_charges = INFINITY)
/datum/component/bullet_intercepting/Initialize(block_chance = 2, list/block_type = list(BULLET), active_slots, datum/callback/on_intercepted, block_charges = INFINITY, datum/callback/is_blocking_check = null)
. = ..()
if (!isitem(parent))
return COMPONENT_INCOMPATIBLE
@@ -24,6 +26,7 @@
src.active_slots = active_slots
src.on_intercepted = on_intercepted
src.block_charges = block_charges
src.is_blocking_check = is_blocking_check
RegisterSignal(parent, COMSIG_ITEM_EQUIPPED, PROC_REF(on_parent_equipped))
RegisterSignal(parent, COMSIG_ITEM_PRE_UNEQUIP, PROC_REF(on_unequipped))
@@ -58,15 +61,18 @@
/// Called when wearer is shot, check if we're going to block the hit
/datum/component/bullet_intercepting/proc/on_wearer_shot(mob/living/victim, obj/projectile/bullet)
SIGNAL_HANDLER
if (victim != wearer || victim.stat == DEAD || bullet.armor_flag != block_type)
if(!isnull(is_blocking_check) && !is_blocking_check.Invoke())
return NONE
if (!prob(block_chance))
if (victim != wearer || victim.stat == DEAD || !prob(block_chance))
return NONE
on_intercepted?.Invoke(victim, bullet)
block_charges--
if (block_charges <= 0)
qdel(src)
return PROJECTILE_INTERRUPT_HIT
for (var/blocktype in block_type)
if (bullet.armor_flag == blocktype)
on_intercepted?.Invoke(victim, bullet)
block_charges--
if (block_charges <= 0)
qdel(src)
return PROJECTILE_INTERRUPT_HIT
return NONE
/// Called when wearer is deleted, stop tracking them
/datum/component/bullet_intercepting/proc/on_wearer_deleted()

View File

@@ -237,6 +237,14 @@
/obj/item/flamethrower/Initialize(mapload)
. = ..()
AddComponent(\
/datum/component/bullet_intercepting,\
block_chance = 15,\
on_intercepted = CALLBACK(src, PROC_REF(intercepted_bullet_reaction)),\
active_slots = ITEM_SLOT_HANDS,\
block_type = list(BULLET,LASER),\
is_blocking_check = CALLBACK(src, PROC_REF(check_tank)),\
)
if(create_full)
if(!weldtool)
weldtool = new /obj/item/weldingtool(src)
@@ -256,15 +264,15 @@
/obj/item/flamethrower/full/tank
create_with_tank = TRUE
/obj/item/flamethrower/hit_reaction(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", final_block_chance = 0, damage = 0, attack_type = MELEE_ATTACK, damage_type = BRUTE)
if(damage && attack_type == PROJECTILE_ATTACK && damage_type != STAMINA && prob(15))
owner.visible_message(span_danger("\The [attack_text] hits the fuel tank on [owner]'s [name], rupturing it! What a shot!"))
var/turf/target_turf = get_turf(owner)
owner.log_message("held a flamethrower tank detonated by a projectile ([hitby])", LOG_GAME)
igniter.ignite_turf(src,target_turf, release_amount = 100)
qdel(ptank)
return 1 //It hit the flamethrower, not them
/obj/item/flamethrower/proc/intercepted_bullet_reaction(mob/living/holder, obj/projectile/bullet)
holder.visible_message(span_danger("\The [bullet] hits the fuel tank on [holder]'s [name], rupturing it! What a shot!"))
var/turf/target_turf = get_turf(holder)
holder.log_message("held a flamethrower tank detonated by a projectile ([bullet])", LOG_GAME)
igniter.ignite_turf(src,target_turf, release_amount = 100)
qdel(ptank)
/obj/item/flamethrower/proc/check_tank()
return ptank
/obj/item/assembly/igniter/proc/flamethrower_process(turf/open/location)
location.hotspot_expose(heat,2)