SupaLidlGame/Characters/Doc.cs

197 lines
5.4 KiB
C#
Raw Normal View History

2023-07-13 23:46:58 -07:00
using Godot;
2023-07-21 02:54:13 -07:00
using GodotUtilities;
2023-07-24 21:29:14 -07:00
using SupaLidlGame.Extensions;
2023-07-23 23:39:20 -07:00
using SupaLidlGame.State.Character;
2023-07-13 23:46:58 -07:00
namespace SupaLidlGame.Characters;
2023-07-22 20:23:48 -07:00
public partial class Doc : Boss
2023-07-13 23:46:58 -07:00
{
2023-07-22 20:23:48 -07:00
public AnimationPlayer TelegraphAnimation { get; set; }
2023-07-17 09:30:49 -07:00
2023-07-23 23:39:20 -07:00
[Export]
public Items.Weapons.Sword Lance { get; set; }
protected bool _dashedAway = false;
2023-07-24 21:29:14 -07:00
protected CharacterDashState _dashState;
protected float _originalDashModifier;
2023-07-23 23:39:20 -07:00
2023-07-22 20:23:48 -07:00
public override float Health
{
get => base.Health;
set
{
if (IsActive)
{
base.Health = value;
}
else
{
// play opening animation
// then become active when it finishes
base.Health = value;
}
}
}
public override int Intensity
2023-07-18 00:57:28 -07:00
{
get
{
switch (Health)
{
2023-07-24 21:29:14 -07:00
case < 300:
2023-07-18 00:57:28 -07:00
return 3;
2023-07-24 21:29:14 -07:00
case < 600:
2023-07-18 00:57:28 -07:00
return 2;
default:
return 1;
}
}
}
2023-07-22 20:23:48 -07:00
public Doc()
{
ShouldMove = false;
}
2023-07-17 09:30:49 -07:00
public override void _Ready()
{
2023-07-22 20:23:48 -07:00
TelegraphAnimation = GetNode<AnimationPlayer>("Animations/Telegraph");
2023-07-17 09:30:49 -07:00
base._Ready();
2023-07-23 11:05:01 -07:00
2023-07-24 21:29:14 -07:00
_dashState = StateMachine.FindChildOfType<CharacterDashState>();
_originalDashModifier = _dashState.VelocityModifier;
2023-07-23 11:05:01 -07:00
// when we are hurt, start the boss fight
Hurt += (Events.HealthChangedArgs args) =>
{
if (!IsActive)
{
IsActive = true;
2023-07-23 23:39:20 -07:00
Inventory.SelectedItem = Lance;
2023-07-23 11:05:01 -07:00
}
};
2023-07-17 09:30:49 -07:00
}
2023-07-13 23:46:58 -07:00
public override void _Process(double delta)
{
2023-07-22 20:23:48 -07:00
if (IsActive)
{
BossStateMachine.Process(delta);
}
2023-07-13 23:46:58 -07:00
base._Process(delta);
}
2023-07-21 02:54:13 -07:00
2023-07-22 20:23:48 -07:00
protected override float ReceiveDamage(
float damage,
Character inflictor,
float knockback,
Vector2 knockbackDir = default)
{
if (IsActive)
{
return base.ReceiveDamage(
damage, inflictor, knockback, knockbackDir);
}
return 1;
}
2023-07-21 02:54:13 -07:00
public override void OnReceivedDamage(
float damage,
Character inflictor,
float knockback,
Vector2 knockbackDir = default)
{
GetNode<GpuParticles2D>("Effects/HurtParticles")
.SetDirection(knockbackDir);
base.OnReceivedDamage(damage, inflictor, knockback, knockbackDir);
}
2023-07-23 23:39:20 -07:00
protected override void Think()
{
if (BossStateMachine.CurrentState is State.NPC.Doc.DocLanceState)
{
ThirdPhaseThink();
}
else
{
base.Think();
}
}
protected void ThirdPhaseThink()
{
Character bestTarget = FindBestTarget();
if (bestTarget is not null)
{
Vector2 pos = bestTarget.GlobalPosition;
Target = pos - GlobalPosition;
Vector2 dir = GlobalPosition.DirectionTo(pos);
float dist = GlobalPosition.DistanceSquaredTo(pos);
UpdateWeights(pos);
if (CanAttack && StunTime <= 0)
{
bool isTargetStunned = bestTarget.StunTime > 0;
2023-07-24 21:29:14 -07:00
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)
2023-07-23 23:39:20 -07:00
{
2023-07-24 21:29:14 -07:00
// dash away if too close
_dashState.VelocityModifier = _originalDashModifier;
DashTo(-dir);
UseCurrentItem();
_dashedAway = true;
2023-07-23 23:39:20 -07:00
}
2023-07-24 21:29:14 -07:00
else if (shouldDashTowards && !shouldDashAway)
2023-07-23 23:39:20 -07:00
{
2023-07-24 21:29:14 -07:00
// 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;
2023-07-23 23:39:20 -07:00
}
}
}
}
private void DashTo(Vector2 direction)
{
StateMachine.ChangeState<CharacterDashState>(out var state);
state.DashDirection = direction;
}
2023-07-13 23:46:58 -07:00
}