diff --git a/README.md b/README.md
index 3e8a4a6b..6d4d6afd 100644
--- a/README.md
+++ b/README.md
@@ -1,76 +1,88 @@
-# Intro
+# re3
+[![Build status](https://ci.appveyor.com/api/projects/status/hyiwgegks122h8jg?svg=true)](https://ci.appveyor.com/project/aap/re3/branch/master)
+
+
+
+
+## Intro
The aim of this project is to reverse GTA III for PC by replacing
parts of the game [one by one](https://en.wikipedia.org/wiki/Ship_of_Theseus)
such that we have a working game at all times.
-Apparently you can download a binary of the latest version here:
-[Debug](https://ci.appveyor.com/api/projects/aap/re3/artifacts/bin/Debug/re3.dll?branch=master&job=Configuration%3A+Debug),
-[Release](https://ci.appveyor.com/api/projects/aap/re3/artifacts/bin/Release/re3.dll?branch=master&job=Configuration%3A+Release).
+## How can I try it?
-Build status:
-[![Build status](https://ci.appveyor.com/api/projects/status/hyiwgegks122h8jg?svg=true)](https://ci.appveyor.com/project/aap/re3/branch/master)
+- re3 requires game assets to work, so you need to own a copy of GTA III.
+- Since re3 is a DLL that works with original GTA III for now, you need Simple DLL Loader. You can get it [here](https://github.com/aap/simpledllloader).
+- Build re3 or download it from one of the above links (Debug or Release).
+- Make sure you included the re3 in `plugins.cfg` or `dlls.cfg`.
+- re3 starts the script `main_freeroam.scm` that comes along with it by default, so you should copy it to from `gamefiles/` to your game's `data/` directory.
-Re3 starts the script main_freeroam.scm by default. Make sure you copy it to your data directory.
+![#ffa500](https://placehold.it/15/ffa500/000000?text=+) **Notice**
-# Strategy
+If you want to load original script/story, press and hold G while game is loading.
+This includes both starting new game and loading save game.
+
+![#ffa500](https://placehold.it/15/ffa500/000000?text=+) **Notice if you will build it**
+
+There are various settings at the very bottom of `config.h`, you may want to take a look there. i.e. FIX_BUGS define fixes the bugs we've come across.
+
+https://github.com/GTAmodding/re3/tree/master/src/core/config.h
+
+## I want to contribute, where should I start?
A good approach is to start at the fringes of the code base,
i.e. classes that don't depend on code that we don't have reversed yet.
If a function uses only few unreversed functions that would be inconvenient
to reverse at the time, calling the original functions is acceptable.
-# Progress
-
-This is a list of some things that have been reversed to some non-trivial extent.
-Not everything is listed, check the code.
-(TODO: keep this list at least a bit up to date...)
-
+### Unreversed / incomplete classes (at least the ones we know)
```
-CPool
-CTxdStore
-CVector
-CVector2D
-CMatrix
-CModelInfo
-CBaseModelInfo
-CSimpleModelInfo
-CTimeModelInfo
-CClumpModelInfo
-CPedModelInfo
-CVehicleModelInfo
-CVisibilityPlugins
-CRenderer
-CSprite
-CSprite2d
-CFont
-CEntity
-CPhysical
-CCollision
-CCullZones
-CTheZones
-CPathFind
+CAudioManager, cDMAudio, cSampleManager and all audio - being worked on
+CAccidentManager
+CBoat
+CBrightLights
+CBulletInfo
+CBulletTraces
CCam
-CParticle
-CParticleMgr
-CPointLights
-CCoronas
-CAntennas
-CClouds
-CHud
+CCamera
+CCivilianPed
+CCopPed
+CCrane
+CCranes
+CCullZone
+CCullZones
+CEmergencyPed
+CExplosion
+CFallingGlassPane
+CFire
+CFireManager
+CGame
+CGarage
+CGarages
+CGlass
+CMenuManager
+CMotionBlurStreaks
+CPacManPickups
+CPed - being worked on
+CPedIK
+CPhoneInfo - one function left
+CPlayerInfo
+CPlayerPed
+CProjectile
+CProjectileInfo
+CRoadBlocks
+CRunningScript - being worked on
+CStats
+CSpecialFX
+CTrafficLights
+CWaterCannon
+CWaterCannons
+CWeapon
+CWeaponEffects
```
-# Low hanging fruit
-
-There are a couple of things that have been reversed for other projects
-already that could probably be put into this project without too much effort.
-Again, the list is not complete:
-
-* ~~Animation (https://github.com/aap/iii_anim)~~
-* File Loader (https://github.com/aap/librwgta/tree/master/tools/IIItest)
-* ...
-
-# Coding style
+### Coding style
I started writing in [Plan 9 style](http://man.cat-v.org/plan_9/6/style),
but realize that this is not the most popular style, so I'm willing to compromise.
@@ -178,7 +190,7 @@ but here are some observations:
* Generally, try to make the code look as if R* could have written it
-# Environment Variables
+### Environment Variables
Here you can find a list of variables that you might need to set in windows:
```
"GTA_III_RE_DIR" * path to "gta3_re" game folder usually where this plugin run.
diff --git a/src/animation/AnimManager.h b/src/animation/AnimManager.h
index d2e85c06..0d4e17fe 100644
--- a/src/animation/AnimManager.h
+++ b/src/animation/AnimManager.h
@@ -61,9 +61,9 @@ enum AnimationId
ANIM_KD_LEFT,
ANIM_KD_RIGHT,
ANIM_KO_SKID_FRONT,
- ANIM_KO_SPIN_R,
+ ANIM_KO_SPIN_R, // named left in VC
ANIM_KO_SKID_BACK,
- ANIM_KO_SPIN_L,
+ ANIM_KO_SPIN_L, // named right in VC
ANIM_SHOT_FRONT_PARTIAL,
ANIM_SHOT_LEFT_PARTIAL,
ANIM_SHOT_BACK_PARTIAL,
diff --git a/src/audio/AudioManager.cpp b/src/audio/AudioManager.cpp
index 3bfcb3a8..facf3a4a 100644
--- a/src/audio/AudioManager.cpp
+++ b/src/audio/AudioManager.cpp
@@ -38,11 +38,18 @@
#include "sampman.h"
cAudioManager &AudioManager = *(cAudioManager *)0x880FC0;
-uint32 *audioLogicTimers = (uint32 *)0x6508A0;
+uint32 &gPornNextTime = *(uint32*)0x6508A0;
+uint32 &gSawMillNextTime = *(uint32*)0x6508A4;
+uint32 &gShopNextTime = *(uint32*)0x6508A8;
+uint32 &gAirportNextTime = *(uint32*)0x6508AC;
+uint32 &gCinemaNextTime = *(uint32*)0x6508B0;
+uint32 &gDocksNextTime = *(uint32*)0x6508B4;
+uint32 &gHomeNextTime = *(uint32*)0x6508B8;
+uint32 &gCellNextTime = *(uint32*)0x6508BC;
+uint32 &gNextCryTime = *(uint32*)0x6508C0;
uint8 &jumboVolOffset = *(uint8 *)0x6508ED;
uint8 &gJumboVolOffsetPercentage = *(uint8 *)0x6508ED;
char &g_nMissionAudioPlayingStatus = *(char *)0x60ED88;
-int32 *BankStartOffset = (int32 *)0x6FAB70; //[2]
int32 &g_nMissionAudioSfx = *(int32 *)0x60ED84;
bool &bPlayerJustEnteredCar = *(bool *)0x6508C4;
bool &g_bMissionAudioLoadFailed = *(bool *)0x95CD8E;
@@ -415,47 +422,47 @@ cAudioManager::AddReleasingSounds()
{
bool toProcess[44];
- for(int32 i = 0; i < m_bSampleRequestQueuesStatus[m_bActiveSampleQueue]; i++) {
- tActiveSample &sample =
- m_asSamples[!m_bActiveSampleQueue][m_abSampleQueueIndexTable[!m_bActiveSampleQueue][i]];
- if(!m_asSamples[!m_bActiveSampleQueue][m_abSampleQueueIndexTable[!m_bActiveSampleQueue][i]]
- .m_bLoopEnded) {
- toProcess[i] = false;
- for(int32 j = 0; j < m_bSampleRequestQueuesStatus[m_bActiveSampleQueue]; j++) {
- if(sample.m_nEntityIndex ==
- m_asSamples[m_bActiveSampleQueue]
- [m_abSampleQueueIndexTable[m_bActiveSampleQueue][j]]
- .m_nEntityIndex &&
- sample.m_counter == m_asSamples[m_bActiveSampleQueue]
- [m_abSampleQueueIndexTable[m_bActiveSampleQueue][j]]
- .m_counter) {
- toProcess[i] = true;
- break;
- }
+ int8 queue = m_bActiveSampleQueue == 0;
+
+ for(int32 i = 0; i < m_bSampleRequestQueuesStatus[queue]; i++) {
+ tActiveSample &sample = m_asSamples[queue][m_abSampleQueueIndexTable[queue][i]];
+ if (sample.m_bLoopEnded) continue;
+
+ toProcess[i] = false;
+ for(int32 j = 0; j < m_bSampleRequestQueuesStatus[m_bActiveSampleQueue]; j++) {
+ if(sample.m_nEntityIndex ==
+ m_asSamples[m_bActiveSampleQueue]
+ [m_abSampleQueueIndexTable[m_bActiveSampleQueue][j]]
+ .m_nEntityIndex &&
+ sample.m_counter == m_asSamples[m_bActiveSampleQueue]
+ [m_abSampleQueueIndexTable[m_bActiveSampleQueue][j]]
+ .m_counter) {
+ toProcess[i] = true;
+ break;
}
- if(!toProcess[i]) {
- if(sample.m_counter <= 255u || !sample.m_bLoopsRemaining) {
- if(!sample.field_76) continue;
- if(!sample.m_nLoopCount) {
- if(sample.field_88 == -1) {
- sample.field_88 = sample.m_bVolume / sample.field_76;
- if(sample.field_88 <= 0) sample.field_88 = 1;
- }
- if(sample.m_bVolume <= sample.field_88) {
- sample.field_76 = 0;
- continue;
- }
- sample.m_bVolume -= sample.field_88;
+ }
+ if(!toProcess[i]) {
+ if(sample.m_counter <= 255u || !sample.m_bLoopsRemaining) {
+ if(!sample.field_76) continue;
+ if(!sample.m_nLoopCount) {
+ if(sample.field_88 == -1) {
+ sample.field_88 = sample.m_bVolume / sample.field_76;
+ if(sample.field_88 <= 0) sample.field_88 = 1;
}
- --sample.field_76;
- if(field_2) {
- if(sample.field_16 < 20) ++sample.field_16;
+ if(sample.m_bVolume <= sample.field_88) {
+ sample.field_76 = 0;
+ continue;
}
- sample.field_56 = 0;
+ sample.m_bVolume -= sample.field_88;
}
- memcpy(&m_sQueueSample, &sample, 92);
- AddSampleToRequestedQueue();
+ --sample.field_76;
+ if(field_2) {
+ if(sample.field_16 < 20) ++sample.field_16;
+ }
+ sample.field_56 = 0;
}
+ memcpy(&m_sQueueSample, &sample, sizeof(sample));
+ AddSampleToRequestedQueue();
}
}
}
@@ -625,7 +632,7 @@ cAudioManager::ComputeVolume(uint8 emittingVolume, float soundIntensity, float d
}
int32
-cAudioManager::CreateEntity(int32 type, CPhysical *entity)
+cAudioManager::CreateEntity(int32 type, void *entity)
{
if(!m_bIsInitialised) return -4;
if(!entity) return -2;
@@ -635,7 +642,7 @@ cAudioManager::CreateEntity(int32 type, CPhysical *entity)
m_asAudioEntities[i].m_bIsUsed = true;
m_asAudioEntities[i].m_bStatus = 0;
m_asAudioEntities[i].m_nType = (eAudioType)type;
- m_asAudioEntities[i].m_pEntity = (void *)entity;
+ m_asAudioEntities[i].m_pEntity = entity;
m_asAudioEntities[i].m_awAudioEvent[0] = SOUND_TOTAL_PED_SOUNDS;
m_asAudioEntities[i].m_awAudioEvent[1] = SOUND_TOTAL_PED_SOUNDS;
m_asAudioEntities[i].m_awAudioEvent[2] = SOUND_TOTAL_PED_SOUNDS;
@@ -2123,16 +2130,16 @@ 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); }
+ if(strcmpi(modelName, "eight") == 0 || strcmpi(modelName, "eight2") == 0) { return GetEightTalkSfx(sound); }
+ if(strcmpi(modelName, "frankie") == 0) { return GetFrankieTalkSfx(sound); }
+ if(strcmpi(modelName, "misty") == 0) { return GetMistyTalkSfx(sound); }
+ if(strcmpi(modelName, "ojg") == 0 || strcmpi(modelName, "ojg_p") == 0) { return GetOJGTalkSfx(sound); }
+ if(strcmpi(modelName, "cat") == 0) { return GetCatatalinaTalkSfx(sound); }
+ if(strcmpi(modelName, "bomber") == 0) { return GetBomberTalkSfx(sound); }
+ if(strcmpi(modelName, "s_guard") == 0) { return GetSecurityGuardTalkSfx(sound); }
+ if(strcmpi(modelName, "chunky") == 0) { return GetChunkyTalkSfx(sound); }
+ if(strcmpi(modelName, "asuka") == 0) { return GetGenericFemaleTalkSfx(sound); }
+ if(strcmpi(modelName, "maria") == 0) { return GetGenericFemaleTalkSfx(sound); }
return GetGenericMaleTalkSfx(sound);
}
@@ -2610,9 +2617,8 @@ char *SubZo3Label = (char *)0x6E9870;
void
cAudioManager::InitialisePoliceRadioZones()
{
- for(int32 i = 0; i < 36; i++) {
- for(int32 j = 0; j < 8; j++) { ZoneSfx[i].m_aName[j] = 0; }
- }
+ for(int32 i = 0; i < NUMAUDIOZONES; i++)
+ memset(ZoneSfx[i].m_aName, 0, 8);
strcpy(ZoneSfx[0].m_aName, "HOSPI_2");
ZoneSfx[0].m_nSampleIndex = SFX_POLICE_RADIO_ROCKFORD;
@@ -2988,26 +2994,25 @@ cAudioManager::PlayerJustLeftCar(void) const
void
cAudioManager::PostInitialiseGameSpecificSetup()
{
- m_nFireAudioEntity = CreateEntity(AUDIOTYPE_FIRE,
- (CPhysical *)0x8F31D0); // last is addr of firemanager @todo change
+ m_nFireAudioEntity = CreateEntity(AUDIOTYPE_FIRE, &gFireManager);
if(m_nFireAudioEntity >= 0) SetEntityStatus(m_nFireAudioEntity, 1);
- m_nCollisionEntity = CreateEntity(AUDIOTYPE_COLLISION, (CPhysical *)1);
+ m_nCollisionEntity = CreateEntity(AUDIOTYPE_COLLISION, (void*)1);
if(m_nCollisionEntity >= 0) SetEntityStatus(m_nCollisionEntity, 1);
- m_nFrontEndEntity = CreateEntity(AUDIOTYPE_FRONTEND, (CPhysical *)1);
+ m_nFrontEndEntity = CreateEntity(AUDIOTYPE_FRONTEND, (void*)1);
if(m_nFrontEndEntity >= 0) SetEntityStatus(m_nFrontEndEntity, 1);
- m_nProjectileEntity = CreateEntity(AUDIOTYPE_PROJECTILE, (CPhysical *)1);
+ m_nProjectileEntity = CreateEntity(AUDIOTYPE_PROJECTILE, (void*)1);
if(m_nProjectileEntity >= 0) SetEntityStatus(m_nProjectileEntity, 1);
- m_nWaterCannonEntity = CreateEntity(AUDIOTYPE_WATERCANNON, (CPhysical *)1);
+ m_nWaterCannonEntity = CreateEntity(AUDIOTYPE_WATERCANNON, (void*)1);
if(m_nWaterCannonEntity >= 0) SetEntityStatus(m_nWaterCannonEntity, 1);
- m_nPoliceChannelEntity = CreateEntity(AUDIOTYPE_POLICERADIO, (CPhysical *)1);
+ m_nPoliceChannelEntity = CreateEntity(AUDIOTYPE_POLICERADIO, (void*)1);
if(m_nPoliceChannelEntity >= 0) SetEntityStatus(m_nPoliceChannelEntity, 1);
- m_nBridgeEntity = CreateEntity(AUDIOTYPE_BRIDGE, (CPhysical *)1);
+ m_nBridgeEntity = CreateEntity(AUDIOTYPE_BRIDGE, (void*)1);
if(m_nBridgeEntity >= 0) SetEntityStatus(m_nBridgeEntity, 1);
m_sMissionAudio.m_nSampleIndex = NO_SAMPLE;
@@ -3017,7 +3022,7 @@ cAudioManager::PostInitialiseGameSpecificSetup()
m_sMissionAudio.m_bIsPlayed = 0;
m_sMissionAudio.field_12 = 1;
m_sMissionAudio.field_24 = 0;
- ResetAudioLogicTimers((int32)CTimer::GetTimeInMilliseconds);
+ ResetAudioLogicTimers(CTimer::GetTimeInMilliseconds());
}
void
@@ -3033,11 +3038,92 @@ cAudioManager::PreInitialiseGameSpecificSetup() const
BankStartOffset[1] = SFX_COP_VOICE_1_ARREST_1;
}
-WRAPPER
-void
-cAudioManager::PreloadMissionAudio(char *)
+struct MissionAudioData {
+ const char *m_pName;
+ int32 m_nId;
+};
+
+constexpr MissionAudioData MissionAudioNameSfxAssoc[] = {
+ {"lib_a1", STREAMED_SOUND_MISSION_LIB_A1}, {"lib_a2", STREAMED_SOUND_MISSION_LIB_A2},
+ {"lib_a", STREAMED_SOUND_MISSION_LIB_A}, {"lib_b", STREAMED_SOUND_MISSION_LIB_B},
+ {"lib_c", STREAMED_SOUND_MISSION_LIB_C}, {"lib_d", STREAMED_SOUND_MISSION_LIB_D},
+ {"l2_a", STREAMED_SOUND_MISSION_L2_A}, {"j4t_1", STREAMED_SOUND_MISSION_J4T_1},
+ {"j4t_2", STREAMED_SOUND_MISSION_J4T_2}, {"j4t_3", STREAMED_SOUND_MISSION_J4T_3},
+ {"j4t_4", STREAMED_SOUND_MISSION_J4T_4}, {"j4_a", STREAMED_SOUND_MISSION_J4_A},
+ {"j4_b", STREAMED_SOUND_MISSION_J4_B}, {"j4_c", STREAMED_SOUND_MISSION_J4_C},
+ {"j4_d", STREAMED_SOUND_MISSION_J4_D}, {"j4_e", STREAMED_SOUND_MISSION_J4_E},
+ {"j4_f", STREAMED_SOUND_MISSION_J4_F}, {"j6_1", STREAMED_SOUND_MISSION_J6_1},
+ {"j6_a", STREAMED_SOUND_MISSION_J6_A}, {"j6_b", STREAMED_SOUND_MISSION_J6_B},
+ {"j6_c", STREAMED_SOUND_MISSION_J6_C}, {"j6_d", STREAMED_SOUND_MISSION_J6_D},
+ {"t4_a", STREAMED_SOUND_MISSION_T4_A}, {"s1_a", STREAMED_SOUND_MISSION_S1_A},
+ {"s1_a1", STREAMED_SOUND_MISSION_S1_A1}, {"s1_b", STREAMED_SOUND_MISSION_S1_B},
+ {"s1_c", STREAMED_SOUND_MISSION_S1_C}, {"s1_c1", STREAMED_SOUND_MISSION_S1_C1},
+ {"s1_d", STREAMED_SOUND_MISSION_S1_D}, {"s1_e", STREAMED_SOUND_MISSION_S1_E},
+ {"s1_f", STREAMED_SOUND_MISSION_S1_F}, {"s1_g", STREAMED_SOUND_MISSION_S1_G},
+ {"s1_h", STREAMED_SOUND_MISSION_S1_H}, {"s1_i", STREAMED_SOUND_MISSION_S1_I},
+ {"s1_j", STREAMED_SOUND_MISSION_S1_J}, {"s1_k", STREAMED_SOUND_MISSION_S1_K},
+ {"s1_l", STREAMED_SOUND_MISSION_S1_L}, {"s3_a", STREAMED_SOUND_MISSION_S3_A},
+ {"s3_b", STREAMED_SOUND_MISSION_S3_B}, {"el3_a", STREAMED_SOUND_MISSION_EL3_A},
+ {"mf1_a", STREAMED_SOUND_MISSION_MF1_A}, {"mf2_a", STREAMED_SOUND_MISSION_MF2_A},
+ {"mf3_a", STREAMED_SOUND_MISSION_MF3_A}, {"mf3_b", STREAMED_SOUND_MISSION_MF3_B},
+ {"mf3_b1", STREAMED_SOUND_MISSION_MF3_B1}, {"mf3_c", STREAMED_SOUND_MISSION_MF3_C},
+ {"mf4_a", STREAMED_SOUND_MISSION_MF4_A}, {"mf4_b", STREAMED_SOUND_MISSION_MF4_B},
+ {"mf4_c", STREAMED_SOUND_MISSION_MF4_C}, {"a1_a", STREAMED_SOUND_MISSION_A1_A},
+ {"a3_a", STREAMED_SOUND_MISSION_A3_A}, {"a5_a", STREAMED_SOUND_MISSION_A5_A},
+ {"a4_a", STREAMED_SOUND_MISSION_A4_A}, {"a4_b", STREAMED_SOUND_MISSION_A4_B},
+ {"a4_c", STREAMED_SOUND_MISSION_A4_C}, {"a4_d", STREAMED_SOUND_MISSION_A4_D},
+ {"k1_a", STREAMED_SOUND_MISSION_K1_A}, {"k3_a", STREAMED_SOUND_MISSION_K3_A},
+ {"r1_a", STREAMED_SOUND_MISSION_R1_A}, {"r2_a", STREAMED_SOUND_MISSION_R2_A},
+ {"r2_b", STREAMED_SOUND_MISSION_R2_B}, {"r2_c", STREAMED_SOUND_MISSION_R2_C},
+ {"r2_d", STREAMED_SOUND_MISSION_R2_D}, {"r2_e", STREAMED_SOUND_MISSION_R2_E},
+ {"r2_f", STREAMED_SOUND_MISSION_R2_F}, {"r2_g", STREAMED_SOUND_MISSION_R2_G},
+ {"r2_h", STREAMED_SOUND_MISSION_R2_H}, {"r5_a", STREAMED_SOUND_MISSION_R5_A},
+ {"r6_a", STREAMED_SOUND_MISSION_R6_A}, {"r6_a1", STREAMED_SOUND_MISSION_R6_A1},
+ {"r6_b", STREAMED_SOUND_MISSION_R6_B}, {"lo2_a", STREAMED_SOUND_MISSION_LO2_A},
+ {"lo6_a", STREAMED_SOUND_MISSION_LO6_A}, {"yd2_a", STREAMED_SOUND_MISSION_YD2_A},
+ {"yd2_b", STREAMED_SOUND_MISSION_YD2_B}, {"yd2_c", STREAMED_SOUND_MISSION_YD2_C},
+ {"yd2_c1", STREAMED_SOUND_MISSION_YD2_C1}, {"yd2_d", STREAMED_SOUND_MISSION_YD2_D},
+ {"yd2_e", STREAMED_SOUND_MISSION_YD2_E}, {"yd2_f", STREAMED_SOUND_MISSION_YD2_F},
+ {"yd2_g", STREAMED_SOUND_MISSION_YD2_G}, {"yd2_h", STREAMED_SOUND_MISSION_YD2_H},
+ {"yd2_ass", STREAMED_SOUND_MISSION_YD2_ASS}, {"yd2_ok", STREAMED_SOUND_MISSION_YD2_OK},
+ {"h5_a", STREAMED_SOUND_MISSION_H5_A}, {"h5_b", STREAMED_SOUND_MISSION_H5_B},
+ {"h5_c", STREAMED_SOUND_MISSION_H5_C}, {"ammu_a", STREAMED_SOUND_MISSION_AMMU_A},
+ {"ammu_b", STREAMED_SOUND_MISSION_AMMU_B}, {"ammu_c", STREAMED_SOUND_MISSION_AMMU_C},
+ {"door_1", STREAMED_SOUND_MISSION_DOOR_1}, {"door_2", STREAMED_SOUND_MISSION_DOOR_2},
+ {"door_3", STREAMED_SOUND_MISSION_DOOR_3}, {"door_4", STREAMED_SOUND_MISSION_DOOR_4},
+ {"door_5", STREAMED_SOUND_MISSION_DOOR_5}, {"door_6", STREAMED_SOUND_MISSION_DOOR_6},
+ {"t3_a", STREAMED_SOUND_MISSION_T3_A}, {"t3_b", STREAMED_SOUND_MISSION_T3_B},
+ {"t3_c", STREAMED_SOUND_MISSION_T3_C}, {"k1_b", STREAMED_SOUND_MISSION_K1_B},
+ {"c_1", STREAMED_SOUND_MISSION_CAT1}};
+
+int32
+FindMissionAudioSfx(const char *name)
{
- EAXJMP(0x579550);
+ for(uint32 i = 0; i < ARRAY_SIZE(MissionAudioNameSfxAssoc); ++i) {
+ if(strcmpi(MissionAudioNameSfxAssoc[i].m_pName, name) == 0) return MissionAudioNameSfxAssoc[i].m_nId;
+ }
+ debug("Can't find mission audio %s", name);
+ return NO_SAMPLE;
+}
+
+void
+cAudioManager::PreloadMissionAudio(const char *name)
+{
+ if(m_bIsInitialised) {
+ int32 missionAudioSfx = FindMissionAudioSfx(name);
+ if(missionAudioSfx != NO_SAMPLE) {
+ m_sMissionAudio.m_nSampleIndex = missionAudioSfx;
+ m_sMissionAudio.m_bLoadingStatus = 0;
+ m_sMissionAudio.m_bPlayStatus = 0;
+ m_sMissionAudio.field_22 = 0;
+ m_sMissionAudio.field_24 =
+ field_19192 * SampleManager.GetStreamedFileLength(missionAudioSfx) / 1000;
+ m_sMissionAudio.field_24 *= 4;
+ m_sMissionAudio.m_bIsPlayed = 0;
+ m_sMissionAudio.field_12 = 1;
+ g_bMissionAudioLoadFailed = 0;
+ }
+ }
}
void
@@ -3129,7 +3215,7 @@ cAudioManager::ProcessAirportScriptObject(uint8 sound)
static uint8 counter = 0;
uint32 time = CTimer::GetTimeInMilliseconds();
- if(time > audioLogicTimers[3]) {
+ if(time > gAirportNextTime) {
switch(sound) {
case SCRIPT_SOUND_AIRPORT_LOOP_S:
maxDist = 900.f;
@@ -3164,7 +3250,7 @@ cAudioManager::ProcessAirportScriptObject(uint8 sound)
m_sQueueSample.m_bReverbFlag = 1;
m_sQueueSample.m_bRequireReflection = 0;
AddSampleToRequestedQueue();
- audioLogicTimers[3] = time + 10000 + m_anRandomTable[3] % 20000;
+ gAirportNextTime = time + 10000 + m_anRandomTable[3] % 20000;
}
}
}
@@ -3539,7 +3625,7 @@ cAudioManager::ProcessCinemaScriptObject(uint8 sound)
static uint8 counter = 0;
uint32 time = CTimer::GetTimeInMilliseconds();
- if(time > audioLogicTimers[4]) {
+ if(time > gCinemaNextTime) {
switch(sound) {
case SCRIPT_SOUND_CINEMA_LOOP_S:
maxDist = 900.f;
@@ -3575,7 +3661,7 @@ cAudioManager::ProcessCinemaScriptObject(uint8 sound)
m_sQueueSample.m_bReverbFlag = 1;
m_sQueueSample.m_bRequireReflection = 0;
AddSampleToRequestedQueue();
- audioLogicTimers[4] = time + 1000 + m_anRandomTable[3] % 4000;
+ gCinemaNextTime = time + 1000 + m_anRandomTable[3] % 4000;
}
}
}
@@ -3599,7 +3685,7 @@ cAudioManager::ProcessDocksScriptObject(uint8 sound)
static uint32 counter = 0;
time = CTimer::GetTimeInMilliseconds();
- if(time > audioLogicTimers[5]) {
+ if(time > gDocksNextTime) {
switch(sound) {
case SCRIPT_SOUND_DOCKS_LOOP_S:
maxDist = 900.f;
@@ -3634,7 +3720,7 @@ cAudioManager::ProcessDocksScriptObject(uint8 sound)
m_sQueueSample.m_bReverbFlag = 1;
m_sQueueSample.m_bRequireReflection = 0;
AddSampleToRequestedQueue();
- audioLogicTimers[5] = time + 10000 + m_anRandomTable[3] % 40000;
+ gDocksNextTime = time + 10000 + m_anRandomTable[3] % 40000;
}
}
}
@@ -3887,16 +3973,20 @@ void
cAudioManager::ProcessFrontEnd()
{
bool processed;
+ bool processedPickup;
+ bool processedMission;
int16 sample;
- static uint32 counter = 0;
+ static uint8 counter = 0;
+ static uint32 cPickupNextFrame = 0;
+ static uint32 cPartMisComNextFrame = 0;
for(uint32 i = 0; i < m_asAudioEntities[m_sQueueSample.m_nEntityIndex].m_AudioEvents; i++) {
+ processedPickup = 0;
processed = 0;
+ processedMission = 0;
switch(m_asAudioEntities[m_sQueueSample.m_nEntityIndex].m_awAudioEvent[i]) {
- case SOUND_WEAPON_SNIPER_SHOT_NO_ZOOM:
- m_sQueueSample.m_nSampleIndex = SFX_ERROR_FIRE_RIFLE;
- break;
+ case SOUND_WEAPON_SNIPER_SHOT_NO_ZOOM: m_sQueueSample.m_nSampleIndex = SFX_ERROR_FIRE_RIFLE; break;
case SOUND_WEAPON_ROCKET_SHOT_NO_ZOOM:
m_sQueueSample.m_nSampleIndex = SFX_ERROR_FIRE_ROCKET_LAUNCHER;
break;
@@ -3904,7 +3994,7 @@ cAudioManager::ProcessFrontEnd()
case SOUND_GARAGE_BAD_VEHICLE:
case SOUND_3C:
m_sQueueSample.m_nSampleIndex = SFX_PICKUP_ERROR_LEFT;
- processed = 1;
+ processed = true;
break;
case SOUND_GARAGE_OPENING:
case SOUND_GARAGE_BOMB1_SET:
@@ -3920,16 +4010,19 @@ cAudioManager::ProcessFrontEnd()
case SOUND_EVIDENCE_PICKUP:
case SOUND_UNLOAD_GOLD:
m_sQueueSample.m_nSampleIndex = SFX_PICKUP_2_LEFT;
- processed = 1;
+ processedPickup = true;
+ processed = true;
break;
case SOUND_PICKUP_WEAPON_BOUGHT:
case SOUND_PICKUP_WEAPON:
m_sQueueSample.m_nSampleIndex = SFX_PICKUP_1_LEFT;
- processed = 1;
+ processedPickup = true;
+ processed = true;
break;
case SOUND_4A:
m_sQueueSample.m_nSampleIndex = SFX_PICKUP_ERROR_LEFT;
- processed = 1;
+ processedPickup = true;
+ processed = true;
break;
case SOUND_PICKUP_BONUS:
case SOUND_PICKUP_MONEY:
@@ -3938,60 +4031,65 @@ cAudioManager::ProcessFrontEnd()
case SOUND_PICKUP_PACMAN_PACKAGE:
case SOUND_PICKUP_FLOAT_PACKAGE:
m_sQueueSample.m_nSampleIndex = SFX_PICKUP_3_LEFT;
- processed = 1;
+ processedPickup = true;
+ processed = true;
break;
case SOUND_PAGER: m_sQueueSample.m_nSampleIndex = SFX_PAGER; break;
case SOUND_RACE_START_3:
case SOUND_RACE_START_2:
case SOUND_RACE_START_1:
case SOUND_CLOCK_TICK: m_sQueueSample.m_nSampleIndex = SFX_TIMER_BEEP; break;
- case SOUND_RACE_START_GO:
- m_sQueueSample.m_nSampleIndex = SFX_PART_MISSION_COMPLETE;
- break;
+ case SOUND_RACE_START_GO: m_sQueueSample.m_nSampleIndex = SFX_PART_MISSION_COMPLETE; break;
case SOUND_PART_MISSION_COMPLETE:
m_sQueueSample.m_nSampleIndex = SFX_PART_MISSION_COMPLETE;
+ processedMission = true;
break;
case SOUND_FRONTEND_MENU_STARTING:
- processed = 1;
m_sQueueSample.m_nSampleIndex = SFX_START_BUTTON_LEFT;
+ processed = true;
break;
case SOUND_FRONTEND_MENU_COMPLETED:
- processed = 1;
m_sQueueSample.m_nSampleIndex = SFX_PAGE_CHANGE_AND_BACK_LEFT;
+ processed = true;
break;
case SOUND_FRONTEND_MENU_DENIED:
- processed = 1;
m_sQueueSample.m_nSampleIndex = SFX_HIGHLIGHT_LEFT;
+ processed = true;
break;
case SOUND_FRONTEND_MENU_SUCCESS:
- processed = 1;
m_sQueueSample.m_nSampleIndex = SFX_SELECT_LEFT;
+ processed = true;
break;
case SOUND_FRONTEND_EXIT:
- processed = 1;
m_sQueueSample.m_nSampleIndex = SFX_SUB_MENU_BACK_LEFT;
+ processed = true;
break;
case SOUND_9A:
- processed = 1;
m_sQueueSample.m_nSampleIndex = SFX_STEREO_LEFT;
+ processed = true;
break;
case SOUND_9B: m_sQueueSample.m_nSampleIndex = SFX_MONO; break;
case SOUND_FRONTEND_AUDIO_TEST:
- m_sQueueSample.m_nSampleIndex =
- m_anRandomTable[0] % 3 + SFX_NOISE_BURST_1;
+ m_sQueueSample.m_nSampleIndex = m_anRandomTable[0] % 3 + SFX_NOISE_BURST_1;
break;
case SOUND_FRONTEND_FAIL:
- processed = 1;
m_sQueueSample.m_nSampleIndex = SFX_ERROR_LEFT;
+ processed = true;
break;
case SOUND_FRONTEND_NO_RADIO:
- case SOUND_FRONTEND_RADIO_CHANGE:
- m_sQueueSample.m_nSampleIndex = SFX_RADIO_CLICK;
- break;
+ case SOUND_FRONTEND_RADIO_CHANGE: m_sQueueSample.m_nSampleIndex = SFX_RADIO_CLICK; break;
case SOUND_A0: m_sQueueSample.m_nSampleIndex = SFX_INFO; break;
default: continue;
}
+ if(processedPickup) {
+ if(m_nTimeOfRecentCrime <= cPickupNextFrame) continue;
+ cPickupNextFrame = m_nTimeOfRecentCrime + 5;
+ } else if(processedMission) {
+ if(m_nTimeOfRecentCrime <= cPartMisComNextFrame) continue;
+ cPartMisComNextFrame = m_nTimeOfRecentCrime + 5;
+ }
+
sample = m_asAudioEntities[m_sQueueSample.m_nEntityIndex].m_awAudioEvent[i];
if(sample == SFX_RAIN) {
m_sQueueSample.m_nFrequency = 28509;
@@ -4106,7 +4204,7 @@ cAudioManager::ProcessHomeScriptObject(uint8 sound)
static uint8 counter = 0;
time = CTimer::GetTimeInMilliseconds();
- if(time > audioLogicTimers[6]) {
+ if(time > gHomeNextTime) {
switch(sound) {
case SCRIPT_SOUND_HOME_LOOP_S:
maxDist = 900.f;
@@ -4142,7 +4240,7 @@ cAudioManager::ProcessHomeScriptObject(uint8 sound)
m_sQueueSample.m_bReverbFlag = 1;
m_sQueueSample.m_bRequireReflection = 1;
AddSampleToRequestedQueue();
- audioLogicTimers[6] = time + 1000 + m_anRandomTable[3] % 4000;
+ gHomeNextTime = time + 1000 + m_anRandomTable[3] % 4000;
}
}
}
@@ -5507,7 +5605,7 @@ cAudioManager::ProcessPedOneShots(cPedParams *params)
static uint8 iSound = 21;
weapon = nil;
- for(uint32 i = 0; i < m_asAudioEntities[m_sQueueSample.m_nEntityIndex].m_Loops; i++) {
+ for(uint32 i = 0; i < m_asAudioEntities[m_sQueueSample.m_nEntityIndex].m_AudioEvents; i++) {
noReflection = 0;
processed = 0;
m_sQueueSample.m_bRequireReflection = 0;
@@ -6666,7 +6764,7 @@ cAudioManager::ProcessPoliceCellBeatingScriptObject(uint8 sound)
static uint8 counter = 0;
- if(time > audioLogicTimers[7]) {
+ if(time > gCellNextTime) {
switch(sound) {
case SCRIPT_SOUND_POLICE_CELL_BEATING_LOOP_S:
maxDist = 900.f;
@@ -6711,7 +6809,7 @@ cAudioManager::ProcessPoliceCellBeatingScriptObject(uint8 sound)
params.m_pPed = 0;
SetupPedComments(¶ms, SOUND_8A);
}
- audioLogicTimers[7] = time + 500 + m_anRandomTable[3] % 1500;
+ gCellNextTime = time + 500 + m_anRandomTable[3] % 1500;
}
}
}
@@ -6800,7 +6898,7 @@ cAudioManager::ProcessPornCinema(uint8 sound)
}
time = CTimer::GetTimeInMilliseconds();
- if(time > audioLogicTimers[0]) {
+ if(time > gPornNextTime) {
m_sQueueSample.m_bVolume =
ComputeVolume(90, m_sQueueSample.m_fSoundIntensity, m_sQueueSample.m_fDistance);
if(m_sQueueSample.m_bVolume) {
@@ -6820,7 +6918,7 @@ cAudioManager::ProcessPornCinema(uint8 sound)
m_sQueueSample.m_bReverbFlag = 1;
m_sQueueSample.m_bRequireReflection = 0;
AddSampleToRequestedQueue();
- audioLogicTimers[0] = time + 2000 + m_anRandomTable[3] % 6000;
+ gPornNextTime = time + 2000 + m_anRandomTable[3] % 6000;
}
}
}
@@ -7025,7 +7123,7 @@ cAudioManager::ProcessSawMillScriptObject(uint8 sound)
AddSampleToRequestedQueue();
}
time = CTimer::GetTimeInMilliseconds();
- if(time > audioLogicTimers[1]) {
+ if(time > gSawMillNextTime) {
m_sQueueSample.m_bVolume =
ComputeVolume(70, m_sQueueSample.m_fSoundIntensity, m_sQueueSample.m_fDistance);
if(m_sQueueSample.m_bVolume) {
@@ -7044,7 +7142,7 @@ cAudioManager::ProcessSawMillScriptObject(uint8 sound)
m_sQueueSample.m_bReverbFlag = 1;
m_sQueueSample.m_bRequireReflection = 0;
AddSampleToRequestedQueue();
- audioLogicTimers[1] = time + 2000 + m_anRandomTable[3] % 4000;
+ gSawMillNextTime = time + 2000 + m_anRandomTable[3] % 4000;
}
}
}
@@ -7103,7 +7201,7 @@ cAudioManager::ProcessShopScriptObject(uint8 sound)
AddSampleToRequestedQueue();
}
time = CTimer::GetTimeInMilliseconds();
- if(time > audioLogicTimers[2]) {
+ if(time > gShopNextTime) {
m_sQueueSample.m_bVolume =
ComputeVolume(70, m_sQueueSample.m_fSoundIntensity, m_sQueueSample.m_fDistance);
if(m_sQueueSample.m_bVolume) {
@@ -7124,7 +7222,7 @@ cAudioManager::ProcessShopScriptObject(uint8 sound)
m_sQueueSample.m_bReverbFlag = 1;
m_sQueueSample.m_bRequireReflection = 0;
AddSampleToRequestedQueue();
- audioLogicTimers[2] = time + 3000 + m_anRandomTable[3] % 7000;
+ gShopNextTime = time + 3000 + m_anRandomTable[3] % 7000;
}
}
}
@@ -7912,17 +8010,17 @@ cAudioManager::ReportCrime(int32 type, const CVector *pos)
}
void
-cAudioManager::ResetAudioLogicTimers(int32 timer)
+cAudioManager::ResetAudioLogicTimers(uint32 timer)
{
- audioLogicTimers[0] = timer;
- audioLogicTimers[8] = timer;
- audioLogicTimers[1] = timer;
- audioLogicTimers[7] = timer;
- audioLogicTimers[2] = timer;
- audioLogicTimers[6] = timer;
- audioLogicTimers[3] = timer;
- audioLogicTimers[5] = timer;
- audioLogicTimers[4] = timer;
+ gPornNextTime = timer;
+ gNextCryTime = timer;
+ gSawMillNextTime = timer;
+ gCellNextTime = timer;
+ gShopNextTime = timer;
+ gHomeNextTime = timer;
+ gAirportNextTime = timer;
+ gDocksNextTime = timer;
+ gCinemaNextTime = timer;
for(int32 i = 0; i < m_nAudioEntitiesTotal; i++) {
if(m_asAudioEntities[m_anAudioEntityIndices[i]].m_nType == AUDIOTYPE_PHYSICAL) {
CPed *ped = (CPed *)m_asAudioEntities[m_anAudioEntityIndices[i]].m_pEntity;
@@ -8207,7 +8305,7 @@ cAudioManager::SetEffectsMasterVolume(uint8 volume) const
}
void
-cAudioManager::SetEntityStatus(int32 id, bool status)
+cAudioManager::SetEntityStatus(int32 id, uint8 status)
{
if(m_bIsInitialised && id >= 0 && id < totalAudioEntitiesSlots && m_asAudioEntities[id].m_bIsUsed) {
m_asAudioEntities[id].m_bStatus = status;
@@ -8811,10 +8909,10 @@ cAudioManager::SetupPedComments(cPedParams *params, uint32 sound)
SFX_POLICE_HELI_1;
break;
case SOUND_PED_BODYCAST_HIT:
- if(CTimer::GetTimeInMilliseconds() <= audioLogicTimers[8]) return;
+ if(CTimer::GetTimeInMilliseconds() <= gNextCryTime) return;
maxDist = 2500.f;
soundIntensity = 50.f;
- audioLogicTimers[8] = CTimer::GetTimeInMilliseconds() + 500;
+ gNextCryTime = CTimer::GetTimeInMilliseconds() + 500;
pedComment.m_nSampleIndex =
(m_anRandomTable[m_sQueueSample.m_nEntityIndex & 3] & 3) + SFX_PLASTER_BLOKE_1;
break;
@@ -8869,46 +8967,124 @@ cAudioManager::SetupPedComments(cPedParams *params, uint32 sound)
void
cAudioManager::SetupSuspectLastSeenReport()
{
- CAutomobile *automobile;
+ CVehicle *veh;
uint8 color1;
- int32 index;
int32 main_color;
int32 sample;
int32 color_pre_modifier;
int32 color_post_modifier;
- constexpr int32 colors[] = {
- 3032, 248, 3032, 3032, 249, 3032, 3032, 250, 3032, 3032, 251, 3032, 258, 250, 3032, 3032, 252, 3032,
- 3032, 253, 3032, 260, 250, 3032, 259, 250, 254, 259, 3032, 3032, 258, 3032, 3032, 258, 3032, 3032,
- 258, 251, 3032, 3032, 251, 3032, 3032, 251, 3032, 3032, 251, 3032, 3032, 251, 3032, 3032, 251, 3032,
- 3032, 251, 3032, 259, 3032, 3032, 258, 3032, 3032, 258, 3032, 3032, 258, 3032, 3032, 3032, 255, 3032,
- 3032, 255, 3032, 3032, 255, 3032, 3032, 255, 3032, 3032, 255, 3032, 3032, 255, 3032, 259, 3032, 3032,
- 258, 3032, 3032, 258, 3032, 3032, 258, 3032, 3032, 3032, 253, 3032, 3032, 253, 3032, 3032, 253, 3032,
- 3032, 253, 3032, 3032, 253, 3032, 3032, 253, 3032, 259, 3032, 3032, 258, 3032, 3032, 258, 3032, 3032,
- 258, 3032, 3032, 3032, 256, 3032, 3032, 256, 3032, 3032, 256, 3032, 3032, 256, 3032, 3032, 256, 3032,
- 3032, 256, 3032, 259, 3032, 3032, 258, 3032, 3032, 258, 3032, 3032, 258, 3032, 3032, 3032, 250, 3032,
- 3032, 250, 3032, 3032, 250, 3032, 3032, 250, 3032, 3032, 250, 3032, 3032, 250, 3032, 259, 3032, 3032,
- 258, 3032, 3032, 258, 3032, 3032, 258, 3032, 3032, 3032, 252, 3032, 3032, 252, 3032, 3032, 252, 3032,
- 3032, 252, 3032, 3032, 252, 3032, 3032, 252, 3032, 259, 3032, 3032, 258, 3032, 3032, 258, 3032, 3032,
- 258, 3032, 3032, 3032, 257, 3032, 3032, 257, 3032, 3032, 257, 3032, 3032, 257, 3032, 3032, 257, 3032,
- 3032, 257, 3032, 259, 3032, 3032, 259, 3032, 3032, 259, 3032, 3032, 259, 3032, 3032, 259, 3032, 3032,
- 259, 3032, 3032, 259, 3032, 3032, 259, 3032, 3032, 259, 3032, 3032, 259, 3032, 3032, 259, 3032, 3032,
- 258, 3032, 3032, 258, 3032, 3032, 258, 3032, 3032, 258, 3032, 3032, 258, 3032, 3032};
+ constexpr int32 gCarColourTable[][3] = {
+ {TOTAL_AUDIO_SAMPLES, SFX_POLICE_RADIO_BLACK, TOTAL_AUDIO_SAMPLES},
+ {TOTAL_AUDIO_SAMPLES, SFX_POLICE_RADIO_WHITE, TOTAL_AUDIO_SAMPLES},
+ {TOTAL_AUDIO_SAMPLES, SFX_POLICE_RADIO_BLUE, TOTAL_AUDIO_SAMPLES},
+ {TOTAL_AUDIO_SAMPLES, SFX_POLICE_RADIO_RED, TOTAL_AUDIO_SAMPLES},
+ {SFX_POLICE_RADIO_DARK, SFX_POLICE_RADIO_BLUE, TOTAL_AUDIO_SAMPLES},
+ {TOTAL_AUDIO_SAMPLES, SFX_POLICE_RADIO_PURPLE, TOTAL_AUDIO_SAMPLES},
+ {TOTAL_AUDIO_SAMPLES, SFX_POLICE_RADIO_YELLOW, TOTAL_AUDIO_SAMPLES},
+ {SFX_POLICE_RADIO_BRIGHT, SFX_POLICE_RADIO_BLUE, TOTAL_AUDIO_SAMPLES},
+ {SFX_POLICE_RADIO_LIGHT, SFX_POLICE_RADIO_BLUE, SFX_POLICE_RADIO_GREY},
+ {SFX_POLICE_RADIO_LIGHT, TOTAL_AUDIO_SAMPLES, TOTAL_AUDIO_SAMPLES},
+ {SFX_POLICE_RADIO_DARK, TOTAL_AUDIO_SAMPLES, TOTAL_AUDIO_SAMPLES},
+ {SFX_POLICE_RADIO_DARK, TOTAL_AUDIO_SAMPLES, TOTAL_AUDIO_SAMPLES},
+ {SFX_POLICE_RADIO_DARK, SFX_POLICE_RADIO_RED, TOTAL_AUDIO_SAMPLES},
+ {TOTAL_AUDIO_SAMPLES, SFX_POLICE_RADIO_RED, TOTAL_AUDIO_SAMPLES},
+ {TOTAL_AUDIO_SAMPLES, SFX_POLICE_RADIO_RED, TOTAL_AUDIO_SAMPLES},
+ {TOTAL_AUDIO_SAMPLES, SFX_POLICE_RADIO_RED, TOTAL_AUDIO_SAMPLES},
+ {TOTAL_AUDIO_SAMPLES, SFX_POLICE_RADIO_RED, TOTAL_AUDIO_SAMPLES},
+ {TOTAL_AUDIO_SAMPLES, SFX_POLICE_RADIO_RED, TOTAL_AUDIO_SAMPLES},
+ {TOTAL_AUDIO_SAMPLES, SFX_POLICE_RADIO_RED, TOTAL_AUDIO_SAMPLES},
+ {SFX_POLICE_RADIO_LIGHT, TOTAL_AUDIO_SAMPLES, TOTAL_AUDIO_SAMPLES},
+ {SFX_POLICE_RADIO_DARK, TOTAL_AUDIO_SAMPLES, TOTAL_AUDIO_SAMPLES},
+ {SFX_POLICE_RADIO_DARK, TOTAL_AUDIO_SAMPLES, TOTAL_AUDIO_SAMPLES},
+ {SFX_POLICE_RADIO_DARK, TOTAL_AUDIO_SAMPLES, TOTAL_AUDIO_SAMPLES},
+ {TOTAL_AUDIO_SAMPLES, SFX_POLICE_RADIO_ORANGE, TOTAL_AUDIO_SAMPLES},
+ {TOTAL_AUDIO_SAMPLES, SFX_POLICE_RADIO_ORANGE, TOTAL_AUDIO_SAMPLES},
+ {TOTAL_AUDIO_SAMPLES, SFX_POLICE_RADIO_ORANGE, TOTAL_AUDIO_SAMPLES},
+ {TOTAL_AUDIO_SAMPLES, SFX_POLICE_RADIO_ORANGE, TOTAL_AUDIO_SAMPLES},
+ {TOTAL_AUDIO_SAMPLES, SFX_POLICE_RADIO_ORANGE, TOTAL_AUDIO_SAMPLES},
+ {TOTAL_AUDIO_SAMPLES, SFX_POLICE_RADIO_ORANGE, TOTAL_AUDIO_SAMPLES},
+ {SFX_POLICE_RADIO_LIGHT, TOTAL_AUDIO_SAMPLES, TOTAL_AUDIO_SAMPLES},
+ {SFX_POLICE_RADIO_DARK, TOTAL_AUDIO_SAMPLES, TOTAL_AUDIO_SAMPLES},
+ {SFX_POLICE_RADIO_DARK, TOTAL_AUDIO_SAMPLES, TOTAL_AUDIO_SAMPLES},
+ {SFX_POLICE_RADIO_DARK, TOTAL_AUDIO_SAMPLES, TOTAL_AUDIO_SAMPLES},
+ {TOTAL_AUDIO_SAMPLES, SFX_POLICE_RADIO_YELLOW, TOTAL_AUDIO_SAMPLES},
+ {TOTAL_AUDIO_SAMPLES, SFX_POLICE_RADIO_YELLOW, TOTAL_AUDIO_SAMPLES},
+ {TOTAL_AUDIO_SAMPLES, SFX_POLICE_RADIO_YELLOW, TOTAL_AUDIO_SAMPLES},
+ {TOTAL_AUDIO_SAMPLES, SFX_POLICE_RADIO_YELLOW, TOTAL_AUDIO_SAMPLES},
+ {TOTAL_AUDIO_SAMPLES, SFX_POLICE_RADIO_YELLOW, TOTAL_AUDIO_SAMPLES},
+ {TOTAL_AUDIO_SAMPLES, SFX_POLICE_RADIO_YELLOW, TOTAL_AUDIO_SAMPLES},
+ {SFX_POLICE_RADIO_LIGHT, TOTAL_AUDIO_SAMPLES, TOTAL_AUDIO_SAMPLES},
+ {SFX_POLICE_RADIO_DARK, TOTAL_AUDIO_SAMPLES, TOTAL_AUDIO_SAMPLES},
+ {SFX_POLICE_RADIO_DARK, TOTAL_AUDIO_SAMPLES, TOTAL_AUDIO_SAMPLES},
+ {SFX_POLICE_RADIO_DARK, TOTAL_AUDIO_SAMPLES, TOTAL_AUDIO_SAMPLES},
+ {TOTAL_AUDIO_SAMPLES, SFX_POLICE_RADIO_GREEN, TOTAL_AUDIO_SAMPLES},
+ {TOTAL_AUDIO_SAMPLES, SFX_POLICE_RADIO_GREEN, TOTAL_AUDIO_SAMPLES},
+ {TOTAL_AUDIO_SAMPLES, SFX_POLICE_RADIO_GREEN, TOTAL_AUDIO_SAMPLES},
+ {TOTAL_AUDIO_SAMPLES, SFX_POLICE_RADIO_GREEN, TOTAL_AUDIO_SAMPLES},
+ {TOTAL_AUDIO_SAMPLES, SFX_POLICE_RADIO_GREEN, TOTAL_AUDIO_SAMPLES},
+ {TOTAL_AUDIO_SAMPLES, SFX_POLICE_RADIO_GREEN, TOTAL_AUDIO_SAMPLES},
+ {SFX_POLICE_RADIO_LIGHT, TOTAL_AUDIO_SAMPLES, TOTAL_AUDIO_SAMPLES},
+ {SFX_POLICE_RADIO_DARK, TOTAL_AUDIO_SAMPLES, TOTAL_AUDIO_SAMPLES},
+ {SFX_POLICE_RADIO_DARK, TOTAL_AUDIO_SAMPLES, TOTAL_AUDIO_SAMPLES},
+ {SFX_POLICE_RADIO_DARK, TOTAL_AUDIO_SAMPLES, TOTAL_AUDIO_SAMPLES},
+ {TOTAL_AUDIO_SAMPLES, SFX_POLICE_RADIO_BLUE, TOTAL_AUDIO_SAMPLES},
+ {TOTAL_AUDIO_SAMPLES, SFX_POLICE_RADIO_BLUE, TOTAL_AUDIO_SAMPLES},
+ {TOTAL_AUDIO_SAMPLES, SFX_POLICE_RADIO_BLUE, TOTAL_AUDIO_SAMPLES},
+ {TOTAL_AUDIO_SAMPLES, SFX_POLICE_RADIO_BLUE, TOTAL_AUDIO_SAMPLES},
+ {TOTAL_AUDIO_SAMPLES, SFX_POLICE_RADIO_BLUE, TOTAL_AUDIO_SAMPLES},
+ {TOTAL_AUDIO_SAMPLES, SFX_POLICE_RADIO_BLUE, TOTAL_AUDIO_SAMPLES},
+ {SFX_POLICE_RADIO_LIGHT, TOTAL_AUDIO_SAMPLES, TOTAL_AUDIO_SAMPLES},
+ {SFX_POLICE_RADIO_DARK, TOTAL_AUDIO_SAMPLES, TOTAL_AUDIO_SAMPLES},
+ {SFX_POLICE_RADIO_DARK, TOTAL_AUDIO_SAMPLES, TOTAL_AUDIO_SAMPLES},
+ {SFX_POLICE_RADIO_DARK, TOTAL_AUDIO_SAMPLES, TOTAL_AUDIO_SAMPLES},
+ {TOTAL_AUDIO_SAMPLES, SFX_POLICE_RADIO_PURPLE, TOTAL_AUDIO_SAMPLES},
+ {TOTAL_AUDIO_SAMPLES, SFX_POLICE_RADIO_PURPLE, TOTAL_AUDIO_SAMPLES},
+ {TOTAL_AUDIO_SAMPLES, SFX_POLICE_RADIO_PURPLE, TOTAL_AUDIO_SAMPLES},
+ {TOTAL_AUDIO_SAMPLES, SFX_POLICE_RADIO_PURPLE, TOTAL_AUDIO_SAMPLES},
+ {TOTAL_AUDIO_SAMPLES, SFX_POLICE_RADIO_PURPLE, TOTAL_AUDIO_SAMPLES},
+ {TOTAL_AUDIO_SAMPLES, SFX_POLICE_RADIO_PURPLE, TOTAL_AUDIO_SAMPLES},
+ {SFX_POLICE_RADIO_LIGHT, TOTAL_AUDIO_SAMPLES, TOTAL_AUDIO_SAMPLES},
+ {SFX_POLICE_RADIO_DARK, TOTAL_AUDIO_SAMPLES, TOTAL_AUDIO_SAMPLES},
+ {SFX_POLICE_RADIO_DARK, TOTAL_AUDIO_SAMPLES, TOTAL_AUDIO_SAMPLES},
+ {SFX_POLICE_RADIO_DARK, TOTAL_AUDIO_SAMPLES, TOTAL_AUDIO_SAMPLES},
+ {TOTAL_AUDIO_SAMPLES, SFX_POLICE_RADIO_SILVER, TOTAL_AUDIO_SAMPLES},
+ {TOTAL_AUDIO_SAMPLES, SFX_POLICE_RADIO_SILVER, TOTAL_AUDIO_SAMPLES},
+ {TOTAL_AUDIO_SAMPLES, SFX_POLICE_RADIO_SILVER, TOTAL_AUDIO_SAMPLES},
+ {TOTAL_AUDIO_SAMPLES, SFX_POLICE_RADIO_SILVER, TOTAL_AUDIO_SAMPLES},
+ {TOTAL_AUDIO_SAMPLES, SFX_POLICE_RADIO_SILVER, TOTAL_AUDIO_SAMPLES},
+ {TOTAL_AUDIO_SAMPLES, SFX_POLICE_RADIO_SILVER, TOTAL_AUDIO_SAMPLES},
+ {SFX_POLICE_RADIO_LIGHT, TOTAL_AUDIO_SAMPLES, TOTAL_AUDIO_SAMPLES},
+ {SFX_POLICE_RADIO_LIGHT, TOTAL_AUDIO_SAMPLES, TOTAL_AUDIO_SAMPLES},
+ {SFX_POLICE_RADIO_LIGHT, TOTAL_AUDIO_SAMPLES, TOTAL_AUDIO_SAMPLES},
+ {SFX_POLICE_RADIO_LIGHT, TOTAL_AUDIO_SAMPLES, TOTAL_AUDIO_SAMPLES},
+ {SFX_POLICE_RADIO_LIGHT, TOTAL_AUDIO_SAMPLES, TOTAL_AUDIO_SAMPLES},
+ {SFX_POLICE_RADIO_LIGHT, TOTAL_AUDIO_SAMPLES, TOTAL_AUDIO_SAMPLES},
+ {SFX_POLICE_RADIO_LIGHT, TOTAL_AUDIO_SAMPLES, TOTAL_AUDIO_SAMPLES},
+ {SFX_POLICE_RADIO_LIGHT, TOTAL_AUDIO_SAMPLES, TOTAL_AUDIO_SAMPLES},
+ {SFX_POLICE_RADIO_LIGHT, TOTAL_AUDIO_SAMPLES, TOTAL_AUDIO_SAMPLES},
+ {SFX_POLICE_RADIO_LIGHT, TOTAL_AUDIO_SAMPLES, TOTAL_AUDIO_SAMPLES},
+ {SFX_POLICE_RADIO_LIGHT, TOTAL_AUDIO_SAMPLES, TOTAL_AUDIO_SAMPLES},
+ {SFX_POLICE_RADIO_DARK, TOTAL_AUDIO_SAMPLES, TOTAL_AUDIO_SAMPLES},
+ {SFX_POLICE_RADIO_DARK, TOTAL_AUDIO_SAMPLES, TOTAL_AUDIO_SAMPLES},
+ {SFX_POLICE_RADIO_DARK, TOTAL_AUDIO_SAMPLES, TOTAL_AUDIO_SAMPLES},
+ {SFX_POLICE_RADIO_DARK, TOTAL_AUDIO_SAMPLES, TOTAL_AUDIO_SAMPLES},
+ {SFX_POLICE_RADIO_DARK, TOTAL_AUDIO_SAMPLES, TOTAL_AUDIO_SAMPLES}
+ };
- if(MusicManager.m_nMusicMode != 2) {
- automobile = (CAutomobile *)FindPlayerVehicle();
- if(automobile) {
+ if(MusicManager.m_nMusicMode != MUSICMODE_CUTSCENE) {
+ veh = FindPlayerVehicle();
+ if(veh) {
if(60 - policeChannelTimer > 9) {
- color1 = automobile->m_currentColour1;
- if(color1 >= 95) {
+ color1 = veh->m_currentColour1;
+ if(color1 >= ARRAY_SIZE(gCarColourTable)) {
debug("\n *** UNKNOWN CAR COLOUR %d *** ", color1);
} else {
- index = 3 * color1;
- main_color = colors[index + 1]; // todo refactor struct
- color_pre_modifier = colors[index];
- color_post_modifier = colors[index + 2];
- switch(automobile->m_modelIndex) {
+ main_color = gCarColourTable[color1][1];
+ color_pre_modifier = gCarColourTable[color1][0];
+ color_post_modifier = gCarColourTable[color1][2];
+ switch(veh->m_modelIndex) {
case MI_LANDSTAL:
case MI_BLISTA: sample = SFX_POLICE_RADIO_CRUISER; break;
case MI_IDAHO:
@@ -8959,7 +9135,7 @@ cAudioManager::SetupSuspectLastSeenReport()
break;
default:
debug("\n *** UNKNOWN CAR MODEL INDEX %d *** ",
- automobile->m_modelIndex);
+ veh->m_modelIndex);
return;
}
if(policeChannelTimer != 60) {
@@ -8995,17 +9171,17 @@ cAudioManager::SetupSuspectLastSeenReport()
++policeChannelTimer;
policeChannelTimerSeconds = (policeChannelTimerSeconds + 1) % 60;
}
- if(color_pre_modifier != 3032 && policeChannelTimer != 60) {
+ if(color_pre_modifier != TOTAL_AUDIO_SAMPLES && policeChannelTimer != 60) {
crimesSamples[policeChannelTimerSeconds] = color_pre_modifier;
++policeChannelTimer;
policeChannelTimerSeconds = (policeChannelTimerSeconds + 1) % 60;
}
- if(main_color != 3032 && policeChannelTimer != 60) {
+ if(main_color != TOTAL_AUDIO_SAMPLES && policeChannelTimer != 60) {
crimesSamples[policeChannelTimerSeconds] = main_color;
++policeChannelTimer;
policeChannelTimerSeconds = (policeChannelTimerSeconds + 1) % 60;
}
- if(color_post_modifier != 3032 && policeChannelTimer != 60) {
+ if(color_post_modifier != TOTAL_AUDIO_SAMPLES && policeChannelTimer != 60) {
crimesSamples[policeChannelTimerSeconds] = color_post_modifier;
++policeChannelTimer;
policeChannelTimerSeconds = (policeChannelTimerSeconds + 1) % 60;
@@ -9113,11 +9289,75 @@ cAudioManager::UpdateGasPedalAudio(CAutomobile *automobile)
automobile->m_fGasPedalAudio = newGasPedalAudio;
}
-WRAPPER
void
cAudioManager::UpdateReflections()
{
- EAXJMP(0x57B470);
+ const CVector &camPos = TheCamera.GetPosition();
+ CColPoint colpoint;
+ CEntity *ent;
+
+ if(m_nTimeOfRecentCrime & 7) {
+ if(((uint8)m_nTimeOfRecentCrime + 1) & 7) {
+ if(((uint8)m_nTimeOfRecentCrime + 2) & 7) {
+ if(((uint8)m_nTimeOfRecentCrime + 3) & 7) {
+ if(!(((uint8)m_nTimeOfRecentCrime + 4) & 7)) {
+ m_avecReflectionsPos[4] = camPos;
+ m_avecReflectionsPos[4].z += 50.f;
+ if(CWorld::ProcessVerticalLine(
+ camPos, m_avecReflectionsPos[4].z, colpoint,
+ ent, true, false, false, false, true, false,
+ false)) {
+ m_afReflectionsDistances[4] =
+ colpoint.point.z - camPos.z;
+ } else {
+ m_afReflectionsDistances[4] = 50.0f;
+ }
+ }
+ } else {
+ m_avecReflectionsPos[3] = camPos;
+ m_avecReflectionsPos[3].x += 50.f;
+ if(CWorld::ProcessLineOfSight(
+ camPos, m_avecReflectionsPos[3], colpoint, ent, true,
+ false, false, true, false, true, true)) {
+ m_afReflectionsDistances[3] =
+ Distance(camPos, colpoint.point);
+ } else {
+ m_afReflectionsDistances[3] = 50.0f;
+ }
+ }
+ } else {
+ m_avecReflectionsPos[2] = camPos;
+ m_avecReflectionsPos[2].x -= 50.f;
+ if(CWorld::ProcessLineOfSight(camPos, m_avecReflectionsPos[2],
+ colpoint, ent, true, false, false,
+ true, false, true, true)) {
+ m_afReflectionsDistances[2] =
+ Distance(camPos, colpoint.point);
+ } else {
+ m_afReflectionsDistances[2] = 50.0f;
+ }
+ }
+ } else {
+ m_avecReflectionsPos[1] = camPos;
+ m_avecReflectionsPos[1].y -= 50.f;
+ if(CWorld::ProcessLineOfSight(camPos, m_avecReflectionsPos[1], colpoint,
+ ent, true, false, false, true, false, true,
+ true)) {
+ m_afReflectionsDistances[1] = Distance(camPos, colpoint.point);
+ } else {
+ m_afReflectionsDistances[1] = 50.0f;
+ }
+ }
+ } else {
+ m_avecReflectionsPos[0] = camPos;
+ m_avecReflectionsPos[0].y += 50.f;
+ if(CWorld::ProcessLineOfSight(camPos, m_avecReflectionsPos[0], colpoint, ent, true,
+ false, false, true, false, true, true)) {
+ m_afReflectionsDistances[0] = Distance(camPos, colpoint.point);
+ } else {
+ m_afReflectionsDistances[0] = 50.0f;
+ }
+ }
}
bool
@@ -9299,6 +9539,7 @@ InjectHook(0x580500, &cAudioManager::PlaySuspectLastSeen, PATCH_JUMP);
InjectHook(0x569420, &cAudioManager::PostInitialiseGameSpecificSetup, PATCH_JUMP);
InjectHook(0x569640, &cAudioManager::PostTerminateGameSpecificShutdown, PATCH_JUMP);
InjectHook(0x569400, &cAudioManager::PreInitialiseGameSpecificSetup, PATCH_JUMP);
+InjectHook(0x579550, &cAudioManager::PreloadMissionAudio, PATCH_JUMP);
InjectHook(0x569570, &cAudioManager::PreTerminateGameSpecificShutdown, PATCH_JUMP);
// InjectHook(0x57BA60, &cAudioManager::ProcessActiveQueues, PATCH_JUMP);
InjectHook(0x56C940, &cAudioManager::ProcessAirBrakes, PATCH_JUMP);
@@ -9393,6 +9634,7 @@ InjectHook(0x57FCC0, &cAudioManager::SetupSuspectLastSeenReport, PATCH_JUMP);
InjectHook(0x57A150, &cAudioManager::Terminate, PATCH_JUMP);
InjectHook(0x57AC60, &cAudioManager::TranslateEntity, PATCH_JUMP);
InjectHook(0x56AC80, &cAudioManager::UpdateGasPedalAudio, PATCH_JUMP);
+InjectHook(0x57B470, &cAudioManager::UpdateReflections, PATCH_JUMP);
InjectHook(0x56C600, &cAudioManager::UsesReverseWarning, PATCH_JUMP);
InjectHook(0x56C3C0, &cAudioManager::UsesSiren, PATCH_JUMP);
InjectHook(0x56C3F0, &cAudioManager::UsesSirenSwitching, PATCH_JUMP);
diff --git a/src/audio/AudioManager.h b/src/audio/AudioManager.h
index ef7900e2..19809286 100644
--- a/src/audio/AudioManager.h
+++ b/src/audio/AudioManager.h
@@ -449,7 +449,7 @@ public:
float speedMultiplier) const; /// ok
int32 ComputePan(float, CVector *); /// ok
uint8 ComputeVolume(uint8 emittingVolume, float soundIntensity, float distance) const; /// ok
- int32 CreateEntity(int32 type, CPhysical *entity); /// ok
+ int32 CreateEntity(int32 type, void* entity); /// ok
void DestroyAllGameCreatedEntities(); /// ok
void DestroyEntity(int32 id); /// ok
@@ -576,8 +576,8 @@ public:
void PlayerJustLeftCar() const; /// ok
void PostInitialiseGameSpecificSetup(); /// ok
void PostTerminateGameSpecificShutdown(); /// ok
- void PreInitialiseGameSpecificSetup() const; // ok
- void PreloadMissionAudio(char *); // todo
+ void PreInitialiseGameSpecificSetup() const; /// ok
+ void PreloadMissionAudio(const char *name); /// ok
void PreTerminateGameSpecificShutdown(); /// ok
/// processX - main logic of adding new sounds
void ProcessActiveQueues(); // todo
@@ -653,7 +653,7 @@ public:
void ReportCollision(CEntity *entity1, CEntity *entity2, uint8 surface1, uint8 surface2,
float collisionPower, float intensity2); /// ok
void ReportCrime(int32 crime, const CVector *pos); /// ok
- void ResetAudioLogicTimers(int32 timer); /// ok
+ void ResetAudioLogicTimers(uint32 timer); /// ok
void ResetPoliceRadio(); /// ok
void ResetTimers(uint32 time); /// ok
@@ -666,7 +666,7 @@ public:
void SetDynamicAcousticModelingStatus(bool status);
void SetEffectsFadeVolume(uint8 volume) const;
void SetEffectsMasterVolume(uint8 volume) const;
- void SetEntityStatus(int32 id, bool status);
+ void SetEntityStatus(int32 id, uint8 status);
uint32 SetLoopingCollisionRequestedSfxFreqAndGetVol(cAudioCollision *audioCollision); /// ok
void SetMissionAudioLocation(float x, float y, float z);
void SetMissionScriptPoliceAudio(int32 sfx) const;
@@ -689,7 +689,7 @@ public:
void TranslateEntity(CVector *v1, CVector *v2) const;
void UpdateGasPedalAudio(CAutomobile *automobile);
- void UpdateReflections(); // todo
+ void UpdateReflections();
bool UsesReverseWarning(int32 model) const;
bool UsesSiren(int32 model) const;
bool UsesSirenSwitching(int32 model) const;
diff --git a/src/audio/sampman.cpp b/src/audio/sampman.cpp
index 9bb2687d..53b81a36 100644
--- a/src/audio/sampman.cpp
+++ b/src/audio/sampman.cpp
@@ -18,7 +18,7 @@
#pragma comment( lib, "mss32.lib" )
cSampleManager &SampleManager = *(cSampleManager *)0x7341E0;
-int32 (&BankStartOffset)[MAX_SAMPLEBANKS] = *(int32 (*)[MAX_SAMPLEBANKS])*(int *)0x6FAB70;
+extern int32 (&BankStartOffset)[MAX_SAMPLEBANKS] = *(int32 (*)[MAX_SAMPLEBANKS])*(int *)0x6FAB70;
///////////////////////////////////////////////////////////////
@@ -2327,4 +2327,4 @@ STARTPATCHES
InjectHook(0x568290, &cSampleManager::IsStreamPlaying, PATCH_JUMP);
InjectHook(0x5682D0, &cSampleManager::InitialiseSampleBanks, PATCH_JUMP);
//InjectHook(0x5683F0, `global constructor keyed to'sampman.cpp, PATCH_JUMP);
-ENDPATCHES
\ No newline at end of file
+ENDPATCHES
diff --git a/src/audio/sampman.h b/src/audio/sampman.h
index def4853f..ae27cdbf 100644
--- a/src/audio/sampman.h
+++ b/src/audio/sampman.h
@@ -135,6 +135,7 @@ public:
};
extern cSampleManager &SampleManager;
+extern int32 (&BankStartOffset)[MAX_SAMPLEBANKS];
static char StreamedNameTable[][25]=
{
@@ -334,4 +335,4 @@ static char StreamedNameTable[][25]=
"AUDIO\\t3_c.WAV",
"AUDIO\\k1_b.WAV",
"AUDIO\\cat1.WAV"
-};
\ No newline at end of file
+};
diff --git a/src/control/Pickups.cpp b/src/control/Pickups.cpp
index 91fd889c..52861e99 100644
--- a/src/control/Pickups.cpp
+++ b/src/control/Pickups.cpp
@@ -660,7 +660,7 @@ CPickups::DoPickUpEffects(CEntity *entity)
if (!entity->m_flagD80) {
float s = Sin((float)((CTimer::GetTimeInMilliseconds() + (uintptr)entity) & 0x7FF) * DEGTORAD(360.0f / 0x800));
- float modifiedSin = 0.3 * (s + 1.0f);
+ float modifiedSin = 0.3f * (s + 1.0f);
int16 colorId;
diff --git a/src/control/Script.cpp b/src/control/Script.cpp
index ccb551dd..d361045c 100644
--- a/src/control/Script.cpp
+++ b/src/control/Script.cpp
@@ -4677,7 +4677,7 @@ int8 CRunningScript::ProcessCommandsFrom500To599(int32 command)
CollectParameters(&m_nIp, 2);
CPlayerPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed;
assert(pPed);
- pPed->m_fHealth = *(float*)&ScriptParams[1];
+ pPed->m_fHealth = ScriptParams[1];
return 0;
}
case COMMAND_SET_CHAR_HEALTH:
@@ -4685,9 +4685,8 @@ int8 CRunningScript::ProcessCommandsFrom500To599(int32 command)
CollectParameters(&m_nIp, 2);
CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
assert(pPed);
- float health = *(float*)&ScriptParams[1];
- if (health != 0.0f) {
- pPed->m_fHealth = *(float*)&ScriptParams[1];
+ if (ScriptParams[1]) {
+ pPed->m_fHealth = ScriptParams[1];
}
else if (pPed->bInVehicle) {
pPed->SetDead();
@@ -4704,7 +4703,7 @@ int8 CRunningScript::ProcessCommandsFrom500To599(int32 command)
CollectParameters(&m_nIp, 2);
CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
assert(pVehicle);
- pVehicle->m_fHealth = *(float*)&ScriptParams[1];
+ pVehicle->m_fHealth = ScriptParams[1];
return 0;
}
case COMMAND_GET_PLAYER_HEALTH:
@@ -4840,7 +4839,7 @@ int8 CRunningScript::ProcessCommandsFrom500To599(int32 command)
CPed* pSourcePed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
assert(pSourcePed);
pSourcePed->ClearLookFlag();
- pSourcePed->bIsRestoringLook = false;
+ pSourcePed->bKeepTryingToLook = false;
if (pSourcePed->GetPedState() == PED_LOOK_HEADING || pSourcePed->GetPedState() == PED_LOOK_ENTITY)
pSourcePed->RestorePreviousState();
return 0;
@@ -4851,7 +4850,7 @@ int8 CRunningScript::ProcessCommandsFrom500To599(int32 command)
CPed* pSourcePed = CWorld::Players[ScriptParams[0]].m_pPed;
assert(pSourcePed);
pSourcePed->ClearLookFlag();
- pSourcePed->bIsRestoringLook = false;
+ pSourcePed->bKeepTryingToLook = false;
if (pSourcePed->GetPedState() == PED_LOOK_HEADING || pSourcePed->GetPedState() == PED_LOOK_ENTITY)
pSourcePed->RestorePreviousState();
return 0;
diff --git a/src/core/ControllerConfig.cpp b/src/core/ControllerConfig.cpp
index d32b8283..f0492b0f 100644
--- a/src/core/ControllerConfig.cpp
+++ b/src/core/ControllerConfig.cpp
@@ -16,6 +16,7 @@
#include "ModelIndices.h"
#include "Camera.h"
#include "win.h"
+#include "PCSave.h"
CControllerConfigManager &ControlsManager = *(CControllerConfigManager*)0x8F43A4;
@@ -75,7 +76,7 @@ void CControllerConfigManager::LoadSettings(int32 file)
char buff[29];
CFileMgr::Read(file, buff, sizeof(buff));
- if (!strcmp(buff, "THIS FILE IS NOT VALID YET"))
+ if (!strncmp(buff, TopLineEmptyFile, sizeof(TopLineEmptyFile)-1))
bValid = false;
else
CFileMgr::Seek(file, 0, 0);
@@ -109,7 +110,7 @@ void CControllerConfigManager::InitDefaultControlConfiguration()
SetControllerKeyAssociatedWithAction(VEHICLE_HORN, rsRSHIFT, KEYBOARD);
}
else
- SetControllerKeyAssociatedWithAction(VEHICLE_HORN, rsSHIFT, OPTIONAL_EXTRA);
+ SetControllerKeyAssociatedWithAction(VEHICLE_HORN, rsSHIFT, OPTIONAL_EXTRA); // BUG: must be KEYBOARD ?
SetControllerKeyAssociatedWithAction (VEHICLE_HANDBRAKE, rsRCTRL, KEYBOARD);
SetControllerKeyAssociatedWithAction (VEHICLE_HANDBRAKE, ' ', OPTIONAL_EXTRA);
@@ -162,11 +163,11 @@ void CControllerConfigManager::InitDefaultControlConfiguration()
#ifndef FIX_BUGS
SetControllerKeyAssociatedWithAction(PED_SPRINT, rsRSHIFT, OPTIONAL_EXTRA); // BUG: must be KEYBOARD
#else
- SetControllerKeyAssociatedWithAction(PED_SPRINT, rsRSHIFT, KEYBOARD); // BUG: must be KEYBOARD ?
+ SetControllerKeyAssociatedWithAction(PED_SPRINT, rsRSHIFT, KEYBOARD);
#endif
}
else
- SetControllerKeyAssociatedWithAction(PED_SPRINT, rsSHIFT, OPTIONAL_EXTRA);
+ SetControllerKeyAssociatedWithAction(PED_SPRINT, rsSHIFT, OPTIONAL_EXTRA); // BUG: must be KEYBOARD ?
SetControllerKeyAssociatedWithAction (PED_CYCLE_TARGET_LEFT, '[', KEYBOARD);
@@ -351,115 +352,48 @@ void CControllerConfigManager::InitDefaultControlConfigJoyPad(uint32 buttons)
void CControllerConfigManager::InitialiseControllerActionNameArray()
{
- wchar buff[40+2];
+ wchar buf[ACTIONNAME_LENGTH + 2];
- AsciiToUnicode("PED_LOOKBEHIND", buff);
- CMessages::WideStringCopy(m_aActionNames[PED_LOOKBEHIND], buff, sizeof(m_aActionNames[PED_LOOKBEHIND]));
-
- AsciiToUnicode("PED_CYCLE_WEAPON_LEFT", buff);
- CMessages::WideStringCopy(m_aActionNames[PED_CYCLE_WEAPON_LEFT], buff, sizeof(m_aActionNames[PED_CYCLE_WEAPON_LEFT]));
-
- AsciiToUnicode("PED_CYCLE_WEAPON_RIGHT", buff);
- CMessages::WideStringCopy(m_aActionNames[PED_CYCLE_WEAPON_RIGHT], buff, sizeof(m_aActionNames[PED_CYCLE_WEAPON_RIGHT]));
-
- AsciiToUnicode("PED_LOCK_TARGET", buff);
- CMessages::WideStringCopy(m_aActionNames[PED_LOCK_TARGET], buff, sizeof(m_aActionNames[PED_LOCK_TARGET]));
-
- AsciiToUnicode("PED_JUMPING", buff);
- CMessages::WideStringCopy(m_aActionNames[PED_JUMPING], buff, sizeof(m_aActionNames[PED_JUMPING]));
-
- AsciiToUnicode("PED_SPRINT", buff);
- CMessages::WideStringCopy(m_aActionNames[PED_SPRINT], buff, sizeof(m_aActionNames[PED_SPRINT]));
-
- AsciiToUnicode("PED_CYCLE_TARGET_LEFT", buff);
- CMessages::WideStringCopy(m_aActionNames[PED_CYCLE_TARGET_LEFT], buff, sizeof(m_aActionNames[PED_CYCLE_TARGET_LEFT]));
-
- AsciiToUnicode("PED_CYCLE_TARGET_RIGHT", buff);
- CMessages::WideStringCopy(m_aActionNames[PED_CYCLE_TARGET_RIGHT], buff, sizeof(m_aActionNames[PED_CYCLE_TARGET_RIGHT]));
-
- AsciiToUnicode("PED_CENTER_CAMERA_BEHIND_PLAYER", buff);
- CMessages::WideStringCopy(m_aActionNames[PED_CENTER_CAMERA_BEHIND_PLAYER], buff, sizeof(m_aActionNames[PED_CENTER_CAMERA_BEHIND_PLAYER]));
-
- AsciiToUnicode("VEHICLE_LOOKBEHIND", buff);
- CMessages::WideStringCopy(m_aActionNames[VEHICLE_LOOKBEHIND], buff, sizeof(m_aActionNames[VEHICLE_LOOKBEHIND]));
-
- AsciiToUnicode("VEHICLE_LOOKLEFT", buff);
- CMessages::WideStringCopy(m_aActionNames[VEHICLE_LOOKLEFT], buff, sizeof(m_aActionNames[VEHICLE_LOOKLEFT]));
-
- AsciiToUnicode("VEHICLE_LOOKRIGHT", buff);
- CMessages::WideStringCopy(m_aActionNames[VEHICLE_LOOKRIGHT], buff, sizeof(m_aActionNames[VEHICLE_LOOKRIGHT]));
-
- AsciiToUnicode("VEHICLE_HORN", buff);
- CMessages::WideStringCopy(m_aActionNames[VEHICLE_HORN], buff, sizeof(m_aActionNames[VEHICLE_HORN]));
-
- AsciiToUnicode("VEHICLE_HANDBRAKE", buff);
- CMessages::WideStringCopy(m_aActionNames[VEHICLE_HANDBRAKE], buff, sizeof(m_aActionNames[VEHICLE_HANDBRAKE]));
-
- AsciiToUnicode("VEHICLE_ACCELERATE", buff);
- CMessages::WideStringCopy(m_aActionNames[VEHICLE_ACCELERATE], buff, sizeof(m_aActionNames[VEHICLE_ACCELERATE]));
-
- AsciiToUnicode("VEHICLE_BRAKE", buff);
- CMessages::WideStringCopy(m_aActionNames[VEHICLE_BRAKE], buff, sizeof(m_aActionNames[VEHICLE_BRAKE]));
-
- AsciiToUnicode("VEHICLE_CHANGE_RADIO_STATION", buff);
- CMessages::WideStringCopy(m_aActionNames[VEHICLE_CHANGE_RADIO_STATION], buff, sizeof(m_aActionNames[VEHICLE_CHANGE_RADIO_STATION]));
-
- AsciiToUnicode("TOGGLE_SUBMISSIONS", buff);
- CMessages::WideStringCopy(m_aActionNames[TOGGLE_SUBMISSIONS], buff, sizeof(m_aActionNames[TOGGLE_SUBMISSIONS]));
-
- AsciiToUnicode("PED_SNIPER_ZOOM_IN", buff);
- CMessages::WideStringCopy(m_aActionNames[PED_SNIPER_ZOOM_IN], buff, sizeof(m_aActionNames[PED_SNIPER_ZOOM_IN]));
-
- AsciiToUnicode("PED_SNIPER_ZOOM_OUT", buff);
- CMessages::WideStringCopy(m_aActionNames[PED_SNIPER_ZOOM_OUT], buff, sizeof(m_aActionNames[PED_SNIPER_ZOOM_OUT]));
-
- AsciiToUnicode("PED_1RST_PERSON_LOOK_LEFT", buff);
- CMessages::WideStringCopy(m_aActionNames[PED_1RST_PERSON_LOOK_LEFT], buff, sizeof(m_aActionNames[PED_1RST_PERSON_LOOK_LEFT]));
-
- AsciiToUnicode("PED_1RST_PERSON_LOOK_RIGHT", buff);
- CMessages::WideStringCopy(m_aActionNames[PED_1RST_PERSON_LOOK_RIGHT], buff, sizeof(m_aActionNames[PED_1RST_PERSON_LOOK_RIGHT]));
-
- AsciiToUnicode("PED_1RST_PERSON_LOOK_UP", buff);
- CMessages::WideStringCopy(m_aActionNames[PED_1RST_PERSON_LOOK_UP], buff, sizeof(m_aActionNames[PED_1RST_PERSON_LOOK_UP]));
-
- AsciiToUnicode("PED_1RST_PERSON_LOOK_DOWN", buff);
- CMessages::WideStringCopy(m_aActionNames[PED_1RST_PERSON_LOOK_DOWN], buff, sizeof(m_aActionNames[PED_1RST_PERSON_LOOK_DOWN]));
-
- AsciiToUnicode("SHOW_MOUSE_POINTER_TOGGLE", buff);
- CMessages::WideStringCopy(m_aActionNames[SHOW_MOUSE_POINTER_TOGGLE], buff, sizeof(m_aActionNames[SHOW_MOUSE_POINTER_TOGGLE]));
+#define SETACTIONNAME(name) AsciiToUnicode(#name, buf); CMessages::WideStringCopy(m_aActionNames[name], buf, ACTIONNAME_LENGTH);
- AsciiToUnicode("CAMERA_CHANGE_VIEW_ALL_SITUATIONS", buff);
- CMessages::WideStringCopy(m_aActionNames[CAMERA_CHANGE_VIEW_ALL_SITUATIONS], buff, sizeof(m_aActionNames[CAMERA_CHANGE_VIEW_ALL_SITUATIONS]));
+ SETACTIONNAME(PED_LOOKBEHIND);
+ SETACTIONNAME(PED_CYCLE_WEAPON_LEFT);
+ SETACTIONNAME(PED_CYCLE_WEAPON_RIGHT);
+ SETACTIONNAME(PED_LOCK_TARGET);
+ SETACTIONNAME(PED_JUMPING);
+ SETACTIONNAME(PED_SPRINT);
+ SETACTIONNAME(PED_CYCLE_TARGET_LEFT);
+ SETACTIONNAME(PED_CYCLE_TARGET_RIGHT);
+ SETACTIONNAME(PED_CENTER_CAMERA_BEHIND_PLAYER);
+ SETACTIONNAME(VEHICLE_LOOKBEHIND);
+ SETACTIONNAME(VEHICLE_LOOKLEFT);
+ SETACTIONNAME(VEHICLE_LOOKRIGHT);
+ SETACTIONNAME(VEHICLE_HORN);
+ SETACTIONNAME(VEHICLE_HANDBRAKE);
+ SETACTIONNAME(VEHICLE_ACCELERATE);
+ SETACTIONNAME(VEHICLE_BRAKE);
+ SETACTIONNAME(VEHICLE_CHANGE_RADIO_STATION);
+ SETACTIONNAME(TOGGLE_SUBMISSIONS);
+ SETACTIONNAME(PED_SNIPER_ZOOM_IN);
+ SETACTIONNAME(PED_SNIPER_ZOOM_OUT);
+ SETACTIONNAME(PED_1RST_PERSON_LOOK_LEFT);
+ SETACTIONNAME(PED_1RST_PERSON_LOOK_RIGHT);
+ SETACTIONNAME(PED_1RST_PERSON_LOOK_UP);
+ SETACTIONNAME(PED_1RST_PERSON_LOOK_DOWN);
+ SETACTIONNAME(SHOW_MOUSE_POINTER_TOGGLE);
+ SETACTIONNAME(CAMERA_CHANGE_VIEW_ALL_SITUATIONS);
+ SETACTIONNAME(PED_FIREWEAPON);
+ SETACTIONNAME(VEHICLE_ENTER_EXIT);
+ SETACTIONNAME(GO_LEFT);
+ SETACTIONNAME(GO_RIGHT);
+ SETACTIONNAME(GO_FORWARD);
+ SETACTIONNAME(GO_BACK);
+ SETACTIONNAME(NETWORK_TALK);
+ SETACTIONNAME(TOGGLE_DPAD);
+ SETACTIONNAME(SWITCH_DEBUG_CAM_ON);
+ SETACTIONNAME(TAKE_SCREEN_SHOT);
- AsciiToUnicode("PED_FIREWEAPON", buff);
- CMessages::WideStringCopy(m_aActionNames[PED_FIREWEAPON], buff, sizeof(m_aActionNames[PED_FIREWEAPON]));
-
- AsciiToUnicode("VEHICLE_ENTER_EXIT", buff);
- CMessages::WideStringCopy(m_aActionNames[VEHICLE_ENTER_EXIT], buff, sizeof(m_aActionNames[VEHICLE_ENTER_EXIT]));
-
- AsciiToUnicode("GO_LEFT", buff);
- CMessages::WideStringCopy(m_aActionNames[GO_LEFT], buff, sizeof(m_aActionNames[GO_LEFT]));
-
- AsciiToUnicode("GO_RIGHT", buff);
- CMessages::WideStringCopy(m_aActionNames[GO_RIGHT], buff, sizeof(m_aActionNames[GO_RIGHT]));
-
- AsciiToUnicode("GO_FORWARD", buff);
- CMessages::WideStringCopy(m_aActionNames[GO_FORWARD], buff, sizeof(m_aActionNames[GO_FORWARD]));
-
- AsciiToUnicode("GO_BACK", buff);
- CMessages::WideStringCopy(m_aActionNames[GO_BACK], buff, sizeof(m_aActionNames[GO_BACK]));
-
- AsciiToUnicode("NETWORK_TALK", buff);
- CMessages::WideStringCopy(m_aActionNames[NETWORK_TALK], buff, sizeof(m_aActionNames[NETWORK_TALK]));
-
- AsciiToUnicode("TOGGLE_DPAD", buff);
- CMessages::WideStringCopy(m_aActionNames[TOGGLE_DPAD], buff, sizeof(m_aActionNames[TOGGLE_DPAD]));
-
- AsciiToUnicode("SWITCH_DEBUG_CAM_ON", buff);
- CMessages::WideStringCopy(m_aActionNames[SWITCH_DEBUG_CAM_ON], buff, sizeof(m_aActionNames[SWITCH_DEBUG_CAM_ON]));
-
- AsciiToUnicode("TAKE_SCREEN_SHOT", buff);
- CMessages::WideStringCopy(m_aActionNames[TAKE_SCREEN_SHOT], buff, sizeof(m_aActionNames[TAKE_SCREEN_SHOT]));
+#undef SETACTIONNAME
}
void CControllerConfigManager::UpdateJoyInConfigMenus_ButtonDown(int32 button, int32 padnumber)
@@ -1422,7 +1356,7 @@ bool CControllerConfigManager::GetIsKeyboardKeyJustDown(RsKeyCodes keycode)
return true;
break;
case rsENTER:
- if (CPad::GetPad(PAD1)->GetEnterJustDown())
+ if (CPad::GetPad(PAD1)->GetReturnJustDown())
return true;
break;
case rsLSHIFT:
diff --git a/src/core/ControllerConfig.h b/src/core/ControllerConfig.h
index e7abb21d..e04f9583 100644
--- a/src/core/ControllerConfig.h
+++ b/src/core/ControllerConfig.h
@@ -117,7 +117,7 @@ public:
DIJOYSTATE2 m_OldState;
DIJOYSTATE2 m_NewState;
#endif
- wchar m_aActionNames[MAX_CONTROLLERACTIONS][40];
+ wchar m_aActionNames[MAX_CONTROLLERACTIONS][ACTIONNAME_LENGTH];
bool m_aButtonStates[MAX_BUTTONS];
char _pad1[3];
tControllerConfigBind m_aSettings[MAX_CONTROLLERACTIONS][MAX_CONTROLLERTYPES];
diff --git a/src/core/CutsceneMgr.cpp b/src/core/CutsceneMgr.cpp
index f147e8c9..fa322242 100644
--- a/src/core/CutsceneMgr.cpp
+++ b/src/core/CutsceneMgr.cpp
@@ -411,7 +411,7 @@ CCutsceneMgr::Update(void)
if (CPad::GetPad(0)->GetCrossJustDown()
|| (CGame::playingIntro && CPad::GetPad(0)->GetStartJustDown())
|| CPad::GetPad(0)->GetLeftMouseJustDown()
- || CPad::GetPad(0)->GetPadEnterJustDown() || CPad::GetPad(0)->GetEnterJustDown() // NOTE: In original code it's a single CPad method
+ || CPad::GetPad(0)->GetEnterJustDown()
|| CPad::GetPad(0)->GetCharJustDown(VK_SPACE))
FinishCutscene();
}
diff --git a/src/core/Frontend.cpp b/src/core/Frontend.cpp
index 984e693f..5911433c 100644
--- a/src/core/Frontend.cpp
+++ b/src/core/Frontend.cpp
@@ -1148,12 +1148,12 @@ void CMenuManager::LoadSettings()
CMBlur::BlurOn = true;
MousePointerStateHelper.bInvertVertically = true;
- static char Ver;
+ char Ver[50];
int fileHandle = CFileMgr::OpenFile("gta3.set", "r");
if (fileHandle) {
- CFileMgr::Read(fileHandle, (char*)&Ver, sizeof(Ver));
+ CFileMgr::Read(fileHandle, Ver, 29);
- if (strncmp(&Ver, "THIS FILE IS NOT VALID YET", 26)) {
+ if (strncmp(Ver, TopLineEmptyFile, sizeof(TopLineEmptyFile) - 1)) {
CFileMgr::Seek(fileHandle, 0, 0);
ControlsManager.LoadSettings(fileHandle);
CFileMgr::Read(fileHandle, gString, 20);
diff --git a/src/core/PCSave.h b/src/core/PCSave.h
index 696e158a..42239744 100644
--- a/src/core/PCSave.h
+++ b/src/core/PCSave.h
@@ -19,3 +19,5 @@ extern C_PcSave PcSaveHelper;
extern int *Slots;
extern int *SlotFileName;
extern int *SlotSaveDate;
+
+const char TopLineEmptyFile[] = "THIS FILE IS NOT VALID YET";
diff --git a/src/core/Pad.cpp b/src/core/Pad.cpp
index f334a255..e5178ef3 100644
--- a/src/core/Pad.cpp
+++ b/src/core/Pad.cpp
@@ -1855,7 +1855,7 @@ char *CPad::EditString(char *pStr, int32 nSize)
}
// extenter/up/down
- if ( GetPad(0)->GetEnterJustDown() || GetPad(0)->GetUpJustDown() || GetPad(0)->GetDownJustDown() )
+ if ( GetPad(0)->GetReturnJustDown() || GetPad(0)->GetUpJustDown() || GetPad(0)->GetDownJustDown() )
return nil;
return pStr;
@@ -1976,7 +1976,7 @@ int32 *CPad::EditCodesForControls(int32 *pRsKeys, int32 nSize)
if ( GetPad(0)->GetCapsLockJustDown() )
*pRsKeys = rsCAPSLK;
- if ( GetPad(0)->GetEnterJustDown() )
+ if ( GetPad(0)->GetReturnJustDown() )
*pRsKeys = rsENTER;
if ( GetPad(0)->GetLeftShiftJustDown() )
diff --git a/src/core/Pad.h b/src/core/Pad.h
index e1223629..89ec4aa2 100644
--- a/src/core/Pad.h
+++ b/src/core/Pad.h
@@ -299,7 +299,7 @@ public:
bool GetTimesJustDown() { return !!(NewKeyState.MUL && !OldKeyState.MUL); }
bool GetMinusJustDown() { return !!(NewKeyState.SUB && !OldKeyState.SUB); }
bool GetPlusJustDown() { return !!(NewKeyState.ADD && !OldKeyState.ADD); }
- bool GetPadEnterJustDown() { return !!(NewKeyState.ENTER && !OldKeyState.ENTER); } // GetEnterJustDown
+ bool GetPadEnterJustDown() { return !!(NewKeyState.ENTER && !OldKeyState.ENTER); }
bool GetPadDelJustDown() { return !!(NewKeyState.DECIMAL && !OldKeyState.DECIMAL); }
bool GetPad1JustDown() { return !!(NewKeyState.NUM1 && !OldKeyState.NUM1); }
bool GetPad2JustDown() { return !!(NewKeyState.NUM2 && !OldKeyState.NUM2); }
@@ -314,7 +314,7 @@ public:
bool GetBackspaceJustDown() { return !!(NewKeyState.BACKSP && !OldKeyState.BACKSP); }
bool GetTabJustDown() { return !!(NewKeyState.TAB && !OldKeyState.TAB); }
bool GetCapsLockJustDown() { return !!(NewKeyState.CAPSLOCK && !OldKeyState.CAPSLOCK); }
- bool GetEnterJustDown() { return !!(NewKeyState.EXTENTER && !OldKeyState.EXTENTER); }
+ bool GetReturnJustDown() { return !!(NewKeyState.EXTENTER && !OldKeyState.EXTENTER); }
bool GetLeftShiftJustDown() { return !!(NewKeyState.LSHIFT && !OldKeyState.LSHIFT); }
bool GetShiftJustDown() { return !!(NewKeyState.SHIFT && !OldKeyState.SHIFT); }
bool GetRightShiftJustDown() { return !!(NewKeyState.RSHIFT && !OldKeyState.RSHIFT); }
@@ -325,6 +325,8 @@ public:
bool GetLeftWinJustDown() { return !!(NewKeyState.LWIN && !OldKeyState.LWIN); }
bool GetRightWinJustDown() { return !!(NewKeyState.RWIN && !OldKeyState.RWIN); }
bool GetAppsJustDown() { return !!(NewKeyState.APPS && !OldKeyState.APPS); }
+ bool GetEnterJustDown() { return GetPadEnterJustDown() || GetReturnJustDown(); }
+ bool GetAltJustDown() { return GetLeftAltJustDown() || GetRightAltJustDown(); }
bool GetChar(int32 c) { return NewKeyState.VK_KEYS[c]; }
bool GetF(int32 n) { return NewKeyState.F[n]; }
diff --git a/src/core/Radar.cpp b/src/core/Radar.cpp
index f1dbb8b4..f06e5317 100644
--- a/src/core/Radar.cpp
+++ b/src/core/Radar.cpp
@@ -15,7 +15,7 @@
#include "World.h"
#include "Streaming.h"
-float &CRadar::m_RadarRange = *(float*)0x8E281C;
+float &CRadar::m_radarRange = *(float*)0x8E281C;
CBlip (&CRadar::ms_RadarTrace)[NUMRADARBLIPS] = *(CBlip(*)[NUMRADARBLIPS]) * (uintptr*)0x6ED5E0;
CVector2D &vec2DRadarOrigin = *(CVector2D*)0x6299B8;
int *gRadarTxdIds = (int*)0x6299C0;
@@ -288,7 +288,7 @@ void CRadar::DrawBlips()
CVector2D vec2d;
vec2d.x = vec2DRadarOrigin.x;
- vec2d.y = M_SQRT2 * m_RadarRange + vec2DRadarOrigin.y;
+ vec2d.y = M_SQRT2 * m_radarRange + vec2DRadarOrigin.y;
TransformRealWorldPointToRadarSpace(in, vec2d);
LimitRadarPoint(in);
TransformRadarPointToScreenSpace(out, in);
@@ -527,14 +527,14 @@ void CRadar::DrawMap()
if (FindPlayerVehicle()) {
float speed = FindPlayerSpeed().Magnitude();
if (speed < RADAR_MIN_SPEED)
- m_RadarRange = RADAR_MIN_RANGE;
+ m_radarRange = RADAR_MIN_RANGE;
else if (speed < RADAR_MAX_SPEED)
- m_RadarRange = (speed - RADAR_MIN_SPEED)/(RADAR_MAX_SPEED-RADAR_MIN_SPEED) * (RADAR_MAX_RANGE-RADAR_MIN_RANGE) + RADAR_MIN_RANGE;
+ m_radarRange = (speed - RADAR_MIN_SPEED)/(RADAR_MAX_SPEED-RADAR_MIN_SPEED) * (RADAR_MAX_RANGE-RADAR_MIN_RANGE) + RADAR_MIN_RANGE;
else
- m_RadarRange = RADAR_MAX_RANGE;
+ m_radarRange = RADAR_MAX_RANGE;
}
else
- m_RadarRange = RADAR_MIN_RANGE;
+ m_radarRange = RADAR_MIN_RANGE;
vec2DRadarOrigin = CVector2D(FindPlayerCentreOfWorld_NoSniperShift());
DrawRadarMap();
@@ -795,12 +795,89 @@ uint32 CRadar::GetRadarTraceColour(uint32 color, bool bright)
}
#endif
-#if 1
+const char* gRadarTexNames[] = {
+ "radar00",
+ "radar01",
+ "radar02",
+ "radar03",
+ "radar04",
+ "radar05",
+ "radar06",
+ "radar07",
+ "radar08",
+ "radar09",
+ "radar10",
+ "radar11",
+ "radar12",
+ "radar13",
+ "radar14",
+ "radar15",
+ "radar16",
+ "radar17",
+ "radar18",
+ "radar19",
+ "radar20",
+ "radar21",
+ "radar22",
+ "radar23",
+ "radar24",
+ "radar25",
+ "radar26",
+ "radar27",
+ "radar28",
+ "radar29",
+ "radar30",
+ "radar31",
+ "radar32",
+ "radar33",
+ "radar34",
+ "radar35",
+ "radar36",
+ "radar37",
+ "radar38",
+ "radar39",
+ "radar40",
+ "radar41",
+ "radar42",
+ "radar43",
+ "radar44",
+ "radar45",
+ "radar46",
+ "radar47",
+ "radar48",
+ "radar49",
+ "radar50",
+ "radar51",
+ "radar52",
+ "radar53",
+ "radar54",
+ "radar55",
+ "radar56",
+ "radar57",
+ "radar58",
+ "radar59",
+ "radar60",
+ "radar61",
+};
+
+#if 0
WRAPPER void CRadar::Initialise() { EAXJMP(0x4A3EF0); }
#else
-void CRadar::Initialise()
-{
-
+void
+CRadar::Initialise()
+{
+ for (int i = 0; i < NUMRADARBLIPS; i++) {
+ ms_RadarTrace[i].m_BlipIndex = 1;
+ SetRadarMarkerState(i, false);
+ ms_RadarTrace[i].m_bInUse = false;
+ ms_RadarTrace[i].m_eBlipType = BLIP_NONE;
+ ms_RadarTrace[i].m_eBlipDisplay = BLIP_DISPLAY_NEITHER;
+ ms_RadarTrace[i].m_IconID = RADAR_SPRITE_NONE;
+ }
+
+ m_radarRange = 350.0f;
+ for (int i = 0; i < 64; i++)
+ gRadarTxdIds[i] = CTxdStore::FindTxdSlot(gRadarTexNames[i]);
}
#endif
@@ -1102,7 +1179,7 @@ void CRadar::TransformRadarPointToRealWorldSpace(CVector2D &out, const CVector2D
out.x = s * in.y + c * in.x;
out.y = c * in.y - s * in.x;
- out = out * m_RadarRange + vec2DRadarOrigin;
+ out = out * m_radarRange + vec2DRadarOrigin;
}
#endif
@@ -1142,8 +1219,8 @@ void CRadar::TransformRealWorldPointToRadarSpace(CVector2D &out, const CVector2D
c = Cos(forward.Heading());
}
- float x = (in.x - vec2DRadarOrigin.x) * (1.0f / m_RadarRange);
- float y = (in.y - vec2DRadarOrigin.y) * (1.0f / m_RadarRange);
+ float x = (in.x - vec2DRadarOrigin.x) * (1.0f / m_radarRange);
+ float y = (in.y - vec2DRadarOrigin.y) * (1.0f / m_radarRange);
out.x = s * y + c * x;
out.y = c * y - s * x;
diff --git a/src/core/Radar.h b/src/core/Radar.h
index d6b249db..650c6fb4 100644
--- a/src/core/Radar.h
+++ b/src/core/Radar.h
@@ -55,7 +55,7 @@ enum
struct CBlip
{
uint32 m_nColor;
- uint16 m_eBlipType; // eBlipType
+ uint32 m_eBlipType; // eBlipType
int32 m_nEntityHandle;
CVector2D m_vec2DPos;
CVector m_vecPos;
@@ -78,7 +78,7 @@ static_assert(sizeof(CBlip) == 0x30, "CBlip: error");
class CRadar
{
public:
- static float &m_RadarRange;
+ static float &m_radarRange;
static CBlip (&ms_RadarTrace)[NUMRADARBLIPS];
static CSprite2d *AsukaSprite;
static CSprite2d *BombSprite;
diff --git a/src/core/common.h b/src/core/common.h
index a538ddb6..fd5f35b0 100644
--- a/src/core/common.h
+++ b/src/core/common.h
@@ -365,4 +365,4 @@ inline T *WriteSaveBuf(uint8 *&buf, const T &value)
assert(ReadSaveBuf(buf) == b);\
assert(ReadSaveBuf(buf) == c);\
assert(ReadSaveBuf(buf) == d);\
- assert(ReadSaveBuf(buf) == size);
\ No newline at end of file
+ assert(ReadSaveBuf(buf) == size);
diff --git a/src/core/config.h b/src/core/config.h
index 12cb7be8..175a5f61 100644
--- a/src/core/config.h
+++ b/src/core/config.h
@@ -87,6 +87,9 @@ enum Config {
NUM_FIRES = 40,
NUMPEDROUTES = 200,
+
+ NUMVISIBLEENTITIES = 2000,
+ NUMINVISIBLEENTITIES = 150,
};
// We'll use this once we're ready to become independent of the game
@@ -141,17 +144,17 @@ enum Config {
# define CHATTYSPLASH // print what the game is loading
#endif
-#define FIX_BUGS // fix bugs in the game, TODO: use this more
+#define FIX_BUGS // fixes bugs that we've came across during reversing, TODO: use this more
// Pad
#define KANGAROO_CHEAT
// Hud & radar
#define ASPECT_RATIO_SCALE
-#define TRIANGULAR_BLIPS
+#define TRIANGULAR_BLIPS // height indicating triangular radar blips, as in VC
// Script
-#define USE_DEBUG_SCRIPT_LOADER
+#define USE_DEBUG_SCRIPT_LOADER // makes game load main_freeroam.scm by default
// Vehicles
#define EXPLODING_AIRTRAIN // can blow up jumbo jet with rocket launcher
@@ -162,6 +165,6 @@ enum Config {
// Peds
#define ANIMATE_PED_COL_MODEL
-#define VC_PED_PORTS
-#define NEW_WALK_AROUND_ALGORITHM
+#define VC_PED_PORTS // various ports from VC's CPed, mostly subtle
+#define NEW_WALK_AROUND_ALGORITHM // to make walking around vehicles/objects less awkward
#define CANCELLABLE_CAR_ENTER
diff --git a/src/core/re3.cpp b/src/core/re3.cpp
index 62e9a040..d6bc8148 100644
--- a/src/core/re3.cpp
+++ b/src/core/re3.cpp
@@ -354,6 +354,7 @@ DebugMenuPopulate(void)
#ifndef MASTER
DebugMenuAddVarBool8("Debug", "Toggle unused fight feature", (int8*)&CPed::bUnusedFightThingOnPlayer, nil);
DebugMenuAddVarBool8("Debug", "Toggle banned particles", (int8*)&CParticle::bEnableBannedParticles, nil);
+ DebugMenuAddVarBool8("Debug", "Toggle popping heads on headshot", (int8*)&CPed::bPopHeadsOnHeadshot, nil);
#endif
DebugMenuAddCmd("Debug", "Start Credits", CCredits::Start);
diff --git a/src/math/Vector.h b/src/math/Vector.h
index 42087339..605d96ab 100644
--- a/src/math/Vector.h
+++ b/src/math/Vector.h
@@ -78,21 +78,6 @@ public:
bool IsZero(void) { return x == 0.0f && y == 0.0f && z == 0.0f; }
};
-inline float
-DotProduct(const CVector &v1, const CVector &v2)
-{
- return v1.x*v2.x + v1.y*v2.y + v1.z*v2.z;
-}
-
-inline CVector
-CrossProduct(const CVector &v1, const CVector &v2)
-{
- return CVector(
- v1.y*v2.z - v1.z*v2.y,
- v1.z*v2.x - v1.x*v2.z,
- v1.x*v2.y - v1.y*v2.x);
-}
-
inline CVector operator+(const CVector &left, const CVector &right)
{
return CVector(left.x + right.x, left.y + right.y, left.z + right.z);
@@ -117,3 +102,24 @@ inline CVector operator/(const CVector &left, float right)
{
return CVector(left.x / right, left.y / right, left.z / right);
}
+
+inline float
+DotProduct(const CVector &v1, const CVector &v2)
+{
+ return v1.x*v2.x + v1.y*v2.y + v1.z*v2.z;
+}
+
+inline CVector
+CrossProduct(const CVector &v1, const CVector &v2)
+{
+ return CVector(
+ v1.y*v2.z - v1.z*v2.y,
+ v1.z*v2.x - v1.x*v2.z,
+ v1.x*v2.y - v1.y*v2.x);
+}
+
+inline float
+Distance(const CVector &v1, const CVector &v2)
+{
+ return (v2 - v1).Magnitude();
+}
\ No newline at end of file
diff --git a/src/math/Vector2D.h b/src/math/Vector2D.h
index a090155c..1e4d698f 100644
--- a/src/math/Vector2D.h
+++ b/src/math/Vector2D.h
@@ -49,9 +49,6 @@ public:
CVector2D operator+(const CVector2D &rhs) const {
return CVector2D(x+rhs.x, y+rhs.y);
}
- CVector2D operator*(float t) const {
- return CVector2D(x*t, y*t);
- }
CVector2D operator/(float t) const {
return CVector2D(x/t, y/t);
}
@@ -91,3 +88,13 @@ NormalizeXY(float &x, float &y)
}else
x = 1.0f;
}
+
+inline CVector2D operator*(const CVector2D &left, float right)
+{
+ return CVector2D(left.x * right, left.y * right);
+}
+
+inline CVector2D operator*(float left, const CVector2D &right)
+{
+ return CVector2D(left * right.x, left * right.y);
+}
diff --git a/src/peds/Ped.cpp b/src/peds/Ped.cpp
index 0a76dcc5..4e64c1db 100644
--- a/src/peds/Ped.cpp
+++ b/src/peds/Ped.cpp
@@ -49,20 +49,14 @@
#include "ParticleObject.h"
#include "Floater.h"
-WRAPPER void CPed::SpawnFlyingComponent(int, int8) { EAXJMP(0x4EB060); }
-WRAPPER void CPed::SetPedPositionInCar(void) { EAXJMP(0x4D4970); }
WRAPPER void CPed::SetMoveAnim(void) { EAXJMP(0x4C5A40); }
-WRAPPER void CPed::StartFightDefend(uint8, uint8, uint8) { EAXJMP(0x4E7780); }
-WRAPPER void CPed::ServiceTalking(void) { EAXJMP(0x4E5870); }
-WRAPPER void CPed::UpdatePosition(void) { EAXJMP(0x4C7A00); }
WRAPPER void CPed::WanderPath(void) { EAXJMP(0x4D28D0); }
-WRAPPER void CPed::UpdateFromLeader(void) { EAXJMP(0x4D8F30); }
WRAPPER void CPed::SetEnterCar_AllClear(CVehicle*, uint32, uint32) { EAXJMP(0x4E0A40); }
WRAPPER bool CPed::WarpPedToNearEntityOffScreen(CEntity*) { EAXJMP(0x4E5570); }
WRAPPER void CPed::SetObjective(eObjective, CVector) { EAXJMP(0x4D8A90); }
WRAPPER void CPed::SetObjective(eObjective, CVector, float) { EAXJMP(0x4D8770); }
-WRAPPER void CPed::WarpPedIntoCar(CVehicle*) { EAXJMP(0x4D7D20); }
WRAPPER void CPed::SetCarJack(CVehicle*) { EAXJMP(0x4E0220); }
+WRAPPER void CPed::WarpPedToNearLeaderOffScreen(void) { EAXJMP(0x4E52A0); }
#define FEET_OFFSET 1.04f
@@ -80,7 +74,36 @@ CPedAudioData (&CPed::CommentWaitTime)[38] = *(CPedAudioData(*)[38]) * (uintptr*
uint16 nPlayerInComboMove;
-FightMove (&tFightMoves)[24] = * (FightMove(*)[24]) * (uintptr*)0x5F9844;
+RpClump *flyingClumpTemp;
+
+// This is beta fistfite.dat array. Not used anymore since they're being fetched from fistfite.dat.
+FightMove tFightMoves[NUM_FIGHTMOVES] = {
+ {NUM_ANIMS, 0.0f, 0.0f, 0.0f, 0.0f, HITLEVEL_NULL, 0, 0},
+ {ANIM_PUNCH_R, 0.2f, 8.0f / 30.0f, 0.0f, 0.3f, HITLEVEL_HIGH, 1, 0},
+ {ANIM_FIGHT_IDLE, 0.0f, 0.0f, 0.0f, 0.0f, HITLEVEL_NULL, 0, 0},
+ {ANIM_FIGHT_SH_F, 0.0f, 0.0f, 0.0f, 0.0f, HITLEVEL_NULL, 0, 0},
+ {ANIM_FIGHT_KNEE, 4.0f / 30.0f, 0.2f, 0.0f, 0.6f, HITLEVEL_LOW, 2, 0},
+ {ANIM_FIGHT_HEAD, 4.0f / 30.0f, 0.2f, 0.0f, 0.7f, HITLEVEL_HIGH, 3, 0},
+ {ANIM_FIGHT_PUNCH, 4.0f / 30.0f, 7.0f / 30.0f, 10.0f / 30.0f, 0.4f, HITLEVEL_HIGH, 1, 0},
+ {ANIM_FIGHT_LHOOK, 8.0f / 30.0f, 10.0f / 30.0f, 0.0f, 0.4f, HITLEVEL_HIGH, 3, 0},
+ {ANIM_FIGHT_KICK, 8.0f / 30.0f, 10.0f / 30.0f, 0.0f, 0.5, HITLEVEL_MEDIUM, 2, 0},
+ {ANIM_FIGHT_LONGKICK, 8.0f / 30.0f, 10.0f / 30.0f, 0.0f, 0.5, HITLEVEL_MEDIUM, 4, 0},
+ {ANIM_FIGHT_ROUNDHOUSE, 8.0f / 30.0f, 10.0f / 30.0f, 0.0f, 0.6f, HITLEVEL_MEDIUM, 4, 0},
+ {ANIM_FIGHT_BODYBLOW, 5.0f / 30.0f, 7.0f / 30.0f, 0.0f, 0.35f, HITLEVEL_LOW, 2, 0},
+ {ANIM_KICK_FLOOR, 10.0f / 30.0f, 14.0f / 30.0f, 0.0f, 0.4f, HITLEVEL_GROUND, 1, 0},
+ {ANIM_HIT_FRONT, 0.0f, 0.0f, 0.0f, 0.0f, HITLEVEL_NULL, 0, 0},
+ {ANIM_HIT_BACK, 0.0f, 0.0f, 0.0f, 0.0f, HITLEVEL_NULL, 0, 0},
+ {ANIM_HIT_RIGHT, 0.0f, 0.0f, 0.0f, 0.0f, HITLEVEL_NULL, 0, 0},
+ {ANIM_HIT_LEFT, 0.0f, 0.0f, 0.0f, 0.0f, HITLEVEL_NULL, 0, 0},
+ {ANIM_HIT_BODYBLOW, 0.0f, 0.0f, 0.0f, 0.0f, HITLEVEL_NULL, 0, 0},
+ {ANIM_HIT_CHEST, 0.0f, 0.0f, 0.0f, 0.0f, HITLEVEL_NULL, 0, 0},
+ {ANIM_HIT_HEAD, 0.0f, 0.0f, 0.0f, 0.0f, HITLEVEL_NULL, 0, 0},
+ {ANIM_HIT_WALK, 0.0f, 0.0f, 0.0f, 0.0f, HITLEVEL_NULL, 0, 0},
+ {ANIM_FLOOR_HIT, 0.0f, 0.0f, 0.0f, 0.0f, HITLEVEL_NULL, 0, 0},
+ {ANIM_HIT_BEHIND, 0.0f, 0.0f, 0.0f, 0.0f, HITLEVEL_NULL, 0, 0},
+ {ANIM_FIGHT2_IDLE, 0.0f, 0.0f, 0.0f, 0.0f, HITLEVEL_NULL, 0, 0},
+};
+// *(FightMove(*)[NUM_FIGHTMOVES])* (uintptr*)0x5F9844;
uint16 &CPed::nThreatReactionRangeMultiplier = *(uint16*)0x5F8C98;
uint16 &CPed::nEnterCarRangeMultiplier = *(uint16*)0x5F8C94;
@@ -261,6 +284,7 @@ static char WaitStateText[][16] = {
#ifndef MASTER
int nDisplayDebugInfo = 0;
bool CPed::bUnusedFightThingOnPlayer = false;
+bool CPed::bPopHeadsOnHeadshot = false;
void
CPed::SwitchDebugDisplay(void)
@@ -853,7 +877,11 @@ CPed::RemoveBodyPart(PedNode nodeId, int8 direction)
frame = GetNodeFrame(nodeId);
if (frame) {
if (CGame::nastyGame) {
+#ifndef MASTER
+ if (bPopHeadsOnHeadshot || nodeId != PED_HEAD)
+#else
if (nodeId != PED_HEAD)
+#endif
SpawnFlyingComponent(nodeId, direction);
RecurseFrameChildrenVisibilityCB(frame, nil);
@@ -1827,11 +1855,11 @@ CPed::LineUpPedWithCar(PedLineUpPhase phase)
// Getting out
if (!veh->bIsBus || (veh->bIsBus && vehIsUpsideDown)) {
- float pedZSpeedOnExit = m_vecMoveSpeed.z - 0.008f * CTimer::GetTimeStep();
+ float nextZSpeed = m_vecMoveSpeed.z - GRAVITY * CTimer::GetTimeStep();
// If we're not in ground at next step, apply animation
- if (neededPos.z + pedZSpeedOnExit >= autoZPos.z) {
- m_vecMoveSpeed.z = pedZSpeedOnExit;
+ if (neededPos.z + nextZSpeed >= autoZPos.z) {
+ m_vecMoveSpeed.z = nextZSpeed;
ApplyMoveSpeed();
// Removing below line breaks the animation
neededPos.z = GetPosition().z;
@@ -4829,19 +4857,19 @@ CPed::LoadFightData(void)
switch (hitLevel) {
case 'G':
- tFightMoves[moveId].hitLevel = 1;
+ tFightMoves[moveId].hitLevel = HITLEVEL_GROUND;
break;
case 'H':
- tFightMoves[moveId].hitLevel = 4;
+ tFightMoves[moveId].hitLevel = HITLEVEL_HIGH;
break;
case 'L':
- tFightMoves[moveId].hitLevel = 2;
+ tFightMoves[moveId].hitLevel = HITLEVEL_LOW;
break;
case 'M':
- tFightMoves[moveId].hitLevel = 3;
+ tFightMoves[moveId].hitLevel = HITLEVEL_MEDIUM;
break;
case 'N':
- tFightMoves[moveId].hitLevel = 0;
+ tFightMoves[moveId].hitLevel = HITLEVEL_NULL;
break;
default:
break;
@@ -4962,7 +4990,7 @@ CPed::FightStrike(CVector &touchedNodePos)
}
nearPed->ReactToAttack(this);
- // Mostly unused.
+ // Mostly unused. if > 5, ANIM_HIT_WALK will be run, that's it.
int unk2;
if (GetWeapon()->m_eWeaponType != WEAPONTYPE_UNARMED && !nearPed->IsPlayer())
unk2 = 101;
@@ -4978,7 +5006,7 @@ CPed::FightStrike(CVector &touchedNodePos)
}
if (CGame::nastyGame
- && tFightMoves[m_lastFightMove].hitLevel > 3
+ && tFightMoves[m_lastFightMove].hitLevel > HITLEVEL_MEDIUM
&& nearPed->m_nPedState == PED_DIE
&& nearPed->GetIsOnScreen()) {
@@ -5556,7 +5584,7 @@ CPed::CollideWithPed(CPed *collideWith)
if (!heIsMissionChar) {
CVector2D posDiff2D(posDiff);
int direction = collideWith->GetLocalDirection(posDiff2D);
- collideWith->StartFightDefend(direction, 4, 5);
+ collideWith->StartFightDefend(direction, HITLEVEL_HIGH, 5);
}
}
}
@@ -6370,7 +6398,7 @@ CPed::Fight(void)
} else if (currentAssoc && m_fightState != FIGHTSTATE_MOVE_FINISHED) {
float animTime = currentAssoc->currentTime;
FightMove &curMove = tFightMoves[m_lastFightMove];
- if (curMove.hitLevel != 0 && animTime > curMove.startFireTime && animTime <= curMove.endFireTime && m_fightState >= FIGHTSTATE_NO_MOVE) {
+ if (curMove.hitLevel != HITLEVEL_NULL && animTime > curMove.startFireTime && animTime <= curMove.endFireTime && m_fightState >= FIGHTSTATE_NO_MOVE) {
CVector touchingNodePos(0.0f, 0.0f, 0.0f);
RwFrame *touchingFrame = nil;
@@ -6415,7 +6443,7 @@ CPed::Fight(void)
return;
}
- if (curMove.hitLevel != 0) {
+ if (curMove.hitLevel != HITLEVEL_NULL) {
if (animTime > curMove.endFireTime) {
if (IsPlayer())
currentAssoc->speed = 1.0f;
@@ -6868,8 +6896,8 @@ CPed::FinishLaunchCB(CAnimBlendAssociation *animAssoc, void *arg)
}
#ifdef VC_PED_PORTS
if (ped->m_pCurrentPhysSurface) {
- ped->m_vecMoveSpeed.x += ((CPhysical*)ped->m_pCurrentPhysSurface)->m_vecMoveSpeed.x;
- ped->m_vecMoveSpeed.y += ((CPhysical*)ped->m_pCurrentPhysSurface)->m_vecMoveSpeed.y;
+ ped->m_vecMoveSpeed.x += ped->m_pCurrentPhysSurface->m_vecMoveSpeed.x;
+ ped->m_vecMoveSpeed.y += ped->m_pCurrentPhysSurface->m_vecMoveSpeed.y;
}
#endif
}
@@ -8305,8 +8333,7 @@ CPed::InvestigateEvent(void)
bool
CPed::IsPedDoingDriveByShooting(void)
{
- if (this == FindPlayerPed() && GetWeapon()->m_eWeaponType == WEAPONTYPE_UZI) {
-
+ if (FindPlayerPed() == this && GetWeapon()->m_eWeaponType == WEAPONTYPE_UZI) {
if (TheCamera.Cams[TheCamera.ActiveCam].LookingLeft || TheCamera.Cams[TheCamera.ActiveCam].LookingRight)
return true;
}
@@ -9011,7 +9038,8 @@ FinishFuckUCB(CAnimBlendAssociation *animAssoc, void *arg)
}
void
-CPed::Pause(void) {
+CPed::Pause(void)
+{
m_moved = CVector2D(0.0f, 0.0f);
if (CTimer::GetTimeInMilliseconds() > m_leaveCarTimer)
ClearPause();
@@ -13395,7 +13423,7 @@ CPed::ProcessObjective(void)
punchAssoc->flags |= ASSOC_FADEOUTWHENDONE;
CVector2D offset(distWithTarget.x, distWithTarget.y);
int dir = m_pedInObjective->GetLocalDirection(offset);
- m_pedInObjective->StartFightDefend(dir, 4, 5);
+ m_pedInObjective->StartFightDefend(dir, HITLEVEL_HIGH, 5);
m_pedInObjective->ReactToAttack(this);
m_pedInObjective->Say(SOUND_PED_ROBBED);
Say(SOUND_PED_MUGGING);
@@ -13612,7 +13640,7 @@ LocalPosForWalkAround(CVector2D colMin, CVector2D colMax, int walkAround, uint32
bool
CanWeSeeTheCorner(CVector2D dist, CVector2D fwdOffset)
{
- // because if dist is more then 5 unit, fov isn't important, we want shortest way
+ // because fov isn't important if dist is more then 5 unit, we want shortest way
if (dist.Magnitude() > 5.0f)
return true;
@@ -13743,6 +13771,7 @@ CPed::SetDirectionToWalkAroundObject(CEntity *obj)
CVector cornerToGo = CVector(10.0f, 10.0f, 10.0f);
int dirToGo;
m_walkAroundType = 0;
+ int iWouldPreferGoingBack = 0; // 1:left 2:right
#endif
float adjustedCheckInterval = 0.7f * checkIntervalInDist;
CVector posToCheck;
@@ -13770,6 +13799,9 @@ CPed::SetDirectionToWalkAroundObject(CEntity *obj)
if (goingToEnterCar && (m_vehEnterType == CAR_DOOR_LF || m_vehEnterType == CAR_DOOR_LR)) {
cornerToGo = tl;
m_walkAroundType = 1;
+
+ if (m_vehEnterType == CAR_DOOR_LR)
+ iWouldPreferGoingBack = 1;
} else if(CanWeSeeTheCorner(tl, GetForward())){
cornerToGo = tl;
dirToGo = GetLocalDirection(tl);
@@ -13805,6 +13837,9 @@ CPed::SetDirectionToWalkAroundObject(CEntity *obj)
if (goingToEnterCar && (m_vehEnterType == CAR_DOOR_RF || m_vehEnterType == CAR_DOOR_RR)) {
cornerToGo = tr;
m_walkAroundType = 2;
+
+ if (m_vehEnterType == CAR_DOOR_RR)
+ iWouldPreferGoingBack = 2;
} else if (CanWeSeeTheCorner(tr, GetForward())) {
cornerToGo = tr;
dirToGo = GetLocalDirection(tr);
@@ -13837,7 +13872,9 @@ CPed::SetDirectionToWalkAroundObject(CEntity *obj)
#ifdef NEW_WALK_AROUND_ALGORITHM
else {
CVector br = obj->GetMatrix() * CVector(adjustedColMax.x, adjustedColMin.y, 0.0f) - GetPosition();
- if (br.Magnitude2D() < cornerToGo.Magnitude2D()) {
+ if (iWouldPreferGoingBack == 2)
+ m_walkAroundType = 4;
+ else if (br.Magnitude2D() < cornerToGo.Magnitude2D()) {
if (goingToEnterCar && (m_vehEnterType == CAR_DOOR_RF || m_vehEnterType == CAR_DOOR_RR)) {
cornerToGo = br;
m_walkAroundType = 5;
@@ -13873,7 +13910,9 @@ CPed::SetDirectionToWalkAroundObject(CEntity *obj)
#ifdef NEW_WALK_AROUND_ALGORITHM
else {
CVector bl = obj->GetMatrix() * CVector(adjustedColMin.x, adjustedColMin.y, 0.0f) - GetPosition();
- if (bl.Magnitude2D() < cornerToGo.Magnitude2D()) {
+ if (iWouldPreferGoingBack == 1)
+ m_walkAroundType = 7;
+ else if (bl.Magnitude2D() < cornerToGo.Magnitude2D()) {
if (goingToEnterCar && (m_vehEnterType == CAR_DOOR_LF || m_vehEnterType == CAR_DOOR_LR)) {
cornerToGo = bl;
m_walkAroundType = 6;
@@ -14274,8 +14313,8 @@ CPed::ProcessEntityCollision(CEntity *collidingEnt, CColPoint *collidingPoints)
m_ped_flagH10 = false;
bOnBoat = false;
} else {
- m_pCurrentPhysSurface = collidingEnt;
- collidingEnt->RegisterReference((CEntity**)m_pCurrentPhysSurface);
+ m_pCurrentPhysSurface = (CPhysical*)collidingEnt;
+ collidingEnt->RegisterReference((CEntity**)&m_pCurrentPhysSurface);
m_vecOffsetFromPhysSurface = intersectionPoint.point - collidingEnt->GetPosition();
m_pCurSurface = collidingEnt;
collidingEnt->RegisterReference((CEntity**)&m_pCurSurface);
@@ -14301,7 +14340,8 @@ CPed::ProcessEntityCollision(CEntity *collidingEnt, CColPoint *collidingPoints)
m_vecDamageNormal = intersectionPoint.normal;
}
}
-#ifdef VC_PED_PORTS
+ // VC code is working perfectly, but we don't want mega jumps to damage us significantly :shrug:
+#if 0 // #ifdef VC_PED_PORTS
float upperSpeedLimit = 0.33f;
float lowerSpeedLimit = -0.25f;
float speed = m_vecMoveSpeed.Magnitude2D();
@@ -14309,49 +14349,48 @@ CPed::ProcessEntityCollision(CEntity *collidingEnt, CColPoint *collidingPoints)
upperSpeedLimit *= 2.0f;
lowerSpeedLimit *= 1.5f;
}
- if (m_ped_flagA2
- || (speed <= upperSpeedLimit /* || (bfFlagsL >> 5) & 1 */) && m_vecMoveSpeed.z >= lowerSpeedLimit
- || m_pCollidingEntity == collidingEnt) {
+ if (!m_ped_flagA2) {
+ if ((speed <= upperSpeedLimit /* || (bfFlagsL >> 5) & 1 */) && m_vecMoveSpeed.z >= lowerSpeedLimit
+ || m_pCollidingEntity == collidingEnt) {
- if (!m_ped_flagA2 && RpAnimBlendClumpGetAssociation(GetClump(), ANIM_FALL_FALL)
- && -0.016f * CTimer::GetTimeStep() > m_vecMoveSpeed.z) {
- InflictDamage(collidingEnt, WEAPONTYPE_FALL_DAMAGE, 15.0f, PEDPIECE_TORSO, 2);
- }
- } else {
- float damage = 100.0f * max(speed - 0.25f, 0.0f);
- float damage2 = damage;
- if (m_vecMoveSpeed.z < -0.25f)
- damage += (-0.25f - m_vecMoveSpeed.z) * 150.0f;
+ if (RpAnimBlendClumpGetAssociation(GetClump(), ANIM_FALL_FALL) && -0.016f * CTimer::GetTimeStep() > m_vecMoveSpeed.z) {
+ InflictDamage(collidingEnt, WEAPONTYPE_FALL_DAMAGE, 15.0f, PEDPIECE_TORSO, 2);
+ }
+ } else {
+ float damage = 100.0f * max(speed - 0.25f, 0.0f);
+ float damage2 = damage;
+ if (m_vecMoveSpeed.z < -0.25f)
+ damage += (-0.25f - m_vecMoveSpeed.z) * 150.0f;
- uint8 dir = 2; // from backward
- if (m_vecMoveSpeed.x > 0.01f || m_vecMoveSpeed.x < -0.01f
- || m_vecMoveSpeed.y > 0.01f || m_vecMoveSpeed.y < -0.01f) {
- CVector2D offset = -m_vecMoveSpeed;
- dir = GetLocalDirection(offset);
+ uint8 dir = 2; // from backward
+ if (m_vecMoveSpeed.x > 0.01f || m_vecMoveSpeed.x < -0.01f || m_vecMoveSpeed.y > 0.01f || m_vecMoveSpeed.y < -0.01f) {
+ CVector2D offset = -m_vecMoveSpeed;
+ dir = GetLocalDirection(offset);
+ }
+ InflictDamage(collidingEnt, WEAPONTYPE_FALL_DAMAGE, damage, PEDPIECE_TORSO, dir);
+ if (IsPlayer() && damage2 > 5.0f)
+ Say(SOUND_PED_LAND);
}
- InflictDamage(collidingEnt, WEAPONTYPE_FALL_DAMAGE, damage, PEDPIECE_TORSO, dir);
- if (IsPlayer() && damage2 > 5.0f)
- Say(SOUND_PED_LAND);
}
#else
- float speedSqr = m_vecMoveSpeed.MagnitudeSqr();
- if (m_ped_flagA2
- || m_vecMoveSpeed.z >= -0.25f && speedSqr <= 0.25f) {
- if (!m_ped_flagA2 && RpAnimBlendClumpGetAssociation(GetClump(), ANIM_FALL_FALL)
- && -0.016f * CTimer::GetTimeStep() > m_vecMoveSpeed.z) {
- InflictDamage(collidingEnt, WEAPONTYPE_FALL_DAMAGE, 15.0f, PEDPIECE_TORSO, 2);
- }
- } else {
- if (speedSqr == 0.0f)
- speedSqr = sq(m_vecMoveSpeed.z);
+ float speedSqr = 0.0f;
+ if (!m_ped_flagA2) {
+ if (m_vecMoveSpeed.z >= -0.25f && (speedSqr = m_vecMoveSpeed.MagnitudeSqr()) <= 0.25f) {
- uint8 dir = 2; // from backward
- if (m_vecMoveSpeed.x > 0.01f || m_vecMoveSpeed.x < -0.01f
- || m_vecMoveSpeed.y > 0.01f || m_vecMoveSpeed.y < -0.01f) {
- CVector2D offset = -m_vecMoveSpeed;
- dir = GetLocalDirection(offset);
+ if (RpAnimBlendClumpGetAssociation(GetClump(), ANIM_FALL_FALL) && -0.016f * CTimer::GetTimeStep() > m_vecMoveSpeed.z) {
+ InflictDamage(collidingEnt, WEAPONTYPE_FALL_DAMAGE, 15.0f, PEDPIECE_TORSO, 2);
+ }
+ } else {
+ if (speedSqr == 0.0f)
+ speedSqr = sq(m_vecMoveSpeed.z);
+
+ uint8 dir = 2; // from backward
+ if (m_vecMoveSpeed.x > 0.01f || m_vecMoveSpeed.x < -0.01f || m_vecMoveSpeed.y > 0.01f || m_vecMoveSpeed.y < -0.01f) {
+ CVector2D offset = -m_vecMoveSpeed;
+ dir = GetLocalDirection(offset);
+ }
+ InflictDamage(collidingEnt, WEAPONTYPE_FALL_DAMAGE, 350.0f * sq(speedSqr), PEDPIECE_TORSO, dir);
}
- InflictDamage(collidingEnt, WEAPONTYPE_FALL_DAMAGE, 350.0f * sq(speedSqr), PEDPIECE_TORSO, dir);
}
#endif
m_vecMoveSpeed.z = 0.0f;
@@ -14479,7 +14518,7 @@ CPed::WillChat(CPed *stranger)
}
if (m_nSurfaceTouched == SURFACE_TARMAC)
return false;
- if (this == stranger)
+ if (stranger == this)
return false;
if (m_nPedType == stranger->m_nPedType)
return true;
@@ -14758,7 +14797,7 @@ CPed::ProcessBuoyancy(void)
float buoyancyLevel = (m_nPedState == PED_DEAD ? 1.8f : 1.1f);
#endif
- if (mod_Buoyancy.ProcessBuoyancy(this, 0.008f * m_fMass * buoyancyLevel, &buoyancyPoint, &buoyancyImpulse)) {
+ if (mod_Buoyancy.ProcessBuoyancy(this, GRAVITY * m_fMass * buoyancyLevel, &buoyancyPoint, &buoyancyImpulse)) {
m_flagD8 = true;
CEntity *entity;
CColPoint point;
@@ -15738,6 +15777,783 @@ CPed::SeekCar(void)
}
}
+void
+CPed::ServiceTalking(void)
+{
+ if (!bBodyPartJustCameOff || m_bodyPartBleeding != PED_HEAD) {
+ if (strcmpi(CModelInfo::GetModelInfo(m_modelIndex)->GetName(), "bomber")) {
+ if (m_nPedState == PED_ON_FIRE)
+ m_queuedSound = SOUND_PED_BURNING;
+ } else {
+ m_queuedSound = SOUND_PED_BOMBER;
+ }
+ if (m_queuedSound != SOUND_TOTAL_PED_SOUNDS) {
+ if (m_queuedSound == SOUND_PED_DEATH)
+ m_soundStart = CTimer::GetTimeInMilliseconds() - 1;
+
+ if (CTimer::GetTimeInMilliseconds() > m_soundStart) {
+ DMAudio.PlayOneShot(m_audioEntityId, m_queuedSound, 1.0f);
+ m_lastSoundStart = CTimer::GetTimeInMilliseconds();
+ m_soundStart =
+ CommentWaitTime[m_queuedSound - SOUND_PED_DEATH].m_nFixedDelayTime
+ + CTimer::GetTimeInMilliseconds()
+ + CGeneral::GetRandomNumberInRange(0, CommentWaitTime[m_queuedSound - SOUND_PED_DEATH].m_nOverrideFixedDelayTime);
+ m_lastQueuedSound = m_queuedSound;
+ m_queuedSound = SOUND_TOTAL_PED_SOUNDS;
+ }
+ }
+ }
+}
+
+void
+CPed::StartFightDefend(uint8 direction, uint8 hitLevel, uint8 unk)
+{
+ if (m_nPedState == PED_DEAD) {
+ if (CGame::nastyGame) {
+ if (hitLevel == HITLEVEL_GROUND) {
+ CAnimBlendAssociation *floorHitAssoc;
+ if (RpAnimBlendClumpGetFirstAssociation(GetClump(), ASSOC_FLAG800)) {
+ floorHitAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_FLOOR_HIT_F, 8.0f);
+ } else {
+ floorHitAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, tFightMoves[FIGHTMOVE_HITONFLOOR].animId, 8.0f);
+ }
+ if (floorHitAssoc) {
+ floorHitAssoc->SetCurrentTime(0.0f);
+ floorHitAssoc->SetRun();
+ floorHitAssoc->flags &= ~ASSOC_FADEOUTWHENDONE;
+ }
+ }
+ if (CGame::nastyGame) {
+ RwMatrix headMat;
+ CPedIK::GetWorldMatrix(GetNodeFrame(PED_HEAD), &headMat);
+ for(int i = 0; i < 4; ++i) {
+ CVector bloodDir(0.0f, 0.0f, 0.1f);
+ CVector bloodPos = headMat.pos - 0.2f * GetForward();
+ CParticle::AddParticle(PARTICLE_BLOOD, bloodPos, bloodDir, nil, 0.0f, 0, 0, 0, 0);
+ }
+ }
+ }
+ } else if (m_nPedState == PED_FALL) {
+ if (hitLevel == HITLEVEL_GROUND && !IsPedHeadAbovePos(-0.3f)) {
+ CAnimBlendAssociation *floorHitAssoc = RpAnimBlendClumpGetFirstAssociation(GetClump(), ASSOC_FLAG800) ?
+ CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_FLOOR_HIT_F, 8.0f) :
+ CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_FLOOR_HIT, 8.0f);
+ if (floorHitAssoc) {
+ floorHitAssoc->flags &= ~ASSOC_FADEOUTWHENDONE;
+ floorHitAssoc->flags |= ASSOC_DELETEFADEDOUT;
+ }
+ }
+ } else if (IsPedInControl()) {
+ if ((IsPlayer() && m_nPedState != PED_FIGHT && ((CPlayerPed*)this)->m_fMoveSpeed > 1.0f)
+ || (!IsPlayer() && m_objective == OBJECTIVE_FLEE_CHAR_ON_FOOT_TILL_SAFE)) {
+#ifndef VC_PED_PORTS
+ if (hitLevel != HITLEVEL_HIGH && hitLevel != HITLEVEL_LOW || (IsPlayer() || CGeneral::GetRandomNumber() & 3) && CGeneral::GetRandomNumber() & 7) {
+ if (IsPlayer() || CGeneral::GetRandomNumber() & 3) {
+#else
+ if (hitLevel != HITLEVEL_HIGH && hitLevel != HITLEVEL_LOW || (IsPlayer() || CGeneral::GetRandomNumber() & 1) && CGeneral::GetRandomNumber() & 7) {
+ if (IsPlayer() || CGeneral::GetRandomNumber() & 1) {
+#endif
+ AnimationId shotAnim;
+ switch (direction) {
+ case 1:
+ shotAnim = ANIM_SHOT_LEFT_PARTIAL;
+ break;
+ case 2:
+ shotAnim = ANIM_SHOT_BACK_PARTIAL;
+ break;
+ case 3:
+ shotAnim = ANIM_SHOT_RIGHT_PARTIAL;
+ break;
+ default:
+ shotAnim = ANIM_SHOT_FRONT_PARTIAL;
+ break;
+ }
+ CAnimBlendAssociation *shotAssoc = RpAnimBlendClumpGetAssociation(GetClump(), shotAnim);
+ if (!shotAssoc || shotAssoc->blendDelta < 0.0f)
+ shotAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, shotAnim, 8.0f);
+
+ shotAssoc->SetCurrentTime(0.0f);
+ shotAssoc->SetRun();
+ shotAssoc->flags |= ASSOC_FADEOUTWHENDONE;
+ } else {
+ int time = CGeneral::GetRandomNumberInRange(1000, 3000);
+ SetWaitState(WAITSTATE_PLAYANIM_DUCK, &time);
+ }
+ } else {
+#ifndef VC_PED_PORTS
+ switch (direction) {
+ case 1:
+ SetFall(500, ANIM_KO_SPIN_R, false);
+ break;
+ case 2:
+ SetFall(500, ANIM_KO_SKID_BACK, false);
+ break;
+ case 3:
+ SetFall(500, ANIM_KO_SPIN_L, false);
+ break;
+ default:
+ SetFall(500, ANIM_KO_SHOT_STOM, false);
+ break;
+ }
+#else
+ bool fall = true;
+ AnimationId hitAnim;
+ switch (direction) {
+ case 1:
+ hitAnim = ANIM_KO_SPIN_R;
+ break;
+ case 2:
+ if (CGeneral::GetRandomNumber() & 1) {
+ fall = false;
+ hitAnim = ANIM_HIT_BACK;
+ } else {
+ hitAnim = ANIM_KO_SKID_BACK;
+ }
+ break;
+ case 3:
+ hitAnim = ANIM_KO_SPIN_L;
+ break;
+ default:
+ if (hitLevel == HITLEVEL_LOW) {
+ hitAnim = ANIM_KO_SHOT_STOM;
+ } else if (CGeneral::GetRandomNumber() & 1) {
+ fall = false;
+ hitAnim = ANIM_HIT_WALK;
+ } else if (CGeneral::GetRandomNumber() & 1) {
+ fall = false;
+ hitAnim = ANIM_HIT_HEAD;
+ } else {
+ hitAnim = ANIM_KO_SHOT_FACE;
+ }
+ break;
+ }
+ if (fall) {
+ SetFall(500, hitAnim, false);
+ } else {
+ CAnimBlendAssociation *hitAssoc = RpAnimBlendClumpGetAssociation(GetClump(), hitAnim);
+ if (!hitAssoc || hitAssoc->blendDelta < 0.0f)
+ hitAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, hitAnim, 8.0f);
+
+ hitAssoc->SetCurrentTime(0.0f);
+ hitAssoc->SetRun();
+ hitAssoc->flags |= ASSOC_FADEOUTWHENDONE;
+ }
+#endif
+ }
+ Say(SOUND_PED_DEFEND);
+ } else {
+ Say(SOUND_PED_DEFEND);
+ switch (hitLevel) {
+ case HITLEVEL_GROUND:
+ m_lastFightMove = FIGHTMOVE_HITONFLOOR;
+ break;
+ case HITLEVEL_LOW:
+#ifndef VC_PED_PORTS
+ if (direction == 2) {
+ CPed::SetFall(1000, ANIM_KO_SKID_BACK, false);
+ return;
+ }
+#else
+ if (direction == 2 && (!IsPlayer() || ((CGeneral::GetRandomNumber() & 1) && m_fHealth < 30.0f))) {
+ CPed::SetFall(1000, ANIM_KO_SKID_BACK, false);
+ return;
+ } else if (direction != 2 && !IsPlayer() && (CGeneral::GetRandomNumber() & 1) && m_fHealth < 30.0f) {
+ CPed::SetFall(1000, ANIM_KO_SHOT_STOM, false);
+ return;
+ }
+#endif
+ m_lastFightMove = FIGHTMOVE_HITBODY;
+ break;
+ case HITLEVEL_HIGH:
+ switch (direction) {
+ case 1:
+ m_lastFightMove = FIGHTMOVE_HITLEFT;
+ break;
+ case 2:
+ m_lastFightMove = FIGHTMOVE_HITBACK;
+ break;
+ case 3:
+ m_lastFightMove = FIGHTMOVE_HITRIGHT;
+ break;
+ default:
+ if (unk <= 5)
+ m_lastFightMove = FIGHTMOVE_HITHEAD;
+ else
+ m_lastFightMove = FIGHTMOVE_HITBIGSTEP;
+ break;
+ }
+ break;
+ default:
+ switch (direction) {
+ case 1:
+ m_lastFightMove = FIGHTMOVE_HITLEFT;
+ break;
+ case 2:
+ m_lastFightMove = FIGHTMOVE_HITBACK;
+ break;
+ case 3:
+ m_lastFightMove = FIGHTMOVE_HITRIGHT;
+ break;
+ default:
+ if (unk <= 5)
+ m_lastFightMove = FIGHTMOVE_HITCHEST;
+ else
+ m_lastFightMove = FIGHTMOVE_HITBIGSTEP;
+ break;
+ }
+ break;
+ }
+ if (m_nPedState == PED_GETUP && !IsPedHeadAbovePos(0.0f))
+ m_lastFightMove = FIGHTMOVE_HITONFLOOR;
+
+ if (m_nPedState == PED_FIGHT) {
+ CAnimBlendAssociation *moveAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, tFightMoves[m_lastFightMove].animId, 8.0f);
+ moveAssoc->SetCurrentTime(0.0f);
+ moveAssoc->SetFinishCallback(FinishFightMoveCB, this);
+ if (IsPlayer())
+ moveAssoc->speed = 1.3f;
+
+ m_takeAStepAfterAttack = 0;
+ m_fightButtonPressure = 0;
+ } else if (IsPlayer() && m_currentWeapon != WEAPONTYPE_UNARMED) {
+ CAnimBlendAssociation *moveAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, tFightMoves[m_lastFightMove].animId, 4.0f);
+ moveAssoc->SetCurrentTime(0.0f);
+ moveAssoc->speed = 1.3f;
+ } else {
+ if (m_nPedState != PED_AIM_GUN && m_nPedState != PED_ATTACK)
+ SetStoredState();
+
+ if (m_nWaitState != WAITSTATE_FALSE) {
+ m_nWaitState = WAITSTATE_FALSE;
+ RestoreHeadingRate();
+ }
+ m_nPedState = PED_FIGHT;
+ m_fightButtonPressure = 0;
+ RpAnimBlendClumpRemoveAssociations(GetClump(), ASSOC_REPEAT);
+ CAnimBlendAssociation *walkStartAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_WALK_START);
+ if (walkStartAssoc) {
+ walkStartAssoc->flags |= ASSOC_DELETEFADEDOUT;
+ walkStartAssoc->blendDelta = -1000.0f;
+ }
+ CAnimBlendAssociation *walkStopAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_RUN_STOP);
+ if (!walkStopAssoc)
+ walkStopAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_RUN_STOP_R);
+ if (walkStopAssoc) {
+ walkStopAssoc->flags |= ASSOC_DELETEFADEDOUT;
+ walkStopAssoc->blendDelta = -1000.0f;
+ RestoreHeadingRate();
+ }
+ SetMoveState(PEDMOVE_NONE);
+ m_nStoredMoveState = PEDMOVE_NONE;
+ CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, ANIM_FIGHT_IDLE)->blendAmount = 1.0f;
+ CAnimBlendAssociation *moveAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, tFightMoves[m_lastFightMove].animId, 8.0f);
+ moveAssoc->SetFinishCallback(FinishFightMoveCB, this);
+ m_fightState = FIGHTSTATE_NO_MOVE;
+ m_takeAStepAfterAttack = false;
+ bIsAttacking = true;
+ }
+ }
+ }
+}
+
+void
+CPed::UpdateFromLeader(void)
+{
+ if (CTimer::GetTimeInMilliseconds() <= m_objectiveTimer)
+ return;
+
+ if (!m_leader)
+ return;
+
+ CVector leaderDist;
+ if (m_leader->bInVehicle && m_leader->m_pMyVehicle)
+ leaderDist = m_leader->m_pMyVehicle->GetPosition() - GetPosition();
+ else
+ leaderDist = m_leader->GetPosition() - GetPosition();
+
+ if (leaderDist.Magnitude() > 30.0f) {
+ if (IsPedInControl()) {
+ SetObjective(OBJECTIVE_NONE);
+ SetIdle();
+ SetMoveState(PEDMOVE_STILL);
+ }
+ SetLeader(nil);
+ return;
+ }
+
+ if (IsPedInControl()) {
+ if (m_nWaitState == WAITSTATE_PLAYANIM_TAXI)
+ WarpPedToNearLeaderOffScreen();
+
+ if (m_leader->m_nPedState == PED_DEAD) {
+ SetLeader(nil);
+ SetObjective(OBJECTIVE_FLEE_TILL_SAFE);
+ return;
+ }
+ if (!m_leader->bInVehicle) {
+ if (m_leader->m_objective != OBJECTIVE_ENTER_CAR_AS_DRIVER) {
+ if (bInVehicle) {
+ if (m_objective != OBJECTIVE_WAIT_IN_CAR_THEN_GETOUT && m_objective != OBJECTIVE_LEAVE_VEHICLE)
+ SetObjective(OBJECTIVE_LEAVE_VEHICLE, m_pMyVehicle);
+
+ return;
+ }
+ if (m_objective == OBJECTIVE_ENTER_CAR_AS_PASSENGER) {
+ RestorePreviousObjective();
+ RestorePreviousState();
+ }
+ }
+ if (m_nPedType == PEDTYPE_PROSTITUTE && CharCreatedBy == RANDOM_CHAR) {
+ SetLeader(nil);
+ return;
+ }
+ }
+ if (bInVehicle || !m_leader->bInVehicle || m_leader->m_nPedState != PED_DRIVING) {
+ if (m_leader->m_objective != OBJECTIVE_NONE && (!m_leader->IsPlayer() || m_leader->m_objective != OBJECTIVE_IDLE)
+ && m_objective != m_leader->m_objective) {
+
+ switch (m_leader->m_objective) {
+ case OBJECTIVE_IDLE:
+ case OBJECTIVE_FLEE_TILL_SAFE:
+ case OBJECTIVE_WAIT_IN_CAR:
+ case OBJECTIVE_FOLLOW_ROUTE:
+ SetObjective(m_leader->m_objective);
+ m_objectiveTimer = m_leader->m_objectiveTimer;
+ break;
+ case OBJECTIVE_GUARD_SPOT:
+ SetObjective(OBJECTIVE_GUARD_SPOT, m_leader->m_vecSeekPosEx);
+ m_objectiveTimer = m_leader->m_objectiveTimer;
+ break;
+ case OBJECTIVE_KILL_CHAR_ON_FOOT:
+ case OBJECTIVE_KILL_CHAR_ANY_MEANS:
+ case OBJECTIVE_GOTO_CHAR_ON_FOOT:
+ if (m_leader->m_pedInObjective) {
+ SetObjective(m_leader->m_objective, m_leader->m_pedInObjective);
+ m_objectiveTimer = m_leader->m_objectiveTimer;
+ }
+ break;
+ case OBJECTIVE_ENTER_CAR_AS_PASSENGER:
+ case OBJECTIVE_ENTER_CAR_AS_DRIVER:
+ if (m_leader->m_carInObjective) {
+ SetObjective(OBJECTIVE_ENTER_CAR_AS_PASSENGER, m_leader->m_carInObjective);
+ return;
+ }
+ break;
+ case OBJECTIVE_FIGHT_CHAR:
+ return;
+ case OBJECTIVE_HAIL_TAXI:
+ m_leader = nil;
+ SetObjective(OBJECTIVE_NONE);
+ break;
+ default:
+ SetObjective(OBJECTIVE_GOTO_CHAR_ON_FOOT, m_leader);
+ SetObjectiveTimer(0);
+ break;
+ }
+ } else {
+ if (m_leader->m_nPedState == PED_ATTACK) {
+ CEntity *lookTargetOfLeader = m_leader->m_pLookTarget;
+ if (lookTargetOfLeader && m_objective != OBJECTIVE_KILL_CHAR_ON_FOOT
+ && lookTargetOfLeader->IsPed() && lookTargetOfLeader != this) {
+
+ SetObjective(OBJECTIVE_KILL_CHAR_ON_FOOT, lookTargetOfLeader);
+ SetObjectiveTimer(8000);
+ SetLookFlag(m_leader->m_pLookTarget, false);
+ SetLookTimer(500);
+ }
+ } else {
+ if (IsPedInControl() && m_nPedState != PED_ATTACK) {
+#ifndef VC_PED_PORTS
+ SetObjective(OBJECTIVE_GOTO_CHAR_ON_FOOT, m_leader);
+ SetObjectiveTimer(0);
+#else
+ if (m_leader->m_objective != OBJECTIVE_NONE || m_objective != OBJECTIVE_NONE
+ || m_leader->m_nPedState != PED_CHAT || m_nPedState != PED_CHAT) {
+
+ SetObjective(OBJECTIVE_GOTO_CHAR_ON_FOOT, m_leader);
+ SetObjectiveTimer(0);
+ } else {
+ SetObjective(OBJECTIVE_NONE);
+ }
+#endif
+ }
+ if (m_nPedState == PED_IDLE && m_leader->IsPlayer()) {
+ if (ScanForThreats() && m_threatEntity) {
+ m_pLookTarget = m_threatEntity;
+ m_pLookTarget->RegisterReference((CEntity **) &m_pLookTarget);
+ TurnBody();
+ if (m_attackTimer < CTimer::GetTimeInMilliseconds() && !GetWeapon()->IsTypeMelee()) {
+ m_pPointGunAt = m_threatEntity;
+ if (m_threatEntity)
+ m_threatEntity->RegisterReference((CEntity **) &m_pPointGunAt);
+ SetAttack(m_threatEntity);
+ }
+ }
+ }
+ }
+ }
+ } else {
+ if (m_objective != OBJECTIVE_ENTER_CAR_AS_PASSENGER && m_objective != OBJECTIVE_ENTER_CAR_AS_DRIVER) {
+ if (m_leader->m_pMyVehicle->m_nNumPassengers < m_leader->m_pMyVehicle->m_nNumMaxPassengers)
+ SetObjective(OBJECTIVE_ENTER_CAR_AS_PASSENGER, m_leader->m_pMyVehicle);
+ }
+ }
+ } else if (bInVehicle) {
+ if ((!m_leader->bInVehicle || m_leader->m_nPedState == PED_EXIT_CAR) && m_objective != OBJECTIVE_WAIT_IN_CAR_THEN_GETOUT) {
+
+ switch (m_leader->m_objective) {
+ case OBJECTIVE_ENTER_CAR_AS_PASSENGER:
+ case OBJECTIVE_ENTER_CAR_AS_DRIVER:
+ if (m_pMyVehicle == m_leader->m_pMyVehicle || m_pMyVehicle == m_leader->m_carInObjective)
+ break;
+
+ // fall through
+ default:
+ if (m_pMyVehicle && m_objective != OBJECTIVE_LEAVE_VEHICLE) {
+#ifdef VC_PED_PORTS
+ m_leaveCarTimer = CTimer::GetTimeInMilliseconds() + 250;
+#endif
+ SetObjective(OBJECTIVE_LEAVE_VEHICLE, m_pMyVehicle);
+ }
+
+ break;
+ }
+ }
+ }
+}
+
+void
+CPed::UpdatePosition(void)
+{
+ if (CReplay::IsPlayingBack() || !bIsStanding)
+ return;
+
+ CVector2D velocityChange;
+
+ SetHeading(m_fRotationCur);
+ if (m_pCurrentPhysSurface) {
+ CVector2D velocityOfSurface;
+ CPhysical *curSurface = m_pCurrentPhysSurface;
+ if (!IsPlayer() && m_pCurrentPhysSurface->IsVehicle() && ((CVehicle*)m_pCurrentPhysSurface)->IsBoat()) {
+
+ // It seems R* didn't like m_vecOffsetFromPhysSurface for boats
+ CVector offsetToSurface = GetPosition() - curSurface->GetPosition();
+ offsetToSurface.z -= FEET_OFFSET;
+
+ CVector surfaceMoveVelocity = curSurface->m_vecMoveSpeed;
+ CVector surfaceTurnVelocity = CrossProduct(curSurface->m_vecTurnSpeed, offsetToSurface);
+
+ // Also we use that weird formula instead of friction if it's boat
+ float slideMult = -curSurface->m_vecTurnSpeed.MagnitudeSqr();
+ velocityOfSurface = slideMult * offsetToSurface * CTimer::GetTimeStep() + (surfaceTurnVelocity + surfaceMoveVelocity);
+ m_vecMoveSpeed.z = slideMult * offsetToSurface.z * CTimer::GetTimeStep() + (surfaceTurnVelocity.z + surfaceMoveVelocity.z);
+ } else {
+ velocityOfSurface = curSurface->GetSpeed(m_vecOffsetFromPhysSurface);
+ }
+ // Reminder: m_moved is displacement from walking/running.
+ velocityChange = m_moved + velocityOfSurface - m_vecMoveSpeed;
+ m_fRotationCur += curSurface->m_vecTurnSpeed.z * CTimer::GetTimeStep();
+ m_fRotationDest += curSurface->m_vecTurnSpeed.z * CTimer::GetTimeStep();
+ } else if (m_nSurfaceTouched != SURFACE_STONE || m_vecDamageNormal.x == 0.0f && m_vecDamageNormal.y == 0.0f) {
+ velocityChange = m_moved - m_vecMoveSpeed;
+ } else {
+ // Ped got damaged by steep slope
+ m_vecMoveSpeed = CVector(0.0f, 0.0f, -0.001f);
+ // some kind of
+ CVector2D reactionForce = m_vecDamageNormal * (1.0f / m_vecDamageNormal.Magnitude2D());
+
+ velocityChange = 0.02f * reactionForce + m_moved;
+
+ float reactionAndVelocityDotProd = DotProduct2D(reactionForce, velocityChange);
+ // they're in same direction
+ if (reactionAndVelocityDotProd < 0.0f) {
+ velocityChange -= reactionAndVelocityDotProd * reactionForce;
+ }
+ }
+
+ // Take time step into account
+ if (m_pCurrentPhysSurface) {
+ float speedChange = velocityChange.Magnitude();
+ float changeMult = speedChange;
+ if (m_nPedState != PED_DIE || !m_pCurrentPhysSurface->IsVehicle()) {
+ if (!m_pCurrentPhysSurface->IsVehicle() || !((CVehicle*)m_pCurrentPhysSurface)->IsBoat())
+ changeMult = 0.01f * CTimer::GetTimeStep();
+ } else {
+ changeMult = 0.002f * CTimer::GetTimeStep();
+ }
+
+ if (speedChange > changeMult) {
+ velocityChange = velocityChange * (changeMult / speedChange);
+ }
+ }
+ m_vecMoveSpeed.x += velocityChange.x;
+ m_vecMoveSpeed.y += velocityChange.y;
+}
+
+void
+CPed::SetPedPositionInCar(void)
+{
+ if (CReplay::IsPlayingBack())
+ return;
+
+ if (bChangedSeat) {
+ bool notYet = false;
+ if (RpAnimBlendClumpGetAssociation(GetClump(), ANIM_CAR_GETIN_LHS)
+ || RpAnimBlendClumpGetAssociation(GetClump(), ANIM_CAR_GETIN_LOW_LHS)
+ || RpAnimBlendClumpGetAssociation(GetClump(), ANIM_CAR_CLOSEDOOR_LHS)
+ || RpAnimBlendClumpGetAssociation(GetClump(), ANIM_CAR_CLOSEDOOR_LOW_LHS)
+ || RpAnimBlendClumpGetAssociation(GetClump(), ANIM_CAR_SHUFFLE_RHS)
+ || RpAnimBlendClumpGetAssociation(GetClump(), ANIM_CAR_LSHUFFLE_RHS)
+ || RpAnimBlendClumpGetAssociation(GetClump(), ANIM_VAN_CLOSE_L)
+ || RpAnimBlendClumpGetAssociation(GetClump(), ANIM_VAN_CLOSE)
+ || RpAnimBlendClumpGetAssociation(GetClump(), ANIM_VAN_GETIN_L)
+ || RpAnimBlendClumpGetAssociation(GetClump(), ANIM_VAN_GETIN)
+ || RpAnimBlendClumpGetAssociation(GetClump(), ANIM_COACH_IN_L)
+ || RpAnimBlendClumpGetAssociation(GetClump(), ANIM_COACH_IN_R)) {
+ notYet = true;
+ }
+ if (notYet) {
+ LineUpPedWithCar(LINE_UP_TO_CAR_START);
+ bChangedSeat = false;
+ return;
+ }
+ }
+ CVehicleModelInfo *vehModel = (CVehicleModelInfo*)CModelInfo::GetModelInfo(m_pMyVehicle->m_modelIndex);
+ CMatrix newMat(m_pMyVehicle->GetMatrix());
+ CVector seatPos;
+ if (m_pMyVehicle->pDriver == this) {
+ if (vehModel->m_vehicleType == VEHICLE_TYPE_BOAT)
+ seatPos = vehModel->m_positions[BOAT_POS_FRONTSEAT];
+ else
+ seatPos = vehModel->m_positions[CAR_POS_FRONTSEAT];
+
+ if (!m_pMyVehicle->IsBoat() && m_pMyVehicle->m_vehType != VEHICLE_TYPE_BIKE)
+ seatPos.x = -seatPos.x;
+
+ } else if (m_pMyVehicle->pPassengers[0] == this) {
+ if (vehModel->m_vehicleType == VEHICLE_TYPE_BOAT)
+ seatPos = vehModel->m_positions[BOAT_POS_FRONTSEAT];
+ else
+ seatPos = vehModel->m_positions[CAR_POS_FRONTSEAT];
+ } else if (m_pMyVehicle->pPassengers[1] == this) {
+ seatPos = vehModel->m_positions[CAR_POS_BACKSEAT];
+ seatPos.x = -seatPos.x;
+ } else {
+ if (m_pMyVehicle->pPassengers[2] == this) {
+ seatPos = vehModel->m_positions[CAR_POS_BACKSEAT];
+ } else if (vehModel->m_vehicleType == VEHICLE_TYPE_BOAT) {
+ seatPos = vehModel->m_positions[BOAT_POS_FRONTSEAT];
+ } else {
+ seatPos = vehModel->m_positions[CAR_POS_FRONTSEAT];
+ }
+ }
+ newMat.GetPosition() += Multiply3x3(newMat, seatPos);
+ // Already done below (SetTranslate(0.0f, 0.0f, 0.0f))
+ // tempMat.SetUnity();
+
+ // Rear seats on vans don't face to front, so rotate them HALFPI.
+ if (m_pMyVehicle->bIsVan) {
+ CMatrix tempMat;
+ if (m_pMyVehicle->pPassengers[1] == this) {
+ m_fRotationCur = m_pMyVehicle->GetForward().Heading() - HALFPI;
+ tempMat.SetTranslate(0.0f, 0.0f, 0.0f);
+ tempMat.RotateZ(-HALFPI);
+ newMat = newMat * tempMat;
+ } else if (m_pMyVehicle->pPassengers[2] == this) {
+ m_fRotationCur = HALFPI + m_pMyVehicle->GetForward().Heading();
+ tempMat.SetTranslate(0.0f, 0.0f, 0.0f);
+ tempMat.RotateZ(HALFPI);
+ newMat = newMat * tempMat;
+ } else {
+ m_fRotationCur = m_pMyVehicle->GetForward().Heading();
+ }
+ } else {
+ m_fRotationCur = m_pMyVehicle->GetForward().Heading();
+ }
+ GetMatrix() = newMat;
+}
+
+static RwObject*
+CloneAtomicToFrameCB(RwObject *frame, void *data)
+{
+ RpAtomic *newAtomic = RpAtomicClone((RpAtomic*)frame);
+ RpAtomicSetFrame(newAtomic, (RwFrame*)data);
+ RpClumpAddAtomic(flyingClumpTemp, newAtomic);
+ CVisibilityPlugins::SetAtomicRenderCallback(newAtomic, nil);
+ return frame;
+}
+
+static RwFrame*
+RecurseFrameChildrenToCloneCB(RwFrame *frame, void *data)
+{
+ RwFrame *newFrame = RwFrameCreate();
+ RwFrameAddChild((RwFrame*)data, newFrame);
+ RwFrameTransform(newFrame, RwFrameGetMatrix(frame), rwCOMBINEREPLACE);
+ RwFrameForAllObjects(frame, CloneAtomicToFrameCB, newFrame);
+ RwFrameForAllChildren(frame, RecurseFrameChildrenToCloneCB, newFrame);
+ return newFrame;
+}
+
+CObject*
+CPed::SpawnFlyingComponent(int pedNode, int8 direction)
+{
+ if (CObject::nNoTempObjects >= NUMTEMPOBJECTS)
+ return nil;
+
+ CObject *obj = new CObject();
+ if (!obj)
+ return nil;
+
+ RwFrame *frame = RwFrameCreate();
+ RpClump *clump = RpClumpCreate();
+ RpClumpSetFrame(clump, frame);
+ RwMatrix *matrix = RwFrameGetLTM(GetNodeFrame(pedNode));
+ *RwFrameGetMatrix(frame) = *matrix;
+
+ flyingClumpTemp = clump;
+ RwFrameForAllObjects(GetNodeFrame(pedNode), CloneAtomicToFrameCB, frame);
+ RwFrameForAllChildren(GetNodeFrame(pedNode), RecurseFrameChildrenToCloneCB, frame);
+ flyingClumpTemp = nil;
+ switch (pedNode) {
+ case PED_HEAD:
+ // So popping head would have wheel collision. They disabled it anyway
+ obj->SetModelIndexNoCreate(MI_CAR_WHEEL);
+ break;
+ case PED_UPPERARML:
+ case PED_UPPERARMR:
+ obj->SetModelIndexNoCreate(MI_BODYPARTB);
+ obj->SetCenterOfMass(0.25f, 0.0f, 0.0f);
+ break;
+ case PED_UPPERLEGL:
+ case PED_UPPERLEGR:
+ obj->SetModelIndexNoCreate(MI_BODYPARTA);
+ obj->SetCenterOfMass(0.4f, 0.0f, 0.0f);
+ break;
+ default:
+ break;
+ }
+ obj->RefModelInfo(m_modelIndex);
+ obj->AttachToRwObject((RwObject*)clump);
+ obj->m_fMass = 15.0f;
+ obj->m_fTurnMass = 5.0f;
+ obj->m_fAirResistance = 0.99f;
+ obj->m_fElasticity = 0.03f;
+ obj->m_fBuoyancy = m_fMass*GRAVITY/0.75f;
+ obj->ObjectCreatedBy = TEMP_OBJECT;
+ obj->bIsStatic = false;
+ obj->bIsPickup = false;
+ obj->m_nSpecialCollisionResponseCases = COLLRESPONSE_SPLIT_MODEL;
+
+ // life time - the more objects the are, the shorter this one will live
+ CObject::nNoTempObjects++;
+ if (CObject::nNoTempObjects > 20)
+ obj->m_nEndOfLifeTime = CTimer::GetTimeInMilliseconds() + 12000;
+ else if (CObject::nNoTempObjects > 10)
+ obj->m_nEndOfLifeTime = CTimer::GetTimeInMilliseconds() + 30000;
+ else
+ obj->m_nEndOfLifeTime = CTimer::GetTimeInMilliseconds() + 60000;
+
+ CVector localForcePos, forceDir;
+
+ if (direction == 2) {
+ obj->m_vecMoveSpeed = 0.03f * GetForward();
+ obj->m_vecMoveSpeed.z = (CGeneral::GetRandomNumber() & 0x3F) * 0.001f;
+ obj->m_vecTurnSpeed = CVector(0.0f, 0.0f, 0.0f);
+ localForcePos = CVector(0.0f, 0.0f, 0.0f);
+ forceDir = GetForward();
+ } else {
+ obj->m_vecMoveSpeed = -0.03f * GetForward();
+ obj->m_vecMoveSpeed.z = (CGeneral::GetRandomNumber() & 0x3F) * 0.001f;
+ obj->m_vecTurnSpeed = CVector(0.0f, 0.0f, 0.0f);
+ localForcePos = CVector(0.0f, 0.0f, 0.0f);
+ forceDir = -GetForward();
+ }
+ obj->ApplyTurnForce(forceDir, localForcePos);
+ CWorld::Add(obj);
+
+ return obj;
+}
+
+void
+CPed::WarpPedIntoCar(CVehicle *car)
+{
+ bInVehicle = true;
+ m_pMyVehicle = car;
+ m_pMyVehicle->RegisterReference((CEntity **) &m_pMyVehicle);
+ m_carInObjective = car;
+ m_carInObjective->RegisterReference((CEntity **) &m_carInObjective);
+ m_nPedState = PED_DRIVING;
+ bUsesCollision = false;
+ bIsInTheAir = false;
+ m_ped_flagI4 = true;
+ if (m_objective == OBJECTIVE_ENTER_CAR_AS_DRIVER) {
+ car->SetDriver(this);
+ car->pDriver->RegisterReference((CEntity **) &car->pDriver);
+
+ } else if (m_objective == OBJECTIVE_ENTER_CAR_AS_PASSENGER) {
+ for (int i = 0; i < 4; i++) {
+ if (!car->pPassengers[i]) {
+ car->pPassengers[i] = this;
+ car->pPassengers[i]->RegisterReference((CEntity **) &car->pPassengers[i]);
+ break;
+ }
+ }
+ } else
+ return;
+
+ if (IsPlayer()) {
+ car->m_status = STATUS_PLAYER;
+ AudioManager.PlayerJustGotInCar();
+ CCarCtrl::RegisterVehicleOfInterest(car);
+ } else {
+ car->m_status = STATUS_PHYSICS;
+ }
+
+ CWorld::Remove(this);
+ GetPosition() = car->GetPosition();
+ CWorld::Add(this);
+
+ if (car->bIsAmbulanceOnDuty) {
+ car->bIsAmbulanceOnDuty = false;
+ --CCarCtrl::NumAmbulancesOnDuty;
+ }
+ if (car->bIsFireTruckOnDuty) {
+ car->bIsFireTruckOnDuty = false;
+ --CCarCtrl::NumFiretrucksOnDuty;
+ }
+ if (!car->bEngineOn) {
+ car->bEngineOn = true;
+ DMAudio.PlayOneShot(car->m_audioEntityId, SOUND_CAR_ENGINE_START, 1.0f);
+ }
+ if (car->IsBoat()) {
+ m_pVehicleAnim = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_DRIVE_BOAT, 100.0f);
+ CWeaponInfo *ourWeapon = CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType);
+ RemoveWeaponModel(ourWeapon->m_nModelId);
+ } else {
+
+ // Because we can use Uzi for drive by
+ // RemoveWeaponWhenEnteringVehicle in VC
+ if (IsPlayer() && HasWeapon(WEAPONTYPE_UZI) && GetWeapon(WEAPONTYPE_UZI).m_nAmmoTotal > 0) {
+ if (m_storedWeapon == WEAPONTYPE_UNIDENTIFIED)
+ m_storedWeapon = GetWeapon()->m_eWeaponType;
+ SetCurrentWeapon(WEAPONTYPE_UZI);
+ } else {
+ CWeaponInfo *ourWeapon = CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType);
+ RemoveWeaponModel(ourWeapon->m_nModelId);
+ }
+
+ if (car->bLowVehicle)
+ m_pVehicleAnim = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_CAR_LSIT, 100.0f);
+ else
+ m_pVehicleAnim = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_CAR_SIT, 100.0f);
+ }
+ StopNonPartialAnims();
+ if (car->bIsBus)
+ bRenderPedInCar = false;
+
+ bChangedSeat = true;
+}
+
class CPed_ : public CPed
{
public:
@@ -15956,4 +16772,9 @@ STARTPATCHES
InjectHook(0x4C5FE0, &CPed::ScanForThreats, PATCH_JUMP);
InjectHook(0x4C6C10, &CPed::ScanForInterestingStuff, PATCH_JUMP);
InjectHook(0x4D3F90, &CPed::SeekCar, PATCH_JUMP);
+ InjectHook(0x4E5870, &CPed::ServiceTalking, PATCH_JUMP);
+ InjectHook(0x4E7780, &CPed::StartFightDefend, PATCH_JUMP);
+ InjectHook(0x4D8F30, &CPed::UpdateFromLeader, PATCH_JUMP);
+ InjectHook(0x4D4970, &CPed::SetPedPositionInCar, PATCH_JUMP);
+ InjectHook(0x4D7D20, &CPed::WarpPedIntoCar, PATCH_JUMP);
ENDPATCHES
\ No newline at end of file
diff --git a/src/peds/Ped.h b/src/peds/Ped.h
index b8d2f5dd..50a8bfec 100644
--- a/src/peds/Ped.h
+++ b/src/peds/Ped.h
@@ -15,6 +15,7 @@
struct CPathNode;
class CAccident;
+class CObject;
struct CPedAudioData
{
@@ -58,6 +59,15 @@ enum PedRouteType
PEDROUTE_GO_TO_START_WHEN_DONE
};
+enum FightMoveHitLevel
+{
+ HITLEVEL_NULL,
+ HITLEVEL_GROUND,
+ HITLEVEL_LOW,
+ HITLEVEL_MEDIUM,
+ HITLEVEL_HIGH
+};
+
struct FightMove
{
AnimationId animId;
@@ -65,7 +75,7 @@ struct FightMove
float endFireTime;
float comboFollowOnTime;
float strikeRadius;
- uint8 hitLevel;
+ uint8 hitLevel; // FightMoveHitLevel
uint8 damage;
uint8 flags;
};
@@ -99,7 +109,8 @@ enum PedFightMoves
FIGHTMOVE_HITBIGSTEP,
FIGHTMOVE_HITONFLOOR,
FIGHTMOVE_HITBEHIND,
- FIGHTMOVE_IDLE2NORM
+ FIGHTMOVE_IDLE2NORM,
+ NUM_FIGHTMOVES
};
enum ePedPieceTypes
@@ -352,7 +363,7 @@ public:
uint8 bShakeFist : 1; // test shake hand at look entity
uint8 bNoCriticalHits : 1; // if set, limbs won't came off
- uint8 m_ped_flagI4 : 1; // seems like related with cars
+ uint8 m_ped_flagI4 : 1; // we've been put to car by script? - related with cars
uint8 bHasAlreadyBeenRecorded : 1;
uint8 bFallenDown : 1;
#ifdef VC_PED_PORTS
@@ -420,7 +431,7 @@ public:
float m_headingRate;
uint16 m_vehEnterType; // TODO: this is more like a door, not a type
int16 m_walkAroundType;
- CEntity *m_pCurrentPhysSurface;
+ CPhysical *m_pCurrentPhysSurface;
CVector m_vecOffsetFromPhysSurface;
CEntity *m_pCurSurface;
CVector m_vecSeekPos;
@@ -522,7 +533,6 @@ public:
void SetDead(void);
void ApplyHeadShot(eWeaponType weaponType, CVector pos, bool evenOnPlayer);
void RemoveBodyPart(PedNode nodeId, int8 direction);
- void SpawnFlyingComponent(int, int8);
bool OurPedCanSeeThisOne(CEntity *target);
void Avoid(void);
void Attack(void);
@@ -660,7 +670,6 @@ public:
void ProcessBuoyancy(void);
void ServiceTalking(void);
void SetJump(void);
- void UpdatePosition(void);
void WanderPath(void);
void ReactToPointGun(CEntity*);
void SeekCar(void);
@@ -681,6 +690,7 @@ public:
void ScanForInterestingStuff(void);
void WarpPedIntoCar(CVehicle*);
void SetCarJack(CVehicle*);
+ void WarpPedToNearLeaderOffScreen(void);
// Static methods
static CVector GetLocalPositionToOpenCarDoor(CVehicle *veh, uint32 component, float offset);
@@ -756,6 +766,8 @@ public:
void WanderRange(void);
void SetFollowRoute(int16, int16);
void SeekBoatPosition(void);
+ void UpdatePosition(void);
+ CObject *SpawnFlyingComponent(int, int8);
#ifdef VC_PED_PORTS
bool CanPedJumpThis(CEntity*, CVector*);
#else
@@ -785,9 +797,12 @@ public:
static CPedAudioData (&CommentWaitTime)[38];
#ifndef MASTER
+ static bool bUnusedFightThingOnPlayer;
+ static bool bPopHeadsOnHeadshot;
+
+ // Mobile things
static void SwitchDebugDisplay(void);
void DebugRenderOnePedText(void);
- static bool bUnusedFightThingOnPlayer;
#endif
};
diff --git a/src/render/Credits.cpp b/src/render/Credits.cpp
index 6d20c1ff..8f4e2270 100644
--- a/src/render/Credits.cpp
+++ b/src/render/Credits.cpp
@@ -493,6 +493,11 @@ CCredits::Render(void)
bCreditsGoing = false;
}
+bool CCredits::AreCreditsDone(void)
+{
+ return !bCreditsGoing;
+}
+
STARTPATCHES
InjectHook(0x4FE7A0, CCredits::Init, PATCH_JUMP);
InjectHook(0x4FE760, CCredits::Start, PATCH_JUMP);
diff --git a/src/render/Credits.h b/src/render/Credits.h
index cbe63172..c39fb035 100644
--- a/src/render/Credits.h
+++ b/src/render/Credits.h
@@ -8,7 +8,7 @@ public:
static void Init(void);
static void Start(void);
static void Stop(void);
- static bool AreCreditsDone(void) { return bCreditsGoing; }
+ static bool AreCreditsDone(void);
static void Render(void);
static void PrintCreditSpace(float space, uint32 &line);
static void PrintCreditText(float scaleX, float scaleY, wchar *text, uint32 &lineoffset, float scrolloffset);
diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp
index 562d5882..8322c22a 100644
--- a/src/render/Renderer.cpp
+++ b/src/render/Renderer.cpp
@@ -40,9 +40,9 @@ struct EntityInfo
CLinkList &gSortedVehiclesAndPeds = *(CLinkList*)0x629AC0;
int32 &CRenderer::ms_nNoOfVisibleEntities = *(int32*)0x940730;
-CEntity **CRenderer::ms_aVisibleEntityPtrs = (CEntity**)0x6E9920;
+CEntity *(&CRenderer::ms_aVisibleEntityPtrs)[NUMVISIBLEENTITIES] = *(CEntity * (*)[NUMVISIBLEENTITIES]) * (uintptr*)0x6E9920;
+CEntity *(&CRenderer::ms_aInVisibleEntityPtrs)[NUMINVISIBLEENTITIES] = *(CEntity * (*)[NUMINVISIBLEENTITIES]) * (uintptr*)0x880B50;
int32 &CRenderer::ms_nNoOfInVisibleEntities = *(int32*)0x8F1B78;
-CEntity **CRenderer::ms_aInVisibleEntityPtrs = (CEntity**)0x880B50;
CVector &CRenderer::ms_vecCameraPosition = *(CVector*)0x8E2C3C;
CVehicle *&CRenderer::m_pFirstPersonVehicle = *(CVehicle**)0x885B80;
@@ -73,9 +73,9 @@ CRenderer::PreRender(void)
for(i = 0; i < ms_nNoOfInVisibleEntities; i++)
ms_aInVisibleEntityPtrs[i]->PreRender();
- for(node = CVisibilityPlugins::m_alphaEntityList.tail.prev;
- node != &CVisibilityPlugins::m_alphaEntityList.head;
- node = node->prev)
+ for(node = CVisibilityPlugins::m_alphaEntityList.head.next;
+ node != &CVisibilityPlugins::m_alphaEntityList.tail;
+ node = node->next)
((CEntity*)node->item.entity)->PreRender();
CHeli::SpecialHeliPreRender();
@@ -983,7 +983,7 @@ CRenderer::ScanSectorList(CPtrList *lists)
dy = ms_vecCameraPosition.y - ent->GetPosition().y;
if(dx > -65.0f && dx < 65.0f &&
dy > -65.0f && dy < 65.0f &&
- ms_nNoOfInVisibleEntities < 150)
+ ms_nNoOfInVisibleEntities < NUMINVISIBLEENTITIES - 1)
ms_aInVisibleEntityPtrs[ms_nNoOfInVisibleEntities++] = ent;
break;
case VIS_STREAMME:
@@ -1033,7 +1033,7 @@ CRenderer::ScanSectorList_Priority(CPtrList *lists)
dy = ms_vecCameraPosition.y - ent->GetPosition().y;
if(dx > -65.0f && dx < 65.0f &&
dy > -65.0f && dy < 65.0f &&
- ms_nNoOfInVisibleEntities < 150)
+ ms_nNoOfInVisibleEntities < NUMINVISIBLEENTITIES - 1)
ms_aInVisibleEntityPtrs[ms_nNoOfInVisibleEntities++] = ent;
break;
case VIS_STREAMME:
@@ -1078,7 +1078,7 @@ CRenderer::ScanSectorList_Subway(CPtrList *lists)
dy = ms_vecCameraPosition.y - ent->GetPosition().y;
if(dx > -65.0f && dx < 65.0f &&
dy > -65.0f && dy < 65.0f &&
- ms_nNoOfInVisibleEntities < 150)
+ ms_nNoOfInVisibleEntities < NUMINVISIBLEENTITIES - 1)
ms_aInVisibleEntityPtrs[ms_nNoOfInVisibleEntities++] = ent;
break;
}
@@ -1160,8 +1160,12 @@ CRenderer::IsEntityCullZoneVisible(CEntity *ent)
return IsVehicleCullZoneVisible(ent);
case ENTITY_TYPE_PED:
ped = (CPed*)ent;
- if(ped->bInVehicle)
- return ped->m_pMyVehicle && IsVehicleCullZoneVisible(ped->m_pMyVehicle);
+ if (ped->bInVehicle) {
+ if (ped->m_pMyVehicle)
+ return IsVehicleCullZoneVisible(ped->m_pMyVehicle);
+ else
+ return true;
+ }
return !(ped->m_pCurSurface && ped->m_pCurSurface->bZoneCulled2);
case ENTITY_TYPE_OBJECT:
obj = (CObject*)ent;
diff --git a/src/render/Renderer.h b/src/render/Renderer.h
index 817cdaae..ea49ed4e 100644
--- a/src/render/Renderer.h
+++ b/src/render/Renderer.h
@@ -19,9 +19,9 @@ class CPtrList;
class CRenderer
{
static int32 &ms_nNoOfVisibleEntities;
- static CEntity **ms_aVisibleEntityPtrs; // [2000];
+ static CEntity *(&ms_aVisibleEntityPtrs)[NUMVISIBLEENTITIES];
static int32 &ms_nNoOfInVisibleEntities;
- static CEntity **ms_aInVisibleEntityPtrs; // [150];
+ static CEntity *(&ms_aInVisibleEntityPtrs)[NUMINVISIBLEENTITIES];
static CVector &ms_vecCameraPosition;
static CVehicle *&m_pFirstPersonVehicle;
diff --git a/src/skel/win/win.cpp b/src/skel/win/win.cpp
index 89726ed2..5b328d03 100644
--- a/src/skel/win/win.cpp
+++ b/src/skel/win/win.cpp
@@ -1969,11 +1969,11 @@ _WinMain(HINSTANCE instance,
++gGameState;
else if ( CPad::GetPad(0)->GetLeftMouseJustDown() )
++gGameState;
- else if ( CPad::GetPad(0)->GetPadEnterJustDown() || CPad::GetPad(0)->GetEnterJustDown() )
+ else if ( CPad::GetPad(0)->GetEnterJustDown() )
++gGameState;
- else if ( CPad::GetPad(0)->GetCharJustDown(' ') )
+ else if ( CPad::GetPad(0)->GetCharJustDown(VK_SPACE) )
++gGameState;
- else if ( CPad::GetPad(0)->GetLeftAltJustDown() || CPad::GetPad(0)->GetRightAltJustDown() )
+ else if ( CPad::GetPad(0)->GetAltJustDown() )
++gGameState;
else if ( CPad::GetPad(0)->GetTabJustDown() )
++gGameState;
@@ -2005,11 +2005,11 @@ _WinMain(HINSTANCE instance,
++gGameState;
else if ( CPad::GetPad(0)->GetLeftMouseJustDown() )
++gGameState;
- else if ( CPad::GetPad(0)->GetPadEnterJustDown() || CPad::GetPad(0)->GetEnterJustDown() )
+ else if ( CPad::GetPad(0)->GetEnterJustDown() )
++gGameState;
- else if ( CPad::GetPad(0)->GetCharJustDown(' ') )
+ else if ( CPad::GetPad(0)->GetCharJustDown(VK_SPACE) )
++gGameState;
- else if ( CPad::GetPad(0)->GetLeftAltJustDown() || CPad::GetPad(0)->GetRightAltJustDown() )
+ else if ( CPad::GetPad(0)->GetAltJustDown() )
++gGameState;
else if ( CPad::GetPad(0)->GetTabJustDown() )
++gGameState;
diff --git a/src/vehicles/Automobile.cpp b/src/vehicles/Automobile.cpp
index a077bba4..0f5ff811 100644
--- a/src/vehicles/Automobile.cpp
+++ b/src/vehicles/Automobile.cpp
@@ -2474,8 +2474,8 @@ CAutomobile::TankControl(void)
int lifeSpan = 250;
if(m_vecMoveSpeed.Magnitude() > 0.08f){
lifeSpan = 125;
- flashPos.x += 0.5f*m_vecMoveSpeed.x;
- flashPos.y += 0.5f*m_vecMoveSpeed.y;
+ flashPos.x += 5.0f*m_vecMoveSpeed.x;
+ flashPos.y += 5.0f*m_vecMoveSpeed.y;
}
CParticle::AddParticle(PARTICLE_GUNFLASH, flashPos, nullDir, nil, 0.4f, black, 0, 0, 0, lifeSpan);
flashPos += 0.3f*shotDir;
@@ -4210,7 +4210,7 @@ CAutomobile::SpawnFlyingComponent(int32 component, uint32 type)
if(atomic == nil)
return nil;
- obj = new CObject;
+ obj = new CObject();
if(obj == nil)
return nil;