Merge pull request #2539 from comma/organ

Organ code restructuring
This commit is contained in:
Christian Bielert
2013-03-16 07:10:40 -07:00
17 changed files with 1353 additions and 1385 deletions

View File

@@ -166,11 +166,6 @@
#include "code\datums\helper_datums\global_iterator.dm"
#include "code\datums\helper_datums\teleport.dm"
#include "code\datums\helper_datums\topic_input.dm"
#include "code\datums\organs\organ.dm"
#include "code\datums\organs\organ_external.dm"
#include "code\datums\organs\organ_internal.dm"
#include "code\datums\organs\pain.dm"
#include "code\datums\organs\wound.dm"
#include "code\datums\spells\area_teleport.dm"
#include "code\datums\spells\conjure.dm"
#include "code\datums\spells\dumbfire.dm"
@@ -508,6 +503,7 @@
#include "code\game\objects\items\robot\robot_parts.dm"
#include "code\game\objects\items\robot\robot_upgrades.dm"
#include "code\game\objects\items\stacks\medical.dm"
#include "code\game\objects\items\stacks\nanopaste.dm"
#include "code\game\objects\items\stacks\rods.dm"
#include "code\game\objects\items\stacks\stack.dm"
#include "code\game\objects\items\stacks\sheets\glass.dm"
@@ -1029,6 +1025,12 @@
#include "code\modules\mob\new_player\preferences_setup.dm"
#include "code\modules\mob\new_player\skill.dm"
#include "code\modules\mob\new_player\sprite_accessories.dm"
#include "code\modules\organs\blood.dm"
#include "code\modules\organs\organ.dm"
#include "code\modules\organs\organ_external.dm"
#include "code\modules\organs\organ_internal.dm"
#include "code\modules\organs\pain.dm"
#include "code\modules\organs\wound.dm"
#include "code\modules\paperwork\clipboard.dm"
#include "code\modules\paperwork\filingcabinet.dm"
#include "code\modules\paperwork\folders.dm"

View File

@@ -1,20 +0,0 @@
/datum/organ
var/name = "organ"
var/mob/living/carbon/human/owner = null
var/list/datum/autopsy_data/autopsy_data = list()
var/list/trace_chemicals = list() // traces of chemicals in the organ,
// links chemical IDs to number of ticks for which they'll stay in the blood
///datum/organ/proc/process()
// return 0
///datum/organ/proc/receive_chem(chemical as obj)
// return 0
proc/process()
return 0
proc/receive_chem(chemical as obj)
return 0

View File

@@ -84,7 +84,7 @@
if(istype(src.beaker, /obj/item/weapon/reagent_containers/blood))
// speed up transfer on blood packs
transfer_amount = 4
src.beaker.reagents.trans_to(src.attached, transfer_amount)
attached.inject_blood(beaker,transfer_amount)
update_icon()
// Take blood
@@ -99,52 +99,23 @@
var/mob/living/carbon/human/T = attached
if(!istype(T)) return
var/datum/reagent/B
for(var/datum/reagent/blood/Blood in beaker.reagents.reagent_list)
if(Blood.data && Blood.data["blood_type"]==T.dna.b_type)
B = Blood
break
if(!B) B = new /datum/reagent/blood
if(!T.dna)
return
if(NOCLONE in T.mutations)
return
// If the human is losing too much blood, beep.
if(T.vessel.get_reagent_amount("blood") < BLOOD_VOLUME_SAFE) if(prob(5))
visible_message("\The [src] beeps loudly.")
if(T.vessel.get_reagent_amount("blood") < amount)
return
B.holder = beaker
B.volume += amount
//set reagent data
B.data["donor"] = T
if(T.virus2)
B.data["virus2"] = T.virus2.getcopy()
var/datum/reagent/B = T.take_blood(beaker,amount)
B.data["blood_DNA"] = copytext(T.dna.unique_enzymes,1,0)
if(T.resistances && T.resistances.len)
if(B.data["resistances"])
B.data["resistances"] |= T.resistances.Copy()
else
B.data["resistances"] = T.resistances.Copy()
B.data["blood_type"] = copytext(T.dna.b_type,1,0)
var/list/temp_chem = list()
for(var/datum/reagent/R in T.reagents.reagent_list)
temp_chem += R.name
temp_chem[R.name] = R.volume
B.data["trace_chem"] = list2params(temp_chem)
B.data["antibodies"] |= T.antibodies
T.vessel.remove_reagent("blood",amount) // Removes blood if human
beaker.reagents.reagent_list |= B
beaker.reagents.update_total()
beaker.on_reagent_change()
beaker.reagents.handle_reactions()
update_icon()
if (B)
beaker.reagents.reagent_list |= B
beaker.reagents.update_total()
beaker.on_reagent_change()
beaker.reagents.handle_reactions()
update_icon()
/obj/machinery/iv_drip/attack_hand(mob/user as mob)
if(src.beaker)

View File

