Files
kiwistation/code/modules/shuttle/navigation_computer.dm
T
Cruix 275aa2bfa2 AI detection multitools can show camera static and AI eyes (#38255)
The old color-change functionality of the multitool remains unchanged. The hud is toggled with an action button, because multitools already have an attack_self() that does something. When toggled on, you get the hud as long as the multitool is in any slot on your body.

The only way I could find to reliably show exactly where an AI is looking was to place an image on every turf they are looking at. Because AI eyes move around a lot and I do not want them placing images all over the place when they do not have to, if there is nobody in the world currently using an ai detection multitool, they will not update the images until someone is.

Only AI eyes and multicamera zones currently appear. Advanced camera consoles do not appear on the hud, and no longer trigger the proximity color change. Also fixed multitools not appearing in-hands if their icon state changed.
2018-07-08 17:19:55 +12:00

331 lines
12 KiB
Plaintext

/obj/machinery/computer/camera_advanced/shuttle_docker
name = "navigation computer"
desc = "Used to designate a precise transit location for a spacecraft."
jump_action = null
var/datum/action/innate/shuttledocker_rotate/rotate_action = new
var/datum/action/innate/shuttledocker_place/place_action = new
var/shuttleId = ""
var/shuttlePortId = ""
var/shuttlePortName = ""
var/list/jumpto_ports = list() //hashset of ports to jump to and ignore for collision purposes
var/obj/docking_port/stationary/my_port //the custom docking port placed by this console
var/obj/docking_port/mobile/shuttle_port //the mobile docking port of the connected shuttle
var/view_range = 7
var/x_offset = 0
var/y_offset = 0
var/space_turfs_only = TRUE
var/see_hidden = FALSE
var/designate_time = 0
var/turf/designating_target_loc
var/jammed = FALSE
/obj/machinery/computer/camera_advanced/shuttle_docker/Initialize()
. = ..()
GLOB.navigation_computers += src
/obj/machinery/computer/camera_advanced/shuttle_docker/Destroy()
. = ..()
GLOB.navigation_computers -= src
/obj/machinery/computer/camera_advanced/shuttle_docker/attack_hand(mob/user)
if(jammed)
to_chat(user, "<span class='warning'>The Syndicate is jamming the console!</span>")
return
if(!shuttle_port)
to_chat(user,"<span class='warning'>Warning: Shuttle connection severed!</span>")
return
return ..()
/obj/machinery/computer/camera_advanced/shuttle_docker/GrantActions(mob/living/user)
if(jumpto_ports.len)
jump_action = new /datum/action/innate/camera_jump/shuttle_docker
..()
if(rotate_action)
rotate_action.target = user
rotate_action.Grant(user)
actions += rotate_action
if(place_action)
place_action.target = user
place_action.Grant(user)
actions += place_action
/obj/machinery/computer/camera_advanced/shuttle_docker/CreateEye()
shuttle_port = SSshuttle.getShuttle(shuttleId)
if(QDELETED(shuttle_port))
shuttle_port = null
return
eyeobj = new /mob/camera/aiEye/remote/shuttle_docker()
var/mob/camera/aiEye/remote/shuttle_docker/the_eye = eyeobj
the_eye.origin = src
the_eye.dir = 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)
var/area/A = V
for(var/turf/T in A)
if(T.z != origin.z)
continue
var/image/I = image('icons/effects/alphacolors.dmi', origin, "red")
var/x_off = T.x - origin.x
var/y_off = T.y - origin.y
I.loc = locate(origin.x + x_off, origin.y + y_off, origin.z) //we have to set this after creating the image because it might be null, and images created in nullspace are immutable.
I.layer = ABOVE_NORMAL_TURF_LAYER
I.plane = 0
I.mouse_opacity = 0
the_eye.placement_images[I] = list(x_off, y_off)
/obj/machinery/computer/camera_advanced/shuttle_docker/give_eye_control(mob/user)
..()
if(!QDELETED(user) && user.client)
var/mob/camera/aiEye/remote/shuttle_docker/the_eye = eyeobj
var/list/to_add = list()
to_add += the_eye.placement_images
to_add += the_eye.placed_images
if(!see_hidden)
to_add += SSshuttle.hidden_shuttle_turf_images
user.client.images += to_add
user.client.change_view(view_range)
/obj/machinery/computer/camera_advanced/shuttle_docker/remove_eye_control(mob/living/user)
..()
if(!QDELETED(user) && user.client)
var/mob/camera/aiEye/remote/shuttle_docker/the_eye = eyeobj
var/list/to_remove = list()
to_remove += the_eye.placement_images
to_remove += the_eye.placed_images
if(!see_hidden)
to_remove += SSshuttle.hidden_shuttle_turf_images
user.client.images -= to_remove
user.client.change_view(CONFIG_GET(string/default_view))
/obj/machinery/computer/camera_advanced/shuttle_docker/proc/placeLandingSpot()
if(designating_target_loc || !current_user)
return
var/mob/camera/aiEye/remote/shuttle_docker/the_eye = eyeobj
var/landing_clear = checkLandingSpot()
if(designate_time && (landing_clear != SHUTTLE_DOCKER_BLOCKED))
to_chat(current_user, "<span class='warning'>Targeting transit location, please wait [DisplayTimeText(designate_time)]...</span>")
designating_target_loc = the_eye.loc
var/wait_completed = do_after(current_user, designate_time, FALSE, designating_target_loc, TRUE, CALLBACK(src, /obj/machinery/computer/camera_advanced/shuttle_docker/proc/canDesignateTarget))
designating_target_loc = null
if(!current_user)
return
if(!wait_completed)
to_chat(current_user, "<span class='warning'>Operation aborted.</span>")
return
landing_clear = checkLandingSpot()
if(landing_clear != SHUTTLE_DOCKER_LANDING_CLEAR)
switch(landing_clear)
if(SHUTTLE_DOCKER_BLOCKED)
to_chat(current_user, "<span class='warning'>Invalid transit location</span>")
if(SHUTTLE_DOCKER_BLOCKED_BY_HIDDEN_PORT)
to_chat(current_user, "<span class='warning'>Unknown object detected in landing zone. Please designate another location.</span>")
return
if(!my_port)
my_port = new()
my_port.name = shuttlePortName
my_port.id = shuttlePortId
my_port.height = shuttle_port.height
my_port.width = shuttle_port.width
my_port.dheight = shuttle_port.dheight
my_port.dwidth = shuttle_port.dwidth
my_port.hidden = shuttle_port.hidden
my_port.dir = the_eye.dir
my_port.forceMove(locate(eyeobj.x - x_offset, eyeobj.y - y_offset, eyeobj.z))
if(current_user.client)
current_user.client.images -= the_eye.placed_images
QDEL_LIST(the_eye.placed_images)
for(var/V in the_eye.placement_images)
var/image/I = V
var/image/newI = image('icons/effects/alphacolors.dmi', the_eye.loc, "blue")
newI.loc = I.loc //It is highly unlikely that any landing spot including a null tile will get this far, but better safe than sorry.
newI.layer = ABOVE_OPEN_TURF_LAYER
newI.plane = 0
newI.mouse_opacity = 0
the_eye.placed_images += newI
if(current_user.client)
current_user.client.images += the_eye.placed_images
to_chat(current_user, "<span class='notice'>Transit location designated</span>")
return
/obj/machinery/computer/camera_advanced/shuttle_docker/proc/canDesignateTarget()
if(!designating_target_loc || !current_user || (eyeobj.loc != designating_target_loc) || (stat & (NOPOWER|BROKEN)) )
return FALSE
return TRUE
/obj/machinery/computer/camera_advanced/shuttle_docker/proc/rotateLandingSpot()
var/mob/camera/aiEye/remote/shuttle_docker/the_eye = eyeobj
var/list/image_cache = the_eye.placement_images
the_eye.dir = turn(the_eye.dir, -90)
for(var/i in 1 to image_cache.len)
var/image/pic = image_cache[i]
var/list/coords = image_cache[pic]
var/Tmp = coords[1]
coords[1] = coords[2]
coords[2] = -Tmp
pic.loc = locate(the_eye.x + coords[1], the_eye.y + coords[2], the_eye.z)
var/Tmp = x_offset
x_offset = y_offset
y_offset = -Tmp
checkLandingSpot()
/obj/machinery/computer/camera_advanced/shuttle_docker/proc/checkLandingSpot()
var/mob/camera/aiEye/remote/shuttle_docker/the_eye = eyeobj
var/turf/eyeturf = get_turf(the_eye)
if(!eyeturf)
return SHUTTLE_DOCKER_BLOCKED
if(z_lock.len && !(eyeturf.z in z_lock))
return SHUTTLE_DOCKER_BLOCKED
. = SHUTTLE_DOCKER_LANDING_CLEAR
var/list/bounds = shuttle_port.return_coords(the_eye.x - x_offset, the_eye.y - y_offset, the_eye.dir)
var/list/overlappers = SSshuttle.get_dock_overlap(bounds[1], bounds[2], bounds[3], bounds[4], the_eye.z)
var/list/image_cache = the_eye.placement_images
for(var/i in 1 to image_cache.len)
var/image/I = image_cache[i]
var/list/coords = image_cache[I]
var/turf/T = locate(eyeturf.x + coords[1], eyeturf.y + coords[2], eyeturf.z)
I.loc = T
switch(checkLandingTurf(T, overlappers))
if(SHUTTLE_DOCKER_LANDING_CLEAR)
I.icon_state = "green"
if(SHUTTLE_DOCKER_BLOCKED_BY_HIDDEN_PORT)
I.icon_state = "green"
if(. == SHUTTLE_DOCKER_LANDING_CLEAR)
. = SHUTTLE_DOCKER_BLOCKED_BY_HIDDEN_PORT
else
I.icon_state = "red"
. = SHUTTLE_DOCKER_BLOCKED
/obj/machinery/computer/camera_advanced/shuttle_docker/proc/checkLandingTurf(turf/T, list/overlappers)
// Too close to the map edge is never allowed
if(!T || T.x <= 10 || T.y <= 10 || T.x >= world.maxx - 10 || T.y >= world.maxy - 10)
return SHUTTLE_DOCKER_BLOCKED
// If it's one of our shuttle areas assume it's ok to be there
if(shuttle_port.shuttle_areas[T.loc])
return SHUTTLE_DOCKER_LANDING_CLEAR
. = SHUTTLE_DOCKER_LANDING_CLEAR
// See if the turf is hidden from us
var/list/hidden_turf_info
if(!see_hidden)
hidden_turf_info = SSshuttle.hidden_shuttle_turfs[T]
if(hidden_turf_info)
. = SHUTTLE_DOCKER_BLOCKED_BY_HIDDEN_PORT
if(space_turfs_only)
var/turf_type = hidden_turf_info ? hidden_turf_info[2] : T.type
if(!ispath(turf_type, /turf/open/space))
return SHUTTLE_DOCKER_BLOCKED
// Checking for overlapping dock boundaries
for(var/i in 1 to overlappers.len)
var/obj/docking_port/port = overlappers[i]
if(port == my_port)
continue
var/port_hidden = !see_hidden && port.hidden
var/list/overlap = overlappers[port]
var/list/xs = overlap[1]
var/list/ys = overlap[2]
if(xs["[T.x]"] && ys["[T.y]"])
if(port_hidden)
. = SHUTTLE_DOCKER_BLOCKED_BY_HIDDEN_PORT
else
return SHUTTLE_DOCKER_BLOCKED
/obj/machinery/computer/camera_advanced/shuttle_docker/proc/update_hidden_docking_ports(list/remove_images, list/add_images)
if(!see_hidden && current_user && current_user.client)
current_user.client.images -= remove_images
current_user.client.images += add_images
/mob/camera/aiEye/remote/shuttle_docker
visible_icon = FALSE
use_static = USE_STATIC_NONE
var/list/placement_images = list()
var/list/placed_images = list()
/mob/camera/aiEye/remote/shuttle_docker/setLoc(T)
..()
var/obj/machinery/computer/camera_advanced/shuttle_docker/console = origin
console.checkLandingSpot()
/mob/camera/aiEye/remote/shuttle_docker/update_remote_sight(mob/living/user)
user.sight = BLIND|SEE_TURFS
user.lighting_alpha = LIGHTING_PLANE_ALPHA_INVISIBLE
user.sync_lighting_plane_alpha()
return TRUE
/datum/action/innate/shuttledocker_rotate
name = "Rotate"
icon_icon = 'icons/mob/actions/actions_mecha.dmi'
button_icon_state = "mech_cycle_equip_off"
/datum/action/innate/shuttledocker_rotate/Activate()
if(QDELETED(target) || !isliving(target))
return
var/mob/living/C = target
var/mob/camera/aiEye/remote/remote_eye = C.remote_control
var/obj/machinery/computer/camera_advanced/shuttle_docker/origin = remote_eye.origin
origin.rotateLandingSpot()
/datum/action/innate/shuttledocker_place
name = "Place"
icon_icon = 'icons/mob/actions/actions_mecha.dmi'
button_icon_state = "mech_zoom_off"
/datum/action/innate/shuttledocker_place/Activate()
if(QDELETED(target) || !isliving(target))
return
var/mob/living/C = target
var/mob/camera/aiEye/remote/remote_eye = C.remote_control
var/obj/machinery/computer/camera_advanced/shuttle_docker/origin = remote_eye.origin
origin.placeLandingSpot(target)
/datum/action/innate/camera_jump/shuttle_docker
name = "Jump to Location"
button_icon_state = "camera_jump"
/datum/action/innate/camera_jump/shuttle_docker/Activate()
if(QDELETED(target) || !isliving(target))
return
var/mob/living/C = target
var/mob/camera/aiEye/remote/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)
var/list/L = list()
for(var/V in SSshuttle.stationary)
if(!V)
continue
var/obj/docking_port/stationary/S = V
if(console.z_lock.len && !(S.z in console.z_lock))
continue
if(console.jumpto_ports[S.id])
L[S.name] = S
playsound(console, 'sound/machines/terminal_prompt.ogg', 25, 0)
var/selected = input("Choose location to jump to", "Locations", null) as null|anything in L
if(QDELETED(src) || QDELETED(target) || !isliving(target))
return
playsound(src, "terminal_type", 25, 0)
if(selected)
var/turf/T = get_turf(L[selected])
if(T)
playsound(console, 'sound/machines/terminal_prompt_confirm.ogg', 25, 0)
remote_eye.setLoc(T)
to_chat(target, "<span class='notice'>Jumped to [selected]</span>")
C.overlay_fullscreen("flash", /obj/screen/fullscreen/flash/static)
C.clear_fullscreen("flash", 3)
else
playsound(console, 'sound/machines/terminal_prompt_deny.ogg', 25, 0)