- Introduced a health bar for flowers, which updates based on the current GameState values. - Enhanced snail behavior with eating and sleeping states. Snails now have a chance to switch to the sleeping state while eating. - Improved mouse interaction with snails, allowing them to potentially switch to sleep mode when clicked. - Refactored cursor management into its own class for better code organization and readability. - Updated drone placement logic to use the new CursorManager class. - Added functionality for bees to replenish flower nectar levels after a certain number of deposits.
76 lines
2.3 KiB
GDScript
76 lines
2.3 KiB
GDScript
@icon("res://resources/icons/fsm.png")
|
|
extends Node
|
|
class_name FiniteStateMachine
|
|
|
|
var states : Dictionary = {}
|
|
var current_state : State
|
|
@export var initial_state : State
|
|
|
|
#NOTE This is a generic finite_state_machine, it handles all states, changes to this code will affect
|
|
# everything that uses a state machine!
|
|
|
|
func _ready() -> void:
|
|
for child : Node in get_children():
|
|
if child is State:
|
|
states[child.name.to_lower()] = child
|
|
child.state_transition.connect(change_state)
|
|
|
|
if initial_state:
|
|
initial_state.enter()
|
|
current_state = initial_state
|
|
|
|
# Call the current states update function
|
|
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 get_current_state_name() -> String:
|
|
if current_state:
|
|
return current_state.name.to_lower()
|
|
else:
|
|
return ""
|
|
|
|
# Use force_change_state cautiously, it immediately switches to a state regardless of any transitions.
|
|
# This is used to force us into a 'death state' when killed
|
|
func force_change_state(new_state : String) -> void:
|
|
var newState : State = states.get(new_state.to_lower())
|
|
|
|
if !newState:
|
|
print(new_state + " does not exist in the dictionary of states")
|
|
return
|
|
|
|
if current_state == newState:
|
|
print("State is same, aborting")
|
|
return
|
|
|
|
# NOTE Calling exit like so: (current_state.Exit()) may cause warnings when flushing queries, like when the enemy is being removed after death.
|
|
# call_deferred is safe and prevents this from occuring. We get the Exit function from the state as a callable and then call it in a thread-safe manner
|
|
if current_state:
|
|
var exit_callable : Callable = Callable(current_state, "exit")
|
|
exit_callable.call_deferred()
|
|
|
|
newState.enter()
|
|
|
|
current_state = newState
|
|
|
|
func change_state(source_state : State, new_state_name : String) -> void:
|
|
if source_state != current_state:
|
|
#print("Invalid change_state trying from: " + source_state.name + " but currently in: " + current_state.name)
|
|
#This typically only happens when trying to switch from death state following a force_change
|
|
return
|
|
|
|
var new_state : State = states.get(new_state_name.to_lower())
|
|
if !new_state:
|
|
print("New state is empty")
|
|
return
|
|
|
|
if current_state:
|
|
current_state.exit()
|
|
|
|
new_state.enter()
|
|
|
|
current_state = new_state
|