diff options
-rw-r--r-- | src/control/Replay.cpp | 12 | ||||
-rw-r--r-- | src/control/Script.cpp | 22 | ||||
-rw-r--r-- | src/core/Pools.cpp | 61 | ||||
-rw-r--r-- | src/core/Radar.cpp | 4 | ||||
-rw-r--r-- | src/core/Radar.h | 2 | ||||
-rw-r--r-- | src/core/Timer.cpp | 3 | ||||
-rw-r--r-- | src/core/main.cpp | 2 | ||||
-rw-r--r-- | src/peds/Ped.cpp | 30 | ||||
-rw-r--r-- | src/peds/PedAttractor.cpp | 6 | ||||
-rw-r--r-- | src/peds/PlayerPed.cpp | 6 | ||||
-rw-r--r-- | src/render/Glass.cpp | 478 | ||||
-rw-r--r-- | src/render/Glass.h | 12 | ||||
-rw-r--r-- | src/render/Hud.cpp | 2 | ||||
-rw-r--r-- | src/render/SpecialFX.cpp | 524 | ||||
-rw-r--r-- | src/render/SpecialFX.h | 48 | ||||
-rw-r--r-- | src/save/GenericGameStorage.cpp | 75 | ||||
-rw-r--r-- | src/save/GenericGameStorage.h | 2 | ||||
-rw-r--r-- | src/vehicles/Automobile.cpp | 6 | ||||
-rw-r--r-- | src/vehicles/Bike.cpp | 24 | ||||
-rw-r--r-- | src/vehicles/Bike.h | 6 | ||||
-rw-r--r-- | src/vehicles/Boat.cpp | 6 | ||||
-rw-r--r-- | src/vehicles/CarGen.cpp | 2 | ||||
-rw-r--r-- | src/vehicles/Cranes.h | 1 | ||||
-rw-r--r-- | src/vehicles/Vehicle.cpp | 20 |
24 files changed, 1002 insertions, 352 deletions
diff --git a/src/control/Replay.cpp b/src/control/Replay.cpp index 310d9686..4fdd3439 100644 --- a/src/control/Replay.cpp +++ b/src/control/Replay.cpp @@ -387,10 +387,8 @@ void CReplay::RecordThisFrame(void) tBulletTracePacket* bt = (tBulletTracePacket*)&Record.m_pBase[Record.m_nOffset]; bt->type = REPLAYPACKET_BULLET_TRACES; bt->index = i; - bt->frames = CBulletTraces::aTraces[i].m_framesInUse; - bt->lifetime = CBulletTraces::aTraces[i].m_lifeTime; - bt->inf = CBulletTraces::aTraces[i].m_vecCurrentPos; - bt->sup = CBulletTraces::aTraces[i].m_vecTargetPos; + bt->inf = CBulletTraces::aTraces[i].m_vecStartPos; + bt->sup = CBulletTraces::aTraces[i].m_vecEndPos; Record.m_nOffset += sizeof(*bt); } tMiscPacket* misc = (tMiscPacket*)&Record.m_pBase[Record.m_nOffset]; @@ -1117,10 +1115,8 @@ bool CReplay::PlayBackThisFrameInterpolation(CAddressInReplayBuffer *buffer, flo { tBulletTracePacket* pb = (tBulletTracePacket*)&ptr[offset]; CBulletTraces::aTraces[pb->index].m_bInUse = true; - CBulletTraces::aTraces[pb->index].m_framesInUse = pb->frames; - CBulletTraces::aTraces[pb->index].m_lifeTime = pb->lifetime; - CBulletTraces::aTraces[pb->index].m_vecCurrentPos = pb->inf; - CBulletTraces::aTraces[pb->index].m_vecTargetPos = pb->sup; + CBulletTraces::aTraces[pb->index].m_vecStartPos = pb->inf; + CBulletTraces::aTraces[pb->index].m_vecEndPos = pb->sup; buffer->m_nOffset += sizeof(tBulletTracePacket); break; } diff --git a/src/control/Script.cpp b/src/control/Script.cpp index a2ab5f0b..0df6d5a2 100644 --- a/src/control/Script.cpp +++ b/src/control/Script.cpp @@ -31,6 +31,7 @@ #include "GameLogic.h" #include "Garages.h" #include "General.h" +#include "Glass.h" #ifdef MISSION_REPLAY #include "GenericGameStorage.h" #endif @@ -1804,9 +1805,8 @@ void CMissionCleanup::Process() if (!CWorld::Players[CWorld::PlayerInFocus].m_pRemoteVehicle) TheCamera.Restore(); TheCamera.SetWideScreenOff(); - // TODO(MIAMI) - //CSpecialFX::bLiftCam = false; - //CSpecialFX::bVideoCam = false; + CSpecialFX::bLiftCam = false; + CSpecialFX::bVideoCam = false; CTimeCycle::StopExtraColour(0); for (int i = 0; i < MISSION_AUDIO_SLOTS; i++) DMAudio.ClearMissionAudio(i); @@ -12404,7 +12404,7 @@ int8 CRunningScript::ProcessCommands1200To1299(int32 command) case COMMAND_SWITCH_SECURITY_CAMERA: { CollectParameters(&m_nIp, 1); - debug("SWITCH_SECURITY_CAMERA is not implemented\n"); // TODO(MIAMI) + CSpecialFX::bVideoCam = ScriptParams[0] != 0; return 0; } //case COMMAND_IS_CHAR_IN_FLYING_VEHICLE: @@ -12844,7 +12844,7 @@ int8 CRunningScript::ProcessCommands1200To1299(int32 command) case COMMAND_SWITCH_LIFT_CAMERA: { CollectParameters(&m_nIp, 1); - debug("SWITCH_LIFT_CAMERA is not implemented\n"); // TODO(MIAMI) + CSpecialFX::bLiftCam = ScriptParams[0] != 0; return 0; } case COMMAND_CLOSE_ALL_CAR_DOORS: @@ -13013,12 +13013,12 @@ int8 CRunningScript::ProcessCommands1300To1399(int32 command) case COMMAND_HAS_GLASS_BEEN_SHATTERED_NEARBY: { CollectParameters(&m_nIp, 3); - static bool bShowed = false; - if (!bShowed) { - debug("HAS_GLASS_BEEN_SHATTERED_NEARBY not implemented, default to TRUE\n"); // TODO(MIAMI) - bShowed = true; - } - UpdateCompareFlag(true); + + bool shattered = false; + if ( CGlass::HasGlassBeenShatteredAtCoors(*(float*)&ScriptParams[0], *(float*)&ScriptParams[1], *(float*)&ScriptParams[2]) ) + shattered = true; + + UpdateCompareFlag(shattered); return 0; } case COMMAND_ATTACH_CUTSCENE_OBJECT_TO_BONE: diff --git a/src/core/Pools.cpp b/src/core/Pools.cpp index fe2cf7ad..b25fa4e1 100644 --- a/src/core/Pools.cpp +++ b/src/core/Pools.cpp @@ -2,6 +2,7 @@ #include "Pools.h" +#include "Bike.h" #include "Boat.h" #include "CarCtrl.h" #ifdef MISSION_REPLAY @@ -13,6 +14,8 @@ #include "Wanted.h" #include "World.h" +//--MIAMI: file done + CCPtrNodePool *CPools::ms_pPtrNodePool; CEntryInfoNodePool *CPools::ms_pEntryInfoNodePool; CPedPool *CPools::ms_pPedPool; @@ -24,7 +27,6 @@ CDummyPool *CPools::ms_pDummyPool; CAudioScriptObjectPool *CPools::ms_pAudioScriptObjectPool; CColModelPool *CPools::ms_pColModelPool; -//--MIAMI: done void CPools::Initialise(void) { @@ -40,7 +42,6 @@ CPools::Initialise(void) ms_pColModelPool = new CColModelPool(NUMCOLMODELS, "ColModel"); } -//--MIAMI: done void CPools::ShutDown(void) { @@ -119,7 +120,8 @@ void CPools::LoadVehiclePool(uint8* buf, uint32 size) INITSAVEBUF int nNumCars = ReadSaveBuf<int>(buf); int nNumBoats = ReadSaveBuf<int>(buf); - for (int i = 0; i < nNumCars + nNumBoats; i++) { + int nNumBikes = ReadSaveBuf<int>(buf); + for (int i = 0; i < nNumCars + nNumBoats + nNumBikes; i++) { uint32 type = ReadSaveBuf<uint32>(buf); int16 model = ReadSaveBuf<int16>(buf); CStreaming::RequestModel(model, STREAMFLAGS_DEPENDENCY); @@ -131,13 +133,15 @@ INITSAVEBUF pVehicle = new(slot) CBoat(model, RANDOM_VEHICLE); else if (type == VEHICLE_TYPE_CAR) pVehicle = new(slot) CAutomobile(model, RANDOM_VEHICLE); + else if (type == VEHICLE_TYPE_BIKE) + pVehicle = new(slot) CBike(model, RANDOM_VEHICLE); else assert(0); --CCarCtrl::NumRandomCars; pVehicle->Load(buf); CWorld::Add(pVehicle); #else - char* vbuf = new char[Max(CAutomobile::nSaveStructSize, CBoat::nSaveStructSize)]; + char* vbuf = new char[Max(CBike::nSaveStructSize, Max(CAutomobile::nSaveStructSize, CBoat::nSaveStructSize))]; if (type == VEHICLE_TYPE_BOAT) { memcpy(vbuf, buf, sizeof(CBoat)); SkipSaveBuf(buf, sizeof(CBoat)); @@ -156,6 +160,17 @@ INITSAVEBUF pAutomobile->Damage = ((CAutomobile*)vbuf)->Damage; pAutomobile->SetupDamageAfterLoad(); } + else if (type == VEHICLE_TYPE_BIKE) { +#ifdef FIX_BUGS + memcpy(vbuf, buf, sizeof(CBike)); +#else + memcpy(vbuf, buf, sizeof(CAutomobile)); +#endif + SkipSaveBuf(buf, sizeof(CBike)); + CBike* pBike = new(slot) CBike(model, RANDOM_VEHICLE); + pVehicle = pBike; + --CCarCtrl::NumRandomCars; + } else assert(0); CVehicle* pBufferVehicle = (CVehicle*)vbuf; @@ -193,6 +208,7 @@ INITSAVEBUF (pVehicle->GetAddressOfEntityProperties())[0] = (pBufferVehicle->GetAddressOfEntityProperties())[0]; (pVehicle->GetAddressOfEntityProperties())[1] = (pBufferVehicle->GetAddressOfEntityProperties())[1]; pVehicle->AutoPilot = pBufferVehicle->AutoPilot; + CCarCtrl::UpdateCarCount(pVehicle, false); CWorld::Add(pVehicle); delete[] vbuf; #endif @@ -205,6 +221,7 @@ void CPools::SaveVehiclePool(uint8* buf, uint32* size) INITSAVEBUF int nNumCars = 0; int nNumBoats = 0; + int nNumBikes = 0; int nPoolSize = GetVehiclePool()->GetSize(); for (int i = 0; i < nPoolSize; i++) { CVehicle* pVehicle = GetVehiclePool()->GetSlot(i); @@ -226,19 +243,25 @@ INITSAVEBUF ++nNumCars; if (pVehicle->IsBoat() && (pVehicle->VehicleCreatedBy == MISSION_VEHICLE || bForceSaving)) ++nNumBoats; + if (pVehicle->IsBike() && (pVehicle->VehicleCreatedBy == MISSION_VEHICLE || bForceSaving)) + ++nNumBoats; #else if (!pVehicle->pDriver && !bHasPassenger) { if (pVehicle->IsCar() && pVehicle->VehicleCreatedBy == MISSION_VEHICLE) ++nNumCars; if (pVehicle->IsBoat() && pVehicle->VehicleCreatedBy == MISSION_VEHICLE) ++nNumBoats; + if (pVehicle->IsBike() && pVehicle->VehicleCreatedBy == MISSION_VEHICLE) + ++nNumBoats; #endif } } *size = nNumCars * (sizeof(uint32) + sizeof(int16) + sizeof(int32) + CAutomobile::nSaveStructSize) + sizeof(int) + - nNumBoats * (sizeof(uint32) + sizeof(int16) + sizeof(int32) + CBoat::nSaveStructSize) + sizeof(int); + nNumBoats * (sizeof(uint32) + sizeof(int16) + sizeof(int32) + CBoat::nSaveStructSize) + sizeof(int) + + nNumBikes * (sizeof(uint32) + sizeof(int16) + sizeof(int32) + CBike::nSaveStructSize) + sizeof(int); WriteSaveBuf(buf, nNumCars); WriteSaveBuf(buf, nNumBoats); + WriteSaveBuf(buf, nNumBikes); for (int i = 0; i < nPoolSize; i++) { CVehicle* pVehicle = GetVehiclePool()->GetSlot(i); if (!pVehicle) @@ -258,9 +281,9 @@ INITSAVEBUF #endif #ifdef COMPATIBLE_SAVES #ifdef MISSION_REPLAY - if ((pVehicle->IsCar() || pVehicle->IsBoat()) && (pVehicle->VehicleCreatedBy == MISSION_VEHICLE || bForceSaving)) { + if ((pVehicle->IsCar() || pVehicle->IsBoat() || pVehicle->IsBike()) && (pVehicle->VehicleCreatedBy == MISSION_VEHICLE || bForceSaving)) { #else - if ((pVehicle->IsCar() || pVehicle->IsBoat()) && pVehicle->VehicleCreatedBy == MISSION_VEHICLE) { + if ((pVehicle->IsCar() || pVehicle->IsBoat() || pVehicle->IsBike()) && pVehicle->VehicleCreatedBy == MISSION_VEHICLE) { #endif WriteSaveBuf<uint32>(buf, pVehicle->m_vehType); WriteSaveBuf<int16>(buf, pVehicle->GetModelIndex()); @@ -290,6 +313,17 @@ INITSAVEBUF memcpy(buf, pVehicle, sizeof(CBoat)); SkipSaveBuf(buf, sizeof(CBoat)); } +#ifdef MISSION_REPLAY + if (pVehicle->IsBike() && (pVehicle->VehicleCreatedBy == MISSION_VEHICLE || bForceSaving)) { +#else + if (pVehicle->IsBike() && pVehicle->VehicleCreatedBy == MISSION_VEHICLE) { +#endif + WriteSaveBuf(buf, (uint32)pVehicle->m_vehType); + WriteSaveBuf(buf, pVehicle->GetModelIndex()); + WriteSaveBuf(buf, GetVehicleRef(pVehicle)); + memcpy(buf, pVehicle, sizeof(CBike)); + SkipSaveBuf(buf, sizeof(CBike)); + } #endif } } @@ -311,8 +345,9 @@ INITSAVEBUF ++nObjects; } *size = nObjects * (sizeof(int16) + sizeof(int) + sizeof(CCompressedMatrix) + - sizeof(float) + sizeof(CCompressedMatrix) + sizeof(int8) + 7 * sizeof(bool) + sizeof(float) + - sizeof(int8) + sizeof(int8) + sizeof(uint32) + 2 * sizeof(uint32)) + sizeof(int); + sizeof(float) + sizeof(CCompressedMatrix) + sizeof(int8) + 7 * sizeof(bool) + sizeof(int16) + + + sizeof(int8) * 2 + sizeof(float) + sizeof(int8) + sizeof(int8) + + sizeof(uint32) + 2 * sizeof(uint32)) + sizeof(int); CopyToBuf(buf, nObjects); for (int i = 0; i < nPoolSize; i++) { CObject* pObject = GetObjectPool()->GetSlot(i); @@ -343,6 +378,9 @@ INITSAVEBUF CopyToBuf(buf, bGlassBroken); CopyToBuf(buf, bHasBeenDamaged); CopyToBuf(buf, bUseVehicleColours); + CopyToBuf(buf, pObject->m_nCostValue); + CopyToBuf(buf, pObject->m_nBonusValue); + SkipSaveBuf(buf, 1); CopyToBuf(buf, pObject->m_fCollisionDamageMultiplier); CopyToBuf(buf, pObject->m_nCollisionDamageEffect); CopyToBuf(buf, pObject->m_nSpecialCollisionResponseCases); @@ -392,6 +430,9 @@ INITSAVEBUF pBufferObject->bHasBeenDamaged = bitFlag; CopyFromBuf(buf, bitFlag); pBufferObject->bUseVehicleColours = bitFlag; + CopyFromBuf(buf, pBufferObject->m_nCostValue); + CopyFromBuf(buf, pBufferObject->m_nBonusValue); + SkipSaveBuf(buf, 1); CopyFromBuf(buf, pBufferObject->m_fCollisionDamageMultiplier); CopyFromBuf(buf, pBufferObject->m_nCollisionDamageEffect); CopyFromBuf(buf, pBufferObject->m_nSpecialCollisionResponseCases); @@ -426,6 +467,8 @@ INITSAVEBUF (pObject->GetAddressOfEntityProperties())[1] = (pBufferObject->GetAddressOfEntityProperties())[1]; #endif pObject->bHasCollided = false; + pObject->m_nCostValue = pBufferObject->m_nCostValue; + pObject->m_nBonusValue = pBufferObject->m_nBonusValue; CWorld::Add(pObject); delete[] obuf; } diff --git a/src/core/Radar.cpp b/src/core/Radar.cpp index 4556e3b4..8fe900ae 100644 --- a/src/core/Radar.cpp +++ b/src/core/Radar.cpp @@ -924,6 +924,7 @@ INITSAVEBUF for (int i = 0; i < NUMRADARBLIPS; i++) { ms_RadarTrace[i].m_nColor = ReadSaveBuf<uint32>(buf); + ms_RadarTrace[i].m_Radius = ReadSaveBuf<float>(buf); ms_RadarTrace[i].m_eBlipType = ReadSaveBuf<uint32>(buf); ms_RadarTrace[i].m_nEntityHandle = ReadSaveBuf<int32>(buf); ms_RadarTrace[i].m_vec2DPos.x = ReadSaveBuf<float>(buf); // CVector2D @@ -934,7 +935,6 @@ INITSAVEBUF ms_RadarTrace[i].m_bInUse = ReadSaveBuf<bool>(buf); ms_RadarTrace[i].m_bShortRange = ReadSaveBuf<bool>(buf); ms_RadarTrace[i].m_unused = ReadSaveBuf<bool>(buf); - ms_RadarTrace[i].m_Radius = ReadSaveBuf<float>(buf); ms_RadarTrace[i].m_wScale = ReadSaveBuf<int16>(buf); ms_RadarTrace[i].m_eBlipDisplay = ReadSaveBuf<uint16>(buf); ms_RadarTrace[i].m_eRadarSprite = ReadSaveBuf<uint16>(buf); @@ -961,6 +961,7 @@ INITSAVEBUF sRadarTraceSave *saveStruct = (sRadarTraceSave*) buf; saveStruct->m_nColor = ms_RadarTrace[i].m_nColor; + saveStruct->m_Radius = ms_RadarTrace[i].m_Radius; saveStruct->m_eBlipType = ms_RadarTrace[i].m_eBlipType; saveStruct->m_nEntityHandle = ms_RadarTrace[i].m_nEntityHandle; saveStruct->m_vec2DPos = ms_RadarTrace[i].m_vec2DPos; @@ -970,7 +971,6 @@ INITSAVEBUF saveStruct->m_bInUse = ms_RadarTrace[i].m_bInUse; saveStruct->m_bShortRange = ms_RadarTrace[i].m_bShortRange; saveStruct->m_unused = ms_RadarTrace[i].m_unused; - saveStruct->m_Radius = ms_RadarTrace[i].m_Radius; saveStruct->m_wScale = ms_RadarTrace[i].m_wScale; saveStruct->m_eBlipDisplay = ms_RadarTrace[i].m_eBlipDisplay; saveStruct->m_eRadarSprite = ms_RadarTrace[i].m_eRadarSprite; diff --git a/src/core/Radar.h b/src/core/Radar.h index b5f34f1f..8f2e7069 100644 --- a/src/core/Radar.h +++ b/src/core/Radar.h @@ -137,6 +137,7 @@ struct sRadarTrace struct sRadarTraceSave { uint32 m_nColor; + float m_Radius; uint32 m_eBlipType; // eBlipType int32 m_nEntityHandle; CVector2D m_vec2DPos; @@ -146,7 +147,6 @@ struct sRadarTraceSave bool m_bInUse; bool m_bShortRange; bool m_unused; - float m_Radius; int16 m_wScale; uint16 m_eBlipDisplay; // eBlipDisplay uint16 m_eRadarSprite; // eRadarSprite diff --git a/src/core/Timer.cpp b/src/core/Timer.cpp index f60adf07..5adc36b5 100644 --- a/src/core/Timer.cpp +++ b/src/core/Timer.cpp @@ -5,6 +5,7 @@ #include "DMAudio.h" #include "Record.h" #include "Timer.h" +#include "SpecialFX.h" uint32 CTimer::m_snTimeInMilliseconds; PauseModeTime CTimer::m_snTimeInMillisecondsPauseMode = 1; @@ -141,7 +142,7 @@ void CTimer::Update(void) } } - if ( ms_fTimeStep < 0.01f && !GetIsPaused() ) + if ( ms_fTimeStep < 0.01f && !GetIsPaused() && !CSpecialFX::bSnapShotActive) ms_fTimeStep = 0.01f; ms_fTimeStepNonClipped = ms_fTimeStep; diff --git a/src/core/main.cpp b/src/core/main.cpp index b39a9c8b..fa5a5000 100644 --- a/src/core/main.cpp +++ b/src/core/main.cpp @@ -969,7 +969,7 @@ Render2dStuff(void) else CHud::Draw(); // TODO(Miami) - // CSpecialFX::Render2DFXs(); + CSpecialFX::Render2DFXs(); CUserDisplay::OnscnTimer.ProcessForDisplay(); CMessages::Display(); CDarkel::DrawMessages(); diff --git a/src/peds/Ped.cpp b/src/peds/Ped.cpp index 3f573171..82298e74 100644 --- a/src/peds/Ped.cpp +++ b/src/peds/Ped.cpp @@ -14,6 +14,7 @@ #include "AnimBlendClumpData.h" #include "AnimBlendAssociation.h" #include "Fire.h" +#include "Glass.h" #include "DMAudio.h" #include "General.h" #include "SurfaceTable.h" @@ -5865,7 +5866,7 @@ CPed::FightStrike(CVector &touchedNodePos, bool fightWithWeapon) if (m_fightState == FIGHTSTATE_JUST_ATTACKED) return false; - // TODO(Miami): BreakGlassPhysically + CGlass::BreakGlassPhysically(touchedNodePos, radius); for (int i = 0; i < m_numNearPeds; i++) { int8 pedFound = 0; @@ -15403,7 +15404,7 @@ CPed::ProcessObjective(void) CVector distance = m_nextRoutePointPos - GetPosition(); distance.z = 0.0f; if (m_objective == OBJECTIVE_GOTO_SHELTER_ON_FOOT) { - if (m_nMoveState == PEDMOVE_RUN && distance.Magnitude() < SQR(2.0f)) { + if (m_nMoveState == PEDMOVE_RUN && distance.MagnitudeSqr() < SQR(2.0f)) { SetMoveState(PEDMOVE_WALK); bIsRunning = false; } @@ -15413,7 +15414,7 @@ CPed::ProcessObjective(void) } } else if (m_objective == OBJECTIVE_GOTO_ICE_CREAM_VAN_ON_FOOT) { - if (m_nMoveState == PEDMOVE_RUN && distance.Magnitude() < SQR(4.0f)) { + if (m_nMoveState == PEDMOVE_RUN && distance.MagnitudeSqr() < SQR(4.0f)) { SetMoveState(PEDMOVE_WALK); bIsRunning = false; } @@ -20040,15 +20041,13 @@ CPed::Save(uint8*& buf) CopyToBuf(buf, GetPosition().z); SkipSaveBuf(buf, 288); CopyToBuf(buf, CharCreatedBy); - SkipSaveBuf(buf, 351); + SkipSaveBuf(buf, 499); CopyToBuf(buf, m_fHealth); CopyToBuf(buf, m_fArmour); - SkipSaveBuf(buf, 148); - for (int i = 0; i < 13; i++) // has to be hardcoded + SkipSaveBuf(buf, 172); + for (int i = 0; i < 10; i++) // has to be hardcoded m_weapons[i].Save(buf); - SkipSaveBuf(buf, 5); - CopyToBuf(buf, m_maxWeaponTypeAllowed); - SkipSaveBuf(buf, 162); + SkipSaveBuf(buf, 252); } void @@ -20060,16 +20059,15 @@ CPed::Load(uint8*& buf) CopyFromBuf(buf, GetMatrix().GetPosition().z); SkipSaveBuf(buf, 288); CopyFromBuf(buf, CharCreatedBy); - SkipSaveBuf(buf, 351); + SkipSaveBuf(buf, 499); CopyFromBuf(buf, m_fHealth); CopyFromBuf(buf, m_fArmour); - SkipSaveBuf(buf, 148); + SkipSaveBuf(buf, 172); + m_currentWeapon = WEAPONTYPE_UNARMED; CWeapon bufWeapon; - for (int i = 0; i < 13; i++) { // has to be hardcoded + for (int i = 0; i < 10; i++) { // has to be hardcoded bufWeapon.Load(buf); - if (i >= 10) - continue; // tmp hack before we fix save/load if (bufWeapon.m_eWeaponType != WEAPONTYPE_UNARMED) { int modelId = CWeaponInfo::GetWeaponInfo(bufWeapon.m_eWeaponType)->m_nModelId; @@ -20084,9 +20082,7 @@ CPed::Load(uint8*& buf) GiveWeapon(bufWeapon.m_eWeaponType, bufWeapon.m_nAmmoTotal); } } - SkipSaveBuf(buf, 5); - CopyFromBuf(buf, m_maxWeaponTypeAllowed); - SkipSaveBuf(buf, 162); + SkipSaveBuf(buf, 252); } #undef CopyFromBuf #undef CopyToBuf diff --git a/src/peds/PedAttractor.cpp b/src/peds/PedAttractor.cpp index 9f77f2a4..cebe31b0 100644 --- a/src/peds/PedAttractor.cpp +++ b/src/peds/PedAttractor.cpp @@ -135,8 +135,10 @@ void CPedAttractorManager::RemoveIceCreamVanEffects(C2dEffect* pEffect) if (vVehicleToEffect.empty()) return; for (std::vector<CVehicleToEffect>::const_iterator assoc = vVehicleToEffect.cbegin(); assoc != vVehicleToEffect.cend();) { - if (assoc->GetVehicle() != pVehicle) - return; + if (assoc->GetVehicle() != pVehicle) { + assoc++; + continue; + } uint32 total = 0; for (uint32 j = 0; j < NUM_ATTRACTORS_FOR_ICECREAM_VAN; j++) { if (FindAssociatedAttractor(assoc->GetEffect(j), vIceCreamAttractors)) diff --git a/src/peds/PlayerPed.cpp b/src/peds/PlayerPed.cpp index 041fb5e8..1f53853f 100644 --- a/src/peds/PlayerPed.cpp +++ b/src/peds/PlayerPed.cpp @@ -23,7 +23,7 @@ const uint32 CPlayerPed::nSaveStructSize = #ifdef COMPATIBLE_SAVES - 1520; + 1752; #else sizeof(CPlayerPed); #endif @@ -1935,7 +1935,7 @@ CPlayerPed::Save(uint8*& buf) CopyToBuf(buf, m_nTargettableObjects[1]); CopyToBuf(buf, m_nTargettableObjects[2]); CopyToBuf(buf, m_nTargettableObjects[3]); - SkipSaveBuf(buf, 116); + SkipSaveBuf(buf, 164); } void @@ -1949,7 +1949,7 @@ CPlayerPed::Load(uint8*& buf) CopyFromBuf(buf, m_nTargettableObjects[1]); CopyFromBuf(buf, m_nTargettableObjects[2]); CopyFromBuf(buf, m_nTargettableObjects[3]); - SkipSaveBuf(buf, 116); + SkipSaveBuf(buf, 164); } #undef CopyFromBuf #undef CopyToBuf diff --git a/src/render/Glass.cpp b/src/render/Glass.cpp index aabb6e52..0e26ee0b 100644 --- a/src/render/Glass.cpp +++ b/src/render/Glass.cpp @@ -3,6 +3,8 @@ #include "Glass.h" #include "Timer.h" #include "Object.h" +#include "Vehicle.h" +#include "Pools.h" #include "General.h" #include "AudioScriptObject.h" #include "World.h" @@ -14,6 +16,7 @@ #include "ModelIndices.h" #include "main.h" #include "soundlist.h" +#include "SurfaceTable.h" uint32 CGlass::NumGlassEntities; @@ -57,17 +60,17 @@ const CVector2D CoorsWithTriangle[NUM_GLASSTRIANGLES][3] = #define TEMPBUFFERVERTHILIGHTOFFSET 0 #define TEMPBUFFERINDEXHILIGHTOFFSET 0 -#define TEMPBUFFERVERTHILIGHTSIZE 128 +#define TEMPBUFFERVERTHILIGHTSIZE 256 #define TEMPBUFFERINDEXHILIGHTSIZE 512 #define TEMPBUFFERVERTSHATTEREDOFFSET TEMPBUFFERVERTHILIGHTSIZE #define TEMPBUFFERINDEXSHATTEREDOFFSET TEMPBUFFERINDEXHILIGHTSIZE -#define TEMPBUFFERVERTSHATTEREDSIZE 192 +#define TEMPBUFFERVERTSHATTEREDSIZE 384 #define TEMPBUFFERINDEXSHATTEREDSIZE 768 #define TEMPBUFFERVERTREFLECTIONOFFSET TEMPBUFFERVERTSHATTEREDSIZE #define TEMPBUFFERINDEXREFLECTIONOFFSET TEMPBUFFERINDEXSHATTEREDSIZE -#define TEMPBUFFERVERTREFLECTIONSIZE 256 +#define TEMPBUFFERVERTREFLECTIONSIZE 512 #define TEMPBUFFERINDEXREFLECTIONSIZE 1024 int32 TempBufferIndicesStoredHiLight = 0; @@ -83,10 +86,16 @@ CFallingGlassPane::Update(void) if ( CTimer::GetTimeInMilliseconds() >= m_nTimer ) { // Apply MoveSpeed - GetPosition() += m_vecMoveSpeed * CTimer::GetTimeStep(); + if ( m_bCarGlass ) + GetPosition() += m_vecMoveSpeed * CTimer::GetTimeStep() * 0.35f; + else + GetPosition() += m_vecMoveSpeed * CTimer::GetTimeStep(); // Apply Gravity - m_vecMoveSpeed.z -= 0.02f * CTimer::GetTimeStep(); + if ( m_bCarGlass ) + m_vecMoveSpeed.z -= 0.01f * CTimer::GetTimeStep(); + else + m_vecMoveSpeed.z -= 0.02f * CTimer::GetTimeStep(); // Apply TurnSpeed GetRight() += CrossProduct(m_vecTurn, GetRight()); @@ -106,24 +115,27 @@ CFallingGlassPane::Update(void) RwRGBA color = { 255, 255, 255, 255 }; - static int32 nFrameGen = 0; - - for ( int32 i = 0; i < 4; i++ ) + if ( !m_bCarGlass ) { - dir.x = CGeneral::GetRandomNumberInRange(-0.35f, 0.35f); - dir.y = CGeneral::GetRandomNumberInRange(-0.35f, 0.35f); - dir.z = CGeneral::GetRandomNumberInRange(0.05f, 0.20f); - - CParticle::AddParticle(PARTICLE_CAR_DEBRIS, - pos, - dir, - nil, - CGeneral::GetRandomNumberInRange(0.02f, 0.2f), - color, - CGeneral::GetRandomNumberInRange(-40, 40), - 0, - ++nFrameGen & 3, - 500); + static int32 nFrameGen = 0; + + for ( int32 i = 0; i < 4; i++ ) + { + dir.x = CGeneral::GetRandomNumberInRange(-0.35f, 0.35f); + dir.y = CGeneral::GetRandomNumberInRange(-0.35f, 0.35f); + dir.z = CGeneral::GetRandomNumberInRange(0.05f, 0.20f); + + CParticle::AddParticle(PARTICLE_CAR_DEBRIS, + pos, + dir, + nil, + CGeneral::GetRandomNumberInRange(0.02f, 0.2f), + color, + CGeneral::GetRandomNumberInRange(-40, 40), + 0, + ++nFrameGen & 3, + 500); + } } } } @@ -146,7 +158,10 @@ CFallingGlassPane::Render(void) CGlass::RenderHiLightPolys(); // HiLight Polys - + + if ( m_bCarGlass && color < 64 ) + color = 64; + RwIm3DVertexSetRGBA (&TempBufferRenderVertices[TempBufferVerticesStoredHiLight + 0], color, color, color, color); RwIm3DVertexSetRGBA (&TempBufferRenderVertices[TempBufferVerticesStoredHiLight + 1], color, color, color, color); RwIm3DVertexSetRGBA (&TempBufferRenderVertices[TempBufferVerticesStoredHiLight + 2], color, color, color, color); @@ -186,9 +201,9 @@ CFallingGlassPane::Render(void) if ( TempBufferIndicesStoredShattered >= TEMPBUFFERINDEXSHATTEREDSIZE-7 || TempBufferVerticesStoredShattered >= TEMPBUFFERVERTSHATTEREDSIZE-4 ) CGlass::RenderShatteredPolys(); - uint8 shatteredColor = 255; + uint8 shatteredColor = 140; if ( distToCamera > 30.0f ) - shatteredColor = int32((1.0f - (distToCamera - 30.0f) * 4.0f / 40.0f) * 255); + shatteredColor = int32((1.0f - (distToCamera - 30.0f) * 4.0f / 40.0f) * 140); RwIm3DVertexSetRGBA (&TempBufferRenderVertices[TempBufferVerticesStoredShattered + 0], shatteredColor, shatteredColor, shatteredColor, shatteredColor); RwIm3DVertexSetRGBA (&TempBufferRenderVertices[TempBufferVerticesStoredShattered + 1], shatteredColor, shatteredColor, shatteredColor, shatteredColor); @@ -292,8 +307,8 @@ CGlass::FindFreePane(void) } void -CGlass::GeneratePanesForWindow(uint32 type, CVector pos, CVector up, CVector right, CVector speed, CVector point, - float moveSpeed, bool cracked, bool explosion) +CGlass::GeneratePanesForWindow(uint32 type, CVector pos, CVector up, CVector right, CVector speed, CVector center, + float moveSpeed, bool cracked, bool explosion, int32 stepmul, bool carGlass) { float upLen = up.Magnitude(); float rightLen = right.Magnitude(); @@ -304,10 +319,10 @@ CGlass::GeneratePanesForWindow(uint32 type, CVector pos, CVector up, CVector rig float rightSteps = rightLen + 0.75f; if ( rightSteps < 1.0f ) rightSteps = 1.0f; - uint32 ysteps = (uint32)upSteps; + uint32 ysteps = stepmul * (uint32)upSteps; if ( ysteps > 3 ) ysteps = 3; - uint32 xsteps = (uint32)rightSteps; + uint32 xsteps = stepmul * (uint32)rightSteps; if ( xsteps > 3 ) xsteps = 3; if ( explosion ) @@ -338,11 +353,8 @@ CGlass::GeneratePanesForWindow(uint32 type, CVector pos, CVector up, CVector rig pane->m_nTriIndex = i; pane->GetRight() = (right * rightScl) / rightLen; -#ifdef FIX_BUGS pane->GetUp() = (up * upScl) / upLen; -#else - pane->GetUp() = (up * upScl) / rightLen; // copypaste bug -#endif + CVector fwd = CrossProduct(pane->GetRight(), pane->GetUp()); fwd.Normalise(); @@ -358,7 +370,7 @@ CGlass::GeneratePanesForWindow(uint32 type, CVector pos, CVector up, CVector rig if ( moveSpeed != 0.0f ) { - CVector dist = pane->GetPosition() - point; + CVector dist = pane->GetPosition() - center; dist.Normalise(); pane->m_vecMoveSpeed += moveSpeed * dist; @@ -371,10 +383,11 @@ CGlass::GeneratePanesForWindow(uint32 type, CVector pos, CVector up, CVector rig switch ( type ) { case 0: + case 2: pane->m_nTimer = CTimer::GetTimeInMilliseconds(); break; case 1: - float dist = (pane->GetPosition() - point).Magnitude(); + float dist = (pane->GetPosition() - center).Magnitude(); pane->m_nTimer = uint32(dist*100 + CTimer::GetTimeInMilliseconds()); break; } @@ -382,6 +395,7 @@ CGlass::GeneratePanesForWindow(uint32 type, CVector pos, CVector up, CVector rig pane->m_fGroundZ = groundZ; pane->m_bShattered = cracked; pane->m_fStep = upLen / float(ysteps); + pane->m_bCarGlass = carGlass; pane->m_bActive = true; } } @@ -613,42 +627,48 @@ CGlass::WindowRespondsToCollision(CEntity *entity, float amount, CVector speed, CColModel *col = object->GetColModel(); ASSERT(col!=nil); - CVector a = object->GetMatrix() * col->vertices[0].Get(); - CVector b = object->GetMatrix() * col->vertices[1].Get(); - CVector c = object->GetMatrix() * col->vertices[2].Get(); - CVector d = object->GetMatrix() * col->vertices[3].Get(); - - float minx = Min(Min(a.x, b.x), Min(c.x, d.x)); - float maxx = Max(Max(a.x, b.x), Max(c.x, d.x)); - float miny = Min(Min(a.y, b.y), Min(c.y, d.y)); - float maxy = Max(Max(a.y, b.y), Max(c.y, d.y)); - float minz = Min(Min(a.z, b.z), Min(c.z, d.z)); - float maxz = Max(Max(a.z, b.z), Max(c.z, d.z)); - - - if ( amount > 300.0f ) - { - PlayOneShotScriptObject(SCRIPT_SOUND_GLASS_BREAK_L, object->GetPosition()); - - GeneratePanesForWindow(0, - CVector(minx, miny, minz), - CVector(0.0f, 0.0f, maxz-minz), - CVector(maxx-minx, maxy-miny, 0.0f), - speed, point, 0.1f, !!object->bGlassCracked, explosion); - } - else + if ( col->numTriangles == 2 ) { - PlayOneShotScriptObject(SCRIPT_SOUND_GLASS_BREAK_S, object->GetPosition()); - - GeneratePanesForWindow(1, - CVector(minx, miny, minz), - CVector(0.0f, 0.0f, maxz-minz), - CVector(maxx-minx, maxy-miny, 0.0f), - speed, point, 0.1f, !!object->bGlassCracked, explosion); + CVector a = col->vertices[0].Get(); + CVector b = col->vertices[1].Get(); + CVector c = col->vertices[2].Get(); + CVector d = col->vertices[3].Get(); + + float minx = Min(Min(a.x, b.x), Min(c.x, d.x)); + float maxx = Max(Max(a.x, b.x), Max(c.x, d.x)); + float miny = Min(Min(a.y, b.y), Min(c.y, d.y)); + float maxy = Max(Max(a.y, b.y), Max(c.y, d.y)); + float minz = Min(Min(a.z, b.z), Min(c.z, d.z)); + float maxz = Max(Max(a.z, b.z), Max(c.z, d.z)); + + CVector pa = object->GetMatrix() * CVector(minx, miny, minz); + CVector pb = object->GetMatrix() * CVector(maxx, maxy, minz); + + if ( amount > 300.0f ) + { + PlayOneShotScriptObject(SCRIPT_SOUND_GLASS_BREAK_L, object->GetPosition()); + + GeneratePanesForWindow(0, + pa, + CVector(0.0f, 0.0f, maxz-minz), + pb - pa, + speed, point, 0.1f, !!object->bGlassCracked, explosion, 1, false); + } + else + { + PlayOneShotScriptObject(SCRIPT_SOUND_GLASS_BREAK_S, object->GetPosition()); + + GeneratePanesForWindow(1, + pa, + CVector(0.0f, 0.0f, maxz-minz), + pb - pa, + speed, point, 0.1f, !!object->bGlassCracked, explosion, 1, false); + } } - + object->bGlassBroken = true; - object->GetMatrix().GetPosition().z = -100.0f; + object->bIsVisible = false; + object->bUsesCollision = true; } void @@ -658,7 +678,7 @@ CGlass::WindowRespondsToSoftCollision(CEntity *entity, float amount) CObject *object = (CObject *)entity; - if ( amount > 50.0f && !object->bGlassCracked ) + if ( entity->bUsesCollision && amount > 50.0f && !object->bGlassCracked ) { PlayOneShotScriptObject(SCRIPT_SOUND_GLASS_CRACK, object->GetPosition()); object->bGlassCracked = true; @@ -674,15 +694,18 @@ CGlass::WasGlassHitByBullet(CEntity *entity, CVector point) if ( IsGlass(object->GetModelIndex()) ) { - if ( !object->bGlassCracked ) - { - PlayOneShotScriptObject(SCRIPT_SOUND_GLASS_CRACK, object->GetPosition()); - object->bGlassCracked = true; - } - else + if ( object->bUsesCollision ) { - if ( (CGeneral::GetRandomNumber() & 3) == 2 ) - WindowRespondsToCollision(object, 0.0f, CVector(0.0f, 0.0f, 0.0f), point, false); + if ( !object->bGlassCracked ) + { + PlayOneShotScriptObject(SCRIPT_SOUND_GLASS_CRACK, object->GetPosition()); + object->bGlassCracked = true; + } + else + { + if ( (CGeneral::GetRandomNumber() & 3) == 2 ) + WindowRespondsToCollision(object, 0.0f, CVector(0.0f, 0.0f, 0.0f), point, false); + } } } } @@ -693,19 +716,304 @@ CGlass::WindowRespondsToExplosion(CEntity *entity, CVector point) ASSERT(entity!=nil); CObject *object = (CObject *)entity; + + if ( object->bUsesCollision ) + { + CVector distToGlass = object->GetPosition() - point; + + float fDistToGlass = distToGlass.Magnitude(); + + if ( fDistToGlass < 10.0f ) + { + distToGlass *= (0.3f / fDistToGlass); // normalise + WindowRespondsToCollision(object, 10000.0f, distToGlass, object->GetPosition(), true); + } + else + { + if ( fDistToGlass < 30.0f ) + object->bGlassCracked = true; + } + } +} - CVector distToGlass = object->GetPosition() - point; - float fDistToGlass = distToGlass.Magnitude(); +void +CGlass::CarWindscreenShatters(CVehicle *vehicle, bool unk) +{ + ASSERT(vehicle!=nil); + + CColModel *col = vehicle->GetColModel(); + ASSERT(col!=nil); + + if ( col->numTriangles < 2 ) + return; + + CColTriangle *tria = nil; + int32 triIndex = -1; + CColTriangle *trib = nil; + + for ( int32 i = 0; i < col->numTriangles; i++ ) + { + CColTriangle *tri = &col->triangles[i]; + if ( tri->surface == SURFACE_GLASS ) + { + if ( tria ) + { + trib = tri; + break; + } + + triIndex = i; + tria = tri; + } + } + + if ( trib == nil ) + return; + + CCollision::CalculateTrianglePlanes(col); + + CColTrianglePlane *triPlanes = col->trianglePlanes; + + if ( triPlanes == nil ) + return; + + CVector planeNormal; + triPlanes[triIndex].GetNormal(planeNormal); + planeNormal = Multiply3x3(vehicle->GetMatrix(), planeNormal); + + CVector vec1 = CrossProduct(vehicle->GetRight(), planeNormal); + vec1.Normalise(); + + CVector vec2 = CrossProduct(planeNormal, vehicle->GetUp()); + vec2.Normalise(); + + CVector v[6]; + float proj1[6]; + float proj2[6]; + + v[0] = col->vertices[tria->a].Get(); + v[1] = col->vertices[tria->b].Get(); + v[2] = col->vertices[tria->c].Get(); + + v[3] = col->vertices[trib->a].Get(); + v[4] = col->vertices[trib->b].Get(); + v[5] = col->vertices[trib->c].Get(); + + v[0] = vehicle->GetMatrix() * v[0]; + v[1] = vehicle->GetMatrix() * v[1]; + v[2] = vehicle->GetMatrix() * v[2]; + v[3] = vehicle->GetMatrix() * v[3]; + v[4] = vehicle->GetMatrix() * v[4]; + v[5] = vehicle->GetMatrix() * v[5]; + + proj1[0] = DotProduct(v[0], vec1); + proj2[0] = DotProduct(v[0], vec2); + proj1[1] = DotProduct(v[1], vec1); + proj2[1] = DotProduct(v[1], vec2); + proj1[2] = DotProduct(v[2], vec1); + proj2[2] = DotProduct(v[2], vec2); + + proj1[3] = DotProduct(v[3], vec1); + proj2[3] = DotProduct(v[3], vec2); + proj1[4] = DotProduct(v[4], vec1); + proj2[4] = DotProduct(v[4], vec2); + proj1[5] = DotProduct(v[5], vec1); + proj2[5] = DotProduct(v[5], vec2); + + int32 originIndex = 0; + float max1 = proj1[0]; + float max2 = proj2[0]; + float origin = proj1[0] + proj2[0]; + + for ( int32 i = 1; i < 6; i++ ) + { + float o = proj1[i] + proj2[i]; + if ( o < origin ) + { + origin = o; + originIndex = i; + } + + if ( proj1[i] > max1 ) + max1 = proj1[i]; + if ( proj2[i] > max2 ) + max2 = proj2[i]; + } + + float bound1 = max1 - proj1[originIndex]; + float bound2 = max2 - proj2[originIndex]; + + PlayOneShotScriptObject(SCRIPT_SOUND_GLASS_BREAK_L, vehicle->GetPosition()); + + CVector center = v[originIndex] + ((0.5f*bound1) * vec1) + ((0.5f*bound2) * vec2); + CVector speed = vehicle->m_vecMoveSpeed; + CVector right = bound2 * vec2; + CVector up = bound1 * vec1; + CVector pos = v[originIndex]; + + GeneratePanesForWindow(2, pos, up, right, speed, center, 0.1f, false, false, 2, true); +} - if ( fDistToGlass < 10.0f ) +bool +CGlass::HasGlassBeenShatteredAtCoors(float x, float y, float z) +{ + CEntity *entity = nil; + float dist = 20.0f; + + int32 nStartX = Max(CWorld::GetSectorIndexX(x - 30.0f), 0); + int32 nStartY = Max(CWorld::GetSectorIndexY(y - 30.0f), 0); + int32 nEndX = Min(CWorld::GetSectorIndexX(x + 30.0f), NUMSECTORS_X-1); + int32 nEndY = Min(CWorld::GetSectorIndexY(y + 30.0f), NUMSECTORS_Y-1); + + CWorld::AdvanceCurrentScanCode(); + + for ( int32 y = nStartY; y <= nEndY; y++ ) { - distToGlass *= (0.3f / fDistToGlass); // normalise - WindowRespondsToCollision(object, 10000.0f, distToGlass, object->GetPosition(), true); + for ( int32 x = nStartX; x <= nEndX; x++ ) + { + CSector *sector = CWorld::GetSector(x, y); + + ASSERT(sector != nil); + + FindWindowSectorList(sector->m_lists[ENTITYLIST_OBJECTS], &dist, &entity, x, y, z); + FindWindowSectorList(sector->m_lists[ENTITYLIST_DUMMIES], &dist, &entity, x, y, z); + } } - else + + if ( entity ) { - if ( fDistToGlass < 30.0f ) - object->bGlassCracked = true; + if ( entity->GetType() == ENTITY_TYPE_DUMMY ) + return false; + + return !!((CObject*)entity)->bGlassBroken; } + + return false; } + +void +CGlass::FindWindowSectorList(CPtrList &list, float *dist, CEntity **entity, float x, float y, float z) +{ + ASSERT(dist!=nil); + ASSERT(entity!=nil); + + CPtrNode *node = list.first; + + while ( node != nil ) + { + CEntity *ent = (CEntity *)node->item; + uint16 scanCode = ent->m_scanCode; + node = node->next; + + ASSERT(ent!=nil); + + if ( IsGlass(ent->GetModelIndex()) ) + { + if ( scanCode != CWorld::GetCurrentScanCode() ) + { + ent->m_scanCode = CWorld::GetCurrentScanCode(); + + float dst = (CVector(x,y,z) - ent->GetPosition()).Magnitude(); + + if ( dst < *dist ) + { + *dist = dst; + *entity = ent; + } + } + } + } +} + +void +CGlass::BreakGlassPhysically(CVector pos, float radius) +{ + static uint32 breakTime = 0; + + if ( CTimer::GetTimeInMilliseconds() < breakTime + 1000 && CTimer::GetTimeInMilliseconds() >= breakTime ) + return; + + CColSphere sphere; + sphere.piece = 0; + sphere.radius = radius; + sphere.surface = 0; + + for ( int32 i = CPools::GetObjectPool()->GetSize() - 1; i >= 0; i-- ) + { + CObject *object = CPools::GetObjectPool()->GetSlot(i); + if (object) + { + if ( IsGlass(object->GetModelIndex()) ) + { + if ( object->bUsesCollision ) + { + CColModel *col = object->GetColModel(); + ASSERT(col!=nil); + + if ( col->numTriangles < 2 ) + continue; + + bool hit = false; + + CVector dist = pos - object->GetPosition(); + + sphere.center.x = DotProduct(dist, object->GetRight()); + sphere.center.y = DotProduct(dist, object->GetForward()); + sphere.center.z = DotProduct(dist, object->GetUp()); + + CCollision::CalculateTrianglePlanes(col); + + for ( int32 j = 0; j < col->numTriangles; j++ ) + { + if ( CCollision::TestSphereTriangle(sphere, + col->vertices, col->triangles[i], col->trianglePlanes[i]) ) + { + hit = true; + } + } + + if ( hit ) + { + breakTime = CTimer::GetTimeInMilliseconds(); + + if ( object->bGlassCracked ) + { + CVector a = col->vertices[0].Get(); + CVector b = col->vertices[1].Get(); + CVector c = col->vertices[2].Get(); + CVector d = col->vertices[3].Get(); + + float minx = Min(Min(a.x, b.x), Min(c.x, d.x)); + float maxx = Max(Max(a.x, b.x), Max(c.x, d.x)); + float miny = Min(Min(a.y, b.y), Min(c.y, d.y)); + float maxy = Max(Max(a.y, b.y), Max(c.y, d.y)); + float minz = Min(Min(a.z, b.z), Min(c.z, d.z)); + float maxz = Max(Max(a.z, b.z), Max(c.z, d.z)); + + CVector pa = object->GetMatrix() * CVector(minx, miny, minz); + CVector pb = object->GetMatrix() * CVector(maxx, maxy, minz); + + PlayOneShotScriptObject(SCRIPT_SOUND_GLASS_BREAK_S, object->GetPosition()); + + GeneratePanesForWindow(1, + pa, + CVector(0.0f, 0.0f, maxz-minz), + pb - pa, + CVector(0.0f, 0.0f, 0.0f), pos, 0.1f, !!object->bGlassCracked, false, 1, false); + + object->bGlassBroken = true; + object->bIsVisible = false; + object->bUsesCollision = false; + } + else + { + PlayOneShotScriptObject(SCRIPT_SOUND_GLASS_CRACK, object->GetPosition()); + object->bGlassCracked = true; + } + } + } + } + } + } +}
\ No newline at end of file diff --git a/src/render/Glass.h b/src/render/Glass.h index 937ab6a9..f1c85779 100644 --- a/src/render/Glass.h +++ b/src/render/Glass.h @@ -2,6 +2,7 @@ class CEntity; class CVehicle; +class CPtrList; class CFallingGlassPane : public CMatrix { @@ -14,6 +15,7 @@ public: uint8 m_nTriIndex; bool m_bActive; bool m_bShattered; + bool m_bCarGlass; CFallingGlassPane() { } ~CFallingGlassPane() { } @@ -39,7 +41,7 @@ public: static void Update(void); static void Render(void); static CFallingGlassPane *FindFreePane(void); - static void GeneratePanesForWindow(uint32 type, CVector pos, CVector up, CVector right, CVector speed, CVector point, float moveSpeed, bool cracked, bool explosion); + static void GeneratePanesForWindow(uint32 type, CVector pos, CVector up, CVector right, CVector speed, CVector center, float moveSpeed, bool cracked, bool explosion, int32 stepmul, bool carGlass); static void AskForObjectToBeRenderedInGlass(CEntity *entity); static void RenderEntityInGlass(CEntity *entity); static int32 CalcAlphaWithNormal(CVector *normal); @@ -50,8 +52,8 @@ public: static void WindowRespondsToSoftCollision(CEntity *entity, float amount); static void WasGlassHitByBullet(CEntity *entity, CVector point); static void WindowRespondsToExplosion(CEntity *entity, CVector point); - -//TODO(MIAMI) - static void CarWindscreenShatters(CVehicle *vehicle, bool unk) {} - static void BreakGlassPhysically(CVector, float) {} + static void CarWindscreenShatters(CVehicle *vehicle, bool unk); + static bool HasGlassBeenShatteredAtCoors(float x, float y, float z); + static void FindWindowSectorList(CPtrList &list, float *dist, CEntity **entity, float x, float y, float z); + static void BreakGlassPhysically(CVector pos, float radius); };
\ No newline at end of file diff --git a/src/render/Hud.cpp b/src/render/Hud.cpp index 3ea756fa..753bb42b 100644 --- a/src/render/Hud.cpp +++ b/src/render/Hud.cpp @@ -583,7 +583,7 @@ void CHud::Draw() CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(182.0f), SCREEN_SCALE_Y(65.0f), sPrint); - if (!CWorld::Players[CWorld::PlayerInFocus].m_nTimeLastArmourLoss || CTimer::GetTimeInMilliseconds() > CWorld::Players[CWorld::PlayerInFocus].m_nTimeLastArmourLoss + 2000 || CTimer::GetFrameCounter() & 1) { + if (!CWorld::Players[CWorld::PlayerInFocus].m_nTimeLastArmourLoss || CTimer::GetTimeInMilliseconds() > CWorld::Players[CWorld::PlayerInFocus].m_nTimeLastArmourLoss + 2000 || CTimer::GetFrameCounter() & 4) { // CFont::SetColor(ARMOUR_COLOR); CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(182.0f + 52.0f), SCREEN_SCALE_Y(65.0f), sPrintIcon); } diff --git a/src/render/SpecialFX.cpp b/src/render/SpecialFX.cpp index 08dfda35..7864b0f0 100644 --- a/src/render/SpecialFX.cpp +++ b/src/render/SpecialFX.cpp @@ -24,21 +24,44 @@ #include "ColStore.h" #include "Coronas.h" #include "Script.h" +#include "DMAudio.h" RwIm3DVertex StreakVertices[4]; RwImVertexIndex StreakIndexList[12]; -RwIm3DVertex TraceVertices[6]; -RwImVertexIndex TraceIndexList[12]; +RwIm3DVertex TraceVertices[10]; +static RwImVertexIndex TraceIndexList[48] = {0, 5, 7, 0, 7, 2, 0, 7, 5, 0, 2, 7, 0, 4, 9, 0, + 9, 5, 0, 9, 4, 0, 5, 9, 0, 1, 6, 0, 6, 5, 0, 6, + 1, 0, 5, 6, 0, 3, 8, 0, 8, 5, 0, 8, 3, 0, 5, 8 }; +bool CSpecialFX::bVideoCam; +bool CSpecialFX::bLiftCam; bool CSpecialFX::bSnapShotActive; int32 CSpecialFX::SnapShotFrames; +static RwTexture* gpSmokeTrailTexture; + void CSpecialFX::Init(void) { CBulletTraces::Init(); + RwIm3DVertexSetU(&TraceVertices[0], 0.0); + RwIm3DVertexSetV(&TraceVertices[0], 0.0); + RwIm3DVertexSetU(&TraceVertices[1], 1.0); + RwIm3DVertexSetV(&TraceVertices[1], 0.0); + RwIm3DVertexSetU(&TraceVertices[2], 1.0); + RwIm3DVertexSetV(&TraceVertices[2], 0.0); + RwIm3DVertexSetU(&TraceVertices[3], 1.0); + RwIm3DVertexSetV(&TraceVertices[3], 0.0); + RwIm3DVertexSetU(&TraceVertices[4], 1.0); + RwIm3DVertexSetV(&TraceVertices[4], 0.0); + RwIm3DVertexSetU(&TraceVertices[5], 0.0); + RwIm3DVertexSetU(&TraceVertices[6], 1.0); + RwIm3DVertexSetU(&TraceVertices[7], 1.0); + RwIm3DVertexSetU(&TraceVertices[8], 1.0); + RwIm3DVertexSetU(&TraceVertices[9], 1.0); + RwIm3DVertexSetU(&StreakVertices[0], 0.0f); RwIm3DVertexSetV(&StreakVertices[0], 0.0f); RwIm3DVertexSetU(&StreakVertices[1], 1.0f); @@ -47,7 +70,6 @@ CSpecialFX::Init(void) RwIm3DVertexSetV(&StreakVertices[2], 0.0f); RwIm3DVertexSetU(&StreakVertices[3], 1.0f); RwIm3DVertexSetV(&StreakVertices[3], 0.0f); - StreakIndexList[0] = 0; StreakIndexList[1] = 1; StreakIndexList[2] = 2; @@ -61,43 +83,51 @@ CSpecialFX::Init(void) StreakIndexList[10] = 2; StreakIndexList[11] = 3; - RwIm3DVertexSetRGBA(&TraceVertices[0], 20, 20, 20, 255); - RwIm3DVertexSetRGBA(&TraceVertices[1], 20, 20, 20, 255); - RwIm3DVertexSetRGBA(&TraceVertices[2], 70, 70, 70, 255); - RwIm3DVertexSetRGBA(&TraceVertices[3], 70, 70, 70, 255); - RwIm3DVertexSetRGBA(&TraceVertices[4], 10, 10, 10, 255); - RwIm3DVertexSetRGBA(&TraceVertices[5], 10, 10, 10, 255); - RwIm3DVertexSetU(&TraceVertices[0], 0.0); - RwIm3DVertexSetV(&TraceVertices[0], 0.0); - RwIm3DVertexSetU(&TraceVertices[1], 1.0); - RwIm3DVertexSetV(&TraceVertices[1], 0.0); - RwIm3DVertexSetU(&TraceVertices[2], 0.0); - RwIm3DVertexSetV(&TraceVertices[2], 0.5); - RwIm3DVertexSetU(&TraceVertices[3], 1.0); - RwIm3DVertexSetV(&TraceVertices[3], 0.5); - RwIm3DVertexSetU(&TraceVertices[4], 0.0); - RwIm3DVertexSetV(&TraceVertices[4], 1.0); - RwIm3DVertexSetU(&TraceVertices[5], 1.0); - RwIm3DVertexSetV(&TraceVertices[5], 1.0); - - TraceIndexList[0] = 0; - TraceIndexList[1] = 2; - TraceIndexList[2] = 1; - TraceIndexList[3] = 1; - TraceIndexList[4] = 2; - TraceIndexList[5] = 3; - TraceIndexList[6] = 2; - TraceIndexList[7] = 4; - TraceIndexList[8] = 3; - TraceIndexList[9] = 3; - TraceIndexList[10] = 4; - TraceIndexList[11] = 5; - CMotionBlurStreaks::Init(); CBrightLights::Init(); CShinyTexts::Init(); CMoneyMessages::Init(); C3dMarkers::Init(); + CSpecialFX::bSnapShotActive = false; + CSpecialFX::bVideoCam = false; + CSpecialFX::SnapShotFrames = 0; + CSpecialFX::bLiftCam = false; + CTxdStore::PushCurrentTxd(); + CTxdStore::SetCurrentTxd(CTxdStore::FindTxdSlot("particle")); + if(gpSmokeTrailTexture == nil) + gpSmokeTrailTexture = RwTextureRead("smoketrail", 0); + CTxdStore::PopCurrentTxd(); +} + +void +CSpecialFX::AddWeaponStreak(int type) +{ + static CMatrix matrix; + CVector start; + CVector end; + + if (FindPlayerPed() != nil && FindPlayerPed()->m_pWeaponModel != nil) { + switch (type) { + case WEAPONTYPE_BASEBALLBAT: + matrix = RwFrameGetLTM(RpAtomicGetFrame(FindPlayerPed()->m_pWeaponModel)); + start = matrix * CVector(0.02f, 0.05f, 0.07f); + end = matrix * CVector(0.246f, 0.0325f, 0.796f); + break; + case WEAPONTYPE_GOLFCLUB: + matrix = RwFrameGetLTM(RpAtomicGetFrame(FindPlayerPed()->m_pWeaponModel)); + start = matrix * CVector(0.02f, 0.05f, 0.07f); + end = matrix * CVector(-0.054f, 0.0325f, 0.796f); + break; + case WEAPONTYPE_KATANA: + matrix = RwFrameGetLTM(RpAtomicGetFrame(FindPlayerPed()->m_pWeaponModel)); + start = matrix * CVector(0.02f, 0.05f, 0.07f); + end = matrix * CVector(0.096f, -0.0175f, 1.096f); + break; + default: + return; + } + CMotionBlurStreaks::RegisterStreak((uintptr)FindPlayerPed()->m_pWeaponModel, 100, 100, 100, start, end); + } } RwObject* @@ -119,23 +149,16 @@ CSpecialFX::Update(void) { CMotionBlurStreaks::Update(); CBulletTraces::Update(); - - if(FindPlayerPed() && - FindPlayerPed()->GetWeapon()->m_eWeaponType == WEAPONTYPE_BASEBALLBAT && - FindPlayerPed()->GetWeapon()->m_eWeaponState == WEAPONSTATE_FIRING){ -#ifdef PED_SKIN - if(IsClumpSkinned(FindPlayerPed()->GetClump())){ - LookForBatCB((RwObject*)FindPlayerPed()->m_pWeaponModel, CModelInfo::GetModelInfo(MI_BASEBALL_BAT)); - }else -#endif - RwFrameForAllObjects(FindPlayerPed()->m_pFrames[PED_HANDR]->frame, LookForBatCB, CModelInfo::GetModelInfo(MI_BASEBALL_BAT)); - } } void CSpecialFX::Shutdown(void) { C3dMarkers::Shutdown(); + if (gpSmokeTrailTexture) { + RwTextureDestroy(gpSmokeTrailTexture); + gpSmokeTrailTexture = nil; + } } void @@ -149,6 +172,80 @@ CSpecialFX::Render(void) C3dMarkers::Render(); } +void +CSpecialFX::Render2DFXs(void) +{ + if (CSpecialFX::bVideoCam) { + CFont::SetScale(SCREEN_SCALE_X(1.5f), SCREEN_SCALE_Y(1.5f)); + CFont::SetJustifyOff(); + CFont::SetBackgroundOff(); + CFont::SetCentreSize(SCREEN_SCALE_FROM_RIGHT(20.0f)); + CFont::SetCentreOff(); + CFont::SetPropOn(); + CFont::SetColor(CRGBA(0, 255, 0, 200)); + FONT_LOCALE(FONT_STANDARD); + sprintf(gString, "%d", CTimer::GetFrameCounter() & 0x3F); // mb % 63 + AsciiToUnicode(gString, gUString); + CFont::PrintString(SCREEN_WIDTH * 8 / 10, SCREEN_HEIGHT * 8 / 10, gUString); + for (int32 i = 0; i < SCREEN_HEIGHT; i += 4) { + RwRenderStateSet(rwRENDERSTATESRCBLEND, (void *)rwBLENDONE); + RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void *)rwBLENDONE); + CSprite2d::Draw2DPolygon(0.0f, i, SCREEN_WIDTH, i, 0.0f, i+1, SCREEN_WIDTH, i+1, CRGBA(0, 100, 0, 100)); + RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA); + RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA); + CSprite2d::Draw2DPolygon(0.0f, i+2, SCREEN_WIDTH, i+2, 0.0f, i+3, SCREEN_WIDTH, i+3, CRGBA(0, 0, 0, 150)); + } + int32 tmp = (CTimer::GetTimeInMilliseconds() & 0x7ff) * (SCREEN_HEIGHT + 70.0f) / 2048 - 70.0f; //mb % 2048 + RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA); + RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA); + CSprite2d::Draw2DPolygon(0.0, tmp, SCREEN_WIDTH, tmp, 0.0, tmp + 70.0f, SCREEN_WIDTH, tmp + 70.0f , CRGBA(0, 100, 0, 60)); + } + if (CSpecialFX::bLiftCam) { + CFont::SetScale(SCREEN_SCALE_X(1.5f), SCREEN_SCALE_Y(1.5f)); + CFont::SetJustifyOff(); + CFont::SetBackgroundOff(); + CFont::SetCentreSize(SCREEN_SCALE_FROM_RIGHT(20.0f)); + CFont::SetCentreOff(); + CFont::SetPropOn(); + CFont::SetColor(CRGBA(100, 100, 100, 200)); + FONT_LOCALE(FONT_STANDARD); + CFont::PrintString(SCREEN_WIDTH * 8 / 10, SCREEN_HEIGHT * 8 / 10, gUString); + for (int32 i = 0; i < SCREEN_HEIGHT; i += 4) { + RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDONE); + RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDONE); + CSprite2d::Draw2DPolygon(0.0f, i, SCREEN_WIDTH, i, 0.0f, i + 1, SCREEN_WIDTH, i + 1, CRGBA(100, 100, 100, 100)); + RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA); + RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA); + CSprite2d::Draw2DPolygon(0.0f, i + 2, SCREEN_WIDTH, i + 2, 0.0f, i + 3, SCREEN_WIDTH, i + 3, CRGBA(0, 0, 0, 150)); + } + int32 tmp = (CTimer::GetTimeInMilliseconds() & 0x7ff) * (SCREEN_HEIGHT + 70.0f) / 2048 - 70.0f; //mb % 2048 + RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA); + RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA); + CSprite2d::Draw2DPolygon(0.0, tmp, SCREEN_WIDTH, tmp, 0.0, tmp + 70.0f, SCREEN_WIDTH, tmp + 70.0f, CRGBA(100, 100, 100, 60)); + for (int32 i = 0; i < 200; i++) { + int32 posX = CGeneral::GetRandomNumber() % (int32)SCREEN_WIDTH; + int32 posY = CGeneral::GetRandomNumber() % (int32)SCREEN_HEIGHT; + CSprite2d::DrawRect(CRect(posX, posY + 2, posX+20, posY), CRGBA(255, 255, 255, 64)); + } + } + if (CSpecialFX::bSnapShotActive) { + if (++CSpecialFX::SnapShotFrames > 20) { + CSpecialFX::bSnapShotActive = false; + CTimer::SetTimeScale(1.0f); + } else { + CTimer::SetTimeScale(0.0f); //in andro it's 0.00001 + if (CSpecialFX::SnapShotFrames < 10) { + int32 tmp = (255 - 255 * CSpecialFX::SnapShotFrames / 10) * 0.65f; + RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDONE); + RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDONE); + CSprite2d::Draw2DPolygon(0.0f, 0.0f, SCREEN_WIDTH, 0.0f, 0.0f, SCREEN_HEIGHT, SCREEN_WIDTH, SCREEN_HEIGHT, CRGBA(tmp, tmp, tmp, tmp)); + RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA); + RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA); + } + } + } +} + CRegisteredMotionBlurStreak CMotionBlurStreaks::aStreaks[NUMMBLURSTREAKS]; void @@ -217,6 +314,7 @@ void CMotionBlurStreaks::RegisterStreak(uintptr id, uint8 r, uint8 g, uint8 b, CVector p1, CVector p2) { int i; + for(i = 0; i < NUMMBLURSTREAKS; i++){ if(aStreaks[i].m_id == id){ // Found a streak from last frame, update @@ -229,10 +327,12 @@ CMotionBlurStreaks::RegisterStreak(uintptr id, uint8 r, uint8 g, uint8 b, CVecto return; } } + // Find free slot - for(i = 0; aStreaks[i].m_id != 0; i++) + for(i = 0; aStreaks[i].m_id != 0 ; i++) if(i == NUMMBLURSTREAKS-1) return; + // Create a new streak aStreaks[i].m_id = id; aStreaks[i].m_red = r; @@ -281,20 +381,103 @@ void CBulletTraces::Init(void) aTraces[i].m_bInUse = false; } -void CBulletTraces::AddTrace(CVector* vecStart, CVector* vecTarget) +void CBulletTraces::AddTrace(CVector* start, CVector* end, float thickness, uint32 lifeTime, uint8 visibility) { - int index; - for (index = 0; index < NUMBULLETTRACES; index++) { - if (!aTraces[index].m_bInUse) - break; + int32 enabledCount; + uint32 modifiedLifeTime; + int32 nextSlot; + + enabledCount = 0; + for (int i = 0; i < NUMBULLETTRACES; i++) + if (aTraces[i].m_bInUse) + enabledCount++; + if (enabledCount >= 10) + modifiedLifeTime = lifeTime / 4; + else if (enabledCount >= 5) + modifiedLifeTime = lifeTime / 2; + else + modifiedLifeTime = lifeTime; + + nextSlot = 0; + for (int i = 0; nextSlot < NUMBULLETTRACES && aTraces[i].m_bInUse; i++) + nextSlot++; + if (nextSlot < 16) { + aTraces[nextSlot].m_vecStartPos = *start; + aTraces[nextSlot].m_vecEndPos = *end; + aTraces[nextSlot].m_bInUse = true; + aTraces[nextSlot].m_nCreationTime = CTimer::GetTimeInMilliseconds(); + aTraces[nextSlot].m_fVisibility = visibility; + aTraces[nextSlot].m_fThickness = thickness; + aTraces[nextSlot].m_nLifeTime = modifiedLifeTime; + } + + float startProjFwd = DotProduct(TheCamera.GetForward(), *start - TheCamera.GetPosition()); + float endProjFwd = DotProduct(TheCamera.GetForward(), *end - TheCamera.GetPosition()); + if (startProjFwd * endProjFwd < 0.0f) { //if one of point behind us and second before us + float fStartDistFwd = Abs(startProjFwd) / (Abs(startProjFwd) + Abs(endProjFwd)); + + float startProjUp = DotProduct(TheCamera.GetUp(), *start - TheCamera.GetPosition()); + float endProjUp = DotProduct(TheCamera.GetUp(), *end - TheCamera.GetPosition()); + float distUp = (endProjUp - startProjUp) * fStartDistFwd + startProjUp; + + float startProjRight = DotProduct(TheCamera.GetRight(), *start - TheCamera.GetPosition()); + float endProjRight = DotProduct(TheCamera.GetRight(), *end - TheCamera.GetPosition()); + float distRight = (endProjRight - startProjRight) * fStartDistFwd + startProjRight; + + float dist = Sqrt(SQR(distUp) + SQR(distRight)); + if (dist < 2.0f) { + if(distRight < 0.0f) + DMAudio.PlayFrontEndSound(SOUND_BULLETTRACE_2, 127 * (1.0f - dist * 0.5f)); + else + DMAudio.PlayFrontEndSound(SOUND_BULLETTRACE_1, 127 * (1.0f - dist * 0.5f)); + } + } +} + +void CBulletTraces::AddTrace(CVector* start, CVector* end, int32 weaponType, class CEntity* shooter) +{ + CPhysical* player; + float speed; + int16 camMode; + + if (shooter == (CEntity*)FindPlayerPed() || (FindPlayerVehicle() != nil && FindPlayerVehicle() == (CVehicle*)shooter)) { + camMode = TheCamera.Cams[TheCamera.ActiveCam].Mode; + if (camMode == CCam::MODE_M16_1STPERSON + || camMode == CCam::MODE_CAMERA + || camMode == CCam::MODE_SNIPER + || camMode == CCam::MODE_M16_1STPERSON_RUNABOUT + || camMode == CCam::MODE_ROCKETLAUNCHER + || camMode == CCam::MODE_ROCKETLAUNCHER_RUNABOUT + || camMode == CCam::MODE_SNIPER_RUNABOUT + || camMode == CCam::MODE_HELICANNON_1STPERSON) { + + player = FindPlayerVehicle() ? (CPhysical*)FindPlayerVehicle() : (CPhysical*)FindPlayerPed(); + speed = player->m_vecMoveSpeed.Magnitude(); + if (speed < 0.05f) + return; + } + } + + switch (weaponType) { + case WEAPONTYPE_PYTHON: + case WEAPONTYPE_SHOTGUN: + case WEAPONTYPE_SPAS12_SHOTGUN: + case WEAPONTYPE_STUBBY_SHOTGUN: + CBulletTraces::AddTrace(start, end, 0.7f, 1000, 200); + break; + case WEAPONTYPE_M4: + case WEAPONTYPE_RUGER: + case WEAPONTYPE_SNIPERRIFLE: + case WEAPONTYPE_LASERSCOPE: + case WEAPONTYPE_M60: + case WEAPONTYPE_MINIGUN: + case WEAPONTYPE_HELICANNON: + CBulletTraces::AddTrace(start, end, 1.0f, 2000, 220); + break; + default: + CBulletTraces::AddTrace(start, end, 0.4f, 750, 150); + break; } - if (index == NUMBULLETTRACES) - return; - aTraces[index].m_vecCurrentPos = *vecStart; - aTraces[index].m_vecTargetPos = *vecTarget; - aTraces[index].m_bInUse = true; - aTraces[index].m_framesInUse = 0; - aTraces[index].m_lifeTime = 25 + CGeneral::GetRandomNumber() % 32; } void CBulletTraces::Render(void) @@ -303,31 +486,131 @@ void CBulletTraces::Render(void) if (!aTraces[i].m_bInUse) continue; RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)FALSE); + RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA); + RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA); + RwRenderStateSet(rwRENDERSTATETEXTURERASTER, RwTextureGetRaster(gpSmokeTrailTexture)); + + float timeAlive = CTimer::GetTimeInMilliseconds() - aTraces[i].m_nCreationTime; + + float traceThickness = aTraces[i].m_fThickness * timeAlive / aTraces[i].m_nLifeTime; + CVector horizontalOffset = aTraces[i].m_vecEndPos - aTraces[i].m_vecStartPos; + horizontalOffset.Normalise(); + horizontalOffset *= traceThickness; + + //then closer trace to die then it more transparent + uint8 nAlphaValue = aTraces[i].m_fVisibility * (aTraces[i].m_nLifeTime - timeAlive) / aTraces[i].m_nLifeTime; + + CVector start = aTraces[i].m_vecStartPos; + CVector end = aTraces[i].m_vecEndPos; + float startProj = DotProduct(start - TheCamera.GetPosition(), TheCamera.GetForward()) - 0.7f; + float endProj = DotProduct(end - TheCamera.GetPosition(), TheCamera.GetForward()) - 0.7f; + if (startProj < 0.0f && endProj < 0.0f) //we dont need render trace behind us + continue; + + if (startProj < 0.0f) { //if strat behind us move it closer + float absStartProj = Abs(startProj); + float absEndProj = Abs(endProj); + start = (absEndProj * start + absStartProj * end) / (absStartProj + absEndProj); + } else if (endProj < 0.0f) { + float absStartProj = Abs(startProj); + float absEndProj = Abs(endProj); + end = (absEndProj * start + absStartProj * end) / (absStartProj + absEndProj); + } + + //we divide trace at three parts + CVector start2 = (7.0f * start + end) / 8; + CVector end2 = (7.0f * end + start) / 8; + + RwIm3DVertexSetV(&TraceVertices[5], 10.0f); + RwIm3DVertexSetV(&TraceVertices[6], 10.0f); + RwIm3DVertexSetV(&TraceVertices[7], 10.0f); + RwIm3DVertexSetV(&TraceVertices[8], 10.0f); + RwIm3DVertexSetV(&TraceVertices[9], 10.0f); + + RwIm3DVertexSetRGBA(&TraceVertices[0], 255, 255, 255, nAlphaValue); + RwIm3DVertexSetRGBA(&TraceVertices[1], 255, 255, 255, nAlphaValue); + RwIm3DVertexSetRGBA(&TraceVertices[2], 255, 255, 255, nAlphaValue); + RwIm3DVertexSetRGBA(&TraceVertices[3], 255, 255, 255, nAlphaValue); + RwIm3DVertexSetRGBA(&TraceVertices[4], 255, 255, 255, nAlphaValue); + RwIm3DVertexSetRGBA(&TraceVertices[5], 255, 255, 255, nAlphaValue); + RwIm3DVertexSetRGBA(&TraceVertices[6], 255, 255, 255, nAlphaValue); + RwIm3DVertexSetRGBA(&TraceVertices[7], 255, 255, 255, nAlphaValue); + RwIm3DVertexSetRGBA(&TraceVertices[8], 255, 255, 255, nAlphaValue); + RwIm3DVertexSetRGBA(&TraceVertices[9], 255, 255, 255, nAlphaValue); + //two points in center + RwIm3DVertexSetPos(&TraceVertices[0], start2.x, start2.y, start2.z); + RwIm3DVertexSetPos(&TraceVertices[5], end2.x, end2.y, end2.z); + //vertical planes + RwIm3DVertexSetPos(&TraceVertices[1], start2.x, start2.y, start2.z + traceThickness); + RwIm3DVertexSetPos(&TraceVertices[3], start2.x, start2.y, start2.z - traceThickness); + RwIm3DVertexSetPos(&TraceVertices[6], end2.x, end2.y, end2.z + traceThickness); + RwIm3DVertexSetPos(&TraceVertices[8], end2.x, end2.y, end2.z - traceThickness); + //horizontal planes + RwIm3DVertexSetPos(&TraceVertices[2], start2.x + horizontalOffset.y, start2.y - horizontalOffset.x, start2.z); + RwIm3DVertexSetPos(&TraceVertices[7], end2.x + horizontalOffset.y, end2.y - horizontalOffset.x, end2.z); +#ifdef FIX_BUGS //this point calculated wrong for some reason + RwIm3DVertexSetPos(&TraceVertices[4], start2.x - horizontalOffset.y, start2.y + horizontalOffset.x, start2.z); + RwIm3DVertexSetPos(&TraceVertices[9], end2.x - horizontalOffset.y, end2.y + horizontalOffset.x, end2.z); +#else + RwIm3DVertexSetPos(&TraceVertices[4], start2.x - horizontalOffset.y, start2.y - horizontalOffset.y, start2.z); + RwIm3DVertexSetPos(&TraceVertices[9], end2.x - horizontalOffset.y, end2.y - horizontalOffset.y, end2.z); +#endif + + if (RwIm3DTransform(TraceVertices, ARRAY_SIZE(TraceVertices), nil, 1)) { + RwIm3DRenderIndexedPrimitive(rwPRIMTYPETRILIST, TraceIndexList, ARRAY_SIZE(TraceIndexList)); + RwIm3DEnd(); + } + + RwIm3DVertexSetV(&TraceVertices[5], 2.0f); + RwIm3DVertexSetV(&TraceVertices[6], 2.0f); + RwIm3DVertexSetV(&TraceVertices[7], 2.0f); + RwIm3DVertexSetV(&TraceVertices[8], 2.0f); + RwIm3DVertexSetV(&TraceVertices[9], 2.0f); + RwIm3DVertexSetRGBA(&TraceVertices[0], 255, 255, 255, 0); + RwIm3DVertexSetRGBA(&TraceVertices[1], 255, 255, 255, 0); + RwIm3DVertexSetRGBA(&TraceVertices[2], 255, 255, 255, 0); + RwIm3DVertexSetRGBA(&TraceVertices[3], 255, 255, 255, 0); + RwIm3DVertexSetRGBA(&TraceVertices[4], 255, 255, 255, 0); + + RwIm3DVertexSetPos(&TraceVertices[0], start.x, start.y, start.z); + RwIm3DVertexSetPos(&TraceVertices[1], start.x, start.y, start.z + traceThickness); + RwIm3DVertexSetPos(&TraceVertices[3], start.x, start.y, start.z - traceThickness); + RwIm3DVertexSetPos(&TraceVertices[2], start.x + horizontalOffset.y, start.y - horizontalOffset.x, start.z); + + RwIm3DVertexSetPos(&TraceVertices[5], start2.x, start2.y, start2.z); + RwIm3DVertexSetPos(&TraceVertices[6], start2.x, start2.y, start2.z + traceThickness); + RwIm3DVertexSetPos(&TraceVertices[8], start2.x, start2.y, start2.z - traceThickness); + RwIm3DVertexSetPos(&TraceVertices[7], start2.x + horizontalOffset.y, start2.y - horizontalOffset.x, start2.z); #ifdef FIX_BUGS - // Raster has no transparent pixels so it relies on the raster format having alpha - // to turn on blending. librw image conversion might get rid of it right now so let's - // just force it on. - RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)TRUE); + RwIm3DVertexSetPos(&TraceVertices[4], start.x - horizontalOffset.y, start.y + horizontalOffset.x, start.z); + RwIm3DVertexSetPos(&TraceVertices[9], start2.x - horizontalOffset.y, start2.y + horizontalOffset.x, start2.z); +#else + RwIm3DVertexSetPos(&TraceVertices[4], start.x - horizontalOffset.y, start.y - horizontalOffset.y, start.z); + RwIm3DVertexSetPos(&TraceVertices[9], start2.x - horizontalOffset.y, start2.y - horizontalOffset.y, start2.z); #endif - RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDONE); - RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDONE); - RwRenderStateSet(rwRENDERSTATETEXTURERASTER, RwTextureGetRaster(gpShadowExplosionTex)); - CVector inf = aTraces[i].m_vecCurrentPos; - CVector sup = aTraces[i].m_vecTargetPos; - CVector center = (inf + sup) / 2; - CVector width = CrossProduct(TheCamera.GetForward(), (sup - inf)); - width.Normalise(); - width /= 20; - uint8 intensity = aTraces[i].m_lifeTime; - for (int i = 0; i < ARRAY_SIZE(TraceVertices); i++) - RwIm3DVertexSetRGBA(&TraceVertices[i], intensity, intensity, intensity, 0xFF); - RwIm3DVertexSetPos(&TraceVertices[0], inf.x + width.x, inf.y + width.y, inf.z + width.z); - RwIm3DVertexSetPos(&TraceVertices[1], inf.x - width.x, inf.y - width.y, inf.z - width.z); - RwIm3DVertexSetPos(&TraceVertices[2], center.x + width.x, center.y + width.y, center.z + width.z); - RwIm3DVertexSetPos(&TraceVertices[3], center.x - width.x, center.y - width.y, center.z - width.z); - RwIm3DVertexSetPos(&TraceVertices[4], sup.x + width.x, sup.y + width.y, sup.z + width.z); - RwIm3DVertexSetPos(&TraceVertices[5], sup.x - width.x, sup.y - width.y, sup.z - width.z); - LittleTest(); + + if (RwIm3DTransform(TraceVertices, ARRAY_SIZE(TraceVertices), nil, rwIM3D_VERTEXUV)) { + RwIm3DRenderIndexedPrimitive(rwPRIMTYPETRILIST, TraceIndexList, ARRAY_SIZE(TraceIndexList)); + RwIm3DEnd(); + } + + RwIm3DVertexSetPos(&TraceVertices[1], end.x, end.y, end.z); + RwIm3DVertexSetPos(&TraceVertices[2], end.x, end.y, end.z + traceThickness); + RwIm3DVertexSetPos(&TraceVertices[4], end.x, end.y, end.z - traceThickness); + RwIm3DVertexSetPos(&TraceVertices[3], end.x + horizontalOffset.y, end.y - horizontalOffset.x, end.z); + + RwIm3DVertexSetPos(&TraceVertices[5], end2.x, end2.y, end2.z); + RwIm3DVertexSetPos(&TraceVertices[6], end2.x, end2.y, end2.z + traceThickness); + RwIm3DVertexSetPos(&TraceVertices[8], end2.x, end2.y, end2.z - traceThickness); + RwIm3DVertexSetPos(&TraceVertices[7], end2.x + horizontalOffset.y, end2.y - horizontalOffset.x, end2.z); +#ifdef FIX_BUGS + RwIm3DVertexSetPos(&TraceVertices[5], end.x - horizontalOffset.y, end.y + horizontalOffset.x, end.z); + RwIm3DVertexSetPos(&TraceVertices[9], end2.x - horizontalOffset.y, end2.y + horizontalOffset.x, end2.z); +#else + RwIm3DVertexSetPos(&TraceVertices[5], end.x - horizontalOffset.y, end.y - horizontalOffset.y, end.z); + RwIm3DVertexSetPos(&TraceVertices[9], end2.x - horizontalOffset.y, end2.y - horizontalOffset.y, end2.z); +#endif + if (RwIm3DTransform(TraceVertices, ARRAY_SIZE(TraceVertices), nil, rwIM3D_VERTEXUV)) { RwIm3DRenderIndexedPrimitive(rwPRIMTYPETRILIST, TraceIndexList, ARRAY_SIZE(TraceIndexList)); RwIm3DEnd(); @@ -348,23 +631,8 @@ void CBulletTraces::Update(void) void CBulletTrace::Update(void) { - if (m_framesInUse == 0) { - m_framesInUse++; - return; - } - if (m_framesInUse > 60) { + if (CTimer::GetTimeInMilliseconds() - m_nCreationTime >= m_nLifeTime) m_bInUse = false; - return; - } - CVector diff = m_vecCurrentPos - m_vecTargetPos; - float remaining = diff.Magnitude(); - if (remaining > 0.8f) - m_vecCurrentPos = m_vecTargetPos + (remaining - 0.8f) / remaining * diff; - else - m_bInUse = false; - if (--m_lifeTime == 0) - m_bInUse = false; - m_framesInUse++; } RpAtomic * @@ -578,7 +846,7 @@ C3dMarkers::PlaceMarker(uint32 identifier, uint16 type, CVector &pos, float size } else { pMarker->m_fStdSize = size; } - } else if (type == MARKERTYPE_CYLINDER) { + } else { if (dist < size + 12.0f) { if (dist > size + 1.0f) pMarker->m_Color.alpha = (1.0f - (size + 12.0f - dist) * 0.7f / 11.0f) * (float)a; @@ -591,15 +859,9 @@ C3dMarkers::PlaceMarker(uint32 identifier, uint16 type, CVector &pos, float size float someSin = Sin(TWOPI * (float)((pMarker->m_nPulsePeriod - 1) & (CTimer::GetTimeInMilliseconds() - pMarker->m_nStartTime)) / (float)pMarker->m_nPulsePeriod); pMarker->m_fSize = pMarker->m_fStdSize - pulseFraction * pMarker->m_fStdSize * someSin; - if (type == MARKERTYPE_ARROW) { + if (type == MARKERTYPE_ARROW) pos.z += 0.25f * pMarker->m_fStdSize * someSin; - } else if (type == MARKERTYPE_0) { - if (someSin > 0.0f) - pMarker->m_Color.alpha = (float)a * 0.7f * someSin + a; - else - pMarker->m_Color.alpha = (float)a * 0.4f * someSin + a; - } - if (pMarker->m_nRotateRate) { + if (pMarker->m_nRotateRate != 0) { RwV3d pos = pMarker->m_Matrix.m_matrix.pos; pMarker->m_Matrix.RotateZ(DEGTORAD(pMarker->m_nRotateRate * CTimer::GetTimeStep())); pMarker->m_Matrix.GetPosition() = pos; @@ -623,7 +885,7 @@ C3dMarkers::PlaceMarker(uint32 identifier, uint16 type, CVector &pos, float size pMarker->DeleteMarkerObject(); pMarker->AddMarker(identifier, type, size, r, g, b, a, pulsePeriod, pulseFraction, rotateRate); - if (type == MARKERTYPE_CYLINDER || type == MARKERTYPE_0 || type == MARKERTYPE_2) { + if (type == MARKERTYPE_CYLINDER) { if ((playerPos - pos).MagnitudeSqr() < sq(100.f) && CColStore::HasCollisionLoaded(CVector2D(pos))) { float z = CWorld::FindGroundZFor3DCoord(pos.x, pos.y, pos.z + 1.0f, nil); if (z != 0.0f) @@ -634,10 +896,6 @@ C3dMarkers::PlaceMarker(uint32 identifier, uint16 type, CVector &pos, float size } } pMarker->m_Matrix.SetTranslate(pos.x, pos.y, pos.z); - if (type == MARKERTYPE_2) { - pMarker->m_Matrix.RotateX(PI); - pMarker->m_Matrix.GetPosition() = pos; - } pMarker->m_Matrix.UpdateRW(); if (type == MARKERTYPE_ARROW) { if (dist < 25.0f) { @@ -648,7 +906,7 @@ C3dMarkers::PlaceMarker(uint32 identifier, uint16 type, CVector &pos, float size } else { pMarker->m_fStdSize = size; } - } else if (type == MARKERTYPE_CYLINDER) { + } else { if (dist < size + 12.0f) { if (dist > size + 1.0f) pMarker->m_Color.alpha = (1.0f - (size + 12.0f - dist) * 0.7f / 11.0f) * (float)a; @@ -752,6 +1010,9 @@ CBrightLights::Render(void) RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA); RwRenderStateSet(rwRENDERSTATETEXTURERASTER, nil); + TempBufferVerticesStored = 0; + TempBufferIndicesStored = 0; + for(i = 0; i < NumBrightLights; i++){ if(TempBufferIndicesStored > TEMPBUFFERINDEXSIZE-40 || TempBufferVerticesStored > TEMPBUFFERVERTSIZE-40) RenderOutGeometryBuffer(); @@ -788,6 +1049,10 @@ CBrightLights::Render(void) g = aBrightLights[i].m_green; b = aBrightLights[i].m_blue; break; +#ifdef FIX_BUGS //just to make sure that color never will be undefined + default: + return; +#endif } if(aBrightLights[i].m_camDist < BRIGHTLIGHTS_FADE_DIST) @@ -854,18 +1119,18 @@ CBrightLights::Render(void) case BRIGHTLIGHT_FRONT_BIG: case BRIGHTLIGHT_REAR_BIG: for (j = 0; j < 8; j++) { - pos = BigCarHeadLightsSide[j] * aBrightLights[i].m_side + - BigCarHeadLightsUp[j] * aBrightLights[i].m_up + - BigCarHeadLightsFront[j] * aBrightLights[i].m_front + - aBrightLights[i].m_pos; - RwIm3DVertexSetRGBA(&TempBufferRenderVertices[TempBufferVerticesStored + j], r, g, b, a); - RwIm3DVertexSetPos(&TempBufferRenderVertices[TempBufferVerticesStored + j], pos.x, pos.y, pos.z); - } - for (j = 0; j < 12 * 3; j++) - TempBufferRenderIndexList[TempBufferIndicesStored + j] = CubeIndices[j] + TempBufferVerticesStored; - TempBufferVerticesStored += 8; - TempBufferIndicesStored += 12 * 3; - break; + pos = BigCarHeadLightsSide[j] * aBrightLights[i].m_side + + BigCarHeadLightsUp[j] * aBrightLights[i].m_up + + BigCarHeadLightsFront[j] * aBrightLights[i].m_front + + aBrightLights[i].m_pos; + RwIm3DVertexSetRGBA(&TempBufferRenderVertices[TempBufferVerticesStored + j], r, g, b, a); + RwIm3DVertexSetPos(&TempBufferRenderVertices[TempBufferVerticesStored + j], pos.x, pos.y, pos.z); + } + for (j = 0; j < 12 * 3; j++) + TempBufferRenderIndexList[TempBufferIndicesStored + j] = CubeIndices[j] + TempBufferVerticesStored; + TempBufferVerticesStored += 8; + TempBufferIndicesStored += 12 * 3; + break; case BRIGHTLIGHT_FRONT_TALL: case BRIGHTLIGHT_REAR_TALL: @@ -1072,8 +1337,9 @@ CMoneyMessage::Render() { const float MAX_SCALE = 4.0f; uint32 nLifeTime = CTimer::GetTimeInMilliseconds() - m_nTimeRegistered; - if (nLifeTime >= MONEY_MESSAGE_LIFETIME_MS) m_nTimeRegistered = 0; - else { + if (nLifeTime >= MONEY_MESSAGE_LIFETIME_MS) { + m_nTimeRegistered = 0; + } else { float fLifeTime = (float)nLifeTime / MONEY_MESSAGE_LIFETIME_MS; RwV3d vecOut; float fDistX, fDistY; @@ -1082,17 +1348,15 @@ CMoneyMessage::Render() fDistY *= (0.7 * fLifeTime + 2.0) * m_fSize; CFont::SetPropOn(); CFont::SetBackgroundOff(); - float fScaleY = Min(fDistY / 100.0f, MAX_SCALE); float fScaleX = Min(fDistX / 100.0f, MAX_SCALE); - CFont::SetScale(fScaleX, fScaleY); // maybe use SCREEN_SCALE_X and SCREEN_SCALE_Y here? CFont::SetCentreOn(); CFont::SetCentreSize(SCREEN_WIDTH); CFont::SetJustifyOff(); CFont::SetColor(CRGBA(m_Colour.r, m_Colour.g, m_Colour.b, (255.0f - 255.0f * fLifeTime) * m_fOpacity)); CFont::SetBackGroundOnlyTextOff(); - CFont::SetFontStyle(FONT_STANDARD); + FONT_LOCALE(FONT_STANDARD); CFont::PrintString(vecOut.x, vecOut.y, m_aText); } } diff --git a/src/render/SpecialFX.h b/src/render/SpecialFX.h index 8bd0d5e1..f163d8ca 100644 --- a/src/render/SpecialFX.h +++ b/src/render/SpecialFX.h @@ -1,8 +1,12 @@ #pragma once +//file done + class CSpecialFX { public: + static bool bVideoCam; + static bool bLiftCam; static bool bSnapShotActive; static int32 SnapShotFrames; @@ -10,8 +14,11 @@ public: static void Update(void); static void Init(void); static void Shutdown(void); + static void AddWeaponStreak(int type); + static void Render2DFXs(); }; + class CRegisteredMotionBlurStreak { public: @@ -27,6 +34,7 @@ public: void Render(void); }; + class CMotionBlurStreaks { static CRegisteredMotionBlurStreak aStreaks[NUMMBLURSTREAKS]; @@ -37,33 +45,31 @@ public: static void Render(void); }; + struct CBulletTrace { - CVector m_vecCurrentPos; - CVector m_vecTargetPos; + CVector m_vecStartPos; + CVector m_vecEndPos; bool m_bInUse; - uint8 m_framesInUse; - uint8 m_lifeTime; + uint32 m_nCreationTime; + uint32 m_nLifeTime; + float m_fThickness; + uint8 m_fVisibility; void Update(void); }; + class CBulletTraces { public: static CBulletTrace aTraces[NUMBULLETTRACES]; static void Init(void); - static void AddTrace(CVector*, CVector*); static void Render(void); static void Update(void); - -//TODO(MIAMI) - static void AddTrace(CVector *, CVector *, float, unsigned int, unsigned char) {} - static void AddTrace(CVector *a, CVector *b, int32 weapontype, class CEntity *shooter) - { - AddTrace(a, b); //TODO: temp - } + static void AddTrace(CVector* start, CVector* end, float thickness, uint32 lifeTime, uint8 visibility); + static void AddTrace(CVector* start, CVector* end, int32 weaponType, class CEntity* shooter); }; enum @@ -104,6 +110,7 @@ public: void Render(); }; + class C3dMarkers { public: @@ -144,6 +151,7 @@ enum BRIGHTLIGHT_REAR = BRIGHTLIGHT_REAR_LONG, }; + class CBrightLight { public: @@ -158,6 +166,7 @@ public: uint8 m_blue; }; + class CBrightLights { static int NumBrightLights; @@ -177,6 +186,7 @@ enum SHINYTEXT_FLAT }; + class CShinyText { public: @@ -189,7 +199,8 @@ public: uint8 m_blue; }; -class CShinyTexts + +class CShinyTexts { static int NumShinyTexts; static CShinyText aShinyTexts[NUMSHINYTEXTS]; @@ -197,11 +208,12 @@ public: static void Init(void); static void RegisterOne(CVector p0, CVector p1, CVector p2, CVector p3, float u0, float v0, float u1, float v1, float u2, float v2, float u3, float v3, - uint8 type, uint8 red, uint8 green, uint8 blue, float maxDist); + uint8 type, uint8 red, uint8 green, uint8 blue, float maxDist); //not used static void Render(void); static void RenderOutGeometryBuffer(void); }; + class CMoneyMessage { friend class CMoneyMessages; @@ -216,6 +228,7 @@ public: void Render(); }; + class CMoneyMessages { static CMoneyMessage aMoneyMessages[NUMMONEYMESSAGES]; @@ -225,11 +238,12 @@ public: static void RegisterOne(CVector vecPos, const char *pText, uint8 bRed, uint8 bGreen, uint8 bBlue, float fSize, float fOpacity); }; + class CSpecialParticleStuff { static uint32 BoatFromStart; public: - static void CreateFoamAroundObject(CMatrix*, float, float, float, int32); - static void StartBoatFoamAnimation(); - static void UpdateBoatFoamAnimation(CMatrix*); + static void CreateFoamAroundObject(CMatrix*, float, float, float, int32); //not used + static void StartBoatFoamAnimation(); //not used + static void UpdateBoatFoamAnimation(CMatrix*); //not used }; diff --git a/src/save/GenericGameStorage.cpp b/src/save/GenericGameStorage.cpp index 18eecd95..966f353a 100644 --- a/src/save/GenericGameStorage.cpp +++ b/src/save/GenericGameStorage.cpp @@ -41,8 +41,10 @@ #include "Timecycle.h" #include "Fluff.h" -#define BLOCK_COUNT 20 -#define SIZE_OF_SIMPLEVARS 0xFC +// --MIAMI: file done + +#define BLOCK_COUNT 22 +#define SIZE_OF_SIMPLEVARS 0xE4 const uint32 SIZE_OF_ONE_GAME_IN_BYTES = 201729; @@ -60,7 +62,6 @@ int CheckSum; eLevelName m_LevelToLoad; char SaveFileNameJustSaved[260]; int Slots[SLOT_COUNT]; -CDate CompileDateAndTime; bool b_FoundRecentSavedGameWantToLoad; bool JustLoadedDontFadeInYet; @@ -112,13 +113,14 @@ do {\ buf += size;\ } while (0) -#define WriteSaveDataBlock(save_func)\ +#define WriteSaveDataBlock(save_func, msg)\ do {\ size = 0;\ buf = work_buff;\ reserved = 0;\ MakeSpaceForSizeInBufferPointer(presize, buf, postsize);\ save_func(buf, &size);\ + debug(msg"== %i \n", size);\ CopySizeAndPreparePointer(presize, buf, postsize, reserved, size);\ if (!PcSaveHelper.PcClassSaveRoutine(file, work_buff, buf - work_buff))\ return false;\ @@ -145,9 +147,10 @@ GenericSave(int file) reserved = 0; // Save simple vars - lastMissionPassed = TheText.Get(CStats::LastMissionPassedName); + lastMissionPassed = TheText.Get(CStats::LastMissionPassedName[0] ? CStats::LastMissionPassedName : "ITBEG"); if (lastMissionPassed[0] != '\0') { AsciiToUnicode("...'", suffix); + suffix[3] = L'\0'; #ifdef FIX_BUGS // fix buffer overflow int len = UnicodeStrlen(lastMissionPassed); @@ -194,12 +197,6 @@ GenericSave(int file) WriteDataToBufferPointer(buf, CWeather::NewWeatherType); WriteDataToBufferPointer(buf, CWeather::ForcedWeatherType); WriteDataToBufferPointer(buf, CWeather::InterpolationValue); - WriteDataToBufferPointer(buf, CompileDateAndTime.m_nSecond); - WriteDataToBufferPointer(buf, CompileDateAndTime.m_nMinute); - WriteDataToBufferPointer(buf, CompileDateAndTime.m_nHour); - WriteDataToBufferPointer(buf, CompileDateAndTime.m_nDay); - WriteDataToBufferPointer(buf, CompileDateAndTime.m_nMonth); - WriteDataToBufferPointer(buf, CompileDateAndTime.m_nYear); WriteDataToBufferPointer(buf, CWeather::WeatherTypeInList); #ifdef COMPATIBLE_SAVES // converted to float for compatibility with original format @@ -227,6 +224,7 @@ GenericSave(int file) buf += 4; postsize = buf; CTheScripts::SaveAllScripts(buf, &size); + debug("ScriptSize== %i \n", size); CopySizeAndPreparePointer(presize, buf, postsize, reserved, size); if (!PcSaveHelper.PcClassSaveRoutine(file, work_buff, buf - work_buff)) return false; @@ -234,28 +232,28 @@ GenericSave(int file) totalSize = buf - work_buff; // Save the rest - WriteSaveDataBlock(CPools::SavePedPool); - WriteSaveDataBlock(CGarages::Save); - WriteSaveDataBlock(CGameLogic::Save); - WriteSaveDataBlock(CPools::SaveVehiclePool); - WriteSaveDataBlock(CPools::SaveObjectPool); - WriteSaveDataBlock(ThePaths.Save); - WriteSaveDataBlock(CCranes::Save); - WriteSaveDataBlock(CPickups::Save); - WriteSaveDataBlock(gPhoneInfo.Save); - WriteSaveDataBlock(CRestart::SaveAllRestartPoints); - WriteSaveDataBlock(CRadar::SaveAllRadarBlips); - WriteSaveDataBlock(CTheZones::SaveAllZones); - WriteSaveDataBlock(CGangs::SaveAllGangData); - WriteSaveDataBlock(CTheCarGenerators::SaveAllCarGenerators); - WriteSaveDataBlock(CParticleObject::SaveParticle); - WriteSaveDataBlock(cAudioScriptObject::SaveAllAudioScriptObjects); - WriteSaveDataBlock(CScriptPaths::Save); - WriteSaveDataBlock(CWorld::Players[CWorld::PlayerInFocus].SavePlayerInfo); - WriteSaveDataBlock(CStats::SaveStats); - WriteSaveDataBlock(CSetPieces::Save); - WriteSaveDataBlock(CStreaming::MemoryCardSave); - WriteSaveDataBlock(CPedType::Save); + WriteSaveDataBlock(CPools::SavePedPool, "PedPoolSize"); + WriteSaveDataBlock(CGarages::Save, "GaragesSize"); + WriteSaveDataBlock(CGameLogic::Save, "GameLogicSize"); + WriteSaveDataBlock(CPools::SaveVehiclePool, "VehPoolSize"); + WriteSaveDataBlock(CPools::SaveObjectPool, "ObjectPoolSize"); + WriteSaveDataBlock(ThePaths.Save, "ThePathsSize"); + WriteSaveDataBlock(CCranes::Save, "CranesSize"); + WriteSaveDataBlock(CPickups::Save, "PickUpsSize"); + WriteSaveDataBlock(gPhoneInfo.Save, "PhoneInfoSize"); + WriteSaveDataBlock(CRestart::SaveAllRestartPoints, "RestartPointsBufferSize"); + WriteSaveDataBlock(CRadar::SaveAllRadarBlips, "RadarBlipsBufferSize"); + WriteSaveDataBlock(CTheZones::SaveAllZones, "AllZonesBufferSize"); + WriteSaveDataBlock(CGangs::SaveAllGangData, "AllGangDataSize"); + WriteSaveDataBlock(CTheCarGenerators::SaveAllCarGenerators, "AllCarGeneratorsSize"); + WriteSaveDataBlock(CParticleObject::SaveParticle, "ParticlesSize"); + WriteSaveDataBlock(cAudioScriptObject::SaveAllAudioScriptObjects, "AllAudioScriptObjectsSize"); + WriteSaveDataBlock(CScriptPaths::Save, "ScriptPathsSize"); + WriteSaveDataBlock(CWorld::Players[CWorld::PlayerInFocus].SavePlayerInfo, "PlayerInfoSize"); + WriteSaveDataBlock(CStats::SaveStats, "StatsSize"); + WriteSaveDataBlock(CSetPieces::Save, "SetPiecesSize"); + WriteSaveDataBlock(CStreaming::MemoryCardSave, "StreamingSize"); + WriteSaveDataBlock(CPedType::Save, "PedTypeSize"); // Write padding for (int i = 0; i < 4; i++) { @@ -331,12 +329,6 @@ GenericLoad() ReadDataFromBufferPointer(buf, CWeather::NewWeatherType); ReadDataFromBufferPointer(buf, CWeather::ForcedWeatherType); ReadDataFromBufferPointer(buf, CWeather::InterpolationValue); - ReadDataFromBufferPointer(buf, CompileDateAndTime.m_nSecond); - ReadDataFromBufferPointer(buf, CompileDateAndTime.m_nMinute); - ReadDataFromBufferPointer(buf, CompileDateAndTime.m_nHour); - ReadDataFromBufferPointer(buf, CompileDateAndTime.m_nDay); - ReadDataFromBufferPointer(buf, CompileDateAndTime.m_nMonth); - ReadDataFromBufferPointer(buf, CompileDateAndTime.m_nYear); ReadDataFromBufferPointer(buf, CWeather::WeatherTypeInList); #ifdef COMPATIBLE_SAVES // converted to float for compatibility with original format @@ -470,8 +462,13 @@ CloseFile(int32 file) void DoGameSpecificStuffAfterSucessLoad() { + CCollision::SortOutCollisionAfterLoad(); + CStreaming::LoadSceneCollision(TheCamera.GetPosition()); + CStreaming::LoadScene(TheCamera.GetPosition()); + CGame::TidyUpMemory(true, false); StillToFadeOut = true; JustLoadedDontFadeInYet = true; + TheCamera.Fade(0.0f, 0); CTheScripts::Process(); } diff --git a/src/save/GenericGameStorage.h b/src/save/GenericGameStorage.h index 236e34f5..07aa23ca 100644 --- a/src/save/GenericGameStorage.h +++ b/src/save/GenericGameStorage.h @@ -25,8 +25,6 @@ bool CheckDataNotCorrupt(int32 slot, char *name); bool RestoreForStartLoad(); int align4bytes(int32 size); -extern class CDate CompileDateAndTime; - extern char DefaultPCSaveFileName[260]; extern char ValidSaveName[260]; extern char LoadFileName[256]; diff --git a/src/vehicles/Automobile.cpp b/src/vehicles/Automobile.cpp index 395f3917..d1a7505e 100644 --- a/src/vehicles/Automobile.cpp +++ b/src/vehicles/Automobile.cpp @@ -59,7 +59,7 @@ bool CAutomobile::m_sAllTaxiLights; const uint32 CAutomobile::nSaveStructSize = #ifdef COMPATIBLE_SAVES - 1448; + 1500; #else sizeof(CAutomobile); #endif @@ -5713,7 +5713,7 @@ CAutomobile::Save(uint8*& buf) { CVehicle::Save(buf); WriteSaveBuf<CDamageManager>(buf, Damage); - SkipSaveBuf(buf, 800 - sizeof(CDamageManager)); + SkipSaveBuf(buf, 1500 - 672 - sizeof(CDamageManager)); } void @@ -5721,7 +5721,7 @@ CAutomobile::Load(uint8*& buf) { CVehicle::Load(buf); Damage = ReadSaveBuf<CDamageManager>(buf); - SkipSaveBuf(buf, 800 - sizeof(CDamageManager)); + SkipSaveBuf(buf, 1500 - 672 - sizeof(CDamageManager)); SetupDamageAfterLoad(); } #endif diff --git a/src/vehicles/Bike.cpp b/src/vehicles/Bike.cpp index b5bc9480..4a4b0516 100644 --- a/src/vehicles/Bike.cpp +++ b/src/vehicles/Bike.cpp @@ -39,6 +39,14 @@ //--MIAMI: file done +const uint32 CBike::nSaveStructSize = +#ifdef COMPATIBLE_SAVES + 1260; +#else + sizeof(CBoat); +#endif + + // TODO: maybe put this somewhere else inline void GetRelativeMatrix(RwMatrix *mat, RwFrame *frm, RwFrame *end) @@ -2922,3 +2930,19 @@ CBike::ReduceHornCounter(void) if(m_nCarHornTimer != 0) m_nCarHornTimer--; } + +#ifdef COMPATIBLE_SAVES +void +CBike::Save(uint8*& buf) +{ + CVehicle::Save(buf); + SkipSaveBuf(buf, 1260 - 672); +} + +void +CBike::Load(uint8*& buf) +{ + CVehicle::Load(buf); + SkipSaveBuf(buf, 1260 - 672); +} +#endif diff --git a/src/vehicles/Bike.h b/src/vehicles/Bike.h index 885fe1b0..3fcf66a2 100644 --- a/src/vehicles/Bike.h +++ b/src/vehicles/Bike.h @@ -132,6 +132,12 @@ public: void Fix(void); void SetupModelNodes(void); void ReduceHornCounter(void); + +#ifdef COMPATIBLE_SAVES + virtual void Save(uint8*& buf); + virtual void Load(uint8*& buf); +#endif + static const uint32 nSaveStructSize; }; // These functions and function names are made up diff --git a/src/vehicles/Boat.cpp b/src/vehicles/Boat.cpp index d727b1bc..8b5de929 100644 --- a/src/vehicles/Boat.cpp +++ b/src/vehicles/Boat.cpp @@ -43,7 +43,7 @@ CBoat *CBoat::apFrameWakeGeneratingBoats[4]; const uint32 CBoat::nSaveStructSize = #ifdef COMPATIBLE_SAVES - 1156; + 1216; #else sizeof(CBoat); #endif @@ -1449,13 +1449,13 @@ void CBoat::Save(uint8*& buf) { CVehicle::Save(buf); - SkipSaveBuf(buf, 1156 - 648); + SkipSaveBuf(buf, 1216 - 672); } void CBoat::Load(uint8*& buf) { CVehicle::Load(buf); - SkipSaveBuf(buf, 1156 - 648); + SkipSaveBuf(buf, 1216 - 672); } #endif diff --git a/src/vehicles/CarGen.cpp b/src/vehicles/CarGen.cpp index 598b8342..77d66cbf 100644 --- a/src/vehicles/CarGen.cpp +++ b/src/vehicles/CarGen.cpp @@ -91,7 +91,7 @@ void CCarGenerator::DoInternalProcessing() pVehicle = pBoat; if (pos.z <= -100.0f) pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y); - pBoat->bExtendedRange = false; + pBoat->bExtendedRange = true; }else{ bool groundFound; pos = m_vecPos; diff --git a/src/vehicles/Cranes.h b/src/vehicles/Cranes.h index 6d877d82..45ea7a8d 100644 --- a/src/vehicles/Cranes.h +++ b/src/vehicles/Cranes.h @@ -26,7 +26,6 @@ public: }; CBuilding *m_pCraneEntity; CObject *m_pHook; - int32 m_nAudioEntity; float m_fPickupX1; float m_fPickupX2; float m_fPickupY1; diff --git a/src/vehicles/Vehicle.cpp b/src/vehicles/Vehicle.cpp index 994f3c99..cba465b7 100644 --- a/src/vehicles/Vehicle.cpp +++ b/src/vehicles/Vehicle.cpp @@ -2367,15 +2367,15 @@ CVehicle::Save(uint8*& buf) WriteSaveBuf<float>(buf, GetPosition().z); SkipSaveBuf(buf, 16); SaveEntityFlags(buf); - SkipSaveBuf(buf, 212); + SkipSaveBuf(buf, 208); AutoPilot.Save(buf); WriteSaveBuf<int8>(buf, m_currentColour1); WriteSaveBuf<int8>(buf, m_currentColour2); SkipSaveBuf(buf, 2); WriteSaveBuf<int16>(buf, m_nAlarmState); - SkipSaveBuf(buf, 43); + SkipSaveBuf(buf, 42); WriteSaveBuf<uint8>(buf, m_nNumMaxPassengers); - SkipSaveBuf(buf, 2); + SkipSaveBuf(buf, 3); WriteSaveBuf<float>(buf, field_1D0[0]); WriteSaveBuf<float>(buf, field_1D0[1]); WriteSaveBuf<float>(buf, field_1D0[2]); @@ -2398,13 +2398,13 @@ CVehicle::Save(uint8*& buf) WriteSaveBuf<uint8>(buf, m_nCurrentGear); SkipSaveBuf(buf, 3); WriteSaveBuf<float>(buf, m_fChangeGearTime); - SkipSaveBuf(buf, 4); + SkipSaveBuf(buf, 12); WriteSaveBuf<uint32>(buf, m_nTimeOfDeath); SkipSaveBuf(buf, 2); WriteSaveBuf<int16>(buf, m_nBombTimer); SkipSaveBuf(buf, 12); WriteSaveBuf<int8>(buf, m_nDoorLock); - SkipSaveBuf(buf, 99); + SkipSaveBuf(buf, 111); } void @@ -2430,15 +2430,15 @@ CVehicle::Load(uint8*& buf) m_matrix = tmp; SkipSaveBuf(buf, 16); LoadEntityFlags(buf); - SkipSaveBuf(buf, 212); + SkipSaveBuf(buf, 208); AutoPilot.Load(buf); m_currentColour1 = ReadSaveBuf<int8>(buf); m_currentColour2 = ReadSaveBuf<int8>(buf); SkipSaveBuf(buf, 2); m_nAlarmState = ReadSaveBuf<int16>(buf); - SkipSaveBuf(buf, 43); + SkipSaveBuf(buf, 42); m_nNumMaxPassengers = ReadSaveBuf<int8>(buf); - SkipSaveBuf(buf, 2); + SkipSaveBuf(buf, 3); field_1D0[0] = ReadSaveBuf<float>(buf); field_1D0[1] = ReadSaveBuf<float>(buf); field_1D0[2] = ReadSaveBuf<float>(buf); @@ -2460,13 +2460,13 @@ CVehicle::Load(uint8*& buf) m_nCurrentGear = ReadSaveBuf<uint8>(buf); SkipSaveBuf(buf, 3); m_fChangeGearTime = ReadSaveBuf<float>(buf); - SkipSaveBuf(buf, 4); + SkipSaveBuf(buf, 12); m_nTimeOfDeath = ReadSaveBuf<uint32>(buf); SkipSaveBuf(buf, 2); m_nBombTimer = ReadSaveBuf<int16>(buf); SkipSaveBuf(buf, 12); m_nDoorLock = (eCarLock)ReadSaveBuf<int8>(buf); - SkipSaveBuf(buf, 99); + SkipSaveBuf(buf, 111); } #endif |