Add buff management for miracles; implement checks for active buffs and update buff identifiers

This commit is contained in:
2025-08-23 18:28:05 +02:00
parent 73a89b736e
commit 8ae0e7e80c
11 changed files with 42 additions and 4 deletions

View File

@@ -7,6 +7,7 @@
"effects": [ "effects": [
{ {
"type": "ApplyBuff", "type": "ApplyBuff",
"buffId": "gods_endurance",
"targetStat": "FaithPerFollower", "targetStat": "FaithPerFollower",
"multiplier": 2.0, "multiplier": 2.0,
"duration": 60 "duration": 60

View File

@@ -7,6 +7,7 @@
"effects": [ "effects": [
{ {
"type": "ApplyBuff", "type": "ApplyBuff",
"buffId": "harness_the_sun",
"targetStat": "CorruptionPerSecond", "targetStat": "CorruptionPerSecond",
"multiplier": -1.5, "multiplier": -1.5,
"duration": 120 "duration": 120

View File

@@ -86,6 +86,11 @@ public partial class MiracleButton : Button
missingRequirements.Add("Already unlocked subsequent powers."); missingRequirements.Add("Already unlocked subsequent powers.");
} }
if (IsBuffAlreadyActive(state))
{
missingRequirements.Add("This buff is already active.");
}
if (missingRequirements.Any()) if (missingRequirements.Any())
{ {
Disabled = true; Disabled = true;
@@ -145,4 +150,16 @@ public partial class MiracleButton : Button
return unlockEffect.MiraclesToUnlock.All(state.IsMiracleUnlocked); return unlockEffect.MiraclesToUnlock.All(state.IsMiracleUnlocked);
} }
private bool IsBuffAlreadyActive(GameState state)
{
var buffEffect = _miracle.Effects.OfType<ApplyBuffEffect>().FirstOrDefault();
if (buffEffect == null || string.IsNullOrEmpty(buffEffect.BuffId))
{
return false;
}
return state.IsBuffActive(buffEffect.BuffId);
}
} }

View File

@@ -34,16 +34,16 @@ public partial class ActiveBuffsManager : Node
var buffInstance = _activeBuffScene.Instantiate<ActiveBuffUi>(); var buffInstance = _activeBuffScene.Instantiate<ActiveBuffUi>();
AddChild(buffInstance); AddChild(buffInstance);
buffInstance.SetBuff(buff); buffInstance.SetBuff(buff);
_activeBuffUis.Add(buff.Id, buffInstance); _activeBuffUis.Add(buff.InstanceId, buffInstance);
_buffAddedSfx?.Play(); _buffAddedSfx?.Play();
} }
private void OnBuffRemoved(Buff buff) private void OnBuffRemoved(Buff buff)
{ {
if (_activeBuffUis.TryGetValue(buff.Id, out var buffUi)) if (_activeBuffUis.TryGetValue(buff.InstanceId, out var buffUi))
{ {
buffUi.QueueFree(); buffUi.QueueFree();
_activeBuffUis.Remove(buff.Id); _activeBuffUis.Remove(buff.InstanceId);
_buffRemovedSfx?.Play(); _buffRemovedSfx?.Play();
} }
} }

View File

@@ -6,12 +6,19 @@ namespace ParasiticGod.Scripts.Core.Effects;
[GlobalClass] [GlobalClass]
public partial class ApplyBuffEffect : Effect public partial class ApplyBuffEffect : Effect
{ {
[Export] public string BuffId { get; set; }
[Export] public Stat TargetStat { get; set; } [Export] public Stat 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;
public override void Execute(GameState gameState) public override void Execute(GameState gameState)
{ {
if (gameState.IsBuffActive(BuffId))
{
GD.Print($"Buff '{BuffId}' is already active. Cannot apply again.");
return;
}
var newBuff = new Buff var newBuff = new Buff
{ {
Name = $"{TargetStat} x{Multiplier}", Name = $"{TargetStat} x{Multiplier}",
@@ -20,6 +27,7 @@ public partial class ApplyBuffEffect : Effect
}; };
gameState.ActiveBuffs.Add(newBuff); gameState.ActiveBuffs.Add(newBuff);
gameState.AddActiveBuff(BuffId);
GameBus.Instance.NotifyBuffAdded(newBuff); GameBus.Instance.NotifyBuffAdded(newBuff);
} }

View File

@@ -4,7 +4,8 @@ namespace ParasiticGod.Scripts.Core.Effects;
public class Buff public class Buff
{ {
public Guid Id { get; } = Guid.NewGuid(); // Unique identifier public Guid InstanceId { get; } = Guid.NewGuid(); // Unique identifier
public string BuffId { get; set; } // Identifier for the type of buff
public string Name { get; set; } // For display purposes public string Name { get; set; } // For display purposes
public float Multiplier { get; set; } = 1.0f; public float Multiplier { get; set; } = 1.0f;
public double Duration { get; set; } public double Duration { get; set; }

View File

@@ -17,6 +17,7 @@ public class GameLogic
state.Modify(Stat.Faith, faithPerSecond * delta); state.Modify(Stat.Faith, faithPerSecond * delta);
state.Modify(Stat.Production, state.Get(Stat.ProductionPerSecond) * delta); state.Modify(Stat.Production, state.Get(Stat.ProductionPerSecond) * delta);
state.Modify(Stat.Corruption, state.Get(Stat.CorruptionPerSecond) * delta); state.Modify(Stat.Corruption, state.Get(Stat.CorruptionPerSecond) * delta);
state.Modify(Stat.Followers, state.Get(Stat.FollowersPerSecond) * delta);
for (var i = state.ActiveBuffs.Count - 1; i >= 0; i--) for (var i = state.ActiveBuffs.Count - 1; i >= 0; i--)
{ {
@@ -26,6 +27,7 @@ public class GameLogic
{ {
GameBus.Instance.NotifyBuffRemoved(buff); GameBus.Instance.NotifyBuffRemoved(buff);
state.ActiveBuffs.RemoveAt(i); state.ActiveBuffs.RemoveAt(i);
state.RemoveActiveBuff(buff.BuffId);
} }
} }
} }

View File

@@ -8,6 +8,7 @@ public class GameState
{ {
private readonly Dictionary<Stat, StatData> _stats = new(); private readonly Dictionary<Stat, StatData> _stats = new();
private readonly HashSet<string> _unlockedMiracleIds = []; private readonly HashSet<string> _unlockedMiracleIds = [];
private readonly HashSet<string> _activeBuffIds = [];
public List<Buff> ActiveBuffs { get; } = []; public List<Buff> ActiveBuffs { get; } = [];
@@ -38,4 +39,8 @@ public class GameState
public bool IsMiracleUnlocked(string miracleId) => _unlockedMiracleIds.Contains(miracleId); public bool IsMiracleUnlocked(string miracleId) => _unlockedMiracleIds.Contains(miracleId);
public void AddUnlockedMiracle(string miracleId) => _unlockedMiracleIds.Add(miracleId); public void AddUnlockedMiracle(string miracleId) => _unlockedMiracleIds.Add(miracleId);
public void RemoveUnlockedMiracle(string miracleId) => _unlockedMiracleIds.Remove(miracleId); public void RemoveUnlockedMiracle(string miracleId) => _unlockedMiracleIds.Remove(miracleId);
public bool IsBuffActive(string buffId) => _activeBuffIds.Contains(buffId);
public void AddActiveBuff(string buffId) => _activeBuffIds.Add(buffId);
public void RemoveActiveBuff(string buffId) => _activeBuffIds.Remove(buffId);
} }

View File

@@ -12,6 +12,7 @@ public class EffectDto
public double Value { get; set; } public double Value { get; set; }
// --- For "ApplyBuff" Effect --- // --- For "ApplyBuff" Effect ---
public string BuffId { get; set; }
public float Multiplier { get; set; } public float Multiplier { get; set; }
public double Duration { get; set; } public double Duration { get; set; }

View File

@@ -101,6 +101,7 @@ public static class MiracleLoader
applyBuffEffect.TargetStat = effectDto.TargetStat; applyBuffEffect.TargetStat = effectDto.TargetStat;
applyBuffEffect.Multiplier = effectDto.Multiplier; applyBuffEffect.Multiplier = effectDto.Multiplier;
applyBuffEffect.Duration = effectDto.Duration; applyBuffEffect.Duration = effectDto.Duration;
applyBuffEffect.BuffId = effectDto.BuffId;
break; break;
case ConvertResourceEffect convertResourceEffect: case ConvertResourceEffect convertResourceEffect:
convertResourceEffect.FromResource = effectDto.FromResource; convertResourceEffect.FromResource = effectDto.FromResource;

View File

@@ -11,6 +11,7 @@ public enum Stat
// Passive Generation Stats // Passive Generation Stats
ProductionPerSecond, ProductionPerSecond,
CorruptionPerSecond, CorruptionPerSecond,
FollowersPerSecond,
// Modifying Stats // Modifying Stats
FaithPerFollower FaithPerFollower