Merge remote-tracking branch 'upstream/master'

This commit is contained in:
Nikolay Korolev 2019-07-01 00:18:10 +03:00
commit be808bed53
36 changed files with 905 additions and 120 deletions

View File

@ -1,12 +0,0 @@
#pragma once
#include "common.h"
struct CBulletTrace
{
CVector m_vecInf;
CVector m_vecSup;
bool m_bInUse;
uint8 m_bFramesInUse;
uint8 m_bLifeTime;
};

View File

@ -1,7 +0,0 @@
#include "common.h"
#include "patcher.h"
#include "BulletTraces.h"
CBulletTrace (&CBulletTraces::aTraces)[16] = *(CBulletTrace(*)[16])*(uintptr*)0x72B1B8;
WRAPPER void CBulletTraces::Init(void) { EAXJMP(0x518DE0); }

View File

@ -1,11 +0,0 @@
#pragma once
#include "BulletTrace.h"
class CBulletTraces
{
public:
static CBulletTrace(&aTraces)[16];
static void Init(void);
};

View File

@ -855,7 +855,7 @@ CFileLoader::Load2dEffect(const char *line)
int id, r, g, b, a, type; int id, r, g, b, a, type;
float x, y, z; float x, y, z;
char corona[32], shadow[32]; char corona[32], shadow[32];
int shadowIntens, flash, roadReflection, flare, flags, probability; int shadowIntens, lightType, roadReflection, flare, flags, probability;
CBaseModelInfo *mi; CBaseModelInfo *mi;
C2dEffect *effect; C2dEffect *effect;
char *p; char *p;
@ -888,14 +888,14 @@ CFileLoader::Load2dEffect(const char *line)
sscanf(line, "%f %f %f %f %d %d %d %d %d", sscanf(line, "%f %f %f %f %d %d %d %d %d",
&effect->light.dist, &effect->light.dist,
&effect->light.outerRange, &effect->light.range,
&effect->light.size, &effect->light.size,
&effect->light.innerRange, &effect->light.shadowRange,
&shadowIntens, &flash, &roadReflection, &flare, &flags); &shadowIntens, &lightType, &roadReflection, &flare, &flags);
effect->light.corona = RwTextureRead(corona, nil); effect->light.corona = RwTextureRead(corona, nil);
effect->light.shadow = RwTextureRead(shadow, nil); effect->light.shadow = RwTextureRead(shadow, nil);
effect->light.shadowIntensity = shadowIntens; effect->light.shadowIntensity = shadowIntens;
effect->light.flash = flash; effect->light.lightType = lightType;
effect->light.roadReflection = roadReflection; effect->light.roadReflection = roadReflection;
effect->light.flareType = flare; effect->light.flareType = flare;
// TODO: check out the flags // TODO: check out the flags

View File

@ -2,7 +2,9 @@
#include "patcher.h" #include "patcher.h"
#include "ParticleObject.h" #include "ParticleObject.h"
WRAPPER void CParticleObject::AddObject(uint16, const CVector &pos, bool remove) { EAXJMP(0x4BC4D0); } WRAPPER void CParticleObject::AddObject(uint16 type, const CVector &pos, bool remove) { EAXJMP(0x4BC4D0); }
WRAPPER void CParticleObject::AddObject(uint16 type, const CVector &pos, float size, bool remove) { EAXJMP(0x4BC520); }
WRAPPER void CParticleObject::AddObject(uint16 type, const CVector &pos, const CVector &dir, float size, bool remove) { EAXJMP(0x4BC570); }
// Converted from static void __cdecl CParticleObject::Initialise() 0x42C760 // Converted from static void __cdecl CParticleObject::Initialise() 0x42C760
void CParticleObject::Initialise() void CParticleObject::Initialise()

View File

