diff --git a/Content.Client/Stack/StackSystem.cs b/Content.Client/Stack/StackSystem.cs index 7e681aeba3e..f57f4d4e170 100644 --- a/Content.Client/Stack/StackSystem.cs +++ b/Content.Client/Stack/StackSystem.cs @@ -8,7 +8,7 @@ namespace Content.Client.Stack { [UsedImplicitly] - public sealed class StackSystem : SharedStackSystem + public sealed partial class StackSystem : SharedStackSystem // Frontier: add partial to class definition { [Dependency] private readonly AppearanceSystem _appearanceSystem = default!; [Dependency] private readonly ItemCounterSystem _counterSystem = default!; @@ -44,7 +44,7 @@ public override void SetCount(EntityUid uid, int amount, StackComponent? compone // TODO PREDICT ENTITY DELETION: This should really just be a normal entity deletion call. if (component.Count <= 0 && !component.Lingering) { - Xform.DetachEntity(uid, Transform(uid)); + Xform.DetachParentToNull(uid, Transform(uid)); return; } @@ -56,20 +56,25 @@ private void OnAppearanceChange(EntityUid uid, StackComponent comp, ref Appearan if (args.Sprite == null || comp.LayerStates.Count < 1) return; + StackLayerData data = new StackLayerData(); // Frontier: use structure to store StackLayerData + // Skip processing if no actual - if (!_appearanceSystem.TryGetData(uid, StackVisuals.Actual, out var actual, args.Component)) + if (!_appearanceSystem.TryGetData(uid, StackVisuals.Actual, out data.Actual, args.Component)) return; - if (!_appearanceSystem.TryGetData(uid, StackVisuals.MaxCount, out var maxCount, args.Component)) - maxCount = comp.LayerStates.Count; + if (!_appearanceSystem.TryGetData(uid, StackVisuals.MaxCount, out data.MaxCount, args.Component)) + data.MaxCount = comp.LayerStates.Count; + + if (!_appearanceSystem.TryGetData(uid, StackVisuals.Hide, out data.Hidden, args.Component)) + data.Hidden = false; - if (!_appearanceSystem.TryGetData(uid, StackVisuals.Hide, out var hidden, args.Component)) - hidden = false; + if (comp.LayerFunction != StackLayerFunction.None) // Frontier: use stack layer function to modify appearance if provided. + ApplyLayerFunction(uid, comp, ref data); // Frontier: definition in _NF/Stack/StackSystem.Layers.cs if (comp.IsComposite) - _counterSystem.ProcessCompositeSprite(uid, actual, maxCount, comp.LayerStates, hidden, sprite: args.Sprite); + _counterSystem.ProcessCompositeSprite(uid, data.Actual, data.MaxCount, comp.LayerStates, data.Hidden, sprite: args.Sprite); else - _counterSystem.ProcessOpaqueSprite(uid, comp.BaseLayer, actual, maxCount, comp.LayerStates, hidden, sprite: args.Sprite); + _counterSystem.ProcessOpaqueSprite(uid, comp.BaseLayer, data.Actual, data.MaxCount, comp.LayerStates, data.Hidden, sprite: args.Sprite); } } } diff --git a/Content.Client/_NF/Stack/StackSystem.Layers.cs b/Content.Client/_NF/Stack/StackSystem.Layers.cs new file mode 100644 index 00000000000..2893d32d3f5 --- /dev/null +++ b/Content.Client/_NF/Stack/StackSystem.Layers.cs @@ -0,0 +1,56 @@ +using Content.Shared.Stacks.Components; +using Content.Shared.Stacks; + +namespace Content.Client.Stack +{ + /// + /// Data used to determine which layers of a stack's sprite are visible. + /// + public struct StackLayerData + { + public int Actual; + public int MaxCount; + public bool Hidden; + } + + public sealed partial class StackSystem : SharedStackSystem + { + // Modifies a given stack component to adjust the layers to display. + private bool ApplyLayerFunction(EntityUid uid, StackComponent comp, ref StackLayerData data) + { + switch (comp.LayerFunction) + { + case StackLayerFunction.Threshold: + if (TryComp(uid, out var threshold)) + { + ApplyThreshold(threshold, ref data); + return true; + } + break; + } + // No function applied. + return false; + } + + /// + /// Sets Actual to the number of thresholds that Actual exceeds from the beginning of the list. + /// Sets MaxCount to the total number of thresholds plus one (for values under thresholds). + /// + private static void ApplyThreshold(StackLayerThresholdComponent comp, ref StackLayerData data) + { + // We must stop before we run out of thresholds or layers, whichever's smaller. + data.MaxCount = Math.Min(comp.Thresholds.Count + 1, data.MaxCount); + int newActual = 0; + foreach (var threshold in comp.Thresholds) + { + //If our value exceeds threshold, the next layer should be displayed. + //Note: we must ensure actual <= MaxCount. + if (data.Actual >= threshold && newActual < data.MaxCount) + newActual++; + else + break; + } + data.Actual = newActual; + } + } +} diff --git a/Content.Packaging/Properties/launchSettings.json b/Content.Packaging/Properties/launchSettings.json new file mode 100644 index 00000000000..33504c948ad --- /dev/null +++ b/Content.Packaging/Properties/launchSettings.json @@ -0,0 +1,8 @@ +{ + "profiles": { + "WSL": { + "commandName": "WSL2", + "distributionName": "" + } + } +} \ No newline at end of file diff --git a/Content.Shared/Stacks/StackComponent.cs b/Content.Shared/Stacks/StackComponent.cs index 7137f8c0c22..b18f9b0d051 100644 --- a/Content.Shared/Stacks/StackComponent.cs +++ b/Content.Shared/Stacks/StackComponent.cs @@ -24,7 +24,7 @@ public sealed partial class StackComponent : Component /// [ViewVariables(VVAccess.ReadOnly)] [DataField("maxCountOverride")] - public int? MaxCountOverride { get; set; } + public int? MaxCountOverride { get; set; } /// /// Set to true to not reduce the count when used. @@ -78,6 +78,14 @@ public sealed partial class StackComponent : Component [DataField("layerStates")] [ViewVariables(VVAccess.ReadWrite)] public List LayerStates = new(); + + // Frontier: transforming Amount, MaxCount in speso stacks + /// + /// An optional function to adjust the layers used for a stack's appearance. + /// + [DataField] + public StackLayerFunction LayerFunction = StackLayerFunction.None; + // End Frontier } [Serializable, NetSerializable] diff --git a/Content.Shared/_NF/Stacks/Components/StackLayerThresholdComponent.cs b/Content.Shared/_NF/Stacks/Components/StackLayerThresholdComponent.cs new file mode 100644 index 00000000000..98d3bb0e61f --- /dev/null +++ b/Content.Shared/_NF/Stacks/Components/StackLayerThresholdComponent.cs @@ -0,0 +1,13 @@ +namespace Content.Shared.Stacks.Components; + +[RegisterComponent] +public sealed partial class StackLayerThresholdComponent : Component +{ + /// + /// A list of thresholds to check against the number of things in the stack. + /// Each exceeded threshold will cause the next layer to be displayed. + /// Should be sorted in ascending order. + /// + [DataField(required: true)] + public List Thresholds = new List(); +} diff --git a/Content.Shared/_NF/Stacks/StackLayerFunction.cs b/Content.Shared/_NF/Stacks/StackLayerFunction.cs new file mode 100644 index 00000000000..c655f3f76c2 --- /dev/null +++ b/Content.Shared/_NF/Stacks/StackLayerFunction.cs @@ -0,0 +1,7 @@ +namespace Content.Shared.Stacks; + +public enum StackLayerFunction +{ + None, + Threshold +} diff --git a/Resources/Prototypes/Entities/Objects/Misc/space_cash.yml b/Resources/Prototypes/Entities/Objects/Misc/space_cash.yml index 57dfb400984..12dd680d9f6 100644 --- a/Resources/Prototypes/Entities/Objects/Misc/space_cash.yml +++ b/Resources/Prototypes/Entities/Objects/Misc/space_cash.yml @@ -9,6 +9,9 @@ shape: - 0,0,1,0 storedOffset: 0,-2 + - type: Currency + price: + Speso: 1 - type: Material - type: PhysicalComposition materialComposition: @@ -25,9 +28,17 @@ - cash_100 - cash_500 - cash_1000 - - cash_1000000 + - cash_5000 # Frontier: larger denominations + - cash_10000 # Frontier: larger denominations + - cash_25000 # Frontier: larger denominations + - cash_50000 # Frontier: larger denominations + - cash_100000 # Frontier: larger denominations + - cash_250000 # Frontier: larger denominations (cash_1000000