diff --git a/code/__DEFINES/mob_hud.dm b/code/__DEFINES/mob_hud.dm index a39160cc2247..1b9cf6120535 100644 --- a/code/__DEFINES/mob_hud.dm +++ b/code/__DEFINES/mob_hud.dm @@ -13,8 +13,6 @@ #define XENO_HOSTILE_SLOW "13" // xeno-inflicted slow. used by a bunch of MOBA xenos stuff #define XENO_HOSTILE_TAG "14" // dancer prae 'tag' #define XENO_HOSTILE_FREEZE "15" // Any xeno-inflifcted root -#define XENO_EXECUTE "28" // Execute thershold, vampire - #define HEALTH_HUD_XENO "16" // health HUD for xenos #define PLASMA_HUD "17" // indicates the plasma level of xenos. #define PHEROMONE_HUD "18" // indicates which pheromone is active on a xeno. @@ -27,7 +25,9 @@ #define HUNTER_CLAN "25" //Displays a colored icon to represent ingame Hunter Clans #define HUNTER_HUD "26" //Displays various statuses on mobs for Hunters to identify targets #define HOLOCARD_HUD "27" //Displays the holocards set by medical personnel +#define XENO_EXECUTE "28" // Execute thershold, vampire #define NEW_PLAYER_HUD "29" //Makes it easy to see new players. +#define SPYCAM_HUD "30" //Remote control spy cameras. //data HUD (medhud, sechud) defines #define MOB_HUD_SECURITY_BASIC 1 @@ -49,6 +49,7 @@ #define MOB_HUD_HUNTER_CLAN 17 #define MOB_HUD_EXECUTE 18 #define MOB_HUD_NEW_PLAYER 19 +#define MOB_HUD_SPYCAMS 20 //for SL/FTL/LZ targeting on locator huds #define TRACKER_SL "track_sl" diff --git a/code/__DEFINES/mode.dm b/code/__DEFINES/mode.dm index 5acb27352794..8dc78fdf6629 100644 --- a/code/__DEFINES/mode.dm +++ b/code/__DEFINES/mode.dm @@ -311,6 +311,11 @@ DEFINE_BITFIELD(whitelist_status, list( #define FACTION_LIST_MARINE_UPP list(FACTION_MARINE, FACTION_UPP) #define FACTION_LIST_MARINE_TWE list(FACTION_MARINE, FACTION_TWE) #define FACTION_LIST_YAUTJA list(FACTION_YAUTJA) +#define FACTION_LIST_COLONY list(FACTION_SURVIVOR, FACTION_COLONIST) +#define FACTION_LIST_NEUTRAL list(FACTION_NEUTRAL) + +/// The list of factions loosely allied with the USCM +#define FACTION_LIST_MARINE_FAXES list(FACTION_MARINE, FACTION_WY, FACTION_MARSHAL, FACTION_TWE) // Xenomorphs #define FACTION_PREDALIEN "Predalien" diff --git a/code/_globalvars/lists/mapping_globals.dm b/code/_globalvars/lists/mapping_globals.dm index 772561dbf4a6..67cf01d7e170 100644 --- a/code/_globalvars/lists/mapping_globals.dm +++ b/code/_globalvars/lists/mapping_globals.dm @@ -33,6 +33,7 @@ GLOBAL_LIST_EMPTY(zombie_landmarks) GLOBAL_LIST_EMPTY(newplayer_start) GLOBAL_LIST_EMPTY_TYPED(observer_starts, /obj/effect/landmark/observer_start) +GLOBAL_LIST_EMPTY_TYPED(spycam_starts, /obj/effect/landmark/spycam_start) GLOBAL_LIST_EMPTY(map_items) GLOBAL_LIST_EMPTY(xeno_tunnels) diff --git a/code/datums/mob_hud.dm b/code/datums/mob_hud.dm index c2cb0d8791f0..3bc3486801e7 100644 --- a/code/datums/mob_hud.dm +++ b/code/datums/mob_hud.dm @@ -21,6 +21,7 @@ GLOBAL_LIST_INIT_TYPED(huds, /datum/mob_hud, list( MOB_HUD_HUNTER_CLAN = new /datum/mob_hud/hunter_clan(), MOB_HUD_EXECUTE = new /datum/mob_hud/execute_hud(), MOB_HUD_NEW_PLAYER = new /datum/mob_hud/new_player(), + MOB_HUD_SPYCAMS = new /datum/mob_hud/spy_cams(), )) /datum/mob_hud @@ -219,6 +220,9 @@ GLOBAL_LIST_INIT_TYPED(huds, /datum/mob_hud, list( /datum/mob_hud/faction/observer hud_icons = list(FACTION_HUD, ORDER_HUD, HUNTER_CLAN, HOLOCARD_HUD) +/datum/mob_hud/spy_cams + hud_icons = list(SPYCAM_HUD) + ///////// MOB PROCS //////////////////////////////: diff --git a/code/game/machinery/camera/camera.dm b/code/game/machinery/camera/camera.dm index 1b566dcd3717..8ac1a9590585 100644 --- a/code/game/machinery/camera/camera.dm +++ b/code/game/machinery/camera/camera.dm @@ -38,6 +38,8 @@ var/autoname = FALSE var/autonumber = 0 //camera number in area + var/list/owner_factions = FACTION_LIST_NEUTRAL + GLOBAL_LIST_EMPTY_TYPED(all_cameras, /obj/structure/machinery/camera) /obj/structure/machinery/camera/Initialize(mapload, ...) . = ..() @@ -314,6 +316,9 @@ GLOBAL_LIST_EMPTY_TYPED(all_cameras, /obj/structure/machinery/camera) linked_broadcasting = camera_item c_tag = linked_broadcasting.get_broadcast_name() +/obj/structure/machinery/camera/overwatch + network = list(CAMERA_NET_OVERWATCH) + /obj/structure/machinery/camera/mortar alpha = 0 mouse_opacity = MOUSE_OPACITY_TRANSPARENT diff --git a/code/game/machinery/camera/presets.dm b/code/game/machinery/camera/presets.dm index 6ab2d9569ab9..efe61436e1f4 100644 --- a/code/game/machinery/camera/presets.dm +++ b/code/game/machinery/camera/presets.dm @@ -59,6 +59,7 @@ icon = 'icons/obj/vehicles/interiors/general.dmi' icon_state = "vehicle_camera" network = list(CAMERA_NET_VEHICLE) + owner_factions = FACTION_LIST_HUMANOID /obj/structure/machinery/camera/vehicle/toggle_cam_status(on = FALSE) if(on) @@ -92,6 +93,7 @@ /obj/structure/machinery/camera/autoname/almayer name = "military-grade camera" network = list(CAMERA_NET_ALMAYER) + owner_factions = FACTION_LIST_MARINE_WY /obj/structure/machinery/camera/autoname/almayer/containment name = "containment camera" @@ -104,6 +106,7 @@ /obj/structure/machinery/camera/autoname/almayer/containment/hidden network = list(CAMERA_NET_CONTAINMENT_HIDDEN) + owner_factions = FACTION_LIST_WY /obj/structure/machinery/camera/autoname/almayer/containment/ares name = "ares core camera" @@ -125,6 +128,7 @@ colony_camera_mapload = FALSE emp_proof = TRUE + owner_factions = FACTION_LIST_HUMANOID /obj/structure/machinery/camera/autoname/lz_camera/ex_act() return diff --git a/code/game/machinery/computer/fax_responder_spy.dm b/code/game/machinery/computer/fax_responder_spy.dm new file mode 100644 index 000000000000..e179425ae6be --- /dev/null +++ b/code/game/machinery/computer/fax_responder_spy.dm @@ -0,0 +1,329 @@ +/obj/structure/machinery/computer/spy_camera + name = "remote monitoring computer" + + icon_state = "terminal" + + var/mob/hologram/spy_camera/spy_eye + var/spy_range = 5 + var/spy_faction = FACTION_NEUTRAL + + var/turf/last_location + var/turf/start_location + + /// Computer and Spycam can only be used if this variable is cleared + var/locked = FALSE + +/obj/structure/machinery/computer/spy_camera/attackby(obj/I as obj, mob/user as mob) //Can't break or disassemble. + return + +/obj/structure/machinery/computer/spy_camera/bullet_act(obj/projectile/Proj) //Can't shoot it + return FALSE + +/obj/structure/machinery/computer/spy_camera/proc/set_operator(mob/living/carbon/human/new_operator) + if(!istype(new_operator)) + return + remove_current_operator() + + operator = new_operator + var/datum/mob_hud/spy_hud = GLOB.huds[MOB_HUD_SPYCAMS] + spy_hud.add_hud_to(new_operator, src) + RegisterSignal(operator, COMSIG_PARENT_QDELETING, PROC_REF(remove_current_operator)) + RegisterSignal(operator, COMSIG_MOVABLE_MOVED, PROC_REF(remove_current_operator)) + + if(!last_location) + last_location = loc + + start_location = last_location + + spy_eye = new(last_location, new_operator, src) + //RegisterSignal(eye, COMSIG_MOVABLE_PRE_MOVE, PROC_REF(check_and_set_zlevel)) + RegisterSignal(spy_eye, COMSIG_PARENT_QDELETING, PROC_REF(remove_current_operator)) + +/obj/structure/machinery/computer/spy_camera/proc/remove_current_operator() + SIGNAL_HANDLER + if(!operator) return + + if(spy_eye) + last_location = spy_eye.loc + if(spy_eye.gc_destroyed) + spy_eye = null + else + QDEL_NULL(spy_eye) + + UnregisterSignal(operator, list( + COMSIG_PARENT_QDELETING, + COMSIG_MOVABLE_PRE_MOVE, + COMSIG_MOB_POST_CLICK + )) + operator.update_sight() + var/datum/mob_hud/spy_hud = GLOB.huds[MOB_HUD_SPYCAMS] + spy_hud.remove_hud_from(operator, src) + operator = null + +/obj/structure/machinery/computer/spy_camera/attack_hand(mob/living/carbon/human/pos_operator) + if(..()) + return + + if(!istype(pos_operator)) + return + + if(locked || (!(pos_operator.faction == FACTION_FAX) && !(spy_faction in pos_operator.faction_group))) + to_chat(pos_operator, SPAN_WARNING("The remote camera system is locked out!")) + return FALSE + + if(operator && operator.stat == CONSCIOUS) + to_chat(pos_operator, SPAN_WARNING("Someone is already using this computer!")) + return + + if(tgui_alert(pos_operator, "Change the camera focus?", "Spycam Computer", list("Yes", "No")) == "Yes") + var/obj/effect/landmark/spycam_start/start_point = tgui_input_list(pos_operator, "Where do you want to focus the camera?", "Camera Focus", GLOB.spycam_starts) + if(!start_point) + return + last_location = start_point.loc + + set_operator(pos_operator) + + +/obj/effect/landmark/spycam_start + name = "Spycam Landmark" + icon_state = "spycam" + +/obj/effect/landmark/spycam_start/Initialize() + . = ..() + name = "Spycam [get_area_name(src, TRUE)]" + GLOB.spycam_starts += src + +/obj/effect/landmark/spycam_start/Destroy() + GLOB.spycam_starts -= src + return ..() + +/mob/hologram/spy_camera + name = "Spy Camera" + motion_sensed = FALSE + icon_state = "spycam" + + color = "#10948d" + + hud_possible = list(SPYCAM_HUD) + hears_speech = TRUE + + var/mob/living/carbon/is_watching + + var/spy_range = 5 + var/spy_faction = FACTION_NEUTRAL + + var/list/temporary_list = list() + var/list/temporary_list_2 = list() + + ///Whether or not the camera is on cooldown for a warning message it can't move to a certain tile, locked to one message every 3 seconds. + var/move_warn = FALSE + + +/mob/hologram/spy_camera/Initialize(mapload, mob/living/carbon/spy_operator, obj/structure/machinery/computer/spy_camera/console) + if(!console || !spy_operator) + return INITIALIZE_HINT_QDEL + + if(!istype(console)) + stack_trace("Tried to initialize a /mob/hologram/spy_camera on type ([console.type])") + return INITIALIZE_HINT_QDEL + + spy_range = console.spy_range + spy_faction = console.spy_faction + faction = spy_faction + + switch(spy_faction) + if(FACTION_MARINE, FACTION_MARSHAL) + color = "#0947bb" + if(FACTION_CLF) + color = "#717fbd" + if(FACTION_UPP) + color = "#0f3d11" + if(FACTION_TWE) + color = "#b350c0" + if(FACTION_WY) + color = "#b6b6b6" + + . = ..() + + name = "Spy Camera ([spy_faction])" + RegisterSignal(spy_operator, COMSIG_MOB_PRE_CLICK, PROC_REF(handle_overwatch)) + //RegisterSignal(spy_operator, COMSIG_XENO_OVERWATCH_XENO, PROC_REF(start_watching)) + //RegisterSignal(spy_operator, list( + // COMSIG_XENO_STOP_OVERWATCH, + // COMSIG_XENO_STOP_OVERWATCH_XENO + //), PROC_REF(stop_watching)) + RegisterSignal(src, COMSIG_MOVABLE_TURF_ENTER, PROC_REF(can_spy_turf)) + + med_hud_set_status() + add_to_all_mob_huds() + + spy_operator.sight |= SEE_TURFS|SEE_OBJS + +/mob/hologram/spy_camera/proc/exit_hologram() + SIGNAL_HANDLER + qdel(src) + +/mob/hologram/spy_camera/handle_move(mob/living/carbon/human/spy_operator, NewLoc, direct) + if(is_watching && (can_spy_turf(src, is_watching.loc) & COMPONENT_TURF_DENY_MOVEMENT)) + return COMPONENT_OVERRIDE_MOVE + + return ..() + +/mob/hologram/spy_camera/proc/start_watching(mob/living/carbon/human/source_mob, mob/living/carbon/human/target_mob) + SIGNAL_HANDLER + forceMove(target_mob) + is_watching = target_mob + + RegisterSignal(target_mob, COMSIG_PARENT_QDELETING, PROC_REF(target_watching_qdeleted)) + return + +// able to stop watching here before the loc is set to null +/mob/hologram/spy_camera/proc/target_watching_qdeleted(mob/living/carbon/target) + SIGNAL_HANDLER + stop_watching(linked_mob, target) + +/mob/hologram/spy_camera/proc/stop_watching(mob/living/carbon/human/responder, mob/living/carbon/human/target) + SIGNAL_HANDLER + if(target) + if(loc == target) + var/turf/target_turf = get_turf(target) + + if(target_turf) + forceMove(target_turf) + UnregisterSignal(target, COMSIG_PARENT_QDELETING) + + if(!isturf(loc) || (can_spy_turf(src, loc) & COMPONENT_TURF_DENY_MOVEMENT)) + forceMove(target.loc) + + is_watching = null + target.reset_view() + return + +/mob/hologram/spy_camera/proc/can_spy_turf(mob/self, turf/crossing_turf) + SIGNAL_HANDLER + + if(!crossing_turf || istype(crossing_turf, /turf/open/space) || istype(get_area(crossing_turf), /area/space)) + return COMPONENT_TURF_DENY_MOVEMENT + + if(istype(crossing_turf, /turf/closed/wall)) + var/turf/closed/wall/crossing_wall = crossing_turf + if(crossing_wall.hull) + if(!move_warn) + move_warn = TRUE + addtimer(CALLBACK(src, PROC_REF(reset_warn)), 3 SECONDS) + to_chat(linked_mob, SPAN_WARNING("You cannot move the camera here, it's a solid wall!")) + return COMPONENT_TURF_DENY_MOVEMENT + + if(is_mainship_level(z)) + if(spy_faction in FACTION_LIST_MARINE_FAXES) + return COMPONENT_TURF_ALLOW_MOVEMENT + + var/list/turf_area = view(spy_range, crossing_turf) + temporary_list = turf_area + + var/list/obj/structure/machinery/camera/camera_list = list() + temporary_list_2 = camera_list + + for(var/obj/structure/machinery/camera/nearby_camera in turf_area) + camera_list += nearby_camera + for(var/mob/living/carbon/human/local_mob in turf_area) + if(istype(local_mob.head, /obj/item/clothing/head/helmet/marine)) + var/obj/item/clothing/head/helmet/marine/helm = local_mob.head + camera_list += helm.camera + + for(var/obj/structure/machinery/camera/possible_camera in camera_list) + if(spy_faction in possible_camera.owner_factions) + return COMPONENT_TURF_ALLOW_MOVEMENT + + if(!move_warn) + move_warn = TRUE + addtimer(CALLBACK(src, PROC_REF(reset_warn)), 3 SECONDS) + to_chat(linked_mob, SPAN_WARNING("You can't move the spy here, there's no camera you have access to nearby!")) + return COMPONENT_TURF_DENY_MOVEMENT + +/mob/hologram/spy_camera/proc/reset_warn() + move_warn = FALSE + +/mob/hologram/spy_camera/proc/is_spy_faction(atom/target_atom) + if(!ismob(target_atom)) + return FALSE + var/mob/living/carbon/target_mob = target_atom + if(!(spy_faction in target_mob.faction_group)) + return FALSE + return TRUE + +/mob/hologram/spy_camera/proc/handle_overwatch(mob/living/carbon/human/spy_operator, atom/target_atom, mods) + SIGNAL_HANDLER + + var/turf/target_turf = get_turf(target_atom) + if(!istype(target_turf)) + return + + if(!mods["ctrl"]) + return + + // I want to make this mimic observer follow. + //if(is_spy_faction(target_atom)) + // var/mob/living/carbon/target_mob = target_atom + // return COMPONENT_INTERRUPT_CLICK + + + if(!(can_spy_turf(src, target_turf) & COMPONENT_TURF_ALLOW_MOVEMENT)) + return + + forceMove(target_turf) + + return COMPONENT_INTERRUPT_CLICK + +/mob/hologram/spy_camera/handle_view(mob/spy_operator, atom/target) + if(spy_operator.client) + spy_operator.client.perspective = EYE_PERSPECTIVE + + if(is_watching) + spy_operator.client.eye = is_watching + else + spy_operator.client.eye = src + + return COMPONENT_OVERRIDE_VIEW + +/mob/hologram/spy_camera/Destroy() + if(linked_mob) + linked_mob.sight &= ~(SEE_TURFS|SEE_OBJS) + + remove_from_all_mob_huds() + is_watching = null + + return ..() + +/mob/hologram/spy_camera/add_to_all_mob_huds() + var/datum/mob_hud/hud = GLOB.huds[MOB_HUD_SPYCAMS] + hud.add_to_hud(src) + +/mob/hologram/spy_camera/remove_from_all_mob_huds() + var/datum/mob_hud/hud = GLOB.huds[MOB_HUD_SPYCAMS] + hud.remove_from_hud(src) + +/mob/hologram/spy_camera/med_hud_set_status() + var/image/holder = hud_list[SPYCAM_HUD] + holder.icon_state = "hudeye" + holder.color = color + + + +/obj/structure/machinery/computer/spy_camera/uscm + spy_faction = FACTION_MARINE + +/obj/structure/machinery/computer/spy_camera/wy + spy_faction = FACTION_WY + +/obj/structure/machinery/computer/spy_camera/twe + spy_faction = FACTION_TWE + +/obj/structure/machinery/computer/spy_camera/clf + spy_faction = FACTION_CLF + +/obj/structure/machinery/computer/spy_camera/upp + spy_faction = FACTION_UPP + +/obj/structure/machinery/computer/spy_camera/cmb + spy_faction = FACTION_MARSHAL diff --git a/code/modules/clothing/head/helmet.dm b/code/modules/clothing/head/helmet.dm index fbbd04f0a2be..5df45ac92de5 100644 --- a/code/modules/clothing/head/helmet.dm +++ b/code/modules/clothing/head/helmet.dm @@ -346,6 +346,9 @@ GLOBAL_LIST_INIT(allowed_helmet_items, list( ///Designates a visor type that should start down when initialized var/start_down_visor_type + ///Faction owners of the inbuilt camera + var/list/camera_factions = FACTION_LIST_MARINE_WY + /obj/item/clothing/head/helmet/marine/Initialize(mapload, new_protection[] = list(MAP_ICE_COLONY = ICE_PLANET_MIN_COLD_PROT)) . = ..() if(!(flags_atom & NO_NAME_OVERRIDE)) @@ -367,8 +370,8 @@ GLOBAL_LIST_INIT(allowed_helmet_items, list( pockets.bypass_w_limit = GLOB.allowed_helmet_items pockets.max_storage_space = storage_max_storage_space - camera = new /obj/structure/machinery/camera(src) - camera.network = list(CAMERA_NET_OVERWATCH) + camera = new /obj/structure/machinery/camera/overwatch(src) + camera.owner_factions = camera_factions for(var/obj/visor as anything in built_in_visors) visor.forceMove(src) @@ -1048,6 +1051,7 @@ GLOBAL_LIST_INIT(allowed_helmet_items, list( flags_inventory = BLOCKSHARPOBJ flags_inv_hide = NO_FLAGS flags_marine_helmet = NO_FLAGS + camera_factions = FACTION_LIST_WY /obj/item/clothing/head/helmet/marine/veteran/pmc/leader name = "\improper PMC beret" @@ -1143,6 +1147,7 @@ GLOBAL_LIST_INIT(allowed_helmet_items, list( item_icons = list( WEAR_HEAD = 'icons/mob/humans/onmob/clothing/head/misc_ert_colony.dmi', ) + camera_factions = FACTION_LIST_COLONY //==========================//DISTRESS\\=================================\\ //=======================================================================\\ @@ -1161,6 +1166,7 @@ GLOBAL_LIST_INIT(allowed_helmet_items, list( armor_bomb = CLOTHING_ARMOR_MEDIUM armor_rad = CLOTHING_ARMOR_MEDIUM flags_marine_helmet = HELMET_GARB_OVERLAY|HELMET_DAMAGE_OVERLAY + camera_factions = list(FACTION_DUTCH) /obj/item/clothing/head/helmet/marine/veteran/dutch/cap name = "\improper Dutch's Dozen cap" @@ -1201,6 +1207,7 @@ GLOBAL_LIST_INIT(allowed_helmet_items, list( armor_internaldamage = CLOTHING_ARMOR_HIGH min_cold_protection_temperature = ICE_PLANET_MIN_COLD_PROT clothing_traits = list(TRAIT_EAR_PROTECTION) //the sprites clearly fully cover the ears and most of the head + camera_factions = FACTION_LIST_UPP /obj/item/clothing/head/helmet/marine/veteran/UPP/engi name = "\improper UM4-V helmet" @@ -1246,7 +1253,7 @@ GLOBAL_LIST_INIT(allowed_helmet_items, list( flags_inv_hide = HIDEEARS /obj/item/clothing/head/uppcap/civi - name = "\improper UL2 UPP cap" + name = "\improper UL2C UPP cap" desc = "UPP civilian headgear. It's of poor quality, and isn't expected to last all that long, however for as long as it's whole, it appears quite stylish." icon_state = "upp_cap_civi" @@ -1288,7 +1295,7 @@ GLOBAL_LIST_INIT(allowed_helmet_items, list( /obj/item/clothing/head/uppcap/ushanka/civi - name = "\improper UL8c UPP ushanka" + name = "\improper UL8C UPP ushanka" icon_state = "upp_ushanka_civi" item_state = "upp_ushanka_civi" original_state = "upp_ushanka_civi" @@ -1303,6 +1310,7 @@ GLOBAL_LIST_INIT(allowed_helmet_items, list( WEAR_HEAD = 'icons/mob/humans/onmob/clothing/head/misc_ert_colony.dmi', ) flags_marine_helmet = NO_FLAGS + camera_factions = FACTION_LIST_COLONY //head rag @@ -1425,8 +1433,9 @@ GLOBAL_LIST_INIT(allowed_helmet_items, list( flags_inventory = COVEREYES|COVERMOUTH|BLOCKSHARPOBJ flags_inv_hide = HIDEEARS|HIDEEYES|HIDEFACE|HIDEMASK|HIDEALLHAIR flags_marine_helmet = HELMET_DAMAGE_OVERLAY + camera_factions = FACTION_LIST_MERCENARY -/obj/item/clothing/head/helmet/marine/veteran/mercenary +/obj/item/clothing/head/helmet/marine/veteran/mercenary/heavy name = "\improper Modified K12 ceramic helmet" desc = "A sturdy helmet worn by an unknown mercenary group. Reinforced with extra plating." armor_melee = CLOTHING_ARMOR_ULTRAHIGH @@ -1447,6 +1456,8 @@ GLOBAL_LIST_INIT(allowed_helmet_items, list( armor_bomb = CLOTHING_ARMOR_MEDIUM armor_internaldamage = CLOTHING_ARMOR_HIGHPLUS +/obj/item/clothing/head/helmet/marine/veteran/mercenary/miner/clf + camera_factions = FACTION_LIST_CLF /obj/item/clothing/head/helmet/marine/veteran/mercenary/support name = "\improper Z7 helmet" @@ -1488,6 +1499,7 @@ GLOBAL_LIST_INIT(allowed_helmet_items, list( var/mob/activator = null var/active = FALSE var/det_time = 40 + camera_factions = list(FACTION_HEFA) /obj/item/clothing/head/helmet/marine/specialist/hefa/Initialize(mapload, list/new_protection) . = ..() @@ -1604,6 +1616,7 @@ GLOBAL_LIST_INIT(allowed_helmet_items, list( flags_inv_hide = NO_FLAGS flags_marine_helmet = NO_FLAGS flags_atom = NO_NAME_OVERRIDE|NO_GAMEMODE_SKIN + camera_factions = FACTION_LIST_TWE /obj/item/clothing/head/helmet/marine/veteran/royal_marine/breacher name = "\improper L5A3 ballistic helmet" diff --git a/code/modules/cm_tech/hologram.dm b/code/modules/cm_tech/hologram.dm index 1d85df9e49ad..2365808cd17a 100644 --- a/code/modules/cm_tech/hologram.dm +++ b/code/modules/cm_tech/hologram.dm @@ -18,6 +18,8 @@ GLOBAL_LIST_EMPTY_TYPED(hologram_list, /mob/hologram) var/datum/action/leave_hologram/leave_button ///If can be detected on motion detectors. var/motion_sensed = FALSE + ///If this hologram can hear speech. + var/hears_speech = FALSE /mob/hologram/movement_delay() . = -2 // Very fast speed, so they can navigate through easily, they can't ever have movement delay whilst as a hologram diff --git a/code/modules/gear_presets/clf.dm b/code/modules/gear_presets/clf.dm index 81cb64644b93..4cbb173573b3 100644 --- a/code/modules/gear_presets/clf.dm +++ b/code/modules/gear_presets/clf.dm @@ -987,7 +987,7 @@ access = get_access(ACCESS_LIST_CLF_ALL) /datum/equipment_preset/clf/commander/load_gear(mob/living/carbon/human/new_human) - new_human.equip_to_slot_or_del(new /obj/item/clothing/head/helmet/marine/veteran/mercenary/miner(new_human), WEAR_HEAD) + new_human.equip_to_slot_or_del(new /obj/item/clothing/head/helmet/marine/veteran/mercenary/miner/clf(new_human), WEAR_HEAD) new_human.equip_to_slot_or_del(new /obj/item/device/radio/headset/distress/CLF/command(new_human), WEAR_L_EAR) new_human.equip_to_slot_or_del(new /obj/item/clothing/under/colonist/clf(new_human), WEAR_BODY) new_human.equip_to_slot_or_del(new /obj/item/clothing/suit/storage/militia/smartgun(new_human), WEAR_JACKET) @@ -1014,7 +1014,7 @@ list("Combat Pack", 0, /obj/item/storage/backpack/lightpack, MARINE_CAN_BUY_BACKPACK, VENDOR_ITEM_MANDATORY), list("HELMET (CHOOSE 1)", 0, null, null, null), - list("Y8 Miner Helmet", 0, /obj/item/clothing/head/helmet/marine/veteran/mercenary/miner, MARINE_CAN_BUY_HELMET, VENDOR_ITEM_REGULAR), + list("Y8 Miner Helmet", 0, /obj/item/clothing/head/helmet/marine/veteran/mercenary/miner/clf, MARINE_CAN_BUY_HELMET, VENDOR_ITEM_REGULAR), list("POUCHES (CHOOSE 2)", 0, null, null, null), list("Bayonet Sheath", 0, /obj/item/storage/pouch/bayonet/upp, MARINE_CAN_BUY_POUCH, VENDOR_ITEM_REGULAR), diff --git a/code/modules/mob/dead/observer/observer.dm b/code/modules/mob/dead/observer/observer.dm index 83664697fa09..b8714b3a2c48 100644 --- a/code/modules/mob/dead/observer/observer.dm +++ b/code/modules/mob/dead/observer/observer.dm @@ -388,28 +388,28 @@ the_hud = GLOB.huds[MOB_HUD_MEDICAL_OBSERVER] the_hud.add_hud_to(src, src) if("Security HUD") - the_hud= GLOB.huds[MOB_HUD_SECURITY_ADVANCED] + the_hud = GLOB.huds[MOB_HUD_SECURITY_ADVANCED] the_hud.add_hud_to(src, src) if("Squad HUD") - the_hud= GLOB.huds[MOB_HUD_FACTION_OBSERVER] + the_hud = GLOB.huds[MOB_HUD_FACTION_OBSERVER] the_hud.add_hud_to(src, src) if("Xeno Status HUD") - the_hud= GLOB.huds[MOB_HUD_XENO_STATUS] + the_hud = GLOB.huds[MOB_HUD_XENO_STATUS] the_hud.add_hud_to(src, src) if("Faction UPP HUD") - the_hud= GLOB.huds[MOB_HUD_FACTION_UPP] + the_hud = GLOB.huds[MOB_HUD_FACTION_UPP] the_hud.add_hud_to(src, src) if("Faction Wey-Yu HUD") - the_hud= GLOB.huds[MOB_HUD_FACTION_WY] + the_hud = GLOB.huds[MOB_HUD_FACTION_WY] the_hud.add_hud_to(src, src) if("Faction TWE HUD") - the_hud= GLOB.huds[MOB_HUD_FACTION_TWE] + the_hud = GLOB.huds[MOB_HUD_FACTION_TWE] the_hud.add_hud_to(src, src) if("Faction CLF HUD") - the_hud= GLOB.huds[MOB_HUD_FACTION_CLF] + the_hud = GLOB.huds[MOB_HUD_FACTION_CLF] the_hud.add_hud_to(src, src) if(HUD_MENTOR_SIGHT) - the_hud= GLOB.huds[MOB_HUD_NEW_PLAYER] + the_hud = GLOB.huds[MOB_HUD_NEW_PLAYER] the_hud.add_hud_to(src, src) see_invisible = INVISIBILITY_OBSERVER diff --git a/code/modules/mob/hear_say.dm b/code/modules/mob/hear_say.dm index ef9ac4b6cfcc..e2af9022a2b6 100644 --- a/code/modules/mob/hear_say.dm +++ b/code/modules/mob/hear_say.dm @@ -2,6 +2,19 @@ /mob/proc/hear_apollo() return FALSE +/mob/hologram/hear_say(message, verb = "says", datum/language/language = null, alt_name = "", italics = 0, mob/speaker = null, sound/speech_sound, sound_vol) + if(!hears_speech || !linked_mob) + return + if(speaker == linked_mob) + return + linked_mob.hear_say(message, verb, language, alt_name, italics, speaker, speech_sound, sound_vol) + /// I had to bastardise this because it was duplicating messages for some reason. + if(speaker && linked_mob.client && !linked_mob.ear_deaf) + if(!linked_mob.client?.prefs.lang_chat_disabled && linked_mob.say_understands(speaker, language)) + speaker.langchat_display_image(linked_mob) + return + + /mob/proc/hear_say(message, verb = "says", datum/language/language = null, alt_name = "", italics = 0, mob/speaker = null, sound/speech_sound, sound_vol) if(!client && !(mind && mind.current != src)) diff --git a/colonialmarines.dme b/colonialmarines.dme index c96c2bdfe0f9..8f0bd0b830e7 100644 --- a/colonialmarines.dme +++ b/colonialmarines.dme @@ -932,6 +932,7 @@ #include "code\game\machinery\computer\demo_sim.dm" #include "code\game\machinery\computer\dropship_weapons.dm" #include "code\game\machinery\computer\emails.dm" +#include "code\game\machinery\computer\fax_responder_spy.dm" #include "code\game\machinery\computer\fluff.dm" #include "code\game\machinery\computer\general_air_control.dm" #include "code\game\machinery\computer\groundside_operations.dm" diff --git a/icons/landmarks.dmi b/icons/landmarks.dmi index 32fe9e0790a6..a7ed9ba34c3e 100644 Binary files a/icons/landmarks.dmi and b/icons/landmarks.dmi differ diff --git a/icons/mob/mob.dmi b/icons/mob/mob.dmi index 7b56684a49ff..1d929c9b0d01 100644 Binary files a/icons/mob/mob.dmi and b/icons/mob/mob.dmi differ diff --git a/maps/map_files/BigRed/BigRed.dmm b/maps/map_files/BigRed/BigRed.dmm index b9f432079a10..7609c34f8d57 100644 --- a/maps/map_files/BigRed/BigRed.dmm +++ b/maps/map_files/BigRed/BigRed.dmm @@ -8,6 +8,10 @@ icon_state = "pwall" }, /area/space) +"aac" = ( +/obj/effect/landmark/spycam_start, +/turf/open/floor/asteroidfloor/north, +/area/bigredv2/outside/space_port_lz2) "aad" = ( /turf/open/mars_cave/mars_cave_2, /area/bigredv2/caves_north) @@ -167,6 +171,10 @@ /obj/effect/landmark/objective_landmark/close, /turf/open/floor/dark, /area/bigredv2/outside/space_port) +"aaM" = ( +/obj/effect/landmark/spycam_start, +/turf/open/floor/asteroidfloor/north, +/area/bigredv2/outside/space_port) "aaN" = ( /obj/structure/surface/table, /obj/effect/spawner/random/powercell, @@ -44682,7 +44690,7 @@ aah aah aah aek -aaf +aaM aaf aaf acJ @@ -48034,7 +48042,7 @@ eWd eWd eWd eWd -eWd +aac eWd eWd eWd diff --git a/maps/map_files/DesertDam/Desert_Dam.dmm b/maps/map_files/DesertDam/Desert_Dam.dmm index 631668649b77..9714afe29b05 100644 --- a/maps/map_files/DesertDam/Desert_Dam.dmm +++ b/maps/map_files/DesertDam/Desert_Dam.dmm @@ -10,6 +10,10 @@ /obj/effect/blocker/toxic_water, /turf/open/gm/river/desert/deep, /area/desert_dam/exterior/river/riverside_central_north) +"aac" = ( +/obj/effect/landmark/spycam_start, +/turf/open/desert/dirt, +/area/desert_dam/exterior/landing_pad_two) "aad" = ( /obj/structure/sign/safety/bulkhead_door, /turf/closed/wall/r_wall, @@ -190,6 +194,13 @@ /obj/effect/blocker/toxic_water/Group_2, /turf/open/gm/river/desert/deep, /area/desert_dam/exterior/river/riverside_central_north) +"aaR" = ( +/obj/effect/decal/warning_stripes{ + icon_state = "E" + }, +/obj/effect/landmark/spycam_start, +/turf/open/asphalt, +/area/desert_dam/exterior/landing_pad_one) "aaS" = ( /obj/effect/decal/sand_overlay/sand1{ dir = 4 @@ -54062,7 +54073,7 @@ lIt lIt lIt lIt -lIt +aac lIt lIt lIt @@ -56920,7 +56931,7 @@ aQW aQW aQW aQW -aQW +aaR aQW aQW aQW diff --git a/maps/map_files/FOP_v3_Sciannex/Fiorina_SciAnnex.dmm b/maps/map_files/FOP_v3_Sciannex/Fiorina_SciAnnex.dmm index 94cb78af7e79..8ee647a9edfc 100644 --- a/maps/map_files/FOP_v3_Sciannex/Fiorina_SciAnnex.dmm +++ b/maps/map_files/FOP_v3_Sciannex/Fiorina_SciAnnex.dmm @@ -7,6 +7,14 @@ }, /turf/open/space, /area/fiorina/oob) +"aab" = ( +/obj/effect/landmark/spycam_start, +/turf/open/floor/prison, +/area/fiorina/lz/near_lzII) +"aac" = ( +/obj/effect/landmark/spycam_start, +/turf/open/floor/prison/floor_plate, +/area/fiorina/lz/near_lzI) "aak" = ( /obj/effect/decal/hefa_cult_decals/d32{ icon_state = "4" @@ -67133,7 +67141,7 @@ fAf nZB nZB nZB -fAf +aab nZB nZB nZB @@ -83170,7 +83178,7 @@ nGZ nGZ qaL fDJ -fDJ +aac uYi cUd cUd diff --git a/maps/map_files/Kutjevo/Kutjevo.dmm b/maps/map_files/Kutjevo/Kutjevo.dmm index 59061d40dae3..e4a0d98dbb74 100644 --- a/maps/map_files/Kutjevo/Kutjevo.dmm +++ b/maps/map_files/Kutjevo/Kutjevo.dmm @@ -1,4 +1,12 @@ //MAP CONVERTED BY dmm2tgm.py THIS HEADER COMMENT PREVENTS RECONVERSION, DO NOT REMOVE +"aaa" = ( +/obj/effect/landmark/spycam_start, +/turf/open/auto_turf/sand/layer1, +/area/kutjevo/exterior/lz_dunes) +"aab" = ( +/obj/effect/landmark/spycam_start, +/turf/open/auto_turf/sand/layer1, +/area/kutjevo/exterior/lz_pad) "aat" = ( /obj/structure/flora/grass/tallgrass/desert/corner{ dir = 10 @@ -19969,7 +19977,7 @@ gAM gAM gAM wGH -wGH +aaa wGH wGH wGH @@ -21034,7 +21042,7 @@ lKk lKk lKk lKk -lKk +aab lKk lKk lKk diff --git a/maps/map_files/LV522_Chances_Claim/LV522_Chances_Claim.dmm b/maps/map_files/LV522_Chances_Claim/LV522_Chances_Claim.dmm index a7258d69b201..da8bf451acb4 100644 --- a/maps/map_files/LV522_Chances_Claim/LV522_Chances_Claim.dmm +++ b/maps/map_files/LV522_Chances_Claim/LV522_Chances_Claim.dmm @@ -77418,7 +77418,7 @@ tJa wQa eXG eXG -eXG +aaa eXG eXG wPN diff --git a/maps/map_files/LV624/LV624.dmm b/maps/map_files/LV624/LV624.dmm index 8ad33cc54c03..28350af1f94b 100644 --- a/maps/map_files/LV624/LV624.dmm +++ b/maps/map_files/LV624/LV624.dmm @@ -13,6 +13,14 @@ icon_state = "pwall" }, /area/space) +"aad" = ( +/obj/effect/landmark/spycam_start, +/turf/open/floor, +/area/lv624/lazarus/landing_zones/lz1) +"aae" = ( +/obj/effect/landmark/spycam_start, +/turf/open/gm/dirt, +/area/lv624/lazarus/landing_zones/lz2) "aag" = ( /turf/open/gm/dirt, /area/lv624/ground/caves/north_east_caves) @@ -31393,7 +31401,7 @@ aDv aDv aDv aDv -aDv +aae aDv aDv aOB @@ -54427,7 +54435,7 @@ aGz aHM aGz eaJ -aGz +aad aHM aMq eaJ diff --git a/maps/map_files/New_Varadero/New_Varadero.dmm b/maps/map_files/New_Varadero/New_Varadero.dmm index d031ae9cd81e..f256769eddfd 100644 --- a/maps/map_files/New_Varadero/New_Varadero.dmm +++ b/maps/map_files/New_Varadero/New_Varadero.dmm @@ -1,4 +1,12 @@ //MAP CONVERTED BY dmm2tgm.py THIS HEADER COMMENT PREVENTS RECONVERSION, DO NOT REMOVE +"aaa" = ( +/obj/effect/landmark/spycam_start, +/turf/open/floor/asteroidfloor/north, +/area/varadero/exterior/lz1_near) +"aab" = ( +/obj/effect/landmark/spycam_start, +/turf/open/gm/dirt, +/area/varadero/exterior/lz2_near) "aae" = ( /obj/structure/disposalpipe/segment, /turf/open/floor/shiva, @@ -41694,7 +41702,7 @@ wMw wMw wMw wMw -wMw +aaa xcE wMw wMw @@ -55145,7 +55153,7 @@ lTg wlB wlB wlB -wlB +aab wlB lTg wlB diff --git a/maps/map_files/Sorokyne_Strata/Sorokyne_Strata.dmm b/maps/map_files/Sorokyne_Strata/Sorokyne_Strata.dmm index c0f8e74a4011..08b39b1d55ca 100644 --- a/maps/map_files/Sorokyne_Strata/Sorokyne_Strata.dmm +++ b/maps/map_files/Sorokyne_Strata/Sorokyne_Strata.dmm @@ -1,4 +1,8 @@ //MAP CONVERTED BY dmm2tgm.py THIS HEADER COMMENT PREVENTS RECONVERSION, DO NOT REMOVE +"aaa" = ( +/obj/effect/landmark/spycam_start, +/turf/open/auto_turf/snow/brown_base/layer0, +/area/strata/ag/exterior/landing_zones/near_lz2) "aab" = ( /turf/closed/shuttle{ dir = 1; @@ -11,6 +15,10 @@ "aad" = ( /turf/closed/wall/strata_ice/jungle, /area/strata/ug/interior) +"aae" = ( +/obj/effect/landmark/spycam_start, +/turf/open/floor/strata, +/area/strata/ag/interior/landing_zones/near_lz1) "aaf" = ( /obj/effect/landmark/xeno_spawn, /turf/open/floor/strata/multi_tiles/southwest, @@ -37489,7 +37497,7 @@ cqE cqE cqE cqE -cqE +aae cqE cqE cqE @@ -43509,7 +43517,7 @@ wSb wSb bvD bvD -bvD +aaa xgU bvD xTU diff --git a/maps/map_files/USS_Almayer/USS_Almayer.dmm b/maps/map_files/USS_Almayer/USS_Almayer.dmm index 52a93e2c0b98..101944778a2f 100644 --- a/maps/map_files/USS_Almayer/USS_Almayer.dmm +++ b/maps/map_files/USS_Almayer/USS_Almayer.dmm @@ -131,9 +131,21 @@ }, /turf/open/floor/plating/plating_catwalk, /area/almayer/engineering/upper_engineering/starboard) +"aas" = ( +/obj/effect/landmark/spycam_start, +/turf/open/floor/almayer/plate, +/area/almayer/hallways/hangar) +"aat" = ( +/obj/effect/landmark/spycam_start, +/turf/open/floor/almayer/plate, +/area/almayer/engineering/lower/workshop) "aau" = ( /turf/closed/wall/almayer/reinforced/temphull, /area/almayer/living/pilotbunks) +"aav" = ( +/obj/effect/landmark/spycam_start, +/turf/open/floor/almayer, +/area/almayer/command/lifeboat) "aaC" = ( /obj/structure/lattice, /turf/open/space/basic, @@ -8798,6 +8810,7 @@ /obj/structure/pipes/standard/manifold/hidden/supply{ dir = 4 }, +/obj/effect/landmark/spycam_start, /turf/open/floor/plating/plating_catwalk, /area/almayer/hallways/upper/fore_hallway) "bjA" = ( @@ -85520,7 +85533,7 @@ xyw xyw xyw xyw -xyw +aas xyw xyw xyw @@ -118812,7 +118825,7 @@ uZF xoj xoj osI -qXk +aat fie pUj xoj @@ -119929,7 +119942,7 @@ eky aDQ pyy eky -eky +aav eky dLc aDQ