mirror of
https://github.com/CHOMPStation2/CHOMPStation2.git
synced 2025-12-10 10:12:45 +00:00
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:
@@ -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
|
||||
@@ -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)
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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>"
|
||||
|
||||
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user