diff --git a/code/_onclick/item_attack.dm b/code/_onclick/item_attack.dm index 38889db1ea1..745d63b5b94 100644 --- a/code/_onclick/item_attack.dm +++ b/code/_onclick/item_attack.dm @@ -164,6 +164,16 @@ return attacking_item.attack_atom(src, user, params) /mob/living/item_interaction(mob/living/user, obj/item/tool, list/modifiers, is_right_clicking) + // Surgery and such happens very high up in the interaction chain, before parent call + var/attempt_tending = item_tending(user, tool, modifiers) + if(attempt_tending & ITEM_INTERACT_ANY_BLOCKER) + return attempt_tending + + return ..() | attempt_tending + +/// Handles any use of using a surgical tool or item on a mob to tend to them. +/// The sole reason this is a separate proc is so carbons can tend wounds AFTER the check for surgery. +/mob/living/proc/item_tending(mob/living/user, obj/item/tool, list/modifiers) for(var/datum/surgery/operation as anything in surgeries) if(IS_IN_INVALID_SURGICAL_POSITION(src, operation)) continue @@ -172,7 +182,7 @@ if(operation.next_step(user, modifiers)) return ITEM_INTERACT_SUCCESS - return ..() + return NONE /mob/living/attackby(obj/item/attacking_item, mob/living/user, params) if(..()) diff --git a/code/game/objects/items/stacks/medical.dm b/code/game/objects/items/stacks/medical.dm index b9e5ee828fc..9ec5f22746d 100644 --- a/code/game/objects/items/stacks/medical.dm +++ b/code/game/objects/items/stacks/medical.dm @@ -36,8 +36,8 @@ /obj/item/stack/medical/interact_with_atom(atom/interacting_with, mob/living/user) if(!isliving(interacting_with)) return NONE - - try_heal(interacting_with, user) + if(!begin_heal_loop(interacting_with, user)) + return NONE // [ITEM_INTERACT_BLOCKING] would be redundant as we are nobludgeon return ITEM_INTERACT_SUCCESS /obj/item/stack/medical/apply_fantasy_bonuses(bonus) @@ -61,27 +61,57 @@ flesh_regeneration = reset_fantasy_variable("flesh_regeneration", flesh_regeneration) return ..() +/// Used to begin the recursive healing loop. +/// Returns TRUE if we entered the loop, FALSE if we didn't +/obj/item/stack/medical/proc/begin_heal_loop(mob/living/patient, mob/user) + if(!can_heal(patient, user)) + return FALSE + + INVOKE_ASYNC(src, PROC_REF(try_heal), patient, user) + return TRUE + +/// Checks if the passed patient can be healed by the passed user +/obj/item/stack/medical/proc/can_heal(mob/living/patient, mob/user) + return patient.try_inject(user, injection_flags = INJECT_TRY_SHOW_ERROR_MESSAGE) /// In which we print the message that we're starting to heal someone, then we try healing them. Does the do_after whether or not it can actually succeed on a targeted mob /obj/item/stack/medical/proc/try_heal(mob/living/patient, mob/user, silent = FALSE) - if(!patient.try_inject(user, injection_flags = INJECT_TRY_SHOW_ERROR_MESSAGE)) - return if(patient == user) if(!silent) - user.visible_message(span_notice("[user] starts to apply [src] on [user.p_them()]self..."), span_notice("You begin applying [src] on yourself...")) - if(!do_after(user, self_delay, patient, extra_checks=CALLBACK(patient, TYPE_PROC_REF(/mob/living, try_inject), user, null, INJECT_TRY_SHOW_ERROR_MESSAGE))) + user.visible_message( + span_notice("[user] starts to apply [src] on [user.p_them()]self..."), + span_notice("You begin applying [src] on yourself..."), + ) + if(!do_after( + user, + self_delay, + patient, + extra_checks = CALLBACK(src, PROC_REF(can_heal), patient, user), + )) return + else if(other_delay) if(!silent) - user.visible_message(span_notice("[user] starts to apply [src] on [patient]."), span_notice("You begin applying [src] on [patient]...")) - if(!do_after(user, other_delay, patient, extra_checks=CALLBACK(patient, TYPE_PROC_REF(/mob/living, try_inject), user, null, INJECT_TRY_SHOW_ERROR_MESSAGE))) + user.visible_message( + span_notice("[user] starts to apply [src] on [patient]."), + span_notice("You begin applying [src] on [patient]..."), + ) + if(!do_after( + user, + other_delay, + patient, + extra_checks = CALLBACK(src, PROC_REF(can_heal), patient, user), + )) return - if(heal(patient, user)) - log_combat(user, patient, "healed", src.name) - use(1) - if(repeating && amount > 0) - try_heal(patient, user, TRUE) + if(!heal(patient, user)) + return + log_combat(user, patient, "healed", name) + if(!use(1) || !repeating || amount <= 0) + return + if(!can_heal(patient, user)) + return + try_heal(patient, user, silent = TRUE) /// Apply the actual effects of the healing if it's a simple animal, goes to [/obj/item/stack/medical/proc/heal_carbon] if it's a carbon, returns TRUE if it works, FALSE if it doesn't /obj/item/stack/medical/proc/heal(mob/living/patient, mob/user) diff --git a/code/game/objects/items/tools/weldingtool.dm b/code/game/objects/items/tools/weldingtool.dm index 53c42ed35ab..e09beadd5af 100644 --- a/code/game/objects/items/tools/weldingtool.dm +++ b/code/game/objects/items/tools/weldingtool.dm @@ -143,7 +143,7 @@ var/mob/living/carbon/human/attacked_humanoid = interacting_with var/obj/item/bodypart/affecting = attacked_humanoid.get_bodypart(check_zone(user.zone_selected)) if(isnull(affecting) || !IS_ROBOTIC_LIMB(affecting)) - return ITEM_INTERACT_BLOCKING + return NONE if(!use_tool(attacked_humanoid, user, 0, volume=50, amount=1)) return ITEM_INTERACT_BLOCKING diff --git a/code/modules/mob/living/carbon/carbon.dm b/code/modules/mob/living/carbon/carbon.dm index abcf6dd43a2..a95ef30426f 100644 --- a/code/modules/mob/living/carbon/carbon.dm +++ b/code/modules/mob/living/carbon/carbon.dm @@ -28,14 +28,9 @@ QDEL_NULL(dna) GLOB.carbon_list -= src -/mob/living/carbon/item_interaction(mob/living/user, obj/item/tool, list/modifiers, is_right_clicking) +/mob/living/carbon/item_tending(mob/living/user, obj/item/tool, list/modifiers) . = ..() - if(. & ITEM_INTERACT_SUCCESS) - return . - - if(!length(all_wounds)) - return . - if(user.combat_mode && user != src) + if(. & ITEM_INTERACT_ANY_BLOCKER) return . for(var/datum/wound/wound as anything in shuffle(all_wounds))