]> git.smokeofanarchy.ru Git - space-station-14.git/commitdiff
Resolves StackVisualizer is Obsolete (#13908)
authorTemporalOroboros <TemporalOroboros@gmail.com>
Thu, 18 May 2023 06:16:53 +0000 (23:16 -0700)
committerGitHub <noreply@github.com>
Thu, 18 May 2023 06:16:53 +0000 (16:16 +1000)
20 files changed:
Content.Client/Stack/StackSystem.cs
Content.Client/Stack/StackVisualizer.cs [deleted file]
Content.Client/Storage/Systems/ItemCounterSystem.cs [new file with mode: 0644]
Content.Shared/Stacks/StackComponent.cs
Content.Shared/Storage/Components/ItemCounterComponent.cs
Resources/Prototypes/Entities/Objects/Consumable/Drinks/drinks_cans.yml
Resources/Prototypes/Entities/Objects/Consumable/Food/Baked/misc.yml
Resources/Prototypes/Entities/Objects/Consumable/Food/Containers/box.yml
Resources/Prototypes/Entities/Objects/Consumable/Smokeables/Cigarettes/packs.yml
Resources/Prototypes/Entities/Objects/Consumable/Smokeables/Cigars/case.yml
Resources/Prototypes/Entities/Objects/Materials/Sheets/glass.yml
Resources/Prototypes/Entities/Objects/Materials/Sheets/metal.yml
Resources/Prototypes/Entities/Objects/Materials/Sheets/other.yml
Resources/Prototypes/Entities/Objects/Materials/ingots.yml
Resources/Prototypes/Entities/Objects/Materials/materials.yml
Resources/Prototypes/Entities/Objects/Materials/parts.yml
Resources/Prototypes/Entities/Objects/Misc/space_cash.yml
Resources/Prototypes/Entities/Objects/Tools/cable_coils.yml
Resources/Prototypes/Entities/Objects/Tools/inflatable_wall.yml
Resources/Prototypes/Entities/Objects/Tools/matches.yml

index 34b00bc0810f105ce2a3f8c99ffd07c0e0a44e12..85eb0dfb35d68af21338093acf07c694f0103f5f 100644 (file)
@@ -1,16 +1,22 @@
 using Content.Client.Items;
+using Content.Client.Storage.Systems;
 using Content.Shared.Stacks;
 using JetBrains.Annotations;
+using Robust.Client.GameObjects;
 
 namespace Content.Client.Stack
 {
     [UsedImplicitly]
     public sealed class StackSystem : SharedStackSystem
     {
+        [Dependency] private readonly AppearanceSystem _appearanceSystem = default!;
+        [Dependency] private readonly ItemCounterSystem _counterSystem = default!;
+
         public override void Initialize()
         {
             base.Initialize();
             SubscribeLocalEvent<StackComponent, ItemStatusCollectMessage>(OnItemStatus);
+            SubscribeLocalEvent<StackComponent, AppearanceChangeEvent>(OnAppearanceChange);
         }
 
         private void OnItemStatus(EntityUid uid, StackComponent component, ItemStatusCollectMessage args)
@@ -36,5 +42,26 @@ namespace Content.Client.Stack
             if (component is StackComponent clientComp)
                 clientComp.UiUpdateNeeded = true;
         }
+
+        private void OnAppearanceChange(EntityUid uid, StackComponent comp, ref AppearanceChangeEvent args)
+        {
+            if (args.Sprite == null || comp.LayerStates.Count < 1)
+                return;
+
+            // Skip processing if no actual
+            if (!_appearanceSystem.TryGetData<int>(uid, StackVisuals.Actual, out var actual, args.Component))
+                return;
+
+            if (!_appearanceSystem.TryGetData<int>(uid, StackVisuals.MaxCount, out var maxCount, args.Component))
+                maxCount = comp.LayerStates.Count;
+
+            if (!_appearanceSystem.TryGetData<bool>(uid, StackVisuals.Hide, out var hidden, args.Component))
+                hidden = false;
+
+            if (comp.IsComposite)
+                _counterSystem.ProcessCompositeSprite(uid, actual, maxCount, comp.LayerStates, hidden, sprite: args.Sprite);
+            else
+                _counterSystem.ProcessOpaqueSprite(uid, comp.BaseLayer, actual, maxCount, comp.LayerStates, hidden, sprite: args.Sprite);
+        }
     }
 }
