Updates bots to be mobs. Several changes.

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.
This commit is contained in:
Kelenius
2015-04-26 15:30:11 +03:00
parent c7a4a77f50
commit 6d1614cb7a
27 changed files with 2352 additions and 3206 deletions

View File

@@ -1,363 +0,0 @@
//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 = 10.0
throw_speed = 2
throw_range = 5
w_class = 3.0
var/created_name = "Cleanbot"
//Cleanbot
/obj/machinery/bot/cleanbot
name = "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/cleaning = 0
var/screwloose = 0
var/oddbutton = 0
var/blood = 1
var/list/target_types = list()
var/obj/effect/decal/cleanable/target
var/obj/effect/decal/cleanable/oldtarget
var/oldloc = null
req_access = list(access_janitor)
var/path[] = new()
var/patrol_path[] = null
var/beacon_freq = 1445 // navigation beacon frequency
var/closest_dist
var/closest_loc
var/failed_steps
var/should_patrol
var/next_dest
var/next_dest_loc
/obj/machinery/bot/cleanbot/New()
..()
src.get_targets()
src.icon_state = "cleanbot[src.on]"
should_patrol = 1
src.botcard = new /obj/item/weapon/card/id(src)
src.botcard.access = list(access_janitor, access_maint_tunnels)
src.locked = 0 // Start unlocked so roboticist can set them to patrol.
if(radio_controller)
radio_controller.add_object(src, beacon_freq, filter = RADIO_NAVBEACONS)
/obj/machinery/bot/cleanbot/turn_on()
. = ..()
src.icon_state = "cleanbot[src.on]"
src.updateUsrDialog()
/obj/machinery/bot/cleanbot/turn_off()
..()
if(!isnull(src.target))
target.targeted_by = null
src.target = null
src.oldtarget = null
src.oldloc = null
src.icon_state = "cleanbot[src.on]"
src.path = new()
src.updateUsrDialog()
/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 += text({"
<TT><B>Automatic Station Cleaner v1.0</B></TT><BR><BR>
Status: []<BR>
Behaviour controls are [src.locked ? "locked" : "unlocked"]<BR>
Maintenance panel is [src.open ? "opened" : "closed"]"},
text("<A href='?src=\ref[src];operation=start'>[src.on ? "On" : "Off"]</A>"))
if(!src.locked || issilicon(user))
dat += text({"<BR>Cleans Blood: []<BR>"}, text("<A href='?src=\ref[src];operation=blood'>[src.blood ? "Yes" : "No"]</A>"))
dat += text({"<BR>Patrol station: []<BR>"}, text("<A href='?src=\ref[src];operation=patrol'>[src.should_patrol ? "Yes" : "No"]</A>"))
// dat += text({"<BR>Beacon frequency: []<BR>"}, text("<A href='?src=\ref[src];operation=freq'>[src.beacon_freq]</A>"))
if(src.open && !src.locked)
dat += text({"
Odd looking screw twiddled: []<BR>
Weird button pressed: []"},
text("<A href='?src=\ref[src];operation=screw'>[src.screwloose ? "Yes" : "No"]</A>"),
text("<A href='?src=\ref[src];operation=oddbutton'>[src.oddbutton ? "Yes" : "No"]</A>"))
user << browse("<HEAD><TITLE>Cleaner v1.0 controls</TITLE></HEAD>[dat]", "window=autocleaner")
onclose(user, "autocleaner")
return
/obj/machinery/bot/cleanbot/Topic(href, href_list)
if(..())
return
usr.set_machine(src)
src.add_fingerprint(usr)
switch(href_list["operation"])
if("start")
if (src.on)
turn_off()
else
turn_on()
if("blood")
src.blood =!src.blood
src.get_targets()
src.updateUsrDialog()
if("patrol")
src.should_patrol =!src.should_patrol
src.patrol_path = null
src.updateUsrDialog()
if("freq")
var/freq = text2num(input("Select frequency for navigation beacons", "Frequnecy", num2text(beacon_freq / 10))) * 10
if (freq > 0)
src.beacon_freq = freq
src.updateUsrDialog()
if("screw")
src.screwloose = !src.screwloose
usr << "<span class='notice>You twiddle the screw.</span>"
src.updateUsrDialog()
if("oddbutton")
src.oddbutton = !src.oddbutton
usr << "<span class='notice'>You press the weird button.</span>"
src.updateUsrDialog()
/obj/machinery/bot/cleanbot/attackby(obj/item/weapon/W, mob/user as mob)
if (istype(W, /obj/item/weapon/card/id)||istype(W, /obj/item/device/pda))
if(src.allowed(usr) && !open && !emagged)
src.locked = !src.locked
user << "<span class='notice'>You [ src.locked ? "lock" : "unlock"] the [src] behaviour controls.</span>"
else
if(emagged)
user << "<span class='warning'>ERROR</span>"
if(open)
user << "<span class='warning'>Please close the access panel before locking it.</span>"
else
user << "<span class='notice'>This [src] doesn't seem to respect your authority.</span>"
else
return ..()
/obj/machinery/bot/cleanbot/Emag(mob/user as mob)
..()
if(open && !locked)
if(user) user << "<span class='notice'>The [src] buzzes and beeps.</span>"
src.oddbutton = 1
src.screwloose = 1
/obj/machinery/bot/cleanbot/process()
set background = 1
if(!src.on)
return
if(src.cleaning)
return
if(!src.screwloose && !src.oddbutton && prob(5))
visible_message("[src] makes an excited beeping booping sound!")
if(src.screwloose && prob(5))
if(istype(loc,/turf/simulated))
var/turf/simulated/T = src.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(src.oddbutton && prob(5))
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(src.loc)
//gib.streak(list(NORTH, SOUTH, EAST, WEST, NORTHEAST, NORTHWEST, SOUTHEAST, SOUTHWEST))
src.oldtarget = gib
if(!src.target || src.target == null)
for (var/obj/effect/decal/cleanable/D in view(7,src))
for(var/T in src.target_types)
if(isnull(D.targeted_by) && istype(D, T) && D != src.oldtarget) // If the mess isn't targeted (D.type == T || D.parent_type == T)
src.oldtarget = D // or if it is but the bot is gone.
src.target = D // and it's stuff we clean? Clean it.
D.targeted_by = src // Claim the mess we are targeting.
return
if(!src.target || src.target == null)
if(src.loc != src.oldloc)
src.oldtarget = null
if (!should_patrol)
return
if (!patrol_path || patrol_path.len < 1)
var/datum/radio_frequency/frequency = radio_controller.return_frequency(beacon_freq)
if(!frequency) return
closest_dist = 9999
closest_loc = null
next_dest_loc = null
var/datum/signal/signal = new()
signal.source = src
signal.transmission_method = 1
signal.data = list("findbeacon" = "patrol")
frequency.post_signal(src, signal, filter = RADIO_NAVBEACONS)
spawn(5)
if (!next_dest_loc)
next_dest_loc = closest_loc
if (next_dest_loc)
src.patrol_path = AStar(src.loc, next_dest_loc, /turf/proc/CardinalTurfsWithAccess, /turf/proc/Distance, 0, 120, id=botcard, exclude=null)
else
patrol_move()
return
if(target && path.len == 0)
spawn(0)
if(!src || !target) return
src.path = AStar(src.loc, src.target.loc, /turf/proc/CardinalTurfsWithAccess, /turf/proc/Distance, 0, 30, id=botcard)
if (!path) path = list()
if(src.path.len == 0)
src.oldtarget = src.target
target.targeted_by = null
src.target = null
return
if(src.path.len > 0 && src.target && (src.target != null))
step_to(src, src.path[1])
src.path -= src.path[1]
else if(src.path.len == 1)
step_to(src, target)
if(src.target && (src.target != null))
patrol_path = null
if(src.loc == src.target.loc)
clean(src.target)
src.path = new()
src.target = null
return
src.oldloc = src.loc
/obj/machinery/bot/cleanbot/proc/patrol_move()
if (src.patrol_path.len <= 0)
return
var/next = src.patrol_path[1]
src.patrol_path -= next
if (next == src.loc)
return
var/moved = step_towards(src, next)
if (!moved)
failed_steps++
if (failed_steps > 4)
patrol_path = null
next_dest = null
failed_steps = 0
else
failed_steps = 0
/obj/machinery/bot/cleanbot/receive_signal(datum/signal/signal)
var/recv = signal.data["beacon"]
var/valid = signal.data["patrol"]
if(!recv || !valid)
return
var/dist = get_dist(src, signal.source.loc)
if (dist < closest_dist && signal.source.loc != src.loc)
closest_dist = dist
closest_loc = signal.source.loc
next_dest = signal.data["next_patrol"]
if (recv == next_dest)
next_dest_loc = signal.source.loc
next_dest = signal.data["next_patrol"]
/obj/machinery/bot/cleanbot/proc/get_targets()
src.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/crayon
target_types += /obj/effect/decal/cleanable/liquid_fuel
target_types += /obj/effect/decal/cleanable/mucus
target_types += /obj/effect/decal/cleanable/dirt
if(src.blood)
target_types += /obj/effect/decal/cleanable/blood/
/obj/machinery/bot/cleanbot/proc/clean(var/obj/effect/decal/cleanable/target)
anchored = 1
icon_state = "cleanbot-c"
visible_message("\red [src] begins to clean up the [target]")
cleaning = 1
var/cleantime = 50
if(istype(target,/obj/effect/decal/cleanable/dirt)) // Clean Dirt much faster
cleantime = 10
spawn(cleantime)
if(istype(loc,/turf/simulated))
var/turf/simulated/f = loc
f.dirt = 0
cleaning = 0
del(target)
icon_state = "cleanbot[on]"
anchored = 0
target = null
/obj/machinery/bot/cleanbot/explode()
src.on = 0
src.visible_message("\red <B>[src] blows apart!</B>", 1)
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
/obj/item/weapon/bucket_sensor/attackby(var/obj/item/W, mob/user as mob)
..()
if(istype(W, /obj/item/robot_parts/l_arm) || istype(W, /obj/item/robot_parts/r_arm))
user.drop_item()
del(W)
var/turf/T = get_turf(src.loc)
var/obj/machinery/bot/cleanbot/A = new /obj/machinery/bot/cleanbot(T)
A.name = src.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(W, /obj/item/weapon/pen))
var/t = sanitizeSafe(input(user, "Enter new robot name", src.name, src.created_name), MAX_NAME_LEN)
if (!t)
return
if (!in_range(src, usr) && src.loc != usr)
return
src.created_name = t

View File

@@ -1,210 +0,0 @@
/obj/machinery/bot/secbot/ed209
name = "ED-209 Security Robot"
desc = "A security robot. He looks less than thrilled."
icon = 'icons/obj/aibots.dmi'
icon_state = "ed2090"
density = 1
health = 100
maxhealth = 100
bot_version = "2.5"
search_range = 12
has_laser = 1
preparing_arrest_sounds = new()
secbot_assembly = /obj/item/weapon/secbot_assembly/ed209_assembly
/obj/item/weapon/secbot_assembly/ed209_assembly
name = "ED-209 assembly"
desc = "Some sort of bizarre assembly."
icon = 'icons/obj/aibots.dmi'
icon_state = "ed209_frame"
item_state = "ed209_frame"
created_name = "ED-209 Security Robot" //To preserve the name if it's a unique securitron I guess
var/lasercolor = ""
/obj/machinery/bot/secbot/ed209/update_icon()
if(on && is_attacking)
src.icon_state = "[lasercolor]ed209-c"
else
src.icon_state = "[lasercolor]ed209[src.on]"
/obj/machinery/bot/secbot/ed209/on_explosion(var/turf/Tsec)
if(!lasercolor)
var/obj/item/weapon/gun/energy/taser/G = new /obj/item/weapon/gun/energy/taser(Tsec)
G.power_supply.charge = 0
else if(lasercolor == "b")
var/obj/item/weapon/gun/energy/lasertag/blue/G = new (Tsec)
G.power_supply.charge = 0
else if(lasercolor == "r")
var/obj/item/weapon/gun/energy/lasertag/red/G = new (Tsec)
G.power_supply.charge = 0
if (prob(50))
new /obj/item/robot_parts/l_leg(Tsec)
if (prob(25))
new /obj/item/robot_parts/r_leg(Tsec)
if (prob(25))//50% chance for a helmet OR vest
if (prob(50))
new /obj/item/clothing/head/helmet(Tsec)
else
if(!lasercolor)
new /obj/item/clothing/suit/armor/vest(Tsec)
if(lasercolor == "b")
new /obj/item/clothing/suit/bluetag(Tsec)
if(lasercolor == "r")
new /obj/item/clothing/suit/redtag(Tsec)
/obj/item/weapon/secbot_assembly/ed209_assembly/attackby(obj/item/weapon/W as obj, mob/user as mob)
..()
if(istype(W, /obj/item/weapon/pen))
var/t = sanitizeSafe(input(user, "Enter new robot name", src.name, src.created_name), MAX_NAME_LEN)
if(!t) return
if(!in_range(src, usr) && src.loc != usr) return
created_name = t
return
switch(build_step)
if(0,1)
if( istype(W, /obj/item/robot_parts/l_leg) || istype(W, /obj/item/robot_parts/r_leg) )
user.drop_item()
del(W)
build_step++
user << "<span class='notice'>You add the robot leg to [src].</span>"
name = "legs/frame assembly"
if(build_step == 1)
item_state = "ed209_leg"
icon_state = "ed209_leg"
else
item_state = "ed209_legs"
icon_state = "ed209_legs"
if(2)
if( istype(W, /obj/item/clothing/suit/redtag) )
lasercolor = "r"
else if( istype(W, /obj/item/clothing/suit/bluetag) )
lasercolor = "b"
if( lasercolor || istype(W, /obj/item/clothing/suit/storage/vest) )
user.drop_item()
del(W)
build_step++
user << "<span class='notice'>You add the armor to [src].</span>"
name = "vest/legs/frame assembly"
item_state = "[lasercolor]ed209_shell"
icon_state = "[lasercolor]ed209_shell"
if(3)
if( istype(W, /obj/item/weapon/weldingtool) )
var/obj/item/weapon/weldingtool/WT = W
if(WT.remove_fuel(0,user))
build_step++
name = "shielded frame assembly"
user << "<span class='notice'>You welded the vest to [src].</span>"
if(4)
if( istype(W, /obj/item/clothing/head/helmet) )
user.drop_item()
del(W)
build_step++
user << "<span class='notice'>You add the helmet to [src].</span>"
name = "covered and shielded frame assembly"
item_state = "[lasercolor]ed209_hat"
icon_state = "[lasercolor]ed209_hat"
if(5)
if( isprox(W) )
user.drop_item()
del(W)
build_step++
user << "<span class='notice'>You add the prox sensor to [src].</span>"
name = "covered, shielded and sensored frame assembly"
item_state = "[lasercolor]ed209_prox"
icon_state = "[lasercolor]ed209_prox"
if(6)
if(istype(W, /obj/item/stack/cable_coil))
var/obj/item/stack/cable_coil/C = W
if (C.get_amount() < 1)
user << "<span class='warning'>You need one coil of wire to do wire [src].</span>"
return
user << "<span class='notice'>You start to wire [src].</span>"
if (do_after(user, 40) && build_step == 6)
if (C.use(1))
build_step++
user << "<span class='notice'>You wire the ED-209 assembly.</span>"
name = "wired ED-209 assembly"
return
if(7)
switch(lasercolor)
if("b")
if( !istype(W, /obj/item/weapon/gun/energy/lasertag/blue) )
return
name = "bluetag ED-209 assembly"
if("r")
if( !istype(W, /obj/item/weapon/gun/energy/lasertag/red) )
return
name = "redtag ED-209 assembly"
if("")
if( !istype(W, /obj/item/weapon/gun/energy/taser) )
return
name = "taser ED-209 assembly"
else
return
build_step++
user << "<span class='notice'>You add [W] to [src].</span>"
src.item_state = "[lasercolor]ed209_taser"
src.icon_state = "[lasercolor]ed209_taser"
user.drop_item()
del(W)
if(8)
if( istype(W, /obj/item/weapon/screwdriver) )
playsound(src.loc, 'sound/items/Screwdriver.ogg', 100, 1)
var/turf/T = get_turf(user)
user << "<span class='notice'>Now attaching the gun to the frame...</span>"
sleep(40)
if(get_turf(user) == T && build_step == 8)
build_step++
name = "armed [name]"
user << "<span class='notice'>Taser gun attached.</span>"
if(9)
if( istype(W, /obj/item/weapon/cell) )
build_step++
user << "<span class='notice'>You complete the ED-209.</span>"
var/turf/T = get_turf(src)
new /obj/machinery/bot/secbot/ed209(T,created_name,lasercolor)
user.drop_item()
del(W)
user.drop_from_inventory(src)
del(src)
/obj/machinery/bot/secbot/ed209/bullet_act(var/obj/item/projectile/Proj)
if((src.lasercolor == "b") && (src.disabled == 0))
if(istype(Proj, /obj/item/projectile/beam/lastertag/red))
src.disabled = 1
del (Proj)
sleep(100)
src.disabled = 0
else
..()
else if((src.lasercolor == "r") && (src.disabled == 0))
if(istype(Proj, /obj/item/projectile/beam/lastertag/blue))
src.disabled = 1
del (Proj)
sleep(100)
src.disabled = 0
else
..()
else
..()
/obj/machinery/bot/secbot/ed209/bluetag/New()//If desired, you spawn red and bluetag bots easily
new /obj/machinery/bot/secbot/ed209(get_turf(src),null,"b")
del(src)
/obj/machinery/bot/secbot/ed209/redtag/New()
new /obj/machinery/bot/secbot/ed209(get_turf(src),null,"r")
del(src)

View File

@@ -1,595 +0,0 @@
//Farmbots by GauHelldragon - 12/30/2012
// A new type of buildable aiBot that helps out in hydroponics
// Made by using a robot arm on a water tank and then adding:
// A plant analyzer, a bucket, a mini-hoe and then a proximity sensor (in that order)
// Will water, weed and fertilize plants that need it
// When emagged, it will "water", "weed" and "fertilize" humans instead
// Holds up to 10 fertilizers (only the type dispensed by the machines, not chemistry bottles)
// It will fill up it's water tank at a sink when low.
// The behavior panel can be unlocked with hydroponics access and be modified to disable certain behaviors
// By default, it will ignore weeds and mushrooms, but can be set to tend to these types of plants as well.
#define FARMBOT_MODE_WATER 1
#define FARMBOT_MODE_FERTILIZE 2
#define FARMBOT_MODE_WEED 3
#define FARMBOT_MODE_REFILL 4
#define FARMBOT_MODE_WAITING 5
#define FARMBOT_ANIMATION_TIME 25 //How long it takes to use one of the action animations
#define FARMBOT_EMAG_DELAY 60 //How long of a delay after doing one of the emagged attack actions
#define FARMBOT_ACTION_DELAY 35 //How long of a delay after doing one of the normal actions
/obj/machinery/bot/farmbot
name = "Farmbot"
desc = "The botanist's best friend."
icon = 'icons/obj/aibots.dmi'
icon_state = "farmbot0"
layer = 5.0
density = 1
anchored = 0
health = 50
maxhealth = 50
req_access =list(access_hydroponics)
var/Max_Fertilizers = 10
var/setting_water = 1
var/setting_refill = 1
var/setting_fertilize = 1
var/setting_weed = 1
var/setting_ignoreWeeds = 1
var/setting_ignoreMushrooms = 1
var/atom/target //Current target, can be a human, a hydroponics tray, or a sink
var/mode //Which mode is being used, 0 means it is looking for work
var/obj/structure/reagent_dispensers/watertank/tank // the water tank that was used to make it, remains inside the bot.
var/path[] = new() // used for pathing
var/frustration
/obj/machinery/bot/farmbot/New()
..()
src.icon_state = "farmbot[src.on]"
spawn (4)
src.botcard = new /obj/item/weapon/card/id(src)
src.botcard.access = req_access
if ( !tank ) //Should be set as part of making it... but lets check anyway
tank = locate(/obj/structure/reagent_dispensers/watertank/) in contents
if ( !tank ) //An admin must have spawned the farmbot! Better give it a tank.
tank = new /obj/structure/reagent_dispensers/watertank(src)
/obj/machinery/bot/farmbot/Bump(M as mob|obj) //Leave no door unopened!
spawn(0)
if ((istype(M, /obj/machinery/door)) && (!isnull(src.botcard)))
var/obj/machinery/door/D = M
if (!istype(D, /obj/machinery/door/firedoor) && D.check_access(src.botcard))
D.open()
src.frustration = 0
return
return
/obj/machinery/bot/farmbot/turn_on()
. = ..()
src.icon_state = "farmbot[src.on]"
src.updateUsrDialog()
/obj/machinery/bot/farmbot/turn_off()
..()
src.path = new()
src.icon_state = "farmbot[src.on]"
src.updateUsrDialog()
/obj/machinery/bot/farmbot/attack_paw(mob/user as mob)
return attack_hand(user)
/obj/machinery/bot/farmbot/proc/get_total_ferts()
var total_fert = 0
for (var/obj/item/nutrient/fert in contents)
total_fert++
return total_fert
/obj/machinery/bot/farmbot/attack_hand(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'>[src.on ? "On" : "Off"]</A><BR>"
dat += "Water Tank: "
if ( tank )
dat += "\[[tank.reagents.total_volume]/[tank.reagents.maximum_volume]\]"
else
dat += "Error: Water Tank not Found"
dat += "<br>Fertilizer Storage: <A href='?src=\ref[src];eject=1'>\[[get_total_ferts()]/[Max_Fertilizers]\]</a>"
dat += "<br>Behaviour controls are [src.locked ? "locked" : "unlocked"]<hr>"
if(!src.locked)
dat += "<TT>Watering Controls:<br>"
dat += " Water Plants : <A href='?src=\ref[src];water=1'>[src.setting_water ? "Yes" : "No"]</A><BR>"
dat += " Refill Watertank : <A href='?src=\ref[src];refill=1'>[src.setting_refill ? "Yes" : "No"]</A><BR>"
dat += "<br>Fertilizer Controls:<br>"
dat += " Fertilize Plants : <A href='?src=\ref[src];fertilize=1'>[src.setting_fertilize ? "Yes" : "No"]</A><BR>"
dat += "<br>Weeding Controls:<br>"
dat += " Weed Plants : <A href='?src=\ref[src];weed=1'>[src.setting_weed ? "Yes" : "No"]</A><BR>"
dat += "<br>Ignore Weeds : <A href='?src=\ref[src];ignoreWeed=1'>[src.setting_ignoreWeeds ? "Yes" : "No"]</A><BR>"
dat += "Ignore Mushrooms : <A href='?src=\ref[src];ignoreMush=1'>[src.setting_ignoreMushrooms ? "Yes" : "No"]</A><BR>"
dat += "</TT>"
user << browse("<HEAD><TITLE>Farmbot v1.0 controls</TITLE></HEAD>[dat]", "window=autofarm")
onclose(user, "autofarm")
return
/obj/machinery/bot/farmbot/Topic(href, href_list)
if(..())
return
usr.machine = src
src.add_fingerprint(usr)
if ((href_list["power"]) && (src.allowed(usr)))
if (src.on)
turn_off()
else
turn_on()
else if((href_list["water"]) && (!src.locked))
setting_water = !setting_water
else if((href_list["refill"]) && (!src.locked))
setting_refill = !setting_refill
else if((href_list["fertilize"]) && (!src.locked))
setting_fertilize = !setting_fertilize
else if((href_list["weed"]) && (!src.locked))
setting_weed = !setting_weed
else if((href_list["ignoreWeed"]) && (!src.locked))
setting_ignoreWeeds = !setting_ignoreWeeds
else if((href_list["ignoreMush"]) && (!src.locked))
setting_ignoreMushrooms = !setting_ignoreMushrooms
else if (href_list["eject"] )
flick("farmbot_hatch",src)
for (var/obj/item/nutrient/fert in contents)
fert.loc = get_turf(src)
src.updateUsrDialog()
return
/obj/machinery/bot/farmbot/attackby(obj/item/weapon/W as obj, mob/user as mob)
if (istype(W, /obj/item/weapon/card/id)||istype(W, /obj/item/device/pda))
if (src.allowed(user))
src.locked = !src.locked
user << "Controls are now [src.locked ? "locked." : "unlocked."]"
src.updateUsrDialog()
else
user << "\red Access denied."
else if (istype(W, /obj/item/nutrient))
if ( get_total_ferts() >= Max_Fertilizers )
user << "The fertilizer storage is full!"
return
user.drop_item()
W.loc = src
user << "You insert [W]."
flick("farmbot_hatch",src)
src.updateUsrDialog()
return
else
..()
/obj/machinery/bot/farmbot/Emag(mob/user as mob)
..()
if(user) user << "\red You short out [src]'s plant identifier circuits."
spawn(0)
for(var/mob/O in hearers(src, null))
O.show_message("\red <B>[src] buzzes oddly!</B>", 1)
flick("farmbot_broke", src)
src.emagged = 1
src.on = 1
src.icon_state = "farmbot[src.on]"
target = null
mode = FARMBOT_MODE_WAITING //Give the emagger a chance to get away! 15 seconds should be good.
spawn(150)
mode = 0
/obj/machinery/bot/farmbot/explode()
src.on = 0
visible_message("\red <B>[src] blows apart!</B>", 1)
var/turf/Tsec = get_turf(src)
new /obj/item/weapon/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
for ( var/obj/item/nutrient/fert in contents )
if ( prob(50) )
fert.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()
del(src)
return
/obj/machinery/bot/farmbot/process()
set background = 1
if(!src.on)
return
if ( emagged && prob(1) )
flick("farmbot_broke", src)
if ( mode == FARMBOT_MODE_WAITING )
return
if ( !mode || !target || !(target in view(7,src)) ) //Don't bother chasing down targets out of view
mode = 0
target = null
if ( !find_target() )
// Couldn't find a target, wait a while before trying again.
mode = FARMBOT_MODE_WAITING
spawn(100)
mode = 0
return
if ( mode && target )
if ( get_dist(target,src) <= 1 || ( emagged && mode == FARMBOT_MODE_FERTILIZE ) )
// If we are in emagged fertilize mode, we throw the fertilizer, so distance doesn't matter
frustration = 0
use_farmbot_item()
else
move_to_target()
return
/obj/machinery/bot/farmbot/proc/use_farmbot_item()
if ( !target )
mode = 0
return 0
if ( emagged && !ismob(target) ) // Humans are plants!
mode = 0
target = null
return 0
if ( !emagged && !istype(target,/obj/machinery/hydroponics) && !istype(target,/obj/structure/sink) ) // Humans are not plants!
mode = 0
target = null
return 0
if ( mode == FARMBOT_MODE_FERTILIZE )
//Find which fertilizer to use
var/obj/item/nutrient/fert
for ( var/obj/item/nutrient/nut in contents )
fert = nut
break
if ( !fert )
target = null
mode = 0
return
fertilize(fert)
if ( mode == FARMBOT_MODE_WEED )
weed()
if ( mode == FARMBOT_MODE_WATER )
water()
if ( mode == FARMBOT_MODE_REFILL )
refill()
/obj/machinery/bot/farmbot/proc/find_target()
if ( emagged ) //Find a human and help them!
for ( var/mob/living/carbon/human/human in view(7,src) )
if (human.stat == 2)
continue
var list/options = list(FARMBOT_MODE_WEED)
if ( get_total_ferts() )
options.Add(FARMBOT_MODE_FERTILIZE)
if ( tank && tank.reagents.total_volume >= 1 )
options.Add(FARMBOT_MODE_WATER)
mode = pick(options)
target = human
return mode
return 0
else
if ( setting_refill && tank && tank.reagents.total_volume < 100 )
for ( var/obj/structure/sink/source in view(7,src) )
target = source
mode = FARMBOT_MODE_REFILL
return 1
for ( var/obj/machinery/hydroponics/tray in view(7,src) )
var newMode = GetNeededMode(tray)
if ( newMode )
mode = newMode
target = tray
return 1
return 0
/obj/machinery/bot/farmbot/proc/GetNeededMode(obj/machinery/hydroponics/tray)
if ( !tray.planted || tray.dead )
return 0
if ( tray.myseed.plant_type == 1 && setting_ignoreWeeds )
return 0
if ( tray.myseed.plant_type == 2 && setting_ignoreMushrooms )
return 0
if ( setting_water && tray.waterlevel <= 10 && tank && tank.reagents.total_volume >= 1 )
return FARMBOT_MODE_WATER
if ( setting_weed && tray.weedlevel >= 5 )
return FARMBOT_MODE_WEED
if ( setting_fertilize && tray.nutrilevel <= 2 && get_total_ferts() )
return FARMBOT_MODE_FERTILIZE
return 0
/obj/machinery/bot/farmbot/proc/move_to_target()
//Mostly copied from medibot code.
if(src.frustration > 8)
target = null
mode = 0
frustration = 0
src.path = new()
if(src.target && (src.path.len) && (get_dist(src.target,src.path[src.path.len]) > 2))
src.path = new()
if(src.target && src.path.len == 0 && (get_dist(src,src.target) > 1))
spawn(0)
var/turf/dest = get_step_towards(target,src) //Can't pathfind to a tray, as it is dense, so pathfind to the spot next to the tray
src.path = AStar(src.loc, dest, /turf/proc/CardinalTurfsWithAccess, /turf/proc/Distance, 0, 30,id=botcard)
if(src.path.len == 0)
for ( var/turf/spot in orange(1,target) ) //The closest one is unpathable, try the other spots
if ( spot == dest ) //We already tried this spot
continue
if ( spot.density )
continue
src.path = AStar(src.loc, spot, /turf/proc/CardinalTurfsWithAccess, /turf/proc/Distance, 0, 30,id=botcard)
src.path = reverselist(src.path)
if ( src.path.len > 0 )
break
if ( src.path.len == 0 )
target = null
mode = 0
return
if(src.path.len > 0 && src.target)
step_to(src, src.path[1])
src.path -= src.path[1]
spawn(3)
if(src.path.len)
step_to(src, src.path[1])
src.path -= src.path[1]
if(src.path.len > 8 && src.target)
src.frustration++
/obj/machinery/bot/farmbot/proc/fertilize(obj/item/nutrient/fert)
if ( !fert )
target = null
mode = 0
return 0
if ( emagged ) // Warning, hungry humans detected: throw fertilizer at them
spawn(0)
fert.loc = src.loc
fert.throw_at(target, 16, 3, src)
src.visible_message("\red <b>[src] launches [fert.name] at [target.name]!</b>")
flick("farmbot_broke", src)
spawn (FARMBOT_EMAG_DELAY)
mode = 0
target = null
return 1
else // feed them plants~
var /obj/machinery/hydroponics/tray = target
tray.nutrilevel = 10
tray.yieldmod = fert.yieldmod
tray.mutmod = fert.mutmod
del fert
tray.updateicon()
icon_state = "farmbot_fertile"
mode = FARMBOT_MODE_WAITING
spawn (FARMBOT_ACTION_DELAY)
mode = 0
target = null
spawn (FARMBOT_ANIMATION_TIME)
icon_state = "farmbot[src.on]"
return 1
/obj/machinery/bot/farmbot/proc/weed()
icon_state = "farmbot_hoe"
spawn(FARMBOT_ANIMATION_TIME)
icon_state = "farmbot[src.on]"
if ( emagged ) // Warning, humans infested with weeds!
mode = FARMBOT_MODE_WAITING
spawn(FARMBOT_EMAG_DELAY)
mode = 0
if ( prob(50) ) // better luck next time little guy
src.visible_message("\red <b>[src] swings wildly at [target] with a minihoe, missing completely!</b>")
else // yayyy take that weeds~
var/attackVerb = pick("slashed", "sliced", "cut", "clawed")
var /mob/living/carbon/human/human = target
src.visible_message("\red <B>[src] [attackVerb] [human]!</B>")
var/damage = 5
var/dam_zone = pick("chest", "l_hand", "r_hand", "l_leg", "r_leg")
var/datum/organ/external/affecting = human.get_organ(ran_zone(dam_zone))
var/armor = human.run_armor_check(affecting, "melee")
human.apply_damage(damage,BRUTE,affecting,armor,sharp=1,edge=1)
else // warning, plants infested with weeds!
mode = FARMBOT_MODE_WAITING
spawn(FARMBOT_ACTION_DELAY)
mode = 0
var /obj/machinery/hydroponics/tray = target
tray.weedlevel = 0
tray.updateicon()
/obj/machinery/bot/farmbot/proc/water()
if ( !tank || tank.reagents.total_volume < 1 )
mode = 0
target = null
return 0
icon_state = "farmbot_water"
spawn(FARMBOT_ANIMATION_TIME)
icon_state = "farmbot[src.on]"
if ( emagged ) // warning, humans are thirsty!
var splashAmount = min(70,tank.reagents.total_volume)
src.visible_message("\red [src] splashes [target] with a bucket of water!")
playsound(src.loc, 'sound/effects/slosh.ogg', 25, 1)
if ( prob(50) )
tank.reagents.reaction(target, TOUCH) //splash the human!
else
tank.reagents.reaction(target.loc, TOUCH) //splash the human's roots!
spawn(5)
tank.reagents.remove_any(splashAmount)
mode = FARMBOT_MODE_WAITING
spawn(FARMBOT_EMAG_DELAY)
mode = 0
else
var /obj/machinery/hydroponics/tray = target
var/b_amount = tank.reagents.get_reagent_amount("water")
if(b_amount > 0 && tray.waterlevel < 100)
if(b_amount + tray.waterlevel > 100)
b_amount = 100 - tray.waterlevel
tank.reagents.remove_reagent("water", b_amount)
tray.waterlevel += b_amount
playsound(src.loc, 'sound/effects/slosh.ogg', 25, 1)
// Toxicity dilutation code. The more water you put in, the lesser the toxin concentration.
tray.toxic -= round(b_amount/4)
if (tray.toxic < 0 ) // Make sure it won't go overboard
tray.toxic = 0
tray.updateicon()
mode = FARMBOT_MODE_WAITING
spawn(FARMBOT_ACTION_DELAY)
mode = 0
/obj/machinery/bot/farmbot/proc/refill()
if ( !tank || !tank.reagents.total_volume > 600 || !istype(target,/obj/structure/sink) )
mode = 0
target = null
return
mode = FARMBOT_MODE_WAITING
playsound(src.loc, 'sound/effects/slosh.ogg', 25, 1)
src.visible_message("\blue [src] starts filling it's tank from [target].")
spawn(300)
src.visible_message("\blue [src] finishes filling it's tank.")
src.mode = 0
tank.reagents.add_reagent("water", tank.reagents.maximum_volume - tank.reagents.total_volume )
playsound(src.loc, 'sound/effects/slosh.ogg', 25, 1)
/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" //To preserve the name if it's a unique farmbot I guess
w_class = 3.0
New()
..()
spawn(4) // If an admin spawned it, it won't have a watertank it, so lets make one for em!
var tank = locate(/obj/structure/reagent_dispensers/watertank) in contents
if( !tank )
new /obj/structure/reagent_dispensers/watertank(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
//Making a farmbot!
var/obj/item/weapon/farmbot_arm_assembly/A = new /obj/item/weapon/farmbot_arm_assembly
A.loc = src.loc
user << "You add the robot arm to the [src]"
src.loc = A //Place the water tank into the assembly, it will be needed for the finished bot
user.remove_from_mob(S)
del(S)
/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)) && (!src.build_step))
src.build_step++
user << "You add the plant analyzer to [src]!"
src.name = "farmbot assembly"
user.remove_from_mob(W)
del(W)
else if(( istype(W, /obj/item/weapon/reagent_containers/glass/bucket)) && (src.build_step == 1))
src.build_step++
user << "You add a bucket to [src]!"
src.name = "farmbot assembly with bucket"
user.remove_from_mob(W)
del(W)
else if(( istype(W, /obj/item/weapon/minihoe)) && (src.build_step == 2))
src.build_step++
user << "You add a minihoe to [src]!"
src.name = "farmbot assembly with bucket and minihoe"
user.remove_from_mob(W)
del(W)
else if((isprox(W)) && (src.build_step == 3))
src.build_step++
user << "You complete the Farmbot! Beep boop."
var/obj/machinery/bot/farmbot/S = new /obj/machinery/bot/farmbot
for ( var/obj/structure/reagent_dispensers/watertank/wTank in src.contents )
wTank.loc = S
S.tank = wTank
S.loc = get_turf(src)
S.name = src.created_name
user.remove_from_mob(W)
del(W)
del(src)
else if(istype(W, /obj/item/weapon/pen))
var/t = input(user, "Enter new robot name", src.name, src.created_name) as text
t = sanitize(t, MAX_NAME_LEN)
if (!t)
return
if (!in_range(src, usr) && src.loc != usr)
return
src.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

