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

@@ -1,54 +1,54 @@
extends Node
class_name BenchInteractionConnector
# Signals
signal SitOnBenchTriggered(position: Vector2, sitting_direction: Enums.Directions)
# Exports
@export var player: PlayerCharacter
# Private Variables
var _benches_in_range: Array[WoodenBench] = []
# Private Methods
func _ready() -> void:
player.interact_scanner.area_entered.connect(_on_interact_scanned)
player.interact_scanner.area_exited.connect(_on_interact_unscanned)
player.interact_scanner.InteractionActionTriggered.connect(_on_interact_triggered)
func _on_interact_scanned(area: Area2D) -> void:
var parent := area.get_parent()
if parent == null or parent is not WoodenBench or _benches_in_range.has(parent):
return
_benches_in_range.append(parent)
func _on_interact_unscanned(area: Area2D) -> void:
var parent: Node = area.get_parent()
if parent == null or parent is not WoodenBench or !_benches_in_range.has(parent):
return
_benches_in_range.erase(parent)
func _on_interact_triggered() -> void:
if _benches_in_range.is_empty():
return
var bench := _benches_in_range[0]
var sitting_spots_container := bench.get_node("Sitting Spots") as Node2D
var sitting_spot_markers := sitting_spots_container.get_children()
var closest_marker: Marker2D
var distance_to_player := 9999.0
for node in sitting_spot_markers:
var marker := node as Marker2D
var distance := marker.global_position.distance_to(player.global_position)
if distance < distance_to_player:
closest_marker = marker
distance_to_player = distance
if !closest_marker:
return
player.SitOnFurnitureTriggered.emit(closest_marker.global_position, Enums.Directions.DOWN)
#class_name BenchInteractionConnector
#
## Signals
#signal SitOnBenchTriggered(position: Vector2, sitting_direction: Enums.Directions)
#
## Exports
#@export var player: PlayerBody
#
## Private Variables
#var _benches_in_range: Array[WoodenBench] = []
#
## Private Methods
#func _ready() -> void:
#player.interact_scanner.area_entered.connect(_on_interact_scanned)
#player.interact_scanner.area_exited.connect(_on_interact_unscanned)
#player.interact_scanner.InteractionActionTriggered.connect(_on_interact_triggered)
#
#
#func _on_interact_scanned(area: Area2D) -> void:
#var parent := area.get_parent()
#if parent == null or parent is not WoodenBench or _benches_in_range.has(parent):
#return
#_benches_in_range.append(parent)
#
#
#func _on_interact_unscanned(area: Area2D) -> void:
#var parent: Node = area.get_parent()
#if parent == null or parent is not WoodenBench or !_benches_in_range.has(parent):
#return
#_benches_in_range.erase(parent)
#
#
#func _on_interact_triggered() -> void:
#if _benches_in_range.is_empty():
#return
#
#var bench := _benches_in_range[0]
#var sitting_spots_container := bench.get_node("Sitting Spots") as Node2D
#var sitting_spot_markers := sitting_spots_container.get_children()
#
#var closest_marker: Marker2D
#var distance_to_player := 9999.0
#for node in sitting_spot_markers:
#var marker := node as Marker2D
#var distance := marker.global_position.distance_to(player.global_position)
#if distance < distance_to_player:
#closest_marker = marker
#distance_to_player = distance
#
#if !closest_marker:
#return
#
#player.SitOnFurnitureTriggered.emit(closest_marker.global_position, Enums.Directions.DOWN)

View File

