331 lines
14 KiB
C++
331 lines
14 KiB
C++
// 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<CTaskNMControl*>(GetParent()), "Parent task MUST be type CTaskNMControl!");
|
|
CTaskNMControl *pControlTask = smart_cast<CTaskNMControl*>(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<CTaskNMControl*>(GetParent()), "Parent task MUST be type CTaskNMControl!");
|
|
CTaskNMControl *pControlTask = smart_cast<CTaskNMControl*>(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
|
|
|