@@ -0,0 +1,37 @@
/obj/item/stack/nanopaste
name = "nanopaste"
singular_name = "nanite swarm"
desc = "A tube of paste containing swarms of repair nanties. Very effective in repairing robotic machinery."
icon = 'icons/obj/nanopaste.dmi'
icon_state = "tube"
origin_tech = "materials=4;engineering=3"
amount = 10
/obj/item/stack/nanopaste/attack(mob/living/M as mob, mob/user as mob)
if (!istype(M) || !istype(user))
return 0
if (istype(M,/mob/living/silicon/robot)) //Repairing cyborgs
var/mob/living/silicon/robot/R = M
if (R.getBruteLoss() || R.getFireLoss() )
R.adjustBruteLoss(-60)
R.adjustFireLoss(-60)
R.updatehealth()
use(1)
user.visible_message("<span class='notice'>You apply some [src] at [R]'s damaged areas.</span>",\
"<span class='notice'>\The [user] applied some [src] at [R]'s damaged areas.</span>")
else
user << "<span class='notice'>All [R]'s systems are nominal.</span>"
if (istype(M,/mob/living/carbon/human)) //Repairing robolimbs
var/mob/living/carbon/human/H = M
var/datum/organ/external/S = H.get_organ(user.zone_sel.selecting)
if (S && (S.status & ORGAN_ROBOT))
if(S.get_damage())
S.heal_damage(30, 30, robo_repair = 1)
H.updatehealth()
use(1)
user.visible_message("<span class='notice'>You apply some nanite paste at [user == M ? "your" : "[M]'s"] [S.display_name]</span>",\
"<span class='notice'>\The [user] applies some nanite paste at[user != M ? " \the [M]'s" : " \the"][S.display_name] with \the [src]</span>")
else
user << "<span class='notice'>Nothing to fix here.</span>"

View File

@@ -5,10 +5,6 @@
icon = 'icons/mob/human.dmi'
icon_state = "body_m_s"
var/datum/reagents/vessel
// TODO: make this actually affect the way the mob is rendered
var/pale = 0
/mob/living/carbon/human/dummy
real_name = "Test Dummy"
@@ -24,78 +20,14 @@
if(!dna)
dna = new /datum/dna(null)
//initialise organs
organs = list()
organs_by_name["chest"] = new/datum/organ/external/chest()
organs_by_name["groin"] = new/datum/organ/external/groin(organs_by_name["chest"])
organs_by_name["head"] = new/datum/organ/external/head(organs_by_name["chest"])
organs_by_name["l_arm"] = new/datum/organ/external/l_arm(organs_by_name["chest"])
organs_by_name["r_arm"] = new/datum/organ/external/r_arm(organs_by_name["chest"])
organs_by_name["r_leg"] = new/datum/organ/external/r_leg(organs_by_name["groin"])
organs_by_name["l_leg"] = new/datum/organ/external/l_leg(organs_by_name["groin"])
organs_by_name["l_hand"] = new/datum/organ/external/l_hand(organs_by_name["l_arm"])
organs_by_name["r_hand"] = new/datum/organ/external/r_hand(organs_by_name["r_arm"])
organs_by_name["l_foot"] = new/datum/organ/external/l_foot(organs_by_name["l_leg"])
organs_by_name["r_foot"] = new/datum/organ/external/r_foot(organs_by_name["r_leg"])
new/datum/organ/internal/heart(src)
new/datum/organ/internal/lungs(src)
new/datum/organ/internal/liver(src)
new/datum/organ/internal/kidney(src)
new/datum/organ/internal/brain(src)
for(var/name in organs_by_name)
organs += organs_by_name[name]
for(var/datum/organ/external/O in organs)
O.owner = src
..()
if(dna)
dna.real_name = real_name
prev_gender = gender // Debug for plural genders
vessel = new/datum/reagents(600)
vessel.my_atom = src
vessel.add_reagent("blood",560)
spawn(1)
fixblood()
/mob/living/carbon/human/proc/drip(var/amt as num)
if(!amt)
return
var/amm = 0.1 * amt
var/turf/T = get_turf(src)
var/list/obj/effect/decal/cleanable/blood/drip/nums = list()
var/list/iconL = list("1","2","3","4","5")
vessel.remove_reagent("blood",amm)
for(var/obj/effect/decal/cleanable/blood/drip/G in T)
nums += G
iconL.Remove(G.icon_state)
if (nums.len < 5)
var/obj/effect/decal/cleanable/blood/drip/this = new(T)
this.icon_state = pick(iconL)
this.blood_DNA = list()
this.blood_DNA[dna.unique_enzymes] = dna.b_type
else
for(var/obj/effect/decal/cleanable/blood/drip/G in nums)
del G
T.add_blood(src)
/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.b_type,"resistances"=null,"trace_chem"=null, "virus2" = null, "antobodies" = null)
make_organs()
make_blood()
/mob/living/carbon/human/Bump(atom/movable/AM as mob|obj, yes)
if ((!( yes ) || now_pushing))

