]> git.smokeofanarchy.ru Git - space-station-14.git/commitdiff
Makes Eyepatches Flippable (#26277)
authorCojoke <83733158+Cojoke-dot@users.noreply.github.com>
Mon, 17 Jun 2024 03:21:29 +0000 (22:21 -0500)
committerGitHub <noreply@github.com>
Mon, 17 Jun 2024 03:21:29 +0000 (23:21 -0400)
Content.Client/Clothing/ClientClothingSystem.cs
Content.Client/Clothing/FlippableClothingVisualizerSystem.cs [new file with mode: 0644]
Content.Client/Clothing/FlippableClothingVisualsComponent.cs [new file with mode: 0644]
Content.Client/Sprite/RandomSpriteSystem.cs
Content.Shared/Clothing/Components/ClothingComponent.cs
Content.Shared/Clothing/EntitySystems/ClothingSystem.cs
Content.Shared/Clothing/EntitySystems/FoldableClothingSystem.cs
Resources/Prototypes/Entities/Clothing/Eyes/base_clothingeyes.yml
Resources/Prototypes/Entities/Clothing/Eyes/hud.yml
Resources/Prototypes/Entities/Clothing/Eyes/misc.yml

index dd69521f483819da7c1d2969622d06b96e4f8bf5..1c0d831226db73cf2e141dd23daa47b0964f892f 100644 (file)
@@ -1,5 +1,6 @@
 using System.Diagnostics.CodeAnalysis;
 using System.Linq;
+using System.Numerics;
 using Content.Client.Inventory;
 using Content.Shared.Clothing;
 using Content.Shared.Clothing.Components;
@@ -113,6 +114,7 @@ public sealed class ClientClothingSystem : ClothingSystem
                 i++;
             }
 
+            item.MappedLayer = key;
             args.Layers.Add((key, layer));
         }
     }
@@ -153,13 +155,9 @@ public sealed class ClientClothingSystem : ClothingSystem
 
         // species specific
         if (speciesId != null && rsi.TryGetState($"{state}-{speciesId}", out _))
-        {
             state = $"{state}-{speciesId}";
-        }
         else if (!rsi.TryGetState(state, out _))
-        {
             return false;
-        }
 
         var layer = new PrototypeLayerData();
         layer.RsiPath = rsi.Path.ToString();
@@ -287,6 +285,8 @@ public sealed class ClientClothingSystem : ClothingSystem
 
                 if (layerData.Color != null)
                     sprite.LayerSetColor(key, layerData.Color.Value);
+                if (layerData.Scale != null)
+                    sprite.LayerSetScale(key, layerData.Scale.Value);
             }
             else
                 index = sprite.LayerMapReserveBlank(key);
