Migrate security cameras to the new attack chain and refactor slightly. (#32466)

* Migrate security cameras to the new attack chain and refactor slightly.

* Only use one sheet of plasma.

* Remove double fingerprint.

* Apply suggestions from CRUNCH review.

Co-authored-by: CRUNCH <143041327+CRUNCH-Borg@users.noreply.github.com>
Signed-off-by: Alan <alfalfascout@users.noreply.github.com>

* Extrapolate from CRUNCH review.

* Apply suggestions from CRUNCH review.

Co-authored-by: CRUNCH <143041327+CRUNCH-Borg@users.noreply.github.com>
Signed-off-by: Alan <alfalfascout@users.noreply.github.com>

---------

Signed-off-by: Alan <alfalfascout@users.noreply.github.com>
Co-authored-by: CRUNCH <143041327+CRUNCH-Borg@users.noreply.github.com>
This commit is contained in:
Alan
2026-08-23 15:07:37 +00:00
committed by GitHub
co-authored by CRUNCH
parent 0244ba16c8
commit b54a0a404b
4 changed files with 95 additions and 71 deletions
+23 -17
View File
@@ -44,10 +44,14 @@
/// If this camera doesnt add to camera chunks. Used by camera bugs.
var/non_chunking_camera = FALSE
/obj/machinery/camera/Initialize(mapload, should_add_to_cameranet = TRUE)
/obj/machinery/camera/Initialize(mapload, should_add_to_cameranet = TRUE, obj/item/camera_assembly/use_assembly = null)
. = ..()
wires = new(src)
assembly = new(src)
if(istype(use_assembly))
assembly = use_assembly
else
assembly = new(src)
apply_upgrades()
assembly.state = 4
assembly.anchored = TRUE
assembly.update_icon()
@@ -69,7 +73,7 @@
/obj/machinery/camera/proc/create_prox_monitor()
if(!proximity_monitor)
proximity_monitor = new(src, 1)
proximity_monitor = new(src, CAMERA_VIEW_DISTANCE)
RegisterSignal(proximity_monitor, COMSIG_PARENT_QDELETING, PROC_REF(proximity_deleted))
/obj/machinery/camera/Moved(atom/OldLoc, Dir, Forced)
@@ -103,7 +107,6 @@
else
. += SPAN_NOTICE("[src]'s <i>internal wires</i> are disconnected, but it can be <b>cut free</b>.")
/obj/machinery/camera/emp_act(severity)
if(!status)
return
@@ -142,8 +145,8 @@
..()
/obj/machinery/camera/item_interaction(mob/living/user, obj/item/used, list/modifiers)
var/msg = SPAN_NOTICE("You attach [used] into the assembly inner circuits.")
var/msg2 = SPAN_NOTICE("The camera already has that upgrade!")
var/attach_msg = SPAN_NOTICE("You attach [used] to the inner circuits of [src].")
var/reject_msg = SPAN_WARNING("[src] already has that upgrade!")
if(istype(used, /obj/item/stack/sheet/mineral/plasma) && panel_open)
if(!user.canUnEquip(used, FALSE))
@@ -151,22 +154,24 @@
return ITEM_INTERACT_COMPLETE
if(!isEmpProof())
var/obj/item/stack/sheet/mineral/plasma/P = used
if(!P.use(1))
to_chat(user, SPAN_WARNING("You need at least one sheet of plasma to add EMP shielding to [src]!"))
return ITEM_INTERACT_COMPLETE
upgradeEmpProof()
to_chat(user, "[msg]")
P.use(1)
to_chat(user, attach_msg)
return ITEM_INTERACT_COMPLETE
else
to_chat(user, "[msg2]")
to_chat(user, reject_msg)
else if(istype(used, /obj/item/assembly/prox_sensor) && panel_open)
if(!user.canUnEquip(used, FALSE))
to_chat(user, SPAN_WARNING("[used] is stuck to your hand!"))
return ITEM_INTERACT_COMPLETE
if(!isMotion())
upgradeMotion()
to_chat(user, "[msg]")
to_chat(user, attach_msg)
qdel(used)
else
to_chat(user, "[msg2]")
to_chat(user, reject_msg)
return ITEM_INTERACT_COMPLETE
@@ -242,8 +247,10 @@
return
WELDER_ATTEMPT_WELD_MESSAGE
if(I.use_tool(src, user, 100, volume = I.tool_volume))
visible_message(SPAN_WARNING("[user] unwelds [src], leaving it as just a frame bolted to the wall."),
SPAN_WARNING("You unweld [src], leaving it as just a frame bolted to the wall"))
visible_message(
SPAN_WARNING("[user] unwelds [src], leaving it as just a frame bolted to the wall."),
SPAN_WARNING("You unweld [src], leaving it as just a frame bolted to the wall.")
)
deconstruct(TRUE)
/obj/machinery/camera/run_obj_armor(damage_amount, damage_type, damage_flag = 0, attack_dir)
@@ -339,10 +346,10 @@
/obj/machinery/camera/proc/can_use()
if(!status)
return 0
return FALSE
if(stat & EMPED)
return 0
return 1
return FALSE
return TRUE
/obj/machinery/camera/proc/can_see()
var/list/see = null
@@ -453,7 +460,6 @@
GLOB.cameranet.update_portable_camera(src, prev_turf)
prev_turf = get_turf(src)
/obj/machinery/camera/toxins // cameras to be used in toxins
c_tag = "Research Toxins Test Chamber East";
c_tag = "Bomb Test Site";
+46 -31
View File
@@ -12,12 +12,12 @@
icon_state = "cameracase"
w_class = WEIGHT_CLASS_SMALL
materials = list(MAT_METAL = 400, MAT_GLASS = 250)
new_attack_chain = TRUE
// Motion, EMP-Proof
var/list/obj/item/possible_upgrades = list(/obj/item/assembly/prox_sensor, /obj/item/stack/sheet/mineral/plasma)
var/list/upgrades = list()
var/state = ASSEMBLY_UNBUILT
/obj/item/camera_assembly/Destroy()
QDEL_LIST_CONTENTS(upgrades)
return ..()
@@ -35,29 +35,49 @@
. += SPAN_NOTICE("The camera assembly is <b>wired</b>, but the maintenence panel needs to be <i>screwed shut</i>.")
. += SPAN_NOTICE("Upgrades can be added to the camera assembly, and removed with a crowbar.")
/obj/item/camera_assembly/attackby__legacy__attackchain(obj/item/I, mob/living/user, params)
if(state == ASSEMBLY_WELDED && iscoil(I))
var/obj/item/stack/cable_coil/C = I
if(C.use(2))
to_chat(user, SPAN_NOTICE("You add wires to the assembly."))
playsound(loc, I.usesound, 50, 1)
state = ASSEMBLY_WIRED
else
/obj/item/camera_assembly/item_interaction(mob/living/user, obj/item/used, list/modifiers)
if(state == ASSEMBLY_WELDED && iscoil(used))
var/obj/item/stack/cable_coil/cables = used
if(!cables.use(2))
to_chat(user, SPAN_WARNING("You need 2 coils of wire to wire the assembly."))
return
return ITEM_INTERACT_COMPLETE
to_chat(user, SPAN_NOTICE("You add wires to the assembly."))
playsound(loc, used.usesound, 50, 1)
state = ASSEMBLY_WIRED
add_fingerprint(user)
return ITEM_INTERACT_COMPLETE
// Upgrades!
else if(is_type_in_list(I, possible_upgrades) && !is_type_in_list(I, upgrades)) // Is a possible upgrade and isn't in the camera already.
if(!user.drop_item_to_ground(I))
to_chat(user, SPAN_WARNING("[I] is stuck!"))
return
to_chat(user, SPAN_NOTICE("You attach [I] into the assembly inner circuits."))
upgrades += I
user.drop_item()
I.loc = src
return
else
return ..()
if(is_type_in_list(used, upgrades))
to_chat(user, SPAN_WARNING("The assembly already has that upgrade!"))
return ITEM_INTERACT_COMPLETE
if(!is_type_in_list(used, possible_upgrades))
return NONE
if(istype(used, /obj/item/stack/sheet/mineral/plasma))
var/obj/item/stack/sheet/mineral/plasma/old_stack = used
var/obj/item/new_stack = old_stack.split(user, 1)
if(!new_stack)
to_chat(user, SPAN_WARNING("You need at least one sheet of plasma to add EMP shielding to [src]!"))
return ITEM_INTERACT_COMPLETE
to_chat(user, SPAN_NOTICE("You attach [used] to the inner circuits of [src]."))
new_stack.forceMove(src)
upgrades += new_stack
add_fingerprint(user)
return ITEM_INTERACT_COMPLETE
if(!user.drop_item_to_ground(used))
to_chat(user, SPAN_WARNING("[used] is stuck to your hand!"))
return ITEM_INTERACT_COMPLETE
to_chat(user, SPAN_NOTICE("You attach [used] to the inner circuits of [src]."))
upgrades += used
add_fingerprint(user)
used.forceMove(src)
return ITEM_INTERACT_COMPLETE
/obj/item/camera_assembly/crowbar_act(mob/user, obj/item/I)
if(!length(upgrades))
@@ -69,7 +89,7 @@
if(U)
to_chat(user, SPAN_NOTICE("You detach an upgrade from the assembly."))
playsound(loc, I.usesound, 50, 1)
U.loc = get_turf(src)
U.forceMove(get_turf(src))
upgrades -= U
/obj/item/camera_assembly/screwdriver_act(mob/user, obj/item/I)
@@ -82,13 +102,13 @@
var/input = strip_html(input(usr, "Which networks would you like to connect this camera to? Separate networks with a comma. No Spaces!\nFor example: SS13,Security,Secret ", "Set Network", "SS13"))
if(!input)
state = ASSEMBLY_WIRED
to_chat(usr, SPAN_WARNING("No input found please hang up and try your call again."))
to_chat(usr, SPAN_WARNING("No input found. Please hang up and try your call again."))
return
var/list/tempnetwork = splittext(input, ",")
if(length(tempnetwork) < 1)
state = ASSEMBLY_WIRED
to_chat(usr, SPAN_WARNING("No network found please hang up and try your call again."))
to_chat(usr, SPAN_WARNING("No network found. Please hang up and try your call again."))
return
var/area/camera_area = get_area(src)
@@ -97,14 +117,11 @@
state = ASSEMBLY_BUILT
var/list/network_list = uniquelist(tempnetwork)
var/list/visible_networks = difflist(network_list, GLOB.restricted_camera_networks)
var/obj/machinery/camera/C = new(loc, length(visible_networks) > 0)
loc = C
C.assembly = src
var/obj/machinery/camera/C = new(loc, length(visible_networks) > 0, src)
forceMove(C)
C.auto_turn()
C.network = network_list
C.c_tag = input
for(var/i = 5; i >= 0; i -= 1)
@@ -116,7 +133,6 @@
if(confirm == "Yes")
break
/obj/item/camera_assembly/wirecutter_act(mob/user, obj/item/I)
if(state != ASSEMBLY_WIRED)
return
@@ -181,7 +197,6 @@
new /obj/item/stack/sheet/metal(loc)
qdel(src)
#undef ASSEMBLY_UNBUILT
#undef ASSEMBLY_WRENCHED
#undef ASSEMBLY_WELDED
+17 -9
View File
@@ -139,26 +139,34 @@
// UPGRADE PROCS
/obj/machinery/camera/proc/upgradeEmpProof()
if(isEmpProof())
return
assembly.upgrades.Add(new /obj/item/stack/sheet/mineral/plasma(assembly))
setPowerUsage()
apply_upgrades()
/obj/machinery/camera/proc/upgradeXRay()
if(isXRay())
return
assembly.upgrades.Add(new /obj/item/analyzer(assembly))
setPowerUsage()
//Update what it can see.
GLOB.cameranet.update_visibility(src, 0)
apply_upgrades()
// If you are upgrading Motion, and it isn't in the camera's New(), add it to the machines list.
/obj/machinery/camera/proc/upgradeMotion()
if(isMotion())
return
if(name == initial(name))
name = "motion-sensitive security camera"
assembly.upgrades.Add(new /obj/item/assembly/prox_sensor(assembly))
proximity_monitor = new(src, CAMERA_VIEW_DISTANCE)
apply_upgrades()
/obj/machinery/camera/proc/apply_upgrades()
setPowerUsage()
// Add it to machines that process
START_PROCESSING(SSmachines, src)
if(isMotion())
if(name == initial(name))
name = "motion-sensitive security camera"
set_area_motion(get_area(src))
if(!isprocessing)
START_PROCESSING(SSmachines, src)
if(isXRay())
GLOB.cameranet.update_visibility(src, 0)
/obj/machinery/camera/proc/setPowerUsage()
var/mult = 1
+9 -14
View File
@@ -1,9 +1,9 @@
/mob/living/silicon/ai/proc/InvalidTurf(turf/T as turf)
if(!T)
return 1
return TRUE
if(!is_level_reachable(T.z))
return 1
return 0
return TRUE
return FALSE
/mob/living/silicon/ai/proc/get_camera_list()
@@ -38,7 +38,7 @@
return
if(!camera || camera == "Cancel")
return 0
return FALSE
var/obj/machinery/camera/C = track.cameras[camera]
src.eyeobj.set_loc(C)
@@ -67,11 +67,6 @@
if(!M.can_track(usr))
continue
// Human check
var/human = 0
if(ishuman(M))
human = 1
var/name = M.name
if(name in track.names)
track.namecounts[name]++
@@ -79,7 +74,7 @@
else
track.names.Add(name)
track.namecounts[name] = 1
if(human)
if(ishuman(M))
track.humans[name] = M
else
track.others[name] = M
@@ -172,14 +167,14 @@
/proc/near_camera(mob/living/M)
if(!isturf(M.loc))
return 0
return FALSE
if(isrobot(M))
var/mob/living/silicon/robot/R = M
if(!(R.camera && R.camera.can_use()) && !GLOB.cameranet.check_camera_vis(M))
return 0
return FALSE
else if(!GLOB.cameranet.check_camera_vis(M))
return 0
return 1
return FALSE
return TRUE
/obj/machinery/camera/attack_ai(mob/living/silicon/ai/user)
if(!istype(user))