diff options
Diffstat (limited to 'src/animation')
-rw-r--r-- | src/animation/AnimBlendAssocGroup.cpp | 51 | ||||
-rw-r--r-- | src/animation/AnimBlendAssocGroup.h | 4 | ||||
-rw-r--r-- | src/animation/AnimBlendAssociation.cpp | 47 | ||||
-rw-r--r-- | src/animation/AnimBlendAssociation.h | 26 | ||||
-rw-r--r-- | src/animation/AnimBlendClumpData.h | 18 | ||||
-rw-r--r-- | src/animation/AnimBlendHierarchy.cpp | 49 | ||||
-rw-r--r-- | src/animation/AnimBlendHierarchy.h | 5 | ||||
-rw-r--r-- | src/animation/AnimBlendNode.cpp | 172 | ||||
-rw-r--r-- | src/animation/AnimBlendNode.h | 6 | ||||
-rw-r--r-- | src/animation/AnimBlendSequence.cpp | 22 | ||||
-rw-r--r-- | src/animation/AnimBlendSequence.h | 45 | ||||
-rw-r--r-- | src/animation/AnimManager.cpp | 1070 | ||||
-rw-r--r-- | src/animation/AnimManager.h | 59 | ||||
-rw-r--r-- | src/animation/AnimationId.h | 193 | ||||
-rw-r--r-- | src/animation/Bones.cpp | 73 | ||||
-rw-r--r-- | src/animation/Bones.h | 38 | ||||
-rw-r--r-- | src/animation/CutsceneMgr.cpp | 531 | ||||
-rw-r--r-- | src/animation/CutsceneMgr.h | 12 | ||||
-rw-r--r-- | src/animation/FrameUpdate.cpp | 249 | ||||
-rw-r--r-- | src/animation/RpAnimBlend.cpp | 112 | ||||
-rw-r--r-- | src/animation/RpAnimBlend.h | 8 |
21 files changed, 2124 insertions, 666 deletions
diff --git a/src/animation/AnimBlendAssocGroup.cpp b/src/animation/AnimBlendAssocGroup.cpp index 295d6be3..935e7fd6 100644 --- a/src/animation/AnimBlendAssocGroup.cpp +++ b/src/animation/AnimBlendAssocGroup.cpp @@ -12,6 +12,7 @@ #include "General.h" #include "RwHelper.h" +#include "ModelIndices.h" #include "ModelInfo.h" #include "AnimManager.h" #include "RpAnimBlend.h" @@ -20,8 +21,11 @@ CAnimBlendAssocGroup::CAnimBlendAssocGroup(void) { + animBlock = nil; assocList = nil; numAssociations = 0; + firstAnimId = 0; + groupId = -1; } CAnimBlendAssocGroup::~CAnimBlendAssocGroup(void) @@ -42,7 +46,7 @@ CAnimBlendAssocGroup::DestroyAssociations(void) CAnimBlendAssociation* CAnimBlendAssocGroup::GetAnimation(uint32 id) { - return &assocList[id]; + return &assocList[id - firstAnimId]; } CAnimBlendAssociation* @@ -52,6 +56,7 @@ CAnimBlendAssocGroup::GetAnimation(const char *name) for(i = 0; i < numAssociations; i++) if(!CGeneral::faststricmp(assocList[i].hierarchy->name, name)) return &assocList[i]; + debug("\n\nCan't find the fucking animation %s\n\n\n", name); return nil; } @@ -101,7 +106,7 @@ strcmpIgnoringDigits(const char *s1, const char *s2) c2 = __ascii_toupper(c2); #endif - if(c1 != c2) + if(c1 && c2 && c1 != c2) return false; } } @@ -111,6 +116,15 @@ GetModelFromName(const char *name) { int i; CBaseModelInfo *mi; + char playername[32]; + + if(strncasecmp(name, "CSplay", 6) == 0 && + strncasecmp(CModelInfo::GetModelInfo(MI_PLAYER)->GetModelName(), "ig", 2) == 0){ + strcpy(playername, CModelInfo::GetModelInfo(MI_PLAYER)->GetModelName()); + playername[0] = 'C'; + playername[1] = 'S'; + name = playername; + } for(i = 0; i < MODELINFOSIZE; i++){ mi = CModelInfo::GetModelInfo(i); @@ -127,8 +141,7 @@ CAnimBlendAssocGroup::CreateAssociations(const char *name) int i; CAnimBlock *animBlock; - if(assocList) - DestroyAssociations(); + DestroyAssociations(); animBlock = CAnimManager::GetAnimationBlock(name); assocList = new CAnimBlendAssociation[animBlock->numAnims]; @@ -137,17 +150,18 @@ CAnimBlendAssocGroup::CreateAssociations(const char *name) for(i = 0; i < animBlock->numAnims; i++){ CAnimBlendHierarchy *anim = CAnimManager::GetAnimation(animBlock->firstIndex + i); CBaseModelInfo *model = GetModelFromName(anim->name); - assert(model); - printf("Associated anim %s with model %s\n", anim->name, model->GetModelName()); - RpClump *clump = (RpClump*)model->CreateInstance(); -#ifdef PED_SKIN - if(IsClumpSkinned(clump)) - RpClumpForAllAtomics(clump, AtomicRemoveAnimFromSkinCB, nil); -#endif - RpAnimBlendClumpInit(clump); - assocList[i].Init(clump, anim); - RpClumpDestroy(clump); - assocList[i].animId = i; + if(model){ + debug("Associated anim %s with model %s\n", anim->name, model->GetModelName()); + RpClump *clump = (RpClump*)model->CreateInstance(); + RpAnimBlendClumpInit(clump); + assocList[i].Init(clump, anim); + if(IsClumpSkinned(clump)) + RpClumpForAllAtomics(clump, AtomicRemoveAnimFromSkinCB, nil); + RpClumpDestroy(clump); + assocList[i].animId = firstAnimId + i; + assocList[i].groupId = groupId; + }else + debug("\n\nCANNOT FIND MODELINFO WITH NAME %s\n\n\n", anim->name); } numAssociations = animBlock->numAnims; } @@ -157,10 +171,8 @@ void CAnimBlendAssocGroup::CreateAssociations(const char *blockName, RpClump *clump, const char **animNames, int numAssocs) { int i; - CAnimBlock *animBlock; - if(assocList) - DestroyAssociations(); + DestroyAssociations(); animBlock = CAnimManager::GetAnimationBlock(blockName); assocList = new CAnimBlendAssociation[numAssocs]; @@ -168,7 +180,8 @@ CAnimBlendAssocGroup::CreateAssociations(const char *blockName, RpClump *clump, numAssociations = 0; for(i = 0; i < numAssocs; i++){ assocList[i].Init(clump, CAnimManager::GetAnimation(animNames[i], animBlock)); - assocList[i].animId = i; + assocList[i].animId = firstAnimId + i; + assocList[i].groupId = groupId; } numAssociations = numAssocs; } diff --git a/src/animation/AnimBlendAssocGroup.h b/src/animation/AnimBlendAssocGroup.h index aa58b0d3..86f0ca18 100644 --- a/src/animation/AnimBlendAssocGroup.h +++ b/src/animation/AnimBlendAssocGroup.h @@ -1,12 +1,16 @@ #pragma once class CAnimBlendAssociation; +struct CAnimBlock; class CAnimBlendAssocGroup { public: + CAnimBlock *animBlock; CAnimBlendAssociation *assocList; int32 numAssociations; + int32 firstAnimId; + int32 groupId; // id of self in ms_aAnimAssocGroups CAnimBlendAssocGroup(void); ~CAnimBlendAssocGroup(void); diff --git a/src/animation/AnimBlendAssociation.cpp b/src/animation/AnimBlendAssociation.cpp index b03571b0..bb4e7bf4 100644 --- a/src/animation/AnimBlendAssociation.cpp +++ b/src/animation/AnimBlendAssociation.cpp @@ -9,6 +9,7 @@ CAnimBlendAssociation::CAnimBlendAssociation(void) { + groupId = -1; nodes = nil; blendAmount = 1.0f; blendDelta = 0.0f; @@ -54,8 +55,8 @@ CAnimBlendAssociation::AllocateAnimBlendNodeArray(int n) void CAnimBlendAssociation::FreeAnimBlendNodeArray(void) { - assert(nodes != nil); - RwFreeAlign(nodes); + if(nodes) + RwFreeAlign(nodes); } void @@ -75,7 +76,10 @@ CAnimBlendAssociation::Init(RpClump *clump, CAnimBlendHierarchy *hier) // NB: This is where the order of nodes is defined for(i = 0; i < hier->numSequences; i++){ CAnimBlendSequence *seq = &hier->sequences[i]; - frame = RpAnimBlendClumpFindFrame(clump, seq->name); + if(seq->boneTag == -1) + frame = RpAnimBlendClumpFindFrame(clump, seq->name); + else + frame = RpAnimBlendClumpFindBone(clump, seq->boneTag); if(frame && seq->numFrames > 0) nodes[frame - clumpData->frames].sequence = seq; } @@ -90,6 +94,7 @@ CAnimBlendAssociation::Init(CAnimBlendAssociation &assoc) numNodes = assoc.numNodes; flags = assoc.flags; animId = assoc.animId; + groupId = assoc.groupId; AllocateAnimBlendNodeArray(numNodes); for(i = 0; i < numNodes; i++){ nodes[i] = assoc.nodes[i]; @@ -126,12 +131,25 @@ CAnimBlendAssociation::SetCurrentTime(float time) int i; for(currentTime = time; currentTime >= hierarchy->totalLength; currentTime -= hierarchy->totalLength) - if(!IsRepeating()) - return; + if (!IsRepeating()) { + currentTime = hierarchy->totalLength; + break; + } + CAnimManager::UncompressAnimation(hierarchy); - for(i = 0; i < numNodes; i++) - if(nodes[i].sequence) - nodes[i].FindKeyFrame(currentTime); +#ifdef ANIM_COMPRESSION + // strangely PC has this but android doesn't + if(hierarchy->keepCompressed){ + for(i = 0; i < numNodes; i++) + if(nodes[i].sequence) + nodes[i].SetupKeyFrameCompressed(); + }else +#endif + { + for(i = 0; i < numNodes; i++) + if(nodes[i].sequence) + nodes[i].FindKeyFrame(currentTime); + } } void @@ -147,13 +165,23 @@ CAnimBlendAssociation::Start(float time) SetCurrentTime(time); } +void +CAnimBlendAssociation::UpdateTimeStep(float timeDelta, float relSpeed) +{ + if(IsRunning()) + timeStep = (flags & ASSOC_MOVEMENT ? relSpeed*hierarchy->totalLength : speed) * timeDelta; +} + bool CAnimBlendAssociation::UpdateTime(float timeDelta, float relSpeed) { if(!IsRunning()) return true; + if(currentTime >= hierarchy->totalLength){ + flags &= ~ASSOC_RUNNING; + return true; + } - timeStep = (flags & ASSOC_MOVEMENT ? relSpeed*hierarchy->totalLength : speed) * timeDelta; currentTime += timeStep; if(currentTime >= hierarchy->totalLength){ @@ -163,7 +191,6 @@ CAnimBlendAssociation::UpdateTime(float timeDelta, float relSpeed) currentTime -= hierarchy->totalLength; else{ currentTime = hierarchy->totalLength; - flags &= ~ASSOC_RUNNING; if(flags & ASSOC_FADEOUTWHENDONE){ flags |= ASSOC_DELETEFADEDOUT; blendDelta = -4.0f; diff --git a/src/animation/AnimBlendAssociation.h b/src/animation/AnimBlendAssociation.h index 45720b6f..dbfcb722 100644 --- a/src/animation/AnimBlendAssociation.h +++ b/src/animation/AnimBlendAssociation.h @@ -12,12 +12,13 @@ enum { ASSOC_PARTIAL = 0x10, ASSOC_MOVEMENT = 0x20, // ??? ASSOC_HAS_TRANSLATION = 0x40, - ASSOC_WALK = 0x80, // for CPed::PlayFootSteps(void) - ASSOC_IDLE = 0x100, // only used by xpress scratch, see CPed::Chat(void) - ASSOC_NOWALK = 0x200, // see CPed::PlayFootSteps(void) - ASSOC_BLOCK = 0x400, // unused in assoc description, blocks other anims from being played - ASSOC_FRONTAL = 0x800, // anims that we fall to front - ASSOC_HAS_X_TRANSLATION = 0x1000, // for 2d velocity extraction + ASSOC_HAS_X_TRANSLATION = 0x80, // for 2d velocity extraction + ASSOC_WALK = 0x100, // for CPed::PlayFootSteps(void) + ASSOC_IDLE = 0x200, // only xpress scratch has it by default, but game adds it to player's idle animations later + ASSOC_NOWALK = 0x400, // see CPed::PlayFootSteps(void) + ASSOC_BLOCK = 0x800, // unused in assoc description, blocks other anims from being played + ASSOC_FRONTAL = 0x1000, // anims that we fall to front + ASSOC_DRIVING = 0x2000, // new in VC }; // Anim hierarchy associated with a clump @@ -35,7 +36,8 @@ public: CAnimBlendLink link; - int32 numNodes; // taken from CAnimBlendClumpData::numFrames + int16 numNodes; // taken from CAnimBlendClumpData::numFrames + int16 groupId; // ID of CAnimBlendAssocGroup this is in // NB: Order of these depends on order of nodes in Clump this was built from CAnimBlendNode *nodes; CAnimBlendHierarchy *hierarchy; @@ -44,8 +46,8 @@ public: float currentTime; float speed; float timeStep; - int32 animId; - int32 flags; + int16 animId; + int16 flags; int32 callbackType; void (*callback)(CAnimBlendAssociation*, void*); void *callbackArg; @@ -76,16 +78,16 @@ public: void SetCurrentTime(float time); void SyncAnimation(CAnimBlendAssociation *other); void Start(float time); + void UpdateTimeStep(float timeDelta, float relSpeed); bool UpdateTime(float timeDelta, float relSpeed); bool UpdateBlend(float timeDelta); void SetRun(void) { flags |= ASSOC_RUNNING; } - inline float GetTimeLeft() { return hierarchy->totalLength - currentTime; } + float GetTimeLeft() { return hierarchy->totalLength - currentTime; } + float GetProgress() { return currentTime / hierarchy->totalLength; } static CAnimBlendAssociation *FromLink(CAnimBlendLink *l) { return (CAnimBlendAssociation*)((uint8*)l - offsetof(CAnimBlendAssociation, link)); } }; - -VALIDATE_SIZE(CAnimBlendAssociation, 0x40); diff --git a/src/animation/AnimBlendClumpData.h b/src/animation/AnimBlendClumpData.h index acfd006f..bb711b28 100644 --- a/src/animation/AnimBlendClumpData.h +++ b/src/animation/AnimBlendClumpData.h @@ -10,23 +10,19 @@ struct AnimBlendFrameData IGNORE_TRANSLATION = 4, VELOCITY_EXTRACTION = 8, VELOCITY_EXTRACTION_3D = 0x10, + UPDATE_KEYFRAMES = 0x20, + COMPRESSED = 0x40 }; uint8 flag; RwV3d resetPos; -#ifdef PED_SKIN union { RwFrame *frame; RpHAnimStdInterpFrame *hanimFrame; }; int32 nodeID; -#else - RwFrame *frame; -#endif }; -#ifndef PED_SKIN -VALIDATE_SIZE(AnimBlendFrameData, 0x14); -#endif +VALIDATE_SIZE(AnimBlendFrameData, 0x18); class CAnimBlendClumpData @@ -34,9 +30,6 @@ class CAnimBlendClumpData public: CAnimBlendLink link; int32 numFrames; -#ifdef PED_SKIN - int32 modelNumber; // doesn't seem to be used -#endif union { CVector2D *velocity2d; CVector *velocity3d; @@ -47,11 +40,6 @@ public: CAnimBlendClumpData(void); ~CAnimBlendClumpData(void); void SetNumberOfFrames(int n); -#ifdef PED_SKIN void SetNumberOfBones(int n) { SetNumberOfFrames(n); } -#endif void ForAllFrames(void (*cb)(AnimBlendFrameData*, void*), void *arg); }; -#ifndef PED_SKIN -VALIDATE_SIZE(CAnimBlendClumpData, 0x14); -#endif diff --git a/src/animation/AnimBlendHierarchy.cpp b/src/animation/AnimBlendHierarchy.cpp index ea669999..bfa39ef9 100644 --- a/src/animation/AnimBlendHierarchy.cpp +++ b/src/animation/AnimBlendHierarchy.cpp @@ -2,6 +2,7 @@ #include "AnimBlendSequence.h" #include "AnimBlendHierarchy.h" +#include "AnimManager.h" CAnimBlendHierarchy::CAnimBlendHierarchy(void) { @@ -15,9 +16,10 @@ CAnimBlendHierarchy::CAnimBlendHierarchy(void) void CAnimBlendHierarchy::Shutdown(void) { + CAnimManager::RemoveFromUncompressedCache(this); RemoveAnimSequences(); + totalLength = 0.0f; compressed = 0; - linkPtr = nil; } void @@ -30,13 +32,43 @@ void CAnimBlendHierarchy::CalcTotalTime(void) { int i, j; + totalLength = 0.0f; for(i = 0; i < numSequences; i++){ - float seqTime = 0.0f; - for(j = 0; j < sequences[i].numFrames; j++) - seqTime += sequences[i].GetKeyFrame(j)->deltaTime; - totalLength = Max(totalLength, seqTime); +#ifdef FIX_BUGS + if(sequences[i].numFrames == 0) + continue; +#endif + + totalLength = Max(totalLength, sequences[i].GetKeyFrame(sequences[i].numFrames-1)->deltaTime); + for(j = sequences[i].numFrames-1; j >= 1; j--){ + KeyFrame *kf1 = sequences[i].GetKeyFrame(j); + KeyFrame *kf2 = sequences[i].GetKeyFrame(j-1); + kf1->deltaTime -= kf2->deltaTime; + } + } +} + +void +CAnimBlendHierarchy::CalcTotalTimeCompressed(void) +{ + int i, j; + + totalLength = 0.0f; + + for(i = 0; i < numSequences; i++){ +#ifdef FIX_BUGS + if(sequences[i].numFrames == 0) + continue; +#endif + + totalLength = Max(totalLength, sequences[i].GetKeyFrameCompressed(sequences[i].numFrames-1)->GetDeltaTime()); + for(j = sequences[i].numFrames-1; j >= 1; j--){ + KeyFrameCompressed *kf1 = sequences[i].GetKeyFrameCompressed(j); + KeyFrameCompressed *kf2 = sequences[i].GetKeyFrameCompressed(j-1); + kf1->deltaTime -= kf2->deltaTime; + } } } @@ -53,6 +85,7 @@ void CAnimBlendHierarchy::RemoveAnimSequences(void) { delete[] sequences; + sequences = nil; numSequences = 0; } @@ -65,9 +98,11 @@ CAnimBlendHierarchy::Uncompress(void) for(i = 0; i < numSequences; i++) sequences[i].Uncompress(); #endif - if(totalLength == 0.0f) - CalcTotalTime(); compressed = 0; + if(totalLength == 0.0f){ + RemoveQuaternionFlips(); + CalcTotalTime(); + } } void diff --git a/src/animation/AnimBlendHierarchy.h b/src/animation/AnimBlendHierarchy.h index 40d2731b..4838c4f8 100644 --- a/src/animation/AnimBlendHierarchy.h +++ b/src/animation/AnimBlendHierarchy.h @@ -15,7 +15,8 @@ public: char name[24]; CAnimBlendSequence *sequences; int16 numSequences; - int16 compressed; + bool compressed; + bool keepCompressed; float totalLength; CLink<CAnimBlendHierarchy*> *linkPtr; @@ -23,11 +24,13 @@ public: void Shutdown(void); void SetName(char *name); void CalcTotalTime(void); + void CalcTotalTimeCompressed(void); void RemoveQuaternionFlips(void); void RemoveAnimSequences(void); void Uncompress(void); void RemoveUncompressedData(void); void MoveMemory(bool onlyone = false); + bool IsCompressed() { return !!compressed; }; }; VALIDATE_SIZE(CAnimBlendHierarchy, 0x28);
\ No newline at end of file diff --git a/src/animation/AnimBlendNode.cpp b/src/animation/AnimBlendNode.cpp index df6cd1d5..6352c11b 100644 --- a/src/animation/AnimBlendNode.cpp +++ b/src/animation/AnimBlendNode.cpp @@ -46,6 +46,44 @@ CAnimBlendNode::Update(CVector &trans, CQuaternion &rot, float weight) } bool +CAnimBlendNode::UpdateCompressed(CVector &trans, CQuaternion &rot, float weight) +{ + bool looped = false; + + trans = CVector(0.0f, 0.0f, 0.0f); + rot = CQuaternion(0.0f, 0.0f, 0.0f, 0.0f); + + if(association->IsRunning()){ + remainingTime -= association->timeStep; + if(remainingTime <= 0.0f) + looped = NextKeyFrameCompressed(); + } + + float blend = association->GetBlendAmount(weight); + if(blend > 0.0f){ + KeyFrameTransCompressed *kfA = (KeyFrameTransCompressed*)sequence->GetKeyFrameCompressed(frameA); + KeyFrameTransCompressed *kfB = (KeyFrameTransCompressed*)sequence->GetKeyFrameCompressed(frameB); + float t = kfA->deltaTime == 0 ? 0.0f : (kfA->GetDeltaTime() - remainingTime)/kfA->GetDeltaTime(); + if(sequence->type & CAnimBlendSequence::KF_TRANS){ + CVector transA, transB; + kfA->GetTranslation(&transA); + kfB->GetTranslation(&transB); + trans = transB + t*(transA - transB); + trans *= blend; + } + if(sequence->type & CAnimBlendSequence::KF_ROT){ + CQuaternion rotA, rotB; + kfA->GetRotation(&rotA); + kfB->GetRotation(&rotB); + rot.Slerp(rotB, rotA, theta, invSin, t); + rot *= blend; + } + } + + return looped; +} + +bool CAnimBlendNode::NextKeyFrame(void) { bool looped; @@ -82,6 +120,43 @@ CAnimBlendNode::NextKeyFrame(void) return looped; } +bool +CAnimBlendNode::NextKeyFrameCompressed(void) +{ + bool looped; + + if(sequence->numFrames <= 1) + return false; + + looped = false; + frameB = frameA; + + // Advance as long as we have to + while(remainingTime <= 0.0f){ + frameA++; + + if(frameA >= sequence->numFrames){ + // reached end of animation + if(!association->IsRepeating()){ + frameA--; + remainingTime = 0.0f; + return false; + } + looped = true; + frameA = 0; + } + + remainingTime += sequence->GetKeyFrameCompressed(frameA)->GetDeltaTime(); + } + + frameB = frameA - 1; + if(frameB < 0) + frameB += sequence->numFrames; + + CalcDeltasCompressed(); + return looped; +} + // Set animation to time t bool CAnimBlendNode::FindKeyFrame(float t) @@ -92,20 +167,22 @@ CAnimBlendNode::FindKeyFrame(float t) frameA = 0; frameB = frameA; - if(sequence->numFrames >= 2){ - frameA++; - + if(sequence->numFrames == 1){ + remainingTime = 0.0f; + }else{ // advance until t is between frameB and frameA - while(t > sequence->GetKeyFrame(frameA)->deltaTime){ + while (t > sequence->GetKeyFrame(++frameA)->deltaTime) { t -= sequence->GetKeyFrame(frameA)->deltaTime; - frameB = frameA++; - if(frameA >= sequence->numFrames){ + if (frameA + 1 >= sequence->numFrames) { // reached end of animation - if(!association->IsRepeating()) + if (!association->IsRepeating()) { + CalcDeltas(); + remainingTime = 0.0f; return false; + } frameA = 0; - frameB = 0; } + frameB = frameA; } remainingTime = sequence->GetKeyFrame(frameA)->deltaTime - t; @@ -115,6 +192,25 @@ CAnimBlendNode::FindKeyFrame(float t) return true; } +bool +CAnimBlendNode::SetupKeyFrameCompressed(void) +{ + if(sequence->numFrames < 1) + return false; + + frameA = 1; + frameB = 0; + + if(sequence->numFrames == 1){ + frameA = 0; + remainingTime = 0.0f; + }else + remainingTime = sequence->GetKeyFrameCompressed(frameA)->GetDeltaTime(); + + CalcDeltasCompressed(); + return true; +} + void CAnimBlendNode::CalcDeltas(void) { @@ -130,6 +226,28 @@ CAnimBlendNode::CalcDeltas(void) } void +CAnimBlendNode::CalcDeltasCompressed(void) +{ + if((sequence->type & CAnimBlendSequence::KF_ROT) == 0) + return; + KeyFrameCompressed *kfA = sequence->GetKeyFrameCompressed(frameA); + KeyFrameCompressed *kfB = sequence->GetKeyFrameCompressed(frameB); + CQuaternion rotA, rotB; + kfA->GetRotation(&rotA); + kfB->GetRotation(&rotB); + float cos = DotProduct(rotA, rotB); + if(cos < 0.0f){ + rotB *= -1.0f; + kfB->SetRotation(rotB); + } + cos = DotProduct(rotA, rotB); + if(cos > 1.0f) + cos = 1.0f; + theta = Acos(cos); + invSin = theta == 0.0f ? 0.0f : 1.0f/Sin(theta); +} + +void CAnimBlendNode::GetCurrentTranslation(CVector &trans, float weight) { trans = CVector(0.0f, 0.0f, 0.0f); @@ -138,7 +256,7 @@ CAnimBlendNode::GetCurrentTranslation(CVector &trans, float weight) if(blend > 0.0f){ KeyFrameTrans *kfA = (KeyFrameTrans*)sequence->GetKeyFrame(frameA); KeyFrameTrans *kfB = (KeyFrameTrans*)sequence->GetKeyFrame(frameB); - float t = (kfA->deltaTime - remainingTime)/kfA->deltaTime; + float t = kfA->deltaTime == 0.0f ? 0.0f : (kfA->deltaTime - remainingTime)/kfA->deltaTime; if(sequence->type & CAnimBlendSequence::KF_TRANS){ trans = kfB->translation + t*(kfA->translation - kfB->translation); trans *= blend; @@ -147,6 +265,26 @@ CAnimBlendNode::GetCurrentTranslation(CVector &trans, float weight) } void +CAnimBlendNode::GetCurrentTranslationCompressed(CVector &trans, float weight) +{ + trans = CVector(0.0f, 0.0f, 0.0f); + + float blend = association->GetBlendAmount(weight); + if(blend > 0.0f){ + KeyFrameTransCompressed *kfA = (KeyFrameTransCompressed*)sequence->GetKeyFrameCompressed(frameA); + KeyFrameTransCompressed *kfB = (KeyFrameTransCompressed*)sequence->GetKeyFrameCompressed(frameB); + float t = kfA->deltaTime == 0 ? 0.0f : (kfA->GetDeltaTime() - remainingTime)/kfA->GetDeltaTime(); + if(sequence->type & CAnimBlendSequence::KF_TRANS){ + CVector transA, transB; + kfA->GetTranslation(&transA); + kfB->GetTranslation(&transB); + trans = transB + t*(transA - transB); + trans *= blend; + } + } +} + +void CAnimBlendNode::GetEndTranslation(CVector &trans, float weight) { trans = CVector(0.0f, 0.0f, 0.0f); @@ -158,3 +296,19 @@ CAnimBlendNode::GetEndTranslation(CVector &trans, float weight) trans = kf->translation * blend; } } + +void +CAnimBlendNode::GetEndTranslationCompressed(CVector &trans, float weight) +{ + trans = CVector(0.0f, 0.0f, 0.0f); + + float blend = association->GetBlendAmount(weight); + if(blend > 0.0f){ + KeyFrameTransCompressed *kf = (KeyFrameTransCompressed*)sequence->GetKeyFrameCompressed(sequence->numFrames-1); + if(sequence->type & CAnimBlendSequence::KF_TRANS){ + CVector pos; + kf->GetTranslation(&pos); + trans = pos * blend; + } + } +} diff --git a/src/animation/AnimBlendNode.h b/src/animation/AnimBlendNode.h index 89924d6a..99a657ac 100644 --- a/src/animation/AnimBlendNode.h +++ b/src/animation/AnimBlendNode.h @@ -20,11 +20,17 @@ public: void Init(void); bool Update(CVector &trans, CQuaternion &rot, float weight); + bool UpdateCompressed(CVector &trans, CQuaternion &rot, float weight); bool NextKeyFrame(void); + bool NextKeyFrameCompressed(void); bool FindKeyFrame(float t); + bool SetupKeyFrameCompressed(void); void CalcDeltas(void); + void CalcDeltasCompressed(void); void GetCurrentTranslation(CVector &trans, float weight); + void GetCurrentTranslationCompressed(CVector &trans, float weight); void GetEndTranslation(CVector &trans, float weight); + void GetEndTranslationCompressed(CVector &trans, float weight); }; diff --git a/src/animation/AnimBlendSequence.cpp b/src/animation/AnimBlendSequence.cpp index 2ae150c1..36ac9495 100644 --- a/src/animation/AnimBlendSequence.cpp +++ b/src/animation/AnimBlendSequence.cpp @@ -9,9 +9,7 @@ CAnimBlendSequence::CAnimBlendSequence(void) numFrames = 0; keyFrames = nil; keyFramesCompressed = nil; -#ifdef PED_SKIN boneTag = -1; -#endif } CAnimBlendSequence::~CAnimBlendSequence(void) @@ -29,18 +27,21 @@ CAnimBlendSequence::SetName(char *name) } void -CAnimBlendSequence::SetNumFrames(int numFrames, bool translation) +CAnimBlendSequence::SetNumFrames(int numFrames, bool translation, bool compressed) { - int sz; - if(translation){ - sz = sizeof(KeyFrameTrans); type |= KF_ROT | KF_TRANS; + if(compressed) + keyFramesCompressed = RwMalloc(sizeof(KeyFrameTrans) * numFrames); + else + keyFrames = RwMalloc(sizeof(KeyFrameTrans) * numFrames); }else{ - sz = sizeof(KeyFrame); type |= KF_ROT; + if(compressed) + keyFramesCompressed = RwMalloc(sizeof(KeyFrame) * numFrames); + else + keyFrames = RwMalloc(sizeof(KeyFrame) * numFrames); } - keyFrames = RwMalloc(sz * numFrames); this->numFrames = numFrames; } @@ -76,7 +77,7 @@ CAnimBlendSequence::Uncompress(void) float rotScale = 1.0f/4096.0f; float timeScale = 1.0f/60.0f; - float transScale = 1.0f/128.0f; + float transScale = 1.0f/1024.0f; if(type & KF_TRANS){ void *newKfs = RwMalloc(numFrames * sizeof(KeyFrameTrans)); KeyFrameTransCompressed *ckf = (KeyFrameTransCompressed*)keyFramesCompressed; @@ -129,7 +130,7 @@ CAnimBlendSequence::CompressKeyframes(void) float rotScale = 4096.0f; float timeScale = 60.0f; - float transScale = 128.0f; + float transScale = 1024.0f; if(type & KF_TRANS){ void *newKfs = RwMalloc(numFrames * sizeof(KeyFrameTransCompressed)); KeyFrameTransCompressed *ckf = (KeyFrameTransCompressed*)newKfs; @@ -197,4 +198,3 @@ CAnimBlendSequence::MoveMemory(void) return false; } #endif - diff --git a/src/animation/AnimBlendSequence.h b/src/animation/AnimBlendSequence.h index c6e70f22..67118b2f 100644 --- a/src/animation/AnimBlendSequence.h +++ b/src/animation/AnimBlendSequence.h @@ -19,10 +19,38 @@ struct KeyFrameTrans : KeyFrame { struct KeyFrameCompressed { int16 rot[4]; // 4096 int16 deltaTime; // 60 + + void GetRotation(CQuaternion *quat){ + float scale = 1.0f/4096.0f; + quat->x = rot[0]*scale; + quat->y = rot[1]*scale; + quat->z = rot[2]*scale; + quat->w = rot[3]*scale; + } + void SetRotation(const CQuaternion &quat){ + rot[0] = quat.x * 4096.0f; + rot[1] = quat.y * 4096.0f; + rot[2] = quat.z * 4096.0f; + rot[3] = quat.w * 4096.0f; + } + float GetDeltaTime(void) { return deltaTime/60.0f; } + void SetTime(float t) { deltaTime = t*60.0f + 0.5f; } }; struct KeyFrameTransCompressed : KeyFrameCompressed { - int16 trans[3]; // 128 + int16 trans[3]; // 1024 + + void GetTranslation(CVector *vec) { + float scale = 1.0f/1024.0f; + vec->x = trans[0]*scale; + vec->y = trans[1]*scale; + vec->z = trans[2]*scale; + } + void SetTranslation(const CVector &vec){ + trans[0] = vec.x*1024.0f; + trans[1] = vec.y*1024.0f; + trans[2] = vec.z*1024.0f; + } }; @@ -37,32 +65,31 @@ public: int32 type; char name[24]; int32 numFrames; -#ifdef PED_SKIN int16 boneTag; -#endif void *keyFrames; void *keyFramesCompressed; CAnimBlendSequence(void); virtual ~CAnimBlendSequence(void); void SetName(char *name); - void SetNumFrames(int numFrames, bool translation); + void SetNumFrames(int numFrames, bool translation, bool compressed); void RemoveQuaternionFlips(void); KeyFrame *GetKeyFrame(int n) { return type & KF_TRANS ? &((KeyFrameTrans*)keyFrames)[n] : &((KeyFrame*)keyFrames)[n]; } + KeyFrameCompressed *GetKeyFrameCompressed(int n) { + return type & KF_TRANS ? + &((KeyFrameTransCompressed*)keyFramesCompressed)[n] : + &((KeyFrameCompressed*)keyFramesCompressed)[n]; + } bool HasTranslation(void) { return !!(type & KF_TRANS); } void Uncompress(void); void CompressKeyframes(void); void RemoveUncompressedData(void); bool MoveMemory(void); -#ifdef PED_SKIN void SetBoneTag(int tag) { boneTag = tag; } -#endif }; -#ifndef PED_SKIN -VALIDATE_SIZE(CAnimBlendSequence, 0x2C); -#endif +VALIDATE_SIZE(CAnimBlendSequence, 0x30); diff --git a/src/animation/AnimManager.cpp b/src/animation/AnimManager.cpp index c66997ce..f6ac3eb5 100644 --- a/src/animation/AnimManager.cpp +++ b/src/animation/AnimManager.cpp @@ -10,6 +10,7 @@ #include "AnimBlendAssociation.h" #include "AnimBlendAssocGroup.h" #include "AnimManager.h" +#include "Streaming.h" CAnimBlock CAnimManager::ms_aAnimBlocks[NUMANIMBLOCKS]; CAnimBlendHierarchy CAnimManager::ms_aAnimations[NUMANIMATIONS]; @@ -32,65 +33,38 @@ AnimAssocDesc aStdAnimDescs[] = { { ANIM_STD_IDLE_BIGGUN, ASSOC_REPEAT | ASSOC_PARTIAL }, { ANIM_STD_CHAT, ASSOC_REPEAT | ASSOC_PARTIAL }, { ANIM_STD_HAILTAXI, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL }, - { ANIM_STD_KO_FRONT, ASSOC_PARTIAL | ASSOC_HAS_TRANSLATION | ASSOC_FRONTAL }, - { ANIM_STD_KO_LEFT, ASSOC_PARTIAL | ASSOC_HAS_TRANSLATION | ASSOC_FRONTAL }, - { ANIM_STD_KO_BACK, ASSOC_PARTIAL | ASSOC_HAS_TRANSLATION | ASSOC_FRONTAL }, - { ANIM_STD_KO_RIGHT, ASSOC_PARTIAL | ASSOC_HAS_TRANSLATION | ASSOC_FRONTAL }, - { ANIM_STD_KO_SHOT_FACE, ASSOC_PARTIAL | ASSOC_HAS_TRANSLATION | ASSOC_FRONTAL }, + { ANIM_STD_KO_FRONT, ASSOC_PARTIAL | ASSOC_HAS_TRANSLATION | ASSOC_FRONTAL }, + { ANIM_STD_KO_LEFT, ASSOC_PARTIAL | ASSOC_HAS_TRANSLATION | ASSOC_FRONTAL }, + { ANIM_STD_KO_BACK, ASSOC_PARTIAL | ASSOC_HAS_TRANSLATION | ASSOC_FRONTAL }, + { ANIM_STD_KO_RIGHT, ASSOC_PARTIAL | ASSOC_HAS_TRANSLATION | ASSOC_FRONTAL }, + { ANIM_STD_KO_SHOT_FACE, ASSOC_PARTIAL | ASSOC_HAS_TRANSLATION | ASSOC_FRONTAL }, { ANIM_STD_KO_SHOT_STOMACH, ASSOC_PARTIAL | ASSOC_HAS_TRANSLATION }, - { ANIM_STD_KO_SHOT_ARM_L, ASSOC_PARTIAL | ASSOC_FRONTAL }, - { ANIM_STD_KO_SHOT_ARM_R, ASSOC_PARTIAL | ASSOC_FRONTAL }, + { ANIM_STD_KO_SHOT_ARM_L, ASSOC_PARTIAL | ASSOC_FRONTAL }, + { ANIM_STD_KO_SHOT_ARM_R, ASSOC_PARTIAL | ASSOC_FRONTAL }, { ANIM_STD_KO_SHOT_LEG_L, ASSOC_PARTIAL | ASSOC_HAS_TRANSLATION }, { ANIM_STD_KO_SHOT_LEG_R, ASSOC_PARTIAL | ASSOC_HAS_TRANSLATION }, - { ANIM_STD_SPINFORWARD_LEFT, ASSOC_PARTIAL | ASSOC_FRONTAL }, - { ANIM_STD_SPINFORWARD_RIGHT, ASSOC_PARTIAL | ASSOC_FRONTAL }, + { ANIM_STD_SPINFORWARD_LEFT, ASSOC_PARTIAL | ASSOC_FRONTAL }, + { ANIM_STD_SPINFORWARD_RIGHT, ASSOC_PARTIAL | ASSOC_FRONTAL }, { ANIM_STD_HIGHIMPACT_FRONT, ASSOC_PARTIAL }, { ANIM_STD_HIGHIMPACT_LEFT, ASSOC_PARTIAL }, - { ANIM_STD_HIGHIMPACT_BACK, ASSOC_PARTIAL | ASSOC_FRONTAL }, + { ANIM_STD_HIGHIMPACT_BACK, ASSOC_PARTIAL | ASSOC_FRONTAL }, { ANIM_STD_HIGHIMPACT_RIGHT, ASSOC_PARTIAL }, - { ANIM_STD_HITBYGUN_FRONT, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL | ASSOC_NOWALK }, - { ANIM_STD_HITBYGUN_LEFT, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL | ASSOC_NOWALK }, - { ANIM_STD_HITBYGUN_BACK, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL | ASSOC_NOWALK }, - { ANIM_STD_HITBYGUN_RIGHT, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL | ASSOC_NOWALK }, + { ANIM_STD_HITBYGUN_FRONT, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL | ASSOC_NOWALK }, + { ANIM_STD_HITBYGUN_LEFT, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL | ASSOC_NOWALK }, + { ANIM_STD_HITBYGUN_BACK, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL | ASSOC_NOWALK }, + { ANIM_STD_HITBYGUN_RIGHT, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL | ASSOC_NOWALK }, { ANIM_STD_HIT_FRONT, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL | ASSOC_HAS_TRANSLATION }, { ANIM_STD_HIT_LEFT, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL }, { ANIM_STD_HIT_BACK, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL | ASSOC_HAS_TRANSLATION }, { ANIM_STD_HIT_RIGHT, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL }, { ANIM_STD_HIT_FLOOR, ASSOC_DELETEFADEDOUT | ASSOC_PARTIAL }, -#if GTA_VERSION <= GTA3_PS2_160 - { ANIM_STD_HIT_BODY, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL }, -#endif { ANIM_STD_HIT_BODYBLOW, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL | ASSOC_HAS_TRANSLATION }, { ANIM_STD_HIT_CHEST, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL | ASSOC_HAS_TRANSLATION }, { ANIM_STD_HIT_HEAD, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL | ASSOC_HAS_TRANSLATION }, { ANIM_STD_HIT_WALK, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL | ASSOC_HAS_TRANSLATION }, { ANIM_STD_HIT_WALL, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL | ASSOC_HAS_TRANSLATION }, - { ANIM_STD_HIT_FLOOR_FRONT, ASSOC_DELETEFADEDOUT | ASSOC_PARTIAL | ASSOC_FRONTAL }, + { ANIM_STD_HIT_FLOOR_FRONT, ASSOC_DELETEFADEDOUT | ASSOC_PARTIAL | ASSOC_FRONTAL }, { ANIM_STD_HIT_BEHIND, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL }, - { ANIM_STD_PUNCH, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL }, - { ANIM_STD_KICKGROUND, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL }, - { ANIM_STD_WEAPON_BAT_H, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL }, - { ANIM_STD_WEAPON_BAT_V, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL }, - { ANIM_STD_WEAPON_HGUN_BODY, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL | ASSOC_NOWALK }, - { ANIM_STD_WEAPON_AK_BODY, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL }, - { ANIM_STD_WEAPON_PUMP, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL }, - { ANIM_STD_WEAPON_SNIPER, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL }, - { ANIM_STD_WEAPON_THROW, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL }, - { ANIM_STD_THROW_UNDER, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL }, - { ANIM_STD_START_THROW, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL }, - { ANIM_STD_DETONATE, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL | ASSOC_NOWALK }, - { ANIM_STD_HGUN_RELOAD, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL | ASSOC_NOWALK }, - { ANIM_STD_AK_RELOAD, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL | ASSOC_NOWALK }, -#ifdef PC_PLAYER_CONTROLS - // maybe wrong define, but unused anyway - { ANIM_FPS_PUNCH, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL }, - { ANIM_FPS_BAT, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL }, - { ANIM_FPS_UZI, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL }, - { ANIM_FPS_PUMP, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL }, - { ANIM_FPS_AK, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL }, - { ANIM_FPS_M16, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL }, - { ANIM_FPS_ROCKET, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL }, -#endif { ANIM_STD_FIGHT_IDLE, ASSOC_REPEAT }, { ANIM_STD_FIGHT_2IDLE, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL }, { ANIM_STD_FIGHT_SHUFFLE_F, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL | ASSOC_HAS_TRANSLATION }, @@ -102,7 +76,18 @@ AnimAssocDesc aStdAnimDescs[] = { { ANIM_STD_FIGHT_PUNCH, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL }, { ANIM_STD_FIGHT_ROUNDHOUSE, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL | ASSOC_HAS_TRANSLATION }, { ANIM_STD_FIGHT_LONGKICK, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL | ASSOC_HAS_TRANSLATION }, - { ANIM_STD_PARTIAL_PUNCH, ASSOC_DELETEFADEDOUT | ASSOC_PARTIAL | ASSOC_NOWALK }, + { ANIM_STD_PARTIAL_PUNCH, ASSOC_DELETEFADEDOUT | ASSOC_PARTIAL | ASSOC_NOWALK }, + { ANIM_STD_FIGHT_JAB, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL }, + { ANIM_STD_FIGHT_ELBOW_L, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL }, + { ANIM_STD_FIGHT_ELBOW_R, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL }, + { ANIM_STD_FIGHT_BKICK_L, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL }, + { ANIM_STD_FIGHT_BKICK_R, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL }, + { ANIM_STD_DETONATE, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL }, + { ANIM_STD_PUNCH, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL }, + { ANIM_STD_PARTIALPUNCH, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL }, + { ANIM_STD_KICKGROUND, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL }, + { ANIM_STD_THROW_UNDER, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL }, + { ANIM_STD_FIGHT_SHUFFLE_B, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL | ASSOC_HAS_TRANSLATION }, { ANIM_STD_JACKEDCAR_RHS, ASSOC_DELETEFADEDOUT | ASSOC_PARTIAL }, { ANIM_STD_JACKEDCAR_LO_RHS, ASSOC_DELETEFADEDOUT | ASSOC_PARTIAL }, { ANIM_STD_JACKEDCAR_LHS, ASSOC_DELETEFADEDOUT | ASSOC_PARTIAL }, @@ -121,6 +106,7 @@ AnimAssocDesc aStdAnimDescs[] = { { ANIM_STD_CAR_CLOSE_DOOR_LO_LHS, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL }, { ANIM_STD_CAR_CLOSE_DOOR_ROLLING_LHS, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL }, { ANIM_STD_CAR_CLOSE_DOOR_ROLLING_LO_LHS, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL }, + { ANIM_STD_CAR_JUMP_IN_LO_LHS, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL }, { ANIM_STD_GETOUT_LHS, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL }, { ANIM_STD_GETOUT_LO_LHS, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL }, { ANIM_STD_CAR_CLOSE_LHS, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL }, @@ -136,39 +122,41 @@ AnimAssocDesc aStdAnimDescs[] = { { ANIM_STD_CAR_CLOSE_DOOR_LO_RHS, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL }, { ANIM_STD_CAR_SHUFFLE_RHS, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL }, { ANIM_STD_CAR_SHUFFLE_LO_RHS, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL }, - { ANIM_STD_CAR_SIT, ASSOC_DELETEFADEDOUT }, - { ANIM_STD_CAR_SIT_LO, ASSOC_DELETEFADEDOUT }, - { ANIM_STD_CAR_SIT_P, ASSOC_DELETEFADEDOUT }, - { ANIM_STD_CAR_SIT_P_LO, ASSOC_DELETEFADEDOUT }, - { ANIM_STD_CAR_DRIVE_LEFT, ASSOC_DELETEFADEDOUT | ASSOC_PARTIAL }, - { ANIM_STD_CAR_DRIVE_RIGHT, ASSOC_DELETEFADEDOUT | ASSOC_PARTIAL }, - { ANIM_STD_CAR_DRIVE_LEFT_LO, ASSOC_DELETEFADEDOUT | ASSOC_PARTIAL }, - { ANIM_STD_CAR_DRIVE_RIGHT_LO, ASSOC_DELETEFADEDOUT | ASSOC_PARTIAL }, - { ANIM_STD_CAR_DRIVEBY_LEFT, ASSOC_DELETEFADEDOUT | ASSOC_PARTIAL }, - { ANIM_STD_CAR_DRIVEBY_RIGHT, ASSOC_DELETEFADEDOUT | ASSOC_PARTIAL }, - { ANIM_STD_CAR_LOOKBEHIND, ASSOC_DELETEFADEDOUT | ASSOC_PARTIAL }, - { ANIM_STD_BOAT_DRIVE, ASSOC_DELETEFADEDOUT }, + { ANIM_STD_CAR_SIT, ASSOC_DELETEFADEDOUT}, + { ANIM_STD_CAR_SIT_LO, ASSOC_DELETEFADEDOUT}, + { ANIM_STD_CAR_SIT_P, ASSOC_DELETEFADEDOUT}, + { ANIM_STD_CAR_SIT_P_LO, ASSOC_DELETEFADEDOUT}, + { ANIM_STD_CAR_DRIVE_LEFT, ASSOC_DELETEFADEDOUT | ASSOC_PARTIAL | ASSOC_DRIVING }, + { ANIM_STD_CAR_DRIVE_RIGHT, ASSOC_DELETEFADEDOUT | ASSOC_PARTIAL | ASSOC_DRIVING }, + { ANIM_STD_CAR_DRIVE_LEFT_LO, ASSOC_DELETEFADEDOUT | ASSOC_PARTIAL | ASSOC_DRIVING }, + { ANIM_STD_CAR_DRIVE_RIGHT_LO, ASSOC_DELETEFADEDOUT | ASSOC_PARTIAL | ASSOC_DRIVING }, + { ANIM_STD_CAR_DRIVEBY_LEFT, ASSOC_DELETEFADEDOUT | ASSOC_PARTIAL | ASSOC_DRIVING }, + { ANIM_STD_CAR_DRIVEBY_RIGHT, ASSOC_DELETEFADEDOUT | ASSOC_PARTIAL | ASSOC_DRIVING }, + { ANIM_STD_CAR_DRIVEBY_LEFT_LO, ASSOC_DELETEFADEDOUT | ASSOC_PARTIAL | ASSOC_DRIVING }, + { ANIM_STD_CAR_DRIVEBY_RIGHT_LO, ASSOC_DELETEFADEDOUT | ASSOC_PARTIAL | ASSOC_DRIVING }, + { ANIM_STD_CAR_LOOKBEHIND, ASSOC_DELETEFADEDOUT | ASSOC_PARTIAL | ASSOC_DRIVING }, + { ANIM_STD_BOAT_DRIVE, ASSOC_DELETEFADEDOUT | ASSOC_DRIVING }, + { ANIM_STD_BOAT_DRIVE_LEFT, ASSOC_DELETEFADEDOUT | ASSOC_PARTIAL | ASSOC_DRIVING }, + { ANIM_STD_BOAT_DRIVE_RIGHT, ASSOC_DELETEFADEDOUT | ASSOC_PARTIAL | ASSOC_DRIVING }, + { ANIM_STD_BOAT_LOOKBEHIND, ASSOC_DELETEFADEDOUT | ASSOC_PARTIAL | ASSOC_DRIVING }, + { ANIM_STD_BIKE_PICKUP_LHS, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL }, + { ANIM_STD_BIKE_PICKUP_RHS, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL }, + { ANIM_STD_BIKE_PULLUP_LHS, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL }, + { ANIM_STD_BIKE_PULLUP_RHS, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL }, + { ANIM_STD_BIKE_ELBOW_LHS, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL }, + { ANIM_STD_BIKE_ELBOW_RHS, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL }, + { ANIM_STD_BIKE_FALLOFF, ASSOC_DELETEFADEDOUT | ASSOC_PARTIAL | ASSOC_HAS_TRANSLATION }, + { ANIM_STD_BIKE_FALLBACK, ASSOC_DELETEFADEDOUT | ASSOC_PARTIAL | ASSOC_HAS_TRANSLATION }, { ANIM_STD_GETOUT_RHS, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL }, { ANIM_STD_GETOUT_LO_RHS, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL }, { ANIM_STD_CAR_CLOSE_RHS, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL }, { ANIM_STD_CAR_HOOKERTALK, ASSOC_REPEAT | ASSOC_PARTIAL }, - { ANIM_STD_COACH_OPEN_LHS, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL }, - { ANIM_STD_COACH_OPEN_RHS, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL }, - { ANIM_STD_COACH_GET_IN_LHS, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL }, - { ANIM_STD_COACH_GET_IN_RHS, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL }, - { ANIM_STD_COACH_GET_OUT_LHS, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL }, { ANIM_STD_TRAIN_GETIN, ASSOC_PARTIAL }, { ANIM_STD_TRAIN_GETOUT, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL }, { ANIM_STD_CRAWLOUT_LHS, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL }, { ANIM_STD_CRAWLOUT_RHS, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL }, - { ANIM_STD_VAN_OPEN_DOOR_REAR_LHS, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL }, - { ANIM_STD_VAN_GET_IN_REAR_LHS, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL }, - { ANIM_STD_VAN_CLOSE_DOOR_REAR_LHS, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL }, - { ANIM_STD_VAN_GET_OUT_REAR_LHS, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL }, - { ANIM_STD_VAN_OPEN_DOOR_REAR_RHS, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL }, - { ANIM_STD_VAN_GET_IN_REAR_RHS, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL }, - { ANIM_STD_VAN_CLOSE_DOOR_REAR_RHS, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL }, - { ANIM_STD_VAN_GET_OUT_REAR_RHS, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL }, + { ANIM_STD_ROLLOUT_LHS, ASSOC_DELETEFADEDOUT | ASSOC_PARTIAL | ASSOC_HAS_TRANSLATION | ASSOC_HAS_X_TRANSLATION }, + { ANIM_STD_ROLLOUT_RHS, ASSOC_DELETEFADEDOUT | ASSOC_PARTIAL | ASSOC_HAS_TRANSLATION | ASSOC_HAS_X_TRANSLATION }, { ANIM_STD_GET_UP, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL | ASSOC_HAS_TRANSLATION }, { ANIM_STD_GET_UP_LEFT, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL | ASSOC_HAS_TRANSLATION }, { ANIM_STD_GET_UP_RIGHT, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL | ASSOC_HAS_TRANSLATION }, @@ -180,35 +168,133 @@ AnimAssocDesc aStdAnimDescs[] = { { ANIM_STD_FALL_GLIDE, ASSOC_DELETEFADEDOUT | ASSOC_PARTIAL }, { ANIM_STD_FALL_LAND, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL | ASSOC_HAS_TRANSLATION }, { ANIM_STD_FALL_COLLAPSE, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL | ASSOC_HAS_TRANSLATION }, + { ANIM_STD_FALL_ONBACK, ASSOC_DELETEFADEDOUT | ASSOC_PARTIAL }, + { ANIM_STD_FALL_ONFRONT, ASSOC_DELETEFADEDOUT | ASSOC_PARTIAL | ASSOC_FRONTAL }, { ANIM_STD_EVADE_STEP, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL | ASSOC_HAS_TRANSLATION }, - { ANIM_STD_EVADE_DIVE, ASSOC_PARTIAL | ASSOC_HAS_TRANSLATION | ASSOC_FRONTAL }, - { ANIM_STD_XPRESS_SCRATCH, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL | ASSOC_IDLE }, + { ANIM_STD_EVADE_DIVE, ASSOC_PARTIAL | ASSOC_HAS_TRANSLATION | ASSOC_FRONTAL }, + { ANIM_STD_XPRESS_SCRATCH, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL | ASSOC_IDLE }, { ANIM_STD_ROADCROSS, ASSOC_REPEAT | ASSOC_PARTIAL }, { ANIM_STD_TURN180, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL }, { ANIM_STD_ARREST, ASSOC_PARTIAL | ASSOC_HAS_TRANSLATION }, { ANIM_STD_DROWN, ASSOC_PARTIAL }, - { ANIM_MEDIC_CPR, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL }, { ANIM_STD_DUCK_DOWN, ASSOC_DELETEFADEDOUT | ASSOC_PARTIAL }, { ANIM_STD_DUCK_LOW, ASSOC_DELETEFADEDOUT | ASSOC_PARTIAL }, + { ANIM_STD_DUCK_WEAPON, ASSOC_DELETEFADEDOUT | ASSOC_PARTIAL }, { ANIM_STD_RBLOCK_SHOOT, ASSOC_DELETEFADEDOUT | ASSOC_PARTIAL }, - { ANIM_STD_THROW_UNDER2, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL }, { ANIM_STD_HANDSUP, ASSOC_PARTIAL | ASSOC_HAS_TRANSLATION }, { ANIM_STD_HANDSCOWER, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL | ASSOC_HAS_TRANSLATION }, - { ANIM_STD_PARTIAL_FUCKU, ASSOC_DELETEFADEDOUT | ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL | ASSOC_NOWALK }, - { ANIM_STD_PHONE_IN, ASSOC_PARTIAL }, + { ANIM_STD_PARTIAL_FUCKU, ASSOC_DELETEFADEDOUT | ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL | ASSOC_NOWALK }, + { ANIM_STD_PHONE_IN, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL }, { ANIM_STD_PHONE_OUT, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL }, { ANIM_STD_PHONE_TALK, ASSOC_REPEAT | ASSOC_DELETEFADEDOUT | ASSOC_PARTIAL }, + { ANIM_STD_SEAT_DOWN, ASSOC_DELETEFADEDOUT | ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL }, + { ANIM_STD_SEAT_UP, ASSOC_DELETEFADEDOUT | ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL }, + { ANIM_STD_SEAT_IDLE, ASSOC_REPEAT | ASSOC_DELETEFADEDOUT | ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL }, + { ANIM_STD_SEAT_RVRS, ASSOC_DELETEFADEDOUT | ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL }, + { ANIM_STD_ATM, ASSOC_DELETEFADEDOUT | ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL }, + { ANIM_STD_ABSEIL, ASSOC_DELETEFADEDOUT | ASSOC_PARTIAL }, +}; +AnimAssocDesc aVanAnimDescs[] = { + { ANIM_STD_VAN_OPEN_DOOR_REAR_LHS, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL }, + { ANIM_STD_VAN_GET_IN_REAR_LHS, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL }, + { ANIM_STD_VAN_CLOSE_DOOR_REAR_LHS, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL }, + { ANIM_STD_VAN_GET_OUT_REAR_LHS, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL }, + { ANIM_STD_VAN_OPEN_DOOR_REAR_RHS, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL }, + { ANIM_STD_VAN_GET_IN_REAR_RHS, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL }, + { ANIM_STD_VAN_CLOSE_DOOR_REAR_RHS, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL }, + { ANIM_STD_VAN_GET_OUT_REAR_RHS, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL }, +}; +AnimAssocDesc aCoachAnimDescs[] = { + { ANIM_STD_COACH_OPEN_LHS, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL }, + { ANIM_STD_COACH_OPEN_RHS, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL }, + { ANIM_STD_COACH_GET_IN_LHS, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL }, + { ANIM_STD_COACH_GET_IN_RHS, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL }, + { ANIM_STD_COACH_GET_OUT_LHS, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL }, +}; +AnimAssocDesc aBikeAnimDescs[] = { + { ANIM_BIKE_RIDE, ASSOC_DELETEFADEDOUT}, + { ANIM_BIKE_READY, ASSOC_DELETEFADEDOUT | ASSOC_PARTIAL | ASSOC_DRIVING }, + { ANIM_BIKE_LEFT, ASSOC_PARTIAL | ASSOC_DRIVING }, + { ANIM_BIKE_RIGHT, ASSOC_PARTIAL | ASSOC_DRIVING }, + { ANIM_BIKE_LEANB, ASSOC_PARTIAL | ASSOC_DRIVING }, + { ANIM_BIKE_LEANF, ASSOC_PARTIAL | ASSOC_DRIVING }, + { ANIM_BIKE_WALKBACK, ASSOC_REPEAT | ASSOC_DELETEFADEDOUT | ASSOC_PARTIAL | ASSOC_DRIVING }, + { ANIM_BIKE_JUMPON_LHS, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL }, + { ANIM_BIKE_JUMPON_RHS, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL }, + { ANIM_BIKE_KICK, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL }, + { ANIM_BIKE_HIT, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL }, + { ANIM_BIKE_GETOFF_LHS, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL }, + { ANIM_BIKE_GETOFF_RHS, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL }, + { ANIM_BIKE_GETOFF_BACK, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL | ASSOC_HAS_TRANSLATION }, + { ANIM_BIKE_DRIVEBY_LHS, ASSOC_DELETEFADEDOUT | ASSOC_PARTIAL | ASSOC_DRIVING }, + { ANIM_BIKE_DRIVEBY_RHS, ASSOC_DELETEFADEDOUT | ASSOC_PARTIAL | ASSOC_DRIVING }, + { ANIM_BIKE_DRIVEBY_FORWARD, ASSOC_DELETEFADEDOUT | ASSOC_PARTIAL | ASSOC_DRIVING }, + { ANIM_BIKE_RIDE_P, ASSOC_DELETEFADEDOUT | ASSOC_DRIVING }, +}; +AnimAssocDesc aMeleeAnimDescs[] = { + { ANIM_MELEE_ATTACK, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL }, + { ANIM_MELEE_ATTACK_2ND, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL }, + { ANIM_MELEE_ATTACK_START, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL | ASSOC_NOWALK }, + { ANIM_MELEE_IDLE_FIGHTMODE, ASSOC_REPEAT }, + { ANIM_MELEE_ATTACK_FINISH, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL | ASSOC_HAS_TRANSLATION }, +}; +AnimAssocDesc aSwingAnimDescs[] = { + { ANIM_MELEE_ATTACK, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL }, + { ANIM_MELEE_ATTACK_2ND, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL }, + { ANIM_MELEE_ATTACK_START, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL }, + { ANIM_MELEE_IDLE_FIGHTMODE, ASSOC_REPEAT }, + { ANIM_MELEE_ATTACK_FINISH, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL }, +}; +AnimAssocDesc aWeaponAnimDescs[] = { + { ANIM_WEAPON_FIRE, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL }, + { ANIM_WEAPON_CROUCHFIRE, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL }, + { ANIM_WEAPON_RELOAD, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL }, + { ANIM_WEAPON_CROUCHRELOAD, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL }, + { ANIM_WEAPON_FIRE_3RD, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL }, +}; +AnimAssocDesc aMedicAnimDescs[] = { + { ANIM_MEDIC_CPR, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL }, +}; +AnimAssocDesc aSunbatheAnimDescs[] = { + { ANIM_SUNBATHE_IDLE, ASSOC_REPEAT | ASSOC_PARTIAL }, + { ANIM_SUNBATHE_DOWN, ASSOC_REPEAT | ASSOC_PARTIAL | ASSOC_HAS_TRANSLATION | ASSOC_HAS_X_TRANSLATION }, + { ANIM_SUNBATHE_UP, ASSOC_REPEAT | ASSOC_PARTIAL | ASSOC_HAS_TRANSLATION | ASSOC_HAS_X_TRANSLATION }, + { ANIM_SUNBATHE_ESCAPE, ASSOC_REPEAT | ASSOC_PARTIAL | ASSOC_HAS_TRANSLATION | ASSOC_HAS_X_TRANSLATION }, +}; +AnimAssocDesc aPlayerIdleAnimDescs[] = { + { ANIM_PLAYER_IDLE1, ASSOC_DELETEFADEDOUT | ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL }, + { ANIM_PLAYER_IDLE2, ASSOC_DELETEFADEDOUT | ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL }, + { ANIM_PLAYER_IDLE3, ASSOC_DELETEFADEDOUT | ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL }, + { ANIM_PLAYER_IDLE4, ASSOC_DELETEFADEDOUT | ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL }, +}; +AnimAssocDesc aRiotAnimDescs[] = { + { ANIM_RIOT_ANGRY, ASSOC_REPEAT | ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL }, + { ANIM_RIOT_ANGRY_B, ASSOC_REPEAT | ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL }, + { ANIM_RIOT_CHANT, ASSOC_REPEAT | ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL }, + { ANIM_RIOT_PUNCHES, ASSOC_REPEAT | ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL }, + { ANIM_RIOT_SHOUT, ASSOC_REPEAT | ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL }, + { ANIM_RIOT_CHALLENGE, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL }, + { ANIM_RIOT_FUCKYOU, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL }, +}; +AnimAssocDesc aStripAnimDescs[] = { + { ANIM_STRIP_A, ASSOC_REPEAT | ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL }, + { ANIM_STRIP_B, ASSOC_REPEAT | ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL }, + { ANIM_STRIP_C, ASSOC_REPEAT | ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL }, + { ANIM_STRIP_D, ASSOC_REPEAT | ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL }, + { ANIM_STRIP_E, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL }, + { ANIM_STRIP_F, ASSOC_REPEAT | ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL }, + { ANIM_STRIP_G, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL }, }; #ifdef PC_PLAYER_CONTROLS AnimAssocDesc aStdAnimDescsSide[] = { - { ANIM_STD_WALK, ASSOC_REPEAT | ASSOC_MOVEMENT | ASSOC_HAS_TRANSLATION | ASSOC_WALK | ASSOC_HAS_X_TRANSLATION }, - { ANIM_STD_RUN, ASSOC_REPEAT | ASSOC_MOVEMENT | ASSOC_HAS_TRANSLATION | ASSOC_WALK | ASSOC_HAS_X_TRANSLATION }, - { ANIM_STD_RUNFAST, ASSOC_REPEAT | ASSOC_MOVEMENT | ASSOC_HAS_TRANSLATION | ASSOC_WALK | ASSOC_HAS_X_TRANSLATION }, + { ANIM_STD_WALK, ASSOC_REPEAT | ASSOC_MOVEMENT | ASSOC_HAS_TRANSLATION | ASSOC_HAS_X_TRANSLATION | ASSOC_WALK }, + { ANIM_STD_RUN, ASSOC_REPEAT | ASSOC_MOVEMENT | ASSOC_HAS_TRANSLATION | ASSOC_HAS_X_TRANSLATION | ASSOC_WALK }, + { ANIM_STD_RUNFAST, ASSOC_REPEAT | ASSOC_MOVEMENT | ASSOC_HAS_TRANSLATION | ASSOC_HAS_X_TRANSLATION | ASSOC_WALK }, { ANIM_STD_IDLE, ASSOC_REPEAT }, { ANIM_STD_STARTWALK, ASSOC_HAS_TRANSLATION | ASSOC_HAS_X_TRANSLATION }, }; #endif -char const *aStdAnimations[] = { +char const* aStdAnimations[] = { "walk_civi", "run_civi", "sprint_panic", @@ -216,7 +302,7 @@ char const *aStdAnimations[] = { "walk_start", "run_stop", "run_stopR", - "idle_cam", + "idle_hbhb", "idle_hbhb", "idle_tired", "idle_armed", @@ -247,9 +333,6 @@ char const *aStdAnimations[] = { "HIT_back", "HIT_R", "FLOOR_hit", -#if GTA_VERSION <= GTA3_PS2_160 - "HIT_body", -#endif "HIT_bodyblow", "HIT_chest", "HIT_head", @@ -257,30 +340,6 @@ char const *aStdAnimations[] = { "HIT_wall", "FLOOR_hit_f", "HIT_behind", - "punchR", - "KICK_floor", - "WEAPON_bat_h", - "WEAPON_bat_v", - "WEAPON_hgun_body", - "WEAPON_AK_body", - "WEAPON_pump", - "WEAPON_sniper", - "WEAPON_throw", - "WEAPON_throwu", - "WEAPON_start_throw", - "bomber", - "WEAPON_hgun_rload", - "WEAPON_AK_rload", -#ifdef PC_PLAYER_CONTROLS - // maybe wrong define, but unused anyway - "FPS_PUNCH", - "FPS_BAT", - "FPS_UZI", - "FPS_PUMP", - "FPS_AK", - "FPS_M16", - "FPS_ROCKET", -#endif "FIGHTIDLE", "FIGHT2IDLE", "FIGHTsh_F", @@ -293,6 +352,17 @@ char const *aStdAnimations[] = { "FIGHTrndhse", "FIGHTlngkck", "FIGHTppunch", + "FIGHTjab", + "FIGHTelbowL", + "FIGHTelbowR", + "FIGHTbkickL", + "FIGHTbkickR", + "bomber", + "punchR", + "FIGHTppunch", + "KICK_floor", + "WEAPON_throwu", + "FIGHTsh_back", "car_jackedRHS", "car_LjackedRHS", "car_jackedLHS", @@ -311,6 +381,7 @@ char const *aStdAnimations[] = { "CAR_closedoorL_LHS", "CAR_rolldoor", "CAR_rolldoorLO", + "CAR_jumpin_LHS", "CAR_getout_LHS", "CAR_getoutL_LHS", "CAR_close_LHS", @@ -336,29 +407,31 @@ char const *aStdAnimations[] = { "Drive_LO_R", "Driveby_L", "Driveby_R", + "DrivebyL_L", + "DrivebyL_R", "CAR_LB", "DRIVE_BOAT", + "DRIVE_BOAT_L", + "DRIVE_BOAT_R", + "DRIVE_BOAT_back", + "BIKE_pickupR", + "BIKE_pickupL", + "BIKE_pullupR", + "BIKE_pullupL", + "BIKE_elbowR", + "BIKE_elbowL", + "BIKE_fall_off", + "BIKE_fallR", "CAR_getout_RHS", "CAR_getoutL_RHS", "CAR_close_RHS", "car_hookertalk", - "COACH_opnL", - "COACH_opnR", - "COACH_inL", - "COACH_inR", - "COACH_outL", - "TRAIN_getin", - "TRAIN_getout", + "idle_stance", + "idle_stance", "CAR_crawloutRHS", "CAR_crawloutRHS", - "VAN_openL", - "VAN_getinL", - "VAN_closeL", - "VAN_getoutL", - "VAN_open", - "VAN_getin", - "VAN_close", - "VAN_getout", + "CAR_rollout_LHS", + "CAR_rollout_LHS", "Getup", "Getup", "Getup", @@ -370,6 +443,8 @@ char const *aStdAnimations[] = { "FALL_glide", "FALL_land", "FALL_collapse", + "FALL_back", + "FALL_front", "EV_step", "EV_dive", "XPRESSscratch", @@ -377,197 +452,507 @@ char const *aStdAnimations[] = { "TURN_180", "ARRESTgun", "DROWN", - "CPR", "DUCK_down", "DUCK_low", + "WEAPON_crouch", "RBLOCK_Cshoot", - "WEAPON_throwu", "handsup", "handsCOWER", "FUCKU", "PHONE_in", "PHONE_out", "PHONE_talk", + "SEAT_down", + "SEAT_up", + "SEAT_idle", + "SEAT_down", + "ATM", + "abseil", +}; +char const* aVanAnimations[] = { + "VAN_openL", + "VAN_getinL", + "VAN_closeL", + "VAN_getoutL", + "VAN_open", + "VAN_getin", + "VAN_close", + "VAN_getout", +}; +char const* aCoachAnimations[] = { + "COACH_opnL", + "COACH_opnL", + "COACH_inL", + "COACH_inL", + "COACH_outL", +}; +char const* aBikesAnimations[] = { + "BIKEs_Ride", + "BIKEs_Still", + "BIKEs_Left", + "BIKEs_Right", + "BIKEs_Back", + "BIKEs_Fwd", + "BIKEs_pushes", + "BIKEs_jumponR", + "BIKEs_jumponL", + "BIKEs_kick", + "BIKEs_hit", + "BIKEs_getoffRHS", + "BIKEs_getoffLHS", + "BIKEs_getoffBACK", + "BIKEs_drivebyLHS", + "BIKEs_drivebyRHS", + "BIKEs_drivebyFT", + "BIKEs_passenger", +}; +char const* aBikevAnimations[] = { + "BIKEv_Ride", + "BIKEv_Still", + "BIKEv_Left", + "BIKEv_Right", + "BIKEv_Back", + "BIKEv_Fwd", + "BIKEv_pushes", + "BIKEv_jumponR", + "BIKEv_jumponL", + "BIKEv_kick", + "BIKEv_hit", + "BIKEv_getoffRHS", + "BIKEv_getoffLHS", + "BIKEv_getoffBACK", + "BIKEv_drivebyLHS", + "BIKEv_drivebyRHS", + "BIKEv_drivebyFT", + "BIKEv_passenger", +}; +char const* aBikehAnimations[] = { + "BIKEh_Ride", + "BIKEh_Still", + "BIKEh_Left", + "BIKEh_Right", + "BIKEh_Back", + "BIKEh_Fwd", + "BIKEh_pushes", + "BIKEh_jumponR", + "BIKEh_jumponL", + "BIKEh_kick", + "BIKEh_hit", + "BIKEh_getoffRHS", + "BIKEh_getoffLHS", + "BIKEh_getoffBACK", + "BIKEh_drivebyLHS", + "BIKEh_drivebyRHS", + "BIKEh_drivebyFT", + "BIKEh_passenger", +}; +char const* aBikedAnimations[] = { + "BIKEd_Ride", + "BIKEd_Still", + "BIKEd_Left", + "BIKEd_Right", + "BIKEd_Back", + "BIKEd_Fwd", + "BIKEd_pushes", + "BIKEd_jumponR", + "BIKEd_jumponL", + "BIKEd_kick", + "BIKEd_hit", + "BIKEd_getoffRHS", + "BIKEd_getoffLHS", + "BIKEd_getoffBACK", + "BIKEd_drivebyLHS", + "BIKEd_drivebyRHS", + "BIKEd_drivebyFT", + "BIKEd_passenger", +}; +char const* aUnarmedAnimations[] = { + "punchR", + "KICK_floor", + "FIGHTppunch", +}; +char const* aScrewdriverAnimations[] = { + "FIGHTbodyblow", + "FIGHTbodyblow", + "FIGHTppunch", + "FIGHTIDLE", + "FIGHTbodyblow", +}; +char const* aKnifeAnimations[] = { + "WEAPON_knife_1", + "WEAPON_knife_2", + "knife_part", + "WEAPON_knifeidle", + "WEAPON_knife_3", +}; +char const* aBaseballbatAnimations[] = { + "WEAPON_bat_h", + "WEAPON_bat_v", + "BAT_PART", + "WEAPON_bat_h", + "WEAPON_golfclub", +}; +char const* aGolfclubAnimations[] = { + "WEAPON_bat_h", + "WEAPON_golfclub", + "BAT_PART", + "WEAPON_bat_h", + "WEAPON_bat_v", +}; +char const* aChainsawAnimations[] = { + "WEAPON_csaw", + "WEAPON_csawlo", + "csaw_part", +}; +char const* aPythonAnimations[] = { + "python_fire", + "python_crouchfire", + "python_reload", + "python_crouchreload", +}; +char const* aColtAnimations[] = { + "colt45_fire", + "colt45_crouchfire", + "colt45_reload", + "colt45_crouchreload", + "colt45_cop", +}; +char const* aShotgunAnimations[] = { + "shotgun_fire", + "shotgun_crouchfire", +}; +char const* aBuddyAnimations[] = { + "buddy_fire", + "buddy_crouchfire", }; -char const *aPlayerAnimations[] = { +char const* aTecAnimations[] = { + "TEC_fire", + "TEC_crouchfire", + "TEC_reload", + "TEC_crouchreload", +}; +char const* aUziAnimations[] = { + "UZI_fire", + "UZI_crouchfire", + "UZI_reload", + "UZI_crouchreload", +}; +char const* aRifleAnimations[] = { + "RIFLE_fire", + "RIFLE_crouchfire", + "RIFLE_load", + "RIFLE_crouchload", +}; +char const* aM60Animations[] = { + "M60_fire", + "M60_fire", + "M60_reload", +}; +char const* aSniperAnimations[] = { + "WEAPON_sniper", +}; +char const* aThrowAnimations[] = { + "WEAPON_throw", + "WEAPON_throwu", + "WEAPON_start_throw", +}; +char const* aFlamethrowerAnimations[] = { + "FLAME_fire", +}; +char const* aMedicAnimations[] = { + "CPR", +}; +char const* aSunbatheAnimations[] = { + "bather", + "batherdown", + "batherup", + "batherscape", +}; +char const* aPlayerIdleAnimations[] = { + "stretch", + "time", + "shldr", + "strleg", +}; +char const* aRiotAnimations[] = { + "riot_angry", + "riot_angry_b", + "riot_chant", + "riot_punches", + "riot_shout", + "riot_challenge", + "riot_fuku", +}; +char const* aStripAnimations[] = { + "strip_A", + "strip_B", + "strip_C", + "strip_D", + "strip_E", + "strip_F", + "strip_G", +}; +char const* aLanceAnimations[] = { + "lance", +}; +char const* aPlayerAnimations[] = { "walk_player", "run_player", "SPRINT_civi", "IDLE_STANCE", "walk_start", }; -char const *aPlayerWithRocketAnimations[] = { +char const* aPlayerWithRocketAnimations[] = { "walk_rocket", "run_rocket", "run_rocket", "idle_rocket", "walk_start_rocket", }; -char const *aPlayer1ArmedAnimations[] = { +char const* aPlayer1ArmedAnimations[] = { "walk_player", "run_1armed", "SPRINT_civi", "IDLE_STANCE", "walk_start", }; -char const *aPlayer2ArmedAnimations[] = { - "walk_player", +char const* aPlayer2ArmedAnimations[] = { + "walk_armed", "run_armed", "run_armed", - "idle_stance", - "walk_start", + "idle_armed", + "walk_start_armed", }; -char const *aPlayerBBBatAnimations[] = { +char const* aPlayerBBBatAnimations[] = { "walk_player", "run_player", "run_player", "IDLE_STANCE", "walk_start", }; -char const *aShuffleAnimations[] = { +char const* aPlayerChainsawAnimations[] = { + "walk_csaw", + "run_csaw", + "run_csaw", + "IDLE_csaw", + "walk_start_csaw", +}; +char const* aShuffleAnimations[] = { "WALK_shuffle", "RUN_civi", "SPRINT_civi", "IDLE_STANCE", }; -char const *aOldAnimations[] = { +char const* aOldAnimations[] = { "walk_old", "run_civi", "sprint_civi", "idle_stance", }; -char const *aGang1Animations[] = { +char const* aGang1Animations[] = { "walk_gang1", "run_gang1", "sprint_civi", "idle_stance", }; -char const *aGang2Animations[] = { +char const* aGang2Animations[] = { "walk_gang2", "run_gang1", "sprint_civi", "idle_stance", }; -char const *aFatAnimations[] = { +char const* aFatAnimations[] = { "walk_fat", "run_civi", "woman_runpanic", "idle_stance", }; -char const *aOldFatAnimations[] = { +char const* aOldFatAnimations[] = { "walk_fatold", "run_fatold", "woman_runpanic", "idle_stance", }; -char const *aStdWomanAnimations[] = { +char const* aJoggerAnimations[] = { + "JOG_maleA", + "run_civi", + "sprint_civi", + "idle_stance", +}; +char const* aStdWomanAnimations[] = { "woman_walknorm", "woman_run", "woman_runpanic", "woman_idlestance", }; -char const *aWomanShopAnimations[] = { +char const* aWomanShopAnimations[] = { "woman_walkshop", "woman_run", "woman_run", "woman_idlestance", }; -char const *aBusyWomanAnimations[] = { +char const* aBusyWomanAnimations[] = { "woman_walkbusy", "woman_run", "woman_runpanic", "woman_idlestance", }; -char const *aSexyWomanAnimations[] = { +char const* aSexyWomanAnimations[] = { "woman_walksexy", "woman_run", "woman_runpanic", "woman_idlestance", }; -char const *aOldWomanAnimations[] = { +char const* aFatWomanAnimations[] = { + "walk_fat", + "woman_run", + "woman_runpanic", + "woman_idlestance", +}; +char const* aOldWomanAnimations[] = { "woman_walkold", "woman_run", "woman_runpanic", "woman_idlestance", }; -char const *aFatWomanAnimations[] = { - "walk_fat", +char const* aJoggerWomanAnimations[] = { + "JOG_maleB", "woman_run", "woman_runpanic", "woman_idlestance", }; -char const *aPanicChunkyAnimations[] = { +char const* aPanicChunkyAnimations[] = { "run_fatold", "woman_runpanic", "woman_runpanic", "idle_stance", }; +char const* aSkateAnimations[] = { + "skate_run", + "skate_sprint", + "skate_sprint", + "skate_idle", +}; #ifdef PC_PLAYER_CONTROLS -char const *aPlayerStrafeBackAnimations[] = { - "walk_player_back", - "run_player_back", - "run_player_back", +char const* aPlayerStrafeBackAnimations[] = { + "walk_back", + "run_back", + "run_back", "IDLE_STANCE", "walk_start_back", }; -char const *aPlayerStrafeLeftAnimations[] = { - "walk_player_left", +char const* aPlayerStrafeLeftAnimations[] = { + "walk_left", "run_left", "run_left", "IDLE_STANCE", "walk_start_left", }; -char const *aPlayerStrafeRightAnimations[] = { - "walk_player_right", +char const* aPlayerStrafeRightAnimations[] = { + "walk_right", "run_right", "run_right", "IDLE_STANCE", "walk_start_right", }; -char const *aRocketStrafeBackAnimations[] = { +char const* aRocketStrafeBackAnimations[] = { "walk_rocket_back", "run_rocket_back", "run_rocket_back", "idle_rocket", "walkst_rocket_back", }; -char const *aRocketStrafeLeftAnimations[] = { +char const* aRocketStrafeLeftAnimations[] = { "walk_rocket_left", "run_rocket_left", "run_rocket_left", "idle_rocket", "walkst_rocket_left", }; -char const *aRocketStrafeRightAnimations[] = { +char const* aRocketStrafeRightAnimations[] = { "walk_rocket_right", "run_rocket_right", "run_rocket_right", "idle_rocket", "walkst_rocket_right", }; +char const* aChainsawStrafeBackAnimations[] = { + "walk_csaw_back", + "run_csaw_back", + "run_csaw_back", + "idle_csaw", + "walkst_csaw_back", +}; +char const* aChainsawStrafeLeftAnimations[] = { + "walk_csaw_left", + "run_csaw_left", + "run_csaw_left", + "idle_csaw", + "walkst_csaw_left", +}; +char const* aChainsawStrafeRightAnimations[] = { + "walk_csaw_right", + "run_csaw_right", + "run_csaw_right", + "idle_csaw", + "walkst_csaw_right", +}; #endif #define awc(a) ARRAY_SIZE(a), a const AnimAssocDefinition CAnimManager::ms_aAnimAssocDefinitions[NUM_ANIM_ASSOC_GROUPS] = { { "man", "ped", MI_COP, awc(aStdAnimations), aStdAnimDescs }, + { "van", "van", MI_COP, awc(aVanAnimations), aVanAnimDescs }, + { "coach", "coach", MI_COP, awc(aCoachAnimations), aCoachAnimDescs }, + { "bikes", "bikes", MI_COP, awc(aBikesAnimations), aBikeAnimDescs }, + { "bikev", "bikev", MI_COP, awc(aBikevAnimations), aBikeAnimDescs }, + { "bikeh", "bikeh", MI_COP, awc(aBikehAnimations), aBikeAnimDescs }, + { "biked", "biked", MI_COP, awc(aBikedAnimations), aBikeAnimDescs }, + { "unarmed", "ped", MI_COP, awc(aUnarmedAnimations), aMeleeAnimDescs }, + { "screwdrv", "ped", MI_COP, awc(aScrewdriverAnimations), aMeleeAnimDescs }, + { "knife", "knife", MI_COP, awc(aKnifeAnimations), aMeleeAnimDescs }, + { "baseball", "baseball", MI_COP, awc(aBaseballbatAnimations), aSwingAnimDescs }, + { "golfclub", "baseball", MI_COP, awc(aGolfclubAnimations), aSwingAnimDescs }, + { "chainsaw", "chainsaw", MI_COP, awc(aChainsawAnimations), aMeleeAnimDescs }, + { "python", "python", MI_COP, awc(aPythonAnimations), aWeaponAnimDescs }, + { "colt45", "colt45", MI_COP, awc(aColtAnimations), aWeaponAnimDescs }, + { "shotgun", "shotgun", MI_COP, awc(aShotgunAnimations), aWeaponAnimDescs }, + { "buddy", "buddy", MI_COP, awc(aBuddyAnimations), aWeaponAnimDescs }, + { "tec", "tec", MI_COP, awc(aTecAnimations), aWeaponAnimDescs }, + { "uzi", "uzi", MI_COP, awc(aUziAnimations), aWeaponAnimDescs }, + { "rifle", "rifle", MI_COP, awc(aRifleAnimations), aWeaponAnimDescs }, + { "m60", "m60", MI_COP, awc(aM60Animations), aWeaponAnimDescs }, + { "sniper", "sniper", MI_COP, awc(aSniperAnimations), aWeaponAnimDescs }, + { "grenade", "grenade", MI_COP, awc(aThrowAnimations), aWeaponAnimDescs }, + { "flame", "flame", MI_COP, awc(aFlamethrowerAnimations), aWeaponAnimDescs }, + { "medic", "medic", MI_COP, awc(aMedicAnimations), aMedicAnimDescs }, + { "sunbathe", "sunbathe", MI_COP, 1, aSunbatheAnimations, aSunbatheAnimDescs }, // NB: not using awc here! + { "playidles", "playidles", MI_COP, awc(aPlayerIdleAnimations), aPlayerIdleAnimDescs }, + { "riot", "riot", MI_COP, awc(aRiotAnimations), aRiotAnimDescs }, + { "strip", "strip", MI_COP, awc(aStripAnimations), aStripAnimDescs }, + { "lance", "lance", MI_COP, awc(aLanceAnimations), aSunbatheAnimDescs }, { "player", "ped", MI_COP, awc(aPlayerAnimations), aStdAnimDescs }, { "playerrocket", "ped", MI_COP, awc(aPlayerWithRocketAnimations), aStdAnimDescs }, { "player1armed", "ped", MI_COP, awc(aPlayer1ArmedAnimations), aStdAnimDescs }, { "player2armed", "ped", MI_COP, awc(aPlayer2ArmedAnimations), aStdAnimDescs }, { "playerBBBat", "ped", MI_COP, awc(aPlayerBBBatAnimations), aStdAnimDescs }, + { "playercsaw", "ped", MI_COP, awc(aPlayerChainsawAnimations), aStdAnimDescs }, { "shuffle", "ped", MI_COP, awc(aShuffleAnimations), aStdAnimDescs }, { "oldman", "ped", MI_COP, awc(aOldAnimations), aStdAnimDescs }, { "gang1", "ped", MI_COP, awc(aGang1Animations), aStdAnimDescs }, { "gang2", "ped", MI_COP, awc(aGang2Animations), aStdAnimDescs }, { "fatman", "ped", MI_COP, awc(aFatAnimations), aStdAnimDescs }, { "oldfatman", "ped", MI_COP, awc(aOldFatAnimations), aStdAnimDescs }, + { "jogger", "ped", MI_COP, awc(aJoggerAnimations), aStdAnimDescs }, { "woman", "ped", MI_COP, awc(aStdWomanAnimations), aStdAnimDescs }, { "shopping", "ped", MI_COP, awc(aWomanShopAnimations), aStdAnimDescs }, { "busywoman", "ped", MI_COP, awc(aBusyWomanAnimations), aStdAnimDescs }, { "sexywoman", "ped", MI_COP, awc(aSexyWomanAnimations), aStdAnimDescs }, - { "oldwoman", "ped", MI_COP, awc(aOldWomanAnimations), aStdAnimDescs }, { "fatwoman", "ped", MI_COP, awc(aFatWomanAnimations), aStdAnimDescs }, + { "oldwoman", "ped", MI_COP, awc(aOldWomanAnimations), aStdAnimDescs }, + { "jogwoman", "ped", MI_COP, awc(aJoggerWomanAnimations), aStdAnimDescs }, { "panicchunky", "ped", MI_COP, awc(aPanicChunkyAnimations), aStdAnimDescs }, + { "skate", "skate", MI_COP, awc(aSkateAnimations), aStdAnimDescs }, #ifdef PC_PLAYER_CONTROLS { "playerback", "ped", MI_COP, awc(aPlayerStrafeBackAnimations), aStdAnimDescs }, { "playerleft", "ped", MI_COP, awc(aPlayerStrafeLeftAnimations), aStdAnimDescsSide }, @@ -575,6 +960,9 @@ const AnimAssocDefinition CAnimManager::ms_aAnimAssocDefinitions[NUM_ANIM_ASSOC_ { "rocketback", "ped", MI_COP, awc(aRocketStrafeBackAnimations), aStdAnimDescs }, { "rocketleft", "ped", MI_COP, awc(aRocketStrafeLeftAnimations), aStdAnimDescsSide }, { "rocketright", "ped", MI_COP, awc(aRocketStrafeRightAnimations), aStdAnimDescsSide }, + { "csawback", "ped", MI_COP, awc(aChainsawStrafeBackAnimations), aStdAnimDescs }, + { "csawleft", "ped", MI_COP, awc(aChainsawStrafeLeftAnimations), aStdAnimDescsSide }, + { "csawright", "ped", MI_COP, awc(aChainsawStrafeRightAnimations), aStdAnimDescsSide }, #endif }; #undef awc @@ -585,8 +973,6 @@ CAnimManager::Initialise(void) ms_numAnimations = 0; ms_numAnimBlocks = 0; ms_animCache.Init(25); - -// dumpanimdata(); } void @@ -594,31 +980,50 @@ CAnimManager::Shutdown(void) { int i; - ms_animCache.Shutdown(); + for(i = 0; i < NUMANIMBLOCKS; i++) + CStreaming::RemoveAnim(i); for(i = 0; i < ms_numAnimations; i++) ms_aAnimations[i].Shutdown(); + ms_animCache.Shutdown(); + delete[] ms_aAnimAssocGroups; } void CAnimManager::UncompressAnimation(CAnimBlendHierarchy *hier) { - if(!hier->compressed){ - if(hier->linkPtr){ - hier->linkPtr->Remove(); - ms_animCache.head.Insert(hier->linkPtr); - } + if(hier->keepCompressed){ + if(hier->totalLength == 0.0f) + hier->CalcTotalTimeCompressed(); }else{ - CLink<CAnimBlendHierarchy*> *link = ms_animCache.Insert(hier); - if(link == nil){ - ms_animCache.tail.prev->item->RemoveUncompressedData(); - ms_animCache.Remove(ms_animCache.tail.prev); - link = ms_animCache.Insert(hier); + if(!hier->compressed){ + if(hier->linkPtr){ + hier->linkPtr->Remove(); + ms_animCache.head.Insert(hier->linkPtr); + } + }else{ + CLink<CAnimBlendHierarchy*> *link = ms_animCache.Insert(hier); + if(link == nil){ + CAnimBlendHierarchy *lastHier = ms_animCache.tail.prev->item; + lastHier->RemoveUncompressedData(); + ms_animCache.Remove(ms_animCache.tail.prev); + lastHier->linkPtr = nil; + link = ms_animCache.Insert(hier); + } + hier->linkPtr = link; + hier->Uncompress(); } - hier->linkPtr = link; - hier->Uncompress(); + } +} + +void +CAnimManager::RemoveFromUncompressedCache(CAnimBlendHierarchy *hier) +{ + if(hier->linkPtr){ + ms_animCache.Remove(hier->linkPtr); + hier->linkPtr = nil; } } @@ -633,6 +1038,73 @@ CAnimManager::GetAnimationBlock(const char *name) return nil; } +int32 +CAnimManager::GetAnimationBlockIndex(const char *name) +{ + int i; + + for(i = 0; i < ms_numAnimBlocks; i++) + if(strcasecmp(ms_aAnimBlocks[i].name, name) == 0) + return i; + return -1; +} + +int32 +CAnimManager::RegisterAnimBlock(const char *name) +{ + CAnimBlock *animBlock = GetAnimationBlock(name); + if(animBlock == nil){ + animBlock = &ms_aAnimBlocks[ms_numAnimBlocks++]; + strncpy(animBlock->name, name, MAX_ANIMBLOCK_NAME); + animBlock->numAnims = 0; + assert(animBlock->refCount == 0); + } + return animBlock - ms_aAnimBlocks; +} + +int32 +CAnimManager::GetNumRefsToAnimBlock(int32 block) +{ + return ms_aAnimBlocks[block].refCount; +} + +void +CAnimManager::AddAnimBlockRef(int32 block) +{ + ms_aAnimBlocks[block].refCount++; +} + +void +CAnimManager::RemoveAnimBlockRefWithoutDelete(int32 block) +{ + ms_aAnimBlocks[block].refCount--; +} + +void +CAnimManager::RemoveAnimBlockRef(int32 block) +{ + ms_aAnimBlocks[block].refCount--; + if(ms_aAnimBlocks[block].refCount == 0) + CStreaming::RemoveAnim(block); +} + +void +CAnimManager::RemoveAnimBlock(int32 block) +{ + int i; + CAnimBlock *animblock; + + animblock = &ms_aAnimBlocks[block]; + debug("Removing ANIMS %s\n", animblock->name); + for(i = 0; i < NUM_ANIM_ASSOC_GROUPS; i++) + if(ms_aAnimAssocGroups[i].animBlock == animblock) + ms_aAnimAssocGroups[i].DestroyAssociations(); + for(i = 0; i < animblock->numAnims; i++) + ms_aAnimations[animblock->firstIndex + i].Shutdown(); + animblock->isLoaded = false; + animblock->refCount = 0; +} + CAnimBlendHierarchy* CAnimManager::GetAnimation(const char *name, CAnimBlock *animBlock) { @@ -640,7 +1112,7 @@ CAnimManager::GetAnimation(const char *name, CAnimBlock *animBlock) CAnimBlendHierarchy *hier = &ms_aAnimations[animBlock->firstIndex]; for(i = 0; i < animBlock->numAnims; i++){ - if(!CGeneral::faststricmp(hier->name, name)) + if(strcasecmp(hier->name, name) == 0) return hier; hier++; } @@ -761,26 +1233,34 @@ CAnimManager::BlendAnimation(RpClump *clump, AssocGroupId groupId, AnimationId a void CAnimManager::LoadAnimFiles(void) { - int i, j; - LoadAnimFile("ANIM\\PED.IFP"); - - // Create all assoc groups ms_aAnimAssocGroups = new CAnimBlendAssocGroup[NUM_ANIM_ASSOC_GROUPS]; + CreateAnimAssocGroups(); +} + +void +CAnimManager::CreateAnimAssocGroups(void) +{ + int i, j; + for(i = 0; i < NUM_ANIM_ASSOC_GROUPS; i++){ + CAnimBlock *block = GetAnimationBlock(ms_aAnimAssocDefinitions[i].blockName); + if(block == nil || !block->isLoaded || ms_aAnimAssocGroups[i].assocList) + continue; + CBaseModelInfo *mi = CModelInfo::GetModelInfo(ms_aAnimAssocDefinitions[i].modelIndex); RpClump *clump = (RpClump*)mi->CreateInstance(); RpAnimBlendClumpInit(clump); CAnimBlendAssocGroup *group = &ms_aAnimAssocGroups[i]; const AnimAssocDefinition *def = &ms_aAnimAssocDefinitions[i]; + group->groupId = i; + group->firstAnimId = def->animDescs[0].animId; group->CreateAssociations(def->blockName, clump, def->animNames, def->numAnims); for(j = 0; j < group->numAssociations; j++) - group->GetAnimation(j)->flags |= def->animDescs[j].flags; -#ifdef PED_SKIN - // forgot on xbox/android + // GetAnimation(i) in III (but it's in LoadAnimFiles), GetAnimation(group->animDesc[j].animId) in VC + group->GetAnimation(def->animDescs[j].animId)->flags |= def->animDescs[j].flags; if(IsClumpSkinned(clump)) RpClumpForAllAtomics(clump, AtomicRemoveAnimFromSkinCB, nil); -#endif RpClumpDestroy(clump); } } @@ -788,15 +1268,15 @@ CAnimManager::LoadAnimFiles(void) void CAnimManager::LoadAnimFile(const char *filename) { - int fd; - fd = CFileMgr::OpenFile(filename, "rb"); - assert(fd > 0); - LoadAnimFile(fd, true); - CFileMgr::CloseFile(fd); + RwStream *stream; + stream = RwStreamOpen(rwSTREAMFILENAME, rwSTREAMREAD, filename); + assert(stream); + LoadAnimFile(stream, true); + RwStreamClose(stream, nil); } void -CAnimManager::LoadAnimFile(int fd, bool compress) +CAnimManager::LoadAnimFile(RwStream *stream, bool compress, char (*uncompressedAnims)[32]) { #define ROUNDSIZE(x) if((x) & 3) (x) += 4 - ((x)&3) struct IfpHeader { @@ -804,130 +1284,161 @@ CAnimManager::LoadAnimFile(int fd, bool compress) uint32 size; }; IfpHeader anpk, info, name, dgan, cpan, anim; - int numANPK; char buf[256]; - int i, j, k, l; + int j, k, l; float *fbuf = (float*)buf; - CFileMgr::Read(fd, (char*)&anpk, sizeof(IfpHeader)); - if(!CGeneral::faststrncmp(anpk.ident, "ANLF", 4)) { - ROUNDSIZE(anpk.size); - CFileMgr::Read(fd, buf, anpk.size); - numANPK = *(int*)buf; - } else if(!CGeneral::faststrncmp(anpk.ident, "ANPK", 4)) { - CFileMgr::Seek(fd, -8, 1); - numANPK = 1; - } - - for(i = 0; i < numANPK; i++){ - // block name - CFileMgr::Read(fd, (char*)&anpk, sizeof(IfpHeader)); - ROUNDSIZE(anpk.size); - CFileMgr::Read(fd, (char*)&info, sizeof(IfpHeader)); - ROUNDSIZE(info.size); - CFileMgr::Read(fd, buf, info.size); - CAnimBlock *animBlock = &ms_aAnimBlocks[ms_numAnimBlocks++]; - strncpy(animBlock->name, buf+4, 24); + // block name + RwStreamRead(stream, &anpk, sizeof(IfpHeader)); + ROUNDSIZE(anpk.size); + RwStreamRead(stream, &info, sizeof(IfpHeader)); + ROUNDSIZE(info.size); + RwStreamRead(stream, buf, info.size); + CAnimBlock *animBlock = GetAnimationBlock(buf+4); + if(animBlock){ + if(animBlock->numAnims == 0){ + animBlock->numAnims = *(int*)buf; + animBlock->firstIndex = ms_numAnimations; + } + }else{ + animBlock = &ms_aAnimBlocks[ms_numAnimBlocks++]; + strncpy(animBlock->name, buf+4, MAX_ANIMBLOCK_NAME); animBlock->numAnims = *(int*)buf; - animBlock->firstIndex = ms_numAnimations; + } - for(j = 0; j < animBlock->numAnims; j++){ - CAnimBlendHierarchy *hier = &ms_aAnimations[ms_numAnimations++]; + debug("Loading ANIMS %s\n", animBlock->name); + animBlock->isLoaded = true; - // animation name - CFileMgr::Read(fd, (char*)&name, sizeof(IfpHeader)); - ROUNDSIZE(name.size); - CFileMgr::Read(fd, buf, name.size); - hier->SetName(buf); + int animIndex = animBlock->firstIndex; + for(j = 0; j < animBlock->numAnims; j++){ + assert(animIndex < ARRAY_SIZE(ms_aAnimations)); + CAnimBlendHierarchy *hier = &ms_aAnimations[animIndex++]; - // DG info has number of nodes/sequences - CFileMgr::Read(fd, (char*)&dgan, sizeof(IfpHeader)); - ROUNDSIZE(dgan.size); - CFileMgr::Read(fd, (char*)&info, sizeof(IfpHeader)); - ROUNDSIZE(info.size); - CFileMgr::Read(fd, buf, info.size); - hier->numSequences = *(int*)buf; - hier->sequences = new CAnimBlendSequence[hier->numSequences]; - - CAnimBlendSequence *seq = hier->sequences; - for(k = 0; k < hier->numSequences; k++, seq++){ - // Each node has a name and key frames - CFileMgr::Read(fd, (char*)&cpan, sizeof(IfpHeader)); - ROUNDSIZE(dgan.size); - CFileMgr::Read(fd, (char*)&anim, sizeof(IfpHeader)); - ROUNDSIZE(anim.size); - CFileMgr::Read(fd, buf, anim.size); - int numFrames = *(int*)(buf+28); - seq->SetName(buf); -#ifdef PED_SKIN - if(anim.size == 44) - seq->SetBoneTag(*(int*)(buf+40)); + // animation name + RwStreamRead(stream, &name, sizeof(IfpHeader)); + ROUNDSIZE(name.size); + RwStreamRead(stream, buf, name.size); + hier->SetName(buf); + +#ifdef ANIM_COMPRESSION + bool compressHier = compress; +#else + bool compressHier = false; #endif - if(numFrames == 0) - continue; - - bool hasScale = false; - bool hasTranslation = false; - CFileMgr::Read(fd, (char*)&info, sizeof(info)); - if(!CGeneral::faststrncmp(info.ident, "KRTS", 4)) { - hasScale = true; - seq->SetNumFrames(numFrames, true); - }else if(!CGeneral::faststrncmp(info.ident, "KRT0", 4)) { - hasTranslation = true; - seq->SetNumFrames(numFrames, true); - }else if(!CGeneral::faststrncmp(info.ident, "KR00", 4)){ - seq->SetNumFrames(numFrames, false); + if (uncompressedAnims) { + for (int i = 0; uncompressedAnims[i][0]; i++) { + if (!CGeneral::faststricmp(uncompressedAnims[i], hier->name)){ + debug("Loading %s uncompressed\n", hier->name); + compressHier = false; } + } + } + + hier->compressed = compressHier; + hier->keepCompressed = false; + + // DG info has number of nodes/sequences + RwStreamRead(stream, (char*)&dgan, sizeof(IfpHeader)); + ROUNDSIZE(dgan.size); + RwStreamRead(stream, (char*)&info, sizeof(IfpHeader)); + ROUNDSIZE(info.size); + RwStreamRead(stream, buf, info.size); + hier->numSequences = *(int*)buf; + hier->sequences = new CAnimBlendSequence[hier->numSequences]; - for(l = 0; l < numFrames; l++){ - if(hasScale){ - CFileMgr::Read(fd, buf, 0x2C); - CQuaternion rot(fbuf[0], fbuf[1], fbuf[2], fbuf[3]); - rot.Invert(); - CVector trans(fbuf[4], fbuf[5], fbuf[6]); + CAnimBlendSequence *seq = hier->sequences; + for(k = 0; k < hier->numSequences; k++, seq++){ + // Each node has a name and key frames + RwStreamRead(stream, &cpan, sizeof(IfpHeader)); + ROUNDSIZE(dgan.size); + RwStreamRead(stream, &anim, sizeof(IfpHeader)); + ROUNDSIZE(anim.size); + RwStreamRead(stream, buf, anim.size); + int numFrames = *(int*)(buf+28); + seq->SetName(buf); + if(anim.size == 44) + seq->SetBoneTag(*(int*)(buf+40)); + if(numFrames == 0) + continue; + + bool hasScale = false; + bool hasTranslation = false; + RwStreamRead(stream, &info, sizeof(info)); + if(strncmp(info.ident, "KRTS", 4) == 0){ + hasScale = true; + seq->SetNumFrames(numFrames, true, compressHier); + }else if(strncmp(info.ident, "KRT0", 4) == 0){ + hasTranslation = true; + seq->SetNumFrames(numFrames, true, compressHier); + }else if(strncmp(info.ident, "KR00", 4) == 0){ + seq->SetNumFrames(numFrames, false, compressHier); + } + if(strstr(seq->name, "L Toe")) + debug("anim %s has toe keyframes\n", hier->name); // BUG: seq->name + + for(l = 0; l < numFrames; l++){ + if(hasScale){ + RwStreamRead(stream, buf, 0x2C); + CQuaternion rot(fbuf[0], fbuf[1], fbuf[2], fbuf[3]); + rot.Invert(); + CVector trans(fbuf[4], fbuf[5], fbuf[6]); + if(compressHier){ + KeyFrameTransCompressed *kf = (KeyFrameTransCompressed*)seq->GetKeyFrameCompressed(l); + kf->SetRotation(rot); + kf->SetTranslation(trans); + // scaling ignored + kf->SetTime(fbuf[10]); // absolute time here + }else{ KeyFrameTrans *kf = (KeyFrameTrans*)seq->GetKeyFrame(l); kf->rotation = rot; kf->translation = trans; // scaling ignored kf->deltaTime = fbuf[10]; // absolute time here - }else if(hasTranslation){ - CFileMgr::Read(fd, buf, 0x20); - CQuaternion rot(fbuf[0], fbuf[1], fbuf[2], fbuf[3]); - rot.Invert(); - CVector trans(fbuf[4], fbuf[5], fbuf[6]); + } + }else if(hasTranslation){ + RwStreamRead(stream, buf, 0x20); + CQuaternion rot(fbuf[0], fbuf[1], fbuf[2], fbuf[3]); + rot.Invert(); + CVector trans(fbuf[4], fbuf[5], fbuf[6]); + if(compressHier){ + KeyFrameTransCompressed *kf = (KeyFrameTransCompressed*)seq->GetKeyFrameCompressed(l); + kf->SetRotation(rot); + kf->SetTranslation(trans); + kf->SetTime(fbuf[7]); // absolute time here + }else{ KeyFrameTrans *kf = (KeyFrameTrans*)seq->GetKeyFrame(l); kf->rotation = rot; kf->translation = trans; kf->deltaTime = fbuf[7]; // absolute time here - }else{ - CFileMgr::Read(fd, buf, 0x14); - CQuaternion rot(fbuf[0], fbuf[1], fbuf[2], fbuf[3]); - rot.Invert(); + } + }else{ + RwStreamRead(stream, buf, 0x14); + CQuaternion rot(fbuf[0], fbuf[1], fbuf[2], fbuf[3]); + rot.Invert(); + if(compressHier){ + KeyFrameCompressed *kf = (KeyFrameCompressed*)seq->GetKeyFrameCompressed(l); + kf->SetRotation(rot); + kf->SetTime(fbuf[4]); // absolute time here + }else{ KeyFrame *kf = (KeyFrame*)seq->GetKeyFrame(l); kf->rotation = rot; kf->deltaTime = fbuf[4]; // absolute time here } } - - // convert absolute time to deltas - for(l = seq->numFrames-1; l > 0; l--){ - KeyFrame *kf1 = seq->GetKeyFrame(l); - KeyFrame *kf2 = seq->GetKeyFrame(l-1); - kf1->deltaTime -= kf2->deltaTime; - } } + } + if(!compressHier){ hier->RemoveQuaternionFlips(); - if(compress) - hier->RemoveUncompressedData(); - else - hier->CalcTotalTime(); + hier->CalcTotalTime(); } } + if(animIndex > ms_numAnimations) + ms_numAnimations = animIndex; } void @@ -937,5 +1448,6 @@ CAnimManager::RemoveLastAnimFile(void) ms_numAnimBlocks--; ms_numAnimations = ms_aAnimBlocks[ms_numAnimBlocks].firstIndex; for(i = 0; i < ms_aAnimBlocks[ms_numAnimBlocks].numAnims; i++) - ms_aAnimations[ms_aAnimBlocks[ms_numAnimBlocks].firstIndex + i].RemoveAnimSequences(); + ms_aAnimations[ms_aAnimBlocks[ms_numAnimBlocks].firstIndex + i].Shutdown(); + ms_aAnimBlocks[ms_numAnimBlocks].isLoaded = false; } diff --git a/src/animation/AnimManager.h b/src/animation/AnimManager.h index 92192c71..213326b6 100644 --- a/src/animation/AnimManager.h +++ b/src/animation/AnimManager.h @@ -6,24 +6,57 @@ enum AssocGroupId { ASSOCGRP_STD, + ASSOCGRP_VAN, + ASSOCGRP_COACH, + ASSOCGRP_BIKE_STANDARD, + ASSOCGRP_BIKE_VESPA, + ASSOCGRP_BIKE_HARLEY, + ASSOCGRP_BIKE_DIRT, + ASSOCGRP_UNARMED, + ASSOCGRP_SCREWDRIVER, + ASSOCGRP_KNIFE, + ASSOCGRP_BASEBALLBAT, + ASSOCGRP_GOLFCLUB, + ASSOCGRP_CHAINSAW, + ASSOCGRP_PYTHON, + ASSOCGRP_COLT, + ASSOCGRP_SHOTGUN, + ASSOCGRP_BUDDY, + ASSOCGRP_TEC, + ASSOCGRP_UZI, + ASSOCGRP_RIFLE, + ASSOCGRP_M60, + ASSOCGRP_SNIPER, + ASSOCGRP_THROW, + ASSOCGRP_FLAMETHROWER, + ASSOCGRP_MEDIC, + ASSOCGRP_SUNBATHE, + ASSOCGRP_PLAYER_IDLE, + ASSOCGRP_RIOT, + ASSOCGRP_STRIP, + ASSOCGRP_LANCE, ASSOCGRP_PLAYER, ASSOCGRP_PLAYERROCKET, ASSOCGRP_PLAYER1ARMED, ASSOCGRP_PLAYER2ARMED, ASSOCGRP_PLAYERBBBAT, + ASSOCGRP_PLAYERCHAINSAW, ASSOCGRP_SHUFFLE, ASSOCGRP_OLD, ASSOCGRP_GANG1, ASSOCGRP_GANG2, ASSOCGRP_FAT, ASSOCGRP_OLDFAT, + ASSOCGRP_JOGGER, ASSOCGRP_WOMAN, ASSOCGRP_WOMANSHOP, ASSOCGRP_BUSYWOMAN, ASSOCGRP_SEXYWOMAN, - ASSOCGRP_OLDWOMAN, ASSOCGRP_FATWOMAN, + ASSOCGRP_OLDWOMAN, + ASSOCGRP_JOGWOMAN, ASSOCGRP_PANICCHUNKY, + ASSOCGRP_SKATE, #ifdef PC_PLAYER_CONTROLS ASSOCGRP_PLAYERBACK, ASSOCGRP_PLAYERLEFT, @@ -31,6 +64,9 @@ enum AssocGroupId ASSOCGRP_ROCKETBACK, ASSOCGRP_ROCKETLEFT, ASSOCGRP_ROCKETRIGHT, + ASSOCGRP_CHAINSAWBACK, + ASSOCGRP_CHAINSAWLEFT, + ASSOCGRP_CHAINSAWRIGHT, #endif NUM_ANIM_ASSOC_GROUPS @@ -39,11 +75,15 @@ enum AssocGroupId class CAnimBlendAssociation; class CAnimBlendAssocGroup; +#define MAX_ANIMBLOCK_NAME 20 + // A block of hierarchies struct CAnimBlock { - char name[24]; - int32 firstIndex; + char name[MAX_ANIMBLOCK_NAME]; + bool isLoaded; + int16 refCount; + int32 firstIndex; // first animtion in ms_aAnimations int32 numAnims; }; @@ -77,7 +117,16 @@ public: static void Initialise(void); static void Shutdown(void); static void UncompressAnimation(CAnimBlendHierarchy *anim); + static void RemoveFromUncompressedCache(CAnimBlendHierarchy *hier); + static CAnimBlock *GetAnimationBlock(int32 block) { return &ms_aAnimBlocks[block]; } static CAnimBlock *GetAnimationBlock(const char *name); + static int32 GetAnimationBlockIndex(const char *name); + static int32 RegisterAnimBlock(const char *name); + static int32 GetNumRefsToAnimBlock(int32 block); + static void AddAnimBlockRef(int32 block); + static void RemoveAnimBlockRefWithoutDelete(int32 block); + static void RemoveAnimBlockRef(int32 block); + static void RemoveAnimBlock(int32 block); static CAnimBlendHierarchy *GetAnimation(const char *name, CAnimBlock *animBlock); static CAnimBlendHierarchy *GetAnimation(int32 n) { return &ms_aAnimations[n]; } static const char *GetAnimGroupName(AssocGroupId groupId); @@ -89,6 +138,8 @@ public: static CAnimBlendAssociation *BlendAnimation(RpClump *clump, AssocGroupId groupId, AnimationId animId, float delta); static void LoadAnimFiles(void); static void LoadAnimFile(const char *filename); - static void LoadAnimFile(int fd, bool compress); + static void LoadAnimFile(RwStream *stream, bool compress, char (*uncompressedAnims)[32] = nil); + static void CreateAnimAssocGroups(void); static void RemoveLastAnimFile(void); + static CAnimBlendAssocGroup* GetAnimAssocGroups(void) { return ms_aAnimAssocGroups; } }; diff --git a/src/animation/AnimationId.h b/src/animation/AnimationId.h index baf6eb33..0b5d8d8e 100644 --- a/src/animation/AnimationId.h +++ b/src/animation/AnimationId.h @@ -42,9 +42,6 @@ enum AnimationId ANIM_STD_HIT_FLOOR, /* names made up */ -#if GTA_VERSION <= GTA3_PS2_160 - ANIM_STD_HIT_BODY, -#endif ANIM_STD_HIT_BODYBLOW, ANIM_STD_HIT_CHEST, ANIM_STD_HIT_HEAD, @@ -54,42 +51,6 @@ enum AnimationId ANIM_STD_HIT_WALL, ANIM_STD_HIT_FLOOR_FRONT, ANIM_STD_HIT_BEHIND, - ANIM_STD_PUNCH, - ANIM_STD_KICKGROUND, - - /* names made up */ - ANIM_STD_WEAPON_BAT_H, - ANIM_STD_WEAPON_BAT_V, - ANIM_STD_WEAPON_HGUN_BODY, - ANIM_STD_WEAPON_AK_BODY, - ANIM_STD_WEAPON_PUMP, - ANIM_STD_WEAPON_SNIPER, - ANIM_STD_WEAPON_THROW, - /**/ - - ANIM_STD_THROW_UNDER, - - /* names made up */ - ANIM_STD_START_THROW, - /**/ - - ANIM_STD_DETONATE, - - /* names made up */ - ANIM_STD_HGUN_RELOAD, - ANIM_STD_AK_RELOAD, -#ifdef PC_PLAYER_CONTROLS - // maybe wrong define, but unused anyway - ANIM_FPS_PUNCH, - ANIM_FPS_BAT, - ANIM_FPS_UZI, - ANIM_FPS_PUMP, - ANIM_FPS_AK, - ANIM_FPS_M16, - ANIM_FPS_ROCKET, -#endif - /**/ - ANIM_STD_FIGHT_IDLE, ANIM_STD_FIGHT_2IDLE, ANIM_STD_FIGHT_SHUFFLE_F, @@ -106,6 +67,23 @@ enum AnimationId /**/ ANIM_STD_PARTIAL_PUNCH, + + /* names made up */ + ANIM_STD_FIGHT_JAB, + ANIM_STD_FIGHT_ELBOW_L, + ANIM_STD_FIGHT_ELBOW_R, + ANIM_STD_FIGHT_BKICK_L, + ANIM_STD_FIGHT_BKICK_R, + /**/ + + ANIM_STD_DETONATE, + ANIM_STD_PUNCH, + ANIM_STD_PARTIALPUNCH, + ANIM_STD_KICKGROUND, + + ANIM_STD_THROW_UNDER, + ANIM_STD_FIGHT_SHUFFLE_B, + ANIM_STD_JACKEDCAR_RHS, ANIM_STD_JACKEDCAR_LO_RHS, ANIM_STD_JACKEDCAR_LHS, @@ -124,6 +102,7 @@ enum AnimationId ANIM_STD_CAR_CLOSE_DOOR_LO_LHS, ANIM_STD_CAR_CLOSE_DOOR_ROLLING_LHS, ANIM_STD_CAR_CLOSE_DOOR_ROLLING_LO_LHS, + ANIM_STD_CAR_JUMP_IN_LO_LHS, ANIM_STD_GETOUT_LHS, ANIM_STD_GETOUT_LO_LHS, ANIM_STD_CAR_CLOSE_LHS, @@ -149,29 +128,36 @@ enum AnimationId ANIM_STD_CAR_DRIVE_RIGHT_LO, ANIM_STD_CAR_DRIVEBY_LEFT, ANIM_STD_CAR_DRIVEBY_RIGHT, + ANIM_STD_CAR_DRIVEBY_LEFT_LO, + ANIM_STD_CAR_DRIVEBY_RIGHT_LO, ANIM_STD_CAR_LOOKBEHIND, ANIM_STD_BOAT_DRIVE, + ANIM_STD_BOAT_DRIVE_LEFT, + ANIM_STD_BOAT_DRIVE_RIGHT, + ANIM_STD_BOAT_LOOKBEHIND, + + ANIM_STD_BIKE_PICKUP_LHS, + ANIM_STD_BIKE_PICKUP_RHS, + ANIM_STD_BIKE_PULLUP_LHS, + ANIM_STD_BIKE_PULLUP_RHS, + ANIM_STD_BIKE_ELBOW_LHS, + ANIM_STD_BIKE_ELBOW_RHS, + ANIM_STD_BIKE_FALLOFF, + ANIM_STD_BIKE_FALLBACK, + ANIM_STD_GETOUT_RHS, ANIM_STD_GETOUT_LO_RHS, ANIM_STD_CAR_CLOSE_RHS, ANIM_STD_CAR_HOOKERTALK, - ANIM_STD_COACH_OPEN_LHS, - ANIM_STD_COACH_OPEN_RHS, - ANIM_STD_COACH_GET_IN_LHS, - ANIM_STD_COACH_GET_IN_RHS, - ANIM_STD_COACH_GET_OUT_LHS, + ANIM_STD_TRAIN_GETIN, ANIM_STD_TRAIN_GETOUT, + ANIM_STD_CRAWLOUT_LHS, ANIM_STD_CRAWLOUT_RHS, - ANIM_STD_VAN_OPEN_DOOR_REAR_LHS, - ANIM_STD_VAN_GET_IN_REAR_LHS, - ANIM_STD_VAN_CLOSE_DOOR_REAR_LHS, - ANIM_STD_VAN_GET_OUT_REAR_LHS, - ANIM_STD_VAN_OPEN_DOOR_REAR_RHS, - ANIM_STD_VAN_GET_IN_REAR_RHS, - ANIM_STD_VAN_CLOSE_DOOR_REAR_RHS, - ANIM_STD_VAN_GET_OUT_REAR_RHS, + ANIM_STD_ROLLOUT_LHS, + ANIM_STD_ROLLOUT_RHS, + ANIM_STD_GET_UP, ANIM_STD_GET_UP_LEFT, ANIM_STD_GET_UP_RIGHT, @@ -183,6 +169,9 @@ enum AnimationId ANIM_STD_FALL_GLIDE, ANIM_STD_FALL_LAND, ANIM_STD_FALL_COLLAPSE, + ANIM_STD_FALL_ONBACK, + ANIM_STD_FALL_ONFRONT, + ANIM_STD_EVADE_STEP, ANIM_STD_EVADE_DIVE, ANIM_STD_XPRESS_SCRATCH, @@ -190,15 +179,12 @@ enum AnimationId ANIM_STD_TURN180, ANIM_STD_ARREST, ANIM_STD_DROWN, - ANIM_MEDIC_CPR, ANIM_STD_DUCK_DOWN, ANIM_STD_DUCK_LOW, - ANIM_STD_RBLOCK_SHOOT, - /* names made up */ - ANIM_STD_THROW_UNDER2, - /**/ + ANIM_STD_DUCK_WEAPON, + ANIM_STD_RBLOCK_SHOOT, ANIM_STD_HANDSUP, ANIM_STD_HANDSCOWER, ANIM_STD_PARTIAL_FUCKU, @@ -206,5 +192,96 @@ enum AnimationId ANIM_STD_PHONE_OUT, ANIM_STD_PHONE_TALK, - ANIM_STD_NUM + ANIM_STD_SEAT_DOWN, + ANIM_STD_SEAT_UP, + ANIM_STD_SEAT_IDLE, + ANIM_STD_SEAT_RVRS, + ANIM_STD_ATM, + ANIM_STD_ABSEIL, + + ANIM_STD_NUM, + + ANIM_STD_VAN_OPEN_DOOR_REAR_LHS, + ANIM_STD_VAN_GET_IN_REAR_LHS, + ANIM_STD_VAN_CLOSE_DOOR_REAR_LHS, + ANIM_STD_VAN_GET_OUT_REAR_LHS, + ANIM_STD_VAN_OPEN_DOOR_REAR_RHS, + ANIM_STD_VAN_GET_IN_REAR_RHS, + ANIM_STD_VAN_CLOSE_DOOR_REAR_RHS, + ANIM_STD_VAN_GET_OUT_REAR_RHS, + + ANIM_STD_COACH_OPEN_LHS, + ANIM_STD_COACH_OPEN_RHS, + ANIM_STD_COACH_GET_IN_LHS, + ANIM_STD_COACH_GET_IN_RHS, + ANIM_STD_COACH_GET_OUT_LHS, + + ANIM_BIKE_RIDE, + ANIM_BIKE_READY, + ANIM_BIKE_LEFT, + ANIM_BIKE_RIGHT, + ANIM_BIKE_LEANB, + ANIM_BIKE_LEANF, + ANIM_BIKE_WALKBACK, + ANIM_BIKE_JUMPON_LHS, + ANIM_BIKE_JUMPON_RHS, + ANIM_BIKE_KICK, + ANIM_BIKE_HIT, + ANIM_BIKE_GETOFF_LHS, + ANIM_BIKE_GETOFF_RHS, + ANIM_BIKE_GETOFF_BACK, + ANIM_BIKE_DRIVEBY_LHS, + ANIM_BIKE_DRIVEBY_RHS, + ANIM_BIKE_DRIVEBY_FORWARD, + ANIM_BIKE_RIDE_P, + + ANIM_ATTACK_1, + ANIM_ATTACK_2, + ANIM_ATTACK_EXTRA1, + ANIM_ATTACK_EXTRA2, + ANIM_ATTACK_3, + + // our synonyms... because originals are hard to understand + ANIM_WEAPON_FIRE = ANIM_ATTACK_1, + ANIM_WEAPON_CROUCHFIRE, + ANIM_WEAPON_FIRE_2ND = ANIM_WEAPON_CROUCHFIRE, + ANIM_WEAPON_RELOAD, + ANIM_WEAPON_CROUCHRELOAD, + ANIM_WEAPON_FIRE_3RD, + ANIM_THROWABLE_THROW = ANIM_ATTACK_1, + ANIM_THROWABLE_THROWU, + ANIM_THROWABLE_START_THROW, + ANIM_MELEE_ATTACK = ANIM_ATTACK_1, + ANIM_MELEE_ATTACK_2ND, + ANIM_MELEE_ATTACK_START, + ANIM_MELEE_IDLE_FIGHTMODE, + ANIM_MELEE_ATTACK_FINISH, + + ANIM_SUNBATHE_IDLE, + ANIM_SUNBATHE_DOWN, + ANIM_SUNBATHE_UP, + ANIM_SUNBATHE_ESCAPE, + + ANIM_MEDIC_CPR, + + ANIM_PLAYER_IDLE1, + ANIM_PLAYER_IDLE2, + ANIM_PLAYER_IDLE3, + ANIM_PLAYER_IDLE4, + + ANIM_RIOT_ANGRY, + ANIM_RIOT_ANGRY_B, + ANIM_RIOT_CHANT, + ANIM_RIOT_PUNCHES, + ANIM_RIOT_SHOUT, + ANIM_RIOT_CHALLENGE, + ANIM_RIOT_FUCKYOU, + + ANIM_STRIP_A, + ANIM_STRIP_B, + ANIM_STRIP_C, + ANIM_STRIP_D, + ANIM_STRIP_E, + ANIM_STRIP_F, + ANIM_STRIP_G, };
\ No newline at end of file diff --git a/src/animation/Bones.cpp b/src/animation/Bones.cpp index 1608449d..87f3b6e7 100644 --- a/src/animation/Bones.cpp +++ b/src/animation/Bones.cpp @@ -2,26 +2,29 @@ #include "PedModelInfo.h" #include "Bones.h" -#ifdef PED_SKIN - int ConvertPedNode2BoneTag(int node) { switch(node){ - case PED_TORSO: return BONE_waist; - case PED_MID: return BONE_torso; // this is what Xbox/Mobile use - // return BONE_mid; // this is what PS2/PC use - case PED_HEAD: return BONE_head; - case PED_UPPERARML: return BONE_upperarml; - case PED_UPPERARMR: return BONE_upperarmr; - case PED_HANDL: return BONE_Lhand; - case PED_HANDR: return BONE_Rhand; - case PED_UPPERLEGL: return BONE_upperlegl; - case PED_UPPERLEGR: return BONE_upperlegr; - case PED_FOOTL: return BONE_footl; - case PED_FOOTR: return BONE_footr; - case PED_LOWERLEGR: return BONE_lowerlegl; + case PED_MID: return BONE_spine1; + case PED_HEAD: return BONE_head; + case PED_UPPERARML: return BONE_l_upperarm; + case PED_UPPERARMR: return BONE_r_upperarm; + case PED_HANDL: return BONE_l_hand; + case PED_HANDR: return BONE_r_hand; + case PED_UPPERLEGL: return BONE_l_thigh; + case PED_UPPERLEGR: return BONE_r_thigh; + case PED_FOOTL: return BONE_l_foot; + case PED_FOOTR: return BONE_r_foot; + case PED_LOWERLEGR: return BONE_r_calf; + case PED_LOWERLEGL: return BONE_l_calf; + case PED_FOREARML: return BONE_l_forearm; + case PED_FOREARMR: return BONE_r_forearm; + case PED_CLAVICLEL: return BONE_l_clavicle; + case PED_CLAVICLER: return BONE_r_clavicle; + case PED_NECK: return BONE_neck; } + assert(0 && "this node has no bone"); return -1; } @@ -29,24 +32,28 @@ const char* ConvertBoneTag2BoneName(int tag) { switch(tag){ - case BONE_waist: return "Swaist"; - case BONE_upperlegr: return "Supperlegr"; - case BONE_lowerlegr: return "Slowerlegr"; - case BONE_footr: return "Sfootr"; - case BONE_upperlegl: return "Supperlegl"; - case BONE_lowerlegl: return "Slowerlegl"; - case BONE_footl: return "Sfootl"; - case BONE_mid: return "Smid"; - case BONE_torso: return "Storso"; - case BONE_head: return "Shead"; - case BONE_upperarmr: return "Supperarmr"; - case BONE_lowerarmr: return "Slowerarmr"; - case BONE_Rhand: return "SRhand"; - case BONE_upperarml: return "Supperarml"; - case BONE_lowerarml: return "Slowerarml"; - case BONE_Lhand: return "SLhand"; + case BONE_root: return "Root"; + case BONE_pelvis: return "Pelvis"; + case BONE_spine: return "Spine"; + case BONE_spine1: return "Spine1"; + case BONE_neck: return "Neck"; + case BONE_head: return "Head"; + case BONE_r_clavicle: return "Bip01 R Clavicle"; + case BONE_r_upperarm: return "R UpperArm"; + case BONE_r_forearm: return "R Forearm"; + case BONE_r_hand: return "R Hand"; + case BONE_r_finger: return "R Fingers"; + case BONE_l_clavicle: return "Bip01 L Clavicle"; + case BONE_l_upperarm: return "L UpperArm"; + case BONE_l_forearm: return "L Forearm"; + case BONE_l_hand: return "L Hand"; + case BONE_l_finger: return "L Fingers"; + case BONE_l_thigh: return "L Thigh"; + case BONE_l_calf: return "L Calf"; + case BONE_l_foot: return "L Foot"; + case BONE_r_thigh: return "R Thigh"; + case BONE_r_calf: return "R Calf"; + case BONE_r_foot: return "R Foot"; } return nil; } - -#endif diff --git a/src/animation/Bones.h b/src/animation/Bones.h index 38d91ba3..e133fd7f 100644 --- a/src/animation/Bones.h +++ b/src/animation/Bones.h @@ -2,22 +2,28 @@ enum BoneTag { - BONE_waist, - BONE_upperlegr, - BONE_lowerlegr, - BONE_footr, - BONE_upperlegl, - BONE_lowerlegl, - BONE_footl, - BONE_mid, - BONE_torso, - BONE_head, - BONE_upperarmr, - BONE_lowerarmr, - BONE_Rhand, - BONE_upperarml, - BONE_lowerarml, - BONE_Lhand, + BONE_root = 0, + BONE_pelvis = 1, + BONE_spine = 2, + BONE_spine1 = 3, + BONE_neck = 4, + BONE_head = 5, + BONE_l_clavicle = 31, + BONE_l_upperarm = 32, + BONE_l_forearm = 33, + BONE_l_hand = 34, + BONE_l_finger = 35, + BONE_r_clavicle = 21, + BONE_r_upperarm = 22, + BONE_r_forearm = 23, + BONE_r_hand = 24, + BONE_r_finger = 25, + BONE_l_thigh = 41, + BONE_l_calf = 42, + BONE_l_foot = 43, + BONE_r_thigh = 51, + BONE_r_calf = 52, + BONE_r_foot = 53, }; int ConvertPedNode2BoneTag(int node); diff --git a/src/animation/CutsceneMgr.cpp b/src/animation/CutsceneMgr.cpp index 83c4dbcb..633618b1 100644 --- a/src/animation/CutsceneMgr.cpp +++ b/src/animation/CutsceneMgr.cpp @@ -16,94 +16,92 @@ #include "World.h" #include "PlayerPed.h" #include "Wanted.h" -#include "CutsceneHead.h" #include "RpAnimBlend.h" #include "ModelIndices.h" #include "TempColModels.h" +#include "ColStore.h" +#include "Radar.h" +#include "Pools.h" const struct { const char *szTrackName; int iTrackId; } musicNameIdAssoc[] = { - { "JB", STREAMED_SOUND_NEWS_INTRO }, - { "BET", STREAMED_SOUND_BANK_INTRO }, - { "L1_LG", STREAMED_SOUND_CUTSCENE_LUIGI1_LG }, - { "L2_DSB", STREAMED_SOUND_CUTSCENE_LUIGI2_DSB }, - { "L3_DM", STREAMED_SOUND_CUTSCENE_LUIGI3_DM }, - { "L4_PAP", STREAMED_SOUND_CUTSCENE_LUIGI4_PAP }, - { "L5_TFB", STREAMED_SOUND_CUTSCENE_LUIGI5_TFB }, - { "J0_DM2", STREAMED_SOUND_CUTSCENE_JOEY0_DM2 }, - { "J1_LFL", STREAMED_SOUND_CUTSCENE_JOEY1_LFL }, - { "J2_KCL", STREAMED_SOUND_CUTSCENE_JOEY2_KCL }, - { "J3_VH", STREAMED_SOUND_CUTSCENE_JOEY3_VH }, - { "J4_ETH", STREAMED_SOUND_CUTSCENE_JOEY4_ETH }, - { "J5_DST", STREAMED_SOUND_CUTSCENE_JOEY5_DST }, - { "J6_TBJ", STREAMED_SOUND_CUTSCENE_JOEY6_TBJ }, - { "T1_TOL", STREAMED_SOUND_CUTSCENE_TONI1_TOL }, - { "T2_TPU", STREAMED_SOUND_CUTSCENE_TONI2_TPU }, - { "T3_MAS", STREAMED_SOUND_CUTSCENE_TONI3_MAS }, - { "T4_TAT", STREAMED_SOUND_CUTSCENE_TONI4_TAT }, - { "T5_BF", STREAMED_SOUND_CUTSCENE_TONI5_BF }, - { "S0_MAS", STREAMED_SOUND_CUTSCENE_SAL0_MAS }, - { "S1_PF", STREAMED_SOUND_CUTSCENE_SAL1_PF }, - { "S2_CTG", STREAMED_SOUND_CUTSCENE_SAL2_CTG }, - { "S3_RTC", STREAMED_SOUND_CUTSCENE_SAL3_RTC }, - { "S5_LRQ", STREAMED_SOUND_CUTSCENE_SAL5_LRQ }, - { "S4_BDBA", STREAMED_SOUND_CUTSCENE_SAL4_BDBA }, - { "S4_BDBB", STREAMED_SOUND_CUTSCENE_SAL4_BDBB }, - { "S2_CTG2", STREAMED_SOUND_CUTSCENE_SAL2_CTG2 }, - { "S4_BDBD", STREAMED_SOUND_CUTSCENE_SAL4_BDBD }, - { "S5_LRQB", STREAMED_SOUND_CUTSCENE_SAL5_LRQB }, - { "S5_LRQC", STREAMED_SOUND_CUTSCENE_SAL5_LRQC }, - { "A1_SS0", STREAMED_SOUND_CUTSCENE_ASUKA_1_SSO }, - { "A2_PP", STREAMED_SOUND_CUTSCENE_ASUKA_2_PP }, - { "A3_SS", STREAMED_SOUND_CUTSCENE_ASUKA_3_SS }, - { "A4_PDR", STREAMED_SOUND_CUTSCENE_ASUKA_4_PDR }, - { "A5_K2FT", STREAMED_SOUND_CUTSCENE_ASUKA_5_K2FT}, - { "K1_KBO", STREAMED_SOUND_CUTSCENE_KENJI1_KBO }, - { "K2_GIS", STREAMED_SOUND_CUTSCENE_KENJI2_GIS }, - { "K3_DS", STREAMED_SOUND_CUTSCENE_KENJI3_DS }, - { "K4_SHI", STREAMED_SOUND_CUTSCENE_KENJI4_SHI }, - { "K5_SD", STREAMED_SOUND_CUTSCENE_KENJI5_SD }, - { "R0_PDR2", STREAMED_SOUND_CUTSCENE_RAY0_PDR2 }, - { "R1_SW", STREAMED_SOUND_CUTSCENE_RAY1_SW }, - { "R2_AP", STREAMED_SOUND_CUTSCENE_RAY2_AP }, - { "R3_ED", STREAMED_SOUND_CUTSCENE_RAY3_ED }, - { "R4_GF", STREAMED_SOUND_CUTSCENE_RAY4_GF }, - { "R5_PB", STREAMED_SOUND_CUTSCENE_RAY5_PB }, - { "R6_MM", STREAMED_SOUND_CUTSCENE_RAY6_MM }, - { "D1_STOG", STREAMED_SOUND_CUTSCENE_DONALD1_STOG }, - { "D2_KK", STREAMED_SOUND_CUTSCENE_DONALD2_KK }, - { "D3_ADO", STREAMED_SOUND_CUTSCENE_DONALD3_ADO }, - { "D5_ES", STREAMED_SOUND_CUTSCENE_DONALD5_ES }, - { "D7_MLD", STREAMED_SOUND_CUTSCENE_DONALD7_MLD }, - { "D4_GTA", STREAMED_SOUND_CUTSCENE_DONALD4_GTA }, - { "D4_GTA2", STREAMED_SOUND_CUTSCENE_DONALD4_GTA2 }, - { "D6_STS", STREAMED_SOUND_CUTSCENE_DONALD6_STS }, - { "A6_BAIT", STREAMED_SOUND_CUTSCENE_ASUKA6_BAIT }, - { "A7_ETG", STREAMED_SOUND_CUTSCENE_ASUKA7_ETG }, - { "A8_PS", STREAMED_SOUND_CUTSCENE_ASUKA8_PS }, - { "A9_ASD", STREAMED_SOUND_CUTSCENE_ASUKA9_ASD }, - { "K4_SHI2", STREAMED_SOUND_CUTSCENE_KENJI4_SHI2 }, - { "C1_TEX", STREAMED_SOUND_CUTSCENE_CATALINA1_TEX }, - { "EL_PH1", STREAMED_SOUND_CUTSCENE_ELBURRO1_PH1 }, - { "EL_PH2", STREAMED_SOUND_CUTSCENE_ELBURRO2_PH2 }, - { "EL_PH3", STREAMED_SOUND_CUTSCENE_ELBURRO3_PH3 }, - { "EL_PH4", STREAMED_SOUND_CUTSCENE_ELBURRO4_PH4 }, - { "YD_PH1", STREAMED_SOUND_CUTSCENE_YARDIE_PH1 }, - { "YD_PH2", STREAMED_SOUND_CUTSCENE_YARDIE_PH2 }, - { "YD_PH3", STREAMED_SOUND_CUTSCENE_YARDIE_PH3 }, - { "YD_PH4", STREAMED_SOUND_CUTSCENE_YARDIE_PH4 }, - { "HD_PH1", STREAMED_SOUND_CUTSCENE_HOODS_PH1 }, - { "HD_PH2", STREAMED_SOUND_CUTSCENE_HOODS_PH2 }, - { "HD_PH3", STREAMED_SOUND_CUTSCENE_HOODS_PH3 }, - { "HD_PH4", STREAMED_SOUND_CUTSCENE_HOODS_PH4 }, - { "HD_PH5", STREAMED_SOUND_CUTSCENE_HOODS_PH5 }, - { "MT_PH1", STREAMED_SOUND_CUTSCENE_MARTY_PH1 }, - { "MT_PH2", STREAMED_SOUND_CUTSCENE_MARTY_PH2 }, - { "MT_PH3", STREAMED_SOUND_CUTSCENE_MARTY_PH3 }, - { "MT_PH4", STREAMED_SOUND_CUTSCENE_MARTY_PH4 }, - { NULL, 0 } + { "ASS_1", STREAMED_SOUND_CUTSCENE_ASS_1 }, + { "ASS_2", STREAMED_SOUND_CUTSCENE_ASS_2 }, + { "BANK_1", STREAMED_SOUND_CUTSCENE_BANK_1 }, + { "BANK_2A", STREAMED_SOUND_CUTSCENE_BANK_2A }, + { "BANK_2B", STREAMED_SOUND_CUTSCENE_BANK_2B }, + { "BANK_3A", STREAMED_SOUND_CUTSCENE_BANK_3A }, + { "BANK_3B", STREAMED_SOUND_CUTSCENE_BANK_3B }, + { "BANK_4", STREAMED_SOUND_CUTSCENE_BANK_4 }, + { "BIKE_1", STREAMED_SOUND_CUTSCENE_BIKE_1 }, + { "BIKE_2", STREAMED_SOUND_CUTSCENE_BIKE_2 }, + { "BIKE_3", STREAMED_SOUND_CUTSCENE_BIKE_3 }, + { "BUD_1", STREAMED_SOUND_CUTSCENE_BUD_1 }, + { "BUD_2", STREAMED_SOUND_CUTSCENE_BUD_2 }, + { "BUD_3", STREAMED_SOUND_CUTSCENE_BUD_3 }, + { "CAP_1", STREAMED_SOUND_CUTSCENE_CAP_1 }, + { "CAR_1", STREAMED_SOUND_CUTSCENE_CAR_1 }, + { "CNT_1A", STREAMED_SOUND_CUTSCENE_CNT_1A }, + { "CNT_1B", STREAMED_SOUND_CUTSCENE_CNT_1B }, + { "CNT_2", STREAMED_SOUND_CUTSCENE_CNT_2 }, + { "COK_1", STREAMED_SOUND_CUTSCENE_COK_1 }, + { "COK_2A", STREAMED_SOUND_CUTSCENE_COK_2A }, + { "COK_2B", STREAMED_SOUND_CUTSCENE_COK_2B }, + { "COK_3", STREAMED_SOUND_CUTSCENE_COK_3 }, + { "COK_4A", STREAMED_SOUND_CUTSCENE_COK_4A }, + { "COK_4A2", STREAMED_SOUND_CUTSCENE_COK_4A2 }, + { "COK_4B", STREAMED_SOUND_CUTSCENE_COK_4B }, + { "COL_1", STREAMED_SOUND_CUTSCENE_COL_1 }, + { "COL_2", STREAMED_SOUND_CUTSCENE_COL_2 }, + { "COL_3A", STREAMED_SOUND_CUTSCENE_COL_3A }, + { "COL_4A", STREAMED_SOUND_CUTSCENE_COL_4A }, + { "COL_5A", STREAMED_SOUND_CUTSCENE_COL_5A }, + { "COL_5B", STREAMED_SOUND_CUTSCENE_COL_5B }, + { "CUB_1", STREAMED_SOUND_CUTSCENE_CUB_1 }, + { "CUB_2", STREAMED_SOUND_CUTSCENE_CUB_2 }, + { "CUB_3", STREAMED_SOUND_CUTSCENE_CUB_3 }, + { "CUB_4", STREAMED_SOUND_CUTSCENE_CUB_4 }, + { "DRUG_1", STREAMED_SOUND_CUTSCENE_DRUG_1 }, + { "FIN", STREAMED_SOUND_CUTSCENE_FIN }, + { "FIN_2", STREAMED_SOUND_CUTSCENE_FIN2 }, + { "FINALE", STREAMED_SOUND_CUTSCENE_FINALE }, + { "HAT_1", STREAMED_SOUND_CUTSCENE_HAT_1 }, + { "HAT_2", STREAMED_SOUND_CUTSCENE_HAT_2 }, + { "HAT_3", STREAMED_SOUND_CUTSCENE_HAT_3 }, + { "ICE_1", STREAMED_SOUND_CUTSCENE_ICE_1 }, + { "INT_A", STREAMED_SOUND_CUTSCENE_INT_A }, + { "INT_B", STREAMED_SOUND_CUTSCENE_INT_B }, + { "INT_D", STREAMED_SOUND_CUTSCENE_INT_D }, + { "INT_M", STREAMED_SOUND_CUTSCENE_INT_M }, + { "LAW_1A", STREAMED_SOUND_CUTSCENE_LAW_1A }, + { "LAW_1B", STREAMED_SOUND_CUTSCENE_LAW_1B }, + { "LAW_2A", STREAMED_SOUND_CUTSCENE_LAW_2A }, + { "LAW_2B", STREAMED_SOUND_CUTSCENE_LAW_2B }, + { "LAW_2C", STREAMED_SOUND_CUTSCENE_LAW_2C }, + { "LAW_3", STREAMED_SOUND_CUTSCENE_LAW_3 }, + { "LAW_4", STREAMED_SOUND_CUTSCENE_LAW_4 }, + { "PHIL_1", STREAMED_SOUND_CUTSCENE_PHIL_1 }, + { "PHIL_2", STREAMED_SOUND_CUTSCENE_PHIL_2 }, + { "PORN_1", STREAMED_SOUND_CUTSCENE_PORN_1 }, + { "PORN_2", STREAMED_SOUND_CUTSCENE_PORN_2 }, + { "PORN_3", STREAMED_SOUND_CUTSCENE_PORN_3 }, + { "PORN_4", STREAMED_SOUND_CUTSCENE_PORN_4 }, + { "RESC_1A", STREAMED_SOUND_CUTSCENE_RESC_1A }, + { "ROK_1", STREAMED_SOUND_CUTSCENE_ROK_1 }, + { "ROK_2", STREAMED_SOUND_CUTSCENE_ROK_2 }, + { "ROK_3A", STREAMED_SOUND_CUTSCENE_ROK_3A }, + { "STRIPA", STREAMED_SOUND_CUTSCENE_STRIPA }, + { "TAX_1", STREAMED_SOUND_CUTSCENE_TAX_1 }, + { "TEX_1", STREAMED_SOUND_CUTSCENE_TEX_1 }, + { "TEX_2", STREAMED_SOUND_CUTSCENE_TEX_2 }, + { "TEX_3", STREAMED_SOUND_CUTSCENE_TEX_3 }, + { "GSPOT", STREAMED_SOUND_CUTSCENE_GLIGHT }, + { "FIST", STREAMED_SOUND_CUTSCENE_FIST }, + { "EL_PH1", STREAMED_SOUND_CUTSCENE_ELBURRO1_PH1 }, + { "EL_PH2", STREAMED_SOUND_CUTSCENE_ELBURRO2_PH2 }, + { NULL, 0 } }; int @@ -128,7 +126,18 @@ char CCutsceneMgr::ms_cutsceneName[CUTSCENENAMESIZE]; CAnimBlendAssocGroup CCutsceneMgr::ms_cutsceneAssociations; CVector CCutsceneMgr::ms_cutsceneOffset; float CCutsceneMgr::ms_cutsceneTimer; +bool CCutsceneMgr::ms_wasCutsceneSkipped; uint32 CCutsceneMgr::ms_cutsceneLoadStatus; +bool CCutsceneMgr::ms_useCutsceneShadows = true; + +bool bCamLoaded; +bool bIsEverythingRemovedFromTheWorldForTheBiggestFuckoffCutsceneEver; // pls don't shrink the name :P +int32 NumberOfSavedWeapons; +eWeaponType SavedWeaponIDs[TOTAL_WEAPON_SLOTS]; +int32 SavedWeaponAmmo[TOTAL_WEAPON_SLOTS]; +char uncompressedAnims[8][32]; +uint32 numUncompressedAnims; + RpAtomic * CalculateBoundingSphereRadiusCB(RpAtomic *atomic, void *data) @@ -150,13 +159,17 @@ CCutsceneMgr::Initialise(void) { ms_numCutsceneObjs = 0; ms_loaded = false; + ms_wasCutsceneSkipped = false; ms_running = false; + ms_useLodMultiplier = false; ms_animLoaded = false; ms_cutsceneProcessing = false; - ms_useLodMultiplier = false; ms_pCutsceneDir = new CDirectory(CUTSCENEDIRSIZE); ms_pCutsceneDir->ReadDirFile("ANIM\\CUTS.DIR"); + + numUncompressedAnims = 0; + uncompressedAnims[0][0] = '\0'; } void @@ -174,9 +187,10 @@ CCutsceneMgr::LoadCutsceneData(const char *szCutsceneName) CPlayerPed *pPlayerPed; ms_cutsceneProcessing = true; - if (!strcasecmp(szCutsceneName, "jb")) - ms_useLodMultiplier = true; - CTimer::Stop(); + ms_wasCutsceneSkipped = false; + CTimer::Suspend(); + if (!bIsEverythingRemovedFromTheWorldForTheBiggestFuckoffCutsceneEver) + CStreaming::RemoveCurrentZonesModels(); ms_pCutsceneDir->numEntries = 0; ms_pCutsceneDir->ReadDirFile("ANIM\\CUTS.DIR"); @@ -185,32 +199,42 @@ CCutsceneMgr::LoadCutsceneData(const char *szCutsceneName) CGame::DrasticTidyUpMemory(true); strcpy(ms_cutsceneName, szCutsceneName); - file = CFileMgr::OpenFile("ANIM\\CUTS.IMG", "rb"); + + RwStream *stream; + stream = RwStreamOpen(rwSTREAMFILENAME, rwSTREAMREAD, "ANIM\\CUTS.IMG"); + assert(stream); // Load animations sprintf(gString, "%s.IFP", szCutsceneName); if (ms_pCutsceneDir->FindItem(gString, offset, size)) { CStreaming::MakeSpaceFor(size << 11); CStreaming::ImGonnaUseStreamingMemory(); - CFileMgr::Seek(file, offset << 11, SEEK_SET); - CAnimManager::LoadAnimFile(file, false); + RwStreamSkip(stream, offset << 11); + CAnimManager::LoadAnimFile(stream, true, uncompressedAnims); ms_cutsceneAssociations.CreateAssociations(szCutsceneName); CStreaming::IHaveUsedStreamingMemory(); ms_animLoaded = true; } else { ms_animLoaded = false; } + RwStreamClose(stream, nil); // Load camera data + file = CFileMgr::OpenFile("ANIM\\CUTS.IMG", "rb"); sprintf(gString, "%s.DAT", szCutsceneName); if (ms_pCutsceneDir->FindItem(gString, offset, size)) { + CStreaming::ImGonnaUseStreamingMemory(); CFileMgr::Seek(file, offset << 11, SEEK_SET); TheCamera.LoadPathSplines(file); + CStreaming::IHaveUsedStreamingMemory(); + bCamLoaded = true; + } else { + bCamLoaded = false; } CFileMgr::CloseFile(file); - if (CGeneral::faststricmp(ms_cutsceneName, "end")) { + if (CGeneral::faststricmp(ms_cutsceneName, "finale")) { DMAudio.ChangeMusicMode(MUSICMODE_CUTSCENE); int trackId = FindCutsceneAudioTrackId(szCutsceneName); if (trackId != -1) { @@ -225,30 +249,23 @@ CCutsceneMgr::LoadCutsceneData(const char *szCutsceneName) ms_cutsceneOffset = CVector(0.0f, 0.0f, 0.0f); pPlayerPed = FindPlayerPed(); - CTimer::Update(); - pPlayerPed->m_pWanted->ClearQdCrimes(); pPlayerPed->bIsVisible = false; pPlayerPed->m_fCurrentStamina = pPlayerPed->m_fMaxStamina; CPad::GetPad(0)->SetDisablePlayerControls(PLAYERCONTROL_CUTSCENE); CWorld::Players[CWorld::PlayerInFocus].MakePlayerSafe(true); -} - -void -CCutsceneMgr::SetHeadAnim(const char *animName, CObject *pObject) -{ - CCutsceneHead *pCutsceneHead = (CCutsceneHead*)pObject; - char szAnim[CUTSCENENAMESIZE * 2]; - sprintf(szAnim, "%s_%s", ms_cutsceneName, animName); - pCutsceneHead->PlayAnimation(szAnim); + CTimer::Resume(); } void CCutsceneMgr::FinishCutscene() { - CCutsceneMgr::ms_cutsceneTimer = TheCamera.GetCutSceneFinishTime() * 0.001f; - TheCamera.FinishCutscene(); + ms_wasCutsceneSkipped = true; + if (bCamLoaded) { + CCutsceneMgr::ms_cutsceneTimer = TheCamera.GetCutSceneFinishTime() * 0.001f; + TheCamera.FinishCutscene(); + } FindPlayerPed()->bIsVisible = true; CWorld::Players[CWorld::PlayerInFocus].MakePlayerSafe(false); @@ -257,9 +274,11 @@ CCutsceneMgr::FinishCutscene() void CCutsceneMgr::SetupCutsceneToStart(void) { - TheCamera.SetCamCutSceneOffSet(ms_cutsceneOffset); - TheCamera.TakeControlWithSpline(JUMP_CUT); - TheCamera.SetWideScreenOn(); + if (bCamLoaded) { + TheCamera.SetCamCutSceneOffSet(ms_cutsceneOffset); + TheCamera.TakeControlWithSpline(JUMP_CUT); + TheCamera.SetWideScreenOn(); + } ms_cutsceneOffset.z++; @@ -267,12 +286,27 @@ CCutsceneMgr::SetupCutsceneToStart(void) assert(RwObjectGetType(ms_pCutsceneObjects[i]->m_rwObject) == rpCLUMP); if (CAnimBlendAssociation *pAnimBlendAssoc = RpAnimBlendClumpGetFirstAssociation((RpClump*)ms_pCutsceneObjects[i]->m_rwObject)) { assert(pAnimBlendAssoc->hierarchy->sequences[0].HasTranslation()); - ms_pCutsceneObjects[i]->SetPosition(ms_cutsceneOffset + ((KeyFrameTrans*)pAnimBlendAssoc->hierarchy->sequences[0].GetKeyFrame(0))->translation); - CWorld::Add(ms_pCutsceneObjects[i]); + if (ms_pCutsceneObjects[i]->m_pAttachTo != nil) { + pAnimBlendAssoc->flags &= (~ASSOC_HAS_TRANSLATION); + } else { + if (pAnimBlendAssoc->hierarchy->IsCompressed()){ + KeyFrameTransCompressed *keyFrames = ((KeyFrameTransCompressed*)pAnimBlendAssoc->hierarchy->sequences[0].GetKeyFrameCompressed(0)); + CVector trans; + keyFrames->GetTranslation(&trans); + ms_pCutsceneObjects[i]->SetPosition(ms_cutsceneOffset + trans); + }else{ + KeyFrameTrans *keyFrames = ((KeyFrameTrans*)pAnimBlendAssoc->hierarchy->sequences[0].GetKeyFrame(0)); + ms_pCutsceneObjects[i]->SetPosition(ms_cutsceneOffset + keyFrames->translation); + } + } pAnimBlendAssoc->SetRun(); } else { ms_pCutsceneObjects[i]->SetPosition(ms_cutsceneOffset); } + CWorld::Add(ms_pCutsceneObjects[i]); + if (RwObjectGetType(ms_pCutsceneObjects[i]->m_rwObject) == rpCLUMP) { + ms_pCutsceneObjects[i]->UpdateRpHAnim(); + } } CTimer::Update(); @@ -288,25 +322,55 @@ CCutsceneMgr::SetCutsceneAnim(const char *animName, CObject *pObject) CAnimBlendClumpData *pAnimBlendClumpData; assert(RwObjectGetType(pObject->m_rwObject) == rpCLUMP); + debug("Give cutscene anim %s\n", animName); RpAnimBlendClumpRemoveAllAssociations((RpClump*)pObject->m_rwObject); + pNewAnim = ms_cutsceneAssociations.GetAnimation(animName); + if (!pNewAnim) { + debug("\n\nHaven't I told you I can't find the fucking animation %s\n\n\n", animName); + return; + } + + if (pNewAnim->hierarchy->IsCompressed()) + pNewAnim->hierarchy->keepCompressed = true; + + CStreaming::ImGonnaUseStreamingMemory(); pNewAnim = ms_cutsceneAssociations.CopyAnimation(animName); + CStreaming::IHaveUsedStreamingMemory(); + pNewAnim->SetCurrentTime(0.0f); pNewAnim->flags |= ASSOC_HAS_TRANSLATION; pNewAnim->flags &= ~ASSOC_RUNNING; pAnimBlendClumpData = *RPANIMBLENDCLUMPDATA(pObject->m_rwObject); pAnimBlendClumpData->link.Prepend(&pNewAnim->link); + + if (pNewAnim->hierarchy->keepCompressed) + pAnimBlendClumpData->frames->flag |= AnimBlendFrameData::COMPRESSED; +} + +void +CCutsceneMgr::SetCutsceneAnimToLoop(const char* animName) +{ + ms_cutsceneAssociations.GetAnimation(animName)->flags |= ASSOC_REPEAT; } CCutsceneHead * CCutsceneMgr::AddCutsceneHead(CObject *pObject, int modelId) { - CCutsceneHead *pHead = new CCutsceneHead(pObject); - pHead->SetModelIndex(modelId); - CWorld::Add(pHead); - ms_pCutsceneObjects[ms_numCutsceneObjs++] = pHead; - return pHead; + return nil; +} + +void UpdateCutsceneObjectBoundingBox(RpClump* clump, int modelId) +{ + if (modelId >= MI_CUTOBJ01 && modelId <= MI_CUTOBJ05) { + CColModel* pColModel = &CTempColModels::ms_colModelCutObj[modelId - MI_CUTOBJ01]; + float radius = 0.0f; + RpClumpForAllAtomics(clump, CalculateBoundingSphereRadiusCB, &radius); + pColModel->boundingSphere.radius = radius; + pColModel->boundingBox.min = CVector(-radius, -radius, -radius); + pColModel->boundingBox.max = CVector(radius, radius, radius); + } } CCutsceneObject * @@ -314,20 +378,25 @@ CCutsceneMgr::CreateCutsceneObject(int modelId) { CBaseModelInfo *pModelInfo; CColModel *pColModel; - float radius; - RpClump *clump; CCutsceneObject *pCutsceneObject; + CStreaming::ImGonnaUseStreamingMemory(); + debug("Created cutscene object %s\n", CModelInfo::GetModelInfo(modelId)->GetModelName()); if (modelId >= MI_CUTOBJ01 && modelId <= MI_CUTOBJ05) { pModelInfo = CModelInfo::GetModelInfo(modelId); pColModel = &CTempColModels::ms_colModelCutObj[modelId - MI_CUTOBJ01]; - radius = 0.0f; - pModelInfo->SetColModel(pColModel); - clump = (RpClump*)pModelInfo->GetRwObject(); - assert(RwObjectGetType((RwObject*)clump) == rpCLUMP); - RpClumpForAllAtomics(clump, CalculateBoundingSphereRadiusCB, &radius); - + UpdateCutsceneObjectBoundingBox((RpClump*)pModelInfo->GetRwObject(), modelId); + } else if (modelId >= MI_SPECIAL01 && modelId <= MI_SPECIAL21) { + pModelInfo = CModelInfo::GetModelInfo(modelId); + if (pModelInfo->GetColModel() == &CTempColModels::ms_colModelPed1) { + CColModel *colModel = new CColModel(); + colModel->boundingSphere.radius = 2.0f; + colModel->boundingSphere.center = CVector(0.0f, 0.0f, 0.0f); + pModelInfo->SetColModel(colModel, true); + } + pColModel = pModelInfo->GetColModel(); + float radius = 2.0f; pColModel->boundingSphere.radius = radius; pColModel->boundingBox.min = CVector(-radius, -radius, -radius); pColModel->boundingBox.max = CVector(radius, radius, radius); @@ -335,7 +404,10 @@ CCutsceneMgr::CreateCutsceneObject(int modelId) pCutsceneObject = new CCutsceneObject(); pCutsceneObject->SetModelIndex(modelId); + if (ms_useCutsceneShadows) + pCutsceneObject->CreateShadow(); ms_pCutsceneObjects[ms_numCutsceneObjs++] = pCutsceneObject; + CStreaming::IHaveUsedStreamingMemory(); return pCutsceneObject; } @@ -343,9 +415,11 @@ void CCutsceneMgr::DeleteCutsceneData(void) { if (!ms_loaded) return; + CTimer::Suspend(); ms_cutsceneProcessing = false; ms_useLodMultiplier = false; + ms_useCutsceneShadows = true; for (--ms_numCutsceneObjs; ms_numCutsceneObjs >= 0; ms_numCutsceneObjs--) { CWorld::Remove(ms_pCutsceneObjects[ms_numCutsceneObjs]); @@ -355,12 +429,27 @@ CCutsceneMgr::DeleteCutsceneData(void) } ms_numCutsceneObjs = 0; + for (int i = MI_SPECIAL01; i < MI_SPECIAL21; i++) { + CBaseModelInfo *minfo = CModelInfo::GetModelInfo(i); + CColModel *colModel = minfo->GetColModel(); + if (colModel != &CTempColModels::ms_colModelPed1) { + delete colModel; + minfo->SetColModel(&CTempColModels::ms_colModelPed1); + } + } + if (ms_animLoaded) CAnimManager::RemoveLastAnimFile(); ms_animLoaded = false; - TheCamera.RestoreWithJumpCut(); - TheCamera.SetWideScreenOff(); + numUncompressedAnims = 0; + uncompressedAnims[0][0] = '\0'; + + if (bCamLoaded) { + TheCamera.RestoreWithJumpCut(); + TheCamera.SetWideScreenOff(); + TheCamera.DeleteCutSceneCamDataMemory(); + } ms_running = false; ms_loaded = false; @@ -368,14 +457,42 @@ CCutsceneMgr::DeleteCutsceneData(void) CPad::GetPad(0)->SetEnablePlayerControls(PLAYERCONTROL_CUTSCENE); CWorld::Players[CWorld::PlayerInFocus].MakePlayerSafe(false); - if (CGeneral::faststricmp(ms_cutsceneName, "end")) { + if (CGeneral::faststricmp(ms_cutsceneName, "finale")) { DMAudio.StopCutSceneMusic(); - if (CGeneral::faststricmp(ms_cutsceneName, "bet")) - DMAudio.ChangeMusicMode(MUSICMODE_GAME); + DMAudio.ChangeMusicMode(MUSICMODE_GAME); } - CTimer::Stop(); - CGame::DrasticTidyUpMemory(TheCamera.GetScreenFadeStatus() == FADE_2); - CTimer::Update(); + + CStreaming::ms_disableStreaming = false; + CWorld::bProcessCutsceneOnly = false; + + if(bCamLoaded) + CGame::DrasticTidyUpMemory(TheCamera.GetScreenFadeStatus() == FADE_2); + + CPad::GetPad(0)->Clear(false); + if (bIsEverythingRemovedFromTheWorldForTheBiggestFuckoffCutsceneEver) { + CStreaming::LoadInitialPeds(); + CStreaming::LoadInitialWeapons(); + CStreaming::LoadInitialVehicles(); + bIsEverythingRemovedFromTheWorldForTheBiggestFuckoffCutsceneEver = false; + + CPlayerPed *pPlayerPed = FindPlayerPed(); + for (int i = 0; i < NumberOfSavedWeapons; i++) { + int32 weaponModelId = CWeaponInfo::GetWeaponInfo(SavedWeaponIDs[i])->m_nModelId; + uint8 flags = CStreaming::ms_aInfoForModel[weaponModelId].m_flags; + CStreaming::RequestModel(weaponModelId, STREAMFLAGS_DONT_REMOVE); + CStreaming::LoadAllRequestedModels(false); + if (CWeaponInfo::GetWeaponInfo(SavedWeaponIDs[i])->m_nModel2Id != -1) { + CStreaming::RequestModel(CWeaponInfo::GetWeaponInfo(SavedWeaponIDs[i])->m_nModel2Id, 0); + CStreaming::LoadAllRequestedModels(false); + } + if (!(flags & STREAMFLAGS_DONT_REMOVE)) + CStreaming::SetModelIsDeletable(weaponModelId); + pPlayerPed->GiveWeapon(SavedWeaponIDs[i], SavedWeaponAmmo[i], true); + } + NumberOfSavedWeapons = 0; + } + + CTimer::Resume(); } void @@ -392,7 +509,7 @@ CCutsceneMgr::Update(void) switch (ms_cutsceneLoadStatus) { case CUTSCENE_LOADING_AUDIO: SetupCutsceneToStart(); - if (CGeneral::faststricmp(ms_cutsceneName, "end")) + if (CGeneral::faststricmp(ms_cutsceneName, "finale")) DMAudio.PlayPreloadedCutSceneMusic(); ms_cutsceneLoadStatus++; break; @@ -410,15 +527,157 @@ CCutsceneMgr::Update(void) if (!ms_running) return; ms_cutsceneTimer += CTimer::GetTimeStepNonClippedInSeconds(); - if (CGeneral::faststricmp(ms_cutsceneName, "end") && TheCamera.Cams[TheCamera.ActiveCam].Mode == CCam::MODE_FLYBY && ms_cutsceneLoadStatus == CUTSCENE_LOADING_0) { - if (CPad::GetPad(0)->GetCrossJustDown() - || (CGame::playingIntro && CPad::GetPad(0)->GetStartJustDown()) - || CPad::GetPad(0)->GetLeftMouseJustDown() - || CPad::GetPad(0)->GetEnterJustDown() - || CPad::GetPad(0)->GetCharJustDown(' ')) - FinishCutscene(); + + for (int i = 0; i < ms_numCutsceneObjs; i++) { + int modelId = ms_pCutsceneObjects[i]->GetModelIndex(); + if (modelId >= MI_CUTOBJ01 && modelId <= MI_CUTOBJ05) + UpdateCutsceneObjectBoundingBox(ms_pCutsceneObjects[i]->GetClump(), modelId); + + if (ms_pCutsceneObjects[i]->m_pAttachTo != nil && modelId >= MI_SPECIAL01 && modelId <= MI_SPECIAL21) + UpdateCutsceneObjectBoundingBox(ms_pCutsceneObjects[i]->GetClump(), modelId); } + + if (bCamLoaded) + if (CGeneral::faststricmp(ms_cutsceneName, "finale") && TheCamera.Cams[TheCamera.ActiveCam].Mode == CCam::MODE_FLYBY && ms_cutsceneLoadStatus == CUTSCENE_LOADING_0) { + if (CPad::GetPad(0)->GetCrossJustDown() + || (CGame::playingIntro && CPad::GetPad(0)->GetStartJustDown()) + || CPad::GetPad(0)->GetLeftMouseJustDown() + || CPad::GetPad(0)->GetEnterJustDown() + || CPad::GetPad(0)->GetCharJustDown(' ')) + FinishCutscene(); + } } -bool CCutsceneMgr::HasCutsceneFinished(void) { return TheCamera.GetPositionAlongSpline() == 1.0f; } +bool CCutsceneMgr::HasCutsceneFinished(void) { return !bCamLoaded || TheCamera.GetPositionAlongSpline() == 1.0f; } + +void +CCutsceneMgr::LoadAnimationUncompressed(char const* name) +{ + strcpy(uncompressedAnims[numUncompressedAnims], name); + + // Because that's how CAnimManager knows the end of array + ++numUncompressedAnims; + assert(numUncompressedAnims < ARRAY_SIZE(uncompressedAnims)); + uncompressedAnims[numUncompressedAnims][0] = '\0'; +} +void +CCutsceneMgr::AttachObjectToParent(CObject *pObject, CEntity *pAttachTo) +{ + ((CCutsceneObject*)pObject)->m_pAttachmentObject = nil; + ((CCutsceneObject*)pObject)->m_pAttachTo = RpClumpGetFrame(pAttachTo->GetClump()); + + debug("Attach %s to %s\n", CModelInfo::GetModelInfo(pObject->GetModelIndex())->GetModelName(), CModelInfo::GetModelInfo(pAttachTo->GetModelIndex())->GetModelName()); +} + +void +CCutsceneMgr::AttachObjectToFrame(CObject *pObject, CEntity *pAttachTo, const char *frame) +{ + ((CCutsceneObject*)pObject)->m_pAttachmentObject = nil; + ((CCutsceneObject*)pObject)->m_pAttachTo = RpAnimBlendClumpFindFrame(pAttachTo->GetClump(), frame)->frame; + debug("Attach %s to component %s of %s\n", + CModelInfo::GetModelInfo(pObject->GetModelIndex())->GetModelName(), + frame, + CModelInfo::GetModelInfo(pAttachTo->GetModelIndex())->GetModelName()); + if (RwObjectGetType(pObject->m_rwObject) == rpCLUMP) { + RpClump *clump = (RpClump*)pObject->m_rwObject; + if (IsClumpSkinned(clump)) + RpAtomicGetBoundingSphere(GetFirstAtomic(clump))->radius *= 1.1f; + } +} + +void +CCutsceneMgr::AttachObjectToBone(CObject *pObject, CObject *pAttachTo, int bone) +{ + RpHAnimHierarchy *hanim = GetAnimHierarchyFromSkinClump(pAttachTo->GetClump()); + RwInt32 id = RpHAnimIDGetIndex(hanim, bone); + RwMatrix *matrixArray = RpHAnimHierarchyGetMatrixArray(hanim); + ((CCutsceneObject*)pObject)->m_pAttachmentObject = pAttachTo; + ((CCutsceneObject*)pObject)->m_pAttachTo = &matrixArray[id]; + debug("Attach %s to %s\n", + CModelInfo::GetModelInfo(pObject->GetModelIndex())->GetModelName(), + CModelInfo::GetModelInfo(pAttachTo->GetModelIndex())->GetModelName()); +} + +void +CCutsceneMgr::RemoveEverythingFromTheWorldForTheBiggestFuckoffCutsceneEver() +{ + CStreaming::ms_disableStreaming = true; + CColStore::RemoveAllCollision(); + CWorld::bProcessCutsceneOnly = true; + ms_cutsceneProcessing = true; + + for (int i = CPools::GetPedPool()->GetSize() - 1; i >= 0; i--) { + CPed *pPed = CPools::GetPedPool()->GetSlot(i); + if (pPed) { + if (!pPed->IsPlayer() && pPed->CanBeDeleted()) { + CWorld::Remove(pPed); + delete pPed; + } + } + } + + for (int i = CPools::GetVehiclePool()->GetSize() - 1; i >= 0; i--) { + CVehicle *pVehicle = CPools::GetVehiclePool()->GetSlot(i); + if (pVehicle) { + if (pVehicle->CanBeDeleted()) { + CWorld::Remove(pVehicle); + delete pVehicle; + } + } + } + + bIsEverythingRemovedFromTheWorldForTheBiggestFuckoffCutsceneEver = true; + CStreaming::RemoveCurrentZonesModels(); + CStreaming::SetModelIsDeletable(MI_MALE01); + CStreaming::SetModelTxdIsDeletable(MI_MALE01); + CStreaming::SetModelIsDeletable(MI_TAXI_D); + CStreaming::SetModelTxdIsDeletable(MI_TAXI_D); + CStreaming::SetModelIsDeletable(MI_NIGHTSTICK); + CStreaming::SetModelTxdIsDeletable(MI_NIGHTSTICK); + CStreaming::SetModelIsDeletable(MI_MISSILE); + CStreaming::SetModelTxdIsDeletable(MI_MISSILE); + CStreaming::SetModelIsDeletable(MI_POLICE); + CStreaming::SetModelTxdIsDeletable(MI_POLICE); + + while (CStreaming::RemoveLoadedVehicle()) ; + + CRadar::RemoveRadarSections(); + + for (int i = CPools::GetDummyPool()->GetSize() - 1; i >= 0; i--) { + CDummy* pDummy = CPools::GetDummyPool()->GetSlot(i); + if (pDummy) + pDummy->DeleteRwObject(); + } + + for (int i = CPools::GetObjectPool()->GetSize() - 1; i >= 0; i--) { + CObject* pObject = CPools::GetObjectPool()->GetSlot(i); + if (pObject) + pObject->DeleteRwObject(); + } + + for (int i = CPools::GetBuildingPool()->GetSize() - 1; i >= 0; i--) { + CBuilding* pBuilding = CPools::GetBuildingPool()->GetSlot(i); + if (pBuilding && pBuilding->m_rwObject != nil && pBuilding->bIsBIGBuilding && pBuilding->bStreamBIGBuilding) { + if (pBuilding->bIsBIGBuilding) + CStreaming::RequestModel(pBuilding->GetModelIndex(), 0); + if (!pBuilding->bImBeingRendered) + pBuilding->DeleteRwObject(); + } + } + + CPlayerPed *pPlayerPed = FindPlayerPed(); + pPlayerPed->RemoveWeaponAnims(0, -1000.0f); + NumberOfSavedWeapons = 0; + + for (int i = 0; i < TOTAL_WEAPON_SLOTS; i++) { + if (pPlayerPed->m_weapons[i].m_eWeaponType != WEAPONTYPE_UNARMED) { + SavedWeaponIDs[NumberOfSavedWeapons] = pPlayerPed->m_weapons[i].m_eWeaponType; + SavedWeaponAmmo[NumberOfSavedWeapons] = pPlayerPed->m_weapons[i].m_nAmmoTotal; + NumberOfSavedWeapons++; + } + } + + pPlayerPed->ClearWeapons(); + CGame::DrasticTidyUpMemory(true); +}
\ No newline at end of file diff --git a/src/animation/CutsceneMgr.h b/src/animation/CutsceneMgr.h index bfdcdb57..51ef6c04 100644 --- a/src/animation/CutsceneMgr.h +++ b/src/animation/CutsceneMgr.h @@ -21,7 +21,9 @@ class CCutsceneMgr static CAnimBlendAssocGroup ms_cutsceneAssociations; static CVector ms_cutsceneOffset; static float ms_cutsceneTimer; + static bool ms_wasCutsceneSkipped; static bool ms_cutsceneProcessing; + static bool ms_useCutsceneShadows; public: static CDirectory *ms_pCutsceneDir; static uint32 ms_cutsceneLoadStatus; @@ -30,6 +32,7 @@ public: static bool IsRunning(void) { return ms_running; } static bool HasLoaded(void) { return ms_loaded; } static bool IsCutsceneProcessing(void) { return ms_cutsceneProcessing; } + static bool WasCutsceneSkipped(void) { return ms_wasCutsceneSkipped; } static bool UseLodMultiplier(void) { return ms_useLodMultiplier; } static CCutsceneObject* GetCutsceneObject(int id) { return ms_pCutsceneObjects[id]; } static int GetCutsceneTimeInMilleseconds(void) { return 1000.0f * ms_cutsceneTimer; } @@ -41,11 +44,18 @@ public: static void Shutdown(void); static void LoadCutsceneData(const char *szCutsceneName); static void FinishCutscene(void); - static void SetHeadAnim(const char *animName, CObject *pObject); static void SetupCutsceneToStart(void); static void SetCutsceneAnim(const char *animName, CObject *pObject); + static void SetCutsceneAnimToLoop(const char *animName); static CCutsceneHead *AddCutsceneHead(CObject *pObject, int modelId); static CCutsceneObject *CreateCutsceneObject(int modelId); static void DeleteCutsceneData(void); + static void LoadAnimationUncompressed(char const*); static void Update(void); + + static void AttachObjectToParent(CObject *pObject, CEntity *pAttachTo); + static void AttachObjectToFrame(CObject *pObject, CEntity *pAttachTo, const char *frame); + static void AttachObjectToBone(CObject *pObject, CObject *pAttachTo, int frame); + static void RemoveEverythingFromTheWorldForTheBiggestFuckoffCutsceneEver(); + static void DisableCutsceneShadows() { ms_useCutsceneShadows = false; } }; diff --git a/src/animation/FrameUpdate.cpp b/src/animation/FrameUpdate.cpp index c7d347b3..d3094bb0 100644 --- a/src/animation/FrameUpdate.cpp +++ b/src/animation/FrameUpdate.cpp @@ -17,6 +17,8 @@ void FrameUpdateCallBackSkinned(AnimBlendFrameData *frame, void *arg); void FrameUpdateCallBackWithVelocityExtractionSkinned(AnimBlendFrameData *frame, void *arg); void FrameUpdateCallBackWith3dVelocityExtractionSkinned(AnimBlendFrameData *frame, void *arg); +void FrameUpdateCallBackNonSkinnedCompressed(AnimBlendFrameData *frame, void *arg); +void FrameUpdateCallBackSkinnedCompressed(AnimBlendFrameData *frame, void *arg); void FrameUpdateCallBackNonSkinned(AnimBlendFrameData *frame, void *arg) @@ -228,12 +230,11 @@ FrameUpdateCallBackWith3dVelocityExtractionNonSkinned(AnimBlendFrameData *frame, RwMatrixUpdate(mat); } -#ifdef PED_SKIN - void FrameUpdateCallBackSkinned(AnimBlendFrameData *frame, void *arg) { CVector vec, pos(0.0f, 0.0f, 0.0f); + float transBlendAmount = 0.0f; CQuaternion q, rot(0.0f, 0.0f, 0.0f, 0.0f); float totalBlendAmount = 0.0f; RpHAnimStdInterpFrame *xform = frame->hanimFrame; @@ -257,13 +258,13 @@ FrameUpdateCallBackSkinned(AnimBlendFrameData *frame, void *arg) for(node = updateData->nodes; *node; node++){ if((*node)->sequence){ (*node)->Update(vec, q, 1.0f-totalBlendAmount); - if((*node)->sequence->HasTranslation()) + if((*node)->sequence->HasTranslation()){ pos += vec; -#ifdef FIX_BUGS + transBlendAmount += (*node)->association->blendAmount; + } if(DotProduct(rot, q) < 0.0f) rot -= q; else -#endif rot += q; } ++*node; @@ -278,12 +279,12 @@ FrameUpdateCallBackSkinned(AnimBlendFrameData *frame, void *arg) } if((frame->flag & AnimBlendFrameData::IGNORE_TRANSLATION) == 0){ - xform->t.x = pos.x; - xform->t.y = pos.y; - xform->t.z = pos.z; - xform->t.x += frame->resetPos.x; - xform->t.y += frame->resetPos.y; - xform->t.z += frame->resetPos.z; + xform->t.x = transBlendAmount*pos.x; + xform->t.y = transBlendAmount*pos.y; + xform->t.z = transBlendAmount*pos.z; + xform->t.x += (1.0f-transBlendAmount)*frame->resetPos.x; + xform->t.y += (1.0f-transBlendAmount)*frame->resetPos.y; + xform->t.z += (1.0f-transBlendAmount)*frame->resetPos.z; } } @@ -319,11 +320,9 @@ FrameUpdateCallBackWithVelocityExtractionSkinned(AnimBlendFrameData *frame, void for(node = updateData->nodes; *node; node++){ if((*node)->sequence){ bool nodelooped = (*node)->Update(vec, q, 1.0f-totalBlendAmount); -#ifdef FIX_BUGS if(DotProduct(rot, q) < 0.0f) rot -= q; else -#endif rot += q; if((*node)->sequence->HasTranslation()){ pos += vec; @@ -442,4 +441,228 @@ FrameUpdateCallBackWith3dVelocityExtractionSkinned(AnimBlendFrameData *frame, vo } } +void +FrameUpdateCallBackOffscreen(AnimBlendFrameData *frame, void *arg) +{ + if(frame->flag & AnimBlendFrameData::VELOCITY_EXTRACTION && gpAnimBlendClump->velocity2d) + FrameUpdateCallBackWithVelocityExtractionSkinned(frame, arg); +} + + +void +FrameUpdateCallBackNonSkinnedCompressed(AnimBlendFrameData *frame, void *arg) +{ + CVector vec, pos(0.0f, 0.0f, 0.0f); + CQuaternion q, rot(0.0f, 0.0f, 0.0f, 0.0f); + float totalBlendAmount = 0.0f; + CVector trans(0.0f, 0.0f, 0.0f); + CVector cur(0.0f, 0.0f, 0.0f); + CVector end(0.0f, 0.0f, 0.0f); + bool looped = false; + RwMatrix *mat = RwFrameGetMatrix(frame->frame); + CAnimBlendNode **node; + AnimBlendFrameUpdateData *updateData = (AnimBlendFrameUpdateData*)arg; + + if(frame->flag & AnimBlendFrameData::VELOCITY_EXTRACTION && + gpAnimBlendClump->velocity2d){ + if(updateData->foobar) + for(node = updateData->nodes; *node; node++) + if((*node)->sequence && (*node)->association->IsPartial()) + totalBlendAmount += (*node)->association->blendAmount; + + for(node = updateData->nodes; *node; node++) + if((*node)->sequence && (*node)->sequence->HasTranslation()){ + if((*node)->association->HasTranslation()){ + (*node)->GetCurrentTranslationCompressed(vec, 1.0f-totalBlendAmount); + cur += vec; + } + } + + for(node = updateData->nodes; *node; node++){ + if((*node)->sequence){ + bool nodelooped = (*node)->UpdateCompressed(vec, q, 1.0f-totalBlendAmount); +#ifdef FIX_BUGS + if(DotProduct(rot, q) < 0.0f) + rot -= q; + else +#endif + rot += q; + if((*node)->sequence->HasTranslation()){ + pos += vec; + if((*node)->association->HasTranslation()){ + trans += vec; + looped |= nodelooped; + if(nodelooped){ + (*node)->GetEndTranslationCompressed(vec, 1.0f-totalBlendAmount); + end += vec; + } + } + } + } + ++*node; + } + + if((frame->flag & AnimBlendFrameData::IGNORE_ROTATION) == 0){ + RwMatrixSetIdentity(mat); + rot.Normalise(); + rot.Get(mat); + } + + if((frame->flag & AnimBlendFrameData::IGNORE_TRANSLATION) == 0){ + *gpAnimBlendClump->velocity3d = trans - cur; + if(looped) + *gpAnimBlendClump->velocity3d += end; + mat->pos.x = (pos - trans).x + frame->resetPos.x; + mat->pos.y = (pos - trans).y + frame->resetPos.y; + mat->pos.z = (pos - trans).z + frame->resetPos.z; + } + RwMatrixUpdate(mat); + }else{ + if(updateData->foobar) + for(node = updateData->nodes; *node; node++) + if((*node)->sequence && (*node)->association->IsPartial()) + totalBlendAmount += (*node)->association->blendAmount; + + for(node = updateData->nodes; *node; node++){ + if((*node)->sequence){ + (*node)->UpdateCompressed(vec, q, 1.0f-totalBlendAmount); + if((*node)->sequence->HasTranslation()) + pos += vec; +#ifdef FIX_BUGS + if(DotProduct(rot, q) < 0.0f) + rot -= q; + else #endif + rot += q; + } + ++*node; + } + + if((frame->flag & AnimBlendFrameData::IGNORE_ROTATION) == 0){ + RwMatrixSetIdentity(mat); + rot.Normalise(); + rot.Get(mat); + } + + if((frame->flag & AnimBlendFrameData::IGNORE_TRANSLATION) == 0){ + mat->pos.x = pos.x; + mat->pos.y = pos.y; + mat->pos.z = pos.z; + mat->pos.x += frame->resetPos.x; + mat->pos.y += frame->resetPos.y; + mat->pos.z += frame->resetPos.z; + } + RwMatrixUpdate(mat); + } +} + +void +FrameUpdateCallBackSkinnedCompressed(AnimBlendFrameData *frame, void *arg) +{ + CVector vec, pos(0.0f, 0.0f, 0.0f); + CQuaternion q, rot(0.0f, 0.0f, 0.0f, 0.0f); + float totalBlendAmount = 0.0f; + CVector trans(0.0f, 0.0f, 0.0f); + CVector cur(0.0f, 0.0f, 0.0f); + CVector end(0.0f, 0.0f, 0.0f); + bool looped = false; + RpHAnimStdInterpFrame *xform = frame->hanimFrame; + CAnimBlendNode **node; + AnimBlendFrameUpdateData *updateData = (AnimBlendFrameUpdateData*)arg; + + if(frame->flag & AnimBlendFrameData::VELOCITY_EXTRACTION && + gpAnimBlendClump->velocity2d){ + if(updateData->foobar) + for(node = updateData->nodes; *node; node++) + if((*node)->sequence && (*node)->association->IsPartial()) + totalBlendAmount += (*node)->association->blendAmount; + + for(node = updateData->nodes; *node; node++) + if((*node)->sequence && (*node)->sequence->HasTranslation()){ + if((*node)->association->HasTranslation()){ + (*node)->GetCurrentTranslationCompressed(vec, 1.0f-totalBlendAmount); + cur += vec; + } + } + + for(node = updateData->nodes; *node; node++){ + if((*node)->sequence){ + bool nodelooped = (*node)->UpdateCompressed(vec, q, 1.0f-totalBlendAmount); +#ifdef FIX_BUGS + if(DotProduct(rot, q) < 0.0f) + rot -= q; + else +#endif + rot += q; + if((*node)->sequence->HasTranslation()){ + pos += vec; + if((*node)->association->HasTranslation()){ + trans += vec; + looped |= nodelooped; + if(nodelooped){ + (*node)->GetEndTranslationCompressed(vec, 1.0f-totalBlendAmount); + end += vec; + } + } + } + } + ++*node; + } + + if((frame->flag & AnimBlendFrameData::IGNORE_ROTATION) == 0){ + rot.Normalise(); + xform->q.imag.x = rot.x; + xform->q.imag.y = rot.y; + xform->q.imag.z = rot.z; + xform->q.real = rot.w; + } + + if((frame->flag & AnimBlendFrameData::IGNORE_TRANSLATION) == 0){ + *gpAnimBlendClump->velocity3d = trans - cur; + if(looped) + *gpAnimBlendClump->velocity3d += end; + xform->t.x = (pos - trans).x + frame->resetPos.x; + xform->t.y = (pos - trans).y + frame->resetPos.y; + xform->t.z = (pos - trans).z + frame->resetPos.z; + } + }else{ + float transBlendAmount = 0.0f; + + if(updateData->foobar) + for(node = updateData->nodes; *node; node++) + if((*node)->sequence && (*node)->association->IsPartial()) + totalBlendAmount += (*node)->association->blendAmount; + + for(node = updateData->nodes; *node; node++){ + if((*node)->sequence){ + (*node)->UpdateCompressed(vec, q, 1.0f-totalBlendAmount); + if((*node)->sequence->HasTranslation()){ + pos += vec; + transBlendAmount += (*node)->association->blendAmount; + } + if(DotProduct(rot, q) < 0.0f) + rot -= q; + else + rot += q; + } + ++*node; + } + + if((frame->flag & AnimBlendFrameData::IGNORE_ROTATION) == 0){ + rot.Normalise(); + xform->q.imag.x = rot.x; + xform->q.imag.y = rot.y; + xform->q.imag.z = rot.z; + xform->q.real = rot.w; + } + + if((frame->flag & AnimBlendFrameData::IGNORE_TRANSLATION) == 0){ + xform->t.x = transBlendAmount*pos.x; + xform->t.y = transBlendAmount*pos.y; + xform->t.z = transBlendAmount*pos.z; + xform->t.x += (1.0f-transBlendAmount)*frame->resetPos.x; + xform->t.y += (1.0f-transBlendAmount)*frame->resetPos.y; + xform->t.z += (1.0f-transBlendAmount)*frame->resetPos.z; + } + } +} diff --git a/src/animation/RpAnimBlend.cpp b/src/animation/RpAnimBlend.cpp index e430e52a..9a11d8bb 100644 --- a/src/animation/RpAnimBlend.cpp +++ b/src/animation/RpAnimBlend.cpp @@ -10,9 +10,7 @@ #include "AnimBlendAssociation.h" #include "AnimManager.h" #include "RpAnimBlend.h" -#ifdef PED_SKIN #include "PedModelInfo.h" -#endif RwInt32 ClumpOffset; @@ -142,7 +140,6 @@ FrameInitCBskin(AnimBlendFrameData *frameData, void*) frameData->flag = 0; } -#ifdef PED_SKIN void RpAnimBlendClumpInitSkinned(RpClump *clump) { @@ -156,7 +153,7 @@ RpAnimBlendClumpInitSkinned(RpClump *clump) RpAnimBlendAllocateData(clump); clumpData = *RPANIMBLENDCLUMPDATA(clump); - atomic = IsClumpSkinned(clump); + atomic = GetFirstAtomic(clump); assert(atomic); skin = RpSkinGeometryGetSkin(RpAtomicGetGeometry(atomic)); assert(skin); @@ -171,12 +168,15 @@ RpAnimBlendClumpInitSkinned(RpClump *clump) for(i = 0; i < numBones; i++){ frames[i].nodeID = HIERNODEID(hier, i); frames[i].resetPos = boneTab[i]; +#ifdef LIBRW frames[i].hanimFrame = (RpHAnimStdInterpFrame*)rpHANIMHIERARCHYGETINTERPFRAME(hier, i); +#else + frames[i].hanimFrame = (RpHAnimStdInterpFrame*)rtANIMGETINTERPFRAME(hier->currentAnim, i); +#endif } clumpData->ForAllFrames(FrameInitCBskin, nil); clumpData->frames[0].flag |= AnimBlendFrameData::VELOCITY_EXTRACTION; } -#endif void RpAnimBlendClumpInitNotSkinned(RpClump *clump) @@ -200,11 +200,9 @@ RpAnimBlendClumpInitNotSkinned(RpClump *clump) void RpAnimBlendClumpInit(RpClump *clump) { -#ifdef PED_SKIN if(IsClumpSkinned(clump)) RpAnimBlendClumpInitSkinned(clump); else -#endif RpAnimBlendClumpInitNotSkinned(clump); } @@ -364,7 +362,6 @@ FillFrameArrayCBnonskin(AnimBlendFrameData *frame, void *arg) frames[CVisibilityPlugins::GetFrameHierarchyId(frame->frame)] = frame; } -#ifdef PED_SKIN void RpAnimBlendClumpFillFrameArraySkin(RpClump *clump, AnimBlendFrameData **frames) { @@ -374,22 +371,18 @@ RpAnimBlendClumpFillFrameArraySkin(RpClump *clump, AnimBlendFrameData **frames) for(i = PED_MID; i < PED_NODE_MAX; i++) frames[i] = &clumpData->frames[RpHAnimIDGetIndex(hier, ConvertPedNode2BoneTag(i))]; } -#endif void RpAnimBlendClumpFillFrameArray(RpClump *clump, AnimBlendFrameData **frames) { -#ifdef PED_SKIN if(IsClumpSkinned(clump)) RpAnimBlendClumpFillFrameArraySkin(clump, frames); else -#endif (*RPANIMBLENDCLUMPDATA(clump))->ForAllFrames(FillFrameArrayCBnonskin, frames); } AnimBlendFrameData *pFrameDataFound; -// FrameFindCallBack on PS2 void FrameFindByNameCBnonskin(AnimBlendFrameData *frame, void *arg) { @@ -398,7 +391,6 @@ FrameFindByNameCBnonskin(AnimBlendFrameData *frame, void *arg) pFrameDataFound = frame; } -#ifdef PED_SKIN void FrameFindByNameCBskin(AnimBlendFrameData *frame, void *arg) { @@ -406,25 +398,58 @@ FrameFindByNameCBskin(AnimBlendFrameData *frame, void *arg) if(name && CGeneral::faststricmp(name, (char*)arg) == 0) pFrameDataFound = frame; } -#endif + +void +FrameFindByBoneCB(AnimBlendFrameData *frame, void *arg) +{ + if(frame->nodeID == (int32)(uintptr)arg) + pFrameDataFound = frame; +} AnimBlendFrameData* RpAnimBlendClumpFindFrame(RpClump *clump, const char *name) { pFrameDataFound = nil; -#ifdef PED_SKIN if(IsClumpSkinned(clump)) (*RPANIMBLENDCLUMPDATA(clump))->ForAllFrames(FrameFindByNameCBskin, (void*)name); else -#endif (*RPANIMBLENDCLUMPDATA(clump))->ForAllFrames(FrameFindByNameCBnonskin, (void*)name); return pFrameDataFound; } +AnimBlendFrameData* +RpAnimBlendClumpFindBone(RpClump *clump, uint32 boneTag) +{ + pFrameDataFound = nil; + (*RPANIMBLENDCLUMPDATA(clump))->ForAllFrames(FrameFindByBoneCB, (void*)boneTag); + return pFrameDataFound; +} + void -RpAnimBlendClumpUpdateAnimations(RpClump *clump, float timeDelta) +RpAnimBlendNodeUpdateKeyframes(AnimBlendFrameData *frames, AnimBlendFrameUpdateData *updateData, int32 numNodes) { + CAnimBlendNode **node; int i; + + for(node = updateData->nodes; *node; node++){ + CAnimBlendAssociation *a = (*node)->association; + for(i = 0; i < numNodes; i++) + if((frames[i].flag & AnimBlendFrameData::VELOCITY_EXTRACTION) == 0 || + gpAnimBlendClump->velocity2d == nil){ + if((*node)[i].sequence) + (*node)[i].FindKeyFrame(a->currentTime - a->timeStep); + } + } +} + +// TODO: +// CAnimBlendClumpData::LoadFramesIntoSPR +// CAnimBlendClumpData::ForAllFramesInSPR +void +RpAnimBlendClumpUpdateAnimations(RpClump *clump, float timeDelta, bool doRender) +{ + int i; + CAnimBlendAssociation *assoc; AnimBlendFrameUpdateData updateData; float totalLength = 0.0f; float totalBlend = 0.0f; @@ -440,30 +465,53 @@ RpAnimBlendClumpUpdateAnimations(RpClump *clump, float timeDelta) updateData.foobar = 0; for(link = clumpData->link.next; link; link = next){ next = link->next; - CAnimBlendAssociation *assoc = CAnimBlendAssociation::FromLink(link); + assoc = CAnimBlendAssociation::FromLink(link); if(assoc->UpdateBlend(timeDelta)){ - CAnimManager::UncompressAnimation(assoc->hierarchy); - updateData.nodes[i++] = assoc->GetNode(0); - if(assoc->flags & ASSOC_MOVEMENT){ - totalLength += assoc->hierarchy->totalLength/assoc->speed * assoc->blendAmount; - totalBlend += assoc->blendAmount; + if(assoc->hierarchy->sequences){ + CAnimManager::UncompressAnimation(assoc->hierarchy); + if(i < 11) + updateData.nodes[i++] = assoc->GetNode(0); + if(assoc->flags & ASSOC_MOVEMENT){ + totalLength += assoc->hierarchy->totalLength/assoc->speed * assoc->blendAmount; + totalBlend += assoc->blendAmount; + }else + updateData.foobar = 1; }else - updateData.foobar = 1; + debug("anim %s is not loaded\n", assoc->hierarchy->name); } } + + for(link = clumpData->link.next; link; link = link->next){ + assoc = CAnimBlendAssociation::FromLink(link); + assoc->UpdateTimeStep(timeDelta, totalLength == 0.0f ? 1.0f : totalBlend/totalLength); + } + updateData.nodes[i] = nil; -#ifdef PED_SKIN - if(IsClumpSkinned(clump)) - clumpData->ForAllFrames(FrameUpdateCallBackSkinned, &updateData); - else +#ifdef ANIM_COMPRESSION + if(clumpData->frames[0].flag & AnimBlendFrameData::COMPRESSED){ + if(IsClumpSkinned(clump)) + clumpData->ForAllFrames(FrameUpdateCallBackSkinnedCompressed, &updateData); + else + clumpData->ForAllFrames(FrameUpdateCallBackNonSkinnedCompressed, &updateData); + }else #endif - clumpData->ForAllFrames(FrameUpdateCallBackNonSkinned, &updateData); + if(doRender){ + if(clumpData->frames[0].flag & AnimBlendFrameData::UPDATE_KEYFRAMES) + RpAnimBlendNodeUpdateKeyframes(clumpData->frames, &updateData, clumpData->numFrames); + if(IsClumpSkinned(clump)) + clumpData->ForAllFrames(FrameUpdateCallBackSkinned, &updateData); + else + clumpData->ForAllFrames(FrameUpdateCallBackNonSkinned, &updateData); + clumpData->frames[0].flag &= ~AnimBlendFrameData::UPDATE_KEYFRAMES; + }else{ + clumpData->ForAllFrames(FrameUpdateCallBackOffscreen, &updateData); + clumpData->frames[0].flag |= AnimBlendFrameData::UPDATE_KEYFRAMES; + } for(link = clumpData->link.next; link; link = link->next){ - CAnimBlendAssociation *assoc = CAnimBlendAssociation::FromLink(link); - float relSpeed = totalLength == 0.0f ? 1.0f : totalBlend/totalLength; - assoc->UpdateTime(timeDelta, relSpeed); + assoc = CAnimBlendAssociation::FromLink(link); + assoc->UpdateTime(timeDelta, totalLength == 0.0f ? 1.0f : totalBlend/totalLength); } RwFrameUpdateObjects(RpClumpGetFrame(clump)); } diff --git a/src/animation/RpAnimBlend.h b/src/animation/RpAnimBlend.h index 838c8816..6e9e0f0f 100644 --- a/src/animation/RpAnimBlend.h +++ b/src/animation/RpAnimBlend.h @@ -26,6 +26,7 @@ void RpAnimBlendClumpInit(RpClump *clump); bool RpAnimBlendClumpIsInitialized(RpClump *clump); void RpAnimBlendClumpFillFrameArray(RpClump* clump, AnimBlendFrameData** frames); AnimBlendFrameData *RpAnimBlendClumpFindFrame(RpClump *clump, const char *name); +AnimBlendFrameData *RpAnimBlendClumpFindBone(RpClump *clump, uint32 boneTag); void FillFrameArrayCallBack(AnimBlendFrameData *frame, void *arg); CAnimBlendAssociation *RpAnimBlendClumpGetAssociation(RpClump *clump, uint32 id); CAnimBlendAssociation *RpAnimBlendClumpGetMainAssociation(RpClump *clump, CAnimBlendAssociation **assocRet, float *blendRet); @@ -34,9 +35,14 @@ CAnimBlendAssociation *RpAnimBlendClumpGetMainAssociation_N(RpClump *clump, int CAnimBlendAssociation *RpAnimBlendClumpGetMainPartialAssociation_N(RpClump *clump, int n); CAnimBlendAssociation *RpAnimBlendClumpGetFirstAssociation(RpClump *clump, uint32 mask); CAnimBlendAssociation *RpAnimBlendClumpGetFirstAssociation(RpClump *clump); -void RpAnimBlendClumpUpdateAnimations(RpClump* clump, float timeDelta); +void RpAnimBlendNodeUpdateKeyframes(AnimBlendFrameData *frames, AnimBlendFrameUpdateData *updateData, int32 numNodes); +void RpAnimBlendClumpUpdateAnimations(RpClump* clump, float timeDelta, bool doRender = true); extern CAnimBlendClumpData *gpAnimBlendClump; void FrameUpdateCallBackNonSkinned(AnimBlendFrameData *frame, void *arg); void FrameUpdateCallBackSkinned(AnimBlendFrameData *frame, void *arg); +void FrameUpdateCallBackOffscreen(AnimBlendFrameData *frame, void *arg); + +void FrameUpdateCallBackNonSkinnedCompressed(AnimBlendFrameData *frame, void *arg); +void FrameUpdateCallBackSkinnedCompressed(AnimBlendFrameData *frame, void *arg); |