Compare commits

...

8 Commits

Author SHA1 Message Date
66be7838bb buffered inputs revamped and added mantle jumps and dashed
All checks were successful
Create tag and build when new code gets to main / BumpTag (push) Successful in 21s
Create tag and build when new code gets to main / Export (push) Successful in 10m30s
2026-01-11 18:14:53 +01:00
1eb65d1520 some shader work and improved mantle feel 2026-01-11 17:09:58 +01:00
f2a39316ba shader changes that don't do anything
All checks were successful
Create tag and build when new code gets to main / BumpTag (push) Successful in 19s
Create tag and build when new code gets to main / Export (push) Successful in 9m48s
2026-01-07 17:11:49 +01:00
fffd8c947b implementing jump input buffering on grounded
All checks were successful
Create tag and build when new code gets to main / BumpTag (push) Successful in 18s
Create tag and build when new code gets to main / Export (push) Successful in 9m47s
2026-01-07 09:58:18 +01:00
a1d57d6a1a some tuto fixing
All checks were successful
Create tag and build when new code gets to main / BumpTag (push) Successful in 19s
Create tag and build when new code gets to main / Export (push) Successful in 9m49s
2026-01-06 16:35:17 +01:00
941205af2b small gravity and jump balancing, removed wall jumping coyote times
All checks were successful
Create tag and build when new code gets to main / BumpTag (push) Successful in 19s
Create tag and build when new code gets to main / Export (push) Successful in 9m34s
2026-01-06 16:08:39 +01:00
6c2ad89687 fixing the manlting into geo
All checks were successful
Create tag and build when new code gets to main / BumpTag (push) Successful in 19s
Create tag and build when new code gets to main / Export (push) Successful in 9m42s
2026-01-06 12:36:38 +01:00
59494f9e98 updating CI to build for linux as well
All checks were successful
Create tag and build when new code gets to main / BumpTag (push) Successful in 19s
Create tag and build when new code gets to main / Export (push) Successful in 9m34s
2025-12-25 09:37:51 +01:00
17 changed files with 826 additions and 655 deletions

View File

@@ -54,27 +54,12 @@ jobs:
- name: Import resources and build solution - name: Import resources and build solution
run: | run: |
godot --headless --editor --build-solutions --quit --import --path $PWD godot --headless --editor --build-solutions --quit --import --path $PWD
- name: Build Windows - name: Build Windows
run: | run: |
mkdir -v -p build/windows mkdir -v -p build/windows
godot --headless --verbose --build-solutions --export-release "Windows Desktop" build/windows/${{ env.GAME_NAME }}.exe godot --headless --verbose --build-solutions --export-release "Windows Desktop" build/windows/${{ env.GAME_NAME }}.exe
zip -r Windows.zip build/windows zip -r Windows.zip build/windows
- name: Build Windows ARM
run: |
mkdir -v -p build/windowsArm
godot --headless --verbose --build-solutions --export-release "Windows ARM" build/windowsArm/${{ env.GAME_NAME }}.exe
zip -r WindowsArm.zip build/windowsArm
# - name: Linux Build
# run: |
# mkdir -v -p build/linux
# godot --headless --verbose --export-release "Linux/X11" build/linux/${{ env.GAME_NAME }}.x86_64
# zip -r Linux.zip build/linux
- name: Mac Build
run: |
mkdir -v -p build/mac
godot --headless --verbose --export-release "macOS" build/mac/${{ env.GAME_NAME }}.zip
zip -r Mac.zip build/mac
- name: Upload to Itch - name: Upload to Itch
uses: KikimoraGames/itch-publish@v0.0.3 uses: KikimoraGames/itch-publish@v0.0.3
with: with:
@@ -84,6 +69,12 @@ jobs:
buildNumber: ${{ needs.BumpTag.outputs.tag_name }} buildNumber: ${{ needs.BumpTag.outputs.tag_name }}
gameData: Windows.zip gameData: Windows.zip
buildChannel: windows buildChannel: windows
- name: Build Windows ARM
run: |
mkdir -v -p build/windowsArm
godot --headless --verbose --build-solutions --export-release "Windows ARM" build/windowsArm/${{ env.GAME_NAME }}.exe
zip -r WindowsArm.zip build/windowsArm
- name: Upload to Itch - name: Upload to Itch
uses: KikimoraGames/itch-publish@v0.0.3 uses: KikimoraGames/itch-publish@v0.0.3
with: with:
@@ -93,15 +84,27 @@ jobs:
buildNumber: ${{ needs.BumpTag.outputs.tag_name }} buildNumber: ${{ needs.BumpTag.outputs.tag_name }}
gameData: WindowsArm.zip gameData: WindowsArm.zip
buildChannel: windows-arm buildChannel: windows-arm
# - name: Upload to Itch
# uses: KikimoraGames/itch-publish@v0.0.3 - name: Linux Build
# with: run: |
# butlerApiKey: ${{ secrets.BUTLER_TOKEN }} mkdir -v -p build/linux
# itchUsername: ${{ env.ITCHIO_USERNAME }} godot --headless --verbose --export-release "Linux/X11" build/linux/${{ env.GAME_NAME }}.x86_64
# itchGameId: ${{ env.ITCHIO_GAMEID }} zip -r Linux.zip build/linux
# buildNumber: ${{ needs.BumpTag.outputs.tag_name }} - name: Upload to Itch
# gameData: Linux.zip uses: KikimoraGames/itch-publish@v0.0.3
# buildChannel: linux with:
butlerApiKey: ${{ secrets.BUTLER_TOKEN }}
itchUsername: ${{ env.ITCHIO_USERNAME }}
itchGameId: ${{ env.ITCHIO_GAMEID }}
buildNumber: ${{ needs.BumpTag.outputs.tag_name }}
gameData: Linux.zip
buildChannel: linux
- name: Mac Build
run: |
mkdir -v -p build/mac
godot --headless --verbose --export-release "macOS" build/mac/${{ env.GAME_NAME }}.zip
zip -r Mac.zip build/mac
- name: Upload to Itch - name: Upload to Itch
uses: KikimoraGames/itch-publish@v0.0.3 uses: KikimoraGames/itch-publish@v0.0.3
with: with:

1
.gitignore vendored
View File

@@ -10,6 +10,7 @@
.import/ .import/
/builds /builds
/communication
# Imported translations (automatically generated from CSV files) # Imported translations (automatically generated from CSV files)
*.translation *.translation

Binary file not shown.

File diff suppressed because it is too large Load Diff

View File

@@ -27,7 +27,7 @@ shader_parameter/floorRoughnessMap = ExtResource("4_rir86")
shader_parameter/floorNormalMap = ExtResource("3_f1b6h") shader_parameter/floorNormalMap = ExtResource("3_f1b6h")
shader_parameter/floorHeightMap = ExtResource("2_0e3id") shader_parameter/floorHeightMap = ExtResource("2_0e3id")
shader_parameter/floorUvScale = 0.5 shader_parameter/floorUvScale = 0.5
shader_parameter/enablePom = true shader_parameter/enablePom = false
shader_parameter/heightMinLayers = 8 shader_parameter/heightMinLayers = 8
shader_parameter/heightMaxLayers = 64 shader_parameter/heightMaxLayers = 64
shader_parameter/heightScale = 0.08 shader_parameter/heightScale = 0.08

View File

@@ -28,6 +28,7 @@ uniform float heightScale = 1.0;
varying vec3 worldPos; varying vec3 worldPos;
varying vec3 worldNormal; varying vec3 worldNormal;
varying vec3 diffuse;
void vertex() { void vertex() {
@@ -177,12 +178,14 @@ void fragment() {
// sample and output // sample and output
SPECULAR = specular; SPECULAR = specular;
ALBEDO = triplanarSample(texCoordX, texCoordY, texCoordZ, blend, yDot).rgb; ALBEDO = triplanarSample(texCoordX, texCoordY, texCoordZ, blend, yDot).rgb;
diffuse = ALBEDO;
ROUGHNESS = triplanarRoughness(texCoordX, texCoordY, texCoordZ, blend, yDot).r; ROUGHNESS = triplanarRoughness(texCoordX, texCoordY, texCoordZ, blend, yDot).r;
NORMAL = mix(worldNormal, triplanarNormal(yDot, texCoordX, texCoordY, texCoordZ, blend), normalMapStrength); NORMAL = mix(worldNormal, triplanarNormal(yDot, texCoordX, texCoordY, texCoordZ, blend), normalMapStrength);
NORMAL = normalize((VIEW_MATRIX * vec4(NORMAL, 0.0)).xyz); NORMAL = normalize((VIEW_MATRIX * vec4(NORMAL, 0.0)).xyz);
} }
//void light() { void light() {
// // Called for every pixel for every light affecting the material. float lambert = clamp(dot(NORMAL, LIGHT), 0.0, 1.0);
// // Uncomment to replace the default light processing function with this one. float halfLambert = pow(lambert*0.5 + 0.5, 5);
//} DIFFUSE_LIGHT += halfLambert * ATTENUATION * LIGHT_COLOR / PI;
}

View File

@@ -31,7 +31,7 @@ shader_parameter/floorRoughnessMap = ExtResource("4_4vhk1")
shader_parameter/floorNormalMap = ExtResource("3_ytvoj") shader_parameter/floorNormalMap = ExtResource("3_ytvoj")
shader_parameter/floorHeightMap = ExtResource("2_4vhk1") shader_parameter/floorHeightMap = ExtResource("2_4vhk1")
shader_parameter/floorUvScale = 0.5 shader_parameter/floorUvScale = 0.5
shader_parameter/enablePom = true shader_parameter/enablePom = false
shader_parameter/heightMinLayers = 8 shader_parameter/heightMinLayers = 8
shader_parameter/heightMaxLayers = 64 shader_parameter/heightMaxLayers = 64
shader_parameter/heightScale = 0.2 shader_parameter/heightScale = 0.2

View File

@@ -27,7 +27,7 @@ shader_parameter/floorRoughnessMap = ExtResource("4_ob11h")
shader_parameter/floorNormalMap = ExtResource("3_ff2cr") shader_parameter/floorNormalMap = ExtResource("3_ff2cr")
shader_parameter/floorHeightMap = ExtResource("2_roy1o") shader_parameter/floorHeightMap = ExtResource("2_roy1o")
shader_parameter/floorUvScale = 0.5 shader_parameter/floorUvScale = 0.5
shader_parameter/enablePom = true shader_parameter/enablePom = false
shader_parameter/heightMinLayers = 8 shader_parameter/heightMinLayers = 8
shader_parameter/heightMaxLayers = 64 shader_parameter/heightMaxLayers = 64
shader_parameter/heightScale = 1.0 shader_parameter/heightScale = 1.0

Binary file not shown.

Binary file not shown.

View File

@@ -567,6 +567,12 @@ use_collision = true
size = Vector3(3, 1, 0.25) size = Vector3(3, 1, 0.25)
material = ExtResource("3_vvhq3") material = ExtResource("3_vvhq3")
[node name="CSGBox3D57" type="CSGBox3D" parent="Greybox/Mantles"]
transform = Transform3D(-4.371139e-08, 0, -1, 0, 1, 0, 1, 0, -4.371139e-08, -13, 3.5, -21.629175)
use_collision = true
size = Vector3(5, 1, 0.25)
material = ExtResource("3_vvhq3")
[node name="CSGBox3D54" type="CSGBox3D" parent="Greybox/Mantles"] [node name="CSGBox3D54" type="CSGBox3D" parent="Greybox/Mantles"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -8.5, 1, 20.125) transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -8.5, 1, 20.125)
use_collision = true use_collision = true

