Refactor game state management to use a unified Stat system and update UI labels for production and corruption
This commit is contained in:
@@ -9,29 +9,40 @@ public partial class Main : Node
|
|||||||
[Export] private Label _faithLabel;
|
[Export] private Label _faithLabel;
|
||||||
[Export] private Label _followersLabel;
|
[Export] private Label _followersLabel;
|
||||||
[Export] private Label _corruptionLabel;
|
[Export] private Label _corruptionLabel;
|
||||||
|
[Export] private Label _productionLabel;
|
||||||
[Export] private MiraclePanel _miraclePanel;
|
[Export] private MiraclePanel _miraclePanel;
|
||||||
[Export] private Sprite2D _worldSprite;
|
[Export] private Sprite2D _worldSprite;
|
||||||
[Export] private Color _deadWorldColor = new Color("#581845");
|
[Export] private Color _deadWorldColor = new("#581845");
|
||||||
|
|
||||||
public override void _Ready()
|
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);
|
_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()
|
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;
|
GameBus.Instance.StateChanged -= OnStateChanged;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnStateChanged(GameState newState)
|
private void OnStateChanged(GameState newState)
|
||||||
{
|
{
|
||||||
_faithLabel.Text = $"Faith: {newState.Faith:F0} (+{newState.FaithPerSecond:F1}/s)";
|
UpdateWorldVisuals(newState.Get(Stat.Corruption));
|
||||||
_followersLabel.Text = $"Followers: {newState.Followers}";
|
|
||||||
_corruptionLabel.Text = $"Corruption: {newState.Corruption:F0}%";
|
|
||||||
|
|
||||||
UpdateWorldVisuals(newState.Corruption);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void UpdateWorldVisuals(double corruption)
|
private void UpdateWorldVisuals(double corruption)
|
||||||
@@ -41,4 +52,24 @@ public partial class Main : Node
|
|||||||
var ratio = (float)corruption / 100.0f;
|
var ratio = (float)corruption / 100.0f;
|
||||||
shaderMaterial.SetShaderParameter("corruption_level", ratio);
|
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}";
|
||||||
|
}
|
||||||
}
|
}
|
@@ -24,12 +24,13 @@ shader_parameter/corrupted_color = Color(0.3, 0.1, 0.2, 1)
|
|||||||
shader_parameter/corruption_level = 0.0
|
shader_parameter/corruption_level = 0.0
|
||||||
shader_parameter/tolerance = 0.1
|
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")
|
script = ExtResource("1_p8rbg")
|
||||||
_faithLabel = NodePath("UiLayer/Control/MarginContainer/Main/Top/FaithLabel")
|
_faithLabel = NodePath("UiLayer/Control/Main/Top/FaithLabel")
|
||||||
_followersLabel = NodePath("UiLayer/Control/MarginContainer/Main/Top/FollowersLabel")
|
_followersLabel = NodePath("UiLayer/Control/Main/Top/FollowersLabel")
|
||||||
_corruptionLabel = NodePath("UiLayer/Control/MarginContainer/Main/Top/CorruptionLabel")
|
_corruptionLabel = NodePath("UiLayer/Control/Main/Top/CorruptionLabel")
|
||||||
_miraclePanel = NodePath("UiLayer/Control/MarginContainer/Main/Bottom")
|
_productionLabel = NodePath("UiLayer/Control/Main/Top/ProductionLabel")
|
||||||
|
_miraclePanel = NodePath("UiLayer/Control/Main/ScrollContainer/Bottom")
|
||||||
_worldSprite = NodePath("World Sprite")
|
_worldSprite = NodePath("World Sprite")
|
||||||
|
|
||||||
[node name="UiLayer" type="CanvasLayer" parent="."]
|
[node name="UiLayer" type="CanvasLayer" parent="."]
|
||||||
@@ -44,45 +45,121 @@ grow_vertical = 2
|
|||||||
size_flags_horizontal = 3
|
size_flags_horizontal = 3
|
||||||
size_flags_vertical = 3
|
size_flags_vertical = 3
|
||||||
|
|
||||||
[node name="MarginContainer" type="MarginContainer" parent="UiLayer/Control"]
|
[node name="Main" type="MarginContainer" parent="UiLayer/Control"]
|
||||||
layout_mode = 1
|
layout_mode = 1
|
||||||
anchors_preset = 15
|
anchors_preset = 15
|
||||||
anchor_right = 1.0
|
anchor_right = 1.0
|
||||||
anchor_bottom = 1.0
|
anchor_bottom = 1.0
|
||||||
grow_horizontal = 2
|
grow_horizontal = 2
|
||||||
grow_vertical = 2
|
grow_vertical = 2
|
||||||
|
size_flags_horizontal = 4
|
||||||
|
size_flags_vertical = 0
|
||||||
theme_override_constants/margin_left = 8
|
theme_override_constants/margin_left = 8
|
||||||
theme_override_constants/margin_top = 8
|
theme_override_constants/margin_top = 8
|
||||||
theme_override_constants/margin_right = 8
|
theme_override_constants/margin_right = 8
|
||||||
theme_override_constants/margin_bottom = 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
|
layout_mode = 2
|
||||||
size_flags_horizontal = 4
|
size_flags_horizontal = 4
|
||||||
size_flags_vertical = 0
|
size_flags_vertical = 0
|
||||||
|
alignment = 1
|
||||||
|
|
||||||
[node name="Top" type="HBoxContainer" parent="UiLayer/Control/MarginContainer/Main"]
|
[node name="FaithLabel" type="Label" parent="UiLayer/Control/Main/Top"]
|
||||||
layout_mode = 2
|
|
||||||
|
|
||||||
[node name="FaithLabel" type="Label" parent="UiLayer/Control/MarginContainer/Main/Top"]
|
|
||||||
layout_mode = 2
|
layout_mode = 2
|
||||||
text = "Faith Label"
|
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
|
layout_mode = 2
|
||||||
text = "FollowersLabel"
|
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
|
layout_mode = 2
|
||||||
text = "CorruptionLabel"
|
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
|
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
|
columns = 3
|
||||||
script = ExtResource("2_hcu3t")
|
script = ExtResource("2_hcu3t")
|
||||||
_miracleButtonScene = ExtResource("3_qdkat")
|
_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="Camera2D" type="Camera2D" parent="."]
|
||||||
|
|
||||||
[node name="World Sprite" type="Sprite2D" parent="."]
|
[node name="World Sprite" type="Sprite2D" parent="."]
|
||||||
|
@@ -17,7 +17,8 @@ public partial class MiracleButton : Button
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Text = $"{_miracle.Name}\nCost: {_miracle.FaithCost} Faith";
|
Text = BuildText();
|
||||||
|
TooltipText = BuildTooltipText();
|
||||||
|
|
||||||
Pressed += OnPressed;
|
Pressed += OnPressed;
|
||||||
}
|
}
|
||||||
@@ -35,8 +36,25 @@ public partial class MiracleButton : Button
|
|||||||
public void SetMiracle(MiracleDefinition miracle)
|
public void SetMiracle(MiracleDefinition miracle)
|
||||||
{
|
{
|
||||||
_miracle = miracle;
|
_miracle = miracle;
|
||||||
Text = $"{_miracle.Name}\nCost: {_miracle.FaithCost} Faith";
|
Text = BuildText();
|
||||||
|
TooltipText = BuildTooltipText();
|
||||||
}
|
}
|
||||||
|
|
||||||
public MiracleDefinition GetMiracle() { return _miracle; }
|
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();
|
||||||
|
}
|
||||||
}
|
}
|
@@ -6,24 +6,16 @@ namespace ParasiticGod.Scripts.Core.Effects;
|
|||||||
[GlobalClass]
|
[GlobalClass]
|
||||||
public partial class AddResourceEffect : Effect
|
public partial class AddResourceEffect : Effect
|
||||||
{
|
{
|
||||||
[Export] public ResourceType TargetResource { get; set; }
|
[Export] public Stat TargetResource { get; set; }
|
||||||
[Export] public double Value { get; set; }
|
[Export] public double Value { get; set; }
|
||||||
|
|
||||||
public override void Execute(GameState state)
|
public override void Execute(GameState state)
|
||||||
{
|
{
|
||||||
switch (TargetResource)
|
state.Modify(TargetResource, Value);
|
||||||
{
|
}
|
||||||
case ResourceType.Faith:
|
|
||||||
state.Faith += Value;
|
public override string ToString()
|
||||||
break;
|
{
|
||||||
case ResourceType.Followers:
|
return $"Add {Value} to {TargetResource}";
|
||||||
state.Followers += (long)Value;
|
|
||||||
break;
|
|
||||||
case ResourceType.Corruption:
|
|
||||||
state.Corruption += Value;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
throw new ArgumentOutOfRangeException();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -5,9 +5,7 @@ namespace ParasiticGod.Scripts.Core.Effects;
|
|||||||
[GlobalClass]
|
[GlobalClass]
|
||||||
public partial class ApplyBuffEffect : Effect
|
public partial class ApplyBuffEffect : Effect
|
||||||
{
|
{
|
||||||
public enum BuffTarget { FaithGeneration }
|
[Export] public Stat TargetStat { get; set; }
|
||||||
|
|
||||||
[Export] public BuffTarget TargetStat { get; set; }
|
|
||||||
[Export] public float Multiplier { get; set; } = 2.0f;
|
[Export] public float Multiplier { get; set; } = 2.0f;
|
||||||
[Export] public double Duration { get; set; } = 30.0;
|
[Export] public double Duration { get; set; } = 30.0;
|
||||||
|
|
||||||
@@ -21,4 +19,9 @@ public partial class ApplyBuffEffect : Effect
|
|||||||
|
|
||||||
gameState.ActiveBuffs.Add(newBuff);
|
gameState.ActiveBuffs.Add(newBuff);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override string ToString()
|
||||||
|
{
|
||||||
|
return $"Apply Buff: x{Multiplier} to {TargetStat} for {Duration} seconds";
|
||||||
|
}
|
||||||
}
|
}
|
@@ -5,32 +5,21 @@ namespace ParasiticGod.Scripts.Core.Effects;
|
|||||||
[GlobalClass]
|
[GlobalClass]
|
||||||
public partial class ConvertResourceEffect : Effect
|
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 double FromAmount { get; set; }
|
||||||
[Export] public ResourceType ToResource { get; set; }
|
[Export] public Stat ToResource { get; set; }
|
||||||
[Export] public double ToAmount { get; set; }
|
[Export] public double ToAmount { get; set; }
|
||||||
|
|
||||||
public override void Execute(GameState gameState)
|
public override void Execute(GameState gameState)
|
||||||
{
|
{
|
||||||
double GetValue(ResourceType type) => type switch {
|
if (!(gameState.Get(FromResource) >= FromAmount)) return;
|
||||||
ResourceType.Faith => gameState.Faith,
|
|
||||||
ResourceType.Followers => gameState.Followers,
|
|
||||||
ResourceType.Corruption => gameState.Corruption,
|
|
||||||
_ => 0
|
|
||||||
};
|
|
||||||
|
|
||||||
void SetValue(ResourceType type, double value) {
|
gameState.Set(FromResource, gameState.Get(FromResource) - FromAmount);
|
||||||
switch(type) {
|
gameState.Set(ToResource, gameState.Get(ToResource) + ToAmount);
|
||||||
case ResourceType.Faith: gameState.Faith = value; break;
|
}
|
||||||
case ResourceType.Followers: gameState.Followers = (long)value; break;
|
|
||||||
case ResourceType.Corruption: gameState.Corruption = value; break;
|
public override string ToString()
|
||||||
}
|
{
|
||||||
}
|
return $"Convert {FromAmount} {FromResource} to {ToAmount} {ToResource}";
|
||||||
|
|
||||||
if (GetValue(FromResource) >= FromAmount)
|
|
||||||
{
|
|
||||||
SetValue(FromResource, GetValue(FromResource) - FromAmount);
|
|
||||||
SetValue(ToResource, GetValue(ToResource) + ToAmount);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -8,4 +8,9 @@ public partial class DestroySelfEffect : Effect
|
|||||||
public override void Execute(GameState gameState)
|
public override void Execute(GameState gameState)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override string ToString()
|
||||||
|
{
|
||||||
|
return "";
|
||||||
|
}
|
||||||
}
|
}
|
@@ -5,4 +5,9 @@ namespace ParasiticGod.Scripts.Core.Effects;
|
|||||||
public abstract partial class Effect : Resource
|
public abstract partial class Effect : Resource
|
||||||
{
|
{
|
||||||
public abstract void Execute(GameState gameState);
|
public abstract void Execute(GameState gameState);
|
||||||
|
|
||||||
|
public override string ToString()
|
||||||
|
{
|
||||||
|
return GetType().Name.Replace("Effect", "");
|
||||||
|
}
|
||||||
}
|
}
|
@@ -5,7 +5,6 @@ namespace ParasiticGod.Scripts.Core.Effects;
|
|||||||
[GlobalClass]
|
[GlobalClass]
|
||||||
public partial class ModifyStatEffect : Effect
|
public partial class ModifyStatEffect : Effect
|
||||||
{
|
{
|
||||||
public enum Stat { FaithPerFollower }
|
|
||||||
public enum Operation { Add, Multiply }
|
public enum Operation { Add, Multiply }
|
||||||
|
|
||||||
[Export] public Stat TargetStat { get; set; }
|
[Export] public Stat TargetStat { get; set; }
|
||||||
@@ -14,17 +13,26 @@ public partial class ModifyStatEffect : Effect
|
|||||||
|
|
||||||
public override void Execute(GameState gameState)
|
public override void Execute(GameState gameState)
|
||||||
{
|
{
|
||||||
if (TargetStat == Stat.FaithPerFollower)
|
switch (Op)
|
||||||
{
|
{
|
||||||
switch (Op)
|
case Operation.Add:
|
||||||
{
|
var currentValue = gameState.Get(TargetStat);
|
||||||
case Operation.Add:
|
gameState.Set(TargetStat, currentValue + Value);
|
||||||
gameState.FaithPerFollower += Value;
|
break;
|
||||||
break;
|
case Operation.Multiply:
|
||||||
case Operation.Multiply:
|
var currentValueMul = gameState.Get(TargetStat);
|
||||||
gameState.FaithPerFollower *= Value;
|
gameState.Set(TargetStat, currentValueMul * Value);
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override string ToString()
|
||||||
|
{
|
||||||
|
return Op switch
|
||||||
|
{
|
||||||
|
Operation.Add => $"Add {Value} to {TargetStat}",
|
||||||
|
Operation.Multiply => $"Multiply {TargetStat} by {Value}",
|
||||||
|
_ => "Unknown Operation"
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
@@ -1,3 +0,0 @@
|
|||||||
namespace ParasiticGod.Scripts.Core.Effects;
|
|
||||||
|
|
||||||
public enum ResourceType { Faith, Followers, Corruption }
|
|
@@ -1 +0,0 @@
|
|||||||
uid://do6aurfs8oif0
|
|
@@ -13,4 +13,9 @@ public partial class UnlockMiracleEffect : Effect
|
|||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override string ToString()
|
||||||
|
{
|
||||||
|
return $"Unlock miracles: {string.Join(", ", MiraclesToUnlock)}";
|
||||||
|
}
|
||||||
}
|
}
|
@@ -6,7 +6,16 @@ public class GameLogic
|
|||||||
{
|
{
|
||||||
public void UpdateGameState(GameState state, double delta)
|
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--)
|
for (var i = state.ActiveBuffs.Count - 1; i >= 0; i--)
|
||||||
{
|
{
|
||||||
@@ -21,13 +30,13 @@ public class GameLogic
|
|||||||
|
|
||||||
public bool TryToPerformMiracle(GameState state, MiracleDefinition miracle)
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
state.Faith -= miracle.FaithCost;
|
state.Modify(Stat.Faith, -miracle.FaithCost);
|
||||||
|
|
||||||
if (miracle.Effects != null)
|
if (miracle.Effects != null)
|
||||||
{
|
{
|
||||||
foreach (var effect in miracle.Effects)
|
foreach (var effect in miracle.Effects)
|
||||||
@@ -35,9 +44,8 @@ public class GameLogic
|
|||||||
effect.Execute(state);
|
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;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -1,3 +1,4 @@
|
|||||||
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using ParasiticGod.Scripts.Core.Effects;
|
using ParasiticGod.Scripts.Core.Effects;
|
||||||
|
|
||||||
@@ -5,23 +6,32 @@ namespace ParasiticGod.Scripts.Core;
|
|||||||
|
|
||||||
public class GameState
|
public class GameState
|
||||||
{
|
{
|
||||||
public double Faith { get; set; } = 50.0;
|
private readonly Dictionary<Stat, StatData> _stats = new();
|
||||||
public double FaithPerFollower { get; set; } = 0.5;
|
|
||||||
public long Followers { get; set; } = 40;
|
|
||||||
public double Corruption { get; set; } = 0.0;
|
|
||||||
|
|
||||||
public List<Buff> ActiveBuffs { get; } = [];
|
public List<Buff> 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;
|
_stats[stat] = new StatData();
|
||||||
foreach (var buff in ActiveBuffs)
|
|
||||||
{
|
|
||||||
totalMultiplier *= buff.Multiplier;
|
|
||||||
}
|
|
||||||
return Followers * FaithPerFollower * totalMultiplier;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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<double> listener) => _stats[stat].OnChanged += listener;
|
||||||
|
|
||||||
|
public void Unsubscribe(Stat stat, Action<double> listener) => _stats[stat].OnChanged -= listener;
|
||||||
}
|
}
|
@@ -7,22 +7,21 @@ public class EffectDto
|
|||||||
{
|
{
|
||||||
public string Type { get; set; }
|
public string Type { get; set; }
|
||||||
// --- For "AddResource" Effect ---
|
// --- For "AddResource" Effect ---
|
||||||
public ResourceType TargetResource { get; set; }
|
public Stat TargetResource { get; set; }
|
||||||
public double Value { get; set; }
|
public double Value { get; set; }
|
||||||
|
|
||||||
// --- For "ApplyBuff" Effect ---
|
// --- For "ApplyBuff" Effect ---
|
||||||
public ApplyBuffEffect.BuffTarget TargetBuffStat { get; set; }
|
|
||||||
public float Multiplier { get; set; }
|
public float Multiplier { get; set; }
|
||||||
public double Duration { get; set; }
|
public double Duration { get; set; }
|
||||||
|
|
||||||
// --- For "ConvertResource" Effect ---
|
// --- For "ConvertResource" Effect ---
|
||||||
public ResourceType FromResource { get; set; }
|
public Stat FromResource { get; set; }
|
||||||
public double FromAmount { get; set; }
|
public double FromAmount { get; set; }
|
||||||
public ResourceType ToResource { get; set; }
|
public Stat ToResource { get; set; }
|
||||||
public double ToAmount { get; set; }
|
public double ToAmount { get; set; }
|
||||||
|
|
||||||
// --- For "ModifyStat" Effect ---
|
// --- For "ModifyStat" Effect ---
|
||||||
public ModifyStatEffect.Stat TargetStat { get; set; }
|
public Stat TargetStat { get; set; }
|
||||||
public ModifyStatEffect.Operation Op { get; set; }
|
public ModifyStatEffect.Operation Op { get; set; }
|
||||||
|
|
||||||
public List<string> MiraclesToUnlock { get; set; }
|
public List<string> MiraclesToUnlock { get; set; }
|
||||||
|
@@ -84,7 +84,7 @@ public static class MiracleLoader
|
|||||||
addResourceEffect.Value = effectDto.Value;
|
addResourceEffect.Value = effectDto.Value;
|
||||||
break;
|
break;
|
||||||
case ApplyBuffEffect applyBuffEffect:
|
case ApplyBuffEffect applyBuffEffect:
|
||||||
applyBuffEffect.TargetStat = effectDto.TargetBuffStat;
|
applyBuffEffect.TargetStat = effectDto.TargetStat;
|
||||||
applyBuffEffect.Multiplier = effectDto.Multiplier;
|
applyBuffEffect.Multiplier = effectDto.Multiplier;
|
||||||
applyBuffEffect.Duration = effectDto.Duration;
|
applyBuffEffect.Duration = effectDto.Duration;
|
||||||
break;
|
break;
|
||||||
|
17
Scripts/Core/Stat.cs
Normal file
17
Scripts/Core/Stat.cs
Normal file
@@ -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
|
||||||
|
}
|
1
Scripts/Core/Stat.cs.uid
Normal file
1
Scripts/Core/Stat.cs.uid
Normal file
@@ -0,0 +1 @@
|
|||||||
|
uid://lc6dt3ct28vk
|
17
Scripts/Core/StatData.cs
Normal file
17
Scripts/Core/StatData.cs
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
using System;
|
||||||
|
|
||||||
|
namespace ParasiticGod.Scripts.Core;
|
||||||
|
|
||||||
|
public class StatData
|
||||||
|
{
|
||||||
|
public double Value { get; private set; }
|
||||||
|
public event Action<double> OnChanged;
|
||||||
|
|
||||||
|
public void Set(double value)
|
||||||
|
{
|
||||||
|
if (!(Math.Abs(Value - value) > 0.001)) return;
|
||||||
|
|
||||||
|
Value = value;
|
||||||
|
OnChanged?.Invoke(Value);
|
||||||
|
}
|
||||||
|
}
|
1
Scripts/Core/StatData.cs.uid
Normal file
1
Scripts/Core/StatData.cs.uid
Normal file
@@ -0,0 +1 @@
|
|||||||
|
uid://cd1q4nlnrgtp1
|
@@ -40,7 +40,7 @@ public partial class PopulationVisualizer : Node
|
|||||||
{
|
{
|
||||||
if (_isUpdating) return;
|
if (_isUpdating) return;
|
||||||
|
|
||||||
var currentUnitCount = newState.Followers;
|
var currentUnitCount = (long)newState.Get(Stat.Followers);
|
||||||
|
|
||||||
var currentMarkersToShow = (int)currentUnitCount / _unitsPerMarker;
|
var currentMarkersToShow = (int)currentUnitCount / _unitsPerMarker;
|
||||||
var lastMarkersToShow = (int)_lastKnownUnitCount / _unitsPerMarker;
|
var lastMarkersToShow = (int)_lastKnownUnitCount / _unitsPerMarker;
|
||||||
@@ -84,8 +84,6 @@ public partial class PopulationVisualizer : Node
|
|||||||
|
|
||||||
if (i < followersToShow)
|
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 || _lastKnownTierIndex != newTierIndex)
|
||||||
{
|
{
|
||||||
if (marker.IsOccupied) marker.RemoveFollower();
|
if (marker.IsOccupied) marker.RemoveFollower();
|
||||||
|
@@ -35,7 +35,7 @@ public partial class GameBus : Node
|
|||||||
_gameLogic.UpdateGameState(_gameState, delta);
|
_gameLogic.UpdateGameState(_gameState, delta);
|
||||||
StateChanged?.Invoke(_gameState);
|
StateChanged?.Invoke(_gameState);
|
||||||
|
|
||||||
if (_gameState.Corruption >= 100)
|
if (_gameState.Get(Stat.Corruption) >= 100)
|
||||||
{
|
{
|
||||||
GD.Print("The world has died!");
|
GD.Print("The world has died!");
|
||||||
GetTree().Quit(); // For now
|
GetTree().Quit(); // For now
|
||||||
@@ -73,4 +73,9 @@ public partial class GameBus : Node
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void SubscribeToStat(Stat stat, Action<double> listener) => _gameState.Subscribe(stat, listener);
|
||||||
|
public void UnsubscribeFromStat(Stat stat, Action<double> listener) => _gameState.Unsubscribe(stat, listener);
|
||||||
|
|
||||||
|
public GameState CurrentState => _gameState;
|
||||||
}
|
}
|
@@ -22,6 +22,10 @@ config/icon="uid://dihjvrhshhklu"
|
|||||||
|
|
||||||
GameBus="*res://Scripts/Singletons/GameBus.cs"
|
GameBus="*res://Scripts/Singletons/GameBus.cs"
|
||||||
|
|
||||||
|
[display]
|
||||||
|
|
||||||
|
window/stretch/mode="canvas_items"
|
||||||
|
|
||||||
[dotnet]
|
[dotnet]
|
||||||
|
|
||||||
project/assembly_name="ParasiticGod"
|
project/assembly_name="ParasiticGod"
|
||||||
|
Reference in New Issue
Block a user