feat: added grapple mechanic
This commit is contained in:
@@ -20,6 +20,15 @@ var input_jump_pressed: bool = false
|
||||
var input_jump_just_pressed: bool = false
|
||||
var input_crouch: bool = false
|
||||
var input_dash: bool = false
|
||||
var input_grapple: bool = false
|
||||
var input_grapple_just_pressed: bool = false
|
||||
|
||||
# Grapple state
|
||||
var grapple_point: Vector3 = Vector3.ZERO
|
||||
var grapple_length: float = 0.0
|
||||
var grapple_travel_time: float = 0.0
|
||||
var grapple_shoot_time: float = 0.0
|
||||
var is_grapple_shooting: bool = false
|
||||
|
||||
# ── State tracking ────────────────────────────────────────────────────────────
|
||||
var wall_normal: Vector3 = Vector3.ZERO
|
||||
@@ -40,6 +49,12 @@ var is_crouched: bool = false
|
||||
|
||||
|
||||
func _ready() -> void:
|
||||
# Ensure grapple state is injected
|
||||
var grapple_state = Node.new()
|
||||
grapple_state.name = "state_grapple"
|
||||
grapple_state.set_script(load("res://movement/states/state_grapple.gd"))
|
||||
add_child(grapple_state)
|
||||
|
||||
for child in get_children():
|
||||
if child is Node and child.name.begins_with("state_"):
|
||||
states[child.name.replace("state_", "")] = child
|
||||
@@ -72,6 +87,17 @@ func _physics_process(delta: float) -> void:
|
||||
chain_count = 0
|
||||
current_chain_bonus = 0.0
|
||||
|
||||
# Global grapple check: if just pressed, raycast from camera
|
||||
if input_grapple_just_pressed and current_state != "grapple" and not is_grapple_shooting:
|
||||
_try_start_grapple()
|
||||
|
||||
if is_grapple_shooting:
|
||||
grapple_shoot_time += delta
|
||||
if grapple_shoot_time >= grapple_travel_time:
|
||||
is_grapple_shooting = false
|
||||
movement_event.emit("grapple_latch", {})
|
||||
switch_to("grapple")
|
||||
|
||||
# Manage global crouch state
|
||||
var want_crouch = input_crouch
|
||||
if current_state == "slide":
|
||||
@@ -117,6 +143,27 @@ func switch_to(new_state_name: String, data: Dictionary = {}) -> void:
|
||||
state_changed.emit(prev, new_state_name)
|
||||
|
||||
|
||||
func _try_start_grapple() -> void:
|
||||
if not player or not player.camera:
|
||||
return
|
||||
var camera: Camera3D = player.camera
|
||||
var space_state := player.get_world_3d().direct_space_state
|
||||
var origin := camera.global_position
|
||||
var end := origin - camera.global_transform.basis.z * params.grapple_range
|
||||
var ray := PhysicsRayQueryParameters3D.create(origin, end)
|
||||
ray.exclude = [player.get_rid()]
|
||||
var hit := space_state.intersect_ray(ray)
|
||||
if not hit.is_empty():
|
||||
grapple_point = hit.position
|
||||
grapple_length = origin.distance_to(grapple_point)
|
||||
|
||||
# Travel at 45 m/s
|
||||
grapple_travel_time = grapple_length / 45
|
||||
grapple_shoot_time = 0.0
|
||||
is_grapple_shooting = true
|
||||
movement_event.emit("grapple_shoot", {})
|
||||
|
||||
|
||||
func register_chain_mechanic(_mechanic_name: String) -> void:
|
||||
if chain_timer > 0.0 and chain_count > 0:
|
||||
chain_count += 1
|
||||
|
||||
Reference in New Issue
Block a user