View File

@@ -102,6 +102,7 @@ player = NodePath("../Player")
pause = ExtResource("10_0ari0") pause = ExtResource("10_0ari0")
[node name="TutorialController" type="Control" parent="."] [node name="TutorialController" type="Control" parent="."]
visible = false
layout_mode = 3 layout_mode = 3
anchors_preset = 15 anchors_preset = 15
anchor_right = 1.0 anchor_right = 1.0
@@ -374,9 +375,10 @@ shadow_opacity = 0.95
shadow_blur = 2.435 shadow_blur = 2.435
[node name="Player" parent="." node_paths=PackedStringArray("TutorialWeaponTarget") instance=ExtResource("1_2vsi6")] [node name="Player" parent="." node_paths=PackedStringArray("TutorialWeaponTarget") instance=ExtResource("1_2vsi6")]
transform = Transform3D(0.054514527, 0, -0.9985129, 0, 1, 0, 0.9985129, 0, 0.054514527, 0, -132.75, 118) transform = Transform3D(0.054514527, 0, -0.9985129, 0, 1, 0, 0.9985129, 0, 0.054514527, -6, 75.5, -13.5)
collision_layer = 17 collision_layer = 17
TutorialWeaponTarget = NodePath("../PlacedTutorialWeapon/WeaponLocationTarget") TutorialWeaponTarget = NodePath("../PlacedTutorialWeapon/WeaponLocationTarget")
TutorialDone = true
AccelerationAir = 1.5 AccelerationAir = 1.5
[node name="DebugLayer" type="CanvasLayer" parent="."] [node name="DebugLayer" type="CanvasLayer" parent="."]

View File