diff --git a/Content.Client/Clothing/FlippableClothingVisualizerSystem.cs b/Content.Client/Clothing/FlippableClothingVisualizerSystem.cs
new file mode 100644 (file)
index 0000000..2c3afb0
--- /dev/null
@@ -0,0 +1,48 @@
+using Content.Shared.Clothing;
+using Content.Shared.Clothing.Components;
+using Content.Shared.Clothing.EntitySystems;
+using Content.Shared.Foldable;
+using Content.Shared.Item;
+using Robust.Client.GameObjects;
+
+namespace Content.Client.Clothing;
+
+public sealed class FlippableClothingVisualizerSystem  : VisualizerSystem<FlippableClothingVisualsComponent>
+{
+    [Dependency] private readonly SharedItemSystem _itemSys = default!;
+
+    public override void Initialize()
+    {
+        base.Initialize();
+
+        SubscribeLocalEvent<FlippableClothingVisualsComponent, GetEquipmentVisualsEvent>(OnGetVisuals, after: [typeof(ClothingSystem)]);
+        SubscribeLocalEvent<FlippableClothingVisualsComponent, FoldedEvent>(OnFolded);
+    }
+
+    private void OnFolded(Entity<FlippableClothingVisualsComponent> ent, ref FoldedEvent args)
+    {
+        _itemSys.VisualsChanged(ent);
+    }
+
+    private void OnGetVisuals(Entity<FlippableClothingVisualsComponent> ent, ref GetEquipmentVisualsEvent args)
+    {
+        if (!TryComp(ent, out SpriteComponent? sprite) ||
+            !TryComp(ent, out ClothingComponent? clothing))
+            return;
+
+        if (clothing.MappedLayer == null ||
+            !AppearanceSystem.TryGetData<bool>(ent, FoldableSystem.FoldedVisuals.State, out var folding) ||
+            !sprite.LayerMapTryGet(folding ? ent.Comp.FoldingLayer : ent.Comp.UnfoldingLayer, out var idx))
+            return;
+
+        // add each layer to the visuals
+        var spriteLayer = sprite[idx];
+        foreach (var layer in args.Layers)
+        {
+            if (layer.Item1 != clothing.MappedLayer)
+                continue;
+
+            layer.Item2.Scale = spriteLayer.Scale;
+        }
+    }
+}
diff --git a/Content.Client/Clothing/FlippableClothingVisualsComponent.cs b/Content.Client/Clothing/FlippableClothingVisualsComponent.cs
new file mode 100644 (file)
index 0000000..33d622b
--- /dev/null
@@ -0,0 +1,16 @@
+namespace Content.Client.Clothing;
+
+/// <summary>
+/// Communicates folded layers data (currently only Scale to handle flipping)
+/// to the wearer clothing sprite layer
+/// </summary>
+[RegisterComponent]
+[Access(typeof(FlippableClothingVisualizerSystem))]
+public sealed partial class FlippableClothingVisualsComponent : Component
+{
+    [DataField]
+    public string FoldingLayer = "foldedLayer";
+
+    [DataField]
+    public string UnfoldingLayer = "unfoldedLayer";
+}
index b9be2a44b42d5aa3550bd6dbfd86bfe67f5078fc..c4aa43a65bc4bc040acf2f4e8ac28816f31d1e24 100644 (file)
@@ -43,9 +43,6 @@ public sealed class RandomSpriteSystem : SharedRandomSpriteSystem
         if (!Resolve(uid, ref clothing, false))
             return;
 
