From 3ecf74f1fdd4b81d84eae568eb0bf976521ea2d8 Mon Sep 17 00:00:00 2001 From: XDTM Date: Mon, 29 Jan 2018 10:59:14 +0100 Subject: [PATCH] Xenobiology consoles can now scan slimes and apply potions (#34748) * Xenobiology consoles can now scan slimes and apply potions * no smack --- code/game/objects/items/devices/scanners.dm | 5 +- code/modules/mining/machine_vending.dm | 2 +- code/modules/mining/minebot.dm | 2 +- .../chemistry/recipes/slime_extracts.dm | 10 +-- .../research/xenobiology/xenobio_camera.dm | 64 ++++++++++++++++++ .../research/xenobiology/xenobiology.dm | 64 +++++++++--------- code/modules/uplink/uplink_items.dm | 4 +- icons/mob/actions/actions_silicon.dmi | Bin 5891 -> 7018 bytes 8 files changed, 108 insertions(+), 43 deletions(-) diff --git a/code/game/objects/items/devices/scanners.dm b/code/game/objects/items/devices/scanners.dm index ca1feafe5e3..0d54cac1b12 100644 --- a/code/game/objects/items/devices/scanners.dm +++ b/code/game/objects/items/devices/scanners.dm @@ -425,6 +425,9 @@ GAS ANALYZER to_chat(user, "This device can only scan slimes!") return var/mob/living/simple_animal/slime/T = M + slime_scan(T, user) + +/proc/slime_scan(mob/living/simple_animal/slime/T, mob/living/user) to_chat(user, "Slime scan results:") to_chat(user, "[T.colour] [T.is_adult ? "adult" : "baby"] slime") to_chat(user, "Nutrition: [T.nutrition]/[T.get_max_nutrition()]") @@ -449,4 +452,4 @@ GAS ANALYZER to_chat(user, "Genetic destability: [T.mutation_chance] % chance of mutation on splitting") if (T.cores > 1) to_chat(user, "Anomalious slime core amount detected") - to_chat(user, "Growth progress: [T.amount_grown]/[SLIME_EVOLUTION_THRESHOLD]") + to_chat(user, "Growth progress: [T.amount_grown]/[SLIME_EVOLUTION_THRESHOLD]") \ No newline at end of file diff --git a/code/modules/mining/machine_vending.dm b/code/modules/mining/machine_vending.dm index c872756872d..71574104c60 100644 --- a/code/modules/mining/machine_vending.dm +++ b/code/modules/mining/machine_vending.dm @@ -55,7 +55,7 @@ new /datum/data/mining_equipment("Drone Melee Upgrade", /obj/item/device/mine_bot_ugprade, 400), new /datum/data/mining_equipment("Drone Health Upgrade", /obj/item/device/mine_bot_ugprade/health, 400), new /datum/data/mining_equipment("Drone Ranged Upgrade", /obj/item/device/mine_bot_ugprade/cooldown, 600), - new /datum/data/mining_equipment("Drone AI Upgrade", /obj/item/slimepotion/sentience/mining, 1000), + new /datum/data/mining_equipment("Drone AI Upgrade", /obj/item/slimepotion/slime/sentience/mining, 1000), new /datum/data/mining_equipment("Jump Boots", /obj/item/clothing/shoes/bhop, 2500), ) diff --git a/code/modules/mining/minebot.dm b/code/modules/mining/minebot.dm index 7caf57b0a64..3c33441561c 100644 --- a/code/modules/mining/minebot.dm +++ b/code/modules/mining/minebot.dm @@ -255,7 +255,7 @@ //AI -/obj/item/slimepotion/sentience/mining +/obj/item/slimepotion/slime/sentience/mining name = "minebot AI upgrade" desc = "Can be used to grant sentience to minebots." icon_state = "door_electronics" diff --git a/code/modules/reagents/chemistry/recipes/slime_extracts.dm b/code/modules/reagents/chemistry/recipes/slime_extracts.dm index 44f904b0a74..11d41ea20fc 100644 --- a/code/modules/reagents/chemistry/recipes/slime_extracts.dm +++ b/code/modules/reagents/chemistry/recipes/slime_extracts.dm @@ -194,7 +194,7 @@ required_other = 1 /datum/chemical_reaction/slime/slimestabilizer/on_reaction(datum/reagents/holder) - new /obj/item/slimepotion/stabilizer(get_turf(holder.my_atom)) + new /obj/item/slimepotion/slime/stabilizer(get_turf(holder.my_atom)) ..() /datum/chemical_reaction/slime/slimefoam @@ -326,7 +326,7 @@ required_other = 1 /datum/chemical_reaction/slime/slimepsteroid/on_reaction(datum/reagents/holder) - new /obj/item/slimepotion/steroid(get_turf(holder.my_atom)) + new /obj/item/slimepotion/slime/steroid(get_turf(holder.my_atom)) ..() /datum/chemical_reaction/slime/slimeregen @@ -358,7 +358,7 @@ required_other = 1 /datum/chemical_reaction/slime/slimemutator/on_reaction(datum/reagents/holder) - new /obj/item/slimepotion/mutator(get_turf(holder.my_atom)) + new /obj/item/slimepotion/slime/mutator(get_turf(holder.my_atom)) ..() /datum/chemical_reaction/slime/slimebloodlust @@ -394,7 +394,7 @@ required_other = 1 /datum/chemical_reaction/slime/docility/on_reaction(datum/reagents/holder) - new /obj/item/slimepotion/docility(get_turf(holder.my_atom)) + new /obj/item/slimepotion/slime/docility(get_turf(holder.my_atom)) ..() /datum/chemical_reaction/slime/gender @@ -465,7 +465,7 @@ required_other = 1 /datum/chemical_reaction/slime/slimepotion2/on_reaction(datum/reagents/holder) - new /obj/item/slimepotion/sentience(get_turf(holder.my_atom)) + new /obj/item/slimepotion/slime/sentience(get_turf(holder.my_atom)) ..() //Adamantine diff --git a/code/modules/research/xenobiology/xenobio_camera.dm b/code/modules/research/xenobiology/xenobio_camera.dm index ca929e5e9a7..45460eccbd3 100644 --- a/code/modules/research/xenobiology/xenobio_camera.dm +++ b/code/modules/research/xenobiology/xenobio_camera.dm @@ -26,8 +26,11 @@ 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/list/stored_slimes = list() + var/obj/item/slimepotion/slime/current_potion var/max_slimes = 5 var/monkeys = 0 @@ -66,6 +69,16 @@ 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 + /obj/machinery/computer/camera_advanced/xenobio/attackby(obj/item/O, mob/user, params) if(istype(O, /obj/item/reagent_containers/food/snacks/monkeycube)) monkeys++ @@ -83,6 +96,16 @@ 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(istype(O, /obj/item/slimepotion/slime)) + var/replaced = FALSE + if(user && !user.transferItemToLoc(O, src)) + return + 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 ..() /datum/action/innate/slime_place @@ -173,3 +196,44 @@ 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)) + 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)) + 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(QDELETED(X.current_potion)) + to_chat(owner, "No potion loaded.") + return + + 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.") diff --git a/code/modules/research/xenobiology/xenobiology.dm b/code/modules/research/xenobiology/xenobiology.dm index a072e160592..77f5a04c880 100644 --- a/code/modules/research/xenobiology/xenobiology.dm +++ b/code/modules/research/xenobiology/xenobiology.dm @@ -327,7 +327,7 @@ /obj/item/slime_extract/lightpink/activate(mob/living/carbon/human/user, datum/species/jelly/luminescent/species, activation_type) switch(activation_type) if(SLIME_ACTIVATE_MINOR) - var/obj/item/slimepotion/docility/O = new(null, 1) + var/obj/item/slimepotion/slime/docility/O = new(null, 1) if(!user.put_in_active_hand(O)) O.forceMove(user.drop_location()) playsound(user, 'sound/effects/splat.ogg', 50, 1) @@ -335,7 +335,7 @@ return 150 if(SLIME_ACTIVATE_MAJOR) - var/obj/item/slimepotion/sentience/O = new(null, 1) + var/obj/item/slimepotion/slime/sentience/O = new(null, 1) if(!user.put_in_active_hand(O)) O.forceMove(user.drop_location()) playsound(user, 'sound/effects/splat.ogg', 50, 1) @@ -539,19 +539,19 @@ to_chat(user, "You cannot transfer [src] to [target]! It appears the potion must be given directly to a slime to absorb." ) 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 = "potsilver" -/obj/item/slimepotion/docility/attack(mob/living/simple_animal/slime/M, mob/user) +/obj/item/slimepotion/slime/docility/attack(mob/living/simple_animal/slime/M, mob/user) if(!isslime(M)) to_chat(user, "The potion only works on slimes!") return ..() if(M.stat) to_chat(user, "The slime is dead!") - return ..() + return M.docile = 1 M.nutrition = 700 @@ -565,33 +565,31 @@ M.real_name = newname qdel(src) -/obj/item/slimepotion/sentience +/obj/item/slimepotion/slime/sentience name = "intelligence potion" desc = "A miraculous chemical mix that grants human like intelligence to living beings." icon = 'icons/obj/chemical.dmi' icon_state = "potpink" var/list/not_interested = list() - var/being_used = 0 + var/being_used = FALSE var/sentience_type = SENTIENCE_ORGANIC -/obj/item/slimepotion/sentience/afterattack(mob/living/M, mob/user) - if(being_used || !ismob(M) || !user.Adjacent(M)) +/obj/item/slimepotion/slime/sentience/attack(mob/living/M, mob/user) + if(being_used || !ismob(M)) return if(!isanimal(M) || M.ckey) //only works on animals that aren't player controlled to_chat(user, "[M] is already too intelligent for this to work!") - return ..() + return if(M.stat) to_chat(user, "[M] is dead!") - return ..() + return var/mob/living/simple_animal/SM = M if(SM.sentience_type != sentience_type) to_chat(user, "[src] won't work on [SM].") - return ..() - - + return to_chat(user, "You offer [src] to [SM]...") - being_used = 1 + being_used = TRUE var/list/candidates = pollCandidatesForMob("Do you want to play as [SM.name]?", ROLE_ALIEN, null, ROLE_ALIEN, 50, SM, POLL_IGNORE_SENTIENCE_POTION) // see poll_ignore.dm var/mob/dead/observer/theghost = null @@ -608,17 +606,17 @@ qdel(src) else to_chat(user, "[SM] looks interested for a moment, but then looks back down. Maybe you should try again later.") - being_used = 0 + being_used = FALSE ..() -/obj/item/slimepotion/sentience/proc/after_success(mob/living/user, mob/living/simple_animal/SM) +/obj/item/slimepotion/slime/sentience/proc/after_success(mob/living/user, mob/living/simple_animal/SM) return -/obj/item/slimepotion/sentience/nuclear +/obj/item/slimepotion/slime/sentience/nuclear name = "syndicate intelligence potion" desc = "A miraculous chemical mix that grants human like intelligence to living beings. It has been modified with Syndicate technology to also grant an internal radio implant to the target and authenticate with identification systems." -/obj/item/slimepotion/sentience/nuclear/after_success(mob/living/user, mob/living/simple_animal/SM) +/obj/item/slimepotion/slime/sentience/nuclear/after_success(mob/living/user, mob/living/simple_animal/SM) var/obj/item/implant/radio/imp = new(src) imp.implant(SM, user) @@ -667,25 +665,25 @@ 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 = "potred" -/obj/item/slimepotion/steroid/attack(mob/living/simple_animal/slime/M, mob/user) +/obj/item/slimepotion/slime/steroid/attack(mob/living/simple_animal/slime/M, mob/user) if(!isslime(M))//If target is not a slime. to_chat(user, "The steroid only works on baby slimes!") return ..() if(M.is_adult) //Can't steroidify adults to_chat(user, "Only baby slimes can use the steroid!") - return ..() + return if(M.stat) to_chat(user, "The slime is dead!") - return ..() + return if(M.cores >= 5) to_chat(user, "The slime already has the maximum amount of extract!") - return ..() + return to_chat(user, "You feed the slime the steroid. It will now produce one more extract.") M.cores++ @@ -697,46 +695,46 @@ icon = 'icons/obj/chemical.dmi' icon_state = "potpurple" -/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 = "potcyan" -/obj/item/slimepotion/stabilizer/attack(mob/living/simple_animal/slime/M, mob/user) +/obj/item/slimepotion/slime/stabilizer/attack(mob/living/simple_animal/slime/M, mob/user) if(!isslime(M)) to_chat(user, "The stabilizer only works on slimes!") return ..() if(M.stat) to_chat(user, "The slime is dead!") - return ..() + return if(M.mutation_chance == 0) to_chat(user, "The slime already has no chance of mutating!") - return ..() + return to_chat(user, "You feed the slime the stabilizer. It is now less likely to mutate.") 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 = "potgreen" -/obj/item/slimepotion/mutator/attack(mob/living/simple_animal/slime/M, mob/user) +/obj/item/slimepotion/slime/mutator/attack(mob/living/simple_animal/slime/M, mob/user) if(!isslime(M)) to_chat(user, "The mutator only works on slimes!") return ..() if(M.stat) to_chat(user, "The slime is dead!") - return ..() + return if(M.mutator_used) to_chat(user, "This slime has already consumed a mutator, any more would be far too unstable!") - return ..() + return if(M.mutation_chance == 100) to_chat(user, "The slime is already guaranteed to mutate!") - return ..() + return to_chat(user, "You feed the slime the mutator. It is now more likely to mutate.") M.mutation_chance = CLAMP(M.mutation_chance+12,0,100) diff --git a/code/modules/uplink/uplink_items.dm b/code/modules/uplink/uplink_items.dm index 4c4137d52c8..e66c201e078 100644 --- a/code/modules/uplink/uplink_items.dm +++ b/code/modules/uplink/uplink_items.dm @@ -1061,7 +1061,7 @@ GLOBAL_LIST_EMPTY(uplink_items) // Global list so we only initialize this once. /datum/uplink_item/device_tools/potion name = "Syndicate Sentience Potion" - item = /obj/item/slimepotion/sentience/nuclear + item = /obj/item/slimepotion/slime/sentience/nuclear desc = "A potion recovered at great risk by undercover syndicate operatives and then subsequently modified with syndicate technology. Using it will make any animal sentient, and bound to serve you, as well as implanting an internal radio for communication and an internal ID card for opening doors." cost = 4 include_modes = list(/datum/game_mode/nuclear) @@ -1372,7 +1372,7 @@ GLOBAL_LIST_EMPTY(uplink_items) // Global list so we only initialize this once. exclude_modes = list(/datum/game_mode/nuclear) cant_discount = TRUE var/starting_crate_value = 50 - + /datum/uplink_item/badass/surplus/super name = "Super Surplus Crate" desc = "A dusty SUPER-SIZED from the back of the Syndicate warehouse. Rumored to contain a valuable assortment of items, \ diff --git a/icons/mob/actions/actions_silicon.dmi b/icons/mob/actions/actions_silicon.dmi index 5b198649baaaf137d2e395cf880b25419934e07b..cd997a25ac12f7c89d0e2f80a277d2de33d9c8a3 100644 GIT binary patch literal 7018 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 mjMz$)kZ}39 literal 5891 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