diff --git a/Content.Client/Stack/StackVisualizer.cs b/Content.Client/Stack/StackVisualizer.cs
deleted file mode 100644 (file)
index a3437bb..0000000
+++ /dev/null
@@ -1,162 +0,0 @@
-
-using System.Collections.Generic;
-using Content.Shared.Rounding;
-using Content.Shared.Stacks;
-using JetBrains.Annotations;
-using Robust.Client.GameObjects;
-using Robust.Shared.GameObjects;
-using Robust.Shared.IoC;
-using Robust.Shared.Serialization.Manager.Attributes;
-using Robust.Shared.Utility;
-
-namespace Content.Client.Stack
-{
-    /// <summary>
-    /// Visualizer for items that come in stacks and have different appearance
-    /// depending on the size of the stack. Visualizer can work by switching between different
-    /// icons in <c>_spriteLayers</c> or if the sprite layers are supposed to be composed as transparent layers.
-    /// The former behavior is default and the latter behavior can be defined in prototypes.
-    ///
-    /// <example>
-    /// <para>To define a Stack Visualizer prototype insert the following
-    /// snippet (you can skip Appearance if already defined)
-    /// </para>
-    /// <code>
-    /// - type: Appearance
-    ///   visuals:
-    ///     - type: StackVisualizer
-    ///       stackLayers:
-    ///         - goldbar_10
-    ///         - goldbar_20
-    ///         - goldbar_30
-    /// </code>
-    /// </example>
-    /// <example>
-    /// <para>Defining a stack visualizer with composable transparent layers</para>
-    /// <code>
-    ///   - type: StackVisualizer
-    ///     composite: true
-    ///     stackLayers:
-    ///       - cigarette_1
-    ///       - cigarette_2
-    ///       - cigarette_3
-    ///       - cigarette_4
-    ///       - cigarette_5
-    ///       - cigarette_6
-    /// </code>
-    /// </example>
-    ///  <seealso cref="_spriteLayers"/>
-    /// </summary>
-    [UsedImplicitly]
-    public sealed class StackVisualizer : AppearanceVisualizer
-    {
-        /// <summary>
-        /// Default IconLayer stack.
-        /// </summary>
-        private const int IconLayer = 0;
-
-        /// <summary>
-        /// Sprite layers used in stack visualizer. Sprites first in layer correspond to lower stack states
-        /// e.g. <code>_spriteLayers[0]</code> is lower stack level than <code>_spriteLayers[1]</code>.
-        /// </summary>
-        [DataField("stackLayers")] private readonly List<string> _spriteLayers = new();
-
-        /// <summary>
-        /// Determines if the visualizer uses composite or non-composite layers for icons. Defaults to false.
-        ///
-        /// <list type="bullet">
-        /// <item>
-        /// <description>false: they are opaque and mutually exclusive (e.g. sprites in a cable coil). <b>Default value</b></description>
-        /// </item>
-        /// <item>
-        /// <description>true: they are transparent and thus layered one over another in ascending order first</description>
-        /// </item>
-        /// </list>
-        ///
-        /// </summary>
-        [DataField("composite")] private bool _isComposite;
-
-        [DataField("sprite")] private ResPath? _spritePath;
-
-        [Obsolete("Subscribe to your component being initialised instead.")]
-        public override void InitializeEntity(EntityUid entity)
-        {
-            base.InitializeEntity(entity);
-
-            if (_isComposite
-                && _spriteLayers.Count > 0
-                && IoCManager.Resolve<IEntityManager>().TryGetComponent<SpriteComponent?>(entity, out var spriteComponent))
-            {
-                var spritePath = _spritePath ?? spriteComponent.BaseRSI!.Path!;
-
-                foreach (var sprite in _spriteLayers)
-                {
-                    spriteComponent.LayerMapReserveBlank(sprite);
-                    spriteComponent.LayerSetSprite(sprite, new SpriteSpecifier.Rsi(spritePath, sprite));
-                    spriteComponent.LayerSetVisible(sprite, false);
-                }
-            }
-        }
-
-        [Obsolete("Subscribe to AppearanceChangeEvent instead.")]
-        public override void OnChangeData(AppearanceComponent component)
-        {
-            base.OnChangeData(component);
-
-            var entities = IoCManager.Resolve<IEntityManager>();
-            if (entities.TryGetComponent(component.Owner, out SpriteComponent? spriteComponent))
-            {
-                if (_isComposite)
-                {
-                    ProcessCompositeSprites(component, spriteComponent);
-                }
-                else
-                {
-                    ProcessOpaqueSprites(component, spriteComponent);
-                }
-            }
-        }
-
-        private void ProcessOpaqueSprites(AppearanceComponent component, SpriteComponent spriteComponent)
-        {
-            // Skip processing if no actual
-            if (!component.TryGetData<int>(StackVisuals.Actual, out var actual)) return;
-            if (!component.TryGetData<int>(StackVisuals.MaxCount, out var maxCount))
-            {
-                maxCount = _spriteLayers.Count;
-            }
-
-            var activeLayer = ContentHelpers.RoundToEqualLevels(actual, maxCount, _spriteLayers.Count);
-            spriteComponent.LayerSetState(IconLayer, _spriteLayers[activeLayer]);
-        }
-
-        private void ProcessCompositeSprites(AppearanceComponent component, SpriteComponent spriteComponent)
-        {
-            // If hidden, don't render any sprites
-            if (component.TryGetData<bool>(StackVisuals.Hide, out var hide)
-                && hide)
-            {
-                foreach (var transparentSprite in _spriteLayers)
-                {
-                    spriteComponent.LayerSetVisible(transparentSprite, false);
-                }
-
-                return;
-            }
-
-            // Skip processing if no actual/maxCount
-            if (!component.TryGetData<int>(StackVisuals.Actual, out var actual)) return;
-            if (!component.TryGetData<int>(StackVisuals.MaxCount, out var maxCount))
-            {
-                maxCount = _spriteLayers.Count;
-            }
-
-
-            var activeTill = ContentHelpers.RoundToNearestLevels(actual, maxCount, _spriteLayers.Count);
-            for (var i = 0; i < _spriteLayers.Count; i++)
-            {
-                spriteComponent.LayerSetVisible(_spriteLayers[i], i < activeTill);
-            }
-        }
-    }
-}
diff --git a/Content.Client/Storage/Systems/ItemCounterSystem.cs b/Content.Client/Storage/Systems/ItemCounterSystem.cs
new file mode 100644 (file)
index 0000000..605f47d
--- /dev/null
@@ -0,0 +1,70 @@
+using Content.Shared.Rounding;
+using Content.Shared.Stacks;
+using Content.Shared.Storage.Components;
+using Content.Shared.Storage.EntitySystems;
+using Robust.Client.GameObjects;
+using Robust.Shared.Containers;
+
+namespace Content.Client.Storage.Systems;
+
+public sealed class ItemCounterSystem : SharedItemCounterSystem
+{
+    [Dependency] private readonly AppearanceSystem _appearanceSystem = default!;
+
+    public override void Initialize()
+    {
+        base.Initialize();
+        SubscribeLocalEvent<ItemCounterComponent, AppearanceChangeEvent>(OnAppearanceChange);
+    }
+
+    private void OnAppearanceChange(EntityUid uid, ItemCounterComponent comp, ref AppearanceChangeEvent args)
+    {
+        if (args.Sprite == null || comp.LayerStates.Count < 1)
+            return;
+
+        // Skip processing if no actual
+        if (!_appearanceSystem.TryGetData<int>(uid, StackVisuals.Actual, out var actual, args.Component))
+            return;
+
+        if (!_appearanceSystem.TryGetData<int>(uid, StackVisuals.MaxCount, out var maxCount, args.Component))
+            maxCount = comp.LayerStates.Count;
+
+        if (!_appearanceSystem.TryGetData<bool>(uid, StackVisuals.Hide, out var hidden, args.Component))
+            hidden = false;
+        
+        if (comp.IsComposite)
+            ProcessCompositeSprite(uid, actual, maxCount, comp.LayerStates, hidden, sprite: args.Sprite);
+        else
+            ProcessOpaqueSprite(uid, comp.BaseLayer, actual, maxCount, comp.LayerStates, hidden, sprite: args.Sprite);
+    }
+
+    public void ProcessOpaqueSprite(EntityUid uid, string layer, int count, int maxCount, List<string> states, bool hide = false, SpriteComponent? sprite = null)
+    {
+        if (!Resolve(uid, ref sprite)
+        ||  !sprite.LayerMapTryGet(layer, out var layerKey, logError: true))
+            return;
+        
+        var activeState = ContentHelpers.RoundToEqualLevels(count, maxCount, states.Count);
+        sprite.LayerSetState(layerKey, states[activeState]);
+        sprite.LayerSetVisible(layerKey, !hide);
+    }
+
+    public void ProcessCompositeSprite(EntityUid uid, int count, int maxCount, List<string> layers, bool hide = false, SpriteComponent? sprite = null)
+    {
+        if(!Resolve(uid, ref sprite))
+            return;
+        
+        var activeTill = ContentHelpers.RoundToNearestLevels(count, maxCount, layers.Count);
+        for(var i = 0; i < layers.Count; ++i)
+        {
+            sprite.LayerSetVisible(layers[i], !hide && i < activeTill);
+        }
+    }
+
+    protected override int? GetCount(ContainerModifiedMessage msg, ItemCounterComponent itemCounter)
+    {
+        if (_appearanceSystem.TryGetData<int>(msg.Container.Owner, StackVisuals.Actual, out var actual))
+            return actual;
+        return null;
+    }
+}
index 96df85efc0d988fcdef0509db3d2400232f860da..1bd2007f2354da510abc54cde325ec07565a1051 100644 (file)
@@ -38,6 +38,38 @@ namespace Content.Shared.Stacks
 
         [ViewVariables]
         public bool UiUpdateNeeded { get; set; }
