asset vibe
This commit is contained in:
@@ -1,25 +1,56 @@
|
||||
extends CharacterBody3D
|
||||
|
||||
const SKELETON_WARRIOR: PackedScene = preload("res://assets/models/characters/Skeleton_Warrior.glb")
|
||||
const SKELETON_MAGE: PackedScene = preload("res://assets/models/characters/Skeleton_Mage.glb")
|
||||
|
||||
@export var stats: EnemyStats
|
||||
|
||||
var gravity: float = ProjectSettings.get_setting("physics/3d/default_gravity")
|
||||
var spawn_scale: float = 1.0
|
||||
var hover_t: float = 0.0
|
||||
var mesh_base_y: float = 0.0
|
||||
var anim_player: AnimationPlayer = null
|
||||
var current_anim: String = ""
|
||||
var attack_lock_until: float = 0.0
|
||||
var is_dying: bool = false
|
||||
|
||||
func _ready() -> void:
|
||||
add_to_group("enemies")
|
||||
if is_in_group("boss"):
|
||||
BossData.register(self, stats, spawn_scale)
|
||||
BossData.set_stat(self, "spawn_position", global_position)
|
||||
_swap_model(SKELETON_MAGE, 1.3)
|
||||
else:
|
||||
EnemyData.register(self, stats, spawn_scale)
|
||||
EnemyData.set_stat(self, "spawn_position", global_position)
|
||||
EventBus.entity_died.connect(_on_entity_died)
|
||||
EventBus.attack_executed.connect(_on_attack_executed)
|
||||
call_deferred("_check_variant")
|
||||
call_deferred("_init_anim")
|
||||
|
||||
func _init_anim() -> void:
|
||||
anim_player = get_node_or_null("Mesh/Model/AnimationPlayer")
|
||||
_play_anim("Idle")
|
||||
|
||||
func _check_variant() -> void:
|
||||
if is_in_group("boss"):
|
||||
return
|
||||
if is_in_group("red_enemies") or is_in_group("invasion"):
|
||||
_swap_model(SKELETON_WARRIOR, 1.0)
|
||||
anim_player = get_node_or_null("Mesh/Model/AnimationPlayer")
|
||||
_play_anim("Idle")
|
||||
|
||||
func _swap_model(new_scene: PackedScene, scale_factor: float = 1.0) -> void:
|
||||
var mesh: Node3D = get_node_or_null("Mesh")
|
||||
if mesh:
|
||||
mesh_base_y = mesh.position.y
|
||||
_apply_appearance(mesh)
|
||||
if not mesh:
|
||||
return
|
||||
var old: Node = mesh.get_node_or_null("Model")
|
||||
if old:
|
||||
old.queue_free()
|
||||
var new_model: Node3D = new_scene.instantiate()
|
||||
new_model.name = "Model"
|
||||
new_model.scale = Vector3(scale_factor, scale_factor, scale_factor)
|
||||
new_model.position = Vector3(0, -0.75, 0)
|
||||
new_model.rotation.y = PI
|
||||
mesh.add_child(new_model)
|
||||
|
||||
func _exit_tree() -> void:
|
||||
if is_in_group("boss"):
|
||||
@@ -28,29 +59,41 @@ func _exit_tree() -> void:
|
||||
EnemyData.deregister(self)
|
||||
|
||||
func _on_entity_died(entity: Node) -> void:
|
||||
if entity == self:
|
||||
queue_free()
|
||||
if entity != self:
|
||||
return
|
||||
is_dying = true
|
||||
_play_anim("Death_A", false)
|
||||
get_tree().create_timer(1.0).timeout.connect(queue_free)
|
||||
|
||||
func _process(delta: float) -> void:
|
||||
hover_t += delta
|
||||
var mesh: Node3D = get_node_or_null("Mesh")
|
||||
if mesh:
|
||||
mesh.position.y = mesh_base_y + sin(hover_t * 3.0) * 0.08
|
||||
func _on_attack_executed(attacker: Node, _pos: Vector3, _dir: Vector3, _damage: float) -> void:
|
||||
if attacker != self:
|
||||
return
|
||||
_play_anim("1H_Melee_Attack_Chop", false)
|
||||
attack_lock_until = Time.get_ticks_msec() / 1000.0 + 0.5
|
||||
|
||||
func _apply_appearance(mesh: Node3D) -> void:
|
||||
if mesh is MeshInstance3D:
|
||||
var mat := StandardMaterial3D.new()
|
||||
if is_in_group("boss"):
|
||||
mat.albedo_color = Color(0.6, 0.15, 0.7, 1)
|
||||
mat.emission_enabled = true
|
||||
mat.emission = Color(0.8, 0.2, 0.9, 1)
|
||||
mat.emission_energy_multiplier = 0.4
|
||||
else:
|
||||
mat.albedo_color = Color(0.7, 0.25, 0.25, 1)
|
||||
mat.emission_enabled = true
|
||||
mat.emission = Color(0.9, 0.3, 0.2, 1)
|
||||
mat.emission_energy_multiplier = 0.25
|
||||
(mesh as MeshInstance3D).material_override = mat
|
||||
func _process(_delta: float) -> void:
|
||||
if is_dying:
|
||||
return
|
||||
var now: float = Time.get_ticks_msec() / 1000.0
|
||||
if now < attack_lock_until:
|
||||
return
|
||||
if velocity.length() > 0.1:
|
||||
_play_anim("Running_A")
|
||||
else:
|
||||
_play_anim("Idle")
|
||||
|
||||
func _play_anim(anim_name: String, loop: bool = true) -> void:
|
||||
if not anim_player:
|
||||
return
|
||||
if current_anim == anim_name:
|
||||
return
|
||||
if not anim_player.has_animation(anim_name):
|
||||
return
|
||||
var anim: Animation = anim_player.get_animation(anim_name)
|
||||
if anim:
|
||||
anim.loop_mode = Animation.LOOP_LINEAR if loop else Animation.LOOP_NONE
|
||||
anim_player.play(anim_name)
|
||||
current_anim = anim_name
|
||||
|
||||
func _physics_process(delta: float) -> void:
|
||||
if not is_on_floor():
|
||||
|
||||
Reference in New Issue
Block a user