From 18312671d7aefbb005bd8ca6b08744e7204b7fd3 Mon Sep 17 00:00:00 2001 From: Gabriel Kaszewski Date: Sat, 23 Aug 2025 02:44:54 +0200 Subject: [PATCH] Refactor game state management to use a unified Stat system and update UI labels for production and corruption --- Scenes/Main/Main.cs | 45 ++++++-- Scenes/Main/Main.tscn | 107 +++++++++++++++--- Scenes/Main/MiracleButton.cs | 22 +++- Scripts/Core/Effects/AddResourceEffect.cs | 22 ++-- Scripts/Core/Effects/ApplyBuffEffect.cs | 9 +- Scripts/Core/Effects/ConvertResourceEffect.cs | 31 ++--- Scripts/Core/Effects/DestroySelfEffect.cs | 5 + Scripts/Core/Effects/Effect.cs | 5 + Scripts/Core/Effects/ModifyStatEffect.cs | 30 +++-- Scripts/Core/Effects/ResourceType.cs | 3 - Scripts/Core/Effects/ResourceType.cs.uid | 1 - Scripts/Core/Effects/UnlockMiracleEffect.cs | 5 + Scripts/Core/GameLogic.cs | 22 ++-- Scripts/Core/GameState.cs | 38 ++++--- Scripts/Core/MiracleDto.cs | 9 +- Scripts/Core/MiracleLoader.cs | 2 +- Scripts/Core/Stat.cs | 17 +++ Scripts/Core/Stat.cs.uid | 1 + Scripts/Core/StatData.cs | 17 +++ Scripts/Core/StatData.cs.uid | 1 + Scripts/PopulationVisualizer.cs | 4 +- Scripts/Singletons/GameBus.cs | 7 +- project.godot | 4 + 23 files changed, 298 insertions(+), 109 deletions(-) delete mode 100644 Scripts/Core/Effects/ResourceType.cs delete mode 100644 Scripts/Core/Effects/ResourceType.cs.uid create mode 100644 Scripts/Core/Stat.cs create mode 100644 Scripts/Core/Stat.cs.uid create mode 100644 Scripts/Core/StatData.cs create mode 100644 Scripts/Core/StatData.cs.uid diff --git a/Scenes/Main/Main.cs b/Scenes/Main/Main.cs index 7a02ec5..326d59d 100644 --- a/Scenes/Main/Main.cs +++ b/Scenes/Main/Main.cs @@ -9,29 +9,40 @@ public partial class Main : Node [Export] private Label _faithLabel; [Export] private Label _followersLabel; [Export] private Label _corruptionLabel; + [Export] private Label _productionLabel; [Export] private MiraclePanel _miraclePanel; [Export] private Sprite2D _worldSprite; - [Export] private Color _deadWorldColor = new Color("#581845"); + [Export] private Color _deadWorldColor = new("#581845"); public override void _Ready() { - GameBus.Instance.StateChanged += OnStateChanged; + GameBus.Instance.SubscribeToStat(Stat.Faith, UpdateFaithLabel); + GameBus.Instance.SubscribeToStat(Stat.Followers, UpdateFollowersLabel); + GameBus.Instance.SubscribeToStat(Stat.Corruption, UpdateCorruptionLabel); + GameBus.Instance.SubscribeToStat(Stat.Production, UpdateProductionLabel); _miraclePanel.PopulateInitialButtons(GameBus.Instance.AllMiracles); + + GameBus.Instance.StateChanged += OnStateChanged; + + UpdateFaithLabel(GameBus.Instance.CurrentState.Get(Stat.Faith)); + UpdateFollowersLabel(GameBus.Instance.CurrentState.Get(Stat.Followers)); + UpdateCorruptionLabel(GameBus.Instance.CurrentState.Get(Stat.Corruption)); + UpdateProductionLabel(GameBus.Instance.CurrentState.Get(Stat.Production)); } public override void _ExitTree() { + GameBus.Instance.UnsubscribeFromStat(Stat.Faith, UpdateFaithLabel); + GameBus.Instance.UnsubscribeFromStat(Stat.Followers, UpdateFollowersLabel); + GameBus.Instance.UnsubscribeFromStat(Stat.Corruption, UpdateCorruptionLabel); + GameBus.Instance.UnsubscribeFromStat(Stat.Production, UpdateProductionLabel); GameBus.Instance.StateChanged -= OnStateChanged; } private void OnStateChanged(GameState newState) { - _faithLabel.Text = $"Faith: {newState.Faith:F0} (+{newState.FaithPerSecond:F1}/s)"; - _followersLabel.Text = $"Followers: {newState.Followers}"; - _corruptionLabel.Text = $"Corruption: {newState.Corruption:F0}%"; - - UpdateWorldVisuals(newState.Corruption); + UpdateWorldVisuals(newState.Get(Stat.Corruption)); } private void UpdateWorldVisuals(double corruption) @@ -41,4 +52,24 @@ public partial class Main : Node var ratio = (float)corruption / 100.0f; shaderMaterial.SetShaderParameter("corruption_level", ratio); } + + private void UpdateFaithLabel(double newValue) + { + _faithLabel.Text = $"Faith: {newValue:F0}"; + } + + private void UpdateFollowersLabel(double newValue) + { + _followersLabel.Text = $"Followers: {newValue:F0}"; + } + + private void UpdateCorruptionLabel(double newValue) + { + _corruptionLabel.Text = $"Corruption: {newValue:F0}%"; + } + + private void UpdateProductionLabel(double production) + { + _productionLabel.Text = $"Production: {production:F0}"; + } } \ No newline at end of file diff --git a/Scenes/Main/Main.tscn b/Scenes/Main/Main.tscn index 67f8355..f3b8e3c 100644 --- a/Scenes/Main/Main.tscn +++ b/Scenes/Main/Main.tscn @@ -24,12 +24,13 @@ shader_parameter/corrupted_color = Color(0.3, 0.1, 0.2, 1) shader_parameter/corruption_level = 0.0 shader_parameter/tolerance = 0.1 -[node name="World" type="Node2D" node_paths=PackedStringArray("_faithLabel", "_followersLabel", "_corruptionLabel", "_miraclePanel", "_worldSprite")] +[node name="World" type="Node2D" node_paths=PackedStringArray("_faithLabel", "_followersLabel", "_corruptionLabel", "_productionLabel", "_miraclePanel", "_worldSprite")] script = ExtResource("1_p8rbg") -_faithLabel = NodePath("UiLayer/Control/MarginContainer/Main/Top/FaithLabel") -_followersLabel = NodePath("UiLayer/Control/MarginContainer/Main/Top/FollowersLabel") -_corruptionLabel = NodePath("UiLayer/Control/MarginContainer/Main/Top/CorruptionLabel") -_miraclePanel = NodePath("UiLayer/Control/MarginContainer/Main/Bottom") +_faithLabel = NodePath("UiLayer/Control/Main/Top/FaithLabel") +_followersLabel = NodePath("UiLayer/Control/Main/Top/FollowersLabel") +_corruptionLabel = NodePath("UiLayer/Control/Main/Top/CorruptionLabel") +_productionLabel = NodePath("UiLayer/Control/Main/Top/ProductionLabel") +_miraclePanel = NodePath("UiLayer/Control/Main/ScrollContainer/Bottom") _worldSprite = NodePath("World Sprite") [node name="UiLayer" type="CanvasLayer" parent="."] @@ -44,45 +45,121 @@ grow_vertical = 2 size_flags_horizontal = 3 size_flags_vertical = 3 -[node name="MarginContainer" type="MarginContainer" parent="UiLayer/Control"] +[node name="Main" type="MarginContainer" parent="UiLayer/Control"] layout_mode = 1 anchors_preset = 15 anchor_right = 1.0 anchor_bottom = 1.0 grow_horizontal = 2 grow_vertical = 2 +size_flags_horizontal = 4 +size_flags_vertical = 0 theme_override_constants/margin_left = 8 theme_override_constants/margin_top = 8 theme_override_constants/margin_right = 8 theme_override_constants/margin_bottom = 8 -[node name="Main" type="VBoxContainer" parent="UiLayer/Control/MarginContainer"] +[node name="Top" type="HBoxContainer" parent="UiLayer/Control/Main"] layout_mode = 2 size_flags_horizontal = 4 size_flags_vertical = 0 +alignment = 1 -[node name="Top" type="HBoxContainer" parent="UiLayer/Control/MarginContainer/Main"] -layout_mode = 2 - -[node name="FaithLabel" type="Label" parent="UiLayer/Control/MarginContainer/Main/Top"] +[node name="FaithLabel" type="Label" parent="UiLayer/Control/Main/Top"] layout_mode = 2 text = "Faith Label" -[node name="FollowersLabel" type="Label" parent="UiLayer/Control/MarginContainer/Main/Top"] +[node name="FollowersLabel" type="Label" parent="UiLayer/Control/Main/Top"] layout_mode = 2 text = "FollowersLabel" -[node name="CorruptionLabel" type="Label" parent="UiLayer/Control/MarginContainer/Main/Top"] +[node name="ProductionLabel" type="Label" parent="UiLayer/Control/Main/Top"] +layout_mode = 2 +text = "ProductionLabel" + +[node name="CorruptionLabel" type="Label" parent="UiLayer/Control/Main/Top"] layout_mode = 2 text = "CorruptionLabel" -[node name="Bottom" type="GridContainer" parent="UiLayer/Control/MarginContainer/Main"] +[node name="ScrollContainer" type="ScrollContainer" parent="UiLayer/Control/Main"] +custom_minimum_size = Vector2(430, 200) layout_mode = 2 -size_flags_vertical = 6 +size_flags_horizontal = 8 +size_flags_vertical = 10 +horizontal_scroll_mode = 0 + +[node name="Bottom" type="GridContainer" parent="UiLayer/Control/Main/ScrollContainer"] +layout_mode = 2 +size_flags_horizontal = 3 +size_flags_vertical = 3 +theme_override_constants/h_separation = 4 +theme_override_constants/v_separation = 4 columns = 3 script = ExtResource("2_hcu3t") _miracleButtonScene = ExtResource("3_qdkat") +[node name="ScrollContainer2" type="ScrollContainer" parent="UiLayer/Control/Main"] +custom_minimum_size = Vector2(400, 100) +layout_mode = 2 +size_flags_horizontal = 0 +size_flags_vertical = 10 +vertical_scroll_mode = 0 + +[node name="HBoxContainer" type="HBoxContainer" parent="UiLayer/Control/Main/ScrollContainer2"] +layout_mode = 2 +size_flags_horizontal = 3 +size_flags_vertical = 3 + +[node name="Button" type="Button" parent="UiLayer/Control/Main/ScrollContainer2/HBoxContainer"] +layout_mode = 2 +disabled = true +text = "Effect" + +[node name="Button2" type="Button" parent="UiLayer/Control/Main/ScrollContainer2/HBoxContainer"] +layout_mode = 2 +disabled = true +text = "Effect" + +[node name="Button3" type="Button" parent="UiLayer/Control/Main/ScrollContainer2/HBoxContainer"] +layout_mode = 2 +disabled = true +text = "Effect" + +[node name="Button4" type="Button" parent="UiLayer/Control/Main/ScrollContainer2/HBoxContainer"] +layout_mode = 2 +disabled = true +text = "Effect" + +[node name="Button5" type="Button" parent="UiLayer/Control/Main/ScrollContainer2/HBoxContainer"] +layout_mode = 2 +disabled = true +text = "Effect" + +[node name="Button6" type="Button" parent="UiLayer/Control/Main/ScrollContainer2/HBoxContainer"] +layout_mode = 2 +disabled = true +text = "Effect" + +[node name="Button7" type="Button" parent="UiLayer/Control/Main/ScrollContainer2/HBoxContainer"] +layout_mode = 2 +disabled = true +text = "Effect" + +[node name="Button8" type="Button" parent="UiLayer/Control/Main/ScrollContainer2/HBoxContainer"] +layout_mode = 2 +disabled = true +text = "Effect" + +[node name="Button9" type="Button" parent="UiLayer/Control/Main/ScrollContainer2/HBoxContainer"] +layout_mode = 2 +disabled = true +text = "Effect" + +[node name="Button10" type="Button" parent="UiLayer/Control/Main/ScrollContainer2/HBoxContainer"] +layout_mode = 2 +disabled = true +text = "Effect" + [node name="Camera2D" type="Camera2D" parent="."] [node name="World Sprite" type="Sprite2D" parent="."] diff --git a/Scenes/Main/MiracleButton.cs b/Scenes/Main/MiracleButton.cs index a881377..81336e5 100644 --- a/Scenes/Main/MiracleButton.cs +++ b/Scenes/Main/MiracleButton.cs @@ -17,7 +17,8 @@ public partial class MiracleButton : Button return; } - Text = $"{_miracle.Name}\nCost: {_miracle.FaithCost} Faith"; + Text = BuildText(); + TooltipText = BuildTooltipText(); Pressed += OnPressed; } @@ -35,8 +36,25 @@ public partial class MiracleButton : Button public void SetMiracle(MiracleDefinition miracle) { _miracle = miracle; - Text = $"{_miracle.Name}\nCost: {_miracle.FaithCost} Faith"; + Text = BuildText(); + TooltipText = BuildTooltipText(); } public MiracleDefinition GetMiracle() { return _miracle; } + + private string BuildText() + { + return $"{_miracle.Name}\nCost: {_miracle.FaithCost} Faith"; + } + + private string BuildTooltipText() + { + var tooltip = $"Cost: {_miracle.FaithCost} Faith\nRequires: {_miracle.FollowersRequired} Followers\nEffects:\n"; + foreach (var effect in _miracle.Effects) + { + if (effect.ToString() == string.Empty) continue; + tooltip += $"- {effect}\n"; + } + return tooltip.TrimEnd(); + } } \ No newline at end of file diff --git a/Scripts/Core/Effects/AddResourceEffect.cs b/Scripts/Core/Effects/AddResourceEffect.cs index e82dcf1..ed5602f 100644 --- a/Scripts/Core/Effects/AddResourceEffect.cs +++ b/Scripts/Core/Effects/AddResourceEffect.cs @@ -6,24 +6,16 @@ namespace ParasiticGod.Scripts.Core.Effects; [GlobalClass] public partial class AddResourceEffect : Effect { - [Export] public ResourceType TargetResource { get; set; } + [Export] public Stat TargetResource { get; set; } [Export] public double Value { get; set; } public override void Execute(GameState state) { - switch (TargetResource) - { - case ResourceType.Faith: - state.Faith += Value; - break; - case ResourceType.Followers: - state.Followers += (long)Value; - break; - case ResourceType.Corruption: - state.Corruption += Value; - break; - default: - throw new ArgumentOutOfRangeException(); - } + state.Modify(TargetResource, Value); + } + + public override string ToString() + { + return $"Add {Value} to {TargetResource}"; } } \ No newline at end of file diff --git a/Scripts/Core/Effects/ApplyBuffEffect.cs b/Scripts/Core/Effects/ApplyBuffEffect.cs index 2603146..0b78c63 100644 --- a/Scripts/Core/Effects/ApplyBuffEffect.cs +++ b/Scripts/Core/Effects/ApplyBuffEffect.cs @@ -5,9 +5,7 @@ namespace ParasiticGod.Scripts.Core.Effects; [GlobalClass] public partial class ApplyBuffEffect : Effect { - public enum BuffTarget { FaithGeneration } - - [Export] public BuffTarget TargetStat { get; set; } + [Export] public Stat TargetStat { get; set; } [Export] public float Multiplier { get; set; } = 2.0f; [Export] public double Duration { get; set; } = 30.0; @@ -21,4 +19,9 @@ public partial class ApplyBuffEffect : Effect gameState.ActiveBuffs.Add(newBuff); } + + public override string ToString() + { + return $"Apply Buff: x{Multiplier} to {TargetStat} for {Duration} seconds"; + } } \ No newline at end of file diff --git a/Scripts/Core/Effects/ConvertResourceEffect.cs b/Scripts/Core/Effects/ConvertResourceEffect.cs index b224565..9e8f6c7 100644 --- a/Scripts/Core/Effects/ConvertResourceEffect.cs +++ b/Scripts/Core/Effects/ConvertResourceEffect.cs @@ -5,32 +5,21 @@ namespace ParasiticGod.Scripts.Core.Effects; [GlobalClass] public partial class ConvertResourceEffect : Effect { - [Export] public ResourceType FromResource { get; set; } + [Export] public Stat FromResource { get; set; } [Export] public double FromAmount { get; set; } - [Export] public ResourceType ToResource { get; set; } + [Export] public Stat ToResource { get; set; } [Export] public double ToAmount { get; set; } public override void Execute(GameState gameState) { - double GetValue(ResourceType type) => type switch { - ResourceType.Faith => gameState.Faith, - ResourceType.Followers => gameState.Followers, - ResourceType.Corruption => gameState.Corruption, - _ => 0 - }; + if (!(gameState.Get(FromResource) >= FromAmount)) return; - void SetValue(ResourceType type, double value) { - switch(type) { - case ResourceType.Faith: gameState.Faith = value; break; - case ResourceType.Followers: gameState.Followers = (long)value; break; - case ResourceType.Corruption: gameState.Corruption = value; break; - } - } - - if (GetValue(FromResource) >= FromAmount) - { - SetValue(FromResource, GetValue(FromResource) - FromAmount); - SetValue(ToResource, GetValue(ToResource) + ToAmount); - } + gameState.Set(FromResource, gameState.Get(FromResource) - FromAmount); + gameState.Set(ToResource, gameState.Get(ToResource) + ToAmount); + } + + public override string ToString() + { + return $"Convert {FromAmount} {FromResource} to {ToAmount} {ToResource}"; } } \ No newline at end of file diff --git a/Scripts/Core/Effects/DestroySelfEffect.cs b/Scripts/Core/Effects/DestroySelfEffect.cs index 04510d8..e449a63 100644 --- a/Scripts/Core/Effects/DestroySelfEffect.cs +++ b/Scripts/Core/Effects/DestroySelfEffect.cs @@ -8,4 +8,9 @@ public partial class DestroySelfEffect : Effect public override void Execute(GameState gameState) { } + + public override string ToString() + { + return ""; + } } \ No newline at end of file diff --git a/Scripts/Core/Effects/Effect.cs b/Scripts/Core/Effects/Effect.cs index 582f474..1070242 100644 --- a/Scripts/Core/Effects/Effect.cs +++ b/Scripts/Core/Effects/Effect.cs @@ -5,4 +5,9 @@ namespace ParasiticGod.Scripts.Core.Effects; public abstract partial class Effect : Resource { public abstract void Execute(GameState gameState); + + public override string ToString() + { + return GetType().Name.Replace("Effect", ""); + } } \ No newline at end of file diff --git a/Scripts/Core/Effects/ModifyStatEffect.cs b/Scripts/Core/Effects/ModifyStatEffect.cs index 8f7e5a0..ebc1605 100644 --- a/Scripts/Core/Effects/ModifyStatEffect.cs +++ b/Scripts/Core/Effects/ModifyStatEffect.cs @@ -5,7 +5,6 @@ namespace ParasiticGod.Scripts.Core.Effects; [GlobalClass] public partial class ModifyStatEffect : Effect { - public enum Stat { FaithPerFollower } public enum Operation { Add, Multiply } [Export] public Stat TargetStat { get; set; } @@ -14,17 +13,26 @@ public partial class ModifyStatEffect : Effect public override void Execute(GameState gameState) { - if (TargetStat == Stat.FaithPerFollower) + switch (Op) { - switch (Op) - { - case Operation.Add: - gameState.FaithPerFollower += Value; - break; - case Operation.Multiply: - gameState.FaithPerFollower *= Value; - break; - } + case Operation.Add: + var currentValue = gameState.Get(TargetStat); + gameState.Set(TargetStat, currentValue + Value); + break; + case Operation.Multiply: + var currentValueMul = gameState.Get(TargetStat); + gameState.Set(TargetStat, currentValueMul * Value); + break; } } + + public override string ToString() + { + return Op switch + { + Operation.Add => $"Add {Value} to {TargetStat}", + Operation.Multiply => $"Multiply {TargetStat} by {Value}", + _ => "Unknown Operation" + }; + } } \ No newline at end of file diff --git a/Scripts/Core/Effects/ResourceType.cs b/Scripts/Core/Effects/ResourceType.cs deleted file mode 100644 index 9c94cb1..0000000 --- a/Scripts/Core/Effects/ResourceType.cs +++ /dev/null @@ -1,3 +0,0 @@ -namespace ParasiticGod.Scripts.Core.Effects; - -public enum ResourceType { Faith, Followers, Corruption } \ No newline at end of file diff --git a/Scripts/Core/Effects/ResourceType.cs.uid b/Scripts/Core/Effects/ResourceType.cs.uid deleted file mode 100644 index 174fcdb..0000000 --- a/Scripts/Core/Effects/ResourceType.cs.uid +++ /dev/null @@ -1 +0,0 @@ -uid://do6aurfs8oif0 diff --git a/Scripts/Core/Effects/UnlockMiracleEffect.cs b/Scripts/Core/Effects/UnlockMiracleEffect.cs index 0067840..86436f1 100644 --- a/Scripts/Core/Effects/UnlockMiracleEffect.cs +++ b/Scripts/Core/Effects/UnlockMiracleEffect.cs @@ -13,4 +13,9 @@ public partial class UnlockMiracleEffect : Effect { } + + public override string ToString() + { + return $"Unlock miracles: {string.Join(", ", MiraclesToUnlock)}"; + } } \ No newline at end of file diff --git a/Scripts/Core/GameLogic.cs b/Scripts/Core/GameLogic.cs index 3f71034..47c4aa4 100644 --- a/Scripts/Core/GameLogic.cs +++ b/Scripts/Core/GameLogic.cs @@ -6,7 +6,16 @@ public class GameLogic { public void UpdateGameState(GameState state, double delta) { - state.Faith += state.FaithPerSecond * delta; + var totalMultiplier = 1.0; + foreach (var buff in state.ActiveBuffs) + { + totalMultiplier *= buff.Multiplier; + } + var faithPerSecond = state.Get(Stat.Followers) * state.Get(Stat.FaithPerFollower) * totalMultiplier; + + state.Modify(Stat.Faith, faithPerSecond * delta); + state.Modify(Stat.Production, state.Get(Stat.ProductionPerSecond) * delta); + state.Modify(Stat.Corruption, state.Get(Stat.CorruptionPerSecond) * delta); for (var i = state.ActiveBuffs.Count - 1; i >= 0; i--) { @@ -21,13 +30,13 @@ public class GameLogic public bool TryToPerformMiracle(GameState state, MiracleDefinition miracle) { - if (state.Faith < miracle.FaithCost || state.Followers < miracle.FollowersRequired) + if (state.Get(Stat.Faith) < miracle.FaithCost || state.Get(Stat.Followers) < miracle.FollowersRequired) { return false; } - state.Faith -= miracle.FaithCost; - + state.Modify(Stat.Faith, -miracle.FaithCost); + if (miracle.Effects != null) { foreach (var effect in miracle.Effects) @@ -35,9 +44,8 @@ public class GameLogic effect.Execute(state); } } - - state.Corruption = Math.Clamp(state.Corruption, 0, 100); - + + state.Set(Stat.Corruption, Math.Clamp(state.Get(Stat.Corruption), 0, 100)); return true; } } \ No newline at end of file diff --git a/Scripts/Core/GameState.cs b/Scripts/Core/GameState.cs index fdf3791..cbab6cc 100644 --- a/Scripts/Core/GameState.cs +++ b/Scripts/Core/GameState.cs @@ -1,3 +1,4 @@ +using System; using System.Collections.Generic; using ParasiticGod.Scripts.Core.Effects; @@ -5,23 +6,32 @@ namespace ParasiticGod.Scripts.Core; public class GameState { - public double Faith { get; set; } = 50.0; - public double FaithPerFollower { get; set; } = 0.5; - public long Followers { get; set; } = 40; - public double Corruption { get; set; } = 0.0; - + private readonly Dictionary _stats = new(); + public List ActiveBuffs { get; } = []; - - public double FaithPerSecond + + public GameState() { - get + // Initialize all stats with their default values + foreach (Stat stat in Enum.GetValues(typeof(Stat))) { - var totalMultiplier = 1.0; - foreach (var buff in ActiveBuffs) - { - totalMultiplier *= buff.Multiplier; - } - return Followers * FaithPerFollower * totalMultiplier; + _stats[stat] = new StatData(); } + + Set(Stat.Faith, 50); + Set(Stat.Followers, 40); + Set(Stat.FaithPerFollower, 0.5); + Set(Stat.ProductionPerSecond, 1.0); + Set(Stat.CorruptionPerSecond, 0.1); } + + public double Get(Stat stat) => _stats[stat].Value; + + public void Set(Stat stat, double value) => _stats[stat].Set(value); + + public void Modify(Stat stat, double delta) => _stats[stat].Set(Get(stat) + delta); + + public void Subscribe(Stat stat, Action listener) => _stats[stat].OnChanged += listener; + + public void Unsubscribe(Stat stat, Action listener) => _stats[stat].OnChanged -= listener; } \ No newline at end of file diff --git a/Scripts/Core/MiracleDto.cs b/Scripts/Core/MiracleDto.cs index e6d74e8..147084b 100644 --- a/Scripts/Core/MiracleDto.cs +++ b/Scripts/Core/MiracleDto.cs @@ -7,22 +7,21 @@ public class EffectDto { public string Type { get; set; } // --- For "AddResource" Effect --- - public ResourceType TargetResource { get; set; } + public Stat TargetResource { get; set; } public double Value { get; set; } // --- For "ApplyBuff" Effect --- - public ApplyBuffEffect.BuffTarget TargetBuffStat { get; set; } public float Multiplier { get; set; } public double Duration { get; set; } // --- For "ConvertResource" Effect --- - public ResourceType FromResource { get; set; } + public Stat FromResource { get; set; } public double FromAmount { get; set; } - public ResourceType ToResource { get; set; } + public Stat ToResource { get; set; } public double ToAmount { get; set; } // --- For "ModifyStat" Effect --- - public ModifyStatEffect.Stat TargetStat { get; set; } + public Stat TargetStat { get; set; } public ModifyStatEffect.Operation Op { get; set; } public List MiraclesToUnlock { get; set; } diff --git a/Scripts/Core/MiracleLoader.cs b/Scripts/Core/MiracleLoader.cs index 58847b0..7505f77 100644 --- a/Scripts/Core/MiracleLoader.cs +++ b/Scripts/Core/MiracleLoader.cs @@ -84,7 +84,7 @@ public static class MiracleLoader addResourceEffect.Value = effectDto.Value; break; case ApplyBuffEffect applyBuffEffect: - applyBuffEffect.TargetStat = effectDto.TargetBuffStat; + applyBuffEffect.TargetStat = effectDto.TargetStat; applyBuffEffect.Multiplier = effectDto.Multiplier; applyBuffEffect.Duration = effectDto.Duration; break; diff --git a/Scripts/Core/Stat.cs b/Scripts/Core/Stat.cs new file mode 100644 index 0000000..e8aebb3 --- /dev/null +++ b/Scripts/Core/Stat.cs @@ -0,0 +1,17 @@ +namespace ParasiticGod.Scripts.Core; + +public enum Stat +{ + // Primary Resources + Faith, + Followers, + Corruption, + Production, + + // Passive Generation Stats + ProductionPerSecond, + CorruptionPerSecond, + + // Modifying Stats + FaithPerFollower +} \ No newline at end of file diff --git a/Scripts/Core/Stat.cs.uid b/Scripts/Core/Stat.cs.uid new file mode 100644 index 0000000..4ab9354 --- /dev/null +++ b/Scripts/Core/Stat.cs.uid @@ -0,0 +1 @@ +uid://lc6dt3ct28vk diff --git a/Scripts/Core/StatData.cs b/Scripts/Core/StatData.cs new file mode 100644 index 0000000..0b3f62a --- /dev/null +++ b/Scripts/Core/StatData.cs @@ -0,0 +1,17 @@ +using System; + +namespace ParasiticGod.Scripts.Core; + +public class StatData +{ + public double Value { get; private set; } + public event Action OnChanged; + + public void Set(double value) + { + if (!(Math.Abs(Value - value) > 0.001)) return; + + Value = value; + OnChanged?.Invoke(Value); + } +} \ No newline at end of file diff --git a/Scripts/Core/StatData.cs.uid b/Scripts/Core/StatData.cs.uid new file mode 100644 index 0000000..437e624 --- /dev/null +++ b/Scripts/Core/StatData.cs.uid @@ -0,0 +1 @@ +uid://cd1q4nlnrgtp1 diff --git a/Scripts/PopulationVisualizer.cs b/Scripts/PopulationVisualizer.cs index c4c4266..b8aa805 100644 --- a/Scripts/PopulationVisualizer.cs +++ b/Scripts/PopulationVisualizer.cs @@ -40,7 +40,7 @@ public partial class PopulationVisualizer : Node { if (_isUpdating) return; - var currentUnitCount = newState.Followers; + var currentUnitCount = (long)newState.Get(Stat.Followers); var currentMarkersToShow = (int)currentUnitCount / _unitsPerMarker; var lastMarkersToShow = (int)_lastKnownUnitCount / _unitsPerMarker; @@ -84,8 +84,6 @@ public partial class PopulationVisualizer : Node if (i < followersToShow) { - // Note: The 'Follower' script would need a way to know its tier index or resource path - // to do a perfect comparison. For now, we'll just check for occupancy. if (!marker.IsOccupied || _lastKnownTierIndex != newTierIndex) { if (marker.IsOccupied) marker.RemoveFollower(); diff --git a/Scripts/Singletons/GameBus.cs b/Scripts/Singletons/GameBus.cs index 9de14bb..48b7809 100644 --- a/Scripts/Singletons/GameBus.cs +++ b/Scripts/Singletons/GameBus.cs @@ -35,7 +35,7 @@ public partial class GameBus : Node _gameLogic.UpdateGameState(_gameState, delta); StateChanged?.Invoke(_gameState); - if (_gameState.Corruption >= 100) + if (_gameState.Get(Stat.Corruption) >= 100) { GD.Print("The world has died!"); GetTree().Quit(); // For now @@ -73,4 +73,9 @@ public partial class GameBus : Node } } } + + public void SubscribeToStat(Stat stat, Action listener) => _gameState.Subscribe(stat, listener); + public void UnsubscribeFromStat(Stat stat, Action listener) => _gameState.Unsubscribe(stat, listener); + + public GameState CurrentState => _gameState; } \ No newline at end of file diff --git a/project.godot b/project.godot index c2485f8..6a0319b 100644 --- a/project.godot +++ b/project.godot @@ -22,6 +22,10 @@ config/icon="uid://dihjvrhshhklu" GameBus="*res://Scripts/Singletons/GameBus.cs" +[display] + +window/stretch/mode="canvas_items" + [dotnet] project/assembly_name="ParasiticGod"