// AI (i.e. game AI, not the AI player) controlled bots
/obj/machinery/bot
icon = 'aibots.dmi'
layer = MOB_LAYER
var/obj/item/weapon/card/id/botcard // the ID card that the bot "holds"
var/on = 1
var/health = 0 //do not forget to set health for your bot!
var/maxhealth = 0
var/fire_dam_coeff = 1.0
var/brute_dam_coeff = 1.0
var/emagged = 0 //Urist: Moving that var to the general /bot tree as it's used by most bots
/obj/machinery/bot/proc/turn_on()
if (stat)
return 0
src.on = 1
return 1
/obj/machinery/bot/proc/turn_off()
src.on = 0
/obj/machinery/bot/proc/explode()
del(src)
/obj/machinery/bot/proc/healthcheck()
if (src.health <= 0)
src.explode()
/obj/machinery/bot/proc/Emag(mob/user as mob)
if(!emagged) emagged = 1
/obj/machinery/bot/examine()
set src in view()
..()
if (src.health < maxhealth)
if (src.health > maxhealth/3)
usr << text("\red [src]'s parts look loose.")
else
usr << text("\red [src]'s parts look very loose!")
return
/obj/machinery/bot/attack_alien(var/mob/living/carbon/alien/user as mob)
/* Well, aliums dislike machines and do not want to caress them.
if (user.a_intent == "help")
for(var/mob/O in viewers(src, null))
if ((O.client && !( O.blinded )))
O.show_message(text("\blue [user] caresses [src.name] with its scythe like arm."), 1)
else
*/
src.health -= rand(15,30)*brute_dam_coeff
src.visible_message("\red [user] has slashed [src]!")
playsound(src.loc, 'slice.ogg', 25, 1, -1)
if(prob(10))
new /obj/effect/decal/cleanable/oil(src.loc)
healthcheck()
/obj/machinery/bot/attackby(obj/item/weapon/W as obj, mob/user as mob)
if (istype(W, /obj/item/weapon/screwdriver))
if (src.health < maxhealth)
src.health = min(maxhealth, src.health+25)
user.visible_message(
"\red [user] repairs [src]!",
"\blue You repair [src]!"
)
else
user << "\blue [src] does not need a repair!"
else if (istype(W, /obj/item/weapon/card/emag) && !emagged)
Emag(user)
else
switch(W.damtype)
if("fire")
src.health -= W.force * fire_dam_coeff
if("brute")
src.health -= W.force * brute_dam_coeff
..()
healthcheck()
/obj/machinery/bot/bullet_act(var/obj/item/projectile/Proj)
health -= Proj.damage
..()
healthcheck()
/obj/machinery/bot/meteorhit()
src.explode()
return
/obj/machinery/bot/blob_act()
src.health -= rand(20,40)*fire_dam_coeff
healthcheck()
return
/obj/machinery/bot/ex_act(severity)
switch(severity)
if(1.0)
src.explode()
return
if(2.0)
src.health -= rand(5,10)*fire_dam_coeff
src.health -= rand(10,20)*brute_dam_coeff
healthcheck()
return
if(3.0)
if (prob(50))
src.health -= rand(1,5)*fire_dam_coeff
src.health -= rand(1,5)*brute_dam_coeff
healthcheck()
return
return
/obj/machinery/bot/emp_act(severity)
var/was_on = on
stat |= EMPED
var/obj/effect/overlay/pulse2 = new/obj/effect/overlay ( src.loc )
pulse2.icon = 'effects.dmi'
pulse2.icon_state = "empdisable"
pulse2.name = "emp sparks"
pulse2.anchored = 1
pulse2.dir = pick(cardinal)
spawn(10)
del(pulse2)
if (on)
turn_off()
spawn(severity*300)
stat &= ~EMPED
if (was_on)
turn_on()
/obj/machinery/bot/attack_ai(mob/user as mob)
if (src.on)
turn_off()
else
turn_on()
/******************************************************************/
// Navigation procs
// Used for A-star pathfinding
// Returns the surrounding cardinal turfs with open links
// Including through doors openable with the ID
/turf/proc/CardinalTurfsWithAccess(var/obj/item/weapon/card/id/ID)
var/L[] = new()
// for(var/turf/simulated/t in oview(src,1))
for(var/d in cardinal)
var/turf/simulated/T = get_step(src, d)
if(istype(T) && !T.density)
if(!LinkBlockedWithAccess(src, T, ID))
L.Add(T)
return L
// Returns true if a link between A and B is blocked
// Movement through doors allowed if ID has access
/proc/LinkBlockedWithAccess(turf/A, turf/B, obj/item/weapon/card/id/ID)
if(A == null || B == null) return 1
var/adir = get_dir(A,B)
var/rdir = get_dir(B,A)
if((adir & (NORTH|SOUTH)) && (adir & (EAST|WEST))) // diagonal
var/iStep = get_step(A,adir&(NORTH|SOUTH))
if(!LinkBlockedWithAccess(A,iStep, ID) && !LinkBlockedWithAccess(iStep,B,ID))
return 0
var/pStep = get_step(A,adir&(EAST|WEST))
if(!LinkBlockedWithAccess(A,pStep,ID) && !LinkBlockedWithAccess(pStep,B,ID))
return 0
return 1
if(DirBlockedWithAccess(A,adir, ID))
return 1
if(DirBlockedWithAccess(B,rdir, ID))
return 1
for(var/obj/O in B)
if(O.density && !istype(O, /obj/machinery/door) && !(O.flags & ON_BORDER))
return 1
return 0
// Returns true if direction is blocked from loc
// Checks doors against access with given ID
/proc/DirBlockedWithAccess(turf/loc,var/dir,var/obj/item/weapon/card/id/ID)
for(var/obj/structure/window/D in loc)
if(!D.density) continue
if(D.dir == SOUTHWEST) return 1
if(D.dir == dir) return 1
for(var/obj/machinery/door/D in loc)
if(!D.density) continue
if(istype(D, /obj/machinery/door/window))
if( dir & D.dir ) return !D.check_access(ID)
//if((dir & SOUTH) && (D.dir & (EAST|WEST))) return !D.check_access(ID)
//if((dir & EAST ) && (D.dir & (NORTH|SOUTH))) return !D.check_access(ID)
else return !D.check_access(ID) // it's a real, air blocking door
return 0