mirror of
https://github.com/halpz/re3.git
synced 2025-04-25 20:15:48 +00:00
1030 lines
31 KiB
C++
1030 lines
31 KiB
C++
#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);
|
|
}
|
|
}
|
|
} |