// AI (i.e. game AI, not the AI player) controlled bots /obj/machinery/bot icon = 'icons/obj/aibots.dmi' layer = MOB_LAYER luminosity = 3 use_power = 0 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/open = 0//Maint panel var/locked = 1 //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 on = 1 SetLuminosity(initial(luminosity)) return 1 /obj/machinery/bot/proc/turn_off() on = 0 SetLuminosity(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(locked) locked = 0 emagged = 1 user << "You short out [src]'s maintenance hatch lock." log_and_message_admins("emagged [src]'s maintenance hatch lock") if(!locked && open) emagged = 2 log_and_message_admins("emagged [src]'s inner circuits") /obj/machinery/bot/examine(mob/user) ..(user) if (src.health < maxhealth) if (src.health > maxhealth/3) user << "[src]'s parts look loose." else user << "[src]'s parts look very loose!" return /obj/machinery/bot/attackby(obj/item/weapon/W as obj, mob/user as mob) if(istype(W, /obj/item/weapon/screwdriver)) if(!locked) open = !open user << "Maintenance panel is now [src.open ? "opened" : "closed"]." else if(istype(W, /obj/item/weapon/weldingtool)) if(health < maxhealth) if(open) health = min(maxhealth, health+10) user.visible_message("\red [user] repairs [src]!","\blue You repair [src]!") else user << "Unable to repair with the maintenance panel closed." else user << "[src] does not need a repair." else if (istype(W, /obj/item/weapon/card/emag) && emagged < 2) Emag(user) else if(hasvar(W,"force") && hasvar(W,"damtype")) switch(W.damtype) if("fire") src.health -= W.force * fire_dam_coeff if("brute") src.health -= W.force * brute_dam_coeff ..() healthcheck() else ..() /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 = 'icons/effects/effects.dmi' pulse2.icon_state = "empdisable" pulse2.name = "emp sparks" pulse2.anchored = 1 pulse2.set_dir(pick(cardinal)) spawn(10) pulse2.delete() if (on) turn_off() spawn(severity*300) stat &= ~EMPED if (was_on) turn_on() /obj/machinery/bot/attack_ai(mob/user as mob) src.attack_hand(user) /obj/machinery/bot/attack_hand(var/mob/living/carbon/human/user) if(!istype(user)) return ..() if(user.species.can_shred(user)) src.health -= rand(15,30)*brute_dam_coeff src.visible_message("\red [user] has slashed [src]!") playsound(src.loc, 'sound/weapons/slice.ogg', 25, 1, -1) if(prob(10)) new /obj/effect/decal/cleanable/blood/oil(src.loc) healthcheck() /******************************************************************/ // 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