/* * 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. // Description : Instructs an Entity/Actor to play a certain ScriptLine #ifndef CRYINCLUDE_CRYACTION_DIALOGSYSTEM_DIALOGACTORCONTEXT_H #define CRYINCLUDE_CRYACTION_DIALOGSYSTEM_DIALOGACTORCONTEXT_H #pragma once #include "DialogScript.h" #include "DialogSession.h" #include "DialogCommon.h" #include <IEntitySystem.h> #include <IAnimationGraph.h> #define DS_DEBUG_SUPPRESSION // #undef DS_DEBUG_SUPPRESSION class CDialogActorContext : public _i_reference_target_t , public IEntityEventListener , public IGoalPipeListener , public IAnimationGraphStateListener { public: CDialogActorContext(CDialogSession* pSession, CDialogScript::TActorID actorID); ~CDialogActorContext(); bool PlayLine(const CDialogScript::SScriptLine* pLine); // returning false stops the Session! bool Update(float dt); void BeginSession(); void EndSession(); bool IsAborted() const; bool IsStillPlaying() const; CDialogSession::EAbortReason GetAbortReason() const { return m_abortReason; } static const char* FullSoundName(const string& soundName, bool bWav = true); static const char* GetSoundKey(const string& soundName); CDialogSystem::ActorContextID GetContextID() const { return m_ContextID; } static void ResetStaticData(); void GetMemoryUsage(ICrySizer* pSizer) const; ILINE bool CheckActorFlags(CDialogSession::TActorFlags flag) const { return (m_pSession->GetActorFlags(m_actorID) & flag) != 0; } static void OnAudioTriggerFinished(Audio::SAudioRequestInfo const* const pAudioRequestInfo); static const char* GetClassIdentifier() { return "DialogActorContext"; } static CDialogActorContext* GetDialogActorContextByAudioCallbackData(Audio::SAudioRequestInfo const* const pAudioRequestInfo); EntityId GetEntityID() const { return m_entityID; } protected: // Play an animation action on the entity [AG pr EP] bool DoAnimAction(IEntity* pEntity, const string& action, bool bIsSignal, bool bUseEP); // Play an animation action [AnimGraph Action/Signal] on the entity bool DoAnimActionAG(IEntity* pEntity, const char* sAction); // Play an animation action [Exact Positioning Action/Signal] on the entity bool DoAnimActionEP(IEntity* pEntity, const char* sAction); // Play a facial expression on the entity bool DoFacialExpression(IEntity* pEntity, const string& expression, float weight, float fadeTime); // Instrument pEntity to look at pLookAtEntity bool DoLookAt(IEntity* pEntity, IEntity* pLookAtEntity, bool& bTargetReached); // Handle any sticky lookat void DoStickyLookAt(); // Do check wrt. local player bool DoLocalPlayerChecks(const float dt); // IEntityEventListener virtual void OnEntityEvent(IEntity* pEntity, SEntityEvent& event); // ~IEntityEventListener // IGoalPipeListener virtual void OnGoalPipeEvent(IPipeUser* pPipeUser, EGoalPipeEvent event, int goalPipeId, bool& unregisterListenerAfterEvent); // ~IGoalPipeListener // IAnimationGraphStateListener virtual void SetOutput(const char* output, const char* value); virtual void QueryComplete(TAnimationGraphQueryID queryID, bool succeeded); virtual void DestroyedState(IAnimationGraphState*); // ~IAnimationGraphStateListener void ResetState(); void CancelCurrent(bool bResetStates = false); bool ExecuteAI(int& goalPipeID, const char* signalText, IAISignalExtraData* pExtraData = 0, bool bRegisterAsListener = true); void AdvancePhase(); void StopSound(bool bUnregisterOnly = false); void AbortContext(bool bCancel, CDialogSession::EAbortReason reason); void ResetAGState(); void UpdateAuxProxyPosition(); ILINE CDialogSession::EDialogAIInterruptBehaviour GetAIBehaviourMode() const { return m_pSession->GetAIBehaviourMode(); } ILINE bool SessionAllowsLookAt() { const bool bAllowed = GetAIBehaviourMode() != CDialogSession::eDIB_InterruptNever; #ifdef DS_DEBUG_SUPPRESSION if (!bAllowed && m_pCurLine && (m_pCurLine->m_lookatActor != CDialogScript::NO_ACTOR_ID || m_stickyLookAtActorID != CDialogScript::NO_ACTOR_ID)) { DiaLOG::Log(DiaLOG::eDebugB, "[DIALOG] CDialogActorContext::Update: %s now=%f actorID=%d line=%d AIMode=%d SuppressingLookAt=%d", m_pSession->GetDebugName(), m_pSession->GetCurTime(), m_actorID, m_pSession->GetCurrentLine(), (int) GetAIBehaviourMode(), m_pCurLine->m_lookatActor); } #endif return bAllowed; } ILINE bool SessionAllowsAnim() { const bool bAllowed = GetAIBehaviourMode() != CDialogSession::eDIB_InterruptNever; #ifdef DS_DEBUG_SUPPRESSION if (!bAllowed && m_pCurLine && m_pCurLine->m_anim.empty() == false) { DiaLOG::Log(DiaLOG::eDebugB, "[DIALOG] CDialogActorContext::Update: %s now=%f actorID=%d line=%d AIMode=%d SuppressingAnim='%s'", m_pSession->GetDebugName(), m_pSession->GetCurTime(), m_actorID, m_pSession->GetCurrentLine(), (int) GetAIBehaviourMode(), m_pCurLine->m_anim.c_str()); } #endif return bAllowed; } protected: enum EDialogActorContextPhase { eDAC_Idle = 0, eDAC_NewLine, eDAC_LookAt, eDAC_Anim, eDAC_ScheduleSoundPlay, // Schedule sound to play and wait until it really starts eDAC_SoundFacial, eDAC_EndLine, eDAC_Aborted }; // TODO: Currently logically grouped. Needs proper space-saving reordering CDialogSession* m_pSession; CDialogScript::TActorID m_actorID; EntityId m_entityID; const CDialogScript::SScriptLine* m_pCurLine; CDialogSystem::ActorContextID m_ContextID; IActor* m_pIActor; int m_phase; bool m_bHasScheduled; bool m_bNeedsCancel; bool m_bInCancel; bool m_bIsLocalPlayer; // Whether it's the local player bool m_bIsAware; bool m_bIsAwareLooking; bool m_bIsAwareInRange; float m_playerAwareTimeOut; float m_checkPlayerTimeOut; CDialogSession::EAbortReason m_abortReason; Audio::TAudioProxyID m_SpeechAuxProxy; // Animation specific IAnimationGraphState* m_pAGState; TAnimationGraphQueryID m_queryID; bool m_bAnimStarted; bool m_bAnimScheduled; bool m_bAnimUseAGSignal; bool m_bAnimUseEP; bool m_bSoundStopsAnim; // AI bool m_bAbortFromAI; int m_goalPipeID; int m_exPosAnimPipeID; // Sound specific bool m_bSoundScheduled; bool m_bSoundStarted; float m_soundTimeOut; float m_soundLength; int m_VoiceAttachmentIndex; int m_BoneHeadJointID; // LookAt specific CDialogScript::TActorID m_lookAtActorID; CDialogScript::TActorID m_stickyLookAtActorID; float m_lookAtTimeOut; float m_animTimeOut; bool m_bLookAtNeedsReset; // Facial Expression uint32 m_currentEffectorChannelID; static string m_tempBuffer; }; #endif // CRYINCLUDE_CRYACTION_DIALOGSYSTEM_DIALOGACTORCONTEXT_H