+    
+        /// <summary>
+        /// Default IconLayer stack.
+        /// </summary>
+        [DataField("baseLayer")]
+        [ViewVariables(VVAccess.ReadWrite)]
+        public string BaseLayer = "";
+
+        /// <summary>
+        /// Determines if the visualizer uses composite or non-composite layers for icons. Defaults to false.
+        ///
+        /// <list type="bullet">
+        /// <item>
+        /// <description>false: they are opaque and mutually exclusive (e.g. sprites in a cable coil). <b>Default value</b></description>
+        /// </item>
+        /// <item>
+        /// <description>true: they are transparent and thus layered one over another in ascending order first</description>
+        /// </item>
+        /// </list>
+        ///
+        /// </summary>
+        [DataField("composite")]
+        [ViewVariables(VVAccess.ReadWrite)]
+        public bool IsComposite;
+
+        /// <summary>
+        /// Sprite layers used in stack visualizer. Sprites first in layer correspond to lower stack states
+        /// e.g. <code>_spriteLayers[0]</code> is lower stack level than <code>_spriteLayers[1]</code>.
+        /// </summary>
+        [DataField("layerStates")]
+        [ViewVariables(VVAccess.ReadWrite)]
+        public List<string> LayerStates = new();
     }
 
     [Serializable, NetSerializable]
index 3adec11cf9716d7e2b706a113127653b4a206405..40151a502a89291c3e14a76bf5f07bdb53b5ae1f 100644 (file)
@@ -24,5 +24,37 @@ namespace Content.Shared.Storage.Components
 
         [DataField("amount")]
         public int? MaxAmount { get; set; }
+    
+        /// <summary>
+        /// Default IconLayer stack.
+        /// </summary>
+        [DataField("baseLayer")]
+        [ViewVariables(VVAccess.ReadWrite)]
+        public string BaseLayer = "";
+
+        /// <summary>
+        /// Determines if the visualizer uses composite or non-composite layers for icons. Defaults to false.
+        ///
+        /// <list type="bullet">
+        /// <item>
+        /// <description>false: they are opaque and mutually exclusive (e.g. sprites in a cable coil). <b>Default value</b></description>
+        /// </item>
+        /// <item>
+        /// <description>true: they are transparent and thus layered one over another in ascending order first</description>
+        /// </item>
+        /// </list>
+        ///
+        /// </summary>
+        [DataField("composite")]
+        [ViewVariables(VVAccess.ReadWrite)]
+        public bool IsComposite;
+
+        /// <summary>
+        /// Sprite layers used in counter visualizer. Sprites first in layer correspond to lower stack states
+        /// e.g. <code>_spriteLayers[0]</code> is lower stack level than <code>_spriteLayers[1]</code>.
+        /// </summary>
+        [DataField("layerStates")]
+        [ViewVariables(VVAccess.ReadWrite)]
+        public List<string> LayerStates = new();
     }
 }
index b03d9175596994c7570ed09472701b8149d4d2f0..8732134bd6359bd34b488decfe6b820f4feed352 100644 (file)
     sprite: Objects/Misc/6pack.rsi
     layers:
       - state: plastic-thingy
+      - state: 6pack1
+        map: ["6pack1"]
+        visible: false
+      - state: 6pack2
+        map: ["6pack2"]
+        visible: false
+      - state: 6pack3
+        map: ["6pack3"]
+        visible: false
+      - state: 6pack4
+        map: ["6pack4"]
+        visible: false
+      - state: 6pack5
+        map: ["6pack5"]
+        visible: false
+      - state: 6pack6
+        map: ["6pack6"]
+        visible: false
   - type: Item
     size: 6
   - type: Storage
   - type: ItemCounter
     count:
       tags: [Cola]
