|
|
|
|
@@ -35,6 +35,7 @@ public partial class PlayerController : CharacterBody3D
|
|
|
|
|
public Node3D DashIndicatorNode;
|
|
|
|
|
public MeshInstance3D DashIndicatorMesh;
|
|
|
|
|
public CylinderMesh DashIndicatorMeshCylinder;
|
|
|
|
|
public RayCast3D WallRunSnapper;
|
|
|
|
|
|
|
|
|
|
private bool _movementEnabled = true;
|
|
|
|
|
|
|
|
|
|
@@ -154,6 +155,16 @@ public partial class PlayerController : CharacterBody3D
|
|
|
|
|
[Export(PropertyHint.Range, "0.1,10,0.1,or_greater")]
|
|
|
|
|
public float WallHugHorizontalDeceleration { get; set; } = 5f;
|
|
|
|
|
|
|
|
|
|
// Wall run
|
|
|
|
|
[ExportGroup("Wall run")]
|
|
|
|
|
[Export(PropertyHint.Range, "1,20,0.1,or_greater")]
|
|
|
|
|
public float WallRunUpwardVelocity { get; set; } = 10f;
|
|
|
|
|
[Export(PropertyHint.Range, "1,20,0.1,or_greater")]
|
|
|
|
|
public float WallRunAltitudeLossSpeed { get; set; } = 10f;
|
|
|
|
|
|
|
|
|
|
[Export(PropertyHint.Range, "1,20,0.1,or_greater")]
|
|
|
|
|
public float WallRunSpeedThreshold { get; set; } = 8f;
|
|
|
|
|
|
|
|
|
|
private float _targetSpeed;
|
|
|
|
|
private float _gravity;
|
|
|
|
|
|
|
|
|
|
@@ -246,6 +257,7 @@ public partial class PlayerController : CharacterBody3D
|
|
|
|
|
DashSystem = GetNode<DashSystem>("DashSystem");
|
|
|
|
|
StairsSystem = GetNode<StairsSystem>("StairsSystem");
|
|
|
|
|
WallHugSystem = GetNode<WallHugSystem>("WallHugSystem");
|
|
|
|
|
WallRunSnapper = GetNode<RayCast3D>("%WallRunSnapper");
|
|
|
|
|
RayCast3D stairsBelowRayCast3D = GetNode<RayCast3D>("StairsBelowRayCast3D");
|
|
|
|
|
RayCast3D stairsAheadRayCast3D = GetNode<RayCast3D>("StairsAheadRayCast3D");
|
|
|
|
|
_headCollisionDetectors = new RayCast3D[NUM_OF_HEAD_COLLISION_DETECTORS];
|
|
|
|
|
@@ -427,8 +439,6 @@ public partial class PlayerController : CharacterBody3D
|
|
|
|
|
_playerState.SendEvent("start_falling");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private float _wallRunSpeedThreshold = 8f;
|
|
|
|
|
|
|
|
|
|
public void HandleAirborne(float delta)
|
|
|
|
|
{
|
|
|
|
|
MoveInAir(delta);
|
|
|
|
|
@@ -444,19 +454,21 @@ public partial class PlayerController : CharacterBody3D
|
|
|
|
|
|
|
|
|
|
// Should we start a wall run
|
|
|
|
|
var wallNormal = WallHugSystem.WallHugNormal.UnwrapOr(Vector3.Zero);
|
|
|
|
|
var isIndeedWall = wallNormal.Y < 0.1;
|
|
|
|
|
var hvel = new Vector3(Velocity.X, 0, Velocity.Z);
|
|
|
|
|
var hvelProjected = hvel.Slide(_wallHugStartNormal);
|
|
|
|
|
var haveEnoughSpeed = hvelProjected.Length() > _wallRunSpeedThreshold;
|
|
|
|
|
var isHeadPlanting = Velocity.AngleTo(wallNormal) < Math.PI / 4;
|
|
|
|
|
var isGoingDownwards = Velocity.AngleTo(Vector3.Down) < Math.PI / 4;
|
|
|
|
|
if (haveEnoughSpeed && !isHeadPlanting && !isGoingDownwards)
|
|
|
|
|
var haveEnoughSpeed = hvelProjected.Length() > WallRunSpeedThreshold;
|
|
|
|
|
var isCoplanarEnough = Velocity.AngleTo(wallNormal) > Math.PI/4 && Velocity.AngleTo(wallNormal) < 3*Math.PI/4;
|
|
|
|
|
var isGoingDownwards = Velocity.AngleTo(Vector3.Down) < Math.PI/4;
|
|
|
|
|
if (haveEnoughSpeed && isCoplanarEnough && !isGoingDownwards && isIndeedWall && !_coyoteEnabled.Active)
|
|
|
|
|
{
|
|
|
|
|
SetVerticalVelocity(WallRunUpwardVelocity);
|
|
|
|
|
_playerState.SendEvent("wall_run");
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// If all else fail and we go down, we hug
|
|
|
|
|
if (Velocity.Y < 0)
|
|
|
|
|
if (Velocity.Y < 0 && !_coyoteEnabled.Active)
|
|
|
|
|
_playerState.SendEvent("wall_hug");
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
@@ -476,14 +488,11 @@ public partial class PlayerController : CharacterBody3D
|
|
|
|
|
_wallHugStartNormal = newWallNormal;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private float _timeSinceWallStarted;
|
|
|
|
|
|
|
|
|
|
public void OnWallStarted()
|
|
|
|
|
{
|
|
|
|
|
_wallHugStartNormal = WallHugSystem.WallHugNormal.UnwrapOr(Vector3.Up);
|
|
|
|
|
_wallHugStartLocation = WallHugSystem.WallHugLocation.UnwrapOr(Vector3.Zero) + _wallHugStartNormal * _playerRadius;
|
|
|
|
|
_wallHugStartProjectedVelocity = Velocity.Slide(_wallHugStartNormal);
|
|
|
|
|
_timeSinceWallStarted = 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void OnWallStopped()
|
|
|
|
|
@@ -505,23 +514,26 @@ public partial class PlayerController : CharacterBody3D
|
|
|
|
|
WallHang(delta);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private float _wallRunUpwardVelocity = 10f;
|
|
|
|
|
|
|
|
|
|
public void HandleWallRunning(float delta)
|
|
|
|
|
{
|
|
|
|
|
_timeSinceWallStarted += delta;
|
|
|
|
|
|
|
|
|
|
// Find horizontal velocity projected on the current wall
|
|
|
|
|
var hvel = new Vector3(Velocity.X, 0, Velocity.Z);
|
|
|
|
|
var hvelProjected = hvel.Slide(_wallHugStartNormal);
|
|
|
|
|
Velocity = hvelProjected + hvelProjected.Length()*Vector3.Up*0.3f/(1+_timeSinceWallStarted);
|
|
|
|
|
Velocity *= 0.99f;
|
|
|
|
|
|
|
|
|
|
// if (CanMantle())
|
|
|
|
|
// {
|
|
|
|
|
// MantleToLocation(_plannedMantleLocation.Unwrap());
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
if (!WallHugSystem.IsWallHugging() || Velocity.Length() < _wallRunSpeedThreshold)
|
|
|
|
|
// Reorient horizontal velocity so we keep it coplanar with the wall without losing speed
|
|
|
|
|
var finalHVel = hvelProjected.Normalized() * hvel.Length();
|
|
|
|
|
|
|
|
|
|
// Adapt vertical speed
|
|
|
|
|
var verticalSpeed = Velocity.Y - WallRunAltitudeLossSpeed * delta;
|
|
|
|
|
Velocity = finalHVel + Vector3.Up*verticalSpeed;
|
|
|
|
|
Velocity *= 0.995f;
|
|
|
|
|
|
|
|
|
|
if (WallRunSnapper.IsColliding())
|
|
|
|
|
{
|
|
|
|
|
GD.Print((WallRunSnapper.GetCollisionPoint() - WallRunSnapper.GlobalPosition).Length());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!WallHugSystem.IsWallHugging() || Velocity.Length() < WallRunSpeedThreshold)
|
|
|
|
|
{
|
|
|
|
|
_playerState.SendEvent("start_falling");
|
|
|
|
|
}
|
|
|
|
|
@@ -549,7 +561,10 @@ public partial class PlayerController : CharacterBody3D
|
|
|
|
|
{
|
|
|
|
|
if (CanMantle())
|
|
|
|
|
{
|
|
|
|
|
MantleToLocation(_plannedMantleLocation.Unwrap());
|
|
|
|
|
var location = _plannedMantleLocation.UnwrapOr(Vector3.Zero);
|
|
|
|
|
if (location == Vector3.Zero)
|
|
|
|
|
return; // For some reason CanMantle can return an invalid location so fuck off I guess
|
|
|
|
|
MantleToLocation(location);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@@ -558,6 +573,7 @@ public partial class PlayerController : CharacterBody3D
|
|
|
|
|
_playerState.SendEvent("megajump");
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
_playerState.SendEvent("jump");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@@ -582,6 +598,7 @@ public partial class PlayerController : CharacterBody3D
|
|
|
|
|
public void OnDoubleJumpStarted()
|
|
|
|
|
{
|
|
|
|
|
_canDash = true;
|
|
|
|
|
_canDashAirborne = true;
|
|
|
|
|
OnJumpStarted(DoubleJumpStartVelocity);
|
|
|
|
|
}
|
|
|
|
|
public void OnMegaJumpStarted()
|
|
|
|
|
@@ -943,6 +960,9 @@ public partial class PlayerController : CharacterBody3D
|
|
|
|
|
|
|
|
|
|
public void PlaceWeaponForTutorial()
|
|
|
|
|
{
|
|
|
|
|
if (TutorialDone)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
RemoveChild(WeaponRoot);
|
|
|
|
|
GetTree().GetRoot().CallDeferred(Node.MethodName.AddChild, WeaponRoot);
|
|
|
|
|
WeaponRoot.CallDeferred(Node3D.MethodName.SetGlobalPosition, TutorialWeaponTarget.GlobalPosition);
|
|
|
|
|
@@ -1158,7 +1178,7 @@ public partial class PlayerController : CharacterBody3D
|
|
|
|
|
Bobbing.CameraBobbingParams cameraBobbingParams = new Bobbing.CameraBobbingParams
|
|
|
|
|
{
|
|
|
|
|
Delta = delta,
|
|
|
|
|
IsOnFloorCustom = isOnFloorCustom(),
|
|
|
|
|
IsOnFloorCustom = isOnFloorCustom() || _onWallRunning.Active,
|
|
|
|
|
Velocity = Velocity,
|
|
|
|
|
SettingsMultiplier = _headBobbingMultiplier
|
|
|
|
|
};
|
|
|
|
|
|