198 lines
5.8 KiB
Plaintext
198 lines
5.8 KiB
Plaintext
// 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
|