class_name Move extends Object ## Task that can be performed by an actor ## @remarks ## Think of a move as when someone says "cool moves" - these are actions, ## feats or stunts an actor can perform. For player-controlled actors, possible moves ## might be standing around, running, jumping, punching, falling over and so on. ## For AI-controlled actors, moves are usually atomic actions such as ## "run to position x" or "jump onto the platform". ## ## Each move can decide which other moves it can transition to. For example, ## crawling while jumping doesn't make much sense, but jumping while running does. ## ## Usually, moves have a class derived from this one to add more properties ## specific to the actor implementation (eg. platformer moves would reference a ## platformer actor). Overriding moves to use custom implementations can be done ## through the specific move repository classes. ## ## Moves have to be cancellable at any time and also need to be reusable. # ----------------------------------------------------------------------------------------------- # ## Actor controller the move belongs to var actor_controller : ActorController ## Actor physics component the move can use to control the actor var actor_physics : ActorPhysics \ setget _set_actor_physics, _get_actor_physics ## Rigid body component the move can use to control the actor var rigid_body : RigidBody \ setget _set_rigid_body, _get_rigid_body # ----------------------------------------------------------------------------------------------- # ## Whether the lookup for the actor physics component has taken place already ## @remarks ## Used to avoid looking it up over and over in move-derived classes var _actor_physics_queried : bool ## Whether the lookup for the actor physics component has taken place already ## @remarks ## Used to avoid looking it up over and over in move-derived classes var _rigid_body_queried : bool # ----------------------------------------------------------------------------------------------- # ## Initialzes the move when it is accessed by an actor controller for the first time ## @param new_actor_controller ActorController that is making use of the move func _initialize(var new_actor_controller) -> void: if actor_controller == null: actor_controller = new_actor_controller if has_method("_initialize_derived"): _initialize_derived() if has_method("_ready"): _ready() elif new_actor_controller != actor_controller: printerr("ERROR: Move can only belong to one ActorController") # ----------------------------------------------------------------------------------------------- # ## Gives derived classes a chance to do initialization before _ready() is called func _initialize_derived() -> void: pass # Replace with function body. # ----------------------------------------------------------------------------------------------- # ## Called when the node enters the scene tree for the first time func _ready() -> void: pass # Replace with function body. # ----------------------------------------------------------------------------------------------- # ## Called every visual frame to update the observed state of the world ## @param delta_seconds Elapsed time since the previous frame func _process(delta_seconds : float) -> void: pass # ----------------------------------------------------------------------------------------------- # ## Called every physics frame to move objects and the state of the game ## @param delta_seconds Elapsed time since the previous frame func _physics_process(delta_seconds : float) -> void: pass # ----------------------------------------------------------------------------------------------- # ## Called when the actor controller has started performing the move ## @param delta_seconds Elapsed time since the previous frame func _move_started() -> void: pass # ----------------------------------------------------------------------------------------------- # ## Called when the actor controller has stopped performing the move ## @param delta_seconds Elapsed time since the previous frame func _move_stopped() -> void: pass # ----------------------------------------------------------------------------------------------- # ## Whether the move has completed executing ## @remarks ## If a move can finish, this state needs to be reset when calling ## at the earliest and at the latest. ## It is okay to have this property always return false if the moves themselves ## take care of transitions to other moves. ## ## The property is usually only used for AI characters ## where moves are scheduled by a 'strategy' that uses them in a fashion similar to ## behavior tree nodes (though behavior tree nodes would be at a higher level, eg. ## a 'MoveTowardsPlayer' behavior tree node / strategy would use multiple 'run' and ## 'jump' moves to achieve its goal. ## ## When a move completes, the ## method is invoked. By default, this just sets the active move to null, but ## custom actor controllers can override this to notify a behavior tree or ## fall back to some kind of default move, for example. func is_completed() -> bool: return false # ----------------------------------------------------------------------------------------------- # ## Retrieves the actor physics component when the property is read from ## @returns The actor physics component used by the actor, if any func _get_actor_physics() -> ActorPhysics: if not _actor_physics_queried: if actor_controller == null: printerr("ERROR: actor physics accessed before move was initialized") return null actor_physics = actor_controller.actor_physics _actor_physics_queried = true return actor_physics # ----------------------------------------------------------------------------------------------- # ## Complains if the user tries to directly assign the actor physics component ## @param new_actor_physics_component New component that will not be assigned func _set_actor_physics(new_actor_physics : ActorPhysics) -> void: if new_actor_physics != actor_physics: printerr("ERROR: The actor physics component cannot be assigned to") # ----------------------------------------------------------------------------------------------- # ## Retrieves the rigid body node when the property is read from ## @returns The rigid body node used by the actor, if any func _get_rigid_body() -> RigidBody: if not _rigid_body_queried: if actor_controller == null: printerr("ERROR: actor physics accessed before move was initialized") return null rigid_body = actor_controller.rigid_body _rigid_body_queried = true return rigid_body # ----------------------------------------------------------------------------------------------- # ## Complains if the user tries to directly assign the rigid body node ## @param new_rigid_body_node New node that will not be assigned func _set_rigid_body(new_rigid_body : RigidBody) -> void: if new_rigid_body != rigid_body: printerr("ERROR: The rigid body node cannot be assigned to")