Healium bolts now embed and heal/knock out passively over time instead of being instant and unblockable (#91481)

## About The Pull Request

Healium bolts now heal you for 5 of each damage per second for 6 seconds
before falling out, while applying 2 seconds of drowsiness. If you have
at least 5 seconds of drowsiness (after 4 seconds of processing, because
we add 2 and it gets deducted by 1 afterwards) you get knocked out for 3
seconds (similarly to how it worked before, but with 1 additional second
left of processing if you were only shot by one bolt, you end up knocked
out for 4 seconds). It takes 1.5 seconds to rip one out, so you should
be able to react to being shot by one unless the attacker follows it up
with a melee distruption. Bolts that fall out restore their charges, but
only one bolt at a time can be putting the target to sleep.

https://github.com/user-attachments/assets/7936895e-f4dc-4bd6-847f-495c7f1202db

Video is a bit outdated, delay before knockout been bumped by a second.

###### This is a commission for Ezel/Improvedname

## Why It's Good For The Game

Healium bolts are an instant knockout that could be mass-produced to
either instantly win fights, or thrown at medbay to quickly hit corpses
by poking them over and over again as bolts didn't even embed, so
players can instantly reload and shoot them again. It was either making
them harder to produce, or reducing the effects, and former wouldn't
solve the knockout issue.
They also didn't care about block values, so even if you blocked or
reflected one you'd still get knocked out. lol

## Changelog

🆑
balance: Healium bolts now heal and knock out overtime while being
embedded instead of being instant.
balance: Healium bolts dissolve after being embedded for 6 seconds and
don't work on corpses
fix: Healium bolts no longer ignore being blocked/parried/reflected
/🆑
This commit is contained in:
SmArtKar
2025-06-29 05:47:00 +02:00
committed by GitHub
parent 0dc3473b9a
commit c108ef79ac
2 changed files with 81 additions and 25 deletions

View File

@@ -64,6 +64,14 @@
projectile_type = /obj/projectile/bullet/rebar
newtonian_force = 1.5
/obj/item/ammo_casing/rebar/Initialize(mapload)
. = ..()
AddElement(/datum/element/caseless, TRUE)
/obj/item/ammo_casing/rebar/update_icon_state()
. = ..()
icon_state = "[base_icon_state]"
/obj/item/ammo_casing/rebar/syndie
name = "Jagged Iron Rod"
desc = "An Iron rod, with notches cut into it. You really don't want this stuck in you."
@@ -73,7 +81,7 @@
projectile_type = /obj/projectile/bullet/rebar/syndie
/obj/item/ammo_casing/rebar/zaukerite
name = "Zaukerite Sliver"
name = "zaukerite sliver"
desc = "A sliver of a zaukerite crystal. Due to its irregular, jagged edges, removal of an embedded zaukerite sliver should only be done by trained surgeons."
caliber = CALIBER_REBAR
icon_state = "rod_zaukerite"
@@ -81,7 +89,7 @@
projectile_type = /obj/projectile/bullet/rebar/zaukerite
/obj/item/ammo_casing/rebar/hydrogen
name = "Metallic Hydrogen Bolt"
name = "metallic hydrogen bolt"
desc = "An ultra-sharp rod made from pure metallic hydrogen. Armor may as well not exist."
caliber = CALIBER_REBAR
icon_state = "rod_hydrogen"
@@ -89,15 +97,75 @@
projectile_type = /obj/projectile/bullet/rebar/hydrogen
/obj/item/ammo_casing/rebar/healium
name = "Healium Crystal Bolt"
name = "healium crystal bolt"
desc = "Who needs a syringe gun, anyway?"
caliber = CALIBER_REBAR
icon_state = "rod_healium"
base_icon_state = "rod_healium"
projectile_type = /obj/projectile/bullet/rebar/healium
/// How many seconds of healing/sleeping action we have left, once all are spent the bolt dissolves
var/heals_left = 6 SECONDS
/obj/item/ammo_casing/rebar/healium/ready_proj(atom/target, mob/living/user, quiet, zone_override, atom/fired_from)
if (loaded_projectile)
var/obj/projectile/bullet/rebar/healium/bolt = loaded_projectile
bolt.heals_left = heals_left
return ..()
/datum/embedding/rebar_healium
embed_chance = 100
fall_chance = 0
pain_stam_pct = 0.9
ignore_throwspeed_threshold = TRUE
rip_time = 1.5 SECONDS
/// Amount of each type of damage healed per second
var/healing_per_second = 5
/// Amount of drowsiness added per second
var/drowsy_per_second = 2 SECONDS
/// At what point of drowsiness do we knock out the owner
var/drowsy_knockout = 5 SECONDS // Actually more like 8 seconds, because you need 4 ticks to reach this
/// Can this bolt cause sleeping? Used to prevent sleep stacking by shooting multiple bolts
var/can_sleep = TRUE
/datum/embedding/rebar_healium/on_successful_embed(mob/living/carbon/victim, obj/item/bodypart/target_limb)
. = ..()
for(var/obj/item/bodypart/limb as anything in victim.bodyparts)
for(var/obj/item/ammo_casing/rebar/healium/other_rebar in limb.embedded_objects)
if (other_rebar == parent)
continue
var/datum/embedding/rebar_healium/embed_data = other_rebar.get_embed()
if (istype(embed_data) && embed_data.can_sleep)
can_sleep = FALSE
return
/datum/embedding/rebar_healium/process(seconds_per_tick)
. = ..()
var/obj/item/ammo_casing/rebar/healium/casing = parent
casing.heals_left -= seconds_per_tick * 1 SECONDS
var/update_health = FALSE
var/healing = healing_per_second * seconds_per_tick
update_health += owner.adjustBruteLoss(healing, updating_health = FALSE, required_bodytype = BODYTYPE_ORGANIC)
update_health += owner.adjustFireLoss(healing, updating_health = FALSE, required_bodytype = BODYTYPE_ORGANIC)
update_health += owner.adjustToxLoss(healing, updating_health = FALSE, required_biotype = BODYTYPE_ORGANIC)
update_health += owner.adjustOxyLoss(healing, updating_health = FALSE, required_biotype = BODYTYPE_ORGANIC)
if (update_health)
owner.updatehealth()
if (can_sleep && (owner.mob_biotypes & MOB_ORGANIC))
owner.adjust_drowsiness(drowsy_per_second * seconds_per_tick)
var/datum/status_effect/drowsiness/drowsiness = owner.has_status_effect(/datum/status_effect/drowsiness)
if (drowsiness?.duration - world.time >= drowsy_knockout)
owner.Sleeping(3 SECONDS)
if (casing.heals_left <= 0)
fall_out()
/datum/embedding/rebar_healium/remove_embedding(mob/living/to_hands)
. = ..()
var/obj/item/ammo_casing/rebar/healium/casing = parent
casing.heals_left = initial(casing.heals_left)
can_sleep = TRUE
/obj/item/ammo_casing/rebar/supermatter
name = "Supermatter Bolt"
name = "supermatter bolt"
desc = "Wait, how is the bow capable of firing this without dusting?"
caliber = CALIBER_REBAR
icon_state = "rod_supermatter"
@@ -105,19 +173,10 @@
projectile_type = /obj/projectile/bullet/rebar/supermatter
/obj/item/ammo_casing/rebar/paperball
name = "Paper Ball"
name = "paper ball"
desc = "Doink!"
caliber = CALIBER_REBAR
icon_state = "paperball"
base_icon_state = "paperball"
projectile_type = /obj/projectile/bullet/paperball
newtonian_force = 0.5
/obj/item/ammo_casing/rebar/Initialize(mapload)
. = ..()
AddElement(/datum/element/caseless, TRUE)
/obj/item/ammo_casing/rebar/update_icon_state()
. = ..()
icon_state = "[base_icon_state]"

View File

@@ -176,22 +176,19 @@
armour_penetration = 100
wound_bonus = -100
exposed_wound_bonus = -100
embed_type = null
embed_falloff_tile = -3
shrapnel_type = /obj/item/ammo_casing/rebar/healium
embed_type = /datum/embedding/rebar_healium
/// Amount of heals left in our bolt, so we can track it between embeds/misses
var/heals_left = 6 SECONDS
/obj/projectile/bullet/rebar/healium/on_hit(atom/target, blocked = 0, pierce_hit)
/obj/projectile/bullet/rebar/healium/Initialize(mapload)
. = ..()
if(!iscarbon(target))
return BULLET_ACT_HIT
var/mob/living/breather = target
breather.SetSleeping(3 SECONDS)
breather.adjustFireLoss(-30, updating_health = TRUE, required_bodytype = BODYTYPE_ORGANIC)
breather.adjustToxLoss(-30, updating_health = TRUE, required_biotype = BODYTYPE_ORGANIC)
breather.adjustBruteLoss(-30, updating_health = TRUE, required_bodytype = BODYTYPE_ORGANIC)
breather.adjustOxyLoss(-30, updating_health = TRUE, required_biotype = BODYTYPE_ORGANIC, required_respiration_type = ALL)
RegisterSignals(src, list(COMSIG_PROJECTILE_ON_SPAWN_DROP, COMSIG_PROJECTILE_ON_SPAWN_EMBEDDED), PROC_REF(on_spawn_embedded))
return BULLET_ACT_HIT
/obj/projectile/bullet/rebar/healium/proc/on_spawn_embedded(datum/source, obj/item/ammo_casing/rebar/healium/rebar)
SIGNAL_HANDLER
rebar.heals_left = heals_left
/obj/projectile/bullet/rebar/supermatter
name = "supermatter bolt"