Files
Aurora.3/code/game/machinery/camera/tracking.dm

270 lines
7.2 KiB
Plaintext

#define TRACKING_POSSIBLE 0
#define TRACKING_NO_COVERAGE 1
#define TRACKING_TERMINATE 2
/mob/living/silicon/ai/var/max_locations = 10
/mob/living/silicon/ai/var/stored_locations[0]
/proc/InvalidPlayerTurf(turf/T as turf)
return !(T && isStationLevel(T.z))
/mob/living/silicon/ai/proc/get_camera_list()
if(src.stat == 2)
return
var/list/T = list()
for (var/obj/machinery/camera/C in cameranet.cameras)
var/list/tempnetwork = C.network&src.network
if (tempnetwork.len)
T[text("[][]", C.c_tag, (C.can_use() ? null : " (Deactivated)"))] = C
track = new()
track.cameras = T
return T
/mob/living/silicon/ai/proc/ai_camera_list(var/camera in get_camera_list())
set category = "AI Commands"
set name = "Show Camera List"
if(check_unable())
return
if (!camera)
return 0
var/obj/machinery/camera/C = track.cameras[camera]
src.eyeobj.setLoc(C)
return
/mob/living/silicon/ai/proc/ai_store_location(loc as text)
set category = "AI Commands"
set name = "Store Camera Location"
set desc = "Stores your current camera location by the given name"
loc = sanitize(loc)
if(!loc)
to_chat(src, "<span class='warning'>Must supply a location name</span>")
return
if(stored_locations.len >= max_locations)
to_chat(src, "<span class='warning'>Cannot store additional locations. Remove one first</span>")
return
if(loc in stored_locations)
to_chat(src, "<span class='warning'>There is already a stored location by this name</span>")
return
var/L = src.eyeobj.getLoc()
if (InvalidPlayerTurf(get_turf(L)))
to_chat(src, "<span class='warning'>Unable to store this location</span>")
return
stored_locations[loc] = L
to_chat(src, "Location '[loc]' stored")
/mob/living/silicon/ai/proc/sorted_stored_locations()
return sortList(stored_locations)
/mob/living/silicon/ai/proc/ai_goto_location(loc in sorted_stored_locations())
set category = "AI Commands"
set name = "Goto Camera Location"
set desc = "Returns to the selected camera location"
if (!(loc in stored_locations))
to_chat(src, "<span class='warning'>Location [loc] not found</span>")
return
var/L = stored_locations[loc]
src.eyeobj.setLoc(L)
/mob/living/silicon/ai/proc/ai_remove_location(loc in sorted_stored_locations())
set category = "AI Commands"
set name = "Delete Camera Location"
set desc = "Deletes the selected camera location"
if (!(loc in stored_locations))
to_chat(src, "<span class='warning'>Location [loc] not found</span>")
return
stored_locations.Remove(loc)
to_chat(src, "Location [loc] removed")
// Used to allow the AI is write in mob names/camera name from the CMD line.
/datum/trackable
var/list/names = list()
var/list/namecounts = list()
var/list/humans = list()
var/list/others = list()
var/list/cameras = list()
/mob/living/silicon/ai/proc/trackable_mobs()
if(usr.stat == 2)
return list()
var/datum/trackable/TB = new()
for(var/mob/living/M in mob_list)
if(M == usr)
continue
if(M.tracking_status() != TRACKING_POSSIBLE)
continue
var/name = M.name
if (name in TB.names)
TB.namecounts[name]++
name = text("[] ([])", name, TB.namecounts[name])
else
TB.names.Add(name)
TB.namecounts[name] = 1
if(istype(M, /mob/living/carbon/human))
TB.humans[name] = M
else
TB.others[name] = M
var/list/targets = sortList(TB.humans) + sortList(TB.others)
src.track = TB
return targets
/mob/living/silicon/ai/proc/ai_camera_track(var/target_name in trackable_mobs())
set category = "AI Commands"
set name = "Follow With Camera"
set desc = "Select who you would like to track."
if(src.stat == 2)
to_chat(src, "You can't follow [target_name] with cameras because you are dead!")
return
if(!target_name)
src.cameraFollow = null
if (!track)
trackable_mobs()
var/mob/target = (isnull(track.humans[target_name]) ? track.others[target_name] : track.humans[target_name])
src.track = null
ai_actual_track(target)
/mob/living/silicon/ai/proc/ai_cancel_tracking(var/forced = 0)
if(!cameraFollow)
return
to_chat(src, "Follow camera mode [forced ? "terminated" : "ended"].")
cameraFollow.tracking_cancelled()
cameraFollow = null
/mob/living/silicon/ai/proc/ai_actual_track(mob/living/target as mob)
if(!istype(target)) return
var/mob/living/silicon/ai/U = usr
if(target == U.cameraFollow)
return
if(U.cameraFollow)
U.ai_cancel_tracking()
U.cameraFollow = target
to_chat(U, "Now tracking [target.name] on camera.")
target.tracking_initiated()
spawn (0)
while (U.cameraFollow == target)
if (U.cameraFollow == null)
return
switch(target.tracking_status())
if(TRACKING_NO_COVERAGE)
to_chat(U, "Target is not near any active cameras.")
sleep(100)
continue
if(TRACKING_TERMINATE)
U.ai_cancel_tracking(1)
return
if(U.eyeobj)
U.eyeobj.setLoc(get_turf(target), 0)
else
view_core()
return
sleep(10)
/obj/machinery/camera/attack_ai(var/mob/living/silicon/ai/user as mob)
if (!istype(user))
return
if (!src.can_use())
return
user.eyeobj.setLoc(get_turf(src))
/mob/living/silicon/ai/attack_ai(var/mob/user as mob)
ai_camera_list()
/proc/camera_sort(list/L)
if (!L)
return
var/list/target = L.Copy()
// sortTim sorts in-place, but returns a ref to the list anyways.
return sortTim(target, /proc/cmp_camera, FALSE)
mob/living/proc/near_camera()
if (!isturf(loc))
return 0
else if(!cameranet.is_visible(src))
return 0
return 1
/mob/living/proc/tracking_status()
// Easy checks first.
// Don't detect mobs on Centcom. Since the wizard den is on Centcomm, we only need this.
var/obj/item/card/id/id = GetIdCard()
if(id && id.prevent_tracking())
return TRACKING_TERMINATE
if(InvalidPlayerTurf(get_turf(src)))
return TRACKING_TERMINATE
if(invisibility >= INVISIBILITY_LEVEL_ONE) //cloaked
return TRACKING_TERMINATE
if(digitalcamo)
return TRACKING_TERMINATE
if(istype(loc,/obj/effect/dummy))
return TRACKING_TERMINATE
// Now, are they viewable by a camera? (This is last because it's the most intensive check)
return near_camera() ? TRACKING_POSSIBLE : TRACKING_NO_COVERAGE
/mob/living/silicon/robot/tracking_status()
. = ..()
if(. == TRACKING_NO_COVERAGE)
return camera && camera.can_use() ? TRACKING_POSSIBLE : TRACKING_NO_COVERAGE
/mob/living/carbon/human/tracking_status()
//Cameras can't track people wearing an agent card or a ninja hood.
if(istype(head, /obj/item/clothing/head/helmet/space/rig))
var/obj/item/clothing/head/helmet/space/rig/helmet = head
if(helmet.prevent_track())
return TRACKING_TERMINATE
. = ..()
if(. == TRACKING_TERMINATE)
return
if(. == TRACKING_NO_COVERAGE)
var/turf/T = get_turf(src)
if(T && isStationLevel(T.z) && hassensorlevel(src, SUIT_SENSOR_TRACKING))
return TRACKING_POSSIBLE
mob/living/proc/tracking_initiated()
mob/living/silicon/robot/tracking_initiated()
tracking_entities++
if(tracking_entities == 1 && has_zeroth_law())
to_chat(src, "<span class='warning'>Internal camera is currently being accessed.</span>")
mob/living/proc/tracking_cancelled()
mob/living/silicon/robot/tracking_initiated()
tracking_entities--
if(!tracking_entities && has_zeroth_law())
to_chat(src, "<span class='notice'>Internal camera is no longer being accessed.</span>")
#undef TRACKING_POSSIBLE
#undef TRACKING_NO_COVERAGE
#undef TRACKING_TERMINATE