// 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/aiEye name = "Inactive AI Eye" invisibility = INVISIBILITY_MAXIMUM hud_possible = list(ANTAG_HUD, AI_DETECT_HUD = HUD_LIST_LIST) var/list/visibleCameraChunks = list() var/mob/living/silicon/ai/ai = null var/relay_speech = FALSE var/use_static = USE_STATIC_OPAQUE var/static_visibility_range = 16 var/ai_detector_visible = TRUE var/ai_detector_color = COLOR_RED /mob/camera/aiEye/Initialize() . = ..() GLOB.aiEyes += src update_ai_detect_hud() setLoc(loc, TRUE) /mob/camera/aiEye/proc/update_ai_detect_hud() var/datum/atom_hud/ai_detector/hud = GLOB.huds[DATA_HUD_AI_DETECT] var/list/old_images = hud_list[AI_DETECT_HUD] if(!ai_detector_visible) hud.remove_from_hud(src) QDEL_LIST(old_images) return if(!hud.hudusers.len) //no one is watching, do not bother updating anything return hud.remove_from_hud(src) var/static/list/vis_contents_objects = list() var/obj/effect/overlay/ai_detect_hud/hud_obj = vis_contents_objects[ai_detector_color] if(!hud_obj) hud_obj = new /obj/effect/overlay/ai_detect_hud() hud_obj.color = ai_detector_color vis_contents_objects[ai_detector_color] = hud_obj var/list/new_images = list() var/list/turfs = get_visible_turfs() for(var/T in turfs) var/image/I = (old_images.len > new_images.len) ? old_images[new_images.len + 1] : image(null, T) I.loc = T I.vis_contents += hud_obj new_images += I for(var/i in (new_images.len + 1) to old_images.len) qdel(old_images[i]) hud_list[AI_DETECT_HUD] = new_images hud.add_to_hud(src) /mob/camera/aiEye/proc/get_visible_turfs() if(!isturf(loc)) return list() var/client/C = GetViewerClient() var/view = C ? getviewsize(C.view) : getviewsize(world.view) var/turf/lowerleft = locate(max(1, x - (view[1] - 1)/2), max(1, y - (view[2] - 1)/2), z) var/turf/upperright = locate(min(world.maxx, lowerleft.x + (view[1] - 1)), min(world.maxy, lowerleft.y + (view[2] - 1)), lowerleft.z) return block(lowerleft, upperright) // Use this when setting the aiEye's location. // It will also stream the chunk that the new loc is in. /mob/camera/aiEye/proc/setLoc(T, force_update = FALSE) if(ai) if(!isturf(ai.loc)) return T = get_turf(T) if(!force_update && (T == get_turf(src)) ) return //we are already here! if (T) forceMove(T) else moveToNullspace() if(use_static != USE_STATIC_NONE) ai.camera_visibility(src) if(ai.client && !ai.multicam_on) ai.client.eye = src update_ai_detect_hud() update_parallax_contents() //Holopad if(istype(ai.current, /obj/machinery/holopad)) var/obj/machinery/holopad/H = ai.current H.move_hologram(ai, T) if(ai.camera_light_on) ai.light_cameras() if(ai.master_multicam) ai.master_multicam.refresh_view() /mob/camera/aiEye/Move() return 0 /mob/camera/aiEye/proc/GetViewerClient() if(ai) return ai.client return null /mob/camera/aiEye/Destroy() if(ai) ai.all_eyes -= src ai = null for(var/V in visibleCameraChunks) var/datum/camerachunk/c = V c.remove(src) GLOB.aiEyes -= src if(ai_detector_visible) var/datum/atom_hud/ai_detector/hud = GLOB.huds[DATA_HUD_AI_DETECT] hud.remove_from_hud(src) var/list/L = hud_list[AI_DETECT_HUD] QDEL_LIST(L) return ..() /atom/proc/move_camera_by_click() if(isAI(usr)) var/mob/living/silicon/ai/AI = usr if(AI.eyeobj && (AI.multicam_on || (AI.client.eye == AI.eyeobj)) && (AI.eyeobj.z == z)) AI.cameraFollow = null if (isturf(loc) || isturf(src)) AI.eyeobj.setLoc(src) // 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 // Return to the Core. /mob/living/silicon/ai/proc/view_core() if(istype(current,/obj/machinery/holopad)) var/obj/machinery/holopad/H = current H.clear_holo(src) else current = null cameraFollow = null unset_machine() if(!eyeobj || !eyeobj.loc || QDELETED(eyeobj)) 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/aiEye() all_eyes += eyeobj eyeobj.ai = src eyeobj.setLoc(loc) eyeobj.name = "[name] (AI Eye)" /mob/living/silicon/ai/verb/toggle_acceleration() set category = "AI Commands" set name = "Toggle Camera Acceleration" if(incapacitated()) return acceleration = !acceleration to_chat(usr, "Camera acceleration has been toggled [acceleration ? "on" : "off"].") /mob/camera/aiEye/Hear(message, atom/movable/speaker, datum/language/message_language, raw_message, radio_freq, list/spans, message_mode) . = ..() if(relay_speech && speaker && ai && !radio_freq && speaker != ai && near_camera(speaker)) ai.relay_speech(message, speaker, message_language, raw_message, radio_freq, spans, message_mode) /obj/effect/overlay/ai_detect_hud name = "" mouse_opacity = MOUSE_OPACITY_TRANSPARENT icon = 'icons/effects/alphacolors.dmi' icon_state = "" alpha = 100 layer = ABOVE_ALL_MOB_LAYER plane = GAME_PLANE