diff --git a/code/_hooks/events.dm b/code/_hooks/events.dm index 79d9f861f6f..b565c5157a4 100644 --- a/code/_hooks/events.dm +++ b/code/_hooks/events.dm @@ -263,6 +263,11 @@ // atom/movable/exiter: the movable exiting the area /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 // Arguments: // mob: the mob changing areas diff --git a/code/datums/gamemode/powers/changeling.dm b/code/datums/gamemode/powers/changeling.dm index 6fcf5c55f34..c311b9660b0 100644 --- a/code/datums/gamemode/powers/changeling.dm +++ b/code/datums/gamemode/powers/changeling.dm @@ -226,6 +226,7 @@ return var/mob/living/carbon/human/C = R.antag.current to_chat(C, "We distort our form to prevent AI-tracking.") + INVOKE_EVENT(C, /event/camera_sight_changed, "mover" = C) C.digitalcamo = 1 /datum/power/changeling/rapidregeneration diff --git a/code/datums/gamemode/role/ninja.dm b/code/datums/gamemode/role/ninja.dm index 2ea2a34c91b..6715a618ad2 100644 --- a/code/datums/gamemode/role/ninja.dm +++ b/code/datums/gamemode/role/ninja.dm @@ -289,6 +289,7 @@ var/list/valid_ninja_suits = list( max_heat_protection_temperature = GLOVES_MAX_HEAT_PROTECTION_TEMPERATURE heat_conductivity = INS_GLOVES_HEAT_CONDUCTIVITY pressure_resistance = 200 * ONE_ATMOSPHERE + blocks_tracking = TRUE var/cooldown = 0 var/shuriken_icon = "radial_print" actions_types = list( diff --git a/code/game/dna/genes/goon_powers.dm b/code/game/dna/genes/goon_powers.dm index f3f62caf1cd..012bb877d42 100644 --- a/code/game/dna/genes/goon_powers.dm +++ b/code/game/dna/genes/goon_powers.dm @@ -21,6 +21,17 @@ /datum/dna/gene/basic/psychic_resist/New() 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 ///////////////////////// diff --git a/code/game/machinery/camera/tracking.dm b/code/game/machinery/camera/tracking.dm index 642d160ee9b..3776767c734 100644 --- a/code/game/machinery/camera/tracking.dm +++ b/code/game/machinery/camera/tracking.dm @@ -1,3 +1,6 @@ +/mob/living/silicon/ai + var/atom/movable/currently_tracking = null + /mob/living/silicon/ai/proc/get_camera_list() @@ -111,7 +114,7 @@ return spawn(0) 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 var/obj/machinery/door/airlock/tobeopened var/dist = -1 @@ -143,7 +146,7 @@ return /mob/living/silicon/ai/proc/can_track_atom(var/atom/target) - if(target == src) + if(!target || target.gcDestroyed || target == src) return FALSE var/turf/T = get_turf(target) @@ -159,18 +162,13 @@ var/mob/target_mob = target if(target_mob.digitalcamo) return FALSE - if(ishuman(target)) - var/mob/living/carbon/human/target_human = target - if(target_human.wear_id && istype(target_human.wear_id.GetID(), /obj/item/weapon/card/id/syndicate)) - return FALSE - if(target_human.is_wearing_item(/obj/item/clothing/mask/gas/voice)) - return FALSE - if(target_human.is_wearing_item(/obj/item/clothing/gloves/ninja)) - 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 + for(var/obj/item/I in target_mob.get_all_slots()) + if(I.blocks_tracking) + return FALSE + if(target_mob.is_wearing_item(I,slot_wear_id)) + var/obj/item/ourID = I.GetID() + if(ourID && ourID.blocks_tracking) + return FALSE if(isalien(target)) return FALSE @@ -183,34 +181,50 @@ return TRUE -/mob/living/silicon/ai/proc/ai_actual_track(var/atom/target) - if(!istype(target)) +/mob/living/silicon/ai/proc/ai_actual_track(var/atom/movable/target) + if(!istype(target) || !eyeobj) return 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 - 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) - while (cameraFollow == target) - if (cameraFollow == null) - return +/datum/locking_category/ai_eye - if(!can_track_atom(target)) - to_chat(src, "Target is not near any active camera.") - sleep(10 SECONDS) - continue +/mob/living/silicon/ai/proc/on_camera_change() + if(eyeobj && currently_tracking) + var/cantrack = can_track_atom(currently_tracking) + /*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) - eyeobj.forceMove(get_turf(target)) - else - view_core() - return - sleep(1 SECONDS) +/mob/living/silicon/ai/proc/stop_ai_tracking() + if(currently_tracking) + to_chat(src, "No longer tracking [currently_tracking.name] on camera.") + currently_tracking.unregister_event(/event/after_move,src,nameof(src::on_camera_change())) + currently_tracking.unregister_event(/event/destroyed,src,nameof(src::stop_ai_tracking())) + 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) if (!isturf(M.loc)) diff --git a/code/game/machinery/hologram.dm b/code/game/machinery/hologram.dm index 507357c3921..b863443e5e3 100644 --- a/code/game/machinery/hologram.dm +++ b/code/game/machinery/hologram.dm @@ -81,7 +81,6 @@ var/list/holopads = list() /*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. 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. clear_holo() diff --git a/code/game/objects/items.dm b/code/game/objects/items.dm index 266b1e0f0aa..a63d0e47abf 100644 --- a/code/game/objects/items.dm +++ b/code/game/objects/items.dm @@ -87,6 +87,8 @@ 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/last_burn diff --git a/code/game/objects/items/devices/megaphone.dm b/code/game/objects/items/devices/megaphone.dm index 01e10d97764..e9b09f5a501 100644 --- a/code/game/objects/items/devices/megaphone.dm +++ b/code/game/objects/items/devices/megaphone.dm @@ -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." var/frequency = 0 mask_voice = TRUE + blocks_tracking = TRUE flags = FPRINT | HEAR 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")] \ 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) show_ui(user) diff --git a/code/game/objects/items/weapons/cards_ids.dm b/code/game/objects/items/weapons/cards_ids.dm index 1721d6f171b..385920bb6ef 100644 --- a/code/game/objects/items/weapons/cards_ids.dm +++ b/code/game/objects/items/weapons/cards_ids.dm @@ -441,6 +441,7 @@ var/list/global/id_cards = list() access = AGENT_CARD_DEFAULT_ACCESS base_access = list(access_syndicate) origin_tech = Tc_SYNDICATE + "=3" + blocks_tracking = TRUE var/registered_user=null var/copy_appearance = FALSE diff --git a/code/modules/clothing/head/misc_special.dm b/code/modules/clothing/head/misc_special.dm index 4603941c4ee..c5ab0ab38d8 100644 --- a/code/modules/clothing/head/misc_special.dm +++ b/code/modules/clothing/head/misc_special.dm @@ -290,6 +290,7 @@ item_state = "paper" siemens_coefficient = 2 species_fit = list(GREY_SHAPED,VOX_SHAPED, INSECT_SHAPED) + blocks_tracking = TRUE /obj/item/clothing/head/celtic name = "\improper Celtic crown" diff --git a/code/modules/clothing/masks/gasmask.dm b/code/modules/clothing/masks/gasmask.dm index 2cc2d99fcb2..c904ded2a81 100644 --- a/code/modules/clothing/masks/gasmask.dm +++ b/code/modules/clothing/masks/gasmask.dm @@ -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,) species_fit = list(VOX_SHAPED, GREY_SHAPED,INSECT_SHAPED) permeability_coefficient = 0.90 + blocks_tracking = TRUE var/static/list/clothing_choices /obj/item/clothing/mask/gas/voice/New() diff --git a/code/modules/clothing/spacesuits/alien.dm b/code/modules/clothing/spacesuits/alien.dm index a4bfe5f7e6b..7fd7fcd1034 100644 --- a/code/modules/clothing/spacesuits/alien.dm +++ b/code/modules/clothing/spacesuits/alien.dm @@ -754,6 +754,7 @@ heat_conductivity = SPACESUIT_HEAT_CONDUCTIVITY body_parts_covered = FULL_HEAD|IGNORE_INV species_restricted = list("Martian") + blocks_tracking = TRUE var/obj/item/weapon/tank/tank /obj/item/clothing/head/helmet/space/martian/attackby(obj/item/W,mob/user) diff --git a/code/modules/mob/living/living_defines.dm b/code/modules/mob/living/living_defines.dm index 5fec2a9f3f8..7f342c0e3da 100644 --- a/code/modules/mob/living/living_defines.dm +++ b/code/modules/mob/living/living_defines.dm @@ -40,8 +40,6 @@ var/mob_swap_flags = 0 var/mob_push_flags = 0 - var/cameraFollow = null - var/tod = null // Time of death var/update_slimes = 1 diff --git a/code/modules/mob/living/silicon/ai/ai.dm b/code/modules/mob/living/silicon/ai/ai.dm index 545a1156a92..ebc5a583897 100644 --- a/code/modules/mob/living/silicon/ai/ai.dm +++ b/code/modules/mob/living/silicon/ai/ai.dm @@ -592,9 +592,7 @@ var/static/list/ai_icon_states = list( /mob/living/silicon/ai/proc/switchCamera(var/obj/machinery/camera/C) - - - src.cameraFollow = null + stop_ai_tracking() if(!C || isDead()) //C.can_use()) return FALSE @@ -677,7 +675,7 @@ var/static/list/ai_icon_states = list( set category = "AI Commands" set name = "Jump To Network" unset_machine() - src.cameraFollow = null + stop_ai_tracking() var/cameralist[0] if(usr.isDead()) diff --git a/code/modules/mob/living/silicon/ai/freelook/eye.dm b/code/modules/mob/living/silicon/ai/freelook/eye.dm index 72146318e93..f91350e72eb 100644 --- a/code/modules/mob/living/silicon/ai/freelook/eye.dm +++ b/code/modules/mob/living/silicon/ai/freelook/eye.dm @@ -96,8 +96,7 @@ if(istype(usr, /mob/living/silicon/ai)) var/mob/living/silicon/ai/AI = usr if(AI.eyeobj && AI.client.eye == AI.eyeobj) - AI.cameraFollow = null - //AI.eyeobj.forceMove(src) + AI.stop_ai_tracking() if (isturf(src.loc) || isturf(src)) AI.eyeobj.forceMove(src) @@ -153,7 +152,7 @@ else user.sprint = initial - user.cameraFollow = null + user.stop_ai_tracking() //user.unset_machine() //Uncomment this if it causes problems. //user.lightNearbyCamera() @@ -168,7 +167,7 @@ T.malf_release_control() current = null - cameraFollow = null + stop_ai_tracking() unset_machine() if(!loc) @@ -209,7 +208,7 @@ if(!T) to_chat(src, "Nowhere to jump to!") return - cameraFollow = null + stop_ai_tracking() eyeobj.forceMove(T) /mob/living/silicon/ai/proc/toggleholopadoverlays() //shows holopads above all static diff --git a/code/modules/mob/living/silicon/ai/life.dm b/code/modules/mob/living/silicon/ai/life.dm index 22f40ac23bd..5a00fa202c5 100644 --- a/code/modules/mob/living/silicon/ai/life.dm +++ b/code/modules/mob/living/silicon/ai/life.dm @@ -7,7 +7,7 @@ /mob/living/silicon/ai/proc/life_handle_camera() if(stat != CONSCIOUS) - cameraFollow = null + stop_ai_tracking() reset_view(null) unset_machine() if(client) diff --git a/code/modules/mob/living/silicon/pai/pai.dm b/code/modules/mob/living/silicon/pai/pai.dm index b7d1dbd6159..172ea5b094f 100644 --- a/code/modules/mob/living/silicon/pai/pai.dm +++ b/code/modules/mob/living/silicon/pai/pai.dm @@ -255,7 +255,6 @@ return "\The [pointer] points its laser sight at \the [pointed_at]." /mob/living/silicon/pai/proc/switchCamera(var/obj/machinery/camera/C) - cameraFollow = null if(!C) unset_machine() reset_view(null) @@ -275,7 +274,6 @@ set name = "Cancel Camera View" reset_view(null) unset_machine() - cameraFollow = null /mob/living/silicon/pai/ClickOn(var/atom/A, var/params) if(incapacitated()) diff --git a/code/modules/mob/mob.dm b/code/modules/mob/mob.dm index bda2e5cb6f0..6649e5f6f2f 100644 --- a/code/modules/mob/mob.dm +++ b/code/modules/mob/mob.dm @@ -1352,13 +1352,16 @@ Use this proc preferably at the end of an equipment loadout set category = "IC" unset_machine() reset_view(null) - if(istype(src, /mob/living)) - var/mob/living/M = src - if(M.cameraFollow) - M.cameraFollow = null - if(istype(src, /mob/living/carbon/human)) - var/mob/living/carbon/human/H = M - H.handle_regular_hud_updates() + if(ishuman(src)) + var/mob/living/carbon/human/H = src + H.handle_regular_hud_updates() + +/mob/living/silicon/ai/cancel_camera() + set name = "Cancel Camera View" + set category = "IC" + stop_ai_tracking() + unset_machine() + reset_view(null) // http://www.byond.com/forum/?post=2219001#comment22205313 // TODO: Clean up and identify the args, document diff --git a/code/modules/trader/crates/alcatrazfour.dm b/code/modules/trader/crates/alcatrazfour.dm index 0a5c696d4e3..591fd2e316f 100644 --- a/code/modules/trader/crates/alcatrazfour.dm +++ b/code/modules/trader/crates/alcatrazfour.dm @@ -44,6 +44,7 @@ var/global/list/alcatraz_stuff = list( light_color = LIGHT_COLOR_ORANGE mech_flags = MECH_SCAN_FAIL var/obj/item/weapon/cell/bcell + blocks_tracking = TRUE /obj/item/clothing/head/helmet/stun/New() ..()