1
0
Fork 0
mirror of https://github.com/halpz/re3.git synced 2024-12-26 18:15:27 +00:00

Merge remote-tracking branch 'upstream/miami' into miami

This commit is contained in:
Nikolay Korolev 2020-10-18 20:35:19 +03:00
commit bc42b3a78e
13 changed files with 1272 additions and 708 deletions

File diff suppressed because it is too large Load diff

View file

@ -34,21 +34,23 @@ class CPickup
{ {
public: public:
CVector m_vecPos; CVector m_vecPos;
uint32 m_nRevenue; float m_fRevenue;
CObject *m_pObject; CObject *m_pObject;
CObject *m_pExtraObject; CObject *m_pExtraObject;
uint16 m_nQuantity; uint32 m_nQuantity;
uint32 m_nTimer; uint32 m_nTimer;
int16 m_nMoneySpeed; uint16 m_nMoneySpeed;
int16 m_eModelIndex; int16 m_eModelIndex;
uint16 m_nIndex; uint16 m_nIndex;
char m_sTextKey[8]; char m_sTextKey[8];
ePickupType m_eType; ePickupType m_eType;
bool m_bRemoved; bool m_bRemoved;
uint8 m_effects; uint8 m_effects:1;
uint8 m_effects2:1;
CObject *GiveUsAPickUpObject(int32 handle); CObject *GiveUsAPickUpObject(CObject **object, CObject **extraObject, int32 handle, int32 extraHandle);
bool Update(CPlayerPed *player, CVehicle *vehicle, int playerId); bool Update(CPlayerPed *player, CVehicle *vehicle, int playerId);
void GetRidOfObjects();
private: private:
bool IsMine() { return m_eType >= PICKUP_MINE_INACTIVE && m_eType <= PICKUP_FLOATINGPACKAGE_FLOATING; } bool IsMine() { return m_eType >= PICKUP_MINE_INACTIVE && m_eType <= PICKUP_FLOATINGPACKAGE_FLOATING; }
inline bool CanBePickedUp(CPlayerPed *player, int playerId); inline bool CanBePickedUp(CPlayerPed *player, int playerId);
@ -64,8 +66,9 @@ struct tPickupMessage
eWeaponType m_weaponType; eWeaponType m_weaponType;
CVector2D m_dist; CVector2D m_dist;
CRGBA m_color; CRGBA m_color;
uint8 m_bOutOfStock : 1; uint8 m_bOutOfStock;
uint8 m_quantity; uint8 m_quantity;
uint16 money;
}; };
class CPickups class CPickups
@ -111,13 +114,13 @@ public:
static CVector StaticCamCoors; static CVector StaticCamCoors;
static uint32 StaticCamStartTime; static uint32 StaticCamStartTime;
//TODO(MIAMI) static void RemoveAllPickupsOfACertainWeaponGroupWithNoAmmo(eWeaponType);
static void RemoveAllPickupsOfACertainWeaponGroupWithNoAmmo(eWeaponType) {} static CPickup *FindPickUpForThisObject(CEntity*);
}; };
extern uint16 AmmoForWeapon[20]; extern uint16 AmmoForWeapon[WEAPONTYPE_TOTALWEAPONS + 1];
extern uint16 AmmoForWeapon_OnStreet[WEAPONTYPE_TOTALWEAPONS]; extern uint16 AmmoForWeapon_OnStreet[WEAPONTYPE_TOTALWEAPONS + 1];
extern uint16 CostOfWeapon[20]; extern uint16 CostOfWeapon[WEAPONTYPE_TOTALWEAPONS + 3];
enum ePacmanPickupType enum ePacmanPickupType
{ {

View file

@ -387,10 +387,8 @@ void CReplay::RecordThisFrame(void)
tBulletTracePacket* bt = (tBulletTracePacket*)&Record.m_pBase[Record.m_nOffset]; tBulletTracePacket* bt = (tBulletTracePacket*)&Record.m_pBase[Record.m_nOffset];
bt->type = REPLAYPACKET_BULLET_TRACES; bt->type = REPLAYPACKET_BULLET_TRACES;
bt->index = i; bt->index = i;
bt->frames = CBulletTraces::aTraces[i].m_framesInUse; bt->inf = CBulletTraces::aTraces[i].m_vecStartPos;
bt->lifetime = CBulletTraces::aTraces[i].m_lifeTime; bt->sup = CBulletTraces::aTraces[i].m_vecEndPos;
bt->inf = CBulletTraces::aTraces[i].m_vecCurrentPos;
bt->sup = CBulletTraces::aTraces[i].m_vecTargetPos;
Record.m_nOffset += sizeof(*bt); Record.m_nOffset += sizeof(*bt);
} }
tMiscPacket* misc = (tMiscPacket*)&Record.m_pBase[Record.m_nOffset]; tMiscPacket* misc = (tMiscPacket*)&Record.m_pBase[Record.m_nOffset];
@ -1117,10 +1115,8 @@ bool CReplay::PlayBackThisFrameInterpolation(CAddressInReplayBuffer *buffer, flo
{ {
tBulletTracePacket* pb = (tBulletTracePacket*)&ptr[offset]; tBulletTracePacket* pb = (tBulletTracePacket*)&ptr[offset];
CBulletTraces::aTraces[pb->index].m_bInUse = true; CBulletTraces::aTraces[pb->index].m_bInUse = true;
CBulletTraces::aTraces[pb->index].m_framesInUse = pb->frames; CBulletTraces::aTraces[pb->index].m_vecStartPos = pb->inf;
CBulletTraces::aTraces[pb->index].m_lifeTime = pb->lifetime; CBulletTraces::aTraces[pb->index].m_vecEndPos = pb->sup;
CBulletTraces::aTraces[pb->index].m_vecCurrentPos = pb->inf;
CBulletTraces::aTraces[pb->index].m_vecTargetPos = pb->sup;
buffer->m_nOffset += sizeof(tBulletTracePacket); buffer->m_nOffset += sizeof(tBulletTracePacket);
break; break;
} }

View file

@ -31,6 +31,7 @@
#include "GameLogic.h" #include "GameLogic.h"
#include "Garages.h" #include "Garages.h"
#include "General.h" #include "General.h"
#include "Glass.h"
#ifdef MISSION_REPLAY #ifdef MISSION_REPLAY
#include "GenericGameStorage.h" #include "GenericGameStorage.h"
#endif #endif
@ -1804,9 +1805,8 @@ void CMissionCleanup::Process()
if (!CWorld::Players[CWorld::PlayerInFocus].m_pRemoteVehicle) if (!CWorld::Players[CWorld::PlayerInFocus].m_pRemoteVehicle)
TheCamera.Restore(); TheCamera.Restore();
TheCamera.SetWideScreenOff(); TheCamera.SetWideScreenOff();
// TODO(MIAMI) CSpecialFX::bLiftCam = false;
//CSpecialFX::bLiftCam = false; CSpecialFX::bVideoCam = false;
//CSpecialFX::bVideoCam = false;
CTimeCycle::StopExtraColour(0); CTimeCycle::StopExtraColour(0);
for (int i = 0; i < MISSION_AUDIO_SLOTS; i++) for (int i = 0; i < MISSION_AUDIO_SLOTS; i++)
DMAudio.ClearMissionAudio(i); DMAudio.ClearMissionAudio(i);
@ -12404,7 +12404,7 @@ int8 CRunningScript::ProcessCommands1200To1299(int32 command)
case COMMAND_SWITCH_SECURITY_CAMERA: case COMMAND_SWITCH_SECURITY_CAMERA:
{ {
CollectParameters(&m_nIp, 1); CollectParameters(&m_nIp, 1);
debug("SWITCH_SECURITY_CAMERA is not implemented\n"); // TODO(MIAMI) CSpecialFX::bVideoCam = ScriptParams[0] != 0;
return 0; return 0;
} }
//case COMMAND_IS_CHAR_IN_FLYING_VEHICLE: //case COMMAND_IS_CHAR_IN_FLYING_VEHICLE:
@ -12844,7 +12844,7 @@ int8 CRunningScript::ProcessCommands1200To1299(int32 command)
case COMMAND_SWITCH_LIFT_CAMERA: case COMMAND_SWITCH_LIFT_CAMERA:
{ {
CollectParameters(&m_nIp, 1); CollectParameters(&m_nIp, 1);
debug("SWITCH_LIFT_CAMERA is not implemented\n"); // TODO(MIAMI) CSpecialFX::bLiftCam = ScriptParams[0] != 0;
return 0; return 0;
} }
case COMMAND_CLOSE_ALL_CAR_DOORS: case COMMAND_CLOSE_ALL_CAR_DOORS:
@ -13013,12 +13013,12 @@ int8 CRunningScript::ProcessCommands1300To1399(int32 command)
case COMMAND_HAS_GLASS_BEEN_SHATTERED_NEARBY: case COMMAND_HAS_GLASS_BEEN_SHATTERED_NEARBY:
{ {
CollectParameters(&m_nIp, 3); CollectParameters(&m_nIp, 3);
static bool bShowed = false;
if (!bShowed) { bool shattered = false;
debug("HAS_GLASS_BEEN_SHATTERED_NEARBY not implemented, default to TRUE\n"); // TODO(MIAMI) if ( CGlass::HasGlassBeenShatteredAtCoors(*(float*)&ScriptParams[0], *(float*)&ScriptParams[1], *(float*)&ScriptParams[2]) )
bShowed = true; shattered = true;
}
UpdateCompareFlag(true); UpdateCompareFlag(shattered);
return 0; return 0;
} }
case COMMAND_ATTACH_CUTSCENE_OBJECT_TO_BONE: case COMMAND_ATTACH_CUTSCENE_OBJECT_TO_BONE:

View file

@ -5,6 +5,7 @@
#include "DMAudio.h" #include "DMAudio.h"
#include "Record.h" #include "Record.h"
#include "Timer.h" #include "Timer.h"
#include "SpecialFX.h"
uint32 CTimer::m_snTimeInMilliseconds; uint32 CTimer::m_snTimeInMilliseconds;
PauseModeTime CTimer::m_snTimeInMillisecondsPauseMode = 1; 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_fTimeStep = 0.01f;
ms_fTimeStepNonClipped = ms_fTimeStep; ms_fTimeStepNonClipped = ms_fTimeStep;

View file

@ -969,7 +969,7 @@ Render2dStuff(void)
else else
CHud::Draw(); CHud::Draw();
// TODO(Miami) // TODO(Miami)
// CSpecialFX::Render2DFXs(); CSpecialFX::Render2DFXs();
CUserDisplay::OnscnTimer.ProcessForDisplay(); CUserDisplay::OnscnTimer.ProcessForDisplay();
CMessages::Display(); CMessages::Display();
CDarkel::DrawMessages(); CDarkel::DrawMessages();

View file

@ -40,10 +40,10 @@ CWeaponModelInfo::SetWeaponInfo(int32 weaponId)
m_atomics[2] = (RpAtomic*)weaponId; m_atomics[2] = (RpAtomic*)weaponId;
} }
int32 eWeaponType
CWeaponModelInfo::GetWeaponInfo(void) CWeaponModelInfo::GetWeaponInfo(void)
{ {
return (int32)(uintptr)m_atomics[2]; return (eWeaponType)(uintptr)m_atomics[2];
} }
void void

