/obj/item/organ/brain name = "brain" desc = "A piece of juicy meat found in a person's head." icon_state = "brain" throw_speed = 3 throw_range = 5 layer = ABOVE_MOB_LAYER zone = BODY_ZONE_HEAD slot = ORGAN_SLOT_BRAIN vital = TRUE attack_verb = list("attacked", "slapped", "whacked") var/mob/living/brain/brainmob = null var/damaged_brain = FALSE //whether the brain organ is damaged. var/decoy_override = FALSE //I apologize to the security players, and myself, who abused this, but this is going to go. var/list/datum/brain_trauma/traumas = list() /obj/item/organ/brain/Insert(mob/living/carbon/C, special = 0,no_id_transfer = FALSE) ..() name = "brain" if(C.mind && C.mind.has_antag_datum(/datum/antagonist/changeling) && !no_id_transfer) //congrats, you're trapped in a body you don't control if(brainmob && !(C.stat == DEAD || (C.has_trait(TRAIT_FAKEDEATH)))) to_chat(brainmob, "You can't feel your body! You're still just a brain!") forceMove(C) C.update_hair() return if(brainmob) if(C.key) C.ghostize() if(brainmob.mind) brainmob.mind.transfer_to(C) else C.key = brainmob.key QDEL_NULL(brainmob) for(var/X in traumas) var/datum/brain_trauma/BT = X BT.owner = owner BT.on_gain() //Update the body's icon so it doesnt appear debrained anymore C.update_hair() /obj/item/organ/brain/Remove(mob/living/carbon/C, special = 0, no_id_transfer = FALSE) ..() for(var/X in traumas) var/datum/brain_trauma/BT = X BT.on_lose(TRUE) BT.owner = null if((!gc_destroyed || (owner && !owner.gc_destroyed)) && !no_id_transfer) transfer_identity(C) C.update_hair() /obj/item/organ/brain/prepare_eat() return // Too important to eat. /obj/item/organ/brain/proc/transfer_identity(mob/living/L) name = "[L.name]'s brain" if(brainmob || decoy_override) return if(!L.mind) return brainmob = new(src) brainmob.name = L.real_name brainmob.real_name = L.real_name brainmob.timeofhostdeath = L.timeofdeath if(L.has_dna()) var/mob/living/carbon/C = L if(!brainmob.stored_dna) brainmob.stored_dna = new /datum/dna/stored(brainmob) C.dna.copy_dna(brainmob.stored_dna) if(L.has_trait(TRAIT_NOCLONE)) brainmob.status_traits[TRAIT_NOCLONE] = L.status_traits[TRAIT_NOCLONE] var/obj/item/organ/zombie_infection/ZI = L.getorganslot(ORGAN_SLOT_ZOMBIE) if(ZI) brainmob.set_species(ZI.old_species) //For if the brain is cloned if(L.mind && L.mind.current) L.mind.transfer_to(brainmob) to_chat(brainmob, "You feel slightly disoriented. That's normal when you're just a brain.") /obj/item/organ/brain/attackby(obj/item/O, mob/user, params) user.changeNext_move(CLICK_CD_MELEE) if(brainmob) O.attack(brainmob, user) //Oh noooeeeee /obj/item/organ/brain/examine(mob/user) ..() if(brainmob) if(brainmob.client) if(brainmob.health <= HEALTH_THRESHOLD_DEAD) to_chat(user, "It's lifeless and severely damaged.") else to_chat(user, "You can feel the small spark of life still left in this one.") else to_chat(user, "This one seems particularly lifeless. Perhaps it will regain some of its luster later.") else if(decoy_override) to_chat(user, "This one seems particularly lifeless. Perhaps it will regain some of its luster later.") else to_chat(user, "This one is completely devoid of life.") /obj/item/organ/brain/attack(mob/living/carbon/C, mob/user) if(!istype(C)) return ..() add_fingerprint(user) if(user.zone_selected != BODY_ZONE_HEAD) return ..() if((C.head && (C.head.flags_cover & HEADCOVERSEYES)) || (C.wear_mask && (C.wear_mask.flags_cover & MASKCOVERSEYES)) || (C.glasses && (C.glasses.flags_1 & GLASSESCOVERSEYES))) to_chat(user, "You're going to need to remove their head cover first!") return //since these people will be dead M != usr if(!C.getorgan(/obj/item/organ/brain)) if(!C.get_bodypart(BODY_ZONE_HEAD) || !user.temporarilyRemoveItemFromInventory(src)) return var/msg = "[C] has [src] inserted into [C.p_their()] head by [user]." if(C == user) msg = "[user] inserts [src] into [user.p_their()] head!" C.visible_message("[msg]", "[msg]") if(C != user) to_chat(C, "[user] inserts [src] into your head.") to_chat(user, "You insert [src] into [C]'s head.") else to_chat(user, "You insert [src] into your head." ) Insert(C) else ..() /obj/item/organ/brain/proc/get_brain_damage() var/brain_damage_threshold = max_integrity * BRAIN_DAMAGE_INTEGRITY_MULTIPLIER var/offset_integrity = obj_integrity - (max_integrity - brain_damage_threshold) . = round((1 - (offset_integrity / brain_damage_threshold)) * BRAIN_DAMAGE_DEATH,0.1) /obj/item/organ/brain/proc/adjust_brain_damage(amount, maximum) var/adjusted_amount if(amount >= 0 && maximum) var/brainloss = get_brain_damage() var/new_brainloss = CLAMP(brainloss + amount, 0, maximum) if(brainloss > new_brainloss) //brainloss is over the cap already return 0 adjusted_amount = new_brainloss - brainloss else adjusted_amount = amount adjusted_amount = round(adjusted_amount * BRAIN_DAMAGE_INTEGRITY_MULTIPLIER,0.1) if(adjusted_amount) if(adjusted_amount >= 0.1) take_damage(adjusted_amount) else if(adjusted_amount <= -0.1) obj_integrity = min(max_integrity, obj_integrity-adjusted_amount) . = adjusted_amount /obj/item/organ/brain/Destroy() //copypasted from MMIs. if(brainmob) QDEL_NULL(brainmob) QDEL_LIST(traumas) return ..() /obj/item/organ/brain/alien name = "alien brain" desc = "We barely understand the brains of terrestial animals. Who knows what we may find in the brain of such an advanced species?" icon_state = "brain-x" ////////////////////////////////////TRAUMAS//////////////////////////////////////// /obj/item/organ/brain/proc/has_trauma_type(brain_trauma_type = /datum/brain_trauma, resilience = TRAUMA_RESILIENCE_ABSOLUTE) for(var/X in traumas) var/datum/brain_trauma/BT = X if(istype(BT, brain_trauma_type) && (BT.resilience <= resilience)) return BT /obj/item/organ/brain/proc/get_traumas_type(brain_trauma_type = /datum/brain_trauma, resilience = TRAUMA_RESILIENCE_ABSOLUTE) . = list() for(var/X in traumas) var/datum/brain_trauma/BT = X if(istype(BT, brain_trauma_type) && (BT.resilience <= resilience)) . += BT /obj/item/organ/brain/proc/can_gain_trauma(datum/brain_trauma/trauma, resilience) if(!ispath(trauma)) trauma = trauma.type if(!initial(trauma.can_gain)) return FALSE if(!resilience) resilience = initial(trauma.resilience) var/resilience_tier_count = 0 for(var/X in traumas) if(istype(X, trauma)) return FALSE var/datum/brain_trauma/T = X if(resilience == T.resilience) resilience_tier_count++ var/max_traumas switch(resilience) if(TRAUMA_RESILIENCE_BASIC) max_traumas = TRAUMA_LIMIT_BASIC if(TRAUMA_RESILIENCE_SURGERY) max_traumas = TRAUMA_LIMIT_SURGERY if(TRAUMA_RESILIENCE_LOBOTOMY) max_traumas = TRAUMA_LIMIT_LOBOTOMY if(TRAUMA_RESILIENCE_MAGIC) max_traumas = TRAUMA_LIMIT_MAGIC if(TRAUMA_RESILIENCE_ABSOLUTE) max_traumas = TRAUMA_LIMIT_ABSOLUTE if(resilience_tier_count >= max_traumas) return FALSE return TRUE //Proc to use when directly adding a trauma to the brain, so extra args can be given /obj/item/organ/brain/proc/gain_trauma(datum/brain_trauma/trauma, resilience, ...) var/list/arguments = list() if(args.len > 2) arguments = args.Copy(3) . = brain_gain_trauma(trauma, resilience, arguments) //Direct trauma gaining proc. Necessary to assign a trauma to its brain. Avoid using directly. /obj/item/organ/brain/proc/brain_gain_trauma(datum/brain_trauma/trauma, resilience, list/arguments) if(!can_gain_trauma(trauma, resilience)) return var/datum/brain_trauma/actual_trauma if(ispath(trauma)) if(!LAZYLEN(arguments)) actual_trauma = new trauma() //arglist with an empty list runtimes for some reason else actual_trauma = new trauma(arglist(arguments)) else actual_trauma = trauma if(actual_trauma.brain) //we don't accept used traumas here WARNING("gain_trauma was given an already active trauma.") return traumas += actual_trauma actual_trauma.brain = src if(owner) actual_trauma.owner = owner actual_trauma.on_gain() if(resilience) actual_trauma.resilience = resilience SSblackbox.record_feedback("tally", "traumas", 1, actual_trauma.type) //Add a random trauma of a certain subtype /obj/item/organ/brain/proc/gain_trauma_type(brain_trauma_type = /datum/brain_trauma, resilience) var/list/datum/brain_trauma/possible_traumas = list() for(var/T in subtypesof(brain_trauma_type)) var/datum/brain_trauma/BT = T if(can_gain_trauma(BT, resilience)) possible_traumas += BT if(!LAZYLEN(possible_traumas)) return var/trauma_type = pick(possible_traumas) gain_trauma(trauma_type, resilience) //Cure a random trauma of a certain resilience level /obj/item/organ/brain/proc/cure_trauma_type(brain_trauma_type = /datum/brain_trauma, resilience = TRAUMA_RESILIENCE_BASIC) var/list/traumas = get_traumas_type(brain_trauma_type, resilience) if(LAZYLEN(traumas)) qdel(pick(traumas)) /obj/item/organ/brain/proc/cure_all_traumas(resilience = TRAUMA_RESILIENCE_BASIC) var/list/traumas = get_traumas_type(resilience = resilience) for(var/X in traumas) qdel(X)