View File

@@ -47,9 +47,6 @@
var/icon/stand_icon = null
var/icon/lying_icon = null
var/list/organs = list() //Gets filled up in the constructor (human.dm, New() proc, line 24. I'm sick and tired of missing comments. -Agouri
var/list/organs_by_name = list() // map organ names to organs
var/miming = null //Toggle for the mime's abilities.
var/special_voice = "" // For changing our voice. Used by a symptom.

View File

@@ -21,11 +21,6 @@
#define COLD_GAS_DAMAGE_LEVEL_2 1.5 //Amount of damage applied when the current breath's temperature passes the 200K point
#define COLD_GAS_DAMAGE_LEVEL_3 3 //Amount of damage applied when the current breath's temperature passes the 120K point
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/oxygen_alert = 0
var/toxins_alert = 0
@@ -133,98 +128,6 @@ var/const/BLOOD_VOLUME_SURVIVE = 122
/mob/living/carbon/human
proc/handle_blood()
// take care of blood and blood loss
if(stat < 2 && bodytemperature >= 170)
var/blood_volume = round(vessel.get_reagent_amount("blood"))
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
var/datum/reagent/nutriment/F = locate() in reagents.reagent_list
if(F != null)
if(F.volume >= 1)
// nutriment speeds it up quite a bit
B.volume += 0.4
F.volume -= 0.1
else
//At this point, we dun care which blood we are adding to, as long as they get more blood.
B.volume = B.volume + 0.1 // regenerate blood VERY slowly
// Damaged heart virtually reduces the blood volume, as the blood isn't
// being pumped properly anymore.
var/datum/organ/internal/heart/heart = internal_organs["heart"]
switch(heart.damage)
if(5 to 10)
blood_volume *= 0.8
if(11 to 20)
blood_volume *= 0.5
if(21 to INFINITY)
blood_volume *= 0.3
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","woosey","faint")
src << "\red You feel [word]"
if(prob(1))
var/word = pick("dizzy","woosey","faint")
src << "\red You feel [word]"
if(oxyloss < 20)
// hint that they're getting close to suffocation
oxyloss += 3
if(BLOOD_VOLUME_BAD to BLOOD_VOLUME_OKAY)
if(!pale)
pale = 1
update_body()
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]"
if(BLOOD_VOLUME_SURVIVE to BLOOD_VOLUME_BAD)
oxyloss += 5
toxloss += 5
if(prob(15))
var/word = pick("dizzy","woosey","faint")
src << "\red You feel extremely [word]"
if(0 to BLOOD_VOLUME_SURVIVE)
// 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
var/blood_max = 0
for(var/datum/organ/external/temp in organs)
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
if(temp.status & ORGAN_DESTROYED && !(temp.status & ORGAN_GAUZED) && !temp.amputated)
blood_max += 20 //Yer missing a fucking limb.
drip(blood_max)
proc/handle_disabilities()
if (disabilities & EPILEPSY)
if ((prob(1) && paralysis < 1))
@@ -291,108 +194,6 @@ var/const/BLOOD_VOLUME_SURVIVE = 122
src << "\red Your legs won't respond properly, you fall down."
lying = 1
proc/handle_organs()
// take care of organ related updates, such as broken and missing limbs
// recalculate number of wounds
number_wounds = 0
for(var/datum/organ/external/E in organs)
if(!E)
world << name
continue
number_wounds += E.number_wounds
var/leg_tally = 2
var/canstand_l = 1 //Can stand on left leg
var/canstand_r = 1 //Can stand on right leg
var/hasleg_l = 1 //Have left leg
var/hasleg_r = 1 //Have right leg
var/hasarm_l = 1 //Have left arm
var/hasarm_r = 1 //Have right arm
for(var/datum/organ/external/E in organs)
E.process()
if(E.status & ORGAN_ROBOT && prob(E.brute_dam + E.burn_dam))
if(E.name == "l_hand" || E.name == "l_arm")
if(hand && equipped())
drop_item()
emote("me", 1, "drops what they were holding, their [E.display_name?"[E.display_name]":"[E]"] malfunctioning!")
var/datum/effect/effect/system/spark_spread/spark_system = new /datum/effect/effect/system/spark_spread()
spark_system.set_up(5, 0, src)
spark_system.attach(src)
spark_system.start()
spawn(10)
del(spark_system)
else if(E.name == "r_hand" || E.name == "r_arm")
if(!hand && equipped())
drop_item()
emote("me", 1, "drops what they were holding, their [E.display_name?"[E.display_name]":"[E]"] malfunctioning!")
var/datum/effect/effect/system/spark_spread/spark_system = new /datum/effect/effect/system/spark_spread()
spark_system.set_up(5, 0, src)
spark_system.attach(src)
spark_system.start()
spawn(10)
del(spark_system)
else if(E.name == "l_leg" || E.name == "l_foot" \
|| E.name == "r_leg" || E.name == "r_foot" && !lying)
leg_tally-- // let it fail even if just foot&leg
if(E.status & ORGAN_BROKEN || (E.status & ORGAN_DESTROYED && !E.amputated))
if(E.name == "l_hand" || E.name == "l_arm")
if(hand && equipped())
if(E.status & ORGAN_SPLINTED && prob(10))
drop_item()
emote("scream")
else
drop_item()
emote("scream")
else if(E.name == "r_hand" || E.name == "r_arm")
if(!hand && equipped())
if(E.status & ORGAN_SPLINTED && prob(10))
drop_item()
emote("scream")
else
drop_item()
emote("scream")
else if(E.name == "l_leg" || E.name == "l_foot" \
|| E.name == "r_leg" || E.name == "r_foot" && !lying)
if(!(E.status & ORGAN_SPLINTED))
leg_tally-- // let it fail even if just foot&leg
// standing is poor
if(leg_tally <= 0 && !paralysis && !(lying || resting) && prob(5))
emote("scream")
emote("collapse")
paralysis = 10
//Check arms and legs for existence
var/datum/organ/external/E
E = get_organ("l_leg")
if(E.status & ORGAN_DESTROYED && !(E.status & ORGAN_SPLINTED))
canstand_l = 0
hasleg_l = 0
E = get_organ("r_leg")
if(E.status & ORGAN_DESTROYED && !(E.status & ORGAN_SPLINTED))
canstand_r = 0
hasleg_r = 0
E = get_organ("l_foot")
if(E.status & ORGAN_DESTROYED && !(E.status & ORGAN_SPLINTED))
canstand_l = 0
E = get_organ("r_foot")
if(E.status & ORGAN_DESTROYED && !(E.status & ORGAN_SPLINTED))
canstand_r = 0
E = get_organ("l_arm")
if(E.status & ORGAN_DESTROYED && !(E.status & ORGAN_SPLINTED))
hasarm_l = 0
E = get_organ("r_arm")
if(E.status & ORGAN_DESTROYED && !(E.status & ORGAN_SPLINTED))
hasarm_r = 0
// Can stand if have at least one full leg (with leg and foot parts present)
// Has limbs to move around if at least one arm or leg is at least partially there
can_stand = canstand_l||canstand_r
has_limbs = hasleg_l||hasleg_r||hasarm_l||hasarm_r
proc/handle_mutations_and_radiation()
if(getFireLoss())
if((COLD_RESISTANCE in mutations) || (prob(1)))
@@ -455,20 +256,14 @@ var/const/BLOOD_VOLUME_SURVIVE = 122
if(reagents.has_reagent("lexorin")) return
if(istype(loc, /obj/machinery/atmospherics/unary/cryo_cell)) return
var/lung_ruptured = is_lung_ruptured()
if(lung_ruptured && prob(2))
spawn emote("me", 1, "coughs up blood!")
src.drip(10)
var/datum/organ/internal/lungs/L = internal_organs["lungs"]
L.process()
var/datum/gas_mixture/environment = loc.return_air()
var/datum/gas_mixture/breath
// HACK NEED CHANGING LATER
if(health < 0)
losebreath++
if(lung_ruptured && prob(4))
spawn emote("me", 1, "gasps for air!")
losebreath += 5
if(losebreath>0) //Suffocating so do not take a breath
losebreath--
if (prob(10)) //Gasp per 10 ticks? Sounds about right.
@@ -498,7 +293,7 @@ var/const/BLOOD_VOLUME_SURVIVE = 122
breath = loc.remove_air(breath_moles)
if(!lung_ruptured)
if(!is_lung_ruptured())
if(!breath || breath.total_moles < BREATH_MOLES / 5 || breath.total_moles > BREATH_MOLES * 5)
if(prob(5))
rupture_lung()
@@ -1061,34 +856,10 @@ var/const/BLOOD_VOLUME_SURVIVE = 122
dizziness = max(0, dizziness - 3)
jitteriness = max(0, jitteriness - 3)
handle_trace_chems()
if(life_tick % 10 == 0)
// handle trace chemicals for autopsy
for(var/datum/organ/O in organs)
for(var/chemID in O.trace_chemicals)
O.trace_chemicals[chemID] = O.trace_chemicals[chemID] - 1
if(O.trace_chemicals[chemID] <= 0)
O.trace_chemicals.Remove(chemID)
for(var/datum/reagent/A in reagents.reagent_list)
// add chemistry traces to a random organ
var/datum/organ/O = pick(organs)
O.trace_chemicals[A.name] = 100
var/damaged_liver_process_accuracy = 10
if(life_tick % damaged_liver_process_accuracy == 0)
// Damaged liver means some chemicals are very dangerous
var/datum/organ/internal/liver/liver = internal_organs["liver"]
if(liver.damage >= liver.min_bruised_damage)
for(var/datum/reagent/R in src.reagents.reagent_list)
// Ethanol and all drinks are bad
if(istype(R, /datum/reagent/ethanol))
adjustToxLoss(0.1 * damaged_liver_process_accuracy)
// Can't cope with toxins at all
for(var/toxin in list("toxin", "plasma", "sacid", "pacid", "cyanide", "lexorin", "amatoxin", "chloralhydrate", "carpotoxin", "zombiepowder", "mindbreaker"))
if(src.reagents.has_reagent(toxin))
adjustToxLoss(0.3 * damaged_liver_process_accuracy)
var/datum/organ/internal/liver/liver = internal_organs["liver"]
liver.process()
updatehealth()

