diff --git a/code/modules/food_and_drinks/kitchen_machinery/monkeyrecycler.dm b/code/modules/food_and_drinks/kitchen_machinery/monkeyrecycler.dm index c25cb228..789c54f7 100644 --- a/code/modules/food_and_drinks/kitchen_machinery/monkeyrecycler.dm +++ b/code/modules/food_and_drinks/kitchen_machinery/monkeyrecycler.dm @@ -1,6 +1,8 @@ +GLOBAL_LIST_EMPTY(monkey_recyclers) + /obj/machinery/monkey_recycler name = "monkey recycler" - desc = "A machine used for recycling dead monkeys into monkey cubes. It currently produces 1 cube for every 5 monkeys inserted." // except it literally never does + desc = "A machine used for recycling dead monkeys into monkey cubes. You can use a multitool to link it to a xenobiology console. It currently produces 0.2 cubes for every monkey inserted." icon = 'icons/obj/kitchen.dmi' icon_state = "grinder" layer = BELOW_OBJ_LAYER @@ -9,20 +11,29 @@ idle_power_usage = 5 active_power_usage = 50 circuit = /obj/item/circuitboard/machine/monkey_recycler - var/grinded = 0 - var/required_grind = 5 - var/cube_production = 1 + var/stored_matter = 0 + var/cube_production = 0.2 + var/list/connected = list() //Xenobio consoles + +/obj/machinery/monkey_recycler/Initialize(mapload) + . = ..() + GLOB.monkey_recyclers += src -/obj/machinery/monkey_recycler/RefreshParts() - var/req_grind = 5 - var/cubes_made = 1 +/obj/machinery/monkey_recycler/Destroy() + if(src in GLOB.monkey_recyclers) + GLOB.monkey_recyclers -= src + for(var/obj/machinery/computer/camera_advanced/xenobio/C in connected) + var/obj/machinery/computer/camera_advanced/xenobio/console = C + console.connected_recycler = null + return ..() + +/obj/machinery/monkey_recycler/RefreshParts() //Ranges from 0.2 to 0.8 per monkey recycled + cube_production = 0 for(var/obj/item/stock_parts/manipulator/B in component_parts) - req_grind -= B.rating + cube_production += B.rating * 0.1 for(var/obj/item/stock_parts/matter_bin/M in component_parts) - cubes_made = M.rating - cube_production = cubes_made - required_grind = req_grind - src.desc = "A machine used for recycling dead monkeys into monkey cubes. It currently produces [cubes_made] cube(s) for every [required_grind] monkey(s) inserted." + cube_production += M.rating * 0.1 + desc = "A machine used for recycling dead monkeys into monkey cubes. You can use a multitool to link it to a xenobiology console. It currently produces [cube_production] cubes for every monkey inserted." /obj/machinery/monkey_recycler/attackby(obj/item/O, mob/user, params) if(default_deconstruction_screwdriver(user, "grinder_open", "grinder", O)) @@ -64,17 +75,22 @@ var/offset = prob(50) ? -2 : 2 animate(src, pixel_x = pixel_x + offset, time = 0.2, loop = 200) //start shaking use_power(500) - grinded++ + stored_matter += cube_production addtimer(VARSET_CALLBACK(src, pixel_x, initial(pixel_x))) - addtimer(CALLBACK(GLOBAL_PROC, /proc/to_chat, user, "The machine now has [grinded] monkey\s worth of material stored.")) + addtimer(CALLBACK(GLOBAL_PROC, /proc/to_chat, user, "The machine now has [stored_matter] monkey\s worth of material stored.")) /obj/machinery/monkey_recycler/interact(mob/user) - if(grinded >= required_grind) - to_chat(user, "The machine hisses loudly as it condenses the grinded monkey meat. After a moment, it dispenses a brand new monkey cube.") + if(stored_matter >= 1) + to_chat(user, "The machine hisses loudly as it condenses the ground monkey meat. After a moment, it dispenses a brand new monkey cube.") playsound(src.loc, 'sound/machines/hiss.ogg', 50, 1) - grinded -= required_grind - for(var/i = 0, i < cube_production, i++) - new /obj/item/reagent_containers/food/snacks/monkeycube(src.loc) - to_chat(user, "The machine's display flashes that it has [grinded] monkeys worth of material left.") + for(var/i in 1 to max(stored_matter, 1)) + new /obj/item/reagent_containers/food/snacks/monkeycube(loc) + to_chat(user, "The machine's display flashes that it has [stored_matter] monkeys worth of material left.") else - to_chat(user, "The machine needs at least [required_grind] monkey(s) worth of material to produce a monkey cube. It only has [grinded].") + to_chat(user, "The machine needs at least 1 monkey worth of material to produce a monkey cube. It currently has [stored_matter].") + +/obj/machinery/monkey_recycler/multitool_act(mob/living/user, obj/item/multitool/I) + if(istype(I)) + to_chat(user, "You log [src] in the multitool's buffer.") + I.buffer = src + return TRUE diff --git a/code/modules/research/xenobiology/xenobio_camera.dm b/code/modules/research/xenobiology/xenobio_camera.dm index 5aebd1ba..9ece19f6 100644 --- a/code/modules/research/xenobiology/xenobio_camera.dm +++ b/code/modules/research/xenobiology/xenobio_camera.dm @@ -1,6 +1,6 @@ //Xenobio control console /mob/camera/aiEye/remote/xenobio - visible_icon = 1 + visible_icon = TRUE icon = 'icons/obj/abductor.dmi' icon_state = "camera_target" var/allowed_area = null @@ -22,15 +22,11 @@ desc = "A computer used for remotely handling slimes." networks = list("ss13") circuit = /obj/item/circuitboard/computer/xenobiology - var/datum/action/innate/slime_place/slime_place_action - var/datum/action/innate/slime_pick_up/slime_up_action - var/datum/action/innate/feed_slime/feed_slime_action - 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 + var/obj/machinery/monkey_recycler/connected_recycler var/list/stored_slimes var/obj/item/slimepotion/slime/current_potion var/max_slimes = 5 @@ -43,14 +39,13 @@ /obj/machinery/computer/camera_advanced/xenobio/Initialize() . = ..() - slime_place_action = new - slime_up_action = new - feed_slime_action = new - 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))) + for(var/obj/machinery/monkey_recycler/recycler in GLOB.monkey_recyclers) + if(get_area(src) == get_area(recycler)) + connected_recycler = recycler + connected_recycler.connected += src /obj/machinery/computer/camera_advanced/xenobio/Destroy() stored_slimes = null @@ -61,45 +56,56 @@ S.forceMove(drop_location()) return ..() +/obj/machinery/computer/camera_advanced/xenobio/examine(mob/user) + . = ..() + var/thing = "It has " + if((upgradetier & XENOBIO_UPGRADE_SLIMEADV)) + thing += "an advanced slime upgrade disk " + if((upgradetier & XENOBIO_UPGRADE_MONKEYS)) + thing += "and a monkey upgrade disk " + else if((upgradetier & XENOBIO_UPGRADE_SLIMEBASIC)) + thing += "a basic slime upgrade disk " + if((upgradetier & XENOBIO_UPGRADE_MONKEYS)) + thing += "and a monkey upgrade disk " + else if((upgradetier & XENOBIO_UPGRADE_MONKEYS)) + thing += "a monkey upgrade disk " + else + thing += "no upgrades installed." + . += thing + return + thing += "installed." + . += thing + /obj/machinery/computer/camera_advanced/xenobio/CreateEye() eyeobj = new /mob/camera/aiEye/remote/xenobio(get_turf(src)) eyeobj.origin = src - eyeobj.visible_icon = 1 + eyeobj.visible_icon = TRUE eyeobj.icon = 'icons/obj/abductor.dmi' eyeobj.icon_state = "camera_target" /obj/machinery/computer/camera_advanced/xenobio/GrantActions(mob/living/user) ..() - if(slime_up_action && (upgradetier & XENOBIO_UPGRADE_SLIMEBASIC)) //CIT CHANGE - makes slime-related actions require XENOBIO_UPGRADE_SLIMEBASIC - slime_up_action.target = src - slime_up_action.Grant(user) - actions += slime_up_action + if(hotkey_help) + hotkey_help.target = src + hotkey_help.Grant(user) + actions += hotkey_help - if(slime_place_action && (upgradetier & XENOBIO_UPGRADE_SLIMEBASIC)) //CIT CHANGE - makes slime-related actions require XENOBIO_UPGRADE_SLIMEBASIC - slime_place_action.target = src - slime_place_action.Grant(user) - actions += slime_place_action + 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) - if(feed_slime_action && (upgradetier & XENOBIO_UPGRADE_MONKEYS)) //CIT CHANGE - makes monkey-related actions require XENOBIO_UPGRADE_MONKEYS - feed_slime_action.target = src - feed_slime_action.Grant(user) - actions += feed_slime_action - - if(monkey_recycle_action && (upgradetier & XENOBIO_UPGRADE_MONKEYS)) //CIT CHANGE - makes monkey-related actions require XENOBIO_UPGRADE_MONKEYS - monkey_recycle_action.target = src - monkey_recycle_action.Grant(user) - actions += monkey_recycle_action - - if(scan_action) - scan_action.target = src - scan_action.Grant(user) - actions += scan_action - - if(potion_action && (upgradetier & XENOBIO_UPGRADE_SLIMEADV)) // CIT CHANGE - makes giving slimes potions via console require XENOBIO_UPGRADE_SLIMEADV - potion_action.target = src - potion_action.Grant(user) - actions += potion_action +/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) @@ -134,135 +140,161 @@ current_potion = O to_chat(user, "You load [O] in the console's potion slot[replaced ? ", replacing the one that was there before" : ""].") return + else if(istype(O, /obj/item/multitool)) + var/obj/item/multitool/M = O + if(istype(M.buffer)) + to_chat(user, "You link [src] with [M.buffer] in [M] buffer.") + connected_recycler = M.buffer + connected_recycler += src + return + else + to_chat(user, "[M] has no buffer.") + return ..() -/datum/action/innate/slime_place - name = "Place Slimes" +/datum/action/innate/hotkey_help + name = "Hotkey Help" icon_icon = 'icons/mob/actions/actions_silicon.dmi' - button_icon_state = "slime_down" + button_icon_state = "hotkey_help" -/datum/action/innate/slime_place/Activate() +/datum/action/innate/hotkey_help/Activate() if(!target || !isliving(owner)) return - var/mob/living/C = owner - var/mob/camera/aiEye/remote/xenobio/remote_eye = C.remote_control - var/obj/machinery/computer/camera_advanced/xenobio/X = target + to_chat(owner, "Click shortcuts:") + to_chat(owner, "Shift-click a slime to pick it up, or the floor to drop all held slimes.") + to_chat(owner, "Ctrl-click a slime to scan it.") + to_chat(owner, "Alt-click a slime to feed it a potion.") + to_chat(owner, "Ctrl-click or a dead monkey to recycle it, or the floor to place a new monkey.") - if(GLOB.cameranet.checkTurfVis(remote_eye.loc)) - for(var/mob/living/simple_animal/slime/S in X.stored_slimes) - S.forceMove(remote_eye.loc) +// +// Alternate clicks for slime, monkey and open turf if using a xenobio console + +//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 +/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 +/obj/machinery/computer/camera_advanced/xenobio/proc/XenoSlimeClickShift(mob/living/user, mob/living/simple_animal/slime/S) + if(!(upgradetier & XENOBIO_UPGRADE_SLIMEBASIC)) + return + if(!GLOB.cameranet.checkTurfVis(S.loc)) + to_chat(user, "Target is not near a camera. Cannot proceed.") + return + var/area/mobarea = get_area(S.loc) + var/mob/camera/aiEye/remote/xenobio/X = eyeobj + if(mobarea.name == X.allowed_area || mobarea.xenobiology_compatible) + if(stored_slimes.len >= max_slimes) + to_chat(user, "Slime storage is full.") + return + if(S.ckey) + to_chat(user, "The slime wiggled free!") + return + if(S.buckled) + S.Feedstop(silent = TRUE) + S.visible_message("[S] vanishes in a flash of light!") + S.forceMove(src) + stored_slimes += S + +//Place slimes +/obj/machinery/computer/camera_advanced/xenobio/proc/XenoTurfClickShift(mob/living/user, turf/open/T) + if(!(upgradetier & XENOBIO_UPGRADE_SLIMEBASIC)) + return + if(!GLOB.cameranet.checkTurfVis(T)) + to_chat(user, "Target is not near a camera. Cannot proceed.") + return + var/area/turfarea = get_area(T) + var/mob/camera/aiEye/remote/xenobio/X = eyeobj + if(turfarea.name == X.allowed_area || turfarea.xenobiology_compatible) + for(var/mob/living/simple_animal/slime/S in stored_slimes) + S.forceMove(T) S.visible_message("[S] warps in!") - X.stored_slimes -= S - else - to_chat(owner, "Target is not near a camera. Cannot proceed.") + stored_slimes -= S -/datum/action/innate/slime_pick_up - name = "Pick up Slime" - icon_icon = 'icons/mob/actions/actions_silicon.dmi' - button_icon_state = "slime_up" - -/datum/action/innate/slime_pick_up/Activate() - if(!target || !isliving(owner)) +//Place monkey +/obj/machinery/computer/camera_advanced/xenobio/proc/XenoTurfClickCtrl(mob/living/user, turf/open/T) + if(!(upgradetier & XENOBIO_UPGRADE_MONKEYS)) return - var/mob/living/C = owner - var/mob/camera/aiEye/remote/xenobio/remote_eye = C.remote_control - var/obj/machinery/computer/camera_advanced/xenobio/X = target - - if(GLOB.cameranet.checkTurfVis(remote_eye.loc)) - for(var/mob/living/simple_animal/slime/S in remote_eye.loc) - if(X.stored_slimes.len >= X.max_slimes) - break - if(!S.ckey) - if(S.buckled) - S.Feedstop(silent = TRUE) - S.visible_message("[S] vanishes in a flash of light!") - S.forceMove(X) - X.stored_slimes += S - else - to_chat(owner, "Target is not near a camera. Cannot proceed.") - - -/datum/action/innate/feed_slime - name = "Feed Slimes" - icon_icon = 'icons/mob/actions/actions_silicon.dmi' - button_icon_state = "monkey_down" - -/datum/action/innate/feed_slime/Activate() - if(!target || !isliving(owner)) + if(!GLOB.cameranet.checkTurfVis(T)) + to_chat(user, "Target is not near a camera. Cannot proceed.") return - var/mob/living/C = owner - var/mob/camera/aiEye/remote/xenobio/remote_eye = C.remote_control - var/obj/machinery/computer/camera_advanced/xenobio/X = target + var/area/turfarea = get_area(T) + var/mob/camera/aiEye/remote/xenobio/X = eyeobj + if(turfarea.name == X.allowed_area || turfarea.xenobiology_compatible) + if(monkeys >= 1) + var/mob/living/carbon/monkey/food = new/mob/living/carbon/monkey(T, TRUE, user) + if(!QDELETED(food)) + food.LAssailant = user + monkeys = round(monkeys-1, 0.1) + to_chat(user, "[src] now has [monkeys] monkeys stored.") - if(GLOB.cameranet.checkTurfVis(remote_eye.loc)) - if(X.monkeys >= 1) - var/mob/living/carbon/monkey/food = new /mob/living/carbon/monkey(remote_eye.loc, TRUE, owner) - if (!QDELETED(food)) - food.LAssailant = C - X.monkeys -- - to_chat(owner, "[X] now has [X.monkeys] monkeys left.") - else - to_chat(owner, "Target is not near a camera. Cannot proceed.") - - -/datum/action/innate/monkey_recycle - name = "Recycle Monkeys" - icon_icon = 'icons/mob/actions/actions_silicon.dmi' - button_icon_state = "monkey_up" - -/datum/action/innate/monkey_recycle/Activate() - if(!target || !isliving(owner)) +//Pick up monkey +/obj/machinery/computer/camera_advanced/xenobio/proc/XenoMonkeyClickCtrl(mob/living/user, mob/living/carbon/monkey/M) + if(!(upgradetier & XENOBIO_UPGRADE_MONKEYS)) return - var/mob/living/C = owner - var/mob/camera/aiEye/remote/xenobio/remote_eye = C.remote_control - var/obj/machinery/computer/camera_advanced/xenobio/X = target - - 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!") - X.monkeys = round(X.monkeys + 0.2,0.1) - qdel(M) - else - to_chat(owner, "Target is not near a camera. Cannot proceed.") - -/datum/action/innate/slime_scan - name = "Scan Slime" - icon_icon = 'icons/mob/actions/actions_silicon.dmi' - button_icon_state = "slime_scan" - -/datum/action/innate/slime_scan/Activate() - if(!target || !isliving(owner)) + if(!connected_recycler) + to_chat(user, "There is no connected monkey recycler. You can connect one with a multitool.") return - var/mob/living/C = owner - var/mob/camera/aiEye/remote/xenobio/remote_eye = C.remote_control - - if(GLOB.cameranet.checkTurfVis(remote_eye.loc)) - 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.") - -/datum/action/innate/feed_potion - name = "Apply Potion" - icon_icon = 'icons/mob/actions/actions_silicon.dmi' - button_icon_state = "slime_potion" - -/datum/action/innate/feed_potion/Activate() - if(!target || !isliving(owner)) + if(!GLOB.cameranet.checkTurfVis(M.loc)) + to_chat(user, "Target is not near a camera. Cannot proceed.") return + var/area/mobarea = get_area(M.loc) + var/mob/camera/aiEye/remote/xenobio/X = eyeobj + if(mobarea.name == X.allowed_area || mobarea.xenobiology_compatible) + if(!M.stat) + return + M.visible_message("[M] vanishes as [M.p_theyre()] reclaimed for recycling!") + connected_recycler.use_power(500) + monkeys += connected_recycler.cube_production + to_chat(user, "[src] now has [monkeys] monkeys available.") + qdel(M) - var/mob/living/C = owner - var/mob/camera/aiEye/remote/xenobio/remote_eye = C.remote_control - var/obj/machinery/computer/camera_advanced/xenobio/X = target - - if(QDELETED(X.current_potion)) - to_chat(owner, "No potion loaded.") +// 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/area/mobarea = get_area(S.loc) + var/mob/camera/aiEye/remote/xenobio/X = eyeobj + if(mobarea.name == X.allowed_area || mobarea.xenobiology_compatible) + slime_scan(S, user) - if(GLOB.cameranet.checkTurfVis(remote_eye.loc)) - for(var/mob/living/simple_animal/slime/S in remote_eye.loc) - X.current_potion.attack(S, C) - break - else - to_chat(owner, "Target is not near a camera. Cannot proceed.") +//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_SLIMEBASIC)) + return + if(!GLOB.cameranet.checkTurfVis(S.loc)) + to_chat(user, "Target is not near a camera. Cannot proceed.") + return + var/area/mobarea = get_area(S.loc) + if(QDELETED(current_potion)) + to_chat(user, "No potion loaded.") + return + var/mob/camera/aiEye/remote/xenobio/X = eyeobj + if(mobarea.name == X.allowed_area || mobarea.xenobiology_compatible) + current_potion.attack(S, user) diff --git a/icons/mob/actions/actions_silicon.dmi b/icons/mob/actions/actions_silicon.dmi index cd997a25..cf3d7a2a 100644 Binary files a/icons/mob/actions/actions_silicon.dmi and b/icons/mob/actions/actions_silicon.dmi differ