/****************************************************
EXTERNAL ORGANS
****************************************************/
/datum/organ/external
name = "external"
var/datum/species/species
var/icon_name = null
var/body_part = null
var/icon_position = 0
var/obj/item/organ_item = null //The actual item used to make the organ
var/list/slots_to_drop
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 = "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/has_fat = 0 //Has a _fat variant
/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(!is_robotic()) //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, 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(!is_existing()) //No limb there
return 0
if(!is_organic())
brute *= 0.66 //~2/3 damage for ROBOLIMBS
burn *= (status & (ORGAN_PEG) ? 2 : 0.66) //~2/3 damage for ROBOLIMBS 2x for peg
else
if(owner.species)
if(owner.species.brute_mod)
brute *= owner.species.brute_mod
if(owner.species.burn_mod)
burn *= owner.species.burn_mod
//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(((sharp || is_peg()) && prob((5 * brute) * sharp)) || (brute > 20 && prob(2 * brute))) //sharp things have a greater chance to sever based on how sharp they are
droplimb(1)
return
else if((config.limbs_can_break && sharp == 100) || ((sharp >= 2) && (config.limbs_can_break && brute_dam >= (max_damage * config.organ_health_multiplier)/sharp))) //items of exceptional sharpness are capable of severing the limb below its damage threshold, the necessary threshold scaling inversely with sharpness
if(prob((5 * (brute * sharp)) * (sharp - 1))) //the same chance multiplier based on sharpness applies here as well
droplimb(1)
return
//High brute damage or sharp objects may damage internal organs
if(internal_organs != null)
if((sharp && brute >= 5) || brute >= 10) if(prob(5))
//Damage an internal organ
var/datum/organ/internal/I = pick(internal_organs)
I.take_damage(brute / 2)
brute -= brute / 2
if(is_broken() && prob(40) && brute)
owner.emote("scream", , , 1) //Getting hit on broken and unsplinted limbs hurts
if(used_weapon)
add_autopsy_data("[used_weapon]", brute + burn)
var/can_cut = (prob(brute * 2) || sharp) && is_organic()
//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(!is_organic())
droplimb(1) //Non-organic limbs just drop off with no further complications
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()
owner.updatehealth()
var/result = update_icon()
return result
/datum/organ/external/proc/heal_damage(brute, burn, internal = 0, robo_repair = 0)
if(is_robotic() && !robo_repair) //This item can't fix robotic limbs
return
if(is_peg()) //We can't fix peg legs at all
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"
//Robotic organs stay robotic. Fix because right click rejuvinate makes IPC's organs organic.
//N3X: Use bitmask to exclude shit we don't want.
status = status & (ORGAN_ROBOT|ORGAN_PEG)
perma_injury = 0
brute_dam = 0
burn_dam = 0
cancer_stage = 0
germ_level = 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 || damage < 0) //We weren't passed a damage value, or it's negative for some reason
return
//First check whether we can widen an existing wound
if(wounds.len > 0 && prob(max(50 + owner.number_wounds * 10, 100)))
if((type == CUT || type == BRUISE) && damage >= 5)
var/datum/wound/W = pick(wounds)
if(W.amount == 1 && W.started_healing())
W.open_wound(damage)
if(prob(25))
owner.visible_message("The wound on [owner.name]'s [display_name] widens with a nasty ripping sound.", \
"The wound on your [display_name] widens with a nasty ripping sound.", \
"You hear a nasty ripping noise, as if flesh is being torn apart.")
return
//Creating wound
var/datum/wound/W
var/size = min(max(1, damage/10), 6)
//Possible types of wound
var/list/size_names = list()
switch(type)
if(CUT)
size_names = typesof(/datum/wound/cut/) - /datum/wound/cut/
if(BRUISE)
size_names = typesof(/datum/wound/bruise/) - /datum/wound/bruise/
if(BURN)
size_names = typesof(/datum/wound/burn/) - /datum/wound/burn/
size = min(size,size_names.len)
var/wound_type = size_names[size]
W = new wound_type(damage)
//Possibly trigger an internal wound, too.
var/local_damage = brute_dam + burn_dam + damage
if(damage > 10 && type != BURN && local_damage > 20 && prob(damage) && is_organic() && !(owner.species && owner.species.flags & NO_BLOOD))
var/internal_bleeding = 0
for(var/datum/wound/Wound in wounds)
if(Wound.internal)
internal_bleeding = 1
break
if(!internal_bleeding)
var/datum/wound/internal_bleeding/I = new (15)
wounds += I
owner.custom_pain("You feel something rip in your [display_name]!", 1)
//Check whether we can add the wound to an existing wound
for(var/datum/wound/other in wounds)
if(other.desc == W.desc)
//Okay, add it!
other.damage += W.damage
other.amount += 1
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(status && !is_organic()) //If it's non-organic, 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
last_dam = brute_dam + burn_dam
return 0
/datum/organ/external/process()
//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)
droplimb()
return
if(parent)
if(parent.status & ORGAN_DESTROYED)
status |= ORGAN_DESTROYED
owner.update_body(1)
return
//Bone fracurtes
if(config.bones_can_break && brute_dam > min_broken_damage * config.organ_health_multiplier && !(status & (ORGAN_ROBOT|ORGAN_PEG)))
src.fracture()
if(!is_broken())
perma_injury = 0
update_germs()
//Cancer growth for external organs is simple, it grows, hurts, damages, and suddenly grows out of control
//Limb cancer is relatively benign until it grows large, then it cripples you and metastases
/datum/organ/external/handle_cancer()
if(..())
return 1
if(!is_existing()) //Limb has been destroyed or amputated, cancer's over as far as we are concerned since there is no limb to grow on anymore
cancer_stage = 0
return 1
switch(cancer_stage)
if(CANCER_STAGE_SMALL_TUMOR to CANCER_STAGE_LARGE_TUMOR) //Small tumors will not damage your limb, but might flash pain
if(prob(1))
owner.custom_pain("You feel a stabbing pain in your [display_name]!", 1)
if(CANCER_STAGE_LARGE_TUMOR to CANCER_STAGE_METASTASIS) //Large tumors will start damaging your limb and give the owner DNA damage (bodywide, can't go per limb)
if(prob(20))
take_damage(0.5, 0, 0, used_weapon = "tumor growth")
owner.custom_pain("You feel a stabbing pain in your [display_name]!", 1)
if(prob(1))
owner.apply_damage(0.5, CLONE, src)
if(CANCER_STAGE_METASTASIS to INFINITY) //Metastasis achieved, limb will start breaking down very rapidly, and cancer will spread to all other limbs in short order through bloodstream
if(prob(50))
take_damage(0.5, 0, 0, used_weapon = "tumor metastasis")
if(prob(20))
owner.apply_damage(0.5, CLONE, src)
if(prob(1))
owner.add_cancer() //Add a new cancerous growth
//Cancer has a single universal sign. Coughing. Has a chance to happen every tick
//Most likely not medically accurate, but whocares.ru
if(prob(1))
owner.emote("cough")
//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(!is_existing() || !is_organic()) //Needs to be organic and existing
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 += Clamp((fever_temperature - T20C) / BODYTEMP_COLD_DIVISOR + 1, 0, 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.is_organic())
if(child.germ_level < INFECTION_LEVEL_ONE * 2 || prob(30))
child.germ_level++
if(parent)
if(parent.germ_level < germ_level && parent.is_organic())
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
to_chat(owner, "You can't feel your [display_name] anymore.")
owner.update_body(1)
germ_level++
owner.adjustToxLoss(1)
//Updating wounds. Handles wound natural healing, internal bleedings and infections
/datum/organ/external/proc/update_wounds()
if(!is_organic()) //Non-organic 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 && !W.is_treated() && owner.bodytemperature >= 170 && !(owner.species && owner.species.flags & NO_BLOOD))
if(!owner.reagents.has_reagent("bicaridine")) //Bicard stops internal wounds from growing bigger with time, and also stop bleeding
W.open_wound(0.1 * wound_update_accuracy)
owner.vessel.remove_reagent("blood", 0.05 * W.damage * wound_update_accuracy)
if(!owner.reagents.has_reagent("inaprovaline")) //This little copypaste will allow inaprovaline to work too, giving it a much needed buff to help medical.
W.open_wound(0.1 * wound_update_accuracy)
owner.vessel.remove_reagent("blood", 0.05 * W.damage * wound_update_accuracy)
owner.vessel.remove_reagent("blood", 0.02 * W.damage * wound_update_accuracy) //Bicaridine slows Internal Bleeding
if(prob(1 * wound_update_accuracy))
owner.custom_pain("You feel a stabbing pain in your [display_name]!", 1)
//overdose of bicaridine begins healing IB
if(owner.reagents.get_reagent_amount("bicaridine") >= 30)
W.damage = max(0, W.damage - 0.2)
// slow healing
var/heal_amt = 0
if(W.damage < 15) //This thing's edges are not in day's travel of each other, what healing?
heal_amt += 0.2
if(W.is_treated() && W.damage < 50) //Whoa, not even magical band aid can hold it together
heal_amt += 0.3
//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.germ_level = 0
W.disinfected = 1
//Sync the organ's damage with its wounds
src.update_damages()
if(update_icon())
owner.UpdateDamageIcon()
//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
for(var/datum/wound/W in wounds)
if(W.damage_type == CUT || W.damage_type == BRUISE)
brute_dam += W.damage
else if(W.damage_type == BURN)
burn_dam += W.damage
if(is_organic() && W.bleeding() && !(owner.species.flags & NO_BLOOD))
W.bleed_timer--
status |= ORGAN_BLEEDING
clamped |= W.clamped
number_wounds += W.amount
if(open && !clamped && is_organic() && !(owner.species.flags & NO_BLOOD)) //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)
/datum/organ/external/proc/update_icon()
var/n_is = damage_state_text()
if(n_is != damage_state)
damage_state = n_is
//owner.update_body(1)
return 1
return 0
//New damage icon system
//Returns just the brute/burn damage code
/datum/organ/external/proc/damage_state_text()
if(!is_existing())
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/spawn_limb = 1)
if(destspawn)
return
if(body_part == (UPPER_TORSO || LOWER_TORSO)) //We can't lose either, those cannot be amputated and will cause extremely serious problems
return
if(override)
status |= ORGAN_DESTROYED
if(status & ORGAN_DESTROYED)
src.status &= ~ORGAN_BROKEN
src.status &= ~ORGAN_BLEEDING
src.status &= ~ORGAN_SPLINTED
src.status &= ~ORGAN_DEAD
for(var/implant in implants)
qdel(implant)
//If any organs are attached to this, destroy them
for(var/datum/organ/external/O in children)
O.droplimb(1)
var/obj/item/weapon/organ/organ //Dropped limb object
if(spawn_limb)
organ = generate_dropped_organ(organ_item)
if(species) //Transfer species to the generated organ
organ.species = src.species
organ.update_icon()
src.species = null
if(body_part == LOWER_TORSO)
to_chat(owner, "You are now sterile.")
if(slots_to_drop && slots_to_drop.len)
for(var/slot_id in slots_to_drop)
owner.u_equip(owner.get_item_by_slot(slot_id), 1)
destspawn = 1
//Robotic limbs explode if sabotaged.
if(status & ORGAN_ROBOT && !no_explode && sabotaged)
owner.visible_message("\The [owner]'s [display_name] explodes violently!", \
"Your [display_name] explodes violently!", \
"You hear an explosion followed by a scream!")
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)
qdel(spark_system)
spark_system = null
if(organ)
owner.visible_message("[owner.name]'s [display_name] flies off in an arc.", \
"Your [display_name] goes flying off!", \
"You hear a terrible sound of ripping tendons and flesh.")
//Here, we assign the organ health facts from its old position on the body
//Type check to avoid to rewrite everything else, for now
if(istype(organ, /obj/item/weapon/organ))
var/obj/item/weapon/organ/O = organ
O.cancer_stage = cancer_stage
//Throw organs around
var/randomdir = pick(cardinal)
step(organ, randomdir)
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()
/datum/organ/external/proc/generate_dropped_organ(var/obj/item/current_organ)
return current_organ
/****************************************************
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].", \
"\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("You hear a loud cracking sound coming from \the [owner].", \
"Something feels like it shattered in your [display_name]!", \
"You hear a sickening crack.")
if(owner.species && !(owner.species.flags & NO_PAIN))
owner.emote("scream", , , 1)
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()
if(isgolem(owner))
droplimb(1)
return
/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_PEG
src.status |= ORGAN_ROBOT
src.species = null
src.destspawn = 0
for (var/datum/organ/external/T in children)
if(T)
T.robotize()
/datum/organ/external/proc/peggify()
src.status &= ~ORGAN_BROKEN
src.status &= ~ORGAN_BLEEDING
src.status &= ~ORGAN_CUT_AWAY
src.status &= ~ORGAN_SPLINTED
src.status &= ~ORGAN_ATTACHABLE
src.status &= ~ORGAN_DESTROYED
src.status &= ~ORGAN_ROBOT
src.status |= ORGAN_PEG
src.species = null
src.wounds.len = 0
for (var/datum/organ/external/T in children)
if(T)
if(body_part == ARM_LEFT || body_part == ARM_RIGHT)
T.peggify()
else
T.droplimb(1, 1)
T.status &= ~ORGAN_BROKEN
T.status &= ~ORGAN_BLEEDING
T.status &= ~ORGAN_CUT_AWAY
T.status &= ~ORGAN_SPLINTED
T.status &= ~ORGAN_ATTACHABLE
T.status &= ~ORGAN_DESTROYED
T.status &= ~ORGAN_ROBOT
T.wounds.len = 0
/datum/organ/external/proc/fleshify()
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_PEG
src.status &= ~ORGAN_ROBOT
src.destspawn = 0
/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/get_icon(gender = "", isFat = 0)
//stand_icon = new /icon(icobase, "torso_[g][fat?"_fat":""]")
if(gender)
gender="_[gender]"
var/fat = ""
if(isFat && has_fat)
fat = "_fat"
var/icon_state = "[icon_name][gender][fat]"
var/baseicon = (species ? species.icobase : owner.race_icon)
if(status & ORGAN_MUTATED)
baseicon = (species ? species.deform : owner.deform_icon)
else if(is_peg())
baseicon = 'icons/mob/human_races/o_peg.dmi'
else if(is_robotic())
baseicon = 'icons/mob/human_races/o_robot.dmi'
return new /icon(baseicon, icon_state)
//Our external limb is a peg
/datum/organ/external/proc/is_peg()
return (status & ORGAN_PEG)
//Our external limb is robotic
/datum/organ/external/proc/is_robotic()
return (status & ORGAN_ROBOT)
//Our external limb is organic, 100 % bio
/datum/organ/external/proc/is_organic()
return !(status & (ORGAN_ROBOT|ORGAN_PEG))
//Is the limb physically present ?
/datum/organ/external/proc/is_existing()
return !(status & (ORGAN_DESTROYED|ORGAN_CUT_AWAY))
//Can we use the limb at all in any manner
/datum/organ/external/proc/is_usable()
return !(status & (ORGAN_DESTROYED|ORGAN_MUTATED|ORGAN_DEAD|ORGAN_CUT_AWAY))
//Is the limb broken and not splinted
/datum/organ/external/proc/is_broken()
return ((status & ORGAN_BROKEN) && !(status & ORGAN_SPLINTED))
//Is the limb robotic and malfunctioning
/datum/organ/external/proc/is_malfunctioning()
return ((status & ORGAN_ROBOT) && prob(brute_dam + burn_dam))
//Can we use advanced tools (no pegs or hook-hands)
/datum/organ/external/proc/can_use_advanced_tools()
return !(status & (ORGAN_DESTROYED|ORGAN_MUTATED|ORGAN_DEAD|ORGAN_PEG|ORGAN_CUT_AWAY))
/datum/organ/external/proc/process_grasp(var/obj/item/c_hand, var/hand_name)
if(!c_hand)
return
if(is_broken() && !istype(c_hand,/obj/item/tk_grab))
owner.drop_item(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, 1)
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)
qdel(spark_system)
spark_system = null
owner.drop_item(c_hand)
/datum/organ/external/proc/embed(var/obj/item/weapon/W, var/silent = 0)
if(!silent)
owner.visible_message("\The [W] sticks in the wound!")
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, force_drop = 1)
W.loc = owner
/****************************************************
ORGAN DEFINES
****************************************************/
/datum/organ/external/chest
name = "chest"
icon_name = "torso"
display_name = "chest"
max_damage = 150
min_broken_damage = 75
body_part = UPPER_TORSO
has_fat = 1
vital = 1
encased = "ribcage"
/datum/organ/external/groin
name = "groin"
icon_name = "groin"
display_name = "groin"
max_damage = 115
min_broken_damage = 70
body_part = LOWER_TORSO
vital = 1
/datum/organ/external/l_arm
name = "l_arm"
display_name = "left arm"
icon_name = "l_arm"
max_damage = 75
min_broken_damage = 30
body_part = ARM_LEFT
/datum/organ/external/l_arm/process()
..()
process_grasp(owner.l_hand, "left hand")
/datum/organ/external/l_arm/generate_dropped_organ(current_organ)
if(status & ORGAN_PEG) current_organ = new /obj/item/stack/sheet/wood(owner.loc)
if(!current_organ)
if(status & ORGAN_ROBOT)
current_organ= new /obj/item/robot_parts/l_arm(owner.loc)
else
current_organ= new /obj/item/weapon/organ/l_arm(owner.loc, owner)
return current_organ
/datum/organ/external/l_leg
name = "l_leg"
display_name = "left leg"
icon_name = "l_leg"
max_damage = 75
min_broken_damage = 30
body_part = LEG_LEFT
icon_position = LEFT
/datum/organ/external/l_leg/generate_dropped_organ(current_organ)
if(is_peg())
current_organ = new /obj/item/stack/sheet/wood(owner.loc)
if(!current_organ)
if(is_robotic())
current_organ = new /obj/item/robot_parts/l_leg(owner.loc)
else
current_organ = new /obj/item/weapon/organ/l_leg(owner.loc, owner)
return current_organ
/datum/organ/external/r_arm
name = "r_arm"
display_name = "right arm"
icon_name = "r_arm"
max_damage = 75
min_broken_damage = 30
body_part = ARM_RIGHT
/datum/organ/external/r_arm/process()
..()
process_grasp(owner.r_hand, "right hand")
/datum/organ/external/r_arm/generate_dropped_organ(current_organ)
if(is_peg())
current_organ = new /obj/item/stack/sheet/wood(owner.loc)
if(!current_organ)
if(is_robotic())
current_organ = new /obj/item/robot_parts/r_arm(owner.loc)
else
current_organ = new /obj/item/weapon/organ/r_arm(owner.loc, owner)
return current_organ
/datum/organ/external/r_leg
name = "r_leg"
display_name = "right leg"
icon_name = "r_leg"
max_damage = 75
min_broken_damage = 30
body_part = LEG_RIGHT
icon_position = RIGHT
/datum/organ/external/r_leg/generate_dropped_organ(current_organ)
if(is_peg())
current_organ = new /obj/item/stack/sheet/wood(owner.loc)
if(!current_organ)
if(is_robotic())
current_organ = new /obj/item/robot_parts/r_leg(owner.loc)
else
current_organ = new /obj/item/weapon/organ/r_leg(owner.loc, owner)
return current_organ
/datum/organ/external/l_foot
name = "l_foot"
display_name = "left foot"
icon_name = "l_foot"
max_damage = 40
min_broken_damage = 15
body_part = FOOT_LEFT
icon_position = LEFT
slots_to_drop = list(slot_shoes, slot_legcuffed)
/datum/organ/external/l_foot/generate_dropped_organ(current_organ)
if(is_peg())
current_organ = new /obj/item/stack/sheet/wood(owner.loc)
if(!current_organ)
if(!is_robotic())
current_organ = new /obj/item/weapon/organ/l_foot(owner.loc, owner)
return current_organ
/datum/organ/external/r_foot
name = "r_foot"
display_name = "right foot"
icon_name = "r_foot"
max_damage = 40
min_broken_damage = 15
body_part = FOOT_RIGHT
icon_position = RIGHT
slots_to_drop = list(slot_shoes, slot_legcuffed)
/datum/organ/external/r_foot/generate_dropped_organ(current_organ)
if(is_peg())
current_organ = new /obj/item/stack/sheet/wood(owner.loc)
if(!current_organ)
if(!is_robotic())
current_organ = new /obj/item/weapon/organ/r_foot(owner.loc, owner)
return current_organ
/datum/organ/external/r_hand
name = "r_hand"
display_name = "right hand"
icon_name = "r_hand"
max_damage = 40
min_broken_damage = 15
body_part = HAND_RIGHT
slots_to_drop = list(slot_gloves, slot_r_hand, slot_handcuffed)
/datum/organ/external/r_hand/process()
..()
process_grasp(owner.r_hand, "right hand")
/datum/organ/external/r_hand/generate_dropped_organ(current_organ)
if(is_peg())
current_organ = new /obj/item/stack/sheet/wood(owner.loc)
if(!current_organ)
if(!is_robotic())
current_organ = new /obj/item/weapon/organ/r_hand(owner.loc, owner)
return current_organ
/datum/organ/external/l_hand
name = "l_hand"
display_name = "left hand"
icon_name = "l_hand"
max_damage = 40
min_broken_damage = 15
body_part = HAND_LEFT
slots_to_drop = list(slot_gloves, slot_l_hand, slot_handcuffed)
/datum/organ/external/l_hand/process()
..()
process_grasp(owner.l_hand, "left hand")
/datum/organ/external/l_hand/generate_dropped_organ(current_organ)
if(is_peg())
current_organ = new /obj/item/stack/sheet/wood(owner.loc)
if(!current_organ)
if(!is_robotic())
current_organ = new /obj/item/weapon/organ/l_hand(owner.loc, owner)
return current_organ
/datum/organ/external/head
name = "head"
icon_name = "head"
display_name = "head"
max_damage = 130
min_broken_damage = 40
body_part = HEAD
var/disfigured = 0
vital = 1
encased = "skull"
slots_to_drop = list(slot_glasses, slot_wear_mask, slot_head, slot_ears)
/datum/organ/external/head/generate_dropped_organ(current_organ)
if(!current_organ)
current_organ = new /obj/item/weapon/organ/head(owner.loc, owner)
owner.decapitated = current_organ
var/datum/organ/internal/brain/B = owner.internal_organs_by_name["brain"]
var/obj/item/weapon/organ/head/H = current_organ
if(B)
H.organ_data = B
B.organ_holder = current_organ
B.owner_dna = H.owner_dna
owner.internal_organs_by_name["brain"] = null
owner.internal_organs_by_name -= "brain"
owner.internal_organs -= B
internal_organs -= B
return current_organ
/datum/organ/external/head/get_icon()
if(!owner)
return ..()
var/g = "m"
if(owner.gender == FEMALE)
g = "f"
var/baseicon = (species ? species.icobase : owner.race_icon)
if(status & ORGAN_MUTATED)
baseicon = (species ? species.deform : owner.deform_icon)
if(is_peg())
baseicon = 'icons/mob/human_races/o_peg.dmi'
if(is_robotic())
baseicon = 'icons/mob/human_races/o_robot.dmi'
return new /icon(baseicon, "[icon_name]_[g]")
/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((used_weapon != WPN_LOW_BODY_TEMP) ? "burn" : "frostbite")
/datum/organ/external/head/proc/disfigure(var/type = "brute")
if(disfigured)
return
if(type == "brute")
owner.visible_message("You hear a sickening cracking sound coming from \the [owner]'s face.",
"Your face becomes an unrecognizable, mangled mess!",
"You hear a sickening crack.")
else if (type == "burn")
owner.visible_message("[owner]'s face melts away, turning into a mangled mess!",
"Your face melts away into an unrecognizable, mangled mess!",
"You hear a sickening sizzle.")
else if (type == "frostbite")
owner.visible_message("[owner]'s frozen face blisters and cracks.",
"Your face blisters and numbs away!",
"You hear a sickening crackling.")
else // Generic message, shouldn't happen
owner.visible_message("[owner]'s face disfigures.",
"Your face becomes an unrecognizable, mangled mess!")
disfigured = 1
/****************************************************
EXTERNAL ORGAN ITEMS
****************************************************/
obj/item/weapon/organ
icon = 'icons/mob/human_races/r_human.dmi'
var/datum/organ/internal/organ_data
var/datum/dna/owner_dna
var/part = "organ"
//This variable stores "butchering products" - objects of type "/datum/butchering_product" (see code/datums/helper_datums/butchering.dm)
//They are transferred from the mob from which the organ was removed.
//Currently the only "butchering drops" which are going to be stored here are teeth
var/list/butchering_drops = list()
var/datum/species/species
//Store health facts. Right now limited exclusively to cancer, but should likely include all limb stats eventually
var/cancer_stage = 0
obj/item/weapon/organ/New(loc, mob/living/carbon/human/H)
..(loc)
if(!istype(H))
return
if(H.dna)
owner_dna = H.dna.Clone()
if(!blood_DNA)
blood_DNA = list()
blood_DNA[H.dna.unique_enzymes] = H.dna.b_type
src.species = H.species
//Forming icon for the limb
//Setting base icon for this mob's race
update_icon(H)
for(var/datum/butchering_product/B in H.butchering_drops) //Go through all butchering products (like teeth) in the parent
if(B.stored_in_organ == src.part) //If they're stored in our organ,
var/datum/butchering_product/new_bp = new B.type() //Create a new butchering_product datum to go into the head!
new_bp.amount = B.amount
B.amount = 0 //Transfer the found product's amount to the new datum
src.butchering_drops += new_bp
//The reason why B isn't just transferred from H.butchering_drops to src.butchering_drops is:
//on examine(), each butchering drop's "desc_modifier()" is added to the description. This adds stuff like "he HAS NO TEETH AT ALL!!!" to the resulting description.
/obj/item/weapon/organ/examine(mob/user)
..()
//Add information about teeth and the such
var/butchery
if(butchering_drops.len)
for(var/datum/butchering_product/B in butchering_drops)
butchery = "[butchery][B.desc_modifier(src, user)]"
if(butchery)
to_chat(user, "[butchery]")
/obj/item/weapon/organ/update_icon(mob/living/carbon/human/H)
..()
if(!H && !species) return
var/icon/base
if(H)
if(H.species)
if(!src.species)
src.species = H.species //Also store the mob's species for later use
if(H.species.icobase)
base = icon(H.species.icobase)
else
base = icon('icons/mob/human_races/r_human.dmi')
else if(species)
base = icon(species.icobase)
if(base)
//Changing limb's skin tone to match owner
if(H)
if(!H.species || H.species.flags & HAS_SKIN_TONE)
if(H.s_tone >= 0)
base.Blend(rgb(H.s_tone, H.s_tone, H.s_tone), ICON_ADD)
else
base.Blend(rgb(-H.s_tone, -H.s_tone, -H.s_tone), ICON_SUBTRACT)
icon = base
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"
part = "l_arm"
obj/item/weapon/organ/l_foot
name = "left foot"
icon_state = "l_foot"
part = "l_foot"
obj/item/weapon/organ/l_hand
name = "left hand"
icon_state = "l_hand"
part = "l_hand"
obj/item/weapon/organ/l_leg
name = "left leg"
icon_state = "l_leg"
part = "l_leg"
obj/item/weapon/organ/r_arm
name = "right arm"
icon_state = "r_arm"
part = "r_arm"
obj/item/weapon/organ/r_foot
name = "right foot"
icon_state = "r_foot"
part = "r_foot"
obj/item/weapon/organ/r_hand
name = "right hand"
icon_state = "r_hand"
part = "r_hand"
obj/item/weapon/organ/r_leg
name = "right leg"
icon_state = "r_leg"
part = "r_leg"
obj/item/weapon/organ/head
dir = NORTH
name = "head"
icon_state = "head_m"
part = "head"
ashtype = /obj/item/weapon/skull
var/mob/living/carbon/brain/brainmob
var/mob/living/simple_animal/borer/borer
var/brain_op_stage = 0
var/mob/living/carbon/human/origin_body = null
//obj/item/weapon/organ/head/with_teeth starts with 32 human teeth!
/obj/item/weapon/organ/head/with_teeth/New()
.=..()
butchering_drops += new /datum/butchering_product/teeth/human()
/obj/item/weapon/organ/head/posi
name = "robotic head"
obj/item/weapon/organ/head/New(loc, mob/living/carbon/human/H)
origin_body = H
if(istype(H))
src.icon_state = H.gender == MALE? "head_m" : "head_f"
..()
if(isgolem(H)) //Golems don't inhabit their severed heads, they turn to dust when they die.
var/mob/living/simple_animal/borer/B = H.has_brain_worms()
if(B)
B.detach()
qdel(src)
return
//Add (facial) hair.
if(H.f_style && !H.check_hidden_head_flags(HIDEBEARDHAIR))
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.check_hidden_head_flags(HIDEHEADHAIR))
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)
if(hair_style.additional_accessories)
hair.Blend(icon("icon" = hair_style.icon, "icon_state" = "[hair_style.icon_state]_acc"), ICON_OVERLAY)
overlays.Add(hair) //icon.Blend(hair, ICON_OVERLAY)
spawn(5)
if(brainmob && brainmob.client)
brainmob.client.screen.len = null //clear the hud
var/mob/living/simple_animal/borer/B = H.has_brain_worms()
if(B)
B.infest_head(src)
//if(ishuman(H))
// if(H.gender == FEMALE)
// H.icon_state = "head_f"
// H.overlays += H.generate_head_icon()
transfer_identity(H)
name = "[H.real_name]'s head"
H.regenerate_icons()
brainmob.stat = 2
brainmob.death()
if(brainmob.mind && brainmob.mind.special_role == HIGHLANDER)
if(H.lastattacker && istype(H.lastattacker, /mob/living/carbon/human))
var/mob/living/carbon/human/L = H.lastattacker
if(L.mind && L.mind.special_role == HIGHLANDER)
L.revive(0)
to_chat(L, "You absorb \the [brainmob]'s power!")
var/turf/T1 = get_turf(H)
make_tracker_effects(T1, L)
obj/item/weapon/organ/head/proc/transfer_identity(var/mob/living/carbon/human/H)//Same deal as the regular brain proc. Used for human-->head
brainmob = new(src)
brainmob.name = H.real_name
brainmob.real_name = H.real_name
brainmob.dna = H.dna.Clone()
if(H.mind)
H.mind.transfer_to(brainmob)
brainmob.container = src
obj/item/weapon/organ/head/attackby(obj/item/weapon/W as obj, mob/user as mob)
if(istype(W,/obj/item/weapon/scalpel) || istype(W,/obj/item/weapon/shard) || (istype(W,/obj/item/weapon/kitchen/utensil/knife/large) && !istype(W,/obj/item/weapon/kitchen/utensil/knife/large/butch)))
if(organ_data)
switch(brain_op_stage)
if(0)
user.visible_message("[user] cuts [brainmob]'s head open with \the [W].", \
"You cut [brainmob]'s open with \the [W]!")
brain_op_stage = 1
if(2)
user.visible_message("[user] severs [brainmob]'s brain connections delicately with \the [W].", \
"You sever [brainmob]'s brain connections delicately with \the [W]!")
brain_op_stage = 3.0
else
..()
else
to_chat(user, "That head has no brain to remove!")
else if(istype(W,/obj/item/weapon/circular_saw) || istype(W,/obj/item/weapon/kitchen/utensil/knife/large/butch) || istype(W,/obj/item/weapon/hatchet))
if(organ_data)
switch(brain_op_stage)
if(1)
user.visible_message("[user] saws [brainmob]'s head open with \the [W].", \
"You saw [brainmob]'s head open with \the [W].")
brain_op_stage = 2
if(3)
user.visible_message("[user] severs [brainmob]'s spine connections delicately with \the [W].", \
"You sever [brainmob]'s spine connections delicately with \the [W]!")
user.attack_log += "\[[time_stamp()]\] Debrained [brainmob.name] ([brainmob.ckey]) with [W.name] (INTENT: [uppertext(user.a_intent)])"
brainmob.attack_log += "\[[time_stamp()]\] Debrained by [user.name] ([user.ckey]) with [W.name] (INTENT: [uppertext(user.a_intent)])"
msg_admin_attack("[user] ([user.ckey]) debrained [brainmob] ([brainmob.ckey]) (INTENT: [uppertext(user.a_intent)]) (JMP)")
//TODO: ORGAN REMOVAL UPDATE.
var/turf/T = get_turf(src)
if(istype(src,/obj/item/weapon/organ/head/posi))
var/obj/item/device/mmi/posibrain/B = new(T)
B.transfer_identity(brainmob)
else
var/obj/item/organ/brain/B = new(T)
B.transfer_identity(brainmob)
if(borer)
borer.detach()
brain_op_stage = 4.0
organ_data = null
else
..()
else
to_chat(user, "That head has no brain to remove!")
else if(istype(W,/obj/item/device/soulstone))
W.capture_soul_head(src,user)
return
else
..()
obj/item/weapon/organ/head/Destroy()
if(brainmob)
brainmob.ghostize()
if(origin_body)
origin_body.decapitated = null
origin_body = null
..()