mirror of
https://github.com/PolarisSS13/Polaris.git
synced 2025-12-20 15:12:57 +00:00
400 lines
12 KiB
Plaintext
400 lines
12 KiB
Plaintext
#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 += "<TT><B>Automatic Hyrdoponic Assisting Unit v1.0</B></TT><BR><BR>"
|
|
dat += "Status: <A href='?src=\ref[src];power=1'>[on ? "On" : "Off"]</A><BR>"
|
|
dat += "Water Tank: "
|
|
if (tank)
|
|
dat += "[tank.reagents.total_volume]/[tank.reagents.maximum_volume]"
|
|
else
|
|
dat += "Error: Watertank not found"
|
|
dat += "<br>Behaviour controls are [locked ? "locked" : "unlocked"]<hr>"
|
|
if(!locked)
|
|
dat += "<TT>Watering controls:<br>"
|
|
dat += "Water plants : <A href='?src=\ref[src];water=1'>[waters_trays ? "Yes" : "No"]</A><BR>"
|
|
dat += "Refill watertank : <A href='?src=\ref[src];refill=1'>[refills_water ? "Yes" : "No"]</A><BR>"
|
|
dat += "<br>Weeding controls:<br>"
|
|
dat += "Weed plants: <A href='?src=\ref[src];weed=1'>[uproots_weeds ? "Yes" : "No"]</A><BR>"
|
|
dat += "<br>Nutriment controls:<br>"
|
|
dat += "Replace fertilizer: <A href='?src=\ref[src];replacenutri=1'>[replaces_nutriment ? "Yes" : "No"]</A><BR>"
|
|
dat += "<br>Plant controls:<br>"
|
|
dat += "Collect produce: <A href='?src=\ref[src];collect=1'>[collects_produce ? "Yes" : "No"]</A><BR>"
|
|
dat += "Remove dead plants: <A href='?src=\ref[src];removedead=1'>[removes_dead ? "Yes" : "No"]</A><BR>"
|
|
dat += "</TT>"
|
|
|
|
user << browse("<HEAD><TITLE>Farmbot v1.0 controls</TITLE></HEAD>[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, "<span class='notice'>You short out [src]'s plant identifier circuits.</span>")
|
|
spawn(rand(30, 50))
|
|
visible_message("<span class='warning'>[src] buzzes oddly.</span>")
|
|
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("<span class='notice'>[src] starts [T.dead? "removing the plant from" : "harvesting"] \the [A].</span>")
|
|
|
|
busy = 1
|
|
if(do_after(src, 30, A))
|
|
visible_message("<span class='notice'>[src] [T.dead? "removes the plant from" : "harvests"] \the [A].</span>")
|
|
T.attack_hand(src)
|
|
if(FARMBOT_WATER)
|
|
action = "water"
|
|
update_icons()
|
|
visible_message("<span class='notice'>[src] starts watering \the [A].</span>")
|
|
|
|
busy = 1
|
|
if(do_after(src, 30, A))
|
|
playsound(src, 'sound/effects/slosh.ogg', 25, 1)
|
|
visible_message("<span class='notice'>[src] waters \the [A].</span>")
|
|
tank.reagents.trans_to(T, 100 - T.waterlevel)
|
|
if(FARMBOT_UPROOT)
|
|
action = "hoe"
|
|
update_icons()
|
|
visible_message("<span class='notice'>[src] starts uprooting the weeds in \the [A].</span>")
|
|
|
|
busy = 1
|
|
if(do_after(src, 30))
|
|
visible_message("<span class='notice'>[src] uproots the weeds in \the [A].</span>")
|
|
T.weedlevel = 0
|
|
if(FARMBOT_NUTRIMENT)
|
|
action = "fertile"
|
|
update_icons()
|
|
visible_message("<span class='notice'>[src] starts fertilizing \the [A].</span>")
|
|
|
|
busy = 1
|
|
if(do_after(src, 30, A))
|
|
|
|
visible_message("<span class='notice'>[src] fertilizes \the [A].</span>")
|
|
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("<span class='notice'>[src] starts refilling its tank from \the [A].</span>")
|
|
|
|
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("<span class='notice'>[src] finishes refilling its tank.</span>")
|
|
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("<span class='danger'>[src] swings wildly at [A] with a minihoe, missing completely!</span>")
|
|
return
|
|
var/t = pick("slashed", "sliced", "cut", "clawed")
|
|
A.attack_generic(src, 5, t)
|
|
if("water")
|
|
flick("farmbot_water", src)
|
|
|
|
visible_message("<span class='danger'>[src] splashes [A] with water!</span>")
|
|
tank.reagents.splash(A, 100)
|
|
|
|
/mob/living/bot/farmbot/explode()
|
|
visible_message("<span class='danger'>[src] blows apart!</span>")
|
|
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 |