Prosthetics Fixes (#23079)

* Fixed robotic and mechanically assisted organs retaining or recovering
from EMP surge damage incorrectly.
* Fixed several prosthetic limb interactions causing inappropriate pain,
screams, blood, or organic surgery sounds.

For the various tick_surge_damage procs with 'this is intentional' being
removed, it's because it was moved to the base level proc which always
(generally) fires, which caused double-ticks.
<img width="1316" height="488" alt="image"
src="https://github.com/user-attachments/assets/99c97ad8-3bbe-4131-a6fd-86dea23b3239"
/>

AI usage disclosure: The code for the tweaks here was created using GPT
5.6 Sol.
This commit is contained in:
Geeves
2026-08-27 22:40:14 +00:00
committed by GitHub
parent 1dab700b39
commit d5aff0fe4d
10 changed files with 34 additions and 24 deletions
+4 -3
View File
@@ -1125,7 +1125,7 @@
/mob/proc/embedded_needs_process()
return (embedded.len > 0)
/mob/proc/remove_implant(obj/item/implant, surgical_removal = FALSE)
/mob/proc/remove_implant(obj/item/implant, surgical_removal = FALSE, obj/item/organ/external/affected)
if(!LAZYLEN(get_visible_implants(0))) //Yanking out last object - removing verb.
remove_verb(src, /mob/proc/yank_out_object)
for(var/obj/item/O in pinned)
@@ -1134,7 +1134,8 @@
if(!length(pinned))
anchored = 0
implant.dropInto(loc)
implant.add_blood(src)
if(!affected || !BP_IS_ROBOTIC(affected))
implant.add_blood(src)
implant.update_icon()
if(istype(implant,/obj/item/implant))
var/obj/item/implant/imp = implant
@@ -1157,7 +1158,7 @@
apply_damage((implant.w_class * 7), DAMAGE_BRUTE, affected)
if(!BP_IS_ROBOTIC(affected) && prob(implant.w_class * 5) && affected.sever_artery()) //I'M SO ANEMIC I COULD JUST -DIE-.
custom_pain("Something tears wetly in your [affected.name] as [implant] is pulled free!", 50, affecting = affected)
. = ..()
. = ..(implant, surgical_removal, affected)
/mob/proc/yank_out_object()
set category = "Object"
@@ -165,7 +165,6 @@
take_damage(owner.chem_effects[toxin_type] * seconds_per_tick)
handle_regeneration(seconds_per_tick)
tick_surge_damage(seconds_per_tick) //Yes, this is intentional.
/obj/item/organ/internal/proc/handle_regeneration(seconds_per_tick)
SHOULD_CALL_PARENT(TRUE)
+7 -2
View File
@@ -181,7 +181,7 @@ INITIALIZE_IMMEDIATE(/obj/item/organ)
if (is_immune)
germ_level = 0
if((BP_IS_ROBOTIC(src) || robotic >= ROBOTIC_MECHANICAL) && surge_damage)
if(surge_damage)
tick_surge_damage(seconds_per_tick)
if(!owner)
@@ -231,6 +231,8 @@ INITIALIZE_IMMEDIATE(/obj/item/organ)
do_surge_effects()
surge_damage = max(0, surge_damage - (surge_recovery_per_second * seconds_per_tick))
if(!surge_damage)
clear_surge_effects()
return surge_damage
/obj/item/organ/proc/do_surge_effects()
@@ -294,6 +296,8 @@ INITIALIZE_IMMEDIATE(/obj/item/organ)
/obj/item/organ/proc/rejuvenate()
damage = 0
surge_damage = 0
clear_surge_effects()
/obj/item/organ/proc/heal_damage(amount)
if(can_recover())
@@ -447,9 +451,10 @@ INITIALIZE_IMMEDIATE(/obj/item/organ)
#define MAXIMUM_SURGE_DAMAGE 100
/obj/item/organ/proc/take_surge_damage(var/surge)
if(!BP_IS_ROBOTIC(src))
if(!(status & ORGAN_ASSISTED))
return //We check earlier, but just to make sure.
START_PROCESSING(SSprocessing, src)
surge_damage = clamp(0, surge + surge_damage, MAXIMUM_SURGE_DAMAGE) //We want X seconds at most of hampered movement or what have you.
/**
+2 -4
View File
@@ -782,6 +782,8 @@ This function completely restores a damaged organ to perfect condition.
/obj/item/organ/external/proc/need_process()
if(BP_IS_ROBOTIC(src))
return surge_damage
if(surge_damage)
return TRUE
if(get_pain() || status & (ORGAN_CUT_AWAY|ORGAN_BLEEDING|ORGAN_BROKEN|ORGAN_DESTROYED|ORGAN_SPLINTED|ORGAN_DEAD|ORGAN_MUTATED|ORGAN_ARTERY_CUT) || brute_dam || burn_dam)
return TRUE
if(last_dam != brute_dam + burn_dam) // Process when we are fully healed up.
@@ -813,9 +815,6 @@ This function completely restores a damaged organ to perfect condition.
if(!(status & ORGAN_BROKEN))
perma_injury = 0
if(surge_damage && (status & ORGAN_ASSISTED))
tick_surge_damage(seconds_per_tick) //Yes, this being here is intentional since this proc does not call ..() unless the owner is null.
//Infections
update_germs()
@@ -823,7 +822,6 @@ This function completely restores a damaged organ to perfect condition.
check_rigsplints()
/obj/item/organ/external/do_surge_effects()
START_PROCESSING(SSprocessing, src)
if(prob(surge_damage))
owner.custom_pain("The artificial nerves in your [name] scream out in pain!", surge_damage/6)
+1 -1
View File
@@ -7,7 +7,7 @@
// power decides how much painkillers will stop the message
// force means it ignores anti-spam timer
/mob/living/carbon/proc/custom_pain(var/message, var/power, var/force, var/obj/item/organ/external/affecting, var/nohalloss)
if(!message || stat || !can_feel_pain() || chem_effects[CE_PAINKILLER] > power)
if(!message || stat || !can_feel_pain() || (affecting && !ORGAN_CAN_FEEL_PAIN(affecting)) || chem_effects[CE_PAINKILLER] > power)
return 0
power -= chem_effects[CE_PAINKILLER]/2 //Take the edge off.
+6 -7
View File
@@ -60,7 +60,7 @@
var/obj/item/organ/external/affected = target.get_organ(target_zone)
user.visible_message("[user] starts making some space inside [target]'s [get_cavity(affected)] cavity with \the [tool].", \
"You start making some space inside [target]'s [get_cavity(affected)] cavity with \the [tool]." )
target.custom_pain("The pain in your chest is living hell!",1)
target.custom_pain("The pain in your chest is living hell!", 1, affecting = affected)
affected.cavity = CAVITY_OPEN
..()
@@ -91,7 +91,7 @@
var/obj/item/organ/external/affected = target.get_organ(target_zone)
user.visible_message("<b>[user]</b> starts mending [target]'s [get_cavity(affected)] cavity wall with \the [tool].", \
"You start mending [target]'s [get_cavity(affected)] cavity wall with \the [tool]." )
target.custom_pain("The pain in your chest is living hell!", 75)
target.custom_pain("The pain in your chest is living hell!", 75, affecting = affected)
affected.cavity = CAVITY_CLOSED
..()
@@ -125,8 +125,8 @@
var/obj/item/organ/external/affected = target.get_organ(target_zone)
user.visible_message("<b>[user]</b> starts putting \the [tool] inside [target]'s [get_cavity(affected)] cavity.", \
SPAN_NOTICE("You start putting \the [tool] inside [target]'s [get_cavity(affected)] cavity." ))
target.custom_pain("The pain in your chest is living hell!", 75)
playsound(target.loc, 'sound/effects/squelch1.ogg', 50, 1)
target.custom_pain("The pain in your chest is living hell!", 75, affecting = affected)
playsound(target.loc, BP_IS_ROBOTIC(affected) ? 'sound/items/wrench.ogg' : 'sound/effects/squelch1.ogg', 50, 1)
..()
/singleton/surgery_step/cavity/place_item/end_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
@@ -168,7 +168,7 @@
var/obj/item/organ/external/affected = target.get_organ(target_zone)
user.visible_message("[user] starts poking around inside [target]'s [affected.name] with \the [tool].", \
"You start poking around inside [target]'s [affected.name] with \the [tool]." )
target.custom_pain("The pain in your [affected.name] is living hell!", 50)
target.custom_pain("The pain in your [affected.name] is living hell!", 50, affecting = affected)
..()
/singleton/surgery_step/cavity/implant_removal/end_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
@@ -203,7 +203,7 @@
worm.detach()
worm.leave_host()
playsound(target.loc, 'sound/effects/squelch1.ogg', 50, 1)
playsound(target.loc, BP_IS_ROBOTIC(affected) ? 'sound/items/wrench.ogg' : 'sound/effects/squelch1.ogg', 50, 1)
else
user.visible_message("<b>[user]</b> could not find anything inside [target]'s [affected.name], and pulls \the [tool] out.", \
SPAN_NOTICE("You could not find anything inside [target]'s [affected.name].") )
@@ -214,4 +214,3 @@
user.visible_message(SPAN_WARNING("[user] loses their grip and stabs [target] with \the [tool]!"), SPAN_WARNING("You lose your grip on \the [tool] and stab [target]!"))
affected.sever_artery()
target.apply_damage(25, DAMAGE_BRUTE, target_zone)
+2 -2
View File
@@ -142,7 +142,7 @@
user.visible_message("<b>[user]</b> starts mending the damage to [target]'s [I.name]'s mechanisms.", \
SPAN_NOTICE("You start mending the damage to [target]'s [I.name]'s mechanisms." ))
target.custom_pain("The pain in your [affected.name] is living hell!", 75)
target.custom_pain("The pain in your [affected.name] is living hell!", 75, affecting = affected)
..()
/singleton/surgery_step/internal/fix_organ_robotic/end_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
@@ -383,7 +383,7 @@
var/obj/item/organ/external/affected = target.get_organ(target_zone)
user.visible_message("[user] starts transplanting \the [tool] into [target]'s [affected.name].", \
"You start transplanting \the [tool] into [target]'s [affected.name].")
target.custom_pain("Someone's rooting around in your [affected.name]!", 75)
target.custom_pain("Someone's rooting around in your [affected.name]!", 75, affecting = affected)
..()
/singleton/surgery_step/internal/replace_organ/end_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
+1 -1
View File
@@ -302,7 +302,7 @@
var/obj/item/organ/external/affected = target.get_organ(target_zone)
user.visible_message(SPAN_DANGER("[user] is beginning to amputate [target]'s [affected.name] with \the [tool].") , \
SPAN_DANGER("You begin to cut through [target]'s [affected.amputation_point] with \the [tool]."))
target.custom_pain("Your [affected.amputation_point] is being ripped apart!", 75)
target.custom_pain("Your [affected.amputation_point] is being ripped apart!", 75, affecting = affected)
..()
/singleton/surgery_step/amputate/end_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)