Rework player state system to use an event subscription system to avoid directly calling methods on individual state and having to worry about validity

This commit is contained in:
2026-04-01 11:11:02 -05:00
parent 7cd34cb07e
commit eabfeab91a
35 changed files with 882 additions and 2288 deletions

View File

@@ -3,8 +3,11 @@ extends Node
@export var state_machine: PlayerStateMachine
var _subscribed_events: Array[String] = []
var _subscribed_events_callables: Array[Callable] = []
func GetStateEnum() -> PlayerStateMachine.States:
push_error("Unimplemented Method: BaseState.GetName")
push_error("Unimplemented Method: BaseState.GetStateEnum")
return PlayerStateMachine.States.IDLE
@@ -31,3 +34,23 @@ func IsActive() -> bool:
func IsStateActionable() -> bool:
return true
func SubscribeToEvent(event_name: String, callback: Callable) -> void:
if _subscribed_events.has(event_name):
return
_subscribed_events.append(event_name)
_subscribed_events_callables.append(callback)
# State Machine Visibility Only
func _StateMachine_OnEventSent(event_name: String, parameters: Variant) -> void:
var idx := _subscribed_events.find(event_name)
if idx == -1:
push_error("THIS SHOULD NEVER HAPPEN LOL")
var callable := _subscribed_events_callables[idx]
if callable.get_argument_count() == 0:
callable.call()
else:
callable.call(parameters)

View File

@@ -1,52 +1,14 @@
extends BaseState
class_name PlayerIdleState
signal PlayerBecameIdle
# idle_state.gd
@export var player: PlayerCharacter
func _ready() -> void:
SubscribeToEvent("MovementQueued", OnMovementQueued)
var _movement_component: MovementComponent
var _sit_queued := false
var _sit_queue_pos: Vector2
var _sit_queue_dir: Enums.Directions
func OnMovementQueued(dv: Vector2) -> void:
state_machine.QueueStateChange(PlayerStateMachine.States.WALKING, {"dv": dv})
func GetStateEnum() -> PlayerStateMachine.States:
return PlayerStateMachine.States.IDLE
func Enter(_extra_parameters: Dictionary) -> void:
_movement_component = ComponentUtils.GetMovementComponent(player)
if not _movement_component:
print_rich("[color=yellow]Warning: Player does not have a movement component...[/color]")
PlayerBecameIdle.emit()
func Update(_delta: float) -> void:
var item_a := Input.is_action_just_pressed("use_item_a")
if item_a:
state_machine.QueueStateChange(PlayerStateMachine.States.USING_ITEM_A, {})
return
if _sit_queued:
state_machine.QueueStateChange(PlayerStateMachine.States.SITTING, {"pos": _sit_queue_pos, "dir": _sit_queue_dir})
_sit_queued = false
return
if _movement_component and _movement_component.movement_vector != Vector2.ZERO:
state_machine.QueueStateChange(PlayerStateMachine.States.WALKING)
func OnSitOnFurnitureTriggered(sitting_position: Vector2, sitting_direction: Enums.Directions) -> void:
if state_machine.GetCurrentStateEnum() != GetStateEnum():
return
_sit_queued = true
_sit_queue_pos = sitting_position
_sit_queue_dir = sitting_direction
func OnCutsceneStarted() -> void:
state_machine.QueueStateChange(PlayerStateMachine.States.CUTSCENE)

View File

@@ -1,30 +1,41 @@
extends BaseState
# walking_state.gd
signal StartedWalking
@export var walking_speed := 100
@export var direction_component: FacingDirectionComponent
@export var body: CharacterBody2D
var _movement_component: MovementComponent
var _queued_dv: Vector2
func GetStateEnum() -> PlayerStateMachine.States:
return PlayerStateMachine.States.WALKING
func _ready() -> void:
SubscribeToEvent("MovementQueued", OnMovementQueued)
SubscribeToEvent("NoMovementQueued", OnNoMovementQueued)
func Enter(_extra_parameters: Dictionary) -> void:
_movement_component = ComponentUtils.GetMovementComponent(body)
print("Walking State Entered")
_queued_dv = _extra_parameters["dv"]
StartedWalking.emit()
func Update(_delta: float) -> void:
var movement_vector := _movement_component.movement_vector
if movement_vector == Vector2.ZERO:
if _queued_dv == Vector2.ZERO:
state_machine.QueueStateChange(PlayerStateMachine.States.IDLE)
return
body.velocity = movement_vector * walking_speed
body.velocity = _queued_dv * walking_speed
body.move_and_slide()
direction_component.ChangeDirectionUsingMovementVector(movement_vector)
func OnMovementQueued(dv: Vector2) -> void:
_queued_dv = dv
func OnNoMovementQueued() -> void:
_queued_dv = Vector2.ZERO
func GetStateEnum() -> PlayerStateMachine.States:
return PlayerStateMachine.States.WALKING