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"