Skip to content

Instantly share code, notes, and snippets.

@bruchmann
Created August 29, 2025 17:56
Show Gist options
  • Save bruchmann/f6fd48efa610c4b277a7406eb9ad1f0c to your computer and use it in GitHub Desktop.
Save bruchmann/f6fd48efa610c4b277a7406eb9ad1f0c to your computer and use it in GitHub Desktop.
GDScript comment banner
@tool
class_name ActorModel extends Node
################################################################################
# SIGNALS #
################################################################################
signal state_changed(new_state: ActorState)
################################################################################
# PUBLIC PROPERTIES #
################################################################################
@export var default_state: ActorState = null:
set = set_default_state
@onready var actor: Actor = owner as Actor
################################################################################
# PRIVATE PROPERTIES #
################################################################################
var _active_state: ActorState = null
var _states: Array[ActorState] = []
################################################################################
# VIRTUAL METHOD OVERRIDES #
################################################################################
func _ready() -> void:
for child_node: Node in get_children():
if child_node is ActorState:
_states.append(child_node as ActorState)
_set_active_state(default_state)
func _get_configuration_warnings() -> PackedStringArray:
var warnings: PackedStringArray = PackedStringArray()
if owner is not Actor:
warnings.append('"%s" must be owned by an Actor.' % name)
if get_child_count() == 0:
warnings.append("Model has no states.")
else:
for child_node: Node in get_children():
if child_node is not ActorState:
warnings.append('"%s" is not an ActorState.')
if default_state is not ActorState:
warnings.append("Assigning a default state is required.")
return warnings
################################################################################
# GETTERS & SETTERS #
################################################################################
func set_default_state(value: ActorState) -> void:
default_state = value
update_configuration_warnings()
################################################################################
# VIRTUAL METHOD DEFINITIONS #
################################################################################
func _update(actions: ActorActions, delta: float) -> void:
var most_relevant_state: ActorState = _find_most_relevant_state(actions, delta)
if most_relevant_state == null:
most_relevant_state = default_state
if _active_state != most_relevant_state:
_set_active_state(most_relevant_state)
_active_state._update(actions, delta)
################################################################################
# PRIVATE METHODS #
################################################################################
func _find_most_relevant_state(actions: ActorActions, delta: float) -> ActorState:
var most_relevant_state: ActorState = null
var highest_relevance: float = -INF
for candidate: ActorState in _states:
var relevance: float = clampf(
snappedf(candidate._compute_relevance(actions, delta), ActorState.RELEVANCE_STEP),
ActorState.RELEVANCE_MIN,
ActorState.RELEVANCE_MAX
)
var has_highest_relevance: bool = relevance > highest_relevance
var is_of_equal_relevance: bool = (
!has_highest_relevance and is_equal_approx(relevance, highest_relevance)
)
var has_higher_priority: bool = (
most_relevant_state != null and (candidate.priority > most_relevant_state.priority)
)
if has_highest_relevance or (is_of_equal_relevance and has_higher_priority):
most_relevant_state = candidate
highest_relevance = relevance
return most_relevant_state
func _set_active_state(new_state: ActorState, actions: ActorActions = ActorActions.empty()) -> void:
if _active_state:
_active_state._exit_state(actions)
new_state._enter_state(actions)
_active_state = new_state
state_changed.emit(_active_state)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment