diff --git a/Content.Client/Radiation/Systems/GeigerSystem.cs b/Content.Client/Radiation/Systems/GeigerSystem.cs new file mode 100644 index 0000000000..600c5860fb --- /dev/null +++ b/Content.Client/Radiation/Systems/GeigerSystem.cs @@ -0,0 +1,95 @@ +using Content.Client.Items; +using Content.Client.Radiation.UI; +using Content.Shared.Radiation.Components; +using Content.Shared.Radiation.Systems; +using Robust.Client.GameObjects; +using Robust.Client.Player; +using Robust.Shared.GameStates; +using Robust.Shared.Player; + +namespace Content.Client.Radiation.Systems; + +public sealed class GeigerSystem : SharedGeigerSystem +{ + [Dependency] private readonly AudioSystem _audio = default!; + [Dependency] private readonly IPlayerManager _playerManager = default!; + + public override void Initialize() + { + base.Initialize(); + SubscribeLocalEvent(OnAttachedEntityChanged); + SubscribeLocalEvent(OnHandleState); + SubscribeLocalEvent(OnGetStatusMessage); + } + + private void OnHandleState(EntityUid uid, GeigerComponent component, ref ComponentHandleState args) + { + if (args.Current is not GeigerComponentState state) + return; + + UpdateGeigerSound(uid, state.IsEnabled, state.User, state.DangerLevel, false, component); + + component.CurrentRadiation = state.CurrentRadiation; + component.DangerLevel = state.DangerLevel; + component.IsEnabled = state.IsEnabled; + component.User = state.User; + component.UiUpdateNeeded = true; + } + + private void OnGetStatusMessage(EntityUid uid, GeigerComponent component, ItemStatusCollectMessage args) + { + if (!component.ShowControl) + return; + + args.Controls.Add(new GeigerItemControl(component)); + } + + private void OnAttachedEntityChanged(PlayerAttachSysMessage ev) + { + // need to go for each component known to client + // and update their geiger sound + foreach (var geiger in EntityQuery()) + { + ForceUpdateGeigerSound(geiger.Owner, geiger); + } + } + + private void ForceUpdateGeigerSound(EntityUid uid, GeigerComponent? component = null) + { + if (!Resolve(uid, ref component)) + return; + UpdateGeigerSound(uid, component.IsEnabled, component.User, component.DangerLevel, true, component); + } + + private void UpdateGeigerSound(EntityUid uid, bool isEnabled, EntityUid? user, + GeigerDangerLevel dangerLevel, bool force = false, GeigerComponent? component = null) + { + if (!Resolve(uid, ref component)) + return; + + // check if we even need to update sound + if (!force && isEnabled == component.IsEnabled && + user == component.User && dangerLevel == component.DangerLevel) + { + return; + } + + component.Stream?.Stop(); + + if (!isEnabled || user == null) + return; + if (!component.Sounds.TryGetValue(dangerLevel, out var sounds)) + return; + + // check that that local player controls entity that is holding geiger counter + if (_playerManager.LocalPlayer == null) + return; + var attachedEnt = _playerManager.LocalPlayer.Session.AttachedEntity; + if (attachedEnt != user) + return; + + var sound = _audio.GetSound(sounds); + var param = sounds.Params.WithLoop(true).WithVolume(-4f); + component.Stream = _audio.Play(sound, Filter.Local(), uid, false, param); + } +} diff --git a/Content.Client/Radiation/UI/GeigerItemControl.cs b/Content.Client/Radiation/UI/GeigerItemControl.cs new file mode 100644 index 0000000000..af9e46fefa --- /dev/null +++ b/Content.Client/Radiation/UI/GeigerItemControl.cs @@ -0,0 +1,53 @@ +using Content.Client.Message; +using Content.Client.Stylesheets; +using Content.Shared.Radiation.Components; +using Content.Shared.Radiation.Systems; +using Robust.Client.UserInterface; +using Robust.Client.UserInterface.Controls; +using Robust.Shared.Timing; + +namespace Content.Client.Radiation.UI; + +public sealed class GeigerItemControl : Control +{ + private readonly GeigerComponent _component; + private readonly RichTextLabel _label; + + public GeigerItemControl(GeigerComponent component) + { + _component = component; + _label = new RichTextLabel { StyleClasses = { StyleNano.StyleClassItemStatus } }; + AddChild(_label); + + Update(); + } + + protected override void FrameUpdate(FrameEventArgs args) + { + base.FrameUpdate(args); + + if (!_component.UiUpdateNeeded) + return; + Update(); + } + + private void Update() + { + string msg; + if (_component.IsEnabled) + { + var color = SharedGeigerSystem.LevelToColor(_component.DangerLevel); + var currentRads = _component.CurrentRadiation; + var rads = currentRads.ToString("N1"); + msg = Loc.GetString("geiger-item-control-status", + ("rads", rads), ("color", color)); + } + else + { + msg = Loc.GetString("geiger-item-control-disabled"); + } + + _label.SetMarkup(msg); + _component.UiUpdateNeeded = false; + } +} diff --git a/Content.Server/Radiation/Events/RadiationSystemUpdatedEvent.cs b/Content.Server/Radiation/Events/RadiationSystemUpdatedEvent.cs new file mode 100644 index 0000000000..c0d38b2daa --- /dev/null +++ b/Content.Server/Radiation/Events/RadiationSystemUpdatedEvent.cs @@ -0,0 +1,9 @@ +using Content.Server.Radiation.Systems; + +namespace Content.Server.Radiation.Events; + +/// +/// Raised when updated all +/// radiation receivers and radiation sources. +/// +public record struct RadiationSystemUpdatedEvent; diff --git a/Content.Server/Radiation/Systems/GeigerSystem.cs b/Content.Server/Radiation/Systems/GeigerSystem.cs new file mode 100644 index 0000000000..720769cf18 --- /dev/null +++ b/Content.Server/Radiation/Systems/GeigerSystem.cs @@ -0,0 +1,165 @@ +using Content.Server.Radiation.Components; +using Content.Server.Radiation.Events; +using Content.Shared.Hands; +using Content.Shared.Interaction; +using Content.Shared.Inventory.Events; +using Content.Shared.Radiation.Components; +using Content.Shared.Radiation.Systems; +using Robust.Shared.GameStates; + +namespace Content.Server.Radiation.Systems; + +public sealed class GeigerSystem : SharedGeigerSystem +{ + [Dependency] private readonly SharedAppearanceSystem _appearance = default!; + [Dependency] private readonly RadiationSystem _radiation = default!; + + private static readonly float ApproxEqual = 0.01f; + + public override void Initialize() + { + base.Initialize(); + SubscribeLocalEvent(OnActivate); + + SubscribeLocalEvent(OnEquipped); + SubscribeLocalEvent(OnEquippedHand); + SubscribeLocalEvent(OnUnequipped); + SubscribeLocalEvent(OnUnequippedHand); + + SubscribeLocalEvent(OnUpdate); + SubscribeLocalEvent(OnGetState); + } + + private void OnActivate(EntityUid uid, GeigerComponent component, ActivateInWorldEvent args) + { + if (args.Handled || component.AttachedToSuit) + return; + args.Handled = true; + + SetEnabled(uid, component, !component.IsEnabled); + } + + private void OnEquipped(EntityUid uid, GeigerComponent component, GotEquippedEvent args) + { + if (component.AttachedToSuit) + SetEnabled(uid, component, true); + SetUser(component, args.Equipee); + } + + private void OnEquippedHand(EntityUid uid, GeigerComponent component, GotEquippedHandEvent args) + { + if (component.AttachedToSuit) + return; + + SetUser(component, args.User); + } + + private void OnUnequipped(EntityUid uid, GeigerComponent component, GotUnequippedEvent args) + { + if (component.AttachedToSuit) + SetEnabled(uid, component, false); + SetUser(component, null); + } + + private void OnUnequippedHand(EntityUid uid, GeigerComponent component, GotUnequippedHandEvent args) + { + if (component.AttachedToSuit) + return; + + SetUser(component, null); + } + + private void OnUpdate(RadiationSystemUpdatedEvent ev) + { + // update only active geiger counters + // deactivated shouldn't have rad receiver component + var query = EntityQuery(); + foreach (var (geiger, receiver) in query) + { + var rads = receiver.CurrentRadiation; + SetCurrentRadiation(geiger.Owner, geiger, rads); + } + } + + private void OnGetState(EntityUid uid, GeigerComponent component, ref ComponentGetState args) + { + args.State = new GeigerComponentState + { + CurrentRadiation = component.CurrentRadiation, + DangerLevel = component.DangerLevel, + IsEnabled = component.IsEnabled, + User = component.User + }; + } + + private void SetCurrentRadiation(EntityUid uid, GeigerComponent component, float rads) + { + // check that it's approx equal + if (MathHelper.CloseTo(component.CurrentRadiation, rads, ApproxEqual)) + return; + + var curLevel = component.DangerLevel; + var newLevel = RadsToLevel(rads); + + component.CurrentRadiation = rads; + component.DangerLevel = newLevel; + + if (curLevel != newLevel) + { + UpdateAppearance(uid, component); + } + + Dirty(component); + } + + private void SetUser(GeigerComponent component, EntityUid? user) + { + if (component.User == user) + return; + + component.User = user; + Dirty(component); + } + + private void SetEnabled(EntityUid uid, GeigerComponent component, bool isEnabled) + { + if (component.IsEnabled == isEnabled) + return; + + component.IsEnabled = isEnabled; + if (!isEnabled) + { + component.CurrentRadiation = 0f; + component.DangerLevel = GeigerDangerLevel.None; + } + + _radiation.SetCanReceive(uid, isEnabled); + + UpdateAppearance(uid, component); + Dirty(component); + } + + private void UpdateAppearance(EntityUid uid, GeigerComponent? component = null, + AppearanceComponent? appearance = null) + { + if (!Resolve(uid, ref component, ref appearance, false)) + return; + + _appearance.SetData(uid, GeigerVisuals.IsEnabled, component.IsEnabled, appearance); + _appearance.SetData(uid, GeigerVisuals.DangerLevel, component.DangerLevel, appearance); + } + + public static GeigerDangerLevel RadsToLevel(float rads) + { + return rads switch + { + < 0.2f => GeigerDangerLevel.None, + < 1f => GeigerDangerLevel.Low, + < 3f => GeigerDangerLevel.Med, + < 6f => GeigerDangerLevel.High, + _ => GeigerDangerLevel.Extreme + }; + } +} + + diff --git a/Content.Server/Radiation/Systems/RadiationSystem.GridCast.cs b/Content.Server/Radiation/Systems/RadiationSystem.GridCast.cs index c7a105d677..486a674ea2 100644 --- a/Content.Server/Radiation/Systems/RadiationSystem.GridCast.cs +++ b/Content.Server/Radiation/Systems/RadiationSystem.GridCast.cs @@ -1,4 +1,5 @@ using Content.Server.Radiation.Components; +using Content.Server.Radiation.Events; using Content.Shared.Radiation.Components; using Content.Shared.Radiation.Systems; using Robust.Shared.Collections; @@ -82,6 +83,9 @@ public partial class RadiationSystem if (rads > 0) IrradiateEntity(receiver.Owner, rads,GridcastUpdateRate); } + + // raise broadcast event that radiation system has updated + RaiseLocalEvent(new RadiationSystemUpdatedEvent()); } private RadiationRay? Irradiate(EntityUid sourceUid, TransformComponent sourceTrs, Vector2 sourceWorld, diff --git a/Content.Server/Radiation/Systems/RadiationSystem.cs b/Content.Server/Radiation/Systems/RadiationSystem.cs index d6442013f7..8e774c788d 100644 --- a/Content.Server/Radiation/Systems/RadiationSystem.cs +++ b/Content.Server/Radiation/Systems/RadiationSystem.cs @@ -1,4 +1,5 @@ -using Content.Shared.Radiation.Events; +using Content.Server.Radiation.Components; +using Content.Shared.Radiation.Events; using Robust.Shared.Configuration; using Robust.Shared.Map; @@ -43,4 +44,19 @@ public sealed partial class RadiationSystem : EntitySystem var msg = new OnIrradiatedEvent(time, radsPerSecond); RaiseLocalEvent(uid, msg); } + + /// + /// Marks entity to receive/ignore radiation rays. + /// + public void SetCanReceive(EntityUid uid, bool canReceive) + { + if (canReceive) + { + EnsureComp(uid); + } + else + { + RemComp(uid); + } + } } diff --git a/Content.Shared/Radiation/Components/GeigerComponent.cs b/Content.Shared/Radiation/Components/GeigerComponent.cs new file mode 100644 index 0000000000..2acd39c42c --- /dev/null +++ b/Content.Shared/Radiation/Components/GeigerComponent.cs @@ -0,0 +1,118 @@ +using Content.Shared.Radiation.Systems; +using Robust.Shared.Audio; +using Robust.Shared.GameStates; +using Robust.Shared.Serialization; + +namespace Content.Shared.Radiation.Components; + +/// +/// Geiger counter that shows current radiation level. +/// Can be added as a component to clothes. +/// +[RegisterComponent, NetworkedComponent] +[Access(typeof(SharedGeigerSystem))] +public sealed class GeigerComponent : Component +{ + /// + /// If true it will be active only when player equipped it. + /// + [DataField("attachedToSuit")] + public bool AttachedToSuit; + + /// + /// Is geiger counter currently active? + /// If false attached entity will ignore any radiation rays. + /// + [DataField("isEnabled")] + public bool IsEnabled; + + /// + /// Should it shows examine message with current radiation level? + /// + [ViewVariables(VVAccess.ReadWrite)] + [DataField("showExamine")] + public bool ShowExamine; + + /// + /// Should it shows item control when equipped by player? + /// + [ViewVariables(VVAccess.ReadWrite)] + [DataField("showControl")] + public bool ShowControl; + + /// + /// Map of sounds that should be play on loop for different radiation levels. + /// + [DataField("sounds")] + public Dictionary Sounds = new() + { + {GeigerDangerLevel.Low, new SoundPathSpecifier("/Audio/Items/Geiger/low.ogg")}, + {GeigerDangerLevel.Med, new SoundPathSpecifier("/Audio/Items/Geiger/med.ogg")}, + {GeigerDangerLevel.High, new SoundPathSpecifier("/Audio/Items/Geiger/high.ogg")}, + {GeigerDangerLevel.Extreme, new SoundPathSpecifier("/Audio/Items/Geiger/ext.ogg")} + }; + + /// + /// Current radiation level in rad per second. + /// + [ViewVariables(VVAccess.ReadOnly)] + public float CurrentRadiation; + + /// + /// Estimated radiation danger level. + /// + [ViewVariables(VVAccess.ReadOnly)] + public GeigerDangerLevel DangerLevel = GeigerDangerLevel.None; + + /// + /// Current player that equipped geiger counter. + /// Because sound is annoying, geiger counter clicks will play + /// only for player that equipped it. + /// + [ViewVariables(VVAccess.ReadOnly)] + public EntityUid? User; + + /// + /// Marked true if control needs to update UI with latest component state. + /// + [Access(typeof(SharedGeigerSystem), Other = AccessPermissions.ReadWrite)] + public bool UiUpdateNeeded; + + /// + /// Current stream of geiger counter audio. + /// Played only for current user. + /// + public IPlayingAudioStream? Stream; +} + +[Serializable, NetSerializable] +public sealed class GeigerComponentState : ComponentState +{ + public float CurrentRadiation; + public GeigerDangerLevel DangerLevel; + public bool IsEnabled; + public EntityUid? User; +} + +[Serializable, NetSerializable] +public enum GeigerDangerLevel : byte +{ + None, + Low, + Med, + High, + Extreme +} + +[Serializable, NetSerializable] +public enum GeigerLayers : byte +{ + Screen +} + +[Serializable, NetSerializable] +public enum GeigerVisuals : byte +{ + DangerLevel, + IsEnabled +} diff --git a/Content.Shared/Radiation/Systems/SharedGeigerSystem.cs b/Content.Shared/Radiation/Systems/SharedGeigerSystem.cs new file mode 100644 index 0000000000..da21d1d21a --- /dev/null +++ b/Content.Shared/Radiation/Systems/SharedGeigerSystem.cs @@ -0,0 +1,44 @@ +using Content.Shared.Examine; +using Content.Shared.Radiation.Components; + +namespace Content.Shared.Radiation.Systems; + +public abstract class SharedGeigerSystem : EntitySystem +{ + public override void Initialize() + { + base.Initialize(); + SubscribeLocalEvent(OnExamine); + } + + private void OnExamine(EntityUid uid, GeigerComponent component, ExaminedEvent args) + { + if (!component.ShowExamine || !component.IsEnabled || !args.IsInDetailsRange) + return; + + var currentRads = component.CurrentRadiation; + var rads = currentRads.ToString("N1"); + var color = LevelToColor(component.DangerLevel); + var msg = Loc.GetString("geiger-component-examine", + ("rads", rads), ("color", color)); + args.PushMarkup(msg); + } + + public static Color LevelToColor(GeigerDangerLevel level) + { + switch (level) + { + case GeigerDangerLevel.None: + return Color.Green; + case GeigerDangerLevel.Low: + return Color.Yellow; + case GeigerDangerLevel.Med: + return Color.DarkOrange; + case GeigerDangerLevel.High: + case GeigerDangerLevel.Extreme: + return Color.Red; + default: + return Color.White; + } + } +} diff --git a/Resources/Audio/Items/Geiger/attributions.yml b/Resources/Audio/Items/Geiger/attributions.yml new file mode 100644 index 0000000000..858c4ee219 --- /dev/null +++ b/Resources/Audio/Items/Geiger/attributions.yml @@ -0,0 +1,8 @@ +- files: + - "low.ogg" + - "med.ogg" + - "high.ogg" + - "ext.ogg" + license: "CC-BY-SA-3.0" + copyright: "Taken from tgstation at commit https://github.com/tgstation/tgstation/commit/456cd10d94084c7c2574f628cf7ac9b67087ba26" + source: "https://github.com/tgstation/tgstation/tree/456cd10d94084c7c2574f628cf7ac9b67087ba26/sound/items/geiger" diff --git a/Resources/Audio/Items/Geiger/ext.ogg b/Resources/Audio/Items/Geiger/ext.ogg new file mode 100644 index 0000000000..12b189c115 Binary files /dev/null and b/Resources/Audio/Items/Geiger/ext.ogg differ diff --git a/Resources/Audio/Items/Geiger/high.ogg b/Resources/Audio/Items/Geiger/high.ogg new file mode 100644 index 0000000000..c406bd5feb Binary files /dev/null and b/Resources/Audio/Items/Geiger/high.ogg differ diff --git a/Resources/Audio/Items/Geiger/low.ogg b/Resources/Audio/Items/Geiger/low.ogg new file mode 100644 index 0000000000..84750b48f5 Binary files /dev/null and b/Resources/Audio/Items/Geiger/low.ogg differ diff --git a/Resources/Audio/Items/Geiger/med.ogg b/Resources/Audio/Items/Geiger/med.ogg new file mode 100644 index 0000000000..38fbea68ae Binary files /dev/null and b/Resources/Audio/Items/Geiger/med.ogg differ diff --git a/Resources/Locale/en-US/radiation/geiger-component.ftl b/Resources/Locale/en-US/radiation/geiger-component.ftl new file mode 100644 index 0000000000..0e7d2a8a35 --- /dev/null +++ b/Resources/Locale/en-US/radiation/geiger-component.ftl @@ -0,0 +1,3 @@ +geiger-item-control-status = Radiation: [color={$color}]{$rads} rads[/color] +geiger-item-control-disabled = Disabled +geiger-component-examine = Current radiation: [color={$color}]{$rads} rads[/color] diff --git a/Resources/Prototypes/Catalog/Cargo/cargo_emergency.yml b/Resources/Prototypes/Catalog/Cargo/cargo_emergency.yml index bdf6eb0c2c..50a68bbc62 100644 --- a/Resources/Prototypes/Catalog/Cargo/cargo_emergency.yml +++ b/Resources/Prototypes/Catalog/Cargo/cargo_emergency.yml @@ -34,7 +34,7 @@ sprite: Structures/Wallmounts/signs.rsi state: radiation product: CrateEmergencyRadiation - cost: 900 + cost: 1000 category: Emergency group: market diff --git a/Resources/Prototypes/Catalog/Fills/Crates/emergency.yml b/Resources/Prototypes/Catalog/Fills/Crates/emergency.yml index ab0a03a610..a6ca46e4dd 100644 --- a/Resources/Prototypes/Catalog/Fills/Crates/emergency.yml +++ b/Resources/Prototypes/Catalog/Fills/Crates/emergency.yml @@ -63,8 +63,8 @@ amount: 2 - id: ClothingHeadHatHoodRad amount: 2 -# - id: GeigerCounter -# amount: 2 + - id: GeigerCounter + amount: 2 - id: DrinkVodkaBottleFull amount: 1 - id: DrinkShotGlass diff --git a/Resources/Prototypes/Catalog/Fills/Lockers/engineer.yml b/Resources/Prototypes/Catalog/Fills/Lockers/engineer.yml index c25e7b33e8..1ac715567a 100644 --- a/Resources/Prototypes/Catalog/Fills/Lockers/engineer.yml +++ b/Resources/Prototypes/Catalog/Fills/Lockers/engineer.yml @@ -115,3 +115,5 @@ amount: 2 - id: ClothingOuterSuitRad amount: 2 + - id: GeigerCounter + amount: 2 diff --git a/Resources/Prototypes/Entities/Clothing/Belt/belts.yml b/Resources/Prototypes/Entities/Clothing/Belt/belts.yml index a708bb885b..03ed0639d0 100644 --- a/Resources/Prototypes/Entities/Clothing/Belt/belts.yml +++ b/Resources/Prototypes/Entities/Clothing/Belt/belts.yml @@ -19,7 +19,7 @@ - Screwdriver - Flashlight - Wrench -# - GeigerCounter + - GeigerCounter - Flare - CableCoil - CigPack @@ -81,7 +81,7 @@ - Screwdriver - Flashlight - Wrench -# - GeigerCounter + - GeigerCounter - Flare - CableCoil - Powerdrill diff --git a/Resources/Prototypes/Entities/Clothing/OuterClothing/base_clothingouter.yml b/Resources/Prototypes/Entities/Clothing/OuterClothing/base_clothingouter.yml index ba68a4718a..29bb48452b 100644 --- a/Resources/Prototypes/Entities/Clothing/OuterClothing/base_clothingouter.yml +++ b/Resources/Prototypes/Entities/Clothing/OuterClothing/base_clothingouter.yml @@ -45,7 +45,7 @@ - type: entity abstract: true - parent: ClothingOuterBase + parent: [ClothingOuterBase, GeigerCounterClothing] id: ClothingOuterHardsuitBase name: base hardsuit components: diff --git a/Resources/Prototypes/Entities/Clothing/OuterClothing/suits.yml b/Resources/Prototypes/Entities/Clothing/OuterClothing/suits.yml index e80338f302..d4c3a79636 100644 --- a/Resources/Prototypes/Entities/Clothing/OuterClothing/suits.yml +++ b/Resources/Prototypes/Entities/Clothing/OuterClothing/suits.yml @@ -61,7 +61,7 @@ coefficient: 0.01 - type: entity - parent: ClothingOuterBaseLarge + parent: [ClothingOuterBaseLarge, GeigerCounterClothing] id: ClothingOuterSuitRad name: radiation suit description: "A suit that protects against radiation. The label reads, 'Made with lead. Please do not consume insulation.'" diff --git a/Resources/Prototypes/Entities/Clothing/base_clothing.yml b/Resources/Prototypes/Entities/Clothing/base_clothing.yml index 2f57dc258e..68d2a88288 100644 --- a/Resources/Prototypes/Entities/Clothing/base_clothing.yml +++ b/Resources/Prototypes/Entities/Clothing/base_clothing.yml @@ -10,3 +10,10 @@ - WhitelistChameleon - type: StaticPrice price: 15 + +- type: entity + abstract: true + id: GeigerCounterClothing + components: + - type: Geiger + attachedToSuit: true diff --git a/Resources/Prototypes/Entities/Objects/Devices/geiger.yml b/Resources/Prototypes/Entities/Objects/Devices/geiger.yml new file mode 100644 index 0000000000..66eaba5e87 --- /dev/null +++ b/Resources/Prototypes/Entities/Objects/Devices/geiger.yml @@ -0,0 +1,35 @@ +- type: entity + parent: BaseItem + id: GeigerCounter + name: Geiger counter + description: A handheld device used for detecting and measuring radiation pulses. + components: + - type: Sprite + netsync: false + sprite: Objects/Tools/geiger.rsi + layers: + - state: geiger_base + - state: geiger_on_idle + map: ["enum.GeigerLayers.Screen"] + shader: unshaded + visible: false + - type: Item + sprite: Objects/Tools/geiger.rsi + - type: Geiger + showControl: true + showExamine: true + - 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/Prototypes/tags.yml b/Resources/Prototypes/tags.yml index 1e9d881dcb..d07c878fca 100644 --- a/Resources/Prototypes/tags.yml +++ b/Resources/Prototypes/tags.yml @@ -249,6 +249,9 @@ - type: Tag id: Gauze +- type: Tag + id: GeigerCounter + - type: Tag id: GlassBeaker diff --git a/Resources/Textures/Objects/Tools/geiger.rsi/geiger_base.png b/Resources/Textures/Objects/Tools/geiger.rsi/geiger_base.png new file mode 100644 index 0000000000..ccb97cbe60 Binary files /dev/null and b/Resources/Textures/Objects/Tools/geiger.rsi/geiger_base.png differ diff --git a/Resources/Textures/Objects/Tools/geiger.rsi/geiger_on_ext.png b/Resources/Textures/Objects/Tools/geiger.rsi/geiger_on_ext.png new file mode 100644 index 0000000000..fc41e60ff8 Binary files /dev/null and b/Resources/Textures/Objects/Tools/geiger.rsi/geiger_on_ext.png differ diff --git a/Resources/Textures/Objects/Tools/geiger.rsi/geiger_on_high.png b/Resources/Textures/Objects/Tools/geiger.rsi/geiger_on_high.png new file mode 100644 index 0000000000..15edc91e52 Binary files /dev/null and b/Resources/Textures/Objects/Tools/geiger.rsi/geiger_on_high.png differ diff --git a/Resources/Textures/Objects/Tools/geiger.rsi/geiger_on_idle.png b/Resources/Textures/Objects/Tools/geiger.rsi/geiger_on_idle.png new file mode 100644 index 0000000000..6c83622e34 Binary files /dev/null and b/Resources/Textures/Objects/Tools/geiger.rsi/geiger_on_idle.png differ diff --git a/Resources/Textures/Objects/Tools/geiger.rsi/geiger_on_low.png b/Resources/Textures/Objects/Tools/geiger.rsi/geiger_on_low.png new file mode 100644 index 0000000000..015059c730 Binary files /dev/null and b/Resources/Textures/Objects/Tools/geiger.rsi/geiger_on_low.png differ diff --git a/Resources/Textures/Objects/Tools/geiger.rsi/geiger_on_med.png b/Resources/Textures/Objects/Tools/geiger.rsi/geiger_on_med.png new file mode 100644 index 0000000000..c88de643eb Binary files /dev/null and b/Resources/Textures/Objects/Tools/geiger.rsi/geiger_on_med.png differ diff --git a/Resources/Textures/Objects/Tools/geiger.rsi/inhand-left.png b/Resources/Textures/Objects/Tools/geiger.rsi/inhand-left.png new file mode 100644 index 0000000000..8a3690aabd Binary files /dev/null and b/Resources/Textures/Objects/Tools/geiger.rsi/inhand-left.png differ diff --git a/Resources/Textures/Objects/Tools/geiger.rsi/inhand-right.png b/Resources/Textures/Objects/Tools/geiger.rsi/inhand-right.png new file mode 100644 index 0000000000..7f6edf5439 Binary files /dev/null and b/Resources/Textures/Objects/Tools/geiger.rsi/inhand-right.png differ diff --git a/Resources/Textures/Objects/Tools/geiger.rsi/meta.json b/Resources/Textures/Objects/Tools/geiger.rsi/meta.json new file mode 100644 index 0000000000..10968b4776 --- /dev/null +++ b/Resources/Textures/Objects/Tools/geiger.rsi/meta.json @@ -0,0 +1,43 @@ +{ + "version": 1, + "license": "CC-BY-SA-3.0", + "copyright": "Taken from tgstation at commit https://github.com/tgstation/tgstation/commit/bfc9c6ba8126ee8c41564d68c4bfb9ce37faa8f8", + "size": { + "x": 32, + "y": 32 + }, + "states": [ + { + "name": "geiger_base" + }, + { + "name": "geiger_on_idle" + }, + { + "name": "geiger_on_low" + }, + { + "name": "geiger_on_med" + }, + { + "name": "geiger_on_high" + }, + { + "name": "geiger_on_ext", + "delays": [ + [ + 0.2, + 0.1 + ] + ] + }, + { + "name": "inhand-left", + "directions": 4 + }, + { + "name": "inhand-right", + "directions": 4 + } + ] +}