diff --git a/code/__DEFINES/components.dm b/code/__DEFINES/components.dm index 87b9094b47e..02b36614cb5 100644 --- a/code/__DEFINES/components.dm +++ b/code/__DEFINES/components.dm @@ -274,4 +274,12 @@ //Ouch my toes! #define CALTROP_BYPASS_SHOES 1 -#define CALTROP_IGNORE_WALKERS 2 \ No newline at end of file +#define CALTROP_IGNORE_WALKERS 2 + +//Xenobio hotkeys +#define COMSIG_XENO_SLIME_CLICK_CTRL "xeno_slime_click_ctrl" //from slime CtrlClickOn(): (/mob) +#define COMSIG_XENO_SLIME_CLICK_ALT "xeno_slime_click_alt" //from slime AltClickOn(): (/mob) +#define COMSIG_XENO_SLIME_CLICK_SHIFT "xeno_slime_click_shift" //from slime ShiftClickOn(): (/mob) +#define COMSIG_XENO_TURF_CLICK_SHIFT "xeno_turf_click_shift" //from turf ShiftClickOn(): (/mob) +#define COMSIG_XENO_TURF_CLICK_CTRL "xeno_turf_click_alt" //from turf AltClickOn(): (/mob) +#define COMSIG_XENO_MONKEY_CLICK_CTRL "xeno_monkey_click_ctrl" //from monkey CtrlClickOn(): (/mob) \ No newline at end of file diff --git a/code/game/objects/items/devices/scanners.dm b/code/game/objects/items/devices/scanners.dm index dd214c7a673..8ad7fae6d2d 100644 --- a/code/game/objects/items/devices/scanners.dm +++ b/code/game/objects/items/devices/scanners.dm @@ -526,6 +526,9 @@ REAGENT SCANNER materials = list(MAT_METAL=30, MAT_GLASS=20) /obj/item/slime_scanner/attack(mob/living/M as mob, mob/living/user as mob) + slime_scan(M, user) + +/proc/slime_scan(mob/living/carbon/slime/M, mob/living/user) if(!isslime(M)) user.show_message("This device can only scan slimes!", 1) return diff --git a/code/modules/food_and_drinks/kitchen_machinery/monkeyrecycler.dm b/code/modules/food_and_drinks/kitchen_machinery/monkeyrecycler.dm index 8fe5d2cf4d8..1b8f61bb7bf 100644 --- a/code/modules/food_and_drinks/kitchen_machinery/monkeyrecycler.dm +++ b/code/modules/food_and_drinks/kitchen_machinery/monkeyrecycler.dm @@ -1,3 +1,5 @@ +GLOBAL_LIST_EMPTY(monkey_recyclers) + /obj/machinery/monkey_recycler name = "Monkey Recycler" desc = "A machine used for recycling dead monkeys into monkey cubes." @@ -14,6 +16,7 @@ var/cube_production = 1 var/cycle_through = 0 var/obj/item/reagent_containers/food/snacks/monkeycube/cube_type = /obj/item/reagent_containers/food/snacks/monkeycube + var/list/connected = list() /obj/machinery/monkey_recycler/New() ..() @@ -21,8 +24,15 @@ component_parts += new /obj/item/circuitboard/monkey_recycler(null) component_parts += new /obj/item/stock_parts/manipulator(null) component_parts += new /obj/item/stock_parts/matter_bin(null) + GLOB.monkey_recyclers += src RefreshParts() +/obj/machinery/monkey_recycler/Destroy() + GLOB.monkey_recyclers -= src + for(var/obj/machinery/computer/camera_advanced/xenobio/console in connected) + console.connected_recycler = null + return ..() + /obj/machinery/monkey_recycler/RefreshParts() var/req_grind = 5 var/cubes_made = 1 @@ -47,21 +57,25 @@ default_deconstruction_crowbar(O) if(istype(O, /obj/item/multitool)) - cycle_through++ - switch(cycle_through) - if(1) - cube_type = /obj/item/reagent_containers/food/snacks/monkeycube/farwacube - if(2) - cube_type = /obj/item/reagent_containers/food/snacks/monkeycube/wolpincube - if(3) - cube_type = /obj/item/reagent_containers/food/snacks/monkeycube/stokcube - if(4) - cube_type = /obj/item/reagent_containers/food/snacks/monkeycube/neaeracube - if(5) - cube_type = /obj/item/reagent_containers/food/snacks/monkeycube - cycle_through = 0 - to_chat(user, "You change the monkeycube type to [initial(cube_type.name)].") - + if(!panel_open) + cycle_through++ + switch(cycle_through) + if(1) + cube_type = /obj/item/reagent_containers/food/snacks/monkeycube/farwacube + if(2) + cube_type = /obj/item/reagent_containers/food/snacks/monkeycube/wolpincube + if(3) + cube_type = /obj/item/reagent_containers/food/snacks/monkeycube/stokcube + if(4) + cube_type = /obj/item/reagent_containers/food/snacks/monkeycube/neaeracube + if(5) + cube_type = /obj/item/reagent_containers/food/snacks/monkeycube + cycle_through = 0 + to_chat(user, "You change the monkeycube type to [initial(cube_type.name)].") + else + var/obj/item/multitool/M = O + M.buffer = src + to_chat(user, "You log [src] in the [M]'s buffer.") if(stat != 0) //NOPOWER etc return if(istype(O, /obj/item/grab)) diff --git a/code/modules/reagents/chemistry/recipes/slime_extracts.dm b/code/modules/reagents/chemistry/recipes/slime_extracts.dm index aa457938afc..afbc94a9455 100644 --- a/code/modules/reagents/chemistry/recipes/slime_extracts.dm +++ b/code/modules/reagents/chemistry/recipes/slime_extracts.dm @@ -250,7 +250,7 @@ /datum/chemical_reaction/slimestabilizer/on_reaction(datum/reagents/holder) feedback_add_details("slime_cores_used","[type]") - var/obj/item/slimepotion/stabilizer/P = new /obj/item/slimepotion/stabilizer + var/obj/item/slimepotion/slime/stabilizer/P = new /obj/item/slimepotion/slime/stabilizer P.forceMove(get_turf(holder.my_atom)) //Dark Blue @@ -380,7 +380,7 @@ /datum/chemical_reaction/slimepsteroid/on_reaction(datum/reagents/holder) feedback_add_details("slime_cores_used","[type]") - var/obj/item/slimepotion/steroid/P = new /obj/item/slimepotion/steroid + var/obj/item/slimepotion/slime/steroid/P = new /obj/item/slimepotion/slime/steroid P.forceMove(get_turf(holder.my_atom)) /datum/chemical_reaction/slimejam @@ -423,7 +423,7 @@ /datum/chemical_reaction/slimemutator/on_reaction(datum/reagents/holder) feedback_add_details("slime_cores_used","[type]") - var/obj/item/slimepotion/mutator/P = new /obj/item/slimepotion/mutator + var/obj/item/slimepotion/slime/mutator/P = new /obj/item/slimepotion/slime/mutator P.forceMove(get_turf(holder.my_atom)) /datum/chemical_reaction/slimebloodlust @@ -469,7 +469,7 @@ /datum/chemical_reaction/docility/on_reaction(datum/reagents/holder) feedback_add_details("slime_cores_used","[type]") - var/obj/item/slimepotion/docility/P = new /obj/item/slimepotion/docility + var/obj/item/slimepotion/slime/docility/P = new /obj/item/slimepotion/slime/docility P.forceMove(get_turf(holder.my_atom)) diff --git a/code/modules/research/xenobiology/xenobio_camera.dm b/code/modules/research/xenobiology/xenobio_camera.dm index 29a3cd26600..b695ca3a1b4 100644 --- a/code/modules/research/xenobiology/xenobio_camera.dm +++ b/code/modules/research/xenobiology/xenobio_camera.dm @@ -26,14 +26,33 @@ var/datum/action/innate/slime_pick_up/slime_up_action = new var/datum/action/innate/feed_slime/feed_slime_action = new var/datum/action/innate/monkey_recycle/monkey_recycle_action = new + var/datum/action/innate/slime_scan/scan_action = new + var/datum/action/innate/feed_potion/potion_action = new + var/datum/action/innate/hotkey_help/hotkey_help = new var/list/stored_slimes = list() var/max_slimes = 5 var/monkeys = 0 + 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/New() + ..() + 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 + +/obj/machinery/computer/camera_advanced/xenobio/Destroy() + QDEL_NULL(current_potion) + for(var/mob/living/carbon/slime/S in stored_slimes) + S.forceMove(drop_location()) + stored_slimes.Cut() + return ..() + /obj/machinery/computer/camera_advanced/xenobio/CreateEye() eyeobj = new /mob/camera/aiEye/remote/xenobio(get_turf(src)) eyeobj.origin = src @@ -43,26 +62,63 @@ /obj/machinery/computer/camera_advanced/xenobio/GrantActions(mob/living/carbon/user) ..() + if(slime_up_action) slime_up_action.target = src slime_up_action.Grant(user) actions += slime_up_action - + if(slime_place_action) slime_place_action.target = src slime_place_action.Grant(user) actions += slime_place_action - + if(feed_slime_action) feed_slime_action.target = src feed_slime_action.Grant(user) actions += feed_slime_action - + if(monkey_recycle_action) 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) + potion_action.target = src + 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) + + 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 + +/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/attack_hand(mob/user) if(!ishuman(user)) //AIs using it might be weird @@ -71,11 +127,20 @@ /obj/machinery/computer/camera_advanced/xenobio/attackby(obj/item/O, mob/user, params) if(istype(O, /obj/item/reagent_containers/food/snacks/monkeycube)) - monkeys++ - to_chat(user, "You feed [O] to [src]. It now has [monkeys] monkey cubes stored.") - user.drop_item() - qdel(O) - return + if(user.drop_item()) + monkeys++ + to_chat(user, "You feed [O] to [src]. It now has [monkeys] monkey cubes stored.") + 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" : ""].") + return else if(istype(O, /obj/item/storage/bag)) var/obj/item/storage/P = O var/loaded = 0 @@ -87,6 +152,13 @@ if(loaded) to_chat(user, "You fill [src] with the monkey cubes stored in [O]. [src] now has [monkeys] monkey cubes stored.") return + else if(ismultitool(O)) + var/obj/item/multitool/I = O + if(istype(I.buffer, /obj/machinery/monkey_recycler)) + to_chat(user, "You link [src] with [I.buffer] in [I] buffer.") + connected_recycler = I.buffer + connected_recycler.connected += src + return ..() /datum/action/innate/slime_place @@ -163,12 +235,201 @@ var/mob/living/carbon/human/C = owner var/mob/camera/aiEye/remote/xenobio/remote_eye = C.remote_control var/obj/machinery/computer/camera_advanced/xenobio/X = target - + var/obj/machinery/monkey_recycler/recycler = X.connected_recycler + + if(!recycler) + to_chat(owner, "There is no connected monkey recycler. Use a multitool to link one.") + return if(cameranet.checkTurfVis(remote_eye.loc)) for(var/mob/living/carbon/human/M in remote_eye.loc) if(issmall(M) && M.stat) M.visible_message("[M] vanishes as [M.p_theyre()] reclaimed for recycling!") - X.monkeys = round(X.monkeys + 0.2,0.1) + recycler.use_power(500) + 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.") \ No newline at end of file + to_chat(owner, "Target is not near a camera. Cannot proceed.") + +/datum/action/innate/slime_scan + name = "Scan Slime" + button_icon_state = "slime_scan" + +/datum/action/innate/slime_scan/Activate() + if(!target || !isliving(owner)) + return + var/mob/living/C = owner + var/mob/camera/aiEye/remote/xenobio/remote_eye = C.remote_control + + if(cameranet.checkTurfVis(remote_eye.loc)) + for(var/mob/living/carbon/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" + button_icon_state = "slime_potion" + +/datum/action/innate/feed_potion/Activate() + if(!target || !ishuman(owner)) + return + + var/mob/living/carbon/human/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.") + return + + if(cameranet.checkTurfVis(remote_eye.loc)) + for(var/mob/living/carbon/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.") + +/datum/action/innate/hotkey_help + name = "Hotkey Help" + 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.") + 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.") + +// +// Alternate clicks for slime, monkey and open turf if using a xenobio console + +// Scans slime +/mob/living/carbon/slime/CtrlClick(mob/user) + SEND_SIGNAL(user, COMSIG_XENO_SLIME_CLICK_CTRL, src) + ..() + +//Feeds a potion to slime +/mob/living/carbon/slime/AltClick(mob/user) + SEND_SIGNAL(user, COMSIG_XENO_SLIME_CLICK_ALT, src) + ..() + +//Picks up slime +/mob/living/carbon/slime/ShiftClick(mob/user) + SEND_SIGNAL(user, COMSIG_XENO_SLIME_CLICK_SHIFT, src) + ..() + +//Place slimes +/turf/simulated/ShiftClick(mob/user) + SEND_SIGNAL(user, COMSIG_XENO_TURF_CLICK_SHIFT, src) + ..() + +//Place monkey +/turf/simulated/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/carbon/slime/S) + if(!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/carbon/slime/S) + if(!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/carbon/slime/S) + if(!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) + return + if(!S.ckey) + if(S.buckled) + S.buckled.unbuckle_mob() + S.Feedstop() + 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/T) + if(!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/carbon/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/T) + if(!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/human/monkey/food = new /mob/living/carbon/human/monkey(T) + food.LAssailant = C + X.monkeys -- + X.monkeys = round(X.monkeys, 0.1) + to_chat(user, "[X] now has [X.monkeys] monkeys left.") + +//Pick up monkey +/obj/machinery/computer/camera_advanced/xenobio/proc/XenoMonkeyClickCtrl(mob/living/user, mob/living/carbon/monkey/M) + if(!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) + var/obj/machinery/monkey_recycler/recycler = X.connected_recycler + if(!recycler) + to_chat(C, "There is no connected monkey recycler. Use a multitool to link one.") + return + if(mobarea.name == E.allowed_area || mobarea.xenobiology_compatible) + 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) + qdel(M) diff --git a/code/modules/research/xenobiology/xenobiology.dm b/code/modules/research/xenobiology/xenobiology.dm index 02e6b155025..0c67888b444 100644 --- a/code/modules/research/xenobiology/xenobiology.dm +++ b/code/modules/research/xenobiology/xenobiology.dm @@ -132,14 +132,14 @@ to_chat(user, "You cannot transfer [src] to [target]! It appears the potion must be given directly to a slime to absorb.") // le fluff faec return -/obj/item/slimepotion/docility +/obj/item/slimepotion/slime/docility name = "docility potion" desc = "A potent chemical mix that nullifies a slime's hunger, causing it to become docile and tame." icon = 'icons/obj/chemical.dmi' icon_state = "bottle19" var/being_used = 0 -/obj/item/slimepotion/docility/attack(mob/living/carbon/slime/M, mob/user) +/obj/item/slimepotion/slime/docility/attack(mob/living/carbon/slime/M, mob/user) if(!isslime(M)) to_chat(user, "The potion only works on slimes!") return @@ -260,13 +260,13 @@ SM.name = "[SM.name] as [user.real_name]" qdel(src) -/obj/item/slimepotion/steroid +/obj/item/slimepotion/slime/steroid name = "slime steroid" desc = "A potent chemical mix that will cause a baby slime to generate more extract." icon = 'icons/obj/chemical.dmi' icon_state = "bottle16" -/obj/item/slimepotion/steroid/attack(mob/living/carbon/slime/M, mob/user) +/obj/item/slimepotion/slime/steroid/attack(mob/living/carbon/slime/M, mob/user) if(!isslime(M))//If target is not a slime. to_chat(user, "The steroid only works on baby slimes!") return ..() @@ -290,13 +290,13 @@ icon = 'icons/obj/chemical.dmi' icon_state = "bottle17" -/obj/item/slimepotion/stabilizer +/obj/item/slimepotion/slime/stabilizer name = "slime stabilizer" desc = "A potent chemical mix that will reduce the chance of a slime mutating." icon = 'icons/obj/chemical.dmi' icon_state = "bottle15" -/obj/item/slimepotion/stabilizer/attack(mob/living/carbon/slime/M, mob/user) +/obj/item/slimepotion/slime/stabilizer/attack(mob/living/carbon/slime/M, mob/user) if(!isslime(M)) to_chat(user, "The stabilizer only works on slimes!") return ..() @@ -311,13 +311,13 @@ M.mutation_chance = Clamp(M.mutation_chance-15,0,100) qdel(src) -/obj/item/slimepotion/mutator +/obj/item/slimepotion/slime/mutator name = "slime mutator" desc = "A potent chemical mix that will increase the chance of a slime mutating." icon = 'icons/obj/chemical.dmi' icon_state = "bottle3" -/obj/item/slimepotion/mutator/attack(mob/living/carbon/slime/M, mob/user) +/obj/item/slimepotion/slime/mutator/attack(mob/living/carbon/slime/M, mob/user) if(!isslime(M)) to_chat(user, "The mutator only works on slimes!") return ..() diff --git a/icons/mob/actions/actions.dmi b/icons/mob/actions/actions.dmi index 08e645c5c9b..d21323c80b1 100644 Binary files a/icons/mob/actions/actions.dmi and b/icons/mob/actions/actions.dmi differ