From 87a9fad00513accaecb2e3f33f50fd08a9bf48dc Mon Sep 17 00:00:00 2001 From: Minimata Date: Mon, 19 Jan 2026 23:15:40 +0100 Subject: [PATCH] now that's an animation --- player_controller/Scripts/PlayerController.cs | 7 + systems/head/HeadSystem.cs | 17 ++ systems/head/fp_blend_tree.tres | 24 +++ systems/head/fp_state_machine.tres | 28 +++ systems/head/head_system.tscn | 164 +++++++++++++++++- 5 files changed, 238 insertions(+), 2 deletions(-) create mode 100644 systems/head/fp_blend_tree.tres create mode 100644 systems/head/fp_state_machine.tres diff --git a/player_controller/Scripts/PlayerController.cs b/player_controller/Scripts/PlayerController.cs index 9c22e842..671fe5bf 100644 --- a/player_controller/Scripts/PlayerController.cs +++ b/player_controller/Scripts/PlayerController.cs @@ -1735,6 +1735,13 @@ public partial class PlayerController : CharacterBody3D, } if (!WeaponSystem.InHandState.Active) return; + PerformHit(); + } + + public void PerformHit() + { + HeadSystem.OnHit(); + var bodies = WeaponHitbox.GetOverlappingBodies(); foreach (var body in bodies) { diff --git a/systems/head/HeadSystem.cs b/systems/head/HeadSystem.cs index f621e188..dea61e1d 100644 --- a/systems/head/HeadSystem.cs +++ b/systems/head/HeadSystem.cs @@ -21,6 +21,7 @@ public partial class HeadSystem : Node3D private Camera3D _camera; private Marker3D _cameraAnchor; private AnimationPlayer _animationPlayer; + private AnimationTree _animationTree; [Export(PropertyHint.Range, "0,10,0.1,or_greater")] public float LookSensitivity { get; set; } = 1f; @@ -88,6 +89,7 @@ public partial class HeadSystem : Node3D _camera = GetNode("CameraSmooth/Camera3D"); _cameraAnchor = GetNode("CameraAnchor"); _animationPlayer = GetNode("AnimationPlayer"); + _animationTree = GetNode("AnimationTree"); _fpRig = GetNode("FPRig"); _fpDisplacedRig = GetNode("FPRig/Sword"); @@ -101,6 +103,21 @@ public partial class HeadSystem : Node3D { _animationPlayer.Play("mantle"); } + + public void OnHit() + { + _animationTree.Set("parameters/OnHit/request", (int) AnimationNodeOneShot.OneShotRequest.Fire); + } + + public void OnHitboxActivated() + { + GD.Print("Hitbox activated"); + } + + public void OnHitboxDeactivated() + { + GD.Print("Hitbox deactivated"); + } public void LookAround(CameraParameters inputs) { diff --git a/systems/head/fp_blend_tree.tres b/systems/head/fp_blend_tree.tres new file mode 100644 index 00000000..1985c0b9 --- /dev/null +++ b/systems/head/fp_blend_tree.tres @@ -0,0 +1,24 @@ +[gd_resource type="AnimationNodeBlendTree" load_steps=5 format=3 uid="uid://c26yvcyyyj811"] + +[ext_resource type="AnimationNodeStateMachine" uid="uid://3r5oeg0ho0d4" path="res://systems/head/fp_state_machine.tres" id="1_knaxl"] + +[sub_resource type="AnimationNodeAnimation" id="AnimationNodeAnimation_knaxl"] +animation = &"idle" + +[sub_resource type="AnimationNodeOneShot" id="AnimationNodeOneShot_1hkum"] + +[sub_resource type="AnimationNodeAnimation" id="AnimationNodeAnimation_23rmc"] +animation = &"hit1" + +[resource] +graph_offset = Vector2(-455.3856, -37.41575) +nodes/output/position = Vector2(320, 160) +nodes/AnimationNodeStateMachine/node = ExtResource("1_knaxl") +nodes/AnimationNodeStateMachine/position = Vector2(-540, 200) +nodes/Idle/node = SubResource("AnimationNodeAnimation_knaxl") +nodes/Idle/position = Vector2(-80, 20) +nodes/OnHit/node = SubResource("AnimationNodeOneShot_1hkum") +nodes/OnHit/position = Vector2(120, 100) +nodes/hit1/node = SubResource("AnimationNodeAnimation_23rmc") +nodes/hit1/position = Vector2(-80, 220) +node_connections = [&"output", 0, &"OnHit", &"OnHit", 0, &"Idle", &"OnHit", 1, &"hit1"] diff --git a/systems/head/fp_state_machine.tres b/systems/head/fp_state_machine.tres new file mode 100644 index 00000000..34ee2636 --- /dev/null +++ b/systems/head/fp_state_machine.tres @@ -0,0 +1,28 @@ +[gd_resource type="AnimationNodeStateMachine" load_steps=6 format=3 uid="uid://3r5oeg0ho0d4"] + +[sub_resource type="AnimationNodeAnimation" id="AnimationNodeAnimation_adm0b"] +animation = &"hit1" + +[sub_resource type="AnimationNodeAnimation" id="AnimationNodeAnimation_73q32"] +animation = &"idle" + +[sub_resource type="AnimationNodeStateMachineTransition" id="AnimationNodeStateMachineTransition_adm0b"] +advance_mode = 2 + +[sub_resource type="AnimationNodeStateMachineTransition" id="AnimationNodeStateMachineTransition_7r4t3"] +advance_mode = 2 +advance_condition = &"on_hit" + +[sub_resource type="AnimationNodeStateMachineTransition" id="AnimationNodeStateMachineTransition_2u8w7"] +break_loop_at_end = true +switch_mode = 2 +advance_mode = 2 + +[resource] +states/Start/position = Vector2(100, 91) +states/hit1/node = SubResource("AnimationNodeAnimation_adm0b") +states/hit1/position = Vector2(511, 61) +states/idle/node = SubResource("AnimationNodeAnimation_73q32") +states/idle/position = Vector2(331, 91) +transitions = ["Start", "idle", SubResource("AnimationNodeStateMachineTransition_adm0b"), "idle", "hit1", SubResource("AnimationNodeStateMachineTransition_7r4t3"), "hit1", "idle", SubResource("AnimationNodeStateMachineTransition_2u8w7")] +graph_offset = Vector2(-82, -9) diff --git a/systems/head/head_system.tscn b/systems/head/head_system.tscn index aebf76c4..f2b348e2 100644 --- a/systems/head/head_system.tscn +++ b/systems/head/head_system.tscn @@ -1,7 +1,8 @@ -[gd_scene load_steps=6 format=3 uid="uid://0ysqmqphq6mq"] +[gd_scene load_steps=9 format=3 uid="uid://0ysqmqphq6mq"] [ext_resource type="Script" uid="uid://dtkdrnsmlwm67" path="res://systems/head/HeadSystem.cs" id="1_8abgy"] [ext_resource type="ArrayMesh" uid="uid://ckr26s4e3fj1m" path="res://assets/swords/resources/fp_sword23.tres" id="2_c5qep"] +[ext_resource type="AnimationNodeBlendTree" uid="uid://c26yvcyyyj811" path="res://systems/head/fp_blend_tree.tres" id="3_r0h40"] [sub_resource type="Animation" id="Animation_urko7"] length = 0.001 @@ -27,6 +28,54 @@ tracks/1/keys = { "points": PackedFloat32Array(0, -0.15, 0, 0.15, 0), "times": PackedFloat32Array(0) } +tracks/2/type = "value" +tracks/2/imported = false +tracks/2/enabled = true +tracks/2/path = NodePath("../../FPRig/Sword:position") +tracks/2/interp = 1 +tracks/2/loop_wrap = true +tracks/2/keys = { +"times": PackedFloat32Array(0), +"transitions": PackedFloat32Array(1), +"update": 0, +"values": [Vector3(0.53640664, -0.7880347, -1.9288678)] +} +tracks/3/type = "value" +tracks/3/imported = false +tracks/3/enabled = true +tracks/3/path = NodePath("../../FPRig/Sword:rotation") +tracks/3/interp = 1 +tracks/3/loop_wrap = true +tracks/3/keys = { +"times": PackedFloat32Array(0), +"transitions": PackedFloat32Array(1), +"update": 0, +"values": [Vector3(-0.083978735, -1.136043, 0.19867715)] +} +tracks/4/type = "value" +tracks/4/imported = false +tracks/4/enabled = true +tracks/4/path = NodePath("../../FPRig/Sword:scale") +tracks/4/interp = 1 +tracks/4/loop_wrap = true +tracks/4/keys = { +"times": PackedFloat32Array(0), +"transitions": PackedFloat32Array(1), +"update": 0, +"values": [Vector3(1.0000001, 1.0000001, 1.0000005)] +} +tracks/5/type = "value" +tracks/5/imported = false +tracks/5/enabled = true +tracks/5/path = NodePath("..:rotation") +tracks/5/interp = 1 +tracks/5/loop_wrap = true +tracks/5/keys = { +"times": PackedFloat32Array(0), +"transitions": PackedFloat32Array(1), +"update": 0, +"values": [Vector3(0, 0, 0.00011616433)] +} [sub_resource type="Animation" id="Animation_8abgy"] resource_name = "mantle" @@ -54,9 +103,110 @@ tracks/1/keys = { "times": PackedFloat32Array(0, 0.1, 0.2, 0.3) } +[sub_resource type="Animation" id="Animation_0hyrq"] +resource_name = "idle" +length = 2.0 +loop_mode = 1 +tracks/0/type = "value" +tracks/0/imported = false +tracks/0/enabled = true +tracks/0/path = NodePath("../../FPRig/Sword:position") +tracks/0/interp = 2 +tracks/0/loop_wrap = true +tracks/0/keys = { +"times": PackedFloat32Array(0, 0.3, 0.6, 1, 1.4), +"transitions": PackedFloat32Array(1, 1, 1, 1, 1), +"update": 0, +"values": [Vector3(0.53640664, -0.7880347, -1.9288678), Vector3(0.53640664, -0.83580256, -1.9288678), Vector3(0.53640664, -0.86088884, -1.9288678), Vector3(0.53640664, -0.8256072, -1.9288678), Vector3(0.53640664, -0.7880347, -1.9288678)] +} +tracks/1/type = "value" +tracks/1/imported = false +tracks/1/enabled = true +tracks/1/path = NodePath("../../FPRig/Sword:rotation") +tracks/1/interp = 2 +tracks/1/loop_wrap = true +tracks/1/keys = { +"times": PackedFloat32Array(0, 0.3, 0.6, 1, 1.4), +"transitions": PackedFloat32Array(1, 1, 1, 1, 1), +"update": 0, +"values": [Vector3(-0.083978735, -1.136043, 0.19867715), Vector3(-0.06987281, -1.1365474, 0.20524277), Vector3(-0.05990464, -1.1368362, 0.20987195), Vector3(-0.06303402, -1.1367121, 0.2084137), Vector3(-0.083978735, -1.136043, 0.19867715)] +} + +[sub_resource type="Animation" id="Animation_r0h40"] +resource_name = "hit1" +length = 0.30000168 +step = 0.016666668 +tracks/0/type = "value" +tracks/0/imported = false +tracks/0/enabled = true +tracks/0/path = NodePath("../../FPRig/Sword:position") +tracks/0/interp = 1 +tracks/0/loop_wrap = true +tracks/0/keys = { +"times": PackedFloat32Array(0, 0.06666667, 0.11666667, 0.15, 0.21666667, 0.3), +"transitions": PackedFloat32Array(1, 1, 1, 1, 1, 1), +"update": 0, +"values": [Vector3(0.53640664, -0.7880347, -1.9288678), Vector3(0.4045868, -0.4412415, -1.5352597), Vector3(-0.4799922, -0.5403832, -1.6861614), Vector3(-0.46995986, -0.53766656, -1.3638693), Vector3(-0.49520528, -0.5369735, -1.3145388), Vector3(-0.4048354, -0.5878634, -1.2836416)] +} +tracks/1/type = "value" +tracks/1/imported = false +tracks/1/enabled = true +tracks/1/path = NodePath("../../FPRig/Sword:rotation") +tracks/1/interp = 1 +tracks/1/loop_wrap = true +tracks/1/keys = { +"times": PackedFloat32Array(0, 0.06666667, 0.11666667, 0.15, 0.21666667, 0.3), +"transitions": PackedFloat32Array(1, 1, 1, 1, 1, 1), +"update": 0, +"values": [Vector3(-0.083978735, -1.136043, 0.19867715), Vector3(-0.7788485, -2.0049822, -0.2951485), Vector3(-0.94931036, -0.5881021, -0.61733377), Vector3(-1.3252386, -0.102411434, 0.58406436), Vector3(-1.2938086, -0.18945412, 0.7334958), Vector3(-1.1484056, -0.2900904, 0.6867544)] +} +tracks/2/type = "value" +tracks/2/imported = false +tracks/2/enabled = true +tracks/2/path = NodePath("../../FPRig/Sword:scale") +tracks/2/interp = 2 +tracks/2/loop_wrap = true +tracks/2/keys = { +"times": PackedFloat32Array(0, 0.06666667, 0.11666667, 0.15, 0.21666667, 0.3), +"transitions": PackedFloat32Array(1, 1, 1, 1, 1, 1), +"update": 0, +"values": [Vector3(1.0000001, 1.0000001, 1.0000005), Vector3(1, 1.0004268, 1.0000002), Vector3(0.99999994, 1.2493719, 0.99999976), Vector3(1.0000001, 1.1750004, 1.0000004), Vector3(0.99999994, 0.99999994, 0.99999994), Vector3(1.0000001, 0.9999999, 1)] +} +tracks/3/type = "value" +tracks/3/imported = false +tracks/3/enabled = true +tracks/3/path = NodePath("..:rotation") +tracks/3/interp = 2 +tracks/3/loop_wrap = true +tracks/3/keys = { +"times": PackedFloat32Array(0, 0.083333336, 0.11666667, 0.2, 0.23333333, 0.3), +"transitions": PackedFloat32Array(1, 1, 1, 1, 1, 1), +"update": 0, +"values": [Vector3(0, 0, 0), Vector3(0, 0, 0), Vector3(0, 0, 0.00011616433), Vector3(0, -0.02617994, -0.02617994), Vector3(0, 0.02617994, 0.02617994), Vector3(0, 0, 0)] +} +tracks/4/type = "method" +tracks/4/imported = false +tracks/4/enabled = true +tracks/4/path = NodePath("../..") +tracks/4/interp = 1 +tracks/4/loop_wrap = true +tracks/4/keys = { +"times": PackedFloat32Array(0.083333336, 0.23333333), +"transitions": PackedFloat32Array(1, 1), +"values": [{ +"args": [], +"method": &"OnHitboxActivated" +}, { +"args": [], +"method": &"OnHitboxDeactivated" +}] +} + [sub_resource type="AnimationLibrary" id="AnimationLibrary_0hyrq"] _data = { &"RESET": SubResource("Animation_urko7"), +&"hit1": SubResource("Animation_r0h40"), +&"idle": SubResource("Animation_0hyrq"), &"mantle": SubResource("Animation_8abgy") } @@ -69,7 +219,7 @@ DisplacedWeaponAdjustmentSpeed = 8.0 [node name="FPRig" type="Node3D" parent="."] [node name="Sword" type="Node3D" parent="FPRig"] -transform = Transform3D(0.4349438, 0.02783122, -0.90002745, 0.18060648, 0.97651464, 0.1174756, 0.8821594, -0.21364608, 0.41970247, 0.53640664, -0.82246387, -1.9288678) +transform = Transform3D(0.42791694, -0.008550272, -0.9037781, 0.19667713, 0.9768738, 0.0838801, 0.88215953, -0.2136461, 0.41970265, 0.53640664, -0.7880347, -1.9288678) [node name="SwordMesh" type="MeshInstance3D" parent="FPRig/Sword"] transform = Transform3D(1, 0, 0, 0, 0.99999994, 0, 0, 0, 1, 0, 0, 0) @@ -77,6 +227,7 @@ cast_shadow = 0 mesh = ExtResource("2_c5qep") [node name="CameraSmooth" type="Node3D" parent="."] +transform = Transform3D(1, -0.00011616433, 0, 0.00011616433, 1, 0, 0, 0, 1, 0, 0, 0) [node name="Camera3D" type="Camera3D" parent="CameraSmooth"] transform = Transform3D(1, 0, 0, 0, 0.99999994, 0, 0, 0, 0.99999994, 0, 0, 0) @@ -90,3 +241,12 @@ root_node = NodePath("../CameraSmooth/Camera3D") libraries = { &"": SubResource("AnimationLibrary_0hyrq") } + +[node name="AnimationTree" type="AnimationTree" parent="."] +root_node = NodePath("../CameraSmooth/Camera3D") +tree_root = ExtResource("3_r0h40") +anim_player = NodePath("../AnimationPlayer") +parameters/AnimationNodeStateMachine/conditions/on_hit = false +parameters/OnHit/active = false +parameters/OnHit/internal_active = false +parameters/OnHit/request = 0