+    composite: true
+    layerStates:
+    - 6pack1
+    - 6pack2
+    - 6pack3
+    - 6pack4
+    - 6pack5
+    - 6pack6
   - type: Appearance
-    visuals:
-      - type: StackVisualizer
-        composite: true
-        stackLayers:
-          - 6pack1
-          - 6pack2
-          - 6pack3
-          - 6pack4
-          - 6pack5
-          - 6pack6
 
 - type: entity
   parent: DrinkCanBaseFull
index 59a0e0fef5a769ad0053ffa5cb7d2d88085f2a1f..2e306f88219a489c8782f01aeca2c4ce17f0d877 100644 (file)
 
 # Waffles/Pancakes
 
-# Once StackVisualizer is updated you should be able to mix/match stacks of pancakes.
+# Once StackVisuals is updated you should be able to mix/match stacks of pancakes.
 
 - type: entity
   name: pancake
   - type: Stack
     stackType: Pancake
     count: 1
+    composite: true
+    layerStates:
+    - pancakes1
+    - pancakes2
+    - pancakes3
+    - pancakes4
+    - pancakes5
+    - pancakes6
+    - pancakes7
+    - pancakes8
+    - pancakes9
   - type: Sprite
     state: pancakes1
-  # - type: Sprite
-  #   layers:
-  #     - state: plate-small
-  #     - state: pancakes1
+    layers:
+    - state: pancakes1
+      map: ["pancakes1"]
+      visible: false
+    - state: pancakes2
+      map: ["pancakes2"]
+      visible: false
+    - state: pancakes3
+      map: ["pancakes3"]
+      visible: false
+    - state: pancakes4
+      map: ["pancakes4"]
+      visible: false
+    - state: pancakes5
+      map: ["pancakes5"]
+      visible: false
+    - state: pancakes6
+      map: ["pancakes6"]
+      visible: false
+    - state: pancakes7
+      map: ["pancakes7"]
+      visible: false
+    - state: pancakes8
+      map: ["pancakes8"]
+      visible: false
+    - state: pancakes9
+      map: ["pancakes9"]
+      visible: false
   - type: Appearance
-    visuals:
-      - type: StackVisualizer
-        composite: true
-        stackLayers:
-          - pancakes1
-          - pancakes2
-          - pancakes3
-          - pancakes4
-          - pancakes5
-          - pancakes6
-          - pancakes7
-          - pancakes8
-          - pancakes9
 
 - type: entity
   name: blueberry pancake
   - type: Stack
     stackType: Pancake
     count: 1
+    composite: true
+    layerStates:
+    - pancakesbb1
+    - pancakesbb2
+    - pancakesbb3
   - type: Sprite
     state: pancakesbb1
-  # - type: Sprite
-  #   layers:
-  #     - state: plate-small
-  #     - state: pancakesbb1
+    layers:
+    - state: pancakesbb1
+      map: ["pancakesbb1"]
+      visible: false
+    - state: pancakesbb2
+      map: ["pancakesbb2"]
+      visible: false
+    - state: pancakesbb3
+      map: ["pancakesbb3"]
+      visible: false
   - type: Appearance
-    visuals:
-      - type: StackVisualizer
-        composite: true
-        stackLayers:
-          - pancakesbb1
-          - pancakesbb2
-          - pancakesbb3
 
 - type: entity
   name: chocolate chip pancake
   - type: Stack
     stackType: Pancake
     count: 1
+    composite: true
+    layerStates:
+    - pancakescc1
+    - pancakescc2
+    - pancakescc3
   - type: Sprite
     state: pancakescc1
-  # - type: Sprite
-  #   layers:
-  #     - state: plate-small
-  #     - state: pancakescc1
+    layers:
+    - state: pancakescc1
+      map: ["pancakescc1"]
+      visible: false
+    - state: pancakescc2
+      map: ["pancakescc2"]
+      visible: false
+    - state: pancakescc3
+      map: ["pancakescc3"]
+      visible: false
   - type: Appearance
-    visuals:
-      - type: StackVisualizer
-        composite: true
-        stackLayers:
-          - pancakescc1
-          - pancakescc2
-          - pancakescc3
   - type: SolutionContainerManager
     solutions:
       food:
index 0601112ef7d4a71c045b7b7377dc783453278eb6..2a52127b3bebbc73dbdd6d47c9701746108aad55 100644 (file)
@@ -1,7 +1,7 @@
 # Donut
 
 # There is a newer, better version of the donutbox from tgstation included in the
-# donut.rsi. The reason it isn't implemented is it requires a StackVisualizer offsetting
+# donut.rsi. The reason it isn't implemented is it requires a StackVisuals offsetting
 # the layer sprite by a couple pixels everytime a new donut is added. It also requires
 # an alpha color which -Y- said he would implement.
 
     - state: box
     - state: box-open
       map: ["openLayer"]
+      visible: false
+    - state: box1
+      map: ["box1"]
+      visible: false
+    - state: pink-box2
+      map: ["pink-box2"]
+      visible: false
+    - state: box3
+      map: ["box3"]
+      visible: false
+    - state: pink-box4
+      map: ["pink-box4"]
+      visible: false
+    - state: box5
+      map: ["box5"]
+      visible: false
+    - state: pink-box6
+      map: ["pink-box6"]
+      visible: false
   - type: Storage
     capacity: 6
     whitelist:
   - type: ItemCounter
     count:
       tags: [Donut]
+    composite: true
+    layerStates:
+    - box1
+    - pink-box2
+    - box3
+    - pink-box4
+    - box5
+    - pink-box6
   - type: Appearance
