aboutsummaryrefslogtreecommitdiffstats
path: root/src/animation/CutsceneMgr_overlay.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/animation/CutsceneMgr_overlay.cpp')
-rw-r--r--src/animation/CutsceneMgr_overlay.cpp1030
1 files changed, 1030 insertions, 0 deletions
diff --git a/src/animation/CutsceneMgr_overlay.cpp b/src/animation/CutsceneMgr_overlay.cpp
new file mode 100644
index 00000000..5fcb752d
--- /dev/null
+++ b/src/animation/CutsceneMgr_overlay.cpp
@@ -0,0 +1,1030 @@
+#include "common.h"
+#include "relocatableChunk.h"
+
+#include "General.h"
+#include "CutsceneMgr.h"
+#include "Directory.h"
+#include "Camera.h"
+#include "Streaming.h"
+#include "FileMgr.h"
+#include "main.h"
+#include "AnimManager.h"
+#include "AnimBlendAssociation.h"
+#include "AnimBlendAssocGroup.h"
+#include "AnimBlendClumpData.h"
+#include "Pad.h"
+#include "DMAudio.h"
+#include "World.h"
+#include "PlayerPed.h"
+#include "Wanted.h"
+#include "RpAnimBlend.h"
+#include "ModelIndices.h"
+#include "TempColModels.h"
+#include "ColStore.h"
+#include "Radar.h"
+#include "Pools.h"
+#include "Messages.h"
+#include "Population.h"
+#include "CarCtrl.h"
+#include "Timecycle.h"
+#include "Rubbish.h"
+#include "Text.h"
+#include "Hud.h"
+#include "crossplatform.h"
+
+const struct {
+ const char *szTrackName;
+ int iTrackId;
+} musicNameIdAssoc[] = {
+ { "BIKER", STREAMED_SOUND_CUTSCENE_BIKER },
+ { "BONEVOY", STREAMED_SOUND_CUTSCENE_BONEVOY },
+ { "CAMPAIN", STREAMED_SOUND_CUTSCENE_CAMPAIN },
+ { "CASHCHP", STREAMED_SOUND_CUTSCENE_CASHCHP },
+ { "CONTBAN", STREAMED_SOUND_CUTSCENE_CONTBAN },
+ { "CRAZY69", STREAMED_SOUND_CUTSCENE_CRAZY69 },
+ { "CUTTEST", STREAMED_SOUND_CUTSCENE_CUTTEST },
+ { "DEADLY", STREAMED_SOUND_CUTSCENE_DEADLY },
+ { "DONPROB", STREAMED_SOUND_CUTSCENE_DONPROB },
+ { "DRIVNMR", STREAMED_SOUND_CUTSCENE_DRIVNMR },
+ { "ELECTON", STREAMED_SOUND_CUTSCENE_ELECTON },
+ { "FINAL", STREAMED_SOUND_CUTSCENE_FINAL },
+ { "FINAL_2", STREAMED_SOUND_CUTSCENE_FINAL_2 },
+ { "HOMSWET", STREAMED_SOUND_CUTSCENE_HOMSWET },
+ { "HOTWHEL", STREAMED_SOUND_CUTSCENE_HOTWHEL },
+ { "KIDNAPP", STREAMED_SOUND_CUTSCENE_KIDNAPP },
+ { "LANDGRB", STREAMED_SOUND_CUTSCENE_LANDGRB },
+ { "MORGUE", STREAMED_SOUND_CUTSCENE_MORGUE },
+ { "OVERDOS", STREAMED_SOUND_CUTSCENE_OVERDOS },
+ { "RUFJUST", STREAMED_SOUND_CUTSCENE_RUFJUST },
+ { "SAYONAR", STREAMED_SOUND_CUTSCENE_SAYONAR },
+ { "SICILAN", STREAMED_SOUND_CUTSCENE_SICILAN },
+ { "THEOFER", STREAMED_SOUND_CUTSCENE_THEOFER },
+ { "INTRO", STREAMED_SOUND_CUTSCENE_INTRO },
+ { "FINALE", STREAMED_SOUND_CUTSCENE_FINALE },
+ { NULL, 0 }
+};
+
+int
+FindCutsceneAudioTrackId(const char *szCutsceneName)
+{
+ debug("looking for cutscene music track\n");
+ for (int i = 0; musicNameIdAssoc[i].szTrackName; i++) {
+ if (!CGeneral::faststricmp(musicNameIdAssoc[i].szTrackName, szCutsceneName)) {
+ debug("HUZZA! FOUND cutscene music track\n");
+ return musicNameIdAssoc[i].iTrackId;
+ }
+ }
+ debug("NOT FOUND cutscene music track\n");
+ return -1;
+}
+
+const char *
+GetNextLine(const char *buf, char *line, uint32 lineSize)
+{
+ while (*buf == '\n' || *buf == '\r')
+ buf++;
+
+ if (*buf == '\0')
+ return nil;
+
+ // size check never happened, eh?
+ while (*buf != '\n' && *buf != '\r') {
+ if (*buf == '\0')
+ break;
+ *(line++) = *(buf++);
+ }
+ *(line++) = '\0';
+ return buf;
+}
+
+RpAtomic*
+CalculateBoundingSphereRadiusCB(RpAtomic* atomic, void* data)
+{
+ float radius = RpAtomicGetBoundingSphere(atomic)->radius;
+ RwV3d center = RpAtomicGetBoundingSphere(atomic)->center;
+
+ for (RwFrame* frame = RpAtomicGetFrame(atomic); RwFrameGetParent(frame); frame = RwFrameGetParent(frame))
+ RwV3dTransformPoints(&center, &center, 1, RwFrameGetMatrix(frame));
+
+ float size = RwV3dLength(&center) + radius;
+ if (size > *(float*)data)
+ *(float*)data = size;
+ return atomic;
+}
+
+void UpdateCutsceneObjectBoundingBox(RpClump* clump, int modelId)
+{
+ if (modelId >= MI_CUTOBJ01 && modelId <= MI_CUTOBJ10) {
+ CColModel* pColModel = &CTempColModels::ms_colModelCutObj[modelId - MI_CUTOBJ01];
+ float oldRadius = pColModel->boundingSphere.radius;
+ float radius = 0.0f;
+ RpClumpForAllAtomics(clump, CalculateBoundingSphereRadiusCB, &radius);
+ if (oldRadius < 20.0f) oldRadius = 20.0f;
+ if (oldRadius < radius) {
+ debug("Limiting cutscene object radius %f\n", oldRadius);
+ radius = oldRadius;
+ }
+ radius = oldRadius;
+ pColModel->boundingSphere.radius = radius;
+ pColModel->boundingBox.min = CVector(-radius, -radius, -radius);
+ pColModel->boundingBox.max = CVector(radius, radius, radius);
+ }
+}
+
+bool bCamLoaded;
+bool bCamFading;
+
+// yes, they've actually doubled this thing here, thus this one is unused
+static bool bModelsRemovedForCutscene;
+static int32 NumberOfSavedWeapons;
+static eWeaponType SavedWeaponIDs[TOTAL_WEAPON_SLOTS];
+static int32 SavedWeaponAmmo[TOTAL_WEAPON_SLOTS];
+
+enum
+{
+ CUTMODEL_PLAYER = 1,
+ CUTMODEL_SIMPLE,
+ CUTMODEL_REPEATED,
+};
+
+bool CCutsceneMgr::ms_useCutsceneShadows = true;
+bool CCutsceneMgr::mCutsceneSkipFading;
+int CCutsceneMgr::mCutsceneSkipFadeTime;
+float CCutsceneMgr::m_fPrevCarDensity;
+float CCutsceneMgr::m_fPrevPedDensity;
+bool CCutsceneMgr::m_PrevExtraColourOn;
+uint32 CCutsceneMgr::m_PrevExtraColour;
+uint32 CCutsceneMgr::ms_iNumParticleEffects;
+sParticleEffect CCutsceneMgr::ms_pParticleEffects[NUM_CUTS_PARTICLE_EFFECTS];
+sToHideItem CCutsceneMgr::ms_crToHideItems[NUMCUTSCENEOBJECTS];
+uint32 CCutsceneMgr::ms_iNumHiddenEntities;
+CEntity *CCutsceneMgr::ms_pHiddenEntities[NUMCUTSCENEOBJECTS];
+int CCutsceneMgr::ms_numAttachObjectToBones;
+bool CCutsceneMgr::ms_bRepeatObject[NUMCUTSCENEOBJECTS];
+sAttachInfo CCutsceneMgr::ms_iAttachObjectToBone[NUMCUTSCENEOBJECTS];
+uint32 CCutsceneMgr::ms_numUncompressedCutsceneAnims;
+char CCutsceneMgr::ms_aUncompressedCutsceneAnims[NUM_CUTS_UNCOMPRESSED_ANIMS][NAMELENGTH];
+uint32 CCutsceneMgr::ms_iTextDuration[NUM_CUTS_MAX_TEXTS];
+uint32 CCutsceneMgr::ms_iTextStartTime[NUM_CUTS_MAX_TEXTS];
+char CCutsceneMgr::ms_cTextOutput[NUM_CUTS_MAX_TEXTS][TEXT_KEY_SIZE];
+uint32 CCutsceneMgr::ms_currTextOutput;
+uint32 CCutsceneMgr::ms_numTextOutput;
+uint32 CCutsceneMgr::ms_iModelIndex[NUMCUTSCENEOBJECTS];
+char CCutsceneMgr::ms_cLoadAnimName[NUMCUTSCENEOBJECTS][NAMELENGTH];
+char CCutsceneMgr::ms_cLoadObjectName[NUMCUTSCENEOBJECTS][NAMELENGTH];
+int CCutsceneMgr::ms_numLoadObjectNames;
+CCutsceneObject *CCutsceneMgr::ms_pCutsceneObjects[NUMCUTSCENEOBJECTS];
+int32 CCutsceneMgr::ms_numCutsceneObjs;
+CVector CCutsceneMgr::ms_cutsceneOffset;
+float CCutsceneMgr::ms_cutsceneTimer;
+uint32 CCutsceneMgr::ms_cutscenePlayStatus;
+CAnimBlendAssocGroup CCutsceneMgr::ms_cutsceneAssociations;
+char CCutsceneMgr::ms_cutsceneName[CUTSCENENAMESIZE];
+
+CCutsceneObject *
+CCutsceneMgr::CreateCutsceneObject(int modelId)
+{
+ CBaseModelInfo *pModelInfo;
+ CColModel *pColModel;
+ CCutsceneObject *pCutsceneObject;
+
+ CStreaming::ImGonnaUseStreamingMemory();
+ debug("Created cutscene object %s\n", CModelInfo::GetModelInfo(modelId)->GetModelName());
+ if (modelId >= MI_CUTOBJ01 && modelId <= MI_CUTOBJ10) {
+ pModelInfo = CModelInfo::GetModelInfo(modelId);
+ pColModel = &CTempColModels::ms_colModelCutObj[modelId - MI_CUTOBJ01];
+ pModelInfo->SetColModel(pColModel);
+ UpdateCutsceneObjectBoundingBox((RpClump*)pModelInfo->GetRwObject(), modelId);
+ }
+
+ pCutsceneObject = new CCutsceneObject();
+ pCutsceneObject->SetModelIndex(modelId);
+ if (ms_useCutsceneShadows)
+ pCutsceneObject->CreateShadow();
+ ms_pCutsceneObjects[ms_numCutsceneObjs++] = pCutsceneObject;
+ CStreaming::IHaveUsedStreamingMemory();
+ return pCutsceneObject;
+}
+
+void
+CCutsceneMgr::SetCutsceneAnim(const char *animName, CObject *pObject)
+{
+ CAnimBlendAssociation *pNewAnim;
+ CAnimBlendClumpData *pAnimBlendClumpData;
+
+ debug("Give cutscene anim %s\n", animName);
+ /*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::SetHeadAnim(const char*, CObject* pObject)
+{
+ return nil;
+}
+
+void
+CCutsceneMgr::StartCutscene()
+{
+ ms_cutscenePlayStatus = CUTSCENE_STARTED;
+ if (bCamLoaded) {
+ TheCamera.SetWideScreenOn();
+ CHud::SetHelpMessage(nil, true);
+ }
+}
+
+void
+CCutsceneMgr::SetupCutsceneToStart(void)
+{
+ if (bCamLoaded) {
+ TheCamera.SetCamCutSceneOffSet(ms_cutsceneOffset);
+ TheCamera.TakeControlWithSpline(JUMP_CUT);
+ TheCamera.SetWideScreenOn();
+ CHud::SetHelpMessage(nil, true);
+ }
+
+ ms_cutsceneOffset.z += 1.0f;
+
+ for (int i = ms_numCutsceneObjs - 1; i >= 0; i--) {
+ assert(RwObjectGetType(ms_pCutsceneObjects[i]->m_rwObject) == rpCLUMP);
+ if (CAnimBlendAssociation *pAnimBlendAssoc = RpAnimBlendClumpGetFirstAssociation((RpClump*)ms_pCutsceneObjects[i]->m_rwObject)) {
+ assert(pAnimBlendAssoc->hierarchy->sequences[0].HasTranslation());
+ 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();
+ CTimer::Update();
+ ms_cutsceneTimer = 0.0f;
+ ms_running = true;
+ mCutsceneSkipFadeTime = 0;
+ mCutsceneSkipFading = 0;
+}
+
+void
+CCutsceneMgr::FinishCutscene()
+{
+ if (bCamLoaded) {
+ ms_cutsceneTimer = TheCamera.GetCutSceneFinishTime() * 0.001f;
+ TheCamera.FinishCutscene();
+ }
+
+ FindPlayerPed()->bIsVisible = true;
+ CWorld::Players[CWorld::PlayerInFocus].MakePlayerSafe(false);
+}
+
+uint32
+CCutsceneMgr::GetCutsceneTimeInMilleseconds(void)
+{
+ return 1000.0f * ms_cutsceneTimer;
+}
+
+bool CCutsceneMgr::HasCutsceneFinished(void)
+{
+ return !bCamLoaded || TheCamera.GetPositionAlongSpline() == 1.0f;
+}
+
+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::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::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::HideRequestedObjects(void)
+{
+ int num = ms_iNumHiddenEntities;
+ ms_iNumHiddenEntities = 0;
+
+ for (int i = 0; i < num; i++) {
+ int id;
+ if (CModelInfo::GetModelInfo(ms_crToHideItems[i].name, &id)) {
+ CVector pos(ms_crToHideItems[i].x, ms_crToHideItems[i].y, ms_crToHideItems[i].z);
+ int16 foundEntities;
+ CEntity* pEntities[32];
+ CWorld::FindObjectsOfTypeInRange(id, pos, 1.5f, true, &foundEntities, 32, pEntities, true, false, false, true, true);
+ for (int j = 0; i < foundEntities; j++) {
+ if (pEntities[j]->bIsVisible) {
+ ms_pHiddenEntities[ms_iNumHiddenEntities] = pEntities[j];
+ ms_pHiddenEntities[ms_iNumHiddenEntities]->RegisterReference(&ms_pHiddenEntities[ms_iNumHiddenEntities]);
+ ms_pHiddenEntities[ms_iNumHiddenEntities]->bIsVisible = false;
+ ms_iNumHiddenEntities++;
+ }
+ }
+ }
+ }
+}
+
+bool
+CCutsceneMgr::PresubBodge()
+{
+ return true;
+}
+
+void
+CCutsceneMgr::LoadCutsceneData_loading()
+{
+ for (int i = 0; i < ms_numLoadObjectNames; i++) {
+ int mi = ms_iModelIndex[i];
+ if (mi >= MI_CUTOBJ01 && mi <= MI_CUTOBJ10) {
+ if (CStreaming::ms_aInfoForModel[mi].m_loadState != STREAMSTATE_LOADED)
+ return;
+ }
+ }
+
+ if (!LoadCutsceneData_postload())
+ return;
+
+ CCutsceneObject* cutsceneObject;
+ for (int i = 0; i < ms_numLoadObjectNames; i++) {
+ if (!ms_bRepeatObject[i])
+ cutsceneObject = CreateCutsceneObject(ms_iModelIndex[i]);
+ if (ms_cLoadAnimName[i][0] != '\0')
+ SetCutsceneAnim(ms_cLoadAnimName[i], cutsceneObject);
+ }
+
+ for (int i = 0; i < ms_numAttachObjectToBones; i++) {
+ int objectId = ms_iAttachObjectToBone[i].objectId;
+ int attachToId = ms_iAttachObjectToBone[i].attachToId;
+ int bone = ms_iAttachObjectToBone[i].boneId;
+ AttachObjectToBone(ms_pCutsceneObjects[objectId], ms_pCutsceneObjects[attachToId], bone);
+ }
+}
+
+bool
+CCutsceneMgr::LoadCutsceneData_postload(bool b)
+{
+ RwStream *stream = nil;
+ uint32 size;
+ uint32 offset;
+
+ bool result;
+
+ CMessages::ClearThisBigPrintNow(0);
+ CPopulation::PedDensityMultiplier = 0.0f;
+ CCarCtrl::CarDensityMultiplier = 0.0f;
+ CStreaming::ms_disableStreaming = false;
+ if (b)
+ {
+ sprintf(gString, "%s.IFP", ms_cutsceneName);
+ result = false;
+ ms_animLoaded = false;
+ RwStreamClose(stream, nil); // umm...
+ sprintf(gString, "%s.DAT", ms_cutsceneName);
+ bCamLoaded = false;
+ } else {
+
+ stream = RwStreamOpen(rwSTREAMFILENAME, rwSTREAMREAD, "ANIM\\CUTS.IMG");
+ sprintf(gString, "%s.IFP", ms_cutsceneName);
+ if (stream) {
+ if (ms_pCutsceneDir->FindItem(gString, offset, size))
+ {
+ CStreaming::MakeSpaceFor(size << 11);
+ CStreaming::ImGonnaUseStreamingMemory();
+ RwStreamSkip(stream, offset << 11);
+ CAnimManager::LoadAnimFile(stream, true, ms_aUncompressedCutsceneAnims);
+ ms_cutsceneAssociations.CreateAssociations(ms_cutsceneName, ms_cLoadAnimName[0], ms_cLoadObjectName[0], NAMELENGTH);
+ CStreaming::IHaveUsedStreamingMemory();
+ ms_animLoaded = true;
+ }
+ else
+ {
+ ms_animLoaded = false;
+ }
+ RwStreamClose(stream, nil);
+
+ int file = CFileMgr::OpenFile("ANIM\\CUTS.IMG", "rb");
+ sprintf(gString, "%s.DAT", ms_cutsceneName);
+ if (file) {
+ if (ms_pCutsceneDir->FindItem(gString, offset, size))
+ {
+ CStreaming::ImGonnaUseStreamingMemory();
+ CFileMgr::Seek(file, offset << 11, 0);
+ TheCamera.LoadPathSplines(file);
+ CStreaming::IHaveUsedStreamingMemory();
+ bCamLoaded = true;
+ }
+ else
+ {
+ bCamLoaded = false;
+ }
+ result = true;
+ CFileMgr::CloseFile(file);
+ }
+ else
+ {
+ bCamLoaded = false;
+ result = true;
+ }
+ }
+ else
+ {
+ result = false;
+ ms_animLoaded = false;
+ RwStreamClose(stream, nil);
+ sprintf(gString, "%s.DAT", ms_cutsceneName);
+ bCamLoaded = false;
+ }
+ }
+ ms_cutsceneLoadStatus = CUTSCENE_LOADED;
+ ms_cutsceneTimer = 0.0f;
+ FindPlayerPed()->m_pWanted->ClearQdCrimes();
+ return result;
+}
+
+void
+CCutsceneMgr::LoadCutsceneData_overlay(const char *szCutsceneName)
+{
+ CTimer::Suspend();
+ ms_cutsceneProcessing = true;
+ ms_wasCutsceneSkipped = false;
+ if (!bModelsRemovedForCutscene)
+ CStreaming::RemoveCurrentZonesModels();
+
+ ms_pCutsceneDir->numEntries = 0;
+ ms_pCutsceneDir->ReadDirFile("ANIM\\CUTS.DIR");
+
+ CStreaming::RemoveUnusedModelsInLoadedList();
+ CGame::DrasticTidyUpMemory(true);
+
+ strcpy(ms_cutsceneName, szCutsceneName);
+
+ LoadCutsceneData_preload();
+ CTimer::Resume();
+}
+
+void
+CCutsceneMgr::LoadCutsceneData_preload(void)
+{
+ uint32 size;
+ uint32 offset;
+ CPlayerPed* pPlayerPed;
+ if (CGeneral::faststricmp(ms_cutsceneName, "finale")) {
+ DMAudio.ChangeMusicMode(MUSICMODE_CUTSCENE);
+ int trackId = FindCutsceneAudioTrackId(ms_cutsceneName);
+ if (trackId != -1) {
+ printf("Start preload audio %s\n", ms_cutsceneName);
+ DMAudio.PreloadCutSceneMusic(trackId);
+ printf("End preload audio %s\n", ms_cutsceneName);
+ }
+ }
+
+ for (int i = MI_CUTOBJ01; i <= MI_CUTOBJ10; i++) {
+ if (CModelInfo::GetModelInfo(i)->GetNumRefs() <= 0) {
+ if (CStreaming::ms_aInfoForModel[i].m_loadState == STREAMSTATE_LOADED) {
+ CStreaming::RemoveModel(i);
+ CModelInfo::GetModelInfo(i)->SetModelName("&*%");
+ }
+ }
+ }
+
+ m_PrevExtraColour = CTimeCycle::m_ExtraColour;
+ m_PrevExtraColourOn = CTimeCycle::m_bExtraColourOn != 0;
+ m_fPrevPedDensity = CPopulation::PedDensityMultiplier;
+ m_fPrevCarDensity = CCarCtrl::CarDensityMultiplier;
+ ms_cutsceneOffset = CVector(0.0f, 0.0f, 0.0f);
+ ms_numTextOutput = 0;
+ ms_currTextOutput = 0;
+ ms_numLoadObjectNames = 0;
+ ms_numUncompressedCutsceneAnims = 0;
+ ms_numAttachObjectToBones = 0;
+ ms_iNumHiddenEntities = 0;
+ bCamFading = false;
+ ms_iNumParticleEffects = 0;
+
+ for (int i = 0; i < NUM_CUTS_UNCOMPRESSED_ANIMS; i++)
+ ms_aUncompressedCutsceneAnims[i][0] = '\0';
+
+ memset(ms_iModelIndex, 0, sizeof(ms_iModelIndex));
+ CRubbish::SetVisibility(false);
+
+ pPlayerPed = FindPlayerPed();
+ 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);
+
+ sprintf(gString, "%s.CUT", ms_cutsceneName);
+ if (!ms_pCutsceneDir->FindItem(gString, offset, size)) {
+ LoadCutsceneData_postload();
+ return;
+ }
+
+ size <<= 11;
+ offset <<= 11;
+
+ char *cutsBuf = new char[size];
+
+ RwStream* stream = RwStreamOpen(rwSTREAMFILENAME, rwSTREAMREAD, "ANIM\\CUTS.IMG");
+
+ if (stream) {
+ RwStreamSkip(stream, offset);
+ RwStreamRead(stream, cutsBuf, size);
+ RwStreamClose(stream, nil);
+ }
+
+ enum
+ {
+ CUT_NONE = 0,
+ CUT_INFO,
+ CUT_MODEL,
+ CUT_TEXT,
+ CUT_UNCOMPRESS,
+ CUT_ATTACH,
+ CUT_REMOVE,
+ CUT_PARTICLE_EFFECT,
+ CUT_EXTRA_COLOR,
+ };
+
+ int cutSection = CUT_NONE;
+ bool bExtraColSet = false;
+
+ char line[1024];
+ const char *pCurLine = cutsBuf;
+
+ while (true)
+ {
+ pCurLine = GetNextLine(pCurLine, line, sizeof(line));
+ if (pCurLine) {
+ if (line[0] == '\0')
+ break;
+
+ if (strcmp(line, "end") == 0) {
+ cutSection = CUT_NONE;
+ continue;
+ }
+
+ switch (cutSection)
+ {
+ case CUT_NONE:
+ if (strcmp(line, "info") == 0)
+ cutSection = CUT_INFO;
+ if (strcmp(line, "model") == 0)
+ cutSection = CUT_MODEL;
+ if (strcmp(line, "text") == 0)
+ cutSection = CUT_TEXT;
+ if (strcmp(line, "uncompress") == 0)
+ cutSection = CUT_UNCOMPRESS;
+ if (strcmp(line, "attach") == 0)
+ cutSection = CUT_ATTACH;
+ if (strcmp(line, "remove") == 0)
+ cutSection = CUT_REMOVE;
+ if (strcmp(line, "peffect") == 0)
+ cutSection = CUT_PARTICLE_EFFECT;
+ if (strcmp(line, "extracol") == 0)
+ cutSection = CUT_EXTRA_COLOR;
+ break;
+ case CUT_INFO:
+ {
+ if (strncmp(line, "offset", 6) == 0) {
+ float x, y, z;
+ sscanf(line+7, "%f %f %f", &x, &y, &z);
+ FindPlayerPed(); // called for some sa check in here
+ ms_cutsceneOffset = CVector(x, y, z);
+ }
+ break;
+ }
+ case CUT_MODEL:
+ {
+ char objectName[NAMELENGTH];
+ char animName[NAMELENGTH];
+
+ int num; // unused
+ sscanf(strtok(line, " ,"), "%d", &num);
+ strcpy(objectName, strtok(nil, " ,"));
+ char* pAnimName = strtok(0, " ,");
+ strlwr(objectName);
+
+ bool bUsedFirstTime = true;
+ if (pAnimName) {
+ do {
+ strcpy(animName, pAnimName);
+ strlwr(animName);
+ strcpy(ms_cLoadObjectName[ms_numLoadObjectNames], objectName);
+ strcpy(ms_cLoadAnimName[ms_numLoadObjectNames], animName);
+ if (bUsedFirstTime) {
+ bUsedFirstTime = false;
+ ms_iModelIndex[ms_numLoadObjectNames] = CUTMODEL_SIMPLE;
+ ms_bRepeatObject[ms_numLoadObjectNames] = false;
+ } else {
+ ms_bRepeatObject[ms_numLoadObjectNames] = true;
+ ms_iModelIndex[ms_numLoadObjectNames] = CUTMODEL_REPEATED;
+ }
+ ms_numLoadObjectNames++;
+ pAnimName = strtok(0, " ,");
+ } while (pAnimName);
+ }
+ break;
+ }
+ case CUT_TEXT:
+ {
+ int iTextStartTime, iTextDuration;
+ char cTextOutput[8];
+ sscanf(line, "%d,%d,%s", &iTextStartTime, &iTextDuration, cTextOutput);
+ for (size_t i = 0; i < strlen(cTextOutput); i++)
+ cTextOutput[i] = toupper(cTextOutput[i]);
+
+ memcpy(ms_cTextOutput[ms_numTextOutput], cTextOutput, strlen(cTextOutput)+1);
+ ms_iTextStartTime[ms_numTextOutput] = iTextStartTime;
+ ms_iTextDuration[ms_numTextOutput] = iTextDuration;
+ ms_numTextOutput++;
+ break;
+ }
+ case CUT_UNCOMPRESS:
+ LoadAnimationUncompressed(strtok(line, " ,"));
+ break;
+ case CUT_ATTACH:
+ {
+ int attachToId, objectId, bone;
+ sscanf(line, "%d,%d,%d", &attachToId, &objectId, &bone);
+ ms_iAttachObjectToBone[ms_numAttachObjectToBones].attachToId = attachToId;
+ ms_iAttachObjectToBone[ms_numAttachObjectToBones].objectId = objectId;
+ ms_iAttachObjectToBone[ms_numAttachObjectToBones].boneId = bone;
+ ms_numAttachObjectToBones++;
+ break;
+ }
+ case CUT_REMOVE:
+ {
+ float x, y, z;
+ char name[NAMELENGTH];
+ sscanf(line, "%f,%f,%f,%s", &x, &y, &z, name);
+ ms_crToHideItems[ms_iNumHiddenEntities].x = x;
+ ms_crToHideItems[ms_iNumHiddenEntities].y = y;
+ ms_crToHideItems[ms_iNumHiddenEntities].z = z;
+ strcpy(ms_crToHideItems[ms_iNumHiddenEntities].name, name);
+ ms_iNumHiddenEntities++;
+ break;
+ }
+ case CUT_PARTICLE_EFFECT:
+ {
+ char name[NAMELENGTH];
+ char name2[NAMELENGTH];
+
+ int iTime;
+ int unk1;
+ int unk2;
+ float x;
+ float y;
+ float z;
+ float unkX;
+ float unkY;
+ float unkZ;
+
+ memset(name, 0, NAMELENGTH);
+ memset(name2, 0, NAMELENGTH);
+
+ strncpy(name, strtok(line, ","), NAMELENGTH-1);
+ iTime = atoi(strtok(0, ","));
+ unk1 = atoi(strtok(0, ","));
+ unk2 = atoi(strtok(0, ","));
+ strncpy(name, strtok(line, ","), NAMELENGTH-1);
+ x = strtod(strtok(0, ","), nil);
+ y = strtod(strtok(0, ","), nil);
+ z = strtod(strtok(0, ","), nil);
+ unkX = strtod(strtok(0, ","), nil);
+ unkY = strtod(strtok(0, ","), nil);
+ unkZ = strtod(strtok(0, ","), nil);
+
+ ms_pParticleEffects[ms_iNumParticleEffects].bPlayed = false;
+ ms_pParticleEffects[ms_iNumParticleEffects].iTime = iTime;
+ ms_pParticleEffects[ms_iNumParticleEffects].unk1 = unk1;
+ ms_pParticleEffects[ms_iNumParticleEffects].unk2 = unk2;
+ strcpy(CCutsceneMgr::ms_pParticleEffects[ms_iNumParticleEffects].name2, name2);
+ ms_pParticleEffects[ms_iNumParticleEffects].unk10 = false;
+ ms_pParticleEffects[ms_iNumParticleEffects].x = x;
+ ms_pParticleEffects[ms_iNumParticleEffects].y = y;
+ ms_pParticleEffects[ms_iNumParticleEffects].z = z;
+ ms_pParticleEffects[ms_iNumParticleEffects].unkX = unkX;
+ ms_pParticleEffects[ms_iNumParticleEffects].unkY = unkY;
+ ms_pParticleEffects[ms_iNumParticleEffects].unkZ = unkZ;
+ ms_pParticleEffects[ms_iNumParticleEffects].unk11 = false;
+ strcpy(CCutsceneMgr::ms_pParticleEffects[ms_iNumParticleEffects].name, name);
+ ms_iNumParticleEffects++;
+ break;
+ }
+ case CUT_EXTRA_COLOR:
+ if (!bExtraColSet) {
+ int colorId;
+ sscanf(line, "%d", &colorId);
+ if (colorId == 0)
+ bExtraColSet = false;
+ else {
+ CTimeCycle::StartExtraColour(colorId - 1, false);
+ bExtraColSet = true;
+ }
+ }
+ break;
+ default:
+ break;
+ };
+
+ }
+ else
+ {
+ delete[]cutsBuf;
+
+ // add manually inserted objects
+ for (int i = 0; i < ms_numAppendObjectNames; i++) {
+ strcpy(ms_cLoadObjectName[ms_numLoadObjectNames], ms_cAppendObjectName[i]);
+ strcpy(ms_cLoadAnimName[ms_numLoadObjectNames], ms_cAppendAnimName[i]);
+ ms_iModelIndex[ms_numLoadObjectNames] = CUTMODEL_SIMPLE;
+ ms_numLoadObjectNames++;
+ }
+ ms_numAppendObjectNames = 0;
+
+ int specialId = 0;
+ for (int i = 0; i < ms_numLoadObjectNames; i++)
+ {
+ if (strcasecmp(ms_cLoadObjectName[i], "csplay") == 0) {
+ ms_iModelIndex[i] = CUTMODEL_PLAYER;
+ continue;
+ } else if (ms_iModelIndex[i] == CUTMODEL_SIMPLE) {
+ int id;
+ if (CModelInfo::GetModelInfo(ms_cLoadObjectName[i], &id)) {
+ ms_iModelIndex[i] = id;
+ CStreaming::RequestModel(id, STREAMFLAGS_SCRIPTOWNED | STREAMFLAGS_DEPENDENCY | STREAMFLAGS_PRIORITY);
+ } else {
+ CStreaming::RequestSpecialModel(specialId + MI_CUTOBJ01, ms_cLoadObjectName[i], STREAMFLAGS_SCRIPTOWNED | STREAMFLAGS_DEPENDENCY | STREAMFLAGS_PRIORITY);
+ ms_iModelIndex[i] = specialId + MI_CUTOBJ01;
+ specialId++;
+ // skip if id is busy
+ while (CStreaming::ms_aInfoForModel[specialId + MI_CUTOBJ01].m_loadState == STREAMSTATE_LOADED)
+ specialId++;
+ }
+ }
+ else if (ms_iModelIndex[i] == CUTMODEL_REPEATED && i != 0)
+ ms_iModelIndex[i] = ms_iModelIndex[i - 1];
+ }
+
+ CStreaming::LoadAllRequestedModels(true);
+ ms_cutsceneLoadStatus = CUTSCENE_LOADING;
+ return;
+ }
+ }
+
+ delete[]cutsBuf;
+ LoadCutsceneData_postload(true);
+}
+
+void
+CCutsceneMgr::DeleteCutsceneData_overlay(void)
+{
+ if (ms_cutsceneLoadStatus == CUTSCENE_NOT_LOADED) return;
+ CTimer::Suspend();
+ CPopulation::PedDensityMultiplier = m_fPrevPedDensity;
+ CCarCtrl::CarDensityMultiplier = m_fPrevCarDensity;
+ if (m_PrevExtraColourOn)
+ CTimeCycle::StartExtraColour(m_PrevExtraColour, false);
+ else
+ CTimeCycle::StopExtraColour(m_PrevExtraColourOn);
+
+ for (uint32 i = 0; i < ms_iNumHiddenEntities; i++) {
+ if (ms_pHiddenEntities[i]) {
+ ms_pHiddenEntities[i]->CleanUpOldReference(&ms_pHiddenEntities[i]);
+ ms_pHiddenEntities[i]->bIsVisible = true;
+ }
+ }
+
+ ms_iNumHiddenEntities = 0;
+ ms_iNumParticleEffects = 0;
+ CMessages::ClearMessages();
+ CRubbish::SetVisibility(true);
+
+ ms_cutsceneProcessing = false;
+ ms_useLodMultiplier = false;
+ ms_useCutsceneShadows = false;
+
+ ms_numCutsceneObjs--;
+ while (ms_numCutsceneObjs >= 0) {
+ CWorld::Remove(ms_pCutsceneObjects[ms_numCutsceneObjs]);
+ ms_pCutsceneObjects[ms_numCutsceneObjs]->DeleteRwObject();
+ delete ms_pCutsceneObjects[ms_numCutsceneObjs];
+ ms_pCutsceneObjects[ms_numCutsceneObjs] = nil;
+ ms_numCutsceneObjs--;
+ }
+ ms_numCutsceneObjs = 0;
+
+ if (ms_animLoaded)
+ CAnimManager::RemoveLastAnimFile();
+
+ ms_animLoaded = false;
+ ms_cutsceneAssociations.DestroyAssociations();
+
+ ms_aUncompressedCutsceneAnims[0][0] = '\0';
+ ms_numUncompressedCutsceneAnims = 0;
+
+ if (bCamLoaded) {
+ TheCamera.RestoreWithJumpCut();
+ TheCamera.SetWideScreenOff();
+ TheCamera.DeleteCutSceneCamDataMemory();
+ }
+ ms_cutsceneLoadStatus = CUTSCENE_NOT_LOADED;
+ ms_running = false;
+
+ FindPlayerPed()->bIsVisible = true;
+ CPad::GetPad(0)->SetEnablePlayerControls(PLAYERCONTROL_CUTSCENE);
+ CWorld::Players[CWorld::PlayerInFocus].MakePlayerSafe(false);
+
+ if (CGeneral::faststricmp(ms_cutsceneName, "finale")) {
+ DMAudio.StopCutSceneMusic();
+ DMAudio.ChangeMusicMode(MUSICMODE_GAME);
+ }
+
+ CStreaming::ms_disableStreaming = false;
+ CWorld::bProcessCutsceneOnly = false;
+
+ //if(bCamLoaded)
+ // CGame::DrasticTidyUpMemory(TheCamera.GetScreenFadeStatus() == FADE_2);
+
+ CPad::GetPad(0)->Clear(false);
+
+ if (bModelsRemovedForCutscene) {
+ CStreaming::LoadInitialPeds();
+ CStreaming::LoadInitialWeapons();
+ CStreaming::LoadInitialVehicles();
+ bModelsRemovedForCutscene = 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;
+ }
+
+ for (int i = 0; i < ms_numLoadObjectNames; i++)
+ CStreaming::SetMissionDoesntRequireModel(ms_iModelIndex[i]);
+
+ CStreaming::SetMissionDoesntRequireModel(MI_COP);
+ CStreaming::StreamZoneModels(FindPlayerCoors());
+ CTimer::Resume();
+}
+
+void
+CCutsceneMgr::Update_overlay(void)
+{
+ if (ms_cutsceneLoadStatus == CUTSCENE_LOADING) {
+ debug("Loading Cutscene...\n");
+ CTimer::Suspend();
+ LoadCutsceneData_loading();
+ CTimer::Resume();
+ return;
+ }
+
+ if (ms_cutsceneLoadStatus != CUTSCENE_LOADED) {
+ debug("Cutscene Not Loaded!\n");
+ return;
+ }
+
+ switch (ms_cutscenePlayStatus) {
+ case CUTSCENE_STARTED:
+ SetupCutsceneToStart();
+ HideRequestedObjects();
+ ms_cutscenePlayStatus++;
+ break;
+ case CUTSCENE_PLAYING_2:
+ case CUTSCENE_PLAYING_3:
+ ms_cutscenePlayStatus++;
+ break;
+ case CUTSCENE_PLAYING_4:
+ ms_cutscenePlayStatus = CUTSCENE_PLAYING_0;
+ if (CGeneral::faststricmp(ms_cutsceneName, "finale"))
+ DMAudio.PlayPreloadedCutSceneMusic();
+ break;
+ default:
+ break;
+ }
+
+ if (!ms_running) return;
+
+ ms_cutsceneTimer += CTimer::GetTimeStepNonClippedInSeconds();
+ uint32 cutsceneTimeInMS = GetCutsceneTimeInMilleseconds();
+
+ if (ms_currTextOutput < ms_numTextOutput && cutsceneTimeInMS > ms_iTextStartTime[ms_currTextOutput]) {
+ CMessages::AddMessageJumpQ(TheText.Get(ms_cTextOutput[ms_currTextOutput]), ms_iTextDuration[ms_currTextOutput], 1);
+ ms_currTextOutput++;
+ }
+
+ for (int i = 0; i < ms_numCutsceneObjs; i++) {
+ int modelId = ms_pCutsceneObjects[i]->GetModelIndex();
+ if (modelId >= MI_CUTOBJ01 && modelId <= MI_CUTOBJ10)
+ UpdateCutsceneObjectBoundingBox(ms_pCutsceneObjects[i]->GetClump(), modelId);
+ }
+
+ if (!bCamLoaded) return;
+
+ if (CGeneral::faststricmp(ms_cutsceneName, "finale") && TheCamera.Cams[TheCamera.ActiveCam].Mode == CCam::MODE_FLYBY && ms_cutsceneLoadStatus == CUTSCENE_LOADED) {
+ if (TheCamera.GetCutSceneFinishTime() < cutsceneTimeInMS + 1000) {
+ if (!bCamFading) {
+ bCamFading = true;
+ TheCamera.Fade(1.0f, FADE_OUT);
+ }
+ }
+ if (mCutsceneSkipFading) {
+ mCutsceneSkipFadeTime -= CTimer::GetTimeStepInMilliseconds();
+ if (mCutsceneSkipFadeTime < 0) {
+ CHud::m_BigMessage[1][0] = '\0';
+ ms_wasCutsceneSkipped = true;
+ FinishCutscene();
+ mCutsceneSkipFading = false;
+ mCutsceneSkipFadeTime = 0;
+ }
+ }
+ else if (IsCutsceneSkipButtonBeingPressed() && PresubBodge()){
+ mCutsceneSkipFading = true;
+ mCutsceneSkipFadeTime = 1000;
+ TheCamera.Fade(1.0f, FADE_OUT);
+ }
+ }
+} \ No newline at end of file