feat: assign NPC home positions near village houses

Add home_positions export to SimulationManager. When configured, NPCs get homes assigned from the array wrapping around for more NPCs than homes. main.tscn now sets 6 home positions near the three village houses, so each NPC has a real home to walk to at night. Empty home_positions leaves the spawn-point-as-home backward-compatible behavior.
This commit is contained in:
2026-07-08 18:32:08 +02:00
parent cab732a977
commit adedf28417
2 changed files with 24 additions and 17 deletions
+18 -17
View File
@@ -7,10 +7,10 @@
[ext_resource type="PackedScene" uid="uid://dhxxyprqflotq" path="res://player/npc/NpcVisual.tscn" id="5_lquwl"] [ext_resource type="PackedScene" uid="uid://dhxxyprqflotq" path="res://player/npc/NpcVisual.tscn" id="5_lquwl"]
[ext_resource type="Script" uid="uid://cjvbgqx8rao0t" path="res://world/ui/ui.gd" id="6_7mycd"] [ext_resource type="Script" uid="uid://cjvbgqx8rao0t" path="res://world/ui/ui.gd" id="6_7mycd"]
[ext_resource type="Script" uid="uid://bbwol3mrjgn2x" path="res://world/active_world_adapter.gd" id="9_adapter"] [ext_resource type="Script" uid="uid://bbwol3mrjgn2x" path="res://world/active_world_adapter.gd" id="9_adapter"]
[ext_resource type="Script" path="res://simulation/persistence/SaveSlotController.gd" id="10_save"] [ext_resource type="Script" uid="uid://cwvdljsh148wh" path="res://simulation/persistence/SaveSlotController.gd" id="10_save"]
[ext_resource type="PackedScene" path="res://world/jajce/JajceWorld.tscn" id="11_jajce"] [ext_resource type="PackedScene" path="res://world/jajce/JajceWorld.tscn" id="11_jajce"]
[ext_resource type="Script" path="res://world/ui/time_dial.gd" id="12_timedial"] [ext_resource type="Script" uid="uid://cascjhf8lsvay" path="res://world/ui/time_dial.gd" id="12_timedial"]
[ext_resource type="Script" path="res://world/demo/DemoController.gd" id="13_demo"] [ext_resource type="Script" uid="uid://bivrsk5ukgnoo" path="res://world/demo/DemoController.gd" id="13_demo"]
[sub_resource type="CapsuleShape3D" id="CapsuleShape3D_o5qli"] [sub_resource type="CapsuleShape3D" id="CapsuleShape3D_o5qli"]
radius = 0.4 radius = 0.4
@@ -22,7 +22,7 @@ height = 1.7
[node name="Main" type="Node3D" unique_id=1850341560] [node name="Main" type="Node3D" unique_id=1850341560]
[node name="JajceWorld" parent="." instance=ExtResource("11_jajce")] [node name="JajceWorld" parent="." unique_id=1023795383 instance=ExtResource("11_jajce")]
[node name="Player" type="CharacterBody3D" parent="." unique_id=2022843760 node_paths=PackedStringArray("camera_rig", "simulation_manager", "pantry_storage", "guard_site", "study_site")] [node name="Player" type="CharacterBody3D" parent="." unique_id=2022843760 node_paths=PackedStringArray("camera_rig", "simulation_manager", "pantry_storage", "guard_site", "study_site")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.05, 0) transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.05, 0)
@@ -59,15 +59,16 @@ max_zoom_offset = Vector3(0, 20, 15)
current = true current = true
fov = 65.0 fov = 65.0
[node name="ActiveWorldAdapter" type="Node" parent="." node_paths=PackedStringArray("pantry_storage")] [node name="ActiveWorldAdapter" type="Node" parent="." unique_id=1773902505 node_paths=PackedStringArray("pantry_storage")]
script = ExtResource("9_adapter") script = ExtResource("9_adapter")
pantry_storage = NodePath("../JajceWorld/WorldObjects/StorageSites/VillagePantry") pantry_storage = NodePath("../JajceWorld/WorldObjects/StorageSites/VillagePantry")
[node name="SimulationManager" type="Node" parent="." unique_id=1099676814 node_paths=PackedStringArray("active_world_adapter")] [node name="SimulationManager" type="Node" parent="." unique_id=1099676814 node_paths=PackedStringArray("active_world_adapter")]
script = ExtResource("3_lquwl") script = ExtResource("3_lquwl")
active_world_adapter = NodePath("../ActiveWorldAdapter") active_world_adapter = NodePath("../ActiveWorldAdapter")
home_positions = Array[Vector3]([Vector3(-15, 2, 8.5), Vector3(-13.5, 2, 6.5), Vector3(-8.5, 2, 3), Vector3(-6.5, 2, 1.5), Vector3(-15, 2, -2.5), Vector3(-13.5, 2, -5)])
[node name="SaveSlotController" type="Node" parent="." node_paths=PackedStringArray("simulation_manager")] [node name="SaveSlotController" type="Node" parent="." unique_id=1281154019 node_paths=PackedStringArray("simulation_manager")]
script = ExtResource("10_save") script = ExtResource("10_save")
simulation_manager = NodePath("../SimulationManager") simulation_manager = NodePath("../SimulationManager")
@@ -85,11 +86,6 @@ active_npcs_parent = NodePath("../ActiveNPCs")
script = ExtResource("6_7mycd") script = ExtResource("6_7mycd")
simulation_manager = NodePath("../SimulationManager") simulation_manager = NodePath("../SimulationManager")
[node name="DemoController" type="Node" parent="." node_paths=PackedStringArray("ui", "active_npcs_parent")]
script = ExtResource("13_demo")
ui = NodePath("../UI")
active_npcs_parent = NodePath("../ActiveNPCs")
[node name="VillagePanel" type="PanelContainer" parent="UI" unique_id=482126250] [node name="VillagePanel" type="PanelContainer" parent="UI" unique_id=482126250]
offset_left = 20.0 offset_left = 20.0
offset_top = 20.0 offset_top = 20.0
@@ -107,7 +103,7 @@ theme_override_constants/margin_bottom = 4
layout_mode = 2 layout_mode = 2
theme_override_font_sizes/font_size = 10 theme_override_font_sizes/font_size = 10
[node name="NpcInspectorPanel" type="PanelContainer" parent="UI"] [node name="NpcInspectorPanel" type="PanelContainer" parent="UI" unique_id=1165556983]
anchors_preset = 1 anchors_preset = 1
anchor_left = 1.0 anchor_left = 1.0
anchor_right = 1.0 anchor_right = 1.0
@@ -117,24 +113,29 @@ offset_right = -20.0
offset_bottom = 330.0 offset_bottom = 330.0
grow_horizontal = 0 grow_horizontal = 0
[node name="MarginContainer" type="MarginContainer" parent="UI/NpcInspectorPanel"] [node name="MarginContainer" type="MarginContainer" parent="UI/NpcInspectorPanel" unique_id=1227722850]
layout_mode = 2 layout_mode = 2
theme_override_constants/margin_left = 16 theme_override_constants/margin_left = 16
theme_override_constants/margin_top = 12 theme_override_constants/margin_top = 12
theme_override_constants/margin_right = 16 theme_override_constants/margin_right = 16
theme_override_constants/margin_bottom = 12 theme_override_constants/margin_bottom = 12
[node name="NpcInspectorLabel" type="Label" parent="UI/NpcInspectorPanel/MarginContainer"] [node name="NpcInspectorLabel" type="Label" parent="UI/NpcInspectorPanel/MarginContainer" unique_id=1036784952]
layout_mode = 2 layout_mode = 2
theme_override_colors/font_color = Color(0.96, 0.91, 0.78, 1) theme_override_colors/font_color = Color(0.96, 0.91, 0.78, 1)
theme_override_font_sizes/font_size = 15 theme_override_font_sizes/font_size = 15
text = "Villager inspector" text = "Villager inspector"
[node name="TimeDial" type="Control" parent="UI" node_paths=PackedStringArray("simulation_manager")] [node name="TimeDial" type="Control" parent="UI" unique_id=191345668]
layout_mode = 0 layout_mode = 3
anchors_preset = 0
offset_left = 880.0 offset_left = 880.0
offset_top = 6.0 offset_top = 6.0
offset_right = 940.0 offset_right = 940.0
offset_bottom = 66.0 offset_bottom = 66.0
script = ExtResource("12_timedial") script = ExtResource("12_timedial")
simulation_manager = NodePath("../SimulationManager")
[node name="DemoController" type="Node" parent="." unique_id=644713371 node_paths=PackedStringArray("ui", "active_npcs_parent")]
script = ExtResource("13_demo")
ui = NodePath("../UI")
active_npcs_parent = NodePath("../ActiveNPCs")
+6
View File
@@ -18,6 +18,7 @@ var npcs: Array[SimNPC] = []
@export var cycle_duration_seconds := 240.0 @export var cycle_duration_seconds := 240.0
@export var debug_logs := true @export var debug_logs := true
@export var active_world_adapter: Node @export var active_world_adapter: Node
@export var home_positions: Array[Vector3] = []
var clock: SimulationClock var clock: SimulationClock
var tick_count := 0 var tick_count := 0
@@ -80,6 +81,11 @@ func generate_npcs() -> void:
npcs.append(npc) npcs.append(npc)
wander_random_sources[i] = _create_random_source(i, 1) wander_random_sources[i] = _create_random_source(i, 1)
var home_count := home_positions.size()
if home_count > 0:
for i in range(npcs.size()):
npcs[i].home_position = home_positions[i % home_count]
func _create_random_source(npc_id: int, stream_id: int) -> RandomNumberGenerator: func _create_random_source(npc_id: int, stream_id: int) -> RandomNumberGenerator:
var source := RandomNumberGenerator.new() var source := RandomNumberGenerator.new()