mirror of
https://github.com/Aurorastation/Aurora.3.git
synced 2026-01-11 01:42:17 +00:00
Removes all \red's and \blues in favor of span classes. \red things that were bold were replaced with danger because it's warning but bold.
388 lines
12 KiB
Plaintext
388 lines
12 KiB
Plaintext
var/list/organ_cache = list()
|
|
|
|
/obj/item/organ
|
|
name = "organ"
|
|
icon = 'icons/obj/surgery.dmi'
|
|
var/dead_icon
|
|
var/mob/living/carbon/human/owner = null
|
|
var/status = 0
|
|
var/vital //Lose a vital limb, die immediately.
|
|
var/damage = 0 // amount of damage to the organ
|
|
|
|
var/min_bruised_damage = 10
|
|
var/min_broken_damage = 30
|
|
var/max_damage
|
|
var/organ_tag = "organ"
|
|
|
|
var/parent_organ = "chest"
|
|
var/robotic = 0 //For being a robot
|
|
var/rejecting // Is this organ already being rejected?
|
|
|
|
var/list/transplant_data
|
|
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
|
|
germ_level = 0
|
|
var/datum/dna/dna
|
|
var/datum/species/species
|
|
var/emp_coeff = 1 //coefficient for damages taken by EMP, if the organ is robotic.
|
|
|
|
var/force_skintone = FALSE // If true, icon generation will skip is-robotic checks. Used for synthskin limbs.
|
|
|
|
/obj/item/organ/Destroy()
|
|
STOP_PROCESSING(SSprocessing, src)
|
|
if(!owner)
|
|
return ..()
|
|
|
|
if(istype(owner, /mob/living/carbon))
|
|
if(owner.internal_organs)
|
|
owner.internal_organs -= src
|
|
if(istype(owner, /mob/living/carbon/human))
|
|
if(owner.internal_organs_by_name)
|
|
owner.internal_organs_by_name -= src
|
|
if(owner.organs)
|
|
owner.organs -= src
|
|
if(owner.organs_by_name)
|
|
owner.organs_by_name -= src
|
|
|
|
owner = null
|
|
QDEL_NULL(dna)
|
|
|
|
return ..()
|
|
|
|
/obj/item/organ/proc/update_health()
|
|
return
|
|
|
|
/obj/item/organ/New(var/mob/living/carbon/holder, var/internal)
|
|
..(holder)
|
|
create_reagents(5)
|
|
if(!max_damage)
|
|
max_damage = min_broken_damage * 2
|
|
if(istype(holder))
|
|
src.owner = holder
|
|
species = all_species["Human"]
|
|
if(holder.dna)
|
|
dna = holder.dna.Clone()
|
|
species = all_species[dna.species]
|
|
else
|
|
log_debug("[src] at [loc] spawned without a proper DNA.")
|
|
var/mob/living/carbon/human/H = holder
|
|
if(istype(H))
|
|
if(internal)
|
|
var/obj/item/organ/external/E = H.get_organ(parent_organ)
|
|
if(E)
|
|
if(E.internal_organs == null)
|
|
E.internal_organs = list()
|
|
E.internal_organs |= src
|
|
if(dna)
|
|
if(!blood_DNA)
|
|
blood_DNA = list()
|
|
blood_DNA[dna.unique_enzymes] = dna.b_type
|
|
if(internal)
|
|
holder.internal_organs |= src
|
|
|
|
/obj/item/organ/proc/set_dna(var/datum/dna/new_dna)
|
|
if(new_dna)
|
|
dna = new_dna.Clone()
|
|
blood_DNA.Cut()
|
|
blood_DNA[dna.unique_enzymes] = dna.b_type
|
|
|
|
/obj/item/organ/proc/die()
|
|
if(status & ORGAN_ROBOT)
|
|
return
|
|
damage = max_damage
|
|
status |= ORGAN_DEAD
|
|
STOP_PROCESSING(SSprocessing, src)
|
|
if(dead_icon)
|
|
icon_state = dead_icon
|
|
if(owner && vital)
|
|
owner.death()
|
|
|
|
/obj/item/organ/process()
|
|
|
|
if(loc != owner)
|
|
owner = null
|
|
|
|
if (QDELETED(src))
|
|
log_debug("QDELETED organ [DEBUG_REF(src)] had process() called!")
|
|
STOP_PROCESSING(SSprocessing, src)
|
|
return
|
|
|
|
//dead already, no need for more processing
|
|
if(status & ORGAN_DEAD)
|
|
return
|
|
// Don't process if we're in a freezer, an MMI or a stasis bag.or a freezer or something I dunno
|
|
if(istype(loc,/obj/item/device/mmi))
|
|
return
|
|
if(istype(loc,/obj/structure/closet/body_bag/cryobag) || istype(loc,/obj/structure/closet/crate/freezer) || istype(loc,/obj/item/weapon/storage/box/freezer))
|
|
return
|
|
//Process infections
|
|
if ((status & ORGAN_ROBOT) || (owner && owner.species && (owner.species.flags & IS_PLANT)))
|
|
germ_level = 0
|
|
return
|
|
|
|
if(!owner)
|
|
if (QDELETED(reagents))
|
|
log_debug("Organ [DEBUG_REF(src)] had QDELETED reagents! Regenerating.")
|
|
create_reagents(5)
|
|
|
|
var/datum/reagent/blood/B = locate(/datum/reagent/blood) in reagents.reagent_list
|
|
if(B && prob(40))
|
|
reagents.remove_reagent("blood",0.1)
|
|
if (isturf(loc))
|
|
blood_splatter(src,B,1)
|
|
if(config.organs_decay) damage += rand(1,3)
|
|
if(damage >= max_damage)
|
|
damage = max_damage
|
|
germ_level += rand(2,6)
|
|
if(germ_level >= INFECTION_LEVEL_TWO)
|
|
germ_level += rand(2,6)
|
|
if(germ_level >= INFECTION_LEVEL_THREE)
|
|
die()
|
|
|
|
|
|
else if(owner.bodytemperature >= 170) //cryo stops germs from moving and doing their bad stuffs
|
|
//** Handle antibiotics and curing infections
|
|
handle_antibiotics()
|
|
handle_rejection()
|
|
handle_germ_effects()
|
|
|
|
//check if we've hit max_damage
|
|
if(damage >= max_damage)
|
|
die()
|
|
|
|
/obj/item/organ/examine(mob/user)
|
|
..(user)
|
|
if(status & ORGAN_DEAD)
|
|
user << "<span class='notice'>The decay has set in.</span>"
|
|
|
|
/obj/item/organ/proc/handle_germ_effects()
|
|
//** Handle the effects of infections
|
|
var/antibiotics = owner.reagents.get_reagent_amount("spaceacillin")
|
|
|
|
if (germ_level > 0 && germ_level < INFECTION_LEVEL_ONE/2 && prob(30))
|
|
germ_level--
|
|
|
|
if (germ_level >= INFECTION_LEVEL_ONE/2)
|
|
//aiming for germ level to go from ambient to INFECTION_LEVEL_TWO in an average of 15 minutes
|
|
if(antibiotics < 5 && prob(round(germ_level/6)))
|
|
germ_level++
|
|
|
|
if(germ_level >= INFECTION_LEVEL_ONE)
|
|
var/fever_temperature = (owner.species.heat_level_1 - owner.species.body_temperature - 5)* min(germ_level/INFECTION_LEVEL_TWO, 1) + owner.species.body_temperature
|
|
owner.bodytemperature += between(0, (fever_temperature - T20C)/BODYTEMP_COLD_DIVISOR + 1, fever_temperature - owner.bodytemperature)
|
|
|
|
if (germ_level >= INFECTION_LEVEL_TWO)
|
|
var/obj/item/organ/external/parent = owner.get_organ(parent_organ)
|
|
//spread germs
|
|
if (antibiotics < 5 && parent.germ_level < germ_level && ( parent.germ_level < INFECTION_LEVEL_ONE*2 || prob(30) ))
|
|
parent.germ_level++
|
|
|
|
if (prob(3)) //about once every 30 seconds
|
|
take_damage(1,silent=prob(30))
|
|
|
|
/obj/item/organ/proc/handle_rejection()
|
|
// Process unsuitable transplants. TODO: consider some kind of
|
|
// immunosuppressant that changes transplant data to make it match.
|
|
if(dna)
|
|
if(!rejecting)
|
|
if(blood_incompatible(dna.b_type, owner.dna.b_type, species, owner.species))
|
|
rejecting = 1
|
|
else
|
|
rejecting++ //Rejection severity increases over time.
|
|
if(rejecting % 10 == 0) //Only fire every ten rejection ticks.
|
|
switch(rejecting)
|
|
if(1 to 50)
|
|
germ_level++
|
|
if(51 to 200)
|
|
germ_level += rand(1,2)
|
|
if(201 to 500)
|
|
germ_level += rand(2,3)
|
|
if(501 to INFINITY)
|
|
germ_level += rand(3,5)
|
|
owner.reagents.add_reagent("toxin", rand(1,2))
|
|
|
|
/obj/item/organ/proc/receive_chem(chemical as obj)
|
|
return 0
|
|
|
|
/obj/item/organ/proc/rejuvenate()
|
|
damage = 0
|
|
|
|
/obj/item/organ/proc/is_damaged()
|
|
return damage > 0
|
|
|
|
/obj/item/organ/proc/is_bruised()
|
|
return damage >= min_bruised_damage
|
|
|
|
/obj/item/organ/proc/is_broken()
|
|
return (damage >= min_broken_damage || (status & ORGAN_CUT_AWAY) || (status & ORGAN_BROKEN))
|
|
|
|
//Germs
|
|
/obj/item/organ/proc/handle_antibiotics()
|
|
var/antibiotics = owner.reagents.get_reagent_amount("spaceacillin")
|
|
|
|
if (!germ_level || antibiotics < 5)
|
|
return
|
|
|
|
if (germ_level < INFECTION_LEVEL_ONE)
|
|
germ_level = 0 //cure instantly
|
|
else if (germ_level < INFECTION_LEVEL_TWO)
|
|
germ_level -= 6 //at germ_level == 500, this should cure the infection in a minute
|
|
else
|
|
germ_level -= 2 //at germ_level == 1000, this will cure the infection in 5 minutes
|
|
|
|
//Adds autopsy data for used_weapon.
|
|
/obj/item/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
|
|
|
|
//Note: external organs have their own version of this proc
|
|
/obj/item/organ/proc/take_damage(amount, var/silent=0)
|
|
if(src.status & ORGAN_ROBOT)
|
|
src.damage = between(0, src.damage + (amount * 0.8), max_damage)
|
|
else
|
|
src.damage = between(0, src.damage + amount, max_damage)
|
|
|
|
//only show this if the organ is not robotic
|
|
if(owner && parent_organ && amount > 0)
|
|
var/obj/item/organ/external/parent = owner.get_organ(parent_organ)
|
|
if(parent && !silent)
|
|
owner.custom_pain("Something inside your [parent.name] hurts a lot.", 1)
|
|
|
|
/obj/item/organ/proc/bruise()
|
|
damage = max(damage, min_bruised_damage)
|
|
|
|
/obj/item/organ/proc/robotize() //Being used to make robutt hearts, etc
|
|
robotic = 2
|
|
src.status &= ~ORGAN_BROKEN
|
|
src.status &= ~ORGAN_BLEEDING
|
|
src.status &= ~ORGAN_SPLINTED
|
|
src.status &= ~ORGAN_CUT_AWAY
|
|
src.status |= ORGAN_ROBOT
|
|
src.status |= ORGAN_ASSISTED
|
|
|
|
/obj/item/organ/proc/mechassist() //Used to add things like pacemakers, etc
|
|
robotize()
|
|
src.status &= ~ORGAN_ROBOT
|
|
robotic = 1
|
|
min_bruised_damage = 15
|
|
min_broken_damage = 35
|
|
|
|
/obj/item/organ/emp_act(severity)
|
|
if(!(status & ORGAN_ROBOT))
|
|
return
|
|
switch (severity)
|
|
if (1.0)
|
|
take_damage(rand(7,20) * emp_coeff)
|
|
return
|
|
if (2.0)
|
|
take_damage(rand(3,7) * emp_coeff)
|
|
return
|
|
if(3.0)
|
|
take_damage(rand(3) * emp_coeff)
|
|
|
|
/obj/item/organ/proc/removed(var/mob/living/user)
|
|
|
|
if(!istype(owner))
|
|
return
|
|
|
|
owner.internal_organs_by_name[organ_tag] = null
|
|
owner.internal_organs_by_name -= organ_tag
|
|
owner.internal_organs_by_name -= null
|
|
owner.internal_organs -= src
|
|
|
|
var/obj/item/organ/external/affected = owner.get_organ(parent_organ)
|
|
if(affected) affected.internal_organs -= src
|
|
|
|
loc = get_turf(owner)
|
|
START_PROCESSING(SSprocessing, src)
|
|
rejecting = null
|
|
if (!reagents)
|
|
create_reagents(5)
|
|
|
|
var/datum/reagent/blood/organ_blood = locate(/datum/reagent/blood) in reagents.reagent_list
|
|
if(!organ_blood || !organ_blood.data["blood_DNA"])
|
|
owner.vessel.trans_to(src, 5, 1, 1)
|
|
|
|
if(owner && vital)
|
|
if(user)
|
|
user.attack_log += "\[[time_stamp()]\]<font color='red'> removed a vital organ ([src]) from [owner.name] ([owner.ckey]) (INTENT: [uppertext(user.a_intent)])</font>"
|
|
owner.attack_log += "\[[time_stamp()]\]<font color='orange'> had a vital organ ([src]) removed by [user.name] ([user.ckey]) (INTENT: [uppertext(user.a_intent)])</font>"
|
|
msg_admin_attack("[user.name] ([user.ckey]) removed a vital organ ([src]) from [owner.name] ([owner.ckey]) (INTENT: [uppertext(user.a_intent)]) (<A HREF='?_src_=holder;adminplayerobservecoodjump=1;X=[user.x];Y=[user.y];Z=[user.z]'>JMP</a>)",ckey=key_name(user),ckey_target=key_name(owner))
|
|
owner.death()
|
|
|
|
owner = null
|
|
|
|
/obj/item/organ/proc/replaced(var/mob/living/carbon/human/target,var/obj/item/organ/external/affected)
|
|
|
|
if(!istype(target)) return
|
|
|
|
var/datum/reagent/blood/transplant_blood = locate(/datum/reagent/blood) in reagents.reagent_list
|
|
transplant_data = list()
|
|
if(!transplant_blood)
|
|
transplant_data["species"] = target.species.name
|
|
transplant_data["blood_type"] = target.dna.b_type
|
|
transplant_data["blood_DNA"] = target.dna.unique_enzymes
|
|
else
|
|
transplant_data["species"] = transplant_blood.data["species"]
|
|
transplant_data["blood_type"] = transplant_blood.data["blood_type"]
|
|
transplant_data["blood_DNA"] = transplant_blood.data["blood_DNA"]
|
|
|
|
owner = target
|
|
loc = owner
|
|
STOP_PROCESSING(SSprocessing, src)
|
|
target.internal_organs |= src
|
|
affected.internal_organs |= src
|
|
target.internal_organs_by_name[organ_tag] = src
|
|
if(robotic)
|
|
status |= ORGAN_ROBOT
|
|
|
|
/obj/item/organ/eyes/replaced(var/mob/living/carbon/human/target)
|
|
|
|
// Apply our eye colour to the target.
|
|
if(istype(target) && eye_colour)
|
|
target.r_eyes = eye_colour[1]
|
|
target.g_eyes = eye_colour[2]
|
|
target.b_eyes = eye_colour[3]
|
|
target.update_eyes()
|
|
..()
|
|
|
|
/obj/item/organ/proc/bitten(mob/user)
|
|
|
|
if(robotic)
|
|
return
|
|
|
|
user << "<span class='notice'>You take an experimental bite out of \the [src].</span>"
|
|
var/datum/reagent/blood/B = locate(/datum/reagent/blood) in reagents.reagent_list
|
|
blood_splatter(src,B,1)
|
|
|
|
user.drop_from_inventory(src)
|
|
var/obj/item/weapon/reagent_containers/food/snacks/organ/O = new(get_turf(src))
|
|
O.name = name
|
|
O.icon = icon
|
|
O.icon_state = icon_state
|
|
|
|
// Pass over the blood.
|
|
reagents.trans_to(O, reagents.total_volume)
|
|
|
|
if(fingerprints) O.fingerprints = fingerprints.Copy()
|
|
if(fingerprintshidden) O.fingerprintshidden = fingerprintshidden.Copy()
|
|
if(fingerprintslast) O.fingerprintslast = fingerprintslast
|
|
|
|
user.put_in_active_hand(O)
|
|
qdel(src)
|
|
|
|
/obj/item/organ/attack_self(mob/user as mob)
|
|
|
|
// Convert it to an edible form, yum yum.
|
|
if(!robotic && user.a_intent == "help" && user.zone_sel.selecting == "mouth")
|
|
bitten(user)
|
|
return
|