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

277 lines
14 KiB
Plaintext

//////////////////////////////////////////////////////////////////
// MEDIBOTS DREAM COME TRUE! //
// Plastic Surgery+Facial Repair //
//////////////////////////////////////////////////////////////////
/singleton/surgery_step/face
name = "Retract Facial Incisions"
priority = 2
can_infect = FALSE
skill_requirements = alist(SURGERY_SKILL_COMPONENT = SKILL_LEVEL_TRAINED)
/singleton/surgery_step/face/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)
if(!affected || BP_IS_ROBOTIC(affected))
return FALSE
return target_zone == BP_MOUTH
/singleton/surgery_step/generic/prepare_face
allowed_tools = list(
TOOL_RETRACTOR = 100,
/obj/item/material/knife/tacknife = 75
)
base_surgery_time = 9 SECONDS
skill_requirements = alist(SURGERY_SKILL_COMPONENT = SKILL_LEVEL_TRAINED)
skill_diff_fail_modifier = SURGERY_DIFFICULTY_MEDIUM
/singleton/surgery_step/generic/prepare_face/can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
return ..() && target_zone == BP_MOUTH && target.op_stage.face == FACE_CUT_OPEN
/singleton/surgery_step/generic/prepare_face/begin_step(mob/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
user.visible_message("[user] starts to retract [target]'s face with \the [tool].", \
"You start to retract [target]'s face with \the [tool].")
..()
/singleton/surgery_step/generic/prepare_face/end_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
user.visible_message("<b>[user]</b> has retracted [target]'s face with \the [tool] for his facial alteration." , \
SPAN_NOTICE("You have retracted [target]'s face and neck with \the [tool] for plastic surgery."),)
target.op_stage.face = FACE_RETRACTED
/singleton/surgery_step/generic/prepare_face/fail_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
user.visible_message(SPAN_WARNING("[user]'s hand slips, slicing [target]'s throat wth \the [tool]!") , \
SPAN_WARNING("Your hand slips, slicing [target]'s throat wth \the [tool]!") )
target.apply_damage(40, DAMAGE_BRUTE, target_zone, 0, tool, damage_flags = tool.damage_flags())
target.apply_damage(20, DAMAGE_OXY)
target.losebreath += 10
/singleton/surgery_step/generic/alter_face
name = "Alter Face"
allowed_tools = list(
TOOL_HEMOSTAT = 100, \
TOOL_CABLECOIL = 75, \
/obj/item/assembly/mousetrap = 10 //I don't know. Don't ask me. But I'm leaving it because hilarity.
)
base_surgery_time = 7 SECONDS
skill_requirements = alist(SURGERY_SKILL_COMPONENT = SKILL_LEVEL_TRAINED)
skill_diff_fail_modifier = SURGERY_DIFFICULTY_EXTREME
/singleton/surgery_step/generic/alter_face/can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
return ..() && target_zone == BP_MOUTH && target.op_stage.face == FACE_RETRACTED
/singleton/surgery_step/generic/alter_face/begin_step(mob/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
user.visible_message("<b>[user]</b> starts to adjust [target]'s face with \the [tool].", \
SPAN_NOTICE("You start to alter [target]'s face and neck with \the [tool]."))
..()
/singleton/surgery_step/generic/alter_face/end_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
var/obj/item/organ/external/head/head = target.get_organ(target_zone)
if(head.disfigured || (target.mutations & HUSK))
head.disfigured = FALSE
target.mutations &= ~HUSK
target.update_body()
user.visible_message("<b>[user]</b> finishes adjusting the skin [target]'s face.", SPAN_NOTICE("You successfully restore [target]'s appearance."))
var/getName = sanitize(input(user, "What is your patient's new identity?", "Name change") as null|text, MAX_NAME_LEN)
if(getName)
target.real_name = getName
target.name = getName
target.dna.real_name = getName
if(target.mind)
target.mind.name = target.name
target.change_appearance(APPEARANCE_PLASTICSURGERY &~ APPEARANCE_PROSTHETICS, user, TRUE, ui_state = GLOB.default_state, state_object = target)
target.op_stage.face = FACE_ALTERED
/singleton/surgery_step/generic/alter_face/fail_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
user.visible_message(SPAN_WARNING("[user]'s hand slips, slicing [target]'s throat wth \the [tool]!") , \
SPAN_WARNING("Your hand slips, slicing [target]'s throat wth \the [tool]!") )
target.apply_damage(40, DAMAGE_BRUTE, target_zone, 0, tool, damage_flags = tool.damage_flags())
target.apply_damage(20, DAMAGE_OXY)
target.losebreath += 10
/singleton/surgery_step/face/cauterize
name = "Cauterize Face"
allowed_tools = list(
TOOL_CAUTERY = 100, \
/obj/item/clothing/mask/smokable/cigarette = 75, \
/obj/item/flame/lighter = 50, \
/obj/item/weldingtool = 25
)
base_surgery_time = 8 SECONDS
skill_requirements = alist(SURGERY_SKILL_COMPONENT = SKILL_LEVEL_TRAINED)
skill_diff_fail_modifier = SURGERY_DIFFICULTY_MEDIUM
/singleton/surgery_step/face/cauterize/can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
return ..() && target.op_stage.face > FACE_NORMAL
/singleton/surgery_step/face/cauterize/begin_step(mob/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
user.visible_message("[user] is beginning to cauterize the incision on [target]'s face and neck with \the [tool]." , \
"You are beginning to cauterize the incision on [target]'s face and neck with \the [tool].")
..()
/singleton/surgery_step/face/cauterize/end_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
var/obj/item/organ/external/affected = target.get_organ(target_zone)
user.visible_message("<b>[user]</b> cauterizes the incision on [target]'s face and neck with \the [tool].", \
SPAN_NOTICE("You cauterize the incision on [target]'s face and neck with \the [tool]."))
affected.open = ORGAN_CLOSED
affected.status &= ~ORGAN_BLEEDING
if(target.op_stage.face == 3)
var/obj/item/organ/external/head/h = affected
h.disfigured = 0
target.op_stage.face = FACE_NORMAL
/singleton/surgery_step/face/cauterize/fail_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
var/obj/item/organ/external/affected = target.get_organ(target_zone)
user.visible_message(SPAN_WARNING("[user]'s hand slips, leaving a small burn on [target]'s face with \the [tool]!"), \
SPAN_WARNING("Your hand slips, leaving a small burn on [target]'s face with \the [tool]!"))
target.apply_damage(5, DAMAGE_BURN, affected)
/singleton/surgery_step/robotics/face
priority = 2
can_infect = FALSE
/singleton/surgery_step/robotics/face/can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
return ..() && target_zone == BP_MOUTH
/singleton/surgery_step/robotics/face/synthskinopen
name = "Retract facial incisions"
allowed_tools = list(
TOOL_SCALPEL = 100,
/obj/item/material/knife = 75,
/obj/item/material/shard = 50
)
base_surgery_time = 9 SECONDS
skill_requirements = alist(ROBOTICS_SKILL_COMPONENT = SKILL_LEVEL_TRAINED)
skill_diff_fail_modifier = SURGERY_DIFFICULTY_MEDIUM
/singleton/surgery_step/robotics/face/synthskinopen/can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
return ..() && target.op_stage.face == FACE_NORMAL && target.get_species() == SPECIES_IPC_SHELL
/singleton/surgery_step/robotics/face/synthskinopen/begin_step(mob/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
user.visible_message("[user] starts to cut open [target]'s synthskin face and neck with \the [tool].", \
"You start to cut open [target]'s synthskin face and neck with \the [tool].")
..()
/singleton/surgery_step/robotics/face/synthskinopen/end_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
user.visible_message("<b>[user]</b> has cut open [target]'s synthskin face and neck with \the [tool]." , \
SPAN_NOTICE("You have cut open [target]'s synthskin face and neck with \the [tool]."),)
target.op_stage.face = FACE_CUT_OPEN
/singleton/surgery_step/robotics/face/synthskinopen/fail_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
user.visible_message(SPAN_WARNING("[user]'s hand slips, slicing [target]'s throat wth \the [tool]!") , \
SPAN_WARNING("Your hand slips, slicing [target]'s throat wth \the [tool]!") )
target.apply_damage(40, DAMAGE_BRUTE, target_zone, 0, tool, damage_flags = tool.damage_flags())
/singleton/surgery_step/robotics/face/prepare_face
name = "Prepare Face"
allowed_tools = list(
TOOL_RETRACTOR = 100,
/obj/item/material/knife/tacknife = 75
)
base_surgery_time = 9 SECONDS
skill_requirements = alist(ROBOTICS_SKILL_COMPONENT = SKILL_LEVEL_TRAINED)
skill_diff_fail_modifier = SURGERY_DIFFICULTY_MEDIUM
/singleton/surgery_step/robotics/face/prepare_face/can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
return ..() && target_zone == BP_MOUTH && target.op_stage.face == FACE_CUT_OPEN
/singleton/surgery_step/robotics/face/prepare_face/begin_step(mob/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
user.visible_message("[user] starts to retract [target]'s synthskin face with \the [tool].", \
"You start to retract [target]'s face with \the [tool].")
..()
/singleton/surgery_step/robotics/face/prepare_face/end_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
user.visible_message("<b>[user]</b> has retracted [target]'s synthskin face with \the [tool] for thier facial alteration." , \
SPAN_NOTICE("You have retracted [target]'s synthskin face and neck with \the [tool] for plastic surgery."),)
target.op_stage.face = FACE_RETRACTED
/singleton/surgery_step/robotics/face/prepare_face/fail_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
user.visible_message(SPAN_WARNING("[user]'s hand slips, slicing [target]'s throat wth \the [tool]!") , \
SPAN_WARNING("Your hand slips, slicing [target]'s throat wth \the [tool]!") )
target.apply_damage(40, DAMAGE_BRUTE, target_zone, 0, tool, damage_flags = tool.damage_flags())
/singleton/surgery_step/robotics/face/alter_synthface
name = "Alter Face"
allowed_tools = list(
TOOL_MULTITOOL = 100, \
TOOL_CABLECOIL = 75, \
/obj/item/assembly/mousetrap = 10 //I don't know. Don't ask me. But I'm leaving it because hilarity.
)
base_surgery_time = 7 SECONDS
skill_requirements = alist(ROBOTICS_SKILL_COMPONENT = SKILL_LEVEL_TRAINED)
skill_diff_fail_modifier = SURGERY_DIFFICULTY_EXTREME
/singleton/surgery_step/robotics/face/alter_synthface/can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
return ..() && target_zone == BP_MOUTH && target.op_stage.face == FACE_RETRACTED
/singleton/surgery_step/robotics/face/alter_synthface/begin_step(mob/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
user.visible_message("<b>[user]</b> starts to alter [target]'s synthskin face with \the [tool].", \
SPAN_NOTICE("You start to alter [target]'s synthskin face and neck with \the [tool]."))
..()
/singleton/surgery_step/robotics/face/alter_synthface/end_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
var/obj/item/organ/external/head/head = target.get_organ(target_zone)
if(head.disfigured || (target.mutations & HUSK))
head.disfigured = FALSE
target.mutations &= ~HUSK
target.update_body()
user.visible_message("<b>[user]</b> finishes adjusting [target]'s synthetic face.", \
SPAN_NOTICE("You successfully adjust [target]'s appearance."))
var/getName = sanitize(input(user, "What is your patient's new identity?", "Name change") as null|text, MAX_NAME_LEN)
if(getName)
target.real_name = getName
target.name = getName
target.dna.real_name = getName
if(target.mind)
target.mind.name = target.name
target.change_appearance(APPEARANCE_PLASTICSURGERY &~ APPEARANCE_PROSTHETICS, user, TRUE, ui_state = GLOB.default_state, state_object = target)
target.op_stage.face = FACE_ALTERED
/singleton/surgery_step/robotics/face/alter_synthface/fail_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
user.visible_message(SPAN_WARNING("[user]'s hand slips, slicing [target]'s throat wth \the [tool]!") , \
SPAN_WARNING("Your hand slips, slicing [target]'s throat wth \the [tool]!") )
target.apply_damage(40, DAMAGE_BRUTE, target_zone, 0, tool, damage_flags = tool.damage_flags())
/singleton/surgery_step/robotics/face/seal_face
name = "Seal face"
allowed_tools = list(
TOOL_CAUTERY = 100, \
/obj/item/clothing/mask/smokable/cigarette = 75, \
/obj/item/flame/lighter = 50, \
/obj/item/weldingtool = 25
)
base_surgery_time = 8 SECONDS
skill_requirements = alist(ROBOTICS_SKILL_COMPONENT = SKILL_LEVEL_TRAINED)
skill_diff_fail_modifier = SURGERY_DIFFICULTY_MEDIUM
/singleton/surgery_step/robotics/face/seal_face/can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
return ..() && target.op_stage.face > FACE_NORMAL
/singleton/surgery_step/robotics/face/seal_face/begin_step(mob/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
user.visible_message("[user] is beginning to seal the incision on [target]'s synthskin face and neck with \the [tool]." , \
"You are beginning to seal the incision on [target]'s synthskin face and neck with \the [tool].")
..()
/singleton/surgery_step/robotics/face/seal_face/end_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
var/obj/item/organ/external/affected = target.get_organ(target_zone)
user.visible_message(SPAN_NOTICE("[user] seals the incision on [target]'s synthskin face and neck with \the [tool]."), \
SPAN_NOTICE("You seal the incision on [target]'s synthskin face and neck with \the [tool]."))
affected.open = ORGAN_CLOSED
if(target.op_stage.face == FACE_ALTERED)
var/obj/item/organ/external/head/h = affected
h.disfigured = FALSE
target.op_stage.face = FACE_NORMAL
/singleton/surgery_step/robotics/face/seal_face/fail_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
var/obj/item/organ/external/affected = target.get_organ(target_zone)
user.visible_message(SPAN_WARNING("[user]'s hand slips, leaving a small burn on [target]'s synthskin face with \the [tool]!"), \
SPAN_WARNING("Your hand slips, leaving a small burn on [target]'s synthskin face with \the [tool]!"))
target.apply_damage(5, DAMAGE_BURN, affected)