View File

@@ -1,449 +0,0 @@
//Floorbot assemblies
/obj/item/weapon/toolbox_tiles
desc = "It's a toolbox with tiles sticking out the top"
name = "tiles and toolbox"
icon = 'icons/obj/aibots.dmi'
icon_state = "toolbox_tiles"
force = 3.0
throwforce = 10.0
throw_speed = 2
throw_range = 5
w_class = 3.0
var/created_name = "Floorbot"
/obj/item/weapon/toolbox_tiles_sensor
desc = "It's a toolbox with tiles sticking out the top and a sensor attached"
name = "tiles, toolbox and sensor arrangement"
icon = 'icons/obj/aibots.dmi'
icon_state = "toolbox_tiles_sensor"
force = 3.0
throwforce = 10.0
throw_speed = 2
throw_range = 5
w_class = 3.0
var/created_name = "Floorbot"
//Floorbot
/obj/machinery/bot/floorbot
name = "Floorbot"
desc = "A little floor repairing robot, he looks so excited!"
icon = 'icons/obj/aibots.dmi'
icon_state = "floorbot0"
layer = 5.0
density = 0
anchored = 0
health = 25
maxhealth = 25
//weight = 1.0E7
var/amount = 10
var/repairing = 0
var/improvefloors = 0
var/eattiles = 0
var/maketiles = 0
var/turf/target
var/turf/oldtarget
var/oldloc = null
req_access = list(access_construction)
var/path[] = new()
var/targetdirection
/obj/machinery/bot/floorbot/New()
..()
src.updateicon()
/obj/machinery/bot/floorbot/turn_on()
. = ..()
src.updateicon()
src.updateUsrDialog()
/obj/machinery/bot/floorbot/turn_off()
..()
src.target = null
src.oldtarget = null
src.oldloc = null
src.updateicon()
src.path = new()
src.updateUsrDialog()
/obj/machinery/bot/floorbot/attack_hand(mob/user as mob)
. = ..()
if (.)
return
usr.set_machine(src)
interact(user)
/obj/machinery/bot/floorbot/interact(mob/user as mob)
var/dat
dat += "<TT><B>Automatic Station Floor Repairer v1.0</B></TT><BR><BR>"
dat += "Status: <A href='?src=\ref[src];operation=start'>[src.on ? "On" : "Off"]</A><BR>"
dat += "Maintenance panel is [src.open ? "opened" : "closed"]<BR>"
dat += "Tiles left: [src.amount]<BR>"
dat += "Behvaiour controls are [src.locked ? "locked" : "unlocked"]<BR>"
if(!src.locked || issilicon(user))
dat += "Improves floors: <A href='?src=\ref[src];operation=improve'>[src.improvefloors ? "Yes" : "No"]</A><BR>"
dat += "Finds tiles: <A href='?src=\ref[src];operation=tiles'>[src.eattiles ? "Yes" : "No"]</A><BR>"
dat += "Make singles pieces of metal into tiles when empty: <A href='?src=\ref[src];operation=make'>[src.maketiles ? "Yes" : "No"]</A><BR>"
var/bmode
if (src.targetdirection)
bmode = dir2text(src.targetdirection)
else
bmode = "Disabled"
dat += "<BR><BR>Bridge Mode : <A href='?src=\ref[src];operation=bridgemode'>[bmode]</A><BR>"
user << browse("<HEAD><TITLE>Repairbot v1.0 controls</TITLE></HEAD>[dat]", "window=autorepair")
onclose(user, "autorepair")
return
/obj/machinery/bot/floorbot/attackby(var/obj/item/W , mob/user as mob)
if(istype(W, /obj/item/stack/tile/plasteel))
var/obj/item/stack/tile/plasteel/T = W
if(src.amount >= 50)
return
var/loaded = min(50-src.amount, T.get_amount())
T.use(loaded)
src.amount += loaded
user << "<span class='notice'>You load [loaded] tiles into the floorbot. He now contains [src.amount] tiles.</span>"
src.updateicon()
else if(istype(W, /obj/item/weapon/card/id)||istype(W, /obj/item/device/pda))
if(src.allowed(usr) && !open && !emagged)
src.locked = !src.locked
user << "<span class='notice'>You [src.locked ? "lock" : "unlock"] the [src] behaviour controls.</span>"
else
if(emagged)
user << "<span class='warning'>ERROR</span>"
if(open)
user << "<span class='warning'>Please close the access panel before locking it.</span>"
else
user << "<span class='warning'>Access denied.</span>"
src.updateUsrDialog()
else
..()
/obj/machinery/bot/floorbot/Emag(mob/user as mob)
..()
if(open && !locked)
if(user) user << "<span class='notice'>The [src] buzzes and beeps.</span>"
/obj/machinery/bot/floorbot/Topic(href, href_list)
if(..())
return
usr.set_machine(src)
src.add_fingerprint(usr)
switch(href_list["operation"])
if("start")
if (src.on)
turn_off()
else
turn_on()
if("improve")
src.improvefloors = !src.improvefloors
src.updateUsrDialog()
if("tiles")
src.eattiles = !src.eattiles
src.updateUsrDialog()
if("make")
src.maketiles = !src.maketiles
src.updateUsrDialog()
if("bridgemode")
switch(src.targetdirection)
if(null)
targetdirection = 1
if(1)
targetdirection = 2
if(2)
targetdirection = 4
if(4)
targetdirection = 8
if(8)
targetdirection = null
else
targetdirection = null
src.updateUsrDialog()
/obj/machinery/bot/floorbot/process()
set background = 1
if(!src.on)
return
if(src.repairing)
return
var/list/floorbottargets = list()
if(src.amount <= 0 && ((src.target == null) || !src.target))
if(src.eattiles)
for(var/obj/item/stack/tile/plasteel/T in view(7, src))
if(T != src.oldtarget && !(target in floorbottargets))
src.oldtarget = T
src.target = T
break
if(src.target == null || !src.target)
if(src.maketiles)
if(src.target == null || !src.target)
for(var/obj/item/stack/sheet/metal/M in view(7, src))
if(!(M in floorbottargets) && M != src.oldtarget && M.amount == 1 && !(istype(M.loc, /turf/simulated/wall)))
src.oldtarget = M
src.target = M
break
else
return
if(prob(5))
visible_message("[src] makes an excited booping beeping sound!")
if((!src.target || src.target == null) && emagged < 2)
if(targetdirection != null)
/*
for (var/turf/space/D in view(7,src))
if(!(D in floorbottargets) && D != src.oldtarget) // Added for bridging mode -- TLE
if(get_dir(src, D) == targetdirection)
src.oldtarget = D
src.target = D
break
*/
var/turf/T = get_step(src, targetdirection)
if(istype(T, /turf/space))
src.oldtarget = T
src.target = T
if(!src.target || src.target == null)
for (var/turf/space/D in view(7,src))
if(!(D in floorbottargets) && D != src.oldtarget && (D.loc.name != "Space"))
src.oldtarget = D
src.target = D
break
if((!src.target || src.target == null ) && src.improvefloors)
for (var/turf/simulated/floor/F in view(7,src))
if(!(F in floorbottargets) && F != src.oldtarget && F.icon_state == "Floor1" && !(istype(F, /turf/simulated/floor/plating)))
src.oldtarget = F
src.target = F
break
if((!src.target || src.target == null) && src.eattiles)
for(var/obj/item/stack/tile/plasteel/T in view(7, src))
if(!(T in floorbottargets) && T != src.oldtarget)
src.oldtarget = T
src.target = T
break
if((!src.target || src.target == null) && emagged == 2)
if(!src.target || src.target == null)
for (var/turf/simulated/floor/D in view(7,src))
if(!(D in floorbottargets) && D != src.oldtarget && D.floor_type)
src.oldtarget = D
src.target = D
break
if(!src.target || src.target == null)
if(src.loc != src.oldloc)
src.oldtarget = null
return
if(src.target && (src.target != null) && src.path.len == 0)
spawn(0)
if(!istype(src.target, /turf/))
src.path = AStar(src.loc, src.target.loc, /turf/proc/AdjacentTurfsSpace, /turf/proc/Distance, 0, 30, id=botcard)
else
src.path = AStar(src.loc, src.target, /turf/proc/AdjacentTurfsSpace, /turf/proc/Distance, 0, 30, id=botcard)
if (!src.path) src.path = list()
if(src.path.len == 0)
src.oldtarget = src.target
src.target = null
return
if(src.path.len > 0 && src.target && (src.target != null))
step_to(src, src.path[1])
src.path -= src.path[1]
else if(src.path.len == 1)
step_to(src, target)
src.path = new()
if(src.loc == src.target || src.loc == src.target.loc)
if(istype(src.target, /obj/item/stack/tile/plasteel))
src.eattile(src.target)
else if(istype(src.target, /obj/item/stack/sheet/metal))
src.maketile(src.target)
else if(istype(src.target, /turf/) && emagged < 2)
repair(src.target)
else if(emagged == 2 && istype(src.target,/turf/simulated/floor))
var/turf/simulated/floor/F = src.target
src.anchored = 1
src.repairing = 1
if(prob(90))
F.break_tile_to_plating()
else
F.ReplaceWithLattice()
visible_message("\red [src] makes an excited booping sound.")
spawn(50)
src.amount ++
src.anchored = 0
src.repairing = 0
src.target = null
src.path = new()
return
src.oldloc = src.loc
/obj/machinery/bot/floorbot/proc/repair(var/turf/target)
if(istype(target, /turf/space/))
if(target.loc.name == "Space")
return
else if(!istype(target, /turf/simulated/floor))
return
if(src.amount <= 0)
return
src.anchored = 1
src.icon_state = "floorbot-c"
if(istype(target, /turf/space/))
visible_message("\red [src] begins to repair the hole")
var/obj/item/stack/tile/plasteel/T = new /obj/item/stack/tile/plasteel
src.repairing = 1
spawn(50)
T.build(src.loc)
src.repairing = 0
src.amount -= 1
src.updateicon()
src.anchored = 0
src.target = null
else
visible_message("\red [src] begins to improve the floor.")
src.repairing = 1
spawn(50)
src.loc.icon_state = "floor"
src.repairing = 0
src.amount -= 1
src.updateicon()
src.anchored = 0
src.target = null
/obj/machinery/bot/floorbot/proc/eattile(var/obj/item/stack/tile/plasteel/T)
if(!istype(T, /obj/item/stack/tile/plasteel))
return
visible_message("\red [src] begins to collect tiles.")
src.repairing = 1
spawn(20)
if(isnull(T))
src.target = null
src.repairing = 0
return
if(src.amount + T.get_amount() > 50)
var/i = 50 - src.amount
src.amount += i
T.use(i)
else
src.amount += T.get_amount()
del(T)
src.updateicon()
src.target = null
src.repairing = 0
/obj/machinery/bot/floorbot/proc/maketile(var/obj/item/stack/sheet/metal/M)
if(!istype(M, /obj/item/stack/sheet/metal))
return
if(M.get_amount() > 1)
return
visible_message("\red [src] begins to create tiles.")
src.repairing = 1
spawn(20)
if(isnull(M))
src.target = null
src.repairing = 0
return
var/obj/item/stack/tile/plasteel/T = new /obj/item/stack/tile/plasteel
T.amount = 4
T.loc = M.loc
del(M)
src.target = null
src.repairing = 0
/obj/machinery/bot/floorbot/proc/updateicon()
if(src.amount > 0)
src.icon_state = "floorbot[src.on]"
else
src.icon_state = "floorbot[src.on]e"
/obj/machinery/bot/floorbot/explode()
src.on = 0
src.visible_message("\red <B>[src] blows apart!</B>", 1)
var/turf/Tsec = get_turf(src)
var/obj/item/weapon/storage/toolbox/mechanical/N = new /obj/item/weapon/storage/toolbox/mechanical(Tsec)
N.contents = list()
new /obj/item/device/assembly/prox_sensor(Tsec)
if (prob(50))
new /obj/item/robot_parts/l_arm(Tsec)
while (amount)//Dumps the tiles into the appropriate sized stacks
if(amount >= 16)
var/obj/item/stack/tile/plasteel/T = new (Tsec)
T.amount = 16
amount -= 16
else
var/obj/item/stack/tile/plasteel/T = new (Tsec)
T.amount = src.amount
amount = 0
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
/obj/item/weapon/storage/toolbox/mechanical/attackby(var/obj/item/stack/tile/plasteel/T, mob/user as mob)
if(!istype(T, /obj/item/stack/tile/plasteel))
..()
return
if(src.contents.len >= 1)
user << "<span class='notice'>They wont fit in as there is already stuff inside.</span>"
return
if(user.s_active)
user.s_active.close(user)
if (T.use(10))
var/obj/item/weapon/toolbox_tiles/B = new /obj/item/weapon/toolbox_tiles
user.put_in_hands(B)
user << "<span class='notice'>You add the tiles into the empty toolbox. They protrude from the top.</span>"
user.drop_from_inventory(src)
del(src)
else
user << "<span class='warning'>You need 10 floortiles for a floorbot.</span>"
return
/obj/item/weapon/toolbox_tiles/attackby(var/obj/item/W, mob/user as mob)
..()
if(isprox(W))
del(W)
var/obj/item/weapon/toolbox_tiles_sensor/B = new /obj/item/weapon/toolbox_tiles_sensor()
B.created_name = src.created_name
user.put_in_hands(B)
user << "<span class='notice'>You add the sensor to the toolbox and tiles!</span>"
user.drop_from_inventory(src)
del(src)
else if (istype(W, /obj/item/weapon/pen))
var/t = sanitizeSafe(input(user, "Enter new robot name", src.name, src.created_name), MAX_NAME_LEN)
if (!t)
return
if (!in_range(src, usr) && src.loc != usr)
return
src.created_name = t
/obj/item/weapon/toolbox_tiles_sensor/attackby(var/obj/item/W, mob/user as mob)
..()
if(istype(W, /obj/item/robot_parts/l_arm) || istype(W, /obj/item/robot_parts/r_arm))
del(W)
var/turf/T = get_turf(user.loc)
var/obj/machinery/bot/floorbot/A = new /obj/machinery/bot/floorbot(T)
A.name = src.created_name
user << "<span class='notice'>You add the robot arm to the odd looking toolbox assembly! Boop beep!</span>"
user.drop_from_inventory(src)
del(src)
else if (istype(W, /obj/item/weapon/pen))
var/t = sanitizeSafe(input(user, "Enter new robot name", src.name, src.created_name), MAX_NAME_LEN)
if (!t)
return
if (!in_range(src, usr) && src.loc != usr)
return
src.created_name = t

