Fix implant removal bug that allowed you to remove them from a mob multiple times. (#92913)

## About The Pull Request

Sets `implant` to `null` in
`/datum/surgery_step/extract_implant/success()` after removing it.
Surgery steps are global objects, so the cached implant object would
still exist upon entering `/datum/surgery_step/extract_implant/preop()`.
`preop()` was also changed to set the `implant` member to `null` if no
implant is found, so that the implant state is always valid as soon as
the step is started.

## Why It's Good For The Game

Prevents removing the same implant from a mob several times.

The bug also allowed you to attempt to remove the same implant from a
_different_ mob, which can cause a runtime if the mob does not have an
implants list.

I don't believe this was actually duplicating the implant, however I was
able to get the same implant to appear in multiple implant cases, which
I think were just holding a reference to the same implant.
## Changelog
🆑 sushi
fix: implants can no longer be removed from the same mob (or other
mobs!) multiple times
/🆑
This commit is contained in:
sushi
2025-09-12 00:45:34 +02:00
committed by GitHub
parent 33b7a42622
commit ffd3357f6f
+22 -26
View File
@@ -23,9 +23,7 @@
var/obj/item/implant/implant
/datum/surgery_step/extract_implant/preop(mob/user, mob/living/target, target_zone, obj/item/tool, datum/surgery/surgery)
for(var/obj/item/object in target.implants)
implant = object
break
implant = LAZYACCESS(target.implants, 1)
if(implant)
display_results(
user,
@@ -56,29 +54,27 @@
display_pain(target, "You can feel your [implant.name] pulled out of you!")
implant.removed(target)
if (QDELETED(implant))
return ..()
var/obj/item/implantcase/case
for(var/obj/item/implantcase/implant_case in user.held_items)
case = implant_case
break
if(!case)
case = locate(/obj/item/implantcase) in get_turf(target)
if(case && !case.imp)
case.imp = implant
implant.forceMove(case)
case.update_appearance()
display_results(
user,
target,
span_notice("You place [implant] into [case]."),
span_notice("[user] places [implant] into [case]!"),
span_notice("[user] places it into [case]!"),
)
else
qdel(implant)
if (!QDELETED(implant))
var/obj/item/implantcase/case
for(var/obj/item/implantcase/implant_case in user.held_items)
case = implant_case
break
if(!case)
case = locate(/obj/item/implantcase) in get_turf(target)
if(case && !case.imp)
case.imp = implant
implant.forceMove(case)
case.update_appearance()
display_results(
user,
target,
span_notice("You place [implant] into [case]."),
span_notice("[user] places [implant] into [case]!"),
span_notice("[user] places it into [case]!"),
)
else
qdel(implant)
implant = null
else
to_chat(user, span_warning("You can't find anything in [target]'s [target_zone]!"))
return ..()