diff --git a/code/__DEFINES/genetics.dm b/code/__DEFINES/genetics.dm
index 4cf307dbf34..44057453814 100644
--- a/code/__DEFINES/genetics.dm
+++ b/code/__DEFINES/genetics.dm
@@ -91,3 +91,12 @@
#define NUTRITION_LEVEL_FED 350
#define NUTRITION_LEVEL_HUNGRY 250
#define NUTRITION_LEVEL_STARVING 150
+
+//Blood levels
+#define BLOOD_VOLUME_MAXIMUM 2000
+#define BLOOD_VOLUME_SLIME_SPLIT 1120
+#define BLOOD_VOLUME_NORMAL 560
+#define BLOOD_VOLUME_SAFE 501
+#define BLOOD_VOLUME_OKAY 336
+#define BLOOD_VOLUME_BAD 224
+#define BLOOD_VOLUME_SURVIVE 122
diff --git a/code/_onclick/item_attack.dm b/code/_onclick/item_attack.dm
index d981f93f573..19a1dcf84e1 100644
--- a/code/_onclick/item_attack.dm
+++ b/code/_onclick/item_attack.dm
@@ -64,9 +64,11 @@
if(apply_damage(I.force, I.damtype))
if(I.damtype == BRUTE)
if(prob(33))
+ I.add_mob_blood(src)
var/turf/location = get_turf(src)
- location.add_blood_floor(src)
-
+ add_splatter_floor(location)
+ if(get_dist(user, src) <= 1) //people with TK won't get smeared with blood
+ user.add_mob_blood(src)
// Proximity_flag is 1 if this afterattack was called on something adjacent, in your square, or on your person.
diff --git a/code/game/atoms.dm b/code/game/atoms.dm
index 4a2c0a330ee..3702069a3cc 100644
--- a/code/game/atoms.dm
+++ b/code/game/atoms.dm
@@ -226,37 +226,73 @@ var/list/blood_splatter_icons = list()
/atom/proc/blood_splatter_index()
return "\ref[initial(icon)]-[initial(icon_state)]"
-/atom/proc/add_blood_list(mob/living/carbon/M)
+//returns the mob's dna info as a list, to be inserted in an object's blood_DNA list
+/mob/living/proc/get_blood_dna_list()
+ if(get_blood_id() != "blood")
+ return
+ return list("ANIMAL DNA" = "Y-")
+
+/mob/living/carbon/get_blood_dna_list()
+ if(get_blood_id() != "blood")
+ return
+ var/list/blood_dna = list()
+ if(dna)
+ blood_dna[dna.unique_enzymes] = dna.blood_type
+ else
+ blood_dna["UNKNOWN DNA"] = "X*"
+ return blood_dna
+
+/mob/living/carbon/alien/get_blood_dna_list()
+ return list("UNKNOWN DNA" = "X*")
+
+//to add a mob's dna info into an object's blood_DNA list.
+/atom/proc/transfer_mob_blood_dna(mob/living/L)
// Returns 0 if we have that blood already
- if(!istype(blood_DNA, /list)) //if our list of DNA doesn't exist yet (or isn't a list) initialise it.
+ var/new_blood_dna = L.get_blood_dna_list()
+ if(!new_blood_dna)
+ return 0
+ if(!blood_DNA) //if our list of DNA doesn't exist yet, initialise it.
blood_DNA = list()
- //if this blood isn't already in the list, add it
- if(blood_DNA[M.dna.unique_enzymes])
- return 0 //already bloodied with this blood. Cannot add more.
- blood_DNA[M.dna.unique_enzymes] = M.dna.blood_type
+ var/old_length = blood_DNA.len
+ blood_DNA |= new_blood_dna
+ if(blood_DNA.len == old_length)
+ return 0
return 1
-//returns 1 if made bloody, returns 0 otherwise
-/atom/proc/add_blood(mob/living/carbon/M)
- if(!M || !M.has_dna() || rejects_blood())
- return 0
- if(ishuman(M))
- var/mob/living/carbon/human/H = M
- if(NOBLOOD in H.dna.species.specflags)
- return 0
- return 1
+//to add blood dna info to the object's blood_DNA list
+/atom/proc/transfer_blood_dna(list/blood_dna)
+ if(!blood_DNA)
+ blood_DNA = list()
+ var/old_length = blood_DNA.len
+ blood_DNA |= blood_dna
+ if(blood_DNA.len > old_length)
+ return 1//some new blood DNA was added
-/obj/add_blood(mob/living/carbon/M)
- if(!..())
- return 0
- return add_blood_list(M)
-/obj/item/add_blood(mob/living/carbon/M)
+//to add blood from a mob onto something, and transfer their dna info
+/atom/proc/add_mob_blood(mob/living/M)
+ var/list/blood_dna = M.get_blood_dna_list()
+ if(!blood_dna)
+ return 0
+ return add_blood(blood_dna)
+
+//to add blood onto something, with blood dna info to include.
+/atom/proc/add_blood(list/blood_dna)
+ return 0
+
+/obj/add_blood(list/blood_dna)
+ return transfer_blood_dna(blood_dna)
+
+/obj/item/add_blood(list/blood_dna)
var/blood_count = !blood_DNA ? 0 : blood_DNA.len
if(!..())
return 0
- //apply the blood-splatter overlay if it isn't already in there
- if(!blood_count && initial(icon) && initial(icon_state))
+ if(!blood_count)//apply the blood-splatter overlay if it isn't already in there
+ add_blood_overlay()
+ return 1 //we applied blood to the item
+
+/obj/item/proc/add_blood_overlay()
+ if(initial(icon) && initial(icon_state))
//try to find a pre-processed blood-splatter. otherwise, make a new one
var/index = blood_splatter_index()
var/icon/blood_splatter_icon = blood_splatter_icons[index]
@@ -267,56 +303,33 @@ var/list/blood_splatter_icons = list()
blood_splatter_icon = fcopy_rsc(blood_splatter_icon)
blood_splatter_icons[index] = blood_splatter_icon
overlays += blood_splatter_icon
- return 1 //we applied blood to the item
-/obj/item/clothing/gloves/add_blood(mob/living/carbon/M)
- if(!..())
- return 0
+/obj/item/clothing/gloves/add_blood(list/blood_dna)
+ . = ..()
transfer_blood = rand(2, 4)
- bloody_hands_mob = M
- return 1
-/turf/add_blood(mob/living/carbon/human/M)
- if(!..())
- return 0
-
- var/obj/effect/decal/cleanable/blood/B = locate() in contents //check for existing blood splatter
+/turf/add_blood(list/blood_dna)
+ var/obj/effect/decal/cleanable/blood/splatter/B = locate() in src
if(!B)
- blood_splatter(src,M.get_blood(M.vessel),1)
- B = locate(/obj/effect/decal/cleanable/blood) in contents
- B.add_blood_list(M)
+ B = new /obj/effect/decal/cleanable/blood/splatter(src)
+ B.transfer_blood_dna(blood_dna) //give blood info to the blood decal.
return 1 //we bloodied the floor
-/mob/living/carbon/human/add_blood(mob/living/carbon/M)
- if(!..())
- return 0
- add_blood_list(M)
+/mob/living/carbon/human/add_blood(list/blood_dna)
+ if(wear_suit)
+ wear_suit.add_blood(blood_dna)
+ update_inv_wear_suit()
+ else if(w_uniform)
+ w_uniform.add_blood(blood_dna)
+ update_inv_w_uniform()
+ if(gloves)
+ var/obj/item/clothing/gloves/G = gloves
+ G.add_blood(blood_dna)
+ else
+ transfer_blood_dna(blood_dna)
bloody_hands = rand(2, 4)
- bloody_hands_mob = M
update_inv_gloves() //handles bloody hands overlays and updating
- return 1 //we applied blood to the item
-
-/atom/proc/rejects_blood()
- return 0
-
-// Only adds blood on the floor -- Skie
-/atom/proc/add_blood_floor(mob/living/carbon/M)
- if(istype(src, /turf))
- if(M.has_dna()) //mobs with dna = (monkeys + humans at time of writing)
- var/obj/effect/decal/cleanable/blood/B = locate() in contents
- if(!B)
- blood_splatter(src,M,1)
- B = locate(/obj/effect/decal/cleanable/blood) in contents
- B.blood_DNA[M.dna.unique_enzymes] = M.dna.blood_type
- else if(istype(M, /mob/living/carbon/alien))
- var/obj/effect/decal/cleanable/xenoblood/B = locate() in contents
- if(!B)
- B = new(src)
- B.blood_DNA["UNKNOWN BLOOD"] = "X*"
- else if(istype(M, /mob/living/silicon/robot))
- var/obj/effect/decal/cleanable/oil/B = locate() in contents
- if(!B)
- B = new(src)
+ return 1
/atom/proc/clean_blood()
if(istype(blood_DNA, /list))
diff --git a/code/game/gamemodes/changeling/powers/mutations.dm b/code/game/gamemodes/changeling/powers/mutations.dm
index 1dc79ffc084..7d50aca1ee6 100644
--- a/code/game/gamemodes/changeling/powers/mutations.dm
+++ b/code/game/gamemodes/changeling/powers/mutations.dm
@@ -96,10 +96,8 @@
H.update_hair()
if(blood_on_castoff)
- var/turf/T = get_turf(H)
- if(istype(T))
- T.add_blood(H) //So real blood decals
- playsound(H.loc, 'sound/effects/splat.ogg', 50, 1) //So real sounds
+ H.add_splatter_floor()
+ playsound(H.loc, 'sound/effects/splat.ogg', 50, 1) //So real sounds
changeling.geneticdamage += genetic_damage //Casting off a space suit leaves you weak for a few seconds.
changeling.chem_recharge_slowdown -= recharge_slowdown
diff --git a/code/game/gamemodes/cult/cult_items.dm b/code/game/gamemodes/cult/cult_items.dm
index 73ec9b1982c..5607b1f6bdf 100644
--- a/code/game/gamemodes/cult/cult_items.dm
+++ b/code/game/gamemodes/cult/cult_items.dm
@@ -45,9 +45,9 @@
/obj/item/weapon/melee/cultblade/dagger/attack(mob/living/target, mob/living/carbon/human/user)
..()
- if(ishuman(target))
- var/mob/living/carbon/human/H = target
- H.drip(50)
+ if(iscarbon(target))
+ var/mob/living/carbon/C = target
+ C.bleed(50)
/obj/item/weapon/restraints/legcuffs/bola/cult
diff --git a/code/game/gamemodes/miniantags/abduction/gland.dm b/code/game/gamemodes/miniantags/abduction/gland.dm
index 537f29f3551..74e592ba826 100644
--- a/code/game/gamemodes/miniantags/abduction/gland.dm
+++ b/code/game/gamemodes/miniantags/abduction/gland.dm
@@ -191,14 +191,9 @@
"Blood pours from your skin!")
for(var/turf/T in oview(3,owner)) //Make this respect walls and such
- T.add_blood_floor(owner)
+ owner.add_splatter_floor(T)
for(var/mob/living/carbon/human/H in oview(3,owner)) //Blood decals for simple animals would be neat. aka Carp with blood on it.
- if(H.wear_suit)
- H.wear_suit.add_blood(owner)
- H.update_inv_wear_suit(0)
- else if(H.w_uniform)
- H.w_uniform.add_blood(owner)
- H.update_inv_w_uniform(0)
+ H.add_mob_blood(owner)
/obj/item/organ/gland/bodysnatch
origin_tech = "materials=4;biotech=7;abductor=3"
diff --git a/code/game/gamemodes/wizard/artefact.dm b/code/game/gamemodes/wizard/artefact.dm
index 1213bfe6ca5..3f8d58b7377 100644
--- a/code/game/gamemodes/wizard/artefact.dm
+++ b/code/game/gamemodes/wizard/artefact.dm
@@ -419,7 +419,7 @@ var/global/list/multiverse = list()
M.equip_to_slot_or_del(sword, slot_r_hand)
for(var/obj/item/carried_item in M.contents)
if(!istype(carried_item, /obj/item/weapon/implant))
- carried_item.add_blood(M)
+ carried_item.add_mob_blood(M)
if("pirate")
M.equip_to_slot_or_del(new /obj/item/clothing/under/pirate(M), slot_w_uniform)
diff --git a/code/game/machinery/computer/medical.dm b/code/game/machinery/computer/medical.dm
index 51c0c3e8264..4de92482f3b 100644
--- a/code/game/machinery/computer/medical.dm
+++ b/code/game/machinery/computer/medical.dm
@@ -563,35 +563,31 @@
return
/obj/machinery/computer/med_data/emp_act(severity)
- if(stat & (BROKEN|NOPOWER))
- ..(severity)
- return
+ if(!(stat & (BROKEN|NOPOWER)))
+ for(var/datum/data/record/R in data_core.medical)
+ if(prob(10/severity))
+ switch(rand(1,6))
+ if(1)
+ if(prob(10))
+ R.fields["name"] = random_unique_lizard_name(R.fields["sex"],1)
+ else
+ R.fields["name"] = random_unique_name(R.fields["sex"],1)
+ if(2)
+ R.fields["sex"] = pick("Male", "Female")
+ if(3)
+ R.fields["age"] = rand(AGE_MIN, AGE_MAX)
+ if(4)
+ R.fields["blood_type"] = random_blood_type()
+ if(5)
+ R.fields["p_stat"] = pick("*Unconcious*", "Active", "Physically Unfit")
+ if(6)
+ R.fields["m_stat"] = pick("*Insane*", "*Unstable*", "*Watch*", "Stable")
+ continue
- for(var/datum/data/record/R in data_core.medical)
- if(prob(10/severity))
- switch(rand(1,6))
- if(1)
- if(prob(10))
- R.fields["name"] = random_unique_lizard_name(R.fields["sex"],1)
- else
- R.fields["name"] = random_unique_name(R.fields["sex"],1)
- if(2)
- R.fields["sex"] = pick("Male", "Female")
- if(3)
- R.fields["age"] = rand(AGE_MIN, AGE_MAX)
- if(4)
- R.fields["blood_type"] = random_blood_type()
- if(5)
- R.fields["p_stat"] = pick("*Unconcious*", "Active", "Physically Unfit")
- if(6)
- R.fields["m_stat"] = pick("*Insane*", "*Unstable*", "*Watch*", "Stable")
- continue
-
- else if(prob(1))
- qdel(R)
- continue
-
- ..(severity)
+ else if(prob(1))
+ qdel(R)
+ continue
+ ..()
/obj/machinery/computer/med_data/proc/canUseMedicalRecordsConsole(mob/user, message = 1, record1, record2)
if(user)
diff --git a/code/game/machinery/doors/door.dm b/code/game/machinery/doors/door.dm
index 015c78b195a..5ff956d30dc 100644
--- a/code/game/machinery/doors/door.dm
+++ b/code/game/machinery/doors/door.dm
@@ -307,7 +307,7 @@ obj/machinery/door/proc/try_to_crowbar(obj/item/I, mob/user)
L.adjustBruteLoss(DOOR_CRUSH_DAMAGE)
var/turf/location = get_turf(src)
//add_blood doesn't work for borgs/xenos, but add_blood_floor does.
- location.add_blood_floor(L)
+ L.add_splatter_floor(location)
for(var/obj/mecha/M in get_turf(src))
M.take_damage(DOOR_CRUSH_DAMAGE)
diff --git a/code/game/machinery/iv_drip.dm b/code/game/machinery/iv_drip.dm
index c47bc00617d..a6ef761b884 100644
--- a/code/game/machinery/iv_drip.dm
+++ b/code/game/machinery/iv_drip.dm
@@ -4,7 +4,7 @@
icon_state = "iv_drip"
anchored = 0
density = 1
- var/mob/living/carbon/human/attached = null
+ var/mob/living/carbon/attached = null
var/mode = 1 // 1 is injecting, 0 is taking blood.
var/obj/item/weapon/reagent_containers/beaker = null
@@ -65,8 +65,8 @@
update_icon()
return
- if(!ishuman(target))
- usr << "The drip beeps: Warning, human patients only!"
+ if(!target.has_dna())
+ usr << "The drip beeps: Warning, incompatible creature!"
return
if(Adjacent(target) && usr.Adjacent(target))
@@ -129,36 +129,15 @@
if(prob(5)) visible_message("\The [src] pings.")
return
- var/mob/living/carbon/human/T = attached
-
- if(!istype(T))
- return
-
- if(T.disabilities & NOCLONE)
- return
-
- if((NOBLOOD in T.dna.species.specflags) && !T.dna.species.exotic_blood)
- return
-
- if(T.dna.species.exotic_blood)
- T.reagents.trans_to(beaker, amount)
- update_icon()
- else
- // If the human is losing too much blood, beep.
- if(T.vessel.get_reagent_amount("blood") < BLOOD_VOLUME_SAFE && prob(5))
- visible_message("\The [src] beeps loudly.")
- playsound(loc, 'sound/machines/twobeep.ogg', 50, 1)
- var/datum/reagent/B = T.take_blood(beaker,amount)
-
- if (B)
- beaker.reagents.reagent_list |= B
- beaker.reagents.update_total()
- beaker.on_reagent_change()
- beaker.reagents.handle_reactions()
- update_icon()
+ // If the human is losing too much blood, beep.
+ if(attached.blood_volume < BLOOD_VOLUME_SAFE && prob(5))
+ visible_message("\The [src] beeps loudly.")
+ playsound(loc, 'sound/machines/twobeep.ogg', 50, 1)
+ attached.transfer_blood_to(beaker, amount)
+ update_icon()
/obj/machinery/iv_drip/attack_hand(mob/user)
- if (!ishuman(user))
+ if(!ishuman(user))
return
if(attached)
visible_message("[attached] is detached from \the [src]")
diff --git a/code/game/machinery/pipe/construction.dm b/code/game/machinery/pipe/construction.dm
index 05915bc884c..2d125831b43 100644
--- a/code/game/machinery/pipe/construction.dm
+++ b/code/game/machinery/pipe/construction.dm
@@ -248,9 +248,7 @@ var/global/list/pipeID2State = list(
for(var/i=1 to 20)
C.vomit(0,1,0,4,0)
sleep(5)
- if(istype(user, /mob/living/carbon/human))
- var/mob/living/carbon/human/H = C
- H.vessel.remove_reagent("blood",560)
+ C.blood_volume = 0
return(OXYLOSS|BRUTELOSS)
else
return ..()
diff --git a/code/game/machinery/recycler.dm b/code/game/machinery/recycler.dm
index 4b37378f666..21db6aeb7cc 100644
--- a/code/game/machinery/recycler.dm
+++ b/code/game/machinery/recycler.dm
@@ -169,7 +169,7 @@ var/const/SAFETY_COOLDOWN = 100
gib = FALSE
if(L.stat == CONSCIOUS)
L.say("ARRRRRRRRRRRGH!!!")
- add_blood(L)
+ add_mob_blood(L)
if(!blood && !issilicon(L))
blood = TRUE
diff --git a/code/game/objects/effects/decals/Cleanable/humans.dm b/code/game/objects/effects/decals/Cleanable/humans.dm
index e6e90cbde1c..4c679597d97 100644
--- a/code/game/objects/effects/decals/Cleanable/humans.dm
+++ b/code/game/objects/effects/decals/Cleanable/humans.dm
@@ -3,7 +3,7 @@
desc = "It's red and gooey. Perhaps it's the chef's cooking?"
gender = PLURAL
density = 0
- layer = ABOVE_OPEN_TURF_LAYER
+ layer = ABOVE_NORMAL_TURF_LAYER
icon = 'icons/effects/blood.dmi'
icon_state = "floor1"
random_icon_states = list("floor1", "floor2", "floor3", "floor4", "floor5", "floor6", "floor7")
@@ -106,12 +106,8 @@
icon_state = "1"
random_icon_states = list("1","2","3","4","5")
bloodiness = 0
- var/list/drips = list()
+ var/drips = 1
-/obj/effect/decal/cleanable/blood/drip/New()
- ..()
- spawn(1)
- drips |= icon_state
/obj/effect/decal/cleanable/blood/drip/can_bloodcrawl_in()
return 1
diff --git a/code/game/objects/effects/decals/cleanable.dm b/code/game/objects/effects/decals/cleanable.dm
index 548ade544e2..9a24696cc87 100644
--- a/code/game/objects/effects/decals/cleanable.dm
+++ b/code/game/objects/effects/decals/cleanable.dm
@@ -70,6 +70,8 @@
add_blood = bloodiness
bloodiness -= add_blood
S.bloody_shoes[blood_state] = min(MAX_SHOE_BLOODINESS,S.bloody_shoes[blood_state]+add_blood)
+ if(blood_DNA && blood_DNA.len)
+ S.add_blood(blood_DNA)
S.blood_state = blood_state
update_icon()
H.update_inv_shoes()
diff --git a/code/game/objects/items.dm b/code/game/objects/items.dm
index 2839bb1250b..936a599281a 100644
--- a/code/game/objects/items.dm
+++ b/code/game/objects/items.dm
@@ -511,7 +511,6 @@ obj/item/proc/item_action_slot_check(slot, mob/user)
. = ..()
if(.)
transfer_blood = 0
- bloody_hands_mob = null
/obj/item/singularity_pull(S, current_size)
if(current_size >= STAGE_FOUR)
diff --git a/code/game/objects/items/devices/radio/intercom.dm b/code/game/objects/items/devices/radio/intercom.dm
index 8532aeb4ea2..e69d096205c 100644
--- a/code/game/objects/items/devices/radio/intercom.dm
+++ b/code/game/objects/items/devices/radio/intercom.dm
@@ -67,5 +67,5 @@
else
icon_state = "intercom"
-/obj/item/device/radio/intercom/rejects_blood()
- return 1
+/obj/item/device/radio/intercom/add_mob_blood(mob/living/carbon/M)
+ return 0
diff --git a/code/game/objects/items/devices/scanners.dm b/code/game/objects/items/devices/scanners.dm
index 146610a5197..7ef05e74f23 100644
--- a/code/game/objects/items/devices/scanners.dm
+++ b/code/game/objects/items/devices/scanners.dm
@@ -173,7 +173,7 @@ MASS SPECTROMETER
// Time of death
if(M.tod && (M.stat == DEAD || (M.status_flags & FAKEDEATH)))
user << "Time of Death: [M.tod]"
- var/tdelta = world.time - M.timeofdeath
+ var/tdelta = round(world.time - M.timeofdeath)
if(tdelta < (DEFIB_TIME_LIMIT * 10))
user << "Subject died [tdelta / 10] seconds \
ago, defibrillation may be possible!"
@@ -183,26 +183,29 @@ MASS SPECTROMETER
user << "Warning: [D.form] detected\nName: [D.name].\nType: [D.spread_text].\nStage: [D.stage]/[D.max_stages].\nPossible Cure: [D.cure_text]"
// Blood Level
- if(ishuman(M))
- var/mob/living/carbon/human/H = M
- if(H.vessel)
- if(H.blood_max)
- user << "Subject is bleeding!"
- var/blood_volume = round(H.vessel.get_reagent_amount("blood"))
- var/blood_percent = round((blood_volume / 560),0.01)
- var/blood_type = H.dna.blood_type
- blood_percent *= 100
- if(blood_volume <= 500 && blood_volume > 336)
- user << "LOW blood level [blood_percent] %, [blood_volume] cl, type: [blood_type]"
- else if(blood_volume <= 336)
- user << "CRITICAL blood level CRITICAL [blood_percent] %, [blood_volume] cl, type: [blood_type]"
+ if(M.has_dna())
+ var/mob/living/carbon/C = M
+ var/blood_id = C.get_blood_id()
+ if(blood_id)
+ if(ishuman(C))
+ var/mob/living/carbon/human/H = C
+ if(H.bleed_rate)
+ user << "Subject is bleeding!"
+ var/blood_percent = round((C.blood_volume / BLOOD_VOLUME_NORMAL)*100)
+ var/blood_type = C.dna.blood_type
+ if(blood_id != "blood")//special blood substance
+ blood_type = blood_id
+ if(C.blood_volume <= BLOOD_VOLUME_SAFE && C.blood_volume > BLOOD_VOLUME_OKAY)
+ user << "LOW blood level [blood_percent] %, [C.blood_volume] cl, type: [blood_type]"
+ else if(C.blood_volume <= BLOOD_VOLUME_OKAY)
+ user << "CRITICAL blood level [blood_percent] %, [C.blood_volume] cl, type: [blood_type]"
else
- user << "Blood level [blood_percent] %, [blood_volume] cl, type: [blood_type]"
+ user << "Blood level [blood_percent] %, [C.blood_volume] cl, type: [blood_type]"
var/implant_detect
- for(var/obj/item/organ/cyberimp/CI in H.internal_organs)
+ for(var/obj/item/organ/cyberimp/CI in C.internal_organs)
if(CI.status == ORGAN_ROBOTIC)
- implant_detect += "[H.name] is modified with a [CI.name].
"
+ implant_detect += "[C.name] is modified with a [CI.name].
"
if(implant_detect)
user << "Detected cybernetic modifications:"
user << "[implant_detect]"
diff --git a/code/game/objects/items/stacks/medical.dm b/code/game/objects/items/stacks/medical.dm
index eb1a1d7abd0..4cbf7c75299 100644
--- a/code/game/objects/items/stacks/medical.dm
+++ b/code/game/objects/items/stacks/medical.dm
@@ -40,7 +40,7 @@
if(H.bleedsuppress)
user << "[H]'s bleeding is already bandaged!"
return
- else if(!H.blood_max)
+ else if(!H.bleed_rate)
user << "[H] isn't bleeding!"
return
diff --git a/code/game/objects/items/weapons/melee/energy.dm b/code/game/objects/items/weapons/melee/energy.dm
index ac17bdbae2a..25cf489bf0f 100644
--- a/code/game/objects/items/weapons/melee/energy.dm
+++ b/code/game/objects/items/weapons/melee/energy.dm
@@ -13,8 +13,8 @@
"[user] is falling on the [src.name]! It looks like \he's trying to commit suicide."))
return (BRUTELOSS|FIRELOSS)
-/obj/item/weapon/melee/energy/rejects_blood()
- return 1
+/obj/item/weapon/melee/energy/add_mob_blood(mob/living/carbon/M)
+ return 0
/obj/item/weapon/melee/energy/is_sharp()
return active * sharpness
diff --git a/code/game/objects/items/weapons/melee/misc.dm b/code/game/objects/items/weapons/melee/misc.dm
index 5f33b5a192d..4953a136b4c 100644
--- a/code/game/objects/items/weapons/melee/misc.dm
+++ b/code/game/objects/items/weapons/melee/misc.dm
@@ -220,5 +220,5 @@
T.ChangeTurf(T.baseturf)
T.CalculateAdjacentTurfs()
-/obj/item/weapon/melee/supermatter_sword/add_blood()
+/obj/item/weapon/melee/supermatter_sword/add_mob_blood()
return
diff --git a/code/game/objects/items/weapons/tanks/tanks.dm b/code/game/objects/items/weapons/tanks/tanks.dm
index f8b5263cba1..431996019f4 100644
--- a/code/game/objects/items/weapons/tanks/tanks.dm
+++ b/code/game/objects/items/weapons/tanks/tanks.dm
@@ -113,7 +113,7 @@
step(W, pick(alldirs))
H.hair_style = "Bald"
H.update_hair()
- H.blood_max = 5
+ H.bleed_rate = 5
gibs(H.loc, H.viruses, H.dna)
H.adjustBruteLoss(1000) //to make the body super-bloody
diff --git a/code/game/objects/structures/kitchen_spike.dm b/code/game/objects/structures/kitchen_spike.dm
index 998a6820328..ddfd102d863 100644
--- a/code/game/objects/structures/kitchen_spike.dm
+++ b/code/game/objects/structures/kitchen_spike.dm
@@ -65,9 +65,7 @@
L.visible_message("[user] slams [L] onto the meat spike!", "[user] slams you onto the meat spike!", "You hear a squishy wet noise.")
L.loc = src.loc
L.emote("scream")
- if(ishuman(L)) //So you don't get human blood when you spike a giant spider
- var/turf/pos = get_turf(L)
- pos.add_blood_floor(L)
+ L.add_splatter_floor()
L.adjustBruteLoss(30)
L.buckled = src
L.dir = 2
diff --git a/code/modules/client/preferences.dm b/code/modules/client/preferences.dm
index 57854738378..c3747346a01 100644
--- a/code/modules/client/preferences.dm
+++ b/code/modules/client/preferences.dm
@@ -47,7 +47,6 @@ var/list/preferences_datums = list()
var/be_random_body = 0 //whether we'll have a random body every round
var/gender = MALE //gender of character (well duh)
var/age = 30 //age of character
- var/blood_type = "A+" //blood type (not-chooseable)
var/underwear = "Nude" //underwear type
var/undershirt = "Nude" //undershirt type
var/socks = "Nude" //socks type
@@ -92,7 +91,6 @@ var/list/preferences_datums = list()
var/list/ignoring = list()
/datum/preferences/New(client/C)
- blood_type = random_blood_type()
custom_names["ai"] = pick(ai_names)
custom_names["cyborg"] = pick(ai_names)
custom_names["clown"] = pick(clown_names)
@@ -190,7 +188,6 @@ var/list/preferences_datums = list()
else
dat += "Species: Human
"
- dat += "Blood Type: [blood_type]
"
dat += "Underwear:
[underwear]
"
dat += "Undershirt:
[undershirt]
"
dat += "Socks:
[socks]
"
@@ -1192,7 +1189,6 @@ var/list/preferences_datums = list()
character.backbag = backbag
- character.dna.blood_type = blood_type
character.dna.features = features.Copy()
character.dna.real_name = character.real_name
var/datum/species/chosen_species
diff --git a/code/modules/clothing/outfits/standard.dm b/code/modules/clothing/outfits/standard.dm
index e1f8ad0bdcc..517230e8773 100644
--- a/code/modules/clothing/outfits/standard.dm
+++ b/code/modules/clothing/outfits/standard.dm
@@ -135,7 +135,7 @@
/datum/outfit/psycho/post_equip(mob/living/carbon/human/H)
for(var/obj/item/carried_item in H.contents)
if(!istype(carried_item, /obj/item/weapon/implant))//If it's not an implant.
- carried_item.add_blood(H)//Oh yes, there will be blood...
+ carried_item.add_mob_blood(H)//Oh yes, there will be blood...
H.regenerate_icons()
/datum/outfit/assassin
diff --git a/code/modules/detectivework/detective_work.dm b/code/modules/detectivework/detective_work.dm
index 6fa698d12d2..4322546b022 100644
--- a/code/modules/detectivework/detective_work.dm
+++ b/code/modules/detectivework/detective_work.dm
@@ -6,10 +6,10 @@
if(M.gloves && istype(M.gloves,/obj/item/clothing/))
var/obj/item/clothing/gloves/G = M.gloves
if(G.transfer_blood > 1) //bloodied gloves transfer blood to touched objects
- if(add_blood(G.bloody_hands_mob)) //only reduces the bloodiness of our gloves if the item wasn't already bloody
+ if(add_blood(G.blood_DNA)) //only reduces the bloodiness of our gloves if the item wasn't already bloody
G.transfer_blood--
else if(M.bloody_hands > 1)
- if(add_blood(M.bloody_hands_mob))
+ if(add_blood(M.blood_DNA))
M.bloody_hands--
if(!suit_fibers) suit_fibers = list()
var/fibertext
diff --git a/code/modules/detectivework/footprints_and_rag.dm b/code/modules/detectivework/footprints_and_rag.dm
index 17e5b467066..df05f33ccdb 100644
--- a/code/modules/detectivework/footprints_and_rag.dm
+++ b/code/modules/detectivework/footprints_and_rag.dm
@@ -1,11 +1,9 @@
/mob
var/bloody_hands = 0
- var/mob/living/carbon/human/bloody_hands_mob
/obj/item/clothing/gloves
var/transfer_blood = 0
- var/mob/living/carbon/human/bloody_hands_mob
/obj/item/weapon/reagent_containers/glass/rag
diff --git a/code/modules/mob/living/blood.dm b/code/modules/mob/living/blood.dm
new file mode 100644
index 00000000000..f4a39d34771
--- /dev/null
+++ b/code/modules/mob/living/blood.dm
@@ -0,0 +1,271 @@
+/****************************************************
+ BLOOD SYSTEM
+****************************************************/
+
+/mob/living/carbon/human/proc/suppress_bloodloss(amount)
+ if(bleedsuppress)
+ return
+ else
+ bleedsuppress = 1
+ spawn(amount)
+ bleedsuppress = 0
+ if(stat != DEAD && bleed_rate)
+ src << "The blood soaks through your bandage."
+
+
+/mob/living/carbon/monkey/handle_blood()
+ if(bodytemperature >= 225 && !(disabilities & NOCLONE)) //cryosleep or husked people do not pump the blood.
+ //Blood regeneration if there is some space
+ if(blood_volume < BLOOD_VOLUME_NORMAL)
+ blood_volume += 0.1 // regenerate blood VERY slowly
+
+// Takes care blood loss and regeneration
+/mob/living/carbon/human/handle_blood()
+
+ if(NOBLOOD in dna.species.specflags)
+ bleed_rate = 0
+ return
+
+ if(bodytemperature >= 225 && !(disabilities & NOCLONE)) //cryosleep or husked people do not pump the blood.
+
+ //Blood regeneration if there is some space
+ if(blood_volume < BLOOD_VOLUME_NORMAL)
+ blood_volume += 0.1 // regenerate blood VERY slowly
+
+ //Effects of bloodloss
+ switch(blood_volume)
+ if(BLOOD_VOLUME_OKAY to BLOOD_VOLUME_SAFE)
+ if(prob(5))
+ src << "You feel [pick("dizzy","woozy","faint")]."
+ adjustOxyLoss(round((BLOOD_VOLUME_NORMAL - blood_volume) * 0.01, 1))
+ if(BLOOD_VOLUME_BAD to BLOOD_VOLUME_OKAY)
+ adjustOxyLoss(round((BLOOD_VOLUME_NORMAL - blood_volume) * 0.02, 1))
+ if(prob(5))
+ blur_eyes(6)
+ var/word = pick("dizzy","woozy","faint")
+ src << "You feel very [word]."
+ if(BLOOD_VOLUME_SURVIVE to BLOOD_VOLUME_BAD)
+ adjustOxyLoss(5)
+ if(prob(15))
+ Paralyse(rand(1,3))
+ var/word = pick("dizzy","woozy","faint")
+ src << "You feel extremely [word]."
+ if(0 to BLOOD_VOLUME_SURVIVE)
+ death()
+
+ var/temp_bleed = 0
+ //Bleeding out
+ for(var/X in bodyparts)
+ var/obj/item/bodypart/BP = X
+ var/brutedamage = BP.brute_dam
+
+ //We want an accurate reading of .len
+ listclearnulls(BP.embedded_objects)
+ temp_bleed += 0.5*BP.embedded_objects.len
+
+ if(brutedamage > 30)
+ temp_bleed += 0.5
+ if(brutedamage > 50)
+ temp_bleed += 1
+ if(brutedamage > 70)
+ temp_bleed += 2
+
+ bleed_rate = max(bleed_rate - 0.5, temp_bleed)//if no wounds, other bleed effects (heparin) naturally decreases
+
+ if(bleed_rate && !bleedsuppress)
+ bleed(bleed_rate)
+
+//Makes a blood drop, leaking amt units of blood from the mob
+/mob/living/carbon/proc/bleed(amt)
+ if(blood_volume)
+ blood_volume = max(blood_volume - amt, 0)
+ if(isturf(src.loc)) //Blood loss still happens in locker, floor stays clean
+ if(amt >= 10)
+ add_splatter_floor(src.loc)
+ else
+ add_splatter_floor(src.loc, 1)
+
+/mob/living/carbon/human/bleed(amt)
+ if(!(NOBLOOD in dna.species.specflags))
+ ..()
+
+
+
+/mob/living/proc/restore_blood()
+ blood_volume = initial(blood_volume)
+
+/mob/living/carbon/human/restore_blood()
+ blood_volume = BLOOD_VOLUME_NORMAL
+ bleed_rate = 0
+
+/****************************************************
+ BLOOD TRANSFERS
+****************************************************/
+
+//Gets blood from mob to a container or other mob, preserving all data in it.
+/mob/living/proc/transfer_blood_to(atom/movable/AM, amount, forced)
+ if(!blood_volume || !AM.reagents)
+ return 0
+ if(blood_volume < BLOOD_VOLUME_BAD && !forced)
+ return 0
+
+ if(blood_volume < amount)
+ amount = blood_volume
+
+ var/blood_id = get_blood_id()
+ if(!blood_id)
+ return 0
+
+ blood_volume -= amount
+
+ var/list/blood_data = get_blood_data(blood_id)
+
+ if(iscarbon(AM))
+ var/mob/living/carbon/C = AM
+ if(blood_id == C.get_blood_id())//both mobs have the same blood substance
+ if(blood_id == "blood") //normal blood
+ if(blood_data["viruses"])
+ for(var/datum/disease/D in blood_data["viruses"])
+ if((D.spread_flags & SPECIAL) || (D.spread_flags & NON_CONTAGIOUS))
+ continue
+ C.ForceContractDisease(D)
+ if(!(blood_data["blood_type"] in get_safe_blood(C.dna.blood_type)))
+ C.reagents.add_reagent("toxin", amount * 0.5)
+ return 1
+
+ C.blood_volume = min(C.blood_volume + round(amount, 0.1), BLOOD_VOLUME_MAXIMUM)
+ return 1
+
+ AM.reagents.add_reagent(blood_id, amount, blood_data, bodytemperature)
+ return 1
+
+
+/mob/living/proc/get_blood_data(blood_id)
+ return
+
+/mob/living/carbon/get_blood_data(blood_id)
+ if(blood_id == "blood") //actual blood reagent
+ var/blood_data = list()
+ //set the blood data
+ blood_data["donor"] = src
+ blood_data["viruses"] = list()
+
+ for(var/datum/disease/D in viruses)
+ blood_data["viruses"] += D.Copy()
+
+ blood_data["blood_DNA"] = copytext(dna.unique_enzymes,1,0)
+ if(resistances && resistances.len)
+ blood_data["resistances"] = resistances.Copy()
+ var/list/temp_chem = list()
+ for(var/datum/reagent/R in reagents.reagent_list)
+ temp_chem[R.id] = R.volume
+ blood_data["trace_chem"] = list2params(temp_chem)
+ if(mind)
+ blood_data["mind"] = mind
+ if(ckey)
+ blood_data["ckey"] = ckey
+ if(!suiciding)
+ blood_data["cloneable"] = 1
+ blood_data["blood_type"] = copytext(dna.blood_type,1,0)
+ blood_data["gender"] = gender
+ blood_data["real_name"] = real_name
+ blood_data["features"] = dna.features
+ blood_data["factions"] = faction
+ return blood_data
+
+//get the id of the substance this mob use as blood.
+/mob/proc/get_blood_id()
+ return
+
+/mob/living/simple_animal/get_blood_id()
+ if(blood_volume)
+ return "blood"
+
+/mob/living/carbon/monkey/get_blood_id()
+ if(!(disabilities & NOCLONE))
+ return "blood"
+
+/mob/living/carbon/human/get_blood_id()
+ if(dna.species.exotic_blood)
+ return dna.species.exotic_blood
+ else if((NOBLOOD in dna.species.specflags) || (disabilities & NOCLONE))
+ return
+ return "blood"
+
+// This is has more potential uses, and is probably faster than the old proc.
+/proc/get_safe_blood(bloodtype)
+ . = list()
+ if(!bloodtype)
+ return
+ switch(bloodtype)
+ if("A-")
+ return list("A-", "O-")
+ if("A+")
+ return list("A-", "A+", "O-", "O+")
+ if("B-")
+ return list("B-", "O-")
+ if("B+")
+ return list("B-", "B+", "O-", "O+")
+ if("AB-")
+ return list("A-", "B-", "O-", "AB-")
+ if("AB+")
+ return list("A-", "A+", "B-", "B+", "O-", "O+", "AB-", "AB+")
+ if("O-")
+ return list("O-")
+ if("O+")
+ return list("O-", "O+")
+ if("L")
+ return list("L")
+
+//to add a splatter of blood or other mob liquid.
+/mob/living/proc/add_splatter_floor(turf/T, small_drip)
+ if(get_blood_id() != "blood")
+ return
+ if(!T)
+ T = get_turf(src)
+
+ var/list/temp_blood_DNA
+ if(small_drip)
+ // Only a certain number of drips (or one large splatter) can be on a given turf.
+ var/obj/effect/decal/cleanable/blood/drip/drop = locate() in T
+ if(drop)
+ if(drop.drips < 3)
+ drop.drips++
+ drop.overlays |= pick(drop.random_icon_states)
+ drop.transfer_mob_blood_dna(src)
+ return
+ else
+ temp_blood_DNA = list()
+ temp_blood_DNA |= drop.blood_DNA.Copy() //we transfer the dna from the drip to the splatter
+ qdel(drop)//the drip is replaced by a bigger splatter
+ else
+ drop = new(T)
+ drop.transfer_mob_blood_dna(src)
+ return
+
+ // Find a blood decal or create a new one.
+ var/obj/effect/decal/cleanable/blood/B = locate() in T
+ if(!B)
+ B = new /obj/effect/decal/cleanable/blood/splatter(T)
+ B.transfer_mob_blood_dna(src) //give blood info to the blood decal.
+ if(temp_blood_DNA)
+ B.blood_DNA |= temp_blood_DNA
+
+/mob/living/carbon/human/add_splatter_floor(turf/T, small_drip)
+ if(!(NOBLOOD in dna.species.specflags))
+ ..()
+
+/mob/living/carbon/alien/add_splatter_floor(turf/T, small_drip)
+ if(!T)
+ T = get_turf(src)
+ var/obj/effect/decal/cleanable/xenoblood/B = locate() in T.contents
+ if(!B)
+ B = new(T)
+ B.blood_DNA["UNKNOWN DNA"] = "X*"
+
+/mob/living/silicon/robot/add_splatter_floor(turf/T, small_drip)
+ if(!T)
+ T = get_turf(src)
+ var/obj/effect/decal/cleanable/oil/B = locate() in T.contents
+ if(!B)
+ B = new(T)
\ No newline at end of file
diff --git a/code/modules/mob/living/carbon/carbon.dm b/code/modules/mob/living/carbon/carbon.dm
index 75ae791a001..54c33958954 100644
--- a/code/modules/mob/living/carbon/carbon.dm
+++ b/code/modules/mob/living/carbon/carbon.dm
@@ -1,3 +1,6 @@
+/mob/living/carbon
+ blood_volume = BLOOD_VOLUME_NORMAL
+
/mob/living/carbon/New()
create_reagents(1000)
..()
@@ -294,16 +297,6 @@
"[usr] [internal ? "opens" : "closes"] the valve on [src]'s [ITEM].")
-
-/mob/living/carbon/getTrail()
- if(getBruteLoss() < 300)
- if(prob(50))
- return "ltrails_1"
- return "ltrails_2"
- else if(prob(50))
- return "trails_1"
- return "trails_2"
-
/mob/living/carbon/fall(forced)
loc.handle_fall(src, forced)//it's loc so it doesn't call the mob's handle_fall which does nothing
@@ -561,7 +554,7 @@
for(var/i=0 to distance)
if(blood)
if(T)
- T.add_blood_floor(src)
+ add_splatter_floor(T)
if(stun)
adjustBruteLoss(3)
else
diff --git a/code/modules/mob/living/carbon/human/blood.dm b/code/modules/mob/living/carbon/human/blood.dm
deleted file mode 100644
index b68124230d4..00000000000
--- a/code/modules/mob/living/carbon/human/blood.dm
+++ /dev/null
@@ -1,318 +0,0 @@
-/****************************************************
- BLOOD SYSTEM
-****************************************************/
-//Blood levels
-var/const/BLOOD_VOLUME_NORMAL = 560
-var/const/BLOOD_VOLUME_SAFE = 501
-var/const/BLOOD_VOLUME_OKAY = 336
-var/const/BLOOD_VOLUME_BAD = 224
-var/const/BLOOD_VOLUME_SURVIVE = 122
-
-/mob/living/carbon/human/var/datum/reagents/vessel //Container for blood and BLOOD ONLY. Do not transfer other chems here.
-/mob/living/carbon/human/var/pale = 0 //Should affect how mob sprite is drawn, but currently doesn't.
-
-//Initializes blood vessels
-/mob/living/carbon/human/proc/make_blood()
- if(vessel)
- return
-
- vessel = new/datum/reagents(600)
- vessel.my_atom = src
-
- if(NOBLOOD in dna.species.specflags)
- return
-
- vessel.add_reagent("blood", BLOOD_VOLUME_NORMAL)
- for(var/datum/reagent/blood/B in vessel.reagent_list)
- if(B.id == "blood")
- B.data = list(
- "donor" = src,
- "viruses" = null,
- "blood_DNA" = dna.unique_enzymes,
- "blood_type" = dna.blood_type,
- "resistances" = null,
- "trace_chem" = null,
- "mind" = null,
- "ckey" = null,
- "gender" = null,
- "real_name" = null,
- "cloneable" = null,
- "features" = null,
- "factions" = null)
-
-/mob/living/carbon/human/proc/suppress_bloodloss(amount)
- if(bleedsuppress)
- return
- else
- bleedsuppress = 1
- spawn(amount)
- bleedsuppress = 0
- if(stat != DEAD && blood_max)
- src << "The blood soaks through your bandage."
-
-// Takes care blood loss and regeneration
-/mob/living/carbon/human/handle_blood()
-
- if(NOBLOOD in dna.species.specflags)
- blood_max = 0
- return
-
- if(stat != DEAD && bodytemperature >= 225) // Dead or cryosleep people do not pump the blood.
- var/blood_volume = round(vessel.get_reagent_amount("blood"))
-
- //Blood regeneration if there is some space
- if(blood_volume < BLOOD_VOLUME_NORMAL)
- var/datum/reagent/blood/B = locate() in vessel.reagent_list //Grab some blood
- if(B) // Make sure there's some blood at all
- if(B.data["donor"] != src) //If it's not theirs, then we look for theirs
- for(var/datum/reagent/blood/D in vessel.reagent_list)
- if(D.data["donor"] == src)
- B = D
- break
-
- B.volume += 0.1 // regenerate blood VERY slowly
- if(reagents.has_reagent("nutriment")) //Getting food speeds it up
- B.volume += 0.4
- reagents.remove_reagent("nutriment", 0.1)
- if(reagents.has_reagent("iron")) //Hematogen candy anyone?
- B.volume += 0.4
- reagents.remove_reagent("iron", 0.1)
-
- //Effects of bloodloss
- switch(blood_volume)
- if(BLOOD_VOLUME_SAFE to 10000)
- if(pale)
- pale = 0
- update_body()
- if(BLOOD_VOLUME_OKAY to BLOOD_VOLUME_SAFE)
- if(!pale)
- pale = 1
- update_body()
- var/word = pick("dizzy","woozy","faint")
- src << "You feel [word]."
- adjustOxyLoss((BLOOD_VOLUME_NORMAL - blood_volume) / 100)
- if(BLOOD_VOLUME_BAD to BLOOD_VOLUME_OKAY)
- if(!pale)
- pale = 1
- update_body()
- adjustOxyLoss((BLOOD_VOLUME_NORMAL - blood_volume) / 50)
- if(prob(5))
- blur_eyes(6)
- var/word = pick("dizzy","woozy","faint")
- src << "You feel very [word]."
- if(BLOOD_VOLUME_SURVIVE to BLOOD_VOLUME_BAD)
- oxyloss += 5
- if(prob(15))
- Paralyse(rand(1,3))
- var/word = pick("dizzy","woozy","faint")
- src << "You feel extremely [word]."
- if(0 to BLOOD_VOLUME_SURVIVE)
- death()
-
- //Bleeding out
- blood_max = 0
- for(var/X in bodyparts)
- var/obj/item/bodypart/BP = X
- var/brutedamage = BP.brute_dam
-
- //We want an accurate reading of .len
- listclearnulls(BP.embedded_objects)
- blood_max += 0.5*BP.embedded_objects.len
-
- if(brutedamage > 30)
- blood_max += 0.5
- if(brutedamage > 50)
- blood_max += 1
- if(brutedamage > 70)
- blood_max += 2
- if(bleedsuppress)
- blood_max = 0
- if(reagents.has_reagent("heparin") && getBruteLoss()) //Heparin is a powerful toxin that causes bleeding
- blood_max += 3
- drip(blood_max)
-
-//Makes a blood drop, leaking amt units of blood from the mob
-/mob/living/carbon/human/proc/drip(amt as num)
-
- if(!amt)
- return
-
- vessel.remove_reagent("blood",amt)
- if (isturf(src.loc)) //Blood loss still happens in locker, floor stays clean
- blood_splatter(src,src)
-
-/****************************************************
- BLOOD TRANSFERS
-****************************************************/
-
-//Gets blood from mob to the container, preserving all data in it.
-/mob/living/carbon/proc/take_blood(obj/item/weapon/reagent_containers/container, amount)
-
- var/datum/reagent/B = get_blood(container.reagents)
- if(!B) B = new /datum/reagent/blood
- B.holder = container
- B.volume += amount
-
- //set reagent data
- B.data["donor"] = src
- B.data["viruses"] = list()
- /*
- if(T.virus && T.virus.spread_type != SPECIAL)
- B.data["virus"] = new T.virus.type(0)
- */
-
- for(var/datum/disease/D in src.viruses)
- B.data["viruses"] += D.Copy()
-
- B.data["blood_DNA"] = copytext(src.dna.unique_enzymes,1,0)
- if(src.resistances&&src.resistances.len)
- B.data["resistances"] = src.resistances.Copy()
- var/list/temp_chem = list()
- for(var/datum/reagent/R in src.reagents.reagent_list)
- temp_chem[R.id] = R.volume
- B.data["trace_chem"] = list2params(temp_chem)
- if(mind)
- B.data["mind"] = src.mind
- if(ckey)
- B.data["ckey"] = src.ckey
- if(!suiciding)
- B.data["cloneable"] = 1
- B.data["blood_type"] = copytext(src.dna.blood_type,1,0)
- B.data["gender"] = src.gender
- B.data["real_name"] = src.real_name
- B.data["features"] = src.dna.features
- B.data["factions"] = src.faction
- return B
-
-//For humans, blood does not appear from blue, it comes from vessels.
-/mob/living/carbon/human/take_blood(obj/item/weapon/reagent_containers/container, amount)
-
- if(NOBLOOD in dna.species.specflags)
- return null
-
- if(vessel.get_reagent_amount("blood") < amount)
- return null
-
- . = ..()
- vessel.remove_reagent("blood",amount) // Removes blood if human
-
-//Transfers blood from container to vessels
-/mob/living/carbon/proc/inject_blood(obj/item/weapon/reagent_containers/container, amount)
-
- var/datum/reagent/blood/injected = get_blood(container.reagents)
-
- if(!injected)
- return
-
- var/list/chems = list()
- chems = params2list(injected.data["trace_chem"])
- for(var/C in chems)
- src.reagents.add_reagent(C, (text2num(chems[C]) / 560) * amount)//adds trace chemicals to owner's blood
- reagents.update_total()
-
- container.reagents.remove_reagent("blood", amount)
-
-//Transfers blood from container to vessels, respecting blood types compatibility.
-/mob/living/carbon/human/inject_blood(obj/item/weapon/reagent_containers/container, amount)
-
- var/datum/reagent/blood/injected = get_blood(container.reagents)
-
- if(NOBLOOD in dna.species.specflags)
- reagents.add_reagent("blood", amount, injected.data)
- reagents.update_total()
- return
-
- var/datum/reagent/blood/our = get_blood(vessel)
-
- if (!injected || !our || !dna)
- return
-
- if (!(injected.data["blood_type"] in get_safe_blood(dna.blood_type)) || (injected.data["species"] && injected.data["species"] != dna.species.id))
- reagents.add_reagent("toxin",amount * 0.5)
- our.on_merge(injected.data) //still transfer viruses and such, even if incompatibles bloods
- reagents.update_total()
- else
- vessel.add_reagent("blood", amount, injected.data)
- vessel.update_total()
- ..()
-
-//Gets human's own blood.
-/mob/living/carbon/proc/get_blood(datum/reagents/container)
- var/datum/reagent/blood/res = locate() in container.reagent_list //Grab some blood
- if(res) // Make sure there's some blood at all
- if(res.data["donor"] != src) //If it's not theirs, then we look for theirs
- for(var/datum/reagent/blood/D in container.reagent_list)
- if(D.data["donor"] == src)
- return D
- return res
-
-// This is has more potential uses, and is probably faster than the old proc.
-/proc/get_safe_blood(bloodtype)
- . = list()
- if(!bloodtype)
- return
- switch(bloodtype)
- if("A-")
- return list("A-", "O-")
- if("A+")
- return list("A-", "A+", "O-", "O+")
- if("B-")
- return list("B-", "O-")
- if("B+")
- return list("B-", "B+", "O-", "O+")
- if("AB-")
- return list("A-", "B-", "O-", "AB-")
- if("AB+")
- return list("A-", "A+", "B-", "B+", "O-", "O+", "AB-", "AB+")
- if("O-")
- return list("O-")
- if("O+")
- return list("O-", "O+")
-
-/proc/blood_splatter(target,datum/reagent/blood/source,large)
-
- var/obj/effect/decal/cleanable/blood/B
- var/decal_type = /obj/effect/decal/cleanable/blood/splatter
- var/turf/T = get_turf(target)
-
- if(istype(source,/mob/living/carbon/human))
- var/mob/living/carbon/human/M = source
- source = M.get_blood(M.vessel)
- else if(istype(source,/mob/living/carbon/monkey))
- var/mob/living/carbon/monkey/donor = source
- source = new()
- source.data["blood_DNA"] = donor.dna.unique_enzymes
- source.data["blood_type"] = donor.dna.blood_type
-
- // Are we dripping or splattering?
- var/list/drips = list()
- // Only a certain number of drips (or one large splatter) can be on a given turf.
- for(var/obj/effect/decal/cleanable/blood/drip/drop in T)
- drips |= drop.drips
- qdel(drop)
- if(!large && drips.len < 3)
- decal_type = /obj/effect/decal/cleanable/blood/drip
-
- // Find a blood decal or create a new one.
- B = locate(decal_type) in T
- if(!B)
- B = new decal_type(T)
-
- var/obj/effect/decal/cleanable/blood/drip/drop = B
- if(istype(drop) && drips && drips.len && !large)
- drop.overlays |= drips
- drop.drips |= drips
-
- // If there's no data to copy, call it quits here.
- if(!source)
- return B
-
- // Update blood information.
- if(source.data["blood_DNA"])
- B.blood_DNA = list()
- if(source.data["blood_type"])
- B.blood_DNA[source.data["blood_DNA"]] = source.data["blood_type"]
- else
- B.blood_DNA[source.data["blood_DNA"]] = "O+"
-
- return B
diff --git a/code/modules/mob/living/carbon/human/death.dm b/code/modules/mob/living/carbon/human/death.dm
index 393e7e9f2e5..07e56e80a1b 100644
--- a/code/modules/mob/living/carbon/human/death.dm
+++ b/code/modules/mob/living/carbon/human/death.dm
@@ -57,4 +57,5 @@
/mob/living/carbon/proc/Drain()
ChangeToHusk()
disabilities |= NOCLONE
+ blood_volume = 0
return 1
diff --git a/code/modules/mob/living/carbon/human/examine.dm b/code/modules/mob/living/carbon/human/examine.dm
index b2fa55a403d..e6b9d15be24 100644
--- a/code/modules/mob/living/carbon/human/examine.dm
+++ b/code/modules/mob/living/carbon/human/examine.dm
@@ -247,12 +247,12 @@
else
msg += "[t_He] [t_is] quite chubby.\n"
- if(pale)
+ if(blood_volume < BLOOD_VOLUME_SAFE)
msg += "[t_He] [t_has] pale skin.\n"
if(bleedsuppress)
msg += "[t_He] [t_is] bandaged with something.\n"
- if(blood_max)
+ if(bleed_rate)
if(reagents.has_reagent("heparin"))
msg += "[t_He] [t_is] bleeding uncontrollably!\n"
else
diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm
index 0614caaf9f0..dab8babb2d8 100644
--- a/code/modules/mob/living/carbon/human/human.dm
+++ b/code/modules/mob/living/carbon/human/human.dm
@@ -49,8 +49,6 @@
for(var/obj/item/organ/I in internal_organs)
I.Insert(src)
- make_blood()
-
martial_art = default_martial_art
handcrafting = new()
@@ -800,7 +798,7 @@
for(var/t in missing)
src << "Your [parse_zone(t)] is missing!"
- if(blood_max)
+ if(bleed_rate)
src << "You are bleeding!"
if(staminaloss)
if(staminaloss > 30)
@@ -893,7 +891,6 @@
..() // Clear the Blood_DNA list
if(H.bloody_hands)
H.bloody_hands = 0
- H.bloody_hands_mob = null
H.update_inv_gloves()
update_icons() //apply the now updated overlays to the mob
@@ -1032,7 +1029,6 @@
T = new()
T.Insert(src)
- restore_blood()
remove_all_embedded_objects()
drunkenness = 0
for(var/datum/mutation/human/HM in dna.mutations)
@@ -1083,4 +1079,4 @@
/mob/living/carbon/human/update_gravity(has_gravity,override = 0)
override = dna.species.override_float
- ..()
+ ..()
diff --git a/code/modules/mob/living/carbon/human/human_damage.dm b/code/modules/mob/living/carbon/human/human_damage.dm
index ca45f109c58..da3204f6b0e 100644
--- a/code/modules/mob/living/carbon/human/human_damage.dm
+++ b/code/modules/mob/living/carbon/human/human_damage.dm
@@ -153,11 +153,6 @@
if(update)
update_damage_overlays(0)
-/mob/living/carbon/human/proc/restore_blood()
- if(!(NOBLOOD in dna.species.specflags))
- var/blood_volume = vessel.get_reagent_amount("blood")
- vessel.add_reagent("blood",560-blood_volume)
-
////////////////////////////////////////////
diff --git a/code/modules/mob/living/carbon/human/human_defense.dm b/code/modules/mob/living/carbon/human/human_defense.dm
index 91cfb3d12d7..312f41bddba 100644
--- a/code/modules/mob/living/carbon/human/human_defense.dm
+++ b/code/modules/mob/living/carbon/human/human_defense.dm
@@ -357,7 +357,7 @@
throw_alert("embeddedobject", /obj/screen/alert/embeddedobject)
var/obj/item/bodypart/L = pick(bodyparts)
L.embedded_objects |= I
- I.add_blood(src)//it embedded itself in you, of course it's bloody!
+ I.add_mob_blood(src)//it embedded itself in you, of course it's bloody!
I.loc = src
L.take_damage(I.w_class*I.embedded_impact_pain_multiplier)
visible_message("\the [I.name] embeds itself in [src]'s [L.name]!","\the [I.name] embeds itself in your [L.name]!")
diff --git a/code/modules/mob/living/carbon/human/human_defines.dm b/code/modules/mob/living/carbon/human/human_defines.dm
index 4a1699d80e1..1054ae35ea2 100644
--- a/code/modules/mob/living/carbon/human/human_defines.dm
+++ b/code/modules/mob/living/carbon/human/human_defines.dm
@@ -44,7 +44,7 @@ var/global/default_martial_art = new/datum/martial_art
var/gender_ambiguous = 0 //if something goes wrong during gender reassignment this generates a line in examine
- var/blood_max = 0 //how much are we bleeding
+ var/bleed_rate = 0 //how much are we bleeding
var/bleedsuppress = 0 //for stopping bloodloss, eventually this will be limb-based like bleeding
var/datum/martial_art/martial_art = null
@@ -54,4 +54,4 @@ var/global/default_martial_art = new/datum/martial_art
var/heart_attack = 0
var/drunkenness = 0 //Overall drunkenness - check handle_alcohol() in life.dm for effects
- var/datum/personal_crafting/handcrafting
+ var/datum/personal_crafting/handcrafting
diff --git a/code/modules/mob/living/carbon/human/human_movement.dm b/code/modules/mob/living/carbon/human/human_movement.dm
index 0bc87b8520a..3bb4c433f4c 100644
--- a/code/modules/mob/living/carbon/human/human_movement.dm
+++ b/code/modules/mob/living/carbon/human/human_movement.dm
@@ -48,6 +48,8 @@
FP.blood_state = S.blood_state
FP.entered_dirs |= dir
FP.bloodiness = S.bloody_shoes[S.blood_state]
+ if(S.blood_DNA && S.blood_DNA.len)
+ FP.transfer_blood_dna(S.blood_DNA)
FP.update_icon()
update_inv_shoes()
//End bloody footprints
diff --git a/code/modules/mob/living/carbon/human/species.dm b/code/modules/mob/living/carbon/human/species.dm
index 70450bd83ec..390fe71f69b 100644
--- a/code/modules/mob/living/carbon/human/species.dm
+++ b/code/modules/mob/living/carbon/human/species.dm
@@ -137,8 +137,6 @@
C.unEquip(thing)
if(NODISMEMBER in specflags)
C.regenerate_limbs() //if we don't handle dismemberment, we grow our missing limbs back
- if(exotic_blood)
- C.reagents.add_reagent(exotic_blood, 80)
var/obj/item/organ/heart/heart = C.getorganslot("heart")
var/obj/item/organ/lungs/lungs = C.getorganslot("lungs")
@@ -733,6 +731,10 @@
return
/datum/species/proc/handle_chemicals(datum/reagent/chem, mob/living/carbon/human/H)
+ if(chem.id == exotic_blood)
+ H.blood_volume = min(H.blood_volume + round(chem.volume, 0.1), BLOOD_VOLUME_MAXIMUM)
+ H.reagents.remove_reagent(chem.id)
+ return 1
return 0
/datum/species/proc/handle_speech(message, mob/living/carbon/human/H)
@@ -1104,34 +1106,20 @@
//dismemberment
if(prob(I.get_dismemberment_chance(affecting)))
if(affecting.dismember(I.damtype))
- I.add_blood(H)
+ I.add_mob_blood(H)
playsound(get_turf(H), I.get_dismember_sound(), 80, 1)
var/bloody = 0
if(((I.damtype == BRUTE) && I.force && prob(25 + (I.force * 2))))
if(affecting.status == ORGAN_ORGANIC)
- I.add_blood(H) //Make the weapon bloody, not the person.
+ I.add_mob_blood(H) //Make the weapon bloody, not the person.
if(prob(I.force * 2)) //blood spatter!
bloody = 1
var/turf/location = H.loc
- if(istype(location, /turf))
- location.add_blood(H)
- if(ishuman(user))
- var/mob/living/carbon/human/M = user
- if(get_dist(M, H) <= 1) //people with TK won't get smeared with blood
- if(M.wear_suit)
- M.wear_suit.add_blood(H)
- M.update_inv_wear_suit() //updates mob overlays to show the new blood (no refresh)
- else if(M.w_uniform)
- M.w_uniform.add_blood(H)
- M.update_inv_w_uniform() //updates mob overlays to show the new blood (no refresh)
- if (M.gloves)
- var/obj/item/clothing/gloves/G = M.gloves
- G.add_blood(H)
- else
- M.add_blood(H)
- M.update_inv_gloves() //updates on-mob overlays for bloody hands and/or bloody gloves
-
+ if(istype(location))
+ H.add_splatter_floor(location)
+ if(get_dist(user, H) <= 1) //people with TK won't get smeared with blood
+ user.add_mob_blood(H)
switch(hit_area)
if("head") //Harder to score a stun but if you do it lasts a bit longer
@@ -1145,13 +1133,13 @@
if(bloody) //Apply blood
if(H.wear_mask)
- H.wear_mask.add_blood(H)
+ H.wear_mask.add_mob_blood(H)
H.update_inv_wear_mask()
if(H.head)
- H.head.add_blood(H)
+ H.head.add_mob_blood(H)
H.update_inv_head()
if(H.glasses && prob(33))
- H.glasses.add_blood(H)
+ H.glasses.add_mob_blood(H)
H.update_inv_glasses()
if("chest") //Easier to score a stun but lasts less time
@@ -1162,10 +1150,10 @@
if(bloody)
if(H.wear_suit)
- H.wear_suit.add_blood(H)
+ H.wear_suit.add_mob_blood(H)
H.update_inv_wear_suit()
if(H.w_uniform)
- H.w_uniform.add_blood(H)
+ H.w_uniform.add_mob_blood(H)
H.update_inv_w_uniform()
if(Iforce > 10 || Iforce >= 5 && prob(33))
diff --git a/code/modules/mob/living/carbon/human/species_types.dm b/code/modules/mob/living/carbon/human/species_types.dm
index 3eeb393cdb6..cb8d6a881ba 100644
--- a/code/modules/mob/living/carbon/human/species_types.dm
+++ b/code/modules/mob/living/carbon/human/species_types.dm
@@ -75,6 +75,13 @@
return randname
+/datum/species/lizard/on_species_gain(mob/living/carbon/C)
+ if(C.dna.blood_type != "L")
+ C.dna.blood_type = "L"
+
+/datum/species/lizard/on_species_loss(mob/living/carbon/C)
+ C.dna.blood_type = random_blood_type()
+
//I wag in death
/datum/species/lizard/spec_death(gibbed, mob/living/carbon/human/H)
if(H)
@@ -194,27 +201,21 @@
/datum/species/jelly/spec_life(mob/living/carbon/human/H)
if(H.stat == DEAD) //can't farm slime jelly from a dead slime/jelly person indefinitely
return
- if(!H.reagents.get_reagent_amount(exotic_blood))
- H.reagents.add_reagent(exotic_blood, 5)
+ if(!H.blood_volume)
+ H.blood_volume += 5
H.adjustBruteLoss(5)
H << "You feel empty!"
- var/jelly_amount = H.reagents.get_reagent_amount(exotic_blood)
-
- if(jelly_amount < 100)
+ if(H.blood_volume < BLOOD_VOLUME_NORMAL)
if(H.nutrition >= NUTRITION_LEVEL_STARVING)
- H.reagents.add_reagent(exotic_blood, 0.5)
+ H.blood_volume += 3
H.nutrition -= 2.5
- if(jelly_amount < 50)
+ if(H.blood_volume < BLOOD_VOLUME_OKAY)
if(prob(5))
H << "You feel drained!"
- if(jelly_amount < 10)
+ if(H.blood_volume < BLOOD_VOLUME_BAD)
H.losebreath++
-/datum/species/jelly/handle_chemicals(datum/reagent/chem, mob/living/carbon/human/H)
- if(chem.id == exotic_blood)
- return 1
-
/*
SLIMEPEOPLE
*/
@@ -245,6 +246,7 @@
callforward.Remove(C)
if(callback)
callback.Remove(C)
+ C.blood_volume = min(C.blood_volume, BLOOD_VOLUME_NORMAL)
..()
/datum/species/jelly/slime/on_species_gain(mob/living/carbon/C)
@@ -254,12 +256,11 @@
slime_split.Grant(C)
/datum/species/jelly/slime/spec_life(mob/living/carbon/human/H)
- var/jelly_amount = H.reagents.get_reagent_amount(exotic_blood)
- if(jelly_amount >= 200)
+ if(H.blood_volume >= BLOOD_VOLUME_SLIME_SPLIT)
if(prob(5))
H << "You feel very bloated!"
else if(H.nutrition >= NUTRITION_LEVEL_WELL_FED)
- H.reagents.add_reagent(exotic_blood, 0.5)
+ H.blood_volume += 3
H.nutrition -= 2.5
..()
@@ -274,29 +275,28 @@
var/mob/living/carbon/human/H = owner
H << "You focus intently on moving your body while standing perfectly still..."
H.notransform = 1
- for(var/datum/reagent/toxin/slimejelly/S in H.reagents.reagent_list)
- if(S.volume >= 200)
- var/mob/living/carbon/human/spare = new /mob/living/carbon/human(H.loc)
- spare.underwear = "Nude"
- H.dna.transfer_identity(spare, transfer_SE=1)
- H.dna.features["mcolor"] = pick("FFFFFF","7F7F7F", "7FFF7F", "7F7FFF", "FF7F7F", "7FFFFF", "FF7FFF", "FFFF7F")
- spare.real_name = spare.dna.real_name
- spare.name = spare.dna.real_name
- spare.updateappearance(mutcolor_update=1)
- spare.domutcheck()
- spare.Move(get_step(H.loc, pick(NORTH,SOUTH,EAST,WEST)))
- S.volume = 80
- H.notransform = 0
- var/datum/species/jelly/slime/SS = H.dna.species
- SS.callforward = new
- SS.callforward.body = spare
- SS.callforward.Grant(H)
- SS.callback = new
- SS.callback.body = H
- SS.callback.Grant(spare)
- H.mind.transfer_to(spare)
- spare << "...and after a moment of disorentation, you're besides yourself!"
- return
+ if(H.blood_volume >= BLOOD_VOLUME_SLIME_SPLIT)
+ var/mob/living/carbon/human/spare = new /mob/living/carbon/human(H.loc)
+ spare.underwear = "Nude"
+ H.dna.transfer_identity(spare, transfer_SE=1)
+ H.dna.features["mcolor"] = pick("FFFFFF","7F7F7F", "7FFF7F", "7F7FFF", "FF7F7F", "7FFFFF", "FF7FFF", "FFFF7F")
+ spare.real_name = spare.dna.real_name
+ spare.name = spare.dna.real_name
+ spare.updateappearance(mutcolor_update=1)
+ spare.domutcheck()
+ spare.Move(get_step(H.loc, pick(NORTH,SOUTH,EAST,WEST)))
+ H.blood_volume = BLOOD_VOLUME_SAFE
+ H.notransform = 0
+ var/datum/species/jelly/slime/SS = H.dna.species
+ SS.callforward = new
+ SS.callforward.body = spare
+ SS.callforward.Grant(H)
+ SS.callback = new
+ SS.callback.body = H
+ SS.callback.Grant(spare)
+ H.mind.transfer_to(spare)
+ spare << "...and after a moment of disorentation, you're besides yourself!"
+ return
H << "...but there is not enough of you to go around! You must attain more mass to split!"
H.notransform = 0
diff --git a/code/modules/mob/living/carbon/life.dm b/code/modules/mob/living/carbon/life.dm
index c055c89375a..aaaf5cc8086 100644
--- a/code/modules/mob/living/carbon/life.dm
+++ b/code/modules/mob/living/carbon/life.dm
@@ -14,6 +14,8 @@
if(..())
. = 1
+ handle_blood()
+
for(var/obj/item/organ/O in internal_organs)
O.on_life()
@@ -212,6 +214,9 @@
update_internals_hud_icon(1)
return internal.remove_air_volume(volume_needed)
+/mob/living/carbon/proc/handle_blood()
+ return
+
/mob/living/carbon/proc/handle_changeling()
if(mind && hud_used && hud_used.lingchemdisplay)
if(mind.changeling)
diff --git a/code/modules/mob/living/life.dm b/code/modules/mob/living/life.dm
index 7584716e394..7bd479db031 100644
--- a/code/modules/mob/living/life.dm
+++ b/code/modules/mob/living/life.dm
@@ -22,9 +22,6 @@
//Chemicals in the body
handle_chemicals_in_body()
- //Blud
- handle_blood()
-
//Random events (vomiting etc)
handle_random_events()
@@ -69,9 +66,6 @@
AI.client.images |= src.digitaldisguise
-/mob/living/proc/handle_blood()
- return
-
/mob/living/proc/handle_random_events()
return
diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm
index 97cbc6c99e9..1ba8be20c72 100644
--- a/code/modules/mob/living/living.dm
+++ b/code/modules/mob/living/living.dm
@@ -499,6 +499,7 @@ Sorry Giacom. Please don't be mad :(
//proc used to completely heal a mob.
/mob/living/proc/fully_heal(admin_revive = 0)
+ restore_blood()
setToxLoss(0, 0)
setOxyLoss(0, 0)
setCloneLoss(0, 0)
@@ -572,8 +573,8 @@ Sorry Giacom. Please don't be mad :(
if(get_dist(src, pulling) > 1 || ((pull_dir - 1) & pull_dir)) //puller and pullee more than one tile away or in diagonal position
if(isliving(pulling))
var/mob/living/M = pulling
- if(M.lying && !M.buckled && (prob(M.getBruteLoss() / 2)))
- makeTrail(T, M)
+ if(M.lying && !M.buckled && (prob(M.getBruteLoss()*200/M.maxHealth)))
+ M.makeTrail(T)
pulling.Move(T, get_dir(pulling, T)) //the pullee tries to reach our previous position
if(pulling && get_dist(src, pulling) > 1) //the pullee couldn't keep up
stop_pulling()
@@ -598,39 +599,46 @@ Sorry Giacom. Please don't be mad :(
if("walk")
. += config.walk_speed
-/mob/living/proc/makeTrail(turf/T, mob/living/M)
- if(!has_gravity(M))
+/mob/living/proc/makeTrail(turf/T)
+ if(!has_gravity(src))
return
- if(ishuman(M))
- var/mob/living/carbon/human/H = M
- if((NOBLOOD in H.dna.species.specflags) || (!H.blood_max) || (H.bleedsuppress))
- return
var/blood_exists = 0
- var/trail_type = M.getTrail()
- for(var/obj/effect/decal/cleanable/trail_holder/C in M.loc) //checks for blood splatter already on the floor
- blood_exists = 1
- if (istype(M.loc, /turf) && trail_type != null)
- var/newdir = get_dir(T, M.loc)
- if(newdir != M.dir)
- newdir = newdir | M.dir
- if(newdir == 3) //N + S
- newdir = NORTH
- else if(newdir == 12) //E + W
- newdir = EAST
- if((newdir in list(1, 2, 4, 8)) && (prob(50)))
- newdir = turn(get_dir(T, M.loc), 180)
- if(!blood_exists)
- new /obj/effect/decal/cleanable/trail_holder(M.loc)
- for(var/obj/effect/decal/cleanable/trail_holder/H in M.loc)
- if((!(newdir in H.existing_dirs) || trail_type == "trails_1" || trail_type == "trails_2") && H.existing_dirs.len <= 16) //maximum amount of overlays is 16 (all light & heavy directions filled)
- H.existing_dirs += newdir
- H.overlays.Add(image('icons/effects/blood.dmi',trail_type,dir = newdir))
- if(M.has_dna()) //blood DNA
- var/mob/living/carbon/DNA_helper = M
- H.blood_DNA[DNA_helper.dna.unique_enzymes] = DNA_helper.dna.blood_type
-/mob/living/proc/getTrail() //silicon and simple_animals don't get blood trails
- return null
+ for(var/obj/effect/decal/cleanable/trail_holder/C in src.loc) //checks for blood splatter already on the floor
+ blood_exists = 1
+ if (isturf(src.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.
+ var/newdir = get_dir(T, src.loc)
+ if(newdir != src.dir)
+ newdir = newdir | src.dir
+ if(newdir == 3) //N + S
+ newdir = NORTH
+ else if(newdir == 12) //E + W
+ newdir = EAST
+ if((newdir in cardinal) && (prob(50)))
+ newdir = turn(get_dir(T, src.loc), 180)
+ if(!blood_exists)
+ new /obj/effect/decal/cleanable/trail_holder(src.loc)
+ for(var/obj/effect/decal/cleanable/trail_holder/TH in src.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)
+
+/mob/living/carbon/human/makeTrail(turf/T)
+ if((NOBLOOD in dna.species.specflags) || !bleed_rate || bleedsuppress)
+ return
+ ..()
+
+/mob/living/proc/getTrail()
+ if(getBruteLoss() < 300)
+ return pick("ltrails_1", "ltrails_2")
+ else
+ return pick("trails_1", "trails_2")
/mob/living/verb/resist()
set name = "Resist"
diff --git a/code/modules/mob/living/living_defines.dm b/code/modules/mob/living/living_defines.dm
index 400503818f9..2a338caa35e 100644
--- a/code/modules/mob/living/living_defines.dm
+++ b/code/modules/mob/living/living_defines.dm
@@ -68,3 +68,5 @@
var/mob/living/mental_dominator //The person controlling the mind of this person, if applicable
var/mob/living/mind_control_holder/mind_control_holder //If the mob is being mind controlled, where their old mind is stored (check clock_mobs.dm)
+
+ var/blood_volume = 0 //how much blood the mob has
\ No newline at end of file
diff --git a/code/modules/mob/living/simple_animal/bot/mulebot.dm b/code/modules/mob/living/simple_animal/bot/mulebot.dm
index ce5d311e7bf..857f93b8a63 100644
--- a/code/modules/mob/living/simple_animal/bot/mulebot.dm
+++ b/code/modules/mob/living/simple_animal/bot/mulebot.dm
@@ -662,9 +662,8 @@ var/global/mulebot_count = 0
H.apply_damage(0.5*damage, BRUTE, "l_arm", run_armor_check("l_arm", "melee"))
H.apply_damage(0.5*damage, BRUTE, "r_arm", run_armor_check("r_arm", "melee"))
- var/obj/effect/decal/cleanable/blood/B = new(loc)
- B.add_blood_list(H)
- add_blood_list(H)
+ var/turf/T = get_turf(src)
+ T.add_mob_blood(H)
bloodiness += 4
// player on mulebot attempted to move
diff --git a/code/modules/mob/living/simple_animal/friendly/farm_animals.dm b/code/modules/mob/living/simple_animal/friendly/farm_animals.dm
index 94dd02f7501..67a0d63fdac 100644
--- a/code/modules/mob/living/simple_animal/friendly/farm_animals.dm
+++ b/code/modules/mob/living/simple_animal/friendly/farm_animals.dm
@@ -26,6 +26,7 @@
melee_damage_upper = 2
environment_smash = 0
stop_automated_movement_when_pulled = 1
+ blood_volume = BLOOD_VOLUME_NORMAL
var/obj/item/udder/udder = null
/mob/living/simple_animal/hostile/retaliate/goat/New()
@@ -102,6 +103,7 @@
maxHealth = 50
var/obj/item/udder/udder = null
gold_core_spawnable = 2
+ blood_volume = BLOOD_VOLUME_NORMAL
/mob/living/simple_animal/cow/New()
udder = new()
diff --git a/code/modules/mob/living/simple_animal/friendly/pet.dm b/code/modules/mob/living/simple_animal/friendly/pet.dm
index dd6bbd56bc5..587900add16 100644
--- a/code/modules/mob/living/simple_animal/friendly/pet.dm
+++ b/code/modules/mob/living/simple_animal/friendly/pet.dm
@@ -4,6 +4,7 @@
var/obj/item/clothing/tie/petcollar/pcollar = null
var/image/collar = null
var/image/pettag = null
+ blood_volume = BLOOD_VOLUME_NORMAL
/mob/living/simple_animal/pet/attackby(obj/item/O, mob/user, params)
if(istype(O, /obj/item/clothing/tie/petcollar) && !pcollar)
diff --git a/code/modules/mob/living/simple_animal/hostile/mining_mobs.dm b/code/modules/mob/living/simple_animal/hostile/mining_mobs.dm
index ba2db3344ed..6e25b296f1c 100644
--- a/code/modules/mob/living/simple_animal/hostile/mining_mobs.dm
+++ b/code/modules/mob/living/simple_animal/hostile/mining_mobs.dm
@@ -288,10 +288,8 @@
if(NOBLOOD in H.dna.species.specflags)
return
- var/datum/reagent/blood/B = locate() in H.vessel.reagent_list
- var/blood_volume = round(H.vessel.get_reagent_amount("blood"))
- if(B && blood_volume < 560 && blood_volume)
- B.volume += 2 // Fast blood regen
+ if(H.blood_volume && H.blood_volume < BLOOD_VOLUME_NORMAL)
+ H.blood_volume += 2 // Fast blood regen
/obj/item/organ/hivelord_core/afterattack(atom/target, mob/user, proximity_flag)
if(proximity_flag && ishuman(target))
@@ -398,7 +396,7 @@
transfer_reagents(C)
death()
-/mob/living/simple_animal/hostile/asteroid/hivelordbrood/blood/proc/transfer_reagents(mob/living/carbon/C, var/volume = 30)
+/mob/living/simple_animal/hostile/asteroid/hivelordbrood/blood/proc/transfer_reagents(mob/living/carbon/C, volume = 30)
if(!reagents.total_volume)
return
@@ -406,29 +404,11 @@
var/fraction = min(volume/reagents.total_volume, 1)
reagents.reaction(C, INJECT, fraction)
-
- var/datum/reagent/blood/B
- for(var/datum/reagent/blood/d in reagents.reagent_list)
- B = d
- break
- if(B)
- C.inject_blood(src, min(B.volume, volume))
-
reagents.trans_to(C, volume)
/mob/living/simple_animal/hostile/asteroid/hivelordbrood/blood/proc/link_host(mob/living/carbon/C)
faction = list("\ref[src]", "\ref[C]") // Hostile to everyone except the host.
- var/datum/reagent/B = C.take_blood(src, 30)
- if(!B)
- if(ishuman(C))
- var/mob/living/carbon/human/H = C
- if(H.dna.species.exotic_blood && H.reagents.total_volume)
- H.reagents.trans_to(src, 10)
-
- else
- reagents.reagent_list += B
- reagents.update_total()
-
+ C.transfer_blood_to(src, 30)
color = mix_color_from_reagents(reagents.reagent_list)
/mob/living/simple_animal/hostile/asteroid/goliath
diff --git a/code/modules/mob/living/simple_animal/simple_animal.dm b/code/modules/mob/living/simple_animal/simple_animal.dm
index d8fd2af810f..04814cbd2bb 100644
--- a/code/modules/mob/living/simple_animal/simple_animal.dm
+++ b/code/modules/mob/living/simple_animal/simple_animal.dm
@@ -411,6 +411,7 @@
icon_state = icon_dead
stat = DEAD
density = 0
+ lying = 1
..()
/mob/living/simple_animal/ex_act(severity, target)
@@ -457,6 +458,7 @@
icon = initial(icon)
icon_state = icon_living
density = initial(density)
+ lying = 0
. = 1
/mob/living/simple_animal/fully_heal(admin_revive = 0)
diff --git a/code/modules/mob/living/simple_animal/slime/slime.dm b/code/modules/mob/living/simple_animal/slime/slime.dm
index 22178caa4bf..d5e9c1916ab 100644
--- a/code/modules/mob/living/simple_animal/slime/slime.dm
+++ b/code/modules/mob/living/simple_animal/slime/slime.dm
@@ -335,9 +335,6 @@ var/list/slime_colours = list("rainbow", "grey", "purple", "metal", "orange",
++Discipline
return
-/mob/living/simple_animal/slime/getTrail()
- return null
-
/mob/living/simple_animal/slime/examine(mob/user)
var/msg = "*---------*\nThis is \icon[src] \a [src]!\n"
diff --git a/code/modules/paperwork/contract.dm b/code/modules/paperwork/contract.dm
index 43a8e5fce22..b7a09fcf5a1 100644
--- a/code/modules/paperwork/contract.dm
+++ b/code/modules/paperwork/contract.dm
@@ -145,9 +145,7 @@
add_fingerprint(user)
if(M == user && target == M.mind && M.mind.soulOwner == M.mind && attempt_signature(user))
user.visible_message("[user] slices their wrist with [src], and scrawls their name in blood.", "You slice your wrist open and scrawl your name in blood.")
- if(istype(user, /mob/living/carbon/human))
- var/mob/living/carbon/human/H = user
- H.vessel.remove_reagent("blood",10)
+ user.blood_volume = max(user.blood_volume - 10, 0)
else
return ..()
diff --git a/code/modules/projectiles/guns/projectile/saw.dm b/code/modules/projectiles/guns/projectile/saw.dm
index ebc79dfd8ad..a1a3231135e 100644
--- a/code/modules/projectiles/guns/projectile/saw.dm
+++ b/code/modules/projectiles/guns/projectile/saw.dm
@@ -77,9 +77,9 @@
/obj/item/projectile/bullet/saw/bleeding/on_hit(atom/target, blocked = 0, hit_zone)
. = ..()
- if((blocked != 100) && istype(target, /mob/living/carbon/human))
- var/mob/living/carbon/human/H = target
- H.drip(35)
+ if((blocked != 100) && iscarbon(target))
+ var/mob/living/carbon/C = target
+ C.bleed(35)
/obj/item/projectile/bullet/saw/hollow
damage = 60
diff --git a/code/modules/projectiles/guns/projectile/sniper.dm b/code/modules/projectiles/guns/projectile/sniper.dm
index 3cb65acd8ed..555dbe4df73 100644
--- a/code/modules/projectiles/guns/projectile/sniper.dm
+++ b/code/modules/projectiles/guns/projectile/sniper.dm
@@ -127,9 +127,9 @@
breakthings = FALSE
/obj/item/projectile/bullet/sniper/haemorrhage/on_hit(atom/target, blocked = 0, hit_zone)
- if((blocked != 100) && istype(target, /mob/living/carbon/human))
- var/mob/living/carbon/human/H = target
- H.drip(100)
+ if((blocked != 100) && iscarbon(target))
+ var/mob/living/carbon/C = target
+ C.bleed(100)
return ..()
diff --git a/code/modules/reagents/chemistry/holder.dm b/code/modules/reagents/chemistry/holder.dm
index c27f060df24..1b5ad721edf 100644
--- a/code/modules/reagents/chemistry/holder.dm
+++ b/code/modules/reagents/chemistry/holder.dm
@@ -142,10 +142,6 @@ var/const/INJECT = 5 //injection
var/trans_data = null
for(var/reagent in reagent_list)
var/datum/reagent/T = reagent
- if(T.id == "blood" && ishuman(target))
- var/mob/living/carbon/human/H = target
- H.inject_blood(my_atom, amount)
- continue
var/transfer_amount = T.volume * part
if(preserve_data)
trans_data = copy_data(T)
diff --git a/code/modules/reagents/chemistry/reagents/food_reagents.dm b/code/modules/reagents/chemistry/reagents/food_reagents.dm
index c9e1e5c4897..dc8126d6f42 100644
--- a/code/modules/reagents/chemistry/reagents/food_reagents.dm
+++ b/code/modules/reagents/chemistry/reagents/food_reagents.dm
@@ -29,6 +29,10 @@
if(prob(50))
M.heal_organ_damage(1,0, 0)
. = 1
+ if(iscarbon(M))
+ var/mob/living/carbon/C = M
+ if(C.blood_volume < BLOOD_VOLUME_NORMAL)
+ C.blood_volume += 0.4
..()
/datum/reagent/consumable/vitamin
@@ -44,6 +48,10 @@
. = 1
if(M.satiety < 600)
M.satiety += 30
+ if(iscarbon(M))
+ var/mob/living/carbon/C = M
+ if(C.blood_volume < BLOOD_VOLUME_NORMAL)
+ C.blood_volume += 0.5
..()
/datum/reagent/consumable/sugar
diff --git a/code/modules/reagents/chemistry/reagents/medicine_reagents.dm b/code/modules/reagents/chemistry/reagents/medicine_reagents.dm
index b7bc550d64a..54e4340d690 100644
--- a/code/modules/reagents/chemistry/reagents/medicine_reagents.dm
+++ b/code/modules/reagents/chemistry/reagents/medicine_reagents.dm
@@ -272,13 +272,13 @@
..()
/datum/reagent/medicine/salglu_solution/reaction_mob(mob/living/M, method=TOUCH, reac_volume, show_message = 1)
- if(iscarbon(M) && method == INJECT)
+ if(ishuman(M) && method == INJECT)
var/mob/living/carbon/human/H = M
- //The lower the blood of the patient, the better it is as a blood substitute.
- var/efficiency = (560-H.vessel.get_reagent_amount("blood"))/700 + 0.2
- efficiency = min(0.75,efficiency)
- //As it's designed for an IV drip, make large injections not as effective as repeated small injections.
- H.vessel.add_reagent("blood", efficiency * min(5,reac_volume))
+ if(H.dna && !(NOBLOOD in H.dna.species.specflags))
+ var/efficiency = (BLOOD_VOLUME_NORMAL-H.blood_volume)/700 + 0.2//The lower the blood of the patient, the better it is as a blood substitute.
+ efficiency = min(0.75,efficiency)
+ //As it's designed for an IV drip, make large injections not as effective as repeated small injections.
+ H.blood_volume += round(efficiency * min(5,reac_volume), 0.1)
..()
/datum/reagent/medicine/mine_salve
diff --git a/code/modules/reagents/chemistry/reagents/other_reagents.dm b/code/modules/reagents/chemistry/reagents/other_reagents.dm
index eaf4e1c8c68..2daca1f733a 100644
--- a/code/modules/reagents/chemistry/reagents/other_reagents.dm
+++ b/code/modules/reagents/chemistry/reagents/other_reagents.dm
@@ -1,15 +1,16 @@
/datum/reagent/blood
- data = list("donor"=null,"viruses"=null,"blood_DNA"=null,"blood_type"=null,"resistances"=null,"trace_chem"=null,"mind"=null,"ckey"=null,"gender"=null,"real_name"=null,"cloneable"=null,"factions"=null)
- name = "Blood"
- id = "blood"
- color = "#C80000" // rgb: 200, 0, 0
+ data = list("donor"=null,"viruses"=null,"blood_DNA"=null,"blood_type"=null,"resistances"=null,"trace_chem"=null,"mind"=null,"ckey"=null,"gender"=null,"real_name"=null,"cloneable"=null,"factions"=null)
+ name = "Blood"
+ id = "blood"
+ color = "#C80000" // rgb: 200, 0, 0
+ metabolization_rate = 5 //fast rate so it disappears fast.
/datum/reagent/blood/reaction_mob(mob/M, method=TOUCH, reac_volume)
if(data && data["viruses"])
for(var/datum/disease/D in data["viruses"])
- if(D.spread_flags & SPECIAL || D.spread_flags & NON_CONTAGIOUS)
+ if((D.spread_flags & SPECIAL) || (D.spread_flags & NON_CONTAGIOUS))
continue
if(method == TOUCH || method == VAPOR)
@@ -17,6 +18,15 @@
else //ingest, patch or inject
M.ForceContractDisease(D)
+ if(method == INJECT && iscarbon(M))
+ var/mob/living/carbon/C = M
+ if(C.get_blood_id() == "blood")
+ if(!data || !(data["blood_type"] in get_safe_blood(C.dna.blood_type)))
+ C.reagents.add_reagent("toxin", reac_volume * 0.5)
+ else
+ C.blood_volume = min(C.blood_volume + round(reac_volume, 0.1), BLOOD_VOLUME_MAXIMUM)
+
+
/datum/reagent/blood/on_new(list/data)
if(istype(data))
SetViruses(src, data)
@@ -51,38 +61,18 @@
return
if(reac_volume < 3)
return
- if(!data["donor"] || istype(data["donor"], /mob/living/carbon/human))
- var/obj/effect/decal/cleanable/blood/blood_prop = locate() in T //find some blood here
- if(!blood_prop) //first blood!
- blood_prop = new(T)
- blood_prop.blood_DNA[data["blood_DNA"]] = data["blood_type"]
- for(var/datum/disease/D in data["viruses"])
- var/datum/disease/newVirus = D.Copy(1)
- blood_prop.viruses += newVirus
- newVirus.holder = blood_prop
+ var/obj/effect/decal/cleanable/blood/B = locate() in T //find some blood here
+ if(!B)
+ B = new(T)
+ if(data["blood_DNA"])
+ B.blood_DNA[data["blood_DNA"]] = data["blood_type"]
+ for(var/datum/disease/D in data["viruses"])
+ var/datum/disease/newVirus = D.Copy(1)
+ B.viruses += newVirus
+ newVirus.holder = B
- else if(istype(data["donor"], /mob/living/carbon/monkey))
- var/obj/effect/decal/cleanable/blood/blood_prop = locate() in T
- if(!blood_prop)
- blood_prop = new(T)
- blood_prop.blood_DNA["Non-Human DNA"] = "A+"
- for(var/datum/disease/D in data["viruses"])
- var/datum/disease/newVirus = D.Copy(1)
- blood_prop.viruses += newVirus
- newVirus.holder = blood_prop
-
- else if(istype(data["donor"], /mob/living/carbon/alien))
- var/obj/effect/decal/cleanable/xenoblood/blood_prop = locate() in T
- if(!blood_prop)
- blood_prop = new(T)
- blood_prop.blood_DNA["UNKNOWN DNA STRUCTURE"] = "X*"
- for(var/datum/disease/D in data["viruses"])
- var/datum/disease/newVirus = D.Copy(1)
- blood_prop.viruses += newVirus
- newVirus.holder = blood_prop
- return
/datum/reagent/liquidgibs
name = "Liquid gibs"
@@ -634,6 +624,13 @@
color = "#C8A5DC" // rgb: 200, 165, 220
+/datum/reagent/iron/on_mob_life(mob/living/M)
+ if(iscarbon(M))
+ var/mob/living/carbon/C = M
+ if(C.blood_volume < BLOOD_VOLUME_NORMAL)
+ C.blood_volume += 0.5
+ ..()
+
/datum/reagent/iron/reaction_mob(mob/living/M, method=TOUCH, reac_volume)
if(!istype(M, /mob/living))
return
diff --git a/code/modules/reagents/chemistry/reagents/toxin_reagents.dm b/code/modules/reagents/chemistry/reagents/toxin_reagents.dm
index 8d3c4dd2b89..8da685439b5 100644
--- a/code/modules/reagents/chemistry/reagents/toxin_reagents.dm
+++ b/code/modules/reagents/chemistry/reagents/toxin_reagents.dm
@@ -649,7 +649,7 @@
/datum/reagent/toxin/heparin/on_mob_life(mob/living/M)
if(ishuman(M))
var/mob/living/carbon/human/H = M
- H.blood_max += 2
+ H.bleed_rate = min(H.bleed_rate + 2, 8)
H.adjustBruteLoss(1, 0) //Brute damage increases with the amount they're bleeding
. = 1
return ..() || .
diff --git a/code/modules/reagents/reagent_containers/blood_pack.dm b/code/modules/reagents/reagent_containers/blood_pack.dm
index 353b3276e18..3894e80b6b5 100644
--- a/code/modules/reagents/reagent_containers/blood_pack.dm
+++ b/code/modules/reagents/reagent_containers/blood_pack.dm
@@ -4,19 +4,35 @@
icon = 'icons/obj/bloodpack.dmi'
icon_state = "empty"
volume = 200
-
var/blood_type = null
+ var/labelled = 0
/obj/item/weapon/reagent_containers/blood/New()
..()
if(blood_type != null)
- name = "blood pack [blood_type]"
reagents.add_reagent("blood", 200, list("donor"=null,"viruses"=null,"blood_DNA"=null,"blood_type"=blood_type,"resistances"=null,"trace_chem"=null))
update_icon()
/obj/item/weapon/reagent_containers/blood/on_reagent_change()
+ if(reagents)
+ var/datum/reagent/blood/B = reagents.has_reagent("blood")
+ if(B && B.data && B.data["blood_type"])
+ blood_type = B.data["blood_type"]
+ else
+ blood_type = null
+ update_pack_name()
update_icon()
+/obj/item/weapon/reagent_containers/blood/proc/update_pack_name()
+ if(!labelled)
+ if(volume)
+ if(blood_type)
+ name = "blood pack [blood_type]"
+ else
+ name = "blood pack"
+ else
+ name = "empty blood pack"
+
/obj/item/weapon/reagent_containers/blood/update_icon()
var/percent = round((reagents.total_volume / volume) * 100)
switch(percent)
@@ -49,9 +65,11 @@
/obj/item/weapon/reagent_containers/blood/OMinus
blood_type = "O-"
+/obj/item/weapon/reagent_containers/blood/lizard
+ blood_type = "L"
+
/obj/item/weapon/reagent_containers/blood/empty
name = "empty blood pack"
- desc = "Seems pretty useless... Maybe if there were a way to fill it?"
icon_state = "empty"
/obj/item/weapon/reagent_containers/blood/attackby(obj/item/I, mob/user, params)
@@ -62,10 +80,13 @@
return
if(user.get_active_hand() != I)
return
- if(!in_range(src, user) && loc != user)
+ if(loc != user)
return
if(t)
+ labelled = 1
name = "blood pack - [t]"
else
- name = "blood pack"
- return
+ labelled = 0
+ update_pack_name()
+ else
+ return ..()
diff --git a/code/modules/reagents/reagent_containers/syringes.dm b/code/modules/reagents/reagent_containers/syringes.dm
index 68bc332d528..de1b92ca252 100644
--- a/code/modules/reagents/reagent_containers/syringes.dm
+++ b/code/modules/reagents/reagent_containers/syringes.dm
@@ -46,15 +46,18 @@
/obj/item/weapon/reagent_containers/syringe/attackby(obj/item/I, mob/user, params)
return
-/obj/item/weapon/reagent_containers/syringe/afterattack(obj/target, mob/user , proximity)
+/obj/item/weapon/reagent_containers/syringe/afterattack(atom/target, mob/user , proximity)
if(busy)
return
- if(!proximity) return
- if(!target.reagents) return
+ if(!proximity)
+ return
+ if(!target.reagents)
+ return
+ var/mob/living/L
if(isliving(target))
- var/mob/living/M = target
- if(!M.can_inject(user, 1))
+ L = target
+ if(!L.can_inject(user, 1))
return
switch(mode)
@@ -64,45 +67,22 @@
user << "The syringe is full."
return
- if(ismob(target)) //Blood!
- if(ishuman(target))
- var/mob/living/carbon/human/H = target
- if((NOBLOOD in H.dna.species.specflags) && !H.dna.species.exotic_blood)
- user << "You are unable to locate any blood!"
+ if(L) //living mob
+ var/drawn_amount = reagents.maximum_volume - reagents.total_volume
+ if(target != user)
+ target.visible_message("[user] is trying to take a blood sample from [target]!", \
+ "[user] is trying to take a blood sample from [target]!")
+ busy = 1
+ if(!do_mob(user, target))
+ busy = 0
return
- if(reagents.has_reagent("blood"))
- user << "There is already a blood sample in this syringe!"
- return
- if(istype(target, /mob/living/carbon)) //maybe just add a blood reagent to all mobs. Then you can suck them dry...With hundreds of syringes. Jolly good idea.
- var/amount = src.reagents.maximum_volume - src.reagents.total_volume
- var/mob/living/carbon/T = target
- if(!T.has_dna() || (T.disabilities & NOCLONE)) //target done been eat, no more blood in him
- user << "You are unable to locate any blood!"
+ if(reagents.total_volume >= reagents.maximum_volume)
return
- if(target != user)
- target.visible_message("[user] is trying to take a blood sample from [target]!", \
- "[user] is trying to take a blood sample from [target]!")
- busy = 1
- if(!do_mob(user, target))
- busy = 0
- return
- busy = 0
- var/datum/reagent/B
- B = T.take_blood(src,amount)
-
- if(!B && ishuman(target))
- var/mob/living/carbon/human/H = target
- if(H.dna.species.exotic_blood && H.reagents.total_volume)
- target.reagents.trans_to(src, amount)
- else
- user << "You are unable to locate any blood!"
- return
- if (B)
- src.reagents.reagent_list += B
- src.reagents.update_total()
- src.on_reagent_change()
- src.reagents.handle_reactions()
- user.visible_message("[user] takes a blood sample from [target].")
+ busy = 0
+ if(L.transfer_blood_to(src, drawn_amount))
+ user.visible_message("[user] takes a blood sample from [L].")
+ else
+ user << "You are unable to draw any blood from [L]!"
else //if not mob
if(!target.reagents.total_volume)
@@ -132,53 +112,38 @@
user << "[target] is full."
return
- if(ismob(target) && target != user)
- target.visible_message("[user] is trying to inject [target]!", \
- "[user] is trying to inject [target]!")
- if(!do_mob(user, target))
- return
- //Sanity checks after sleep
- if(!reagents.total_volume)
- return
- if(target.reagents.total_volume >= target.reagents.maximum_volume)
- return
+ if(L) //living mob
+ if(L != user)
+ L.visible_message("[user] is trying to inject [L]!", \
+ "[user] is trying to inject [L]!")
+ if(!do_mob(user, L))
+ return
+ if(!reagents.total_volume)
+ return
+ if(L.reagents.total_volume >= L.reagents.maximum_volume)
+ return
+
+ L.visible_message("[user] injects [L] with the syringe!", \
+ "[user] injects [L] with the syringe!")
- target.visible_message("[user] injects [target] with the syringe!", \
- "[user] injects [target] with the syringe!")
- //Attack log entries are produced here due to failure to produce elsewhere. Remove them here if you have doubles from normal syringes.
var/list/rinject = list()
- for(var/datum/reagent/R in src.reagents.reagent_list)
+ for(var/datum/reagent/R in reagents.reagent_list)
rinject += R.name
var/contained = english_list(rinject)
- var/mob/M = target
- add_logs(user, M, "injected", src, addition="which had [contained]")
- var/fraction = min(amount_per_transfer_from_this/reagents.total_volume, 1)
- reagents.reaction(target, INJECT, fraction)
- if(ismob(target) && target == user)
- //Attack log entries are produced here due to failure to produce elsewhere. Remove them here if you have doubles from normal syringes.
- var/list/rinject = list()
- for(var/datum/reagent/R in src.reagents.reagent_list)
- rinject += R.name
- var/contained = english_list(rinject)
- var/mob/M = target
- log_attack("[user.name] ([user.ckey]) injected [M.name] ([M.ckey]) with [src.name], which had [contained] (INTENT: [uppertext(user.a_intent)])")
- M.attack_log += text("\[[time_stamp()]\] Injected themselves ([contained]) with [src.name].")
- var/fraction = min(amount_per_transfer_from_this/reagents.total_volume, 1)
- reagents.reaction(target, INJECT, fraction)
- spawn(5)
- var/datum/reagent/blood/B
- for(var/datum/reagent/blood/d in src.reagents.reagent_list)
- B = d
- break
- if(B && istype(target,/mob/living/carbon))
- var/mob/living/carbon/C = target
- C.inject_blood(src,5)
+
+ if(L != user)
+ add_logs(user, L, "injected", src, addition="which had [contained]")
else
- src.reagents.trans_to(target, amount_per_transfer_from_this)
- user << "You inject [amount_per_transfer_from_this] units of the solution. The syringe now contains [src.reagents.total_volume] units."
- if (reagents.total_volume <= 0 && mode==SYRINGE_INJECT)
- mode = SYRINGE_DRAW
- update_icon()
+ log_attack("[user.name] ([user.ckey]) injected [L.name] ([L.ckey]) with [src.name], which had [contained] (INTENT: [uppertext(user.a_intent)])")
+ L.attack_log += "\[[time_stamp()]\] Injected themselves ([contained]) with [src.name]."
+
+ var/fraction = min(amount_per_transfer_from_this/reagents.total_volume, 1)
+ reagents.reaction(L, INJECT, fraction)
+ reagents.trans_to(target, amount_per_transfer_from_this)
+ user << "You inject [amount_per_transfer_from_this] units of the solution. The syringe now contains [reagents.total_volume] units."
+ if (reagents.total_volume <= 0 && mode==SYRINGE_INJECT)
+ mode = SYRINGE_DRAW
+ update_icon()
/obj/item/weapon/reagent_containers/syringe/update_icon()
diff --git a/code/modules/surgery/bodyparts/dismemberment.dm b/code/modules/surgery/bodyparts/dismemberment.dm
index 0316b3899ff..b100ed0f386 100644
--- a/code/modules/surgery/bodyparts/dismemberment.dm
+++ b/code/modules/surgery/bodyparts/dismemberment.dm
@@ -17,10 +17,10 @@
if(dam_type == BURN)
burn()
return 1
- add_blood(H)
+ add_mob_blood(H)
var/turf/location = H.loc
if(istype(location))
- location.add_blood(H)
+ H.add_splatter_floor(location)
var/direction = pick(cardinal)
var/t_range = rand(2,max(throw_range/2, 2))
var/turf/target_turf = get_turf(src)
@@ -40,7 +40,7 @@
var/organ_spilled = 0
var/turf/T = get_turf(H)
- T.add_blood(H)
+ H.add_splatter_floor(T)
playsound(get_turf(owner), 'sound/misc/splort.ogg', 80, 1)
for(var/X in owner.internal_organs)
var/obj/item/organ/O = X
diff --git a/code/modules/surgery/organs/organ_internal.dm b/code/modules/surgery/organs/organ_internal.dm
index 1b47c0172f6..47e3615388d 100644
--- a/code/modules/surgery/organs/organ_internal.dm
+++ b/code/modules/surgery/organs/organ_internal.dm
@@ -193,11 +193,12 @@
if(world.time > (last_pump + pump_delay))
if(ishuman(owner) && owner.client) //While this entire item exists to make people suffer, they can't control disconnects.
var/mob/living/carbon/human/H = owner
- H.vessel.remove_reagent("blood",blood_loss)
- H << "You have to keep pumping your blood!"
- if(add_colour)
- H.add_client_colour(/datum/client_colour/cursed_heart_blood) //bloody screen so real
- add_colour = FALSE
+ if(H.dna && !(NOBLOOD in H.dna.species.specflags))
+ H.blood_volume = max(H.blood_volume - blood_loss, 0)
+ H << "You have to keep pumping your blood!"
+ if(add_colour)
+ H.add_client_colour(/datum/client_colour/cursed_heart_blood) //bloody screen so real
+ add_colour = FALSE
else
last_pump = world.time //lets be extra fair *sigh*
@@ -225,12 +226,13 @@
var/mob/living/carbon/human/H = owner
if(istype(H))
- H.vessel.add_reagent("blood",(cursed_heart.blood_loss*0.5))//gain half the blood back from a failure
- H.remove_client_colour(/datum/client_colour/cursed_heart_blood)
- cursed_heart.add_colour = TRUE
- H.adjustBruteLoss(-cursed_heart.heal_brute)
- H.adjustFireLoss(-cursed_heart.heal_burn)
- H.adjustOxyLoss(-cursed_heart.heal_oxy)
+ if(H.dna && !(NOBLOOD in H.dna.species.specflags))
+ H.blood_volume = min(H.blood_volume + cursed_heart.blood_loss*0.5, BLOOD_VOLUME_MAXIMUM)
+ H.remove_client_colour(/datum/client_colour/cursed_heart_blood)
+ cursed_heart.add_colour = TRUE
+ H.adjustBruteLoss(-cursed_heart.heal_brute)
+ H.adjustFireLoss(-cursed_heart.heal_burn)
+ H.adjustOxyLoss(-cursed_heart.heal_oxy)
/datum/client_colour/cursed_heart_blood
diff --git a/tgstation.dme b/tgstation.dme
index 9f147302728..2a20872de2a 100644
--- a/tgstation.dme
+++ b/tgstation.dme
@@ -1252,6 +1252,7 @@
#include "code\modules\mob\dead\observer\logout.dm"
#include "code\modules\mob\dead\observer\observer.dm"
#include "code\modules\mob\dead\observer\say.dm"
+#include "code\modules\mob\living\blood.dm"
#include "code\modules\mob\living\bloodcrawl.dm"
#include "code\modules\mob\living\damage_procs.dm"
#include "code\modules\mob\living\death.dm"
@@ -1317,7 +1318,6 @@
#include "code\modules\mob\living\carbon\brain\posibrain.dm"
#include "code\modules\mob\living\carbon\brain\say.dm"
#include "code\modules\mob\living\carbon\brain\status_procs.dm"
-#include "code\modules\mob\living\carbon\human\blood.dm"
#include "code\modules\mob\living\carbon\human\death.dm"
#include "code\modules\mob\living\carbon\human\emote.dm"
#include "code\modules\mob\living\carbon\human\examine.dm"