mirror of
https://github.com/CHOMPstation/CHOMPstation.git
synced 2026-08-22 19:46:36 +01:00
This increases the number of stored camera locations the AI can have at one time, from 10 to 30. This is mostly a quality-of-life update in preparation for the new map, as its multiple floors make navigating around the station as the AI more difficult.
282 lines
7.6 KiB
Plaintext
282 lines
7.6 KiB
Plaintext
#define TRACKING_POSSIBLE 0
|
|
#define TRACKING_NO_COVERAGE 1
|
|
#define TRACKING_TERMINATE 2
|
|
|
|
/mob/living/silicon/ai/var/max_locations = 30
|
|
/mob/living/silicon/ai/var/stored_locations[0]
|
|
|
|
/proc/InvalidPlayerTurf(turf/T as turf)
|
|
return !(T && T.z in using_map.player_levels)
|
|
|
|
/mob/living/silicon/ai/proc/get_camera_list()
|
|
if(src.stat == 2)
|
|
return
|
|
|
|
cameranet.process_sort()
|
|
|
|
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)
|
|
src << "<span class='warning'>Must supply a location name</span>"
|
|
return
|
|
|
|
if(stored_locations.len >= max_locations)
|
|
src << "<span class='warning'>Cannot store additional locations. Remove one first</span>"
|
|
return
|
|
|
|
if(loc in stored_locations)
|
|
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)))
|
|
src << "<span class='warning'>Unable to store this location</span>"
|
|
return
|
|
|
|
stored_locations[loc] = L
|
|
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))
|
|
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))
|
|
src << "<span class='warning'>Location [loc] not found</span>"
|
|
return
|
|
|
|
stored_locations.Remove(loc)
|
|
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)
|
|
src << "You can't follow [target_name] with cameras because you are dead!"
|
|
return
|
|
if(!target_name)
|
|
src.cameraFollow = null
|
|
|
|
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
|
|
|
|
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
|
|
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)
|
|
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)
|
|
var/obj/machinery/camera/a
|
|
var/obj/machinery/camera/b
|
|
|
|
for (var/i = L.len, i > 0, i--)
|
|
for (var/j = 1 to i - 1)
|
|
a = L[j]
|
|
b = L[j + 1]
|
|
if (a.c_tag_order != b.c_tag_order)
|
|
if (a.c_tag_order > b.c_tag_order)
|
|
L.Swap(j, j + 1)
|
|
else
|
|
if (sorttext(a.c_tag, b.c_tag) < 0)
|
|
L.Swap(j, j + 1)
|
|
return L
|
|
|
|
|
|
mob/living/proc/near_camera()
|
|
if (!isturf(loc))
|
|
return 0
|
|
else if(!cameranet.checkVis(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 CentCom, we only need this.
|
|
var/obj/item/weapon/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(alpha < 127) // For lings and possible future alpha-based cloaks.
|
|
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 && (T.z in using_map.station_levels) && 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())
|
|
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())
|
|
src << "<span class='notice'>Internal camera is no longer being accessed.</span>"
|
|
|
|
|
|
#undef TRACKING_POSSIBLE
|
|
#undef TRACKING_NO_COVERAGE
|
|
#undef TRACKING_TERMINATE
|