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)