diff --git a/code/__DEFINES/dcs/signals.dm b/code/__DEFINES/dcs/signals.dm index f7267a7af8d3..97049254cc10 100644 --- a/code/__DEFINES/dcs/signals.dm +++ b/code/__DEFINES/dcs/signals.dm @@ -387,6 +387,9 @@ /* #define SPEECH_IGNORE_SPAM 6 #define SPEECH_FORCED 7 */ +///from /mob/living/life() +#define COMSIG_MOB_LIFE "mob_life" + ///from /mob/say_dead(): (mob/speaker, message) #define COMSIG_MOB_DEADSAY "mob_deadsay" #define MOB_DEADSAY_SIGNAL_INTERCEPT (1<<0) @@ -420,6 +423,8 @@ ///from base of /obj/item/bodypart/proc/attach_limb(): (new_limb, special) allows you to fail limb attachment #define COMSIG_LIVING_ATTACH_LIMB "living_attach_limb" #define COMPONENT_NO_ATTACH 1 +///from base of /obj/item/bodypart/proc/drop_limb(): (special) +#define COMSIG_LIVING_DROP_LIMB "living_drop_limb" ///from base of mob/living/set_buckled(): (new_buckled) #define COMSIG_LIVING_SET_BUCKLED "living_set_buckled" diff --git a/code/__DEFINES/mobs.dm b/code/__DEFINES/mobs.dm index 8026f9635a97..f5c382c15c29 100644 --- a/code/__DEFINES/mobs.dm +++ b/code/__DEFINES/mobs.dm @@ -28,6 +28,13 @@ #define BLOOD_VOLUME_BAD 224 #define BLOOD_VOLUME_SURVIVE 122 +// Bloodloss +#define BLOOD_LOSS_MAXIMUM 30 +#define BLOOD_LOSS_DAMAGE_MAXIMUM 2 +#define BLOOD_LOSS_DAMAGE_BASE 0.013 +#define BLOOD_CAUTERIZATION_RATIO 10 +#define BLOOD_CAUTERIZATION_DAMAGE_RATIO 300 + //Sizes of mobs, used by mob/living/var/mob_size #define MOB_SIZE_TINY 0 #define MOB_SIZE_SMALL 1 diff --git a/code/_onclick/item_attack.dm b/code/_onclick/item_attack.dm index 1cf0585c0ed4..58b9604e585a 100644 --- a/code/_onclick/item_attack.dm +++ b/code/_onclick/item_attack.dm @@ -153,7 +153,7 @@ var/armor_value = run_armor_check(attack_flag = "melee", armour_penetration = I.armour_penetration) //WS Edit - Simplemobs can have armor send_item_attack_message(I, user) if(I.force) - apply_damage(I.force, I.damtype, break_modifier = I.force, blocked = armor_value) //Bone break modifier = item force + apply_damage(I.force, I.damtype, break_modifier = I.force, blocked = armor_value, sharpness = I.get_sharpness()) //Bone break modifier = item force if(I.damtype == BRUTE) if(prob(33)) I.add_mob_blood(src) diff --git a/code/datums/components/bandage.dm b/code/datums/components/bandage.dm new file mode 100644 index 000000000000..16f6a2f0b059 --- /dev/null +++ b/code/datums/components/bandage.dm @@ -0,0 +1,60 @@ +#define TREATMENT_DAMAGE_MOD 2 + +/datum/component/bandage + /// How fast do we stop bleeding? + var/bleed_reduction = 0 + /// How many healing ticks will this bandage apply? Reduced by incoming damage and current bleeding + var/lifespan = 300 + var/bandage_name = "gauze" + /// The person this bandage is applied to + var/mob/living/mummy + +/datum/component/bandage/Initialize(_bleed_reduction, _lifespan, _bandage_name) + if(!istype(parent, /obj/item/bodypart)) + return COMPONENT_INCOMPATIBLE + var/obj/item/bodypart/BP = parent + mummy = BP.owner + if(!mummy) + return COMPONENT_INCOMPATIBLE + if(_bleed_reduction) + bleed_reduction = _bleed_reduction + if(_lifespan) + lifespan = _lifespan + if(_bandage_name) + bandage_name = _bandage_name + RegisterSignal(mummy, COMSIG_MOB_APPLY_DAMGE, PROC_REF(check_damage)) + RegisterSignal(mummy, COMSIG_MOB_LIFE, PROC_REF(bandage_effects)) + RegisterSignal(parent, COMSIG_LIVING_DROP_LIMB, PROC_REF(drop_bandage)) + +/// Checks if damage to the owner is applied to this limb and reduces lifespan (perforated bandages dont work as well) +/datum/component/bandage/proc/check_damage(attacker, damage, damagetype = BRUTE, def_zone = null) + SIGNAL_HANDLER + + if(parent != mummy.get_bodypart(check_zone(def_zone))) + return + lifespan -= damage / 100 * initial(lifespan) * TREATMENT_DAMAGE_MOD //take incoming damage as a % of durability + if(lifespan <= 0) + drop_bandage() + +/// Handles healing effects and passive lifespan usage +/datum/component/bandage/proc/bandage_effects() + SIGNAL_HANDLER + + var/obj/item/bodypart/heal_target = parent + lifespan -= 1 + heal_target.bleeding // particularly nasty bleeding can burn through dressing faster + heal_target.adjust_bleeding(-bleed_reduction) + if(lifespan <= 0 || !heal_target.bleeding) //remove treatment once it's no longer able to treat + drop_bandage(TRUE) + +/// Handles deleting the component when the bandage runs out of lifespan or finishes healing. Special = bandage didn't get torn off +/datum/component/bandage/proc/drop_bandage(special = FALSE) + SIGNAL_HANDLER + + var/obj/item/bodypart/BP = parent + if(special) + to_chat(mummy, span_notice("The [bandage_name] on your [parse_zone(BP.body_zone)] has [BP.bleeding ? "done what it can" : "stopped the bleeding"].")) + else + to_chat(mummy, span_warning("The [bandage_name] on your [parse_zone(BP.body_zone)] is damaged beyond use!")) + qdel(src) + +#undef TREATMENT_DAMAGE_MOD diff --git a/code/datums/components/butchering.dm b/code/datums/components/butchering.dm index 55ba84fb5f7d..3032a98dc85c 100644 --- a/code/datums/components/butchering.dm +++ b/code/datums/components/butchering.dm @@ -73,11 +73,17 @@ "Their neck has already been already cut, you can't make the bleeding any worse!") return + var/obj/item/bodypart/throat_in_question = H.get_bodypart(BODY_ZONE_HEAD) + if(!throat_in_question) + user.show_message("[H]... doesn't have a neck.", MSG_VISUAL, \ + "They don't seem to have a neck to cut.") + return + H.visible_message("[user] slits [H]'s throat!", \ "[user] slits your throat...") log_combat(user, H, "finishes slicing the throat of") H.apply_damage(source.force, BRUTE, BODY_ZONE_HEAD) - H.bleed_rate = clamp(H.bleed_rate + 20, 0, 30) + throat_in_question.adjust_bleeding(20) H.apply_status_effect(/datum/status_effect/neck_slice) /datum/component/butchering/proc/Butcher(mob/living/butcher, mob/living/meat) diff --git a/code/datums/diseases/advance/symptoms/flesh_eating.dm b/code/datums/diseases/advance/symptoms/flesh_eating.dm index f6cd5698d73d..5f18f6c78a91 100644 --- a/code/datums/diseases/advance/symptoms/flesh_eating.dm +++ b/code/datums/diseases/advance/symptoms/flesh_eating.dm @@ -63,7 +63,7 @@ Bonus if(bleed) if(ishuman(M)) var/mob/living/carbon/human/H = M - H.bleed_rate += 5 * power + H.cause_bleeding(5 * power) return 1 /* diff --git a/code/datums/status_effects/debuffs.dm b/code/datums/status_effects/debuffs.dm index 52087f03174c..02b96c1b81de 100644 --- a/code/datums/status_effects/debuffs.dm +++ b/code/datums/status_effects/debuffs.dm @@ -334,7 +334,8 @@ /datum/status_effect/neck_slice/tick() var/mob/living/carbon/human/H = owner - if(H.stat == DEAD || H.bleed_rate <= 8) + var/obj/item/bodypart/throat_in_question = H.get_bodypart(BODY_ZONE_HEAD) + if(H.stat == DEAD || throat_in_question?.bleeding <= 8) H.remove_status_effect(/datum/status_effect/neck_slice) if(prob(10)) H.emote(pick("gasp", "gag", "choke")) diff --git a/code/game/machinery/medical_kiosk.dm b/code/game/machinery/medical_kiosk.dm index 52933a5aba74..2f60c799ae23 100644 --- a/code/game/machinery/medical_kiosk.dm +++ b/code/game/machinery/medical_kiosk.dm @@ -172,7 +172,7 @@ sickness_data = "\nName: [D.name].\nType: [D.spread_text].\nStage: [D.stage]/[D.max_stages].\nPossible Cure: [D.cure_text]" if(altPatient.has_dna()) //Blood levels Information - if(altPatient.bleed_rate) + if(LAZYLEN(altPatient.get_bleeding_parts())) bleed_status = "Patient is currently bleeding!" if(blood_percent <= 80) blood_warning = " Patient has low blood levels. Seek a large meal, or iron supplements." diff --git a/code/game/machinery/suit_storage_unit.dm b/code/game/machinery/suit_storage_unit.dm index 7db02250ce94..107c5656c034 100644 --- a/code/game/machinery/suit_storage_unit.dm +++ b/code/game/machinery/suit_storage_unit.dm @@ -462,6 +462,12 @@ else visible_message(span_warning("[src]'s door slides open, barraging you with the nauseating smell of charred flesh.")) mob_occupant.radiation = 0 + if(iscarbon(mob_occupant)) + var/mob/living/carbon/bacon = mob_occupant + for(var/obj/item/bodypart/grilling as anything in bacon.get_bleeding_parts(TRUE)) + if(!grilling.can_bandage()) + continue + grilling.apply_bandage(0.005, 600, "cauterization") playsound(src, 'sound/machines/airlocks/standard/close.ogg', 25, TRUE) var/list/things_to_clear = list() //Done this way since using GetAllContents on the SSU itself would include circuitry and such. if(suit) diff --git a/code/game/objects/items/devices/scanners.dm b/code/game/objects/items/devices/scanners.dm index 3f40f82fe0ae..cdded7e418ef 100644 --- a/code/game/objects/items/devices/scanners.dm +++ b/code/game/objects/items/devices/scanners.dm @@ -357,7 +357,7 @@ GENE SCANNER if(blood_id) if(ishuman(C)) var/mob/living/carbon/human/H = C - if(H.bleed_rate) + if(LAZYLEN(H.get_bleeding_parts())) render_list += "Subject is bleeding!\n" var/blood_percent = round((C.blood_volume / BLOOD_VOLUME_NORMAL)*100) var/blood_type = C.dna.blood_type.name diff --git a/code/game/objects/items/stacks/medical.dm b/code/game/objects/items/stacks/medical.dm index ca3b1e184168..264ab12646ea 100644 --- a/code/game/objects/items/stacks/medical.dm +++ b/code/game/objects/items/stacks/medical.dm @@ -137,12 +137,13 @@ /obj/item/stack/medical/gauze name = "medical gauze" - desc = "A roll of elastic cloth that is extremely effective at stopping bleeding, but does not heal wounds." + desc = "A roll of elastic cloth that is extremely effective at stopping bleeding and slowly heals wounds." gender = PLURAL singular_name = "medical gauze" icon_state = "gauze" apply_sounds = list('sound/effects/rip1.ogg', 'sound/effects/rip2.ogg') - var/stop_bleeding = 1800 + var/bleed_reduction = 0.02 + var/lifespan = 150 self_delay = 20 max_amount = 12 grind_results = list(/datum/reagent/cellulose = 2) @@ -152,13 +153,16 @@ amount = 12 /obj/item/stack/medical/gauze/heal(mob/living/target, mob/user) - if(ishuman(target)) - var/mob/living/carbon/human/H = target - if(!H.bleedsuppress && H.bleed_rate) //so you can't stack bleed suppression - H.suppress_bloodloss(stop_bleeding) - to_chat(user, "You stop the bleeding of [target]!") + if(iscarbon(target)) + var/mob/living/carbon/C = target + var/obj/item/bodypart/BP = C.get_bodypart(check_zone(user.zone_selected)) + if(!BP) + to_chat(user, span_warning("[C] doesn't have \a [parse_zone(user.zone_selected)]!")) + return + if(BP.can_bandage(user)) + BP.apply_bandage(bleed_reduction, lifespan, name) + user.visible_message(span_notice("[user] wraps [C]'s [parse_zone(BP.body_zone)] with [src]."), span_notice("You wrap [C]'s [parse_zone(check_zone(user.zone_selected))] with [src]."), span_hear("You hear ruffling cloth.")) return TRUE - to_chat(user, "You can not use \the [src] on [target]!") /obj/item/stack/medical/gauze/attackby(obj/item/I, mob/user, params) if(I.tool_behaviour == TOOL_WIRECUTTER || I.get_sharpness()) @@ -178,8 +182,8 @@ /obj/item/stack/medical/gauze/improvised name = "improvised gauze" singular_name = "improvised gauze" - desc = "A roll of cloth roughly cut from something that can stop bleeding, but does not heal wounds." - stop_bleeding = 900 + desc = "A roll of cloth roughly cut from something that can stop bleeding and slowly heal wounds." + bleed_reduction = 0.005 /obj/item/stack/medical/gauze/cyborg custom_materials = null diff --git a/code/game/objects/items/stacks/tape.dm b/code/game/objects/items/stacks/tape.dm index 6a984c021a26..63fc55116d5a 100644 --- a/code/game/objects/items/stacks/tape.dm +++ b/code/game/objects/items/stacks/tape.dm @@ -80,7 +80,8 @@ grind_results = list(/datum/reagent/cellulose = 5) usesound = 'sound/items/tape.ogg' - var/stop_bleed = 600 + var/lifespan = 300 + var/bleed_reduction = 0.002 var/nonorganic_heal = 5 var/self_delay = 30 //! Also used for the tapecuff delay var/other_delay = 10 @@ -173,21 +174,17 @@ if(!affecting) //Missing limb? to_chat(user, "[C] doesn't have \a [parse_zone(user.zone_selected)]!") return - if(!IS_ORGANIC_LIMB(affecting)) - if(ishuman(C)) - var/mob/living/carbon/human/H = C - if(!H.bleedsuppress && H.bleed_rate) - H.suppress_bloodloss(stop_bleed) - to_chat(user, "You tape up the bleeding of [C]!") - return TRUE - to_chat(user, "[C] has a problem \the [src] won't fix!") - else //Robotic patch-up + if(IS_ROBOTIC_LIMB(affecting)) //Robotic patch-up if(affecting.brute_dam) user.visible_message("[user] applies \the [src] on [C]'s [affecting.name].", "You apply \the [src] on [C]'s [affecting.name].") if(affecting.heal_damage(nonorganic_heal)) C.update_damage_overlays() return TRUE - to_chat(user, "[src] can't patch what [C] has...") + if(affecting.can_bandage(user)) + affecting.apply_bandage(bleed_reduction, lifespan, name) + to_chat(user, "You tape up [C]'s [parse_zone(affecting.body_zone)]!") + return TRUE + to_chat(user, "[src] can't patch what [C] has...") /obj/item/stack/tape/proc/apply_gag(mob/living/carbon/target, mob/user) if(target.is_muzzled() || target.is_mouth_covered()) @@ -272,7 +269,7 @@ desc = "This roll of silver sorcery can fix just about anything." icon_state = "tape_d" - stop_bleed = 800 + lifespan = 400 nonorganic_heal = 20 prefix = "super sticky" conferred_embed = EMBED_HARMLESS_SUPERIOR @@ -297,7 +294,6 @@ desc = "Specialty insulated strips of adhesive plastic. Made for securing cables." icon_state = "tape_e" - stop_bleed = 400 nonorganic_heal = 10 prefix = "insulated sticky" siemens_coefficient = 0 @@ -321,6 +317,6 @@ desc = "Now THIS is engineering." icon_state = "tape_y" - stop_bleed = 1000 + lifespan = 500 nonorganic_heal = 30 prefix = "industry-standard sticky" diff --git a/code/game/objects/structures/petrified_statue.dm b/code/game/objects/structures/petrified_statue.dm index c8b804469255..1be0a2517bd6 100644 --- a/code/game/objects/structures/petrified_statue.dm +++ b/code/game/objects/structures/petrified_statue.dm @@ -58,6 +58,9 @@ if(petrified_mob) petrified_mob.status_flags &= ~GODMODE + if(ishuman(petrified_mob)) + var/mob/living/carbon/human/H = petrified_mob + H.bleedsuppress = FALSE petrified_mob.forceMove(loc) REMOVE_TRAIT(petrified_mob, TRAIT_MUTE, STATUE_MUTE) petrified_mob.take_overall_damage((petrified_mob.health - obj_integrity + 100)) //any new damage the statue incurred is transfered to the mob @@ -80,7 +83,7 @@ return 0 var/obj/structure/statue/petrified/S = new(loc, src, statue_timer) S.name = "statue of [name]" - bleedsuppress = 1 + bleedsuppress = TRUE S.copy_overlays(src) var/newcolor = list(rgb(77,77,77), rgb(150,150,150), rgb(28,28,28), rgb(0,0,0)) S.add_atom_colour(newcolor, FIXED_COLOUR_PRIORITY) diff --git a/code/modules/food_and_drinks/kitchen_machinery/microwave.dm b/code/modules/food_and_drinks/kitchen_machinery/microwave.dm index 678016182428..2762892110f8 100644 --- a/code/modules/food_and_drinks/kitchen_machinery/microwave.dm +++ b/code/modules/food_and_drinks/kitchen_machinery/microwave.dm @@ -385,6 +385,12 @@ playsound(src, 'sound/items/cig_light.ogg', 50, 1) moveToNullspace() + +/obj/item/ration_heater/get_temperature() + if(!uses) + return 0 + . = ..() + /obj/item/ration_heater/proc/clear_cooking(datum/source) SIGNAL_HANDLER UnregisterSignal(tocook, COMSIG_PARENT_QDELETING) diff --git a/code/modules/mob/living/blood.dm b/code/modules/mob/living/blood.dm index aec75960989d..1910347e4fdd 100644 --- a/code/modules/mob/living/blood.dm +++ b/code/modules/mob/living/blood.dm @@ -4,19 +4,6 @@ BLOOD SYSTEM ****************************************************/ -/mob/living/carbon/human/proc/suppress_bloodloss(amount) - if(bleedsuppress) - return - else - bleedsuppress = TRUE - addtimer(CALLBACK(src, PROC_REF(resume_bleeding)), amount) - -/mob/living/carbon/human/proc/resume_bleeding() - bleedsuppress = 0 - if(stat != DEAD && bleed_rate) - to_chat(src, "The blood soaks through your bandage.") - - /mob/living/carbon/monkey/handle_blood() if(bodytemperature >= TCRYO && !(HAS_TRAIT(src, TRAIT_HUSK))) //cryosleep or husked people do not pump the blood. //Blood regeneration if there is some space @@ -29,7 +16,6 @@ /mob/living/carbon/human/handle_blood() if(NOBLOOD in dna.species.species_traits) - bleed_rate = 0 return if(bodytemperature >= TCRYO && !(HAS_TRAIT(src, TRAIT_HUSK))) //cryosleep or husked people do not pump the blood. @@ -83,24 +69,20 @@ if(!HAS_TRAIT(src, TRAIT_NODEATH)) death() - var/temp_bleed = 0 //Bleeding out + var/limb_bleed = 0 for(var/obj/item/bodypart/BP as anything in bodyparts) - var/brutedamage = BP.brute_dam - + if(BP.GetComponent(/datum/component/bandage)) + continue //We want an accurate reading of .len listclearnulls(BP.embedded_objects) for(var/obj/item/embeddies in BP.embedded_objects) if(!embeddies.isEmbedHarmless()) - temp_bleed += 0.5 - - if(brutedamage >= 20) - temp_bleed += (brutedamage * 0.013) - - bleed_rate = max(bleed_rate - 0.5, temp_bleed)//if no wounds, other bleed effects (heparin) naturally decreases + BP.adjust_bleeding(0.1, BLOOD_LOSS_DAMAGE_MAXIMUM) + limb_bleed += BP.bleeding - if(bleed_rate && !bleedsuppress && !(HAS_TRAIT(src, TRAIT_FAKEDEATH))) - bleed(bleed_rate) + if(limb_bleed && !bleedsuppress && !HAS_TRAIT(src, TRAIT_FAKEDEATH)) + bleed(limb_bleed) //Makes a blood drop, leaking amt units of blood from the mob /mob/living/carbon/proc/bleed(amt) @@ -125,7 +107,8 @@ /mob/living/carbon/human/restore_blood() blood_volume = BLOOD_VOLUME_NORMAL - bleed_rate = 0 + for(var/obj/item/bodypart/BP as anything in get_bleeding_parts()) + BP.bleeding = 0 /**************************************************** BLOOD TRANSFERS diff --git a/code/modules/mob/living/carbon/carbon_defense.dm b/code/modules/mob/living/carbon/carbon_defense.dm index 8377fc0833d6..916095ed266e 100644 --- a/code/modules/mob/living/carbon/carbon_defense.dm +++ b/code/modules/mob/living/carbon/carbon_defense.dm @@ -1,3 +1,25 @@ +/mob/living/carbon/attackby(obj/item/W, mob/user, params) + var/obj/item/bodypart/BP = get_bodypart(check_zone(user.zone_selected)) + var/has_painkillers = user.reagents.has_reagent(/datum/reagent/medicine/morphine, needs_metabolizing = TRUE) + if(W.tool_behaviour == TOOL_WELDER && IS_ROBOTIC_LIMB(BP) && BP.brute_dam > 5) //prioritize healing if we're synthetic + return ..() + if(user.a_intent != INTENT_HELP || !W.get_temperature() || !BP.can_bandage()) //this will also catch low damage synthetic welding + return ..() + . = TRUE + var/heal_time = 2 SECONDS + playsound(user, 'sound/surgery/cautery1.ogg', 20) + balloon_alert(user, "cauterizing...") + if(src == user && !has_painkillers) + heal_time *= 2 //oof ouch owie + user.visible_message(span_nicegreen("[user] holds [W] up to [user == src ? "their" : "[src]'s"] [parse_zone(BP.body_zone)], trying to slow [p_their()] bleeding..."), span_nicegreen("You hold [W] up to [user == src ? "your" : "[src]'s"] [parse_zone(BP.body_zone)], trying to slow [user == src ? "your" : p_their()] bleeding...")) + if(do_after(user, heal_time, target = src)) + playsound(user, 'sound/surgery/cautery2.ogg', 20) + BP.apply_bandage(0.005, W.get_temperature()/BLOOD_CAUTERIZATION_RATIO, "cauterization") //not particularly fast, this is the "I really would prefer not to be bleeding right now" option + BP.receive_damage(burn = W.get_temperature()/BLOOD_CAUTERIZATION_DAMAGE_RATIO) //my body is a MACHINE that turns BLEEDING into BURN DAMAGE + user.visible_message(span_nicegreen("[user] cauterizes the bleeding on [user == src ? "their" : "[src]'s"] [parse_zone(BP.body_zone)]!"), span_nicegreen("You cauterize the bleeding on [user == src ? "your" : "[src]'s"] [parse_zone(BP.body_zone)]!")) + else + to_chat(user, span_warning("You were interrupted!")) + /mob/living/carbon/get_eye_protection() . = ..() var/obj/item/organ/eyes/E = getorganslot(ORGAN_SLOT_EYES) diff --git a/code/modules/mob/living/carbon/damage_procs.dm b/code/modules/mob/living/carbon/damage_procs.dm index 2045bfe4aa18..8c023299baed 100644 --- a/code/modules/mob/living/carbon/damage_procs.dm +++ b/code/modules/mob/living/carbon/damage_procs.dm @@ -1,6 +1,6 @@ -/mob/living/carbon/apply_damage(damage, damagetype = BRUTE, def_zone = null, blocked = FALSE, forced = FALSE, spread_damage = FALSE, break_modifier = 1) +/mob/living/carbon/apply_damage(damage, damagetype = BRUTE, def_zone = null, blocked = FALSE, forced = FALSE, spread_damage = FALSE, break_modifier = 1, sharpness = FALSE) SEND_SIGNAL(src, COMSIG_MOB_APPLY_DAMGE, damage, damagetype, def_zone) var/hit_percent = (100-blocked)/100 if(!damage || (!forced && hit_percent <= 0)) @@ -21,7 +21,7 @@ switch(damagetype) if(BRUTE) if(BP) - if(BP.receive_damage(damage_amount, 0, break_modifier)) + if(BP.receive_damage(damage_amount, 0, break_modifier, sharpness = sharpness)) update_damage_overlays() else //no bodypart, we deal damage with a more general method. adjustBruteLoss(damage_amount, forced = forced) @@ -29,7 +29,7 @@ shake_animation(damage_amount) if(BURN) if(BP) - if(BP.receive_damage(0, damage_amount, break_modifier)) + if(BP.receive_damage(0, damage_amount, break_modifier, sharpness = sharpness)) update_damage_overlays() else adjustFireLoss(damage_amount, forced = forced) @@ -267,3 +267,68 @@ if(update) update_damage_overlays() update_stamina() + +/// Gets a list of bleeding bodyparts, argument ignore_staunched = are we actively bleeding (no treatment) +/mob/living/carbon/proc/get_bleeding_parts(ignore_staunched = FALSE) + var/list/obj/item/bodypart/parts = list() + for(var/obj/item/bodypart/BP as anything in bodyparts) + if(BP.bleeding && (!ignore_staunched || !BP.GetComponent(/datum/component/bandage))) + parts += BP + return parts + +/// Gets a list of bandaged parts +/mob/living/carbon/proc/get_bandaged_parts() + var/list/obj/item/bodypart/parts = list() + for(var/obj/item/bodypart/BP as anything in bodyparts) + if(BP.GetComponent(/datum/component/bandage)) + parts += BP + return parts + +/// Apply bleeding to one random bodypart. +/mob/living/carbon/proc/cause_bleeding(amt) + if(amt <= 0) + return + var/list/obj/item/bodypart/parts = bodyparts.Copy() + if(!length(parts)) + return + var/obj/item/bodypart/part_in_question = pick(parts) + part_in_question.adjust_bleeding(amt) + +/// Heal bleeding from one random bodypart +/mob/living/carbon/proc/heal_bleeding(amt) + if(amt <= 0) + return + var/list/obj/item/bodypart/parts = get_bleeding_parts() + if(!length(parts)) + return + var/obj/item/bodypart/part_in_question = pick(parts) + part_in_question.adjust_bleeding(-amt) + var/bleed_calc = part_in_question.bleeding + return min(bleed_calc - part_in_question.bleeding, 0) + +/// Apply bleeding to all bodyparts +/mob/living/carbon/proc/cause_overall_bleeding(amt) + if(amt <= 0) + return + var/list/obj/item/bodypart/parts = bodyparts.Copy() + while(length(parts)) + var/obj/item/bodypart/part_in_question = pick(parts) + if(part_in_question.is_pseudopart) + parts -= part_in_question + continue + var/amount_to_take = min(part_in_question.bleeding, amt / length(parts)) + part_in_question.adjust_bleeding(amount_to_take) + amt -= amount_to_take + parts -= part_in_question + +/// Heal bleeding from all bodyparts +/mob/living/carbon/proc/heal_overall_bleeding(amt) + if(amt <= 0) + return + var/list/obj/item/bodypart/parts = get_bleeding_parts() + while(length(parts)) + var/obj/item/bodypart/part_in_question = pick(parts) + var/amount_to_take = min(part_in_question.bleeding, amt / length(parts)) + part_in_question.adjust_bleeding(-amount_to_take) + amt -= amount_to_take + parts -= part_in_question diff --git a/code/modules/mob/living/carbon/human/damage_procs.dm b/code/modules/mob/living/carbon/human/damage_procs.dm index 4883446b7cb1..d7f6834030b3 100644 --- a/code/modules/mob/living/carbon/human/damage_procs.dm +++ b/code/modules/mob/living/carbon/human/damage_procs.dm @@ -1,7 +1,7 @@ /// depending on the species, it will run the corresponding apply_damage code there -/mob/living/carbon/human/apply_damage(damage = 0,damagetype = BRUTE, def_zone = null, blocked = FALSE, forced = FALSE, spread_damage = FALSE, break_modifier = 1) //WS Edit - Breakable Bones - return dna.species.apply_damage(damage, damagetype, def_zone, blocked, src, forced, spread_damage) +/mob/living/carbon/human/apply_damage(damage = 0,damagetype = BRUTE, def_zone = null, blocked = FALSE, forced = FALSE, spread_damage = FALSE, break_modifier = 1, sharpness = FALSE) //WS Edit - Breakable Bones + return dna.species.apply_damage(damage, damagetype, def_zone, blocked, src, forced, spread_damage, sharpness = sharpness) /mob/living/carbon/human/revive(full_heal = 0, admin_revive = 0) if(..()) diff --git a/code/modules/mob/living/carbon/human/examine.dm b/code/modules/mob/living/carbon/human/examine.dm index 64882c75ec4e..4430fc1da300 100644 --- a/code/modules/mob/living/carbon/human/examine.dm +++ b/code/modules/mob/living/carbon/human/examine.dm @@ -257,9 +257,12 @@ if(blood_volume < BLOOD_VOLUME_SAFE || skin_tone == "albino") msg += "[t_He] [t_has] pale skin.\n" - if(bleedsuppress) - msg += "[t_He] [t_is] bandaged with something.\n" - else if(bleed_rate) + + if(LAZYLEN(get_bandaged_parts())) + msg += "[t_He] [t_has] some dressed bleeding.\n" + + var/list/obj/item/bodypart/bleed_check = get_bleeding_parts(TRUE) + if(LAZYLEN(bleed_check)) if(reagents.has_reagent(/datum/reagent/toxin/heparin, needs_metabolizing = TRUE)) msg += "[t_He] [t_is] bleeding uncontrollably!\n" else @@ -414,6 +417,22 @@ /mob/living/carbon/human/examine_more(mob/user) . = ..() + for(var/obj/item/bodypart/BP as anything in get_bandaged_parts()) + var/datum/component/bandage/B = BP.GetComponent(/datum/component/bandage) + . += span_notice("[p_their(TRUE)] [parse_zone(BP.body_zone)] is dressed with [B.bandage_name]") + for(var/obj/item/bodypart/BP as anything in get_bleeding_parts(TRUE)) + var/bleed_text + switch(BP.bleeding) + if(0 to 0.5) + bleed_text = "lightly." + if(0.5 to 1) + bleed_text = "moderately." + if(1 to 1.5) + bleed_text = "heavily!" + else + bleed_text = "significantly!!" + . += span_warning("[p_their(TRUE)] [parse_zone(BP.body_zone)] is bleeding [bleed_text]") + if ((wear_mask && (wear_mask.flags_inv & HIDEFACE)) || (head && (head.flags_inv & HIDEFACE))) return if(get_age()) diff --git a/code/modules/mob/living/carbon/human/human_defense.dm b/code/modules/mob/living/carbon/human/human_defense.dm index 3e3fd2209856..1cb061ff9fd9 100644 --- a/code/modules/mob/living/carbon/human/human_defense.dm +++ b/code/modules/mob/living/carbon/human/human_defense.dm @@ -779,10 +779,10 @@ combined_msg += "\t There is \a [I] embedded in your [LB.name]!" for(var/t in missing) - combined_msg += "Your [parse_zone(t)] is missing!" + combined_msg += span_boldannounce("Your [parse_zone(t)] is missing!") - if(bleed_rate) - combined_msg += "You are bleeding!" + for(var/obj/item/bodypart/BP in get_bleeding_parts(TRUE)) + combined_msg += span_danger("Your [parse_zone(BP.body_zone)] is bleeding!") if(getStaminaLoss()) if(getStaminaLoss() > 30) combined_msg += "You're completely exhausted." diff --git a/code/modules/mob/living/carbon/human/human_defines.dm b/code/modules/mob/living/carbon/human/human_defines.dm index 8cc9e5002749..6556335c2bdb 100644 --- a/code/modules/mob/living/carbon/human/human_defines.dm +++ b/code/modules/mob/living/carbon/human/human_defines.dm @@ -63,9 +63,7 @@ /// Adjective used in get_generic_name(), if any var/generic_adjective - - var/bleed_rate = 0 //how much are we bleeding - var/bleedsuppress = 0 //for stopping bloodloss, eventually this will be limb-based like bleeding + var/bleedsuppress = 0 //for stopping bloodloss body-wide var/name_override //For temporary visible name changes diff --git a/code/modules/mob/living/carbon/human/species.dm b/code/modules/mob/living/carbon/human/species.dm index e848bc01d251..e061cd5c9793 100644 --- a/code/modules/mob/living/carbon/human/species.dm +++ b/code/modules/mob/living/carbon/human/species.dm @@ -1618,7 +1618,7 @@ GLOBAL_LIST_EMPTY(roundstart_races) var/armor_block = H.run_armor_check(affecting, "melee", I.armour_penetration, FALSE, "Your armor has protected your [hit_area]!", "Your armor has softened a hit to your [hit_area]!") armor_block = min(90,armor_block) //cap damage reduction at 90% - apply_damage(I.force, I.damtype, def_zone, armor_block, H) + apply_damage(I.force, I.damtype, def_zone, armor_block, H, sharpness = I.get_sharpness()) H.send_item_attack_message(I, user, hit_area) @@ -1687,7 +1687,7 @@ GLOBAL_LIST_EMPTY(roundstart_races) return TRUE -/datum/species/proc/apply_damage(damage, damagetype = BRUTE, def_zone = null, blocked, mob/living/carbon/human/H, forced = FALSE, spread_damage = FALSE, break_modifier = 1) +/datum/species/proc/apply_damage(damage, damagetype = BRUTE, def_zone = null, blocked, mob/living/carbon/human/H, forced = FALSE, spread_damage = FALSE, break_modifier = 1, sharpness = FALSE) SEND_SIGNAL(H, COMSIG_MOB_APPLY_DAMGE, damage, damagetype, def_zone) var/hit_percent = (100-(blocked+armor))/100 hit_percent = (hit_percent * (100-H.physiology.damage_resistance))/100 @@ -1710,7 +1710,7 @@ GLOBAL_LIST_EMPTY(roundstart_races) H.damageoverlaytemp = 20 var/damage_amount = forced ? damage : damage * hit_percent * brutemod * H.physiology.brute_mod if(BP) - if(BP.receive_damage(damage_amount, 0, break_modifier = break_modifier)) + if(BP.receive_damage(damage_amount, 0, break_modifier = break_modifier, sharpness = sharpness)) H.update_damage_overlays() else//no bodypart, we deal damage with a more general method. H.adjustBruteLoss(damage_amount) @@ -1720,7 +1720,7 @@ GLOBAL_LIST_EMPTY(roundstart_races) H.damageoverlaytemp = 20 var/damage_amount = forced ? damage : damage * hit_percent * burnmod * H.physiology.burn_mod if(BP) - if(BP.receive_damage(0, damage_amount, break_modifier = break_modifier)) + if(BP.receive_damage(0, damage_amount, break_modifier = break_modifier, sharpness = sharpness)) H.update_damage_overlays() else H.adjustFireLoss(damage_amount) diff --git a/code/modules/mob/living/carbon/human/species_types/zombies.dm b/code/modules/mob/living/carbon/human/species_types/zombies.dm index 702adfb224a2..c90cbd0dbc8f 100644 --- a/code/modules/mob/living/carbon/human/species_types/zombies.dm +++ b/code/modules/mob/living/carbon/human/species_types/zombies.dm @@ -46,7 +46,7 @@ /datum/species/zombie/infectious/spec_stun(mob/living/carbon/human/H,amount) . = min(20, amount) -/datum/species/zombie/infectious/apply_damage(damage, damagetype = BRUTE, def_zone = null, blocked, mob/living/carbon/human/H, forced = FALSE) +/datum/species/zombie/infectious/apply_damage(damage, damagetype = BRUTE, def_zone = null, blocked, mob/living/carbon/human/H, forced = FALSE, sharpness = FALSE) . = ..() if(.) regen_cooldown = world.time + REGENERATION_DELAY diff --git a/code/modules/mob/living/damage_procs.dm b/code/modules/mob/living/damage_procs.dm index 76daa5ba21d4..430d02f7f1ea 100644 --- a/code/modules/mob/living/damage_procs.dm +++ b/code/modules/mob/living/damage_procs.dm @@ -11,10 +11,12 @@ * * blocked - armor value applied * * forced - bypass hit percentage * * spread_damage - used in overrides + * * break_modifier - increases bone breaking chance + * * sharpness - used for bleeding * * Returns TRUE if damage applied */ -/mob/living/proc/apply_damage(damage = 0,damagetype = BRUTE, def_zone = null, blocked = FALSE, forced = FALSE, spread_damage = FALSE, break_modifier = 1)//WS Edit - Breakable Bones +/mob/living/proc/apply_damage(damage = 0,damagetype = BRUTE, def_zone = null, blocked = FALSE, forced = FALSE, spread_damage = FALSE, break_modifier = 1, sharpness = FALSE)//WS Edit - Breakable Bones SEND_SIGNAL(src, COMSIG_MOB_APPLY_DAMGE, damage, damagetype, def_zone) var/hit_percent = (100-blocked)/100 if(!damage || (!forced && hit_percent <= 0) || !(flags_1 & INITIALIZED_1)) diff --git a/code/modules/mob/living/life.dm b/code/modules/mob/living/life.dm index 47fc5bd82ecb..a25025294497 100644 --- a/code/modules/mob/living/life.dm +++ b/code/modules/mob/living/life.dm @@ -38,6 +38,8 @@ if (QDELETED(src)) // diseases can qdel the mob via transformations return + SEND_SIGNAL(src, COMSIG_MOB_LIFE) + if(stat != DEAD) //Random events (vomiting etc) handle_random_events() diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm index cb0ec02ced34..5c499fe21029 100644 --- a/code/modules/mob/living/living.dm +++ b/code/modules/mob/living/living.dm @@ -820,7 +820,7 @@ TH.transfer_mob_blood_dna(src) /mob/living/carbon/human/makeTrail(turf/T) - if((NOBLOOD in dna.species.species_traits) || !bleed_rate || bleedsuppress) + if((NOBLOOD in dna.species.species_traits) || bleedsuppress || !LAZYLEN(get_bleeding_parts(TRUE))) return ..() diff --git a/code/modules/mob/living/living_defense.dm b/code/modules/mob/living/living_defense.dm index c1c4cd668792..eb622de65f28 100644 --- a/code/modules/mob/living/living_defense.dm +++ b/code/modules/mob/living/living_defense.dm @@ -54,7 +54,7 @@ var/armor = run_armor_check(def_zone, P.flag, P.armour_penetration, silent = TRUE) var/on_hit_state = P.on_hit(src, armor, piercing_hit) if(!P.nodamage && on_hit_state != BULLET_ACT_BLOCK && !QDELETED(src)) //QDELETED literally just for the instagib rifle. Yeah. - apply_damage(P.damage, P.damage_type, def_zone, armor) + apply_damage(P.damage, P.damage_type, def_zone, armor, sharpness = TRUE) recoil_camera(src, clamp((P.damage-armor)/4,0.5,10), clamp((P.damage-armor)/4,0.5,10), P.damage/8, P.Angle) apply_effects(P.stun, P.knockdown, P.unconscious, P.irradiate, P.slur, P.stutter, P.eyeblur, P.drowsy, armor, P.stamina, P.jitter, P.paralyze, P.immobilize) if(P.dismemberment) diff --git a/code/modules/mob/living/silicon/damage_procs.dm b/code/modules/mob/living/silicon/damage_procs.dm index a6d86d1507ba..80c643e0ceef 100644 --- a/code/modules/mob/living/silicon/damage_procs.dm +++ b/code/modules/mob/living/silicon/damage_procs.dm @@ -1,5 +1,5 @@ -/mob/living/silicon/apply_damage(damage = 0,damagetype = BRUTE, def_zone = null, blocked = FALSE, forced = FALSE, break_modifier = 1) +/mob/living/silicon/apply_damage(damage = 0,damagetype = BRUTE, def_zone = null, blocked = FALSE, forced = FALSE, break_modifier = 1, sharpness = FALSE) var/hit_percent = (100-blocked)/100 if((!damage || (!forced && hit_percent <= 0))) return 0 diff --git a/code/modules/mob/living/simple_animal/hostile/human/cat_butcher.dm b/code/modules/mob/living/simple_animal/hostile/human/cat_butcher.dm index 0e265fc3b531..0f14f615e5b6 100644 --- a/code/modules/mob/living/simple_animal/hostile/human/cat_butcher.dm +++ b/code/modules/mob/living/simple_animal/hostile/human/cat_butcher.dm @@ -68,11 +68,11 @@ L.adjustOxyLoss(-50)// do CPR first if(L.blood_volume <= 500) //bandage them up and give em some blood if they're bleeding L.blood_volume += 30 - L.suppress_bloodloss(1800) + L.heal_bleeding(10) if(L.getBruteLoss() >= 50)// first, did we beat them into crit? if so, heal that var/healing = min(L.getBruteLoss(), 120) L.adjustBruteLoss(-healing) - L.suppress_bloodloss(1800)//bandage their ass + L.heal_bleeding(10) return else if(L.getFireLoss() >= 50) // are they still down from other damage? fix it, but not as fast as the burns var/healing = min(L.getFireLoss(), 50) diff --git a/code/modules/reagents/chemistry/reagents/medicine_reagents.dm b/code/modules/reagents/chemistry/reagents/medicine_reagents.dm index 7fb71324d7af..4c4ad36b2413 100644 --- a/code/modules/reagents/chemistry/reagents/medicine_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/medicine_reagents.dm @@ -1091,7 +1091,7 @@ M.adjustBruteLoss(-2*REM, 0) if(ishuman(M)) var/mob/living/carbon/human/H = M - H.bleed_rate = max(H.bleed_rate - 0.25, 0) + H.heal_bleeding(0.25) ..() . = 1 @@ -1638,7 +1638,7 @@ if(prob(50)) if(ishuman(M)) var/mob/living/carbon/human/H = M - H.bleed_rate = max(H.bleed_rate - 2, 0) + H.heal_bleeding(2) ..() . = 1 diff --git a/code/modules/reagents/chemistry/reagents/toxin_reagents.dm b/code/modules/reagents/chemistry/reagents/toxin_reagents.dm index e03c84dd7840..498017191179 100644 --- a/code/modules/reagents/chemistry/reagents/toxin_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/toxin_reagents.dm @@ -769,7 +769,8 @@ /datum/reagent/toxin/heparin/on_mob_life(mob/living/carbon/M) if(ishuman(M)) var/mob/living/carbon/human/H = M - H.bleed_rate = min(H.bleed_rate + 2, 8) + for(var/obj/item/bodypart/BP in H.get_bleeding_parts()) + BP.adjust_bleeding(BP.bleeding * 0.1) H.adjustBruteLoss(1, 0) //Brute damage increases with the amount they're bleeding . = 1 return ..() || . diff --git a/code/modules/reagents/chemistry/reagents/trickwine_reagents.dm b/code/modules/reagents/chemistry/reagents/trickwine_reagents.dm index 88f1871e6a28..be5e2ce35f9a 100644 --- a/code/modules/reagents/chemistry/reagents/trickwine_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/trickwine_reagents.dm @@ -115,7 +115,7 @@ M.adjust_bodytemperature(5 * TEMPERATURE_DAMAGE_COEFFICIENT, M.get_body_temp_normal()) if(ishuman(M)) var/mob/living/carbon/human/H = M - H.bleed_rate = max(H.bleed_rate - 0.25, 0) + H.heal_bleeding(0.25) return ..() /datum/reagent/consumable/ethanol/trickwine/hearth_wine/expose_mob(mob/living/M, method=TOUCH, reac_volume) diff --git a/code/modules/surgery/bodyparts/bodyparts.dm b/code/modules/surgery/bodyparts/bodyparts.dm index 7cf31dc83ca6..92cb95a9c605 100644 --- a/code/modules/surgery/bodyparts/bodyparts.dm +++ b/code/modules/surgery/bodyparts/bodyparts.dm @@ -50,6 +50,16 @@ /// Is it fine, broken, splinted, or just straight up fucking gone var/bone_status = BONE_FLAG_NO_BONES var/bone_break_threshold = 30 + /// Threshold at which the limb will start bleeding if damaged by sharp items or projectiles + var/bleed_threshold = 10 + /// Threshold at which the limb will start bleeding if damaged by blunt items + var/bleed_threshold_blunt = 25 + /// Minimum damage of an incoming attack for it to cause bleeding + var/bleed_damage_min = 5 + /// Minimum damage of an incoming blunt attack for it to cause bleeding + var/bleed_damage_min_blunt = 10 + /// Current limb bleeding, increased when the limb takes brute damage over certain thresholds, decreased through bandages and cauterization + var/bleeding = 0 /// So we know if we need to scream if this limb hits max damage var/last_maxed @@ -202,11 +212,13 @@ if(stamina_dam > DAMAGE_PRECISION && owner.stam_regen_start_time <= world.time) //DO NOT update health here, it'll be done in the carbon's life. heal_damage(0, 0, INFINITY, null, FALSE) . |= BODYPART_LIFE_UPDATE_HEALTH + if(brute_dam < DAMAGE_PRECISION && bleeding) + adjust_bleeding(-0.2) //slowly stop bleeding if there's no damage left //Applies brute and burn damage to the organ. Returns 1 if the damage-icon states changed at all. //Damage will not exceed max_damage using this proc //Cannot apply negative damage -/obj/item/bodypart/proc/receive_damage(brute = 0, burn = 0, stamina = 0, blocked = 0, updating_health = TRUE, required_status = null, break_modifier = 1) +/obj/item/bodypart/proc/receive_damage(brute = 0, burn = 0, stamina = 0, blocked = 0, updating_health = TRUE, required_status = null, break_modifier = 1, sharpness = FALSE) var/hit_percent = (100-blocked)/100 if((!brute && !burn && !stamina) || hit_percent <= 0) return FALSE @@ -235,6 +247,10 @@ if((brute_dam > bone_break_threshold) && prob(brute_dam + break_modifier)) break_bone() + // Bleeding is applied here + if(brute_dam+brute >= (sharpness ? bleed_threshold : bleed_threshold_blunt) && brute >= (sharpness ? bleed_damage_min : bleed_damage_min_blunt)) + adjust_bleeding(brute * BLOOD_LOSS_DAMAGE_BASE, BLOOD_LOSS_DAMAGE_MAXIMUM) + var/can_inflict = max_damage - get_damage() if(can_inflict <= 0) return FALSE @@ -274,6 +290,7 @@ if(brute) set_brute_dam(round(max(brute_dam - brute, 0), DAMAGE_PRECISION)) + adjust_bleeding(-BLOOD_LOSS_DAMAGE_MAXIMUM * brute / max_damage) if(burn) set_burn_dam(round(max(burn_dam - burn, 0), DAMAGE_PRECISION)) if(stamina) @@ -315,6 +332,30 @@ . = stamina_dam stamina_dam = new_value +/// Adjusts bodypart bleeding, value = amount of change, maximum = maximum current bloodloss amount this can modify +/obj/item/bodypart/proc/adjust_bleeding(value, maximum = BLOOD_LOSS_MAXIMUM) + if(bleeding > maximum) + return + if(owner.dna && (NOBLOOD in owner.dna.species.species_traits)) + return + bleeding = round(clamp(bleeding+value, 0, maximum), 0.001) + +/// Checks if the bodypart is viable for bandaging, if it isn't, tells the person trying (if present) what's stopping it +/obj/item/bodypart/proc/can_bandage(user) + . = TRUE + if(is_pseudopart) + return FALSE + if(!bleeding) + if(user) + to_chat(user, span_warning("[owner]'s [parse_zone(body_zone)] isn't bleeding!")) + return FALSE + if(GetComponent(/datum/component/bandage)) + if(user) + to_chat(user, span_warning("[owner]'s [parse_zone(body_zone)] has already been dressed!")) + return FALSE + +/obj/item/bodypart/proc/apply_bandage(bleed_reduction, lifespan, name) + AddComponent(/datum/component/bandage, bleed_reduction, lifespan, name) //Returns total damage. /obj/item/bodypart/proc/get_damage(include_stamina = FALSE) diff --git a/code/modules/surgery/bodyparts/dismemberment.dm b/code/modules/surgery/bodyparts/dismemberment.dm index 7c292ac21fc4..07d30e727c77 100644 --- a/code/modules/surgery/bodyparts/dismemberment.dm +++ b/code/modules/surgery/bodyparts/dismemberment.dm @@ -90,6 +90,7 @@ return var/atom/Tsec = owner.drop_location() var/mob/living/carbon/C = owner + SEND_SIGNAL(src, COMSIG_LIVING_DROP_LIMB) update_limb(TRUE) C.remove_bodypart(src) diff --git a/code/modules/surgery/coronary_bypass.dm b/code/modules/surgery/coronary_bypass.dm index 4c416c31c633..a4628d19efff 100644 --- a/code/modules/surgery/coronary_bypass.dm +++ b/code/modules/surgery/coronary_bypass.dm @@ -41,7 +41,8 @@ display_results(user, target, "Blood pools around the incision in [H]'s heart.", "Blood pools around the incision in [H]'s heart.", "") - H.bleed_rate += 10 + var/obj/item/bodypart/BP = H.get_bodypart(check_zone(surgery.location)) + BP.adjust_bleeding(10) target.apply_damage(15, BRUTE, "[target_zone]") return ..() @@ -51,7 +52,8 @@ display_results(user, target, "You screw up, cutting too deeply into the heart!", "[user] screws up, causing blood to spurt out of [H]'s chest!", "[user] screws up, causing blood to spurt out of [H]'s chest!") - H.bleed_rate += 20 + var/obj/item/bodypart/BP = H.get_bodypart(check_zone(surgery.location)) + BP.adjust_bleeding(20) H.adjustOrganLoss(ORGAN_SLOT_HEART, 10) target.apply_damage(15, BRUTE, "[target_zone]") @@ -90,5 +92,6 @@ "[user] screws up, causing blood to spurt out of [H]'s chest profusely!", "[user] screws up, causing blood to spurt out of [H]'s chest profusely!") H.adjustOrganLoss(ORGAN_SLOT_HEART, 30) - H.bleed_rate += 30 + var/obj/item/bodypart/BP = H.get_bodypart(check_zone(surgery.location)) + BP.adjust_bleeding(30) return FALSE diff --git a/code/modules/surgery/organic_steps.dm b/code/modules/surgery/organic_steps.dm index 5167bb3a4517..42018e6c1d87 100644 --- a/code/modules/surgery/organic_steps.dm +++ b/code/modules/surgery/organic_steps.dm @@ -30,7 +30,9 @@ display_results(user, target, "Blood pools around the incision in [H]'s [parse_zone(target_zone)].", "Blood pools around the incision in [H]'s [parse_zone(target_zone)].", "") - H.bleed_rate += 3 + var/obj/item/bodypart/BP = H.get_bodypart(check_zone(surgery.location)) + if(BP) + BP.adjust_bleeding(3) return ..() /datum/surgery_step/incise/failure(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) @@ -74,7 +76,9 @@ target.heal_bodypart_damage(20,0) if (ishuman(target)) var/mob/living/carbon/human/H = target - H.bleed_rate = max((H.bleed_rate - 3), 0) + var/obj/item/bodypart/BP = H.get_bodypart(check_zone(surgery.location)) + if(BP) + BP.adjust_bleeding(-3) return ..() /datum/surgery_step/clamp_bleeders/failure(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) @@ -137,7 +141,9 @@ target.heal_bodypart_damage(15,0) if (ishuman(target)) var/mob/living/carbon/human/H = target - H.bleed_rate = max((H.bleed_rate - 3), 0) + var/obj/item/bodypart/BP = H.get_bodypart(check_zone(surgery.location)) + if(BP) + BP.adjust_bleeding(-3) return ..() //saw bone diff --git a/code/modules/surgery/organs/vocal_cords.dm b/code/modules/surgery/organs/vocal_cords.dm index 5eed8abc46be..c0313adb2539 100644 --- a/code/modules/surgery/organs/vocal_cords.dm +++ b/code/modules/surgery/organs/vocal_cords.dm @@ -286,7 +286,7 @@ else if((findtext(message, bleed_words))) cooldown = COOLDOWN_DAMAGE for(var/mob/living/carbon/human/H in listeners) - H.bleed_rate += (5 * power_multiplier) + H.cause_overall_bleeding(5*power_multiplier) //FIRE else if((findtext(message, burn_words))) diff --git a/code/modules/surgery/surgery_helpers.dm b/code/modules/surgery/surgery_helpers.dm index c28ce0855933..f87c6e1bb923 100644 --- a/code/modules/surgery/surgery_helpers.dm +++ b/code/modules/surgery/surgery_helpers.dm @@ -115,7 +115,9 @@ if(ishuman(M)) var/mob/living/carbon/human/H = M - H.bleed_rate = max((H.bleed_rate - 3), 0) + var/obj/item/bodypart/BP = H.get_bodypart(check_zone(S.location)) + if(BP) + BP.adjust_bleeding(-3) M.surgeries -= S user.visible_message("[user] closes [M]'s [parse_zone(selected_zone)] with [close_tool] and stops the surgery.", \ "You close [M]'s [parse_zone(selected_zone)] with [close_tool] and stop the surgery.") diff --git a/shiptest.dme b/shiptest.dme index 630c5d479767..565b4dec6c8f 100644 --- a/shiptest.dme +++ b/shiptest.dme @@ -460,6 +460,7 @@ #include "code\datums\components\anti_magic.dm" #include "code\datums\components\armor_plate.dm" #include "code\datums\components\art.dm" +#include "code\datums\components\bandage.dm" #include "code\datums\components\bane.dm" #include "code\datums\components\beetlejuice.dm" #include "code\datums\components\bloodysoles.dm"