Skip to content

Commit

Permalink
[MIRROR] Fix some shenanigans involving interaction order with wound …
Browse files Browse the repository at this point in the history
…tending [MDB IGNORE] (#25551)

* Fix some shenanigans involving interaction order with wound tending (#80225)

## About The Pull Request

Fixes #80223 . See issue for information about the bug.

This PR fixes it by placing wound tending before parent call but after
surgery.

It also fixes it by rewriting a little bit of medical stack item code to
only block interaction chain when actually healing someone - This is not
necessary with the above fix, but it futureproofs things.

## Changelog

:cl: Melbert
fix: When using an item on a mob, you will always attempt to fix wounds
AFTER surgery, BUT BEFORE the item's own interactions. As an example,
this means using a mesh on a mob will attempt to progress surgery first,
then attempt to fix any burn wounds, then heal burn damage.
/:cl:

* Fix some shenanigans involving interaction order with wound tending

---------

Co-authored-by: MrMelbert <[email protected]>
  • Loading branch information
2 people authored and FFMirrorBot committed Dec 11, 2023
1 parent 5a91c20 commit 7168ac4
Show file tree
Hide file tree
Showing 4 changed files with 57 additions and 22 deletions.
12 changes: 11 additions & 1 deletion code/_onclick/item_attack.dm
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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(..())
Expand Down
56 changes: 43 additions & 13 deletions code/game/objects/items/stacks/medical.dm
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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)
Expand Down
2 changes: 1 addition & 1 deletion code/game/objects/items/tools/weldingtool.dm
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
9 changes: 2 additions & 7 deletions code/modules/mob/living/carbon/carbon.dm
Original file line number Diff line number Diff line change
Expand Up @@ -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))
Expand Down

0 comments on commit 7168ac4

Please sign in to comment.