diff --git a/Assets/Sprites/Characters/doc.ase b/Assets/Sprites/Characters/doc.ase
index edb9f18..b470362 100644
Binary files a/Assets/Sprites/Characters/doc.ase and b/Assets/Sprites/Characters/doc.ase differ
diff --git a/Assets/Sprites/Characters/doc.png b/Assets/Sprites/Characters/doc.png
index cd4c281..399ae0b 100644
Binary files a/Assets/Sprites/Characters/doc.png and b/Assets/Sprites/Characters/doc.png differ
diff --git a/Assets/Sprites/Characters/forsen2-portrait.png.import b/Assets/Sprites/Characters/forsen2-portrait.png.import
new file mode 100644
index 0000000..d43f62c
--- /dev/null
+++ b/Assets/Sprites/Characters/forsen2-portrait.png.import
@@ -0,0 +1,34 @@
+[remap]
+
+importer="texture"
+type="CompressedTexture2D"
+uid="uid://bwlk47lcbhlds"
+path="res://.godot/imported/forsen2-portrait.png-ca8f11b7ad39ec3d34d5a24ad210303a.ctex"
+metadata={
+"vram_texture": false
+}
+
+[deps]
+
+source_file="res://Assets/Sprites/Characters/forsen2-portrait.png"
+dest_files=["res://.godot/imported/forsen2-portrait.png-ca8f11b7ad39ec3d34d5a24ad210303a.ctex"]
+
+[params]
+
+compress/mode=0
+compress/high_quality=false
+compress/lossy_quality=0.7
+compress/hdr_compression=1
+compress/normal_map=0
+compress/channel_pack=0
+mipmaps/generate=false
+mipmaps/limit=-1
+roughness/mode=0
+roughness/src_normal=""
+process/fix_alpha_border=true
+process/premult_alpha=false
+process/normal_map_invert_y=false
+process/hdr_as_srgb=false
+process/hdr_clamp_exposure=false
+process/size_limit=0
+detect_3d/compress_to=1
diff --git a/Assets/Sprites/Characters/forsen2.ase b/Assets/Sprites/Characters/forsen2.ase
index 66fe55b..d9282b3 100644
Binary files a/Assets/Sprites/Characters/forsen2.ase and b/Assets/Sprites/Characters/forsen2.ase differ
diff --git a/Assets/Sprites/Characters/forsen2.png b/Assets/Sprites/Characters/forsen2.png
index 6003833..f5602e5 100644
Binary files a/Assets/Sprites/Characters/forsen2.png and b/Assets/Sprites/Characters/forsen2.png differ
diff --git a/Assets/Sprites/Characters/lost-soul.ase b/Assets/Sprites/Characters/lost-soul.ase
new file mode 100644
index 0000000..7666210
Binary files /dev/null and b/Assets/Sprites/Characters/lost-soul.ase differ
diff --git a/Assets/Sprites/Misc/compact-disc.ase b/Assets/Sprites/Misc/compact-disc.ase
new file mode 100644
index 0000000..2b4f5eb
Binary files /dev/null and b/Assets/Sprites/Misc/compact-disc.ase differ
diff --git a/Assets/Sprites/Misc/compact-disc.png b/Assets/Sprites/Misc/compact-disc.png
new file mode 100644
index 0000000..05cfc7f
Binary files /dev/null and b/Assets/Sprites/Misc/compact-disc.png differ
diff --git a/Assets/Sprites/Misc/compact-disc.png.import b/Assets/Sprites/Misc/compact-disc.png.import
new file mode 100644
index 0000000..9c834db
--- /dev/null
+++ b/Assets/Sprites/Misc/compact-disc.png.import
@@ -0,0 +1,34 @@
+[remap]
+
+importer="texture"
+type="CompressedTexture2D"
+uid="uid://qc6agawkad5k"
+path="res://.godot/imported/compact-disc.png-5b17d460d1330809bc650ebf5321160e.ctex"
+metadata={
+"vram_texture": false
+}
+
+[deps]
+
+source_file="res://Assets/Sprites/Misc/compact-disc.png"
+dest_files=["res://.godot/imported/compact-disc.png-5b17d460d1330809bc650ebf5321160e.ctex"]
+
+[params]
+
+compress/mode=0
+compress/high_quality=false
+compress/lossy_quality=0.7
+compress/hdr_compression=1
+compress/normal_map=0
+compress/channel_pack=0
+mipmaps/generate=false
+mipmaps/limit=-1
+roughness/mode=0
+roughness/src_normal=""
+process/fix_alpha_border=true
+process/premult_alpha=false
+process/normal_map_invert_y=false
+process/hdr_as_srgb=false
+process/hdr_clamp_exposure=false
+process/size_limit=0
+detect_3d/compress_to=1
diff --git a/Assets/Sprites/Particles/circle.png b/Assets/Sprites/Particles/circle.png
new file mode 100644
index 0000000..35051c4
Binary files /dev/null and b/Assets/Sprites/Particles/circle.png differ
diff --git a/Assets/Sprites/Particles/circle.png.import b/Assets/Sprites/Particles/circle.png.import
new file mode 100644
index 0000000..e013f1e
--- /dev/null
+++ b/Assets/Sprites/Particles/circle.png.import
@@ -0,0 +1,34 @@
+[remap]
+
+importer="texture"
+type="CompressedTexture2D"
+uid="uid://bd8l8kafb42dt"
+path="res://.godot/imported/circle.png-e947f0f855ee4b3d0717c4cb325e029e.ctex"
+metadata={
+"vram_texture": false
+}
+
+[deps]
+
+source_file="res://Assets/Sprites/Particles/circle.png"
+dest_files=["res://.godot/imported/circle.png-e947f0f855ee4b3d0717c4cb325e029e.ctex"]
+
+[params]
+
+compress/mode=0
+compress/high_quality=false
+compress/lossy_quality=0.7
+compress/hdr_compression=1
+compress/normal_map=0
+compress/channel_pack=0
+mipmaps/generate=false
+mipmaps/limit=-1
+roughness/mode=0
+roughness/src_normal=""
+process/fix_alpha_border=true
+process/premult_alpha=false
+process/normal_map_invert_y=false
+process/hdr_as_srgb=false
+process/hdr_clamp_exposure=false
+process/size_limit=0
+detect_3d/compress_to=1
diff --git a/Assets/Sprites/Particles/player-light.ase b/Assets/Sprites/Particles/player-light.ase
new file mode 100644
index 0000000..4566692
Binary files /dev/null and b/Assets/Sprites/Particles/player-light.ase differ
diff --git a/Assets/Sprites/Particles/player-light.png b/Assets/Sprites/Particles/player-light.png
new file mode 100644
index 0000000..c161968
Binary files /dev/null and b/Assets/Sprites/Particles/player-light.png differ
diff --git a/Assets/Sprites/Particles/player-light.png.import b/Assets/Sprites/Particles/player-light.png.import
new file mode 100644
index 0000000..22671be
--- /dev/null
+++ b/Assets/Sprites/Particles/player-light.png.import
@@ -0,0 +1,34 @@
+[remap]
+
+importer="texture"
+type="CompressedTexture2D"
+uid="uid://d1ukste16yq6v"
+path="res://.godot/imported/player-light.png-261881914c11364b14e2af7628defbb7.ctex"
+metadata={
+"vram_texture": false
+}
+
+[deps]
+
+source_file="res://Assets/Sprites/Particles/player-light.png"
+dest_files=["res://.godot/imported/player-light.png-261881914c11364b14e2af7628defbb7.ctex"]
+
+[params]
+
+compress/mode=0
+compress/high_quality=false
+compress/lossy_quality=0.7
+compress/hdr_compression=1
+compress/normal_map=0
+compress/channel_pack=0
+mipmaps/generate=false
+mipmaps/limit=-1
+roughness/mode=0
+roughness/src_normal=""
+process/fix_alpha_border=true
+process/premult_alpha=false
+process/normal_map_invert_y=false
+process/hdr_as_srgb=false
+process/hdr_clamp_exposure=false
+process/size_limit=0
+detect_3d/compress_to=1
diff --git a/BoundingBoxes/Hurtbox.cs b/BoundingBoxes/Hurtbox.cs
index ca36c51..ad4cb4b 100644
--- a/BoundingBoxes/Hurtbox.cs
+++ b/BoundingBoxes/Hurtbox.cs
@@ -11,8 +11,13 @@ public partial class Hurtbox : BoundingBox, IFaction
float damage,
Character inflictor,
float knockback,
- Vector2 knockbackOrigin = default,
- Vector2 knockbackVector = default);
+ Vector2 knockbackDir = default);
+
+ ///
+ /// The timer to use for invincibility frames
+ ///
+ [Export]
+ public Timer InvincibilityTimer { get; set; }
public override void _Ready()
{
@@ -20,6 +25,15 @@ public partial class Hurtbox : BoundingBox, IFaction
{
Faction = factionEntity.Faction;
}
+
+ if (InvincibilityTimer is not null)
+ {
+ InvincibilityTimer.Timeout += () =>
+ {
+ GD.Print("invincibility off");
+ Monitorable = true;
+ };
+ }
}
public void InflictDamage(
@@ -29,11 +43,42 @@ public partial class Hurtbox : BoundingBox, IFaction
Vector2 knockbackOrigin = default,
Vector2 knockbackVector = default)
{
+ Vector2 knockbackDir = knockbackVector;
+ if (knockbackDir == default)
+ {
+ if (knockbackOrigin == default)
+ {
+ if (inflictor is null)
+ {
+ knockbackOrigin = GlobalPosition + Vector2.Down;
+ }
+ else
+ {
+ knockbackOrigin = inflictor.GlobalPosition;
+ }
+ }
+
+ knockbackDir = knockbackOrigin.DirectionTo(GlobalPosition);
+ }
+
+ if (InvincibilityTimer is not null)
+ {
+ if (!InvincibilityTimer.IsStopped())
+ {
+ return;
+ }
+
+ InvincibilityTimer.Start();
+ //Monitorable = false;
+ SetDeferred("monitorable", false);
+ GD.Print("invincible");
+ }
+
EmitSignal(
SignalName.ReceivedDamage,
damage,
inflictor,
knockback,
- knockbackOrigin, knockbackVector);
+ knockbackDir);
}
}
diff --git a/Characters/Character.cs b/Characters/Character.cs
index e986353..9e6220f 100644
--- a/Characters/Character.cs
+++ b/Characters/Character.cs
@@ -66,7 +66,7 @@ public partial class Character : CharacterBody2D, IFaction
public double StunTime { get; set; }
[Export]
- public AnimatedSprite2D Sprite { get; set; }
+ public Sprite2D Sprite { get; set; }
[Export]
public Inventory Inventory { get; set; }
@@ -80,8 +80,16 @@ public partial class Character : CharacterBody2D, IFaction
[Export]
public ushort Faction { get; set; }
+ public AnimationPlayer MovementAnimation { get; set; }
+
+ public AnimationPlayer HurtAnimation { get; set; }
+
public override void _Ready()
{
+ // TODO: 80+ char line
+ MovementAnimation = GetNode("Animations/Movement");
+ HurtAnimation = GetNode("Animations/Hurt");
+ GD.Print(Name + " " + MovementAnimation.CurrentAnimation);
Hurtbox.ReceivedDamage += OnReceivedDamage;
}
@@ -163,6 +171,10 @@ public partial class Character : CharacterBody2D, IFaction
if (Inventory.SelectedItem is Weapon weapon)
{
weapon.Use();
+ if (weapon.IsUsing)
+ {
+ Inventory.EmitSignal(Inventory.SignalName.UsedItem, weapon);
+ }
}
}
@@ -178,8 +190,7 @@ public partial class Character : CharacterBody2D, IFaction
float damage,
Character inflictor,
float knockback,
- Vector2 knockbackOrigin = default,
- Vector2 knockbackVector = default)
+ Vector2 knockbackDir = default)
{
if (Health <= 0)
{
@@ -197,34 +208,18 @@ public partial class Character : CharacterBody2D, IFaction
this.GetAncestor().AddChild(instance);
// apply knockback
- Vector2 knockbackDir = knockbackVector;
- if (knockbackDir == default)
- {
- if (knockbackOrigin == default)
- {
- if (inflictor is null)
- {
- knockbackOrigin = GlobalPosition + Vector2.Down;
- }
- else
- {
- knockbackOrigin = inflictor.GlobalPosition;
- }
- }
-
- knockbackDir = knockbackOrigin.DirectionTo(GlobalPosition);
- }
ApplyImpulse(knockbackDir.Normalized() * knockback);
GD.Print("lol");
// play damage animation
- var anim = GetNode("FlashAnimation");
+ var anim = GetNode("Animations/Hurt");
if (anim != null)
{
anim.Stop();
- anim.Play("Hurt");
+ anim.Play("hurt");
+ anim.Queue("hurt_flash");
}
// if anyone involved is a player, shake their screen
diff --git a/Characters/Doc.cs b/Characters/Doc.cs
index 67d9a2b..ce75296 100644
--- a/Characters/Doc.cs
+++ b/Characters/Doc.cs
@@ -1,4 +1,5 @@
using Godot;
+using GodotUtilities;
namespace SupaLidlGame.Characters;
@@ -25,7 +26,6 @@ public partial class Doc : Enemy
public override void _Ready()
{
- GD.Print(Health);
base._Ready();
}
@@ -34,4 +34,16 @@ public partial class Doc : Enemy
BossStateMachine.Process(delta);
base._Process(delta);
}
+
+ public override void OnReceivedDamage(
+ float damage,
+ Character inflictor,
+ float knockback,
+ Vector2 knockbackDir = default)
+ {
+ GetNode("Effects/HurtParticles")
+ .SetDirection(knockbackDir);
+
+ base.OnReceivedDamage(damage, inflictor, knockback, knockbackDir);
+ }
}
diff --git a/Characters/Doc.tscn b/Characters/Doc.tscn
index 5593f81..7b1df8f 100644
--- a/Characters/Doc.tscn
+++ b/Characters/Doc.tscn
@@ -1,4 +1,4 @@
-[gd_scene load_steps=38 format=3 uid="uid://d2skjvvx6fal0"]
+[gd_scene load_steps=48 format=3 uid="uid://d2skjvvx6fal0"]
[ext_resource type="Script" path="res://Characters/Doc.cs" id="2_3elet"]
[ext_resource type="Shader" path="res://Shaders/Flash.gdshader" id="2_5jxom"]
@@ -13,12 +13,13 @@
[ext_resource type="Script" path="res://Items/Inventory.cs" id="8_r8ejq"]
[ext_resource type="Script" path="res://State/NPC/Doc/DocExitState.cs" id="9_6com1"]
[ext_resource type="PackedScene" uid="uid://1tiswf3gtyvv" path="res://Entities/ShungiteSpike.tscn" id="9_7kavk"]
-[ext_resource type="PackedScene" uid="uid://djaljmco3xo4g" path="res://Entities/ShungiteDart.tscn" id="9_kthpr"]
[ext_resource type="AudioStream" uid="uid://k6kpdj1kv0jg" path="res://Assets/Sounds/splat.ogg" id="9_stm0e"]
[ext_resource type="Script" path="res://State/NPC/Doc/DocShungiteSpikeState.cs" id="10_bgs6o"]
+[ext_resource type="PackedScene" uid="uid://cqx56u46g2c16" path="res://Entities/CompactDisc.tscn" id="11_23p3o"]
[ext_resource type="Script" path="res://State/NPC/Doc/DocChooseAttackState.cs" id="12_45x13"]
[ext_resource type="Script" path="res://State/NPC/Doc/DocUnwantedFrequencyState.cs" id="12_d51jv"]
[ext_resource type="PackedScene" uid="uid://1y5r6sklwgrp" path="res://Entities/UnwantedFrequency.tscn" id="13_lpj21"]
+[ext_resource type="Texture2D" uid="uid://bd8l8kafb42dt" path="res://Assets/Sprites/Particles/circle.png" id="16_x277j"]
[sub_resource type="ShaderMaterial" id="ShaderMaterial_7n7iy"]
resource_local_to_scene = true
@@ -26,6 +27,101 @@ shader = ExtResource("2_5jxom")
shader_parameter/color = Quaternion(1, 1, 1, 1)
shader_parameter/intensity = 0.0
+[sub_resource type="Animation" id="Animation_7ay6e"]
+length = 0.001
+tracks/0/type = "value"
+tracks/0/imported = false
+tracks/0/enabled = true
+tracks/0/path = NodePath("../Sprite:frame")
+tracks/0/interp = 1
+tracks/0/loop_wrap = true
+tracks/0/keys = {
+"times": PackedFloat32Array(0),
+"transitions": PackedFloat32Array(1),
+"update": 1,
+"values": [0]
+}
+
+[sub_resource type="Animation" id="Animation_px7yx"]
+resource_name = "idle"
+length = 0.5
+loop_mode = 1
+tracks/0/type = "value"
+tracks/0/imported = false
+tracks/0/enabled = true
+tracks/0/path = NodePath("../Sprite:frame")
+tracks/0/interp = 1
+tracks/0/loop_wrap = true
+tracks/0/keys = {
+"times": PackedFloat32Array(0, 0.3),
+"transitions": PackedFloat32Array(1, 1),
+"update": 1,
+"values": [0, 1]
+}
+
+[sub_resource type="Animation" id="Animation_a7sk6"]
+resource_name = "move"
+length = 0.6
+loop_mode = 1
+tracks/0/type = "value"
+tracks/0/imported = false
+tracks/0/enabled = true
+tracks/0/path = NodePath("../Sprite:frame")
+tracks/0/interp = 1
+tracks/0/loop_wrap = true
+tracks/0/keys = {
+"times": PackedFloat32Array(0, 0.1, 0.2, 0.3, 0.4, 0.5),
+"transitions": PackedFloat32Array(1, 1, 1, 1, 1, 1),
+"update": 1,
+"values": [2, 3, 4, 5, 6, 7]
+}
+
+[sub_resource type="AnimationLibrary" id="AnimationLibrary_1xv7m"]
+_data = {
+"RESET": SubResource("Animation_7ay6e"),
+"idle": SubResource("Animation_px7yx"),
+"move": SubResource("Animation_a7sk6")
+}
+
+[sub_resource type="Animation" id="Animation_dbist"]
+length = 0.001
+tracks/0/type = "value"
+tracks/0/imported = false
+tracks/0/enabled = true
+tracks/0/path = NodePath("../Effects/UnwantedFrequenciesParticles:emitting")
+tracks/0/interp = 1
+tracks/0/loop_wrap = true
+tracks/0/keys = {
+"times": PackedFloat32Array(0),
+"transitions": PackedFloat32Array(1),
+"update": 1,
+"values": [false]
+}
+tracks/1/type = "value"
+tracks/1/imported = false
+tracks/1/enabled = true
+tracks/1/path = NodePath("../Sprite:frame")
+tracks/1/interp = 1
+tracks/1/loop_wrap = true
+tracks/1/keys = {
+"times": PackedFloat32Array(0),
+"transitions": PackedFloat32Array(1),
+"update": 1,
+"values": [0]
+}
+tracks/2/type = "value"
+tracks/2/imported = false
+tracks/2/enabled = true
+tracks/2/path = NodePath("../Sprite:scale")
+tracks/2/interp = 1
+tracks/2/loop_wrap = true
+tracks/2/keys = {
+"times": PackedFloat32Array(0),
+"transitions": PackedFloat32Array(1),
+"update": 0,
+"values": [Vector2(1, 1)]
+}
+
[sub_resource type="Animation" id="Animation_7oukw"]
resource_name = "enter_in"
length = 0.5
@@ -82,102 +178,80 @@ tracks/1/keys = {
"values": [Color(1, 1, 1, 0.5), Color(1, 1, 1, 0)]
}
-[sub_resource type="AnimationLibrary" id="AnimationLibrary_rpply"]
-_data = {
-"enter_in": SubResource("Animation_7oukw"),
-"exit_out": SubResource("Animation_j3s0y")
-}
-
-[sub_resource type="AtlasTexture" id="AtlasTexture_dib6t"]
-atlas = ExtResource("3_rs44f")
-region = Rect2(0, 0, 12, 16)
-
-[sub_resource type="AtlasTexture" id="AtlasTexture_cwqre"]
-atlas = ExtResource("3_rs44f")
-region = Rect2(12, 0, 12, 16)
-
-[sub_resource type="AtlasTexture" id="AtlasTexture_r8xjl"]
-atlas = ExtResource("3_rs44f")
-region = Rect2(24, 0, 12, 16)
-
-[sub_resource type="AtlasTexture" id="AtlasTexture_7hkj4"]
-atlas = ExtResource("3_rs44f")
-region = Rect2(36, 0, 12, 16)
-
-[sub_resource type="AtlasTexture" id="AtlasTexture_w04w0"]
-atlas = ExtResource("3_rs44f")
-region = Rect2(48, 0, 12, 16)
-
-[sub_resource type="AtlasTexture" id="AtlasTexture_ym6tg"]
-atlas = ExtResource("3_rs44f")
-region = Rect2(60, 0, 12, 16)
-
-[sub_resource type="AtlasTexture" id="AtlasTexture_3rbas"]
-atlas = ExtResource("3_rs44f")
-region = Rect2(72, 0, 12, 16)
-
-[sub_resource type="AtlasTexture" id="AtlasTexture_63wkp"]
-atlas = ExtResource("3_rs44f")
-region = Rect2(84, 0, 12, 16)
-
-[sub_resource type="SpriteFrames" id="SpriteFrames_kb0pl"]
-resource_local_to_scene = true
-animations = [{
-"frames": [{
-"duration": 1.0,
-"texture": SubResource("AtlasTexture_dib6t")
-}, {
-"duration": 1.0,
-"texture": SubResource("AtlasTexture_cwqre")
-}],
-"loop": true,
-"name": &"idle",
-"speed": 5.0
-}, {
-"frames": [{
-"duration": 1.0,
-"texture": SubResource("AtlasTexture_r8xjl")
-}, {
-"duration": 1.0,
-"texture": SubResource("AtlasTexture_7hkj4")
-}, {
-"duration": 1.0,
-"texture": SubResource("AtlasTexture_w04w0")
-}, {
-"duration": 1.0,
-"texture": SubResource("AtlasTexture_ym6tg")
-}, {
-"duration": 1.0,
-"texture": SubResource("AtlasTexture_3rbas")
-}, {
-"duration": 1.0,
-"texture": SubResource("AtlasTexture_63wkp")
-}],
-"loop": true,
-"name": &"move",
-"speed": 12.0
-}]
-
-[sub_resource type="RectangleShape2D" id="RectangleShape2D_uict5"]
-size = Vector2(16, 8)
-
-[sub_resource type="RectangleShape2D" id="RectangleShape2D_8lxmf"]
-size = Vector2(16, 18)
-
-[sub_resource type="Animation" id="Animation_dxevc"]
-resource_name = "Hurt"
-length = 0.6
+[sub_resource type="Animation" id="Animation_8dhub"]
+resource_name = "shungite_spike"
tracks/0/type = "value"
tracks/0/imported = false
tracks/0/enabled = true
-tracks/0/path = NodePath(".:material:shader_parameter/intensity")
-tracks/0/interp = 2
+tracks/0/path = NodePath("../Sprite:frame")
+tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/keys = {
-"times": PackedFloat32Array(0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6),
-"transitions": PackedFloat32Array(4, 4, 4, 4, 4, 4, 4),
+"times": PackedFloat32Array(0),
+"transitions": PackedFloat32Array(1),
+"update": 1,
+"values": [15]
+}
+tracks/1/type = "value"
+tracks/1/imported = false
+tracks/1/enabled = true
+tracks/1/path = NodePath("../Sprite:scale")
+tracks/1/interp = 1
+tracks/1/loop_wrap = true
+tracks/1/keys = {
+"times": PackedFloat32Array(0, 0.1, 0.2, 0.3),
+"transitions": PackedFloat32Array(2, 5, 5, 5),
"update": 0,
-"values": [0.0, 1.0, 0.0, 1.0, 0.0, 1.0, 0.0]
+"values": [Vector2(1.5, 0.75), Vector2(1, 1), Vector2(0.75, 1.5), Vector2(1, 1)]
+}
+
+[sub_resource type="Animation" id="Animation_qggcf"]
+resource_name = "unwanted_frequencies"
+length = 3.0
+tracks/0/type = "value"
+tracks/0/imported = false
+tracks/0/enabled = true
+tracks/0/path = NodePath("../Effects/UnwantedFrequenciesParticles:emitting")
+tracks/0/interp = 1
+tracks/0/loop_wrap = true
+tracks/0/keys = {
+"times": PackedFloat32Array(0, 3),
+"transitions": PackedFloat32Array(1, 1),
+"update": 1,
+"values": [true, false]
+}
+tracks/1/type = "value"
+tracks/1/imported = false
+tracks/1/enabled = true
+tracks/1/path = NodePath("../Sprite:frame")
+tracks/1/interp = 1
+tracks/1/loop_wrap = true
+tracks/1/keys = {
+"times": PackedFloat32Array(0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1, 1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7, 1.8, 1.9, 2, 2.1, 2.2, 2.3, 2.4, 2.5, 2.6, 2.7, 2.8, 2.9),
+"transitions": PackedFloat32Array(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1),
+"update": 1,
+"values": [8, 9, 10, 11, 12, 13, 14, 8, 9, 10, 11, 12, 13, 14, 8, 9, 10, 11, 12, 13, 14, 9, 10, 11, 12, 13, 14, 8, 9, 10]
+}
+tracks/2/type = "value"
+tracks/2/imported = false
+tracks/2/enabled = true
+tracks/2/path = NodePath("../Sprite:scale")
+tracks/2/interp = 1
+tracks/2/loop_wrap = true
+tracks/2/keys = {
+"times": PackedFloat32Array(0, 0.1),
+"transitions": PackedFloat32Array(1, 1),
+"update": 0,
+"values": [Vector2(1.5, 0.75), Vector2(1, 1)]
+}
+
+[sub_resource type="AnimationLibrary" id="AnimationLibrary_rpply"]
+_data = {
+"RESET": SubResource("Animation_dbist"),
+"enter_in": SubResource("Animation_7oukw"),
+"exit_out": SubResource("Animation_j3s0y"),
+"shungite_spike": SubResource("Animation_8dhub"),
+"unwanted_frequencies": SubResource("Animation_qggcf")
}
[sub_resource type="Animation" id="Animation_k6l16"]
@@ -195,12 +269,94 @@ tracks/0/keys = {
"values": [0.0]
}
+[sub_resource type="Animation" id="Animation_dxevc"]
+resource_name = "hurt"
+length = 0.6
+tracks/0/type = "value"
+tracks/0/imported = false
+tracks/0/enabled = true
+tracks/0/path = NodePath(".:material:shader_parameter/intensity")
+tracks/0/interp = 2
+tracks/0/loop_wrap = true
+tracks/0/keys = {
+"times": PackedFloat32Array(0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6),
+"transitions": PackedFloat32Array(4, 4, 4, 4, 4, 4, 4),
+"update": 0,
+"values": [0.0, 1.0, 0.0, 1.0, 0.0, 1.0, 0.0]
+}
+
[sub_resource type="AnimationLibrary" id="AnimationLibrary_xe5eq"]
_data = {
-"Hurt": SubResource("Animation_dxevc"),
-"RESET": SubResource("Animation_k6l16")
+"RESET": SubResource("Animation_k6l16"),
+"hurt": SubResource("Animation_dxevc")
}
+[sub_resource type="Gradient" id="Gradient_lcoxi"]
+offsets = PackedFloat32Array(0.37037, 0.651852)
+colors = PackedColorArray(0.367549, 0.894801, 1, 1, 0.992095, 0.364069, 1, 1)
+
+[sub_resource type="GradientTexture1D" id="GradientTexture1D_5606i"]
+gradient = SubResource("Gradient_lcoxi")
+
+[sub_resource type="Gradient" id="Gradient_pikjh"]
+offsets = PackedFloat32Array(0.533333, 1)
+colors = PackedColorArray(1, 1, 1, 1, 1, 1, 1, 0)
+
+[sub_resource type="GradientTexture1D" id="GradientTexture1D_pjeh8"]
+gradient = SubResource("Gradient_pikjh")
+
+[sub_resource type="Curve" id="Curve_x3x4q"]
+_data = [Vector2(0, 0.463636), 0.0, 0.0, 0, 0, Vector2(0.325301, 1), 0.0, 0.0, 0, 0, Vector2(1, 0), 0.0, 0.0, 0, 0]
+point_count = 3
+
+[sub_resource type="CurveTexture" id="CurveTexture_ssoms"]
+curve = SubResource("Curve_x3x4q")
+
+[sub_resource type="ParticleProcessMaterial" id="ParticleProcessMaterial_s1tqp"]
+emission_shape = 3
+emission_box_extents = Vector3(8, 1, 1)
+particle_flag_disable_z = true
+direction = Vector3(0, -1, 0)
+spread = 0.0
+gravity = Vector3(0, 0, 0)
+initial_velocity_min = 32.0
+initial_velocity_max = 64.0
+orbit_velocity_min = 0.0
+orbit_velocity_max = 0.0
+scale_max = 1.5
+scale_curve = SubResource("CurveTexture_ssoms")
+color_ramp = SubResource("GradientTexture1D_pjeh8")
+color_initial_ramp = SubResource("GradientTexture1D_5606i")
+
+[sub_resource type="CanvasTexture" id="CanvasTexture_hs7xn"]
+
+[sub_resource type="Curve" id="Curve_jqr7v"]
+_data = [Vector2(0, 0), 0.0, 2.0, 0, 1, Vector2(0.5, 1), 0.0, 0.0, 0, 0, Vector2(1, 0), -2.0, 0.0, 1, 0]
+point_count = 3
+
+[sub_resource type="CurveTexture" id="CurveTexture_s2csc"]
+curve = SubResource("Curve_jqr7v")
+
+[sub_resource type="ParticleProcessMaterial" id="ParticleProcessMaterial_wkgo8"]
+emission_shape = 1
+emission_sphere_radius = 8.0
+particle_flag_disable_z = true
+direction = Vector3(0, -1, 0)
+gravity = Vector3(0, 0, 0)
+initial_velocity_min = 20.0
+initial_velocity_max = 30.0
+orbit_velocity_min = 0.0
+orbit_velocity_max = 0.0
+scale_min = 0.01
+scale_max = 0.01
+scale_curve = SubResource("CurveTexture_s2csc")
+
+[sub_resource type="RectangleShape2D" id="RectangleShape2D_uict5"]
+size = Vector2(16, 8)
+
+[sub_resource type="RectangleShape2D" id="RectangleShape2D_8lxmf"]
+size = Vector2(16, 18)
+
[node name="Doc" type="CharacterBody2D" node_paths=PackedStringArray("BossStateMachine", "Sprite", "Inventory", "StateMachine", "Hurtbox")]
y_sort_enabled = true
texture_filter = 3
@@ -245,14 +401,14 @@ NPC = NodePath("../..")
script = ExtResource("8_1hoax")
Duration = 8.0
AttackDuration = 1.0
-Projectile = ExtResource("9_kthpr")
+Projectile = ExtResource("11_23p3o")
ChooseAttackState = NodePath("../ChooseAttack")
Doc = NodePath("../..")
NPC = NodePath("../..")
[node name="Spike" type="Node" parent="BossStateMachine" node_paths=PackedStringArray("ChooseAttackState", "Doc", "NPC")]
script = ExtResource("10_bgs6o")
-Duration = 8.0
+Duration = 4.0
AttackDuration = 1.0
Projectile = ExtResource("9_7kavk")
ChooseAttackState = NodePath("../ChooseAttack")
@@ -284,19 +440,48 @@ NPC = NodePath("../..")
[node name="Animations" type="Node" parent="."]
+[node name="Movement" type="AnimationPlayer" parent="Animations"]
+libraries = {
+"": SubResource("AnimationLibrary_1xv7m")
+}
+
[node name="Telegraph" type="AnimationPlayer" parent="Animations"]
libraries = {
"": SubResource("AnimationLibrary_rpply")
}
-[node name="Sprite" type="AnimatedSprite2D" parent="."]
-modulate = Color(1, 1, 1, 0.5)
+[node name="Hurt" type="AnimationPlayer" parent="Animations"]
+root_node = NodePath("../..")
+libraries = {
+"": SubResource("AnimationLibrary_xe5eq")
+}
+
+[node name="Effects" type="Node2D" parent="."]
+
+[node name="UnwantedFrequenciesParticles" type="GPUParticles2D" parent="Effects"]
+position = Vector2(0, 8)
+emitting = false
+process_material = SubResource("ParticleProcessMaterial_s1tqp")
+texture = SubResource("CanvasTexture_hs7xn")
+lifetime = 0.5
+trail_enabled = true
+trail_sections = 4
+
+[node name="HurtParticles" type="GPUParticles2D" parent="Effects"]
+emitting = false
+process_material = SubResource("ParticleProcessMaterial_wkgo8")
+texture = ExtResource("16_x277j")
+lifetime = 0.4
+one_shot = true
+explosiveness = 1.0
+
+[node name="Sprite" type="Sprite2D" parent="."]
+modulate = Color(1, 1, 1, 0.08)
use_parent_material = true
position = Vector2(0, -4)
-sprite_frames = SubResource("SpriteFrames_kb0pl")
-animation = &"move"
-frame_progress = 0.563144
+texture = ExtResource("3_rs44f")
offset = Vector2(0, 4)
+hframes = 16
[node name="CollisionShape2D" type="CollisionShape2D" parent="."]
visible = false
@@ -317,11 +502,6 @@ y_sort_enabled = true
script = ExtResource("8_r8ejq")
Items = Array[Node2D]([])
-[node name="FlashAnimation" type="AnimationPlayer" parent="."]
-libraries = {
-"": SubResource("AnimationLibrary_xe5eq")
-}
-
[node name="HurtSound" type="AudioStreamPlayer2D" parent="."]
stream = ExtResource("9_stm0e")
diff --git a/Characters/NPC.cs b/Characters/NPC.cs
index 96ecb65..df1d9ea 100644
--- a/Characters/NPC.cs
+++ b/Characters/NPC.cs
@@ -1,3 +1,5 @@
+#undef DEBUG_NPC
+
using Godot;
using SupaLidlGame.Extensions;
using SupaLidlGame.Items;
@@ -41,6 +43,8 @@ public partial class NPC : Character
}
}
+ public bool ShouldMove { get; set; } = true;
+
protected float[] _weights = new float[16];
protected int _bestWeightIdx;
protected double _thinkTimeElapsed = 0;
@@ -65,7 +69,7 @@ public partial class NPC : Character
public override void _Draw()
{
-#if DEBUG
+#if DEBUG_NPC
for (int i = 0; i < 16; i++)
{
Vector2 vec = _weightDirs[i] * _weights[i] * 32;
@@ -116,12 +120,19 @@ public partial class NPC : Character
{
_thinkTimeElapsed = 0;
Think();
-#if DEBUG
+#if DEBUG_NPC
QueueRedraw();
#endif
}
- Direction = _weightDirs[_bestWeightIdx];
+ if (ShouldMove)
+ {
+ Direction = _weightDirs[_bestWeightIdx];
+ }
+ else
+ {
+ Direction = Vector2.Zero;
+ }
}
public void UpdateWeights(Vector2 pos)
diff --git a/Characters/Player.cs b/Characters/Player.cs
index 04e2171..d920be6 100644
--- a/Characters/Player.cs
+++ b/Characters/Player.cs
@@ -8,7 +8,6 @@ namespace SupaLidlGame.Characters;
[Scene]
public sealed partial class Player : Character
{
- private AnimatedSprite2D _sprite;
private string _spriteAnim;
[Export]
@@ -17,40 +16,32 @@ public sealed partial class Player : Character
[Export]
public Marker2D DirectionMarker { get; private set; }
+ [Export]
+ public AnimationTree AnimationTree { get; private set; }
+
public InteractionRay InteractionRay { get; private set; }
- public string Animation
- {
- get => _sprite.Animation;
- set
- {
- // the Player.Animation property might be set before this node is
- // even ready, so if _sprite is null, then we just hold the new
- // animation in a temp value, which will be assigned once this node
- // is ready
- if (_sprite is null)
- {
- _spriteAnim = value;
- return;
- }
-
- _sprite.Play(value);
- }
- }
+ public AnimationPlayer AttackAnimation { get; set; }
public override void _Ready()
{
InteractionRay = GetNode("Direction2D/InteractionRay");
- _sprite = GetNode("Sprite");
- if (_spriteAnim != default)
- {
- _sprite.Animation = _spriteAnim;
- }
- base._Ready();
Death += (Events.HealthChangedArgs args) =>
{
Visible = false;
};
+
+ AttackAnimation = GetNode("Animations/Attack");
+
+ base._Ready();
+
+ Inventory.UsedItem += (Items.Item item) =>
+ {
+ if (item is Items.Weapons.Sword)
+ {
+ AttackAnimation.Play("sword");
+ }
+ };
}
public override void _Input(InputEvent @event)
@@ -88,19 +79,17 @@ public sealed partial class Player : Character
float damage,
Character inflictor,
float knockback,
- Vector2 knockbackOrigin = default,
- Vector2 knockbackVector = default)
+ Vector2 knockbackDir = default)
{
if (damage >= 10 && IsAlive)
{
Camera.Shake(2, 0.5f);
}
- base.OnReceivedDamage(
- damage,
- inflictor,
- knockback,
- knockbackOrigin,
- knockbackVector);
+
+ GetNode("Effects/HurtParticles")
+ .SetDirection(knockbackDir);
+
+ base.OnReceivedDamage(damage, inflictor, knockback, knockbackDir);
}
public override void Die()
diff --git a/Characters/Player.tscn b/Characters/Player.tscn
index b3a2f7e..5bef0c9 100644
--- a/Characters/Player.tscn
+++ b/Characters/Player.tscn
@@ -1,4 +1,4 @@
-[gd_scene load_steps=39 format=3 uid="uid://b2254pup8k161"]
+[gd_scene load_steps=57 format=3 uid="uid://b2254pup8k161"]
[ext_resource type="Script" path="res://Characters/Player.cs" id="1_flygr"]
[ext_resource type="Shader" path="res://Shaders/Flash.gdshader" id="2_ngsgt"]
@@ -8,111 +8,159 @@
[ext_resource type="Script" path="res://State/Character/PlayerIdleState.cs" id="6_wkfdm"]
[ext_resource type="PackedScene" uid="uid://dvqap2uhcah63" path="res://Items/Weapons/Sword.tscn" id="7_4rxuv"]
[ext_resource type="Script" path="res://State/Character/PlayerMoveState.cs" id="7_dfqd8"]
+[ext_resource type="Script" path="res://Utils/AnimationManager.cs" id="7_sdgvb"]
[ext_resource type="Script" path="res://Items/Inventory.cs" id="7_xyenu"]
[ext_resource type="Script" path="res://State/Character/PlayerRollState.cs" id="8_fy0v5"]
+[ext_resource type="Texture2D" uid="uid://bd8l8kafb42dt" path="res://Assets/Sprites/Particles/circle.png" id="8_ohe3r"]
[ext_resource type="PackedScene" uid="uid://cjgxyhgcyvsv7" path="res://BoundingBoxes/Hurtbox.tscn" id="9_avyu4"]
[ext_resource type="AudioStream" uid="uid://bkeyg8weaqnuu" path="res://Assets/Sounds/splat-player.ogg" id="12_vvem5"]
[ext_resource type="Script" path="res://BoundingBoxes/InteractionRay.cs" id="13_hs3u1"]
-[ext_resource type="Texture2D" uid="uid://coarr28adgo1u" path="res://Assets/Sprites/Particles/point-light.png" id="14_l4ekh"]
+[ext_resource type="Texture2D" uid="uid://d1ukste16yq6v" path="res://Assets/Sprites/Particles/player-light.png" id="15_3hahh"]
[ext_resource type="Script" path="res://Utils/DamageTime.cs" id="15_4xl06"]
[sub_resource type="ShaderMaterial" id="ShaderMaterial_h78y7"]
shader = ExtResource("2_ngsgt")
-shader_parameter/color = Quaternion(1, 1, 1, 1)
+shader_parameter/color = Vector4(1, 1, 1, 1)
shader_parameter/intensity = 0.0
-[sub_resource type="AtlasTexture" id="AtlasTexture_55yt4"]
-atlas = ExtResource("4_5vird")
-region = Rect2(0, 0, 24, 24)
-
-[sub_resource type="AtlasTexture" id="AtlasTexture_xa1bi"]
-atlas = ExtResource("4_5vird")
-region = Rect2(24, 0, 24, 24)
-
-[sub_resource type="AtlasTexture" id="AtlasTexture_hiodl"]
-atlas = ExtResource("4_5vird")
-region = Rect2(48, 0, 24, 24)
-
-[sub_resource type="AtlasTexture" id="AtlasTexture_tok7d"]
-atlas = ExtResource("4_5vird")
-region = Rect2(72, 0, 24, 24)
-
-[sub_resource type="AtlasTexture" id="AtlasTexture_dp8x6"]
-atlas = ExtResource("4_5vird")
-region = Rect2(96, 0, 24, 24)
-
-[sub_resource type="AtlasTexture" id="AtlasTexture_sglor"]
-atlas = ExtResource("4_5vird")
-region = Rect2(120, 0, 24, 24)
-
-[sub_resource type="AtlasTexture" id="AtlasTexture_gb41o"]
-atlas = ExtResource("4_5vird")
-region = Rect2(144, 0, 24, 24)
-
-[sub_resource type="AtlasTexture" id="AtlasTexture_bx6qq"]
-atlas = ExtResource("4_5vird")
-region = Rect2(168, 0, 24, 24)
-
-[sub_resource type="SpriteFrames" id="SpriteFrames_2h7cf"]
-animations = [{
-"frames": [{
-"duration": 1.0,
-"texture": SubResource("AtlasTexture_55yt4")
-}, {
-"duration": 1.0,
-"texture": SubResource("AtlasTexture_xa1bi")
-}],
-"loop": true,
-"name": &"idle",
-"speed": 2.0
-}, {
-"frames": [{
-"duration": 1.0,
-"texture": SubResource("AtlasTexture_hiodl")
-}, {
-"duration": 1.0,
-"texture": SubResource("AtlasTexture_tok7d")
-}, {
-"duration": 1.0,
-"texture": SubResource("AtlasTexture_dp8x6")
-}, {
-"duration": 1.0,
-"texture": SubResource("AtlasTexture_sglor")
-}, {
-"duration": 1.0,
-"texture": SubResource("AtlasTexture_gb41o")
-}, {
-"duration": 1.0,
-"texture": SubResource("AtlasTexture_bx6qq")
-}],
-"loop": true,
-"name": &"move",
-"speed": 10.0
-}]
-
-[sub_resource type="RectangleShape2D" id="RectangleShape2D_bfqew"]
-size = Vector2(12, 8)
-
-[sub_resource type="LabelSettings" id="LabelSettings_q5h1n"]
-font_size = 24
-
-[sub_resource type="RectangleShape2D" id="RectangleShape2D_cjk6b"]
-size = Vector2(8, 8)
-
-[sub_resource type="Animation" id="Animation_dxevc"]
-resource_name = "Hurt"
-length = 0.6
+[sub_resource type="Animation" id="Animation_imqdv"]
+length = 0.001
tracks/0/type = "value"
tracks/0/imported = false
tracks/0/enabled = true
-tracks/0/path = NodePath(".:material:shader_parameter/intensity")
-tracks/0/interp = 2
+tracks/0/path = NodePath("../Sprites/Character:frame")
+tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/keys = {
-"times": PackedFloat32Array(0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6),
-"transitions": PackedFloat32Array(4, 4, 4, 4, 4, 4, 4),
+"times": PackedFloat32Array(0),
+"transitions": PackedFloat32Array(1),
+"update": 1,
+"values": [0]
+}
+tracks/1/type = "value"
+tracks/1/imported = false
+tracks/1/enabled = true
+tracks/1/path = NodePath("../Sprites/Character:rotation")
+tracks/1/interp = 1
+tracks/1/loop_wrap = true
+tracks/1/keys = {
+"times": PackedFloat32Array(0),
+"transitions": PackedFloat32Array(1),
"update": 0,
-"values": [0.0, 1.0, 0.0, 1.0, 0.0, 1.0, 0.0]
+"values": [0.0]
+}
+
+[sub_resource type="Animation" id="Animation_mg66i"]
+resource_name = "idle"
+length = 0.5
+loop_mode = 1
+tracks/0/type = "value"
+tracks/0/imported = false
+tracks/0/enabled = true
+tracks/0/path = NodePath("../Sprites/Character:frame")
+tracks/0/interp = 1
+tracks/0/loop_wrap = true
+tracks/0/keys = {
+"times": PackedFloat32Array(0, 0.3),
+"transitions": PackedFloat32Array(1, 1),
+"update": 1,
+"values": [0, 1]
+}
+
+[sub_resource type="Animation" id="Animation_iyr4r"]
+resource_name = "move"
+length = 0.6
+loop_mode = 1
+tracks/0/type = "value"
+tracks/0/imported = false
+tracks/0/enabled = true
+tracks/0/path = NodePath("../Sprites/Character:frame")
+tracks/0/interp = 1
+tracks/0/loop_wrap = true
+tracks/0/keys = {
+"times": PackedFloat32Array(0, 0.1, 0.2, 0.3, 0.4, 0.5),
+"transitions": PackedFloat32Array(1, 1, 1, 1, 1, 1),
+"update": 1,
+"values": [2, 3, 4, 5, 6, 7]
+}
+
+[sub_resource type="Animation" id="Animation_vobpw"]
+resource_name = "roll"
+length = 0.5
+step = 0.05
+tracks/0/type = "value"
+tracks/0/imported = false
+tracks/0/enabled = true
+tracks/0/path = NodePath("../Sprites/Character:rotation")
+tracks/0/interp = 1
+tracks/0/loop_wrap = true
+tracks/0/keys = {
+"times": PackedFloat32Array(0, 0.5),
+"transitions": PackedFloat32Array(1, 1),
+"update": 0,
+"values": [0.0, 6.28319]
+}
+
+[sub_resource type="Animation" id="Animation_tpnyg"]
+resource_name = "stop"
+length = 0.2
+tracks/0/type = "value"
+tracks/0/imported = false
+tracks/0/enabled = true
+tracks/0/path = NodePath("../Sprites/Character:frame")
+tracks/0/interp = 1
+tracks/0/loop_wrap = true
+tracks/0/keys = {
+"times": PackedFloat32Array(0, 0.2),
+"transitions": PackedFloat32Array(1, 1),
+"update": 1,
+"values": [10, 0]
+}
+
+[sub_resource type="AnimationLibrary" id="AnimationLibrary_0tohi"]
+_data = {
+"RESET": SubResource("Animation_imqdv"),
+"idle": SubResource("Animation_mg66i"),
+"move": SubResource("Animation_iyr4r"),
+"roll": SubResource("Animation_vobpw"),
+"stop": SubResource("Animation_tpnyg")
+}
+
+[sub_resource type="Animation" id="Animation_adxyh"]
+length = 0.001
+tracks/0/type = "value"
+tracks/0/imported = false
+tracks/0/enabled = true
+tracks/0/path = NodePath("../Sprites/Character:frame")
+tracks/0/interp = 1
+tracks/0/loop_wrap = true
+tracks/0/keys = {
+"times": PackedFloat32Array(0),
+"transitions": PackedFloat32Array(1),
+"update": 1,
+"values": [12]
+}
+
+[sub_resource type="Animation" id="Animation_3w3u1"]
+resource_name = "sword"
+length = 0.2
+tracks/0/type = "value"
+tracks/0/imported = false
+tracks/0/enabled = true
+tracks/0/path = NodePath("../Sprites/Character:frame")
+tracks/0/interp = 1
+tracks/0/loop_wrap = true
+tracks/0/keys = {
+"times": PackedFloat32Array(0, 0.1, 0.2),
+"transitions": PackedFloat32Array(1, 1, 1),
+"update": 1,
+"values": [12, 13, 0]
+}
+
+[sub_resource type="AnimationLibrary" id="AnimationLibrary_73mj7"]
+_data = {
+"RESET": SubResource("Animation_adxyh"),
+"sword": SubResource("Animation_3w3u1")
}
[sub_resource type="Animation" id="Animation_k6l16"]
@@ -129,87 +177,214 @@ tracks/0/keys = {
"update": 0,
"values": [0.0]
}
-
-[sub_resource type="AnimationLibrary" id="AnimationLibrary_xe5eq"]
-_data = {
-"Hurt": SubResource("Animation_dxevc"),
-"RESET": SubResource("Animation_k6l16")
-}
-
-[sub_resource type="Animation" id="Animation_yejx2"]
-length = 0.001
-tracks/0/type = "value"
-tracks/0/imported = false
-tracks/0/enabled = true
-tracks/0/path = NodePath("Sprite:rotation")
-tracks/0/interp = 1
-tracks/0/loop_wrap = true
-tracks/0/keys = {
+tracks/1/type = "value"
+tracks/1/imported = false
+tracks/1/enabled = true
+tracks/1/path = NodePath("Sprites/Character:frame")
+tracks/1/interp = 1
+tracks/1/loop_wrap = true
+tracks/1/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
-"update": 0,
-"values": [0.0]
+"update": 1,
+"values": [0]
+}
+tracks/2/type = "value"
+tracks/2/imported = false
+tracks/2/enabled = true
+tracks/2/path = NodePath("Effects/HurtParticles:emitting")
+tracks/2/interp = 1
+tracks/2/loop_wrap = true
+tracks/2/keys = {
+"times": PackedFloat32Array(0),
+"transitions": PackedFloat32Array(1),
+"update": 1,
+"values": [false]
}
-[sub_resource type="Animation" id="Animation_rx2pj"]
-resource_name = "roll"
-length = 0.5
+[sub_resource type="Animation" id="Animation_dxevc"]
+resource_name = "hurt"
+length = 0.2
step = 0.05
tracks/0/type = "value"
tracks/0/imported = false
tracks/0/enabled = true
-tracks/0/path = NodePath("Sprite:rotation")
-tracks/0/interp = 1
+tracks/0/path = NodePath(".:material:shader_parameter/intensity")
+tracks/0/interp = 2
tracks/0/loop_wrap = true
tracks/0/keys = {
-"times": PackedFloat32Array(0, 0.25, 0.5),
-"transitions": PackedFloat32Array(1, 1, 1),
+"times": PackedFloat32Array(0, 0.05, 0.1, 0.2),
+"transitions": PackedFloat32Array(4, 4, 4, 4),
"update": 0,
-"values": [0.0, 3.14159, 6.28319]
+"values": [1.0, 0.0, 1.0, 0.0]
+}
+tracks/1/type = "value"
+tracks/1/imported = false
+tracks/1/enabled = true
+tracks/1/path = NodePath("Sprites/Character:frame")
+tracks/1/interp = 1
+tracks/1/loop_wrap = true
+tracks/1/keys = {
+"times": PackedFloat32Array(0),
+"transitions": PackedFloat32Array(1),
+"update": 1,
+"values": [11]
+}
+tracks/2/type = "value"
+tracks/2/imported = false
+tracks/2/enabled = true
+tracks/2/path = NodePath("Effects/HurtParticles:emitting")
+tracks/2/interp = 1
+tracks/2/loop_wrap = true
+tracks/2/keys = {
+"times": PackedFloat32Array(0, 0.1),
+"transitions": PackedFloat32Array(1, 1),
+"update": 1,
+"values": [true, false]
}
-[sub_resource type="AnimationLibrary" id="AnimationLibrary_jai06"]
-_data = {
-"RESET": SubResource("Animation_yejx2"),
-"roll": SubResource("Animation_rx2pj")
+[sub_resource type="Animation" id="Animation_pjey7"]
+resource_name = "hurt_flash"
+length = 0.4
+step = 0.05
+tracks/0/type = "value"
+tracks/0/imported = false
+tracks/0/enabled = true
+tracks/0/path = NodePath(".:material:shader_parameter/intensity")
+tracks/0/interp = 2
+tracks/0/loop_wrap = true
+tracks/0/keys = {
+"times": PackedFloat32Array(0, 0.2, 0.4),
+"transitions": PackedFloat32Array(4, 4, 4),
+"update": 0,
+"values": [0.0, 1.0, 0.0]
}
+[sub_resource type="AnimationLibrary" id="AnimationLibrary_xe5eq"]
+_data = {
+"RESET": SubResource("Animation_k6l16"),
+"hurt": SubResource("Animation_dxevc"),
+"hurt_flash": SubResource("Animation_pjey7")
+}
+
+[sub_resource type="AnimationNodeAnimation" id="AnimationNodeAnimation_kwett"]
+animation = &"idle"
+
+[sub_resource type="AnimationNodeAnimation" id="AnimationNodeAnimation_vqdng"]
+animation = &"move"
+
+[sub_resource type="AnimationNodeAnimation" id="AnimationNodeAnimation_4np0m"]
+animation = &"roll"
+
+[sub_resource type="AnimationNodeAnimation" id="AnimationNodeAnimation_suhx1"]
+animation = &"stop"
+
+[sub_resource type="AnimationNodeStateMachineTransition" id="AnimationNodeStateMachineTransition_sorqc"]
+advance_mode = 2
+
+[sub_resource type="AnimationNodeStateMachineTransition" id="AnimationNodeStateMachineTransition_ujrp0"]
+advance_condition = &"move"
+
+[sub_resource type="AnimationNodeStateMachineTransition" id="AnimationNodeStateMachineTransition_kjkm8"]
+advance_condition = &"idle"
+
+[sub_resource type="AnimationNodeStateMachineTransition" id="AnimationNodeStateMachineTransition_1ywlq"]
+switch_mode = 2
+advance_mode = 2
+advance_condition = &"idle"
+
+[sub_resource type="AnimationNodeStateMachineTransition" id="AnimationNodeStateMachineTransition_abs7t"]
+advance_condition = &"roll"
+
+[sub_resource type="AnimationNodeStateMachineTransition" id="AnimationNodeStateMachineTransition_qlka8"]
+advance_condition = &"idle"
+
+[sub_resource type="AnimationNodeStateMachineTransition" id="AnimationNodeStateMachineTransition_ql2f3"]
+advance_condition = &"move"
+
+[sub_resource type="AnimationNodeStateMachineTransition" id="AnimationNodeStateMachineTransition_g1yba"]
+advance_condition = &"roll"
+
+[sub_resource type="AnimationNodeStateMachine" id="AnimationNodeStateMachine_0ukul"]
+states/End/position = Vector2(613, 100)
+states/Start/position = Vector2(89, 100)
+states/idle/node = SubResource("AnimationNodeAnimation_kwett")
+states/idle/position = Vector2(259, 100)
+states/move/node = SubResource("AnimationNodeAnimation_vqdng")
+states/move/position = Vector2(259, 18)
+states/roll/node = SubResource("AnimationNodeAnimation_4np0m")
+states/roll/position = Vector2(89, 18)
+states/stop/node = SubResource("AnimationNodeAnimation_suhx1")
+states/stop/position = Vector2(438, 100)
+transitions = ["Start", "idle", SubResource("AnimationNodeStateMachineTransition_sorqc"), "idle", "move", SubResource("AnimationNodeStateMachineTransition_ujrp0"), "move", "stop", SubResource("AnimationNodeStateMachineTransition_kjkm8"), "stop", "idle", SubResource("AnimationNodeStateMachineTransition_1ywlq"), "idle", "roll", SubResource("AnimationNodeStateMachineTransition_abs7t"), "roll", "idle", SubResource("AnimationNodeStateMachineTransition_qlka8"), "roll", "move", SubResource("AnimationNodeStateMachineTransition_ql2f3"), "move", "roll", SubResource("AnimationNodeStateMachineTransition_g1yba")]
+graph_offset = Vector2(-335.315, -63.5708)
+
+[sub_resource type="AnimationNodeStateMachinePlayback" id="AnimationNodeStateMachinePlayback_jln87"]
+
+[sub_resource type="Gradient" id="Gradient_6k7fi"]
+offsets = PackedFloat32Array(0, 0.540741, 0.592593, 1)
+colors = PackedColorArray(0, 0, 0, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1)
+
+[sub_resource type="GradientTexture1D" id="GradientTexture1D_1phkb"]
+gradient = SubResource("Gradient_6k7fi")
+
[sub_resource type="Gradient" id="Gradient_3tax5"]
-offsets = PackedFloat32Array(0.533333, 1)
-colors = PackedColorArray(1, 1, 1, 1, 1, 1, 1, 0)
+offsets = PackedFloat32Array(0, 0.533333, 1)
+colors = PackedColorArray(1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0)
-[sub_resource type="GradientTexture1D" id="GradientTexture1D_pjeh8"]
+[sub_resource type="GradientTexture1D" id="GradientTexture1D_13jjx"]
gradient = SubResource("Gradient_3tax5")
+[sub_resource type="Curve" id="Curve_0565g"]
+_data = [Vector2(0, 0.5), 0.0, 5.0, 0, 1, Vector2(0.1, 1), 0.0, 0.0, 0, 0, Vector2(1, 0), -1.11111, 0.0, 1, 0]
+point_count = 3
+
+[sub_resource type="CurveTexture" id="CurveTexture_k4txv"]
+curve = SubResource("Curve_0565g")
+
[sub_resource type="ParticleProcessMaterial" id="ParticleProcessMaterial_humq0"]
-emission_shape = 1
-emission_sphere_radius = 1.0
+emission_shape = 2
+emission_sphere_radius = 32.0
particle_flag_disable_z = true
-direction = Vector3(0, 0, 0)
-spread = 180.0
+direction = Vector3(0, -1, 0)
gravity = Vector3(0, 0, 0)
-initial_velocity_min = 32.0
-initial_velocity_max = 32.0
+initial_velocity_min = 128.0
+initial_velocity_max = 256.0
orbit_velocity_min = 0.0
-orbit_velocity_max = 0.1
-tangential_accel_min = 64.0
-tangential_accel_max = 64.0
-color_ramp = SubResource("GradientTexture1D_pjeh8")
+orbit_velocity_max = 0.0
+tangential_accel_min = -8.0
+tangential_accel_max = -4.0
+scale_min = 0.01
+scale_max = 0.01
+scale_curve = SubResource("CurveTexture_k4txv")
+color_ramp = SubResource("GradientTexture1D_13jjx")
+color_initial_ramp = SubResource("GradientTexture1D_1phkb")
+turbulence_enabled = true
+turbulence_noise_scale = 4.0
[sub_resource type="CanvasTexture" id="CanvasTexture_pited"]
+[sub_resource type="RectangleShape2D" id="RectangleShape2D_bfqew"]
+size = Vector2(12, 8)
+
+[sub_resource type="LabelSettings" id="LabelSettings_q5h1n"]
+font_size = 24
+
+[sub_resource type="RectangleShape2D" id="RectangleShape2D_cjk6b"]
+size = Vector2(8, 8)
+
[node name="Player" type="CharacterBody2D" node_paths=PackedStringArray("Camera", "DirectionMarker", "Sprite", "Inventory", "StateMachine", "Hurtbox")]
y_sort_enabled = true
texture_filter = 3
material = SubResource("ShaderMaterial_h78y7")
-position = Vector2(1, -12)
+position = Vector2(0, -8)
collision_layer = 6
collision_mask = 17
script = ExtResource("1_flygr")
Camera = NodePath("Camera2D")
DirectionMarker = NodePath("Direction2D")
-Speed = 64.0
-Sprite = NodePath("Sprite")
+Speed = 80.0
+Sprite = NodePath("Sprites/Character")
Inventory = NodePath("Inventory")
StateMachine = NodePath("StateMachine")
Hurtbox = NodePath("Hurtbox")
@@ -237,18 +412,70 @@ script = ExtResource("8_fy0v5")
IdleState = NodePath("../Idle")
Character = NodePath("../..")
+[node name="Animations" type="Node" parent="."]
+script = ExtResource("7_sdgvb")
+
+[node name="Movement" type="AnimationPlayer" parent="Animations"]
+libraries = {
+"": SubResource("AnimationLibrary_0tohi")
+}
+
+[node name="Attack" type="AnimationPlayer" parent="Animations"]
+libraries = {
+"": SubResource("AnimationLibrary_73mj7")
+}
+
+[node name="Hurt" type="AnimationPlayer" parent="Animations"]
+root_node = NodePath("../..")
+libraries = {
+"": SubResource("AnimationLibrary_xe5eq")
+}
+
+[node name="AnimationTree" type="AnimationTree" parent="Animations"]
+tree_root = SubResource("AnimationNodeStateMachine_0ukul")
+anim_player = NodePath("../Movement")
+parameters/playback = SubResource("AnimationNodeStateMachinePlayback_jln87")
+parameters/conditions/idle = false
+parameters/conditions/move = false
+parameters/conditions/roll = false
+
+[node name="Effects" type="Node2D" parent="."]
+
+[node name="DeathParticles" type="GPUParticles2D" parent="Effects"]
+emitting = false
+amount = 16
+process_material = SubResource("ParticleProcessMaterial_humq0")
+texture = SubResource("CanvasTexture_pited")
+one_shot = true
+explosiveness = 0.9
+
+[node name="HurtParticles" type="GPUParticles2D" parent="Effects"]
+emitting = false
+amount = 32
+process_material = SubResource("ParticleProcessMaterial_humq0")
+texture = ExtResource("8_ohe3r")
+one_shot = true
+explosiveness = 1.0
+
[node name="Camera2D" parent="." instance=ExtResource("4_ym125")]
+limit_left = -256
+limit_top = -256
+limit_right = 256
+limit_bottom = 256
position_smoothing_speed = 8.0
-[node name="Sprite" type="AnimatedSprite2D" parent="."]
+[node name="Sprites" type="Node2D" parent="."]
use_parent_material = true
-position = Vector2(0, 4)
-sprite_frames = SubResource("SpriteFrames_2h7cf")
-animation = &"idle"
+
+[node name="Character" type="Sprite2D" parent="Sprites"]
+y_sort_enabled = true
+use_parent_material = true
+texture = ExtResource("4_5vird")
offset = Vector2(0, -4)
+hframes = 23
[node name="CollisionShape2D" type="CollisionShape2D" parent="."]
-position = Vector2(0, 8)
+position = Vector2(0, 4)
shape = SubResource("RectangleShape2D_bfqew")
[node name="Debug" type="Control" parent="."]
@@ -266,10 +493,7 @@ text = "lol"
label_settings = SubResource("LabelSettings_q5h1n")
horizontal_alignment = 1
-[node name="Node" type="Node" parent="."]
-
[node name="Inventory" type="Node2D" parent="."]
-position = Vector2(0, 4)
script = ExtResource("7_xyenu")
InventoryMap = {
"equip_1": 0,
@@ -278,24 +502,17 @@ InventoryMap = {
[node name="Node2D" parent="Inventory" instance=ExtResource("7_4rxuv")]
visible = false
-ShouldHideIdle = false
-[node name="Hurtbox" parent="." instance=ExtResource("9_avyu4")]
+[node name="Hurtbox" parent="." node_paths=PackedStringArray("InvincibilityTimer") instance=ExtResource("9_avyu4")]
+InvincibilityTimer = NodePath("Timer")
Faction = 1
[node name="CollisionShape2D" parent="Hurtbox" index="0"]
-position = Vector2(0, 6)
+position = Vector2(0, 4)
shape = SubResource("RectangleShape2D_cjk6b")
-[node name="FlashAnimation" type="AnimationPlayer" parent="."]
-libraries = {
-"": SubResource("AnimationLibrary_xe5eq")
-}
-
-[node name="RollAnimation" type="AnimationPlayer" parent="."]
-libraries = {
-"": SubResource("AnimationLibrary_jai06")
-}
+[node name="Timer" type="Timer" parent="Hurtbox"]
+one_shot = true
[node name="HurtSound" type="AudioStreamPlayer2D" parent="."]
stream = ExtResource("12_vvem5")
@@ -313,21 +530,13 @@ collision_mask = 64
collide_with_areas = true
script = ExtResource("13_hs3u1")
-[node name="DeathParticles" type="GPUParticles2D" parent="."]
-emitting = false
-amount = 16
-process_material = SubResource("ParticleProcessMaterial_humq0")
-texture = SubResource("CanvasTexture_pited")
-one_shot = true
-explosiveness = 0.9
-
[node name="PointLight2D" type="PointLight2D" parent="."]
blend_mode = 2
shadow_enabled = true
shadow_filter = 2
shadow_filter_smooth = 3.0
-texture = ExtResource("14_l4ekh")
-texture_scale = 0.5
+texture = ExtResource("15_3hahh")
+height = 10.0
[node name="DamageTime" type="Node" parent="."]
script = ExtResource("15_4xl06")
diff --git a/Entities/CompactDisc.tscn b/Entities/CompactDisc.tscn
new file mode 100644
index 0000000..192ee99
--- /dev/null
+++ b/Entities/CompactDisc.tscn
@@ -0,0 +1,41 @@
+[gd_scene load_steps=7 format=3 uid="uid://cqx56u46g2c16"]
+
+[ext_resource type="PackedScene" uid="uid://djaljmco3xo4g" path="res://Entities/ShungiteDart.tscn" id="1_md2qh"]
+[ext_resource type="Texture2D" uid="uid://qc6agawkad5k" path="res://Assets/Sprites/Misc/compact-disc.png" id="3_8r6gc"]
+
+[sub_resource type="AtlasTexture" id="AtlasTexture_wvy7p"]
+atlas = ExtResource("3_8r6gc")
+region = Rect2(0, 0, 12, 12)
+
+[sub_resource type="AtlasTexture" id="AtlasTexture_0ibsw"]
+atlas = ExtResource("3_8r6gc")
+region = Rect2(12, 0, 12, 12)
+
+[sub_resource type="SpriteFrames" id="SpriteFrames_80dw6"]
+animations = [{
+"frames": [{
+"duration": 1.0,
+"texture": SubResource("AtlasTexture_wvy7p")
+}, {
+"duration": 1.0,
+"texture": SubResource("AtlasTexture_0ibsw")
+}],
+"loop": true,
+"name": &"default",
+"speed": 5.0
+}]
+
+[sub_resource type="CircleShape2D" id="CircleShape2D_v6kob"]
+radius = 4.0
+
+[node name="ShungiteDart" instance=ExtResource("1_md2qh")]
+
+[node name="Sprite2D" parent="." index="0"]
+sprite_frames = SubResource("SpriteFrames_80dw6")
+frame_progress = 0.70222
+speed_scale = 2.0
+
+[node name="CollisionShape2D" parent="Hitbox" index="0"]
+shape = SubResource("CircleShape2D_v6kob")
+
+[editable path="Hitbox"]
diff --git a/Entities/Projectile.cs b/Entities/Projectile.cs
index 31718a9..b617181 100644
--- a/Entities/Projectile.cs
+++ b/Entities/Projectile.cs
@@ -6,7 +6,15 @@ namespace SupaLidlGame.Entities;
public partial class Projectile : RigidBody2D
{
- public Vector2 Velocity => Direction * Speed;
+ //public virtual Vector2 Velocity => Direction * Speed;
+ public virtual Vector2 Velocity
+ {
+ get => Direction * Speed;
+ set
+ {
+ throw new System.NotImplementedException();
+ }
+ }
[Export]
public string ProjectileName { get; set; }
@@ -14,6 +22,12 @@ public partial class Projectile : RigidBody2D
[Export]
public float Speed { get; set; }
+ [Export]
+ public Vector2 AccelerationDirection { get; set; }
+
+ [Export]
+ public float AccelerationMagnitude { get; set; }
+
[Export]
public Vector2 Direction { get; set; }
diff --git a/Entities/ShungiteSpike.cs b/Entities/ShungiteSpike.cs
index c88eb64..26fc2a2 100644
--- a/Entities/ShungiteSpike.cs
+++ b/Entities/ShungiteSpike.cs
@@ -63,8 +63,7 @@ public partial class ShungiteSpike : Projectile
float damage,
Characters.Character inflictor,
float knockback,
- Vector2 knockbackOrigin = default,
- Vector2 knockbackVector = default)
+ Vector2 knockbackDir)
{
// if we were hit by the player before the spike freezes,
// spawn a dart towards where the player is aiming
diff --git a/Entities/Torch.tscn b/Entities/Torch.tscn
index 3d13af6..6aee75c 100644
--- a/Entities/Torch.tscn
+++ b/Entities/Torch.tscn
@@ -57,7 +57,7 @@ animations = [{
}],
"loop": true,
"name": &"default",
-"speed": 5.0
+"speed": 10.0
}]
[node name="Torch" type="Node2D"]
@@ -67,8 +67,7 @@ texture_filter = 1
position = Vector2(0, -12)
sprite_frames = SubResource("SpriteFrames_gf7ku")
autoplay = "default"
-frame = 5
-frame_progress = 0.743234
+frame_progress = 0.337799
[node name="PointLight2D" type="PointLight2D" parent="."]
color = Color(1, 0.898039, 0.686275, 1)
diff --git a/Entities/TorchLamp.tscn b/Entities/TorchLamp.tscn
index ba5c3fa..5aa4f34 100644
--- a/Entities/TorchLamp.tscn
+++ b/Entities/TorchLamp.tscn
@@ -98,12 +98,13 @@ animations = [{
[node name="TorchLamp" type="Node2D"]
[node name="AnimatedSprite2D" type="AnimatedSprite2D" parent="."]
+y_sort_enabled = true
texture_filter = 1
-position = Vector2(0, -12)
sprite_frames = SubResource("SpriteFrames_gf7ku")
autoplay = "default"
frame = 6
frame_progress = 0.743234
+offset = Vector2(0, -12)
[node name="PointLight2D" type="PointLight2D" parent="."]
color = Color(1, 0.827451, 0.619608, 1)
diff --git a/Entities/UnwantedFrequency.cs b/Entities/UnwantedFrequency.cs
index e2c9932..5a1f8a4 100644
--- a/Entities/UnwantedFrequency.cs
+++ b/Entities/UnwantedFrequency.cs
@@ -15,6 +15,7 @@ public partial class UnwantedFrequency : Projectile
public Node2D TrailRotation { get; set; }
public Node2D TrailPosition { get; set; }
public GpuParticles2D DeathParticles { get; set; }
+ public GpuParticles2D SpawnParticles { get; set; }
public Timer DeferDeathTimer { get; set; }
private double _currentLifetime = 0;
@@ -26,6 +27,8 @@ public partial class UnwantedFrequency : Projectile
Trail = TrailPosition.GetNode("Trail");
DeferDeathTimer = GetNode("DeferDeath");
DeathParticles = GetNode("DeathParticles");
+ SpawnParticles = GetNode("SpawnParticles");
+ SpawnParticles.Emitting = true;
Hitbox.Hit += (BoundingBoxes.BoundingBox box) =>
{
if (box is BoundingBoxes.Hurtbox && box.Faction != Hitbox.Faction)
@@ -62,7 +65,8 @@ public partial class UnwantedFrequency : Projectile
public override void Die()
{
- IsDead = Trail.IsDead = Hitbox.IsDisabled = true;
+ IsDead = Trail.IsDead = true;
+ Hitbox.SetDeferred("monitoring", false);
DeferDeathTimer.Timeout += () =>
{
QueueFree();
diff --git a/Entities/UnwantedFrequency.tscn b/Entities/UnwantedFrequency.tscn
index 8087070..43c12da 100644
--- a/Entities/UnwantedFrequency.tscn
+++ b/Entities/UnwantedFrequency.tscn
@@ -1,9 +1,10 @@
-[gd_scene load_steps=14 format=3 uid="uid://1y5r6sklwgrp"]
+[gd_scene load_steps=20 format=3 uid="uid://1y5r6sklwgrp"]
[ext_resource type="Script" path="res://Entities/UnwantedFrequency.cs" id="1_6sbe0"]
[ext_resource type="PackedScene" uid="uid://du5vhccg75nrq" path="res://BoundingBoxes/Hitbox.tscn" id="2_gxtvd"]
[ext_resource type="PackedScene" uid="uid://cojxmcin13ihm" path="res://Utils/Trail.tscn" id="3_67uhs"]
[ext_resource type="AudioStream" uid="uid://cn2wop7rfxku8" path="res://Assets/Sounds/karabast.mp3" id="4_pbgsi"]
+[ext_resource type="Texture2D" uid="uid://d1ukste16yq6v" path="res://Assets/Sprites/Particles/player-light.png" id="5_d8kx8"]
[sub_resource type="RectangleShape2D" id="RectangleShape2D_30y8q"]
size = Vector2(8, 8)
@@ -34,6 +35,36 @@ orbit_velocity_min = 0.0
orbit_velocity_max = 2.0
color_ramp = SubResource("GradientTexture1D_yfhnr")
+[sub_resource type="Gradient" id="Gradient_5hy7c"]
+colors = PackedColorArray(1, 1, 1, 1, 1, 1, 1, 0)
+
+[sub_resource type="GradientTexture1D" id="GradientTexture1D_iyaih"]
+gradient = SubResource("Gradient_5hy7c")
+
+[sub_resource type="Curve" id="Curve_wt1cb"]
+_data = [Vector2(0, 0), 0.0, 0.0, 0, 0, Vector2(0.2, 1), 0.0, 0.0, 0, 0, Vector2(1, 0.5), 0.0, 0.0, 0, 0]
+point_count = 3
+
+[sub_resource type="CurveTexture" id="CurveTexture_5uulw"]
+curve = SubResource("Curve_wt1cb")
+
+[sub_resource type="ParticleProcessMaterial" id="ParticleProcessMaterial_olfm2"]
+particle_flag_disable_z = true
+spread = 180.0
+gravity = Vector3(0, 0, 0)
+initial_velocity_min = 32.0
+initial_velocity_max = 32.0
+angular_velocity_min = 90.0
+angular_velocity_max = 90.0
+orbit_velocity_min = 0.0
+orbit_velocity_max = 0.0
+tangential_accel_min = 8.0
+tangential_accel_max = 8.0
+scale_max = 2.0
+scale_curve = SubResource("CurveTexture_5uulw")
+color = Color(1, 0, 0, 1)
+color_ramp = SubResource("GradientTexture1D_iyaih")
+
[sub_resource type="Animation" id="Animation_w1abs"]
length = 0.001
tracks/0/type = "value"
@@ -122,9 +153,22 @@ lifetime = 2.0
one_shot = true
explosiveness = 0.8
+[node name="SpawnParticles" type="GPUParticles2D" parent="."]
+emitting = false
+amount = 12
+process_material = SubResource("ParticleProcessMaterial_olfm2")
+lifetime = 2.0
+one_shot = true
+explosiveness = 1.0
+
[node name="AnimationPlayer" type="AnimationPlayer" parent="."]
libraries = {
"": SubResource("AnimationLibrary_v8fdt")
}
+[node name="PointLight2D" type="PointLight2D" parent="."]
+energy = 1.2
+blend_mode = 2
+texture = ExtResource("5_d8kx8")
+
[editable path="Hitbox"]
diff --git a/Items/Inventory.cs b/Items/Inventory.cs
index fe50d2f..18190fb 100644
--- a/Items/Inventory.cs
+++ b/Items/Inventory.cs
@@ -14,6 +14,9 @@ public partial class Inventory : Node2D
[Export]
public Dictionary InventoryMap { get; set; }
+ [Signal]
+ public delegate void UsedItemEventHandler(Item item);
+
public const int MaxCapacity = 32;
private Item _selectedItem;
diff --git a/Items/Weapons/Sword.cs b/Items/Weapons/Sword.cs
index 12a719d..24f16b3 100644
--- a/Items/Weapons/Sword.cs
+++ b/Items/Weapons/Sword.cs
@@ -166,7 +166,6 @@ public partial class Sword : Weapon, IParryable
foreach (BoundingBox box in Hitbox.Hits)
{
- GD.Print("processing hit");
if (box is Hurtbox hurtbox)
{
hurtbox.InflictDamage(Damage, Character, Knockback);
diff --git a/Items/Weapons/Sword.tscn b/Items/Weapons/Sword.tscn
index 0b53cac..0262c92 100644
--- a/Items/Weapons/Sword.tscn
+++ b/Items/Weapons/Sword.tscn
@@ -92,6 +92,18 @@ tracks/4/keys = {
"method": &"SetAnimationCondition"
}]
}
+tracks/5/type = "value"
+tracks/5/imported = false
+tracks/5/enabled = true
+tracks/5/path = NodePath("SwingSprite:modulate")
+tracks/5/interp = 1
+tracks/5/loop_wrap = true
+tracks/5/keys = {
+"times": PackedFloat32Array(0),
+"transitions": PackedFloat32Array(1),
+"update": 0,
+"values": [Color(2, 2, 2, 1)]
+}
[sub_resource type="Animation" id="Animation_ameas"]
resource_name = "anticipate"
@@ -444,6 +456,4 @@ max_distance = 256.0
stream = ExtResource("6_8nxjm")
max_distance = 256.0
-[connection signal="Hit" from="Hitbox" to="." method="_on_hitbox_hit"]
-
[editable path="Hitbox"]
diff --git a/Scenes/Maps/Arena.tscn b/Scenes/Maps/Arena.tscn
index 4cf9b93..b4530ab 100644
--- a/Scenes/Maps/Arena.tscn
+++ b/Scenes/Maps/Arena.tscn
@@ -1,9 +1,9 @@
-[gd_scene load_steps=13 format=3 uid="uid://b2x17su05ou5w"]
+[gd_scene load_steps=14 format=3 uid="uid://b2x17su05ou5w"]
[ext_resource type="PackedScene" uid="uid://clwv2owvk6abe" path="res://Scenes/BaseMap.tscn" id="1_ifiic"]
[ext_resource type="Texture2D" uid="uid://b0yiy7w8nxmas" path="res://Assets/Sprites/arena-tileset.png" id="2_wnjm0"]
-[ext_resource type="PackedScene" uid="uid://d2skjvvx6fal0" path="res://Characters/Doc.tscn" id="4_c0csw"]
-[ext_resource type="Shader" path="res://Shaders/Flash.gdshader" id="5_aevwf"]
+[ext_resource type="PackedScene" uid="uid://d2skjvvx6fal0" path="res://Characters/Doc.tscn" id="4_ej0f3"]
+[ext_resource type="Shader" path="res://Shaders/Flash.gdshader" id="5_h8k5p"]
[ext_resource type="PackedScene" uid="uid://c1w7t6irnohfx" path="res://Entities/Torch.tscn" id="6_1wwor"]
[ext_resource type="PackedScene" uid="uid://ceadk7pam7vab" path="res://Entities/TorchLamp.tscn" id="6_jy3pc"]
@@ -249,12 +249,15 @@ physics_layer_0/collision_layer = 1
sources/2 = SubResource("TileSetAtlasSource_5yxvt")
sources/0 = SubResource("TileSetAtlasSource_fcd6d")
-[sub_resource type="ShaderMaterial" id="ShaderMaterial_im5g2"]
+[sub_resource type="ShaderMaterial" id="ShaderMaterial_hcbtx"]
resource_local_to_scene = true
-shader = ExtResource("5_aevwf")
+shader = ExtResource("5_h8k5p")
shader_parameter/color = Quaternion(1, 1, 1, 1)
shader_parameter/intensity = 0.0
+[sub_resource type="RectangleShape2D" id="RectangleShape2D_gwpea"]
+size = Vector2(256, 256)
+
[node name="TileMap" instance=ExtResource("1_ifiic")]
tile_set = SubResource("TileSet_k1u48")
layer_0/tile_data = PackedInt32Array(-524281, 458752, 0, -524284, 458752, 0, -262152, 458752, 0, -327673, 458752, 0, -131065, 458752, 0, -65544, 458752, 0, 131064, 458752, 0, 65543, 458752, 0, 262151, 458752, 0, 327672, 458752, 0, 524280, 458752, 0, 524283, 458752, 0, 524286, 458752, 0, 458753, 458752, 0, 458756, 458752, 0, 458759, 458752, 0, -458760, 458752, 0, -458757, 458752, 0, -524287, 458752, 0, -458754, 458752, 0, -524292, 458752, 3, -589821, 458752, 2, -589822, 393216, 3, -524291, 393216, 2, -589817, 393216, 0)
@@ -262,42 +265,119 @@ layer_3/tile_data = PackedInt32Array(-196612, 65536, 1, -131076, 65536, 1, -6554
layer_4/tile_data = PackedInt32Array(-524296, 327680, 0, -589818, 262144, 0, -589817, 262144, 1, -589819, 327680, 0, -589820, 196608, 1, -589821, 327680, 1, -589822, 131072, 1, -589823, 262144, 1, -589824, 327680, 0, -524289, 131072, 1, -524290, 327680, 0, -524291, 327680, 1, -524292, 327680, 1, -524293, 327680, 0, -524294, 131072, 1, -524295, 262144, 1, -589832, 131072, 2, -589831, 131072, 2, -589830, 131072, 2, -589829, 131072, 2, -589828, 131072, 2, -589827, 131072, 2, -589826, 131072, 2, -589825, 131072, 2, -655360, 131072, 2, -655359, 131072, 2, -655358, 131072, 2, -655357, 131072, 2, -655356, 131072, 2, -655355, 131072, 2, -655354, 131072, 2, -655353, 131072, 2, -655352, 327680, 2, -589833, 262144, 2, -524297, 196608, 3, -458761, 196608, 3, -393225, 196608, 3, -327689, 196608, 3, -262153, 196608, 3, -196617, 196608, 3, -131081, 196608, 3, -65545, 196608, 3, -9, 196608, 3, 65527, 196608, 3, 131063, 196608, 3, 196599, 196608, 3, 262135, 196608, 3, 327671, 196608, 3, 393207, 196608, 3, 458743, 196608, 3, 524279, 196608, 3, 262152, 131072, 3, 327688, 131072, 3, 393224, 131072, 3, 458760, 131072, 3, 196616, 131072, 3, 131080, 131072, 3, 65544, 131072, 3, 8, 131072, 3, -65528, 131072, 3, -131064, 131072, 3, -196600, 131072, 3, -262136, 131072, 3, -589816, 131072, 3, -524280, 131072, 3, -458744, 131072, 3, -393208, 131072, 3, -327672, 131072, 3, 589816, 196608, 2, 589817, 196608, 2, 589818, 196608, 2, 589819, 196608, 2, 589820, 196608, 2, 589821, 196608, 2, 589822, 196608, 2, 589823, 196608, 2, 524288, 196608, 2, 524289, 196608, 2, 524290, 196608, 2, 524291, 196608, 2, 524292, 196608, 2, 524293, 196608, 2, 524294, 196608, 2, 524295, 196608, 2, 524296, 327680, 3, 589815, 262144, 3)
[node name="CanvasModulate" parent="." index="0"]
-color = Color(0.501961, 0.501961, 0.501961, 1)
+color = Color(0.588235, 0.588235, 0.588235, 1)
-[node name="Doc" parent="Entities" index="0" instance=ExtResource("4_c0csw")]
-material = SubResource("ShaderMaterial_im5g2")
-PreferredWeightDistance = 256.0
-MaxWeightDistance = 32.0
-
-[node name="Torch" parent="Entities" index="1" instance=ExtResource("6_1wwor")]
-position = Vector2(-120, -112)
-
-[node name="Torch2" parent="Entities" index="2" instance=ExtResource("6_1wwor")]
-position = Vector2(-72, -112)
-
-[node name="Torch3" parent="Entities" index="3" instance=ExtResource("6_1wwor")]
-position = Vector2(-24, -113)
-
-[node name="Torch4" parent="Entities" index="4" instance=ExtResource("6_1wwor")]
-position = Vector2(24, -112)
-
-[node name="Torch5" parent="Entities" index="5" instance=ExtResource("6_1wwor")]
-position = Vector2(72, -112)
-
-[node name="Torch6" parent="Entities" index="6" instance=ExtResource("6_1wwor")]
-position = Vector2(120, -112)
-
-[node name="TorchLamp" parent="." index="6" instance=ExtResource("6_jy3pc")]
+[node name="TorchLamp" parent="Entities" index="0" instance=ExtResource("6_jy3pc")]
+y_sort_enabled = true
position = Vector2(-96, -120)
-[node name="TorchLamp2" parent="." index="7" instance=ExtResource("6_jy3pc")]
+[node name="TorchLamp2" parent="Entities" index="1" instance=ExtResource("6_jy3pc")]
+y_sort_enabled = true
position = Vector2(-48, -120)
-[node name="TorchLamp3" parent="." index="8" instance=ExtResource("6_jy3pc")]
+[node name="TorchLamp3" parent="Entities" index="2" instance=ExtResource("6_jy3pc")]
+y_sort_enabled = true
position = Vector2(0, -120)
-[node name="TorchLamp4" parent="." index="9" instance=ExtResource("6_jy3pc")]
+[node name="TorchLamp4" parent="Entities" index="3" instance=ExtResource("6_jy3pc")]
+y_sort_enabled = true
position = Vector2(48, -120)
-[node name="TorchLamp5" parent="." index="10" instance=ExtResource("6_jy3pc")]
+[node name="TorchLamp5" parent="Entities" index="4" instance=ExtResource("6_jy3pc")]
+y_sort_enabled = true
position = Vector2(96, -120)
+
+[node name="TorchLamp6" parent="Entities" index="5" instance=ExtResource("6_jy3pc")]
+y_sort_enabled = true
+position = Vector2(-120, -96)
+
+[node name="TorchLamp7" parent="Entities" index="6" instance=ExtResource("6_jy3pc")]
+y_sort_enabled = true
+position = Vector2(120, -96)
+
+[node name="TorchLamp8" parent="Entities" index="7" instance=ExtResource("6_jy3pc")]
+y_sort_enabled = true
+position = Vector2(120, -49)
+
+[node name="TorchLamp9" parent="Entities" index="8" instance=ExtResource("6_jy3pc")]
+y_sort_enabled = true
+position = Vector2(120, -1)
+
+[node name="TorchLamp10" parent="Entities" index="9" instance=ExtResource("6_jy3pc")]
+y_sort_enabled = true
+position = Vector2(120, 47)
+
+[node name="TorchLamp11" parent="Entities" index="10" instance=ExtResource("6_jy3pc")]
+y_sort_enabled = true
+position = Vector2(120, 95)
+
+[node name="TorchLamp12" parent="Entities" index="11" instance=ExtResource("6_jy3pc")]
+y_sort_enabled = true
+position = Vector2(97, 120)
+
+[node name="TorchLamp13" parent="Entities" index="12" instance=ExtResource("6_jy3pc")]
+y_sort_enabled = true
+position = Vector2(47, 120)
+
+[node name="TorchLamp14" parent="Entities" index="13" instance=ExtResource("6_jy3pc")]
+y_sort_enabled = true
+position = Vector2(0, 120)
+
+[node name="TorchLamp15" parent="Entities" index="14" instance=ExtResource("6_jy3pc")]
+y_sort_enabled = true
+position = Vector2(-48, 120)
+
+[node name="TorchLamp16" parent="Entities" index="15" instance=ExtResource("6_jy3pc")]
+y_sort_enabled = true
+position = Vector2(-96, 120)
+
+[node name="TorchLamp17" parent="Entities" index="16" instance=ExtResource("6_jy3pc")]
+y_sort_enabled = true
+position = Vector2(-120, 95)
+
+[node name="TorchLamp18" parent="Entities" index="17" instance=ExtResource("6_jy3pc")]
+y_sort_enabled = true
+position = Vector2(-120, 47)
+
+[node name="TorchLamp19" parent="Entities" index="18" instance=ExtResource("6_jy3pc")]
+y_sort_enabled = true
+position = Vector2(-120, -1)
+
+[node name="TorchLamp20" parent="Entities" index="19" instance=ExtResource("6_jy3pc")]
+y_sort_enabled = true
+position = Vector2(-120, -49)
+
+[node name="Torch" parent="Entities" index="20" instance=ExtResource("6_1wwor")]
+visible = false
+position = Vector2(-120, -112)
+
+[node name="Torch2" parent="Entities" index="21" instance=ExtResource("6_1wwor")]
+visible = false
+position = Vector2(-72, -112)
+
+[node name="Torch3" parent="Entities" index="22" instance=ExtResource("6_1wwor")]
+visible = false
+position = Vector2(-24, -113)
+
+[node name="Torch4" parent="Entities" index="23" instance=ExtResource("6_1wwor")]
+visible = false
+position = Vector2(24, -112)
+
+[node name="Torch5" parent="Entities" index="24" instance=ExtResource("6_1wwor")]
+visible = false
+position = Vector2(72, -112)
+
+[node name="Torch6" parent="Entities" index="25" instance=ExtResource("6_1wwor")]
+visible = false
+position = Vector2(120, -112)
+
+[node name="Doc" parent="Entities" index="26" instance=ExtResource("4_ej0f3")]
+material = SubResource("ShaderMaterial_hcbtx")
+
+[node name="Areas" parent="." index="2"]
+visible = false
+
+[node name="Area2D" type="Area2D" parent="Areas" index="0"]
+
+[node name="CollisionShape2D" type="CollisionShape2D" parent="Areas/Area2D" index="0"]
+shape = SubResource("RectangleShape2D_gwpea")
diff --git a/State/Character/NPCIdleState.cs b/State/Character/NPCIdleState.cs
index 617bf06..597bf5f 100644
--- a/State/Character/NPCIdleState.cs
+++ b/State/Character/NPCIdleState.cs
@@ -19,7 +19,7 @@ public partial class NPCIdleState : NPCState
public override IState Enter(IState previousState)
{
- Character.Sprite.Play("idle");
+ Character.MovementAnimation.Play("idle");
return base.Enter(previousState);
}
}
diff --git a/State/Character/NPCMoveState.cs b/State/Character/NPCMoveState.cs
index 4a6879a..b428d72 100644
--- a/State/Character/NPCMoveState.cs
+++ b/State/Character/NPCMoveState.cs
@@ -19,7 +19,7 @@ public partial class NPCMoveState : NPCState
public override IState Enter(IState prev)
{
- Character.Sprite.Play("move");
+ Character.MovementAnimation.Play("move");
return base.Enter(prev);
}
}
diff --git a/State/Character/PlayerIdleState.cs b/State/Character/PlayerIdleState.cs
index fcc12f4..9810b43 100644
--- a/State/Character/PlayerIdleState.cs
+++ b/State/Character/PlayerIdleState.cs
@@ -9,7 +9,6 @@ public partial class PlayerIdleState : PlayerState
public override IState Enter(IState previousState)
{
- GD.Print("Entered idle state");
if (previousState is not PlayerMoveState)
{
if (Character.Direction.LengthSquared() > 0.01f)
@@ -21,7 +20,18 @@ public partial class PlayerIdleState : PlayerState
return MoveState;
}
}
- _player.Animation = "idle";
+
+ var velocity = _player.Velocity.LengthSquared();
+ if (previousState is PlayerMoveState && velocity > 16)
+ {
+ _player.MovementAnimation.Play("stop");
+ _player.MovementAnimation.Queue("idle");
+ }
+ else
+ {
+ _player.MovementAnimation.Play("idle");
+ }
+
return base.Enter(previousState);
}
diff --git a/State/Character/PlayerMoveState.cs b/State/Character/PlayerMoveState.cs
index 38334e6..9800d66 100644
--- a/State/Character/PlayerMoveState.cs
+++ b/State/Character/PlayerMoveState.cs
@@ -9,8 +9,7 @@ public partial class PlayerMoveState : PlayerState
public override IState Enter(IState previousState)
{
- Godot.GD.Print("Started moving");
- _player.Animation = "move";
+ _player.MovementAnimation.Play("move");
return base.Enter(previousState);
}
diff --git a/State/Character/PlayerRollState.cs b/State/Character/PlayerRollState.cs
index 4c0ddbc..7c4cac4 100644
--- a/State/Character/PlayerRollState.cs
+++ b/State/Character/PlayerRollState.cs
@@ -8,11 +8,8 @@ public partial class PlayerRollState : PlayerState
private Vector2 _rollDirection = Vector2.Zero;
- private AnimationPlayer _rollAnimation;
-
public override void _Ready()
{
- _rollAnimation = _player.GetNode("RollAnimation");
base._Ready();
}
@@ -24,12 +21,13 @@ public partial class PlayerRollState : PlayerState
Character.Target = Character.Direction;
if (Character.Direction.X >= 0)
{
- _rollAnimation.Play("roll");
+ _player.MovementAnimation.Play("roll");
}
else
{
- _rollAnimation.PlayBackwards("roll");
+ _player.MovementAnimation.PlayBackwards("roll");
}
+ _player.MovementAnimation.Queue("idle");
return base.Enter(previousState);
}
@@ -39,7 +37,6 @@ public partial class PlayerRollState : PlayerState
// this state (e.g. from death)
_timeLeftToRoll = 0;
_rollDirection = Character.Direction;
- _rollAnimation.Stop();
base.Exit(nextState);
}
diff --git a/State/NPC/Doc/DocShungiteSpikeState.cs b/State/NPC/Doc/DocShungiteSpikeState.cs
index aee3b37..01f5ec0 100644
--- a/State/NPC/Doc/DocShungiteSpikeState.cs
+++ b/State/NPC/Doc/DocShungiteSpikeState.cs
@@ -9,20 +9,38 @@ public partial class DocShungiteSpikeState : DocShungiteDartState
public override NPCState Enter(IState previous)
{
+ if (this is not DocUnwantedFrequencyState)
+ {
+ GetNode("../../Animations/Telegraph")
+ .Play("shungite_spike");
+ }
_currentAttacks = 0;
_currentAttackDuration = 1;
+ NPC.ShouldMove = false;
return base.Enter(previous);
}
+ public override void Exit(IState nextState)
+ {
+ GetNode("../../Animations/Telegraph").Stop();
+ NPC.ShouldMove = true;
+ }
+
protected override Projectile SpawnProjectile(
Vector2 position,
Vector2 direction)
{
+ GetNode("../../Animations/Telegraph")
+ .Play("shungite_spike");
var projectile = base.SpawnProjectile(position, direction)
as ShungiteSpike;
projectile.GlobalRotation = 0;
projectile.Delay = 0;
- projectile.Hitbox.Faction = projectile.Hurtbox.Faction = Doc.Faction;
+ projectile.Hitbox.Faction = Doc.Faction;
+ if (projectile.Hurtbox is not null)
+ {
+ projectile.Hurtbox.Faction = Doc.Faction;
+ }
return projectile;
}
diff --git a/State/NPC/Doc/DocUnwantedFrequencyState.cs b/State/NPC/Doc/DocUnwantedFrequencyState.cs
index e2b1048..b74ced0 100644
--- a/State/NPC/Doc/DocUnwantedFrequencyState.cs
+++ b/State/NPC/Doc/DocUnwantedFrequencyState.cs
@@ -5,6 +5,22 @@ namespace SupaLidlGame.State.NPC.Doc;
public partial class DocUnwantedFrequencyState : DocShungiteSpikeState
{
+ public override NPCState Enter(IState previous)
+ {
+ GetNode("../../Animations/Telegraph")
+ .Play("unwanted_frequencies");
+ NPC.ShouldMove = false;
+ return base.Enter(previous);
+ }
+
+ public override void Exit(IState nextState)
+ {
+ GetNode("../../Animations/Telegraph").Stop();
+ GetNode("../../Effects/UnwantedFrequenciesParticles")
+ .Emitting = false;
+ NPC.ShouldMove = true;
+ }
+
protected override Projectile SpawnProjectile(
Vector2 position,
Vector2 direction)
diff --git a/State/StateMachine.cs b/State/StateMachine.cs
index e204cc9..04039cf 100644
--- a/State/StateMachine.cs
+++ b/State/StateMachine.cs
@@ -2,7 +2,7 @@ using Godot;
namespace SupaLidlGame.State;
-public abstract partial class StateMachine : Node where T : IState
+public abstract partial class StateMachine : Node where T : Node, IState
{
public T CurrentState { get; protected set; }
@@ -20,16 +20,19 @@ public abstract partial class StateMachine : Node where T : IState
return false;
}
+ // NOTE: proxied states can call Exit() more than once
if (CurrentState is not null)
{
CurrentState.Exit(nextState);
}
+ var previousState = CurrentState;
CurrentState = nextState;
// if the next state decides it should enter a different state,
// then we enter that different state instead
- var nextNextState = nextState.Enter(CurrentState);
+ var nextNextState = nextState.Enter(previousState);
+
if (nextNextState is T t)
{
return ChangeState(t, true);
diff --git a/Utils/AnimationManager.cs b/Utils/AnimationManager.cs
new file mode 100644
index 0000000..70d8421
--- /dev/null
+++ b/Utils/AnimationManager.cs
@@ -0,0 +1,167 @@
+using Godot;
+using System.Collections.Generic;
+
+namespace SupaLidlGame.Utils;
+
+public partial class AnimationManager : Node
+{
+ public List Channels { get; set; }
+
+ private List _holds = new List();
+
+ private struct AnimationHold
+ {
+ public Animation PriorityAnim; // channel to be prioritized
+ public Animation HoldAnim; // channel with disabled track
+ public int TrackIndex; // track idx on HoldAnim
+ }
+
+ public override void _Ready()
+ {
+ Channels = new List();
+ foreach (var node in GetChildren())
+ {
+ if (node is AnimationPlayer player)
+ {
+ Channels.Add(player);
+ }
+ }
+
+ // lower position = lower priority
+ for (int _p1Index = 0; _p1Index < Channels.Count; _p1Index++)
+ {
+ // apparently _p1Index is "static" when referencing it inside the
+ // anonymous functions, so we declare a temp variable so it stays
+ // the same value
+ var p1Index = _p1Index;
+ var p1 = Channels[p1Index];
+
+ p1.AnimationStarted += (StringName name) =>
+ {
+ var anim = p1.GetAnimation(name);
+ RemoveAllHolds(anim);
+ for (int p2Index = 0; p2Index < Channels.Count; p2Index++)
+ {
+ var p2 = Channels[p2Index];
+ if (p1 != p2)
+ {
+ CheckConflicts(p1, p1Index, p2, p2Index);
+ }
+ }
+ };
+
+ p1.AnimationChanged += (StringName oldName, StringName newName) =>
+ {
+ var anim = p1.GetAnimation(oldName);
+ GD.Print(oldName + "resolve");
+ ResolveConflicts(anim);
+ RemoveAllHolds(anim);
+ };
+
+ p1.AnimationFinished += (StringName name) =>
+ {
+ var anim = p1.GetAnimation(name);
+ ResolveConflicts(anim);
+ RemoveAllHolds(anim);
+ };
+ }
+ }
+
+ private string NormPath(string path)
+ {
+ return path.Replace("../", "").Replace("./", "");
+ }
+
+ private void CheckConflicts(AnimationPlayer p1, int p1Priority,
+ AnimationPlayer p2, int p2Priority)
+ {
+ if (p1Priority == p2Priority)
+ {
+ throw new System.InvalidOperationException();
+ }
+ if (p1.IsPlaying() && p2.IsPlaying())
+ {
+ var anim1 = p1.GetAnimation(p1.CurrentAnimation);
+ var anim2 = p2.GetAnimation(p2.CurrentAnimation);
+
+ // compare each track to see if they conflict nodepaths
+ for (int p1Track = 0; p1Track < anim1.GetTrackCount(); p1Track++)
+ {
+ string anim1Node = NormPath(anim1.TrackGetPath(p1Track));
+ for (int p2Track = 0; p2Track < anim2.GetTrackCount(); p2Track++)
+ {
+ string anim2Node = NormPath(anim2.TrackGetPath(p2Track));
+ if (anim1Node == anim2Node)
+ {
+ var hold = new AnimationHold();
+ if (p1Priority > p2Priority)
+ {
+ hold.PriorityAnim = anim1;
+ hold.HoldAnim = anim2;
+ hold.TrackIndex = p2Track;
+ anim2.TrackSetEnabled(p2Track, false);
+ }
+ else
+ {
+ hold.PriorityAnim = anim2;
+ hold.HoldAnim = anim1;
+ hold.TrackIndex = p1Track;
+ anim1.TrackSetEnabled(p1Track, false);
+ }
+ GD.Print($"{hold.PriorityAnim.ResourceName} > {hold.HoldAnim.ResourceName}");
+ _holds.Add(hold);
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ private void ResolveConflicts(Animation anim)
+ {
+ // loop through all holds
+ for (int i = 0; i < _holds.Count; i++)
+ {
+ var hold = _holds[i];
+
+ // if the animation is a priority animation, remove it
+ // if there are no other holds on the track, then set the track to
+ // be enabled
+ if (hold.PriorityAnim == anim)
+ {
+ GD.Print($"{anim.ResourceName} was holding ${hold.HoldAnim.ResourceName}");
+ _holds.RemoveAt(i);
+ i--;
+
+ // if can't find hold with same track index, then it is safe to
+ // enable the track
+ if (_holds.FindIndex(h => h.HoldAnim == hold.HoldAnim && h.TrackIndex == hold.TrackIndex) < 0)
+ {
+ GD.Print($"{hold.HoldAnim.ResourceName} is now free");
+ hold.HoldAnim.TrackSetEnabled(hold.TrackIndex, true);
+ }
+ }
+ }
+
+ GD.Print("There are currently " + _holds.Count + " holds");
+ }
+
+ private void RemoveAllHolds(Animation anim)
+ {
+ // remove all holds where the Animation is being held
+ for (int i = 0; i < _holds.Count; i++)
+ {
+ var hold = _holds[i];
+
+ // if the animation is a priority animation, remove it
+ // if there are no other holds on the track, then set the track to
+ // be enabled
+ if (hold.HoldAnim == anim)
+ {
+ _holds.RemoveAt(i);
+ i--;
+ hold.HoldAnim.TrackSetEnabled(hold.TrackIndex, true);
+ }
+ }
+ }
+}