From 7d92c3e69f2347fe4616600698f63e6d23280282 Mon Sep 17 00:00:00 2001 From: VMSolidus Date: Fri, 9 Aug 2024 07:13:13 -0400 Subject: [PATCH] Soft-Refactor Geiger Counters (#615) # Description This refactors Geiger Counters so that their behavior of "Only making sound to a person holding them" is no longer hardcoded. The GeigerCounterComponent now can define how loud it ticks, how far away people can hear the ticks, and whether it plays only for the person holding it or for anyone nearby. This PR partially fulfills one of the "Nice To Have" features requested for https://github.com/Simple-Station/Einstein-Engines/pull/341 by making it possible to create stationary radiation alarm objects. It also serves as a substantial quality of life improvement for Engineering and Science crew, since it's now possible to place an active Geiger counter in the artifact lab, and then be able to audibly hear if the lab becomes radioactive due to an artifact.

Media

https://github.com/user-attachments/assets/74122135-7345-4995-bb0e-d1216e1d53b6 https://github.com/user-attachments/assets/de79db6f-e1c1-471f-88b5-0a47ff4bfa16

# Changelog :cl: - add: Geiger Counters other than ones installed in Hardsuits now generate an audible sound when active and exposed to radiation. - add: Wall mounted geiger counters have been added to the game. --------- Signed-off-by: VMSolidus --- .../Radiation/Systems/GeigerSystem.cs | 28 +++++----- .../Radiation/Components/GeigerComponent.cs | 19 +++++-- .../OuterClothing/base_clothingouter.yml | 3 ++ .../Structures/Wallmounts/radalarm.yml | 51 ++++++++++++++++++ .../Wallmounts/radalarm.rsi/geiger_base.png | Bin 0 -> 1283 bytes .../Wallmounts/radalarm.rsi/geiger_on_ext.png | Bin 0 -> 375 bytes .../radalarm.rsi/geiger_on_high.png | Bin 0 -> 375 bytes .../radalarm.rsi/geiger_on_idle.png | Bin 0 -> 326 bytes .../Wallmounts/radalarm.rsi/geiger_on_low.png | Bin 0 -> 363 bytes .../Wallmounts/radalarm.rsi/geiger_on_med.png | Bin 0 -> 368 bytes .../Wallmounts/radalarm.rsi/meta.json | 35 ++++++++++++ 11 files changed, 117 insertions(+), 19 deletions(-) create mode 100644 Resources/Prototypes/Entities/Structures/Wallmounts/radalarm.yml create mode 100644 Resources/Textures/Structures/Wallmounts/radalarm.rsi/geiger_base.png create mode 100644 Resources/Textures/Structures/Wallmounts/radalarm.rsi/geiger_on_ext.png create mode 100644 Resources/Textures/Structures/Wallmounts/radalarm.rsi/geiger_on_high.png create mode 100644 Resources/Textures/Structures/Wallmounts/radalarm.rsi/geiger_on_idle.png create mode 100644 Resources/Textures/Structures/Wallmounts/radalarm.rsi/geiger_on_low.png create mode 100644 Resources/Textures/Structures/Wallmounts/radalarm.rsi/geiger_on_med.png create mode 100644 Resources/Textures/Structures/Wallmounts/radalarm.rsi/meta.json diff --git a/Content.Server/Radiation/Systems/GeigerSystem.cs b/Content.Server/Radiation/Systems/GeigerSystem.cs index f889336a068..06e5911cb7c 100644 --- a/Content.Server/Radiation/Systems/GeigerSystem.cs +++ b/Content.Server/Radiation/Systems/GeigerSystem.cs @@ -6,8 +6,8 @@ using Content.Shared.Radiation.Components; using Content.Shared.Radiation.Systems; using Robust.Server.Audio; -using Robust.Server.GameObjects; using Robust.Server.Player; +using Robust.Shared.Player; namespace Content.Server.Radiation.Systems; @@ -152,19 +152,19 @@ private void UpdateSound(EntityUid uid, GeigerComponent? component = null) component.Stream = _audio.Stop(component.Stream); - if (!component.Sounds.TryGetValue(component.DangerLevel, out var sounds)) - return; - - if (component.User == null) - return; - - if (!_player.TryGetSessionByEntity(component.User.Value, out var session)) - return; - - var sound = _audio.GetSound(sounds); - var param = sounds.Params.WithLoop(true).WithVolume(-4f); - - component.Stream = _audio.PlayGlobal(sound, session, param)?.Entity; + if (component.Sounds.TryGetValue(component.DangerLevel, out var sounds)) + { + var sound = _audio.GetSound(sounds); + + if (component.LocalSoundOnly + && component.User is not null + && _player.TryGetSessionByEntity(component.User.Value, out var session)) + { + component.Stream = _audio.PlayGlobal(sound, session, component.AudioParameters)?.Entity; + return; + } + component.Stream = _audio.PlayEntity(sound, Filter.Pvs(uid), uid, true, component.AudioParameters)?.Entity; + } } public static GeigerDangerLevel RadsToLevel(float rads) diff --git a/Content.Shared/Radiation/Components/GeigerComponent.cs b/Content.Shared/Radiation/Components/GeigerComponent.cs index 71edb70b37c..710d74d9b38 100644 --- a/Content.Shared/Radiation/Components/GeigerComponent.cs +++ b/Content.Shared/Radiation/Components/GeigerComponent.cs @@ -29,14 +29,12 @@ public sealed partial class GeigerComponent : Component /// /// Should it shows examine message with current radiation level? /// - [ViewVariables(VVAccess.ReadWrite)] [DataField] public bool ShowExamine; /// /// Should it shows item control when equipped by player? /// - [ViewVariables(VVAccess.ReadWrite)] [DataField] public bool ShowControl; @@ -55,7 +53,7 @@ public sealed partial class GeigerComponent : Component /// /// Current radiation level in rad per second. /// - [ViewVariables(VVAccess.ReadOnly), AutoNetworkedField] + [DataField, AutoNetworkedField] public float CurrentRadiation; /// @@ -66,8 +64,6 @@ public sealed partial class GeigerComponent : Component /// /// Current player that equipped geiger counter. - /// Because sound is annoying, geiger counter clicks will play - /// only for player that equipped it. /// [ViewVariables(VVAccess.ReadOnly), AutoNetworkedField] public EntityUid? User; @@ -83,6 +79,19 @@ public sealed partial class GeigerComponent : Component /// Played only for current user. /// public EntityUid? Stream; + + /// + /// Controls whether the geiger counter plays only for the local player, or plays for everyone nearby. + /// Useful for things like hardsuits with integrated geigers. Alternatively, to create stationary radiation alarm objects. + /// + [DataField] + public bool LocalSoundOnly = false; + + /// + /// Used for all geiger counter audio controls, allowing entities to override default audio parameters. + /// + [DataField] + public AudioParams AudioParameters; } [Serializable, NetSerializable] diff --git a/Resources/Prototypes/Entities/Clothing/OuterClothing/base_clothingouter.yml b/Resources/Prototypes/Entities/Clothing/OuterClothing/base_clothingouter.yml index d6a2cd446be..358f91d2971 100644 --- a/Resources/Prototypes/Entities/Clothing/OuterClothing/base_clothingouter.yml +++ b/Resources/Prototypes/Entities/Clothing/OuterClothing/base_clothingouter.yml @@ -142,6 +142,9 @@ - type: Clothing equipDelay: 2.5 # Hardsuits are heavy and take a while to put on/off. unequipDelay: 2.5 + - type: Geiger + attachedToSuit: true + localSoundOnly: true - type: StaminaDamageResistance coefficient: 0.75 # 25% diff --git a/Resources/Prototypes/Entities/Structures/Wallmounts/radalarm.yml b/Resources/Prototypes/Entities/Structures/Wallmounts/radalarm.yml new file mode 100644 index 00000000000..44bbe3e6170 --- /dev/null +++ b/Resources/Prototypes/Entities/Structures/Wallmounts/radalarm.yml @@ -0,0 +1,51 @@ +- type: entity + id: GeigerCounterWallMount + name: wall-mounted Geiger counter + description: A stationary device that emits a warning tone when it detects radiation pulses. + placement: + mode: SnapgridCenter + snap: + - Wallmount + components: + - type: InteractionOutline + - type: Clickable + - type: Rotatable + rotateWhileAnchored: false + rotateWhilePulling: true + - type: WallMount + - type: Transform + noRot: false + anchored: true + - type: Sprite + noRot: true + drawdepth: WallMountedItems + sprite: Structures/Wallmounts/radalarm.rsi + layers: + - state: geiger_base + - state: geiger_on_idle + map: ["enum.GeigerLayers.Screen"] + shader: unshaded + visible: false + - type: Geiger + showControl: true + showExamine: true + localSoundOnly: false + audioParameters: + volume: -4 + maxDistance: 10 + rolloffFactor: 4 + - type: Appearance + - type: GenericVisualizer + visuals: + enum.GeigerVisuals.IsEnabled: + GeigerLayers.Screen: + True: { visible: True } + False: { visible: False } + enum.GeigerVisuals.DangerLevel: + GeigerLayers.Screen: + None: {state: geiger_on_idle} + Low: {state: geiger_on_low} + Med: {state: geiger_on_med} + High: {state: geiger_on_high} + Extreme: {state: geiger_on_ext} + diff --git a/Resources/Textures/Structures/Wallmounts/radalarm.rsi/geiger_base.png b/Resources/Textures/Structures/Wallmounts/radalarm.rsi/geiger_base.png new file mode 100644 index 0000000000000000000000000000000000000000..778c427735012720fbd093e0a7f54b9adb5b5dcb GIT binary patch literal 1283 zcmV+e1^oJnP)Px#1ZP1_K>z@;j|==^1poj532;bRa{vGi!~g&e!~vBn4jTXf1ei%gK~#8N?VC+# z6fqRXr&cSaqWD?6t)*JE2zpUb#DgLhKMo?O^ybN1p$8GygRlx-R>Xs_7x5&5hzjDt z4+L=!A{9I-i1nkTe$-ZrRV-3vsr%35)tF6YGP|?0vzi|~l1aBS$;-=|yq8_aVzF5M zXKHxqNhXt-)ae3=Hzx9}m3orr8fTS8Qwg6KOt$g=a8F#c!aQnthlTd=_ z1XXMP!^a_3mdgpQT(z!f=V|iHKo)?(%2F;c@KOeEiqUHj`+y*O00Mgf>;sCi02+MW zf>Ql2-ZKCtEQI1vn8Vm~zJm}zqAjc-ky^6=K*2n@X zfoK8PRbJ?8nJUQwyyB3Tub#!j0>S`;7R#V`SwK}N05eHa3|?_fRVY9Q%p7kWS%wN|%+zQ5a5bql8YVO2tzFVm4M5nXo!!3YGv& zzf?RGK(ntB5qB*{;{*vf-!S}+kq_{5Dj2-UYbZ?QwO=g03eY(f5pqaTLf&6SPK&G3 z|+1`002ovPDHLkV1lQfLi_*# literal 0 HcmV?d00001 diff --git a/Resources/Textures/Structures/Wallmounts/radalarm.rsi/geiger_on_ext.png b/Resources/Textures/Structures/Wallmounts/radalarm.rsi/geiger_on_ext.png new file mode 100644 index 0000000000000000000000000000000000000000..7b7f3f4e767822a0454026ece50fdf8aa63daccc GIT binary patch literal 375 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I3?%1nZ+ru!7>k44ofy`glX(f`u%tWsIx;Y9 z?C1WI$O`0(2Ka=yo-qubspz*wJ?a07p8pOJ|MxEk${c^8m;$8OOM?7@|APU8lsB^* zP>8d@BeIx*f$sJOGwXs7uI@pgKH7q$8)q86K*i9cof7b<0cat^NPii2}sJdh|QQQw?qxU9i%sA7!F7P~0;<4II9;|murgH5Pcbli+x?k44ofy`glX(f`u%tWsIx;Y9 z?C1WI$O`0(2Ka=yo-qubspz*wJ?a07p8pOJ|MxEk${c^8m;$8OOM?7@|APU8lsB^* zP>8d@BeIx*f$sJOGwXs7uI@pgKH7q$8)q86K*i9cof7b<0cat^NPii2}sJdh|QQQw?qxU9i%sA7!F7P~0;<4II9;|murgH5Pcbli+x?k44ofy`glX(f`u%tWsIx;Y9 z?C1WI$O_~O1^9%x+S`|Sc~6vEk-F}i@#+7YfWj|k1jGO-wvr&f;Qt`NuzCNI{Xh}U z0*}aI1_r((Aj~*bn@<`jxZ2ajF(ktM?X=r`4GJ6%d;k5{Hy4xSoVh*9^qlvtXMz)@ z)c6)P-RI?228@qvIwE(XyR3@?Nurq^Y~6x>W|$yl@f_MtwG zd)f+}n#D>H@zbP4no78RnGQW?=_|GO45;UJFLPAa3SczQ=qO~I8t?n@t65k9(Af;0 Lu6{1-oD!Mk44ofy`glX(f`u%tWsIx;Y9 z?C1WI$O_~O1^9%xcKM4hij)2SKj*;`&i@}b0fpa6e^LQbY$ZW{!T&*kVe|ea`+*{y z1s;*b3=DinK$vl=HlH+5@Pem{V@QPi+i4fYniV)4m_ProuUw&1I>|Xx-}=t;{(1YYCyj+c)I$ztaD0e0swKOgqZ*U literal 0 HcmV?d00001 diff --git a/Resources/Textures/Structures/Wallmounts/radalarm.rsi/geiger_on_med.png b/Resources/Textures/Structures/Wallmounts/radalarm.rsi/geiger_on_med.png new file mode 100644 index 0000000000000000000000000000000000000000..33d354a6a6ecd6f9b410c95d9aa80557712694e8 GIT binary patch literal 368 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I3?%1nZ+ru!7>k44ofy`glX(f`u%tWsIx;Y9 z?C1WI$O_~O1^9%xPBP(H=Fb27kpHGeqyK07fx=#U>Y9KQTS<^#@P80s*t~zqexL|v zfk$L90|Va?5N4dJ%_j{Myz1%V7!u+BcABG5vjUH+r_%TRMT$$fR9zKv#pmwnJtjHt zBez$FTg->@rU?^2XRcywa9~ilsx!60z&Yq_Q27KY2XFRgJl|HZxI1dGn$DZb7tqH$ zzov!zYgm2&YxB+vtY7E4OMJA73}X!l>j~)$b=;nC&H90;a_FPyk|jG1uu6*WP}r>K zVc+^CaJ#dg`o4EQNM|}nc>gTe~DWM4f D7!iXk literal 0 HcmV?d00001 diff --git a/Resources/Textures/Structures/Wallmounts/radalarm.rsi/meta.json b/Resources/Textures/Structures/Wallmounts/radalarm.rsi/meta.json new file mode 100644 index 00000000000..2ef22994bc0 --- /dev/null +++ b/Resources/Textures/Structures/Wallmounts/radalarm.rsi/meta.json @@ -0,0 +1,35 @@ +{ + "version": 1, + "size": { + "x": 32, + "y": 32 + }, + "license": "CC-BY-SA-3.0", + "copyright": "Made by @dootythefrooty (Discord)", + "states": [ + { + "name": "geiger_base", + "directions": 4 + }, + { + "name": "geiger_on_idle", + "directions": 4 + }, + { + "name": "geiger_on_low", + "directions": 4 + }, + { + "name": "geiger_on_med", + "directions": 4 + }, + { + "name": "geiger_on_high", + "directions": 4 + }, + { + "name": "geiger_on_ext", + "directions": 4 + } + ] +}