mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2026-08-31 00:58:26 +01:00
Merge pull request #7239 from paprka/ointmentandshit
BLOOD FOR THE BLOOD GOD
This commit is contained in:
@@ -20,4 +20,5 @@
|
||||
H.hair_color = random_short_color()
|
||||
H.facial_hair_color = H.hair_color
|
||||
H.eye_color = random_eye_color()
|
||||
H.dna.blood_type = random_blood_type()
|
||||
H.update_icons()
|
||||
@@ -8,26 +8,6 @@
|
||||
var/mob/living/carbon/human/bloody_hands_mob
|
||||
|
||||
|
||||
|
||||
/proc/blood_incompatible(donor,receiver)
|
||||
|
||||
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(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
|
||||
|
||||
|
||||
/obj/item/weapon/reagent_containers/glass/rag
|
||||
name = "damp rag"
|
||||
desc = "For cleaning up messes, you suppose."
|
||||
|
||||
@@ -168,6 +168,8 @@
|
||||
if(status == "")
|
||||
status = "OK"
|
||||
src << "\t [status == "OK" ? "\blue" : "\red"] My [org.getDisplayName()] is [status]."
|
||||
if(H.blood_max)
|
||||
src << "<span class='danger'>You are bleeding!</span>"
|
||||
if(staminaloss)
|
||||
if(staminaloss > 30)
|
||||
src << "<span class='info'>You're completely exhausted.</span>"
|
||||
|
||||
@@ -0,0 +1,313 @@
|
||||
/****************************************************
|
||||
BLOOD SYSTEM
|
||||
****************************************************/
|
||||
//Blood levels
|
||||
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",560)
|
||||
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,"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,"factions"=null)
|
||||
|
||||
/mob/living/carbon/human/proc/suppress_bloodloss(var/amount)
|
||||
if(bleedsuppress)
|
||||
return
|
||||
else
|
||||
bleedsuppress = 1
|
||||
spawn(amount)
|
||||
bleedsuppress = 0
|
||||
if(stat != DEAD && blood_max)
|
||||
src << "<span class='warning'>The blood soaks through your bandage.</span>"
|
||||
|
||||
// Takes care blood loss and regeneration
|
||||
/mob/living/carbon/human/proc/handle_blood()
|
||||
|
||||
if(NOBLOOD in dna.species.specflags)
|
||||
return
|
||||
|
||||
if(stat != DEAD && bodytemperature >= 170) //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 < 560 && 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 (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.8
|
||||
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 << "<span class='warning'>You feel [word].</span>"
|
||||
if(oxyloss < 20)
|
||||
oxyloss += 3
|
||||
if(BLOOD_VOLUME_BAD to BLOOD_VOLUME_OKAY)
|
||||
if(!pale)
|
||||
pale = 1
|
||||
update_body()
|
||||
if(oxyloss < 50)
|
||||
oxyloss += 10
|
||||
oxyloss += 1
|
||||
if(prob(5))
|
||||
eye_blurry += 6
|
||||
var/word = pick("dizzy","woozy","faint")
|
||||
src << "<span class='warning'>You feel very [word].</span>"
|
||||
if(BLOOD_VOLUME_SURVIVE to BLOOD_VOLUME_BAD)
|
||||
oxyloss += 5
|
||||
if(prob(15))
|
||||
Paralyse(rand(1,3))
|
||||
var/word = pick("dizzy","woozy","faint")
|
||||
src << "<span class='warning'>You feel extremely [word].</span>"
|
||||
if(0 to BLOOD_VOLUME_SURVIVE)
|
||||
death()
|
||||
|
||||
//Bleeding out
|
||||
blood_max = 0
|
||||
for(var/obj/item/organ/limb/org in organs)
|
||||
var/brutedamage = org.brute_dam
|
||||
|
||||
if(brutedamage > 30)
|
||||
blood_max += 0.5
|
||||
if(brutedamage > 50)
|
||||
blood_max += 1
|
||||
if(brutedamage > 70)
|
||||
blood_max += 2
|
||||
if(bleedsuppress)
|
||||
blood_max = 0
|
||||
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(!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(T.virus && T.virus.spread_type != SPECIAL)
|
||||
B.data["virus"] = new T.virus.type(0)
|
||||
*/
|
||||
|
||||
for(var/datum/disease/D in src.viruses)
|
||||
if(!B.data["viruses"])
|
||||
B.data["viruses"] = list()
|
||||
|
||||
B.data["viruses"] += new D.type(0, D, 1)
|
||||
|
||||
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.name
|
||||
temp_chem[R.name] = 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["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, var/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 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)
|
||||
|
||||
if(NOBLOOD in dna.species.specflags)
|
||||
reagents.add_reagent("blood", amount, injected.data)
|
||||
reagents.update_total()
|
||||
return
|
||||
|
||||
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 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)
|
||||
|
||||
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)
|
||||
|
||||
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
|
||||
if(donor.dna)
|
||||
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
|
||||
del(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+"
|
||||
|
||||
// Update virus information.
|
||||
for(var/datum/disease/D in source.data["viruses"])
|
||||
var/datum/disease/new_virus = D.Copy(1)
|
||||
source.data["viruses"] += new_virus
|
||||
new_virus.holder = B
|
||||
|
||||
return B
|
||||
@@ -230,6 +230,14 @@
|
||||
else
|
||||
msg += "[t_He] [t_is] quite chubby.\n"
|
||||
|
||||
if(pale)
|
||||
msg += "[t_He] [t_has] pale skin.\n"
|
||||
|
||||
if(bleedsuppress)
|
||||
msg += "[t_He] [t_is] bandaged with something.\n"
|
||||
else if(blood_max)
|
||||
msg += "<B>[t_He] [t_is] bleeding!</B>\n"
|
||||
|
||||
msg += "</span>"
|
||||
|
||||
if(!appears_dead)
|
||||
|
||||
@@ -30,6 +30,8 @@
|
||||
ready_dna(src)
|
||||
randomize_human(src)
|
||||
|
||||
make_blood()
|
||||
|
||||
..()
|
||||
var/mob/M = src
|
||||
faction |= "\ref[M]"
|
||||
|
||||
@@ -140,6 +140,10 @@ mob/living/carbon/human/proc/hat_fall_prob()
|
||||
|
||||
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.0-blood_volume)
|
||||
|
||||
////////////////////////////////////////////
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
var/lip_style = null //no lipstick by default- arguably misleading, as it could be used for general makeup
|
||||
|
||||
var/age = 30 //Player's age (pure fluff)
|
||||
var/blood_type = "A+" //Player's bloodtype (Not currently used, just character fluff)
|
||||
var/blood_type = "A+" //Player's bloodtype
|
||||
|
||||
var/underwear = "Nude" //Which underwear the player wants
|
||||
var/undershirt = "Nude" //Which undershirt the player wants
|
||||
@@ -49,3 +49,6 @@
|
||||
var/xylophone = 0 //For the spoooooooky xylophone cooldown
|
||||
|
||||
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/bleedsuppress = 0 //for stopping bloodloss, eventually this will be limb-based like bleeding
|
||||
@@ -84,6 +84,9 @@
|
||||
//Disabilities
|
||||
handle_disabilities()
|
||||
|
||||
//Blud
|
||||
handle_blood()
|
||||
|
||||
//Random events (vomiting etc)
|
||||
handle_random_events()
|
||||
|
||||
|
||||
@@ -127,6 +127,7 @@
|
||||
sexes = 0
|
||||
ignored_by = list(/mob/living/simple_animal/hostile/faithless)
|
||||
meat = /obj/item/weapon/reagent_containers/food/snacks/meat/human/mutant/shadow
|
||||
specflags = list(NOBREATH,NOBLOOD,RADIMMUNE)
|
||||
|
||||
/datum/species/shadow/spec_life(mob/living/carbon/human/H)
|
||||
var/light_amount = 0
|
||||
@@ -152,7 +153,7 @@
|
||||
default_color = "00FFFF"
|
||||
darksight = 3
|
||||
invis_sight = SEE_INVISIBLE_LEVEL_ONE
|
||||
specflags = list(MUTCOLORS,EYECOLOR,HAIR,FACEHAIR)
|
||||
specflags = list(MUTCOLORS,EYECOLOR,HAIR,FACEHAIR,NOBLOOD)
|
||||
hair_color = "mutcolor"
|
||||
hair_alpha = 150
|
||||
ignored_by = list(/mob/living/carbon/slime)
|
||||
@@ -169,7 +170,7 @@
|
||||
default_color = "00FF90"
|
||||
say_mod = "chirps"
|
||||
eyes = "jelleyes"
|
||||
specflags = list(MUTCOLORS,EYECOLOR)
|
||||
specflags = list(MUTCOLORS,EYECOLOR,NOBLOOD)
|
||||
meat = /obj/item/weapon/reagent_containers/food/snacks/meat/human/mutant/slime
|
||||
|
||||
/*
|
||||
@@ -228,6 +229,7 @@
|
||||
id = "skeleton"
|
||||
sexes = 0
|
||||
meat = /obj/item/weapon/reagent_containers/food/snacks/meat/human/mutant/skeleton
|
||||
specflags = list(NOBREATH,HEATRES,COLDRES,NOBLOOD,RADIMMUNE)
|
||||
/*
|
||||
ZOMBIES
|
||||
*/
|
||||
@@ -239,6 +241,7 @@
|
||||
say_mod = "moans"
|
||||
sexes = 0
|
||||
meat = /obj/item/weapon/reagent_containers/food/snacks/meat/human/mutant/zombie
|
||||
specflags = list(NOBREATH,HEATRES,COLDRES,NOBLOOD,RADIMMUNE)
|
||||
|
||||
/datum/species/zombie/handle_speech(message)
|
||||
var/list/message_list = text2list(message, " ")
|
||||
|
||||
@@ -410,6 +410,9 @@ Sorry Giacom. Please don't be mad :(
|
||||
dead_mob_list -= src
|
||||
living_mob_list += src
|
||||
if(!isanimal(src)) stat = CONSCIOUS
|
||||
if(ishuman(src))
|
||||
var/mob/living/carbon/human/human_mob = src
|
||||
human_mob.restore_blood()
|
||||
update_fire()
|
||||
regenerate_icons()
|
||||
..()
|
||||
@@ -492,30 +495,8 @@ Sorry Giacom. Please don't be mad :(
|
||||
M.stop_pulling()
|
||||
|
||||
//this is the gay blood on floor shit -- Added back -- Skie
|
||||
if (M.lying && (prob(M.getBruteLoss() / 2)))
|
||||
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/simulated) && 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(check_dna_integrity(M)) //blood DNA
|
||||
var/mob/living/carbon/DNA_helper = pulling
|
||||
H.blood_DNA[DNA_helper.dna.unique_enzymes] = DNA_helper.dna.blood_type
|
||||
if(M.lying && (prob(M.getBruteLoss() / 2)))
|
||||
makeTrail(T, M)
|
||||
pulling.Move(T, get_dir(pulling, T))
|
||||
if(M)
|
||||
M.start_pulling(t)
|
||||
@@ -532,6 +513,35 @@ Sorry Giacom. Please don't be mad :(
|
||||
for(var/mob/living/carbon/slime/M in view(1,src))
|
||||
M.UpdateFeed(src)
|
||||
|
||||
/mob/living/proc/makeTrail(var/turf/T, var/mob/living/M)
|
||||
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/simulated) && 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(check_dna_integrity(M)) //blood DNA
|
||||
var/mob/living/carbon/DNA_helper = pulling
|
||||
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
|
||||
|
||||
|
||||
@@ -107,9 +107,13 @@ datum/reagents/proc/trans_to(var/obj/target, var/amount=1, var/multiplier=1, var
|
||||
var/part = amount / src.total_volume
|
||||
var/trans_data = null
|
||||
for (var/datum/reagent/current_reagent in src.reagent_list)
|
||||
if (current_reagent.id == "blood" && ishuman(target))
|
||||
var/mob/living/carbon/human/H = target
|
||||
H.inject_blood(my_atom, amount)
|
||||
continue
|
||||
var/current_reagent_transfer = current_reagent.volume * part
|
||||
if(preserve_data)
|
||||
trans_data = current_reagent.data
|
||||
trans_data = copy_data(current_reagent)
|
||||
R.add_reagent(current_reagent.id, (current_reagent_transfer * multiplier), trans_data)
|
||||
src.remove_reagent(current_reagent.id, current_reagent_transfer)
|
||||
|
||||
@@ -524,6 +528,38 @@ datum/reagents/proc/delete()
|
||||
if(my_atom)
|
||||
my_atom.reagents = null
|
||||
|
||||
//two helper functions to preserve data across reactions (needed for xenoarch)
|
||||
datum/reagents/proc/get_data(var/reagent_id)
|
||||
for(var/datum/reagent/D in reagent_list)
|
||||
if(D.id == reagent_id)
|
||||
//world << "proffering a data-carrying reagent ([reagent_id])"
|
||||
return D.data
|
||||
|
||||
datum/reagents/proc/set_data(var/reagent_id, var/new_data)
|
||||
for(var/datum/reagent/D in reagent_list)
|
||||
if(D.id == reagent_id)
|
||||
//world << "reagent data set ([reagent_id])"
|
||||
D.data = new_data
|
||||
|
||||
datum/reagents/proc/copy_data(var/datum/reagent/current_reagent)
|
||||
if (!current_reagent || !current_reagent.data) return null
|
||||
if (!istype(current_reagent.data, /list)) return current_reagent.data
|
||||
|
||||
var/list/trans_data = current_reagent.data.Copy()
|
||||
|
||||
// We do this so that introducing a virus to a blood sample
|
||||
// doesn't automagically infect all other blood samples from
|
||||
// the same donor.
|
||||
//
|
||||
// Technically we should probably copy all data lists, but
|
||||
// that could possibly eat up a lot of memory needlessly
|
||||
// if most data lists are read-only.
|
||||
if (trans_data["viruses"])
|
||||
var/list/v = trans_data["viruses"]
|
||||
trans_data["viruses"] = v.Copy()
|
||||
|
||||
return trans_data
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
@@ -166,7 +166,6 @@ datum/reagent/blood/on_merge(var/list/data)
|
||||
src.data["viruses"] = preserve
|
||||
return 1
|
||||
|
||||
|
||||
datum/reagent/blood/reaction_turf(var/turf/simulated/T, var/volume)//splash the blood all over the place
|
||||
if(!istype(T)) return
|
||||
var/datum/reagent/blood/self = src
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
/obj/item/weapon/reagent_containers/blood
|
||||
name = "blood pack"
|
||||
desc = "Contains blood used for transfusion. Must be attached to an IV drip."
|
||||
icon = 'icons/obj/bloodpack.dmi'
|
||||
icon_state = "empty"
|
||||
volume = 200
|
||||
|
||||
var/blood_type = null
|
||||
|
||||
/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()
|
||||
update_icon()
|
||||
|
||||
/obj/item/weapon/reagent_containers/blood/update_icon()
|
||||
var/percent = round((reagents.total_volume / volume) * 100)
|
||||
switch(percent)
|
||||
if(0 to 9) icon_state = "empty"
|
||||
if(10 to 50) icon_state = "half"
|
||||
if(51 to INFINITY) icon_state = "full"
|
||||
|
||||
/obj/item/weapon/reagent_containers/blood/random/New()
|
||||
blood_type = pick("A+", "A-", "B+", "B-", "O+", "O-")
|
||||
|
||||
/obj/item/weapon/reagent_containers/blood/APlus
|
||||
blood_type = "A+"
|
||||
|
||||
/obj/item/weapon/reagent_containers/blood/AMinus
|
||||
blood_type = "A-"
|
||||
|
||||
/obj/item/weapon/reagent_containers/blood/BPlus
|
||||
blood_type = "B+"
|
||||
|
||||
/obj/item/weapon/reagent_containers/blood/BMinus
|
||||
blood_type = "B-"
|
||||
|
||||
/obj/item/weapon/reagent_containers/blood/OPlus
|
||||
blood_type = "O+"
|
||||
|
||||
/obj/item/weapon/reagent_containers/blood/OMinus
|
||||
blood_type = "O-"
|
||||
|
||||
/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"
|
||||
@@ -77,11 +77,10 @@
|
||||
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
|
||||
var/datum/reagent/B = new /datum/reagent/blood
|
||||
if(!check_dna_integrity(T))
|
||||
user << "<span class='notice'>You are unable to locate any blood.</span>"
|
||||
return
|
||||
if(NOCLONE in T.mutations) //target done been et, no more blood in him
|
||||
if(NOCLONE in T.mutations) //target done been eat, no more blood in him
|
||||
user << "<span class='notice'>You are unable to locate any blood.</span>"
|
||||
return
|
||||
if(target != user)
|
||||
@@ -92,46 +91,14 @@
|
||||
busy = 0
|
||||
return
|
||||
busy = 0
|
||||
B.holder = src
|
||||
B.volume = amount
|
||||
//set reagent data
|
||||
B.data["donor"] = T
|
||||
var/datum/reagent/B
|
||||
B = T.take_blood(src,amount)
|
||||
|
||||
/*
|
||||
if(T.virus && T.virus.spread_type != SPECIAL)
|
||||
B.data["virus"] = new T.virus.type(0)
|
||||
*/
|
||||
|
||||
for(var/datum/disease/D in T.viruses)
|
||||
if(!B.data["viruses"])
|
||||
B.data["viruses"] = list()
|
||||
|
||||
B.data["viruses"] += new D.type(0, D, 1)
|
||||
|
||||
B.data["blood_DNA"] = copytext(T.dna.unique_enzymes,1,0)
|
||||
if(T.resistances&&T.resistances.len)
|
||||
B.data["resistances"] = T.resistances.Copy()
|
||||
if(istype(target, /mob/living/carbon/human))//I wish there was some hasproperty operation...
|
||||
var/mob/living/carbon/human/HT = target
|
||||
B.data["blood_type"] = copytext(HT.dna.blood_type,1,0)
|
||||
var/list/temp_chem = list()
|
||||
for(var/datum/reagent/R in target.reagents.reagent_list)
|
||||
temp_chem += R.name
|
||||
temp_chem[R.name] = R.volume
|
||||
B.data["trace_chem"] = list2params(temp_chem)
|
||||
if(T.mind)
|
||||
B.data["mind"] = T.mind
|
||||
if(T.ckey)
|
||||
B.data["ckey"] = T.ckey
|
||||
if(!T.suiciding)
|
||||
B.data["cloneable"] = 1
|
||||
B.data["gender"] = T.gender
|
||||
B.data["real_name"] = T.real_name
|
||||
B.data["factions"] = T.faction
|
||||
reagents.reagent_list += B
|
||||
reagents.update_total()
|
||||
on_reagent_change()
|
||||
reagents.handle_reactions()
|
||||
if (B)
|
||||
src.reagents.reagent_list += B
|
||||
src.reagents.update_total()
|
||||
src.on_reagent_change()
|
||||
src.reagents.handle_reactions()
|
||||
user.visible_message("<span class='notice'>[user] takes a blood sample from [target].</span>")
|
||||
|
||||
else //if not mob
|
||||
@@ -191,7 +158,13 @@
|
||||
reagents.reaction(target, INGEST)
|
||||
spawn(5)
|
||||
target.add_fingerprint(user)
|
||||
var/trans = src.reagents.trans_to(target, amount_per_transfer_from_this)
|
||||
var/datum/reagent/blood/B = locate() in src.reagents.reagent_list
|
||||
var/trans
|
||||
if(B && istype(target,/mob/living/carbon))
|
||||
var/mob/living/carbon/C = target
|
||||
C.inject_blood(src,5)
|
||||
else
|
||||
trans = src.reagents.trans_to(target, amount_per_transfer_from_this)
|
||||
user << "<span class='notice'>You inject [trans] unit\s of the solution. [src] now contains [reagents.total_volume] unit\s.</span>"
|
||||
if(reagents.total_volume <= 0 && mode == SYRINGE_INJECT)
|
||||
mode = SYRINGE_DRAW
|
||||
|
||||
Reference in New Issue
Block a user