@ -29,7 +29,9 @@ enum eParticleObjectType
class CParticleObject : CPlaceable class CParticleObject : CPlaceable
{ {
public: public:
static void AddObject(uint16, const CVector &pos, bool remove); static void AddObject(uint16 type, const CVector &pos, bool remove);
static void AddObject(uint16 type, const CVector &pos, float size, bool remove);
static void AddObject(uint16 type, const CVector &pos, const CVector &dir, float size, bool remove);
static void Initialise(); static void Initialise();
static void UpdateAll(); static void UpdateAll();

View File

@ -1,33 +0,0 @@
#pragma once
#include "common.h"
#include "Object.h"
enum ePickupType
{
PICKUP_NONE = 0,
PICKUP_IN_SHOP = 1,
PICKUP_ON_STREET = 2,
PICKUP_ONCE = 3,
PICKUP_ONCE_TIMEOUT = 4,
PICKUP_COLLECTABLE1 = 5,
PICKUP_IN_SHOP_OUT_OF_STOCK = 6,
PICKUP_MONEY = 7,
PICKUP_MINE_INACTIVE = 8,
PICKUP_MINE_ARMED = 9,
PICKUP_NAUTICAL_MINE_INACTIVE = 10,
PICKUP_NAUTICAL_MINE_ARMED = 11,
PICKUP_FLOATINGPACKAGE = 12,
PICKUP_FLOATINGPACKAGE_FLOATING = 13,
PICKUP_ON_STREET_SLOW = 14,
};
class CPickup
{
ePickupType m_eType;
uint16 m_wQuantity;
CObject *m_pObject;
uint32 m_nTimer;
int16 m_eModelIndex;
int16 m_wIndex;
CVector m_vecPos;
};

View File

View File

@ -118,6 +118,7 @@ public:
static int GetSunCoronaGreen(void) { return m_nCurrentSunCoronaGreen; } static int GetSunCoronaGreen(void) { return m_nCurrentSunCoronaGreen; }
static int GetSunCoronaBlue(void) { return m_nCurrentSunCoronaBlue; } static int GetSunCoronaBlue(void) { return m_nCurrentSunCoronaBlue; }
static float GetSunSize(void) { return m_fCurrentSunSize; } static float GetSunSize(void) { return m_fCurrentSunSize; }
static float GetSpriteBrightness(void) { return m_fCurrentSpriteBrightness; }
static float GetFarClip(void) { return m_fCurrentFarClip; } static float GetFarClip(void) { return m_fCurrentFarClip; }
static float GetFogStart(void) { return m_fCurrentFogStart; } static float GetFogStart(void) { return m_fCurrentFogStart; }

View File

@ -645,11 +645,6 @@ cAudioManager::GetWhiteCriminalTalkSfx(int16 sound)
return sfx; return sfx;
} }
WRAPPER int32 cAudioManager::GetSpecialCharacterTalkSfx(int32, int32)
{
EAXJMP(0x574790);
}
uint32 uint32
cAudioManager::GetMaleNo2TalkSfx(int16 sound) cAudioManager::GetMaleNo2TalkSfx(int16 sound)
{ {
@ -2432,6 +2427,197 @@ cAudioManager::GetCasualMaleOldTalkSfx(int16 sound)
return GetGenericMaleTalkSfx(sound); return GetGenericMaleTalkSfx(sound);
} }
uint32
cAudioManager::GetSpecialCharacterTalkSfx(int32 modelIndex, int32 sound)
{
char *modelName = CModelInfo::GetModelInfo(modelIndex)->GetName();
if(strcmp(modelName, "eight") == 0 ||
strcmp(modelName, "eight2") == 0) {
return GetEightTalkSfx(sound);
}
if(strcmp(modelName, "frankie") == 0) {
return GetFrankieTalkSfx(sound);
}
if(strcmp(modelName, "misty") == 0) { return GetMistyTalkSfx(sound); }
if(strcmp(modelName, "ojg") == 0 ||
strcmp(modelName, "ojg_p") == 0) {
return GetOJGTalkSfx(sound);
}
if(strcmp(modelName, "cat") == 0) {
return GetCatatalinaTalkSfx(sound);
}
if(strcmp(modelName, "bomber") == 0) {
return GetBomberTalkSfx(sound);
}
if(strcmp(modelName, "s_guard") == 0) {
return GetSecurityGuardTalkSfx(sound);
}
if(strcmp(modelName, "chunky") == 0) {
return GetChunkyTalkSfx(sound);
}
if(strcmp(modelName, "asuka") == 0) {
return GetGenericFemaleTalkSfx(sound);
}
if(strcmp(modelName, "maria") == 0) {
return GetGenericFemaleTalkSfx(sound);
}
return GetGenericMaleTalkSfx(sound);
}
uint32
cAudioManager::GetEightTalkSfx(int16 sound)
{
uint32 sfx;
static uint32 lastSfx = NO_SAMPLE;
switch(sound) {
case SOUND_PED_HANDS_UP:
cAudioManager::GetPhrase(&sfx, &lastSfx,
AUDIO_SAMPLE_PED_EIGHT_HANDS_UP_1, 2u);
break;
case SOUND_PED_ROBBED:
cAudioManager::GetPhrase(&sfx, &lastSfx,
AUDIO_SAMPLE_PED_EIGHT_ROBBED_1, 2u);
break;
case SOUND_PED_ATTACK:
cAudioManager::GetPhrase(&sfx, &lastSfx,
AUDIO_SAMPLE_PED_EIGHT_ATTACK_1, 6u);
break;
case SOUND_PED_EVADE:
cAudioManager::GetPhrase(&sfx, &lastSfx,
AUDIO_SAMPLE_PED_EIGHT_EVADE_1, 7u);
break;
default: return GetGenericMaleTalkSfx(sound);
}
return sfx;
}
uint32
cAudioManager::GetFrankieTalkSfx(int16 sound)
{
uint32 sfx;
static uint32 lastSfx = NO_SAMPLE;
switch(sound) {
case SOUND_PED_HANDS_UP:
GetPhrase(&sfx, &lastSfx, AUDIO_SAMPLE_PED_FRANKIE_HANDS_UP_1,
4u);
break;
case SOUND_PED_ROBBED:
GetPhrase(&sfx, &lastSfx, AUDIO_SAMPLE_PED_FRANKIE_ROBBED_1,
2u);
break;
case SOUND_PED_ATTACK:
GetPhrase(&sfx, &lastSfx, AUDIO_SAMPLE_PED_FRANKIE_ATTACK_1,
6u);
break;
case SOUND_PED_EVADE:
GetPhrase(&sfx, &lastSfx, AUDIO_SAMPLE_PED_FRANKIE_EVADE_1, 3u);
break;
default: return GetGenericMaleTalkSfx(sound);
}
return sfx;
}
uint32
cAudioManager::GetMistyTalkSfx(int16 sound)
{
uint32 sfx;
static uint32 lastSfx = NO_SAMPLE;
switch(sound) {
case SOUND_PED_HANDS_UP:
GetPhrase(&sfx, &lastSfx, AUDIO_SAMPLE_PED_MISTY_HANDS_UP_1,
5u);
break;
case SOUND_PED_ROBBED:
GetPhrase(&sfx, &lastSfx, AUDIO_SAMPLE_PED_MISTY_ROBBED_1, 2u);
break;
case SOUND_PED_ATTACK:
GetPhrase(&sfx, &lastSfx, AUDIO_SAMPLE_PED_MISTY_ATTACK_1, 4u);
break;
case SOUND_PED_EVADE:
GetPhrase(&sfx, &lastSfx, AUDIO_SAMPLE_PED_MISTY_EVADE_1, 5u);
break;
case SOUND_PED_TAXI_CALL:
GetPhrase(&sfx, &lastSfx, AUDIO_SAMPLE_PED_MISTY_THUMB_LIFT_1,
4u);
break;
default: return GetGenericFemaleTalkSfx(sound); break;
}
return sfx;
}
uint32
cAudioManager::GetOJGTalkSfx(int16 sound)
{
return GetGenericMaleTalkSfx(sound);
}
uint32
cAudioManager::GetCatatalinaTalkSfx(int16 sound)
{
return GetGenericFemaleTalkSfx(sound);
}
uint32
cAudioManager::GetBomberTalkSfx(int16 sound)
{
uint32 sfx;
static uint32 lastSfx = NO_SAMPLE;
if(sound != SOUND_PED_BOMBER) return GetGenericMaleTalkSfx(sound);
GetPhrase(&sfx, &lastSfx, AUDIO_SAMPLE_PED_BOMBER_THREAT_1, 7u);
return sfx;
}
uint32
cAudioManager::GetSecurityGuardTalkSfx(int16 sound)
{
uint32 sfx;
static uint32 lastSfx = NO_SAMPLE;
switch(sound) {
case SOUND_PED_HANDS_UP:
GetPhrase(&sfx, &lastSfx,
AUDIO_SAMPLE_PED_SECURITY_GUARD_HANDS_UP_1, 2u);
break;
case SOUND_PED_HANDS_COWER:
sfx = AUDIO_SAMPLE_PED_SECURITY_GUARD_HANDS_COWER_1;
break;
case SOUND_PED_CAR_JACKED:
case SOUND_PED_CAR_COLLISION:
GetPhrase(&sfx, &lastSfx,
AUDIO_SAMPLE_PED_SECURITY_GUARD_CAR_EVENT_1, 6u);
break;
case SOUND_PED_ATTACK:
GetPhrase(&sfx, &lastSfx,
AUDIO_SAMPLE_PED_SECURITY_GUARD_ATTACK_1, 2u);
break;
case SOUND_PED_FLEE_RUN:
GetPhrase(&sfx, &lastSfx,
AUDIO_SAMPLE_PED_SECURITY_GUARD_CAR_EVENT_1, 12u);
break;
default: return GetGenericMaleTalkSfx(sound);
}
return sfx;
}
uint32
cAudioManager::GetChunkyTalkSfx(int16 sound)
{
uint32 sfx;
static uint32 lastSfx = NO_SAMPLE;
if(sound == SOUND_PED_DEATH) return AUDIO_SAMPLE_PED_CHUNKY_DEATH_1;
if(sound != SOUND_PED_FLEE_RUN) return GetGenericMaleTalkSfx(sound);
GetPhrase(&sfx, &lastSfx, AUDIO_SAMPLE_PED_CHUNKY_FLEE_RUN_1, 5u);
return sfx;
}
uint32 uint32
cAudioManager::GetGenericMaleTalkSfx(int16 sound) cAudioManager::GetGenericMaleTalkSfx(int16 sound)
{ {
@ -2484,7 +2670,7 @@ cAudioManager::GetGenericFemaleTalkSfx(int16 sound)
cAudioManager::GetPhrase( cAudioManager::GetPhrase(
&sfx, &lastSfx, AUDIO_SAMPLE_PED_FEMALE_FLEE_SPRINT_1, 8u); &sfx, &lastSfx, AUDIO_SAMPLE_PED_FEMALE_FLEE_SPRINT_1, 8u);
break; break;
default: sfx = NO_SAMPLE; break; default: return NO_SAMPLE;
} }
return sfx; return sfx;
} }
@ -2518,7 +2704,6 @@ InjectHook(0x571B00, &cAudioManager::GetColumbianTalkSfx, PATCH_JUMP);
InjectHook(0x571C30, &cAudioManager::GetHoodTalkSfx, PATCH_JUMP); InjectHook(0x571C30, &cAudioManager::GetHoodTalkSfx, PATCH_JUMP);
InjectHook(0x571D80, &cAudioManager::GetBlackCriminalTalkSfx, PATCH_JUMP); InjectHook(0x571D80, &cAudioManager::GetBlackCriminalTalkSfx, PATCH_JUMP);
InjectHook(0x571E60, &cAudioManager::GetWhiteCriminalTalkSfx, PATCH_JUMP); InjectHook(0x571E60, &cAudioManager::GetWhiteCriminalTalkSfx, PATCH_JUMP);
// InjectHook(0x574790, &cAudioManager::GetSpecialCharacterTalkSfx, PATCH_JUMP);
InjectHook(0x571F40, &cAudioManager::GetMaleNo2TalkSfx, PATCH_JUMP); InjectHook(0x571F40, &cAudioManager::GetMaleNo2TalkSfx, PATCH_JUMP);
InjectHook(0x572AF0, &cAudioManager::GetBlackProjectMaleTalkSfx, PATCH_JUMP); InjectHook(0x572AF0, &cAudioManager::GetBlackProjectMaleTalkSfx, PATCH_JUMP);
InjectHook(0x5725D0, &cAudioManager::GetWhiteFatMaleTalkSfx, PATCH_JUMP); InjectHook(0x5725D0, &cAudioManager::GetWhiteFatMaleTalkSfx, PATCH_JUMP);
@ -2564,6 +2749,16 @@ InjectHook(0x574590, &cAudioManager::GetStudentMaleTalkSfx, PATCH_JUMP);
InjectHook(0x574690, &cAudioManager::GetStudentFemaleTalkSfx, PATCH_JUMP); InjectHook(0x574690, &cAudioManager::GetStudentFemaleTalkSfx, PATCH_JUMP);
InjectHook(0x572040, &cAudioManager::GetCasualMaleOldTalkSfx, PATCH_JUMP); InjectHook(0x572040, &cAudioManager::GetCasualMaleOldTalkSfx, PATCH_JUMP);
InjectHook(0x574790, &cAudioManager::GetSpecialCharacterTalkSfx, PATCH_JUMP);
InjectHook(0x574DA0, &cAudioManager::GetEightTalkSfx, PATCH_JUMP);
InjectHook(0x574E50, &cAudioManager::GetFrankieTalkSfx, PATCH_JUMP);
InjectHook(0x574F00, &cAudioManager::GetMistyTalkSfx, PATCH_JUMP);
InjectHook(0x574FD0, &cAudioManager::GetOJGTalkSfx, PATCH_JUMP);
InjectHook(0x574FE0, &cAudioManager::GetCatatalinaTalkSfx, PATCH_JUMP);
InjectHook(0x574FF0, &cAudioManager::GetBomberTalkSfx, PATCH_JUMP);
InjectHook(0x575060, &cAudioManager::GetSecurityGuardTalkSfx, PATCH_JUMP);
InjectHook(0x575120, &cAudioManager::GetChunkyTalkSfx, PATCH_JUMP);
InjectHook(0x575460, &cAudioManager::GetGenericMaleTalkSfx, PATCH_JUMP); InjectHook(0x575460, &cAudioManager::GetGenericMaleTalkSfx, PATCH_JUMP);
InjectHook(0x575510, &cAudioManager::GetGenericFemaleTalkSfx, PATCH_JUMP); InjectHook(0x575510, &cAudioManager::GetGenericFemaleTalkSfx, PATCH_JUMP);
ENDPATCHES ENDPATCHES