View File

@@ -1,596 +0,0 @@
//MEDBOT
//MEDBOT PATHFINDING
//MEDBOT ASSEMBLY
/obj/machinery/bot/medbot
name = "Medibot"
desc = "A little medical robot. He looks somewhat underwhelmed."
icon = 'icons/obj/aibots.dmi'
icon_state = "medibot0"
layer = 5.0
density = 0
anchored = 0
health = 20
maxhealth = 20
req_access =list(access_medical)
var/stunned = 0 //It can be stunned by tasers. Delicate circuits.
//var/emagged = 0
var/list/botcard_access = list(access_medical)
var/obj/item/weapon/reagent_containers/glass/reagent_glass = null //Can be set to draw from this for reagents.
var/skin = null //Set to "tox", "ointment" or "o2" for the other two firstaid kits.
var/frustration = 0
var/path[] = new()
var/mob/living/carbon/patient = null
var/mob/living/carbon/oldpatient = null
var/oldloc = null
var/last_found = 0
var/last_newpatient_speak = 0 //Don't spam the "HEY I'M COMING" messages
var/currently_healing = 0
var/injection_amount = 15 //How much reagent do we inject at a time?
var/heal_threshold = 10 //Start healing when they have this much damage in a category
var/use_beaker = 0 //Use reagents in beaker instead of default treatment agents.
//Setting which reagents to use to treat what by default. By id.
var/treatment_brute = "tricordrazine"
var/treatment_oxy = "tricordrazine"
var/treatment_fire = "tricordrazine"
var/treatment_tox = "tricordrazine"
var/treatment_virus = "spaceacillin"
var/declare_treatment = 0 //When attempting to treat a patient, should it notify everyone wearing medhuds?
var/shut_up = 0 //self explanatory :)
/obj/machinery/bot/medbot/mysterious
name = "Mysterious Medibot"
desc = "International Medibot of mystery."
skin = "bezerk"
treatment_oxy = "dexalinp"
treatment_brute = "bicaridine"
treatment_fire = "kelotane"
treatment_tox = "anti_toxin"
/obj/item/weapon/firstaid_arm_assembly
name = "first aid/robot arm assembly"
desc = "A first aid kit with a robot arm permanently grafted to it."
icon = 'icons/obj/aibots.dmi'
icon_state = "firstaid_arm"
var/build_step = 0
var/created_name = "Medibot" //To preserve the name if it's a unique medbot I guess
var/skin = null //Same as medbot, set to tox or ointment for the respective kits.
w_class = 3.0
New()
..()
spawn(5)
if(src.skin)
src.overlays += image('icons/obj/aibots.dmi', "kit_skin_[src.skin]")
/obj/machinery/bot/medbot/New()
..()
src.icon_state = "medibot[src.on]"
spawn(4)
if(src.skin)
src.overlays += image('icons/obj/aibots.dmi', "medskin_[src.skin]")
src.botcard = new /obj/item/weapon/card/id(src)
if(isnull(src.botcard_access) || (src.botcard_access.len < 1))
src.botcard.access = list(access_medical, access_morgue, access_surgery, access_chemistry, access_virology, access_genetics)
else
src.botcard.access = src.botcard_access
/obj/machinery/bot/medbot/turn_on()
. = ..()
src.icon_state = "medibot[src.on]"
src.updateUsrDialog()
/obj/machinery/bot/medbot/turn_off()
..()
src.patient = null
src.oldpatient = null
src.oldloc = null
src.path = new()
src.currently_healing = 0
src.last_found = world.time
src.icon_state = "medibot[src.on]"
src.updateUsrDialog()
/obj/machinery/bot/medbot/attack_hand(mob/user as mob)
. = ..()
if (.)
return
var/dat
dat += "<TT><B>Automatic Medical Unit v1.0</B></TT><BR><BR>"
dat += "Status: <A href='?src=\ref[src];power=1'>[src.on ? "On" : "Off"]</A><BR>"
dat += "Maintenance panel is [src.open ? "opened" : "closed"]<BR>"
dat += "Beaker: "
if (src.reagent_glass)
dat += "<A href='?src=\ref[src];eject=1'>Loaded \[[src.reagent_glass.reagents.total_volume]/[src.reagent_glass.reagents.maximum_volume]\]</a>"
else
dat += "None Loaded"
dat += "<br>Behaviour controls are [src.locked ? "locked" : "unlocked"]<hr>"
if(!src.locked || issilicon(user))
dat += "<TT>Healing Threshold: "
dat += "<a href='?src=\ref[src];adj_threshold=-10'>--</a> "
dat += "<a href='?src=\ref[src];adj_threshold=-5'>-</a> "
dat += "[src.heal_threshold] "
dat += "<a href='?src=\ref[src];adj_threshold=5'>+</a> "
dat += "<a href='?src=\ref[src];adj_threshold=10'>++</a>"
dat += "</TT><br>"
dat += "<TT>Injection Level: "
dat += "<a href='?src=\ref[src];adj_inject=-5'>-</a> "
dat += "[src.injection_amount] "
dat += "<a href='?src=\ref[src];adj_inject=5'>+</a> "
dat += "</TT><br>"
dat += "Reagent Source: "
dat += "<a href='?src=\ref[src];use_beaker=1'>[src.use_beaker ? "Loaded Beaker (When available)" : "Internal Synthesizer"]</a><br>"
dat += "Treatment report is [src.declare_treatment ? "on" : "off"]. <a href='?src=\ref[src];declaretreatment=[1]'>Toggle</a><br>"
dat += "The speaker switch is [src.shut_up ? "off" : "on"]. <a href='?src=\ref[src];togglevoice=[1]'>Toggle</a><br>"
user << browse("<HEAD><TITLE>Medibot v1.0 controls</TITLE></HEAD>[dat]", "window=automed")
onclose(user, "automed")
return
/obj/machinery/bot/medbot/Topic(href, href_list)
if(..())
return
usr.set_machine(src)
src.add_fingerprint(usr)
if ((href_list["power"]) && (src.allowed(usr)))
if (src.on)
turn_off()
else
turn_on()
else if((href_list["adj_threshold"]) && (!src.locked || issilicon(usr)))
var/adjust_num = text2num(href_list["adj_threshold"])
src.heal_threshold += adjust_num
if(src.heal_threshold < 5)
src.heal_threshold = 5
if(src.heal_threshold > 75)
src.heal_threshold = 75
else if((href_list["adj_inject"]) && (!src.locked || issilicon(usr)))
var/adjust_num = text2num(href_list["adj_inject"])
src.injection_amount += adjust_num
if(src.injection_amount < 5)
src.injection_amount = 5
if(src.injection_amount > 15)
src.injection_amount = 15
else if((href_list["use_beaker"]) && (!src.locked || issilicon(usr)))
src.use_beaker = !src.use_beaker
else if (href_list["eject"] && (!isnull(src.reagent_glass)))
if(!src.locked)
src.reagent_glass.loc = get_turf(src)
src.reagent_glass = null
else
usr << "<span class='notice'>You cannot eject the beaker because the panel is locked.</span>"
else if ((href_list["togglevoice"]) && (!src.locked || issilicon(usr)))
src.shut_up = !src.shut_up
else if ((href_list["declaretreatment"]) && (!src.locked || issilicon(usr)))
src.declare_treatment = !src.declare_treatment
src.updateUsrDialog()
return
/obj/machinery/bot/medbot/attackby(obj/item/weapon/W as obj, mob/user as mob)
if (istype(W, /obj/item/weapon/card/id)||istype(W, /obj/item/device/pda))
if (src.allowed(user) && !open && !emagged)
src.locked = !src.locked
user << "<span class='notice'>Controls are now [src.locked ? "locked." : "unlocked."]</span>"
src.updateUsrDialog()
else
if(emagged)
user << "<span class='warning'>ERROR</span>"
if(open)
user << "<span class='warning'>Please close the access panel before locking it.</span>"
else
user << "<span class='warning'>Access denied.</span>"
else if (istype(W, /obj/item/weapon/reagent_containers/glass))
if(src.locked)
user << "<span class='notice'>You cannot insert a beaker because the panel is locked.</span>"
return
if(!isnull(src.reagent_glass))
user << "<span class='notice'>There is already a beaker loaded.</span>"
return
user.drop_item()
W.loc = src
src.reagent_glass = W
user << "<span class='notice'>You insert [W].</span>"
src.updateUsrDialog()
return
else
..()
if (health < maxhealth && !istype(W, /obj/item/weapon/screwdriver) && W.force)
step_to(src, (get_step_away(src,user)))
/obj/machinery/bot/medbot/Emag(mob/user as mob)
..()
if(open && !locked)
if(user) user << "<span class='warning'>You short out [src]'s reagent synthesis circuits.</span>"
spawn(0)
for(var/mob/O in hearers(src, null))
O.show_message("\red <B>[src] buzzes oddly!</B>", 1)
flick("medibot_spark", src)
src.patient = null
if(user) src.oldpatient = user
src.currently_healing = 0
src.last_found = world.time
src.anchored = 0
src.emagged = 2
src.on = 1
src.icon_state = "medibot[src.on]"
/obj/machinery/bot/medbot/process()
set background = 1
if(!src.on)
src.stunned = 0
return
if(src.stunned)
src.icon_state = "medibota"
src.stunned--
src.oldpatient = src.patient
src.patient = null
src.currently_healing = 0
if(src.stunned <= 0)
src.icon_state = "medibot[src.on]"
src.stunned = 0
return
if(src.frustration > 8)
src.oldpatient = src.patient
src.patient = null
src.currently_healing = 0
src.last_found = world.time
src.path = new()
if(!src.patient)
if(!src.shut_up && prob(1))
var/message = pick("Radar, put a mask on!","There's always a catch, and it's the best there is.","I knew it, I should've been a plastic surgeon.","What kind of medbay is this? Everyone's dropping like dead flies.","Delicious!")
src.speak(message)
for (var/mob/living/carbon/C in view(7,src)) //Time to find a patient!
if ((C.stat == 2) || !istype(C, /mob/living/carbon/human))
continue
if ((C == src.oldpatient) && (world.time < src.last_found + 100))
continue
if(src.assess_patient(C))
src.patient = C
src.oldpatient = C
src.last_found = world.time
if((src.last_newpatient_speak + 300) < world.time) //Don't spam these messages!
var/message = pick("Hey, [C.name]! Hold on, I'm coming.","Wait [C.name]! I want to help!","[C.name], you appear to be injured!")
src.speak(message)
src.visible_message("<b>[src]</b> points at [C.name]!")
src.last_newpatient_speak = world.time
break
else
continue
if(src.patient && Adjacent(patient))
if(!src.currently_healing)
src.currently_healing = 1
src.frustration = 0
src.medicate_patient(src.patient)
return
else if(src.patient && (src.path.len) && (get_dist(src.patient,src.path[src.path.len]) > 2))
src.path = new()
src.currently_healing = 0
src.last_found = world.time
if(src.patient && src.path.len == 0 && (get_dist(src,src.patient) > 1))
spawn(0)
src.path = AStar(src.loc, get_turf(src.patient), /turf/proc/CardinalTurfsWithAccess, /turf/proc/Distance, 0, 30,id=botcard)
if (!path) path = list()
if(src.path.len == 0)
src.oldpatient = src.patient
src.patient = null
src.currently_healing = 0
src.last_found = world.time
return
if(src.path.len > 0 && src.patient)
step_to(src, src.path[1])
src.path -= src.path[1]
spawn(3)
if(src.path.len)
step_to(src, src.path[1])
src.path -= src.path[1]
if(src.path.len > 8 && src.patient)
src.frustration++
return
/obj/machinery/bot/medbot/proc/assess_patient(mob/living/carbon/C as mob)
//Time to see if they need medical help!
if(C.stat == 2)
return 0 //welp too late for them!
if(C.suiciding)
return 0 //Kevorkian school of robotic medical assistants.
if(src.emagged == 2) //Everyone needs our medicine. (Our medicine is toxins)
return 1
//If they're injured, we're using a beaker, and don't have one of our WONDERCHEMS.
if((src.reagent_glass) && (src.use_beaker) && ((C.getBruteLoss() >= heal_threshold) || (C.getToxLoss() >= heal_threshold) || (C.getToxLoss() >= heal_threshold) || (C.getOxyLoss() >= (heal_threshold + 15))))
for(var/datum/reagent/R in src.reagent_glass.reagents.reagent_list)
if(!C.reagents.has_reagent(R))
return 1
continue
//They're injured enough for it!
if((C.getBruteLoss() >= heal_threshold) && (!C.reagents.has_reagent(src.treatment_brute)))
return 1 //If they're already medicated don't bother!
if((C.getOxyLoss() >= (15 + heal_threshold)) && (!C.reagents.has_reagent(src.treatment_oxy)))
return 1
if((C.getFireLoss() >= heal_threshold) && (!C.reagents.has_reagent(src.treatment_fire)))
return 1
if((C.getToxLoss() >= heal_threshold) && (!C.reagents.has_reagent(src.treatment_tox)))
return 1
for(var/datum/disease/D in C.viruses)
if((D.stage > 1) || (D.spread_type == AIRBORNE))
if (!C.reagents.has_reagent(src.treatment_virus))
return 1 //STOP DISEASE FOREVER
return 0
/obj/machinery/bot/medbot/proc/medicate_patient(mob/living/carbon/C as mob)
if(!src.on)
return
if(!istype(C))
src.oldpatient = src.patient
src.patient = null
src.currently_healing = 0
src.last_found = world.time
return
if(C.stat == 2)
var/death_message = pick("No! NO!","Live, damnit! LIVE!","I...I've never lost a patient before. Not today, I mean.")
src.speak(death_message)
src.oldpatient = src.patient
src.patient = null
src.currently_healing = 0
src.last_found = world.time
return
var/reagent_id = null
//Use whatever is inside the loaded beaker. If there is one.
if((src.use_beaker) && (src.reagent_glass) && (src.reagent_glass.reagents.total_volume))
reagent_id = "internal_beaker"
if(src.emagged == 2) //Emagged! Time to poison everybody.
reagent_id = "toxin"
var/virus = 0
for(var/datum/disease/D in C.viruses)
virus = 1
if (!reagent_id && (virus))
if(!C.reagents.has_reagent(src.treatment_virus))
reagent_id = src.treatment_virus
if (!reagent_id && (C.getBruteLoss() >= heal_threshold))
if(!C.reagents.has_reagent(src.treatment_brute))
reagent_id = src.treatment_brute
if (!reagent_id && (C.getOxyLoss() >= (15 + heal_threshold)))
if(!C.reagents.has_reagent(src.treatment_oxy))
reagent_id = src.treatment_oxy
if (!reagent_id && (C.getFireLoss() >= heal_threshold))
if(!C.reagents.has_reagent(src.treatment_fire))
reagent_id = src.treatment_fire
if (!reagent_id && (C.getToxLoss() >= heal_threshold))
if(!C.reagents.has_reagent(src.treatment_tox))
reagent_id = src.treatment_tox
if(!reagent_id) //If they don't need any of that they're probably cured!
src.oldpatient = src.patient
src.patient = null
src.currently_healing = 0
src.last_found = world.time
var/message = pick("All patched up!","An apple a day keeps me away.","Feel better soon!")
src.speak(message)
return
else
src.icon_state = "medibots"
visible_message("\red <B>[src] is trying to inject [src.patient]!</B>")
spawn(30)
if ((get_dist(src, src.patient) <= 1) && (src.on))
if((reagent_id == "internal_beaker") && (src.reagent_glass) && (src.reagent_glass.reagents.total_volume))
src.reagent_glass.reagents.trans_to(src.patient,src.injection_amount) //Inject from beaker instead.
src.reagent_glass.reagents.reaction(src.patient, 2)
else
src.patient.reagents.add_reagent(reagent_id,src.injection_amount)
visible_message("\red <B>[src] injects [src.patient] with the syringe!</B>")
if(declare_treatment)
var/area/location = get_area(src)
broadcast_medical_hud_message("[src.name] is treating <b>[C]</b> in <b>[location]</b>", src)
src.icon_state = "medibot[src.on]"
src.currently_healing = 0
return
// src.speak(reagent_id)
reagent_id = null
return
/obj/machinery/bot/medbot/proc/speak(var/message)
if((!src.on) || (!message))
return
visible_message("[src] beeps, \"[message]\"")
return
/obj/machinery/bot/medbot/bullet_act(var/obj/item/projectile/Proj)
if(Proj.taser_effect)
src.stunned = min(stunned+10,20)
..()
/obj/machinery/bot/medbot/explode()
src.on = 0
visible_message("\red <B>[src] blows apart!</B>", 1)
var/turf/Tsec = get_turf(src)
new /obj/item/weapon/storage/firstaid(Tsec)
new /obj/item/device/assembly/prox_sensor(Tsec)
new /obj/item/device/healthanalyzer(Tsec)
if(src.reagent_glass)
src.reagent_glass.loc = Tsec
src.reagent_glass = null
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
/obj/machinery/bot/medbot/Bump(M as mob|obj) //Leave no door unopened!
if ((istype(M, /obj/machinery/door)) && (!isnull(src.botcard)))
var/obj/machinery/door/D = M
if (!istype(D, /obj/machinery/door/firedoor) && D.check_access(src.botcard) && !istype(D,/obj/machinery/door/blast))
D.open()
src.frustration = 0
else if ((istype(M, /mob/living/)) && (!src.anchored))
src.loc = M:loc
src.frustration = 0
return
/* terrible
/obj/machinery/bot/medbot/Bumped(atom/movable/M as mob|obj)
spawn(0)
if (M)
var/turf/T = get_turf(src)
M:loc = T
*/
/*
* Pathfinding procs, allow the medibot to path through doors it has access to.
*/
//Pretty ugh
/*
/turf/proc/AdjacentTurfsAllowMedAccess()
var/L[] = new()
for(var/turf/t in oview(src,1))
if(!t.density)
if(!LinkBlocked(src, t) && !TurfBlockedNonWindowNonDoor(t,get_access("Medical Doctor")))
L.Add(t)
return L
//It isn't blocked if we can open it, man.
/proc/TurfBlockedNonWindowNonDoor(turf/loc, var/list/access)
for(var/obj/O in loc)
if(O.density && !istype(O, /obj/structure/window) && !istype(O, /obj/machinery/door))
return 1
if (O.density && (istype(O, /obj/machinery/door)) && (access.len))
var/obj/machinery/door/D = O
for(var/req in D.req_access)
if(!(req in access)) //doesn't have this access
return 1
return 0
*/
/*
* Medbot Assembly -- Can be made out of all three medkits.
*/
/obj/item/weapon/storage/firstaid/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
//Making a medibot!
if(src.contents.len >= 1)
user << "<span class='notice'>You need to empty [src] out first.</span>"
return
var/obj/item/weapon/firstaid_arm_assembly/A = new /obj/item/weapon/firstaid_arm_assembly
if(istype(src,/obj/item/weapon/storage/firstaid/fire))
A.skin = "ointment"
else if(istype(src,/obj/item/weapon/storage/firstaid/toxin))
A.skin = "tox"
else if(istype(src,/obj/item/weapon/storage/firstaid/o2))
A.skin = "o2"
del(S)
user.put_in_hands(A)
user << "<span class='notice'>You add the robot arm to the first aid kit.</span>"
user.drop_from_inventory(src)
del(src)
/obj/item/weapon/firstaid_arm_assembly/attackby(obj/item/weapon/W as obj, mob/user as mob)
..()
if(istype(W, /obj/item/weapon/pen))
var/t = sanitizeSafe(input(user, "Enter new robot name", src.name, src.created_name), MAX_NAME_LEN)
if (!t)
return
if (!in_range(src, usr) && src.loc != usr)
return
src.created_name = t
else
switch(build_step)
if(0)
if(istype(W, /obj/item/device/healthanalyzer))
user.drop_item()
del(W)
src.build_step++
user << "<span class='notice'>You add the health sensor to [src].</span>"
src.name = "First aid/robot arm/health analyzer assembly"
src.overlays += image('icons/obj/aibots.dmi', "na_scanner")
if(1)
if(isprox(W))
user.drop_item()
del(W)
src.build_step++
user << "<span class='notice'>You complete the Medibot! Beep boop.</span>"
var/turf/T = get_turf(src)
var/obj/machinery/bot/medbot/S = new /obj/machinery/bot/medbot(T)
S.skin = src.skin
S.name = src.created_name
user.drop_from_inventory(src)
del(src)

