Files
GTASource/game/task/Physics/TaskAnimatedAttach.h
T
expvintl 419f2e4752 init
2025-02-23 17:40:52 +08:00

264 lines
7.9 KiB
C++

// Filename : TaskAnimatedAttach.h
// Description: Handle attaching a ped to a CPhysical with anywhere from one limb to all four. This task
// manages the constraints and, once attached, starts an NM task to control the ragdoll
// beyond the simple clip.
#ifndef INC_TASKANIMATEDATTACH_H_
#define INC_TASKANIMATEDATTACH_H_
// --- Include Files ------------------------------------------------------------
#include "Network/General/NetworkUtil.h"
#include "Peds/QueriableInterface.h"
#include "Task/System/Task.h"
#include "Task/System/TaskFSMClone.h"
// ------------------------------------------------------------------------------
class CTaskAnimatedAttach : public CTaskFSMClone
{
public:
// A structure to hold information about the attachments required between ragdoll and the attach parent.
struct sAttachedNMComponents
{
Vector3 vPos;
s32 iRagdollComponent;
s32 iPedBoneIndex;
};
//A mask is set through script so these can be checked later
enum eNMConstraintFlags
{
NMCF_LEFT_HAND = BIT(0),
NMCF_RIGHT_HAND = BIT(1),
NMCF_LEFT_FOOT = BIT(2),
NMCF_RIGHT_FOOT = BIT(3),
NMCF_LEFT_FOREARM = BIT(4),
NMCF_RIGHT_FOREARM = BIT(5),
NMCF_LEFT_SHIN = BIT(6),
NMCF_RIGHT_SHIN = BIT(7),
NMCF_LEFT_THIGH = BIT(8),
NMCF_RIGHT_THIGH = BIT(9),
NMCF_HANDS_AND_FEET = NMCF_LEFT_HAND | NMCF_RIGHT_HAND | NMCF_LEFT_FOOT | NMCF_RIGHT_FOOT,
NMCF_ALL = NMCF_HANDS_AND_FEET | NMCF_LEFT_FOREARM | NMCF_RIGHT_FOREARM | NMCF_LEFT_SHIN | NMCF_RIGHT_SHIN | NMCF_LEFT_THIGH | NMCF_RIGHT_THIGH
};
enum
{
State_Start = 0,
State_StreamAssets,
State_ClipatingApproach,
State_PosingPed,
State_AttachingPed,
State_PedAttached,
// State_ReattachingPed,
State_Finish
};
CTaskAnimatedAttach(CPhysical* pParent, s32 nParentBoneIndex, const Vector3 &vOffset, const Quaternion& RotationQuaternion, u32 iAttachFlags, s32 ClipDict,
u32 ApprochClip, u32 IdleClip , bool bStreamAssets = false);
CTaskAnimatedAttach(CPhysical* pParent, s32 nParentBoneIndex, u32 iAttachFlags, s32 ClipDict, u32 IdleClip);
~CTaskAnimatedAttach();
virtual aiTask* Copy() const;
virtual void CleanUp();
void SetAttachToVehicleDoor(bool bAttachToVehicleDoor) { m_bAttachToVehicleDoor = bAttachToVehicleDoor; }
// Clone task implementation
virtual CTaskInfo* CreateQueriableState() const;
virtual FSM_Return UpdateClonedFSM (const s32 iState, const FSM_Event iEvent);
virtual void OnCloneTaskNoLongerRunningOnOwner();
virtual bool IsInScope(const CPed* pPed);
virtual bool OverridesNetworkAttachment(CPed *UNUSED_PARAM(pPed)) { return true; }
CTaskFSMClone* CreateTaskForClonePed(CPed *pPed);
CTaskFSMClone* CreateTaskForLocalPed(CPed *pPed);
void SetParentNetObjId(ObjectId objId) { m_parentNetObjId = objId; }
////////////////////////////
// CTaskFSM functions:
protected:
//FSM_Return ProcessPreFSM();
FSM_Return UpdateFSM(const s32 iState, const FSM_Event iEvent);
s32 GetDefaultStateAfterAbort() const {return State_Finish;}
int GetTaskTypeInternal() const {return CTaskTypes::TASK_ANIMATED_ATTACH;}
#if !__FINAL
friend class CTaskClassInfoManager;
static const char *GetStaticStateName(s32 iState)
{
Assert(iState>=State_Start&&iState<=State_Finish);
static const char* aStateNames[] =
{
"State_Start",
"State_StreamAssets",
"State_AnimatingApproach",
"State_PosingPed",
"State_AttachingPed",
"State_PedAttached",
// "State_ReattachingPed",
"State_Finish"
};
return aStateNames[iState];
}
#endif // !__FINAL
// Called after the skeleton update but before the Ik. Global matrices are valid in this function.
//virtual void ProcessPreRender2(CPed *);
#if DEBUG_DRAW
public:
virtual void Debug() const;
void DebugVisualise(CPed *pPed);
#endif // DEBUG_DRAW
private:
// Helper functions for FSM state management:
void Start_OnEnter(CPed* pPed);
FSM_Return Start_OnUpdate(CPed* pPed);
FSM_Return StreamAssets_OnUpdate(CPed* pPed);
void PosingPed_OnEnter(CPed* pPed);
FSM_Return PosingPed_OnUpdate(CPed* pPed);
void PosingPed_OnExit(CPed* pPed);
void AttachingPed_OnEnter(CPed* pPed);
FSM_Return AttachingPed_OnUpdate(CPed* pPed);
void AttachingPed_OnExit(CPed* pPed);
void PedAttached_OnEnter(CPed* pPed);
FSM_Return PedAttached_OnUpdate(CPed* pPed);
void PedAttached_OnExit(CPed* pPed);
void ChooseNextIdleClip(fwMvClipSetId &clipSetId, fwMvClipId &clipId);
bool IsAttachFlagSet(const int iFlag) const {return ((m_nAttachFlags & iFlag) ? true : false);}
void CalculateAttachPoints(atArray<sAttachedNMComponents> &Attach, CPed * pPed);
void DetachPed(CPed* pPed, bool bIgnoreAttachState = false);
void ConfigureRagdollCollision(CPed* pPed, bool bCollisionEnabled);
bool HandlesRagdoll(const CPed* pPed) const
{
if (GetState()==State_AttachingPed)
return true;
else
return CTask::HandlesRagdoll(pPed);
}
private:
// Data passed from script:
u32 m_nAttachFlags; // Flags to denote which parts of the ragdoll are attached.
Vector3 m_vAttachOffset;
Quaternion m_RotationQuaternion; // This rotation is never actually used
s32 m_nClipDict;
u32 m_nClip;
u32 m_nIdleClip;
bool m_bStreamAssets;
bool m_bPosedFromIdle;
bool m_bAttachToVehicleDoor;
fwClipSetRequestHelper m_ClipSetRequestHelper;
RegdPhy m_pAttachParent;
bool m_bPedAttached;
bool m_bRunShootingTask;
u32 m_nStartTime;
static u32 m_nFiringDelay;
static Vector3 ms_vecTarget;
s32 m_nBoneIndex;
// The currently playing idle clip:
fwMvClipSetId m_clipSetId;
fwMvClipId m_clipId;
// clone task members
ObjectId m_parentNetObjId;
bool m_bQuitCloneTask;
#if __BANK
public:
#endif // __BANK
static float ms_fInvMassMult;
static bool m_bEnableDebugDraw;
};
//-------------------------------------------------------------------------
// Task info for animated attach
//-------------------------------------------------------------------------
class CClonedAnimatedAttachInfo : public CSerialisedFSMTaskInfo
{
public:
CClonedAnimatedAttachInfo() :
m_nParentBoneIndex(0),
m_iAttachFlags(0),
m_ClipDict(-1),
m_IdleClip(0)
{
}
CClonedAnimatedAttachInfo(CPhysical* pParent, s32 nParentBoneIndex, u32 iAttachFlags, s32 ClipDict, u32 IdleClip ) :
m_parentEntity(pParent),
m_nParentBoneIndex(static_cast<u32>(nParentBoneIndex)),
m_iAttachFlags(iAttachFlags),
m_ClipDict(ClipDict),
m_IdleClip(IdleClip)
{
}
~CClonedAnimatedAttachInfo(){}
virtual s32 GetTaskInfoType( ) const {return INFO_TYPE_ANIMATED_ATTACH;}
virtual CTaskFSMClone *CreateCloneFSMTask()
{
CTaskAnimatedAttach* pTask = NULL;
if (m_parentEntity.GetEntity())
{
pTask = rage_new CTaskAnimatedAttach(SafeCast(CPhysical, m_parentEntity.GetEntity()), m_nParentBoneIndex, m_iAttachFlags, m_ClipDict, m_IdleClip);
}
else
{
pTask = rage_new CTaskAnimatedAttach(NULL, m_nParentBoneIndex, m_iAttachFlags, m_ClipDict, m_IdleClip);
pTask->SetParentNetObjId(m_parentEntity.GetEntityID());
}
return pTask;
}
virtual bool HasState() const { return false; }
void Serialise(CSyncDataBase& serialiser)
{
CSerialisedFSMTaskInfo::Serialise(serialiser);
ObjectId entityID = m_parentEntity.GetEntityID();
SERIALISE_OBJECTID(serialiser, entityID, "Parent Entity");
m_parentEntity.SetEntityID(entityID);
u32 nParentBoneIndex = m_nParentBoneIndex;
SERIALISE_UNSIGNED(serialiser, nParentBoneIndex, SIZEOF_BONE_INDEX, "Parent Bone Index");
m_nParentBoneIndex = nParentBoneIndex;
u32 iAttachFlags = m_iAttachFlags;
SERIALISE_UNSIGNED(serialiser, iAttachFlags, SIZEOF_ATTACH_FLAGS, "Attach Flags");
m_iAttachFlags = iAttachFlags;
SERIALISE_ANIMATION_CLIP(serialiser, m_ClipDict, m_IdleClip, "Attach anim");
}
private:
static const unsigned SIZEOF_BONE_INDEX = 8;
static const unsigned SIZEOF_ATTACH_FLAGS = 9;
CSyncedEntity m_parentEntity;
s32 m_ClipDict;
u32 m_IdleClip;
u32 m_nParentBoneIndex : SIZEOF_BONE_INDEX;
u32 m_iAttachFlags : SIZEOF_ATTACH_FLAGS;
};
#endif //INC_TASKANIMATEDATTACH_H_