feat: shared creature root, enemy definitions, defend duty, and player downing

This commit is contained in:
Rijad Zuzo
2026-08-12 00:16:48 +02:00
parent 6de6d25bf5
commit 661d53f31a
23 changed files with 653 additions and 76 deletions
+50 -47
View File
@@ -1,48 +1,39 @@
class_name HostileCombatant
extends Node3D
extends CreatureVisual
const FOLLOW_SPEED := 6.0
const ARRIVE_DISTANCE := 0.5
var combatant_id: StringName
var combatant: CombatantStateRecord
var simulation_manager: Node
var is_dead_visual := false
var flash_tween: Tween
var spawn_scale := Vector3.ONE
var _flash_tween: Tween
var _spawn_tween: Tween
func _ready() -> void:
spawn_scale = Vector3.ONE
add_to_group("grass_interactors")
scale = Vector3.ONE * 0.001
var tween := create_tween()
tween.set_trans(Tween.TRANS_BACK).set_ease(Tween.EASE_OUT)
tween.tween_property(self, "scale", Vector3.ONE, 0.28)
_spawn_tween = create_tween()
_spawn_tween.set_trans(Tween.TRANS_BACK).set_ease(Tween.EASE_OUT)
_spawn_tween.tween_property(self, "scale", Vector3.ONE, 0.28)
func bind(combatant_id_value: StringName, manager: Node) -> void:
combatant_id = combatant_id_value
creature_id = combatant_id_value
simulation_manager = manager
combatant = manager.get_combatant(combatant_id) as CombatantStateRecord
combatant = manager.get_combatant(creature_id) as CombatantStateRecord
if combatant == null:
return
global_position = combatant.get_position()
_build_body(combatant.get_kind())
sim_position = combatant.get_position()
_build_from_definition()
combatant.changed.connect(_on_combatant_changed)
func _process(delta: float) -> void:
func _process(_delta: float) -> void:
if is_dead_visual or combatant == null or not is_instance_valid(combatant):
return
if not combatant.is_alive():
_play_death()
play_death()
return
var target_position := combatant.get_position()
var to_target := target_position - global_position
if to_target.length() <= ARRIVE_DISTANCE:
return
global_position += to_target.normalized() * minf(FOLLOW_SPEED * delta, to_target.length())
rotation.y = lerp_angle(rotation.y, atan2(to_target.x, to_target.z), delta * 8.0)
set_sim_position(combatant.get_position())
func _on_combatant_changed(_state: CombatantStateRecord) -> void:
@@ -52,42 +43,54 @@ func _on_combatant_changed(_state: CombatantStateRecord) -> void:
func _flash_hit() -> void:
if flash_tween != null and flash_tween.is_valid():
flash_tween.kill()
flash_tween = create_tween()
flash_tween.tween_property(self, "scale", Vector3.ONE * 0.85, 0.06)
flash_tween.tween_property(self, "scale", Vector3.ONE, 0.12)
if _flash_tween != null and _flash_tween.is_valid():
_flash_tween.kill()
_flash_tween = create_tween()
_flash_tween.tween_property(self, "scale", _definition_scale() * 0.85, 0.06)
_flash_tween.tween_property(self, "scale", _definition_scale(), 0.12)
func _play_death() -> void:
func play_death() -> void:
is_dead_visual = true
stop_travel_visual()
var tween := create_tween()
tween.set_trans(Tween.TRANS_QUAD).set_ease(Tween.EASE_IN)
tween.tween_property(self, "scale", Vector3(0.001, 0.001, 0.001), 0.45)
tween.tween_callback(queue_free)
super.play_death()
func stop_travel_visual() -> void:
pass
func _definition_scale() -> Vector3:
var definition := _enemy_definition()
return definition.visual_scale if definition != null else Vector3.ONE
func _build_body(kind: StringName) -> void:
if kind == SimulationIds.COMBATANT_KIND_WOLF:
_build_wolf()
else:
_build_raider()
func _build_from_definition() -> void:
var definition := _enemy_definition()
if definition != null:
move_speed = definition.move_speed
scale = definition.visual_scale
if definition.kind == SimulationIds.COMBATANT_KIND_WOLF:
_build_wolf(definition)
else:
_build_raider(definition)
func _build_raider() -> void:
func _enemy_definition() -> EnemyDefinition:
if combatant == null:
return null
var enemy_id: StringName = (
&"enemy_wolf"
if combatant.get_kind() == SimulationIds.COMBATANT_KIND_WOLF
else &"enemy_raider"
)
return SimulationEnemies.get_enemy(enemy_id)
func _build_raider(definition: EnemyDefinition) -> void:
var tunic := StandardMaterial3D.new()
tunic.albedo_color = Color(0.4, 0.13, 0.1, 1.0)
tunic.albedo_color = definition.body_color
tunic.roughness = 0.85
var skin := StandardMaterial3D.new()
skin.albedo_color = Color(0.8, 0.58, 0.36, 1.0)
skin.roughness = 0.9
var metal := StandardMaterial3D.new()
metal.albedo_color = Color(0.55, 0.55, 0.58, 1.0)
metal.albedo_color = definition.accent_color
metal.roughness = 0.35
_add_mesh("Body", CylinderMesh.new(), Vector3(0.0, 1.1, 0.0), tunic)
@@ -104,12 +107,12 @@ func _build_raider() -> void:
)
func _build_wolf() -> void:
func _build_wolf(definition: EnemyDefinition) -> void:
var fur := StandardMaterial3D.new()
fur.albedo_color = Color(0.32, 0.32, 0.34, 1.0)
fur.albedo_color = definition.body_color
fur.roughness = 0.95
var eye := StandardMaterial3D.new()
eye.albedo_color = Color(0.95, 0.5, 0.12, 1.0)
eye.albedo_color = definition.accent_color
eye.roughness = 0.3
var body := SphereMesh.new()