Files
Papay-Shooter/movement/states/state_wall_cling.gd
T

81 lines
2.9 KiB
GDScript

extends Node
class_name StateWallCling
var machine: MovementStateMachine
var params: MovementParams:
get: return machine.params
var elapsed: float = 0.0
var stamina: float = 0.0
func enter(_data: Dictionary = {}) -> void:
elapsed = 0.0
stamina = params.wall_cling_max_stamina
machine.register_chain_mechanic("wall_cling")
# Kill most velocity but keep slight downward
machine.player.velocity = Vector3.ZERO
func exit() -> void:
pass
func update(delta: float) -> void:
elapsed += delta
stamina -= params.wall_cling_stamina_drain * delta
var player := machine.player
var vel: Vector3 = player.velocity
# ── Slow slide down ───────────────────────────────────────────────────
var slide_factor := 1.0 - (stamina / params.wall_cling_max_stamina) # 0→1 as stamina drains
vel.x = 0.0
vel.z = 0.0
vel.y = params.wall_cling_slide_speed * (1.0 + slide_factor * 2.0)
# Push into wall to maintain contact
vel -= machine.wall_normal * 1.0
player.velocity = vel
player.move_and_slide()
# ── Stamina depleted → fall ───────────────────────────────────────────
if stamina <= 0.0:
machine.wall_normal = Vector3.ZERO
machine.wall_side = 0.0
machine.switch_to("air")
return
# ── Jump off wall ─────────────────────────────────────────────────────
if machine.input_jump_just_pressed and machine.jump_cooldown_timer <= 0.0:
var push_dir := machine.wall_normal * params.wall_run_jump_off_normal
player.velocity = Vector3(push_dir.x, params.jump_velocity, push_dir.z)
machine.wall_normal = Vector3.ZERO
machine.wall_side = 0.0
machine.wall_cooldown_timer = 0.3
machine.register_chain_mechanic("wall_cling_jump")
machine.jump_cooldown_timer = params.jump_cooldown
machine.switch_to("air")
return
# ── Re-enter wall run with movement input ─────────────────────────────
if machine.input_dir.length() > 0.1:
machine.switch_to("wall_run")
return
# ── Lost wall contact ─────────────────────────────────────────────────
var wall := machine.detect_wall_horizontal()
if wall == Vector3.ZERO:
machine.wall_normal = Vector3.ZERO
machine.wall_side = 0.0
machine.switch_to("air")
return
# ── Hit floor ─────────────────────────────────────────────────────────
if player.is_on_floor():
machine.on_ground = true
machine.wall_normal = Vector3.ZERO
machine.wall_side = 0.0
machine.switch_to("ground")