-    visuals:
-    - type: StackVisualizer
-      composite: true
-      stackLayers:
-      - box1
-      - pink-box2
-      - box3
-      - pink-box4
-      - box5
-      - pink-box6
 
 # Egg
 
     - state: box-closed
     - state: box-open
       map: ["openLayer"]
+      visible: false
+    - state: box1
+      map: ["box1"]
+      visible: false
+    - state: box2
+      map: ["box2"]
+      visible: false
+    - state: box3
+      map: ["box3"]
+      visible: false
+    - state: box4
+      map: ["box4"]
+      visible: false
+    - state: box5
+      map: ["box5"]
+      visible: false
+    - state: box6
+      map: ["box6"]
+      visible: false
+    - state: box7
+      map: ["box7"]
+      visible: false
+    - state: box8
+      map: ["box8"]
+      visible: false
+    - state: box9
+      map: ["box9"]
+      visible: false
+    - state: box10
+      map: ["box10"]
+      visible: false
+    - state: box11
+      map: ["box11"]
+      visible: false
+    - state: box12
+      map: ["box12"]
+      visible: false
   - type: Storage
     capacity: 12
     whitelist:
   - type: ItemCounter
     count:
       tags: [Egg]
+    composite: true
+    layerStates:
+    - box1
+    - box2
+    - box3
+    - box4
+    - box5
+    - box6
+    - box7
+    - box8
+    - box9
+    - box10
+    - box11
+    - box12
   - type: Appearance
-    visuals:
-    - type: StackVisualizer
-      composite: true
-      stackLayers:
-      - box1
-      - box2
-      - box3
-      - box4
-      - box5
-      - box6
-      - box7
-      - box8
-      - box9
-      - box10
-      - box11
-      - box12
   # Someday...
   # - type: DamageOnLand
   # - type: DamageOtherOnHit
     - state: box
     - state: box-open
       map: ["openLayer"]
+      visible: false
+    - state: box1
+      map: ["box1"]
+      visible: false
+    - state: box2
+      map: ["box2"]
+      visible: false
+    - state: box3
+      map: ["box3"]
+      visible: false
+    - state: box4
+      map: ["box4"]
+      visible: false
+    - state: box5
+      map: ["box5"]
+      visible: false
+    - state: box6
+      map: ["box6"]
+      visible: false
   - type: Storage
     capacity: 6
   - type: Item
   - type: ItemCounter
     count:
       tags: [Nugget]
+    composite: true
+    layerStates:
+    - box1
+    - box2
+    - box3
+    - box4
+    - box5
+    - box6
   - type: Appearance
-    visuals:
-    - type: StackVisualizer
-      composite: true
-      stackLayers:
-      - box1
-      - box2
-      - box3
-      - box4
-      - box5
-      - box6
 
 # Donkpocket
 
index 49c25a54b5e44972d1926c52e0b5f3db876390f8..693a24452ce462dbf3e8168159c7aa0ba02d0ab6 100644 (file)
     - state: closed
     - state: open
       map: ["openLayer"]
+      visible: false
+    - state: cig1
+      map: ["cig1"]
+      sprite: Objects/Consumable/Smokeables/Cigarettes/Packs/visualizer.rsi
+      visible: false
+    - state: cig2
+      map: ["cig2"]
+      sprite: Objects/Consumable/Smokeables/Cigarettes/Packs/visualizer.rsi
+      visible: false
+    - state: cig3
+      map: ["cig3"]
+      sprite: Objects/Consumable/Smokeables/Cigarettes/Packs/visualizer.rsi
+      visible: false
+    - state: cig4
+      map: ["cig4"]
+      sprite: Objects/Consumable/Smokeables/Cigarettes/Packs/visualizer.rsi
+      visible: false
+    - state: cig5
+      map: ["cig5"]
+      sprite: Objects/Consumable/Smokeables/Cigarettes/Packs/visualizer.rsi
+      visible: false
+    - state: cig6
+      map: ["cig6"]
+      sprite: Objects/Consumable/Smokeables/Cigarettes/Packs/visualizer.rsi
+      visible: false
   - type: Tag
     tags:
     - CigPack
   - type: ItemCounter
     count:
       tags: [Cigarette]
+    composite: true
+    layerStates:
+    - cig1
+    - cig2
+    - cig3
+    - cig4
+    - cig5
+    - cig6
   - type: Appearance
-    visuals:
-    - type: StackVisualizer
-      sprite: Objects/Consumable/Smokeables/Cigarettes/Packs/visualizer.rsi
-      composite: true
-      stackLayers:
-      - cig1
-      - cig2
-      - cig3
-      - cig4
-      - cig5
-      - cig6
 
 - type: entity
   id: CigPackGreen
index b3607ec794c9c354f6fc19888b4b6eef2c591432..f58e5ee6cf6632c970d9045ac3174ba166856aab 100644 (file)
     - state: closed
     - state: open
       map: ["openLayer"]
+    - state: cigar1
+      map: ["cigar1"]
+      visible: false
+    - state: cigar2
+      map: ["cigar2"]
+      visible: false
+    - state: cigar3
+      map: ["cigar3"]
+      visible: false
+    - state: cigar4
+      map: ["cigar4"]
+      visible: false
+    - state: cigar5
+      map: ["cigar5"]
+      visible: false
+    - state: cigar6
+      map: ["cigar6"]
+      visible: false
+    - state: cigar7
+      map: ["cigar7"]
+      visible: false
+    - state: cigar8
+      map: ["cigar8"]
+      visible: false
   - type: Storage
     capacity: 8
   - type: Item
   - type: ItemCounter
     count:
       tags: [Cigar]
+    composite: true
+    layerStates:
+    - cigar1
+    - cigar2
+    - cigar3
+    - cigar4
+    - cigar5
+    - cigar6
+    - cigar7
+    - cigar8
   - type: Appearance
-    visuals:
-    - type: StackVisualizer
-      composite: true
-      stackLayers:
-      - cigar1
-      - cigar2
-      - cigar3
-      - cigar4
-      - cigar5
-      - cigar6
-      - cigar7
-      - cigar8
 
 - type: entity
   id: CigarGoldCase
