/**************************************************** INTERNAL ORGANS DEFINES ****************************************************/ /obj/item/organ/internal /// Icon to use when the organ has died. var/dead_icon /// Modifier for internal organ injury. var/damage_reduction = 0.5 /// If TRUE, pain messages will point to the parent organ, otherwise it will print the organ name. var/unknown_pain_location = TRUE var/toxin_type = "undefined" /// Used for size calcs. var/relative_size = 25 /// The icon state to overlay on the mob. var/on_mob_icon /// If the icon state has an active overlay. var/active_overlay = FALSE /// If the icon state has an active emissive overlay. var/active_emissive = FALSE /// Used in character setup. var/list/possible_modifications = list("Normal","Assisted","Mechanical") /// The amount all organs heal themselves by per second when not being affected by chems. var/organ_self_heal_per_second = 0.2 /// Internal organs are frail, man. min_broken_damage = 10 /obj/item/organ/internal/Destroy() if(owner && owner.internal_organs) owner.internal_organs.Remove(src) owner.internal_organs_by_name[organ_tag] = null owner.internal_organs_by_name -= organ_tag while(null in owner.internal_organs) owner.internal_organs -= null if(parent_organ in owner.organs_by_name) var/obj/item/organ/external/E = astype(owner.organs_by_name[parent_organ]) E?.internal_organs -= src return ..() /// Sets the internal organ as belonging to the targeted external organ, and matches the target's species/robotness. Also updates all organ lists belonging to the owner. /obj/item/organ/internal/replaced(mob/living/carbon/human/target, obj/item/organ/external/affected) . = ..() // robotic organs emulate behavior of the equivalent flesh organ of the species if(BP_IS_ROBOTIC(src) || !species) species = target.species target.internal_organs |= src affected.internal_organs |= src target.internal_organs_by_name[organ_tag] = src return TRUE /obj/item/organ/internal/die() ..() if((status & ORGAN_DEAD) && dead_icon) icon_state = dead_icon /obj/item/organ/internal/proc/surgical_fix(mob/user) if(damage > min_broken_damage) var/scarring = damage / max_damage scarring = 1 - 0.5 * scarring ** 2 // Between ~15 and 50 percent loss. var/new_max_dam = FLOOR(scarring * max_damage, 1) if(new_max_dam < max_damage) to_chat(user, SPAN_WARNING("Not every part of [src] could be saved; some dead tissue had to be removed, making it more susceptible to future damage.")) set_max_damage(new_max_dam) heal_damage(damage) /obj/item/organ/internal/proc/get_scarring_level() . = (initial(max_damage) - max_damage)/initial(max_damage) /obj/item/organ/internal/proc/get_scarring_results() var/scar_level = get_scarring_level() if(scar_level > 0.01) . += "[get_wound_severity(get_scarring_level(), FALSE, FALSE)] scarring" /obj/item/organ/internal/is_usable() if(robotize_type) var/datum/robolimb/R = GLOB.all_robolimbs[robotize_type] if(!R.malfunctioning_check(owner)) return TRUE else return ..() && !is_broken() /obj/item/organ/internal/proc/is_damaged() return damage > 0 || special_condition() /obj/item/organ/internal/proc/special_condition() // For unique conditions return /obj/item/organ/internal/robotize(var/company = PROSTHETIC_UNBRANDED) ..() min_bruised_damage += 5 min_broken_damage += 10 if(company) model = company var/datum/robolimb/R = GLOB.all_robolimbs[company] if(R) if(robotic_sprite) icon_state = "[initial(icon_state)]-[R.internal_organ_suffix]" robotize_type = company /obj/item/organ/internal/mechassist() ..() icon_state = "[initial(icon_state)]-assisted" /obj/item/organ/internal/proc/getToxLoss() if(BP_IS_ROBOTIC(src)) return damage * 0.5 return damage /obj/item/organ/internal/proc/set_max_damage(var/ndamage) max_damage = FLOOR(ndamage, 1) min_broken_damage = FLOOR(0.75 * max_damage, 1) min_bruised_damage = FLOOR(0.25 * max_damage, 1) /obj/item/organ/internal/proc/take_internal_damage(amount, var/silent=0) START_PROCESSING(SSprocessing, src) if(BP_IS_ROBOTIC(src)) damage = between(0, src.damage + (amount * 0.8), max_damage) else damage = between(0, src.damage + amount, max_damage) //only show this if the organ is not robotic if(owner && ORGAN_CAN_FEEL_PAIN(src) && parent_organ && (amount > 5 || prob(10))) var/obj/item/organ/external/parent = owner.get_organ(parent_organ) if(parent && !silent) var/degree = "" if(is_bruised()) degree = " a lot" if(damage < 5) degree = " a bit" owner.custom_pain("Something inside your [parent.name] hurts[degree]!", amount, affecting = parent) /obj/item/organ/internal/proc/get_visible_state() if(damage > max_damage) . = "bits and pieces of a destroyed " else if(is_broken()) . = "broken " else if(is_bruised()) . = "badly damaged " else if(damage > 5) . = "damaged " if(status & ORGAN_DEAD) if(can_recover()) . = "necrotic and debridable [.]" else . = "necrotic and dead [.]" . = "[.][name]" /obj/item/organ/internal/process(seconds_per_tick) ..() if(!owner) return if(owner.stasis_value > 0) // Putting a body in stasis will simultaneously slow down the rate at which organs die // while also slowing down the rate at which they are healed. seconds_per_tick /= owner.stasis_value if(toxin_type in owner.chem_effects) take_damage(owner.chem_effects[toxin_type] * seconds_per_tick) handle_regeneration(seconds_per_tick) tick_surge_damage(seconds_per_tick) //Yes, this is intentional. /obj/item/organ/internal/proc/handle_regeneration(seconds_per_tick) SHOULD_CALL_PARENT(TRUE) if(!damage || BP_IS_ROBOTIC(src) || !istype(owner) || owner.is_asystole() || (owner.chem_effects[CE_TOXIN] || (toxin_type in owner.chem_effects))) return FALSE var/repair_modifier = owner.chem_effects[CE_ORGANREPAIR] || organ_self_heal_per_second if(damage < repair_modifier*max_damage) heal_damage(repair_modifier * seconds_per_tick) return TRUE // regeneration is allowed