diff --git a/code/_onclick/click.dm b/code/_onclick/click.dm
index 620a4ccabc..de06507cff 100644
--- a/code/_onclick/click.dm
+++ b/code/_onclick/click.dm
@@ -62,12 +62,12 @@
A.clicked(src, mods)
return
- if(client && client.click_intercept)
+ if(client && LAZYLEN(client.click_intercepts) > 0)
if(istype(A, /atom/movable/screen/buildmode))
A.clicked(src, mods)
return
- if(check_click_intercept(params,A))
+ if(check_click_intercepts(params,A))
return
// Click handled elsewhere. (These clicks are not affected by the next_move cooldown)
@@ -164,15 +164,15 @@
next_move += 4
UnarmedAttack(A, 1, mods)
-/mob/proc/check_click_intercept(params,A)
- //Client level intercept
- if(client?.click_intercept)
- if(call(client.click_intercept, "InterceptClickOn")(src, params, A))
+/mob/proc/check_click_intercepts(params,A)
+ //Client level intercepts
+ if(client && LAZYLEN(client.click_intercepts) > 0)
+ if(call(client.click_intercepts[length(client.click_intercepts)], "InterceptClickOn")(src, params, A))
return TRUE
- //Mob level intercept
- if(click_intercept)
- if(call(click_intercept, "InterceptClickOn")(src, params, A))
+ //Mob level intercepts
+ if(LAZYLEN(click_intercepts) > 0)
+ if(call(click_intercepts[length(click_intercepts)], "InterceptClickOn")(src, params, A))
return TRUE
return FALSE
diff --git a/code/modules/admin/game_master/extra_buttons/fire_support_menu.dm b/code/modules/admin/game_master/extra_buttons/fire_support_menu.dm
index c3469071f3..fcccd7daa6 100644
--- a/code/modules/admin/game_master/extra_buttons/fire_support_menu.dm
+++ b/code/modules/admin/game_master/extra_buttons/fire_support_menu.dm
@@ -30,7 +30,6 @@
var/mob/mob = user
holder = mob.client
- holder.click_intercept = src
tgui_interact(holder.mob)
///Deletes the mortar when the menu is closed so we dont make a thousand of them.
@@ -69,11 +68,15 @@
return data
-/datum/fire_support_menu/ui_act(action, params)
+/datum/fire_support_menu/ui_act(action, list/params, datum/tgui/ui, datum/ui_state/state)
. = ..()
switch(action)
if("toggle_click_fire_support")
fire_support_click_intercept = !fire_support_click_intercept
+ if(fire_support_click_intercept)
+ LAZYOR(ui.user.client.click_intercepts, src)
+ else
+ LAZYREMOVE(ui.user.client.click_intercepts, src)
return
if("set_selected_ordnance")
selected_ordnance = params["ordnance"]
@@ -83,9 +86,7 @@
return UI_INTERACTIVE
/datum/fire_support_menu/ui_close(mob/user)
- var/client/user_client = user.client
- if(user_client?.click_intercept == src)
- user_client.click_intercept = null
+ LAZYREMOVE(user.client.click_intercepts, src)
fire_support_click_intercept = FALSE
qdel(src)
diff --git a/code/modules/admin/game_master/extra_buttons/rappel_menu.dm b/code/modules/admin/game_master/extra_buttons/rappel_menu.dm
index f35cbae24e..927ec01370 100644
--- a/code/modules/admin/game_master/extra_buttons/rappel_menu.dm
+++ b/code/modules/admin/game_master/extra_buttons/rappel_menu.dm
@@ -46,7 +46,6 @@ GLOBAL_DATUM_INIT(rappel_panel, /datum/rappel_menu, new)
if(!ui)
ui = new(user, src, "GameMasterRappelMenu", "Rappel Menu")
ui.open()
- user.client?.click_intercept = src
/datum/rappel_menu/ui_status(mob/user, datum/ui_state/state)
return UI_INTERACTIVE
@@ -90,12 +89,16 @@ GLOBAL_DATUM_INIT(rappel_panel, /datum/rappel_menu, new)
if("toggle_click_rappel")
rappel_click_intercept = !rappel_click_intercept
+
+ if(rappel_click_intercept)
+ LAZYOR(ui.user.client.click_intercepts, src)
+ else
+ LAZYREMOVE(ui.user.client.click_intercepts, src)
+
return
/datum/rappel_menu/ui_close(mob/user)
- var/client/user_client = user.client
- if(user_client?.click_intercept == src)
- user_client.click_intercept = null
+ LAZYREMOVE(user.client.click_intercepts, src)
rappel_click_intercept = FALSE
diff --git a/code/modules/admin/game_master/game_master.dm b/code/modules/admin/game_master/game_master.dm
index 5370701893..9e6620c016 100644
--- a/code/modules/admin/game_master/game_master.dm
+++ b/code/modules/admin/game_master/game_master.dm
@@ -82,24 +82,15 @@ GLOBAL_VAR_INIT(radio_communication_clarity, 100)
/// If the spawned xeno is an AI in the spawn section
var/spawn_ai = TRUE
- /// If we are currently using the click intercept for the spawn section
- var/spawn_click_intercept = FALSE
-
// Behavior stuff
/// The current behavior to add when clicking with behavior_click_intercept on
var/selected_behavior = DEFAULT_BEHAVIOR_STRING
- /// If we are currently using click intercept for the behavior section
- var/behavior_click_intercept = FALSE
-
// Objective stuff
- /// If we are currently using the click intercept for the objective section
- var/objective_click_intercept = FALSE
-
// Communication stuff
@@ -119,8 +110,6 @@ GLOBAL_VAR_INIT(radio_communication_clarity, 100)
game_master_phone = new(null)
game_master_phone.AddComponent(/datum/component/phone/virtual, "Game Master", "white", "Company Command", null, PHONE_DND_ON, list(FACTION_MARINE, FACTION_COLONIST, FACTION_WY), list(FACTION_MARINE, FACTION_COLONIST, FACTION_WY), null, using_client)
- game_master_client.click_intercept = src
-
for(var/datum/component/ai_behavior_override/override in GLOB.all_ai_behavior_overrides)
game_master_client.images += override.behavior_image
@@ -142,19 +131,18 @@ GLOBAL_VAR_INIT(radio_communication_clarity, 100)
var/list/data = list()
+ data["current_click_intercept_action"] = current_click_intercept_action
+
// Spawn stuff
data["selected_xeno"] = selected_xeno
data["selected_hive"] = selected_hive
data["spawn_ai"] = spawn_ai
- data["spawn_click_intercept"] = spawn_click_intercept
data["xeno_spawn_count"] = xeno_spawn_count
// Behavior stuff
data["selected_behavior"] = selected_behavior
- data["behavior_click_intercept"] = behavior_click_intercept
// Objective stuff
- data["objective_click_intercept"] = objective_click_intercept
data["game_master_objectives"] = length(GLOB.game_master_objectives) ? GLOB.game_master_objectives : ""
// Communication stuff
@@ -205,13 +193,7 @@ GLOBAL_VAR_INIT(radio_communication_clarity, 100)
return
if("toggle_click_spawn")
- if(spawn_click_intercept)
- reset_click_overrides()
- return
-
- reset_click_overrides()
- spawn_click_intercept = TRUE
- current_click_intercept_action = SPAWN_CLICK_INTERCEPT_ACTION
+ set_click_intercept_action(SPAWN_CLICK_INTERCEPT_ACTION)
return
if("delete_all_xenos")
@@ -238,24 +220,13 @@ GLOBAL_VAR_INIT(radio_communication_clarity, 100)
return
if("toggle_click_behavior")
- if(behavior_click_intercept)
- reset_click_overrides()
- return
-
- reset_click_overrides()
- behavior_click_intercept = TRUE
- current_click_intercept_action = BEHAVIOR_CLICK_INTERCEPT_ACTION
+ set_click_intercept_action(BEHAVIOR_CLICK_INTERCEPT_ACTION)
return
+
//Objective Section
if("toggle_click_objective")
- if(objective_click_intercept)
- reset_click_overrides()
- return
-
- reset_click_overrides()
- objective_click_intercept = TRUE
- current_click_intercept_action = OBJECTIVE_CLICK_INTERCEPT_ACTION
+ set_click_intercept_action(OBJECTIVE_CLICK_INTERCEPT_ACTION)
return
if("jump_to")
@@ -305,14 +276,8 @@ GLOBAL_VAR_INIT(radio_communication_clarity, 100)
/datum/game_master/ui_close(mob/user)
. = ..()
- var/client/user_client = user.client
- if(user_client?.click_intercept == src)
- user_client.click_intercept = null
-
- spawn_click_intercept = FALSE
- objective_click_intercept = FALSE
- behavior_click_intercept = FALSE
current_click_intercept_action = null
+ LAZYREMOVE(user.client?.click_intercepts, src)
for(var/datum/component/ai_behavior_override/override in GLOB.all_ai_behavior_overrides)
game_master_client.images -= override.behavior_image
@@ -326,8 +291,6 @@ GLOBAL_VAR_INIT(radio_communication_clarity, 100)
ui = new(user, src, "GameMaster", "Game Master Menu")
ui.open()
- user.client?.click_intercept = src
-
for(var/datum/component/ai_behavior_override/override in GLOB.all_ai_behavior_overrides)
game_master_client.images |= override.behavior_image
@@ -437,11 +400,13 @@ GLOBAL_VAR_INIT(radio_communication_clarity, 100)
return TRUE
-/datum/game_master/proc/reset_click_overrides()
- spawn_click_intercept = FALSE
- objective_click_intercept = FALSE
- behavior_click_intercept = FALSE
- current_click_intercept_action = null
+/datum/game_master/proc/set_click_intercept_action(action)
+ if(current_click_intercept_action == action)
+ current_click_intercept_action = null
+ LAZYREMOVE(game_master_client.click_intercepts, src)
+ else
+ current_click_intercept_action = action
+ LAZYOR(game_master_client.click_intercepts, src)
/datum/game_master/proc/is_objective(atom/checked_object)
for(var/list/cycled_objective in GLOB.game_master_objectives)
diff --git a/code/modules/admin/game_master/resin_panel.dm b/code/modules/admin/game_master/resin_panel.dm
index bab4097173..ad9951d4db 100644
--- a/code/modules/admin/game_master/resin_panel.dm
+++ b/code/modules/admin/game_master/resin_panel.dm
@@ -50,7 +50,6 @@ list( \
var/mob/mob = user
holder = mob.client
- holder.click_intercept = src
tgui_interact(holder.mob)
/datum/resin_panel/proc/get_structures()
@@ -101,7 +100,7 @@ list( \
/datum/resin_panel/ui_close(mob/user)
holder = null
- build_click_intercept = FALSE
+ LAZYREMOVE(user.client.click_intercepts, src)
qdel(src)
/datum/resin_panel/ui_state(mob/user)
@@ -172,6 +171,10 @@ list( \
return TRUE
if("toggle_build_click_intercept")
build_click_intercept = !build_click_intercept
+ if(build_click_intercept)
+ LAZYOR(ui.user.client.click_intercepts, src)
+ else
+ LAZYREMOVE(ui.user.client.click_intercepts, src)
return TRUE
#undef RESIN_PANEL_STRUCTURES
diff --git a/code/modules/admin/game_master/sound_panel.dm b/code/modules/admin/game_master/sound_panel.dm
index 8aff8b0f23..b52472ea46 100644
--- a/code/modules/admin/game_master/sound_panel.dm
+++ b/code/modules/admin/game_master/sound_panel.dm
@@ -52,7 +52,6 @@
var/mob/mob = user
holder = mob.client
- holder.click_intercept = src
tgui_interact(holder.mob)
/datum/sound_panel/proc/get_sounds()
@@ -106,7 +105,7 @@
holder = null
target_loc = null
target_player = null
- loc_click_intercept = FALSE
+ LAZYREMOVE(user.client.click_intercepts, src)
qdel(src)
/datum/sound_panel/ui_state(mob/user)
@@ -222,6 +221,12 @@
return TRUE
if("toggle_loc_click_intercept")
loc_click_intercept = !loc_click_intercept
+
+ if(loc_click_intercept)
+ LAZYOR(ui.user.client.click_intercepts, src)
+ else
+ LAZYREMOVE(ui.user.client.click_intercepts, src)
+
return TRUE
if("toggle_loc_click_play")
loc_click_play = !loc_click_play
diff --git a/code/modules/buildmode/buildmode.dm b/code/modules/buildmode/buildmode.dm
index 4b6d84a5ae..de2c88ad60 100644
--- a/code/modules/buildmode/buildmode.dm
+++ b/code/modules/buildmode/buildmode.dm
@@ -32,13 +32,13 @@
holder.show_popup_menus = FALSE
create_buttons()
holder.add_to_screen(buttons)
- holder.click_intercept = src
+ LAZYOR(holder.click_intercepts, src)
mode.enter_mode(src)
/datum/buildmode/proc/quit()
mode.exit_mode(src)
holder.remove_from_screen(buttons)
- holder.click_intercept = null
+ LAZYREMOVE(holder.click_intercepts, src)
holder.show_popup_menus = TRUE
qdel(src)
@@ -142,20 +142,22 @@
mode.when_clicked(user.client, params, object)
return TRUE // no doing underlying actions
-/proc/togglebuildmode(mob/M as mob in GLOB.player_list)
+/proc/togglebuildmode(mob/builder as mob in GLOB.player_list)
set name = "Toggle Build Mode"
set category = "Admin.Events"
- if(M.client)
- if(istype(M.client.click_intercept, /datum/buildmode))
- var/datum/buildmode/B = M.client.click_intercept
- B.quit()
- message_admins("[key_name(usr)] has left build mode.")
- log_admin("[key_name(usr)] has left build mode.")
- else
- new /datum/buildmode(M.client)
- message_admins("[key_name_admin(usr)] has entered build mode.")
- log_admin("[key_name(usr)] has entered build mode.")
+ if(!builder.client)
+ return
+
+ var/datum/buildmode/bmode = locate() in builder.client?.click_intercepts
+ if(bmode)
+ bmode.quit()
+ message_admins("[key_name(builder)] has left build mode.")
+ log_admin("[key_name(builder)] has left build mode.")
+ else
+ new /datum/buildmode(builder.client)
+ message_admins("[key_name_admin(builder)] has entered build mode.")
+ log_admin("[key_name(builder)] has entered build mode.")
#undef BM_SWITCHSTATE_NONE
#undef BM_SWITCHSTATE_MODE
diff --git a/code/modules/client/client_defines.dm b/code/modules/client/client_defines.dm
index f09023408f..2f001268ba 100644
--- a/code/modules/client/client_defines.dm
+++ b/code/modules/client/client_defines.dm
@@ -30,7 +30,8 @@
var/donator = FALSE
var/adminhelped = 0
- var/datum/click_intercept = null
+ /// Stack of click-intercepting objects for this client.
+ var/list/click_intercepts
var/atom/movable/screen/click_catcher/void
diff --git a/code/modules/mob/mob_defines.dm b/code/modules/mob/mob_defines.dm
index c04a745ea1..f4544ee8e0 100644
--- a/code/modules/mob/mob_defines.dm
+++ b/code/modules/mob/mob_defines.dm
@@ -250,7 +250,8 @@
var/list/important_radio_channels = list()
- var/datum/click_intercept
+ /// Stack of click-intercepting objects for this mob.
+ var/list/click_intercepts
/// Used for tracking last uses of emotes for cooldown purposes
var/list/emotes_used
diff --git a/tgui/packages/tgui/interfaces/GameMaster.jsx b/tgui/packages/tgui/interfaces/GameMaster.jsx
index afb9d1390b..4efbcbab00 100644
--- a/tgui/packages/tgui/interfaces/GameMaster.jsx
+++ b/tgui/packages/tgui/interfaces/GameMaster.jsx
@@ -88,7 +88,10 @@ export const GameMasterSpawningPanel = (props, context) => {