mirror of
https://github.com/ParadiseSS13/Paradise.git
synced 2026-08-29 15:08:02 +01:00
Surgery Hotfixes: Part 1 (#19108)
* Fixes up a few notable bugs with surgery - Synthetic cavity implants now have a close step (oops!) - Fixes up logic for intermediate surgery steps * nah I'll deal with this later * oops this was unused
This commit is contained in:
@@ -45,7 +45,7 @@
|
||||
/obj/item/scalpel/laser/manager // IMS
|
||||
)
|
||||
|
||||
/// Whether or not we should add ourselves as a step after we run a branch
|
||||
/// Whether or not we should add ourselves as a step after we run a branch. This doesn't apply to failures, those will always add ourselves after.
|
||||
var/insert_self_after = TRUE
|
||||
|
||||
/datum/surgery_step/proxy/New()
|
||||
@@ -133,7 +133,7 @@
|
||||
if(istype(next_surgery_step, /datum/surgery_step/proxy))
|
||||
// It might make sense to support this, and I think the flow could work (just treating them like a single step, sorta)
|
||||
// but I think for simplicity's sake it's better to just say no
|
||||
CRASH("[src] was followed by another proxy surgery step in [surgery].")
|
||||
CRASH("[src] was followed by another proxy surgery step [next_surgery_step] in [surgery].")
|
||||
|
||||
if((SURGERY_TOOL_HAND in starting_tools) && next_surgery_step.accept_hand)
|
||||
CRASH("[src] has a conflict with the next main step [next_surgery_step] in surgery [surgery]: both require an open hand.")
|
||||
@@ -173,10 +173,8 @@
|
||||
return FALSE
|
||||
|
||||
if(overridden_tool || next_surgery == surgery || !next_surgery)
|
||||
// Continue along with the original surgery
|
||||
surgery.step_number++
|
||||
var/datum/surgery_step/next_step = surgery.get_surgery_step()
|
||||
return next_step.try_op(user, target, target_zone, tool, surgery)
|
||||
// Continue along with the original surgery.
|
||||
return try_next_step(user, target, target_zone, tool, surgery, null, TRUE)
|
||||
|
||||
if(!target.can_run_surgery(next_surgery, user))
|
||||
// Make sure the target can support the surgery.
|
||||
@@ -188,20 +186,59 @@
|
||||
// Let them try other tools if necessary.
|
||||
return TRUE
|
||||
|
||||
// Insert the steps in our intermediate surgery into the current surgery.
|
||||
// This is how we keep our surgeries still technically linear.
|
||||
var/list/steps_to_insert = next_surgery.steps
|
||||
if(insert_self_after)
|
||||
// add ourselves afterwards as well so we can repeat this step
|
||||
steps_to_insert.Add(type)
|
||||
return try_next_step(user, target, target_zone, tool, surgery, next_surgery.steps)
|
||||
|
||||
// Also, bump the status so we skip past this abstract step.
|
||||
surgery.steps.Insert(surgery.step_number + 1, next_surgery.steps)
|
||||
surgery.step_number++
|
||||
/**
|
||||
* Test the next step, but don't fully commit to it unless it completes successfully.
|
||||
* If the next step doesn't fully complete (such as being interrupted or failing), we'll insert ourselves again to bring us back
|
||||
* to the "base" state.
|
||||
* If it does, we'll add the subsequent steps to the surgery and continue down the expected branch. If you complete the surgery step, it
|
||||
* means you've committed to what comes next.
|
||||
* Part of the motivation behind this is that I don't want to mutate a surgery retroactively. We can insert, but we shouldn't be changing anything
|
||||
* behind us.
|
||||
*
|
||||
* Arguments:
|
||||
* * next_surgery_steps - the steps for the branching surgery to add to the current surgery. If there's no branching surgery (or this would continue the main surgery) ignore this.
|
||||
* * override_adding_self - If true, then regardless of the value of insert_self_after, we won't add ourselves in as another step.
|
||||
* (for other arguments, see try_op())
|
||||
*/
|
||||
/datum/surgery_step/proxy/proc/try_next_step(mob/living/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/running_surgery, list/next_surgery_steps, override_adding_self)
|
||||
|
||||
var/list/following_steps = list()
|
||||
|
||||
if(length(next_surgery_steps))
|
||||
|
||||
// add the first step from the following surgery into the surgery list, to make it the next step.
|
||||
running_surgery.steps.Insert(running_surgery.step_number + 1, next_surgery_steps[1])
|
||||
|
||||
// grab the remaining steps to possibly insert after this surgery, depending on what we're doing
|
||||
// skip the current step though, since if our try_op works, we've completed it.
|
||||
following_steps = next_surgery_steps.Copy()
|
||||
following_steps.Cut(1, 2)
|
||||
|
||||
running_surgery.step_number++
|
||||
|
||||
var/datum/surgery_step/next_step = running_surgery.get_surgery_step()
|
||||
var/step_status = next_step.try_op(user, target, target_zone, tool, running_surgery)
|
||||
|
||||
if(step_status != SURGERY_INITIATE_SUCCESS)
|
||||
// always add ourselves after a failure so someone can make a different choice.
|
||||
running_surgery.steps.Insert(running_surgery.step_number + 1, type)
|
||||
running_surgery.step_number++
|
||||
|
||||
else
|
||||
// Insert the steps in our intermediate surgery into the current surgery.
|
||||
// This is how we keep our surgeries still technically linear.
|
||||
if(insert_self_after && !override_adding_self)
|
||||
// add ourselves afterwards as well so we can repeat this step
|
||||
following_steps.Add(type)
|
||||
|
||||
// insert at the current step number since we're not trying to bump it up
|
||||
running_surgery.steps.Insert(running_surgery.step_number, following_steps)
|
||||
|
||||
|
||||
return step_status
|
||||
|
||||
// force the next surgery step so we don't have to click again.
|
||||
var/datum/surgery_step/next_step = surgery.get_surgery_step()
|
||||
return next_step.try_op(user, target, target_zone, tool, surgery)
|
||||
|
||||
// Some intermediate surgeries
|
||||
/datum/surgery/intermediate/bleeding
|
||||
|
||||
@@ -52,11 +52,52 @@
|
||||
/datum/surgery_step/robotics/external/unscrew_hatch,
|
||||
/datum/surgery_step/robotics/external/open_hatch,
|
||||
/datum/surgery_step/proxy/cavity_manipulation/robotic,
|
||||
/datum/surgery_step/cavity/close_space,
|
||||
/datum/surgery_step/robotics/external/close_hatch
|
||||
)
|
||||
possible_locs = list(BODY_ZONE_CHEST, BODY_ZONE_HEAD, BODY_ZONE_PRECISE_GROIN)
|
||||
requires_organic_bodypart = FALSE
|
||||
|
||||
|
||||
/datum/surgery_step/proxy/cavity_manipulation
|
||||
name = "Cavity Manipulation (proxy)"
|
||||
branches = list(
|
||||
/datum/surgery/intermediate/open_cavity/implant,
|
||||
/datum/surgery/intermediate/open_cavity/extract,
|
||||
/datum/surgery/intermediate/bleeding
|
||||
)
|
||||
|
||||
insert_self_after = TRUE
|
||||
|
||||
/datum/surgery_step/proxy/cavity_manipulation/robotic
|
||||
name = "Robotic Cavity Manipulation (proxy)"
|
||||
branches = list(
|
||||
/datum/surgery/intermediate/open_cavity/implant/robotic,
|
||||
/datum/surgery/intermediate/open_cavity/extract/robotic
|
||||
)
|
||||
|
||||
/datum/surgery/intermediate/open_cavity
|
||||
possible_locs = list(BODY_ZONE_CHEST, BODY_ZONE_HEAD)
|
||||
|
||||
/datum/surgery/intermediate/open_cavity/implant
|
||||
name = "implant object"
|
||||
steps = list(
|
||||
/datum/surgery_step/cavity/place_item
|
||||
)
|
||||
|
||||
/datum/surgery/intermediate/open_cavity/extract
|
||||
name = "extract object"
|
||||
steps = list(
|
||||
/datum/surgery_step/cavity/remove_item
|
||||
)
|
||||
|
||||
/datum/surgery/intermediate/open_cavity/implant/robotic
|
||||
requires_organic_bodypart = FALSE
|
||||
|
||||
/datum/surgery/intermediate/open_cavity/extract/robotic
|
||||
requires_organic_bodypart = FALSE
|
||||
|
||||
|
||||
/datum/surgery_step/cavity
|
||||
|
||||
/datum/surgery_step/cavity/proc/get_max_wclass(obj/item/organ/external/affected)
|
||||
@@ -206,43 +247,6 @@
|
||||
|
||||
return SURGERY_STEP_INCOMPLETE
|
||||
|
||||
/datum/surgery_step/proxy/cavity_manipulation
|
||||
name = "Cavity Manipulation (proxy)"
|
||||
branches = list(
|
||||
/datum/surgery/intermediate/open_cavity/implant,
|
||||
/datum/surgery/intermediate/open_cavity/extract
|
||||
)
|
||||
|
||||
insert_self_after = TRUE
|
||||
|
||||
/datum/surgery_step/proxy/cavity_manipulation/robotic
|
||||
name = "Robotic Cavity Manipulation (proxy)"
|
||||
branches = list(
|
||||
/datum/surgery/intermediate/open_cavity/implant/robotic,
|
||||
/datum/surgery/intermediate/open_cavity/extract/robotic
|
||||
)
|
||||
|
||||
/datum/surgery/intermediate/open_cavity
|
||||
possible_locs = list(BODY_ZONE_CHEST, BODY_ZONE_HEAD)
|
||||
|
||||
/datum/surgery/intermediate/open_cavity/implant
|
||||
name = "implant object"
|
||||
steps = list(
|
||||
/datum/surgery_step/cavity/place_item
|
||||
)
|
||||
|
||||
/datum/surgery/intermediate/open_cavity/extract
|
||||
name = "extract object"
|
||||
steps = list(
|
||||
/datum/surgery_step/cavity/remove_item
|
||||
)
|
||||
|
||||
/datum/surgery/intermediate/open_cavity/implant/robotic
|
||||
requires_organic_bodypart = FALSE
|
||||
|
||||
/datum/surgery/intermediate/open_cavity/extract/robotic
|
||||
requires_organic_bodypart = FALSE
|
||||
|
||||
/datum/surgery_step/cavity/place_item
|
||||
name = "implant object"
|
||||
accept_any_item = TRUE
|
||||
@@ -281,7 +285,7 @@
|
||||
var/can_fit = !affected.hidden && tool.w_class <= get_max_wclass(affected)
|
||||
if(!can_fit)
|
||||
to_chat(user, "<span class='warning'>\The [tool] won't fit in \the [affected]!</span>")
|
||||
return SURGERY_BEGINSTEP_ABORT
|
||||
return SURGERY_BEGINSTEP_SKIP
|
||||
|
||||
user.visible_message(
|
||||
"[user] starts putting \the [tool] inside [target]'s [get_cavity(affected)] cavity.",
|
||||
|
||||
@@ -227,10 +227,9 @@
|
||||
if(is_valid_tool(user, tool))
|
||||
if(target_zone == surgery.location)
|
||||
if(get_location_accessible(target, target_zone) || surgery.ignore_clothes)
|
||||
initiate(user, target, target_zone, tool, surgery)
|
||||
else
|
||||
to_chat(user, "<span class='warning'>You need to expose [target]'s [parse_zone(target_zone)] before you can perform surgery on it!")
|
||||
return TRUE //returns TRUE so we don't stab the guy in the dick or wherever.
|
||||
return initiate(user, target, target_zone, tool, surgery)
|
||||
to_chat(user, "<span class='warning'>You need to expose [target]'s [parse_zone(target_zone)] before you can perform surgery on it!")
|
||||
return SURGERY_INITIATE_FAILURE //returns TRUE so we don't stab the guy in the dick or wherever.
|
||||
|
||||
if(repeatable)
|
||||
// you can continuously, manually, perform a step, so long as you continue to use the correct tool.
|
||||
@@ -241,11 +240,11 @@
|
||||
if(next_step)
|
||||
surgery.step_number++
|
||||
if(next_step.try_op(user, target, user.zone_selected, user.get_active_hand(), surgery))
|
||||
return TRUE
|
||||
return SURGERY_INITIATE_SUCCESS
|
||||
else
|
||||
surgery.step_number--
|
||||
|
||||
return FALSE
|
||||
return SURGERY_INITIATE_CONTINUE_CHAIN
|
||||
|
||||
/**
|
||||
* Determines whether or not this surgery step can repeat if its end/fail steps returned SURGERY_STEP_RETRY.
|
||||
@@ -286,14 +285,15 @@
|
||||
var/begin_step_result = begin_step(user, target, target_zone, tool, surgery)
|
||||
if(begin_step_result == SURGERY_BEGINSTEP_ABORT)
|
||||
surgery.step_in_progress = FALSE
|
||||
return
|
||||
return SURGERY_INITIATE_FAILURE
|
||||
|
||||
if(begin_step_result == SURGERY_BEGINSTEP_SKIP)
|
||||
surgery.step_number++
|
||||
if(surgery.step_number > length(surgery.steps))
|
||||
surgery.complete(target)
|
||||
|
||||
surgery.step_in_progress = FALSE
|
||||
return TRUE
|
||||
return SURGERY_INITIATE_SUCCESS
|
||||
|
||||
if(tool)
|
||||
speed_mod = tool.toolspeed
|
||||
@@ -314,40 +314,45 @@
|
||||
prob_success = allowed_tools[implement_type]
|
||||
prob_success *= get_location_modifier(target)
|
||||
|
||||
if(do_after(user, modded_time, target = target))
|
||||
if(!do_after(user, modded_time, target = target))
|
||||
surgery.step_in_progress = FALSE
|
||||
return SURGERY_INITIATE_INTERRUPTED
|
||||
|
||||
var/chem_check_result = chem_check(target)
|
||||
var/pain_mod = deal_pain(user, target, target_zone, tool, surgery)
|
||||
prob_success *= pain_mod
|
||||
var/chem_check_result = chem_check(target)
|
||||
var/pain_mod = deal_pain(user, target, target_zone, tool, surgery)
|
||||
prob_success *= pain_mod
|
||||
|
||||
var/step_result
|
||||
var/step_result
|
||||
|
||||
if((prob(prob_success) || isrobot(user) && !silicons_obey_prob) && chem_check_result && !try_to_fail)
|
||||
step_result = end_step(user, target, target_zone, tool, surgery)
|
||||
else
|
||||
step_result = fail_step(user, target, target_zone, tool, surgery)
|
||||
switch(step_result)
|
||||
if(SURGERY_STEP_CONTINUE)
|
||||
advance = TRUE
|
||||
if(SURGERY_STEP_RETRY_ALWAYS)
|
||||
if((prob(prob_success) || isrobot(user) && !silicons_obey_prob) && chem_check_result && !try_to_fail)
|
||||
step_result = end_step(user, target, target_zone, tool, surgery)
|
||||
else
|
||||
step_result = fail_step(user, target, target_zone, tool, surgery)
|
||||
switch(step_result)
|
||||
if(SURGERY_STEP_CONTINUE)
|
||||
advance = TRUE
|
||||
if(SURGERY_STEP_RETRY_ALWAYS)
|
||||
retry = TRUE
|
||||
if(SURGERY_STEP_RETRY)
|
||||
if(can_repeat(user, target, target_zone, tool, surgery))
|
||||
retry = TRUE
|
||||
if(SURGERY_STEP_RETRY)
|
||||
if(can_repeat(user, target, target_zone, tool, surgery))
|
||||
retry = TRUE
|
||||
|
||||
if(retry)
|
||||
// if at first you don't succeed...
|
||||
return .(user, target, target_zone, tool, surgery, try_to_fail)
|
||||
if(retry)
|
||||
// if at first you don't succeed...
|
||||
return .(user, target, target_zone, tool, surgery, try_to_fail)
|
||||
|
||||
// Bump the surgery status
|
||||
// if it's repeatable, don't let it truly "complete" though
|
||||
if(advance && !repeatable)
|
||||
surgery.step_number++
|
||||
if(surgery.step_number > length(surgery.steps))
|
||||
surgery.complete(target)
|
||||
// Bump the surgery status
|
||||
// if it's repeatable, don't let it truly "complete" though
|
||||
if(advance && !repeatable)
|
||||
surgery.step_number++
|
||||
if(surgery.step_number > length(surgery.steps))
|
||||
surgery.complete(target)
|
||||
|
||||
surgery.step_in_progress = FALSE
|
||||
return advance
|
||||
if(advance)
|
||||
return SURGERY_INITIATE_SUCCESS
|
||||
else
|
||||
return SURGERY_INITIATE_FAILURE
|
||||
|
||||
/**
|
||||
* Try to inflict pain during a surgery, a surgeon's dream come true.
|
||||
|
||||
Reference in New Issue
Block a user