View File

@ -240,7 +240,6 @@ public:
uint32 GetHoodTalkSfx(int16 sound); uint32 GetHoodTalkSfx(int16 sound);
uint32 GetBlackCriminalTalkSfx(int16 sound); uint32 GetBlackCriminalTalkSfx(int16 sound);
uint32 GetWhiteCriminalTalkSfx(int16 sound); uint32 GetWhiteCriminalTalkSfx(int16 sound);
int32 GetSpecialCharacterTalkSfx(int32, int32);
uint32 GetMaleNo2TalkSfx(int16 sound); uint32 GetMaleNo2TalkSfx(int16 sound);
uint32 GetBlackProjectMaleTalkSfx(int16 sound, int32 model); uint32 GetBlackProjectMaleTalkSfx(int16 sound, int32 model);
uint32 GetWhiteFatMaleTalkSfx(int16 sound); uint32 GetWhiteFatMaleTalkSfx(int16 sound);
@ -286,6 +285,16 @@ public:
uint32 GetStudentFemaleTalkSfx(int16 sound); uint32 GetStudentFemaleTalkSfx(int16 sound);
uint32 GetCasualMaleOldTalkSfx(int16 sound); uint32 GetCasualMaleOldTalkSfx(int16 sound);
uint32 GetSpecialCharacterTalkSfx(int32 modelIndex, int32 sound);
uint32 GetEightTalkSfx(int16 sound);
uint32 GetFrankieTalkSfx(int16 sound);
uint32 GetMistyTalkSfx(int16 sound);
uint32 GetOJGTalkSfx(int16 sound);
uint32 GetCatatalinaTalkSfx(int16 sound);
uint32 GetBomberTalkSfx(int16 sound);
uint32 GetSecurityGuardTalkSfx(int16 sound);
uint32 GetChunkyTalkSfx(int16 sound);
uint32 GetGenericMaleTalkSfx(int16 sound); uint32 GetGenericMaleTalkSfx(int16 sound);
uint32 GetGenericFemaleTalkSfx(int16 sound); uint32 GetGenericFemaleTalkSfx(int16 sound);
}; };

View File

@ -166,4 +166,4 @@ void re3_assert(const char *expr, const char *filename, unsigned int lineno, con
#define BIT(num) (1<<(num)) #define BIT(num) (1<<(num))
#define max(a, b) (((a) > (b)) ? (a) : (b)) #define max(a, b) (((a) > (b)) ? (a) : (b))
#define min(a, b) (((a) < (b)) ? (a) : (b)) #define min(a, b) (((a) < (b)) ? (a) : (b))

5
src/control/Bridge.cpp Normal file
View File

@ -0,0 +1,5 @@
#include "common.h"
#include "patcher.h"
#include "Bridge.h"
WRAPPER bool CBridge::ShouldLightsBeFlashing(void) { EAXJMP(0x413D10); }

7
src/control/Bridge.h Normal file
View File

@ -0,0 +1,7 @@
#pragma once
class CBridge
{
public:
static bool ShouldLightsBeFlashing(void);
};

View File

@ -5,5 +5,9 @@
CPickup(&CPickups::aPickUps)[NUMPICKUPS] = *(CPickup(*)[NUMPICKUPS])*(uintptr*)0x878C98; CPickup(&CPickups::aPickUps)[NUMPICKUPS] = *(CPickup(*)[NUMPICKUPS])*(uintptr*)0x878C98;
WRAPPER void CPickups::RenderPickUpText(void) { EAXJMP(0x432440); } WRAPPER void CPickups::RenderPickUpText(void) { EAXJMP(0x432440); }
WRAPPER void CPickups::DoCollectableEffects(CEntity *ent) { EAXJMP(0x431C30); }
WRAPPER void CPickups::DoMoneyEffects(CEntity *ent) { EAXJMP(0x431F40); }
WRAPPER void CPickups::DoMineEffects(CEntity *ent) { EAXJMP(0x4321C0); }
WRAPPER void CPickups::DoPickUpEffects(CEntity *ent) { EAXJMP(0x431520); }
WRAPPER void CPacManPickups::Render(void) { EAXJMP(0x432F60); } WRAPPER void CPacManPickups::Render(void) { EAXJMP(0x432F60); }

View File

@ -1,14 +1,48 @@
#pragma once #pragma once
#include "config.h" enum ePickupType
#include "Pickup.h" {
PICKUP_NONE = 0,
PICKUP_IN_SHOP = 1,
PICKUP_ON_STREET = 2,
PICKUP_ONCE = 3,
PICKUP_ONCE_TIMEOUT = 4,
PICKUP_COLLECTABLE1 = 5,
PICKUP_IN_SHOP_OUT_OF_STOCK = 6,
PICKUP_MONEY = 7,
PICKUP_MINE_INACTIVE = 8,
PICKUP_MINE_ARMED = 9,
PICKUP_NAUTICAL_MINE_INACTIVE = 10,
PICKUP_NAUTICAL_MINE_ARMED = 11,
PICKUP_FLOATINGPACKAGE = 12,
PICKUP_FLOATINGPACKAGE_FLOATING = 13,
PICKUP_ON_STREET_SLOW = 14,
};
class CEntity;
class CObject;
class CPickup
{
ePickupType m_eType;
uint16 m_wQuantity;
CObject *m_pObject;
uint32 m_nTimer;
int16 m_eModelIndex;
int16 m_wIndex;
CVector m_vecPos;
};
class CPickups class CPickups
{ {
public: public:
static void RenderPickUpText(void); static void RenderPickUpText(void);
static void DoCollectableEffects(CEntity *ent);
static void DoMoneyEffects(CEntity *ent);
static void DoMineEffects(CEntity *ent);
static void DoPickUpEffects(CEntity *ent);
static CPickup(&aPickUps)[NUMPICKUPS]; static CPickup (&aPickUps)[NUMPICKUPS];
}; };
class CPacManPickups class CPacManPickups

View File

