#pragma once #pragma region CPL License /* Nuclex Unreal Module Copyright (C) 2014-2021 Nuclex Development Labs This library is free software; you can redistribute it and/or modify it under the terms of the IBM Common Public License as published by the IBM Corporation; either version 1.0 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the IBM Common Public License for more details. You should have received a copy of the IBM Common Public License along with this library */ #pragma endregion // CPL License #include #include #include #include "PawnMove.generated.h" // --------------------------------------------------------------------------------------------- // /// Move that a controller can execute on a pawn using the moves system /// @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 needs to be reusable. UCLASS(ClassGroup=(Custom), meta=(BlueprintSpawnableComponent), Blueprintable) class NUCLEX_API UPawnMove : public UObject { GENERATED_BODY() /// Initializes a new actor move public: UPawnMove(); /// Initializes the move when it is selected into a pawn for the first time /// @param newPawn Pawn into which the move has been selected public: void Initialize(APawn *newPawn); /// Retrieves the pawn that is currently managing the move (when assigne to a pawn) /// @returns The pawn in which this move is being used /// @remarks /// This will return a null pointer until the move has been selected into /// a pawn. Use it to access other pawn properties needed by the move public: UFUNCTION(BlueprintCallable, Category="Moves") APawn *GetPawn() const { return this->pawn; } /// Initializes the move when it is selected into a pawn for the first time /// @param pawn Pawn into which the move has been selected /// @remarks /// This is always the first method called when a move is assigned to a pawn. /// During OnInitialized(), the pawn reference will be valid, but there's no /// guarantee that the play mode has started yet. Use OnInitialized() as your /// move's constructor, but do not depend on other components (including /// the pawn) being initialized yet. public: UFUNCTION(BlueprintCallable, BlueprintNativeEvent, Category="Moves") void OnInitialized(); virtual void OnInitialized_Implementation() const {} /// Whether the move has completed executing /// @returns True if the move has completed its task /// @remarks /// This is checked by the @see UPawnController to see whether its currently /// active move has ended (allowing it to decide on a new move). Moves are not /// required to ever finish, but they have to be interruptible at any time. /// It is also okay to for the moves themselves to take care of their transition /// to other moves. /// /// If a move can finish, this property should return 'true' as soon as the move /// finishes and reset to 'false' when the move receives the @see OnEnded() /// notification or the @see OnStarted() notification. /// /// Moves that can finish are usually only used for AI characters where moves are /// scheduled by a 'strategy' (or other high-level control system) that uses them /// in a fashion similar to behavior tree nodes (eg. a 'MoveTowardsPlayer' strategy /// or behavior tree node might use multiple 'run' and 'jump' moves to achieve its goal. /// /// When a move completes, the @see UActorController::OnMoveCompleted /// method is invoked. By default, this just sets the active move to null, but /// custom pawn controllers can override this to notify their AI 'strategy' or /// fall back to some kind of default move, for example. public: UFUNCTION(BlueprintCallable, BlueprintNativeEvent, Category="Moves") bool IsCompleted() const; virtual bool IsCompleted_Implementation() const { return false; } /// Called when the pawn has started the move /// @remarks /// This notification indicates that the move has just become active. When active, /// the move's Tick() method will be executed. /// /// Use this method to do any needed preparations, such as resetting counters /// or updating the animation state. public: UFUNCTION(BlueprintCallable, BlueprintNativeEvent, Category="Moves") void OnStarted(); virtual void OnStarted_Implementation() {} /// Called when the actor is dropping the move (both when it's complete or interrupted) public: UFUNCTION(BlueprintCallable, BlueprintNativeEvent, Category="Moves") void OnEnded(); virtual void OnEnded_Implementation() {} /// Advances the game world simulation of the actor running the move /// @param deltaTime Time, in seconds, that has passed since the last tick public: UFUNCTION(BlueprintCallable, BlueprintNativeEvent, Category="Moves") void PhysicsTick(float deltaTime); virtual void PhysicsTick_Implementation(float deltaSeconds) {} /* /// Called once per frame to update the simulation /// @param deltaTime Time that has elapsed since the last tick in seconds /// @param tickType What the tick should update (visual tick / simulation tick) public: UFUNCTION(BlueprintCallable, BlueprintNativeEvent, Category="Moves") void TickMove(float deltaTime, ELevelTick tickType) const; */ // Currently, UnrealHeaderTool does not generate Execute_xyz() methods for base classes, // only for interfaces. Thus we need to replicate them ourselves. #if !defined(UNREAL_HEADER_TOOL_WORKS_CORRECTLY_AND_GENERATES_INTERFACE_METHODS) /// Executes the OnInitialized() event on an PawnMove /// @param self Actor move on which the event will be executed /// @remarks /// Use this instead of directly calling the _Implementation() variant to /// allow Blueprint-Overridden methods to be executed as well. public: static void Execute_OnInitialized(UObject *self); /// Executes the IsCompleted() event on an PawnMove /// @param self Actor move on which the event will be executed /// @returns Whether the IsCompleted() implemented reported move completion /// @remarks /// Use this instead of directly calling the _Implementation() variant to /// allow Blueprint-Overridden methods to be executed as well. public: static bool Execute_IsCompleted(UObject *self); /// Executes the OnStarted() event on an PawnMove /// @param self Actor move on which the event will be executed /// @remarks /// Use this instead of directly calling the _Implementation() variant to /// allow Blueprint-Overridden methods to be executed as well. public: static void Execute_OnStarted(UObject *self); /// Executes the OnEnded() event on an PawnMove /// @param self Actor move on which the event will be executed /// @remarks /// Use this instead of directly calling the _Implementation() variant to /// allow Blueprint-Overridden methods to be executed as well. public: static void Execute_OnEnded(UObject *self); /// Executes the PhysicsTick() event on an PawnMove /// @param self Actor move on which the event will be executed /// @param deltaTime Game time that has elapsed since the last tick /// @remarks /// Use this instead of directly calling the _Implementation() variant to /// allow Blueprint-Overridden methods to be executed as well. public: static void Execute_PhysicsTick(UObject *self, float deltaTime); #endif // !defined(UNREAL_HEADER_TOOL_WORKS_CORRECTLY_AND_GENERATES_INTERFACE_METHODS) /// Pawn on which this move is being run private: UPROPERTY(Transient) APawn *pawn; /// Whether the move has been initialized yet private: bool isInitialized; }; // --------------------------------------------------------------------------------------------- //