From cb5f49f2b3c9882a24c5b2dfe830c6d6095faec9 Mon Sep 17 00:00:00 2001 From: rhailrake <49613070+rhailrake@users.noreply.github.com> Date: Thu, 27 Apr 2023 23:54:17 +0600 Subject: [PATCH] [feat]Med huds --- .../Commands/ToggleHealthBarsCommand.cs | 44 +++++ .../EntityHealthBar/EntityHealthBarOverlay.cs | 163 ++++++++++++++++++ .../EntityHealthBar/ShowHealthBarsSystem.cs | 64 +++++++ .../Overlays/ShowHealthBarsComponent.cs | 2 +- .../Components/ClothingGrantComponent.cs | 15 ++ .../Components/ClothingGrantTagComponent.cs | 11 ++ .../Systems/ClothingGrantingSystem.cs | 86 +++++++++ .../ShowHealthBarsComponent.cs | 21 +++ .../Prototypes/Entities/Clothing/Eyes/hud.yml | 105 +++++++---- .../Prototypes/Entities/Mobs/NPCs/silicon.yml | 15 +- .../Entities/Structures/Machines/lathe.yml | 1 + .../Prototypes/Recipes/Lathes/electronics.yml | 10 ++ .../Interface/Misc/health_bar.rsi/icon.png | Bin 0 -> 153 bytes .../Interface/Misc/health_bar.rsi/meta.json | 14 ++ 14 files changed, 508 insertions(+), 43 deletions(-) create mode 100644 Content.Client/Commands/ToggleHealthBarsCommand.cs create mode 100644 Content.Client/White/EntityHealthBar/EntityHealthBarOverlay.cs create mode 100644 Content.Client/White/EntityHealthBar/ShowHealthBarsSystem.cs create mode 100644 Content.Shared/White/ClothingGrant/Components/ClothingGrantComponent.cs create mode 100644 Content.Shared/White/ClothingGrant/Components/ClothingGrantTagComponent.cs create mode 100644 Content.Shared/White/ClothingGrant/Systems/ClothingGrantingSystem.cs create mode 100644 Content.Shared/White/EntityHealthBar/ShowHealthBarsComponent.cs create mode 100644 Resources/Textures/Interface/Misc/health_bar.rsi/icon.png create mode 100644 Resources/Textures/Interface/Misc/health_bar.rsi/meta.json diff --git a/Content.Client/Commands/ToggleHealthBarsCommand.cs b/Content.Client/Commands/ToggleHealthBarsCommand.cs new file mode 100644 index 0000000000..b1cc811ec4 --- /dev/null +++ b/Content.Client/Commands/ToggleHealthBarsCommand.cs @@ -0,0 +1,44 @@ +using Robust.Client.Player; +using Robust.Shared.Console; +using Content.Shared.EntityHealthBar; + +namespace Content.Client.Commands +{ + public sealed class ToggleHealthBarsCommand : IConsoleCommand + { + [Dependency] private readonly IPlayerManager _playerManager = default!; + [Dependency] private readonly IEntityManager _entityManager = default!; + + public string Command => "togglehealthbars"; + public string Description => "Toggles a health bar above mobs."; + public string Help => $"Usage: {Command}"; + + public void Execute(IConsoleShell shell, string argStr, string[] args) + { + var player = _playerManager.LocalPlayer; + if (player == null) + { + shell.WriteLine("You aren't a player."); + return; + } + + var playerEntity = player?.ControlledEntity; + if (playerEntity == null) + { + shell.WriteLine("You do not have an attached entity."); + return; + } + + if (!_entityManager.TryGetComponent(playerEntity, out var glassComp)) + { + _entityManager.AddComponent((EntityUid) playerEntity); + shell.WriteLine("Enabled health overlay."); + return; + } + + _entityManager.RemoveComponent((EntityUid) playerEntity); + shell.WriteLine("Disabled health overlay."); + return; + } + } +} diff --git a/Content.Client/White/EntityHealthBar/EntityHealthBarOverlay.cs b/Content.Client/White/EntityHealthBar/EntityHealthBarOverlay.cs new file mode 100644 index 0000000000..287d6f394e --- /dev/null +++ b/Content.Client/White/EntityHealthBar/EntityHealthBarOverlay.cs @@ -0,0 +1,163 @@ +using System.Numerics; +using Content.Shared.Damage; +using Content.Shared.Mobs; +using Content.Shared.Mobs.Components; +using Content.Shared.Mobs.Systems; +using Content.Shared.FixedPoint; +using Robust.Client.GameObjects; +using Robust.Client.Graphics; +using Robust.Shared.Enums; +using Robust.Shared.Prototypes; +using Robust.Shared.Utility; + +namespace Content.Client.EntityHealthBar; + +/// +/// Yeah a lot of this is duplicated from doafters. +/// Not much to be done until there's a generic HUD system +/// +public sealed class EntityHealthBarOverlay : Overlay +{ + private readonly IEntityManager _entManager; + private readonly SharedTransformSystem _transform; + private readonly MobStateSystem _mobStateSystem; + private readonly MobThresholdSystem _mobThresholdSystem; + private readonly Texture _barTexture; + private readonly ShaderInstance _shader; + public override OverlaySpace Space => OverlaySpace.WorldSpaceBelowFOV; + public List DamageContainers = new(); + + public EntityHealthBarOverlay(IEntityManager entManager, IPrototypeManager protoManager) + { + _entManager = entManager; + _transform = _entManager.EntitySysManager.GetEntitySystem(); + _mobStateSystem = _entManager.EntitySysManager.GetEntitySystem(); + _mobThresholdSystem = _entManager.EntitySysManager.GetEntitySystem(); + + var sprite = new SpriteSpecifier.Rsi(new ResPath("/Textures/Interface/Misc/health_bar.rsi"), "icon"); + _barTexture = _entManager.EntitySysManager.GetEntitySystem().Frame0(sprite); + + _shader = protoManager.Index("shaded").Instance(); + } + + protected override void Draw(in OverlayDrawArgs args) + { + var handle = args.WorldHandle; + var rotation = args.Viewport.Eye?.Rotation ?? Angle.Zero; + var spriteQuery = _entManager.GetEntityQuery(); + var xformQuery = _entManager.GetEntityQuery(); + + const float scale = 1f; + var scaleMatrix = Matrix3.CreateScale(new Vector2(scale, scale)); + var rotationMatrix = Matrix3.CreateRotation(-rotation); + handle.UseShader(_shader); + + foreach (var (mob, dmg) in _entManager.EntityQuery(true)) + { + if (!xformQuery.TryGetComponent(mob.Owner, out var xform) || + xform.MapID != args.MapId) + { + continue; + } + + if (dmg.DamageContainerID == null || !DamageContainers.Contains(dmg.DamageContainerID)) + continue; + + var worldPosition = _transform.GetWorldPosition(xform); + var worldMatrix = Matrix3.CreateTranslation(worldPosition); + + Matrix3.Multiply(scaleMatrix, worldMatrix, out var scaledWorld); + Matrix3.Multiply(rotationMatrix, scaledWorld, out var matty); + + handle.SetTransform(matty); + + // Use the sprite itself if we know its bounds. This means short or tall sprites don't get overlapped + // by the bar. + float yOffset; + if (spriteQuery.TryGetComponent(mob.Owner, out var sprite)) + { + yOffset = sprite.Bounds.Height + 15f; + } + else + { + yOffset = 1f; + } + + // Position above the entity (we've already applied the matrix transform to the entity itself) + // Offset by the texture size for every do_after we have. + var position = new Vector2(-_barTexture.Width / 2f / EyeManager.PixelsPerMeter, + yOffset / EyeManager.PixelsPerMeter); + + // Draw the underlying bar texture + handle.DrawTexture(_barTexture, position); + + // we are all progressing towards death every day + (float ratio, bool inCrit) deathProgress = CalcProgress(mob.Owner, mob, dmg); + + var color = GetProgressColor(deathProgress.ratio, deathProgress.inCrit); + + // Hardcoded width of the progress bar because it doesn't match the texture. + const float startX = 2f; + const float endX = 22f; + + var xProgress = (endX - startX) * deathProgress.ratio + startX; + + var box = new Box2(new Vector2(startX, 3f) / EyeManager.PixelsPerMeter, new Vector2(xProgress, 4f) / EyeManager.PixelsPerMeter); + box = box.Translated(position); + handle.DrawRect(box, color); + } + + handle.UseShader(null); + handle.SetTransform(Matrix3.Identity); + } + + /// + /// Returns a ratio between 0 and 1, and whether the entity is in crit. + /// + private (float, bool) CalcProgress(EntityUid uid, MobStateComponent component, DamageableComponent dmg) + { + if (_mobStateSystem.IsAlive(uid, component)) + { + if (!_mobThresholdSystem.TryGetThresholdForState(uid, MobState.Critical, out var threshold)) + return (1, false); + + var ratio = 1 - ((FixedPoint2)(dmg.TotalDamage / threshold)).Float(); + return (ratio, false); + } + + if (_mobStateSystem.IsCritical(uid, component)) + { + if (!_mobThresholdSystem.TryGetThresholdForState(uid, MobState.Critical, out var critThreshold) || + !_mobThresholdSystem.TryGetThresholdForState(uid, MobState.Dead, out var deadThreshold)) + { + return (1, true); + } + + var ratio = 1 - + ((dmg.TotalDamage - critThreshold) / + (deadThreshold - critThreshold)).Value.Float(); + + return (ratio, true); + } + + return (0, true); + } + + public static Color GetProgressColor(float progress, bool crit) + { + if (progress >= 1.0f) + { + return new Color(0f, 1f, 0f); + } + // lerp + if (!crit) + { + var hue = (5f / 18f) * progress; + return Color.FromHsv((hue, 1f, 0.75f, 1f)); + } + else + { + return Color.Red; + } + } +} diff --git a/Content.Client/White/EntityHealthBar/ShowHealthBarsSystem.cs b/Content.Client/White/EntityHealthBar/ShowHealthBarsSystem.cs new file mode 100644 index 0000000000..b521027409 --- /dev/null +++ b/Content.Client/White/EntityHealthBar/ShowHealthBarsSystem.cs @@ -0,0 +1,64 @@ +using Content.Shared.EntityHealthBar; +using Content.Shared.GameTicking; +using Robust.Client.Player; +using Robust.Client.Graphics; +using Robust.Shared.Player; +using Robust.Shared.Prototypes; + +namespace Content.Client.EntityHealthBar +{ + public sealed class ShowHealthBarsSystem : EntitySystem + { + [Dependency] private readonly IPlayerManager _player = default!; + [Dependency] private readonly IPrototypeManager _protoMan = default!; + [Dependency] private readonly IOverlayManager _overlayMan = default!; + + private EntityHealthBarOverlay _overlay = default!; + public override void Initialize() + { + base.Initialize(); + + SubscribeLocalEvent(OnInit); + SubscribeLocalEvent(OnRemove); + SubscribeLocalEvent(OnPlayerAttached); + SubscribeLocalEvent(OnPlayerDetached); + SubscribeLocalEvent(OnRoundRestart); + + _overlay = new(EntityManager, _protoMan); + } + + private void OnInit(EntityUid uid, ShowHealthBarsComponent component, ComponentInit args) + { + if (_player.LocalPlayer?.ControlledEntity == uid) + { + _overlayMan.AddOverlay(_overlay); + _overlay.DamageContainers = component.DamageContainers; + } + + + } + private void OnRemove(EntityUid uid, ShowHealthBarsComponent component, ComponentRemove args) + { + if (_player.LocalPlayer?.ControlledEntity == uid) + { + _overlayMan.RemoveOverlay(_overlay); + } + } + + private void OnPlayerAttached(EntityUid uid, ShowHealthBarsComponent component, PlayerAttachedEvent args) + { + _overlayMan.AddOverlay(_overlay); + _overlay.DamageContainers = component.DamageContainers; + } + + private void OnPlayerDetached(EntityUid uid, ShowHealthBarsComponent component, PlayerDetachedEvent args) + { + _overlayMan.RemoveOverlay(_overlay); + } + + private void OnRoundRestart(RoundRestartCleanupEvent args) + { + _overlayMan.RemoveOverlay(_overlay); + } + } +} diff --git a/Content.Shared/Overlays/ShowHealthBarsComponent.cs b/Content.Shared/Overlays/ShowHealthBarsComponent.cs index 48e3162269..5dd8ecd3d6 100644 --- a/Content.Shared/Overlays/ShowHealthBarsComponent.cs +++ b/Content.Shared/Overlays/ShowHealthBarsComponent.cs @@ -8,7 +8,7 @@ namespace Content.Shared.Overlays; /// This component allows you to see health bars above damageable mobs. /// [RegisterComponent, NetworkedComponent] -public sealed partial class ShowHealthBarsComponent : Component +public sealed partial class ShowWhiteHealthBarsComponent : Component { /// /// Displays health bars of the damage containers. diff --git a/Content.Shared/White/ClothingGrant/Components/ClothingGrantComponent.cs b/Content.Shared/White/ClothingGrant/Components/ClothingGrantComponent.cs new file mode 100644 index 0000000000..f12f536f46 --- /dev/null +++ b/Content.Shared/White/ClothingGrant/Components/ClothingGrantComponent.cs @@ -0,0 +1,15 @@ +using Robust.Shared.Prototypes; + +namespace Content.Shared.Clothing +{ + [RegisterComponent] + public sealed partial class ClothingGrantComponentComponent : Component + { + [DataField("component", required: true)] + [AlwaysPushInheritance] + public ComponentRegistry Components { get; } = new(); + + [ViewVariables(VVAccess.ReadWrite)] + public bool IsActive = false; + } +} diff --git a/Content.Shared/White/ClothingGrant/Components/ClothingGrantTagComponent.cs b/Content.Shared/White/ClothingGrant/Components/ClothingGrantTagComponent.cs new file mode 100644 index 0000000000..ff67f5c9a5 --- /dev/null +++ b/Content.Shared/White/ClothingGrant/Components/ClothingGrantTagComponent.cs @@ -0,0 +1,11 @@ +namespace Content.Shared.Clothing +{ + [RegisterComponent] + public sealed partial class ClothingGrantTagComponent : Component + { + [DataField("tag", required: true), ViewVariables(VVAccess.ReadWrite)] + public string Tag = ""; + + [ViewVariables(VVAccess.ReadWrite)] public bool IsActive = false; + } +} diff --git a/Content.Shared/White/ClothingGrant/Systems/ClothingGrantingSystem.cs b/Content.Shared/White/ClothingGrant/Systems/ClothingGrantingSystem.cs new file mode 100644 index 0000000000..8413a4a432 --- /dev/null +++ b/Content.Shared/White/ClothingGrant/Systems/ClothingGrantingSystem.cs @@ -0,0 +1,86 @@ +using Content.Shared.Clothing.Components; +using Content.Shared.Inventory.Events; +using Robust.Shared.Serialization.Manager; +using Content.Shared.Tag; + +namespace Content.Shared.Clothing; + +public sealed class ClothingGrantingSystem : EntitySystem +{ + [Dependency] private readonly IComponentFactory _componentFactory = default!; + [Dependency] private readonly ISerializationManager _serializationManager = default!; + [Dependency] private readonly TagSystem _tagSystem = default!; + + public override void Initialize() + { + base.Initialize(); + SubscribeLocalEvent(OnCompEquip); + SubscribeLocalEvent(OnCompUnequip); + SubscribeLocalEvent(OnTagEquip); + SubscribeLocalEvent(OnTagUnequip); + } + + private void OnCompEquip(EntityUid uid, ClothingGrantComponentComponent component, GotEquippedEvent args) + { + if (!TryComp(uid, out var clothing)) return; + + if (!clothing.Slots.HasFlag(args.SlotFlags)) return; + + if (component.Components.Count > 1) + { + Logger.Error("Although a component registry supports multiple components, we cannot bookkeep more than 1 component for ClothingGrantComponent at this time."); + return; + } + + foreach (var (name, data) in component.Components) + { + var newComp = (Component) _componentFactory.GetComponent(name); + + if (HasComp(args.Equipee, newComp.GetType())) + continue; + + newComp.Owner = args.Equipee; + + var temp = (object) newComp; + _serializationManager.CopyTo(data.Component, ref temp); + EntityManager.AddComponent(args.Equipee, (Component)temp!); + + component.IsActive = true; + } + } + + private void OnCompUnequip(EntityUid uid, ClothingGrantComponentComponent component, GotUnequippedEvent args) + { + if (!component.IsActive) return; + + foreach (var (name, data) in component.Components) + { + var newComp = (Component) _componentFactory.GetComponent(name); + + RemComp(args.Equipee, newComp.GetType()); + } + + component.IsActive = false; + } + + private void OnTagEquip(EntityUid uid, ClothingGrantTagComponent component, GotEquippedEvent args) + { + if (!TryComp(uid, out var clothing)) return; + + if (!clothing.Slots.HasFlag(args.SlotFlags)) return; + + EnsureComp(args.Equipee); + _tagSystem.AddTag(args.Equipee, component.Tag); + + component.IsActive = true; + } + + private void OnTagUnequip(EntityUid uid, ClothingGrantTagComponent component, GotUnequippedEvent args) + { + if (!component.IsActive) return; + + _tagSystem.RemoveTag(args.Equipee, component.Tag); + + component.IsActive = false; + } +} diff --git a/Content.Shared/White/EntityHealthBar/ShowHealthBarsComponent.cs b/Content.Shared/White/EntityHealthBar/ShowHealthBarsComponent.cs new file mode 100644 index 0000000000..6a13805692 --- /dev/null +++ b/Content.Shared/White/EntityHealthBar/ShowHealthBarsComponent.cs @@ -0,0 +1,21 @@ +using Content.Shared.Damage.Prototypes; +using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype; +using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype.List; + +namespace Content.Shared.EntityHealthBar +{ + /// + /// This component allows you to see health bars above damageable mobs. + /// + [RegisterComponent] + public sealed partial class ShowHealthBarsComponent : Component + { + /// + /// If null, displays all health bars. + /// If not null, displays health bars of only that damage container. + /// + + [DataField("damageContainers", customTypeSerializer: typeof(PrototypeIdListSerializer))] + public List DamageContainers = new(); + } +} diff --git a/Resources/Prototypes/Entities/Clothing/Eyes/hud.yml b/Resources/Prototypes/Entities/Clothing/Eyes/hud.yml index 1ab2fab0e6..302e50c8fb 100644 --- a/Resources/Prototypes/Entities/Clothing/Eyes/hud.yml +++ b/Resources/Prototypes/Entities/Clothing/Eyes/hud.yml @@ -8,10 +8,16 @@ sprite: Clothing/Eyes/Hud/diag.rsi - type: Clothing sprite: Clothing/Eyes/Hud/diag.rsi - - type: ShowHealthBars - damageContainers: - - Inorganic - - Silicon +# - type: ShowHealthBars +# damageContainers: +# - Inorganic +# - Silicon + - type: ClothingGrantComponent + component: + - type: ShowWhiteHealthBars + damageContainers: + - Inorganic + - Silicon - type: entity parent: ClothingEyesBase @@ -23,12 +29,17 @@ sprite: Clothing/Eyes/Hud/med.rsi - type: Clothing sprite: Clothing/Eyes/Hud/med.rsi - - type: ShowHealthBars - damageContainers: - - Biological - - type: ShowHealthIcons - damageContainers: - - Biological +# - type: ShowHealthBars +# damageContainers: +# - Biological +# - type: ShowHealthIcons +# damageContainers: +# - Biological + - type: ClothingGrantComponent + component: + - type: ShowWhiteHealthBars + damageContainers: + - Biological - type: entity parent: ClothingEyesBase @@ -104,12 +115,17 @@ sprite: Clothing/Eyes/Hud/medonion.rsi - type: Clothing sprite: Clothing/Eyes/Hud/medonion.rsi - - type: ShowHealthBars - damageContainers: - - Biological - - type: ShowHealthIcons - damageContainers: - - Biological +# - type: ShowHealthBars +# damageContainers: +# - Biological +# - type: ShowHealthIcons +# damageContainers: +# - Biological + - type: ClothingGrantComponent + component: + - type: ShowWhiteHealthBars + damageContainers: + - Biological - type: ShowHungerIcons - type: entity @@ -122,12 +138,17 @@ sprite: Clothing/Eyes/Hud/medonionbeer.rsi - type: Clothing sprite: Clothing/Eyes/Hud/medonionbeer.rsi - - type: ShowHealthBars - damageContainers: - - Biological - - type: ShowHealthIcons - damageContainers: - - Biological +# - type: ShowHealthBars +# damageContainers: +# - Biological +# - type: ShowHealthIcons +# damageContainers: +# - Biological + - type: ClothingGrantComponent + component: + - type: ShowWhiteHealthBars + damageContainers: + - Biological - type: ShowHungerIcons - type: ShowThirstIcons @@ -154,13 +175,19 @@ - type: Clothing sprite: Clothing/Eyes/Hud/medsecengi.rsi - type: ShowSecurityIcons - - type: ShowHealthBars - damageContainers: - - Biological - - Inorganic - - type: ShowHealthIcons - damageContainers: - - Biological + - type: ClothingGrantComponent + component: + - type: ShowWhiteHealthBars + damageContainers: + - Biological + - Inorganic +# - type: ShowHealthBars +# damageContainers: +# - Biological +# - Inorganic +# - type: ShowHealthIcons +# damageContainers: +# - Biological - type: ShowSyndicateIcons - type: entity @@ -174,13 +201,19 @@ - type: Clothing sprite: Clothing/Eyes/Hud/omni.rsi - type: ShowSecurityIcons - - type: ShowHealthBars - damageContainers: - - Biological - - Inorganic - - type: ShowHealthIcons - damageContainers: - - Biological +# - type: ShowHealthBars +# damageContainers: +# - Biological +# - Inorganic +# - type: ShowHealthIcons +# damageContainers: +# - Biological + - type: ClothingGrantComponent + component: + - type: ShowWhiteHealthBars + damageContainers: + - Biological + - Inorganic - type: ShowHungerIcons - type: ShowThirstIcons - type: ShowSyndicateIcons diff --git a/Resources/Prototypes/Entities/Mobs/NPCs/silicon.yml b/Resources/Prototypes/Entities/Mobs/NPCs/silicon.yml index cd7882d3d1..ae6549c071 100644 --- a/Resources/Prototypes/Entities/Mobs/NPCs/silicon.yml +++ b/Resources/Prototypes/Entities/Mobs/NPCs/silicon.yml @@ -349,13 +349,16 @@ interactFailureString: petting-failure-medibot interactSuccessSound: path: /Audio/Ambience/Objects/periodic_beep.ogg - - type: ShowHealthBars - damageContainers: +# - type: ShowHealthBars +# damageContainers: +# - Biological +# - type: ShowHealthIcons +# damageContainers: +# - Biological + - type: ShowWhiteHealthBars + damageContainers: - Biological - - type: ShowHealthIcons - damageContainers: - - Biological - + - type: entity parent: MobSiliconBase id: MobMimeBot diff --git a/Resources/Prototypes/Entities/Structures/Machines/lathe.yml b/Resources/Prototypes/Entities/Structures/Machines/lathe.yml index 2dd454d956..287171d429 100644 --- a/Resources/Prototypes/Entities/Structures/Machines/lathe.yml +++ b/Resources/Prototypes/Entities/Structures/Machines/lathe.yml @@ -801,6 +801,7 @@ - MedkitAdvanced - MedkitRadiation - MedkitCombat + - ClothingEyesHudMedical dynamicRecipes: - HandheldCrewMonitor - ClothingHandsGlovesNitrile diff --git a/Resources/Prototypes/Recipes/Lathes/electronics.yml b/Resources/Prototypes/Recipes/Lathes/electronics.yml index 3b5c04f4fe..fab6db7cea 100644 --- a/Resources/Prototypes/Recipes/Lathes/electronics.yml +++ b/Resources/Prototypes/Recipes/Lathes/electronics.yml @@ -781,3 +781,13 @@ Steel: 100 Glass: 900 Gold: 100 + +- type: latheRecipe + id: ClothingEyesHudMedical + icon: { sprite: Clothing/Eyes/Hud/med.rsi, state: icon } + result: ClothingEyesHudMedical + completetime: 4 + materials: + Steel: 100 + Glass: 300 + Plasma: 200 diff --git a/Resources/Textures/Interface/Misc/health_bar.rsi/icon.png b/Resources/Textures/Interface/Misc/health_bar.rsi/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..edd9c35db835b07c51e10f97ec4968bae45b548b GIT binary patch literal 153 zcmeAS@N?(olHy`uVBq!ia0vp^59Y|h)rvV<=xcsQe*4ga|bTmy?Kgb+k!27e*IrN z+k9nK^Q>J~t5`!!WwRviux~MtNmKI;;@i~B_$p6=zopr7yva> BHW~l` literal 0 HcmV?d00001 diff --git a/Resources/Textures/Interface/Misc/health_bar.rsi/meta.json b/Resources/Textures/Interface/Misc/health_bar.rsi/meta.json new file mode 100644 index 0000000000..9a6f00e2c2 --- /dev/null +++ b/Resources/Textures/Interface/Misc/health_bar.rsi/meta.json @@ -0,0 +1,14 @@ +{ + "version": 1, + "size": { + "y": 7, + "x": 24 + }, + "license": "CC-BY-SA-3.0", + "copyright": "https://github.com/tgstation/tgstation/blob/886ca0f8dddf83ecaf10c92ff106172722352192/icons/effects/progessbar.dmi", + "states": [ + { + "name": "icon" + } + ] +}