@ -2,7 +2,7 @@
#include "patcher.h" #include "patcher.h"
#include "AnimBlendAssociation.h" #include "AnimBlendAssociation.h"
#include "Boat.h" #include "Boat.h"
#include "BulletTraces.h" #include "SpecialFX.h"
#include "CarCtrl.h" #include "CarCtrl.h"
#include "CivilianPed.h" #include "CivilianPed.h"
#include "Clock.h" #include "Clock.h"
@ -308,8 +308,8 @@ void CReplay::RecordThisFrame(void)
tBulletTracePacket* bt = (tBulletTracePacket*)&Record.m_pBase[Record.m_nOffset]; tBulletTracePacket* bt = (tBulletTracePacket*)&Record.m_pBase[Record.m_nOffset];
bt->type = REPLAYPACKET_BULLET_TRACES; bt->type = REPLAYPACKET_BULLET_TRACES;
bt->index = i; bt->index = i;
bt->frames = CBulletTraces::aTraces[i].m_bFramesInUse; bt->frames = CBulletTraces::aTraces[i].m_framesInUse;
bt->lifetime = CBulletTraces::aTraces[i].m_bLifeTime; bt->lifetime = CBulletTraces::aTraces[i].m_lifeTime;
bt->inf = CBulletTraces::aTraces[i].m_vecInf; bt->inf = CBulletTraces::aTraces[i].m_vecInf;
bt->sup = CBulletTraces::aTraces[i].m_vecSup; bt->sup = CBulletTraces::aTraces[i].m_vecSup;
Record.m_nOffset += sizeof(*bt); Record.m_nOffset += sizeof(*bt);
@ -897,8 +897,8 @@ bool CReplay::PlayBackThisFrameInterpolation(CAddressInReplayBuffer *buffer, flo
{ {
tBulletTracePacket* pb = (tBulletTracePacket*)&ptr[offset]; tBulletTracePacket* pb = (tBulletTracePacket*)&ptr[offset];
CBulletTraces::aTraces[pb->index].m_bInUse = true; CBulletTraces::aTraces[pb->index].m_bInUse = true;
CBulletTraces::aTraces[pb->index].m_bFramesInUse = pb->frames; CBulletTraces::aTraces[pb->index].m_framesInUse = pb->frames;
CBulletTraces::aTraces[pb->index].m_bLifeTime = pb->lifetime; CBulletTraces::aTraces[pb->index].m_lifeTime = pb->lifetime;
CBulletTraces::aTraces[pb->index].m_vecInf = pb->inf; CBulletTraces::aTraces[pb->index].m_vecInf = pb->inf;
CBulletTraces::aTraces[pb->index].m_vecSup = pb->sup; CBulletTraces::aTraces[pb->index].m_vecSup = pb->sup;
buffer->m_nOffset += sizeof(tBulletTracePacket); buffer->m_nOffset += sizeof(tBulletTracePacket);

View File

@ -3,7 +3,6 @@
#include "Camera.h" #include "Camera.h"
#include "Ped.h" #include "Ped.h"
#include "Pools.h" #include "Pools.h"
#include "Pickup.h"
#include "Radar.h" #include "Radar.h"
#include "References.h" #include "References.h"
#include "Vehicle.h" #include "Vehicle.h"

View File

@ -0,0 +1,5 @@
#include "common.h"
#include "patcher.h"
#include "TrafficLights.h"
WRAPPER void CTrafficLights::DisplayActualLight(CEntity *ent) { EAXJMP(0x455800); }

View File

@ -0,0 +1,9 @@
#pragma once
class CEntity;
class CTrafficLights
{
public:
static void DisplayActualLight(CEntity *ent);
};

View File

@ -1,14 +1,29 @@
#include "common.h" #include "common.h"
#include "rpworld.h" #include "patcher.h"
#include "General.h"
#include "ModelIndices.h"
#include "Timer.h"
#include "Placeable.h" #include "Placeable.h"
#include "Entity.h" #include "Entity.h"
#include "Object.h"
#include "ParticleObject.h"
#include "Lights.h" #include "Lights.h"
#include "World.h" #include "World.h"
#include "Camera.h" #include "Camera.h"
#include "Glass.h"
#include "Clock.h"
#include "Weather.h"
#include "TimeCycle.h"
#include "Bridge.h"
#include "TrafficLights.h"
#include "Coronas.h"
#include "Pointlights.h"
#include "Shadows.h"
#include "Pickups.h"
#include "SpecialFX.h"
#include "References.h" #include "References.h"
#include "TxdStore.h" #include "TxdStore.h"
#include "Zones.h" #include "Zones.h"
#include "patcher.h"
int gBuildings; int gBuildings;
@ -59,7 +74,7 @@ CEntity::CEntity(void)
m_scanCode = 0; m_scanCode = 0;
m_modelIndex = -1; m_modelIndex = -1;
m_rwObject = nil; m_rwObject = nil;
m_randomSeed = rand(); m_randomSeed = CGeneral::GetRandomNumber();
m_pFirstReference = nil; m_pFirstReference = nil;
} }
@ -339,9 +354,105 @@ CEntity::GetBoundRect(void)
return rect; return rect;
} }
WRAPPER void void
CEntity::PreRender(void) CEntity::PreRender(void)
{ EAXJMP(0x474350); {
switch(m_type){
case ENTITY_TYPE_BUILDING:
if(GetModelIndex() == MI_RAILTRACKS){
CShadows::StoreShadowForPole(this, 0.0f, -10.949f, 5.0f, 8.0f, 1.0f, 0);
CShadows::StoreShadowForPole(this, 0.0f, 10.949f, 5.0f, 8.0f, 1.0f, 1);
}else if(IsTreeModel(GetModelIndex())){
CShadows::StoreShadowForTree(this);
ModifyMatrixForTreeInWind();
}else if(IsBannerModel(GetModelIndex())){
ModifyMatrixForBannerInWind();
}
break;
case ENTITY_TYPE_OBJECT:
if(GetModelIndex() == MI_COLLECTABLE1){
CPickups::DoCollectableEffects(this);
GetMatrix().UpdateRW();
UpdateRwFrame();
}else if(GetModelIndex() == MI_MONEY){
CPickups::DoMoneyEffects(this);
GetMatrix().UpdateRW();
UpdateRwFrame();
}else if(GetModelIndex() == MI_NAUTICALMINE ||
GetModelIndex() == MI_CARMINE ||
GetModelIndex() == MI_BRIEFCASE){
if(((CObject*)this)->bIsPickup){
CPickups::DoMineEffects(this);
GetMatrix().UpdateRW();
UpdateRwFrame();
}
}else if(IsPickupModel(GetModelIndex())){
if(((CObject*)this)->bIsPickup){
CPickups::DoPickUpEffects(this);
GetMatrix().UpdateRW();
UpdateRwFrame();
}else if(GetModelIndex() == MI_GRENADE){
CMotionBlurStreaks::RegisterStreak((uintptr)this,
100, 100, 100,
TheCamera.GetPosition() - 0.07f*TheCamera.GetRight(),
TheCamera.GetPosition() + 0.07f*TheCamera.GetRight());
}else if(GetModelIndex() == MI_MOLOTOV){
CMotionBlurStreaks::RegisterStreak((uintptr)this,
0, 100, 0,
TheCamera.GetPosition() - 0.07f*TheCamera.GetRight(),
TheCamera.GetPosition() + 0.07f*TheCamera.GetRight());
}
}else if(GetModelIndex() == MI_MISSILE){
CVector pos = GetPosition();
float flicker = (CGeneral::GetRandomNumber() & 0xF)/(float)0x10;
CShadows::StoreShadowToBeRendered(SHADOWTYPE_2,
gpShadowExplosionTex, &pos,
8.0f, 0.0f, 0.0f, -8.0f,
255, 200.0f*flicker, 160.0f*flicker, 120.0f*flicker,
20.0f, false, 1.0f);
CPointLights::AddLight(CPointLights::LIGHT_POINT,
pos, CVector(0.0f, 0.0f, 0.0f),
8.0f,
1.0f*flicker,
0.8f*flicker,
0.6f*flicker,
CPointLights::FOG_NONE, true);
CCoronas::RegisterCorona((uintptr)this,
255.0f*flicker, 220.0f*flicker, 190.0f*flicker, 255,
pos, 6.0f*flicker, 80.0f, gpCoronaTexture[CCoronas::TYPE_STAR],
CCoronas::FLARE_NONE, CCoronas::REFLECTION_ON,
CCoronas::LOSCHECK_OFF, CCoronas::STREAK_OFF, 0.0f);
}else if(IsGlass(GetModelIndex())){
PreRenderForGlassWindow();
}
// fall through
case ENTITY_TYPE_DUMMY:
if(GetModelIndex() == MI_TRAFFICLIGHTS){
CTrafficLights::DisplayActualLight(this);
CShadows::StoreShadowForPole(this, 2.957f, 0.147f, 0.0f, 16.0f, 0.4f, 0);
}else if(GetModelIndex() == MI_SINGLESTREETLIGHTS1)
CShadows::StoreShadowForPole(this, 0.744f, 0.0f, 0.0f, 16.0f, 0.4f, 0);
else if(GetModelIndex() == MI_SINGLESTREETLIGHTS2)
CShadows::StoreShadowForPole(this, 0.043f, 0.0f, 0.0f, 16.0f, 0.4f, 0);
else if(GetModelIndex() == MI_SINGLESTREETLIGHTS3)
CShadows::StoreShadowForPole(this, 1.143f, 0.145f, 0.0f, 16.0f, 0.4f, 0);
else if(GetModelIndex() == MI_DOUBLESTREETLIGHTS)
CShadows::StoreShadowForPole(this, 0.0f, -0.048f, 0.0f, 16.0f, 0.4f, 0);
else if(GetModelIndex() == MI_STREETLAMP1 ||
GetModelIndex() == MI_STREETLAMP2)
CShadows::StoreShadowForPole(this, 0.0f, 0.0f, 0.0f, 16.0f, 0.4f, 0);
break;
}
if(CModelInfo::GetModelInfo(GetModelIndex())->m_num2dEffects != 0)
ProcessLightsForEntity();
}
void
CEntity::PreRenderForGlassWindow(void)
{
CGlass::AskForObjectToBeRenderedInGlass(this);
bIsVisible = false;
} }
void void
@ -447,6 +558,313 @@ CEntity::PruneReferences(void)
} }
} }
void
CEntity::AddSteamsFromGround(CVector *unused)
{
int i, n;
C2dEffect *effect;
CVector pos;
n = CModelInfo::GetModelInfo(GetModelIndex())->m_num2dEffects;
for(i = 0; i < n; i++){
effect = CModelInfo::GetModelInfo(GetModelIndex())->Get2dEffect(i);
if(effect->type != EFFECT_PARTICLE)
continue;
pos = GetMatrix() * effect->pos;
switch(effect->particle.particleType){
case 0:
CParticleObject::AddObject(POBJECT_PAVEMENT_STEAM, pos, effect->particle.dir, effect->particle.scale, false);
break;
case 1:
CParticleObject::AddObject(POBJECT_WALL_STEAM, pos, effect->particle.dir, effect->particle.scale, false);
break;
case 2:
CParticleObject::AddObject(POBJECT_DRY_ICE, pos, effect->particle.scale, false);
break;
case 3:
CParticleObject::AddObject(POBJECT_SMALL_FIRE, pos, effect->particle.dir, effect->particle.scale, false);
break;
case 4:
CParticleObject::AddObject(POBJECT_DARK_SMOKE, pos, effect->particle.dir, effect->particle.scale, false);
break;
}
}
}
void
CEntity::ProcessLightsForEntity(void)
{
int i, n;
C2dEffect *effect;
CVector pos;
bool lightOn, lightFlickering;
uint32 flashTimer1, flashTimer2, flashTimer3;
if(bRenderDamaged || !bIsVisible || GetUp().z < 0.96f)
return;
flashTimer1 = 0;
flashTimer2 = 0;
flashTimer3 = 0;
n = CModelInfo::GetModelInfo(GetModelIndex())->m_num2dEffects;
for(i = 0; i < n; i++, flashTimer1 += 0x80, flashTimer2 += 0x100, flashTimer3 += 0x200){
effect = CModelInfo::GetModelInfo(GetModelIndex())->Get2dEffect(i);
if(effect->type != EFFECT_LIGHT)
continue;
pos = GetMatrix() * effect->pos;
lightOn = false;
lightFlickering = false;
switch(effect->light.lightType){
case LIGHT_ON:
lightOn = true;
break;
case LIGHT_ON_NIGHT:
if(CClock::GetHours() > 18 || CClock::GetHours() < 7)
lightOn = true;
break;
case LIGHT_FLICKER:
if((CTimer::GetTimeInMilliseconds() ^ m_randomSeed) & 0x60)
lightOn = true;
else
lightFlickering = true;
if((CTimer::GetTimeInMilliseconds()>>1 ^ m_randomSeed) & 3)
lightOn = true;
break;
case LIGHT_FLICKER_NIGHT:
if(CClock::GetHours() > 18 || CClock::GetHours() < 7){
if((CTimer::GetTimeInMilliseconds() ^ m_randomSeed) & 0x60)
lightOn = true;
else
lightFlickering = true;
if((CTimer::GetTimeInMilliseconds()>>1 ^ m_randomSeed) & 3)
lightOn = true;
}
break;
case LIGHT_FLASH1:
if((CTimer::GetTimeInMilliseconds() + flashTimer1) & 0x200)
lightOn = true;
break;
case LIGHT_FLASH1_NIGHT:
if(CClock::GetHours() > 18 || CClock::GetHours() < 7)
if((CTimer::GetTimeInMilliseconds() + flashTimer1) & 0x200)
lightOn = true;
break;
case LIGHT_FLASH2:
if((CTimer::GetTimeInMilliseconds() + flashTimer2) & 0x400)
lightOn = true;
break;
case LIGHT_FLASH2_NIGHT:
if(CClock::GetHours() > 18 || CClock::GetHours() < 7)
if((CTimer::GetTimeInMilliseconds() + flashTimer2) & 0x400)
lightOn = true;
break;
case LIGHT_FLASH3:
if((CTimer::GetTimeInMilliseconds() + flashTimer3) & 0x800)
lightOn = true;
break;
case LIGHT_FLASH3_NIGHT:
if(CClock::GetHours() > 18 || CClock::GetHours() < 7)
if((CTimer::GetTimeInMilliseconds() + flashTimer3) & 0x800)
lightOn = true;
break;
case LIGHT_RANDOM_FLICKER:
if(m_randomSeed > 16)
lightOn = true;
else{
if((CTimer::GetTimeInMilliseconds() ^ m_randomSeed*8) & 0x60)
lightOn = true;
else
lightFlickering = true;
if((CTimer::GetTimeInMilliseconds()>>1 ^ m_randomSeed*8) & 3)
lightOn = true;
}
break;
case LIGHT_RANDOM_FLICKER_NIGHT:
if(CClock::GetHours() > 18 || CClock::GetHours() < 7){
if(m_randomSeed > 16)
lightOn = true;
else{
if((CTimer::GetTimeInMilliseconds() ^ m_randomSeed*8) & 0x60)
lightOn = true;
else
lightFlickering = true;
if((CTimer::GetTimeInMilliseconds()>>1 ^ m_randomSeed*8) & 3)
lightOn = true;
}
}
break;
case LIGHT_BRIDGE_FLASH1:
if(CBridge::ShouldLightsBeFlashing() && CTimer::GetTimeInMilliseconds() & 0x200)
lightOn = true;
break;
case LIGHT_BRIDGE_FLASH2:
if(CBridge::ShouldLightsBeFlashing() && (CTimer::GetTimeInMilliseconds() & 0x1FF) < 60)
lightOn = true;
break;
}
// Corona
if(lightOn)
CCoronas::RegisterCorona((uintptr)this + i,
effect->col.r, effect->col.g, effect->col.b, 255,
pos, effect->light.size, effect->light.dist,
effect->light.corona, effect->light.flareType, effect->light.roadReflection,
effect->light.flags&LIGHTFLAG_LOSCHECK, CCoronas::STREAK_OFF, 0.0f);
else if(lightFlickering)
CCoronas::RegisterCorona((uintptr)this + i,
0, 0, 0, 255,
pos, effect->light.size, effect->light.dist,
effect->light.corona, effect->light.flareType, effect->light.roadReflection,
effect->light.flags&LIGHTFLAG_LOSCHECK, CCoronas::STREAK_OFF, 0.0f);
// Pointlight
if(effect->light.flags & LIGHTFLAG_FOG_ALWAYS){
CPointLights::AddLight(CPointLights::LIGHT_FOGONLY_ALWAYS,
pos, CVector(0.0f, 0.0f, 0.0f),
effect->light.range,
effect->col.r/255.0f, effect->col.g/255.0f, effect->col.b/255.0f,
CPointLights::FOG_ALWAYS, true);
}else if(effect->light.flags & LIGHTFLAG_FOG_NORMAL && lightOn && effect->light.range == 0.0f){
CPointLights::AddLight(CPointLights::LIGHT_FOGONLY,
pos, CVector(0.0f, 0.0f, 0.0f),
effect->light.range,
effect->col.r/255.0f, effect->col.g/255.0f, effect->col.b/255.0f,
CPointLights::FOG_NORMAL, true);
}else if(lightOn && effect->light.range != 0.0f){
if(effect->col.r == 0 && effect->col.g == 0 && effect->col.b == 0){
CPointLights::AddLight(CPointLights::LIGHT_POINT,
pos, CVector(0.0f, 0.0f, 0.0f),
effect->light.range,
0.0f, 0.0f, 0.0f,
CPointLights::FOG_NONE, true);
}else{
CPointLights::AddLight(CPointLights::LIGHT_POINT,
pos, CVector(0.0f, 0.0f, 0.0f),
effect->light.range,
effect->col.r*CTimeCycle::GetSpriteBrightness()/255.0f,
effect->col.g*CTimeCycle::GetSpriteBrightness()/255.0f,
effect->col.b*CTimeCycle::GetSpriteBrightness()/255.0f,
// half-useless because LIGHTFLAG_FOG_ALWAYS can't be on
(effect->light.flags & LIGHTFLAG_FOG) >> 1,
true);
}
}
// Light shadow
if(effect->light.shadowRange != 0.0f){
if(lightOn){
CShadows::StoreStaticShadow((uintptr)this + i, SHADOWTYPE_2,
effect->light.shadow, &pos,
effect->light.shadowRange, 0.0f,
0.0f, -effect->light.shadowRange,
128,
effect->col.r*CTimeCycle::GetSpriteBrightness()*effect->light.shadowIntensity/255.0f,
effect->col.g*CTimeCycle::GetSpriteBrightness()*effect->light.shadowIntensity/255.0f,
effect->col.b*CTimeCycle::GetSpriteBrightness()*effect->light.shadowIntensity/255.0f,
15.0f, 1.0f, 40.0f, false, 0.0f);
}else if(lightFlickering){
CShadows::StoreStaticShadow((uintptr)this + i, SHADOWTYPE_2,
effect->light.shadow, &pos,
effect->light.shadowRange, 0.0f,
0.0f, -effect->light.shadowRange,
0, 0.0f, 0.0f, 0.0f,
15.0f, 1.0f, 40.0f, false, 0.0f);
}
}
}
}
float WindTabel[] = {
1.0f, 0.5f, 0.2f, 0.7f, 0.4f, 1.0f, 0.5f, 0.3f,
0.2f, 0.1f, 0.7f, 0.6f, 0.3f, 1.0f, 0.5f, 0.2f,
};
void
CEntity::ModifyMatrixForTreeInWind(void)
{
uint16 t;
float f;
float strength, flutter;
if(CTimer::GetIsPaused())
return;
CMatrix mat(GetMatrix().m_attachment);
if(CWeather::Wind >= 0.5){
t = m_randomSeed + 16*CTimer::GetTimeInMilliseconds();
f = (t & 0xFFF)/(float)0x1000;
flutter = f * WindTabel[(t>>12)+1 & 0xF] +
(1.0f - f) * WindTabel[(t>>12) & 0xF] +
1.0f;
strength = CWeather::Wind < 0.8f ? 0.008f : 0.014f;
}else if(CWeather::Wind >= 0.2){
t = (uintptr)this + CTimer::GetTimeInMilliseconds();
f = (t & 0xFFF)/(float)0x1000;
flutter = sin(f * 6.28f);
strength = 0.008f;
}else{
t = (uintptr)this + CTimer::GetTimeInMilliseconds();
f = (t & 0xFFF)/(float)0x1000;
flutter = sin(f * 6.28f);
strength = 0.005f;
}
mat.GetUp()->x = strength * flutter;
mat.GetUp()->y = mat.GetUp()->x;
mat.UpdateRW();
UpdateRwFrame();
}
float BannerWindTabel[] = {
0.0f, 0.3f, 0.6f, 0.85f, 0.99f, 0.97f, 0.65f, 0.15f,
-0.1f, 0.0f, 0.35f, 0.57f, 0.55f, 0.35f, 0.45f, 0.67f,
0.73f, 0.45f, 0.25f, 0.35f, 0.35f, 0.11f, 0.13f, 0.21f,
0.28f, 0.28f, 0.22f, 0.1f, 0.0f, -0.1f, -0.17f, -0.12f
};
void
CEntity::ModifyMatrixForBannerInWind(void)
{
uint16 t;
float f;
float strength, flutter;
CVector right, up;
if(CTimer::GetIsPaused())
return;
if(CWeather::Wind < 0.1f)
strength = 0.2f;
else if(CWeather::Wind < 0.8f)
strength = 0.43f;
else
strength = 0.66f;
t = ((int)(GetMatrix().GetPosition()->x + GetMatrix().GetPosition()->y) << 10) + 16*CTimer::GetTimeInMilliseconds();
f = (t & 0x7FF)/(float)0x800;
flutter = f * BannerWindTabel[(t>>11)+1 & 0x1F] +
(1.0f - f) * BannerWindTabel[(t>>11) & 0x1F];
flutter *= strength;
right = CrossProduct(GetForward(), GetUp());
right.z = 0.0f;
right.Normalise();
up = right * flutter;
up.z = sqrt(sq(1.0f) - sq(flutter));
GetRight() = CrossProduct(GetForward(), up);
GetUp() = up;
GetMatrix().UpdateRW();
UpdateRwFrame();
}
STARTPATCHES STARTPATCHES
InjectHook(0x473C30, &CEntity::ctor, PATCH_JUMP); InjectHook(0x473C30, &CEntity::ctor, PATCH_JUMP);
InjectHook(0x473E40, &CEntity::dtor, PATCH_JUMP); InjectHook(0x473E40, &CEntity::dtor, PATCH_JUMP);
@ -466,11 +884,18 @@ STARTPATCHES
InjectHook(0x473F10, &CEntity::AttachToRwObject, PATCH_JUMP); InjectHook(0x473F10, &CEntity::AttachToRwObject, PATCH_JUMP);
InjectHook(0x473F60, &CEntity::DetachFromRwObject, PATCH_JUMP); InjectHook(0x473F60, &CEntity::DetachFromRwObject, PATCH_JUMP);
InjectHook(0x475A20, &CEntity::PreRenderForGlassWindow, PATCH_JUMP);
InjectHook(0x50CE40, &CEntity::AddSteamsFromGround, PATCH_JUMP);
InjectHook(0x475670, &CEntity::ModifyMatrixForTreeInWind, PATCH_JUMP);
InjectHook(0x475830, &CEntity::ModifyMatrixForBannerInWind, PATCH_JUMP);
InjectHook(0x4FA530, &CEntity::ProcessLightsForEntity, PATCH_JUMP);
InjectHook(0x475080, &CEntity::Add_, PATCH_JUMP); InjectHook(0x475080, &CEntity::Add_, PATCH_JUMP);
InjectHook(0x475310, &CEntity::Remove_, PATCH_JUMP); InjectHook(0x475310, &CEntity::Remove_, PATCH_JUMP);
InjectHook(0x473EA0, &CEntity::CreateRwObject_, PATCH_JUMP); InjectHook(0x473EA0, &CEntity::CreateRwObject_, PATCH_JUMP);
InjectHook(0x473F90, &CEntity::DeleteRwObject_, PATCH_JUMP); InjectHook(0x473F90, &CEntity::DeleteRwObject_, PATCH_JUMP);
InjectHook(0x474000, &CEntity::GetBoundRect_, PATCH_JUMP); InjectHook(0x474000, &CEntity::GetBoundRect_, PATCH_JUMP);
InjectHook(0x474350, &CEntity::PreRender_, PATCH_JUMP);
InjectHook(0x474BD0, &CEntity::Render_, PATCH_JUMP); InjectHook(0x474BD0, &CEntity::Render_, PATCH_JUMP);
InjectHook(0x4A7C60, &CEntity::SetupLighting_, PATCH_JUMP); InjectHook(0x4A7C60, &CEntity::SetupLighting_, PATCH_JUMP);
ENDPATCHES ENDPATCHES

