diff --git a/code/game/gamemodes/cult/blood_magic.dm b/code/game/gamemodes/cult/blood_magic.dm
index 8f3285653a9..8c63827e308 100644
--- a/code/game/gamemodes/cult/blood_magic.dm
+++ b/code/game/gamemodes/cult/blood_magic.dm
@@ -735,148 +735,161 @@
. += "Blood orb and blood empower cost [BLOOD_ORB_COST] and [BLOOD_RECHARGE_COST] charges respectively."
. += "You have collected [uses] charge\s of blood."
+/obj/item/melee/blood_magic/manipulator/proc/restore_blood(mob/living/carbon/human/user, mob/living/carbon/human/H)
+ if(uses == 0)
+ return
+ if(!H.dna || (NO_BLOOD in H.dna.species.species_traits) || !isnull(H.dna.species.exotic_blood))
+ return
+ if(H.blood_volume >= BLOOD_VOLUME_SAFE)
+ return
+ var/restore_blood = BLOOD_VOLUME_SAFE - H.blood_volume
+ if(uses * 2 < restore_blood)
+ H.blood_volume += uses * 2
+ to_chat(user, "You use the last of your charges to restore what blood you could, and the spell dissipates!")
+ uses = 0
+ else
+ H.blood_volume = BLOOD_VOLUME_SAFE
+ uses -= round(restore_blood / 2)
+ to_chat(user, "Your blood rites have restored [H == user ? "your" : "[H.p_their()]"] blood to safe levels!")
+
+/obj/item/melee/blood_magic/manipulator/proc/heal_human_damage(mob/living/carbon/human/user, mob/living/carbon/human/H)
+ if(uses == 0)
+ return
+ var/overall_damage = H.getBruteLoss() + H.getFireLoss() + H.getToxLoss() + H.getOxyLoss()
+ if(overall_damage == 0)
+ to_chat(user, "[H] doesn't require healing!")
+ return
+
+ var/ratio = uses / overall_damage
+ if(H == user)
+ to_chat(user, "Your blood healing is far less efficient when used on yourself!")
+ ratio *= 0.35 // Healing is half as effective if you can't perform a full heal
+ uses -= round(overall_damage) // Healing is 65% more "expensive" even if you can still perform the full heal
+ if(ratio > 1)
+ ratio = 1
+ uses -= round(overall_damage)
+ H.visible_message("[H] is fully healed by [H == user ? "[H.p_their()]" : "[H]'s"] blood magic!",
+ "You are fully healed by [H == user ? "your" : "[user]'s"] blood magic!")
+ else
+ H.visible_message("[H] is partially healed by [H == user ? "[H.p_their()]" : "[H]'s"] blood magic.",
+ "You are partially healed by [H == user ? "your" : "[user]'s"] blood magic.")
+ uses = 0
+ ratio *= -1
+ H.adjustOxyLoss((overall_damage * ratio) * (H.getOxyLoss() / overall_damage), FALSE, null, TRUE)
+ H.adjustToxLoss((overall_damage * ratio) * (H.getToxLoss() / overall_damage), FALSE, null, TRUE)
+ H.adjustFireLoss((overall_damage * ratio) * (H.getFireLoss() / overall_damage), FALSE, null, TRUE)
+ H.adjustBruteLoss((overall_damage * ratio) * (H.getBruteLoss() / overall_damage), FALSE, null, TRUE)
+ H.updatehealth()
+ playsound(get_turf(H), 'sound/magic/staff_healing.ogg', 25)
+ new /obj/effect/temp_visual/cult/sparks(get_turf(H))
+ user.Beam(H, icon_state="sendbeam", time = 15)
+
+/obj/item/melee/blood_magic/manipulator/proc/heal_cultist(mob/living/carbon/human/user, mob/living/carbon/human/H)
+ if(H.stat == DEAD)
+ to_chat(user, "Only a revive rune can bring back the dead!")
+ return
+ var/charge_loss = uses
+ restore_blood(user, H)
+ heal_human_damage(user, H)
+ charge_loss = charge_loss - uses
+ if(!uses)
+ to_chat(user, "You use the last of your charges to heal [H == user ? "yourself" : "[H]"], and the spell dissipates!")
+ else
+ to_chat(user, "You use [charge_loss] charge\s, and have [uses] remaining.")
+
+/obj/item/melee/blood_magic/manipulator/proc/heal_construct(mob/living/carbon/human/user, mob/living/simple_animal/M)
+ if(uses == 0)
+ return
+ var/missing = M.maxHealth - M.health
+ if(!missing)
+ to_chat(user, "[M] doesn't require healing!")
+ return
+ if(uses > missing)
+ M.adjustHealth(-missing)
+ M.visible_message("[M] is fully healed by [user]'s blood magic!",
+ "You are fully healed by [user]'s blood magic!")
+ uses -= missing
+ else
+ M.adjustHealth(-uses)
+ M.visible_message("[M] is partially healed by [user]'s blood magic!",
+ "You are partially healed by [user]'s blood magic.")
+ uses = 0
+ playsound(get_turf(M), 'sound/magic/staff_healing.ogg', 25)
+ user.Beam(M, icon_state = "sendbeam", time = 10)
+
+/obj/item/melee/blood_magic/manipulator/proc/steal_blood(mob/living/carbon/human/user, mob/living/carbon/human/H)
+ if(H.stat == DEAD)
+ to_chat(user, "[H.p_their(TRUE)] blood has stopped flowing, you'll have to find another way to extract it.")
+ return
+ if(H.AmountCultSlurring())
+ to_chat(user, "[H.p_their(TRUE)] blood has been tainted by an even stronger form of blood magic, it's no use to us like this!")
+ return
+ if(!H.dna || (NO_BLOOD in H.dna.species.species_traits) || H.dna.species.exotic_blood != null)
+ to_chat(user, "[H] does not have any usable blood!")
+ return
+ if(H.blood_volume <= BLOOD_VOLUME_SAFE)
+ to_chat(user, "[H] is missing too much blood - you cannot drain [H.p_them()] further!")
+ return
+ H.blood_volume -= 100
+ uses += 50
+ user.Beam(H, icon_state = "drainbeam", time = 10)
+ playsound(get_turf(H), 'sound/misc/enter_blood.ogg', 50)
+ H.visible_message("[user] has drained some of [H]'s blood!",
+ "[user] has drained some of your blood!")
+ to_chat(user, "Your blood rite gains 50 charges from draining [H]'s blood.")
+ new /obj/effect/temp_visual/cult/sparks(get_turf(H))
+
// This should really be split into multiple procs
/obj/item/melee/blood_magic/manipulator/afterattack(atom/target, mob/living/carbon/human/user, proximity)
if(user.holy_check())
return
- if(proximity)
- if(ishuman(target))
- var/mob/living/carbon/human/H = target
+ if(!proximity)
+ return ..()
+ if(ishuman(target))
+ if(iscultist(target))
+ heal_cultist(user, target)
+ target.clean_blood()
+ else
+ steal_blood(user, target)
+ return
- //Healing a cultist
- if(iscultist(H))
- var/charge_loss = uses // Before/after charge difference
- if(H.stat == DEAD)
- to_chat(user, "Only a revive rune can bring back the dead!")
- return
+ if(isconstruct(target))
+ heal_construct(user, target)
+ return
- //Blood restoration
- if(H.dna && !(NO_BLOOD in H.dna.species.species_traits) && H.dna.species.exotic_blood == null)
- if(H.blood_volume < BLOOD_VOLUME_SAFE)
- var/restore_blood = BLOOD_VOLUME_SAFE - H.blood_volume
- if(uses * 2 < restore_blood)
- H.blood_volume += uses * 2
- to_chat(user, "You use the last of your charges to restore what blood you could, and the spell dissipates!")
- uses = 0
- return ..()
- else
- H.blood_volume = BLOOD_VOLUME_SAFE
- uses -= round(restore_blood / 2)
- to_chat(user, "Your blood rites have restored [H == user ? "your" : "[H.p_their()]"] blood to safe levels!")
-
- //Damage healing
- var/overall_damage = H.getBruteLoss() + H.getFireLoss() + H.getToxLoss() + H.getOxyLoss()
- if(overall_damage == 0)
- to_chat(user, "That cultist doesn't require healing!")
- return
- else
- var/ratio = uses / overall_damage
- if(H == user)
- to_chat(user, "Your blood healing is far less efficient when used on yourself!")
- ratio *= 0.35 // Healing is half as effective if you can't perform a full heal
- uses -= round(overall_damage) // Healing is 65% more "expensive" even if you can still perform the full heal
- if(ratio > 1)
- ratio = 1
- uses -= round(overall_damage)
- H.visible_message("[H] is fully healed by [H == user ? "[H.p_their()]" : "[H]'s"] blood magic!",
- "You are fully healed by [H == user ? "your" : "[user]'s"] blood magic!")
- else
- H.visible_message("[H] is partially healed by [H == user ? "[H.p_their()]" : "[H]'s"] blood magic.",
- "You are partially healed by [H == user ? "your" : "[user]'s"] blood magic.")
- uses = 0
- ratio *= -1
- H.adjustOxyLoss((overall_damage * ratio) * (H.getOxyLoss() / overall_damage), FALSE, null, TRUE)
- H.adjustToxLoss((overall_damage * ratio) * (H.getToxLoss() / overall_damage), FALSE, null, TRUE)
- H.adjustFireLoss((overall_damage * ratio) * (H.getFireLoss() / overall_damage), FALSE, null, TRUE)
- H.adjustBruteLoss((overall_damage * ratio) * (H.getBruteLoss() / overall_damage), FALSE, null, TRUE)
- H.updatehealth()
- playsound(get_turf(H), 'sound/magic/staff_healing.ogg', 25)
- new /obj/effect/temp_visual/cult/sparks(get_turf(H))
- user.Beam(H, icon_state="sendbeam", time = 15)
-
- charge_loss = charge_loss - uses
- if(!uses)
- to_chat(user, "You use the last of your charges to heal [H == user ? "yourself" : "[H]"], and the spell dissipates!")
- else
- to_chat(user, "You use [charge_loss] charge\s, and have [uses] remaining.")
-
- //Draining blood from non-cultists
- else
- if(H.stat == DEAD)
- to_chat(user, "[H.p_their(TRUE)] blood has stopped flowing, you'll have to find another way to extract it.")
- return
- if(H.AmountCultSlurring())
- to_chat(user, "[H.p_their(TRUE)] blood has been tainted by an even stronger form of blood magic, it's no use to us like this!")
- return
- if(H.dna && !(NO_BLOOD in H.dna.species.species_traits) && H.dna.species.exotic_blood == null)
- if(H.blood_volume > BLOOD_VOLUME_SAFE)
- H.blood_volume -= 100
- uses += 50
- user.Beam(H, icon_state = "drainbeam", time = 10)
- playsound(get_turf(H), 'sound/misc/enter_blood.ogg', 50)
- H.visible_message("[user] has drained some of [H]'s blood!",
- "[user] has drained some of your blood!")
- to_chat(user, "Your blood rite gains 50 charges from draining [H]'s blood.")
- new /obj/effect/temp_visual/cult/sparks(get_turf(H))
- else
- to_chat(user, "[H] is missing too much blood - you cannot drain [H.p_them()] further!")
- return
- else
- to_chat(user, "[H] does not have any usable blood!")
- return
-
- //Healing constructs
- if(isconstruct(target))
- var/mob/living/simple_animal/M = target
- var/missing = M.maxHealth - M.health
- if(missing)
- if(uses > missing)
- M.adjustHealth(-missing)
- M.visible_message("[M] is fully healed by [user]'s blood magic!",
- "You are fully healed by [user]'s blood magic!")
- uses -= missing
- else
- M.adjustHealth(-uses)
- M.visible_message("[M] is partially healed by [user]'s blood magic!",
- "You are partially healed by [user]'s blood magic.")
- uses = 0
- playsound(get_turf(M), 'sound/magic/staff_healing.ogg', 25)
- user.Beam(M, icon_state = "sendbeam", time = 10)
-
- //Draining blood on the floor
- if(istype(target, /obj/effect/decal/cleanable/blood) || istype(target, /obj/effect/decal/cleanable/trail_holder))
- blood_draw(target, user)
- if(istype(target, /obj/item/blood_orb))
- var/obj/item/blood_orb/candidate = target
- if(candidate.blood)
- uses += candidate.blood
- to_chat(user, "You obtain [candidate.blood] blood from the orb of blood!")
- playsound(user, 'sound/misc/enter_blood.ogg', 50)
- qdel(candidate)
-
- ..()
+ if(istype(target, /obj/item/blood_orb))
+ var/obj/item/blood_orb/candidate = target
+ if(candidate.blood)
+ uses += candidate.blood
+ to_chat(user, "You obtain [candidate.blood] blood from the orb of blood!")
+ playsound(user, 'sound/misc/enter_blood.ogg', 50)
+ qdel(candidate)
+ return
+ blood_draw(target, user)
/obj/item/melee/blood_magic/manipulator/proc/blood_draw(atom/target, mob/living/carbon/human/user)
var/temp = 0
var/turf/T = get_turf(target)
- if(T)
- for(var/obj/effect/decal/cleanable/blood/B in view(T, 2))
- if(B.blood_state == BLOOD_STATE_HUMAN && (B.can_bloodcrawl_in() || istype(B, /obj/effect/decal/cleanable/blood/slime)))
- if(B.bloodiness == 100) //Bonus for "pristine" bloodpools, also to prevent cheese with footprint spam
- temp += 30
- else
- temp += max((B.bloodiness ** 2) / 800, 1)
- new /obj/effect/temp_visual/cult/turf/open/floor(get_turf(B))
- qdel(B)
- for(var/obj/effect/decal/cleanable/trail_holder/TH in view(T, 2))
- qdel(TH)
- if(temp)
- user.Beam(T, icon_state = "drainbeam", time = 15)
- new /obj/effect/temp_visual/cult/sparks(get_turf(user))
- playsound(T, 'sound/misc/enter_blood.ogg', 50)
- temp = round(temp)
- to_chat(user, "Your blood rite has gained [temp] charge\s from blood sources around you!")
- uses += max(1, temp)
+ if(!T)
+ return
+ for(var/obj/effect/decal/cleanable/blood/B in range(T, 2))
+ if(B.blood_state == BLOOD_STATE_HUMAN && (B.can_bloodcrawl_in() || istype(B, /obj/effect/decal/cleanable/blood/slime)))
+ if(B.bloodiness == 100) //Bonus for "pristine" bloodpools, also to prevent cheese with footprint spam
+ temp += 30
+ else
+ temp += max((B.bloodiness ** 2) / 800, 1)
+ new /obj/effect/temp_visual/cult/turf/open/floor(get_turf(B))
+ qdel(B)
+ for(var/obj/effect/decal/cleanable/trail_holder/TH in range(T, 2))
+ new /obj/effect/temp_visual/cult/turf/open/floor(get_turf(TH))
+ qdel(TH)
+ if(temp)
+ user.Beam(T, icon_state = "drainbeam", time = 15)
+ new /obj/effect/temp_visual/cult/sparks(get_turf(user))
+ playsound(T, 'sound/misc/enter_blood.ogg', 50)
+ temp = round(temp)
+ to_chat(user, "Your blood rite has gained [temp] charge\s from blood sources around you!")
+ uses += max(1, temp)
/obj/item/melee/blood_magic/manipulator/attack_self(mob/living/user)
if(user.holy_check())