diff options
Diffstat (limited to 'src/animation/CutsceneMgr_overlay.cpp')
-rw-r--r-- | src/animation/CutsceneMgr_overlay.cpp | 1030 |
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(¢er, ¢er, 1, RwFrameGetMatrix(frame)); + + float size = RwV3dLength(¢er) + 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 |