View File

@ -5,19 +5,6 @@
struct CReference; struct CReference;
enum eEntityFlags
{
IS_UNK = 0,
CONTROL_POSTPONED,
IS_EXPLOSIONPROOF,
IS_VISIBLE,
IS_ON_GROUND,
REQUIRES_SCORCHED_LIGHTS,
HAS_BLIP,
IS_BIG_BUILDING,
HAS_BEEN_DAMAGED,
};
enum eEntityType enum eEntityType
{ {
ENTITY_TYPE_NOTHING = 0, ENTITY_TYPE_NOTHING = 0,
@ -153,6 +140,12 @@ public:
void ResolveReferences(void); void ResolveReferences(void);
void PruneReferences(void); void PruneReferences(void);
void PreRenderForGlassWindow(void);
void AddSteamsFromGround(CVector *unused);
void ModifyMatrixForTreeInWind(void);
void ModifyMatrixForBannerInWind(void);
void ProcessLightsForEntity(void);
// to make patching virtual functions possible // to make patching virtual functions possible
CEntity *ctor(void) { return ::new (this) CEntity(); } CEntity *ctor(void) { return ::new (this) CEntity(); }
@ -163,6 +156,7 @@ public:
void CreateRwObject_(void) { CEntity::CreateRwObject(); } void CreateRwObject_(void) { CEntity::CreateRwObject(); }
void DeleteRwObject_(void) { CEntity::DeleteRwObject(); } void DeleteRwObject_(void) { CEntity::DeleteRwObject(); }
CRect GetBoundRect_(void) { return CEntity::GetBoundRect(); } CRect GetBoundRect_(void) { return CEntity::GetBoundRect(); }
void PreRender_(void) { CEntity::PreRender(); }
void Render_(void) { CEntity::Render(); } void Render_(void) { CEntity::Render(); }
bool SetupLighting_(void) { return CEntity::SetupLighting(); } bool SetupLighting_(void) { return CEntity::SetupLighting(); }
}; };

