added fixed dash targets and can dash towards enemies to hit them, get a knockback or dash through if killed
This commit is contained in:
@@ -7,6 +7,7 @@ using Movementtests.addons.godot_state_charts.csharp;
|
||||
using Movementtests.interfaces;
|
||||
using Movementtests.systems;
|
||||
using Movementtests.player_controller.Scripts;
|
||||
using Movementtests.systems.damage;
|
||||
using RustyOptions;
|
||||
|
||||
public partial class PlayerController : CharacterBody3D,
|
||||
@@ -323,6 +324,11 @@ public partial class PlayerController : CharacterBody3D,
|
||||
private StateChartState _onWallHanging;
|
||||
private StateChartState _onWallRunning;
|
||||
|
||||
private StateChartState _attack;
|
||||
private StateChartState _attackReady;
|
||||
private StateChartState _attackStandard;
|
||||
private StateChartState _attackDash;
|
||||
|
||||
private Transition _onDashEnded;
|
||||
|
||||
private Transition _onJumpFromWall;
|
||||
@@ -340,7 +346,6 @@ public partial class PlayerController : CharacterBody3D,
|
||||
public float CurrentHealth { get; set; }
|
||||
|
||||
private bool _isInvincible;
|
||||
private bool _canAttack = true;
|
||||
private readonly List<IDamageable> _hitEnemies = new List<IDamageable>();
|
||||
|
||||
private ShapeCast3D _closeEnemyDetector;
|
||||
@@ -464,6 +469,12 @@ public partial class PlayerController : CharacterBody3D,
|
||||
_onLeaveWallFromRun = Transition.Of(GetNode("StateChart/Root/Movement/OnWall/Running/OnLeaveWall"));
|
||||
_onAirborneToGrounded = Transition.Of(GetNode("StateChart/Root/Movement/Airborne/OnGrounded"));
|
||||
|
||||
// Attack states
|
||||
_attack = StateChartState.Of(GetNode("StateChart/Root/Attack"));
|
||||
_attackReady = StateChartState.Of(GetNode("StateChart/Root/Attack/Ready"));
|
||||
_attackStandard = StateChartState.Of(GetNode("StateChart/Root/Attack/StandardAttack"));
|
||||
_attackDash = StateChartState.Of(GetNode("StateChart/Root/Attack/DashAttack"));
|
||||
|
||||
// State timers
|
||||
_powerCooldownTimer = GetNode<Timer>("PowerCooldown");
|
||||
_timeScaleAimInAirTimer = GetNode<Timer>("TimeScaleAimInAir");
|
||||
@@ -570,7 +581,11 @@ public partial class PlayerController : CharacterBody3D,
|
||||
_onJumpFromWall.Taken += OnJumpFromWall;
|
||||
_onJumpFromWallFalling.Taken += OnJumpFromWall;
|
||||
_onLeaveWallFromRun.Taken += OnLeaveWallFromRun;
|
||||
_onAirborneToGrounded.Taken += OnAirborneToGrounded;
|
||||
_onAirborneToGrounded.Taken += OnAirborneToGrounded;
|
||||
|
||||
// Attack states
|
||||
_attackStandard.StateEntered += OnStandardAttackStarted;
|
||||
_attackDash.StateEntered += OnDashAttackStarted;
|
||||
}
|
||||
|
||||
///////////////////////////
|
||||
@@ -1705,9 +1720,13 @@ public partial class PlayerController : CharacterBody3D,
|
||||
}
|
||||
public void OnAimedDashFinished()
|
||||
{
|
||||
var postDashVelocity = _preDashVelocity.Length() > PostDashSpeed ? PostDashSpeed : _preDashVelocity.Length();
|
||||
if (_customMantle)
|
||||
{
|
||||
_playerState.SendEvent("mantle");
|
||||
return;
|
||||
}
|
||||
var postDashVelocity = _preDashVelocity.Length() > PostDashSpeed ? _preDashVelocity.Length() : PostDashSpeed;
|
||||
Velocity = _dashDirection * postDashVelocity;
|
||||
if (_customMantle) _playerState.SendEvent("mantle");
|
||||
}
|
||||
|
||||
// Weapon dashing
|
||||
@@ -1823,8 +1842,18 @@ public partial class PlayerController : CharacterBody3D,
|
||||
DashIndicatorNode.LookAt(WeaponSystem.GlobalPosition);
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////
|
||||
// Hit Management ///////
|
||||
///////////////////////////
|
||||
|
||||
private bool _isEnemyInDashAttackRange;
|
||||
private Vector3 _targetHitLocation;
|
||||
private Vector3 _targetLocation;
|
||||
private Object _targetObject;
|
||||
public void HandleEnemyTargeting()
|
||||
{
|
||||
_isEnemyInDashAttackRange = false;
|
||||
_closeEnemyDetector.SetRotation(HeadSystem.GetGlobalLookRotation());
|
||||
|
||||
var enemyTargetState = PlayerUi.TargetState.NoTarget;
|
||||
@@ -1834,24 +1863,35 @@ public partial class PlayerController : CharacterBody3D,
|
||||
PlayerUi.SetEnemyTargetProperties(new PlayerUi.TargetProperties(enemyTargetState, positionOnScreen));
|
||||
return;
|
||||
}
|
||||
|
||||
var collidedObject = _closeEnemyDetector.GetCollider(0);
|
||||
if (collidedObject is not ITargetable target)
|
||||
|
||||
_targetHitLocation = _closeEnemyDetector.GetCollisionPoint(0);
|
||||
_targetObject = _closeEnemyDetector.GetCollider(0);
|
||||
if (_targetObject is not ITargetable target)
|
||||
{
|
||||
PlayerUi.SetEnemyTargetProperties(new PlayerUi.TargetProperties(enemyTargetState, positionOnScreen));
|
||||
return;
|
||||
}
|
||||
|
||||
var targetPos = target.GetTargetGlobalPosition();
|
||||
var targetDistance = targetPos.DistanceTo(GlobalPosition);
|
||||
enemyTargetState = targetDistance > TargetInRangeDistance ? PlayerUi.TargetState.TargetInRange : PlayerUi.TargetState.TargetTooFar;
|
||||
positionOnScreen = _camera.UnprojectPosition(targetPos);
|
||||
_targetLocation = target.GetTargetGlobalPosition();
|
||||
var targetDistance = _targetLocation.DistanceTo(GlobalPosition);
|
||||
positionOnScreen = _camera.UnprojectPosition(_targetLocation);
|
||||
|
||||
_isEnemyInDashAttackRange = targetDistance < TargetInRangeDistance;
|
||||
if (_isEnemyInDashAttackRange)
|
||||
{
|
||||
enemyTargetState = PlayerUi.TargetState.TargetDashThrough;
|
||||
if (_targetObject is IDamageable damageable && _targetObject is IHealthable healthable)
|
||||
{
|
||||
var wouldBeDamage = damageable.ComputeDamage(new DamageRecord(this, RDamage));
|
||||
if (wouldBeDamage.Damage.DamageDealt < healthable.CurrentHealth)
|
||||
enemyTargetState = PlayerUi.TargetState.TargetInRange;
|
||||
}
|
||||
}
|
||||
else enemyTargetState = PlayerUi.TargetState.TargetTooFar;
|
||||
|
||||
PlayerUi.SetEnemyTargetProperties(new PlayerUi.TargetProperties(enemyTargetState, positionOnScreen));
|
||||
}
|
||||
|
||||
///////////////////////////
|
||||
// Hit Management ///////
|
||||
///////////////////////////
|
||||
public DamageRecord TakeDamage(DamageRecord damageRecord)
|
||||
{
|
||||
if (_isInvincible)
|
||||
@@ -1868,11 +1908,71 @@ public partial class PlayerController : CharacterBody3D,
|
||||
return finalDamage;
|
||||
}
|
||||
|
||||
public DamageRecord ComputeDamage(DamageRecord damageRecord)
|
||||
{
|
||||
return CDamageable.ComputeDamage(damageRecord);
|
||||
}
|
||||
|
||||
public void OnHitInvincibility()
|
||||
{
|
||||
_isInvincible = true;
|
||||
_invincibilityTimer.Start();
|
||||
}
|
||||
|
||||
public void OnStandardAttackStarted()
|
||||
{
|
||||
_attackCooldown.Start();
|
||||
HeadSystem.OnHit();
|
||||
_audioStream!.SwitchToClipByName("attacks");
|
||||
}
|
||||
|
||||
public void OnDashAttackStarted()
|
||||
{
|
||||
_audioStream!.SwitchToClipByName("attacks");
|
||||
|
||||
_isInvincible = true;
|
||||
|
||||
var actualDashLocation = _targetLocation + Vector3.Down*HeadSystem.Position.Y;
|
||||
var travel = actualDashLocation - GlobalPosition;
|
||||
_preDashVelocity = Velocity;
|
||||
_dashDirection = travel.Normalized();
|
||||
var dashTween = CreatePositionTween(actualDashLocation, AimedDashTime);
|
||||
dashTween.Finished += OnDashAttackEnded;
|
||||
}
|
||||
|
||||
public void OnDashAttackEnded()
|
||||
{
|
||||
if (_targetObject is IDamageable damageable)
|
||||
{
|
||||
_hitEnemies.Add(damageable);
|
||||
TriggerDamage();
|
||||
}
|
||||
|
||||
if (_targetObject is IStunnable stunnable)
|
||||
{
|
||||
stunnable.Stun();
|
||||
}
|
||||
|
||||
var shouldKnockback = false;
|
||||
if (_targetObject is IHealthable healthable)
|
||||
{
|
||||
if (healthable.CurrentHealth > 0) shouldKnockback = true;
|
||||
}
|
||||
|
||||
if (shouldKnockback)
|
||||
{
|
||||
Velocity = -_dashDirection*RKnockback.Modifier;
|
||||
}
|
||||
else
|
||||
{
|
||||
var locationOtherSide = _targetLocation + (_targetLocation - _targetHitLocation);
|
||||
GlobalPosition = locationOtherSide;
|
||||
var postDashVelocity = _preDashVelocity.Length() > PostDashSpeed ? _preDashVelocity.Length() : PostDashSpeed;
|
||||
Velocity = _dashDirection * postDashVelocity;
|
||||
}
|
||||
_isInvincible = false;
|
||||
_playerState.SendEvent("attack_finished");
|
||||
}
|
||||
|
||||
public void OnInputHitPressed()
|
||||
{
|
||||
@@ -1881,24 +1981,15 @@ public partial class PlayerController : CharacterBody3D,
|
||||
ThrowWeapon();
|
||||
}
|
||||
|
||||
if (!WeaponSystem.InHandState.Active) return;
|
||||
if (!_canAttack) return;
|
||||
|
||||
_canAttack = false;
|
||||
_attackCooldown.Start();
|
||||
PerformHit();
|
||||
var attackToDo = _isEnemyInDashAttackRange ? "dash_attack" : "standard_attack";
|
||||
_playerState.SendEvent(attackToDo);
|
||||
}
|
||||
|
||||
public void ResetAttackCooldown()
|
||||
{
|
||||
_canAttack = true;
|
||||
_playerState.SendEvent("attack_finished");
|
||||
}
|
||||
|
||||
public void PerformHit()
|
||||
{
|
||||
HeadSystem.OnHit();
|
||||
_audioStream!.SwitchToClipByName("attacks");
|
||||
}
|
||||
|
||||
public void OnHitboxActivated()
|
||||
{
|
||||
@@ -1942,6 +2033,7 @@ public partial class PlayerController : CharacterBody3D,
|
||||
}
|
||||
public void ReduceHealth(IDamageable source, DamageRecord damageRecord)
|
||||
{
|
||||
GD.Print("That's NOT fine");
|
||||
CHealth.ReduceHealth(source, damageRecord);
|
||||
HealthChanged?.Invoke(this, CHealth.CurrentHealth);
|
||||
}
|
||||
@@ -1952,7 +2044,8 @@ public partial class PlayerController : CharacterBody3D,
|
||||
|
||||
public Vector3 ComputeKnockback()
|
||||
{
|
||||
return CKnockback.ComputeKnockback();
|
||||
var kb = CKnockback.ComputeKnockback();
|
||||
return kb;
|
||||
}
|
||||
|
||||
public void Kill(IHealthable source)
|
||||
|
||||
Reference in New Issue
Block a user