normalized line endings to LF

This commit is contained in:
aap 2020-04-09 20:50:24 +02:00
parent a5239b554f
commit 34349c4df2
37 changed files with 7717 additions and 7717 deletions

View File

@ -1,403 +1,403 @@
#include "common.h"
#include "patcher.h"
#include "DMAudio.h"
#include "Entity.h"
#include "AudioCollision.h"
#include "AudioManager.h"
#include "AudioSamples.h"
#include "SurfaceTable.h"
#include "sampman.h"
const int CollisionSoundIntensity = 60;
void
cAudioCollisionManager::AddCollisionToRequestedQueue()
{
int32 collisionsIndex;
int32 i;
if (m_bCollisionsInQueue < NUMAUDIOCOLLISIONS)
collisionsIndex = m_bCollisionsInQueue++;
else {
collisionsIndex = m_bIndicesTable[NUMAUDIOCOLLISIONS - 1];
if (m_sQueue.m_fDistance >= m_asCollisions1[collisionsIndex].m_fDistance) return;
}
m_asCollisions1[collisionsIndex] = m_sQueue;
i = 0;
if(collisionsIndex) {
while(m_asCollisions1[m_bIndicesTable[i]].m_fDistance <= m_asCollisions1[collisionsIndex].m_fDistance) {
if(++i >= collisionsIndex) {
m_bIndicesTable[i] = collisionsIndex;
return;
}
}
memmove(&m_bIndicesTable[i + 1], &m_bIndicesTable[i], NUMAUDIOCOLLISIONS - 1 - i);
}
m_bIndicesTable[i] = collisionsIndex;
}
float
cAudioManager::GetCollisionLoopingRatio(uint32 a, uint32 b, float c) const
{
return GetCollisionRatio(c, 0.0f, 0.02f, 0.02f);
}
float
cAudioManager::GetCollisionOneShotRatio(int32 a, float b) const
{
float result;
switch(a) {
case SURFACE_DEFAULT:
case SURFACE_TARMAC:
case SURFACE_PAVEMENT:
case SURFACE_STONE:
case SURFACE_BOLLARD: result = GetCollisionRatio(b, 10.f, 60.f, 50.f); break;
case SURFACE_GRASS:
case SURFACE_LOOSE30: result = GetCollisionRatio(b, 0.f, 2.f, 2.f); break;
case SURFACE_DIRT: result = GetCollisionRatio(b, 0.f, 2.f, 2.f); break;
case SURFACE_DIRTTRACK: result = GetCollisionRatio(b, 0.f, 2.f, 2.f); break;
case SURFACE_METAL6: result = GetCollisionRatio(b, 6.f, 50.f, 44.f); break;
case SURFACE_GLASS: result = GetCollisionRatio(b, 0.1f, 10.f, 9.9f); break;
case SURFACE_SCAFFOLD:
case SURFACE_STEEL: result = GetCollisionRatio(b, 30.f, 130.f, 100.f); break;
case SURFACE_METAL_DOOR: result = GetCollisionRatio(b, 20.f, 100.f, 80.f); break;
case SURFACE_BILLBOARD: result = GetCollisionRatio(b, 0.f, 4.f, 4.f); break;
case SURFACE_METAL_POLE:
case SURFACE_GATE: result = GetCollisionRatio(b, 1.f, 10.f, 9.f); break;
case SURFACE_STREET_LIGHT: result = GetCollisionRatio(b, 1.f, 10.f, 9.f); break;
case SURFACE_METAL14: result = GetCollisionRatio(b, 1.f, 15.f, 14.f); break;
case SURFACE_METAL15: result = GetCollisionRatio(b, 8.f, 50.f, 42.f); break;
case SURFACE_METAL_FENCE: result = GetCollisionRatio(b, 0.1f, 10.f, 9.9f); break;
case SURFACE_FLESH: result = GetCollisionRatio(b, 0.f, 20.f, 20.f); break;
case SURFACE_SAND: result = GetCollisionRatio(b, 0.f, 10.f, 10.f); break;
case SURFACE_PUDDLE: result = GetCollisionRatio(b, 0.f, 10.f, 10.f); break;
case SURFACE_WOOD: result = GetCollisionRatio(b, 1.f, 4.f, 3.f); break;
case SURFACE_WOOD_BOX: result = GetCollisionRatio(b, 0.1f, 5.f, 4.9f); break;
case SURFACE_WOOD_PLANK: result = GetCollisionRatio(b, 0.1f, 40.f, 39.9f); break;
case SURFACE_TIRE:
case SURFACE_RUBBER29: result = GetCollisionRatio(b, 0.f, 10.f, 10.f); break;
case SURFACE_HARD24: result = GetCollisionRatio(b, 0.1f, 4.f, 3.9f); break;
case SURFACE_HEDGE: result = GetCollisionRatio(b, 0.f, 0.5f, 0.5f); break;
case SURFACE_METAL27: result = GetCollisionRatio(b, 4.f, 40.f, 36.f); break;
case SURFACE_METAL28: result = GetCollisionRatio(b, 0.f, 5.f, 5.f); break;
default: result = 0.f; break;
}
return result;
}
float
cAudioManager::GetCollisionRatio(float a, float b, float c, float d) const
{
float e;
e = a;
if(a <= b) return 0.0f;
if(c <= a) e = c;
return (e - b) / d;
}
uint32
cAudioManager::SetLoopingCollisionRequestedSfxFreqAndGetVol(cAudioCollision *audioCollision)
{
uint8 surface1 = audioCollision->m_bSurface1;
uint8 surface2 = audioCollision->m_bSurface2;
int32 vol;
float ratio;
if(surface1 == SURFACE_GRASS || surface2 == SURFACE_GRASS || surface1 == SURFACE_HEDGE ||
surface2 == SURFACE_HEDGE) {
ratio = GetCollisionRatio(audioCollision->m_fIntensity2, 0.0001f, 0.09f, 0.0899f);
m_sQueueSample.m_nSampleIndex = SFX_RAIN;
m_sQueueSample.m_nFrequency = 13000.f * ratio + 35000;
vol = 50.f * ratio;
} else {
if(surface1 == SURFACE_PUDDLE || surface2 == SURFACE_PUDDLE) {
ratio = GetCollisionRatio(audioCollision->m_fIntensity2, 0.0001f, 0.09f, 0.0899f);
m_sQueueSample.m_nSampleIndex = SFX_BOAT_WATER_LOOP;
m_sQueueSample.m_nFrequency = 6050.f * ratio + 16000;
vol = 30.f * ratio;
} else {
if(surface1 == SURFACE_DIRT || surface2 == SURFACE_DIRT || surface1 == SURFACE_DIRTTRACK ||
surface2 == SURFACE_DIRTTRACK || surface1 == SURFACE_SAND || surface2 == SURFACE_SAND) {
ratio = GetCollisionRatio(audioCollision->m_fIntensity2, 0.0001f, 0.09f, 0.0899f);
m_sQueueSample.m_nSampleIndex = SFX_GRAVEL_SKID;
m_sQueueSample.m_nFrequency = 6000.f * ratio + 10000;
vol = 50.f * ratio;
} else {
if(surface1 == SURFACE_FLESH || surface2 == SURFACE_FLESH) { return 0; }
ratio = GetCollisionRatio(audioCollision->m_fIntensity2, 0.0001f, 0.09f, 0.0899f);
m_sQueueSample.m_nSampleIndex = SFX_SCRAPE_CAR_1;
m_sQueueSample.m_nFrequency = 10000.f * ratio + 10000;
vol = 40.f * ratio;
}
}
}
if(audioCollision->m_nBaseVolume < 2) vol = audioCollision->m_nBaseVolume * vol / 2;
return vol;
}
void
cAudioManager::SetUpLoopingCollisionSound(cAudioCollision *col, uint8 counter)
{
if(col->m_fIntensity2 > 0.0016f) {
uint8 emittingVol = SetLoopingCollisionRequestedSfxFreqAndGetVol(col);
if(emittingVol) {
m_sQueueSample.m_fDistance = Sqrt(col->m_fDistance);
m_sQueueSample.m_bVolume =
ComputeVolume(emittingVol, CollisionSoundIntensity, m_sQueueSample.m_fDistance);
if(m_sQueueSample.m_bVolume) {
m_sQueueSample.m_counter = counter;
m_sQueueSample.m_vecPos = col->m_vecPosition;
m_sQueueSample.m_bBankIndex = SAMPLEBANK_MAIN;
m_sQueueSample.m_bIs2D = false;
m_sQueueSample.m_nReleasingVolumeModificator = 7;
m_sQueueSample.m_nLoopCount = 0;
m_sQueueSample.m_bEmittingVolume = emittingVol;
m_sQueueSample.m_nLoopStart =
SampleManager.GetSampleLoopStartOffset(m_sQueueSample.m_nSampleIndex);
m_sQueueSample.m_nLoopEnd =
SampleManager.GetSampleLoopEndOffset(m_sQueueSample.m_nSampleIndex);
m_sQueueSample.m_fSpeedMultiplier = 4.0f;
m_sQueueSample.m_fSoundIntensity = CollisionSoundIntensity;
m_sQueueSample.m_bReleasingSoundFlag = 0;
m_sQueueSample.m_nReleasingVolumeDivider = 5;
m_sQueueSample.m_bReverbFlag = true;
m_sQueueSample.m_bRequireReflection = false;
AddSampleToRequestedQueue();
}
}
}
}
void
cAudioManager::SetUpOneShotCollisionSound(cAudioCollision *col)
{
static const int32 gOneShotCol[] = {
SFX_COL_TARMAC_1, SFX_COL_TARMAC_1, SFX_COL_GRASS_1,
SFX_COL_GRAVEL_1, SFX_COL_MUD_1, SFX_COL_TARMAC_1,
SFX_COL_CAR_1, SFX_COL_GRASS_1, SFX_COL_SCAFFOLD_POLE_1,
SFX_COL_GARAGE_DOOR_1, SFX_COL_CAR_PANEL_1, SFX_COL_THICK_METAL_PLATE_1,
SFX_COL_SCAFFOLD_POLE_1, SFX_COL_LAMP_POST_1, SFX_COL_HYDRANT_1,
SFX_COL_HYDRANT_1, SFX_COL_METAL_CHAIN_FENCE_1, SFX_COL_PED_1,
SFX_COL_SAND_1, SFX_SPLASH_1, SFX_COL_WOOD_CRATES_1,
SFX_COL_WOOD_BENCH_1, SFX_COL_WOOD_SOLID_1, SFX_COL_GRASS_1,
SFX_COL_GRASS_1, SFX_COL_VEG_1, SFX_COL_TARMAC_1,
SFX_COL_CONTAINER_1, SFX_COL_NEWS_VENDOR_1, SFX_TYRE_BUMP,
SFX_COL_CARDBOARD_1, SFX_COL_TARMAC_1, SFX_COL_GATE};
int16 s1;
int16 s2;
int32 emittingVol;
float ratio;
static uint16 counter = 28;
for(int32 i = 0; i < 2; i++) {
if(i) {
s1 = col->m_bSurface2;
s2 = col->m_bSurface1;
} else {
s1 = col->m_bSurface1;
s2 = col->m_bSurface2;
}
ratio = GetCollisionOneShotRatio(s1, col->m_fIntensity1);
if(s1 == SURFACE_METAL6 && s2 == SURFACE_FLESH) ratio = 0.25f * ratio;
if(s1 == SURFACE_METAL6 && ratio < 0.6f) {
s1 = SURFACE_BILLBOARD;
ratio = min(1.f, 2.f * ratio);
}
emittingVol = 40.f * ratio;
if(emittingVol) {
m_sQueueSample.m_fDistance = Sqrt(col->m_fDistance);
m_sQueueSample.m_bVolume =
ComputeVolume(emittingVol, CollisionSoundIntensity, m_sQueueSample.m_fDistance);
if(m_sQueueSample.m_bVolume) {
m_sQueueSample.m_nSampleIndex = gOneShotCol[s1];
switch(m_sQueueSample.m_nSampleIndex) {
case SFX_COL_TARMAC_1:
m_sQueueSample.m_nSampleIndex += m_anRandomTable[3] % 5;
break;
case SFX_COL_CAR_PANEL_1:
m_sQueueSample.m_nSampleIndex += m_anRandomTable[0] % 6;
break;
case SFX_COL_LAMP_POST_1:
m_sQueueSample.m_nSampleIndex += m_anRandomTable[1] % 2;
break;
case SFX_COL_METAL_CHAIN_FENCE_1:
m_sQueueSample.m_nSampleIndex += m_anRandomTable[3] % 4;
break;
case SFX_COL_PED_1:
m_sQueueSample.m_nSampleIndex += m_anRandomTable[4] % 5;
break;
case SFX_COL_WOOD_CRATES_1:
m_sQueueSample.m_nSampleIndex += m_anRandomTable[4] % 4;
break;
case SFX_COL_WOOD_BENCH_1:
m_sQueueSample.m_nSampleIndex += m_anRandomTable[1] % 4;
break;
case SFX_COL_VEG_1:
m_sQueueSample.m_nSampleIndex += m_anRandomTable[2] % 5;
break;
case SFX_COL_NEWS_VENDOR_1:
m_sQueueSample.m_nSampleIndex += m_anRandomTable[2] % 3;
break;
case SFX_COL_CAR_1:
m_sQueueSample.m_nSampleIndex += m_anRandomTable[1] % 5;
break;
case SFX_COL_CARDBOARD_1:
m_sQueueSample.m_nSampleIndex += m_anRandomTable[3] % 2;
break;
default: break;
}
switch(s1) {
case SURFACE_GLASS: m_sQueueSample.m_nFrequency = 13500; break;
case SURFACE_METAL15: m_sQueueSample.m_nFrequency = 8819; break;
case SURFACE_PUDDLE:
m_sQueueSample.m_nFrequency =
2 * SampleManager.GetSampleBaseFrequency(m_sQueueSample.m_nSampleIndex);
break;
case SURFACE_TIRE: m_sQueueSample.m_nFrequency = 6000; break;
case SURFACE_HARD24: m_sQueueSample.m_nFrequency = 8000; break;
default:
m_sQueueSample.m_nFrequency =
SampleManager.GetSampleBaseFrequency(m_sQueueSample.m_nSampleIndex);
break;
}
m_sQueueSample.m_nFrequency += RandomDisplacement(m_sQueueSample.m_nFrequency / 16);
m_sQueueSample.m_counter = counter++;
if(counter >= 255) counter = 28;
m_sQueueSample.m_vecPos = col->m_vecPosition;
m_sQueueSample.m_bBankIndex = SAMPLEBANK_MAIN;
m_sQueueSample.m_bIs2D = false;
m_sQueueSample.m_nReleasingVolumeModificator = 11;
m_sQueueSample.m_nLoopCount = 1;
m_sQueueSample.m_bEmittingVolume = emittingVol;
m_sQueueSample.m_nLoopStart = 0;
m_sQueueSample.m_nLoopEnd = -1;
m_sQueueSample.m_fSpeedMultiplier = 4.0f;
m_sQueueSample.m_fSoundIntensity = CollisionSoundIntensity;
m_sQueueSample.m_bReleasingSoundFlag = 1;
m_sQueueSample.m_bReverbFlag = true;
m_sQueueSample.m_bRequireReflection = false;
AddSampleToRequestedQueue();
}
}
}
}
void
cAudioManager::ServiceCollisions()
{
int i, j;
bool someArr1[NUMAUDIOCOLLISIONS];
bool someArr2[NUMAUDIOCOLLISIONS];
m_sQueueSample.m_nEntityIndex = m_nCollisionEntity;
for (int i = 0; i < NUMAUDIOCOLLISIONS; i++)
someArr1[i] = someArr2[i] = false;
for (i = 0; i < m_sCollisionManager.m_bCollisionsInQueue; i++) {
for (j = 0; j < NUMAUDIOCOLLISIONS; j++) {
int index = m_sCollisionManager.m_bIndicesTable[i];
if ((m_sCollisionManager.m_asCollisions1[index].m_pEntity1 == m_sCollisionManager.m_asCollisions2[j].m_pEntity1)
&& (m_sCollisionManager.m_asCollisions1[index].m_pEntity2 == m_sCollisionManager.m_asCollisions2[j].m_pEntity2)
&& (m_sCollisionManager.m_asCollisions1[index].m_bSurface1 == m_sCollisionManager.m_asCollisions2[j].m_bSurface1)
&& (m_sCollisionManager.m_asCollisions1[index].m_bSurface2 == m_sCollisionManager.m_asCollisions2[j].m_bSurface2)
) {
someArr1[index] = true;
someArr2[j] = true;
m_sCollisionManager.m_asCollisions1[index].m_nBaseVolume = ++m_sCollisionManager.m_asCollisions2[j].m_nBaseVolume;
SetUpLoopingCollisionSound(&m_sCollisionManager.m_asCollisions1[index], j);
break;
}
}
}
for (i = 0; i < NUMAUDIOCOLLISIONS; i++) {
if (!someArr2[i]) {
m_sCollisionManager.m_asCollisions2[i].m_pEntity1 = nil;
m_sCollisionManager.m_asCollisions2[i].m_pEntity2 = nil;
m_sCollisionManager.m_asCollisions2[i].m_bSurface1 = SURFACE_DEFAULT;
m_sCollisionManager.m_asCollisions2[i].m_bSurface2 = SURFACE_DEFAULT;
m_sCollisionManager.m_asCollisions2[i].m_fIntensity2 = 0.0f;
m_sCollisionManager.m_asCollisions2[i].m_fIntensity1 = 0.0f;
m_sCollisionManager.m_asCollisions2[i].m_vecPosition = CVector(0.0f, 0.0f, 0.0f);
m_sCollisionManager.m_asCollisions2[i].m_fDistance = 0.0f;
}
}
for (i = 0; i < m_sCollisionManager.m_bCollisionsInQueue; i++) {
int index = m_sCollisionManager.m_bIndicesTable[i];
if (!someArr1[index]) {
for (j = 0; j < NUMAUDIOCOLLISIONS; j++) {
if (someArr2[j]) {
m_sCollisionManager.m_asCollisions2[j].m_nBaseVolume = 1;
m_sCollisionManager.m_asCollisions2[j].m_pEntity1 = m_sCollisionManager.m_asCollisions1[index].m_pEntity1;
m_sCollisionManager.m_asCollisions2[j].m_pEntity2 = m_sCollisionManager.m_asCollisions1[index].m_pEntity2;
m_sCollisionManager.m_asCollisions2[j].m_bSurface1 = m_sCollisionManager.m_asCollisions1[index].m_bSurface1;
m_sCollisionManager.m_asCollisions2[j].m_bSurface2 = m_sCollisionManager.m_asCollisions1[index].m_bSurface2;
break;
}
}
SetUpOneShotCollisionSound(&m_sCollisionManager.m_asCollisions1[index]);
SetUpLoopingCollisionSound(&m_sCollisionManager.m_asCollisions1[index], j);
}
}
for (int i = 0; i < NUMAUDIOCOLLISIONS; i++)
m_sCollisionManager.m_bIndicesTable[i] = NUMAUDIOCOLLISIONS;
m_sCollisionManager.m_bCollisionsInQueue = 0;
}
void
cAudioManager::ReportCollision(CEntity *entity1, CEntity *entity2, uint8 surface1, uint8 surface2, float collisionPower,
float velocity)
{
float distSquared;
CVector v1;
CVector v2;
if(!m_bIsInitialised || m_nCollisionEntity < 0 || m_bUserPause ||
(velocity < 0.0016f && collisionPower < 0.01f))
return;
if(entity1->IsBuilding()) {
v1 = v2 = entity2->GetPosition();
} else if(entity2->IsBuilding()) {
v1 = v2 = entity1->GetPosition();
} else {
v1 = entity1->GetPosition();
v2 = entity2->GetPosition();
}
CVector pos = (v1 + v2) * 0.5f;
distSquared = GetDistanceSquared(&pos);
if(distSquared < SQR(CollisionSoundIntensity)) {
m_sCollisionManager.m_sQueue.m_pEntity1 = entity1;
m_sCollisionManager.m_sQueue.m_pEntity2 = entity2;
m_sCollisionManager.m_sQueue.m_bSurface1 = surface1;
m_sCollisionManager.m_sQueue.m_bSurface2 = surface2;
m_sCollisionManager.m_sQueue.m_fIntensity1 = collisionPower;
m_sCollisionManager.m_sQueue.m_fIntensity2 = velocity;
m_sCollisionManager.m_sQueue.m_vecPosition = pos;
m_sCollisionManager.m_sQueue.m_fDistance = distSquared;
m_sCollisionManager.AddCollisionToRequestedQueue();
}
}
STARTPATCHES
InjectHook(0x5685E0, &cAudioCollisionManager::AddCollisionToRequestedQueue, PATCH_JUMP);
InjectHook(0x569060, &cAudioManager::GetCollisionOneShotRatio, PATCH_JUMP);
InjectHook(0x5693B0, &cAudioManager::GetCollisionRatio, PATCH_JUMP);
InjectHook(0x568410, &cAudioManager::ReportCollision, PATCH_JUMP);
InjectHook(0x5686D0, &cAudioManager::ServiceCollisions, PATCH_JUMP);
InjectHook(0x568E20, &cAudioManager::SetLoopingCollisionRequestedSfxFreqAndGetVol, PATCH_JUMP);
InjectHook(0x568D30, &cAudioManager::SetUpLoopingCollisionSound, PATCH_JUMP);
InjectHook(0x5689D0, &cAudioManager::SetUpOneShotCollisionSound, PATCH_JUMP);
ENDPATCHES
#include "common.h"
#include "patcher.h"
#include "DMAudio.h"
#include "Entity.h"
#include "AudioCollision.h"
#include "AudioManager.h"
#include "AudioSamples.h"
#include "SurfaceTable.h"
#include "sampman.h"
const int CollisionSoundIntensity = 60;
void
cAudioCollisionManager::AddCollisionToRequestedQueue()
{
int32 collisionsIndex;
int32 i;
if (m_bCollisionsInQueue < NUMAUDIOCOLLISIONS)
collisionsIndex = m_bCollisionsInQueue++;
else {
collisionsIndex = m_bIndicesTable[NUMAUDIOCOLLISIONS - 1];
if (m_sQueue.m_fDistance >= m_asCollisions1[collisionsIndex].m_fDistance) return;
}
m_asCollisions1[collisionsIndex] = m_sQueue;
i = 0;
if(collisionsIndex) {
while(m_asCollisions1[m_bIndicesTable[i]].m_fDistance <= m_asCollisions1[collisionsIndex].m_fDistance) {
if(++i >= collisionsIndex) {
m_bIndicesTable[i] = collisionsIndex;
return;
}
}
memmove(&m_bIndicesTable[i + 1], &m_bIndicesTable[i], NUMAUDIOCOLLISIONS - 1 - i);
}
m_bIndicesTable[i] = collisionsIndex;
}
float
cAudioManager::GetCollisionLoopingRatio(uint32 a, uint32 b, float c) const
{
return GetCollisionRatio(c, 0.0f, 0.02f, 0.02f);
}
float
cAudioManager::GetCollisionOneShotRatio(int32 a, float b) const
{
float result;
switch(a) {
case SURFACE_DEFAULT:
case SURFACE_TARMAC:
case SURFACE_PAVEMENT:
case SURFACE_STONE:
case SURFACE_BOLLARD: result = GetCollisionRatio(b, 10.f, 60.f, 50.f); break;
case SURFACE_GRASS:
case SURFACE_LOOSE30: result = GetCollisionRatio(b, 0.f, 2.f, 2.f); break;
case SURFACE_DIRT: result = GetCollisionRatio(b, 0.f, 2.f, 2.f); break;
case SURFACE_DIRTTRACK: result = GetCollisionRatio(b, 0.f, 2.f, 2.f); break;
case SURFACE_METAL6: result = GetCollisionRatio(b, 6.f, 50.f, 44.f); break;
case SURFACE_GLASS: result = GetCollisionRatio(b, 0.1f, 10.f, 9.9f); break;
case SURFACE_SCAFFOLD:
case SURFACE_STEEL: result = GetCollisionRatio(b, 30.f, 130.f, 100.f); break;
case SURFACE_METAL_DOOR: result = GetCollisionRatio(b, 20.f, 100.f, 80.f); break;
case SURFACE_BILLBOARD: result = GetCollisionRatio(b, 0.f, 4.f, 4.f); break;
case SURFACE_METAL_POLE:
case SURFACE_GATE: result = GetCollisionRatio(b, 1.f, 10.f, 9.f); break;
case SURFACE_STREET_LIGHT: result = GetCollisionRatio(b, 1.f, 10.f, 9.f); break;
case SURFACE_METAL14: result = GetCollisionRatio(b, 1.f, 15.f, 14.f); break;
case SURFACE_METAL15: result = GetCollisionRatio(b, 8.f, 50.f, 42.f); break;
case SURFACE_METAL_FENCE: result = GetCollisionRatio(b, 0.1f, 10.f, 9.9f); break;
case SURFACE_FLESH: result = GetCollisionRatio(b, 0.f, 20.f, 20.f); break;
case SURFACE_SAND: result = GetCollisionRatio(b, 0.f, 10.f, 10.f); break;
case SURFACE_PUDDLE: result = GetCollisionRatio(b, 0.f, 10.f, 10.f); break;
case SURFACE_WOOD: result = GetCollisionRatio(b, 1.f, 4.f, 3.f); break;
case SURFACE_WOOD_BOX: result = GetCollisionRatio(b, 0.1f, 5.f, 4.9f); break;
case SURFACE_WOOD_PLANK: result = GetCollisionRatio(b, 0.1f, 40.f, 39.9f); break;
case SURFACE_TIRE:
case SURFACE_RUBBER29: result = GetCollisionRatio(b, 0.f, 10.f, 10.f); break;
case SURFACE_HARD24: result = GetCollisionRatio(b, 0.1f, 4.f, 3.9f); break;
case SURFACE_HEDGE: result = GetCollisionRatio(b, 0.f, 0.5f, 0.5f); break;
case SURFACE_METAL27: result = GetCollisionRatio(b, 4.f, 40.f, 36.f); break;
case SURFACE_METAL28: result = GetCollisionRatio(b, 0.f, 5.f, 5.f); break;
default: result = 0.f; break;
}
return result;
}
float
cAudioManager::GetCollisionRatio(float a, float b, float c, float d) const
{
float e;
e = a;
if(a <= b) return 0.0f;
if(c <= a) e = c;
return (e - b) / d;
}
uint32
cAudioManager::SetLoopingCollisionRequestedSfxFreqAndGetVol(cAudioCollision *audioCollision)
{
uint8 surface1 = audioCollision->m_bSurface1;
uint8 surface2 = audioCollision->m_bSurface2;
int32 vol;
float ratio;
if(surface1 == SURFACE_GRASS || surface2 == SURFACE_GRASS || surface1 == SURFACE_HEDGE ||
surface2 == SURFACE_HEDGE) {
ratio = GetCollisionRatio(audioCollision->m_fIntensity2, 0.0001f, 0.09f, 0.0899f);
m_sQueueSample.m_nSampleIndex = SFX_RAIN;
m_sQueueSample.m_nFrequency = 13000.f * ratio + 35000;
vol = 50.f * ratio;
} else {
if(surface1 == SURFACE_PUDDLE || surface2 == SURFACE_PUDDLE) {
ratio = GetCollisionRatio(audioCollision->m_fIntensity2, 0.0001f, 0.09f, 0.0899f);
m_sQueueSample.m_nSampleIndex = SFX_BOAT_WATER_LOOP;
m_sQueueSample.m_nFrequency = 6050.f * ratio + 16000;
vol = 30.f * ratio;
} else {
if(surface1 == SURFACE_DIRT || surface2 == SURFACE_DIRT || surface1 == SURFACE_DIRTTRACK ||
surface2 == SURFACE_DIRTTRACK || surface1 == SURFACE_SAND || surface2 == SURFACE_SAND) {
ratio = GetCollisionRatio(audioCollision->m_fIntensity2, 0.0001f, 0.09f, 0.0899f);
m_sQueueSample.m_nSampleIndex = SFX_GRAVEL_SKID;
m_sQueueSample.m_nFrequency = 6000.f * ratio + 10000;
vol = 50.f * ratio;
} else {
if(surface1 == SURFACE_FLESH || surface2 == SURFACE_FLESH) { return 0; }
ratio = GetCollisionRatio(audioCollision->m_fIntensity2, 0.0001f, 0.09f, 0.0899f);
m_sQueueSample.m_nSampleIndex = SFX_SCRAPE_CAR_1;
m_sQueueSample.m_nFrequency = 10000.f * ratio + 10000;
vol = 40.f * ratio;
}
}
}
if(audioCollision->m_nBaseVolume < 2) vol = audioCollision->m_nBaseVolume * vol / 2;
return vol;
}
void
cAudioManager::SetUpLoopingCollisionSound(cAudioCollision *col, uint8 counter)
{
if(col->m_fIntensity2 > 0.0016f) {
uint8 emittingVol = SetLoopingCollisionRequestedSfxFreqAndGetVol(col);
if(emittingVol) {
m_sQueueSample.m_fDistance = Sqrt(col->m_fDistance);
m_sQueueSample.m_bVolume =
ComputeVolume(emittingVol, CollisionSoundIntensity, m_sQueueSample.m_fDistance);
if(m_sQueueSample.m_bVolume) {
m_sQueueSample.m_counter = counter;
m_sQueueSample.m_vecPos = col->m_vecPosition;
m_sQueueSample.m_bBankIndex = SAMPLEBANK_MAIN;
m_sQueueSample.m_bIs2D = false;
m_sQueueSample.m_nReleasingVolumeModificator = 7;
m_sQueueSample.m_nLoopCount = 0;
m_sQueueSample.m_bEmittingVolume = emittingVol;
m_sQueueSample.m_nLoopStart =
SampleManager.GetSampleLoopStartOffset(m_sQueueSample.m_nSampleIndex);
m_sQueueSample.m_nLoopEnd =
SampleManager.GetSampleLoopEndOffset(m_sQueueSample.m_nSampleIndex);
m_sQueueSample.m_fSpeedMultiplier = 4.0f;
m_sQueueSample.m_fSoundIntensity = CollisionSoundIntensity;
m_sQueueSample.m_bReleasingSoundFlag = 0;
m_sQueueSample.m_nReleasingVolumeDivider = 5;
m_sQueueSample.m_bReverbFlag = true;
m_sQueueSample.m_bRequireReflection = false;
AddSampleToRequestedQueue();
}
}
}
}
void
cAudioManager::SetUpOneShotCollisionSound(cAudioCollision *col)
{
static const int32 gOneShotCol[] = {
SFX_COL_TARMAC_1, SFX_COL_TARMAC_1, SFX_COL_GRASS_1,
SFX_COL_GRAVEL_1, SFX_COL_MUD_1, SFX_COL_TARMAC_1,
SFX_COL_CAR_1, SFX_COL_GRASS_1, SFX_COL_SCAFFOLD_POLE_1,
SFX_COL_GARAGE_DOOR_1, SFX_COL_CAR_PANEL_1, SFX_COL_THICK_METAL_PLATE_1,
SFX_COL_SCAFFOLD_POLE_1, SFX_COL_LAMP_POST_1, SFX_COL_HYDRANT_1,
SFX_COL_HYDRANT_1, SFX_COL_METAL_CHAIN_FENCE_1, SFX_COL_PED_1,
SFX_COL_SAND_1, SFX_SPLASH_1, SFX_COL_WOOD_CRATES_1,
SFX_COL_WOOD_BENCH_1, SFX_COL_WOOD_SOLID_1, SFX_COL_GRASS_1,
SFX_COL_GRASS_1, SFX_COL_VEG_1, SFX_COL_TARMAC_1,
SFX_COL_CONTAINER_1, SFX_COL_NEWS_VENDOR_1, SFX_TYRE_BUMP,
SFX_COL_CARDBOARD_1, SFX_COL_TARMAC_1, SFX_COL_GATE};
int16 s1;
int16 s2;
int32 emittingVol;
float ratio;
static uint16 counter = 28;
for(int32 i = 0; i < 2; i++) {
if(i) {
s1 = col->m_bSurface2;
s2 = col->m_bSurface1;
} else {
s1 = col->m_bSurface1;
s2 = col->m_bSurface2;
}
ratio = GetCollisionOneShotRatio(s1, col->m_fIntensity1);
if(s1 == SURFACE_METAL6 && s2 == SURFACE_FLESH) ratio = 0.25f * ratio;
if(s1 == SURFACE_METAL6 && ratio < 0.6f) {
s1 = SURFACE_BILLBOARD;
ratio = min(1.f, 2.f * ratio);
}
emittingVol = 40.f * ratio;
if(emittingVol) {
m_sQueueSample.m_fDistance = Sqrt(col->m_fDistance);
m_sQueueSample.m_bVolume =
ComputeVolume(emittingVol, CollisionSoundIntensity, m_sQueueSample.m_fDistance);
if(m_sQueueSample.m_bVolume) {
m_sQueueSample.m_nSampleIndex = gOneShotCol[s1];
switch(m_sQueueSample.m_nSampleIndex) {
case SFX_COL_TARMAC_1:
m_sQueueSample.m_nSampleIndex += m_anRandomTable[3] % 5;
break;
case SFX_COL_CAR_PANEL_1:
m_sQueueSample.m_nSampleIndex += m_anRandomTable[0] % 6;
break;
case SFX_COL_LAMP_POST_1:
m_sQueueSample.m_nSampleIndex += m_anRandomTable[1] % 2;
break;
case SFX_COL_METAL_CHAIN_FENCE_1:
m_sQueueSample.m_nSampleIndex += m_anRandomTable[3] % 4;
break;
case SFX_COL_PED_1:
m_sQueueSample.m_nSampleIndex += m_anRandomTable[4] % 5;
break;
case SFX_COL_WOOD_CRATES_1:
m_sQueueSample.m_nSampleIndex += m_anRandomTable[4] % 4;
break;
case SFX_COL_WOOD_BENCH_1:
m_sQueueSample.m_nSampleIndex += m_anRandomTable[1] % 4;
break;
case SFX_COL_VEG_1:
m_sQueueSample.m_nSampleIndex += m_anRandomTable[2] % 5;
break;
case SFX_COL_NEWS_VENDOR_1:
m_sQueueSample.m_nSampleIndex += m_anRandomTable[2] % 3;
break;
case SFX_COL_CAR_1:
m_sQueueSample.m_nSampleIndex += m_anRandomTable[1] % 5;
break;
case SFX_COL_CARDBOARD_1:
m_sQueueSample.m_nSampleIndex += m_anRandomTable[3] % 2;
break;
default: break;
}
switch(s1) {
case SURFACE_GLASS: m_sQueueSample.m_nFrequency = 13500; break;
case SURFACE_METAL15: m_sQueueSample.m_nFrequency = 8819; break;
case SURFACE_PUDDLE:
m_sQueueSample.m_nFrequency =
2 * SampleManager.GetSampleBaseFrequency(m_sQueueSample.m_nSampleIndex);
break;
case SURFACE_TIRE: m_sQueueSample.m_nFrequency = 6000; break;
case SURFACE_HARD24: m_sQueueSample.m_nFrequency = 8000; break;
default:
m_sQueueSample.m_nFrequency =
SampleManager.GetSampleBaseFrequency(m_sQueueSample.m_nSampleIndex);
break;
}
m_sQueueSample.m_nFrequency += RandomDisplacement(m_sQueueSample.m_nFrequency / 16);
m_sQueueSample.m_counter = counter++;
if(counter >= 255) counter = 28;
m_sQueueSample.m_vecPos = col->m_vecPosition;
m_sQueueSample.m_bBankIndex = SAMPLEBANK_MAIN;
m_sQueueSample.m_bIs2D = false;
m_sQueueSample.m_nReleasingVolumeModificator = 11;
m_sQueueSample.m_nLoopCount = 1;
m_sQueueSample.m_bEmittingVolume = emittingVol;
m_sQueueSample.m_nLoopStart = 0;
m_sQueueSample.m_nLoopEnd = -1;
m_sQueueSample.m_fSpeedMultiplier = 4.0f;
m_sQueueSample.m_fSoundIntensity = CollisionSoundIntensity;
m_sQueueSample.m_bReleasingSoundFlag = 1;
m_sQueueSample.m_bReverbFlag = true;
m_sQueueSample.m_bRequireReflection = false;
AddSampleToRequestedQueue();
}
}
}
}
void
cAudioManager::ServiceCollisions()
{
int i, j;
bool someArr1[NUMAUDIOCOLLISIONS];
bool someArr2[NUMAUDIOCOLLISIONS];
m_sQueueSample.m_nEntityIndex = m_nCollisionEntity;
for (int i = 0; i < NUMAUDIOCOLLISIONS; i++)
someArr1[i] = someArr2[i] = false;
for (i = 0; i < m_sCollisionManager.m_bCollisionsInQueue; i++) {
for (j = 0; j < NUMAUDIOCOLLISIONS; j++) {
int index = m_sCollisionManager.m_bIndicesTable[i];
if ((m_sCollisionManager.m_asCollisions1[index].m_pEntity1 == m_sCollisionManager.m_asCollisions2[j].m_pEntity1)
&& (m_sCollisionManager.m_asCollisions1[index].m_pEntity2 == m_sCollisionManager.m_asCollisions2[j].m_pEntity2)
&& (m_sCollisionManager.m_asCollisions1[index].m_bSurface1 == m_sCollisionManager.m_asCollisions2[j].m_bSurface1)
&& (m_sCollisionManager.m_asCollisions1[index].m_bSurface2 == m_sCollisionManager.m_asCollisions2[j].m_bSurface2)
) {
someArr1[index] = true;
someArr2[j] = true;
m_sCollisionManager.m_asCollisions1[index].m_nBaseVolume = ++m_sCollisionManager.m_asCollisions2[j].m_nBaseVolume;
SetUpLoopingCollisionSound(&m_sCollisionManager.m_asCollisions1[index], j);
break;
}
}
}
for (i = 0; i < NUMAUDIOCOLLISIONS; i++) {
if (!someArr2[i]) {
m_sCollisionManager.m_asCollisions2[i].m_pEntity1 = nil;
m_sCollisionManager.m_asCollisions2[i].m_pEntity2 = nil;
m_sCollisionManager.m_asCollisions2[i].m_bSurface1 = SURFACE_DEFAULT;
m_sCollisionManager.m_asCollisions2[i].m_bSurface2 = SURFACE_DEFAULT;
m_sCollisionManager.m_asCollisions2[i].m_fIntensity2 = 0.0f;
m_sCollisionManager.m_asCollisions2[i].m_fIntensity1 = 0.0f;
m_sCollisionManager.m_asCollisions2[i].m_vecPosition = CVector(0.0f, 0.0f, 0.0f);
m_sCollisionManager.m_asCollisions2[i].m_fDistance = 0.0f;
}
}
for (i = 0; i < m_sCollisionManager.m_bCollisionsInQueue; i++) {
int index = m_sCollisionManager.m_bIndicesTable[i];
if (!someArr1[index]) {
for (j = 0; j < NUMAUDIOCOLLISIONS; j++) {
if (someArr2[j]) {
m_sCollisionManager.m_asCollisions2[j].m_nBaseVolume = 1;
m_sCollisionManager.m_asCollisions2[j].m_pEntity1 = m_sCollisionManager.m_asCollisions1[index].m_pEntity1;
m_sCollisionManager.m_asCollisions2[j].m_pEntity2 = m_sCollisionManager.m_asCollisions1[index].m_pEntity2;
m_sCollisionManager.m_asCollisions2[j].m_bSurface1 = m_sCollisionManager.m_asCollisions1[index].m_bSurface1;
m_sCollisionManager.m_asCollisions2[j].m_bSurface2 = m_sCollisionManager.m_asCollisions1[index].m_bSurface2;
break;
}
}
SetUpOneShotCollisionSound(&m_sCollisionManager.m_asCollisions1[index]);
SetUpLoopingCollisionSound(&m_sCollisionManager.m_asCollisions1[index], j);
}
}
for (int i = 0; i < NUMAUDIOCOLLISIONS; i++)
m_sCollisionManager.m_bIndicesTable[i] = NUMAUDIOCOLLISIONS;
m_sCollisionManager.m_bCollisionsInQueue = 0;
}
void
cAudioManager::ReportCollision(CEntity *entity1, CEntity *entity2, uint8 surface1, uint8 surface2, float collisionPower,
float velocity)
{
float distSquared;
CVector v1;
CVector v2;
if(!m_bIsInitialised || m_nCollisionEntity < 0 || m_bUserPause ||
(velocity < 0.0016f && collisionPower < 0.01f))
return;
if(entity1->IsBuilding()) {
v1 = v2 = entity2->GetPosition();
} else if(entity2->IsBuilding()) {
v1 = v2 = entity1->GetPosition();
} else {
v1 = entity1->GetPosition();
v2 = entity2->GetPosition();
}
CVector pos = (v1 + v2) * 0.5f;
distSquared = GetDistanceSquared(&pos);
if(distSquared < SQR(CollisionSoundIntensity)) {
m_sCollisionManager.m_sQueue.m_pEntity1 = entity1;
m_sCollisionManager.m_sQueue.m_pEntity2 = entity2;
m_sCollisionManager.m_sQueue.m_bSurface1 = surface1;
m_sCollisionManager.m_sQueue.m_bSurface2 = surface2;
m_sCollisionManager.m_sQueue.m_fIntensity1 = collisionPower;
m_sCollisionManager.m_sQueue.m_fIntensity2 = velocity;
m_sCollisionManager.m_sQueue.m_vecPosition = pos;
m_sCollisionManager.m_sQueue.m_fDistance = distSquared;
m_sCollisionManager.AddCollisionToRequestedQueue();
}
}
STARTPATCHES
InjectHook(0x5685E0, &cAudioCollisionManager::AddCollisionToRequestedQueue, PATCH_JUMP);
InjectHook(0x569060, &cAudioManager::GetCollisionOneShotRatio, PATCH_JUMP);
InjectHook(0x5693B0, &cAudioManager::GetCollisionRatio, PATCH_JUMP);
InjectHook(0x568410, &cAudioManager::ReportCollision, PATCH_JUMP);
InjectHook(0x5686D0, &cAudioManager::ServiceCollisions, PATCH_JUMP);
InjectHook(0x568E20, &cAudioManager::SetLoopingCollisionRequestedSfxFreqAndGetVol, PATCH_JUMP);
InjectHook(0x568D30, &cAudioManager::SetUpLoopingCollisionSound, PATCH_JUMP);
InjectHook(0x5689D0, &cAudioManager::SetUpOneShotCollisionSound, PATCH_JUMP);
ENDPATCHES