@@ -63,22 +63,23 @@ blend_mode = 1
[node name="Player" type="CharacterBody3D"] [node name="Player" type="CharacterBody3D"]
script = ExtResource("1_poq2x") script = ExtResource("1_poq2x")
WalkSpeed = 7.5 WalkSpeed = 7.5
AccelerationAir = 2.0 AccelerationAir = 0.8
DecelerationAir = 0.1 DecelerationAir = 0.02
Weight = 5.0 Weight = 4.0
MantleTime = 0.2
MantlePath = ExtResource("2_6lejt") MantlePath = ExtResource("2_6lejt")
MantleDashStrength = 20.0
MantleJumpStartVelocity = 13.0
CoyoteTime = 0.3 CoyoteTime = 0.3
SimpleJumpStartVelocity = 8.0 InputBufferFrames = 5
SimpleJumpStartVelocity = 6.0
SimpleJumpHangTimeInFrames = 1 SimpleJumpHangTimeInFrames = 1
SimpleJumpGravityLesseningFactor = 2.5 SimpleJumpGravityLesseningFactor = 2.0
DoubleJumpStartVelocity = 15.0
DoubleJumpHangTimeInFrames = 3 DoubleJumpHangTimeInFrames = 3
DoubleJumpGravityLesseningFactor = 1.5 DoubleJumpGravityLesseningFactor = 1.5
MegaJumpStartVelocity = 30.0 MegaJumpStartVelocity = 30.0
MegaJumpHangTimeInFrames = 12 MegaJumpHangTimeInFrames = 12
MegaJumpGravityLesseningFactor = 1.2 MegaJumpGravityLesseningFactor = 1.2
WallJumpStartVelocity = 12.0 WallJumpStartVelocity = 8.0
MaxNumberOfEmpoweredActions = 3 MaxNumberOfEmpoweredActions = 3
SimpleDashStrength = 15.0 SimpleDashStrength = 15.0
PoweredDashStrength = 30.0 PoweredDashStrength = 30.0
@@ -236,6 +237,11 @@ transform = Transform3D(1, 0, 0, 0, -4.371139e-08, 1, 0, -1, -4.371139e-08, 0, 0
mesh = SubResource("CylinderMesh_nodcl") mesh = SubResource("CylinderMesh_nodcl")
[node name="DashCooldown" type="Timer" parent="."] [node name="DashCooldown" type="Timer" parent="."]
wait_time = 0.8
one_shot = true
[node name="AirborneDashCooldown" type="Timer" parent="."]
wait_time = 0.5
one_shot = true one_shot = true
[node name="PowerCooldown" type="Timer" parent="."] [node name="PowerCooldown" type="Timer" parent="."]
@@ -252,10 +258,10 @@ offset_left = 1524.0
offset_top = 1.0 offset_top = 1.0
offset_right = -8.0 offset_right = -8.0
offset_bottom = 1.0 offset_bottom = 1.0
enabled = false
initial_node_to_watch = NodePath("../StateChart") initial_node_to_watch = NodePath("../StateChart")
[node name="UI" type="Control" parent="."] [node name="UI" type="Control" parent="."]
visible = false
layout_mode = 3 layout_mode = 3
anchors_preset = 15 anchors_preset = 15
anchor_right = 1.0 anchor_right = 1.0
@@ -501,6 +507,12 @@ to = NodePath("../../Grounded")
event = &"grounded" event = &"grounded"
delay_in_seconds = "0.0" delay_in_seconds = "0.0"
[node name="OnMantleOtherSide" type="Node" parent="StateChart/Root/Movement/Mantling"]
script = ExtResource("28_n7qhm")
to = NodePath("../../OnWall/Hugging")
event = &"on_wall"
delay_in_seconds = "0.0"
[node name="Jump" type="Node" parent="StateChart/Root/Movement"] [node name="Jump" type="Node" parent="StateChart/Root/Movement"]
script = ExtResource("26_infe6") script = ExtResource("26_infe6")
initial_state = NodePath("SimpleJump") initial_state = NodePath("SimpleJump")
@@ -609,7 +621,7 @@ default_state = NodePath("../CoyoteEnabled")
[node name="OnWallRun" type="Node" parent="StateChart/Root/Movement/Airborne"] [node name="OnWallRun" type="Node" parent="StateChart/Root/Movement/Airborne"]
script = ExtResource("28_n7qhm") script = ExtResource("28_n7qhm")
to = NodePath("../../OnWall/RunningCoyoteEnabled") to = NodePath("../../OnWall/Running")
event = &"wall_run" event = &"wall_run"
delay_in_seconds = "0.0" delay_in_seconds = "0.0"
@@ -672,7 +684,7 @@ script = ExtResource("27_34snm")
[node name="OnWallHug" type="Node" parent="StateChart/Root/Movement/Airborne/Falling"] [node name="OnWallHug" type="Node" parent="StateChart/Root/Movement/Airborne/Falling"]
script = ExtResource("28_n7qhm") script = ExtResource("28_n7qhm")
to = NodePath("../../../OnWall/HuggingCoyoteEnabled") to = NodePath("../../../OnWall/Hugging")
event = &"wall_hug" event = &"wall_hug"
delay_in_seconds = "0.0" delay_in_seconds = "0.0"
@@ -736,7 +748,7 @@ script = ExtResource("27_34snm")
[node name="OnJump" type="Node" parent="StateChart/Root/Movement/OnWall/Hugging"] [node name="OnJump" type="Node" parent="StateChart/Root/Movement/OnWall/Hugging"]
script = ExtResource("28_n7qhm") script = ExtResource("28_n7qhm")
to = NodePath("../../../Jump/SimpleJump") to = NodePath("../../../Jump/DoubleJump")
event = &"jump" event = &"jump"
delay_in_seconds = "0.0" delay_in_seconds = "0.0"
@@ -745,7 +757,7 @@ script = ExtResource("27_34snm")
[node name="OnJump" type="Node" parent="StateChart/Root/Movement/OnWall/Hanging"] [node name="OnJump" type="Node" parent="StateChart/Root/Movement/OnWall/Hanging"]
script = ExtResource("28_n7qhm") script = ExtResource("28_n7qhm")
to = NodePath("../../../Jump/SimpleJump") to = NodePath("../../../Jump/DoubleJump")
event = &"jump" event = &"jump"
delay_in_seconds = "0.0" delay_in_seconds = "0.0"

View File

@@ -16,6 +16,16 @@ public partial class PlayerController : CharacterBody3D
} }
private bool _isUsingGamepad; private bool _isUsingGamepad;
public enum BufferedActions
{
None,
Jump,
MantleJump,
Dash,
MantleDash
}
private BufferedActions _bufferedAction = BufferedActions.None;
// User API to important child nodes. // User API to important child nodes.
public HeadSystem HeadSystem; public HeadSystem HeadSystem;
public Bobbing Bobbing; public Bobbing Bobbing;
@@ -58,6 +68,7 @@ public partial class PlayerController : CharacterBody3D
// Timers // Timers
private Timer _timeScaleAimInAirTimer; private Timer _timeScaleAimInAirTimer;
private Timer _simpleDashCooldownTimer; private Timer _simpleDashCooldownTimer;
private Timer _airborneDashCooldownTimer;
private Timer _powerCooldownTimer; private Timer _powerCooldownTimer;
[Export] public Marker3D TutorialWeaponTarget; [Export] public Marker3D TutorialWeaponTarget;
@@ -78,16 +89,25 @@ public partial class PlayerController : CharacterBody3D
public float DecelerationAir = 1.0f; public float DecelerationAir = 1.0f;
[Export(PropertyHint.Range, "0,10,0.01,or_greater")] [Export(PropertyHint.Range, "0,10,0.01,or_greater")]
public float Weight { get; set; } = 3.0f; public float Weight { get; set; } = 3.0f;
// Mantle
[ExportGroup("Mantle")] [ExportGroup("Mantle")]
[Export(PropertyHint.Range, "0,1,0.01,or_greater")] [Export(PropertyHint.Range, "0,1,0.01,or_greater")]
public float MantleTime { get; set; } = 0.1f; public float MantleTime { get; set; } = 0.1f;
[Export] [Export]
public PackedScene MantlePath { get; set; } public PackedScene MantlePath { get; set; }
[Export(PropertyHint.Range, "0,50,0.1")]
public float MantleDashStrength { get; set; } = 15f;
[Export(PropertyHint.Range, "0,100,1,or_greater")]
public float MantleJumpStartVelocity { get; set; } = 20.0f;
// Jump // Jump
[ExportGroup("Jump")] [ExportGroup("Jump")]
[Export(PropertyHint.Range, "0,1,0.01")] [Export(PropertyHint.Range, "0,1,0.01")]
public float CoyoteTime { get; set; } = 0.2f; public float CoyoteTime { get; set; } = 0.2f;
[Export(PropertyHint.Range, "0,10,1,or_greater")]
public int InputBufferFrames { get; set; } = 3;
// Simple jump // Simple jump
[ExportSubgroup("Simple jump")] [ExportSubgroup("Simple jump")]
@@ -204,7 +224,6 @@ public partial class PlayerController : CharacterBody3D
private StateChartState _grounded; private StateChartState _grounded;
private StateChartState _airborne; private StateChartState _airborne;
private StateChartState _coyoteEnabled; private StateChartState _coyoteEnabled;
// private StateChartState _doubleJumpEnabled;
private StateChartState _simpleJump; private StateChartState _simpleJump;
private StateChartState _doubleJump; private StateChartState _doubleJump;
private StateChartState _megaJump; private StateChartState _megaJump;
@@ -228,6 +247,8 @@ public partial class PlayerController : CharacterBody3D
private Transition _onLeaveWallFromRunCoyote; private Transition _onLeaveWallFromRunCoyote;
private Transition _onLeaveWallFromRun; private Transition _onLeaveWallFromRun;
private int _currentInputBufferFrames;
private float _playerHeight; private float _playerHeight;
private float _playerRadius; private float _playerRadius;
private bool _isJumpInputPressed; private bool _isJumpInputPressed;
@@ -327,6 +348,7 @@ public partial class PlayerController : CharacterBody3D
_powerCooldownTimer = GetNode<Timer>("PowerCooldown"); _powerCooldownTimer = GetNode<Timer>("PowerCooldown");
_timeScaleAimInAirTimer = GetNode<Timer>("TimeScaleAimInAir"); _timeScaleAimInAirTimer = GetNode<Timer>("TimeScaleAimInAir");
_simpleDashCooldownTimer = GetNode<Timer>("DashCooldown"); _simpleDashCooldownTimer = GetNode<Timer>("DashCooldown");
_airborneDashCooldownTimer = GetNode<Timer>("AirborneDashCooldown");
/////////////////////////// ///////////////////////////
// Initialize components // // Initialize components //
@@ -398,6 +420,7 @@ public partial class PlayerController : CharacterBody3D
_aimedDash.StateExited += OnAimedDashFinished; _aimedDash.StateExited += OnAimedDashFinished;
_simpleDashCooldownTimer.Timeout += DashCooldownTimeout; _simpleDashCooldownTimer.Timeout += DashCooldownTimeout;
_airborneDashCooldownTimer.Timeout += AirborneDashCooldownTimeout;
_onWall.StateEntered += OnWallStarted; _onWall.StateEntered += OnWallStarted;
_onWall.StateExited += OnWallStopped; _onWall.StateExited += OnWallStopped;
@@ -463,16 +486,48 @@ public partial class PlayerController : CharacterBody3D
if (_simpleDashCooldownTimer.IsStopped()) if (_simpleDashCooldownTimer.IsStopped())
_simpleDashCooldownTimer.Start(); _simpleDashCooldownTimer.Start();
if (_bufferedAction == BufferedActions.Jump && _currentInputBufferFrames > 0)
{
_currentInputBufferFrames = 0;
PerformJump();
}
if (_bufferedAction == BufferedActions.Dash && _currentInputBufferFrames > 0)
{
_currentInputBufferFrames = 0;
SimpleDash();
}
if (_bufferedAction == BufferedActions.MantleJump)
{
SimpleDash();
OnJumpStarted(MantleJumpStartVelocity);
}
if (_bufferedAction == BufferedActions.MantleDash)
{
SimpleDash(MantleDashStrength);
}
_bufferedAction = BufferedActions.None;
} }
public void DashCooldownTimeout() public void DashCooldownTimeout()
{ {
_canDash = true; _canDash = true;
} }
public void AirborneDashCooldownTimeout()
{
_canDashAirborne = true;
}
public bool IsPlayerInputtingForward()
{
return GetMoveInput().Z < -0.5f;
}
public bool IsTryingToMantle() public bool IsTryingToMantle()
{ {
return MantleSystem.IsMantlePossible && GetMoveInput().Z < -0.5f && _isJumpInputPressed; return MantleSystem.IsMantlePossible && IsPlayerInputtingForward() && _isJumpInputPressed;
} }
public void HandleGrounded(float delta) public void HandleGrounded(float delta)
@@ -485,15 +540,17 @@ public partial class PlayerController : CharacterBody3D
public void HandleAirborne(float delta) public void HandleAirborne(float delta)
{ {
MoveInAir(delta); MoveInAir(delta);
if (isOnFloorCustom()) if (isOnFloorCustom())
_playerState.SendEvent("grounded"); _playerState.SendEvent("grounded");
if (IsTryingToMantle()) _playerState.SendEvent("mantle"); if (IsTryingToMantle()) _playerState.SendEvent("mantle");
if (!WallHugSystem.IsWallHugging()) if (!WallHugSystem.IsWallHugging())
{
_isWallJumpAvailable = true; // reset wall jump if we left the wall
return; return;
}
// Going upwards, we stay simply airborne // Going upwards, we stay simply airborne
if (Velocity.AngleTo(Vector3.Up) < Math.PI / 4) if (Velocity.AngleTo(Vector3.Up) < Math.PI / 4)
@@ -625,7 +682,15 @@ public partial class PlayerController : CharacterBody3D
// Jump // Jump
public void OnInputJumpStarted() public void OnInputJumpStarted()
{ {
_currentInputBufferFrames = InputBufferFrames;
_bufferedAction = _mantling.Active ? BufferedActions.MantleJump : BufferedActions.Jump;
_isJumpInputPressed = true; _isJumpInputPressed = true;
PerformJump();
}
public void PerformJump()
{
if (MantleSystem.IsMantlePossible) if (MantleSystem.IsMantlePossible)
{ {
_playerState.SendEvent("mantle"); _playerState.SendEvent("mantle");
@@ -638,13 +703,15 @@ public partial class PlayerController : CharacterBody3D
return; return;
} }
if (_onWallHuggingCoyoteEnabled.Active || _onWallRunningCoyoteEnabled.Active) if (_onWall.Active && !_isWallJumpAvailable && IsFacingWall()) return;
{
if (!_isWallJumpAvailable) return;
}
_playerState.SendEvent("jump"); _playerState.SendEvent("jump");
} }
public bool IsFacingWall()
{
return _wallHugStartNormal.Dot(GetGlobalForwardFacingVector()) < -0.5f;
}
public void OnInputJumpOngoing() public void OnInputJumpOngoing()
{ {
} }
@@ -667,7 +734,7 @@ public partial class PlayerController : CharacterBody3D
public void OnDoubleJumpStarted() public void OnDoubleJumpStarted()
{ {
_canDash = true; _canDash = true;
_canDashAirborne = true; // _canDashAirborne = true;
OnJumpStarted(DoubleJumpStartVelocity); OnJumpStarted(DoubleJumpStartVelocity);
} }
public void OnMegaJumpStarted() public void OnMegaJumpStarted()
@@ -699,7 +766,14 @@ public partial class PlayerController : CharacterBody3D
public void OnJumpFromWall() public void OnJumpFromWall()
{ {
ComputeJumpFromWallHSpeed(WallJumpStartVelocity); if (!IsFacingWall())
{
ComputeJumpFromWallHSpeed(WallJumpStartVelocity);
}
// Remove the ability to dash straight away so you cannot scale up the wall
_canDashAirborne = false;
_airborneDashCooldownTimer.Start();
_isWallJumpAvailable = false;
} }
public void OnMegajumpFromWall() public void OnMegajumpFromWall()
{ {
@@ -762,6 +836,11 @@ public partial class PlayerController : CharacterBody3D
private Transform3D _customMantleStartTransform; private Transform3D _customMantleStartTransform;
private Curve3D _customMantleCurve; private Curve3D _customMantleCurve;
private Vector3 _mantleStartPosition; private Vector3 _mantleStartPosition;
private Vector3 _velocityOnMantleStarted = Vector3.Zero;
private bool _mantleEndedOnOtherSideOfWall;
private bool _mantleFoundGround;
public void OnMantleStarted() public void OnMantleStarted()
{ {
HeadSystem.OnMantle(); HeadSystem.OnMantle();
@@ -772,17 +851,22 @@ public partial class PlayerController : CharacterBody3D
GD.PrintErr("Failed to instantiate MantlePath"); GD.PrintErr("Failed to instantiate MantlePath");
return; return;
} }
_velocityOnMantleStarted = Velocity;
var transform = _customMantle ? _customMantleStartTransform : MantleSystem.GlobalTransform; var transform = _customMantle ? _customMantleStartTransform : MantleSystem.GlobalTransform;
var curve = _customMantle ? _customMantleCurve : MantleSystem.MantleCurve; var curve = _customMantle ? _customMantleCurve : MantleSystem.MantleCurve;
_mantleEndedOnOtherSideOfWall = _customMantle ? _mantleEndedOnOtherSideOfWall : MantleSystem.EndedOnOtherSideOfWall;
_mantleFoundGround = _customMantle ? _mantleFoundGround : MantleSystem.FoundGround;
GetTree().GetRoot().AddChild(_mantlePath); GetTree().GetRoot().AddChild(_mantlePath);
_mantlePath.Setup(transform, curve); _mantlePath.Setup(transform, curve);
_mantleStartPosition = GlobalPosition; _mantleStartPosition = GlobalPosition;
var curveLength = curve.GetBakedLength();
var tween = GetTree().CreateTween(); var tween = GetTree().CreateTween();
tween.SetTrans(Tween.TransitionType.Linear); tween.SetTrans(Tween.TransitionType.Linear);
tween.SetEase(Tween.EaseType.InOut); tween.SetEase(Tween.EaseType.In);
tween.TweenProperty(_mantlePath.PathFollow, "progress_ratio", 1, MantleTime); tween.TweenProperty(_mantlePath.PathFollow, "progress_ratio", 1, MantleTime*curveLength);
tween.Finished += MantleFinished; tween.Finished += MantleFinished;
} }
@@ -791,26 +875,31 @@ public partial class PlayerController : CharacterBody3D
GlobalPosition = _mantlePath.Target.GlobalPosition; GlobalPosition = _mantlePath.Target.GlobalPosition;
} }
public void SimpleDashInDirection(Vector3 direction) public void SimpleDashInDirection(Vector3 direction, float strength = -1)
{ {
SetVelocity(direction * SimpleDashStrength); if (strength < 0) strength = SimpleDashStrength;
SetVelocity(direction * strength);
} }
public void SimpleDash() public void SimpleDash(float strength = -1)
{ {
SimpleDashInDirection(GetInputGlobalHDirection()); SimpleDashInDirection(GetInputGlobalHDirection(), strength);
} }
public void MantleFinished() public void MantleFinished()
{ {
_mantlePath.Teardown(); _mantlePath.Teardown();
// SetVelocity(_finalCurveDirection.Normalized() * _speedOverCurve);
var isThereMovementInput = GetMoveInput().Length() > 0; var isThereMovementInput = GetMoveInput().Length() > 0;
if (isThereMovementInput) if (isThereMovementInput)
{ {
// If there's a movement input on Mantle, we dash in the direction the mantle took place // If there's a movement input on Mantle, we dash in the direction the mantle ended with
var positionDifference = GlobalPosition - _mantleStartPosition; var positionDifference = GlobalPosition - _mantleStartPosition;
var directionHorizontal = new Vector3(positionDifference.X, 0, positionDifference.Z); var directionHorizontal = new Vector3(positionDifference.X, 0, positionDifference.Z);
SimpleDashInDirection(directionHorizontal.Normalized()); // SimpleDashInDirection(directionHorizontal.Normalized());
SetVelocity(directionHorizontal.Normalized() * WalkSpeed);
} }
_customMantle = false; _customMantle = false;
@@ -847,8 +936,8 @@ public partial class PlayerController : CharacterBody3D
SetVerticalVelocity(Velocity.Y - 2.0f); SetVerticalVelocity(Velocity.Y - 2.0f);
} }
// Move back to Airborne state management when starting to go down again // Move back to Airborne state when starting to go down again or if input isn't held anymore (buffered jump)
if (_framesSinceJumpAtApex > hangFrames) if (_framesSinceJumpAtApex > hangFrames || !_isJumpInputPressed)
_playerState.SendEvent("jump_ended"); _playerState.SendEvent("jump_ended");
} }
public void HandleSimpleJump(float delta) public void HandleSimpleJump(float delta)
@@ -961,7 +1050,9 @@ public partial class PlayerController : CharacterBody3D
return; return;
_canDashAirborne = false; _canDashAirborne = false;
} }
_currentInputBufferFrames = InputBufferFrames;
_bufferedAction = _mantling.Active ? BufferedActions.MantleDash : BufferedActions.Dash;
_playerState.SendEvent("dash"); _playerState.SendEvent("dash");
} }
public void OnAimingEntered() public void OnAimingEntered()
@@ -1085,6 +1176,8 @@ public partial class PlayerController : CharacterBody3D
_customMantle = DashSystem.ShouldMantle; _customMantle = DashSystem.ShouldMantle;
_customMantleCurve = DashSystem.MantleSystem.MantleCurve; _customMantleCurve = DashSystem.MantleSystem.MantleCurve;
_customMantleStartTransform = DashSystem.MantleSystem.GlobalTransform; _customMantleStartTransform = DashSystem.MantleSystem.GlobalTransform;
_mantleEndedOnOtherSideOfWall = DashSystem.MantleSystem.EndedOnOtherSideOfWall;
_mantleFoundGround = DashSystem.MantleSystem.FoundGround;
} }
Tween CreatePositionTween(Vector3 targetLocation, float tweenTime) Tween CreatePositionTween(Vector3 targetLocation, float tweenTime)
@@ -1361,12 +1454,19 @@ public partial class PlayerController : CharacterBody3D
{ {
WeaponRoot.SetRotation(HeadSystem.Rotation); WeaponRoot.SetRotation(HeadSystem.Rotation);
} }
public Vector3 GetGlobalForwardFacingVector()
{
return Transform.Basis * HeadSystem.Transform.Basis * Vector3.Forward;
}
/////////////////////////// ///////////////////////////
// Processes ////////////// // Processes //////////////
/////////////////////////// ///////////////////////////
public override void _PhysicsProcess(double delta) public override void _PhysicsProcess(double delta)
{ {
if (_currentInputBufferFrames > 0) _currentInputBufferFrames -= 1;
LookAround(delta); LookAround(delta);
CameraModifications((float) delta); CameraModifications((float) delta);
HandleStairs((float) delta); HandleStairs((float) delta);

View File

@@ -161,5 +161,6 @@ common/physics_interpolation=true
[rendering] [rendering]
textures/vram_compression/import_etc2_astc=true textures/vram_compression/import_etc2_astc=true
lights_and_shadows/directional_shadow/soft_shadow_filter_quality=5
environment/volumetric_fog/volume_size=256 environment/volumetric_fog/volume_size=256
environment/volumetric_fog/volume_depth=256 environment/volumetric_fog/volume_depth=256

View File

@@ -21,6 +21,8 @@ public partial class MantleSystem: Node3D
public Vector3 FirstMantleProfilePoint { get; private set; } = Vector3.Zero; public Vector3 FirstMantleProfilePoint { get; private set; } = Vector3.Zero;
public bool IsMantlePossible { get; private set; } = false; public bool IsMantlePossible { get; private set; } = false;
public bool EndedOnOtherSideOfWall { get; private set; } = false;
public bool FoundGround { get; private set; } = false;
public const int WallProfileCastCount = 7; public const int WallProfileCastCount = 7;
private ShapeCast3D[] _wallProfileShapecasts = new ShapeCast3D[WallProfileCastCount]; private ShapeCast3D[] _wallProfileShapecasts = new ShapeCast3D[WallProfileCastCount];
@@ -55,15 +57,20 @@ public partial class MantleSystem: Node3D
// Reset state // Reset state
IsMantlePossible = false; IsMantlePossible = false;
EndedOnOtherSideOfWall = false;
FoundGround = false;
if (!isColliding) return; if (!isColliding) return;
// Check if collide with wall // Check if face something wall-like that should be climbable
var collisionNormal = isGrounded ? _groundedWallDetect.GetCollisionNormal(0) : _inAirWallDetect.GetCollisionNormal(0); var collisionNormal = isGrounded ? _groundedWallDetect.GetCollisionNormal(0) : _inAirWallDetect.GetCollisionNormal(0);
if (collisionNormal.Y > 0.9f) return; if (collisionNormal.Y > 0.7f) return;
var spaceState = GetWorld3D().DirectSpaceState;
MantleCurve = new Curve3D(); MantleCurve = new Curve3D();
MantleCurve.AddPoint(Vector3.Zero); MantleCurve.AddPoint(Vector3.Zero);
var hasFirstProfileHit = false; var hasFirstProfileHit = false;
var previousProfilePoint = GlobalPosition;
foreach (var wallProfileShapecast in _wallProfileShapecasts) foreach (var wallProfileShapecast in _wallProfileShapecasts)
{ {
// Haven't met the wall yet // Haven't met the wall yet
@@ -74,22 +81,43 @@ public partial class MantleSystem: Node3D
// Got to the other side of the wall, we stop there // Got to the other side of the wall, we stop there
if (!wallProfileShapecast.IsColliding()) if (!wallProfileShapecast.IsColliding())
{ {
MantleCurve.AddPoint(ToLocal(globalTargetPosition)); /*EndedOnOtherSideOfWall = true;
var origin = globalTargetPosition;
var end = origin + Vector3.Down*0.51f; // We check for the ground a bit below our target
var groundQuery = PhysicsRayQueryParameters3D.Create(origin, end, wallProfileShapecast.CollisionMask);
var groundResult = spaceState.IntersectRay(groundQuery);
if (groundResult.Count > 0)
{
// We found the ground, this is our final location
FoundGround = true;
Vector3 position = (Vector3) groundResult["position"];
MantleCurve.AddPoint(ToLocal(position));
}*/
break; break;
} }
var profilePoint = wallProfileShapecast.GetCollisionPoint(0); var profilePoint = wallProfileShapecast.GetCollisionPoint(0);
var profileNormal = wallProfileShapecast.GetCollisionNormal(0); var profileNormal = wallProfileShapecast.GetCollisionNormal(0);
var shape = wallProfileShapecast.Shape as SphereShape3D;
var shapeRadius = shape == null ? 0.125f : shape.Radius;
var centerOfShape = profilePoint + profileNormal * shapeRadius;
// Check if we collided parallel to a wall // Check if we collided parallel to a wall
var isCollisionSameAsTarget = globalTargetPosition.IsEqualApprox(profilePoint); var isCollisionSameAsTarget = globalTargetPosition.IsEqualApprox(centerOfShape);
var isCollidingWithWall = profileNormal.Y < 0.1f; var isCollidingWithWall = profileNormal.Y < 0.1f;
if (isCollisionSameAsTarget || isCollidingWithWall) continue; if (isCollisionSameAsTarget || isCollidingWithWall) continue;
// Check if the path from the previous point makes us go through a wall
var query = PhysicsRayQueryParameters3D.Create(previousProfilePoint, centerOfShape, wallProfileShapecast.CollisionMask);
var result = spaceState.IntersectRay(query);
if (result.Count > 0) break; // We are going through a wall, we stop there
// We have a valid collision // We have a valid collision
if (!hasFirstProfileHit) FirstMantleProfilePoint = profilePoint; if (!hasFirstProfileHit) FirstMantleProfilePoint = centerOfShape;
hasFirstProfileHit = true; hasFirstProfileHit = true;
MantleCurve.AddPoint(ToLocal(profilePoint)); previousProfilePoint = centerOfShape;
MantleCurve.AddPoint(ToLocal(centerOfShape));
} }
if (MantleCurve.PointCount == 1) return; if (MantleCurve.PointCount == 1) return;

View File

@@ -58,47 +58,47 @@ collision_mask = 2
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 2.5, -0.5) transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 2.5, -0.5)
enabled = false enabled = false
shape = SubResource("SphereShape3D_i32qj") shape = SubResource("SphereShape3D_i32qj")
target_position = Vector3(0, -2.375, 0) target_position = Vector3(0, -2.125, 0)
collision_mask = 2 collision_mask = 2
[node name="ShapeCast2" type="ShapeCast3D" parent="WallProfileShapeCasts"] [node name="ShapeCast2" type="ShapeCast3D" parent="WallProfileShapeCasts"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 2.5, -0.75) transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 2.5, -0.75)
enabled = false enabled = false
shape = SubResource("SphereShape3D_i32qj") shape = SubResource("SphereShape3D_i32qj")
target_position = Vector3(0, -2.375, 0) target_position = Vector3(0, -2.125, 0)
collision_mask = 2 collision_mask = 2
[node name="ShapeCast3" type="ShapeCast3D" parent="WallProfileShapeCasts"] [node name="ShapeCast3" type="ShapeCast3D" parent="WallProfileShapeCasts"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 2.5, -1) transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 2.5, -1)
enabled = false enabled = false
shape = SubResource("SphereShape3D_i32qj") shape = SubResource("SphereShape3D_i32qj")
target_position = Vector3(0, -2.375, 0) target_position = Vector3(0, -2.125, 0)
collision_mask = 2 collision_mask = 2
[node name="ShapeCast4" type="ShapeCast3D" parent="WallProfileShapeCasts"] [node name="ShapeCast4" type="ShapeCast3D" parent="WallProfileShapeCasts"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 2.5, -1.25) transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 2.5, -1.25)
enabled = false enabled = false
shape = SubResource("SphereShape3D_i32qj") shape = SubResource("SphereShape3D_i32qj")
target_position = Vector3(0, -2.375, 0) target_position = Vector3(0, -2.125, 0)
collision_mask = 2 collision_mask = 2
[node name="ShapeCast5" type="ShapeCast3D" parent="WallProfileShapeCasts"] [node name="ShapeCast5" type="ShapeCast3D" parent="WallProfileShapeCasts"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 2.5, -1.5) transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 2.5, -1.5)
enabled = false enabled = false
shape = SubResource("SphereShape3D_i32qj") shape = SubResource("SphereShape3D_i32qj")
target_position = Vector3(0, -2.375, 0) target_position = Vector3(0, -2.125, 0)
collision_mask = 2 collision_mask = 2
[node name="ShapeCast6" type="ShapeCast3D" parent="WallProfileShapeCasts"] [node name="ShapeCast6" type="ShapeCast3D" parent="WallProfileShapeCasts"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 2.5, -1.75) transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 2.5, -1.75)
enabled = false enabled = false
shape = SubResource("SphereShape3D_i32qj") shape = SubResource("SphereShape3D_i32qj")
target_position = Vector3(0, -2.375, 0) target_position = Vector3(0, -2.125, 0)
collision_mask = 2 collision_mask = 2
[node name="ShapeCast7" type="ShapeCast3D" parent="WallProfileShapeCasts"] [node name="ShapeCast7" type="ShapeCast3D" parent="WallProfileShapeCasts"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 2.5, -2) transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 2.5, -2)
enabled = false enabled = false
shape = SubResource("SphereShape3D_i32qj") shape = SubResource("SphereShape3D_i32qj")
target_position = Vector3(0, -2.375, 0) target_position = Vector3(0, -2.125, 0)
collision_mask = 2 collision_mask = 2