@@ -4,73 +4,65 @@ extends Node
signal OpeningOfOpenedChestAttempted
# Exports
@export var player: PlayerCharacter
@export var auto_connect_all_chests := true
# Private Variables
var _chests_in_range: Array[BaseChest] = []
# Private Methods
func _ready() -> void:
player.interact_scanner.area_entered.connect(_on_interact_scanned)
player.interact_scanner.area_exited.connect(_on_interact_unscanned)
player.interact_scanner.InteractionActionTriggered.connect(_on_interact_triggered)
var chests := GroupUtils.GetAllTreasureChests()
for chest in chests:
chest.OpeningAnimationStarted.connect(_on_chest_opening_animation_started)
func _on_chest_opening_animation_started() -> void:
var player := GroupUtils.GetPlayer()
var children := player.get_children()
player.QueueCutsceneState()
var camera_idx := children.find_custom(func(x): return x is Camera2D)
if camera_idx == -1: return
# Zoom In
var camera := children[camera_idx] as Camera2D
var current_zoom := camera.zoom
await get_tree().create_tween().tween_property(camera, "zoom", current_zoom + Vector2(2, 2), 0.5).finished
# Player the player's chest opening animation
player.state_machine.QueueStateChange(PlayerStateMachine.States.PLAY_ANIMATION, { "animation_name": "opening-chest-down" })
await player.state_machine.StateChanged
var play_animation_state := player.state_machine.current_state as PlayerPlayAnimationState
await play_animation_state.AnimationFinished
player.state_machine.QueueStateChange(PlayerStateMachine.States.IDLE)
# Zoom back out
await get_tree().create_tween().tween_property(camera, "zoom", current_zoom, 0.5).finished
func _on_interact_scanned(area: Area2D) -> void:
var chest = area.get_parent()
if chest == null or chest is not BaseChest:
return
if _chests_in_range.has(chest):
return
_chests_in_range.append(chest)
func _on_interact_unscanned(area: Area2D) -> void:
var chest = area.get_parent()
if chest == null or chest is not BaseChest:
return
if !_chests_in_range.has(chest):
return
_chests_in_range.erase(chest)
func _on_interact_triggered() -> void:
if _chests_in_range.is_empty():
return
var chest := _chests_in_range[0]
if !chest.is_open:
chest.Open()
else:
chest.OpenAlreadyOpened()
OpeningOfOpenedChestAttempted.emit()
## Private Methods
#func _ready() -> void:
#var chests := GroupUtils.GetAllTreasureChests()
#for chest in chests:
#chest.OpeningAnimationStarted.connect(_on_chest_opening_animation_started)
#
#
#func _on_chest_opening_animation_started() -> void:
#player.QueueCutsceneState()
#
#var camera_idx := children.find_custom(func(x): return x is Camera2D)
#if camera_idx == -1: return
#
## Zoom In
#var camera := children[camera_idx] as Camera2D
#var current_zoom := camera.zoom
#await get_tree().create_tween().tween_property(camera, "zoom", current_zoom + Vector2(2, 2), 0.5).finished
#
## Player the player's chest opening animation
#player.state_machine.QueueStateChange(PlayerStateMachine.States.PLAY_ANIMATION, { "animation_name": "opening-chest-down" })
#await player.state_machine.StateChanged
#var play_animation_state := player.state_machine.current_state as PlayerPlayAnimationState
#await play_animation_state.AnimationFinished
#player.state_machine.QueueStateChange(PlayerStateMachine.States.IDLE)
#
## Zoom back out
#await get_tree().create_tween().tween_property(camera, "zoom", current_zoom, 0.5).finished
#
#
#func _on_interact_scanned(area: Area2D) -> void:
#var chest = area.get_parent()
#if chest == null or chest is not BaseChest:
#return
#if _chests_in_range.has(chest):
#return
#_chests_in_range.append(chest)
#
#
#func _on_interact_unscanned(area: Area2D) -> void:
#var chest = area.get_parent()
#if chest == null or chest is not BaseChest:
#return
#if !_chests_in_range.has(chest):
#return
#_chests_in_range.erase(chest)
#
#
#func _on_interact_triggered() -> void:
#if _chests_in_range.is_empty():
#return
#
#var chest := _chests_in_range[0]
#if !chest.is_open:
#chest.Open()
#else:
#chest.OpenAlreadyOpened()
#OpeningOfOpenedChestAttempted.emit()

View File

@@ -1,7 +1,5 @@
extends Node
@export var player: PlayerCharacter
# Public Methods
func OnPlayerAreaEntered(area: Area2D) -> void:
pass

View File

@@ -1,35 +1,35 @@
extends Node
# Exports
@export var player: PlayerCharacter
# Private Variables
var _zones_in_range: Array[InteractiveLoadingZone] = []
# Private Methods
func _ready() -> void:
player.interact_scanner.area_entered.connect(_on_interact_scanned)
player.interact_scanner.area_exited.connect(_on_interact_unscanned)
player.interact_scanner.InteractionActionTriggered.connect(_on_interact_triggered)
func _on_interact_scanned(area: Area2D) -> void:
if area is not InteractiveLoadingZone or _zones_in_range.has(area):
return
_zones_in_range.append(area)
func _on_interact_unscanned(area: Area2D) -> void:
if area is not InteractiveLoadingZone or !_zones_in_range.has(area):
return
_zones_in_range.erase(area)
func _on_interact_triggered() -> void:
if _zones_in_range.is_empty():
return
var zone := _zones_in_range[0]
zone.Activate()
#
## Exports
#@export var player: PlayerBody
#
## Private Variables
#var _zones_in_range: Array[InteractiveLoadingZone] = []
#
## Private Methods
#func _ready() -> void:
#player.interact_scanner.area_entered.connect(_on_interact_scanned)
#player.interact_scanner.area_exited.connect(_on_interact_unscanned)
#player.interact_scanner.InteractionActionTriggered.connect(_on_interact_triggered)
#
#
#func _on_interact_scanned(area: Area2D) -> void:
#if area is not InteractiveLoadingZone or _zones_in_range.has(area):
#return
#
#_zones_in_range.append(area)
#
#
#func _on_interact_unscanned(area: Area2D) -> void:
#if area is not InteractiveLoadingZone or !_zones_in_range.has(area):
#return
#
#_zones_in_range.erase(area)
#
#
#func _on_interact_triggered() -> void:
#if _zones_in_range.is_empty():
#return
#
#var zone := _zones_in_range[0]
#zone.Activate()