mirror of
https://github.com/CHOMPStation2/CHOMPStation2.git
synced 2025-12-11 10:43:20 +00:00
General: Bots are now /mob/living/bot. They support player control fully. Just in case an admin feels like letting a ghost take control of beepsky or something. Since they are bots, spooders and whatnot will attack them. They now don't need an open panel to be emagged. Spawns replaced with do_after, meaning that they will stop injecting/cleaning/repairing/arresting if pulled away. Medbot: Emagger is added to ignore list. Will now inject spaceacilin regardeless of disease type and level. Previously: only if disease was past stage 1 or airbone. Cleanbot: Patrolling rewritten. They now find a closest beacon, and go to the NEXT beacon after the closest one. They will not wiggle out when pulled. They will now ignore (for a while) the gibs they make if odd button is pressed. They will now freely claim cleanables. Previously, they would not target ones targeted by other bots. Floorbot: This was a helluva buggy one. They will now build bridges (but still won't do random repairs) in space area. They will now build bridges even if the tile directly next to them in that direction is tiled. They will now ignore for a while a tile they can't reach. This is to stop them from hopelessly targeting tiles under grilles for upgrades and getting stuck. They will now slowly (200 ticks for a tile) build new tiles on their own. They will now preserve tile's icon when repairing it like a player would. They will now place first rods, then tile when fixing space breaches. Rod costs two tiles. When emagged, they will first always tear off the tile, then will (over triple the normal amount of time) breach the tile to space. There are noticeable warnings for both actions. Secbot: Will no longer run away to patrol when panel is open. Now deals stamina damage instead of instastuns. Small delay between approaching the target and stunning them. Laserbots axed. Removed their weird EMP act. Will no longer stun lying people, just cuff. They will also demand surrenderring (lying down) before smacking you. If target moves, or 5 seconds pass, it will attack. Farmbot: It's alive! It has settings to: water trays, refill its own water, uproot weeds, add nutriment (ammonia, internal synthesizer), collect produce, and remove dead plants.
307 lines
8.5 KiB
Plaintext
307 lines
8.5 KiB
Plaintext
/mob/living/bot/cleanbot
|
|
name = "Cleanbot"
|
|
desc = "A little cleaning robot, he looks so excited!"
|
|
icon_state = "cleanbot0"
|
|
req_access = list(access_janitor)
|
|
botcard_access = list(access_janitor, access_maint_tunnels)
|
|
|
|
locked = 0 // Start unlocked so roboticist can set them to patrol.
|
|
|
|
var/obj/effect/decal/cleanable/target
|
|
var/list/path = list()
|
|
var/list/patrol_path = list()
|
|
var/list/ignorelist = list()
|
|
|
|
var/obj/cleanbot_listener/listener = null
|
|
var/beacon_freq = 1445 // navigation beacon frequency
|
|
var/signal_sent = 0
|
|
var/closest_dist
|
|
var/next_dest
|
|
var/next_dest_loc
|
|
|
|
var/cleaning = 0
|
|
var/screwloose = 0
|
|
var/oddbutton = 0
|
|
var/should_patrol = 0
|
|
var/blood = 1
|
|
var/list/target_types = list()
|
|
|
|
/mob/living/bot/cleanbot/New()
|
|
..()
|
|
get_targets()
|
|
|
|
listener = new /obj/cleanbot_listener(src)
|
|
listener.cleanbot = src
|
|
|
|
if(radio_controller)
|
|
radio_controller.add_object(listener, beacon_freq, filter = RADIO_NAVBEACONS)
|
|
|
|
/mob/living/bot/cleanbot/Life()
|
|
..()
|
|
|
|
if(!on)
|
|
return
|
|
|
|
if(client)
|
|
return
|
|
if(cleaning)
|
|
return
|
|
|
|
if(!screwloose && !oddbutton && prob(5))
|
|
custom_emote(2, "makes an excited beeping booping sound!")
|
|
|
|
if(screwloose && prob(5)) // Make a mess
|
|
if(istype(loc, /turf/simulated))
|
|
var/turf/simulated/T = loc
|
|
if(T.wet < 1)
|
|
T.wet = 1
|
|
if(T.wet_overlay)
|
|
T.overlays -= T.wet_overlay
|
|
T.wet_overlay = null
|
|
T.wet_overlay = image('icons/effects/water.dmi', T, "wet_floor")
|
|
T.overlays += T.wet_overlay
|
|
spawn(800)
|
|
if(istype(T) && T.wet < 2)
|
|
T.wet = 0
|
|
if(T.wet_overlay)
|
|
T.overlays -= T.wet_overlay
|
|
T.wet_overlay = null
|
|
|
|
if(oddbutton && prob(5)) // Make a big mess
|
|
visible_message("Something flies out of [src]. He seems to be acting oddly.")
|
|
var/obj/effect/decal/cleanable/blood/gibs/gib = new /obj/effect/decal/cleanable/blood/gibs(loc)
|
|
ignorelist += gib
|
|
spawn(600)
|
|
ignorelist -= gib
|
|
|
|
if(!target) // Find a target
|
|
for(var/obj/effect/decal/cleanable/D in view(7, src))
|
|
if(D in ignorelist)
|
|
continue
|
|
for(var/T in target_types)
|
|
if(istype(D, T))
|
|
target = D
|
|
patrol_path = list()
|
|
|
|
if(!target) // No targets in range
|
|
if(!should_patrol)
|
|
return
|
|
|
|
if(!patrol_path || !patrol_path.len)
|
|
if(!signal_sent || signal_sent > world.time + 200) // Waited enough or didn't send yet
|
|
var/datum/radio_frequency/frequency = radio_controller.return_frequency(beacon_freq)
|
|
if(!frequency)
|
|
return
|
|
|
|
closest_dist = 9999
|
|
next_dest = null
|
|
next_dest_loc = null
|
|
|
|
var/datum/signal/signal = new()
|
|
signal.source = src
|
|
signal.transmission_method = 1
|
|
signal.data = list("findbeakon" = "patrol")
|
|
frequency.post_signal(src, signal, filter = RADIO_NAVBEACONS)
|
|
signal_sent = world.time
|
|
else
|
|
if(next_dest)
|
|
next_dest_loc = listener.memorized[next_dest]
|
|
if(next_dest_loc)
|
|
patrol_path = AStar(loc, next_dest_loc, /turf/proc/CardinalTurfsWithAccess, /turf/proc/Distance, 0, 120, id = botcard, exclude = null)
|
|
signal_sent = 0
|
|
else
|
|
if(pulledby) // Don't wiggle if someone pulls you
|
|
patrol_path = list()
|
|
return
|
|
if(patrol_path[1] == loc)
|
|
patrol_path -= patrol_path[1]
|
|
var/moved = step_towards(src, patrol_path[1])
|
|
if(moved)
|
|
patrol_path -= patrol_path[1]
|
|
if(target)
|
|
if(loc == target.loc)
|
|
if(!cleaning)
|
|
UnarmedAttack(target)
|
|
return
|
|
if(!path.len)
|
|
spawn(0)
|
|
path = AStar(loc, target.loc, /turf/proc/CardinalTurfsWithAccess, /turf/proc/Distance, 0, 30, id = botcard)
|
|
if(!path)
|
|
path = list()
|
|
return
|
|
if(path.len)
|
|
step_to(src, path[1])
|
|
path -= path[1]
|
|
return
|
|
|
|
/mob/living/bot/cleanbot/UnarmedAttack(var/obj/effect/decal/cleanable/D, var/proximity)
|
|
if(!..())
|
|
return
|
|
|
|
if(!istype(D))
|
|
return
|
|
|
|
if(D.loc != loc)
|
|
return
|
|
|
|
cleaning = 1
|
|
custom_emote(2, "begins to clean up the [D]")
|
|
update_icons()
|
|
var/cleantime = istype(D, /obj/effect/decal/cleanable/dirt) ? 10 : 50
|
|
if(do_after(src, cleantime))
|
|
if(istype(loc, /turf/simulated))
|
|
var/turf/simulated/f = loc
|
|
f.dirt = 0
|
|
if(!D)
|
|
return
|
|
del(D)
|
|
cleaning = 0
|
|
update_icons()
|
|
|
|
/mob/living/bot/cleanbot/explode()
|
|
on = 0
|
|
visible_message("<span class='danger'>[src] blows apart!</span>")
|
|
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()
|
|
del(src)
|
|
return
|
|
|
|
/mob/living/bot/cleanbot/update_icons()
|
|
if(cleaning)
|
|
icon_state = "cleanbot-c"
|
|
else
|
|
icon_state = "cleanbot[on]"
|
|
|
|
/mob/living/bot/cleanbot/turn_off()
|
|
..()
|
|
target = null
|
|
path = list()
|
|
patrol_path = list()
|
|
|
|
/mob/living/bot/cleanbot/attack_hand(var/mob/user)
|
|
var/dat
|
|
dat += "<TT><B>Automatic Station Cleaner v1.0</B></TT><BR><BR>"
|
|
dat += "Status: <A href='?src=\ref[src];operation=start'>[on ? "On" : "Off"]</A><BR>"
|
|
dat += "Behaviour controls are [locked ? "locked" : "unlocked"]<BR>"
|
|
dat += "Maintenance panel is [open ? "opened" : "closed"]"
|
|
if(!locked || issilicon(user))
|
|
dat += "<BR>Cleans Blood: <A href='?src=\ref[src];operation=blood'>[blood ? "Yes" : "No"]</A><BR>"
|
|
dat += "<BR>Patrol station: <A href='?src=\ref[src];operation=patrol'>[should_patrol ? "Yes" : "No"]</A><BR>"
|
|
if(open && !locked)
|
|
dat += "Odd looking screw twiddled: <A href='?src=\ref[src];operation=screw'>[screwloose ? "Yes" : "No"]</A><BR>"
|
|
dat += "Weird button pressed: <A href='?src=\ref[src];operation=oddbutton'>[oddbutton ? "Yes" : "No"]</A>"
|
|
|
|
user << browse("<HEAD><TITLE>Cleaner v1.0 controls</TITLE></HEAD>[dat]", "window=autocleaner")
|
|
onclose(user, "autocleaner")
|
|
return
|
|
|
|
/mob/living/bot/cleanbot/Topic(href, href_list)
|
|
if(..())
|
|
return
|
|
usr.set_machine(src)
|
|
add_fingerprint(usr)
|
|
switch(href_list["operation"])
|
|
if("start")
|
|
if(on)
|
|
turn_off()
|
|
else
|
|
turn_on()
|
|
if("blood")
|
|
blood = !blood
|
|
get_targets()
|
|
if("patrol")
|
|
should_patrol = !should_patrol
|
|
patrol_path = null
|
|
if("freq")
|
|
var/freq = text2num(input("Select frequency for navigation beacons", "Frequnecy", num2text(beacon_freq / 10))) * 10
|
|
if (freq > 0)
|
|
beacon_freq = freq
|
|
if("screw")
|
|
screwloose = !screwloose
|
|
usr << "<span class='notice>You twiddle the screw.</span>"
|
|
if("oddbutton")
|
|
oddbutton = !oddbutton
|
|
usr << "<span class='notice'>You press the weird button.</span>"
|
|
attack_hand(usr)
|
|
|
|
/mob/living/bot/cleanbot/Emag(var/mob/user)
|
|
..()
|
|
if(user)
|
|
user << "<span class='notice'>The [src] buzzes and beeps.</span>"
|
|
oddbutton = 1
|
|
screwloose = 1
|
|
|
|
/mob/living/bot/cleanbot/proc/get_targets()
|
|
target_types = list()
|
|
|
|
target_types += /obj/effect/decal/cleanable/blood/oil
|
|
target_types += /obj/effect/decal/cleanable/vomit
|
|
target_types += /obj/effect/decal/cleanable/crayon
|
|
target_types += /obj/effect/decal/cleanable/liquid_fuel
|
|
target_types += /obj/effect/decal/cleanable/mucus
|
|
target_types += /obj/effect/decal/cleanable/dirt
|
|
|
|
if(blood)
|
|
target_types += /obj/effect/decal/cleanable/blood
|
|
|
|
/* Radio object that listens to signals */
|
|
|
|
/obj/cleanbot_listener
|
|
var/mob/living/bot/cleanbot/cleanbot = null
|
|
var/list/memorized = list()
|
|
|
|
/obj/cleanbot_listener/receive_signal(var/datum/signal/signal)
|
|
var/recv = signal.data["beacon"]
|
|
var/valid = signal.data["patrol"]
|
|
if(!recv || !valid || !cleanbot)
|
|
return
|
|
|
|
var/dist = get_dist(cleanbot, signal.source.loc)
|
|
memorized[recv] = signal.source.loc
|
|
|
|
if(dist < cleanbot.closest_dist) // We check all signals, choosing the closest beakon; then we move to the NEXT one after the closest one
|
|
cleanbot.closest_dist = dist
|
|
cleanbot.next_dest = signal.data["next_patrol"]
|
|
|
|
/* 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 = 10.0
|
|
throw_speed = 2
|
|
throw_range = 5
|
|
w_class = 3.0
|
|
var/created_name = "Cleanbot"
|
|
|
|
/obj/item/weapon/bucket_sensor/attackby(var/obj/item/O, var/mob/user)
|
|
..()
|
|
if(istype(O, /obj/item/robot_parts/l_arm) || istype(O, /obj/item/robot_parts/r_arm))
|
|
user.drop_item()
|
|
del(O)
|
|
var/turf/T = get_turf(loc)
|
|
var/mob/living/bot/cleanbot/A = new /mob/living/bot/cleanbot(T)
|
|
A.name = created_name
|
|
user << "<span class='notice'>You add the robot arm to the bucket and sensor assembly. Beep boop!</span>"
|
|
user.drop_from_inventory(src)
|
|
del(src)
|
|
|
|
else if(istype(O, /obj/item/weapon/pen))
|
|
var/t = sanitizeSafe(input(user, "Enter new robot name", name, created_name), MAX_NAME_LEN)
|
|
if(!t)
|
|
return
|
|
if(!in_range(src, usr) && src.loc != usr)
|
|
return
|
|
created_name = t
|