basic natural respawn

This commit is contained in:
anonoe 2026-02-10 16:11:33 +01:00
parent bf874ba633
commit 63ca3220d1
Signed by: anonoe
SSH key fingerprint: SHA256:OnAs6gNQelOnDiY5tBpDYKQiuTgBvnmIdMo5P09cdqg
3 changed files with 35 additions and 6 deletions

View file

@ -21,7 +21,7 @@
"id": "pickup:forest_herb_01", "id": "pickup:forest_herb_01",
"item": "item:forest_herb", "item": "item:forest_herb",
"pos": [120, 140], "pos": [120, 140],
"respawn_seconds": 600 "respawn_seconds": 5
}, },
{ {
"id": "pickup:rusty_coin_01", "id": "pickup:rusty_coin_01",

View file

@ -3,7 +3,12 @@ using System.Collections.Generic;
public class SaveState public class SaveState
{ {
// Permanent one-time removals (e.g. chests, unique items)
public HashSet<string> CollectedPickups { get; set; } = new(); public HashSet<string> CollectedPickups { get; set; } = new();
// Respawnables: pickupId -> unixTimeSeconds when it becomes available again
public Dictionary<string, long> PickupRespawnAt { get; set; } = new();
//public Vector2I? LastPlayerChunk { get; set; } // optional debug, requires "using Godot;" //public Vector2I? LastPlayerChunk { get; set; } // optional debug, requires "using Godot;"
//public int[]? LastPlayerChunk { get; set; } // [x,y] same debug as above, does not require Godot //public int[]? LastPlayerChunk { get; set; } // [x,y] same debug as above, does not require Godot
} }

View file

@ -158,16 +158,34 @@ public partial class ChunkManager : Node2D
return n; return n;
} }
private static long NowUnixSeconds()
{
return DateTimeOffset.UtcNow.ToUnixTimeSeconds();
}
private void AddChunkMarkers(Node2D chunkNode, ChunkData data) private void AddChunkMarkers(Node2D chunkNode, ChunkData data)
{ {
if (_save == null || PickupMarkerScene == null) return; if (_save == null || PickupMarkerScene == null) return;
if (data.pickups != null && _save != null) if (data.pickups != null && _save != null)
{ {
var now = NowUnixSeconds();
foreach (var p in data.pickups) foreach (var p in data.pickups)
{ {
if (_save.State.CollectedPickups.Contains(p.id)) if (_save == null || PickupMarkerScene == null)
continue; // already collected return;
if (p.respawn_seconds <= 0)
{
if (_save.State.CollectedPickups.Contains(p.id))
continue;
}
else
{
if (_save.State.PickupRespawnAt.TryGetValue(p.id, out var respawnAt) && now < respawnAt)
continue;
}
var marker = (PickupMarker)PickupMarkerScene.Instantiate(); var marker = (PickupMarker)PickupMarkerScene.Instantiate();
marker.Position = new Vector2(p.pos[0], p.pos[1]); marker.Position = new Vector2(p.pos[0], p.pos[1]);
@ -178,12 +196,18 @@ public partial class ChunkManager : Node2D
{ {
GD.Print($"Picked up {itemId} ({pickupId})"); GD.Print($"Picked up {itemId} ({pickupId})");
_save.State.CollectedPickups.Add(pickupId); if (p.respawn_seconds <= 0)
_save.Save(); {
_save.State.CollectedPickups.Add(pickupId);
}
else
{
_save.State.PickupRespawnAt[pickupId] = NowUnixSeconds() + p.respawn_seconds;
}
_save.Save();
marker.QueueFree(); marker.QueueFree();
}; };
chunkNode.AddChild(marker); chunkNode.AddChild(marker);
} }
} }