View File

@@ -0,0 +1,213 @@
/****************************************************
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/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
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.b_type, \
"resistances"=null,"trace_chem"=null, "virus2" = null, "antobodies" = null)
// Takes care blood loss and regeneration
/mob/living/carbon/human/proc/handle_blood()
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)
// Damaged heart virtually reduces the blood volume, as the blood isn't
// being pumped properly anymore.
var/datum/organ/internal/heart/heart = internal_organs["heart"]
switch(heart.damage)
if(5 to 10)
blood_volume *= 0.8
if(11 to 20)
blood_volume *= 0.5
if(21 to INFINITY)
blood_volume *= 0.3
//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","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
if(BLOOD_VOLUME_BAD to BLOOD_VOLUME_OKAY)
if(!pale)
pale = 1
update_body()
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]"
if(BLOOD_VOLUME_SURVIVE to BLOOD_VOLUME_BAD)
oxyloss += 5
toxloss += 5
if(prob(15))
var/word = pick("dizzy","woosey","faint")
src << "\red You feel extremely [word]"
if(0 to BLOOD_VOLUME_SURVIVE)
// 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/datum/organ/external/temp in organs)
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
if(temp.status & ORGAN_DESTROYED && !(temp.status & ORGAN_GAUZED) && !temp.amputated)
blood_max += 20 //Yer missing a fucking limb.
if (temp.open)
blood_max += 2 //Yer stomach is cut open
drip(blood_max)
//Makes a blood drop, leaking certain amount of blood from the mob
/mob/living/carbon/human/proc/drip(var/amt as num)
if(!amt)
return
var/amm = 0.1 * amt
var/turf/T = get_turf(src)
var/list/obj/effect/decal/cleanable/blood/drip/nums = list()
var/list/iconL = list("1","2","3","4","5")
vessel.remove_reagent("blood",amm)
for(var/obj/effect/decal/cleanable/blood/drip/G in T)
nums += G
iconL.Remove(G.icon_state)
if (nums.len < 5)
var/obj/effect/decal/cleanable/blood/drip/this = new(T)
this.icon_state = pick(iconL)
this.blood_DNA = list()
this.blood_DNA[dna.unique_enzymes] = dna.b_type
else
for(var/obj/effect/decal/cleanable/blood/drip/G in nums)
del G
T.add_blood(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(src.virus2)
B.data["virus2"] = src.virus2.getcopy()
B.data["antibodies"] |= src.antibodies
B.data["blood_DNA"] = copytext(src.dna.unique_enzymes,1,0)
if(src.resistances && src.resistances.len)
if(B.data["resistances"])
B.data["resistances"] |= src.resistances.Copy()
else
B.data["resistances"] = src.resistances.Copy()
B.data["blood_type"] = copytext(src.dna.b_type,1,0)
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)
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(vessel.get_reagent_amount("blood") < amount)
return null
. = ..()
vessel.remove_reagent("blood",amount) // Removes blood if human
//Transfers blood from container ot vessels, respecting blood types compatability.
/mob/living/carbon/human/proc/inject_blood(obj/item/weapon/reagent_containers/container, var/amount)
var/datum/reagent/blood/our = get_blood(vessel)
var/datum/reagent/blood/injected = get_blood(container.reagents)
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)
vessel.update_total()
container.reagents.remove_reagent("blood", amount)
//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

View File

@@ -0,0 +1,148 @@
/datum/organ
var/name = "organ"
var/mob/living/carbon/human/owner = null
var/list/datum/autopsy_data/autopsy_data = list()
var/list/trace_chemicals = list() // traces of chemicals in the organ,
// links chemical IDs to number of ticks for which they'll stay in the blood
proc/process()
return 0
proc/receive_chem(chemical as obj)
return 0
//Handles chem traces
/mob/living/carbon/human/proc/handle_trace_chems()
//New are added for reagents to random organs.
for(var/datum/reagent/A in reagents.reagent_list)
var/datum/organ/O = pick(organs)
O.trace_chemicals[A.name] = 100
//Adds autopsy data for used_weapon.
/datum/organ/proc/add_autopsy_data(var/used_weapon, var/damage)
var/datum/autopsy_data/W = autopsy_data[used_weapon]
if(!W)
W = new()
W.weapon = used_weapon
autopsy_data[used_weapon] = W
W.hits += 1
W.damage += damage
W.time_inflicted = world.time
/mob/living/carbon/human/var/list/organs = list()
/mob/living/carbon/human/var/list/organs_by_name = list() // map organ names to organs
//Creates and initializes and connects external and internal organs
/mob/living/carbon/human/proc/make_organs()
organs = list()
organs_by_name["chest"] = new/datum/organ/external/chest()
organs_by_name["groin"] = new/datum/organ/external/groin(organs_by_name["chest"])
organs_by_name["head"] = new/datum/organ/external/head(organs_by_name["chest"])
organs_by_name["l_arm"] = new/datum/organ/external/l_arm(organs_by_name["chest"])
organs_by_name["r_arm"] = new/datum/organ/external/r_arm(organs_by_name["chest"])
organs_by_name["r_leg"] = new/datum/organ/external/r_leg(organs_by_name["groin"])
organs_by_name["l_leg"] = new/datum/organ/external/l_leg(organs_by_name["groin"])
organs_by_name["l_hand"] = new/datum/organ/external/l_hand(organs_by_name["l_arm"])
organs_by_name["r_hand"] = new/datum/organ/external/r_hand(organs_by_name["r_arm"])
organs_by_name["l_foot"] = new/datum/organ/external/l_foot(organs_by_name["l_leg"])
organs_by_name["r_foot"] = new/datum/organ/external/r_foot(organs_by_name["r_leg"])
new/datum/organ/internal/heart(src)
new/datum/organ/internal/lungs(src)
new/datum/organ/internal/liver(src)
new/datum/organ/internal/kidney(src)
new/datum/organ/internal/brain(src)
for(var/name in organs_by_name)
organs += organs_by_name[name]
for(var/datum/organ/external/O in organs)
O.owner = src
// Takes care of organ related updates, such as broken and missing limbs
/mob/living/carbon/human/proc/handle_organs()
number_wounds = 0
var/leg_tally = 2
for(var/datum/organ/external/E in organs)
if(!E)
continue
E.process()
number_wounds += E.number_wounds
//Robotic limb malfunctions
var/malfunction = 0
if (E.status & ORGAN_ROBOT && prob(E.brute_dam + E.burn_dam))
malfunction = 1
//Broken limbs hurt too
var/broken = 0
if(E.status & ORGAN_BROKEN && !(E.status & ORGAN_SPLINTED && prob(10)) )
broken = 1
//Special effects for limbs.
if(E.name in list("l_hand","l_arm","r_hand","r_arm"))
var/obj/item/c_hand //Getting what's in this hand
if(E.name == "l_hand" || E.name == "l_arm")
c_hand = l_hand
if(E.name == "r_hand" || E.name == "r_arm")
c_hand = r_hand
if (c_hand)
if (broken||malfunction)
u_equip(c_hand)
if(broken)
emote("me", 1, "screams in pain and drops what they were holding in their [E.display_name?"[E.display_name]":"[E]"]!")
if(malfunction)
emote("me", 1, "drops what they were holding, their [E.display_name?"[E.display_name]":"[E]"] malfunctioning!")
var/datum/effect/effect/system/spark_spread/spark_system = new /datum/effect/effect/system/spark_spread()
spark_system.set_up(5, 0, src)
spark_system.attach(src)
spark_system.start()
spawn(10)
del(spark_system)
else if(E.name in list("l_leg","l_foot","r_leg","r_foot") && !lying)
if (E.status & ORGAN_DESTROYED || malfunction || (broken && !(E.status & ORGAN_SPLINTED)))
leg_tally-- // let it fail even if just foot&leg
// standing is poor
if(leg_tally <= 0 && !paralysis && !(lying || resting) && prob(5))
emote("scream")
emote("collapse")
paralysis = 10
//Check arms and legs for existence
var/canstand_l = 1 //Can stand on left leg
var/canstand_r = 1 //Can stand on right leg
var/hasleg_l = 1 //Have left leg
var/hasleg_r = 1 //Have right leg
var/hasarm_l = 1 //Have left arm
var/hasarm_r = 1 //Have right arm
var/datum/organ/external/E
E = get_organ("l_leg")
if(E.status & ORGAN_DESTROYED && !(E.status & ORGAN_SPLINTED))
canstand_l = 0
hasleg_l = 0
E = get_organ("r_leg")
if(E.status & ORGAN_DESTROYED && !(E.status & ORGAN_SPLINTED))
canstand_r = 0
hasleg_r = 0
E = get_organ("l_foot")
if(E.status & ORGAN_DESTROYED && !(E.status & ORGAN_SPLINTED))
canstand_l = 0
E = get_organ("r_foot")
if(E.status & ORGAN_DESTROYED && !(E.status & ORGAN_SPLINTED))
canstand_r = 0
E = get_organ("l_arm")
if(E.status & ORGAN_DESTROYED && !(E.status & ORGAN_SPLINTED))
hasarm_l = 0
E = get_organ("r_arm")
if(E.status & ORGAN_DESTROYED && !(E.status & ORGAN_SPLINTED))
hasarm_r = 0
// Can stand if have at least one full leg (with leg and foot parts present)
// Has limbs to move around if at least one arm or leg is at least partially there
can_stand = canstand_l||canstand_r
has_limbs = hasleg_l||hasleg_r||hasarm_l||hasarm_r

View File

@@ -52,17 +52,6 @@
parent.children.Add(src)
return ..()
/datum/organ/external/proc/add_autopsy_data(var/used_weapon, var/damage)
var/datum/autopsy_data/W = autopsy_data[used_weapon]
if(!W)
W = new()
W.weapon = used_weapon
autopsy_data[used_weapon] = W
W.hits += 1
W.damage += damage
W.time_inflicted = world.time
/****************************************************
DAMAGE PROCS
****************************************************/
@@ -247,10 +236,17 @@
****************************************************/
/datum/organ/external/process()
// process wounds, doing healing etc., only do this every 4 ticks to save processing power
// Process wounds, doing healing etc. Only do this every few ticks to save processing power
if(owner.life_tick % wound_update_accuracy == 0)
update_wounds()
//Chem traces slowly vanish
if(owner.life_tick % 10 == 0)
for(var/chemID in trace_chemicals)
trace_chemicals[chemID] = trace_chemicals[chemID] - 1
if(trace_chemicals[chemID] <= 0)
trace_chemicals.Remove(chemID)
//Dismemberment
if(status & ORGAN_DESTROYED)
if(!destspawn && config.limbs_can_break)
@@ -348,6 +344,7 @@
brute_dam = 0
burn_dam = 0
status &= ~ORGAN_BLEEDING
var/clamped = 0
for(var/datum/wound/W in wounds)
if(W.damage_type == CUT || W.damage_type == BRUISE)
brute_dam += W.damage
@@ -357,8 +354,13 @@
if(!(status & ORGAN_ROBOT) && W.bleeding())
status |= ORGAN_BLEEDING
clamped |= W.clamped
number_wounds += W.amount
if (open && !clamped) //things tend to bleed if they are CUT OPEN
status |= ORGAN_BLEEDING
// new damage icon system
// adjusted to set damage_state to brute/burn code only (without r_name0 as before)
@@ -718,6 +720,10 @@ obj/item/weapon/organ/New(loc, mob/living/carbon/human/H)
icon = I
/****************************************************
EXTERNAL ORGAN ITEMS DEFINES
****************************************************/
obj/item/weapon/organ/l_arm
name = "left arm"
icon_state = "l_arm"

