Files
Aurora.3/code/game/objects/structures/machinery/bots/bots.dm
T
Batrachophreno 4ecb0bc21c Repath obj/machinery to obj/structure/machinery [MDB Ignore] (#22500)
Repaths obj/machinery to obj/structure/machinery. **Note for
reviewers:** the only meaningful changed code exists within
**code/game/objects/structures.dm** and
**code/game/objects/structures/_machinery.dm**, largely concerning
damage procs. With the exception of moving airlock defines to their own
file, ALL OTHER CHANGES ARE STRICTLY PATH CHANGES.

Objects, _categorically_, are largely divided between those you can hold
in your hand/inventory and those you can't. Machinery objects are
already subtypes of Structures behaviorally, this PR just makes their
pathing reflect that, and allows for future work (tool actions, more
health/destruction functionality) to be developed without unnecessary
code duplication.

I have tested this PR by loading up the Horizon and dismantling various
machines and structures with tools, shooting guns of various types
throughout the ship, and detonating a bunch of explosions throughout the
ship.
2026-05-26 19:35:48 +00:00

206 lines
5.9 KiB
Plaintext

// AI (i.e. game AI, not the AI player) controlled bots
/obj/structure/machinery/bot
icon = 'icons/mob/npc/aibots.dmi'
layer = MOB_LAYER
light_range = 3
use_power = POWER_USE_OFF
light_system = MOVABLE_LIGHT
var/obj/item/card/id/botcard // the ID card that the bot "holds"
var/on = 1
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/structure/machinery/bot/Initialize(mapload, d, populate_components, is_internal)
. = ..()
add_to_target_grid()
/obj/structure/machinery/bot/Destroy()
clear_from_target_grid()
return ..()
/obj/structure/machinery/bot/proc/turn_on()
if(stat)
return 0
on = 1
set_light_on(on)
/obj/structure/machinery/bot/proc/turn_off()
on = 0
set_light_on(on)
/obj/structure/machinery/bot/proc/explode()
qdel(src)
/obj/structure/machinery/bot/on_death(damage, damage_flags, damage_type, armor_penetration, obj/weapon)
explode()
/obj/structure/machinery/bot/emag_act(var/remaining_charges, var/user)
if(locked && !emagged)
locked = 0
emagged = 1
to_chat(user, SPAN_WARNING("You short out [src]'s maintenance hatch lock."))
log_and_message_admins("emagged [src]'s maintenance hatch lock")
return 1
if(!locked && open && emagged == 1)
emagged = 2
log_and_message_admins("emagged [src]'s inner circuits")
return 1
/obj/structure/machinery/bot/attackby(obj/item/attacking_item, mob/user)
if(attacking_item.tool_behaviour == TOOL_SCREWDRIVER)
if(!locked)
open = !open
to_chat(user, SPAN_NOTICE("Maintenance panel is now [src.open ? "opened" : "closed"]."))
return TRUE
else if(attacking_item.tool_behaviour == TOOL_WELDER)
if(health < maxhealth)
if(open)
add_health(10)
user.visible_message(SPAN_WARNING("[user] repairs [src]!"),SPAN_NOTICE("You repair [src]!"))
user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN)
else
to_chat(user, SPAN_NOTICE("Unable to repair with the maintenance panel closed."))
else
to_chat(user, SPAN_NOTICE("[src] does not need a repair."))
return TRUE
else
if(attacking_item.force && attacking_item.damtype)
switch(attacking_item.damtype)
if(DAMAGE_BURN)
add_damage(attacking_item.force * fire_dam_coeff)
if(DAMAGE_BRUTE)
add_damage(attacking_item.force * brute_dam_coeff)
user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN)
return ..()
else
return ..()
/obj/structure/machinery/bot/bullet_act(var/obj/projectile/Proj)
if(!(Proj.damage_type == DAMAGE_BRUTE || Proj.damage_type == DAMAGE_BURN))
return BULLET_ACT_BLOCK
. = ..()
/obj/structure/machinery/bot/ex_act(severity)
switch(severity)
if(1)
explode()
if(2)
add_damage(rand(5,10)*fire_dam_coeff)
add_damage(rand(10,20)*brute_dam_coeff)
if(3)
if (prob(50))
add_damage(rand(1,5)*fire_dam_coeff)
add_damage(rand(1,5)*brute_dam_coeff)
/obj/structure/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(GLOB.cardinals))
QDEL_IN(pulse2, 10)
if (on)
turn_off()
addtimer(CALLBACK(src, PROC_REF(post_emp), was_on), severity * 300)
/obj/structure/machinery/bot/proc/post_emp(was_on)
stat &= ~EMPED
if (was_on)
turn_on()
/obj/structure/machinery/bot/attack_ai(mob/user as mob)
if(!ai_can_interact(user))
return
src.attack_hand(user)
/obj/structure/machinery/bot/attack_hand(var/mob/living/carbon/human/user)
if(!istype(user))
return ..()
if(user.species.can_shred(user))
add_damage(rand(15,30) * brute_dam_coeff)
src.visible_message(SPAN_DANGER("[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)
/******************************************************************/
// 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/card/id/ID)
var/L[] = new()
// for(var/turf/simulated/t in oview(src,1))
for(var/d in GLOB.cardinals)
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/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/structure/machinery/door) && !(O.atom_flags & ATOM_FLAG_CHECKS_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/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/structure/machinery/door/D in loc)
if(!D.density) continue
if(istype(D, /obj/structure/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