god dayum wall hugging on point man

This commit is contained in:
2025-08-18 14:54:41 +02:00
parent 4f9005d016
commit 5087cb58bc
4 changed files with 305 additions and 225 deletions

View File

@ -55,19 +55,21 @@ AccelerationAir = 2.0
DecelerationAir = 0.1
Weight = 5.0
SimpleJumpStartVelocity = 8.0
SimpleJumpHangTimeInFrames = 3
SimpleJumpHangTimeInFrames = 1
SimpleJumpGravityLesseningFactor = 2.5
DoubleJumpStartVelocity = 15.0
DoubleJumpGravityLesseningFactor = 1.2
DoubleJumpHangTimeInFrames = 3
DoubleJumpGravityLesseningFactor = 1.5
MegaJumpStartVelocity = 30.0
MegaJumpHangTimeInFrames = 15
MegaJumpHangTimeInFrames = 12
MegaJumpGravityLesseningFactor = 1.2
JumpFromDashSpeedFactor = 4.0
WallHugHorizontalDeceleration = 3.0
MaxJumpBoostAfterDashing = 0.7
WallJumpStartVelocity = 8.0
SimpleDashStrength = 15.0
PoweredDashStrength = 50.0
WallHugGravityLesseningFactor = 15.0
WallHugDownwardMaxSpeed = 8.0
WallHugHorizontalDeceleration = 0.5
MaxNumberOfDashActions = 2
PerfectlyTimedActionTimer = 0.3
BasicDashStrength = 15.0
DashTimeDilationCurve = ExtResource("2_2q0ik")
[node name="InputController" type="Node3D" parent="."]
@ -181,8 +183,8 @@ transform = Transform3D(1, 0, 0, 0, 0.173648, -0.984808, 0, 0.984808, 0.173648,
ThrowForce = 15.0
StraightThrowDuration = 0.05
[node name="CoyoteTime" type="Timer" parent="."]
wait_time = 0.2
[node name="DashCooldown" type="Timer" parent="."]
wait_time = 0.5
one_shot = true
[node name="PowerCooldown" type="Timer" parent="."]
@ -194,14 +196,6 @@ wait_time = 2.0
one_shot = true
ignore_time_scale = true
[node name="TimeAfterDashing" type="Timer" parent="."]
wait_time = 0.3
one_shot = true
[node name="EmpowerTimeDownscale" type="Timer" parent="."]
one_shot = true
ignore_time_scale = true
[node name="StateChartDebugger" parent="." instance=ExtResource("24_q5h8a")]
offset_left = 1524.0
offset_top = 1.0
@ -318,25 +312,6 @@ to = NodePath("../../Off")
event = &"empower_released"
delay_in_seconds = "0.0"
[node name="Actions" type="Node" parent="StateChart/Root"]
script = ExtResource("26_infe6")
initial_state = NodePath("Default")
[node name="Default" type="Node" parent="StateChart/Root/Actions"]
script = ExtResource("27_34snm")
[node name="Jumping" type="Node" parent="StateChart/Root/Actions"]
script = ExtResource("27_34snm")
[node name="Dashing" type="Node" parent="StateChart/Root/Actions"]
script = ExtResource("27_34snm")
[node name="Hitting" type="Node" parent="StateChart/Root/Actions"]
script = ExtResource("27_34snm")
[node name="Throwing" type="Node" parent="StateChart/Root/Actions"]
script = ExtResource("27_34snm")
[node name="PowerReserve" type="Node" parent="StateChart/Root"]
script = ExtResource("26_infe6")
initial_state = NodePath("Full")
@ -416,6 +391,11 @@ script = ExtResource("27_34snm")
script = ExtResource("26_infe6")
initial_state = NodePath("Grounded")
[node name="Reset" type="Node" parent="StateChart/Root/Movement"]
script = ExtResource("41_ruloh")
deep = true
default_state = NodePath("../Grounded")
[node name="OnFall" type="Node" parent="StateChart/Root/Movement"]
script = ExtResource("28_n7qhm")
to = NodePath("../Airborne/Falling")
@ -434,22 +414,41 @@ to = NodePath("../OnWall/Hanging")
event = &"dash_to_planted"
delay_in_seconds = "0.0"
[node name="OnDash" type="Node" parent="StateChart/Root/Movement"]
[node name="OnPoweredDash" type="Node" parent="StateChart/Root/Movement"]
script = ExtResource("28_n7qhm")
to = NodePath("../Dashing")
event = &"dash"
to = NodePath("../Dashing/PoweredDash")
event = &"powered_dash"
delay_in_seconds = "0.0"
[node name="Mantling" type="Node" parent="StateChart/Root/Movement"]
script = ExtResource("27_34snm")
[node name="OnMantleFinished" type="Node" parent="StateChart/Root/Movement/Mantling"]
script = ExtResource("28_n7qhm")
to = NodePath("../../Grounded")
event = &"grounded"
delay_in_seconds = "0.0"
[node name="Dashing" type="Node" parent="StateChart/Root/Movement"]
script = ExtResource("27_34snm")
script = ExtResource("26_infe6")
initial_state = NodePath("Dash")
[node name="OnDashEnded" type="Node" parent="StateChart/Root/Movement/Dashing"]
script = ExtResource("28_n7qhm")
to = NodePath("../../Airborne/Reset")
event = &"dash_ended"
event = &"dash_finished"
delay_in_seconds = "0.0"
[node name="Mantling" type="Node" parent="StateChart/Root/Movement"]
[node name="OnMantle" type="Node" parent="StateChart/Root/Movement/Dashing"]
script = ExtResource("28_n7qhm")
to = NodePath("../../Mantling")
event = &"mantle"
delay_in_seconds = "0.0"
[node name="Dash" type="Node" parent="StateChart/Root/Movement/Dashing"]
script = ExtResource("27_34snm")
[node name="PoweredDash" type="Node" parent="StateChart/Root/Movement/Dashing"]
script = ExtResource("27_34snm")
[node name="Jump" type="Node" parent="StateChart/Root/Movement"]
@ -498,6 +497,12 @@ delay_in_seconds = "0.0"
[node name="Grounded" type="Node" parent="StateChart/Root/Movement"]
script = ExtResource("27_34snm")
[node name="OnDash" type="Node" parent="StateChart/Root/Movement/Grounded"]
script = ExtResource("28_n7qhm")
to = NodePath("../../Dashing/Dash")
event = &"dash"
delay_in_seconds = "0.0"
[node name="OnJump" type="Node" parent="StateChart/Root/Movement/Grounded"]
script = ExtResource("28_n7qhm")
to = NodePath("../../Jump/SimpleJump")
@ -524,10 +529,16 @@ initial_state = NodePath("CoyoteEnabled")
script = ExtResource("41_ruloh")
default_state = NodePath("../CoyoteEnabled")
[node name="OnMegajump" type="Node" parent="StateChart/Root/Movement/Airborne"]
[node name="OnWallHug" type="Node" parent="StateChart/Root/Movement/Airborne"]
script = ExtResource("28_n7qhm")
to = NodePath("../../Jump/MegaJump")
event = &"megajump"
to = NodePath("../../OnWall/Hugging")
event = &"wall_hug"
delay_in_seconds = "0.0"
[node name="OnDash" type="Node" parent="StateChart/Root/Movement/Airborne"]
script = ExtResource("28_n7qhm")
to = NodePath("../../Dashing/Dash")
event = &"dash"
delay_in_seconds = "0.0"
[node name="OnGrounded" type="Node" parent="StateChart/Root/Movement/Airborne"]
@ -536,27 +547,21 @@ to = NodePath("../../Grounded")
event = &"grounded"
delay_in_seconds = "0.0"
[node name="OnWallHug" type="Node" parent="StateChart/Root/Movement/Airborne"]
script = ExtResource("28_n7qhm")
to = NodePath("../../OnWall/Hugging")
event = &"wall_hug"
delay_in_seconds = "0.0"
[node name="CoyoteEnabled" type="Node" parent="StateChart/Root/Movement/Airborne"]
script = ExtResource("27_34snm")
[node name="OnMegajump" type="Node" parent="StateChart/Root/Movement/Airborne/CoyoteEnabled"]
script = ExtResource("28_n7qhm")
to = NodePath("../../../Jump/MegaJump")
event = &"megajump"
delay_in_seconds = "0.0"
[node name="OnJump" type="Node" parent="StateChart/Root/Movement/Airborne/CoyoteEnabled"]
script = ExtResource("28_n7qhm")
to = NodePath("../../../Jump/SimpleJump")
event = &"jump"
delay_in_seconds = "0.0"
[node name="OnMegajump" type="Node" parent="StateChart/Root/Movement/Airborne/CoyoteEnabled"]
script = ExtResource("28_n7qhm")
to = NodePath("../../Falling")
event = &"megajump"
delay_in_seconds = "0.0"
[node name="OnExpiration" type="Node" parent="StateChart/Root/Movement/Airborne/CoyoteEnabled"]
script = ExtResource("28_n7qhm")
to = NodePath("../../DoubleJumpEnabled")
@ -566,18 +571,18 @@ delay_in_seconds = "0.0"
[node name="DoubleJumpEnabled" type="Node" parent="StateChart/Root/Movement/Airborne"]
script = ExtResource("27_34snm")
[node name="OnMegajump" type="Node" parent="StateChart/Root/Movement/Airborne/DoubleJumpEnabled"]
script = ExtResource("28_n7qhm")
to = NodePath("../../../Jump/MegaJump")
event = &"megajump"
delay_in_seconds = "0.0"
[node name="OnJump" type="Node" parent="StateChart/Root/Movement/Airborne/DoubleJumpEnabled"]
script = ExtResource("28_n7qhm")
to = NodePath("../../../Jump/DoubleJump")
event = &"jump"
delay_in_seconds = "0.0"
[node name="OnDash" type="Node" parent="StateChart/Root/Movement/Airborne/DoubleJumpEnabled"]
script = ExtResource("28_n7qhm")
to = NodePath("../../Falling")
event = &"dash"
delay_in_seconds = "0.0"
[node name="Falling" type="Node" parent="StateChart/Root/Movement/Airborne"]
script = ExtResource("27_34snm")
@ -591,12 +596,24 @@ delay_in_seconds = "0.0"
script = ExtResource("26_infe6")
initial_state = NodePath("Hugging")
[node name="OnGrounded" type="Node" parent="StateChart/Root/Movement/OnWall"]
script = ExtResource("28_n7qhm")
to = NodePath("../../Grounded")
event = &"grounded"
delay_in_seconds = "0.0"
[node name="OnJump" type="Node" parent="StateChart/Root/Movement/OnWall"]
script = ExtResource("28_n7qhm")
to = NodePath("../../Airborne/DoubleJumpEnabled")
to = NodePath("../../Jump/DoubleJump")
event = &"jump"
delay_in_seconds = "0.0"
[node name="OnMegajump" type="Node" parent="StateChart/Root/Movement/OnWall"]
script = ExtResource("28_n7qhm")
to = NodePath("../../Jump/MegaJump")
event = &"megajump"
delay_in_seconds = "0.0"
[node name="HugCanceled" type="Node" parent="StateChart/Root/Movement/OnWall"]
script = ExtResource("27_34snm")
@ -609,6 +626,12 @@ delay_in_seconds = "0.0"
[node name="Hugging" type="Node" parent="StateChart/Root/Movement/OnWall"]
script = ExtResource("27_34snm")
[node name="OnGrounded" type="Node" parent="StateChart/Root/Movement/OnWall/Hugging"]
script = ExtResource("28_n7qhm")
to = NodePath("../../../Grounded")
event = &"grounded"
delay_in_seconds = "0.0"
[node name="OnLeaveWall" type="Node" parent="StateChart/Root/Movement/OnWall/Hugging"]
script = ExtResource("28_n7qhm")
to = NodePath("../../../Airborne/CoyoteEnabled")
@ -645,3 +668,4 @@ delay_in_seconds = "0.0"
[connection signal="input_rotate_floorplane" from="InputController" to="." method="OnInputRotateFloorplane"]
[connection signal="input_rotate_y" from="InputController" to="." method="OnInputRotateY"]
[connection signal="input_throw" from="InputController" to="." method="OnInputThrowPressed"]
[connection signal="WallDetected" from="WallHugSystem" to="." method="OnWallDetected"]

View File

@ -1,6 +1,7 @@
using System;
using Godot;
using GodotStateCharts;
using Movementtests.addons.godot_state_charts.csharp;
using Movementtests.systems;
using Movementtests.player_controller.Scripts;
using RustyOptions;
@ -49,11 +50,9 @@ public partial class PlayerController : CharacterBody3D
private float _inputRotateFloorplane;
// Timers
private Timer _coyoteTimer;
private Timer _timeScaleAimInAirTimer;
private Timer _timeAfterDashingTimer;
private Timer _simpleDashCooldownTimer;
private Timer _powerCooldownTimer;
private Timer _empowerTimeDownscale;
[ExportCategory("Movement")]
[ExportGroup("Ground")]
@ -72,7 +71,9 @@ public partial class PlayerController : CharacterBody3D
public float Weight { get; set; } = 3.0f;
// Jump
[ExportGroup("Jump")]
[ExportGroup("Jump")]
[Export(PropertyHint.Range, "0,1,0.01")]
public float CoyoteTime { get; set; } = 0.2f;
// Simple jump
[ExportSubgroup("Simple jump")]
@ -103,45 +104,48 @@ public partial class PlayerController : CharacterBody3D
[Export(PropertyHint.Range, "1,10,0.1,or_greater")]
public float MegaJumpGravityLesseningFactor { get; set; } = 3f;
// Other jump
[ExportSubgroup("Other jump")]
[Export(PropertyHint.Range, "0,2,0.01,or_greater")]
public float StartVelocity { get; set; } = 1.0f;
[Export(PropertyHint.Range, "0.1,10,0.1,or_greater")]
public float DoubleJumpSpeedFactor { get; set; } = 2f;
[Export(PropertyHint.Range, "0.1,10,0.1,or_greater")]
public float JumpFromDashSpeedFactor { get; set; } = 2f;
[Export(PropertyHint.Range, "0.1,10,0.1,or_greater")]
public float JumpFromWallSpeedFactor { get; set; } = 2f;
[ExportGroup("WallHug")]
[Export(PropertyHint.Range, "0.1,10,0.1,or_greater")]
public float WallHugDownwardSpeed { get; set; } = 2f;
// Wall jump
[ExportSubgroup("Wall jump")]
[Export(PropertyHint.Range, "0,100,1,or_greater")]
public float WallJumpStartVelocity { get; set; } = 10.0f;
[Export(PropertyHint.Range, "0,100,1,or_greater")]
public float WallMegajumpStartVelocity { get; set; } = 20.0f;
// Dash
[ExportGroup("Dash")]
// Simple dash
[ExportSubgroup("Simple")]
[Export(PropertyHint.Range, "0,50,0.1")]
public float SimpleDashStrength { get; set; } = 10f;
// Powered Dash
[ExportSubgroup("Powered")]
[Export(PropertyHint.Range, "0,1,0.01,or_greater")]
public float PoweredDashTime { get; set; } = 0.3f;
[Export(PropertyHint.Range, "0,100,0.1")]
public float PoweredDashStrength { get; set; } = 10f;
// Wall hug
[ExportGroup("Wall hug")]
[Export(PropertyHint.Range, "0,50,0.1,or_greater")]
public float WallHugGravityLesseningFactor { get; set; } = 2f;
[Export(PropertyHint.Range, "0.1,50,0.1,or_greater")]
public float WallHugDownwardMaxSpeed { get; set; } = 2f;
[Export(PropertyHint.Range, "0.1,10,0.1,or_greater")]
public float WallHugHorizontalDeceleration { get; set; } = 5f;
private float _targetSpeed;
private float _gravity;
[ExportCategory("Other")]
[Export(PropertyHint.Range, "0,1,0.01,or_greater")]
public float TimeScaleAimInAir { get; set; } = 0.05f;
[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;
[Export(PropertyHint.Range, "0,200,1,or_greater")]
public int DashIndicatorStartSize { get; set; } = 100;
[Export(PropertyHint.Range, "0,1,0.01")]
public float PerfectlyTimedActionTimer { get; set; } = 0.8f;
[Export(PropertyHint.Range, "0,50,0.1")]
public float BasicDashStrength { get; set; } = 10f;
[Export]
public Curve DashTimeDilationCurve { get; set; }
private bool _canDash = true;
private bool _isDashOnCooldown = false;
private int _empoweredActionsLeft;
public int EmpoweredActionsLeft
{
@ -160,7 +164,6 @@ public partial class PlayerController : CharacterBody3D
private StateChartState _weaponInHand;
private StateChartState _aiming;
private StateChartState _dashing;
private StateChartState _weaponThrown;
private StateChartState _actionHanging;
private StateChartState _empowerOn;
@ -177,6 +180,8 @@ public partial class PlayerController : CharacterBody3D
private StateChartState _simpleJump;
private StateChartState _doubleJump;
private StateChartState _megaJump;
private StateChartState _simpleDash;
private StateChartState _poweredDash;
private StateChartState _doubleJumpEnabled;
private StateChartState _onWall;
private StateChartState _onWallHugCanceled;
@ -184,6 +189,9 @@ public partial class PlayerController : CharacterBody3D
private StateChartState _onWallHanging;
private StateChartState _falling;
private Transition _onJumpFromWall;
private Transition _onMegajumpFromWall;
public override void _Ready()
{
///////////////////////////
@ -240,7 +248,8 @@ public partial class PlayerController : CharacterBody3D
_weaponInHand = StateChartState.Of(GetNode("StateChart/Root/WeaponState/InHand"));
_weaponThrown = StateChartState.Of(GetNode("StateChart/Root/WeaponState/Flying"));
_aiming = StateChartState.Of(GetNode("StateChart/Root/Aim/On"));
_dashing = StateChartState.Of(GetNode("StateChart/Root/Movement/Dashing"));
_simpleDash = StateChartState.Of(GetNode("StateChart/Root/Movement/Dashing/Dash"));
_poweredDash = StateChartState.Of(GetNode("StateChart/Root/Movement/Dashing/PoweredDash"));
// _actionHanging = StateChartState.Of(GetNode("StateChart/Root/Actions/Hanging"));
_empowerOn = StateChartState.Of(GetNode("StateChart/Root/Empower/On"));
_empowerOff = StateChartState.Of(GetNode("StateChart/Root/Empower/Off"));
@ -257,17 +266,17 @@ public partial class PlayerController : CharacterBody3D
_doubleJump = StateChartState.Of(GetNode("StateChart/Root/Movement/Jump/DoubleJump"));
_megaJump = StateChartState.Of(GetNode("StateChart/Root/Movement/Jump/MegaJump"));
_doubleJumpEnabled = StateChartState.Of(GetNode("StateChart/Root/Movement/Airborne/DoubleJumpEnabled"));
_falling = StateChartState.Of(GetNode("StateChart/Root/Movement/Airborne/Falling"));
_onWall = StateChartState.Of(GetNode("StateChart/Root/Movement/OnWall"));
_onJumpFromWall = Transition.Of(GetNode("StateChart/Root/Movement/OnWall/OnJump"));
_onMegajumpFromWall = Transition.Of(GetNode("StateChart/Root/Movement/OnWall/OnMegajump"));
_onWallHugging = StateChartState.Of(GetNode("StateChart/Root/Movement/OnWall/Hugging"));
_onWallHugCanceled = StateChartState.Of(GetNode("StateChart/Root/Movement/OnWall/HugCanceled"));
_onWallHanging = StateChartState.Of(GetNode("StateChart/Root/Movement/OnWall/Hanging"));
_falling = StateChartState.Of(GetNode("StateChart/Root/Movement/Airborne/Falling"));
// State timers
_coyoteTimer = GetNode<Timer>("CoyoteTime");
_powerCooldownTimer = GetNode<Timer>("PowerCooldown");
_timeScaleAimInAirTimer = GetNode<Timer>("TimeScaleAimInAir");
_timeAfterDashingTimer = GetNode<Timer>("TimeAfterDashing");
_empowerTimeDownscale = GetNode<Timer>("EmpowerTimeDownscale");
_simpleDashCooldownTimer = GetNode<Timer>("DashCooldown");
///////////////////////////
// Initialize components //
@ -308,10 +317,6 @@ public partial class PlayerController : CharacterBody3D
///////////////////////////
// Signal setup ///////////
///////////////////////////
DashSystem.DashEnded += OnDashEnded;
DashSystem.DashProgress += OnDashProgress;
_weaponInHand.StateProcessing += HandleWeaponInHand;
_aiming.StateProcessing += HandleAiming;
_aiming.StateEntered += OnAimingEntered;
@ -321,22 +326,12 @@ public partial class PlayerController : CharacterBody3D
_grounded.StateEntered += OnGrounded;
_grounded.StatePhysicsProcessing += HandleGrounded;
_airborne.StatePhysicsProcessing += HandleAirborne;
_onWallHugCanceled.StatePhysicsProcessing += HandleAirborne;
_onWallHugging.StatePhysicsProcessing += HandleWallHugging;
_onWallHanging.StatePhysicsProcessing += HandleWallHanging;
_coyoteEnabled.StateEntered += StartCoyoteTime;
_coyoteTimer.Timeout += CoyoteExpired;
_timeScaleAimInAirTimer.Timeout += ResetTimeScale;
_dashing.StatePhysicsProcessing += Dashing;
// _weaponThrown.StateEntered += OnWeaponThrown;
// _empowerOn.StateEntered += OnEmpowerStarted;
// _empowerOn.StateProcessing += HandleEmpower;
// _empowerOff.StateEntered += EmpowerStopped;
// _empowerTimeDownscale.Timeout += EmpowerTimerTimeout;
_powerFull.StateEntered += StopPowerCooldown;
_powerFull.StateExited += StartPowerCooldown;
_powerRecharging.StateEntered += StartPowerCooldown;
@ -352,13 +347,43 @@ public partial class PlayerController : CharacterBody3D
_megaJump.StateEntered += OnMegaJumpStarted;
_megaJump.StatePhysicsProcessing += HandleMegaJump;
_simpleDash.StateEntered += OnSimpleDashStarted;
_simpleDash.StatePhysicsProcessing += HandleSimpleDash;
_poweredDash.StateEntered += OnPoweredDashStarted;
_poweredDash.StatePhysicsProcessing += HandlePoweredDash;
_poweredDash.StateExited += OnPoweredDashFinished;
_simpleDashCooldownTimer.Timeout += DashCooldownTimeout;
_onWallHugCanceled.StatePhysicsProcessing += HandleAirborne;
_onWallHugging.StatePhysicsProcessing += HandleWallHugging;
_onWallHanging.StatePhysicsProcessing += HandleWallHanging;
_onJumpFromWall.Taken += OnJumpFromWall;
_onMegajumpFromWall.Taken += OnMegajumpFromWall;
}
public void OnWallDetected()
{
FinishPoweredDash();
}
public void OnGrounded()
{
_isWallJumpAvailable = true;
if (_simpleDashCooldownTimer.IsStopped())
_simpleDashCooldownTimer.Start();
}
public void DashCooldownTimeout()
{
_canDash = true;
}
// Physics processes
public void HandleGrounded(float delta)
{
MoveOnGround(delta);
_canDash = true;
if (!isOnFloorCustom())
_playerState.SendEvent("start_falling");
}
@ -378,7 +403,6 @@ public partial class PlayerController : CharacterBody3D
if (!WallHugSystem.IsWallHugging())
_playerState.SendEvent("start_falling");
}
public void HandleWallHanging(float delta)
{
WallHang(delta);
@ -448,21 +472,57 @@ public partial class PlayerController : CharacterBody3D
}
public void OnMegaJumpStarted()
{
PerformEmpoweredAction();
OnJumpStarted(MegaJumpStartVelocity);
}
public Vector3 ComputeHVelocity(float delta, float accelerationFactor, float decelerationFactor)
public void WallHug(float delta)
{
Vector3 direction = HeadSystem.Transform.Basis * _inputMove;
var acceleration = direction.Length() > 0 ? accelerationFactor : decelerationFactor;
var hvel = ComputeHVelocity(delta, WallHugHorizontalDeceleration, WallHugHorizontalDeceleration);
var vvel = Velocity.Y - (CalculateGravityForce() * delta / WallHugGravityLesseningFactor);
vvel = Math.Abs(vvel) > WallHugDownwardMaxSpeed ? -WallHugDownwardMaxSpeed : vvel;
Velocity = hvel + vvel*Vector3.Up;
}
public void WallHang(float delta)
{
Velocity = Vector3.Zero;
MoveAndSlide();
}
public void ComputeJumpFromWallHSpeed(float jumpStrength)
{
// if (!_isWallJumpAvailable)
// return;
// _isWallJumpAvailable = false;
// var isLookingTowardsWall = HeadSystem.GetForwardHorizontalVector().Dot(wallNormal) > 0.5;
// var jumpDirection = isLookingTowardsWall ? Vector3.Up : wallNormal;
var wallNormal = WallHugSystem.GetWallNormal().UnwrapOr(Vector3.Up);
var jumpVector = wallNormal * jumpStrength;
SetHorizontalVelocity(new Vector2(jumpVector.X, jumpVector.Z));
}
public void OnJumpFromWall()
{
ComputeJumpFromWallHSpeed(WallJumpStartVelocity);
}
public void OnMegajumpFromWall()
{
ComputeJumpFromWallHSpeed(WallMegajumpStartVelocity);
}
public Vector3 ComputeHVelocity(float delta, float accelerationFactor, float decelerationFactor, Vector3? direction = null)
{
var dir = direction ?? HeadSystem.Transform.Basis * _inputMove;
var acceleration = dir.Length() > 0 ? accelerationFactor : decelerationFactor;
float xAcceleration = Mathf.Lerp(Velocity.X, direction.X * _targetSpeed, delta * acceleration);
float zAcceleration = Mathf.Lerp(Velocity.Z, direction.Z * _targetSpeed, delta * acceleration);
float xAcceleration = Mathf.Lerp(Velocity.X, dir.X * _targetSpeed, delta * acceleration);
float zAcceleration = Mathf.Lerp(Velocity.Z, dir.Z * _targetSpeed, delta * acceleration);
return new Vector3(xAcceleration, 0, zAcceleration);
}
public Vector3 ComputeHVelocityGround(float delta)
{
return ComputeHVelocity(delta, AccelerationFloor, DecelerationFloor);
}
public Vector3 ComputeHVelocityAir(float delta)
@ -477,6 +537,13 @@ public partial class PlayerController : CharacterBody3D
y: verticalVelocity,
z: Velocity.Z);
}
public void SetHorizontalVelocity(Vector2 velocity)
{
Velocity = new Vector3(
x: velocity.X,
y: Velocity.Y,
z: velocity.Y);
}
public void HandleJump(float delta, float gravityFactor, int hangFrames)
{
@ -528,19 +595,16 @@ public partial class PlayerController : CharacterBody3D
var progress = (float) (_powerCooldownTimer.TimeLeft / _powerCooldownTimer.WaitTime);
PowerCooldownIndicator.SetSize(new Vector2(100 * progress, 10));
}
public void StartPowerCooldown()
{
_powerCooldownTimer.Start();
PowerCooldownIndicator.Visible = true;
}
public void StopPowerCooldown()
{
_powerCooldownTimer.Stop();
PowerCooldownIndicator.Visible = false;
}
public void PowerCooldownExpired()
{
EmpoweredActionsLeft += 1;
@ -563,7 +627,6 @@ public partial class PlayerController : CharacterBody3D
{
_inputRotateFloorplane = value;
}
public void OnInputAimPressed()
{
_playerState.SendEvent("aim_pressed");
@ -592,11 +655,6 @@ public partial class PlayerController : CharacterBody3D
OnWeaponThrown();
}
}
public void OnInputDashPressed()
{
_playerState.SendEvent("dash");
PerformDash(_empowerOn.Active);
}
public void OnInputEmpowerDown()
{
_playerState.SendEvent("empower_down");
@ -606,43 +664,69 @@ public partial class PlayerController : CharacterBody3D
_playerState.SendEvent("empower_released");
}
public void PerformDash(bool isEmpowered)
public void OnInputDashPressed()
{
if (_aiming.Active)
{
OnDashStarted();
return;
}
if (!_canDash)
return;
_canDash = false;
var dashStrength = BasicDashStrength;
if (isEmpowered && CanPerformEmpoweredAction())
if (_empowerOn.Active && CanPerformEmpoweredAction())
{
PerformEmpoweredAction();
dashStrength *= 2.5f;
_playerState.SendEvent("powered_dash");
return;
}
_playerState.SendEvent("dash");
}
public void OnSimpleDashStarted()
{
if (!_canDash)
return;
_canDash = false;
var dashStrength = SimpleDashStrength;
var direction = GetInputGlobalHDirection();
SetVelocity(direction * dashStrength);
}
public void HandleSimpleDash(float delta)
{
_playerState.SendEvent("dash_finished");
}
public Vector3 GetInputGlobalHDirection()
{
var direction = HeadSystem.Transform.Basis * _inputMove;
var planarDirection = new Vector3(direction.X, 0, direction.Z).Normalized();
SetVelocity(planarDirection * dashStrength);
return new Vector3(direction.X, 0, direction.Z).Normalized();
}
public void Dashing(float delta)
public Vector3 GetInputLocalHDirection()
{
_playerState.SendEvent("dash_ended");
var direction = _inputMove;
return new Vector3(direction.X, 0, direction.Z).Normalized();
}
///////////////////////////
// Stateful logic /////////
///////////////////////////
public void OnGrounded()
public void OnPoweredDashStarted()
{
_isWallJumpAvailable = true;
Velocity = GetInputGlobalHDirection() * PoweredDashStrength;
GetTree().CreateTimer(PoweredDashTime).Timeout += FinishPoweredDash;
}
public void OnPoweredDashFinished()
{
// Try mantling here
}
public void FinishPoweredDash()
{
_playerState.SendEvent("dash_finished");
}
public void HandlePoweredDash(float delta)
{
var collision = MoveAndCollide(Velocity * delta, maxCollisions: 10);
if (collision != null)
{
FinishPoweredDash();
}
}
public bool CanPerformEmpoweredAction()
@ -660,7 +744,7 @@ public partial class PlayerController : CharacterBody3D
// Jumping
public void StartCoyoteTime()
{
_coyoteTimer.Start();
GetTree().CreateTimer(CoyoteTime).Timeout += CoyoteExpired;
}
public void CoyoteExpired()
{
@ -699,25 +783,7 @@ public partial class PlayerController : CharacterBody3D
public void Jump(JumpTypes jumpType, Vector3? jumpDirection = null, float boost = 1.0f)
{
var effectiveJumpDirection = jumpDirection ?? Vector3.Up;
var jumpForce = 0.0f;
switch (jumpType)
{
case JumpTypes.DoubleJump:
jumpForce = CalculateDoubleJumpForce();
break;
case JumpTypes.SimpleJump:
jumpForce = CalculateJumpForce();
break;
case JumpTypes.JumpFromDash:
jumpForce = CalculateJumpFromDashForce();
break;
case JumpTypes.JumpFromWall:
jumpForce = CalculateJumpFromWallForce();
break;
default:
jumpForce = CalculateJumpForce();
break;
}
var jumpForce = 100.0f;
var currentHorizontalVelocity = new Vector3(Velocity.X, 0, Velocity.Z);
var jumpVelocity = jumpForce * effectiveJumpDirection * boost;
@ -769,7 +835,6 @@ public partial class PlayerController : CharacterBody3D
}
PerformEmpoweredAction();
_timeAfterDashingTimer.Start();
if (WeaponSystem.FlyingState.Active)
{
DashSystem.ShouldMantle = false;
@ -794,17 +859,6 @@ public partial class PlayerController : CharacterBody3D
_dashDirection = (DashSystem.PlannedPlayerLocation - GlobalPosition).Normalized();
DashSystem.Dash();
}
public void OnDashProgress(float progress)
{
return;
Engine.SetTimeScale(DashTimeDilationCurve.Sample(progress));
DashIndicator.SetCustomMinimumSize(Vector2.One * DashIndicatorStartSize * (1 - progress));
var indicatorColor = progress < PerfectlyTimedActionTimer ? new Color(1, 1, 1) : new Color(0, 1, 0);
DashIndicator.SetModulate(indicatorColor);
}
public void OnDashEnded()
{
// Regular dash
@ -911,25 +965,7 @@ public partial class PlayerController : CharacterBody3D
var verticalVelocity = Velocity.Y - (CalculateGravityForce() * (float)delta);
Velocity = new Vector3(horizontalVelocity.X, verticalVelocity, horizontalVelocity.Z);
}
public void WallHug(float delta)
{
float xAcceleration = Mathf.Lerp(Velocity.X, 0,
(float)delta * WallHugHorizontalDeceleration);
float zAcceleration = Mathf.Lerp(Velocity.Z, 0,
(float)delta * WallHugHorizontalDeceleration);
Velocity = new Vector3(
x: xAcceleration,
y: -WallHugDownwardSpeed,
z: zAcceleration);
}
public void WallHang(float delta)
{
Velocity = Vector3.Zero;
MoveAndSlide();
}
private void HandleStairs(float delta)
{
StairsSystem.UpStairsCheckParams upStairsCheckParams = new StairsSystem.UpStairsCheckParams
@ -1011,10 +1047,6 @@ public partial class PlayerController : CharacterBody3D
// Helpers ////////////////
///////////////////////////
public float CalculateJumpForce() => _gravity * StartVelocity;
public float CalculateJumpFromDashForce() => CalculateJumpForce() * JumpFromDashSpeedFactor;
public float CalculateJumpFromWallForce() => CalculateJumpForce() * JumpFromWallSpeedFactor;
public float CalculateDoubleJumpForce() => CalculateJumpForce() * DoubleJumpSpeedFactor;
public float CalculateGravityForce() => _gravity * Weight;
public void ReduceTimeScaleWhileAiming()