Files
Bubberstation/code/modules/surgery/organ_manipulation.dm
SkyratBot d84d670bde [MIRROR] Prosthesis organ manipulation no longer makes you harm target when you use incorrect tool [MDB IGNORE] (#20043)
* Prosthesis organ manipulation no longer makes you harm target when you use incorrect tool (#74184)

## About The Pull Request

currently if someone is in surgery you can only harm them with a
surgical tool if you are in combat mode
the way the check works is that it only applies to tools that have the
SURGICAL_TOOL item flag

prosthesis organ manipulation is the only surgery that uses normal
engineering tools, and because it involves steps with normal tools, it
means that if you forget or misclick you can easily hurt someone with
the wrong tool

this makes that not happen anymore

## Why It's Good For The Game

i feel like it makes sense for the surgery that uses engineering tools
as surgery tools to treat engineering tools as them, with the same
considerations with regards to only having you bludgeon the patient if
you wanted to

## Changelog

🆑
qol: Prosthesis organ manipulation now warns you if you are using the
incorrect engineering tool
/🆑

* Prosthesis organ manipulation no longer makes you harm target when you use incorrect tool

---------

Co-authored-by: Sol N <116288367+flowercuco@users.noreply.github.com>
2023-03-24 08:50:39 -07:00

283 lines
10 KiB
Plaintext

/datum/surgery/organ_manipulation
name = "Organ manipulation"
surgery_flags = SURGERY_REQUIRE_RESTING | SURGERY_REQUIRE_LIMB | SURGERY_REQUIRES_REAL_LIMB
possible_locs = list(BODY_ZONE_CHEST, BODY_ZONE_HEAD)
steps = list(
/datum/surgery_step/incise,
/datum/surgery_step/retract_skin,
/datum/surgery_step/saw,
/datum/surgery_step/clamp_bleeders,
/datum/surgery_step/incise,
/datum/surgery_step/manipulate_organs/internal,
/datum/surgery_step/close,
)
/datum/surgery/organ_manipulation/soft
possible_locs = list(BODY_ZONE_PRECISE_GROIN, BODY_ZONE_PRECISE_EYES, BODY_ZONE_PRECISE_MOUTH, BODY_ZONE_L_ARM, BODY_ZONE_R_ARM)
steps = list(
/datum/surgery_step/incise,
/datum/surgery_step/retract_skin,
/datum/surgery_step/clamp_bleeders,
/datum/surgery_step/incise,
/datum/surgery_step/manipulate_organs/internal,
/datum/surgery_step/close,
)
/datum/surgery/organ_manipulation/alien
name = "Alien organ manipulation"
possible_locs = list(BODY_ZONE_CHEST, BODY_ZONE_HEAD, BODY_ZONE_PRECISE_GROIN, BODY_ZONE_PRECISE_EYES, BODY_ZONE_PRECISE_MOUTH, BODY_ZONE_L_ARM, BODY_ZONE_R_ARM)
target_mobtypes = list(/mob/living/carbon/alien/adult)
steps = list(
/datum/surgery_step/saw,
/datum/surgery_step/incise,
/datum/surgery_step/retract_skin,
/datum/surgery_step/saw,
/datum/surgery_step/manipulate_organs/internal,
/datum/surgery_step/close,
)
/datum/surgery/organ_manipulation/mechanic
name = "Prosthesis organ manipulation"
requires_bodypart_type = BODYTYPE_ROBOTIC
surgery_flags = SURGERY_SELF_OPERABLE | SURGERY_REQUIRE_LIMB
possible_locs = list(BODY_ZONE_CHEST, BODY_ZONE_HEAD)
steps = list(
/datum/surgery_step/mechanic_open,
/datum/surgery_step/open_hatch,
/datum/surgery_step/mechanic_unwrench,
/datum/surgery_step/prepare_electronics,
/datum/surgery_step/manipulate_organs/internal,
/datum/surgery_step/mechanic_wrench,
/datum/surgery_step/mechanic_close,
)
/datum/surgery/organ_manipulation/mechanic/next_step(mob/living/user, modifiers)
if(location != user.zone_selected)
return FALSE
if(user.combat_mode)
return FALSE
if(step_in_progress)
return TRUE
var/try_to_fail = FALSE
if(LAZYACCESS(modifiers, RIGHT_CLICK))
try_to_fail = TRUE
var/datum/surgery_step/step = get_surgery_step()
if(isnull(step))
return FALSE
var/obj/item/tool = user.get_active_held_item()
if(step.try_op(user, target, user.zone_selected, tool, src, try_to_fail))
return TRUE
if(tool && tool.item_flags) //Mechanic organ manipulation isn't done with just surgery tools
to_chat(user, span_warning("This step requires a different tool!"))
return TRUE
return FALSE
/datum/surgery/organ_manipulation/mechanic/soft
possible_locs = list(
BODY_ZONE_PRECISE_GROIN,
BODY_ZONE_PRECISE_EYES,
BODY_ZONE_PRECISE_MOUTH,
BODY_ZONE_L_ARM,
BODY_ZONE_R_ARM,
)
steps = list(
/datum/surgery_step/mechanic_open,
/datum/surgery_step/open_hatch,
/datum/surgery_step/prepare_electronics,
/datum/surgery_step/manipulate_organs/internal,
/datum/surgery_step/mechanic_close,
)
/datum/surgery/organ_manipulation/external
name = "Feature manipulation"
possible_locs = list(
BODY_ZONE_CHEST,
BODY_ZONE_HEAD,
BODY_ZONE_PRECISE_GROIN,
BODY_ZONE_L_ARM,
BODY_ZONE_R_ARM,
BODY_ZONE_L_LEG,
BODY_ZONE_R_LEG,
)
steps = list(
/datum/surgery_step/incise,
/datum/surgery_step/retract_skin,
/datum/surgery_step/manipulate_organs/external,
/datum/surgery_step/close,
)
///Organ manipulation base class. Do not use, it wont work. Use it's subtypes
/datum/surgery_step/manipulate_organs
name = "manipulate organs"
repeatable = TRUE
implements = list(
/obj/item/organ = 100,
/obj/item/borg/apparatus/organ_storage = 100)
preop_sound = 'sound/surgery/organ2.ogg'
success_sound = 'sound/surgery/organ1.ogg'
var/implements_extract = list(TOOL_HEMOSTAT = 100, TOOL_CROWBAR = 55, /obj/item/kitchen/fork = 35)
var/current_type
var/obj/item/organ/target_organ
/datum/surgery_step/manipulate_organs/New()
..()
implements = implements + implements_extract
/datum/surgery_step/manipulate_organs/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery)
target_organ = null
if(istype(tool, /obj/item/borg/apparatus/organ_storage))
preop_sound = initial(preop_sound)
success_sound = initial(success_sound)
if(!length(tool.contents))
to_chat(user, span_warning("There is nothing inside [tool]!"))
return SURGERY_STEP_FAIL
target_organ = tool.contents[1]
if(!isorgan(target_organ))
if (target_zone == BODY_ZONE_PRECISE_EYES)
target_zone = check_zone(target_zone)
to_chat(user, span_warning("You cannot put [target_organ] into [target]'s [parse_zone(target_zone)]!"))
return SURGERY_STEP_FAIL
tool = target_organ
if(isorgan(tool))
current_type = "insert"
preop_sound = 'sound/surgery/hemostat1.ogg'
success_sound = 'sound/surgery/organ2.ogg'
target_organ = tool
if(target_zone != target_organ.zone || target.getorganslot(target_organ.slot))
to_chat(user, span_warning("There is no room for [target_organ] in [target]'s [parse_zone(target_zone)]!"))
return SURGERY_STEP_FAIL
var/obj/item/organ/meatslab = tool
if(!meatslab.useable)
to_chat(user, span_warning("[target_organ] seems to have been chewed on, you can't use this!"))
return SURGERY_STEP_FAIL
if(!can_use_organ(user, meatslab))
return SURGERY_STEP_FAIL
if (target_zone == BODY_ZONE_PRECISE_EYES)
target_zone = check_zone(target_zone)
display_results(
user,
target,
span_notice("You begin to insert [tool] into [target]'s [parse_zone(target_zone)]..."),
span_notice("[user] begins to insert [tool] into [target]'s [parse_zone(target_zone)]."),
span_notice("[user] begins to insert something into [target]'s [parse_zone(target_zone)]."),
)
display_pain(target, "You can feel something being placed in your [parse_zone(target_zone)]!")
else if(implement_type in implements_extract)
current_type = "extract"
var/list/unfiltered_organs = target.getorganszone(target_zone)
var/list/organs = list()
for(var/organ in unfiltered_organs)
if(can_use_organ(user, organ))
organs.Add(organ)
if (target_zone == BODY_ZONE_PRECISE_EYES)
target_zone = check_zone(target_zone)
if(!length(organs))
to_chat(user, span_warning("There are no removable organs in [target]'s [parse_zone(target_zone)]!"))
return SURGERY_STEP_FAIL
else
for(var/obj/item/organ/organ in organs)
organ.on_find(user)
organs -= organ
organs[organ.name] = organ
var/chosen_organ = tgui_input_list(user, "Remove which organ?", "Surgery", sort_list(organs))
if(isnull(chosen_organ))
return SURGERY_STEP_FAIL
target_organ = chosen_organ
if(user && target && user.Adjacent(target) && user.get_active_held_item() == tool)
target_organ = organs[target_organ]
if(!target_organ)
return SURGERY_STEP_FAIL
if(target_organ.organ_flags & ORGAN_UNREMOVABLE)
to_chat(user, span_warning("[target_organ] is too well connected to take out!"))
return SURGERY_STEP_FAIL
display_results(
user,
target,
span_notice("You begin to extract [target_organ] from [target]'s [parse_zone(target_zone)]..."),
span_notice("[user] begins to extract [target_organ] from [target]'s [parse_zone(target_zone)]."),
span_notice("[user] begins to extract something from [target]'s [parse_zone(target_zone)]."),
)
display_pain(target, "You can feel your [target_organ] being removed from your [parse_zone(target_zone)]!")
else
return SURGERY_STEP_FAIL
/datum/surgery_step/manipulate_organs/success(mob/living/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery, default_display_results = FALSE)
if (target_zone == BODY_ZONE_PRECISE_EYES)
target_zone = check_zone(target_zone)
if(current_type == "insert")
var/obj/item/apparatus
if(istype(tool, /obj/item/borg/apparatus/organ_storage))
apparatus = tool
tool = tool.contents[1]
target_organ = tool
user.temporarilyRemoveItemFromInventory(target_organ, TRUE)
if(target_organ.Insert(target))
if(apparatus)
apparatus.icon_state = initial(apparatus.icon_state)
apparatus.desc = initial(apparatus.desc)
apparatus.cut_overlays()
display_results(
user,
target,
span_notice("You insert [tool] into [target]'s [parse_zone(target_zone)]."),
span_notice("[user] inserts [tool] into [target]'s [parse_zone(target_zone)]!"),
span_notice("[user] inserts something into [target]'s [parse_zone(target_zone)]!"),
)
display_pain(target, "Your [parse_zone(target_zone)] throbs with pain as your new [tool] comes to life!")
else
target_organ.forceMove(target.loc)
else if(current_type == "extract")
if(target_organ && target_organ.owner == target)
display_results(
user,
target,
span_notice("You successfully extract [target_organ] from [target]'s [parse_zone(target_zone)]."),
span_notice("[user] successfully extracts [target_organ] from [target]'s [parse_zone(target_zone)]!"),
span_notice("[user] successfully extracts something from [target]'s [parse_zone(target_zone)]!"),
)
display_pain(target, "Your [parse_zone(target_zone)] throbs with pain, you can't feel your [target_organ] anymore!")
log_combat(user, target, "surgically removed [target_organ.name] from", addition="COMBAT MODE: [uppertext(user.combat_mode)]")
target_organ.Remove(target)
target_organ.forceMove(get_turf(target))
else
display_results(
user,
target,
span_warning("You can't extract anything from [target]'s [parse_zone(target_zone)]!"),
span_notice("[user] can't seem to extract anything from [target]'s [parse_zone(target_zone)]!"),
span_notice("[user] can't seem to extract anything from [target]'s [parse_zone(target_zone)]!"),
)
return ..()
///You can never use this MUHAHAHAHAHAHAH (because its the byond version of abstract)
/datum/surgery_step/manipulate_organs/proc/can_use_organ(mob/user, obj/item/organ/organ)
return FALSE
///Surgery step for internal organs, like hearts and brains
/datum/surgery_step/manipulate_organs/internal
time = 6.4 SECONDS
name = "manipulate organs (hemostat/organ)"
///only operate on internal organs
/datum/surgery_step/manipulate_organs/internal/can_use_organ(mob/user, obj/item/organ/organ)
return isinternalorgan(organ)
///Surgery step for external organs/features, like tails, frills, wings etc
/datum/surgery_step/manipulate_organs/external
time = 3.2 SECONDS
name = "manipulate features (hemostat/feature)"
///Only operate on external organs
/datum/surgery_step/manipulate_organs/external/can_use_organ(mob/user, obj/item/organ/organ)
return isexternalorgan(organ)