diff --git a/code/_onclick/ai.dm b/code/_onclick/ai.dm
index 14c48fbcaa..0090a69cc6 100644
--- a/code/_onclick/ai.dm
+++ b/code/_onclick/ai.dm
@@ -10,9 +10,8 @@
Note that AI have no need for the adjacency proc, and so this proc is a lot cleaner.
*/
/mob/living/silicon/ai/DblClickOn(var/atom/A, params)
- if(client.click_intercept)
- if(call(client.click_intercept, "InterceptClickOn")(src, params, A))
- return
+ if(check_click_intercept(params,A))
+ return
if(control_disabled || incapacitated())
return
@@ -27,9 +26,8 @@
return
next_click = world.time + 1
- if(client.click_intercept)
- if(call(client.click_intercept, "InterceptClickOn")(src, params, A))
- return
+ if(check_click_intercept(params,A))
+ return
if(control_disabled || incapacitated())
return
diff --git a/code/_onclick/click.dm b/code/_onclick/click.dm
index 4c588c96fe..73ad2a94e3 100644
--- a/code/_onclick/click.dm
+++ b/code/_onclick/click.dm
@@ -61,9 +61,8 @@
return
next_click = world.time + 1
- if(client && client.click_intercept)
- if(call(client.click_intercept, "InterceptClickOn")(src, params, A))
- return
+ if(check_click_intercept(params,A))
+ return
var/list/modifiers = params2list(params)
if(modifiers["shift"] && modifiers["middle"])
@@ -476,7 +475,7 @@
var/mob/living/carbon/C = usr
C.swap_hand()
else
- var/turf/T = params2turf(modifiers["screen-loc"], get_turf(usr))
+ var/turf/T = params2turf(modifiers["screen-loc"], get_turf(usr.client ? usr.client.eye : usr))
params += "&catcher=1"
if(T)
T.Click(location, control, params)
@@ -496,3 +495,16 @@
else
view = 1
add_view_range(view)
+
+/mob/proc/check_click_intercept(params,A)
+ //Client level intercept
+ if(client && client.click_intercept)
+ if(call(client.click_intercept, "InterceptClickOn")(src, params, A))
+ return TRUE
+
+ //Mob level intercept
+ if(click_intercept)
+ if(call(click_intercept, "InterceptClickOn")(src, params, A))
+ return TRUE
+
+ return FALSE
diff --git a/code/_onclick/cyborg.dm b/code/_onclick/cyborg.dm
index 6ed126cf37..95f1a50968 100644
--- a/code/_onclick/cyborg.dm
+++ b/code/_onclick/cyborg.dm
@@ -11,9 +11,8 @@
return
next_click = world.time + 1
- if(client.click_intercept)
- if(call(client.click_intercept,"InterceptClickOn")(src,params,A))
- return
+ if(check_click_intercept(params,A))
+ return
if(stat || lockcharge || IsKnockdown() || IsStun() || IsUnconscious())
return
diff --git a/code/_onclick/observer.dm b/code/_onclick/observer.dm
index f124e2779b..19c933952c 100644
--- a/code/_onclick/observer.dm
+++ b/code/_onclick/observer.dm
@@ -1,7 +1,6 @@
/mob/dead/observer/DblClickOn(var/atom/A, var/params)
- if(client.click_intercept)
- if(call(client.click_intercept,"InterceptClickOn")(src,params,A))
- return
+ if(check_click_intercept(params,A))
+ return
if(can_reenter_corpse && mind && mind.current)
if(A == mind.current || (mind.current in A)) // double click your corpse or whatever holds it
@@ -18,9 +17,8 @@
update_parallax_contents()
/mob/dead/observer/ClickOn(var/atom/A, var/params)
- if(client.click_intercept)
- if(call(client.click_intercept,"InterceptClickOn")(src,params,A))
- return
+ if(check_click_intercept(params,A))
+ return
var/list/modifiers = params2list(params)
if(modifiers["shift"] && modifiers["middle"])
diff --git a/code/game/machinery/porta_turret/portable_turret.dm b/code/game/machinery/porta_turret/portable_turret.dm
index c8202b4e10..37efa70b33 100644
--- a/code/game/machinery/porta_turret/portable_turret.dm
+++ b/code/game/machinery/porta_turret/portable_turret.dm
@@ -76,6 +76,11 @@
var/wall_turret_direction //The turret will try to shoot from a turf in that direction when in a wall
+ var/manual_control = FALSE //
+ var/datum/action/turret_quit/quit_action
+ var/datum/action/turret_toggle/toggle_action
+ var/mob/remote_controller
+
/obj/machinery/porta_turret/Initialize()
. = ..()
if(!base)
@@ -154,6 +159,7 @@
cp = null
QDEL_NULL(stored_gun)
QDEL_NULL(spark_system)
+ remove_control()
return ..()
@@ -179,6 +185,14 @@
dat += "Neutralize All Non-Security and Non-Command Personnel: [stun_all ? "Yes" : "No"]
"
dat += "Neutralize All Unidentified Life Signs: [check_anomalies ? "Yes" : "No"]
"
dat += "Neutralize All Non-Loyalty Implanted Personnel: [shoot_unloyal ? "Yes" : "No"]
"
+ if(issilicon(user))
+ if(!manual_control)
+ var/mob/living/silicon/S = user
+ if(S.hack_software)
+ dat += "Assume direct control : Manual Control
"
+ else
+ dat += "Warning! Remote control protocol enabled.
"
+
var/datum/browser/popup = new(user, "autosec", "Automatic Portable Turret Installation", 300, 300)
popup.set_content(dat)
@@ -212,6 +226,9 @@
check_anomalies = !check_anomalies
if("checkloyal")
shoot_unloyal = !shoot_unloyal
+ if("manual")
+ if(issilicon(usr) && !manual_control)
+ give_control(usr)
interact(usr)
/obj/machinery/porta_turret/power_change()
@@ -359,6 +376,8 @@
popDown()
return
+ if(manual_control)
+ return
var/list/targets = list()
var/static/things_to_scan = typecacheof(list(/mob/living, /obj/mecha))
@@ -566,6 +585,66 @@
src.mode = mode
power_change()
+
+/datum/action/turret_toggle
+ name = "Toggle Mode"
+ icon_icon = 'icons/mob/actions/actions_mecha.dmi'
+ button_icon_state = "mech_cycle_equip_off"
+
+/datum/action/turret_toggle/Trigger()
+ var/obj/machinery/porta_turret/P = target
+ if(!istype(P))
+ return
+ P.setState(P.on,!P.mode)
+
+/datum/action/turret_quit
+ name = "Release Control"
+ icon_icon = 'icons/mob/actions/actions_mecha.dmi'
+ button_icon_state = "mech_eject"
+
+/datum/action/turret_quit/Trigger()
+ var/obj/machinery/porta_turret/P = target
+ if(!istype(P))
+ return
+ P.remove_control(owner)
+
+/obj/machinery/porta_turret/proc/give_control(mob/A)
+ if(manual_control)
+ return FALSE
+ remote_controller = A
+ if(!quit_action)
+ quit_action = new(src)
+ quit_action.Grant(remote_controller)
+ if(!toggle_action)
+ toggle_action = new(src)
+ toggle_action.Grant(remote_controller)
+ remote_controller.reset_perspective(src)
+ remote_controller.click_intercept = src
+ manual_control = TRUE
+ always_up = TRUE
+ popUp()
+ return TRUE
+
+/obj/machinery/porta_turret/proc/remove_control()
+ if(!manual_control)
+ return FALSE
+ if(remote_controller)
+ quit_action.Remove(remote_controller)
+ toggle_action.Remove(remote_controller)
+ remote_controller.click_intercept = null
+ remote_controller.reset_perspective()
+ always_up = initial(always_up)
+ manual_control = FALSE
+ remote_controller = null
+ return TRUE
+
+/obj/machinery/porta_turret/proc/InterceptClickOn(mob/living/caller, params, atom/A)
+ if(!manual_control)
+ return FALSE
+ add_logs(caller,A,"fired with manual turret control at")
+ target(A)
+ return TRUE
+
/obj/machinery/porta_turret/syndicate
installation = null
always_up = 1
diff --git a/code/modules/mob/mob_defines.dm b/code/modules/mob/mob_defines.dm
index 0088e09515..cb5769ab8d 100644
--- a/code/modules/mob/mob_defines.dm
+++ b/code/modules/mob/mob_defines.dm
@@ -102,3 +102,5 @@
var/list/progressbars = null //for stacking do_after bars
var/list/mousemove_intercept_objects
+
+ var/datum/click_intercept
diff --git a/code/modules/spells/spell.dm b/code/modules/spells/spell.dm
index 19162d5259..ee02bd524f 100644
--- a/code/modules/spells/spell.dm
+++ b/code/modules/spells/spell.dm
@@ -67,7 +67,7 @@ GLOBAL_LIST_INIT(spells, typesof(/obj/effect/proc_holder/spell)) //needed for th
else
return
user.ranged_ability = src
- user.client.click_intercept = user.ranged_ability
+ user.click_intercept = src
add_mousepointer(user.client)
ranged_ability_user = user
if(msg)
@@ -87,7 +87,7 @@ GLOBAL_LIST_INIT(spells, typesof(/obj/effect/proc_holder/spell)) //needed for th
if(!ranged_ability_user || !ranged_ability_user.client || (ranged_ability_user.ranged_ability && ranged_ability_user.ranged_ability != src)) //To avoid removing the wrong ability
return
ranged_ability_user.ranged_ability = null
- ranged_ability_user.client.click_intercept = null
+ ranged_ability_user.click_intercept = null
remove_mousepointer(ranged_ability_user.client)
if(msg)
to_chat(ranged_ability_user, msg)