Files
Polaris/code/modules/organs/blood.dm
Arokha Sieyes 34d323e57f The Terminator Update
This updates synthetic limbs to make more sense. It tweaks what you can 'see' when examining people. If someone has a robotic leg but is wearing pants, how would you know that? If someone has a burn on their arm, but their jumpsuit sleeves down, how would you know that? If someone has a replacement Vey-Med arm, how would you know it's robotic? It also treats examining FBPs more 'realistically'. If they are covered except for their head, it doesn't matter if their whole body is Bishop robotic. If their head is Vey-Med and that's all you can see, they just look human to you.

So FBP manufacturers can have a 'lifelike' var set. Vey-Med has this. This makes the limbs not show obviously non-organic damage (dents) until they are more damaged and start showing wires/metal. Attempts to treat these limbs with medical stuff results in a different message. Manufacturers can also set individual blood colors. Vey-Med blood is now white, ala Bishop from Aliens.

isSynthetic proc = Is the mob actually synthetic, as in, mechanically for breathing/tox purposes?
looksSynthetic proc = Does the mob display outward signs of being synthetic? Based on head and torso and what's revealed.

Other fixes:
You can no longer attach limbs to non-existent parents. You can't give somone a foot on a leg that doesn't exist.
You can't attach fleshy limbs to robotic ones. BODIES DO NOT WORK THAT WAY.
'Synthetic' var on humans points to manufacturer if you need to grab it quickly. isSynthetic returns this as well.
Robolimb count (and thus overheating speed) updates whenever your limbs change.
Lifelike FBPs do not show a 'system offline glyph'.
isSynthetic and looksSynthetic moved to human_helpers becasue they were defined on human in mob_helpers
Nanopaste correctly repairs limbs using the new procs (both burn and brute, making it an expensive welder+wire)
2016-05-29 02:37:13 -04:00

320 lines
10 KiB
Plaintext

