630 lines
19 KiB
C#
630 lines
19 KiB
C#
using System;
|
|
using Godot;
|
|
using GodotStateCharts;
|
|
using Movementtests.systems;
|
|
using Movementtests.player_controller.Scripts;
|
|
using RustyOptions;
|
|
|
|
public partial class PlayerController : CharacterBody3D
|
|
{
|
|
// User API to important child nodes.
|
|
public HeadSystem HeadSystem;
|
|
public Bobbing Bobbing;
|
|
public FieldOfView FieldOfView;
|
|
public Stamina Stamina;
|
|
public StairsSystem StairsSystem;
|
|
public MantleSystem MantleSystem;
|
|
public DashSystem DashSystem;
|
|
public CapsuleCollider CapsuleCollider;
|
|
public Gravity Gravity;
|
|
public HealthSystem HealthSystem;
|
|
public MoveSystem MoveSystem;
|
|
public TweenQueueSystem TweenQueueSystem;
|
|
public Node3D WeaponRoot;
|
|
public WeaponSystem WeaponSystem;
|
|
public WallHugSystem WallHugSystem;
|
|
|
|
private bool _movementEnabled = true;
|
|
|
|
private bool _shouldMantle;
|
|
private Vector3 _mantleLocation = Vector3.Zero;
|
|
private Vector3 _dashDirection = Vector3.Zero;
|
|
|
|
private float _lastFrameWasOnFloor = -Mathf.Inf;
|
|
|
|
private const int NUM_OF_HEAD_COLLISION_DETECTORS = 4;
|
|
private RayCast3D[] _headCollisionDetectors;
|
|
|
|
private Vector3 _inputMove = Vector3.Zero;
|
|
private float _inputRotateY;
|
|
private float _inputRotateFloorplane;
|
|
|
|
private Timer _coyoteTimer;
|
|
private Timer _timeScaleAimInAirTimer;
|
|
private Timer _timeAfterDashingTimer;
|
|
[Export(PropertyHint.Range, "0,1,0.01,or_greater")]
|
|
public float TimeScaleAimInAir { get; set; } = 0.2f;
|
|
[Export(PropertyHint.Range, "0,5,0.1,or_greater")]
|
|
public float MaxJumpBoostAfterDashing { get; set; } = 1f;
|
|
|
|
[Export(PropertyHint.Range, "0,5,1,or_greater")]
|
|
public int MaxNumberOfDashActions { get; set; } = 1;
|
|
|
|
public int DashActionsLeft { get; set; }
|
|
|
|
private StateChart _playerState;
|
|
// Actions state
|
|
private StateChartState _weaponInHand;
|
|
private StateChartState _aiming;
|
|
private StateChartState _dashing;
|
|
private StateChartState _weaponThrown;
|
|
private StateChartState _actionHanging;
|
|
// Movement state
|
|
private StateChartState _grounded;
|
|
private StateChartState _mantling;
|
|
private StateChartState _movHanging;
|
|
private StateChartState _wallHugging;
|
|
private StateChartState _airborne;
|
|
private StateChartState _coyoteEnabled;
|
|
private StateChartState _jump;
|
|
private StateChartState _jumpFromWall;
|
|
private StateChartState _doubleJumpEnabled;
|
|
private StateChartState _doubleJump;
|
|
private StateChartState _falling;
|
|
|
|
public override void _Ready()
|
|
{
|
|
///////////////////////////
|
|
// Getting components /////
|
|
///////////////////////////
|
|
|
|
// General use stuff
|
|
TweenQueueSystem = GetNode<TweenQueueSystem>("TweenQueueSystem");
|
|
// Node3D mapNode = GetTree().Root.FindChild("Map", true, false) as Node3D;
|
|
|
|
// Camera stuff
|
|
HeadSystem = GetNode<HeadSystem>("HeadSystem");
|
|
Bobbing = GetNode<Bobbing>("Bobbing");
|
|
FieldOfView = GetNode<FieldOfView>("FieldOfView");
|
|
Camera3D camera = GetNode<Camera3D>("HeadSystem/CameraSmooth/Camera3D");
|
|
Node3D cameraSmooth = GetNode<Node3D>("HeadSystem/CameraSmooth");
|
|
ColorRect vignetteRect = GetNode<ColorRect>(
|
|
"HeadSystem/CameraSmooth/Camera3D/CLVignette(Layer_1)/HealthVignetteRect");
|
|
ColorRect distortionRect = GetNode<ColorRect>(
|
|
"HeadSystem/CameraSmooth/Camera3D/CLDistortion(Layer_2)/HealthDistortionRect");
|
|
ColorRect blurRect = GetNode<ColorRect>("HeadSystem/CameraSmooth/Camera3D/CLBlur(Layer_2)/BlurRect");
|
|
|
|
// Movement stuff
|
|
WeaponRoot = GetNode<Node3D>("WeaponRoot");
|
|
WeaponSystem = GetNode<WeaponSystem>("WeaponRoot/WeaponSystem");
|
|
MantleSystem = GetNode<MantleSystem>("MantleSystem");
|
|
CapsuleCollider = GetNode<CapsuleCollider>("CapsuleCollider");
|
|
Gravity = GetNode<Gravity>("Gravity");
|
|
MoveSystem = GetNode<MoveSystem>("MoveSystem");
|
|
DashSystem = GetNode<DashSystem>("DashSystem");
|
|
StairsSystem = GetNode<StairsSystem>("StairsSystem");
|
|
WallHugSystem = GetNode<WallHugSystem>("WallHugSystem");
|
|
RayCast3D stairsBelowRayCast3D = GetNode<RayCast3D>("StairsBelowRayCast3D");
|
|
RayCast3D stairsAheadRayCast3D = GetNode<RayCast3D>("StairsAheadRayCast3D");
|
|
_headCollisionDetectors = new RayCast3D[NUM_OF_HEAD_COLLISION_DETECTORS];
|
|
for (int i = 0; i < NUM_OF_HEAD_COLLISION_DETECTORS; i++)
|
|
{
|
|
_headCollisionDetectors[i] = GetNode<RayCast3D>(
|
|
"HeadCollisionDetectors/HeadCollisionDetector" + i);
|
|
}
|
|
|
|
// RPG Stuff
|
|
Stamina = GetNode<Stamina>("Stamina");
|
|
HealthSystem = GetNode<HealthSystem>("HealthSystem");
|
|
|
|
// State management
|
|
_playerState = StateChart.Of(GetNode("StateChart"));
|
|
// Actions states
|
|
_weaponInHand = StateChartState.Of(GetNode("StateChart/Root/Actions/WeaponInHand"));
|
|
_aiming = StateChartState.Of(GetNode("StateChart/Root/Actions/Aiming"));
|
|
_dashing = StateChartState.Of(GetNode("StateChart/Root/Actions/Dashing"));
|
|
_weaponThrown = StateChartState.Of(GetNode("StateChart/Root/Actions/WeaponThrown"));
|
|
_actionHanging = StateChartState.Of(GetNode("StateChart/Root/Actions/Hanging"));
|
|
// Movement states
|
|
_grounded = StateChartState.Of(GetNode("StateChart/Root/Movement/Grounded"));
|
|
_mantling = StateChartState.Of(GetNode("StateChart/Root/Movement/Mantling"));
|
|
_movHanging = StateChartState.Of(GetNode("StateChart/Root/Movement/Hanging"));
|
|
_airborne = StateChartState.Of(GetNode("StateChart/Root/Movement/Airborne"));
|
|
_wallHugging = StateChartState.Of(GetNode("StateChart/Root/Movement/Airborne/WallHugging"));
|
|
_coyoteEnabled = StateChartState.Of(GetNode("StateChart/Root/Movement/Airborne/CoyoteEnabled"));
|
|
_jump = StateChartState.Of(GetNode("StateChart/Root/Movement/Airborne/Jump"));
|
|
_jumpFromWall = StateChartState.Of(GetNode("StateChart/Root/Movement/Airborne/JumpFromWall"));
|
|
_doubleJumpEnabled = StateChartState.Of(GetNode("StateChart/Root/Movement/Airborne/DoubleJumpEnabled"));
|
|
_doubleJump = StateChartState.Of(GetNode("StateChart/Root/Movement/Airborne/DoubleJump"));
|
|
_falling = StateChartState.Of(GetNode("StateChart/Root/Movement/Airborne/Falling"));
|
|
// State timers
|
|
_coyoteTimer = GetNode<Timer>("CoyoteTime");
|
|
_timeScaleAimInAirTimer = GetNode<Timer>("TimeScaleAimInAir");
|
|
_timeAfterDashingTimer = GetNode<Timer>("TimeAfterDashing");
|
|
|
|
///////////////////////////
|
|
// Initialize components //
|
|
///////////////////////////
|
|
|
|
// General use stuff
|
|
TweenQueueSystem.Init(this);
|
|
|
|
// Camera stuff
|
|
HeadSystem.Init();
|
|
Bobbing.Init(camera);
|
|
FieldOfView.Init(camera);
|
|
|
|
// Movement stuff
|
|
// Getting universal setting from GODOT editor to be in sync
|
|
float gravitySetting = (float)ProjectSettings.GetSetting("physics/3d/default_gravity");
|
|
Gravity.Init(gravitySetting);
|
|
MantleSystem.Init(HeadSystem);
|
|
var moveSystemParams = new MoveSystem.MoveSystemParameters(this, Gravity, MantleSystem, TweenQueueSystem,
|
|
HeadSystem, CapsuleCollider);
|
|
MoveSystem.Init(moveSystemParams);
|
|
StairsSystem.Init(stairsBelowRayCast3D, stairsAheadRayCast3D, cameraSmooth);
|
|
DashSystem.Init(HeadSystem, camera, TweenQueueSystem);
|
|
WeaponSystem.Init(HeadSystem, camera);
|
|
WallHugSystem.Init();
|
|
|
|
// RPG Stuff
|
|
HealthSystem.HealthSystemInitParams healthSystemParams = new HealthSystem.HealthSystemInitParams()
|
|
{
|
|
Gravity = Gravity,
|
|
Parent = this,
|
|
Camera = camera,
|
|
Head = HeadSystem,
|
|
VignetteRect = vignetteRect,
|
|
DistortionRect = distortionRect,
|
|
BlurRect = blurRect,
|
|
};
|
|
HealthSystem.Init(healthSystemParams);
|
|
Stamina.SetSpeeds(MoveSystem.WalkSpeed, MoveSystem.SprintSpeed);
|
|
|
|
DashActionsLeft = MaxNumberOfDashActions;
|
|
|
|
///////////////////////////
|
|
// Signal setup ///////////
|
|
///////////////////////////
|
|
|
|
DashSystem.DashEnded += OnDashEnded;
|
|
|
|
_weaponInHand.StateProcessing += HandleWeaponInHand;
|
|
_aiming.StateProcessing += HandleAiming;
|
|
_aiming.StateEntered += OnAimingEntered;
|
|
_aiming.StateExited += ResetTimeScale;
|
|
|
|
_grounded.StateEntered += OnGrounded;
|
|
_grounded.StatePhysicsProcessing += HandleGrounded;
|
|
_airborne.StatePhysicsProcessing += HandleAirborne;
|
|
_wallHugging.StatePhysicsProcessing += HandleWallHugging;
|
|
|
|
_coyoteEnabled.StateEntered += StartCoyoteTime;
|
|
_coyoteTimer.Timeout += CoyoteExpired;
|
|
_timeScaleAimInAirTimer.Timeout += ResetTimeScale;
|
|
_jump.StateEntered += Jump;
|
|
_jumpFromWall.StateEntered += JumpFromWall;
|
|
_doubleJump.StateEntered += DoubleJump;
|
|
_mantling.StateEntered += Mantle;
|
|
|
|
_dashing.StateEntered += OnDashStarted;
|
|
_weaponThrown.StateEntered += OnWeaponThrown;
|
|
}
|
|
|
|
///////////////////////////
|
|
// Input Management ///////
|
|
///////////////////////////
|
|
public void OnInputMove(Vector3 value)
|
|
{
|
|
_inputMove = value;
|
|
}
|
|
public void OnInputRotateY(float value)
|
|
{
|
|
_inputRotateY = value;
|
|
}
|
|
public void OnInputRotateFloorplane(float value)
|
|
{
|
|
_inputRotateFloorplane = value;
|
|
}
|
|
|
|
public void OnInputAimPressed()
|
|
{
|
|
_playerState.SendEvent("aim_pressed");
|
|
}
|
|
public void OnInputAimReleased()
|
|
{
|
|
_playerState.SendEvent("aim_released");
|
|
}
|
|
public void OnInputAimCanceled()
|
|
{
|
|
_playerState.SendEvent("aim_canceled");
|
|
DashSystem.CancelDash();
|
|
}
|
|
public void OnInputHitPressed()
|
|
{
|
|
_playerState.SendEvent("hit_pressed");
|
|
}
|
|
public void OnInputJumpPressed()
|
|
{
|
|
if (MoveSystem.CanMantle())
|
|
{
|
|
_playerState.SendEvent("mantle");
|
|
return;
|
|
}
|
|
|
|
_playerState.SendEvent("jump");
|
|
}
|
|
public void OnInputDropPressed()
|
|
{
|
|
_playerState.SendEvent("crouch");
|
|
}
|
|
|
|
///////////////////////////
|
|
// Stateful logic /////////
|
|
///////////////////////////
|
|
|
|
// Simple states
|
|
public void OnGrounded()
|
|
{
|
|
DashActionsLeft = MaxNumberOfDashActions;
|
|
GD.Print(DashActionsLeft);
|
|
}
|
|
|
|
public bool CanPerformDashAction()
|
|
{
|
|
return DashActionsLeft > 0;
|
|
}
|
|
|
|
public void PerformDashAction()
|
|
{
|
|
DashActionsLeft--;
|
|
GD.Print(DashActionsLeft);
|
|
}
|
|
|
|
// Jumping
|
|
public void StartCoyoteTime()
|
|
{
|
|
_coyoteTimer.Start();
|
|
}
|
|
public void CoyoteExpired()
|
|
{
|
|
_playerState.SendEvent("coyote_expired");
|
|
}
|
|
public void Jump()
|
|
{
|
|
if (_aiming.Active && CanPerformDashAction())
|
|
{
|
|
_playerState.SendEvent("jump_from_dash");
|
|
PerformDashAction();
|
|
PerformJump(MoveSystem.JumpTypes.JUMP_FROM_DASH);
|
|
return;
|
|
}
|
|
_playerState.SendEvent("to_double_jump");
|
|
PerformJump(MoveSystem.JumpTypes.SIMPLE_JUMP);
|
|
}
|
|
public void JumpFromWall()
|
|
{
|
|
var wallNormal = WallHugSystem.GetWallNormal().UnwrapOr(Vector3.Up);
|
|
if (_aiming.Active && CanPerformDashAction())
|
|
{
|
|
_playerState.SendEvent("jump_from_dash");
|
|
PerformDashAction();
|
|
PerformJump(MoveSystem.JumpTypes.JUMP_FROM_DASH, wallNormal);
|
|
return;
|
|
}
|
|
_playerState.SendEvent("to_double_jump");
|
|
PerformJump(MoveSystem.JumpTypes.SIMPLE_JUMP, wallNormal);
|
|
}
|
|
public void DoubleJump()
|
|
{
|
|
_playerState.SendEvent("to_falling");
|
|
if (_aiming.Active && CanPerformDashAction())
|
|
{
|
|
PerformDashAction();
|
|
PerformJump(MoveSystem.JumpTypes.JUMP_FROM_DASH);
|
|
return;
|
|
}
|
|
PerformJump(MoveSystem.JumpTypes.DOUBLE_JUMP);
|
|
}
|
|
private void PerformJump(MoveSystem.JumpTypes jumpType, Vector3? jumpDirection = null)
|
|
{
|
|
var effectiveJumpDirection = jumpDirection ?? Vector3.Up;
|
|
var jumpVector = (effectiveJumpDirection.Normalized() + Vector3.Up).Normalized();
|
|
|
|
var proportionOfTimeGone = _timeAfterDashingTimer.TimeLeft / _timeAfterDashingTimer.WaitTime;
|
|
var actualBoost = 1 + MaxJumpBoostAfterDashing * proportionOfTimeGone;
|
|
var makeItDouble = actualBoost > 1;
|
|
if (makeItDouble && jumpType == MoveSystem.JumpTypes.SIMPLE_JUMP)
|
|
jumpType = MoveSystem.JumpTypes.DOUBLE_JUMP; // convert simple jump to double if done right after a dash
|
|
_timeAfterDashingTimer.Stop();
|
|
|
|
bool doesCapsuleHaveCrouchingHeight = CapsuleCollider.IsCrouchingHeight();
|
|
bool isPlayerDead = HealthSystem.IsDead();
|
|
if (!doesCapsuleHaveCrouchingHeight && !isPlayerDead)
|
|
MoveSystem.Jump(jumpType, jumpVector, (float) actualBoost);
|
|
}
|
|
|
|
// Mantling
|
|
public void Mantle()
|
|
{
|
|
var optionTween = MoveSystem.Mantle();
|
|
if (optionTween.IsSome(out var tween))
|
|
tween.Finished += MantleFinished;
|
|
}
|
|
public void MantleFinished()
|
|
{
|
|
_playerState.SendEvent("to_grounded");
|
|
}
|
|
|
|
// Dashing and weapon throwing
|
|
public void OnDashStarted()
|
|
{
|
|
if (!CanPerformDashAction())
|
|
{
|
|
_playerState.SendEvent("aim_canceled");
|
|
_playerState.SendEvent("dash_ended");
|
|
DashSystem.CancelDash();
|
|
return;
|
|
}
|
|
|
|
PerformDashAction();
|
|
_timeAfterDashingTimer.Start();
|
|
if (WeaponSystem.FlyingState.Active)
|
|
{
|
|
DashSystem.DashResolve = new DashResolveRecord(false, WeaponSystem.GlobalPosition, Vector3.Zero);
|
|
}
|
|
else if (WeaponSystem.PlantedState.Active)
|
|
{
|
|
// Should we try to resolve with mantle?
|
|
DashSystem.DashResolve = new DashResolveRecord(false, WeaponSystem.PlayerDashLocation, Vector3.Zero);
|
|
}
|
|
_dashDirection = (DashSystem.DashResolve.DashLocation - GlobalPosition).Normalized();
|
|
DashSystem.Dash();
|
|
}
|
|
public void OnDashEnded()
|
|
{
|
|
// _playerState.SendEvent("enable_double_jump"); // Allow for double jump after dash -- OP ?
|
|
// Regular dash
|
|
if (WeaponSystem.InHandState.Active)
|
|
{
|
|
_playerState.SendEvent("dash_ended");
|
|
return;
|
|
}
|
|
|
|
GD.Print(WeaponSystem.GlobalRotation);
|
|
// Store the weapon state before resetting it
|
|
var isPlantedOnWall = Math.Abs(WeaponSystem.GlobalRotation.X) + Math.Abs(WeaponSystem.GlobalRotation.Z) < 0.3;
|
|
var isPlantedUnderPlatform = WeaponSystem.GlobalRotation.X > 1 && Math.Abs(WeaponSystem.GlobalRotation.Y) > 1;
|
|
var shouldDashToPlanted = WeaponSystem.PlantedState.Active && (isPlantedOnWall || isPlantedUnderPlatform);
|
|
var isFlying = WeaponSystem.FlyingState.Active;
|
|
|
|
// Get the weapon back
|
|
GetTree().GetRoot().RemoveChild(WeaponRoot);
|
|
AddChild(WeaponRoot);
|
|
WeaponRoot.SetGlobalPosition(GlobalPosition);
|
|
WeaponSystem.ResetWeapon();
|
|
|
|
if (isFlying)
|
|
{
|
|
var vel = _dashDirection * DashSystem.PostDashSpeed;
|
|
SetVelocity(vel);
|
|
_playerState.SendEvent("dash_ended");
|
|
return; // In case states aren't exclusives
|
|
}
|
|
|
|
if (shouldDashToPlanted)
|
|
{
|
|
_playerState.SendEvent("dash_to_planted");
|
|
return; // In case states aren't exclusives
|
|
}
|
|
|
|
// Weapon planted anywhere else
|
|
_playerState.SendEvent("dash_ended");
|
|
}
|
|
public void OnWeaponThrown()
|
|
{
|
|
RemoveChild(WeaponRoot);
|
|
GetTree().GetRoot().AddChild(WeaponRoot);
|
|
WeaponRoot.SetGlobalPosition(GlobalPosition);
|
|
|
|
var (hasHit, location, collisionPoint, collisionNormal) = DashSystem.DashComputation;
|
|
var (endWithMantle, dashLocation, mantleLocation) = DashSystem.DashResolve;
|
|
|
|
DashSystem.CancelDash();
|
|
WeaponSystem.ThrowWeapon(location, hasHit, collisionPoint, collisionNormal);
|
|
}
|
|
public void OnAimingEntered()
|
|
{
|
|
if (!isOnFloorCustom() && CanPerformDashAction())
|
|
ReduceTimeScaleWhileAiming();
|
|
}
|
|
|
|
// Regular processes
|
|
public void HandleWeaponInHand(float delta)
|
|
{
|
|
RotateWeaponWithPlayer();
|
|
}
|
|
public void HandleAiming(float delta)
|
|
{
|
|
RotateWeaponWithPlayer();
|
|
if (isOnFloorCustom())
|
|
ResetTimeScale();
|
|
if (CanPerformDashAction())
|
|
DashSystem.PrepareDash();
|
|
else
|
|
{
|
|
_playerState.SendEvent("aim_canceled");
|
|
DashSystem.CancelDash();
|
|
}
|
|
}
|
|
|
|
// Physics processes
|
|
public void HandleGrounded(float delta)
|
|
{
|
|
if (!isOnFloorCustom())
|
|
_playerState.SendEvent("start_falling");
|
|
}
|
|
public void HandleAirborne(float delta)
|
|
{
|
|
if (isOnFloorCustom())
|
|
_playerState.SendEvent("grounded");
|
|
if (WallHugSystem.IsWallHugging() && Velocity.Y < 0)
|
|
_playerState.SendEvent("wall_hug");
|
|
}
|
|
public void HandleWallHugging(float delta)
|
|
{
|
|
if (!WallHugSystem.IsWallHugging())
|
|
_playerState.SendEvent("start_falling");
|
|
}
|
|
|
|
///////////////////////////
|
|
// Stateless logic ////////
|
|
///////////////////////////
|
|
private void LookAround()
|
|
{
|
|
Vector2 inputLookDir = new Vector2(_inputRotateY, _inputRotateFloorplane);
|
|
HeadSystem.LookAround(inputLookDir);
|
|
}
|
|
|
|
private void MoveAround(double delta)
|
|
{
|
|
var moveAroundParams = new MoveSystem.MoveAroundParameters(
|
|
delta,
|
|
_inputMove,
|
|
isOnFloorCustom(),
|
|
HealthSystem.IsDead(),
|
|
IsHeadTouchingCeiling(),
|
|
_actionHanging.Active,
|
|
_wallHugging.Active);
|
|
MoveSystem.MoveAround(moveAroundParams);
|
|
}
|
|
|
|
private void HandleStairs(float delta)
|
|
{
|
|
|
|
StairsSystem.UpStairsCheckParams upStairsCheckParams = new StairsSystem.UpStairsCheckParams
|
|
{
|
|
IsOnFloorCustom = isOnFloorCustom(),
|
|
IsCapsuleHeightLessThanNormal = CapsuleCollider.IsCapsuleHeightLessThanNormal(),
|
|
CurrentSpeedGreaterThanWalkSpeed = MoveSystem._currentSpeed > MoveSystem.WalkSpeed,
|
|
IsCrouchingHeight = CapsuleCollider.IsCrouchingHeight(),
|
|
Delta = (float)delta,
|
|
FloorMaxAngle = FloorMaxAngle,
|
|
GlobalPositionFromDriver = GlobalPosition,
|
|
Velocity = Velocity,
|
|
GlobalTransformFromDriver = GlobalTransform,
|
|
Rid = GetRid()
|
|
};
|
|
StairsSystem.UpStairsCheckResult upStairsCheckResult = StairsSystem.SnapUpStairsCheck(upStairsCheckParams);
|
|
|
|
if (upStairsCheckResult.UpdateRequired)
|
|
{
|
|
upStairsCheckResult.Update(this);
|
|
}
|
|
else
|
|
{
|
|
MoveAndSlide();
|
|
|
|
StairsSystem.DownStairsCheckParams downStairsCheckParams = new StairsSystem.DownStairsCheckParams
|
|
{
|
|
IsOnFloor = IsOnFloor(), // TODO: replace on IsOnFloor Custom
|
|
IsCrouchingHeight = CapsuleCollider.IsCrouchingHeight(),
|
|
LastFrameWasOnFloor = _lastFrameWasOnFloor,
|
|
CapsuleDefaultHeight = CapsuleCollider.GetDefaultHeight(),
|
|
CurrentCapsuleHeight = CapsuleCollider.GetCurrentHeight(),
|
|
FloorMaxAngle = FloorMaxAngle,
|
|
VelocityY = Velocity.Y,
|
|
GlobalTransformFromDriver = GlobalTransform,
|
|
Rid = GetRid()
|
|
};
|
|
|
|
StairsSystem.DownStairsCheckResult downStairsCheckResult = StairsSystem.SnapDownStairsCheck(
|
|
downStairsCheckParams);
|
|
|
|
if (downStairsCheckResult.UpdateIsRequired)
|
|
{
|
|
downStairsCheckResult.Update(this);
|
|
}
|
|
}
|
|
|
|
StairsSystem.SlideCameraParams slideCameraParams = new StairsSystem.SlideCameraParams
|
|
{
|
|
IsCapsuleHeightLessThanNormal = CapsuleCollider.IsCapsuleHeightLessThanNormal(),
|
|
CurrentSpeedGreaterThanWalkSpeed = MoveSystem._currentSpeed > MoveSystem.WalkSpeed,
|
|
BetweenCrouchingAndNormalHeight = CapsuleCollider.IsBetweenCrouchingAndNormalHeight(),
|
|
Delta = (float)delta
|
|
};
|
|
StairsSystem.SlideCameraSmoothBackToOrigin(slideCameraParams);
|
|
}
|
|
|
|
private void CameraModifications(float delta)
|
|
{
|
|
Bobbing.CameraBobbingParams cameraBobbingParams = new Bobbing.CameraBobbingParams
|
|
{
|
|
Delta = delta,
|
|
IsOnFloorCustom = isOnFloorCustom(),
|
|
Velocity = Velocity
|
|
};
|
|
Bobbing.PerformCameraBobbing(cameraBobbingParams);
|
|
|
|
FieldOfView.FovParameters fovParams = new FieldOfView.FovParameters
|
|
{
|
|
IsCrouchingHeight = CapsuleCollider.IsCrouchingHeight(),
|
|
Delta = (float)delta,
|
|
SprintSpeed = MoveSystem.SprintSpeed,
|
|
Velocity = Velocity
|
|
};
|
|
FieldOfView.PerformFovAdjustment(fovParams);
|
|
}
|
|
|
|
///////////////////////////
|
|
// Helpers ////////////////
|
|
///////////////////////////
|
|
public void ReduceTimeScaleWhileAiming()
|
|
{
|
|
Engine.SetTimeScale(TimeScaleAimInAir);
|
|
_timeScaleAimInAirTimer.Start();
|
|
}
|
|
public void ResetTimeScale()
|
|
{
|
|
Engine.SetTimeScale(1);
|
|
}
|
|
|
|
private bool IsHeadTouchingCeiling()
|
|
{
|
|
for (int i = 0; i < NUM_OF_HEAD_COLLISION_DETECTORS; i++)
|
|
{
|
|
if (_headCollisionDetectors[i].IsColliding())
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
private bool isOnFloorCustom()
|
|
{
|
|
return IsOnFloor() || StairsSystem.WasSnappedToStairsLastFrame();
|
|
}
|
|
|
|
public void RotateWeaponWithPlayer()
|
|
{
|
|
WeaponRoot.SetRotation(HeadSystem.Rotation);
|
|
}
|
|
|
|
///////////////////////////
|
|
// Processes //////////////
|
|
///////////////////////////
|
|
public override void _PhysicsProcess(double delta)
|
|
{
|
|
TweenQueueSystem.ProcessTweens();
|
|
|
|
LookAround();
|
|
MoveAround(delta);
|
|
CameraModifications((float) delta);
|
|
HandleStairs((float) delta);
|
|
}
|
|
|
|
}
|