208 lines
5.7 KiB
GDScript
208 lines
5.7 KiB
GDScript
extends Node
|
|
|
|
class_name WeaponSystem
|
|
|
|
@export var animation_player: AnimationPlayer
|
|
@export var camera: PlayerCamera
|
|
@export var player: Player
|
|
@export var player_input: PlayerInput
|
|
|
|
var current_state: WeaponSubStateMachine
|
|
var last_slot: StringName
|
|
var disabled: bool
|
|
|
|
var slots: Dictionary[StringName,WeaponSubStateMachine] = {
|
|
"primary": null,
|
|
"secondary": null,
|
|
"knife": null,
|
|
"bomb": null,
|
|
"ability_first": null,
|
|
"ability_second": null,
|
|
"ability_third": null,
|
|
"ultimate": null
|
|
}
|
|
|
|
signal switched_to(state: WeaponSubStateMachine)
|
|
signal slots_updated(current_slot: StringName,slots: Dictionary[StringName,StringName])
|
|
signal ammo_updated(ammo: int, remaining_ammo: int)
|
|
|
|
func _ready() -> void:
|
|
player_input.drop.connect(drop_current)
|
|
player_input.fire_begin.connect(use_begin)
|
|
player_input.fire_end.connect(use_end)
|
|
player_input.switch_weapon.connect(switch)
|
|
player_input.alternate_state.connect(alternate_state)
|
|
player_input.switch_firemode.connect(switch_mode)
|
|
|
|
await get_tree().process_frame
|
|
await get_tree().process_frame
|
|
|
|
notify_slots_updated()
|
|
on_ammo_updated()
|
|
|
|
func get_speed_modifier() -> float:
|
|
if current_state == null:
|
|
return 1
|
|
return current_state.speed_modifier
|
|
|
|
func can_add(slot: StringName) -> bool:
|
|
return slots.has(slot) and slots[slot] == null
|
|
|
|
func add(state: WeaponSubStateMachine, slot: StringName) -> void:
|
|
if not multiplayer.is_server():
|
|
return
|
|
if can_add(slot) == false:
|
|
return
|
|
|
|
add_child(state, true)
|
|
|
|
slots[slot] = state
|
|
|
|
notify_slots_updated()
|
|
|
|
if current_state == null:
|
|
current_state = state
|
|
ammo_updated.emit(current_state.ammo,current_state.remaining_ammo)
|
|
#Replace with way to ensure all players loaded
|
|
await get_tree().process_frame
|
|
await get_tree().process_frame
|
|
state._enter()
|
|
|
|
func get_empty_ability_slot() -> StringName:
|
|
if slots["ability_first"] == null:
|
|
return "ability_first"
|
|
elif slots["ability_second"] == null:
|
|
return "ability_second"
|
|
elif slots["ability_third"] == null:
|
|
return "ability_third"
|
|
return "ability_first"
|
|
|
|
func switch(to: StringName, exit: bool = true):
|
|
if slots.has(to) == false or slots[to] == null or slots[to] == current_state or (multiplayer.get_remote_sender_id() != 1 and is_multiplayer_authority() == false):
|
|
return
|
|
if current_state != null and exit:
|
|
current_state._exit()
|
|
if current_state.can_be_previous:
|
|
last_slot = slots.find_key(current_state)
|
|
else:
|
|
last_slot = ""
|
|
current_state = slots[to]
|
|
current_state._enter()
|
|
|
|
ammo_updated.emit(current_state.ammo,current_state.remaining_ammo)
|
|
switched_to.emit(current_state)
|
|
notify_slots_updated()
|
|
|
|
func return_to_previous(exit: bool = true):
|
|
if last_slot != "":
|
|
switch(last_slot, exit)
|
|
else:
|
|
switch("knife", exit)
|
|
|
|
func drop_current():
|
|
drop(current_state)
|
|
|
|
func drop(weapon: WeaponSubStateMachine) -> void:
|
|
if not is_multiplayer_authority():
|
|
return
|
|
if slots.find_key(weapon) in ["knife","ability_first","ability_second","ability_third"]:
|
|
return
|
|
|
|
var dropped_weapon: DroppableWeapon = Registry.weapons[weapon.registry_entry].dropped_scene.instantiate()
|
|
dropped_weapon.weapon.ammo = weapon.ammo
|
|
dropped_weapon.weapon.remaining_ammo = weapon.remaining_ammo
|
|
dropped_weapon.weapon.slot = weapon.slot
|
|
Session.dynamic_objects_parent.add_child(dropped_weapon)
|
|
dropped_weapon.global_position = camera.global_position
|
|
dropped_weapon.apply_central_impulse(-camera.global_basis.z * 10 + player.velocity)
|
|
|
|
$"../PickupRange".start_temp_ignore()
|
|
|
|
slots[slots.find_key(weapon)] = null
|
|
notify_slots_updated()
|
|
weapon.queue_free()
|
|
return_to_previous(false)
|
|
|
|
func drop_slot(slot: StringName):
|
|
if slots.has(slot) == false or slots[slot] == null:
|
|
return
|
|
drop(slots[slot])
|
|
|
|
func check_for_empty() -> void:
|
|
if is_multiplayer_authority() == false:
|
|
return
|
|
for child in get_children():
|
|
if child is WeaponSubStateMachine and child.ammo == 0 and child.remaining_ammo == 0 and child.destroy_when_empty:
|
|
if child == current_state:
|
|
return_to_previous(false)
|
|
child.queue_free()
|
|
|
|
|
|
func on_ammo_updated() -> void:
|
|
if is_multiplayer_authority() == false:
|
|
return
|
|
if current_state != null:
|
|
ammo_updated.emit(current_state.ammo,current_state.remaining_ammo)
|
|
remote_ammo_update.rpc(current_state.ammo,current_state.remaining_ammo)
|
|
|
|
@rpc
|
|
func remote_ammo_update(ammo: int, remaining_ammo: int):
|
|
ammo_updated.emit(ammo,remaining_ammo)
|
|
|
|
func notify_slots_updated():
|
|
if not is_multiplayer_authority():
|
|
return
|
|
var display_slots: Dictionary[StringName,StringName] = {}
|
|
for key in slots.keys():
|
|
if slots[key] == null:
|
|
display_slots[key] = ""
|
|
else:
|
|
display_slots[key] = slots[key].registry_entry
|
|
var current_slot: StringName = ""
|
|
var found = slots.find_key(current_state)
|
|
if found:
|
|
current_slot = found
|
|
|
|
remote_update_slots.rpc(current_slot,display_slots)
|
|
slots_updated.emit(current_slot,display_slots)
|
|
|
|
@rpc
|
|
func remote_update_slots(current_slot: StringName, update_slots: Dictionary[StringName,StringName]):
|
|
slots_updated.emit(current_slot, update_slots)
|
|
|
|
func disable() -> void:
|
|
disabled = true
|
|
|
|
func _process(delta: float) -> void:
|
|
if current_state == null or disabled:
|
|
return
|
|
current_state.update(delta)
|
|
|
|
func _physics_process(delta: float) -> void:
|
|
if current_state == null or disabled:
|
|
return
|
|
current_state.physics_update(delta)
|
|
|
|
func use_begin() -> void:
|
|
if Session.round_state == Session.ROUND_STATES.BUY:
|
|
return
|
|
if current_state != null:
|
|
current_state.use_begin()
|
|
|
|
func use_end() -> void:
|
|
if Session.round_state == Session.ROUND_STATES.BUY:
|
|
return
|
|
if current_state != null:
|
|
current_state.use_end()
|
|
|
|
func alternate_state() -> void:
|
|
if Session.round_state == Session.ROUND_STATES.BUY:
|
|
return
|
|
if current_state != null:
|
|
current_state.alternate_state()
|
|
|
|
func switch_mode() -> void:
|
|
if Session.round_state == Session.ROUND_STATES.BUY:
|
|
return
|
|
if current_state != null:
|
|
current_state.switch_mode()
|