feat: add cinematic npc task glyphs

This commit is contained in:
2026-07-08 16:31:34 +02:00
parent e813a8b2d5
commit cd0309e224
11 changed files with 144 additions and 8 deletions
+90
View File
@@ -16,6 +16,8 @@ const DEBUG_LOGS := true
@onready var profession_prop: MeshInstance3D = $ProfessionProp
@onready var profession_label: Label3D = $ProfessionLabel
@onready var carried_food_visual: MeshInstance3D = $CarriedFood
@onready var task_glyph_root: Node3D = $TaskGlyphRoot
@onready var task_glyph: MeshInstance3D = $TaskGlyphRoot/TaskGlyph
var has_reported_arrival := false
var sim_id: int = -1
@@ -51,6 +53,7 @@ func setup_from_sim(npc: SimNPC) -> void:
name = "NPC_%s_%s" % [sim_id, npc_name]
_apply_profession_presentation()
set_carried_food_visible(npc.get_inventory_amount(SimulationIds.RESOURCE_FOOD) > 0.0)
set_task_presentation(npc.current_task, npc.task_state)
func _apply_profession_presentation() -> void:
@@ -114,6 +117,18 @@ func set_carried_food_visible(is_visible: bool) -> void:
carried_food_visual.visible = is_visible and not is_dead_visual
func set_task_presentation(action_id: StringName, task_state: StringName) -> void:
if task_glyph_root == null or task_glyph == null:
return
if is_dead_visual or not _should_show_task_glyph(action_id, task_state):
task_glyph_root.visible = false
return
task_glyph.mesh = _create_task_glyph_mesh(action_id)
task_glyph.material_override = _create_task_glyph_material(action_id)
task_glyph_root.visible = task_glyph.mesh != null
func set_debug_overlay_visible(is_visible: bool) -> void:
debug_overlay_visible = is_visible
if profession_label != null:
@@ -251,6 +266,7 @@ func apply_dead_visual_state() -> void:
carried_food_visual.visible = false
profession_prop.visible = false
profession_label.visible = false
task_glyph_root.visible = false
path_request_id += 1
velocity = Vector3.ZERO
current_path = PackedVector3Array()
@@ -269,3 +285,77 @@ func apply_dead_visual_state() -> void:
collision_layer = 0
collision_mask = 0
debug_log("Applied dead visual state")
func _should_show_task_glyph(action_id: StringName, task_state: StringName) -> bool:
if task_state not in [SimNPC.TASK_STATE_TRAVELING, SimNPC.TASK_STATE_WORKING]:
return false
return action_id not in [
SimulationIds.ACTION_IDLE,
SimulationIds.ACTION_DEAD,
SimulationIds.ACTION_WANDER,
]
func _create_task_glyph_mesh(action_id: StringName) -> PrimitiveMesh:
task_glyph.rotation_degrees = Vector3.ZERO
match action_id:
SimulationIds.ACTION_GATHER_FOOD, SimulationIds.ACTION_EAT, SimulationIds.ACTION_WITHDRAW_FOOD:
var food := SphereMesh.new()
food.radius = 0.18
food.height = 0.26
return food
SimulationIds.ACTION_GATHER_WOOD:
var wood := BoxMesh.new()
wood.size = Vector3(0.18, 0.42, 0.18)
task_glyph.rotation_degrees = Vector3(0, 0, -18)
return wood
SimulationIds.ACTION_DEPOSIT_FOOD:
var crate := BoxMesh.new()
crate.size = Vector3(0.34, 0.22, 0.34)
return crate
SimulationIds.ACTION_PATROL:
var shield := CylinderMesh.new()
shield.top_radius = 0.2
shield.bottom_radius = 0.2
shield.height = 0.1
task_glyph.rotation_degrees = Vector3(90, 0, 0)
return shield
SimulationIds.ACTION_STUDY:
var book := BoxMesh.new()
book.size = Vector3(0.36, 0.08, 0.24)
return book
SimulationIds.ACTION_REST:
var rest := SphereMesh.new()
rest.radius = 0.2
rest.height = 0.12
return rest
return null
func _create_task_glyph_material(action_id: StringName) -> StandardMaterial3D:
var material := StandardMaterial3D.new()
material.roughness = 0.65
material.emission_enabled = true
material.emission_energy_multiplier = 0.35
var color := _get_task_glyph_color(action_id)
material.albedo_color = color
material.emission = color
return material
func _get_task_glyph_color(action_id: StringName) -> Color:
match action_id:
SimulationIds.ACTION_GATHER_FOOD, SimulationIds.ACTION_EAT, SimulationIds.ACTION_WITHDRAW_FOOD:
return Color(0.95, 0.42, 0.25, 1.0)
SimulationIds.ACTION_GATHER_WOOD:
return Color(0.58, 0.34, 0.16, 1.0)
SimulationIds.ACTION_DEPOSIT_FOOD:
return Color(0.95, 0.72, 0.32, 1.0)
SimulationIds.ACTION_PATROL:
return Color(0.36, 0.58, 0.95, 1.0)
SimulationIds.ACTION_STUDY:
return Color(0.62, 0.46, 0.9, 1.0)
SimulationIds.ACTION_REST:
return Color(0.4, 0.78, 0.72, 1.0)
return Color(0.9, 0.9, 0.85, 1.0)