index 556f5bcb26a39e858a60cf45fd4bb289c20ae9ca..a3f62811716d2acf9a832cd8972cbf8e43ab6807 100644 (file)
       Glass: 100
   - type: Stack
     stackType: Glass
+    baseLayer: base
+    layerStates:
+    - glass
+    - glass_2
+    - glass_3
   - type: Sprite
     state: glass_3
+    layers:
+    - state: glass_3
+      map: ["base"]
   - type: Item
     heldPrefix: glass
   - type: Appearance
-    visuals:
-    - type: StackVisualizer
-      stackLayers:
-      - glass
-      - glass_2
-      - glass_3
   - type: FloorTile
     outputs:
     - FloorGlass
       ReinforcedGlass: 100
   - type: Stack
     stackType: ReinforcedGlass
+    baseLayer: base
+    layerStates:
+    - rglass
+    - rglass_2
+    - rglass_3
   - type: Sprite
     state: rglass_3
+    layers:
+    - state: rglass_3
+      map: ["base"]
   - type: Item
     heldPrefix: rglass
   - type: Appearance
-    visuals:
-    - type: StackVisualizer
-      stackLayers:
-      - rglass
-      - rglass_2
-      - rglass_3
   - type: FloorTile
     outputs:
     - FloorRGlass
       PlasmaGlass: 100
   - type: Stack
     stackType: PlasmaGlass
+    baseLayer: base
+    layerStates:
+    - pglass
+    - pglass_2
+    - pglass_3
   - type: Sprite
     state: pglass_3
+    layers:
+    - state: pglass_3
+      map: ["base"]
   - type: Item
     heldPrefix: pglass
   - type: Appearance
-    visuals:
-    - type: StackVisualizer
-      stackLayers:
-      - pglass
-      - pglass_2
-      - pglass_3
   - type: Construction
     graph: Glass
     node: SheetPGlass
       ReinforcedPlasmaGlass: 100
   - type: Stack
     stackType: ReinforcedPlasmaGlass
+    baseLayer: base
+    layerStates:
+    - rpglass
+    - rpglass_2
+    - rpglass_3
   - type: Sprite
     state: rpglass_3
+    layers:
+    - state: rpglass_3
+      map: ["base"]
   - type: Item
     heldPrefix: rpglass
   - type: Appearance
-    visuals:
-    - type: StackVisualizer
-      stackLayers:
-      - rpglass
-      - rpglass_2
-      - rpglass_3
   - type: Construction
     graph: Glass
     node: SheetRPGlass
       UraniumGlass: 100
   - type: Stack
     stackType: UraniumGlass
+    baseLayer: base
+    layerStates:
+    - uglass
+    - uglass_2
+    - uglass_3
   - type: Sprite
     state: uglass_3
+    layers:
+    - state: uglass_3
+      map: ["base"]
   - type: Item
     heldPrefix: uglass
   - type: Appearance
-    visuals:
-    - type: StackVisualizer
-      stackLayers:
-      - uglass
-      - uglass_2
-      - uglass_3
   - type: Construction
     graph: Glass
     node: SheetUGlass
       ReinforcedUraniumGlass: 100
   - type: Stack
     stackType: ReinforcedUraniumGlass
+    baseLayer: base
+    layerStates:
+    - ruglass
+    - ruglass_2
+    - ruglass_3
   - type: Sprite
     state: ruglass_3
+    layers:
+    - state: ruglass_3
+      map: ["base"]
   - type: Item
     heldPrefix: ruglass
   - type: Appearance
-    visuals:
-    - type: StackVisualizer
-      stackLayers:
-      - ruglass
-      - ruglass_2
-      - ruglass_3
   - type: Construction
     graph: Glass
     node: SheetRUGlass
index cf26b9523bc551d0f003c10ef33be154928d9a35..bac810b02f3b5052b9b7118965b1cf90911906ff 100644 (file)
       Steel: 100
   - type: Stack
     stackType: Steel
+    baseLayer: base
+    layerStates:
+    - steel
+    - steel_2
+    - steel_3
   - type: Sprite
     state: steel_3
+    layers:
+    - state: plasteel_3
+      map: ["base"]
   - type: Item
     heldPrefix: steel
   - type: Appearance
-    visuals:
-    - type: StackVisualizer
-      stackLayers:
-      - steel
-      - steel_2
-      - steel_3
   - type: FloorTile
     outputs:
     - Plating
       Plasteel: 100
   - type: Stack
     stackType: Plasteel
+    baseLayer: base
+    layerStates:
+    - plasteel
+    - plasteel_2
+    - plasteel_3
   - type: Sprite
     state: plasteel_3
+    layers:
+    - state: plasteel_3
+      map: ["base"]
   - type: Item
     heldPrefix: plasteel
   - type: Appearance
-    visuals:
-    - type: StackVisualizer
-      stackLayers:
-      - plasteel
-      - plasteel_2
-      - plasteel_3
 
 - type: entity
   parent: SheetPlasteel
index d55c143656a7f2fb0b6c184a3b86772da16437dc..50725ecdb2a4c06ce6083fc75d186c8b4b003718 100644 (file)
   components:
   - type: Stack
     stackType: Paper
+    baseLayer: base
+    layerStates:
+    - paper
+    - paper_2
+    - paper_3
   - type: Sprite
     state: paper_3
+    layers:
+    - state: paper_3
+      map: ["base"]
   - type: Item
     heldPrefix: paper
   - type: Appearance
-    visuals:
-    - type: StackVisualizer
-      stackLayers:
-      - paper
-      - paper_2
-      - paper_3
 
 - type: entity
   parent: SheetPaper
       Plasma: 100
   - type: Stack
     stackType: Plasma
+    baseLayer: base
+    layerStates:
+    - plasma
+    - plasma_2
+    - plasma_3
   - type: Sprite
     state: plasma_3