View File

@ -25,7 +25,7 @@ CObject::CObject(void)
m_colour2 = 0; m_colour2 = 0;
m_colour1 = m_colour2; m_colour1 = m_colour2;
field_172 = 0; field_172 = 0;
m_obj_flag1 = false; bIsPickup = false;
m_obj_flag2 = false; m_obj_flag2 = false;
m_obj_flag4 = false; m_obj_flag4 = false;
m_obj_flag8 = false; m_obj_flag8 = false;

View File

@ -32,7 +32,7 @@ public:
CMatrix m_objectMatrix; CMatrix m_objectMatrix;
float m_fUprootLimit; float m_fUprootLimit;
int8 ObjectCreatedBy; int8 ObjectCreatedBy;
int8 m_obj_flag1 : 1; int8 bIsPickup : 1;
int8 m_obj_flag2 : 1; int8 m_obj_flag2 : 1;
int8 m_obj_flag4 : 1; int8 m_obj_flag4 : 1;
int8 m_obj_flag8 : 1; int8 m_obj_flag8 : 1;

View File

@ -315,6 +315,21 @@ enum
MI_TOYZ, MI_TOYZ,
MI_GHOST, MI_GHOST,
MI_GRENADE = 170,
MI_AK47,
MI_BASEBALL_BAT,
MI_COLT,
MI_MOLOTOV,
MI_ROCKETLAUNCHER,
MI_SHOTGUN,
MI_SNIPER,
MI_UZI,
MI_MISSILE,
MI_M16,
MI_FLAMETHROWER,
MI_BOMB,
MI_FINGERS,
MI_CAR_DOOR = 190, MI_CAR_DOOR = 190,
MI_CAR_BUMPER, MI_CAR_BUMPER,
MI_CAR_PANEL, MI_CAR_PANEL,
@ -377,3 +392,65 @@ IsPedModel(int16 id)
{ {
return id >= 0 && id <= 89; return id >= 0 && id <= 89;
} }
inline bool
IsTreeModel(int16 id)
{
return id == MI_TREE1 ||
id == MI_TREE2 ||
id == MI_TREE3 ||
id == MI_TREE4 ||
id == MI_TREE5 ||
id == MI_TREE6 ||
id == MI_TREE7 ||
id == MI_TREE8 ||
id == MI_TREE9 ||
id == MI_TREE10 ||
id == MI_TREE11 ||
id == MI_TREE12 ||
id == MI_TREE13 ||
id == MI_TREE14;
}
inline bool
IsBannerModel(int16 id)
{
return id == MI_CHINABANNER1 ||
id == MI_CHINABANNER2 ||
id == MI_CHINABANNER3 ||
id == MI_CHINABANNER4 ||
id == MI_CHINABANNER5 ||
id == MI_CHINABANNER6 ||
id == MI_CHINABANNER7 ||
id == MI_CHINABANNER8 ||
id == MI_CHINABANNER9 ||
id == MI_CHINABANNER10 ||
id == MI_CHINABANNER11 ||
id == MI_CHINABANNER12 ||
id == MI_ITALYBANNER1 ||
id == MI_CHINALANTERN;
}
inline bool
IsPickupModel(int16 id)
{
return id == MI_GRENADE ||
id == MI_AK47 ||
id == MI_BASEBALL_BAT ||
id == MI_COLT ||
id == MI_MOLOTOV ||
id == MI_ROCKETLAUNCHER ||
id == MI_SHOTGUN ||
id == MI_SNIPER ||
id == MI_UZI ||
id == MI_M16 ||
id == MI_FLAMETHROWER ||
id >= MI_M16 && id <= MI_FLAMETHROWER ||
id == MI_PICKUP_ADRENALINE ||
id == MI_PICKUP_BODYARMOUR ||
id == MI_PICKUP_INFO ||
id == MI_PICKUP_HEALTH ||
id == MI_PICKUP_BONUS ||
id == MI_PICKUP_BRIBE ||
id == MI_PICKUP_KILLFRENZY ||
id == MI_PICKUP_CAMERA;
}

