//Cleanbot assembly
/obj/item/weapon/bucket_sensor
desc = "It's a bucket. With a sensor attached."
name = "proxy bucket"
icon = 'icons/obj/aibots.dmi'
icon_state = "bucket_proxy"
force = 3.0
throwforce = 5.0
throw_speed = 2
throw_range = 5
w_class = 3.0
var/created_name = "Cleanbot"
//Cleanbot
/obj/machinery/bot/cleanbot
name = "\improper Cleanbot"
desc = "A little cleaning robot, he looks so excited!"
icon = 'icons/obj/aibots.dmi'
icon_state = "cleanbot0"
layer = 5.0
density = 0
anchored = 0
//weight = 1.0E7
health = 25
maxhealth = 25
var/blood = 1
var/list/target_types = list()
var/obj/effect/decal/cleanable/target
var/obj/effect/decal/cleanable/oldtarget
var/max_targets = 50 //Maximum number of targets a cleanbot can ignore.
var/oldloc = null
req_one_access = list(access_janitor, access_robotics)
// var/patrol_path[] = null
// var/beacon_freq = 1445 // navigation beacon frequency
var/closest_dist
var/closest_loc
var/failed_steps
var/next_dest
var/next_dest_loc
radio_name = "Service"
bot_type = CLEAN_BOT
bot_type_name = "Cleanbot"
bot_filter = RADIO_CLEANBOT
/obj/machinery/bot/cleanbot/New()
..()
get_targets()
icon_state = "cleanbot[on]"
var/datum/job/janitor/J = new/datum/job/janitor
botcard.access = J.get_access()
prev_access = botcard.access
spawn(5)
add_to_beacons(bot_filter)
/obj/machinery/bot/cleanbot/turn_on()
..()
icon_state = "cleanbot[on]"
updateUsrDialog()
/obj/machinery/bot/cleanbot/turn_off()
..()
icon_state = "cleanbot[on]"
updateUsrDialog()
/obj/machinery/bot/cleanbot/bot_reset()
..()
ignore_list = list() //Allows the bot to clean targets it previously ignored due to being unreachable.
target = null
oldtarget = null
oldloc = null
/obj/machinery/bot/cleanbot/set_custom_texts()
text_hack = "You corrupt [name]'s cleaning software."
text_dehack = "[name]'s software has been reset!"
text_dehack_fail = "[name] does not seem to respond to your repair code!"
/obj/machinery/bot/cleanbot/attack_hand(mob/user as mob)
. = ..()
if (.)
return
usr.set_machine(src)
interact(user)
/obj/machinery/bot/cleanbot/interact(mob/user as mob)
var/dat
dat += hack(user)
dat += text({"
Cleaner v1.1 controls
Status: []
Behaviour controls are [locked ? "locked" : "unlocked"]
Maintenance panel panel is [open ? "opened" : "closed"]"},
text("[on ? "On" : "Off"]"))
if(!locked || issilicon(user))
dat += text({"
Cleans Blood: []
"}, text("[blood ? "Yes" : "No"]"))
dat += text({"
Patrol station: []
"}, text("[auto_patrol ? "Yes" : "No"]"))
var/datum/browser/popup = new(user, "autoclean", "Automatic Station Cleaner v1.1")
popup.set_content(dat)
popup.open()
return
/obj/machinery/bot/cleanbot/Topic(href, href_list)
..()
switch(href_list["operation"])
if("blood")
blood =!blood
get_targets()
updateUsrDialog()
if("freq")
var/freq = text2num(input("Select frequency for navigation beacons", "Frequency", num2text(beacon_freq / 10))) * 10
if (freq > 0)
beacon_freq = freq
updateUsrDialog()
/obj/machinery/bot/cleanbot/attackby(obj/item/weapon/W, mob/user as mob, params)
if (istype(W, /obj/item/weapon/card/id)||istype(W, /obj/item/device/pda))
if(allowed(usr) && !open && !emagged)
locked = !locked
user << "You [ locked ? "lock" : "unlock"] the [src] behaviour controls."
updateUsrDialog()
else
if(emagged)
user << "ERROR"
if(open)
user << "Please close the access panel before locking it."
else
user << "This [src] doesn't seem to respect your authority."
else
return ..()
/obj/machinery/bot/cleanbot/Emag(mob/user as mob)
..()
if(emagged == 2)
if(user)
user << "[src] buzzes and beeps."
/obj/machinery/bot/cleanbot/process_scan(var/obj/effect/decal/cleanable/D)
for(var/T in target_types)
if(istype(D, T))
return D
/obj/machinery/bot/cleanbot/bot_process()
if (!..())
return
if(mode == BOT_CLEANING)
return
if(emagged == 2) //Emag functions
if(istype(loc,/turf/simulated))
if(prob(10)) //Wets floors randomly
var/turf/simulated/T = loc
T.MakeSlippery()
if(prob(5)) //Spawns foam!
visible_message("[src] whirs and bubbles violently, before releasing a plume of froth!")
new /obj/effect/effect/foam(loc)
else if (prob(5))
visible_message("[src] makes an excited beeping booping sound!")
if(!target) //Search for cleanables it can see.
target = scan(/obj/effect/decal/cleanable/, oldtarget)
oldtarget = target
if(!target)
if(loc != oldloc)
oldtarget = null
if(auto_patrol)
if(mode == BOT_IDLE || mode == BOT_START_PATROL)
start_patrol()
if(mode == BOT_PATROL)
bot_patrol()
return
if(target)
if(!path || path.len == 0) //No path, need a new one
//Try to produce a path to the target, and ignore airlocks to which it has access.
path = AStar(loc, target.loc, /turf/proc/AdjacentTurfsWithAccess, /turf/proc/Distance, 0, 30, id=botcard)
if (!bot_move(target))
add_to_ignore(target)
target = null
path = list()
return
mode = BOT_MOVING
else if (!bot_move(target))
target = null
mode = BOT_IDLE
return
if(target && loc == target.loc)
clean(target)
path = list()
target = null
oldloc = loc
/obj/machinery/bot/cleanbot/proc/get_targets()
target_types = new/list()
target_types += /obj/effect/decal/cleanable/blood/oil
target_types += /obj/effect/decal/cleanable/vomit
target_types += /obj/effect/decal/cleanable/poop
target_types += /obj/effect/decal/cleanable/blood/gibs/robot
target_types += /obj/effect/decal/cleanable/crayon
target_types += /obj/effect/decal/cleanable/liquid_fuel
target_types += /obj/effect/decal/cleanable/molten_item
target_types += /obj/effect/decal/cleanable/tomato_smudge
target_types += /obj/effect/decal/cleanable/egg_smudge
target_types += /obj/effect/decal/cleanable/pie_smudge
target_types += /obj/effect/decal/cleanable/flour
target_types += /obj/effect/decal/cleanable/ash
target_types += /obj/effect/decal/cleanable/greenglow
target_types += /obj/effect/decal/cleanable/dirt
target_types += /obj/effect/decal/cleanable/mucus
if(blood)
target_types += /obj/effect/decal/cleanable/blood/xeno/
target_types += /obj/effect/decal/cleanable/blood/gibs/xeno
target_types += /obj/effect/decal/cleanable/blood/
target_types += /obj/effect/decal/cleanable/blood/gibs/
target_types += /obj/effect/decal/cleanable/blood/tracks
target_types += /obj/effect/decal/cleanable/dirt
/obj/machinery/bot/cleanbot/proc/clean(var/obj/effect/decal/cleanable/target)
anchored = 1
icon_state = "cleanbot-c"
visible_message("[src] begins to clean up [target]")
mode = BOT_CLEANING
spawn(25)
if(mode == BOT_CLEANING)
qdel(target)
anchored = 0
target = null
mode = BOT_IDLE
icon_state = "cleanbot[on]"
/obj/machinery/bot/cleanbot/explode()
on = 0
visible_message("[src] blows apart!")
var/turf/Tsec = get_turf(src)
new /obj/item/weapon/reagent_containers/glass/bucket(Tsec)
new /obj/item/device/assembly/prox_sensor(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
/obj/item/weapon/bucket_sensor/attackby(var/obj/item/W, mob/user as mob, params)
..()
if(istype(W, /obj/item/robot_parts/l_arm) || istype(W, /obj/item/robot_parts/r_arm))
user.drop_item()
qdel(W)
var/turf/T = get_turf(loc)
var/obj/machinery/bot/cleanbot/A = new /obj/machinery/bot/cleanbot(T)
A.name = created_name
user << "You add the robot arm to the bucket and sensor assembly. Beep boop!"
user.unEquip(src, 1)
qdel(src)
else if (istype(W, /obj/item/weapon/pen))
var/t = stripped_input(user, "Enter new robot name", name, created_name,MAX_NAME_LEN)
if (!t)
return
if (!in_range(src, usr) && loc != usr)
return
created_name = t