diff --git a/Assets/Music/gillette.mp3 b/Assets/Music/gillette.mp3 index bdf52b0..a6929a6 100644 Binary files a/Assets/Music/gillette.mp3 and b/Assets/Music/gillette.mp3 differ diff --git a/Characters/Boss.cs b/Characters/Boss.cs index a04cdef..f9c57dc 100644 --- a/Characters/Boss.cs +++ b/Characters/Boss.cs @@ -31,4 +31,9 @@ public abstract partial class Boss : Enemy .RegisterBoss(_isActive ? this : null); } } + + public override void _Ready() + { + base._Ready(); + } } diff --git a/Characters/Doc.cs b/Characters/Doc.cs index b54c7a5..b39e7bb 100644 --- a/Characters/Doc.cs +++ b/Characters/Doc.cs @@ -1,5 +1,6 @@ using Godot; using GodotUtilities; +using SupaLidlGame.Extensions; using SupaLidlGame.State.Character; namespace SupaLidlGame.Characters; @@ -12,6 +13,8 @@ public partial class Doc : Boss public Items.Weapons.Sword Lance { get; set; } protected bool _dashedAway = false; + protected CharacterDashState _dashState; + protected float _originalDashModifier; public override float Health { @@ -37,9 +40,9 @@ public partial class Doc : Boss { switch (Health) { - case < 200: + case < 300: return 3; - case < 400: + case < 600: return 2; default: return 1; @@ -57,6 +60,10 @@ public partial class Doc : Boss TelegraphAnimation = GetNode("Animations/Telegraph"); base._Ready(); + _dashState = StateMachine.FindChildOfType(); + _originalDashModifier = _dashState.VelocityModifier; + + // when we are hurt, start the boss fight Hurt += (Events.HealthChangedArgs args) => { @@ -130,24 +137,52 @@ public partial class Doc : Boss if (CanAttack && StunTime <= 0) { bool isTargetStunned = bestTarget.StunTime > 0; - if (!isTargetStunned && dist < 2500) + + bool shouldDashAway = false; + bool shouldDashTowards = false; + + var lance = Inventory.SelectedItem as Items.Weapons.Sword; + var lanceState = lance.StateMachine.CurrentState; + + float dot = Direction.Normalized() + .Dot(bestTarget.Direction.Normalized()); + + // doc will still dash if you are farther than normal but + // moving towards him + float distThreshold = 2500 - (dot * 400); + + // or just directly dash towards you if you are too far + float distTowardsThreshold = 22500; + + // dash towards if lance in anticipate state + shouldDashTowards = (isTargetStunned || _dashedAway) && + lanceState is State.Weapon.SwordAnticipateState || + dist > distTowardsThreshold; + + shouldDashAway = dist < distThreshold && !isTargetStunned; + + //if (!isTargetStunned && dist < 2500 && !_dashedAway) + if (shouldDashAway && !shouldDashTowards) { - if (Inventory.SelectedItem is Items.Weapon weapon) - { - // dash away if too close - DashTo(-dir); - UseCurrentItem(); - _dashedAway = true; - } + // dash away if too close + _dashState.VelocityModifier = _originalDashModifier; + DashTo(-dir); + UseCurrentItem(); + _dashedAway = true; } - else if (isTargetStunned || (dist < 3600 && _dashedAway)) + else if (shouldDashTowards && !shouldDashAway) { - if (!Inventory.SelectedItem.IsUsing) - { - DashTo(dir); - UseCurrentItem(); - _dashedAway = false; - } + // dash to player's predicted position + _dashState.VelocityModifier = _originalDashModifier * 1.75f; + var dashSpeed = _dashState.VelocityModifier * Speed; + var newPos = Utils.Physics.PredictNewPosition( + GlobalPosition, + dashSpeed, + pos, + bestTarget.Velocity, + out float _); + DashTo(GlobalPosition.DirectionTo(newPos)); + _dashedAway = false; } } } diff --git a/Characters/Doc.tscn b/Characters/Doc.tscn index eb2fe04..09b70e9 100644 --- a/Characters/Doc.tscn +++ b/Characters/Doc.tscn @@ -1,4 +1,4 @@ -[gd_scene load_steps=61 format=3 uid="uid://d2skjvvx6fal0"] +[gd_scene load_steps=62 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"] @@ -31,6 +31,7 @@ [ext_resource type="Animation" uid="uid://8e8r3y1imvsx" path="res://Assets/Animations/stun.res" id="21_ixn4k"] [ext_resource type="PackedScene" uid="uid://p7oijq6dbvvk" path="res://Items/Weapons/DocLance.tscn" id="24_2es2r"] [ext_resource type="PackedScene" uid="uid://bauucuqvjwbxp" path="res://Items/Weapons/DocLanceHold.tscn" id="26_0tntj"] +[ext_resource type="AudioStream" uid="uid://cqj44je3mvk60" path="res://Assets/Sounds/rauuul.wav" id="26_js7p2"] [sub_resource type="ShaderMaterial" id="ShaderMaterial_7n7iy"] resource_local_to_scene = true @@ -467,7 +468,7 @@ BossStateMachine = NodePath("BossStateMachine") BossName = "Doc, The Two-Time" Music = ExtResource("3_eo4lg") HandTexture = ExtResource("4_8lqj6") -Health = 800.0 +Health = 900.0 Sprite = NodePath("Sprite") Inventory = NodePath("Inventory") StateMachine = NodePath("StateMachine") @@ -507,8 +508,8 @@ NPC = NodePath("../..") [node name="Dart" type="Node" parent="BossStateMachine" node_paths=PackedStringArray("ChooseAttackState", "Doc", "NPC")] script = ExtResource("8_1hoax") -Duration = 8.0 -AttackDuration = 1.0 +Duration = 6.0 +AttackDuration = 1.5 Projectile = ExtResource("11_23p3o") ChooseAttackState = NodePath("../ChooseAttack") Doc = NodePath("../..") @@ -613,6 +614,11 @@ emitting = false amount = 32 process_material = SubResource("ParticleProcessMaterial_j1srf") +[node name="BattleCry" type="AudioStreamPlayer2D" parent="Effects"] +stream = ExtResource("26_js7p2") +volume_db = 3.0 +attenuation = 0.5 + [node name="Sprite" type="Sprite2D" parent="."] modulate = Color(1, 1, 1, 0.5) y_sort_enabled = true diff --git a/Entities/ShungiteSpike.tscn b/Entities/ShungiteSpike.tscn index 37ae25d..95855ba 100644 --- a/Entities/ShungiteSpike.tscn +++ b/Entities/ShungiteSpike.tscn @@ -132,7 +132,7 @@ texture = ExtResource("2_klp8v") hframes = 5 [node name="Hitbox" parent="." instance=ExtResource("3_kojrj")] -Damage = 14.0 +Damage = 45.0 Knockback = 200.0 [node name="CollisionShape2D" parent="Hitbox" index="0"] diff --git a/Entities/UnwantedFrequency.tscn b/Entities/UnwantedFrequency.tscn index 0a21254..d7e448c 100644 --- a/Entities/UnwantedFrequency.tscn +++ b/Entities/UnwantedFrequency.tscn @@ -108,7 +108,7 @@ ProjectileName = "Unwanted Frequency" Speed = 124.0 Direction = Vector2(1, 1) Hitbox = NodePath("Hitbox") -Lifetime = 7.0 +Lifetime = 4.0 [node name="Hitbox" parent="." instance=ExtResource("2_gxtvd")] collision_layer = 0 diff --git a/Items/Weapons/Sword.cs b/Items/Weapons/Sword.cs index 29bb16b..2098562 100644 --- a/Items/Weapons/Sword.cs +++ b/Items/Weapons/Sword.cs @@ -157,7 +157,7 @@ public partial class Sword : Weapon, IParryable { IsParried = true; AnimationPlayer.SpeedScale = 0.25f; - Character.Stun(1); + Character.Stun(2); GetNode("ParrySound") .OnWorld() .WithPitchDeviation(0.125f) diff --git a/State/NPC/Doc/DocExitState.cs b/State/NPC/Doc/DocExitState.cs index b924cc1..a2a4b95 100644 --- a/State/NPC/Doc/DocExitState.cs +++ b/State/NPC/Doc/DocExitState.cs @@ -19,6 +19,7 @@ public partial class DocExitState : NPCState { _currentDuration = Duration; TelegraphAnimationPlayer.Play("exit_out"); + NPC.ShouldMove = false; return null; } diff --git a/State/NPC/Doc/DocLanceState.cs b/State/NPC/Doc/DocLanceState.cs index 59792ee..c73daf7 100644 --- a/State/NPC/Doc/DocLanceState.cs +++ b/State/NPC/Doc/DocLanceState.cs @@ -36,6 +36,7 @@ public partial class DocLanceState : DocAttackState { var state = base.Enter(previousState); _doc.ShouldMove = true; + _doc.GetNode("Effects/BattleCry").Play(); //if (_doc.Intensity > 2) //{ diff --git a/State/NPC/Doc/DocShungiteDartState.cs b/State/NPC/Doc/DocShungiteDartState.cs index 6b12977..417d10c 100644 --- a/State/NPC/Doc/DocShungiteDartState.cs +++ b/State/NPC/Doc/DocShungiteDartState.cs @@ -45,8 +45,8 @@ public partial class DocShungiteDartState : DocAttackState var playerPos = player.GlobalPosition; // global position is (from npc to player) * 2 = (2 * npc) - player //projectile.GlobalPosition = 2 * NPC.GlobalPosition - playerPos; - Vector2 position1 = 2 * NPC.GlobalPosition - playerPos; - Vector2 position2 = 2 * playerPos - NPC.GlobalPosition; + Vector2 position1 = 3 * NPC.GlobalPosition - 2 * playerPos; + Vector2 position2 = 3 * playerPos - 2 * NPC.GlobalPosition; Vector2 direction1 = position1.DirectionTo(playerPos); Vector2 direction2 = -direction1; SpawnProjectile(position1, direction1); @@ -61,7 +61,7 @@ public partial class DocShungiteDartState : DocAttackState return null; } - if ((_currentDuration -= delta) <= 0) + if ((_currentDuration -= delta) <= 0 || Doc.Intensity > 2) { return ChooseAttackState; } diff --git a/State/NPC/Doc/DocShungiteSpikeState.cs b/State/NPC/Doc/DocShungiteSpikeState.cs index f216365..eb884f3 100644 --- a/State/NPC/Doc/DocShungiteSpikeState.cs +++ b/State/NPC/Doc/DocShungiteSpikeState.cs @@ -75,7 +75,7 @@ public partial class DocShungiteSpikeState : DocShungiteDartState return null; } - if ((_currentAttackDuration -= delta) <= 0) + if ((_currentAttackDuration -= delta) <= 0 || Doc.Intensity > 2) { Attack(); } diff --git a/State/NPC/Doc/DocTelegraphState.cs b/State/NPC/Doc/DocTelegraphState.cs index baa1cd6..21bbd07 100644 --- a/State/NPC/Doc/DocTelegraphState.cs +++ b/State/NPC/Doc/DocTelegraphState.cs @@ -26,6 +26,7 @@ public partial class DocTelegraphState : NPCState _currentDuration = Duration; TelegraphAnimationPlayer.Play("enter_in"); + NPC.ShouldMove = true; var player = this.GetAncestor().CurrentPlayer; Vector2 randVec; @@ -36,8 +37,8 @@ public partial class DocTelegraphState : NPCState float randY = GD.RandRange(-112, 112); randVec = new Vector2(randX, randY); } - while (randVec.DistanceSquaredTo(player.GlobalPosition) < 1024); - // can not teleport within 32 units of the player + while (randVec.DistanceSquaredTo(player.GlobalPosition) < 9216); + // can not teleport within 96 units of the player NPC.GlobalPosition = randVec; return null;