Fixing embedding for projectiles. (#77674)

So, the main issue was that the variables for the embed element wouldn't
set when attached to a projectile but only on items for some
insignificant reason, which means it'll spawn the shrapnel yes, but
won't embed it since the chance is null/zero. I read the code over and
over and over with the assumption that something like this wouldn't have
been done, yet it was.

As for the secondary issue, because of how embedding works, the casing
types of arrows and harpoon aren't spawned when hitting a non-carbon or
reaching their maximum range. So, I'm re-enabling the reusable arg/var
for the caseless component of harpoons and arrows, and modifying the
`projectile_drop` to not drop their payload if the embedding component
would already do that, so we avoid duping.
This commit is contained in:
Ghom
2023-08-20 18:40:03 +02:00
committed by GitHub
parent e3a835b960
commit 54491a67e9
5 changed files with 50 additions and 29 deletions
+21 -20
View File
@@ -40,23 +40,23 @@
RegisterSignal(target, COMSIG_ATOM_EXAMINE, PROC_REF(examined))
RegisterSignal(target, COMSIG_EMBED_TRY_FORCE, PROC_REF(tryForceEmbed))
RegisterSignal(target, COMSIG_ITEM_DISABLE_EMBED, PROC_REF(detachFromWeapon))
if(!initialized)
src.embed_chance = embed_chance
src.fall_chance = fall_chance
src.pain_chance = pain_chance
src.pain_mult = pain_mult
src.remove_pain_mult = remove_pain_mult
src.rip_time = rip_time
src.impact_pain_mult = impact_pain_mult
src.ignore_throwspeed_threshold = ignore_throwspeed_threshold
src.jostle_chance = jostle_chance
src.jostle_pain_mult = jostle_pain_mult
src.pain_stam_pct = pain_stam_pct
initialized = TRUE
else
payload_type = projectile_payload
RegisterSignal(target, COMSIG_PROJECTILE_SELF_ON_HIT, PROC_REF(checkEmbedProjectile))
if(!initialized)
src.embed_chance = embed_chance
src.fall_chance = fall_chance
src.pain_chance = pain_chance
src.pain_mult = pain_mult
src.remove_pain_mult = remove_pain_mult
src.rip_time = rip_time
src.impact_pain_mult = impact_pain_mult
src.ignore_throwspeed_threshold = ignore_throwspeed_threshold
src.jostle_chance = jostle_chance
src.jostle_pain_mult = jostle_pain_mult
src.pain_stam_pct = pain_stam_pct
initialized = TRUE
/datum/element/embed/Detach(obj/target)
. = ..()
@@ -136,24 +136,25 @@
* That's awful, and it'll limit us to drop-deletable shrapnels in the worry of stuff like
* arrows and harpoons being embeddable even when not let loose by their weapons.
*/
/datum/element/embed/proc/checkEmbedProjectile(obj/projectile/P, atom/movable/firer, atom/hit, angle, hit_zone)
/datum/element/embed/proc/checkEmbedProjectile(obj/projectile/source, atom/movable/firer, atom/hit, angle, hit_zone)
SIGNAL_HANDLER
if(!iscarbon(hit) || HAS_TRAIT(hit, TRAIT_PIERCEIMMUNE))
Detach(P)
if(!source.can_embed_into(hit))
Detach(source)
return // we don't care
var/obj/item/payload = new payload_type(get_turf(hit))
if(istype(payload, /obj/item/shrapnel/bullet))
payload.name = P.name
SEND_SIGNAL(P, COMSIG_PROJECTILE_ON_SPAWN_EMBEDDED, payload)
payload.name = source.name
SEND_SIGNAL(source, COMSIG_PROJECTILE_ON_SPAWN_EMBEDDED, payload)
var/mob/living/carbon/C = hit
var/obj/item/bodypart/limb = C.get_bodypart(hit_zone)
if(!limb)
limb = C.get_bodypart()
tryForceEmbed(payload, limb)
Detach(P)
if(!tryForceEmbed(payload, limb))
payload.failedEmbed()
Detach(source)
/**
* tryForceEmbed() is called here when we fire COMSIG_EMBED_TRY_FORCE from [/obj/item/proc/tryEmbed]. Mostly, this means we're a piece of shrapnel from a projectile that just impacted something, and we're trying to embed in it.
+19 -3
View File
@@ -1,4 +1,8 @@
///A simple element that spawns an atom when the bullet hits an object or reaches the end of its range
/**
* A simple element that spawns an atom when the bullet hits an object or reaches the end of its range
* If the projectile has embedding and it can embed into the target, then it won't spawn the drop,
* since embedding the embed element already handles that.
*/
/datum/element/projectile_drop
element_flags = ELEMENT_BESPOKE
argument_hash_start_idx = 2
@@ -9,7 +13,12 @@
if(!isprojectile(target))
return ELEMENT_INCOMPATIBLE
src.drop_type = drop_type
RegisterSignals(target, list(COMSIG_PROJECTILE_RANGE_OUT, COMSIG_PROJECTILE_SELF_ON_HIT), PROC_REF(spawn_drop))
RegisterSignal(target, COMSIG_PROJECTILE_RANGE_OUT, PROC_REF(spawn_drop))
RegisterSignal(target, COMSIG_PROJECTILE_SELF_ON_HIT, PROC_REF(spawn_drop_if_not_embeddable))
/datum/element/projectile_drop/Detach(datum/source)
UnregisterSignal(source, list(COMSIG_PROJECTILE_RANGE_OUT, COMSIG_PROJECTILE_SELF_ON_HIT))
return ..()
/datum/element/projectile_drop/proc/spawn_drop(obj/projectile/source)
SIGNAL_HANDLER
@@ -17,4 +26,11 @@
var/atom/new_drop = new drop_type(turf)
SEND_SIGNAL(source, COMSIG_PROJECTILE_ON_SPAWN_DROP, new_drop)
//Just to be safe, knowing it won't be spawned multiple times.
UnregisterSignal(source, list(COMSIG_PROJECTILE_RANGE_OUT, COMSIG_PROJECTILE_SELF_ON_HIT, COMSIG_QDELETING))
Detach(source)
/datum/element/projectile_drop/proc/spawn_drop_if_not_embeddable(obj/projectile/source, atom/movable/firer, atom/hit, angle, hit_zone)
SIGNAL_HANDLER
if(source.can_embed_into(hit))
Detach(source)
return
spawn_drop(source)
@@ -7,7 +7,7 @@
/obj/item/ammo_casing/harpoon/Initialize(mapload)
. = ..()
AddElement(/datum/element/caseless)
AddElement(/datum/element/caseless, TRUE)
/obj/item/ammo_casing/harpoon/update_icon_state()
. = ..()
@@ -12,11 +12,13 @@
firing_effect_type = null
caliber = CALIBER_ARROW
is_cased_ammo = FALSE
///Whether the bullet type spawns another casing of the same type or not.
var/reusable = TRUE
/obj/item/ammo_casing/arrow/Initialize(mapload)
. = ..()
AddElement(/datum/element/envenomable_casing)
AddElement(/datum/element/caseless)
AddElement(/datum/element/caseless, reusable)
/obj/item/ammo_casing/arrow/update_icon_state()
. = ..()
@@ -58,7 +60,7 @@
desc = "Here it comes, cultist scum!"
icon_state = "holy_arrow_projectile"
damage = 20 //still a lot but this is roundstart gear so far less
shrapnel_type =/obj/projectile/bullet/arrow/holy
shrapnel_type =/obj/item/ammo_casing/arrow/holy
embedding = list(
embed_chance = 50,
fall_chance = 2,
@@ -80,6 +82,7 @@
name = "blazing star arrow"
desc = "A holy diver seeking its target, blessed with fire. Will ignite on hit, destroying the arrow. But if you hit an already ignited target...?"
projectile_type = /obj/projectile/bullet/arrow/blazing
reusable = FALSE
/obj/projectile/bullet/arrow/blazing
name = "blazing arrow"
+4 -3
View File
@@ -740,9 +740,6 @@
SEND_SIGNAL(fired_from, COMSIG_PROJECTILE_BEFORE_FIRE, src, original)
if(firer)
SEND_SIGNAL(firer, COMSIG_PROJECTILE_FIRER_BEFORE_FIRE, src, fired_from, original)
//If no angle needs to resolve it from xo/yo!
if(shrapnel_type && LAZYLEN(embedding))
AddElement(/datum/element/embed, projectile_payload = shrapnel_type)
if(!log_override && firer && original)
log_combat(firer, original, "fired at", src, "from [get_area_name(src, TRUE)]")
//note: mecha projectile logging is handled in /obj/item/mecha_parts/mecha_equipment/weapon/action(). try to keep these messages roughly the sameish just for consistency's sake.
@@ -1129,6 +1126,10 @@
return FALSE
///Checks if the projectile can embed into someone
/obj/projectile/proc/can_embed_into(atom/hit)
return embedding && shrapnel_type && iscarbon(hit) && !HAS_TRAIT(hit, TRAIT_PIERCEIMMUNE)
#undef MOVES_HITSCAN
#undef MUZZLE_EFFECT_PIXEL_INCREMENT