diff --git a/code/_helpers/unsorted.dm b/code/_helpers/unsorted.dm index 00ad3a0a584..bc7dca1d749 100644 --- a/code/_helpers/unsorted.dm +++ b/code/_helpers/unsorted.dm @@ -1178,12 +1178,19 @@ proc/is_hot(obj/item/W as obj) // check if mob is lying down on something we can operate him on. // The RNG with table/rollerbeds comes into play in do_surgery() so that fail_step() can be used instead. -/proc/can_operate(mob/living/carbon/M) - return M.lying +/proc/can_operate(mob/living/carbon/M, mob/living/user) + . = M.lying + + if(user && M == user && user.allow_self_surgery && user.a_intent == I_HELP) // You can, technically, always operate on yourself after standing still. Inadvised, but you can. + + if(!M.isSynthetic()) + . = TRUE + + return . // Returns an instance of a valid surgery surface. -/mob/living/proc/get_surgery_surface() - if(!lying) +/mob/living/proc/get_surgery_surface(mob/living/user) + if(!lying && user != src) return null // Not lying down means no surface. var/obj/surface = null for(var/obj/O in loc) // Looks for the best surface. diff --git a/code/_onclick/item_attack.dm b/code/_onclick/item_attack.dm index ddfe6205705..bb31527126b 100644 --- a/code/_onclick/item_attack.dm +++ b/code/_onclick/item_attack.dm @@ -49,7 +49,7 @@ avoid code duplication. This includes items that may sometimes act as a standard /mob/living/attackby(obj/item/I, mob/user, var/attack_modifier, var/click_parameters) if(!ismob(user)) return 0 - if(can_operate(src) && I.do_surgery(src,user)) + if(can_operate(src, user) && I.do_surgery(src,user)) return 1 if(attempt_vr(src,"vore_attackby",args)) return //VOREStation Add - The vore, of course. return I.attack(src, user, user.zone_sel.selecting, attack_modifier) diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm index 889f5281cb1..09b49505fd4 100644 --- a/code/modules/mob/living/carbon/human/human.dm +++ b/code/modules/mob/living/carbon/human/human.dm @@ -52,6 +52,8 @@ dna.real_name = real_name sync_organ_dna() + verbs |= /mob/living/proc/toggle_selfsurgery + /mob/living/carbon/human/Destroy() human_mob_list -= src for(var/organ in organs) diff --git a/code/modules/mob/living/living_defines.dm b/code/modules/mob/living/living_defines.dm index 4238a56080a..357208114c6 100644 --- a/code/modules/mob/living/living_defines.dm +++ b/code/modules/mob/living/living_defines.dm @@ -73,5 +73,9 @@ var/image/selected_image = null // Used for buildmode AI control stuff. +<<<<<<< HEAD var/inventory_panel_type = /datum/inventory_panel var/datum/inventory_panel/inventory_panel +======= + var/allow_self_surgery = FALSE // Used to determine if the mob can perform surgery on itself. +>>>>>>> b411c75... Self-Surgery (#7671) diff --git a/code/modules/mob/living/living_powers.dm b/code/modules/mob/living/living_powers.dm index 787dd313619..2125f2679e3 100644 --- a/code/modules/mob/living/living_powers.dm +++ b/code/modules/mob/living/living_powers.dm @@ -20,3 +20,13 @@ layer = HIDING_LAYER //Just above cables with their 2.44 plane = OBJ_PLANE to_chat(src,"You are now hiding.") + +/mob/living/proc/toggle_selfsurgery() + set name = "Allow Self Surgery" + set desc = "Toggles the 'safeties' on self-surgery, allowing you to do so." + set category = "Object" + + allow_self_surgery = !allow_self_surgery + + to_chat(usr, "You will [allow_self_surgery ? "now" : "no longer"] attempt to operate upon yourself.") + log_admin("DEBUG \[[world.timeofday]\]: [src.ckey ? "[src.name]:([src.ckey])" : "[src.name]"] has [allow_self_surgery ? "Enabled" : "Disabled"] self surgery.") diff --git a/code/modules/surgery/surgery.dm b/code/modules/surgery/surgery.dm index e6e4554090f..24806225c88 100644 --- a/code/modules/surgery/surgery.dm +++ b/code/modules/surgery/surgery.dm @@ -121,8 +121,8 @@ /obj/item/proc/can_do_surgery(mob/living/carbon/M, mob/living/user) - if(M == user) - return 0 +// if(M == user) +// return 0 if(!ishuman(M)) return 1 @@ -139,11 +139,19 @@ if(zone in M.op_stage.in_progress) //Can't operate on someone repeatedly. to_chat(user, "You can't operate on this area while surgery is already in progress.") return 1 + for(var/datum/surgery_step/S in surgery_steps) //check if tool is right or close enough and if this step is possible if(S.tool_quality(src)) var/step_is_valid = S.can_use(user, M, zone, src) if(step_is_valid && S.is_valid_target(M)) + + if(M == user) // Once we determine if we can actually do a step at all, give a slight delay to self-surgery to confirm attempts. + to_chat(user, "You focus on attempting to perform surgery upon yourself.") + + if(!do_after(user, 3 SECONDS, M)) + return 0 + if(step_is_valid == SURGERY_FAILURE) // This is a failure that already has a message for failing. return 1 M.op_stage.in_progress += zone @@ -155,7 +163,7 @@ success = FALSE // Bad or no surface may mean failure as well. - var/obj/surface = M.get_surgery_surface() + var/obj/surface = M.get_surgery_surface(user) if(!surface || !prob(surface.surgery_odds)) success = FALSE