Quaternius weapons, input fixes, sound & path fixes
- Added 6 Quaternius weapon models (Pistol, Revolver, Rifle, Shotgun, P90, SniperRifle) - Created weapon resource files with balanced stats - Wired Pistol + Rifle into player.tscn replacing Kenney blasters - Fixed WASD input (matched input map action names) - Fixed Escape key toggles mouse capture - Added Audio autoload singleton - Fixed broken sound asset paths across all scripts - Fixed all scene ext_resource text paths (nested under assets/kenney-fps/) - Fixed all .import source_file paths - Deleted stale .import files (will be regenerated by editor on open)
This commit is contained in:
@@ -21,6 +21,12 @@ var _slot_2_latch := false
|
||||
var _slot_3_latch := false
|
||||
var _slot_4_latch := false
|
||||
|
||||
# Direct keyboard state (bypasses Input.get_axis() for reliability)
|
||||
var _key_w := false
|
||||
var _key_s := false
|
||||
var _key_a := false
|
||||
var _key_d := false
|
||||
|
||||
# Input variables (frame-rate mouse accumulator)
|
||||
var mouse_rotation: Vector2 = Vector2.ZERO
|
||||
|
||||
@@ -43,6 +49,7 @@ func _notification(what):
|
||||
if what == NOTIFICATION_WM_WINDOW_FOCUS_IN:
|
||||
Input.set_mouse_mode(Input.MOUSE_MODE_CAPTURED)
|
||||
override_mouse = false
|
||||
print("[INPUT] Window focus gained — recaptured mouse")
|
||||
|
||||
func _input(event: InputEvent) -> void:
|
||||
if !is_multiplayer_authority(): return
|
||||
@@ -73,14 +80,36 @@ func _input(event: InputEvent) -> void:
|
||||
if event.is_action_pressed("weapon_slot_4"):
|
||||
_slot_4_latch = true
|
||||
|
||||
# Track WASD directly from key events (backup for Input.get_axis())
|
||||
if event is InputEventKey and event.keycode != 0:
|
||||
match event.keycode:
|
||||
KEY_W: _key_w = event.pressed
|
||||
KEY_S: _key_s = event.pressed
|
||||
KEY_A: _key_a = event.pressed
|
||||
KEY_D: _key_d = event.pressed
|
||||
# Also check physical keycode as fallback
|
||||
match event.physical_keycode:
|
||||
KEY_W: _key_w = event.pressed
|
||||
KEY_S: _key_s = event.pressed
|
||||
KEY_A: _key_a = event.pressed
|
||||
KEY_D: _key_d = event.pressed
|
||||
|
||||
func _gather():
|
||||
if !is_setup:
|
||||
print("[INPUT DEBUG] _gather first call - setting up")
|
||||
setup()
|
||||
|
||||
# Movement (continuous)
|
||||
|
||||
# Movement: try Input.get_axis() first, fall back to direct key tracking
|
||||
var mx = Input.get_axis("move_west", "move_east")
|
||||
var mz = Input.get_axis("move_north", "move_south")
|
||||
|
||||
# If Input.get_axis() returns 0 but keys are pressed via event tracking, use event tracking
|
||||
if mx == 0.0 and mz == 0.0:
|
||||
if _key_d: mx = 1.0
|
||||
elif _key_a: mx = -1.0
|
||||
if _key_s: mz = 1.0
|
||||
elif _key_w: mz = -1.0
|
||||
|
||||
var old_mv = movement
|
||||
movement = Vector3(mx, 0, mz)
|
||||
if movement != old_mv and (mx != 0 or mz != 0):
|
||||
@@ -131,3 +160,7 @@ func setup():
|
||||
big_gun.hide()
|
||||
hud.show()
|
||||
Input.set_mouse_mode(Input.MOUSE_MODE_CAPTURED)
|
||||
# Ensure window has keyboard focus for WASD
|
||||
get_window().call_deferred("grab_focus")
|
||||
DisplayServer.call_deferred("window_move_to_foreground")
|
||||
print("[INPUT] Setup complete — camera active, mouse captured, focus grabbed")
|
||||
|
||||
@@ -94,8 +94,9 @@ func _handle_new_peer(id: int):
|
||||
if bomb:
|
||||
bomb.sync_to_peer(id)
|
||||
if avatars.size() <= 2:
|
||||
# First opponent joined — restart round so both spawn alive
|
||||
round_manager.start_round()
|
||||
# Dedicated server handles match start via headless_server.gd
|
||||
if not _dedicated_server:
|
||||
round_manager.start_round()
|
||||
else:
|
||||
# 3+ players: sync state, spectate until next round
|
||||
round_manager.sync_to_peer(id)
|
||||
|
||||
@@ -133,7 +133,14 @@ func _process(_delta: float):
|
||||
if _is_local and input:
|
||||
var mx := Input.get_axis("move_west", "move_east")
|
||||
var mz := Input.get_axis("move_north", "move_south")
|
||||
get_window().title = "TS [mv=%.1f,%.1f] [sl=%s%s%s%s] [fire=%s]" % [mx, mz, input.slot_1, input.slot_2, input.slot_3, input.slot_4, input.fire_held]
|
||||
var dead := death_tick >= 0
|
||||
var frozen := round_manager != null and round_manager.freeze_end_tick >= 0 and NetworkTime.tick < round_manager.freeze_end_tick
|
||||
var hp_str := str(health)
|
||||
var rm_ok := round_manager != null
|
||||
# Weapon model load status from weapon_manager
|
||||
var knife_ok := weapon_manager != null and weapon_manager.has_knife_model()
|
||||
var gun_ok := weapon_manager != null and weapon_manager.has_gun_model()
|
||||
get_window().title = "TS [mv=%.1f,%.1f] hp=%s d=%s f=%s k=%s g=%s [fire=%s]" % [mx, mz, hp_str, dead, frozen, knife_ok, gun_ok, input.fire_held]
|
||||
|
||||
# Smooth position interpolation between ticks
|
||||
var f := NetworkTime.tick_factor
|
||||
|
||||
@@ -8,7 +8,7 @@ signal round_started(round_number: int)
|
||||
signal round_ended(winner: TeamManager.Team)
|
||||
signal player_killed(victim_id: int, killer_id: int, weapon_id: int, kill_tick: int)
|
||||
|
||||
@export var freeze_time: float = 5.0
|
||||
@export var freeze_time: float = 0.0
|
||||
@export var round_time: float = 115.0
|
||||
@export var round_end_time: float = 5.0
|
||||
@export var max_rounds: int = 24
|
||||
|
||||
@@ -26,6 +26,7 @@ var _pending_grenades: Array[Dictionary] = [] # Buffered throws, consumed in _a
|
||||
|
||||
# Weapon models (loaded at runtime)
|
||||
var _knife_model: Node3D
|
||||
var _pistol_model: Node3D
|
||||
var _gun_model: Node3D
|
||||
var _grenade_model: Node3D
|
||||
var _current_visible_slot: int = -1
|
||||
@@ -40,17 +41,61 @@ func _ready():
|
||||
_load_weapon_models()
|
||||
|
||||
func _load_weapon_models():
|
||||
# Knife model
|
||||
var knife_scene := load("res://examples/multiplayer-fps/models/knife.fbx") as PackedScene
|
||||
if knife_scene:
|
||||
_knife_model = knife_scene.instantiate()
|
||||
_knife_model.scale = Vector3(0.003, 0.003, 0.003)
|
||||
_knife_model.position = Vector3(0.15, -0.22, -0.35)
|
||||
_knife_model.rotation_degrees = Vector3(-90, 180, 0)
|
||||
add_child(_knife_model)
|
||||
# Weapon models from Quaternius FPS Pack — GLB format, reliable import
|
||||
|
||||
# Slot 0 (melee) + Slot 1 (pistol): Use Quaternius Pistol model
|
||||
var pistol_scene := load("res://assets/quaternius/models/Pistol.glb") as PackedScene
|
||||
if pistol_scene:
|
||||
# Slot 0: small pistol as melee visual
|
||||
var knife = pistol_scene.instantiate()
|
||||
knife.scale = Vector3(0.35, 0.35, 0.35)
|
||||
knife.position = Vector3(0.08, -0.18, -0.28)
|
||||
knife.rotation_degrees = Vector3(-90, 180, 0)
|
||||
add_child(knife)
|
||||
_knife_model = knife
|
||||
_knife_model.hide()
|
||||
|
||||
# Slot 1: same pistol model, slightly different position
|
||||
var pistol = pistol_scene.instantiate()
|
||||
pistol.scale = Vector3(0.35, 0.35, 0.35)
|
||||
pistol.position = Vector3(0.08, -0.18, -0.28)
|
||||
pistol.rotation_degrees = Vector3(-90, 180, 0)
|
||||
add_child(pistol)
|
||||
_pistol_model = pistol
|
||||
_pistol_model.hide()
|
||||
else:
|
||||
print("[WM] Pistol model not available — using placeholder")
|
||||
for slot in [0, 1]:
|
||||
var box := MeshInstance3D.new()
|
||||
box.mesh = BoxMesh.new()
|
||||
box.mesh.size = Vector3(0.3, 0.05, 0.02)
|
||||
box.position = Vector3(0.15, -0.22, -0.35)
|
||||
box.rotation_degrees = Vector3(-90, 0, 0)
|
||||
add_child(box)
|
||||
if slot == 0:
|
||||
_knife_model = box
|
||||
else:
|
||||
_pistol_model = box
|
||||
box.hide()
|
||||
|
||||
# Grenade model
|
||||
# Slot 2 (primary rifle): Use Quaternius Rifle model
|
||||
var rifle_scene := load("res://assets/quaternius/models/Rifle.glb") as PackedScene
|
||||
if not rifle_scene:
|
||||
rifle_scene = load("res://assets/quaternius/models/P90.glb") as PackedScene
|
||||
if rifle_scene:
|
||||
var rifle = rifle_scene.instantiate()
|
||||
rifle.scale = Vector3(0.35, 0.35, 0.35)
|
||||
rifle.position = Vector3(0.06, -0.16, -0.25)
|
||||
rifle.rotation_degrees = Vector3(-90, 180, 0)
|
||||
add_child(rifle)
|
||||
if _gun_model:
|
||||
_gun_model.hide()
|
||||
_gun_model = rifle
|
||||
_gun_model.hide()
|
||||
else:
|
||||
print("[WM] Rifle model not available — using placeholder TinyGun")
|
||||
|
||||
# Grenade model (keep existing)
|
||||
var grenade_scene := load("res://examples/multiplayer-fps/models/grenade.glb") as PackedScene
|
||||
if grenade_scene:
|
||||
_grenade_model = grenade_scene.instantiate()
|
||||
@@ -59,21 +104,7 @@ func _load_weapon_models():
|
||||
add_child(_grenade_model)
|
||||
_grenade_model.hide()
|
||||
|
||||
# Gun model — replace placeholder box with Kenney blaster
|
||||
var gun_scene := load("res://assets/kenney/models/blaster.glb") as PackedScene
|
||||
if gun_scene:
|
||||
var blaster = gun_scene.instantiate()
|
||||
blaster.scale = Vector3(0.003, 0.003, 0.003)
|
||||
blaster.position = Vector3(0.09, -0.18, -0.3)
|
||||
blaster.rotation_degrees = Vector3(-90, 180, 0)
|
||||
add_child(blaster)
|
||||
# Hide the old box mesh, use blaster instead
|
||||
if _gun_model:
|
||||
_gun_model.hide()
|
||||
_gun_model = blaster
|
||||
_gun_model.hide()
|
||||
|
||||
# Knife sound
|
||||
# Knife slash sound
|
||||
var slash_stream := load("res://examples/multiplayer-fps/sounds/knife/knife_slash1.wav")
|
||||
if slash_stream:
|
||||
_knife_sound = AudioStreamPlayer3D.new()
|
||||
@@ -87,14 +118,18 @@ func _process(_delta: float):
|
||||
_current_visible_slot = active_slot
|
||||
if _knife_model:
|
||||
_knife_model.visible = (active_slot == 0)
|
||||
if _pistol_model:
|
||||
_pistol_model.visible = (active_slot == 1)
|
||||
if _gun_model:
|
||||
_gun_model.visible = (active_slot == 1 or active_slot == 2)
|
||||
_gun_model.visible = (active_slot == 2)
|
||||
if _grenade_model:
|
||||
_grenade_model.visible = (active_slot == 3)
|
||||
|
||||
func hide_weapons():
|
||||
if _knife_model:
|
||||
_knife_model.hide()
|
||||
if _pistol_model:
|
||||
_pistol_model.hide()
|
||||
if _gun_model:
|
||||
_gun_model.hide()
|
||||
if _grenade_model:
|
||||
@@ -104,6 +139,12 @@ func hide_weapons():
|
||||
func show_weapons():
|
||||
_current_visible_slot = -1 # Force refresh on next _process
|
||||
|
||||
# Debug helpers for window title
|
||||
func has_knife_model() -> bool:
|
||||
return _knife_model != null
|
||||
func has_gun_model() -> bool:
|
||||
return _gun_model != null
|
||||
|
||||
func get_active_weapon() -> WeaponData:
|
||||
var wid := inventory[active_slot]
|
||||
if wid == 0:
|
||||
|
||||
Reference in New Issue
Block a user