mirror of
https://github.com/Aurorastation/Aurora-Old.git
synced 2026-07-14 01:02:53 +01:00
e859991c31
Added a new flag for advanced synthetic organs. They're meant to be immune to EMP, mimmic most fleshy organ features, but lack the ability to heal themselves (while still accepting fleshy organ medicine). This also fixes the Vaurca automatically healing themselves.
1205 lines
37 KiB
Plaintext
1205 lines
37 KiB
Plaintext
/****************************************************
|
|
EXTERNAL ORGANS
|
|
****************************************************/
|
|
/datum/organ/external
|
|
name = "external"
|
|
var/icon_name = null
|
|
var/body_part = null
|
|
var/icon_position = 0
|
|
|
|
var/damage_state = "00"
|
|
var/brute_dam = 0
|
|
var/burn_dam = 0
|
|
var/max_damage = 0
|
|
var/max_size = 0
|
|
var/last_dam = -1
|
|
|
|
var/display_name
|
|
var/list/wounds = list()
|
|
var/number_wounds = 0 // cache the number of wounds, which is NOT wounds.len!
|
|
|
|
var/tmp/perma_injury = 0
|
|
var/tmp/destspawn = 0 //Has it spawned the broken limb?
|
|
var/tmp/amputated = 0 //Whether this has been cleanly amputated, thus causing no pain
|
|
var/min_broken_damage = 30
|
|
|
|
var/datum/organ/external/parent
|
|
var/list/datum/organ/external/children
|
|
|
|
// Internal organs of this body part
|
|
var/list/datum/organ/internal/internal_organs
|
|
|
|
var/damage_msg = "\red You feel an intense pain"
|
|
var/broken_description
|
|
|
|
var/open = 0
|
|
var/stage = 0
|
|
var/cavity = 0
|
|
var/sabotaged = 0 // If a prosthetic limb is emagged, it will detonate when it fails.
|
|
var/encased // Needs to be opened with a saw to access the organs.
|
|
|
|
var/obj/item/hidden = null
|
|
var/list/implants = list()
|
|
|
|
// how often wounds should be updated, a higher number means less often
|
|
var/wound_update_accuracy = 1
|
|
|
|
var/datum/synthetic_limb_cover/covering = null // paint or synth skin
|
|
|
|
var/gendered = FALSE
|
|
|
|
|
|
/datum/organ/external/New(var/datum/organ/external/P)
|
|
if(P)
|
|
parent = P
|
|
if(!parent.children)
|
|
parent.children = list()
|
|
parent.children.Add(src)
|
|
return ..()
|
|
|
|
/****************************************************
|
|
DAMAGE PROCS
|
|
****************************************************/
|
|
|
|
/datum/organ/external/proc/emp_act(severity)
|
|
if(!(status & ORGAN_ROBOT)) //meatbags do not care about EMP
|
|
return
|
|
var/probability = 30
|
|
var/damage = 15
|
|
if(severity == 2)
|
|
probability = 1
|
|
damage = 3
|
|
if(prob(probability))
|
|
droplimb(1)
|
|
else
|
|
take_damage(damage, 0, 1, 1, used_weapon = "EMP")
|
|
|
|
/datum/organ/external/proc/take_damage(brute, burn, sharp, edge, used_weapon = null, list/forbidden_limbs = list())
|
|
if((brute <= 0) && (burn <= 0))
|
|
return 0
|
|
|
|
if(status & ORGAN_DESTROYED)
|
|
return 0
|
|
if(status & ORGAN_ROBOT )
|
|
|
|
var/brmod = 0.66
|
|
var/bumod = 0.66
|
|
|
|
if(istype(owner,/mob/living/carbon/human))
|
|
var/mob/living/carbon/human/H = owner
|
|
if(H.species && H.species.flags & IS_SYNTHETIC)
|
|
brmod = H.species.brute_mod
|
|
bumod = H.species.burn_mod
|
|
|
|
brute *= brmod //~2/3 damage for ROBOLIMBS
|
|
burn *= bumod //~2/3 damage for ROBOLIMBS
|
|
|
|
// High brute damage or sharp objects may damage internal organs
|
|
if(internal_organs && ( (sharp && brute >= 5) || brute >= 10) && prob(5))
|
|
// Damage an internal organ
|
|
var/datum/organ/internal/I = pick(internal_organs)
|
|
I.take_damage(brute / 2)
|
|
brute -= brute / 2
|
|
|
|
if(status & ORGAN_BROKEN && prob(40) && brute)
|
|
if (!(owner.species && (owner.species.flags & NO_PAIN)))
|
|
owner.emote("scream") //getting hit on broken hand hurts
|
|
if(used_weapon)
|
|
add_autopsy_data("[used_weapon]", brute + burn)
|
|
|
|
var/can_cut = (prob(brute*2) || sharp) && !(status & ORGAN_ROBOT)
|
|
// If the limbs can break, make sure we don't exceed the maximum damage a limb can take before breaking
|
|
if((brute_dam + burn_dam + brute + burn) < max_damage || !config.limbs_can_break)
|
|
if(brute)
|
|
if(can_cut)
|
|
createwound( CUT, brute )
|
|
else
|
|
createwound( BRUISE, brute )
|
|
if(burn)
|
|
createwound( BURN, burn )
|
|
else
|
|
//If we can't inflict the full amount of damage, spread the damage in other ways
|
|
//How much damage can we actually cause?
|
|
var/can_inflict = max_damage * config.organ_health_multiplier - (brute_dam + burn_dam)
|
|
if(can_inflict)
|
|
if (brute > 0)
|
|
//Inflict all burte damage we can
|
|
if(can_cut)
|
|
createwound( CUT, min(brute,can_inflict) )
|
|
else
|
|
createwound( BRUISE, min(brute,can_inflict) )
|
|
var/temp = can_inflict
|
|
//How much mroe damage can we inflict
|
|
can_inflict = max(0, can_inflict - brute)
|
|
//How much brute damage is left to inflict
|
|
brute = max(0, brute - temp)
|
|
|
|
if (burn > 0 && can_inflict)
|
|
//Inflict all burn damage we can
|
|
createwound(BURN, min(burn,can_inflict))
|
|
//How much burn damage is left to inflict
|
|
burn = max(0, burn - can_inflict)
|
|
//If there are still hurties to dispense
|
|
if (burn || brute)
|
|
if (status & ORGAN_ROBOT)
|
|
droplimb(1) //Robot limbs just kinda fail at full damage.
|
|
else
|
|
//List organs we can pass it to
|
|
var/list/datum/organ/external/possible_points = list()
|
|
if(parent)
|
|
possible_points += parent
|
|
if(children)
|
|
possible_points += children
|
|
if(forbidden_limbs.len)
|
|
possible_points -= forbidden_limbs
|
|
if(possible_points.len)
|
|
//And pass the pain around
|
|
var/datum/organ/external/target = pick(possible_points)
|
|
target.take_damage(brute, burn, sharp, edge, used_weapon, forbidden_limbs + src)
|
|
|
|
// sync the organ's damage with its wounds
|
|
src.update_damages()
|
|
|
|
//If limb took enough damage, try to cut or tear it off
|
|
if(body_part != UPPER_TORSO && body_part != LOWER_TORSO) //as hilarious as it is, getting hit on the chest too much shouldn't effectively gib you.
|
|
if(config.limbs_can_break && brute_dam >= max_damage * config.organ_health_multiplier)
|
|
if( (edge && prob(5 * brute)) || (brute > 20 && prob(brute)) )
|
|
droplimb(1)
|
|
return
|
|
|
|
owner.updatehealth()
|
|
|
|
var/result = update_icon()
|
|
return result
|
|
|
|
/datum/organ/external/proc/heal_damage(brute, burn, internal = 0, robo_repair = 0)
|
|
if(status & ORGAN_ROBOT && !robo_repair)
|
|
return
|
|
|
|
//Heal damage on the individual wounds
|
|
for(var/datum/wound/W in wounds)
|
|
if(brute == 0 && burn == 0)
|
|
break
|
|
|
|
// heal brute damage
|
|
if(W.damage_type == CUT || W.damage_type == BRUISE)
|
|
brute = W.heal_damage(brute)
|
|
else if(W.damage_type == BURN)
|
|
burn = W.heal_damage(burn)
|
|
|
|
if(internal)
|
|
status &= ~ORGAN_BROKEN
|
|
perma_injury = 0
|
|
|
|
//Sync the organ's damage with its wounds
|
|
src.update_damages()
|
|
owner.updatehealth()
|
|
|
|
var/result = update_icon()
|
|
return result
|
|
|
|
/*
|
|
This function completely restores a damaged organ to perfect condition.
|
|
*/
|
|
/datum/organ/external/proc/rejuvenate()
|
|
damage_state = "00"
|
|
if(status & 128) //Robotic organs stay robotic. Fix because right click rejuvinate makes IPC's organs organic.
|
|
status = 128
|
|
else
|
|
status = 0
|
|
perma_injury = 0
|
|
brute_dam = 0
|
|
burn_dam = 0
|
|
germ_level = 0
|
|
wounds.Cut()
|
|
number_wounds = 0
|
|
|
|
// handle internal organs
|
|
for(var/datum/organ/internal/current_organ in internal_organs)
|
|
current_organ.rejuvenate()
|
|
|
|
// remove embedded objects and drop them on the floor
|
|
for(var/obj/implanted_object in implants)
|
|
if(!istype(implanted_object,/obj/item/weapon/implant)) // We don't want to remove REAL implants. Just shrapnel etc.
|
|
implanted_object.loc = owner.loc
|
|
implants -= implanted_object
|
|
|
|
owner.updatehealth()
|
|
|
|
|
|
/datum/organ/external/proc/createwound(var/type = CUT, var/damage)
|
|
if(damage == 0) return
|
|
|
|
//moved this before the open_wound check so that having many small wounds for example doesn't somehow protect you from taking internal damage (because of the return)
|
|
//Possibly trigger an internal wound, too.
|
|
var/local_damage = brute_dam + burn_dam + damage
|
|
if(damage > 15 && type != BURN && local_damage > 30 && prob(damage) && !(status & ORGAN_ROBOT))
|
|
var/datum/wound/internal_bleeding/I = new (min(damage - 15, 15))
|
|
wounds += I
|
|
owner.custom_pain("You feel something rip in your [display_name]!", 1)
|
|
|
|
// first check whether we can widen an existing wound
|
|
if(wounds.len > 0 && prob(max(50+(number_wounds-1)*10,90)))
|
|
if((type == CUT || type == BRUISE) && damage >= 5)
|
|
//we need to make sure that the wound we are going to worsen is compatible with the type of damage...
|
|
var/list/compatible_wounds = list()
|
|
for (var/datum/wound/W in wounds)
|
|
if (W.can_worsen(type, damage))
|
|
compatible_wounds += W
|
|
|
|
if(compatible_wounds.len)
|
|
var/datum/wound/W = pick(compatible_wounds)
|
|
W.open_wound(damage)
|
|
if(prob(25))
|
|
//maybe have a separate message for BRUISE type damage?
|
|
owner.visible_message("\red The wound on [owner.name]'s [display_name] widens with a nasty ripping noise.",\
|
|
"\red The wound on your [display_name] widens with a nasty ripping noise.",\
|
|
"You hear a nasty ripping noise, as if flesh is being torn apart.")
|
|
return
|
|
|
|
//Creating wound
|
|
var/wound_type = get_wound_type(type, damage)
|
|
|
|
if(wound_type)
|
|
var/datum/wound/W = new wound_type(damage)
|
|
|
|
//Check whether we can add the wound to an existing wound
|
|
for(var/datum/wound/other in wounds)
|
|
if(other.can_merge(W))
|
|
other.merge_wound(W)
|
|
W = null // to signify that the wound was added
|
|
break
|
|
if(W)
|
|
wounds += W
|
|
|
|
/****************************************************
|
|
PROCESSING & UPDATING
|
|
****************************************************/
|
|
|
|
//Determines if we even need to process this organ.
|
|
|
|
/datum/organ/external/proc/need_process()
|
|
if(destspawn) //Missing limb is missing
|
|
return 0
|
|
if(status && status != ORGAN_ROBOT) // If it's robotic, that's fine it will have a status.
|
|
return 1
|
|
if(brute_dam || burn_dam)
|
|
return 1
|
|
if(last_dam != brute_dam + burn_dam) // Process when we are fully healed up.
|
|
last_dam = brute_dam + burn_dam
|
|
return 1
|
|
else
|
|
last_dam = brute_dam + burn_dam
|
|
if(germ_level)
|
|
return 1
|
|
return 0
|
|
|
|
/datum/organ/external/process()
|
|
//Dismemberment
|
|
if(status & ORGAN_DESTROYED)
|
|
if(!destspawn && config.limbs_can_break)
|
|
droplimb()
|
|
return
|
|
if(parent)
|
|
if(parent.status & ORGAN_DESTROYED)
|
|
status |= ORGAN_DESTROYED
|
|
owner.update_body(1)
|
|
return
|
|
|
|
// 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)
|
|
|
|
//Bone fracurtes
|
|
if(config.bones_can_break && brute_dam > min_broken_damage * config.organ_health_multiplier && !(status & ORGAN_ROBOT))
|
|
src.fracture()
|
|
if(!(status & ORGAN_BROKEN))
|
|
perma_injury = 0
|
|
|
|
//Infections
|
|
update_germs()
|
|
|
|
//Updating germ levels. Handles organ germ levels and necrosis.
|
|
/*
|
|
The INFECTION_LEVEL values defined in setup.dm control the time it takes to reach the different
|
|
infection levels. Since infection growth is exponential, you can adjust the time it takes to get
|
|
from one germ_level to another using the rough formula:
|
|
|
|
desired_germ_level = initial_germ_level*e^(desired_time_in_seconds/1000)
|
|
|
|
So if I wanted it to take an average of 15 minutes to get from level one (100) to level two
|
|
I would set INFECTION_LEVEL_TWO to 100*e^(15*60/1000) = 245. Note that this is the average time,
|
|
the actual time is dependent on RNG.
|
|
|
|
INFECTION_LEVEL_ONE below this germ level nothing happens, and the infection doesn't grow
|
|
INFECTION_LEVEL_TWO above this germ level the infection will start to spread to internal and adjacent organs
|
|
INFECTION_LEVEL_THREE above this germ level the player will take additional toxin damage per second, and will die in minutes without
|
|
antitox. also, above this germ level you will need to overdose on spaceacillin to reduce the germ_level.
|
|
|
|
Note that amputating the affected organ does in fact remove the infection from the player's body.
|
|
*/
|
|
/datum/organ/external/proc/update_germs()
|
|
|
|
if(status & (ORGAN_ROBOT|ORGAN_DESTROYED) || (owner.species && owner.species.flags & IS_PLANT)) //Robotic limbs shouldn't be infected, nor should nonexistant limbs.
|
|
germ_level = 0
|
|
return
|
|
|
|
if(owner.bodytemperature >= 170) //cryo stops germs from moving and doing their bad stuffs
|
|
//** Syncing germ levels with external wounds
|
|
handle_germ_sync()
|
|
|
|
//** Handle antibiotics and curing infections
|
|
handle_antibiotics()
|
|
|
|
//** Handle the effects of infections
|
|
handle_germ_effects()
|
|
|
|
/datum/organ/external/proc/handle_germ_sync()
|
|
var/antibiotics = owner.reagents.get_reagent_amount("spaceacillin")
|
|
for(var/datum/wound/W in wounds)
|
|
//Open wounds can become infected
|
|
if (owner.germ_level > W.germ_level && W.infection_check())
|
|
W.germ_level++
|
|
|
|
if (antibiotics < 5)
|
|
for(var/datum/wound/W in wounds)
|
|
//Infected wounds raise the organ's germ level
|
|
if (W.germ_level > germ_level)
|
|
germ_level++
|
|
break //limit increase to a maximum of one per second
|
|
|
|
/datum/organ/external/proc/handle_germ_effects()
|
|
var/antibiotics = owner.reagents.get_reagent_amount("spaceacillin")
|
|
|
|
if (germ_level > 0 && germ_level < INFECTION_LEVEL_ONE && prob(60)) //this could be an else clause, but it looks cleaner this way
|
|
germ_level-- //since germ_level increases at a rate of 1 per second with dirty wounds, prob(60) should give us about 5 minutes before level one.
|
|
|
|
if(germ_level >= INFECTION_LEVEL_ONE)
|
|
//having an infection raises your body temperature
|
|
var/fever_temperature = (owner.species.heat_level_1 - owner.species.body_temperature - 5)* min(germ_level/INFECTION_LEVEL_TWO, 1) + owner.species.body_temperature
|
|
//need to make sure we raise temperature fast enough to get around environmental cooling preventing us from reaching fever_temperature
|
|
owner.bodytemperature += between(0, (fever_temperature - T20C)/BODYTEMP_COLD_DIVISOR + 1, fever_temperature - owner.bodytemperature)
|
|
|
|
if(prob(round(germ_level/10)))
|
|
if (antibiotics < 5)
|
|
germ_level++
|
|
|
|
if (prob(10)) //adjust this to tweak how fast people take toxin damage from infections
|
|
owner.adjustToxLoss(1)
|
|
|
|
if(germ_level >= INFECTION_LEVEL_TWO && antibiotics < 5)
|
|
//spread the infection to internal organs
|
|
var/datum/organ/internal/target_organ = null //make internal organs become infected one at a time instead of all at once
|
|
for (var/datum/organ/internal/I in internal_organs)
|
|
if (I.germ_level > 0 && I.germ_level < min(germ_level, INFECTION_LEVEL_TWO)) //once the organ reaches whatever we can give it, or level two, switch to a different one
|
|
if (!target_organ || I.germ_level > target_organ.germ_level) //choose the organ with the highest germ_level
|
|
target_organ = I
|
|
|
|
if (!target_organ)
|
|
//figure out which organs we can spread germs to and pick one at random
|
|
var/list/candidate_organs = list()
|
|
for (var/datum/organ/internal/I in internal_organs)
|
|
if (I.germ_level < germ_level)
|
|
candidate_organs += I
|
|
if (candidate_organs.len)
|
|
target_organ = pick(candidate_organs)
|
|
|
|
if (target_organ)
|
|
target_organ.germ_level++
|
|
|
|
//spread the infection to child and parent organs
|
|
if (children)
|
|
for (var/datum/organ/external/child in children)
|
|
if (child.germ_level < germ_level && !(child.status & ORGAN_ROBOT))
|
|
if (child.germ_level < INFECTION_LEVEL_ONE*2 || prob(30))
|
|
child.germ_level++
|
|
|
|
if (parent)
|
|
if (parent.germ_level < germ_level && !(parent.status & ORGAN_ROBOT))
|
|
if (parent.germ_level < INFECTION_LEVEL_ONE*2 || prob(30))
|
|
parent.germ_level++
|
|
|
|
if(germ_level >= INFECTION_LEVEL_THREE && antibiotics < 30) //overdosing is necessary to stop severe infections
|
|
if (!(status & ORGAN_DEAD))
|
|
status |= ORGAN_DEAD
|
|
owner << "<span class='notice'>You can't feel your [display_name] anymore...</span>"
|
|
owner.update_body(1)
|
|
|
|
germ_level++
|
|
owner.adjustToxLoss(1)
|
|
|
|
//Updating wounds. Handles wound natural I had some free spachealing, internal bleedings and infections
|
|
/datum/organ/external/proc/update_wounds()
|
|
|
|
if((status & ORGAN_ROBOT) || (status & ORGAN_ADV_ROBOT)) //Robotic limbs don't heal or get worse.
|
|
return
|
|
|
|
for(var/datum/wound/W in wounds)
|
|
// wounds can disappear after 10 minutes at the earliest
|
|
if(W.damage <= 0 && W.created + 10 * 10 * 60 <= world.time)
|
|
wounds -= W
|
|
continue
|
|
// let the GC handle the deletion of the wound
|
|
|
|
// Internal wounds get worse over time. Low temperatures (cryo) stop them.
|
|
if(W.internal && owner.bodytemperature >= 170)
|
|
var/bicardose = owner.reagents.get_reagent_amount("bicaridine")
|
|
var/inaprovaline = owner.reagents.get_reagent_amount("inaprovaline")
|
|
if(!(W.can_autoheal() || (bicardose && inaprovaline))) //bicaridine and inaprovaline stop internal wounds from growing bigger with time, unless it is so small that it is already healing
|
|
W.open_wound(0.1 * wound_update_accuracy)
|
|
if(bicardose >= 30) //overdose of bicaridine begins healing IB
|
|
W.damage = max(0, W.damage - 0.2)
|
|
|
|
owner.vessel.remove_reagent("blood", wound_update_accuracy * W.damage/40) //line should possibly be moved to handle_blood, so all the bleeding stuff is in one place.
|
|
if(prob(1 * wound_update_accuracy))
|
|
owner.custom_pain("You feel a stabbing pain in your [display_name]!",1)
|
|
|
|
// slow healing
|
|
var/heal_amt = 0
|
|
|
|
// if damage >= 50 AFTER treatment then it's probably too severe to heal within the timeframe of a round.
|
|
if (W.can_autoheal() && W.wound_damage() < 50)
|
|
heal_amt += 0.5
|
|
|
|
//we only update wounds once in [wound_update_accuracy] ticks so have to emulate realtime
|
|
heal_amt = heal_amt * wound_update_accuracy
|
|
//configurable regen speed woo, no-regen hardcore or instaheal hugbox, choose your destiny
|
|
heal_amt = heal_amt * config.organ_regeneration_multiplier
|
|
// amount of healing is spread over all the wounds
|
|
heal_amt = heal_amt / (wounds.len + 1)
|
|
// making it look prettier on scanners
|
|
heal_amt = round(heal_amt,0.1)
|
|
W.heal_damage(heal_amt)
|
|
|
|
// Salving also helps against infection
|
|
if(W.germ_level > 0 && W.salved && prob(2))
|
|
W.disinfected = 1
|
|
W.germ_level = 0
|
|
|
|
// sync the organ's damage with its wounds
|
|
src.update_damages()
|
|
if (update_icon())
|
|
owner.UpdateDamageIcon(1)
|
|
|
|
//Updates brute_damn and burn_damn from wound damages. Updates BLEEDING status.
|
|
/datum/organ/external/proc/update_damages()
|
|
number_wounds = 0
|
|
brute_dam = 0
|
|
burn_dam = 0
|
|
status &= ~ORGAN_BLEEDING
|
|
var/clamped = 0
|
|
|
|
var/mob/living/carbon/human/H
|
|
if(istype(owner,/mob/living/carbon/human))
|
|
H = owner
|
|
|
|
for(var/datum/wound/W in wounds)
|
|
if(!W.internal) //so IB doesn't count towards crit/paincrit
|
|
if(W.damage_type == CUT || W.damage_type == BRUISE)
|
|
brute_dam += W.damage
|
|
else if(W.damage_type == BURN)
|
|
burn_dam += W.damage
|
|
|
|
if(!(status & ORGAN_ROBOT) && W.bleeding() && (H && !(H.species.flags & NO_BLOOD)))
|
|
W.bleed_timer--
|
|
status |= ORGAN_BLEEDING
|
|
|
|
clamped |= W.clamped
|
|
|
|
number_wounds += W.amount
|
|
|
|
if (open && !clamped && (H && !(H.species.flags & NO_BLOOD))) //things tend to bleed if they are CUT OPEN
|
|
status |= ORGAN_BLEEDING
|
|
|
|
|
|
/datum/organ/external/proc/can_take_covering() // is this organ functional enough to take a covering
|
|
if (status&(ORGAN_DESTROYED|ORGAN_BROKEN|ORGAN_DEAD))
|
|
return
|
|
return (burn_dam + brute_dam) <= (max_damage * 0.1) // you get hurt you're going to lose your covering
|
|
|
|
|
|
// new damage icon system
|
|
// adjusted to set damage_state to brute/burn code only (without r_name0 as before)
|
|
/datum/organ/external/proc/update_icon()
|
|
var/n_is = damage_state_text()
|
|
if (n_is != damage_state)
|
|
damage_state = n_is
|
|
return TRUE
|
|
if (covering) // check to see if we lose the covering
|
|
if (covering.coverage==SYNTHETIC_COVERING_WORKING)
|
|
if (!can_take_covering()) // if your limbs get badly damaged you lose the covering
|
|
covering.coverage = SYNTHETIC_COVERING_DAMAGED
|
|
owner.update_body(TRUE)
|
|
return TRUE
|
|
return FALSE
|
|
|
|
/datum/organ/external/head/update_icon()
|
|
var/result = ..()
|
|
if (result)
|
|
owner.update_hair()
|
|
return result
|
|
|
|
|
|
// new damage icon system
|
|
// returns just the brute/burn damage code
|
|
/datum/organ/external/proc/damage_state_text()
|
|
if(status & ORGAN_DESTROYED)
|
|
return "--"
|
|
|
|
var/tburn = 0
|
|
var/tbrute = 0
|
|
|
|
if(burn_dam ==0)
|
|
tburn =0
|
|
else if (burn_dam < (max_damage * 0.25 / 2))
|
|
tburn = 1
|
|
else if (burn_dam < (max_damage * 0.75 / 2))
|
|
tburn = 2
|
|
else
|
|
tburn = 3
|
|
|
|
if (brute_dam == 0)
|
|
tbrute = 0
|
|
else if (brute_dam < (max_damage * 0.25 / 2))
|
|
tbrute = 1
|
|
else if (brute_dam < (max_damage * 0.75 / 2))
|
|
tbrute = 2
|
|
else
|
|
tbrute = 3
|
|
|
|
|
|
return "[tbrute][tburn]"
|
|
|
|
/****************************************************
|
|
DISMEMBERMENT
|
|
****************************************************/
|
|
|
|
//Recursive setting of all child organs to amputated
|
|
/datum/organ/external/proc/setAmputatedTree()
|
|
for(var/datum/organ/external/O in children)
|
|
O.amputated=amputated
|
|
O.setAmputatedTree()
|
|
|
|
//Handles dismemberment
|
|
/datum/organ/external/proc/droplimb(var/override = 0,var/no_explode = 0,var/amputation=0)
|
|
if(destspawn) return
|
|
if(override)
|
|
status |= ORGAN_DESTROYED
|
|
if(status & ORGAN_DESTROYED)
|
|
if(body_part == UPPER_TORSO)
|
|
return
|
|
|
|
src.status &= ~ORGAN_BROKEN
|
|
src.status &= ~ORGAN_BLEEDING
|
|
src.status &= ~ORGAN_SPLINTED
|
|
src.status &= ~ORGAN_DEAD
|
|
for(var/implant in implants)
|
|
del(implant)
|
|
|
|
germ_level = 0
|
|
|
|
// If any organs are attached to this, destroy them
|
|
for(var/datum/organ/external/O in children)
|
|
O.droplimb(1, no_explode, amputation)
|
|
|
|
//Replace all wounds on that arm with one wound on parent organ.
|
|
wounds.Cut()
|
|
if (parent && !amputation)
|
|
var/datum/wound/W
|
|
if(max_damage < 50)
|
|
W = new/datum/wound/lost_limb/small(max_damage)
|
|
else
|
|
W = new/datum/wound/lost_limb(max_damage)
|
|
parent.wounds += W
|
|
parent.update_damages()
|
|
update_damages()
|
|
|
|
var/obj/organ //Dropped limb object
|
|
var/list/dropped_items
|
|
switch(body_part)
|
|
if(HEAD)
|
|
organ = new /obj/item/weapon/organ/head(owner.loc, owner)
|
|
dropped_items = list(owner.glasses, owner.head, owner.l_ear, owner.r_ear, owner.wear_mask)
|
|
if(ARM_RIGHT)
|
|
if(status & ORGAN_ROBOT)
|
|
organ = new /obj/item/robot_parts/r_arm(owner.loc)
|
|
else
|
|
organ= new /obj/item/weapon/organ/r_arm(owner.loc, owner)
|
|
if(ARM_LEFT)
|
|
if(status & ORGAN_ROBOT)
|
|
organ= new /obj/item/robot_parts/l_arm(owner.loc)
|
|
else
|
|
organ= new /obj/item/weapon/organ/l_arm(owner.loc, owner)
|
|
if(LEG_RIGHT)
|
|
if(status & ORGAN_ROBOT)
|
|
organ = new /obj/item/robot_parts/r_leg(owner.loc)
|
|
else
|
|
organ= new /obj/item/weapon/organ/r_leg(owner.loc, owner)
|
|
if(LEG_LEFT)
|
|
if(status & ORGAN_ROBOT)
|
|
organ = new /obj/item/robot_parts/l_leg(owner.loc)
|
|
else
|
|
organ= new /obj/item/weapon/organ/l_leg(owner.loc, owner)
|
|
if(HAND_RIGHT)
|
|
if(!(status & ORGAN_ROBOT))
|
|
organ= new /obj/item/weapon/organ/r_hand(owner.loc, owner)
|
|
dropped_items = list(owner.gloves) //should probably make it so that you can still wear gloves if you have one hand
|
|
if(HAND_LEFT)
|
|
if(!(status & ORGAN_ROBOT))
|
|
organ= new /obj/item/weapon/organ/l_hand(owner.loc, owner)
|
|
dropped_items = list(owner.gloves)
|
|
if(FOOT_RIGHT)
|
|
if(!(status & ORGAN_ROBOT))
|
|
organ= new /obj/item/weapon/organ/r_foot/(owner.loc, owner)
|
|
dropped_items = list(owner.shoes)
|
|
if(FOOT_LEFT)
|
|
if(!(status & ORGAN_ROBOT))
|
|
organ = new /obj/item/weapon/organ/l_foot(owner.loc, owner)
|
|
dropped_items = list(owner.shoes)
|
|
if(dropped_items)
|
|
for(var/obj/O in dropped_items)
|
|
owner.remove_from_mob(O)
|
|
|
|
destspawn = 1
|
|
//Robotic limbs explode if sabotaged.
|
|
if(status & ORGAN_ROBOT && !no_explode && sabotaged)
|
|
owner.visible_message("\red \The [owner]'s [display_name] explodes violently!",\
|
|
"\red <b>Your [display_name] explodes!</b>",\
|
|
"You hear an explosion!")
|
|
explosion(get_turf(owner),-1,-1,2,3)
|
|
var/datum/effect/effect/system/spark_spread/spark_system = new /datum/effect/effect/system/spark_spread()
|
|
spark_system.set_up(5, 0, owner)
|
|
spark_system.attach(owner)
|
|
spark_system.start()
|
|
spawn(10)
|
|
del(spark_system)
|
|
|
|
owner.visible_message("\red [owner.name]'s [display_name] flies off in an arc.",\
|
|
"<span class='moderate'><b>Your [display_name] goes flying off!</b></span>",\
|
|
"You hear a terrible sound of ripping tendons and flesh.")
|
|
|
|
//Throw organs around
|
|
if(istype(owner.loc,/turf) && organ)
|
|
step(organ,pick(cardinal))
|
|
|
|
owner.update_body(1)
|
|
|
|
// OK so maybe your limb just flew off, but if it was attached to a pair of cuffs then hooray! Freedom!
|
|
release_restraints()
|
|
|
|
if(vital)
|
|
owner.death()
|
|
|
|
/****************************************************
|
|
HELPERS
|
|
****************************************************/
|
|
|
|
/datum/organ/external/proc/release_restraints()
|
|
if (owner.handcuffed && body_part in list(ARM_LEFT, ARM_RIGHT, HAND_LEFT, HAND_RIGHT))
|
|
owner.visible_message(\
|
|
"\The [owner.handcuffed.name] falls off of [owner.name].",\
|
|
"\The [owner.handcuffed.name] falls off you.")
|
|
|
|
owner.drop_from_inventory(owner.handcuffed)
|
|
|
|
if (owner.legcuffed && body_part in list(FOOT_LEFT, FOOT_RIGHT, LEG_LEFT, LEG_RIGHT))
|
|
owner.visible_message(\
|
|
"\The [owner.legcuffed.name] falls off of [owner.name].",\
|
|
"\The [owner.legcuffed.name] falls off you.")
|
|
|
|
owner.drop_from_inventory(owner.legcuffed)
|
|
|
|
/datum/organ/external/proc/bandage()
|
|
var/rval = 0
|
|
src.status &= ~ORGAN_BLEEDING
|
|
for(var/datum/wound/W in wounds)
|
|
if(W.internal) continue
|
|
rval |= !W.bandaged
|
|
W.bandaged = 1
|
|
return rval
|
|
|
|
/datum/organ/external/proc/disinfect()
|
|
var/rval = 0
|
|
for(var/datum/wound/W in wounds)
|
|
if(W.internal) continue
|
|
rval |= !W.disinfected
|
|
W.disinfected = 1
|
|
W.germ_level = 0
|
|
return rval
|
|
|
|
/datum/organ/external/proc/clamp()
|
|
var/rval = 0
|
|
src.status &= ~ORGAN_BLEEDING
|
|
for(var/datum/wound/W in wounds)
|
|
if(W.internal) continue
|
|
rval |= !W.clamped
|
|
W.clamped = 1
|
|
return rval
|
|
|
|
/datum/organ/external/proc/salve()
|
|
var/rval = 0
|
|
for(var/datum/wound/W in wounds)
|
|
rval |= !W.salved
|
|
W.salved = 1
|
|
return rval
|
|
|
|
/datum/organ/external/proc/fracture()
|
|
|
|
if(status & ORGAN_BROKEN)
|
|
return
|
|
|
|
owner.visible_message(\
|
|
"\red You hear a loud cracking sound coming from \the [owner].",\
|
|
"\red <b>Something feels like it shattered in your [display_name]!</b>",\
|
|
"You hear a sickening crack.")
|
|
|
|
if(owner.species && !(owner.species.flags & NO_PAIN))
|
|
owner.emote("scream")
|
|
|
|
status |= ORGAN_BROKEN
|
|
broken_description = pick("broken","fracture","hairline fracture")
|
|
perma_injury = brute_dam
|
|
|
|
// Fractures have a chance of getting you out of restraints
|
|
if (prob(25))
|
|
release_restraints()
|
|
|
|
// This is mostly for the ninja suit to stop ninja being so crippled by breaks.
|
|
// TODO: consider moving this to a suit proc or process() or something during
|
|
// hardsuit rewrite.
|
|
if(!(status & ORGAN_SPLINTED) && istype(owner,/mob/living/carbon/human))
|
|
|
|
var/mob/living/carbon/human/H = owner
|
|
|
|
if(H.wear_suit && istype(H.wear_suit,/obj/item/clothing/suit/space))
|
|
|
|
var/obj/item/clothing/suit/space/suit = H.wear_suit
|
|
|
|
if(isnull(suit.supporting_limbs))
|
|
return
|
|
|
|
owner << "You feel \the [suit] constrict about your [display_name], supporting it."
|
|
status |= ORGAN_SPLINTED
|
|
suit.supporting_limbs |= src
|
|
return
|
|
|
|
/datum/organ/external/proc/mend_fracture()
|
|
if(status & ORGAN_ROBOT)
|
|
return 0 //ORGAN_BROKEN doesn't have the same meaning for robot limbs
|
|
if(brute_dam > min_broken_damage * config.organ_health_multiplier)
|
|
return 0 //will just immediately fracture again
|
|
|
|
status &= ~ORGAN_BROKEN
|
|
return 1
|
|
|
|
/datum/organ/external/proc/robotize()
|
|
src.status &= ~ORGAN_BROKEN
|
|
src.status &= ~ORGAN_BLEEDING
|
|
src.status &= ~ORGAN_SPLINTED
|
|
src.status &= ~ORGAN_CUT_AWAY
|
|
src.status &= ~ORGAN_ATTACHABLE
|
|
src.status &= ~ORGAN_DESTROYED
|
|
src.status |= ORGAN_ROBOT
|
|
src.destspawn = 0
|
|
for (var/datum/organ/external/T in children)
|
|
if(T)
|
|
T.robotize()
|
|
|
|
/datum/organ/external/proc/robotize_advanced()
|
|
status |= ORGAN_ADV_ROBOT
|
|
for (var/datum/organ/external/T in children)
|
|
if (T)
|
|
T.robotize_advanced()
|
|
|
|
/datum/organ/external/proc/mutate()
|
|
src.status |= ORGAN_MUTATED
|
|
owner.update_body()
|
|
|
|
/datum/organ/external/proc/unmutate()
|
|
src.status &= ~ORGAN_MUTATED
|
|
owner.update_body()
|
|
|
|
/datum/organ/external/proc/get_damage() //returns total damage
|
|
return max(brute_dam + burn_dam - perma_injury, perma_injury) //could use health?
|
|
|
|
/datum/organ/external/proc/has_infected_wound()
|
|
for(var/datum/wound/W in wounds)
|
|
if(W.germ_level > INFECTION_LEVEL_ONE)
|
|
return 1
|
|
return 0
|
|
|
|
|
|
/datum/organ/external/proc/get_icon_key()
|
|
if (status & ORGAN_DESTROYED)
|
|
return "L" // l for lost
|
|
if (status & ORGAN_DEAD)
|
|
return "D" // d for dead
|
|
if (status & ORGAN_ROBOT)
|
|
return get_synthetic_icon_key()
|
|
return "G" // regular old limb
|
|
|
|
|
|
/datum/organ/external/proc/valid_covering()
|
|
if (status & ORGAN_ROBOT)
|
|
if (covering)
|
|
return (covering.coverage) // is our covering working?
|
|
return FALSE // if we have no covering at all
|
|
return TRUE // squishies always have skin
|
|
|
|
|
|
/datum/organ/external/proc/get_synthetic_icon_key()
|
|
if (!covering) // no covering at all, this should not happen
|
|
return "R" // regular old robot
|
|
return covering.get_icon_key()
|
|
|
|
|
|
/datum/organ/external/proc/get_synthetic_icon()
|
|
if (!covering) // no covering at all, this should not happen
|
|
return new /icon('icons/mob/human_races/robotic.dmi', "[icon_name][get_gender_string()]")
|
|
return covering.get_icon()
|
|
|
|
|
|
/datum/organ/external/proc/get_gender_string()
|
|
if (!gendered) // most organs aren't gender specific
|
|
return ""
|
|
if (owner) // if we're a gender specific organ with an owner
|
|
return (owner.gender == FEMALE ? "_f" : "_m")
|
|
return "_f"
|
|
|
|
|
|
/datum/organ/external/get_icon(var/icon/race_icon, var/icon/deform_icon, var/list/skin_info)
|
|
if (status & ORGAN_ROBOT)
|
|
return get_synthetic_icon()
|
|
var/icon/result = new /icon((status & ORGAN_MUTATED) ? deform_icon : race_icon, "[icon_name][get_gender_string()]")
|
|
if (skin_info["blend"])
|
|
result.Blend(skin_info["rgb"],skin_info["mode"])
|
|
return result
|
|
|
|
|
|
/datum/organ/external/proc/is_usable()
|
|
return !(status & (ORGAN_DESTROYED|ORGAN_MUTATED|ORGAN_DEAD))
|
|
|
|
/datum/organ/external/proc/is_broken()
|
|
return ((status & ORGAN_BROKEN) && !(status & ORGAN_SPLINTED))
|
|
|
|
/datum/organ/external/proc/is_malfunctioning()
|
|
return ((status & ORGAN_ROBOT) && prob(brute_dam + burn_dam))
|
|
|
|
//for arms and hands
|
|
/datum/organ/external/proc/process_grasp(var/obj/item/c_hand, var/hand_name)
|
|
if (!c_hand)
|
|
return
|
|
|
|
if(is_broken())
|
|
owner.u_equip(c_hand)
|
|
var/emote_scream = pick("screams in pain and ", "lets out a sharp cry and ", "cries out and ")
|
|
owner.emote("me", 1, "[(owner.species && owner.species.flags & NO_PAIN) ? "" : emote_scream ]drops what they were holding in their [hand_name]!")
|
|
if(is_malfunctioning())
|
|
owner.u_equip(c_hand)
|
|
owner.emote("me", 1, "drops what they were holding, their [hand_name] malfunctioning!")
|
|
var/datum/effect/effect/system/spark_spread/spark_system = new /datum/effect/effect/system/spark_spread()
|
|
spark_system.set_up(5, 0, owner)
|
|
spark_system.attach(owner)
|
|
spark_system.start()
|
|
spawn(10)
|
|
del(spark_system)
|
|
|
|
/datum/organ/external/proc/embed(var/obj/item/weapon/W, var/silent = 0)
|
|
if(!silent)
|
|
owner.visible_message("<span class='danger'>\The [W] sticks in the wound!</span>")
|
|
implants += W
|
|
owner.embedded_flag = 1
|
|
owner.verbs += /mob/proc/yank_out_object
|
|
W.add_blood(owner)
|
|
if(ismob(W.loc))
|
|
var/mob/living/H = W.loc
|
|
H.drop_item()
|
|
W.loc = owner
|
|
|
|
/****************************************************
|
|
ORGAN DEFINES
|
|
****************************************************/
|
|
|
|
/datum/organ/external/chest
|
|
name = "chest"
|
|
icon_name = "torso"
|
|
display_name = "chest"
|
|
max_damage = 75
|
|
min_broken_damage = 40
|
|
body_part = UPPER_TORSO
|
|
vital = 1
|
|
encased = "ribcage"
|
|
gendered = TRUE
|
|
|
|
/datum/organ/external/groin
|
|
name = "groin"
|
|
icon_name = "groin"
|
|
display_name = "groin"
|
|
max_damage = 50
|
|
min_broken_damage = 30
|
|
body_part = LOWER_TORSO
|
|
vital = 1
|
|
gendered = TRUE
|
|
|
|
/datum/organ/external/l_arm
|
|
name = "l_arm"
|
|
display_name = "left arm"
|
|
icon_name = "l_arm"
|
|
max_damage = 50
|
|
min_broken_damage = 20
|
|
body_part = ARM_LEFT
|
|
|
|
process()
|
|
..()
|
|
process_grasp(owner.l_hand, "left hand")
|
|
|
|
/datum/organ/external/l_leg
|
|
name = "l_leg"
|
|
display_name = "left leg"
|
|
icon_name = "l_leg"
|
|
max_damage = 50
|
|
min_broken_damage = 20
|
|
body_part = LEG_LEFT
|
|
icon_position = LEFT
|
|
|
|
/datum/organ/external/r_arm
|
|
name = "r_arm"
|
|
display_name = "right arm"
|
|
icon_name = "r_arm"
|
|
max_damage = 50
|
|
min_broken_damage = 20
|
|
body_part = ARM_RIGHT
|
|
|
|
process()
|
|
..()
|
|
process_grasp(owner.r_hand, "right hand")
|
|
|
|
/datum/organ/external/r_leg
|
|
name = "r_leg"
|
|
display_name = "right leg"
|
|
icon_name = "r_leg"
|
|
max_damage = 50
|
|
min_broken_damage = 20
|
|
body_part = LEG_RIGHT
|
|
icon_position = RIGHT
|
|
|
|
/datum/organ/external/l_foot
|
|
name = "l_foot"
|
|
display_name = "left foot"
|
|
icon_name = "l_foot"
|
|
max_damage = 30
|
|
min_broken_damage = 15
|
|
body_part = FOOT_LEFT
|
|
icon_position = LEFT
|
|
|
|
/datum/organ/external/r_foot
|
|
name = "r_foot"
|
|
display_name = "right foot"
|
|
icon_name = "r_foot"
|
|
max_damage = 30
|
|
min_broken_damage = 15
|
|
body_part = FOOT_RIGHT
|
|
icon_position = RIGHT
|
|
|
|
/datum/organ/external/r_hand
|
|
name = "r_hand"
|
|
display_name = "right hand"
|
|
icon_name = "r_hand"
|
|
max_damage = 30
|
|
min_broken_damage = 15
|
|
body_part = HAND_RIGHT
|
|
|
|
process()
|
|
..()
|
|
process_grasp(owner.r_hand, "right hand")
|
|
|
|
/datum/organ/external/l_hand
|
|
name = "l_hand"
|
|
display_name = "left hand"
|
|
icon_name = "l_hand"
|
|
max_damage = 30
|
|
min_broken_damage = 15
|
|
body_part = HAND_LEFT
|
|
|
|
process()
|
|
..()
|
|
process_grasp(owner.l_hand, "left hand")
|
|
|
|
/datum/organ/external/head
|
|
name = "head"
|
|
icon_name = "head"
|
|
display_name = "head"
|
|
max_damage = 75
|
|
min_broken_damage = 40
|
|
body_part = HEAD
|
|
var/disfigured = 0
|
|
vital = 1
|
|
encased = "skull"
|
|
gendered = TRUE
|
|
|
|
|
|
/datum/organ/external/head/take_damage(brute, burn, sharp, edge, used_weapon = null, list/forbidden_limbs = list())
|
|
..(brute, burn, sharp, edge, used_weapon, forbidden_limbs)
|
|
if (!disfigured)
|
|
if (brute_dam > 40)
|
|
if (prob(50))
|
|
disfigure("brute")
|
|
if (burn_dam > 40)
|
|
disfigure("burn")
|
|
|
|
/datum/organ/external/head/proc/disfigure(var/type = "brute")
|
|
if (disfigured)
|
|
return
|
|
if(type == "brute")
|
|
owner.visible_message("\red You hear a sickening cracking sound coming from \the [owner]'s face.", \
|
|
"\red <b>Your face becomes unrecognizible mangled mess!</b>", \
|
|
"\red You hear a sickening crack.")
|
|
else
|
|
owner.visible_message("\red [owner]'s face melts away, turning into mangled mess!", \
|
|
"\red <b>Your face melts off!</b>", \
|
|
"\red You hear a sickening sizzle.")
|
|
disfigured = 1
|
|
|
|
/****************************************************
|
|
EXTERNAL ORGAN ITEMS
|
|
****************************************************/
|
|
|
|
obj/item/weapon/organ
|
|
icon = 'icons/mob/human_races/r_human.dmi'
|
|
var/op_stage = 0
|
|
var/list/organs_internal = list()
|
|
|
|
|
|
obj/item/weapon/organ/New(loc, mob/living/carbon/human/H)
|
|
..(loc)
|
|
if(!istype(H))
|
|
return
|
|
if(H.dna)
|
|
if(!blood_DNA)
|
|
blood_DNA = list()
|
|
blood_DNA[H.dna.unique_enzymes] = H.dna.b_type
|
|
|
|
// Transferring over organs from the host.
|
|
for(var/datum/organ/internal/I in H.internal_organs)
|
|
if(I.parent_organ != name)
|
|
continue
|
|
var/obj/item/organ/new_organ_object = I.remove()
|
|
if(new_organ_object && istype(new_organ_object))
|
|
new_organ_object.removed(H)
|
|
if(new_organ_object.organ_data)
|
|
organs_internal |= new_organ_object.organ_data
|
|
new_organ_object.loc = src // put the organ inside the severed external organ
|
|
// Forming icon for the limb
|
|
// Setting base icon for this mob's race
|
|
var/icon/base
|
|
if(H.species && H.species.icobase)
|
|
base = icon(H.species.icobase)
|
|
else
|
|
base = icon('icons/mob/human_races/r_human.dmi')
|
|
if(base) // handle skin colours
|
|
var/list/skin_info = H.skin_colour_info() // get the skin tone info
|
|
base.Blend(skin_info["rgb"],skin_info["mode"])
|
|
icon = base
|
|
set_dir(SOUTH)
|
|
src.transform = turn(src.transform, rand(70,130))
|
|
|
|
|
|
/****************************************************
|
|
EXTERNAL ORGAN ITEMS DEFINES
|
|
****************************************************/
|
|
|
|
obj/item/weapon/organ/l_arm
|
|
name = "left arm"
|
|
icon_state = "l_arm"
|
|
obj/item/weapon/organ/l_foot
|
|
name = "left foot"
|
|
icon_state = "l_foot"
|
|
obj/item/weapon/organ/l_hand
|
|
name = "left hand"
|
|
icon_state = "l_hand"
|
|
obj/item/weapon/organ/l_leg
|
|
name = "left leg"
|
|
icon_state = "l_leg"
|
|
obj/item/weapon/organ/r_arm
|
|
name = "right arm"
|
|
icon_state = "r_arm"
|
|
obj/item/weapon/organ/r_foot
|
|
name = "right foot"
|
|
icon_state = "r_foot"
|
|
obj/item/weapon/organ/r_hand
|
|
name = "right hand"
|
|
icon_state = "r_hand"
|
|
obj/item/weapon/organ/r_leg
|
|
name = "right leg"
|
|
icon_state = "r_leg"
|
|
obj/item/weapon/organ/head
|
|
name = "head"
|
|
icon_state = "head_m"
|
|
var/mob/living/carbon/brain/brainmob
|
|
|
|
/obj/item/weapon/organ/head/posi
|
|
name = "robotic head"
|
|
|
|
obj/item/weapon/organ/head/New(loc, mob/living/carbon/human/H)
|
|
if(istype(H))
|
|
src.icon_state = H.gender == MALE? "head_m" : "head_f"
|
|
..()
|
|
//Add (facial) hair.
|
|
if(H.f_style)
|
|
var/datum/sprite_accessory/facial_hair_style = facial_hair_styles_list[H.f_style]
|
|
if(facial_hair_style)
|
|
var/icon/facial = new/icon("icon" = facial_hair_style.icon, "icon_state" = "[facial_hair_style.icon_state]_s")
|
|
if(facial_hair_style.do_colouration)
|
|
facial.Blend(rgb(H.r_facial, H.g_facial, H.b_facial), ICON_ADD)
|
|
|
|
overlays.Add(facial) // icon.Blend(facial, ICON_OVERLAY)
|
|
|
|
if(H.h_style && !(H.head && (H.head.flags & BLOCKHEADHAIR)))
|
|
var/datum/sprite_accessory/hair_style = hair_styles_list[H.h_style]
|
|
if(hair_style)
|
|
var/icon/hair = new/icon("icon" = hair_style.icon, "icon_state" = "[hair_style.icon_state]_s")
|
|
if(hair_style.do_colouration)
|
|
hair.Blend(rgb(H.r_hair, H.g_hair, H.b_hair), ICON_ADD)
|
|
|
|
overlays.Add(hair) //icon.Blend(hair, ICON_OVERLAY)
|
|
|
|
name = "[H.real_name]'s head"
|
|
H.regenerate_icons()
|
|
|
|
obj/item/weapon/organ/attackby(obj/item/weapon/W as obj, mob/user as mob)
|
|
switch(op_stage)
|
|
if(0)
|
|
if(istype(W,/obj/item/weapon/scalpel))
|
|
user.visible_message("<span class='danger'><b>[user]</b> cuts [src] open with [W]!")
|
|
op_stage++
|
|
return
|
|
if(1)
|
|
if(istype(W,/obj/item/weapon/retractor))
|
|
user.visible_message("<span class='danger'><b>[user]</b> cracks [src] open like an egg with [W]!")
|
|
op_stage++
|
|
return
|
|
if(2)
|
|
if(istype(W,/obj/item/weapon/hemostat))
|
|
if(contents.len)
|
|
var/obj/item/organ/removing = pick(contents)
|
|
var/exposed_result
|
|
removing.loc = get_turf(user.loc)
|
|
if(istype(removing))
|
|
var/obj/item/organ/removed_organ = removing
|
|
organs_internal -= removed_organ.organ_data
|
|
exposed_result = removing.exposed_to_the_world()
|
|
if(!(user.l_hand && user.r_hand))
|
|
user.put_in_hands((isnull(exposed_result)) ? removing : exposed_result)
|
|
user.visible_message("<span class='danger'><b>[user]</b> extracts [removing] from [src] with [W]!")
|
|
else
|
|
user.visible_message("<span class='danger'><b>[user]</b> fishes around fruitlessly in [src] with [W].")
|
|
return
|
|
..()
|