From 67c21a2f3036149c68bded10bc4613343355fc14 Mon Sep 17 00:00:00 2001 From: Paul Mullen <101871009+mullenpaul@users.noreply.github.com> Date: Sat, 30 Dec 2023 08:56:22 +0000 Subject: [PATCH 01/16] sentry laptop now uses camera manager (#5309) The sentry laptop had a bunch of custom code for handling gunsight cameras. This PR refactors it to exclusively use the camera_manager component. Reduction of duplicated code.
Screenshots & Videos Put screenshots and videos here with an empty line between the screenshots and the `
` tags.
:cl: refactor: sentry laptop now uses camera manager component /:cl: --- code/modules/defenses/sentry_computer.dm | 117 ++++++----------------- 1 file changed, 27 insertions(+), 90 deletions(-) diff --git a/code/modules/defenses/sentry_computer.dm b/code/modules/defenses/sentry_computer.dm index bb6f55d72b..fa57bc7901 100644 --- a/code/modules/defenses/sentry_computer.dm +++ b/code/modules/defenses/sentry_computer.dm @@ -48,41 +48,18 @@ // Stuff needed to render the map /// asset name for the game map - var/map_name - - /// camera screen which renders the world - var/atom/movable/screen/map_view/cam_screen - - /// camera screen which shows a blank error - var/atom/movable/screen/background/cam_background - - var/list/cam_plane_masters + var/camera_map_name /obj/item/device/sentry_computer/Initialize(mapload) . = ..() if(cell_type) cell = new cell_type() cell.charge = cell.maxcharge - // set up cameras - map_name = "sentry_computer_[REF(src)]_map" - cam_screen = new - cam_screen.name = "screen" - cam_screen.assigned_map = map_name - cam_screen.del_on_map_removal = FALSE - cam_screen.screen_loc = "[map_name]:1,1" - cam_background = new - cam_background.assigned_map = map_name - cam_background.del_on_map_removal = FALSE - - cam_plane_masters = list() - for(var/plane in subtypesof(/atom/movable/screen/plane_master) - /atom/movable/screen/plane_master/blackness) - var/atom/movable/screen/plane_master/instance = new plane() - instance.assigned_map = map_name - instance.del_on_map_removal = FALSE - if(instance.blend_mode_override) - instance.blend_mode = instance.blend_mode_override - instance.screen_loc = "[map_name]:CENTER" - cam_plane_masters += instance + + RegisterSignal(src, COMSIG_CAMERA_MAPNAME_ASSIGNED, PROC_REF(camera_mapname_update)) + + AddComponent(/datum/component/camera_manager) + SEND_SIGNAL(src, COMSIG_CAMERA_CLEAR) faction_group = FACTION_LIST_MARINE transceiver.forceMove(src) @@ -94,9 +71,8 @@ /obj/item/device/sentry_computer/Destroy() . = ..() + UnregisterSignal(src, COMSIG_CAMERA_MAPNAME_ASSIGNED) QDEL_NULL(cell) - QDEL_NULL(cam_background) - QDEL_NULL(cam_screen) QDEL_NULL(transceiver) QDEL_NULL(voice) last_camera_turf = null @@ -104,6 +80,9 @@ registered_tools = null paired_sentry = null +/obj/item/device/sentry_computer/proc/camera_mapname_update(source, value) + camera_map_name = value + /obj/item/device/sentry_computer/Move(NewLoc, direct) ..() if(table_setup || open || on) @@ -321,7 +300,7 @@ if(current == target) current = null - update_active_camera() + SEND_SIGNAL(src, COMSIG_CAMERA_CLEAR) /obj/item/device/sentry_computer/ui_status(mob/user, datum/ui_state/state) . = ..() @@ -332,15 +311,13 @@ /obj/item/device/sentry_computer/ui_close(mob/user) - - // Unregister map objects - user.client.clear_map(map_name) + SEND_SIGNAL(src, COMSIG_CAMERA_UNREGISTER_UI, user) /obj/item/device/sentry_computer/ui_static_data(mob/user) . = list() .["sentry_static"] = list() - .["mapRef"] = map_name + .["mapRef"] = camera_map_name var/index = 1 for(var/sentry in paired_sentry) var/list/sentry_holder = list() @@ -396,13 +373,8 @@ /obj/item/device/sentry_computer/tgui_interact(mob/user, datum/tgui/ui) ui = SStgui.try_update_ui(user, src, ui) - update_active_camera() if (!ui) - // Register map objects - user.client.register_map_obj(cam_background) - user.client.register_map_obj(cam_screen) - for(var/plane in cam_plane_masters) - user.client.register_map_obj(plane) + SEND_SIGNAL(src, COMSIG_CAMERA_REGISTER_UI, user) ui = new(user, src, "SentryGunUI", name) ui.open() @@ -426,7 +398,18 @@ if("set-camera") current = sentry playsound(src, get_sfx("terminal_button"), 25, FALSE) - update_active_camera() + var/obj/structure/machinery/defenses/sentry/defense = sentry + if (defense.has_camera) + defense.set_watched_turfs() + var/list/turf/visible_turfs = defense.watching_turfs + var/list/bbox = get_bbox_of_atoms(visible_turfs) + var/center_x = (bbox[3] + bbox[1]) * 0.5 + var/center_y = (bbox[4] + bbox[2]) * 0.5 + var/size_x = bbox[3] - bbox[1] + 1 + var/size_y = bbox[4] - bbox[2] + 1 + var/datum/shape/rectangle/current_bb = defense.range_bounds + SEND_SIGNAL(src, COMSIG_CAMERA_SET_AREA, center_x, center_y, defense.loc.z, size_x, size_y) + return TRUE if("ping") playsound(sentry, 'sound/machines/twobeep.ogg', 50, 1) @@ -439,54 +422,8 @@ if("clear-camera") current = null playsound(src, get_sfx("terminal_button"), 25, FALSE) - update_active_camera() + SEND_SIGNAL(src, COMSIG_CAMERA_CLEAR) return TRUE if("ui-interact") playsound(src, get_sfx("terminal_button"), 25, FALSE) return FALSE - -/** - * Set the displayed camera to the static not-connected. - */ -/obj/item/device/sentry_computer/proc/show_camera_static() - cam_screen.vis_contents.Cut() - last_camera_turf = null - cam_background.icon_state = "scanline2" - cam_background.fill_rect(1, 1, 15, 15) - -/** - * Update camera settings and redraw camera on the current variable. - */ -/obj/item/device/sentry_computer/proc/update_active_camera() - // Show static if can't use the camera - if(isnull(current) || !current.has_camera || current.placed != 1) - show_camera_static() - return - - // Is this camera located in or attached to a living thing, Vehicle or helmet? If so, assume the camera's loc is the living (or non) thing. - var/cam_location = current - if(isliving(current.loc) || isVehicle(current.loc)) - cam_location = current.loc - else if(istype(current.loc, /obj/item/clothing/head/helmet/marine)) - var/obj/item/clothing/head/helmet/marine/helmet = current.loc - cam_location = helmet.loc - // If we're not forcing an update for some reason and the cameras are in the same location, - // we don't need to update anything. - // Most security cameras will end here as they're not moving. - if(last_camera_turf == get_turf(cam_location)) - return - - // Cameras that get here are moving, and are likely attached to some moving atom such as cyborgs. - last_camera_turf = get_turf(cam_location) - - current.set_watched_turfs() - var/list/turf/visible_turfs = current.watching_turfs - - var/list/bbox = get_bbox_of_atoms(visible_turfs) - var/size_x = bbox[3] - bbox[1] + 1 - var/size_y = bbox[4] - bbox[2] + 1 - cam_screen.icon = null - cam_screen.icon_state = "clear" - cam_screen.vis_contents = visible_turfs - cam_background.icon_state = "clear" - cam_background.fill_rect(1, 1, size_x, size_y) From 59248e3c31f109e29652c1660c7c0837e7cf1cca Mon Sep 17 00:00:00 2001 From: Doubleumc Date: Tue, 6 Aug 2024 02:05:00 -0400 Subject: [PATCH 02/16] Update sentry_computer.dm --- code/modules/defenses/sentry_computer.dm | 1 - 1 file changed, 1 deletion(-) diff --git a/code/modules/defenses/sentry_computer.dm b/code/modules/defenses/sentry_computer.dm index fa57bc7901..9e44e9eeb6 100644 --- a/code/modules/defenses/sentry_computer.dm +++ b/code/modules/defenses/sentry_computer.dm @@ -407,7 +407,6 @@ var/center_y = (bbox[4] + bbox[2]) * 0.5 var/size_x = bbox[3] - bbox[1] + 1 var/size_y = bbox[4] - bbox[2] + 1 - var/datum/shape/rectangle/current_bb = defense.range_bounds SEND_SIGNAL(src, COMSIG_CAMERA_SET_AREA, center_x, center_y, defense.loc.z, size_x, size_y) return TRUE From 3307a372916e44cd72fa2844e58c131f97ecdb2f Mon Sep 17 00:00:00 2001 From: Drathek <76988376+Drulikar@users.noreply.github.com> Date: Sat, 6 Jan 2024 06:12:33 -0800 Subject: [PATCH 03/16] Port Overlay Lighting Fixes (#5331) This PR ports https://github.com/tgstation/tgstation/pull/79939 and fixes a few other things in the overlay_lighting component. Less hard deletes and lights in objects disables the light (despite actually still being on). Fixes: https://github.com/cmss13-devs/cmss13/assets/76988376/4a89b0de-ccb2-4d80-a081-2ec2d311f753
Screenshots & Videos ![flares](https://github.com/cmss13-devs/cmss13/assets/76988376/12765f93-78e9-42f3-90f9-5118ad62af65) https://github.com/cmss13-devs/cmss13/assets/76988376/cb7b2d6d-9f2d-4e0e-86cd-82371582524e
:cl: Drathek refactor: Refactored the overlay_lighting component to better handle objects deleting fix: Fix putting lights in bags somereason keeping the light on /:cl: --- code/datums/components/overlay_lighting.dm | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/code/datums/components/overlay_lighting.dm b/code/datums/components/overlay_lighting.dm index e14066ffb7..225149ecb4 100644 --- a/code/datums/components/overlay_lighting.dm +++ b/code/datums/components/overlay_lighting.dm @@ -199,7 +199,7 @@ get_new_turfs() -///Adds the luminosity and source for the afected movable atoms to keep track of their visibility. +///Adds the luminosity and source for the affected movable atoms to keep track of their visibility. /datum/component/overlay_lighting/proc/add_dynamic_lumi() LAZYSET(current_holder.affected_movable_lights, src, lumcount_range + 1) current_holder.underlays += visible_mask @@ -207,7 +207,7 @@ if(directional) current_holder.underlays += cone -///Removes the luminosity and source for the afected movable atoms to keep track of their visibility. +///Removes the luminosity and source for the affected movable atoms to keep track of their visibility. /datum/component/overlay_lighting/proc/remove_dynamic_lumi() LAZYREMOVE(current_holder.affected_movable_lights, src) current_holder.underlays -= visible_mask @@ -267,6 +267,9 @@ ///Used to determine the new valid current_holder from the parent's loc. /datum/component/overlay_lighting/proc/check_holder() var/atom/movable/movable_parent = GET_PARENT + if(QDELETED(movable_parent)) + set_holder(null) + return if(isturf(movable_parent.loc)) set_holder(movable_parent) return @@ -275,13 +278,21 @@ set_holder(null) return if(isturf(inside.loc)) - set_holder(inside) + // storage items block light, also don't be moving into a qdeleted item + if(QDELETED(inside) || istype(inside, /obj/item/storage)) + set_holder(null) + else + set_holder(inside) return set_holder(null) ///Called when the current_holder is qdeleted, to remove the light effect. /datum/component/overlay_lighting/proc/on_holder_qdel(atom/movable/source, force) + SIGNAL_HANDLER + if(QDELETED(current_holder)) + set_holder(null) + return UnregisterSignal(current_holder, list(COMSIG_PARENT_QDELETING, COMSIG_MOVABLE_MOVED)) if(directional) UnregisterSignal(current_holder, COMSIG_ATOM_DIR_CHANGE) @@ -290,6 +301,7 @@ ///Called when current_holder changes loc. /datum/component/overlay_lighting/proc/on_holder_moved(atom/movable/source, OldLoc, Dir, Forced) + SIGNAL_HANDLER if(!(overlay_lighting_flags & LIGHTING_ON)) return make_luminosity_update() @@ -450,8 +462,7 @@ . = lum_power lum_power = new_lum_power var/difference = . - lum_power - for(var/t in affected_turfs) - var/turf/lit_turf = t + for(var/turf/lit_turf as anything in affected_turfs) lit_turf.dynamic_lumcount -= difference ///Here we append the behavior associated to changing lum_power. From 5db17819732a8b42829daed30e3352c0a8e4c9a2 Mon Sep 17 00:00:00 2001 From: Drathek <76988376+Drulikar@users.noreply.github.com> Date: Sun, 31 Dec 2023 16:27:47 -0800 Subject: [PATCH 04/16] Fix runtimes and multitool bricking if a sentry_computer is deleted (#5345) This PR resolves some runtimes and the bricking of a multitool if it is loaded with a deleted sentry. The weakref resolve in the multitool wasn't checked if the resolve passed. Additionally, the sentries would remain encrypted to a non-existent computer. If bricking an encrypted sentry is intended, it needs to be handled more gracefully. Fixes a runtime when using a multitool linked to a deleted sentry_computer: ![image](https://github.com/cmss13-devs/cmss13/assets/76988376/4db7c411-aff1-4b56-9cee-b2cec6e05519) Fixes a runtime when using said multitool to unpair the sentry from a deleted sentry_computer. ![image](https://github.com/cmss13-devs/cmss13/assets/76988376/946f002d-2246-4632-a554-e2cfd6ad5a9d)
Screenshots & Videos 1. Link tuner w/ a laptop 2. Delete laptop 3. Spawn a new laptop 4. Use tuner on new laptop 5. Runtime when trying to clear because the weakref resolve wasn't checked. https://github.com/cmss13-devs/cmss13/assets/76988376/bfe447ce-a6dc-4d88-b3e8-b4ee6efb1daf
:cl: Drathek fix: Fix handling of sentry_computer deletion /:cl: --- code/modules/defenses/sentry_computer.dm | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/code/modules/defenses/sentry_computer.dm b/code/modules/defenses/sentry_computer.dm index 9e44e9eeb6..7cb4f7bb84 100644 --- a/code/modules/defenses/sentry_computer.dm +++ b/code/modules/defenses/sentry_computer.dm @@ -78,6 +78,8 @@ last_camera_turf = null current = null registered_tools = null + for(var/obj/structure/machinery/defenses/sentry/sentrygun as anything in paired_sentry) + unpair_sentry(sentrygun) paired_sentry = null /obj/item/device/sentry_computer/proc/camera_mapname_update(source, value) @@ -211,7 +213,7 @@ for(var/key_id in tool.encryption_keys) var/datum/weakref/ref = tool.encryption_keys[key_id] var/obj/item/device/sentry_computer/key_object = ref.resolve() - key_object.registered_tools -= id + key_object?.registered_tools -= id tool.encryption_keys = list() to_chat(user, SPAN_NOTICE("Existing encryption keys cleared.")) to_chat(usr, SPAN_NOTICE("You begin encryption key to \the [tool].")) @@ -319,9 +321,8 @@ .["sentry_static"] = list() .["mapRef"] = camera_map_name var/index = 1 - for(var/sentry in paired_sentry) + for(var/obj/structure/machinery/defenses/sentry/sentrygun as anything in paired_sentry) var/list/sentry_holder = list() - var/obj/structure/machinery/defenses/sentry/sentrygun = sentry sentry_holder["selection_menu"] = list() sentry_holder["index"] = index sentry_holder["name"] = sentrygun.name From 8eb219b5735655a6341b4de734e0afe3ddf2d740 Mon Sep 17 00:00:00 2001 From: ihatethisengine <115417687+ihatethisengine@users.noreply.github.com> Date: Fri, 24 Nov 2023 13:13:55 +0300 Subject: [PATCH 05/16] Lockdown actually closes doors on DS (#5015) Lockdown actually closes doors on DS. It used to be the case before the gui rework. I think. Anyway DP should be able to control doors, hunting for the moment when all doors are closed to lock them is extremely not fun.
:)
:cl: ihatethisengine add: Locking down dropship's doors closes them before locking. /:cl: From 804277894596dbacb1f10b862290226acab07441 Mon Sep 17 00:00:00 2001 From: fira Date: Sat, 28 Oct 2023 13:33:43 +0200 Subject: [PATCH 06/16] Remove Direct Hit Limb Penalty against Xenos (#4788) Selecting a body part on doll at bottom right applies an inherent accuracy debuff to shots (an hand is harder to hit than chest). This penalty still applied to sprite-click attacks on Xenomorphs, despite the localized damage having no effect. This means that you'd have to constantly reset your aimed part to chest every time you try to shoot a Xeno, or would suffer a "free" penalty. Old flow went as follow: * Get base Hit Chance and Roll * If it's only a near hit, or target's not the shot clicked target, the shot targeted limb is reset to a random one * Hit chance receives a penalty based on aimed limb * We proceed checking hit chance vs roll Because of the above problem this is changed to: * Get base Hit Chance and Roll * If it's a near hit (including limb penalty), a near xeno hit (excluding limb penalty), or not the sprite-clicked target, aimed limb is reset to a random one * Else if the target is a xeno and it was a proper direct hit, there is no penalty -- functionally similar to a chest shot * Else Finally, apply per-limb penalty as usual * We proceed checking hit chance vs roll Avoids an invisible noobtrap debuff for just about everyone in the game that isn't in the know - and the neccessity to constantly reset targeting to chest for medics. The problem was tested by a player on discord -- the fix i tested just was spawning stuff and shooting up the place observing RNG misses. I did not take detailed statistics over time to confirm. :cl: fix: Sprite-click shots onto Xenos are no longer affected by limb-targeting penalty, because it was an accuracy debuff when there is no inherent benefit to targeting Xeno limbs. /:cl: From 064e119ed94ef34a7c336b3e86856ef22dc5e60d Mon Sep 17 00:00:00 2001 From: Vero <73014819+vero5123@users.noreply.github.com> Date: Mon, 8 Apr 2024 05:26:40 -0400 Subject: [PATCH 07/16] Fixes notifications emitting light (#6088) # About the pull request Fixes #5985, albeit there might be a better approach. # Explain why it's good for the game bug fix, tested it with the steps listed in the issue. Worked as far as I could tell. # Changelog :cl: fix: Notifications should no longer emit light. /:cl: --------- Co-authored-by: DOOM --- code/modules/mob/mob_helpers.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/modules/mob/mob_helpers.dm b/code/modules/mob/mob_helpers.dm index 7bda746325..2664c14a8a 100644 --- a/code/modules/mob/mob_helpers.dm +++ b/code/modules/mob/mob_helpers.dm @@ -584,7 +584,7 @@ var/global/list/limb_types_by_name = list( alert_overlay.layer = FLOAT_LAYER alert_overlay.plane = FLOAT_PLANE - + alert_overlay.underlays.Cut() screen_alert.overlays += alert_overlay /mob/proc/reset_lighting_alpha() From dc9000caeb28108b1ffc0072377a0416d92de478 Mon Sep 17 00:00:00 2001 From: Doubleumc Date: Sat, 6 Jul 2024 03:22:15 -0400 Subject: [PATCH 08/16] Sound Environment update (#6620) Changes to how a client's sound `environment` and `echo` is handled: https://www.byond.com/docs/ref/#/sound/var/environment https://www.byond.com/docs/ref/#/sound/var/echo A client's `soundOutput` now has sole control over environment and echo. The environment is updated when the mob moves into a different area, or if the mob's environment override is set. The echo is used to enable or disable the environmental reverb per-sound. Issue: an environment applies to all sounds for that client, current and future, until another one is set. It applies to in-world sounds as well as, say, admin pings. Solution: since an echo is applied per-sound, by adjusting the echo's Room & RoomHF fields the environmental effects can be enabled or disabled (more accurately, made so quiet as to be inaudible). This is set to off by default, and is only enabled for positional sounds. Admin pings are safe. Idea from here: https://github.com/tgstation/tgstation/pull/55333 Boots without issue. Sound environments change at appropriate points. Sound environments effect only positional sounds. :cl: code: environmental reverb applies more reliably and only to positional sounds /:cl: --- code/__DEFINES/sounds.dm | 3 + code/datums/soundOutput.dm | 75 +++++++++++++++++++++---- code/game/sound.dm | 43 ++++++++++---- code/modules/mob/living/init_signals.dm | 2 + code/modules/mob/living/living.dm | 4 -- 5 files changed, 99 insertions(+), 28 deletions(-) diff --git a/code/__DEFINES/sounds.dm b/code/__DEFINES/sounds.dm index 6c5d2879f3..13a4468427 100644 --- a/code/__DEFINES/sounds.dm +++ b/code/__DEFINES/sounds.dm @@ -61,6 +61,9 @@ #define SOUND_ENVIRONMENT_DIZZY 24 #define SOUND_ENVIRONMENT_PSYCHOTIC 25 +#define SOUND_ECHO_REVERB_ON list(0, 0, 0, 0, 0, 0.0, 0, 0.25, 1.5, 1.0, 0, 1.0, 0, 0.0, 0.0, 0.0, 1.0, 0) +#define SOUND_ECHO_REVERB_OFF list(0, 0, -10000, -10000, 0, 0.0, 0, 0.25, 1.5, 1.0, 0, 1.0, 0, 0.0, 0.0, 0.0, 1.0, 0) //-10000 to Room & RoomHF makes enviromental reverb effectively inaudible + #define AMBIENCE_SHIP 'sound/ambience/shipambience.ogg' #define AMBIENCE_JUNGLE 'sound/ambience/ambienceLV624.ogg' #define AMBIENCE_RIVER 'sound/ambience/ambienceriver.ogg' diff --git a/code/datums/soundOutput.dm b/code/datums/soundOutput.dm index 85548d6c90..0fddd9b503 100644 --- a/code/datums/soundOutput.dm +++ b/code/datums/soundOutput.dm @@ -4,13 +4,25 @@ var/list/soundscape_playlist = list() //Updated on changing areas var/ambience = null //The file currently being played as ambience var/status_flags = 0 //For things like ear deafness, psychodelic effects, and other things that change how all sounds behave - var/list/echo -/datum/soundOutput/New(client/C) - if(!C) + + /// Currently applied environmental reverb. + VAR_PROTECTED/owner_environment = SOUND_ENVIRONMENT_NONE + +/datum/soundOutput/New(client/client) + if(!client) qdel(src) return - owner = C - . = ..() + owner = client + RegisterSignal(owner.mob, COMSIG_MOVABLE_MOVED, PROC_REF(on_mob_moved)) + RegisterSignal(owner.mob, COMSIG_MOB_LOGOUT, PROC_REF(on_mob_logout)) + RegisterSignal(owner, COMSIG_CLIENT_MOB_LOGGED_IN, PROC_REF(on_client_mob_logged_in)) + return ..() + +/datum/soundOutput/Destroy() + UnregisterSignal(owner.mob, list(COMSIG_MOVABLE_MOVED, COMSIG_MOB_LOGOUT)) + UnregisterSignal(owner, COMSIG_CLIENT_MOB_LOGGED_IN) + owner = null + return ..() /datum/soundOutput/proc/process_sound(datum/sound_template/T) var/sound/S = sound(T.file, T.repeat, T.wait) @@ -24,7 +36,6 @@ S.offset = T.offset S.pitch = T.pitch S.status = T.status - S.echo = T.echo if(T.x && T.y && T.z) var/turf/owner_turf = get_turf(owner.mob) if(owner_turf) @@ -40,16 +51,12 @@ S.x = T.x - owner_turf.x S.y = 0 S.z = T.y - owner_turf.y - var/area/A = owner_turf.loc - S.environment = A.sound_environment S.y += T.y_s_offset S.x += T.x_s_offset + S.echo = SOUND_ECHO_REVERB_ON //enable environment reverb for positional sounds if(owner.mob.ear_deaf > 0) S.status |= SOUND_MUTE - if(owner.mob.sound_environment_override != SOUND_ENVIRONMENT_NONE) - S.environment = owner.mob.sound_environment_override - sound_to(owner,S) /datum/soundOutput/proc/update_ambience(area/target_area, ambience_override, force_update = FALSE) @@ -86,7 +93,6 @@ S.status = status_flags if(target_area) - S.environment = target_area.sound_environment var/muffle if(target_area.ceiling_muffle) switch(target_area.ceiling) @@ -130,6 +136,51 @@ S.status = SOUND_UPDATE sound_to(owner, S) +/// Pulls mob's area's sound_environment and applies if necessary and not overridden. +/datum/soundOutput/proc/update_area_environment() + var/area/owner_area = get_area(owner.mob) + var/new_environment = owner_area.sound_environment + + if(owner.mob.sound_environment_override != SOUND_ENVIRONMENT_NONE) //override in effect, can't apply + return + + set_owner_environment(new_environment) + +/// Pulls mob's sound_environment_override and applies if necessary. +/datum/soundOutput/proc/update_mob_environment_override() + var/new_environment_override = owner.mob.sound_environment_override + + if(new_environment_override == SOUND_ENVIRONMENT_NONE) //revert to area environment + update_area_environment() + return + + set_owner_environment(new_environment_override) + +/// Pushes new_environment to owner and updates owner_environment var. +/datum/soundOutput/proc/set_owner_environment(new_environment = SOUND_ENVIRONMENT_NONE) + if(new_environment ~= src.owner_environment) //no need to change + return + + var/sound/sound = sound() + sound.environment = new_environment + sound_to(owner, sound) + + src.owner_environment = new_environment + +/datum/soundOutput/proc/on_mob_moved(datum/source, atom/oldloc, direction, Forced) + SIGNAL_HANDLER //COMSIG_MOVABLE_MOVED + update_area_environment() + +/datum/soundOutput/proc/on_mob_logout(datum/source) + SIGNAL_HANDLER //COMSIG_MOB_LOGOUT + UnregisterSignal(owner.mob, list(COMSIG_MOVABLE_MOVED, COMSIG_MOB_LOGOUT)) + +/datum/soundOutput/proc/on_client_mob_logged_in(datum/source, mob/new_mob) + SIGNAL_HANDLER //COMSIG_CLIENT_MOB_LOGGED_IN + RegisterSignal(owner.mob, COMSIG_MOVABLE_MOVED, PROC_REF(on_mob_moved)) + RegisterSignal(owner.mob, COMSIG_MOB_LOGOUT, PROC_REF(on_mob_logout)) + update_mob_environment_override() + /client/proc/adjust_volume_prefs(volume_key, prompt = "", channel_update = 0) volume_preferences[volume_key] = (tgui_input_number(src, prompt, "Volume", volume_preferences[volume_key]*100)) / 100 if(volume_preferences[volume_key] > 1) diff --git a/code/game/sound.dm b/code/game/sound.dm index f2574975a7..6bee74ba01 100644 --- a/code/game/sound.dm +++ b/code/game/sound.dm @@ -1,3 +1,5 @@ +/sound + echo = SOUND_ECHO_REVERB_OFF //disable enviroment reverb by default, soundOutput re-enables for positional sounds /datum/sound_template //Basically a sound datum, but only serves as a way to carry info to soundOutput //copied sound datum vars @@ -23,8 +25,6 @@ var/falloff = 1 ///Changes the environmental reverb for all 3D sounds until another environment is specified. The default value (-1) specifies no change in environment. A numeric value from 0 to 25 specifies a set of reverb presets for the environment. var/environment = -1 - ///If set to an 18-element list, this value customizes reverbration settings for this sound only. - var/list/echo //custom vars ///The category of this sound for client volume purposes: VOLUME_SFX (Sound effects), VOLUME_AMB (Ambience and Soundscapes) and VOLUME_ADM (Admin sounds and some other stuff) @@ -59,16 +59,40 @@ * * channel - use this only when you want to force the sound to play on a specific channel * * status - combined bit flags: SOUND_MUTE, SOUND_PAUSED, SOUND_STREAM, SOUND_UPDATE * * falloff - max range till sound volume starts dropping as distance increases - * * echo - customizes reverbration settings for this sound * * y_s_offset - vertical sound position offset * * x_s_offset - horizontal sound position offset * * Returns selected channel on success, FALSE on failure */ -/proc/playsound(atom/source, sound/soundin, vol = 100, vary = FALSE, sound_range, vol_cat = VOLUME_SFX, channel = 0, status, falloff = 1, list/echo, y_s_offset, x_s_offset) +/proc/playsound(atom/source, sound/soundin, vol = 100, vary = FALSE, sound_range, vol_cat = VOLUME_SFX, channel = 0, status, falloff = 1, y_s_offset, x_s_offset) if(isarea(source)) error("[source] is an area and is trying to make the sound: [soundin]") return FALSE + var/datum/sound_template/S = new() + + var/sound/SD = soundin + if(istype(SD)) + S.file = SD.file + S.wait = SD.wait + S.repeat = SD.repeat + else + S.file = get_sfx(soundin) + S.channel = channel ? channel : get_free_channel() + S.status = status + S.falloff = falloff + S.volume = vol + S.volume_cat = vol_cat + S.y_s_offset = y_s_offset + S.x_s_offset = x_s_offset + if(vary != FALSE) + if(vary > 1) + S.frequency = vary + else + S.frequency = GET_RANDOM_FREQ // Same frequency for everybody + + if(!sound_range) + sound_range = floor(0.25*vol) //if no specific range, the max range is equal to a quarter of the volume. + S.range = sound_range var/turf/turf_source = get_turf(source) if(!turf_source?.z) @@ -100,7 +124,6 @@ template.frequency = GET_RANDOM_FREQ // Same frequency for everybody template.status = status template.falloff = falloff - template.echo = echo template.volume_cat = vol_cat template.range = sound_range || floor(0.25 * vol) //if no specific range, the max range is equal to a quarter of the volume. @@ -147,13 +170,12 @@ * * vol_cat - the category of this sound for client volume purposes: VOLUME_SFX (Sound effects), VOLUME_AMB (Ambience and Soundscapes), VOLUME_ADM (Admin sounds) * * channel - use this only when you want to force the sound to play on a specific channel * * status - combined bit flags: SOUND_MUTE, SOUND_PAUSED, SOUND_STREAM, SOUND_UPDATE - * * echo - customizes reverbration settings for this sound * * y_s_offset - vertical sound position offset * * x_s_offset - horizontal sound position offset * * Returns FALSE on failure */ -/proc/playsound_client(client/C, sound/soundin, atom/origin, vol = 100, random_freq, vol_cat = VOLUME_SFX, channel = 0, status, list/echo, y_s_offset, x_s_offset) +/proc/playsound_client(client/C, sound/soundin, atom/origin, vol = 100, random_freq, vol_cat = VOLUME_SFX, channel = 0, status, y_s_offset, x_s_offset) if(!istype(C) || !C.soundOutput) return FALSE var/datum/sound_template/template = new() @@ -179,7 +201,6 @@ if(random_freq) template.frequency = GET_RANDOM_FREQ template.status = status - template.echo = echo template.volume_cat = vol_cat var/turf/turf_origin = get_turf(origin) @@ -206,7 +227,7 @@ * * Returns FALSE on failure */ -/proc/playsound_area(area/A, sound/soundin, vol = 100, channel = 0, status, vol_cat = VOLUME_SFX, list/echo, y_s_offset, x_s_offset) +/proc/playsound_area(area/A, sound/soundin, vol = 100, channel = 0, status, vol_cat = VOLUME_SFX, y_s_offset, x_s_offset) if(!isarea(A)) return FALSE @@ -259,13 +280,12 @@ * * soundin - sound datum ( sound() ), sound file ('mysound.ogg'), or string to get a SFX ("male_warcry") * * volume - the initial volume of the sound, 0 is no sound at all, 75 is loud queen screech. * * vol_cat - the category of this sound for client volume purposes: VOLUME_SFX (Sound effects), VOLUME_AMB (Ambience and Soundscapes), VOLUME_ADM (Admin sounds) - * * echo - customizes reverbration settings for this sound * * y_s_offset - vertical sound position offset * * x_s_offset - horizontal sound position offset * * Returns selected channel on success, FALSE on failure */ -/proc/playsound_z(list/z, sound/soundin, volume = 100, vol_cat = VOLUME_SFX, echo, y_s_offset, x_s_offset) +/proc/playsound_z(list/z, sound/soundin, volume = 100, vol_cat = VOLUME_SFX, y_s_offset, x_s_offset) var/datum/sound_template/template = new() if(istype(soundin)) @@ -286,7 +306,6 @@ template.channel = SOUND_CHANNEL_Z template.volume = volume - template.echo = echo template.volume_cat = vol_cat template.x_s_offset = x_s_offset diff --git a/code/modules/mob/living/init_signals.dm b/code/modules/mob/living/init_signals.dm index a2b92007d9..825fa4dcc9 100644 --- a/code/modules/mob/living/init_signals.dm +++ b/code/modules/mob/living/init_signals.dm @@ -26,6 +26,7 @@ if(stat < UNCONSCIOUS) set_stat(UNCONSCIOUS) sound_environment_override = SOUND_ENVIRONMENT_PSYCHOTIC + client?.soundOutput?.update_mob_environment_override() /// Called when [TRAIT_KNOCKEDOUT] is removed from the mob. /mob/living/proc/on_knockedout_trait_loss(datum/source) @@ -33,6 +34,7 @@ if(stat <= UNCONSCIOUS) update_stat() sound_environment_override = SOUND_ENVIRONMENT_NONE + client?.soundOutput?.update_mob_environment_override() /// Called when [TRAIT_IMMOBILIZED] is added to the mob. /mob/living/proc/on_immobilized_trait_gain(datum/source) diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm index 64c8513108..72fd380e58 100644 --- a/code/modules/mob/living/living.dm +++ b/code/modules/mob/living/living.dm @@ -485,12 +485,10 @@ if(CONSCIOUS) if(stat >= UNCONSCIOUS) ADD_TRAIT(src, TRAIT_IMMOBILIZED, TRAIT_KNOCKEDOUT) - sound_environment_override = SOUND_ENVIRONMENT_PSYCHOTIC add_traits(list(/*TRAIT_HANDS_BLOCKED, */ TRAIT_INCAPACITATED, TRAIT_FLOORED), STAT_TRAIT) if(UNCONSCIOUS) if(stat >= UNCONSCIOUS) ADD_TRAIT(src, TRAIT_IMMOBILIZED, TRAIT_KNOCKEDOUT) //adding trait sources should come before removing to avoid unnecessary updates - sound_environment_override = SOUND_ENVIRONMENT_PSYCHOTIC if(DEAD) SEND_SIGNAL(src, COMSIG_MOB_STAT_SET_ALIVE) // remove_from_dead_mob_list() @@ -500,12 +498,10 @@ if(CONSCIOUS) if(. >= UNCONSCIOUS) REMOVE_TRAIT(src, TRAIT_IMMOBILIZED, TRAIT_KNOCKEDOUT) - sound_environment_override = SOUND_ENVIRONMENT_NONE remove_traits(list(/*TRAIT_HANDS_BLOCKED, */ TRAIT_INCAPACITATED, TRAIT_FLOORED, /*TRAIT_CRITICAL_CONDITION*/), STAT_TRAIT) if(UNCONSCIOUS) if(. >= UNCONSCIOUS) REMOVE_TRAIT(src, TRAIT_IMMOBILIZED, TRAIT_KNOCKEDOUT) - sound_environment_override = SOUND_ENVIRONMENT_NONE if(DEAD) SEND_SIGNAL(src, COMSIG_MOB_STAT_SET_DEAD) // REMOVE_TRAIT(src, TRAIT_CRITICAL_CONDITION, STAT_TRAIT) From 72937851765ad5d45c8bd222cdd5a01c82bee26b Mon Sep 17 00:00:00 2001 From: MrDas <62486730+Das15@users.noreply.github.com> Date: Sun, 3 Dec 2023 13:43:30 +0100 Subject: [PATCH 09/16] Fixes ocassional observer minimap desync (#5095) Fixes annoying bug involving jumptocoord hrefs in some deadchat messages, making ghost's minimap desync with the map observer is in. Bugs bad. Removing bugs good.
Screenshots & Videos Put screenshots and videos here with an empty line between the screenshots and the `
` tags.
:cl: MrDas fix: Observer minimap should no longer occasionally show wrong / no map. /:cl: --- code/modules/mob/dead/observer/observer.dm | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/code/modules/mob/dead/observer/observer.dm b/code/modules/mob/dead/observer/observer.dm index 409c88388f..994e1ab09a 100644 --- a/code/modules/mob/dead/observer/observer.dm +++ b/code/modules/mob/dead/observer/observer.dm @@ -758,12 +758,7 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp if(!tx || !ty || !tz) return following = null - spawn(0) - // To stop the ghost flickering. - x = tx - y = ty - z = tz - sleep(15) + forceMove(locate(tx, ty, tz)) /mob/dead/observer/verb/dead_teleport_mob() //Moves the ghost instead of just changing the ghosts's eye -Nodrak set category = "Ghost" From 66785c5ab8ef150fcedad833377ee7aed55dd0ab Mon Sep 17 00:00:00 2001 From: SabreML <57483089+SabreML@users.noreply.github.com> Date: Sat, 6 Jan 2024 14:10:05 +0000 Subject: [PATCH 10/16] Fixes monkey orbiting breaking the camera (#5383) Fixes orbiting a monkey/farwa/stok/etc. locking your camera onto it. This was happening due to `RegisterSignal(src, COMSIG_MOVABLE_MOVED, PROC_REF(observer_move_react))` not being called if the target mob didn't have a HUD, meaning that the client's `eye` wouldn't be set back to their body when they tried moving away. I also moved the `COMSIG_PARENT_QDELETING` one over too so that the same doesn't happen if the target mob is deleted. (The other signals all seem to be HUD related.) Bug!
Screenshots & Videos https://github.com/cmss13-devs/cmss13/assets/57483089/c188db1f-4fb2-4634-baeb-b87ab6e17ae8 https://github.com/cmss13-devs/cmss13/assets/57483089/05348463-49ed-442c-80c3-9c880b4f3d91 https://github.com/cmss13-devs/cmss13/assets/57483089/3f0c8da7-d688-4523-8f63-9f743e699326 https://github.com/cmss13-devs/cmss13/assets/57483089/b39eefa3-3138-437b-bffe-89813ee0a46b
:cl: fix: Fixed observing a monkey/farwa/stok/etc. locking the camera onto it. /:cl: --- code/modules/mob/dead/observer/observer.dm | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/code/modules/mob/dead/observer/observer.dm b/code/modules/mob/dead/observer/observer.dm index 994e1ab09a..256cc07d0b 100644 --- a/code/modules/mob/dead/observer/observer.dm +++ b/code/modules/mob/dead/observer/observer.dm @@ -262,6 +262,9 @@ var/mob/living/carbon/human/human_target = target client.eye = human_target + observe_target_mob = human_target + RegisterSignal(observe_target_mob, COMSIG_PARENT_QDELETING, PROC_REF(clean_observe_target)) + RegisterSignal(src, COMSIG_MOVABLE_MOVED, PROC_REF(observer_move_react)) if(!human_target.hud_used) return @@ -290,19 +293,14 @@ break - observe_target_mob = human_target - RegisterSignal(observe_target_mob, COMSIG_PARENT_QDELETING, PROC_REF(clean_observe_target)) RegisterSignal(observe_target_mob, COMSIG_MOB_GHOSTIZE, PROC_REF(observe_target_ghosting)) RegisterSignal(observe_target_mob, COMSIG_MOB_NEW_MIND, PROC_REF(observe_target_new_mind)) RegisterSignal(observe_target_mob, COMSIG_MOB_LOGIN, PROC_REF(observe_target_login)) - RegisterSignal(src, COMSIG_MOVABLE_MOVED, PROC_REF(observer_move_react)) - if(human_target.client) observe_target_client = human_target.client RegisterSignal(observe_target_client, COMSIG_CLIENT_SCREEN_ADD, PROC_REF(observe_target_screen_add)) RegisterSignal(observe_target_client, COMSIG_CLIENT_SCREEN_REMOVE, PROC_REF(observe_target_screen_remove)) - return /mob/dead/observer/reset_perspective(atom/A) if(observe_target_mob) From 8d7e697b1d46b80f69f252c45683c646f6d0a022 Mon Sep 17 00:00:00 2001 From: SabreML <57483089+SabreML@users.noreply.github.com> Date: Thu, 18 Jan 2024 16:09:56 +0000 Subject: [PATCH 11/16] Makes TGUI transfer over when changing bodies (#5388) Makes any open TGUI windows transfer over when a player's mind is transferred to a new body. *(At least if it's done through `/datum/mind/proc/transfer_to()`)* This is mainly useful for xeno players who want to evolve, since it means they won't need to re-open any interfaces they had open. The changes in `code/controllers/subsystem/minimap.dm` are there so that the tacmap image remains visible to the player after a transfer, since the client changing bodies seems to remove it from their [`screen`](https://www.byond.com/docs/ref/#/client/var/screen) list. (This *could* have hidden side effects of interfaces staying open when they shouldn't, so I'd appreciate this being testmerged for a bit just in case.) QOL addition so that you don't have to manually re-open them yourself.
Screenshots & Videos https://github.com/cmss13-devs/cmss13/assets/57483089/70549c92-915b-4881-95ca-d1625a346f4b
:cl: qol: Made open TGUI windows transfer over when a xeno player evolves. /:cl: --- code/__DEFINES/dcs/signals/atom/mob/signals_mind.dm | 2 ++ code/controllers/subsystem/minimap.dm | 10 ++++++++++ code/datums/mind.dm | 7 ++++--- code/modules/mob/dead/observer/observer.dm | 1 - colonialmarines.dme | 1 + 5 files changed, 17 insertions(+), 4 deletions(-) create mode 100644 code/__DEFINES/dcs/signals/atom/mob/signals_mind.dm diff --git a/code/__DEFINES/dcs/signals/atom/mob/signals_mind.dm b/code/__DEFINES/dcs/signals/atom/mob/signals_mind.dm new file mode 100644 index 0000000000..2cca5fe18c --- /dev/null +++ b/code/__DEFINES/dcs/signals/atom/mob/signals_mind.dm @@ -0,0 +1,2 @@ +///from mind/transfer_to. Sent after the mind has been transferred to a different body: (mob/previous_body) +#define COMSIG_MIND_TRANSFERRED "mind_transferred" diff --git a/code/controllers/subsystem/minimap.dm b/code/controllers/subsystem/minimap.dm index 1c2a6d3e24..a26d024b17 100644 --- a/code/controllers/subsystem/minimap.dm +++ b/code/controllers/subsystem/minimap.dm @@ -717,6 +717,7 @@ SUBSYSTEM_DEF(minimaps) user.client.register_map_obj(map_holder.map) ui = new(user, src, "TacticalMap") ui.open() + RegisterSignal(user.mind, COMSIG_MIND_TRANSFERRED, PROC_REF(on_mind_transferred)) /datum/tacmap/drawing/tgui_interact(mob/user, datum/tgui/ui) var/mob/living/carbon/xenomorph/xeno = user @@ -755,6 +756,7 @@ SUBSYSTEM_DEF(minimaps) tacmap_ready_time = SSminimaps.next_fire + 2 SECONDS addtimer(CALLBACK(src, PROC_REF(on_tacmap_fire), faction), SSminimaps.next_fire - world.time + 1 SECONDS) user.client.register_map_obj(map_holder.map) + RegisterSignal(user.mind, COMSIG_MIND_TRANSFERRED, PROC_REF(on_mind_transferred)) ui = new(user, src, "TacticalMap") ui.open() @@ -835,6 +837,9 @@ SUBSYSTEM_DEF(minimaps) return data +/datum/tacmap/ui_close(mob/user) + UnregisterSignal(user.mind, COMSIG_MIND_TRANSFERRED) + /datum/tacmap/drawing/ui_close(mob/user) . = ..() action_queue_change = 0 @@ -950,6 +955,11 @@ SUBSYSTEM_DEF(minimaps) return UI_INTERACTIVE +// This gets removed when the player changes bodies (i.e. xeno evolution), so re-register it when that happens. +/datum/tacmap/proc/on_mind_transferred(datum/mind/source, mob/previous_body) + SIGNAL_HANDLER + source.current.client.register_map_obj(map_holder.map) + /datum/tacmap_holder var/map_ref var/atom/movable/screen/minimap/map diff --git a/code/datums/mind.dm b/code/datums/mind.dm index fe59699fb9..ebe49e23fc 100644 --- a/code/datums/mind.dm +++ b/code/datums/mind.dm @@ -32,11 +32,11 @@ msg_admin_niche("[key]/[ckey] has tried to transfer to deleted [new_character].") return - SEND_SIGNAL(current.client, COMSIG_CLIENT_MIND_TRANSFER, new_character) - + var/mob/old_current = current if(current) current.mind = null //remove ourself from our old body's mind variable - nanomanager.user_transferred(current, new_character) // transfer active NanoUI instances to new user + SSnano.nanomanager.user_transferred(current, new_character) // transfer active NanoUI instances to new user + SStgui.on_transfer(current, new_character) // and active TGUI instances if(key) if(new_character.key != key) @@ -66,6 +66,7 @@ continue player_entity = setup_player_entity(ckey) + SEND_SIGNAL(src, COMSIG_MIND_TRANSFERRED, old_current) SEND_SIGNAL(new_character, COMSIG_MOB_NEW_MIND, current.client) new_character.refresh_huds(current) //inherit the HUDs from the old body diff --git a/code/modules/mob/dead/observer/observer.dm b/code/modules/mob/dead/observer/observer.dm index 256cc07d0b..c72fbf0542 100644 --- a/code/modules/mob/dead/observer/observer.dm +++ b/code/modules/mob/dead/observer/observer.dm @@ -618,7 +618,6 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp return mind.transfer_to(mind.original, TRUE) - SStgui.on_transfer(src, mind.current) qdel(src) return TRUE diff --git a/colonialmarines.dme b/colonialmarines.dme index 37c2468767..73716cf47f 100644 --- a/colonialmarines.dme +++ b/colonialmarines.dme @@ -136,6 +136,7 @@ #include "code\__DEFINES\dcs\signals\atom\signals_obj.dm" #include "code\__DEFINES\dcs\signals\atom\signals_projectile.dm" #include "code\__DEFINES\dcs\signals\atom\signals_turf.dm" +#include "code\__DEFINES\dcs\signals\atom\mob\signals_mind.dm" #include "code\__DEFINES\dcs\signals\atom\mob\signals_mob.dm" #include "code\__DEFINES\dcs\signals\atom\mob\living\signals_human.dm" #include "code\__DEFINES\dcs\signals\atom\mob\living\signals_living.dm" From 215678c1c15c87e9aeece60ace3033bb2c5788e3 Mon Sep 17 00:00:00 2001 From: SabreML <57483089+SabreML@users.noreply.github.com> Date: Sun, 28 Jan 2024 10:09:58 +0000 Subject: [PATCH 12/16] Makes observers see the marine version of CAS warnings (#5561) Makes the CAS warning messages for observers say 'Dropship' rather than 'Large bird'. It seems a bit weird that observers get the "in-character" xeno version of the messages, rather than the "correct" version.
Screenshots & Videos Put screenshots and videos here with an empty line between the screenshots and the `
` tags.
(no idea what CL category to make this) :cl: spellcheck: Made observers see the marine version of CAS warnings, rather than the xeno one. /:cl: --- code/modules/mob/dead/observer/observer.dm | 1 + 1 file changed, 1 insertion(+) diff --git a/code/modules/mob/dead/observer/observer.dm b/code/modules/mob/dead/observer/observer.dm index c72fbf0542..27370f81e3 100644 --- a/code/modules/mob/dead/observer/observer.dm +++ b/code/modules/mob/dead/observer/observer.dm @@ -32,6 +32,7 @@ plane = GHOST_PLANE layer = ABOVE_FLY_LAYER stat = DEAD + mob_flags = KNOWS_TECHNOLOGY var/adminlarva = FALSE var/ghostvision = TRUE var/can_reenter_corpse From 9cb87a27a4665fca211d94384793b17671748221 Mon Sep 17 00:00:00 2001 From: SabreML <57483089+SabreML@users.noreply.github.com> Date: Wed, 21 Feb 2024 10:11:10 +0000 Subject: [PATCH 13/16] Makes observers able to see the UI of Xeno players (and also action buttons) (#5751) Makes auto-observing work for xenomorphs *and* humans by moving it to `/carbon`, and also makes it show the target's action buttons. I'm pretty confident that this all works correctly, but I would still recommend testmerging it anyway. It's ~~probable~~possible that I missed something somewhere and an observer could get stuck being unable to click anything, or something like that. This makes auto-observing a bit more consistent, more interesting for observers, and could actually help newer players to learn how to play some castes. (Which abilities to use and when, where to target, etc.)
Screenshots & Videos https://github.com/cmss13-devs/cmss13/assets/57483089/54fbb8c6-f9fa-444b-b80c-228b4e6e3480
:cl: add: Added 'observe' functionality to Xenomorphs, allowing observers to view the target's UI. add: Made observing a player also show their action buttons. /:cl: --- code/_onclick/hud/screen_objects.dm | 10 ++- code/modules/mob/dead/observer/observer.dm | 78 +++++++------------ code/modules/mob/living/carbon/carbon.dm | 19 +++++ code/modules/mob/living/carbon/human/human.dm | 23 ++++++ strings/metatips.txt | 1 + 5 files changed, 77 insertions(+), 54 deletions(-) diff --git a/code/_onclick/hud/screen_objects.dm b/code/_onclick/hud/screen_objects.dm index d114aff6b7..18587c0545 100644 --- a/code/_onclick/hud/screen_objects.dm +++ b/code/_onclick/hud/screen_objects.dm @@ -59,9 +59,11 @@ /atom/movable/screen/action_button/attack_ghost(mob/dead/observer/user) return -/atom/movable/screen/action_button/clicked(mob/user) +/atom/movable/screen/action_button/clicked(mob/user, list/mods) if(!user || !source_action) return TRUE + if(source_action.owner != user) + return TRUE if(source_action.can_use_action()) source_action.action_activate() @@ -97,7 +99,7 @@ icon_state = "hide" var/hidden = 0 -/atom/movable/screen/action_button/hide_toggle/clicked(mob/user, mods) +/atom/movable/screen/action_button/hide_toggle/clicked(mob/user, list/mods) user.hud_used.action_buttons_hidden = !user.hud_used.action_buttons_hidden hidden = user.hud_used.action_buttons_hidden if(hidden) @@ -107,7 +109,7 @@ name = "Hide Buttons" icon_state = "hide" user.update_action_buttons() - return 1 + return TRUE /atom/movable/screen/action_button/ghost/minimap/get_button_screen_loc(button_number) return "SOUTH:6,CENTER+1:24" @@ -214,7 +216,7 @@ /atom/movable/screen/zone_sel/robot icon = 'icons/mob/hud/screen1_robot.dmi' -/atom/movable/screen/clicked(mob/user) +/atom/movable/screen/clicked(mob/user, list/mods) if(!user) return TRUE diff --git a/code/modules/mob/dead/observer/observer.dm b/code/modules/mob/dead/observer/observer.dm index 27370f81e3..8c60c97cde 100644 --- a/code/modules/mob/dead/observer/observer.dm +++ b/code/modules/mob/dead/observer/observer.dm @@ -190,37 +190,38 @@ clean_observe_target() /// When the observer target gets a screen, our observer gets a screen minus some game screens we don't want the observer to touch -/mob/dead/observer/proc/observe_target_screen_add(observe_target_mob_client, add_to_screen) +/mob/dead/observer/proc/observe_target_screen_add(observe_target_mob_client, screen_add) SIGNAL_HANDLER - if(!client) - return - - if(istype(add_to_screen, /atom/movable/screen/action_button)) - return - - if(istype(add_to_screen, /atom/movable/screen/fullscreen)) - return + var/static/list/excluded_types = typecacheof(list( + /atom/movable/screen/fullscreen, + /atom/movable/screen/click_catcher, + /atom/movable/screen/escape_menu, + /atom/movable/screen/buildmode, + /obj/effect/detector_blip, + )) - if(istype(add_to_screen, /atom/movable/screen/click_catcher)) + if(!client) return - if(istype(add_to_screen, /atom/movable/screen/escape_menu)) - return + // `screen_add` can sometimes be a list, so it's safest to just handle everything as one. + var/list/stuff_to_add = (islist(screen_add) ? screen_add : list(screen_add)) - if(istype(add_to_screen, /obj/effect/detector_blip)) - return + for(var/item in stuff_to_add) + // Ignore anything that's in `excluded_types`. + if(is_type_in_typecache(item, excluded_types)) + continue - client.add_to_screen(add_to_screen) + client.add_to_screen(screen_add) /// When the observer target loses a screen, our observer loses it as well -/mob/dead/observer/proc/observe_target_screen_remove(observe_target_mob_client, remove_from_screen) +/mob/dead/observer/proc/observe_target_screen_remove(observe_target_mob_client, screen_remove) SIGNAL_HANDLER if(!client) return - client.remove_from_screen(remove_from_screen) + client.remove_from_screen(screen_remove) /// When the observe target ghosts our observer disconnect from their screen updates /mob/dead/observer/proc/observe_target_ghosting(mob/observer_target_mob) @@ -258,48 +259,25 @@ ManualFollow(target) reset_perspective() - if(!ishuman(target) || !client.prefs?.auto_observe) + if(!iscarbon(target) || !client.prefs?.auto_observe) return - var/mob/living/carbon/human/human_target = target - - client.eye = human_target - observe_target_mob = human_target - RegisterSignal(observe_target_mob, COMSIG_PARENT_QDELETING, PROC_REF(clean_observe_target)) - RegisterSignal(src, COMSIG_MOVABLE_MOVED, PROC_REF(observer_move_react)) - - if(!human_target.hud_used) + var/mob/living/carbon/carbon_target = target + if(!carbon_target.hud_used) return client.clear_screen() - LAZYINITLIST(human_target.observers) - human_target.observers |= src - human_target.hud_used.show_hud(human_target.hud_used.hud_version, src) - - var/list/target_contents = human_target.get_contents() - - //Handles any currently open storage containers the target is looking in when we observe - for(var/obj/item/storage/checked_storage in target_contents) - if(!(human_target in checked_storage.content_watchers)) - continue - - client.add_to_screen(checked_storage.closer) - client.add_to_screen(checked_storage.contents) - - if(checked_storage.storage_slots) - client.add_to_screen(checked_storage.boxes) - else - client.add_to_screen(checked_storage.storage_start) - client.add_to_screen(checked_storage.storage_continue) - client.add_to_screen(checked_storage.storage_end) - - break + client.eye = carbon_target + observe_target_mob = carbon_target + carbon_target.auto_observed(src) + RegisterSignal(src, COMSIG_MOVABLE_MOVED, PROC_REF(observer_move_react)) + RegisterSignal(observe_target_mob, COMSIG_PARENT_QDELETING, PROC_REF(clean_observe_target)) RegisterSignal(observe_target_mob, COMSIG_MOB_GHOSTIZE, PROC_REF(observe_target_ghosting)) RegisterSignal(observe_target_mob, COMSIG_MOB_NEW_MIND, PROC_REF(observe_target_new_mind)) RegisterSignal(observe_target_mob, COMSIG_MOB_LOGIN, PROC_REF(observe_target_login)) - if(human_target.client) - observe_target_client = human_target.client + if(observe_target_mob.client) + observe_target_client = observe_target_mob.client RegisterSignal(observe_target_client, COMSIG_CLIENT_SCREEN_ADD, PROC_REF(observe_target_screen_add)) RegisterSignal(observe_target_client, COMSIG_CLIENT_SCREEN_REMOVE, PROC_REF(observe_target_screen_remove)) diff --git a/code/modules/mob/living/carbon/carbon.dm b/code/modules/mob/living/carbon/carbon.dm index b63ce0174a..df09b2d6c6 100644 --- a/code/modules/mob/living/carbon/carbon.dm +++ b/code/modules/mob/living/carbon/carbon.dm @@ -416,6 +416,25 @@
"} show_browser(user, dat, name, "mob[name]") +/** + * Called by [/mob/dead/observer/proc/do_observe] when a carbon mob is observed by a ghost with [/datum/preferences/var/auto_observe] enabled. + * + * Any HUD changes past this point are handled by [/mob/dead/observer/proc/observe_target_screen_add] + * and [/mob/dead/observer/proc/observe_target_screen_remove]. + * + * Override on subtype mobs if they have any extra HUD elements/behaviour. + */ +/mob/living/carbon/proc/auto_observed(mob/dead/observer/observer) + SHOULD_CALL_PARENT(TRUE) + + LAZYINITLIST(observers) + observers |= observer + hud_used.show_hud(hud_used.hud_version, observer) + + for(var/datum/action/action as anything in actions) + // Add the action's button (not the action itself) to the observer's screen. + observer.client.add_to_screen(action.button) + //generates realistic-ish pulse output based on preset levels /mob/living/carbon/proc/get_pulse(method) //method 0 is for hands, 1 is for machines, more accurate var/temp = 0 //see setup.dm:694 diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm index dfa646ef80..350bcec3e8 100644 --- a/code/modules/mob/living/carbon/human/human.dm +++ b/code/modules/mob/living/carbon/human/human.dm @@ -313,6 +313,29 @@
"} show_browser(user, dat, name, "mob[name]") +/** + * Handles any storage containers that the human is looking inside when auto-observed. + */ +/mob/living/carbon/human/auto_observed(mob/dead/observer/observer) + . = ..() + + // If `src` doesn't have an inventory open. + if(!s_active) + return + + // Add the storage interface to `observer`'s screen. + observer.client.add_to_screen(s_active.closer) + observer.client.add_to_screen(s_active.contents) + + // If the storage has a set number of item slots. + if(s_active.storage_slots) + observer.client.add_to_screen(s_active.boxes) + // If the storage instead has a maximum combined item 'weight'. + else + observer.client.add_to_screen(s_active.storage_start) + observer.client.add_to_screen(s_active.storage_continue) + observer.client.add_to_screen(s_active.storage_end) + // called when something steps onto a human // this handles mulebots and vehicles /mob/living/carbon/human/Crossed(atom/movable/AM) diff --git a/strings/metatips.txt b/strings/metatips.txt index 17ffd607a7..e0ede9c626 100644 --- a/strings/metatips.txt +++ b/strings/metatips.txt @@ -12,6 +12,7 @@ As a mentor, you can become the imaginary friend of a new player to teach them! You shouldn't ignore what your allies are up to. Sometimes they can be organizing a flank on the radio, sometimes they can be walking up behind you with a buck-loaded shotgun. Either way, it pays to be alert to what they're doing, as much to as what the enemies are. The Wiki (https://cm-ss13.com/wiki) is a very useful repository of information about the game, such as weapons, equipment, xenomorph castes and their strains. It may not be fully up to date much of the time, but the basics are usually accurate. As an observer, you may see how much remaining hijack time is left in the status panel. +As an observer, you can quickly follow someone by ctrl-clicking on their sprite. You can always AdminHelp with the F1 key to question a member of staff regarding rules or game bugs. As ghost you are given extra tools for spectating the round: you can jump and follow specific players, get notifications about CAS and OB strikes, can see all health bars, and such. You can press ESC key to bring up the game pause menu. It allows you change settings, AdminHelp and MentorHelp, and even access the Web Maps of game by clicking at top right. From 31bc2b412c3fe191deaa30ec040acea38bed6221 Mon Sep 17 00:00:00 2001 From: SabreML <57483089+SabreML@users.noreply.github.com> Date: Sat, 24 Feb 2024 20:35:38 +0000 Subject: [PATCH 14/16] Small auto-observe fixes (#5788) Fixes/tweaks a couple of auto-observe things that I noticed after #5751. Specifically: - Fixes `runtime error: client_screen_add overridden. Use override = TRUE to suppress this warning`/`runtime error: client_screen_remove overridden. Use override = TRUE to suppress this warning`. *This error was consistently thrown when a ghost who's body is being observed re-enters their body. `observe_target_new_mind()` tries to re-register the some signals on the body's new client, but didn't have the `override` argument set.* - Stops 'hidden' actions being added to the screen of observing players. (e.g. the xeno tacmap action if the queen isn't ovied) - Makes any observers transfer over to the new body when a xenomorph evolves/de-evolves. *(I also added `/mob/dead/observer` to the `observers` variable's declaration since it wasn't particularly clear what the list held.)* - Fixes the target player's action buttons disappearing for observers if they reconnect or re-enter their body. *(The actions were being shown to the player in `Login()`>`show_hud()`>`update_action_buttons()` before the observer could re-register signals in `observe_target_login()`.) In order to fix this I renamed the existing `COMSIG_GLOB_MOB_LOGIN`, `COMSIG_CLIENT_MOB_LOGIN`, `COMSIG_MOB_LOGIN` signals, and made `COMSIG_MOB_LOGIN` send a bit earlier in the proc.* Bugfixes :)
Screenshots & Videos Put screenshots and videos here with an empty line between the screenshots and the `
` tags.
:cl: fix: Fixed 'hidden' action buttons being shown to observing players. qol: Made any observers transfer over when a Xenomorph evolves/de-evolves. /:cl: --- code/__DEFINES/dcs/signals/atom/mob/signals_mob.dm | 8 ++++++-- code/__DEFINES/dcs/signals/signals_client.dm | 4 ++-- code/__DEFINES/dcs/signals/signals_global.dm | 6 ++++-- code/controllers/subsystem/ticker.dm | 2 +- code/controllers/subsystem/vote.dm | 4 ++-- code/game/objects/items/devices/radio/headset.dm | 4 ++-- code/modules/client/client_procs.dm | 2 +- code/modules/escape_menu/escape_menu.dm | 2 +- code/modules/mob/dead/observer/observer.dm | 11 +++++++---- code/modules/mob/living/carbon/carbon.dm | 6 +++++- code/modules/mob/living/carbon/xenomorph/Xenomorph.dm | 5 +++++ code/modules/mob/login.dm | 8 +++++--- code/modules/mob/mob_defines.dm | 4 ++-- code/modules/vehicles/van/van.dm | 6 +++--- 14 files changed, 46 insertions(+), 26 deletions(-) diff --git a/code/__DEFINES/dcs/signals/atom/mob/signals_mob.dm b/code/__DEFINES/dcs/signals/atom/mob/signals_mob.dm index 0271cd6334..dd995ba864 100644 --- a/code/__DEFINES/dcs/signals/atom/mob/signals_mob.dm +++ b/code/__DEFINES/dcs/signals/atom/mob/signals_mob.dm @@ -72,9 +72,13 @@ #define COMSIG_MOB_PRE_CLICK "mob_pre_click" #define COMPONENT_INTERRUPT_CLICK (1<<0) -///from base of /mob/Login(): () +/// From base of /mob/Login(), called when a client logs into this mob: () +/// Not to be confused with [COMSIG_MOB_LOGGED_IN] #define COMSIG_MOB_LOGIN "mob_login" -///from base of /mob/Logout(): () +/// From base of /mob/Login(), called after a client logs into this mob: () +/// Not to be confused with [COMSIG_MOB_LOGIN] +#define COMSIG_MOB_LOGGED_IN "mob_logged_in" +/// From base of /mob/Logout(): () #define COMSIG_MOB_LOGOUT "mob_logout" //from /mob/proc/on_deafness_gain() diff --git a/code/__DEFINES/dcs/signals/signals_client.dm b/code/__DEFINES/dcs/signals/signals_client.dm index 6733e07035..e7e74771fc 100644 --- a/code/__DEFINES/dcs/signals/signals_client.dm +++ b/code/__DEFINES/dcs/signals/signals_client.dm @@ -19,8 +19,8 @@ /// Called after one or more verbs are added: (list of verbs added) #define COMSIG_CLIENT_VERB_REMOVED "client_verb_removed" -/// Called after a client logs into a mob: (mob) -#define COMSIG_CLIENT_MOB_LOGIN "client_mob_changed" +/// Called from /mob/Login() after a client logs into a mob: (mob) +#define COMSIG_CLIENT_MOB_LOGGED_IN "client_mob_logged_in" /// Called when something is added to a client's screen : /client/proc/add_to_screen(screen_add) #define COMSIG_CLIENT_SCREEN_ADD "client_screen_add" diff --git a/code/__DEFINES/dcs/signals/signals_global.dm b/code/__DEFINES/dcs/signals/signals_global.dm index 89904c5a1b..825f427695 100644 --- a/code/__DEFINES/dcs/signals/signals_global.dm +++ b/code/__DEFINES/dcs/signals/signals_global.dm @@ -34,9 +34,11 @@ #define COMSIG_GLOB_REMOVE_VOTE_BUTTON "!remove_vote_button" -#define COMSIG_GLOB_CLIENT_LOGIN "!client_login" +/// Called from /client/New() when a client logs in to the game: (client) +#define COMSIG_GLOB_CLIENT_LOGGED_IN "!client_logged_in" -#define COMSIG_GLOB_MOB_LOGIN "!mob_login" +/// Called from /mob/Login() when a client logs into a mob: (mob) +#define COMSIG_GLOB_MOB_LOGGED_IN "!mob_logged_in" ///from /datum/controller/subsystem/ticker/PostSetup #define COMSIG_GLOB_POST_SETUP "!post_setup" diff --git a/code/controllers/subsystem/ticker.dm b/code/controllers/subsystem/ticker.dm index cfe66421c9..d3cb19c40e 100644 --- a/code/controllers/subsystem/ticker.dm +++ b/code/controllers/subsystem/ticker.dm @@ -180,7 +180,7 @@ SUBSYSTEM_DEF(ticker) CHECK_TICK mode.announce() if(mode.taskbar_icon) - RegisterSignal(SSdcs, COMSIG_GLOB_CLIENT_LOGIN, PROC_REF(handle_mode_icon)) + RegisterSignal(SSdcs, COMSIG_GLOB_CLIENT_LOGGED_IN, PROC_REF(handle_mode_icon)) set_clients_taskbar_icon(mode.taskbar_icon) if(GLOB.perf_flags & PERF_TOGGLE_LAZYSS) diff --git a/code/controllers/subsystem/vote.dm b/code/controllers/subsystem/vote.dm index a56e10636a..34350613ce 100644 --- a/code/controllers/subsystem/vote.dm +++ b/code/controllers/subsystem/vote.dm @@ -59,7 +59,7 @@ SUBSYSTEM_DEF(vote) voting.Cut() remove_action_buttons() - UnregisterSignal(SSdcs, COMSIG_GLOB_CLIENT_LOGIN) + UnregisterSignal(SSdcs, COMSIG_GLOB_CLIENT_LOGGED_IN) for(var/c in GLOB.player_list) update_static_data(c) @@ -370,7 +370,7 @@ SUBSYSTEM_DEF(vote) if(send_clients_vote) C.mob.vote() - RegisterSignal(SSdcs, COMSIG_GLOB_CLIENT_LOGIN, PROC_REF(handle_client_joining)) + RegisterSignal(SSdcs, COMSIG_GLOB_CLIENT_LOGGED_IN, PROC_REF(handle_client_joining)) SStgui.update_uis(src) return TRUE return FALSE diff --git a/code/game/objects/items/devices/radio/headset.dm b/code/game/objects/items/devices/radio/headset.dm index e6daba29ae..f00ba138ef 100644 --- a/code/game/objects/items/devices/radio/headset.dm +++ b/code/game/objects/items/devices/radio/headset.dm @@ -244,7 +244,7 @@ ), PROC_REF(turn_on)) wearer = user RegisterSignal(user, COMSIG_MOB_STAT_SET_ALIVE, PROC_REF(update_minimap_icon)) - RegisterSignal(user, COMSIG_MOB_LOGIN, PROC_REF(add_hud_tracker)) + RegisterSignal(user, COMSIG_MOB_LOGGED_IN, PROC_REF(add_hud_tracker)) RegisterSignal(user, COMSIG_MOB_DEATH, PROC_REF(update_minimap_icon)) RegisterSignal(user, COMSIG_HUMAN_SET_UNDEFIBBABLE, PROC_REF(update_minimap_icon)) if(headset_hud_on) @@ -261,7 +261,7 @@ UnregisterSignal(user, list( COMSIG_LIVING_REJUVENATED, COMSIG_HUMAN_REVIVED, - COMSIG_MOB_LOGIN, + COMSIG_MOB_LOGGED_IN, COMSIG_MOB_DEATH, COMSIG_HUMAN_SET_UNDEFIBBABLE, COMSIG_MOB_STAT_SET_ALIVE diff --git a/code/modules/client/client_procs.dm b/code/modules/client/client_procs.dm index d69833ec5c..01ab3d04a5 100644 --- a/code/modules/client/client_procs.dm +++ b/code/modules/client/client_procs.dm @@ -464,7 +464,7 @@ GLOBAL_LIST_INIT(whitelisted_client_procs, list( view = world_view_size - SEND_GLOBAL_SIGNAL(COMSIG_GLOB_CLIENT_LOGIN, src) + SEND_GLOBAL_SIGNAL(COMSIG_GLOB_CLIENT_LOGGED_IN, src) ////////////// //DISCONNECT// diff --git a/code/modules/escape_menu/escape_menu.dm b/code/modules/escape_menu/escape_menu.dm index c31234678b..b61bbd5b3f 100644 --- a/code/modules/escape_menu/escape_menu.dm +++ b/code/modules/escape_menu/escape_menu.dm @@ -49,7 +49,7 @@ GLOBAL_LIST_EMPTY(escape_menus) show_page() RegisterSignal(client, COMSIG_PARENT_QDELETING, PROC_REF(on_client_qdel)) - RegisterSignal(client, COMSIG_CLIENT_MOB_LOGIN, PROC_REF(on_client_mob_login)) + RegisterSignal(client, COMSIG_CLIENT_MOB_LOGGED_IN, PROC_REF(on_client_mob_login)) if (!isnull(ckey)) GLOB.escape_menus[ckey] = src diff --git a/code/modules/mob/dead/observer/observer.dm b/code/modules/mob/dead/observer/observer.dm index 8c60c97cde..cf225caadc 100644 --- a/code/modules/mob/dead/observer/observer.dm +++ b/code/modules/mob/dead/observer/observer.dm @@ -238,8 +238,9 @@ if(observe_target_client != new_client) observe_target_client = new_client - RegisterSignal(observe_target_client, COMSIG_CLIENT_SCREEN_ADD, PROC_REF(observe_target_screen_add)) - RegisterSignal(observe_target_client, COMSIG_CLIENT_SCREEN_REMOVE, PROC_REF(observe_target_screen_remove)) + // Override the signal from any previous targets. + RegisterSignal(observe_target_client, COMSIG_CLIENT_SCREEN_ADD, PROC_REF(observe_target_screen_add), TRUE) + RegisterSignal(observe_target_client, COMSIG_CLIENT_SCREEN_REMOVE, PROC_REF(observe_target_screen_remove), TRUE) /// When the observe target logs in our observer connect to the new client /mob/dead/observer/proc/observe_target_login(mob/living/new_character) @@ -248,8 +249,9 @@ if(observe_target_client != new_character.client) observe_target_client = new_character.client - RegisterSignal(observe_target_client, COMSIG_CLIENT_SCREEN_ADD, PROC_REF(observe_target_screen_add)) - RegisterSignal(observe_target_client, COMSIG_CLIENT_SCREEN_REMOVE, PROC_REF(observe_target_screen_remove)) + // Override the signal from any previous targets. + RegisterSignal(observe_target_client, COMSIG_CLIENT_SCREEN_ADD, PROC_REF(observe_target_screen_add), TRUE) + RegisterSignal(observe_target_client, COMSIG_CLIENT_SCREEN_REMOVE, PROC_REF(observe_target_screen_remove), TRUE) ///makes the ghost see the target hud and sets the eye at the target. /mob/dead/observer/proc/do_observe(atom/movable/target) @@ -268,6 +270,7 @@ client.clear_screen() client.eye = carbon_target observe_target_mob = carbon_target + carbon_target.auto_observed(src) RegisterSignal(src, COMSIG_MOVABLE_MOVED, PROC_REF(observer_move_react)) diff --git a/code/modules/mob/living/carbon/carbon.dm b/code/modules/mob/living/carbon/carbon.dm index df09b2d6c6..4ea2f35aa6 100644 --- a/code/modules/mob/living/carbon/carbon.dm +++ b/code/modules/mob/living/carbon/carbon.dm @@ -431,8 +431,12 @@ observers |= observer hud_used.show_hud(hud_used.hud_version, observer) + // Add the player's action buttons (not the actions themselves) to the observer's screen. for(var/datum/action/action as anything in actions) - // Add the action's button (not the action itself) to the observer's screen. + // Skip any hidden ones (of course). + if(action.hidden || action.player_hidden) + continue + observer.client.add_to_screen(action.button) //generates realistic-ish pulse output based on preset levels diff --git a/code/modules/mob/living/carbon/xenomorph/Xenomorph.dm b/code/modules/mob/living/carbon/xenomorph/Xenomorph.dm index a89e2d0444..f27616508d 100644 --- a/code/modules/mob/living/carbon/xenomorph/Xenomorph.dm +++ b/code/modules/mob/living/carbon/xenomorph/Xenomorph.dm @@ -797,6 +797,11 @@ var/datum/mob_hud/MH = huds[MOB_HUD_XENO_INFECTION] MH.add_hud_to(src, src) +// Transfer any observing players over to the xeno's new body (`target`) on evolve/de-evolve. +/mob/living/carbon/xenomorph/transfer_observers_to(atom/target) + for(var/mob/dead/observer/observer as anything in observers) + observer.clean_observe_target() + observer.do_observe(target) /mob/living/carbon/xenomorph/check_improved_pointing() //xeno leaders get a big arrow and less cooldown diff --git a/code/modules/mob/login.dm b/code/modules/mob/login.dm index 775e69dc0b..38157a0673 100644 --- a/code/modules/mob/login.dm +++ b/code/modules/mob/login.dm @@ -18,6 +18,8 @@ update_Login_details() + SEND_SIGNAL(src, COMSIG_MOB_LOGIN) + client.images = null client.screen = null //remove hud items just in case if(!hud_used) @@ -58,6 +60,6 @@ client.init_verbs() - SEND_GLOBAL_SIGNAL(COMSIG_GLOB_MOB_LOGIN, src) - SEND_SIGNAL(client, COMSIG_CLIENT_MOB_LOGIN, src) - SEND_SIGNAL(src, COMSIG_MOB_LOGIN) + SEND_GLOBAL_SIGNAL(COMSIG_GLOB_MOB_LOGGED_IN, src) + SEND_SIGNAL(client, COMSIG_CLIENT_MOB_LOGGED_IN, src) + SEND_SIGNAL(src, COMSIG_MOB_LOGGED_IN) diff --git a/code/modules/mob/mob_defines.dm b/code/modules/mob/mob_defines.dm index f0e5bc48a8..e2f40506b2 100644 --- a/code/modules/mob/mob_defines.dm +++ b/code/modules/mob/mob_defines.dm @@ -28,7 +28,8 @@ I'll make some notes on where certain variable defines should probably go. Changing this around would probably require a good look-over the pre-existing code. */ - var/list/observers //The list of people observing this mob. + /// The list of people observing this mob. + var/list/mob/dead/observer/observers var/zone_selected = "chest" var/use_me = 1 //Allows all mobs to use the me verb by default, will have to manually specify they cannot @@ -433,4 +434,3 @@ return src.regenerate_icons() - diff --git a/code/modules/vehicles/van/van.dm b/code/modules/vehicles/van/van.dm index 0b99d682c0..3dcc603445 100644 --- a/code/modules/vehicles/van/van.dm +++ b/code/modules/vehicles/van/van.dm @@ -82,7 +82,7 @@ icon_state = null - RegisterSignal(SSdcs, COMSIG_GLOB_MOB_LOGIN, PROC_REF(add_default_image)) + RegisterSignal(SSdcs, COMSIG_GLOB_MOB_LOGGED_IN, PROC_REF(add_default_image)) for(var/I in GLOB.player_list) add_default_image(SSdcs, I) @@ -124,7 +124,7 @@ mobs_under += L RegisterSignal(L, COMSIG_PARENT_QDELETING, PROC_REF(remove_under_van)) - RegisterSignal(L, COMSIG_MOB_LOGIN, PROC_REF(add_client)) + RegisterSignal(L, COMSIG_MOB_LOGGED_IN, PROC_REF(add_client)) RegisterSignal(L, COMSIG_MOVABLE_MOVED, PROC_REF(check_under_van)) if(L.client) @@ -140,7 +140,7 @@ UnregisterSignal(L, list( COMSIG_PARENT_QDELETING, - COMSIG_MOB_LOGIN, + COMSIG_MOB_LOGGED_IN, COMSIG_MOVABLE_MOVED, )) From 4dcc6841d46f4f61379c44ccd6632e31c4eddd9e Mon Sep 17 00:00:00 2001 From: BeagleGaming1 <56142455+BeagleGaming1@users.noreply.github.com> Date: Sat, 30 Dec 2023 03:22:30 -0500 Subject: [PATCH 15/16] Adds a verb to hide action buttons (#5304) Adds a verb on /client to show/hide action buttons Makes it a new variable, as var/hidden also prevents the action from being used ![image](https://github.com/cmss13-devs/cmss13/assets/56142455/1d78441c-5085-4165-a2b7-f7c3e9f7e2c3) :cl: qol: Adds the ability to hide your action buttons /:cl: --- code/datums/action.dm | 8 ++++---- code/modules/client/client_procs.dm | 29 +++++++++++++++++++++++++++++ 2 files changed, 33 insertions(+), 4 deletions(-) diff --git a/code/datums/action.dm b/code/datums/action.dm index 0510a43415..3a597ad262 100644 --- a/code/datums/action.dm +++ b/code/datums/action.dm @@ -11,9 +11,9 @@ var/cost = 0 // By default an action has no cost -> will be utilized by skill actions/xeno actions var/action_flags = 0 // Check out __game.dm for flags /// Whether the action is hidden from its owner - /// Useful for when you want to preserve action state while preventing - /// a mob from using said action - var/hidden = FALSE + var/hidden = FALSE //Preserve action state while preventing mob from using action + ///Hide the action from the owner without preventing them from using it (incase of keybind listen_signal) + var/player_hidden = FALSE var/unique = TRUE /// A signal on the mob that will cause the action to activate var/listen_signal @@ -227,7 +227,7 @@ var/atom/movable/screen/action_button/B = A.button if(reload_screen) client.add_to_screen(B) - if(A.hidden) + if(A.hidden || A.player_hidden) B.screen_loc = null continue button_number++ diff --git a/code/modules/client/client_procs.dm b/code/modules/client/client_procs.dm index 01ab3d04a5..8456b92463 100644 --- a/code/modules/client/client_procs.dm +++ b/code/modules/client/client_procs.dm @@ -820,3 +820,32 @@ GLOBAL_LIST_INIT(whitelisted_client_procs, list( xeno_prefix = "XX" if(!xeno_postfix || xeno_name_ban) xeno_postfix = "" + +/client/verb/action_hide_menu() + set name = "Show/Hide Actions" + set category = "IC" + + var/mob/user = usr + + var/list/actions_list = list() + for(var/datum/action/action as anything in user.actions) + var/action_name = action.name + if(action.player_hidden) + action_name += " (Hidden)" + actions_list[action_name] += action + + if(!LAZYLEN(actions_list)) + to_chat(user, SPAN_WARNING("You have no actions available.")) + return + + var/selected_action_name = tgui_input_list(user, "Show or hide selected action", "Show/Hide Actions", actions_list, 30 SECONDS) + if(!selected_action_name) + to_chat(user, SPAN_WARNING("You did not select an action.")) + return + + var/datum/action/selected_action = actions_list[selected_action_name] + selected_action.player_hidden = !selected_action.player_hidden + user.update_action_buttons() + + if(!selected_action.player_hidden && selected_action.hidden) //Inform the player that even if they are unhiding it, itll still not be visible + to_chat(user, SPAN_NOTICE("[selected_action] is forcefully hidden, bypassing player unhiding.")) From 4bddd66614bafa3c9f45711b0b2ed5ca7caba933 Mon Sep 17 00:00:00 2001 From: Doubleumc Date: Tue, 6 Aug 2024 03:26:22 -0400 Subject: [PATCH 16/16] Update mind.dm --- code/datums/mind.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/datums/mind.dm b/code/datums/mind.dm index ebe49e23fc..ae6304dbcd 100644 --- a/code/datums/mind.dm +++ b/code/datums/mind.dm @@ -35,7 +35,7 @@ var/mob/old_current = current if(current) current.mind = null //remove ourself from our old body's mind variable - SSnano.nanomanager.user_transferred(current, new_character) // transfer active NanoUI instances to new user + nanomanager.user_transferred(current, new_character) // transfer active NanoUI instances to new user SStgui.on_transfer(current, new_character) // and active TGUI instances if(key)