Files
expvintl 419f2e4752 init
2025-02-23 17:40:52 +08:00

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