Enemy dreamer AI mostly functional, fix player attack knockback oversight,

This commit is contained in:
ToasterPanic 2026-05-14 10:41:51 -04:00
parent 44ab597ca7
commit 5743ecf313
4 changed files with 97 additions and 25 deletions

View file

@ -194,10 +194,9 @@ script = ExtResource("12_trtic")
[node name="HitCollision" type="Area3D" parent="Dreamer" unique_id=1754593615] [node name="HitCollision" type="Area3D" parent="Dreamer" unique_id=1754593615]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.1500001, 0) transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.1500001, 0)
collision_layer = 0 collision_layer = 0
collision_mask = 2
[node name="Shape" type="CollisionShape3D" parent="Dreamer/HitCollision" unique_id=1642136717] [node name="Shape" type="CollisionShape3D" parent="Dreamer/HitCollision" unique_id=1642136717]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -0.5, 0, 0) transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, -0.5)
shape = SubResource("BoxShape3D_trtic") shape = SubResource("BoxShape3D_trtic")
[node name="DreamerBody" parent="Dreamer" unique_id=595793987 instance=ExtResource("4_p57ef")] [node name="DreamerBody" parent="Dreamer" unique_id=595793987 instance=ExtResource("4_p57ef")]

View file

@ -189,6 +189,21 @@ tracks/14/keys = {
"values": [Vector3(0, 0, 0)] "values": [Vector3(0, 0, 0)]
} }
[sub_resource type="Animation" id="Animation_lg4u0"]
resource_name = "charge_weapon"
tracks/0/type = "value"
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/path = NodePath("Body/ArmPivot:rotation")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/keys = {
"times": PackedFloat32Array(0, 1),
"transitions": PackedFloat32Array(1, 1),
"update": 0,
"values": [Vector3(0, 0, 0), Vector3(0, 0, -1.134464)]
}
[sub_resource type="Animation" id="Animation_u5sy4"] [sub_resource type="Animation" id="Animation_u5sy4"]
resource_name = "fall" resource_name = "fall"
length = 0.2 length = 0.2
@ -730,6 +745,7 @@ tracks/0/keys = {
[sub_resource type="AnimationLibrary" id="AnimationLibrary_vtaks"] [sub_resource type="AnimationLibrary" id="AnimationLibrary_vtaks"]
_data = { _data = {
&"RESET": SubResource("Animation_gee14"), &"RESET": SubResource("Animation_gee14"),
&"charge_weapon": SubResource("Animation_lg4u0"),
&"fall": SubResource("Animation_u5sy4"), &"fall": SubResource("Animation_u5sy4"),
&"hold_weapon": SubResource("Animation_yptk5"), &"hold_weapon": SubResource("Animation_yptk5"),
&"jump": SubResource("Animation_p57ef"), &"jump": SubResource("Animation_p57ef"),
@ -757,9 +773,16 @@ animation = &"hold_weapon"
[sub_resource type="AnimationNodeAnimation" id="AnimationNodeAnimation_ny5xw"] [sub_resource type="AnimationNodeAnimation" id="AnimationNodeAnimation_ny5xw"]
animation = &"swing_weapon" animation = &"swing_weapon"
[sub_resource type="AnimationNodeAnimation" id="AnimationNodeAnimation_lg4u0"]
animation = &"charge_weapon"
[sub_resource type="AnimationNodeAnimation" id="AnimationNodeAnimation_p57ef"] [sub_resource type="AnimationNodeAnimation" id="AnimationNodeAnimation_p57ef"]
animation = &"jump" animation = &"jump"
[sub_resource type="AnimationNodeOneShot" id="AnimationNodeOneShot_1speq"]
filter_enabled = true
filters = ["Body/ArmPivot:rotation"]
[sub_resource type="AnimationNodeBlend2" id="AnimationNodeBlend2_gee14"] [sub_resource type="AnimationNodeBlend2" id="AnimationNodeBlend2_gee14"]
[sub_resource type="AnimationNodeAnimation" id="AnimationNodeAnimation_u5sy4"] [sub_resource type="AnimationNodeAnimation" id="AnimationNodeAnimation_u5sy4"]
@ -791,8 +814,8 @@ filters = ["Body/ArmPivot:rotation"]
[sub_resource type="AnimationNodeTimeScale" id="AnimationNodeTimeScale_p57ef"] [sub_resource type="AnimationNodeTimeScale" id="AnimationNodeTimeScale_p57ef"]
[sub_resource type="AnimationNodeBlendTree" id="AnimationNodeBlendTree_kvpfn"] [sub_resource type="AnimationNodeBlendTree" id="AnimationNodeBlendTree_kvpfn"]
graph_offset = Vector2(242.94073, -68.15653) graph_offset = Vector2(601.4115, -104.36627)
nodes/output/position = Vector2(2140, 100) nodes/output/position = Vector2(2500, 60)
nodes/jump/node = SubResource("AnimationNodeOneShot_u5sy4") nodes/jump/node = SubResource("AnimationNodeOneShot_u5sy4")
nodes/jump/position = Vector2(860, 100) nodes/jump/position = Vector2(860, 100)
nodes/reset/node = SubResource("AnimationNodeAnimation_0tnpc") nodes/reset/node = SubResource("AnimationNodeAnimation_0tnpc")
@ -829,7 +852,11 @@ nodes/swing_weapon/node = SubResource("AnimationNodeOneShot_06ej8")
nodes/swing_weapon/position = Vector2(1900, 60) nodes/swing_weapon/position = Vector2(1900, 60)
"nodes/Animation 6/node" = SubResource("AnimationNodeAnimation_ny5xw") "nodes/Animation 6/node" = SubResource("AnimationNodeAnimation_ny5xw")
"nodes/Animation 6/position" = Vector2(1700, 340) "nodes/Animation 6/position" = Vector2(1700, 340)
node_connections = [&"output", 0, &"swing_weapon", &"jump", 0, &"leap", &"jump", 1, &"Animation", &"walk", 0, &"reset", &"walk", 1, &"walk_speed", &"walk_speed", 0, &"move", &"fall", 0, &"walk", &"fall", 1, &"fall_anim", &"leap", 0, &"fall", &"leap", 1, &"Animation 2", &"Add2", 0, &"jump", &"Add2", 1, &"layering", &"layering", 0, &"Animation 3", &"layering", 1, &"Animation 4", &"hold_weapon", 0, &"Add2", &"hold_weapon", 1, &"Animation 5", &"swing_weapon", 0, &"hold_weapon", &"swing_weapon", 1, &"Animation 6"] nodes/charge_weapon/node = SubResource("AnimationNodeOneShot_1speq")
nodes/charge_weapon/position = Vector2(2180, 60)
"nodes/Animation 7/node" = SubResource("AnimationNodeAnimation_lg4u0")
"nodes/Animation 7/position" = Vector2(2000, 340)
node_connections = [&"output", 0, &"charge_weapon", &"jump", 0, &"leap", &"jump", 1, &"Animation", &"walk", 0, &"reset", &"walk", 1, &"walk_speed", &"walk_speed", 0, &"move", &"fall", 0, &"walk", &"fall", 1, &"fall_anim", &"leap", 0, &"fall", &"leap", 1, &"Animation 2", &"Add2", 0, &"jump", &"Add2", 1, &"layering", &"layering", 0, &"Animation 3", &"layering", 1, &"Animation 4", &"hold_weapon", 0, &"Add2", &"hold_weapon", 1, &"Animation 5", &"swing_weapon", 0, &"hold_weapon", &"swing_weapon", 1, &"Animation 6", &"charge_weapon", 0, &"swing_weapon", &"charge_weapon", 1, &"Animation 7"]
[node name="DreamerBody" type="Node3D" unique_id=723408850] [node name="DreamerBody" type="Node3D" unique_id=723408850]
script = ExtResource("1_54k0m") script = ExtResource("1_54k0m")
@ -913,3 +940,6 @@ parameters/hold_weapon/blend_amount = 0.0
parameters/swing_weapon/active = false parameters/swing_weapon/active = false
parameters/swing_weapon/internal_active = false parameters/swing_weapon/internal_active = false
parameters/swing_weapon/request = 0 parameters/swing_weapon/request = 0
parameters/charge_weapon/active = false
parameters/charge_weapon/internal_active = false
parameters/charge_weapon/request = 0

View file

@ -9,20 +9,25 @@ var face_left = false
var combatable = true var combatable = true
var iframes = 0 var iframes := 0.0
var knockback_time = 0 var knockback_time := 0.0
var health = 100 var health := 100.0
var current_weapon = "test_sword" var current_weapon := "test_sword"
enum { enum {
STATE_IDLE, STATE_IDLE,
STATE_APPROACH_ENEMY, STATE_APPROACH_ENEMY,
STATE_CHARGE_ATTACK, STATE_CHARGE_ATTACK,
STATE_ATTACK STATE_ATTACK,
STATE_HIT,
STATE_DEAD,
} }
var state = STATE_APPROACH_ENEMY
var state_timer := 0.0
@onready var game = get_parent() @onready var game = get_parent()
@onready var player = game.get_node("Player") @onready var player = game.get_node("Player")
@ -41,18 +46,14 @@ func get_weapon_info(weapon: String, value: String):
return Global.weapons[weapon][value] return Global.weapons[weapon][value]
else: return null else: return null
func on_hit(hitter: Node3D = null) -> void: func on_knockback(hitter: Node3D = null) -> void:
iframes = 0.8 state = STATE_HIT
state_timer = 0.5
if hitter:
knockback_time = 0.25
velocity += hitter.global_position.direction_to(global_position) * 8
velocity.y = 0
func _ready() -> void: func _ready() -> void:
$DreamerBody.look_at(game.get_node("PlayerCamera").global_position)
$DreamerBody.rotation.x = 0 $DreamerBody.rotation.x = 0
face_rotation = $DreamerBody.rotation.y face_rotation = player.face_rotation
$DreamerBody/Animator.set("parameters/hold_weapon/blend_amount", 1.0)
func _process(delta: float) -> void: func _process(delta: float) -> void:
if iframes > 0: if iframes > 0:
@ -82,7 +83,6 @@ func _physics_process(delta: float) -> void:
if combatable: if combatable:
#$DreamerBody/Body/ArmPivot.rotation.z = mouse_point_angle #$DreamerBody/Body/ArmPivot.rotation.z = mouse_point_angle
$HitCollision.rotation.y = -mouse_point_angle + face_rotation
if abs(rad_to_deg(mouse_point_angle) - (-90)) < 50: if abs(rad_to_deg(mouse_point_angle) - (-90)) < 50:
$HitCollision/Shape.shape.size.x = 1.5 $HitCollision/Shape.shape.size.x = 1.5
@ -110,11 +110,49 @@ func _physics_process(delta: float) -> void:
velocity.y = JUMP_VELOCITY velocity.y = JUMP_VELOCITY
$DreamerBody/Animator.set("parameters/jump/request", AnimationNodeOneShot.ONE_SHOT_REQUEST_FIRE) $DreamerBody/Animator.set("parameters/jump/request", AnimationNodeOneShot.ONE_SHOT_REQUEST_FIRE)
navigation_agent.set_target_position(player.global_position) var direction = Vector2.ZERO
var next_path_position: Vector3 = navigation_agent.get_next_path_position() state_timer -= delta
var direction = global_position.direction_to(next_path_position) if state == STATE_APPROACH_ENEMY:
navigation_agent.set_target_position(player.global_position)
var next_path_position: Vector3 = navigation_agent.get_next_path_position()
direction = global_position.direction_to(next_path_position)
if (player.global_position - global_position).length() < 1:
state = STATE_CHARGE_ATTACK
state_timer = 1
$DreamerBody/Animator.set("parameters/charge_weapon/request", AnimationNodeOneShot.ONE_SHOT_REQUEST_FIRE)
elif state == STATE_CHARGE_ATTACK:
$HitCollision.look_at(player.global_position)
$HitCollision.rotation.x = 0
if state_timer <= 0:
state = STATE_ATTACK
$DreamerBody/Animator.set("parameters/swing_weapon/request", AnimationNodeOneShot.ONE_SHOT_REQUEST_FIRE)
var slash = load("res://scenes/effects/slash.tscn").instantiate()
game.add_child(slash)
slash.global_position = global_position
slash.global_rotation.y = $HitCollision.global_rotation.y + deg_to_rad(90)
slash.play_effect()
if player in $HitCollision.get_overlapping_bodies():
if player.iframes <= 0:
player.health -= 20
player.on_hit(self)
state_timer = 0.5
elif state == STATE_ATTACK:
if state_timer <= 0:
state = STATE_APPROACH_ENEMY
elif state == STATE_HIT:
$DreamerBody/Animator.set("parameters/charge_weapon/request", AnimationNodeOneShot.ONE_SHOT_REQUEST_ABORT)
if state_timer <= 0:
state = STATE_APPROACH_ENEMY
if direction.x > 0: if direction.x > 0:
face_left = false face_left = false

View file

@ -174,9 +174,14 @@ func _physics_process(delta: float) -> void:
if "health" in body: if "health" in body:
body.health -= damage body.health -= damage
var knockback_pos = global_position
knockback_pos.y = 0
var knockback_body_pos = body.global_position
knockback_body_pos.y = 0
body.position.y += 0.2 body.position.y += 0.2
body.velocity.y = 0.4 body.velocity.y = 0.4
body.velocity += global_position.direction_to(body.global_position) * knockback body.velocity += knockback_pos.direction_to(knockback_body_pos) * knockback
if body.velocity.length() > knockback: if body.velocity.length() > knockback:
body.velocity = body.velocity.normalized() * knockback body.velocity = body.velocity.normalized() * knockback