View File

@ -1,36 +1,36 @@
#pragma once
#define NUMAUDIOCOLLISIONS 10
class cAudioCollision
{
public:
CEntity *m_pEntity1;
CEntity *m_pEntity2;
uint8 m_bSurface1;
uint8 m_bSurface2;
float m_fIntensity1;
float m_fIntensity2;
CVector m_vecPosition;
float m_fDistance;
int32 m_nBaseVolume;
// no methods
};
static_assert(sizeof(cAudioCollision) == 40, "cAudioCollision: error");
class cAudioCollisionManager
{
public:
cAudioCollision m_asCollisions1[NUMAUDIOCOLLISIONS];
cAudioCollision m_asCollisions2[NUMAUDIOCOLLISIONS];
uint8 m_bIndicesTable[NUMAUDIOCOLLISIONS];
uint8 m_bCollisionsInQueue;
cAudioCollision m_sQueue;
// reversed all methods
void AddCollisionToRequestedQueue(); /// ok
};
#pragma once
#define NUMAUDIOCOLLISIONS 10
class cAudioCollision
{
public:
CEntity *m_pEntity1;
CEntity *m_pEntity2;
uint8 m_bSurface1;
uint8 m_bSurface2;
float m_fIntensity1;
float m_fIntensity2;
CVector m_vecPosition;
float m_fDistance;
int32 m_nBaseVolume;
// no methods
};
static_assert(sizeof(cAudioCollision) == 40, "cAudioCollision: error");
class cAudioCollisionManager
{
public:
cAudioCollision m_asCollisions1[NUMAUDIOCOLLISIONS];
cAudioCollision m_asCollisions2[NUMAUDIOCOLLISIONS];
uint8 m_bIndicesTable[NUMAUDIOCOLLISIONS];
uint8 m_bCollisionsInQueue;
cAudioCollision m_sQueue;
// reversed all methods
void AddCollisionToRequestedQueue(); /// ok
};
static_assert(sizeof(cAudioCollisionManager) == 852, "cAudioCollisionManager: error");

View File

@ -1,4 +1,4 @@
#pragma once
#pragma once
#include "DMAudio.h"
#include "common.h"

File diff suppressed because it is too large Load Diff

View File

@ -1,46 +1,46 @@
#pragma once
#include "Wanted.h"
struct cAMCrime {
int32 type;
CVector position;
uint16 timer;
cAMCrime()
{
type = CRIME_NONE;
position = CVector(0.0f, 0.0f, 0.0f);
timer = 0;
}
};
static_assert(sizeof(cAMCrime) == 20, "cAMCrime: error ");
class cPoliceRadioQueue
{
public:
int32 crimesSamples[60];
uint8 policeChannelTimer;
uint8 policeChannelTimerSeconds;
uint8 policeChannelCounterSeconds;
cAMCrime crimes[10];
cPoliceRadioQueue()
{
policeChannelTimerSeconds = 0;
policeChannelCounterSeconds = 0;
policeChannelTimer = 0;
}
void Add(uint32 sample)
{
if (policeChannelTimer != 60) {
crimesSamples[policeChannelTimerSeconds] = sample;
policeChannelTimer++;
policeChannelTimerSeconds = (policeChannelTimerSeconds + 1) % 60;
}
}
};
#pragma once
#include "Wanted.h"
struct cAMCrime {
int32 type;
CVector position;
uint16 timer;
cAMCrime()
{
type = CRIME_NONE;
position = CVector(0.0f, 0.0f, 0.0f);
timer = 0;
}
};
static_assert(sizeof(cAMCrime) == 20, "cAMCrime: error ");
class cPoliceRadioQueue
{
public:
int32 crimesSamples[60];
uint8 policeChannelTimer;
uint8 policeChannelTimerSeconds;
uint8 policeChannelCounterSeconds;
cAMCrime crimes[10];
cPoliceRadioQueue()
{
policeChannelTimerSeconds = 0;
policeChannelCounterSeconds = 0;
policeChannelTimer = 0;
}
void Add(uint32 sample)
{
if (policeChannelTimer != 60) {
crimesSamples[policeChannelTimerSeconds] = sample;
policeChannelTimer++;
policeChannelTimerSeconds = (policeChannelTimerSeconds + 1) % 60;
}
}
};
static_assert(sizeof(cPoliceRadioQueue) == 444, "cPoliceRadioQueue: error ");

View File

