|
|
|
|
@@ -66,7 +66,8 @@ public partial class PlayerController : CharacterBody3D,
|
|
|
|
|
public ShapeCast3D CeilingDetector;
|
|
|
|
|
public RayCast3D DirectGroundDetector;
|
|
|
|
|
public Area3D WeaponHitbox;
|
|
|
|
|
public AudioStreamPlayer3D SFXPlayer;
|
|
|
|
|
public AudioStreamPlayer3D SfxPlayer;
|
|
|
|
|
public ShapeCast3D DashDamageDetector;
|
|
|
|
|
|
|
|
|
|
// Inspector stuff
|
|
|
|
|
[Export] public Marker3D TutorialWeaponTarget;
|
|
|
|
|
@@ -325,13 +326,9 @@ 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;
|
|
|
|
|
private Transition _onJumpFromWallFalling;
|
|
|
|
|
private Transition _onLeaveWallFromRun;
|
|
|
|
|
@@ -375,8 +372,8 @@ public partial class PlayerController : CharacterBody3D,
|
|
|
|
|
DashIndicatorMeshCylinder = DashIndicatorMesh.Mesh as CylinderMesh;
|
|
|
|
|
DashIndicatorMesh.Visible = false;
|
|
|
|
|
|
|
|
|
|
SFXPlayer = GetNode<AudioStreamPlayer3D>("SFXPlayer");
|
|
|
|
|
_audioStream = SFXPlayer.GetStreamPlayback() as AudioStreamPlaybackInteractive;
|
|
|
|
|
SfxPlayer = GetNode<AudioStreamPlayer3D>("SFXPlayer");
|
|
|
|
|
_audioStream = SfxPlayer.GetStreamPlayback() as AudioStreamPlaybackInteractive;
|
|
|
|
|
|
|
|
|
|
// Camera stuff
|
|
|
|
|
HeadSystem = GetNode<HeadSystem>("HeadSystem");
|
|
|
|
|
@@ -395,6 +392,7 @@ public partial class PlayerController : CharacterBody3D,
|
|
|
|
|
GroundDetector = GetNode<ShapeCast3D>("GroundDetector");
|
|
|
|
|
CeilingDetector = GetNode<ShapeCast3D>("CeilingDetector");
|
|
|
|
|
DirectGroundDetector = GetNode<RayCast3D>("DirectGroundDetector");
|
|
|
|
|
DashDamageDetector = GetNode<ShapeCast3D>("DashDamage");
|
|
|
|
|
RayCast3D stairsBelowRayCast3D = GetNode<RayCast3D>("StairsBelowRayCast3D");
|
|
|
|
|
RayCast3D stairsAheadRayCast3D = GetNode<RayCast3D>("StairsAheadRayCast3D");
|
|
|
|
|
_headCollisionDetectors = new RayCast3D[NUM_OF_HEAD_COLLISION_DETECTORS];
|
|
|
|
|
@@ -447,7 +445,6 @@ public partial class PlayerController : CharacterBody3D,
|
|
|
|
|
_airGlidingDoubleJump = StateChartState.Of(GetNode("StateChart/Root/Movement/Sliding/AirGlideDoubleJumpEnabled"));
|
|
|
|
|
_onGroundSlideJump = Transition.Of(GetNode("StateChart/Root/Movement/Sliding/GroundSlide/OnJump"));
|
|
|
|
|
_onAirGlideDoubleJump = Transition.Of(GetNode("StateChart/Root/Movement/Sliding/AirGlideDoubleJumpEnabled/OnJump"));
|
|
|
|
|
_onDashEnded = Transition.Of(GetNode("StateChart/Root/Movement/Dashing/OnDashEnded"));
|
|
|
|
|
|
|
|
|
|
// _actionHanging = StateChartState.Of(GetNode("StateChart/Root/Actions/Hanging"));
|
|
|
|
|
_powerExpired = StateChartState.Of(GetNode("StateChart/Root/PowerReserve/Expired"));
|
|
|
|
|
@@ -472,8 +469,6 @@ public partial class PlayerController : CharacterBody3D,
|
|
|
|
|
_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"));
|
|
|
|
|
|
|
|
|
|
@@ -1364,7 +1359,7 @@ public partial class PlayerController : CharacterBody3D,
|
|
|
|
|
// Slide management //
|
|
|
|
|
///////////////////////////
|
|
|
|
|
|
|
|
|
|
private bool _isSlideInputDown = false;
|
|
|
|
|
private bool _isSlideInputDown;
|
|
|
|
|
|
|
|
|
|
public void OnInputSlideStarted()
|
|
|
|
|
{
|
|
|
|
|
@@ -1381,7 +1376,6 @@ public partial class PlayerController : CharacterBody3D,
|
|
|
|
|
|
|
|
|
|
public record SlopeRecord(
|
|
|
|
|
Vector3 Position,
|
|
|
|
|
Vector3 Normal,
|
|
|
|
|
Vector3 Direction,
|
|
|
|
|
float AngleRadians
|
|
|
|
|
);
|
|
|
|
|
@@ -1400,7 +1394,7 @@ public partial class PlayerController : CharacterBody3D,
|
|
|
|
|
var angle = normal.AngleTo(Vector3.Up);
|
|
|
|
|
var vectorInPlane = normal.Cross(Vector3.Up).Normalized();
|
|
|
|
|
var direction = normal.Cross(vectorInPlane).Normalized();
|
|
|
|
|
return new SlopeRecord(position, normal, direction, angle);
|
|
|
|
|
return new SlopeRecord(position, direction, angle);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void SetupSlideCollision()
|
|
|
|
|
@@ -1445,7 +1439,7 @@ public partial class PlayerController : CharacterBody3D,
|
|
|
|
|
var finalSpeed = Mathf.Max(currentVelocity * speedLossRate, minimumVelocity);
|
|
|
|
|
|
|
|
|
|
// Going down a slope?
|
|
|
|
|
var (position, _, slopeDirection, slopeAngleRadians) = GetSlope();
|
|
|
|
|
var (position, slopeDirection, slopeAngleRadians) = GetSlope();
|
|
|
|
|
|
|
|
|
|
// Change velocity based on Input
|
|
|
|
|
var horizontalVelocity = ComputeHVelocity(delta, AccelerationGroundSlide, DecelerationGroundSlide);
|
|
|
|
|
@@ -1707,11 +1701,13 @@ public partial class PlayerController : CharacterBody3D,
|
|
|
|
|
|
|
|
|
|
if (DashSystem.CanDashThroughTarget && DashSystem.CollidedObject is ITargetable targetable)
|
|
|
|
|
correctedLocation = ComputePositionAfterTargetedDash(targetable.GetTargetGlobalPosition(), DashSystem.CollisionPoint);
|
|
|
|
|
|
|
|
|
|
// Start invincibility timer for the duration of the dash and a bit more afterwards
|
|
|
|
|
OnHitInvincibility();
|
|
|
|
|
|
|
|
|
|
_preDashVelocity = Velocity;
|
|
|
|
|
_dashDirection = (correctedLocation - GlobalPosition).Normalized();
|
|
|
|
|
SetupDashDamageDetector(correctedLocation);
|
|
|
|
|
|
|
|
|
|
var dashTween = CreatePositionTween(correctedLocation, AimedDashTime);
|
|
|
|
|
// dashTween.TweenMethod(Callable.From<float>(AimedDashTweenOngoing), 0.0f, 1.0f, AimedDashTime);
|
|
|
|
|
@@ -1721,6 +1717,28 @@ public partial class PlayerController : CharacterBody3D,
|
|
|
|
|
_customMantleCurve = DashSystem.MantleSystem.MantleCurve;
|
|
|
|
|
_customMantleStartTransform = DashSystem.MantleSystem.GlobalTransform;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void SetupDashDamageDetector(Vector3 endDashLocation)
|
|
|
|
|
{
|
|
|
|
|
RemoveChildNode(DashDamageDetector);
|
|
|
|
|
DashDamageDetector.SetTargetPosition(DashDamageDetector.ToLocal(endDashLocation));
|
|
|
|
|
DashDamageDetector.Enabled = true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void ComputeDashDamage()
|
|
|
|
|
{
|
|
|
|
|
for (var i = 0; i < DashDamageDetector.GetCollisionCount(); i++)
|
|
|
|
|
{
|
|
|
|
|
var collidedObject = DashDamageDetector.GetCollider(i);
|
|
|
|
|
if (collidedObject is not IDamageable damageable) continue;
|
|
|
|
|
_hitEnemies.Add(damageable);
|
|
|
|
|
}
|
|
|
|
|
TriggerDamage();
|
|
|
|
|
|
|
|
|
|
RecoverChildNode(DashDamageDetector);
|
|
|
|
|
DashDamageDetector.Enabled = false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void AimedDashTweenEnded()
|
|
|
|
|
{
|
|
|
|
|
var dashEvent = isOnFloorCustom() ? "grounded" : "dash_finished";
|
|
|
|
|
@@ -1730,6 +1748,7 @@ public partial class PlayerController : CharacterBody3D,
|
|
|
|
|
{
|
|
|
|
|
ManageAttackedEnemyPostDash(DashSystem.CollidedObject as Node);
|
|
|
|
|
DashSystem.CollidedObject = null;
|
|
|
|
|
ComputeDashDamage();
|
|
|
|
|
|
|
|
|
|
if (_customMantle)
|
|
|
|
|
{
|
|
|
|
|
@@ -1775,6 +1794,8 @@ public partial class PlayerController : CharacterBody3D,
|
|
|
|
|
_audioStream.SwitchToClipByName("dash");
|
|
|
|
|
// Start invincibility timer for the duration of the dash and a bit more afterwards
|
|
|
|
|
OnHitInvincibility();
|
|
|
|
|
|
|
|
|
|
SetupDashDamageDetector(WeaponSystem.GlobalPosition);
|
|
|
|
|
|
|
|
|
|
DashSystem.ShouldMantle = false;
|
|
|
|
|
_dashDirection = (WeaponSystem.GlobalPosition - GlobalPosition).Normalized();
|
|
|
|
|
@@ -1785,6 +1806,7 @@ public partial class PlayerController : CharacterBody3D,
|
|
|
|
|
public void DashToFlyingWeaponTweenEnded()
|
|
|
|
|
{
|
|
|
|
|
RecoverWeapon();
|
|
|
|
|
ComputeDashDamage();
|
|
|
|
|
|
|
|
|
|
var vel = _dashDirection * PostDashSpeed;
|
|
|
|
|
SetVelocity(vel);
|
|
|
|
|
@@ -1815,6 +1837,8 @@ public partial class PlayerController : CharacterBody3D,
|
|
|
|
|
_wallHugStartLocation = dashLocation;
|
|
|
|
|
_wallHugStartProjectedVelocity = Velocity.Slide(_wallHugStartNormal);
|
|
|
|
|
|
|
|
|
|
SetupDashDamageDetector(dashLocation);
|
|
|
|
|
|
|
|
|
|
var dashTween = CreatePositionTween(dashLocation, AimedDashTime);
|
|
|
|
|
dashTween.Finished += DashToPlantedWeaponTweenEnded;
|
|
|
|
|
}
|
|
|
|
|
@@ -1828,7 +1852,7 @@ public partial class PlayerController : CharacterBody3D,
|
|
|
|
|
var resultingEvent = shouldDashToHanging ? "dash_to_planted" : "dash_finished";
|
|
|
|
|
|
|
|
|
|
if (!shouldDashToHanging) RecoverWeapon(); // Manually recover weapon before enemy is freed in case it owns the weapon object
|
|
|
|
|
if (WeaponSystem.PlantObject is ITargetable targetable)
|
|
|
|
|
if (WeaponSystem.PlantObject is ITargetable)
|
|
|
|
|
{
|
|
|
|
|
HeadSystem.OnMantle(); // Recycle mantle animation
|
|
|
|
|
SetVerticalVelocity(PostDashSpeed);
|
|
|
|
|
@@ -1836,6 +1860,7 @@ public partial class PlayerController : CharacterBody3D,
|
|
|
|
|
|
|
|
|
|
ManageAttackedEnemyPostDash(WeaponSystem.PlantObject);
|
|
|
|
|
WeaponSystem.PlantObject = null;
|
|
|
|
|
ComputeDashDamage();
|
|
|
|
|
|
|
|
|
|
_playerState.SendEvent(resultingEvent);
|
|
|
|
|
}
|
|
|
|
|
@@ -1929,14 +1954,14 @@ public partial class PlayerController : CharacterBody3D,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
_targetLocation = target.GetTargetGlobalPosition();
|
|
|
|
|
var targetDistance = _targetLocation.DistanceTo(GlobalPosition);
|
|
|
|
|
// var targetDistance = _targetLocation.DistanceTo(GlobalPosition);
|
|
|
|
|
positionOnScreen = _camera.UnprojectPosition(_targetLocation);
|
|
|
|
|
|
|
|
|
|
_isEnemyInDashAttackRange = true; //targetDistance < TargetInRangeDistance; // Removing the "almost dash" UI
|
|
|
|
|
if (_isEnemyInDashAttackRange)
|
|
|
|
|
{
|
|
|
|
|
enemyTargetState = PlayerUi.TargetState.TargetDashThrough;
|
|
|
|
|
if (_targetObject is IDamageable damageable && _targetObject is IHealthable healthable)
|
|
|
|
|
if (_targetObject is IDamageable damageable and IHealthable healthable)
|
|
|
|
|
{
|
|
|
|
|
var wouldBeDamage = damageable.ComputeDamage(new DamageRecord(this, RDamage));
|
|
|
|
|
if (wouldBeDamage.Damage.DamageDealt < healthable.CurrentHealth)
|
|
|
|
|
@@ -2018,12 +2043,7 @@ public partial class PlayerController : CharacterBody3D,
|
|
|
|
|
stunnable.Stun();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var shouldKnockback = false;
|
|
|
|
|
if (_targetObject is IHealthable healthable)
|
|
|
|
|
{
|
|
|
|
|
if (healthable.CurrentHealth > 0) shouldKnockback = true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var shouldKnockback = _targetObject is IHealthable { CurrentHealth: > 0 };
|
|
|
|
|
if (shouldKnockback)
|
|
|
|
|
{
|
|
|
|
|
Velocity = -_dashDirection*RKnockback.Modifier;
|
|
|
|
|
@@ -2038,7 +2058,7 @@ public partial class PlayerController : CharacterBody3D,
|
|
|
|
|
_playerState.SendEvent("attack_finished");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public Vector3 ComputePositionAfterTargetedDash(Vector3 targetLocation, Vector3 targetHitLocation)
|
|
|
|
|
public static Vector3 ComputePositionAfterTargetedDash(Vector3 targetLocation, Vector3 targetHitLocation)
|
|
|
|
|
{
|
|
|
|
|
return targetLocation + (targetLocation - targetHitLocation);
|
|
|
|
|
}
|
|
|
|
|
|