Files
VMSolidus 0625b841c3 Surgery Speed Modifiers (#22472)
This PR "gently refactors" surgery doafter timers to be deterministic
and variable. Instead of being simply a random number of seconds between
an upper and lower bounds, surgeries now have a base amount of time they
take to perform (in fractional seconds). This doafter time can then be
modified via signal interactions, such as coming from components.

The Morale component, Surgery skill, Anatomy skill, and Xenobiology
skill all have had signal hooks for surgery speed added, while the
latter two are uniquely conditional signal modifiers. Anatomy only
provides its modifier if the target's species matches your own, while
Xenobiology only applies its modifier if the target is an alien. Morale
can situationally either give a bonus or a penalty depending on your
current amount of morale points.

So to offset that this is now significantly more variable and that 4
different sources of bonus surgical speed exist, I've actually made the
base surgery times always on the upper end of what their previous
doafter duration range was, so surgeries are in general slower if you
aren't taking advantage of specializing in it.

Signed-off-by: VMSolidus <evilexecutive@gmail.com>
2026-06-19 16:47:29 +00:00

214 lines
9.0 KiB
Plaintext

//Procedures in this file: Generic ribcage opening steps, Removing alien embryo, Fixing internal organs.
//////////////////////////////////////////////////////////////////
// GENERIC RIBCAGE SURGERY //
//////////////////////////////////////////////////////////////////
/singleton/surgery_step/open_encased
name = "Saw Through Bone"
priority = 2
can_infect = TRUE
blood_level = 1
skill_requirements = alist(SURGERY_SKILL_COMPONENT = SKILL_LEVEL_TRAINED)
/singleton/surgery_step/open_encased/can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
if(!..())
return FALSE
var/obj/item/organ/external/affected = target.get_organ(target_zone)
return affected && !BP_IS_ROBOTIC(affected) && affected.encased && affected.open >= ORGAN_OPEN_RETRACTED
/singleton/surgery_step/open_encased/saw
allowed_tools = list(
TOOL_SAW = 100,
/obj/item/melee/energy = 100,
/obj/item/melee/chainsword = 70,
/obj/item/material/hatchet = 75
)
base_surgery_time = 5 SECONDS
/singleton/surgery_step/open_encased/saw/can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
if(!..())
return FALSE
var/obj/item/organ/external/affected = target.get_organ(target_zone)
return affected && affected.open == ORGAN_OPEN_RETRACTED
/singleton/surgery_step/open_encased/saw/begin_step(mob/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
if(!ishuman(target))
return
var/obj/item/organ/external/affected = target.get_organ(target_zone)
user.visible_message("[user] begins to cut through [target]'s [affected.encased] with \the [tool].", \
"You begin to cut through [target]'s [affected.encased] with \the [tool].")
target.custom_pain("Something hurts horribly in your [affected.name]!", 75)
..()
/singleton/surgery_step/open_encased/saw/end_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
if(!ishuman(target))
return
var/obj/item/organ/external/affected = target.get_organ(target_zone)
user.visible_message("<b>[user]</b> has cut [target]'s [affected.encased] open with \the [tool].", \
SPAN_NOTICE("You have cut [target]'s [affected.encased] open with \the [tool]."))
affected.open = ORGAN_ENCASED_OPEN
/singleton/surgery_step/open_encased/saw/fail_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
if(!ishuman(target))
return
var/obj/item/organ/external/affected = target.get_organ(target_zone)
user.visible_message(SPAN_WARNING("[user]'s hand slips, cracking [target]'s [affected.encased] with \the [tool]!") , \
SPAN_WARNING("Your hand slips, cracking [target]'s [affected.encased] with \the [tool]!") )
target.apply_damage(20, DAMAGE_BRUTE, target_zone, 0, tool, damage_flags = tool.damage_flags())
affected.fracture()
/singleton/surgery_step/open_encased/retract
name = "Retract Sawed Bone"
allowed_tools = list(
TOOL_RETRACTOR = 100, \
TOOL_CROWBAR = 75
)
base_surgery_time = 3 SECONDS
skill_requirements = alist(SURGERY_SKILL_COMPONENT = SKILL_LEVEL_TRAINED)
/singleton/surgery_step/open_encased/retract/can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
if(!..())
return FALSE
var/obj/item/organ/external/affected = target.get_organ(target_zone)
return affected && affected.open == ORGAN_ENCASED_OPEN
/singleton/surgery_step/open_encased/retract/begin_step(mob/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
if(!ishuman(target))
return
var/obj/item/organ/external/affected = target.get_organ(target_zone)
var/msg = "[user] starts to force open the [affected.encased] in [target]'s [affected.name] with \the [tool]."
var/self_msg = "You start to force open the [affected.encased] in [target]'s [affected.name] with \the [tool]."
user.visible_message(msg, self_msg)
target.custom_pain("Something hurts horribly in your [affected.name]!", 75)
..()
/singleton/surgery_step/open_encased/retract/end_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
if(!ishuman(target))
return
var/obj/item/organ/external/affected = target.get_organ(target_zone)
var/msg = "<b>[user]</b> forces open [target]'s [affected.encased] with \the [tool]."
var/self_msg = "You force open [target]'s [affected.encased] with \the [tool]."
user.visible_message(msg, SPAN_NOTICE(self_msg))
..()
affected.open = ORGAN_ENCASED_RETRACTED
for(var/obj/item/implant/I in affected.implants)
I.exposed()
/singleton/surgery_step/open_encased/retract/fail_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
if(!ishuman(target))
return
var/obj/item/organ/external/affected = target.get_organ(target_zone)
var/msg = SPAN_WARNING("[user]'s hand slips, cracking [target]'s [affected.encased]!")
var/self_msg = SPAN_WARNING("Your hand slips, cracking [target]'s [affected.encased]!")
user.visible_message(msg, self_msg)
target.apply_damage(20, DAMAGE_BRUTE, target_zone, 0, tool, damage_flags = tool.damage_flags())
affected.fracture()
/singleton/surgery_step/open_encased/close
name = "Bend Sawed Bone Closed"
allowed_tools = list(
TOOL_RETRACTOR = 100, \
TOOL_CROWBAR = 75
)
base_surgery_time = 3 SECONDS
skill_requirements = alist(SURGERY_SKILL_COMPONENT = SKILL_LEVEL_TRAINED)
/singleton/surgery_step/open_encased/close/can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
if(!..())
return FALSE
var/obj/item/organ/external/affected = target.get_organ(target_zone)
return affected && affected.open == ORGAN_ENCASED_RETRACTED
/singleton/surgery_step/open_encased/close/begin_step(mob/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
if(!ishuman(target))
return
var/obj/item/organ/external/affected = target.get_organ(target_zone)
var/msg = "[user] starts bending [target]'s [affected.encased] back into place with \the [tool]."
var/self_msg = "You start bending [target]'s [affected.encased] back into place with \the [tool]."
user.visible_message(msg, self_msg)
target.custom_pain("Something hurts horribly in your [affected.name]!", 75)
..()
/singleton/surgery_step/open_encased/close/end_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
if(!ishuman(target))
return
var/obj/item/organ/external/affected = target.get_organ(target_zone)
var/msg = "<b>[user]</b> bends [target]'s [affected.encased] back into place with \the [tool]."
var/self_msg = "You bend [target]'s [affected.encased] back into place with \the [tool]."
user.visible_message(msg, SPAN_NOTICE(self_msg))
target.custom_pain("Something hurts horribly in your [affected.name]!", 75)
..()
affected.open = ORGAN_ENCASED_OPEN
/singleton/surgery_step/open_encased/close/fail_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
if(!ishuman(target))
return
var/obj/item/organ/external/affected = target.get_organ(target_zone)
var/msg = SPAN_WARNING("[user]'s hand slips, bending [target]'s [affected.encased] the wrong way!")
var/self_msg = SPAN_WARNING("Your hand slips, bending [target]'s [affected.encased] the wrong way!")
user.visible_message(msg, self_msg)
target.apply_damage(20, DAMAGE_BRUTE, target_zone, 0, tool, damage_flags = tool.damage_flags())
affected.fracture()
if(affected.internal_organs && affected.internal_organs.len)
if(prob(40))
var/obj/item/organ/O = pick(affected.internal_organs) //TODO weight by organ size
user.visible_message(SPAN_DANGER("A wayward piece of [target]'s [affected.encased] pierces [target.get_pronoun("his")] [O.name]!"))
O.bruise()
/singleton/surgery_step/open_encased/mend
name = "Repair Sawed Bone"
allowed_tools = list(
/obj/item/surgery/bone_gel = 100, \
/obj/item/tape_roll = 60
)
base_surgery_time = 3 SECONDS
skill_requirements = alist(SURGERY_SKILL_COMPONENT = SKILL_LEVEL_TRAINED)
/singleton/surgery_step/open_encased/mend/can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
if(!..())
return FALSE
var/obj/item/organ/external/affected = target.get_organ(target_zone)
return affected && affected.open == ORGAN_ENCASED_OPEN
/singleton/surgery_step/open_encased/mend/begin_step(mob/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
if(!ishuman(target))
return
var/obj/item/organ/external/affected = target.get_organ(target_zone)
var/msg = "[user] starts applying \the [tool] to [target]'s [affected.encased]."
var/self_msg = "You start applying \the [tool] to [target]'s [affected.encased]."
user.visible_message(msg, self_msg)
target.custom_pain("Something hurts horribly in your [affected.name]!", 75)
..()
/singleton/surgery_step/open_encased/mend/end_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
if(!ishuman(target))
return
var/obj/item/organ/external/affected = target.get_organ(target_zone)
var/msg = "<b>[user]</b> applies some of \the [tool] to [target]'s [affected.encased]."
var/self_msg = "You apply some of \the [tool] to [target]'s [affected.encased]."
user.visible_message(msg, SPAN_NOTICE(self_msg))
target.custom_pain("Something hurts horribly in your [affected.name]!", 75)
..()
affected.open = ORGAN_OPEN_RETRACTED