feat: add completition of work only after work is done
This commit is contained in:
@@ -49,6 +49,7 @@ height = 5.774
|
|||||||
[sub_resource type="BoxMesh" id="BoxMesh_kek77"]
|
[sub_resource type="BoxMesh" id="BoxMesh_kek77"]
|
||||||
|
|
||||||
[sub_resource type="PrismMesh" id="PrismMesh_5vw27"]
|
[sub_resource type="PrismMesh" id="PrismMesh_5vw27"]
|
||||||
|
size = Vector3(3, 5, 2)
|
||||||
|
|
||||||
[sub_resource type="BoxMesh" id="BoxMesh_4c57u"]
|
[sub_resource type="BoxMesh" id="BoxMesh_4c57u"]
|
||||||
|
|
||||||
@@ -146,30 +147,41 @@ mesh = SubResource("BoxMesh_5vw27")
|
|||||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 8, 0, -6)
|
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 8, 0, -6)
|
||||||
|
|
||||||
[node name="smallTree" parent="TaskZone/ForestZone" instance=ExtResource("6_5vw27")]
|
[node name="smallTree" parent="TaskZone/ForestZone" instance=ExtResource("6_5vw27")]
|
||||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.13034248, 0.23380828, -0.6683569)
|
transform = Transform3D(3, 0, 0, 0, 3, 0, 0, 0, 3, 1.891, 0, -0.22)
|
||||||
|
|
||||||
|
[node name="smallTree2" parent="TaskZone/ForestZone" instance=ExtResource("6_5vw27")]
|
||||||
|
transform = Transform3D(2, 0, 0, 0, 2, 0, 0, 0, 2, -0.043, 0, -1.767)
|
||||||
|
|
||||||
|
[node name="smallTree3" parent="TaskZone/ForestZone" instance=ExtResource("6_5vw27")]
|
||||||
|
transform = Transform3D(3, 0, 0, 0, 3, 0, 0, 0, 3, 0.13, 0, 0.614)
|
||||||
|
|
||||||
[node name="highTree" parent="TaskZone/ForestZone" instance=ExtResource("7_kek77")]
|
[node name="highTree" parent="TaskZone/ForestZone" instance=ExtResource("7_kek77")]
|
||||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -0.78092957, 0.23380828, 0.17081833)
|
transform = Transform3D(3, 0, 0, 0, 3, 0, 0, 0, 3, -1.539, 0, 0.171)
|
||||||
|
|
||||||
[node name="GuardZone" type="Marker3D" parent="TaskZone"]
|
[node name="GuardZone" type="Marker3D" parent="TaskZone"]
|
||||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 8)
|
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 8)
|
||||||
|
|
||||||
[node name="MeshInstance3D" type="MeshInstance3D" parent="TaskZone/GuardZone"]
|
[node name="MeshInstance3D" type="MeshInstance3D" parent="TaskZone/GuardZone"]
|
||||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 3, 0)
|
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1.354011, 0)
|
||||||
mesh = SubResource("CylinderMesh_5vw27")
|
mesh = SubResource("CylinderMesh_5vw27")
|
||||||
|
|
||||||
[node name="StudyZone" type="Marker3D" parent="TaskZone"]
|
[node name="StudyZone" type="Marker3D" parent="TaskZone"]
|
||||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -6, 0, 6)
|
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -6, 0, 6)
|
||||||
|
|
||||||
[node name="MeshInstance3D" type="MeshInstance3D" parent="TaskZone/StudyZone"]
|
[node name="MeshInstance3D" type="MeshInstance3D" parent="TaskZone/StudyZone"]
|
||||||
transform = Transform3D(1, 0, 0, 0, 10, 0, 0, 0, 1, 0, 5, 0)
|
transform = Transform3D(3.279775, 0, 0, 0, 5.511466, 0, 0, 0, 1, 0, 2.8180213, 0)
|
||||||
mesh = SubResource("BoxMesh_kek77")
|
mesh = SubResource("BoxMesh_kek77")
|
||||||
|
metadata/_edit_group_ = true
|
||||||
|
|
||||||
[node name="RestZone" type="Marker3D" parent="TaskZone"]
|
[node name="RestZone" type="Marker3D" parent="TaskZone"]
|
||||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 4, 0, 5)
|
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 4, 0, 5)
|
||||||
|
|
||||||
[node name="MeshInstance3D" type="MeshInstance3D" parent="TaskZone/RestZone"]
|
[node name="MeshInstance3D" type="MeshInstance3D" parent="TaskZone/RestZone"]
|
||||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0)
|
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 2.4911091, 0)
|
||||||
|
mesh = SubResource("PrismMesh_5vw27")
|
||||||
|
|
||||||
|
[node name="MeshInstance3D2" type="MeshInstance3D" parent="TaskZone/RestZone"]
|
||||||
|
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 1.3897309, 1.399735, 1.0352364)
|
||||||
mesh = SubResource("PrismMesh_5vw27")
|
mesh = SubResource("PrismMesh_5vw27")
|
||||||
|
|
||||||
[node name="FoodZone" type="Marker3D" parent="TaskZone"]
|
[node name="FoodZone" type="Marker3D" parent="TaskZone"]
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
extends CharacterBody3D
|
extends CharacterBody3D
|
||||||
|
|
||||||
|
signal arrived_at_target(sim_id: int)
|
||||||
|
|
||||||
const DEBUG_LOGS := false
|
const DEBUG_LOGS := false
|
||||||
|
|
||||||
@export var move_speed := 3.0
|
@export var move_speed := 3.0
|
||||||
@@ -8,6 +10,7 @@ const DEBUG_LOGS := false
|
|||||||
|
|
||||||
@onready var nav_agent: NavigationAgent3D = $NavigationAgent3D
|
@onready var nav_agent: NavigationAgent3D = $NavigationAgent3D
|
||||||
|
|
||||||
|
var has_reported_arrival := false
|
||||||
var sim_id: int = -1
|
var sim_id: int = -1
|
||||||
var npc_name: String = ""
|
var npc_name: String = ""
|
||||||
var profession: String = ""
|
var profession: String = ""
|
||||||
@@ -30,6 +33,24 @@ func set_target_position(pos: Vector3) -> void:
|
|||||||
if current_target.distance_to(pos) < 0.1:
|
if current_target.distance_to(pos) < 0.1:
|
||||||
return
|
return
|
||||||
|
|
||||||
|
current_target = pos
|
||||||
|
has_reported_arrival = false
|
||||||
|
nav_agent.target_position = pos
|
||||||
|
|
||||||
|
await get_tree().physics_frame
|
||||||
|
|
||||||
|
current_path = NavigationServer3D.map_get_path(
|
||||||
|
get_world_3d().navigation_map,
|
||||||
|
global_position,
|
||||||
|
pos,
|
||||||
|
true
|
||||||
|
)
|
||||||
|
|
||||||
|
path_index = 0
|
||||||
|
debug_log("New target: %s Path points: %s" % [pos, current_path.size()])
|
||||||
|
if current_target.distance_to(pos) < 0.1:
|
||||||
|
return
|
||||||
|
|
||||||
current_target = pos
|
current_target = pos
|
||||||
nav_agent.target_position = pos
|
nav_agent.target_position = pos
|
||||||
|
|
||||||
@@ -50,6 +71,12 @@ func _physics_process(delta: float) -> void:
|
|||||||
if current_path.is_empty() or path_index >= current_path.size():
|
if current_path.is_empty() or path_index >= current_path.size():
|
||||||
velocity = Vector3.ZERO
|
velocity = Vector3.ZERO
|
||||||
move_and_slide()
|
move_and_slide()
|
||||||
|
|
||||||
|
if not has_reported_arrival and current_target != Vector3.INF:
|
||||||
|
has_reported_arrival = true
|
||||||
|
debug_log("Arrived at target")
|
||||||
|
arrived_at_target.emit(sim_id)
|
||||||
|
|
||||||
return
|
return
|
||||||
|
|
||||||
var next_pos := current_path[path_index]
|
var next_pos := current_path[path_index]
|
||||||
|
|||||||
+25
-11
@@ -1,6 +1,11 @@
|
|||||||
class_name SimNPC
|
class_name SimNPC
|
||||||
extends RefCounted
|
extends RefCounted
|
||||||
|
|
||||||
|
const TASK_STATE_IDLE := "idle"
|
||||||
|
const TASK_STATE_TRAVELING := "traveling"
|
||||||
|
const TASK_STATE_WORKING := "working"
|
||||||
|
const TASK_STATE_COMPLETE := "complete"
|
||||||
|
|
||||||
var id: int
|
var id: int
|
||||||
var npc_name: String
|
var npc_name: String
|
||||||
var profession: String
|
var profession: String
|
||||||
@@ -9,6 +14,7 @@ var energy: float
|
|||||||
var strength: float
|
var strength: float
|
||||||
var intelligence: float
|
var intelligence: float
|
||||||
var current_task: String = "idle"
|
var current_task: String = "idle"
|
||||||
|
var task_state: String = TASK_STATE_IDLE
|
||||||
var position: Vector3
|
var position: Vector3
|
||||||
|
|
||||||
var is_starving := false
|
var is_starving := false
|
||||||
@@ -31,7 +37,6 @@ func _init(
|
|||||||
intelligence = _intelligence
|
intelligence = _intelligence
|
||||||
hunger = randf_range(20.0, 80.0)
|
hunger = randf_range(20.0, 80.0)
|
||||||
energy = randf_range(40.0, 100.0)
|
energy = randf_range(40.0, 100.0)
|
||||||
|
|
||||||
position = Vector3(randf_range(-8.0, 8.0), 0.0, randf_range(-8.0, 8.0))
|
position = Vector3(randf_range(-8.0, 8.0), 0.0, randf_range(-8.0, 8.0))
|
||||||
|
|
||||||
func simulate_tick(village: SimVillage) -> void:
|
func simulate_tick(village: SimVillage) -> void:
|
||||||
@@ -48,30 +53,30 @@ func simulate_tick(village: SimVillage) -> void:
|
|||||||
|
|
||||||
energy = clamp(energy, 0.0, 100.0)
|
energy = clamp(energy, 0.0, 100.0)
|
||||||
|
|
||||||
if not task_complete:
|
if task_state == TASK_STATE_IDLE or task_state == TASK_STATE_COMPLETE:
|
||||||
task_progress += 1.0
|
choose_new_task(village)
|
||||||
if task_progress >= task_duration:
|
|
||||||
task_complete = true
|
|
||||||
return
|
return
|
||||||
|
|
||||||
choose_new_task(village)
|
if task_state == TASK_STATE_TRAVELING:
|
||||||
|
return
|
||||||
|
|
||||||
|
if task_state == TASK_STATE_WORKING:
|
||||||
|
task_progress += 1.0
|
||||||
|
|
||||||
|
if task_progress >= task_duration:
|
||||||
|
task_complete = true
|
||||||
|
task_state = TASK_STATE_COMPLETE
|
||||||
|
|
||||||
func choose_new_task(village: SimVillage) -> void:
|
func choose_new_task(village: SimVillage) -> void:
|
||||||
task_progress = 0.0
|
|
||||||
task_complete = false
|
|
||||||
|
|
||||||
if hunger > 75.0:
|
if hunger > 75.0:
|
||||||
if village.food > 0:
|
if village.food > 0:
|
||||||
set_task("eat", 2.0)
|
set_task("eat", 2.0)
|
||||||
hunger -= 25.0
|
|
||||||
else:
|
else:
|
||||||
set_task("gather_food", 5.0)
|
set_task("gather_food", 5.0)
|
||||||
return
|
return
|
||||||
|
|
||||||
if energy < 30.0:
|
if energy < 30.0:
|
||||||
set_task("rest", 4.0)
|
set_task("rest", 4.0)
|
||||||
energy += 20.0
|
|
||||||
return
|
return
|
||||||
|
|
||||||
if village.food < 15.0:
|
if village.food < 15.0:
|
||||||
@@ -107,3 +112,12 @@ func set_task(task: String, duration: float) -> void:
|
|||||||
task_duration = duration
|
task_duration = duration
|
||||||
task_progress = 0.0
|
task_progress = 0.0
|
||||||
task_complete = false
|
task_complete = false
|
||||||
|
task_state = TASK_STATE_TRAVELING
|
||||||
|
|
||||||
|
func start_working() -> void:
|
||||||
|
if task_state != TASK_STATE_TRAVELING:
|
||||||
|
return
|
||||||
|
|
||||||
|
task_state = TASK_STATE_WORKING
|
||||||
|
task_progress = 0.0
|
||||||
|
task_complete = false
|
||||||
|
|||||||
@@ -56,6 +56,7 @@ func simulate_tick() -> void:
|
|||||||
|
|
||||||
for npc in npcs:
|
for npc in npcs:
|
||||||
var old_task := npc.current_task
|
var old_task := npc.current_task
|
||||||
|
var old_state := npc.task_state
|
||||||
var was_complete := npc.task_complete
|
var was_complete := npc.task_complete
|
||||||
|
|
||||||
npc.simulate_tick(village)
|
npc.simulate_tick(village)
|
||||||
@@ -67,6 +68,10 @@ func simulate_tick() -> void:
|
|||||||
village.apply_npc_task(npc)
|
village.apply_npc_task(npc)
|
||||||
village_was_changed = true
|
village_was_changed = true
|
||||||
|
|
||||||
|
npc.task_complete = true
|
||||||
|
npc.task_state = SimNPC.TASK_STATE_IDLE
|
||||||
|
npc.current_task = "idle"
|
||||||
|
|
||||||
if DEBUG_LOGS:
|
if DEBUG_LOGS:
|
||||||
print(
|
print(
|
||||||
npc.npc_name,
|
npc.npc_name,
|
||||||
@@ -74,6 +79,8 @@ func simulate_tick() -> void:
|
|||||||
npc.profession,
|
npc.profession,
|
||||||
" | task: ",
|
" | task: ",
|
||||||
npc.current_task,
|
npc.current_task,
|
||||||
|
" | state: ",
|
||||||
|
npc.task_state,
|
||||||
" | progress: ",
|
" | progress: ",
|
||||||
npc.task_progress,
|
npc.task_progress,
|
||||||
"/",
|
"/",
|
||||||
@@ -86,12 +93,25 @@ func simulate_tick() -> void:
|
|||||||
round(npc.energy)
|
round(npc.energy)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if old_state != npc.task_state:
|
||||||
|
print("[SimulationManager] State changed: ", npc.npc_name, " ", old_state, " -> ", npc.task_state)
|
||||||
|
|
||||||
if village_was_changed:
|
if village_was_changed:
|
||||||
village_changed.emit(village)
|
village_changed.emit(village)
|
||||||
|
|
||||||
if DEBUG_LOGS:
|
if DEBUG_LOGS:
|
||||||
print(village.get_summary())
|
print(village.get_summary())
|
||||||
|
|
||||||
|
func notify_npc_arrived(npc_id: int) -> void:
|
||||||
|
for npc in npcs:
|
||||||
|
if npc.id == npc_id:
|
||||||
|
if npc.task_state == SimNPC.TASK_STATE_TRAVELING:
|
||||||
|
npc.start_working()
|
||||||
|
|
||||||
|
if DEBUG_LOGS:
|
||||||
|
print("[SimulationManager] ", npc.npc_name, " arrived and started working on: ", npc.current_task)
|
||||||
|
return
|
||||||
|
|
||||||
func eat_food(amount: float) -> void:
|
func eat_food(amount: float) -> void:
|
||||||
village.food -= amount
|
village.food -= amount
|
||||||
village_changed.emit(village)
|
village_changed.emit(village)
|
||||||
|
|||||||
@@ -61,8 +61,12 @@ func spawn_npc_visual(npc: SimNPC) -> void:
|
|||||||
visual.global_position = npc.position
|
visual.global_position = npc.position
|
||||||
visual.setup_from_sim(npc)
|
visual.setup_from_sim(npc)
|
||||||
|
|
||||||
active_npc_visuals[npc.id] = visual
|
if visual.has_signal("arrived_at_target"):
|
||||||
|
visual.arrived_at_target.connect(_on_npc_visual_arrived)
|
||||||
|
else:
|
||||||
|
push_error("WorldViewManager: NPCVisual has no arrived_at_target signal")
|
||||||
|
|
||||||
|
active_npc_visuals[npc.id] = visual
|
||||||
debug_log("Spawned visual for %s at %s" % [npc.npc_name, npc.position])
|
debug_log("Spawned visual for %s at %s" % [npc.npc_name, npc.position])
|
||||||
|
|
||||||
func update_npc_targets() -> void:
|
func update_npc_targets() -> void:
|
||||||
@@ -111,3 +115,15 @@ func _on_npc_task_changed(npc: SimNPC, old_task: String, new_task: String) -> vo
|
|||||||
|
|
||||||
if target != null:
|
if target != null:
|
||||||
visual.set_target_position(target.global_position)
|
visual.set_target_position(target.global_position)
|
||||||
|
|
||||||
|
func _on_npc_visual_arrived(sim_id: int) -> void:
|
||||||
|
debug_log("NPC visual arrived. sim_id=%s" % sim_id)
|
||||||
|
|
||||||
|
if simulation_manager == null:
|
||||||
|
push_error("WorldViewManager: simulation_manager missing during arrival report")
|
||||||
|
return
|
||||||
|
|
||||||
|
if simulation_manager.has_method("notify_npc_arrived"):
|
||||||
|
simulation_manager.notify_npc_arrived(sim_id)
|
||||||
|
else:
|
||||||
|
push_error("WorldViewManager: SimulationManager has no notify_npc_arrived method")
|
||||||
|
|||||||
Reference in New Issue
Block a user