[MIRROR] Pathfinding circuitry and ID lockable assemblies (#11246)

Co-authored-by: Aura Dusklight <46622484+NovaDusklight@users.noreply.github.com>
Co-authored-by: Kashargul <144968721+Kashargul@users.noreply.github.com>
This commit is contained in:
CHOMPStation2StaffMirrorBot
2025-07-26 12:31:01 -07:00
committed by GitHub
parent 053f149ebc
commit 2e377cdc40
3 changed files with 191 additions and 14 deletions
@@ -15,6 +15,9 @@
var/obj/item/cell/device/battery = null // Internal cell which most circuits need to work.
var/net_power = 0 // Set every tick, to display how much power is being drawn in total.
var/detail_color = COLOR_ASSEMBLY_BLACK
var/locked = FALSE // If true, the assembly cannot be opened with a crowbar
var/obj/item/card/id/locked_by = null // The ID that locked this assembly
var/obj/item/card/id/access_card = null // ID card for door access
/obj/item/electronic_assembly/Initialize(mapload)
@@ -191,6 +194,9 @@
/obj/item/electronic_assembly/update_icon()
if(opened)
icon_state = initial(icon_state) + "-open"
// else if(locked)
// For when I finish the locked assembly sprites.
// icon_state = initial(icon_state) // + "-locked" would be added once sprites are made
else
icon_state = initial(icon_state)
cut_overlays()
@@ -200,19 +206,6 @@
detail_overlay.color = detail_color
add_overlay(detail_overlay)
/obj/item/electronic_assembly/GetAccess()
. = list()
for(var/obj/item/integrated_circuit/part in contents)
. |= part.GetAccess()
/obj/item/electronic_assembly/GetIdCard()
. = list()
for(var/obj/item/integrated_circuit/part in contents)
var/id_card = part.GetIdCard()
if(id_card)
return id_card
/obj/item/electronic_assembly/examine(mob/user)
. = ..()
if(Adjacent(user))
@@ -300,12 +293,46 @@
return TRUE
else if(I.has_tool_quality(TOOL_CROWBAR))
if(locked)
to_chat(user, span_warning("\The [src] is locked! You cannot open it with a crowbar."))
return FALSE
playsound(src, 'sound/items/Crowbar.ogg', 50, 1)
opened = !opened
to_chat(user, span_notice("You [opened ? "opened" : "closed"] \the [src]."))
update_icon()
return TRUE
else if((istype(I, /obj/item/card/id) || istype(I, /obj/item/pda)) && !opened)
var/obj/item/card/id/id_card = null
if(istype(I, /obj/item/card/id))
id_card = I
else
var/obj/item/pda/pda = I
id_card = pda.id
if(!id_card)
to_chat(user, span_warning("You need an ID card to lock this assembly!"))
return FALSE
if(locked)
// Trying to unlock
if(locked_by && id_card.registered_name == locked_by.registered_name)
locked = FALSE
locked_by = null
to_chat(user, span_notice("You unlock \the [src]."))
update_icon()
else
to_chat(user, span_warning("Access denied. This assembly was locked by [locked_by ? locked_by.registered_name : "someone else"]."))
return TRUE
else
// Trying to lock
locked = TRUE
locked_by = id_card
to_chat(user, span_notice("You lock \the [src]. Now only your ID card can unlock it."))
update_icon()
return TRUE
else if(istype(I, /obj/item/integrated_electronics/wirer) || istype(I, /obj/item/integrated_electronics/debugger) || I.has_tool_quality(TOOL_SCREWDRIVER))
if(opened)
tgui_interact(user)
@@ -404,6 +431,14 @@
for(var/obj/item/integrated_circuit/IC in contents)
IC.on_unanchored()
// Bump functionality, for pathfinding circuits. (Droid circuit assembly types)
/obj/item/electronic_assembly/Bump(atom/AM)
..()
if(istype(AM, /obj/machinery/door) && can_move())
var/obj/machinery/door/D = AM
if(D.check_access(src))
D.open()
// Returns TRUE if I is something that could/should have a valid interaction. Used to tell circuitclothes to hit the circuit with something instead of the clothes
/obj/item/electronic_assembly/proc/is_valid_tool(var/obj/item/I)
return I.has_tool_quality(TOOL_CROWBAR) || I.has_tool_quality(TOOL_SCREWDRIVER) || istype(I, /obj/item/integrated_circuit) || istype(I, /obj/item/cell/device) || istype(I, /obj/item/integrated_electronics)
@@ -31,7 +31,7 @@
set_pin_data(IC_OUTPUT, 1, desired_dir)
push_data()
activate_pin(2) //CHOMPEdit
activate_pin(2)
//CHOMPEdit Begin
/obj/item/integrated_circuit/smart/advanced_pathfinder
@@ -79,3 +79,132 @@
push_data()
activate_pin(2)
//CHOMPEdit End
/obj/item/integrated_circuit/smart/targeted_pathfinder
name = "targeted pathfinder"
desc = "Finds the best direction to a target using advanced pathfinding, when pulsed."
extended_desc = "This circuit uses a miniturized, integrated camera and advanced pathfinding to determine the best direction to a target, when pulsed."
icon_state = "numberpad"
complexity = 25
inputs = list(
"target" = IC_PINTYPE_REF
)
outputs = list(
"dir" = IC_PINTYPE_DIR
)
activators = list(
"calculate dir" = IC_PINTYPE_PULSE_IN,
"on calculated" = IC_PINTYPE_PULSE_OUT
)
spawn_flags = IC_SPAWN_RESEARCH
origin_tech = list(TECH_ENGINEERING = 4, TECH_DATA = 5)
power_draw_per_use = 40
/obj/item/integrated_circuit/smart/targeted_pathfinder/do_work()
var/datum/integrated_io/I = inputs[1]
set_pin_data(IC_OUTPUT, 1, null)
if(!isweakref(I.data))
push_data()
activate_pin(2)
return
var/atom/A = I.data.resolve()
if(!A)
push_data()
activate_pin(2)
return
var/turf/start = get_turf(src)
var/turf/goal = get_turf(A)
if(!start || !goal)
push_data()
activate_pin(2)
return
if(!(A in view(start)))
push_data()
activate_pin(2)
return // Can't see the target.
// Pathfinding start
var/list/path = AStar(start, goal, /turf/proc/AdjacentTurfsWithAccess, /turf/proc/Distance, 0, 30, id = assembly)
if(path && path.len > 1)
var/turf/next = path[2] // path[1] is current location
var/desired_dir = get_dir(start, next)
set_pin_data(IC_OUTPUT, 1, desired_dir)
else
// Fallback if pathfinding fails
var/desired_dir = get_dir(start, goal)
set_pin_data(IC_OUTPUT, 1, desired_dir)
push_data()
activate_pin(2)
/obj/item/integrated_circuit/smart/pathfinding_locomotion
name = "pathfinding locomotion controller"
desc = "A specialized circuit that uses pathfinding to move towards a target when pulsed."
extended_desc = "This circuit will calculate a path to the target and move one step along that path each time it's pulsed."
icon_state = "numberpad"
complexity = 40
inputs = list(
"target" = IC_PINTYPE_REF
)
outputs = list(
"current direction" = IC_PINTYPE_DIR,
"distance to target" = IC_PINTYPE_NUMBER
)
activators = list(
"step toward target" = IC_PINTYPE_PULSE_IN,
"on successful move" = IC_PINTYPE_PULSE_OUT,
"on failed move" = IC_PINTYPE_PULSE_OUT
)
spawn_flags = IC_SPAWN_RESEARCH
origin_tech = list(TECH_ENGINEERING = 5, TECH_DATA = 5)
power_draw_per_use = 60
cooldown_per_use = 2 // 3 delay on a ticker circuit from testing.
/obj/item/integrated_circuit/smart/pathfinding_locomotion/do_work()
var/datum/integrated_io/I = inputs[1]
if(!isweakref(I.data))
activate_pin(3)
return
var/atom/A = I.data.resolve()
if(!A)
activate_pin(3)
return
var/turf/start = get_turf(src)
var/turf/goal = get_turf(A)
if(!start || !goal)
activate_pin(3)
return
var/desired_dir
// Only calculate full path if target is in view
if(A in view(start))
var/list/path = AStar(start, goal, /turf/proc/AdjacentTurfsWithAccess, /turf/proc/Distance, 0, 30, id = assembly)
if(path && path.len > 1)
var/turf/next = path[2]
desired_dir = get_dir(start, next)
else
desired_dir = get_dir(start, goal)
else
// If we can't see the target, just move in its direction
desired_dir = get_dir(start, goal)
set_pin_data(IC_OUTPUT, 1, desired_dir)
set_pin_data(IC_OUTPUT, 2, get_dist(start, goal))
push_data()
// Move the assembly.
if(assembly && !assembly.anchored && assembly.can_move())
var/move_result = step(assembly, desired_dir)
if(move_result)
activate_pin(2)
else
activate_pin(3)
else
activate_pin(3)