#define FARMBOT_COLLECT 1 #define FARMBOT_WATER 2 #define FARMBOT_UPROOT 3 #define FARMBOT_NUTRIMENT 4 /mob/living/bot/farmbot name = "Farmbot" desc = "The botanist's best friend." icon = 'icons/obj/aibots.dmi' icon_state = "farmbot0" health = 50 maxHealth = 50 req_one_access = list(access_robotics, access_hydroponics, access_xenobiology) //TFF 11/7/19 - adds Xenobio access on behalf of Nalarac var/action = "" // Used to update icon var/waters_trays = 1 var/refills_water = 1 var/uproots_weeds = 1 var/replaces_nutriment = 0 var/collects_produce = 0 var/removes_dead = 0 var/obj/structure/reagent_dispensers/watertank/tank /mob/living/bot/farmbot/New(var/newloc, var/newTank) ..(newloc) if(!newTank) newTank = new /obj/structure/reagent_dispensers/watertank(src) tank = newTank tank.forceMove(src) /mob/living/bot/farmbot/attack_hand(var/mob/user as mob) . = ..() if(.) return var/dat = "" dat += "Automatic Hyrdoponic Assisting Unit v1.0

" dat += "Status: [on ? "On" : "Off"]
" dat += "Water Tank: " if (tank) dat += "[tank.reagents.total_volume]/[tank.reagents.maximum_volume]" else dat += "Error: Watertank not found" dat += "
Behaviour controls are [locked ? "locked" : "unlocked"]
" if(!locked) dat += "Watering controls:
" dat += "Water plants : [waters_trays ? "Yes" : "No"]
" dat += "Refill watertank : [refills_water ? "Yes" : "No"]
" dat += "
Weeding controls:
" dat += "Weed plants: [uproots_weeds ? "Yes" : "No"]
" dat += "
Nutriment controls:
" dat += "Replace fertilizer: [replaces_nutriment ? "Yes" : "No"]
" dat += "
Plant controls:
" dat += "Collect produce: [collects_produce ? "Yes" : "No"]
" dat += "Remove dead plants: [removes_dead ? "Yes" : "No"]
" dat += "
" user << browse("Farmbot v1.0 controls[dat]", "window=autofarm") onclose(user, "autofarm") return /mob/living/bot/farmbot/emag_act(var/remaining_charges, var/mob/user) . = ..() if(!emagged) if(user) to_chat(user, "You short out [src]'s plant identifier circuits.") spawn(rand(30, 50)) visible_message("[src] buzzes oddly.") emagged = 1 return 1 /mob/living/bot/farmbot/Topic(href, href_list) if(..()) return usr.machine = src add_fingerprint(usr) if((href_list["power"]) && (access_scanner.allowed(usr))) if(on) turn_off() else turn_on() if(locked) return if(href_list["water"]) waters_trays = !waters_trays else if(href_list["refill"]) refills_water = !refills_water else if(href_list["weed"]) uproots_weeds = !uproots_weeds else if(href_list["replacenutri"]) replaces_nutriment = !replaces_nutriment else if(href_list["collect"]) collects_produce = !collects_produce else if(href_list["removedead"]) removes_dead = !removes_dead attack_hand(usr) return /mob/living/bot/farmbot/update_icons() if(on && action) icon_state = "farmbot_[action]" else icon_state = "farmbot[on]" /mob/living/bot/farmbot/handleRegular() if(emagged && prob(1)) flick("farmbot_broke", src) /mob/living/bot/farmbot/handleAdjacentTarget() UnarmedAttack(target) /mob/living/bot/farmbot/lookForTargets() if(emagged) for(var/mob/living/carbon/human/H in view(7, src)) target = H return else for(var/obj/machinery/portable_atmospherics/hydroponics/tray in view(7, src)) if(confirmTarget(tray)) target = tray return if(!target && refills_water && tank && tank.reagents.total_volume < tank.reagents.maximum_volume) for(var/obj/structure/sink/source in view(7, src)) target = source return /mob/living/bot/farmbot/calcTargetPath() // We need to land NEXT to the tray, because the tray itself is impassable for(var/trayDir in list(NORTH, SOUTH, EAST, WEST)) target_path = AStar(get_turf(loc), get_step(get_turf(target), trayDir), /turf/proc/CardinalTurfsWithAccess, /turf/proc/Distance, 0, max_target_dist, id = botcard) if(target_path) break if(!target_path) ignore_list |= target target = null target_path = list() return /mob/living/bot/farmbot/stepToTarget() // Same reason var/turf/T = get_turf(target) if(!target_path.len || !T.Adjacent(target_path[target_path.len])) calcTargetPath() makeStep(target_path) return /mob/living/bot/farmbot/UnarmedAttack(var/atom/A, var/proximity) if(!..()) return if(busy) return if(istype(A, /obj/machinery/portable_atmospherics/hydroponics)) var/obj/machinery/portable_atmospherics/hydroponics/T = A var/t = confirmTarget(T) switch(t) if(0) return if(FARMBOT_COLLECT) action = "water" // Needs a better one update_icons() visible_message("[src] starts [T.dead? "removing the plant from" : "harvesting"] \the [A].") busy = 1 if(do_after(src, 30, A)) visible_message("[src] [T.dead? "removes the plant from" : "harvests"] \the [A].") T.attack_hand(src) if(FARMBOT_WATER) action = "water" update_icons() visible_message("[src] starts watering \the [A].") busy = 1 if(do_after(src, 30, A)) playsound(src, 'sound/effects/slosh.ogg', 25, 1) visible_message("[src] waters \the [A].") tank.reagents.trans_to(T, 100 - T.waterlevel) if(FARMBOT_UPROOT) action = "hoe" update_icons() visible_message("[src] starts uprooting the weeds in \the [A].") busy = 1 if(do_after(src, 30)) visible_message("[src] uproots the weeds in \the [A].") T.weedlevel = 0 if(FARMBOT_NUTRIMENT) action = "fertile" update_icons() visible_message("[src] starts fertilizing \the [A].") busy = 1 if(do_after(src, 30, A)) visible_message("[src] fertilizes \the [A].") T.reagents.add_reagent("ammonia", 10) busy = 0 action = "" update_icons() T.update_icon() else if(istype(A, /obj/structure/sink)) if(!tank || tank.reagents.total_volume >= tank.reagents.maximum_volume) return action = "water" update_icons() visible_message("[src] starts refilling its tank from \the [A].") busy = 1 while(do_after(src, 10) && tank.reagents.total_volume < tank.reagents.maximum_volume) tank.reagents.add_reagent("water", 10) if(prob(5)) playsound(src, 'sound/effects/slosh.ogg', 25, 1) busy = 0 action = "" update_icons() visible_message("[src] finishes refilling its tank.") else if(emagged && ishuman(A)) var/action = pick("weed", "water") busy = 1 spawn(50) // Some delay busy = 0 switch(action) if("weed") flick("farmbot_hoe", src) do_attack_animation(A) if(prob(50)) visible_message("[src] swings wildly at [A] with a minihoe, missing completely!") return var/t = pick("slashed", "sliced", "cut", "clawed") A.attack_generic(src, 5, t) if("water") flick("farmbot_water", src) visible_message("[src] splashes [A] with water!") tank.reagents.splash(A, 100) /mob/living/bot/farmbot/explode() visible_message("[src] blows apart!") var/turf/Tsec = get_turf(src) new /obj/item/weapon/material/minihoe(Tsec) new /obj/item/weapon/reagent_containers/glass/bucket(Tsec) new /obj/item/device/assembly/prox_sensor(Tsec) new /obj/item/device/analyzer/plant_analyzer(Tsec) if(tank) tank.loc = Tsec if(prob(50)) new /obj/item/robot_parts/l_arm(Tsec) var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread s.set_up(3, 1, src) s.start() qdel(src) return /mob/living/bot/farmbot/confirmTarget(var/atom/targ) if(!..()) return 0 if(emagged && ishuman(targ)) if(targ in view(world.view, src)) return 1 return 0 if(istype(targ, /obj/structure/sink)) if(!tank || tank.reagents.total_volume >= tank.reagents.maximum_volume) return 0 return 1 var/obj/machinery/portable_atmospherics/hydroponics/tray = targ if(!istype(tray)) return 0 if(tray.closed_system || !tray.seed) return 0 if(tray.dead && removes_dead || tray.harvest && collects_produce) return FARMBOT_COLLECT else if(refills_water && tray.waterlevel < 40 && !tray.reagents.has_reagent("water") && tank.reagents.total_volume > 0) return FARMBOT_WATER else if(uproots_weeds && tray.weedlevel > 3) return FARMBOT_UPROOT else if(replaces_nutriment && tray.nutrilevel < 1 && tray.reagents.total_volume < 1) return FARMBOT_NUTRIMENT return 0 // Assembly /obj/item/weapon/farmbot_arm_assembly name = "water tank/robot arm assembly" desc = "A water tank with a robot arm permanently grafted to it." icon = 'icons/obj/aibots.dmi' icon_state = "water_arm" var/build_step = 0 var/created_name = "Farmbot" var/obj/tank w_class = ITEMSIZE_NORMAL /obj/item/weapon/farmbot_arm_assembly/New(var/newloc, var/theTank) ..(newloc) if(!theTank) // If an admin spawned it, it won't have a watertank it, so lets make one for em! tank = new /obj/structure/reagent_dispensers/watertank(src) else tank = theTank tank.forceMove(src) /obj/structure/reagent_dispensers/watertank/attackby(var/obj/item/robot_parts/S, mob/user as mob) if ((!istype(S, /obj/item/robot_parts/l_arm)) && (!istype(S, /obj/item/robot_parts/r_arm))) ..() return to_chat(user, "You add the robot arm to [src].") user.drop_from_inventory(S) qdel(S) new /obj/item/weapon/farmbot_arm_assembly(loc, src) /obj/structure/reagent_dispensers/watertank/attackby(var/obj/item/organ/external/S, mob/user as mob) if ((!istype(S, /obj/item/organ/external/arm)) || S.robotic != ORGAN_ROBOT) ..() return to_chat(user, "You add the robot arm to [src].") user.drop_from_inventory(S) qdel(S) new /obj/item/weapon/farmbot_arm_assembly(loc, src) /obj/item/weapon/farmbot_arm_assembly/attackby(obj/item/weapon/W as obj, mob/user as mob) ..() if((istype(W, /obj/item/device/analyzer/plant_analyzer)) && (build_step == 0)) build_step++ to_chat(user, "You add the plant analyzer to [src].") name = "farmbot assembly" user.remove_from_mob(W) qdel(W) else if((istype(W, /obj/item/weapon/reagent_containers/glass/bucket)) && (build_step == 1)) build_step++ to_chat(user, "You add a bucket to [src].") name = "farmbot assembly with bucket" user.remove_from_mob(W) qdel(W) else if((istype(W, /obj/item/weapon/material/minihoe)) && (build_step == 2)) build_step++ to_chat(user, "You add a minihoe to [src].") name = "farmbot assembly with bucket and minihoe" user.remove_from_mob(W) qdel(W) else if((isprox(W)) && (build_step == 3)) build_step++ to_chat(user, "You complete the Farmbot! Beep boop.") var/mob/living/bot/farmbot/S = new /mob/living/bot/farmbot(get_turf(src), tank) S.name = created_name user.remove_from_mob(W) qdel(W) qdel(src) else if(istype(W, /obj/item/weapon/pen)) var/t = input(user, "Enter new robot name", name, created_name) as text t = sanitize(t, MAX_NAME_LEN) if(!t) return if(!in_range(src, usr) && loc != usr) return created_name = t /obj/item/weapon/farmbot_arm_assembly/attack_hand(mob/user as mob) return //it's a converted watertank, no you cannot pick it up and put it in your backpack