From 93ed0f096d2ec9841f704c340f5e158f02131e87 Mon Sep 17 00:00:00 2001
From: asciodev <81930475+asciodev@users.noreply.github.com>
Date: Fri, 17 Jan 2025 13:22:43 -0500
Subject: [PATCH] Refactors AI / camera eyes and slows holopad holograms to
walk speed (#25078)
* Refactor/deduplicate camera eye code
Camera Eyes previously had duplicated logic across several files. This
change uncooks the spaghetti. Additionally, half-baked support for TG's
multicam feature has been removed, as it was not functional or in use.
* lets ff now
* Camera Eye refactor fixes and finishing touches
This change completes a refactor of AI eyes, which were previously used
by xenobio consoles, syndicate and abductor camera consoles, shuttle
docking computers, holograms, and, of course, the AI. Duplicated logic
has been extracted to an abstract base mob, /mob/camera/eye, from which
new types for each of the above now derive.
Functionality is largely the same, with only a few minor cosmetic
differences (i.e. camera eyes are now appropriately named given their
type and user), as well as a quality-of-life enhancement for holograms,
slowing their movement speed to base run speed to prevent users from
accidentally zooming out of calls.
* Camera eye refactor: Fix AI acceleration toggle
The acceleration toggle was broken in the camera eye refactor, as
previously the boolean was stored on the AI rather than its eye. This
change fixes that.
* Camera eye refactor: Fix syndicate cam visibility
With the camera eye refactor, the syndicate advanced camera consoles
lost the ability to view maintenance tunnels and other areas without
active cameras, seeing static in their place instead (as all other
cameras do). This change reinstates the original behavior.
* Camera eye refactor: Convert spaces to tabs
* Camera eye refactor: Fix CRLF
* Apply suggestions from code review
General minor code quality improvements suggested by GDNgit
Co-authored-by: GDN <96800819+GDNgit@users.noreply.github.com>
* Apply suggestions from code review
Rename parameter names to avoid src accesses, remove an ambiguous and
unused mob_define and holopad range variable from a previous WIP, change
the for loop in /mob/camera/eye/relaymove to a for-to loop, and change
the chat message warning, sent when an AI Eye is created on an AI that
already has one, to a stack trace
* Adds toggle to AI commands for fast holograms
* Refactor ripped Hologram Eye relaymove
Previously, the relaymove proc for hologram eyes was redundant and
nearly impossible to read. It has been separated out into a few
different named procs, and has had its use of `spawn` removed.
* Remove unnecessary src access
* Fix bug involving shuttle placement outlines
The camera eye refactor that this commit is a part of introduced a bug
that prevented shuttle placement outlines from showing up on first use
of the shuttle console. This change fixes that bug.
* Unrevert some changes from #26306 lost in merge
* Remove erroneous free xray vision on advanced cams
* Autodoc camera acceleration vars
* Remove redundant null var initialization per code review
Co-authored-by: Drsmail <60036448+Drsmail@users.noreply.github.com>
Signed-off-by: asciodev <81930475+asciodev@users.noreply.github.com>
* Changed variables to camel_case, autodocs, cleanup
Changed a number of camera eye-related variables to camel_case style,
added appropriate autodoc comments, as per code review. Also removed an
unused cameranet function, modified the call signature of a cameranet
function to be more semantic, and changed a qdel-on-initialize in camera
eyes to return INITIALIZE_HINT_QDEL instead.
Co-authored-by: Luc <89928798+lewcc@users.noreply.github.com>
* Remove stray qdel(src) per code review
Co-authored-by: Luc <89928798+lewcc@users.noreply.github.com>
Signed-off-by: asciodev <81930475+asciodev@users.noreply.github.com>
---------
Signed-off-by: asciodev <81930475+asciodev@users.noreply.github.com>
Co-authored-by: GDN <96800819+GDNgit@users.noreply.github.com>
Co-authored-by: Drsmail <60036448+Drsmail@users.noreply.github.com>
Co-authored-by: Luc <89928798+lewcc@users.noreply.github.com>
---
code/__DEFINES/mob_defines.dm | 4 +-
code/__HELPERS/unsorted.dm | 2 +-
code/_onclick/ai_onclick.dm | 12 +-
code/_onclick/hud/ai_hud.dm | 4 +-
code/_onclick/hud/alert.dm | 2 +-
code/controllers/subsystem/SSshuttles.dm | 2 +-
.../subsystem/tickets/SStickets.dm | 2 +-
code/datums/diseases/magnitis.dm | 6 +-
code/datums/emote.dm | 2 +-
code/datums/holocall.dm | 54 +++--
code/datums/keybindings/ai_keybinds.dm | 4 +-
code/datums/mind.dm | 2 +-
code/datums/station_traits/positive_traits.dm | 2 +-
code/game/atoms_movable.dm | 6 +-
code/game/data_huds.dm | 2 +-
.../game/gamemodes/autotraitor/autotraitor.dm | 2 +-
.../gamemodes/malfunction/Malf_Modules.dm | 10 +-
.../abduction/machinery/abductor_camera.dm | 13 +-
code/game/gamemodes/nuclear/nuclear.dm | 2 +-
code/game/gamemodes/scoreboard.dm | 2 +-
code/game/machinery/ai_display.dm | 2 +-
code/game/machinery/camera/camera.dm | 12 +-
code/game/machinery/camera/camera_presets.dm | 2 +-
code/game/machinery/camera/motion.dm | 2 +-
code/game/machinery/camera/tracking.dm | 28 +--
.../machinery/computer/camera_advanced.dm | 119 ++---------
.../game/machinery/computer/camera_console.dm | 2 +-
.../game/machinery/computer/communications.dm | 12 +-
.../machinery/computer/message_monitor.dm | 6 +-
code/game/machinery/computer/robot_control.dm | 4 +-
code/game/machinery/dance_machine.dm | 2 +-
code/game/machinery/doors/door.dm | 2 +-
code/game/machinery/hologram.dm | 23 ++-
code/game/machinery/magnetic_module.dm | 2 +-
code/game/machinery/poolcontroller.dm | 2 +-
code/game/machinery/portable_turret.dm | 2 +-
code/game/machinery/quantum_pad.dm | 8 +-
code/game/machinery/teleporter.dm | 4 +-
code/game/machinery/turret_control.dm | 2 +-
code/game/mecha/mecha.dm | 19 +-
.../effects/effect_system/effect_system.dm | 4 +-
.../objects/items/devices/radio/headset.dm | 2 +-
.../items/devices/radio/radio_objects.dm | 2 +-
code/game/objects/items/devices/scanners.dm | 2 +-
code/game/objects/items/tools/multitool.dm | 8 +-
code/game/objects/items/toys.dm | 4 +-
code/game/objects/objs.dm | 2 +-
code/game/objects/structures.dm | 4 +-
.../structures/crates_lockers/closets.dm | 2 +-
code/game/objects/structures/inflatable.dm | 2 +-
code/game/objects/structures/kitchen_spike.dm | 2 +-
code/game/objects/structures/mineral_doors.dm | 2 +-
code/game/turfs/turf.dm | 8 +-
code/game/verbs/ooc.dm | 4 +-
code/modules/admin/admin_verbs.dm | 4 +-
code/modules/admin/misc_admin_procs.dm | 6 +-
code/modules/admin/player_panel.dm | 4 +-
code/modules/admin/topic.dm | 16 +-
code/modules/admin/verbs/randomverbs.dm | 2 +-
.../antagonists/traitor/datum_traitor.dm | 10 +-
.../atmospherics/machinery/airalarm.dm | 8 +-
.../atmospherics/machinery/other/meter.dm | 4 +-
code/modules/clothing/suits/misc_suits.dm | 2 +-
code/modules/events/dust.dm | 2 +-
code/modules/fish/fishtank.dm | 2 +-
.../silicon/ai/freelook => camera}/README.md | 0
code/modules/mob/camera/cameranet.dm | 160 +++++++++++++++
.../silicon/ai/freelook => camera}/chunk.dm | 84 ++++----
code/modules/mob/camera/eye.dm | 191 ++++++++++++++++++
code/modules/mob/camera/eye/abductor.dm | 14 ++
code/modules/mob/camera/eye/ai_eye.dm | 34 ++++
code/modules/mob/camera/eye/hologram_eye.dm | 53 +++++
.../mob/camera/eye/shuttle_navigator.dm | 30 +++
code/modules/mob/camera/eye/syndicate.dm | 10 +
code/modules/mob/camera/eye/xenobio_eye.dm | 22 ++
.../mob/dead/observer/observer_base.dm | 4 +-
.../modules/mob/dead/observer/observer_say.dm | 2 +-
code/modules/mob/language.dm | 2 +-
code/modules/mob/living/carbon/examine.dm | 2 +-
.../mob/living/carbon/human/human_mob.dm | 2 +-
code/modules/mob/living/living_defines.dm | 2 +-
.../modules/mob/living/silicon/ai/ai_death.dm | 2 +-
code/modules/mob/living/silicon/ai/ai_life.dm | 2 +-
code/modules/mob/living/silicon/ai/ai_mob.dm | 67 ++++--
code/modules/mob/living/silicon/ai/ai_say.dm | 2 +-
.../living/silicon/ai/freelook/cameranet.dm | 177 ----------------
.../mob/living/silicon/ai/freelook/eye.dm | 155 --------------
.../mob/living/silicon/robot/robot_mob.dm | 2 +-
code/modules/mob/mob.dm | 4 +-
code/modules/mob/mob_misc_procs.dm | 4 +-
code/modules/mob/mob_movement.dm | 17 +-
code/modules/mob/mob_say_base.dm | 2 +-
code/modules/paperwork/photocopier.dm | 2 +-
code/modules/paperwork/silicon_photography.dm | 2 +-
code/modules/power/apc/apc.dm | 4 +-
.../generators/portable generators/pacman.dm | 2 +-
code/modules/projectiles/projectile/beams.dm | 2 +-
code/modules/recycling/disposal.dm | 4 +-
code/modules/recycling/sortingmachinery.dm | 2 +-
.../research/xenobiology/xenobio_camera.dm | 83 +++-----
code/modules/shuttle/emergency.dm | 2 +-
code/modules/shuttle/navigation_computer.dm | 59 ++----
code/modules/surgery/organs/vocal_cords.dm | 4 +-
code/modules/tgui/modules/crew_monitor.dm | 4 +-
code/modules/tgui/modules/law_manager.dm | 4 +-
code/modules/tgui/plugins/tgui_login.dm | 4 +-
paradise.dme | 12 +-
107 files changed, 912 insertions(+), 822 deletions(-)
rename code/modules/mob/{living/silicon/ai/freelook => camera}/README.md (100%)
create mode 100644 code/modules/mob/camera/cameranet.dm
rename code/modules/mob/{living/silicon/ai/freelook => camera}/chunk.dm (63%)
create mode 100644 code/modules/mob/camera/eye.dm
create mode 100644 code/modules/mob/camera/eye/abductor.dm
create mode 100644 code/modules/mob/camera/eye/ai_eye.dm
create mode 100644 code/modules/mob/camera/eye/hologram_eye.dm
create mode 100644 code/modules/mob/camera/eye/shuttle_navigator.dm
create mode 100644 code/modules/mob/camera/eye/syndicate.dm
create mode 100644 code/modules/mob/camera/eye/xenobio_eye.dm
delete mode 100644 code/modules/mob/living/silicon/ai/freelook/cameranet.dm
delete mode 100644 code/modules/mob/living/silicon/ai/freelook/eye.dm
diff --git a/code/__DEFINES/mob_defines.dm b/code/__DEFINES/mob_defines.dm
index bccec9548a2..d3eb93078ea 100644
--- a/code/__DEFINES/mob_defines.dm
+++ b/code/__DEFINES/mob_defines.dm
@@ -259,7 +259,7 @@
#define ismorph(A) (istype((A), /mob/living/simple_animal/hostile/morph))
#define issilicon(A) (istype((A), /mob/living/silicon))
-#define isAI(A) (istype((A), /mob/living/silicon/ai))
+#define is_ai(A) (istype((A), /mob/living/silicon/ai))
#define isrobot(A) (istype((A), /mob/living/silicon/robot))
#define isdrone(A) (istype((A), /mob/living/silicon/robot/drone))
#define ispAI(A) (istype((A), /mob/living/silicon/pai))
@@ -273,7 +273,7 @@
#define ispathanimal(A) (ispath(A, /mob/living/simple_animal))
#define iscameramob(A) (istype((A), /mob/camera))
-#define isAIEye(A) (istype((A), /mob/camera/ai_eye))
+#define is_ai_eye(A) (istype((A), /mob/camera/eye))
#define isovermind(A) (istype((A), /mob/camera/blob))
#define isSpirit(A) (istype((A), /mob/spirit))
diff --git a/code/__HELPERS/unsorted.dm b/code/__HELPERS/unsorted.dm
index 487c5eb39fe..7a339ec8283 100644
--- a/code/__HELPERS/unsorted.dm
+++ b/code/__HELPERS/unsorted.dm
@@ -879,7 +879,7 @@ Returns 1 if the chain up to the area contains the given typepath
continue
O.loc.Exited(O)
- O.setLoc(X)
+ O.set_loc(X)
O.loc.Entered(O)
for(var/mob/M in T)
diff --git a/code/_onclick/ai_onclick.dm b/code/_onclick/ai_onclick.dm
index 3801ae81dd7..a9d63f51c6b 100644
--- a/code/_onclick/ai_onclick.dm
+++ b/code/_onclick/ai_onclick.dm
@@ -102,20 +102,20 @@
add_attack_logs(src, src, "[key_name_admin(src)] might be running a modified client! (failed can_see on AI click of [A]([ADMIN_COORDJMP(pixel_turf)]))", ATKLOG_ALL)
var/message = "[key_name(src)] might be running a modified client! (failed can_see on AI click of [A]([COORD(pixel_turf)]))"
log_admin(message)
- GLOB.discord_manager.send2discord_simple_noadmins("**\[Warning]** [key_name(src)] might be running a modified client! (failed checkTurfVis on AI click of [A]([COORD(pixel_turf)]))")
+ GLOB.discord_manager.send2discord_simple_noadmins("**\[Warning]** [key_name(src)] might be running a modified client! (failed check_turf_vis on AI click of [A]([COORD(pixel_turf)]))")
return FALSE
var/turf_visible
if(pixel_turf)
- turf_visible = GLOB.cameranet.checkTurfVis(pixel_turf)
+ turf_visible = GLOB.cameranet.check_turf_vis(pixel_turf)
if(!turf_visible)
if((istype(loc, /obj/item/aicard) || ismecha(loc)) && (pixel_turf in range(client.view, loc)))
turf_visible = TRUE
else
if(pixel_turf.obscured)
- log_admin("[key_name_admin(src)] might be running a modified client! (failed checkTurfVis on AI click of [A]([COORD(pixel_turf)])")
- add_attack_logs(src, src, "[key_name_admin(src)] might be running a modified client! (failed checkTurfVis on AI click of [A]([ADMIN_COORDJMP(pixel_turf)]))", ATKLOG_ALL)
- GLOB.discord_manager.send2discord_simple_noadmins("**\[Warning]** [key_name(src)] might be running a modified client! (failed checkTurfVis on AI click of [A]([COORD(pixel_turf)]))")
+ log_admin("[key_name_admin(src)] might be running a modified client! (failed check_turf_vis on AI click of [A]([COORD(pixel_turf)])")
+ add_attack_logs(src, src, "[key_name_admin(src)] might be running a modified client! (failed check_turf_vis on AI click of [A]([ADMIN_COORDJMP(pixel_turf)]))", ATKLOG_ALL)
+ GLOB.discord_manager.send2discord_simple_noadmins("**\[Warning]** [key_name(src)] might be running a modified client! (failed check_turf_vis on AI click of [A]([COORD(pixel_turf)]))")
return FALSE
return TRUE
@@ -184,7 +184,7 @@
return
/mob/living/silicon/ai/TurfAdjacent(turf/T)
- return (GLOB.cameranet && GLOB.cameranet.checkTurfVis(T))
+ return (GLOB.cameranet && GLOB.cameranet.check_turf_vis(T))
// APC
diff --git a/code/_onclick/hud/ai_hud.dm b/code/_onclick/hud/ai_hud.dm
index 9d2fba72029..f25d9356c0a 100644
--- a/code/_onclick/hud/ai_hud.dm
+++ b/code/_onclick/hud/ai_hud.dm
@@ -105,7 +105,7 @@
/atom/movable/screen/ai/state_laws/Click()
if(..())
return
- if(isAI(usr))
+ if(is_ai(usr))
var/mob/living/silicon/ai/AI = usr
AI.subsystem_law_manager()
@@ -156,7 +156,7 @@
/atom/movable/screen/ai/sensors/Click()
if(..())
return
- if(isAI(usr))
+ if(is_ai(usr))
var/mob/living/silicon/ai/AI = usr
AI.sensor_mode()
else if(isrobot(usr))
diff --git a/code/_onclick/hud/alert.dm b/code/_onclick/hud/alert.dm
index 5fbf8c8ef26..f1823e4b4b8 100644
--- a/code/_onclick/hud/alert.dm
+++ b/code/_onclick/hud/alert.dm
@@ -514,7 +514,7 @@ so as to remain in compliance with the most up-to-date laws."
var/mob/living/silicon/ai/AI = usr
var/turf/T = get_turf(target)
if(T)
- AI.eyeobj.setLoc(T)
+ AI.eyeobj.set_loc(T)
//MECHS
/atom/movable/screen/alert/low_mech_integrity
diff --git a/code/controllers/subsystem/SSshuttles.dm b/code/controllers/subsystem/SSshuttles.dm
index 1ccc4e5be71..2065c39026f 100644
--- a/code/controllers/subsystem/SSshuttles.dm
+++ b/code/controllers/subsystem/SSshuttles.dm
@@ -173,7 +173,7 @@ SUBSYSTEM_DEF(shuttle)
var/callShuttle = 1
for(var/thing in GLOB.shuttle_caller_list)
- if(isAI(thing))
+ if(is_ai(thing))
var/mob/living/silicon/ai/AI = thing
if(AI.stat || !AI.client)
continue
diff --git a/code/controllers/subsystem/tickets/SStickets.dm b/code/controllers/subsystem/tickets/SStickets.dm
index 269a53fcc1b..c7c77d18f48 100644
--- a/code/controllers/subsystem/tickets/SStickets.dm
+++ b/code/controllers/subsystem/tickets/SStickets.dm
@@ -161,7 +161,7 @@ SUBSYSTEM_DEF(tickets)
if(M)
L += "([ADMIN_QUE(M,"?")]) ([ADMIN_PP(M,"PP")]) ([ADMIN_VV(M,"VV")]) ([ADMIN_TP(M,"TP")]) ([ADMIN_SM(M,"SM")]) ([admin_jump_link(M)])"
L += "(TICKET) "
- L += "[isAI(M) ? "(CL)" : ""] (TAKE) "
+ L += "[is_ai(M) ? "(CL)" : ""] (TAKE) "
L += "(RESOLVE) (AUTO) "
L += "(CONVERT) : [one_line ? " " : "
"][msg]"
return L.Join()
diff --git a/code/datums/diseases/magnitis.dm b/code/datums/diseases/magnitis.dm
index 10095d0ad13..ddb6782f6db 100644
--- a/code/datums/diseases/magnitis.dm
+++ b/code/datums/diseases/magnitis.dm
@@ -22,7 +22,7 @@
if(!M.anchored && (M.flags & CONDUCT))
step_towards(M,affected_mob)
for(var/mob/living/silicon/S in orange(2,affected_mob))
- if(isAI(S)) continue
+ if(is_ai(S)) continue
step_towards(S,affected_mob)
if(3)
if(prob(2))
@@ -37,7 +37,7 @@
for(i=0,iYou haven't set location [location_number] yet!")
return
- AI.eyeobj.setLoc(AI.stored_locations[location_number])
+ AI.eyeobj.set_loc(AI.stored_locations[location_number])
/datum/keybinding/ai/to_location/one
name = "Jump to Location One"
diff --git a/code/datums/mind.dm b/code/datums/mind.dm
index b84e06b7b4e..b23129559d8 100644
--- a/code/datums/mind.dm
+++ b/code/datums/mind.dm
@@ -1509,7 +1509,7 @@
message_admins("[key_name_admin(usr)] has un-emagged [key_name_admin(current)]")
if("unemagcyborgs")
- if(!isAI(current))
+ if(!is_ai(current))
return
var/mob/living/silicon/ai/ai = current
for(var/mob/living/silicon/robot/R in ai.connected_robots)
diff --git a/code/datums/station_traits/positive_traits.dm b/code/datums/station_traits/positive_traits.dm
index a545c1504e5..b4f5420d6ec 100644
--- a/code/datums/station_traits/positive_traits.dm
+++ b/code/datums/station_traits/positive_traits.dm
@@ -213,7 +213,7 @@
var/cybernetic_type = job_to_cybernetic[job.type]
if(!cybernetic_type)
- if(isAI(spawned))
+ if(is_ai(spawned))
var/mob/living/silicon/ai/ai = spawned
ai.eyeobj.relay_speech = TRUE //surveillance upgrade. the ai gets cybernetics too.
return
diff --git a/code/game/atoms_movable.dm b/code/game/atoms_movable.dm
index 13e3133e7d9..2c102af007a 100644
--- a/code/game/atoms_movable.dm
+++ b/code/game/atoms_movable.dm
@@ -198,9 +198,9 @@
return FALSE
return TRUE
-// Used in shuttle movement and AI eye stuff.
-// Primarily used to notify objects being moved by a shuttle/bluespace fuckup.
-/atom/movable/proc/setLoc(T, teleported=0)
+/// Used in shuttle movement and camera eye stuff.
+/// Primarily used to notify objects being moved by a shuttle/bluespace fuckup.
+/atom/movable/proc/set_loc(T, teleported=0)
var/old_loc = loc
loc = T
Moved(old_loc, get_dir(old_loc, loc))
diff --git a/code/game/data_huds.dm b/code/game/data_huds.dm
index da9bc720a4f..83704a83585 100644
--- a/code/game/data_huds.dm
+++ b/code/game/data_huds.dm
@@ -534,7 +534,7 @@
else if(isrobot(commenter))
var/mob/living/silicon/robot/U = commenter
commenter_display = "[U.name] ([U.modtype] [U.braintype])"
- else if(isAI(commenter))
+ else if(is_ai(commenter))
var/mob/living/silicon/ai/U = commenter
commenter_display = "[U.name] (artificial intelligence)"
comment_text = "Made by [commenter_display] on [GLOB.current_date_string] [station_time_timestamp()]:
[comment_text]"
diff --git a/code/game/gamemodes/autotraitor/autotraitor.dm b/code/game/gamemodes/autotraitor/autotraitor.dm
index 9c510fc5a74..dbcf5e38f9a 100644
--- a/code/game/gamemodes/autotraitor/autotraitor.dm
+++ b/code/game/gamemodes/autotraitor/autotraitor.dm
@@ -72,7 +72,7 @@
if(player.mind.has_antag_datum(/datum/antagonist/traitor))
traitor_count += 1
continue
- if(ishuman(player) || isAI(player))
+ if(ishuman(player) || is_ai(player))
if((ROLE_TRAITOR in player.client.prefs.be_special) && !player.client.skip_antag && !jobban_isbanned(player, ROLE_TRAITOR) && !jobban_isbanned(player, ROLE_SYNDICATE))
possible_traitors += player.mind
for(var/datum/mind/player in possible_traitors)
diff --git a/code/game/gamemodes/malfunction/Malf_Modules.dm b/code/game/gamemodes/malfunction/Malf_Modules.dm
index 90ba39865b7..5aff5df2a95 100644
--- a/code/game/gamemodes/malfunction/Malf_Modules.dm
+++ b/code/game/gamemodes/malfunction/Malf_Modules.dm
@@ -126,7 +126,7 @@
/datum/module_picker/Topic(href, href_list)
..()
- if(!isAI(usr))
+ if(!is_ai(usr))
return
var/mob/living/silicon/ai/A = usr
@@ -573,8 +573,8 @@
var/turf/T = turfs[n]
if(!isfloorturf(T))
success = FALSE
- var/datum/camerachunk/C = GLOB.cameranet.getCameraChunk(T.x, T.y, T.z)
- if(!C.visibleTurfs[T])
+ var/datum/camerachunk/C = GLOB.cameranet.get_camera_chunk(T.x, T.y, T.z)
+ if(!C.visible_turfs[T])
alert_msg = "You don't have camera vision of this location!"
success = FALSE
for(var/atom/movable/AM in T.contents)
@@ -673,12 +673,12 @@
I.loc = deploylocation
client.images += I
I.icon_state = "redOverlay"
- var/datum/camerachunk/C = GLOB.cameranet.getCameraChunk(deploylocation.x, deploylocation.y, deploylocation.z)
+ var/datum/camerachunk/C = GLOB.cameranet.get_camera_chunk(deploylocation.x, deploylocation.y, deploylocation.z)
if(!istype(deploylocation))
to_chat(src, "There isn't enough room! Make sure you are placing the machine in a clear area and on a floor.")
return FALSE
- if(!C.visibleTurfs[deploylocation])
+ if(!C.visible_turfs[deploylocation])
to_chat(src, "You don't have camera vision of this location!")
addtimer(CALLBACK(src, PROC_REF(remove_transformer_image), client, I, deploylocation), 3 SECONDS)
return FALSE
diff --git a/code/game/gamemodes/miniantags/abduction/machinery/abductor_camera.dm b/code/game/gamemodes/miniantags/abduction/machinery/abductor_camera.dm
index df5767cf2a9..b8d28d1161a 100644
--- a/code/game/gamemodes/miniantags/abduction/machinery/abductor_camera.dm
+++ b/code/game/gamemodes/miniantags/abduction/machinery/abductor_camera.dm
@@ -23,7 +23,8 @@
return ..()
/obj/machinery/computer/camera_advanced/abductor/CreateEye()
- ..()
+ eyeobj = new /mob/camera/eye/abductor(loc, name, src, current_user)
+ give_eye_control(current_user)
eyeobj.visible_icon = 1
eyeobj.icon = 'icons/obj/abductor.dmi'
eyeobj.icon_state = "camera_target"
@@ -74,10 +75,10 @@
if(!target || !iscarbon(owner))
return
var/mob/living/carbon/human/C = owner
- var/mob/camera/ai_eye/remote/remote_eye = C.remote_control
+ var/mob/camera/eye/abductor/remote_eye = C.remote_control
var/obj/machinery/abductor/pad/P = target
- if(GLOB.cameranet.checkTurfVis(remote_eye.loc))
+ if(GLOB.cameranet.check_turf_vis(remote_eye.loc))
P.PadToLoc(remote_eye.loc)
/datum/action/innate/teleport_out
@@ -101,10 +102,10 @@
if(!target || !iscarbon(owner))
return
var/mob/living/carbon/human/C = owner
- var/mob/camera/ai_eye/remote/remote_eye = C.remote_control
+ var/mob/camera/eye/abductor/remote_eye = C.remote_control
var/obj/machinery/abductor/pad/P = target
- if(GLOB.cameranet.checkTurfVis(remote_eye.loc))
+ if(GLOB.cameranet.check_turf_vis(remote_eye.loc))
P.MobToLoc(remote_eye.loc,C)
/datum/action/innate/vest_mode_swap
@@ -137,7 +138,7 @@
return
var/mob/living/carbon/human/C = owner
- var/mob/camera/ai_eye/remote/remote_eye = C.remote_control
+ var/mob/camera/eye/abductor/remote_eye = C.remote_control
var/obj/machinery/abductor/console/console = target
console.SetDroppoint(remote_eye.loc,owner)
diff --git a/code/game/gamemodes/nuclear/nuclear.dm b/code/game/gamemodes/nuclear/nuclear.dm
index 323943bd78d..99be8d840c2 100644
--- a/code/game/gamemodes/nuclear/nuclear.dm
+++ b/code/game/gamemodes/nuclear/nuclear.dm
@@ -501,7 +501,7 @@
for(var/mob in GLOB.mob_living_list)
var/mob/living/C = mob
- if(ishuman(C) || isAI(C) || isrobot(C))
+ if(ishuman(C) || is_ai(C) || isrobot(C))
if(C.stat == DEAD)
continue
if(!C.client)
diff --git a/code/game/gamemodes/scoreboard.dm b/code/game/gamemodes/scoreboard.dm
index ad5d6da9479..a38ba8eeffc 100644
--- a/code/game/gamemodes/scoreboard.dm
+++ b/code/game/gamemodes/scoreboard.dm
@@ -135,7 +135,7 @@ GLOBAL_VAR(scoreboard) // Variable to save the scoreboard string once it's been
/datum/scoreboard/proc/check_station_player(mob/M)
if(!is_station_level(M.z) || M.stat != DEAD)
return
- if(isAI(M))
+ if(is_ai(M))
dead_ai = TRUE
score_dead_crew++
else if(ishuman(M))
diff --git a/code/game/machinery/ai_display.dm b/code/game/machinery/ai_display.dm
index fda00c73582..155d67d7238 100644
--- a/code/game/machinery/ai_display.dm
+++ b/code/game/machinery/ai_display.dm
@@ -23,7 +23,7 @@ GLOBAL_LIST_EMPTY(ai_displays)
return ..()
/obj/machinery/ai_status_display/attack_ai(mob/living/silicon/ai/user)
- if(isAI(user))
+ if(is_ai(user))
user.ai_statuschange()
/obj/machinery/ai_status_display/emp_act(severity)
diff --git a/code/game/machinery/camera/camera.dm b/code/game/machinery/camera/camera.dm
index ca131022a99..bc793fadcc3 100644
--- a/code/game/machinery/camera/camera.dm
+++ b/code/game/machinery/camera/camera.dm
@@ -55,7 +55,7 @@
GLOB.cameranet.cameras += src
part_of_camera_network = should_add_to_cameranet
if(part_of_camera_network)
- GLOB.cameranet.addCamera(src)
+ GLOB.cameranet.add_camera(src)
if(isturf(loc))
var/area/our_area = get_area(src)
LAZYADD(our_area.cameras, UID())
@@ -81,7 +81,7 @@
kick_out_watchers()
QDEL_NULL(assembly)
QDEL_NULL(wires)
- GLOB.cameranet.removeCamera(src)
+ GLOB.cameranet.remove_camera(src)
GLOB.cameranet.cameras -= src
var/area/our_area = get_area(src)
if(our_area) // We should probably send out the warning alarms if this doesn't exist, because this should always have an area!
@@ -134,7 +134,7 @@
/obj/machinery/camera/proc/setViewRange(num = CAMERA_VIEW_DISTANCE)
view_range = num
- GLOB.cameranet.updateVisibility(src, 0)
+ GLOB.cameranet.update_visibility(src, 0)
/obj/machinery/camera/singularity_pull(S, current_size)
if(status && current_size >= STAGE_FIVE) // If the singulo is strong enough to pull anchored objects and the camera is still active, turn off the camera as it gets ripped off the wall.
@@ -192,7 +192,7 @@
to_chat(U, "You hold \the [itemname] up to the camera ...")
U.changeNext_move(CLICK_CD_MELEE)
for(var/mob/O in GLOB.player_list)
- if(isAI(O))
+ if(is_ai(O))
var/mob/living/silicon/ai/AI = O
if(AI.control_disabled || (AI.stat == DEAD))
return
@@ -415,7 +415,7 @@
user.overlay_fullscreen("remote_view", /atom/movable/screen/fullscreen/stretch/impaired, 2)
/obj/machinery/camera/update_remote_sight(mob/living/user)
- if(isXRay() && isAI(user))
+ if(isXRay() && is_ai(user))
user.sight |= (SEE_TURFS|SEE_MOBS|SEE_OBJS)
user.see_in_dark = max(user.see_in_dark, 8)
user.lighting_alpha = LIGHTING_PLANE_ALPHA_MOSTLY_INVISIBLE
@@ -446,5 +446,5 @@
return
SEND_SIGNAL(src, COMSIG_CAMERA_MOVED, prev_turf)
- GLOB.cameranet.updatePortableCamera(src, prev_turf)
+ GLOB.cameranet.update_portable_camera(src, prev_turf)
prev_turf = get_turf(src)
diff --git a/code/game/machinery/camera/camera_presets.dm b/code/game/machinery/camera/camera_presets.dm
index 36a39afc6c2..34f90ce2f40 100644
--- a/code/game/machinery/camera/camera_presets.dm
+++ b/code/game/machinery/camera/camera_presets.dm
@@ -146,7 +146,7 @@
assembly.upgrades.Add(new /obj/item/analyzer(assembly))
setPowerUsage()
//Update what it can see.
- GLOB.cameranet.updateVisibility(src, 0)
+ GLOB.cameranet.update_visibility(src, 0)
// 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()
diff --git a/code/game/machinery/camera/motion.dm b/code/game/machinery/camera/motion.dm
index 5f2e83b11a2..e3b57014330 100644
--- a/code/game/machinery/camera/motion.dm
+++ b/code/game/machinery/camera/motion.dm
@@ -22,7 +22,7 @@
return localMotionTargets
/obj/machinery/camera/proc/newTarget(mob/target)
- if(isAI(target))
+ if(is_ai(target))
return FALSE
if(isbot(target)) //No armsky, you don't get to set off the motion alarm constantly
return FALSE
diff --git a/code/game/machinery/camera/tracking.dm b/code/game/machinery/camera/tracking.dm
index 92f39c2a0d3..9c1a491b6fc 100644
--- a/code/game/machinery/camera/tracking.dm
+++ b/code/game/machinery/camera/tracking.dm
@@ -41,7 +41,7 @@
return 0
var/obj/machinery/camera/C = track.cameras[camera]
- src.eyeobj.setLoc(C)
+ src.eyeobj.set_loc(C)
return
@@ -104,18 +104,18 @@
ai_actual_track(target)
/mob/living/silicon/ai/proc/ai_cancel_tracking(forced = 0)
- if(!cameraFollow)
+ if(!camera_follow)
return
to_chat(src, "Follow camera mode [forced ? "terminated" : "ended"].")
- cameraFollow = null
+ camera_follow = null
/mob/living/silicon/ai/proc/ai_actual_track(mob/living/target, doubleclick = FALSE)
if(!istype(target))
return
var/mob/living/silicon/ai/U = usr
- U.cameraFollow = target
+ U.camera_follow = target
U.tracking = TRUE
to_chat(U, "Attempting to track [target.get_visible_name()]...")
@@ -126,20 +126,20 @@
if(target.is_jammed())
to_chat(U, "Unable to track [target.get_visible_name()]...")
- U.cameraFollow = null
+ U.camera_follow = null
return
if(!target || !target.can_track(usr))
to_chat(U, "Target is not near any active cameras.")
- U.cameraFollow = null
+ U.camera_follow = null
return
to_chat(U, "Now tracking [target.get_visible_name()] on camera.")
var/cameraticks = 0
spawn(0)
- while(U.cameraFollow == target)
- if(U.cameraFollow == null)
+ while(U.camera_follow == target)
+ if(U.camera_follow == null)
return
if(!target.can_track(usr))
@@ -148,7 +148,7 @@
to_chat(U, "Target is not near any active cameras. Attempting to reacquire...")
cameraticks++
if(cameraticks > 9)
- U.cameraFollow = null
+ U.camera_follow = null
to_chat(U, "Unable to reacquire, cancelling track...")
U.tracking = FALSE
return
@@ -161,11 +161,11 @@
U.tracking = FALSE
if(U.eyeobj)
- U.eyeobj.setLoc(get_turf(target))
+ U.eyeobj.set_loc(get_turf(target))
else
view_core()
- U.cameraFollow = null
+ U.camera_follow = null
return
sleep(10)
@@ -175,9 +175,9 @@
return 0
if(isrobot(M))
var/mob/living/silicon/robot/R = M
- if(!(R.camera && R.camera.can_use()) && !GLOB.cameranet.checkCameraVis(M))
+ if(!(R.camera && R.camera.can_use()) && !GLOB.cameranet.check_camera_vis(M))
return 0
- else if(!GLOB.cameranet.checkCameraVis(M))
+ else if(!GLOB.cameranet.check_camera_vis(M))
return 0
return 1
@@ -186,7 +186,7 @@
return
if(!src.can_use())
return
- user.eyeobj.setLoc(get_turf(src))
+ user.eyeobj.set_loc(get_turf(src))
/mob/living/silicon/ai/attack_ai(mob/user)
diff --git a/code/game/machinery/computer/camera_advanced.dm b/code/game/machinery/computer/camera_advanced.dm
index 8c09419e916..a920236b48d 100644
--- a/code/game/machinery/computer/camera_advanced.dm
+++ b/code/game/machinery/computer/camera_advanced.dm
@@ -3,7 +3,7 @@
desc = "Used to access the various cameras on the station."
icon_screen = "cameras"
icon_keyboard = "security_key"
- var/mob/camera/ai_eye/remote/eyeobj
+ var/mob/camera/eye/eyeobj
var/mob/living/carbon/human/current_user = null
var/list/networks = list("SS13")
var/datum/action/innate/camera_off/off_action = new
@@ -11,8 +11,8 @@
var/list/actions = list()
/obj/machinery/computer/camera_advanced/proc/CreateEye()
- eyeobj = new()
- eyeobj.origin = src
+ eyeobj = new /mob/camera/eye/syndicate(loc, name, src, current_user)
+ give_eye_control(current_user)
/obj/machinery/computer/camera_advanced/proc/GrantActions(mob/living/user)
if(off_action)
@@ -25,19 +25,17 @@
jump_action.Grant(user)
actions += jump_action
-/obj/machinery/computer/camera_advanced/proc/remove_eye_control(mob/living/user)
- if(!user)
+/obj/machinery/computer/camera_advanced/proc/RemoveActions()
+ if(!istype(current_user))
return
for(var/V in actions)
var/datum/action/A = V
- A.Remove(user)
+ A.Remove(current_user)
actions.Cut()
- if(user.client)
- user.reset_perspective(null)
- eyeobj.RemoveImages()
- eyeobj.eye_user = null
- user.remote_control = null
+/obj/machinery/computer/camera_advanced/proc/remove_eye_control(mob/living/user)
+ RemoveActions()
+ eyeobj.release_control()
current_user = null
remove_eye(user)
playsound(src, 'sound/machines/terminal_off.ogg', 25, 0)
@@ -57,7 +55,7 @@
return ..()
/obj/machinery/computer/camera_advanced/proc/remove_eye(mob/M)
- if(M == current_user)
+ if(istype(M) && M == current_user)
remove_eye_control(M)
/obj/machinery/computer/camera_advanced/attack_hand(mob/user)
@@ -68,102 +66,17 @@
return
if(..())
return
+ current_user = user
if(!eyeobj)
CreateEye()
-
- if(!eyeobj.eye_initialized)
- var/camera_location
- for(var/obj/machinery/camera/C in GLOB.cameranet.cameras)
- if(!C.can_use())
- continue
- if(length(C.network & networks))
- camera_location = get_turf(C)
- break
- if(camera_location)
- eyeobj.eye_initialized = 1
- give_eye_control(user)
- eyeobj.setLoc(camera_location)
- else
- // An abberant case - silent failure is obnoxious
- to_chat(user, "ERROR: No linked and active camera network found.")
- remove_eye(user)
else
give_eye_control(user)
- eyeobj.setLoc(eyeobj.loc)
-
+ eyeobj.set_loc(eyeobj.loc)
/obj/machinery/computer/camera_advanced/proc/give_eye_control(mob/user)
+ eyeobj.give_control(user)
GrantActions(user)
- current_user = user
- eyeobj.eye_user = user
- eyeobj.name = "Camera Eye ([user.name])"
- user.remote_control = eyeobj
- user.reset_perspective(eyeobj)
-
-/mob/camera/ai_eye/remote
- name = "Inactive Camera Eye"
- // Abductors dont trigger the Ai Detector
- ai_detector_visible = FALSE
- var/sprint = 10
- var/cooldown = 0
- var/acceleration = 1
- var/mob/living/carbon/human/eye_user = null
- var/obj/machinery/computer/camera_advanced/origin
- var/eye_initialized = 0
- var/visible_icon = 0
- var/image/user_image = null
-
-/mob/camera/ai_eye/remote/Destroy()
- eye_user = null
- origin = null
- return ..()
-
-/mob/camera/ai_eye/remote/RemoveImages()
- ..()
- if(visible_icon)
- var/client/C = GetViewerClient()
- if(C)
- C.images -= user_image
-
-/mob/camera/ai_eye/remote/GetViewerClient()
- if(eye_user)
- return eye_user.client
- return null
-
-/mob/camera/ai_eye/remote/setLoc(T)
- if(eye_user)
- if(!isturf(eye_user.loc))
- return
- T = get_turf(T)
- var/old_loc = loc
- loc = T
- Moved(old_loc, get_dir(old_loc, loc))
- if(use_static)
- GLOB.cameranet.visibility(src, GetViewerClient())
- if(visible_icon)
- if(eye_user.client)
- eye_user.client.images -= user_image
- user_image = image(icon,loc,icon_state,FLY_LAYER)
- eye_user.client.images += user_image
-
-/mob/camera/ai_eye/remote/relaymove(mob/user,direct)
- var/initial = initial(sprint)
- var/max_sprint = 50
-
- if(cooldown && cooldown < world.timeofday) // 3 seconds
- sprint = initial
-
- for(var/i = 0; i < max(sprint, initial); i += 20)
- var/turf/step = get_turf(get_step(src, direct))
- if(step)
- src.setLoc(step)
-
- cooldown = world.timeofday + 5
- if(acceleration)
- sprint = min(sprint + 0.5, max_sprint)
- else
- sprint = initial
/datum/action/innate/camera_off
name = "End Camera View"
@@ -173,7 +86,7 @@
if(!target || !iscarbon(target))
return
var/mob/living/carbon/C = target
- var/mob/camera/ai_eye/remote/remote_eye = C.remote_control
+ var/mob/camera/eye/remote_eye = C.remote_control
var/obj/machinery/computer/camera_advanced/console = remote_eye.origin
console.remove_eye_control(target)
@@ -185,7 +98,7 @@
if(!target || !iscarbon(target))
return
var/mob/living/carbon/C = target
- var/mob/camera/ai_eye/remote/remote_eye = C.remote_control
+ var/mob/camera/eye/remote_eye = C.remote_control
var/obj/machinery/computer/camera_advanced/origin = remote_eye.origin
var/list/L = list()
@@ -209,7 +122,7 @@
playsound(origin, "terminal_type", 25, 0)
if(final)
playsound(origin, 'sound/machines/terminal_prompt_confirm.ogg', 25, FALSE)
- remote_eye.setLoc(get_turf(final))
+ remote_eye.set_loc(get_turf(final))
C.overlay_fullscreen("flash", /atom/movable/screen/fullscreen/stretch/flash/noise)
C.clear_fullscreen("flash", 3) //Shorter flash than normal since it's an ~~advanced~~ console!
else
diff --git a/code/game/machinery/computer/camera_console.dm b/code/game/machinery/computer/camera_console.dm
index dfb4e1f08ea..1bcf9828003 100644
--- a/code/game/machinery/computer/camera_console.dm
+++ b/code/game/machinery/computer/camera_console.dm
@@ -173,7 +173,7 @@
ui_interact(user)
/obj/machinery/computer/security/attack_ai(mob/user)
- if(isAI(user))
+ if(is_ai(user))
to_chat(user, "You realise it's kind of stupid to access a camera console when you have the entire camera network at your metaphorical fingertips.")
return
diff --git a/code/game/machinery/computer/communications.dm b/code/game/machinery/computer/communications.dm
index 2870683a5c3..83ce0497dcc 100644
--- a/code/game/machinery/computer/communications.dm
+++ b/code/game/machinery/computer/communications.dm
@@ -134,7 +134,7 @@
setMenuState(ui.user, COMM_SCREEN_MAIN)
if("newalertlevel")
- if(isAI(ui.user) || isrobot(ui.user))
+ if(is_ai(ui.user) || isrobot(ui.user))
to_chat(ui.user, "Firewalls prevent you from changing the alert level.")
return
else if(ADMIN_CHECK(ui.user))
@@ -184,7 +184,7 @@
setMenuState(ui.user, COMM_SCREEN_MAIN)
if("cancelshuttle")
- if(isAI(ui.user) || isrobot(ui.user))
+ if(is_ai(ui.user) || isrobot(ui.user))
to_chat(ui.user, "Firewalls prevent you from recalling the shuttle.")
return
var/response = tgui_alert(usr, "Are you sure you wish to recall the shuttle?", "Confirm", list("Yes", "No"))
@@ -418,7 +418,7 @@
/obj/machinery/computer/communications/ui_data(mob/user)
var/list/data = list()
- data["is_ai"] = isAI(user) || isrobot(user)
+ data["is_ai"] = is_ai(user) || isrobot(user)
data["noauthbutton"] = !ishuman(user)
data["menu_state"] = data["is_ai"] ? ai_menu_state : menu_state
data["emagged"] = emagged
@@ -515,19 +515,19 @@
return data
/obj/machinery/computer/communications/proc/setCurrentMessage(mob/user, value)
- if(isAI(user) || isrobot(user))
+ if(is_ai(user) || isrobot(user))
aicurrmsg = value
else
currmsg = value
/obj/machinery/computer/communications/proc/getCurrentMessage(mob/user)
- if(isAI(user) || isrobot(user))
+ if(is_ai(user) || isrobot(user))
return aicurrmsg
else
return currmsg
/obj/machinery/computer/communications/proc/setMenuState(mob/user, value)
- if(isAI(user) || isrobot(user))
+ if(is_ai(user) || isrobot(user))
ai_menu_state=value
else
menu_state=value
diff --git a/code/game/machinery/computer/message_monitor.dm b/code/game/machinery/computer/message_monitor.dm
index fd66ec23513..d89bd4eba62 100644
--- a/code/game/machinery/computer/message_monitor.dm
+++ b/code/game/machinery/computer/message_monitor.dm
@@ -129,7 +129,7 @@
else
for(var/n = ++i; n <= optioncount; n++)
dat += " [n]. ---------------
"
- if((isAI(user) || isrobot(user)) && (user.mind.special_role && user.mind.is_original_mob(user)))
+ if((is_ai(user) || isrobot(user)) && (user.mind.special_role && user.mind.is_original_mob(user)))
//Malf/Traitor AIs can bruteforce into the system to gain the Key.
dat += "*&@#. Bruteforce Key
"
else
@@ -159,7 +159,7 @@
dat += ""
//Hacking screen.
if(2)
- if(isAI(user) || isrobot(user))
+ if(is_ai(user) || isrobot(user))
dat += "Brute-forcing for server key.
It will take 20 seconds for every character that the password has."
dat += "In the meantime, this console can reveal your true intentions if you let someone access it. Make sure no humans enter the room during that time."
else
@@ -349,7 +349,7 @@
//Hack the Console to get the password
if(href_list["hack"])
- if((isAI(usr) || isrobot(usr)) && (usr.mind.special_role && usr.mind.is_original_mob(usr)))
+ if((is_ai(usr) || isrobot(usr)) && (usr.mind.special_role && usr.mind.is_original_mob(usr)))
src.hacking = 1
src.screen = 2
src.icon_screen = hack_icon
diff --git a/code/game/machinery/computer/robot_control.dm b/code/game/machinery/computer/robot_control.dm
index f15a9014be0..d9f96e0a991 100644
--- a/code/game/machinery/computer/robot_control.dm
+++ b/code/game/machinery/computer/robot_control.dm
@@ -66,7 +66,7 @@
return FALSE
if(!console_shows(R))
return FALSE
- if(isAI(user))
+ if(is_ai(user))
if(R.connected_ai != user)
if(telluserwhy)
to_chat(user, "AIs can only control cyborgs which are linked to them.")
@@ -107,7 +107,7 @@
return FALSE
if(user.can_admin_interact())
return TRUE
- if(!isAI(user))
+ if(!is_ai(user))
return FALSE
return (user.mind.special_role && user.mind.is_original_mob(user))
diff --git a/code/game/machinery/dance_machine.dm b/code/game/machinery/dance_machine.dm
index f5a4cf90752..c2389895e0c 100644
--- a/code/game/machinery/dance_machine.dm
+++ b/code/game/machinery/dance_machine.dm
@@ -95,7 +95,7 @@
if(!anchored)
to_chat(user,"This device must be anchored by a wrench!")
return
- if(!Adjacent(user) && !isAI(user))
+ if(!Adjacent(user) && !is_ai(user))
return
user.set_machine(src)
var/list/dat = list()
diff --git a/code/game/machinery/doors/door.dm b/code/game/machinery/doors/door.dm
index 3ce720c1f8c..c89fff93af6 100644
--- a/code/game/machinery/doors/door.dm
+++ b/code/game/machinery/doors/door.dm
@@ -466,7 +466,7 @@
/obj/machinery/door/proc/update_freelook_sight()
if(!glass && GLOB.cameranet)
- GLOB.cameranet.updateVisibility(src, 0)
+ GLOB.cameranet.update_visibility(src, 0)
/obj/machinery/door/proc/check_unres() //unrestricted sides. This overlay indicates which directions the player can access even without an ID
if(hasPower() && unres_sides)
diff --git a/code/game/machinery/hologram.dm b/code/game/machinery/hologram.dm
index c57b10ff4ea..118340d2df8 100644
--- a/code/game/machinery/hologram.dm
+++ b/code/game/machinery/hologram.dm
@@ -92,6 +92,7 @@ GLOBAL_LIST_EMPTY(holopads)
var/ringing = FALSE
/// Whether or not the user is currently selecting where to send their call.
var/dialling_input = FALSE
+ var/mob/camera/eye/hologram/eye
/obj/machinery/hologram/holopad/Initialize(mapload)
. = ..()
@@ -190,7 +191,7 @@ GLOBAL_LIST_EMPTY(holopads)
/obj/machinery/hologram/holopad/AltClick(mob/living/carbon/human/user)
if(..())
return
- if(isAI(user))
+ if(is_ai(user))
hangup_all_calls()
return
@@ -240,7 +241,7 @@ GLOBAL_LIST_EMPTY(holopads)
popup.open()
/obj/machinery/hologram/holopad/Topic(href, href_list)
- if(..() || isAI(usr))
+ if(..() || is_ai(usr))
return
add_fingerprint(usr)
if(stat & NOPOWER)
@@ -319,7 +320,7 @@ GLOBAL_LIST_EMPTY(holopads)
I don't need to check for client since they're clicking on an object.
This may change in the future but for now will suffice.*/
else if(ai.eyeobj.loc != loc)//Set client eye on the object if it's not already.
- ai.eyeobj.setLoc(get_turf(src))
+ ai.eyeobj.set_loc(get_turf(src))
else if(!LAZYLEN(masters) || !masters[ai])//If there is no hologram, possibly make one.
activate_holo(ai, 1)
else//If there is a hologram, remove it.
@@ -358,7 +359,7 @@ GLOBAL_LIST_EMPTY(holopads)
//Try to transfer hologram to another pad that can project on T
/obj/machinery/hologram/holopad/proc/transfer_to_nearby_pad(turf/T, mob/holo_owner)
- if(!isAI(holo_owner))
+ if(!is_ai(holo_owner))
return
for(var/pad in GLOB.holopads)
var/obj/machinery/hologram/holopad/another = pad
@@ -375,7 +376,7 @@ GLOBAL_LIST_EMPTY(holopads)
if(QDELETED(user) || user.incapacitated() || !user.client)
return FALSE
- if(isAI(user))
+ if(is_ai(user))
var/mob/living/silicon/ai/AI = user
if(!AI.current)
return FALSE
@@ -383,8 +384,8 @@ GLOBAL_LIST_EMPTY(holopads)
//Can we display holos there
//Area check instead of line of sight check because this is a called a lot if AI wants to move around.
-/obj/machinery/hologram/holopad/proc/validate_location(turf/T,check_los = FALSE)
- if(T.z == z && get_dist(T, src) <= holo_range && T.loc == get_area(src))
+/obj/machinery/hologram/holopad/proc/validate_location(turf/T)
+ if(T.z == z && (get_dist(T, src) <= holo_range) && T.loc == get_area(src))
return TRUE
return FALSE
@@ -418,7 +419,7 @@ GLOBAL_LIST_EMPTY(holopads)
return
var/obj/effect/overlay/holo_pad_hologram/hologram = new(loc)//Spawn a blank effect at the location.
- if(isAI(user))
+ if(is_ai(user))
hologram.icon = AI.holo_icon
else //make it like real life
if(isrobot(user))
@@ -438,6 +439,7 @@ GLOBAL_LIST_EMPTY(holopads)
hologram.set_light(2) //hologram lighting
move_hologram()
+ eye = new /mob/camera/eye/hologram(src, user.name, src, user)
set_holo(user, hologram)
if(!masters[user])//If there is not already a hologram.
@@ -490,6 +492,8 @@ For the other part of the code, check silicon say.dm. Particularly robot talk.*/
/obj/machinery/hologram/holopad/proc/set_holo(mob/living/user, obj/effect/overlay/holo_pad_hologram/h)
+ eye = user.remote_control
+ eye.holopad = src
masters[user] = h
holorays[user] = new /obj/effect/overlay/holoray(loc)
var/mob/living/silicon/ai/AI = user
@@ -501,10 +505,13 @@ For the other part of the code, check silicon say.dm. Particularly robot talk.*/
/obj/machinery/hologram/holopad/proc/clear_holo(mob/living/user)
qdel(masters[user]) // Get rid of user's hologram
+ if(!QDELETED(eye))
+ QDEL_NULL(eye)
unset_holo(user)
return TRUE
/obj/machinery/hologram/holopad/proc/unset_holo(mob/living/user)
+ eye = null
var/mob/living/silicon/ai/AI = user
if(istype(AI) && AI.current == src)
AI.current = null
diff --git a/code/game/machinery/magnetic_module.dm b/code/game/machinery/magnetic_module.dm
index 5f50939ffd1..7e0e012b648 100644
--- a/code/game/machinery/magnetic_module.dm
+++ b/code/game/machinery/magnetic_module.dm
@@ -165,7 +165,7 @@
step_towards(M, center)
for(var/mob/living/silicon/S in orange(magnetic_field, center))
- if(isAI(S)) continue
+ if(is_ai(S)) continue
step_towards(S, center)
use_power(electricity_level * 5)
diff --git a/code/game/machinery/poolcontroller.dm b/code/game/machinery/poolcontroller.dm
index 46df33dfc23..71cc230dba3 100644
--- a/code/game/machinery/poolcontroller.dm
+++ b/code/game/machinery/poolcontroller.dm
@@ -102,7 +102,7 @@
QDEL_IN(decal, 25)
/obj/machinery/poolcontroller/proc/handleTemp(mob/M)
- if(!M || isAIEye(M) || issilicon(M) || isobserver(M) || M.stat == DEAD)
+ if(!M || is_ai_eye(M) || issilicon(M) || isobserver(M) || M.stat == DEAD)
return
M.water_act(100, temperature, src)//leave temp at 0, we handle it in the switch. oh wait
switch(temperature) //Apply different effects based on what the temperature is set to.
diff --git a/code/game/machinery/portable_turret.dm b/code/game/machinery/portable_turret.dm
index f97faf4f0ad..b0156847211 100644
--- a/code/game/machinery/portable_turret.dm
+++ b/code/game/machinery/portable_turret.dm
@@ -189,7 +189,7 @@ GLOBAL_LIST_EMPTY(turret_icons)
/obj/machinery/porta_turret/proc/isLocked(mob/user)
if(HasController())
return TRUE
- if(isrobot(user) || isAI(user))
+ if(isrobot(user) || is_ai(user))
if(ailock)
to_chat(user, "There seems to be a firewall preventing you from accessing this device.")
return TRUE
diff --git a/code/game/machinery/quantum_pad.dm b/code/game/machinery/quantum_pad.dm
index f5f31efc6fb..7d85686548a 100644
--- a/code/game/machinery/quantum_pad.dm
+++ b/code/game/machinery/quantum_pad.dm
@@ -147,7 +147,7 @@
return TRUE
/obj/machinery/quantumpad/attack_hand(mob/user)
- if(isAI(user))
+ if(is_ai(user))
return
if(!check_usable(user))
return
@@ -161,13 +161,13 @@
if(!istype(AI))
return
if(AI.eyeobj.loc != loc)
- AI.eyeobj.setLoc(get_turf(loc))
+ AI.eyeobj.set_loc(get_turf(loc))
return
if(!check_usable(user))
return
var/turf/T = get_turf(linked_pad)
- if(GLOB.cameranet && GLOB.cameranet.checkTurfVis(T))
- AI.eyeobj.setLoc(T)
+ if(GLOB.cameranet && GLOB.cameranet.check_turf_vis(T))
+ AI.eyeobj.set_loc(T)
else
to_chat(user, "Linked pad is not on or near any active cameras on the station.")
diff --git a/code/game/machinery/teleporter.dm b/code/game/machinery/teleporter.dm
index da4fafec5c3..d8b133a3eb2 100644
--- a/code/game/machinery/teleporter.dm
+++ b/code/game/machinery/teleporter.dm
@@ -334,8 +334,8 @@
Prevents AI from using the teleporter, prints out failure messages for clarity
*/
/obj/machinery/teleport/proc/blockAI(atom/A)
- if(isAI(A) || istype(A, /obj/structure/ai_core))
- if(isAI(A))
+ if(is_ai(A) || istype(A, /obj/structure/ai_core))
+ if(is_ai(A))
var/mob/living/silicon/ai/T = A
if(T.allow_teleporter)
return FALSE
diff --git a/code/game/machinery/turret_control.dm b/code/game/machinery/turret_control.dm
index ea9bf127181..bdc87cd7d9c 100644
--- a/code/game/machinery/turret_control.dm
+++ b/code/game/machinery/turret_control.dm
@@ -88,7 +88,7 @@
update_icon(UPDATE_ICON_STATE)
/obj/machinery/turretid/proc/isLocked(mob/user)
- if(isrobot(user) || isAI(user))
+ if(isrobot(user) || is_ai(user))
if(ailock)
to_chat(user, "There seems to be a firewall preventing you from accessing this device.")
return TRUE
diff --git a/code/game/mecha/mecha.dm b/code/game/mecha/mecha.dm
index a0719e38671..df4cad6e001 100644
--- a/code/game/mecha/mecha.dm
+++ b/code/game/mecha/mecha.dm
@@ -660,7 +660,7 @@
occupant.SetSleeping(destruction_sleep_duration)
go_out()
for(var/mob/M in src) //Let's just be ultra sure
- if(isAI(M))
+ if(is_ai(M))
var/mob/living/silicon/ai/AI = M //AIs are loaded into the mech computer itself. When the mech dies, so does the AI. They can be recovered with an AI card from the wreck.
AI.gib() //No wreck, no AI to recover
else
@@ -949,7 +949,7 @@
/////////////////////////////////////
/obj/mecha/attack_ai(mob/living/silicon/ai/user)
- if(!isAI(user))
+ if(!is_ai(user))
return
//Allows the Malf to scan a mech's status and loadout, helping it to decide if it is a worthy chariot.
if(user.can_dominate_mechs)
@@ -987,7 +987,7 @@
to_chat(user, "[name] must have maintenance protocols active in order to allow a transfer.")
return
AI = occupant
- if(!AI || !isAI(occupant)) //Mech does not have an AI for a pilot
+ if(!AI || !is_ai(occupant)) //Mech does not have an AI for a pilot
to_chat(user, "No AI detected in the [name] onboard computer.")
return
if(AI.mind.special_role) //Malf AIs cannot leave mechs. Except through death.
@@ -1042,6 +1042,7 @@
AI.cancel_camera()
AI.controlled_mech = src
AI.remote_control = src
+ AI.reset_perspective(src)
AI.can_shunt = FALSE //ONE AI ENTERS. NO AI LEAVES.
to_chat(AI, "[AI.can_dominate_mechs ? "Takeover of [name] complete! You are now permanently loaded onto the onboard computer. Do not attempt to leave the station sector!" \
: "You have been uploaded to a mech's onboard computer."]")
@@ -1273,7 +1274,7 @@
/obj/mecha/Exited(atom/movable/M, direction)
var/new_loc = get_step(M, direction)
if(occupant && occupant == M) // The occupant exited the mech without calling go_out()
- if(!isAI(occupant)) //This causes carded AIS to gib, so we do not want this to be called during carding.
+ if(!is_ai(occupant)) //This causes carded AIS to gib, so we do not want this to be called during carding.
go_out(1, new_loc)
/obj/mecha/proc/go_out(forced, atom/newloc = loc)
@@ -1292,7 +1293,7 @@
var/mob/living/brain/brain = occupant
RemoveActions(brain)
mob_container = brain.container
- else if(isAI(occupant))
+ else if(is_ai(occupant))
var/mob/living/silicon/ai/AI = occupant
if(forced)//This should only happen if there are multiple AIs in a round, and at least one is Malf.
RemoveActions(occupant)
@@ -1306,7 +1307,11 @@
return
to_chat(AI, "Returning to core...")
AI.controlled_mech = null
- AI.remote_control = null
+ if(istype(AI.eyeobj))
+ AI.remote_control = AI.eyeobj
+ AI.reset_perspective(AI.eyeobj)
+ else
+ AI.eyeobj = new /mob/camera/eye/ai(loc, AI.name, AI, AI)
RemoveActions(occupant, 1)
mob_container = AI
newloc = get_turf(AI.linked_core)
@@ -1581,7 +1586,7 @@
/obj/mecha/obj_destruction()
if(wreckage)
var/mob/living/silicon/ai/AI
- if(isAI(occupant))
+ if(is_ai(occupant))
AI = occupant
occupant = null
var/obj/structure/mecha_wreckage/WR = new wreckage(loc, AI)
diff --git a/code/game/objects/effects/effect_system/effect_system.dm b/code/game/objects/effects/effect_system/effect_system.dm
index 246fd64e963..1a6ee994609 100644
--- a/code/game/objects/effects/effect_system/effect_system.dm
+++ b/code/game/objects/effects/effect_system/effect_system.dm
@@ -13,11 +13,11 @@ would spawn and follow the beaker, even if it is carried or thrown.
/obj/effect/particle_effect/New()
..()
if(SSticker)
- GLOB.cameranet.updateVisibility(src)
+ GLOB.cameranet.update_visibility(src)
/obj/effect/particle_effect/Destroy()
if(SSticker)
- GLOB.cameranet.updateVisibility(src)
+ GLOB.cameranet.update_visibility(src)
return ..()
/datum/effect_system
diff --git a/code/game/objects/items/devices/radio/headset.dm b/code/game/objects/items/devices/radio/headset.dm
index 0f0da313d3d..af74b6cb5eb 100644
--- a/code/game/objects/items/devices/radio/headset.dm
+++ b/code/game/objects/items/devices/radio/headset.dm
@@ -71,7 +71,7 @@
var/mob/living/carbon/human/H = loc
if(H.l_ear == src || H.r_ear == src)
return ..()
- else if(isanimal(loc) || isAI(loc))
+ else if(isanimal(loc) || is_ai(loc))
return ..()
return FALSE
diff --git a/code/game/objects/items/devices/radio/radio_objects.dm b/code/game/objects/items/devices/radio/radio_objects.dm
index d505e3aa64d..98a12cb9145 100644
--- a/code/game/objects/items/devices/radio/radio_objects.dm
+++ b/code/game/objects/items/devices/radio/radio_objects.dm
@@ -411,7 +411,7 @@ GLOBAL_LIST_EMPTY(deadsay_radio_systems)
jobname = "No id"
// --- AI ---
- else if(isAI(M))
+ else if(is_ai(M))
jobname = "AI"
// --- Cyborg ---
diff --git a/code/game/objects/items/devices/scanners.dm b/code/game/objects/items/devices/scanners.dm
index b45a8cf5022..395cca3a964 100644
--- a/code/game/objects/items/devices/scanners.dm
+++ b/code/game/objects/items/devices/scanners.dm
@@ -497,7 +497,7 @@ SLIME SCANNER
scan_type = "robot"
else if(ishuman(M))
scan_type = "prosthetics"
- else if(isAI(M))
+ else if(is_ai(M))
scan_type = "ai"
else
to_chat(user, "You can't analyze non-robotic things!")
diff --git a/code/game/objects/items/tools/multitool.dm b/code/game/objects/items/tools/multitool.dm
index 5f7187c9a0c..42d477cf7f0 100644
--- a/code/game/objects/items/tools/multitool.dm
+++ b/code/game/objects/items/tools/multitool.dm
@@ -94,15 +94,15 @@
/obj/item/multitool/ai_detect/proc/multitool_detect()
var/turf/our_turf = get_turf(src)
for(var/mob/living/silicon/ai/AI in GLOB.ai_list)
- if(AI.cameraFollow == src)
+ if(AI.camera_follow == src)
detect_state = PROXIMITY_ON_SCREEN
break
- if(!detect_state && GLOB.cameranet.chunkGenerated(our_turf.x, our_turf.y, our_turf.z))
- var/datum/camerachunk/chunk = GLOB.cameranet.getCameraChunk(our_turf.x, our_turf.y, our_turf.z)
+ if(!detect_state && GLOB.cameranet.chunk_generated(our_turf.x, our_turf.y, our_turf.z))
+ var/datum/camerachunk/chunk = GLOB.cameranet.get_camera_chunk(our_turf.x, our_turf.y, our_turf.z)
if(chunk)
if(length(chunk.seenby))
- for(var/mob/camera/ai_eye/A in chunk.seenby)
+ for(var/mob/camera/eye/ai/A in chunk.seenby)
//Checks if the A is to be detected or not
if(!A.ai_detector_visible)
continue
diff --git a/code/game/objects/items/toys.dm b/code/game/objects/items/toys.dm
index 0b4d7a1b1b1..f9b0a46abc2 100644
--- a/code/game/objects/items/toys.dm
+++ b/code/game/objects/items/toys.dm
@@ -515,7 +515,7 @@
..()
playsound(src, 'sound/effects/meteorimpact.ogg', 40, 1)
for(var/mob/M in range(10, src))
- if(!M.stat && !isAI(M))\
+ if(!M.stat && !is_ai(M))\
shake_camera(M, 3, 1)
qdel(src)
@@ -1378,7 +1378,7 @@
playsound(src, 'sound/effects/explosionfar.ogg', 50, FALSE, 0)
flick("bigred_press", src)
for(var/mob/M in range(10, src)) // Checks range
- if(!M.stat && !isAI(M)) // Checks to make sure whoever's getting shaken is alive/not the AI
+ if(!M.stat && !is_ai(M)) // Checks to make sure whoever's getting shaken is alive/not the AI
sleep(8) // Short delay to match up with the explosion sound
shake_camera(M, 2, 1) // Shakes player camera 2 squares for 1 second.
diff --git a/code/game/objects/objs.dm b/code/game/objects/objs.dm
index 635984ca9c5..66661d0d0d4 100644
--- a/code/game/objects/objs.dm
+++ b/code/game/objects/objs.dm
@@ -113,7 +113,7 @@
if(M.client && M.machine == src)
is_in_use = TRUE
src.attack_hand(M)
- if(isAI(usr) || isrobot(usr))
+ if(is_ai(usr) || isrobot(usr))
if(!(usr in nearby))
if(usr.client && usr.machine==src) // && M.machine == src is omitted because if we triggered this by using the dialog, it doesn't matter if our machine changed in between triggering it and this - the dialog is probably still supposed to refresh.
is_in_use = TRUE
diff --git a/code/game/objects/structures.dm b/code/game/objects/structures.dm
index 3b6a8c87633..35f8be4f301 100644
--- a/code/game/objects/structures.dm
+++ b/code/game/objects/structures.dm
@@ -22,7 +22,7 @@
if(smoothing_flags & SMOOTH_CORNERS)
icon_state = ""
if(SSticker)
- GLOB.cameranet.updateVisibility(src)
+ GLOB.cameranet.update_visibility(src)
/obj/structure/Initialize(mapload)
if(!armor)
@@ -34,7 +34,7 @@
/obj/structure/Destroy()
climbers = null
if(SSticker)
- GLOB.cameranet.updateVisibility(src)
+ GLOB.cameranet.update_visibility(src)
if(smoothing_flags & (SMOOTH_CORNERS|SMOOTH_BITMASK))
var/turf/T = get_turf(src)
QUEUE_SMOOTH_NEIGHBORS(T)
diff --git a/code/game/objects/structures/crates_lockers/closets.dm b/code/game/objects/structures/crates_lockers/closets.dm
index 81a88adc6d2..a1e0b163ebf 100644
--- a/code/game/objects/structures/crates_lockers/closets.dm
+++ b/code/game/objects/structures/crates_lockers/closets.dm
@@ -247,7 +247,7 @@
continue
if(M.buckled || M.anchored || M.has_buckled_mobs())
continue
- if(isAI(M))
+ if(is_ai(M))
continue
M.forceMove(src)
diff --git a/code/game/objects/structures/inflatable.dm b/code/game/objects/structures/inflatable.dm
index 1db795432b7..d8e4e975453 100644
--- a/code/game/objects/structures/inflatable.dm
+++ b/code/game/objects/structures/inflatable.dm
@@ -107,7 +107,7 @@
var/is_operating = FALSE
/obj/structure/inflatable/door/attack_ai(mob/user as mob) //those aren't machinery, they're just big fucking slabs of a mineral
- if(isAI(user)) //so the AI can't open it
+ if(is_ai(user)) //so the AI can't open it
return
else if(isrobot(user)) //but cyborgs can
if(get_dist(user,src) <= 1) //not remotely though
diff --git a/code/game/objects/structures/kitchen_spike.dm b/code/game/objects/structures/kitchen_spike.dm
index 4ab47a636f3..26d4692461b 100644
--- a/code/game/objects/structures/kitchen_spike.dm
+++ b/code/game/objects/structures/kitchen_spike.dm
@@ -87,7 +87,7 @@
deconstruct(TRUE)
/obj/structure/kitchenspike/MouseDrop_T(mob/living/victim, mob/living/user)
- if(!user.Adjacent(src) || !user.Adjacent(victim) || isAI(user) || !ismob(victim))
+ if(!user.Adjacent(src) || !user.Adjacent(victim) || is_ai(user) || !ismob(victim))
return
if(isanimal(user) && victim != user)
return // animals cannot put mobs other than themselves onto spikes
diff --git a/code/game/objects/structures/mineral_doors.dm b/code/game/objects/structures/mineral_doors.dm
index 144bf5f747d..e12f73b712d 100644
--- a/code/game/objects/structures/mineral_doors.dm
+++ b/code/game/objects/structures/mineral_doors.dm
@@ -47,7 +47,7 @@
return try_to_operate(user)
/obj/structure/mineral_door/attack_ai(mob/user) //those aren't machinery, they're just big fucking slabs of a mineral
- if(isAI(user)) //so the AI can't open it
+ if(is_ai(user)) //so the AI can't open it
return
else if(isrobot(user) && Adjacent(user)) //but cyborgs can, but not remotely
return try_to_operate(user)
diff --git a/code/game/turfs/turf.dm b/code/game/turfs/turf.dm
index 09341eaea35..55d44814975 100644
--- a/code/game/turfs/turf.dm
+++ b/code/game/turfs/turf.dm
@@ -118,7 +118,7 @@
SET_BITFLAG_LIST(canSmoothWith)
if(smoothing_flags & (SMOOTH_CORNERS|SMOOTH_BITMASK))
QUEUE_SMOOTH(src)
- visibilityChanged()
+ visibility_changed()
for(var/atom/movable/AM in src)
Entered(AM)
@@ -150,7 +150,7 @@
qdel(A)
return
REMOVE_FROM_SMOOTH_QUEUE(src)
- visibilityChanged()
+ visibility_changed()
QDEL_LIST_CONTENTS(blueprint_data)
initialized = FALSE
bound_air = null
@@ -480,9 +480,9 @@
ChangeTurf(baseturf)
return 2
-/turf/proc/visibilityChanged()
+/turf/proc/visibility_changed()
if(SSticker)
- GLOB.cameranet.updateVisibility(src)
+ GLOB.cameranet.update_visibility(src)
/turf/attack_by(obj/item/attacking, mob/user, params)
if(..())
diff --git a/code/game/verbs/ooc.dm b/code/game/verbs/ooc.dm
index f3fc59dfa41..b7a1ace80fb 100644
--- a/code/game/verbs/ooc.dm
+++ b/code/game/verbs/ooc.dm
@@ -177,10 +177,10 @@ GLOBAL_VAR_INIT(admin_ooc_colour, "#b82e00")
if(target.mob in heard)
send = 1
- if(isAI(target.mob))
+ if(is_ai(target.mob))
prefix = " (Core)"
- else if(isAI(target.mob)) // Special case
+ else if(is_ai(target.mob)) // Special case
var/mob/living/silicon/ai/A = target.mob
if(A.eyeobj in hearers(7, source))
send = 1
diff --git a/code/modules/admin/admin_verbs.dm b/code/modules/admin/admin_verbs.dm
index 0e80d8806f2..f12dd40466d 100644
--- a/code/modules/admin/admin_verbs.dm
+++ b/code/modules/admin/admin_verbs.dm
@@ -387,9 +387,9 @@ GLOBAL_LIST_INIT(view_runtimes_verbs, list(
if(ishuman(mob))
var/mob/living/carbon/human/H = mob
H.regenerate_icons() // workaround for #13269
- if(isAI(mob)) // client.mob, built in byond client var
+ if(is_ai(mob)) // client.mob, built in byond client var
var/mob/living/silicon/ai/ai = mob
- ai.eyeobj.setLoc(old_turf)
+ ai.eyeobj.set_loc(old_turf)
else if(isnewplayer(mob))
to_chat(src, "Error: Aghost: Can't admin-ghost whilst in the lobby. Join or observe first.")
else
diff --git a/code/modules/admin/misc_admin_procs.dm b/code/modules/admin/misc_admin_procs.dm
index aee3772ced0..e3349394eba 100644
--- a/code/modules/admin/misc_admin_procs.dm
+++ b/code/modules/admin/misc_admin_procs.dm
@@ -157,7 +157,7 @@ GLOBAL_VAR_INIT(disable_explosions, FALSE)
"}
var/jumptoeye = ""
- if(isAI(M))
+ if(is_ai(M))
var/mob/living/silicon/ai/A = M
if(A.client && A.eyeobj) // No point following clientless AI eyes
jumptoeye = " (Eye)"
@@ -199,7 +199,7 @@ GLOBAL_VAR_INIT(disable_explosions, FALSE)
body += "Corgize | "
//AI / Cyborg
- if(isAI(M))
+ if(is_ai(M))
body += "Is an AI "
else if(ishuman(M))
body += {"Make AI |
@@ -800,7 +800,7 @@ GLOBAL_VAR_INIT(disable_explosions, FALSE)
if(istype(S, /mob/living/silicon/decoy) && !S.client)
continue
ai_number++
- if(isAI(S))
+ if(is_ai(S))
messages += "AI [key_name(S, TRUE)]'s laws:"
else if(isrobot(S))
var/mob/living/silicon/robot/R = S
diff --git a/code/modules/admin/player_panel.dm b/code/modules/admin/player_panel.dm
index eb6c435f6a8..3c1eefa6c07 100644
--- a/code/modules/admin/player_panel.dm
+++ b/code/modules/admin/player_panel.dm
@@ -255,7 +255,7 @@
M_job = "Carbon-based"
else if(issilicon(M)) //silicon
- if(isAI(M))
+ if(is_ai(M))
M_job = "AI"
else if(ispAI(M))
M_job = "pAI"
@@ -298,7 +298,7 @@
M_key = replacetext(M_key, "\\", "")
var/M_eyeUID = ""
- if(isAI(M))
+ if(is_ai(M))
var/mob/living/silicon/ai/A = M
if(A.client && A.eyeobj) // No point following clientless AI eyes
M_eyeUID = "[A.eyeobj.UID()]"
diff --git a/code/modules/admin/topic.dm b/code/modules/admin/topic.dm
index 602e710d128..27340e1c3ea 100644
--- a/code/modules/admin/topic.dm
+++ b/code/modules/admin/topic.dm
@@ -1146,7 +1146,7 @@
if(!ismob(M))
to_chat(usr, "This can only be used on instances of type /mob")
return
- if(isAI(M))
+ if(is_ai(M))
to_chat(usr, "This cannot be used on instances of type /mob/living/silicon/ai")
return
@@ -1297,7 +1297,7 @@
if(!ismob(M))
to_chat(usr, "This can only be used on instances of type /mob")
return
- if(isAI(M))
+ if(is_ai(M))
to_chat(usr, "This cannot be used on instances of type /mob/living/silicon/ai")
return
@@ -1329,7 +1329,7 @@
if(!ismob(M))
to_chat(usr, "This can only be used on instances of type /mob")
return
- if(isAI(M))
+ if(is_ai(M))
to_chat(usr, "This cannot be used on instances of type /mob/living/silicon/ai")
return
@@ -1361,7 +1361,7 @@
if(!ismob(M))
to_chat(usr, "This can only be used on instances of type /mob")
return
- if(isAI(M))
+ if(is_ai(M))
to_chat(usr, "This cannot be used on instances of type /mob/living/silicon/ai")
return
@@ -1385,7 +1385,7 @@
if(!ismob(M))
to_chat(usr, "This can only be used on instances of type /mob")
return
- if(isAI(M))
+ if(is_ai(M))
to_chat(usr, "This cannot be used on instances of type /mob/living/silicon/ai")
return
@@ -1492,7 +1492,7 @@
if(!ismob(M))
to_chat(usr, "This can only be used on instances of type /mob")
return
- if(isAI(M))
+ if(is_ai(M))
to_chat(usr, "This cannot be used on instances of type /mob/living/silicon/ai")
return
@@ -2255,7 +2255,7 @@
if(!href_list["cryoafk"] && !isLivingSSD(M))
to_chat(usr, "This can only be used on living, SSD players.")
return
- if(isAI(M))
+ if(is_ai(M))
var/mob/living/silicon/ai/A = M
A.cryo_AI()
if(istype(M.loc, /obj/machinery/cryopod))
@@ -3615,7 +3615,7 @@
target = C.mob
. = ADMIN_FLW(target, "FLW")
- if(isAI(target)) // AI core/eye follow links
+ if(is_ai(target)) // AI core/eye follow links
var/mob/living/silicon/ai/A = target
if(A.client && A.eyeobj) // No point following clientless AI eyes
. += "|[ADMIN_FLW(A.eyeobj,"EYE")]"
diff --git a/code/modules/admin/verbs/randomverbs.dm b/code/modules/admin/verbs/randomverbs.dm
index b4953dd3107..0a09fa34d0d 100644
--- a/code/modules/admin/verbs/randomverbs.dm
+++ b/code/modules/admin/verbs/randomverbs.dm
@@ -23,7 +23,7 @@
return
if(ismob(M))
- if(isAI(M))
+ if(is_ai(M))
alert("The AI can't be sent to prison you jerk!", null, null, null, null, null)
return
//strip their stuff before they teleport into a cell :downs:
diff --git a/code/modules/antagonists/traitor/datum_traitor.dm b/code/modules/antagonists/traitor/datum_traitor.dm
index 3cf88d939d2..cc709d5fe20 100644
--- a/code/modules/antagonists/traitor/datum_traitor.dm
+++ b/code/modules/antagonists/traitor/datum_traitor.dm
@@ -44,7 +44,7 @@ RESTRICT_TYPE(/datum/antagonist/traitor)
/datum/antagonist/traitor/Destroy(force, ...)
// Remove all associated malf AI abilities.
- if(isAI(owner.current))
+ if(is_ai(owner.current))
var/mob/living/silicon/ai/A = owner.current
A.clear_zeroth_law()
var/obj/item/radio/headset/heads/ai_integrated/radio = A.get_radio()
@@ -84,7 +84,7 @@ RESTRICT_TYPE(/datum/antagonist/traitor)
return ..()
/datum/antagonist/traitor/select_organization()
- if(isAI(owner.current))
+ if(is_ai(owner.current))
return
var/chaos = pickweight(list(ORG_CHAOS_HUNTER = ORG_PROB_HUNTER, ORG_CHAOS_MILD = ORG_PROB_MILD, ORG_CHAOS_AVERAGE = ORG_PROB_AVERAGE, ORG_CHAOS_HIJACK = ORG_PROB_HIJACK))
for(var/org_type in shuffle(subtypesof(/datum/antag_org/syndicate)))
@@ -108,7 +108,7 @@ RESTRICT_TYPE(/datum/antagonist/traitor)
return ..()
/datum/antagonist/traitor/give_objectives()
- if(isAI(owner.current))
+ if(is_ai(owner.current))
forge_ai_objectives()
else
forge_human_objectives()
@@ -163,7 +163,7 @@ RESTRICT_TYPE(/datum/antagonist/traitor)
antag_memory += "Organization: [organization.name]
"
if(give_codewords)
messages.Add(give_codewords())
- if(isAI(owner.current))
+ if(is_ai(owner.current))
add_law_zero()
owner.current.playsound_local(get_turf(owner.current), 'sound/ambience/antag/malf.ogg', 100, FALSE, pressure_affected = FALSE, use_reverb = FALSE)
var/mob/living/silicon/ai/A = owner.current
@@ -211,7 +211,7 @@ RESTRICT_TYPE(/datum/antagonist/traitor)
* Gives a traitor human their uplink, and uplink code.
*/
/datum/antagonist/traitor/proc/give_uplink()
- if(isAI(owner.current))
+ if(is_ai(owner.current))
return FALSE
var/mob/living/carbon/human/traitor_mob = owner.current
diff --git a/code/modules/atmospherics/machinery/airalarm.dm b/code/modules/atmospherics/machinery/airalarm.dm
index 87fd428c61d..9e86fa0c13e 100644
--- a/code/modules/atmospherics/machinery/airalarm.dm
+++ b/code/modules/atmospherics/machinery/airalarm.dm
@@ -674,7 +674,7 @@ GLOBAL_LIST_INIT(aalarm_modes, list(
return data
/obj/machinery/alarm/proc/has_rcon_access(mob/user)
- return user && (isAI(user) || allowed(user) || emagged || rcon_setting == RCON_YES)
+ return user && (is_ai(user) || allowed(user) || emagged || rcon_setting == RCON_YES)
// Intentional nulls here
/obj/machinery/alarm/ui_data(mob/user)
@@ -796,7 +796,7 @@ GLOBAL_LIST_INIT(aalarm_modes, list(
return thresholds
/obj/machinery/alarm/ui_state(mob/user)
- if(isAI(user))
+ if(is_ai(user))
var/mob/living/silicon/ai/AI = user
if(!AI.lacks_power() || AI.apc_override)
return GLOB.always_state
@@ -821,7 +821,7 @@ GLOBAL_LIST_INIT(aalarm_modes, list(
return TRUE
if(user.can_admin_interact())
return TRUE
- else if(isAI(user) || isrobot(user) || emagged || user.has_unlimited_silicon_privilege)
+ else if(is_ai(user) || isrobot(user) || emagged || user.has_unlimited_silicon_privilege)
return TRUE
else
return !locked
@@ -830,7 +830,7 @@ GLOBAL_LIST_INIT(aalarm_modes, list(
if(buildstage != 2)
return UI_CLOSE
- if(aidisabled && (isAI(user) || isrobot(user)))
+ if(aidisabled && (is_ai(user) || isrobot(user)))
to_chat(user, "AI control for \the [src] interface has been disabled.")
return UI_CLOSE
diff --git a/code/modules/atmospherics/machinery/other/meter.dm b/code/modules/atmospherics/machinery/other/meter.dm
index 0f6deb15046..c485f4afda2 100644
--- a/code/modules/atmospherics/machinery/other/meter.dm
+++ b/code/modules/atmospherics/machinery/other/meter.dm
@@ -61,7 +61,7 @@ GLOBAL_LIST_EMPTY(gas_meters)
/obj/machinery/atmospherics/meter/examine(mob/user)
. = ..()
. += "Measures the volume and temperature of the pipe under the meter."
- if(get_dist(user, src) > 3 && !(isAI(user) || istype(user, /mob/dead)))
+ if(get_dist(user, src) > 3 && !(is_ai(user) || istype(user, /mob/dead)))
. += "You are too far away to read it."
else if(stat & (NOPOWER|BROKEN))
@@ -77,7 +77,7 @@ GLOBAL_LIST_EMPTY(gas_meters)
. += "The connect error light is blinking."
/obj/machinery/atmospherics/meter/Click()
- if(isAI(usr)) // ghosts can call ..() for examine
+ if(is_ai(usr)) // ghosts can call ..() for examine
usr.examinate(src)
return TRUE
diff --git a/code/modules/clothing/suits/misc_suits.dm b/code/modules/clothing/suits/misc_suits.dm
index d1f6402e34d..c08071b5881 100644
--- a/code/modules/clothing/suits/misc_suits.dm
+++ b/code/modules/clothing/suits/misc_suits.dm
@@ -204,7 +204,7 @@
if(!M.anchored && (M.flags & CONDUCT))
step_towards(M,src)
for(var/mob/living/silicon/S in orange(2,src))
- if(isAI(S)) continue
+ if(is_ai(S)) continue
step_towards(S,src)
for(var/mob/living/carbon/human/machine/M in orange(2,src))
step_towards(M,src)
diff --git a/code/modules/events/dust.dm b/code/modules/events/dust.dm
index de651813776..f4f83edc12f 100644
--- a/code/modules/events/dust.dm
+++ b/code/modules/events/dust.dm
@@ -73,7 +73,7 @@
return
if(prob(shake_chance))
for(var/mob/M in range(10, src))
- if(!M.stat && !isAI(M))
+ if(!M.stat && !is_ai(M))
shake_camera(M, 3, 1)
playsound(loc, 'sound/effects/meteorimpact.ogg', 40, 1)
diff --git a/code/modules/fish/fishtank.dm b/code/modules/fish/fishtank.dm
index a5fb9ffed0d..eaa21b7dc70 100644
--- a/code/modules/fish/fishtank.dm
+++ b/code/modules/fish/fishtank.dm
@@ -567,7 +567,7 @@
return ..()
/obj/machinery/fishtank/attack_hand(mob/user)
- if(isAI(user))
+ if(is_ai(user))
return
user.changeNext_move(CLICK_CD_MELEE)
playsound(get_turf(src), 'sound/effects/glassknock.ogg', 80, TRUE)
diff --git a/code/modules/mob/living/silicon/ai/freelook/README.md b/code/modules/mob/camera/README.md
similarity index 100%
rename from code/modules/mob/living/silicon/ai/freelook/README.md
rename to code/modules/mob/camera/README.md
diff --git a/code/modules/mob/camera/cameranet.dm b/code/modules/mob/camera/cameranet.dm
new file mode 100644
index 00000000000..8e6277f4045
--- /dev/null
+++ b/code/modules/mob/camera/cameranet.dm
@@ -0,0 +1,160 @@
+// CAMERA NET
+//
+// The datum containing all the chunks.
+GLOBAL_DATUM_INIT(cameranet, /datum/cameranet, new())
+
+/datum/cameranet
+ var/name = "Camera Net"
+
+ /// The cameras on the map, no matter if they work or not. Updated in obj/machinery/camera.dm by New() and Destroy().
+ var/list/cameras = list()
+ /// The chunks of the map, mapping the areas that the cameras can see.
+ var/list/chunks = list()
+ var/ready = FALSE
+
+/// Returns the chunk at (x, y, z) if it exists, otherwise returns null.
+/datum/cameranet/proc/chunk_generated(x, y, z)
+ x &= ~(CAMERA_CHUNK_SIZE - 1)
+ y &= ~(CAMERA_CHUNK_SIZE - 1)
+ var/key = "[x],[y],[z]"
+ return (chunks[key])
+
+/// Returns the chunk at (x, y, z) if it exists, otherwise returns a new chunk at that location.
+/datum/cameranet/proc/get_camera_chunk(x, y, z)
+ x &= ~(CAMERA_CHUNK_SIZE - 1)
+ y &= ~(CAMERA_CHUNK_SIZE - 1)
+ var/key = "[x],[y],[z]"
+ if(!chunks[key])
+ chunks[key] = new /datum/camerachunk(null, x, y, z)
+
+ return chunks[key]
+
+/// Updates what the camera network can see.
+/datum/cameranet/proc/visibility(list/moved_eyes, client/C)
+ if(!islist(moved_eyes))
+ moved_eyes = moved_eyes ? list(moved_eyes) : list()
+
+ var/list/chunks_pre_seen = list()
+ var/list/chunks_post_seen = list()
+
+ for(var/V in moved_eyes)
+ var/mob/camera/eye/eye = V
+ if(C)
+ chunks_pre_seen |= eye.visible_camera_chunks
+ // 0xf = 15
+ var/static_range = eye.static_visibility_range
+ var/x1 = max(0, eye.x - static_range) & ~(CAMERA_CHUNK_SIZE - 1)
+ var/y1 = max(0, eye.y - static_range) & ~(CAMERA_CHUNK_SIZE - 1)
+ var/x2 = min(world.maxx, eye.x + static_range) & ~(CAMERA_CHUNK_SIZE - 1)
+ var/y2 = min(world.maxy, eye.y + static_range) & ~(CAMERA_CHUNK_SIZE - 1)
+
+ var/list/visible_chunks = list()
+
+ for(var/x = x1; x <= x2; x += CAMERA_CHUNK_SIZE)
+ for(var/y = y1; y <= y2; y += CAMERA_CHUNK_SIZE)
+ visible_chunks |= get_camera_chunk(x, y, eye.z)
+
+ var/list/remove = eye.visible_camera_chunks - visible_chunks
+ var/list/add = visible_chunks - eye.visible_camera_chunks
+
+ for(var/chunk in remove)
+ var/datum/camerachunk/c = chunk
+ c.remove(eye, FALSE)
+
+ for(var/chunk in add)
+ var/datum/camerachunk/c = chunk
+ c.add(eye, FALSE)
+
+ if(C)
+ chunks_post_seen |= eye.visible_camera_chunks
+
+ if(C)
+ var/list/remove = chunks_pre_seen - chunks_post_seen
+ var/list/add = chunks_post_seen - chunks_pre_seen
+
+ for(var/chunk in remove)
+ var/datum/camerachunk/c = chunk
+ C.images -= c.obscured
+
+ for(var/chunk in add)
+ var/datum/camerachunk/c = chunk
+ C.images += c.obscured
+
+
+/// Updates the chunks that the turf is located in. Use this when obstacles are destroyed or when doors open.
+/datum/cameranet/proc/update_visibility(atom/A, opacity_check = 1)
+ if(!SSticker || (opacity_check && !A.opacity))
+ return
+ major_chunk_change(update = A)
+
+/// Removes a camera from a chunk.
+/datum/cameranet/proc/remove_camera(obj/machinery/camera/c)
+ major_chunk_change(remove = c)
+
+/// Add a camera to a chunk.
+/datum/cameranet/proc/add_camera(obj/machinery/camera/c)
+ major_chunk_change(add = c)
+
+/// Refreshes the chunk location of a portable camera. Used by Cyborgs.
+/datum/cameranet/proc/update_portable_camera(obj/machinery/camera/c, turf/old_loc)
+ major_chunk_change(add = c, old_loc = old_loc)
+
+/// Private method for updating the chunk an atom is in, and all surrounding chunks.
+/// `add` will be added as a camera to the chunk of its current location and all surrounding chunks.
+/// `remove` will be removed as a camera from the chunk of its current location and all surrounding chunks.
+/// `update` will not be added or removed as a camera, but its surrounding chunks will be updated.
+/// These parameters are mutually exclusive.
+/datum/cameranet/proc/major_chunk_change(atom/add = null, atom/remove = null, atom/update = null, turf/old_loc = null)
+ // 0xf = 15
+ if(!add && !remove && !update)
+ return
+ if(add && remove)
+ CRASH("Adding and removing a camera to the cameranet simultaneously is not implemented")
+
+ var/atom/c = remove
+ if(!c)
+ c = add
+ if(!c)
+ c = update
+
+ var/turf/T = get_turf(c)
+ if(!T)
+ return
+
+ // Check if the turf to add falls in the same chunk as the old_loc. If so, do nothing
+ if(old_loc)
+ if(T.x & ~(CAMERA_CHUNK_SIZE - 1) == old_loc.x & ~(CAMERA_CHUNK_SIZE - 1) && T.y & ~(CAMERA_CHUNK_SIZE - 1) == old_loc.y & ~(CAMERA_CHUNK_SIZE - 1))
+ return
+
+ // Use camera view distance here to actually know how far a camera can max watch
+ var/x1 = max(0, T.x - CAMERA_VIEW_DISTANCE) & ~(CAMERA_CHUNK_SIZE - 1)
+ var/y1 = max(0, T.y - CAMERA_VIEW_DISTANCE) & ~(CAMERA_CHUNK_SIZE - 1)
+ var/x2 = min(world.maxx, T.x + CAMERA_VIEW_DISTANCE) & ~(CAMERA_CHUNK_SIZE - 1)
+ var/y2 = min(world.maxy, T.y + CAMERA_VIEW_DISTANCE) & ~(CAMERA_CHUNK_SIZE - 1)
+
+ for(var/x = x1; x <= x2; x += CAMERA_CHUNK_SIZE)
+ for(var/y = y1; y <= y2; y += CAMERA_CHUNK_SIZE)
+ if(chunk_generated(x, y, T.z))
+ var/datum/camerachunk/chunk = get_camera_chunk(x, y, T.z)
+ if(remove)
+ // Remove the camera.
+ chunk.remove_camera(c)
+ else if(add)
+ // You can't have the same camera in the list twice.
+ chunk.add_camera(c)
+ chunk.has_changed()
+
+/// Returns 1 if a mob is on a viewable turf, otherwise returns 0.
+/datum/cameranet/proc/check_camera_vis(mob/living/target as mob)
+ // 0xf = 15
+ var/turf/position = get_turf(target)
+ return check_turf_vis(position)
+
+/datum/cameranet/proc/check_turf_vis(turf/position)
+ var/datum/camerachunk/chunk = get_camera_chunk(position.x, position.y, position.z)
+ if(chunk)
+ if(chunk.changed)
+ chunk.has_changed(1) // Update now, no matter if it's visible or not.
+ if(chunk.visible_turfs[position])
+ return 1
+ return 0
diff --git a/code/modules/mob/living/silicon/ai/freelook/chunk.dm b/code/modules/mob/camera/chunk.dm
similarity index 63%
rename from code/modules/mob/living/silicon/ai/freelook/chunk.dm
rename to code/modules/mob/camera/chunk.dm
index 7deb20f2ef3..6a0e7ff9c26 100644
--- a/code/modules/mob/living/silicon/ai/freelook/chunk.dm
+++ b/code/modules/mob/camera/chunk.dm
@@ -1,11 +1,8 @@
-// CAMERA CHUNK
-//
-// A 16x16 grid of the map with a list of turfs that can be seen, are visible and are dimmed.
-// Allows the AI Eye to stream these chunks and know what it can and cannot see.
-
+/// A 16x16 grid of the map with a list of turfs that can be seen, are visible and are dimmed.
+/// Allows camera eyes to stream these chunks and know what they can and cannot see.
/datum/camerachunk
- var/list/obscuredTurfs = list()
- var/list/visibleTurfs = list()
+ var/list/obscured_turfs = list()
+ var/list/visible_turfs = list()
var/list/obscured = list()
var/list/active_cameras = list()
var/list/inactive_cameras = list()
@@ -17,6 +14,7 @@
var/y = 0
var/z = 0
+/// Adds a camera to the chunk if it has not already been added.
/datum/camerachunk/proc/add_camera(obj/machinery/camera/cam)
if(active_cameras[cam] || inactive_cameras[cam])
return
@@ -32,6 +30,7 @@
else
inactive_cameras[cam] = cam
+/// Handles each movement by a camera that has been added to the chunk.
/datum/camerachunk/proc/camera_moved(obj/machinery/camera/cam, atom/old_loc)
var/turf/T = get_turf(cam)
@@ -39,6 +38,7 @@
if(T.x + CAMERA_VIEW_DISTANCE < x || T.x - CAMERA_VIEW_DISTANCE >= x + CAMERA_CHUNK_SIZE || T.y + CAMERA_VIEW_DISTANCE < y || T.y - CAMERA_VIEW_DISTANCE >= y + CAMERA_CHUNK_SIZE || T.z != z)
remove_camera(cam)
+/// Removes a camera from the chunk.
/datum/camerachunk/proc/remove_camera(obj/machinery/camera/cam)
UnregisterSignal(cam, list(COMSIG_CAMERA_OFF, COMSIG_CAMERA_ON, COMSIG_PARENT_QDELETING, COMSIG_CAMERA_MOVED))
active_cameras -= cam
@@ -55,42 +55,40 @@
active_cameras -= cam
SScamera.queue(src)
-// Add an AI eye to the chunk, then update if changed.
-/datum/camerachunk/proc/add(mob/camera/ai_eye/eye, add_images = TRUE)
+/// Add a camera eye to the chunk, then update if changed.
+/datum/camerachunk/proc/add(mob/camera/eye/eye, add_images = TRUE)
if(add_images)
- var/client/client = eye.GetViewerClient()
+ var/client/client = eye.get_viewer_client()
if(client)
client.images += obscured
- eye.visibleCameraChunks += src
+ eye.visible_camera_chunks += src
seenby += eye
- RegisterSignal(eye, COMSIG_PARENT_QDELETING, PROC_REF(aiEye_destroyed))
+ RegisterSignal(eye, COMSIG_PARENT_QDELETING, PROC_REF(eye_destroyed))
if(changed)
SScamera.queue(src)
-/datum/camerachunk/proc/aiEye_destroyed(mob/camera/ai_eye/eye)
+/datum/camerachunk/proc/eye_destroyed(mob/camera/eye/eye)
remove(eye, FALSE)
-// Remove an AI eye from the chunk, then update if changed.
-/datum/camerachunk/proc/remove(mob/camera/ai_eye/eye, remove_images = TRUE)
+/// Remove a camera eye from the chunk, then update if changed.
+/datum/camerachunk/proc/remove(mob/camera/eye/eye, remove_images = TRUE)
if(remove_images)
- var/client/client = eye.GetViewerClient()
+ var/client/client = eye.get_viewer_client()
if(client)
client.images -= obscured
- eye.visibleCameraChunks -= src
+ eye.visible_camera_chunks -= src
seenby -= eye
UnregisterSignal(eye, COMSIG_PARENT_QDELETING)
-// Called when a chunk has changed. I.E: A wall was deleted.
-
-/datum/camerachunk/proc/visibilityChanged(turf/loc)
- if(!visibleTurfs[loc])
+/// Called when a chunk has changed. I.E: A wall was deleted.
+/datum/camerachunk/proc/visibility_changed(turf/loc)
+ if(!visible_turfs[loc])
return
- hasChanged()
+ has_changed()
-// Updates the chunk, makes sure that it doesn't update too much. If the chunk isn't being watched it will
-// instead be flagged to update the next time an AI Eye moves near it.
-
-/datum/camerachunk/proc/hasChanged(update_now = 0)
+/// Updates the chunk, makes sure that it doesn't update too much. If the chunk isn't being watched it will
+/// instead be flagged to update the next time a camera eye moves near it.
+/datum/camerachunk/proc/has_changed(update_now = 0)
if(update_now)
update()
SScamera.remove_from_queue(src)
@@ -100,48 +98,48 @@
else
changed = TRUE
-// The actual updating. It gathers the visible turfs from cameras and puts them into the appropiate lists.
-
+/// Gathers the visible turfs from cameras and puts them into the appropiate lists.
/datum/camerachunk/proc/update()
- var/list/newVisibleTurfs = list()
+ var/list/new_visible_turfs = list()
for(var/obj/machinery/camera/c as anything in active_cameras)
var/turf/point = locate(src.x + (CAMERA_CHUNK_SIZE / 2), src.y + (CAMERA_CHUNK_SIZE / 2), src.z)
var/turf/T = get_turf(c)
if(get_dist(point, T) > CAMERA_VIEW_DISTANCE + (CAMERA_CHUNK_SIZE / 2))
- continue // Still needed for Ais who get created on Z level 1 on the spot of the new player
+ // Still needed for Ais who get created on Z level 1 on the spot of the new player
+ continue
for(var/turf/t in c.can_see())
if(turfs[t])
- newVisibleTurfs[t] = t
+ new_visible_turfs[t] = t
- var/list/visAdded = newVisibleTurfs - visibleTurfs
- var/list/visRemoved = visibleTurfs - newVisibleTurfs
+ var/list/vis_added = new_visible_turfs - visible_turfs
+ var/list/vis_removed = visible_turfs - new_visible_turfs
- visibleTurfs = newVisibleTurfs
- obscuredTurfs = turfs - newVisibleTurfs
+ visible_turfs = new_visible_turfs
+ obscured_turfs = turfs - new_visible_turfs
var/list/images_to_remove = list()
var/list/images_to_add = list()
- for(var/turf/t as anything in visAdded)
+ for(var/turf/t as anything in vis_added)
if(t.obscured)
obscured -= t.obscured
images_to_remove += t.obscured
- for(var/turf/t as anything in visRemoved)
+ for(var/turf/t as anything in vis_removed)
if(!t.obscured)
t.obscured = image('icons/effects/cameravis.dmi', t, null, BYOND_LIGHTING_LAYER + 0.1)
t.obscured.plane = BYOND_LIGHTING_PLANE + 1
obscured += t.obscured
images_to_add += t.obscured
- for(var/mob/camera/ai_eye/eye as anything in seenby)
- var/client/client = eye.GetViewerClient()
+ for(var/mob/camera/eye/eye as anything in seenby)
+ var/client/client = eye.get_viewer_client()
if(client)
client.images -= images_to_remove
client.images += images_to_add
changed = FALSE
-// Create a new camera chunk, since the chunks are made as they are needed.
+/// Create a new camera chunk, since the chunks are made as they are needed.
/datum/camerachunk/New(loc, x, y, z)
// 0xf = 15
@@ -162,11 +160,11 @@
for(var/obj/machinery/camera/c as anything in active_cameras)
for(var/turf/t in c.can_see())
if(turfs[t])
- visibleTurfs[t] = t
+ visible_turfs[t] = t
- obscuredTurfs = turfs - visibleTurfs
+ obscured_turfs = turfs - visible_turfs
- for(var/turf/t as anything in obscuredTurfs)
+ for(var/turf/t as anything in obscured_turfs)
if(!t.obscured)
t.obscured = image('icons/effects/cameravis.dmi', t, "black", BYOND_LIGHTING_LAYER + 0.1)
t.obscured.plane = BYOND_LIGHTING_PLANE + 1
diff --git a/code/modules/mob/camera/eye.dm b/code/modules/mob/camera/eye.dm
new file mode 100644
index 00000000000..2034a6c7c30
--- /dev/null
+++ b/code/modules/mob/camera/eye.dm
@@ -0,0 +1,191 @@
+/// Camera eyes are remote-control mobs that can move and see throughout the global cameranet.
+/// They're used in AI eyes, holograms, advanced camera consoles, abductor consoles, shuttle consoles,
+/// and xenobiology consoles. When created, the user with which they are initialized will be granted control,
+/// and their movements will be relayed to the camera eye instead. When destroyed, the user's control of the
+/// camera eye will be released; if they were previously remote controlling another object (such as another
+/// camera eye) then they will be put back in control of that object; otherwise they will return to their body.
+/mob/camera/eye
+ name = "Inactive Camera Eye"
+ icon = 'icons/obj/abductor.dmi'
+ icon_state = "camera_target"
+ alpha = 127
+ invisibility = SEE_INVISIBLE_OBSERVER
+
+ /// The list of camera chunks currently visible to the camera eye.
+ var/list/visible_camera_chunks = list()
+ /// The user controlling the eye.
+ var/mob/living/user
+ /// The thing that the user was previously remote controlling before this eye.
+ var/user_previous_remote_control
+ /// The object that created the eye.
+ var/origin
+ /// If true, speech near the camera eye will be relayed to its controller.
+ var/relay_speech = FALSE
+ /// Sets the camera eye visibility range; does not expand viewport, only affects cameranet obscuring
+ var/static_visibility_range = 16
+ /// Toggles whether this eye is detectable by AI Detectors.
+ var/ai_detector_visible = TRUE
+ /// Toggles whether the eye's icon should be visible to its user.
+ var/visible_icon = FALSE
+ /// The list of cameranets that this camera eye can see and access.
+ var/list/networks = list("SS13")
+ /// The in-memory image of the camera eye's icon.
+ var/image/user_image
+
+ // Camera acceleration settings
+ // Initially, the camera moves one turf per move. If there is no movement for
+ // cooldown_rate in deciseconds, the camera will reset to this movement rate.
+ // Every move otherwise increases sprint by acceleration_rate, until sprint
+ // exceeds sprint_threshold, and the movement rate increases by one per move.
+ // The movement rate is 1 + round(sprint / sprint_threshold).
+
+ /// The maximum sprint value - this caps acceleration
+ var/max_sprint = 50
+ /// The minimum sprint needed to increase base velocity
+ var/sprint_threshold = 20
+ /// The amount that sprint is increased per move
+ var/acceleration_rate = 0.5
+ /// Keeps track of acceleration - movement rate is 1 + round(sprint / sprint_threshold)
+ var/sprint = 10
+ /// The absolute time that sprint will reset to its initial value
+ var/cooldown = 0
+ /// The time after which sprint should be reset to its initial state, if no movements are made
+ var/cooldown_rate = 5
+ /// Toggles camera acceleration on or off.
+ var/acceleration = 1
+
+/mob/camera/eye/Initialize(mapload, owner_name, camera_origin, mob/living/user)
+ . = ..()
+ name = "Camera Eye ([owner_name])"
+ origin = camera_origin
+ give_control(user)
+ update_visibility()
+ refresh_visible_icon()
+ if(!validate_active_cameranet())
+ return INITIALIZE_HINT_QDEL
+
+/// Validates that there is an active cameranet. If strict is 0, does nothing.
+/// Returns 1 if there is an active cameranet. Warns the user and returns 0 if there is not.
+/mob/camera/eye/proc/validate_active_cameranet(strict = 0)
+ var/camera = first_active_camera()
+ if(strict && !camera)
+ to_chat(user, "ERROR: No linked and active camera network found.")
+ return FALSE
+ return TRUE
+
+/// Returns the turf of the first active camera in the global cameranet.
+/mob/camera/eye/proc/first_active_camera()
+ for(var/obj/machinery/camera/C in GLOB.cameranet.cameras)
+ if(!C.can_use())
+ continue
+ if(length(C.network & networks))
+ return get_turf(C)
+
+/// Updates what the global cameranet can see with respect to this eye and its user's client.
+/mob/camera/eye/proc/update_visibility()
+ GLOB.cameranet.visibility(src, user.client)
+
+/// Refreshes user_image in the user's client.images.
+/mob/camera/eye/proc/refresh_visible_icon()
+ if(visible_icon && user.client)
+ user.client.images -= user_image
+ user_image = image(icon,loc,icon_state,FLY_LAYER)
+ user.client.images += user_image
+
+/// Sets the camera eye's location to T, updates global cameranet visibility, and refreshes user_images.
+/mob/camera/eye/set_loc(T)
+ if(user)
+ T = get_turf(T)
+ ..(T)
+ update_visibility()
+ refresh_visible_icon()
+
+/// Disables independent movement by camera eyes; camera eyes must be controlled by relaymove.
+/mob/camera/eye/Move()
+ return FALSE
+
+/// If `usr` is an AI, set the camera eye's location to the location of the atom clicked.
+/atom/proc/move_camera_by_click()
+ if(is_ai(usr))
+ var/mob/living/silicon/ai/AI = usr
+ if(AI.eyeobj && (AI.client.eye == AI.eyeobj) && (AI.eyeobj.z == z))
+ AI.camera_follow = null
+ if(isturf(loc) || isturf(src))
+ AI.eyeobj.set_loc(src)
+
+/// Returns the user's client, if it exists; otherwise returns null.
+/mob/camera/eye/proc/get_viewer_client()
+ return user?.client
+
+/// Removes obscured chunk images and user_images from the user's client.images.
+/mob/camera/eye/proc/remove_images()
+ var/client/C = get_viewer_client()
+ if(!C)
+ return
+ for(var/datum/camerachunk/chunk as anything in visible_camera_chunks)
+ C.images -= chunk.obscured
+ if(visible_icon)
+ C.images -= user_image
+
+/// Calls `remove_images`, changes the user's remote control from this camera eye to `user_previous_remote_control`.
+/mob/camera/eye/proc/release_control()
+ if(!istype(user))
+ return
+ if(user.client)
+ user.reset_perspective(user.client.mob)
+ remove_images()
+ user.remote_control = null
+ if(user_previous_remote_control)
+ user.reset_perspective(user_previous_remote_control)
+ user.remote_control = user_previous_remote_control
+ user_previous_remote_control = null
+ user = null
+
+/// Forces this eye's current user to release control, renames this eye, and grants `new_user` control of this eye.
+/mob/camera/eye/proc/give_control(mob/new_user)
+ if(!istype(new_user))
+ return
+ release_control()
+ user = new_user
+ rename_camera(user.name)
+ if(istype(user.remote_control))
+ user_previous_remote_control = user.remote_control
+ user.remote_control = src
+ user.reset_perspective(src)
+
+/// Renames the camera eye (only visible in observer Orbit menu)
+/mob/camera/eye/proc/rename_camera(new_name)
+ name = "Camera Eye ([new_name])"
+
+/// Remove this eye from all chunks containing it.
+/mob/camera/eye/proc/release_chunks()
+ for(var/datum/camerachunk/chunk as anything in visible_camera_chunks)
+ chunk.remove(src)
+
+/mob/camera/eye/Destroy()
+ release_control()
+ release_chunks()
+ return ..()
+
+/// Called when the user controlling this eye attempts to move; uses camera acceleration settings.
+/mob/camera/eye/relaymove(mob/user,direct)
+ var/initial = initial(sprint)
+
+ if(cooldown && cooldown < world.timeofday)
+ sprint = initial
+
+ for(var/i in 0 to sprint step sprint_threshold)
+ var/turf/next_step= get_turf(get_step(src, direct))
+ if(next_step)
+ set_loc(next_step)
+
+ cooldown = world.timeofday + cooldown_rate
+ if(acceleration)
+ sprint = min(sprint + acceleration_rate, max_sprint)
+ else
+ sprint = initial
+
+/// If `relay_speech` is truthy, allows the camera eye's user to hear speech spoken at the eye's location.
+/mob/camera/eye/hear_say(list/message_pieces, verb = "says", italics = 0, mob/speaker = null, sound/speech_sound, sound_vol, sound_frequency, use_voice = TRUE)
+ if(relay_speech)
+ user.hear_say(message_pieces, verb, italics, speaker, speech_sound, sound_vol, sound_frequency)
diff --git a/code/modules/mob/camera/eye/abductor.dm b/code/modules/mob/camera/eye/abductor.dm
new file mode 100644
index 00000000000..3b8c531099a
--- /dev/null
+++ b/code/modules/mob/camera/eye/abductor.dm
@@ -0,0 +1,14 @@
+/mob/camera/eye/abductor
+ name = "Abductor Camera Eye"
+ ai_detector_visible = FALSE
+
+/mob/camera/eye/abductor/Initialize(mapload, owner_name, camera_origin, user)
+ ..()
+ set_loc(first_active_camera())
+
+/mob/camera/eye/abductor/rename_camera(new_name)
+ name = "Abductor Camera Eye ([new_name])"
+
+/// Requires the cameranet to be validated.
+/mob/camera/eye/abductor/validate_active_cameranet()
+ ..(TRUE)
diff --git a/code/modules/mob/camera/eye/ai_eye.dm b/code/modules/mob/camera/eye/ai_eye.dm
new file mode 100644
index 00000000000..d915f95f2fe
--- /dev/null
+++ b/code/modules/mob/camera/eye/ai_eye.dm
@@ -0,0 +1,34 @@
+/mob/camera/eye/ai
+ name = "Inactive AI Eye"
+ icon = 'icons/mob/ai.dmi'
+ icon_state = "eye"
+ var/mob/living/silicon/ai/ai = null
+
+/mob/camera/eye/ai/Initialize(mapload, owner_name, camera_origin, mob/living/user)
+ . = ..()
+ ai = user
+ if(is_ai_eye(ai.eyeobj))
+ stack_trace("Tried to create an AI Eye for [user], but there is one already assigned")
+ return INITIALIZE_HINT_QDEL
+ name = "[owner_name] (AI Eye)"
+
+/// Ensures that the user's perspective is on this eye (instead of, for example, a mech or hologram eye) and
+/// updates parallax
+/mob/camera/eye/ai/set_loc(T)
+ ..()
+ user.reset_perspective(src)
+ update_parallax_contents()
+
+/// Cancels the camera's follow target if tracking has stopped, and lights up nearby lights if the AI has
+/// "Toggle Camera Lights" enabled
+/mob/camera/eye/ai/relaymove(mob/user, direct)
+ ..()
+ if(!ai.tracking)
+ ai.camera_follow = null
+ if(ai.camera_light_on)
+ ai.light_cameras()
+
+/// Relays speech near the AI eye to the AI if the AI has surveillance, either from a malf module or a station trait
+/mob/camera/eye/ai/hear_say(list/message_pieces, verb = "says", italics = 0, mob/speaker = null, sound/speech_sound, sound_vol, sound_frequency, use_voice = TRUE)
+ if(relay_speech)
+ ai.relay_speech(speaker, message_pieces, verb)
diff --git a/code/modules/mob/camera/eye/hologram_eye.dm b/code/modules/mob/camera/eye/hologram_eye.dm
new file mode 100644
index 00000000000..a30c63827a9
--- /dev/null
+++ b/code/modules/mob/camera/eye/hologram_eye.dm
@@ -0,0 +1,53 @@
+/mob/camera/eye/hologram
+ name = "Inactive Hologram Eye"
+ ai_detector_visible = FALSE
+ acceleration = FALSE
+ relay_speech = TRUE
+ var/obj/machinery/hologram/holopad/holopad
+
+/mob/camera/eye/hologram/Initialize(mapload, owner_name, camera_origin, mob/living/user)
+ ..()
+ holopad = camera_origin
+ set_loc(holopad)
+
+/mob/camera/eye/hologram/rename_camera(new_name)
+ name = "Hologram ([new_name])"
+
+/// Hologram movement copies the delays and diagonal delays of regular mob movement
+/// for crew, and for AI unless fast holograms are enabled
+/mob/camera/eye/hologram/relaymove(mob/user, direct)
+ var/mob/living/silicon/ai/ai = user
+ if(istype(ai) && ai.fast_holograms)
+ return ..()
+ var/turf/new_location = get_turf(get_step(src, direct))
+ if(new_location.z != z || get_dist(new_location, src) > 1)
+ return
+ var/base_delay = GLOB.configuration.movement.base_run_speed
+ var/diag_delay = base_delay * SQRT_2
+ var/delay = (direct & (direct - 1)) ? diag_delay : base_delay
+ user.client.move_delay = debounced_move(normalized_delay_speed(delay))
+ user.last_movement = world.time
+ set_loc(new_location)
+
+/mob/camera/eye/hologram/proc/debounced_move(delay_speed)
+ var/old_move_delay = user.client.move_delay
+ if(old_move_delay + world.tick_lag > world.time)
+ return old_move_delay + delay_speed
+ else
+ return world.time + delay_speed
+
+/mob/camera/eye/hologram/proc/normalized_delay_speed(delay_speed)
+ return TICKS2DS(-round(-(DS2TICKS(delay_speed))))
+
+/// Requires the cameranet to be validated.
+/mob/camera/eye/hologram/validate_active_cameranet()
+ ..(TRUE)
+
+/// Moves the associated hologram, and the previously controlled object (probably an AI eye), to the new location.
+/mob/camera/eye/hologram/set_loc(T)
+ . = ..()
+ var/turf/new_location = get_turf(T)
+ holopad.move_hologram(user, new_location)
+ var/mob/camera/eye/previous_eye = user_previous_remote_control
+ if(istype(previous_eye))
+ previous_eye.set_loc(new_location)
diff --git a/code/modules/mob/camera/eye/shuttle_navigator.dm b/code/modules/mob/camera/eye/shuttle_navigator.dm
new file mode 100644
index 00000000000..6e80fbc2ee4
--- /dev/null
+++ b/code/modules/mob/camera/eye/shuttle_navigator.dm
@@ -0,0 +1,30 @@
+/mob/camera/eye/shuttle_docker
+ name = "Shuttle Docker Camera Eye"
+ ai_detector_visible = FALSE
+ simulated = FALSE
+ var/list/placement_images = list()
+ var/list/placed_images = list()
+
+/mob/camera/eye/shuttle_docker/Initialize(mapload, owner_name, camera_origin, mob/living/user)
+ ..()
+ set_loc(first_active_camera())
+
+/mob/camera/eye/shuttle_docker/rename_camera(new_name)
+ name = "Shuttle Docker Camera Eye ([new_name])"
+
+/// Prevents the shuttle docker eye from updating global cameranet chunks. Shuttle dockers don't use station cameras.
+/mob/camera/eye/shuttle_docker/update_visibility()
+ return FALSE
+
+/// Prevents moving the camera eye into the station, and updates the current location's landing spot validity.
+/mob/camera/eye/shuttle_docker/set_loc(T)
+ if(isspaceturf(get_turf(T)) || istype(get_area(T), /area/space) || istype(get_area(T), /area/shuttle))
+ ..()
+ var/obj/machinery/computer/camera_advanced/shuttle_docker/console = origin
+ console.check_landing_spot()
+
+/mob/camera/eye/shuttle_docker/update_remote_sight(mob/living/user)
+ user.sight = SEE_TURFS
+
+ ..()
+ return TRUE
diff --git a/code/modules/mob/camera/eye/syndicate.dm b/code/modules/mob/camera/eye/syndicate.dm
new file mode 100644
index 00000000000..47fa732f81f
--- /dev/null
+++ b/code/modules/mob/camera/eye/syndicate.dm
@@ -0,0 +1,10 @@
+/mob/camera/eye/syndicate
+ name = "Syndicate Researcher Camera Eye"
+ ai_detector_visible = FALSE
+
+/mob/camera/eye/syndicate/Initialize(mapload, owner_name, camera_origin, user)
+ ..()
+ set_loc(first_active_camera())
+
+/mob/camera/eye/syndicate/rename_camera(new_name)
+ name = "Syndicate Researcher Camera Eye ([new_name])"
diff --git a/code/modules/mob/camera/eye/xenobio_eye.dm b/code/modules/mob/camera/eye/xenobio_eye.dm
new file mode 100644
index 00000000000..2e2bef7e710
--- /dev/null
+++ b/code/modules/mob/camera/eye/xenobio_eye.dm
@@ -0,0 +1,22 @@
+/mob/camera/eye/xenobio
+ name = "Xenobiology Console Camera Eye"
+ visible_icon = TRUE
+ ai_detector_visible = FALSE
+ var/allowed_area
+
+/mob/camera/eye/xenobio/Initialize(mapload, owner_name, camera_origin, mob/living/user)
+ . = ..()
+ var/area/A = get_area(camera_origin)
+ allowed_area = A.name
+
+/mob/camera/eye/xenobio/rename_camera(new_name)
+ name = "Xenobiology Console ([new_name])"
+
+/// Prevents the camera eye from going outside of the xenobiology area
+/mob/camera/eye/xenobio/set_loc(T)
+ var/area/new_area = get_area(T)
+ if(!new_area)
+ return
+ if(new_area.name != allowed_area && !new_area.xenobiology_compatible)
+ return
+ return ..()
diff --git a/code/modules/mob/dead/observer/observer_base.dm b/code/modules/mob/dead/observer/observer_base.dm
index 59159c638f8..d7d10ee753d 100644
--- a/code/modules/mob/dead/observer/observer_base.dm
+++ b/code/modules/mob/dead/observer/observer_base.dm
@@ -255,7 +255,7 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
warningmsg = "You have committed suicide too early in the round"
else if(stat != DEAD)
warningmsg = "You are alive"
- if(isAI(src))
+ if(is_ai(src))
warningmsg = "You are a living AI! You should probably use OOC -> Wipe Core instead."
else if(GLOB.non_respawnable_keys[ckey])
warningmsg = "You have lost your right to respawn"
@@ -656,7 +656,7 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
/proc/ghost_follow_link(atom/target, atom/ghost)
if((!target) || (!ghost)) return
- if(isAI(target)) // AI core/eye follow links
+ if(is_ai(target)) // AI core/eye follow links
var/mob/living/silicon/ai/A = target
. = "core"
if(A.client && A.eyeobj) // No point following clientless AI eyes
diff --git a/code/modules/mob/dead/observer/observer_say.dm b/code/modules/mob/dead/observer/observer_say.dm
index 0f86ba90898..79e01aeae49 100644
--- a/code/modules/mob/dead/observer/observer_say.dm
+++ b/code/modules/mob/dead/observer/observer_say.dm
@@ -17,7 +17,7 @@
if(!speaker || !ismob(speaker))
return speaker_name
var/mob/speaker_mob = speaker
- if(isAI(speaker_mob))
+ if(is_ai(speaker_mob))
//AI's can't pretend to be other mobs.
return speaker_name
if(!check_name_against || check_name_against == speaker_mob.real_name)
diff --git a/code/modules/mob/language.dm b/code/modules/mob/language.dm
index 1de7157c975..98bd00372f3 100644
--- a/code/modules/mob/language.dm
+++ b/code/modules/mob/language.dm
@@ -624,7 +624,7 @@
continue
else if(drone_only && !isdrone(S))
continue
- else if(isAI(S))
+ else if(is_ai(S))
message_start = list("[name], [speaker.name]")
else if(isrobot(S))
var/mob/living/silicon/robot/borg = S
diff --git a/code/modules/mob/living/carbon/examine.dm b/code/modules/mob/living/carbon/examine.dm
index 0dd5b93626a..3ac09b57112 100644
--- a/code/modules/mob/living/carbon/examine.dm
+++ b/code/modules/mob/living/carbon/examine.dm
@@ -364,7 +364,7 @@
return (hudtype in have_hudtypes)
- else if(isrobot(M) || isAI(M)) //Stand-in/Stopgap to prevent pAIs from freely altering records, pending a more advanced Records system
+ else if(isrobot(M) || is_ai(M)) //Stand-in/Stopgap to prevent pAIs from freely altering records, pending a more advanced Records system
return (hudtype in list(EXAMINE_HUD_SECURITY_READ, EXAMINE_HUD_SECURITY_WRITE, EXAMINE_HUD_MEDICAL_READ, EXAMINE_HUD_MEDICAL_WRITE))
else if(isobserver(M))
diff --git a/code/modules/mob/living/carbon/human/human_mob.dm b/code/modules/mob/living/carbon/human/human_mob.dm
index ebe84b02116..26a3e275b2d 100644
--- a/code/modules/mob/living/carbon/human/human_mob.dm
+++ b/code/modules/mob/living/carbon/human/human_mob.dm
@@ -723,7 +723,7 @@
else if(isrobot(user))
var/mob/living/silicon/robot/U = user
rank = "[U.modtype] [U.braintype]"
- else if(isAI(user))
+ else if(is_ai(user))
rank = "AI"
set_criminal_status(user, found_record, new_status, reason, rank)
diff --git a/code/modules/mob/living/living_defines.dm b/code/modules/mob/living/living_defines.dm
index db2fa4914bd..e85da8a348a 100644
--- a/code/modules/mob/living/living_defines.dm
+++ b/code/modules/mob/living/living_defines.dm
@@ -30,7 +30,7 @@
var/now_pushing = null
- var/atom/movable/cameraFollow = null
+ var/atom/movable/camera_follow = null
var/on_fire = 0 //The "Are we on fire?" var
var/fire_stacks = 0 //Tracks how many stacks of fire we have on, max is usually 20
diff --git a/code/modules/mob/living/silicon/ai/ai_death.dm b/code/modules/mob/living/silicon/ai/ai_death.dm
index 6f170c292f1..b2dbf6e8bda 100644
--- a/code/modules/mob/living/silicon/ai/ai_death.dm
+++ b/code/modules/mob/living/silicon/ai/ai_death.dm
@@ -10,7 +10,7 @@
else
icon_state = "ai_dead"
if(eyeobj)
- eyeobj.setLoc(get_turf(src))
+ eyeobj.set_loc(get_turf(src))
GLOB.shuttle_caller_list -= src
SSshuttle.autoEvac()
diff --git a/code/modules/mob/living/silicon/ai/ai_life.dm b/code/modules/mob/living/silicon/ai/ai_life.dm
index abf0b4e9452..3ba153e83e9 100644
--- a/code/modules/mob/living/silicon/ai/ai_life.dm
+++ b/code/modules/mob/living/silicon/ai/ai_life.dm
@@ -10,7 +10,7 @@
var/turf/T = get_turf(src)
if(stat != CONSCIOUS) //ai's fucked
- cameraFollow = null
+ camera_follow = null
reset_perspective(null)
unset_machine()
diff --git a/code/modules/mob/living/silicon/ai/ai_mob.dm b/code/modules/mob/living/silicon/ai/ai_mob.dm
index 33a071912f7..77504341b2c 100644
--- a/code/modules/mob/living/silicon/ai/ai_mob.dm
+++ b/code/modules/mob/living/silicon/ai/ai_mob.dm
@@ -14,6 +14,7 @@ GLOBAL_LIST_INIT(ai_verbs_default, list(
/mob/living/silicon/ai/proc/pick_icon,
/mob/living/silicon/ai/proc/sensor_mode,
/mob/living/silicon/ai/proc/show_laws_verb,
+ /mob/living/silicon/ai/proc/toggle_fast_holograms,
/mob/living/silicon/ai/proc/toggle_acceleration,
/mob/living/silicon/ai/proc/toggle_camera_light,
/mob/living/silicon/ai/proc/botcall,
@@ -104,10 +105,8 @@ GLOBAL_LIST_INIT(ai_verbs_default, list(
var/obj/machinery/doomsday_device/doomsday_device
var/obj/machinery/hologram/holopad/holo = null
- var/mob/camera/ai_eye/eyeobj
- var/sprint = 10
- var/cooldown = 0
- var/acceleration = 1
+ var/mob/camera/eye/ai/eyeobj
+ var/fast_holograms = TRUE
var/tracking = FALSE //this is 1 if the AI is currently tracking somebody, but the track has not yet been completed.
/// If true, this AI core can use the teleporter.
@@ -121,7 +120,6 @@ GLOBAL_LIST_INIT(ai_verbs_default, list(
var/announce_arrivals = TRUE
var/arrivalmsg = "$name, $rank, has arrived on the station."
- var/list/all_eyes = list()
var/next_text_announcement
//Used with the hotkeys on 2-5 to store locations.
@@ -228,8 +226,8 @@ GLOBAL_LIST_INIT(ai_verbs_default, list(
spawn(5)
new /obj/machinery/ai_powersupply(src)
-
- create_eye()
+
+ eyeobj = new /mob/camera/eye/ai(loc, name, src, src)
builtInCamera = new /obj/machinery/camera/portable(src)
builtInCamera.c_tag = name
@@ -769,7 +767,7 @@ GLOBAL_LIST_INIT(ai_verbs_default, list(
if(controlled_mech)
to_chat(src, "You are already loaded into an onboard computer!")
return
- if(!GLOB.cameranet.checkCameraVis(M))
+ if(!GLOB.cameranet.check_camera_vis(M))
to_chat(src, "Exosuit is no longer near active cameras.")
return
if(lacks_power())
@@ -826,7 +824,7 @@ GLOBAL_LIST_INIT(ai_verbs_default, list(
//The target must be in view of a camera or near the core.
if(turf_check in range(get_turf(src)))
call_bot(turf_check)
- else if(GLOB.cameranet && GLOB.cameranet.checkTurfVis(turf_check))
+ else if(GLOB.cameranet && GLOB.cameranet.check_turf_vis(turf_check))
call_bot(turf_check)
else
to_chat(src, "Selected location is not visible.")
@@ -882,7 +880,7 @@ GLOBAL_LIST_INIT(ai_verbs_default, list(
/mob/living/silicon/ai/proc/switchCamera(obj/machinery/camera/C)
if(!tracking)
- cameraFollow = null
+ camera_follow = null
if(QDELETED(C) || stat == DEAD) //C.can_use())
return FALSE
@@ -891,7 +889,7 @@ GLOBAL_LIST_INIT(ai_verbs_default, list(
view_core()
return
// ok, we're alive, camera is good and in our network...
- eyeobj.setLoc(get_turf(C))
+ eyeobj.set_loc(get_turf(C))
//machine = src
return TRUE
@@ -939,7 +937,7 @@ GLOBAL_LIST_INIT(ai_verbs_default, list(
if(!C.can_use())
continue
if(network in C.network)
- U.eyeobj.setLoc(get_turf(C))
+ U.eyeobj.set_loc(get_turf(C))
break
to_chat(src, "Switched to [network] camera network.")
//End of code by Mord_Sith
@@ -1238,7 +1236,7 @@ GLOBAL_LIST_INIT(ai_verbs_default, list(
var/list/obj/machinery/camera/add = list()
var/list/obj/machinery/camera/remove = list()
var/list/obj/machinery/camera/visible = list()
- for(var/datum/camerachunk/CC in eyeobj.visibleCameraChunks)
+ for(var/datum/camerachunk/CC in eyeobj.visible_camera_chunks)
for(var/obj/machinery/camera/C in CC.active_cameras)
if(!C.can_use() || get_dist(C, eyeobj) > 7)
continue
@@ -1340,7 +1338,7 @@ GLOBAL_LIST_INIT(ai_verbs_default, list(
//get_turf_pixel() is because APCs in maint aren't actually in view of the inner camera
//apc_override is needed here because AIs use their own APC when depowered
var/turf/T = isturf(A) ? A : get_turf_pixel(A)
- return (GLOB.cameranet && GLOB.cameranet.checkTurfVis(T)) || apc_override
+ return (GLOB.cameranet && GLOB.cameranet.check_turf_vis(T)) || apc_override
//AI is carded/shunted
//view(src) returns nothing for carded/shunted AIs and they have x-ray vision so just use get_dist
var/list/viewscale = getviewsize(client.view)
@@ -1433,8 +1431,45 @@ GLOBAL_LIST_INIT(ai_verbs_default, list(
else
to_chat(src, "Target is not on or near any active cameras on the station.")
-/mob/living/silicon/ai/proc/camera_visibility(mob/camera/ai_eye/moved_eye)
- GLOB.cameranet.visibility(moved_eye, client, all_eyes)
+// Return to the Core.
+/mob/living/silicon/ai/proc/core()
+ set category = "AI Commands"
+ set name = "AI Core"
+
+ view_core()
+
+/mob/living/silicon/ai/proc/view_core()
+
+ current = null
+ camera_follow = null
+ unset_machine()
+
+ if(eyeobj && loc)
+ eyeobj.loc = loc
+ else
+ to_chat(src, "ERROR: Eyeobj not found. Creating new eye...")
+ eyeobj = new /mob/camera/eye/ai(loc, name, src, src)
+
+ eyeobj.set_loc(loc)
+
+/mob/living/silicon/ai/proc/toggle_fast_holograms()
+ set category = "AI Commands"
+ set name = "Toggle Fast Holograms"
+
+ if(usr.stat == DEAD || !is_ai_eye(eyeobj))
+ return
+ fast_holograms = !fast_holograms
+ to_chat(usr, "Fast holograms have been toggled [fast_holograms ? "on" : "off"].")
+
+/mob/living/silicon/ai/proc/toggle_acceleration()
+ set category = "AI Commands"
+ set name = "Toggle Camera Acceleration"
+
+ if(usr.stat == DEAD)
+ return //won't work if dead
+ if(is_ai_eye(eyeobj))
+ eyeobj.acceleration = !eyeobj.acceleration
+ to_chat(usr, "Camera acceleration has been toggled [eyeobj.acceleration ? "on" : "off"].")
/mob/living/silicon/ai/handle_fire()
return
diff --git a/code/modules/mob/living/silicon/ai/ai_say.dm b/code/modules/mob/living/silicon/ai/ai_say.dm
index 1e676eb05a3..ebcec382ef4 100644
--- a/code/modules/mob/living/silicon/ai/ai_say.dm
+++ b/code/modules/mob/living/silicon/ai/ai_say.dm
@@ -28,7 +28,7 @@
else if(iscarbon(speaker)) // Nonhuman carbon mob
jobname = "No ID"
- else if(isAI(speaker))
+ else if(is_ai(speaker))
jobname = "AI"
else if(isrobot(speaker))
jobname = "Cyborg"
diff --git a/code/modules/mob/living/silicon/ai/freelook/cameranet.dm b/code/modules/mob/living/silicon/ai/freelook/cameranet.dm
deleted file mode 100644
index c98203ef2bd..00000000000
--- a/code/modules/mob/living/silicon/ai/freelook/cameranet.dm
+++ /dev/null
@@ -1,177 +0,0 @@
-// CAMERA NET
-//
-// The datum containing all the chunks.
-GLOBAL_DATUM_INIT(cameranet, /datum/cameranet, new())
-
-/datum/cameranet
- var/name = "Camera Net" // Name to show for VV and stat()
-
- // The cameras on the map, no matter if they work or not. Updated in obj/machinery/camera.dm by New() and Destroy().
- var/list/cameras = list()
- // The chunks of the map, mapping the areas that the cameras can see.
- var/list/chunks = list()
- var/ready = FALSE
-
-// Checks if a chunk has been Generated in x, y, z.
-/datum/cameranet/proc/chunkGenerated(x, y, z)
- x &= ~(CAMERA_CHUNK_SIZE - 1)
- y &= ~(CAMERA_CHUNK_SIZE - 1)
- var/key = "[x],[y],[z]"
- return (chunks[key])
-
-// Returns the chunk in the x, y, z.
-// If there is no chunk, it creates a new chunk and returns that.
-/datum/cameranet/proc/getCameraChunk(x, y, z)
- x &= ~(CAMERA_CHUNK_SIZE - 1)
- y &= ~(CAMERA_CHUNK_SIZE - 1)
- var/key = "[x],[y],[z]"
- if(!chunks[key])
- chunks[key] = new /datum/camerachunk(null, x, y, z)
-
- return chunks[key]
-
-// Updates what the aiEye can see. It is recommended you use this when the aiEye moves or it's location is set.
-
-/datum/cameranet/proc/visibility(list/moved_eyes, client/C, list/other_eyes)
- if(!islist(moved_eyes))
- moved_eyes = moved_eyes ? list(moved_eyes) : list()
- if(islist(other_eyes))
- other_eyes = (other_eyes - moved_eyes)
- else
- other_eyes = list()
-
- var/list/chunks_pre_seen = list()
- var/list/chunks_post_seen = list()
-
- for(var/V in moved_eyes)
- var/mob/camera/ai_eye/eye = V
- if(C)
- chunks_pre_seen |= eye.visibleCameraChunks
- // 0xf = 15
- var/static_range = eye.static_visibility_range
- var/x1 = max(0, eye.x - static_range) & ~(CAMERA_CHUNK_SIZE - 1)
- var/y1 = max(0, eye.y - static_range) & ~(CAMERA_CHUNK_SIZE - 1)
- var/x2 = min(world.maxx, eye.x + static_range) & ~(CAMERA_CHUNK_SIZE - 1)
- var/y2 = min(world.maxy, eye.y + static_range) & ~(CAMERA_CHUNK_SIZE - 1)
-
- var/list/visibleChunks = list()
-
- for(var/x = x1; x <= x2; x += CAMERA_CHUNK_SIZE)
- for(var/y = y1; y <= y2; y += CAMERA_CHUNK_SIZE)
- visibleChunks |= getCameraChunk(x, y, eye.z)
-
- var/list/remove = eye.visibleCameraChunks - visibleChunks
- var/list/add = visibleChunks - eye.visibleCameraChunks
-
- for(var/chunk in remove)
- var/datum/camerachunk/c = chunk
- c.remove(eye, FALSE)
-
- for(var/chunk in add)
- var/datum/camerachunk/c = chunk
- c.add(eye, FALSE)
-
- if(C)
- chunks_post_seen |= eye.visibleCameraChunks
-
- if(C)
- for(var/V in other_eyes)
- var/mob/camera/ai_eye/eye = V
- chunks_post_seen |= eye.visibleCameraChunks
-
- var/list/remove = chunks_pre_seen - chunks_post_seen
- var/list/add = chunks_post_seen - chunks_pre_seen
-
- for(var/chunk in remove)
- var/datum/camerachunk/c = chunk
- C.images -= c.obscured
-
- for(var/chunk in add)
- var/datum/camerachunk/c = chunk
- C.images += c.obscured
-
-
-// Updates the chunks that the turf is located in. Use this when obstacles are destroyed or when doors open.
-
-/datum/cameranet/proc/updateVisibility(atom/A, opacity_check = 1)
-
- if(!SSticker || (opacity_check && !A.opacity))
- return
- majorChunkChange(A, 2)
-
-/datum/cameranet/proc/updateChunk(x, y, z)
- // 0xf = 15
- if(!chunkGenerated(x, y, z))
- return
- var/datum/camerachunk/chunk = getCameraChunk(x, y, z)
- chunk.hasChanged()
-
-// Removes a camera from a chunk.
-
-/datum/cameranet/proc/removeCamera(obj/machinery/camera/c)
- majorChunkChange(c, 0)
-
-// Add a camera to a chunk.
-
-/datum/cameranet/proc/addCamera(obj/machinery/camera/c)
- majorChunkChange(c, 1)
-
-// Used for Cyborg cameras. Since portable cameras can be in ANY chunk.
-
-/datum/cameranet/proc/updatePortableCamera(obj/machinery/camera/c, turf/old_loc)
- majorChunkChange(c, 1, old_loc)
-
-// Never access this proc directly!!!!
-// This will update the chunk and all the surrounding chunks.
-// It will also add the atom to the cameras list if you set the choice to 1.
-// Setting the choice to 0 will remove the camera from the chunks.
-// If you want to update the chunks around an object, without adding/removing a camera, use choice 2.
-
-/datum/cameranet/proc/majorChunkChange(atom/c, choice, turf/old_loc = null)
- // 0xf = 15
- if(!c)
- return
-
- var/turf/T = get_turf(c)
- if(!T)
- return
-
- if(old_loc)
- // Check if the current turf falls in the same chunka as the old_loc. If so, don't do anything
- if(T.x & ~(CAMERA_CHUNK_SIZE - 1) == old_loc.x & ~(CAMERA_CHUNK_SIZE - 1) && T.y & ~(CAMERA_CHUNK_SIZE - 1) == old_loc.y & ~(CAMERA_CHUNK_SIZE - 1))
- return
-
- // Use camera view distance here to actually know how far a camera can max watch
- var/x1 = max(0, T.x - CAMERA_VIEW_DISTANCE) & ~(CAMERA_CHUNK_SIZE - 1)
- var/y1 = max(0, T.y - CAMERA_VIEW_DISTANCE) & ~(CAMERA_CHUNK_SIZE - 1)
- var/x2 = min(world.maxx, T.x + CAMERA_VIEW_DISTANCE) & ~(CAMERA_CHUNK_SIZE - 1)
- var/y2 = min(world.maxy, T.y + CAMERA_VIEW_DISTANCE) & ~(CAMERA_CHUNK_SIZE - 1)
-
- for(var/x = x1; x <= x2; x += CAMERA_CHUNK_SIZE)
- for(var/y = y1; y <= y2; y += CAMERA_CHUNK_SIZE)
- if(chunkGenerated(x, y, T.z))
- var/datum/camerachunk/chunk = getCameraChunk(x, y, T.z)
- if(choice == 0)
- // Remove the camera.
- chunk.remove_camera(c)
- else if(choice == 1)
- // You can't have the same camera in the list twice.
- chunk.add_camera(c)
- chunk.hasChanged()
-
-// Will check if a mob is on a viewable turf. Returns 1 if it is, otherwise returns 0.
-
-/datum/cameranet/proc/checkCameraVis(mob/living/target as mob)
-
- // 0xf = 15
- var/turf/position = get_turf(target)
- return checkTurfVis(position)
-
-/datum/cameranet/proc/checkTurfVis(turf/position)
- var/datum/camerachunk/chunk = getCameraChunk(position.x, position.y, position.z)
- if(chunk)
- if(chunk.changed)
- chunk.hasChanged(1) // Update now, no matter if it's visible or not.
- if(chunk.visibleTurfs[position])
- return 1
- return 0
diff --git a/code/modules/mob/living/silicon/ai/freelook/eye.dm b/code/modules/mob/living/silicon/ai/freelook/eye.dm
deleted file mode 100644
index e4219d090d1..00000000000
--- a/code/modules/mob/living/silicon/ai/freelook/eye.dm
+++ /dev/null
@@ -1,155 +0,0 @@
-// AI EYE
-//
-// An invisible (no icon) mob that the AI controls to look around the station with.
-// It streams chunks as it moves around, which will show it what the AI can and cannot see.
-
-/mob/camera/ai_eye
- name = "Inactive AI Eye"
-
- icon = 'icons/mob/ai.dmi' //Allows ghosts to see what the AI is looking at.
- icon_state = "eye"
- alpha = 127
- invisibility = SEE_INVISIBLE_OBSERVER
-
- var/list/visibleCameraChunks = list()
- var/mob/living/silicon/ai/ai = null
- var/relay_speech = FALSE
- var/use_static = TRUE
- var/static_visibility_range = 16
- // Decides if it is shown by AI Detector or not
- var/ai_detector_visible = TRUE
-
-
-// Use this when setting the aiEye's location.
-// It will also stream the chunk that the new loc is in.
-
-/mob/camera/ai_eye/setLoc(T)
- if(ai)
- if(!isturf(ai.loc))
- return
- T = get_turf(T)
- ..(T)
- if(use_static)
- ai.camera_visibility(src)
- if(ai.client)
- ai.client.eye = src
- update_parallax_contents()
- //Holopad
- if(istype(ai.current, /obj/machinery/hologram/holopad))
- var/obj/machinery/hologram/holopad/H = ai.current
- H.move_hologram(ai, T)
-
-/mob/camera/ai_eye/Move()
- return 0
-
-/mob/camera/ai_eye/Process_Spacemove(movement_dir)
- // Nothing in space can stop us from moving.
- return 1
-
-/mob/camera/ai_eye/proc/GetViewerClient()
- if(ai)
- return ai.client
- return null
-
-/mob/camera/ai_eye/proc/RemoveImages()
- var/client/C = GetViewerClient()
- if(C && use_static)
- for(var/V in visibleCameraChunks)
- var/datum/camerachunk/chunk = V
- C.images -= chunk.obscured
-
-/mob/camera/ai_eye/Destroy()
- if(ai)
- ai.all_eyes -= src
- ai = null
- for(var/V in visibleCameraChunks)
- var/datum/camerachunk/chunk = V
- chunk.remove(src)
- return ..()
-
-/atom/proc/move_camera_by_click()
- if(isAI(usr))
- var/mob/living/silicon/ai/AI = usr
- if(AI.eyeobj && (AI.client.eye == AI.eyeobj) && (AI.eyeobj.z == z))
- AI.cameraFollow = null
- if(isturf(loc) || isturf(src))
- AI.eyeobj.setLoc(src)
-
-// AI MOVEMENT
-
-// This will move the AIEye. It will also cause lights near the eye to light up, if toggled.
-// This is handled in the proc below this one.
-
-/client/proc/AIMove(n, direct, mob/living/silicon/ai/user)
-
- var/initial = initial(user.sprint)
- var/max_sprint = 50
-
- if(user.cooldown && user.cooldown < world.timeofday) // 3 seconds
- user.sprint = initial
-
- for(var/i = 0; i < max(user.sprint, initial); i += 20)
- var/turf/step = get_turf(get_step(user.eyeobj, direct))
- if(step)
- user.eyeobj.setLoc(step)
-
- user.cooldown = world.timeofday + 5
- if(user.acceleration)
- user.sprint = min(user.sprint + 0.5, max_sprint)
- else
- user.sprint = initial
-
- if(!user.tracking)
- user.cameraFollow = null
-
- //user.unset_machine() //Uncomment this if it causes problems.
- //user.lightNearbyCamera()
- if(user.camera_light_on)
- user.light_cameras()
-
-// Return to the Core.
-/mob/living/silicon/ai/proc/core()
- set category = "AI Commands"
- set name = "AI Core"
-
- view_core()
-
-/mob/living/silicon/ai/proc/view_core()
-
- current = null
- cameraFollow = null
- unset_machine()
-
- if(src.eyeobj && src.loc)
- src.eyeobj.loc = src.loc
- else
- to_chat(src, "ERROR: Eyeobj not found. Creating new eye...")
- create_eye()
-
- eyeobj.setLoc(loc)
-
-/mob/living/silicon/ai/proc/create_eye()
- if(eyeobj)
- return
- eyeobj = new /mob/camera/ai_eye()
- all_eyes += eyeobj
- eyeobj.ai = src
- eyeobj.setLoc(loc)
- eyeobj.name = "[name] (AI Eye)"
-
-/mob/living/silicon/ai/proc/toggle_acceleration()
- set category = "AI Commands"
- set name = "Toggle Camera Acceleration"
-
- if(usr.stat == DEAD)
- return //won't work if dead
- acceleration = !acceleration
- to_chat(usr, "Camera acceleration has been toggled [acceleration ? "on" : "off"].")
-
-/mob/camera/ai_eye/hear_say(list/message_pieces, verb = "says", italics = 0, mob/speaker = null, sound/speech_sound, sound_vol, sound_frequency, use_voice = TRUE)
- if(relay_speech)
- if(istype(ai))
- ai.relay_speech(speaker, message_pieces, verb)
- else
- var/mob/M = ai
- M.hear_say(message_pieces, verb, italics, speaker, speech_sound, sound_vol, sound_frequency)
diff --git a/code/modules/mob/living/silicon/robot/robot_mob.dm b/code/modules/mob/living/silicon/robot/robot_mob.dm
index 1695045530a..4b49a4010b1 100644
--- a/code/modules/mob/living/silicon/robot/robot_mob.dm
+++ b/code/modules/mob/living/silicon/robot/robot_mob.dm
@@ -1424,7 +1424,7 @@ GLOBAL_LIST_INIT(robot_verbs_default, list(
. = ..()
if(camera && last_camera_update + CAMERA_UPDATE_COOLDOWN < world.time)
last_camera_update = world.time
- GLOB.cameranet.updatePortableCamera(camera, OldLoc)
+ GLOB.cameranet.update_portable_camera(camera, OldLoc)
SEND_SIGNAL(camera, COMSIG_CAMERA_MOVED, OldLoc)
#undef CAMERA_UPDATE_COOLDOWN
diff --git a/code/modules/mob/mob.dm b/code/modules/mob/mob.dm
index 6cc28544343..f6ada6c5994 100644
--- a/code/modules/mob/mob.dm
+++ b/code/modules/mob/mob.dm
@@ -805,8 +805,8 @@ GLOBAL_LIST_INIT(slot_equipment_priority, list( \
reset_perspective(null)
unset_machine()
if(isliving(src))
- if(src:cameraFollow)
- src:cameraFollow = null
+ if(src:camera_follow)
+ src:camera_follow = null
/mob/Topic(href, href_list)
if(href_list["flavor_more"])
diff --git a/code/modules/mob/mob_misc_procs.dm b/code/modules/mob/mob_misc_procs.dm
index a9d99cfb3f0..9ffcbc99bc4 100644
--- a/code/modules/mob/mob_misc_procs.dm
+++ b/code/modules/mob/mob_misc_procs.dm
@@ -461,7 +461,7 @@
if(hud_used && hud_used.action_intent)
hud_used.action_intent.icon_state = "[a_intent]"
- else if(isrobot(src) || islarva(src) || isanimal(src) || isAI(src))
+ else if(isrobot(src) || islarva(src) || isanimal(src) || is_ai(src))
switch(input)
if(INTENT_HELP)
a_intent = INTENT_HELP
@@ -511,7 +511,7 @@
var/obj/item/multitool/P
if(isrobot(user) || ishuman(user))
P = user.get_active_hand()
- else if(isAI(user))
+ else if(is_ai(user))
var/mob/living/silicon/ai/AI=user
P = AI.aiMulti
diff --git a/code/modules/mob/mob_movement.dm b/code/modules/mob/mob_movement.dm
index 6f1cd194d7f..80254530dca 100644
--- a/code/modules/mob/mob_movement.dm
+++ b/code/modules/mob/mob_movement.dm
@@ -91,12 +91,17 @@
if(mob.remote_control) //we're controlling something, our movement is relayed to it
return mob.remote_control.relaymove(mob, direct)
- if(isAI(mob))
- if(istype(mob.loc, /obj/item/aicard))
- var/obj/O = mob.loc
- return O.relaymove(mob, direct) // aicards have special relaymove stuff
- return AIMove(n, direct, mob)
-
+ if(is_ai(mob))
+ var/mob/living/silicon/ai/ai = mob
+ var/mob/camera/eye/ai/eye = ai.eyeobj
+ if(istype(eye) && !istype(ai.remote_control))
+ ai.remote_control = eye
+ return eye.relaymove(mob, direct)
+ if(!istype(eye) && !istype(mob.loc, /obj/item/aicard))
+ eye = new /mob/camera/eye/ai(mob.loc, ai.name, ai, ai)
+ if(istype(eye))
+ return eye.relaymove(mob, direct)
+ return FALSE // If the AI is outside of its eye or a mech (e.g. carded), it can't move
if(Process_Grab())
return
diff --git a/code/modules/mob/mob_say_base.dm b/code/modules/mob/mob_say_base.dm
index ddb279e0ac9..c3bc723c4d3 100644
--- a/code/modules/mob/mob_say_base.dm
+++ b/code/modules/mob/mob_say_base.dm
@@ -89,7 +89,7 @@
var/mob/other_mob = other
if(other_mob.universal_speak)
return TRUE
- if(isAI(src) && ispAI(other_mob))
+ if(is_ai(src) && ispAI(other_mob))
return TRUE
if(istype(other_mob, src.type) || istype(src, other_mob.type))
return TRUE
diff --git a/code/modules/paperwork/photocopier.dm b/code/modules/paperwork/photocopier.dm
index 4c9ab5822db..0ddea1a79e2 100644
--- a/code/modules/paperwork/photocopier.dm
+++ b/code/modules/paperwork/photocopier.dm
@@ -525,7 +525,7 @@
toner = 0
/obj/machinery/photocopier/MouseDrop_T(mob/target, mob/living/user)
- if(!istype(target) || target.buckled || get_dist(user, src) > 1 || get_dist(user, target) > 1 || user.stat || isAI(user) || target.move_resist > user.pull_force)
+ if(!istype(target) || target.buckled || get_dist(user, src) > 1 || get_dist(user, target) > 1 || user.stat || is_ai(user) || target.move_resist > user.pull_force)
return
if(check_mob()) //is target mob or another mob on this photocopier already?
return
diff --git a/code/modules/paperwork/silicon_photography.dm b/code/modules/paperwork/silicon_photography.dm
index dedde0f789f..f8180ef4a5a 100644
--- a/code/modules/paperwork/silicon_photography.dm
+++ b/code/modules/paperwork/silicon_photography.dm
@@ -165,7 +165,7 @@
deletepicture(src)
/obj/item/camera/siliconcam/proc/getsource()
- if(isAI(loc))
+ if(is_ai(loc))
return src
var/mob/living/silicon/robot/C = loc
diff --git a/code/modules/power/apc/apc.dm b/code/modules/power/apc/apc.dm
index 6552d232ce6..ffb063c52d4 100644
--- a/code/modules/power/apc/apc.dm
+++ b/code/modules/power/apc/apc.dm
@@ -518,7 +518,7 @@
/obj/machinery/power/apc/proc/is_authenticated(mob/user as mob)
if(user.can_admin_interact())
return TRUE
- if(isAI(user) || isrobot(user) || user.has_unlimited_silicon_privilege)
+ if(is_ai(user) || isrobot(user) || user.has_unlimited_silicon_privilege)
return TRUE
else
return !locked
@@ -526,7 +526,7 @@
/obj/machinery/power/apc/proc/is_locked(mob/user as mob)
if(user.can_admin_interact())
return FALSE
- if(isAI(user) || isrobot(user) || user.has_unlimited_silicon_privilege)
+ if(is_ai(user) || isrobot(user) || user.has_unlimited_silicon_privilege)
return FALSE
else
return locked
diff --git a/code/modules/power/generators/portable generators/pacman.dm b/code/modules/power/generators/portable generators/pacman.dm
index f350c7bf8a1..12705003760 100644
--- a/code/modules/power/generators/portable generators/pacman.dm
+++ b/code/modules/power/generators/portable generators/pacman.dm
@@ -263,7 +263,7 @@
var/list/data = list()
data["active"] = active
- if(isAI(user))
+ if(is_ai(user))
data["is_ai"] = TRUE
else if(isrobot(user) && !Adjacent(user))
data["is_ai"] = TRUE
diff --git a/code/modules/projectiles/projectile/beams.dm b/code/modules/projectiles/projectile/beams.dm
index 86ff7958f7a..59e51c611ac 100644
--- a/code/modules/projectiles/projectile/beams.dm
+++ b/code/modules/projectiles/projectile/beams.dm
@@ -52,7 +52,7 @@
impact_light_color_override = LIGHT_COLOR_DARKRED
/obj/item/projectile/beam/laser/ai_turret/prehit(atom/target)
- if(isAI(target))
+ if(is_ai(target))
damage = 0 //cheater cheater I don't want AI to die to stupid placement eater
nodamage = 1
if(isliving(target))
diff --git a/code/modules/recycling/disposal.dm b/code/modules/recycling/disposal.dm
index 0ea0f0e2f01..33a01ea0c84 100644
--- a/code/modules/recycling/disposal.dm
+++ b/code/modules/recycling/disposal.dm
@@ -273,7 +273,7 @@
// mouse drop another mob or self
//
/obj/machinery/disposal/MouseDrop_T(mob/living/target, mob/living/user)
- if(!istype(target) || target.buckled || target.has_buckled_mobs() || get_dist(user, src) > 1 || get_dist(user, target) > 1 || user.stat || isAI(user))
+ if(!istype(target) || target.buckled || target.has_buckled_mobs() || get_dist(user, src) > 1 || get_dist(user, target) > 1 || user.stat || is_ai(user))
return
// Animals cannot put mobs other than themselves into disposals.
@@ -389,7 +389,7 @@
/obj/machinery/disposal/ui_data(mob/user)
var/list/data = list()
- data["isAI"] = isAI(user)
+ data["is_ai"] = is_ai(user)
data["flushing"] = flush
data["mode"] = mode
data["pressure"] = round(clamp(100* air_contents.return_pressure() / (SEND_PRESSURE), 0, 100),1)
diff --git a/code/modules/recycling/sortingmachinery.dm b/code/modules/recycling/sortingmachinery.dm
index ddc87780cbc..1a391158a0c 100644
--- a/code/modules/recycling/sortingmachinery.dm
+++ b/code/modules/recycling/sortingmachinery.dm
@@ -308,7 +308,7 @@
. = ..()
/obj/machinery/disposal/delivery_chute/Bumped(atom/movable/AM) //Go straight into the chute
- if(isprojectile(AM) || isAI(AM) || QDELETED(AM))
+ if(isprojectile(AM) || is_ai(AM) || QDELETED(AM))
return
// We may already contain the object because thrown objects
diff --git a/code/modules/research/xenobiology/xenobio_camera.dm b/code/modules/research/xenobiology/xenobio_camera.dm
index fe330b6a36e..84a60c49cf0 100644
--- a/code/modules/research/xenobiology/xenobio_camera.dm
+++ b/code/modules/research/xenobiology/xenobio_camera.dm
@@ -1,26 +1,3 @@
-//Xenobio control console
-/mob/camera/ai_eye/remote/xenobio
- visible_icon = 1
- icon = 'icons/obj/abductor.dmi'
- icon_state = "camera_target"
- // The Xenobio Console does not trigger the AI Detector
- ai_detector_visible = FALSE
- /// Area that the xenobio camera eye is allowed to travel
- var/allowed_area = null
-
-/mob/camera/ai_eye/remote/xenobio/Initialize(mapload)
- . = ..()
- var/area/A = get_area(loc)
- allowed_area = A.name
-
-/mob/camera/ai_eye/remote/xenobio/setLoc(t)
- var/area/new_area = get_area(t)
- if(!new_area)
- return
- if(new_area.name != allowed_area && !new_area.xenobiology_compatible)
- return
- return ..()
-
/*
* # Slime Management Console
*
@@ -54,6 +31,10 @@
if(!connected_recycler)
locate_recycler()
+/obj/machinery/computer/camera_advanced/xenobio/CreateEye()
+ eyeobj = new /mob/camera/eye/xenobio(loc, name, src, current_user)
+ give_eye_control(current_user)
+
/obj/machinery/computer/camera_advanced/xenobio/proc/locate_recycler()
for(var/obj/machinery/monkey_recycler/recycler in GLOB.monkey_recyclers)
if(get_area(recycler) == get_area(loc))
@@ -79,14 +60,6 @@
stored_slimes -= A
return ..()
-/obj/machinery/computer/camera_advanced/xenobio/CreateEye()
- eyeobj = new /mob/camera/ai_eye/remote/xenobio(get_turf(src))
- eyeobj.origin = src
- eyeobj.visible_icon = TRUE
- eyeobj.acceleration = FALSE
- eyeobj.icon = 'icons/obj/abductor.dmi'
- eyeobj.icon_state = "camera_target"
-
/obj/machinery/computer/camera_advanced/xenobio/GrantActions(mob/living/carbon/user)
..()
@@ -223,13 +196,13 @@
if(!target || !ishuman(owner))
return
var/mob/living/carbon/human/C = owner
- var/mob/camera/ai_eye/remote/xenobio/remote_eye = C.remote_control
+ var/mob/camera/eye/xenobio/remote_eye = C.remote_control
var/obj/machinery/computer/camera_advanced/xenobio/X = target
if(iswallturf(remote_eye.loc))
to_chat(owner, "You can't place slime here.")
return
- else if(GLOB.cameranet.checkTurfVis(remote_eye.loc))
+ else if(GLOB.cameranet.check_turf_vis(remote_eye.loc))
for(var/mob/living/simple_animal/slime/S in X.stored_slimes)
X.release_slime(S, remote_eye.loc)
else
@@ -243,10 +216,10 @@
if(!target || !ishuman(owner))
return
var/mob/living/carbon/human/C = owner
- var/mob/camera/ai_eye/remote/xenobio/remote_eye = C.remote_control
+ var/mob/camera/eye/xenobio/remote_eye = C.remote_control
var/obj/machinery/computer/camera_advanced/xenobio/X = target
- if(GLOB.cameranet.checkTurfVis(remote_eye.loc))
+ if(GLOB.cameranet.check_turf_vis(remote_eye.loc))
for(var/mob/living/simple_animal/slime/S in remote_eye.loc)
if(length(X.stored_slimes) >= X.max_slimes)
break
@@ -265,11 +238,11 @@
if(!target || !ishuman(owner))
return
var/mob/living/carbon/human/C = owner
- var/mob/camera/ai_eye/remote/xenobio/remote_eye = C.remote_control
+ var/mob/camera/eye/xenobio/remote_eye = C.remote_control
var/obj/machinery/computer/camera_advanced/xenobio/X = target
var/obj/machinery/monkey_recycler/recycler = X.connected_recycler
- if(GLOB.cameranet.checkTurfVis(remote_eye.loc))
+ if(GLOB.cameranet.check_turf_vis(remote_eye.loc))
if(LAZYLEN(SSmobs.cubemonkeys) >= GLOB.configuration.general.monkey_cube_cap)
to_chat(owner, "Bluespace harmonics prevent the spawning of more than [GLOB.configuration.general.monkey_cube_cap] monkeys on the station at one time!")
return
@@ -309,14 +282,14 @@
if(!target || !ishuman(owner))
return
var/mob/living/carbon/human/C = owner
- var/mob/camera/ai_eye/remote/xenobio/remote_eye = C.remote_control
+ var/mob/camera/eye/xenobio/remote_eye = C.remote_control
var/obj/machinery/computer/camera_advanced/xenobio/X = target
var/obj/machinery/monkey_recycler/recycler = X.connected_recycler
if(!recycler)
to_chat(owner, "There is no connected monkey recycler. Use a multitool to link one.")
return
- if(GLOB.cameranet.checkTurfVis(remote_eye.loc))
+ if(GLOB.cameranet.check_turf_vis(remote_eye.loc))
for(var/mob/living/carbon/human/M in remote_eye.loc)
if(issmall(M) && M.stat)
M.visible_message("[M] vanishes as [M.p_theyre()] reclaimed for recycling!")
@@ -334,9 +307,9 @@
if(!target || !isliving(owner))
return
var/mob/living/C = owner
- var/mob/camera/ai_eye/remote/xenobio/remote_eye = C.remote_control
+ var/mob/camera/eye/xenobio/remote_eye = C.remote_control
- if(GLOB.cameranet.checkTurfVis(remote_eye.loc))
+ if(GLOB.cameranet.check_turf_vis(remote_eye.loc))
for(var/mob/living/simple_animal/slime/S in remote_eye.loc)
slime_scan(S, C)
else
@@ -351,14 +324,14 @@
return
var/mob/living/carbon/human/C = owner
- var/mob/camera/ai_eye/remote/xenobio/remote_eye = C.remote_control
+ var/mob/camera/eye/xenobio/remote_eye = C.remote_control
var/obj/machinery/computer/camera_advanced/xenobio/X = target
if(QDELETED(X.current_potion))
to_chat(owner, "No potion loaded.")
return
- if(GLOB.cameranet.checkTurfVis(remote_eye.loc))
+ if(GLOB.cameranet.check_turf_vis(remote_eye.loc))
for(var/mob/living/simple_animal/slime/S in remote_eye.loc)
X.current_potion.attack__legacy__attackchain(S, C)
break
@@ -416,22 +389,22 @@
// Scans slime
/obj/machinery/computer/camera_advanced/xenobio/proc/XenoSlimeClickCtrl(mob/living/user, mob/living/simple_animal/slime/S)
- if(!GLOB.cameranet.checkTurfVis(S.loc))
+ if(!GLOB.cameranet.check_turf_vis(S.loc))
to_chat(user, "Target is not near a camera. Cannot proceed.")
return
var/mob/living/C = user
- var/mob/camera/ai_eye/remote/xenobio/E = C.remote_control
+ var/mob/camera/eye/xenobio/E = C.remote_control
var/area/mobarea = get_area(S.loc)
if(mobarea.name == E.allowed_area || mobarea.xenobiology_compatible)
slime_scan(S, C)
//Feeds a potion to slime
/obj/machinery/computer/camera_advanced/xenobio/proc/XenoSlimeClickAlt(mob/living/user, mob/living/simple_animal/slime/S)
- if(!GLOB.cameranet.checkTurfVis(S.loc))
+ if(!GLOB.cameranet.check_turf_vis(S.loc))
to_chat(user, "Target is not near a camera. Cannot proceed.")
return
var/mob/living/C = user
- var/mob/camera/ai_eye/remote/xenobio/E = C.remote_control
+ var/mob/camera/eye/xenobio/E = C.remote_control
var/obj/machinery/computer/camera_advanced/xenobio/X = E.origin
var/area/mobarea = get_area(S.loc)
if(!X.current_potion)
@@ -442,11 +415,11 @@
//Picks up slime
/obj/machinery/computer/camera_advanced/xenobio/proc/XenoSlimeClickShift(mob/living/user, mob/living/simple_animal/slime/S)
- if(!GLOB.cameranet.checkTurfVis(S.loc))
+ if(!GLOB.cameranet.check_turf_vis(S.loc))
to_chat(user, "Target is not near a camera. Cannot proceed.")
return
var/mob/living/C = user
- var/mob/camera/ai_eye/remote/xenobio/E = C.remote_control
+ var/mob/camera/eye/xenobio/E = C.remote_control
var/obj/machinery/computer/camera_advanced/xenobio/X = E.origin
var/area/mobarea = get_area(S.loc)
if(mobarea.name == E.allowed_area || mobarea.xenobiology_compatible)
@@ -463,11 +436,11 @@
//Place slimes
/obj/machinery/computer/camera_advanced/xenobio/proc/XenoTurfClickShift(mob/living/user, turf/T)
- if(!GLOB.cameranet.checkTurfVis(T))
+ if(!GLOB.cameranet.check_turf_vis(T))
to_chat(user, "Target is not near a camera. Cannot proceed.")
return
var/mob/living/C = user
- var/mob/camera/ai_eye/remote/xenobio/E = C.remote_control
+ var/mob/camera/eye/xenobio/E = C.remote_control
var/obj/machinery/computer/camera_advanced/xenobio/X = E.origin
var/area/turfarea = get_area(T)
if(iswallturf(T))
@@ -479,11 +452,11 @@
//Place monkey
/obj/machinery/computer/camera_advanced/xenobio/proc/XenoTurfClickCtrl(mob/living/user, turf/T)
- if(!GLOB.cameranet.checkTurfVis(T))
+ if(!GLOB.cameranet.check_turf_vis(T))
to_chat(user, "Target is not near a camera. Cannot proceed.")
return
var/mob/living/C = user
- var/mob/camera/ai_eye/remote/xenobio/E = C.remote_control
+ var/mob/camera/eye/xenobio/E = C.remote_control
var/obj/machinery/computer/camera_advanced/xenobio/X = E.origin
var/obj/machinery/monkey_recycler/recycler = X.connected_recycler
var/area/turfarea = get_area(T)
@@ -513,11 +486,11 @@
//Pick up monkey
/obj/machinery/computer/camera_advanced/xenobio/proc/XenoMonkeyClickCtrl(mob/living/user, mob/living/carbon/human/M)
- if(!GLOB.cameranet.checkTurfVis(M.loc))
+ if(!GLOB.cameranet.check_turf_vis(M.loc))
to_chat(user, "Target is not near a camera. Cannot proceed.")
return
var/mob/living/C = user
- var/mob/camera/ai_eye/remote/xenobio/E = C.remote_control
+ var/mob/camera/eye/xenobio/E = C.remote_control
var/obj/machinery/computer/camera_advanced/xenobio/X = E.origin
var/area/mobarea = get_area(M.loc)
var/obj/machinery/monkey_recycler/recycler = X.connected_recycler
diff --git a/code/modules/shuttle/emergency.dm b/code/modules/shuttle/emergency.dm
index 762fba8ab68..8c41e177816 100644
--- a/code/modules/shuttle/emergency.dm
+++ b/code/modules/shuttle/emergency.dm
@@ -182,7 +182,7 @@
attempt_hijack_stage(user)
/obj/machinery/computer/emergency_shuttle/proc/attempt_hijack_stage(mob/living/user)
- var/is_ai = isAI(user)
+ var/is_ai = is_ai(user)
if(!Adjacent(user) && !is_ai)
return
if(!ishuman(user) && !is_ai) //No, xenomorphs, constructs and traitors in cyborgs can not hack it.
diff --git a/code/modules/shuttle/navigation_computer.dm b/code/modules/shuttle/navigation_computer.dm
index ac9c5a4add9..9cdaca55d54 100644
--- a/code/modules/shuttle/navigation_computer.dm
+++ b/code/modules/shuttle/navigation_computer.dm
@@ -55,8 +55,8 @@
shuttle_port = null
return
- eyeobj = new /mob/camera/ai_eye/remote/shuttle_docker(get_turf(locate("landmark*Observer-Start")), src) // There should always be an observer start landmark
- var/mob/camera/ai_eye/remote/shuttle_docker/the_eye = eyeobj
+ eyeobj = new /mob/camera/eye/shuttle_docker(get_turf(locate("landmark*Observer-Start")), name, src, current_user) // There should always be an observer start landmark
+ var/mob/camera/eye/shuttle_docker/the_eye = eyeobj
the_eye.setDir(shuttle_port.dir)
var/turf/origin = locate(shuttle_port.x + x_offset, shuttle_port.y + y_offset, shuttle_port.z)
for(var/V in shuttle_port.shuttle_areas)
@@ -72,11 +72,12 @@
I.plane = 0
I.mouse_opacity = MOUSE_OPACITY_TRANSPARENT
the_eye.placement_images[I] = list(x_off, y_off)
+ give_eye_control(current_user)
/obj/machinery/computer/camera_advanced/shuttle_docker/give_eye_control(mob/user)
..()
if(!QDELETED(user) && user.client)
- var/mob/camera/ai_eye/remote/shuttle_docker/the_eye = eyeobj
+ var/mob/camera/eye/shuttle_docker/the_eye = eyeobj
var/list/to_add = list()
to_add += the_eye.placement_images
to_add += the_eye.placed_images
@@ -89,7 +90,7 @@
/obj/machinery/computer/camera_advanced/shuttle_docker/remove_eye_control(mob/living/user)
..()
if(!QDELETED(user) && user.client)
- var/mob/camera/ai_eye/remote/shuttle_docker/the_eye = eyeobj
+ var/mob/camera/eye/shuttle_docker/the_eye = eyeobj
var/list/to_remove = list()
to_remove += the_eye.placement_images
to_remove += the_eye.placed_images
@@ -103,8 +104,8 @@
if(designating_target_loc || !current_user)
return
- var/mob/camera/ai_eye/remote/shuttle_docker/the_eye = eyeobj
- var/landing_clear = checkLandingSpot()
+ var/mob/camera/eye/shuttle_docker/the_eye = eyeobj
+ var/landing_clear = check_landing_spot()
if(designate_time && (landing_clear != SHUTTLE_DOCKER_BLOCKED))
to_chat(current_user, "Targeting transit location, please wait [DisplayTimeText(designate_time)]...")
designating_target_loc = the_eye.loc
@@ -115,7 +116,7 @@
if(!wait_completed)
to_chat(current_user, "Operation aborted.")
return
- landing_clear = checkLandingSpot()
+ landing_clear = check_landing_spot()
if(landing_clear != SHUTTLE_DOCKER_LANDING_CLEAR)
switch(landing_clear)
@@ -162,7 +163,7 @@
return TRUE
/obj/machinery/computer/camera_advanced/shuttle_docker/proc/rotateLandingSpot()
- var/mob/camera/ai_eye/remote/shuttle_docker/the_eye = eyeobj
+ var/mob/camera/eye/shuttle_docker/the_eye = eyeobj
var/list/image_cache = the_eye.placement_images
the_eye.setDir(turn(the_eye.dir, -90))
for(var/i in 1 to length(image_cache))
@@ -175,10 +176,10 @@
var/Tmp = x_offset
x_offset = y_offset
y_offset = -Tmp
- checkLandingSpot()
+ check_landing_spot()
-/obj/machinery/computer/camera_advanced/shuttle_docker/proc/checkLandingSpot()
- var/mob/camera/ai_eye/remote/shuttle_docker/the_eye = eyeobj
+/obj/machinery/computer/camera_advanced/shuttle_docker/proc/check_landing_spot()
+ var/mob/camera/eye/shuttle_docker/the_eye = eyeobj
var/turf/eyeturf = get_turf(the_eye)
if(!eyeturf)
return SHUTTLE_DOCKER_BLOCKED
@@ -253,34 +254,6 @@
if(dock)
jumpto_ports[dock.id] = TRUE
-/mob/camera/ai_eye/remote/shuttle_docker
- visible_icon = FALSE
- use_static = FALSE
- simulated = FALSE
- // The Shuttle Docker does not trigger the AI Detector
- ai_detector_visible = FALSE
- var/list/placement_images = list()
- var/list/placed_images = list()
-
-/mob/camera/ai_eye/remote/shuttle_docker/Initialize(mapload, obj/machinery/computer/camera_advanced/origin)
- src.origin = origin
- return ..()
-
-/mob/camera/ai_eye/remote/shuttle_docker/setLoc(T)
- if(isspaceturf(get_turf(T)) || isspacearea(get_area(T)) || istype(get_area(T), /area/shuttle))
- ..()
- var/obj/machinery/computer/camera_advanced/shuttle_docker/console = origin
- console.checkLandingSpot()
- return
- else
- return
-
-/mob/camera/ai_eye/remote/shuttle_docker/update_remote_sight(mob/living/user)
- user.sight = SEE_TURFS
-
- ..()
- return TRUE
-
/datum/action/innate/shuttledocker_rotate
name = "Rotate"
button_overlay_icon = 'icons/mob/actions/actions_mecha.dmi'
@@ -290,7 +263,7 @@
if(QDELETED(target) || !isliving(target))
return
var/mob/living/C = target
- var/mob/camera/ai_eye/remote/remote_eye = C.remote_control
+ var/mob/camera/eye/remote_eye = C.remote_control
var/obj/machinery/computer/camera_advanced/shuttle_docker/origin = remote_eye.origin
origin.rotateLandingSpot()
@@ -303,7 +276,7 @@
if(QDELETED(target) || !isliving(target))
return
var/mob/living/C = target
- var/mob/camera/ai_eye/remote/remote_eye = C.remote_control
+ var/mob/camera/eye/remote_eye = C.remote_control
var/obj/machinery/computer/camera_advanced/shuttle_docker/origin = remote_eye.origin
origin.placeLandingSpot(target)
@@ -315,7 +288,7 @@
if(QDELETED(target) || !isliving(target))
return
var/mob/living/C = target
- var/mob/camera/ai_eye/remote/remote_eye = C.remote_control
+ var/mob/camera/eye/remote_eye = C.remote_control
var/obj/machinery/computer/camera_advanced/shuttle_docker/console = remote_eye.origin
playsound(console, 'sound/machines/terminal_prompt_deny.ogg', 25, 0)
@@ -337,7 +310,7 @@
var/turf/T = get_turf(L[selected])
if(T)
playsound(console, 'sound/machines/terminal_prompt_confirm.ogg', 25, 0)
- remote_eye.setLoc(T)
+ remote_eye.set_loc(T)
to_chat(target, "Jumped to [selected]")
else
playsound(console, 'sound/machines/terminal_prompt_deny.ogg', 25, 0)
diff --git a/code/modules/surgery/organs/vocal_cords.dm b/code/modules/surgery/organs/vocal_cords.dm
index a4e35b9bec9..289beee4223 100644
--- a/code/modules/surgery/organs/vocal_cords.dm
+++ b/code/modules/surgery/organs/vocal_cords.dm
@@ -166,8 +166,8 @@ GLOBAL_DATUM_INIT(multispin_words, /regex, regex("like a record baby"))
var/mob/living/carbon/human/H = L
if(H.check_ear_prot() >= HEARING_PROTECTION_TOTAL)
continue
- if(istype(L, /mob/camera/ai_eye))
- var/mob/camera/ai_eye/ai_eye = L
+ if(istype(L, /mob/camera/eye/ai))
+ var/mob/camera/eye/ai/ai_eye = L
if(ai_eye.relay_speech && ai_eye.ai)
listeners += ai_eye.ai
else
diff --git a/code/modules/tgui/modules/crew_monitor.dm b/code/modules/tgui/modules/crew_monitor.dm
index 7b8df4bae23..f10b8ac3b59 100644
--- a/code/modules/tgui/modules/crew_monitor.dm
+++ b/code/modules/tgui/modules/crew_monitor.dm
@@ -37,7 +37,7 @@
switch(action)
if("track")
var/mob/living/carbon/human/H = locate(params["track"]) in GLOB.human_list
- if(isAI(usr))
+ if(is_ai(usr))
var/mob/living/silicon/ai/AI = usr
if(hassensorlevel(H, SUIT_SENSOR_TRACKING))
AI.ai_actual_track(H)
@@ -105,7 +105,7 @@
data["offsetX"] = offset_x
data["offsetY"] = offset_y
- data["isAI"] = isAI(user)
+ data["isAI"] = is_ai(user)
data["isObserver"] = isobserver(user)
data["ignoreSensors"] = ignore_sensors
data["crewmembers"] = GLOB.crew_repository.health_data(viewing_current_z_level, ignore_sensors)
diff --git a/code/modules/tgui/modules/law_manager.dm b/code/modules/tgui/modules/law_manager.dm
index 001a8bdc31c..4e8cf27f791 100644
--- a/code/modules/tgui/modules/law_manager.dm
+++ b/code/modules/tgui/modules/law_manager.dm
@@ -140,7 +140,7 @@
if("notify_laws")
to_chat(owner, "Law Notice")
owner.laws.show_laws(owner)
- if(isAI(owner))
+ if(is_ai(owner))
var/mob/living/silicon/ai/AI = owner
for(var/mob/living/silicon/robot/R in AI.connected_robots)
to_chat(R, "Law Notice")
@@ -178,7 +178,7 @@
package_laws(data, "inherent_laws", owner.laws.inherent_laws)
package_laws(data, "supplied_laws", owner.laws.supplied_laws)
- data["isAI"] = isAI(owner)
+ data["isAI"] = is_ai(owner)
data["isMalf"] = is_malf(user)
data["isSlaved"] = owner.is_slaved()
data["isAdmin"] = is_admin(user)
diff --git a/code/modules/tgui/plugins/tgui_login.dm b/code/modules/tgui/plugins/tgui_login.dm
index 0f80f0a13fe..ea1beabaf6e 100644
--- a/code/modules/tgui/plugins/tgui_login.dm
+++ b/code/modules/tgui/plugins/tgui_login.dm
@@ -56,7 +56,7 @@ GLOBAL_LIST(ui_logins)
"rank" = state.rank,
"logged_in" = state.logged_in,
)
- data["isAI"] = isAI(user)
+ data["isAI"] = is_ai(user)
data["isRobot"] = isrobot(user)
data["isAdmin"] = user.can_admin_interact()
@@ -133,7 +133,7 @@ GLOBAL_LIST(ui_logins)
else
to_chat(usr, "Access Denied")
return
- else if(login_type == LOGIN_TYPE_AI && isAI(usr))
+ else if(login_type == LOGIN_TYPE_AI && is_ai(usr))
state.name = usr.name
state.rank = "AI"
else if(login_type == LOGIN_TYPE_ROBOT && isrobot(usr))
diff --git a/paradise.dme b/paradise.dme
index 06372adc927..0ad61290e5c 100644
--- a/paradise.dme
+++ b/paradise.dme
@@ -2214,6 +2214,15 @@
#include "code\modules\mob\transform_procs.dm"
#include "code\modules\mob\typing_indicator.dm"
#include "code\modules\mob\camera\camera_mob.dm"
+#include "code\modules\mob\camera\cameranet.dm"
+#include "code\modules\mob\camera\chunk.dm"
+#include "code\modules\mob\camera\eye.dm"
+#include "code\modules\mob\camera\eye\abductor.dm"
+#include "code\modules\mob\camera\eye\ai_eye.dm"
+#include "code\modules\mob\camera\eye\hologram_eye.dm"
+#include "code\modules\mob\camera\eye\shuttle_navigator.dm"
+#include "code\modules\mob\camera\eye\syndicate.dm"
+#include "code\modules\mob\camera\eye\xenobio_eye.dm"
#include "code\modules\mob\dead\dead.dm"
#include "code\modules\mob\dead\observer\observer_base.dm"
#include "code\modules\mob\dead\observer\observer_login.dm"
@@ -2349,9 +2358,6 @@
#include "code\modules\mob\living\silicon\ai\ai_update_status.dm"
#include "code\modules\mob\living\silicon\ai\latejoin.dm"
#include "code\modules\mob\living\silicon\ai\ai_verbs\botcall.dm"
-#include "code\modules\mob\living\silicon\ai\freelook\cameranet.dm"
-#include "code\modules\mob\living\silicon\ai\freelook\chunk.dm"
-#include "code\modules\mob\living\silicon\ai\freelook\eye.dm"
#include "code\modules\mob\living\silicon\decoy\decoy.dm"
#include "code\modules\mob\living\silicon\decoy\decoy_death.dm"
#include "code\modules\mob\living\silicon\decoy\decoy_life.dm"