-        if (clothing.ClothingVisuals == null)
-            return;
-
         foreach (var slotPair in clothing.ClothingVisuals)
         {
             foreach (var keyColorPair in component.Selected)
index 6d7226e767daf740d4c704841ed112a114fd1240..846a78b8680c34a5dc76c5fe0cd4d72d9811ecf7 100644 (file)
@@ -16,9 +16,14 @@ namespace Content.Shared.Clothing.Components;
 public sealed partial class ClothingComponent : Component
 {
     [DataField("clothingVisuals")]
-    [Access(typeof(ClothingSystem), typeof(InventorySystem), Other = AccessPermissions.ReadExecute)] // TODO remove execute permissions.
     public Dictionary<string, List<PrototypeLayerData>> ClothingVisuals = new();
 
+    /// <summary>
+    /// The name of the layer in the user that this piece of clothing will map to
+    /// </summary>
+    [DataField]
+    public string? MappedLayer;
+
     [ViewVariables(VVAccess.ReadWrite)]
     [DataField("quickEquip")]
     public bool QuickEquip = true;
@@ -121,4 +126,3 @@ public sealed partial class ClothingUnequipDoAfterEvent : DoAfterEvent
 
     public override DoAfterEvent Clone() => this;
 }
-
index 1e2825a49a5b26da93e9e92b1562e661d20321d7..bdcb2c8204267ede4a25dcc7e4f037be34814a5d 100644 (file)
@@ -241,9 +241,6 @@ public abstract class ClothingSystem : EntitySystem
 
     public void SetLayerColor(ClothingComponent clothing, string slot, string mapKey, Color? color)
     {
-        if (clothing.ClothingVisuals == null)
-            return;
-
         foreach (var layer in clothing.ClothingVisuals[slot])
         {
             if (layer.MapKeys == null)
@@ -257,9 +254,6 @@ public abstract class ClothingSystem : EntitySystem
     }
     public void SetLayerState(ClothingComponent clothing, string slot, string mapKey, string state)
     {
-        if (clothing.ClothingVisuals == null)
-            return;
-
         foreach (var layer in clothing.ClothingVisuals[slot])
         {
             if (layer.MapKeys == null)
index 27ea168018873163a567492a5f13ba50298a40d4..be55588ddd57e88d215b40389ef7cfd170db7cbb 100644 (file)
@@ -33,32 +33,32 @@ public sealed class FoldableClothingSystem : EntitySystem
 
     private void OnFolded(Entity<FoldableClothingComponent> ent, ref FoldedEvent args)
     {
-        if (TryComp<ClothingComponent>(ent.Owner, out var clothingComp) &&
-            TryComp<ItemComponent>(ent.Owner, out var itemComp))
+        if (!TryComp<ClothingComponent>(ent.Owner, out var clothingComp) ||
+            !TryComp<ItemComponent>(ent.Owner, out var itemComp))
+            return;
+
+        if (args.IsFolded)
         {
-            if (args.IsFolded)
-            {
-                if (ent.Comp.FoldedSlots.HasValue)
-                    _clothingSystem.SetSlots(ent.Owner, ent.Comp.FoldedSlots.Value, clothingComp);
+            if (ent.Comp.FoldedSlots.HasValue)
+                _clothingSystem.SetSlots(ent.Owner, ent.Comp.FoldedSlots.Value, clothingComp);
 
-                if (ent.Comp.FoldedEquippedPrefix != null)
-                    _clothingSystem.SetEquippedPrefix(ent.Owner, ent.Comp.FoldedEquippedPrefix, clothingComp);
+            if (ent.Comp.FoldedEquippedPrefix != null)
+                _clothingSystem.SetEquippedPrefix(ent.Owner, ent.Comp.FoldedEquippedPrefix, clothingComp);
 
-                if (ent.Comp.FoldedHeldPrefix != null)
-                    _itemSystem.SetHeldPrefix(ent.Owner, ent.Comp.FoldedHeldPrefix, false, itemComp);
-            }
-            else
-            {
-                if (ent.Comp.UnfoldedSlots.HasValue)
-                    _clothingSystem.SetSlots(ent.Owner, ent.Comp.UnfoldedSlots.Value, clothingComp);
+            if (ent.Comp.FoldedHeldPrefix != null)
+                _itemSystem.SetHeldPrefix(ent.Owner, ent.Comp.FoldedHeldPrefix, false, itemComp);
+        }
+        else
+        {
+            if (ent.Comp.UnfoldedSlots.HasValue)
+                _clothingSystem.SetSlots(ent.Owner, ent.Comp.UnfoldedSlots.Value, clothingComp);
 
-                if (ent.Comp.FoldedEquippedPrefix != null)
-                    _clothingSystem.SetEquippedPrefix(ent.Owner, null, clothingComp);
+            if (ent.Comp.FoldedEquippedPrefix != null)
+                _clothingSystem.SetEquippedPrefix(ent.Owner, null, clothingComp);
 
-                if (ent.Comp.FoldedHeldPrefix != null)
-                    _itemSystem.SetHeldPrefix(ent.Owner, null, false, itemComp);
+            if (ent.Comp.FoldedHeldPrefix != null)
+                _itemSystem.SetHeldPrefix(ent.Owner, null, false, itemComp);
 
-            }
         }
     }
 }
index 10f265a4a2c66e07ea2550392768f583e3a23f8c..b31f821629dd27c449e18de30cace8349d88ebc6 100644 (file)
   - type: Item
     size: Small
     storedRotation: -90
+
+- type: entity
+  parent: [ClothingEyesBase, BaseFoldable]
+  id: ClothingHeadEyeBaseFlippable
+  abstract: true
+  components:
+  - type: Appearance
+  - type: FlippableClothingVisuals
+  - type: Foldable
+    canFoldInsideContainer: true
+    unfoldVerbText: fold-flip-verb
+    foldVerbText: fold-flip-verb
+  - type: FoldableClothing
+  - type: Sprite
+    layers:
+    - map: [ "unfoldedLayer" ]
+      state: icon
+    - map: ["foldedLayer"]
+      state: icon
+      visible: false
+      scale: -1,1
+
+- type: entity
+  parent: ClothingHeadEyeBaseFlippable
+  id: ClothingHeadEyeBaseFlipped
+  suffix: flipped
+  abstract: true
+  components:
+  - type: Foldable
+    folded: true
+  - type: Sprite
+    layers:
+    - map: [ "unfoldedLayer" ]
+      state: icon
+      visible: false
+    - map: ["foldedLayer"]
+      state: icon
+      visible: true
+      scale: -1,1
index c74a60e8fc450a1e580a2c396d199a1f754da40b..0c7fc5b2a1fca47fd0b1926c3f04a4af7b55bb88 100644 (file)
   suffix: Syndicate
 
 - type: entity
-  parent: ClothingEyesHudMedical
+  parent: [ClothingEyesHudMedical, ClothingHeadEyeBaseFlippable]
   id: ClothingEyesEyepatchHudMedical
   name: medical hud eyepatch
   description: A heads-up display that scans the humanoids in view and provides accurate data about their health status. For true patriots.
     sprite: Clothing/Eyes/Hud/medpatch.rsi
 
 - type: entity
-  parent: ClothingEyesHudSecurity
+  parent: [ClothingEyesEyepatchHudMedical, ClothingHeadEyeBaseFlipped]
+  id: ClothingEyesEyepatchHudMedicalFlipped
+  name: medical hud eyepatch
+
+- type: entity
+  parent: [ClothingEyesHudSecurity, ClothingHeadEyeBaseFlippable]
   id: ClothingEyesEyepatchHudSecurity
   name: security hud eyepatch
   description: A heads-up display that scans the humanoids in view and provides accurate data about their ID status and security records. For true patriots.
     sprite: Clothing/Eyes/Hud/secpatch.rsi
 
 - type: entity
-  parent: ClothingEyesHudBeer
+  parent: [ClothingEyesEyepatchHudSecurity,  ClothingHeadEyeBaseFlipped]
+  id: ClothingEyesEyepatchHudSecurityFlipped
+  name: security hud eyepatch
+
+- type: entity
+  parent: [ClothingEyesHudBeer, ClothingHeadEyeBaseFlippable]
   id: ClothingEyesEyepatchHudBeer
   name: beer hud eyepatch
   description: A pair of sunHud outfitted with apparatus to scan reagents, as well as providing an innate understanding of liquid viscosity while in motion. For true patriots.
     sprite: Clothing/Eyes/Hud/beerpatch.rsi
 
 - type: entity
-  parent: ClothingEyesBase
+  parent: [ClothingEyesEyepatchHudBeer, ClothingHeadEyeBaseFlipped]
+  id: ClothingEyesEyepatchHudBeerFlipped
+  name: beer hud eyepatch
+
+- type: entity
+  parent: [ClothingEyesHudDiagnostic, ClothingHeadEyeBaseFlippable]
   id: ClothingEyesEyepatchHudDiag
   name: diagnostic hud eyepatch
   description: A heads-up display capable of analyzing the integrity and status of robotics and exosuits. Made out of see-borg-ium.
     sprite: Clothing/Eyes/Hud/diagpatch.rsi
   - type: Clothing
     sprite: Clothing/Eyes/Hud/diagpatch.rsi
-  - type: ShowHealthBars
-    damageContainers:
-    - Inorganic
-    - Silicon
+
+- type: entity
+  parent: [ClothingEyesEyepatchHudDiag, ClothingHeadEyeBaseFlipped]
+  id: ClothingEyesEyepatchHudDiagFlipped
+  name: diagnostic hud eyepatch
index 06ff3471727f556a1d28eeef0456887e0add4982..075ccae1c49d808d69bb32a5014f05f9884d48fb 100644 (file)
@@ -1,16 +1,3 @@
-- type: entity
-  parent: ClothingEyesBase
-  id: ClothingEyesEyepatch
-  name: eyepatch
-  description: Yarr.
-  components:
-  - type: Sprite
-    sprite: Clothing/Eyes/Misc/eyepatch.rsi
-  - type: Clothing
-    sprite: Clothing/Eyes/Misc/eyepatch.rsi
-  - type: EyeProtection
-    protectionTime: 5
-
 - type: entity
   parent: ClothingEyesBase
   id: ClothingEyesBlindfold
     graph: Blindfold
     node: blindfold
   - type: FlashImmunity
+
+- type: entity
+  parent: ClothingHeadEyeBaseFlippable
+  id: ClothingEyesEyepatch
+  name: eyepatch
+  description: Yarr.
+  components:
+  - type: Sprite
+    sprite: Clothing/Eyes/Misc/eyepatch.rsi
+  - type: Clothing
+    sprite: Clothing/Eyes/Misc/eyepatch.rsi
+  - type: EyeProtection
+    protectionTime: 5
+
+- type: entity
+  parent: [ClothingEyesEyepatch, ClothingHeadEyeBaseFlipped]
+  id: ClothingEyesEyepatchFlipped
+  suffix: flipped