Forces statpanel to update immediately on item move (#22946)

The statpanel (alt-click pickup menu) now updates whenever an item in it
is moved.

The statpanel (alt-click pickup menu) previously only updates on the
subsystem firing, every 2 seconds.
This lets you interact with an object after it's already in the contents
of another object.

Eg. Pick up a bullet, load it into a magazine, pick up that same bullet
from the statpanel, load it again.

This is the source of nearly every inventory bug I've encountered.
(vanishing armor attachments, bullet pile duplication, double-click
triggering grenades, modlaser components being in two guns at the same
time).

It also just feels bad and makes the menu much less usable. (Have I
picked up that item? Which one of these 6 identical icons did I click on
last? Better wait 2 seconds for it to update).


This does NOT cause the panel to update when a new item is added, as
that causes an Icon/Image refresh, which is the expensive part of the
proc. (At least I hope it doesn't)


https://github.com/user-attachments/assets/f396d4bb-d9be-407a-ad66-0cbf8cd4490b
This commit is contained in:
FenodyreeAv
2026-08-08 20:47:58 +00:00
committed by GitHub
parent 65a9f06765
commit ecc8f4db66
2 changed files with 92 additions and 0 deletions
+33
View File
@@ -204,6 +204,14 @@ SUBSYSTEM_DEF(statpanels)
if(!target.obj_window)
target.obj_window = new /datum/object_window_info(target)
var/datum/object_window_info/obj_window = target.obj_window
// Unregister signals for any atoms we used to track but will no longer show
var/list/old_atoms = obj_window.atoms_to_show
if(old_atoms)
for(var/atom as anything in old_atoms)
if(!(atom in atoms_to_display))
obj_window.UnregisterSignal(atom, COMSIG_QDELETING, TYPE_PROC_REF(/datum/object_window_info,viewing_atom_deleted))
obj_window.UnregisterSignal(atom, COMSIG_MOVABLE_MOVED, TYPE_PROC_REF(/datum/object_window_info,item_moved_from_turf))
obj_window.atoms_to_show = atoms_to_display
START_PROCESSING(SSobj_tab_items, obj_window)
refresh_client_obj_view(target)
@@ -248,6 +256,7 @@ SUBSYSTEM_DEF(statpanels)
to_make += turf_item
already_seen[turf_item] = OBJ_IMAGE_LOADING
obj_window.RegisterSignal(turf_item, COMSIG_QDELETING, TYPE_PROC_REF(/datum/object_window_info,viewing_atom_deleted)) // we reset cache if anything in it gets deleted
obj_window.RegisterSignal(turf_item, COMSIG_MOVABLE_MOVED, TYPE_PROC_REF(/datum/object_window_info,item_moved_from_turf)) // we reset cache if anything in it moves
return turf_items
#undef OBJ_IMAGE_LOADING
@@ -338,6 +347,10 @@ SUBSYSTEM_DEF(statpanels)
src.parent = parent
/datum/object_window_info/Destroy(force)
if(atoms_to_show)
for(var/atom as anything in atoms_to_show)
UnregisterSignal(atom, COMSIG_QDELETING, TYPE_PROC_REF(/datum/object_window_info,viewing_atom_deleted))
UnregisterSignal(atom, COMSIG_MOVABLE_MOVED, TYPE_PROC_REF(/datum/object_window_info,item_moved_from_turf))
atoms_to_show = null
atoms_to_images = null
atoms_to_imagify = null
@@ -402,10 +415,30 @@ SUBSYSTEM_DEF(statpanels)
/// We use hard refs cause we'd need a signal for this anyway. Cleaner this way
/datum/object_window_info/proc/viewing_atom_deleted(atom/deleted)
SIGNAL_HANDLER
UnregisterSignal(deleted, COMSIG_QDELETING, TYPE_PROC_REF(/datum/object_window_info,viewing_atom_deleted))
UnregisterSignal(deleted, COMSIG_MOVABLE_MOVED, TYPE_PROC_REF(/datum/object_window_info,item_moved_from_turf))
atoms_to_show -= deleted
atoms_to_imagify -= deleted
atoms_to_images -= deleted
/*
* Immediately removes an item from the statpanel if it is no longer on the turf.
* This is used to immediately update the panel when an item is picked up.
* Prevents many bugs related to items that should no longer be accessible to the player, still being able to be clicked on.
* Eg. Loading a bullet into a magazine, the panel does not update, the bullet can be clicked again, despite already being in the magazine.
* The bullet can then be loaded into the magazine twice.
*/
/datum/object_window_info/proc/item_moved_from_turf(atom/moved)
SIGNAL_HANDLER
if(!actively_tracking)
return
UnregisterSignal(moved, COMSIG_QDELETING, TYPE_PROC_REF(/datum/object_window_info,viewing_atom_deleted))
UnregisterSignal(moved, COMSIG_MOVABLE_MOVED, TYPE_PROC_REF(/datum/object_window_info,item_moved_from_turf))
atoms_to_show -= moved
atoms_to_imagify -= moved
atoms_to_images -= moved
SSstatpanels.refresh_client_obj_view(parent)
/mob/proc/set_listed_turf(turf/new_turf)
listed_turf = new_turf
if(!client)