From 35183418d4ce91e824e54b16810b982f42122230 Mon Sep 17 00:00:00 2001 From: PowerfulBacon <26465327+PowerfulBacon@users.noreply.github.com> Date: Tue, 19 Dec 2023 04:53:35 +0000 Subject: [PATCH] Simplified bodyzone targeting preference (#9845) * Zone selector for patches * Preference * Adds in a generic bodyzone part getter * Combat zone targetting * Update mob_helpers.dm * Fixes some mistakes * Bug fixes, makes the task not have a delay * Makes the bodyzone wheel represent the positions of the limb * Mechanical repair interaction * Adds in the flashlight interaction * Hotkeys can now be hidden based on the values of preferences * Scroll hotkey for cycling the selected area * Surgery, cleans up the priority code and spelling mistake correction * Update mob_helpers.dm * Fixes the logic in the technophile cult * Voodoo Doll * Update code/__DEFINES/preferences.dm Co-authored-by: itsmeow * Review addresses * Adjacency checks * Changes the dropdown to buttons * Fix * Named parameter arguments * Changes the required preference to a typepath * Update _basemap.dm * Fixes wrong variable name * You now have to be adjacent to medical items to use them as well as the target * You can't select a bodyzone to heal while healing * Removes the ERP message when using simplified zone targeting since it makes less sense on the legs * Fixes holoparasite missing parameters * Makes it so that mechanical repairs repeat * Fixes some linter catches * Fixes surgery on groin being impossible --------- Co-authored-by: itsmeow --- beestation.dme | 2 + code/__DEFINES/async.dm | 4 + code/__DEFINES/bodyparts.dm | 7 + code/__DEFINES/combat.dm | 4 + code/__DEFINES/keybinding.dm | 2 + code/__DEFINES/preferences.dm | 4 + code/__HELPERS/mob_bodyzone.dm | 142 ++++++++++++ code/_onclick/click.dm | 11 +- code/_onclick/hud/screen_objects.dm | 35 +-- code/datums/components/butchering.dm | 2 +- code/datums/components/embedded.dm | 2 +- code/datums/components/jousting.dm | 2 +- code/datums/components/pellet_cloud.dm | 2 +- code/datums/elements/mechanical_repair.dm | 50 +++-- code/datums/keybinding/keybinding.dm | 8 +- code/datums/keybinding/mob.dm | 91 +++++++- code/datums/martial/_martial.dm | 2 +- code/datums/martial/boxing.dm | 2 +- code/datums/martial/krav_maga.dm | 4 +- code/datums/task.dm | 23 +- code/game/atoms_movable.dm | 2 +- code/game/objects/items/bedsheets.dm | 3 +- code/game/objects/items/clown_items.dm | 2 +- code/game/objects/items/cosmetics.dm | 159 +++++++------- code/game/objects/items/defib.dm | 2 +- code/game/objects/items/devices/flashlight.dm | 206 +++++++++--------- .../objects/items/devices/laserpointer.dm | 2 +- code/game/objects/items/kitchen.dm | 2 +- code/game/objects/items/knives.dm | 2 +- code/game/objects/items/melee/misc.dm | 11 +- code/game/objects/items/robot/robot_items.dm | 4 +- code/game/objects/items/stacks/medical.dm | 27 ++- code/game/objects/items/stunbaton.dm | 2 +- code/game/objects/items/tools/powertools.dm | 2 +- code/game/objects/items/tools/screwdriver.dm | 2 +- code/game/objects/items/weaponry.dm | 4 +- code/game/objects/structures/watercloset.dm | 5 +- .../abductor/equipment/abduction_surgery.dm | 14 +- .../antagonists/wizard/equipment/artefact.dm | 14 +- .../entries/player/zone_selection.dm | 28 +++ .../preferences/middleware/keybindings.dm | 3 + code/modules/clothing/neck/_neck.dm | 7 +- code/modules/food_and_drinks/drinks/drinks.dm | 4 +- .../food_and_drinks/drinks/drinks/bottle.dm | 17 +- .../holoparasite/holoparasite_damage.dm | 2 +- code/modules/keybindings/bindings_client.dm | 2 + .../mob/living/carbon/alien/alien_defense.dm | 4 +- .../mob/living/carbon/alien/humanoid/queen.dm | 2 +- .../carbon/alien/larva/larva_defense.dm | 2 +- .../mob/living/carbon/carbon_defense.dm | 14 +- code/modules/mob/living/carbon/human/human.dm | 9 +- .../mob/living/carbon/human/human_defense.dm | 16 +- .../mob/living/carbon/human/species.dm | 6 +- .../carbon/human/species_types/pumpkin_man.dm | 2 +- .../living/carbon/monkey/monkey_defense.dm | 6 +- code/modules/mob/living/living.dm | 10 +- code/modules/mob/living/silicon/silicon.dm | 2 +- code/modules/mob/mob_defines.dm | 3 +- code/modules/mob/mob_helpers.dm | 113 ++++++++++ code/modules/mob/mob_movement.dm | 33 ++- code/modules/paperwork/pen.dm | 2 +- .../modules/projectiles/ammunition/_firing.dm | 2 +- code/modules/projectiles/gun.dm | 14 +- .../projectiles/guns/ballistic/revolver.dm | 2 +- .../projectiles/guns/misc/beam_rifle.dm | 2 +- .../reagents/reagent_containers/borghydro.dm | 2 +- .../reagents/reagent_containers/medspray.dm | 16 +- .../reagents/reagent_containers/patch.dm | 19 +- .../reagents/reagent_containers/pill.dm | 6 +- code/modules/religion/religion_sects.dm | 6 +- .../advanced/bioware/cortex_folding.dm | 8 +- .../advanced/bioware/cortex_imprint.dm | 8 +- .../bioware/experimental_dissection.dm | 8 +- .../surgery/advanced/bioware/ligament_hook.dm | 4 +- .../bioware/ligament_reinforcement.dm | 4 +- .../surgery/advanced/bioware/muscled_veins.dm | 4 +- .../advanced/bioware/nerve_grounding.dm | 4 +- .../advanced/bioware/nerve_splicing.dm | 4 +- .../advanced/bioware/vein_threading.dm | 4 +- code/modules/surgery/advanced/brainwashing.dm | 8 +- code/modules/surgery/advanced/lobotomy.dm | 8 +- .../surgery/advanced/necrotic_revival.dm | 6 +- code/modules/surgery/advanced/pacification.dm | 8 +- code/modules/surgery/advanced/revival.dm | 8 +- .../modules/surgery/advanced/viral_bonding.dm | 6 +- code/modules/surgery/amputation.dm | 16 +- code/modules/surgery/blood_filter.dm | 10 +- code/modules/surgery/brain_recalibration.dm | 8 +- code/modules/surgery/cavity_implant.dm | 32 +-- code/modules/surgery/core_removal.dm | 4 +- code/modules/surgery/coronary_bypass.dm | 14 +- code/modules/surgery/dental_implant.dm | 16 +- code/modules/surgery/eye_surgery.dm | 8 +- code/modules/surgery/gastrectomy.dm | 8 +- code/modules/surgery/healing.dm | 12 +- code/modules/surgery/helpers.dm | 142 ++++++------ code/modules/surgery/hepatectomy.dm | 8 +- code/modules/surgery/implant_removal.dm | 24 +- code/modules/surgery/limb_augmentation.dm | 28 +-- code/modules/surgery/lipoplasty.dm | 16 +- code/modules/surgery/lobectomy.dm | 8 +- code/modules/surgery/mechanic_steps.dm | 48 ++-- code/modules/surgery/organ_manipulation.dm | 44 ++-- code/modules/surgery/organic_steps.dm | 86 ++++---- code/modules/surgery/organs/organ_internal.dm | 3 +- code/modules/surgery/plastic_surgery.dm | 6 +- .../modules/surgery/prosthetic_replacement.dm | 40 ++-- .../modules/surgery/remove_embedded_object.dm | 16 +- code/modules/surgery/surgery.dm | 6 +- code/modules/surgery/surgery_step.dm | 40 ++-- code/modules/surgery/tools.dm | 3 +- code/modules/zombie/items.dm | 2 +- icons/mob/screen_gen.dmi | Bin 115675 -> 88715 bytes icons/mob/zone_dam.dmi | Bin 0 -> 558 bytes .../PreferencesMenu/KeybindingsPage.tsx | 70 +++--- .../features/game_preferences/hotkeys.tsx | 10 +- 116 files changed, 1293 insertions(+), 747 deletions(-) create mode 100644 code/__HELPERS/mob_bodyzone.dm create mode 100644 code/modules/client/preferences/entries/player/zone_selection.dm create mode 100644 icons/mob/zone_dam.dmi diff --git a/beestation.dme b/beestation.dme index a58e4eb9e3f6c..639846d2d7fe1 100644 --- a/beestation.dme +++ b/beestation.dme @@ -254,6 +254,7 @@ #include "code\__HELPERS\level_traits.dm" #include "code\__HELPERS\maths.dm" #include "code\__HELPERS\matrices.dm" +#include "code\__HELPERS\mob_bodyzone.dm" #include "code\__HELPERS\mobs.dm" #include "code\__HELPERS\mouse_control.dm" #include "code\__HELPERS\names.dm" @@ -2342,6 +2343,7 @@ #include "code\modules\client\preferences\entries\player\tooltips.dm" #include "code\modules\client\preferences\entries\player\ui_style.dm" #include "code\modules\client\preferences\entries\player\window_flashing.dm" +#include "code\modules\client\preferences\entries\player\zone_selection.dm" #include "code\modules\client\preferences\middleware\_middleware.dm" #include "code\modules\client\preferences\middleware\antags.dm" #include "code\modules\client\preferences\middleware\jobs.dm" diff --git a/code/__DEFINES/async.dm b/code/__DEFINES/async.dm index c33f361b9a987..8825de5a30777 100644 --- a/code/__DEFINES/async.dm +++ b/code/__DEFINES/async.dm @@ -17,9 +17,13 @@ #define ASYNC_RETURN(value) created_task.mark_completed(value);\ return; +#define ASYNC_RETURN_TASK(value) return value; + /// Waits for the provided task to be completed, or the timeout to expire. /// Returns null if the timeout expires, or the task's result otherwise. /// Note that if a task's result is null, then null will be returned. +/// This adds a delay for long periods of waiting, so using continue_with +/// is preferred. #define AWAIT(TASK, TIMEOUT) get_result(TASK, TIMEOUT) /proc/get_result(datum/task/task, timeout) diff --git a/code/__DEFINES/bodyparts.dm b/code/__DEFINES/bodyparts.dm index c3d51099e3fb3..a17da968ca9af 100644 --- a/code/__DEFINES/bodyparts.dm +++ b/code/__DEFINES/bodyparts.dm @@ -1 +1,8 @@ #define IS_ORGANIC_LIMB(A) (A.bodytype & BODYTYPE_ORGANIC) + +#define BODYZONE_STYLE_DEFAULT 0 +#define BODYZONE_STYLE_MEDICAL 1 + +#define BODYZONE_CONTEXT_COMBAT 0 +#define BODYZONE_CONTEXT_INJECTION 1 +#define BODYZONE_CONTEXT_ROBOTIC_LIMB_HEALING 2 diff --git a/code/__DEFINES/combat.dm b/code/__DEFINES/combat.dm index e74c112a47600..d82eac619e6ca 100644 --- a/code/__DEFINES/combat.dm +++ b/code/__DEFINES/combat.dm @@ -254,6 +254,10 @@ GLOBAL_LIST_INIT(shove_disarming_types, typecacheof(list( #define GRENADE_NONCLUMSY_FUMBLE 2 #define GRENADE_NO_FUMBLE 3 +#define BODY_GROUP_CHEST_HEAD "chesthead" +#define BODY_GROUP_LEGS "legs" +#define BODY_GROUP_ARMS "arms" + #define BODY_ZONE_HEAD "head" #define BODY_ZONE_CHEST "chest" #define BODY_ZONE_L_ARM "l_arm" diff --git a/code/__DEFINES/keybinding.dm b/code/__DEFINES/keybinding.dm index fa5b2cbe52b52..1d7fb760ea26c 100644 --- a/code/__DEFINES/keybinding.dm +++ b/code/__DEFINES/keybinding.dm @@ -66,6 +66,8 @@ #define COMSIG_KB_MOB_TARGETRIGHTLEG_DOWN "keybinding_mob_targetrightleg_down" #define COMSIG_KB_MOB_TARGETBODYGROIN_DOWN "keybinding_mob_targetbodygroin_down" #define COMSIG_KB_MOB_TARGETLEFTLEG_DOWN "keybinding_mob_targetleftleg_down" +#define COMSIG_KB_MOB_TARGETCYCLEUP_DOWN "keybinding_mob_targetcycleup_down" +#define COMSIG_KB_MOB_TARGETCYCLEDOWN_DOWN "keybinding_mob_targetcycledown_down" #define COMSIG_KB_MOB_PREVENTMOVEMENT_DOWN "keybinding_mob_preventmovement_down" #define COMSIG_KB_MOB_MOVEUP_DOWN "keybinding_mob_moveup_down" #define COMSIG_KB_MOB_MOVEDOWN_DOWN "keybinding_mob_movedown_down" diff --git a/code/__DEFINES/preferences.dm b/code/__DEFINES/preferences.dm index c9da8c7c4b4a1..d43c028ae2f26 100644 --- a/code/__DEFINES/preferences.dm +++ b/code/__DEFINES/preferences.dm @@ -178,6 +178,9 @@ GLOBAL_PROTECT(undatumized_preference_tags_character) #define PREFERENCE_SHEET_LARGE "preferences_l" #define PREFERENCE_SHEET_HUGE "preferences_h" +#define PREFERENCE_BODYZONE_SIMPLIFIED "Simplified Targeting" // Use the simplified system +#define PREFERENCE_BODYZONE_INTENT "Precise Targeting" // Use the bodyzone intent system + /// Stop loading immediately, inform the user. Do not save the data. #define PREFERENCE_LOAD_ERROR 0 /// There is no data to load, they are a guest and will never have this data. @@ -186,3 +189,4 @@ GLOBAL_PROTECT(undatumized_preference_tags_character) #define PREFERENCE_LOAD_NO_DATA 2 /// Normal behavior - success! #define PREFERENCE_LOAD_SUCCESS 3 + diff --git a/code/__HELPERS/mob_bodyzone.dm b/code/__HELPERS/mob_bodyzone.dm new file mode 100644 index 0000000000000..1c5c4e59dff74 --- /dev/null +++ b/code/__HELPERS/mob_bodyzone.dm @@ -0,0 +1,142 @@ + +#define NOT_PRESENT_COLOUR "#0d0d0d" +#define FULL_HEALTH_COLOUR "#11ff00" +#define LOW_DAMAGE_COLOUR "#d9ff00" +#define POOR_HEALTH_COLOUR "#ff0000" + +/// Displays a UI around the target allowing the user to select which bodypart +/// that they want to act on. +/// Target: The location to show the user interface. +/// Precise: Toggle to include groin, eyes and mouth. If true, implies hide_non_present will be forced to false. +/// Icon Callback: The callback to run in order to get the selection zone overlay. +/// If you want to wait for the result use: AWAIT(select_bodyzone(target)) +/mob/proc/select_bodyzone_from_wheel(atom/target, precise = FALSE, datum/callback/icon_callback, override_zones = null) + DECLARE_ASYNC + if (!client || !client.prefs) + ASYNC_RETURN(null) + if (!icon_callback) + icon_callback = CALLBACK(GLOBAL_PROC, GLOBAL_PROC_REF(select_bodyzone_limb_default)) + // Determine what parts we want to show + var/list/bodyzone_options = list() + var/list/parts = list(BODY_ZONE_HEAD, BODY_ZONE_L_ARM, BODY_ZONE_L_LEG, BODY_ZONE_CHEST, BODY_ZONE_R_LEG, BODY_ZONE_R_ARM) + if (override_zones) + parts = override_zones + for (var/bodyzone in parts) + var/image/created_image = image(icon = ui_style2icon(client.prefs?.read_player_preference(/datum/preference/choiced/ui_style)), icon_state = "zone_sel") + var/selection_overlay = icon_callback.Invoke(src, target, bodyzone, FALSE) + created_image.overlays += selection_overlay + bodyzone_options[bodyzone] = created_image + var/result = show_radial_menu(src, target, bodyzone_options, radius = 40, require_near = TRUE, tooltips = TRUE) + + // Disconnected or no result + if (!result || !client) + ASYNC_RETURN(null) + + // Let the user choose more zones + var/list/suboptions = null + if (precise && result == BODY_ZONE_HEAD) + suboptions = list(BODY_ZONE_HEAD, BODY_ZONE_PRECISE_EYES, BODY_ZONE_PRECISE_MOUTH) + else if (precise && result == BODY_ZONE_CHEST) + suboptions = list(BODY_ZONE_CHEST, BODY_ZONE_PRECISE_GROIN) + + if (suboptions) + bodyzone_options = list() + for (var/bodyzone in suboptions) + var/image/created_image = image(icon = ui_style2icon(client.prefs?.read_player_preference(/datum/preference/choiced/ui_style)), icon_state = "zone_sel") + var/selection_overlay = icon_callback.Invoke(src, target, bodyzone, !(bodyzone in parts)) + created_image.overlays += selection_overlay + bodyzone_options[bodyzone] = created_image + result = show_radial_menu(src, target, bodyzone_options, radius = 40, require_near = TRUE, tooltips = TRUE) + + // Disconnected or no result + if (!result || !client) + ASYNC_RETURN(null) + if (!(result in parts) && !(result in suboptions)) + ASYNC_RETURN(null) + ASYNC_RETURN(result) + +/proc/select_bodyzone_limb_default( mob/user, atom/target, bodyzone, is_precise_part = FALSE) + // Create the overlay + var/image/selection_overlay = image(icon = 'icons/mob/zone_sel.dmi', icon_state = bodyzone) + return selection_overlay + +/proc/select_bodyzone_limb_health(accurate_health = FALSE, mob/user, atom/target, bodyzone, is_precise_part = FALSE) + // Get the colours + var/list/healthy = rgb2num(FULL_HEALTH_COLOUR) + var/list/damaged = rgb2num(LOW_DAMAGE_COLOUR) + var/list/unhealthy = rgb2num(POOR_HEALTH_COLOUR) + var/list/not_present = rgb2num(NOT_PRESENT_COLOUR) + // Create the overlay + var/image/selection_overlay = image(icon = 'icons/mob/zone_sel.dmi', icon_state = bodyzone) + // If the target is a mob, then colour the parts according to the part's health + if (isliving(target)) + var/mob/living/living_target = target + var/obj/item/bodypart/target_part = living_target.get_bodypart(bodyzone) + // Determine what colour to make the indicator + var/list/new_colour + var/flash = FALSE + if (!target_part) + if (is_precise_part) + new_colour = healthy + else + new_colour = not_present + else + // 0 = healthy, 1 = dead + var/proportion = target_part.get_damage() / target_part.max_damage + if (!accurate_health) + proportion = proportion > 0 ? max(round(proportion, 1), 0.05) : 0 + else + if (target_part.burn_dam > 0) + var/image/dam_indicator = image(icon = 'icons/mob/zone_dam.dmi', icon_state = "burn") + dam_indicator.appearance_flags = RESET_COLOR | RESET_ALPHA + selection_overlay.overlays += dam_indicator + if (target_part.brute_dam > 0) + var/image/dam_indicator = image(icon = 'icons/mob/zone_dam.dmi', icon_state = "brute") + dam_indicator.appearance_flags = RESET_COLOR | RESET_ALPHA + selection_overlay.overlays += dam_indicator + if (proportion > 0) + new_colour = list( + proportion * unhealthy[1] + (1 - proportion) * damaged[1], + proportion * unhealthy[2] + (1 - proportion) * damaged[2], + proportion * unhealthy[3] + (1 - proportion) * damaged[3], + ) + else + new_colour = healthy + flash = proportion >= 0.01 + // Set the colour + selection_overlay.color = list( + new_colour[1] / 255, + new_colour[2] / 255, + new_colour[3] / 255, + 0, + 0, 1, 0, 0, + 0, 0, 1, 0, + 0, 0, 0, 1, + ) + if (flash) + animate(selection_overlay, time = 1 SECONDS, loop = -1, easing = SINE_EASING, color = list( + new_colour[1] / 255, + new_colour[2] / 255, + new_colour[3] / 255, + 0, + 0, 1, 0, 0, + 0, 0, 1, 0, + 0, 0, 0, 2, + )) + animate(time = 1 SECONDS, loop = -1, easing = SINE_EASING, color = list( + new_colour[1] / 255, + new_colour[2] / 255, + new_colour[3] / 255, + 0, + 0, 1, 0, 0, + 0, 0, 1, 0, + 0, 0, 0, 1, + )) + return selection_overlay + +/mob/proc/_is_holding(obj/item/item) + return get_active_held_item() == item + +#undef NOT_PRESENT_COLOUR +#undef FULL_HEALTH_COLOUR +#undef POOR_HEALTH_COLOUR diff --git a/code/_onclick/click.dm b/code/_onclick/click.dm index e8aac70c8206d..f585a80349d20 100644 --- a/code/_onclick/click.dm +++ b/code/_onclick/click.dm @@ -392,7 +392,7 @@ playsound(usr.loc, 'sound/weapons/taser2.ogg', 75, 1) LE.firer = src - LE.def_zone = ran_zone(zone_selected) + LE.def_zone = ran_zone(get_combat_bodyzone(A)) LE.preparePixelProjectile(A, src, params) LE.fire() @@ -473,6 +473,15 @@ /mob/proc/MouseWheelOn(atom/A, delta_x, delta_y, params) SEND_SIGNAL(src, COMSIG_MOB_MOUSE_SCROLL_ON, A, delta_x, delta_y, params) + if (!client) + return + // Send the hotkey action + if (delta_y > 0) + client.keyDown("ScrollUp") + client.keyUp("ScrollUp") + else if (delta_y < 0) + client.keyDown("ScrollDown") + client.keyUp("ScrollDown") /mob/dead/observer/proc/mouse_wheeled(atom/A, delta_x, delta_y, params) SIGNAL_HANDLER diff --git a/code/_onclick/hud/screen_objects.dm b/code/_onclick/hud/screen_objects.dm index a07a3af44cc8e..656986a950f22 100644 --- a/code/_onclick/hud/screen_objects.dm +++ b/code/_onclick/hud/screen_objects.dm @@ -474,7 +474,7 @@ var/list/modifiers = params2list(params) var/icon_x = text2num(LAZYACCESS(modifiers, ICON_X)) var/icon_y = text2num(LAZYACCESS(modifiers, ICON_Y)) - var/choice = get_zone_at(icon_x, icon_y) + var/choice = get_zone_at(usr, icon_x, icon_y) if (!choice) return 1 @@ -490,7 +490,7 @@ var/list/modifiers = params2list(params) var/icon_x = text2num(LAZYACCESS(modifiers, ICON_X)) var/icon_y = text2num(LAZYACCESS(modifiers, ICON_Y)) - var/choice = get_zone_at(icon_x, icon_y) + var/choice = get_zone_at(usr, icon_x, icon_y) if(hovering == choice) return @@ -517,43 +517,44 @@ vis_contents -= hover_overlays_cache[hovering] hovering = null -/atom/movable/screen/zone_sel/proc/get_zone_at(icon_x, icon_y) +/atom/movable/screen/zone_sel/proc/get_zone_at(mob/user, icon_x, icon_y) + var/simple_mode = user.client?.prefs.read_player_preference(/datum/preference/choiced/zone_select) == PREFERENCE_BODYZONE_SIMPLIFIED switch(icon_y) if(1 to 9) //Legs switch(icon_x) if(10 to 15) - return BODY_ZONE_R_LEG + return simple_mode ? BODY_GROUP_LEGS : BODY_ZONE_R_LEG if(17 to 22) - return BODY_ZONE_L_LEG + return simple_mode ? BODY_GROUP_LEGS : BODY_ZONE_L_LEG if(10 to 13) //Hands and groin switch(icon_x) if(8 to 11) - return BODY_ZONE_R_ARM + return simple_mode ? BODY_GROUP_ARMS : BODY_ZONE_R_ARM if(12 to 20) - return BODY_ZONE_PRECISE_GROIN + return simple_mode ? BODY_GROUP_ARMS : BODY_ZONE_PRECISE_GROIN if(21 to 24) - return BODY_ZONE_L_ARM + return simple_mode ? BODY_GROUP_ARMS : BODY_ZONE_L_ARM if(14 to 22) //Chest and arms to shoulders switch(icon_x) if(8 to 11) - return BODY_ZONE_R_ARM + return simple_mode ? BODY_GROUP_ARMS : BODY_ZONE_R_ARM if(12 to 20) - return BODY_ZONE_CHEST + return simple_mode ? BODY_GROUP_CHEST_HEAD : BODY_ZONE_CHEST if(21 to 24) - return BODY_ZONE_L_ARM + return simple_mode ? BODY_GROUP_ARMS : BODY_ZONE_L_ARM if(23 to 30) //Head, but we need to check for eye or mouth if(icon_x in 12 to 20) switch(icon_y) if(23 to 24) if(icon_x in 15 to 17) - return BODY_ZONE_PRECISE_MOUTH + return simple_mode ? BODY_GROUP_CHEST_HEAD : BODY_ZONE_PRECISE_MOUTH if(26) //Eyeline, eyes are on 15 and 17 if(icon_x in 14 to 18) - return BODY_ZONE_PRECISE_EYES + return simple_mode ? BODY_GROUP_CHEST_HEAD : BODY_ZONE_PRECISE_EYES if(25 to 27) if(icon_x in 15 to 17) - return BODY_ZONE_PRECISE_EYES - return BODY_ZONE_HEAD + return simple_mode ? BODY_GROUP_CHEST_HEAD : BODY_ZONE_PRECISE_EYES + return simple_mode ? BODY_GROUP_CHEST_HEAD : BODY_ZONE_HEAD /atom/movable/screen/zone_sel/proc/set_selected_zone(choice, mob/user) if(user != hud?.mymob) @@ -570,7 +571,7 @@ cut_overlay(selecting_appearance) selecting_appearance = mutable_appearance('icons/mob/screen_gen.dmi', "[selecting]") add_overlay(selecting_appearance) - hud?.mymob?.zone_selected = selecting + hud?.mymob?._set_zone_selected(selecting) /atom/movable/screen/zone_sel/alien icon = 'icons/mob/screen_alien.dmi' @@ -580,7 +581,7 @@ cut_overlay(selecting_appearance) selecting_appearance = mutable_appearance('icons/mob/screen_alien.dmi', "[selecting]") add_overlay(selecting_appearance) - hud?.mymob?.zone_selected = selecting + hud?.mymob?._set_zone_selected(selecting) /atom/movable/screen/zone_sel/robot icon = 'icons/mob/screen_cyborg.dmi' diff --git a/code/datums/components/butchering.dm b/code/datums/components/butchering.dm index b8f66d204cac0..8901bfdba4343 100644 --- a/code/datums/components/butchering.dm +++ b/code/datums/components/butchering.dm @@ -35,7 +35,7 @@ user.show_message("[H]'s neck has already been already cut, you can't make the bleeding any worse!", 1, \ "Their neck has already been already cut, you can't make the bleeding any worse!") return COMPONENT_ITEM_NO_ATTACK - if((H.health <= H.crit_threshold || (user.pulling == H && user.grab_state >= GRAB_NECK) || H.IsSleeping()) && user.zone_selected == BODY_ZONE_HEAD) // Only sleeping, neck grabbed, or crit, can be sliced. + if((H.health <= H.crit_threshold || (user.pulling == H && user.grab_state >= GRAB_NECK) || H.IsSleeping())) // Only sleeping, neck grabbed, or crit, can be sliced. INVOKE_ASYNC(src, PROC_REF(startNeckSlice), source, H, user) return COMPONENT_ITEM_NO_ATTACK diff --git a/code/datums/components/embedded.dm b/code/datums/components/embedded.dm index 5334171425b8f..7216502497aef 100644 --- a/code/datums/components/embedded.dm +++ b/code/datums/components/embedded.dm @@ -256,7 +256,7 @@ /datum/component/embedded/proc/checkRemoval(mob/living/carbon/victim, obj/item/I, mob/user) SIGNAL_HANDLER - if(!istype(victim) || user.zone_selected != limb.body_zone || user.a_intent != INTENT_HELP) + if(!istype(victim) || user.is_zone_selected(limb.body_zone) || user.a_intent != INTENT_HELP) return var/damage_multiplier = 1 diff --git a/code/datums/components/jousting.dm b/code/datums/components/jousting.dm index b5ecc67a5ec7a..17a27da9ef120 100644 --- a/code/datums/components/jousting.dm +++ b/code/datums/components/jousting.dm @@ -55,7 +55,7 @@ var/msg if(damage) msg += "[user] [sharp? "impales" : "slams into"] [target] [sharp? "on" : "with"] their [parent]" - target.apply_damage(damage, BRUTE, user.zone_selected, 0) + target.apply_damage(damage, BRUTE, user.get_combat_bodyzone(target), 0) if(prob(knockdown_chance)) msg += " and knocks [target] [target_buckled? "off of [target.buckled]" : "down"]" if(target_buckled) diff --git a/code/datums/components/pellet_cloud.dm b/code/datums/components/pellet_cloud.dm index 1c855ad6bcf60..846fa4e55637e 100644 --- a/code/datums/components/pellet_cloud.dm +++ b/code/datums/components/pellet_cloud.dm @@ -91,7 +91,7 @@ shooter = user var/turf/targloc = get_turf(target) if(!zone_override) - zone_override = shooter.zone_selected + zone_override = shooter.get_combat_bodyzone(target) for(var/i in 1 to num_pellets) shell.ready_proj(target, user, SUPPRESSED_VERY, zone_override, fired_from) diff --git a/code/datums/elements/mechanical_repair.dm b/code/datums/elements/mechanical_repair.dm index 121654f246bee..298f6bc76773d 100644 --- a/code/datums/elements/mechanical_repair.dm +++ b/code/datums/elements/mechanical_repair.dm @@ -16,36 +16,54 @@ /datum/element/mechanical_repair/proc/try_repair(datum/source, obj/item/I, mob/user) var/mob/living/carbon/human/target = source - var/obj/item/bodypart/affecting = target.get_bodypart(check_zone(user.zone_selected)) + + if(!istype(I, /obj/item/stack/cable_coil) && I.tool_behaviour != TOOL_WELDER) + return // Check to make sure we can repair - if((!affecting || (IS_ORGANIC_LIMB(affecting))) || user.a_intent == INTENT_HARM) + if(user.a_intent == INTENT_HARM) return if(target in user.do_afters) return COMPONENT_NO_AFTERATTACK + var/datum/task/fetch_selected_limb = user.select_bodyzone(target, style = BODYZONE_STYLE_MEDICAL) + fetch_selected_limb.continue_with(CALLBACK(src, PROC_REF(complete_repairs), target, I, user)) + return COMPONENT_NO_AFTERATTACK + +/datum/element/mechanical_repair/proc/complete_repairs(mob/living/carbon/human/target, obj/item/I, mob/user, selected_zone) + if(target in user.do_afters || !user.can_interact_with(target, TRUE) || !user.can_interact_with(I, TRUE)) + return COMPONENT_NO_AFTERATTACK + + var/obj/item/bodypart/affecting = target.get_bodypart(check_zone(selected_zone)) + + if (!affecting || (IS_ORGANIC_LIMB(affecting))) + to_chat(user, "That limb is not robotic!.") + return + // Handles welder repairs on human limbs if(I.tool_behaviour == TOOL_WELDER) - if(I.use_tool(source, user, 0, volume=50, amount=1)) - if(user == target) - user.visible_message("[user] starts to fix some of the dents on [target == user ? "[p_their()]" : "[target]'s"] [parse_zone(affecting.body_zone)].", - "You start fixing some of the dents on [target == user ? "your" : "[target]'s"] [parse_zone(affecting.body_zone)].") - if(!do_after(user, 1.5 SECONDS, target)) - return COMPONENT_NO_AFTERATTACK - item_heal_robotic(target, user, 15, 0, affecting) + do + if(I.use_tool(target, user, 0, volume=50, amount=1)) + if(user == target) + user.visible_message("[user] starts to fix some of the dents on [target == user ? "[p_their()]" : "[target]'s"] [parse_zone(affecting.body_zone)].", + "You start fixing some of the dents on [target == user ? "your" : "[target]'s"] [parse_zone(affecting.body_zone)].") + if(!do_after(user, 1.5 SECONDS, target)) + return COMPONENT_NO_AFTERATTACK + while (item_heal_robotic(target, user, 15, 0, affecting) && user.is_zone_selected(selected_zone) && !QDELETED(I)) user.changeNext_move(CLICK_CD_MELEE * 0.5) //antispam return COMPONENT_NO_AFTERATTACK // Handles cable repairs if(istype(I, /obj/item/stack/cable_coil)) var/obj/item/stack/cable_coil/coil = I - if(user == target) - user.visible_message("[user] starts to fix some of the burn wires in [target == user ? "[p_their()]" : "[target]'s"] [parse_zone(affecting.body_zone)].", - "You start fixing some of the burnt wires in [target == user ? "your" : "[target]'s"] [parse_zone(affecting.body_zone)].") - if(!do_after(user, 1.5 SECONDS, target)) - return COMPONENT_NO_AFTERATTACK - if(coil.amount && item_heal_robotic(target, user, 0, 15, affecting)) - coil.use(1) + do + if(user == target) + user.visible_message("[user] starts to fix some of the burn wires in [target == user ? "[p_their()]" : "[target]'s"] [parse_zone(affecting.body_zone)].", + "You start fixing some of the burnt wires in [target == user ? "your" : "[target]'s"] [parse_zone(affecting.body_zone)].") + if(!do_after(user, 1.5 SECONDS, target)) + return COMPONENT_NO_AFTERATTACK + // Run checks to ensure that we can continue healing. We check coil twice, as we want to break out of the loop if we ran out of coil + while (coil.amount && item_heal_robotic(target, user, 0, 15, affecting) && coil.use(1) && coil.amount && user.is_zone_selected(selected_zone) && !QDELETED(coil)) user.changeNext_move(CLICK_CD_MELEE * 0.5) //antispam return COMPONENT_NO_AFTERATTACK diff --git a/code/datums/keybinding/keybinding.dm b/code/datums/keybinding/keybinding.dm index b77e7ee580364..e306d2b4803a7 100644 --- a/code/datums/keybinding/keybinding.dm +++ b/code/datums/keybinding/keybinding.dm @@ -9,6 +9,10 @@ /// Does this keybind apply regardless of any modifier keys (SHIFT-, ALT-, CTRL-)? /// Important for movement keys, which need to still activate despite other "hold to toggle" bindings on the modifier keys. var/any_modifier = FALSE + /// The typepath of the preference that we must have set to a specific value in order to show + var/required_pref_type = null + /// The value of the preference outlined in required_pref_type that must be set in order to show this keybinding to the user. + var/required_pref_value = null //I don't know why this is done in New() and not down() when it says down(), but that's how it's currently on tg /datum/keybinding/New() @@ -23,4 +27,6 @@ return FALSE /datum/keybinding/proc/can_use(client/user) - return TRUE + if (!required_pref_type) + return TRUE + return user.prefs.read_preference(required_pref_type) == required_pref_value diff --git a/code/datums/keybinding/mob.dm b/code/datums/keybinding/mob.dm index 518d31d78d7b1..8f674cdde5560 100644 --- a/code/datums/keybinding/mob.dm +++ b/code/datums/keybinding/mob.dm @@ -291,12 +291,42 @@ M.toggle_move_intent() return TRUE +/datum/keybinding/mob/prevent_movement + keys = list("Ctrl") + name = "block_movement" + full_name = "Hold to change facing" + description = "While pressed, prevents movement when pressing directional keys; instead just changes your facing direction" + keybind_signal = COMSIG_KB_MOB_PREVENTMOVEMENT_DOWN + +/datum/keybinding/mob/prevent_movement/down(client/user) + . = ..() + if(.) + return + user.movement_locked = TRUE + +/datum/keybinding/mob/prevent_movement/up(client/user) + . = ..() + if(.) + return + user.movement_locked = FALSE + +/** + * =========================== + * Bodyzone targeting section + * =========================== + * + * Precise hotkeys + * + */ + /datum/keybinding/mob/target_head_cycle keys = list("Numpad8") name = "target_head_cycle" full_name = "Target: Cycle head" description = "" keybind_signal = COMSIG_KB_MOB_TARGETCYCLEHEAD_DOWN + required_pref_type = /datum/preference/choiced/zone_select + required_pref_value = PREFERENCE_BODYZONE_INTENT /datum/keybinding/mob/target_head_cycle/down(client/user) . = ..() @@ -312,6 +342,8 @@ full_name = "Target: right arm" description = "" keybind_signal = COMSIG_KB_MOB_TARGETRIGHTARM_DOWN + required_pref_type = /datum/preference/choiced/zone_select + required_pref_value = PREFERENCE_BODYZONE_INTENT /datum/keybinding/mob/target_r_arm/down(client/user) . = ..() @@ -327,6 +359,8 @@ full_name = "Target: Body" description = "" keybind_signal = COMSIG_KB_MOB_TARGETBODYCHEST_DOWN + required_pref_type = /datum/preference/choiced/zone_select + required_pref_value = PREFERENCE_BODYZONE_INTENT /datum/keybinding/mob/target_body_chest/down(client/user) . = ..() @@ -342,6 +376,8 @@ full_name = "Target: left arm" description = "" keybind_signal = COMSIG_KB_MOB_TARGETLEFTARM_DOWN + required_pref_type = /datum/preference/choiced/zone_select + required_pref_value = PREFERENCE_BODYZONE_INTENT /datum/keybinding/mob/target_left_arm/down(client/user) . = ..() @@ -357,6 +393,8 @@ full_name = "Target: Right leg" description = "" keybind_signal = COMSIG_KB_MOB_TARGETRIGHTLEG_DOWN + required_pref_type = /datum/preference/choiced/zone_select + required_pref_value = PREFERENCE_BODYZONE_INTENT /datum/keybinding/mob/target_right_leg/down(client/user) . = ..() @@ -372,6 +410,8 @@ full_name = "Target: Groin" description = "" keybind_signal = COMSIG_KB_MOB_TARGETBODYGROIN_DOWN + required_pref_type = /datum/preference/choiced/zone_select + required_pref_value = PREFERENCE_BODYZONE_INTENT /datum/keybinding/mob/target_body_groin/down(client/user) . = ..() @@ -387,6 +427,8 @@ full_name = "Target: left leg" description = "" keybind_signal = COMSIG_KB_MOB_TARGETLEFTLEG_DOWN + required_pref_type = /datum/preference/choiced/zone_select + required_pref_value = PREFERENCE_BODYZONE_INTENT /datum/keybinding/mob/target_left_leg/down(client/user) . = ..() @@ -396,22 +438,49 @@ user.body_l_leg() return TRUE -/datum/keybinding/mob/prevent_movement - keys = list("Ctrl") - name = "block_movement" - full_name = "Hold to change facing" - description = "While pressed, prevents movement when pressing directional keys; instead just changes your facing direction" - keybind_signal = COMSIG_KB_MOB_PREVENTMOVEMENT_DOWN - -/datum/keybinding/mob/prevent_movement/down(client/user) +/** + * =========================== + * Bodyzone targeting section + * =========================== + * + * Simplified hotkeys + * + */ + +/datum/keybinding/mob/target_higher_zone + keys = list("ScrollUp") + name = "target_higher_zone" + full_name = "Target: Cycle zone up" + description = "Cycles the targeted bodyzone upwards. Leg targeting will become arm targeting, and arm targeting will become body/head targeting." + keybind_signal = COMSIG_KB_MOB_TARGETCYCLEUP_DOWN + required_pref_type = /datum/preference/choiced/zone_select + required_pref_value = PREFERENCE_BODYZONE_SIMPLIFIED + +/datum/keybinding/mob/target_higher_zone/down(client/user) . = ..() if(.) return - user.movement_locked = TRUE + if(!user.mob) + return + user.body_up() + return TRUE -/datum/keybinding/mob/prevent_movement/up(client/user) + +/datum/keybinding/mob/target_lower_zone + keys = list("ScrollDown") + name = "target_lower_zone" + full_name = "Target: Cycle zone down" + description = "Cycles the targeted bodyzone downwards. Head/body targeting will become arm targeting and arm targeting will become leg targeting.." + keybind_signal = COMSIG_KB_MOB_TARGETCYCLEDOWN_DOWN + required_pref_type = /datum/preference/choiced/zone_select + required_pref_value = PREFERENCE_BODYZONE_SIMPLIFIED + +/datum/keybinding/mob/target_lower_zone/down(client/user) . = ..() if(.) return - user.movement_locked = FALSE + if(!user.mob) + return + user.body_down() + return TRUE diff --git a/code/datums/martial/_martial.dm b/code/datums/martial/_martial.dm index aa50a31dd718b..272cc3059ebbf 100644 --- a/code/datums/martial/_martial.dm +++ b/code/datums/martial/_martial.dm @@ -61,7 +61,7 @@ log_combat(A, D, "attempted to [atk_verb]") return 0 - var/obj/item/bodypart/affecting = D.get_bodypart(ran_zone(A.zone_selected)) + var/obj/item/bodypart/affecting = D.get_bodypart(ran_zone(A.get_combat_bodyzone(D))) var/armor_block = D.run_armor_check(affecting, MELEE) playsound(D.loc, A.dna.species.attack_sound, 25, 1, -1) diff --git a/code/datums/martial/boxing.dm b/code/datums/martial/boxing.dm index 59d5cfdb2e0d6..c29325e261be0 100644 --- a/code/datums/martial/boxing.dm +++ b/code/datums/martial/boxing.dm @@ -25,7 +25,7 @@ return 0 - var/obj/item/bodypart/affecting = D.get_bodypart(ran_zone(A.zone_selected)) + var/obj/item/bodypart/affecting = D.get_bodypart(ran_zone(A.get_combat_bodyzone(D))) var/armor_block = D.run_armor_check(affecting, MELEE) playsound(D.loc, A.dna.species.attack_sound, 25, 1, -1) diff --git a/code/datums/martial/krav_maga.dm b/code/datums/martial/krav_maga.dm index 643845af95e97..c6f166d298c56 100644 --- a/code/datums/martial/krav_maga.dm +++ b/code/datums/martial/krav_maga.dm @@ -130,7 +130,7 @@ if(check_streak(A,D)) return 1 log_combat(A, D, "punched") - var/obj/item/bodypart/affecting = D.get_bodypart(ran_zone(A.zone_selected)) + var/obj/item/bodypart/affecting = D.get_bodypart(ran_zone(A.get_combat_bodyzone(D))) var/armor_block = D.run_armor_check(affecting, MELEE) var/picked_hit_type = pick("punched", "kicked") var/bonus_damage = 0 @@ -152,7 +152,7 @@ /datum/martial_art/krav_maga/disarm_act(var/mob/living/carbon/human/A, var/mob/living/carbon/human/D) if(check_streak(A,D)) return 1 - var/obj/item/bodypart/affecting = D.get_bodypart(ran_zone(A.zone_selected)) + var/obj/item/bodypart/affecting = D.get_bodypart(ran_zone(A.get_combat_bodyzone(D))) var/armor_block = D.run_armor_check(affecting, MELEE) if((D.mobility_flags & MOBILITY_STAND)) D.visible_message("[A] reprimands [D]!", \ diff --git a/code/datums/task.dm b/code/datums/task.dm index c9d57fdd83140..c9022064ea5db 100644 --- a/code/datums/task.dm +++ b/code/datums/task.dm @@ -2,6 +2,7 @@ var/result = null var/completed = FALSE var/list/subtasks + var/list/continuation_tasks = list() /// Add a subtask to this subtask. When awaiting a parent task, it will wait for all subtasks to complete /// and then will return a list containing all the results. @@ -14,15 +15,14 @@ CRASH("Attempting to mark a subtask holder as completed. This is not allowed") completed = TRUE src.result = result + for (var/datum/callback/callback as() in continuation_tasks) + callback.InvokeAsync(result) /// Wait for the task to be completed, or the timeout to expire /// Returns true if the task was completed /datum/task/proc/await(timeout = 30 SECONDS) var/start_time = world.time - var/sleep_time = 1 - while(world.time < start_time + timeout && !is_completed()) - sleep(sleep_time) - sleep_time = min(sleep_time * 2, 1 SECONDS) + UNTIL (world.time >= start_time + timeout || is_completed()) // Check for success var/success = length(subtasks) ? TRUE : completed if (length(subtasks) && !result) @@ -41,3 +41,18 @@ return FALSE return TRUE return completed + +/// Continue with a callback once the task has completed, +/// invokes immediately unlike AWAIT which may have a 1 second +/// delay causing it to be unresponsive. +/// This is the most effective option for use with UI or player-controlled +/// responses. +/datum/task/proc/continue_with(datum/callback/callback) + if (!callback) + return + // If the async function wasn't async then + // immediately invoke the continuation task + if (completed) + callback.InvokeAsync(result) + return + continuation_tasks += callback diff --git a/code/game/atoms_movable.dm b/code/game/atoms_movable.dm index 30ea7f6b4fbcf..878bf3ca7e5f2 100644 --- a/code/game/atoms_movable.dm +++ b/code/game/atoms_movable.dm @@ -728,7 +728,7 @@ if(QDELETED(thrower) || !istype(thrower)) thrower = null //Let's not pass an invalid reference. else - target_zone = thrower.zone_selected + target_zone = thrower.get_combat_bodyzone(target) var/datum/thrownthing/TT = new(src, target, get_dir(src, target), range, speed, thrower, diagonals_first, force, callback, target_zone) diff --git a/code/game/objects/items/bedsheets.dm b/code/game/objects/items/bedsheets.dm index ba6ba688e78d9..aad4534553160 100644 --- a/code/game/objects/items/bedsheets.dm +++ b/code/game/objects/items/bedsheets.dm @@ -27,8 +27,7 @@ AddElement(/datum/element/bed_tuckable, 0, 0, 0) /obj/item/bedsheet/attack(mob/living/M, mob/user) - if(!attempt_initiate_surgery(src, M, user)) - ..() + attempt_initiate_surgery(src, M, user) /obj/item/bedsheet/attack_self(mob/user) if(!user.CanReach(src)) //No telekenetic grabbing. diff --git a/code/game/objects/items/clown_items.dm b/code/game/objects/items/clown_items.dm index ad7e50cdce868..ee83ff4dfb5de 100644 --- a/code/game/objects/items/clown_items.dm +++ b/code/game/objects/items/clown_items.dm @@ -99,7 +99,7 @@ qdel(target) decreaseUses(user) - else if(ishuman(target) && user.zone_selected == BODY_ZONE_PRECISE_MOUTH) + else if(ishuman(target) && user.is_zone_selected(BODY_ZONE_PRECISE_MOUTH)) var/mob/living/carbon/human/H = user user.visible_message("\the [user] washes \the [target]'s mouth out with [src.name]!", "You wash \the [target]'s mouth out with [src.name]!") //washes mouth out with soap sounds better than 'the soap' here if(user.zone_selected == "mouth") H.lip_style = null //removes lipstick diff --git a/code/game/objects/items/cosmetics.dm b/code/game/objects/items/cosmetics.dm index 1690f6e9a1957..69d133edb6a44 100644 --- a/code/game/objects/items/cosmetics.dm +++ b/code/game/objects/items/cosmetics.dm @@ -78,7 +78,7 @@ //you can wipe off lipstick with paper! /obj/item/paper/attack(mob/M, mob/user) - if(user.zone_selected == BODY_ZONE_PRECISE_MOUTH) + if(user.is_zone_selected(BODY_ZONE_PRECISE_MOUTH)) if(!ismob(M)) return @@ -125,93 +125,101 @@ /obj/item/razor/attack(mob/M, mob/user) - if(ishuman(M) && extended == 1 && user.a_intent != INTENT_HARM) - var/mob/living/carbon/human/H = M - var/location = user.zone_selected - var/mirror = FALSE - if(HAS_TRAIT(H, TRAIT_SELF_AWARE) || locate(/obj/structure/mirror) in range(1, H)) - mirror = TRUE - if((location in list(BODY_ZONE_PRECISE_EYES, BODY_ZONE_PRECISE_MOUTH, BODY_ZONE_HEAD)) && !H.get_bodypart(BODY_ZONE_HEAD)) - to_chat(user, "[H] doesn't have a head!") - return - if(location == BODY_ZONE_PRECISE_MOUTH) - if(user.a_intent == INTENT_HELP) - if(H.gender == MALE) - INVOKE_ASYNC(src, PROC_REF(new_facial_hairstyle), H, user, mirror) - return - else - return + if(!ishuman(M) || extended != 1 || user.a_intent == INTENT_HARM) + return ..() + var/mob/living/carbon/human/H = M + // Must be targetting the head + if (!user.is_zone_selected(BODY_ZONE_HEAD) && !user.is_zone_selected(BODY_ZONE_PRECISE_MOUTH)) + return ..() + if(!H.get_bodypart(BODY_ZONE_HEAD)) + to_chat(user, "[H] doesn't have a head!") + return + var/mirror = FALSE + if(HAS_TRAIT(H, TRAIT_SELF_AWARE) || locate(/obj/structure/mirror) in range(1, H)) + mirror = TRUE + var/datum/task/select_bodyzone = user.select_bodyzone(M, TRUE, BODYZONE_STYLE_DEFAULT, override_zones = list(BODY_ZONE_HEAD, BODY_ZONE_PRECISE_MOUTH)) + select_bodyzone.continue_with(CALLBACK(src, PROC_REF(razor_action), H, user, mirror)) + +/obj/item/razor/proc/razor_action(mob/living/carbon/human/H, mob/user, mirror, location) + if (!user.can_interact_with(H, TRUE)) + to_chat(user, "[H] is too far away!") + return + if (!user.can_interact_with(src, TRUE)) + to_chat(user, "[src] is too far away!") + return + if(location == BODY_ZONE_PRECISE_MOUTH) + if(user.a_intent == INTENT_HELP) + if(H.gender == MALE) + INVOKE_ASYNC(src, PROC_REF(new_facial_hairstyle), H, user, mirror) + return else - if(!(FACEHAIR in H.dna.species.species_traits)) - to_chat(user, "There is no facial hair to shave!") - return - if(!get_location_accessible(H, location)) - to_chat(user, "The mask is in the way!") - return - if(H.facial_hair_style == "Shaved") - to_chat(user, "Already clean-shaven!") - return + return + else + if(!(FACEHAIR in H.dna.species.species_traits)) + to_chat(user, "There is no facial hair to shave!") + return + if(!get_location_accessible(H, location)) + to_chat(user, "The mask is in the way!") + return + if(H.facial_hair_style == "Shaved") + to_chat(user, "Already clean-shaven!") + return - if(H == user) //shaving yourself - user.visible_message("[user] starts to shave [user.p_their()] facial hair with [src].", \ - "You take a moment to shave your facial hair with [src]...") - if(do_after(user, 50, target = H)) - user.visible_message("[user] shaves [user.p_their()] facial hair clean with [src].", \ - "You finish shaving with [src]. Fast and clean!") - shave(H, location) - else - user.visible_message("[user] tries to shave [H]'s facial hair with [src].", \ - "You start shaving [H]'s facial hair...") - if(do_after(user, 50, target = H)) - user.visible_message("[user] shaves off [H]'s facial hair with [src].", \ - "You shave [H]'s facial hair clean off.") - shave(H, location) + if(H == user) //shaving yourself + user.visible_message("[user] starts to shave [user.p_their()] facial hair with [src].", \ + "You take a moment to shave your facial hair with [src]...") + if(do_after(user, 50, target = H)) + user.visible_message("[user] shaves [user.p_their()] facial hair clean with [src].", \ + "You finish shaving with [src]. Fast and clean!") + shave(H, location) + else + user.visible_message("[user] tries to shave [H]'s facial hair with [src].", \ + "You start shaving [H]'s facial hair...") + if(do_after(user, 50, target = H)) + user.visible_message("[user] shaves off [H]'s facial hair with [src].", \ + "You shave [H]'s facial hair clean off.") + shave(H, location) - else if(location == BODY_ZONE_HEAD) - if(user.a_intent == INTENT_HELP) - INVOKE_ASYNC(src, PROC_REF(new_hairstyle), H, user) + else if(location == BODY_ZONE_HEAD) + if(user.a_intent == INTENT_HELP) + INVOKE_ASYNC(src, PROC_REF(new_hairstyle), H, user) + return + else + if(!(HAIR in H.dna.species.species_traits)) + to_chat(user, "There is no hair to shave!") + return + if(!get_location_accessible(H, location)) + to_chat(user, "The headgear is in the way!") + return + if(H.hair_style == "Bald" || H.hair_style == "Balding Hair" || H.hair_style == "Skinhead") + to_chat(user, "There is not enough hair left to shave!") return - else - if(!(HAIR in H.dna.species.species_traits)) - to_chat(user, "There is no hair to shave!") - return - if(!get_location_accessible(H, location)) - to_chat(user, "The headgear is in the way!") - return - if(H.hair_style == "Bald" || H.hair_style == "Balding Hair" || H.hair_style == "Skinhead") - to_chat(user, "There is not enough hair left to shave!") - return - if(H == user) //shaving yourself - user.visible_message("[user] starts to shave [user.p_their()] head with [src].", \ - "You start to shave your head with [src]...") - if(do_after(user, 5, target = H)) - user.visible_message("[user] shaves [user.p_their()] head with [src].", \ - "You finish shaving with [src].") + if(H == user) //shaving yourself + user.visible_message("[user] starts to shave [user.p_their()] head with [src].", \ + "You start to shave your head with [src]...") + if(do_after(user, 5, target = H)) + user.visible_message("[user] shaves [user.p_their()] head with [src].", \ + "You finish shaving with [src].") + shave(H, location) + else + var/turf/H_loc = H.loc + user.visible_message("[user] tries to shave [H]'s head with [src]!", \ + "You start shaving [H]'s head...") + if(do_after(user, 50, target = H)) + if(H_loc == H.loc) + user.visible_message("[user] shaves [H]'s head bald with [src]!", \ + "You shave [H]'s head bald.") shave(H, location) - else - var/turf/H_loc = H.loc - user.visible_message("[user] tries to shave [H]'s head with [src]!", \ - "You start shaving [H]'s head...") - if(do_after(user, 50, target = H)) - if(H_loc == H.loc) - user.visible_message("[user] shaves [H]'s head bald with [src]!", \ - "You shave [H]'s head bald.") - shave(H, location) - else - ..() - else - ..() /obj/item/razor/proc/new_hairstyle(mob/living/carbon/human/H, mob/user, mirror) - var/location = user.zone_selected if (H == user && !mirror) to_chat(user, "You need a mirror to properly style your own hair!") return if(!user.canUseTopic(src, BE_CLOSE, FALSE, NO_TK)) return var/new_style = input(user, "Select a hair style", "Grooming") as null|anything in GLOB.hair_styles_list - if(!get_location_accessible(H, location)) + if(!get_location_accessible(H, BODY_ZONE_HEAD)) to_chat(user, "The headgear is in the way!") return user.visible_message("[user] tries to change [H]'s hairstyle using [src].", "You try to change [H]'s hairstyle using [src].") @@ -221,14 +229,13 @@ H.update_hair() /obj/item/razor/proc/new_facial_hairstyle(mob/living/carbon/human/H, mob/user, var/mirror) - var/location = user.zone_selected if(H == user && !mirror) to_chat(user, "You need a mirror to properly style your own facial hair!") return if(!user.canUseTopic(src, BE_CLOSE, FALSE, NO_TK)) return var/new_style = input(user, "Select a facial hair style", "Grooming") as null|anything in GLOB.facial_hair_styles_list - if(!get_location_accessible(H, location)) + if(!get_location_accessible(H, BODY_ZONE_PRECISE_MOUTH)) to_chat(user, "The mask is in the way!") return user.visible_message("[user] tries to change [H]'s facial hair style using [src].", "You try to change [H]'s facial hair style using [src].") diff --git a/code/game/objects/items/defib.dm b/code/game/objects/items/defib.dm index 8a33fb2264bd7..4675d451aa906 100644 --- a/code/game/objects/items/defib.dm +++ b/code/game/objects/items/defib.dm @@ -465,7 +465,7 @@ var/mob/living/carbon/H = M - if(user.zone_selected != BODY_ZONE_CHEST) + if(!user.is_zone_selected(BODY_ZONE_CHEST)) to_chat(user, "You need to target your patient's chest with [src]!") return diff --git a/code/game/objects/items/devices/flashlight.dm b/code/game/objects/items/devices/flashlight.dm index 0a1f423d445d1..0af132d8641eb 100644 --- a/code/game/objects/items/devices/flashlight.dm +++ b/code/game/objects/items/devices/flashlight.dm @@ -56,116 +56,120 @@ /obj/item/flashlight/attack(mob/living/carbon/M, mob/living/carbon/human/user) add_fingerprint(user) - if(istype(M) && on && (user.zone_selected in list(BODY_ZONE_PRECISE_EYES, BODY_ZONE_PRECISE_MOUTH))) + if (!istype(M) || !on || !user.is_zone_selected(BODY_ZONE_HEAD, precise = FALSE)) + return ..() - if((HAS_TRAIT(user, TRAIT_CLUMSY) || HAS_TRAIT(user, TRAIT_DUMB)) && prob(50)) //too dumb to use flashlight properly - return ..() //just hit them in the head + if((HAS_TRAIT(user, TRAIT_CLUMSY) || HAS_TRAIT(user, TRAIT_DUMB)) && prob(50)) //too dumb to use flashlight properly + return ..() //just hit them in the head - if(!user.IsAdvancedToolUser()) - to_chat(user, "You don't have the dexterity to do this!") - return + if(!user.IsAdvancedToolUser()) + to_chat(user, "You don't have the dexterity to do this!") + return - if(!M.get_bodypart(BODY_ZONE_HEAD)) - to_chat(user, "[M] doesn't have a head!") - return + if(!M.get_bodypart(BODY_ZONE_HEAD)) + to_chat(user, "[M] doesn't have a head!") + return - if(light_power < 1) - to_chat(user, "\The [src] isn't bright enough to see anything! ") - return + if(light_power < 1) + to_chat(user, "\The [src] isn't bright enough to see anything! ") + return - switch(user.zone_selected) - if(BODY_ZONE_PRECISE_EYES) - if((M.head && M.head.flags_cover & HEADCOVERSEYES) || (M.wear_mask && M.wear_mask.flags_cover & MASKCOVERSEYES) || (M.glasses && M.glasses.flags_cover & GLASSESCOVERSEYES)) - to_chat(user, "You're going to need to remove that [(M.head && M.head.flags_cover & HEADCOVERSEYES) ? "helmet" : (M.wear_mask && M.wear_mask.flags_cover & MASKCOVERSEYES) ? "mask": "glasses"] first.") - return + user.visible_message("[user] shines the light at [M]!", ignored_mobs = list(user)) - var/obj/item/organ/eyes/E = M.getorganslot(ORGAN_SLOT_EYES) - if(!E) - to_chat(user, "[M] doesn't have any eyes!") - return + var/list/results = list() - if(M == user) //they're using it on themselves - if(M.flash_act(visual = 1)) - M.visible_message("[M] directs [src] to [M.p_their()] eyes.", "You wave the light in front of your eyes! Trippy!") - else - M.visible_message("[M] directs [src] to [M.p_their()] eyes.", "You wave the light in front of your eyes.") - else - user.visible_message("[user] directs [src] to [M]'s eyes.", \ - "You direct [src] to [M]'s eyes.") - if(M.stat == DEAD || (M.is_blind()) || !M.flash_act(visual = 1)) //mob is dead or fully blind - to_chat(user, "[M]'s pupils don't react to the light!") - else if(M.has_dna() && M.dna.check_mutation(XRAY)) //mob has X-ray vision - to_chat(user, "[M]'s pupils give an eerie glow!") - else //they're okay! - to_chat(user, "[M]'s pupils narrow.") - - if(BODY_ZONE_PRECISE_MOUTH) - - if(M.is_mouth_covered()) - to_chat(user, "You're going to need to remove that [(M.head && M.head.flags_cover & HEADCOVERSMOUTH) ? "helmet" : "mask"] first.") - return - - var/their = M.p_their() - - var/list/mouth_organs = new - for(var/obj/item/organ/O in M.internal_organs) - if(O.zone == BODY_ZONE_PRECISE_MOUTH) - mouth_organs.Add(O) - var/organ_list = "" - var/organ_count = LAZYLEN(mouth_organs) - if(organ_count) - for(var/I in 1 to organ_count) - if(I > 1) - if(I == mouth_organs.len) - organ_list += ", and " - else - organ_list += ", " - var/obj/item/organ/O = mouth_organs[I] - organ_list += (O.gender == "plural" ? O.name : "\an [O.name]") - - var/pill_count = 0 - for(var/datum/action/item_action/hands_free/activate_pill/AP in M.actions) - pill_count++ - - if(M == user) - var/can_use_mirror = FALSE - if(isturf(user.loc)) - var/obj/structure/mirror/mirror = locate(/obj/structure/mirror, user.loc) - if(mirror) - switch(user.dir) - if(NORTH) - can_use_mirror = mirror.pixel_y > 0 - if(SOUTH) - can_use_mirror = mirror.pixel_y < 0 - if(EAST) - can_use_mirror = mirror.pixel_x > 0 - if(WEST) - can_use_mirror = mirror.pixel_x < 0 - - M.visible_message("[M] directs [src] to [their] mouth.", \ - "You point [src] into your mouth.") - if(!can_use_mirror) - to_chat(user, "You can't see anything without a mirror.") - return - if(organ_count) - to_chat(user, "Inside your mouth [organ_count > 1 ? "are" : "is"] [organ_list].") - else - to_chat(user, "There's nothing inside your mouth.") - if(pill_count) - to_chat(user, "You have [pill_count] implanted pill[pill_count > 1 ? "s" : ""].") - - else - user.visible_message("[user] directs [src] to [M]'s mouth.",\ - "You direct [src] to [M]'s mouth.") - if(organ_count) - to_chat(user, "Inside [their] mouth [organ_count > 1 ? "are" : "is"] [organ_list].") + results += "You shine the light at [M]..." + + /** + * Handle mouth + */ + + if(M.is_mouth_covered()) + results += "[M.p_their()] mouth is covered by [(M.head && M.head.flags_cover & HEADCOVERSMOUTH) ? "a helmet" : "a mask"]." + else + var/their = M.p_their() + + var/list/mouth_organs = new + for(var/obj/item/organ/O in M.internal_organs) + if(O.zone == BODY_ZONE_PRECISE_MOUTH) + mouth_organs.Add(O) + var/organ_list = "" + var/organ_count = LAZYLEN(mouth_organs) + if(organ_count) + for(var/I in 1 to organ_count) + if(I > 1) + if(I == mouth_organs.len) + organ_list += ", and " else - to_chat(user, "[M] doesn't have any organs in [their] mouth.") - if(pill_count) - to_chat(user, "[M] has [pill_count] pill[pill_count > 1 ? "s" : ""] implanted in [their] teeth.") + organ_list += ", " + var/obj/item/organ/O = mouth_organs[I] + organ_list += (O.gender == "plural" ? O.name : "\an [O.name]") + + var/pill_count = 0 + for(var/datum/action/item_action/hands_free/activate_pill/AP in M.actions) + pill_count++ + + if(M == user) + var/can_use_mirror = FALSE + if(isturf(user.loc)) + var/obj/structure/mirror/mirror = locate(/obj/structure/mirror, user.loc) + if(mirror) + switch(user.dir) + if(NORTH) + can_use_mirror = mirror.pixel_y > 0 + if(SOUTH) + can_use_mirror = mirror.pixel_y < 0 + if(EAST) + can_use_mirror = mirror.pixel_x > 0 + if(WEST) + can_use_mirror = mirror.pixel_x < 0 + + if(!can_use_mirror) + to_chat(user, "You can't see anything without a mirror.") + return + if(organ_count) + results += "Inside your mouth [organ_count > 1 ? "are" : "is"] [organ_list]." + else + results += "There's nothing inside your mouth." + if(pill_count) + results += "You have [pill_count] implanted pill[pill_count > 1 ? "s" : ""]." + else + user.visible_message("[user] directs [src] to [M]'s mouth.",\ + "You direct [src] to [M]'s mouth.") + if(organ_count) + results += "Inside [their] mouth [organ_count > 1 ? "are" : "is"] [organ_list]." + else + results += "[M] doesn't have any organs in [their] mouth." + if(pill_count) + results += "[M] has [pill_count] pill[pill_count > 1 ? "s" : ""] implanted in [their] teeth." + + /** + * Handle eyes + */ + + var/obj/item/organ/eyes/E = M.getorganslot(ORGAN_SLOT_EYES) + + if((M.head && M.head.flags_cover & HEADCOVERSEYES) || (M.wear_mask && M.wear_mask.flags_cover & MASKCOVERSEYES) || (M.glasses && M.glasses.flags_cover & GLASSESCOVERSEYES)) + results += "[M.p_their()] eyes are covered by [(M.head && M.head.flags_cover & HEADCOVERSEYES) ? "a helmet" : (M.wear_mask && M.wear_mask.flags_cover & MASKCOVERSEYES) ? "a mask": "some glasses"]." + else if(!E) + results += "[M.p_they()] doesn't have any eyes!" + else if(M == user) + //they're using it on themselves, give less of a report + if(M.flash_act(visual = 1)) + to_chat(user, "You wave the light in front of your eyes! Trippy!") + else + to_chat(user, "You wave the light in front of your eyes.") + return else - return ..() + if(M.stat == DEAD || (M.is_blind()) || !M.flash_act(visual = 1)) //mob is dead or fully blind + results += "[M.p_their(TRUE)] pupils don't react to the light!" + else if(M.has_dna() && M.dna.check_mutation(XRAY)) //mob has X-ray vision + results += "[M.p_their(TRUE)] pupils give an eerie glow!" + else //they're okay! + results += "[M.p_their(TRUE)] pupils narrow." + + to_chat(user, EXAMINE_BLOCK(jointext(results, "\n"))) /obj/item/flashlight/pen name = "penlight" @@ -400,7 +404,7 @@ return TRUE /obj/item/flashlight/emp/attack(mob/living/M, mob/living/user) - if(on && (user.zone_selected in list(BODY_ZONE_PRECISE_EYES, BODY_ZONE_PRECISE_MOUTH))) // call original attack when examining organs + if(on && (user.is_zone_selected(BODY_ZONE_PRECISE_EYES, precise_only = TRUE) || user.is_zone_selected(BODY_ZONE_PRECISE_MOUTH, precise_only = TRUE))) // call original attack when examining organs ..() return diff --git a/code/game/objects/items/devices/laserpointer.dm b/code/game/objects/items/devices/laserpointer.dm index 854c23e66aece..6960b2c2d6c0a 100644 --- a/code/game/objects/items/devices/laserpointer.dm +++ b/code/game/objects/items/devices/laserpointer.dm @@ -99,7 +99,7 @@ //human/alien mobs if(iscarbon(target)) var/mob/living/carbon/C = target - if(user.zone_selected == BODY_ZONE_PRECISE_EYES) + if(user.is_zone_selected(BODY_ZONE_PRECISE_EYES)) log_combat(user, C, "shone in the eyes", src) var/severity = 1 diff --git a/code/game/objects/items/kitchen.dm b/code/game/objects/items/kitchen.dm index 41de38bc42992..a752a2b8be86f 100644 --- a/code/game/objects/items/kitchen.dm +++ b/code/game/objects/items/kitchen.dm @@ -50,7 +50,7 @@ icon_state = "fork" forkload = null - else if(user.zone_selected == BODY_ZONE_PRECISE_EYES) + else if(user.is_zone_selected(BODY_ZONE_PRECISE_EYES, simplified_probability = 30)) if(HAS_TRAIT(user, TRAIT_CLUMSY) && prob(50)) M = user return eyestab(M,user) diff --git a/code/game/objects/items/knives.dm b/code/game/objects/items/knives.dm index 81203389c7a6f..e0a0de7a9d215 100644 --- a/code/game/objects/items/knives.dm +++ b/code/game/objects/items/knives.dm @@ -31,7 +31,7 @@ set_butchering() /obj/item/knife/attack(mob/living/carbon/M, mob/living/carbon/user) - if(user.zone_selected == BODY_ZONE_PRECISE_EYES) + if(user.is_zone_selected(BODY_ZONE_PRECISE_EYES)) if(HAS_TRAIT(user, TRAIT_CLUMSY) && prob(50)) M = user return eyestab(M,user) diff --git a/code/game/objects/items/melee/misc.dm b/code/game/objects/items/melee/misc.dm index c82a1aaddd764..8914f17fac922 100644 --- a/code/game/objects/items/melee/misc.dm +++ b/code/game/objects/items/melee/misc.dm @@ -292,19 +292,20 @@ user.do_attack_animation(target) playsound(get_turf(src), on_stun_sound, 75, 1, -1) additional_effects_carbon(target, user) - if((user.zone_selected == BODY_ZONE_HEAD) || (user.zone_selected == BODY_ZONE_CHEST)) + if((user.is_zone_selected(BODY_ZONE_HEAD)) || (user.is_zone_selected(BODY_ZONE_CHEST))) target.apply_damage(stamina_damage, STAMINA, BODY_ZONE_CHEST, def_check) log_combat(user, target, "stunned", src) target.visible_message(desc["visiblestun"], desc["localstun"]) - if((user.zone_selected == BODY_ZONE_R_LEG) || (user.zone_selected == BODY_ZONE_L_LEG)) + if((user.is_zone_selected(BODY_ZONE_R_LEG)) || (user.is_zone_selected(BODY_ZONE_L_LEG))) target.Knockdown(30) log_combat(user, target, "tripped", src) target.visible_message(desc["visibletrip"], desc["localtrip"]) - if(user.zone_selected == BODY_ZONE_L_ARM) + var/combat_zone = user.get_combat_bodyzone(target) + if(combat_zone == BODY_ZONE_L_ARM) target.apply_damage(50, STAMINA, BODY_ZONE_L_ARM, def_check) log_combat(user, target, "disarmed", src) target.visible_message(desc["visibledisarm"], desc["localdisarm"]) - if(user.zone_selected == BODY_ZONE_R_ARM) + if(combat_zone == BODY_ZONE_R_ARM) target.apply_damage(50, STAMINA, BODY_ZONE_R_ARM, def_check) log_combat(user, target, "disarmed", src) target.visible_message(desc["visibledisarm"], desc["localdisarm"]) @@ -711,7 +712,7 @@ if(!ishuman(target)) return - switch(user.zone_selected) + switch(user.get_combat_bodyzone(target)) if(BODY_ZONE_L_ARM) whip_disarm(user, target, "left") if(BODY_ZONE_R_ARM) diff --git a/code/game/objects/items/robot/robot_items.dm b/code/game/objects/items/robot/robot_items.dm index 8fc40dc90ddab..7cc6957e03195 100644 --- a/code/game/objects/items/robot/robot_items.dm +++ b/code/game/objects/items/robot/robot_items.dm @@ -70,7 +70,7 @@ switch(mode) if(0) if(M.health >= 0) - if(user.zone_selected == BODY_ZONE_HEAD) + if(user.is_zone_selected(BODY_ZONE_HEAD, precise_only = TRUE)) user.visible_message("[user] playfully boops [M] on the head!", \ "You playfully boop [M] on the head!") user.do_attack_animation(M, ATTACK_EFFECT_BOOP) @@ -94,7 +94,7 @@ if(!(M.mobility_flags & MOBILITY_STAND)) user.visible_message("[user] shakes [M] trying to get [M.p_them()] up!", \ "You shake [M] trying to get [M.p_them()] up!") - else if(user.zone_selected == BODY_ZONE_HEAD) + else if(user.is_zone_selected(BODY_ZONE_HEAD, precise_only = TRUE)) user.visible_message("[user] bops [M] on the head!", \ "You bop [M] on the head!") user.do_attack_animation(M, ATTACK_EFFECT_PUNCH) diff --git a/code/game/objects/items/stacks/medical.dm b/code/game/objects/items/stacks/medical.dm index 71d41d697e3cd..6a553a1193053 100644 --- a/code/game/objects/items/stacks/medical.dm +++ b/code/game/objects/items/stacks/medical.dm @@ -40,6 +40,9 @@ if(!iscarbon(M) && !isanimal(M)) to_chat(user, "You don't know how to apply \the [src] to [M]!") return + + if(M in user.do_afters) //One at a time, please. + return if(isanimal(M)) var/mob/living/simple_animal/critter = M @@ -57,15 +60,33 @@ use(1) return + var/datum/task/select_bodyzone_task = user.select_bodyzone(M, FALSE, BODYZONE_STYLE_MEDICAL) + select_bodyzone_task.continue_with(CALLBACK(src, PROC_REF(do_application), M, user)) + +/obj/item/stack/medical/proc/do_application(mob/living/M, mob/user, zone_selected) + if (!zone_selected) + return + if (!user.can_interact_with(M, TRUE)) + to_chat(user, "You cannot reach [M]!") + return + if (!user.can_interact_with(src, TRUE)) + to_chat(user, "You cannot reach [src]!") + return + if(M.stat == DEAD && !stop_bleeding) + to_chat(user, "\The [M] is dead, you cannot help [M.p_them()]!") + return + if(!iscarbon(M)) + to_chat(user, "You don't know how to apply \the [src] to [M]!") + return var/obj/item/bodypart/affecting var/mob/living/carbon/C = M - affecting = C.get_bodypart(check_zone(user.zone_selected)) + affecting = C.get_bodypart(check_zone(zone_selected)) if(M in user.do_afters) //One at a time, please. return if(!affecting) //Missing limb? - to_chat(user, "[C] doesn't have \a [parse_zone(user.zone_selected)]!") + to_chat(user, "[C] doesn't have \a [parse_zone(zone_selected)]!") return if(ishuman(C)) //apparently only humans bleed? funky. @@ -84,7 +105,7 @@ return if(!(affecting.brute_dam || affecting.burn_dam)) - to_chat(user, "[M]'s [parse_zone(user.zone_selected)] isn't hurt!") + to_chat(user, "[M]'s [parse_zone(zone_selected)] isn't hurt!") return if((affecting.brute_dam && !affecting.burn_dam && !heal_brute) || (affecting.burn_dam && !affecting.brute_dam && !heal_burn)) //suffer diff --git a/code/game/objects/items/stunbaton.dm b/code/game/objects/items/stunbaton.dm index b488427db88a5..29a34635387f9 100644 --- a/code/game/objects/items/stunbaton.dm +++ b/code/game/objects/items/stunbaton.dm @@ -177,7 +177,7 @@ if(!deductcharge(hitcost)) return FALSE - var/obj/item/bodypart/affecting = target.get_bodypart(ran_zone(user.zone_selected)) + var/obj/item/bodypart/affecting = target.get_bodypart(ran_zone(user.get_combat_bodyzone(target))) var/armor_block = target.run_armor_check(affecting, STAMINA) // L.adjustStaminaLoss(stunforce) target.apply_damage(stunforce, STAMINA, affecting, armor_block) diff --git a/code/game/objects/items/tools/powertools.dm b/code/game/objects/items/tools/powertools.dm index 1e8aa0544a917..b44c3afbe6f4d 100644 --- a/code/game/objects/items/tools/powertools.dm +++ b/code/game/objects/items/tools/powertools.dm @@ -72,7 +72,7 @@ /obj/item/powertool/hand_drill/attack(mob/living/M, mob/living/user) if(!istype(M) || tool_behaviour != TOOL_SCREWDRIVER) return ..() - if(user.zone_selected != BODY_ZONE_PRECISE_EYES && user.zone_selected != BODY_ZONE_HEAD) + if(!user.is_zone_selected(BODY_ZONE_PRECISE_EYES, precise_only = TRUE) && !user.is_zone_selected(BODY_ZONE_HEAD, simplified_probability = 40)) return ..() if(HAS_TRAIT(user, TRAIT_PACIFISM)) to_chat(user, "You don't want to harm [M]!") diff --git a/code/game/objects/items/tools/screwdriver.dm b/code/game/objects/items/tools/screwdriver.dm index 3875a5ec30b1b..14f576faae143 100644 --- a/code/game/objects/items/tools/screwdriver.dm +++ b/code/game/objects/items/tools/screwdriver.dm @@ -55,7 +55,7 @@ /obj/item/screwdriver/attack(mob/living/carbon/M, mob/living/carbon/user) if(!istype(M)) return ..() - if(user.zone_selected != BODY_ZONE_PRECISE_EYES && user.zone_selected != BODY_ZONE_HEAD) + if(!user.is_zone_selected(BODY_ZONE_PRECISE_EYES, precise_only = TRUE) && !user.is_zone_selected(BODY_ZONE_HEAD, simplified_probability = 40)) return ..() if(HAS_TRAIT(user, TRAIT_PACIFISM)) to_chat(user, "You don't want to harm [M]!") diff --git a/code/game/objects/items/weaponry.dm b/code/game/objects/items/weaponry.dm index c47660c3dc38b..c7961370befa2 100644 --- a/code/game/objects/items/weaponry.dm +++ b/code/game/objects/items/weaponry.dm @@ -24,7 +24,7 @@ mrdoombringer sez: and remember kids, if you try and PR a fix for this item's gr for further reading, please see: https://github.com/tgstation/tgstation/pull/30173 and https://translate.google.com/translate?sl=auto&tl=en&js=y&prev=_t&hl=en&ie=UTF-8&u=%2F%2Flurkmore.to%2FSS13&edit-text=&act=url */ /obj/item/banhammer/attack(mob/M, mob/user) - if(user.zone_selected == BODY_ZONE_HEAD) + if(user.is_zone_selected(BODY_ZONE_HEAD, precise_only = FALSE)) M.visible_message("[user] are stroking the head of [M] with a bangammer", "[user] are stroking the head with a bangammer", "you hear a bangammer stroking a head"); else M.visible_message("[M] has been banned FOR NO REISIN by [user]", "You have been banned FOR NO REISIN by [user]", "you hear a banhammer banning someone") @@ -814,7 +814,7 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301 user.do_attack_animation(M) var/slap_volume = 50 - if(user.zone_selected == BODY_ZONE_HEAD || user.zone_selected == BODY_ZONE_PRECISE_MOUTH) + if(user.is_zone_selected(BODY_ZONE_HEAD, precise_only = TRUE) || user.is_zone_selected(BODY_ZONE_PRECISE_MOUTH, simplified_probability = 50)) user.visible_message("[user] slaps [M] in the face!", "You slap [M] in the face!", "You hear a slap.") diff --git a/code/game/objects/structures/watercloset.dm b/code/game/objects/structures/watercloset.dm index fb4d5e1c3285e..719d3d625af9d 100644 --- a/code/game/objects/structures/watercloset.dm +++ b/code/game/objects/structures/watercloset.dm @@ -260,10 +260,7 @@ if(busy) to_chat(user, "Someone's already washing here.") return - var/selected_area = parse_zone(user.zone_selected) - var/washing_face = 0 - if(selected_area in list(BODY_ZONE_HEAD, BODY_ZONE_PRECISE_MOUTH, BODY_ZONE_PRECISE_EYES)) - washing_face = 1 + var/washing_face = user.is_zone_selected(BODY_ZONE_HEAD) user.visible_message("[user] starts washing [user.p_their()] [washing_face ? "face" : "hands"]...", \ "You start washing your [washing_face ? "face" : "hands"]...") busy = TRUE diff --git a/code/modules/antagonists/abductor/equipment/abduction_surgery.dm b/code/modules/antagonists/abductor/equipment/abduction_surgery.dm index 82c06c1524f23..6e7e39f53412d 100644 --- a/code/modules/antagonists/abductor/equipment/abduction_surgery.dm +++ b/code/modules/antagonists/abductor/equipment/abduction_surgery.dm @@ -4,7 +4,7 @@ possible_locs = list(BODY_ZONE_CHEST) ignore_clothes = 1 -/datum/surgery/organ_extraction/can_start(mob/user, mob/living/carbon/target) +/datum/surgery/organ_extraction/can_start(mob/user, mob/living/carbon/target, target_zone) if(!ishuman(user)) return 0 var/mob/living/carbon/human/H = user @@ -22,21 +22,21 @@ var/obj/item/organ/IC = null var/list/organ_types = list(/obj/item/organ/heart) -/datum/surgery_step/extract_organ/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) +/datum/surgery_step/extract_organ/preop(mob/user, mob/living/carbon/target, obj/item/tool, datum/surgery/surgery) for(var/atom/A in target.internal_organs) if(A.type in organ_types) IC = A break user.visible_message("[user] starts to remove [target]'s organs.", "You start to remove [target]'s organs...") -/datum/surgery_step/extract_organ/success(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) +/datum/surgery_step/extract_organ/success(mob/user, mob/living/carbon/target, obj/item/tool, datum/surgery/surgery) if(IC) - user.visible_message("[user] pulls [IC] out of [target]'s [target_zone]!", "You pull [IC] out of [target]'s [target_zone].") + user.visible_message("[user] pulls [IC] out of [target]'s [surgery.location]!", "You pull [IC] out of [target]'s [surgery.location].") user.put_in_hands(IC) IC.Remove(target) return 1 else - to_chat(user, "You don't find anything in [target]'s [target_zone]!") + to_chat(user, "You don't find anything in [target]'s [surgery.location]!") return 1 /datum/surgery_step/gland_insert @@ -44,10 +44,10 @@ implements = list(/obj/item/organ/heart/gland = 100) time = 32 -/datum/surgery_step/gland_insert/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) +/datum/surgery_step/gland_insert/preop(mob/user, mob/living/carbon/target, obj/item/tool, datum/surgery/surgery) user.visible_message("[user] starts to insert [tool] into [target].", "You start to insert [tool] into [target]...") -/datum/surgery_step/gland_insert/success(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) +/datum/surgery_step/gland_insert/success(mob/user, mob/living/carbon/target, obj/item/tool, datum/surgery/surgery) user.visible_message("[user] inserts [tool] into [target].", "You insert [tool] into [target].") user.temporarilyRemoveItemFromInventory(tool, TRUE) var/obj/item/organ/heart/gland/gland = tool diff --git a/code/modules/antagonists/wizard/equipment/artefact.dm b/code/modules/antagonists/wizard/equipment/artefact.dm index cdb3511ea8235..22b5341c1ef41 100644 --- a/code/modules/antagonists/wizard/equipment/artefact.dm +++ b/code/modules/antagonists/wizard/equipment/artefact.dm @@ -331,7 +331,7 @@ target.adjust_bodytemperature(50) GiveHint(target) else if(is_pointed(I)) - to_chat(target, "You feel a stabbing pain in [parse_zone(user.zone_selected)]!") + to_chat(target, "You feel a stabbing pain in [parse_zone(user.get_combat_bodyzone(target))]!") target.Paralyze(40) GiveHint(target) else if(istype(I, /obj/item/bikehorn)) @@ -359,7 +359,15 @@ target = input(user, "Select your victim!", "Voodoo") as null|anything in sort_names(possible) return - if(user.zone_selected == BODY_ZONE_CHEST) + var/datum/task/select_zone_task = user.select_bodyzone(user, TRUE, BODYZONE_STYLE_DEFAULT) + select_zone_task.continue_with(CALLBACK(PROC_REF(perform_voodoo), user)) + +/obj/item/voodoo/proc/perform_voodoo(mob/user, zone_selected) + if (!can_interact(user)) + to_chat(user, "You are too far away!") + return + + if(zone_selected == BODY_ZONE_CHEST) if(voodoo_link) target = null voodoo_link.forceMove(drop_location()) @@ -369,7 +377,7 @@ return if(target && cooldown < world.time) - switch(user.zone_selected) + switch(zone_selected) if(BODY_ZONE_PRECISE_MOUTH) var/wgw = stripped_input(user, "What would you like the victim to say", "Voodoo") target.say(wgw, forced = "voodoo doll") diff --git a/code/modules/client/preferences/entries/player/zone_selection.dm b/code/modules/client/preferences/entries/player/zone_selection.dm new file mode 100644 index 0000000000000..d9b64e3c77650 --- /dev/null +++ b/code/modules/client/preferences/entries/player/zone_selection.dm @@ -0,0 +1,28 @@ +/// The preference for zone selection +/datum/preference/choiced/zone_select + db_key = "zone_select" + preference_type = PREFERENCE_PLAYER + category = PREFERENCE_CATEGORY_GAME_PREFERENCES + +/datum/preference/choiced/zone_select/init_possible_values() + return list( + PREFERENCE_BODYZONE_SIMPLIFIED, + PREFERENCE_BODYZONE_INTENT, + ) + +/datum/preference/choiced/zone_select/create_default_value() + // For the time being the default will be the standard intent system + // until we have had some time to play with the new simplified bodyzone + // system and determine if its good or not. If playing with it is acceptable + // and more intuative than bodyzones, switch the default to simplified. + return PREFERENCE_BODYZONE_INTENT + +/datum/preference/choiced/zone_select/apply_to_client(client/client, value) + var/atom/movable/screen/zone_sel/selector = client.mob?.hud_used?.zone_select + if (!selector) + return + // Reset zone selected to a sane value + if (value == PREFERENCE_BODYZONE_SIMPLIFIED) + selector.set_selected_zone(BODY_GROUP_CHEST_HEAD, client.mob) + else + selector.set_selected_zone(BODY_ZONE_CHEST, client.mob) diff --git a/code/modules/client/preferences/middleware/keybindings.dm b/code/modules/client/preferences/middleware/keybindings.dm index 4c06684595967..d3ee0f2ece72b 100644 --- a/code/modules/client/preferences/middleware/keybindings.dm +++ b/code/modules/client/preferences/middleware/keybindings.dm @@ -86,9 +86,12 @@ if (!(keybinding.category in keybindings)) keybindings[keybinding.category] = list() + var/datum/preference/required_type = keybinding.required_pref_type keybindings[keybinding.category][keybinding.name] = list( "name" = keybinding.full_name, "description" = keybinding.description, + "pref_key" = required_type && initial(required_type.db_key), + "pref_value" = keybinding.required_pref_value, ) return keybindings diff --git a/code/modules/clothing/neck/_neck.dm b/code/modules/clothing/neck/_neck.dm index f2480404a187b..31616d8295e27 100644 --- a/code/modules/clothing/neck/_neck.dm +++ b/code/modules/clothing/neck/_neck.dm @@ -63,8 +63,6 @@ /obj/item/clothing/neck/stethoscope/attack(mob/living/carbon/human/M, mob/living/user) if(ishuman(M) && isliving(user)) if(user.a_intent == INTENT_HELP) - var/body_part = parse_zone(user.zone_selected) - var/heart_strength = "no" var/lung_strength = "no" @@ -84,8 +82,9 @@ if(M.stat == DEAD && heart && world.time - M.timeofdeath < DEFIB_TIME_LIMIT * 10) heart_strength = "a faint, fluttery" - var/diagnosis = (body_part == BODY_ZONE_CHEST ? "You hear [heart_strength] pulse and [lung_strength] respiration." : "You faintly hear [heart_strength] pulse.") - user.visible_message("[user] places [src] against [M]'s [body_part] and listens attentively.", "You place [src] against [M]'s [body_part]. [diagnosis]") + var/diagnosis = (user.is_zone_selected(BODY_ZONE_CHEST) ? "You hear [heart_strength] pulse and [lung_strength] respiration." : "You faintly hear [heart_strength] pulse.") + var/bodypart = parse_zone(user.is_zone_selected(BODY_ZONE_CHEST) ? BODY_ZONE_CHEST : user.get_combat_bodyzone(M)) + user.visible_message("[user] places [src] against [M]'s [bodypart] and listens attentively.", "You place [src] against [M]'s [bodypart]. [diagnosis]") return return ..(M,user) diff --git a/code/modules/food_and_drinks/drinks/drinks.dm b/code/modules/food_and_drinks/drinks/drinks.dm index fd17c0fd9bb0a..200d71a99f30d 100644 --- a/code/modules/food_and_drinks/drinks/drinks.dm +++ b/code/modules/food_and_drinks/drinks/drinks.dm @@ -34,7 +34,7 @@ return 0 var/gulp_amount = gulp_size if(M == user) - if(user.zone_selected == BODY_ZONE_PRECISE_MOUTH && !beingChugged) + if(user.is_zone_selected(BODY_ZONE_PRECISE_MOUTH, precise_only = TRUE) && !beingChugged) beingChugged = TRUE user.visible_message("[user] starts chugging [src].", \ "You start chugging [src].") @@ -500,7 +500,7 @@ return TOXLOSS /obj/item/reagent_containers/food/drinks/soda_cans/attack(mob/M, mob/user) - if(M == user && !src.reagents.total_volume && user.a_intent == INTENT_HARM && user.zone_selected == BODY_ZONE_HEAD) + if(M == user && !src.reagents.total_volume && user.a_intent == INTENT_HARM && user.is_zone_selected(BODY_ZONE_HEAD)) user.visible_message("[user] crushes the can of [src] on [user.p_their()] forehead!", "You crush the can of [src] on your forehead.") playsound(user.loc,'sound/weapons/pierce.ogg', rand(10,50), 1) var/obj/item/trash/can/crushed_can = new /obj/item/trash/can(user.loc) diff --git a/code/modules/food_and_drinks/drinks/drinks/bottle.dm b/code/modules/food_and_drinks/drinks/drinks/bottle.dm index ee7e4f3ee1c36..6cd70bf1f8356 100644 --- a/code/modules/food_and_drinks/drinks/drinks/bottle.dm +++ b/code/modules/food_and_drinks/drinks/drinks/bottle.dm @@ -60,20 +60,21 @@ force = 15 //Smashing bottles over someoen's head hurts. - var/obj/item/bodypart/affecting = user.zone_selected //Find what the player is aiming at - var/armor_block = 0 //Get the target's armor values for normal attack damage. var/armor_duration = 0 //The more force the bottle has, the longer the duration. + // Preference for smashing on the head with this item due to it dealing a stun effect on top + var/target_zone = user.is_zone_selected(BODY_ZONE_HEAD) ? BODY_ZONE_HEAD : user.get_combat_bodyzone(target) + //Calculating duration and calculating damage. if(ishuman(target)) var/mob/living/carbon/human/H = target var/headarmor = 0 // Target's head armor - armor_block = H.run_armor_check(affecting, MELEE,"","",armour_penetration) // For normal attack damage + armor_block = H.run_armor_check(target_zone, MELEE,"","",armour_penetration) // For normal attack damage //If they have a hat/helmet and the user is targeting their head. - if(istype(H.head, /obj/item/clothing/head) && affecting == BODY_ZONE_HEAD) + if(istype(H.head, /obj/item/clothing/head) && target_zone == BODY_ZONE_HEAD) headarmor = H.head.armor.melee else headarmor = 0 @@ -83,17 +84,17 @@ else //Only humans can have armor, right? - armor_block = target.run_armor_check(affecting, MELEE) - if(affecting == BODY_ZONE_HEAD) + armor_block = target.run_armor_check(target_zone, MELEE) + if(target_zone == BODY_ZONE_HEAD) armor_duration = bottle_knockdown_duration + force //Apply the damage! armor_block = min(90,armor_block) - target.apply_damage(force, BRUTE, affecting, armor_block) + target.apply_damage(force, BRUTE, target_zone, armor_block) // You are going to knock someone down for longer if they are not wearing a helmet. var/head_attack_message = "" - if(affecting == BODY_ZONE_HEAD && istype(target, /mob/living/carbon/)) + if(target_zone == BODY_ZONE_HEAD && istype(target, /mob/living/carbon/)) head_attack_message = " on the head" //Knock down the target for the duration that we calculated and divide it by 5. if(armor_duration) diff --git a/code/modules/holoparasite/holoparasite_damage.dm b/code/modules/holoparasite/holoparasite_damage.dm index 6276c0d52ce88..f23b52f8e305a 100644 --- a/code/modules/holoparasite/holoparasite_damage.dm +++ b/code/modules/holoparasite/holoparasite_damage.dm @@ -143,7 +143,7 @@ /** * Holoparasites are NOT physically soft like flesh. */ -/mob/living/simple_animal/hostile/holoparasite/can_inject() +/mob/living/simple_animal/hostile/holoparasite/can_inject(mob/user, error_msg, target_zone, penetrate_thick = FALSE) return FALSE /mob/living/simple_animal/hostile/holoparasite/ex_act(severity, target) diff --git a/code/modules/keybindings/bindings_client.dm b/code/modules/keybindings/bindings_client.dm index 94f56f9fe0b24..a35332985088a 100644 --- a/code/modules/keybindings/bindings_client.dm +++ b/code/modules/keybindings/bindings_client.dm @@ -27,6 +27,8 @@ GLOBAL_LIST_INIT(valid_keys, list( // AZERTY support "&" = 1, "É" = 1, "\"" = 1, "(" = 1, "È" = 1, "_" = 1, "Ç" = 1, "À" = 1, ")" = 1, "*" = 1, "$" = 1, "!" = 1, ":" = 1, "²" = 1, "Ù" = 1, "é" = 1, "è" = 1, "ç" = 1, "à" = 1, "ù" = 1, + // Scrolling support + "ScrollUp" = 1, "ScrollDown" = 1, )) /proc/input_sanity_check(client/C, key) diff --git a/code/modules/mob/living/carbon/alien/alien_defense.dm b/code/modules/mob/living/carbon/alien/alien_defense.dm index a8c0b3f87cbe4..0196a8b2eeed1 100644 --- a/code/modules/mob/living/carbon/alien/alien_defense.dm +++ b/code/modules/mob/living/carbon/alien/alien_defense.dm @@ -53,7 +53,7 @@ In all, this is a lot like the monkey code. /N if(!..()) return if(stat != DEAD) - var/obj/item/bodypart/affecting = get_bodypart(ran_zone(M.zone_selected)) + var/obj/item/bodypart/affecting = get_bodypart(ran_zone(M.get_combat_bodyzone(src))) apply_damage(rand(3), BRUTE, affecting) /mob/living/carbon/alien/attack_hand(mob/living/carbon/human/M) @@ -68,7 +68,7 @@ In all, this is a lot like the monkey code. /N playsound(loc, "punch", 25, 1, -1) visible_message("[M] punches [src]!", \ "[M] punches you!", null, COMBAT_MESSAGE_RANGE) - var/obj/item/bodypart/affecting = get_bodypart(ran_zone(M.zone_selected)) + var/obj/item/bodypart/affecting = get_bodypart(ran_zone(M.get_combat_bodyzone(src))) apply_damage(M.dna.species.punchdamage, BRUTE, affecting) log_combat(M, src, "attacked") M.do_attack_animation(src, ATTACK_EFFECT_PUNCH) diff --git a/code/modules/mob/living/carbon/alien/humanoid/queen.dm b/code/modules/mob/living/carbon/alien/humanoid/queen.dm index cbb36665fc112..db3d5e6dc2cb3 100644 --- a/code/modules/mob/living/carbon/alien/humanoid/queen.dm +++ b/code/modules/mob/living/carbon/alien/humanoid/queen.dm @@ -15,7 +15,7 @@ var/alt_inhands_file = 'icons/mob/alienqueen.dmi' var/game_end_timer -/mob/living/carbon/alien/humanoid/royal/can_inject() +/mob/living/carbon/alien/humanoid/royal/can_inject(mob/user, error_msg, target_zone, penetrate_thick = FALSE) return FALSE /mob/living/carbon/alien/humanoid/royal/queen/proc/maidify() diff --git a/code/modules/mob/living/carbon/alien/larva/larva_defense.dm b/code/modules/mob/living/carbon/alien/larva/larva_defense.dm index 425501773550f..52db20e63a1db 100644 --- a/code/modules/mob/living/carbon/alien/larva/larva_defense.dm +++ b/code/modules/mob/living/carbon/alien/larva/larva_defense.dm @@ -6,7 +6,7 @@ log_combat(M, src, "attacked") visible_message("[M] kicks [src]!", \ "[M] kicks you!", null, COMBAT_MESSAGE_RANGE) - var/obj/item/bodypart/affecting = get_bodypart(ran_zone(M.zone_selected)) + var/obj/item/bodypart/affecting = get_bodypart(ran_zone(M.get_combat_bodyzone(src))) apply_damage(M.dna.species.punchdamage, BRUTE, affecting) /mob/living/carbon/alien/larva/attack_hulk(mob/living/carbon/human/user, does_attack_animation = 0) diff --git a/code/modules/mob/living/carbon/carbon_defense.dm b/code/modules/mob/living/carbon/carbon_defense.dm index 0876340f737d9..e5a468199338b 100644 --- a/code/modules/mob/living/carbon/carbon_defense.dm +++ b/code/modules/mob/living/carbon/carbon_defense.dm @@ -72,7 +72,7 @@ /mob/living/carbon/attacked_by(obj/item/I, mob/living/user) var/obj/item/bodypart/affecting - affecting = get_bodypart(check_zone(user.zone_selected)) + affecting = get_bodypart(check_zone(user.get_combat_bodyzone(src))) if(!affecting) //missing limb? we select the first bodypart (you can never have zero, because of chest) affecting = bodyparts[1] SEND_SIGNAL(I, COMSIG_ITEM_ATTACK_ZONE, src, user, affecting) @@ -274,7 +274,7 @@ return M.visible_message("[M] shakes [src] trying to get [p_them()] up!", \ "You shake [src] trying to get [p_them()] up!") - else if(M.zone_selected == BODY_ZONE_CHEST) + else if(M.is_zone_selected(BODY_ZONE_CHEST)) M.visible_message("[M] hugs [src] to make [p_them()] feel better!", \ "You hug [src] to make [p_them()] feel better!") @@ -305,19 +305,19 @@ SEND_SIGNAL(src, COMSIG_ADD_MOOD_EVENT, "friendly_hug", /datum/mood_event/betterhug, M) for(var/datum/brain_trauma/trauma in M.get_traumas()) trauma.on_hug(M, src) - else if(M.zone_selected == BODY_ZONE_HEAD) + else if(M.is_zone_selected(BODY_ZONE_HEAD)) M.visible_message("[M] pats [src] on the head.", \ "You pat [src] on the head.") SEND_SIGNAL(src, COMSIG_ADD_MOOD_EVENT, "headpat", /datum/mood_event/headpat, M) for(var/datum/brain_trauma/trauma in M.get_traumas()) trauma.on_hug(M, src) - else if((M.zone_selected == BODY_ZONE_L_ARM) || (M.zone_selected == BODY_ZONE_R_ARM)) - if(!get_bodypart(check_zone(M.zone_selected))) - to_chat(M, "[src] does not have a [M.zone_selected == BODY_ZONE_L_ARM ? "left" : "right"] arm!") + else if((M.is_zone_selected(BODY_ZONE_L_ARM)) || (M.is_zone_selected(BODY_ZONE_R_ARM))) + if(!get_bodypart(check_zone(M.get_combat_bodyzone(src)))) + to_chat(M, "[src] does not have a [M.get_combat_bodyzone(src) == BODY_ZONE_L_ARM ? "left" : "right"] arm!") else M.visible_message("[M] shakes [src]'s hand.", \ "You shake [src]'s hand.") - else if(M.zone_selected == BODY_ZONE_PRECISE_GROIN) + else if(M.is_zone_selected(BODY_ZONE_PRECISE_GROIN, precise_only = TRUE)) to_chat(M, "ERP is not allowed on this server!") AdjustStun(-60) AdjustKnockdown(-60) diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm index b37fec36b4ed5..c6707b08b9166 100644 --- a/code/modules/mob/living/carbon/human/human.dm +++ b/code/modules/mob/living/carbon/human/human.dm @@ -409,7 +409,7 @@ if(!target_zone) if(user) - target_zone = user.zone_selected + target_zone = user.get_combat_bodyzone(src, FALSE, BODYZONE_CONTEXT_INJECTION) else target_zone = BODY_ZONE_CHEST // If targeting the head, see if the head item is thin enough. @@ -874,7 +874,7 @@ . = ..() if(ishuman(over)) var/mob/living/carbon/human/T = over // curbstomp, ported from PP with modifications - if(!src.is_busy && (src.zone_selected == BODY_ZONE_HEAD || src.zone_selected == BODY_ZONE_PRECISE_GROIN) && get_turf(src) == get_turf(T) && !(T.mobility_flags & MOBILITY_STAND) && src.a_intent != INTENT_HELP && !HAS_TRAIT(src, TRAIT_PACIFISM)) //all the stars align, time to curbstomp + if(!src.is_busy && (src.is_zone_selected(BODY_ZONE_HEAD) || src.is_zone_selected(BODY_ZONE_PRECISE_GROIN)) && get_turf(src) == get_turf(T) && !(T.mobility_flags & MOBILITY_STAND) && src.a_intent != INTENT_HELP && !HAS_TRAIT(src, TRAIT_PACIFISM)) //all the stars align, time to curbstomp src.is_busy = TRUE if (!do_after(src, 2.5 SECONDS, T) || get_turf(src) != get_turf(T) || (T.mobility_flags & MOBILITY_STAND) || src.a_intent == INTENT_HELP || src == T) //wait 30ds and make sure the stars still align (Body zone check removed after PR #958) @@ -883,7 +883,7 @@ T.Stun(6) - if(src.zone_selected == BODY_ZONE_HEAD) //curbstomp specific code + if(src.is_zone_selected(BODY_ZONE_HEAD)) //curbstomp specific code var/increment = (T.lying_angle/90)-2 setDir(increment > 0 ? WEST : EAST) @@ -907,7 +907,8 @@ log_combat(src, T, "curbstomped") - else if(src.zone_selected == BODY_ZONE_PRECISE_GROIN) //groinkick specific code + // Will be legs only on simplified mode since groin is legs + else if(src.is_zone_selected(BODY_ZONE_PRECISE_GROIN)) //groinkick specific code var/increment = (T.lying_angle/90)-2 setDir(increment > 0 ? WEST : EAST) diff --git a/code/modules/mob/living/carbon/human/human_defense.dm b/code/modules/mob/living/carbon/human/human_defense.dm index 4359e07bd7794..f47e90a69db18 100644 --- a/code/modules/mob/living/carbon/human/human_defense.dm +++ b/code/modules/mob/living/carbon/human/human_defense.dm @@ -176,10 +176,10 @@ var/obj/item/bodypart/affecting if(user == src) - affecting = get_bodypart(check_zone(user.zone_selected)) //stabbing yourself always hits the right target + affecting = get_bodypart(check_zone(user.get_combat_bodyzone(src))) //stabbing yourself always hits the right target else - affecting = get_bodypart(ran_zone(user.zone_selected)) - var/target_area = parse_zone(check_zone(user.zone_selected)) //our intended target + affecting = get_bodypart(ran_zone(user.get_combat_bodyzone(src))) + var/target_area = parse_zone(check_zone(user.get_combat_bodyzone(src))) //our intended target if(affecting) if(I.force && I.damtype != STAMINA && (!IS_ORGANIC_LIMB(affecting))) // Bodpart_robotic sparks when hit, but only when it does real damage if(I.force >= 5) @@ -206,7 +206,7 @@ var/message = "[user] has [hulk_verb]ed [src]!" visible_message("[message]", \ "[message]") - var/obj/item/bodypart/affecting = get_bodypart(ran_zone(user.zone_selected)) + var/obj/item/bodypart/affecting = get_bodypart(ran_zone(user.get_combat_bodyzone(src))) if(!affecting) affecting = get_bodypart(BODY_ZONE_CHEST) var/armor_block = run_armor_check(affecting, MELEE,"","",10) @@ -257,7 +257,7 @@ if(M.a_intent == INTENT_HARM) if (w_uniform) w_uniform.add_fingerprint(M) - var/obj/item/bodypart/affecting = get_bodypart(ran_zone(M.zone_selected)) + var/obj/item/bodypart/affecting = get_bodypart(ran_zone(M.get_combat_bodyzone(src))) if(!affecting) affecting = get_bodypart(BODY_ZONE_CHEST) var/armor_block = run_armor_check(affecting, MELEE,"","",10) @@ -266,7 +266,7 @@ visible_message("[M] slashes at [src]!", \ "[M] slashes at you!") log_combat(M, src, "attacked") - if(!dismembering_strike(M, M.zone_selected)) //Dismemberment successful + if(!dismembering_strike(M, M.get_combat_bodyzone(src))) //Dismemberment successful return 1 apply_damage(20, BRUTE, affecting, armor_block) @@ -274,7 +274,7 @@ playsound(loc, 'sound/weapons/pierce.ogg', 25, 1, -1) Knockdown(20) log_combat(M, src, "tackled") - var/obj/item/bodypart/affecting = get_bodypart(ran_zone(M.zone_selected)) + var/obj/item/bodypart/affecting = get_bodypart(ran_zone(M.get_combat_bodyzone(src))) if(!affecting) affecting = get_bodypart(BODY_ZONE_CHEST) var/armor_block = run_armor_check(affecting, MELEE,"","",10) @@ -291,7 +291,7 @@ return 0 if(stat != DEAD) L.amount_grown = min(L.amount_grown + damage, L.max_grown) - var/obj/item/bodypart/affecting = get_bodypart(ran_zone(L.zone_selected)) + var/obj/item/bodypart/affecting = get_bodypart(ran_zone(L.get_combat_bodyzone(src))) if(!affecting) affecting = get_bodypart(BODY_ZONE_CHEST) var/armor_block = run_armor_check(affecting, MELEE) diff --git a/code/modules/mob/living/carbon/human/species.dm b/code/modules/mob/living/carbon/human/species.dm index 8a08bf82c6f06..dda8929df62de 100644 --- a/code/modules/mob/living/carbon/human/species.dm +++ b/code/modules/mob/living/carbon/human/species.dm @@ -1526,7 +1526,7 @@ GLOBAL_LIST_EMPTY(features_by_species) return TRUE else //Steal them shoes - if(!(target.mobility_flags & MOBILITY_STAND) && (user.zone_selected == BODY_ZONE_L_LEG || user.zone_selected == BODY_ZONE_R_LEG) && user.a_intent == INTENT_GRAB && target.shoes) + if(!(target.mobility_flags & MOBILITY_STAND) && (user.is_zone_selected(BODY_ZONE_L_LEG) || user.is_zone_selected(BODY_ZONE_R_LEG)) && user.a_intent == INTENT_GRAB && target.shoes) if(HAS_TRAIT(target.shoes, TRAIT_NODROP)) target.grabbedby(user) return TRUE @@ -1569,7 +1569,7 @@ GLOBAL_LIST_EMPTY(features_by_species) var/damage = user.dna.species.punchdamage - var/obj/item/bodypart/affecting = target.get_bodypart(ran_zone(user.zone_selected)) + var/obj/item/bodypart/affecting = target.get_bodypart(ran_zone(user.get_combat_bodyzone(target))) if(!damage || !affecting)//future-proofing for species that have 0 damage/weird cases where no zone is targeted playsound(target.loc, user.dna.species.miss_sound, 25, 1, -1) @@ -1626,7 +1626,7 @@ GLOBAL_LIST_EMPTY(features_by_species) if(target.w_uniform) target.w_uniform.add_fingerprint(user) - SEND_SIGNAL(target, COMSIG_HUMAN_DISARM_HIT, user, user.zone_selected) + SEND_SIGNAL(target, COMSIG_HUMAN_DISARM_HIT, user, user.get_combat_bodyzone(target)) var/turf/target_oldturf = target.loc var/shove_dir = get_dir(user.loc, target_oldturf) diff --git a/code/modules/mob/living/carbon/human/species_types/pumpkin_man.dm b/code/modules/mob/living/carbon/human/species_types/pumpkin_man.dm index 85a4357f7804d..ec390b8df420b 100644 --- a/code/modules/mob/living/carbon/human/species_types/pumpkin_man.dm +++ b/code/modules/mob/living/carbon/human/species_types/pumpkin_man.dm @@ -61,7 +61,7 @@ //Check if the item is sharp - give owner a random face if applicable var/mob/living/carbon/human/M = _source var/obj/item/bodypart/head/pumpkin_man/head = M.get_bodypart(BODY_ZONE_HEAD) - if(_item.is_sharp() && head?.item_flags & ISCARVABLE && _user.a_intent == INTENT_HELP && _user.zone_selected == BODY_ZONE_HEAD) + if(_item.is_sharp() && head?.item_flags & ISCARVABLE && _user.a_intent == INTENT_HELP && _user.is_zone_selected(BODY_ZONE_HEAD)) to_chat(_user, "You begin to carve a face into [_source]...") //Do after for *flourish* if(do_after(_user, 3 SECONDS)) diff --git a/code/modules/mob/living/carbon/monkey/monkey_defense.dm b/code/modules/mob/living/carbon/monkey/monkey_defense.dm index 1dd266a6ebb7b..9021281aaab82 100644 --- a/code/modules/mob/living/carbon/monkey/monkey_defense.dm +++ b/code/modules/mob/living/carbon/monkey/monkey_defense.dm @@ -22,7 +22,7 @@ var/damage = rand(1, 3) if(stat != DEAD) L.amount_grown = min(L.amount_grown + damage, L.max_grown) - var/obj/item/bodypart/affecting = get_bodypart(ran_zone(L.zone_selected)) + var/obj/item/bodypart/affecting = get_bodypart(ran_zone(L.get_combat_bodyzone(src))) if(!affecting) affecting = get_bodypart(BODY_ZONE_CHEST) apply_damage(damage, BRUTE, affecting) @@ -42,7 +42,7 @@ "[M] punches you!", null, COMBAT_MESSAGE_RANGE) playsound(loc, "punch", 25, 1, -1) var/damage = M.dna.species.punchdamage - var/obj/item/bodypart/affecting = get_bodypart(check_zone(M.zone_selected)) + var/obj/item/bodypart/affecting = get_bodypart(check_zone(M.get_combat_bodyzone(src))) if(!affecting) affecting = get_bodypart(BODY_ZONE_CHEST) apply_damage(damage, BRUTE, affecting) @@ -73,7 +73,7 @@ visible_message("[M] slashes [name]!", \ "[M] slashes you!", null, COMBAT_MESSAGE_RANGE) - var/obj/item/bodypart/affecting = get_bodypart(ran_zone(M.zone_selected)) + var/obj/item/bodypart/affecting = get_bodypart(ran_zone(M.get_combat_bodyzone(src))) log_combat(M, src, "attacked") if(!affecting) affecting = get_bodypart(BODY_ZONE_CHEST) diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm index 3c1bf8db0dd3a..d331b0d850c97 100644 --- a/code/modules/mob/living/living.dm +++ b/code/modules/mob/living/living.dm @@ -318,14 +318,14 @@ log_combat(src, M, "grabbed", addition="passive grab") if(!supress_message && !(iscarbon(AM) && HAS_TRAIT(src, TRAIT_STRONG_GRABBER))) //Everything in this if statement handles chat messages for grabbing var/mob/living/L = M - if (L.getorgan(/obj/item/organ/tail) && zone_selected == BODY_ZONE_PRECISE_GROIN) //Does the target have a tail? + if (L.getorgan(/obj/item/organ/tail) && (is_zone_selected(BODY_ZONE_PRECISE_GROIN, precise_only = TRUE) || is_group_selected(BODY_GROUP_LEGS))) //Does the target have a tail? M.visible_message("[src] grabs [L] by [L.p_their()] tail!",\ " [src] grabs you by the tail!", null, null, src) //Message sent to area, Message sent to grabbee to_chat(src, "You grab [L] by [L.p_their()] tail!") //Message sent to grabber else - M.visible_message("[src] grabs [M] [(zone_selected == BODY_ZONE_L_ARM || zone_selected == BODY_ZONE_R_ARM)? "by their hands":"passively"]!", \ - "[src] grabs you [(zone_selected == BODY_ZONE_L_ARM || zone_selected == BODY_ZONE_R_ARM)? "by your hands":"passively"]!", null, null, src) //Message sent to area, Message sent to grabbee - to_chat(src, "You grab [M] [(zone_selected == BODY_ZONE_L_ARM|| zone_selected == BODY_ZONE_R_ARM)? "by their hands":"passively"]!") //Message sent to grabber + M.visible_message("[src] grabs [M] [(is_zone_selected(BODY_ZONE_L_ARM) || is_zone_selected(BODY_ZONE_R_ARM))? "by their hands":"passively"]!", \ + "[src] grabs you [(is_zone_selected(BODY_ZONE_L_ARM) || is_zone_selected(BODY_ZONE_R_ARM))? "by your hands":"passively"]!", null, null, src) //Message sent to area, Message sent to grabbee + to_chat(src, "You grab [M] [(is_zone_selected(BODY_ZONE_L_ARM) || is_zone_selected(BODY_ZONE_R_ARM))? "by their hands":"passively"]!") //Message sent to grabber if(!iscarbon(src)) M.LAssailant = null else @@ -543,7 +543,7 @@ return FALSE // Living mobs use can_inject() to make sure that the mob is not syringe-proof in general. -/mob/living/proc/can_inject() +/mob/living/proc/can_inject(mob/user, error_msg, target_zone, penetrate_thick = FALSE) return TRUE /mob/living/is_injectable(mob/user, allowmobs = TRUE) diff --git a/code/modules/mob/living/silicon/silicon.dm b/code/modules/mob/living/silicon/silicon.dm index 4ed9a04c30f0d..8c9f416283761 100644 --- a/code/modules/mob/living/silicon/silicon.dm +++ b/code/modules/mob/living/silicon/silicon.dm @@ -165,7 +165,7 @@ for(var/key in alarm_types_clear) alarm_types_clear[key] = 0 -/mob/living/silicon/can_inject(mob/user, error_msg) +/mob/living/silicon/can_inject(mob/user, error_msg, target_zone, penetrate_thick = FALSE) if(error_msg) to_chat(user, "[p_their(TRUE)] outer shell is too tough.") return FALSE diff --git a/code/modules/mob/mob_defines.dm b/code/modules/mob/mob_defines.dm index afdc1eab41c18..0b260b6a37af0 100644 --- a/code/modules/mob/mob_defines.dm +++ b/code/modules/mob/mob_defines.dm @@ -48,7 +48,8 @@ */ /// The zone this mob is currently targeting - var/zone_selected = BODY_ZONE_CHEST + /// Use select_bodyzone and get_combat_bodyzone to get this value + VAR_PRIVATE/zone_selected = BODY_ZONE_CHEST var/computer_id = null var/list/logging = list() diff --git a/code/modules/mob/mob_helpers.dm b/code/modules/mob/mob_helpers.dm index b2d9fdacf98fe..c542890c09a6a 100644 --- a/code/modules/mob/mob_helpers.dm +++ b/code/modules/mob/mob_helpers.dm @@ -608,3 +608,116 @@ return TRUE else if(HAS_TRAIT(src, TRAIT_BARMASTER)) return TRUE + +/** + * Zone selection helpers. + * + * There are 2 ways to get the zone selected, a combat mode + * which determines the zone to target based on what target was + * pressed and a non-combat mode which displays a wheel of options. + */ + +/mob/proc/select_bodyzone(atom/target, precise = FALSE, style = BODYZONE_STYLE_DEFAULT, override_zones = null) + DECLARE_ASYNC + // Get the selected bodyzone + if (client?.prefs.read_player_preference(/datum/preference/choiced/zone_select) == PREFERENCE_BODYZONE_SIMPLIFIED) + switch (style) + if (BODYZONE_STYLE_DEFAULT) + ASYNC_RETURN_TASK(select_bodyzone_from_wheel(target, precise, override_zones = override_zones)) + if (BODYZONE_STYLE_MEDICAL) + var/accurate_health = HAS_TRAIT(src, TRAIT_MEDICAL_HUD) || istype(get_inactive_held_item(), /obj/item/healthanalyzer) + if (!accurate_health && isliving(target)) + to_chat(src, "You could more easilly determine how injured [target] was if you had a medical hud or a health analyser!") + ASYNC_RETURN_TASK(select_bodyzone_from_wheel(target, precise, CALLBACK(GLOBAL_PROC, GLOBAL_PROC_REF(select_bodyzone_limb_health), accurate_health), override_zones)) + // Return the value instantly + if (precise) + ASYNC_RETURN(zone_selected) + ASYNC_RETURN(check_zone(zone_selected)) + +/** + * Get the zone that we probably wanted to target. This depends on the context. + * If we are in an injection context (quick injects like the hyposray) then we will + * target the first part in the group that isn't protected from injections. + * If we are in a combat context, then we will randomly pick legs, head and chest and + * will pick the arm that the target currently has selected. + * Arm target: Disarm target + * Leg target: Reduce mobility of target + * Head/Chest target: Damage/kill target + */ +/mob/proc/get_combat_bodyzone(atom/target = null, precise = FALSE, zone_context = BODYZONE_CONTEXT_COMBAT) + // Just grab whatever bodyzone they were targetting + if (client?.prefs.read_player_preference(/datum/preference/choiced/zone_select) != PREFERENCE_BODYZONE_SIMPLIFIED) + if (!precise) + return check_zone(zone_selected) + return zone_selected || BODY_ZONE_CHEST + // Implicitly determine the bodypart we were trying to target + switch (zone_selected) + if (BODY_GROUP_CHEST_HEAD) + var/head_priority = is_priority_zone(target, BODY_ZONE_HEAD, zone_context) + var/chest_priority = is_priority_zone(target, BODY_ZONE_CHEST, zone_context) + return head_priority == chest_priority ? (prob(70) ? BODY_ZONE_CHEST : BODY_ZONE_HEAD) : (head_priority ? BODY_ZONE_HEAD : BODY_ZONE_CHEST) + if (BODY_GROUP_LEGS) + var/left_priority = is_priority_zone(target, BODY_ZONE_L_LEG, zone_context) + var/right_priority = is_priority_zone(target, BODY_ZONE_R_LEG, zone_context) + return left_priority == right_priority ? pick(BODY_ZONE_L_LEG, BODY_ZONE_R_LEG) : (left_priority ? BODY_ZONE_R_LEG : BODY_ZONE_R_LEG) + if (BODY_GROUP_ARMS) + var/left_priority = is_priority_zone(target, BODY_ZONE_L_ARM, zone_context) + var/right_priority = is_priority_zone(target, BODY_ZONE_R_ARM, zone_context) + return left_priority == right_priority ? pick(BODY_ZONE_L_ARM, BODY_ZONE_R_ARM) : (left_priority ? BODY_ZONE_L_ARM : BODY_ZONE_R_ARM) + +/mob/proc/is_priority_zone(atom/target, target_zone, context) + switch (context) + // Prioritise active hand + if (BODYZONE_CONTEXT_COMBAT) + if (isliving(target)) + var/mob/living/living_target = target + if (living_target.active_hand_index == 1) + return target_zone == BODY_ZONE_L_ARM + else + return target_zone == BODY_ZONE_R_ARM + return FALSE + // Prioritise things that aren't injection proof + if (BODYZONE_CONTEXT_INJECTION) + if (isliving(target)) + var/mob/living/living_target = target + return living_target.can_inject(target_zone = target_zone) + return FALSE + // Prioritise robotic limbs + if (BODYZONE_CONTEXT_ROBOTIC_LIMB_HEALING) + if (isliving(target)) + var/mob/living/living_target = target + var/obj/item/bodypart/limb = living_target.get_bodypart(target_zone) + if (!limb) + return FALSE + return !IS_ORGANIC_LIMB(limb) && (limb.get_damage() > 0) + return FALSE + +/// Does the mob have a specific bodyzone group selected? +/// This will only work if you are using the simplified system (I mean it will work +/// if the mob isn't, but this proc shouldn't be used for that) +/mob/proc/is_group_selected(requested_group) + return zone_selected == requested_group + +/mob/proc/is_zone_selected(requested_zone = BODY_ZONE_CHEST, simplified_probability = 100, precise_only = FALSE, precise = TRUE) + if (client?.prefs.read_player_preference(/datum/preference/choiced/zone_select) != PREFERENCE_BODYZONE_SIMPLIFIED) + return zone_selected == requested_zone || (!precise && check_zone(zone_selected) == requested_zone) + if (precise_only) + return FALSE + // Check if we randomly don't hit the selected zone + if (simplified_probability != 100 && !prob(simplified_probability)) + return FALSE + if (requested_zone == zone_selected) + return TRUE + switch (zone_selected) + if (BODY_GROUP_LEGS) + return requested_zone == BODY_ZONE_L_LEG || requested_zone == BODY_ZONE_R_LEG || requested_zone == BODY_ZONE_PRECISE_L_FOOT || requested_zone == BODY_ZONE_PRECISE_R_FOOT || requested_zone == BODY_ZONE_PRECISE_GROIN + if (BODY_GROUP_ARMS) + return requested_zone == BODY_ZONE_L_ARM || requested_zone == BODY_ZONE_R_ARM || requested_zone == BODY_ZONE_PRECISE_L_HAND || requested_zone == BODY_ZONE_PRECISE_R_HAND + if (BODY_GROUP_CHEST_HEAD) + return requested_zone == BODY_ZONE_CHEST || requested_zone == BODY_ZONE_HEAD || requested_zone == BODY_ZONE_PRECISE_EYES || requested_zone == BODY_ZONE_PRECISE_MOUTH + +/** + * Don't use this + */ +/mob/proc/_set_zone_selected(zone_selected) + src.zone_selected = zone_selected diff --git a/code/modules/mob/mob_movement.dm b/code/modules/mob/mob_movement.dm index fde8a758ef52d..d3085aee11e8d 100644 --- a/code/modules/mob/mob_movement.dm +++ b/code/modules/mob/mob_movement.dm @@ -391,8 +391,10 @@ if(!check_has_body_select()) return + var/atom/movable/screen/zone_sel/selector = mob.hud_used.zone_select + var/next_in_line - switch(mob.zone_selected) + switch(selector.selecting) if(BODY_ZONE_HEAD) next_in_line = BODY_ZONE_PRECISE_EYES if(BODY_ZONE_PRECISE_EYES) @@ -400,7 +402,6 @@ else next_in_line = BODY_ZONE_HEAD - var/atom/movable/screen/zone_sel/selector = mob.hud_used.zone_select selector.set_selected_zone(next_in_line, mob) ///Hidden verb to target the right arm, bound to 4 @@ -469,6 +470,34 @@ var/atom/movable/screen/zone_sel/selector = mob.hud_used.zone_select selector.set_selected_zone(BODY_ZONE_L_LEG, mob) +/client/verb/body_up() + set name = "body-up" + set hidden = 1 + + if(!check_has_body_select()) + return + + var/atom/movable/screen/zone_sel/selector = mob.hud_used.zone_select + switch (selector.selecting) + if (BODY_GROUP_LEGS, BODY_ZONE_L_LEG, BODY_ZONE_R_LEG) + selector.set_selected_zone(BODY_GROUP_ARMS, mob) + if (BODY_GROUP_ARMS, BODY_ZONE_L_ARM, BODY_ZONE_R_ARM) + selector.set_selected_zone(BODY_GROUP_CHEST_HEAD, mob) + +/client/verb/body_down() + set name = "body-down" + set hidden = 1 + + if(!check_has_body_select()) + return + + var/atom/movable/screen/zone_sel/selector = mob.hud_used.zone_select + switch (selector.selecting) + if (BODY_GROUP_CHEST_HEAD, BODY_ZONE_HEAD, BODY_ZONE_CHEST, BODY_ZONE_PRECISE_EYES, BODY_ZONE_PRECISE_MOUTH, BODY_ZONE_PRECISE_GROIN) + selector.set_selected_zone(BODY_GROUP_ARMS, mob) + if (BODY_GROUP_ARMS, BODY_ZONE_L_ARM, BODY_ZONE_R_ARM) + selector.set_selected_zone(BODY_GROUP_LEGS, mob) + ///Verb to toggle the walk or run status /client/verb/toggle_walk_run() set name = "toggle-walk-run" diff --git a/code/modules/paperwork/pen.dm b/code/modules/paperwork/pen.dm index 57362d7b7e01d..a32d674606df5 100644 --- a/code/modules/paperwork/pen.dm +++ b/code/modules/paperwork/pen.dm @@ -312,7 +312,7 @@ return ..() if(!istype(M)) return ..() - if(user.zone_selected != BODY_ZONE_PRECISE_EYES && user.zone_selected != BODY_ZONE_HEAD) + if(!user.is_zone_selected(BODY_ZONE_PRECISE_EYES) && !user.is_zone_selected(BODY_ZONE_HEAD)) return ..() if(HAS_TRAIT(user, TRAIT_PACIFISM)) to_chat(user, "You don't want to harm [M]!") diff --git a/code/modules/projectiles/ammunition/_firing.dm b/code/modules/projectiles/ammunition/_firing.dm index 93082748f1d88..b3f6c491ccfcf 100644 --- a/code/modules/projectiles/ammunition/_firing.dm +++ b/code/modules/projectiles/ammunition/_firing.dm @@ -33,7 +33,7 @@ if (zone_override) BB.def_zone = zone_override else - BB.def_zone = user.zone_selected + BB.def_zone = user.get_combat_bodyzone(target) BB.suppressed = quiet if(reagents && BB.reagents) diff --git a/code/modules/projectiles/gun.dm b/code/modules/projectiles/gun.dm index 73f4eaf938a43..50a7378c30c68 100644 --- a/code/modules/projectiles/gun.dm +++ b/code/modules/projectiles/gun.dm @@ -303,7 +303,7 @@ return if(!ismob(target) || user.a_intent == INTENT_HARM) //melee attack return - if(target == user && user.zone_selected != BODY_ZONE_PRECISE_MOUTH) //so we can't shoot ourselves (unless mouth selected) + if(target == user && user.is_zone_selected(BODY_ZONE_PRECISE_MOUTH)) //so we can't shoot ourselves (unless mouth selected) return if(istype(user))//Check if the user can use the gun, if the user isn't alive(turrets) assume it can. @@ -312,7 +312,15 @@ return if(flag) - if(user.zone_selected == BODY_ZONE_PRECISE_MOUTH) + var/simplified_mode = user.client?.prefs.read_player_preference(/datum/preference/choiced/zone_select) == PREFERENCE_BODYZONE_SIMPLIFIED + var/mob/living/living_target = target + if (!simplified_mode) + if(user.is_zone_selected(BODY_ZONE_PRECISE_MOUTH)) + handle_suicide(user, target, params) + return + // On simplified mode, contextually determine if we want to suicide them + // If the target is ourselves, they are buckled, restrained or lying down then suicide them + else if(user.is_zone_selected(BODY_ZONE_HEAD) && istype(living_target) && (user == target || living_target.restrained() || living_target.buckled || living_target.IsUnconscious())) handle_suicide(user, target, params) return @@ -732,7 +740,7 @@ semicd = TRUE - if(!bypass_timer && (!do_after(user, 12 SECONDS, target) || user.zone_selected != BODY_ZONE_PRECISE_MOUTH)) + if(!bypass_timer && (!do_after(user, 12 SECONDS, target) || !user.is_zone_selected(BODY_ZONE_PRECISE_MOUTH))) if(user) if(user == target) user.visible_message("[user] decided not to shoot.") diff --git a/code/modules/projectiles/guns/ballistic/revolver.dm b/code/modules/projectiles/guns/ballistic/revolver.dm index 727652d49ee27..5c7a0cdc89815 100644 --- a/code/modules/projectiles/guns/ballistic/revolver.dm +++ b/code/modules/projectiles/guns/ballistic/revolver.dm @@ -250,7 +250,7 @@ var/obj/item/ammo_casing/AC = chambered if(AC.fire_casing(user, user)) playsound(user, fire_sound, fire_sound_volume, vary_fire_sound) - var/zone = check_zone(user.zone_selected) + var/zone = check_zone(user.get_combat_bodyzone(target)) var/obj/item/bodypart/affecting = H.get_bodypart(zone) if(zone == BODY_ZONE_HEAD || zone == BODY_ZONE_PRECISE_EYES || zone == BODY_ZONE_PRECISE_MOUTH) shoot_self(user, affecting) diff --git a/code/modules/projectiles/guns/misc/beam_rifle.dm b/code/modules/projectiles/guns/misc/beam_rifle.dm index d81f15dcb0cc2..a87cacd48d9c9 100644 --- a/code/modules/projectiles/guns/misc/beam_rifle.dm +++ b/code/modules/projectiles/guns/misc/beam_rifle.dm @@ -302,7 +302,7 @@ return if(!ismob(target) || user.a_intent == INTENT_HARM) //melee attack return - if(target == user && user.zone_selected != BODY_ZONE_PRECISE_MOUTH) //so we can't shoot ourselves (unless mouth selected) + if(target == user && !user.is_zone_selected(BODY_ZONE_PRECISE_MOUTH)) //so we can't shoot ourselves (unless mouth selected) return if(!passthrough && (aiming_time > aiming_time_fire_threshold)) return diff --git a/code/modules/reagents/reagent_containers/borghydro.dm b/code/modules/reagents/reagent_containers/borghydro.dm index 939fb14f9738f..d6f0ca14de7ec 100644 --- a/code/modules/reagents/reagent_containers/borghydro.dm +++ b/code/modules/reagents/reagent_containers/borghydro.dm @@ -102,7 +102,7 @@ Borg Hypospray return if(!istype(M)) return - if(R.total_volume && M.can_inject(user, 1, user.zone_selected,bypass_protection)) + if(R.total_volume && M.can_inject(user, 1, user.get_combat_bodyzone(M, zone_context = BODYZONE_CONTEXT_INJECTION), bypass_protection)) to_chat(M, "You feel a tiny prick!") to_chat(user, "You inject [M] with the injector.") var/fraction = min(amount_per_transfer_from_this/R.total_volume, 1) diff --git a/code/modules/reagents/reagent_containers/medspray.dm b/code/modules/reagents/reagent_containers/medspray.dm index 7369017018af3..cd10521efbb0a 100644 --- a/code/modules/reagents/reagent_containers/medspray.dm +++ b/code/modules/reagents/reagent_containers/medspray.dm @@ -32,7 +32,7 @@ amount_per_transfer_from_this = initial(amount_per_transfer_from_this) to_chat(user, "You will now apply the medspray's contents in [squirt_mode ? "short bursts":"extended sprays"]. You'll now use [amount_per_transfer_from_this] units per use.") -/obj/item/reagent_containers/medspray/attack(mob/living/carbon/M, mob/user, def_zone) +/obj/item/reagent_containers/medspray/attack(mob/living/carbon/M, mob/user) if(!iscarbon(M)) return @@ -40,7 +40,19 @@ to_chat(user, "[src] is empty!") return - var/obj/item/bodypart/affecting = M.get_bodypart(check_zone(user.zone_selected)) + var/datum/task/target_zone_task = user.select_bodyzone(M, FALSE, BODYZONE_STYLE_MEDICAL) + target_zone_task.continue_with(CALLBACK(src, PROC_REF(do_spray), M, user)) + +/obj/item/reagent_containers/medspray/proc/do_spray(mob/living/carbon/M, mob/user, def_zone) + if (!def_zone) + return + if (!user.can_interact_with(M, TRUE)) + balloon_alert(user, "[M] is too far away!") + return + if (!user.can_interact_with(src, TRUE)) + balloon_alert(user, "[src] is too far away!") + return + var/obj/item/bodypart/affecting = M.get_bodypart(check_zone(def_zone)) if(!affecting) balloon_alert(user, "The limb is missing.") return diff --git a/code/modules/reagents/reagent_containers/patch.dm b/code/modules/reagents/reagent_containers/patch.dm index 75ebe0daa310d..384cd193c165a 100644 --- a/code/modules/reagents/reagent_containers/patch.dm +++ b/code/modules/reagents/reagent_containers/patch.dm @@ -10,17 +10,30 @@ self_delay = 3 SECONDS dissolvable = FALSE -/obj/item/reagent_containers/pill/patch/attack(mob/living/L, mob/user, obj/item/bodypart/affecting) +/obj/item/reagent_containers/pill/patch/attack(mob/living/L, mob/user) if(!ishuman(L)) return ..() - affecting = L.get_bodypart(check_zone(user.zone_selected)) + var/datum/task/select_bodyzone = user.select_bodyzone(L, FALSE, BODYZONE_STYLE_MEDICAL) + select_bodyzone.continue_with(CALLBACK(src, PROC_REF(apply_part), L, user)) + return TRUE + +/obj/item/reagent_containers/pill/patch/proc/apply_part(mob/living/L, mob/user, selected_target) + if (!selected_target) + return + if (!user.can_interact_with(L, TRUE)) + balloon_alert(user, "[L] is too far away!") + return + if (!user.can_interact_with(src, TRUE)) + balloon_alert(user, "[src] is too far away!") + return + var/obj/item/bodypart/affecting = L.get_bodypart(selected_target) if(!affecting) balloon_alert(user, "The limb is missing.") return if(!IS_ORGANIC_LIMB(affecting)) balloon_alert(user, "[src] doesn't work on robotic limbs.") return - return ..() + perform_application(L, user, affecting) /obj/item/reagent_containers/pill/patch/canconsume(mob/eater, mob/user) if(!iscarbon(eater)) diff --git a/code/modules/reagents/reagent_containers/pill.dm b/code/modules/reagents/reagent_containers/pill.dm index cbee1647f4e10..4efc4fbe5c21e 100644 --- a/code/modules/reagents/reagent_containers/pill.dm +++ b/code/modules/reagents/reagent_containers/pill.dm @@ -27,7 +27,10 @@ return -/obj/item/reagent_containers/pill/attack(mob/M, mob/user, obj/item/bodypart/affecting) +/obj/item/reagent_containers/pill/attack(mob/M, mob/user, def_zone) + perform_application(M, user, null) + +/obj/item/reagent_containers/pill/proc/perform_application(mob/M, mob/user, obj/item/bodypart/affecting) if(!canconsume(M, user)) return FALSE if(iscarbon(M)) @@ -59,7 +62,6 @@ qdel(src) return TRUE - /obj/item/reagent_containers/pill/afterattack(obj/target, mob/user , proximity) . = ..() if(!proximity) diff --git a/code/modules/religion/religion_sects.dm b/code/modules/religion/religion_sects.dm index b03a9fecfeb40..c773691fe9b8e 100644 --- a/code/modules/religion/religion_sects.dm +++ b/code/modules/religion/religion_sects.dm @@ -167,9 +167,9 @@ eth_stomach.adjust_charge(60) did_we_charge = TRUE - //if we're not targetting a robot part we stop early - var/obj/item/bodypart/bodypart = blessed.get_bodypart(chap.zone_selected) - if(!IS_ORGANIC_LIMB(bodypart)) + //if we're not targeting a robot part we stop early + var/obj/item/bodypart/bodypart = blessed.get_bodypart(chap.get_combat_bodyzone(target, zone_context = BODYZONE_CONTEXT_ROBOTIC_LIMB_HEALING)) + if(IS_ORGANIC_LIMB(bodypart)) if(!did_we_charge) to_chat(chap, "[GLOB.deity] scoffs at the idea of healing such fleshy matter!") else diff --git a/code/modules/surgery/advanced/bioware/cortex_folding.dm b/code/modules/surgery/advanced/bioware/cortex_folding.dm index fb6216c1ef760..ca11a23eee374 100644 --- a/code/modules/surgery/advanced/bioware/cortex_folding.dm +++ b/code/modules/surgery/advanced/bioware/cortex_folding.dm @@ -14,7 +14,7 @@ bioware_target = BIOWARE_CORTEX -/datum/surgery/advanced/bioware/cortex_folding/can_start(mob/user, mob/living/carbon/target) +/datum/surgery/advanced/bioware/cortex_folding/can_start(mob/user, mob/living/carbon/target, target_zone) var/obj/item/organ/brain/target_brain = target.getorganslot(ORGAN_SLOT_BRAIN) if(!target_brain) return FALSE @@ -25,7 +25,7 @@ accept_hand = TRUE time = 125 -/datum/surgery_step/fold_cortex/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) +/datum/surgery_step/fold_cortex/preop(mob/user, mob/living/carbon/target, obj/item/tool, datum/surgery/surgery) display_results( user, target, @@ -34,7 +34,7 @@ "[user] begins to perform surgery on [target]'s brain.", ) -/datum/surgery_step/fold_cortex/success(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery, default_display_results = FALSE) +/datum/surgery_step/fold_cortex/success(mob/user, mob/living/carbon/target, obj/item/tool, datum/surgery/surgery, default_display_results = FALSE) display_results( user, target, @@ -45,7 +45,7 @@ new /datum/bioware/cortex_fold(target) return ..() -/datum/surgery_step/fold_cortex/failure(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) +/datum/surgery_step/fold_cortex/failure(mob/user, mob/living/carbon/target, obj/item/tool, datum/surgery/surgery) if(target.getorganslot(ORGAN_SLOT_BRAIN)) display_results( user, diff --git a/code/modules/surgery/advanced/bioware/cortex_imprint.dm b/code/modules/surgery/advanced/bioware/cortex_imprint.dm index bec0637b8e7db..7c376508bc0a9 100644 --- a/code/modules/surgery/advanced/bioware/cortex_imprint.dm +++ b/code/modules/surgery/advanced/bioware/cortex_imprint.dm @@ -14,7 +14,7 @@ bioware_target = BIOWARE_CORTEX -/datum/surgery/advanced/bioware/cortex_imprint/can_start(mob/user, mob/living/carbon/target) +/datum/surgery/advanced/bioware/cortex_imprint/can_start(mob/user, mob/living/carbon/target, target_zone) var/obj/item/organ/brain/target_brain = target.getorganslot(ORGAN_SLOT_BRAIN) if(!target_brain) return FALSE @@ -25,7 +25,7 @@ accept_hand = TRUE time = 125 -/datum/surgery_step/imprint_cortex/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) +/datum/surgery_step/imprint_cortex/preop(mob/user, mob/living/carbon/target, obj/item/tool, datum/surgery/surgery) display_results( user, target, @@ -34,7 +34,7 @@ "[user] begins to perform surgery on [target]'s brain.", ) -/datum/surgery_step/imprint_cortex/success(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery, default_display_results = FALSE) +/datum/surgery_step/imprint_cortex/success(mob/user, mob/living/carbon/target, obj/item/tool, datum/surgery/surgery, default_display_results = FALSE) display_results( user, target, @@ -45,7 +45,7 @@ new /datum/bioware/cortex_imprint(target) return ..() -/datum/surgery_step/imprint_cortex/failure(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) +/datum/surgery_step/imprint_cortex/failure(mob/user, mob/living/carbon/target, obj/item/tool, datum/surgery/surgery) if(target.getorganslot(ORGAN_SLOT_BRAIN)) display_results( user, diff --git a/code/modules/surgery/advanced/bioware/experimental_dissection.dm b/code/modules/surgery/advanced/bioware/experimental_dissection.dm index 12de45aa7a2a6..741e4164e8e41 100644 --- a/code/modules/surgery/advanced/bioware/experimental_dissection.dm +++ b/code/modules/surgery/advanced/bioware/experimental_dissection.dm @@ -10,7 +10,7 @@ possible_locs = list(BODY_ZONE_CHEST) target_mobtypes = list(/mob/living/carbon) //Feel free to dissect devils but they're magic. -/datum/surgery/advanced/experimental_dissection/can_start(mob/user, mob/living/carbon/target) +/datum/surgery/advanced/experimental_dissection/can_start(mob/user, mob/living/carbon/target, target_zone) . = ..() if(HAS_TRAIT(target, TRAIT_DISSECTED)) return FALSE @@ -25,7 +25,7 @@ implements = list(TOOL_SCALPEL = 60, /obj/item/knife = 30, /obj/item/shard = 15) time = 125 -/datum/surgery_step/dissection/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) +/datum/surgery_step/dissection/preop(mob/user, mob/living/carbon/target, obj/item/tool, datum/surgery/surgery) user.visible_message("[user] starts dissecting [target].", "You start dissecting [target].") /datum/surgery_step/dissection/proc/check_value(mob/living/carbon/target) @@ -46,7 +46,7 @@ return 3000 return 2000 -/datum/surgery_step/dissection/success(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) +/datum/surgery_step/dissection/success(mob/user, mob/living/carbon/target, obj/item/tool, datum/surgery/surgery) user.visible_message("[user] dissects [target]!", "You dissect [target], and add your discoveries to the research database!") SSresearch.science_tech.add_point_list(list(TECHWEB_POINT_TYPE_DISCOVERY = check_value(target))) var/obj/item/bodypart/L = target.get_bodypart(BODY_ZONE_CHEST) @@ -54,7 +54,7 @@ ADD_TRAIT(target, TRAIT_DISSECTED, "surgery") return TRUE -/datum/surgery_step/dissection/failure(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) +/datum/surgery_step/dissection/failure(mob/user, mob/living/carbon/target, obj/item/tool, datum/surgery/surgery) user.visible_message("[user] dissects [target]!", "You dissect [target], but do not find anything particularly interesting.") SSresearch.science_tech.add_point_list(list(TECHWEB_POINT_TYPE_DISCOVERY = (check_value(target) * 0.2))) var/obj/item/bodypart/L = target.get_bodypart(BODY_ZONE_CHEST) diff --git a/code/modules/surgery/advanced/bioware/ligament_hook.dm b/code/modules/surgery/advanced/bioware/ligament_hook.dm index cf47e774cc5eb..0b05040622dee 100644 --- a/code/modules/surgery/advanced/bioware/ligament_hook.dm +++ b/code/modules/surgery/advanced/bioware/ligament_hook.dm @@ -17,12 +17,12 @@ accept_hand = TRUE time = 125 -/datum/surgery_step/reshape_ligaments/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) +/datum/surgery_step/reshape_ligaments/preop(mob/user, mob/living/carbon/target, obj/item/tool, datum/surgery/surgery) display_results(user, target, "You start reshaping [target]'s ligaments into a hook-like shape.", "[user] starts reshaping [target]'s ligaments into a hook-like shape.", "[user] starts manipulating [target]'s ligaments.") -/datum/surgery_step/reshape_ligaments/success(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) +/datum/surgery_step/reshape_ligaments/success(mob/user, mob/living/carbon/target, obj/item/tool, datum/surgery/surgery) display_results(user, target, "You reshape [target]'s ligaments into a connective hook!", "[user] reshapes [target]'s ligaments into a connective hook!", "[user] finishes manipulating [target]'s ligaments.") diff --git a/code/modules/surgery/advanced/bioware/ligament_reinforcement.dm b/code/modules/surgery/advanced/bioware/ligament_reinforcement.dm index 7d65c9dd0d092..0c7350419fe91 100644 --- a/code/modules/surgery/advanced/bioware/ligament_reinforcement.dm +++ b/code/modules/surgery/advanced/bioware/ligament_reinforcement.dm @@ -17,12 +17,12 @@ accept_hand = TRUE time = 125 -/datum/surgery_step/reinforce_ligaments/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) +/datum/surgery_step/reinforce_ligaments/preop(mob/user, mob/living/carbon/target, obj/item/tool, datum/surgery/surgery) display_results(user, target, "You start reinforcing [target]'s ligaments.", "[user] starts reinforce [target]'s ligaments.", "[user] starts manipulating [target]'s ligaments.") -/datum/surgery_step/reinforce_ligaments/success(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) +/datum/surgery_step/reinforce_ligaments/success(mob/user, mob/living/carbon/target, obj/item/tool, datum/surgery/surgery) display_results(user, target, "You reinforce [target]'s ligaments!", "[user] reinforces [target]'s ligaments!", "[user] finishes manipulating [target]'s ligaments.") diff --git a/code/modules/surgery/advanced/bioware/muscled_veins.dm b/code/modules/surgery/advanced/bioware/muscled_veins.dm index c9771d8b295d8..f45d6035ab447 100644 --- a/code/modules/surgery/advanced/bioware/muscled_veins.dm +++ b/code/modules/surgery/advanced/bioware/muscled_veins.dm @@ -16,12 +16,12 @@ accept_hand = TRUE time = 125 -/datum/surgery_step/muscled_veins/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) +/datum/surgery_step/muscled_veins/preop(mob/user, mob/living/carbon/target, obj/item/tool, datum/surgery/surgery) display_results(user, target, "You start wrapping muscles around [target]'s circulatory system.", "[user] starts wrapping muscles around [target]'s circulatory system.", "[user] starts manipulating [target]'s circulatory system.") -/datum/surgery_step/muscled_veins/success(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) +/datum/surgery_step/muscled_veins/success(mob/user, mob/living/carbon/target, obj/item/tool, datum/surgery/surgery) display_results(user, target, "You reshape [target]'s circulatory system, adding a muscled membrane!", "[user] reshapes [target]'s circulatory system, adding a muscled membrane!", "[user] finishes manipulating [target]'s circulatory system.") diff --git a/code/modules/surgery/advanced/bioware/nerve_grounding.dm b/code/modules/surgery/advanced/bioware/nerve_grounding.dm index eb70a838a4099..32cf2588433da 100644 --- a/code/modules/surgery/advanced/bioware/nerve_grounding.dm +++ b/code/modules/surgery/advanced/bioware/nerve_grounding.dm @@ -16,12 +16,12 @@ accept_hand = TRUE time = 155 -/datum/surgery_step/ground_nerves/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) +/datum/surgery_step/ground_nerves/preop(mob/user, mob/living/carbon/target, obj/item/tool, datum/surgery/surgery) display_results(user, target, "You start rerouting [target]'s nerves.", "[user] starts rerouting [target]'s nerves.", "[user] starts manipulating [target]'s nervous system.") -/datum/surgery_step/ground_nerves/success(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) +/datum/surgery_step/ground_nerves/success(mob/user, mob/living/carbon/target, obj/item/tool, datum/surgery/surgery) display_results(user, target, "You successfully reroute [target]'s nervous system!", "[user] successfully reroutes [target]'s nervous system!", "[user] finishes manipulating [target]'s nervous system.") diff --git a/code/modules/surgery/advanced/bioware/nerve_splicing.dm b/code/modules/surgery/advanced/bioware/nerve_splicing.dm index 50872fa6c2a18..b408ac678b1f7 100644 --- a/code/modules/surgery/advanced/bioware/nerve_splicing.dm +++ b/code/modules/surgery/advanced/bioware/nerve_splicing.dm @@ -16,12 +16,12 @@ accept_hand = TRUE time = 155 -/datum/surgery_step/splice_nerves/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) +/datum/surgery_step/splice_nerves/preop(mob/user, mob/living/carbon/target, obj/item/tool, datum/surgery/surgery) display_results(user, target, "You start splicing together [target]'s nerves.", "[user] starts splicing together [target]'s nerves.", "[user] starts manipulating [target]'s nervous system.") -/datum/surgery_step/splice_nerves/success(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) +/datum/surgery_step/splice_nerves/success(mob/user, mob/living/carbon/target, obj/item/tool, datum/surgery/surgery) display_results(user, target, "You successfully splice [target]'s nervous system!", "[user] successfully splices [target]'s nervous system!", "[user] finishes manipulating [target]'s nervous system.") diff --git a/code/modules/surgery/advanced/bioware/vein_threading.dm b/code/modules/surgery/advanced/bioware/vein_threading.dm index 92df47ab353b9..b3e9e634f5a78 100644 --- a/code/modules/surgery/advanced/bioware/vein_threading.dm +++ b/code/modules/surgery/advanced/bioware/vein_threading.dm @@ -17,12 +17,12 @@ accept_hand = TRUE time = 125 -/datum/surgery_step/thread_veins/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) +/datum/surgery_step/thread_veins/preop(mob/user, mob/living/carbon/target, obj/item/tool, datum/surgery/surgery) display_results(user, target, "You start weaving [target]'s circulatory system.", "[user] starts weaving [target]'s circulatory system.", "[user] starts manipulating [target]'s circulatory system.") -/datum/surgery_step/thread_veins/success(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) +/datum/surgery_step/thread_veins/success(mob/user, mob/living/carbon/target, obj/item/tool, datum/surgery/surgery) display_results(user, target, "You weave [target]'s circulatory system into a resistant mesh!", "[user] weaves [target]'s circulatory system into a resistant mesh!", "[user] finishes manipulating [target]'s circulatory system.") diff --git a/code/modules/surgery/advanced/brainwashing.dm b/code/modules/surgery/advanced/brainwashing.dm index a16e93a09898d..64d324068564b 100644 --- a/code/modules/surgery/advanced/brainwashing.dm +++ b/code/modules/surgery/advanced/brainwashing.dm @@ -18,7 +18,7 @@ possible_locs = list(BODY_ZONE_HEAD) abductor_surgery_blacklist = TRUE -/datum/surgery/advanced/brainwashing/can_start(mob/user, mob/living/carbon/target) +/datum/surgery/advanced/brainwashing/can_start(mob/user, mob/living/carbon/target, target_zone) if(!..()) return FALSE var/obj/item/organ/brain/B = target.getorganslot(ORGAN_SLOT_BRAIN) @@ -35,7 +35,7 @@ failure_sound = 'sound/surgery/organ2.ogg' var/objective -/datum/surgery_step/brainwash/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) +/datum/surgery_step/brainwash/preop(mob/user, mob/living/carbon/target, obj/item/tool, datum/surgery/surgery) objective = stripped_input(user, "Choose the objective to imprint on your victim's brain.", "Brainwashing", null, MAX_MESSAGE_LEN) if(!objective) return -1 @@ -43,7 +43,7 @@ "[user] begins to fix [target]'s brain.", "[user] begins to perform surgery on [target]'s brain.") -/datum/surgery_step/brainwash/success(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) +/datum/surgery_step/brainwash/success(mob/user, mob/living/carbon/target, obj/item/tool, datum/surgery/surgery) if(!target.mind) to_chat(user, "[target] doesn't respond to the brainwashing, as if [target.p_they()] lacked a mind...") return FALSE @@ -59,7 +59,7 @@ log_game("[key_name(user)] surgically brainwashed [key_name(target)] with the objective '[objective]'.") return TRUE -/datum/surgery_step/brainwash/failure(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) +/datum/surgery_step/brainwash/failure(mob/user, mob/living/carbon/target, obj/item/tool, datum/surgery/surgery) if(target.getorganslot(ORGAN_SLOT_BRAIN)) display_results(user, target, "You screw up, bruising the brain tissue!", "[user] screws up, causing brain damage!", diff --git a/code/modules/surgery/advanced/lobotomy.dm b/code/modules/surgery/advanced/lobotomy.dm index 796c7e2f26d6e..cb041d55f3413 100644 --- a/code/modules/surgery/advanced/lobotomy.dm +++ b/code/modules/surgery/advanced/lobotomy.dm @@ -13,7 +13,7 @@ possible_locs = list(BODY_ZONE_HEAD) requires_bodypart_type = 0 -/datum/surgery/advanced/lobotomy/can_start(mob/user, mob/living/carbon/target) +/datum/surgery/advanced/lobotomy/can_start(mob/user, mob/living/carbon/target, target_zone) if(!..()) return FALSE var/obj/item/organ/brain/B = target.getorganslot(ORGAN_SLOT_BRAIN) @@ -35,12 +35,12 @@ return FALSE return TRUE -/datum/surgery_step/lobotomize/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) +/datum/surgery_step/lobotomize/preop(mob/user, mob/living/carbon/target, obj/item/tool, datum/surgery/surgery) display_results(user, target, "You begin to perform a lobotomy on [target]'s brain...", "[user] begins to perform a lobotomy on [target]'s brain.", "[user] begins to perform surgery on [target]'s brain.") -/datum/surgery_step/lobotomize/success(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) +/datum/surgery_step/lobotomize/success(mob/user, mob/living/carbon/target, obj/item/tool, datum/surgery/surgery) display_results(user, target, "You succeed in lobotomizing [target].", "[user] successfully lobotomizes [target]!", "[user] completes the surgery on [target]'s brain.") @@ -61,7 +61,7 @@ SWITCH_EMPTY_STATEMENT return TRUE -/datum/surgery_step/lobotomize/failure(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) +/datum/surgery_step/lobotomize/failure(mob/user, mob/living/carbon/target, obj/item/tool, datum/surgery/surgery) var/obj/item/organ/brain/B = target.getorganslot(ORGAN_SLOT_BRAIN) if(B) display_results(user, target, "You remove the wrong part, causing more damage!", diff --git a/code/modules/surgery/advanced/necrotic_revival.dm b/code/modules/surgery/advanced/necrotic_revival.dm index 87e7e8f8ff0e1..7b930841f968f 100644 --- a/code/modules/surgery/advanced/necrotic_revival.dm +++ b/code/modules/surgery/advanced/necrotic_revival.dm @@ -11,7 +11,7 @@ possible_locs = list(BODY_ZONE_HEAD) abductor_surgery_blacklist = TRUE -/datum/surgery/advanced/necrotic_revival/can_start(mob/user, mob/living/carbon/target) +/datum/surgery/advanced/necrotic_revival/can_start(mob/user, mob/living/carbon/target, target_zone) . = ..() var/obj/item/organ/zombie_infection/ZI = target.getorganslot(ORGAN_SLOT_ZOMBIE) if(ZI) @@ -24,12 +24,12 @@ chems_needed = list(/datum/reagent/toxin/zombiepowder, /datum/reagent/medicine/rezadone) require_all_chems = FALSE -/datum/surgery_step/bionecrosis/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) +/datum/surgery_step/bionecrosis/preop(mob/user, mob/living/carbon/target, obj/item/tool, datum/surgery/surgery) display_results(user, target, "You begin to grow a romerol tumor on [target]'s brain...", "[user] begins to tinker with [target]'s brain...", "[user] begins to perform surgery on [target]'s brain.") -/datum/surgery_step/bionecrosis/success(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) +/datum/surgery_step/bionecrosis/success(mob/user, mob/living/carbon/target, obj/item/tool, datum/surgery/surgery) display_results(user, target, "You succeed in growing a romerol tumor on [target]'s brain.", "[user] successfully grows a romerol tumor on [target]'s brain!", "[user] completes the surgery on [target]'s brain.") diff --git a/code/modules/surgery/advanced/pacification.dm b/code/modules/surgery/advanced/pacification.dm index a20a4889bfbe6..5a98e32083430 100644 --- a/code/modules/surgery/advanced/pacification.dm +++ b/code/modules/surgery/advanced/pacification.dm @@ -12,7 +12,7 @@ possible_locs = list(BODY_ZONE_HEAD) requires_bodypart_type = 0 -/datum/surgery/advanced/pacify/can_start(mob/user, mob/living/carbon/target) +/datum/surgery/advanced/pacify/can_start(mob/user, mob/living/carbon/target, target_zone) . = ..() var/obj/item/organ/brain/B = target.getorganslot(ORGAN_SLOT_BRAIN) if(!B) @@ -26,19 +26,19 @@ success_sound = 'sound/surgery/hemostat1.ogg' failure_sound = 'sound/surgery/organ2.ogg' -/datum/surgery_step/pacify/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) +/datum/surgery_step/pacify/preop(mob/user, mob/living/carbon/target, obj/item/tool, datum/surgery/surgery) display_results(user, target, "You begin to pacify [target]...", "[user] begins to fix [target]'s brain.", "[user] begins to perform surgery on [target]'s brain.") -/datum/surgery_step/pacify/success(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) +/datum/surgery_step/pacify/success(mob/user, mob/living/carbon/target, obj/item/tool, datum/surgery/surgery) display_results(user, target, "You succeed in neurologically pacifying [target].", "[user] successfully fixes [target]'s brain!", "[user] completes the surgery on [target]'s brain.") target.gain_trauma(/datum/brain_trauma/severe/pacifism, TRAUMA_RESILIENCE_LOBOTOMY) return TRUE -/datum/surgery_step/pacify/failure(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) +/datum/surgery_step/pacify/failure(mob/user, mob/living/carbon/target, obj/item/tool, datum/surgery/surgery) display_results(user, target, "You screw up, rewiring [target]'s brain the wrong way around...", "[user] screws up, causing brain damage!", "[user] completes the surgery on [target]'s brain.") diff --git a/code/modules/surgery/advanced/revival.dm b/code/modules/surgery/advanced/revival.dm index f18ed376e04f6..b5ae8bce78b33 100644 --- a/code/modules/surgery/advanced/revival.dm +++ b/code/modules/surgery/advanced/revival.dm @@ -13,7 +13,7 @@ possible_locs = list(BODY_ZONE_HEAD) requires_bodypart_type = 0 -/datum/surgery/advanced/revival/can_start(mob/user, mob/living/carbon/target) +/datum/surgery/advanced/revival/can_start(mob/user, mob/living/carbon/target, target_zone) if(!..()) return FALSE if(target.stat != DEAD) @@ -53,13 +53,13 @@ to_chat(user, "You need an electrode for this!") return FALSE -/datum/surgery_step/revive/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) +/datum/surgery_step/revive/preop(mob/user, mob/living/carbon/target, obj/item/tool, datum/surgery/surgery) display_results(user, target, "You prepare to give [target]'s brain the spark of life with [tool].", "[user] prepares to shock [target]'s brain with [tool].", "[user] prepares to shock [target]'s brain with [tool].") target.notify_ghost_cloning("Someone is trying to zap your brain!", source = target) -/datum/surgery_step/revive/success(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) +/datum/surgery_step/revive/success(mob/user, mob/living/carbon/target, obj/item/tool, datum/surgery/surgery) display_results(user, target, "You successfully shock [target]'s brain with [tool]...", "[user] send a powerful shock to [target]'s brain with [tool]...", "[user] send a powerful shock to [target]'s brain with [tool]...") @@ -76,7 +76,7 @@ target.visible_message("...[target.p_they()] convulses, then lies still.") return FALSE -/datum/surgery_step/revive/failure(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) +/datum/surgery_step/revive/failure(mob/user, mob/living/carbon/target, obj/item/tool, datum/surgery/surgery) display_results(user, target, "You shock [target]'s brain with [tool], but [target.p_they()] doesn't react.", "[user] send a powerful shock to [target]'s brain with [tool], but [target.p_they()] doesn't react.", "[user] send a powerful shock to [target]'s brain with [tool], but [target.p_they()] doesn't react.") diff --git a/code/modules/surgery/advanced/viral_bonding.dm b/code/modules/surgery/advanced/viral_bonding.dm index 72055c08da280..53017cf892618 100644 --- a/code/modules/surgery/advanced/viral_bonding.dm +++ b/code/modules/surgery/advanced/viral_bonding.dm @@ -12,7 +12,7 @@ possible_locs = list(BODY_ZONE_CHEST) self_operable = TRUE -/datum/surgery/advanced/viral_bonding/can_start(mob/user, mob/living/carbon/target) +/datum/surgery/advanced/viral_bonding/can_start(mob/user, mob/living/carbon/target, target_zone) if(!..()) return FALSE if(!LAZYLEN(target.diseases)) @@ -31,12 +31,12 @@ return TRUE -/datum/surgery_step/viral_bond/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) +/datum/surgery_step/viral_bond/preop(mob/user, mob/living/carbon/target, obj/item/tool, datum/surgery/surgery) display_results(user, target, "You start heating [target]'s bone marrow with [tool]...", "[user] starts heating [target]'s bone marrow with [tool]...", "[user] starts heating something in [target]'s chest with [tool]...") -/datum/surgery_step/viral_bond/success(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) +/datum/surgery_step/viral_bond/success(mob/user, mob/living/carbon/target, obj/item/tool, datum/surgery/surgery) display_results(user, target, "[target]'s bone marrow begins pulsing slowly. The viral bonding is complete.", "[target]'s bone marrow begins pulsing slowly.", "[user] finishes the operation.") diff --git a/code/modules/surgery/amputation.dm b/code/modules/surgery/amputation.dm index 98e66b71e3103..62ba5d084f0d5 100644 --- a/code/modules/surgery/amputation.dm +++ b/code/modules/surgery/amputation.dm @@ -15,16 +15,16 @@ preop_sound = 'sound/surgery/scalpel1.ogg' success_sound = 'sound/surgery/organ2.ogg' -/datum/surgery_step/sever_limb/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) - display_results(user, target, "You begin to sever [target]'s [parse_zone(target_zone)]...", - "[user] begins to sever [target]'s [parse_zone(target_zone)]!", - "[user] begins to sever [target]'s [parse_zone(target_zone)]!") +/datum/surgery_step/sever_limb/preop(mob/user, mob/living/carbon/target, obj/item/tool, datum/surgery/surgery) + display_results(user, target, "You begin to sever [target]'s [parse_zone(surgery.location)]...", + "[user] begins to sever [target]'s [parse_zone(surgery.location)]!", + "[user] begins to sever [target]'s [parse_zone(surgery.location)]!") -/datum/surgery_step/sever_limb/success(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) +/datum/surgery_step/sever_limb/success(mob/user, mob/living/carbon/target, obj/item/tool, datum/surgery/surgery) var/mob/living/carbon/human/L = target - display_results(user, target, "You sever [L]'s [parse_zone(target_zone)].", - "[user] severs [L]'s [parse_zone(target_zone)]!", - "[user] severs [L]'s [parse_zone(target_zone)]!") + display_results(user, target, "You sever [L]'s [parse_zone(surgery.location)].", + "[user] severs [L]'s [parse_zone(surgery.location)]!", + "[user] severs [L]'s [parse_zone(surgery.location)]!") if(surgery.operated_bodypart) var/obj/item/bodypart/target_limb = surgery.operated_bodypart target_limb.drop_limb() diff --git a/code/modules/surgery/blood_filter.dm b/code/modules/surgery/blood_filter.dm index d1d28b9b42bf2..0027a851bfc1a 100644 --- a/code/modules/surgery/blood_filter.dm +++ b/code/modules/surgery/blood_filter.dm @@ -24,7 +24,7 @@ filtering_step_type, /datum/surgery_step/close) -/datum/surgery/blood_filter/can_start(mob/user, mob/living/carbon/target) +/datum/surgery/blood_filter/can_start(mob/user, mob/living/carbon/target, target_zone) if(HAS_TRAIT(target, TRAIT_HUSK)) //Can't filter husk return FALSE var/datum/surgery_step/filter_blood/filtering_step = filtering_step_type @@ -42,7 +42,7 @@ var/chem_purge_factor = 0.2 var/tox_heal_factor = 0 -/datum/surgery_step/filter_blood/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) +/datum/surgery_step/filter_blood/preop(mob/user, mob/living/carbon/target, obj/item/tool, datum/surgery/surgery) if(istype(surgery,/datum/surgery/blood_filter)) var/datum/surgery/blood_filter/the_surgery = surgery if(!the_surgery.antispam) @@ -50,13 +50,13 @@ "[user] uses [tool] to filtering your blood.", "[user] uses [tool] on [target]'s chest.") -/datum/surgery_step/filter_blood/initiate(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery, try_to_fail = FALSE) +/datum/surgery_step/filter_blood/initiate(mob/user, mob/living/carbon/target, obj/item/tool, datum/surgery/surgery, try_to_fail = FALSE) if(..()) while(target.reagents.total_volume || (tox_heal_factor > 0 && target.getToxLoss() > 0)) if(!..()) break -/datum/surgery_step/filter_blood/success(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery, default_display_results = FALSE) +/datum/surgery_step/filter_blood/success(mob/user, mob/living/carbon/target, obj/item/tool, datum/surgery/surgery, default_display_results = FALSE) var/tox_loss = target.getToxLoss() if(target.reagents.total_volume || (tox_heal_factor > 0 && tox_loss > 0)) for(var/blood_chem in target.reagents.reagent_list) @@ -86,7 +86,7 @@ the_surgery.antispam = TRUE return TRUE -/datum/surgery_step/filter_blood/failure(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) +/datum/surgery_step/filter_blood/failure(mob/user, mob/living/carbon/target, obj/item/tool, datum/surgery/surgery) display_results(user, target, "You screw up, brusing [target]'s chest!", "[user] screws up, brusing [target]'s chest!", "[user] screws up!") diff --git a/code/modules/surgery/brain_recalibration.dm b/code/modules/surgery/brain_recalibration.dm index 41a47baea9dd2..46cb89dc73c0d 100644 --- a/code/modules/surgery/brain_recalibration.dm +++ b/code/modules/surgery/brain_recalibration.dm @@ -21,18 +21,18 @@ success_sound = 'sound/surgery/hemostat1.ogg' failure_sound = 'sound/surgery/organ2.ogg' -/datum/surgery/brain_recalibration/can_start(mob/user, mob/living/carbon/target) +/datum/surgery/brain_recalibration/can_start(mob/user, mob/living/carbon/target, target_zone) var/obj/item/organ/brain/B = target.getorganslot(ORGAN_SLOT_BRAIN) if(!B) return FALSE return TRUE -/datum/surgery_step/fix_brain/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) +/datum/surgery_step/fix_brain/preop(mob/user, mob/living/carbon/target, obj/item/tool, datum/surgery/surgery) display_results(user, target, "You begin to fix [target]'s brain...", "[user] begins to fix [target]'s brain.", "[user] begins to perform surgery on [target]'s brain.") -/datum/surgery_step/fix_brain/success(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) +/datum/surgery_step/fix_brain/success(mob/user, mob/living/carbon/target, obj/item/tool, datum/surgery/surgery) display_results(user, target, "You succeed in fixing [target]'s brain.", "[user] successfully fixes [target]'s brain!", "[user] completes the surgery on [target]'s brain.") @@ -44,7 +44,7 @@ to_chat(user, "It looks like [target]'s brain could be fixed further.") return TRUE -/datum/surgery_step/fix_brain/failure(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) +/datum/surgery_step/fix_brain/failure(mob/user, mob/living/carbon/target, obj/item/tool, datum/surgery/surgery) if(target.getorganslot(ORGAN_SLOT_BRAIN)) display_results(user, target, "You screw up, causing more damage!", "[user] screws up, causing brain damage!", diff --git a/code/modules/surgery/cavity_implant.dm b/code/modules/surgery/cavity_implant.dm index 48eb59d579fdf..4a9350a9061d8 100644 --- a/code/modules/surgery/cavity_implant.dm +++ b/code/modules/surgery/cavity_implant.dm @@ -22,31 +22,31 @@ return FALSE return !tool.is_hot() -/datum/surgery_step/handle_cavity/preop(mob/user, mob/living/carbon/human/target, target_zone, obj/item/tool, datum/surgery/surgery) +/datum/surgery_step/handle_cavity/preop(mob/user, mob/living/carbon/human/target, obj/item/tool, datum/surgery/surgery) var/obj/item/bodypart/chest/CH = target.get_bodypart(BODY_ZONE_CHEST) IC = CH.cavity_item if(tool) - display_results(user, target, "You begin to insert [tool] into [target]'s [target_zone]...", - "[user] begins to insert [tool] into [target]'s [target_zone].", - "[user] begins to insert [tool.w_class > WEIGHT_CLASS_SMALL ? tool : "something"] into [target]'s [target_zone].") + display_results(user, target, "You begin to insert [tool] into [target]'s [surgery.location]...", + "[user] begins to insert [tool] into [target]'s [surgery.location].", + "[user] begins to insert [tool.w_class > WEIGHT_CLASS_SMALL ? tool : "something"] into [target]'s [surgery.location].") //Incase they are interupted mid-insert, log it; shows intent to implant log_combat(user, target, "tried to cavity implant [tool.name] into") else - display_results(user, target, "You check for items in [target]'s [target_zone]...", - "[user] checks for items in [target]'s [target_zone].", - "[user] looks for something in [target]'s [target_zone].") + display_results(user, target, "You check for items in [target]'s [surgery.location]...", + "[user] checks for items in [target]'s [surgery.location].", + "[user] looks for something in [target]'s [surgery.location].") log_combat(user, target, "searched for cavity item [IC ? "([IC.name])" : null] in") -/datum/surgery_step/handle_cavity/success(mob/user, mob/living/carbon/human/target, target_zone, obj/item/tool, datum/surgery/surgery) +/datum/surgery_step/handle_cavity/success(mob/user, mob/living/carbon/human/target, obj/item/tool, datum/surgery/surgery) var/obj/item/bodypart/chest/CH = target.get_bodypart(BODY_ZONE_CHEST) if(tool) if(IC || tool.w_class > WEIGHT_CLASS_NORMAL || HAS_TRAIT(tool, TRAIT_NODROP) || istype(tool, /obj/item/organ)) - to_chat(user, "You can't seem to fit [tool] in [target]'s [target_zone]!") + to_chat(user, "You can't seem to fit [tool] in [target]'s [surgery.location]!") return 0 else - display_results(user, target, "You stuff [tool] into [target]'s [target_zone].", - "[user] stuffs [tool] into [target]'s [target_zone]!", - "[user] stuffs [tool.w_class > WEIGHT_CLASS_SMALL ? tool : "something"] into [target]'s [target_zone].") + display_results(user, target, "You stuff [tool] into [target]'s [surgery.location].", + "[user] stuffs [tool] into [target]'s [surgery.location]!", + "[user] stuffs [tool.w_class > WEIGHT_CLASS_SMALL ? tool : "something"] into [target]'s [surgery.location].") user.transferItemToLoc(tool, target, TRUE) CH.cavity_item = tool //Logs stowing items in a cavity, similar to organ manipulation @@ -54,14 +54,14 @@ return 1 else if(IC) - display_results(user, target, "You pull [IC] out of [target]'s [target_zone].", - "[user] pulls [IC] out of [target]'s [target_zone]!", - "[user] pulls [IC.w_class > WEIGHT_CLASS_SMALL ? IC : "something"] out of [target]'s [target_zone].") + display_results(user, target, "You pull [IC] out of [target]'s [surgery.location].", + "[user] pulls [IC] out of [target]'s [surgery.location]!", + "[user] pulls [IC.w_class > WEIGHT_CLASS_SMALL ? IC : "something"] out of [target]'s [surgery.location].") user.put_in_hands(IC) CH.cavity_item = null //Log when cavity items are surgically removed, we don't care about it popping out from gibbing log_combat(user, target, "extracted [IC.name] from cavity in") return 1 else - to_chat(user, "You don't find anything in [target]'s [target_zone].") + to_chat(user, "You don't find anything in [target]'s [surgery.location].") return 0 diff --git a/code/modules/surgery/core_removal.dm b/code/modules/surgery/core_removal.dm index 5c9b8f334d28b..cb1484209b1d5 100644 --- a/code/modules/surgery/core_removal.dm +++ b/code/modules/surgery/core_removal.dm @@ -17,12 +17,12 @@ implements = list(TOOL_HEMOSTAT = 100, TOOL_CROWBAR = 100) time = 16 -/datum/surgery_step/extract_core/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) +/datum/surgery_step/extract_core/preop(mob/user, mob/living/carbon/target, obj/item/tool, datum/surgery/surgery) display_results(user, target, "You begin to extract a core from [target]...", "[user] begins to extract a core from [target].", "[user] begins to extract a core from [target].") -/datum/surgery_step/extract_core/success(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) +/datum/surgery_step/extract_core/success(mob/user, mob/living/carbon/target, obj/item/tool, datum/surgery/surgery) var/mob/living/simple_animal/slime/slime = target if(slime.cores > 0) slime.cores-- diff --git a/code/modules/surgery/coronary_bypass.dm b/code/modules/surgery/coronary_bypass.dm index eb74be456b856..2e49b36ade5c5 100644 --- a/code/modules/surgery/coronary_bypass.dm +++ b/code/modules/surgery/coronary_bypass.dm @@ -4,7 +4,7 @@ /datum/surgery_step/incise_heart, /datum/surgery_step/coronary_bypass, /datum/surgery_step/close) possible_locs = list(BODY_ZONE_CHEST) -/datum/surgery/coronary_bypass/can_start(mob/user, mob/living/carbon/target) +/datum/surgery/coronary_bypass/can_start(mob/user, mob/living/carbon/target, target_zone) var/obj/item/organ/heart/H = target.getorganslot(ORGAN_SLOT_HEART) if(H) if(H.damage > 60 && !H.operated) @@ -22,12 +22,12 @@ success_sound = 'sound/surgery/scalpel2.ogg' failure_sound = 'sound/surgery/organ2.ogg' -/datum/surgery_step/incise_heart/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) +/datum/surgery_step/incise_heart/preop(mob/user, mob/living/carbon/target, obj/item/tool, datum/surgery/surgery) display_results(user, target, "You begin to make an incision in [target]'s heart...", "[user] begins to make an incision in [target]'s heart.", "[user] begins to make an incision in [target]'s heart.") -/datum/surgery_step/incise_heart/success(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) +/datum/surgery_step/incise_heart/success(mob/user, mob/living/carbon/target, obj/item/tool, datum/surgery/surgery) if(ishuman(target)) var/mob/living/carbon/human/H = target if (!(NOBLOOD in H.dna.species.species_traits)) @@ -38,7 +38,7 @@ H.adjustBruteLoss(10) return TRUE -/datum/surgery_step/incise_heart/failure(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) +/datum/surgery_step/incise_heart/failure(mob/user, mob/living/carbon/target, obj/item/tool, datum/surgery/surgery) if(ishuman(target)) var/mob/living/carbon/human/H = target display_results(user, target, "You screw up, cutting too deeply into the heart!", @@ -54,12 +54,12 @@ implements = list(TOOL_HEMOSTAT = 90, TOOL_WIRECUTTER = 35, /obj/item/stack/package_wrap = 15, /obj/item/stack/cable_coil = 5) time = 90 -/datum/surgery_step/coronary_bypass/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) +/datum/surgery_step/coronary_bypass/preop(mob/user, mob/living/carbon/target, obj/item/tool, datum/surgery/surgery) display_results(user, target, "You begin to graft a bypass onto [target]'s heart...", "[user] begins to graft something onto [target]'s heart!", "[user] begins to graft something onto [target]'s heart!") -/datum/surgery_step/coronary_bypass/success(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) +/datum/surgery_step/coronary_bypass/success(mob/user, mob/living/carbon/target, obj/item/tool, datum/surgery/surgery) target.setOrganLoss(ORGAN_SLOT_HEART, 60) var/obj/item/organ/heart/heart = target.getorganslot(ORGAN_SLOT_HEART) if(heart) //slightly worrying if we lost our heart mid-operation, but that's life @@ -69,7 +69,7 @@ "[user] finishes grafting something onto [target]'s heart.") return TRUE -/datum/surgery_step/coronary_bypass/failure(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) +/datum/surgery_step/coronary_bypass/failure(mob/user, mob/living/carbon/target, obj/item/tool, datum/surgery/surgery) if(ishuman(target)) var/mob/living/carbon/human/H = target display_results(user, target, "You screw up in attaching the graft, and it tears off, tearing part of the heart!", diff --git a/code/modules/surgery/dental_implant.dm b/code/modules/surgery/dental_implant.dm index 7a0d828299b8a..7d6dfe54e1165 100644 --- a/code/modules/surgery/dental_implant.dm +++ b/code/modules/surgery/dental_implant.dm @@ -9,12 +9,12 @@ implements = list(/obj/item/reagent_containers/pill = 100) time = 16 -/datum/surgery_step/insert_pill/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) - display_results(user, target, "You begin to wedge [tool] in [target]'s [parse_zone(target_zone)]...", - "[user] begins to wedge \the [tool] in [target]'s [parse_zone(target_zone)].", - "[user] begins to wedge something in [target]'s [parse_zone(target_zone)].") +/datum/surgery_step/insert_pill/preop(mob/user, mob/living/carbon/target, obj/item/tool, datum/surgery/surgery) + display_results(user, target, "You begin to wedge [tool] in [target]'s [parse_zone(surgery.location)]...", + "[user] begins to wedge \the [tool] in [target]'s [parse_zone(surgery.location)].", + "[user] begins to wedge something in [target]'s [parse_zone(surgery.location)].") -/datum/surgery_step/insert_pill/success(mob/user, mob/living/carbon/target, target_zone, var/obj/item/reagent_containers/pill/tool, datum/surgery/surgery) +/datum/surgery_step/insert_pill/success(mob/user, mob/living/carbon/target, obj/item/reagent_containers/pill/tool, datum/surgery/surgery) if(!istype(tool)) return 0 @@ -25,9 +25,9 @@ P.target = tool P.Grant(target) //The pill never actually goes in an inventory slot, so the owner doesn't inherit actions from it - display_results(user, target, "You wedge [tool] into [target]'s [parse_zone(target_zone)].", - "[user] wedges \the [tool] into [target]'s [parse_zone(target_zone)]!", - "[user] wedges something into [target]'s [parse_zone(target_zone)]!") + display_results(user, target, "You wedge [tool] into [target]'s [parse_zone(surgery.location)].", + "[user] wedges \the [tool] into [target]'s [parse_zone(surgery.location)]!", + "[user] wedges something into [target]'s [parse_zone(surgery.location)]!") return 1 /datum/action/item_action/hands_free/activate_pill diff --git a/code/modules/surgery/eye_surgery.dm b/code/modules/surgery/eye_surgery.dm index e0d739df76a5b..3a29baf23acb1 100644 --- a/code/modules/surgery/eye_surgery.dm +++ b/code/modules/surgery/eye_surgery.dm @@ -11,19 +11,19 @@ implements = list(TOOL_HEMOSTAT = 100, TOOL_SCREWDRIVER = 45, /obj/item/pen = 25) time = 64 -/datum/surgery/eye_surgery/can_start(mob/user, mob/living/carbon/target) +/datum/surgery/eye_surgery/can_start(mob/user, mob/living/carbon/target, target_zone) var/obj/item/organ/eyes/E = target.getorganslot(ORGAN_SLOT_EYES) if(!E) to_chat(user, "It's hard to do surgery on someone's eyes when [target.p_they()] [target.p_do()]n't have any.") return FALSE return TRUE -/datum/surgery_step/fix_eyes/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) +/datum/surgery_step/fix_eyes/preop(mob/user, mob/living/carbon/target, obj/item/tool, datum/surgery/surgery) display_results(user, target, "You begin to fix [target]'s eyes...", "[user] begins to fix [target]'s eyes.", "[user] begins to perform surgery on [target]'s eyes.") -/datum/surgery_step/fix_eyes/success(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) +/datum/surgery_step/fix_eyes/success(mob/user, mob/living/carbon/target, obj/item/tool, datum/surgery/surgery) var/obj/item/organ/eyes/E = target.getorganslot(ORGAN_SLOT_EYES) user.visible_message("[user] successfully fixes [target]'s eyes!", "You succeed in fixing [target]'s eyes.") display_results(user, target, "You succeed in fixing [target]'s eyes.", @@ -36,7 +36,7 @@ E.setOrganDamage(0) return TRUE -/datum/surgery_step/fix_eyes/failure(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) +/datum/surgery_step/fix_eyes/failure(mob/user, mob/living/carbon/target, obj/item/tool, datum/surgery/surgery) if(target.getorgan(/obj/item/organ/brain)) display_results(user, target, "You accidentally stab [target] right in the brain!", "[user] accidentally stabs [target] right in the brain!", diff --git a/code/modules/surgery/gastrectomy.dm b/code/modules/surgery/gastrectomy.dm index cbc56604a0597..e766b30cd1e81 100644 --- a/code/modules/surgery/gastrectomy.dm +++ b/code/modules/surgery/gastrectomy.dm @@ -13,7 +13,7 @@ /datum/surgery_step/close ) -/datum/surgery/gastrectomy/can_start(mob/user, mob/living/carbon/target) +/datum/surgery/gastrectomy/can_start(mob/user, mob/living/carbon/target, target_zone) var/obj/item/organ/stomach/L = target.getorganslot(ORGAN_SLOT_STOMACH) if(L?.damage > 50 && !(L.organ_flags & ORGAN_FAILING)) return TRUE @@ -26,12 +26,12 @@ /obj/item/shard = 35) time = 52 -/datum/surgery_step/gastrectomy/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) +/datum/surgery_step/gastrectomy/preop(mob/user, mob/living/carbon/target, obj/item/tool, datum/surgery/surgery) display_results(user, target, "You begin to cut out a damaged piece of [target]'s stomach...", "[user] begins to make an incision in [target].", "[user] begins to make an incision in [target].") -/datum/surgery_step/gastrectomy/success(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery, default_display_results = FALSE) +/datum/surgery_step/gastrectomy/success(mob/user, mob/living/carbon/target, obj/item/tool, datum/surgery/surgery, default_display_results = FALSE) var/mob/living/carbon/human/H = target H.setOrganLoss(ORGAN_SLOT_STOMACH, 20) // Stomachs have a threshold for being able to even digest food, so I might tweak this number display_results(user, target, "You successfully remove the damaged part of [target]'s stomach.", @@ -39,7 +39,7 @@ "[user] successfully removes the damaged part of [target]'s stomach.") return ..() -/datum/surgery_step/gastrectomy/failure(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery) +/datum/surgery_step/gastrectomy/failure(mob/user, mob/living/carbon/target, obj/item/tool, datum/surgery) var/mob/living/carbon/human/H = target H.adjustOrganLoss(ORGAN_SLOT_STOMACH, 15) display_results(user, target, "You cut the wrong part of [target]'s stomach!", diff --git a/code/modules/surgery/healing.dm b/code/modules/surgery/healing.dm index 4dc1ea5b7c368..d6cfaf7b0cb47 100644 --- a/code/modules/surgery/healing.dm +++ b/code/modules/surgery/healing.dm @@ -33,7 +33,7 @@ /datum/surgery_step/heal/proc/get_progress(mob/user, mob/living/carbon/target, brute_healed, burn_healed) return -/datum/surgery_step/heal/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) +/datum/surgery_step/heal/preop(mob/user, mob/living/carbon/target, obj/item/tool, datum/surgery/surgery) var/woundtype if(brutehealing && burnhealing) woundtype = "wounds" @@ -49,13 +49,13 @@ "[user] attempts to patch some of [target]'s [woundtype].") -/datum/surgery_step/heal/initiate(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery, try_to_fail = FALSE) +/datum/surgery_step/heal/initiate(mob/user, mob/living/carbon/target, obj/item/tool, datum/surgery/surgery, try_to_fail = FALSE) if(..()) while((brutehealing && target.getBruteLoss()) || (burnhealing && target.getFireLoss())) if(!..()) break -/datum/surgery_step/heal/success(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) +/datum/surgery_step/heal/success(mob/user, mob/living/carbon/target, obj/item/tool, datum/surgery/surgery) var/umsg = "You succeed in fixing some of [target]'s wounds" //no period, add initial space to "addons" var/tmsg = "[user] fixes some of [target]'s wounds" //see above var/urhealedamt_brute = brutehealing @@ -67,7 +67,7 @@ else //less healing bonus for the dead since they're expected to have lots of damage to begin with (to make TW into defib not TOO simple) urhealedamt_brute += round((target.getBruteLoss()/ (missinghpbonus*5)),0.1) urhealedamt_burn += round((target.getFireLoss()/ (missinghpbonus*5)),0.1) - if(!get_location_accessible(target, target_zone)) + if(!get_location_accessible(target, surgery.location)) urhealedamt_brute *= 0.55 urhealedamt_burn *= 0.55 umsg += " as best as you can while [target.p_they()] [target.p_have()] clothing on" @@ -83,7 +83,7 @@ the_surgery.antispam = TRUE return TRUE -/datum/surgery_step/heal/failure(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) +/datum/surgery_step/heal/failure(mob/user, mob/living/carbon/target, obj/item/tool, datum/surgery/surgery) display_results(user, target, "You screwed up!", "[user] screws up!", "[user] fixes some of [target]'s wounds.", TRUE) @@ -325,7 +325,7 @@ success_sound = 'sound/surgery/retractor2.ogg' failure_sound = 'sound/surgery/organ1.ogg' -/datum/surgery_step/heal/combo/upgraded/femto/failure(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) +/datum/surgery_step/heal/combo/upgraded/femto/failure(mob/user, mob/living/carbon/target, obj/item/tool, datum/surgery/surgery) display_results(user, target, "You screwed up!", "[user] screws up!", "[user] fixes some of [target]'s wounds.", TRUE) diff --git a/code/modules/surgery/helpers.dm b/code/modules/surgery/helpers.dm index a48037fea3164..2e79428cf6731 100644 --- a/code/modules/surgery/helpers.dm +++ b/code/modules/surgery/helpers.dm @@ -2,95 +2,93 @@ if(!istype(M)) return - var/mob/living/carbon/C - var/obj/item/bodypart/affecting - var/selected_zone = user.zone_selected - - if(iscarbon(M)) - C = M - affecting = C.get_bodypart(check_zone(selected_zone)) - var/datum/surgery/current_surgery for(var/datum/surgery/S in M.surgeries) - if(S.location == selected_zone) - current_surgery = S + current_surgery = S if(!current_surgery) - var/list/all_surgeries = GLOB.surgeries_list.Copy() - var/list/available_surgeries = list() + var/datum/task/zone_selector = user.select_bodyzone(M, TRUE) + zone_selector.continue_with(CALLBACK(GLOBAL_PROC, GLOBAL_PROC_REF(initiate_surgery_at_zone), I, M, user)) - for(var/datum/surgery/S in all_surgeries) - if(!S.possible_locs.Find(selected_zone)) - continue - if(affecting) - if(!S.requires_bodypart) - continue - if(S.requires_bodypart_type && !(affecting.bodytype & S.requires_bodypart_type)) - continue - if(S.requires_real_bodypart && affecting.is_pseudopart) - continue - else if(C && S.requires_bodypart) //mob with no limb in surgery zone when we need a limb + else if(!current_surgery.step_in_progress) + attempt_cancel_surgery(current_surgery, I, M, user) + + return 1 + +/proc/initiate_surgery_at_zone(obj/item/I, mob/living/M, mob/user, target_zone) + var/list/all_surgeries = GLOB.surgeries_list.Copy() + var/list/available_surgeries = list() + + var/mob/living/carbon/C + if (iscarbon(M)) + C = M + + var/obj/item/bodypart/affecting = M.get_bodypart(check_zone(target_zone)) + + for(var/datum/surgery/S in all_surgeries) + if(!S.possible_locs.Find(target_zone)) + continue + if(affecting) + if(!S.requires_bodypart) continue - if(S.lying_required && (M.mobility_flags & MOBILITY_STAND)) + if(S.requires_bodypart_type && !(affecting.bodytype & S.requires_bodypart_type)) continue - if(!S.can_start(user, M)) + if(S.requires_real_bodypart && affecting.is_pseudopart) continue - for(var/path in S.target_mobtypes) - if(istype(M, path)) - available_surgeries[S.name] = S - break + else if(C && S.requires_bodypart) //mob with no limb in surgery zone when we need a limb + continue + if(S.lying_required && (M.mobility_flags & MOBILITY_STAND)) + continue + if(!S.can_start(user, M, target_zone)) + continue + for(var/path in S.target_mobtypes) + if(istype(M, path)) + available_surgeries[S.name] = S + break + + if(!available_surgeries.len) + return - if(!available_surgeries.len) - return + var/P = input("Begin which procedure?", "Surgery", null, null) as null|anything in sort_list(available_surgeries) + if(P && user && user.Adjacent(M) && (I in user)) + var/datum/surgery/S = available_surgeries[P] - var/P = input("Begin which procedure?", "Surgery", null, null) as null|anything in sort_list(available_surgeries) - if(P && user && user.Adjacent(M) && (I in user)) - var/datum/surgery/S = available_surgeries[P] - - for(var/datum/surgery/other in M.surgeries) - if(other.location == S.location) - return //during the input() another surgery was started at the same location. - - //we check that the surgery is still doable after the input() wait. - if(C) - affecting = C.get_bodypart(check_zone(selected_zone)) - if(affecting) - if(!S.requires_bodypart) - return - if(S.requires_bodypart_type && !(affecting.bodytype & S.requires_bodypart_type)) - return - else if(C && S.requires_bodypart) - return - if(S.lying_required && (M.mobility_flags & MOBILITY_STAND)) + for(var/datum/surgery/other in M.surgeries) + if(other.location == S.location) + return //during the input() another surgery was started at the same location. + + //we check that the surgery is still doable after the input() wait. + if(C) + affecting = C.get_bodypart(check_zone(target_zone)) + if(affecting) + if(!S.requires_bodypart) return - if(!S.can_start(user, M)) + if(S.requires_bodypart_type && !(affecting.bodytype & S.requires_bodypart_type)) return + else if(C && S.requires_bodypart) + return + if(S.lying_required && (M.mobility_flags & MOBILITY_STAND)) + return + if(!S.can_start(user, M, target_zone)) + return - if(S.ignore_clothes || get_location_accessible(M, selected_zone)) - var/datum/surgery/procedure = new S.type(M, selected_zone, affecting) - user.visible_message("[user] drapes [I] over [M]'s [parse_zone(selected_zone)] to prepare for surgery.", - "You drape [I] over [M]'s [parse_zone(selected_zone)] to prepare for \an [procedure.name].") - I.balloon_alert(user, "You drape over [parse_zone(selected_zone)].") - - log_combat(user, M, "operated on", null, "(OPERATION TYPE: [procedure.name]) (TARGET AREA: [selected_zone])") - else - I.balloon_alert(user, "[parse_zone(selected_zone)] is covered up!") - - - else if(!current_surgery.step_in_progress) - attempt_cancel_surgery(current_surgery, I, M, user) + if(S.ignore_clothes || get_location_accessible(M, target_zone)) + var/datum/surgery/procedure = new S.type(M, target_zone, affecting) + user.visible_message("[user] drapes [I] over [M]'s [parse_zone(target_zone)] to prepare for surgery.", + "You drape [I] over [M]'s [parse_zone(target_zone)] to prepare for \an [procedure.name].") + I.balloon_alert(user, "You drape over [parse_zone(target_zone)].") - return 1 + log_combat(user, M, "operated on", null, "(OPERATION TYPE: [procedure.name]) (TARGET AREA: [target_zone])") + else + I.balloon_alert(user, "[parse_zone(target_zone)] is covered up!") /proc/attempt_cancel_surgery(datum/surgery/S, obj/item/I, mob/living/M, mob/user) - var/selected_zone = user.zone_selected - if(S.status == 1) M.surgeries -= S - user.visible_message("[user] removes [I] from [M]'s [parse_zone(selected_zone)].", \ - "You remove [I] from [M]'s [parse_zone(selected_zone)].") - I.balloon_alert(user, "You remove [I] from [parse_zone(selected_zone)].") + user.visible_message("[user] removes [I] from [M]'s [parse_zone(S.location)].", \ + "You remove [I] from [M]'s [parse_zone(S.location)].") + I.balloon_alert(user, "You remove [I] from [parse_zone(S.location)].") qdel(S) return @@ -111,8 +109,8 @@ to_chat(user, "You need to hold a [is_robotic ? "screwdriver" : "cautery"] in your inactive hand to stop [M]'s surgery!") return M.surgeries -= S - user.visible_message("[user] closes [M]'s [parse_zone(selected_zone)] with [close_tool] and removes [I].", \ - "You close [M]'s [parse_zone(selected_zone)] with [close_tool] and remove [I].") + user.visible_message("[user] closes [M]'s [parse_zone(S.location)] with [close_tool] and removes [I].", \ + "You close [M]'s [parse_zone(S.location)] with [close_tool] and remove [I].") qdel(S) /proc/get_location_accessible(mob/M, location) diff --git a/code/modules/surgery/hepatectomy.dm b/code/modules/surgery/hepatectomy.dm index a2f7165c8e239..87ab3c1444246 100644 --- a/code/modules/surgery/hepatectomy.dm +++ b/code/modules/surgery/hepatectomy.dm @@ -12,7 +12,7 @@ /datum/surgery_step/close ) -/datum/surgery/hepatectomy/can_start(mob/user, mob/living/carbon/target) +/datum/surgery/hepatectomy/can_start(mob/user, mob/living/carbon/target, target_zone) var/obj/item/organ/liver/L = target.getorganslot(ORGAN_SLOT_LIVER) if(L?.damage > 50 && !(L.organ_flags & ORGAN_FAILING)) return TRUE @@ -25,12 +25,12 @@ /obj/item/shard = 35) time = 52 -/datum/surgery_step/hepatectomy/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) +/datum/surgery_step/hepatectomy/preop(mob/user, mob/living/carbon/target, obj/item/tool, datum/surgery/surgery) display_results(user, target, "You begin to cut out a damaged piece of [target]'s liver...", "[user] begins to make an incision in [target].", "[user] begins to make an incision in [target].") -/datum/surgery_step/hepatectomy/success(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) +/datum/surgery_step/hepatectomy/success(mob/user, mob/living/carbon/target, obj/item/tool, datum/surgery/surgery) var/mob/living/carbon/human/H = target H.setOrganLoss(ORGAN_SLOT_LIVER, 10) //not bad, not great display_results(user, target, "You successfully remove the damaged part of [target]'s liver.", @@ -38,7 +38,7 @@ "[user] successfullly removes the damaged part of [target]'s liver.") return TRUE -/datum/surgery_step/hepatectomy/failure(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery) +/datum/surgery_step/hepatectomy/failure(mob/user, mob/living/carbon/target, obj/item/tool, datum/surgery) var/mob/living/carbon/human/H = target H.adjustOrganLoss(ORGAN_SLOT_LIVER, 15) display_results(user, target, "You cut the wrong part of [target]'s liver!", diff --git a/code/modules/surgery/implant_removal.dm b/code/modules/surgery/implant_removal.dm index 4929098adc550..8d72ceac92a01 100644 --- a/code/modules/surgery/implant_removal.dm +++ b/code/modules/surgery/implant_removal.dm @@ -12,28 +12,28 @@ var/obj/item/implant/I = null success_sound = 'sound/surgery/hemostat1.ogg' -/datum/surgery_step/extract_implant/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) +/datum/surgery_step/extract_implant/preop(mob/user, mob/living/carbon/target, obj/item/tool, datum/surgery/surgery) for(var/obj/item/O in target.implants) I = O break if(I) - display_results(user, target, "You begin to extract [I] from [target]'s [target_zone]...", - "[user] begins to extract [I] from [target]'s [target_zone].", - "[user] begins to extract something from [target]'s [target_zone].") + display_results(user, target, "You begin to extract [I] from [target]'s [surgery.location]...", + "[user] begins to extract [I] from [target]'s [surgery.location].", + "[user] begins to extract something from [target]'s [surgery.location].") //Incase they are interupted mid-extraction, log it log_combat(user, target, "tried to extract [I.name] from") else - display_results(user, target, "You look for an implant in [target]'s [target_zone]...", - "[user] looks for an implant in [target]'s [target_zone].", - "[user] looks for something in [target]'s [target_zone].") + display_results(user, target, "You look for an implant in [target]'s [surgery.location]...", + "[user] looks for an implant in [target]'s [surgery.location].", + "[user] looks for something in [target]'s [surgery.location].") //Doesn't matter if they finish or not, defaults to this if there are no implants log_combat(user, target, "implant checked") -/datum/surgery_step/extract_implant/success(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) +/datum/surgery_step/extract_implant/success(mob/user, mob/living/carbon/target, obj/item/tool, datum/surgery/surgery) if(I) - display_results(user, target, "You successfully remove [I] from [target]'s [target_zone].", - "[user] successfully removes [I] from [target]'s [target_zone]!", - "[user] successfully removes something from [target]'s [target_zone]!") + display_results(user, target, "You successfully remove [I] from [target]'s [surgery.location].", + "[user] successfully removes [I] from [target]'s [surgery.location]!", + "[user] successfully removes something from [target]'s [surgery.location]!") I.removed(target) //Logs removal of implants, similar to removal of organs during organ manipulation @@ -56,7 +56,7 @@ qdel(I) else - to_chat(user, "You can't find anything in [target]'s [target_zone]!") + to_chat(user, "You can't find anything in [target]'s [surgery.location]!") return 1 /datum/surgery/implant_removal/mechanic diff --git a/code/modules/surgery/limb_augmentation.dm b/code/modules/surgery/limb_augmentation.dm index d9f660278417b..c9c2d9d1111cd 100644 --- a/code/modules/surgery/limb_augmentation.dm +++ b/code/modules/surgery/limb_augmentation.dm @@ -11,15 +11,15 @@ var/obj/item/bodypart/L = null // L because "limb" -/datum/surgery_step/replace_limb/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) +/datum/surgery_step/replace_limb/preop(mob/user, mob/living/carbon/target, obj/item/tool, datum/surgery/surgery) if(istype(tool, /obj/item/organ_storage) && istype(tool.contents[1], /obj/item/bodypart)) tool = tool.contents[1] var/obj/item/bodypart/aug = tool if(IS_ORGANIC_LIMB(aug)) to_chat(user, "That's not an augment, silly!") return -1 - if(aug.body_zone != target_zone) - to_chat(user, "[tool] isn't the right type for [parse_zone(target_zone)].") + if(aug.body_zone != surgery.location) + to_chat(user, "[tool] isn't the right type for [parse_zone(surgery.location)].") return -1 L = surgery.operated_bodypart if(L) @@ -27,11 +27,11 @@ to_chat(user, "You can't augment a limb with paralysis!") return -1 else - display_results(user, target, "You begin to augment [target]'s [parse_zone(user.zone_selected)]...", - "[user] begins to augment [target]'s [parse_zone(user.zone_selected)] with [aug].", - "[user] begins to augment [target]'s [parse_zone(user.zone_selected)].") + display_results(user, target, "You begin to augment [target]'s [parse_zone(surgery.location)]...", + "[user] begins to augment [target]'s [parse_zone(surgery.location)] with [aug].", + "[user] begins to augment [target]'s [parse_zone(surgery.location)].") else - user.visible_message("[user] looks for [target]'s [parse_zone(user.zone_selected)].", "You look for [target]'s [parse_zone(user.zone_selected)]...") + user.visible_message("[user] looks for [target]'s [parse_zone(surgery.location)].", "You look for [target]'s [parse_zone(surgery.location)]...") //ACTUAL SURGERIES @@ -45,12 +45,12 @@ -/datum/surgery/augmentation/can_start(mob/user, mob/living/carbon/target) +/datum/surgery/augmentation/can_start(mob/user, mob/living/carbon/target, target_zone) return ..() && !isoozeling(target) //SURGERY STEP SUCCESSES -/datum/surgery_step/replace_limb/success(mob/user, mob/living/carbon/target, target_zone, obj/item/bodypart/tool, datum/surgery/surgery) +/datum/surgery_step/replace_limb/success(mob/user, mob/living/carbon/target, obj/item/bodypart/tool, datum/surgery/surgery) if(L) if(istype(tool, /obj/item/organ_storage)) tool.icon_state = initial(tool.icon_state) @@ -59,10 +59,10 @@ tool = tool.contents[1] if(istype(tool) && user.temporarilyRemoveItemFromInventory(tool)) tool.replace_limb(target, TRUE) - display_results(user, target, "You successfully augment [target]'s [parse_zone(target_zone)].", - "[user] successfully augments [target]'s [parse_zone(target_zone)] with [tool]!", - "[user] successfully augments [target]'s [parse_zone(target_zone)]!") - log_combat(user, target, "augmented", addition="by giving him new [parse_zone(target_zone)] INTENT: [uppertext(user.a_intent)]") + display_results(user, target, "You successfully augment [target]'s [parse_zone(surgery.location)].", + "[user] successfully augments [target]'s [parse_zone(surgery.location)] with [tool]!", + "[user] successfully augments [target]'s [parse_zone(surgery.location)]!") + log_combat(user, target, "augmented", addition="by giving him new [parse_zone(surgery.location)] INTENT: [uppertext(user.a_intent)]") else - to_chat(user, "[target] has no organic [parse_zone(target_zone)] there!") + to_chat(user, "[target] has no organic [parse_zone(surgery.location)] there!") return TRUE diff --git a/code/modules/surgery/lipoplasty.dm b/code/modules/surgery/lipoplasty.dm index 8c7812ba5cdb4..5b93a881b2db5 100644 --- a/code/modules/surgery/lipoplasty.dm +++ b/code/modules/surgery/lipoplasty.dm @@ -3,7 +3,7 @@ steps = list(/datum/surgery_step/incise, /datum/surgery_step/clamp_bleeders, /datum/surgery_step/cut_fat, /datum/surgery_step/remove_fat, /datum/surgery_step/close) possible_locs = list(BODY_ZONE_CHEST) -/datum/surgery/lipoplasty/can_start(mob/user, mob/living/carbon/target) +/datum/surgery/lipoplasty/can_start(mob/user, mob/living/carbon/target, target_zone) if(HAS_TRAIT(target, TRAIT_FAT)) return 1 return 0 @@ -15,16 +15,16 @@ implements = list(TOOL_SAW = 100, /obj/item/hatchet = 35, /obj/item/knife/butcher = 25) time = 64 -/datum/surgery_step/cut_fat/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) +/datum/surgery_step/cut_fat/preop(mob/user, mob/living/carbon/target, obj/item/tool, datum/surgery/surgery) user.visible_message("[user] begins to cut away [target]'s excess fat.", "You begin to cut away [target]'s excess fat...") display_results(user, target, "You begin to cut away [target]'s excess fat...", "[user] begins to cut away [target]'s excess fat.", - "[user] begins to cut [target]'s [target_zone] with [tool].") + "[user] begins to cut [target]'s [surgery.location] with [tool].") -/datum/surgery_step/cut_fat/success(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) +/datum/surgery_step/cut_fat/success(mob/user, mob/living/carbon/target, obj/item/tool, datum/surgery/surgery) display_results(user, target, "You cut [target]'s excess fat loose.", "[user] cuts [target]'s excess fat loose!", - "[user] finishes the cut on [target]'s [target_zone].") + "[user] finishes the cut on [target]'s [surgery.location].") return 1 //remove fat @@ -33,12 +33,12 @@ implements = list(TOOL_RETRACTOR = 100, TOOL_SCREWDRIVER = 45, TOOL_WIRECUTTER = 35) time = 32 -/datum/surgery_step/remove_fat/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) +/datum/surgery_step/remove_fat/preop(mob/user, mob/living/carbon/target, obj/item/tool, datum/surgery/surgery) display_results(user, target, "You begin to extract [target]'s loose fat...", "[user] begins to extract [target]'s loose fat!", - "[user] begins to extract something from [target]'s [target_zone].") + "[user] begins to extract something from [target]'s [surgery.location].") -/datum/surgery_step/remove_fat/success(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) +/datum/surgery_step/remove_fat/success(mob/user, mob/living/carbon/target, obj/item/tool, datum/surgery/surgery) display_results(user, target, "You extract [target]'s fat.", "[user] extracts [target]'s fat!", "[user] extracts [target]'s fat!") diff --git a/code/modules/surgery/lobectomy.dm b/code/modules/surgery/lobectomy.dm index 0bb0ab39a8122..c10051f71842e 100644 --- a/code/modules/surgery/lobectomy.dm +++ b/code/modules/surgery/lobectomy.dm @@ -4,7 +4,7 @@ /datum/surgery_step/lobectomy, /datum/surgery_step/close) possible_locs = list(BODY_ZONE_CHEST) -/datum/surgery/lobectomy/can_start(mob/user, mob/living/carbon/target) +/datum/surgery/lobectomy/can_start(mob/user, mob/living/carbon/target, target_zone) var/obj/item/organ/lungs/L = target.getorganslot(ORGAN_SLOT_LUNGS) if(L) if(L.damage > 60 && !L.operated) @@ -22,12 +22,12 @@ success_sound = 'sound/surgery/organ1.ogg' failure_sound = 'sound/surgery/organ2.ogg' -/datum/surgery_step/lobectomy/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) +/datum/surgery_step/lobectomy/preop(mob/user, mob/living/carbon/target, obj/item/tool, datum/surgery/surgery) display_results(user, target, "You begin to make an incision in [target]'s lungs...", "[user] begins to make an incision in [target].", "[user] begins to make an incision in [target].") -/datum/surgery_step/lobectomy/success(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) +/datum/surgery_step/lobectomy/success(mob/user, mob/living/carbon/target, obj/item/tool, datum/surgery/surgery) if(ishuman(target)) var/mob/living/carbon/human/H = target var/obj/item/organ/lungs/L = H.getorganslot(ORGAN_SLOT_LUNGS) @@ -38,7 +38,7 @@ "") return TRUE -/datum/surgery_step/lobectomy/failure(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) +/datum/surgery_step/lobectomy/failure(mob/user, mob/living/carbon/target, obj/item/tool, datum/surgery/surgery) if(ishuman(target)) var/mob/living/carbon/human/H = target display_results(user, target, "You screw up, failing to excise [H]'s damaged lobe!", diff --git a/code/modules/surgery/mechanic_steps.dm b/code/modules/surgery/mechanic_steps.dm index 930c109c4667a..4d180a7014100 100644 --- a/code/modules/surgery/mechanic_steps.dm +++ b/code/modules/surgery/mechanic_steps.dm @@ -10,10 +10,10 @@ preop_sound = 'sound/items/screwdriver.ogg' success_sound = 'sound/items/screwdriver2.ogg' -/datum/surgery_step/mechanic_open/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) - display_results(user, target, "You begin to unscrew the shell of [target]'s [parse_zone(target_zone)]...", - "[user] begins to unscrew the shell of [target]'s [parse_zone(target_zone)].", - "[user] begins to unscrew the shell of [target]'s [parse_zone(target_zone)].") +/datum/surgery_step/mechanic_open/preop(mob/user, mob/living/carbon/target, obj/item/tool, datum/surgery/surgery) + display_results(user, target, "You begin to unscrew the shell of [target]'s [parse_zone(surgery.location)]...", + "[user] begins to unscrew the shell of [target]'s [parse_zone(surgery.location)].", + "[user] begins to unscrew the shell of [target]'s [parse_zone(surgery.location)].") /datum/surgery_step/mechanic_incise/tool_check(mob/user, obj/item/tool) if(implement_type == /obj/item && !tool.is_sharp()) @@ -35,10 +35,10 @@ preop_sound = 'sound/items/screwdriver.ogg' success_sound = 'sound/items/screwdriver2.ogg' -/datum/surgery_step/mechanic_close/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) - display_results(user, target, "You begin to screw the shell of [target]'s [parse_zone(target_zone)]...", - "[user] begins to screw the shell of [target]'s [parse_zone(target_zone)].", - "[user] begins to screw the shell of [target]'s [parse_zone(target_zone)].") +/datum/surgery_step/mechanic_close/preop(mob/user, mob/living/carbon/target, obj/item/tool, datum/surgery/surgery) + display_results(user, target, "You begin to screw the shell of [target]'s [parse_zone(surgery.location)]...", + "[user] begins to screw the shell of [target]'s [parse_zone(surgery.location)].", + "[user] begins to screw the shell of [target]'s [parse_zone(surgery.location)].") /datum/surgery_step/mechanic_close/tool_check(mob/user, obj/item/tool) if(implement_type == /obj/item && !tool.is_sharp()) @@ -58,10 +58,10 @@ preop_sound = 'sound/surgery/tape_flip.ogg' success_sound = 'sound/surgery/taperecorder_close.ogg' -/datum/surgery_step/prepare_electronics/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) - display_results(user, target, "You begin to prepare electronics in [target]'s [parse_zone(target_zone)]...", - "[user] begins to prepare electronics in [target]'s [parse_zone(target_zone)].", - "[user] begins to prepare electronics in [target]'s [parse_zone(target_zone)].") +/datum/surgery_step/prepare_electronics/preop(mob/user, mob/living/carbon/target, obj/item/tool, datum/surgery/surgery) + display_results(user, target, "You begin to prepare electronics in [target]'s [parse_zone(surgery.location)]...", + "[user] begins to prepare electronics in [target]'s [parse_zone(surgery.location)].", + "[user] begins to prepare electronics in [target]'s [parse_zone(surgery.location)].") //unwrench /datum/surgery_step/mechanic_unwrench @@ -72,10 +72,10 @@ time = 24 preop_sound = 'sound/items/ratchet.ogg' -/datum/surgery_step/mechanic_unwrench/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) - display_results(user, target, "You begin to unwrench some bolts in [target]'s [parse_zone(target_zone)]...", - "[user] begins to unwrench some bolts in [target]'s [parse_zone(target_zone)].", - "[user] begins to unwrench some bolts in [target]'s [parse_zone(target_zone)].") +/datum/surgery_step/mechanic_unwrench/preop(mob/user, mob/living/carbon/target, obj/item/tool, datum/surgery/surgery) + display_results(user, target, "You begin to unwrench some bolts in [target]'s [parse_zone(surgery.location)]...", + "[user] begins to unwrench some bolts in [target]'s [parse_zone(surgery.location)].", + "[user] begins to unwrench some bolts in [target]'s [parse_zone(surgery.location)].") //wrench /datum/surgery_step/mechanic_wrench @@ -86,10 +86,10 @@ time = 24 preop_sound = 'sound/items/ratchet.ogg' -/datum/surgery_step/mechanic_wrench/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) - display_results(user, target, "You begin to wrench some bolts in [target]'s [parse_zone(target_zone)]...", - "[user] begins to wrench some bolts in [target]'s [parse_zone(target_zone)].", - "[user] begins to wrench some bolts in [target]'s [parse_zone(target_zone)].") +/datum/surgery_step/mechanic_wrench/preop(mob/user, mob/living/carbon/target, obj/item/tool, datum/surgery/surgery) + display_results(user, target, "You begin to wrench some bolts in [target]'s [parse_zone(surgery.location)]...", + "[user] begins to wrench some bolts in [target]'s [parse_zone(surgery.location)].", + "[user] begins to wrench some bolts in [target]'s [parse_zone(surgery.location)].") //open hatch /datum/surgery_step/open_hatch @@ -99,7 +99,7 @@ preop_sound = 'sound/items/ratchet.ogg' preop_sound = 'sound/machines/doorclick.ogg' -/datum/surgery_step/open_hatch/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) - display_results(user, target, "You begin to open the hatch holders in [target]'s [parse_zone(target_zone)]...", - "[user] begins to open the hatch holders in [target]'s [parse_zone(target_zone)].", - "[user] begins to open the hatch holders in [target]'s [parse_zone(target_zone)].") +/datum/surgery_step/open_hatch/preop(mob/user, mob/living/carbon/target, obj/item/tool, datum/surgery/surgery) + display_results(user, target, "You begin to open the hatch holders in [target]'s [parse_zone(surgery.location)]...", + "[user] begins to open the hatch holders in [target]'s [parse_zone(surgery.location)].", + "[user] begins to open the hatch holders in [target]'s [parse_zone(surgery.location)].") diff --git a/code/modules/surgery/organ_manipulation.dm b/code/modules/surgery/organ_manipulation.dm index 704d94a0ab68b..f4ecca1455928 100644 --- a/code/modules/surgery/organ_manipulation.dm +++ b/code/modules/surgery/organ_manipulation.dm @@ -81,7 +81,7 @@ ..() implements = implements + implements_extract -/datum/surgery_step/manipulate_organs/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) +/datum/surgery_step/manipulate_organs/preop(mob/user, mob/living/carbon/target, obj/item/tool, datum/surgery/surgery) I = null if(istype(tool, /obj/item/organ_storage)) if(!tool.contents.len) @@ -89,14 +89,14 @@ return -1 I = tool.contents[1] if(!isorgan(I)) - to_chat(user, "You cannot put [I] into [target]'s [parse_zone(target_zone)]!") + to_chat(user, "You cannot put [I] into [target]'s [parse_zone(surgery.location)]!") return -1 tool = I if(isorgan(tool)) current_type = "insert" I = tool - if(target_zone != I.zone || target.getorganslot(I.slot)) - to_chat(user, "There is no room for [I] in [target]'s [parse_zone(target_zone)]!") + if(surgery.location != I.zone || target.getorganslot(I.slot)) + to_chat(user, "There is no room for [I] in [target]'s [parse_zone(surgery.location)]!") return -1 if(istype(I, /obj/item/organ/brain/positron)) var/obj/item/bodypart/affected = target.get_bodypart(check_zone(I.zone)) @@ -112,16 +112,16 @@ if(!meatslab.useable) to_chat(user, "[I] seems to have been chewed on, you can't use this!") return -1 - display_results(user, target, "You begin to insert [tool] into [target]'s [parse_zone(target_zone)]...", - "[user] begins to insert [tool] into [target]'s [parse_zone(target_zone)].", - "[user] begins to insert something into [target]'s [parse_zone(target_zone)].") + display_results(user, target, "You begin to insert [tool] into [target]'s [parse_zone(surgery.location)]...", + "[user] begins to insert [tool] into [target]'s [parse_zone(surgery.location)].", + "[user] begins to insert something into [target]'s [parse_zone(surgery.location)].") log_combat(user, target, "tried to insert [I.name] into") else if(implement_type in implements_extract) current_type = "extract" - var/list/organs = target.getorganszone(target_zone) + var/list/organs = target.getorganszone(surgery.location) if(!organs.len) - to_chat(user, "There are no removable organs in [target]'s [parse_zone(target_zone)]!") + to_chat(user, "There are no removable organs in [target]'s [parse_zone(surgery.location)]!") return -1 else for(var/obj/item/organ/O in organs) @@ -134,14 +134,14 @@ I = organs[I] if(!I) return -1 - display_results(user, target, "You begin to extract [I] from [target]'s [parse_zone(target_zone)]...", - "[user] begins to extract [I] from [target]'s [parse_zone(target_zone)].", - "[user] begins to extract something from [target]'s [parse_zone(target_zone)].") + display_results(user, target, "You begin to extract [I] from [target]'s [parse_zone(surgery.location)]...", + "[user] begins to extract [I] from [target]'s [parse_zone(surgery.location)].", + "[user] begins to extract something from [target]'s [parse_zone(surgery.location)].") log_combat(user, target, "tried to extract [I.name] from") else return -1 -/datum/surgery_step/manipulate_organs/success(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) +/datum/surgery_step/manipulate_organs/success(mob/user, mob/living/carbon/target, obj/item/tool, datum/surgery/surgery) if(current_type == "insert") if(istype(tool, /obj/item/organ_storage)) I = tool.contents[1] @@ -153,21 +153,21 @@ I = tool user.temporarilyRemoveItemFromInventory(I, TRUE) I.Insert(target) - display_results(user, target, "You insert [tool] into [target]'s [parse_zone(target_zone)].", - "[user] inserts [tool] into [target]'s [parse_zone(target_zone)]!", - "[user] inserts something into [target]'s [parse_zone(target_zone)]!") + display_results(user, target, "You insert [tool] into [target]'s [parse_zone(surgery.location)].", + "[user] inserts [tool] into [target]'s [parse_zone(surgery.location)]!", + "[user] inserts something into [target]'s [parse_zone(surgery.location)]!") log_combat(user, target, "surgically installed [I.name] into") else if(current_type == "extract") if(I && I.owner == target) - display_results(user, target, "You successfully extract [I] from [target]'s [parse_zone(target_zone)].", - "[user] successfully extracts [I] from [target]'s [parse_zone(target_zone)]!", - "[user] successfully extracts something from [target]'s [parse_zone(target_zone)]!") + display_results(user, target, "You successfully extract [I] from [target]'s [parse_zone(surgery.location)].", + "[user] successfully extracts [I] from [target]'s [parse_zone(surgery.location)]!", + "[user] successfully extracts something from [target]'s [parse_zone(surgery.location)]!") log_combat(user, target, "surgically removed [I.name] from") I.Remove(target) I.forceMove(get_turf(target)) else - display_results(user, target, "You can't extract anything from [target]'s [parse_zone(target_zone)]!", - "[user] can't seem to extract anything from [target]'s [parse_zone(target_zone)]!", - "[user] can't seem to extract anything from [target]'s [parse_zone(target_zone)]!") + display_results(user, target, "You can't extract anything from [target]'s [parse_zone(surgery.location)]!", + "[user] can't seem to extract anything from [target]'s [parse_zone(surgery.location)]!", + "[user] can't seem to extract anything from [target]'s [parse_zone(surgery.location)]!") return 0 diff --git a/code/modules/surgery/organic_steps.dm b/code/modules/surgery/organic_steps.dm index 4c56c9709197e..9243218101665 100644 --- a/code/modules/surgery/organic_steps.dm +++ b/code/modules/surgery/organic_steps.dm @@ -8,10 +8,10 @@ preop_sound = 'sound/surgery/scalpel1.ogg' success_sound = 'sound/surgery/scalpel2.ogg' -/datum/surgery_step/incise/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) - display_results(user, target, "You begin to make an incision in [target]'s [parse_zone(target_zone)]...", - "[user] begins to make an incision in [target]'s [parse_zone(target_zone)].", - "[user] begins to make an incision in [target]'s [parse_zone(target_zone)].") +/datum/surgery_step/incise/preop(mob/user, mob/living/carbon/target, obj/item/tool, datum/surgery/surgery) + display_results(user, target, "You begin to make an incision in [target]'s [parse_zone(surgery.location)]...", + "[user] begins to make an incision in [target]'s [parse_zone(surgery.location)].", + "[user] begins to make an incision in [target]'s [parse_zone(surgery.location)].") /datum/surgery_step/incise/tool_check(mob/user, obj/item/tool) if(implement_type == /obj/item && !tool.is_sharp()) @@ -19,24 +19,24 @@ return TRUE -/datum/surgery_step/incise/success(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) +/datum/surgery_step/incise/success(mob/user, mob/living/carbon/target, obj/item/tool, datum/surgery/surgery) if ishuman(target) var/mob/living/carbon/human/H = target if (!(NOBLOOD in H.dna.species.species_traits)) - display_results(user, target, "Blood pools around the incision in [H]'s [parse_zone(target_zone)].", - "Blood pools around the incision in [H]'s [parse_zone(target_zone)].", + display_results(user, target, "Blood pools around the incision in [H]'s [parse_zone(surgery.location)].", + "Blood pools around the incision in [H]'s [parse_zone(surgery.location)].", "") H.bleed_rate += 3 return TRUE /datum/surgery_step/incise/nobleed //silly friendly! -/datum/surgery_step/incise/nobleed/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) - display_results(user, target, "You begin to carefully make an incision in [target]'s [parse_zone(target_zone)]...", - "[user] begins to carefully make an incision in [target]'s [parse_zone(target_zone)].", - "[user] begins to carefully make an incision in [target]'s [parse_zone(target_zone)].") +/datum/surgery_step/incise/nobleed/preop(mob/user, mob/living/carbon/target, obj/item/tool, datum/surgery/surgery) + display_results(user, target, "You begin to carefully make an incision in [target]'s [parse_zone(surgery.location)]...", + "[user] begins to carefully make an incision in [target]'s [parse_zone(surgery.location)].", + "[user] begins to carefully make an incision in [target]'s [parse_zone(surgery.location)].") -/datum/surgery_step/incise/nobleed/success(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) +/datum/surgery_step/incise/nobleed/success(mob/user, mob/living/carbon/target, obj/item/tool, datum/surgery/surgery) return TRUE //clamp bleeders @@ -46,12 +46,12 @@ time = 24 preop_sound = 'sound/surgery/hemostat1.ogg' -/datum/surgery_step/clamp_bleeders/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) - display_results(user, target, "You begin to clamp bleeders in [target]'s [parse_zone(target_zone)]...", - "[user] begins to clamp bleeders in [target]'s [parse_zone(target_zone)].", - "[user] begins to clamp bleeders in [target]'s [parse_zone(target_zone)].") +/datum/surgery_step/clamp_bleeders/preop(mob/user, mob/living/carbon/target, obj/item/tool, datum/surgery/surgery) + display_results(user, target, "You begin to clamp bleeders in [target]'s [parse_zone(surgery.location)]...", + "[user] begins to clamp bleeders in [target]'s [parse_zone(surgery.location)].", + "[user] begins to clamp bleeders in [target]'s [parse_zone(surgery.location)].") -/datum/surgery_step/clamp_bleeders/success(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) +/datum/surgery_step/clamp_bleeders/success(mob/user, mob/living/carbon/target, obj/item/tool, datum/surgery/surgery) if(locate(/datum/surgery_step/saw) in surgery.steps) target.heal_bodypart_damage(20,0) return ..() @@ -65,10 +65,10 @@ preop_sound = 'sound/surgery/retractor1.ogg' success_sound = 'sound/surgery/retractor2.ogg' -/datum/surgery_step/retract_skin/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) - display_results(user, target, "You begin to retract the skin in [target]'s [parse_zone(target_zone)]...", - "[user] begins to retract the skin in [target]'s [parse_zone(target_zone)].", - "[user] begins to retract the skin in [target]'s [parse_zone(target_zone)].") +/datum/surgery_step/retract_skin/preop(mob/user, mob/living/carbon/target, obj/item/tool, datum/surgery/surgery) + display_results(user, target, "You begin to retract the skin in [target]'s [parse_zone(surgery.location)]...", + "[user] begins to retract the skin in [target]'s [parse_zone(surgery.location)].", + "[user] begins to retract the skin in [target]'s [parse_zone(surgery.location)].") @@ -81,10 +81,10 @@ preop_sound = 'sound/surgery/cautery1.ogg' success_sound = 'sound/surgery/cautery2.ogg' -/datum/surgery_step/close/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) - display_results(user, target, "You begin to mend the incision in [target]'s [parse_zone(target_zone)]...", - "[user] begins to mend the incision in [target]'s [parse_zone(target_zone)].", - "[user] begins to mend the incision in [target]'s [parse_zone(target_zone)].") +/datum/surgery_step/close/preop(mob/user, mob/living/carbon/target, obj/item/tool, datum/surgery/surgery) + display_results(user, target, "You begin to mend the incision in [target]'s [parse_zone(surgery.location)]...", + "[user] begins to mend the incision in [target]'s [parse_zone(surgery.location)].", + "[user] begins to mend the incision in [target]'s [parse_zone(surgery.location)].") /datum/surgery_step/close/tool_check(mob/user, obj/item/tool) if(implement_type == TOOL_WELDER || implement_type == /obj/item) @@ -92,7 +92,7 @@ return TRUE -/datum/surgery_step/close/success(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) +/datum/surgery_step/close/success(mob/user, mob/living/carbon/target, obj/item/tool, datum/surgery/surgery) if(locate(/datum/surgery_step/saw) in surgery.steps) target.heal_bodypart_damage(45,0) return ..() @@ -115,16 +115,16 @@ ) success_sound = 'sound/surgery/organ2.ogg' -/datum/surgery_step/saw/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) - display_results(user, target, "You begin to saw through the bone in [target]'s [parse_zone(target_zone)]...", - "[user] begins to saw through the bone in [target]'s [parse_zone(target_zone)].", - "[user] begins to saw through the bone in [target]'s [parse_zone(target_zone)].") +/datum/surgery_step/saw/preop(mob/user, mob/living/carbon/target, obj/item/tool, datum/surgery/surgery) + display_results(user, target, "You begin to saw through the bone in [target]'s [parse_zone(surgery.location)]...", + "[user] begins to saw through the bone in [target]'s [parse_zone(surgery.location)].", + "[user] begins to saw through the bone in [target]'s [parse_zone(surgery.location)].") -/datum/surgery_step/saw/success(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) - target.apply_damage(50, BRUTE, "[target_zone]") - display_results(user, target, "You saw [target]'s [parse_zone(target_zone)] open.", - "[user] saws [target]'s [parse_zone(target_zone)] open!", - "[user] saws [target]'s [parse_zone(target_zone)] open!") +/datum/surgery_step/saw/success(mob/user, mob/living/carbon/target, obj/item/tool, datum/surgery/surgery) + target.apply_damage(50, BRUTE, "[surgery.location]") + display_results(user, target, "You saw [target]'s [parse_zone(surgery.location)] open.", + "[user] saws [target]'s [parse_zone(surgery.location)] open!", + "[user] saws [target]'s [parse_zone(surgery.location)] open!") return 1 //drill bone @@ -140,13 +140,13 @@ return FALSE return TRUE -/datum/surgery_step/drill/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) - display_results(user, target, "You begin to drill into the bone in [target]'s [parse_zone(target_zone)]...", - "[user] begins to drill into the bone in [target]'s [parse_zone(target_zone)].", - "[user] begins to drill into the bone in [target]'s [parse_zone(target_zone)].") +/datum/surgery_step/drill/preop(mob/user, mob/living/carbon/target, obj/item/tool, datum/surgery/surgery) + display_results(user, target, "You begin to drill into the bone in [target]'s [parse_zone(surgery.location)]...", + "[user] begins to drill into the bone in [target]'s [parse_zone(surgery.location)].", + "[user] begins to drill into the bone in [target]'s [parse_zone(surgery.location)].") -/datum/surgery_step/drill/success(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) - display_results(user, target, "You drill into [target]'s [parse_zone(target_zone)].", - "[user] drills into [target]'s [parse_zone(target_zone)]!", - "[user] drills into [target]'s [parse_zone(target_zone)]!") +/datum/surgery_step/drill/success(mob/user, mob/living/carbon/target, obj/item/tool, datum/surgery/surgery) + display_results(user, target, "You drill into [target]'s [parse_zone(surgery.location)].", + "[user] drills into [target]'s [parse_zone(surgery.location)]!", + "[user] drills into [target]'s [parse_zone(surgery.location)]!") return 1 diff --git a/code/modules/surgery/organs/organ_internal.dm b/code/modules/surgery/organs/organ_internal.dm index 6d004190bca6d..e2ec41f9e6209 100644 --- a/code/modules/surgery/organs/organ_internal.dm +++ b/code/modules/surgery/organs/organ_internal.dm @@ -156,8 +156,7 @@ INITIALIZE_IMMEDIATE(/obj/item/organ) /obj/item/organ/proc/check_for_surgery(mob/living/carbon/human/H) for(var/datum/surgery/S in H.surgeries) - if(S.location == H.zone_selected) - return TRUE //no snacks mid surgery + return TRUE //no snacks mid surgery return FALSE /obj/item/organ/item_action_slot_check(slot,mob/user) diff --git a/code/modules/surgery/plastic_surgery.dm b/code/modules/surgery/plastic_surgery.dm index 48f3d69a72f05..0544d89250191 100644 --- a/code/modules/surgery/plastic_surgery.dm +++ b/code/modules/surgery/plastic_surgery.dm @@ -9,13 +9,13 @@ implements = list(TOOL_SCALPEL = 100, /obj/item/knife = 50, TOOL_WIRECUTTER = 35) time = 64 -/datum/surgery_step/reshape_face/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) +/datum/surgery_step/reshape_face/preop(mob/user, mob/living/carbon/target, obj/item/tool, datum/surgery/surgery) user.visible_message("[user] begins to alter [target]'s appearance.", "You begin to alter [target]'s appearance...") display_results(user, target, "You begin to alter [target]'s appearance...", "[user] begins to alter [target]'s appearance.", "[user] begins to make an incision in [target]'s face.") -/datum/surgery_step/reshape_face/success(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) +/datum/surgery_step/reshape_face/success(mob/user, mob/living/carbon/target, obj/item/tool, datum/surgery/surgery) if(HAS_TRAIT_FROM(target, TRAIT_DISFIGURED, TRAIT_GENERIC)) REMOVE_TRAIT(target, TRAIT_DISFIGURED, TRAIT_GENERIC) display_results(user, target, "You successfully restore [target]'s appearance.", @@ -44,7 +44,7 @@ H.sec_hud_set_ID() return TRUE -/datum/surgery_step/reshape_face/failure(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) +/datum/surgery_step/reshape_face/failure(mob/user, mob/living/carbon/target, obj/item/tool, datum/surgery/surgery) display_results(user, target, "You screw up, leaving [target]'s appearance disfigured!", "[user] screws up, disfiguring [target]'s appearance!", "[user] finishes the operation on [target]'s face.") diff --git a/code/modules/surgery/prosthetic_replacement.dm b/code/modules/surgery/prosthetic_replacement.dm index 9c95ee4963e6b..f74a63eaeec9e 100644 --- a/code/modules/surgery/prosthetic_replacement.dm +++ b/code/modules/surgery/prosthetic_replacement.dm @@ -7,12 +7,12 @@ requires_bodypart_type = 0 self_operable = TRUE -/datum/surgery/prosthetic_replacement/can_start(mob/user, mob/living/carbon/target) +/datum/surgery/prosthetic_replacement/can_start(mob/user, mob/living/carbon/target, target_zone) if(!iscarbon(target)) return 0 var/mob/living/carbon/C = target if(!isoozeling(target)) - if(!C.get_bodypart(user.zone_selected)) //can only start if limb is missing + if(!C.get_bodypart(target_zone)) //can only start if limb is missing return 1 @@ -22,7 +22,7 @@ time = 32 var/organ_rejection_dam = 0 -/datum/surgery_step/add_prosthetic/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) +/datum/surgery_step/add_prosthetic/preop(mob/user, mob/living/carbon/target, obj/item/tool, datum/surgery/surgery) if(istype(tool, /obj/item/organ_storage)) if(!tool.contents.len) to_chat(user, "There is nothing inside [tool]!") @@ -48,22 +48,22 @@ if(H.dna.species.id != BP.limb_id) organ_rejection_dam = 30 - if(target_zone == BP.body_zone) //so we can't replace a leg with an arm, or a human arm with a monkey arm. - display_results(user, target, "You begin to replace [target]'s [parse_zone(target_zone)] with [tool]...", - "[user] begins to replace [target]'s [parse_zone(target_zone)] with [tool].", - "[user] begins to replace [target]'s [parse_zone(target_zone)].") + if(surgery.location == BP.body_zone) //so we can't replace a leg with an arm, or a human arm with a monkey arm. + display_results(user, target, "You begin to replace [target]'s [parse_zone(surgery.location)] with [tool]...", + "[user] begins to replace [target]'s [parse_zone(surgery.location)] with [tool].", + "[user] begins to replace [target]'s [parse_zone(surgery.location)].") else - to_chat(user, "[tool] isn't the right type for [parse_zone(target_zone)].") + to_chat(user, "[tool] isn't the right type for [parse_zone(surgery.location)].") return -1 - else if(target_zone == BODY_ZONE_L_ARM || target_zone == BODY_ZONE_R_ARM) + else if(surgery.location == BODY_ZONE_L_ARM || surgery.location == BODY_ZONE_R_ARM) display_results(user, target, "You begin to attach [tool] onto [target]...", - "[user] begins to attach [tool] onto [target]'s [parse_zone(target_zone)].", - "[user] begins to attach something onto [target]'s [parse_zone(target_zone)].") + "[user] begins to attach [tool] onto [target]'s [parse_zone(surgery.location)].", + "[user] begins to attach something onto [target]'s [parse_zone(surgery.location)].") else to_chat(user, "[tool] must be installed onto an arm.") return -1 -/datum/surgery_step/add_prosthetic/success(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) +/datum/surgery_step/add_prosthetic/success(mob/user, mob/living/carbon/target, obj/item/tool, datum/surgery/surgery) if(istype(tool, /obj/item/organ_storage)) tool.icon_state = initial(tool.icon_state) tool.desc = initial(tool.desc) @@ -74,12 +74,12 @@ L.attach_limb(target) if(organ_rejection_dam) target.adjustToxLoss(organ_rejection_dam) - display_results(user, target, "You succeed in replacing [target]'s [parse_zone(target_zone)].", - "[user] successfully replaces [target]'s [parse_zone(target_zone)] with [tool]!", - "[user] successfully replaces [target]'s [parse_zone(target_zone)]!") + display_results(user, target, "You succeed in replacing [target]'s [parse_zone(surgery.location)].", + "[user] successfully replaces [target]'s [parse_zone(surgery.location)] with [tool]!", + "[user] successfully replaces [target]'s [parse_zone(surgery.location)]!") return 1 else - var/obj/item/bodypart/L = target.newBodyPart(target_zone, FALSE, FALSE) + var/obj/item/bodypart/L = target.newBodyPart(surgery.location, FALSE, FALSE) L.is_pseudopart = TRUE L.attach_limb(target) user.visible_message("[user] finishes attaching [tool]!", "You attach [tool].") @@ -89,17 +89,17 @@ qdel(tool) if(istype(tool, /obj/item/chainsaw/energy/doom)) var/obj/item/mounted_chainsaw/super/new_arm = new(target) - target_zone == BODY_ZONE_R_ARM ? target.put_in_r_hand(new_arm) : target.put_in_l_hand(new_arm) + surgery.location == BODY_ZONE_R_ARM ? target.put_in_r_hand(new_arm) : target.put_in_l_hand(new_arm) return 1 else if(istype(tool, /obj/item/chainsaw/energy)) var/obj/item/mounted_chainsaw/energy/new_arm = new(target) - target_zone == BODY_ZONE_R_ARM ? target.put_in_r_hand(new_arm) : target.put_in_l_hand(new_arm) + surgery.location == BODY_ZONE_R_ARM ? target.put_in_r_hand(new_arm) : target.put_in_l_hand(new_arm) return 1 else if(istype(tool, /obj/item/chainsaw)) var/obj/item/mounted_chainsaw/normal/new_arm = new(target) - target_zone == BODY_ZONE_R_ARM ? target.put_in_r_hand(new_arm) : target.put_in_l_hand(new_arm) + surgery.location == BODY_ZONE_R_ARM ? target.put_in_r_hand(new_arm) : target.put_in_l_hand(new_arm) return 1 else if(istype(tool, /obj/item/melee/synthetic_arm_blade)) var/obj/item/melee/arm_blade/new_arm = new(target,TRUE,TRUE) - target_zone == BODY_ZONE_R_ARM ? target.put_in_r_hand(new_arm) : target.put_in_l_hand(new_arm) + surgery.location == BODY_ZONE_R_ARM ? target.put_in_r_hand(new_arm) : target.put_in_l_hand(new_arm) return 1 diff --git a/code/modules/surgery/remove_embedded_object.dm b/code/modules/surgery/remove_embedded_object.dm index 29c3ef30d208a..858946b3e9d92 100644 --- a/code/modules/surgery/remove_embedded_object.dm +++ b/code/modules/surgery/remove_embedded_object.dm @@ -12,18 +12,18 @@ var/obj/item/bodypart/L = null -/datum/surgery_step/remove_object/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) +/datum/surgery_step/remove_object/preop(mob/user, mob/living/carbon/target, obj/item/tool, datum/surgery/surgery) L = surgery.operated_bodypart if(L) - user.visible_message("[user] looks for objects embedded in [target]'s [parse_zone(user.zone_selected)].", "You look for objects embedded in [target]'s [parse_zone(user.zone_selected)]...") - display_results(user, target, "You look for objects embedded in [target]'s [parse_zone(user.zone_selected)]...", - "[user] looks for objects embedded in [target]'s [parse_zone(user.zone_selected)].", - "[user] looks for something in [target]'s [parse_zone(user.zone_selected)].") + user.visible_message("[user] looks for objects embedded in [target]'s [parse_zone(surgery.location)].", "You look for objects embedded in [target]'s [parse_zone(surgery.location)]...") + display_results(user, target, "You look for objects embedded in [target]'s [parse_zone(surgery.location)]...", + "[user] looks for objects embedded in [target]'s [parse_zone(surgery.location)].", + "[user] looks for something in [target]'s [parse_zone(surgery.location)].") else - user.visible_message("[user] looks for [target]'s [parse_zone(user.zone_selected)].", "You look for [target]'s [parse_zone(user.zone_selected)]...") + user.visible_message("[user] looks for [target]'s [parse_zone(surgery.location)].", "You look for [target]'s [parse_zone(surgery.location)]...") -/datum/surgery_step/remove_object/success(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) +/datum/surgery_step/remove_object/success(mob/user, mob/living/carbon/target, obj/item/tool, datum/surgery/surgery) if(L) if(ishuman(target)) var/mob/living/carbon/human/H = target @@ -40,6 +40,6 @@ to_chat(user, "You find no objects embedded in [H]'s [L]!") else - to_chat(user, "You can't find [target]'s [parse_zone(user.zone_selected)], let alone any objects embedded in it!") + to_chat(user, "You can't find [target]'s [parse_zone(surgery.location)], let alone any objects embedded in it!") return 1 diff --git a/code/modules/surgery/surgery.dm b/code/modules/surgery/surgery.dm index d829cc8afff28..51256efd318fe 100644 --- a/code/modules/surgery/surgery.dm +++ b/code/modules/surgery/surgery.dm @@ -43,7 +43,7 @@ return ..() -/datum/surgery/proc/can_start(mob/user, mob/living/carbon/target) //FALSE to not show in list +/datum/surgery/proc/can_start(mob/user, mob/living/carbon/target, target_zone) //FALSE to not show in list . = TRUE if(replaced_by == /datum/surgery) return FALSE @@ -119,7 +119,7 @@ var/datum/surgery_step/S = get_surgery_step() if(S) - if(S.try_op(user, target, user.zone_selected, user.get_active_held_item(), src, try_to_fail)) + if(S.try_op(user, target, user.get_active_held_item(), src, try_to_fail)) return TRUE if(iscyborg(user) && user.a_intent != INTENT_HARM) //to save asimov borgs a LOT of heartache return TRUE @@ -145,7 +145,7 @@ name = "advanced surgery" requires_tech = TRUE -/datum/surgery/advanced/can_start(mob/user, mob/living/carbon/target) +/datum/surgery/advanced/can_start(mob/user, mob/living/carbon/target, target_zone) if(!..()) return FALSE // True surgeons (like abductor scientists) need no instructions diff --git a/code/modules/surgery/surgery_step.dm b/code/modules/surgery/surgery_step.dm index 3f471cbc32ee5..bd23bf935b0db 100644 --- a/code/modules/surgery/surgery_step.dm +++ b/code/modules/surgery/surgery_step.dm @@ -12,7 +12,7 @@ var/success_sound //Sound played if the step succeeded var/failure_sound //Sound played if the step fails -/datum/surgery_step/proc/try_op(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery, try_to_fail = FALSE) +/datum/surgery_step/proc/try_op(mob/user, mob/living/carbon/target, obj/item/tool, datum/surgery/surgery, try_to_fail = FALSE) var/success = FALSE if(accept_hand) if(!tool) @@ -40,18 +40,17 @@ break if(success) - if(target_zone == surgery.location) - if(get_location_accessible(target, target_zone) || surgery.ignore_clothes) - return initiate(user, target, target_zone, tool, surgery, try_to_fail) - else - to_chat(user, "You need to expose [target]'s [parse_zone(target_zone)] to perform surgery on it!") - return TRUE //returns TRUE so we don't stab the guy in the dick or wherever. + if(get_location_accessible(target, surgery.location) || surgery.ignore_clothes) + return initiate(user, target, tool, surgery, try_to_fail) + else + to_chat(user, "You need to expose [target]'s [parse_zone(surgery.location)] to perform surgery on it!") + return TRUE //returns TRUE so we don't stab the guy in the dick or wherever. if(repeatable) var/datum/surgery_step/next_step = surgery.get_surgery_next_step() if(next_step) surgery.status++ - if(next_step.try_op(user, target, user.zone_selected, user.get_active_held_item(), surgery)) + if(next_step.try_op(user, target, user.get_active_held_item(), surgery)) return TRUE else surgery.status-- @@ -83,17 +82,17 @@ return max(propability + sleepbonus - selfpenalty, 0.1) -/datum/surgery_step/proc/initiate(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery, try_to_fail = FALSE) +/datum/surgery_step/proc/initiate(mob/user, mob/living/carbon/target, obj/item/tool, datum/surgery/surgery, try_to_fail = FALSE) surgery.step_in_progress = TRUE var/speed_mod = 1 var/fail_prob = 0//100 - fail_prob = success_prob var/advance = FALSE - if(preop(user, target, target_zone, tool, surgery) == -1) + if(preop(user, target, tool, surgery) == -1) surgery.step_in_progress = FALSE return FALSE - play_preop_sound(user, target, target_zone, tool, surgery) // Here because most steps overwrite preop + play_preop_sound(user, target, tool, surgery) // Here because most steps overwrite preop if(tool) speed_mod = tool.toolspeed @@ -114,10 +113,11 @@ if((prob(100 - fail_prob) || iscyborg(user)) && chem_check(target) && !try_to_fail) - if(success(user, target, target_zone, tool, surgery)) - play_success_sound(user, target, target_zone, tool, surgery) + if(success(user, target, tool, surgery)) + play_success_sound(user, target, tool, surgery) advance = TRUE - else if(failure(user, target, target_zone, tool, surgery, fail_prob)) + else if(failure(user, target, tool, surgery, fail_prob)) + play_failure_sound(user, target, tool, surgery) advance = TRUE if(advance && !repeatable) @@ -128,12 +128,12 @@ surgery.step_in_progress = FALSE return advance -/datum/surgery_step/proc/preop(mob/user, mob/living/target, target_zone, obj/item/tool, datum/surgery/surgery) +/datum/surgery_step/proc/preop(mob/user, mob/living/target, obj/item/tool, datum/surgery/surgery) display_results(user, target, "You begin to perform surgery on [target]...", "[user] begins to perform surgery on [target].", "[user] begins to perform surgery on [target].") -/datum/surgery_step/proc/play_preop_sound(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) +/datum/surgery_step/proc/play_preop_sound(mob/user, mob/living/carbon/target, obj/item/tool, datum/surgery/surgery) if(!preop_sound) return var/sound_file_use @@ -146,18 +146,18 @@ sound_file_use = preop_sound playsound(get_turf(target), sound_file_use, 75, TRUE, falloff_exponent = 12, falloff_distance = 1) -/datum/surgery_step/proc/success(mob/user, mob/living/target, target_zone, obj/item/tool, datum/surgery/surgery, default_display_results = TRUE) +/datum/surgery_step/proc/success(mob/user, mob/living/target, obj/item/tool, datum/surgery/surgery, default_display_results = TRUE) display_results(user, target, "You succeed.", "[user] succeeds.", "[user] finishes.") return TRUE -/datum/surgery_step/proc/play_success_sound(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) +/datum/surgery_step/proc/play_success_sound(mob/user, mob/living/carbon/target, obj/item/tool, datum/surgery/surgery) if(!success_sound) return playsound(get_turf(target), success_sound, 75, TRUE, falloff_exponent = 12, falloff_distance = 1) -/datum/surgery_step/proc/failure(mob/user, mob/living/target, target_zone, obj/item/tool, datum/surgery/surgery, fail_prob = 0) +/datum/surgery_step/proc/failure(mob/user, mob/living/target, obj/item/tool, datum/surgery/surgery, fail_prob = 0) var/screwedmessage = "" switch(fail_prob) if(0 to 24) @@ -172,7 +172,7 @@ "[user] finishes.", TRUE) //By default the patient will notice if the wrong thing has been cut return FALSE -/datum/surgery_step/proc/play_failure_sound(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) +/datum/surgery_step/proc/play_failure_sound(mob/user, mob/living/carbon/target, obj/item/tool, datum/surgery/surgery) if(!failure_sound) return playsound(get_turf(target), failure_sound, 75, TRUE, falloff_exponent = 12, falloff_distance = 1) diff --git a/code/modules/surgery/tools.dm b/code/modules/surgery/tools.dm index a37abc9c01583..dd245beb64fa9 100644 --- a/code/modules/surgery/tools.dm +++ b/code/modules/surgery/tools.dm @@ -233,8 +233,7 @@ attack_verb = list("slapped") /obj/item/surgical_drapes/attack(mob/living/M, mob/user) - if(!attempt_initiate_surgery(src, M, user)) - ..() + attempt_initiate_surgery(src, M, user) /obj/item/organ_storage //allows medical cyborgs to manipulate organs without hands name = "organ storage bag" diff --git a/code/modules/zombie/items.dm b/code/modules/zombie/items.dm index 675ec355535d8..602755735e9f0 100644 --- a/code/modules/zombie/items.dm +++ b/code/modules/zombie/items.dm @@ -34,7 +34,7 @@ else if(isliving(target)) if(ishuman(target)) var/mob/living/carbon/human/H = target - var/flesh_wound = ran_zone(user.zone_selected) + var/flesh_wound = ran_zone(user.get_combat_bodyzone(target)) if(H.check_shields(src, 0)) return if(prob(100-H.getarmor(flesh_wound, MELEE, armour_penetration))) diff --git a/icons/mob/screen_gen.dmi b/icons/mob/screen_gen.dmi index 712c6d1b2c2b9ceed2223ea82ebc935135ac9382..1ead9f6d2309db36559d9fd15cd1be37f795364a 100644 GIT binary patch literal 88715 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

lNp7{~OP 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 literal 115675 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%0A$DK_ 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

hTF4&4 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 literal 0 HcmV?d00001 diff --git a/tgui/packages/tgui/interfaces/PreferencesMenu/KeybindingsPage.tsx b/tgui/packages/tgui/interfaces/PreferencesMenu/KeybindingsPage.tsx index 0d24e6904e16e..256a27c464fcb 100644 --- a/tgui/packages/tgui/interfaces/PreferencesMenu/KeybindingsPage.tsx +++ b/tgui/packages/tgui/interfaces/PreferencesMenu/KeybindingsPage.tsx @@ -18,6 +18,8 @@ const CATEGORY_SCALES = { type Keybinding = { name: string; description?: string; + pref_key?: string; + pref_value?: string; }; type Keybindings = Record>; @@ -416,6 +418,7 @@ export class KeybindingsPage extends Component<{}, KeybindingsPageState> { ); } const { act } = useBackend(this.context); + const { data } = useBackend(this.context); const keybindings = this.state?.keybindings; if (!keybindings) { @@ -439,37 +442,44 @@ export class KeybindingsPage extends Component<{}, KeybindingsPageState> { return [ category, - {sortKeybindings(Object.entries(keybindings)).map(([keybindingId, keybinding]) => { - const keys = this.state.selectedKeybindings![keybindingId] || []; - - const name = ( - - - - ); - - return ( - - - {name} - - {range(0, 3).map((key) => ( - - + {sortKeybindings(Object.entries(keybindings)) + .filter(([keybindingId, keybinding]) => { + return ( + !keybinding.pref_key || + data.character_preferences.game_preferences[keybinding.pref_key] === keybinding.pref_value + ); + }) + .map(([keybindingId, keybinding]) => { + const keys = this.state.selectedKeybindings![keybindingId] || []; + + const name = ( + + + + ); + + return ( + + + {name} + + {range(0, 3).map((key) => ( + + + + ))} + + + - ))} - - - - - - - ); - })} + + + ); + })} , ]; })} diff --git a/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/game_preferences/hotkeys.tsx b/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/game_preferences/hotkeys.tsx index 04ed6c04558f7..ce4546fef5144 100644 --- a/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/game_preferences/hotkeys.tsx +++ b/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/game_preferences/hotkeys.tsx @@ -1,4 +1,4 @@ -import { CheckboxInputInverse, FeatureToggle } from '../base'; +import { CheckboxInputInverse, FeatureButtonedDropdownInput, FeatureToggle, Feature } from '../base'; export const hotkeys: FeatureToggle = { name: 'Classic hotkeys', @@ -6,3 +6,11 @@ export const hotkeys: FeatureToggle = { description: 'When enabled, will revert to the legacy hotkeys, using the input bar rather than popups.', component: CheckboxInputInverse, }; + +export const zone_select: Feature = { + name: 'Bodyzone Targeting Mode', + category: 'GAMEPLAY', + description: + 'When set to simplified, the bodyzone system will be replaced with a grouped system where the bodyparts are put into 3 groups: Arms, Legs and Body/Chest. This setting is recommended if you do not have a numpad or want a simpler experience', + component: FeatureButtonedDropdownInput, +};