View File

@@ -2,70 +2,6 @@
INTERNAL ORGANS
****************************************************/
/*
/datum/organ/internal
name = "internal"
var/damage = 0
var/max_damage = 100
/datum/organ/internal/skeleton
name = "spooky scary skeleton"
max_damage = 200
/datum/organ/internal/skin
name = "skin"
max_damage = 100
/datum/organ/internal/blood_vessels
name = "blood vessels"
var/heart = null
var/lungs = null
var/kidneys = null
/datum/organ/internal/brain
name = "brain"
var/head = null
/datum/organ/internal/excretory
name = "excretory"
var/excretory = 7.0
var/blood_vessels = null
/datum/organ/internal/heart
name = "heart"
/datum/organ/internal/immune_system
name = "immune system"
var/blood_vessels = null
var/isys = null
/datum/organ/internal/intestines
name = "intestines"
var/intestines = 3.0
var/blood_vessels = null
/datum/organ/internal/liver
name = "liver"
var/intestines = null
var/blood_vessels = null
/datum/organ/internal/lungs
name = "lungs"
var/lungs = 3.0
var/throat = null
var/blood_vessels = null
/datum/organ/internal/stomach
name = "stomach"
var/intestines = null
/datum/organ/internal/throat
name = "throat"
var/lungs = null
var/stomach = null
*/
/mob/living/carbon/human/var/list/internal_organs = list()
/datum/organ/internal
@@ -97,6 +33,10 @@
var/datum/organ/external/parent = owner.get_organ(parent_organ)
owner.custom_pain("Something inside your [parent.display_name] hurts a lot.", 1)
/****************************************************
INTERNAL ORGANS DEFINES
****************************************************/
/datum/organ/internal/heart
name = "heart"
parent_organ = "chest"
@@ -106,10 +46,33 @@
name = "lungs"
parent_organ = "chest"
process()
if(is_bruised())
if(prob(2))
spawn owner.emote("me", 1, "coughs up blood!")
owner.drip(10)
if(prob(4))
spawn owner.emote("me", 1, "gasps for air!")
owner.losebreath += 5
/datum/organ/internal/liver
name = "liver"
parent_organ = "chest"
var/process_accuracy = 10
process()
if(owner.life_tick % process_accuracy == 0)
// Damaged liver means some chemicals are very dangerous
if(src.damage >= src.min_bruised_damage)
for(var/datum/reagent/R in owner.reagents.reagent_list)
// Ethanol and all drinks are bad
if(istype(R, /datum/reagent/ethanol))
owner.adjustToxLoss(0.1 * process_accuracy)
// Can't cope with toxins at all
for(var/toxin in list("toxin", "plasma", "sacid", "pacid", "cyanide", "lexorin", "amatoxin", "chloralhydrate", "carpotoxin", "zombiepowder", "mindbreaker"))
if(owner.reagents.has_reagent(toxin))
owner.adjustToxLoss(0.3 * process_accuracy)
/datum/organ/internal/kidney
name = "kidney"

