Compare commits
2 Commits
4e4fdb91e7
...
9188a97268
| Author | SHA1 | Date | |
|---|---|---|---|
| 9188a97268 | |||
| 1e8ebb7567 |
@@ -64,6 +64,7 @@ var culture_buttons: Array[Button] = []
|
||||
|
||||
func _ready() -> void:
|
||||
Input.mouse_mode = Input.MOUSE_MODE_VISIBLE
|
||||
GameplayInput.set_menu_open(self, true)
|
||||
name_input = _find("NameInput") as LineEdit
|
||||
background_list = _find("BackgroundL") as Control
|
||||
if background_list == null:
|
||||
@@ -126,6 +127,20 @@ func _ready() -> void:
|
||||
if backgrounds.size() > 0:
|
||||
_select_background(backgrounds[0])
|
||||
_set_sex("male")
|
||||
if sex_male:
|
||||
sex_male.grab_focus()
|
||||
|
||||
|
||||
## Controller cancel follows the existing back command without changing creation data.
|
||||
func _unhandled_input(event: InputEvent) -> void:
|
||||
if event.is_action_pressed("ui_cancel"):
|
||||
get_viewport().set_input_as_handled()
|
||||
_on_back()
|
||||
|
||||
|
||||
## Releases menu ownership when entering gameplay or returning to the main menu.
|
||||
func _exit_tree() -> void:
|
||||
GameplayInput.set_menu_open(self, false)
|
||||
|
||||
|
||||
func _find(n: String) -> Node:
|
||||
|
||||
@@ -15,7 +15,6 @@ extends CharacterBody3D
|
||||
var player_inside: bool = false
|
||||
var player_ref: CharacterBody3D = null
|
||||
var using_third_person: bool = false
|
||||
var f_was_down: bool = false
|
||||
|
||||
var mass: float = 6500.0
|
||||
var thrust_force: float = 180000.0
|
||||
@@ -64,11 +63,12 @@ var _hatch_crew_open: bool = false
|
||||
var _hatch_dock_open: bool = false
|
||||
var _ladder_out: bool = false
|
||||
var _cabin_dim: bool = false
|
||||
var _v_was: bool = false
|
||||
var _thrust_input: float = 0.0
|
||||
|
||||
|
||||
func _ready() -> void:
|
||||
_ensure_actions()
|
||||
GameplayInput.command_requested.connect(_handle_vehicle_command)
|
||||
GameplayInput.transient_input_cleared.connect(_clear_vehicle_input)
|
||||
if interaction_area:
|
||||
interaction_area.monitoring = true
|
||||
interaction_area.monitorable = true
|
||||
@@ -193,7 +193,7 @@ func _gravity_accel() -> Vector3:
|
||||
|
||||
func _update_telemetry() -> void:
|
||||
telem_speed = velocity.length()
|
||||
telem_thrust = Input.is_key_pressed(KEY_SPACE)
|
||||
telem_thrust = _thrust_input > 0.0
|
||||
var earth := _earth()
|
||||
if earth:
|
||||
telem_earth_rng = maxf(0.0, global_position.distance_to(earth.global_position) - EARTH_RADIUS)
|
||||
@@ -262,7 +262,7 @@ func _on_body_entered(body: Node3D) -> void:
|
||||
if body.is_in_group("player"):
|
||||
player_ref = body
|
||||
if interact_prompt and not player_inside:
|
||||
interact_prompt.text = "Press F to Enter"
|
||||
interact_prompt.text = "[%s] Enter" % GameplayInput.binding_label(&"interact")
|
||||
interact_prompt.visible = true
|
||||
|
||||
|
||||
@@ -273,103 +273,61 @@ func _on_body_exited(body: Node3D) -> void:
|
||||
interact_prompt.visible = false
|
||||
|
||||
|
||||
func _unhandled_input(event: InputEvent) -> void:
|
||||
if not player_inside:
|
||||
## Handles semantic vehicle commands; proximity permits entry only on foot.
|
||||
func _handle_vehicle_command(action: StringName, command_context: int) -> void:
|
||||
if command_context != GameplayInput.context:
|
||||
return
|
||||
if event.is_action_pressed("ui_cancel"):
|
||||
if pause_menu and pause_menu.has_method("open_pause") and player_ref:
|
||||
pause_menu.open_pause(player_ref)
|
||||
get_viewport().set_input_as_handled()
|
||||
return
|
||||
if _event_toggles(event, "capsule_gear", KEY_G):
|
||||
_gear_down = not _gear_down
|
||||
_set_hull("gear_deploy", 1.0 if _gear_down else 0.0)
|
||||
get_viewport().set_input_as_handled()
|
||||
elif _event_toggles(event, "capsule_hatch_crew", KEY_H):
|
||||
_hatch_crew_open = not _hatch_crew_open
|
||||
_set_hull("hatch_crew_open", 1.0 if _hatch_crew_open else 0.0)
|
||||
get_viewport().set_input_as_handled()
|
||||
elif _event_toggles(event, "capsule_hatch_dock", KEY_J):
|
||||
_hatch_dock_open = not _hatch_dock_open
|
||||
_set_hull("hatch_dock_open", 1.0 if _hatch_dock_open else 0.0)
|
||||
get_viewport().set_input_as_handled()
|
||||
elif _event_toggles(event, "capsule_ladder", KEY_L):
|
||||
_ladder_out = not _ladder_out
|
||||
_set_hull("hatch_ladder_deploy", 1.0 if _ladder_out else 0.0)
|
||||
get_viewport().set_input_as_handled()
|
||||
elif _event_toggles(event, "capsule_instruments", KEY_I):
|
||||
_set_hull("instruments_demo", 1.0)
|
||||
get_viewport().set_input_as_handled()
|
||||
elif _event_toggles(event, "capsule_cabin_light", KEY_K):
|
||||
_cabin_dim = not _cabin_dim
|
||||
_set_hull("cabin_dim", _cabin_dim)
|
||||
get_viewport().set_input_as_handled()
|
||||
|
||||
|
||||
func _ensure_actions() -> void:
|
||||
var binds := {
|
||||
"interact": KEY_F,
|
||||
"toggle_first_person": KEY_V,
|
||||
"capsule_gear": KEY_G,
|
||||
"capsule_hatch_crew": KEY_H,
|
||||
"capsule_hatch_dock": KEY_J,
|
||||
"capsule_ladder": KEY_L,
|
||||
"capsule_instruments": KEY_I,
|
||||
"capsule_cabin_light": KEY_K,
|
||||
}
|
||||
for action in binds.keys():
|
||||
if InputMap.has_action(action):
|
||||
continue
|
||||
InputMap.add_action(action)
|
||||
var ev := InputEventKey.new()
|
||||
ev.physical_keycode = binds[action]
|
||||
InputMap.action_add_event(action, ev)
|
||||
|
||||
|
||||
func _event_toggles(event: InputEvent, action: String, key: Key) -> bool:
|
||||
if InputMap.has_action(action) and event.is_action_pressed(action):
|
||||
return true
|
||||
if event is InputEventKey and event.pressed and not event.echo and event.physical_keycode == key:
|
||||
return true
|
||||
return false
|
||||
|
||||
|
||||
func _act_pressed(action: String) -> bool:
|
||||
return InputMap.has_action(action) and Input.is_action_pressed(action)
|
||||
|
||||
|
||||
func _act_just(action: String) -> bool:
|
||||
return InputMap.has_action(action) and Input.is_action_just_pressed(action)
|
||||
|
||||
|
||||
func _process(delta: float) -> void:
|
||||
var interact_now := _act_just("interact") or _just_key(KEY_F)
|
||||
if not player_inside and player_ref and interact_now:
|
||||
f_was_down = true
|
||||
if action == &"interact":
|
||||
if player_inside:
|
||||
exit_capsule()
|
||||
elif player_ref and interaction_area.overlaps_body(player_ref) and GameplayInput.context == GameplayInput.Context.ON_FOOT:
|
||||
enter_capsule()
|
||||
return
|
||||
if not player_inside:
|
||||
f_was_down = Input.is_physical_key_pressed(KEY_F)
|
||||
_update_crust_exception()
|
||||
if not player_inside or GameplayInput.context != GameplayInput.Context.VEHICLE:
|
||||
return
|
||||
if interact_now and not f_was_down:
|
||||
f_was_down = true
|
||||
exit_capsule()
|
||||
return
|
||||
f_was_down = _act_pressed("interact") or Input.is_physical_key_pressed(KEY_F)
|
||||
if _act_just("toggle_first_person"):
|
||||
match action:
|
||||
&"toggle_view":
|
||||
toggle_camera()
|
||||
elif not InputMap.has_action("toggle_first_person") and _just_key(KEY_V):
|
||||
toggle_camera()
|
||||
var was_free = free_look
|
||||
free_look = Input.is_mouse_button_pressed(MOUSE_BUTTON_RIGHT)
|
||||
if was_free and not free_look and not using_third_person:
|
||||
&"vehicle_toggle_gear":
|
||||
_gear_down = not _gear_down
|
||||
_set_hull("gear_deploy", 1.0 if _gear_down else 0.0)
|
||||
&"vehicle_toggle_crew_hatch":
|
||||
_hatch_crew_open = not _hatch_crew_open
|
||||
_set_hull("hatch_crew_open", 1.0 if _hatch_crew_open else 0.0)
|
||||
&"vehicle_toggle_dock_hatch":
|
||||
_hatch_dock_open = not _hatch_dock_open
|
||||
_set_hull("hatch_dock_open", 1.0 if _hatch_dock_open else 0.0)
|
||||
&"capsule_toggle_ladder":
|
||||
_ladder_out = not _ladder_out
|
||||
_set_hull("hatch_ladder_deploy", 1.0 if _ladder_out else 0.0)
|
||||
&"vehicle_activate_instruments":
|
||||
_set_hull("instruments_demo", 1.0)
|
||||
&"vehicle_toggle_cabin_lights":
|
||||
_cabin_dim = not _cabin_dim
|
||||
_set_hull("cabin_dim", _cabin_dim)
|
||||
|
||||
|
||||
## Clears held cockpit look and visual thrust on menus, handoffs, or focus loss.
|
||||
func _clear_vehicle_input() -> void:
|
||||
free_look = false
|
||||
cockpit_yaw = 0.0
|
||||
cockpit_pitch = 0.0
|
||||
if Input.is_key_pressed(KEY_ALT):
|
||||
Input.mouse_mode = Input.MOUSE_MODE_VISIBLE
|
||||
else:
|
||||
Input.mouse_mode = Input.MOUSE_MODE_CAPTURED
|
||||
_thrust_input = 0.0
|
||||
if player_inside:
|
||||
_set_hull("abort_burn", false)
|
||||
_set_hull("att_pitch", 0.0)
|
||||
_set_hull("att_yaw", 0.0)
|
||||
_set_hull("att_roll", 0.0)
|
||||
|
||||
|
||||
## Updates active vehicle input/cameras while retaining the original flight timing.
|
||||
func _process(delta: float) -> void:
|
||||
if not player_inside:
|
||||
if player_ref and interact_prompt:
|
||||
interact_prompt.text = "[%s] Enter" % GameplayInput.binding_label(&"interact")
|
||||
_update_crust_exception()
|
||||
return
|
||||
_update_vehicle_look(delta)
|
||||
handle_flight(delta)
|
||||
_update_telemetry()
|
||||
_update_flight_hud()
|
||||
@@ -383,30 +341,38 @@ func _process(delta: float) -> void:
|
||||
capsule_camera.make_current()
|
||||
|
||||
|
||||
func _just_key(key: Key) -> bool:
|
||||
var down := Input.is_physical_key_pressed(key)
|
||||
if key == KEY_V:
|
||||
var edge := down and not _v_was
|
||||
_v_was = down
|
||||
return edge
|
||||
return false
|
||||
|
||||
|
||||
func _input(event: InputEvent) -> void:
|
||||
if not player_inside:
|
||||
## Updates cockpit/orbit look without letting menu input reach the vehicle camera.
|
||||
func _update_vehicle_look(delta: float) -> void:
|
||||
var cursor_released := GameplayInput.is_held(&"vehicle_release_cursor")
|
||||
if GameplayInput.gameplay_enabled():
|
||||
Input.mouse_mode = Input.MOUSE_MODE_VISIBLE if cursor_released else Input.MOUSE_MODE_CAPTURED
|
||||
var previous_freelook := free_look
|
||||
free_look = GameplayInput.is_held(&"vehicle_freelook")
|
||||
if previous_freelook and not free_look and not using_third_person:
|
||||
cockpit_yaw = 0.0
|
||||
cockpit_pitch = 0.0
|
||||
var mouse_displacement := GameplayInput.consume_mouse_displacement()
|
||||
if cursor_released:
|
||||
return
|
||||
if Input.is_key_pressed(KEY_ALT):
|
||||
return
|
||||
if event is InputEventMouseMotion:
|
||||
var mouse_turn := mouse_displacement * look_sensitivity
|
||||
var controller_turn := GameplayInput.read_controller_look(delta)
|
||||
if using_third_person:
|
||||
orbit_yaw -= event.relative.x * look_sensitivity
|
||||
orbit_pitch += event.relative.y * look_sensitivity
|
||||
_apply_vehicle_look(mouse_turn + controller_turn)
|
||||
else:
|
||||
_apply_vehicle_look((mouse_turn if free_look else Vector2.ZERO) + controller_turn)
|
||||
|
||||
|
||||
## Applies angular displacement in radians while preserving existing camera limits.
|
||||
func _apply_vehicle_look(look_delta: Vector2) -> void:
|
||||
if using_third_person:
|
||||
orbit_yaw -= look_delta.x
|
||||
orbit_pitch += look_delta.y
|
||||
orbit_pitch = clampf(orbit_pitch, orbit_pitch_min, orbit_pitch_max)
|
||||
elif free_look:
|
||||
cockpit_yaw -= event.relative.x * look_sensitivity
|
||||
cockpit_pitch -= event.relative.y * look_sensitivity
|
||||
cockpit_yaw = clamp(cockpit_yaw, -cockpit_look_limit_yaw, cockpit_look_limit_yaw)
|
||||
cockpit_pitch = clamp(cockpit_pitch, -cockpit_look_limit_down, cockpit_look_limit_up)
|
||||
else:
|
||||
cockpit_yaw -= look_delta.x
|
||||
cockpit_pitch -= look_delta.y
|
||||
cockpit_yaw = clampf(cockpit_yaw, -cockpit_look_limit_yaw, cockpit_look_limit_yaw)
|
||||
cockpit_pitch = clampf(cockpit_pitch, -cockpit_look_limit_down, cockpit_look_limit_up)
|
||||
|
||||
|
||||
func enter_capsule() -> void:
|
||||
@@ -436,7 +402,6 @@ func enter_capsule() -> void:
|
||||
orbit_yaw = 0.0
|
||||
orbit_pitch = 0.4
|
||||
using_third_person = false
|
||||
f_was_down = true
|
||||
free_look = false
|
||||
if camera_pivot:
|
||||
camera_pivot.top_level = false
|
||||
@@ -454,6 +419,7 @@ func enter_capsule() -> void:
|
||||
if flight_label:
|
||||
flight_label.visible = true
|
||||
_update_crust_exception()
|
||||
GameplayInput.set_context(GameplayInput.Context.VEHICLE)
|
||||
|
||||
|
||||
func exit_capsule() -> void:
|
||||
@@ -463,7 +429,6 @@ func exit_capsule() -> void:
|
||||
player_inside = false
|
||||
velocity = Vector3.ZERO
|
||||
free_look = false
|
||||
f_was_down = false
|
||||
using_third_person = false
|
||||
_set_hull("abort_burn", false)
|
||||
_set_hull("rcs_direction", 0)
|
||||
@@ -504,6 +469,7 @@ func exit_capsule() -> void:
|
||||
FloatingOrigin.set_focus(exiting_player)
|
||||
Input.mouse_mode = Input.MOUSE_MODE_CAPTURED
|
||||
player_ref = null
|
||||
GameplayInput.set_context(GameplayInput.Context.ON_FOOT)
|
||||
|
||||
|
||||
func toggle_camera() -> void:
|
||||
@@ -569,27 +535,17 @@ func update_third_person_camera() -> void:
|
||||
third_person_camera.global_basis = cam_basis
|
||||
|
||||
|
||||
## Reads signed flight intent while preserving the existing flight equations/timing.
|
||||
func handle_flight(delta: float) -> void:
|
||||
_update_crust_exception()
|
||||
var input_pitch := 0.0
|
||||
var input_roll := 0.0
|
||||
var input_yaw := 0.0
|
||||
if Input.is_key_pressed(KEY_W):
|
||||
input_pitch -= 1.0
|
||||
if Input.is_key_pressed(KEY_S):
|
||||
input_pitch += 1.0
|
||||
if Input.is_key_pressed(KEY_A):
|
||||
input_yaw += 1.0
|
||||
if Input.is_key_pressed(KEY_D):
|
||||
input_yaw -= 1.0
|
||||
if Input.is_key_pressed(KEY_Q):
|
||||
input_roll -= 1.0
|
||||
if Input.is_key_pressed(KEY_E):
|
||||
input_roll += 1.0
|
||||
var input_pitch := GameplayInput.read_axis(&"vehicle_pitch_up", &"vehicle_pitch_down")
|
||||
var input_roll := GameplayInput.read_axis(&"vehicle_roll_left", &"vehicle_roll_right")
|
||||
var input_yaw := GameplayInput.read_axis(&"vehicle_yaw_right", &"vehicle_yaw_left")
|
||||
rotate_object_local(Vector3.RIGHT, input_pitch * rotation_speed * delta)
|
||||
rotate_object_local(Vector3.FORWARD, -input_yaw * rotation_speed * delta)
|
||||
rotate_object_local(Vector3.UP, input_roll * rotation_speed * delta)
|
||||
var thrusting := Input.is_key_pressed(KEY_SPACE)
|
||||
_thrust_input = GameplayInput.read_strength(&"vehicle_thrust")
|
||||
var thrusting := _thrust_input > 0.0
|
||||
_set_hull("abort_burn", thrusting)
|
||||
_set_hull("att_pitch", input_pitch)
|
||||
_set_hull("att_yaw", input_yaw)
|
||||
@@ -597,7 +553,7 @@ func handle_flight(delta: float) -> void:
|
||||
_set_hull("rcs_direction", 0)
|
||||
var acceleration: Vector3 = _gravity_accel()
|
||||
if thrusting:
|
||||
acceleration += global_transform.basis.y * (thrust_force / mass)
|
||||
acceleration += global_transform.basis.y * (thrust_force / mass) * _thrust_input
|
||||
velocity += acceleration * delta
|
||||
var near_surface := is_on_floor() or _crust_exception
|
||||
if not near_surface:
|
||||
|
||||
@@ -0,0 +1,287 @@
|
||||
extends Node
|
||||
## Device-independent gameplay input. Bindings remain in Godot's InputMap.
|
||||
|
||||
signal command_requested(action: StringName, command_context: int)
|
||||
signal transient_input_cleared
|
||||
|
||||
## Gameplay input context enumeration.
|
||||
## ON_FOOT: Player is on foot and can perform standard movement actions.
|
||||
## VEHICLE: Player is controlling a vehicle and movement actions are mapped accordingly.
|
||||
enum Context { ON_FOOT, VEHICLE }
|
||||
|
||||
## Current gameplay input context.
|
||||
var context: Context = Context.ON_FOOT
|
||||
## Whether sprint is currently enabled.
|
||||
var sprint_enabled: bool = false
|
||||
## Controller turn speed for look input.
|
||||
var controller_turn_speed: Vector2 = Vector2(2.5, 2.0)
|
||||
## Whether the Y-axis of the controller look input is inverted.
|
||||
var invert_controller_y: bool = false
|
||||
## Deadzone for movement stick input.
|
||||
var movement_deadzone: float = 0.2
|
||||
## Deadzone for look stick input.
|
||||
var look_deadzone: float = 0.2
|
||||
## List of nodes that currently own the menu, blocking gameplay input.
|
||||
var _menu_owners: Array[Node] = []
|
||||
## Accumulated mouse displacement since the last frame.
|
||||
var _mouse_displacement: Vector2 = Vector2.ZERO
|
||||
## Whether a jump has been requested this frame.
|
||||
var _jump_requested: bool = false
|
||||
## Whether the input system is waiting for all controls to return to neutral.
|
||||
var _awaiting_neutral: bool = false
|
||||
## Whether the game window is currently focused.
|
||||
var _window_focused: bool = true
|
||||
## Dictionary tracking currently processed but not yet canceled: i.e. when you press the fire button and it has been handled but you have not yet released the button.
|
||||
var _latched_commands: Dictionary = {}
|
||||
## Outgoing/incoming controls monitored until an ownership handoff reaches neutral.
|
||||
var _neutral_actions: Array[StringName] = []
|
||||
|
||||
## List of all trigger-based actions the player can perform.
|
||||
const TRIGGER_ACTIONS: Array[StringName] = [
|
||||
&"interact", &"combat_reload", &"character_toggle_inventory", &"toggle_view",
|
||||
&"combat_toggle_weapon", &"character_toggle_mag_boots", &"character_sprint", &"character_jump", &"combat_fire",
|
||||
&"vehicle_toggle_gear", &"vehicle_toggle_crew_hatch", &"vehicle_toggle_dock_hatch",
|
||||
&"capsule_toggle_ladder", &"vehicle_activate_instruments", &"vehicle_toggle_cabin_lights",
|
||||
]
|
||||
## Explicit command membership; action prefixes are organizational only.
|
||||
const CONTEXT_TRIGGER_ACTIONS: Dictionary = {
|
||||
Context.ON_FOOT: [
|
||||
&"interact", &"toggle_view", &"character_toggle_inventory", &"character_toggle_mag_boots",
|
||||
&"character_sprint", &"character_jump", &"combat_fire", &"combat_reload", &"combat_toggle_weapon",
|
||||
],
|
||||
Context.VEHICLE: [
|
||||
&"interact", &"toggle_view", &"vehicle_toggle_gear", &"vehicle_toggle_crew_hatch",
|
||||
&"vehicle_toggle_dock_hatch", &"capsule_toggle_ladder", &"vehicle_activate_instruments",
|
||||
&"vehicle_toggle_cabin_lights",
|
||||
],
|
||||
}
|
||||
## Commands requiring the controller auxiliary modifier, independent of their names.
|
||||
const VEHICLE_AUXILIARY_ACTIONS: Array[StringName] = [
|
||||
&"vehicle_toggle_gear", &"vehicle_toggle_crew_hatch", &"vehicle_toggle_dock_hatch",
|
||||
&"capsule_toggle_ladder", &"vehicle_activate_instruments", &"vehicle_toggle_cabin_lights",
|
||||
]
|
||||
## List of all axis-based actions the player can perform.
|
||||
const AXIS_ACTIONS: Array[StringName] = [
|
||||
&"character_move_left", &"character_move_right", &"character_move_forward", &"character_move_back",
|
||||
&"look_left", &"look_right", &"look_up", &"look_down",
|
||||
&"eva_roll_left", &"eva_roll_right", &"vehicle_pitch_up", &"vehicle_pitch_down",
|
||||
&"vehicle_yaw_left", &"vehicle_yaw_right", &"vehicle_roll_left", &"vehicle_roll_right",
|
||||
]
|
||||
## Look is shared; character/EVA and vehicle axes belong to distinct contexts.
|
||||
const SHARED_AXIS_ACTIONS: Array[StringName] = [
|
||||
&"look_left", &"look_right", &"look_up", &"look_down",
|
||||
]
|
||||
const CONTEXT_AXIS_ACTIONS: Dictionary = {
|
||||
Context.ON_FOOT: [
|
||||
&"character_move_left", &"character_move_right", &"character_move_forward", &"character_move_back",
|
||||
&"eva_roll_left", &"eva_roll_right",
|
||||
],
|
||||
Context.VEHICLE: [
|
||||
&"vehicle_pitch_up", &"vehicle_pitch_down", &"vehicle_yaw_left", &"vehicle_yaw_right",
|
||||
&"vehicle_roll_left", &"vehicle_roll_right",
|
||||
],
|
||||
}
|
||||
## Held controls are polled, not dispatched through command_requested.
|
||||
const CONTEXT_HELD_ACTIONS: Dictionary = {
|
||||
Context.ON_FOOT: [&"combat_aim", &"freelook", &"release_cursor"],
|
||||
Context.VEHICLE: [&"vehicle_thrust", &"vehicle_freelook", &"vehicle_auxiliary", &"vehicle_release_cursor"],
|
||||
}
|
||||
|
||||
## Connects device/focus boundaries; project defaults are never reapplied on spawn.
|
||||
func _ready() -> void:
|
||||
process_mode = Node.PROCESS_MODE_ALWAYS
|
||||
Input.joy_connection_changed.connect(_on_controller_connection_changed)
|
||||
get_tree().root.focus_entered.connect(_on_focus_entered)
|
||||
get_tree().root.focus_exited.connect(_on_focus_exited)
|
||||
|
||||
|
||||
## Updates neutral gating and ends sprint when the movement stick is released.
|
||||
func _process(_delta: float) -> void:
|
||||
for owner_index in range(_menu_owners.size() - 1, -1, -1):
|
||||
if not is_instance_valid(_menu_owners[owner_index]):
|
||||
_menu_owners.remove_at(owner_index)
|
||||
if _awaiting_neutral and _controls_are_neutral():
|
||||
_awaiting_neutral = false
|
||||
_neutral_actions.clear()
|
||||
if not gameplay_enabled() or read_movement().length_squared() < 0.0001:
|
||||
sprint_enabled = false
|
||||
|
||||
|
||||
## UI receives events first. Only the current gameplay context gets commands.
|
||||
func _unhandled_input(event: InputEvent) -> void:
|
||||
for action in _latched_commands.keys():
|
||||
if event.is_action_released(action):
|
||||
_latched_commands.erase(action)
|
||||
if not gameplay_enabled():
|
||||
return
|
||||
if event is InputEventMouseMotion:
|
||||
if Input.mouse_mode == Input.MOUSE_MODE_CAPTURED:
|
||||
record_mouse_displacement(event.relative)
|
||||
return
|
||||
for action in CONTEXT_TRIGGER_ACTIONS[context]:
|
||||
if event.is_action_pressed(action) and _command_is_available(action, event):
|
||||
if _latched_commands.has(action):
|
||||
return
|
||||
_latched_commands[action] = true
|
||||
get_viewport().set_input_as_handled()
|
||||
if action == &"character_sprint":
|
||||
sprint_enabled = not sprint_enabled
|
||||
elif action == &"character_jump":
|
||||
_jump_requested = true
|
||||
else:
|
||||
command_requested.emit(action, context)
|
||||
return
|
||||
|
||||
|
||||
## Changes control ownership and discards commands from the previous owner.
|
||||
func set_context(next_context: Context) -> void:
|
||||
_monitor_context_for_neutral(context)
|
||||
context = next_context
|
||||
clear_transient_input()
|
||||
|
||||
|
||||
## Blocks gameplay while an owning menu is open; nested menus are supported.
|
||||
func set_menu_open(owner_node: Node, is_open: bool) -> void:
|
||||
if is_open and not _menu_owners.has(owner_node):
|
||||
_menu_owners.append(owner_node)
|
||||
elif not is_open:
|
||||
_menu_owners.erase(owner_node)
|
||||
clear_transient_input()
|
||||
|
||||
|
||||
## Clears held/queued state and requires neutral controls before gameplay resumes.
|
||||
func clear_transient_input() -> void:
|
||||
_monitor_context_for_neutral(context)
|
||||
_mouse_displacement = Vector2.ZERO
|
||||
_jump_requested = false
|
||||
_latched_commands.clear()
|
||||
sprint_enabled = false
|
||||
_awaiting_neutral = true
|
||||
transient_input_cleared.emit()
|
||||
|
||||
|
||||
## Polling must use this gate: UI event consumption does not block Input state.
|
||||
## Returns true if the window is focused, the game is not paused, no menus are open, and we are not awaiting neutral input.
|
||||
func gameplay_enabled() -> bool:
|
||||
return _window_focused and not get_tree().paused and _menu_owners.is_empty() and not _awaiting_neutral
|
||||
|
||||
|
||||
## Checks explicit membership without relying on action naming prefixes.
|
||||
func is_action_available(action: StringName) -> bool:
|
||||
return (
|
||||
CONTEXT_TRIGGER_ACTIONS[context].has(action)
|
||||
or SHARED_AXIS_ACTIONS.has(action)
|
||||
or CONTEXT_AXIS_ACTIONS[context].has(action)
|
||||
or CONTEXT_HELD_ACTIONS[context].has(action)
|
||||
)
|
||||
|
||||
|
||||
## Returns body-relative movement, with forward on negative Y and magnitude <= 1.
|
||||
func read_movement() -> Vector2:
|
||||
if not gameplay_enabled() or context != Context.ON_FOOT:
|
||||
return Vector2.ZERO
|
||||
return Input.get_vector("character_move_left", "character_move_right", "character_move_forward", "character_move_back", movement_deadzone)
|
||||
|
||||
|
||||
## Returns signed analog strength without exposing device axes to gameplay.
|
||||
func read_axis(negative_action: StringName, positive_action: StringName) -> float:
|
||||
if not gameplay_enabled() or not is_action_available(negative_action) or not is_action_available(positive_action):
|
||||
return 0.0
|
||||
return Input.get_axis(negative_action, positive_action)
|
||||
|
||||
|
||||
## Returns an unsigned analog command strength in the range 0..1.
|
||||
func read_strength(action: StringName) -> float:
|
||||
return Input.get_action_strength(action) if gameplay_enabled() and is_action_available(action) else 0.0
|
||||
|
||||
|
||||
## Returns a held action; future automatic weapons can use this independently of presses.
|
||||
func is_held(action: StringName) -> bool:
|
||||
return gameplay_enabled() and is_action_available(action) and Input.is_action_pressed(action)
|
||||
|
||||
|
||||
## Consumes one UI-aware jump request during the next physics update.
|
||||
func consume_jump_request() -> bool:
|
||||
var requested: bool = _jump_requested and gameplay_enabled()
|
||||
_jump_requested = false
|
||||
return requested
|
||||
|
||||
|
||||
## Accumulates mouse pixels independently of the render/physics update rates.
|
||||
func record_mouse_displacement(displacement: Vector2) -> void:
|
||||
if gameplay_enabled():
|
||||
_mouse_displacement += displacement
|
||||
|
||||
|
||||
## Consumes mouse pixels, once per camera update, without time scaling.
|
||||
func consume_mouse_displacement() -> Vector2:
|
||||
var displacement := _mouse_displacement if gameplay_enabled() else Vector2.ZERO
|
||||
_mouse_displacement = Vector2.ZERO
|
||||
return displacement
|
||||
|
||||
|
||||
## Returns stick angular displacement in radians for this frame; positive Y looks down.
|
||||
func read_controller_look(delta: float) -> Vector2:
|
||||
if not gameplay_enabled():
|
||||
return Vector2.ZERO
|
||||
var stick := Input.get_vector("look_left", "look_right", "look_up", "look_down", look_deadzone)
|
||||
if invert_controller_y:
|
||||
stick.y = -stick.y
|
||||
return stick * controller_turn_speed * delta
|
||||
|
||||
|
||||
## Returns a current-device binding label, with a fallback for unmapped actions.
|
||||
func binding_label(action: StringName) -> String:
|
||||
var helper := get_node_or_null("/root/InputHelper")
|
||||
if helper == null:
|
||||
return "Unbound"
|
||||
var binding: InputEvent = helper.get_keyboard_or_joypad_input_for_action(action)
|
||||
return helper.get_label_for_input(binding) if binding != null else "Unbound"
|
||||
|
||||
|
||||
## Restricts contextual commands and routes modifier-layer controller buttons.
|
||||
func _command_is_available(action: StringName, event: InputEvent) -> bool:
|
||||
if not CONTEXT_TRIGGER_ACTIONS[context].has(action):
|
||||
return false
|
||||
if context == Context.VEHICLE and event is InputEventJoypadButton:
|
||||
var auxiliary_layer := Input.is_action_pressed("vehicle_auxiliary")
|
||||
return auxiliary_layer if VEHICLE_AUXILIARY_ACTIONS.has(action) else not auxiliary_layer
|
||||
return true
|
||||
|
||||
|
||||
## Adds only relevant controls to a handoff; unrelated future axes cannot block it.
|
||||
func _monitor_context_for_neutral(monitored_context: Context) -> void:
|
||||
var actions: Array = CONTEXT_TRIGGER_ACTIONS[monitored_context] + SHARED_AXIS_ACTIONS
|
||||
actions.append_array(CONTEXT_AXIS_ACTIONS[monitored_context])
|
||||
actions.append_array(CONTEXT_HELD_ACTIONS[monitored_context])
|
||||
for action in actions:
|
||||
if not _neutral_actions.has(action):
|
||||
_neutral_actions.append(action)
|
||||
|
||||
|
||||
## Waits for outgoing/incoming controls, including latched command releases.
|
||||
func _controls_are_neutral() -> bool:
|
||||
for action in _neutral_actions:
|
||||
if not AXIS_ACTIONS.has(action) and Input.is_action_pressed(action):
|
||||
return false
|
||||
if Input.get_action_strength(action) > 0.2:
|
||||
return false
|
||||
return true
|
||||
|
||||
|
||||
## Disconnects clear held commands; reconnects require neutral input too.
|
||||
func _on_controller_connection_changed(_device: int, _connected: bool) -> void:
|
||||
clear_transient_input()
|
||||
|
||||
|
||||
## Window focus loss must not leave firing, look, or sprint latched.
|
||||
func _on_focus_exited() -> void:
|
||||
_window_focused = false
|
||||
clear_transient_input()
|
||||
|
||||
|
||||
## Focus restoration requires a fresh press rather than replaying held controls.
|
||||
func _on_focus_entered() -> void:
|
||||
_window_focused = true
|
||||
clear_transient_input()
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
uid://bd26m8dx3k2pn
|
||||
@@ -7,6 +7,7 @@ extends Control
|
||||
|
||||
func _ready() -> void:
|
||||
Input.mouse_mode = Input.MOUSE_MODE_VISIBLE
|
||||
GameplayInput.set_menu_open(self, true)
|
||||
if new_game_button:
|
||||
new_game_button.pressed.connect(_on_new_game)
|
||||
if continue_button:
|
||||
@@ -15,6 +16,12 @@ func _ready() -> void:
|
||||
quit_button.pressed.connect(_on_quit)
|
||||
if continue_button:
|
||||
continue_button.disabled = not GameState.has_save
|
||||
new_game_button.grab_focus()
|
||||
|
||||
|
||||
## Removes menu ownership when changing scenes so gameplay can resume.
|
||||
func _exit_tree() -> void:
|
||||
GameplayInput.set_menu_open(self, false)
|
||||
|
||||
|
||||
func _on_new_game() -> void:
|
||||
|
||||
@@ -17,8 +17,11 @@ func _ready() -> void:
|
||||
quit_button.pressed.connect(_on_quit_to_menu)
|
||||
|
||||
|
||||
## Pause has its own binding; menu cancel must not pause during gameplay.
|
||||
func _input(event: InputEvent) -> void:
|
||||
if not event.is_action_pressed("ui_cancel"):
|
||||
var pause_pressed := event.is_action_pressed("ui_pause")
|
||||
var cancel_pressed := event.is_action_pressed("ui_cancel")
|
||||
if not pause_pressed and not (visible and cancel_pressed):
|
||||
return
|
||||
var banner := get_node_or_null("/root/Node3D/HUD/ScrambleBanner")
|
||||
if banner and banner.visible:
|
||||
@@ -27,6 +30,8 @@ func _input(event: InputEvent) -> void:
|
||||
_on_resume()
|
||||
get_viewport().set_input_as_handled()
|
||||
return
|
||||
if not GameplayInput.gameplay_enabled():
|
||||
return
|
||||
var p := get_tree().get_first_node_in_group("player")
|
||||
if p == null:
|
||||
p = get_node_or_null("/root/Node3D/Player")
|
||||
@@ -35,16 +40,21 @@ func _input(event: InputEvent) -> void:
|
||||
get_viewport().set_input_as_handled()
|
||||
|
||||
|
||||
## Blocks gameplay and selects a controller-accessible control before pausing.
|
||||
func open_pause(player_ref: Node) -> void:
|
||||
player = player_ref
|
||||
visible = true
|
||||
GameplayInput.set_menu_open(self, true)
|
||||
resume_button.grab_focus()
|
||||
Input.mouse_mode = Input.MOUSE_MODE_VISIBLE
|
||||
get_tree().paused = true
|
||||
|
||||
|
||||
## Restores control only after currently held gameplay inputs return to neutral.
|
||||
func _on_resume() -> void:
|
||||
visible = false
|
||||
get_tree().paused = false
|
||||
GameplayInput.set_menu_open(self, false)
|
||||
Input.mouse_mode = Input.MOUSE_MODE_CAPTURED
|
||||
|
||||
|
||||
@@ -59,5 +69,6 @@ func _on_save() -> void:
|
||||
|
||||
func _on_quit_to_menu() -> void:
|
||||
get_tree().paused = false
|
||||
GameplayInput.set_menu_open(self, false)
|
||||
Input.mouse_mode = Input.MOUSE_MODE_VISIBLE
|
||||
get_tree().change_scene_to_file("res://Scenes/main_menu.tscn")
|
||||
|
||||
+118
-117
@@ -117,34 +117,14 @@ var interact_cd: float = 0.0
|
||||
var jump_anim_cd: float = 0.0
|
||||
var _crust_on: bool = false
|
||||
var _moon_colliders: Array[PhysicsBody3D] = []
|
||||
|
||||
|
||||
func _ensure_action(action: String, keycode: Key) -> void:
|
||||
if not InputMap.has_action(action):
|
||||
InputMap.add_action(action)
|
||||
for ev in InputMap.action_get_events(action):
|
||||
if ev is InputEventKey and (ev as InputEventKey).physical_keycode == keycode:
|
||||
return
|
||||
var evk := InputEventKey.new()
|
||||
evk.physical_keycode = keycode
|
||||
InputMap.action_add_event(action, evk)
|
||||
|
||||
|
||||
func _ensure_default_actions() -> void:
|
||||
_ensure_action("interact", KEY_F)
|
||||
_ensure_action("mag_boots", KEY_C)
|
||||
_ensure_action("toggle_mag_boots", KEY_C)
|
||||
_ensure_action("toggle_pistol", KEY_G)
|
||||
_ensure_action("reload", KEY_R)
|
||||
_ensure_action("toggle_inventory", KEY_TAB)
|
||||
_ensure_action("toggle_first_person", KEY_V)
|
||||
_ensure_action("sprint", KEY_SHIFT)
|
||||
_ensure_action("eva_roll_left", KEY_Q)
|
||||
_ensure_action("eva_roll_right", KEY_E)
|
||||
var _movement_input: Vector2 = Vector2.ZERO
|
||||
var _fire_requested: bool = false
|
||||
|
||||
|
||||
func _ready() -> void:
|
||||
_ensure_default_actions()
|
||||
GameplayInput.command_requested.connect(_handle_gameplay_command)
|
||||
GameplayInput.transient_input_cleared.connect(_clear_player_input)
|
||||
GameplayInput.set_context(GameplayInput.Context.ON_FOOT)
|
||||
scale = Vector3.ONE
|
||||
safe_margin = 0.05
|
||||
floor_snap_length = 0.45
|
||||
@@ -383,6 +363,7 @@ func _find_l5_spawn() -> Node3D:
|
||||
|
||||
func set_in_vehicle(value: bool) -> void:
|
||||
in_vehicle = value
|
||||
_clear_player_input()
|
||||
if value:
|
||||
pressurized = true
|
||||
_set_moon_surface_visible(true)
|
||||
@@ -408,7 +389,10 @@ func _update_waist_aim() -> void:
|
||||
look_loader.set_aim_pitch(pitch)
|
||||
|
||||
|
||||
## Updates device-independent camera look before existing visual camera smoothing.
|
||||
func _process(delta: float) -> void:
|
||||
if not in_vehicle:
|
||||
_update_player_look(delta)
|
||||
if first_person:
|
||||
_cam_pos_target = _fp_cam_pos()
|
||||
_update_fp_meshes()
|
||||
@@ -723,92 +707,17 @@ func _set_alt_look(on: bool) -> void:
|
||||
camera_pivot.rotation.z = 0.0
|
||||
|
||||
|
||||
## Keeps development shortcuts separate from remappable gameplay controls.
|
||||
func _unhandled_input(event: InputEvent) -> void:
|
||||
if in_vehicle:
|
||||
if in_vehicle or not GameplayInput.gameplay_enabled():
|
||||
return
|
||||
if vendor_menu and vendor_menu.visible:
|
||||
if event.is_action_pressed("ui_cancel"):
|
||||
close_vendor_menu()
|
||||
return
|
||||
if event is InputEventKey and event.keycode == KEY_QUOTELEFT:
|
||||
if event.pressed:
|
||||
Input.mouse_mode = Input.MOUSE_MODE_VISIBLE
|
||||
else:
|
||||
if not get_tree().paused and not (vendor_menu and vendor_menu.visible):
|
||||
Input.mouse_mode = Input.MOUSE_MODE_CAPTURED
|
||||
return
|
||||
if event is InputEventKey and event.keycode == KEY_ALT:
|
||||
_set_alt_look(event.pressed)
|
||||
return
|
||||
if event is InputEventMouseButton and event.button_index == MOUSE_BUTTON_RIGHT:
|
||||
if pistol_drawn:
|
||||
ads = event.pressed
|
||||
_apply_camera_mode(false)
|
||||
if event is InputEventMouseButton and event.button_index == MOUSE_BUTTON_LEFT and event.pressed:
|
||||
if pistol_drawn:
|
||||
_try_fire()
|
||||
if event is InputEventMouseMotion and Input.mouse_mode == Input.MOUSE_MODE_CAPTURED:
|
||||
if _is_eva():
|
||||
# Whole-body look in 1P and 3P EVA. World-Y yaw felt broken after a roll.
|
||||
rotate_object_local(Vector3.UP, -event.relative.x * mouse_sensitivity)
|
||||
rotate_object_local(Vector3.RIGHT, -event.relative.y * mouse_sensitivity)
|
||||
if camera_pivot:
|
||||
camera_pivot.rotation = Vector3.ZERO
|
||||
elif first_person:
|
||||
if free_looking:
|
||||
# Euler SET — rotate_x+rotate_y on a pitched pivot was the warp.
|
||||
free_look_yaw -= event.relative.x * mouse_sensitivity
|
||||
free_look_pitch -= event.relative.y * mouse_sensitivity
|
||||
free_look_pitch = clamp(free_look_pitch, deg_to_rad(-78), deg_to_rad(62))
|
||||
free_look_yaw = clamp(free_look_yaw, deg_to_rad(-75), deg_to_rad(75))
|
||||
camera_pivot.rotation = Vector3(free_look_pitch, free_look_yaw, 0.0)
|
||||
else:
|
||||
rotate_y(-event.relative.x * mouse_sensitivity)
|
||||
camera_pivot.rotate_x(-event.relative.y * mouse_sensitivity)
|
||||
camera_pivot.rotation.x = clamp(camera_pivot.rotation.x, deg_to_rad(-78), deg_to_rad(85))
|
||||
elif free_looking:
|
||||
free_look_yaw -= event.relative.x * free_look_sensitivity
|
||||
free_look_pitch -= event.relative.y * free_look_sensitivity
|
||||
free_look_pitch = clamp(free_look_pitch, deg_to_rad(-80), deg_to_rad(80))
|
||||
if camera_pivot:
|
||||
camera_pivot.rotation.y = free_look_yaw
|
||||
camera_pivot.rotation.x = free_look_pitch
|
||||
else:
|
||||
rotate_y(-event.relative.x * mouse_sensitivity)
|
||||
camera_pivot.rotate_x(-event.relative.y * mouse_sensitivity)
|
||||
camera_pivot.rotation.x = clamp(camera_pivot.rotation.x, deg_to_rad(-78), deg_to_rad(55))
|
||||
if event is InputEventKey and event.pressed and not event.echo:
|
||||
match event.keycode:
|
||||
KEY_1:
|
||||
_toggle_pistol()
|
||||
KEY_F3:
|
||||
_debug_fp_eye()
|
||||
KEY_F4:
|
||||
if look_loader and look_loader.has_method("cycle_arm_axis"):
|
||||
look_loader.cycle_arm_axis()
|
||||
if event.is_action_pressed("interact"):
|
||||
if can_interact and current_interactable:
|
||||
_try_interact()
|
||||
if event.is_action_pressed("mag_boots"):
|
||||
mag_boots_on = not mag_boots_on
|
||||
if mag_boots_on:
|
||||
eva_peak_height = 0.0
|
||||
velocity = velocity.slide(_walk_up()) * 0.35
|
||||
_align_walk(_walk_up())
|
||||
_reset_camera_to_walk()
|
||||
print("Mag Boots: ", "ON" if mag_boots_on else "OFF")
|
||||
if event.is_action_pressed("toggle_pistol"):
|
||||
_toggle_pistol()
|
||||
if event.is_action_pressed("reload"):
|
||||
_reload_pistol()
|
||||
if event.is_action_pressed("toggle_inventory"):
|
||||
inventory_open = not inventory_open
|
||||
if event.is_action_pressed("toggle_first_person"):
|
||||
if in_vehicle:
|
||||
return
|
||||
first_person = not first_person
|
||||
_set_alt_look(false)
|
||||
_apply_camera_mode(false)
|
||||
if event.is_action_pressed("ui_page_up"):
|
||||
food = min(food + 25.0, 100.0)
|
||||
if event.is_action_pressed("ui_page_down"):
|
||||
@@ -825,6 +734,93 @@ func _unhandled_input(event: InputEvent) -> void:
|
||||
banner.hide_banner()
|
||||
|
||||
|
||||
## Dispatches device-independent commands only while the player owns control.
|
||||
func _handle_gameplay_command(action: StringName, command_context: int) -> void:
|
||||
if in_vehicle or command_context != GameplayInput.Context.ON_FOOT or GameplayInput.context != command_context:
|
||||
return
|
||||
match action:
|
||||
&"interact":
|
||||
if can_interact and current_interactable:
|
||||
_try_interact()
|
||||
&"combat_fire":
|
||||
_fire_requested = pistol_drawn
|
||||
&"combat_reload":
|
||||
_reload_pistol()
|
||||
&"combat_toggle_weapon":
|
||||
_toggle_pistol()
|
||||
&"character_toggle_inventory":
|
||||
inventory_open = not inventory_open
|
||||
&"toggle_view":
|
||||
first_person = not first_person
|
||||
_set_alt_look(false)
|
||||
_apply_camera_mode(false)
|
||||
&"character_toggle_mag_boots":
|
||||
_toggle_magnetic_boots()
|
||||
|
||||
|
||||
## Toggles boots without changing the existing landing or gravity mechanics.
|
||||
func _toggle_magnetic_boots() -> void:
|
||||
mag_boots_on = not mag_boots_on
|
||||
if mag_boots_on:
|
||||
eva_peak_height = 0.0
|
||||
velocity = velocity.slide(_walk_up()) * 0.35
|
||||
_align_walk(_walk_up())
|
||||
_reset_camera_to_walk()
|
||||
print("Mag Boots: ", "ON" if mag_boots_on else "OFF")
|
||||
|
||||
|
||||
## Clears pending shots and held camera states at input ownership boundaries.
|
||||
func _clear_player_input() -> void:
|
||||
_movement_input = Vector2.ZERO
|
||||
_fire_requested = false
|
||||
ads = false
|
||||
_set_alt_look(false)
|
||||
_apply_camera_mode(false)
|
||||
|
||||
|
||||
## Combines mouse displacement and time-scaled controller turn rate once per frame.
|
||||
func _update_player_look(delta: float) -> void:
|
||||
var cursor_released := GameplayInput.is_held(&"release_cursor")
|
||||
if GameplayInput.gameplay_enabled():
|
||||
Input.mouse_mode = Input.MOUSE_MODE_VISIBLE if cursor_released else Input.MOUSE_MODE_CAPTURED
|
||||
var next_freelook := GameplayInput.is_held(&"freelook")
|
||||
if next_freelook != free_looking:
|
||||
_set_alt_look(next_freelook)
|
||||
var next_aim := pistol_drawn and GameplayInput.is_held(&"combat_aim")
|
||||
if next_aim != ads:
|
||||
ads = next_aim
|
||||
_apply_camera_mode(false)
|
||||
var mouse_displacement := GameplayInput.consume_mouse_displacement()
|
||||
if cursor_released:
|
||||
return
|
||||
var sensitivity := free_look_sensitivity if free_looking and not first_person else mouse_sensitivity
|
||||
_apply_player_look(mouse_displacement * sensitivity + GameplayInput.read_controller_look(delta))
|
||||
|
||||
|
||||
## Applies radians of yaw/pitch to existing walking, freelook, and body-local EVA modes.
|
||||
func _apply_player_look(look_delta: Vector2) -> void:
|
||||
if camera_pivot == null or look_delta == Vector2.ZERO:
|
||||
return
|
||||
if _is_eva():
|
||||
rotate_object_local(Vector3.UP, -look_delta.x)
|
||||
rotate_object_local(Vector3.RIGHT, -look_delta.y)
|
||||
camera_pivot.rotation = Vector3.ZERO
|
||||
elif free_looking:
|
||||
free_look_yaw -= look_delta.x
|
||||
free_look_pitch -= look_delta.y
|
||||
var minimum_pitch := deg_to_rad(-78.0) if first_person else deg_to_rad(-80.0)
|
||||
var maximum_pitch := deg_to_rad(62.0) if first_person else deg_to_rad(80.0)
|
||||
free_look_pitch = clampf(free_look_pitch, minimum_pitch, maximum_pitch)
|
||||
if first_person:
|
||||
free_look_yaw = clampf(free_look_yaw, deg_to_rad(-75.0), deg_to_rad(75.0))
|
||||
camera_pivot.rotation = Vector3(free_look_pitch, free_look_yaw, 0.0)
|
||||
else:
|
||||
rotate_y(-look_delta.x)
|
||||
var maximum_pitch := deg_to_rad(85.0) if first_person else deg_to_rad(55.0)
|
||||
camera_pivot.rotation.x = clampf(camera_pivot.rotation.x - look_delta.y, deg_to_rad(-78.0), maximum_pitch)
|
||||
|
||||
|
||||
## Samples movement once and consumes queued jump/fire requests on physics ticks.
|
||||
func _physics_process(delta: float) -> void:
|
||||
_update_crust_exception()
|
||||
if fire_cd > 0.0:
|
||||
@@ -838,6 +834,12 @@ func _physics_process(delta: float) -> void:
|
||||
if vendor_menu and vendor_menu.visible:
|
||||
velocity = Vector3.ZERO
|
||||
return
|
||||
_movement_input = GameplayInput.read_movement()
|
||||
var jump_requested := GameplayInput.consume_jump_request()
|
||||
if _fire_requested:
|
||||
_fire_requested = false
|
||||
if GameplayInput.gameplay_enabled() and pistol_drawn:
|
||||
_try_fire()
|
||||
if is_on_floor():
|
||||
coyote_time = 0.14
|
||||
else:
|
||||
@@ -846,17 +848,15 @@ func _physics_process(delta: float) -> void:
|
||||
var gvec: Vector3 = _soi_gravity()
|
||||
if _is_eva():
|
||||
_set_body_visible(true)
|
||||
if Input.is_action_pressed("eva_roll_left") or Input.is_key_pressed(KEY_Q):
|
||||
rotate_object_local(Vector3.FORWARD, -2.2 * delta)
|
||||
if Input.is_action_pressed("eva_roll_right") or Input.is_key_pressed(KEY_E):
|
||||
rotate_object_local(Vector3.FORWARD, 2.2 * delta)
|
||||
var roll_input := GameplayInput.read_axis(&"eva_roll_left", &"eva_roll_right")
|
||||
rotate_object_local(Vector3.FORWARD, roll_input * 2.2 * delta)
|
||||
if gvec.length() > 0.01:
|
||||
velocity += gvec * delta
|
||||
var input_dir_eva: Vector2 = Input.get_vector("ui_left", "ui_right", "ui_up", "ui_down")
|
||||
if input_dir_eva.length() > 0.1:
|
||||
var input_dir_eva: Vector2 = _movement_input
|
||||
if input_dir_eva.length() > 0.001:
|
||||
var thrust: Vector3 = (
|
||||
-transform.basis.z * -input_dir_eva.y + transform.basis.x * input_dir_eva.x
|
||||
).normalized() * speed * 0.35
|
||||
) * speed * 0.35
|
||||
velocity += thrust * delta
|
||||
move_and_slide()
|
||||
_process_needs(delta)
|
||||
@@ -876,13 +876,13 @@ func _physics_process(delta: float) -> void:
|
||||
else:
|
||||
g_amt = maxf(g_amt, MOON_G)
|
||||
velocity += -up * g_amt * delta
|
||||
var input_dir: Vector2 = Input.get_vector("ui_left", "ui_right", "ui_up", "ui_down")
|
||||
var input_dir: Vector2 = _movement_input
|
||||
var direction: Vector3 = (transform.basis * Vector3(input_dir.x, 0.0, input_dir.y)).slide(up)
|
||||
if direction.length() > 0.001:
|
||||
direction = direction.normalized()
|
||||
direction = direction.normalized() * input_dir.length()
|
||||
else:
|
||||
direction = Vector3.ZERO
|
||||
var want_sprint: bool = Input.is_action_pressed("sprint") and input_dir.y < -0.12
|
||||
var want_sprint: bool = GameplayInput.sprint_enabled and input_dir.y < -0.12
|
||||
var current_speed: float = sprint_speed if want_sprint else speed
|
||||
if ads and pistol_drawn:
|
||||
current_speed *= ads_sprint_scale if want_sprint else ads_walk_scale
|
||||
@@ -904,13 +904,13 @@ func _physics_process(delta: float) -> void:
|
||||
velocity = v_h + up * v_up
|
||||
# Jump LAST so floor rebuild cannot eat or replace the impulse.
|
||||
var can_jump: bool = is_on_floor() or coyote_time > 0.0
|
||||
if Input.is_action_just_pressed("ui_accept") and can_jump:
|
||||
if jump_requested and can_jump:
|
||||
coyote_time = 0.0
|
||||
jump_anim_cd = 0.45
|
||||
var jv: float = 1.7 if mag_boots_on else 6.4
|
||||
velocity = velocity.slide(up) + up * jv
|
||||
print("JUMP boots=", mag_boots_on, " jv=", jv, " g=", g_amt, " floor=", is_on_floor())
|
||||
if is_on_floor() and not Input.is_action_just_pressed("ui_accept"):
|
||||
if is_on_floor() and not jump_requested:
|
||||
_try_step(up)
|
||||
move_and_slide()
|
||||
_keep_walk_upright()
|
||||
@@ -1033,6 +1033,7 @@ func open_vendor_menu() -> void:
|
||||
func close_vendor_menu() -> void:
|
||||
if vendor_menu:
|
||||
vendor_menu.visible = false
|
||||
GameplayInput.set_menu_open(vendor_menu, false)
|
||||
Input.mouse_mode = Input.MOUSE_MODE_CAPTURED
|
||||
|
||||
|
||||
@@ -1055,10 +1056,10 @@ func _update_animations() -> void:
|
||||
_play_move_anim("Idle")
|
||||
return
|
||||
# Stick, not velocity — accel must not pick the clip.
|
||||
var stick: Vector2 = Input.get_vector("ui_left", "ui_right", "ui_up", "ui_down")
|
||||
var stick: Vector2 = _movement_input
|
||||
var strafe: float = clampf(stick.x, -1.0, 1.0)
|
||||
var back: float = clampf(stick.y, -1.0, 1.0)
|
||||
var want_sprint: bool = Input.is_action_pressed("sprint") and stick.y < -0.12
|
||||
var want_sprint: bool = GameplayInput.sprint_enabled and stick.y < -0.12
|
||||
var run_amt: float = 1.0 if want_sprint else 0.0
|
||||
if look_loader and look_loader.has_method("set_loco"):
|
||||
look_loader.set_loco(strafe, back, run_amt, dt, _is_aiming())
|
||||
@@ -1073,7 +1074,7 @@ func _update_animations() -> void:
|
||||
|
||||
func _update_hud() -> void:
|
||||
if needs_label:
|
||||
var interact_text: String = " [F] Use" if can_interact else ""
|
||||
var interact_text: String = " [%s] Use" % GameplayInput.binding_label(&"interact") if can_interact else ""
|
||||
var gun_text: String = ""
|
||||
if pistol_drawn:
|
||||
gun_text = " | PISTOL %d/%d%s" % [pistol_ammo, pistol_reserve, " ADS" if ads else ""]
|
||||
|
||||
@@ -71,10 +71,14 @@ func _ready() -> void:
|
||||
|
||||
visible = false
|
||||
|
||||
## Claims menu input and gives controllers a predictable initial focus.
|
||||
func open_menu(player_ref: Node) -> void:
|
||||
player = player_ref
|
||||
visible = true
|
||||
GameplayInput.set_menu_open(self, true)
|
||||
Input.mouse_mode = Input.MOUSE_MODE_VISIBLE
|
||||
_update_button_states()
|
||||
close_button.grab_focus()
|
||||
print("Vendor menu opened")
|
||||
|
||||
func _update_button_states() -> void:
|
||||
@@ -112,6 +116,15 @@ func _buy(item_name: String, price: int) -> void:
|
||||
else:
|
||||
print("Not enough credits")
|
||||
|
||||
## Cancels the vendor without allowing the same event to reach gameplay.
|
||||
func _unhandled_input(event: InputEvent) -> void:
|
||||
if visible and event.is_action_pressed("ui_cancel"):
|
||||
_on_close_pressed()
|
||||
get_viewport().set_input_as_handled()
|
||||
|
||||
|
||||
## Releases menu ownership; the adapter clears queued and held commands.
|
||||
func _on_close_pressed() -> void:
|
||||
visible = false
|
||||
GameplayInput.set_menu_open(self, false)
|
||||
Input.mouse_mode = Input.MOUSE_MODE_CAPTURED
|
||||
|
||||
+209
-6
@@ -21,6 +21,7 @@ GameState="*uid://b3o7ua8cv55tq"
|
||||
FloatingOrigin="*uid://ckl5inm8ugypo"
|
||||
InputHelper="*uid://cholww48njaeh"
|
||||
Audio="*uid://cujwm7u5pvogl"
|
||||
GameplayInput="*res://Scenes/Scripts/gameplay_input.gd"
|
||||
|
||||
[display]
|
||||
|
||||
@@ -38,6 +39,20 @@ import/blender/enabled=false
|
||||
|
||||
[input]
|
||||
|
||||
ui_accept={
|
||||
"deadzone": 0.2,
|
||||
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":16,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":4194309,"physical_keycode":0,"key_label":0,"unicode":0,"location":0,"echo":false,"script":null)
|
||||
, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":16,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":4194310,"physical_keycode":0,"key_label":0,"unicode":0,"location":0,"echo":false,"script":null)
|
||||
, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":16,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":32,"physical_keycode":0,"key_label":0,"unicode":0,"location":0,"echo":false,"script":null)
|
||||
, Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":-1,"button_index":0,"pressure":0.0,"pressed":false,"script":null)
|
||||
]
|
||||
}
|
||||
ui_cancel={
|
||||
"deadzone": 0.2,
|
||||
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":16,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":4194305,"physical_keycode":0,"key_label":0,"unicode":0,"location":0,"echo":false,"script":null)
|
||||
, Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":-1,"button_index":1,"pressure":0.0,"pressed":false,"script":null)
|
||||
]
|
||||
}
|
||||
ui_left={
|
||||
"deadzone": 0.5,
|
||||
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":16,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":4194319,"physical_keycode":0,"key_label":0,"unicode":0,"location":0,"echo":false,"script":null)
|
||||
@@ -70,49 +85,237 @@ ui_down={
|
||||
, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":83,"key_label":0,"unicode":115,"location":0,"echo":false,"script":null)
|
||||
]
|
||||
}
|
||||
toggle_mag_boots={
|
||||
character_toggle_mag_boots={
|
||||
"deadzone": 0.2,
|
||||
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":67,"key_label":0,"unicode":99,"location":0,"echo":false,"script":null)
|
||||
, Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":-1,"button_index":12,"pressure":0.0,"pressed":false,"script":null)
|
||||
]
|
||||
}
|
||||
interact={
|
||||
"deadzone": 0.2,
|
||||
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":70,"key_label":0,"unicode":102,"location":0,"echo":false,"script":null)
|
||||
, Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":-1,"button_index":2,"pressure":0.0,"pressed":false,"script":null)
|
||||
]
|
||||
}
|
||||
sprint={
|
||||
character_sprint={
|
||||
"deadzone": 0.2,
|
||||
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":4194325,"key_label":0,"unicode":0,"location":0,"echo":false,"script":null)
|
||||
, Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":-1,"button_index":7,"pressure":0.0,"pressed":false,"script":null)
|
||||
]
|
||||
}
|
||||
toggle_inventory={
|
||||
character_toggle_inventory={
|
||||
"deadzone": 0.2,
|
||||
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":4194306,"key_label":0,"unicode":0,"location":0,"echo":false,"script":null)
|
||||
, Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":-1,"button_index":4,"pressure":0.0,"pressed":false,"script":null)
|
||||
]
|
||||
}
|
||||
toggle_first_person={
|
||||
toggle_view={
|
||||
"deadzone": 0.2,
|
||||
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":86,"key_label":0,"unicode":118,"location":0,"echo":false,"script":null)
|
||||
, Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":-1,"button_index":11,"pressure":0.0,"pressed":false,"script":null)
|
||||
]
|
||||
}
|
||||
toggle_pistol={
|
||||
combat_toggle_weapon={
|
||||
"deadzone": 0.2,
|
||||
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":71,"key_label":0,"unicode":103,"location":0,"echo":false,"script":null)
|
||||
, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":16,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":49,"key_label":0,"unicode":0,"location":0,"echo":false,"script":null)
|
||||
, Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":-1,"button_index":3,"pressure":0.0,"pressed":false,"script":null)
|
||||
]
|
||||
}
|
||||
reload={
|
||||
combat_reload={
|
||||
"deadzone": 0.2,
|
||||
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":82,"key_label":0,"unicode":114,"location":0,"echo":false,"script":null)
|
||||
, Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":-1,"button_index":1,"pressure":0.0,"pressed":false,"script":null)
|
||||
]
|
||||
}
|
||||
eva_roll_left={
|
||||
"deadzone": 0.2,
|
||||
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":81,"key_label":0,"unicode":113,"location":0,"echo":false,"script":null)
|
||||
, Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":-1,"button_index":9,"pressure":0.0,"pressed":false,"script":null)
|
||||
]
|
||||
}
|
||||
eva_roll_right={
|
||||
"deadzone": 0.2,
|
||||
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":69,"key_label":0,"unicode":101,"location":0,"echo":false,"script":null)
|
||||
, Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":-1,"button_index":10,"pressure":0.0,"pressed":false,"script":null)
|
||||
]
|
||||
}
|
||||
character_move_left={
|
||||
"deadzone": 0.2,
|
||||
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":16,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":65,"key_label":0,"unicode":0,"location":0,"echo":false,"script":null)
|
||||
, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":16,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":4194319,"key_label":0,"unicode":0,"location":0,"echo":false,"script":null)
|
||||
, Object(InputEventJoypadMotion,"resource_local_to_scene":false,"resource_name":"","device":-1,"axis":0,"axis_value":-1.0,"script":null)
|
||||
]
|
||||
}
|
||||
character_move_right={
|
||||
"deadzone": 0.2,
|
||||
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":16,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":68,"key_label":0,"unicode":0,"location":0,"echo":false,"script":null)
|
||||
, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":16,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":4194321,"key_label":0,"unicode":0,"location":0,"echo":false,"script":null)
|
||||
, Object(InputEventJoypadMotion,"resource_local_to_scene":false,"resource_name":"","device":-1,"axis":0,"axis_value":1.0,"script":null)
|
||||
]
|
||||
}
|
||||
character_move_forward={
|
||||
"deadzone": 0.2,
|
||||
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":16,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":87,"key_label":0,"unicode":0,"location":0,"echo":false,"script":null)
|
||||
, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":16,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":4194320,"key_label":0,"unicode":0,"location":0,"echo":false,"script":null)
|
||||
, Object(InputEventJoypadMotion,"resource_local_to_scene":false,"resource_name":"","device":-1,"axis":1,"axis_value":-1.0,"script":null)
|
||||
]
|
||||
}
|
||||
character_move_back={
|
||||
"deadzone": 0.2,
|
||||
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":16,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":83,"key_label":0,"unicode":0,"location":0,"echo":false,"script":null)
|
||||
, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":16,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":4194322,"key_label":0,"unicode":0,"location":0,"echo":false,"script":null)
|
||||
, Object(InputEventJoypadMotion,"resource_local_to_scene":false,"resource_name":"","device":-1,"axis":1,"axis_value":1.0,"script":null)
|
||||
]
|
||||
}
|
||||
look_left={
|
||||
"deadzone": 0.2,
|
||||
"events": [Object(InputEventJoypadMotion,"resource_local_to_scene":false,"resource_name":"","device":-1,"axis":2,"axis_value":-1.0,"script":null)
|
||||
]
|
||||
}
|
||||
look_right={
|
||||
"deadzone": 0.2,
|
||||
"events": [Object(InputEventJoypadMotion,"resource_local_to_scene":false,"resource_name":"","device":-1,"axis":2,"axis_value":1.0,"script":null)
|
||||
]
|
||||
}
|
||||
look_up={
|
||||
"deadzone": 0.2,
|
||||
"events": [Object(InputEventJoypadMotion,"resource_local_to_scene":false,"resource_name":"","device":-1,"axis":3,"axis_value":-1.0,"script":null)
|
||||
]
|
||||
}
|
||||
look_down={
|
||||
"deadzone": 0.2,
|
||||
"events": [Object(InputEventJoypadMotion,"resource_local_to_scene":false,"resource_name":"","device":-1,"axis":3,"axis_value":1.0,"script":null)
|
||||
]
|
||||
}
|
||||
character_jump={
|
||||
"deadzone": 0.2,
|
||||
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":16,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":32,"key_label":0,"unicode":0,"location":0,"echo":false,"script":null)
|
||||
, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":16,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":4194309,"key_label":0,"unicode":0,"location":0,"echo":false,"script":null)
|
||||
, Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":-1,"button_index":0,"pressure":0.0,"pressed":false,"script":null)
|
||||
]
|
||||
}
|
||||
combat_aim={
|
||||
"deadzone": 0.2,
|
||||
"events": [Object(InputEventMouseButton,"resource_local_to_scene":false,"resource_name":"","device":32,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"button_mask":0,"position":Vector2(0, 0),"global_position":Vector2(0, 0),"factor":1.0,"button_index":2,"canceled":false,"pressed":false,"double_click":false,"script":null)
|
||||
, Object(InputEventJoypadMotion,"resource_local_to_scene":false,"resource_name":"","device":-1,"axis":4,"axis_value":1.0,"script":null)
|
||||
]
|
||||
}
|
||||
combat_fire={
|
||||
"deadzone": 0.2,
|
||||
"events": [Object(InputEventMouseButton,"resource_local_to_scene":false,"resource_name":"","device":32,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"button_mask":0,"position":Vector2(0, 0),"global_position":Vector2(0, 0),"factor":1.0,"button_index":1,"canceled":false,"pressed":false,"double_click":false,"script":null)
|
||||
, Object(InputEventJoypadMotion,"resource_local_to_scene":false,"resource_name":"","device":-1,"axis":5,"axis_value":1.0,"script":null)
|
||||
]
|
||||
}
|
||||
freelook={
|
||||
"deadzone": 0.2,
|
||||
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":16,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":4194328,"key_label":0,"unicode":0,"location":0,"echo":false,"script":null)
|
||||
, Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":-1,"button_index":8,"pressure":0.0,"pressed":false,"script":null)
|
||||
]
|
||||
}
|
||||
release_cursor={
|
||||
"deadzone": 0.2,
|
||||
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":16,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":96,"key_label":0,"unicode":0,"location":0,"echo":false,"script":null)
|
||||
]
|
||||
}
|
||||
ui_pause={
|
||||
"deadzone": 0.2,
|
||||
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":16,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":4194305,"key_label":0,"unicode":0,"location":0,"echo":false,"script":null)
|
||||
, Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":-1,"button_index":6,"pressure":0.0,"pressed":false,"script":null)
|
||||
]
|
||||
}
|
||||
vehicle_pitch_up={
|
||||
"deadzone": 0.2,
|
||||
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":16,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":87,"key_label":0,"unicode":0,"location":0,"echo":false,"script":null)
|
||||
, Object(InputEventJoypadMotion,"resource_local_to_scene":false,"resource_name":"","device":-1,"axis":1,"axis_value":-1.0,"script":null)
|
||||
]
|
||||
}
|
||||
vehicle_pitch_down={
|
||||
"deadzone": 0.2,
|
||||
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":16,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":83,"key_label":0,"unicode":0,"location":0,"echo":false,"script":null)
|
||||
, Object(InputEventJoypadMotion,"resource_local_to_scene":false,"resource_name":"","device":-1,"axis":1,"axis_value":1.0,"script":null)
|
||||
]
|
||||
}
|
||||
vehicle_yaw_left={
|
||||
"deadzone": 0.2,
|
||||
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":16,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":65,"key_label":0,"unicode":0,"location":0,"echo":false,"script":null)
|
||||
, Object(InputEventJoypadMotion,"resource_local_to_scene":false,"resource_name":"","device":-1,"axis":0,"axis_value":-1.0,"script":null)
|
||||
]
|
||||
}
|
||||
vehicle_yaw_right={
|
||||
"deadzone": 0.2,
|
||||
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":16,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":68,"key_label":0,"unicode":0,"location":0,"echo":false,"script":null)
|
||||
, Object(InputEventJoypadMotion,"resource_local_to_scene":false,"resource_name":"","device":-1,"axis":0,"axis_value":1.0,"script":null)
|
||||
]
|
||||
}
|
||||
vehicle_roll_left={
|
||||
"deadzone": 0.2,
|
||||
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":16,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":81,"key_label":0,"unicode":0,"location":0,"echo":false,"script":null)
|
||||
, Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":-1,"button_index":9,"pressure":0.0,"pressed":false,"script":null)
|
||||
]
|
||||
}
|
||||
vehicle_roll_right={
|
||||
"deadzone": 0.2,
|
||||
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":16,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":69,"key_label":0,"unicode":0,"location":0,"echo":false,"script":null)
|
||||
, Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":-1,"button_index":10,"pressure":0.0,"pressed":false,"script":null)
|
||||
]
|
||||
}
|
||||
vehicle_thrust={
|
||||
"deadzone": 0.2,
|
||||
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":16,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":32,"key_label":0,"unicode":0,"location":0,"echo":false,"script":null)
|
||||
, Object(InputEventJoypadMotion,"resource_local_to_scene":false,"resource_name":"","device":-1,"axis":5,"axis_value":1.0,"script":null)
|
||||
]
|
||||
}
|
||||
vehicle_freelook={
|
||||
"deadzone": 0.2,
|
||||
"events": [Object(InputEventMouseButton,"resource_local_to_scene":false,"resource_name":"","device":32,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"button_mask":0,"position":Vector2(0, 0),"global_position":Vector2(0, 0),"factor":1.0,"button_index":2,"canceled":false,"pressed":false,"double_click":false,"script":null)
|
||||
, Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":-1,"button_index":8,"pressure":0.0,"pressed":false,"script":null)
|
||||
]
|
||||
}
|
||||
vehicle_release_cursor={
|
||||
"deadzone": 0.2,
|
||||
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":16,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":4194328,"key_label":0,"unicode":0,"location":0,"echo":false,"script":null)
|
||||
]
|
||||
}
|
||||
vehicle_auxiliary={
|
||||
"deadzone": 0.2,
|
||||
"events": [Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":-1,"button_index":4,"pressure":0.0,"pressed":false,"script":null)
|
||||
]
|
||||
}
|
||||
vehicle_toggle_gear={
|
||||
"deadzone": 0.2,
|
||||
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":16,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":71,"key_label":0,"unicode":0,"location":0,"echo":false,"script":null)
|
||||
, Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":-1,"button_index":0,"pressure":0.0,"pressed":false,"script":null)
|
||||
]
|
||||
}
|
||||
vehicle_toggle_crew_hatch={
|
||||
"deadzone": 0.2,
|
||||
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":16,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":72,"key_label":0,"unicode":0,"location":0,"echo":false,"script":null)
|
||||
, Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":-1,"button_index":2,"pressure":0.0,"pressed":false,"script":null)
|
||||
]
|
||||
}
|
||||
vehicle_toggle_dock_hatch={
|
||||
"deadzone": 0.2,
|
||||
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":16,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":74,"key_label":0,"unicode":0,"location":0,"echo":false,"script":null)
|
||||
, Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":-1,"button_index":3,"pressure":0.0,"pressed":false,"script":null)
|
||||
]
|
||||
}
|
||||
capsule_toggle_ladder={
|
||||
"deadzone": 0.2,
|
||||
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":16,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":76,"key_label":0,"unicode":0,"location":0,"echo":false,"script":null)
|
||||
, Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":-1,"button_index":1,"pressure":0.0,"pressed":false,"script":null)
|
||||
]
|
||||
}
|
||||
vehicle_activate_instruments={
|
||||
"deadzone": 0.2,
|
||||
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":16,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":73,"key_label":0,"unicode":0,"location":0,"echo":false,"script":null)
|
||||
, Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":-1,"button_index":11,"pressure":0.0,"pressed":false,"script":null)
|
||||
]
|
||||
}
|
||||
vehicle_toggle_cabin_lights={
|
||||
"deadzone": 0.2,
|
||||
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":16,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":75,"key_label":0,"unicode":0,"location":0,"echo":false,"script":null)
|
||||
, Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":-1,"button_index":12,"pressure":0.0,"pressed":false,"script":null)
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user