diff --git a/code/datums/elements/embed.dm b/code/datums/elements/embed.dm index 3b3f02ecb08..0ba3a581d9a 100644 --- a/code/datums/elements/embed.dm +++ b/code/datums/elements/embed.dm @@ -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. diff --git a/code/datums/elements/projectile_drop.dm b/code/datums/elements/projectile_drop.dm index 633d43c201b..36e189d6c3a 100644 --- a/code/datums/elements/projectile_drop.dm +++ b/code/datums/elements/projectile_drop.dm @@ -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) diff --git a/code/modules/projectiles/ammunition/ballistic/harpoon.dm b/code/modules/projectiles/ammunition/ballistic/harpoon.dm index 61aa16fe56e..79590ccb97d 100644 --- a/code/modules/projectiles/ammunition/ballistic/harpoon.dm +++ b/code/modules/projectiles/ammunition/ballistic/harpoon.dm @@ -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() . = ..() diff --git a/code/modules/projectiles/guns/ballistic/bows/bow_arrows.dm b/code/modules/projectiles/guns/ballistic/bows/bow_arrows.dm index 50d0d456ee2..d9443719a7e 100644 --- a/code/modules/projectiles/guns/ballistic/bows/bow_arrows.dm +++ b/code/modules/projectiles/guns/ballistic/bows/bow_arrows.dm @@ -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" diff --git a/code/modules/projectiles/projectile.dm b/code/modules/projectiles/projectile.dm index ec4fc9227e9..0782194f4cf 100644 --- a/code/modules/projectiles/projectile.dm +++ b/code/modules/projectiles/projectile.dm @@ -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