changed doc to 3-stage boss
parent
cc3ca57467
commit
89f2e375cf
Binary file not shown.
|
@ -31,4 +31,9 @@ public abstract partial class Boss : Enemy
|
||||||
.RegisterBoss(_isActive ? this : null);
|
.RegisterBoss(_isActive ? this : null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override void _Ready()
|
||||||
|
{
|
||||||
|
base._Ready();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)
|
||||||
{
|
{
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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"]
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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)
|
||||||
//{
|
//{
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
Loading…
Reference in New Issue