asset vibe
This commit is contained in:
@@ -3,17 +3,12 @@
|
||||
[ext_resource type="Script" uid="uid://vy6hyqok0p8b" path="res://scenes/enemy/init.gd" id="1"]
|
||||
[ext_resource type="Script" uid="uid://b07aajhufqvb3" path="res://scenes/enemy/detection.gd" id="2"]
|
||||
[ext_resource type="Resource" uid="uid://cj1shmjwf0xeo" path="res://scenes/enemy/enemy_stats.tres" id="8"]
|
||||
[ext_resource type="PackedScene" path="res://assets/models/characters/Skeleton_Minion.glb" id="9"]
|
||||
|
||||
[sub_resource type="CapsuleShape3D" id="CapsuleShape3D_1"]
|
||||
radius = 0.4
|
||||
height = 1.5
|
||||
|
||||
[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_1"]
|
||||
albedo_color = Color(0.8, 0.1, 0.1, 1)
|
||||
|
||||
[sub_resource type="SphereMesh" id="SphereMesh_1"]
|
||||
material = SubResource("StandardMaterial3D_1")
|
||||
|
||||
[sub_resource type="CapsuleShape3D" id="CapsuleShape3D_2"]
|
||||
radius = 0.4
|
||||
height = 1.5
|
||||
@@ -40,8 +35,10 @@ stats = ExtResource("8")
|
||||
[node name="CollisionShape3D" type="CollisionShape3D" parent="." unique_id=1011138038]
|
||||
shape = SubResource("CapsuleShape3D_1")
|
||||
|
||||
[node name="Mesh" type="MeshInstance3D" parent="." unique_id=1598094615]
|
||||
mesh = SubResource("SphereMesh_1")
|
||||
[node name="Mesh" type="Node3D" parent="." unique_id=1598094615]
|
||||
|
||||
[node name="Model" parent="Mesh" instance=ExtResource("9")]
|
||||
transform = Transform3D(-1, 0, 0, 0, 1, 0, 0, 0, -1, 0, -0.75, 0)
|
||||
|
||||
[node name="HitArea" type="Area3D" parent="." unique_id=893463784]
|
||||
collision_layer = 4
|
||||
@@ -62,7 +59,7 @@ collision_layer = 0
|
||||
shape = SubResource("SphereShape3D_1")
|
||||
|
||||
[node name="Healthbar" type="Sprite3D" parent="." unique_id=1008728031]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1.5, 0)
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 2, 0)
|
||||
billboard = 1
|
||||
|
||||
[node name="SubViewport" type="SubViewport" parent="Healthbar" unique_id=1219060718]
|
||||
|
||||
@@ -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():
|
||||
|
||||
@@ -2,6 +2,10 @@ extends CharacterBody3D
|
||||
|
||||
@export var stats: PlayerStats
|
||||
|
||||
var anim_player: AnimationPlayer = null
|
||||
var current_anim: String = ""
|
||||
var attack_lock_until: float = 0.0
|
||||
|
||||
func _ready() -> void:
|
||||
add_to_group("player")
|
||||
PlayerData.init_from_resource(stats)
|
||||
@@ -10,3 +14,46 @@ func _ready() -> void:
|
||||
PlayerData.returning_from_dungeon = false
|
||||
elif PlayerData.dungeon_cleared:
|
||||
PlayerData.clear_cache()
|
||||
anim_player = get_node_or_null("Mesh/Model/AnimationPlayer")
|
||||
_play_anim("Idle")
|
||||
EventBus.attack_executed.connect(_on_attack_executed)
|
||||
EventBus.entity_died.connect(_on_entity_died)
|
||||
EventBus.player_respawned.connect(_on_player_respawned)
|
||||
|
||||
func _process(_delta: float) -> void:
|
||||
if not PlayerData.alive:
|
||||
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 _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 _on_entity_died(entity: Node) -> void:
|
||||
if entity != PlayerData:
|
||||
return
|
||||
_play_anim("Death_A", false)
|
||||
|
||||
func _on_player_respawned(_player: Node) -> void:
|
||||
_play_anim("Idle")
|
||||
|
||||
@@ -25,6 +25,11 @@ func _physics_process(delta: float) -> void:
|
||||
if direction:
|
||||
player.velocity.x = direction.x * PlayerData.speed
|
||||
player.velocity.z = direction.z * PlayerData.speed
|
||||
var world_yaw: float = atan2(-direction.x, -direction.z)
|
||||
var local_yaw: float = world_yaw - player.rotation.y
|
||||
var mesh: Node3D = player.get_node_or_null("Mesh") as Node3D
|
||||
if mesh:
|
||||
mesh.rotation.y = lerp_angle(mesh.rotation.y, local_yaw, 10.0 * delta)
|
||||
else:
|
||||
player.velocity.x = move_toward(player.velocity.x, 0, PlayerData.speed)
|
||||
player.velocity.z = move_toward(player.velocity.z, 0, PlayerData.speed)
|
||||
|
||||
@@ -7,15 +7,12 @@
|
||||
[ext_resource type="Script" uid="uid://b05nkuryipwny" path="res://scenes/player/targeting.gd" id="8"]
|
||||
[ext_resource type="Script" uid="uid://dhomrampxola4" path="res://scenes/player/role/role.gd" id="10"]
|
||||
[ext_resource type="Resource" uid="uid://btd0g0oiulssq" path="res://scenes/player/player_stats.tres" id="14"]
|
||||
[ext_resource type="PackedScene" path="res://assets/models/characters/Knight.glb" id="15"]
|
||||
|
||||
[sub_resource type="CapsuleShape3D" id="CapsuleShape3D_1"]
|
||||
radius = 0.3
|
||||
height = 1.8
|
||||
|
||||
[sub_resource type="CapsuleMesh" id="CapsuleMesh_1"]
|
||||
radius = 0.3
|
||||
height = 1.8
|
||||
|
||||
[node name="Player" type="CharacterBody3D" unique_id=197716516]
|
||||
script = ExtResource("1")
|
||||
stats = ExtResource("14")
|
||||
@@ -23,8 +20,10 @@ stats = ExtResource("14")
|
||||
[node name="CollisionShape3D" type="CollisionShape3D" parent="." unique_id=311205642]
|
||||
shape = SubResource("CapsuleShape3D_1")
|
||||
|
||||
[node name="Mesh" type="MeshInstance3D" parent="." unique_id=1514179122]
|
||||
mesh = SubResource("CapsuleMesh_1")
|
||||
[node name="Mesh" type="Node3D" parent="." unique_id=1514179122]
|
||||
|
||||
[node name="Model" parent="Mesh" instance=ExtResource("15")]
|
||||
transform = Transform3D(-1, 0, 0, 0, 1, 0, 0, 0, -1, 0, -0.9, 0)
|
||||
|
||||
[node name="CameraPivot" type="Node3D" parent="." unique_id=1881685457]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1.5, 0)
|
||||
|
||||
@@ -2,24 +2,11 @@
|
||||
|
||||
[ext_resource type="Script" path="res://scenes/tavern/init.gd" id="1"]
|
||||
[ext_resource type="Resource" path="res://scenes/tavern/tavern_stats.tres" id="2"]
|
||||
[ext_resource type="PackedScene" path="res://assets/models/buildings/building_home_A_blue.gltf" id="3"]
|
||||
|
||||
[sub_resource type="BoxShape3D" id="BoxShape3D_tavern"]
|
||||
size = Vector3(5, 3, 5)
|
||||
|
||||
[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_tavern"]
|
||||
albedo_color = Color(0.45, 0.3, 0.15, 1)
|
||||
|
||||
[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_roof"]
|
||||
albedo_color = Color(0.3, 0.15, 0.08, 1)
|
||||
|
||||
[sub_resource type="BoxMesh" id="BoxMesh_tavern"]
|
||||
size = Vector3(5, 3, 5)
|
||||
material = SubResource("StandardMaterial3D_tavern")
|
||||
|
||||
[sub_resource type="PrismMesh" id="PrismMesh_roof"]
|
||||
size = Vector3(5.4, 2, 5.4)
|
||||
material = SubResource("StandardMaterial3D_roof")
|
||||
|
||||
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_health_bg"]
|
||||
bg_color = Color(0.3, 0.1, 0.1, 1)
|
||||
|
||||
@@ -33,12 +20,10 @@ stats = ExtResource("2")
|
||||
[node name="CollisionShape3D" type="CollisionShape3D" parent="."]
|
||||
shape = SubResource("BoxShape3D_tavern")
|
||||
|
||||
[node name="Mesh" type="MeshInstance3D" parent="."]
|
||||
mesh = SubResource("BoxMesh_tavern")
|
||||
[node name="Mesh" type="Node3D" parent="."]
|
||||
|
||||
[node name="Roof" type="MeshInstance3D" parent="."]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 2.5, 0)
|
||||
mesh = SubResource("PrismMesh_roof")
|
||||
[node name="Model" parent="Mesh" instance=ExtResource("3")]
|
||||
transform = Transform3D(2.5, 0, 0, 0, 2.5, 0, 0, 0, 2.5, 0, -1.5, 0)
|
||||
|
||||
[node name="Healthbar" type="Sprite3D" parent="."]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 4, 0)
|
||||
|
||||
Reference in New Issue
Block a user