/* * All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or * its licensors. * * For complete copyright and license terms please see the LICENSE at the root of this * distribution (the "License"). All use of this software is governed by the License, * or, if provided, by the license below or the license accompanying this file. Do not * remove or modify any license notices. This file is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * */ // Original file Copyright Crytek GMBH or its affiliates, used under license. #ifndef CRYINCLUDE_CRYACTION_AIHANDLER_H #define CRYINCLUDE_CRYACTION_AIHANDLER_H #pragma once #include "AIFaceManager.h" #include "ICryMannequin.h" #include "Mannequin/AnimActionTriState.h" #include "IMovementController.h" // for the exactpositioning types struct IScriptSystem; struct IScriptTable; struct ISystem; struct IAISignalExtraData; class CAIProxy; class CMovementRequest; // //------------------------------------------------------------------------------ class CAnimActionAIAction : public CAnimActionTriState { public: typedef CAnimActionTriState TBase; enum EAIActionType { EAT_Looping, EAT_OneShot, }; // TODO: Move mannequin priorities into CryAction or get this from a central location enum { NORMAL_ACTION_PRIORITY = 3, // currently equal to PP_Action, just above movement, but underneath urgent actions, hit death, etc. URGENT_ACTION_PRIORITY = 4 // currently equal to PP_Urgent_Action, just above normal actions, but underneath hit death, etc. }; DEFINE_ACTION("AIAction"); CAnimActionAIAction(bool isUrgent, FragmentID fragmentID, IAnimatedCharacter& animChar, EAIActionType type, const string& value, IAnimActionTriStateListener& listener, bool skipIntro = false) : TBase((isUrgent ? URGENT_ACTION_PRIORITY : NORMAL_ACTION_PRIORITY), fragmentID, animChar, (type == EAT_OneShot), -1, skipIntro, &listener) , m_type(type) , m_value(value) , m_isUrgent(isUrgent) { InitMovementControlMethods(eMCM_AnimationHCollision, eMCM_Entity); } // overrides ---------------------------------------------------------------- EPriorityComparison ComparePriority(const IAction& actionCurrent) const override { if (m_isUrgent) { return (IAction::Installed == actionCurrent.GetStatus() && IAction::Installing & ~actionCurrent.GetFlags()) ? Higher : TBase::ComparePriority(actionCurrent); } else { return TBase::ComparePriority(actionCurrent); } } // ~overrides --------------------------------------------------------------- EAIActionType GetType() const { return m_type; } const string& GetValue() const { return m_value; } private: EAIActionType m_type; string m_value; bool m_isUrgent; }; // ---------------------------------------------------------------------------- class CAIHandler : public IAnimationGraphStateListener , IExactPositioningListener , IAnimActionTriStateListener { friend class CAIProxy; // implementation of IAnimationGraphStateListener virtual void SetOutput(const char* output, const char* value) {} virtual void QueryComplete(TAnimationGraphQueryID queryID, bool succeeded); virtual void DestroyedState(IAnimationGraphState*); //------------------ IExactPositioningListener virtual void ExactPositioningQueryComplete(TExactPositioningQueryID queryID, bool succeeded); virtual void ExactPositioningNotifyFinishPoint(const Vec3& pt); //------------------ ~IExactPositioningListener //------------------ IAnimActionTriStateListener virtual void OnAnimActionTriStateEnter(CAnimActionTriState* pActionTriState); virtual void OnAnimActionTriStateMiddle(CAnimActionTriState* pActionTriState); virtual void OnAnimActionTriStateExit(CAnimActionTriState* pActionTriState); //------------------ ~IAnimActionTriStateListener public: CAIHandler(IGameObject* pGameObject); ~CAIHandler(void); void Init(); void Reset(EObjectResetType type); void OnReused(IGameObject* pGameObject); void HandleCoverRequest(SOBJECTSTATE& state, CMovementRequest& mr); void HandleMannequinRequest(SOBJECTSTATE& state, CMovementRequest& mr); void HandleExactPositioning(SOBJECTSTATE& state, CMovementRequest& mr); void Update(); void AIMind(SOBJECTSTATE& state); void AISignal(int signalID, const char* signalText, uint32 crc, IEntity* pSender, const IAISignalExtraData* pData); void Release(); /// Plays a readability set (Group + Response) /// Note: A response delay of 0 means a random delay is chosen bool HasReadibilitySoundFinished() const { return m_bSoundFinished; } bool SetAGInput(EAIAGInput input, const char* value, const bool isUrgent = false); bool SetMannequinAGInput(IActionController* pActionController, EAIAGInput input, const char* value, const bool isUrgent = false); void FinishRunningAGActions(); /// Returns an estimate of how long the triggered animation would play when triggered now. /// (with the current stance, vehicle state, ...) CTimeValue GetEstimatedAGAnimationLength(EAIAGInput input, const char* value); bool ResetAGInput(EAIAGInput input); bool ResetMannequinAGInput(EAIAGInput input); IAnimationGraphState* GetAGState(); bool IsSignalAnimationPlayed(const char* value); bool IsActionAnimationStarted(const char* value); bool IsAnimationBlockingMovement() const; EActorTargetPhase GetActorTargetPhase() const { return m_eActorTargetPhase; } IActionController* GetActionController(); void OnDialogLoaded(struct ILipSync* pLipSync); void OnDialogFailed(struct ILipSync* pLipSync); enum ESetFlags { SET_IMMEDIATE, SET_DELAYED, SET_ON_SERILIAZE, }; #ifdef USE_DEPRECATED_AI_CHARACTER_SYSTEM bool SetCharacter(const char* character, ESetFlags setFlags = SET_IMMEDIATE); #endif void SetBehavior(const char* szBehavior, const IAISignalExtraData* pData = 0, ESetFlags setFlags = SET_IMMEDIATE); #ifdef USE_DEPRECATED_AI_CHARACTER_SYSTEM const char* GetCharacter(); void CallCharacterConstructor(); #endif void CallBehaviorConstructor(const IAISignalExtraData* pData); void ResendTargetSignalsNextFrame(); // For temporary debug info retrieving in AIProxy. bool DEBUG_IsPlayingSignalAnimation() const { return m_playingSignalAnimation; } bool DEBUG_IsPlayingActionAnimation() const { return m_playingActionAnimation; } const char* DEBUG_GetCurrentSignaAnimationName() const { return m_currentSignalAnimName.c_str(); } const char* DEBUG_GetCurrentActionAnimationName() const { return m_currentActionAnimName.c_str(); } protected: class CAnimActionExactPositioning* CreateExactPositioningAction(bool isOneShot, float loopDuration, const char* szFragmentID, bool isNavigationalSO, const QuatT& exactStartLocation); #ifdef USE_DEPRECATED_AI_CHARACTER_SYSTEM const char* GetInitialCharacterName(); #endif const char* GetInitialBehaviorName(); const char* GetBehaviorFileName(const char* szBehaviorName); IActor* GetActor() const; #ifdef USE_DEPRECATED_AI_CHARACTER_SYSTEM void ResetCharacter(); #endif void ResetBehavior(); void ResetAnimationData(); void SetInitialBehaviorAndCharacter(); #ifdef USE_DEPRECATED_AI_CHARACTER_SYSTEM const char* CheckAndGetBehaviorTransition(const char* szSignalText) const; #endif bool CallScript(IScriptTable* scriptTable, const char* funcName, float* pValue = NULL, IEntity* pSender = NULL, const IAISignalExtraData* pData = NULL); bool GetMostLikelyTable(IScriptTable* table, SmartScriptTable& dest); bool FindOrLoadTable(IScriptTable* pGlobalTable, const char* szTableName, SmartScriptTable& tableOut); void FindOrLoadBehavior(const char* szBehaviorName, SmartScriptTable& pBehaviorTable); void Serialize(TSerialize ser); void SerializeScriptAI(TSerialize& ser); void SetAlertness(int value, bool triggerEvent = false); /// Iterates to the next valid readability sound while testing readability sounds. void NextReadabilityTest(); void ResetCommonTables(); bool SetCommonTables(); static const char* GetAGInputName(EAIAGInput input); void MakeFace(CAIFaceManager::e_ExpressionEvent expression); IScriptTable* m_pScriptObject; IEntity* m_pEntity; IGameObject* m_pGameObject; bool m_bSoundFinished; #ifdef USE_DEPRECATED_AI_CHARACTER_SYSTEM SmartScriptTable m_pCharacter; #endif SmartScriptTable m_pBehavior; SmartScriptTable m_pPreviousBehavior; #ifdef USE_DEPRECATED_AI_CHARACTER_SYSTEM SmartScriptTable m_pDefaultBehavior; SmartScriptTable m_pDefaultCharacter; #endif SmartScriptTable m_pDEFAULTDefaultBehavior; SmartScriptTable m_pBehaviorTable; SmartScriptTable m_pBehaviorTableAVAILABLE; SmartScriptTable m_pBehaviorTableINTERNAL; int m_CurrentAlertness; bool m_CurrentExclusive; #ifdef USE_DEPRECATED_AI_CHARACTER_SYSTEM bool m_bDelayedCharacterConstructor; #endif bool m_bDelayedBehaviorConstructor; string m_sBehaviorName; #ifdef USE_DEPRECATED_AI_CHARACTER_SYSTEM string m_sDefaultBehaviorName; string m_sCharacterName; string m_sPrevCharacterName; string m_sFirstCharacterName; #endif string m_sFirstBehaviorName; IAnimationGraphState* m_pAGState; TAnimationGraphQueryID m_ActionQueryID; TAnimationGraphQueryID m_SignalQueryID; string m_sQueriedActionAnimation; string m_sQueriedSignalAnimation; bool m_bSignaledAnimationStarted; typedef std::set< string > SetStrings; SetStrings m_setPlayedSignalAnimations; SetStrings m_setStartedActionAnimations; TAnimationGraphQueryID m_actorTargetStartedQueryID; TAnimationGraphQueryID m_actorTargetEndQueryID; TExactPositioningQueryID* m_curActorTargetStartedQueryID; TExactPositioningQueryID* m_curActorTargetEndQueryID; bool m_bAnimationStarted; EActorTargetPhase m_eActorTargetPhase; int m_actorTargetId; TAnimationGraphQueryID m_changeActionInputQueryId; TAnimationGraphQueryID m_changeSignalInputQueryId; string m_sAGActionSOAutoState; bool m_playingSignalAnimation; bool m_playingActionAnimation; string m_currentSignalAnimName; string m_currentActionAnimName; Vec3 m_vAnimationTargetPosition; Quat m_qAnimationTargetOrientation; CAIFaceManager m_FaceManager; EAITargetType m_lastTargetType; EAITargetThreat m_lastTargetThreat; tAIObjectID m_lastTargetID; Vec3 m_lastTargetPos; struct SAnimActionTracker { SAnimActionTracker() { m_animActions.reserve(4); } void ReleaseAll(); // cancel all animactions and deregister listeners void ForceFinishAll(); // forcefinish all animactions (keep listening for events) void StopAll(); // stop all animactions (keep listening for events) void StopAllActionsOfType(bool isOneShot); // stop all animactions of specified type (keep listening for events) void Add(CAnimActionTriState* pAction); void Remove(CAnimActionTriState* pAction); bool IsNotEmpty() const { return !m_animActions.empty(); } private: typedef _smart_ptr AnimActionPtr; typedef std::vector TAnimActionVector; TAnimActionVector m_animActions; }; SAnimActionTracker m_animActionTracker; private: void DoReadibilityPackForAIObjectsOfType(unsigned short int nType, const char* szText, float fResponseDelay); float m_timeSinceEvent; }; #endif // CRYINCLUDE_CRYACTION_AIHANDLER_H