summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/control/Replay.cpp12
-rw-r--r--src/control/Script.cpp22
-rw-r--r--src/core/Pools.cpp61
-rw-r--r--src/core/Radar.cpp4
-rw-r--r--src/core/Radar.h2
-rw-r--r--src/core/Timer.cpp3
-rw-r--r--src/core/main.cpp2
-rw-r--r--src/peds/Ped.cpp30
-rw-r--r--src/peds/PedAttractor.cpp6
-rw-r--r--src/peds/PlayerPed.cpp6
-rw-r--r--src/render/Glass.cpp478
-rw-r--r--src/render/Glass.h12
-rw-r--r--src/render/Hud.cpp2
-rw-r--r--src/render/SpecialFX.cpp524
-rw-r--r--src/render/SpecialFX.h48
-rw-r--r--src/save/GenericGameStorage.cpp75
-rw-r--r--src/save/GenericGameStorage.h2
-rw-r--r--src/vehicles/Automobile.cpp6
-rw-r--r--src/vehicles/Bike.cpp24
-rw-r--r--src/vehicles/Bike.h6
-rw-r--r--src/vehicles/Boat.cpp6
-rw-r--r--src/vehicles/CarGen.cpp2
-rw-r--r--src/vehicles/Cranes.h1
-rw-r--r--src/vehicles/Vehicle.cpp20
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