Hardsuit bugfixes (#22848)

The closest thing to a balance change is the hardsuit boots being
deployable without the chestpiece again.

The SFX can be moved with the recent update to armour sounds if someone
wants, but the slowdown is a heavy enough penalty to discourage it.

- bugfix: "Fixed the Retract All Hardsuit Parts verb, by making hardsuit
boots retractable with the chestpiece deployed, at a heavy slowdown"
- bugfix: "Fixed the stealth system module not decloaking when the user
fires a gun or hits a mob."
- bugfix: "Fixed being able to instantly remove your hardsuit if it had
a storage module in it."
- bugfix: "Fixed mounted energy guns being stuck in taser mode. Also
extends support to other guns with multiple firemods."
  - bugfix: "Fixed most hardsuit modules not having an on-mob sprite."
- bugfix: "Fixed synthetic chargers not charging the hardsuit, if the
wearer was an IPC."
- bugfix: "Fixed the hardsuit UI not updating when toggling jetpack
stabalizers."
- bugfix: "Fixed the advanced hacking tool searching the wearer's entire
contents to see if it had been dropped every tick."
This commit is contained in:
FenodyreeAv
2026-07-17 11:32:03 +00:00
committed by GitHub
parent 53a02f5776
commit affab40530
12 changed files with 144 additions and 64 deletions
@@ -21,15 +21,20 @@
/obj/item/storage/internal/mob_can_equip(M, slot, disable_warning = FALSE, bypass_blocked_check = FALSE, is_overlay_check = FALSE)
return 0 //make sure this is never picked up
//Helper procs to cleanly implement internal storages - storage items that provide inventory slots for other items.
//These procs are completely optional, it is up to the master item to decide when it's storage get's opened by calling open()
//However they are helpful for allowing the master item to pretend it is a storage item itself.
//If you are using these you will probably want to override attackby() as well.
//See /obj/item/clothing/suit/storage for an example.
//items that use internal storage have the option of calling this to emulate default storage MouseDrop behaviour.
//returns 1 if the master item's parent's MouseDrop() should be called, 0 otherwise. It's strange, but no other way of
//doing it without the ability to call another proc's parent, really.
/**
* Helper procs to cleanly implement internal storages - storage items that provide inventory slots for other items.
* These procs are completely optional, it is up to the master item to decide when it's storage get's opened by calling open()
*
* However they are helpful for allowing the master item to pretend it is a storage item itself.
*
* If you are using these you will probably want to override attackby() as well.
* See /obj/item/clothing/suit/storage for an example.
*
* items that use internal storage have the option of calling this to emulate default storage MouseDrop behaviour.
*
* Returns 1 if the master item's parent's MouseDrop() should be called, 0 otherwise.
* It's strange, but no other way of doing it without the ability to call another proc's parent, really.
*/
/obj/item/storage/internal/proc/handle_mousedrop(mob/user as mob, obj/over_object as obj)
if (ishuman(user) || issmall(user)) //so monkeys can take off their backpacks -- Urist
@@ -48,20 +53,22 @@
return 0
if (!( user.restrained() ) && !( user.stat ))
if(!user.prepare_for_slotmove(real_master_item)) //Prevents removing hardsuits when they have storage modules in them.
return 0
switch(over_object.name)
if("right hand")
user.u_equip(real_master_item)
user.equip_to_slot_if_possible(real_master_item, slot_r_hand)
if("left hand")
user.u_equip(real_master_item)
user.equip_to_slot_if_possible(real_master_item, slot_l_hand)
real_master_item.add_fingerprint(user)
return 0
return 0
//items that use internal storage have the option of calling this to emulate default storage attack_hand behaviour.
//returns 1 if the master item's parent's attack_hand() should be called, 0 otherwise.
//It's strange, but no other way of doing it without the ability to call another proc's parent, really.
/**
* items that use internal storage have the option of calling this to emulate default storage attack_hand behaviour.
* returns 1 if the master item's parent's attack_hand() should be called, 0 otherwise.
* It's strange, but no other way of doing it without the ability to call another proc's parent, really.
*/
/obj/item/storage/internal/proc/handle_attack_hand(mob/user as mob)
var/obj/item/real_master_item = special_master_item_handling ? get_master_item() : master_item
@@ -135,26 +135,26 @@
if(ishuman(occupant))
var/mob/living/carbon/human/H = occupant
var/obj/item/organ/internal/machine/power_core/IC = H.internal_organs_by_name[BP_CELL]
if(istype(IC))
target = IC.cell
// Different reactor types have different external recharge speeds.
if(isipc(H))
reactor = H.internal_organs_by_name[BP_REACTOR]
if(!istype(reactor))
return
if((!target || target.percent() > 98) && istype(H.back, /obj/item/rig))
if((!target || target.percent() > 99) && istype(H.back, /obj/item/rig))
var/obj/item/rig/R = H.back
if(R.cell && !R.cell.fully_charged())
target = R.cell
if(!target)
var/obj/item/organ/internal/machine/power_core/IC = H.internal_organs_by_name[BP_CELL]
if(istype(IC))
target = IC.cell
if(target && !target.fully_charged())
var/diff = min(target.maxcharge - target.charge, charging_power * CELLRATE * seconds_per_tick) // Capped by charging_power / tick
var/charge_used = cell.use(diff)
if(!reactor) // not an IPC
if(!reactor || target.percent() < 99) // not an IPC
target.give(charge_used * charging_efficiency)
else
reactor.generate_power(charge_used * charging_efficiency * reactor.external_charge_multiplier)