View File

@@ -101,7 +101,7 @@ mob/living/carbon/human/proc/handle_pain()
if(11 to 15)
toxMessageProb = 2
toxDamageMessage = "Your whole body hurts."
else
if(91 to 10000)
toxMessageProb = 5
toxDamageMessage = "Your body aches all over, it's driving you mad."

View File

@@ -107,30 +107,9 @@ datum
var/current_reagent_transfer = current_reagent.volume * part
if(preserve_data)
trans_data = current_reagent.data
if(current_reagent.id == "blood" && ishuman(target)) // can never be sure
var/mob/living/carbon/human/H = target
var/datum/reagent/blood/HisBlood = locate() in H.vessel.reagent_list //Grab some blood
if(HisBlood) // Make sure there's some blood at all
if(HisBlood.data["donor"] != H) //If it's not theirs, then we look for theirs
for(var/datum/reagent/blood/D in H.vessel.reagent_list)
if(D.data["donor"] == H)
HisBlood = D
break
if(HisBlood && HisBlood.data && trans_data)
if(blood_incompatible(trans_data["blood_type"],HisBlood.data["blood_type"]))
H.reagents.add_reagent("toxin",(current_reagent_transfer * multiplier * 0.5))
H.reagents.update_total()
else
H.vessel.add_reagent(current_reagent.id, (current_reagent_transfer * multiplier), trans_data)
H.vessel.update_total()
else
H.vessel.add_reagent(current_reagent.id, (current_reagent_transfer * multiplier), trans_data)
H.vessel.update_total()
src.remove_reagent(current_reagent.id, current_reagent_transfer)
else
R.add_reagent(current_reagent.id, (current_reagent_transfer * multiplier), trans_data)
src.remove_reagent(current_reagent.id, current_reagent_transfer)
R.add_reagent(current_reagent.id, (current_reagent_transfer * multiplier), trans_data)
src.remove_reagent(current_reagent.id, current_reagent_transfer)
src.update_total()
R.update_total()

