diff --git a/code/game/objects/items/devices/scanners.dm b/code/game/objects/items/devices/scanners.dm
index 932e730b085..e3a274326f0 100644
--- a/code/game/objects/items/devices/scanners.dm
+++ b/code/game/objects/items/devices/scanners.dm
@@ -548,8 +548,7 @@ REAGENT SCANNER
if(!isslime(M))
to_chat(user, "This device can only scan slimes!")
return
- var/mob/living/simple_animal/slime/T = M
- slime_scan(T, user)
+ slime_scan(M, user)
/proc/slime_scan(mob/living/simple_animal/slime/T, mob/living/user)
to_chat(user, "========================")
diff --git a/code/modules/food_and_drinks/kitchen_machinery/monkeyrecycler.dm b/code/modules/food_and_drinks/kitchen_machinery/monkeyrecycler.dm
index 76792806490..8510e6bce62 100644
--- a/code/modules/food_and_drinks/kitchen_machinery/monkeyrecycler.dm
+++ b/code/modules/food_and_drinks/kitchen_machinery/monkeyrecycler.dm
@@ -25,6 +25,7 @@ GLOBAL_LIST_EMPTY(monkey_recyclers)
component_parts += new /obj/item/stock_parts/matter_bin(null)
GLOB.monkey_recyclers += src
RefreshParts()
+ locate_camera_console()
/obj/machinery/monkey_recycler/Destroy()
GLOB.monkey_recyclers -= src
@@ -34,6 +35,15 @@ GLOBAL_LIST_EMPTY(monkey_recyclers)
connected.Cut()
return ..()
+/obj/machinery/monkey_recycler/proc/locate_camera_console()
+ if(length(connected))
+ return // we're already connected!
+ for(var/obj/machinery/computer/camera_advanced/xenobio/xeno_camera in GLOB.machines)
+ if(get_area(xeno_camera) == get_area(loc))
+ xeno_camera.connected_recycler = src
+ connected |= xeno_camera
+ break
+
/obj/machinery/monkey_recycler/RefreshParts()
var/req_grind = 5
var/cubes_made = 1
@@ -92,6 +102,7 @@ GLOBAL_LIST_EMPTY(monkey_recyclers)
else
user.drop_item()
qdel(target)
+ target = null //we sleep in this proc, clear reference NOW
to_chat(user, "You stuff the monkey in the machine.")
playsound(loc, 'sound/machines/juicer.ogg', 50, 1)
var/offset = prob(50) ? -2 : 2
diff --git a/code/modules/food_and_drinks/kitchen_machinery/processor.dm b/code/modules/food_and_drinks/kitchen_machinery/processor.dm
index 54291db7963..b71bdd1bb20 100644
--- a/code/modules/food_and_drinks/kitchen_machinery/processor.dm
+++ b/code/modules/food_and_drinks/kitchen_machinery/processor.dm
@@ -51,6 +51,7 @@
var/output
var/time = 40
+/// WHO NAME A PARAMETER FOR A PROC "what" holy hell
/datum/food_processor_process/proc/process_food(loc, what, obj/machinery/processor/processor)
if(output && loc && processor)
for(var/i = 0, i < processor.rating_amount, i++)
diff --git a/code/modules/mob/living/simple_animal/slime/slime_death.dm b/code/modules/mob/living/simple_animal/slime/slime_death.dm
index 8dbcefac68a..8aa4e2f67f0 100644
--- a/code/modules/mob/living/simple_animal/slime/slime_death.dm
+++ b/code/modules/mob/living/simple_animal/slime/slime_death.dm
@@ -1,6 +1,10 @@
/mob/living/simple_animal/slime/death(gibbed)
if(stat == DEAD)
return
+
+ if(buckled)
+ Feedstop(silent = TRUE) //releases ourselves from the mob we fed on.
+
if(!gibbed)
if(is_adult)
var/mob/living/simple_animal/slime/M = new(loc, colour)
@@ -18,9 +22,6 @@
update_name()
return
- if(buckled)
- Feedstop(silent = TRUE) //releases ourselves from the mob we fed on.
-
set_stat(DEAD) //Temporarily set to dead for icon updates
regenerate_icons()
set_stat(CONSCIOUS)
diff --git a/code/modules/mob/living/simple_animal/slime/slime_mob.dm b/code/modules/mob/living/simple_animal/slime/slime_mob.dm
index 96fac4bdd19..ac613a4d69c 100644
--- a/code/modules/mob/living/simple_animal/slime/slime_mob.dm
+++ b/code/modules/mob/living/simple_animal/slime/slime_mob.dm
@@ -351,6 +351,7 @@
discipline_slime(M)
+
/mob/living/simple_animal/slime/attackby(obj/item/I, mob/living/user, params)
if(stat == DEAD && surgeries.len)
if(user.a_intent == INTENT_HELP || user.a_intent == INTENT_DISARM)
@@ -362,6 +363,7 @@
++Friends[user]
else
Friends[user] = 1
+ RegisterSignal(user, COMSIG_PARENT_QDELETING, PROC_REF(clear_friend))
to_chat(user, "You feed the slime the plasma. It chirps happily.")
var/obj/item/stack/sheet/mineral/plasma/S = I
S.use(1)
@@ -381,50 +383,12 @@
force_effect = round(I.force / 2)
if(prob(10 + force_effect))
discipline_slime(user)
-/* if(istype(I, /obj/item/storage/bag/bio))
- var/obj/item/storage/P = I
- if(!effectmod)
- to_chat(user, "The slime is not currently being mutated.")
- return
- var/hasOutput = FALSE //Have we outputted text?
- var/hasFound = FALSE //Have we found an extract to be added?
- for(var/obj/item/slime_extract/S in P.contents)
- if(S.effectmod == effectmod)
- SEND_SIGNAL(P, COMSIG_TRY_STORAGE_TAKE, S, get_turf(src), TRUE)
- qdel(S)
- applied++
- hasFound = TRUE
- if(applied >= SLIME_EXTRACT_CROSSING_REQUIRED)
- to_chat(user, "You feed the slime as many of the extracts from the bag as you can, and it mutates!")
- playsound(src, 'sound/effects/attackblob.ogg', 50, TRUE)
- spawn_corecross()
- hasOutput = TRUE
- break
- if(!hasOutput)
- if(!hasFound)
- to_chat(user, "There are no extracts in the bag that this slime will accept!")
- else
- to_chat(user, "You feed the slime some extracts from the bag.")
- playsound(src, 'sound/effects/attackblob.ogg', 50, TRUE)
- return */
..()
-/*
-/mob/living/simple_animal/slime/proc/spawn_corecross()
- var/static/list/crossbreeds = subtypesof(/obj/item/slimecross)
- visible_message("[src] shudders, its mutated core consuming the rest of its body!")
- playsound(src, 'sound/magic/smoke.ogg', 50, TRUE)
- var/crosspath
- for(var/X in crossbreeds)
- var/obj/item/slimecross/S = X
- if(initial(S.colour) == colour && initial(S.effect) == effectmod)
- crosspath = S
- break
- if(crosspath)
- new crosspath(loc)
- else
- visible_message("The mutated core shudders, and collapses into a puddle, unable to maintain its form.")
- qdel(src)
-*/
+
+/mob/living/simple_animal/slime/proc/clear_friend(mob/living/friend)
+ UnregisterSignal(friend, COMSIG_PARENT_QDELETING)
+ Friends -= friend
+
/mob/living/simple_animal/slime/water_act(volume, temperature, source, method = REAGENT_TOUCH)
. = ..()
var/water_damage = rand(10, 15) * volume
diff --git a/code/modules/mob/living/simple_animal/slime/slime_powers.dm b/code/modules/mob/living/simple_animal/slime/slime_powers.dm
index a4ac4d4a242..e8686b5f09a 100644
--- a/code/modules/mob/living/simple_animal/slime/slime_powers.dm
+++ b/code/modules/mob/living/simple_animal/slime/slime_powers.dm
@@ -170,6 +170,9 @@
to_chat(src, "I must be conscious to do this...")
return
+ if(istype(loc, /obj/machinery/computer/camera_advanced/xenobio))
+ return //no you cannot split while you're in the matrix (this prevents GC issues and slimes disappearing)
+
var/list/babies = list()
var/new_nutrition = round(nutrition * 0.9)
var/new_powerlevel = round(powerlevel / 4)
@@ -187,7 +190,7 @@
M.set_nutrition(new_nutrition) //Player slimes are more robust at spliting. Once an oversight of poor copypasta, now a feature!
M.powerlevel = new_powerlevel
if(i != 1)
- step_away(M,src)
+ step_away(M, get_turf(src))
M.Friends = Friends.Copy()
babies += M
M.mutation_chance = clamp(mutation_chance+(rand(5,-5)),0,100)
diff --git a/code/modules/research/xenobiology/xenobio_camera.dm b/code/modules/research/xenobiology/xenobio_camera.dm
index bf500c3a845..531dc923780 100644
--- a/code/modules/research/xenobiology/xenobio_camera.dm
+++ b/code/modules/research/xenobiology/xenobio_camera.dm
@@ -3,27 +3,38 @@
visible_icon = 1
icon = 'icons/obj/abductor.dmi'
icon_state = "camera_target"
- var/allowed_area = null
// The Xenobio Console does not trigger the AI Detector
ai_detector_visible = FALSE
+ /// Area that the xenobio camera eye is allowed to travel
+ var/allowed_area = null
-/mob/camera/aiEye/remote/xenobio/New(loc)
+/mob/camera/aiEye/remote/xenobio/Initialize(mapload)
+ . = ..()
var/area/A = get_area(loc)
allowed_area = A.name
- ..()
/mob/camera/aiEye/remote/xenobio/setLoc(t)
var/area/new_area = get_area(t)
- if(new_area && new_area.name == allowed_area || new_area && new_area.xenobiology_compatible)
- return ..()
- else
+ if(!new_area)
return
+ if(new_area.name != allowed_area && !new_area.xenobiology_compatible)
+ return
+ return ..()
+/*
+ * # Slime Management Console
+ *
+ * Camera overview console for xenobiology, handles slime management and xenobio actions
+*/
/obj/machinery/computer/camera_advanced/xenobio
name = "slime management console"
desc = "A computer used for remotely handling slimes."
+ icon_screen = "slime_comp"
+ icon_keyboard = "rd_key"
networks = list("SS13")
circuit = /obj/item/circuitboard/xenobiology
+
+
var/datum/action/innate/slime_place/slime_place_action = new
var/datum/action/innate/slime_pick_up/slime_up_action = new
var/datum/action/innate/feed_slime/feed_slime_action = new
@@ -38,19 +49,17 @@
var/obj/item/slimepotion/slime/current_potion
var/obj/machinery/monkey_recycler/connected_recycler
- icon_screen = "slime_comp"
- icon_keyboard = "rd_key"
-
/obj/machinery/computer/camera_advanced/xenobio/Initialize(mapload)
- ..()
- return INITIALIZE_HINT_LATELOAD
+ . = ..()
+ if(!connected_recycler)
+ locate_recycler()
-/obj/machinery/computer/camera_advanced/xenobio/LateInitialize()
- ..()
+/obj/machinery/computer/camera_advanced/xenobio/proc/locate_recycler()
for(var/obj/machinery/monkey_recycler/recycler in GLOB.monkey_recyclers)
- if(get_area(recycler.loc) == get_area(loc))
+ if(get_area(recycler) == get_area(loc))
connected_recycler = recycler
- connected_recycler.connected += src
+ connected_recycler.connected |= src
+ break
/obj/machinery/computer/camera_advanced/xenobio/Destroy()
QDEL_NULL(current_potion)
@@ -73,7 +82,7 @@
/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.acceleration = FALSE
eyeobj.icon = 'icons/obj/abductor.dmi'
eyeobj.icon_state = "camera_target"
@@ -124,10 +133,7 @@
RegisterSignal(user, COMSIG_XENO_MONKEY_CLICK_CTRL, PROC_REF(XenoMonkeyClickCtrl))
if(!connected_recycler)
- for(var/obj/machinery/monkey_recycler/recycler in GLOB.monkey_recyclers)
- if(get_area(recycler.loc) == get_area(loc))
- connected_recycler = recycler
- connected_recycler.connected += src
+ locate_recycler()
/obj/machinery/computer/camera_advanced/xenobio/remove_eye_control(mob/living/user)
UnregisterSignal(user, COMSIG_XENO_SLIME_CLICK_CTRL)
@@ -138,6 +144,33 @@
UnregisterSignal(user, COMSIG_XENO_MONKEY_CLICK_CTRL)
..()
+/obj/machinery/computer/camera_advanced/xenobio/proc/insert_potion(obj/item/slimepotion/slime/potion)
+ clear_potion()
+ potion.forceMove(src)
+ current_potion = potion
+ RegisterSignal(current_potion, COMSIG_PARENT_QDELETING, PROC_REF(clear_potion))
+
+/obj/machinery/computer/camera_advanced/xenobio/proc/clear_potion()
+ if(!QDELETED(current_potion))
+ current_potion.forceMove(drop_location())
+ UnregisterSignal(current_potion, COMSIG_PARENT_QDELETING)
+ current_potion = null
+
+/obj/machinery/computer/camera_advanced/xenobio/proc/capture_slime(mob/living/simple_animal/slime/slime)
+ slime.visible_message("[slime] vanishes in a flash of light!")
+ slime.forceMove(src)
+ stored_slimes += slime
+ RegisterSignal(slime, COMSIG_PARENT_QDELETING, PROC_REF(clear_slime))
+
+/obj/machinery/computer/camera_advanced/xenobio/proc/release_slime(mob/living/simple_animal/slime/slime, release_spot)
+ slime.visible_message("[slime] warps in!")
+ clear_slime(slime)
+ slime.forceMove(release_spot)
+
+/obj/machinery/computer/camera_advanced/xenobio/proc/clear_slime(mob/living/simple_animal/slime/slime)
+ UnregisterSignal(slime, COMSIG_PARENT_QDELETING)
+ stored_slimes -= slime
+
/obj/machinery/computer/camera_advanced/xenobio/attack_hand(mob/user)
if(!ishuman(user)) //AIs using it might be weird
return
@@ -151,13 +184,10 @@
qdel(O)
return
else if(istype(O, /obj/item/slimepotion/slime))
- var/replaced = FALSE
- if(user.drop_item())
- if(!QDELETED(current_potion))
- current_potion.forceMove(drop_location())
- replaced = TRUE
- current_potion = O
- to_chat(user, "You load [O] in the console's potion slot[replaced ? ", replacing the one that was there before" : ""].")
+ if(!user.drop_item())
+ return
+ to_chat(user, "You load [O] in the console's potion slot[current_potion ? ", replacing the one that was there before" : ""].")
+ insert_potion(O, user)
return
else if(istype(O, /obj/item/storage/bag) || istype(O, /obj/item/storage/box))
var/obj/item/storage/P = O
@@ -184,6 +214,7 @@
connected_recycler.connected += src
to_chat(user, "You link [src] to the recycler stored in [M]'s buffer.")
+// === SLIME ACTION DATUMS ====
/datum/action/innate/slime_place
name = "Place Slimes"
button_icon_state = "slime_down"
@@ -200,9 +231,7 @@
return
else if(GLOB.cameranet.checkTurfVis(remote_eye.loc))
for(var/mob/living/simple_animal/slime/S in X.stored_slimes)
- S.forceMove(remote_eye.loc)
- S.visible_message("[S] warps in!")
- X.stored_slimes -= S
+ X.release_slime(S, remote_eye.loc)
else
to_chat(owner, "Target is not near a camera. Cannot proceed.")
@@ -219,14 +248,12 @@
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)
+ if(length(X.stored_slimes) >= 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
+ X.capture_slime(S)
else
to_chat(owner, "Target is not near a camera. Cannot proceed.")
@@ -280,7 +307,7 @@
if(issmall(M) && M.stat)
M.visible_message("[M] vanishes as [M.p_theyre()] reclaimed for recycling!")
recycler.use_power(500)
- X.monkeys = round(X.monkeys + recycler.cube_production/recycler.required_grind, 0.1)
+ X.monkeys = round(X.monkeys + recycler.cube_production / recycler.required_grind, 0.1)
qdel(M)
else
to_chat(owner, "Target is not near a camera. Cannot proceed.")
@@ -331,12 +358,12 @@
/datum/action/innate/hotkey_help/Activate()
if(!target || !isliving(owner))
return
+ var/obj/machinery/computer/camera_advanced/xenobio/X = owner.machine
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.")
- var/obj/machinery/computer/camera_advanced/xenobio/X = owner.machine
to_chat(owner, "[X] now has [X.monkeys] monkeys left.")
//
@@ -393,7 +420,7 @@
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))
+ if(!X.current_potion)
to_chat(C, "No potion loaded.")
return
if(mobarea.name == E.allowed_area || mobarea.xenobiology_compatible)
@@ -409,7 +436,7 @@
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)
+ if(length(X.stored_slimes) >= X.max_slimes)
to_chat(C, "Slime storage is full.")
return
if(S.ckey)
@@ -417,9 +444,8 @@
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
+
+ X.capture_slime(S)
//Place slimes
/obj/machinery/computer/camera_advanced/xenobio/proc/XenoTurfClickShift(mob/living/user, turf/T)
@@ -435,9 +461,7 @@
return
else 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
+ X.release_slime(S, T)
//Place monkey
/obj/machinery/computer/camera_advanced/xenobio/proc/XenoTurfClickCtrl(mob/living/user, turf/T)
@@ -455,7 +479,7 @@
if(X.monkeys >= 1)
var/mob/living/carbon/human/monkey/food = new /mob/living/carbon/human/monkey(T)
food.LAssailant = C
- X.monkeys --
+ X.monkeys--
X.monkeys = round(X.monkeys, 0.1)
to_chat(user, "[X] now has [X.monkeys] monkeys left.")