View file

@ -1,6 +1,7 @@
#pragma once #pragma once
#include "SimpleModelInfo.h" #include "SimpleModelInfo.h"
#include "WeaponType.h"
class CWeaponModelInfo : public CSimpleModelInfo class CWeaponModelInfo : public CSimpleModelInfo
{ {
@ -18,5 +19,5 @@ public:
void Init(void); void Init(void);
void SetWeaponInfo(int32 weaponId); void SetWeaponInfo(int32 weaponId);
int32 GetWeaponInfo(void); eWeaponType GetWeaponInfo(void);
}; };

View file

@ -14,6 +14,7 @@
#include "AnimBlendClumpData.h" #include "AnimBlendClumpData.h"
#include "AnimBlendAssociation.h" #include "AnimBlendAssociation.h"
#include "Fire.h" #include "Fire.h"
#include "Glass.h"
#include "DMAudio.h" #include "DMAudio.h"
#include "General.h" #include "General.h"
#include "SurfaceTable.h" #include "SurfaceTable.h"
@ -5865,7 +5866,7 @@ CPed::FightStrike(CVector &touchedNodePos, bool fightWithWeapon)
if (m_fightState == FIGHTSTATE_JUST_ATTACKED) if (m_fightState == FIGHTSTATE_JUST_ATTACKED)
return false; return false;
// TODO(Miami): BreakGlassPhysically CGlass::BreakGlassPhysically(touchedNodePos, radius);
for (int i = 0; i < m_numNearPeds; i++) { for (int i = 0; i < m_numNearPeds; i++) {
int8 pedFound = 0; int8 pedFound = 0;
@ -15403,7 +15404,7 @@ CPed::ProcessObjective(void)
CVector distance = m_nextRoutePointPos - GetPosition(); CVector distance = m_nextRoutePointPos - GetPosition();
distance.z = 0.0f; distance.z = 0.0f;
if (m_objective == OBJECTIVE_GOTO_SHELTER_ON_FOOT) { 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); SetMoveState(PEDMOVE_WALK);
bIsRunning = false; bIsRunning = false;
} }
@ -15413,7 +15414,7 @@ CPed::ProcessObjective(void)
} }
} }
else if (m_objective == OBJECTIVE_GOTO_ICE_CREAM_VAN_ON_FOOT) { 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); SetMoveState(PEDMOVE_WALK);
bIsRunning = false; bIsRunning = false;
} }

