So ive made a weapon swapping system using a state machine, each weapon is a separate state, and when a slot number is selected, it changes the weapon state to the weapon thats on that slot, i have 2 issues, 1st issue is that when i have chainsaw out and i try to select a different weapon like for example the pistol, i cant, it will just not swap, until i press a different slot number and select a different weapon, and 2nd issue is that sometimes the chainsaw idle sound wont stop when swapping to a different weapon
Node structure:
State machine:
extends Node
@export var initial_state : State
var current_state = State
var states : Dictionary = {}
func _ready() -> void:
for child in get_children():
if child is State:
states[child.name.to_lower()] = child
child.Transitioned.connect(on_child_transition)
if initial_state:
initial_state.Enter()
current_state = initial_state
func _process(delta: float) -> void:
if current_state:
current_state.Update(delta)
func _physics_process(delta: float) -> void:
if current_state:
current_state.Physics_Update(delta)
func on_child_transition(state, new_state_name):
if state != current_state:
return
var new_state = states.get(new_state_name.to_lower())
if !new_state:
return
if current_state:
current_state.Exit()
new_state.Enter()
current_state = new_state
State:
extends Node
class_name State
signal Transitioned
func Enter():
pass
func Exit():
pass
func Update(delta: float) -> void:
pass
func Physics_Update(delta: float) -> void:
pass
WeaponState:
extends State
class_name Weapon_State
@export var Weapon_Base: Node3D
@onready var Rocket = preload("res://Assets/Scenes/Projectile/Rocket.tscn")
@onready var Projectile_Checker = get_owner().get_node("Hitscan/Projectile")
@onready var Ranged = get_owner().get_node("Hitscan/Ranged")
@onready var Melee = get_owner().get_node("Hitscan/Melee")
@onready var Weapon_Sprite = get_owner().get_node("CanvasLayer/Control/WeaponSprite")
var can_fire = true
var can_swap = true
var has_ammo = true
var fire_rate # you put in the amount of frames you want the fire rate to be
var fire_timer # = fire_rate
func check_hit_long_range():
if Ranged.is_colliding():
if Ranged.get_collider().is_in_group("Enemy"):
#Ranged.get_collider().take_damage(5)
return
func check_hit_melee():
if Melee.is_colliding():
if Melee.get_collider().is_in_group("Enemy"):
#Melee.get_collider().take_damage(5) # currently removed as im reworking the enemies
return
func launch_rocket():
var new_projectile = Rocket.instantiate()
# TODO: when i implement level system, figure out better way to do this
get_node("/root/World").add_child(new_projectile)
# checks if player is close to a wall and changes firing location accordingly
if Projectile_Checker.is_colliding():
new_projectile.global_transform = get_owner().get_node("ProjectileLocation/FiringPosition2").global_transform
else:
new_projectile.global_transform = get_owner().get_node("ProjectileLocation/FiringPosition1").global_transform
# --------------------
# WEAPON SWAPPING CODE
# --------------------
var Current_Weapon = "Pistol"
func Swap(Weap):
Current_Weapon = Weap
Transitioned.emit(self, Weap)
func weapon_swap():
# slot weapon swapping
if can_swap:
if Input.is_action_just_pressed("Slot1"):
if Current_Weapon != "Knife":
Swap("Knife")
else:
Swap("Chainsaw")
if Input.is_action_just_pressed("Slot2"):
get_owner().get_node("CanvasLayer/Control/AnimatedSprite2D").play("Lol")
if Current_Weapon != "Pistol":
Swap("Pistol")
if Input.is_action_just_pressed("Slot3"):
if Current_Weapon != "Machine_Gun":
Swap("Machine_Gun")
if Input.is_action_just_pressed("Slot4"):
if Current_Weapon != "Chain_Gun":
Swap("Chain_Gun")
if Input.is_action_just_pressed("Slot5"):
if Current_Weapon != "Rocket_Launcher":
Swap("Rocket_Launcher")
if Input.is_action_just_pressed("Slot6"):
if Current_Weapon != "Flamethrower":
Swap("Flamethrower")
Chainsaw code:
extends Weapon_State
class_name Chainsaw
# TODO: fix issue of not stopping sounds and not being able to swap
var idle_saw = 6
var idle_saw_timer = idle_saw
func Enter():
get_owner().get_node("Sounds/Weapon/Chainsaw/Rev").play()
# weapon_swap() this is removed because it prevented from selecting from the chainsaw to back to the knife
can_fire = true
fire_rate = 6
fire_timer = fire_rate
Weapon_Sprite.play("CS_Idle_1")
func Update(delta):
if Input.is_action_just_pressed("Slot2"):
get_owner().get_node("CanvasLayer/Control/AnimatedSprite2D").play("Lol")
weapon_swap()
# ---------------
# CHAINSAW IDLING
# ---------------
if can_fire:
weapon_swap()
if idle_saw_timer == 4:
Weapon_Sprite.play("CS_Idle_2")
if fire_timer == 3:
get_owner().get_node("Sounds/Weapon/Chainsaw/Saw").stop()
get_owner().get_node("Sounds/Weapon/Chainsaw/Idle").play()
return
if idle_saw_timer > 0:
idle_saw_timer -= 1
if idle_saw_timer == 0:
Weapon_Sprite.play("CS_Idle_1")
idle_saw_timer = idle_saw
get_owner().get_node("Sounds/Weapon/Chainsaw/Saw").stop()
get_owner().get_node("Sounds/Weapon/Chainsaw/Idle").play()
# ---------------
# CHAINSAW FIRING
# ---------------
if fire_timer == 4:
Weapon_Sprite.play("CS_Fire_2")
if fire_timer == 3:
check_hit_melee()
get_owner().get_node("Sounds/Weapon/Chainsaw/Saw").play()
if can_fire == false:
if fire_timer > 0:
fire_timer -= 1
if fire_timer == 0:
fire_timer = fire_rate
can_fire = true
if not Input.is_action_pressed("main_fire_weapon"):
Weapon_Sprite.play("CS_Idle_1")
if Input.is_action_pressed("main_fire_weapon") and can_fire:
Fire()
func Fire():
get_owner().get_node("Sounds/Weapon/Chainsaw/Saw").play()
get_owner().get_node("Sounds/Weapon/Chainsaw/Idle").stop()
Weapon_Sprite.play("CS_Fire_1")
can_fire = false
check_hit_melee()
func Exit():
get_owner().get_node("Sounds/Weapon/Chainsaw/Idle").stop()
get_owner().get_node("Sounds/Weapon/Chainsaw/Saw").stop()