Smoother AI tracking (#36383)

* Improved AI mob tracking

* Improved AI mob tracking

* Improved AI mob tracking

* Improved AI mob tracking

* Improved AI mob tracking

* Improved AI mob tracking

* Improved AI mob tracking

* Improved AI mob tracking

* bit of an improvement

* events on item equip and unequip

* events on item equip and unequip

* events on item equip and unequip

* events on item equip and unequip

* megaphones

* better way?

* file unchanged

* have to track it like this

* performance

* performance

* cutdown

* unnecessary

* nevermind

* actually sets null

* actually sets null

* rewrite

* relocates this

* relocates this

* updates to new syntax

* documentation

* possible help with this

* this oughta do it

* smooths this out too

* updates this

* fixes to new name

* cuts this down and cleans up

* cleaner system

* Revert "cleaner system"

This reverts commit e679a83297.

* removes controversial bit

* restores something

* clearer

* extra line to be sure

* fix

* fixes requested

* covers these cases too

* more accurate

* changes all of this

* forgot this

* unusable

* makes unlocking work

---------

Co-authored-by: SECBATON GRIFFON <sage>
Co-authored-by: SECBATON-GRIFFON <kanef9x@protonmail.com>
Co-authored-by: SECBATON-GRIFFON <>
This commit is contained in:
SECBATON GRIFFON
2024-08-21 14:08:32 +01:00
committed by GitHub
parent b4fe2c3110
commit ccb9f33037
19 changed files with 97 additions and 55 deletions

View File

@@ -263,6 +263,11 @@
// atom/movable/exiter: the movable exiting the area // atom/movable/exiter: the movable exiting the area
/event/area_exited /event/area_exited
// Called by miscellaneous functions not covered by entered, equipped and unequipped events for cameranet updates
// Arguments:
// atom/movable/mover: the atom changing status on the cameranet
/event/camera_sight_changed
// Called by both area/Entered and area/Exited if the atom changing areas is a mob // Called by both area/Entered and area/Exited if the atom changing areas is a mob
// Arguments: // Arguments:
// mob: the mob changing areas // mob: the mob changing areas

View File

@@ -226,6 +226,7 @@
return return
var/mob/living/carbon/human/C = R.antag.current var/mob/living/carbon/human/C = R.antag.current
to_chat(C, "<span class='notice'>We distort our form to prevent AI-tracking.</span>") to_chat(C, "<span class='notice'>We distort our form to prevent AI-tracking.</span>")
INVOKE_EVENT(C, /event/camera_sight_changed, "mover" = C)
C.digitalcamo = 1 C.digitalcamo = 1
/datum/power/changeling/rapidregeneration /datum/power/changeling/rapidregeneration

View File

@@ -289,6 +289,7 @@ var/list/valid_ninja_suits = list(
max_heat_protection_temperature = GLOVES_MAX_HEAT_PROTECTION_TEMPERATURE max_heat_protection_temperature = GLOVES_MAX_HEAT_PROTECTION_TEMPERATURE
heat_conductivity = INS_GLOVES_HEAT_CONDUCTIVITY heat_conductivity = INS_GLOVES_HEAT_CONDUCTIVITY
pressure_resistance = 200 * ONE_ATMOSPHERE pressure_resistance = 200 * ONE_ATMOSPHERE
blocks_tracking = TRUE
var/cooldown = 0 var/cooldown = 0
var/shuriken_icon = "radial_print" var/shuriken_icon = "radial_print"
actions_types = list( actions_types = list(

View File

@@ -21,6 +21,17 @@
/datum/dna/gene/basic/psychic_resist/New() /datum/dna/gene/basic/psychic_resist/New()
block = PSYRESISTBLOCK block = PSYRESISTBLOCK
/datum/dna/gene/basic/psychic_resist/activate(var/mob/M, var/connected, var/flags)
..()
INVOKE_EVENT(M, /event/camera_sight_changed, "mover" = M)
return 1
/*/datum/dna/gene/basic/psychic_resist/deactivate(var/mob/M, var/connected, var/flags)
if(!..())
return 0
INVOKE_EVENT(M, /event/camera_sight_changed, "mover" = M)
return 1*/ // Allows retracking, uncomment to enable
///////////////////////// /////////////////////////
// Stealth Enhancers // Stealth Enhancers
///////////////////////// /////////////////////////

View File

@@ -1,3 +1,6 @@
/mob/living/silicon/ai
var/atom/movable/currently_tracking = null
/mob/living/silicon/ai/proc/get_camera_list() /mob/living/silicon/ai/proc/get_camera_list()
@@ -111,7 +114,7 @@
return return
spawn(0) spawn(0)
if(!can_track_atom(target)) if(!can_track_atom(target))
to_chat(src, "Target is not near any active cameras.") to_chat(src, "Target is not trackable by any means.")
return return
var/obj/machinery/door/airlock/tobeopened var/obj/machinery/door/airlock/tobeopened
var/dist = -1 var/dist = -1
@@ -143,7 +146,7 @@
return return
/mob/living/silicon/ai/proc/can_track_atom(var/atom/target) /mob/living/silicon/ai/proc/can_track_atom(var/atom/target)
if(target == src) if(!target || target.gcDestroyed || target == src)
return FALSE return FALSE
var/turf/T = get_turf(target) var/turf/T = get_turf(target)
@@ -159,18 +162,13 @@
var/mob/target_mob = target var/mob/target_mob = target
if(target_mob.digitalcamo) if(target_mob.digitalcamo)
return FALSE return FALSE
if(ishuman(target)) for(var/obj/item/I in target_mob.get_all_slots())
var/mob/living/carbon/human/target_human = target if(I.blocks_tracking)
if(target_human.wear_id && istype(target_human.wear_id.GetID(), /obj/item/weapon/card/id/syndicate)) return FALSE
return FALSE if(target_mob.is_wearing_item(I,slot_wear_id))
if(target_human.is_wearing_item(/obj/item/clothing/mask/gas/voice)) var/obj/item/ourID = I.GetID()
return FALSE if(ourID && ourID.blocks_tracking)
if(target_human.is_wearing_item(/obj/item/clothing/gloves/ninja)) return FALSE
return FALSE
if(target_human.is_wearing_item(/obj/item/clothing/head/tinfoil))
return FALSE
if(target_human.is_holding_item(/obj/item/device/megaphone/madscientist))
return FALSE
if(isalien(target)) if(isalien(target))
return FALSE return FALSE
@@ -183,34 +181,50 @@
return TRUE return TRUE
/mob/living/silicon/ai/proc/ai_actual_track(var/atom/target) /mob/living/silicon/ai/proc/ai_actual_track(var/atom/movable/target)
if(!istype(target)) if(!istype(target) || !eyeobj)
return return
if(!can_track_atom(target)) if(!can_track_atom(target))
to_chat(src, "Target is not near any active camera.") to_chat(src, "Target is not trackable by any means.")
return return
cameraFollow = target stop_ai_tracking()
currently_tracking = target
eyeobj.forceMove(get_turf(currently_tracking))
currently_tracking.lock_atom(eyeobj,/datum/locking_category/ai_eye)
to_chat(src, "Now tracking [target.name] on camera.") currently_tracking.register_event(/event/after_move,src,nameof(src::on_camera_change()))
currently_tracking.register_event(/event/destroyed,src,nameof(src::stop_ai_tracking()))
currently_tracking.register_event(/event/equipped,src,nameof(src::on_camera_change()))
//currently_tracking.register_event(/event/unequipped,src,nameof(src::on_camera_change()))
currently_tracking.register_event(/event/camera_sight_changed,src,nameof(src::on_camera_change()))
to_chat(src, "Now tracking [currently_tracking.name] on camera.")
spawn (0) /datum/locking_category/ai_eye
while (cameraFollow == target)
if (cameraFollow == null)
return
if(!can_track_atom(target)) /mob/living/silicon/ai/proc/on_camera_change()
to_chat(src, "Target is not near any active camera.") if(eyeobj && currently_tracking)
sleep(10 SECONDS) var/cantrack = can_track_atom(currently_tracking)
continue /*if(!eyeobj.locked_to && cantrack) // Retracking code
to_chat(src, "Target is trackable again.")
currently_tracking.lock_atom(eyeobj,/datum/locking_category/ai_eye)
else */if(!cantrack && eyeobj.locked_to == currently_tracking)
to_chat(src, "Target is no longer trackable.")
//eyeobj.unlock_from()
stop_ai_tracking() // remove this if you want retracking
if(eyeobj) /mob/living/silicon/ai/proc/stop_ai_tracking()
eyeobj.forceMove(get_turf(target)) if(currently_tracking)
else to_chat(src, "No longer tracking [currently_tracking.name] on camera.")
view_core() currently_tracking.unregister_event(/event/after_move,src,nameof(src::on_camera_change()))
return currently_tracking.unregister_event(/event/destroyed,src,nameof(src::stop_ai_tracking()))
sleep(1 SECONDS) currently_tracking.unregister_event(/event/equipped,src,nameof(src::on_camera_change()))
//currently_tracking.unregister_event(/event/unequipped,src,nameof(src::on_camera_change()))
currently_tracking.unregister_event(/event/camera_sight_changed,src,nameof(src::on_camera_change()))
if(eyeobj?.locked_to == currently_tracking)
eyeobj.unlock_from()
currently_tracking = null
/proc/near_camera(var/mob/living/M) /proc/near_camera(var/mob/living/M)
if (!isturf(M.loc)) if (!isturf(M.loc))

View File

@@ -81,7 +81,6 @@ var/list/holopads = list()
/*There are pretty much only three ways to interact here. /*There are pretty much only three ways to interact here.
I don't need to check for client since they're clicking on an object. I don't need to check for client since they're clicking on an object.
This may change in the future but for now will suffice.*/ This may change in the future but for now will suffice.*/
user.cameraFollow = null // Stops tracking
if(master && (master==user) && holo)//If there is a hologram, remove it. But only if the user is the master. Otherwise do nothing. if(master && (master==user) && holo)//If there is a hologram, remove it. But only if the user is the master. Otherwise do nothing.
clear_holo() clear_holo()

View File

@@ -87,6 +87,8 @@
var/is_cookvessel //If true, the item is a cooking vessel. var/is_cookvessel //If true, the item is a cooking vessel.
var/blocks_tracking = FALSE //Blocks mind and AI tracking
var/list/quick_equip_priority = list() //stuff to override the quick equip thing so it goes in this first var/list/quick_equip_priority = list() //stuff to override the quick equip thing so it goes in this first
var/last_burn var/last_burn

View File

@@ -37,6 +37,7 @@
desc = "An ominous-sounding megaphone with a built-in radio transmitter and voice scrambler. Use in hand to fiddle with the controls." desc = "An ominous-sounding megaphone with a built-in radio transmitter and voice scrambler. Use in hand to fiddle with the controls."
var/frequency = 0 var/frequency = 0
mask_voice = TRUE mask_voice = TRUE
blocks_tracking = TRUE
flags = FPRINT | HEAR flags = FPRINT | HEAR
var/list/megaphone_channels = list("DISABLE" = 0) + stationchannels var/list/megaphone_channels = list("DISABLE" = 0) + stationchannels
@@ -54,6 +55,13 @@ var/list/megaphone_channels = list("DISABLE" = 0) + stationchannels
to_chat(speech.speaker, "\The [src] [pick("creaks", "whines", "crackles", "whirrs", 1;"makes an odd static/popping noise that you kind of recognize as similar to a geiger counter", 1;"squeaks")] \ to_chat(speech.speaker, "\The [src] [pick("creaks", "whines", "crackles", "whirrs", 1;"makes an odd static/popping noise that you kind of recognize as similar to a geiger counter", 1;"squeaks")] \
as it transmits your voice into the set frequency...") //Since you may not be able to hear your own demands, some feedback that they're getting through as it transmits your voice into the set frequency...") //Since you may not be able to hear your own demands, some feedback that they're getting through
/obj/item/device/megaphone/madscientist/pickup(mob/user)
INVOKE_EVENT(user, /event/camera_sight_changed, "mover" = user)
/*/obj/item/device/megaphone/madscientist/dropped(mob/user)
..()
INVOKE_EVENT(user, /event/camera_sight_changed, "mover" = user)*/ // Allows retracking, uncomment to enable
/obj/item/device/megaphone/madscientist/attack_self(mob/living/user as mob) /obj/item/device/megaphone/madscientist/attack_self(mob/living/user as mob)
show_ui(user) show_ui(user)

View File

@@ -441,6 +441,7 @@ var/list/global/id_cards = list()
access = AGENT_CARD_DEFAULT_ACCESS access = AGENT_CARD_DEFAULT_ACCESS
base_access = list(access_syndicate) base_access = list(access_syndicate)
origin_tech = Tc_SYNDICATE + "=3" origin_tech = Tc_SYNDICATE + "=3"
blocks_tracking = TRUE
var/registered_user=null var/registered_user=null
var/copy_appearance = FALSE var/copy_appearance = FALSE

View File

@@ -290,6 +290,7 @@
item_state = "paper" item_state = "paper"
siemens_coefficient = 2 siemens_coefficient = 2
species_fit = list(GREY_SHAPED,VOX_SHAPED, INSECT_SHAPED) species_fit = list(GREY_SHAPED,VOX_SHAPED, INSECT_SHAPED)
blocks_tracking = TRUE
/obj/item/clothing/head/celtic /obj/item/clothing/head/celtic
name = "\improper Celtic crown" name = "\improper Celtic crown"

View File

@@ -104,6 +104,7 @@
actions_types = list(/datum/action/item_action/toggle_mask, /datum/action/item_action/change_appearance_mask, /datum/action/item_action/toggle_voicechanger,) actions_types = list(/datum/action/item_action/toggle_mask, /datum/action/item_action/change_appearance_mask, /datum/action/item_action/toggle_voicechanger,)
species_fit = list(VOX_SHAPED, GREY_SHAPED,INSECT_SHAPED) species_fit = list(VOX_SHAPED, GREY_SHAPED,INSECT_SHAPED)
permeability_coefficient = 0.90 permeability_coefficient = 0.90
blocks_tracking = TRUE
var/static/list/clothing_choices var/static/list/clothing_choices
/obj/item/clothing/mask/gas/voice/New() /obj/item/clothing/mask/gas/voice/New()

View File

@@ -754,6 +754,7 @@
heat_conductivity = SPACESUIT_HEAT_CONDUCTIVITY heat_conductivity = SPACESUIT_HEAT_CONDUCTIVITY
body_parts_covered = FULL_HEAD|IGNORE_INV body_parts_covered = FULL_HEAD|IGNORE_INV
species_restricted = list("Martian") species_restricted = list("Martian")
blocks_tracking = TRUE
var/obj/item/weapon/tank/tank var/obj/item/weapon/tank/tank
/obj/item/clothing/head/helmet/space/martian/attackby(obj/item/W,mob/user) /obj/item/clothing/head/helmet/space/martian/attackby(obj/item/W,mob/user)

View File

@@ -40,8 +40,6 @@
var/mob_swap_flags = 0 var/mob_swap_flags = 0
var/mob_push_flags = 0 var/mob_push_flags = 0
var/cameraFollow = null
var/tod = null // Time of death var/tod = null // Time of death
var/update_slimes = 1 var/update_slimes = 1

View File

@@ -592,9 +592,7 @@ var/static/list/ai_icon_states = list(
/mob/living/silicon/ai/proc/switchCamera(var/obj/machinery/camera/C) /mob/living/silicon/ai/proc/switchCamera(var/obj/machinery/camera/C)
stop_ai_tracking()
src.cameraFollow = null
if(!C || isDead()) //C.can_use()) if(!C || isDead()) //C.can_use())
return FALSE return FALSE
@@ -677,7 +675,7 @@ var/static/list/ai_icon_states = list(
set category = "AI Commands" set category = "AI Commands"
set name = "Jump To Network" set name = "Jump To Network"
unset_machine() unset_machine()
src.cameraFollow = null stop_ai_tracking()
var/cameralist[0] var/cameralist[0]
if(usr.isDead()) if(usr.isDead())

View File

@@ -96,8 +96,7 @@
if(istype(usr, /mob/living/silicon/ai)) if(istype(usr, /mob/living/silicon/ai))
var/mob/living/silicon/ai/AI = usr var/mob/living/silicon/ai/AI = usr
if(AI.eyeobj && AI.client.eye == AI.eyeobj) if(AI.eyeobj && AI.client.eye == AI.eyeobj)
AI.cameraFollow = null AI.stop_ai_tracking()
//AI.eyeobj.forceMove(src)
if (isturf(src.loc) || isturf(src)) if (isturf(src.loc) || isturf(src))
AI.eyeobj.forceMove(src) AI.eyeobj.forceMove(src)
@@ -153,7 +152,7 @@
else else
user.sprint = initial user.sprint = initial
user.cameraFollow = null user.stop_ai_tracking()
//user.unset_machine() //Uncomment this if it causes problems. //user.unset_machine() //Uncomment this if it causes problems.
//user.lightNearbyCamera() //user.lightNearbyCamera()
@@ -168,7 +167,7 @@
T.malf_release_control() T.malf_release_control()
current = null current = null
cameraFollow = null stop_ai_tracking()
unset_machine() unset_machine()
if(!loc) if(!loc)
@@ -209,7 +208,7 @@
if(!T) if(!T)
to_chat(src, "<span class='danger'>Nowhere to jump to!</span>") to_chat(src, "<span class='danger'>Nowhere to jump to!</span>")
return return
cameraFollow = null stop_ai_tracking()
eyeobj.forceMove(T) eyeobj.forceMove(T)
/mob/living/silicon/ai/proc/toggleholopadoverlays() //shows holopads above all static /mob/living/silicon/ai/proc/toggleholopadoverlays() //shows holopads above all static

View File

@@ -7,7 +7,7 @@
/mob/living/silicon/ai/proc/life_handle_camera() /mob/living/silicon/ai/proc/life_handle_camera()
if(stat != CONSCIOUS) if(stat != CONSCIOUS)
cameraFollow = null stop_ai_tracking()
reset_view(null) reset_view(null)
unset_machine() unset_machine()
if(client) if(client)

View File

@@ -255,7 +255,6 @@
return "<b>\The [pointer]</b> points its laser sight at <b>\the [pointed_at]</b>." return "<b>\The [pointer]</b> points its laser sight at <b>\the [pointed_at]</b>."
/mob/living/silicon/pai/proc/switchCamera(var/obj/machinery/camera/C) /mob/living/silicon/pai/proc/switchCamera(var/obj/machinery/camera/C)
cameraFollow = null
if(!C) if(!C)
unset_machine() unset_machine()
reset_view(null) reset_view(null)
@@ -275,7 +274,6 @@
set name = "Cancel Camera View" set name = "Cancel Camera View"
reset_view(null) reset_view(null)
unset_machine() unset_machine()
cameraFollow = null
/mob/living/silicon/pai/ClickOn(var/atom/A, var/params) /mob/living/silicon/pai/ClickOn(var/atom/A, var/params)
if(incapacitated()) if(incapacitated())

View File

@@ -1352,13 +1352,16 @@ Use this proc preferably at the end of an equipment loadout
set category = "IC" set category = "IC"
unset_machine() unset_machine()
reset_view(null) reset_view(null)
if(istype(src, /mob/living)) if(ishuman(src))
var/mob/living/M = src var/mob/living/carbon/human/H = src
if(M.cameraFollow) H.handle_regular_hud_updates()
M.cameraFollow = null
if(istype(src, /mob/living/carbon/human)) /mob/living/silicon/ai/cancel_camera()
var/mob/living/carbon/human/H = M set name = "Cancel Camera View"
H.handle_regular_hud_updates() set category = "IC"
stop_ai_tracking()
unset_machine()
reset_view(null)
// http://www.byond.com/forum/?post=2219001#comment22205313 // http://www.byond.com/forum/?post=2219001#comment22205313
// TODO: Clean up and identify the args, document // TODO: Clean up and identify the args, document

View File

@@ -44,6 +44,7 @@ var/global/list/alcatraz_stuff = list(
light_color = LIGHT_COLOR_ORANGE light_color = LIGHT_COLOR_ORANGE
mech_flags = MECH_SCAN_FAIL mech_flags = MECH_SCAN_FAIL
var/obj/item/weapon/cell/bcell var/obj/item/weapon/cell/bcell
blocks_tracking = TRUE
/obj/item/clothing/head/helmet/stun/New() /obj/item/clothing/head/helmet/stun/New()
..() ..()