@ -1,294 +1,294 @@
#include "common.h"
#include "patcher.h"
#include "GameLogic.h"
#include "Clock.h"
#include "Stats.h"
#include "Pickups.h"
#include "Timer.h"
#include "Streaming.h"
#include "CutsceneMgr.h"
#include "World.h"
#include "PlayerPed.h"
#include "Wanted.h"
#include "Camera.h"
#include "Messages.h"
#include "CarCtrl.h"
#include "Restart.h"
#include "Pad.h"
#include "References.h"
#include "Fire.h"
#include "Script.h"
#include "Garages.h"
uint8 CGameLogic::ActivePlayers; // 0x95CD5E
void
CGameLogic::InitAtStartOfGame()
{
ActivePlayers = 1;
}
void
CGameLogic::PassTime(uint32 time)
{
int32 minutes, hours, days;
minutes = time + CClock::GetMinutes();
hours = CClock::GetHours();
for (; minutes >= 60; minutes -= 60)
hours++;
if (hours > 23) {
days = CStats::DaysPassed;
for (; hours >= 24; hours -= 24)
days++;
CStats::DaysPassed = days;
}
CClock::SetGameClock(hours, minutes);
CPickups::PassTime(time * 1000);
}
void
CGameLogic::SortOutStreamingAndMemory(const CVector &pos)
{
CTimer::Stop();
CStreaming::FlushRequestList();
CStreaming::DeleteRwObjectsAfterDeath(pos);
CStreaming::RemoveUnusedModelsInLoadedList();
CGame::DrasticTidyUpMemory(true);
CStreaming::LoadScene(pos);
CTimer::Update();
}
void
CGameLogic::Update()
{
CVector vecRestartPos;
float fRestartFloat;
if (CCutsceneMgr::IsCutsceneProcessing()) return;
CPlayerInfo &pPlayerInfo = CWorld::Players[CWorld::PlayerInFocus];
switch (pPlayerInfo.m_WBState) {
case WBSTATE_PLAYING:
if (pPlayerInfo.m_pPed->m_nPedState == PED_DEAD) {
pPlayerInfo.m_pPed->ClearAdrenaline();
pPlayerInfo.KillPlayer();
}
if (pPlayerInfo.m_pPed->m_nPedState == PED_ARRESTED) {
pPlayerInfo.m_pPed->ClearAdrenaline();
pPlayerInfo.ArrestPlayer();
}
break;
case WBSTATE_WASTED:
if ((CTimer::GetTimeInMilliseconds() - pPlayerInfo.m_nWBTime > 0x800) && (CTimer::GetPreviousTimeInMilliseconds() - pPlayerInfo.m_nWBTime <= 0x800)) {
TheCamera.SetFadeColour(200, 200, 200);
TheCamera.Fade(2.0f, FADE_OUT);
}
if (CTimer::GetTimeInMilliseconds() - pPlayerInfo.m_nWBTime >= 0x1000) {
pPlayerInfo.m_WBState = WBSTATE_PLAYING;
if (pPlayerInfo.m_bGetOutOfHospitalFree) {
pPlayerInfo.m_bGetOutOfHospitalFree = false;
} else {
pPlayerInfo.m_nMoney = max(0, pPlayerInfo.m_nMoney - 1000);
pPlayerInfo.m_pPed->ClearWeapons();
}
if (pPlayerInfo.m_pPed->bInVehicle) {
CVehicle *pVehicle = pPlayerInfo.m_pPed->m_pMyVehicle;
if (pVehicle != nil) {
if (pVehicle->pDriver == pPlayerInfo.m_pPed) {
pVehicle->pDriver = nil;
if (pVehicle->m_status != STATUS_WRECKED)
pVehicle->m_status = STATUS_ABANDONED;
} else
pVehicle->RemovePassenger(pPlayerInfo.m_pPed);
}
}
CEventList::Initialise();
CMessages::ClearMessages();
CCarCtrl::ClearInterestingVehicleList();
CWorld::ClearExcitingStuffFromArea(pPlayerInfo.GetPos(), 4000.0f, 1);
CRestart::FindClosestHospitalRestartPoint(pPlayerInfo.GetPos(), &vecRestartPos, &fRestartFloat);
CRestart::OverrideHospitalLevel = LEVEL_NONE;
CRestart::OverridePoliceStationLevel = LEVEL_NONE;
PassTime(720);
RestorePlayerStuffDuringResurrection(pPlayerInfo.m_pPed, vecRestartPos, fRestartFloat);
SortOutStreamingAndMemory(pPlayerInfo.GetPos());
TheCamera.m_fCamShakeForce = 0.0f;
TheCamera.SetMotionBlur(0, 0, 0, 0, MBLUR_NONE);
CPad::GetPad(0)->StopShaking(0);
CReferences::RemoveReferencesToPlayer();
CCarCtrl::CountDownToCarsAtStart = 2;
CPad::GetPad(CWorld::PlayerInFocus)->DisablePlayerControls = PLAYERCONTROL_ENABLED;
if (CRestart::bFadeInAfterNextDeath) {
TheCamera.SetFadeColour(200, 200, 200);
TheCamera.Fade(4.0f, FADE_IN);
} else CRestart::bFadeInAfterNextDeath = true;
}
break;
case WBSTATE_BUSTED:
if ((CTimer::GetTimeInMilliseconds() - pPlayerInfo.m_nWBTime > 0x800) && (CTimer::GetPreviousTimeInMilliseconds() - pPlayerInfo.m_nWBTime <= 0x800)) {
TheCamera.SetFadeColour(0, 0, 0);
TheCamera.Fade(2.0f, FADE_OUT);
}
if (CTimer::GetTimeInMilliseconds() - pPlayerInfo.m_nWBTime >= 0x1000) {
pPlayerInfo.m_WBState = WBSTATE_PLAYING;
int takeMoney;
switch (pPlayerInfo.m_pPed->m_pWanted->m_nWantedLevel) {
case 0:
case 1:
takeMoney = 100;
break;
case 2:
takeMoney = 200;
break;
case 3:
takeMoney = 400;
break;
case 4:
takeMoney = 600;
break;
case 5:
takeMoney = 900;
break;
case 6:
takeMoney = 1500;
break;
}
if (pPlayerInfo.m_bGetOutOfJailFree) {
pPlayerInfo.m_bGetOutOfJailFree = false;
} else {
pPlayerInfo.m_nMoney = max(0, pPlayerInfo.m_nMoney - takeMoney);
pPlayerInfo.m_pPed->ClearWeapons();
}
if (pPlayerInfo.m_pPed->bInVehicle) {
CVehicle *pVehicle = pPlayerInfo.m_pPed->m_pMyVehicle;
if (pVehicle != nil) {
if (pVehicle->pDriver == pPlayerInfo.m_pPed) {
pVehicle->pDriver = nil;
if (pVehicle->m_status != STATUS_WRECKED)
pVehicle->m_status = STATUS_ABANDONED;
}
else
pVehicle->RemovePassenger(pPlayerInfo.m_pPed);
}
}
CEventList::Initialise();
CMessages::ClearMessages();
CCarCtrl::ClearInterestingVehicleList();
CWorld::ClearExcitingStuffFromArea(pPlayerInfo.GetPos(), 4000.0f, 1);
CRestart::FindClosestPoliceRestartPoint(pPlayerInfo.GetPos(), &vecRestartPos, &fRestartFloat);
CRestart::OverrideHospitalLevel = LEVEL_NONE;
CRestart::OverridePoliceStationLevel = LEVEL_NONE;
PassTime(720);
RestorePlayerStuffDuringResurrection(pPlayerInfo.m_pPed, vecRestartPos, fRestartFloat);
pPlayerInfo.m_pPed->ClearWeapons();
SortOutStreamingAndMemory(pPlayerInfo.GetPos());
TheCamera.m_fCamShakeForce = 0.0f;
TheCamera.SetMotionBlur(0, 0, 0, 0, MBLUR_NONE);
CPad::GetPad(0)->StopShaking(0);
CReferences::RemoveReferencesToPlayer();
CCarCtrl::CountDownToCarsAtStart = 2;
CPad::GetPad(CWorld::PlayerInFocus)->DisablePlayerControls = PLAYERCONTROL_ENABLED;
if (CRestart::bFadeInAfterNextArrest) {
TheCamera.SetFadeColour(0, 0, 0);
TheCamera.Fade(4.0f, FADE_IN);
} else CRestart::bFadeInAfterNextArrest = true;
}
break;
case WBSTATE_FAILED_CRITICAL_MISSION:
if (CTimer::GetTimeInMilliseconds() - pPlayerInfo.m_nWBTime > 0x800 && CTimer::GetPreviousTimeInMilliseconds() - pPlayerInfo.m_nWBTime <= 0x800) {
TheCamera.SetFadeColour(0, 0, 0);
TheCamera.Fade(2.0f, FADE_OUT);
}
if (CTimer::GetTimeInMilliseconds() - pPlayerInfo.m_nWBTime >= 0x1000) {
pPlayerInfo.m_WBState = WBSTATE_PLAYING;
if (pPlayerInfo.m_pPed->bInVehicle) {
CVehicle *pVehicle = pPlayerInfo.m_pPed->m_pMyVehicle;
if (pVehicle != nil) {
if (pVehicle->pDriver == pPlayerInfo.m_pPed) {
pVehicle->pDriver = nil;
if (pVehicle->m_status != STATUS_WRECKED)
pVehicle->m_status = STATUS_ABANDONED;
} else
pVehicle->RemovePassenger(pPlayerInfo.m_pPed);
}
}
CEventList::Initialise();
CMessages::ClearMessages();
CCarCtrl::ClearInterestingVehicleList();
CWorld::ClearExcitingStuffFromArea(pPlayerInfo.GetPos(), 4000.0f, 1);
CRestart::FindClosestPoliceRestartPoint(pPlayerInfo.GetPos(), &vecRestartPos, &fRestartFloat);
CRestart::OverridePoliceStationLevel = LEVEL_NONE;
CRestart::OverrideHospitalLevel = LEVEL_NONE;
RestorePlayerStuffDuringResurrection(pPlayerInfo.m_pPed, vecRestartPos, fRestartFloat);
SortOutStreamingAndMemory(pPlayerInfo.GetPos());
TheCamera.m_fCamShakeForce = 0.0f;
TheCamera.SetMotionBlur(0, 0, 0, 0, MBLUR_NONE);
CPad::GetPad(0)->StopShaking(0);
CReferences::RemoveReferencesToPlayer();
CCarCtrl::CountDownToCarsAtStart = 2;
CPad::GetPad(CWorld::PlayerInFocus)->DisablePlayerControls = PLAYERCONTROL_ENABLED;
TheCamera.SetFadeColour(0, 0, 0);
TheCamera.Fade(4.0f, FADE_IN);
}
break;
case 4:
return;
}
}
void
CGameLogic::RestorePlayerStuffDuringResurrection(CPlayerPed *pPlayerPed, CVector pos, float angle)
{
pPlayerPed->m_fHealth = 100.0f;
pPlayerPed->m_fArmour = 0.0f;
pPlayerPed->bIsVisible = true;
pPlayerPed->m_bloodyFootprintCountOrDeathTime = 0;
pPlayerPed->bDoBloodyFootprints = false;
pPlayerPed->ClearAdrenaline();
pPlayerPed->m_fCurrentStamina = pPlayerPed->m_fMaxStamina;
if (pPlayerPed->m_pFire)
pPlayerPed->m_pFire->Extinguish();
pPlayerPed->bInVehicle = false;
pPlayerPed->m_pMyVehicle = nil;
pPlayerPed->m_pVehicleAnim = nil;
pPlayerPed->m_pWanted->Reset();
pPlayerPed->RestartNonPartialAnims();
pPlayerPed->GetPlayerInfoForThisPlayerPed()->MakePlayerSafe(false);
pPlayerPed->bRemoveFromWorld = false;
pPlayerPed->ClearWeaponTarget();
pPlayerPed->SetInitialState();
CCarCtrl::ClearInterestingVehicleList();
pos.z += 1.0f;
pPlayerPed->Teleport(pos);
pPlayerPed->SetMoveSpeed(CVector(0.0f, 0.0f, 0.0f));
pPlayerPed->m_fRotationCur = DEGTORAD(angle);
pPlayerPed->m_fRotationDest = pPlayerPed->m_fRotationCur;
pPlayerPed->SetHeading(pPlayerPed->m_fRotationCur);
CTheScripts::ClearSpaceForMissionEntity(pos, pPlayerPed);
CWorld::ClearExcitingStuffFromArea(pos, 4000.0, 1);
pPlayerPed->RestoreHeadingRate();
TheCamera.SetCameraDirectlyInFrontForFollowPed_CamOnAString();
CReferences::RemoveReferencesToPlayer();
CGarages::PlayerArrestedOrDied();
CStats::CheckPointReachedUnsuccessfully();
CWorld::Remove(pPlayerPed);
CWorld::Add(pPlayerPed);
}
#include "GameLogic.h"
#include "Clock.h"
#include "Stats.h"
#include "Pickups.h"
#include "Timer.h"
#include "Streaming.h"
#include "CutsceneMgr.h"
#include "World.h"
#include "PlayerPed.h"
#include "Wanted.h"
#include "Camera.h"
#include "Messages.h"
#include "CarCtrl.h"
#include "Restart.h"
#include "Pad.h"
#include "References.h"
#include "Fire.h"
#include "Script.h"
#include "Garages.h"
uint8 CGameLogic::ActivePlayers; // 0x95CD5E
void
CGameLogic::InitAtStartOfGame()
{
ActivePlayers = 1;
}
void
CGameLogic::PassTime(uint32 time)
{
int32 minutes, hours, days;
minutes = time + CClock::GetMinutes();
hours = CClock::GetHours();
for (; minutes >= 60; minutes -= 60)
hours++;
if (hours > 23) {
days = CStats::DaysPassed;
for (; hours >= 24; hours -= 24)
days++;
CStats::DaysPassed = days;
}
CClock::SetGameClock(hours, minutes);
CPickups::PassTime(time * 1000);
}
void
CGameLogic::SortOutStreamingAndMemory(const CVector &pos)
{
CTimer::Stop();
CStreaming::FlushRequestList();
CStreaming::DeleteRwObjectsAfterDeath(pos);
CStreaming::RemoveUnusedModelsInLoadedList();
CGame::DrasticTidyUpMemory(true);
CStreaming::LoadScene(pos);
CTimer::Update();
}
void
CGameLogic::Update()
{
CVector vecRestartPos;
float fRestartFloat;
if (CCutsceneMgr::IsCutsceneProcessing()) return;
CPlayerInfo &pPlayerInfo = CWorld::Players[CWorld::PlayerInFocus];
switch (pPlayerInfo.m_WBState) {
case WBSTATE_PLAYING:
if (pPlayerInfo.m_pPed->m_nPedState == PED_DEAD) {
pPlayerInfo.m_pPed->ClearAdrenaline();
pPlayerInfo.KillPlayer();
}
if (pPlayerInfo.m_pPed->m_nPedState == PED_ARRESTED) {
pPlayerInfo.m_pPed->ClearAdrenaline();
pPlayerInfo.ArrestPlayer();
}
break;
case WBSTATE_WASTED:
if ((CTimer::GetTimeInMilliseconds() - pPlayerInfo.m_nWBTime > 0x800) && (CTimer::GetPreviousTimeInMilliseconds() - pPlayerInfo.m_nWBTime <= 0x800)) {
TheCamera.SetFadeColour(200, 200, 200);
TheCamera.Fade(2.0f, FADE_OUT);
}
if (CTimer::GetTimeInMilliseconds() - pPlayerInfo.m_nWBTime >= 0x1000) {
pPlayerInfo.m_WBState = WBSTATE_PLAYING;
if (pPlayerInfo.m_bGetOutOfHospitalFree) {
pPlayerInfo.m_bGetOutOfHospitalFree = false;
} else {
pPlayerInfo.m_nMoney = max(0, pPlayerInfo.m_nMoney - 1000);
pPlayerInfo.m_pPed->ClearWeapons();
}
if (pPlayerInfo.m_pPed->bInVehicle) {
CVehicle *pVehicle = pPlayerInfo.m_pPed->m_pMyVehicle;
if (pVehicle != nil) {
if (pVehicle->pDriver == pPlayerInfo.m_pPed) {
pVehicle->pDriver = nil;
if (pVehicle->m_status != STATUS_WRECKED)
pVehicle->m_status = STATUS_ABANDONED;
} else
pVehicle->RemovePassenger(pPlayerInfo.m_pPed);
}
}
CEventList::Initialise();
CMessages::ClearMessages();
CCarCtrl::ClearInterestingVehicleList();
CWorld::ClearExcitingStuffFromArea(pPlayerInfo.GetPos(), 4000.0f, 1);
CRestart::FindClosestHospitalRestartPoint(pPlayerInfo.GetPos(), &vecRestartPos, &fRestartFloat);
CRestart::OverrideHospitalLevel = LEVEL_NONE;
CRestart::OverridePoliceStationLevel = LEVEL_NONE;
PassTime(720);
RestorePlayerStuffDuringResurrection(pPlayerInfo.m_pPed, vecRestartPos, fRestartFloat);
SortOutStreamingAndMemory(pPlayerInfo.GetPos());
TheCamera.m_fCamShakeForce = 0.0f;
TheCamera.SetMotionBlur(0, 0, 0, 0, MBLUR_NONE);
CPad::GetPad(0)->StopShaking(0);
CReferences::RemoveReferencesToPlayer();
CCarCtrl::CountDownToCarsAtStart = 2;
CPad::GetPad(CWorld::PlayerInFocus)->DisablePlayerControls = PLAYERCONTROL_ENABLED;
if (CRestart::bFadeInAfterNextDeath) {
TheCamera.SetFadeColour(200, 200, 200);
TheCamera.Fade(4.0f, FADE_IN);
} else CRestart::bFadeInAfterNextDeath = true;
}
break;
case WBSTATE_BUSTED:
if ((CTimer::GetTimeInMilliseconds() - pPlayerInfo.m_nWBTime > 0x800) && (CTimer::GetPreviousTimeInMilliseconds() - pPlayerInfo.m_nWBTime <= 0x800)) {
TheCamera.SetFadeColour(0, 0, 0);
TheCamera.Fade(2.0f, FADE_OUT);
}
if (CTimer::GetTimeInMilliseconds() - pPlayerInfo.m_nWBTime >= 0x1000) {
pPlayerInfo.m_WBState = WBSTATE_PLAYING;
int takeMoney;
switch (pPlayerInfo.m_pPed->m_pWanted->m_nWantedLevel) {
case 0:
case 1:
takeMoney = 100;
break;
case 2:
takeMoney = 200;
break;
case 3:
takeMoney = 400;
break;
case 4:
takeMoney = 600;
break;
case 5:
takeMoney = 900;
break;
case 6:
takeMoney = 1500;
break;
}
if (pPlayerInfo.m_bGetOutOfJailFree) {
pPlayerInfo.m_bGetOutOfJailFree = false;
} else {
pPlayerInfo.m_nMoney = max(0, pPlayerInfo.m_nMoney - takeMoney);
pPlayerInfo.m_pPed->ClearWeapons();
}
if (pPlayerInfo.m_pPed->bInVehicle) {
CVehicle *pVehicle = pPlayerInfo.m_pPed->m_pMyVehicle;
if (pVehicle != nil) {
if (pVehicle->pDriver == pPlayerInfo.m_pPed) {
pVehicle->pDriver = nil;
if (pVehicle->m_status != STATUS_WRECKED)
pVehicle->m_status = STATUS_ABANDONED;
}
else
pVehicle->RemovePassenger(pPlayerInfo.m_pPed);
}
}
CEventList::Initialise();
CMessages::ClearMessages();
CCarCtrl::ClearInterestingVehicleList();
CWorld::ClearExcitingStuffFromArea(pPlayerInfo.GetPos(), 4000.0f, 1);
CRestart::FindClosestPoliceRestartPoint(pPlayerInfo.GetPos(), &vecRestartPos, &fRestartFloat);
CRestart::OverrideHospitalLevel = LEVEL_NONE;
CRestart::OverridePoliceStationLevel = LEVEL_NONE;
PassTime(720);
RestorePlayerStuffDuringResurrection(pPlayerInfo.m_pPed, vecRestartPos, fRestartFloat);
pPlayerInfo.m_pPed->ClearWeapons();
SortOutStreamingAndMemory(pPlayerInfo.GetPos());
TheCamera.m_fCamShakeForce = 0.0f;
TheCamera.SetMotionBlur(0, 0, 0, 0, MBLUR_NONE);
CPad::GetPad(0)->StopShaking(0);
CReferences::RemoveReferencesToPlayer();
CCarCtrl::CountDownToCarsAtStart = 2;
CPad::GetPad(CWorld::PlayerInFocus)->DisablePlayerControls = PLAYERCONTROL_ENABLED;
if (CRestart::bFadeInAfterNextArrest) {
TheCamera.SetFadeColour(0, 0, 0);
TheCamera.Fade(4.0f, FADE_IN);
} else CRestart::bFadeInAfterNextArrest = true;
}
break;
case WBSTATE_FAILED_CRITICAL_MISSION:
if (CTimer::GetTimeInMilliseconds() - pPlayerInfo.m_nWBTime > 0x800 && CTimer::GetPreviousTimeInMilliseconds() - pPlayerInfo.m_nWBTime <= 0x800) {
TheCamera.SetFadeColour(0, 0, 0);
TheCamera.Fade(2.0f, FADE_OUT);
}
if (CTimer::GetTimeInMilliseconds() - pPlayerInfo.m_nWBTime >= 0x1000) {
pPlayerInfo.m_WBState = WBSTATE_PLAYING;
if (pPlayerInfo.m_pPed->bInVehicle) {
CVehicle *pVehicle = pPlayerInfo.m_pPed->m_pMyVehicle;
if (pVehicle != nil) {
if (pVehicle->pDriver == pPlayerInfo.m_pPed) {
pVehicle->pDriver = nil;
if (pVehicle->m_status != STATUS_WRECKED)
pVehicle->m_status = STATUS_ABANDONED;
} else
pVehicle->RemovePassenger(pPlayerInfo.m_pPed);
}
}
CEventList::Initialise();
CMessages::ClearMessages();
CCarCtrl::ClearInterestingVehicleList();
CWorld::ClearExcitingStuffFromArea(pPlayerInfo.GetPos(), 4000.0f, 1);
CRestart::FindClosestPoliceRestartPoint(pPlayerInfo.GetPos(), &vecRestartPos, &fRestartFloat);
CRestart::OverridePoliceStationLevel = LEVEL_NONE;
CRestart::OverrideHospitalLevel = LEVEL_NONE;
RestorePlayerStuffDuringResurrection(pPlayerInfo.m_pPed, vecRestartPos, fRestartFloat);
SortOutStreamingAndMemory(pPlayerInfo.GetPos());
TheCamera.m_fCamShakeForce = 0.0f;
TheCamera.SetMotionBlur(0, 0, 0, 0, MBLUR_NONE);
CPad::GetPad(0)->StopShaking(0);
CReferences::RemoveReferencesToPlayer();
CCarCtrl::CountDownToCarsAtStart = 2;
CPad::GetPad(CWorld::PlayerInFocus)->DisablePlayerControls = PLAYERCONTROL_ENABLED;
TheCamera.SetFadeColour(0, 0, 0);
TheCamera.Fade(4.0f, FADE_IN);
}
break;
case 4:
return;
}
}
void
CGameLogic::RestorePlayerStuffDuringResurrection(CPlayerPed *pPlayerPed, CVector pos, float angle)
{
pPlayerPed->m_fHealth = 100.0f;
pPlayerPed->m_fArmour = 0.0f;
pPlayerPed->bIsVisible = true;
pPlayerPed->m_bloodyFootprintCountOrDeathTime = 0;
pPlayerPed->bDoBloodyFootprints = false;
pPlayerPed->ClearAdrenaline();
pPlayerPed->m_fCurrentStamina = pPlayerPed->m_fMaxStamina;
if (pPlayerPed->m_pFire)
pPlayerPed->m_pFire->Extinguish();
pPlayerPed->bInVehicle = false;
pPlayerPed->m_pMyVehicle = nil;
pPlayerPed->m_pVehicleAnim = nil;
pPlayerPed->m_pWanted->Reset();
pPlayerPed->RestartNonPartialAnims();
pPlayerPed->GetPlayerInfoForThisPlayerPed()->MakePlayerSafe(false);
pPlayerPed->bRemoveFromWorld = false;
pPlayerPed->ClearWeaponTarget();
pPlayerPed->SetInitialState();
CCarCtrl::ClearInterestingVehicleList();
pos.z += 1.0f;
pPlayerPed->Teleport(pos);
pPlayerPed->SetMoveSpeed(CVector(0.0f, 0.0f, 0.0f));
pPlayerPed->m_fRotationCur = DEGTORAD(angle);
pPlayerPed->m_fRotationDest = pPlayerPed->m_fRotationCur;
pPlayerPed->SetHeading(pPlayerPed->m_fRotationCur);
CTheScripts::ClearSpaceForMissionEntity(pos, pPlayerPed);
CWorld::ClearExcitingStuffFromArea(pos, 4000.0, 1);
pPlayerPed->RestoreHeadingRate();
TheCamera.SetCameraDirectlyInFrontForFollowPed_CamOnAString();
CReferences::RemoveReferencesToPlayer();
CGarages::PlayerArrestedOrDied();
CStats::CheckPointReachedUnsuccessfully();
CWorld::Remove(pPlayerPed);
CWorld::Add(pPlayerPed);
}
STARTPATCHES
InjectHook(0x4213F0, &CGameLogic::InitAtStartOfGame, PATCH_JUMP);
InjectHook(0x421C00, &CGameLogic::PassTime, PATCH_JUMP);
InjectHook(0x421A20, &CGameLogic::SortOutStreamingAndMemory, PATCH_JUMP);
InjectHook(0x421400, &CGameLogic::Update, PATCH_JUMP);
InjectHook(0x421A60, &CGameLogic::RestorePlayerStuffDuringResurrection, PATCH_JUMP);
InjectHook(0x421A60, &CGameLogic::RestorePlayerStuffDuringResurrection, PATCH_JUMP);
ENDPATCHES

View File

