From c3861eba6a4420fcced7de66c1dec94df60b6dbe Mon Sep 17 00:00:00 2001 From: Wildkins Date: Fri, 30 Apr 2021 23:00:29 -0400 Subject: [PATCH] Datumize tendon behavior, make tendon snapping more consistent (#11773) --- aurorastation.dme | 1 + code/__defines/damage_organs.dm | 5 +- code/game/gamemodes/cult/structures/altar.dm | 4 +- code/game/gamemodes/vampire/vampire_powers.dm | 4 +- code/game/machinery/body_scanner.dm | 6 +- code/game/objects/items/devices/scanners.dm | 2 +- code/modules/organs/organ_external.dm | 52 +++++++----------- code/modules/organs/subtypes/parasite.dm | 4 +- code/modules/organs/subtypes/standard.dm | 6 +- code/modules/organs/tendons.dm | 55 +++++++++++++++++++ .../psionics/complexus/complexus_process.dm | 4 +- code/modules/psionics/faculties/redaction.dm | 4 +- .../Chemistry-Reagents-Medicine.dm | 4 +- .../spells/spell_list/others/generic/mend.dm | 6 +- code/modules/surgery/other.dm | 4 +- 15 files changed, 99 insertions(+), 62 deletions(-) create mode 100644 code/modules/organs/tendons.dm diff --git a/aurorastation.dme b/aurorastation.dme index 39cc61ad5bc..ed99b98a33e 100644 --- a/aurorastation.dme +++ b/aurorastation.dme @@ -2353,6 +2353,7 @@ #include "code\modules\organs\organ_stump.dm" #include "code\modules\organs\pain.dm" #include "code\modules\organs\robolimbs.dm" +#include "code\modules\organs\tendons.dm" #include "code\modules\organs\wound.dm" #include "code\modules\organs\internal\_internal.dm" #include "code\modules\organs\internal\appendix.dm" diff --git a/code/__defines/damage_organs.dm b/code/__defines/damage_organs.dm index d7243e67485..42418f1a6a3 100644 --- a/code/__defines/damage_organs.dm +++ b/code/__defines/damage_organs.dm @@ -46,11 +46,10 @@ #define ORGAN_ADV_ROBOT (1<<9) #define ORGAN_PLANT (1<<10) #define ORGAN_ARTERY_CUT (1<<11) -#define ORGAN_TENDON_CUT (1<<12) -#define ORGAN_LIFELIKE (1<<13) // Robotic, made to appear organic. +#define ORGAN_LIFELIKE (1<<12) // Robotic, made to appear organic. // the largest bitflag, in the WORLD -#define ORGAN_DAMAGE_STATES ORGAN_CUT_AWAY|ORGAN_BLEEDING|ORGAN_BROKEN|ORGAN_DESTROYED|ORGAN_SPLINTED|ORGAN_DEAD|ORGAN_MUTATED|ORGAN_ARTERY_CUT|ORGAN_TENDON_CUT +#define ORGAN_DAMAGE_STATES ORGAN_CUT_AWAY|ORGAN_BLEEDING|ORGAN_BROKEN|ORGAN_DESTROYED|ORGAN_SPLINTED|ORGAN_DEAD|ORGAN_MUTATED|ORGAN_ARTERY_CUT // Limb behaviour defines. #define ORGAN_CAN_AMPUTATE (1<<0) //Can this organ be amputated? diff --git a/code/game/gamemodes/cult/structures/altar.dm b/code/game/gamemodes/cult/structures/altar.dm index c472aa000f8..6c21b0c34d8 100644 --- a/code/game/gamemodes/cult/structures/altar.dm +++ b/code/game/gamemodes/cult/structures/altar.dm @@ -18,10 +18,10 @@ to_chat(H, SPAN_WARNING("Severed artery found in [O.name], repairing...")) if(do_after(user, 20)) O.status &= ~ORGAN_ARTERY_CUT - if(O.status & ORGAN_TENDON_CUT) + if(istype(O.tendon) && !O.tendon.intact) to_chat(H, SPAN_WARNING("Severed tendon found in [O.name], repairing...")) if(do_after(user, 20)) - O.status &= ~ORGAN_TENDON_CUT + O.tendon.heal() if(O.status & ORGAN_BROKEN) to_chat(H, SPAN_WARNING("Broken bone found in [O.name], repairing...")) if(do_after(user, 20)) diff --git a/code/game/gamemodes/vampire/vampire_powers.dm b/code/game/gamemodes/vampire/vampire_powers.dm index d8a5674f4da..eb170594848 100644 --- a/code/game/gamemodes/vampire/vampire_powers.dm +++ b/code/game/gamemodes/vampire/vampire_powers.dm @@ -616,8 +616,8 @@ if(E.status & ORGAN_ARTERY_CUT) E.status &= ~ORGAN_ARTERY_CUT blood_used += 2 - if(E.status & ORGAN_TENDON_CUT) - E.status &= ~ORGAN_TENDON_CUT + if(istype(E.tendon) && !E.tendon.intact) + E.tendon.heal() blood_used += 2 if(E.status & ORGAN_BROKEN) E.status &= ~ORGAN_BROKEN diff --git a/code/game/machinery/body_scanner.dm b/code/game/machinery/body_scanner.dm index dbd86a1c290..7578b0191b7 100644 --- a/code/game/machinery/body_scanner.dm +++ b/code/game/machinery/body_scanner.dm @@ -503,8 +503,8 @@ wounds += "Appears to be composed of inorganic material." if (O.status & ORGAN_ARTERY_CUT) wounds += "Severed [O.artery_name]." - if (O.status & ORGAN_TENDON_CUT) - wounds += "Severed [O.tendon_name]." + if(istype(O.tendon) && !O.tendon.intact) + wounds += "Severed [O.tendon.name]." if (O.status & ORGAN_SPLINTED) wounds += "Splinted." if (O.status & ORGAN_BLEEDING) @@ -714,7 +714,7 @@ if(e.status & ORGAN_ARTERY_CUT) internal_bleeding = "Arterial bleeding." - if(e.status & ORGAN_TENDON_CUT) + if(istype(e.tendon) && !e.tendon.intact) severed_tendon = "Severed tendon." if(istype(e, /obj/item/organ/external/chest) && occ["lung_ruptured"]) lung_ruptured = "Lung ruptured." diff --git a/code/game/objects/items/devices/scanners.dm b/code/game/objects/items/devices/scanners.dm index b152e9e9122..b11b9aeeaa2 100644 --- a/code/game/objects/items/devices/scanners.dm +++ b/code/game/objects/items/devices/scanners.dm @@ -248,7 +248,7 @@ BREATH ANALYZER if(!found_bleed && (e.status & ORGAN_ARTERY_CUT)) dat += "Arterial bleeding detected. Advanced scanner required for location." found_bleed = TRUE - if(!found_tendon && (e.status & ORGAN_TENDON_CUT)) + if(!found_tendon && (istype(e.tendon) && !e.tendon.intact)) dat += "Tendon or ligament damage detected. Advanced scanner required for location." found_tendon = TRUE if(found_disloc && found_bleed && found_tendon) diff --git a/code/modules/organs/organ_external.dm b/code/modules/organs/organ_external.dm index 97cc4b8c92e..e732d3689a6 100644 --- a/code/modules/organs/organ_external.dm +++ b/code/modules/organs/organ_external.dm @@ -63,6 +63,12 @@ var/supports_children = TRUE var/list/internal_organs = list() // Internal organs of this body part + var/datum/tendon/tendon + var/tendon_path = /datum/tendon + var/tendon_name = "tendon" // Name of the limb's tendon. Achilles heel, etc. + var/tendon_dt // Damage threshold required to possibly snap a tendon + var/list/tendon_msgs = list("tore apart", "ripped away") + var/damage_msg = "You feel an intense pain!" var/broken_description var/open = 0 @@ -72,7 +78,6 @@ var/encased // Needs to be opened with a saw to access the organs. var/joint = "joint" // Descriptive string used in dislocation. var/artery_name = "artery" //Name of the artery. Cartoid, etc. - var/tendon_name = "tendon" //Name of the limb's tendon. Achilles heel, etc. var/amputation_point // Descriptive string used in amputation. var/dislocated = 0 // If you target a joint, you can dislocate the limb, causing temporary damage to the organ. @@ -227,6 +232,9 @@ get_icon() + if((limb_flags & ORGAN_HAS_TENDON) && !BP_IS_ROBOTIC(src)) + tendon = new tendon_path(src, tendon_name, tendon_dt, tendon_msgs) + /obj/item/organ/external/replaced(var/mob/living/carbon/human/target) ..() if(istype(owner)) @@ -291,8 +299,8 @@ handle_limb_gibbing(used_weapon, brute, burn) if(brute_dam + brute > min_broken_damage && prob(brute_dam + brute * (1 + blunt))) - if(damage_flags & DAM_EDGE) - sever_tendon() + if((brute && !blunt) && istype(tendon) && brute_dam + brute > tendon.threshold) + tendon.sever() if(brute_dam > FRACTURE_AND_TENDON_DAM_THRESHOLD) fracture() else @@ -472,14 +480,14 @@ This function completely restores a damaged organ to perfect condition. //Possibly trigger an internal wound, too. var/local_damage = brute_dam + burn_dam + damage if(damage > 15 && !(type in list(BURN, LASER)) && local_damage > 30 && !(status & ORGAN_ROBOT)) - var/internal_damage if(prob(damage) && sever_artery()) - internal_damage = TRUE - if(prob(Ceiling(damage / 4)) && type == CUT && sever_tendon()) - internal_damage = TRUE - if(internal_damage) owner.custom_pain("You feel something rip in your [name]!", 25) + if(istype(tendon) && type == CUT && !(status & ORGAN_ROBOT)) + var/DT = tendon.threshold + if(DT && local_damage > DT && damage > (DT / 2) && prob(damage)) + tendon.sever() + //Burn damage can cause fluid loss due to blistering and cook-off if((type in list(BURN, LASER)) && (damage > 5 || damage + burn_dam >= 15) && !BP_IS_ROBOTIC(src)) var/fluid_loss_severity @@ -814,10 +822,7 @@ Note that amputating the affected organ does in fact remove the infection from t //Bone fractures if(config.bones_can_break && brute_dam > min_broken_damage * config.organ_health_multiplier && !(status & ORGAN_ROBOT)) - if(cut_dam > brute_dam * 0.5) - sever_tendon() - else - fracture() + fracture() update_damage_ratios() /obj/item/organ/external/proc/update_damage_ratios() @@ -1150,9 +1155,9 @@ Note that amputating the affected organ does in fact remove the infection from t /obj/item/organ/external/is_usable() if(is_dislocated()) return FALSE - if(status & ORGAN_TENDON_CUT) + if(istype(tendon) && !tendon.intact) return FALSE - if(parent && (parent.status & ORGAN_TENDON_CUT)) + if(parent && (istype(parent.tendon) && !parent.tendon.intact)) return FALSE if(can_feel_pain() && get_pain() > pain_disability_threshold) return FALSE @@ -1356,25 +1361,6 @@ Note that amputating the affected organ does in fact remove the infection from t status |= ORGAN_ARTERY_CUT return TRUE -/obj/item/organ/external/proc/sever_tendon() - if(!(limb_flags & ORGAN_HAS_TENDON) || (status & ORGAN_ROBOT) || (status & ORGAN_TENDON_CUT)) - return FALSE - - . = TRUE - playsound(src.loc, 'sound/effects/snap.ogg', 40, 1, -2) - status |= ORGAN_TENDON_CUT - if(!owner) - return - - var/message = pick("tore apart", "ripped away") - owner.visible_message(\ - "You hear a loud snapping sound coming from \the [owner]!",\ - "Something feels like it [message] in your [name]!",\ - "You hear a sickening snap!") - if(owner.species && owner.can_feel_pain()) - owner.emote("scream") - owner.flash_strong_pain() - // Damage procs /obj/item/organ/external/proc/get_brute_damage() return brute_dam diff --git a/code/modules/organs/subtypes/parasite.dm b/code/modules/organs/subtypes/parasite.dm index 3b45175eb52..da321ba6c94 100644 --- a/code/modules/organs/subtypes/parasite.dm +++ b/code/modules/organs/subtypes/parasite.dm @@ -251,8 +251,8 @@ O.status &= ~ORGAN_ARTERY_CUT owner.visible_message(SPAN_WARNING("The severed artery in \the [owner]'s [O] stitches itself back together..."), SPAN_NOTICE("The severed artery in your [O] stitches itself back together...")) healed = TRUE - else if(O.status & ORGAN_TENDON_CUT) - O.status &= ~ORGAN_TENDON_CUT + else if(istype(O.tendon) && !O.tendon.intact) + O.tendon.heal() owner.visible_message(SPAN_WARNING("The severed tendon in \the [owner]'s [O] stitches itself back together..."), SPAN_NOTICE("The severed tendon in your [O] stitches itself back together...")) healed = TRUE else if(O.status & ORGAN_BROKEN) diff --git a/code/modules/organs/subtypes/standard.dm b/code/modules/organs/subtypes/standard.dm index 5dc6a68eeca..a5cb54c25ab 100644 --- a/code/modules/organs/subtypes/standard.dm +++ b/code/modules/organs/subtypes/standard.dm @@ -176,10 +176,6 @@ . = ..() owner.update_hud_hands() -/obj/item/organ/external/hand/sever_tendon() - . = ..() - owner.update_hud_hands() - /obj/item/organ/external/hand/removed() owner.drop_from_inventory(owner.gloves) owner.update_hud_hands() @@ -256,4 +252,4 @@ /obj/item/organ/external/head/droplimb(var/clean, var/disintegrate = DROPLIMB_EDGE, var/ignore_children = null) if(iszombie(owner)) return ..(disintegrate = DROPLIMB_BLUNT) - return ..() \ No newline at end of file + return ..() diff --git a/code/modules/organs/tendons.dm b/code/modules/organs/tendons.dm new file mode 100644 index 00000000000..443ebceb675 --- /dev/null +++ b/code/modules/organs/tendons.dm @@ -0,0 +1,55 @@ +/datum/tendon + var/name = "tendon" + var/threshold + var/intact = TRUE + + var/list/messages + + var/obj/item/organ/external/parent + +/datum/tendon/New(var/obj/item/organ/external/E, var/name, var/damage_threshold, var/list/damage_msgs) + if(!istype(E)) + crash_with("Tendon created with invalid parent organ: [E]") + qdel(src) + return + + parent = E + + if(name) + src.name = name + if(islist(damage_msgs)) + messages = damage_msgs + + if(damage_threshold) + threshold = damage_threshold + else + threshold = parent.min_broken_damage + +/datum/tendon/proc/heal() + if(!parent?.owner || intact) + return FALSE + + . = intact = TRUE + +/datum/tendon/proc/sever() + if(!parent?.owner || !intact) + return FALSE + + playsound(parent.owner.loc, 'sound/effects/snap.ogg', 40, 1, -2) + intact = FALSE + + if(parent.owner.species && parent.owner.can_feel_pain()) + parent.owner.emote("scream") + parent.owner.flash_strong_pain() + parent.owner.custom_pain("You feel something [pick(messages)] in your [parent.owner.name]!", 25) + parent.owner.visible_message(SPAN_WARNING("You hear a loud snapping sound coming from [parent.owner]!"), + blind_message = "You hear a sickening snap!") + else + parent.owner.visible_message(SPAN_WARNING("You hear a loud snapping sound coming from [parent.owner]!"),\ + SPAN_DANGER("Something feels like it [pick(messages)] in your [parent.name]!"),\ + "You hear a sickening snap!") + + if(istype(parent, /obj/item/organ/external/hand)) + parent.owner.update_hud_hands() + + return TRUE diff --git a/code/modules/psionics/complexus/complexus_process.dm b/code/modules/psionics/complexus/complexus_process.dm index 6945df397c8..0cae991b7e2 100644 --- a/code/modules/psionics/complexus/complexus_process.dm +++ b/code/modules/psionics/complexus/complexus_process.dm @@ -190,9 +190,9 @@ E.status &= ~ORGAN_ARTERY_CUT return - if(E.status & ORGAN_TENDON_CUT) + if(istype(E.tendon) && !E.tendon.intact) to_chat(H, SPAN_NOTICE("Your autoredactive faculty repairs the severed tendon in your [E.name].")) - E.status &= ~ORGAN_TENDON_CUT + E.tendon.heal() return TRUE for(var/datum/wound/W in E.wounds) diff --git a/code/modules/psionics/faculties/redaction.dm b/code/modules/psionics/faculties/redaction.dm index 9727426001f..448d1201752 100644 --- a/code/modules/psionics/faculties/redaction.dm +++ b/code/modules/psionics/faculties/redaction.dm @@ -83,9 +83,9 @@ to_chat(user, SPAN_NOTICE("You painstakingly mend the torn veins in \the [E], stemming the internal bleeding.")) E.status &= ~ORGAN_ARTERY_CUT return TRUE - if(E.status & ORGAN_TENDON_CUT) + if(istype(E.tendon) && !E.tendon.intact) to_chat(user, SPAN_NOTICE("You interleave and repair the severed tendon in \the [E].")) - E.status &= ~ORGAN_TENDON_CUT + E.tendon.heal() return TRUE if(E.status & ORGAN_BROKEN) to_chat(user, SPAN_NOTICE("You coax shattered bones to come together and fuse, mending the break.")) diff --git a/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Medicine.dm b/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Medicine.dm index 1f8b1acff62..7e1c97eab67 100644 --- a/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Medicine.dm +++ b/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Medicine.dm @@ -1279,8 +1279,8 @@ var/mob/living/carbon/human/H = M for (var/A in H.organs) var/obj/item/organ/external/E = A - if(E.status & ORGAN_TENDON_CUT) - E.status &= ~ORGAN_TENDON_CUT + if(istype(E.tendon) && !E.tendon.intact) + E.tendon.heal() return 1 if(E.status & ORGAN_ARTERY_CUT) diff --git a/code/modules/spell_system/spells/spell_list/others/generic/mend.dm b/code/modules/spell_system/spells/spell_list/others/generic/mend.dm index a68755fd606..b7796b08caa 100644 --- a/code/modules/spell_system/spells/spell_list/others/generic/mend.dm +++ b/code/modules/spell_system/spells/spell_list/others/generic/mend.dm @@ -67,9 +67,9 @@ E.stage = 0 return 1 - if(E.status & ORGAN_TENDON_CUT) + if(istype(E.tendon) && !E.tendon.intact) to_chat(user, "You place your hands over [target]'s [E.name], joining the two ends of their [E.tendon_name] in the process.") - E.status &= ~ORGAN_TENDON_CUT + E.tendon.heal() return 1 for(var/obj/item/organ/I in E.internal_organs) @@ -79,4 +79,4 @@ return 1 to_chat(user, "You can find nothing within \the [target]'s [E.name] to mend.") - return 1 \ No newline at end of file + return 1 diff --git a/code/modules/surgery/other.dm b/code/modules/surgery/other.dm index edeec246065..925c7ce5374 100644 --- a/code/modules/surgery/other.dm +++ b/code/modules/surgery/other.dm @@ -201,7 +201,7 @@ return FALSE var/obj/item/organ/external/affected = target.get_organ(target_zone) - return affected && (affected.status & ORGAN_TENDON_CUT) && affected.open >= ORGAN_OPEN_RETRACTED + return affected && istype(affected.tendon) && !affected.tendon.intact && affected.open >= ORGAN_OPEN_RETRACTED /decl/surgery_step/fix_tendon/begin_step(mob/user, mob/living/carbon/human/target, target_zone, obj/item/tool) var/obj/item/organ/external/affected = target.get_organ(target_zone) @@ -214,7 +214,7 @@ var/obj/item/organ/external/affected = target.get_organ(target_zone) user.visible_message(SPAN_NOTICE("[user] has reattached the [affected.tendon_name] in [target]'s [affected.name] with \the [tool]."), \ SPAN_NOTICE("You have reattached the [affected.tendon_name] in [target]'s [affected.name] with \the [tool].")) - affected.status &= ~ORGAN_TENDON_CUT + affected.tendon.heal() affected.update_damages() /decl/surgery_step/fix_tendon/fail_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)