// Filename : TaskNMPose.cpp // Description: Debug task to hold the bind pose with natural motion without any physics acting (FSM version). // Used to investigate transition between NM ragdolls and clip. #if __DEV // --- Include Files ------------------------------------------------------------ // Rage headers: #include "crskeleton/Skeleton.h" #include "fragmentnm/messageparams.h" // Game headers: #include "Event/Events.h" #include "Peds/Ped.h" #include "Peds/PedIntelligence.h" #include "Streaming/streaming.h" #include "Task/Physics/TaskNMBindPose.h" // ------------------------------------------------------------------------------ AI_OPTIMISATIONS() static const strStreamingObjectName g_clipDictName("playidles_cold", 0x73FAC095); //static char g_clipName[] = "blow_hands"; ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// CTaskBindPose::CTaskBindPose(bool bDoBlendFromNM) ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// : m_bDoBlendFromNM(bDoBlendFromNM), m_bSwitchStateSignal(false), m_bInNmMode(false) { SetInternalTaskType(CTaskTypes::TASK_BIND_POSE); } ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// aiTask* CTaskBindPose::Copy() const ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// { CTaskBindPose* pNewTask = rage_new CTaskBindPose(m_bDoBlendFromNM); return pNewTask; } ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void CTaskBindPose::CleanUp() ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// { /* s32 index = fwAnimManager::FindSlot(g_clipDictName); if(taskVerifyf(index != -1, "Invalid clip name")) { u32 ClipHashKey = atStringHash(g_clipDictName); CStreaming::RemoveObject(index, fwAnimManager::GetStreamingModuleId()); } */ } ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// CTask::FSM_Return CTaskBindPose::UpdateFSM(const s32 iState, const FSM_Event iEvent) ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// { CPed *pPed = GetPed(); //Get the ped ptr. FSM_Begin FSM_State(State_Start) FSM_OnEnter Start_OnEnter(pPed); FSM_OnUpdate return Start_OnUpdate(pPed); FSM_State(State_StreamingClips) FSM_OnEnter StreamingClips_OnEnter(pPed); FSM_OnUpdate return StreamingClips_OnUpdate(pPed); FSM_OnExit StreamingClips_OnExit(pPed); FSM_State(State_NmBindPose) FSM_OnEnter NmBindPose_OnEnter(pPed); FSM_OnUpdate return NmBindPose_OnUpdate(pPed); FSM_OnExit NmBindPose_OnExit(pPed); FSM_State(State_ClipBindPose) FSM_OnEnter ClipBindPose_OnEnter(pPed); FSM_OnUpdate return ClipBindPose_OnUpdate(pPed); FSM_OnExit ClipBindPose_OnExit(pPed); FSM_State(State_Finish) FSM_OnUpdate return FSM_Quit; FSM_End } ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void CTaskBindPose::Start_OnEnter(CPed* UNUSED_PARAM(pPed)) ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// { } ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// CTask::FSM_Return CTaskBindPose::Start_OnUpdate(CPed* UNUSED_PARAM(pPed)) ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// { SetState(State_StreamingClips); return FSM_Continue; } ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void CTaskBindPose::StreamingClips_OnEnter(CPed* UNUSED_PARAM(pPed)) ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// { // Request the bind-pose dictionary. strLocalIndex index = fwAnimManager::FindSlot(g_clipDictName); taskAssertf(index != -1, "Invalid clip name"); ASSERT_ONLY(bool bStreamRqstOk =) fwAnimManager::GetStreamingModule()->StreamingRequest(index, STRFLAG_MISSION_REQUIRED); taskAssertf(bStreamRqstOk, "Streaming request failed."); } ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// CTask::FSM_Return CTaskBindPose::StreamingClips_OnUpdate(CPed* UNUSED_PARAM(pPed)) ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// { // Poll the clip streaming helper every cycle until it signals that it has // loaded the required clip dictionary. bool bClipsLoaded = false; strLocalIndex index = fwAnimManager::FindSlot(g_clipDictName); if(!taskVerifyf(index != -1, "Invalid clip name")) { return FSM_Quit; } bClipsLoaded = CStreaming::HasObjectLoaded(index, fwAnimManager::GetStreamingModuleId()); if(bClipsLoaded) { SetState(State_ClipBindPose); } return FSM_Continue; } ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void CTaskBindPose::StreamingClips_OnExit(CPed* UNUSED_PARAM(pPed)) ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// { // why are we playing a clip in a bind pose task!? /*StartClipByDictAndHash(pPed, fwAnimManager::FindSlot(g_clipDictName), atStringHash(g_clipName), APF_ISLOOPED|APF_ISBLENDAUTOREMOVE, BONEMASK_ALL, AP_HIGH, INSTANT_BLEND_IN_DELTA, CClipHelper::TerminationType_OnDelete);*/ } ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void CTaskBindPose::NmBindPose_OnEnter(CPed* pPed) ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// { m_bInNmMode = true; if (CTaskNMBehaviour::CanUseRagdoll(pPed, RAGDOLL_TRIGGER_SCRIPT)) { // Instantiate the NM bind-pose task. CTaskNMBindPose* pTask = rage_new CTaskNMBindPose(m_bDoBlendFromNM); CTaskNMControl* pNmControlTask = rage_new CTaskNMControl(pTask->GetMinTime(), pTask->GetMaxTime(), pTask, CTaskNMControl::ALL_FLAGS_CLEAR); SetNewTask(pNmControlTask); } } ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// CTask::FSM_Return CTaskBindPose::NmBindPose_OnUpdate(CPed* UNUSED_PARAM(pPed)) ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// { if(m_bSwitchStateSignal || !GetSubTask()) { m_bSwitchStateSignal = false; SetState(State_ClipBindPose); } return FSM_Continue; } ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void CTaskBindPose::NmBindPose_OnExit(CPed* UNUSED_PARAM(pPed)) ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// { } ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void CTaskBindPose::ClipBindPose_OnEnter(CPed* UNUSED_PARAM(pPed)) ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// { m_bInNmMode = false; } ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// CTask::FSM_Return CTaskBindPose::ClipBindPose_OnUpdate(CPed* pPed) { if(m_bSwitchStateSignal) { m_bSwitchStateSignal = false; SetState(State_NmBindPose); pPed->SwitchToAnimated(); } else { pPed->ForceMotionStateThisFrame(CPedMotionStates::MotionState_AnimatedVelocity); } return FSM_Continue; } ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void CTaskBindPose::ClipBindPose_OnExit(CPed* UNUSED_PARAM(pPed)) ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// { } ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void CTaskBindPose::ToggleNmBindPose() ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// { m_bSwitchStateSignal = true; } /****************************************************************************************************************************************/ /***************************************************** CTaskNMBindPose ****************************************************************/ /****************************************************************************************************************************************/ ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// CTaskNMBindPose::CTaskNMBindPose(bool bDoBlendFromNM) ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// : CTaskNMBehaviour(1000, 10000) { m_bDoBlendFromNM = bDoBlendFromNM; m_bExitSignalReceived = false; SetInternalTaskType(CTaskTypes::TASK_NM_BIND_POSE); } ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// CTaskNMBindPose::~CTaskNMBindPose() ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// { } ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// CTaskInfo* CTaskNMBindPose::CreateQueriableState() const ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// { // this task is not networked yet Assert(!NetworkInterface::IsGameInProgress()); return rage_new CTaskInfo(); } ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// aiTask* CTaskNMBindPose::Copy() const ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// { CTaskNMBindPose* pNewTask = rage_new CTaskNMBindPose(m_bDoBlendFromNM); return pNewTask; } ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void CTaskNMBindPose::StartBehaviour(CPed* pPed) ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// { taskAssert(GetParent()); taskAssertf(dynamic_cast(GetParent()), "Parent task MUST be type CTaskNMControl!"); CTaskNMControl *pControlTask = smart_cast(GetParent()); if(m_bDoBlendFromNM) { pControlTask->SetFlag(CTaskNMControl::DO_BLEND_FROM_NM); } else { pControlTask->ClearFlag(CTaskNMControl::DO_BLEND_FROM_NM); } // Start an "incomingTransforms" behaviour which will completely drive the character to the incoming clip // which, in this case, is just the bind pose. ART::MessageParams msg; msg.addBool(NMSTR_PARAM(NM_START), true); pPed->GetRagdollInst()->PostARTMessage(NMSTR_MSG(NM_INCOMING_TRANSFORMS_MSG), &msg); } ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void CTaskNMBindPose::ControlBehaviour(CPed *UNUSED_PARAM(pPed)) ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// { // Get a pointer to the NM control task which should be our immediate parent. /* taskAssert(GetParent()); taskAssertf(dynamic_cast(GetParent()), "Parent task MUST be type CTaskNMControl!"); CTaskNMControl *pControlTask = smart_cast(GetParent()); */ // Continually update the incoming transforms from the clip if playing. } ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// bool CTaskNMBindPose::FinishConditions(CPed* pPed) ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// { // Override timeout so that this task can be toggled on and off by sending signals. if(m_bExitSignalReceived) { if(!m_bDoBlendFromNM) { pPed->SwitchToAnimated(false, true, false); } return true; } return false; } ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void CTaskNMBindPose::ExitTask() ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// { // This function must be called to get out of the NM bind pose since the task will // never time out on its own (see FinishConditions above). m_bExitSignalReceived = true; } #endif // __DEV