+    layers:
+    - state: plasma_3
+      map: ["base"]
   - type: Item
     heldPrefix: plasma
   - type: Appearance
-    visuals:
-    - type: StackVisualizer
-      stackLayers:
-      - plasma
-      - plasma_2
-      - plasma_3
   - type: Extractable
     grindableSolutionName: plasma
   - type: SolutionContainerManager
       Plastic: 100
   - type: Stack
     stackType: Plastic
+    baseLayer: base
+    layerStates:
+    - plastic
+    - plastic_2
+    - plastic_3
   - type: Sprite
     state: plastic_3
+    layers:
+    - state: plastic_3
+      map: ["base"]
   - type: Item
     heldPrefix: plastic
   - type: Appearance
-    visuals:
-    - type: StackVisualizer
-      stackLayers:
-      - plastic
-      - plastic_2
-      - plastic_3
 
 - type: entity
   parent: SheetPlastic
       Uranium: 100
   - type: Stack
     stackType: Uranium
+    baseLayer: base
+    layerStates:
+    - uranium
+    - uranium_2
+    - uranium_3
   - type: Sprite
     state: uranium_3
+    layers:
+    - state: uranium_3
+      map: ["base"]
   - type: Appearance
-    visuals:
-    - type: StackVisualizer
-      stackLayers:
-      - uranium
-      - uranium_2
-      - uranium_3
   - type: Item
     heldPrefix: uranium
   - type: Extractable
index 1066fcb024597358e1fe820408c9642661b4a193..877efc2de4bd32424eb5d76244834dd216d6954c 100644 (file)
       Gold: 100
   - type: Stack
     stackType: Gold
+    baseLayer: base
+    layerStates:
+    - gold
+    - gold_2
+    - gold_3
   - type: Sprite
     state: gold_3
+    layers:
+    - state: gold_3
+      map: ["base"]
   - type: Item
     heldPrefix: gold
   - type: Appearance
-    visuals:
-    - type: StackVisualizer
-      stackLayers:
-      - gold
-      - gold_2
-      - gold_3
 
 - type: entity
   parent: IngotGold
       Silver: 100
   - type: Stack
     stackType: Silver
+    baseLayer: base
+    layerStates:
+    - silver
+    - silver_2
+    - silver_3
   - type: Sprite
     state: silver_3
+    layers:
+    - state: silver_3
+      map: ["base"]
   - type: Item
     heldPrefix: silver
   - type: Appearance
-    visuals:
-    - type: StackVisualizer
-      stackLayers:
-      - silver
-      - silver_2
-      - silver_3
 
 - type: entity
   parent: IngotSilver
index 4369b15928d4573fe3154825d189d8398b6be9bc..a306238ef4252ab2049a3aa56769b30d29ad36fd 100644 (file)
       Cardboard: 100
   - type: Stack
     stackType: Cardboard
+    baseLayer: base
+    layerStates:
+    - cardboard
+    - cardboard_2
+    - cardboard_3
   - type: Sprite
     state: cardboard_3
+    layers:
+    - state: cardboard_3
+      map: ["base"]
   - type: Appearance
-    visuals:
-    - type: StackVisualizer
-      stackLayers:
-      - cardboard
-      - cardboard_2
-      - cardboard_3
 
 - type: entity
   parent: MaterialCardboard
       path: "/Audio/Items/Medical/brutepack_end.ogg"
   - type: Stack
     stackType: Cloth
+    baseLayer: base
+    layerStates:
+    - cloth
+    - cloth_2
+    - cloth_3
   - type: Material
   - type: PhysicalComposition
     materialComposition:
         Quantity: 3
   - type: Sprite
     state: cloth_3
+    layers:
+    - state: cloth_3
+      map: ["base"]
   - type: Appearance
-    visuals:
-    - type: StackVisualizer
-      stackLayers:
-      - cloth
-      - cloth_2
-      - cloth_3
 
 - type: entity
   parent: MaterialCloth
   components:
   - type: Stack
     stackType: Durathread
+    baseLayer: base
+    layerStates:
+    - durathread
+    - durathread_2
+    - durathread_3
   - type: Material
   - type: PhysicalComposition
     materialComposition:
       Durathread: 100
   - type: Sprite
     state: durathread_3
+    layers:
+    - state: durathread_3
+      map: ["base"]
   - type: Appearance
-    visuals:
-    - type: StackVisualizer
-      stackLayers:
-      - durathread
-      - durathread_2
-      - durathread_3
   - type: Construction
     graph: Durathread
     node: MaterialDurathread
       Wood: 100
   - type: Stack
     stackType: WoodPlank
+    baseLayer: base
+    layerStates:
+    - wood
+    - wood_2
+    - wood_3
   - type: Sprite
     state: wood
+    layers:
+    - state: wood
+      map: ["base"]
   - type: Appearance
-    visuals:
-    - type: StackVisualizer
-      stackLayers:
-      - wood
-      - wood_2
-      - wood_3
   - type: Item
     heldPrefix: wood
 
   components:
   - type: Stack
     stackType: Cotton
+    baseLayer: base
+    layerStates:
+    - cotton
+    - cotton_2
+    - cotton_3
   - type: Sprite
     state: cotton_3
+    layers:
+    - state: cotton_3
+      map: ["base"]
   - type: Appearance
-    visuals:
-      - type: StackVisualizer
-        stackLayers:
-          - cotton
-          - cotton_2
-          - cotton_3
 
 - type: entity
   parent: MaterialCotton
       Bananium: 150
   - type: Sprite
     state: bananium_1
+    layers:
+    - state: bananium_1
+      map: ["base"]
   - type: Stack
     stackType: Bananium
     count: 10
+    baseLayer: base
+    layerStates:
+      - bananium
+      - bananium_1
   - type: RadiationSource
     intensity: 0.3
   - type: FlavorProfile
       - ReagentId: Honk
         Quantity: 5
   - type: Appearance
