mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2026-07-14 17:45:02 +01:00
21b4095dfd
Upstream 04/17/2026 fixes https://github.com/Bubberstation/Bubberstation/issues/5549 --------- Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: tgstation-ci[bot] <179393467+tgstation-ci[bot]@users.noreply.github.com> Co-authored-by: ArcaneMusic <41715314+ArcaneMusic@users.noreply.github.com> Co-authored-by: MrMelbert <51863163+MrMelbert@users.noreply.github.com> Co-authored-by: Rhials <28870487+Rhials@users.noreply.github.com> Co-authored-by: rageguy505 <54517726+rageguy505@users.noreply.github.com> Co-authored-by: LemonInTheDark <58055496+LemonInTheDark@users.noreply.github.com> Co-authored-by: John Willard <53777086+JohnFulpWillard@users.noreply.github.com> Co-authored-by: Aliceee2ch <160794176+Aliceee2ch@users.noreply.github.com> Co-authored-by: Time-Green <7501474+Time-Green@users.noreply.github.com> Co-authored-by: Tsar-Salat <62388554+Tsar-Salat@users.noreply.github.com> Co-authored-by: SmArtKar <44720187+SmArtKar@users.noreply.github.com> Co-authored-by: Maxipat <108554989+Maxipat112@users.noreply.github.com> Co-authored-by: SyncIt21 <110812394+SyncIt21@users.noreply.github.com> Co-authored-by: deltanedas <39013340+deltanedas@users.noreply.github.com> Co-authored-by: SimplyLogan <47579821+loganuk@users.noreply.github.com> Co-authored-by: loganuk <fakeemail123@aol.com> Co-authored-by: Leland Kemble <70413276+lelandkemble@users.noreply.github.com> Co-authored-by: FalloutFalcon <86381784+FalloutFalcon@users.noreply.github.com> Co-authored-by: Roxy <75404941+TealSeer@users.noreply.github.com> Co-authored-by: Lucy <lucy@absolucy.moe> Co-authored-by: siliconOpossum <138069572+siliconOpossum@users.noreply.github.com> Co-authored-by: Isratosh <Isratosh@hotmail.com> Co-authored-by: TheRyeGuyWhoWillNowDie <70169560+TheRyeGuyWhoWillNowDie@users.noreply.github.com> Co-authored-by: Neocloudy <88008002+Neocloudy@users.noreply.github.com> Co-authored-by: Alexander V. <volas@ya.ru> Co-authored-by: ElGitificador <168473461+ElGitificador@users.noreply.github.com> Co-authored-by: Twaticus <46540570+Twaticus@users.noreply.github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Bloop <13398309+vinylspiders@users.noreply.github.com> Co-authored-by: Cameron Lennox <killer65311@gmail.com> Co-authored-by: Tim <timothymtorres@gmail.com> Co-authored-by: Iamgoofball <iamgoofball@gmail.com> Co-authored-by: Layzu666 <121319428+Layzu666@users.noreply.github.com> Co-authored-by: Arturlang <24881678+Arturlang@users.noreply.github.com> Co-authored-by: _0Steven <42909981+00-Steven@users.noreply.github.com> Co-authored-by: mrmanlikesbt <99309552+mrmanlikesbt@users.noreply.github.com> Co-authored-by: Ben10Omintrix <138636438+Ben10Omintrix@users.noreply.github.com> Co-authored-by: John F. Kennedy <54908920+MacaroniCritter@users.noreply.github.com> Co-authored-by: Cursor <102828457+theselfish@users.noreply.github.com> Co-authored-by: Josh <josh.adam.powell@gmail.com> Co-authored-by: Josh Powell <josh.powell@softwire.com> Co-authored-by: Yobrocharlie <Charliemiller5617@gmail.com> Co-authored-by: Hardly3D <66234359+Hardly3D@users.noreply.github.com> Co-authored-by: shayoki <96078776+shayoki@users.noreply.github.com> Co-authored-by: LT3 <83487515+lessthnthree@users.noreply.github.com>
856 lines
33 KiB
Plaintext
856 lines
33 KiB
Plaintext
/obj/item/stack/medical
|
|
name = "medical pack"
|
|
singular_name = "medical pack"
|
|
icon = 'icons/obj/medical/stack_medical.dmi'
|
|
worn_icon_state = "nothing"
|
|
amount = 6
|
|
max_amount = 6
|
|
w_class = WEIGHT_CLASS_TINY
|
|
full_w_class = WEIGHT_CLASS_TINY
|
|
throw_speed = 3
|
|
throw_range = 7
|
|
resistance_flags = FLAMMABLE
|
|
max_integrity = 40
|
|
novariants = FALSE
|
|
item_flags = NOBLUDGEON|SKIP_FANTASY_ON_SPAWN
|
|
cost = 250
|
|
source = /datum/robot_energy_storage/medical
|
|
merge_type = /obj/item/stack/medical
|
|
|
|
/// Verb used when applying this object to someone
|
|
var/apply_verb = "applying"
|
|
/// If set and this used as a splint for a broken bone wound,
|
|
/// This is used as a multiplier for applicable slowdowns (lower = better) (also for speeding up burn recoveries)
|
|
var/splint_factor
|
|
/// Like splint_factor but for burns instead of bone wounds. This is a multiplier used to speed up burn recoveries
|
|
var/burn_cleanliness_bonus
|
|
/// How much blood flow this stack can absorb if used as a bandage on a cut wound.
|
|
/// note that absorption is how much we lower the flow rate, not the raw amount of blood we suck up
|
|
var/absorption_capacity
|
|
/// How quickly we lower the blood flow on a cut wound we're bandaging.
|
|
/// Expected lifetime of this bandage in seconds is thus absorption_capacity/absorption_rate,
|
|
/// or until the cut heals, whichever comes first
|
|
var/absorption_rate
|
|
|
|
/// How long it takes to apply it to yourself
|
|
var/self_delay = 5 SECONDS
|
|
/// How long it takes to apply it to someone else
|
|
var/other_delay = 0
|
|
/// If we've still got more and the patient is still hurt, should we keep going automatically?
|
|
var/repeating = FALSE
|
|
/// How much brute we heal per application. This is the only number that matters for simplemobs
|
|
var/heal_brute
|
|
/// How much burn we heal per application
|
|
var/heal_burn
|
|
/// How much we reduce bleeding per application on cut wounds
|
|
var/stop_bleeding
|
|
/// How much sanitization to apply to burn wounds on application
|
|
var/sanitization
|
|
/// How much we add to flesh_healing for burn wounds on application
|
|
var/flesh_regeneration
|
|
/// Whether this item can be used on dead bodies
|
|
var/works_on_dead = FALSE
|
|
/// The sound this makes when starting healing with this item
|
|
var/heal_begin_sound = null
|
|
/// The sound this makes when healed successfully with this item
|
|
var/heal_end_sound = null
|
|
/// The sound this makes when doing a continuous loop of healing with this item
|
|
var/heal_continuous_sound = null
|
|
|
|
/obj/item/stack/medical/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers)
|
|
if(!isliving(interacting_with))
|
|
return NONE
|
|
if(!begin_heal_loop(interacting_with, user, auto_change_zone = TRUE))
|
|
return NONE // [ITEM_INTERACT_BLOCKING] would be redundant as we are nobludgeon
|
|
return ITEM_INTERACT_SUCCESS
|
|
|
|
/obj/item/stack/medical/interact_with_atom_secondary(atom/interacting_with, mob/living/user, list/modifiers)
|
|
if(!isliving(interacting_with))
|
|
return NONE
|
|
if(!begin_heal_loop(interacting_with, user, auto_change_zone = FALSE))
|
|
return NONE // see above
|
|
return ITEM_INTERACT_SUCCESS
|
|
|
|
/obj/item/stack/medical/Initialize(mapload, new_amount, merge, list/mat_override, mat_amt)
|
|
. = ..()
|
|
register_item_context()
|
|
|
|
/obj/item/stack/medical/add_item_context(obj/item/source, list/context, atom/target, mob/living/user)
|
|
if(!isliving(target))
|
|
return NONE
|
|
if(iscarbon(target))
|
|
context[SCREENTIP_CONTEXT_LMB] = "Auto Heal"
|
|
context[SCREENTIP_CONTEXT_RMB] = "Manual Heal"
|
|
else
|
|
context[SCREENTIP_CONTEXT_LMB] = "Heal"
|
|
return CONTEXTUAL_SCREENTIP_SET
|
|
|
|
/obj/item/stack/medical/apply_fantasy_bonuses(bonus)
|
|
. = ..()
|
|
if(heal_brute)
|
|
heal_brute = modify_fantasy_variable("heal_brute", heal_brute, bonus)
|
|
if(heal_burn)
|
|
heal_burn = modify_fantasy_variable("heal_burn", heal_burn, bonus)
|
|
if(stop_bleeding)
|
|
stop_bleeding = modify_fantasy_variable("stop_bleeding", stop_bleeding, bonus/10)
|
|
if(sanitization)
|
|
sanitization = modify_fantasy_variable("sanitization", sanitization, bonus/10)
|
|
if(flesh_regeneration)
|
|
flesh_regeneration = modify_fantasy_variable("flesh_regeneration", flesh_regeneration, bonus/10)
|
|
|
|
/obj/item/stack/medical/remove_fantasy_bonuses(bonus)
|
|
heal_brute = reset_fantasy_variable("heal_brute", heal_brute)
|
|
heal_burn = reset_fantasy_variable("heal_burn", heal_burn)
|
|
stop_bleeding = reset_fantasy_variable("stop_bleeding", stop_bleeding)
|
|
sanitization = reset_fantasy_variable("sanitization", sanitization)
|
|
flesh_regeneration = reset_fantasy_variable("flesh_regeneration", flesh_regeneration)
|
|
return ..()
|
|
|
|
/// Used to begin the recursive healing loop.
|
|
/// Returns TRUE if we entered the loop, FALSE if we didn't
|
|
/obj/item/stack/medical/proc/begin_heal_loop(mob/living/patient, mob/living/user, auto_change_zone = TRUE)
|
|
if(DOING_INTERACTION_WITH_TARGET(user, patient))
|
|
return FALSE
|
|
var/heal_zone = check_zone(user.zone_selected)
|
|
if(!try_heal_checks(patient, user, heal_zone))
|
|
return FALSE
|
|
SSblackbox.record_feedback("nested tally", "medical_item_used", 1, list("[auto_change_zone ? "auto" : "manual"]", "[type]"))
|
|
patient.balloon_alert(user, "[apply_verb] [parse_zone(heal_zone)]...")
|
|
INVOKE_ASYNC(src, PROC_REF(try_heal), patient, user, heal_zone, FALSE, iscarbon(patient) && auto_change_zone) // auto change is useless for non-carbons
|
|
return TRUE
|
|
|
|
/**
|
|
* What actually handles printing the message that we're starting to heal someone, and trying to heal them
|
|
*
|
|
* This proc is recursively called until we run out of charges OR until the patient is fully healed
|
|
* OR until the target zone is fully healed (if auto_change_zone is FALSE)
|
|
*
|
|
* * patient - The mob we're trying to heal
|
|
* * user - The mob that's trying to heal the patient
|
|
* * healed_zone - The zone we're trying to heal on the patient
|
|
* Disregarded if auto_change_zone is TRUE
|
|
* * silent - If we should not print the message that we're starting to heal the patient
|
|
* Used so looping the proc doesn't spam messages
|
|
* * auto_change_zone - Handles the behavior when we finish healing a zone
|
|
* If auto_change_zone is set to TRUE, it picks the next most damaged zone to heal
|
|
* If auto_change_zone is set to FALSE, it'll give the user a chance to pick a new zone to heal
|
|
* If continuous is set to true, it will play the continuous sound for healing
|
|
*/
|
|
/obj/item/stack/medical/proc/try_heal(mob/living/patient, mob/living/user, healed_zone, silent = FALSE, auto_change_zone = TRUE, continuous = FALSE)
|
|
if(heal_begin_sound && !continuous)
|
|
playsound(patient, heal_begin_sound, 75, TRUE, MEDIUM_RANGE_SOUND_EXTRARANGE)
|
|
if(patient == user)
|
|
if(!silent)
|
|
user.visible_message(
|
|
span_notice("[user] starts to apply [src] on [user.p_them()]self..."),
|
|
span_notice("You begin applying [src] on yourself..."),
|
|
visible_message_flags = ALWAYS_SHOW_SELF_MESSAGE,
|
|
)
|
|
if(!do_after(
|
|
user,
|
|
self_delay * (auto_change_zone ? 1 : 0.9),
|
|
patient,
|
|
extra_checks = CALLBACK(src, PROC_REF(can_heal), patient, user, healed_zone),
|
|
))
|
|
return
|
|
if(!auto_change_zone)
|
|
healed_zone = check_zone(user.zone_selected)
|
|
if(!try_heal_checks(patient, user, healed_zone))
|
|
return
|
|
|
|
else if(other_delay)
|
|
if(!silent)
|
|
user.visible_message(
|
|
span_notice("[user] starts to apply [src] on [patient]."),
|
|
span_notice("You begin applying [src] on [patient]..."),
|
|
visible_message_flags = ALWAYS_SHOW_SELF_MESSAGE,
|
|
)
|
|
if(!do_after(
|
|
user,
|
|
other_delay * (auto_change_zone ? 1 : 0.9),
|
|
patient,
|
|
extra_checks = CALLBACK(src, PROC_REF(can_heal), patient, user, healed_zone),
|
|
))
|
|
return
|
|
if(!auto_change_zone)
|
|
healed_zone = check_zone(user.zone_selected)
|
|
if(!try_heal_checks(patient, user, healed_zone))
|
|
return
|
|
|
|
else
|
|
if(!silent)
|
|
user.visible_message(
|
|
span_notice("[user] applies [src] on [patient]."),
|
|
span_notice("You apply [src] on [patient]."),
|
|
visible_message_flags = ALWAYS_SHOW_SELF_MESSAGE,
|
|
)
|
|
|
|
if(iscarbon(patient))
|
|
if(!heal_carbon(patient, user, healed_zone))
|
|
return
|
|
else if(isanimal_or_basicmob(patient))
|
|
if(!heal_simplemob(patient, user))
|
|
return
|
|
else
|
|
CRASH("Stack medical item healing a non-carbon, non-animal mob [patient] ([patient.type])")
|
|
if(!use(1) || !repeating || amount <= 0)
|
|
var/atom/alert_loc = QDELETED(src) ? user : src
|
|
alert_loc.balloon_alert(user, repeating ? "all used up!" : "treated [parse_zone(healed_zone)]")
|
|
if(heal_end_sound)
|
|
playsound(patient, heal_end_sound, 75, TRUE, MEDIUM_RANGE_SOUND_EXTRARANGE)
|
|
return
|
|
if(heal_continuous_sound && (continuous || !silent))
|
|
playsound(patient, heal_continuous_sound, 75, TRUE, MEDIUM_RANGE_SOUND_EXTRARANGE)
|
|
log_combat(user, patient, "healed", src)
|
|
|
|
// first, just try looping
|
|
// 1. we can keep healing the current target
|
|
// 2. the user's changed their target (and thus we should heal that limb instead)
|
|
var/preferred_target = check_zone(user.zone_selected)
|
|
if(try_heal_checks(patient, user, preferred_target, silent = TRUE))
|
|
if(preferred_target != healed_zone)
|
|
patient.balloon_alert(user, "[apply_verb] [parse_zone(preferred_target)]...")
|
|
try_heal(patient, user, preferred_target, TRUE, auto_change_zone, TRUE)
|
|
return
|
|
|
|
// second, handle what happens otherwise
|
|
if(!iscarbon(patient))
|
|
// behavior 0: non-carbons have no limbs so we can assume they are fully healed
|
|
patient.balloon_alert(user, "fully treated")
|
|
else if(auto_change_zone)
|
|
// behavior 1: automatically pick another zone to heal
|
|
try_heal_auto_change_zone(patient, user, preferred_target, healed_zone)
|
|
else
|
|
// behavior 2: assess injury, giving the user time to manually pick another zone
|
|
try_heal_manual_target(patient, user)
|
|
if(heal_end_sound)
|
|
playsound(patient, heal_end_sound, 75, TRUE, MEDIUM_RANGE_SOUND_EXTRARANGE)
|
|
|
|
/obj/item/stack/medical/proc/try_heal_auto_change_zone(mob/living/carbon/patient, mob/living/user, preferred_target, last_zone)
|
|
PRIVATE_PROC(TRUE)
|
|
|
|
var/list/other_affected_limbs = list()
|
|
for(var/obj/item/bodypart/limb as anything in patient.get_bodyparts())
|
|
if(!try_heal_checks(patient, user, limb.body_zone, silent = TRUE))
|
|
continue
|
|
other_affected_limbs += limb.body_zone
|
|
|
|
if(!length(other_affected_limbs))
|
|
patient.balloon_alert(user, "fully treated")
|
|
return
|
|
|
|
var/next_picked = (preferred_target in other_affected_limbs) ? preferred_target : other_affected_limbs[1]
|
|
if(next_picked != last_zone)
|
|
patient.balloon_alert(user, "[apply_verb] [parse_zone(next_picked)]...")
|
|
try_heal(patient, user, next_picked, silent = TRUE, auto_change_zone = TRUE, continuous = TRUE)
|
|
|
|
/obj/item/stack/medical/proc/try_heal_manual_target(mob/living/carbon/patient, mob/living/user)
|
|
PRIVATE_PROC(TRUE)
|
|
|
|
patient.balloon_alert(user, "assessing injury...")
|
|
if(!do_after(user, 1 SECONDS, patient))
|
|
return
|
|
var/new_zone = check_zone(user.zone_selected)
|
|
if(!try_heal_checks(patient, user, new_zone))
|
|
return
|
|
patient.balloon_alert(user, "[apply_verb] [parse_zone(new_zone)]...")
|
|
try_heal(patient, user, new_zone, silent = TRUE, auto_change_zone = FALSE, continuous = TRUE)
|
|
|
|
/// Checks if the passed patient can be healed by the passed user
|
|
/obj/item/stack/medical/proc/can_heal(mob/living/patient, mob/living/user, healed_zone, silent = FALSE)
|
|
return patient.try_inject(user, healed_zone, injection_flags = silent ? NONE : INJECT_TRY_SHOW_ERROR_MESSAGE)
|
|
|
|
/// Checks a bunch of stuff to see if we can heal the patient, including can_heal
|
|
/// Gives a feedback if we can't ultimatly heal the patient (unless silent is TRUE)
|
|
/obj/item/stack/medical/proc/try_heal_checks(mob/living/patient, mob/living/user, healed_zone, silent = FALSE)
|
|
if(!(healed_zone in patient.get_all_limbs()))
|
|
healed_zone = BODY_ZONE_CHEST
|
|
|
|
if(!can_heal(patient, user, healed_zone, silent))
|
|
// has its own feedback
|
|
return FALSE
|
|
if(!works_on_dead && patient.stat == DEAD)
|
|
if(!silent)
|
|
patient.balloon_alert(user, "[patient.p_theyre()] dead!")
|
|
return FALSE
|
|
|
|
if(iscarbon(patient))
|
|
var/mob/living/carbon/carbon_patient = patient
|
|
var/obj/item/bodypart/affecting = carbon_patient.get_bodypart(healed_zone)
|
|
if(!affecting) //Missing limb?
|
|
if(!silent)
|
|
carbon_patient.balloon_alert(user, "no [parse_zone(healed_zone)]!")
|
|
return FALSE
|
|
if(!IS_ORGANIC_LIMB(affecting)) //Limb must be organic to be healed - RR
|
|
if(!silent)
|
|
carbon_patient.balloon_alert(user, "[affecting.plaintext_zone] is not organic!")
|
|
return FALSE
|
|
|
|
var/datum/wound/burn/flesh/any_burn_wound = locate() in affecting.wounds
|
|
var/can_heal_burn_wounds = (flesh_regeneration || sanitization) && any_burn_wound?.can_be_ointmented_or_meshed()
|
|
var/can_suture_bleeding = stop_bleeding && affecting.cached_bleed_rate > 0
|
|
var/brute_to_heal = heal_brute && affecting.brute_dam > 0
|
|
var/burn_to_heal = heal_burn && affecting.burn_dam > 0
|
|
|
|
if(!brute_to_heal && !burn_to_heal && !can_heal_burn_wounds && !can_suture_bleeding)
|
|
if(!silent)
|
|
if(!brute_to_heal && stop_bleeding) // no brute, no bleeding
|
|
carbon_patient.balloon_alert(user, "[affecting.plaintext_zone] is not bleeding or bruised!")
|
|
else if(!burn_to_heal && (flesh_regeneration || sanitization) && any_burn_wound) // no burns, existing burn wounds are treated
|
|
carbon_patient.balloon_alert(user, "[affecting.plaintext_zone] is fully treated, give it time!")
|
|
else if(!affecting.brute_dam && !affecting.burn_dam) // not hurt at all
|
|
carbon_patient.balloon_alert(user, "[affecting.plaintext_zone] is not hurt!")
|
|
else // probably hurt in some way but we are not the right item for this
|
|
carbon_patient.balloon_alert(user, "can't heal [affecting.plaintext_zone] with [name]!")
|
|
return FALSE
|
|
return TRUE
|
|
|
|
if(isanimal_or_basicmob(patient))
|
|
if(!heal_brute) // only brute can heal
|
|
if(!silent)
|
|
patient.balloon_alert(user, "can't heal with [name]!")
|
|
return FALSE
|
|
if(!(patient.mob_biotypes & MOB_ORGANIC))
|
|
if(!silent)
|
|
patient.balloon_alert(user, "no organic tissue!")
|
|
return FALSE
|
|
if(patient.health == patient.maxHealth)
|
|
if(!silent)
|
|
patient.balloon_alert(user, "not hurt!")
|
|
return FALSE
|
|
return TRUE
|
|
|
|
return FALSE
|
|
|
|
/// The healing effects on a carbon patient.
|
|
/// Since we have extra details for dealing with bodyparts, we get our own fancy proc.
|
|
/// Still returns TRUE on success and FALSE on fail
|
|
/obj/item/stack/medical/proc/heal_carbon(mob/living/carbon/patient, mob/living/user, healed_zone)
|
|
var/obj/item/bodypart/affecting = patient.get_bodypart(healed_zone)
|
|
user.visible_message(
|
|
span_green("[user] applies [src] on [patient]'s [affecting.plaintext_zone]."),
|
|
span_green("You apply [src] on [patient]'s [affecting.plaintext_zone]."),
|
|
visible_message_flags = ALWAYS_SHOW_SELF_MESSAGE,
|
|
)
|
|
var/previous_damage = affecting.get_damage()
|
|
if(affecting.heal_damage(heal_brute, heal_burn))
|
|
patient.update_damage_overlays()
|
|
if(stop_bleeding)
|
|
for(var/datum/wound/wound as anything in affecting.wounds)
|
|
if(wound.blood_flow)
|
|
wound.adjust_blood_flow(-1 * stop_bleeding * (user == patient ? 0.7 : 1))
|
|
break // one at a time
|
|
affecting.adjustBleedStacks(-1 * stop_bleeding, 0)
|
|
if(flesh_regeneration || sanitization)
|
|
for(var/datum/wound/burn/flesh/wound in affecting.wounds)
|
|
if(wound.can_be_ointmented_or_meshed())
|
|
wound.flesh_healing += flesh_regeneration
|
|
wound.sanitization += sanitization
|
|
break // one at a time
|
|
post_heal_effects(max(previous_damage - affecting.get_damage(), 0), patient, user)
|
|
return TRUE
|
|
|
|
/// Healing a simple mob, just an adjust_brute_loss() call
|
|
/obj/item/stack/medical/proc/heal_simplemob(mob/living/patient, mob/living/user)
|
|
patient.adjust_brute_loss(-1 * (heal_brute * patient.maxHealth / 100))
|
|
user.visible_message(
|
|
span_green("[user] applies [src] on [patient]."),
|
|
span_green("You apply [src] on [patient]."),
|
|
visible_message_flags = ALWAYS_SHOW_SELF_MESSAGE,
|
|
)
|
|
return TRUE
|
|
|
|
///Override this proc for special post heal effects. Only called for carbon patients.
|
|
/obj/item/stack/medical/proc/post_heal_effects(amount_healed, mob/living/carbon/healed_mob, mob/living/user)
|
|
return
|
|
|
|
/obj/item/stack/medical/bruise_pack
|
|
name = "bruise pack"
|
|
singular_name = "bruise pack"
|
|
desc = "A therapeutic gel pack and bandages designed to treat blunt-force trauma."
|
|
icon_state = "brutepack"
|
|
lefthand_file = 'icons/mob/inhands/equipment/medical_lefthand.dmi'
|
|
righthand_file = 'icons/mob/inhands/equipment/medical_righthand.dmi'
|
|
heal_brute = 40
|
|
self_delay = 4 SECONDS
|
|
other_delay = 2 SECONDS
|
|
merge_type = /obj/item/stack/medical/bruise_pack
|
|
apply_verb = "applying to"
|
|
|
|
/obj/item/stack/medical/bruise_pack/grind_results()
|
|
return list(/datum/reagent/medicine/c2/libital = 10)
|
|
|
|
/obj/item/stack/medical/bruise_pack/suicide_act(mob/living/user)
|
|
user.visible_message(span_suicide("[user] is bludgeoning [user.p_them()]self with [src]! It looks like [user.p_theyre()] trying to commit suicide!"))
|
|
return BRUTELOSS
|
|
|
|
/obj/item/stack/medical/wrap
|
|
name = "wrap"
|
|
desc = "Something you can wrap around someone, like a hug."
|
|
gender = PLURAL
|
|
icon_state = "gauze"
|
|
apply_verb = "wrapping"
|
|
works_on_dead = TRUE
|
|
|
|
/obj/item/stack/medical/wrap/Initialize(mapload, new_amount, merge, list/mat_override, mat_amt)
|
|
. = ..()
|
|
AddComponent( \
|
|
/datum/component/limb_applicable, \
|
|
apply_category = LIMB_ITEM_GAUZE, \
|
|
override_existing = TRUE, \
|
|
can_apply = CALLBACK(src, PROC_REF(can_gauze_limb)), \
|
|
do_apply = CALLBACK(src, PROC_REF(do_gauze_limb)), \
|
|
on_apply = CALLBACK(src, PROC_REF(on_gauze_limb)), \
|
|
)
|
|
RegisterSignals(src, list(COMSIG_ITEM_APPLIED_TO_LIMB, COMSIG_ITEM_UNAPPLIED_FROM_LIMB), PROC_REF(update_wounds))
|
|
|
|
/obj/item/stack/medical/wrap/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers)
|
|
return NONE // uses component
|
|
|
|
/// Callback for limb applicability component
|
|
/obj/item/stack/medical/wrap/proc/can_gauze_limb(mob/user, mob/living/patient, obj/item/bodypart/limb)
|
|
var/can_gauze = FALSE
|
|
for(var/datum/wound/wound as anything in limb.wounds)
|
|
if(!(wound.wound_flags & ACCEPTS_GAUZE))
|
|
continue
|
|
can_gauze = TRUE
|
|
break
|
|
|
|
. = NONE
|
|
var/surgery_prepped = HAS_TRAIT(limb, TRAIT_READY_TO_OPERATE)
|
|
if(!surgery_prepped)
|
|
. |= LIMB_APPLICABLE_BLOCK_ITEM_INTERACTION
|
|
|
|
if(!can_gauze)
|
|
if(!surgery_prepped)
|
|
patient.balloon_alert(user, LAZYLEN(limb.wounds) ? "can't gauze!" : "no wounds!")
|
|
. |= LIMB_APPLICABLE_BLOCK_APPLICATION
|
|
return .
|
|
|
|
var/obj/item/stack/medical/wrap/current_gauze = LAZYACCESS(limb.applied_items, LIMB_ITEM_GAUZE)
|
|
if(current_gauze && (current_gauze.absorption_capacity * 1.2 > absorption_capacity)) // ignore if our new wrap is < 20% better than the current one, so someone doesn't bandage it 5 times in a row
|
|
if(!surgery_prepped)
|
|
patient.balloon_alert(user, pick("already bandaged!", "bandage is clean!")) // good enough
|
|
. |= LIMB_APPLICABLE_BLOCK_APPLICATION
|
|
return .
|
|
|
|
/// Callback for limb applicability component
|
|
/obj/item/stack/medical/wrap/proc/do_gauze_limb(mob/user, mob/living/patient, obj/item/bodypart/limb)
|
|
|
|
var/scanned_wound = FALSE
|
|
for(var/datum/wound/wound as anything in limb.wounds)
|
|
if(!HAS_TRAIT(wound, TRAIT_WOUND_SCANNED))
|
|
continue
|
|
scanned_wound = TRUE
|
|
break
|
|
|
|
var/treatment_delay = (user == patient ? self_delay : other_delay)
|
|
if(scanned_wound)
|
|
treatment_delay *= 0.5
|
|
if(user == patient)
|
|
user.visible_message(
|
|
span_warning("[user] begins expertly wrapping the wounds on [p_their()]'s [limb.plaintext_zone] with [src]..."),
|
|
span_warning("You begin quickly wrapping the wounds on your [limb.plaintext_zone] with [src], keeping the holo-image indications in mind..."),
|
|
visible_message_flags = ALWAYS_SHOW_SELF_MESSAGE,
|
|
)
|
|
else
|
|
user.visible_message(
|
|
span_warning("[user] begins expertly wrapping the wounds on [patient]'s [limb.plaintext_zone] with [src]..."),
|
|
span_warning("You begin quickly wrapping the wounds on [patient]'s [limb.plaintext_zone] with [src], keeping the holo-image indications in mind..."),
|
|
visible_message_flags = ALWAYS_SHOW_SELF_MESSAGE,
|
|
)
|
|
else
|
|
user.visible_message(
|
|
span_warning("[user] begins wrapping the wounds on [patient]'s [limb.plaintext_zone] with [src]..."),
|
|
span_warning("You begin wrapping the wounds on [user == patient ? "your" : "[patient]'s"] [limb.plaintext_zone] with [src]..."),
|
|
visible_message_flags = ALWAYS_SHOW_SELF_MESSAGE,
|
|
)
|
|
if(heal_begin_sound)
|
|
playsound(src, heal_begin_sound, 75, TRUE, MEDIUM_RANGE_SOUND_EXTRARANGE)
|
|
|
|
if(!do_after(user, treatment_delay, patient))
|
|
return FALSE
|
|
|
|
if(heal_end_sound)
|
|
playsound(patient, heal_end_sound, 75, TRUE, MEDIUM_RANGE_SOUND_EXTRARANGE)
|
|
return TRUE
|
|
|
|
/// Callback for limb applicability component
|
|
/obj/item/stack/medical/wrap/proc/on_gauze_limb(mob/user, mob/living/patient, obj/item/bodypart/limb)
|
|
patient.balloon_alert(user, "wrapped [limb.plaintext_zone]")
|
|
user.visible_message(
|
|
span_green("[user] applies [src] to [patient]'s [limb.plaintext_zone]."),
|
|
span_green("You bandage the wounds on [user == patient ? "your" : "[patient]'s"] [limb.plaintext_zone]."),
|
|
visible_message_flags = ALWAYS_SHOW_SELF_MESSAGE,
|
|
)
|
|
if(limb.cached_bleed_rate)
|
|
add_mob_blood(patient)
|
|
// Dressing burns provides a "one-time" bonus to sanitization and healing
|
|
// However, any notable infection will reduce the effectiveness of this bonus
|
|
for(var/datum/wound/burn/flesh/wound in limb.wounds)
|
|
wound.sanitization += sanitization * (wound.infection > 0.1 ? 0.2 : 1)
|
|
wound.flesh_healing += flesh_regeneration * (wound.infection > 0.1 ? 0 : 1)
|
|
|
|
/// Used via signal to update wounds
|
|
/obj/item/stack/medical/wrap/proc/update_wounds(datum/source, obj/item/bodypart/limb)
|
|
SIGNAL_HANDLER
|
|
for(var/datum/wound/gauzed as anything in limb.wounds)
|
|
gauzed.update_inefficiencies()
|
|
|
|
/obj/item/stack/medical/wrap/gauze
|
|
name = "medical gauze"
|
|
desc = "A roll of elastic cloth, perfect for stabilizing all kinds of wounds, from cuts and burns, to broken bones."
|
|
singular_name = "medical gauze"
|
|
self_delay = 5 SECONDS
|
|
other_delay = 2 SECONDS
|
|
max_amount = 12
|
|
amount = 6
|
|
custom_price = PAYCHECK_CREW * 2
|
|
absorption_rate = 0.125
|
|
absorption_capacity = 5
|
|
sanitization = 3
|
|
flesh_regeneration = 5
|
|
splint_factor = 0.7
|
|
burn_cleanliness_bonus = 0.35
|
|
merge_type = /obj/item/stack/medical/wrap/gauze
|
|
heal_end_sound = SFX_BANDAGE_END
|
|
heal_begin_sound = SFX_BANDAGE_BEGIN
|
|
drop_sound = SFX_CLOTH_DROP
|
|
pickup_sound = SFX_CLOTH_PICKUP
|
|
|
|
/obj/item/stack/medical/wrap/gauze/grind_results()
|
|
return list(/datum/reagent/cellulose = 2)
|
|
|
|
/obj/item/stack/medical/wrap/gauze/add_context(atom/source, list/context, obj/item/held_item, mob/living/user)
|
|
. = ..()
|
|
if(isnull(held_item))
|
|
return
|
|
if(held_item.tool_behaviour == TOOL_WIRECUTTER || held_item.get_sharpness())
|
|
context[SCREENTIP_CONTEXT_LMB] = "Shred Into Cloth"
|
|
return CONTEXTUAL_SCREENTIP_SET
|
|
|
|
/obj/item/stack/medical/wrap/gauze/twelve
|
|
amount = 12
|
|
|
|
/obj/item/stack/medical/wrap/gauze/item_interaction(mob/living/user, obj/item/tool, list/modifiers)
|
|
if(tool.tool_behaviour == TOOL_WIRECUTTER || tool.get_sharpness())
|
|
if(get_amount() < 2)
|
|
balloon_alert(user, "not enough gauze!")
|
|
return ITEM_INTERACT_BLOCKING
|
|
new /obj/item/stack/sheet/cloth(tool.drop_location())
|
|
if(IsReachableBy(user))
|
|
user.visible_message(span_notice("[user] cuts [src] into pieces of cloth with [tool]."), \
|
|
span_notice("You cut [src] into pieces of cloth with [tool]."), \
|
|
span_hear("You hear cutting."))
|
|
else //telekinesis
|
|
visible_message(span_notice("[tool] cuts [src] into pieces of cloth."), \
|
|
blind_message = span_hear("You hear cutting."))
|
|
use(2)
|
|
return ITEM_INTERACT_SUCCESS
|
|
|
|
return NONE
|
|
|
|
|
|
/obj/item/stack/medical/wrap/gauze/suicide_act(mob/living/user)
|
|
user.visible_message(span_suicide("[user] begins tightening [src] around [user.p_their()] neck! It looks like [user.p_they()] forgot how to use medical supplies!"))
|
|
return OXYLOSS
|
|
|
|
/obj/item/stack/medical/wrap/gauze/improvised
|
|
name = "improvised gauze"
|
|
singular_name = "improvised gauze"
|
|
desc = "A roll of cloth roughly cut from something that does a decent job of stabilizing wounds, but less efficiently so than real medical gauze."
|
|
icon_state = "gauze_imp"
|
|
self_delay = 6 SECONDS
|
|
other_delay = 3 SECONDS
|
|
splint_factor = 0.85
|
|
burn_cleanliness_bonus = 0.7
|
|
absorption_rate = 0.075
|
|
absorption_capacity = 4
|
|
sanitization = 1
|
|
flesh_regeneration = 3
|
|
merge_type = /obj/item/stack/medical/wrap/gauze/improvised
|
|
|
|
/*
|
|
The idea is for the following medical devices to work like a hybrid of the old brute packs and tend wounds,
|
|
they heal a little at a time, have reduced healing density and does not allow for rapid healing while in combat.
|
|
However they provice graunular control of where the healing is directed, this makes them better for curing work-related cuts and scrapes.
|
|
|
|
The interesting limb targeting mechanic is retained and i still believe they will be a viable choice, especially when healing others in the field.
|
|
*/
|
|
|
|
/obj/item/stack/medical/suture
|
|
name = "suture"
|
|
desc = "Basic sterile sutures used to seal up cuts and lacerations and stop bleeding."
|
|
gender = PLURAL
|
|
singular_name = "suture"
|
|
icon_state = "suture"
|
|
self_delay = 3 SECONDS
|
|
other_delay = 1 SECONDS
|
|
amount = 10
|
|
max_amount = 10
|
|
repeating = TRUE
|
|
heal_brute = 10
|
|
stop_bleeding = 0.5
|
|
merge_type = /obj/item/stack/medical/suture
|
|
apply_verb = "suturing"
|
|
drop_sound = SFX_SUTURE_DROP
|
|
pickup_sound = SFX_SUTURE_PICKUP
|
|
heal_begin_sound = SFX_SUTURE_BEGIN
|
|
heal_continuous_sound = SFX_SUTURE_CONTINUOUS
|
|
heal_end_sound = SFX_SUTURE_END
|
|
|
|
/obj/item/stack/medical/suture/grind_results()
|
|
return list(/datum/reagent/medicine/spaceacillin = 2)
|
|
|
|
/obj/item/stack/medical/suture/medicated
|
|
name = "medicated suture"
|
|
icon_state = "suture_purp"
|
|
desc = "A suture infused with drugs that speed up wound healing of the treated laceration."
|
|
heal_brute = 15
|
|
stop_bleeding = 0.75
|
|
merge_type = /obj/item/stack/medical/suture/medicated
|
|
|
|
/obj/item/stack/medical/suture/medicated/grind_results()
|
|
return list(/datum/reagent/medicine/polypyr = 1)
|
|
|
|
/obj/item/stack/medical/ointment
|
|
name = "ointment"
|
|
desc = "Basic burn ointment, rated effective for second degree burns with proper bandaging, though it's still an effective stabilizer for worse burns. Not terribly good at outright healing burns though."
|
|
gender = PLURAL
|
|
singular_name = "ointment"
|
|
icon_state = "ointment"
|
|
lefthand_file = 'icons/mob/inhands/equipment/medical_lefthand.dmi'
|
|
righthand_file = 'icons/mob/inhands/equipment/medical_righthand.dmi'
|
|
amount = 8
|
|
max_amount = 8
|
|
self_delay = 4 SECONDS
|
|
other_delay = 2 SECONDS
|
|
heal_burn = 5
|
|
flesh_regeneration = 2.5
|
|
sanitization = 0.25
|
|
merge_type = /obj/item/stack/medical/ointment
|
|
apply_verb = "applying to"
|
|
|
|
/obj/item/stack/medical/ointment/grind_results()
|
|
return list(/datum/reagent/medicine/c2/lenturi = 10)
|
|
|
|
/obj/item/stack/medical/ointment/suicide_act(mob/living/user)
|
|
user.visible_message(span_suicide("[user] is squeezing [src] into [user.p_their()] mouth! [user.p_do(TRUE)]n't [user.p_they()] know that stuff is toxic?"))
|
|
return TOXLOSS
|
|
|
|
/obj/item/stack/medical/mesh
|
|
name = "regenerative mesh"
|
|
desc = "A bacteriostatic mesh used to dress burns."
|
|
gender = PLURAL
|
|
singular_name = "mesh piece"
|
|
icon_state = "regen_mesh"
|
|
self_delay = 3 SECONDS
|
|
other_delay = 1 SECONDS
|
|
amount = 15
|
|
heal_burn = 10
|
|
max_amount = 15
|
|
repeating = TRUE
|
|
sanitization = 0.75
|
|
flesh_regeneration = 3
|
|
pickup_sound = SFX_REGEN_MESH_PICKUP
|
|
drop_sound = SFX_REGEN_MESH_DROP
|
|
heal_begin_sound = SFX_REGEN_MESH_BEGIN
|
|
heal_continuous_sound = SFX_REGEN_MESH_CONTINUOUS
|
|
heal_end_sound = SFX_REGEN_MESH_END
|
|
merge_type = /obj/item/stack/medical/mesh
|
|
|
|
///This var determines if the sterile packaging of the mesh has been opened.
|
|
var/is_open = TRUE
|
|
|
|
/obj/item/stack/medical/mesh/Initialize(mapload, new_amount, merge = TRUE, list/mat_override=null, mat_amt=1)
|
|
. = ..()
|
|
if(amount == max_amount) //only seal full mesh packs
|
|
is_open = FALSE
|
|
update_appearance()
|
|
|
|
/obj/item/stack/medical/mesh/grind_results()
|
|
return list(/datum/reagent/medicine/spaceacillin = 2)
|
|
|
|
/obj/item/stack/medical/mesh/update_icon_state()
|
|
if(is_open)
|
|
return ..()
|
|
icon_state = "regen_mesh_closed"
|
|
|
|
/obj/item/stack/medical/mesh/try_heal_checks(mob/living/patient, mob/living/user, healed_zone, silent = FALSE)
|
|
if(!is_open)
|
|
if(!silent)
|
|
balloon_alert(user, "open it first!")
|
|
return FALSE
|
|
return ..()
|
|
|
|
/obj/item/stack/medical/mesh/click_alt(mob/living/user)
|
|
if(!is_open)
|
|
balloon_alert(user, "open it first!")
|
|
return CLICK_ACTION_BLOCKING
|
|
return CLICK_ACTION_SUCCESS
|
|
|
|
/obj/item/stack/medical/mesh/attack_hand(mob/user, list/modifiers)
|
|
if(!is_open && user.get_inactive_held_item() == src)
|
|
balloon_alert(user, "open it first!")
|
|
return
|
|
return ..()
|
|
|
|
/obj/item/stack/medical/mesh/attack_self(mob/user)
|
|
if(!is_open)
|
|
is_open = TRUE
|
|
balloon_alert(user, "opened")
|
|
update_appearance()
|
|
playsound(src, 'sound/items/poster/poster_ripped.ogg', 20, TRUE)
|
|
return
|
|
return ..()
|
|
|
|
/obj/item/stack/medical/mesh/advanced
|
|
name = "advanced regenerative mesh"
|
|
desc = "An advanced mesh made with aloe extracts and sterilizing chemicals, used to treat burns."
|
|
gender = PLURAL
|
|
icon_state = "aloe_mesh"
|
|
heal_burn = 15
|
|
sanitization = 1.25
|
|
flesh_regeneration = 3.5
|
|
merge_type = /obj/item/stack/medical/mesh/advanced
|
|
|
|
/obj/item/stack/medical/mesh/advanced/grind_results()
|
|
return list(/datum/reagent/consumable/aloejuice = 1)
|
|
|
|
/obj/item/stack/medical/mesh/advanced/update_icon_state()
|
|
if(is_open)
|
|
return ..()
|
|
icon_state = "aloe_mesh_closed"
|
|
|
|
/obj/item/stack/medical/aloe
|
|
name = "aloe cream"
|
|
desc = "A healing paste for minor cuts and burns."
|
|
gender = PLURAL
|
|
singular_name = "aloe cream"
|
|
icon_state = "aloe_paste"
|
|
self_delay = 2 SECONDS
|
|
other_delay = 1 SECONDS
|
|
novariants = TRUE
|
|
amount = 20
|
|
max_amount = 20
|
|
repeating = TRUE
|
|
heal_brute = 3
|
|
heal_burn = 3
|
|
merge_type = /obj/item/stack/medical/aloe
|
|
apply_verb = "applying to"
|
|
|
|
/obj/item/stack/medical/aloe/Initialize(mapload, new_amount, merge, list/mat_override, mat_amt)
|
|
. = ..()
|
|
AddComponent(/datum/component/bakeable, /obj/item/food/badrecipe, rand(10 SECONDS, 15 SECONDS), FALSE)
|
|
|
|
/obj/item/stack/medical/aloe/grind_results()
|
|
return list(/datum/reagent/consumable/aloejuice = 1)
|
|
|
|
/obj/item/stack/medical/aloe/fresh
|
|
amount = 2
|
|
|
|
/obj/item/stack/medical/bone_gel
|
|
name = "bone gel"
|
|
singular_name = "bone gel"
|
|
desc = "A potent medical gel that, when applied to a damaged bone in a proper surgical setting, triggers an intense melding reaction to repair the wound. Can be directly applied alongside surgical sticky tape to a broken bone in dire circumstances, though this is very harmful to the patient and not recommended."
|
|
icon = 'icons/obj/medical/surgery_tools.dmi'
|
|
icon_state = "bone-gel"
|
|
inhand_icon_state = "bone-gel"
|
|
lefthand_file = 'icons/mob/inhands/equipment/medical_lefthand.dmi'
|
|
righthand_file = 'icons/mob/inhands/equipment/medical_righthand.dmi'
|
|
amount = 5
|
|
self_delay = 20
|
|
novariants = TRUE
|
|
merge_type = /obj/item/stack/medical/bone_gel
|
|
apply_verb = "applying to"
|
|
|
|
/obj/item/stack/medical/bone_gel/grind_results()
|
|
return list(/datum/reagent/bone_dust = 10, /datum/reagent/carbon = 10)
|
|
|
|
/obj/item/stack/medical/bone_gel/get_surgery_tool_overlay(tray_extended)
|
|
return "gel" + (tray_extended ? "" : "_out")
|
|
|
|
/obj/item/stack/medical/bone_gel/attack(mob/living/patient, mob/user)
|
|
patient.balloon_alert(user, "no fractures!")
|
|
return
|
|
|
|
/obj/item/stack/medical/bone_gel/suicide_act(mob/living/user)
|
|
if(!iscarbon(user))
|
|
return
|
|
var/mob/living/carbon/patient = user
|
|
patient.visible_message(span_suicide("[patient] is squirting all of [src] into [patient.p_their()] mouth! That's not proper procedure! It looks like [patient.p_theyre()] trying to commit suicide!"))
|
|
if(!do_after(patient, 2 SECONDS))
|
|
patient.visible_message(span_suicide("[patient] screws up like an idiot and still dies anyway!"))
|
|
return BRUTELOSS
|
|
|
|
patient.emote("scream")
|
|
for(var/obj/item/bodypart/bone as anything in patient.get_bodyparts())
|
|
// fine to just, use these raw, its a meme anyway
|
|
var/datum/wound/blunt/bone/severe/oof_ouch = new
|
|
oof_ouch.apply_wound(bone, wound_source = "bone gel")
|
|
var/datum/wound/blunt/bone/critical/oof_OUCH = new
|
|
oof_OUCH.apply_wound(bone, wound_source = "bone gel")
|
|
for(var/zone in patient.get_all_limbs())
|
|
patient.apply_damage(60, BRUTE, zone)
|
|
use(1)
|
|
return BRUTELOSS
|
|
|
|
/obj/item/stack/medical/bone_gel/one
|
|
amount = 1
|
|
|
|
/obj/item/stack/medical/poultice
|
|
name = "mourning poultices"
|
|
singular_name = "mourning poultice"
|
|
desc = "A type of primitive herbal poultice.\n\
|
|
While traditionally used to prepare corpses for the mourning feast, \
|
|
it can also treat scrapes and burns on the living, however, \
|
|
it is liable to cause shortness of breath when employed in this manner.\n\
|
|
It is imbued with ancient wisdom."
|
|
icon_state = "poultice"
|
|
amount = 15
|
|
max_amount = 15
|
|
heal_brute = 10
|
|
heal_burn = 10
|
|
self_delay = 40
|
|
other_delay = 10
|
|
repeating = TRUE
|
|
drop_sound = 'sound/misc/moist_impact.ogg'
|
|
mob_throw_hit_sound = 'sound/misc/moist_impact.ogg'
|
|
hitsound = 'sound/misc/moist_impact.ogg'
|
|
merge_type = /obj/item/stack/medical/poultice
|
|
apply_verb = "applying to"
|
|
works_on_dead = TRUE
|
|
|
|
/obj/item/stack/medical/poultice/post_heal_effects(amount_healed, mob/living/carbon/healed_mob, mob/living/user)
|
|
. = ..()
|
|
playsound(src, 'sound/misc/soggy.ogg', 30, TRUE)
|
|
healed_mob.adjust_oxy_loss(amount_healed)
|
|
|
|
/obj/item/stack/medical/bandage
|
|
name = "first aid bandage"
|
|
desc = "A DeForest brand bandage designed for basic first aid on blunt-force trauma."
|
|
icon_state = "bandage"
|
|
inhand_icon_state = "bandage"
|
|
novariants = TRUE
|
|
amount = 1
|
|
max_amount = 1
|
|
lefthand_file = 'icons/mob/inhands/equipment/medical_lefthand.dmi'
|
|
righthand_file = 'icons/mob/inhands/equipment/medical_righthand.dmi'
|
|
heal_brute = 25
|
|
stop_bleeding = 0.2
|
|
self_delay = 3 SECONDS
|
|
other_delay = 1 SECONDS
|
|
apply_verb = "applying to"
|
|
pickup_sound = SFX_CLOTH_PICKUP
|
|
|
|
/obj/item/stack/medical/bandage/grind_results()
|
|
return list(/datum/reagent/medicine/c2/libital = 2)
|
|
|
|
/obj/item/stack/medical/bandage/makeshift
|
|
name = "makeshift bandage"
|
|
desc = "A hastily constructed bandage designed for basic first aid on blunt-force trauma."
|
|
icon_state = "bandage_makeshift"
|
|
icon_state_preview = "bandage_makeshift"
|
|
inhand_icon_state = "bandage"
|
|
novariants = TRUE
|