|
|
|
@@ -1,87 +1,42 @@
|
|
|
|
|
/****************************************************
|
|
|
|
|
BLOOD SYSTEM
|
|
|
|
|
****************************************************/
|
|
|
|
|
|
|
|
|
|
/mob/living/carbon/human/var/datum/reagents/vessel //Container for blood and BLOOD ONLY. Do not transfer other chems here.
|
|
|
|
|
|
|
|
|
|
//Initializes blood vessels
|
|
|
|
|
/mob/living/carbon/human/proc/make_blood()
|
|
|
|
|
|
|
|
|
|
if(vessel)
|
|
|
|
|
/mob/living/carbon/human/proc/suppress_bloodloss(amount)
|
|
|
|
|
if(bleedsuppress)
|
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
vessel = new/datum/reagents(max_blood)
|
|
|
|
|
vessel.my_atom = src
|
|
|
|
|
|
|
|
|
|
if(species && species.exotic_blood)
|
|
|
|
|
vessel.add_reagent(species.exotic_blood, max_blood)
|
|
|
|
|
else
|
|
|
|
|
vessel.add_reagent("blood", max_blood)
|
|
|
|
|
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_colour" = species.blood_color,
|
|
|
|
|
"blood_type" = b_type,
|
|
|
|
|
"resistances" = null,
|
|
|
|
|
"trace_chem" = null)
|
|
|
|
|
spawn(1)
|
|
|
|
|
fixblood()
|
|
|
|
|
bleedsuppress = 1
|
|
|
|
|
spawn(amount)
|
|
|
|
|
bleedsuppress = 0
|
|
|
|
|
if(stat != DEAD && bleed_rate)
|
|
|
|
|
to_chat(src, "<span class='warning'>The blood soaks through your bandage.</span>")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//Resets blood data
|
|
|
|
|
/mob/living/carbon/human/proc/fixblood()
|
|
|
|
|
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_colour" = species.blood_color,
|
|
|
|
|
"blood_type" = b_type,
|
|
|
|
|
"resistances" = null,
|
|
|
|
|
"trace_chem" = null)
|
|
|
|
|
|
|
|
|
|
// Takes care blood loss and regeneration
|
|
|
|
|
/mob/living/carbon/human/proc/handle_blood()
|
|
|
|
|
var/blood_volume
|
|
|
|
|
if(species && species.flags & NO_BLOOD)
|
|
|
|
|
/mob/living/carbon/human/handle_blood()
|
|
|
|
|
var/list/blood_data = get_blood_data(get_blood_id())//PROCCEPTION
|
|
|
|
|
|
|
|
|
|
if(in_stasis)
|
|
|
|
|
return
|
|
|
|
|
if(stat != DEAD && bodytemperature >= 170) //Dead or cryosleep people do not pump the blood.
|
|
|
|
|
if(species.exotic_blood)
|
|
|
|
|
var/blood_reagent = species.exotic_blood // This is a string of the name of the species' blood reagent
|
|
|
|
|
blood_volume = round(vessel.get_reagent_amount(blood_reagent))
|
|
|
|
|
if(blood_volume < max_blood && blood_volume)
|
|
|
|
|
vessel.add_reagent(blood_reagent, 0.1) // regenerate blood VERY slowly
|
|
|
|
|
if(reagents.has_reagent(blood_reagent))
|
|
|
|
|
vessel.add_reagent(blood_reagent, 0.4)
|
|
|
|
|
|
|
|
|
|
else
|
|
|
|
|
blood_volume = round(vessel.get_reagent_amount("blood"))
|
|
|
|
|
//Blood regeneration if there is some space
|
|
|
|
|
if(blood_volume < max_blood && blood_volume)
|
|
|
|
|
var/datum/reagent/blood/B = locate() in vessel.reagent_list //Grab some blood
|
|
|
|
|
if(B) // Make sure there's some blood at all
|
|
|
|
|
if(mind) //Handles vampires "eating" blood that isn't their own.
|
|
|
|
|
if(mind in ticker.mode.vampires)
|
|
|
|
|
for(var/datum/reagent/blood/BL in vessel.reagent_list)
|
|
|
|
|
if(nutrition >= NUTRITION_LEVEL_WELL_FED)
|
|
|
|
|
break //We don't want blood tranfusions making vampires fat.
|
|
|
|
|
if(BL.data["donor"] != src)
|
|
|
|
|
nutrition += (15 * REAGENTS_METABOLISM)
|
|
|
|
|
BL.volume -= REAGENTS_METABOLISM
|
|
|
|
|
if(BL.volume <= 0)
|
|
|
|
|
qdel(BL)
|
|
|
|
|
break //Only process one blood per tick, to maintain the same metabolism as nutriment for non-vampires.
|
|
|
|
|
if(species && species.flags & NO_BLOOD)
|
|
|
|
|
bleed_rate = 0
|
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
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
|
|
|
|
|
if(bodytemperature >= 225 && !(NOCLONE in mutations)) //cryosleep or husked people do not pump the blood.
|
|
|
|
|
|
|
|
|
|
vessel.add_reagent("blood", 0.1) // regenerate blood VERY slowly
|
|
|
|
|
//Blood regeneration if there is some space
|
|
|
|
|
if(blood_volume < max_blood && blood_volume)
|
|
|
|
|
if(mind) //Handles vampires "eating" blood that isn't their own.
|
|
|
|
|
if(mind in ticker.mode.vampires)
|
|
|
|
|
if(nutrition >= NUTRITION_LEVEL_WELL_FED)
|
|
|
|
|
return //We don't want blood tranfusions making vampires fat.
|
|
|
|
|
if(blood_data["donor"] != src)
|
|
|
|
|
nutrition += (15 * REAGENTS_METABOLISM)
|
|
|
|
|
return //Only process one blood per tick, to maintain the same metabolism as nutriment for non-vampires.
|
|
|
|
|
if(blood_volume < BLOOD_VOLUME_NORMAL)
|
|
|
|
|
blood_volume += 0.1 // regenerate blood VERY slowly
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//Effects of bloodloss
|
|
|
|
@@ -102,6 +57,7 @@
|
|
|
|
|
adjustOxyLoss(round((BLOOD_VOLUME_NORMAL - blood_volume) * 0.02, 1))
|
|
|
|
|
if(prob(5))
|
|
|
|
|
EyeBlurry(6)
|
|
|
|
|
|
|
|
|
|
var/word = pick("dizzy","woozy","faint")
|
|
|
|
|
to_chat(src, "<span class='warning'>You feel very [word].</span>")
|
|
|
|
|
if(BLOOD_VOLUME_SURVIVE to BLOOD_VOLUME_BAD)
|
|
|
|
@@ -117,265 +73,217 @@
|
|
|
|
|
death()
|
|
|
|
|
|
|
|
|
|
//Bleeding out
|
|
|
|
|
var/blood_max = 0
|
|
|
|
|
var/temp_bleed = 0
|
|
|
|
|
for(var/obj/item/organ/external/temp in bodyparts)
|
|
|
|
|
if(!(temp.status & ORGAN_BLEEDING) || temp.status & ORGAN_ROBOT)
|
|
|
|
|
continue
|
|
|
|
|
for(var/datum/wound/W in temp.wounds)
|
|
|
|
|
if(W.bleeding())
|
|
|
|
|
blood_max += W.damage / 4
|
|
|
|
|
temp_bleed += W.damage / 4
|
|
|
|
|
if(temp.open)
|
|
|
|
|
blood_max += 2 //Yer stomach is cut open
|
|
|
|
|
drip(blood_max)
|
|
|
|
|
temp_bleed += 0.5
|
|
|
|
|
|
|
|
|
|
//Makes a blood drop, leaking certain amount of blood from the mob
|
|
|
|
|
/mob/living/carbon/human/proc/drip(var/amt as num)
|
|
|
|
|
bleed_rate = max(bleed_rate - 0.5, temp_bleed)//if no wounds, other bleed effects (heparin) naturally decreases
|
|
|
|
|
|
|
|
|
|
if(species && species.flags & NO_BLOOD) //TODO: Make drips come from the reagents instead.
|
|
|
|
|
return
|
|
|
|
|
if(bleed_rate && !bleedsuppress)
|
|
|
|
|
bleed(bleed_rate)
|
|
|
|
|
|
|
|
|
|
if(!amt)
|
|
|
|
|
return
|
|
|
|
|
//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(loc)) //Blood loss still happens in locker, floor stays clean
|
|
|
|
|
if(amt >= 10)
|
|
|
|
|
add_splatter_floor(loc)
|
|
|
|
|
else
|
|
|
|
|
add_splatter_floor(loc, 1)
|
|
|
|
|
|
|
|
|
|
var/amm = 0.1 * amt
|
|
|
|
|
var/turf/T = get_turf(src)
|
|
|
|
|
/mob/living/carbon/human/bleed(amt)
|
|
|
|
|
if(!(species && species.flags & NO_BLOOD))
|
|
|
|
|
..()
|
|
|
|
|
if(species.exotic_blood)
|
|
|
|
|
var/datum/reagent/R = chemical_reagents_list[get_blood_id()]
|
|
|
|
|
if(istype(R) && isturf(loc))
|
|
|
|
|
R.reaction_turf(get_turf(src), amt)
|
|
|
|
|
|
|
|
|
|
if(species.exotic_blood)
|
|
|
|
|
vessel.remove_reagent(species.exotic_blood,amm)
|
|
|
|
|
if(vessel.total_volume)
|
|
|
|
|
var/fraction = amm / vessel.total_volume
|
|
|
|
|
vessel.reaction(T, TOUCH, fraction)
|
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
else
|
|
|
|
|
vessel.remove_reagent("blood",amm)
|
|
|
|
|
blood_splatter(src, src)
|
|
|
|
|
/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 the container, preserving all data in it.
|
|
|
|
|
/mob/living/carbon/proc/take_blood(obj/item/weapon/reagent_containers/container, var/amount)
|
|
|
|
|
var/datum/reagent/B = get_blood(container.reagents)
|
|
|
|
|
if(!istype(B, /datum/reagent/blood)) B = new /datum/reagent/blood
|
|
|
|
|
B.holder = container
|
|
|
|
|
B.volume += amount
|
|
|
|
|
//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
|
|
|
|
|
|
|
|
|
|
//set reagent data
|
|
|
|
|
B.data["donor"] = src
|
|
|
|
|
B.data["viruses"] = list()
|
|
|
|
|
if(blood_volume < amount)
|
|
|
|
|
amount = blood_volume
|
|
|
|
|
|
|
|
|
|
for(var/thing in viruses)
|
|
|
|
|
var/datum/disease/D = thing
|
|
|
|
|
B.data["viruses"] += D.Copy()
|
|
|
|
|
if(resistances && resistances.len)
|
|
|
|
|
B.data["resistances"] = resistances.Copy()
|
|
|
|
|
var/blood_id = get_blood_id()
|
|
|
|
|
if(!blood_id)
|
|
|
|
|
return 0
|
|
|
|
|
|
|
|
|
|
B.data["blood_DNA"] = copytext(src.dna.unique_enzymes,1,0)
|
|
|
|
|
B.data["blood_type"] = copytext(src.dna.b_type,1,0)
|
|
|
|
|
blood_volume -= amount
|
|
|
|
|
|
|
|
|
|
// Putting this here due to return shenanigans.
|
|
|
|
|
if(istype(src,/mob/living/carbon/human))
|
|
|
|
|
var/mob/living/carbon/human/H = src
|
|
|
|
|
B.data["blood_colour"] = H.species.blood_color
|
|
|
|
|
B.color = B.data["blood_colour"]
|
|
|
|
|
var/list/blood_data = get_blood_data(blood_id)
|
|
|
|
|
|
|
|
|
|
var/list/temp_chem = list()
|
|
|
|
|
for(var/datum/reagent/R in src.reagents.reagent_list)
|
|
|
|
|
temp_chem += R.id
|
|
|
|
|
temp_chem[R.id] = R.volume
|
|
|
|
|
B.data["trace_chem"] = list2params(temp_chem)
|
|
|
|
|
if(mind)
|
|
|
|
|
B.data["mind"] = mind
|
|
|
|
|
if(ckey)
|
|
|
|
|
B.data["ckey"] = ckey
|
|
|
|
|
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/thing in blood_data["viruses"])
|
|
|
|
|
var/datum/disease/D = thing
|
|
|
|
|
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.b_type)))
|
|
|
|
|
C.reagents.add_reagent("toxin", amount * 0.5)
|
|
|
|
|
return 1
|
|
|
|
|
|
|
|
|
|
if(!suiciding)
|
|
|
|
|
B.data["cloneable"] = 1
|
|
|
|
|
B.data["gender"] = gender
|
|
|
|
|
B.data["real_name"] = real_name
|
|
|
|
|
B.data["factions"] = faction
|
|
|
|
|
return B
|
|
|
|
|
C.blood_volume = min(C.blood_volume + round(amount, 0.1), BLOOD_VOLUME_MAXIMUM)
|
|
|
|
|
return 1
|
|
|
|
|
|
|
|
|
|
//For humans, blood does not appear from blue, it comes from vessels.
|
|
|
|
|
/mob/living/carbon/human/take_blood(obj/item/weapon/reagent_containers/container, var/amount)
|
|
|
|
|
if(src.species.exotic_blood)
|
|
|
|
|
if(vessel.get_reagent_amount(src.species.exotic_blood) < amount)
|
|
|
|
|
return null
|
|
|
|
|
var/datum/reagent/W = new /datum/reagent
|
|
|
|
|
W.holder = container
|
|
|
|
|
W.volume += amount
|
|
|
|
|
AM.reagents.add_reagent(blood_id, amount, blood_data, bodytemperature)
|
|
|
|
|
return 1
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/mob/living/proc/get_blood_data(blood_id)
|
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
/mob/living/carbon/human/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/thing in viruses)
|
|
|
|
|
var/datum/disease/D = thing
|
|
|
|
|
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 src.reagents.reagent_list)
|
|
|
|
|
temp_chem += R.id
|
|
|
|
|
for(var/datum/reagent/R in reagents.reagent_list)
|
|
|
|
|
temp_chem[R.id] = R.volume
|
|
|
|
|
W.data["trace_chem"] = list2params(temp_chem)
|
|
|
|
|
vessel.remove_reagent(src.species.exotic_blood,amount) // Removes blood if human
|
|
|
|
|
return W
|
|
|
|
|
if(species && species.flags & NO_BLOOD)
|
|
|
|
|
return null
|
|
|
|
|
else
|
|
|
|
|
if(vessel.get_reagent_amount("blood") < amount)
|
|
|
|
|
return null
|
|
|
|
|
. = ..()
|
|
|
|
|
vessel.remove_reagent("blood",amount) // Removes blood if human
|
|
|
|
|
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(src.dna.b_type,1,0)
|
|
|
|
|
blood_data["gender"] = gender
|
|
|
|
|
blood_data["real_name"] = real_name
|
|
|
|
|
blood_data["blood_color"] = species.blood_color
|
|
|
|
|
blood_data["factions"] = faction
|
|
|
|
|
return blood_data
|
|
|
|
|
|
|
|
|
|
//Transfers blood from container ot vessels
|
|
|
|
|
/mob/living/carbon/proc/inject_blood(obj/item/weapon/reagent_containers/container, var/amount)
|
|
|
|
|
var/datum/reagent/blood/injected = get_blood(container.reagents)
|
|
|
|
|
//get the id of the substance this mob use as blood.
|
|
|
|
|
/mob/proc/get_blood_id()
|
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
if(!istype(injected))
|
|
|
|
|
/mob/living/simple_animal/get_blood_id()
|
|
|
|
|
if(blood_volume)
|
|
|
|
|
return "blood"
|
|
|
|
|
|
|
|
|
|
/mob/living/carbon/human/get_blood_id()
|
|
|
|
|
if(species.exotic_blood)//some races may bleed water..or kethcup..
|
|
|
|
|
return species.exotic_blood
|
|
|
|
|
else if((species && species.flags & NO_BLOOD) || (NOCLONE in mutations))
|
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
var/list/chems = list()
|
|
|
|
|
chems = params2list(injected.data["trace_chem"])
|
|
|
|
|
for(var/C in chems)
|
|
|
|
|
src.reagents.add_reagent(C, (text2num(chems[C]) / BLOOD_VOLUME_NORMAL) * amount)//adds trace chemicals to owner's blood
|
|
|
|
|
reagents.update_total()
|
|
|
|
|
|
|
|
|
|
container.reagents.remove_reagent("blood", amount)
|
|
|
|
|
|
|
|
|
|
//Transfers blood from container ot vessels, respecting blood types compatability.
|
|
|
|
|
/mob/living/carbon/human/inject_blood(obj/item/weapon/reagent_containers/container, var/amount)
|
|
|
|
|
|
|
|
|
|
var/datum/reagent/blood/injected = get_blood(container.reagents)
|
|
|
|
|
|
|
|
|
|
if(!istype(injected)) //Sanity..
|
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
if(species && species.flags & NO_BLOOD)
|
|
|
|
|
reagents.add_reagent("blood", amount, injected.data)
|
|
|
|
|
reagents.update_total()
|
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
var/datum/reagent/blood/our = get_blood(vessel)
|
|
|
|
|
|
|
|
|
|
if(!istype(our)) // Do we not have blood?
|
|
|
|
|
vessel.add_reagent("blood", amount, injected.data) // This is only ran once, so we need to add back their DNA.
|
|
|
|
|
vessel.update_total()
|
|
|
|
|
..()
|
|
|
|
|
our = get_blood(vessel) // Get the new blood.
|
|
|
|
|
our.data["blood_DNA"] = dna.unique_enzymes // Give it the proper DNA we had before (src.dna)
|
|
|
|
|
our.data["blood_type"] = dna.b_type // Proper blood type.
|
|
|
|
|
our.data["donor"] = src // Without this, it'd be random each time it was extracted or Null.
|
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
if(blood_incompatible(injected.data["blood_type"],our.data["blood_type"]) )
|
|
|
|
|
reagents.add_reagent("toxin",amount * 0.5)
|
|
|
|
|
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
|
|
|
|
|
|
|
|
|
|
/mob/living/carbon/human/get_blood(datum/reagents/container)
|
|
|
|
|
if(species.exotic_blood)
|
|
|
|
|
return container.get_reagent_from_id(species.exotic_blood)
|
|
|
|
|
else
|
|
|
|
|
return ..()
|
|
|
|
|
|
|
|
|
|
/mob/living/carbon/proc/get_blood_name()
|
|
|
|
|
return "blood"
|
|
|
|
|
|
|
|
|
|
/mob/living/carbon/human/get_blood_name()
|
|
|
|
|
if(species.exotic_blood)
|
|
|
|
|
return species.exotic_blood
|
|
|
|
|
else
|
|
|
|
|
return ..()
|
|
|
|
|
// 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_incompatible(donor,receiver)
|
|
|
|
|
//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")//is it blood or welding fuel?
|
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
var/donor_antigen = copytext(donor,1,lentext(donor))
|
|
|
|
|
var/receiver_antigen = copytext(receiver,1,lentext(receiver))
|
|
|
|
|
var/donor_rh = findtext("+",donor)
|
|
|
|
|
var/receiver_rh = findtext("+",receiver)
|
|
|
|
|
if(!T)
|
|
|
|
|
T = get_turf(src)
|
|
|
|
|
|
|
|
|
|
if(donor_rh && !receiver_rh) return 1
|
|
|
|
|
switch(receiver_antigen)
|
|
|
|
|
if("A")
|
|
|
|
|
if(donor_antigen != "A" && donor_antigen != "O") return 1
|
|
|
|
|
if("B")
|
|
|
|
|
if(donor_antigen != "B" && donor_antigen != "O") return 1
|
|
|
|
|
if("O")
|
|
|
|
|
if(donor_antigen != "O") return 1
|
|
|
|
|
//AB is a universal receiver.
|
|
|
|
|
return 0
|
|
|
|
|
var/list/temp_blood_DNA
|
|
|
|
|
var/list/b_data = get_blood_data(get_blood_id())
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
Target: Thing/tile to get bloody
|
|
|
|
|
Source: Human or blood reagent
|
|
|
|
|
Large: Whether the splat should be big or not
|
|
|
|
|
*/
|
|
|
|
|
/proc/blood_splatter(var/target,var/source,var/large = 0)
|
|
|
|
|
|
|
|
|
|
var/obj/effect/decal/cleanable/blood/B
|
|
|
|
|
var/decal_type = /obj/effect/decal/cleanable/blood/splatter
|
|
|
|
|
var/turf/T = get_turf(target)
|
|
|
|
|
var/datum/reagent/blood/bld
|
|
|
|
|
if(istype(source,/mob/living/carbon/human))
|
|
|
|
|
var/mob/living/carbon/human/H = source
|
|
|
|
|
bld = H.get_blood(H.vessel)
|
|
|
|
|
if(H.species.exotic_blood)
|
|
|
|
|
H.vessel.reaction(T, TOUCH)
|
|
|
|
|
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)
|
|
|
|
|
drop.basecolor = b_data["blood_color"]
|
|
|
|
|
drop.update_icon()
|
|
|
|
|
else
|
|
|
|
|
temp_blood_DNA = list()
|
|
|
|
|
temp_blood_DNA |= drop.blood_DNA.Copy() //we transfer the dna from the drip to the splatter
|
|
|
|
|
qdel(drop)
|
|
|
|
|
else
|
|
|
|
|
drop = new(T)
|
|
|
|
|
drop.transfer_mob_blood_dna(src)
|
|
|
|
|
drop.basecolor = b_data["blood_color"]
|
|
|
|
|
drop.update_icon()
|
|
|
|
|
return
|
|
|
|
|
else if(H.species.flags & NO_BLOOD)
|
|
|
|
|
return
|
|
|
|
|
else if(istype(source, /datum/reagent))
|
|
|
|
|
bld = source
|
|
|
|
|
if(!istype(bld, /datum/reagent/blood))
|
|
|
|
|
var/datum/reagent/R = bld
|
|
|
|
|
if(istype(R))
|
|
|
|
|
R.reaction_turf(T, R.volume)
|
|
|
|
|
return
|
|
|
|
|
else if(source)
|
|
|
|
|
log_runtime(EXCEPTION("Non-human or reagent blood source. Area: [get_area(source)], Name: [source]"), source)
|
|
|
|
|
|
|
|
|
|
// 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
|
|
|
|
|
var/obj/effect/decal/cleanable/blood/B = locate() in T
|
|
|
|
|
if(!B)
|
|
|
|
|
B = new decal_type(T)
|
|
|
|
|
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
|
|
|
|
|
B.update_icon()
|
|
|
|
|
|
|
|
|
|
var/obj/effect/decal/cleanable/blood/drip/drop = B
|
|
|
|
|
if(istype(drop) && drips && drips.len && !large)
|
|
|
|
|
drop.overlays |= drips
|
|
|
|
|
drop.drips |= drips
|
|
|
|
|
/mob/living/carbon/human/add_splatter_floor(turf/T, small_drip)
|
|
|
|
|
if(!(species && species.flags & NO_BLOOD))
|
|
|
|
|
..()
|
|
|
|
|
|
|
|
|
|
// If there's no data to copy, call it quits here.
|
|
|
|
|
if(!bld)
|
|
|
|
|
return B
|
|
|
|
|
/mob/living/carbon/alien/add_splatter_floor(turf/T, small_drip)
|
|
|
|
|
if(!T)
|
|
|
|
|
T = get_turf(src)
|
|
|
|
|
var/obj/effect/decal/cleanable/blood/xeno/B = locate() in T.contents
|
|
|
|
|
if(!B)
|
|
|
|
|
B = new(T)
|
|
|
|
|
B.blood_DNA["UNKNOWN DNA"] = "X*"
|
|
|
|
|
|
|
|
|
|
// Update appearance.
|
|
|
|
|
if(bld.data["blood_colour"])
|
|
|
|
|
B.basecolor = bld.data["blood_colour"]
|
|
|
|
|
B.update_icon()
|
|
|
|
|
|
|
|
|
|
// Update blood information.
|
|
|
|
|
if(bld.data["blood_DNA"])
|
|
|
|
|
B.blood_DNA = list()
|
|
|
|
|
if(bld.data["blood_type"])
|
|
|
|
|
B.blood_DNA[bld.data["blood_DNA"]] = bld.data["blood_type"]
|
|
|
|
|
else
|
|
|
|
|
B.blood_DNA[bld.data["blood_DNA"]] = "O+"
|
|
|
|
|
|
|
|
|
|
return B
|
|
|
|
|
/mob/living/silicon/robot/add_splatter_floor(turf/T, small_drip)
|
|
|
|
|
if(!T)
|
|
|
|
|
T = get_turf(src)
|
|
|
|
|
var/obj/effect/decal/cleanable/blood/oil/B = locate() in T.contents
|
|
|
|
|
if(!B)
|
|
|
|
|
B = new(T)
|