View File

@@ -80,57 +80,20 @@
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(!T.dna)
usr << "You are unable to locate any blood. (To be specific, your target seems to be missing their DNA datum)"
return
if(NOCLONE in T.mutations) //target done been et, no more blood in him
user << "\red You are unable to locate any blood."
return
if(ishuman(T))
if(T:vessel.get_reagent_amount("blood") < amount)
return
B.holder = src
B.volume = amount
//set reagent data
B.data["donor"] = T
/*
if(T.virus && T.virus.spread_type != SPECIAL)
B.data["virus"] = new T.virus.type(0)
*/
var/datum/reagent/B = T.take_blood(src,amount)
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)
if(T.virus2)
B.data["virus2"] = T.virus2.getcopy()
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.b_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)
B.data["antibodies"] = T.antibodies
if(ishuman(T))
T:vessel.remove_reagent("blood",amount) // Removes blood if human
src.reagents.reagent_list += B
src.reagents.update_total()
src.on_reagent_change()
src.reagents.handle_reactions()
if (B)
src.reagents.reagent_list += B
src.reagents.update_total()
src.on_reagent_change()
src.reagents.handle_reactions()
user << "\blue You take a blood sample from [target]"
for(var/mob/O in viewers(4, user))
O.show_message("\red [user] takes a blood sample from [target].", 1)
@@ -182,9 +145,7 @@
var/trans
if(B && ishuman(target))
var/mob/living/carbon/human/H = target
trans = B.volume > 5? 5 : B.volume
H.vessel.add_reagent("blood",trans,B.data)
src.reagents.remove_reagent("blood",trans)
H.inject_blood(src,5)
else
trans = src.reagents.trans_to(target, amount_per_transfer_from_this)
user << "\blue You inject [trans] units of the solution. The syringe now contains [src.reagents.total_volume] units."

View File

@@ -1321,6 +1321,14 @@ datum/design/synthetic_flash
build_path = "/obj/item/device/flash/synthetic"
category = "Misc"
datum/design/nanopaste
name = "nanopaste"
desc = "A tube of paste containing swarms of repair nanties. Very effective in repairing robotic machinery."
id = "nanopaste"
req_tech = list("materials" = 4, "engineering" = 3)
build_type = PROTOLATHE
materials = list("$metal" = 7000, "$glass" = 7000)
build_path = "/obj/item/stack/nanopaste"
/////////////////////////////////////////
/////////////////Weapons/////////////////
/////////////////////////////////////////

BIN
icons/obj/nanopaste.dmi Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 311 B