diff --git a/code/__DEFINES/subsystems.dm b/code/__DEFINES/subsystems.dm index ff463fb44c6..155a2b16888 100644 --- a/code/__DEFINES/subsystems.dm +++ b/code/__DEFINES/subsystems.dm @@ -198,6 +198,7 @@ #define FIRE_PRIORITY_STATPANEL 390 #define FIRE_PRIORITY_CHAT 400 #define FIRE_PRIORITY_RUNECHAT 410 +#define FIRE_PRIORITY_MOUSE_ENTERED 450 #define FIRE_PRIORITY_OVERLAYS 500 #define FIRE_PRIORITY_EXPLOSIONS 666 #define FIRE_PRIORITY_TIMER 700 diff --git a/code/controllers/subsystem/mouse_entered.dm b/code/controllers/subsystem/mouse_entered.dm new file mode 100644 index 00000000000..6dc8d995a52 --- /dev/null +++ b/code/controllers/subsystem/mouse_entered.dm @@ -0,0 +1,23 @@ +/// Defers MouseEntered inputs to only apply to the most recently hovered over atom in the tick +SUBSYSTEM_DEF(mouse_entered) + name = "MouseEntered" + wait = 1 + flags = SS_NO_INIT | SS_TICKER + priority = FIRE_PRIORITY_MOUSE_ENTERED + runlevels = RUNLEVELS_DEFAULT | RUNLEVEL_LOBBY + + var/list/hovers = list() + +/datum/controller/subsystem/mouse_entered/fire() + for (var/hovering_client in hovers) + var/atom/hovering_atom = hovers[hovering_client] + if (isnull(hovering_atom)) + continue + + hovering_atom.on_mouse_enter(hovering_client) + + // This intentionally runs `= null` and not `-= hovering_client`, as we want to prevent the list from shrinking, + // which could cause problems given the heat of MouseEntered. + // Lummox has teased this for 515: https://www.byond.com/forum/post/2621745 + // ...though you're most likely reading this on BYOND version 600. + hovers[hovering_client] = null diff --git a/code/game/atoms.dm b/code/game/atoms.dm index b12cd643804..73ae564f216 100644 --- a/code/game/atoms.dm +++ b/code/game/atoms.dm @@ -2101,11 +2101,19 @@ return TRUE -//Update the screentip to reflect what we're hoverin over /atom/MouseEntered(location, control, params) - . = ..() + SSmouse_entered.hovers[usr.client] = src + +/// Fired whenever this atom is the most recent to be hovered over in the tick. +/// Preferred over MouseEntered if you do not need information such as the position of the mouse. +/// Especially because this is deferred over a tick, do not trust that `client` is not null. +/atom/proc/on_mouse_enter(client/client) + SHOULD_NOT_SLEEP(TRUE) + + var/mob/user = client?.mob + // Screentips - var/datum/hud/active_hud = usr.hud_used + var/datum/hud/active_hud = user?.hud_used if(active_hud) if(!active_hud.screentips_enabled || (flags_1 & NO_SCREENTIPS_1)) active_hud.screentip_text.maptext = "" diff --git a/code/modules/client/client_procs.dm b/code/modules/client/client_procs.dm index 9588a786128..a1bf1831fe3 100644 --- a/code/modules/client/client_procs.dm +++ b/code/modules/client/client_procs.dm @@ -548,6 +548,7 @@ GLOBAL_LIST_INIT(blacklisted_builds, list( active_mousedown_item = null SSambience.remove_ambience_client(src) + SSmouse_entered.hovers -= src QDEL_NULL(view_size) QDEL_NULL(void) QDEL_NULL(tooltips) diff --git a/tgstation.dme b/tgstation.dme index 2b799411731..6151bead8ad 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -486,6 +486,7 @@ #include "code\controllers\subsystem\minor_mapping.dm" #include "code\controllers\subsystem\mobs.dm" #include "code\controllers\subsystem\moods.dm" +#include "code\controllers\subsystem\mouse_entered.dm" #include "code\controllers\subsystem\nightshift.dm" #include "code\controllers\subsystem\npcpool.dm" #include "code\controllers\subsystem\overlays.dm"