diff --git a/project.godot b/project.godot index e5e0ff7..3e880d1 100644 --- a/project.godot +++ b/project.godot @@ -53,6 +53,11 @@ ui_down={ , Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":83,"key_label":0,"unicode":115,"location":0,"echo":false,"script":null) ] } +debug_cycle_time={ +"deadzone": 0.5, +"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":84,"key_label":0,"unicode":116,"location":0,"echo":false,"script":null) +] +} [physics] diff --git a/scenes/Main.tscn b/scenes/Main.tscn index 3b8434d..a5c3edb 100644 --- a/scenes/Main.tscn +++ b/scenes/Main.tscn @@ -4,7 +4,9 @@ [ext_resource type="Script" uid="uid://cqdq8fslu7cyp" path="res://scripts/world/ChunkManager.cs" id="2_0bbpv"] [ext_resource type="Script" uid="uid://db2vbbh5737ke" path="res://scripts/core/PackManager.cs" id="3_rarhs"] [ext_resource type="PackedScene" uid="uid://bs7qu34sfgvjx" path="res://scenes/world/PickupMarker.tscn" id="3_vcsgt"] +[ext_resource type="PackedScene" uid="uid://bjil24xdbm76x" path="res://scenes/world/CreatureMarker.tscn" id="4_nxtc6"] [ext_resource type="Script" uid="uid://osk74jjhtcjy" path="res://scripts/core/SaveManager.cs" id="4_rarhs"] +[ext_resource type="Script" uid="uid://b6gxknud5unt" path="res://scripts/core/WorldClock.cs" id="6_c01mt"] [node name="Main" type="Node2D" unique_id=1194367579] @@ -18,9 +20,14 @@ PlayerPath = NodePath("../Player") PackManagerPath = NodePath("../../PackManager") PickupMarkerScene = ExtResource("3_vcsgt") SaveManagerPath = NodePath("../../SaveManager") +CreatureMarkerScene = ExtResource("4_nxtc6") +WorldClockPath = NodePath("../../WorldClock") [node name="PackManager" type="Node" parent="." unique_id=1706387276] script = ExtResource("3_rarhs") [node name="SaveManager" type="Node" parent="." unique_id=1115563669] script = ExtResource("4_rarhs") + +[node name="WorldClock" type="Node" parent="." unique_id=437350596] +script = ExtResource("6_c01mt") diff --git a/scenes/world/CreatureMarker.tscn b/scenes/world/CreatureMarker.tscn new file mode 100644 index 0000000..784f40a --- /dev/null +++ b/scenes/world/CreatureMarker.tscn @@ -0,0 +1,5 @@ +[gd_scene format=3 uid="uid://bjil24xdbm76x"] + +[node name="CreatureMarker" type="Node2D" unique_id=1874810005] + +[node name="Visual" type="Node2D" parent="." unique_id=309456162] diff --git a/scripts/core/WorldClock.cs b/scripts/core/WorldClock.cs new file mode 100644 index 0000000..e3dab86 --- /dev/null +++ b/scripts/core/WorldClock.cs @@ -0,0 +1,30 @@ +using Godot; + +public partial class WorldClock : Node +{ + public enum TimeOfDay { Morning, Day, Night } + + [Export] public TimeOfDay Current { get; private set; } = TimeOfDay.Day; + + public override void _Process(double delta) + { + // Debug toggle: press T to cycle + if (Input.IsActionJustPressed("debug_cycle_time")) + { + Current = Current switch + { + TimeOfDay.Morning => TimeOfDay.Day, + TimeOfDay.Day => TimeOfDay.Night, + _ => TimeOfDay.Morning + }; + GD.Print($"TimeOfDay -> {Current}"); + } + } + + public static string ToPackString(TimeOfDay t) => t switch + { + TimeOfDay.Morning => "morning", + TimeOfDay.Day => "day", + _ => "night" + }; +} diff --git a/scripts/core/WorldClock.cs.uid b/scripts/core/WorldClock.cs.uid new file mode 100644 index 0000000..0c229d6 --- /dev/null +++ b/scripts/core/WorldClock.cs.uid @@ -0,0 +1 @@ +uid://b6gxknud5unt diff --git a/scripts/world/ChunkManager.cs b/scripts/world/ChunkManager.cs index 961dab8..6985102 100644 --- a/scripts/world/ChunkManager.cs +++ b/scripts/world/ChunkManager.cs @@ -10,6 +10,11 @@ public partial class ChunkManager : Node2D [Export] public int LoadRadius { get; set; } = 1; // 1 => 3x3 [Export] public PackedScene PickupMarkerScene { get; set; } [Export] public NodePath SaveManagerPath { get; set; } + [Export] public PackedScene CreatureMarkerScene { get; set; } + [Export] public NodePath WorldClockPath { get; set; } + [Export] public int MaxCreaturesPerChunk { get; set; } = 3; + private WorldClock? _clock; + private WorldClock.TimeOfDay? _lastTime; private SaveManager? _save; private CharacterBody2D? _player; private PackManager? _packs; @@ -36,6 +41,9 @@ public partial class ChunkManager : Node2D _save = GetNodeOrNull(SaveManagerPath); if (_save == null) GD.PrintErr("ChunkManager: SaveManagerPath not set or invalid."); + _clock = GetNodeOrNull(WorldClockPath); + if (_clock == null) GD.PrintErr("ChunkManager: WorldClockPath not set or invalid."); + LoadWorldIndex(); } @@ -95,6 +103,17 @@ public partial class ChunkManager : Node2D _loaded[k].QueueFree(); _loaded.Remove(k); } + + if (_clock != null) + { + if (_lastTime == null) _lastTime = _clock.Current; + + if (_clock.Current != _lastTime) + { + _lastTime = _clock.Current; + RefreshCreaturesInLoadedChunks(); + } + } } private void EnsureLoaded(int x, int y) @@ -121,8 +140,10 @@ public partial class ChunkManager : Node2D var biome = data.biome ?? "biome:unknown"; var node = CreateDebugChunkNode(x, y, _world!.chunk_size_px, biome); - AddChunkMarkers(node, data); + node.SetMeta("chunk_data", data); + // Put the chunk into the scene tree first so Timers can run. AddChild(node); + AddChunkMarkers(node, data); _loaded[key] = node; } @@ -228,6 +249,12 @@ public partial class ChunkManager : Node2D } // Collision rects: gray outlines (optional later) + + if (data.spawn_zones != null) + { + foreach (var z in data.spawn_zones) + SpawnCreaturesForZone(chunkNode, z); + } } private static long NowUnixSeconds() @@ -326,6 +353,63 @@ public partial class ChunkManager : Node2D }; chunkNode.AddChild(timer); - timer.Start(); + // Start after the node is fully in-tree (avoids start-before-tree edge cases). + timer.CallDeferred(Timer.MethodName.Start); } + + private void SpawnCreaturesForZone(Node2D chunkNode, ChunkSpawnZone zone) + { + if (_clock == null || CreatureMarkerScene == null) return; + + var timeStr = WorldClock.ToPackString(_clock.Current); + if (zone.time_windows != null && zone.time_windows.Count > 0 && !zone.time_windows.Contains(timeStr)) + return; + + // Dedup: ensure one spawn container per zone + var containerName = $"Creatures_{zone.id.Replace(":", "_")}"; + if (chunkNode.HasNode(containerName)) + return; + + var container = new Node2D { Name = containerName }; + chunkNode.AddChild(container); + + var r = zone.rect; // [x,y,w,h] + var rng = new RandomNumberGenerator(); + rng.Randomize(); + + var count = Math.Min(MaxCreaturesPerChunk, 3); + for (int i = 0; i < count; i++) + { + var c = (Node2D)CreatureMarkerScene.Instantiate(); + c.Position = new Vector2( + r[0] + rng.RandfRange(0, r[2]), + r[1] + rng.RandfRange(0, r[3]) + ); + container.AddChild(c); + } + } + + private void RefreshCreaturesInLoadedChunks() + { + foreach (var chunk in _loaded.Values) + { + // Remove existing creature containers + foreach (var child in chunk.GetChildren()) + { + if (child is Node n && n.Name.StartsWith("Creatures_")) + n.QueueFree(); + } + + // Re-read spawn zones by re-parsing the chunk json is overkill. + // v0 hack: store ChunkData on the chunk node as metadata. + if (chunk.HasMeta("chunk_data")) + { + var data = (ChunkData)chunk.GetMeta("chunk_data"); + if (data.spawn_zones != null) + foreach (var z in data.spawn_zones) + SpawnCreaturesForZone(chunk, z); + } + } + } + } diff --git a/scripts/world/CreatureVisual.cs b/scripts/world/CreatureVisual.cs new file mode 100644 index 0000000..e4f3a95 --- /dev/null +++ b/scripts/world/CreatureVisual.cs @@ -0,0 +1,13 @@ +using Godot; + +public partial class CreatureVisual : Node2D +{ + [Export] public float Radius = 8f; + + public override void _Draw() + { + DrawCircle(Vector2.Zero, Radius, new Color(1f, 0.8f, 0.2f, 0.9f)); + } + + public override void _Ready() => QueueRedraw(); +} diff --git a/scripts/world/CreatureVisual.cs.uid b/scripts/world/CreatureVisual.cs.uid new file mode 100644 index 0000000..faf2853 --- /dev/null +++ b/scripts/world/CreatureVisual.cs.uid @@ -0,0 +1 @@ +uid://c3276p03ic158