Add NotificationManager and NotificationLabel for age advancement notifications; refactor scripts into Components directory
This commit is contained in:
46
Scripts/Components/ActiveBuffsManager.cs
Normal file
46
Scripts/Components/ActiveBuffsManager.cs
Normal file
@@ -0,0 +1,46 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Godot;
|
||||
using ParasiticGod.Scripts;
|
||||
using ParasiticGod.Scripts.Core.Effects;
|
||||
using ParasiticGod.Scripts.Singletons;
|
||||
|
||||
namespace ParasiticGod.Scripts.Components;
|
||||
|
||||
[GlobalClass]
|
||||
public partial class ActiveBuffsManager : Node
|
||||
{
|
||||
[Export] private PackedScene _activeBuffScene;
|
||||
|
||||
private readonly Dictionary<Guid, ActiveBuffUi> _activeBuffUis = new();
|
||||
|
||||
public override void _Ready()
|
||||
{
|
||||
GameBus.Instance.BuffAdded += OnBuffAdded;
|
||||
GameBus.Instance.BuffRemoved += OnBuffRemoved;
|
||||
}
|
||||
|
||||
public override void _ExitTree()
|
||||
{
|
||||
if (GameBus.Instance == null) return;
|
||||
GameBus.Instance.BuffAdded -= OnBuffAdded;
|
||||
GameBus.Instance.BuffRemoved -= OnBuffRemoved;
|
||||
}
|
||||
|
||||
private void OnBuffAdded(Buff buff)
|
||||
{
|
||||
var buffInstance = _activeBuffScene.Instantiate<ActiveBuffUi>();
|
||||
AddChild(buffInstance);
|
||||
buffInstance.SetBuff(buff);
|
||||
_activeBuffUis.Add(buff.Id, buffInstance);
|
||||
}
|
||||
|
||||
private void OnBuffRemoved(Buff buff)
|
||||
{
|
||||
if (_activeBuffUis.TryGetValue(buff.Id, out var buffUi))
|
||||
{
|
||||
buffUi.QueueFree();
|
||||
_activeBuffUis.Remove(buff.Id);
|
||||
}
|
||||
}
|
||||
}
|
1
Scripts/Components/ActiveBuffsManager.cs.uid
Normal file
1
Scripts/Components/ActiveBuffsManager.cs.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://ddshg236tlltt
|
74
Scripts/Components/ForestVisualizer.cs
Normal file
74
Scripts/Components/ForestVisualizer.cs
Normal file
@@ -0,0 +1,74 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Godot;
|
||||
using ParasiticGod.Scripts.Core;
|
||||
using ParasiticGod.Scripts.Singletons;
|
||||
|
||||
namespace ParasiticGod.Scripts.Components;
|
||||
|
||||
[GlobalClass]
|
||||
public partial class ForestVisualizer : Node
|
||||
{
|
||||
[Export] private Node2D _treesContainer;
|
||||
|
||||
private List<Node2D> _trees = [];
|
||||
private int _lastKnownTreesToShow = -1;
|
||||
private bool _isUpdating = false;
|
||||
|
||||
public override void _Ready()
|
||||
{
|
||||
foreach (var child in _treesContainer.GetChildren())
|
||||
{
|
||||
if (child is Node2D tree)
|
||||
{
|
||||
_trees.Add(tree);
|
||||
}
|
||||
}
|
||||
|
||||
var rng = new RandomNumberGenerator();
|
||||
rng.Randomize();
|
||||
_trees = _trees.OrderBy(_ => Guid.NewGuid()).ToList();
|
||||
|
||||
GameBus.Instance.StateChanged += OnStateChanged;
|
||||
}
|
||||
|
||||
public override void _ExitTree()
|
||||
{
|
||||
GameBus.Instance.StateChanged -= OnStateChanged;
|
||||
}
|
||||
|
||||
private void OnStateChanged(GameState newState)
|
||||
{
|
||||
if (_isUpdating) return;
|
||||
|
||||
var corruptionRatio = newState.Get(Stat.Corruption) / 100.0;
|
||||
var treesToShow = (int)(_trees.Count * (1.0 - corruptionRatio));
|
||||
|
||||
if (treesToShow != _lastKnownTreesToShow)
|
||||
{
|
||||
UpdateForestProgressively(treesToShow);
|
||||
}
|
||||
}
|
||||
|
||||
private async void UpdateForestProgressively(int treesToShow)
|
||||
{
|
||||
_isUpdating = true;
|
||||
|
||||
for (var i = 0; i < _trees.Count; i++)
|
||||
{
|
||||
var tree = _trees[i];
|
||||
var shouldBeVisible = i < treesToShow;
|
||||
var needsChange = tree.Visible != shouldBeVisible;
|
||||
|
||||
if (needsChange)
|
||||
{
|
||||
tree.Visible = shouldBeVisible;
|
||||
await ToSignal(GetTree().CreateTimer(0.01f), SceneTreeTimer.SignalName.Timeout);
|
||||
}
|
||||
}
|
||||
|
||||
_lastKnownTreesToShow = treesToShow;
|
||||
_isUpdating = false;
|
||||
}
|
||||
}
|
1
Scripts/Components/ForestVisualizer.cs.uid
Normal file
1
Scripts/Components/ForestVisualizer.cs.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://furbvcmw31bx
|
31
Scripts/Components/NotificationManager.cs
Normal file
31
Scripts/Components/NotificationManager.cs
Normal file
@@ -0,0 +1,31 @@
|
||||
using Godot;
|
||||
using ParasiticGod.Scripts;
|
||||
using ParasiticGod.Scripts.Singletons;
|
||||
|
||||
namespace ParasiticGod.Scripts.Components;
|
||||
|
||||
[GlobalClass]
|
||||
public partial class NotificationManager : CanvasLayer
|
||||
{
|
||||
[Export] private PackedScene _notificationLabelScene;
|
||||
|
||||
public override void _Ready()
|
||||
{
|
||||
GameBus.Instance.AgeAdvanced += OnAgeAdvanced;
|
||||
}
|
||||
|
||||
public override void _ExitTree()
|
||||
{
|
||||
if (GameBus.Instance != null)
|
||||
{
|
||||
GameBus.Instance.AgeAdvanced -= OnAgeAdvanced;
|
||||
}
|
||||
}
|
||||
|
||||
private void OnAgeAdvanced(string ageName)
|
||||
{
|
||||
var notification = _notificationLabelScene.Instantiate<NotificationLabel>();
|
||||
AddChild(notification);
|
||||
notification.ShowNotification($"You have entered\n{ageName}!");
|
||||
}
|
||||
}
|
1
Scripts/Components/NotificationManager.cs.uid
Normal file
1
Scripts/Components/NotificationManager.cs.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://c6uh5h3sdlg7n
|
116
Scripts/Components/PopulationVisualizer.cs
Normal file
116
Scripts/Components/PopulationVisualizer.cs
Normal file
@@ -0,0 +1,116 @@
|
||||
using System.Collections.Generic;
|
||||
using Godot;
|
||||
using Godot.Collections;
|
||||
using ParasiticGod.Scripts.Core;
|
||||
using ParasiticGod.Scripts.Singletons;
|
||||
|
||||
namespace ParasiticGod.Scripts.Components;
|
||||
|
||||
[GlobalClass]
|
||||
public partial class PopulationVisualizer : Node
|
||||
{
|
||||
[Export] private Node2D _markersContainer;
|
||||
[Export] private int _unitsPerMarker = 5;
|
||||
[Export] private Array<TierDefinition> _tiers;
|
||||
|
||||
private readonly List<FollowerMarker> _markers = [];
|
||||
private long _lastKnownUnitCount = -1;
|
||||
private int _lastKnownTierIndex = -1;
|
||||
private bool _isUpdating = false;
|
||||
|
||||
public override void _Ready()
|
||||
{
|
||||
foreach (var child in _markersContainer.GetChildren())
|
||||
{
|
||||
if (child is FollowerMarker marker)
|
||||
{
|
||||
_markers.Add(marker);
|
||||
}
|
||||
}
|
||||
|
||||
GameBus.Instance.StateChanged += OnStateChanged;
|
||||
}
|
||||
|
||||
public override void _ExitTree()
|
||||
{
|
||||
GameBus.Instance.StateChanged -= OnStateChanged;
|
||||
}
|
||||
|
||||
private void OnStateChanged(GameState newState)
|
||||
{
|
||||
if (_isUpdating) return;
|
||||
|
||||
var currentUnitCount = (long)newState.Get(Stat.Followers);
|
||||
|
||||
var currentMarkersToShow = (int)currentUnitCount / _unitsPerMarker;
|
||||
var lastMarkersToShow = (int)_lastKnownUnitCount / _unitsPerMarker;
|
||||
var newTierIndex = GetTierIndex(currentUnitCount);
|
||||
|
||||
if (currentMarkersToShow != lastMarkersToShow || newTierIndex != _lastKnownTierIndex)
|
||||
{
|
||||
UpdateVisualsProgressively(currentUnitCount, newTierIndex);
|
||||
}
|
||||
}
|
||||
|
||||
private int GetTierIndex(long currentUnitCount)
|
||||
{
|
||||
for (var i = _tiers.Count - 1; i >= 0; i--)
|
||||
{
|
||||
if (currentUnitCount >= _tiers[i].Threshold)
|
||||
{
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
private async void UpdateVisualsProgressively(long currentUnitCount, int newTierIndex)
|
||||
{
|
||||
_isUpdating = true;
|
||||
|
||||
if (newTierIndex < 0)
|
||||
{
|
||||
_isUpdating = false;
|
||||
return;
|
||||
}
|
||||
|
||||
var followersToShow = (int)currentUnitCount / _unitsPerMarker;
|
||||
var currentTier = _tiers[newTierIndex];
|
||||
|
||||
for (var i = 0; i < _markers.Count; i++)
|
||||
{
|
||||
var marker = _markers[i];
|
||||
var needsChange = false;
|
||||
|
||||
if (i < followersToShow)
|
||||
{
|
||||
if (!marker.IsOccupied || _lastKnownTierIndex != newTierIndex)
|
||||
{
|
||||
if (marker.IsOccupied) marker.RemoveFollower();
|
||||
var followerInstance = currentTier.Scene.Instantiate<Follower>();
|
||||
marker.PlaceFollower(followerInstance);
|
||||
needsChange = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (marker.IsOccupied)
|
||||
{
|
||||
marker.RemoveFollower();
|
||||
needsChange = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (needsChange)
|
||||
{
|
||||
await ToSignal(GetTree().CreateTimer(0.1f), SceneTreeTimer.SignalName.Timeout);
|
||||
}
|
||||
}
|
||||
|
||||
_lastKnownUnitCount = currentUnitCount;
|
||||
_lastKnownTierIndex = newTierIndex;
|
||||
_isUpdating = false;
|
||||
|
||||
GameBus.Instance.NotifyPopulationVisualsUpdated();
|
||||
}
|
||||
}
|
1
Scripts/Components/PopulationVisualizer.cs.uid
Normal file
1
Scripts/Components/PopulationVisualizer.cs.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://dj2wyrq07gfp2
|
1
Scripts/Components/ProgressiveVisualizer.cs.uid
Normal file
1
Scripts/Components/ProgressiveVisualizer.cs.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://m3qqshwpk16h
|
101
Scripts/Components/RoadManager.cs
Normal file
101
Scripts/Components/RoadManager.cs
Normal file
@@ -0,0 +1,101 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Godot;
|
||||
using ParasiticGod.Scripts.Singletons;
|
||||
|
||||
namespace ParasiticGod.Scripts.Components;
|
||||
|
||||
[GlobalClass]
|
||||
public partial class RoadManager : Node2D
|
||||
{
|
||||
[Export] private Node2D _markersContainer;
|
||||
[Export] private float _roadWidth = 4.0f;
|
||||
[Export] private Color _roadColor = new("saddlebrown");
|
||||
|
||||
[Export] private Follower.FollowerTier _minimumTierForRoads = Follower.FollowerTier.Tier2;
|
||||
|
||||
private Line2D _roadNetwork;
|
||||
|
||||
public override void _Ready()
|
||||
{
|
||||
_roadNetwork = new Line2D
|
||||
{
|
||||
Width = _roadWidth,
|
||||
DefaultColor = _roadColor,
|
||||
};
|
||||
AddChild(_roadNetwork);
|
||||
|
||||
Callable.From(() =>
|
||||
{
|
||||
GenerateRoads();
|
||||
GameBus.Instance.PopulationVisualsUpdated += GenerateRoads;
|
||||
}).CallDeferred();
|
||||
}
|
||||
|
||||
public override void _ExitTree()
|
||||
{
|
||||
if (GameBus.Instance != null)
|
||||
{
|
||||
GameBus.Instance.PopulationVisualsUpdated -= GenerateRoads;
|
||||
}
|
||||
}
|
||||
|
||||
private void GenerateRoads()
|
||||
{
|
||||
_roadNetwork.ClearPoints();
|
||||
|
||||
var activeMarkers = _markersContainer.GetChildren()
|
||||
.OfType<FollowerMarker>()
|
||||
.Where(m => m.IsOccupied && m.FollowerInstance != null &&
|
||||
m.FollowerInstance.Tier >= _minimumTierForRoads)
|
||||
.ToList();
|
||||
|
||||
if (activeMarkers.Count < 2) return;
|
||||
|
||||
var treeNodes = new HashSet<FollowerMarker>();
|
||||
var remainingNodes = new List<FollowerMarker>(activeMarkers);
|
||||
var edges = new List<(Vector2, Vector2)>();
|
||||
|
||||
var startNode = remainingNodes[0];
|
||||
treeNodes.Add(startNode);
|
||||
remainingNodes.RemoveAt(0);
|
||||
|
||||
while (remainingNodes.Any())
|
||||
{
|
||||
FollowerMarker bestSource = null;
|
||||
FollowerMarker bestDest = null;
|
||||
var minDistanceSq = float.MaxValue;
|
||||
|
||||
foreach (var source in treeNodes)
|
||||
{
|
||||
foreach (var dest in remainingNodes)
|
||||
{
|
||||
var distSq = source.GlobalPosition.DistanceSquaredTo(dest.GlobalPosition);
|
||||
if (distSq < minDistanceSq)
|
||||
{
|
||||
minDistanceSq = distSq;
|
||||
bestSource = source;
|
||||
bestDest = dest;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (bestDest != null)
|
||||
{
|
||||
treeNodes.Add(bestDest);
|
||||
remainingNodes.Remove(bestDest);
|
||||
edges.Add((bestSource.Position, bestDest.Position));
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var (start, end) in edges)
|
||||
{
|
||||
_roadNetwork.AddPoint(start);
|
||||
_roadNetwork.AddPoint(end);
|
||||
}
|
||||
}
|
||||
}
|
1
Scripts/Components/RoadManager.cs.uid
Normal file
1
Scripts/Components/RoadManager.cs.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://cw8gpeaq3yfjn
|
Reference in New Issue
Block a user