changed doc to 3-stage boss

godot-4.1.1
John Montagu, the 4th Earl of Sandvich 2023-07-24 21:29:14 -07:00
parent cc3ca57467
commit 89f2e375cf
Signed by: sandvich
GPG Key ID: 9A39BE37E602B22D
12 changed files with 79 additions and 30 deletions

Binary file not shown.

View File

@ -31,4 +31,9 @@ public abstract partial class Boss : Enemy
.RegisterBoss(_isActive ? this : null); .RegisterBoss(_isActive ? this : null);
} }
} }
public override void _Ready()
{
base._Ready();
}
} }

View File

@ -1,5 +1,6 @@
using Godot; using Godot;
using GodotUtilities; using GodotUtilities;
using SupaLidlGame.Extensions;
using SupaLidlGame.State.Character; using SupaLidlGame.State.Character;
namespace SupaLidlGame.Characters; namespace SupaLidlGame.Characters;
@ -12,6 +13,8 @@ public partial class Doc : Boss
public Items.Weapons.Sword Lance { get; set; } public Items.Weapons.Sword Lance { get; set; }
protected bool _dashedAway = false; protected bool _dashedAway = false;
protected CharacterDashState _dashState;
protected float _originalDashModifier;
public override float Health public override float Health
{ {
@ -37,9 +40,9 @@ public partial class Doc : Boss
{ {
switch (Health) switch (Health)
{ {
case < 200: case < 300:
return 3; return 3;
case < 400: case < 600:
return 2; return 2;
default: default:
return 1; return 1;
@ -57,6 +60,10 @@ public partial class Doc : Boss
TelegraphAnimation = GetNode<AnimationPlayer>("Animations/Telegraph"); TelegraphAnimation = GetNode<AnimationPlayer>("Animations/Telegraph");
base._Ready(); base._Ready();
_dashState = StateMachine.FindChildOfType<CharacterDashState>();
_originalDashModifier = _dashState.VelocityModifier;
// when we are hurt, start the boss fight // when we are hurt, start the boss fight
Hurt += (Events.HealthChangedArgs args) => Hurt += (Events.HealthChangedArgs args) =>
{ {
@ -130,28 +137,56 @@ public partial class Doc : Boss
if (CanAttack && StunTime <= 0) if (CanAttack && StunTime <= 0)
{ {
bool isTargetStunned = bestTarget.StunTime > 0; bool isTargetStunned = bestTarget.StunTime > 0;
if (!isTargetStunned && dist < 2500)
{ bool shouldDashAway = false;
if (Inventory.SelectedItem is Items.Weapon weapon) 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)
{ {
// dash away if too close // dash away if too close
_dashState.VelocityModifier = _originalDashModifier;
DashTo(-dir); DashTo(-dir);
UseCurrentItem(); UseCurrentItem();
_dashedAway = true; _dashedAway = true;
} }
} else if (shouldDashTowards && !shouldDashAway)
else if (isTargetStunned || (dist < 3600 && _dashedAway))
{ {
if (!Inventory.SelectedItem.IsUsing) // dash to player's predicted position
{ _dashState.VelocityModifier = _originalDashModifier * 1.75f;
DashTo(dir); var dashSpeed = _dashState.VelocityModifier * Speed;
UseCurrentItem(); var newPos = Utils.Physics.PredictNewPosition(
GlobalPosition,
dashSpeed,
pos,
bestTarget.Velocity,
out float _);
DashTo(GlobalPosition.DirectionTo(newPos));
_dashedAway = false; _dashedAway = false;
} }
} }
} }
} }
}
private void DashTo(Vector2 direction) private void DashTo(Vector2 direction)
{ {

View File

@ -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="Script" path="res://Characters/Doc.cs" id="2_3elet"]
[ext_resource type="Shader" path="res://Shaders/Flash.gdshader" id="2_5jxom"] [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="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://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="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"] [sub_resource type="ShaderMaterial" id="ShaderMaterial_7n7iy"]
resource_local_to_scene = true resource_local_to_scene = true
@ -467,7 +468,7 @@ BossStateMachine = NodePath("BossStateMachine")
BossName = "Doc, The Two-Time" BossName = "Doc, The Two-Time"
Music = ExtResource("3_eo4lg") Music = ExtResource("3_eo4lg")
HandTexture = ExtResource("4_8lqj6") HandTexture = ExtResource("4_8lqj6")
Health = 800.0 Health = 900.0
Sprite = NodePath("Sprite") Sprite = NodePath("Sprite")
Inventory = NodePath("Inventory") Inventory = NodePath("Inventory")
StateMachine = NodePath("StateMachine") StateMachine = NodePath("StateMachine")
@ -507,8 +508,8 @@ NPC = NodePath("../..")
[node name="Dart" type="Node" parent="BossStateMachine" node_paths=PackedStringArray("ChooseAttackState", "Doc", "NPC")] [node name="Dart" type="Node" parent="BossStateMachine" node_paths=PackedStringArray("ChooseAttackState", "Doc", "NPC")]
script = ExtResource("8_1hoax") script = ExtResource("8_1hoax")
Duration = 8.0 Duration = 6.0
AttackDuration = 1.0 AttackDuration = 1.5
Projectile = ExtResource("11_23p3o") Projectile = ExtResource("11_23p3o")
ChooseAttackState = NodePath("../ChooseAttack") ChooseAttackState = NodePath("../ChooseAttack")
Doc = NodePath("../..") Doc = NodePath("../..")
@ -613,6 +614,11 @@ emitting = false
amount = 32 amount = 32
process_material = SubResource("ParticleProcessMaterial_j1srf") 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="."] [node name="Sprite" type="Sprite2D" parent="."]
modulate = Color(1, 1, 1, 0.5) modulate = Color(1, 1, 1, 0.5)
y_sort_enabled = true y_sort_enabled = true

View File

@ -132,7 +132,7 @@ texture = ExtResource("2_klp8v")
hframes = 5 hframes = 5
[node name="Hitbox" parent="." instance=ExtResource("3_kojrj")] [node name="Hitbox" parent="." instance=ExtResource("3_kojrj")]
Damage = 14.0 Damage = 45.0
Knockback = 200.0 Knockback = 200.0
[node name="CollisionShape2D" parent="Hitbox" index="0"] [node name="CollisionShape2D" parent="Hitbox" index="0"]

View File

@ -108,7 +108,7 @@ ProjectileName = "Unwanted Frequency"
Speed = 124.0 Speed = 124.0
Direction = Vector2(1, 1) Direction = Vector2(1, 1)
Hitbox = NodePath("Hitbox") Hitbox = NodePath("Hitbox")
Lifetime = 7.0 Lifetime = 4.0
[node name="Hitbox" parent="." instance=ExtResource("2_gxtvd")] [node name="Hitbox" parent="." instance=ExtResource("2_gxtvd")]
collision_layer = 0 collision_layer = 0

View File

@ -157,7 +157,7 @@ public partial class Sword : Weapon, IParryable
{ {
IsParried = true; IsParried = true;
AnimationPlayer.SpeedScale = 0.25f; AnimationPlayer.SpeedScale = 0.25f;
Character.Stun(1); Character.Stun(2);
GetNode<AudioStreamPlayer2D>("ParrySound") GetNode<AudioStreamPlayer2D>("ParrySound")
.OnWorld() .OnWorld()
.WithPitchDeviation(0.125f) .WithPitchDeviation(0.125f)

View File

@ -19,6 +19,7 @@ public partial class DocExitState : NPCState
{ {
_currentDuration = Duration; _currentDuration = Duration;
TelegraphAnimationPlayer.Play("exit_out"); TelegraphAnimationPlayer.Play("exit_out");
NPC.ShouldMove = false;
return null; return null;
} }

View File

@ -36,6 +36,7 @@ public partial class DocLanceState : DocAttackState
{ {
var state = base.Enter(previousState); var state = base.Enter(previousState);
_doc.ShouldMove = true; _doc.ShouldMove = true;
_doc.GetNode<AudioStreamPlayer2D>("Effects/BattleCry").Play();
//if (_doc.Intensity > 2) //if (_doc.Intensity > 2)
//{ //{

View File

@ -45,8 +45,8 @@ public partial class DocShungiteDartState : DocAttackState
var playerPos = player.GlobalPosition; var playerPos = player.GlobalPosition;
// global position is (from npc to player) * 2 = (2 * npc) - player // global position is (from npc to player) * 2 = (2 * npc) - player
//projectile.GlobalPosition = 2 * NPC.GlobalPosition - playerPos; //projectile.GlobalPosition = 2 * NPC.GlobalPosition - playerPos;
Vector2 position1 = 2 * NPC.GlobalPosition - playerPos; Vector2 position1 = 3 * NPC.GlobalPosition - 2 * playerPos;
Vector2 position2 = 2 * playerPos - NPC.GlobalPosition; Vector2 position2 = 3 * playerPos - 2 * NPC.GlobalPosition;
Vector2 direction1 = position1.DirectionTo(playerPos); Vector2 direction1 = position1.DirectionTo(playerPos);
Vector2 direction2 = -direction1; Vector2 direction2 = -direction1;
SpawnProjectile(position1, direction1); SpawnProjectile(position1, direction1);
@ -61,7 +61,7 @@ public partial class DocShungiteDartState : DocAttackState
return null; return null;
} }
if ((_currentDuration -= delta) <= 0) if ((_currentDuration -= delta) <= 0 || Doc.Intensity > 2)
{ {
return ChooseAttackState; return ChooseAttackState;
} }

View File

@ -75,7 +75,7 @@ public partial class DocShungiteSpikeState : DocShungiteDartState
return null; return null;
} }
if ((_currentAttackDuration -= delta) <= 0) if ((_currentAttackDuration -= delta) <= 0 || Doc.Intensity > 2)
{ {
Attack(); Attack();
} }

View File

@ -26,6 +26,7 @@ public partial class DocTelegraphState : NPCState
_currentDuration = Duration; _currentDuration = Duration;
TelegraphAnimationPlayer.Play("enter_in"); TelegraphAnimationPlayer.Play("enter_in");
NPC.ShouldMove = true;
var player = this.GetAncestor<Utils.World>().CurrentPlayer; var player = this.GetAncestor<Utils.World>().CurrentPlayer;
Vector2 randVec; Vector2 randVec;
@ -36,8 +37,8 @@ public partial class DocTelegraphState : NPCState
float randY = GD.RandRange(-112, 112); float randY = GD.RandRange(-112, 112);
randVec = new Vector2(randX, randY); randVec = new Vector2(randX, randY);
} }
while (randVec.DistanceSquaredTo(player.GlobalPosition) < 1024); while (randVec.DistanceSquaredTo(player.GlobalPosition) < 9216);
// can not teleport within 32 units of the player // can not teleport within 96 units of the player
NPC.GlobalPosition = randVec; NPC.GlobalPosition = randVec;
return null; return null;