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;