View File

@@ -1,924 +0,0 @@
/obj/machinery/bot/secbot
name = "Securitron"
desc = "A little security robot. He looks less than thrilled."
icon = 'icons/obj/aibots.dmi'
icon_state = "secbot0"
layer = 5.0
density = 0
anchored = 0
health = 25
maxhealth = 25
fire_dam_coeff = 0.7
brute_dam_coeff = 0.5
req_one_access = list(access_security, access_forensics_lockers)
var/mob/target
var/oldtarget_name
var/threatlevel = 0
var/target_lastloc //Loc of target when arrested.
var/last_found //There's a delay
var/frustration = 0
var/idcheck = 0 //If false, all station IDs are authorized for weapons.
var/check_records = 0 //Does it check security records?
var/check_arrest = 1 //Does it check arrest status?
var/arrest_type = 0 //If true, don't handcuff
var/declare_arrests = 0 //When making an arrest, should it notify everyone wearing sechuds?
var/has_laser = 0
var/next_harm_time = 0
var/lastfired = 0
var/shot_delay = 3 //.3 seconds between shots
var/lasercolor = ""
var/projectile = null//Holder for projectile type, to avoid so many else if chains
var/disabled = 0//A holder for if it needs to be disabled, if true it will not seach for targets, shoot at targets, or move, currently only used for lasertag
var/mode = 0
#define SECBOT_IDLE 0 // idle
#define SECBOT_HUNT 1 // found target, hunting
#define SECBOT_PREP_ARREST 2 // at target, preparing to arrest
#define SECBOT_ARREST 3 // arresting target
#define SECBOT_START_PATROL 4 // start patrol
#define SECBOT_PATROL 5 // patrolling
#define SECBOT_SUMMON 6 // summoned by PDA
var/auto_patrol = 0 // set to make bot automatically patrol
var/beacon_freq = 1445 // navigation beacon frequency
var/control_freq = AI_FREQ // bot control frequency
var/turf/patrol_target // this is turf to navigate to (location of beacon)
var/new_destination // pending new destination (waiting for beacon response)
var/destination // destination description tag
var/next_destination // the next destination in the patrol route
var/list/path = new // list of path turfs
var/blockcount = 0 //number of times retried a blocked path
var/awaiting_beacon = 0 // count of pticks awaiting a beacon response
var/nearest_beacon // the nearest beacon's tag
var/turf/nearest_beacon_loc // the nearest beacon's location
var/bot_version = "1.3"
var/search_range = 7
var/is_attacking = 0
var/obj/item/weapon/secbot_assembly = /obj/item/weapon/secbot_assembly
var/list/threat_found_sounds = new('sound/voice/bcriminal.ogg', 'sound/voice/bjustice.ogg', 'sound/voice/bfreeze.ogg')
var/list/preparing_arrest_sounds = new('sound/voice/bgod.ogg', 'sound/voice/biamthelaw.ogg', 'sound/voice/bsecureday.ogg', 'sound/voice/bradio.ogg', 'sound/voice/binsult.ogg', 'sound/voice/bcreep.ogg')
/obj/machinery/bot/secbot/beepsky
name = "Officer Beep O'sky"
desc = "It's Officer Beep O'sky! Powered by a potato and a shot of whiskey."
idcheck = 0
auto_patrol = 1
/obj/item/weapon/secbot_assembly
name = "helmet/signaler assembly"
desc = "Some sort of bizarre assembly."
icon = 'icons/obj/aibots.dmi'
icon_state = "helmet_signaler"
item_state = "helmet"
var/build_step = 0
var/created_name = "Securitron" //To preserve the name if it's a unique securitron I guess
/obj/machinery/bot/secbot/New(loc, created_name, created_lasercolor)
..()
if(created_name) name = created_name
if(created_lasercolor) lasercolor = created_lasercolor
update_icon()
spawn(3)
src.botcard = new /obj/item/weapon/card/id(src)
src.botcard.access = list(access_security, access_sec_doors, access_forensics_lockers, access_morgue, access_maint_tunnels, access_court)
if(radio_controller)
radio_controller.add_object(src, control_freq, filter = RADIO_SECBOT)
radio_controller.add_object(src, beacon_freq, filter = RADIO_NAVBEACONS)
if(lasercolor)
shot_delay = 6 //Longer shot delay because JESUS CHRIST
check_arrest = 0
check_records = 0 //Don't actively target people set to arrest
arrest_type = 1 //Don't even try to cuff
req_access = list(access_maint_tunnels)
arrest_type = 1
if((lasercolor == "b") && (name == created_name))//Picks a name if there isn't already a custome one
name = pick("BLUE BALLER","SANIC","BLUE KILLDEATH MURDERBOT")
if((lasercolor == "r") && (name == created_name))
name = pick("RED RAMPAGE","RED ROVER","RED KILLDEATH MURDERBOT")
/obj/machinery/bot/secbot/update_icon()
if(on && is_attacking)
src.icon_state = "secbot-c"
else
src.icon_state = "secbot[src.on]"
/obj/machinery/bot/secbot/turn_on()
..()
update_icon()
src.updateUsrDialog()
/obj/machinery/bot/secbot/turn_off()
..()
src.target = null
src.oldtarget_name = null
src.anchored = 0
src.mode = SECBOT_IDLE
walk_to(src,0)
update_icon()
src.updateUsrDialog()
/obj/machinery/bot/secbot/attack_hand(mob/user as mob)
. = ..()
if(.)
return
usr.set_machine(src)
interact(user)
/obj/machinery/bot/secbot/interact(mob/user as mob)
var/dat
dat += text({"
<TT><B>Automatic Security Unit v[bot_version]</B></TT><BR><BR>
Status: []<BR>
Behaviour controls are [src.locked ? "locked" : "unlocked"]<BR>
Maintenance panel is [src.open ? "opened" : "closed"]"},
"<A href='?src=\ref[src];power=1'>[src.on ? "On" : "Off"]</A>" )
if(!src.locked || issilicon(user))
dat += text({"<BR>
Check for Weapon Authorization: []<BR>
Check Security Records: []<BR>
Check Arrest Status: []<BR>
Operating Mode: []<BR>
Report Arrests: []<BR>
Auto Patrol: []"},
"<A href='?src=\ref[src];operation=idcheck'>[src.idcheck ? "Yes" : "No"]</A>",
"<A href='?src=\ref[src];operation=ignorerec'>[src.check_records ? "Yes" : "No"]</A>",
"<A href='?src=\ref[src];operation=ignorearr'>[src.check_arrest ? "Yes" : "No"]</A>",
"<A href='?src=\ref[src];operation=switchmode'>[src.arrest_type ? "Detain" : "Arrest"]</A>",
"<A href='?src=\ref[src];operation=declarearrests'>[src.declare_arrests ? "Yes" : "No"]</A>",
"<A href='?src=\ref[src];operation=patrol'>[auto_patrol ? "On" : "Off"]</A>" )
user << browse("<HEAD><TITLE>Securitron v[bot_version] controls</TITLE></HEAD>[dat]", "window=autosec")
onclose(user, "autosec")
return
/obj/machinery/bot/secbot/Topic(href, href_list)
if(..())
return
usr.set_machine(src)
src.add_fingerprint(usr)
if(lasercolor && (istype(usr,/mob/living/carbon/human)))
var/mob/living/carbon/human/H = usr
if((lasercolor == "b") && (istype(H.wear_suit, /obj/item/clothing/suit/redtag)))//Opposing team cannot operate it
return
else if((lasercolor == "r") && (istype(H.wear_suit, /obj/item/clothing/suit/bluetag)))
return
if((href_list["power"]) && (src.allowed(usr)))
if(src.on)
turn_off()
else
turn_on()
src.updateUsrDialog()
return
switch(href_list["operation"])
if("idcheck")
src.idcheck = !src.idcheck
if("ignorerec")
src.check_records = !src.check_records
if("ignorearr")
src.check_arrest = !src.check_arrest
if("switchmode")
src.arrest_type = !src.arrest_type
if("patrol")
auto_patrol = !auto_patrol
mode = SECBOT_IDLE
if("declarearrests")
src.declare_arrests = !src.declare_arrests
src.updateUsrDialog()
/obj/machinery/bot/secbot/attackby(obj/item/weapon/W as obj, mob/user as mob)
if(istype(W, /obj/item/weapon/card/id)||istype(W, /obj/item/device/pda))
if(src.allowed(user) && !open && !emagged)
src.locked = !src.locked
user << "<span class='notice'>Controls are now [src.locked ? "locked" : "unlocked"].</span>"
else
if(emagged)
user << "<span class='warning'>ERROR</span>"
if(open)
user << "<span class='warning'>Please close the access panel before locking it.</span>"
else
user << "<span class='notice'>Access denied.</span>"
else
..()
if(!istype(W, /obj/item/weapon/screwdriver) && W.force && !src.target)
src.target = user
if(lasercolor)//To make up for the fact that lasertag bots don't hunt
src.shootAt(user)
src.mode = SECBOT_HUNT
/obj/machinery/bot/secbot/Emag(mob/user as mob)
..()
if(open && !locked)
if(user) user << "<span class='warning'>You short out [src]'s target assessment circuits.</span>"
spawn(0)
for(var/mob/O in hearers(src, null))
O.show_message("\red <B>[src] buzzes oddly!</B>", 1)
src.target = null
if(user) src.oldtarget_name = user.name
src.last_found = world.time
src.anchored = 0
src.emagged = 2
src.on = 1
update_icon()
src.projectile = null
mode = SECBOT_IDLE
/obj/machinery/bot/secbot/process()
set background = 1
if(!src.on)
return
switch(mode)
if(SECBOT_IDLE) // idle
walk_to(src,0)
look_for_perp() // see if any criminals are in range
if(!mode && auto_patrol) // still idle, and set to patrol
mode = SECBOT_START_PATROL // switch to patrol mode
if(SECBOT_HUNT) // hunting for perp
// if can't reach perp for long enough, go idle
if(src.frustration >= 8)
// for(var/mob/O in hearers(src, null))
// O << "<span class='game say'><span class='name'>[src]</span> beeps, \"Backup requested! Suspect has evaded arrest.\""
src.target = null
src.last_found = world.time
src.frustration = 0
src.mode = 0
walk_to(src,0)
if(target) // make sure target exists
// We re-assess human targets, before bashing their head in, in case their credentials change
if(istype(target, /mob/living/carbon/human))
var/threat = src.assess_perp(target, idcheck, check_records, check_arrest)
if(threat < 4)
frustration = 8
return
// The target must remain in view to complete the desire to bash its head in
if(!(target in view(search_range,src)))
frustration++
return
if(!lasercolor && Adjacent(target)) // If right next to perp. Lasertag bots do not arrest anyone, just patrol and shoot and whatnot
if(istype(src.target,/mob/living/carbon))
playsound(src.loc, 'sound/weapons/Egloves.ogg', 50, 1, -1)
is_attacking = 1
update_icon()
spawn(2)
is_attacking = 0
update_icon()
var/mob/living/carbon/M = src.target
var/maxstuns = 4
if(istype(M, /mob/living/carbon/human))
if(M.stuttering < 10 && (!(HULK in M.mutations)))
M.stuttering = 10
M.Stun(10)
M.Weaken(10)
else
M.Weaken(10)
M.stuttering = 10
M.Stun(10)
maxstuns--
if(maxstuns <= 0)
target = null
if(declare_arrests)
var/area/location = get_area(src)
broadcast_security_hud_message("[src.name] is [arrest_type ? "detaining" : "arresting"] level [threatlevel] suspect <b>[target]</b> in <b>[location]</b>", src)
visible_message("\red <B>[src.target] has been stunned by [src]!</B>")
mode = SECBOT_PREP_ARREST
src.anchored = 1
src.target_lastloc = M.loc
return
else if(istype(src.target,/mob/living/simple_animal))
//just harmbaton them until dead
if(world.time > next_harm_time)
next_harm_time = world.time + 15
playsound(src.loc, 'sound/weapons/Egloves.ogg', 50, 1, -1)
visible_message("\red <B>[src] beats [src.target] with the stun baton!</B>")
update_icon()
spawn(2)
is_attacking = 0
update_icon()
var/mob/living/simple_animal/S = src.target
S.AdjustStunned(10)
S.adjustBruteLoss(15)
if(S.stat)
src.frustration = 8
if(preparing_arrest_sounds.len > 0)
playsound(src.loc, pick(preparing_arrest_sounds), 50, 0)
else // not next to perp
var/turf/olddist = get_dist(src, src.target)
walk_to(src, target,1,4)
shootAt(target)
if((get_dist(src, src.target)) >= (olddist))
src.frustration++
else
src.frustration = 0
else
src.frustration = 8
if(SECBOT_PREP_ARREST) // preparing to arrest target
if(src.lasercolor)
mode = SECBOT_IDLE
return
if(!target)
mode = SECBOT_IDLE
src.anchored = 0
return
// see if he got away
if((get_dist(src, src.target) > 1) || ((src.target.loc != src.target_lastloc) && src.target.weakened < 2))
src.anchored = 0
mode = SECBOT_HUNT
return
if(istype(src.target,/mob/living/carbon))
var/mob/living/carbon/C = target
var/wearing_hardsuit
if(istype(C,/mob/living/carbon/human))
var/mob/living/carbon/human/H = C
if(istype(H.back, /obj/item/weapon/rig) && istype(H.gloves,/obj/item/clothing/gloves/rig))
wearing_hardsuit = 1
if(!wearing_hardsuit && !C.handcuffed && !src.arrest_type)
playsound(src.loc, 'sound/weapons/handcuffs.ogg', 30, 1, -2)
mode = SECBOT_ARREST
visible_message("\red <B>[src] is trying to put handcuffs on [src.target]!</B>")
spawn(60)
if(get_dist(src, src.target) <= 1)
/*if(src.target.handcuffed)
return*/
if(istype(src.target,/mob/living/carbon))
C = target
if(!C.handcuffed)
C.handcuffed = new /obj/item/weapon/handcuffs(target)
C.update_inv_handcuffed() //update the handcuffs overlay
mode = SECBOT_IDLE
src.target = null
src.anchored = 0
src.last_found = world.time
src.frustration = 0
if(preparing_arrest_sounds.len > 0)
playsound(src.loc, pick(preparing_arrest_sounds), 50, 0)
// var/arrest_message = pick("Have a secure day!","I AM THE LAW.", "God made tomorrow for the crooks we don't catch today.","You can't outrun a radio.")
// src.speak(arrest_message)
else
mode = SECBOT_IDLE
src.target = null
src.anchored = 0
src.last_found = world.time
src.frustration = 0
if(SECBOT_ARREST) // arresting
if(src.lasercolor)
mode = SECBOT_IDLE
return
if(!target || !istype(target, /mob/living/carbon))
src.anchored = 0
mode = SECBOT_IDLE
return
else
var/mob/living/carbon/C = target
if(!C.handcuffed)
src.anchored = 0
mode = SECBOT_IDLE
return
if(SECBOT_START_PATROL) // start a patrol
if(path.len > 0 && patrol_target) // have a valid path, so just resume
mode = SECBOT_PATROL
return
else if(patrol_target) // has patrol target already
spawn(0)
calc_path() // so just find a route to it
if(path.len == 0)
patrol_target = 0
return
mode = SECBOT_PATROL
else // no patrol target, so need a new one
find_patrol_target()
speak("Engaging patrol mode.")
if(SECBOT_PATROL) // patrol mode
patrol_step()
spawn(5)
if(mode == SECBOT_PATROL)
patrol_step()
if(SECBOT_SUMMON) // summoned to PDA
patrol_step()
spawn(4)
if(mode == SECBOT_SUMMON)
patrol_step()
sleep(4)
patrol_step()
return
// perform a single patrol step
/obj/machinery/bot/secbot/proc/patrol_step()
if(loc == patrol_target) // reached target
at_patrol_target()
return
else if(path.len > 0 && patrol_target) // valid path
var/turf/next = path[1]
if(next == loc)
path -= next
return
if(istype( next, /turf/simulated))
var/moved = step_towards(src, next) // attempt to move
if(moved) // successful move
blockcount = 0
path -= loc
look_for_perp()
if(lasercolor)
sleep(20)
else // failed to move
blockcount++
if(blockcount > 5) // attempt 5 times before recomputing
// find new path excluding blocked turf
spawn(2)
calc_path(next)
if(path.len == 0)
find_patrol_target()
else
blockcount = 0
return
return
else // not a valid turf
mode = SECBOT_IDLE
return
else // no path, so calculate new one
mode = SECBOT_START_PATROL
// finds a new patrol target
/obj/machinery/bot/secbot/proc/find_patrol_target()
send_status()
if(awaiting_beacon) // awaiting beacon response
awaiting_beacon++
if(awaiting_beacon > 5) // wait 5 secs for beacon response
find_nearest_beacon() // then go to nearest instead
return
if(next_destination)
set_destination(next_destination)
else
find_nearest_beacon()
return
// finds the nearest beacon to self
// signals all beacons matching the patrol code
/obj/machinery/bot/secbot/proc/find_nearest_beacon()
nearest_beacon = null
new_destination = "__nearest__"
post_signal(beacon_freq, "findbeacon", "patrol")
awaiting_beacon = 1
spawn(10)
awaiting_beacon = 0
if(nearest_beacon)
set_destination(nearest_beacon)
else
auto_patrol = 0
mode = SECBOT_IDLE
speak("Disengaging patrol mode.")
send_status()
/obj/machinery/bot/secbot/proc/at_patrol_target()
find_patrol_target()
return
// sets the current destination
// signals all beacons matching the patrol code
// beacons will return a signal giving their locations
/obj/machinery/bot/secbot/proc/set_destination(var/new_dest)
new_destination = new_dest
post_signal(beacon_freq, "findbeacon", "patrol")
awaiting_beacon = 1
// receive a radio signal
// used for beacon reception
/obj/machinery/bot/secbot/receive_signal(datum/signal/signal)
//log_admin("DEBUG \[[world.timeofday]\]: /obj/machinery/bot/secbot/receive_signal([signal.debug_print()])")
if(!on)
return
/*
world << "rec signal: [signal.source]"
for(var/x in signal.data)
world << "* [x] = [signal.data[x]]"
*/
var/recv = signal.data["command"]
// process all-bot input
if(recv=="bot_status")
send_status()
// check to see if we are the commanded bot
if(signal.data["active"] == src)
// process control input
switch(recv)
if("stop")
mode = SECBOT_IDLE
auto_patrol = 0
return
if("go")
mode = SECBOT_IDLE
auto_patrol = 1
return
if("summon")
patrol_target = signal.data["target"]
next_destination = destination
destination = null
awaiting_beacon = 0
mode = SECBOT_SUMMON
calc_path()
speak("Responding.")
return
// receive response from beacon
recv = signal.data["beacon"]
var/valid = signal.data["patrol"]
if(!recv || !valid)
return
if(recv == new_destination) // if the recvd beacon location matches the set destination
// the we will navigate there
destination = new_destination
patrol_target = signal.source.loc
next_destination = signal.data["next_patrol"]
awaiting_beacon = 0
// if looking for nearest beacon
else if(new_destination == "__nearest__")
var/dist = get_dist(src,signal.source.loc)
if(nearest_beacon)
// note we ignore the beacon we are located at
if(dist>1 && dist<get_dist(src,nearest_beacon_loc))
nearest_beacon = recv
nearest_beacon_loc = signal.source.loc
return
else
return
else if(dist > 1)
nearest_beacon = recv
nearest_beacon_loc = signal.source.loc
return
// send a radio signal with a single data key/value pair
/obj/machinery/bot/secbot/proc/post_signal(var/freq, var/key, var/value)
post_signal_multiple(freq, list("[key]" = value) )
// send a radio signal with multiple data key/values
/obj/machinery/bot/secbot/proc/post_signal_multiple(var/freq, var/list/keyval)
var/datum/radio_frequency/frequency = radio_controller.return_frequency(freq)
if(!frequency) return
var/datum/signal/signal = new()
signal.source = src
signal.transmission_method = 1
//for(var/key in keyval)
// signal.data[key] = keyval[key]
signal.data = keyval
//world << "sent [key],[keyval[key]] on [freq]"
if(signal.data["findbeacon"])
frequency.post_signal(src, signal, filter = RADIO_NAVBEACONS)
else if(signal.data["type"] == "secbot")
frequency.post_signal(src, signal, filter = RADIO_SECBOT)
else
frequency.post_signal(src, signal)
// signals bot status etc. to controller
/obj/machinery/bot/secbot/proc/send_status()
var/list/kv = list(
"type" = "secbot",
"name" = name,
"loca" = loc.loc, // area
"mode" = mode
)
post_signal_multiple(control_freq, kv)
// calculates a path to the current destination
// given an optional turf to avoid
/obj/machinery/bot/secbot/proc/calc_path(var/turf/avoid = null)
src.path = AStar(src.loc, patrol_target, /turf/proc/CardinalTurfsWithAccess, /turf/proc/Distance, 0, 120, id=botcard, exclude=avoid)
if(!path) path = list()
// look for a criminal in view of the bot
/obj/machinery/bot/secbot/proc/look_for_perp()
if(src.disabled)
return
src.anchored = 0
for(var/mob/living/M in view(search_range,src)) //Let's find us a criminal
if(M.invisibility >= INVISIBILITY_LEVEL_ONE) // Cannot see him. see_invisible is a mob-var
continue
if(istype(M, /mob/living/carbon))
var/mob/living/carbon/C = M
if(C.stat || C.handcuffed)
continue
if(src.lasercolor && C.lying)
continue//Does not shoot at people lying down when in lasertag mode, because it's just annoying, and they can fire once they get up.
if(C.name == src.oldtarget_name && world.time < src.last_found + 100)
continue
if(istype(C, /mob/living/carbon/human))
src.threatlevel = src.assess_perp(C, idcheck, check_records, check_arrest)
else if(istype(M, /mob/living/simple_animal/hostile))
if(M.stat == DEAD)
continue
else
src.threatlevel = 4
if(!src.threatlevel)
continue
else if(M.stat != DEAD && src.threatlevel >= 4)
src.target = M
src.oldtarget_name = M.name
src.speak("Level [src.threatlevel] infraction alert!")
if(!src.lasercolor && threat_found_sounds.len > 0)
playsound(src.loc, pick(threat_found_sounds), 50, 0)
src.visible_message("<b>[src]</b> points at [M.name]!")
mode = SECBOT_HUNT
spawn(0)
process() // ensure bot quickly responds to a perp
break
else
continue
/obj/machinery/bot/secbot/on_assess_perp(mob/living/carbon/human/perp)
if(lasercolor)
return laser_check(perp, lasercolor)
var/threat = 0
threat -= laser_check(perp, "b")
threat -= laser_check(perp, "r")
return threat
/obj/machinery/bot/secbot/proc/laser_check(mob/living/carbon/human/perp, var/lasercolor)
var/target_suit
var/target_weapon
var/threat = 0
//Lasertag turrets target the opposing team, how great is that? -Sieve
switch(lasercolor)
if("b")
target_suit = /obj/item/clothing/suit/redtag
target_weapon = /obj/item/weapon/gun/energy/lasertag/red
if("r")
target_suit = /obj/item/clothing/suit/bluetag
target_weapon = /obj/item/weapon/gun/energy/lasertag/blue
if((istype(perp.r_hand, target_weapon)) || (istype(perp.l_hand, target_weapon)))
threat += 4
if(istype(perp, /mob/living/carbon/human))
if(istype(perp.wear_suit, target_suit))
threat += 4
if(istype(perp.belt, target_weapon))
threat += 2
return threat
/obj/machinery/bot/secbot/is_assess_emagged()
return emagged == 2
/obj/machinery/bot/secbot/Bump(M as mob|obj) //Leave no door unopened!
if((istype(M, /obj/machinery/door)) && !isnull(src.botcard))
var/obj/machinery/door/D = M
if(!istype(D, /obj/machinery/door/firedoor) && D.check_access(src.botcard) && !istype(D,/obj/machinery/door/blast))
D.open()
src.frustration = 0
else if(!src.anchored)
if((istype(M, /mob/living/)))
var/mob/living/O = M
src.loc = O.loc
src.frustration = 0
else if(istype(M, /obj/machinery/bot))
var/obj/machinery/bot/B = M
if(B.dir != src.dir) // Avoids issues if two bots are currently patrolling in the same direction
src.loc = B.loc
src.frustration = 0
return
/obj/machinery/bot/secbot/proc/speak(var/message)
for(var/mob/O in hearers(src, null))
O.show_message("<span class='game say'><span class='name'>[src]</span> beeps, \"[message]\"",2)
return
/obj/machinery/bot/secbot/explode()
walk_to(src,0)
src.visible_message("\red <B>[src] blows apart!</B>", 1)
var/turf/Tsec = get_turf(src)
var/obj/item/weapon/secbot_assembly/Sa = new secbot_assembly(Tsec)
Sa.build_step = 1
Sa.overlays += image('icons/obj/aibots.dmi', "hs_hole")
Sa.created_name = src.name
new /obj/item/device/assembly/prox_sensor(Tsec)
new /obj/item/weapon/melee/baton(Tsec)
on_explosion()
var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread
s.set_up(3, 1, src)
s.start()
new /obj/effect/decal/cleanable/blood/oil(src.loc)
del(src)
/obj/machinery/bot/secbot/proc/on_explosion(var/turf/Tsec)
new /obj/item/weapon/melee/baton(Tsec)
if(prob(50))
new /obj/item/robot_parts/l_arm(Tsec)
//Secbot Construction
/obj/item/clothing/head/helmet/attackby(var/obj/item/device/assembly/signaler/S, mob/user as mob)
..()
if(!issignaler(S))
..()
return
if(src.type != /obj/item/clothing/head/helmet) //Eh, but we don't want people making secbots out of space helmets.
return
if(S.secured)
del(S)
var/obj/item/weapon/secbot_assembly/A = new /obj/item/weapon/secbot_assembly
user.put_in_hands(A)
user << "You add the signaler to the helmet."
user.drop_from_inventory(src)
del(src)
else
return
/obj/item/weapon/secbot_assembly/attackby(obj/item/weapon/W as obj, mob/user as mob)
..()
if((istype(W, /obj/item/weapon/weldingtool)) && (!src.build_step))
var/obj/item/weapon/weldingtool/WT = W
if(WT.remove_fuel(0,user))
src.build_step++
src.overlays += image('icons/obj/aibots.dmi', "hs_hole")
user << "You weld a hole in [src]!"
else if(isprox(W) && (src.build_step == 1))
user.drop_item()
src.build_step++
user << "You add the prox sensor to [src]!"
src.overlays += image('icons/obj/aibots.dmi', "hs_eye")
src.name = "helmet/signaler/prox sensor assembly"
del(W)
else if(((istype(W, /obj/item/robot_parts/l_arm)) || (istype(W, /obj/item/robot_parts/r_arm))) && (src.build_step == 2))
user.drop_item()
src.build_step++
user << "You add the robot arm to [src]!"
src.name = "helmet/signaler/prox sensor/robot arm assembly"
src.overlays += image('icons/obj/aibots.dmi', "hs_arm")
del(W)
else if((istype(W, /obj/item/weapon/melee/baton)) && (src.build_step >= 3))
user.drop_item()
src.build_step++
user << "You complete the Securitron! Beep boop."
var/obj/machinery/bot/secbot/S = new /obj/machinery/bot/secbot
S.loc = get_turf(src)
S.name = src.created_name
del(W)
del(src)
else if(istype(W, /obj/item/weapon/pen))
var/t = sanitizeSafe(input(user, "Enter new robot name", src.name, src.created_name), MAX_NAME_LEN)
if(!t)
return
if(!in_range(src, usr) && src.loc != usr)
return
src.created_name = t
/obj/machinery/bot/secbot/proc/shootAt(var/mob/target)
if(!has_laser || (lastfired && world.time - lastfired < shot_delay))
return
lastfired = world.time
var/turf/T = loc
var/atom/U = (istype(target, /atom/movable) ? target.loc : target)
if((!( U ) || !( T )))
return
while(!( istype(U, /turf) ))
U = U.loc
if(!( istype(T, /turf) ))
return
if(!projectile)
if(!lasercolor)
if(src.emagged == 2)
projectile = /obj/item/projectile/beam
else
projectile = /obj/item/projectile/beam/stun
else if(lasercolor == "b")
if(src.emagged == 2)
projectile = /obj/item/projectile/beam/lastertag/omni
else
projectile = /obj/item/projectile/beam/lastertag/blue
else if(lasercolor == "r")
if(src.emagged == 2)
projectile = /obj/item/projectile/beam/lastertag/omni
else
projectile = /obj/item/projectile/beam/lastertag/red
if(!( istype(U, /turf) ))
return
playsound(src.loc, src.emagged == 2 ? 'sound/weapons/Laser.ogg' : 'sound/weapons/Taser.ogg', 50, 1)
var/obj/item/projectile/A = new projectile (loc)
A.current = U
A.yo = U.y - T.y
A.xo = U.x - T.x
spawn( 0 )
A.process()
return
return
/obj/machinery/bot/secbot/emp_act(severity)
if(severity==2 && prob(70))
..(severity-1)
else
var/obj/effect/overlay/pulse2 = new/obj/effect/overlay ( src.loc )
pulse2.icon = 'icons/effects/effects.dmi'
pulse2.icon_state = "empdisable"
pulse2.name = "emp sparks"
pulse2.anchored = 1
pulse2.set_dir(pick(cardinal))
spawn(10)
pulse2.delete()
var/list/mob/living/carbon/targets = new
for(var/mob/living/carbon/C in view(12,src))
if(C.stat==2)
continue
targets += C
if(targets.len)
if(prob(50))
var/mob/toshoot = pick(targets)
if(toshoot)
targets-=toshoot
if(prob(50) && emagged < 2)
emagged = 2
shootAt(toshoot)
emagged = 0
else
shootAt(toshoot)
else if(prob(50))
if(targets.len)
var/mob/toarrest = pick(targets)
if(toarrest)
src.target = toarrest
src.mode = SECBOT_HUNT

View File

@@ -124,7 +124,7 @@
dat += "<a href='?src=\ref[src];screen=1'>Back</a>"
dat += "<br><b>Medical Robots:</b>"
var/bdat = null
for(var/obj/machinery/bot/medbot/M in world)
for(var/mob/living/bot/medbot/M in world)
if(M.z != src.z) continue //only find medibots on the same z-level as the computer
var/turf/bl = get_turf(M)

View File

@@ -136,7 +136,7 @@
dat += "<a href='?src=\ref[src];screen=1'>Back</a>"
dat += "<br><b>Medical Robots:</b>"
var/bdat = null
for(var/obj/machinery/bot/medbot/M in world)
for(var/mob/living/bot/medbot/M in world)
if(M.z != computer.z) continue //only find medibots on the same z-level as the computer
var/turf/bl = get_turf(M)

View File

@@ -103,8 +103,8 @@
bumpopen(M)
return
if(istype(AM, /obj/machinery/bot))
var/obj/machinery/bot/bot = AM
if(istype(AM, /mob/living/bot))
var/mob/living/bot/bot = AM
if(src.check_access(bot.botcard))
if(density)
open()

View File

@@ -58,7 +58,7 @@
/obj/machinery/door/window/Bumped(atom/movable/AM as mob|obj)
if (!( ismob(AM) ))
var/obj/machinery/bot/bot = AM
var/mob/living/bot/bot = AM
if(istype(bot))
if(density && src.check_access(bot.botcard))
open()

View File

@@ -333,51 +333,3 @@ Class Procs:
I.loc = loc
del(src)
return 1
/obj/machinery/proc/on_assess_perp(mob/living/carbon/human/perp)
return 0
/obj/machinery/proc/is_assess_emagged()
return emagged
/obj/machinery/proc/assess_perp(mob/living/carbon/human/perp, var/auth_weapons, var/check_records, var/check_arrest)
var/threatcount = 0 //the integer returned
if(is_assess_emagged())
return 10 //if emagged, always return 10.
threatcount += on_assess_perp(perp)
if(threatcount >= 10)
return threatcount
//Agent cards lower threatlevel.
var/obj/item/weapon/card/id/id = GetIdCard(perp)
if(id && istype(id, /obj/item/weapon/card/id/syndicate))
threatcount -= 2
if(auth_weapons && !src.allowed(perp))
if(istype(perp.l_hand, /obj/item/weapon/gun) || istype(perp.l_hand, /obj/item/weapon/melee))
threatcount += 4
if(istype(perp.r_hand, /obj/item/weapon/gun) || istype(perp.r_hand, /obj/item/weapon/melee))
threatcount += 4
if(istype(perp.belt, /obj/item/weapon/gun) || istype(perp.belt, /obj/item/weapon/melee))
threatcount += 2
if(perp.species.name != "Human") //beepsky so racist.
threatcount += 2
if(check_records || check_arrest)
var/perpname = perp.name
if(id)
perpname = id.registered_name
var/datum/data/record/R = find_security_record("name", perpname)
if(check_records && !R)
threatcount += 4
if(check_arrest && R && (R.fields["criminal"] == "*Arrest*"))
threatcount += 4
return threatcount

View File

@@ -494,7 +494,7 @@
return check_anomalies ? TURRET_PRIORITY_TARGET : TURRET_NOT_TARGET
if(ishuman(L)) //if the target is a human, analyze threat level
if(assess_perp(L, check_weapons, check_records, check_arrest) < 4)
if(assess_perp(L) < 4)
return TURRET_NOT_TARGET //if threat level < 4, keep going
if(L.lying) //if the perp is lying down, it's still a target but a less-important target
@@ -502,6 +502,45 @@
return TURRET_PRIORITY_TARGET //if the perp has passed all previous tests, congrats, it is now a "shoot-me!" nominee
/obj/machinery/porta_turret/proc/assess_perp(var/mob/living/carbon/human/H)
if(!H || !istype(H))
return
if(emagged)
return 10
var/threatcount = 0
var/obj/item/weapon/card/id/id = GetIdCard(H) //Agent cards lower threatlevel.
if(id && istype(id, /obj/item/weapon/card/id/syndicate))
threatcount -= 2
if(check_weapons && !allowed(H))
if(istype(H.l_hand, /obj/item/weapon/gun) || istype(H.l_hand, /obj/item/weapon/melee))
threatcount += 4
if(istype(H.r_hand, /obj/item/weapon/gun) || istype(H.r_hand, /obj/item/weapon/melee))
threatcount += 4
if(istype(H.belt, /obj/item/weapon/gun) || istype(H.belt, /obj/item/weapon/melee))
threatcount += 2
if(H.species.name != "Human")
threatcount += 2
if(check_records || check_arrest)
var/perpname = H.name
if(id)
perpname = id.registered_name
var/datum/data/record/R = find_security_record("name", perpname)
if(check_records && !R)
threatcount += 4
if(check_arrest && R && (R.fields["criminal"] == "*Arrest*"))
threatcount += 4
return threatcount
/obj/machinery/porta_turret/proc/tryToShootAt(var/list/mob/living/targets)
if(targets.len && last_target && (last_target in targets) && target(last_target))
return 1
@@ -549,12 +588,14 @@
update_icon()
/*
/obj/machinery/porta_turret/on_assess_perp(mob/living/carbon/human/perp)
if((check_access || attacked) && !allowed(perp))
//if the turret has been attacked or is angry, target all non-authorized personnel, see req_access
return 10
return ..()
*/
/obj/machinery/porta_turret/proc/target(var/mob/living/target)

View File

@@ -1,6 +1,5 @@
/obj/effect/decal/cleanable
var/list/random_icon_states = list()
var/targeted_by = null // Used so cleanbots can't claim a mess.
/obj/effect/decal/cleanable/New()
if (random_icon_states && length(src.random_icon_states) > 0)

View File

@@ -331,7 +331,7 @@
beepskyData["botstatus"] = list("loca" = null, "mode" = -1)
var/botsCount=0
if(SC.botlist && SC.botlist.len)
for(var/obj/machinery/bot/B in SC.botlist)
for(var/mob/living/bot/B in SC.botlist)
botsCount++
if(B.loc)
botsData[++botsData.len] = list("Name" = sanitize(B.name), "Location" = sanitize(B.loc.loc.name), "ref" = "\ref[B]")
@@ -465,7 +465,7 @@
BucketData[++BucketData.len] = list("x" = 0, "y" = 0, dir=null, status = null)
var/CbotData[0]
for(var/obj/machinery/bot/cleanbot/B in world)
for(var/mob/living/bot/cleanbot/B in world)
var/turf/bl = get_turf(B)
if(bl)
if(bl.z != cl.z)

View File

@@ -37,7 +37,7 @@
/obj/item/radio/integrated/beepsky
var/list/botlist = null // list of bots
var/obj/machinery/bot/secbot/active // the active bot; if null, show bot list
var/mob/living/bot/secbot/active // the active bot; if null, show bot list
var/list/botstatus // the status signal sent by the bot
var/control_freq = AI_FREQ

View File

@@ -128,12 +128,12 @@
if(istype(W, /obj/item/stack/sheet/metal) && !l_arm && !r_arm && !l_leg && !r_leg && !chest && !head)
var/obj/item/stack/sheet/metal/M = W
if (M.use(1))
var/obj/item/weapon/secbot_assembly/ed209_assembly/B = new /obj/item/weapon/secbot_assembly/ed209_assembly
B.loc = get_turf(src)
//var/obj/item/weapon/secbot_assembly/ed209_assembly/B = new /obj/item/weapon/secbot_assembly/ed209_assembly
//B.loc = get_turf(src)
user << "<span class='notice'>You armed the robot frame.</span>"
if (user.get_inactive_hand()==src)
user.remove_from_mob(src)
user.put_in_inactive_hand(B)
// user.put_in_inactive_hand(B)
del(src)
else
user << "<span class='warning'>You need one sheet of metal to arm the robot frame.</span>"

View File

@@ -97,7 +97,7 @@
/obj/machinery/shieldgen,
/obj/machinery/turretid,
/obj/machinery/vending,
/obj/machinery/bot,
/mob/living/bot,
/obj/machinery/door,
/obj/machinery/telecomms,
/obj/machinery/mecha_part_fabricator,