From 9dd4525fcd41727e41ab9845a48a9c15cba81834 Mon Sep 17 00:00:00 2001 From: HumanoidSandvichDispenser Date: Tue, 18 Jul 2023 00:57:28 -0700 Subject: [PATCH] new attack --- Characters/Doc.cs | 16 +++++ Characters/Doc.tscn | 26 +++++++- Entities/ShungiteDart.cs | 8 ++- Entities/ShungiteSpike.cs | 72 +++++++++++++++++++++ Entities/ShungiteSpike.tscn | 87 ++++++++++++++++++++++++++ Scenes/Maps/Hills.tscn | 20 +++--- State/NPC/Doc/DocAttackState.cs | 2 +- State/NPC/Doc/DocChooseAttackState.cs | 51 +++++++++++++++ State/NPC/Doc/DocShungiteDartState.cs | 21 ++----- State/NPC/Doc/DocShungiteSpikeState.cs | 32 +++++++++- State/NPC/Doc/DocTelegraphState.cs | 2 +- 11 files changed, 302 insertions(+), 35 deletions(-) create mode 100644 Entities/ShungiteSpike.cs create mode 100644 Entities/ShungiteSpike.tscn create mode 100644 State/NPC/Doc/DocChooseAttackState.cs diff --git a/Characters/Doc.cs b/Characters/Doc.cs index 65562d6..67d9a2b 100644 --- a/Characters/Doc.cs +++ b/Characters/Doc.cs @@ -7,6 +7,22 @@ public partial class Doc : Enemy [Export] public State.NPC.NPCStateMachine BossStateMachine { get; set; } + public int Intensity + { + get + { + switch (Health) + { + case < 250: + return 3; + case < 500: + return 2; + default: + return 1; + } + } + } + public override void _Ready() { GD.Print(Health); diff --git a/Characters/Doc.tscn b/Characters/Doc.tscn index 6cedbb9..fef7ca4 100644 --- a/Characters/Doc.tscn +++ b/Characters/Doc.tscn @@ -1,4 +1,4 @@ -[gd_scene load_steps=33 format=3 uid="uid://d2skjvvx6fal0"] +[gd_scene load_steps=36 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"] @@ -12,8 +12,11 @@ [ext_resource type="Script" path="res://State/NPC/Doc/DocShungiteDartState.cs" id="8_1hoax"] [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="Script" path="res://State/NPC/Doc/DocChooseAttackState.cs" id="12_45x13"] [sub_resource type="ShaderMaterial" id="ShaderMaterial_7n7iy"] resource_local_to_scene = true @@ -233,14 +236,31 @@ InitialState = NodePath("Telegraph") [node name="Telegraph" type="Node" parent="BossStateMachine" node_paths=PackedStringArray("TelegraphAnimationPlayer", "AttackState", "NPC")] script = ExtResource("7_tfwbh") TelegraphAnimationPlayer = NodePath("../../Animations/Telegraph") -AttackState = NodePath("../Attack") +AttackState = NodePath("../ChooseAttack") NPC = NodePath("../..") -[node name="Attack" type="Node" parent="BossStateMachine" node_paths=PackedStringArray("ExitState", "NPC")] +[node name="Dart" type="Node" parent="BossStateMachine" node_paths=PackedStringArray("ChooseAttackState", "Doc", "NPC")] script = ExtResource("8_1hoax") Duration = 8.0 AttackDuration = 1.0 Projectile = ExtResource("9_kthpr") +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 +AttackDuration = 1.0 +Projectile = ExtResource("9_7kavk") +ChooseAttackState = NodePath("../ChooseAttack") +Doc = NodePath("../..") +NPC = NodePath("../..") + +[node name="ChooseAttack" type="Node" parent="BossStateMachine" node_paths=PackedStringArray("DartState", "SpikeState", "ExitState", "NPC")] +script = ExtResource("12_45x13") +DartState = NodePath("../Dart") +SpikeState = NodePath("../Spike") ExitState = NodePath("../Exit") NPC = NodePath("../..") diff --git a/Entities/ShungiteDart.cs b/Entities/ShungiteDart.cs index f6d0a29..302c3db 100644 --- a/Entities/ShungiteDart.cs +++ b/Entities/ShungiteDart.cs @@ -1,4 +1,5 @@ using Godot; + namespace SupaLidlGame.Entities; public partial class ShungiteDart : Projectile @@ -6,8 +7,11 @@ public partial class ShungiteDart : Projectile public override void _Ready() { var player = GetNode("AnimationPlayer"); - player.Play("spin"); - player.SpeedScale = (float)(1 / Delay); + if (Delay > 0) + { + player.Play("spin"); + player.SpeedScale = (float)(1 / Delay); + } base._Ready(); } } diff --git a/Entities/ShungiteSpike.cs b/Entities/ShungiteSpike.cs new file mode 100644 index 0000000..c2d8d90 --- /dev/null +++ b/Entities/ShungiteSpike.cs @@ -0,0 +1,72 @@ +using Godot; +using GodotUtilities; +using SupaLidlGame.Extensions; + +namespace SupaLidlGame.Entities; + +public partial class ShungiteSpike : Projectile +{ + [Export] + public PackedScene Dart { get; set; } + + [Export] + public double ExplodeTime { get; set; } = 6; + + [Export] + public BoundingBoxes.Hurtbox Hurtbox { get; set; } + + [Export] + public AudioStreamPlayer2D HitSound { get; set; } + + [Export] + public AnimationPlayer AnimationPlayer { get; set; } + + private double _currentExplodeTime; + + private Scenes.Map _map; + + public override void _Ready() + { + _currentExplodeTime = ExplodeTime; + _map = this.GetAncestor(); + + Hurtbox.ReceivedDamage += OnReceivedDamage; + AnimationPlayer.Play("spin"); + + base._Ready(); + } + + private void OnReceivedDamage( + float damage, + Characters.Character inflictor, + float knockback, + Vector2 knockbackOrigin = default, + Vector2 knockbackVector = default) + { + HitSound.At(GlobalPosition).PlayOneShot(); + QueueFree(); + } + + + private Entities.ShungiteDart CreateDart(Vector2 direction) + { + var dart = _map.SpawnEntity(Dart); + dart.Direction = direction; + dart.Hitbox.Faction = Hitbox.Faction; + dart.GlobalPosition = GlobalPosition; + dart.Delay = 0; + return dart; + } + + public override void _Process(double delta) + { + if ((_currentExplodeTime -= delta) <= 0) + { + CreateDart(Vector2.Up); + CreateDart(Vector2.Down); + CreateDart(Vector2.Left); + CreateDart(Vector2.Right); + QueueFree(); + } + } +} diff --git a/Entities/ShungiteSpike.tscn b/Entities/ShungiteSpike.tscn new file mode 100644 index 0000000..9393476 --- /dev/null +++ b/Entities/ShungiteSpike.tscn @@ -0,0 +1,87 @@ +[gd_scene load_steps=12 format=3 uid="uid://1tiswf3gtyvv"] + +[ext_resource type="Script" path="res://Entities/ShungiteSpike.cs" id="1_pclpe"] +[ext_resource type="PackedScene" uid="uid://djaljmco3xo4g" path="res://Entities/ShungiteDart.tscn" id="2_hinxt"] +[ext_resource type="Texture2D" uid="uid://dvx2b0y6dup53" path="res://Assets/Sprites/Misc/shungite-spike.png" id="2_klp8v"] +[ext_resource type="PackedScene" uid="uid://du5vhccg75nrq" path="res://BoundingBoxes/Hitbox.tscn" id="3_kojrj"] +[ext_resource type="PackedScene" uid="uid://cjgxyhgcyvsv7" path="res://BoundingBoxes/Hurtbox.tscn" id="4_d8dl4"] +[ext_resource type="AudioStream" uid="uid://c4n7ioxpukdwi" path="res://Assets/Sounds/parry.wav" id="6_fepye"] + +[sub_resource type="RectangleShape2D" id="RectangleShape2D_konb7"] + +[sub_resource type="CircleShape2D" id="CircleShape2D_kumrg"] +radius = 20.0 + +[sub_resource type="Animation" id="Animation_dlpaa"] +resource_name = "spin" +length = 0.5 +loop_mode = 1 +tracks/0/type = "value" +tracks/0/imported = false +tracks/0/enabled = true +tracks/0/path = NodePath("Sprite2D: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_0vfvo"] +length = 0.001 +tracks/0/type = "value" +tracks/0/imported = false +tracks/0/enabled = true +tracks/0/path = NodePath("Sprite2D:rotation") +tracks/0/interp = 1 +tracks/0/loop_wrap = true +tracks/0/keys = { +"times": PackedFloat32Array(0), +"transitions": PackedFloat32Array(1), +"update": 0, +"values": [0.0] +} + +[sub_resource type="AnimationLibrary" id="AnimationLibrary_jj1qe"] +_data = { +"RESET": SubResource("Animation_0vfvo"), +"spin": SubResource("Animation_dlpaa") +} + +[node name="ShungiteSpike" type="RigidBody2D" node_paths=PackedStringArray("Hurtbox", "HitSound", "Hitbox")] +script = ExtResource("1_pclpe") +Dart = ExtResource("2_hinxt") +Hurtbox = NodePath("Hurtbox") +HitSound = NodePath("AudioStreamPlayer2D") +Hitbox = NodePath("Hitbox") + +[node name="Sprite2D" type="Sprite2D" parent="."] +modulate = Color(1.4, 0, 1.2, 1) +self_modulate = Color(2, 2, 2, 1) +texture_filter = 1 +texture = ExtResource("2_klp8v") + +[node name="Hitbox" parent="." instance=ExtResource("3_kojrj")] +Damage = 10.0 +Knockback = 256.0 + +[node name="CollisionShape2D" parent="Hitbox" index="0"] +shape = SubResource("RectangleShape2D_konb7") + +[node name="Hurtbox" parent="." instance=ExtResource("4_d8dl4")] + +[node name="CollisionShape2D" parent="Hurtbox" index="0"] +shape = SubResource("CircleShape2D_kumrg") + +[node name="AudioStreamPlayer2D" type="AudioStreamPlayer2D" parent="."] +stream = ExtResource("6_fepye") + +[node name="AnimationPlayer" type="AnimationPlayer" parent="."] +libraries = { +"": SubResource("AnimationLibrary_jj1qe") +} + +[editable path="Hitbox"] +[editable path="Hurtbox"] diff --git a/Scenes/Maps/Hills.tscn b/Scenes/Maps/Hills.tscn index 3abe54d..896b900 100644 --- a/Scenes/Maps/Hills.tscn +++ b/Scenes/Maps/Hills.tscn @@ -212,31 +212,31 @@ physics_layer_0/collision_mask = 16 physics_layer_1/collision_layer = 1 sources/0 = SubResource("TileSetAtlasSource_dvbe3") -[sub_resource type="ShaderMaterial" id="ShaderMaterial_lhxal"] +[sub_resource type="ShaderMaterial" id="ShaderMaterial_5ho8d"] resource_local_to_scene = true shader = ExtResource("4_mwgaq") shader_parameter/color = Quaternion(1, 1, 1, 1) shader_parameter/intensity = 0.0 -[sub_resource type="ShaderMaterial" id="ShaderMaterial_ypbiq"] +[sub_resource type="ShaderMaterial" id="ShaderMaterial_tic7i"] resource_local_to_scene = true shader = ExtResource("4_mwgaq") shader_parameter/color = Quaternion(1, 1, 1, 1) shader_parameter/intensity = 0.0 -[sub_resource type="ShaderMaterial" id="ShaderMaterial_rl34k"] +[sub_resource type="ShaderMaterial" id="ShaderMaterial_oh7dr"] resource_local_to_scene = true shader = ExtResource("4_mwgaq") shader_parameter/color = Quaternion(1, 1, 1, 1) shader_parameter/intensity = 0.0 -[sub_resource type="ShaderMaterial" id="ShaderMaterial_txxdc"] +[sub_resource type="ShaderMaterial" id="ShaderMaterial_x6kxt"] resource_local_to_scene = true shader = ExtResource("4_mwgaq") shader_parameter/color = Quaternion(1, 1, 1, 1) shader_parameter/intensity = 0.0 -[sub_resource type="ShaderMaterial" id="ShaderMaterial_rqx80"] +[sub_resource type="ShaderMaterial" id="ShaderMaterial_uuq2q"] resource_local_to_scene = true shader = ExtResource("4_mwgaq") shader_parameter/color = Quaternion(1, 1, 1, 1) @@ -268,23 +268,23 @@ layer_4/tile_data = PackedInt32Array(1114105, 196608, 3, 1114106, 262144, 3, 111 layer_5/tile_data = PackedInt32Array(786438, 262144, 3, 720899, 262144, 3, 851971, 458752, 3, 196611, 458752, 3, 1835019, 262144, 3, 1835034, 458752, 3) [node name="ExampleEnemy" parent="Entities" index="0" instance=ExtResource("3_hwof6")] -material = SubResource("ShaderMaterial_lhxal") +material = SubResource("ShaderMaterial_5ho8d") position = Vector2(169, 115) [node name="ExampleEnemy2" parent="Entities" index="1" instance=ExtResource("3_hwof6")] -material = SubResource("ShaderMaterial_ypbiq") +material = SubResource("ShaderMaterial_tic7i") position = Vector2(75, 130) [node name="ExampleEnemy3" parent="Entities" index="2" instance=ExtResource("3_hwof6")] -material = SubResource("ShaderMaterial_rl34k") +material = SubResource("ShaderMaterial_oh7dr") position = Vector2(140, 177) [node name="ExampleEnemy4" parent="Entities" index="3" instance=ExtResource("3_hwof6")] -material = SubResource("ShaderMaterial_txxdc") +material = SubResource("ShaderMaterial_x6kxt") position = Vector2(14, 159) [node name="ExampleEnemy5" parent="Entities" index="4" instance=ExtResource("3_hwof6")] -material = SubResource("ShaderMaterial_rqx80") +material = SubResource("ShaderMaterial_uuq2q") position = Vector2(10, 22) Faction = 1 diff --git a/State/NPC/Doc/DocAttackState.cs b/State/NPC/Doc/DocAttackState.cs index aaeac51..2caf1ec 100644 --- a/State/NPC/Doc/DocAttackState.cs +++ b/State/NPC/Doc/DocAttackState.cs @@ -10,7 +10,7 @@ public abstract partial class DocAttackState : NPCState public abstract PackedScene Projectile { get; set; } - public abstract DocExitState ExitState { get; set; } + public abstract DocChooseAttackState ChooseAttackState { get; set; } protected abstract void Attack(); } diff --git a/State/NPC/Doc/DocChooseAttackState.cs b/State/NPC/Doc/DocChooseAttackState.cs new file mode 100644 index 0000000..6959bd7 --- /dev/null +++ b/State/NPC/Doc/DocChooseAttackState.cs @@ -0,0 +1,51 @@ +using Godot; +using System.Collections.Generic; + +namespace SupaLidlGame.State.NPC.Doc; + +public partial class DocChooseAttackState : NPCState +{ + [Export] + public DocShungiteDartState DartState { get; set; } + + [Export] + public DocShungiteSpikeState SpikeState { get; set; } + + [Export] + public DocExitState ExitState { get; set; } + + public Characters.Doc Doc => NPC as Characters.Doc; + + private List _states = new List(); + + private int _consecutiveAttacks = 0; + + public override void _Ready() + { + _states.Add(DartState); + _states.Add(SpikeState); + base._Ready(); + } + + public override NPCState Enter(IState previous) + { + if (previous is not DocTelegraphState) + { + _consecutiveAttacks++; + } + else + { + _consecutiveAttacks = 0; + } + + if (_consecutiveAttacks > Doc.Intensity) + { + _consecutiveAttacks = 0; + return ExitState; + } + + // choose random attack + var random = new System.Random(); + return _states[random.Next(_states.Count)]; + } +} diff --git a/State/NPC/Doc/DocShungiteDartState.cs b/State/NPC/Doc/DocShungiteDartState.cs index 5a19af9..f2b2601 100644 --- a/State/NPC/Doc/DocShungiteDartState.cs +++ b/State/NPC/Doc/DocShungiteDartState.cs @@ -22,9 +22,10 @@ public partial class DocShungiteDartState : DocAttackState public override PackedScene Projectile { get; set; } [Export] - public override DocExitState ExitState { get; set; } + public override DocChooseAttackState ChooseAttackState { get; set; } - private float _intensity = 1; + [Export] + public Characters.Doc Doc { get; set; } public override NPCState Enter(IState previousState) { @@ -51,7 +52,7 @@ public partial class DocShungiteDartState : DocAttackState projectile.GlobalPosition = position; projectile.Direction = direction; projectile.GlobalRotation = direction.Angle(); - projectile.Delay = 1 / _intensity; + projectile.Delay = 1.0 / Doc.Intensity; return projectile; } @@ -65,24 +66,14 @@ public partial class DocShungiteDartState : DocAttackState Vector2 direction2 = -direction1; SpawnProjectile(position1, direction1); SpawnProjectile(position2, direction2); - _currentAttackDuration = AttackDuration / _intensity; + _currentAttackDuration = AttackDuration / Doc.Intensity; } public override NPCState Process(double delta) { if ((_currentDuration -= delta) <= 0) { - return ExitState; - } - - if (NPC.Health < 500) - { - _intensity = 2; - } - - if (NPC.Health < 250) - { - _intensity = 3; + return ChooseAttackState; } if ((_currentAttackDuration -= delta) <= 0) diff --git a/State/NPC/Doc/DocShungiteSpikeState.cs b/State/NPC/Doc/DocShungiteSpikeState.cs index b8968bd..6f76bcb 100644 --- a/State/NPC/Doc/DocShungiteSpikeState.cs +++ b/State/NPC/Doc/DocShungiteSpikeState.cs @@ -7,12 +7,23 @@ public partial class DocShungiteSpikeState : DocShungiteDartState { private float _intensity = 1; + public override NPCState Enter(IState previous) + { + // subtract from total state time by intensity + Duration = _currentDuration = 9 - 2 * Doc.Intensity; + return base.Enter(previous); + } + protected override Projectile SpawnProjectile( Vector2 position, Vector2 direction) { - var projectile = base.SpawnProjectile(position, direction); - projectile.Delay = 4; + var projectile = base.SpawnProjectile(position, direction) + as ShungiteSpike; + projectile.GlobalRotation = 0; + projectile.Delay = 0; + projectile.ExplodeTime = 6 - 2 * Doc.Intensity; + projectile.Hitbox.Faction = projectile.Hurtbox.Faction = Doc.Faction; return projectile; } @@ -30,6 +41,21 @@ public partial class DocShungiteSpikeState : DocShungiteDartState SpawnProjectile(down, Vector2.Zero); // only attack once and stop (but keep in this state for 8 seconds) - _currentAttackDuration = float.PositiveInfinity; + _currentAttackDuration += 8; + } + + public override NPCState Process(double delta) + { + if ((_currentDuration -= delta) <= 0) + { + return ChooseAttackState; + } + + if ((_currentAttackDuration -= delta) <= 0) + { + Attack(); + } + + return null; } } diff --git a/State/NPC/Doc/DocTelegraphState.cs b/State/NPC/Doc/DocTelegraphState.cs index c19cdcd..33649af 100644 --- a/State/NPC/Doc/DocTelegraphState.cs +++ b/State/NPC/Doc/DocTelegraphState.cs @@ -8,7 +8,7 @@ public partial class DocTelegraphState : NPCState public AnimationPlayer TelegraphAnimationPlayer { get; set; } [Export] - public DocAttackState AttackState { get; set; } + public DocChooseAttackState AttackState { get; set; } [Export] public double Duration { get; set; } = 1;