From e2549ac50cffb61951d90998287a84550725c433 Mon Sep 17 00:00:00 2001 From: Rijad Zuzo Date: Fri, 19 Jun 2026 08:08:17 +0200 Subject: [PATCH] feat: add movment based on needs with themed zones --- main.tscn | 28 ++++++++++++++++++++++++- player/npc/NpcVisual.gd | 32 ++++++++++++++++++++++++++++ player/npc/NpcVisual.tscn | 2 +- world/world_view_manager.gd | 42 +++++++++++++++++++++++++++++++++++++ 4 files changed, 102 insertions(+), 2 deletions(-) diff --git a/main.tscn b/main.tscn index 9bae6a7..1483ee8 100644 --- a/main.tscn +++ b/main.tscn @@ -70,11 +70,17 @@ fov = 65.0 [node name="SimulationManager" type="Node" parent="."] script = ExtResource("3_lquwl") -[node name="WorldViewManager" type="Node" parent="." node_paths=PackedStringArray("simulation_manager", "active_npcs_parent")] +[node name="WorldViewManager" type="Node" parent="." node_paths=PackedStringArray("simulation_manager", "active_npcs_parent", "farm_zone", "forest_zone", "guard_zone", "study_zone", "rest_zone", "food_zone")] script = ExtResource("4_1bvp3") npc_visual_scene = ExtResource("5_lquwl") simulation_manager = NodePath("../SimulationManager") active_npcs_parent = NodePath("../ActiveNPCs") +farm_zone = NodePath("../TaskZone/FarmZone") +forest_zone = NodePath("../TaskZone/ForestZone") +guard_zone = NodePath("../TaskZone/GuardZone") +study_zone = NodePath("../TaskZone/StudyZone") +rest_zone = NodePath("../TaskZone/RestZone") +food_zone = NodePath("../TaskZone/FoodZone") [node name="EventBus" type="Node" parent="."] @@ -82,3 +88,23 @@ active_npcs_parent = NodePath("../ActiveNPCs") environment = SubResource("Environment_o5qli") [node name="ActiveNPCs" type="Node3D" parent="."] + +[node name="TaskZone" type="Node3D" parent="."] + +[node name="FarmZone" type="Marker3D" parent="TaskZone"] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -8, 0, -6) + +[node name="ForestZone" type="Marker3D" parent="TaskZone"] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 8, 0, -6) + +[node name="GuardZone" type="Marker3D" parent="TaskZone"] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 8) + +[node name="StudyZone" type="Marker3D" parent="TaskZone"] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -6, 0, 6) + +[node name="RestZone" type="Marker3D" parent="TaskZone"] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 4, 0, 5) + +[node name="FoodZone" type="Marker3D" parent="TaskZone"] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, -8) diff --git a/player/npc/NpcVisual.gd b/player/npc/NpcVisual.gd index 8b18950..3a71e86 100644 --- a/player/npc/NpcVisual.gd +++ b/player/npc/NpcVisual.gd @@ -1,11 +1,43 @@ extends CharacterBody3D +@export var move_speed := 3.0 +@export var rotation_speed := 8.0 + var sim_id: int = -1 var npc_name: String = "" var profession: String = "" +var target_position: Vector3 +var has_target := false func setup_from_sim(npc: SimNPC) -> void: sim_id = npc.id npc_name = npc.npc_name profession = npc.profession name = "NPC_%s_%s" % [sim_id, npc_name] + target_position = global_position + +func set_target_position(pos: Vector3) -> void: + target_position = pos + has_target = true + +func _physics_process(delta: float) -> void: + if not has_target: + return + + var to_target := target_position - global_position + to_target.y = 0 + + if to_target.length() < 0.25: + velocity = Vector3.ZERO + move_and_slide() + return + + var direction := to_target.normalized() + velocity.x = direction.x * move_speed + velocity.z = direction.z * move_speed + velocity.y = 0 + + move_and_slide() + + var target_angle := atan2(direction.x, direction.z) + rotation.y = lerp_angle(rotation.y, target_angle, rotation_speed * delta) diff --git a/player/npc/NpcVisual.tscn b/player/npc/NpcVisual.tscn index 055da55..6c32034 100644 --- a/player/npc/NpcVisual.tscn +++ b/player/npc/NpcVisual.tscn @@ -24,5 +24,5 @@ transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.85, 0) mesh = SubResource("CapsuleMesh_d844k") [node name="FaceMarker" type="MeshInstance3D" parent="."] -transform = Transform3D(0.15, 0, 0, 0, 0.15, 0, 0, 0, 0.35, 0, 1.2, -0.5) +transform = Transform3D(0.15, 0, 0, 0, 0.15, 0, 0, 0, 0.35, 0, 1.2, 0.59052056) mesh = SubResource("BoxMesh_d844k") diff --git a/world/world_view_manager.gd b/world/world_view_manager.gd index 61a5be4..d6646eb 100644 --- a/world/world_view_manager.gd +++ b/world/world_view_manager.gd @@ -4,6 +4,13 @@ extends Node @export var simulation_manager: Node @export var active_npcs_parent: Node3D +@export var farm_zone: Marker3D +@export var forest_zone: Marker3D +@export var guard_zone: Marker3D +@export var study_zone: Marker3D +@export var rest_zone: Marker3D +@export var food_zone: Marker3D + var active_npc_visuals := {} # sim_id -> NPCVisual func _ready() -> void: @@ -32,3 +39,38 @@ func spawn_npc_visual(npc: SimNPC) -> void: visual.setup_from_sim(npc) active_npc_visuals[npc.id] = visual + +func _process(delta: float) -> void: + update_npc_targets() + + +func update_npc_targets() -> void: + if simulation_manager == null: + return + + for npc in simulation_manager.npcs: + if not active_npc_visuals.has(npc.id): + continue + + var visual = active_npc_visuals[npc.id] + var target := get_target_for_task(npc.current_task) + + if target != null: + visual.set_target_position(target.global_position) + +func get_target_for_task(task: String) -> Marker3D: + match task: + "gather_food": + return farm_zone + "gather_wood": + return forest_zone + "patrol": + return guard_zone + "study": + return study_zone + "rest": + return rest_zone + "eat": + return food_zone + _: + return rest_zone