View file

@ -3,6 +3,8 @@
#include "Glass.h" #include "Glass.h"
#include "Timer.h" #include "Timer.h"
#include "Object.h" #include "Object.h"
#include "Vehicle.h"
#include "Pools.h"
#include "General.h" #include "General.h"
#include "AudioScriptObject.h" #include "AudioScriptObject.h"
#include "World.h" #include "World.h"
@ -14,6 +16,7 @@
#include "ModelIndices.h" #include "ModelIndices.h"
#include "main.h" #include "main.h"
#include "soundlist.h" #include "soundlist.h"
#include "SurfaceTable.h"
uint32 CGlass::NumGlassEntities; uint32 CGlass::NumGlassEntities;
@ -57,17 +60,17 @@ const CVector2D CoorsWithTriangle[NUM_GLASSTRIANGLES][3] =
#define TEMPBUFFERVERTHILIGHTOFFSET 0 #define TEMPBUFFERVERTHILIGHTOFFSET 0
#define TEMPBUFFERINDEXHILIGHTOFFSET 0 #define TEMPBUFFERINDEXHILIGHTOFFSET 0
#define TEMPBUFFERVERTHILIGHTSIZE 128 #define TEMPBUFFERVERTHILIGHTSIZE 256
#define TEMPBUFFERINDEXHILIGHTSIZE 512 #define TEMPBUFFERINDEXHILIGHTSIZE 512
#define TEMPBUFFERVERTSHATTEREDOFFSET TEMPBUFFERVERTHILIGHTSIZE #define TEMPBUFFERVERTSHATTEREDOFFSET TEMPBUFFERVERTHILIGHTSIZE
#define TEMPBUFFERINDEXSHATTEREDOFFSET TEMPBUFFERINDEXHILIGHTSIZE #define TEMPBUFFERINDEXSHATTEREDOFFSET TEMPBUFFERINDEXHILIGHTSIZE
#define TEMPBUFFERVERTSHATTEREDSIZE 192 #define TEMPBUFFERVERTSHATTEREDSIZE 384
#define TEMPBUFFERINDEXSHATTEREDSIZE 768 #define TEMPBUFFERINDEXSHATTEREDSIZE 768
#define TEMPBUFFERVERTREFLECTIONOFFSET TEMPBUFFERVERTSHATTEREDSIZE #define TEMPBUFFERVERTREFLECTIONOFFSET TEMPBUFFERVERTSHATTEREDSIZE
#define TEMPBUFFERINDEXREFLECTIONOFFSET TEMPBUFFERINDEXSHATTEREDSIZE #define TEMPBUFFERINDEXREFLECTIONOFFSET TEMPBUFFERINDEXSHATTEREDSIZE
#define TEMPBUFFERVERTREFLECTIONSIZE 256 #define TEMPBUFFERVERTREFLECTIONSIZE 512
#define TEMPBUFFERINDEXREFLECTIONSIZE 1024 #define TEMPBUFFERINDEXREFLECTIONSIZE 1024
int32 TempBufferIndicesStoredHiLight = 0; int32 TempBufferIndicesStoredHiLight = 0;
@ -83,10 +86,16 @@ CFallingGlassPane::Update(void)
if ( CTimer::GetTimeInMilliseconds() >= m_nTimer ) if ( CTimer::GetTimeInMilliseconds() >= m_nTimer )
{ {
// Apply MoveSpeed // 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 // 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 // Apply TurnSpeed
GetRight() += CrossProduct(m_vecTurn, GetRight()); GetRight() += CrossProduct(m_vecTurn, GetRight());
@ -106,24 +115,27 @@ CFallingGlassPane::Update(void)
RwRGBA color = { 255, 255, 255, 255 }; RwRGBA color = { 255, 255, 255, 255 };
static int32 nFrameGen = 0; if ( !m_bCarGlass )
for ( int32 i = 0; i < 4; i++ )
{ {
dir.x = CGeneral::GetRandomNumberInRange(-0.35f, 0.35f); static int32 nFrameGen = 0;
dir.y = CGeneral::GetRandomNumberInRange(-0.35f, 0.35f);
dir.z = CGeneral::GetRandomNumberInRange(0.05f, 0.20f);
CParticle::AddParticle(PARTICLE_CAR_DEBRIS, for ( int32 i = 0; i < 4; i++ )
pos, {
dir, dir.x = CGeneral::GetRandomNumberInRange(-0.35f, 0.35f);
nil, dir.y = CGeneral::GetRandomNumberInRange(-0.35f, 0.35f);
CGeneral::GetRandomNumberInRange(0.02f, 0.2f), dir.z = CGeneral::GetRandomNumberInRange(0.05f, 0.20f);
color,
CGeneral::GetRandomNumberInRange(-40, 40), CParticle::AddParticle(PARTICLE_CAR_DEBRIS,
0, pos,
++nFrameGen & 3, dir,
500); nil,
CGeneral::GetRandomNumberInRange(0.02f, 0.2f),
color,
CGeneral::GetRandomNumberInRange(-40, 40),
0,
++nFrameGen & 3,
500);
}
} }
} }
} }
@ -147,6 +159,9 @@ CFallingGlassPane::Render(void)
// HiLight Polys // HiLight Polys
if ( m_bCarGlass && color < 64 )
color = 64;
RwIm3DVertexSetRGBA (&TempBufferRenderVertices[TempBufferVerticesStoredHiLight + 0], color, color, color, color); RwIm3DVertexSetRGBA (&TempBufferRenderVertices[TempBufferVerticesStoredHiLight + 0], color, color, color, color);
RwIm3DVertexSetRGBA (&TempBufferRenderVertices[TempBufferVerticesStoredHiLight + 1], color, color, color, color); RwIm3DVertexSetRGBA (&TempBufferRenderVertices[TempBufferVerticesStoredHiLight + 1], color, color, color, color);
RwIm3DVertexSetRGBA (&TempBufferRenderVertices[TempBufferVerticesStoredHiLight + 2], 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 ) if ( TempBufferIndicesStoredShattered >= TEMPBUFFERINDEXSHATTEREDSIZE-7 || TempBufferVerticesStoredShattered >= TEMPBUFFERVERTSHATTEREDSIZE-4 )
CGlass::RenderShatteredPolys(); CGlass::RenderShatteredPolys();
uint8 shatteredColor = 255; uint8 shatteredColor = 140;
if ( distToCamera > 30.0f ) 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 + 0], shatteredColor, shatteredColor, shatteredColor, shatteredColor);
RwIm3DVertexSetRGBA (&TempBufferRenderVertices[TempBufferVerticesStoredShattered + 1], shatteredColor, shatteredColor, shatteredColor, shatteredColor); RwIm3DVertexSetRGBA (&TempBufferRenderVertices[TempBufferVerticesStoredShattered + 1], shatteredColor, shatteredColor, shatteredColor, shatteredColor);
@ -292,8 +307,8 @@ CGlass::FindFreePane(void)
} }
void void
CGlass::GeneratePanesForWindow(uint32 type, CVector pos, CVector up, CVector right, CVector speed, CVector point, CGlass::GeneratePanesForWindow(uint32 type, CVector pos, CVector up, CVector right, CVector speed, CVector center,
float moveSpeed, bool cracked, bool explosion) float moveSpeed, bool cracked, bool explosion, int32 stepmul, bool carGlass)
{ {
float upLen = up.Magnitude(); float upLen = up.Magnitude();
float rightLen = right.Magnitude(); float rightLen = right.Magnitude();
@ -304,10 +319,10 @@ CGlass::GeneratePanesForWindow(uint32 type, CVector pos, CVector up, CVector rig
float rightSteps = rightLen + 0.75f; float rightSteps = rightLen + 0.75f;
if ( rightSteps < 1.0f ) rightSteps = 1.0f; if ( rightSteps < 1.0f ) rightSteps = 1.0f;
uint32 ysteps = (uint32)upSteps; uint32 ysteps = stepmul * (uint32)upSteps;
if ( ysteps > 3 ) ysteps = 3; if ( ysteps > 3 ) ysteps = 3;
uint32 xsteps = (uint32)rightSteps; uint32 xsteps = stepmul * (uint32)rightSteps;
if ( xsteps > 3 ) xsteps = 3; if ( xsteps > 3 ) xsteps = 3;
if ( explosion ) if ( explosion )
@ -338,11 +353,8 @@ CGlass::GeneratePanesForWindow(uint32 type, CVector pos, CVector up, CVector rig
pane->m_nTriIndex = i; pane->m_nTriIndex = i;
pane->GetRight() = (right * rightScl) / rightLen; pane->GetRight() = (right * rightScl) / rightLen;
#ifdef FIX_BUGS
pane->GetUp() = (up * upScl) / upLen; pane->GetUp() = (up * upScl) / upLen;
#else
pane->GetUp() = (up * upScl) / rightLen; // copypaste bug
#endif
CVector fwd = CrossProduct(pane->GetRight(), pane->GetUp()); CVector fwd = CrossProduct(pane->GetRight(), pane->GetUp());
fwd.Normalise(); fwd.Normalise();
@ -358,7 +370,7 @@ CGlass::GeneratePanesForWindow(uint32 type, CVector pos, CVector up, CVector rig
if ( moveSpeed != 0.0f ) if ( moveSpeed != 0.0f )
{ {
CVector dist = pane->GetPosition() - point; CVector dist = pane->GetPosition() - center;
dist.Normalise(); dist.Normalise();
pane->m_vecMoveSpeed += moveSpeed * dist; pane->m_vecMoveSpeed += moveSpeed * dist;
@ -371,10 +383,11 @@ CGlass::GeneratePanesForWindow(uint32 type, CVector pos, CVector up, CVector rig
switch ( type ) switch ( type )
{ {
case 0: case 0:
case 2:
pane->m_nTimer = CTimer::GetTimeInMilliseconds(); pane->m_nTimer = CTimer::GetTimeInMilliseconds();
break; break;
case 1: case 1:
float dist = (pane->GetPosition() - point).Magnitude(); float dist = (pane->GetPosition() - center).Magnitude();
pane->m_nTimer = uint32(dist*100 + CTimer::GetTimeInMilliseconds()); pane->m_nTimer = uint32(dist*100 + CTimer::GetTimeInMilliseconds());
break; break;
} }
@ -382,6 +395,7 @@ CGlass::GeneratePanesForWindow(uint32 type, CVector pos, CVector up, CVector rig
pane->m_fGroundZ = groundZ; pane->m_fGroundZ = groundZ;
pane->m_bShattered = cracked; pane->m_bShattered = cracked;
pane->m_fStep = upLen / float(ysteps); pane->m_fStep = upLen / float(ysteps);
pane->m_bCarGlass = carGlass;
pane->m_bActive = true; pane->m_bActive = true;
} }
} }
@ -613,42 +627,48 @@ CGlass::WindowRespondsToCollision(CEntity *entity, float amount, CVector speed,
CColModel *col = object->GetColModel(); CColModel *col = object->GetColModel();
ASSERT(col!=nil); ASSERT(col!=nil);
CVector a = object->GetMatrix() * col->vertices[0].Get(); if ( col->numTriangles == 2 )
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()); CVector a = col->vertices[0].Get();
CVector b = col->vertices[1].Get();
CVector c = col->vertices[2].Get();
CVector d = col->vertices[3].Get();
GeneratePanesForWindow(0, float minx = Min(Min(a.x, b.x), Min(c.x, d.x));
CVector(minx, miny, minz), float maxx = Max(Max(a.x, b.x), Max(c.x, d.x));
CVector(0.0f, 0.0f, maxz-minz), float miny = Min(Min(a.y, b.y), Min(c.y, d.y));
CVector(maxx-minx, maxy-miny, 0.0f), float maxy = Max(Max(a.y, b.y), Max(c.y, d.y));
speed, point, 0.1f, !!object->bGlassCracked, explosion); 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));
else
{
PlayOneShotScriptObject(SCRIPT_SOUND_GLASS_BREAK_S, object->GetPosition());
GeneratePanesForWindow(1, CVector pa = object->GetMatrix() * CVector(minx, miny, minz);
CVector(minx, miny, minz), CVector pb = object->GetMatrix() * CVector(maxx, maxy, minz);
CVector(0.0f, 0.0f, maxz-minz),
CVector(maxx-minx, maxy-miny, 0.0f), if ( amount > 300.0f )
speed, point, 0.1f, !!object->bGlassCracked, explosion); {
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->bGlassBroken = true;
object->GetMatrix().GetPosition().z = -100.0f; object->bIsVisible = false;
object->bUsesCollision = true;
} }
void void
@ -658,7 +678,7 @@ CGlass::WindowRespondsToSoftCollision(CEntity *entity, float amount)
CObject *object = (CObject *)entity; 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()); PlayOneShotScriptObject(SCRIPT_SOUND_GLASS_CRACK, object->GetPosition());
object->bGlassCracked = true; object->bGlassCracked = true;
@ -674,15 +694,18 @@ CGlass::WasGlassHitByBullet(CEntity *entity, CVector point)
if ( IsGlass(object->GetModelIndex()) ) if ( IsGlass(object->GetModelIndex()) )
{ {
if ( !object->bGlassCracked ) if ( object->bUsesCollision )
{ {
PlayOneShotScriptObject(SCRIPT_SOUND_GLASS_CRACK, object->GetPosition()); if ( !object->bGlassCracked )
object->bGlassCracked = true; {
} PlayOneShotScriptObject(SCRIPT_SOUND_GLASS_CRACK, object->GetPosition());
else object->bGlassCracked = true;
{ }
if ( (CGeneral::GetRandomNumber() & 3) == 2 ) else
WindowRespondsToCollision(object, 0.0f, CVector(0.0f, 0.0f, 0.0f), point, false); {
if ( (CGeneral::GetRandomNumber() & 3) == 2 )
WindowRespondsToCollision(object, 0.0f, CVector(0.0f, 0.0f, 0.0f), point, false);
}
} }
} }
} }
@ -694,18 +717,303 @@ CGlass::WindowRespondsToExplosion(CEntity *entity, CVector point)
CObject *object = (CObject *)entity; CObject *object = (CObject *)entity;
CVector distToGlass = object->GetPosition() - point; if ( object->bUsesCollision )
float fDistToGlass = distToGlass.Magnitude();
if ( fDistToGlass < 10.0f )
{ {
distToGlass *= (0.3f / fDistToGlass); // normalise CVector distToGlass = object->GetPosition() - point;
WindowRespondsToCollision(object, 10000.0f, distToGlass, object->GetPosition(), true);
} float fDistToGlass = distToGlass.Magnitude();
else
{ if ( fDistToGlass < 10.0f )
if ( fDistToGlass < 30.0f ) {
object->bGlassCracked = true; distToGlass *= (0.3f / fDistToGlass); // normalise
WindowRespondsToCollision(object, 10000.0f, distToGlass, object->GetPosition(), true);
}
else
{
if ( fDistToGlass < 30.0f )
object->bGlassCracked = true;
}
}
}
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);
}
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++ )
{
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);
}
}
if ( entity )
{
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;
}
}
}
}
}
} }
} }

