I’m having an issue with my State Machine for my battle system… It is constantly swapping between the state_upkeep and the state_selecting. The StateMachine is a node with children nodes underneath it for each state. Also when I do press a move it doesn’t move into state_executing it just keeps going back and forth between state_upkeep and state_selecting.
Here is my StateMachine code:
class_name StateMachine extends Node
var current_state: MachineState
var states: Dictionary = {}
@export var initial_state: MachineState
func _ready():
# Get all child states
for child in get_children():
if child is MachineState:
states[child.name.to_lower()] = child
child.state_machine = self
# Set initial state to first one
current_state = states[initial_state.name.to_lower()]
current_state.enter()
func _process(delta: float):
if current_state:
current_state.update(delta)
func _physics_process(delta: float):
if current_state:
current_state.physics_update(delta)
func _input(event: InputEvent):
if current_state:
current_state.handle_input(event)
func change_state(state_name: String):
if state_name.to_lower() in states:
if current_state:
current_state.exit()
current_state = states[state_name.to_lower()]
current_state.enter()
else:
print("State not found: ", state_name)
This is my state_upkeep code:
extends MachineState
@export var element_box: HBoxContainer
#Temporary storage for elemental points gained this upkeep
var wood_gained: int
var fire_gained: int
var earth_gained: int
var metal_gained: int
var water_gained: int
func enter() -> void:
print("Upkeep started")
#Reset to 0
wood_gained = 0
fire_gained = 0
earth_gained = 0
metal_gained = 0
water_gained = 0
#Generate some elemental points
generate_elemental_points()
# Update UI
if element_box:
element_box.update_points()
#Change state to selecting state
state_machine.change_state("state_selecting")
func generate_elemental_points() -> void:
#Make sure everything gets at least one
wood_gained += 1
fire_gained += 1
earth_gained += 1
metal_gained += 1
water_gained += 1
#Make some get extra at random
var rng = RandomNumberGenerator.new()
rng.randomize()
var num_extra_boosts = rng.randi_range(1,3)
for i in range(num_extra_boosts):
var random_element_index = rng.randi_range(0,4)
match random_element_index:
0: wood_gained += rng.randi_range(1,2)
1: fire_gained += rng.randi_range(1,2)
2: earth_gained += rng.randi_range(1,2)
3: metal_gained += rng.randi_range(1,2)
4: water_gained += rng.randi_range(1,2)
#Add points to the player data
PlayerManager.current_player_data.wood_points += wood_gained
PlayerManager.current_player_data.fire_points += fire_gained
PlayerManager.current_player_data.earth_points += earth_gained
PlayerManager.current_player_data.metal_points += metal_gained
PlayerManager.current_player_data.water_points += water_gained
This is my state_selecting code:
extends MachineState
@export var battle_ref: Battle
func enter() -> void:
print("picking moves")
battle_ref.enable_menu()
This is my main battle code:
class_name Battle extends CanvasLayer
#Access to State Machine
@onready var state_machine: StateMachine = $StateMachine
#Background
@onready var background: TextureRect = $SubViewportContainer/SubViewport/Background
#Elements
@onready var elements_box: HBoxContainer = $SubViewportContainer/SubViewport/MC/PlayerMainMenu/HBox/NPR/MC/HBox/ElementsBox
#Menus
@onready var player_main_menu: Control = $SubViewportContainer/SubViewport/MC/PlayerMainMenu
@onready var player_move_menu: Control = $SubViewportContainer/SubViewport/MC/PlayerMoveMenu
#Info
@onready var info: Control = $SubViewportContainer/SubViewport/MC/Info
#Track choices
var choices: Array = []
#Myxlings
static var player_myxlings: Array[MyxlingBase]
static var opponent_myxlings: Array[MyxlingBase]
#Self reference
static var active_battle_reference: Battle
@onready var state_selecting: Node = $StateMachine/state_selecting
@export var fight_button: Button
@export var item_button: Button
@export var defend_button: Button
@export var run_button: Button
func _ready() -> void:
active_battle_reference = self
#Make sure move menu is hidden
player_move_menu.hide()
info.update()
#Disable the menu buttons
disable_menu()
#Connect to the buttons
fight_button.pressed.connect(on_fight_pressed)
item_button.pressed.connect(on_item_pressed)
run_button.pressed.connect(on_run_pressed)
func enable_menu() -> void:
fight_button.disabled = false
item_button.disabled = false
defend_button.disabled = false
run_button.disabled = false
func disable_menu() -> void:
fight_button.disabled = true
item_button.disabled = true
defend_button.disabled = true
run_button.disabled = true
func on_move_selected(move) -> void:
print(move)
state_machine.change_state("state_executing")
func on_fight_pressed():
print("fight")
player_move_menu.show()
func on_item_pressed() -> void:
print("items")
func on_run_pressed() -> void:
print("run")