#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