View File

@ -188,6 +188,7 @@ DebugMenuPopulate(void)
DebugMenuEntrySetWrap(e, true); DebugMenuEntrySetWrap(e, true);
e = DebugMenuAddVar("Time & Weather", "New Weather", (int16*)&CWeather::NewWeatherType, nil, 1, 0, 3, weathers); e = DebugMenuAddVar("Time & Weather", "New Weather", (int16*)&CWeather::NewWeatherType, nil, 1, 0, 3, weathers);
DebugMenuEntrySetWrap(e, true); DebugMenuEntrySetWrap(e, true);
DebugMenuAddVar("Time & Weather", "Wind", (float*)&CWeather::Wind, nil, 0.1f, 0.0f, 1.0f);
DebugMenuAddVar("Time & Weather", "Time scale", (float*)0x8F2C20, nil, 0.1f, 0.0f, 10.0f); DebugMenuAddVar("Time & Weather", "Time scale", (float*)0x8F2C20, nil, 0.1f, 0.0f, 10.0f);
DebugMenuAddCmd("Cheats", "Weapons", WeaponCheat); DebugMenuAddCmd("Cheats", "Weapons", WeaponCheat);

View File

@ -4,19 +4,45 @@ enum {
EFFECT_ATTRACTOR EFFECT_ATTRACTOR
}; };
enum {
LIGHT_ON,
LIGHT_ON_NIGHT,
LIGHT_FLICKER,
LIGHT_FLICKER_NIGHT,
LIGHT_FLASH1,
LIGHT_FLASH1_NIGHT,
LIGHT_FLASH2,
LIGHT_FLASH2_NIGHT,
LIGHT_FLASH3,
LIGHT_FLASH3_NIGHT,
LIGHT_RANDOM_FLICKER,
LIGHT_RANDOM_FLICKER_NIGHT,
LIGHT_SPECIAL,
LIGHT_BRIDGE_FLASH1,
LIGHT_BRIDGE_FLASH2,
};
enum {
LIGHTFLAG_LOSCHECK = 1,
// same order as CPointLights flags, must start at 2
LIGHTFLAG_FOG_NORMAL = 2, // can have light and fog
LIGHTFLAG_FOG_ALWAYS = 4, // fog only
LIGHTFLAG_FOG = (LIGHTFLAG_FOG_NORMAL|LIGHTFLAG_FOG_ALWAYS)
};
class C2dEffect class C2dEffect
{ {
public: public:
struct Light { struct Light {
float dist; float dist;
float outerRange; float range; // of pointlight
float size; float size;
float innerRange; float shadowRange;
uint8 flash; uint8 lightType; // LIGHT_
uint8 roadReflection; uint8 roadReflection;
uint8 flareType; uint8 flareType;
uint8 shadowIntensity; uint8 shadowIntensity;
uint8 flags; uint8 flags; // LIGHTFLAG_
RwTexture *corona; RwTexture *corona;
RwTexture *shadow; RwTexture *shadow;
}; };

View File

@ -2,6 +2,8 @@
#include "patcher.h" #include "patcher.h"
#include "Glass.h" #include "Glass.h"
WRAPPER void CGlass::AskForObjectToBeRenderedInGlass(CEntity *ent) { EAXJMP(0x5033F0); }
WRAPPER void WRAPPER void
CGlass::WindowRespondsToCollision(CEntity *ent, float amount, CVector speed, CVector point, bool foo) CGlass::WindowRespondsToCollision(CEntity *ent, float amount, CVector speed, CVector point, bool foo)
{ {

View File

@ -5,6 +5,7 @@ class CEntity;
class CGlass class CGlass
{ {
public: public:
static void AskForObjectToBeRenderedInGlass(CEntity *ent);
static void WindowRespondsToCollision(CEntity *ent, float amount, CVector speed, CVector point, bool foo); static void WindowRespondsToCollision(CEntity *ent, float amount, CVector speed, CVector point, bool foo);
static void WindowRespondsToSoftCollision(CEntity *ent, float amount); static void WindowRespondsToSoftCollision(CEntity *ent, float amount);
static void Render(void); static void Render(void);

View File

@ -13,8 +13,6 @@
int16 &CPointLights::NumLights = *(int16*)0x95CC3E; int16 &CPointLights::NumLights = *(int16*)0x95CC3E;
CRegisteredPointLight *CPointLights::aLights = (CRegisteredPointLight*)0x7096D0; CRegisteredPointLight *CPointLights::aLights = (CRegisteredPointLight*)0x7096D0;
//WRAPPER void CPointLights::RenderFogEffect(void) { EAXJMP(0x510C30); }
void void
CPointLights::InitPerFrame(void) CPointLights::InitPerFrame(void)
{ {
@ -69,7 +67,7 @@ CPointLights::GenerateLightsAffectingObject(CVector *objCoors)
ret = 1.0f; ret = 1.0f;
for(i = 0; i < NumLights; i++){ for(i = 0; i < NumLights; i++){
if(aLights[i].type == LIGHT_FOGONLY_3 || aLights[i].type == LIGHT_FOGONLY_4) if(aLights[i].type == LIGHT_FOGONLY || aLights[i].type == LIGHT_FOGONLY_ALWAYS)
continue; continue;
// same weird distance calculation. simplified here // same weird distance calculation. simplified here
@ -235,7 +233,7 @@ CPointLights::RenderFogEffect(void)
} }
} }
}else if(aLights[i].type == LIGHT_POINT || aLights[i].type == LIGHT_FOGONLY_3 || aLights[i].type == LIGHT_FOGONLY_4){ }else if(aLights[i].type == LIGHT_POINT || aLights[i].type == LIGHT_FOGONLY || aLights[i].type == LIGHT_FOGONLY_ALWAYS){
if(CWorld::ProcessVerticalLine(aLights[i].coors, aLights[i].coors.z - 20.0f, if(CWorld::ProcessVerticalLine(aLights[i].coors, aLights[i].coors.z - 20.0f,
point, entity, true, false, false, false, true, false, nil)){ point, entity, true, false, false, false, true, false, nil)){

View File

@ -26,8 +26,10 @@ public:
LIGHT_DIRECTIONAL, LIGHT_DIRECTIONAL,
LIGHT_DARKEN, // no effects at all LIGHT_DARKEN, // no effects at all
// these have only fog, otherwise no difference? // these have only fog, otherwise no difference?
LIGHT_FOGONLY_3, // only used by CEntity::ProcessLightsForEntity it seems
LIGHT_FOGONLY_4, // and there used together with fog type
LIGHT_FOGONLY_ALWAYS,
LIGHT_FOGONLY,
}; };
enum { enum {
FOG_NONE, FOG_NONE,

View File

@ -7,6 +7,16 @@ WRAPPER void CShadows::RenderStaticShadows(void) { EAXJMP(0x5145F0); }
WRAPPER void CShadows::RenderStoredShadows(void) { EAXJMP(0x514010); } WRAPPER void CShadows::RenderStoredShadows(void) { EAXJMP(0x514010); }
WRAPPER void CShadows::RenderExtraPlayerShadows(void) { EAXJMP(0x516F90); } WRAPPER void CShadows::RenderExtraPlayerShadows(void) { EAXJMP(0x516F90); }
WRAPPER void CShadows::CalcPedShadowValues(CVector light, float *frontX, float *frontY, float *sideX, float *sideY, float *dispX, float *dispY) { EAXJMP(0x516EB0); } WRAPPER void CShadows::CalcPedShadowValues(CVector light, float *frontX, float *frontY, float *sideX, float *sideY, float *dispX, float *dispY) { EAXJMP(0x516EB0); }
WRAPPER void CShadows::StoreShadowForPole(CEntity *ent, float offsetX, float offsetY, float offsetZ, float poleHeight, float poleWidth, uint32 subId) { EAXJMP(0x513E10); }
WRAPPER void CShadows::StoreShadowForPedObject(CEntity *ent, float dispX, float dispY, float frontX, float frontY, float sideX, float sideY) { EAXJMP(0x513CB0); } WRAPPER void CShadows::StoreShadowForPedObject(CEntity *ent, float dispX, float dispY, float frontX, float frontY, float sideX, float sideY) { EAXJMP(0x513CB0); }
WRAPPER void CShadows::StoreStaticShadow(uint32 id, uint8 type, RwTexture *texture, CVector *coors, float frontX, float frontY, float sideX, float sideY, int16 intensity, uint8 red, uint8 green, uint8 blue, float zDistance, float scale, float drawDistance, bool temporaryShadow, float upDistance) { EAXJMP(0x5130A0); }
WRAPPER void CShadows::StoreShadowToBeRendered(uint8 type, RwTexture *texture, CVector *coors, float frontX, float frontY, float sideX, float sideY, int16 intensity, uint8 red, uint8 green, uint8 blue, float zDistance, bool drawOnWater, float upDistance) { EAXJMP(0x513750); }
RwTexture*& gpBloodPoolTex = *(RwTexture * *)0x9415F8; RwTexture *&gpBloodPoolTex = *(RwTexture**)0x9415F8;
RwTexture *&gpShadowExplosionTex = *(RwTexture**)0x8F2A00;
void
CShadows::StoreShadowForTree(CEntity *ent)
{
// empty
}

View File

@ -3,6 +3,11 @@
struct RwTexture; struct RwTexture;
class CEntity; class CEntity;
enum
{
SHADOWTYPE_2 = 2
};
class CShadows class CShadows
{ {
public: public:
@ -11,7 +16,12 @@ public:
static void RenderStoredShadows(void); static void RenderStoredShadows(void);
static void RenderExtraPlayerShadows(void); static void RenderExtraPlayerShadows(void);
static void CalcPedShadowValues(CVector light, float *frontX, float *frontY, float *sideX, float *sideY, float *dispX, float *dispY); static void CalcPedShadowValues(CVector light, float *frontX, float *frontY, float *sideX, float *sideY, float *dispX, float *dispY);
static void StoreShadowForTree(CEntity *ent);
static void StoreShadowForPole(CEntity *ent, float offsetX, float offsetY, float offsetZ, float poleHeight, float poleWidth, uint32 subId);
static void StoreShadowForPedObject(CEntity *ent, float dispX, float dispY, float frontX, float frontY, float sideX, float sideY); static void StoreShadowForPedObject(CEntity *ent, float dispX, float dispY, float frontX, float frontY, float sideX, float sideY);
static void StoreStaticShadow(uint32 id, uint8 type, RwTexture *texture, CVector *coors, float frontX, float frontY, float sideX, float sideY, int16 intensity, uint8 red, uint8 green, uint8 blue, float zDistance, float scale, float drawDistance, bool temporaryShadow, float upDistance);;
static void StoreShadowToBeRendered(uint8 type, RwTexture *texture, CVector *coors, float frontX, float frontY, float sideX, float sideY, int16 intensity, uint8 red, uint8 green, uint8 blue, float zDistance, bool drawOnWater, float upDistance);
}; };
extern RwTexture*& gpBloodPoolTex; extern RwTexture *&gpBloodPoolTex;
extern RwTexture *&gpShadowExplosionTex;

View File

@ -3,3 +3,10 @@
#include "SpecialFX.h" #include "SpecialFX.h"
WRAPPER void CSpecialFX::Render(void) { EAXJMP(0x518DC0); } WRAPPER void CSpecialFX::Render(void) { EAXJMP(0x518DC0); }
WRAPPER void CMotionBlurStreaks::RegisterStreak(int32 id, uint8 r, uint8 g, uint8 b, CVector p1, CVector p2) { EAXJMP(0x519460); }
CBulletTrace (&CBulletTraces::aTraces)[16] = *(CBulletTrace(*)[16])*(uintptr*)0x72B1B8;
WRAPPER void CBulletTraces::Init(void) { EAXJMP(0x518DE0); }

View File

@ -5,3 +5,26 @@ class CSpecialFX
public: public:
static void Render(void); static void Render(void);
}; };
class CMotionBlurStreaks
{
public:
static void RegisterStreak(int32 id, uint8 r, uint8 g, uint8 b, CVector p1, CVector p2);
};
struct CBulletTrace
{
CVector m_vecInf;
CVector m_vecSup;
bool m_bInUse;
uint8 m_framesInUse;
uint8 m_lifeTime;
};
class CBulletTraces
{
public:
static CBulletTrace (&aTraces)[16];
static void Init(void);
};