diff --git a/code/modules/research/xenobiology/xenobio_camera.dm b/code/modules/research/xenobiology/xenobio_camera.dm
index 5aebd1bafa..07b25c6de8 100644
--- a/code/modules/research/xenobiology/xenobio_camera.dm
+++ b/code/modules/research/xenobiology/xenobio_camera.dm
@@ -28,6 +28,7 @@
var/datum/action/innate/monkey_recycle/monkey_recycle_action
var/datum/action/innate/slime_scan/scan_action
var/datum/action/innate/feed_potion/potion_action
+ var/datum/action/innate/hotkey_help/hotkey_help
var/datum/component/redirect/listener
@@ -49,6 +50,7 @@
monkey_recycle_action = new
scan_action = new
potion_action = new
+ hotkey_help = new
stored_slimes = list()
listener = AddComponent(/datum/component/redirect, list(COMSIG_ATOM_CONTENTS_DEL = CALLBACK(src, .proc/on_contents_del)))
@@ -101,6 +103,27 @@
potion_action.Grant(user)
actions += potion_action
+ if(hotkey_help)
+ hotkey_help.target = src
+ hotkey_help.Grant(user)
+ actions += hotkey_help
+
+ RegisterSignal(user, COMSIG_XENO_SLIME_CLICK_CTRL, .proc/XenoSlimeClickCtrl)
+ RegisterSignal(user, COMSIG_XENO_SLIME_CLICK_ALT, .proc/XenoSlimeClickAlt)
+ RegisterSignal(user, COMSIG_XENO_SLIME_CLICK_SHIFT, .proc/XenoSlimeClickShift)
+ RegisterSignal(user, COMSIG_XENO_TURF_CLICK_SHIFT, .proc/XenoTurfClickShift)
+ RegisterSignal(user, COMSIG_XENO_TURF_CLICK_CTRL, .proc/XenoTurfClickCtrl)
+ RegisterSignal(user, COMSIG_XENO_MONKEY_CLICK_CTRL, .proc/XenoMonkeyClickCtrl)
+
+/obj/machinery/computer/camera_advanced/xenobio/remove_eye_control(mob/living/user)
+ UnregisterSignal(user, COMSIG_XENO_SLIME_CLICK_CTRL)
+ UnregisterSignal(user, COMSIG_XENO_SLIME_CLICK_ALT)
+ UnregisterSignal(user, COMSIG_XENO_SLIME_CLICK_SHIFT)
+ UnregisterSignal(user, COMSIG_XENO_TURF_CLICK_SHIFT)
+ UnregisterSignal(user, COMSIG_XENO_TURF_CLICK_CTRL)
+ UnregisterSignal(user, COMSIG_XENO_MONKEY_CLICK_CTRL)
+ ..()
+
/obj/machinery/computer/camera_advanced/xenobio/proc/on_contents_del(atom/deleted)
if(current_potion == deleted)
current_potion = null
@@ -154,7 +177,7 @@
S.visible_message("[S] warps in!")
X.stored_slimes -= S
else
- to_chat(owner, "Target is not near a camera. Cannot proceed.")
+ to_chat(owner, "Target is not near a camera. Cannot proceed.")
/datum/action/innate/slime_pick_up
name = "Pick up Slime"
@@ -179,7 +202,7 @@
S.forceMove(X)
X.stored_slimes += S
else
- to_chat(owner, "Target is not near a camera. Cannot proceed.")
+ to_chat(owner, "Target is not near a camera. Cannot proceed.")
/datum/action/innate/feed_slime
@@ -200,9 +223,11 @@
if (!QDELETED(food))
food.LAssailant = C
X.monkeys --
- to_chat(owner, "[X] now has [X.monkeys] monkeys left.")
+ to_chat(owner, "[X] now has [X.monkeys] monkey(s) left.")
+ else
+ to_chat(owner, "[X] needs to have at least 1 monkey stored. Currently has [X.monkeys] monkeys stored.")
else
- to_chat(owner, "Target is not near a camera. Cannot proceed.")
+ to_chat(owner, "Target is not near a camera. Cannot proceed.")
/datum/action/innate/monkey_recycle
@@ -220,11 +245,13 @@
if(GLOB.cameranet.checkTurfVis(remote_eye.loc))
for(var/mob/living/carbon/monkey/M in remote_eye.loc)
if(M.stat)
- M.visible_message("[M] vanishes as [M.p_theyre()] reclaimed for recycling!")
+ M.visible_message("[M] vanishes as [p_theyre()] reclaimed for recycling!")
X.monkeys = round(X.monkeys + 0.2,0.1)
qdel(M)
+ if (X.monkeys == (round(X.monkeys,1)))
+ to_chat(C, "[X] now has [X.monkeys] monkey(s) available.")
else
- to_chat(owner, "Target is not near a camera. Cannot proceed.")
+ to_chat(owner, "Target is not near a camera. Cannot proceed.")
/datum/action/innate/slime_scan
name = "Scan Slime"
@@ -241,7 +268,7 @@
for(var/mob/living/simple_animal/slime/S in remote_eye.loc)
slime_scan(S, C)
else
- to_chat(owner, "Target is not near a camera. Cannot proceed.")
+ to_chat(owner, "Target is not near a camera. Cannot proceed.")
/datum/action/innate/feed_potion
name = "Apply Potion"
@@ -257,7 +284,7 @@
var/obj/machinery/computer/camera_advanced/xenobio/X = target
if(QDELETED(X.current_potion))
- to_chat(owner, "No potion loaded.")
+ to_chat(owner, "No potion loaded.")
return
if(GLOB.cameranet.checkTurfVis(remote_eye.loc))
@@ -265,4 +292,167 @@
X.current_potion.attack(S, C)
break
else
- to_chat(owner, "Target is not near a camera. Cannot proceed.")
+ to_chat(owner, "Target is not near a camera. Cannot proceed.")
+
+/datum/action/innate/hotkey_help
+ name = "Hotkey Help"
+ icon_icon = 'icons/mob/actions/actions_silicon.dmi'
+ button_icon_state = "hotkey_help"
+
+/datum/action/innate/hotkey_help/Activate()
+ if(!target || !isliving(owner))
+ return
+ to_chat(owner, "Click shortcuts:")
+ to_chat(owner, "Shift-click a slime to pick it up, or the floor to drop all held slimes. (Requires Basic Slime Console upgrade)")
+ to_chat(owner, "Ctrl-click a slime to scan it.")
+ to_chat(owner, "Alt-click a slime to feed it a potion. (Requires Advanced Slime Console upgrade)")
+ to_chat(owner, "Ctrl-click on a dead monkey to recycle it, or the floor to place a new monkey. (Requires Monkey Console upgrade)")
+
+//
+// Alternate clicks for slime, monkey and open turf if using a xenobio console
+
+// Scans slime
+/mob/living/simple_animal/slime/CtrlClick(mob/user)
+ SEND_SIGNAL(user, COMSIG_XENO_SLIME_CLICK_CTRL, src)
+ ..()
+
+//Feeds a potion to slime
+/mob/living/simple_animal/slime/AltClick(mob/user)
+ SEND_SIGNAL(user, COMSIG_XENO_SLIME_CLICK_ALT, src)
+ ..()
+
+//Picks up slime
+/mob/living/simple_animal/slime/ShiftClick(mob/user)
+ SEND_SIGNAL(user, COMSIG_XENO_SLIME_CLICK_SHIFT, src)
+ ..()
+
+//Place slimes
+/turf/open/ShiftClick(mob/user)
+ SEND_SIGNAL(user, COMSIG_XENO_TURF_CLICK_SHIFT, src)
+ ..()
+
+//Place monkey
+/turf/open/CtrlClick(mob/user)
+ SEND_SIGNAL(user, COMSIG_XENO_TURF_CLICK_CTRL, src)
+ ..()
+
+//Pick up monkey
+/mob/living/carbon/monkey/CtrlClick(mob/user)
+ SEND_SIGNAL(user, COMSIG_XENO_MONKEY_CLICK_CTRL, src)
+ ..()
+
+// Scans slime
+/obj/machinery/computer/camera_advanced/xenobio/proc/XenoSlimeClickCtrl(mob/living/user, mob/living/simple_animal/slime/S)
+ if(!GLOB.cameranet.checkTurfVis(S.loc))
+ to_chat(user, "Target is not near a camera. Cannot proceed.")
+ return
+ var/mob/living/C = user
+ var/mob/camera/aiEye/remote/xenobio/E = C.remote_control
+ var/area/mobarea = get_area(S.loc)
+ if(mobarea.name == E.allowed_area || mobarea.xenobiology_compatible)
+ slime_scan(S, C)
+
+//Feeds a potion to slime
+/obj/machinery/computer/camera_advanced/xenobio/proc/XenoSlimeClickAlt(mob/living/user, mob/living/simple_animal/slime/S)
+ if(!(upgradetier & XENOBIO_UPGRADE_SLIMEADV)) //CIT CHANGE - makes slime-related actions require XENOBIO_UPGRADE_SLIMEADV
+ to_chat(user, "This console does not have the advanced slime upgrade.")
+ return
+ if(!GLOB.cameranet.checkTurfVis(S.loc))
+ to_chat(user, "Target is not near a camera. Cannot proceed.")
+ return
+ var/mob/living/C = user
+ var/mob/camera/aiEye/remote/xenobio/E = C.remote_control
+ var/obj/machinery/computer/camera_advanced/xenobio/X = E.origin
+ var/area/mobarea = get_area(S.loc)
+ if(QDELETED(X.current_potion))
+ to_chat(C, "No potion loaded.")
+ return
+ if(mobarea.name == E.allowed_area || mobarea.xenobiology_compatible)
+ X.current_potion.attack(S, C)
+
+//Picks up slime
+/obj/machinery/computer/camera_advanced/xenobio/proc/XenoSlimeClickShift(mob/living/user, mob/living/simple_animal/slime/S)
+ if(!(upgradetier & XENOBIO_UPGRADE_SLIMEBASIC)) //CIT CHANGE - makes slime-related actions require XENOBIO_UPGRADE_SLIMEBASIC
+ to_chat(user, "This console does not have the basic slime upgrade.")
+ return
+ if(!GLOB.cameranet.checkTurfVis(S.loc))
+ to_chat(user, "Target is not near a camera. Cannot proceed.")
+ return
+ var/mob/living/C = user
+ var/mob/camera/aiEye/remote/xenobio/E = C.remote_control
+ var/obj/machinery/computer/camera_advanced/xenobio/X = E.origin
+ var/area/mobarea = get_area(S.loc)
+ if(mobarea.name == E.allowed_area || mobarea.xenobiology_compatible)
+ if(X.stored_slimes.len >= X.max_slimes)
+ to_chat(C, "Slime storage is full.")
+ return
+ if(S.ckey)
+ to_chat(C, "The slime wiggled free!")
+ return
+ if(S.buckled)
+ S.Feedstop(silent = TRUE)
+ S.visible_message("[S] vanishes in a flash of light!")
+ S.forceMove(X)
+ X.stored_slimes += S
+
+//Place slimes
+/obj/machinery/computer/camera_advanced/xenobio/proc/XenoTurfClickShift(mob/living/user, turf/open/T)
+ if(!(upgradetier & XENOBIO_UPGRADE_SLIMEBASIC)) //CIT CHANGE - makes slime-related actions require XENOBIO_UPGRADE_SLIMEBASIC
+ to_chat(user, "This console does not have the basic slime upgrade.")
+ return
+ if(!GLOB.cameranet.checkTurfVis(T))
+ to_chat(user, "Target is not near a camera. Cannot proceed.")
+ return
+ var/mob/living/C = user
+ var/mob/camera/aiEye/remote/xenobio/E = C.remote_control
+ var/obj/machinery/computer/camera_advanced/xenobio/X = E.origin
+ var/area/turfarea = get_area(T)
+ if(turfarea.name == E.allowed_area || turfarea.xenobiology_compatible)
+ for(var/mob/living/simple_animal/slime/S in X.stored_slimes)
+ S.forceMove(T)
+ S.visible_message("[S] warps in!")
+ X.stored_slimes -= S
+
+//Place monkey
+/obj/machinery/computer/camera_advanced/xenobio/proc/XenoTurfClickCtrl(mob/living/user, turf/open/T)
+ if(!(upgradetier & XENOBIO_UPGRADE_MONKEYS)) // CIT CHANGE - makes monkey-related actions require XENOBIO_UPGRADE_MONKEYS
+ to_chat(user, "This console does not have the monkey upgrade.")
+ return
+ if(!GLOB.cameranet.checkTurfVis(T))
+ to_chat(user, "Target is not near a camera. Cannot proceed.")
+ return
+ var/mob/living/C = user
+ var/mob/camera/aiEye/remote/xenobio/E = C.remote_control
+ var/obj/machinery/computer/camera_advanced/xenobio/X = E.origin
+ var/area/turfarea = get_area(T)
+ if(turfarea.name == E.allowed_area || turfarea.xenobiology_compatible)
+ if(X.monkeys >= 1)
+ var/mob/living/carbon/monkey/food = new /mob/living/carbon/monkey(T, TRUE, C)
+ if (!QDELETED(food))
+ food.LAssailant = C
+ X.monkeys--
+ X.monkeys = round(X.monkeys, 0.1) //Prevents rounding errors
+ to_chat(C, "[X] now has [X.monkeys] monkey(s) stored.")
+ else
+ to_chat(C, "[X] needs to have at least 1 monkey stored. Currently has [X.monkeys] monkeys stored.")
+
+//Pick up monkey
+/obj/machinery/computer/camera_advanced/xenobio/proc/XenoMonkeyClickCtrl(mob/living/user, mob/living/carbon/monkey/M)
+ if(!(upgradetier & XENOBIO_UPGRADE_MONKEYS)) // CIT CHANGE - makes monkey-related actions require XENOBIO_UPGRADE_MONKEYS
+ to_chat(user, "This console does not have the monkey upgrade.")
+ return
+ if(!GLOB.cameranet.checkTurfVis(M.loc))
+ to_chat(user, "Target is not near a camera. Cannot proceed.")
+ return
+ var/mob/living/C = user
+ var/mob/camera/aiEye/remote/xenobio/E = C.remote_control
+ var/obj/machinery/computer/camera_advanced/xenobio/X = E.origin
+ var/area/mobarea = get_area(M.loc)
+ if(mobarea.name == E.allowed_area || mobarea.xenobiology_compatible)
+ if(!M.stat)
+ return
+ M.visible_message("[M] vanishes as [p_theyre()] reclaimed for recycling!")
+ X.monkeys = round(X.monkeys + 0.2,0.1)
+ qdel(M)
+ if (X.monkeys == (round(X.monkeys,1)))
+ to_chat(C, "[X] now has [X.monkeys] monkey(s) available.")