@ -1,13 +1,13 @@
#pragma once
class CGameLogic
{
public:
static void InitAtStartOfGame();
static void PassTime(uint32 time);
static void SortOutStreamingAndMemory(const CVector &pos);
static void Update();
static void RestorePlayerStuffDuringResurrection(class CPlayerPed *pPlayerPed, CVector pos, float angle);
static uint8 ActivePlayers;
#pragma once
class CGameLogic
{
public:
static void InitAtStartOfGame();
static void PassTime(uint32 time);
static void SortOutStreamingAndMemory(const CVector &pos);
static void Update();
static void RestorePlayerStuffDuringResurrection(class CPlayerPed *pPlayerPed, CVector pos, float angle);
static uint8 ActivePlayers;
};

View File

@ -1,7 +1,7 @@
#include "common.h"
#include "patcher.h"
#include "ModelIndices.h"
#include "Gangs.h"
#include "Gangs.h"
#include "Weapon.h"
//CGangInfo(&CGangs::Gang)[NUM_GANGS] = *(CGangInfo(*)[NUM_GANGS])*(uintptr*)0x6EDF78;
@ -57,20 +57,20 @@ void CGangs::SaveAllGangData(uint8 *buf, uint32 *size)
{
INITSAVEBUF
*size = SAVE_HEADER_SIZE + sizeof(Gang);
*size = SAVE_HEADER_SIZE + sizeof(Gang);
WriteSaveHeader(buf, 'G','N','G','\0', *size - SAVE_HEADER_SIZE);
for (int i = 0; i < NUM_GANGS; i++)
WriteSaveBuf(buf, Gang[i]);
for (int i = 0; i < NUM_GANGS; i++)
WriteSaveBuf(buf, Gang[i]);
VALIDATESAVEBUF(*size);
}
void CGangs::LoadAllGangData(uint8 *buf, uint32 size)
{
Initialise();
INITSAVEBUF
// original: SkipSaveBuf(buf, SAVE_HEADER_SIZE);
Initialise();
INITSAVEBUF
// original: SkipSaveBuf(buf, SAVE_HEADER_SIZE);
CheckSaveHeader(buf, 'G','N','G','\0', size - SAVE_HEADER_SIZE);
for (int i = 0; i < NUM_GANGS; i++)

View File

@ -1,49 +1,49 @@
#pragma once
enum
{
COUNTER_DISPLAY_NUMBER,
COUNTER_DISPLAY_BAR,
};
class COnscreenTimerEntry
{
public:
uint32 m_nTimerOffset;
uint32 m_nCounterOffset;
char m_aTimerText[10];
char m_aCounterText[10];
uint16 m_nType;
char m_bCounterBuffer[42];
char m_bTimerBuffer[42];
bool m_bTimerProcessed;
bool m_bCounterProcessed;
void Process();
bool ProcessForDisplay();
void ProcessForDisplayClock();
void ProcessForDisplayCounter();
};
static_assert(sizeof(COnscreenTimerEntry) == 0x74, "COnscreenTimerEntry: error");
class COnscreenTimer
{
public:
COnscreenTimerEntry m_sEntries[NUMONSCREENTIMERENTRIES];
bool m_bProcessed;
bool m_bDisabled;
void Init();
void Process();
void ProcessForDisplay();
void ClearCounter(uint32 offset);
void ClearClock(uint32 offset);
void AddCounter(uint32 offset, uint16 type, char* text);
void AddClock(uint32 offset, char* text);
};
#pragma once
enum
{
COUNTER_DISPLAY_NUMBER,
COUNTER_DISPLAY_BAR,
};
class COnscreenTimerEntry
{
public:
uint32 m_nTimerOffset;
uint32 m_nCounterOffset;
char m_aTimerText[10];
char m_aCounterText[10];
uint16 m_nType;
char m_bCounterBuffer[42];
char m_bTimerBuffer[42];
bool m_bTimerProcessed;
bool m_bCounterProcessed;
void Process();
bool ProcessForDisplay();
void ProcessForDisplayClock();
void ProcessForDisplayCounter();
};
static_assert(sizeof(COnscreenTimerEntry) == 0x74, "COnscreenTimerEntry: error");
class COnscreenTimer
{
public:
COnscreenTimerEntry m_sEntries[NUMONSCREENTIMERENTRIES];
bool m_bProcessed;
bool m_bDisabled;
void Init();
void Process();
void ProcessForDisplay();
void ClearCounter(uint32 offset);
void ClearClock(uint32 offset);
void AddCounter(uint32 offset, uint16 type, char* text);
void AddClock(uint32 offset, char* text);
};
static_assert(sizeof(COnscreenTimer) == 0x78, "COnscreenTimer: error");

File diff suppressed because it is too large Load Diff

View File

@ -1,124 +1,124 @@
#pragma once
#include "Weapon.h"
enum ePickupType : uint8
{
PICKUP_NONE = 0,
PICKUP_IN_SHOP,
PICKUP_ON_STREET,
PICKUP_ONCE,
PICKUP_ONCE_TIMEOUT,
PICKUP_COLLECTABLE1,
PICKUP_IN_SHOP_OUT_OF_STOCK,
PICKUP_MONEY,
PICKUP_MINE_INACTIVE,
PICKUP_MINE_ARMED,
PICKUP_NAUTICAL_MINE_INACTIVE,
PICKUP_NAUTICAL_MINE_ARMED,
PICKUP_FLOATINGPACKAGE,
PICKUP_FLOATINGPACKAGE_FLOATING,
PICKUP_ON_STREET_SLOW,
PICKUP_NUMOFTYPES
};
class CEntity;
class CObject;
class CVehicle;
class CPlayerPed;
class CPickup
{
public:
ePickupType m_eType;
bool m_bRemoved;
uint16 m_nQuantity;
CObject *m_pObject;
uint32 m_nTimer;
int16 m_eModelIndex;
uint16 m_nIndex;
CVector m_vecPos;
CObject *GiveUsAPickUpObject(int32 handle);
bool Update(CPlayerPed *player, CVehicle *vehicle, int playerId);
private:
bool IsMine() { return m_eType >= PICKUP_MINE_INACTIVE && m_eType <= PICKUP_FLOATINGPACKAGE_FLOATING; }
inline bool CanBePickedUp(CPlayerPed *player);
void RemoveKeepType();
void Remove();
};
static_assert(sizeof(CPickup) == 0x1C, "CPickup: error");
struct tPickupMessage
{
CVector2D m_pos;
eWeaponType m_weaponType;
CVector2D m_dist;
CRGBA m_color;
uint8 m_bOutOfStock : 1;
uint8 m_quantity;
};
class CPickups
{
static int32 aPickUpsCollected[NUMCOLLECTEDPICKUPS];
static int16 CollectedPickUpIndex;
static int16 NumMessages;
static tPickupMessage aMessages[NUMPICKUPMESSAGES];
public:
static void Init();
static void Update();
static void RenderPickUpText();
static void DoCollectableEffects(CEntity *ent);
static void DoMoneyEffects(CEntity *ent);
static void DoMineEffects(CEntity *ent);
static void DoPickUpEffects(CEntity *ent);
static int32 GenerateNewOne(CVector pos, uint32 modelIndex, uint8 type, uint32 quantity);
static int32 GenerateNewOne_WeaponType(CVector pos, eWeaponType weaponType, uint8 type, uint32 quantity);
static void RemovePickUp(int32 pickupIndex);
static void RemoveAllFloatingPickups();
static void AddToCollectedPickupsArray(int32 index);
static bool IsPickUpPickedUp(int32 pickupId);
static int32 ModelForWeapon(eWeaponType weaponType);
static enum eWeaponType WeaponForModel(int32 model);
static int32 FindColourIndexForWeaponMI(int32 model);
static int32 GetActualPickupIndex(int32 index);
static int32 GetNewUniquePickupIndex(int32 slot);
static void PassTime(uint32 time);
static bool GivePlayerGoodiesWithPickUpMI(int16 modelIndex, int playerIndex);
static void Load(uint8 *buf, uint32 size);
static void Save(uint8 *buf, uint32 *size);
static CPickup(&aPickUps)[NUMPICKUPS];
// unused
static bool &bPickUpcamActivated;
static CVehicle *&pPlayerVehicle;
static CVector &StaticCamCoors;
static uint32 &StaticCamStartTime;
};
extern uint16 AmmoForWeapon[20];
extern uint16 AmmoForWeapon_OnStreet[20];
extern uint16 CostOfWeapon[20];
class CPacManPickups
{
public:
static void Init(void);
static void Update(void);
static void GeneratePMPickUps(CVector, float, int16, uint8);
static void GeneratePMPickUpsForRace(int32);
static void GenerateOnePMPickUp(CVector);
static void Render(void);
static void DoCleanUpPacManStuff(void);
static void StartPacManRace(int32);
static void StartPacManRecord(void);
static uint32 QueryPowerPillsEatenInRace(void);
static void ResetPowerPillsEatenInRace(void);
static void CleanUpPacManStuff(void);
static void StartPacManScramble(CVector, float, int16);
static uint32 QueryPowerPillsCarriedByPlayer(void);
static void ResetPowerPillsCarriedByPlayer(void);
};
#pragma once
#include "Weapon.h"
enum ePickupType : uint8
{
PICKUP_NONE = 0,
PICKUP_IN_SHOP,
PICKUP_ON_STREET,
PICKUP_ONCE,
PICKUP_ONCE_TIMEOUT,
PICKUP_COLLECTABLE1,
PICKUP_IN_SHOP_OUT_OF_STOCK,
PICKUP_MONEY,
PICKUP_MINE_INACTIVE,
PICKUP_MINE_ARMED,
PICKUP_NAUTICAL_MINE_INACTIVE,
PICKUP_NAUTICAL_MINE_ARMED,
PICKUP_FLOATINGPACKAGE,
PICKUP_FLOATINGPACKAGE_FLOATING,
PICKUP_ON_STREET_SLOW,
PICKUP_NUMOFTYPES
};
class CEntity;
class CObject;
class CVehicle;
class CPlayerPed;
class CPickup
{
public:
ePickupType m_eType;
bool m_bRemoved;
uint16 m_nQuantity;
CObject *m_pObject;
uint32 m_nTimer;
int16 m_eModelIndex;
uint16 m_nIndex;
CVector m_vecPos;
CObject *GiveUsAPickUpObject(int32 handle);
bool Update(CPlayerPed *player, CVehicle *vehicle, int playerId);
private:
bool IsMine() { return m_eType >= PICKUP_MINE_INACTIVE && m_eType <= PICKUP_FLOATINGPACKAGE_FLOATING; }
inline bool CanBePickedUp(CPlayerPed *player);
void RemoveKeepType();
void Remove();
};
static_assert(sizeof(CPickup) == 0x1C, "CPickup: error");
struct tPickupMessage
{
CVector2D m_pos;
eWeaponType m_weaponType;
CVector2D m_dist;
CRGBA m_color;
uint8 m_bOutOfStock : 1;
uint8 m_quantity;
};
class CPickups
{
static int32 aPickUpsCollected[NUMCOLLECTEDPICKUPS];
static int16 CollectedPickUpIndex;
static int16 NumMessages;
static tPickupMessage aMessages[NUMPICKUPMESSAGES];
public:
static void Init();
static void Update();
static void RenderPickUpText();
static void DoCollectableEffects(CEntity *ent);
static void DoMoneyEffects(CEntity *ent);
static void DoMineEffects(CEntity *ent);
static void DoPickUpEffects(CEntity *ent);
static int32 GenerateNewOne(CVector pos, uint32 modelIndex, uint8 type, uint32 quantity);
static int32 GenerateNewOne_WeaponType(CVector pos, eWeaponType weaponType, uint8 type, uint32 quantity);
static void RemovePickUp(int32 pickupIndex);
static void RemoveAllFloatingPickups();
static void AddToCollectedPickupsArray(int32 index);
static bool IsPickUpPickedUp(int32 pickupId);
static int32 ModelForWeapon(eWeaponType weaponType);
static enum eWeaponType WeaponForModel(int32 model);
static int32 FindColourIndexForWeaponMI(int32 model);
static int32 GetActualPickupIndex(int32 index);
static int32 GetNewUniquePickupIndex(int32 slot);
static void PassTime(uint32 time);
static bool GivePlayerGoodiesWithPickUpMI(int16 modelIndex, int playerIndex);
static void Load(uint8 *buf, uint32 size);
static void Save(uint8 *buf, uint32 *size);
static CPickup(&aPickUps)[NUMPICKUPS];
// unused
static bool &bPickUpcamActivated;
static CVehicle *&pPlayerVehicle;
static CVector &StaticCamCoors;
static uint32 &StaticCamStartTime;
};
extern uint16 AmmoForWeapon[20];
extern uint16 AmmoForWeapon_OnStreet[20];
extern uint16 CostOfWeapon[20];
class CPacManPickups
{
public:
static void Init(void);
static void Update(void);
static void GeneratePMPickUps(CVector, float, int16, uint8);
static void GeneratePMPickUpsForRace(int32);
static void GenerateOnePMPickUp(CVector);
static void Render(void);
static void DoCleanUpPacManStuff(void);
static void StartPacManRace(int32);
static void StartPacManRecord(void);
static uint32 QueryPowerPillsEatenInRace(void);
static void ResetPowerPillsEatenInRace(void);
static void CleanUpPacManStuff(void);
static void StartPacManScramble(CVector, float, int16);
static uint32 QueryPowerPillsCarriedByPlayer(void);
static void ResetPowerPillsCarriedByPlayer(void);
};

View File

@ -1,22 +1,22 @@
#include "common.h"
#include "PowerPoints.h"
// Some cut beta feature
void CPowerPoint::Update()
{}
void CPowerPoints::Init()
{}
void CPowerPoints::Update()
{}
void CPowerPoints::GenerateNewOne(float, float, float, float, float, float, uint8)
{}
void CPowerPoints::Save(uint8**, uint32*)
{}
void CPowerPoints::Load(uint8*, uint32)
#include "common.h"
#include "PowerPoints.h"
// Some cut beta feature
void CPowerPoint::Update()
{}
void CPowerPoints::Init()
{}
void CPowerPoints::Update()
{}
void CPowerPoints::GenerateNewOne(float, float, float, float, float, float, uint8)
{}
void CPowerPoints::Save(uint8**, uint32*)
{}
void CPowerPoints::Load(uint8*, uint32)
{}

View File

@ -1,26 +1,26 @@
#pragma once
enum
{
POWERPOINT_NONE = 0,
POWERPOINT_HEALTH,
POWERPOINT_HIDEOUT_INDUSTRIAL,
POWERPOINT_HIDEOUT_COMMERCIAL,
POWERPOINT_HIDEOUT_SUBURBAN
};
class CPowerPoint
{
public:
void Update();
};
class CPowerPoints
{
public:
static void Init();
static void Update();
static void GenerateNewOne(float, float, float, float, float, float, uint8);
static void Save(uint8**, uint32*);
static void Load(uint8*, uint32);
#pragma once
enum
{
POWERPOINT_NONE = 0,
POWERPOINT_HEALTH,
POWERPOINT_HIDEOUT_INDUSTRIAL,
POWERPOINT_HIDEOUT_COMMERCIAL,
POWERPOINT_HIDEOUT_SUBURBAN
};
class CPowerPoint
{
public:
void Update();
};
class CPowerPoints
{
public:
static void Init();
static void Update();
static void GenerateNewOne(float, float, float, float, float, float, uint8);
static void Save(uint8**, uint32*);
static void Load(uint8*, uint32);
};

View File

@ -21,234 +21,234 @@ CVector(&CRestart::PoliceRestartPoints)[NUM_RESTART_POINTS] = *(CVector(*)[NUM_R
float(&CRestart::PoliceRestartHeadings)[NUM_RESTART_POINTS] = *(float(*)[NUM_RESTART_POINTS])*(uintptr*)0x6F1D20;
uint16 &CRestart::NumberOfPoliceRestarts = *(uint16*)0x95CC44;
void
CRestart::Initialise()
{
OverridePoliceStationLevel = LEVEL_NONE;
OverrideHospitalLevel = LEVEL_NONE;
bFadeInAfterNextArrest = true;
bFadeInAfterNextDeath = true;
OverrideHeading = 0.0f;
OverridePosition = CVector(0.0f, 0.0f, 0.0f);
bOverrideRestart = false;
NumberOfPoliceRestarts = 0;
NumberOfHospitalRestarts = 0;
for (int i = 0; i < NUM_RESTART_POINTS; i++) {
HospitalRestartPoints[i] = CVector(0.0f, 0.0f, 0.0f);
HospitalRestartHeadings[i] = 0.0f;
PoliceRestartPoints[i] = CVector(0.0f, 0.0f, 0.0f);
PoliceRestartHeadings[i] = 0.0f;
}
void
CRestart::Initialise()
{
OverridePoliceStationLevel = LEVEL_NONE;
OverrideHospitalLevel = LEVEL_NONE;
bFadeInAfterNextArrest = true;
bFadeInAfterNextDeath = true;
OverrideHeading = 0.0f;
OverridePosition = CVector(0.0f, 0.0f, 0.0f);
bOverrideRestart = false;
NumberOfPoliceRestarts = 0;
NumberOfHospitalRestarts = 0;
for (int i = 0; i < NUM_RESTART_POINTS; i++) {
HospitalRestartPoints[i] = CVector(0.0f, 0.0f, 0.0f);
HospitalRestartHeadings[i] = 0.0f;
PoliceRestartPoints[i] = CVector(0.0f, 0.0f, 0.0f);
PoliceRestartHeadings[i] = 0.0f;
}
}
void
CRestart::AddHospitalRestartPoint(const CVector &pos, float heading)
{
HospitalRestartPoints[NumberOfHospitalRestarts] = pos;
HospitalRestartHeadings[NumberOfHospitalRestarts++] = heading;
void
CRestart::AddHospitalRestartPoint(const CVector &pos, float heading)
{
HospitalRestartPoints[NumberOfHospitalRestarts] = pos;
HospitalRestartHeadings[NumberOfHospitalRestarts++] = heading;
}
void
CRestart::AddPoliceRestartPoint(const CVector &pos, float heading)
{
PoliceRestartPoints[NumberOfPoliceRestarts] = pos;
PoliceRestartHeadings[NumberOfPoliceRestarts++] = heading;
void
CRestart::AddPoliceRestartPoint(const CVector &pos, float heading)
{
PoliceRestartPoints[NumberOfPoliceRestarts] = pos;
PoliceRestartHeadings[NumberOfPoliceRestarts++] = heading;
}
void
CRestart::OverrideNextRestart(const CVector &pos, float heading)
{
bOverrideRestart = true;
OverridePosition = pos;
OverrideHeading = heading;
void
CRestart::OverrideNextRestart(const CVector &pos, float heading)
{
bOverrideRestart = true;
OverridePosition = pos;
OverrideHeading = heading;
}
void
CRestart::CancelOverrideRestart()
{
bOverrideRestart = false;
void
CRestart::CancelOverrideRestart()
{
bOverrideRestart = false;
}
void
CRestart::FindClosestHospitalRestartPoint(const CVector &pos, CVector *outPos, float *outHeading)
{
if (bOverrideRestart) {
*outPos = OverridePosition;
*outHeading = OverrideHeading;
CancelOverrideRestart();
return;
}
eLevelName curlevel = CTheZones::FindZoneForPoint(pos);
float fMinDist = 16000000.0f;
int closestPoint = NUM_RESTART_POINTS;
// find closest point on this level
for (int i = 0; i < NumberOfHospitalRestarts; i++) {
if (CTheZones::FindZoneForPoint(HospitalRestartPoints[i]) == (OverrideHospitalLevel != LEVEL_NONE ? OverrideHospitalLevel : curlevel)) {
float dist = (pos - HospitalRestartPoints[i]).MagnitudeSqr();
if (fMinDist >= dist) {
fMinDist = dist;
closestPoint = i;
}
}
}
// if we didn't find anything, find closest point on any level
if (closestPoint == NUM_RESTART_POINTS) {
for (int i = 0; i < NumberOfHospitalRestarts; i++) {
float dist = (pos - HospitalRestartPoints[i]).MagnitudeSqr();
if (fMinDist >= dist) {
fMinDist = dist;
closestPoint = i;
}
}
}
// if we still didn't find anything, find closest path node
if (closestPoint == NUM_RESTART_POINTS) {
*outPos = ThePaths.m_pathNodes[ThePaths.FindNodeClosestToCoors(pos, PATH_PED, 999999.9f)].pos;
*outHeading = 0.0f;
printf("Couldn't find a hospital restart zone near the player %f %f %f->%f %f %f\n", pos.x, pos.y, pos.z, outPos->x, outPos->y, outPos->z);
} else {
*outPos = HospitalRestartPoints[closestPoint];
*outHeading = HospitalRestartHeadings[closestPoint];
}
void
CRestart::FindClosestHospitalRestartPoint(const CVector &pos, CVector *outPos, float *outHeading)
{
if (bOverrideRestart) {
*outPos = OverridePosition;
*outHeading = OverrideHeading;
CancelOverrideRestart();
return;
}
eLevelName curlevel = CTheZones::FindZoneForPoint(pos);
float fMinDist = 16000000.0f;
int closestPoint = NUM_RESTART_POINTS;
// find closest point on this level
for (int i = 0; i < NumberOfHospitalRestarts; i++) {
if (CTheZones::FindZoneForPoint(HospitalRestartPoints[i]) == (OverrideHospitalLevel != LEVEL_NONE ? OverrideHospitalLevel : curlevel)) {
float dist = (pos - HospitalRestartPoints[i]).MagnitudeSqr();
if (fMinDist >= dist) {
fMinDist = dist;
closestPoint = i;
}
}
}
// if we didn't find anything, find closest point on any level
if (closestPoint == NUM_RESTART_POINTS) {
for (int i = 0; i < NumberOfHospitalRestarts; i++) {
float dist = (pos - HospitalRestartPoints[i]).MagnitudeSqr();
if (fMinDist >= dist) {
fMinDist = dist;
closestPoint = i;
}
}
}
// if we still didn't find anything, find closest path node
if (closestPoint == NUM_RESTART_POINTS) {
*outPos = ThePaths.m_pathNodes[ThePaths.FindNodeClosestToCoors(pos, PATH_PED, 999999.9f)].pos;
*outHeading = 0.0f;
printf("Couldn't find a hospital restart zone near the player %f %f %f->%f %f %f\n", pos.x, pos.y, pos.z, outPos->x, outPos->y, outPos->z);
} else {
*outPos = HospitalRestartPoints[closestPoint];
*outHeading = HospitalRestartHeadings[closestPoint];
}
}
void
CRestart::FindClosestPoliceRestartPoint(const CVector &pos, CVector *outPos, float *outHeading)
{
if (bOverrideRestart) {
*outPos = OverridePosition;
*outHeading = OverrideHeading;
CancelOverrideRestart();
return;
}
eLevelName curlevel = CTheZones::FindZoneForPoint(pos);
float fMinDist = 16000000.0f;
int closestPoint = NUM_RESTART_POINTS;
// find closest point on this level
for (int i = 0; i < NumberOfPoliceRestarts; i++) {
if (CTheZones::FindZoneForPoint(PoliceRestartPoints[i]) == (OverridePoliceStationLevel != LEVEL_NONE ? OverridePoliceStationLevel : curlevel)) {
float dist = (pos - PoliceRestartPoints[i]).MagnitudeSqr();
if (fMinDist >= dist) {
fMinDist = dist;
closestPoint = i;
}
}
}
// if we didn't find anything, find closest point on any level
if (closestPoint == NUM_RESTART_POINTS) {
for (int i = 0; i < NumberOfPoliceRestarts; i++) {
float dist = (pos - PoliceRestartPoints[i]).MagnitudeSqr();
if (fMinDist >= dist) {
fMinDist = dist;
closestPoint = i;
}
}
}
// if we still didn't find anything, find closest path node
if (closestPoint == NUM_RESTART_POINTS) {
printf("Couldn't find a police restart zone near the player\n");
*outPos = ThePaths.m_pathNodes[ThePaths.FindNodeClosestToCoors(pos, PATH_PED, 999999.9f)].pos;
*outHeading = 0.0f;
} else {
*outPos = PoliceRestartPoints[closestPoint];
*outHeading = PoliceRestartHeadings[closestPoint];
}
}
void
CRestart::LoadAllRestartPoints(uint8 *buf, uint32 size)
{
Initialise();
INITSAVEBUF
CheckSaveHeader(buf, 'R','S','T','\0', size - SAVE_HEADER_SIZE);
for (int i = 0; i < NUM_RESTART_POINTS; i++) {
HospitalRestartPoints[i] = ReadSaveBuf<CVector>(buf);
HospitalRestartHeadings[i] = ReadSaveBuf<float>(buf);
}
for (int i = 0; i < NUM_RESTART_POINTS; i++) {
PoliceRestartPoints[i] = ReadSaveBuf<CVector>(buf);
PoliceRestartHeadings[i] = ReadSaveBuf<float>(buf);
}
NumberOfHospitalRestarts = ReadSaveBuf<uint16>(buf);
NumberOfPoliceRestarts = ReadSaveBuf<uint16>(buf);
bOverrideRestart = ReadSaveBuf<bool>(buf);
// skip something unused
ReadSaveBuf<uint8>(buf);
ReadSaveBuf<uint16>(buf);
OverridePosition = ReadSaveBuf<CVector>(buf);
OverrideHeading = ReadSaveBuf<float>(buf);
bFadeInAfterNextDeath = ReadSaveBuf<bool>(buf);
bFadeInAfterNextArrest = ReadSaveBuf<bool>(buf);
OverrideHospitalLevel = ReadSaveBuf<uint8>(buf);
OverridePoliceStationLevel = ReadSaveBuf<uint8>(buf);
VALIDATESAVEBUF(size);
}
void
CRestart::SaveAllRestartPoints(uint8 *buf, uint32 *size)
{
*size = SAVE_HEADER_SIZE
+ sizeof(HospitalRestartPoints)
+ sizeof(HospitalRestartHeadings)
+ sizeof(PoliceRestartPoints)
+ sizeof(PoliceRestartHeadings)
+ sizeof(NumberOfHospitalRestarts)
+ sizeof(NumberOfPoliceRestarts)
+ sizeof(bOverrideRestart)
+ sizeof(uint8)
+ sizeof(uint16)
+ sizeof(OverridePosition)
+ sizeof(OverrideHeading)
+ sizeof(bFadeInAfterNextDeath)
+ sizeof(bFadeInAfterNextArrest)
+ sizeof(OverrideHospitalLevel)
+ sizeof(OverridePoliceStationLevel); // == 292
INITSAVEBUF
WriteSaveHeader(buf, 'R','S','T','\0', *size - SAVE_HEADER_SIZE);
for (int i = 0; i < NUM_RESTART_POINTS; i++) {
WriteSaveBuf(buf, HospitalRestartPoints[i]);
WriteSaveBuf(buf, HospitalRestartHeadings[i]);
}
for (int i = 0; i < NUM_RESTART_POINTS; i++) {
WriteSaveBuf(buf, PoliceRestartPoints[i]);
WriteSaveBuf(buf, PoliceRestartHeadings[i]);
}
WriteSaveBuf(buf, NumberOfHospitalRestarts);
WriteSaveBuf(buf, NumberOfPoliceRestarts);
WriteSaveBuf(buf, bOverrideRestart);
WriteSaveBuf(buf, (uint8)0);
WriteSaveBuf(buf, (uint16)0);
WriteSaveBuf(buf, OverridePosition);
WriteSaveBuf(buf, OverrideHeading);
WriteSaveBuf(buf, bFadeInAfterNextDeath);
WriteSaveBuf(buf, bFadeInAfterNextArrest);
WriteSaveBuf(buf, OverrideHospitalLevel);
WriteSaveBuf(buf, OverridePoliceStationLevel);
VALIDATESAVEBUF(*size);
}
void
CRestart::FindClosestPoliceRestartPoint(const CVector &pos, CVector *outPos, float *outHeading)
{
if (bOverrideRestart) {
*outPos = OverridePosition;
*outHeading = OverrideHeading;
CancelOverrideRestart();
return;
}
eLevelName curlevel = CTheZones::FindZoneForPoint(pos);
float fMinDist = 16000000.0f;
int closestPoint = NUM_RESTART_POINTS;
// find closest point on this level
for (int i = 0; i < NumberOfPoliceRestarts; i++) {
if (CTheZones::FindZoneForPoint(PoliceRestartPoints[i]) == (OverridePoliceStationLevel != LEVEL_NONE ? OverridePoliceStationLevel : curlevel)) {
float dist = (pos - PoliceRestartPoints[i]).MagnitudeSqr();
if (fMinDist >= dist) {
fMinDist = dist;
closestPoint = i;
}
}
}
// if we didn't find anything, find closest point on any level
if (closestPoint == NUM_RESTART_POINTS) {
for (int i = 0; i < NumberOfPoliceRestarts; i++) {
float dist = (pos - PoliceRestartPoints[i]).MagnitudeSqr();
if (fMinDist >= dist) {
fMinDist = dist;
closestPoint = i;
}
}
}
// if we still didn't find anything, find closest path node
if (closestPoint == NUM_RESTART_POINTS) {
printf("Couldn't find a police restart zone near the player\n");
*outPos = ThePaths.m_pathNodes[ThePaths.FindNodeClosestToCoors(pos, PATH_PED, 999999.9f)].pos;
*outHeading = 0.0f;
} else {
*outPos = PoliceRestartPoints[closestPoint];
*outHeading = PoliceRestartHeadings[closestPoint];
}
}
void
CRestart::LoadAllRestartPoints(uint8 *buf, uint32 size)
{
Initialise();
INITSAVEBUF
CheckSaveHeader(buf, 'R','S','T','\0', size - SAVE_HEADER_SIZE);
for (int i = 0; i < NUM_RESTART_POINTS; i++) {
HospitalRestartPoints[i] = ReadSaveBuf<CVector>(buf);
HospitalRestartHeadings[i] = ReadSaveBuf<float>(buf);
}
for (int i = 0; i < NUM_RESTART_POINTS; i++) {
PoliceRestartPoints[i] = ReadSaveBuf<CVector>(buf);
PoliceRestartHeadings[i] = ReadSaveBuf<float>(buf);
}
NumberOfHospitalRestarts = ReadSaveBuf<uint16>(buf);
NumberOfPoliceRestarts = ReadSaveBuf<uint16>(buf);
bOverrideRestart = ReadSaveBuf<bool>(buf);
// skip something unused
ReadSaveBuf<uint8>(buf);
ReadSaveBuf<uint16>(buf);
OverridePosition = ReadSaveBuf<CVector>(buf);
OverrideHeading = ReadSaveBuf<float>(buf);
bFadeInAfterNextDeath = ReadSaveBuf<bool>(buf);
bFadeInAfterNextArrest = ReadSaveBuf<bool>(buf);
OverrideHospitalLevel = ReadSaveBuf<uint8>(buf);
OverridePoliceStationLevel = ReadSaveBuf<uint8>(buf);
VALIDATESAVEBUF(size);
}
void
CRestart::SaveAllRestartPoints(uint8 *buf, uint32 *size)
{
*size = SAVE_HEADER_SIZE
+ sizeof(HospitalRestartPoints)
+ sizeof(HospitalRestartHeadings)
+ sizeof(PoliceRestartPoints)
+ sizeof(PoliceRestartHeadings)
+ sizeof(NumberOfHospitalRestarts)
+ sizeof(NumberOfPoliceRestarts)
+ sizeof(bOverrideRestart)
+ sizeof(uint8)
+ sizeof(uint16)
+ sizeof(OverridePosition)
+ sizeof(OverrideHeading)
+ sizeof(bFadeInAfterNextDeath)
+ sizeof(bFadeInAfterNextArrest)
+ sizeof(OverrideHospitalLevel)
+ sizeof(OverridePoliceStationLevel); // == 292
INITSAVEBUF
WriteSaveHeader(buf, 'R','S','T','\0', *size - SAVE_HEADER_SIZE);
for (int i = 0; i < NUM_RESTART_POINTS; i++) {
WriteSaveBuf(buf, HospitalRestartPoints[i]);
WriteSaveBuf(buf, HospitalRestartHeadings[i]);
}
for (int i = 0; i < NUM_RESTART_POINTS; i++) {
WriteSaveBuf(buf, PoliceRestartPoints[i]);
WriteSaveBuf(buf, PoliceRestartHeadings[i]);
}
WriteSaveBuf(buf, NumberOfHospitalRestarts);
WriteSaveBuf(buf, NumberOfPoliceRestarts);
WriteSaveBuf(buf, bOverrideRestart);
WriteSaveBuf(buf, (uint8)0);
WriteSaveBuf(buf, (uint16)0);
WriteSaveBuf(buf, OverridePosition);
WriteSaveBuf(buf, OverrideHeading);
WriteSaveBuf(buf, bFadeInAfterNextDeath);
WriteSaveBuf(buf, bFadeInAfterNextArrest);
WriteSaveBuf(buf, OverrideHospitalLevel);
WriteSaveBuf(buf, OverridePoliceStationLevel);
VALIDATESAVEBUF(*size);
}
STARTPATCHES
InjectHook(0x435E20, &CRestart::Initialise, PATCH_JUMP);
InjectHook(0x436100, &CRestart::AddHospitalRestartPoint, PATCH_JUMP);
@ -258,5 +258,5 @@ STARTPATCHES
InjectHook(0x4361A0, &CRestart::FindClosestHospitalRestartPoint, PATCH_JUMP);
InjectHook(0x436450, &CRestart::FindClosestPoliceRestartPoint, PATCH_JUMP);
InjectHook(0x436B20, &CRestart::LoadAllRestartPoints, PATCH_JUMP);
InjectHook(0x436700, &CRestart::SaveAllRestartPoints, PATCH_JUMP);
InjectHook(0x436700, &CRestart::SaveAllRestartPoints, PATCH_JUMP);
ENDPATCHES

View File

@ -550,10 +550,10 @@ public:
static int32 &sthWithButtons;
static int32 &sthWithButtons2;
#ifndef MASTER
static bool m_PrefsMarketing;
static bool m_PrefsDisableTutorials;
#endif // !MASTER
#ifndef MASTER
static bool m_PrefsMarketing;
static bool m_PrefsDisableTutorials;
#endif // !MASTER
#ifdef MENU_MAP
static bool bMenuMapActive;

View File

@ -48,45 +48,45 @@ CPlayerInfo::GetPos()
void
CPlayerInfo::LoadPlayerSkin()
{
DeletePlayerSkin();
m_pSkinTexture = CPlayerSkin::GetSkinTexture(m_aSkinName);
if (!m_pSkinTexture)
{
DeletePlayerSkin();
m_pSkinTexture = CPlayerSkin::GetSkinTexture(m_aSkinName);
if (!m_pSkinTexture)
m_pSkinTexture = CPlayerSkin::GetSkinTexture(DEFAULT_SKIN_NAME);
}
void
CPlayerInfo::DeletePlayerSkin()
{
if (m_pSkinTexture) {
RwTextureDestroy(m_pSkinTexture);
m_pSkinTexture = nil;
{
if (m_pSkinTexture) {
RwTextureDestroy(m_pSkinTexture);
m_pSkinTexture = nil;
}
}
void
CPlayerInfo::KillPlayer()
{
if (m_WBState != WBSTATE_PLAYING) return;
m_WBState = WBSTATE_WASTED;
m_nWBTime = CTimer::GetTimeInMilliseconds();
CDarkel::ResetOnPlayerDeath();
CMessages::AddBigMessage(TheText.Get("DEAD"), 4000, 2);
CStats::TimesDied++;
void
CPlayerInfo::KillPlayer()
{
if (m_WBState != WBSTATE_PLAYING) return;
m_WBState = WBSTATE_WASTED;
m_nWBTime = CTimer::GetTimeInMilliseconds();
CDarkel::ResetOnPlayerDeath();
CMessages::AddBigMessage(TheText.Get("DEAD"), 4000, 2);
CStats::TimesDied++;
}
void
CPlayerInfo::ArrestPlayer()
{
if (m_WBState != WBSTATE_PLAYING) return;
m_WBState = WBSTATE_BUSTED;
m_nWBTime = CTimer::GetTimeInMilliseconds();
CDarkel::ResetOnPlayerDeath();
CMessages::AddBigMessage(TheText.Get("BUSTED"), 5000, 2);
CStats::TimesArrested++;
void
CPlayerInfo::ArrestPlayer()
{
if (m_WBState != WBSTATE_PLAYING) return;
m_WBState = WBSTATE_BUSTED;
m_nWBTime = CTimer::GetTimeInMilliseconds();
CDarkel::ResetOnPlayerDeath();
CMessages::AddBigMessage(TheText.Get("BUSTED"), 5000, 2);
CStats::TimesArrested++;
}
bool
@ -105,102 +105,102 @@ CPlayerInfo::PlayerFailedCriticalMission()
CDarkel::ResetOnPlayerDeath();
}
void
CPlayerInfo::Clear(void)
{
m_pPed = nil;
m_pRemoteVehicle = nil;
if (m_pVehicleEx) {
m_pVehicleEx->bUsingSpecialColModel = false;
m_pVehicleEx = nil;
}
m_nVisibleMoney = 0;
m_nMoney = m_nVisibleMoney;
m_WBState = WBSTATE_PLAYING;
m_nWBTime = 0;
m_nTrafficMultiplier = 0;
m_fRoadDensity = 1.0f;
m_bInRemoteMode = false;
m_bUnusedTaxiThing = false;
m_nUnusedTaxiTimer = 0;
m_nCollectedPackages = 0;
m_nTotalPackages = 3;
m_nTimeLastHealthLoss = 0;
m_nTimeLastArmourLoss = 0;
m_nNextSexFrequencyUpdateTime = 0;
m_nNextSexMoneyUpdateTime = 0;
m_nSexFrequency = 0;
m_pHooker = nil;
m_nTimeTankShotGun = 0;
field_248 = 0;
m_nUpsideDownCounter = 0;
m_bInfiniteSprint = false;
m_bFastReload = false;
m_bGetOutOfJailFree = false;
m_bGetOutOfHospitalFree = false;
m_nPreviousTimeRewardedForExplosion = 0;
m_nExplosionsSinceLastReward = 0;
void
CPlayerInfo::Clear(void)
{
m_pPed = nil;
m_pRemoteVehicle = nil;
if (m_pVehicleEx) {
m_pVehicleEx->bUsingSpecialColModel = false;
m_pVehicleEx = nil;
}
m_nVisibleMoney = 0;
m_nMoney = m_nVisibleMoney;
m_WBState = WBSTATE_PLAYING;
m_nWBTime = 0;
m_nTrafficMultiplier = 0;
m_fRoadDensity = 1.0f;
m_bInRemoteMode = false;
m_bUnusedTaxiThing = false;
m_nUnusedTaxiTimer = 0;
m_nCollectedPackages = 0;
m_nTotalPackages = 3;
m_nTimeLastHealthLoss = 0;
m_nTimeLastArmourLoss = 0;
m_nNextSexFrequencyUpdateTime = 0;
m_nNextSexMoneyUpdateTime = 0;
m_nSexFrequency = 0;
m_pHooker = nil;
m_nTimeTankShotGun = 0;
field_248 = 0;
m_nUpsideDownCounter = 0;
m_bInfiniteSprint = false;
m_bFastReload = false;
m_bGetOutOfJailFree = false;
m_bGetOutOfHospitalFree = false;
m_nPreviousTimeRewardedForExplosion = 0;
m_nExplosionsSinceLastReward = 0;
}
void
CPlayerInfo::BlowUpRCBuggy(void)
{
if (!m_pRemoteVehicle || m_pRemoteVehicle->bRemoveFromWorld)
return;
CRemote::TakeRemoteControlledCarFromPlayer();
m_pRemoteVehicle->BlowUpCar(FindPlayerPed());
}
void
CPlayerInfo::CancelPlayerEnteringCars(CVehicle *car)
{
if (!car || car == m_pPed->m_pMyVehicle) {
if (m_pPed->EnteringCar())
m_pPed->QuitEnteringCar();
}
if (m_pPed->m_objective == OBJECTIVE_ENTER_CAR_AS_PASSENGER || m_pPed->m_objective == OBJECTIVE_ENTER_CAR_AS_DRIVER)
m_pPed->ClearObjective();
void
CPlayerInfo::BlowUpRCBuggy(void)
{
if (!m_pRemoteVehicle || m_pRemoteVehicle->bRemoveFromWorld)
return;
CRemote::TakeRemoteControlledCarFromPlayer();
m_pRemoteVehicle->BlowUpCar(FindPlayerPed());
}
void
CPlayerInfo::MakePlayerSafe(bool toggle)
{
if (toggle) {
CTheScripts::ResetCountdownToMakePlayerUnsafe();
m_pPed->m_pWanted->m_bIgnoredByEveryone = true;
CWorld::StopAllLawEnforcersInTheirTracks();
CPad::GetPad(0)->DisablePlayerControls |= PLAYERCONTROL_DISABLED_20;
CPad::StopPadsShaking();
m_pPed->bBulletProof = true;
m_pPed->bFireProof = true;
m_pPed->bCollisionProof = true;
m_pPed->bMeleeProof = true;
m_pPed->bOnlyDamagedByPlayer = true;
m_pPed->bExplosionProof = true;
m_pPed->m_bCanBeDamaged = false;
((CPlayerPed*)m_pPed)->ClearAdrenaline();
CancelPlayerEnteringCars(false);
gFireManager.ExtinguishPoint(GetPos(), 4000.0f);
CExplosion::RemoveAllExplosionsInArea(GetPos(), 4000.0f);
CProjectileInfo::RemoveAllProjectiles();
CWorld::SetAllCarsCanBeDamaged(false);
CWorld::ExtinguishAllCarFiresInArea(GetPos(), 4000.0f);
CReplay::DisableReplays();
} else if (!CGame::playingIntro && !CTheScripts::IsCountdownToMakePlayerUnsafeOn()) {
m_pPed->m_pWanted->m_bIgnoredByEveryone = false;
CPad::GetPad(0)->DisablePlayerControls &= ~PLAYERCONTROL_DISABLED_20;
m_pPed->bBulletProof = false;
m_pPed->bFireProof = false;
m_pPed->bCollisionProof = false;
m_pPed->bMeleeProof = false;
m_pPed->bOnlyDamagedByPlayer = false;
m_pPed->bExplosionProof = false;
m_pPed->m_bCanBeDamaged = true;
CWorld::SetAllCarsCanBeDamaged(true);
CReplay::EnableReplays();
}
void
CPlayerInfo::CancelPlayerEnteringCars(CVehicle *car)
{
if (!car || car == m_pPed->m_pMyVehicle) {
if (m_pPed->EnteringCar())
m_pPed->QuitEnteringCar();
}
if (m_pPed->m_objective == OBJECTIVE_ENTER_CAR_AS_PASSENGER || m_pPed->m_objective == OBJECTIVE_ENTER_CAR_AS_DRIVER)
m_pPed->ClearObjective();
}
void
CPlayerInfo::MakePlayerSafe(bool toggle)
{
if (toggle) {
CTheScripts::ResetCountdownToMakePlayerUnsafe();
m_pPed->m_pWanted->m_bIgnoredByEveryone = true;
CWorld::StopAllLawEnforcersInTheirTracks();
CPad::GetPad(0)->DisablePlayerControls |= PLAYERCONTROL_DISABLED_20;
CPad::StopPadsShaking();
m_pPed->bBulletProof = true;
m_pPed->bFireProof = true;
m_pPed->bCollisionProof = true;
m_pPed->bMeleeProof = true;
m_pPed->bOnlyDamagedByPlayer = true;
m_pPed->bExplosionProof = true;
m_pPed->m_bCanBeDamaged = false;
((CPlayerPed*)m_pPed)->ClearAdrenaline();
CancelPlayerEnteringCars(false);
gFireManager.ExtinguishPoint(GetPos(), 4000.0f);
CExplosion::RemoveAllExplosionsInArea(GetPos(), 4000.0f);
CProjectileInfo::RemoveAllProjectiles();
CWorld::SetAllCarsCanBeDamaged(false);
CWorld::ExtinguishAllCarFiresInArea(GetPos(), 4000.0f);
CReplay::DisableReplays();
} else if (!CGame::playingIntro && !CTheScripts::IsCountdownToMakePlayerUnsafeOn()) {
m_pPed->m_pWanted->m_bIgnoredByEveryone = false;
CPad::GetPad(0)->DisablePlayerControls &= ~PLAYERCONTROL_DISABLED_20;
m_pPed->bBulletProof = false;
m_pPed->bFireProof = false;
m_pPed->bCollisionProof = false;
m_pPed->bMeleeProof = false;
m_pPed->bOnlyDamagedByPlayer = false;
m_pPed->bExplosionProof = false;
m_pPed->m_bCanBeDamaged = true;
CWorld::SetAllCarsCanBeDamaged(true);
CReplay::EnableReplays();
}
}
bool
@ -216,347 +216,347 @@ CPlayerInfo::IsRestartingAfterArrest()
}
// lastCloseness is passed to other calls of this function
void
CPlayerInfo::EvaluateCarPosition(CEntity *carToTest, CPed *player, float carBoundCentrePedDist, float *lastCloseness, CVehicle **closestCarOutput)
{
// This dist used for determining the angle to face
CVector2D dist(carToTest->GetPosition() - player->GetPosition());
float neededTurn = CGeneral::GetATanOfXY(player->GetForward().x, player->GetForward().y) - CGeneral::GetATanOfXY(dist.x, dist.y);
while (neededTurn >= PI) {
neededTurn -= 2 * PI;
}
while (neededTurn < -PI) {
neededTurn += 2 * PI;
}
// This dist used for evaluating cars' distances, weird...
// Accounts inverted needed turn (or needed turn in long way) and car dist.
float closeness = (1.0f - Abs(neededTurn) / TWOPI) * (10.0f - carBoundCentrePedDist);
if (closeness > *lastCloseness) {
*lastCloseness = closeness;
*closestCarOutput = (CVehicle*)carToTest;
}
void
CPlayerInfo::EvaluateCarPosition(CEntity *carToTest, CPed *player, float carBoundCentrePedDist, float *lastCloseness, CVehicle **closestCarOutput)
{
// This dist used for determining the angle to face
CVector2D dist(carToTest->GetPosition() - player->GetPosition());
float neededTurn = CGeneral::GetATanOfXY(player->GetForward().x, player->GetForward().y) - CGeneral::GetATanOfXY(dist.x, dist.y);
while (neededTurn >= PI) {
neededTurn -= 2 * PI;
}
while (neededTurn < -PI) {
neededTurn += 2 * PI;
}
// This dist used for evaluating cars' distances, weird...
// Accounts inverted needed turn (or needed turn in long way) and car dist.
float closeness = (1.0f - Abs(neededTurn) / TWOPI) * (10.0f - carBoundCentrePedDist);
if (closeness > *lastCloseness) {
*lastCloseness = closeness;
*closestCarOutput = (CVehicle*)carToTest;
}
}
// There is something unfinished in here... Sadly all IDBs we have have it unfinished.
void
CPlayerInfo::AwardMoneyForExplosion(CVehicle *wreckedCar)
{
if (CTimer::GetTimeInMilliseconds() - m_nPreviousTimeRewardedForExplosion < 6000)
++m_nExplosionsSinceLastReward;
else
m_nExplosionsSinceLastReward = 1;
m_nPreviousTimeRewardedForExplosion = CTimer::GetTimeInMilliseconds();
int award = wreckedCar->pHandling->nMonetaryValue * 0.002f;
sprintf(gString, "$%d", award);
#ifdef MONEY_MESSAGES
// This line is a leftover from PS2, I don't know what it was meant to be.
// CVector sth(TheCamera.GetPosition() * 4.0f);
CMoneyMessages::RegisterOne(wreckedCar->GetPosition() + CVector(0.0f, 0.0f, 2.0f), gString, 0, 255, 0, 2.0f, 0.5f);
#endif
CWorld::Players[CWorld::PlayerInFocus].m_nMoney += award;
for (int i = m_nExplosionsSinceLastReward; i > 1; --i) {
CGeneral::GetRandomNumber();
CWorld::Players[CWorld::PlayerInFocus].m_nMoney += award;
}
void
CPlayerInfo::AwardMoneyForExplosion(CVehicle *wreckedCar)
{
if (CTimer::GetTimeInMilliseconds() - m_nPreviousTimeRewardedForExplosion < 6000)
++m_nExplosionsSinceLastReward;
else
m_nExplosionsSinceLastReward = 1;
m_nPreviousTimeRewardedForExplosion = CTimer::GetTimeInMilliseconds();
int award = wreckedCar->pHandling->nMonetaryValue * 0.002f;
sprintf(gString, "$%d", award);
#ifdef MONEY_MESSAGES
// This line is a leftover from PS2, I don't know what it was meant to be.
// CVector sth(TheCamera.GetPosition() * 4.0f);
CMoneyMessages::RegisterOne(wreckedCar->GetPosition() + CVector(0.0f, 0.0f, 2.0f), gString, 0, 255, 0, 2.0f, 0.5f);
#endif
CWorld::Players[CWorld::PlayerInFocus].m_nMoney += award;
for (int i = m_nExplosionsSinceLastReward; i > 1; --i) {
CGeneral::GetRandomNumber();
CWorld::Players[CWorld::PlayerInFocus].m_nMoney += award;
}
}
void
CPlayerInfo::SavePlayerInfo(uint8 *buf, uint32 *size)
{
// Interesting
*size = sizeof(CPlayerInfo);
INITSAVEBUF
WriteSaveBuf(buf, CWorld::Players[CWorld::PlayerInFocus].m_nMoney);
WriteSaveBuf(buf, CWorld::Players[CWorld::PlayerInFocus].m_WBState);
WriteSaveBuf(buf, CWorld::Players[CWorld::PlayerInFocus].m_nWBTime);
WriteSaveBuf(buf, CWorld::Players[CWorld::PlayerInFocus].m_nTrafficMultiplier);
WriteSaveBuf(buf, CWorld::Players[CWorld::PlayerInFocus].m_fRoadDensity);
WriteSaveBuf(buf, CWorld::Players[CWorld::PlayerInFocus].m_nVisibleMoney);
WriteSaveBuf(buf, CWorld::Players[CWorld::PlayerInFocus].m_nCollectedPackages);
WriteSaveBuf(buf, CWorld::Players[CWorld::PlayerInFocus].m_nTotalPackages);
WriteSaveBuf(buf, CWorld::Players[CWorld::PlayerInFocus].m_bInfiniteSprint);
WriteSaveBuf(buf, CWorld::Players[CWorld::PlayerInFocus].m_bFastReload);
WriteSaveBuf(buf, CWorld::Players[CWorld::PlayerInFocus].m_bGetOutOfJailFree);
WriteSaveBuf(buf, CWorld::Players[CWorld::PlayerInFocus].m_bGetOutOfHospitalFree);
for (int i = 0; i < sizeof(CWorld::Players[CWorld::PlayerInFocus].m_aPlayerName); i++) {
WriteSaveBuf(buf, CWorld::Players[CWorld::PlayerInFocus].m_aPlayerName[i]);
}
// Save struct is different
// VALIDATESAVEBUF(*size)
void
CPlayerInfo::SavePlayerInfo(uint8 *buf, uint32 *size)
{
// Interesting
*size = sizeof(CPlayerInfo);
INITSAVEBUF
WriteSaveBuf(buf, CWorld::Players[CWorld::PlayerInFocus].m_nMoney);
WriteSaveBuf(buf, CWorld::Players[CWorld::PlayerInFocus].m_WBState);
WriteSaveBuf(buf, CWorld::Players[CWorld::PlayerInFocus].m_nWBTime);
WriteSaveBuf(buf, CWorld::Players[CWorld::PlayerInFocus].m_nTrafficMultiplier);
WriteSaveBuf(buf, CWorld::Players[CWorld::PlayerInFocus].m_fRoadDensity);
WriteSaveBuf(buf, CWorld::Players[CWorld::PlayerInFocus].m_nVisibleMoney);
WriteSaveBuf(buf, CWorld::Players[CWorld::PlayerInFocus].m_nCollectedPackages);
WriteSaveBuf(buf, CWorld::Players[CWorld::PlayerInFocus].m_nTotalPackages);
WriteSaveBuf(buf, CWorld::Players[CWorld::PlayerInFocus].m_bInfiniteSprint);
WriteSaveBuf(buf, CWorld::Players[CWorld::PlayerInFocus].m_bFastReload);
WriteSaveBuf(buf, CWorld::Players[CWorld::PlayerInFocus].m_bGetOutOfJailFree);
WriteSaveBuf(buf, CWorld::Players[CWorld::PlayerInFocus].m_bGetOutOfHospitalFree);
for (int i = 0; i < sizeof(CWorld::Players[CWorld::PlayerInFocus].m_aPlayerName); i++) {
WriteSaveBuf(buf, CWorld::Players[CWorld::PlayerInFocus].m_aPlayerName[i]);
}
// Save struct is different
// VALIDATESAVEBUF(*size)
}
void
CPlayerInfo::LoadPlayerInfo(uint8 *buf, uint32 size)
{
INITSAVEBUF
CWorld::Players[CWorld::PlayerInFocus].m_nMoney = ReadSaveBuf<uint32>(buf);
CWorld::Players[CWorld::PlayerInFocus].m_WBState = ReadSaveBuf<int8>(buf);
CWorld::Players[CWorld::PlayerInFocus].m_nWBTime = ReadSaveBuf<uint32>(buf);
CWorld::Players[CWorld::PlayerInFocus].m_nTrafficMultiplier = ReadSaveBuf<int16>(buf);
CWorld::Players[CWorld::PlayerInFocus].m_fRoadDensity = ReadSaveBuf<float>(buf);
CWorld::Players[CWorld::PlayerInFocus].m_nVisibleMoney = ReadSaveBuf<int32>(buf);
CWorld::Players[CWorld::PlayerInFocus].m_nCollectedPackages = ReadSaveBuf<int32>(buf);
CWorld::Players[CWorld::PlayerInFocus].m_nTotalPackages = ReadSaveBuf<int32>(buf);
CWorld::Players[CWorld::PlayerInFocus].m_bInfiniteSprint = ReadSaveBuf<bool>(buf);
CWorld::Players[CWorld::PlayerInFocus].m_bFastReload = ReadSaveBuf<bool>(buf);
CWorld::Players[CWorld::PlayerInFocus].m_bGetOutOfJailFree = ReadSaveBuf<bool>(buf);
CWorld::Players[CWorld::PlayerInFocus].m_bGetOutOfHospitalFree = ReadSaveBuf<bool>(buf);
for (int i = 0; i < sizeof(CWorld::Players[CWorld::PlayerInFocus].m_aPlayerName); i++) {
CWorld::Players[CWorld::PlayerInFocus].m_aPlayerName[i] = ReadSaveBuf<char>(buf);
}
// Save struct is different
// VALIDATESAVEBUF(size)
void
CPlayerInfo::LoadPlayerInfo(uint8 *buf, uint32 size)
{
INITSAVEBUF
CWorld::Players[CWorld::PlayerInFocus].m_nMoney = ReadSaveBuf<uint32>(buf);
CWorld::Players[CWorld::PlayerInFocus].m_WBState = ReadSaveBuf<int8>(buf);
CWorld::Players[CWorld::PlayerInFocus].m_nWBTime = ReadSaveBuf<uint32>(buf);
CWorld::Players[CWorld::PlayerInFocus].m_nTrafficMultiplier = ReadSaveBuf<int16>(buf);
CWorld::Players[CWorld::PlayerInFocus].m_fRoadDensity = ReadSaveBuf<float>(buf);
CWorld::Players[CWorld::PlayerInFocus].m_nVisibleMoney = ReadSaveBuf<int32>(buf);
CWorld::Players[CWorld::PlayerInFocus].m_nCollectedPackages = ReadSaveBuf<int32>(buf);
CWorld::Players[CWorld::PlayerInFocus].m_nTotalPackages = ReadSaveBuf<int32>(buf);
CWorld::Players[CWorld::PlayerInFocus].m_bInfiniteSprint = ReadSaveBuf<bool>(buf);
CWorld::Players[CWorld::PlayerInFocus].m_bFastReload = ReadSaveBuf<bool>(buf);
CWorld::Players[CWorld::PlayerInFocus].m_bGetOutOfJailFree = ReadSaveBuf<bool>(buf);
CWorld::Players[CWorld::PlayerInFocus].m_bGetOutOfHospitalFree = ReadSaveBuf<bool>(buf);
for (int i = 0; i < sizeof(CWorld::Players[CWorld::PlayerInFocus].m_aPlayerName); i++) {
CWorld::Players[CWorld::PlayerInFocus].m_aPlayerName[i] = ReadSaveBuf<char>(buf);
}
// Save struct is different
// VALIDATESAVEBUF(size)
}
void
CPlayerInfo::FindClosestCarSectorList(CPtrList& carList, CPed* ped, float unk1, float unk2, float unk3, float unk4, float* lastCloseness, CVehicle** closestCarOutput)
{
for (CPtrNode* node = carList.first; node; node = node->next) {
CVehicle *car = (CVehicle*)node->item;
if(car->m_scanCode != CWorld::GetCurrentScanCode()) {
if (!car->bUsesCollision || !car->IsVehicle())
continue;
car->m_scanCode = CWorld::GetCurrentScanCode();
if (car->m_status != STATUS_WRECKED && car->m_status != STATUS_TRAIN_MOVING
&& (car->GetUp().z > 0.3f || (car->IsVehicle() && ((CVehicle*)car)->m_vehType == VEHICLE_TYPE_BIKE))) {
CVector carCentre = car->GetBoundCentre();
if (Abs(ped->GetPosition().z - carCentre.z) < 2.0f) {
float dist = (ped->GetPosition() - carCentre).Magnitude2D();
if (dist <= 10.0f && !CCranes::IsThisCarBeingCarriedByAnyCrane(car)) {
EvaluateCarPosition(car, ped, dist, lastCloseness, closestCarOutput);
}
}
}
}
}
void
CPlayerInfo::FindClosestCarSectorList(CPtrList& carList, CPed* ped, float unk1, float unk2, float unk3, float unk4, float* lastCloseness, CVehicle** closestCarOutput)
{
for (CPtrNode* node = carList.first; node; node = node->next) {
CVehicle *car = (CVehicle*)node->item;
if(car->m_scanCode != CWorld::GetCurrentScanCode()) {
if (!car->bUsesCollision || !car->IsVehicle())
continue;
car->m_scanCode = CWorld::GetCurrentScanCode();
if (car->m_status != STATUS_WRECKED && car->m_status != STATUS_TRAIN_MOVING
&& (car->GetUp().z > 0.3f || (car->IsVehicle() && ((CVehicle*)car)->m_vehType == VEHICLE_TYPE_BIKE))) {
CVector carCentre = car->GetBoundCentre();
if (Abs(ped->GetPosition().z - carCentre.z) < 2.0f) {
float dist = (ped->GetPosition() - carCentre).Magnitude2D();
if (dist <= 10.0f && !CCranes::IsThisCarBeingCarriedByAnyCrane(car)) {
EvaluateCarPosition(car, ped, dist, lastCloseness, closestCarOutput);
}
}
}
}
}
}
void
CPlayerInfo::Process(void)
{
// Unused taxi feature. Gives you a dollar for every second with a passenger. Can be toggled via 0x29A opcode.
bool startTaxiTimer = true;
if (m_bUnusedTaxiThing && m_pPed->bInVehicle) {
CVehicle *veh = m_pPed->m_pMyVehicle;
if ((veh->m_modelIndex == MI_TAXI || veh->m_modelIndex == MI_CABBIE || veh->m_modelIndex == MI_BORGNINE)
&& veh->pDriver == m_pPed && veh->m_nNumPassengers != 0) {
for (uint32 timePassed = CTimer::GetTimeInMilliseconds() - m_nUnusedTaxiTimer; timePassed >= 1000; m_nUnusedTaxiTimer += 1000) {
timePassed -= 1000;
++m_nMoney;
}
startTaxiTimer = false;
}
}
if (startTaxiTimer)
m_nUnusedTaxiTimer = CTimer::GetTimeInMilliseconds();
// The effect that makes money counter does while earning/losing money
if (m_nVisibleMoney != m_nMoney) {
int diff = m_nMoney - m_nVisibleMoney;
int diffAbs = Abs(diff);
int changeBy;
if (diffAbs > 100000)
changeBy = 12345;
else if (diffAbs > 10000)
changeBy = 1234;
else if (diffAbs > 1000)
changeBy = 123;
else if (diffAbs > 50)
changeBy = 42;
else
changeBy = 1;
if (diff < 0)
m_nVisibleMoney -= changeBy;
else
m_nVisibleMoney += changeBy;
}
if (!(CTimer::GetFrameCounter() & 15)) {
CVector2D playerPos = m_pPed->bInVehicle ? m_pPed->m_pMyVehicle->GetPosition() : m_pPed->GetPosition();
m_fRoadDensity = ThePaths.CalcRoadDensity(playerPos.x, playerPos.y);
}
m_fRoadDensity = clamp(m_fRoadDensity, 0.4f, 1.45f);
// Because vehicle enter/exit use same key binding.
bool enterOrExitVeh;
if (m_pPed->bVehExitWillBeInstant && m_pPed->bInVehicle)
enterOrExitVeh = CPad::GetPad(0)->ExitVehicleJustDown();
else
enterOrExitVeh = CPad::GetPad(0)->GetExitVehicle();
if (enterOrExitVeh && m_pPed->m_nPedState != PED_SNIPER_MODE && m_pPed->m_nPedState != PED_ROCKET_ODE) {
if (m_pPed->bInVehicle) {
if (!m_pRemoteVehicle) {
CEntity *surfaceBelowVeh = m_pPed->m_pMyVehicle->m_pCurGroundEntity;
if (!surfaceBelowVeh || !CBridge::ThisIsABridgeObjectMovingUp(surfaceBelowVeh->m_modelIndex)) {
CVehicle *veh = m_pPed->m_pMyVehicle;
if (!veh->IsBoat() || veh->m_nDoorLock == CARLOCK_LOCKED_PLAYER_INSIDE) {
// This condition will always return true, else block was probably WIP Miami code.
if (veh->m_vehType != VEHICLE_TYPE_BIKE || veh->m_nDoorLock == CARLOCK_LOCKED_PLAYER_INSIDE) {
if (veh->m_status != STATUS_WRECKED && veh->m_status != STATUS_TRAIN_MOVING && veh->m_nDoorLock != CARLOCK_LOCKED_PLAYER_INSIDE) {
if (veh->m_vecMoveSpeed.Magnitude() < 0.17f && CTimer::GetTimeScale() >= 0.5f && !veh->bIsInWater) {
m_pPed->SetObjective(OBJECTIVE_LEAVE_VEHICLE, veh);
}
}
} else {
CVector sth = 0.7f * veh->GetRight() + veh->GetPosition();
bool found = false;
float groundZ = CWorld::FindGroundZFor3DCoord(sth.x, sth.y, 2.0f + sth.z, &found);
if (found)
sth.z = 1.0f + groundZ;
m_pPed->m_nPedState = PED_IDLE;
m_pPed->SetMoveState(PEDMOVE_STILL);
CPed::PedSetOutCarCB(0, m_pPed);
CAnimManager::BlendAnimation(m_pPed->GetClump(), m_pPed->m_animGroup, ANIM_IDLE_STANCE, 100.0f);
CAnimManager::BlendAnimation(m_pPed->GetClump(), ASSOCGRP_STD, ANIM_FALL_LAND, 100.0f);
m_pPed->GetPosition() = sth;
m_pPed->SetMoveState(PEDMOVE_STILL);
m_pPed->m_vecMoveSpeed = veh->m_vecMoveSpeed;
}
} else {
// The code in here was under CPed::SetExitBoat in VC, did the same for here.
m_pPed->SetExitBoat(veh);
m_pPed->bTryingToReachDryLand = true;
}
}
}
} else {
// Enter vehicle
if (CPad::GetPad(0)->ExitVehicleJustDown()) {
bool weAreOnBoat = false;
float lastCloseness = 0.0f;
CVehicle *carBelow = nil;
CEntity *surfaceBelow = m_pPed->m_pCurrentPhysSurface;
if (surfaceBelow && surfaceBelow->IsVehicle()) {
carBelow = (CVehicle*)surfaceBelow;
if (carBelow->IsBoat()) {
weAreOnBoat = true;
m_pPed->bOnBoat = true;
#ifdef VC_PED_PORTS
if (carBelow->m_status != STATUS_WRECKED && carBelow->GetUp().z > 0.3f)
#else
if (carBelow->m_status != STATUS_WRECKED)
#endif
m_pPed->SetSeekBoatPosition(carBelow);
}
}
// Find closest car
if (!weAreOnBoat) {
float minX = m_pPed->GetPosition().x - 10.0f;
float maxX = 10.0f + m_pPed->GetPosition().x;
float minY = m_pPed->GetPosition().y - 10.0f;
float maxY = 10.0f + m_pPed->GetPosition().y;
int minXSector = CWorld::GetSectorIndexX(minX);
if (minXSector < 0) minXSector = 0;
int minYSector = CWorld::GetSectorIndexY(minY);
if (minYSector < 0) minYSector = 0;
int maxXSector = CWorld::GetSectorIndexX(maxX);
if (maxXSector > NUMSECTORS_X - 1) maxXSector = NUMSECTORS_X - 1;
int maxYSector = CWorld::GetSectorIndexY(maxY);
if (maxYSector > NUMSECTORS_Y - 1) maxYSector = NUMSECTORS_Y - 1;
CWorld::AdvanceCurrentScanCode();
for (int curY = minYSector; curY <= maxYSector; curY++) {
for (int curX = minXSector; curX <= maxXSector; curX++) {
CSector *sector = CWorld::GetSector(curX, curY);
FindClosestCarSectorList(sector->m_lists[ENTITYLIST_VEHICLES], m_pPed,
minX, minY, maxX, maxY, &lastCloseness, &carBelow);
FindClosestCarSectorList(sector->m_lists[ENTITYLIST_VEHICLES_OVERLAP], m_pPed,
minX, minY, maxX, maxY, &lastCloseness, &carBelow);
}
}
}
// carBelow is now closest vehicle
if (carBelow && !weAreOnBoat) {
if (carBelow->m_status == STATUS_TRAIN_NOT_MOVING) {
m_pPed->SetObjective(OBJECTIVE_ENTER_CAR_AS_PASSENGER, carBelow);
} else if (carBelow->IsBoat()) {
if (!carBelow->pDriver) {
m_pPed->m_vehEnterType = 0;
m_pPed->SetEnterCar(carBelow, m_pPed->m_vehEnterType);
}
} else {
m_pPed->SetObjective(OBJECTIVE_ENTER_CAR_AS_DRIVER, carBelow);
}
}
}
}
}
if (m_bInRemoteMode) {
uint32 timeWithoutRemoteCar = CTimer::GetTimeInMilliseconds() - m_nTimeLostRemoteCar;
if (CTimer::GetPreviousTimeInMilliseconds() - m_nTimeLostRemoteCar < 1000 && timeWithoutRemoteCar >= 1000 && m_WBState == WBSTATE_PLAYING) {
TheCamera.SetFadeColour(0, 0, 0);
TheCamera.Fade(1.0f, 0);
}
if (timeWithoutRemoteCar > 2000) {
if (m_WBState == WBSTATE_PLAYING) {
TheCamera.RestoreWithJumpCut();
TheCamera.SetFadeColour(0, 0, 0);
TheCamera.Fade(1.0f, 1);
TheCamera.Process();
CTimer::Stop();
CCullZones::ForceCullZoneCoors(TheCamera.GetPosition());
CRenderer::RequestObjectsInFrustum();
CStreaming::LoadAllRequestedModels(false);
CTimer::Update();
}
m_bInRemoteMode = false;
CWorld::Players[CWorld::PlayerInFocus].m_pRemoteVehicle = nil;
if (FindPlayerVehicle()) {
FindPlayerVehicle()->m_status = STATUS_PLAYER;
}
}
}
if (!(CTimer::GetFrameCounter() & 31)) {
CVehicle *veh = FindPlayerVehicle();
if (veh && m_pPed->bInVehicle && veh->GetUp().z < 0.0f
&& veh->m_vecMoveSpeed.Magnitude() < 0.05f && veh->IsCar() && !veh->bIsInWater) {
if (veh->GetUp().z < -0.5f) {
m_nUpsideDownCounter += 2;
} else {
m_nUpsideDownCounter++;
}
} else {
m_nUpsideDownCounter = 0;
}
if (m_nUpsideDownCounter > 6 && veh->bCanBeDamaged) {
veh->m_fHealth = 249.0f < veh->m_fHealth ? 249.0f : veh->m_fHealth;
if (veh->IsCar()) {
CAutomobile* car = (CAutomobile*)veh;
car->Damage.SetEngineStatus(225);
car->m_pSetOnFireEntity = nil;
}
}
}
if (FindPlayerVehicle()) {
CVehicle *veh = FindPlayerVehicle();
veh->m_nZoneLevel = -1;
for (int i = 0; i < ARRAY_SIZE(veh->pPassengers); i++) {
if (veh->pPassengers[i])
veh->pPassengers[i]->m_nZoneLevel = 0;
}
CStats::DistanceTravelledInVehicle += veh->m_fDistanceTravelled;
} else {
CStats::DistanceTravelledOnFoot += FindPlayerPed()->m_fDistanceTravelled;
}
void
CPlayerInfo::Process(void)
{
// Unused taxi feature. Gives you a dollar for every second with a passenger. Can be toggled via 0x29A opcode.
bool startTaxiTimer = true;
if (m_bUnusedTaxiThing && m_pPed->bInVehicle) {
CVehicle *veh = m_pPed->m_pMyVehicle;
if ((veh->m_modelIndex == MI_TAXI || veh->m_modelIndex == MI_CABBIE || veh->m_modelIndex == MI_BORGNINE)
&& veh->pDriver == m_pPed && veh->m_nNumPassengers != 0) {
for (uint32 timePassed = CTimer::GetTimeInMilliseconds() - m_nUnusedTaxiTimer; timePassed >= 1000; m_nUnusedTaxiTimer += 1000) {
timePassed -= 1000;
++m_nMoney;
}
startTaxiTimer = false;
}
}
if (startTaxiTimer)
m_nUnusedTaxiTimer = CTimer::GetTimeInMilliseconds();
// The effect that makes money counter does while earning/losing money
if (m_nVisibleMoney != m_nMoney) {
int diff = m_nMoney - m_nVisibleMoney;
int diffAbs = Abs(diff);
int changeBy;
if (diffAbs > 100000)
changeBy = 12345;
else if (diffAbs > 10000)
changeBy = 1234;
else if (diffAbs > 1000)
changeBy = 123;
else if (diffAbs > 50)
changeBy = 42;
else
changeBy = 1;
if (diff < 0)
m_nVisibleMoney -= changeBy;
else
m_nVisibleMoney += changeBy;
}
if (!(CTimer::GetFrameCounter() & 15)) {
CVector2D playerPos = m_pPed->bInVehicle ? m_pPed->m_pMyVehicle->GetPosition() : m_pPed->GetPosition();
m_fRoadDensity = ThePaths.CalcRoadDensity(playerPos.x, playerPos.y);
}
m_fRoadDensity = clamp(m_fRoadDensity, 0.4f, 1.45f);
// Because vehicle enter/exit use same key binding.
bool enterOrExitVeh;
if (m_pPed->bVehExitWillBeInstant && m_pPed->bInVehicle)
enterOrExitVeh = CPad::GetPad(0)->ExitVehicleJustDown();
else
enterOrExitVeh = CPad::GetPad(0)->GetExitVehicle();
if (enterOrExitVeh && m_pPed->m_nPedState != PED_SNIPER_MODE && m_pPed->m_nPedState != PED_ROCKET_ODE) {
if (m_pPed->bInVehicle) {
if (!m_pRemoteVehicle) {
CEntity *surfaceBelowVeh = m_pPed->m_pMyVehicle->m_pCurGroundEntity;
if (!surfaceBelowVeh || !CBridge::ThisIsABridgeObjectMovingUp(surfaceBelowVeh->m_modelIndex)) {
CVehicle *veh = m_pPed->m_pMyVehicle;
if (!veh->IsBoat() || veh->m_nDoorLock == CARLOCK_LOCKED_PLAYER_INSIDE) {
// This condition will always return true, else block was probably WIP Miami code.
if (veh->m_vehType != VEHICLE_TYPE_BIKE || veh->m_nDoorLock == CARLOCK_LOCKED_PLAYER_INSIDE) {
if (veh->m_status != STATUS_WRECKED && veh->m_status != STATUS_TRAIN_MOVING && veh->m_nDoorLock != CARLOCK_LOCKED_PLAYER_INSIDE) {
if (veh->m_vecMoveSpeed.Magnitude() < 0.17f && CTimer::GetTimeScale() >= 0.5f && !veh->bIsInWater) {
m_pPed->SetObjective(OBJECTIVE_LEAVE_VEHICLE, veh);
}
}
} else {
CVector sth = 0.7f * veh->GetRight() + veh->GetPosition();
bool found = false;
float groundZ = CWorld::FindGroundZFor3DCoord(sth.x, sth.y, 2.0f + sth.z, &found);
if (found)
sth.z = 1.0f + groundZ;
m_pPed->m_nPedState = PED_IDLE;
m_pPed->SetMoveState(PEDMOVE_STILL);
CPed::PedSetOutCarCB(0, m_pPed);
CAnimManager::BlendAnimation(m_pPed->GetClump(), m_pPed->m_animGroup, ANIM_IDLE_STANCE, 100.0f);
CAnimManager::BlendAnimation(m_pPed->GetClump(), ASSOCGRP_STD, ANIM_FALL_LAND, 100.0f);
m_pPed->GetPosition() = sth;
m_pPed->SetMoveState(PEDMOVE_STILL);
m_pPed->m_vecMoveSpeed = veh->m_vecMoveSpeed;
}
} else {
// The code in here was under CPed::SetExitBoat in VC, did the same for here.
m_pPed->SetExitBoat(veh);
m_pPed->bTryingToReachDryLand = true;
}
}
}
} else {
// Enter vehicle
if (CPad::GetPad(0)->ExitVehicleJustDown()) {
bool weAreOnBoat = false;
float lastCloseness = 0.0f;
CVehicle *carBelow = nil;
CEntity *surfaceBelow = m_pPed->m_pCurrentPhysSurface;
if (surfaceBelow && surfaceBelow->IsVehicle()) {
carBelow = (CVehicle*)surfaceBelow;
if (carBelow->IsBoat()) {
weAreOnBoat = true;
m_pPed->bOnBoat = true;
#ifdef VC_PED_PORTS
if (carBelow->m_status != STATUS_WRECKED && carBelow->GetUp().z > 0.3f)
#else
if (carBelow->m_status != STATUS_WRECKED)
#endif
m_pPed->SetSeekBoatPosition(carBelow);
}
}
// Find closest car
if (!weAreOnBoat) {
float minX = m_pPed->GetPosition().x - 10.0f;
float maxX = 10.0f + m_pPed->GetPosition().x;
float minY = m_pPed->GetPosition().y - 10.0f;
float maxY = 10.0f + m_pPed->GetPosition().y;
int minXSector = CWorld::GetSectorIndexX(minX);
if (minXSector < 0) minXSector = 0;
int minYSector = CWorld::GetSectorIndexY(minY);
if (minYSector < 0) minYSector = 0;
int maxXSector = CWorld::GetSectorIndexX(maxX);
if (maxXSector > NUMSECTORS_X - 1) maxXSector = NUMSECTORS_X - 1;
int maxYSector = CWorld::GetSectorIndexY(maxY);
if (maxYSector > NUMSECTORS_Y - 1) maxYSector = NUMSECTORS_Y - 1;
CWorld::AdvanceCurrentScanCode();
for (int curY = minYSector; curY <= maxYSector; curY++) {
for (int curX = minXSector; curX <= maxXSector; curX++) {
CSector *sector = CWorld::GetSector(curX, curY);
FindClosestCarSectorList(sector->m_lists[ENTITYLIST_VEHICLES], m_pPed,
minX, minY, maxX, maxY, &lastCloseness, &carBelow);
FindClosestCarSectorList(sector->m_lists[ENTITYLIST_VEHICLES_OVERLAP], m_pPed,
minX, minY, maxX, maxY, &lastCloseness, &carBelow);
}
}
}
// carBelow is now closest vehicle
if (carBelow && !weAreOnBoat) {
if (carBelow->m_status == STATUS_TRAIN_NOT_MOVING) {
m_pPed->SetObjective(OBJECTIVE_ENTER_CAR_AS_PASSENGER, carBelow);
} else if (carBelow->IsBoat()) {
if (!carBelow->pDriver) {
m_pPed->m_vehEnterType = 0;
m_pPed->SetEnterCar(carBelow, m_pPed->m_vehEnterType);
}
} else {
m_pPed->SetObjective(OBJECTIVE_ENTER_CAR_AS_DRIVER, carBelow);
}
}
}
}
}
if (m_bInRemoteMode) {
uint32 timeWithoutRemoteCar = CTimer::GetTimeInMilliseconds() - m_nTimeLostRemoteCar;
if (CTimer::GetPreviousTimeInMilliseconds() - m_nTimeLostRemoteCar < 1000 && timeWithoutRemoteCar >= 1000 && m_WBState == WBSTATE_PLAYING) {
TheCamera.SetFadeColour(0, 0, 0);
TheCamera.Fade(1.0f, 0);
}
if (timeWithoutRemoteCar > 2000) {
if (m_WBState == WBSTATE_PLAYING) {
TheCamera.RestoreWithJumpCut();
TheCamera.SetFadeColour(0, 0, 0);
TheCamera.Fade(1.0f, 1);
TheCamera.Process();
CTimer::Stop();
CCullZones::ForceCullZoneCoors(TheCamera.GetPosition());
CRenderer::RequestObjectsInFrustum();
CStreaming::LoadAllRequestedModels(false);
CTimer::Update();
}
m_bInRemoteMode = false;
CWorld::Players[CWorld::PlayerInFocus].m_pRemoteVehicle = nil;
if (FindPlayerVehicle()) {
FindPlayerVehicle()->m_status = STATUS_PLAYER;
}
}
}
if (!(CTimer::GetFrameCounter() & 31)) {
CVehicle *veh = FindPlayerVehicle();
if (veh && m_pPed->bInVehicle && veh->GetUp().z < 0.0f
&& veh->m_vecMoveSpeed.Magnitude() < 0.05f && veh->IsCar() && !veh->bIsInWater) {
if (veh->GetUp().z < -0.5f) {
m_nUpsideDownCounter += 2;
} else {
m_nUpsideDownCounter++;
}
} else {
m_nUpsideDownCounter = 0;
}
if (m_nUpsideDownCounter > 6 && veh->bCanBeDamaged) {
veh->m_fHealth = 249.0f < veh->m_fHealth ? 249.0f : veh->m_fHealth;
if (veh->IsCar()) {
CAutomobile* car = (CAutomobile*)veh;
car->Damage.SetEngineStatus(225);
car->m_pSetOnFireEntity = nil;
}
}
}
if (FindPlayerVehicle()) {
CVehicle *veh = FindPlayerVehicle();
veh->m_nZoneLevel = -1;
for (int i = 0; i < ARRAY_SIZE(veh->pPassengers); i++) {
if (veh->pPassengers[i])
veh->pPassengers[i]->m_nZoneLevel = 0;
}
CStats::DistanceTravelledInVehicle += veh->m_fDistanceTravelled;
} else {
CStats::DistanceTravelledOnFoot += FindPlayerPed()->m_fDistanceTravelled;
}
}
STARTPATCHES

View File

@ -1,171 +1,171 @@
#include "common.h"
#include "patcher.h"
#include "main.h"
#include "PlayerSkin.h"
#include "TxdStore.h"
#include "rtbmp.h"
#include "ClumpModelInfo.h"
#include "VisibilityPlugins.h"
#include "World.h"
#include "PlayerInfo.h"
#include "CdStream.h"
#include "FileMgr.h"
#include "Directory.h"
#include "RwHelper.h"
#include "Timer.h"
#include "Lights.h"
int CPlayerSkin::m_txdSlot;
void
FindPlayerDff(uint32 &offset, uint32 &size)
{
int file;
CDirectory::DirectoryInfo info;
file = CFileMgr::OpenFile("models\\gta3.dir", "rb");
do {
if (!CFileMgr::Read(file, (char*)&info, sizeof(CDirectory::DirectoryInfo)))
return;
} while (strcasecmp("player.dff", info.name) != 0);
offset = info.offset;
size = info.size;
}
void
LoadPlayerDff(void)
{
RwStream *stream;
RwMemory mem;
uint32 offset, size;
uint8 *buffer;
bool streamWasAdded = false;
if (CdStreamGetNumImages() == 0) {
CdStreamAddImage("models\\gta3.img");
streamWasAdded = true;
}
FindPlayerDff(offset, size);
buffer = (uint8*)RwMallocAlign(size << 11, 2048);
CdStreamRead(0, buffer, offset, size);
CdStreamSync(0);
mem.start = buffer;
mem.length = size << 11;
stream = RwStreamOpen(rwSTREAMMEMORY, rwSTREAMREAD, &mem);
if (RwStreamFindChunk(stream, rwID_CLUMP, nil, nil))
gpPlayerClump = RpClumpStreamRead(stream);
RwStreamClose(stream, &mem);
RwFreeAlign(buffer);
if (streamWasAdded)
CdStreamRemoveImages();
}
void
CPlayerSkin::Initialise(void)
{
m_txdSlot = CTxdStore::AddTxdSlot("skin");
CTxdStore::Create(m_txdSlot);
CTxdStore::AddRef(m_txdSlot);
}
void
CPlayerSkin::Shutdown(void)
{
CTxdStore::RemoveTxdSlot(m_txdSlot);
}
RwTexture *
CPlayerSkin::GetSkinTexture(const char *texName)
{
RwTexture *tex;
RwRaster *raster;
int32 width, height, depth, format;
CTxdStore::PushCurrentTxd();
CTxdStore::SetCurrentTxd(m_txdSlot);
tex = RwTextureRead(texName, NULL);
CTxdStore::PopCurrentTxd();
if (tex) return tex;
if (strcmp(DEFAULT_SKIN_NAME, texName) == 0)
sprintf(gString, "models\\generic\\player.bmp");
else
sprintf(gString, "skins\\%s.bmp", texName);
if (RwImage *image = RtBMPImageRead(gString)) {
RwImageFindRasterFormat(image, rwRASTERTYPETEXTURE, &width, &height, &depth, &format);
raster = RwRasterCreate(width, height, depth, format);
RwRasterSetFromImage(raster, image);
tex = RwTextureCreate(raster);
RwTextureSetName(tex, texName);
#ifdef FIX_BUGS
RwTextureSetFilterMode(tex, rwFILTERLINEAR); // filtering bugfix from VC
#endif
RwTexDictionaryAddTexture(CTxdStore::GetSlot(m_txdSlot)->texDict, tex);
RwImageDestroy(image);
}
return tex;
}
void
CPlayerSkin::BeginFrontendSkinEdit(void)
{
LoadPlayerDff();
RpClumpForAllAtomics(gpPlayerClump, CClumpModelInfo::SetAtomicRendererCB, CVisibilityPlugins::RenderPlayerCB);
CWorld::Players[0].LoadPlayerSkin();
gOldFov = CDraw::GetFOV();
CDraw::SetFOV(30.0f);
}
void
CPlayerSkin::EndFrontendSkinEdit(void)
{
RpClumpDestroy(gpPlayerClump);
gpPlayerClump = NULL;
CDraw::SetFOV(gOldFov);
}
void
CPlayerSkin::RenderFrontendSkinEdit(void)
{
static float rotation = 0.0f;
RwRGBAReal AmbientColor = { 0.65f, 0.65f, 0.65f, 1.0f };
RwV3d pos = { 1.35f, 0.35f, 7.725f };
const RwV3d axis1 = { 1.0f, 0.0f, 0.0f };
const RwV3d axis2 = { 0.0f, 0.0f, 1.0f };
static uint32 LastFlash = 0;
RwFrame *frame = RpClumpGetFrame(gpPlayerClump);
if (CTimer::GetTimeInMillisecondsPauseMode() - LastFlash > 7) {
rotation += 2.0f;
if (rotation > 360.0f)
rotation -= 360.0f;
LastFlash = CTimer::GetTimeInMillisecondsPauseMode();
}
RwFrameTransform(frame, RwFrameGetMatrix(RwCameraGetFrame(Scene.camera)), rwCOMBINEREPLACE);
RwFrameTranslate(frame, &pos, rwCOMBINEPRECONCAT);
RwFrameRotate(frame, &axis1, -90.0f, rwCOMBINEPRECONCAT);
RwFrameRotate(frame, &axis2, rotation, rwCOMBINEPRECONCAT);
RwFrameUpdateObjects(frame);
SetAmbientColours(&AmbientColor);
RpClumpRender(gpPlayerClump);
}
STARTPATCHES
InjectHook(0x59B9B0, &CPlayerSkin::Initialise, PATCH_JUMP);
InjectHook(0x59B9E0, &CPlayerSkin::Shutdown, PATCH_JUMP);
InjectHook(0x59B9F0, &CPlayerSkin::GetSkinTexture, PATCH_JUMP);
InjectHook(0x59BC70, &CPlayerSkin::BeginFrontendSkinEdit, PATCH_JUMP);
InjectHook(0x59BCB0, &CPlayerSkin::EndFrontendSkinEdit, PATCH_JUMP);
InjectHook(0x59BCE0, &CPlayerSkin::RenderFrontendSkinEdit, PATCH_JUMP);
#include "common.h"
#include "patcher.h"
#include "main.h"
#include "PlayerSkin.h"
#include "TxdStore.h"
#include "rtbmp.h"
#include "ClumpModelInfo.h"
#include "VisibilityPlugins.h"
#include "World.h"
#include "PlayerInfo.h"
#include "CdStream.h"
#include "FileMgr.h"
#include "Directory.h"
#include "RwHelper.h"
#include "Timer.h"
#include "Lights.h"
int CPlayerSkin::m_txdSlot;
void
FindPlayerDff(uint32 &offset, uint32 &size)
{
int file;
CDirectory::DirectoryInfo info;
file = CFileMgr::OpenFile("models\\gta3.dir", "rb");
do {
if (!CFileMgr::Read(file, (char*)&info, sizeof(CDirectory::DirectoryInfo)))
return;
} while (strcasecmp("player.dff", info.name) != 0);
offset = info.offset;
size = info.size;
}
void
LoadPlayerDff(void)
{
RwStream *stream;
RwMemory mem;
uint32 offset, size;
uint8 *buffer;
bool streamWasAdded = false;
if (CdStreamGetNumImages() == 0) {
CdStreamAddImage("models\\gta3.img");
streamWasAdded = true;
}
FindPlayerDff(offset, size);
buffer = (uint8*)RwMallocAlign(size << 11, 2048);
CdStreamRead(0, buffer, offset, size);
CdStreamSync(0);
mem.start = buffer;
mem.length = size << 11;
stream = RwStreamOpen(rwSTREAMMEMORY, rwSTREAMREAD, &mem);
if (RwStreamFindChunk(stream, rwID_CLUMP, nil, nil))
gpPlayerClump = RpClumpStreamRead(stream);
RwStreamClose(stream, &mem);
RwFreeAlign(buffer);
if (streamWasAdded)
CdStreamRemoveImages();
}
void
CPlayerSkin::Initialise(void)
{
m_txdSlot = CTxdStore::AddTxdSlot("skin");
CTxdStore::Create(m_txdSlot);
CTxdStore::AddRef(m_txdSlot);
}
void
CPlayerSkin::Shutdown(void)
{
CTxdStore::RemoveTxdSlot(m_txdSlot);
}
RwTexture *
CPlayerSkin::GetSkinTexture(const char *texName)
{
RwTexture *tex;
RwRaster *raster;
int32 width, height, depth, format;
CTxdStore::PushCurrentTxd();
CTxdStore::SetCurrentTxd(m_txdSlot);
tex = RwTextureRead(texName, NULL);
CTxdStore::PopCurrentTxd();
if (tex) return tex;
if (strcmp(DEFAULT_SKIN_NAME, texName) == 0)
sprintf(gString, "models\\generic\\player.bmp");
else
sprintf(gString, "skins\\%s.bmp", texName);
if (RwImage *image = RtBMPImageRead(gString)) {
RwImageFindRasterFormat(image, rwRASTERTYPETEXTURE, &width, &height, &depth, &format);
raster = RwRasterCreate(width, height, depth, format);
RwRasterSetFromImage(raster, image);
tex = RwTextureCreate(raster);
RwTextureSetName(tex, texName);
#ifdef FIX_BUGS
RwTextureSetFilterMode(tex, rwFILTERLINEAR); // filtering bugfix from VC
#endif
RwTexDictionaryAddTexture(CTxdStore::GetSlot(m_txdSlot)->texDict, tex);
RwImageDestroy(image);
}
return tex;
}
void
CPlayerSkin::BeginFrontendSkinEdit(void)
{
LoadPlayerDff();
RpClumpForAllAtomics(gpPlayerClump, CClumpModelInfo::SetAtomicRendererCB, CVisibilityPlugins::RenderPlayerCB);
CWorld::Players[0].LoadPlayerSkin();
gOldFov = CDraw::GetFOV();
CDraw::SetFOV(30.0f);
}
void
CPlayerSkin::EndFrontendSkinEdit(void)
{
RpClumpDestroy(gpPlayerClump);
gpPlayerClump = NULL;
CDraw::SetFOV(gOldFov);
}
void
CPlayerSkin::RenderFrontendSkinEdit(void)
{
static float rotation = 0.0f;
RwRGBAReal AmbientColor = { 0.65f, 0.65f, 0.65f, 1.0f };
RwV3d pos = { 1.35f, 0.35f, 7.725f };
const RwV3d axis1 = { 1.0f, 0.0f, 0.0f };
const RwV3d axis2 = { 0.0f, 0.0f, 1.0f };
static uint32 LastFlash = 0;
RwFrame *frame = RpClumpGetFrame(gpPlayerClump);
if (CTimer::GetTimeInMillisecondsPauseMode() - LastFlash > 7) {
rotation += 2.0f;
if (rotation > 360.0f)
rotation -= 360.0f;
LastFlash = CTimer::GetTimeInMillisecondsPauseMode();
}
RwFrameTransform(frame, RwFrameGetMatrix(RwCameraGetFrame(Scene.camera)), rwCOMBINEREPLACE);
RwFrameTranslate(frame, &pos, rwCOMBINEPRECONCAT);
RwFrameRotate(frame, &axis1, -90.0f, rwCOMBINEPRECONCAT);
RwFrameRotate(frame, &axis2, rotation, rwCOMBINEPRECONCAT);
RwFrameUpdateObjects(frame);
SetAmbientColours(&AmbientColor);
RpClumpRender(gpPlayerClump);
}
STARTPATCHES
InjectHook(0x59B9B0, &CPlayerSkin::Initialise, PATCH_JUMP);
InjectHook(0x59B9E0, &CPlayerSkin::Shutdown, PATCH_JUMP);
InjectHook(0x59B9F0, &CPlayerSkin::GetSkinTexture, PATCH_JUMP);
InjectHook(0x59BC70, &CPlayerSkin::BeginFrontendSkinEdit, PATCH_JUMP);
InjectHook(0x59BCB0, &CPlayerSkin::EndFrontendSkinEdit, PATCH_JUMP);
InjectHook(0x59BCE0, &CPlayerSkin::RenderFrontendSkinEdit, PATCH_JUMP);
ENDPATCHES

View File

@ -1,119 +1,119 @@
#include "common.h"
#include "Debug.h"
#include "obrstr.h"
char obrstr[128];
char obrstr2[128];
void ObrInt(int32 n1)
{
IntToStr(n1, obrstr);
CDebug::DebugAddText(obrstr);
}
void ObrInt2(int32 n1, int32 n2)
{
IntToStr(n1, obrstr);
strcat(obrstr, " ");
IntToStr(n2, obrstr2);
strcat(obrstr, obrstr2);
CDebug::DebugAddText(obrstr);
}
void ObrInt3(int32 n1, int32 n2, int32 n3)
{
IntToStr(n1, obrstr);
strcat(obrstr, " ");
IntToStr(n2, obrstr2);
strcat(obrstr, obrstr2);
strcat(obrstr, " ");
IntToStr(n3, obrstr2);
strcat(obrstr, obrstr2);
CDebug::DebugAddText(obrstr);
}
void ObrInt4(int32 n1, int32 n2, int32 n3, int32 n4)
{
IntToStr(n1, obrstr);
strcat(obrstr, " ");
IntToStr(n2, obrstr2);
strcat(obrstr, obrstr2);
strcat(obrstr, " ");
IntToStr(n3, obrstr2);
strcat(obrstr, obrstr2);
strcat(obrstr, " ");
IntToStr(n4, obrstr2);
strcat(obrstr, obrstr2);
CDebug::DebugAddText(obrstr);
}
void ObrInt5(int32 n1, int32 n2, int32 n3, int32 n4, int32 n5)
{
IntToStr(n1, obrstr);
strcat(obrstr, " ");
IntToStr(n2, obrstr2);
strcat(obrstr, obrstr2);
strcat(obrstr, " ");
IntToStr(n3, obrstr2);
strcat(obrstr, obrstr2);
strcat(obrstr, " ");
IntToStr(n4, obrstr2);
strcat(obrstr, obrstr2);
strcat(obrstr, " ");
IntToStr(n5, obrstr2);
strcat(obrstr, obrstr2);
CDebug::DebugAddText(obrstr);
}
void ObrInt6(int32 n1, int32 n2, int32 n3, int32 n4, int32 n5, int32 n6)
{
IntToStr(n1, obrstr);
strcat(obrstr, " ");
IntToStr(n2, obrstr2);
strcat(obrstr, obrstr2);
strcat(obrstr, " ");
IntToStr(n3, obrstr2);
strcat(obrstr, obrstr2);
strcat(obrstr, " ");
IntToStr(n4, obrstr2);
strcat(obrstr, obrstr2);
strcat(obrstr, " ");
IntToStr(n5, obrstr2);
strcat(obrstr, obrstr2);
strcat(obrstr, " ");
IntToStr(n6, obrstr2);
strcat(obrstr, obrstr2);
CDebug::DebugAddText(obrstr);
}
void IntToStr(int32 inNum, char *outStr)
{
bool isNeg = inNum < 0;
if (isNeg) {
inNum = -inNum;
*outStr = '-';
}
int16 digits = 1;
if (inNum > 9) {
int32 _inNum = inNum;
do {
digits++;
_inNum /= 10;
} while (_inNum > 9);
}
int32 strSize = digits;
if (isNeg)
strSize++;
char *pStr = &outStr[strSize];
int32 i = 0;
do {
*(pStr-- - 1) = (inNum % 10) + '0';
inNum /= 10;
} while (++i < strSize);
outStr[strSize] = '\0';
#include "common.h"
#include "Debug.h"
#include "obrstr.h"
char obrstr[128];
char obrstr2[128];
void ObrInt(int32 n1)
{
IntToStr(n1, obrstr);
CDebug::DebugAddText(obrstr);
}
void ObrInt2(int32 n1, int32 n2)
{
IntToStr(n1, obrstr);
strcat(obrstr, " ");
IntToStr(n2, obrstr2);
strcat(obrstr, obrstr2);
CDebug::DebugAddText(obrstr);
}
void ObrInt3(int32 n1, int32 n2, int32 n3)
{
IntToStr(n1, obrstr);
strcat(obrstr, " ");
IntToStr(n2, obrstr2);
strcat(obrstr, obrstr2);
strcat(obrstr, " ");
IntToStr(n3, obrstr2);
strcat(obrstr, obrstr2);
CDebug::DebugAddText(obrstr);
}
void ObrInt4(int32 n1, int32 n2, int32 n3, int32 n4)
{
IntToStr(n1, obrstr);
strcat(obrstr, " ");
IntToStr(n2, obrstr2);
strcat(obrstr, obrstr2);
strcat(obrstr, " ");
IntToStr(n3, obrstr2);
strcat(obrstr, obrstr2);
strcat(obrstr, " ");
IntToStr(n4, obrstr2);
strcat(obrstr, obrstr2);
CDebug::DebugAddText(obrstr);
}
void ObrInt5(int32 n1, int32 n2, int32 n3, int32 n4, int32 n5)
{
IntToStr(n1, obrstr);
strcat(obrstr, " ");
IntToStr(n2, obrstr2);
strcat(obrstr, obrstr2);
strcat(obrstr, " ");
IntToStr(n3, obrstr2);
strcat(obrstr, obrstr2);
strcat(obrstr, " ");
IntToStr(n4, obrstr2);
strcat(obrstr, obrstr2);
strcat(obrstr, " ");
IntToStr(n5, obrstr2);
strcat(obrstr, obrstr2);
CDebug::DebugAddText(obrstr);
}
void ObrInt6(int32 n1, int32 n2, int32 n3, int32 n4, int32 n5, int32 n6)
{
IntToStr(n1, obrstr);
strcat(obrstr, " ");
IntToStr(n2, obrstr2);
strcat(obrstr, obrstr2);
strcat(obrstr, " ");
IntToStr(n3, obrstr2);
strcat(obrstr, obrstr2);
strcat(obrstr, " ");
IntToStr(n4, obrstr2);
strcat(obrstr, obrstr2);
strcat(obrstr, " ");
IntToStr(n5, obrstr2);
strcat(obrstr, obrstr2);
strcat(obrstr, " ");
IntToStr(n6, obrstr2);
strcat(obrstr, obrstr2);
CDebug::DebugAddText(obrstr);
}
void IntToStr(int32 inNum, char *outStr)
{
bool isNeg = inNum < 0;
if (isNeg) {
inNum = -inNum;
*outStr = '-';
}
int16 digits = 1;
if (inNum > 9) {
int32 _inNum = inNum;
do {
digits++;
_inNum /= 10;
} while (_inNum > 9);
}
int32 strSize = digits;
if (isNeg)
strSize++;
char *pStr = &outStr[strSize];
int32 i = 0;
do {
*(pStr-- - 1) = (inNum % 10) + '0';
inNum /= 10;
} while (++i < strSize);
outStr[strSize] = '\0';
}

View File

@ -1,9 +1,9 @@
#pragma once
void ObrInt(int32 n1);
void ObrInt2(int32 n1, int32 n2);
void ObrInt3(int32 n1, int32 n2, int32 n3);
void ObrInt4(int32 n1, int32 n2, int32 n3, int32 n4);
void ObrInt5(int32 n1, int32 n2, int32 n3, int32 n4, int32 n5);
void ObrInt6(int32 n1, int32 n2, int32 n3, int32 n4, int32 n5, int32 n6);
#pragma once
void ObrInt(int32 n1);
void ObrInt2(int32 n1, int32 n2);
void ObrInt3(int32 n1, int32 n2, int32 n3);
void ObrInt4(int32 n1, int32 n2, int32 n3, int32 n4);
void ObrInt5(int32 n1, int32 n2, int32 n3, int32 n4, int32 n5);
void ObrInt6(int32 n1, int32 n2, int32 n3, int32 n4, int32 n5, int32 n6);
void IntToStr(int32 inNum, char *outStr);

View File

@ -1,121 +1,121 @@
#ifndef MASTER
#include "common.h"
#include "Font.h"
#include "Frontend.h"
#include "Timer.h"
#include "Text.h"
#define MAX_TIMERS (50)
#define MAX_MS_COLLECTED (40)
// enables frame time output
#define FRAMETIME
struct sTimeBar
{
char name[20];
float startTime;
float endTime;
int32 unk;
};
struct
{
sTimeBar Timers[MAX_TIMERS];
uint32 count;
} TimerBar;
float MaxTimes[MAX_TIMERS];
float MaxFrameTime;
uint32 curMS;
uint32 msCollected[MAX_MS_COLLECTED];
#ifdef FRAMETIME
float FrameInitTime;
#endif
void tbInit()
{
TimerBar.count = 0;
uint32 i = CTimer::GetFrameCounter() & 0x7F;
if (i == 0) {
do
MaxTimes[i++] = 0.0f;
while (i != MAX_TIMERS);
#ifdef FRAMETIME
MaxFrameTime = 0.0f;
#endif
}
#ifdef FRAMETIME
FrameInitTime = (float)CTimer::GetCurrentTimeInCycles() / (float)CTimer::GetCyclesPerFrame();
#endif
}
void tbStartTimer(int32 unk, char *name)
{
strcpy(TimerBar.Timers[TimerBar.count].name, name);
TimerBar.Timers[TimerBar.count].unk = unk;
TimerBar.Timers[TimerBar.count].startTime = (float)CTimer::GetCurrentTimeInCycles() / (float)CTimer::GetCyclesPerFrame();
TimerBar.count++;
}
void tbEndTimer(char* name)
{
uint32 n = 1500;
for (uint32 i = 0; i < TimerBar.count; i++) {
if (strcmp(name, TimerBar.Timers[i].name) == 0)
n = i;
}
assert(n != 1500);
TimerBar.Timers[n].endTime = (float)CTimer::GetCurrentTimeInCycles() / (float)CTimer::GetCyclesPerFrame();
}
float Diag_GetFPS()
{
return 39000.0f / (msCollected[(curMS - 1) % MAX_MS_COLLECTED] - msCollected[curMS % MAX_MS_COLLECTED]);
}
void tbDisplay()
{
char temp[200];
wchar wtemp[200];
#ifdef FRAMETIME
float FrameEndTime = (float)CTimer::GetCurrentTimeInCycles() / (float)CTimer::GetCyclesPerFrame();
#endif
msCollected[(curMS++) % MAX_MS_COLLECTED] = RsTimer();
CFont::SetBackgroundOff();
CFont::SetBackgroundColor(CRGBA(0, 0, 0, 128));
CFont::SetScale(0.48f, 1.12f);
CFont::SetCentreOff();
CFont::SetJustifyOff();
CFont::SetWrapx(640.0f);
CFont::SetRightJustifyOff();
CFont::SetPropOn();
CFont::SetFontStyle(FONT_BANK);
sprintf(temp, "FPS: %.2f", Diag_GetFPS());
AsciiToUnicode(temp, wtemp);
CFont::SetColor(CRGBA(255, 255, 255, 255));
if (!CMenuManager::m_PrefsMarketing || !CMenuManager::m_PrefsDisableTutorials) {
CFont::PrintString(RsGlobal.maximumWidth * (4.0f / DEFAULT_SCREEN_WIDTH), RsGlobal.maximumHeight * (4.0f / DEFAULT_SCREEN_HEIGHT), wtemp);
#ifndef FINAL
// Timers output (my own implementation)
for (uint32 i = 0; i < TimerBar.count; i++) {
MaxTimes[i] = max(MaxTimes[i], TimerBar.Timers[i].endTime - TimerBar.Timers[i].startTime);
sprintf(temp, "%s: %.2f", &TimerBar.Timers[i].name[0], MaxTimes[i]);
AsciiToUnicode(temp, wtemp);
CFont::PrintString(RsGlobal.maximumWidth * (4.0f / DEFAULT_SCREEN_WIDTH), RsGlobal.maximumHeight * ((8.0f * (i + 2)) / DEFAULT_SCREEN_HEIGHT), wtemp);
}
#ifdef FRAMETIME
MaxFrameTime = max(MaxFrameTime, FrameEndTime - FrameInitTime);
sprintf(temp, "Frame Time: %.2f", MaxFrameTime);
AsciiToUnicode(temp, wtemp);
CFont::PrintString(RsGlobal.maximumWidth * (4.0f / DEFAULT_SCREEN_WIDTH), RsGlobal.maximumHeight * ((8.0f * (TimerBar.count + 4)) / DEFAULT_SCREEN_HEIGHT), wtemp);
#endif // FRAMETIME
#endif // !FINAL
}
}
#ifndef MASTER
#include "common.h"
#include "Font.h"
#include "Frontend.h"
#include "Timer.h"
#include "Text.h"
#define MAX_TIMERS (50)
#define MAX_MS_COLLECTED (40)
// enables frame time output
#define FRAMETIME
struct sTimeBar
{
char name[20];
float startTime;
float endTime;
int32 unk;
};
struct
{
sTimeBar Timers[MAX_TIMERS];
uint32 count;
} TimerBar;
float MaxTimes[MAX_TIMERS];
float MaxFrameTime;
uint32 curMS;
uint32 msCollected[MAX_MS_COLLECTED];
#ifdef FRAMETIME
float FrameInitTime;
#endif
void tbInit()
{
TimerBar.count = 0;
uint32 i = CTimer::GetFrameCounter() & 0x7F;
if (i == 0) {
do
MaxTimes[i++] = 0.0f;
while (i != MAX_TIMERS);
#ifdef FRAMETIME
MaxFrameTime = 0.0f;
#endif
}
#ifdef FRAMETIME
FrameInitTime = (float)CTimer::GetCurrentTimeInCycles() / (float)CTimer::GetCyclesPerFrame();
#endif
}
void tbStartTimer(int32 unk, char *name)
{
strcpy(TimerBar.Timers[TimerBar.count].name, name);
TimerBar.Timers[TimerBar.count].unk = unk;
TimerBar.Timers[TimerBar.count].startTime = (float)CTimer::GetCurrentTimeInCycles() / (float)CTimer::GetCyclesPerFrame();
TimerBar.count++;
}
void tbEndTimer(char* name)
{
uint32 n = 1500;
for (uint32 i = 0; i < TimerBar.count; i++) {
if (strcmp(name, TimerBar.Timers[i].name) == 0)
n = i;
}
assert(n != 1500);
TimerBar.Timers[n].endTime = (float)CTimer::GetCurrentTimeInCycles() / (float)CTimer::GetCyclesPerFrame();
}
float Diag_GetFPS()
{
return 39000.0f / (msCollected[(curMS - 1) % MAX_MS_COLLECTED] - msCollected[curMS % MAX_MS_COLLECTED]);
}
void tbDisplay()
{
char temp[200];
wchar wtemp[200];
#ifdef FRAMETIME
float FrameEndTime = (float)CTimer::GetCurrentTimeInCycles() / (float)CTimer::GetCyclesPerFrame();
#endif
msCollected[(curMS++) % MAX_MS_COLLECTED] = RsTimer();
CFont::SetBackgroundOff();
CFont::SetBackgroundColor(CRGBA(0, 0, 0, 128));
CFont::SetScale(0.48f, 1.12f);
CFont::SetCentreOff();
CFont::SetJustifyOff();
CFont::SetWrapx(640.0f);
CFont::SetRightJustifyOff();
CFont::SetPropOn();
CFont::SetFontStyle(FONT_BANK);
sprintf(temp, "FPS: %.2f", Diag_GetFPS());
AsciiToUnicode(temp, wtemp);
CFont::SetColor(CRGBA(255, 255, 255, 255));
if (!CMenuManager::m_PrefsMarketing || !CMenuManager::m_PrefsDisableTutorials) {
CFont::PrintString(RsGlobal.maximumWidth * (4.0f / DEFAULT_SCREEN_WIDTH), RsGlobal.maximumHeight * (4.0f / DEFAULT_SCREEN_HEIGHT), wtemp);
#ifndef FINAL
// Timers output (my own implementation)
for (uint32 i = 0; i < TimerBar.count; i++) {
MaxTimes[i] = max(MaxTimes[i], TimerBar.Timers[i].endTime - TimerBar.Timers[i].startTime);
sprintf(temp, "%s: %.2f", &TimerBar.Timers[i].name[0], MaxTimes[i]);
AsciiToUnicode(temp, wtemp);
CFont::PrintString(RsGlobal.maximumWidth * (4.0f / DEFAULT_SCREEN_WIDTH), RsGlobal.maximumHeight * ((8.0f * (i + 2)) / DEFAULT_SCREEN_HEIGHT), wtemp);
}
#ifdef FRAMETIME
MaxFrameTime = max(MaxFrameTime, FrameEndTime - FrameInitTime);
sprintf(temp, "Frame Time: %.2f", MaxFrameTime);
AsciiToUnicode(temp, wtemp);
CFont::PrintString(RsGlobal.maximumWidth * (4.0f / DEFAULT_SCREEN_WIDTH), RsGlobal.maximumHeight * ((8.0f * (TimerBar.count + 4)) / DEFAULT_SCREEN_HEIGHT), wtemp);
#endif // FRAMETIME
#endif // !FINAL
}
}
#endif // !MASTER

View File

@ -1,6 +1,6 @@
#pragma once
void tbInit();
void tbStartTimer(int32, char*);
void tbEndTimer(char*);
#pragma once
void tbInit();
void tbStartTimer(int32, char*);
void tbEndTimer(char*);
void tbDisplay();

View File

@ -1,12 +1,12 @@
#pragma once
#include "Entity.h"
class CSolid : public CEntity
{
public:
CSolid(void) {
m_type = ENTITY_TYPE_BUILDING;
bUsesCollision = true;
}
#pragma once
#include "Entity.h"
class CSolid : public CEntity
{
public:
CSolid(void) {
m_type = ENTITY_TYPE_BUILDING;
bUsesCollision = true;
}
};

View File

@ -1,14 +1,14 @@
#pragma once
#include "ClumpModelInfo.h"
class CMloModelInfo : public CClumpModelInfo
{
public:
float field_34; // draw distance?
int firstInstance;
int lastInstance;
public:
CMloModelInfo(void) : CClumpModelInfo(MITYPE_MLO) {}
void ConstructClump();
#pragma once
#include "ClumpModelInfo.h"
class CMloModelInfo : public CClumpModelInfo
{
public:
float field_34; // draw distance?
int firstInstance;
int lastInstance;
public:
CMloModelInfo(void) : CClumpModelInfo(MITYPE_MLO) {}
void ConstructClump();
};

View File

@ -1,12 +1,12 @@
#pragma once
#include "ClumpModelInfo.h"
class CXtraCompsModelInfo : public CClumpModelInfo
{
int field_34;
public:
CXtraCompsModelInfo(void) : CClumpModelInfo(MITYPE_XTRACOMPS) { field_34 = 0; }
void SetClump(RpClump*) {};
void Shutdown(void) {};
#pragma once
#include "ClumpModelInfo.h"
class CXtraCompsModelInfo : public CClumpModelInfo
{
int field_34;
public:
CXtraCompsModelInfo(void) : CClumpModelInfo(MITYPE_XTRACOMPS) { field_34 = 0; }
void SetClump(RpClump*) {};
void Shutdown(void) {};
};

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -12,26 +12,26 @@ public:
class CRegisteredMotionBlurStreak
{
public:
uintptr m_id;
uint8 m_red;
uint8 m_green;
uint8 m_blue;
CVector m_pos1[3];
CVector m_pos2[3];
uintptr m_id;
uint8 m_red;
uint8 m_green;
uint8 m_blue;
CVector m_pos1[3];
CVector m_pos2[3];
bool m_isValid[3];
void Update(void);
void Render(void);
void Update(void);
void Render(void);
};
class CMotionBlurStreaks
{
static CRegisteredMotionBlurStreak aStreaks[NUMMBLURSTREAKS];
public:
static void Init(void);
static void Update(void);
static void Init(void);
static void Update(void);
static void RegisterStreak(uintptr id, uint8 r, uint8 g, uint8 b, CVector p1, CVector p2);
static void Render(void);
static void Render(void);
};
struct CBulletTrace
@ -133,18 +133,18 @@ enum
BRIGHTLIGHT_REAR = BRIGHTLIGHT_REAR_LONG,
};
class CBrightLight
{
public:
CVector m_pos;
CVector m_up;
CVector m_side;
CVector m_front;
float m_camDist;
uint8 m_type;
uint8 m_red;
uint8 m_green;
uint8 m_blue;
class CBrightLight
{
public:
CVector m_pos;
CVector m_up;
CVector m_side;
CVector m_front;
float m_camDist;
uint8 m_type;
uint8 m_red;
uint8 m_green;
uint8 m_blue;
};
class CBrightLights
@ -152,11 +152,11 @@ class CBrightLights
static int NumBrightLights;
static CBrightLight aBrightLights[NUMBRIGHTLIGHTS];
public:
static void Init(void);
static void Init(void);
static void RegisterOne(CVector pos, CVector up, CVector side, CVector front,
uint8 type, uint8 red = 0, uint8 green = 0, uint8 blue = 0);
static void Render(void);
static void RenderOutGeometryBuffer(void);
static void Render(void);
static void RenderOutGeometryBuffer(void);
};
@ -169,12 +169,12 @@ enum
class CShinyText
{
public:
CVector m_verts[4];
CVector2D m_texCoords[4];
float m_camDist;
uint8 m_type;
uint8 m_red;
uint8 m_green;
CVector m_verts[4];
CVector2D m_texCoords[4];
float m_camDist;
uint8 m_type;
uint8 m_red;
uint8 m_green;
uint8 m_blue;
};
@ -183,12 +183,12 @@ class CShinyTexts
static int NumShinyTexts;
static CShinyText aShinyTexts[NUMSHINYTEXTS];
public:
static void Init(void);
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);
static void Render(void);
static void RenderOutGeometryBuffer(void);
static void Render(void);
static void RenderOutGeometryBuffer(void);
};
class CMoneyMessage

View File

@ -1,41 +1,41 @@
#include "common.h"
#include "TexList.h"
#include "rtbmp.h"
#include "FileMgr.h"
bool CTexList::ms_nTexUsed[MAX_TEXUSED];
void
CTexList::Initialise()
{}
void
CTexList::Shutdown()
{}
RwTexture *
CTexList::SetTexture(int32 slot, char *name)
{
return nil;
}
int32
CTexList::GetFirstFreeTexture()
{
for (int32 i = 0; i < MAX_TEXUSED; i++)
if (!ms_nTexUsed[i])
return i;
return -1;
}
RwTexture *
CTexList::LoadFileNameTexture(char *name)
{
return SetTexture(GetFirstFreeTexture(), name);
}
void
CTexList::LoadGlobalTextureList()
{
CFileMgr::SetDir("TEXTURES");
#include "common.h"
#include "TexList.h"
#include "rtbmp.h"
#include "FileMgr.h"
bool CTexList::ms_nTexUsed[MAX_TEXUSED];
void
CTexList::Initialise()
{}
void
CTexList::Shutdown()
{}
RwTexture *
CTexList::SetTexture(int32 slot, char *name)
{
return nil;
}
int32
CTexList::GetFirstFreeTexture()
{
for (int32 i = 0; i < MAX_TEXUSED; i++)
if (!ms_nTexUsed[i])
return i;
return -1;
}
RwTexture *
CTexList::LoadFileNameTexture(char *name)
{
return SetTexture(GetFirstFreeTexture(), name);
}
void
CTexList::LoadGlobalTextureList()
{
CFileMgr::SetDir("TEXTURES");
}

View File

@ -1,14 +1,14 @@
#pragma once
class CTexList
{
enum { MAX_TEXUSED = 400, };
static bool ms_nTexUsed[MAX_TEXUSED];
public:
static void Initialise();
static void Shutdown();
static RwTexture *SetTexture(int32 slot, char *name);
static int32 GetFirstFreeTexture();
static RwTexture *LoadFileNameTexture(char *name);
static void LoadGlobalTextureList();
#pragma once
class CTexList
{
enum { MAX_TEXUSED = 400, };
static bool ms_nTexUsed[MAX_TEXUSED];
public:
static void Initialise();
static void Shutdown();
static RwTexture *SetTexture(int32 slot, char *name);
static int32 GetFirstFreeTexture();
static RwTexture *LoadFileNameTexture(char *name);
static void LoadGlobalTextureList();
};

View File

@ -1,18 +1,18 @@
#pragma once
class CDate
{
public:
int m_nSecond;
int m_nMinute;
int m_nHour;
int m_nDay;
int m_nMonth;
int m_nYear;
CDate();
bool operator>(const CDate &right);
bool operator<(const CDate &right);
bool operator==(const CDate &right);
void PopulateDateFields(int8 &second, int8 &minute, int8 &hour, int8 &day, int8 &month, int16 year);
#pragma once
class CDate
{
public:
int m_nSecond;
int m_nMinute;
int m_nHour;
int m_nDay;
int m_nMonth;
int m_nYear;
CDate();
bool operator>(const CDate &right);
bool operator<(const CDate &right);
bool operator==(const CDate &right);
void PopulateDateFields(int8 &second, int8 &minute, int8 &hour, int8 &day, int8 &month, int16 year);
};

View File

@ -1,43 +1,43 @@
#pragma once
#include "PCSave.h"
#define SLOT_COUNT (8)
bool GenericSave(int file);
bool GenericLoad();
bool ReadInSizeofSaveFileBuffer(int32 &file, uint32 &size);
bool ReadDataFromFile(int32 file, uint8 *buf, uint32 size);
bool CloseFile(int32 file);
void DoGameSpecificStuffAfterSucessLoad();
bool CheckSlotDataValid(int32 slot);
void MakeSpaceForSizeInBufferPointer(uint8 *&presize, uint8 *&buf, uint8 *&postsize);
void CopySizeAndPreparePointer(uint8 *&buf, uint8 *&postbuf, uint8 *&postbuf2, uint32 &unused, uint32 &size);
void DoGameSpecificStuffBeforeSave();
void MakeValidSaveName(int32 slot);
wchar *GetSavedGameDateAndTime(int32 slot);
wchar *GetNameOfSavedGame(int32 slot);
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];
extern wchar (&SlotFileName)[SLOT_COUNT][260];
extern wchar (&SlotSaveDate)[SLOT_COUNT][70];
extern int &CheckSum;
extern enum eLevelName &m_LevelToLoad;
extern int (&Slots)[SLOT_COUNT+1];
extern bool &b_FoundRecentSavedGameWantToLoad;
extern bool &JustLoadedDontFadeInYet;
extern bool &StillToFadeOut;
extern uint32 &TimeStartedCountingForFade;
extern uint32 &TimeToStayFadedBeforeFadeOut;
extern char SaveFileNameJustSaved[260]; // 8F2570
#pragma once
#include "PCSave.h"
#define SLOT_COUNT (8)
bool GenericSave(int file);
bool GenericLoad();
bool ReadInSizeofSaveFileBuffer(int32 &file, uint32 &size);
bool ReadDataFromFile(int32 file, uint8 *buf, uint32 size);
bool CloseFile(int32 file);
void DoGameSpecificStuffAfterSucessLoad();
bool CheckSlotDataValid(int32 slot);
void MakeSpaceForSizeInBufferPointer(uint8 *&presize, uint8 *&buf, uint8 *&postsize);
void CopySizeAndPreparePointer(uint8 *&buf, uint8 *&postbuf, uint8 *&postbuf2, uint32 &unused, uint32 &size);
void DoGameSpecificStuffBeforeSave();
void MakeValidSaveName(int32 slot);
wchar *GetSavedGameDateAndTime(int32 slot);
wchar *GetNameOfSavedGame(int32 slot);
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];
extern wchar (&SlotFileName)[SLOT_COUNT][260];
extern wchar (&SlotSaveDate)[SLOT_COUNT][70];
extern int &CheckSum;
extern enum eLevelName &m_LevelToLoad;
extern int (&Slots)[SLOT_COUNT+1];
extern bool &b_FoundRecentSavedGameWantToLoad;
extern bool &JustLoadedDontFadeInYet;
extern bool &StillToFadeOut;
extern uint32 &TimeStartedCountingForFade;
extern uint32 &TimeToStayFadedBeforeFadeOut;
extern char SaveFileNameJustSaved[260]; // 8F2570
const char TopLineEmptyFile[] = "THIS FILE IS NOT VALID YET";

File diff suppressed because it is too large Load Diff

View File

@ -1,194 +1,194 @@
#include "common.h"
#include "patcher.h"
#include "Pager.h"
#include "Timer.h"
#include "Messages.h"
#include "Hud.h"
#include "Camera.h"
void
CPager::Init()
{
ClearMessages();
m_nNumDisplayLetters = 8;
}
void
CPager::Process()
{
if (m_messages[0].m_pText != nil && m_messages[0].m_nCurrentPosition >= (int32)m_messages[0].m_nStringLength) {
m_messages[0].m_pText = nil;
uint16 i = 0;
while (i < NUMPAGERMESSAGES-1) {
if (m_messages[i + 1].m_pText == nil) break;
m_messages[i] = m_messages[i + 1];
i++;
}
m_messages[i].m_pText = nil;
if (m_messages[0].m_pText != nil)
CMessages::AddToPreviousBriefArray(
m_messages[0].m_pText,
m_messages[0].m_nNumber[0],
m_messages[0].m_nNumber[1],
m_messages[0].m_nNumber[2],
m_messages[0].m_nNumber[3],
m_messages[0].m_nNumber[4],
m_messages[0].m_nNumber[5],
0);
}
Display();
if (m_messages[0].m_pText != nil) {
if (TheCamera.m_WideScreenOn || !CHud::m_Wants_To_Draw_Hud || CHud::m_BigMessage[0][0] || CHud::m_BigMessage[2][0]) {
RestartCurrentMessage();
} else {
if (CTimer::GetTimeInMilliseconds() > m_messages[0].m_nTimeToChangePosition) {
m_messages[0].m_nCurrentPosition++;
m_messages[0].m_nTimeToChangePosition = CTimer::GetTimeInMilliseconds() + m_messages[0].m_nSpeedMs;
}
}
}
}
void
CPager::Display()
{
wchar outstr1[256];
wchar outstr2[260];
wchar *pText = m_messages[0].m_pText;
uint16 i = 0;
if (pText != nil) {
CMessages::InsertNumberInString(
pText,
m_messages[0].m_nNumber[0],
m_messages[0].m_nNumber[1],
m_messages[0].m_nNumber[2],
m_messages[0].m_nNumber[3],
m_messages[0].m_nNumber[4],
m_messages[0].m_nNumber[5],
outstr1);
for (; i < m_nNumDisplayLetters; i++) {
int pos = m_messages[0].m_nCurrentPosition + i;
if (pos >= 0) {
if (!outstr1[pos]) break;
outstr2[i] = outstr1[pos];
} else {
outstr2[i] = ' ';
}
}
}
outstr2[i] = '\0';
CHud::SetPagerMessage(outstr2);
}
void
CPager::AddMessage(wchar *str, uint16 speed, uint16 priority, uint16 a5)
{
uint16 size = CMessages::GetWideStringLength(str);
for (int32 i = 0; i < NUMPAGERMESSAGES; i++) {
if (m_messages[i].m_pText) {
if (m_messages[i].m_nPriority >= priority)
continue;
for (int j = NUMPAGERMESSAGES-1; j > i; j--)
m_messages[j] = m_messages[j-1];
}
m_messages[i].m_pText = str;
m_messages[i].m_nSpeedMs = speed;
m_messages[i].m_nPriority = priority;
m_messages[i].field_10 = a5;
m_messages[i].m_nCurrentPosition = -(m_nNumDisplayLetters + 10);
m_messages[i].m_nTimeToChangePosition = CTimer::GetTimeInMilliseconds() + speed;
m_messages[i].m_nStringLength = size;
m_messages[i].m_nNumber[0] = -1;
m_messages[i].m_nNumber[1] = -1;
m_messages[i].m_nNumber[2] = -1;
m_messages[i].m_nNumber[3] = -1;
m_messages[i].m_nNumber[4] = -1;
m_messages[i].m_nNumber[5] = -1;
if (i == 0)
CMessages::AddToPreviousBriefArray(
m_messages[0].m_pText,
m_messages[0].m_nNumber[0],
m_messages[0].m_nNumber[1],
m_messages[0].m_nNumber[2],
m_messages[0].m_nNumber[3],
m_messages[0].m_nNumber[4],
m_messages[0].m_nNumber[5],
nil);
return;
}
}
void
CPager::AddMessageWithNumber(wchar *str, int32 n1, int32 n2, int32 n3, int32 n4, int32 n5, int32 n6, uint16 speed, uint16 priority, uint16 a11)
{
wchar nstr[520];
CMessages::InsertNumberInString(str, n1, n2, n3, n4, n5, n6, nstr);
uint16 size = CMessages::GetWideStringLength(nstr);
for (int32 i = 0; i < NUMPAGERMESSAGES; i++) {
if (m_messages[i].m_pText) {
if (m_messages[i].m_nPriority >= priority)
continue;
for (int j = NUMPAGERMESSAGES-1; j > i; j--)
m_messages[j] = m_messages[j - 1];
}
m_messages[i].m_pText = str;
m_messages[i].m_nSpeedMs = speed;
m_messages[i].m_nPriority = priority;
m_messages[i].field_10 = a11;
m_messages[i].m_nCurrentPosition = -(m_nNumDisplayLetters + 10);
m_messages[i].m_nTimeToChangePosition = CTimer::GetTimeInMilliseconds() + speed;
m_messages[i].m_nStringLength = size;
m_messages[i].m_nNumber[0] = n1;
m_messages[i].m_nNumber[1] = n2;
m_messages[i].m_nNumber[2] = n3;
m_messages[i].m_nNumber[3] = n4;
m_messages[i].m_nNumber[4] = n5;
m_messages[i].m_nNumber[5] = n6;
if (i == 0)
CMessages::AddToPreviousBriefArray(
m_messages[0].m_pText,
m_messages[0].m_nNumber[0],
m_messages[0].m_nNumber[1],
m_messages[0].m_nNumber[2],
m_messages[0].m_nNumber[3],
m_messages[0].m_nNumber[4],
m_messages[0].m_nNumber[5],
nil);
return;
}
}
void
CPager::ClearMessages()
{
for (int32 i = 0; i < NUMPAGERMESSAGES; i++)
m_messages[i].m_pText = nil;
}
void
CPager::RestartCurrentMessage()
{
if (m_messages[0].m_pText != nil) {
m_messages[0].m_nCurrentPosition = -(m_nNumDisplayLetters + 10);
m_messages[0].m_nTimeToChangePosition = CTimer::GetTimeInMilliseconds() + m_messages[0].m_nSpeedMs;
}
}
STARTPATCHES
InjectHook(0x52B6F0, &CPager::Init, PATCH_JUMP);
InjectHook(0x52B740, &CPager::Process, PATCH_JUMP);
InjectHook(0x52B890, &CPager::Display, PATCH_JUMP);
InjectHook(0x52B940, &CPager::AddMessage, PATCH_JUMP);
InjectHook(0x52BB50, &CPager::AddMessageWithNumber, PATCH_JUMP);
InjectHook(0x52BE50, &CPager::RestartCurrentMessage, PATCH_JUMP);
InjectHook(0x52BE00, &CPager::ClearMessages, PATCH_JUMP);
#include "common.h"
#include "patcher.h"
#include "Pager.h"
#include "Timer.h"
#include "Messages.h"
#include "Hud.h"
#include "Camera.h"
void
CPager::Init()
{
ClearMessages();
m_nNumDisplayLetters = 8;
}
void
CPager::Process()
{
if (m_messages[0].m_pText != nil && m_messages[0].m_nCurrentPosition >= (int32)m_messages[0].m_nStringLength) {
m_messages[0].m_pText = nil;
uint16 i = 0;
while (i < NUMPAGERMESSAGES-1) {
if (m_messages[i + 1].m_pText == nil) break;
m_messages[i] = m_messages[i + 1];
i++;
}
m_messages[i].m_pText = nil;
if (m_messages[0].m_pText != nil)
CMessages::AddToPreviousBriefArray(
m_messages[0].m_pText,
m_messages[0].m_nNumber[0],
m_messages[0].m_nNumber[1],
m_messages[0].m_nNumber[2],
m_messages[0].m_nNumber[3],
m_messages[0].m_nNumber[4],
m_messages[0].m_nNumber[5],
0);
}
Display();
if (m_messages[0].m_pText != nil) {
if (TheCamera.m_WideScreenOn || !CHud::m_Wants_To_Draw_Hud || CHud::m_BigMessage[0][0] || CHud::m_BigMessage[2][0]) {
RestartCurrentMessage();
} else {
if (CTimer::GetTimeInMilliseconds() > m_messages[0].m_nTimeToChangePosition) {
m_messages[0].m_nCurrentPosition++;
m_messages[0].m_nTimeToChangePosition = CTimer::GetTimeInMilliseconds() + m_messages[0].m_nSpeedMs;
}
}
}
}
void
CPager::Display()
{
wchar outstr1[256];
wchar outstr2[260];
wchar *pText = m_messages[0].m_pText;
uint16 i = 0;
if (pText != nil) {
CMessages::InsertNumberInString(
pText,
m_messages[0].m_nNumber[0],
m_messages[0].m_nNumber[1],
m_messages[0].m_nNumber[2],
m_messages[0].m_nNumber[3],
m_messages[0].m_nNumber[4],
m_messages[0].m_nNumber[5],
outstr1);
for (; i < m_nNumDisplayLetters; i++) {
int pos = m_messages[0].m_nCurrentPosition + i;
if (pos >= 0) {
if (!outstr1[pos]) break;
outstr2[i] = outstr1[pos];
} else {
outstr2[i] = ' ';
}
}
}
outstr2[i] = '\0';
CHud::SetPagerMessage(outstr2);
}
void
CPager::AddMessage(wchar *str, uint16 speed, uint16 priority, uint16 a5)
{
uint16 size = CMessages::GetWideStringLength(str);
for (int32 i = 0; i < NUMPAGERMESSAGES; i++) {
if (m_messages[i].m_pText) {
if (m_messages[i].m_nPriority >= priority)
continue;
for (int j = NUMPAGERMESSAGES-1; j > i; j--)
m_messages[j] = m_messages[j-1];
}
m_messages[i].m_pText = str;
m_messages[i].m_nSpeedMs = speed;
m_messages[i].m_nPriority = priority;
m_messages[i].field_10 = a5;
m_messages[i].m_nCurrentPosition = -(m_nNumDisplayLetters + 10);
m_messages[i].m_nTimeToChangePosition = CTimer::GetTimeInMilliseconds() + speed;
m_messages[i].m_nStringLength = size;
m_messages[i].m_nNumber[0] = -1;
m_messages[i].m_nNumber[1] = -1;
m_messages[i].m_nNumber[2] = -1;
m_messages[i].m_nNumber[3] = -1;
m_messages[i].m_nNumber[4] = -1;
m_messages[i].m_nNumber[5] = -1;
if (i == 0)
CMessages::AddToPreviousBriefArray(
m_messages[0].m_pText,
m_messages[0].m_nNumber[0],
m_messages[0].m_nNumber[1],
m_messages[0].m_nNumber[2],
m_messages[0].m_nNumber[3],
m_messages[0].m_nNumber[4],
m_messages[0].m_nNumber[5],
nil);
return;
}
}
void
CPager::AddMessageWithNumber(wchar *str, int32 n1, int32 n2, int32 n3, int32 n4, int32 n5, int32 n6, uint16 speed, uint16 priority, uint16 a11)
{
wchar nstr[520];
CMessages::InsertNumberInString(str, n1, n2, n3, n4, n5, n6, nstr);
uint16 size = CMessages::GetWideStringLength(nstr);
for (int32 i = 0; i < NUMPAGERMESSAGES; i++) {
if (m_messages[i].m_pText) {
if (m_messages[i].m_nPriority >= priority)
continue;
for (int j = NUMPAGERMESSAGES-1; j > i; j--)
m_messages[j] = m_messages[j - 1];
}
m_messages[i].m_pText = str;
m_messages[i].m_nSpeedMs = speed;
m_messages[i].m_nPriority = priority;
m_messages[i].field_10 = a11;
m_messages[i].m_nCurrentPosition = -(m_nNumDisplayLetters + 10);
m_messages[i].m_nTimeToChangePosition = CTimer::GetTimeInMilliseconds() + speed;
m_messages[i].m_nStringLength = size;
m_messages[i].m_nNumber[0] = n1;
m_messages[i].m_nNumber[1] = n2;
m_messages[i].m_nNumber[2] = n3;
m_messages[i].m_nNumber[3] = n4;
m_messages[i].m_nNumber[4] = n5;
m_messages[i].m_nNumber[5] = n6;
if (i == 0)
CMessages::AddToPreviousBriefArray(
m_messages[0].m_pText,
m_messages[0].m_nNumber[0],
m_messages[0].m_nNumber[1],
m_messages[0].m_nNumber[2],
m_messages[0].m_nNumber[3],
m_messages[0].m_nNumber[4],
m_messages[0].m_nNumber[5],
nil);
return;
}
}
void
CPager::ClearMessages()
{
for (int32 i = 0; i < NUMPAGERMESSAGES; i++)
m_messages[i].m_pText = nil;
}
void
CPager::RestartCurrentMessage()
{
if (m_messages[0].m_pText != nil) {
m_messages[0].m_nCurrentPosition = -(m_nNumDisplayLetters + 10);
m_messages[0].m_nTimeToChangePosition = CTimer::GetTimeInMilliseconds() + m_messages[0].m_nSpeedMs;
}
}
STARTPATCHES
InjectHook(0x52B6F0, &CPager::Init, PATCH_JUMP);
InjectHook(0x52B740, &CPager::Process, PATCH_JUMP);
InjectHook(0x52B890, &CPager::Display, PATCH_JUMP);
InjectHook(0x52B940, &CPager::AddMessage, PATCH_JUMP);
InjectHook(0x52BB50, &CPager::AddMessageWithNumber, PATCH_JUMP);
InjectHook(0x52BE50, &CPager::RestartCurrentMessage, PATCH_JUMP);
InjectHook(0x52BE00, &CPager::ClearMessages, PATCH_JUMP);
ENDPATCHES

View File

@ -1,28 +1,28 @@
#pragma once
struct PagerMessage {
wchar *m_pText;
uint16 m_nSpeedMs;
int16 m_nCurrentPosition;
uint16 m_nStringLength;
uint16 m_nPriority;
uint32 m_nTimeToChangePosition;
int16 field_10;
int32 m_nNumber[6];
};
#define NUMPAGERMESSAGES 8
class CPager
{
int16 m_nNumDisplayLetters;
PagerMessage m_messages[NUMPAGERMESSAGES];
public:
void Init();
void Process();
void Display();
void AddMessage(wchar*, uint16, uint16, uint16);
void AddMessageWithNumber(wchar *str, int32 n1, int32 n2, int32 n3, int32 n4, int32 n5, int32 n6, uint16 speed, uint16 priority, uint16 a11);
void ClearMessages();
void RestartCurrentMessage();
#pragma once
struct PagerMessage {
wchar *m_pText;
uint16 m_nSpeedMs;
int16 m_nCurrentPosition;
uint16 m_nStringLength;
uint16 m_nPriority;
uint32 m_nTimeToChangePosition;
int16 field_10;
int32 m_nNumber[6];
};
#define NUMPAGERMESSAGES 8
class CPager
{
int16 m_nNumDisplayLetters;
PagerMessage m_messages[NUMPAGERMESSAGES];
public:
void Init();
void Process();
void Display();
void AddMessage(wchar*, uint16, uint16, uint16);
void AddMessageWithNumber(wchar *str, int32 n1, int32 n2, int32 n3, int32 n4, int32 n5, int32 n6, uint16 speed, uint16 priority, uint16 a11);
void ClearMessages();
void RestartCurrentMessage();
};

View File

@ -1,324 +1,324 @@
#include "common.h"
#include "patcher.h"
#include "FileMgr.h"
#include "Frontend.h"
#include "Messages.h"
#include "Text.h"
static wchar WideErrorString[25];
CText &TheText = *(CText*)0x941520;
CText::CText(void)
{
encoding = 'e';
memset(WideErrorString, 0, sizeof(WideErrorString));
}
void
CText::Load(void)
{
uint8 *filedata;
char filename[32], type[4];
int length;
int offset, sectlen;
Unload();
filedata = new uint8[0x40000];
CFileMgr::SetDir("TEXT");
switch(CMenuManager::m_PrefsLanguage){
case LANGUAGE_AMERICAN:
sprintf(filename, "AMERICAN.GXT");
break;
case LANGUAGE_FRENCH:
sprintf(filename, "FRENCH.GXT");
break;
case LANGUAGE_GERMAN:
sprintf(filename, "GERMAN.GXT");
break;
case LANGUAGE_ITALIAN:
sprintf(filename, "ITALIAN.GXT");
break;
case LANGUAGE_SPANISH:
sprintf(filename, "SPANISH.GXT");
break;
#ifdef MORE_LANGUAGES
case LANGUAGE_RUSSIAN:
sprintf(filename, "RUSSIAN.GXT");
break;
#endif
}
length = CFileMgr::LoadFile(filename, filedata, 0x40000, "rb");
CFileMgr::SetDir("");
offset = 0;
while(offset < length){
type[0] = filedata[offset++];
type[1] = filedata[offset++];
type[2] = filedata[offset++];
type[3] = filedata[offset++];
sectlen = (int)filedata[offset+3]<<24 | (int)filedata[offset+2]<<16 |
(int)filedata[offset+1]<<8 | (int)filedata[offset+0];
offset += 4;
if(sectlen != 0){
if(strncmp(type, "TKEY", 4) == 0)
keyArray.Load(sectlen, filedata, &offset);
else if(strncmp(type, "TDAT", 4) == 0)
data.Load(sectlen, filedata, &offset);
else
offset += sectlen;
}
}
keyArray.Update(data.chars);
delete[] filedata;
}
void
CText::Unload(void)
{
CMessages::ClearAllMessagesDisplayedByGame();
data.Unload();
keyArray.Unload();
}
wchar*
CText::Get(const char *key)
{
return keyArray.Search(key);
}
wchar UpperCaseTable[128] = {
128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138,
139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149,
150, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137,
138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148,
149, 173, 173, 175, 176, 177, 178, 179, 180, 181, 182,
183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193,
194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204,
205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215,
216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226,
227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237,
238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248,
249, 250, 251, 252, 253, 254, 255
};
wchar FrenchUpperCaseTable[128] = {
128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138,
139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149,
150, 65, 65, 65, 65, 132, 133, 69, 69, 69, 69, 73, 73,
73, 73, 79, 79, 79, 79, 85, 85, 85, 85, 173, 173, 175,
176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186,
187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197,
198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208,
209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219,
220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230,
231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241,
242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252,
253, 254, 255
};
wchar
CText::GetUpperCase(wchar c)
{
switch (encoding)
{
case 'e':
if (c >= 'a' && c <= 'z')
return c - 32;
break;
case 'f':
if (c >= 'a' && c <= 'z')
return c - 32;
if (c >= 128 && c <= 255)
return FrenchUpperCaseTable[c-128];
break;
case 'g':
case 'i':
case 's':
if (c >= 'a' && c <= 'z')
return c - 32;
if (c >= 128 && c <= 255)
return UpperCaseTable[c-128];
break;
default:
break;
}
return c;
}
void
CText::UpperCase(wchar *s)
{
while(*s){
*s = GetUpperCase(*s);
s++;
}
}
void
CKeyArray::Load(uint32 length, uint8 *data, int *offset)
{
uint32 i;
uint8 *rawbytes;
numEntries = length / sizeof(CKeyEntry);
entries = new CKeyEntry[numEntries];
rawbytes = (uint8*)entries;
for(i = 0; i < length; i++)
rawbytes[i] = data[(*offset)++];
}
void
CKeyArray::Unload(void)
{
delete[] entries;
entries = nil;
numEntries = 0;
}
void
CKeyArray::Update(wchar *chars)
{
int i;
for(i = 0; i < numEntries; i++)
entries[i].value = (wchar*)((uint8*)chars + (uintptr)entries[i].value);
}
CKeyEntry*
CKeyArray::BinarySearch(const char *key, CKeyEntry *entries, int16 low, int16 high)
{
int mid;
int diff;
if(low > high)
return nil;
mid = (low + high)/2;
diff = strcmp(key, entries[mid].key);
if(diff == 0)
return &entries[mid];
if(diff < 0)
return BinarySearch(key, entries, low, mid-1);
if(diff > 0)
return BinarySearch(key, entries, mid+1, high);
return nil;
}
wchar*
CKeyArray::Search(const char *key)
{
CKeyEntry *found;
char errstr[25];
int i;
found = BinarySearch(key, entries, 0, numEntries-1);
if(found)
return found->value;
sprintf(errstr, "%s missing", key);
for(i = 0; i < 25; i++)
WideErrorString[i] = errstr[i];
return WideErrorString;
}
void
CData::Load(uint32 length, uint8 *data, int *offset)
{
uint32 i;
uint8 *rawbytes;
numChars = length / sizeof(wchar);
chars = new wchar[numChars];
rawbytes = (uint8*)chars;
for(i = 0; i < length; i++)
rawbytes[i] = data[(*offset)++];
}
void
CData::Unload(void)
{
delete[] chars;
chars = nil;
numChars = 0;
}
void
AsciiToUnicode(const char *src, wchar *dst)
{
while((*dst++ = *src++) != '\0');
}
char*
UnicodeToAscii(wchar *src)
{
static char aStr[256];
int len;
for(len = 0; *src != '\0' && len < 256-1; len++, src++)
if(*src < 128)
aStr[len] = *src;
else
aStr[len] = '#';
aStr[len] = '\0';
return aStr;
}
char*
UnicodeToAsciiForSaveLoad(wchar *src)
{
static char aStr[256];
int len;
for(len = 0; *src != '\0' && len < 256-1; len++, src++)
if(*src < 256)
aStr[len] = *src;
else
aStr[len] = '#';
aStr[len] = '\0';
return aStr;
}
void
UnicodeStrcpy(wchar *dst, const wchar *src)
{
while((*dst++ = *src++) != '\0');
}
int
UnicodeStrlen(const wchar *str)
{
int len;
for(len = 0; *str != '\0'; len++, str++);
return len;
}
void
TextCopy(wchar *dst, const wchar *src)
{
while((*dst++ = *src++) != '\0');
}
STARTPATCHES
InjectHook(0x52C3C0, &CText::Load, PATCH_JUMP);
InjectHook(0x52C580, &CText::Unload, PATCH_JUMP);
InjectHook(0x52C5A0, &CText::Get, PATCH_JUMP);
InjectHook(0x52C220, &CText::GetUpperCase, PATCH_JUMP);
InjectHook(0x52C2C0, &CText::UpperCase, PATCH_JUMP);
InjectHook(0x52BE70, &CKeyArray::Load, PATCH_JUMP);
InjectHook(0x52BF60, &CKeyArray::Unload, PATCH_JUMP);
InjectHook(0x52BF80, &CKeyArray::Update, PATCH_JUMP);
InjectHook(0x52C060, &CKeyArray::BinarySearch, PATCH_JUMP);
InjectHook(0x52BFB0, &CKeyArray::Search, PATCH_JUMP);
InjectHook(0x52C120, &CData::Load, PATCH_JUMP);
InjectHook(0x52C200, &CData::Unload, PATCH_JUMP);
ENDPATCHES
#include "common.h"
#include "patcher.h"
#include "FileMgr.h"
#include "Frontend.h"
#include "Messages.h"
#include "Text.h"
static wchar WideErrorString[25];
CText &TheText = *(CText*)0x941520;
CText::CText(void)
{
encoding = 'e';
memset(WideErrorString, 0, sizeof(WideErrorString));
}
void
CText::Load(void)
{
uint8 *filedata;
char filename[32], type[4];
int length;
int offset, sectlen;
Unload();
filedata = new uint8[0x40000];
CFileMgr::SetDir("TEXT");
switch(CMenuManager::m_PrefsLanguage){
case LANGUAGE_AMERICAN:
sprintf(filename, "AMERICAN.GXT");
break;
case LANGUAGE_FRENCH:
sprintf(filename, "FRENCH.GXT");
break;
case LANGUAGE_GERMAN:
sprintf(filename, "GERMAN.GXT");
break;
case LANGUAGE_ITALIAN:
sprintf(filename, "ITALIAN.GXT");
break;
case LANGUAGE_SPANISH:
sprintf(filename, "SPANISH.GXT");
break;
#ifdef MORE_LANGUAGES
case LANGUAGE_RUSSIAN:
sprintf(filename, "RUSSIAN.GXT");
break;
#endif
}
length = CFileMgr::LoadFile(filename, filedata, 0x40000, "rb");
CFileMgr::SetDir("");
offset = 0;
while(offset < length){
type[0] = filedata[offset++];
type[1] = filedata[offset++];
type[2] = filedata[offset++];
type[3] = filedata[offset++];
sectlen = (int)filedata[offset+3]<<24 | (int)filedata[offset+2]<<16 |
(int)filedata[offset+1]<<8 | (int)filedata[offset+0];
offset += 4;
if(sectlen != 0){
if(strncmp(type, "TKEY", 4) == 0)
keyArray.Load(sectlen, filedata, &offset);
else if(strncmp(type, "TDAT", 4) == 0)
data.Load(sectlen, filedata, &offset);
else
offset += sectlen;
}
}
keyArray.Update(data.chars);
delete[] filedata;
}
void
CText::Unload(void)
{
CMessages::ClearAllMessagesDisplayedByGame();
data.Unload();
keyArray.Unload();
}
wchar*
CText::Get(const char *key)
{
return keyArray.Search(key);
}
wchar UpperCaseTable[128] = {
128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138,
139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149,
150, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137,
138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148,
149, 173, 173, 175, 176, 177, 178, 179, 180, 181, 182,
183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193,
194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204,
205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215,
216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226,
227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237,
238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248,
249, 250, 251, 252, 253, 254, 255
};
wchar FrenchUpperCaseTable[128] = {
128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138,
139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149,
150, 65, 65, 65, 65, 132, 133, 69, 69, 69, 69, 73, 73,
73, 73, 79, 79, 79, 79, 85, 85, 85, 85, 173, 173, 175,
176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186,
187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197,
198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208,
209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219,
220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230,
231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241,
242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252,
253, 254, 255
};
wchar
CText::GetUpperCase(wchar c)
{
switch (encoding)
{
case 'e':
if (c >= 'a' && c <= 'z')
return c - 32;
break;
case 'f':
if (c >= 'a' && c <= 'z')
return c - 32;
if (c >= 128 && c <= 255)
return FrenchUpperCaseTable[c-128];
break;
case 'g':
case 'i':
case 's':
if (c >= 'a' && c <= 'z')
return c - 32;
if (c >= 128 && c <= 255)
return UpperCaseTable[c-128];
break;
default:
break;
}
return c;
}
void
CText::UpperCase(wchar *s)
{
while(*s){
*s = GetUpperCase(*s);
s++;
}
}
void
CKeyArray::Load(uint32 length, uint8 *data, int *offset)
{
uint32 i;
uint8 *rawbytes;
numEntries = length / sizeof(CKeyEntry);
entries = new CKeyEntry[numEntries];
rawbytes = (uint8*)entries;
for(i = 0; i < length; i++)
rawbytes[i] = data[(*offset)++];
}
void
CKeyArray::Unload(void)
{
delete[] entries;
entries = nil;
numEntries = 0;
}
void
CKeyArray::Update(wchar *chars)
{
int i;
for(i = 0; i < numEntries; i++)
entries[i].value = (wchar*)((uint8*)chars + (uintptr)entries[i].value);
}
CKeyEntry*
CKeyArray::BinarySearch(const char *key, CKeyEntry *entries, int16 low, int16 high)
{
int mid;
int diff;
if(low > high)
return nil;
mid = (low + high)/2;
diff = strcmp(key, entries[mid].key);
if(diff == 0)
return &entries[mid];
if(diff < 0)
return BinarySearch(key, entries, low, mid-1);
if(diff > 0)
return BinarySearch(key, entries, mid+1, high);
return nil;
}
wchar*
CKeyArray::Search(const char *key)
{
CKeyEntry *found;
char errstr[25];
int i;
found = BinarySearch(key, entries, 0, numEntries-1);
if(found)
return found->value;
sprintf(errstr, "%s missing", key);
for(i = 0; i < 25; i++)
WideErrorString[i] = errstr[i];
return WideErrorString;
}
void
CData::Load(uint32 length, uint8 *data, int *offset)
{
uint32 i;
uint8 *rawbytes;
numChars = length / sizeof(wchar);
chars = new wchar[numChars];
rawbytes = (uint8*)chars;
for(i = 0; i < length; i++)
rawbytes[i] = data[(*offset)++];
}
void
CData::Unload(void)
{
delete[] chars;
chars = nil;
numChars = 0;
}
void
AsciiToUnicode(const char *src, wchar *dst)
{
while((*dst++ = *src++) != '\0');
}
char*
UnicodeToAscii(wchar *src)
{
static char aStr[256];
int len;
for(len = 0; *src != '\0' && len < 256-1; len++, src++)
if(*src < 128)
aStr[len] = *src;
else
aStr[len] = '#';
aStr[len] = '\0';
return aStr;
}
char*
UnicodeToAsciiForSaveLoad(wchar *src)
{
static char aStr[256];
int len;
for(len = 0; *src != '\0' && len < 256-1; len++, src++)
if(*src < 256)
aStr[len] = *src;
else
aStr[len] = '#';
aStr[len] = '\0';
return aStr;
}
void
UnicodeStrcpy(wchar *dst, const wchar *src)
{
while((*dst++ = *src++) != '\0');
}
int
UnicodeStrlen(const wchar *str)
{
int len;
for(len = 0; *str != '\0'; len++, str++);
return len;
}
void
TextCopy(wchar *dst, const wchar *src)
{
while((*dst++ = *src++) != '\0');
}
STARTPATCHES
InjectHook(0x52C3C0, &CText::Load, PATCH_JUMP);
InjectHook(0x52C580, &CText::Unload, PATCH_JUMP);
InjectHook(0x52C5A0, &CText::Get, PATCH_JUMP);
InjectHook(0x52C220, &CText::GetUpperCase, PATCH_JUMP);
InjectHook(0x52C2C0, &CText::UpperCase, PATCH_JUMP);
InjectHook(0x52BE70, &CKeyArray::Load, PATCH_JUMP);
InjectHook(0x52BF60, &CKeyArray::Unload, PATCH_JUMP);
InjectHook(0x52BF80, &CKeyArray::Update, PATCH_JUMP);
InjectHook(0x52C060, &CKeyArray::BinarySearch, PATCH_JUMP);
InjectHook(0x52BFB0, &CKeyArray::Search, PATCH_JUMP);
InjectHook(0x52C120, &CData::Load, PATCH_JUMP);
InjectHook(0x52C200, &CData::Unload, PATCH_JUMP);
ENDPATCHES

View File

@ -1,15 +1,15 @@
#pragma once
// some miami bike leftovers
enum eBikeNodes {
BIKE_NODE_NONE,
BIKE_CHASSIS,
BIKE_FORKS_FRONT,
BIKE_FORKS_REAR,
BIKE_WHEEL_FRONT,
BIKE_WHEEL_REAR,
BIKE_MUDGUARD,
BIKE_HANDLEBARS,
BIKE_NUM_NODES
#pragma once
// some miami bike leftovers
enum eBikeNodes {
BIKE_NODE_NONE,
BIKE_CHASSIS,
BIKE_FORKS_FRONT,
BIKE_FORKS_REAR,
BIKE_WHEEL_FRONT,
BIKE_WHEEL_REAR,
BIKE_MUDGUARD,
BIKE_HANDLEBARS,
BIKE_NUM_NODES
};

View File

@ -1,32 +1,32 @@
#pragma once
class CEntity;
class CObject;
class CProjectile;
enum eWeaponType;
class CProjectileInfo
{
public:
eWeaponType m_eWeaponType;
CEntity* m_pSource;
uint32 m_nExplosionTime;
bool m_bInUse;
CVector m_vecPos;
public:
static CProjectileInfo* GetProjectileInfo(int32 id);
static CProjectile* (&ms_apProjectile)[NUM_PROJECTILES];
static void Initialise();
static void Shutdown();
static bool AddProjectile(CEntity *ped, eWeaponType weapon, CVector pos, float speed);
static void RemoveProjectile(CProjectileInfo *info, CProjectile *projectile);
static void RemoveNotAdd(CEntity *entity, eWeaponType weaponType, CVector pos);
static bool RemoveIfThisIsAProjectile(CObject *pObject);
static void RemoveAllProjectiles();
static void Update();
static bool IsProjectileInRange(float x1, float x2, float y1, float y2, float z1, float z2, bool remove);
};
#pragma once
class CEntity;
class CObject;
class CProjectile;
enum eWeaponType;
class CProjectileInfo
{
public:
eWeaponType m_eWeaponType;
CEntity* m_pSource;
uint32 m_nExplosionTime;
bool m_bInUse;
CVector m_vecPos;
public:
static CProjectileInfo* GetProjectileInfo(int32 id);
static CProjectile* (&ms_apProjectile)[NUM_PROJECTILES];
static void Initialise();
static void Shutdown();
static bool AddProjectile(CEntity *ped, eWeaponType weapon, CVector pos, float speed);
static void RemoveProjectile(CProjectileInfo *info, CProjectile *projectile);
static void RemoveNotAdd(CEntity *entity, eWeaponType weaponType, CVector pos);
static bool RemoveIfThisIsAProjectile(CObject *pObject);
static void RemoveAllProjectiles();
static void Update();
static bool IsProjectileInRange(float x1, float x2, float y1, float y2, float z1, float z2, bool remove);
};
extern CProjectileInfo (&gaProjectileInfo)[NUM_PROJECTILES];