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); + } + } + } +}