-    visuals:
-      - type: StackVisualizer
-        stackLayers:
-          - bananium
-          - bananium_1
 
 - type: entity
   parent: MaterialBananium
index b629352d47e0b46d26ae1b015161730ecbfc77dc..c86bcdce9655b5d7e91e8abc8ee58c06ccd2045b 100644 (file)
   components:
   - type: Stack
     stackType: MetalRod
+    baseLayer: base
+    layerStates:
+    - rods
+    - rods_2
+    - rods_3
+    - rods_4
+    - rods_5
   - type: Sprite
     state: rods_5
+    layers:
+    - state: rods_5
+      map: ["base"]
 #  - type: Item
 #    heldPrefix: rods
   - type: Construction
     graph: MetalRod
     node: MetalRod
   - type: Appearance
-    visuals:
-    - type: StackVisualizer
-      stackLayers:
-      - rods
-      - rods_2
-      - rods_3
-      - rods_4
-      - rods_5
   - type: FloorTile
     outputs:
     - Lattice
index b034a692364ddc5a61235b7087762dc1e054f1f5..369faba4e91ce39af03122fb90c1e515a5373fe2 100644 (file)
   - type: Stack
     stackType: Credit
     count: 1
+    baseLayer: base
+    layerStates:
+    - cash
+    - cash_10
+    - cash_100
+    - cash_500
+    - cash_1000
+    - cash_1000000
   - type: Sprite
     sprite: Objects/Economy/cash.rsi
     netsync: false
     state: cash
+    layers:
+    - state: cash
+      map: ["base"]
   - type: Physics
     bodyType: Dynamic
   - type: Fixtures
         mask:
         - ItemMask
   - type: Appearance
-    visuals:
-    - type: StackVisualizer
-      # TODO: This won't work because stackvisualizer works based off of an even count and not denominations.
-      # Ideally we'd just be able to specify at what count does the new layer take place e.g.
-      # - 10: cash_10
-      # - 100: cash_100
-      stackLayers:
-      - cash
-      - cash_10
-      - cash_100
-      - cash_500
-      - cash_1000
-      - cash_1000000
 
 - type: material
   id: Credit
index 4c0dd0133051678e008db1e9fe794342c68d5666..eb258034c0c246631bb2c20985c446baf4722690 100644 (file)
   components:
   - type: Stack
     stackType: CableHV
+    baseLayer: base
+    layerStates:
+    - coilhv-10
+    - coilhv-20
+    - coilhv-30
   - type: Sprite
     state: coilhv-30
+    layers:
+    - state: coilhv-30
+      map: ["base"]
   - type: Item
     heldPrefix: coilhv
   - type: CablePlacer
     cablePrototypeID: CableHV
     blockingWireType: HighVoltage
   - type: Appearance
-    visuals:
-      - type: StackVisualizer
-        stackLayers:
-          - coilhv-10
-          - coilhv-20
-          - coilhv-30
 
 - type: entity
   parent: CableHVStack
   components:
   - type: Stack
     stackType: CableMV
+    baseLayer: base
+    layerStates:
+    - coilmv-10
+    - coilmv-20
+    - coilmv-30
   - type: Sprite
     state: coilmv-30
+    layers:
+    - state: coilmv-30
+      map: ["base"]
   - type: Item
     heldPrefix: coilmv
   - type: CablePlacer
     cablePrototypeID: CableMV
     blockingWireType: MediumVoltage
   - type: Appearance
-    visuals:
-      - type: StackVisualizer
-        stackLayers:
-          - coilmv-10
-          - coilmv-20
-          - coilmv-30
 
 - type: entity
   parent: CableMVStack
   components:
   - type: Sprite
     state: coillv-30
+    layers:
+    - state: coillv-30
+      map: ["base"]
   - type: Item
     heldPrefix: coillv
+  - type: Stack
+    baseLayer: base
+    layerStates:
+    - coillv-10
+    - coillv-20
+    - coillv-30
   - type: CablePlacer
     cablePrototypeID: CableApcExtension
     blockingWireType: Apc
   - type: Appearance
-    visuals:
-      - type: StackVisualizer
-        stackLayers:
-          - coillv-10
-          - coillv-20
-          - coillv-30
 
 - type: entity
   parent: CableApcStack
index beb074766590d408735d493703d946738fa8f4e4..ef32ab913c1060ae57a3736adeb733d3587f9bd7 100644 (file)
     - type: Tag
       tags:
         - DroneUsable
-#    - type: Appearance # TODO: Add stack sprites
-#      visuals:
-#        - type: StackVisualizer
-#          stackLayers:
-#            - coillv-10
-#            - coillv-20
-#            - coillv-30
+# TODO: Add stack sprites + visuals.
 
 - type: entity
   id: InflatableDoorStack
@@ -56,6 +50,7 @@
     - type: Tag
       tags:
         - DroneUsable
+# TODO: Add stack sprites + visuals.
 
 - type: entity
   parent: InflatableWallStack
index 0097cfa053575cfc89c244f36c5c9b5306fc32f9..cc2ef078a53fddb6fd503c665c87d3abc2024710 100644 (file)
     - state: matchbox
     - state: matchbox-open
       map: ["openLayer"]
+    - state: matchbox1
+      map: ["matchbox1"]
+      visible: false
+    - state: matchbox2
+      map: ["matchbox2"]
+      visible: false
+    - state: matchbox3
+      map: ["matchbox3"]
+      visible: false
   - type: Item
     sprite: Objects/Tools/matches.rsi
     heldPrefix: matchbox
   - type: ItemCounter
     count:
       tags: [Matchstick]
+    composite: true
+    layerStates:
+    - matchbox1
+    - matchbox2
+    - matchbox3
   - type: Appearance
-    visuals:
-    - type: StackVisualizer
-      composite: true
-      stackLayers:
-        - matchbox1
-        - matchbox2
-        - matchbox3
   - type: Tag
     tags:
     - Trash