update
This commit is contained in:
@@ -1,5 +0,0 @@
|
||||
extends "res://scenes/enemy/enemy.gd"
|
||||
|
||||
func _ready() -> void:
|
||||
super._ready()
|
||||
add_to_group("boss")
|
||||
@@ -1 +0,0 @@
|
||||
uid://bkehq3dqyp2yd
|
||||
@@ -1,108 +0,0 @@
|
||||
[gd_scene load_steps=6 format=3]
|
||||
|
||||
[ext_resource type="Script" path="res://scenes/enemy/boss.gd" id="1"]
|
||||
[ext_resource type="Script" path="res://scenes/healthbar.gd" id="4"]
|
||||
[ext_resource type="Script" path="res://scenes/enemy/enemy_movement.gd" id="5"]
|
||||
[ext_resource type="Resource" path="res://scenes/enemy/boss_stats.tres" id="8"]
|
||||
|
||||
[sub_resource type="CapsuleShape3D" id="CapsuleShape3D_1"]
|
||||
radius = 0.6
|
||||
height = 2.0
|
||||
|
||||
[sub_resource type="CapsuleShape3D" id="CapsuleShape3D_2"]
|
||||
radius = 0.6
|
||||
height = 2.0
|
||||
|
||||
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_health_bg"]
|
||||
bg_color = Color(0.3, 0.1, 0.1, 1)
|
||||
|
||||
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_health_fill"]
|
||||
bg_color = Color(0.2, 0.8, 0.2, 1)
|
||||
|
||||
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_shield_bg"]
|
||||
bg_color = Color(0.1, 0.1, 0.3, 1)
|
||||
|
||||
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_shield_fill"]
|
||||
bg_color = Color(0.2, 0.5, 0.9, 1)
|
||||
|
||||
[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_1"]
|
||||
albedo_color = Color(0.6, 0.1, 0.6, 1)
|
||||
|
||||
[sub_resource type="SphereMesh" id="SphereMesh_1"]
|
||||
radius = 0.75
|
||||
height = 1.5
|
||||
material = SubResource("StandardMaterial3D_1")
|
||||
|
||||
[sub_resource type="SphereShape3D" id="SphereShape3D_1"]
|
||||
radius = 8.0
|
||||
|
||||
[node name="Boss" type="CharacterBody3D"]
|
||||
script = ExtResource("1")
|
||||
stats = ExtResource("8")
|
||||
|
||||
[node name="CollisionShape3D" type="CollisionShape3D" parent="."]
|
||||
shape = SubResource("CapsuleShape3D_1")
|
||||
|
||||
[node name="Mesh" type="MeshInstance3D" parent="."]
|
||||
transform = Transform3D(1.5, 0, 0, 0, 1.5, 0, 0, 0, 1.5, 0, 0, 0)
|
||||
mesh = SubResource("SphereMesh_1")
|
||||
|
||||
[node name="HitArea" type="Area3D" parent="."]
|
||||
collision_layer = 4
|
||||
collision_mask = 0
|
||||
|
||||
[node name="CollisionShape3D" type="CollisionShape3D" parent="HitArea"]
|
||||
shape = SubResource("CapsuleShape3D_2")
|
||||
|
||||
[node name="NavigationAgent3D" type="NavigationAgent3D" parent="."]
|
||||
|
||||
[node name="EnemyMovement" type="Node" parent="."]
|
||||
script = ExtResource("5")
|
||||
|
||||
[node name="DetectionArea" type="Area3D" parent="."]
|
||||
collision_layer = 0
|
||||
collision_mask = 1
|
||||
monitoring = true
|
||||
|
||||
[node name="CollisionShape3D" type="CollisionShape3D" parent="DetectionArea"]
|
||||
shape = SubResource("SphereShape3D_1")
|
||||
|
||||
[node name="Healthbar" type="Sprite3D" parent="."]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 2.0, 0)
|
||||
billboard = 1
|
||||
pixel_size = 0.01
|
||||
script = ExtResource("4")
|
||||
|
||||
[node name="SubViewport" type="SubViewport" parent="Healthbar"]
|
||||
transparent_bg = true
|
||||
size = Vector2i(104, 29)
|
||||
|
||||
[node name="Border" type="ColorRect" parent="Healthbar/SubViewport"]
|
||||
offset_right = 104.0
|
||||
offset_bottom = 29.0
|
||||
color = Color(1, 0.9, 0.2, 1)
|
||||
|
||||
[node name="HealthBar" type="ProgressBar" parent="Healthbar/SubViewport"]
|
||||
offset_left = 2.0
|
||||
offset_top = 2.0
|
||||
offset_right = 102.0
|
||||
offset_bottom = 12.0
|
||||
theme_override_styles/background = SubResource("StyleBoxFlat_health_bg")
|
||||
theme_override_styles/fill = SubResource("StyleBoxFlat_health_fill")
|
||||
max_value = 500.0
|
||||
value = 500.0
|
||||
show_percentage = false
|
||||
|
||||
[node name="ShieldBar" type="ProgressBar" parent="Healthbar/SubViewport"]
|
||||
offset_left = 2.0
|
||||
offset_top = 15.0
|
||||
offset_right = 102.0
|
||||
offset_bottom = 27.0
|
||||
theme_override_styles/background = SubResource("StyleBoxFlat_shield_bg")
|
||||
theme_override_styles/fill = SubResource("StyleBoxFlat_shield_fill")
|
||||
max_value = 100.0
|
||||
value = 100.0
|
||||
show_percentage = false
|
||||
|
||||
[connection signal="body_entered" from="DetectionArea" to="." method="_on_detection_area_body_entered"]
|
||||
[connection signal="body_exited" from="DetectionArea" to="." method="_on_detection_area_body_exited"]
|
||||
@@ -1 +1 @@
|
||||
uid://bio01w2gd5e7q
|
||||
uid://dlawq281oesnf
|
||||
|
||||
11
scenes/enemy/detection.gd
Normal file
11
scenes/enemy/detection.gd
Normal file
@@ -0,0 +1,11 @@
|
||||
extends Node
|
||||
|
||||
@onready var entity: CharacterBody3D = get_parent()
|
||||
|
||||
func _on_detection_area_body_entered(body: Node3D) -> void:
|
||||
if body is CharacterBody3D and body.name == "Player":
|
||||
EventBus.enemy_detected.emit(entity, body)
|
||||
|
||||
func _on_detection_area_body_exited(body: Node3D) -> void:
|
||||
if body is CharacterBody3D and body.name == "Player":
|
||||
EventBus.enemy_lost.emit(entity, body)
|
||||
1
scenes/enemy/detection.gd.uid
Normal file
1
scenes/enemy/detection.gd.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://b07aajhufqvb3
|
||||
@@ -1,37 +0,0 @@
|
||||
extends CharacterBody3D
|
||||
|
||||
enum State { IDLE, CHASE, ATTACK, RETURN }
|
||||
|
||||
@export var stats: BaseStats
|
||||
|
||||
var state: int = State.IDLE
|
||||
var target: Node3D = null
|
||||
var spawn_position: Vector3
|
||||
var portal: Node3D = null
|
||||
var gravity: float = ProjectSettings.get_setting("physics/3d/default_gravity")
|
||||
|
||||
func _ready() -> void:
|
||||
spawn_position = global_position
|
||||
add_to_group("enemies")
|
||||
Stats.register(self, stats)
|
||||
EventBus.entity_died.connect(_on_entity_died)
|
||||
|
||||
func _exit_tree() -> void:
|
||||
Stats.deregister(self)
|
||||
|
||||
func _on_entity_died(entity: Node) -> void:
|
||||
if entity == self:
|
||||
queue_free()
|
||||
|
||||
func _physics_process(delta: float) -> void:
|
||||
if not is_on_floor():
|
||||
velocity.y -= gravity * delta
|
||||
move_and_slide()
|
||||
|
||||
func _on_detection_area_body_entered(body: Node3D) -> void:
|
||||
if body is CharacterBody3D and body.name == "Player":
|
||||
EventBus.enemy_detected.emit(self, body)
|
||||
|
||||
func _on_detection_area_body_exited(body: Node3D) -> void:
|
||||
if body is CharacterBody3D and body.name == "Player":
|
||||
EventBus.enemy_lost.emit(self, body)
|
||||
@@ -1 +0,0 @@
|
||||
uid://bwi75jx0agktd
|
||||
@@ -1,18 +1,26 @@
|
||||
[gd_scene load_steps=6 format=3]
|
||||
[gd_scene format=3 uid="uid://db8pa55ev4l4a"]
|
||||
|
||||
[ext_resource type="Script" path="res://scenes/enemy/enemy.gd" id="1"]
|
||||
[ext_resource type="Script" path="res://scenes/healthbar.gd" id="4"]
|
||||
[ext_resource type="Script" path="res://scenes/enemy/enemy_movement.gd" id="5"]
|
||||
[ext_resource type="Resource" path="res://scenes/enemy/enemy_stats.tres" id="8"]
|
||||
[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"]
|
||||
|
||||
[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
|
||||
|
||||
[sub_resource type="SphereShape3D" id="SphereShape3D_1"]
|
||||
radius = 10.0
|
||||
|
||||
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_health_bg"]
|
||||
bg_color = Color(0.3, 0.1, 0.1, 1)
|
||||
|
||||
@@ -25,74 +33,58 @@ bg_color = Color(0.1, 0.1, 0.3, 1)
|
||||
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_shield_fill"]
|
||||
bg_color = Color(0.2, 0.5, 0.9, 1)
|
||||
|
||||
[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_1"]
|
||||
albedo_color = Color(0.8, 0.1, 0.1, 1)
|
||||
|
||||
[sub_resource type="SphereMesh" id="SphereMesh_1"]
|
||||
radius = 0.5
|
||||
height = 1.0
|
||||
material = SubResource("StandardMaterial3D_1")
|
||||
|
||||
[sub_resource type="SphereShape3D" id="SphereShape3D_1"]
|
||||
radius = 10.0
|
||||
|
||||
[node name="Enemy" type="CharacterBody3D"]
|
||||
[node name="Enemy" type="CharacterBody3D" unique_id=1724620529]
|
||||
script = ExtResource("1")
|
||||
stats = ExtResource("8")
|
||||
|
||||
[node name="CollisionShape3D" type="CollisionShape3D" parent="."]
|
||||
[node name="CollisionShape3D" type="CollisionShape3D" parent="." unique_id=1011138038]
|
||||
shape = SubResource("CapsuleShape3D_1")
|
||||
|
||||
[node name="Mesh" type="MeshInstance3D" parent="."]
|
||||
[node name="Mesh" type="MeshInstance3D" parent="." unique_id=1598094615]
|
||||
mesh = SubResource("SphereMesh_1")
|
||||
|
||||
[node name="HitArea" type="Area3D" parent="."]
|
||||
[node name="HitArea" type="Area3D" parent="." unique_id=893463784]
|
||||
collision_layer = 4
|
||||
collision_mask = 0
|
||||
|
||||
[node name="CollisionShape3D" type="CollisionShape3D" parent="HitArea"]
|
||||
[node name="CollisionShape3D" type="CollisionShape3D" parent="HitArea" unique_id=984781962]
|
||||
shape = SubResource("CapsuleShape3D_2")
|
||||
|
||||
[node name="NavigationAgent3D" type="NavigationAgent3D" parent="."]
|
||||
[node name="NavigationAgent3D" type="NavigationAgent3D" parent="." unique_id=440641945]
|
||||
|
||||
[node name="EnemyMovement" type="Node" parent="."]
|
||||
script = ExtResource("5")
|
||||
[node name="Detection" type="Node" parent="." unique_id=534240144]
|
||||
script = ExtResource("2")
|
||||
|
||||
[node name="DetectionArea" type="Area3D" parent="."]
|
||||
[node name="DetectionArea" type="Area3D" parent="." unique_id=1955178598]
|
||||
collision_layer = 0
|
||||
collision_mask = 1
|
||||
monitoring = true
|
||||
|
||||
[node name="CollisionShape3D" type="CollisionShape3D" parent="DetectionArea"]
|
||||
[node name="CollisionShape3D" type="CollisionShape3D" parent="DetectionArea" unique_id=557461347]
|
||||
shape = SubResource("SphereShape3D_1")
|
||||
|
||||
[node name="Healthbar" type="Sprite3D" parent="."]
|
||||
[node name="Healthbar" type="Sprite3D" parent="." unique_id=1008728031]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1.5, 0)
|
||||
billboard = 1
|
||||
pixel_size = 0.01
|
||||
script = ExtResource("4")
|
||||
|
||||
[node name="SubViewport" type="SubViewport" parent="Healthbar"]
|
||||
[node name="SubViewport" type="SubViewport" parent="Healthbar" unique_id=1219060718]
|
||||
transparent_bg = true
|
||||
size = Vector2i(104, 29)
|
||||
|
||||
[node name="Border" type="ColorRect" parent="Healthbar/SubViewport"]
|
||||
[node name="Border" type="ColorRect" parent="Healthbar/SubViewport" unique_id=848146848]
|
||||
offset_right = 104.0
|
||||
offset_bottom = 29.0
|
||||
color = Color(1, 0.9, 0.2, 1)
|
||||
|
||||
[node name="HealthBar" type="ProgressBar" parent="Healthbar/SubViewport"]
|
||||
[node name="HealthBar" type="ProgressBar" parent="Healthbar/SubViewport" unique_id=1206434403]
|
||||
offset_left = 2.0
|
||||
offset_top = 2.0
|
||||
offset_right = 102.0
|
||||
offset_bottom = 12.0
|
||||
theme_override_styles/background = SubResource("StyleBoxFlat_health_bg")
|
||||
theme_override_styles/fill = SubResource("StyleBoxFlat_health_fill")
|
||||
max_value = 100.0
|
||||
value = 100.0
|
||||
show_percentage = false
|
||||
|
||||
[node name="ShieldBar" type="ProgressBar" parent="Healthbar/SubViewport"]
|
||||
[node name="ShieldBar" type="ProgressBar" parent="Healthbar/SubViewport" unique_id=1891108036]
|
||||
offset_left = 2.0
|
||||
offset_top = 15.0
|
||||
offset_right = 102.0
|
||||
@@ -103,5 +95,5 @@ max_value = 50.0
|
||||
value = 50.0
|
||||
show_percentage = false
|
||||
|
||||
[connection signal="body_entered" from="DetectionArea" to="." method="_on_detection_area_body_entered"]
|
||||
[connection signal="body_exited" from="DetectionArea" to="." method="_on_detection_area_body_exited"]
|
||||
[connection signal="body_entered" from="DetectionArea" to="Detection" method="_on_detection_area_body_entered"]
|
||||
[connection signal="body_exited" from="DetectionArea" to="Detection" method="_on_detection_area_body_exited"]
|
||||
|
||||
@@ -1,62 +0,0 @@
|
||||
extends Node
|
||||
|
||||
const SPEED := 3.0
|
||||
const ATTACK_RANGE := 2.0
|
||||
const REGEN_FAST := 0.10
|
||||
const REGEN_SLOW := 0.01
|
||||
|
||||
@onready var enemy: CharacterBody3D = get_parent()
|
||||
@onready var nav_agent: NavigationAgent3D = get_parent().get_node("NavigationAgent3D")
|
||||
|
||||
func _physics_process(delta: float) -> void:
|
||||
match enemy.state:
|
||||
enemy.State.IDLE:
|
||||
enemy.velocity.x = 0
|
||||
enemy.velocity.z = 0
|
||||
enemy.State.CHASE:
|
||||
_chase()
|
||||
enemy.State.RETURN:
|
||||
_return_to_spawn(delta)
|
||||
|
||||
func _chase() -> void:
|
||||
if not is_instance_valid(enemy.target):
|
||||
enemy.state = enemy.State.RETURN
|
||||
return
|
||||
var dist_to_target := enemy.global_position.distance_to(enemy.target.global_position)
|
||||
if dist_to_target <= ATTACK_RANGE:
|
||||
enemy.state = enemy.State.ATTACK
|
||||
return
|
||||
nav_agent.target_position = enemy.target.global_position
|
||||
var next_pos := nav_agent.get_next_path_position()
|
||||
var direction := (next_pos - enemy.global_position).normalized()
|
||||
direction.y = 0
|
||||
enemy.velocity.x = direction.x * SPEED
|
||||
enemy.velocity.z = direction.z * SPEED
|
||||
|
||||
func _return_to_spawn(delta: float) -> void:
|
||||
var dist := enemy.global_position.distance_to(enemy.spawn_position)
|
||||
if dist < 1.0:
|
||||
enemy.state = enemy.State.IDLE
|
||||
enemy.velocity.x = 0
|
||||
enemy.velocity.z = 0
|
||||
return
|
||||
nav_agent.target_position = enemy.spawn_position
|
||||
var next_pos := nav_agent.get_next_path_position()
|
||||
var direction := (next_pos - enemy.global_position).normalized()
|
||||
direction.y = 0
|
||||
enemy.velocity.x = direction.x * SPEED
|
||||
enemy.velocity.z = direction.z * SPEED
|
||||
_regenerate(delta)
|
||||
|
||||
func _regenerate(delta: float) -> void:
|
||||
var health: float = Stats.get_stat(enemy, "health")
|
||||
var max_health: float = Stats.get_stat(enemy, "max_health")
|
||||
if health == null or max_health == null:
|
||||
return
|
||||
if health < max_health:
|
||||
var rate: float = REGEN_FAST
|
||||
if health >= max_health * 0.99:
|
||||
rate = REGEN_SLOW
|
||||
health = min(health + max_health * rate * delta, max_health)
|
||||
Stats.set_stat(enemy, "health", health)
|
||||
EventBus.health_changed.emit(enemy, health, max_health)
|
||||
@@ -1 +0,0 @@
|
||||
uid://tnx6rbnnngn
|
||||
30
scenes/enemy/init.gd
Normal file
30
scenes/enemy/init.gd
Normal file
@@ -0,0 +1,30 @@
|
||||
extends CharacterBody3D
|
||||
|
||||
@export var stats: EnemyStats
|
||||
|
||||
var gravity: float = ProjectSettings.get_setting("physics/3d/default_gravity")
|
||||
|
||||
func _ready() -> void:
|
||||
add_to_group("enemies")
|
||||
if is_in_group("boss"):
|
||||
BossData.register(self, stats)
|
||||
BossData.set_stat(self, "spawn_position", global_position)
|
||||
else:
|
||||
EnemyData.register(self, stats)
|
||||
EnemyData.set_stat(self, "spawn_position", global_position)
|
||||
EventBus.entity_died.connect(_on_entity_died)
|
||||
|
||||
func _exit_tree() -> void:
|
||||
if is_in_group("boss"):
|
||||
BossData.deregister(self)
|
||||
else:
|
||||
EnemyData.deregister(self)
|
||||
|
||||
func _on_entity_died(entity: Node) -> void:
|
||||
if entity == self:
|
||||
queue_free()
|
||||
|
||||
func _physics_process(delta: float) -> void:
|
||||
if not is_on_floor():
|
||||
velocity.y -= gravity * delta
|
||||
move_and_slide()
|
||||
1
scenes/enemy/init.gd.uid
Normal file
1
scenes/enemy/init.gd.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://vy6hyqok0p8b
|
||||
Reference in New Issue
Block a user