diff --git a/src/control/Replay.cpp b/src/control/Replay.cpp index 1a050bee..80c05f31 100644 --- a/src/control/Replay.cpp +++ b/src/control/Replay.cpp @@ -39,6 +39,7 @@ #include "Text.h" #include "Camera.h" #include "Radar.h" +#include "Fluff.h" uint8 CReplay::Mode; CAddressInReplayBuffer CReplay::Record; @@ -229,7 +230,7 @@ void CReplay::EnableReplays(void) void PlayReplayFromHD(void); void CReplay::Update(void) { - if (CCutsceneMgr::IsCutsceneProcessing() || CTimer::GetIsPaused()) + if (CCutsceneMgr::IsCutsceneProcessing() || CTimer::GetIsPaused() || CScriptPaths::IsOneActive()) return; switch (Mode){ case MODE_RECORD: @@ -1175,6 +1176,7 @@ void CReplay::StoreStuffInMem(void) if (ped) StoreDetailedPedAnimation(ped, &pPedAnims[i]); } + CScriptPaths::Save_ForReplay(); } void CReplay::RestoreStuffFromMem(void) @@ -1351,6 +1353,7 @@ void CReplay::RestoreStuffFromMem(void) } delete[] pPedAnims; pPedAnims = nil; + CScriptPaths::Load_ForReplay(); DMAudio.ChangeMusicMode(MUSICMODE_FRONTEND); DMAudio.SetRadioInCar(OldRadioStation); DMAudio.ChangeMusicMode(MUSICMODE_GAME); diff --git a/src/control/Script.cpp b/src/control/Script.cpp index fabc375b..fb95e834 100644 --- a/src/control/Script.cpp +++ b/src/control/Script.cpp @@ -82,6 +82,7 @@ #include "main.h" #include "Ropes.h" #include "MBlur.h" +#include "Fluff.h" #ifdef USE_ADVANCED_SCRIPT_DEBUG_OUTPUT #include #endif @@ -12057,36 +12058,42 @@ int8 CRunningScript::ProcessCommands1100To1199(int32 command) //case COMMAND_IS_PLAYER_STANDING_ON_A_VEHICLE: //case COMMAND_IS_PLAYER_FOOT_DOWN: //case COMMAND_IS_CHAR_FOOT_DOWN: - case COMMAND_INITIALISE_OBJECT_PATH: - // TODO(MIAMI): script path + case COMMAND_INITIALISE_OBJECT_PATH: { CollectParameters(&m_nIp, 2); - debug("INITALISE_OBJECT_PATH not yet implemented, skipping\n"); - ScriptParams[0] = 0; + int32 counter = 0; + while (counter < 3 && CScriptPaths::aArray[counter].m_state != SCRIPT_PATH_DISABLED) { + counter++; + } + CScriptPaths::aArray[counter].InitialiseOne(ScriptParams[0], *(float*)&ScriptParams[1]); + ScriptParams[0] = counter; StoreParameters(&m_nIp, 1); return 0; + } case COMMAND_START_OBJECT_ON_PATH: { CollectParameters(&m_nIp, 2); - debug("START_OBJECT_ON_PATH not yet implemented, skipping\n"); + CObject *pObj = CPools::GetObjectPool()->GetAt(ScriptParams[0]); + assert(pObj); + CScriptPaths::aArray[ScriptParams[1]].SetObjectToControl(pObj); return 0; } case COMMAND_SET_OBJECT_PATH_SPEED: { CollectParameters(&m_nIp, 2); - debug("SET_OBJECT_PATH_SPEED not yet implemented, skipping\n"); + CScriptPaths::aArray[ScriptParams[0]].m_fSpeed = *(float*)&ScriptParams[1]; return 0; } case COMMAND_SET_OBJECT_PATH_POSITION: { CollectParameters(&m_nIp, 2); - debug("SET_OBJECT_PATH_POSITION not yet implemented, skipping\n"); + CScriptPaths::aArray[ScriptParams[0]].m_fPosition = *(float*)&ScriptParams[1]; return 0; } //case COMMAND_GET_OBJECT_DISTANCE_ALONG_PATH: case COMMAND_CLEAR_OBJECT_PATH: { CollectParameters(&m_nIp, 1); - debug("CLEAR_OBJECT_PATH not yet implemented, skipping\n"); + CScriptPaths::aArray[ScriptParams[0]].Clear(); return 0; } case COMMAND_HELI_GOTO_COORDS: diff --git a/src/core/Game.cpp b/src/core/Game.cpp index dbb898bf..7a2e56ed 100644 --- a/src/core/Game.cpp +++ b/src/core/Game.cpp @@ -329,6 +329,7 @@ bool CGame::Initialise(const char* datFile) CDebug::DebugInitTextBuffer(); ThePaths.Init(); ThePaths.AllocatePathFindInfoMem(4500); + CScriptPaths::Init(); CWeather::Init(); CCullZones::Init(); COcclusion::Init(); @@ -459,6 +460,7 @@ bool CGame::ShutDown(void) CReplay::FinishPlayback(); CPlane::Shutdown(); CTrain::Shutdown(); + CScriptPaths::Shutdown(); CSpecialFX::Shutdown(); #ifndef PS2 CGarages::Shutdown(); @@ -573,6 +575,7 @@ void CGame::ReInitGameObjectVariables(void) CSpecialFX::Init(); CRopes::Init(); CWaterCannons::Init(); + CScriptPaths::Init(); CParticle::ReloadConfig(); #ifdef PS2_MENU @@ -715,6 +718,7 @@ void CGame::Process(void) CWeather::Update(); CTheScripts::Process(); CCollision::Update(); + CScriptPaths::Update(); CTrain::UpdateTrains(); CPlane::UpdatePlanes(); CHeli::UpdateHelis(); diff --git a/src/render/Fluff.cpp b/src/render/Fluff.cpp index 14c80a63..77d2af2a 100644 --- a/src/render/Fluff.cpp +++ b/src/render/Fluff.cpp @@ -1520,4 +1520,197 @@ CEscalators::Shutdown(void) { aEscalators[i].SwitchOff(); } NumEscalators = 0; +} + + +CScriptPath CScriptPaths::aArray[3]; + +void CScriptPath::FindCoorsFromDistanceOnPath(float t, float *pX, float *pY, float *pZ) +{ + int32 i; + for (i = 0; m_pNode[i + 1].t < t; i++) + if (i == m_numNodes - 1) { + // don't go beyond last node + *pX = m_pNode[m_numNodes - 1].p.x; + *pY = m_pNode[m_numNodes - 1].p.y; + *pZ = m_pNode[m_numNodes - 1].p.z; + return; + } + float f = (t - m_pNode[i].t) / (m_pNode[i + 1].t - m_pNode[i].t); + *pX = (1.0f - f)*m_pNode[i].p.x + f*m_pNode[i + 1].p.x; + *pY = (1.0f - f)*m_pNode[i].p.y + f*m_pNode[i + 1].p.y; + *pZ = (1.0f - f)*m_pNode[i].p.z + f*m_pNode[i + 1].p.z; +} + +void CScriptPath::Update(void) { + if (m_state != SCRIPT_PATH_ACTIVE) + return; + + m_fPosition += m_fSpeed * CTimer::GetTimeStepInSeconds(); + m_fPosition = clamp(m_fPosition, 0.0f, m_fTotalLength); + + if (m_pObjects[0] || m_pObjects[1] || m_pObjects[2] || m_pObjects[3] + || m_pObjects[4] || m_pObjects[5]) { + + float t1, t2; + CVector pos1, pos2; + + t1 = Max(m_fPosition - m_fObjectLength / 2.0f, 0.0f); + FindCoorsFromDistanceOnPath(t1, &pos1.x, &pos1.y, &pos1.z); + t2 = Min(m_fPosition + m_fObjectLength / 2.0f, m_fTotalLength); + FindCoorsFromDistanceOnPath(t2, &pos2.x, &pos2.y, &pos2.z); + + CVector newForward, newUp(0.0f, 0.0f, 1.0f), newRight; + + newForward = pos2 - pos1; + newForward.Normalise(); + newRight = CrossProduct(newForward, newUp); + newRight.Normalise(); + newUp = CrossProduct(newRight, newForward); + + for (int i = 0; i < 6; i++) { + if (m_pObjects[i]) { + CMatrix prevMat(m_pObjects[i]->GetMatrix()); + CVector prevPosition = m_pObjects[i]->GetPosition(); + + m_pObjects[i]->SetPosition((pos1 + pos2) / 2.0f); + m_pObjects[i]->GetRight() = newRight; + m_pObjects[i]->GetUp() = newUp; + m_pObjects[i]->GetForward() = newForward; + m_pObjects[i]->GetMatrix().UpdateRW(); + m_pObjects[i]->UpdateRwFrame(); + + if (!m_pObjects[i]->bIsBIGBuilding && prevPosition != m_pObjects[i]->GetPosition()) + m_pObjects[i]->RemoveAndAdd(); + + m_pObjects[i]->GetMatrix().UpdateRW(); + m_pObjects[i]->UpdateRwFrame(); + + m_pObjects[i]->m_vecMoveSpeed = (m_pObjects[i]->GetPosition() - prevMat.GetPosition()) / CTimer::GetTimeStep(); + + float deltaAngle = m_pObjects[i]->GetForward().Heading() - prevMat.GetForward().Heading(); + while (deltaAngle < (float)PI) deltaAngle += (float)TWOPI; + while (deltaAngle > (float)PI) deltaAngle -= (float)TWOPI; + float zTurnSpeed = deltaAngle / CTimer::GetTimeStep(); + + m_pObjects[i]->m_vecTurnSpeed = CVector(0.0f, 0.0f, zTurnSpeed); + m_pObjects[i]->m_vecMoveFriction = CVector(0.0f, 0.0f, 0.0f); + m_pObjects[i]->m_vecTurnFriction = CVector(0.0f, 0.0f, 0.0f); + } + } + } +} + +void CScriptPath::Clear(void) { + if (m_pNode) + delete m_pNode; + m_pNode = nil; + m_numNodes = 0; + for (int i = 0; i < 6; i++) + m_pObjects[i] = nil; + m_state = SCRIPT_PATH_DISABLED; +} + +void CScriptPath::InitialiseOne(int32 numNodes, float width) { + char Dest[32]; + sprintf(Dest, "data\\paths\\spath%d.dat", numNodes); + m_pNode = CPlane::LoadPath(Dest, m_numNodes, m_fTotalLength, false); + m_fSpeed = 1.0f; + m_fPosition = 0.0f; + m_fObjectLength = width; + m_state = SCRIPT_PATH_INITIALIZED; +} + +void CScriptPath::SetObjectToControl(CObject *pObj) { + int32 i = 0; + while (i < 6 && m_pObjects[i]) + i++; + m_pObjects[i] = pObj; + pObj->RegisterReference((CEntity**)&m_pObjects[i]); + pObj->m_phy_flagA08 = false; + m_state = SCRIPT_PATH_ACTIVE; +} + +void CScriptPaths::Init(void) { + for (int i = 0; i < 3; i++) + aArray[i].Clear(); +} + +void CScriptPaths::Shutdown(void) { + for (int i = 0; i < 3; i++) + aArray[i].Clear(); +} + +void CScriptPaths::Update(void) { + for (int i = 0; i < 3; i++) + aArray[i].Update(); +} + +bool CScriptPaths::IsOneActive(void) { + for (int i = 0; i < 3; i++) + if (aArray[i].m_state == SCRIPT_PATH_ACTIVE && aArray[i].m_fSpeed != 0.0f) + return true; + + return false; +} + +void CScriptPaths::Load(uint8 *buf, uint32 size) { +INITSAVEBUF + for (int32 i = 0; i < 3; i++) + aArray[i].Clear(); + + for (int32 i = 0; i < 3; i++) { + aArray[i] = ReadSaveBuf(buf); + + for (int32 j = 0; j < 6; j++) { + CScriptPath *pPath = &aArray[i]; + if (pPath->m_pObjects[j] != nil) { + pPath->m_pObjects[j] = CPools::GetObjectPool()->GetSlot((uintptr)pPath->m_pObjects[j] - 1); + pPath->m_pObjects[j]->m_phy_flagA08 = false; + } + } + + aArray[i].m_pNode = new CPlaneNode[aArray[i].m_numNodes]; + for (int32 j = 0; j < aArray[i].m_numNodes; j++) { + aArray[i].m_pNode[j] = ReadSaveBuf(buf); + } + } +VALIDATESAVEBUF(size) +} + +void CScriptPaths::Save(uint8 *buf, uint32 *size) { + *size = sizeof(aArray); +INITSAVEBUF + for (int32 i = 0; i < 3; i++) { + CScriptPath *pPath = WriteSaveBuf(buf, aArray[i]); + + for (int32 j = 0; j < 6; j++) { + if (pPath->m_pObjects[j] != nil) + pPath->m_pObjects[j] = (CObject*)(CPools::GetObjectPool()->GetJustIndex(pPath->m_pObjects[j]) + 1); + } + + for (int32 j = 0; j < aArray[i].m_numNodes; j++) { + WriteSaveBuf(buf, aArray[i].m_pNode[j]); + *size += sizeof(aArray[i].m_pNode[j]); + } + } +VALIDATESAVEBUF(*size); +} + +CObject* g_pScriptPathObjects[18]; + +void CScriptPaths::Load_ForReplay(void) { + for (int i = 0; i < 3; i++) { + for (int32 j = 0; j < 6; j++) { + aArray[i].m_pObjects[j] = g_pScriptPathObjects[6 * i + j]; + } + } +} + +void CScriptPaths::Save_ForReplay(void) { + for (int i = 0; i < 3; i++) { + for (int32 j = 0; j < 6; j++) { + g_pScriptPathObjects[6 * i + j] = aArray[i].m_pObjects[j]; + } + } } \ No newline at end of file diff --git a/src/render/Fluff.h b/src/render/Fluff.h index a938a4fe..a31ac335 100644 --- a/src/render/Fluff.h +++ b/src/render/Fluff.h @@ -2,17 +2,45 @@ #include "common.h" #include "Vector.h" #include "Object.h" +#include "Plane.h" + +enum { + SCRIPT_PATH_DISABLED = 0, + SCRIPT_PATH_INITIALIZED, + SCRIPT_PATH_ACTIVE +}; -// TODO class CScriptPath { public: + int32 m_numNodes; + CPlaneNode *m_pNode; + float m_fTotalLength; + float m_fSpeed; + float m_fPosition; + float m_fObjectLength; + int32 m_state; + CObject *m_pObjects[6]; + + void Clear(void); + void Update(void); + void InitialiseOne(int32 numNodes, float width); + void FindCoorsFromDistanceOnPath(float t, float *pX, float *pY, float *pZ); + void SetObjectToControl(CObject *pObj); }; -// TODO class CScriptPaths { public: + static CScriptPath aArray[3]; + static void Init(void); + static void Shutdown(void); + static void Update(void); + static bool IsOneActive(void); + static void Save(uint8 *buf, uint32 *size); + static void Load(uint8 *buf, uint32 size); + static void Save_ForReplay(); + static void Load_ForReplay(); }; class CPlaneTrail diff --git a/src/save/GenericGameStorage.cpp b/src/save/GenericGameStorage.cpp index 4f69123b..90e7e122 100644 --- a/src/save/GenericGameStorage.cpp +++ b/src/save/GenericGameStorage.cpp @@ -38,6 +38,7 @@ #include "World.h" #include "Zones.h" #include "Timecycle.h" +#include "Fluff.h" #define BLOCK_COUNT 20 #define SIZE_OF_SIMPLEVARS 0xD4 @@ -226,6 +227,7 @@ GenericSave(int file) WriteSaveDataBlock(CTheCarGenerators::SaveAllCarGenerators); WriteSaveDataBlock(CParticleObject::SaveParticle); WriteSaveDataBlock(cAudioScriptObject::SaveAllAudioScriptObjects); + WriteSaveDataBlock(CScriptPaths::Save); WriteSaveDataBlock(CWorld::Players[CWorld::PlayerInFocus].SavePlayerInfo); WriteSaveDataBlock(CStats::SaveStats); WriteSaveDataBlock(CSetPieces::Save); @@ -377,6 +379,8 @@ GenericLoad() LoadSaveDataBlock(); ReadDataFromBlock("Loading AudioScript Objects \n", cAudioScriptObject::LoadAllAudioScriptObjects); LoadSaveDataBlock(); + ReadDataFromBlock("Loading ScriptPaths \n", CScriptPaths::Load); + LoadSaveDataBlock(); ReadDataFromBlock("Loading Player Info \n", CWorld::Players[CWorld::PlayerInFocus].LoadPlayerInfo); LoadSaveDataBlock(); ReadDataFromBlock("Loading Stats \n", CStats::LoadStats);