diff --git a/code/__defines/mobs.dm b/code/__defines/mobs.dm index 8426edcfcfe..efb94d49631 100644 --- a/code/__defines/mobs.dm +++ b/code/__defines/mobs.dm @@ -210,13 +210,17 @@ #define O_GBLADDER "gas bladder" #define O_POLYP "polyp segment" #define O_ANCHOR "anchoring ligament" +#define O_REGBRUTE "pneumoregenitor" +#define O_REGBURN "thermoregenitor" +#define O_REGOXY "respiroregenitor" +#define O_REGTOX "toxoregenitor" #define O_ACID "acid gland" #define O_EGG "egg sac" #define O_RESIN "resin spinner" #define O_AREJECT "immune hub" #define O_VENTC "morphoplastic node" #define O_VRLINK "virtual node" -#define O_ALL list(O_STANDARD, O_MOUTH, O_CELL, O_PLASMA, O_HIVE, O_NUTRIENT, O_STRATA, O_RESPONSE, O_GBLADDER, O_POLYP, O_ANCHOR, O_ACID, O_EGG, O_RESIN, O_AREJECT, O_VENTC, O_VRLINK) +#define O_ALL list(O_STANDARD, O_MOUTH, O_CELL, O_PLASMA, O_HIVE, O_NUTRIENT, O_STRATA, O_RESPONSE, O_GBLADDER, O_POLYP, O_ANCHOR, O_REGBRUTE, O_REGBURN, O_REGOXY, O_REGTOX, O_ACID, O_EGG, O_RESIN, O_AREJECT, O_VENTC, O_VRLINK) // External organs, aka limbs #define BP_L_FOOT "l_foot" diff --git a/code/modules/mob/living/carbon/human/human_powers.dm b/code/modules/mob/living/carbon/human/human_powers.dm index 809a5ef8ade..a3c5e654701 100644 --- a/code/modules/mob/living/carbon/human/human_powers.dm +++ b/code/modules/mob/living/carbon/human/human_powers.dm @@ -286,8 +286,11 @@ nutrition -= 200 for(var/obj/item/organ/I in internal_organs) + if(I.robotic >= ORGAN_ROBOT) // No free robofix. + continue if(I.damage > 0) I.damage = max(I.damage - 30, 0) //Repair functionally half of a dead internal organ. + I.status = 0 // Wipe status, as it's being regenerated from possibly dead. to_chat(src, "You feel a soothing sensation within your [I.name]...") // Replace completely missing limbs. @@ -310,6 +313,15 @@ var/agony_to_apply = round(0.66 * O.max_damage) // 66% of the limb's health is converted into pain. src.apply_damage(agony_to_apply, HALLOSS) + for(var/organtype in species.has_organ) // Replace completely missing internal organs. -After- external ones, so they all should exist. + if(!src.internal_organs_by_name[organtype]) + var/organpath = species.has_organ[organtype] + var/obj/item/organ/Int = new organpath(src, TRUE) + + Int.rejuvenate(TRUE) + + handle_organs() // Update everything + update_icons_body() active_regen = FALSE else diff --git a/code/modules/mob/living/carbon/human/species/station/prometheans.dm b/code/modules/mob/living/carbon/human/species/station/prometheans.dm index a14db9d9f50..8c745c056e5 100644 --- a/code/modules/mob/living/carbon/human/species/station/prometheans.dm +++ b/code/modules/mob/living/carbon/human/species/station/prometheans.dm @@ -74,7 +74,13 @@ var/datum/species/shapeshifter/promethean/prometheans genders = list(MALE, FEMALE, NEUTER, PLURAL) unarmed_types = list(/datum/unarmed_attack/slime_glomp) - has_organ = list(O_BRAIN = /obj/item/organ/internal/brain/slime) // Slime core. + + has_organ = list(O_BRAIN = /obj/item/organ/internal/brain/slime, + O_HEART = /obj/item/organ/internal/heart/grey/colormatch/slime, + O_REGBRUTE = /obj/item/organ/internal/regennetwork, + O_REGBURN = /obj/item/organ/internal/regennetwork/burn, + O_REGOXY = /obj/item/organ/internal/regennetwork/oxy, + O_REGTOX = /obj/item/organ/internal/regennetwork/tox) dispersed_eyes = TRUE @@ -197,35 +203,71 @@ var/datum/species/shapeshifter/promethean/prometheans var/nutrition_cost = 0 // The total amount of nutrition drained every tick, when healing var/nutrition_debt = 0 // Holder variable used to store previous damage values prior to healing for use in the nutrition_cost equation. var/starve_mod = 1 // Lowering this lowers healing and increases agony multiplicatively. - if(H.nutrition <= 150) // This is when the icon goes red + + var/strain_negation = 0 // How much agony is being prevented by the + + if(H.nutrition <= 150) // This is when the icon goes red starve_mod = 0.75 if(H.nutrition <= 50) // Severe starvation. Damage repaired beyond this point will cause a stunlock if untreated. starve_mod = 0.5 + var/to_pay = 0 if(regen_brute) nutrition_debt = H.getBruteLoss() H.adjustBruteLoss(-heal_rate * starve_mod) - nutrition_cost += nutrition_debt - H.getBruteLoss() + + to_pay = nutrition_debt - H.getBruteLoss() + + nutrition_cost += to_pay + + var/obj/item/organ/internal/regennetwork/BrReg = H.internal_organs_by_name[O_REGBRUTE] + + if(BrReg) + strain_negation += to_pay * max(0, (1 - BrReg.get_strain_percent())) if(regen_burn) nutrition_debt = H.getFireLoss() H.adjustFireLoss(-heal_rate * starve_mod) - nutrition_cost += nutrition_debt - H.getFireLoss() + + to_pay = nutrition_debt - H.getFireLoss() + + nutrition_cost += to_pay + + var/obj/item/organ/internal/regennetwork/BuReg = H.internal_organs_by_name[O_REGBURN] + + if(BuReg) + strain_negation += to_pay * max(0, (1 - BuReg.get_strain_percent())) if(regen_oxy) nutrition_debt = H.getOxyLoss() H.adjustOxyLoss(-heal_rate * starve_mod) - nutrition_cost += nutrition_debt - H.getOxyLoss() + + to_pay = nutrition_debt - H.getOxyLoss() + + nutrition_cost += to_pay + + var/obj/item/organ/internal/regennetwork/OxReg = H.internal_organs_by_name[O_REGOXY] + + if(OxReg) + strain_negation += to_pay * max(0, (1 - OxReg.get_strain_percent())) if(regen_tox) nutrition_debt = H.getToxLoss() H.adjustToxLoss(-heal_rate * starve_mod) - nutrition_cost += nutrition_debt - H.getToxLoss() + + to_pay = nutrition_debt - H.getToxLoss() + + nutrition_cost += to_pay + + var/obj/item/organ/internal/regennetwork/ToxReg = H.internal_organs_by_name[O_REGTOX] + + if(ToxReg) + strain_negation += to_pay * max(0, (1 - ToxReg.get_strain_percent())) H.nutrition -= (3 * nutrition_cost) //Costs Nutrition when damage is being repaired, corresponding to the amount of damage being repaired. H.nutrition = max(0, H.nutrition) //Ensure it's not below 0. - var/agony_to_apply = ((1 / starve_mod) * nutrition_cost) //Regenerating damage causes minor pain over time. Small injures will be no issue, large ones will cause problems. + var/agony_to_apply = ((1 / starve_mod) * (nutrition_cost - strain_negation)) //Regenerating damage causes minor pain over time, if the organs responsible are nonexistant or too high on strain. Small injures will be no issue, large ones will cause problems. if((starve_mod <= 0.5 && (H.getHalLoss() + agony_to_apply) <= 90) || ((H.getHalLoss() + agony_to_apply) <= 70)) // Will max out at applying halloss at 70, unless they are starving; starvation regeneration will bring them up to a maximum of 120, the same amount of agony a human receives from three taser hits. H.apply_damage(agony_to_apply, HALLOSS) diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm index e5dd8bf63ec..e6fde9860fa 100644 --- a/code/modules/mob/living/living.dm +++ b/code/modules/mob/living/living.dm @@ -1060,7 +1060,7 @@ default behaviour is: var/mob/living/carbon/human/H = src if(!H.isSynthetic()) var/obj/item/organ/internal/liver/L = H.internal_organs_by_name["liver"] - if(L.is_broken()) + if(!L || L.is_broken()) blood_vomit = 1 Stun(5) diff --git a/code/modules/organs/organ.dm b/code/modules/organs/organ.dm index 579e7776b79..215ef65ced8 100644 --- a/code/modules/organs/organ.dm +++ b/code/modules/organs/organ.dm @@ -78,6 +78,7 @@ var/list/organ_cache = list() if(E.internal_organs == null) E.internal_organs = list() E.internal_organs |= src + H.internal_organs_by_name[organ_tag] = src if(dna) if(!blood_DNA) blood_DNA = list() diff --git a/code/modules/organs/subtypes/slime.dm b/code/modules/organs/subtypes/slime.dm index f22b90caea2..5fb54a21b45 100644 --- a/code/modules/organs/subtypes/slime.dm +++ b/code/modules/organs/subtypes/slime.dm @@ -56,3 +56,89 @@ max_damage = 30 encased = 0 spread_dam = 1 + +/* + * Internal Slime organs. + */ + +/obj/item/organ/internal/heart/grey/colormatch/slime + name = "pneumatic network" + desc = "A disgusting sac of goo." + icon_state = "sac_slime" + dead_icon = null + standard_pulse_level = PULSE_NONE + +/obj/item/organ/internal/heart/grey/colormatch/slime/process() + ..() + if(!(QDELETED(src)) && src.loc != owner) + visible_message("\The [src] splatters!") + var/turf/T = get_turf(src) + var/obj/effect/decal/cleanable/blood/B = new (T) + + B.basecolor = src.color + B.update_icon() + qdel(src) + +/obj/item/organ/internal/regennetwork + name = "pneumoregenesis network" + parent_organ = BP_TORSO + organ_tag = O_REGBRUTE + + icon_state = "sac_slime" + + var/strain = 0 // The amount of stress this organ is under. Capped at min_broken_damage, usually half its max damage. + + var/last_strain_increase = 0 // World time of the last increase in strain. + var/strain_regen_cooldown = 5 MINUTES + +/obj/item/organ/internal/regennetwork/Initialize() + ..() + var/mob/living/carbon/human/H = null + spawn(15) + if(ishuman(owner)) + H = owner + color = H.species.get_blood_colour(H) + +/obj/item/organ/internal/regennetwork/proc/get_strain_percent(var/cost) + adjust_strain(cost) + + if((status & ORGAN_CUT_AWAY) || (status & ORGAN_BROKEN) || (status & ORGAN_DEAD)) + return 1 + + return round((strain / min_broken_damage) * 10) / 10 + +/obj/item/organ/internal/regennetwork/proc/adjust_strain(var/amount) + if(amount < 0 && world.time < (last_strain_increase + strain_regen_cooldown)) + return + + else if(amount > 0) + last_strain_increase = world.time + + strain = CLAMP(strain + amount, 0, min_broken_damage) + +/obj/item/organ/internal/regennetwork/process() + ..() + + if(!(QDELETED(src)) && src.loc != owner) + visible_message("\The [src] splatters!") + var/turf/T = get_turf(src) + var/obj/effect/decal/cleanable/blood/B = new (T) + + B.basecolor = src.color + B.update_icon() + qdel(src) + + if(src && !is_bruised()) + adjust_strain(-0.25 * max(0, (min_broken_damage - damage) / min_broken_damage)) // Decrease the current strain with respect to the current strain level. + +/obj/item/organ/internal/regennetwork/burn + name = "thermoregenesis network" + organ_tag = O_REGBURN + +/obj/item/organ/internal/regennetwork/oxy + name = "respiroregenesis network" + organ_tag = O_REGOXY + +/obj/item/organ/internal/regennetwork/tox + name = "toxoregenesis network" + organ_tag = O_REGTOX diff --git a/html/changelogs/Mechoid - Promethean Organs.yml b/html/changelogs/Mechoid - Promethean Organs.yml new file mode 100644 index 00000000000..c579478d5a9 --- /dev/null +++ b/html/changelogs/Mechoid - Promethean Organs.yml @@ -0,0 +1,40 @@ +################################ +# Example Changelog File +# +# Note: This file, and files beginning with ".", and files that don't end in ".yml" will not be read. If you change this file, you will look really dumb. +# +# Your changelog will be merged with a master changelog. (New stuff added only, and only on the date entry for the day it was merged.) +# When it is, any changes listed below will disappear. +# +# Valid Prefixes: +# bugfix +# wip (For works in progress) +# tweak +# soundadd +# sounddel +# rscadd (general adding of nice things) +# rscdel (general deleting of nice things) +# imageadd +# imagedel +# maptweak +# spellcheck (typo fixes) +# experiment +################################# + +# Your name. +author: Mechoid + +# Optional: Remove this file after generating master changelog. Useful for PR changelogs that won't get used again. +delete-after: True + +# Any changes you've made. See valid prefix list above. +# INDENT WITH TWO SPACES. NOT TABS. SPACES. +# SCREW THIS UP AND IT WON'T WORK. +# Also, all entries are changed into a single [] after a master changelog generation. Just remove the brackets when you add new entries. +# Please surround your changes in double quotes ("), as certain characters otherwise screws up compiling. The quotes will not show up in the changelog. +changes: + - rscadd: "Added multiple new organs for Prometheans. Removing them will cause them to take large amounts of Toxloss untill they are Regenerated using the active regeneration verb." + - rscadd: "Organ: pneumatic network, a series of skeletal tubes with high pressure used to move nutrients and waste." + - rscadd: "Organs: -regenesis systems, different 'networks' of clumped cellular matter that allow Prometheans to recover rapidly from small injuries. Large or numerous injuries cause un-needed stress, and pain." + - bugfix: "Internal organs now properly add themselves to the internal organ-by-name list, the one referenced 99.9% of the time." + - tweak: "Active regeneration will now replace internal organs if they are nonexistant, as it does for limbs." diff --git a/icons/obj/surgery.dmi b/icons/obj/surgery.dmi index 12bededf903..5d28658eed7 100644 Binary files a/icons/obj/surgery.dmi and b/icons/obj/surgery.dmi differ