Fix jetpack vectors, change seeking_climb behaviour

This commit is contained in:
2025-11-01 14:09:26 +01:00
parent 60f2ddb3d7
commit 14b24beb23
3 changed files with 51 additions and 43 deletions

8
Init_Prompt.md Normal file
View File

@ -0,0 +1,8 @@
You are a Godot 4.5 Code assistant. You are not overly agreeable or apologetic but still pleasant and you understand that coding can be quick with your help but that does not mean that you are infallible. Please wait for me to verify that code works before suggesting that we move on from the current task. Suggestions for next steps and features that are adjacent to what were working are very welcome however.
I will attach the full project files of the project being worked on which includes a game design document as well as a running note on the current state of the project which details implemented and planned features. Read these and report back to me. Please suggest potential bugs, features not working as intended, refactorizations for cleaner code, and missing best practices as part of this project ingestion.
Additionally you understand the following things about the version of Godot being used:
- To utilize the editor interface in you reference the global singleton `EditorInterface`. You do not need to call a function to get the a reference to it.
- `xform()` is not a function on transform objects. To achieve the same effect you would use simple transform multiplication (`Transform_A * Transform_B)`)

View File

@ -50,14 +50,14 @@ func process_movement(delta: float, move_input: Vector2, vertical_input: float,
_apply_floating_movement(delta, move_input, vertical_input, roll_input)
func apply_thrusters(pawn: CharacterPawn3D, delta: float, move_input: Vector2, vertical_input: float, roll_input: float):
if not is_instance_valid(pawn) or not camera: return
if not is_instance_valid(pawn): return
# Apply Linear Velocity
var camera_forward = -camera.global_transform.basis.z
var camera_right = camera.global_transform.basis.x
var camera_up = camera.global_transform.basis.y
var move_dir_horizontal = (camera_forward * move_input.y + camera_right * move_input.x)
var move_dir_vertical = camera_up * vertical_input
var pawn_forward = -pawn.global_basis.z
var pawn_right = pawn.global_basis.x
var pawn_up = pawn.global_basis.y
var move_dir_horizontal = (pawn_forward * move_input.y + pawn_right * move_input.x)
var move_dir_vertical = pawn_up * vertical_input
var combined_move_dir = move_dir_horizontal + move_dir_vertical
if combined_move_dir != Vector3.ZERO:
@ -89,11 +89,11 @@ func on_exit_state():
func _apply_floating_movement(delta: float, move_input: Vector2, vertical_input: float, roll_input: float):
# Apply Linear Velocity
var camera_forward = -camera.global_transform.basis.z
var camera_right = camera.global_transform.basis.x # Use camera's right for consistency
var camera_up = camera.global_transform.basis.y
var move_dir_horizontal = (camera_forward * move_input.y + camera_right * move_input.x)
var move_dir_vertical = camera_up * vertical_input
var pawn_forward = -pawn.global_basis.z
var pawn_right = pawn.global_basis.x # Use pawn's right for consistency
var pawn_up = pawn.global_basis.y
var move_dir_horizontal = (pawn_forward * move_input.y + pawn_right * move_input.x)
var move_dir_vertical = pawn_up * vertical_input
var combined_move_dir = move_dir_horizontal + move_dir_vertical
if combined_move_dir != Vector3.ZERO:
@ -109,14 +109,14 @@ func _apply_floating_movement(delta: float, move_input: Vector2, vertical_input:
# --- Auto-Orientation Logic ---
func _orient_pawn(delta: float):
# 1. Determine Target Orientation Basis
var initial_cam_basis = camera_pivot.global_transform.basis
var target_forward = -camera_pivot.global_transform.basis.z # Look where camera looks
var initial_cam_basis = camera_pivot.global_basis
var target_forward = -camera_pivot.global_basis.z # Look where camera looks
var target_up = Vector3.UP # Default up initially
# --- THE FIX: Adjust how target_up is calculated ---
# Calculate velocity components relative to camera orientation
var _forward_velocity_component = pawn.velocity.dot(target_forward)
var _right_velocity_component = pawn.velocity.dot(camera_pivot.global_transform.basis.x)
var _right_velocity_component = pawn.velocity.dot(camera_pivot.global_basis.x)
# Only apply strong "feet trailing" if significant forward/backward movement dominates
# and we are actually moving.
@ -143,7 +143,7 @@ func _orient_pawn(delta: float):
# target_basis = target_basis.rotated(target_basis.x, target_pitch_rad) # Rotate around the target right vector
# 2. Smoothly Interpolate Towards Target Basis
var current_basis = pawn.global_transform.basis
var current_basis = pawn.global_basis
var new_basis = current_basis.slerp(target_basis, delta * orientation_speed)
# Store the body's yaw *before* applying the new basis
@ -151,10 +151,10 @@ func _orient_pawn(delta: float):
var _old_body_pitch = current_basis.get_euler().x
# 3. Apply the new orientation
pawn.global_transform.basis = new_basis
pawn.global_basis = new_basis
# 4. Reset camera pivot to rotation to what it was before we rotated the parent
camera_pivot.global_transform.basis = initial_cam_basis
camera_pivot.global_basis = initial_cam_basis
# --- Add new function placeholder ---
# TODO: Implement Rotation Stabilization Logic

View File

@ -18,7 +18,6 @@ var nearby_grips: Array[GripArea3D] = []
@export var gripping_linear_damping: float = 5.0 # How quickly velocity stops
@export var gripping_angular_damping: float = 5.0 # How quickly spin stops
@export var gripping_orient_speed: float = 2.0 # How quickly pawn rotates to face grip
# var _movement_input_was_neutral: bool = true # Tracks if input was released, for coasting.
# --- Climbing parameters ---
@export var climb_speed: float = 2.0
@ -75,18 +74,7 @@ func process_movement(delta: float, move_input: Vector2, vertical_input: float,
match current_state:
MovementState.IDLE:
# State is IDLE (free-floating).
# Check for EVA suit usage.
var has_movement_input = (move_input != Vector2.ZERO or vertical_input != 0.0 or roll_input != 0.0)
if has_movement_input and is_instance_valid(pawn.eva_suit_component):
# Use EVA suit
pawn.eva_suit_component.apply_thrusters(pawn, delta, move_input, vertical_input, roll_input)
# _movement_input_was_neutral = not has_movement_input
# Check for body orientation (if applicable)
if release_input.held and is_instance_valid(pawn.eva_suit_component):
pawn.eva_suit_component._orient_pawn(delta) # Use suit's orient
_process_idle(delta, move_input, vertical_input, roll_input, release_input)
MovementState.REACHING:
_process_reaching(delta)
MovementState.GRIPPING:
@ -152,13 +140,16 @@ func _update_state(
_release_current_grip(move_input)
return
# FIX: Check for launch charge *before* checking for climb, as it's a more specific action.
# Check for launch charge *before* checking for climb, as it's a more specific action.
if (reach_input.pressed or reach_input.held) and move_input != Vector2.ZERO:
_start_charge(move_input)
return
elif move_input != Vector2.ZERO:
_start_climb(move_input)
_start_climb(move_input) # This is overshadowed by the above check.
MovementState.CLIMBING:
if reach_input.pressed or reach_input.held:
_start_charge(move_input)
return
if release_input.pressed or release_input.held or not is_instance_valid(current_grip):
_stop_climb(true) # Release grip and stop
return
@ -175,6 +166,18 @@ func _update_state(
# === MOVEMENT PROCESSING ===
func _process_idle(delta: float, move_input: Vector2, vertical_input: float, roll_input: float, release_input: PlayerController3D.KeyInput):
# State is IDLE (free-floating).
# Check for EVA suit usage.
var has_movement_input = (move_input != Vector2.ZERO or vertical_input != 0.0 or roll_input != 0.0)
if has_movement_input and is_instance_valid(pawn.eva_suit_component):
# Use EVA suit
pawn.eva_suit_component.apply_thrusters(pawn, delta, move_input, vertical_input, roll_input)
# Check for body orientation (if applicable)
if release_input.held and is_instance_valid(pawn.eva_suit_component):
pawn.eva_suit_component._orient_pawn(delta) # Use suit's orient
func _process_reaching(_delta: float):
# TODO: Drive IK target towards current_grip.get_grip_transform().origin
# TODO: Monitor distance / animation state
@ -253,16 +256,15 @@ func _apply_climb_physics(delta: float, move_input: Vector2):
func _process_seeking_climb(_delta: float, move_input: Vector2):
# If the player's input has changed from what initiated the seek, cancel it.
if not move_input.is_equal_approx(_seeking_climb_input):
current_state = MovementState.IDLE
var target_grip = _find_best_grip()
_seeking_climb_input = Vector2.ZERO # Reset for next time
return # Exit, on next frame new input will be processed in IDLE state
# Continuously look for a new grip in the direction of climbing.
var climb_direction = move_input.y * pawn.global_basis.y + move_input.x * pawn.global_basis.x
next_grip_target = _find_best_grip(climb_direction.normalized(), INF, climb_angle_threshold_deg)
if next_grip_target:
# Found a grip, transition to REACHING. _seeking_climb_input is still active.
current_state = MovementState.REACHING
if _attempt_grip(target_grip):
# Successfully found and grabbed a grip. The state is now GRIPPING.
print("Seeking Climb ended, gripped new target.")
else:
current_state = MovementState.IDLE
# No grip found. Transition to IDLE.
print("Seeking Climb ended, no grip found. Reverting to IDLE.")
# --- Grip Helpers
@ -439,8 +441,6 @@ func _handle_launch_charge(delta: float):
launch_charge = min(launch_charge + launch_charge_rate * delta, max_launch_speed)
pawn.velocity = Vector3.ZERO
pawn.angular_velocity = Vector3.ZERO
# _movement_input_was_neutral = false # Ensure we don't immediately thrust after launch
func _execute_launch(move_input: Vector2):
if not is_instance_valid(current_grip): return # Safety check