/****************************************************
BLOOD SYSTEM
****************************************************/
//Blood levels. These are percentages based on the species blood_volume far.
var/const/BLOOD_VOLUME_SAFE = 85
var/const/BLOOD_VOLUME_OKAY = 75
var/const/BLOOD_VOLUME_BAD = 60
var/const/BLOOD_VOLUME_SURVIVE = 40
/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/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(species.blood_volume)
vessel.my_atom = src
if(!should_have_organ(O_HEART)) //We want the var for safety but we can do without the actual blood.
return
vessel.add_reagent("blood",species.blood_volume)
spawn(1)
fixblood()
//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,"species"=species.name,"blood_DNA"=dna.unique_enzymes,"blood_colour"= species.get_blood_colour(src),"blood_type"=dna.b_type, \
"resistances"=null,"trace_chem"=null, "virus2" = null, "antibodies" = list())
B.color = B.data["blood_colour"]
// Takes care blood loss and regeneration
/mob/living/carbon/human/handle_blood()
if(in_stasis)
return
if(!should_have_organ(O_HEART))
return
if(stat != DEAD && bodytemperature >= 170) //Dead or cryosleep people do not pump the blood.
var/blood_volume_raw = vessel.get_reagent_amount("blood")
var/blood_volume = round((blood_volume_raw/species.blood_volume)*100) // Percentage.
//Blood regeneration if there is some space
if(blood_volume_raw < species.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(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(CE_BLOODRESTORE in chem_effects)
B.volume += chem_effects[CE_BLOODRESTORE]
// Damaged heart virtually reduces the blood volume, as the blood isn't
// being pumped properly anymore.
if(species && should_have_organ(O_HEART))
var/obj/item/organ/internal/heart/heart = internal_organs_by_name[O_HEART]
if(!heart)
blood_volume = 0
else if(heart.damage > 1 && heart.damage < heart.min_bruised_damage)
blood_volume *= 0.8
else if(heart.damage >= heart.min_bruised_damage && heart.damage < heart.min_broken_damage)
blood_volume *= 0.6
else if(heart.damage >= heart.min_broken_damage && heart.damage < INFINITY)
blood_volume *= 0.3
//Effects of bloodloss
if(blood_volume >= BLOOD_VOLUME_SAFE)
if(pale)
pale = 0
update_body()
else if(blood_volume >= BLOOD_VOLUME_OKAY)
if(!pale)
pale = 1
update_body()
var/word = pick("dizzy","woosey","faint")
src << "\red You feel [word]"
if(prob(1))
var/word = pick("dizzy","woosey","faint")
src << "\red You feel [word]"
if(oxyloss < 20)
oxyloss += 3
else if(blood_volume >= BLOOD_VOLUME_BAD)
if(!pale)
pale = 1
update_body()
eye_blurry = max(eye_blurry,6)
if(oxyloss < 50)
oxyloss += 10
oxyloss += 1
if(prob(15))
Paralyse(rand(1,3))
var/word = pick("dizzy","woosey","faint")
src << "\red You feel extremely [word]"
else if(blood_volume >= BLOOD_VOLUME_SURVIVE)
oxyloss += 5
toxloss += 3
if(prob(15))
var/word = pick("dizzy","woosey","faint")
src << "\red You feel extremely [word]"
else
// There currently is a strange bug here. If the mob is not below -100 health
// when death() is called, apparently they will be just fine, and this way it'll
// spam deathgasp. Adjusting toxloss ensures the mob will stay dead.
toxloss += 300 // just to be safe!
death()
// Without enough blood you slowly go hungry.
if(blood_volume < BLOOD_VOLUME_SAFE)
if(nutrition >= 300)
nutrition -= 10
else if(nutrition >= 200)
nutrition -= 3
//Bleeding out
var/blood_max = 0
for(var/obj/item/organ/external/temp in organs)
if(!(temp.status & ORGAN_BLEEDING) || (temp.robotic >= ORGAN_ROBOT))
continue
for(var/datum/wound/W in temp.wounds) if(W.bleeding())
blood_max += W.damage / 40
if (temp.open)
blood_max += 2 //Yer stomach is cut open
drip(blood_max)
//Makes a blood drop, leaking amt units of blood from the mob
/mob/living/carbon/human/proc/drip(var/amt as num)
if(!should_have_organ(O_HEART)) //TODO: Make drips come from the reagents instead.
return
if(!amt)
return
vessel.remove_reagent("blood",amt)
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, var/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
if (!B.data["virus2"])
B.data["virus2"] = list()
B.data["virus2"] |= virus_copylist(src.virus2)
B.data["antibodies"] = src.antibodies
B.data["blood_DNA"] = copytext(src.dna.unique_enzymes,1,0)
B.data["blood_type"] = copytext(src.dna.b_type,1,0)
// 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.get_blood_colour(H)
B.color = B.data["blood_colour"]
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)
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, var/amount)
if(!should_have_organ(O_HEART))
return null
if(vessel.get_reagent_amount("blood") < amount)
return null
. = ..()
vessel.remove_reagent("blood",amount) // Removes blood if human
//Transfers blood from container ot vessels
/mob/living/carbon/proc/inject_blood(var/datum/reagent/blood/injected, var/amount)
if (!injected || !istype(injected))
return
var/list/sniffles = virus_copylist(injected.data["virus2"])
for(var/ID in sniffles)
var/datum/disease2/disease/sniffle = sniffles[ID]
infect_virus2(src,sniffle,1)
if (injected.data["antibodies"] && prob(5))
antibodies |= injected.data["antibodies"]
var/list/chems = list()
chems = params2list(injected.data["trace_chem"])
for(var/C in chems)
src.reagents.add_reagent(C, (text2num(chems[C]) / species.blood_volume) * amount)//adds trace chemicals to owner's blood
reagents.update_total()
//Transfers blood from reagents to vessel, respecting blood types compatability.
/mob/living/carbon/human/inject_blood(var/datum/reagent/blood/injected, var/amount)
if(!should_have_organ(O_HEART))
reagents.add_reagent("blood", amount, injected.data)
reagents.update_total()
return
var/datum/reagent/blood/our = get_blood(vessel)
if (!injected || !our)
return
if(blood_incompatible(injected.data["blood_type"],our.data["blood_type"],injected.data["species"],our.data["species"]) )
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
proc/blood_incompatible(donor,receiver,donor_species,receiver_species)
if(!donor || !receiver) return 0
if(donor_species && receiver_species)
if(donor_species != receiver_species)
return 1
var/donor_antigen = copytext(donor,1,lentext(donor))
var/receiver_antigen = copytext(receiver,1,lentext(receiver))
var/donor_rh = (findtext(donor,"+")>0)
var/receiver_rh = (findtext(receiver,"+")>0)
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
proc/blood_splatter(var/target,var/datum/reagent/blood/source,var/large)
var/obj/effect/decal/cleanable/blood/B
var/decal_type = /obj/effect/decal/cleanable/blood/splatter
var/turf/T = get_turf(target)
var/synth = 0
if(istype(source,/mob/living/carbon/human))
var/mob/living/carbon/human/M = source
if(M.isSynthetic()) synth = 1
source = M.get_blood(M.vessel)
// 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 appearance.
if(source.data["blood_colour"])
B.basecolor = source.data["blood_colour"]
B.synthblood = synth
B.update_icon()
// 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+"
// Update virus information.
if(source.data["virus2"])
B.virus2 = virus_copylist(source.data["virus2"])
B.fluorescent = 0
B.invisibility = 0
return B