From 5a086cf7bc6abe3c6af1b886e054b16eafab9674 Mon Sep 17 00:00:00 2001 From: Antoonij <42318445+Antoonij@users.noreply.github.com> Date: Fri, 15 Nov 2024 12:31:55 +0100 Subject: [PATCH] setBlood --- code/__DEFINES/dcs/signals.dm | 8 +++-- code/datums/status_effects/buffs.dm | 12 +++++-- .../gamemodes/clockwork/clockwork_items.dm | 2 +- .../gamemodes/miniantags/abduction/gland.dm | 6 ++-- .../antagonists/vampire/vampire_datum.dm | 4 +-- .../vampire/vampire_powers/bestia_powers.dm | 6 ++-- code/modules/mob/living/living.dm | 23 ++++++++++--- code/modules/paperwork/contract.dm | 2 +- .../reagents/chemistry/reagents/medicine.dm | 10 +++--- .../reagents/chemistry/reagents/toxins.dm | 2 +- code/modules/surgery/organs/blood.dm | 33 +++++++++++++++---- 11 files changed, 77 insertions(+), 31 deletions(-) diff --git a/code/__DEFINES/dcs/signals.dm b/code/__DEFINES/dcs/signals.dm index 9b25828c7e7..c7ccfbc3df6 100644 --- a/code/__DEFINES/dcs/signals.dm +++ b/code/__DEFINES/dcs/signals.dm @@ -619,10 +619,14 @@ #define COMPONENT_CANT_TRACK (1<<0) /// Source: /mob/living/adjustBloodLoss(amount) -#define COMSIG_LIVING_BLOOD_ADJUST "living_blood_adjust" +#define COMSIG_LIVING_BLOOD_ADJUST "living_blood_adjust" #define COMPONENT_PREVENT_BLOODLOSS (1<<0) /// Source: /mob/living/adjustBloodLoss(amount) -#define COMSIG_LIVING_BLOOD_ADJUSTED "living_blood_adjusted" +#define COMSIG_LIVING_BLOOD_ADJUSTED "living_blood_adjusted" +/// Source: /mob/living/setBloodLoss(amount) +#define COMSIG_LIVING_EARLY_SET_BLOOD "living_early_set_blood" +/// Source: /mob/living/setBloodLoss(amount) +#define COMSIG_LIVING_SET_BLOOD "living_set_blood" /// From /mob/add_language() (language_name) #define COMSIG_MOB_LANGUAGE_ADD "mob_language_add" diff --git a/code/datums/status_effects/buffs.dm b/code/datums/status_effects/buffs.dm index eeb076ff564..9366b9abc46 100644 --- a/code/datums/status_effects/buffs.dm +++ b/code/datums/status_effects/buffs.dm @@ -374,22 +374,30 @@ active_instances += instance_duration /datum/status_effect/fleshmend/tick(seconds_between_ticks) - if(length(active_instances) >= 1) + if(LAZYLEN(active_instances) >= 1) var/heal_amount = (length(active_instances) / tolerance) * (freezing ? 2 : 10) var/blood_restore = 30 * length(active_instances) var/update = NONE + update |= owner.heal_overall_damage(heal_amount, heal_amount, updating_health = FALSE) update |= owner.heal_damage_type(heal_amount, OXY, FALSE) + if(update) owner.updatehealth("fleshmend") + if(!HAS_TRAIT(owner, TRAIT_NO_BLOOD_RESTORE)) - owner.blood_volume = min(owner.blood_volume + blood_restore, BLOOD_VOLUME_NORMAL) + owner.setBlood(min(owner.blood_volume + blood_restore, BLOOD_VOLUME_NORMAL)) + var/list/expired_instances = list() + for(var/i in 1 to length(active_instances)) active_instances[i]-- + if(active_instances[i] <= 0) expired_instances += active_instances[i] + active_instances -= expired_instances + tolerance = max(tolerance - 0.05, 1) if(tolerance <= 1 && length(active_instances) == 0) qdel(src) diff --git a/code/game/gamemodes/clockwork/clockwork_items.dm b/code/game/gamemodes/clockwork/clockwork_items.dm index d4f8b5db9f3..2b1467a73c7 100644 --- a/code/game/gamemodes/clockwork/clockwork_items.dm +++ b/code/game/gamemodes/clockwork/clockwork_items.dm @@ -557,7 +557,7 @@ if(bodypart.internal_bleeding()) to_chat(user, span_warning("You tear through [human]'s skin releasing the blood from [human.p_their()] [bodypart.name]!")) playsound(get_turf(human), 'sound/effects/pierce.ogg', 30, TRUE) - human.blood_volume = max(human.blood_volume - 100, 0) + human.setBlood(max(human.blood_volume - 100, 0)) var/splatter_dir = get_dir(user, human) blood_color = human.dna.species.blood_color new /obj/effect/temp_visual/dir_setting/bloodsplatter(human.drop_location(), splatter_dir, blood_color) diff --git a/code/game/gamemodes/miniantags/abduction/gland.dm b/code/game/gamemodes/miniantags/abduction/gland.dm index 445466bfc48..371c16b8a08 100644 --- a/code/game/gamemodes/miniantags/abduction/gland.dm +++ b/code/game/gamemodes/miniantags/abduction/gland.dm @@ -316,9 +316,9 @@ uses = -1 /obj/item/organ/internal/heart/gland/bloody/activate() - owner.blood_volume = max(owner.blood_volume - 20, 0) - owner.visible_message("[owner]'s skin erupts with blood!",\ - "Blood pours from your skin!") + owner.setBlood(max(owner.blood_volume - 20, 0)) + owner.visible_message(span_danger("[owner]'s skin erupts with blood!"), \ + span_userdanger("Blood pours from your skin!")) for(var/turf/T in oview(3,owner)) //Make this respect walls and such owner.add_splatter_floor(T) diff --git a/code/modules/antagonists/vampire/vampire_datum.dm b/code/modules/antagonists/vampire/vampire_datum.dm index ab388e1ffa9..c1dbb7ef48c 100644 --- a/code/modules/antagonists/vampire/vampire_datum.dm +++ b/code/modules/antagonists/vampire/vampire_datum.dm @@ -266,7 +266,7 @@ if(unique_suck_id in drained_humans) if(drained_humans[unique_suck_id] >= BLOOD_DRAIN_LIMIT) to_chat(owner.current, span_warning("Вы поглотили всю жизненную эссенцию [target], дальнейшее питьё крови будет только утолять голод!")) - target.blood_volume = max(target.blood_volume - 25, 0) + target.setBlood(max(target.blood_volume - 25, 0)) owner.current.set_nutrition(min(NUTRITION_LEVEL_WELL_FED, owner.current.nutrition + 5)) continue @@ -277,7 +277,7 @@ adjust_blood(target, blood * BLOOD_GAINED_MODIFIER) to_chat(owner.current, span_boldnotice("Вы накопили [bloodtotal] единиц[declension_ru(bloodtotal, "у", "ы", "")] крови[bloodusable != old_bloodusable ? ", и теперь вам доступно [bloodusable] единиц[declension_ru(bloodusable, "а", "ы", "")] крови" : ""].")) - target.blood_volume = max(target.blood_volume - 25, 0) + target.setBlood(max(target.blood_volume - 25, 0)) //Blood level warnings (Code 'borrowed' from Fulp) if(target.blood_volume) diff --git a/code/modules/antagonists/vampire/vampire_powers/bestia_powers.dm b/code/modules/antagonists/vampire/vampire_powers/bestia_powers.dm index 1ba68b43c40..db0e03d8661 100644 --- a/code/modules/antagonists/vampire/vampire_powers/bestia_powers.dm +++ b/code/modules/antagonists/vampire/vampire_powers/bestia_powers.dm @@ -1582,7 +1582,7 @@ // blood if(!HAS_TRAIT(human_vampire, TRAIT_NO_BLOOD_RESTORE)) - human_vampire.blood_volume = clamp(human_vampire.blood_volume + heal_blood, 0, BLOOD_VOLUME_NORMAL) + human_vampire.setBlood(clamp(human_vampire.blood_volume + heal_blood, 0, BLOOD_VOLUME_NORMAL)) // internal organs for(var/obj/item/organ/internal/organ as anything in human_vampire.internal_organs) @@ -2076,7 +2076,7 @@ if(t_livers && human_vampire && l_target.mind && l_target.ckey) var/blood_amt = round(t_livers / 2) vampire.adjust_blood(l_target, blood_amt) // +5 vampire blood max - l_target.blood_volume = max(l_target.blood_volume - blood_amt, 0) // -5 blood MAX + l_target.setBlood(max(l_target.blood_volume - blood_amt, 0)) // -5 blood MAX human_vampire.set_nutrition(min(NUTRITION_LEVEL_WELL_FED, human_vampire.nutrition + 5)) @@ -2249,7 +2249,7 @@ if(t_livers && human_vampire && l_target.mind && l_target.ckey) var/blood_amt = round(t_livers / 2) vampire.adjust_blood(l_target, blood_amt) // +5 vampire blood max - l_target.blood_volume = max(l_target.blood_volume - blood_amt, 0) // -5 blood MAX + l_target.setBlood(max(l_target.blood_volume - blood_amt, 0)) // -5 blood MAX human_vampire.set_nutrition(min(NUTRITION_LEVEL_WELL_FED, human_vampire.nutrition + 5)) diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm index f966df04963..7ef73f42ec5 100644 --- a/code/modules/mob/living/living.dm +++ b/code/modules/mob/living/living.dm @@ -873,36 +873,49 @@ /mob/living/proc/makeTrail(turf/T) if(!has_gravity()) return - var/blood_exists = 0 - for(var/obj/effect/decal/cleanable/trail_holder/C in loc) //checks for blood splatter already on the floor - blood_exists = 1 + var/blood_exists = FALSE + + for(var/obj/effect/decal/cleanable/trail_holder/C in loc) // checks for blood splatter already on the floor + blood_exists = TRUE + if(isturf(loc)) var/trail_type = getTrail() + if(trail_type) var/brute_ratio = round(getBruteLoss()/maxHealth, 0.1) - if(blood_volume && blood_volume > max(BLOOD_VOLUME_NORMAL*(1 - brute_ratio * 0.25), 0))//don't leave trail if blood volume below a threshold - blood_volume = max(blood_volume - max(1, brute_ratio * 2), 0) //that depends on our brute damage. + + if(blood_volume && blood_volume > max(BLOOD_VOLUME_NORMAL*(1 - brute_ratio * 0.25), 0)) // don't leave trail if blood volume below a threshold + setBlood(max(blood_volume - max(1, brute_ratio * 2), 0)) // that depends on our brute damage. var/newdir = get_dir(T, loc) + if(newdir != src.dir) newdir = newdir | dir + if(newdir == 3) //N + S newdir = NORTH + else if(newdir == 12) //E + W newdir = EAST + if((newdir in GLOB.cardinal) && (prob(50))) newdir = turn(get_dir(T, loc), 180) + if(!blood_exists) new /obj/effect/decal/cleanable/trail_holder(loc) + for(var/obj/effect/decal/cleanable/trail_holder/TH in loc) if((!(newdir in TH.existing_dirs) || trail_type == "trails_1" || trail_type == "trails_2") && TH.existing_dirs.len <= 16) //maximum amount of overlays is 16 (all light & heavy directions filled) TH.existing_dirs += newdir TH.overlays.Add(image('icons/effects/blood.dmi', trail_type, dir = newdir)) TH.transfer_mob_blood_dna(src) + if(ishuman(src)) var/mob/living/carbon/human/H = src + if(H.dna.species.blood_color) TH.color = H.dna.species.blood_color + else TH.color = "#A10808" diff --git a/code/modules/paperwork/contract.dm b/code/modules/paperwork/contract.dm index 6696c160477..739a3f7cb9f 100644 --- a/code/modules/paperwork/contract.dm +++ b/code/modules/paperwork/contract.dm @@ -209,7 +209,7 @@ span_danger("You slice your wrist open and scrawl your name in blood."), ) if(ishuman(user)) - user.blood_volume = max(0, user.blood_volume - 100) + user.setBlood(max(0, user.blood_volume - 100)) /obj/item/paper/contract/infernal/proc/attempt_signature(mob/living/carbon/human/user, blood = 0) diff --git a/code/modules/reagents/chemistry/reagents/medicine.dm b/code/modules/reagents/chemistry/reagents/medicine.dm index 02a1f3e2441..6e08d76eee6 100644 --- a/code/modules/reagents/chemistry/reagents/medicine.dm +++ b/code/modules/reagents/chemistry/reagents/medicine.dm @@ -141,7 +141,7 @@ if(method == REAGENT_INGEST && iscarbon(M)) var/mob/living/carbon/C = M if(C.get_blood_id() == id && !HAS_TRAIT(C, TRAIT_NO_BLOOD_RESTORE)) - C.blood_volume = min(C.blood_volume + round(volume, 0.1), BLOOD_VOLUME_NORMAL) + C.setBlood(min(C.blood_volume + round(volume, 0.1), BLOOD_VOLUME_NORMAL)) C.reagents.del_reagent(id) /datum/reagent/medicine/cryoxadone/on_mob_life(mob/living/M) @@ -1053,20 +1053,20 @@ if(severity == 1) if(effect <= 2) M.vomit(0, VOMIT_BLOOD, 0 SECONDS) - M.blood_volume = max(M.blood_volume - rand(5, 10), 0) + M.setBlood(max(M.blood_volume - rand(5, 10), 0)) else if(effect <= 4) M.vomit(0, VOMIT_BLOOD, 0 SECONDS) - M.blood_volume = max(M.blood_volume - rand(1, 2), 0) + M.setBlood(max(M.blood_volume - rand(1, 2), 0)) else if(severity == 2) if(effect <= 2) M.visible_message("[M] is bleeding from [M.p_their()] very pores!") M.bleed(rand(10, 20)) else if(effect <= 4) M.vomit(0, VOMIT_BLOOD, 0 SECONDS) - M.blood_volume = max(M.blood_volume - rand(5, 10), 0) + M.setBlood(max(M.blood_volume - rand(5, 10), 0)) else if(effect <= 8) M.vomit(0, VOMIT_BLOOD, 0 SECONDS) - M.blood_volume = max(M.blood_volume - rand(1, 2), 0) + M.setBlood(max(M.blood_volume - rand(1, 2), 0)) return list(effect, update_flags) diff --git a/code/modules/reagents/chemistry/reagents/toxins.dm b/code/modules/reagents/chemistry/reagents/toxins.dm index a8d96df05b4..9840b80713b 100644 --- a/code/modules/reagents/chemistry/reagents/toxins.dm +++ b/code/modules/reagents/chemistry/reagents/toxins.dm @@ -132,7 +132,7 @@ if(method == REAGENT_INGEST && iscarbon(M)) var/mob/living/carbon/C = M if(C.get_blood_id() == id && !HAS_TRAIT(C, TRAIT_NO_BLOOD_RESTORE)) - C.blood_volume = min(C.blood_volume + round(volume, 0.1), BLOOD_VOLUME_NORMAL) + C.setBlood(min(C.blood_volume + round(volume, 0.1), BLOOD_VOLUME_NORMAL)) C.reagents.del_reagent(id) /datum/reagent/slimejelly/reaction_turf(turf/T, volume, color) diff --git a/code/modules/surgery/organs/blood.dm b/code/modules/surgery/organs/blood.dm index 030c9924d30..832c8653cd1 100644 --- a/code/modules/surgery/organs/blood.dm +++ b/code/modules/surgery/organs/blood.dm @@ -84,12 +84,17 @@ /mob/living/carbon/proc/bleed(amt) if(!blood_volume) return FALSE + . = TRUE - blood_volume = max(blood_volume - amt, 0) + + setBlood(max(blood_volume - amt, 0)) + if(!isturf(loc)) //Blood loss still happens in locker, floor stays clean return . + if(amt >= 10) add_splatter_floor(loc) + else add_splatter_floor(loc, small_drip = TRUE) @@ -110,12 +115,16 @@ /mob/living/carbon/proc/bleed_internal(amt) if(!blood_volume) return FALSE + . = TRUE - blood_volume = max(blood_volume - amt, 0) + + setBlood(max(blood_volume - amt, 0)) + if(prob(10 * amt)) // +5% chance per internal bleeding site that we'll cough up blood on a given tick. - custom_emote(EMOTE_AUDIBLE, "кашля%(ет,ют)% кровью!") + custom_emote(EMOTE_AUDIBLE, "кашля%(ет, ют)% кровью!") add_splatter_floor(loc, small_drip = TRUE) return . + // +2.5% chance per internal bleeding site that we'll cough up blood on a given tick. // Must be bleeding internally in more than one place to have a chance at this. if(amt >= 1 && prob(5 * amt)) @@ -152,11 +161,23 @@ return ..(amount) +/mob/living/proc/setBlood(amount) + if(HAS_TRAIT(src, TRAIT_NO_BLOOD)) + return FALSE + + if(SEND_SIGNAL(src, COMSIG_LIVING_EARLY_SET_BLOOD, amount) & COMPONENT_PREVENT_BLOODLOSS) + return FALSE + + blood_volume = max(round(amount, DAMAGE_PRECISION), 0) + SEND_SIGNAL(src, COMSIG_LIVING_SET_BLOOD, amount) + + return TRUE + /mob/living/proc/restore_blood() - blood_volume = initial(blood_volume) + setBlood(initial(blood_volume)) /mob/living/carbon/human/restore_blood() - blood_volume = BLOOD_VOLUME_NORMAL + setBlood(BLOOD_VOLUME_NORMAL) bleed_rate = 0 /**************************************************** @@ -194,7 +215,7 @@ C.reagents.add_reagent("toxin", amount * 0.5) return 1 - C.blood_volume = min(C.blood_volume + round(amount, 0.1), BLOOD_VOLUME_NORMAL) + C.setBlood(min(C.blood_volume + round(amount, 0.1), BLOOD_VOLUME_NORMAL)) return 1 AM.reagents.add_reagent(blood_id, amount, blood_data, bodytemperature)