From 12767e3c70955605a60f4782926b1c43fa988522 Mon Sep 17 00:00:00 2001 From: HumanoidSandvichDispenser <25856867+HumanoidSandvichDispenser@users.noreply.github.com> Date: Sat, 6 Jul 2024 22:51:09 -0700 Subject: [PATCH] Merge branch 'wip' into master (#42) * Implement igniting bow arrows * Add bow alt-fire ability --- Assets/Sprites/Misc/flame.ase | Bin 0 -> 2382 bytes Assets/Sprites/Misc/flame.png | Bin 0 -> 379 bytes Assets/Sprites/Misc/flame.png.import | 34 ++++ Items/Weapons/Bow.cs | 22 ++- Items/Weapons/Bow.tscn | 229 ++++++++++++++++++++++++++- Items/Weapons/ProjectileSpawner.cs | 9 +- Items/Weapons/Ranged.cs | 12 ++ State/Weapon/BowAltState.cs | 75 +++++++++ 8 files changed, 368 insertions(+), 13 deletions(-) create mode 100644 Assets/Sprites/Misc/flame.ase create mode 100644 Assets/Sprites/Misc/flame.png create mode 100644 Assets/Sprites/Misc/flame.png.import create mode 100644 State/Weapon/BowAltState.cs diff --git a/Assets/Sprites/Misc/flame.ase b/Assets/Sprites/Misc/flame.ase new file mode 100644 index 0000000000000000000000000000000000000000..ad323ff99396415d17a1be758d158328643cc37e GIT binary patch literal 2382 zcmcJRdrVtp7{=fBw5Kr3MFgQT)|0>(GC*38%WPN)8y8`d%{YvgrB%d*IF;Lg?GMW^ zWjNf{NCvv8(MYz%7=eX|#w;)phho^AQ!cyUrr-rl8u(*Or9R(j3#Uj4|5(C9+wbx| zzxR927q0TwiZyK1~g%}^oDL9~9; zZm41RVdx`AKZ91ByA1u{+Bj5`6c1g$D*>8)P!Fv-l?6Th)#K2MV>alvjqLmVxtY+9 zs*9jK%@xoex|*R=SI$C{*KUBC;^Lr(@;5@yRWrT*4qNq0@5|7r5H=?>LIu4 zh=B`MfPxZ;-~$}UfCVN1fd(kx00anNAKqacu3;H|VHQqd6CPm@?qChRU`oq82|<#R zgIQ8hfw}g%azXDL#;Gs7q{9!cJe;)haI$mQTWy^IHI)LPVRCZF-3E9>zvkq#CZjU{ z&+GHUmaS^*rMd2YAM;a_6ZhmCueZxO@`^unu9ab}Lb6tgPi(Epl%{=g#A>4lc?i-}@gIjSlpYdPXvYir8dCpL4<)(+bo&20~;jTYx~*jpu; z&uZ74Jiz9XYJk(Ei?bBi)kiW*Av${W?#CP-%lo7CfkUK-E!6QbmchQ;7fNNM^^d)Y zg?H@Ag=a2I+{o1yb_KXzTkuyYu(F(_01t>oPHEs^F#fd9eb9hNrwu7^(*eo?ihJC(y zPUo%`NSse$kJS+7xCjZmF9t$|%B)t8VybWNeB=!9{%L5eA4#ljO>6SI6?ynpl4>-g zGGoX;%#W(-Vvo4b*E1VS&UaIZMIIPV#o8d7b3PkiArE@Y4-2QPw*zXuVNR|RGkaM~ z9~Y*@^5ouq4o!P|+2DJZM@GQh6L#W>KpO1rH~(fovo$q9LEmgk9cP!aQjjl+gWNO4 z>LlYF9kHm*&Vy$emWGFYmK-D3oc(;{OlC5vuZEoQMrmIq<<134na5$O#EMSJ;fC?Q z8#*+{`ZJSr{Rj9wU#t7fO1EvReA011ds0A2O91pP{Lp*;kxVWW>^VEFZ-r zu{z_E&ixOs)yzkg6{pa2evr)@@QYuJ*r_UUzR9vvDu zrHbay3sv2-JwKUlj?7L}a1@to7` z*XW4enoyg)0ghsu)jXc=+B_B9`N`Pyd>;$!eB{@4w*~fi2J{IT1?rM}3*tLJ s6;kN@YccWcp9q%Q0fhdEP)ZrE5JhLVMWW6LXpw0_}T`xZRH?bT4_?&I^zi2NZSpndQRjR~`EF97!#-WP&B$EKC2tc|bF&n-8%rUqyZ zp~Hn~BCp%o1@VvN>3TO?;n+7SYcn>jj7__M^T`Fzv1w)MXD_2>v)sgFwFtd1O(ck| zu#tv_4#SxG*$d0>O#S=|SQi$cx5oTnWq!*6j+E9#Wo@39$1240@>uSA>bxQJa3ZAM z5C<5l+)e$wytBu)1jKIw5zIJ*-U5H%biJFYpI5("%Flame").Visible = false; + // TODO: instead of doing 1.5x damage, create an "On Fire" debuff + projectile.Hitbox.Damage *= 1.5f; + _isOnFire = false; + } + + return projectile; } public override void _Ready() { base._Ready(); _ignitionArea = GetNode("IgnitionArea"); - _ignitionArea.AreaEntered += (Area2D area) => + var onAreaEntered = (Area2D area) => { - _isOnFire = false; + GetNode("%Flame").Visible = true; + _isOnFire = true; }; + _ignitionArea.Connect( + Area2D.SignalName.AreaEntered, + Callable.From(onAreaEntered)); } } diff --git a/Items/Weapons/Bow.tscn b/Items/Weapons/Bow.tscn index 42f8d7b..707aadf 100644 --- a/Items/Weapons/Bow.tscn +++ b/Items/Weapons/Bow.tscn @@ -1,15 +1,74 @@ -[gd_scene load_steps=17 format=3 uid="uid://cgg0sfm2qeiwn"] +[gd_scene load_steps=28 format=3 uid="uid://cgg0sfm2qeiwn"] [ext_resource type="Texture2D" uid="uid://dam6aigkw8xs" path="res://Assets/Sprites/Items/bow-and-arrow.png" id="1_1ghvv"] -[ext_resource type="Script" path="res://Items/Weapons/ProjectileSpawner.cs" id="1_76bur"] +[ext_resource type="Script" path="res://Items/Weapons/Bow.cs" id="1_ikgu2"] [ext_resource type="PackedScene" uid="uid://cjiftn2suskla" path="res://Entities/Arrow.tscn" id="2_mvw0j"] -[ext_resource type="Resource" uid="uid://cjsh0dcgbfn77" path="res://Items/Weapons/Bow.tres" id="3_j7q7r"] [ext_resource type="Script" path="res://State/Weapon/WeaponStateMachine.cs" id="3_pg4gy"] [ext_resource type="Script" path="res://State/Weapon/RangedIdleState.cs" id="3_uxif8"] [ext_resource type="Script" path="res://State/Weapon/RangedFireState.cs" id="4_moo4d"] [ext_resource type="Script" path="res://State/Weapon/RangedChargeState.cs" id="5_k8y6f"] +[ext_resource type="Script" path="res://State/Weapon/BowAltState.cs" id="7_l73rl"] [ext_resource type="AudioStream" uid="uid://bkekgj4gu7fw4" path="res://Assets/Sounds/bow-draw.wav" id="7_t07v0"] +[ext_resource type="Texture2D" uid="uid://coarr28adgo1u" path="res://Assets/Sprites/Particles/point-light.png" id="9_tk6lc"] [ext_resource type="AudioStream" uid="uid://cwy4giq8eod5g" path="res://Assets/Sounds/bow-release.wav" id="9_v051g"] +[ext_resource type="Texture2D" uid="uid://dj1vsctgh1scr" path="res://Assets/Sprites/Misc/flame.png" id="9_xwcvy"] + +[sub_resource type="AtlasTexture" id="AtlasTexture_5af70"] +atlas = ExtResource("9_xwcvy") +region = Rect2(0, 0, 8, 8) + +[sub_resource type="AtlasTexture" id="AtlasTexture_bct7o"] +atlas = ExtResource("9_xwcvy") +region = Rect2(8, 0, 8, 8) + +[sub_resource type="AtlasTexture" id="AtlasTexture_fhtjn"] +atlas = ExtResource("9_xwcvy") +region = Rect2(16, 0, 8, 8) + +[sub_resource type="AtlasTexture" id="AtlasTexture_si88l"] +atlas = ExtResource("9_xwcvy") +region = Rect2(24, 0, 8, 8) + +[sub_resource type="AtlasTexture" id="AtlasTexture_ap5vw"] +atlas = ExtResource("9_xwcvy") +region = Rect2(32, 0, 8, 8) + +[sub_resource type="AtlasTexture" id="AtlasTexture_uad0p"] +atlas = ExtResource("9_xwcvy") +region = Rect2(40, 0, 8, 8) + +[sub_resource type="AtlasTexture" id="AtlasTexture_cxv2f"] +atlas = ExtResource("9_xwcvy") +region = Rect2(48, 0, 8, 8) + +[sub_resource type="SpriteFrames" id="SpriteFrames_b2khh"] +animations = [{ +"frames": [{ +"duration": 1.0, +"texture": SubResource("AtlasTexture_5af70") +}, { +"duration": 1.0, +"texture": SubResource("AtlasTexture_bct7o") +}, { +"duration": 1.0, +"texture": SubResource("AtlasTexture_fhtjn") +}, { +"duration": 1.0, +"texture": SubResource("AtlasTexture_si88l") +}, { +"duration": 1.0, +"texture": SubResource("AtlasTexture_ap5vw") +}, { +"duration": 1.0, +"texture": SubResource("AtlasTexture_uad0p") +}, { +"duration": 1.0, +"texture": SubResource("AtlasTexture_cxv2f") +}], +"loop": true, +"name": &"default", +"speed": 10.0 +}] [sub_resource type="Animation" id="Animation_h0fti"] resource_name = "RESET" @@ -25,6 +84,101 @@ tracks/0/keys = { "update": 1, "values": [0] } +tracks/1/type = "value" +tracks/1/imported = false +tracks/1/enabled = true +tracks/1/path = NodePath("Anchor/Flame:position") +tracks/1/interp = 1 +tracks/1/loop_wrap = true +tracks/1/keys = { +"times": PackedFloat32Array(0), +"transitions": PackedFloat32Array(1), +"update": 0, +"values": [Vector2(15, -8)] +} +tracks/2/type = "value" +tracks/2/imported = false +tracks/2/enabled = true +tracks/2/path = NodePath("Anchor/Flame:visible") +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_bejvb"] +resource_name = "alt_fire" +step = 0.05 +tracks/0/type = "value" +tracks/0/imported = false +tracks/0/enabled = true +tracks/0/path = NodePath("Anchor/Sprite2D: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, 0.7, 0.8), +"transitions": PackedFloat32Array(1, 1, 1, 1, 1, 1, 1, 1, 1), +"update": 1, +"values": [0, 5, 0, 5, 0, 5, 0, 5, 0] +} +tracks/1/type = "audio" +tracks/1/imported = false +tracks/1/enabled = true +tracks/1/path = NodePath("AudioStreamPlayer2D") +tracks/1/interp = 1 +tracks/1/loop_wrap = true +tracks/1/keys = { +"clips": [{ +"end_offset": 0.0, +"start_offset": 0.03, +"stream": ExtResource("9_v051g") +}, { +"end_offset": 0.0, +"start_offset": 0.03, +"stream": ExtResource("9_v051g") +}, { +"end_offset": 0.0, +"start_offset": 0.03, +"stream": ExtResource("9_v051g") +}, { +"end_offset": 0.0, +"start_offset": 0.03, +"stream": ExtResource("9_v051g") +}, { +"end_offset": 0.0, +"start_offset": 0.03, +"stream": ExtResource("9_v051g") +}], +"times": PackedFloat32Array(0, 0.1998, 0.3996, 0.5994, 0.7992) +} +tracks/1/use_blend = true +tracks/2/type = "value" +tracks/2/imported = false +tracks/2/enabled = true +tracks/2/path = NodePath("Anchor/Flame:position") +tracks/2/interp = 1 +tracks/2/loop_wrap = true +tracks/2/keys = { +"times": PackedFloat32Array(0), +"transitions": PackedFloat32Array(1), +"update": 0, +"values": [Vector2(15, -8)] +} +tracks/3/type = "value" +tracks/3/imported = false +tracks/3/enabled = true +tracks/3/path = NodePath("Anchor/Flame:visible") +tracks/3/interp = 1 +tracks/3/loop_wrap = true +tracks/3/keys = { +"times": PackedFloat32Array(0), +"transitions": PackedFloat32Array(1), +"update": 1, +"values": [false] +} [sub_resource type="Animation" id="Animation_8qr8x"] resource_name = "charge" @@ -56,8 +210,20 @@ tracks/1/keys = { "times": PackedFloat32Array(0) } tracks/1/use_blend = true +tracks/2/type = "value" +tracks/2/imported = false +tracks/2/enabled = true +tracks/2/path = NodePath("Anchor/Flame:position") +tracks/2/interp = 1 +tracks/2/loop_wrap = true +tracks/2/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": [Vector2(15, -8), Vector2(14, -8), Vector2(13, -8), Vector2(12, -8), Vector2(11, -8), Vector2(9, -8)] +} -[sub_resource type="Animation" id="Animation_bejvb"] +[sub_resource type="Animation" id="Animation_j5qtq"] resource_name = "fire" tracks/0/type = "value" tracks/0/imported = false @@ -86,6 +252,30 @@ tracks/1/keys = { "times": PackedFloat32Array(0) } tracks/1/use_blend = true +tracks/2/type = "value" +tracks/2/imported = false +tracks/2/enabled = true +tracks/2/path = NodePath("Anchor/Flame:position") +tracks/2/interp = 1 +tracks/2/loop_wrap = true +tracks/2/keys = { +"times": PackedFloat32Array(0), +"transitions": PackedFloat32Array(1), +"update": 0, +"values": [Vector2(15, -8)] +} +tracks/3/type = "value" +tracks/3/imported = false +tracks/3/enabled = true +tracks/3/path = NodePath("Anchor/Flame:visible") +tracks/3/interp = 1 +tracks/3/loop_wrap = true +tracks/3/keys = { +"times": PackedFloat32Array(0), +"transitions": PackedFloat32Array(1), +"update": 1, +"values": [false] +} [sub_resource type="Animation" id="Animation_riv7t"] resource_name = "idle" @@ -105,8 +295,9 @@ tracks/0/keys = { [sub_resource type="AnimationLibrary" id="AnimationLibrary_5vx8d"] _data = { "RESET": SubResource("Animation_h0fti"), +"alt_fire": SubResource("Animation_bejvb"), "charge": SubResource("Animation_8qr8x"), -"fire": SubResource("Animation_bejvb"), +"fire": SubResource("Animation_j5qtq"), "idle": SubResource("Animation_riv7t") } @@ -114,27 +305,29 @@ _data = { [node name="Bow" type="Node2D" node_paths=PackedStringArray("StateMachine")] y_sort_enabled = true -script = ExtResource("1_76bur") +script = ExtResource("1_ikgu2") Projectile = ExtResource("2_mvw0j") ChargeTime = 0.5 StateMachine = NodePath("StateMachine") Damage = 20.0 UseTime = 0.5 +UseAltTime = 0.2 Knockback = 64.0 InitialVelocity = 200.0 ShouldFreezeAngleOnUse = false PlayerLevelGain = 1.0 -Metadata = ExtResource("3_j7q7r") [node name="StateMachine" type="Node" parent="." node_paths=PackedStringArray("InitialState")] script = ExtResource("3_pg4gy") InitialState = NodePath("Idle") UsedItemStates = Array[NodePath]([NodePath("Charge"), NodePath("Fire")]) +UsedItemAltStates = Array[NodePath]([NodePath("AltFire")]) DeusedItemStates = Array[NodePath]([NodePath("Idle")]) -[node name="Idle" type="Node" parent="StateMachine" node_paths=PackedStringArray("FireState", "Weapon", "AnimationPlayer")] +[node name="Idle" type="Node" parent="StateMachine" node_paths=PackedStringArray("FireState", "AltFireState", "Weapon", "AnimationPlayer")] script = ExtResource("3_uxif8") FireState = NodePath("../Charge") +AltFireState = NodePath("../AltFire") Weapon = NodePath("../..") AnimationPlayer = NodePath("../../AnimationPlayer") AnimationKey = "idle" @@ -154,6 +347,14 @@ IdleState = NodePath("../Idle") AnimationPlayer = NodePath("../../AnimationPlayer") AnimationKey = "fire" +[node name="AltFire" type="Node" parent="StateMachine" node_paths=PackedStringArray("Bow", "IdleState", "AnimationPlayer")] +script = ExtResource("7_l73rl") +Bow = NodePath("../..") +IdleState = NodePath("../Idle") +AnimationPlayer = NodePath("../../AnimationPlayer") +AnimationKey = "alt_fire" +AngleDeviation = 30.0 + [node name="Anchor" type="Node2D" parent="."] y_sort_enabled = true position = Vector2(0, 4) @@ -166,6 +367,18 @@ centered = false offset = Vector2(-8, -16) hframes = 8 +[node name="Flame" type="AnimatedSprite2D" parent="Anchor"] +unique_name_in_owner = true +visible = false +position = Vector2(15, -8) +sprite_frames = SubResource("SpriteFrames_b2khh") +autoplay = "default" + +[node name="PointLight2D" type="PointLight2D" parent="Anchor/Flame"] +color = Color(1, 0.8, 0.701961, 1) +texture = ExtResource("9_tk6lc") +texture_scale = 0.13 + [node name="AnimationPlayer" type="AnimationPlayer" parent="."] libraries = { "": SubResource("AnimationLibrary_5vx8d") diff --git a/Items/Weapons/ProjectileSpawner.cs b/Items/Weapons/ProjectileSpawner.cs index 33d5ad2..769d467 100644 --- a/Items/Weapons/ProjectileSpawner.cs +++ b/Items/Weapons/ProjectileSpawner.cs @@ -33,7 +33,7 @@ public partial class ProjectileSpawner : Ranged } } - protected virtual void SpawnProjectile(Scenes.Map map, + protected virtual Entities.Projectile SpawnProjectile(Scenes.Map map, Vector2 direction, float velocityModifier = 1) { var projectile = map.SpawnEntity(Projectile); @@ -70,6 +70,7 @@ public partial class ProjectileSpawner : Ranged } } + return projectile; } public override void Attack() @@ -85,6 +86,12 @@ public partial class ProjectileSpawner : Ranged Vector2 target = Character.Target.Normalized(); + if (AngleDeviation > 0) + { + float angle = (GD.Randf() - 0.5f) * AngleDeviation; + target = target.Rotated(Mathf.DegToRad(angle)); + } + if (CharacterRecoil > 0) { Character.ApplyImpulse(-target * CharacterRecoil); diff --git a/Items/Weapons/Ranged.cs b/Items/Weapons/Ranged.cs index 659b61b..c29c9e9 100644 --- a/Items/Weapons/Ranged.cs +++ b/Items/Weapons/Ranged.cs @@ -29,12 +29,24 @@ public abstract partial class Ranged : Weapon base.Use(); } + public override void UseAlt() + { + StateMachine.UseAlt(); + base.Use(); + } + public override void Deuse() { StateMachine.Deuse(); base.Deuse(); } + public override void DeuseAlt() + { + StateMachine.DeuseAlt(); + base.Deuse(); + } + public override void _Process(double delta) { StateMachine.Process(delta); diff --git a/State/Weapon/BowAltState.cs b/State/Weapon/BowAltState.cs new file mode 100644 index 0000000..c19e0e8 --- /dev/null +++ b/State/Weapon/BowAltState.cs @@ -0,0 +1,75 @@ +using Godot; +using SupaLidlGame.Extensions; + +namespace SupaLidlGame.State.Weapon; + +public partial class BowAltState : WeaponState +{ + [Export] + public Items.Weapons.Bow Bow { get; set; } + + [Export] + public RangedIdleState IdleState { get; set; } + + [Export] + public AnimationPlayer AnimationPlayer { get; set; } + + [Export] + public string AnimationKey { get; set; } + + [Export] + public int MaxCount { get; set; } = 5; + + [Export] + public float AngleDeviation { get; set; } + + public float VelocityModifier { get; set; } = 1; + + private Timer _timer; + + private int _count = 0; + + private float _oldDeviation; + + public override IState Enter(IState prev) + { + //_timer = GetTree().CreateTimer(Weapon.UseAltTime); + _timer = new Timer(); + _count = 1; + _oldDeviation = Bow.ProjectileAngleDeviation; + Bow.AngleDeviation = AngleDeviation; + + var timeout = () => + { + Bow.Attack(VelocityModifier); + _count++; + }; + + Bow.Attack(VelocityModifier); + Bow.UseDirection = Bow.Character.Target; + AnimationPlayer?.TryPlay(AnimationKey); + + _timer.Connect(Timer.SignalName.Timeout, Callable.From(timeout)); + AddChild(_timer); + _timer.Start(Bow.UseAltTime); + + GD.Print("Entered alt fire state"); + + return null; + } + + public override WeaponState Process(double delta) + { + if (_count >= MaxCount) + { + return IdleState; + } + return null; + } + + public override void Exit(IState nextState) + { + _timer.QueueFree(); + Bow.AngleDeviation = _oldDeviation; + } +}