View file

@ -2,6 +2,7 @@
class CEntity; class CEntity;
class CVehicle; class CVehicle;
class CPtrList;
class CFallingGlassPane : public CMatrix class CFallingGlassPane : public CMatrix
{ {
@ -14,6 +15,7 @@ public:
uint8 m_nTriIndex; uint8 m_nTriIndex;
bool m_bActive; bool m_bActive;
bool m_bShattered; bool m_bShattered;
bool m_bCarGlass;
CFallingGlassPane() { } CFallingGlassPane() { }
~CFallingGlassPane() { } ~CFallingGlassPane() { }
@ -39,7 +41,7 @@ public:
static void Update(void); static void Update(void);
static void Render(void); static void Render(void);
static CFallingGlassPane *FindFreePane(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 AskForObjectToBeRenderedInGlass(CEntity *entity);
static void RenderEntityInGlass(CEntity *entity); static void RenderEntityInGlass(CEntity *entity);
static int32 CalcAlphaWithNormal(CVector *normal); static int32 CalcAlphaWithNormal(CVector *normal);
@ -50,8 +52,8 @@ public:
static void WindowRespondsToSoftCollision(CEntity *entity, float amount); static void WindowRespondsToSoftCollision(CEntity *entity, float amount);
static void WasGlassHitByBullet(CEntity *entity, CVector point); static void WasGlassHitByBullet(CEntity *entity, CVector point);
static void WindowRespondsToExplosion(CEntity *entity, CVector point); static void WindowRespondsToExplosion(CEntity *entity, CVector point);
static void CarWindscreenShatters(CVehicle *vehicle, bool unk);
//TODO(MIAMI) static bool HasGlassBeenShatteredAtCoors(float x, float y, float z);
static void CarWindscreenShatters(CVehicle *vehicle, bool unk) {} static void FindWindowSectorList(CPtrList &list, float *dist, CEntity **entity, float x, float y, float z);
static void BreakGlassPhysically(CVector, float) {} static void BreakGlassPhysically(CVector pos, float radius);
}; };

View file

@ -24,21 +24,44 @@
#include "ColStore.h" #include "ColStore.h"
#include "Coronas.h" #include "Coronas.h"
#include "Script.h" #include "Script.h"
#include "DMAudio.h"
RwIm3DVertex StreakVertices[4]; RwIm3DVertex StreakVertices[4];
RwImVertexIndex StreakIndexList[12]; RwImVertexIndex StreakIndexList[12];
RwIm3DVertex TraceVertices[6]; RwIm3DVertex TraceVertices[10];
RwImVertexIndex TraceIndexList[12]; 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; bool CSpecialFX::bSnapShotActive;
int32 CSpecialFX::SnapShotFrames; int32 CSpecialFX::SnapShotFrames;
static RwTexture* gpSmokeTrailTexture;
void void
CSpecialFX::Init(void) CSpecialFX::Init(void)
{ {
CBulletTraces::Init(); 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); RwIm3DVertexSetU(&StreakVertices[0], 0.0f);
RwIm3DVertexSetV(&StreakVertices[0], 0.0f); RwIm3DVertexSetV(&StreakVertices[0], 0.0f);
RwIm3DVertexSetU(&StreakVertices[1], 1.0f); RwIm3DVertexSetU(&StreakVertices[1], 1.0f);
@ -47,7 +70,6 @@ CSpecialFX::Init(void)
RwIm3DVertexSetV(&StreakVertices[2], 0.0f); RwIm3DVertexSetV(&StreakVertices[2], 0.0f);
RwIm3DVertexSetU(&StreakVertices[3], 1.0f); RwIm3DVertexSetU(&StreakVertices[3], 1.0f);
RwIm3DVertexSetV(&StreakVertices[3], 0.0f); RwIm3DVertexSetV(&StreakVertices[3], 0.0f);
StreakIndexList[0] = 0; StreakIndexList[0] = 0;
StreakIndexList[1] = 1; StreakIndexList[1] = 1;
StreakIndexList[2] = 2; StreakIndexList[2] = 2;
@ -61,43 +83,51 @@ CSpecialFX::Init(void)
StreakIndexList[10] = 2; StreakIndexList[10] = 2;
StreakIndexList[11] = 3; 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(); CMotionBlurStreaks::Init();
CBrightLights::Init(); CBrightLights::Init();
CShinyTexts::Init(); CShinyTexts::Init();
CMoneyMessages::Init(); CMoneyMessages::Init();
C3dMarkers::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* RwObject*
@ -119,23 +149,16 @@ CSpecialFX::Update(void)
{ {
CMotionBlurStreaks::Update(); CMotionBlurStreaks::Update();
CBulletTraces::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 void
CSpecialFX::Shutdown(void) CSpecialFX::Shutdown(void)
{ {
C3dMarkers::Shutdown(); C3dMarkers::Shutdown();
if (gpSmokeTrailTexture) {
RwTextureDestroy(gpSmokeTrailTexture);
gpSmokeTrailTexture = nil;
}
} }
void void
@ -149,6 +172,80 @@ CSpecialFX::Render(void)
C3dMarkers::Render(); 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]; CRegisteredMotionBlurStreak CMotionBlurStreaks::aStreaks[NUMMBLURSTREAKS];
void void
@ -217,6 +314,7 @@ void
CMotionBlurStreaks::RegisterStreak(uintptr id, uint8 r, uint8 g, uint8 b, CVector p1, CVector p2) CMotionBlurStreaks::RegisterStreak(uintptr id, uint8 r, uint8 g, uint8 b, CVector p1, CVector p2)
{ {
int i; int i;
for(i = 0; i < NUMMBLURSTREAKS; i++){ for(i = 0; i < NUMMBLURSTREAKS; i++){
if(aStreaks[i].m_id == id){ if(aStreaks[i].m_id == id){
// Found a streak from last frame, update // Found a streak from last frame, update
@ -229,10 +327,12 @@ CMotionBlurStreaks::RegisterStreak(uintptr id, uint8 r, uint8 g, uint8 b, CVecto
return; return;
} }
} }
// Find free slot // 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) if(i == NUMMBLURSTREAKS-1)
return; return;
// Create a new streak // Create a new streak
aStreaks[i].m_id = id; aStreaks[i].m_id = id;
aStreaks[i].m_red = r; aStreaks[i].m_red = r;
@ -281,20 +381,103 @@ void CBulletTraces::Init(void)
aTraces[i].m_bInUse = false; 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; int32 enabledCount;
for (index = 0; index < NUMBULLETTRACES; index++) { uint32 modifiedLifeTime;
if (!aTraces[index].m_bInUse) int32 nextSlot;
break;
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) void CBulletTraces::Render(void)
@ -303,31 +486,131 @@ void CBulletTraces::Render(void)
if (!aTraces[i].m_bInUse) if (!aTraces[i].m_bInUse)
continue; continue;
RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)FALSE); RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)FALSE);
#ifdef FIX_BUGS RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA);
// Raster has no transparent pixels so it relies on the raster format having alpha RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA);
// to turn on blending. librw image conversion might get rid of it right now so let's RwRenderStateSet(rwRENDERSTATETEXTURERASTER, RwTextureGetRaster(gpSmokeTrailTexture));
// just force it on.
RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)TRUE); 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 #endif
RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDONE);
RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDONE); if (RwIm3DTransform(TraceVertices, ARRAY_SIZE(TraceVertices), nil, 1)) {
RwRenderStateSet(rwRENDERSTATETEXTURERASTER, RwTextureGetRaster(gpShadowExplosionTex)); RwIm3DRenderIndexedPrimitive(rwPRIMTYPETRILIST, TraceIndexList, ARRAY_SIZE(TraceIndexList));
CVector inf = aTraces[i].m_vecCurrentPos; RwIm3DEnd();
CVector sup = aTraces[i].m_vecTargetPos; }
CVector center = (inf + sup) / 2;
CVector width = CrossProduct(TheCamera.GetForward(), (sup - inf)); RwIm3DVertexSetV(&TraceVertices[5], 2.0f);
width.Normalise(); RwIm3DVertexSetV(&TraceVertices[6], 2.0f);
width /= 20; RwIm3DVertexSetV(&TraceVertices[7], 2.0f);
uint8 intensity = aTraces[i].m_lifeTime; RwIm3DVertexSetV(&TraceVertices[8], 2.0f);
for (int i = 0; i < ARRAY_SIZE(TraceVertices); i++) RwIm3DVertexSetV(&TraceVertices[9], 2.0f);
RwIm3DVertexSetRGBA(&TraceVertices[i], intensity, intensity, intensity, 0xFF); RwIm3DVertexSetRGBA(&TraceVertices[0], 255, 255, 255, 0);
RwIm3DVertexSetPos(&TraceVertices[0], inf.x + width.x, inf.y + width.y, inf.z + width.z); RwIm3DVertexSetRGBA(&TraceVertices[1], 255, 255, 255, 0);
RwIm3DVertexSetPos(&TraceVertices[1], inf.x - width.x, inf.y - width.y, inf.z - width.z); RwIm3DVertexSetRGBA(&TraceVertices[2], 255, 255, 255, 0);
RwIm3DVertexSetPos(&TraceVertices[2], center.x + width.x, center.y + width.y, center.z + width.z); RwIm3DVertexSetRGBA(&TraceVertices[3], 255, 255, 255, 0);
RwIm3DVertexSetPos(&TraceVertices[3], center.x - width.x, center.y - width.y, center.z - width.z); RwIm3DVertexSetRGBA(&TraceVertices[4], 255, 255, 255, 0);
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); RwIm3DVertexSetPos(&TraceVertices[0], start.x, start.y, start.z);
LittleTest(); 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
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
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)) { if (RwIm3DTransform(TraceVertices, ARRAY_SIZE(TraceVertices), nil, rwIM3D_VERTEXUV)) {
RwIm3DRenderIndexedPrimitive(rwPRIMTYPETRILIST, TraceIndexList, ARRAY_SIZE(TraceIndexList)); RwIm3DRenderIndexedPrimitive(rwPRIMTYPETRILIST, TraceIndexList, ARRAY_SIZE(TraceIndexList));
RwIm3DEnd(); RwIm3DEnd();
@ -348,23 +631,8 @@ void CBulletTraces::Update(void)
void CBulletTrace::Update(void) void CBulletTrace::Update(void)
{ {
if (m_framesInUse == 0) { if (CTimer::GetTimeInMilliseconds() - m_nCreationTime >= m_nLifeTime)
m_framesInUse++;
return;
}
if (m_framesInUse > 60) {
m_bInUse = false; 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 * RpAtomic *
@ -578,7 +846,7 @@ C3dMarkers::PlaceMarker(uint32 identifier, uint16 type, CVector &pos, float size
} else { } else {
pMarker->m_fStdSize = size; pMarker->m_fStdSize = size;
} }
} else if (type == MARKERTYPE_CYLINDER) { } else {
if (dist < size + 12.0f) { if (dist < size + 12.0f) {
if (dist > size + 1.0f) if (dist > size + 1.0f)
pMarker->m_Color.alpha = (1.0f - (size + 12.0f - dist) * 0.7f / 11.0f) * (float)a; 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); 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; 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; pos.z += 0.25f * pMarker->m_fStdSize * someSin;
} else if (type == MARKERTYPE_0) { if (pMarker->m_nRotateRate != 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) {
RwV3d pos = pMarker->m_Matrix.m_matrix.pos; RwV3d pos = pMarker->m_Matrix.m_matrix.pos;
pMarker->m_Matrix.RotateZ(DEGTORAD(pMarker->m_nRotateRate * CTimer::GetTimeStep())); pMarker->m_Matrix.RotateZ(DEGTORAD(pMarker->m_nRotateRate * CTimer::GetTimeStep()));
pMarker->m_Matrix.GetPosition() = pos; pMarker->m_Matrix.GetPosition() = pos;
@ -623,7 +885,7 @@ C3dMarkers::PlaceMarker(uint32 identifier, uint16 type, CVector &pos, float size
pMarker->DeleteMarkerObject(); pMarker->DeleteMarkerObject();
pMarker->AddMarker(identifier, type, size, r, g, b, a, pulsePeriod, pulseFraction, rotateRate); 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))) { if ((playerPos - pos).MagnitudeSqr() < sq(100.f) && CColStore::HasCollisionLoaded(CVector2D(pos))) {
float z = CWorld::FindGroundZFor3DCoord(pos.x, pos.y, pos.z + 1.0f, nil); float z = CWorld::FindGroundZFor3DCoord(pos.x, pos.y, pos.z + 1.0f, nil);
if (z != 0.0f) 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); 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(); pMarker->m_Matrix.UpdateRW();
if (type == MARKERTYPE_ARROW) { if (type == MARKERTYPE_ARROW) {
if (dist < 25.0f) { if (dist < 25.0f) {
@ -648,7 +906,7 @@ C3dMarkers::PlaceMarker(uint32 identifier, uint16 type, CVector &pos, float size
} else { } else {
pMarker->m_fStdSize = size; pMarker->m_fStdSize = size;
} }
} else if (type == MARKERTYPE_CYLINDER) { } else {
if (dist < size + 12.0f) { if (dist < size + 12.0f) {
if (dist > size + 1.0f) if (dist > size + 1.0f)
pMarker->m_Color.alpha = (1.0f - (size + 12.0f - dist) * 0.7f / 11.0f) * (float)a; 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(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA);
RwRenderStateSet(rwRENDERSTATETEXTURERASTER, nil); RwRenderStateSet(rwRENDERSTATETEXTURERASTER, nil);
TempBufferVerticesStored = 0;
TempBufferIndicesStored = 0;
for(i = 0; i < NumBrightLights; i++){ for(i = 0; i < NumBrightLights; i++){
if(TempBufferIndicesStored > TEMPBUFFERINDEXSIZE-40 || TempBufferVerticesStored > TEMPBUFFERVERTSIZE-40) if(TempBufferIndicesStored > TEMPBUFFERINDEXSIZE-40 || TempBufferVerticesStored > TEMPBUFFERVERTSIZE-40)
RenderOutGeometryBuffer(); RenderOutGeometryBuffer();
@ -788,6 +1049,10 @@ CBrightLights::Render(void)
g = aBrightLights[i].m_green; g = aBrightLights[i].m_green;
b = aBrightLights[i].m_blue; b = aBrightLights[i].m_blue;
break; 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) if(aBrightLights[i].m_camDist < BRIGHTLIGHTS_FADE_DIST)
@ -854,18 +1119,18 @@ CBrightLights::Render(void)
case BRIGHTLIGHT_FRONT_BIG: case BRIGHTLIGHT_FRONT_BIG:
case BRIGHTLIGHT_REAR_BIG: case BRIGHTLIGHT_REAR_BIG:
for (j = 0; j < 8; j++) { for (j = 0; j < 8; j++) {
pos = BigCarHeadLightsSide[j] * aBrightLights[i].m_side + pos = BigCarHeadLightsSide[j] * aBrightLights[i].m_side +
BigCarHeadLightsUp[j] * aBrightLights[i].m_up + BigCarHeadLightsUp[j] * aBrightLights[i].m_up +
BigCarHeadLightsFront[j] * aBrightLights[i].m_front + BigCarHeadLightsFront[j] * aBrightLights[i].m_front +
aBrightLights[i].m_pos; aBrightLights[i].m_pos;
RwIm3DVertexSetRGBA(&TempBufferRenderVertices[TempBufferVerticesStored + j], r, g, b, a); RwIm3DVertexSetRGBA(&TempBufferRenderVertices[TempBufferVerticesStored + j], r, g, b, a);
RwIm3DVertexSetPos(&TempBufferRenderVertices[TempBufferVerticesStored + j], pos.x, pos.y, pos.z); RwIm3DVertexSetPos(&TempBufferRenderVertices[TempBufferVerticesStored + j], pos.x, pos.y, pos.z);
} }
for (j = 0; j < 12 * 3; j++) for (j = 0; j < 12 * 3; j++)
TempBufferRenderIndexList[TempBufferIndicesStored + j] = CubeIndices[j] + TempBufferVerticesStored; TempBufferRenderIndexList[TempBufferIndicesStored + j] = CubeIndices[j] + TempBufferVerticesStored;
TempBufferVerticesStored += 8; TempBufferVerticesStored += 8;
TempBufferIndicesStored += 12 * 3; TempBufferIndicesStored += 12 * 3;
break; break;
case BRIGHTLIGHT_FRONT_TALL: case BRIGHTLIGHT_FRONT_TALL:
case BRIGHTLIGHT_REAR_TALL: case BRIGHTLIGHT_REAR_TALL:
@ -1072,8 +1337,9 @@ CMoneyMessage::Render()
{ {
const float MAX_SCALE = 4.0f; const float MAX_SCALE = 4.0f;
uint32 nLifeTime = CTimer::GetTimeInMilliseconds() - m_nTimeRegistered; uint32 nLifeTime = CTimer::GetTimeInMilliseconds() - m_nTimeRegistered;
if (nLifeTime >= MONEY_MESSAGE_LIFETIME_MS) m_nTimeRegistered = 0; if (nLifeTime >= MONEY_MESSAGE_LIFETIME_MS) {
else { m_nTimeRegistered = 0;
} else {
float fLifeTime = (float)nLifeTime / MONEY_MESSAGE_LIFETIME_MS; float fLifeTime = (float)nLifeTime / MONEY_MESSAGE_LIFETIME_MS;
RwV3d vecOut; RwV3d vecOut;
float fDistX, fDistY; float fDistX, fDistY;
@ -1082,17 +1348,15 @@ CMoneyMessage::Render()
fDistY *= (0.7 * fLifeTime + 2.0) * m_fSize; fDistY *= (0.7 * fLifeTime + 2.0) * m_fSize;
CFont::SetPropOn(); CFont::SetPropOn();
CFont::SetBackgroundOff(); CFont::SetBackgroundOff();
float fScaleY = Min(fDistY / 100.0f, MAX_SCALE); float fScaleY = Min(fDistY / 100.0f, MAX_SCALE);
float fScaleX = Min(fDistX / 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::SetScale(fScaleX, fScaleY); // maybe use SCREEN_SCALE_X and SCREEN_SCALE_Y here?
CFont::SetCentreOn(); CFont::SetCentreOn();
CFont::SetCentreSize(SCREEN_WIDTH); CFont::SetCentreSize(SCREEN_WIDTH);
CFont::SetJustifyOff(); CFont::SetJustifyOff();
CFont::SetColor(CRGBA(m_Colour.r, m_Colour.g, m_Colour.b, (255.0f - 255.0f * fLifeTime) * m_fOpacity)); CFont::SetColor(CRGBA(m_Colour.r, m_Colour.g, m_Colour.b, (255.0f - 255.0f * fLifeTime) * m_fOpacity));
CFont::SetBackGroundOnlyTextOff(); CFont::SetBackGroundOnlyTextOff();
CFont::SetFontStyle(FONT_STANDARD); FONT_LOCALE(FONT_STANDARD);
CFont::PrintString(vecOut.x, vecOut.y, m_aText); CFont::PrintString(vecOut.x, vecOut.y, m_aText);
} }
} }

View file

@ -1,8 +1,12 @@
#pragma once #pragma once
//file done
class CSpecialFX class CSpecialFX
{ {
public: public:
static bool bVideoCam;
static bool bLiftCam;
static bool bSnapShotActive; static bool bSnapShotActive;
static int32 SnapShotFrames; static int32 SnapShotFrames;
@ -10,8 +14,11 @@ public:
static void Update(void); static void Update(void);
static void Init(void); static void Init(void);
static void Shutdown(void); static void Shutdown(void);
static void AddWeaponStreak(int type);
static void Render2DFXs();
}; };
class CRegisteredMotionBlurStreak class CRegisteredMotionBlurStreak
{ {
public: public:
@ -27,6 +34,7 @@ public:
void Render(void); void Render(void);
}; };
class CMotionBlurStreaks class CMotionBlurStreaks
{ {
static CRegisteredMotionBlurStreak aStreaks[NUMMBLURSTREAKS]; static CRegisteredMotionBlurStreak aStreaks[NUMMBLURSTREAKS];
@ -37,33 +45,31 @@ public:
static void Render(void); static void Render(void);
}; };
struct CBulletTrace struct CBulletTrace
{ {
CVector m_vecCurrentPos; CVector m_vecStartPos;
CVector m_vecTargetPos; CVector m_vecEndPos;
bool m_bInUse; bool m_bInUse;
uint8 m_framesInUse; uint32 m_nCreationTime;
uint8 m_lifeTime; uint32 m_nLifeTime;
float m_fThickness;
uint8 m_fVisibility;
void Update(void); void Update(void);
}; };
class CBulletTraces class CBulletTraces
{ {
public: public:
static CBulletTrace aTraces[NUMBULLETTRACES]; static CBulletTrace aTraces[NUMBULLETTRACES];
static void Init(void); static void Init(void);
static void AddTrace(CVector*, CVector*);
static void Render(void); static void Render(void);
static void Update(void); static void Update(void);
static void AddTrace(CVector* start, CVector* end, float thickness, uint32 lifeTime, uint8 visibility);
//TODO(MIAMI) static void AddTrace(CVector* start, CVector* end, int32 weaponType, class CEntity* shooter);
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
}
}; };
enum enum
@ -104,6 +110,7 @@ public:
void Render(); void Render();
}; };
class C3dMarkers class C3dMarkers
{ {
public: public:
@ -144,6 +151,7 @@ enum
BRIGHTLIGHT_REAR = BRIGHTLIGHT_REAR_LONG, BRIGHTLIGHT_REAR = BRIGHTLIGHT_REAR_LONG,
}; };
class CBrightLight class CBrightLight
{ {
public: public:
@ -158,6 +166,7 @@ public:
uint8 m_blue; uint8 m_blue;
}; };
class CBrightLights class CBrightLights
{ {
static int NumBrightLights; static int NumBrightLights;
@ -177,6 +186,7 @@ enum
SHINYTEXT_FLAT SHINYTEXT_FLAT
}; };
class CShinyText class CShinyText
{ {
public: public:
@ -189,6 +199,7 @@ public:
uint8 m_blue; uint8 m_blue;
}; };
class CShinyTexts class CShinyTexts
{ {
static int NumShinyTexts; static int NumShinyTexts;
@ -197,11 +208,12 @@ public:
static void Init(void); static void Init(void);
static void RegisterOne(CVector p0, CVector p1, CVector p2, CVector p3, 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, 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 Render(void);
static void RenderOutGeometryBuffer(void); static void RenderOutGeometryBuffer(void);
}; };
class CMoneyMessage class CMoneyMessage
{ {
friend class CMoneyMessages; friend class CMoneyMessages;
@ -216,6 +228,7 @@ public:
void Render(); void Render();
}; };
class CMoneyMessages class CMoneyMessages
{ {
static CMoneyMessage aMoneyMessages[NUMMONEYMESSAGES]; 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); static void RegisterOne(CVector vecPos, const char *pText, uint8 bRed, uint8 bGreen, uint8 bBlue, float fSize, float fOpacity);
}; };
class CSpecialParticleStuff class CSpecialParticleStuff
{ {
static uint32 BoatFromStart; static uint32 BoatFromStart;
public: public:
static void CreateFoamAroundObject(CMatrix*, float, float, float, int32); static void CreateFoamAroundObject(CMatrix*, float, float, float, int32); //not used
static void StartBoatFoamAnimation(); static void StartBoatFoamAnimation(); //not used
static void UpdateBoatFoamAnimation(CMatrix*); static void UpdateBoatFoamAnimation(CMatrix*); //not used
}; };