diff options
author | Nikolay Korolev <nickvnuk@gmail.com> | 2019-08-17 14:46:19 +0200 |
---|---|---|
committer | Nikolay Korolev <nickvnuk@gmail.com> | 2019-08-17 14:46:19 +0200 |
commit | 13233ccaed3fd7aad37c99326beee3ddfaf437f3 (patch) | |
tree | 82f5205ffe573d41060ec29646e821841f651837 /src | |
parent | more CCarCtrl (diff) | |
parent | Merge pull request #193 from erorcun/erorcun (diff) | |
download | re3-13233ccaed3fd7aad37c99326beee3ddfaf437f3.tar re3-13233ccaed3fd7aad37c99326beee3ddfaf437f3.tar.gz re3-13233ccaed3fd7aad37c99326beee3ddfaf437f3.tar.bz2 re3-13233ccaed3fd7aad37c99326beee3ddfaf437f3.tar.lz re3-13233ccaed3fd7aad37c99326beee3ddfaf437f3.tar.xz re3-13233ccaed3fd7aad37c99326beee3ddfaf437f3.tar.zst re3-13233ccaed3fd7aad37c99326beee3ddfaf437f3.zip |
Diffstat (limited to 'src')
48 files changed, 2706 insertions, 420 deletions
diff --git a/src/audio/AudioManager.cpp b/src/audio/AudioManager.cpp index bd99628e..e586366d 100644 --- a/src/audio/AudioManager.cpp +++ b/src/audio/AudioManager.cpp @@ -440,7 +440,7 @@ cAudioManager::ComputeVolume(int emittingVolume, float soundIntensity, float dis } int32 -cAudioManager::CreateEntity(int32 type, CPhysical *entity) +cAudioManager::CreateEntity(int32 type, void *entity) { if(!m_bIsInitialised) return -4; if(!entity) return -2; @@ -477,8 +477,8 @@ cAudioManager::DestroyAllGameCreatedEntities() case AUDIOTYPE_WEATHER: case AUDIOTYPE_CRANE: case AUDIOTYPE_GARAGE: - case AUDIOTYPE_HYDRANT: cAudioManager::DestroyEntity(i); break; - case AUDIOTYPE_ONE_SHOT: + case AUDIOTYPE_FIREHYDRANT: cAudioManager::DestroyEntity(i); break; + case AUDIOTYPE_SCRIPTOBJECT: entity = (cAudioScriptObject *)m_asAudioEntities[i].m_pEntity; if(entity) { delete entity; } @@ -602,10 +602,10 @@ cAudioManager::PostInitialiseGameSpecificSetup() m_nProjectileEntity = CreateEntity(AUDIOTYPE_PROJECTILE, (CPhysical *)1); if(m_nProjectileEntity >= 0) SetEntityStatus(m_nProjectileEntity, 1); - m_nWaterCannonEntity = CreateEntity(AUDIOTYPE_WATER_CANNON, (CPhysical *)1); + m_nWaterCannonEntity = CreateEntity(AUDIOTYPE_WATERCANNON, (CPhysical *)1); if(m_nWaterCannonEntity >= 0) SetEntityStatus(m_nWaterCannonEntity, 1); - m_nPoliceChannelEntity = CreateEntity(AUDIOTYPE_D, (CPhysical *)1); + m_nPoliceChannelEntity = CreateEntity(AUDIOTYPE_POLICERADIO, (CPhysical *)1); if(m_nPoliceChannelEntity >= 0) SetEntityStatus(m_nPoliceChannelEntity, 1); m_nBridgeEntity = CreateEntity(AUDIOTYPE_BRIDGE, (CPhysical *)1); @@ -4029,7 +4029,7 @@ cAudioManager::ProcessEntity(int32 id) cAudioManager::ProcessCrane(); } break; - case AUDIOTYPE_ONE_SHOT: + case AUDIOTYPE_SCRIPTOBJECT: if(!m_bUserPause) { m_sQueueSample.m_bReverbFlag = 1; cAudioManager::ProcessScriptObject(id); @@ -4054,13 +4054,13 @@ cAudioManager::ProcessEntity(int32 id) case AUDIOTYPE_GARAGE: if(!m_bUserPause) cAudioManager::ProcessGarages(); break; - case AUDIOTYPE_HYDRANT: + case AUDIOTYPE_FIREHYDRANT: if(!m_bUserPause) { m_sQueueSample.m_bReverbFlag = 1; cAudioManager::ProcessFireHydrant(); } break; - case AUDIOTYPE_WATER_CANNON: + case AUDIOTYPE_WATERCANNON: if(!m_bUserPause) { m_sQueueSample.m_bReverbFlag = 1; cAudioManager::ProcessWaterCannon(id); @@ -5617,6 +5617,51 @@ cAudioManager::Service() EAXJMP(0x57A2A0); } +WRAPPER void cAudioManager::PlayOneShot(int, unsigned short, float) +{ + EAXJMP(0x57A500); +} + +WRAPPER void cAudioManager::SetEffectsFadeVol(unsigned char) +{ + EAXJMP(0x57A770); +} + +WRAPPER void cAudioManager::SetMusicFadeVol(unsigned char) +{ + EAXJMP(0x57A790); +} + +WRAPPER int8 cAudioManager::SetCurrent3DProvider(unsigned char) +{ + EAXJMP(0x57A910); +} + +WRAPPER void cAudioManager::ReportCrime(eCrimeType, CVector const &) +{ + EAXJMP(0x5803D0); +} + +WRAPPER void cAudioManager::PlaySuspectLastSeen(float, float, float) +{ + EAXJMP(0x580500); +} + +WRAPPER void cAudioManager::ReportCollision(CEntity *, CEntity *, unsigned char, unsigned char, float, float) +{ + EAXJMP(0x568410); +} + +WRAPPER void cAudioManager::ResetTimers(unsigned int) +{ + EAXJMP(0x57A7B0); +} + +WRAPPER void cAudioManager::PreloadMissionAudio(char *) +{ + EAXJMP(0x579550); +} + STARTPATCHES InjectHook(0x57B210, &cAudioManager::AddDetailsToRequestedOrderList, PATCH_JUMP); InjectHook(0x56AD30, &cAudioManager::AddPlayerCarSample, PATCH_JUMP); diff --git a/src/audio/AudioManager.h b/src/audio/AudioManager.h index f592d3f3..0d4a6f30 100644 --- a/src/audio/AudioManager.h +++ b/src/audio/AudioManager.h @@ -59,15 +59,15 @@ enum eAudioType : int32 { AUDIOTYPE_FIRE = 2, AUDIOTYPE_WEATHER = 3, AUDIOTYPE_CRANE = 4, - AUDIOTYPE_ONE_SHOT = 5, + AUDIOTYPE_SCRIPTOBJECT = 5, AUDIOTYPE_BRIDGE = 6, AUDIOTYPE_COLLISION = 7, AUDIOTYPE_FRONTEND = 8, AUDIOTYPE_PROJECTILE = 9, AUDIOTYPE_GARAGE = 10, - AUDIOTYPE_HYDRANT = 11, - AUDIOTYPE_WATER_CANNON = 12, - AUDIOTYPE_D = 13, + AUDIOTYPE_FIREHYDRANT = 11, + AUDIOTYPE_WATERCANNON = 12, + AUDIOTYPE_POLICERADIO = 13, TOTAL_AUDIO_TYPES = 14, }; @@ -173,10 +173,12 @@ class CPlane; class CVehicle; class CPed; -struct cAudioScriptObject { - int16 m_wSound; - CVector m_vecPos; - int m_nAudioEntityId; +class cAudioScriptObject { +public: + int16 AudioId; + char _pad0[2]; + CVector Posn; + int32 AudioEntity; static void *operator new(size_t); static void *operator new(size_t, int); @@ -203,6 +205,19 @@ enum REFLECTION_UP, MAX_REFLECTIONS, }; + +enum AudioEntityHandle +{ + AEHANDLE_NONE = -5, + AEHANDLE_ERROR_NOAUDIOSYS = -4, + AEHANDLE_ERROR_NOFREESLOT = -3, + AEHANDLE_ERROR_NOENTITY = -2, + AEHANDLE_ERROR_BADAUDIOTYPE = -1, +}; + +#define AEHANDLE_IS_FAILED(h) ((h)<0) +#define AEHANDLE_IS_OK(h) ((h)>=0) + class cAudioManager { @@ -255,8 +270,7 @@ public: inline uint32 GetFrameCounter(void) { return m_FrameCounter; } float GetReflectionsDistance(int32 idx) { return m_afReflectionsDistances[idx]; } - int32 GetRandomTabe(int32 idx) { return m_anRandomTable[idx]; } - + int32 GetRandomNumber(int32 idx) { return m_anRandomTable[idx]; } // void AddDetailsToRequestedOrderList(uint8 sample); /// ok @@ -276,7 +290,7 @@ public: float speedMultiplier); /// ok int32 ComputePan(float, CVector *); // todo uint32 ComputeVolume(int emittingVolume, float soundIntensity, float distance); /// ok - int32 CreateEntity(int32 type, CPhysical *entity); /// ok + int32 CreateEntity(int32 type, void *entity); /// ok void DestroyAllGameCreatedEntities(); /// ok void DestroyEntity(int32 id); /// ok @@ -509,6 +523,17 @@ public: void ProcessWeather(int32 id); // todo // bool ProcessWetRoadNoise(void *); void ProcessWorkShopScriptObject(uint8 sound); /// ok + + + void PlayOneShot(int, unsigned short, float); + void SetEffectsFadeVol(unsigned char); + void SetMusicFadeVol(unsigned char); + int8 SetCurrent3DProvider(unsigned char); + void ReportCrime(eCrimeType, CVector const &); + void PlaySuspectLastSeen(float, float, float); + void ReportCollision(CEntity *, CEntity *, unsigned char, unsigned char, float, float); + void ResetTimers(unsigned int); + void PreloadMissionAudio(char *); }; static_assert(sizeof(cAudioManager) == 0x4B14, "cAudioManager: error"); diff --git a/src/audio/AudioScriptObject.h b/src/audio/AudioScriptObject.h index c325ce27..3d32913d 100644 --- a/src/audio/AudioScriptObject.h +++ b/src/audio/AudioScriptObject.h @@ -1,131 +1,131 @@ #pragma once -enum /*eSounds*/ +enum { - SOUND_TEST_1 = 0, - _SOUND_UNK_1 = 1, - _SOUND_UNK_2 = 2, - _SOUND_UNK_3 = 3, - _SOUND_CLUB_1_S = 4, - _SOUND_CLUB_1_L = 5, - _SOUND_CLUB_2_S = 6, - _SOUND_CLUB_2_L = 7, - _SOUND_CLUB_3_S = 8, - _SOUND_CLUB_3_L = 9, - _SOUND_CLUB_4_S = 10, - _SOUND_CLUB_4_L = 11, - _SOUND_CLUB_5_S = 12, - _SOUND_CLUB_5_L = 13, - _SOUND_CLUB_6_S = 14, - _SOUND_CLUB_6_L = 15, - _SOUND_CLUB_7_S = 16, - _SOUND_CLUB_7_L = 17, - _SOUND_CLUB_8_S = 18, - _SOUND_CLUB_8_L = 19, - _SOUND_CLUB_9_S = 20, - _SOUND_CLUB_9_L = 21, - _SOUND_CLUB_10_S = 22, - _SOUND_CLUB_10_L = 23, - _SOUND_CLUB_11_S = 24, - _SOUND_CLUB_11_L = 25, - _SOUND_CLUB_12_S = 26, - _SOUND_CLUB_12_L = 27, - _SOUND_CLUB_RAGGA_S = 28, - _SOUND_CLUB_RAGGA_L = 29, - SOUND_STRIP_CLUB_LOOP_1_S = 30, - _SOUND_STRIP_CLUB_LOOP_1_L = 31, - SOUND_STRIP_CLUB_LOOP_2_S = 32, - _SOUND_STRIP_CLUB_LOOP_2_L = 33, - _SOUND_SFX_WORKSHOP_1 = 34, - _SOUND_SFX_WORKSHOP_2 = 35, - _SOUND_SAWMILL_LOOP_S = 36, - SOUND_SAWMILL_LOOP_L = 37, - _SOUND_DOG_FOOD_FACTORY_S = 38, - _SOUND_DOG_FOOD_FACTORY_L = 39, - _SOUND_LAUNDERETTE_1 = 40, - _SOUND_LAUNDERETTE_2 = 41, - _SOUND_RESTAURANT_CHINATOWN_S = 42, - _SOUND_RESTAURANT_CHINATOWN_L = 43, - _SOUND_RESTAURANT_ITALY_S = 44, - _SOUND_RESTAURANT_ITALY_L = 45, - _SOUND_RESTAURANT_GENERIC_1_S = 46, - _SOUND_RESTAURANT_GENERIC_1_L = 47, - _SOUND_RESTAURANT_GENERIC_2_S = 48, - _SOUND_RESTAURANT_GENERIC_2_L = 49, - _SOUND_AIRPORT_ANNOUNCEMENT_S = 50, - _SOUND_AIRPORT_ANNOUNCEMENT_L = 51, - _SOUND_SHOP_LOOP_1 = 52, - _SOUND_SHOP_LOOP_2 = 53, - _SOUND_CINEMA_S = 54, - _SOUND_CINEMA_L = 55, - _SOUND_DOCKS_FOGHORN_S = 56, - _SOUND_DOCKS_FOGHORN_L = 57, - _SOUND_HOME_S = 58, - _SOUND_HOME_L = 59, - _SOUND_PIANO_BAR = 60, - _SOUND_CLUB = 61, - SOUND_PORN_CINEMA_1_S = 62, - _SOUND_PORN_CINEMA_1_L = 63, - SOUND_PORN_CINEMA_2_S = 64, - _SOUND_PORN_CINEMA_2_L = 65, - SOUND_PORN_CINEMA_3_S = 66, - _SOUND_PORN_CINEMA_3_L = 67, - _SOUND_BANK_ALARM_LOOP_S = 68, - SOUND_BANK_ALARM_LOOP_L = 69, - _SOUND_POLICE_BALL_LOOP_S = 70, - SOUND_POLICE_BALL_LOOP_L = 71, - _SOUND_RAVE_LOOP_INDUSTRIAL_S = 72, - SOUND_RAVE_LOOP_INDUSTRIAL_L = 73, - _SOUND_UNK_74 = 74, - _SOUND_UNK_75 = 75, - _SOUND_POLICE_CELL_BEATING_LOOP_S = 76, - SOUND_POLICE_CELL_BEATING_LOOP_L = 77, - SOUND_INJURED_PED_MALE_OUCH_S = 78, - SOUND_INJURED_PED_MALE_OUCH_L = 79, - SOUND_INJURED_PED_FEMALE_OUCH_S = 80, - SOUND_INJURED_PED_FEMALE_OUCH_L = 81, - SOUND_EVIDENCE_PICKUP = 82, - SOUND_UNLOAD_GOLD = 83, - _SOUND_RAVE_INDUSTRIAL_S = 84, - _SOUND_RAVE_INDUSTRIAL_L = 85, - _SOUND_RAVE_COMMERCIAL_S = 86, - _SOUND_RAVE_COMMERCIAL_L = 87, - _SOUND_RAVE_SUBURBAN_S = 88, - _SOUND_RAVE_SUBURBAN_L = 89, - _SOUND_GROAN_S = 90, - _SOUND_GROAN_L = 91, - SOUND_GATE_START_CLUNK = 92, - SOUND_GATE_STOP_CLUNK = 93, - SOUND_PART_MISSION_COMPLETE = 94, - SOUND_CHUNKY_RUN_SHOUT = 95, - SOUND_SECURITY_GUARD_RUN_AWAY_SHOUT = 96, - SOUND_RACE_START_1 = 97, - SOUND_RACE_START_2 = 98, - SOUND_RACE_START_3 = 99, - SOUND_RACE_START_GO = 100, - SOUND_SWAT_PED_SHOUT = 101, - SOUND_PRETEND_FIRE_LOOP = 102, - SOUND_AMMUNATION_CHAT_1 = 103, - SOUND_AMMUNATION_CHAT_2 = 104, - SOUND_AMMUNATION_CHAT_3 = 105, - _SOUND_BULLET_WALL_1 = 106, - _SOUND_BULLET_WALL_2 = 107, - _SOUND_BULLET_WALL_3 = 108, - _SOUND_UNK_109 = 109, - _SOUND_GLASSFX2_1 = 110, - _SOUND_GLASSFX2_2 = 111, - _SOUND_PHONE_RING = 112, - _SOUND_UNK_113 = 113, - _SOUND_GLASS_SMASH_1 = 114, - _SOUND_GLASS_SMASH_2 = 115, - _SOUND_GLASS_CRACK = 116, - _SOUND_GLASS_SHARD = 117, - _SOUND_WOODEN_BOX_SMASH = 118, - _SOUND_CARDBOARD_BOX_SMASH = 119, - _SOUND_COL_CAR = 120, - _SOUND_TYRE_BUMP = 121, - _SOUND_BULLET_SHELL_HIT_GROUND_1 = 122, - _SOUND_BULLET_SHELL_HIT_GROUND_2 = 123, + SCRSOUND_TEST_1 = 0, + _SCRSOUND_UNK_1 = 1, + _SCRSOUND_UNK_2 = 2, + _SCRSOUND_UNK_3 = 3, + _SCRSOUND_CLUB_1_S = 4, + _SCRSOUND_CLUB_1_L = 5, + _SCRSOUND_CLUB_2_S = 6, + _SCRSOUND_CLUB_2_L = 7, + _SCRSOUND_CLUB_3_S = 8, + _SCRSOUND_CLUB_3_L = 9, + _SCRSOUND_CLUB_4_S = 10, + _SCRSOUND_CLUB_4_L = 11, + _SCRSOUND_CLUB_5_S = 12, + _SCRSOUND_CLUB_5_L = 13, + _SCRSOUND_CLUB_6_S = 14, + _SCRSOUND_CLUB_6_L = 15, + _SCRSOUND_CLUB_7_S = 16, + _SCRSOUND_CLUB_7_L = 17, + _SCRSOUND_CLUB_8_S = 18, + _SCRSOUND_CLUB_8_L = 19, + _SCRSOUND_CLUB_9_S = 20, + _SCRSOUND_CLUB_9_L = 21, + _SCRSOUND_CLUB_10_S = 22, + _SCRSOUND_CLUB_10_L = 23, + _SCRSOUND_CLUB_11_S = 24, + _SCRSOUND_CLUB_11_L = 25, + _SCRSOUND_CLUB_12_S = 26, + _SCRSOUND_CLUB_12_L = 27, + _SCRSOUND_CLUB_RAGGA_S = 28, + _SCRSOUND_CLUB_RAGGA_L = 29, + SCRSOUND_STRIP_CLUB_LOOP_1_S = 30, + _SCRSOUND_STRIP_CLUB_LOOP_1_L = 31, + SCRSOUND_STRIP_CLUB_LOOP_2_S = 32, + _SCRSOUND_STRIP_CLUB_LOOP_2_L = 33, + _SCRSOUND_SFX_WORKSHOP_1 = 34, + _SCRSOUND_SFX_WORKSHOP_2 = 35, + _SCRSOUND_SAWMILL_LOOP_S = 36, + SCRSOUND_SAWMILL_LOOP_L = 37, + _SCRSOUND_DOG_FOOD_FACTORY_S = 38, + _SCRSOUND_DOG_FOOD_FACTORY_L = 39, + _SCRSOUND_LAUNDERETTE_1 = 40, + _SCRSOUND_LAUNDERETTE_2 = 41, + _SCRSOUND_RESTAURANT_CHINATOWN_S = 42, + _SCRSOUND_RESTAURANT_CHINATOWN_L = 43, + _SCRSOUND_RESTAURANT_ITALY_S = 44, + _SCRSOUND_RESTAURANT_ITALY_L = 45, + _SCRSOUND_RESTAURANT_GENERIC_1_S = 46, + _SCRSOUND_RESTAURANT_GENERIC_1_L = 47, + _SCRSOUND_RESTAURANT_GENERIC_2_S = 48, + _SCRSOUND_RESTAURANT_GENERIC_2_L = 49, + _SCRSOUND_AIRPORT_ANNOUNCEMENT_S = 50, + _SCRSOUND_AIRPORT_ANNOUNCEMENT_L = 51, + _SCRSOUND_SHOP_LOOP_1 = 52, + _SCRSOUND_SHOP_LOOP_2 = 53, + _SCRSOUND_CINEMA_S = 54, + _SCRSOUND_CINEMA_L = 55, + _SCRSOUND_DOCKS_FOGHORN_S = 56, + _SCRSOUND_DOCKS_FOGHORN_L = 57, + _SCRSOUND_HOME_S = 58, + _SCRSOUND_HOME_L = 59, + _SCRSOUND_PIANO_BAR = 60, + _SCRSOUND_CLUB = 61, + SCRSOUND_PORN_CINEMA_1_S = 62, + _SCRSOUND_PORN_CINEMA_1_L = 63, + SCRSOUND_PORN_CINEMA_2_S = 64, + _SCRSOUND_PORN_CINEMA_2_L = 65, + SCRSOUND_PORN_CINEMA_3_S = 66, + _SCRSOUND_PORN_CINEMA_3_L = 67, + _SCRSOUND_BANK_ALARM_LOOP_S = 68, + SCRSOUND_BANK_ALARM_LOOP_L = 69, + _SCRSOUND_POLICE_BALL_LOOP_S = 70, + SCRSOUND_POLICE_BALL_LOOP_L = 71, + _SCRSOUND_RAVE_LOOP_INDUSTRIAL_S = 72, + SCRSOUND_RAVE_LOOP_INDUSTRIAL_L = 73, + _SCRSOUND_UNK_74 = 74, + _SCRSOUND_UNK_75 = 75, + _SCRSOUND_POLICE_CELL_BEATING_LOOP_S = 76, + SCRSOUND_POLICE_CELL_BEATING_LOOP_L = 77, + SCRSOUND_INJURED_PED_MALE_OUCH_S = 78, + SCRSOUND_INJURED_PED_MALE_OUCH_L = 79, + SCRSOUND_INJURED_PED_FEMALE_OUCH_S = 80, + SCRSOUND_INJURED_PED_FEMALE_OUCH_L = 81, + SCRSOUND_EVIDENCE_PICKUP = 82, + SCRSOUND_UNLOAD_GOLD = 83, + _SCRSOUND_RAVE_INDUSTRIAL_S = 84, + _SCRSOUND_RAVE_INDUSTRIAL_L = 85, + _SCRSOUND_RAVE_COMMERCIAL_S = 86, + _SCRSOUND_RAVE_COMMERCIAL_L = 87, + _SCRSOUND_RAVE_SUBURBAN_S = 88, + _SCRSOUND_RAVE_SUBURBAN_L = 89, + _SCRSOUND_GROAN_S = 90, + _SCRSOUND_GROAN_L = 91, + SCRSOUND_GATE_START_CLUNK = 92, + SCRSOUND_GATE_STOP_CLUNK = 93, + SCRSOUND_PART_MISSION_COMPLETE = 94, + SCRSOUND_CHUNKY_RUN_SHOUT = 95, + SCRSOUND_SECURITY_GUARD_RUN_AWAY_SHOUT = 96, + SCRSOUND_RACE_START_1 = 97, + SCRSOUND_RACE_START_2 = 98, + SCRSOUND_RACE_START_3 = 99, + SCRSOUND_RACE_START_GO = 100, + SCRSOUND_SWAT_PED_SHOUT = 101, + SCRSOUND_PRETEND_FIRE_LOOP = 102, + SCRSOUND_AMMUNATION_CHAT_1 = 103, + SCRSOUND_AMMUNATION_CHAT_2 = 104, + SCRSOUND_AMMUNATION_CHAT_3 = 105, + _SCRSOUND_BULLET_WALL_1 = 106, + _SCRSOUND_BULLET_WALL_2 = 107, + _SCRSOUND_BULLET_WALL_3 = 108, + _SCRSOUND_UNK_109 = 109, + _SCRSOUND_GLASSFX2_1 = 110, + _SCRSOUND_GLASSFX2_2 = 111, + _SCRSOUND_PHONE_RING = 112, + _SCRSOUND_UNK_113 = 113, + _SCRSOUND_GLASS_SMASH_1 = 114, + _SCRSOUND_GLASS_SMASH_2 = 115, + _SCRSOUND_GLASS_CRACK = 116, + _SCRSOUND_GLASS_SHARD = 117, + _SCRSOUND_WOODEN_BOX_SMASH = 118, + _SCRSOUND_CARDBOARD_BOX_SMASH = 119, + _SCRSOUND_COL_CAR = 120, + _SCRSOUND_TYRE_BUMP = 121, + _SCRSOUND_BULLET_SHELL_HIT_GROUND_1 = 122, + _SCRSOUND_BULLET_SHELL_HIT_GROUND_2 = 123, }; extern void PlayOneShotScriptObject(uint8 id, CVector const &pos);
\ No newline at end of file diff --git a/src/audio/DMAudio.cpp b/src/audio/DMAudio.cpp index 6c5ad6e3..6fb6d1e5 100644 --- a/src/audio/DMAudio.cpp +++ b/src/audio/DMAudio.cpp @@ -1,40 +1,374 @@ #include "common.h" #include "patcher.h" #include "DMAudio.h" +#include "MusicManager.h" +#include "AudioManager.h" +#include "sampman.h" cDMAudio &DMAudio = *(cDMAudio*)0x95CDBE; -WRAPPER void cDMAudio::Terminate(void) { EAXJMP(0x57C780); } -WRAPPER void cDMAudio::ReleaseDigitalHandle(void) { EAXJMP(0x57CA10); } -WRAPPER void cDMAudio::ReacquireDigitalHandle(void) { EAXJMP(0x57CA30); } - -WRAPPER void cDMAudio::Service(void) { EAXJMP(0x57C7A0); } -WRAPPER void cDMAudio::ReportCollision(CEntity *A, CEntity *B, uint8 surfA, uint8 surfB, float impulse, float speed) { EAXJMP(0x57CBE0); } -WRAPPER void cDMAudio::ResetTimers(uint32 timerval) { EAXJMP(0x57CCD0); } -WRAPPER bool cDMAudio::IsAudioInitialised() { EAXJMP(0x57CAB0); } -WRAPPER char cDMAudio::GetCDAudioDriveLetter() { EAXJMP(0x57CA90); } -WRAPPER bool cDMAudio::CheckForAnAudioFileOnCD() { EAXJMP(0x57CA70); } -WRAPPER void cDMAudio::ChangeMusicMode(uint8 mode) { EAXJMP(0x57CCF0); } - -WRAPPER void cDMAudio::PlayFrontEndSound(uint32, uint32) { EAXJMP(0x57CC20); } -WRAPPER void cDMAudio::PlayFrontEndTrack(uint32, uint32) { EAXJMP(0x57CC80); } -WRAPPER void cDMAudio::StopFrontEndTrack() { EAXJMP(0x57CCB0); } -WRAPPER void cDMAudio::PlayOneShot(int32 audioentity, uint16 sound/*eSound*/, float) { EAXJMP(0x57C840); } -WRAPPER void cDMAudio::SetMusicMasterVolume(uint8) { EAXJMP(0x57C8C0); } -WRAPPER void cDMAudio::SetEffectsMasterVolume(uint8) { EAXJMP(0x57C890); } -WRAPPER uint8 cDMAudio::SetCurrent3DProvider(uint8) { EAXJMP(0x57C9B0); } -WRAPPER int32 cDMAudio::SetSpeakerConfig(int32) { EAXJMP(0x57C9D0); } - -WRAPPER int32 cDMAudio::GetRadioInCar() { EAXJMP(0x57CE40); } -WRAPPER uint8 cDMAudio::IsMP3RadioChannelAvailable() { EAXJMP(0x57C9F0); } -WRAPPER void cDMAudio::SetEffectsFadeVol(uint8) { EAXJMP(0x57C8F0); } -WRAPPER void cDMAudio::SetMusicFadeVol(uint8) { EAXJMP(0x57C920); } -WRAPPER int32 cDMAudio::CreateEntity(int, void*) { EAXJMP(0x57C7C0); } -WRAPPER void cDMAudio::SetEntityStatus(int32 id, uint8 enable) { EAXJMP(0x57C810); } -WRAPPER void cDMAudio::SetRadioInCar(int32) { EAXJMP(0x57CE60); } -WRAPPER void cDMAudio::DestroyEntity(int32) { EAXJMP(0x57C7F0); } -WRAPPER void cDMAudio::ClearMissionAudio(void) { EAXJMP(0x57CE20); } -WRAPPER void cDMAudio::ReportCrime(eCrimeType crime, const CVector &pos) { EAXJMP(0x57CAD0); } -WRAPPER void cDMAudio::CreateOneShotScriptObject(cAudioScriptObject*) { EAXJMP(0x57CB60); } -WRAPPER int32 cDMAudio::CreateLoopingScriptObject(cAudioScriptObject*) { EAXJMP(0x57CB00); } -WRAPPER void cDMAudio::DestroyLoopingScriptObject(int32) { EAXJMP(0x57CB40); } + +void +cDMAudio::Initialise(void) +{ + AudioManager.Initialise(); +} + +void +cDMAudio::Terminate(void) +{ + AudioManager.Terminate(); +} + +void +cDMAudio::Service(void) +{ + AudioManager.Service(); +} + +int32 +cDMAudio::CreateEntity(eAudioType type, void *UID) +{ + return AudioManager.CreateEntity(type, UID); +} + +void +cDMAudio::DestroyEntity(int32 audioEntity) +{ + AudioManager.DestroyEntity(audioEntity); +} + +void +cDMAudio::SetEntityStatus(int32 audioEntity, uint8 status) +{ + AudioManager.SetEntityStatus(audioEntity, status); +} + +void +cDMAudio::PlayOneShot(int32 audioEntity, uint16 oneShot, float volume) +{ + AudioManager.PlayOneShot(audioEntity, oneShot, volume); +} + +void +cDMAudio::DestroyAllGameCreatedEntities(void) +{ + AudioManager.DestroyAllGameCreatedEntities(); +} + +void +cDMAudio::SetEffectsMasterVolume(uint8 volume) +{ + uint8 vol = volume; + if ( vol > MAX_VOLUME ) vol = MAX_VOLUME; + + AudioManager.SetEffectsMasterVolume(vol); +} + +void +cDMAudio::SetMusicMasterVolume(uint8 volume) +{ + uint8 vol = volume; + if ( vol > MAX_VOLUME ) vol = MAX_VOLUME; + + AudioManager.SetMusicMasterVolume(vol); +} + +void +cDMAudio::SetEffectsFadeVol(uint8 volume) +{ + uint8 vol = volume; + if ( vol > MAX_VOLUME ) vol = MAX_VOLUME; + + AudioManager.SetEffectsFadeVol(vol); +} + +void +cDMAudio::SetMusicFadeVol(uint8 volume) +{ + uint8 vol = volume; + if ( vol > MAX_VOLUME ) vol = MAX_VOLUME; + + AudioManager.SetMusicFadeVol(vol); +} + +uint8 +cDMAudio::GetNum3DProvidersAvailable(void) +{ + return AudioManager.GetNum3DProvidersAvailable(); +} + +char * +cDMAudio::Get3DProviderName(uint8 id) +{ + return AudioManager.Get3DProviderName(id); +} + +int8 +cDMAudio::GetCurrent3DProviderIndex(void) +{ + return AudioManager.GetCurrent3DProviderIndex(); +} + +int8 +cDMAudio::SetCurrent3DProvider(uint8 which) +{ + return AudioManager.SetCurrent3DProvider(which); +} + +void +cDMAudio::SetSpeakerConfig(int32 config) +{ + AudioManager.SetSpeakerConfig(config); +} + +bool +cDMAudio::IsMP3RadioChannelAvailable(void) +{ + return AudioManager.IsMP3RadioChannelAvailable(); +} + +void +cDMAudio::ReleaseDigitalHandle(void) +{ + AudioManager.ReleaseDigitalHandle(); +} + +void +cDMAudio::ReacquireDigitalHandle(void) +{ + AudioManager.ReacquireDigitalHandle(); +} + +void +cDMAudio::SetDynamicAcousticModelingStatus(uint8 status) +{ + AudioManager.SetDynamicAcousticModelingStatus(status); +} + +bool +cDMAudio::CheckForAnAudioFileOnCD(void) +{ + return AudioManager.CheckForAnAudioFileOnCD(); +} + +char +cDMAudio::GetCDAudioDriveLetter(void) +{ + return AudioManager.GetCDAudioDriveLetter(); +} + +bool +cDMAudio::IsAudioInitialised(void) +{ + return AudioManager.IsAudioInitialised(); +} + +void +cDMAudio::ReportCrime(eCrimeType crime, CVector const &pos) +{ + AudioManager.ReportCrime(crime, pos); +} + +int32 +cDMAudio::CreateLoopingScriptObject(cAudioScriptObject *scriptObject) +{ + int32 audioEntity = AudioManager.CreateEntity(AUDIOTYPE_SCRIPTOBJECT, scriptObject); + + if ( AEHANDLE_IS_OK(audioEntity) ) + AudioManager.SetEntityStatus(audioEntity, true); + + return audioEntity; +} + +void +cDMAudio::DestroyLoopingScriptObject(int32 audioEntity) +{ + AudioManager.DestroyEntity(audioEntity); +} + +void +cDMAudio::CreateOneShotScriptObject(cAudioScriptObject *scriptObject) +{ + int32 audioEntity = AudioManager.CreateEntity(AUDIOTYPE_SCRIPTOBJECT, scriptObject); + + if ( AEHANDLE_IS_OK(audioEntity) ) + { + AudioManager.SetEntityStatus(audioEntity, true); + AudioManager.PlayOneShot(audioEntity, scriptObject->AudioId, 0.0f); + } +} + +void +cDMAudio::PlaySuspectLastSeen(float x, float y, float z) +{ + AudioManager.PlaySuspectLastSeen(x, y, z); +} + +void +cDMAudio::ReportCollision(CEntity *entityA, CEntity *entityB, uint8 surfaceTypeA, uint8 surfaceTypeB, float collisionPower, float velocity) +{ + AudioManager.ReportCollision(entityA, entityB, surfaceTypeA, surfaceTypeB, collisionPower, velocity); +} + +void +cDMAudio::PlayFrontEndSound(uint16 frontend, uint32 volume) +{ + AudioManager.PlayOneShot(AudioManager.m_nFrontEndEntity, frontend, (float)volume); +} + +void +cDMAudio::PlayRadioAnnouncement(uint8 announcement) +{ + MusicManager.PlayAnnouncement(announcement); +} + +void +cDMAudio::PlayFrontEndTrack(uint8 track, uint8 frontendFlag) +{ + MusicManager.PlayFrontEndTrack(track, frontendFlag); +} + +void +cDMAudio::StopFrontEndTrack(void) +{ + MusicManager.StopFrontEndTrack(); +} + +void +cDMAudio::ResetTimers(uint32 time) +{ + AudioManager.ResetTimers(time); +} + +void +cDMAudio::ChangeMusicMode(uint8 mode) +{ + MusicManager.ChangeMusicMode(mode); +} + +void +cDMAudio::PreloadCutSceneMusic(uint8 track) +{ + MusicManager.PreloadCutSceneMusic(track); +} + +void +cDMAudio::PlayPreloadedCutSceneMusic(void) +{ + MusicManager.PlayPreloadedCutSceneMusic(); +} + +void +cDMAudio::StopCutSceneMusic(void) +{ + MusicManager.StopCutSceneMusic(); +} + +void +cDMAudio::PreloadMissionAudio(char *missionAudio) +{ + AudioManager.PreloadMissionAudio(missionAudio); +} + +uint8 +cDMAudio::GetMissionAudioLoadingStatus(void) +{ + return AudioManager.GetMissionAudioLoadingStatus(); +} + +void +cDMAudio::SetMissionAudioLocation(float x, float y, float z) +{ + AudioManager.SetMissionAudioLocation(x, y, z); +} + +void +cDMAudio::PlayLoadedMissionAudio(void) +{ + AudioManager.PlayLoadedMissionAudio(); +} + +bool +cDMAudio::IsMissionAudioSampleFinished(void) +{ + return AudioManager.IsMissionAudioSampleFinished(); +} + +void +cDMAudio::ClearMissionAudio(void) +{ + AudioManager.ClearMissionAudio(); +} + +int32 +cDMAudio::GetRadioInCar(void) +{ + return MusicManager.GetRadioInCar(); +} + +void +cDMAudio::SetRadioInCar(uint32 radio) +{ + MusicManager.SetRadioInCar(radio); +} + +void +cDMAudio::SetRadioChannel(int8 radio, int32 pos) +{ + MusicManager.SetRadioChannelByScript(radio, pos); +} + +STARTPATCHES + InjectHook(0x57C760, &cDMAudio::Initialise, PATCH_JUMP); + InjectHook(0x57C780, &cDMAudio::Terminate, PATCH_JUMP); + InjectHook(0x57C7A0, &cDMAudio::Service, PATCH_JUMP); + InjectHook(0x57C7C0, &cDMAudio::CreateEntity, PATCH_JUMP); + InjectHook(0x57C7F0, &cDMAudio::DestroyEntity, PATCH_JUMP); + InjectHook(0x57C810, &cDMAudio::SetEntityStatus, PATCH_JUMP); + InjectHook(0x57C840, &cDMAudio::PlayOneShot, PATCH_JUMP); + InjectHook(0x57C870, &cDMAudio::DestroyAllGameCreatedEntities, PATCH_JUMP); + InjectHook(0x57C890, &cDMAudio::SetEffectsMasterVolume, PATCH_JUMP); + InjectHook(0x57C8C0, &cDMAudio::SetMusicMasterVolume, PATCH_JUMP); + InjectHook(0x57C8F0, &cDMAudio::SetEffectsFadeVol, PATCH_JUMP); + InjectHook(0x57C920, &cDMAudio::SetMusicFadeVol, PATCH_JUMP); + InjectHook(0x57C950, &cDMAudio::GetNum3DProvidersAvailable, PATCH_JUMP); + InjectHook(0x57C970, &cDMAudio::Get3DProviderName, PATCH_JUMP); + InjectHook(0x57C990, &cDMAudio::GetCurrent3DProviderIndex, PATCH_JUMP); + InjectHook(0x57C9B0, &cDMAudio::SetCurrent3DProvider, PATCH_JUMP); + InjectHook(0x57C9D0, &cDMAudio::SetSpeakerConfig, PATCH_JUMP); + InjectHook(0x57C9F0, &cDMAudio::IsMP3RadioChannelAvailable, PATCH_JUMP); + InjectHook(0x57CA10, &cDMAudio::ReleaseDigitalHandle, PATCH_JUMP); + InjectHook(0x57CA30, &cDMAudio::ReacquireDigitalHandle, PATCH_JUMP); + InjectHook(0x57CA50, &cDMAudio::SetDynamicAcousticModelingStatus, PATCH_JUMP); + InjectHook(0x57CA70, &cDMAudio::CheckForAnAudioFileOnCD, PATCH_JUMP); + InjectHook(0x57CA90, &cDMAudio::GetCDAudioDriveLetter, PATCH_JUMP); + InjectHook(0x57CAB0, &cDMAudio::IsAudioInitialised, PATCH_JUMP); + InjectHook(0x57CAD0, &cDMAudio::ReportCrime, PATCH_JUMP); + InjectHook(0x57CB00, &cDMAudio::CreateLoopingScriptObject, PATCH_JUMP); + InjectHook(0x57CB40, &cDMAudio::DestroyLoopingScriptObject, PATCH_JUMP); + InjectHook(0x57CB60, &cDMAudio::CreateOneShotScriptObject, PATCH_JUMP); + InjectHook(0x57CBB0, &cDMAudio::PlaySuspectLastSeen, PATCH_JUMP); + InjectHook(0x57CBE0, &cDMAudio::ReportCollision, PATCH_JUMP); + InjectHook(0x57CC20, &cDMAudio::PlayFrontEndSound, PATCH_JUMP); + InjectHook(0x57CC60, &cDMAudio::PlayRadioAnnouncement, PATCH_JUMP); + InjectHook(0x57CC80, &cDMAudio::PlayFrontEndTrack, PATCH_JUMP); + InjectHook(0x57CCB0, &cDMAudio::StopFrontEndTrack, PATCH_JUMP); + InjectHook(0x57CCD0, &cDMAudio::ResetTimers, PATCH_JUMP); + InjectHook(0x57CCF0, &cDMAudio::ChangeMusicMode, PATCH_JUMP); + InjectHook(0x57CD10, &cDMAudio::PreloadCutSceneMusic, PATCH_JUMP); + InjectHook(0x57CD30, &cDMAudio::PlayPreloadedCutSceneMusic, PATCH_JUMP); + InjectHook(0x57CD50, &cDMAudio::StopCutSceneMusic, PATCH_JUMP); + InjectHook(0x57CD70, &cDMAudio::PreloadMissionAudio, PATCH_JUMP); + InjectHook(0x57CD90, &cDMAudio::GetMissionAudioLoadingStatus, PATCH_JUMP); + InjectHook(0x57CDB0, &cDMAudio::SetMissionAudioLocation, PATCH_JUMP); + InjectHook(0x57CDE0, &cDMAudio::PlayLoadedMissionAudio, PATCH_JUMP); + InjectHook(0x57CE00, &cDMAudio::IsMissionAudioSampleFinished, PATCH_JUMP); + InjectHook(0x57CE20, &cDMAudio::ClearMissionAudio, PATCH_JUMP); + InjectHook(0x57CE40, &cDMAudio::GetRadioInCar, PATCH_JUMP); + InjectHook(0x57CE60, &cDMAudio::SetRadioInCar, PATCH_JUMP); + InjectHook(0x57CE80, &cDMAudio::SetRadioChannel, PATCH_JUMP); + + //InjectHook(0x57CEB0, `global constructor keyed to'dmaudio.cpp, PATCH_JUMP); + //InjectHook(0x57CED0, cDMAudio::~cDMAudio, PATCH_JUMP); +ENDPATCHES diff --git a/src/audio/DMAudio.h b/src/audio/DMAudio.h index 09daea5c..318b9947 100644 --- a/src/audio/DMAudio.h +++ b/src/audio/DMAudio.h @@ -1,5 +1,4 @@ #pragma once - enum eSound : int16 { SOUND_CAR_DOOR_CLOSE_BONNET = 0, @@ -172,43 +171,84 @@ enum eSound : int16 SOUND_TOTAL_PED_SOUNDS = 167, }; +class cAudioScriptObject; class CEntity; enum eCrimeType; -struct cAudioScriptObject; +enum eAudioType; class cDMAudio { public: + ~cDMAudio() + { } + + void Initialise(void); void Terminate(void); + void Service(void); + + int32 CreateEntity(eAudioType type, void *UID); + void DestroyEntity(int32 audioEntity); + void SetEntityStatus(int32 audioEntity, uint8 status); + void PlayOneShot(int32 audioEntity, uint16 oneShot, float volume); + void DestroyAllGameCreatedEntities(void); + + void SetEffectsMasterVolume(uint8 volume); + void SetMusicMasterVolume(uint8 volume); + void SetEffectsFadeVol(uint8 volume); + void SetMusicFadeVol(uint8 volume); + + uint8 GetNum3DProvidersAvailable(void); + char *Get3DProviderName(uint8 id); + + int8 GetCurrent3DProviderIndex(void); + int8 SetCurrent3DProvider(uint8 which); + + void SetSpeakerConfig(int32 config); + + bool IsMP3RadioChannelAvailable(void); + void ReleaseDigitalHandle(void); void ReacquireDigitalHandle(void); - void Service(void); - void ReportCollision(CEntity* A, CEntity* B, uint8 surfA, uint8 surfB, float impulse, float speed); - void ResetTimers(uint32 timerval); - bool IsAudioInitialised(void); - char GetCDAudioDriveLetter(void); + + void SetDynamicAcousticModelingStatus(uint8 status); + bool CheckForAnAudioFileOnCD(void); + + char GetCDAudioDriveLetter(void); + bool IsAudioInitialised(void); + + void ReportCrime(eCrimeType crime, CVector const &pos); + + int32 CreateLoopingScriptObject(cAudioScriptObject *scriptObject); + void DestroyLoopingScriptObject(int32 audioEntity); + void CreateOneShotScriptObject(cAudioScriptObject *scriptObject); + + void PlaySuspectLastSeen(float x, float y, float z); + + void ReportCollision(CEntity *entityA, CEntity *entityB, uint8 surfaceTypeA, uint8 surfaceTypeB, float collisionPower, float velocity); + + void PlayFrontEndSound(uint16 frontend, uint32 volume); + void PlayRadioAnnouncement(uint8 announcement); + void PlayFrontEndTrack(uint8 track, uint8 frontendFlag); + void StopFrontEndTrack(void); + + void ResetTimers(uint32 time); + void ChangeMusicMode(uint8 mode); - void PlayFrontEndSound(uint32, uint32); - void PlayFrontEndTrack(uint32, uint32); - void StopFrontEndTrack(); - void PlayOneShot(int32 audioentity, uint16 sound/*eSound*/, float); - void SetMusicMasterVolume(uint8); - void SetEffectsMasterVolume(uint8); - uint8 SetCurrent3DProvider(uint8); - int32 SetSpeakerConfig(int32); - int32 GetRadioInCar(void); - void SetEffectsFadeVol(uint8); - void SetMusicFadeVol(uint8); - int32 CreateEntity(int, void*); - void SetEntityStatus(int32 id, uint8 enable); - void SetRadioInCar(int32); - uint8 IsMP3RadioChannelAvailable(); - void DestroyEntity(int32); + + void PreloadCutSceneMusic(uint8 track); + void PlayPreloadedCutSceneMusic(void); + void StopCutSceneMusic(void); + + void PreloadMissionAudio(char *missionAudio); + uint8 GetMissionAudioLoadingStatus(void); + void SetMissionAudioLocation(float x, float y, float z); + void PlayLoadedMissionAudio(void); + bool IsMissionAudioSampleFinished(void); void ClearMissionAudio(void); - void ReportCrime(eCrimeType crime, const CVector &pos); - void CreateOneShotScriptObject(cAudioScriptObject*); - int32 CreateLoopingScriptObject(cAudioScriptObject*); - void DestroyLoopingScriptObject(int32); + + int32 GetRadioInCar(void); + void SetRadioInCar(uint32 radio); + void SetRadioChannel(int8 radio, int32 pos); }; extern cDMAudio &DMAudio; diff --git a/src/audio/MusicManager.cpp b/src/audio/MusicManager.cpp index 0700ee63..ce554ab4 100644 --- a/src/audio/MusicManager.cpp +++ b/src/audio/MusicManager.cpp @@ -202,3 +202,44 @@ cMusicManager::StopFrontEndTrack() { EAXJMP(0x57E3D0); } + + +WRAPPER void cMusicManager::PlayAnnouncement(unsigned char) +{ + EAXJMP(0x57E430); +} + +WRAPPER void cMusicManager::PlayFrontEndTrack(unsigned char, unsigned char) +{ + EAXJMP(0x57E2E0); +} + +WRAPPER void cMusicManager::PreloadCutSceneMusic(unsigned char) +{ + EAXJMP(0x57E210); +} + +WRAPPER void cMusicManager::PlayPreloadedCutSceneMusic(void) +{ + EAXJMP(0x57E290); +} + +WRAPPER void cMusicManager::StopCutSceneMusic(void) +{ + EAXJMP(0x57E2B0); +} + +WRAPPER int32 cMusicManager::GetRadioInCar(void) +{ + EAXJMP(0x57D1D0); +} + +WRAPPER void cMusicManager::SetRadioInCar(unsigned int) +{ + EAXJMP(0x57D2C0); +} + +WRAPPER void cMusicManager::SetRadioChannelByScript(unsigned char, int) +{ + EAXJMP(0x57D180); +}
\ No newline at end of file diff --git a/src/audio/MusicManager.h b/src/audio/MusicManager.h index cdea65ec..f20424a8 100644 --- a/src/audio/MusicManager.h +++ b/src/audio/MusicManager.h @@ -286,6 +286,15 @@ public: char *Get3DProviderName(char); bool PlayerInCar(); void DisplayRadioStationName(); + + void PlayAnnouncement(unsigned char); + void PlayFrontEndTrack(unsigned char, unsigned char); + void PreloadCutSceneMusic(unsigned char); + void PlayPreloadedCutSceneMusic(void); + void StopCutSceneMusic(void); + int32 GetRadioInCar(void); + void SetRadioInCar(unsigned int); + void SetRadioChannelByScript(unsigned char, int); }; static_assert(sizeof(cMusicManager) == 0x95C, "cMusicManager: error"); diff --git a/src/audio/sampman.cpp b/src/audio/sampman.cpp index c758fc9f..de222493 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)[2] = *(int32 (*)[2])*(int *)0x6FAB70; +int32 (&BankStartOffset)[MAX_SAMPLEBANKS] = *(int32 (*)[MAX_SAMPLEBANKS])*(int *)0x6FAB70; /////////////////////////////////////////////////////////////// @@ -289,7 +289,7 @@ cSampleManager::SetSpeakerConfig(int32 which) } uint32 -cSampleManager::GetMaximumSupportedChannels(void) //[Y] +cSampleManager::GetMaximumSupportedChannels(void) { if ( _maxSamples > MAXCHANNELS ) return MAXCHANNELS; @@ -857,10 +857,10 @@ cSampleManager::Initialise(void) m_aSamples[i].nLoopEnd = -1; } - m_nEffectsVolume = 127; - m_nMusicVolume = 127; - m_nEffectsFadeVolume = 127; - m_nMusicFadeVolume = 127; + m_nEffectsVolume = MAX_VOLUME; + m_nMusicVolume = MAX_VOLUME; + m_nEffectsFadeVolume = MAX_VOLUME; + m_nMusicFadeVolume = MAX_VOLUME; m_nMonoMode = 0; } @@ -946,14 +946,14 @@ cSampleManager::Initialise(void) return false; } - nSampleBankMemoryStartAddress[0] = (int32)AIL_mem_alloc_lock(nSampleBankSize[0]); - if ( !nSampleBankMemoryStartAddress[0] ) + nSampleBankMemoryStartAddress[SAMPLEBANK_MAIN] = (int32)AIL_mem_alloc_lock(nSampleBankSize[SAMPLEBANK_MAIN]); + if ( !nSampleBankMemoryStartAddress[SAMPLEBANK_MAIN] ) { Terminate(); return false; } - nSampleBankMemoryStartAddress[1] = (int32)AIL_mem_alloc_lock(PED_BLOCKSIZE*MAX_PEDSFX); + nSampleBankMemoryStartAddress[SAMPLEBANK_PED] = (int32)AIL_mem_alloc_lock(PED_BLOCKSIZE*MAX_PEDSFX); } @@ -1159,7 +1159,7 @@ cSampleManager::Initialise(void) TRACE("bank"); - LoadSampleBank(0); + LoadSampleBank(SAMPLEBANK_MAIN); // mp3 TRACE("mp3"); @@ -1188,13 +1188,13 @@ cSampleManager::Initialise(void) bUseRandomTable = true; else { - bUseRandomTable = 0; + bUseRandomTable = false; localtm = localtime(&t); } int32 randval; if ( bUseRandomTable ) - randval = AudioManager.GetRandomTabe(1); + randval = AudioManager.GetRandomNumber(1); else randval = localtm->tm_sec * localtm->tm_min; @@ -1205,16 +1205,16 @@ cSampleManager::Initialise(void) randmp3 = randmp3->pNext; if ( bUseRandomTable ) - _CurMP3Pos = AudioManager.GetRandomTabe(0) % randmp3->nTrackLength; + _CurMP3Pos = AudioManager.GetRandomNumber(0) % randmp3->nTrackLength; else { if ( localtm->tm_sec > 0 ) { int32 s = localtm->tm_sec; - _CurMP3Pos = s*s*s*s*s*s*s*s % randmp3->nTrackLength; + _CurMP3Pos = s*s*s*s*s*s*s*s % randmp3->nTrackLength; } else - _CurMP3Pos = AudioManager.GetRandomTabe(0) % randmp3->nTrackLength; + _CurMP3Pos = AudioManager.GetRandomNumber(0) % randmp3->nTrackLength; } } else @@ -1254,16 +1254,16 @@ cSampleManager::Terminate(void) _DeleteMP3Entries(); - if ( nSampleBankMemoryStartAddress[0] != 0 ) + if ( nSampleBankMemoryStartAddress[SAMPLEBANK_MAIN] != 0 ) { - AIL_mem_free_lock((void *)nSampleBankMemoryStartAddress[0]); - nSampleBankMemoryStartAddress[0] = 0; + AIL_mem_free_lock((void *)nSampleBankMemoryStartAddress[SAMPLEBANK_MAIN]); + nSampleBankMemoryStartAddress[SAMPLEBANK_MAIN] = 0; } - if ( nSampleBankMemoryStartAddress[1] != 0 ) + if ( nSampleBankMemoryStartAddress[SAMPLEBANK_PED] != 0 ) { - AIL_mem_free_lock((void *)nSampleBankMemoryStartAddress[1]); - nSampleBankMemoryStartAddress[1] = 0; + AIL_mem_free_lock((void *)nSampleBankMemoryStartAddress[SAMPLEBANK_PED]); + nSampleBankMemoryStartAddress[SAMPLEBANK_PED] = 0; } if ( DIG ) @@ -1293,7 +1293,7 @@ cSampleManager::CheckForAnAudioFileOnCD(void) strcpy(filepath, m_szCDRomRootPath); #endif // #if defined(GTA3_1_1_PATCH) - strcat(filepath, StreamedNameTable[AudioManager.GetRandomTabe(1) % TOTAL_STREAMED_SOUNDS]); + strcat(filepath, StreamedNameTable[AudioManager.GetRandomNumber(1) % TOTAL_STREAMED_SOUNDS]); FILE *f = fopen(filepath, "rb"); @@ -1407,7 +1407,7 @@ cSampleManager::LoadSampleBank(uint8 nBank) if ( MusicManager.IsInitialised() && MusicManager.GetMusicMode() == MUSICMODE_CUTSCENE - && nBank != 0 ) + && nBank != SAMPLEBANK_MAIN ) { return false; } @@ -1496,10 +1496,10 @@ cSampleManager::LoadPedComment(uint32 nComment) if ( fseek(fpSampleDataHandle, m_aSamples[nComment].nOffset, SEEK_SET) != 0 ) return false; - if ( fread((void *)(nSampleBankMemoryStartAddress[1] + PED_BLOCKSIZE*nCurrentPedSlot), 1, m_aSamples[nComment].nSize, fpSampleDataHandle) != m_aSamples[nComment].nSize ) + if ( fread((void *)(nSampleBankMemoryStartAddress[SAMPLEBANK_PED] + PED_BLOCKSIZE*nCurrentPedSlot), 1, m_aSamples[nComment].nSize, fpSampleDataHandle) != m_aSamples[nComment].nSize ) return false; - nPedSlotSfxAddr[nCurrentPedSlot] = nSampleBankMemoryStartAddress[1] + PED_BLOCKSIZE*nCurrentPedSlot; + nPedSlotSfxAddr[nCurrentPedSlot] = nSampleBankMemoryStartAddress[SAMPLEBANK_PED] + PED_BLOCKSIZE*nCurrentPedSlot; nPedSlotSfx [nCurrentPedSlot] = nComment; if ( ++nCurrentPedSlot >= MAX_PEDSFX ) @@ -1706,7 +1706,7 @@ void cSampleManager::SetChannelEmittingVolume(uint32 nChannel, uint32 nVolume) { uint32 vol = nVolume; - if ( vol > 127 ) vol = 127; + if ( vol > MAX_VOLUME ) vol = MAX_VOLUME; nChannelVolume[nChannel] = vol; @@ -1741,7 +1741,7 @@ void cSampleManager::SetChannelVolume(uint32 nChannel, uint32 nVolume) { uint32 vol = nVolume; - if ( vol > 127 ) vol = 127; + if ( vol > MAX_VOLUME ) vol = MAX_VOLUME; switch ( nChannel ) { @@ -2181,8 +2181,8 @@ cSampleManager::SetStreamedVolumeAndPan(uint8 nVolume, uint8 nPan, uint8 nEffect if ( m_bInitialised ) { - if ( vol > 127 ) vol = 127; - if ( vol > 127 ) vol = 127; + if ( vol > MAX_VOLUME ) vol = MAX_VOLUME; + if ( vol > MAX_VOLUME ) vol = MAX_VOLUME; nStreamVolume[nStream] = vol; nStreamPan[nStream] = nPan; @@ -2228,7 +2228,7 @@ cSampleManager::IsStreamPlaying(uint8 nStream) bool cSampleManager::InitialiseSampleBanks(void) { - int32 nBank = 0; + int32 nBank = SAMPLEBANK_MAIN; fpSampleDescHandle = fopen(SampleBankDescFilename, "rb"); if ( fpSampleDescHandle == NULL ) @@ -2261,8 +2261,8 @@ cSampleManager::InitialiseSampleBanks(void) } } - nSampleBankSize[0] = nSampleBankDiscStartOffset[1] - nSampleBankDiscStartOffset[0]; - nSampleBankSize[1] = _nSampleDataEndOffset - nSampleBankDiscStartOffset[1]; + nSampleBankSize[SAMPLEBANK_MAIN] = nSampleBankDiscStartOffset[SAMPLEBANK_PED] - nSampleBankDiscStartOffset[SAMPLEBANK_MAIN]; + nSampleBankSize[SAMPLEBANK_PED] = _nSampleDataEndOffset - nSampleBankDiscStartOffset[SAMPLEBANK_PED]; return true; } diff --git a/src/audio/sampman.h b/src/audio/sampman.h index ba2381b5..def4853f 100644 --- a/src/audio/sampman.h +++ b/src/audio/sampman.h @@ -2,6 +2,8 @@ #include "common.h" #include "AudioSamples.h" +#define MAX_VOLUME 127 + struct tSample { int32 nOffset; uint32 nSize; @@ -10,30 +12,31 @@ struct tSample { int32 nLoopEnd; }; -#define MAXPROVIDERS 64 - -#define MAXCHANNELS 28 -#define MAXCHANNELS_SURROUND 24 -#define MAX2DCHANNELS 1 -#define CHANNEL2D MAXCHANNELS +enum +{ + SAMPLEBANK_MAIN, + SAMPLEBANK_PED, + MAX_SAMPLEBANKS, +}; +#define MAX_PEDSFX 7 +#define PED_BLOCKSIZE 79000 -#define MAX_MP3STREAMS 2 +#define MAXPROVIDERS 64 +#define MAXCHANNELS 28 +#define MAXCHANNELS_SURROUND 24 +#define MAX2DCHANNELS 1 +#define CHANNEL2D MAXCHANNELS -#define MAX_SAMPLEBANKS 2 -#define MAX_PEDSFX 7 -#define PED_BLOCKSIZE 79000 +#define MAX_MP3STREAMS 2 +#define DIGITALRATE 32000 +#define DIGITALBITS 16 +#define DIGITALCHANNELS 2 #define MAX_DIGITAL_MIXER_CHANNELS 32 -#define DIGITALRATE 32000 -#define DIGITALBITS 16 -#define DIGITALCHANNELS 2 - - - class cSampleManager { uint8 m_nEffectsVolume; @@ -98,7 +101,7 @@ public: int32 _GetPedCommentSlot(uint32 nComment); - int32 GetSampleBaseFrequency (uint32 nSample); + int32 GetSampleBaseFrequency (uint32 nSample); int32 GetSampleLoopStartOffset(uint32 nSample); int32 GetSampleLoopEndOffset (uint32 nSample); uint32 GetSampleLength (uint32 nSample); diff --git a/src/control/CarCtrl.cpp b/src/control/CarCtrl.cpp index 064eab98..2609f8ca 100644 --- a/src/control/CarCtrl.cpp +++ b/src/control/CarCtrl.cpp @@ -63,6 +63,7 @@ WRAPPER void CCarCtrl::GenerateEmergencyServicesCar(void) { EAXJMP(0x41FC50); } WRAPPER void CCarCtrl::PickNextNodeAccordingStrategy(CVehicle*) { EAXJMP(0x41BA50); } WRAPPER void CCarCtrl::DragCarToPoint(CVehicle*, CVector*) { EAXJMP(0x41D450); } WRAPPER void CCarCtrl::SlowCarDownForCarsSectorList(CPtrList&, CVehicle*, float, float, float, float, float*, float) { EAXJMP(0x419B40); } +WRAPPER void CCarCtrl::Init(void) { EAXJMP(0x41D280); } void CCarCtrl::GenerateRandomCars() diff --git a/src/control/CarCtrl.h b/src/control/CarCtrl.h index 735dc89c..b28e6889 100644 --- a/src/control/CarCtrl.h +++ b/src/control/CarCtrl.h @@ -61,7 +61,7 @@ public: static float FindMaximumSpeedForThisCarInTraffic(CVehicle*); static void SlowCarDownForCarsSectorList(CPtrList&, CVehicle*, float, float, float, float, float*, float); static void SlowCarDownForPedsSectorList(CPtrList&, CVehicle*, float, float, float, float, float*, float); - + static void Init(void); static float GetOffsetOfLaneFromCenterOfRoad(int8 lane, CCarPathLink* pLink) { diff --git a/src/control/Replay.cpp b/src/control/Replay.cpp index 1e77da3a..12636d32 100644 --- a/src/control/Replay.cpp +++ b/src/control/Replay.cpp @@ -1166,7 +1166,7 @@ void CReplay::RestoreStuffFromMem(void) ped->m_modelIndex = -1; ped->SetModelIndex(mi); ped->m_pVehicleAnim = 0; - ped->m_audioEntityId = DMAudio.CreateEntity(0, ped); + ped->m_audioEntityId = DMAudio.CreateEntity(AUDIOTYPE_PHYSICAL, ped); DMAudio.SetEntityStatus(ped->m_audioEntityId, true); CPopulation::UpdatePedCount(ped->m_nPedType, false); if (ped->m_wepModelID >= 0) @@ -1204,7 +1204,7 @@ void CReplay::RestoreStuffFromMem(void) car->SetDoorDamage(CAR_DOOR_LR, DOOR_REAR_LEFT, true); car->SetDoorDamage(CAR_DOOR_RR, DOOR_REAR_RIGHT, true); } - vehicle->m_audioEntityId = DMAudio.CreateEntity(0, vehicle); + vehicle->m_audioEntityId = DMAudio.CreateEntity(AUDIOTYPE_PHYSICAL, vehicle); DMAudio.SetEntityStatus(vehicle->m_audioEntityId, true); CCarCtrl::UpdateCarCount(vehicle, false); if ((mi == MI_AIRTRAIN || mi == MI_DEADDODO) && vehicle->m_rwObject){ diff --git a/src/control/Script.cpp b/src/control/Script.cpp index c3c3a154..c81cd050 100644 --- a/src/control/Script.cpp +++ b/src/control/Script.cpp @@ -3494,9 +3494,9 @@ int8 CRunningScript::ProcessCommandsFrom300To399(int32 command) break; } cAudioScriptObject* obj = new cAudioScriptObject(); - obj->m_vecPos = *(CVector*)&ScriptParams[0]; - obj->m_wSound = ScriptParams[3]; - obj->m_nAudioEntityId = -5; + obj->Posn = *(CVector*)&ScriptParams[0]; + obj->AudioId = ScriptParams[3]; + obj->AudioEntity = AEHANDLE_NONE; /* BUG: if audio is not initialized, this object will not be freed. */ /* Issue needs to be addressed in CreateOneShotScriptObject. */ DMAudio.CreateOneShotScriptObject(obj); @@ -3506,9 +3506,9 @@ int8 CRunningScript::ProcessCommandsFrom300To399(int32 command) { CollectParameters(&m_nIp, 4); cAudioScriptObject* obj = new cAudioScriptObject(); - obj->m_vecPos = *(CVector*)&ScriptParams[0]; - obj->m_wSound = ScriptParams[3]; - obj->m_nAudioEntityId = DMAudio.CreateLoopingScriptObject(obj); + obj->Posn = *(CVector*)&ScriptParams[0]; + obj->AudioId = ScriptParams[3]; + obj->AudioEntity = DMAudio.CreateLoopingScriptObject(obj); ScriptParams[0] = CPools::GetAudioScriptObjectPool()->GetIndex(obj); StoreParameters(&m_nIp, 1); return 0; @@ -3521,7 +3521,7 @@ int8 CRunningScript::ProcessCommandsFrom300To399(int32 command) debug("REMOVE_SOUND - Sound doesn't exist\n"); return 0; } - DMAudio.DestroyLoopingScriptObject(obj->m_nAudioEntityId); + DMAudio.DestroyLoopingScriptObject(obj->AudioEntity); delete obj; return 0; } diff --git a/src/core/AnimViewer.cpp b/src/core/AnimViewer.cpp new file mode 100644 index 00000000..30773889 --- /dev/null +++ b/src/core/AnimViewer.cpp @@ -0,0 +1,381 @@ +#include "common.h" +#include "patcher.h" +#include "Font.h" +#include "Pad.h" +#include "Text.h" +#include "main.h" +#include "Timer.h" +#include "DMAudio.h" +#include "FileMgr.h" +#include "Streaming.h" +#include "TxdStore.h" +#include "General.h" +#include "Camera.h" +#include "Vehicle.h" +#include "PlayerSkin.h" +#include "PlayerInfo.h" +#include "World.h" +#include "Renderer.h" +#include "AnimManager.h" +#include "AnimViewer.h" +#include "PlayerPed.h" +#include "Pools.h" +#include "References.h" +#include "PathFind.h" +#include "HandlingMgr.h" +#include "TempColModels.h" +#include "Particle.h" +#include "CdStream.h" +#include "Messages.h" +#include "CarCtrl.h" +#include "FileLoader.h" +#include "ModelIndices.h" +#include "Clock.h" +#include "Timecycle.h" +#include "RpAnimBlend.h" +#include "Shadows.h" + +int CAnimViewer::animTxdSlot = 0; +CEntity *CAnimViewer::pTarget = nil; + +void +CAnimViewer::Render(void) { + if (pTarget) { +// pTarget->GetPosition() = CVector(0.0f, 0.0f, 0.0f); + if (pTarget) { + pTarget->Render(); + CRenderer::RenderOneNonRoad(pTarget); + } + } +} + +void +CAnimViewer::Initialise(void) { + LoadingScreen("Loading the ModelViewer", "", GetRandomSplashScreen()); + animTxdSlot = CTxdStore::AddTxdSlot("generic"); + CTxdStore::Create(animTxdSlot); + int hudSlot = CTxdStore::AddTxdSlot("hud"); + CTxdStore::LoadTxd(hudSlot, "MODELS/HUD.TXD"); + int particleSlot = CTxdStore::AddTxdSlot("particle"); + CTxdStore::LoadTxd(particleSlot, "MODELS/PARTICLE.TXD"); + CTxdStore::SetCurrentTxd(animTxdSlot); + CPools::Initialise(); + CReferences::Init(); + TheCamera.Init(); + TheCamera.SetRwCamera(Scene.camera); + + // I didn't get which camera og code selects. + for (int i = 0; i < 3; i++) { + TheCamera.Cams[i].Distance = 5.0f; + } + + gbModelViewer = true; + + ThePaths.Init(); + ThePaths.AllocatePathFindInfoMem(4500); + CCollision::Init(); + CWorld::Initialise(); + mod_HandlingManager.Initialise(); + CTempColModels::Initialise(); + CAnimManager::Initialise(); + CModelInfo::Initialise(); + CParticle::Initialise(); + CCarCtrl::Init(); + CPedStats::Initialise(); + CMessages::Init(); + CdStreamAddImage("MODELS\\GTA3.IMG"); + CFileLoader::LoadLevel("DATA\\ANIMVIEWER.DAT"); + CStreaming::Init(); + CStreaming::LoadInitialPeds(); + CStreaming::RequestSpecialModel(MI_PLAYER, "player", STREAMFLAGS_DONT_REMOVE); + CStreaming::LoadAllRequestedModels(false); + CRenderer::Init(); + CVehicleModelInfo::LoadVehicleColours(); + CAnimManager::LoadAnimFiles(); + CWorld::PlayerInFocus = 0; + CWeapon::InitialiseWeapons(); + CShadows::Init(); + CPed::Initialise(); + CTimer::Initialise(); + CClock::Initialise(60000); + CTimeCycle::Initialise(); + CCarCtrl::Init(); + CPlayerPed *player = new CPlayerPed(); + player->GetPosition() = CVector(0.0f, 0.0f, 0.0f); + CWorld::Players[0].m_pPed = player; + CDraw::SetFOV(120.0f); + CDraw::ms_fLODDistance = 500.0f; + + int fd = CFileMgr::OpenFile("DATA\\SPECIAL.TXT", "r"); + char animGroup[32], modelName[32]; + if (fd) { + for (int lineId = 0; lineId < NUM_OF_SPECIAL_CHARS; lineId++) { + if (!CFileMgr::ReadLine(fd, gString, 255)) + break; + + sscanf(gString, "%s %s", &modelName, &animGroup); + int groupId; + for (groupId = 0; groupId < NUM_ANIM_ASSOC_GROUPS; groupId++) { + if (!strcmp(animGroup, CAnimManager::GetAnimGroupName((AssocGroupId)groupId))) + break; + } + + if (groupId != NUM_ANIM_ASSOC_GROUPS) + ((CPedModelInfo*)CModelInfo::GetModelInfo(MI_SPECIAL01 + lineId))->m_animGroup = groupId; + + CStreaming::RequestSpecialChar(lineId, modelName, STREAMFLAGS_DONT_REMOVE); + } + CFileMgr::CloseFile(fd); + } else { + // From xbox + CStreaming::RequestSpecialChar(0, "luigi", STREAMFLAGS_DONT_REMOVE); + CStreaming::RequestSpecialChar(1, "joey", STREAMFLAGS_DONT_REMOVE); + CStreaming::RequestSpecialChar(2, "tony", STREAMFLAGS_DONT_REMOVE); + CStreaming::RequestSpecialChar(3, "curly", STREAMFLAGS_DONT_REMOVE); + } +} + +int +LastPedModelId(int modelId) +{ + CBaseModelInfo *model; + for (int i = modelId; i >= 0; i--) { + model = CModelInfo::GetModelInfo(i); + if (model->m_type == MITYPE_PED) + return i; + } + return modelId; +} + +int +LastVehicleModelId(int modelId) +{ + CBaseModelInfo* model; + for (int i = modelId; i >= 0; i--) { + model = CModelInfo::GetModelInfo(i); + if (model->m_type == MITYPE_VEHICLE) + return i; + } + return modelId; +} + + +// It's me that named this. +int +FindMeAModelID(int modelId, int wantedChange) +{ + // Max. 2 trials wasn't here, it's me that added it. + + int tryCount = 2; + int ogModelId = modelId; + + while(tryCount != 0) { + modelId += wantedChange; + if (modelId < 0 || modelId >= MODELINFOSIZE) { + tryCount--; + wantedChange = -wantedChange; + } else if (modelId != 5 && modelId != 6 && modelId != 405) { + CBaseModelInfo *model = CModelInfo::GetModelInfo(modelId); + if (model) + { + //int type = model->m_type; + return modelId; + } + } + } + return ogModelId; +} + +void +PlayAnimation(RpClump *clump, AssocGroupId animGroup, AnimationId anim) +{ + CAnimBlendAssociation *currentAssoc = RpAnimBlendClumpGetAssociation(clump, anim); + + if (currentAssoc && currentAssoc->IsPartial()) + delete currentAssoc; + + RpAnimBlendClumpSetBlendDeltas(clump, ASSOC_PARTIAL, -8.0f); + + CAnimBlendAssociation *animAssoc = CAnimManager::BlendAnimation(clump, animGroup, anim, 8.0f); + animAssoc->flags |= ASSOC_DELETEFADEDOUT; + animAssoc->SetCurrentTime(0.0f); + animAssoc->SetRun(); +} + +void +CAnimViewer::Update(void) +{ + static int modelId = 0; + static int animId = 0; + // Please don't make this bool, static bool's are problematic on my side. + static int reloadIFP = 0; + + AssocGroupId animGroup = ASSOCGRP_STD; + int nextModelId = modelId; + CBaseModelInfo *modelInfo = CModelInfo::GetModelInfo(modelId); + CEntity *newEntity = nil; + + if (modelInfo->m_type == MITYPE_PED) { + int animGroup = ((CPedModelInfo*)modelInfo)->m_animGroup; + + if (animId > ANIM_IDLE_STANCE) + animGroup = ASSOCGRP_STD; + + if (reloadIFP) { + if (pTarget) { + CWorld::Remove(pTarget); + if (pTarget) + delete pTarget; + } + pTarget = nil; + + // These calls were inside of LoadIFP function. + CAnimManager::Shutdown(); + CAnimManager::Initialise(); + CAnimManager::LoadAnimFiles(); + + reloadIFP = 0; + } + } else { + animGroup = ASSOCGRP_STD; + } + CPad::UpdatePads(); + CPad* pad = CPad::GetPad(0); + CStreaming::UpdateForAnimViewer(); + CStreaming::RequestModel(modelId, 0); + if (CStreaming::HasModelLoaded(modelId)) { + + if (!pTarget) { + + if (modelInfo->m_type == MITYPE_VEHICLE) { + + CVehicleModelInfo* veh = (CVehicleModelInfo*)modelInfo; + if (veh->m_vehicleType != VEHICLE_TYPE_CAR) { + // Not ready yet +/* if (veh->m_vehicleType == VEHICLE_TYPE_BOAT) + { + v33 = (CBoat*)CVehicle::operator new((CVehicle*)0x488, v6); + CBoat::CBoat(v33, modelId, 1u); + newEntity = (int)v33; + pTarget = (int)v33; + } + else + { +*/ newEntity = pTarget = new CObject(modelId, true); + if (!modelInfo->GetColModel()) { + modelInfo->SetColModel(&CTempColModels::ms_colModelWheel1); + } +// } + } else { + newEntity = pTarget = new CAutomobile(modelId, RANDOM_VEHICLE); + newEntity->m_status = STATUS_ABANDONED; + } + newEntity->bIsStuck = true; + } else if (modelInfo->m_type == MITYPE_PED) { + pTarget = newEntity = new CPed(PEDTYPE_CIVMALE); + newEntity->SetModelIndex(modelId); + } else { + newEntity = pTarget = new CObject(modelId, true); + if (!modelInfo->GetColModel()) + { + modelInfo->SetColModel(&CTempColModels::ms_colModelWheel1); + } + newEntity->bIsStuck = true; + } + newEntity->GetPosition() = CVector(0.0f, 0.0f, 0.0f); + CWorld::Add(newEntity); + TheCamera.TakeControl(pTarget, 9, 2, 1); + } + if (pTarget->m_type == ENTITY_TYPE_VEHICLE || pTarget->m_type == ENTITY_TYPE_PED || pTarget->m_type == ENTITY_TYPE_OBJECT) { + ((CPhysical*)pTarget)->m_vecMoveSpeed = CVector(0.0f, 0.0f, 0.0f); + } + pTarget->GetPosition().z = 0.0f; + + if (modelInfo->m_type != MITYPE_PED) { + + if (modelInfo->m_type == MITYPE_VEHICLE) { + + if (pad->NewState.LeftShoulder1 && !pad->OldState.LeftShoulder1) { + nextModelId = LastPedModelId(modelId); + } else { + // Start in mobile + if (pad->NewState.Square && !pad->OldState.Square) + CVehicleModelInfo::LoadVehicleColours(); + } + } + } else { + ((CPed*)pTarget)->bKindaStayInSamePlace = true; + + // Triangle in mobile + if (pad->NewState.Square && !pad->OldState.Square) { + reloadIFP = 1; + + } else if (pad->NewState.Cross && !pad->OldState.Cross) { + PlayAnimation(pTarget->GetClump(), animGroup, (AnimationId)animId); + + } else if (pad->NewState.Circle && !pad->OldState.Circle) { + PlayAnimation(pTarget->GetClump(), animGroup, ANIM_IDLE_STANCE); + + } else if (pad->NewState.DPadUp && pad->OldState.DPadUp == 0) { + animId--; + if (animId < 0) { + animId = NUM_ANIMS - 1; + } + PlayAnimation(pTarget->GetClump(), animGroup, (AnimationId)animId); + + } else if (pad->NewState.DPadDown && !pad->OldState.DPadDown) { + animId = (animId == (NUM_ANIMS - 1) ? 0 : animId + 1); + PlayAnimation(pTarget->GetClump(), animGroup, (AnimationId)animId); + + } else { + if (pad->NewState.Start && !pad->OldState.Start) { + + } else { + if (pad->NewState.LeftShoulder1 && !pad->OldState.LeftShoulder1) { + nextModelId = LastVehicleModelId(modelId); + } else { +// if (CPad::GetPad(1)->NewState.LeftShoulder2) +// CPedModelInfo::AnimatePedColModelSkinned(CModelInfo::ms_modelInfoPtrs[(pTarget + 96)], pTarget->GetClump())); + } + } + } + } + } + + if (pad->NewState.DPadLeft && pad->OldState.DPadLeft == 0) { + nextModelId = FindMeAModelID(modelId, -1); + } else if (pad->NewState.DPadRight && pad->OldState.DPadRight == 0) { + nextModelId = FindMeAModelID(modelId, 1); + } + // There were extra codes here to let us change model id by 50, but xbox CPad struct is different, so I couldn't port. + + if (nextModelId != modelId) { + modelId = nextModelId; + if (pTarget) { + CWorld::Remove(pTarget); + if (pTarget) + delete pTarget; + } + pTarget = nil; + return; + } + + CTimeCycle::Update(); + CWorld::Process(); + if (pTarget) + TheCamera.Process(); +} + +void +CAnimViewer::Shutdown(void) +{ + if (CWorld::Players[0].m_pPed) + delete CWorld::Players[0].m_pPed; + + CWorld::ShutDown(); + CModelInfo::ShutDown(); + CAnimManager::Shutdown(); + CTimer::Shutdown(); + CStreaming::Shutdown(); + CTxdStore::RemoveTxdSlot(animTxdSlot); +}
\ No newline at end of file diff --git a/src/core/AnimViewer.h b/src/core/AnimViewer.h new file mode 100644 index 00000000..13dbb8fb --- /dev/null +++ b/src/core/AnimViewer.h @@ -0,0 +1,12 @@ +#pragma once + +class CAnimViewer { +public: + static int animTxdSlot; + static CEntity *pTarget; + + static void Initialise(); + static void Render(); + static void Shutdown(); + static void Update(); +};
\ No newline at end of file diff --git a/src/core/Camera.cpp b/src/core/Camera.cpp index f3582c67..cb16c3ad 100644 --- a/src/core/Camera.cpp +++ b/src/core/Camera.cpp @@ -27,7 +27,9 @@ WRAPPER void CamShakeNoPos(CCamera*, float) { EAXJMP(0x46B100); } WRAPPER void CCamera::TakeControl(CEntity*, int16, int16, int32) { EAXJMP(0x471500); } WRAPPER void CCamera::TakeControlNoEntity(const CVector&, int16, int32) { EAXJMP(0x4715B0); } WRAPPER void CCamera::SetCamPositionForFixedMode(const CVector&, const CVector&) { EAXJMP(0x46FCC0); } - +WRAPPER void CCamera::Init(void) { EAXJMP(0x46BAD0); } +WRAPPER void CCamera::SetRwCamera(RwCamera*) { EAXJMP(0x46FEC0); } +WRAPPER void CCamera::Process(void) { EAXJMP(0x46D3F0); } bool CCamera::GetFading() diff --git a/src/core/Camera.h b/src/core/Camera.h index 97ed79f4..c617c3d7 100644 --- a/src/core/Camera.h +++ b/src/core/Camera.h @@ -476,6 +476,10 @@ int m_iModeObbeCamIsInForCar; void SetCamPositionForFixedMode(const CVector&, const CVector&); bool GetFading(); + void Init(); + void SetRwCamera(RwCamera*); + void Process(); + void dtor(void) { this->CCamera::~CCamera(); } }; static_assert(offsetof(CCamera, m_WideScreenOn) == 0x70, "CCamera: error"); @@ -488,4 +492,4 @@ static_assert(offsetof(CCamera, Cams) == 0x1A4, "CCamera: error"); static_assert(sizeof(CCamera) == 0xE9D8, "CCamera: wrong size"); extern CCamera &TheCamera; -void CamShakeNoPos(CCamera*, float); +void CamShakeNoPos(CCamera*, float);
\ No newline at end of file diff --git a/src/core/Messages.cpp b/src/core/Messages.cpp index c6f3bc1b..b7b6a738 100644 --- a/src/core/Messages.cpp +++ b/src/core/Messages.cpp @@ -14,7 +14,7 @@ WRAPPER void CMessages::AddMessage(wchar* key, uint32 time, uint16 pos) { EAXJMP WRAPPER void CMessages::AddMessageJumpQ(wchar* key, uint32 time, uint16 pos) { EAXJMP(0x529A10); } WRAPPER void CMessages::AddMessageSoon(wchar* key, uint32 time, uint16 pos) { EAXJMP(0x529AF0); } WRAPPER void CMessages::ClearMessages() { EAXJMP(0x529CE0); } - +WRAPPER void CMessages::Init() { EAXJMP(0x529310); } tPreviousBrief *CMessages::PreviousBriefs = (tPreviousBrief *)0x713C08; tMessage *CMessages::BriefMessages = (tMessage *)0x8786E0; tBigMessage *CMessages::BIGMessages = (tBigMessage *)0x773628; diff --git a/src/core/Messages.h b/src/core/Messages.h index 51c36212..1cdcd3b7 100644 --- a/src/core/Messages.h +++ b/src/core/Messages.h @@ -46,4 +46,5 @@ public: static void AddMessageJumpQ(wchar* key, uint32 time, uint16 pos); static void AddMessageSoon(wchar* key, uint32 time, uint16 pos); static void ClearMessages(); + static void Init(); }; diff --git a/src/core/Pad.cpp b/src/core/Pad.cpp index 736e1e9d..f334a255 100644 --- a/src/core/Pad.cpp +++ b/src/core/Pad.cpp @@ -537,6 +537,12 @@ void CPad::AddToPCCheatString(char c) if (!_CHEATCMP("OORAGNAK")) KangarooCheat(); #endif + +#ifndef MASTER + // "PEDDEBUG" + if (!_CHEATCMP("GUBEDDEP")) + CPed::SwitchDebugDisplay(); +#endif #undef _CHEATCMP } diff --git a/src/core/Placeable.h b/src/core/Placeable.h index 648b315c..2df26a7c 100644 --- a/src/core/Placeable.h +++ b/src/core/Placeable.h @@ -25,4 +25,4 @@ public: bool IsWithinArea(float x1, float y1, float x2, float y2); bool IsWithinArea(float x1, float y1, float z1, float x2, float y2, float z2); }; -static_assert(sizeof(CPlaceable) == 0x4C, "CPlaceable: error"); +static_assert(sizeof(CPlaceable) == 0x4C, "CPlaceable: error");
\ No newline at end of file diff --git a/src/core/Pools.cpp b/src/core/Pools.cpp index 404cd558..a76bbb6d 100644 --- a/src/core/Pools.cpp +++ b/src/core/Pools.cpp @@ -1,4 +1,5 @@ #include "common.h" +#include "patcher.h" #include "Pools.h" CCPtrNodePool *&CPools::ms_pPtrNodePool = *(CCPtrNodePool**)0x943044; @@ -11,6 +12,9 @@ CObjectPool *&CPools::ms_pObjectPool = *(CObjectPool**)0x880E28; CDummyPool *&CPools::ms_pDummyPool = *(CDummyPool**)0x8F2C18; CAudioScriptObjectPool *&CPools::ms_pAudioScriptObjectPool = *(CAudioScriptObjectPool**)0x8F1B6C; +WRAPPER void CPools::Initialise(void) { EAXJMP(0x4A1770); } + +#if 0 void CPools::Initialise(void) { @@ -26,6 +30,7 @@ CPools::Initialise(void) ms_pDummyPool = new CDummyPool(NUMDUMMIES); ms_pAudioScriptObjectPool = new CAudioScriptObjectPool(NUMAUDIOSCRIPTOBJECTS); } +#endif int32 CPools::GetPedRef(CPed *ped) { return ms_pPedPool->GetIndex(ped); } CPed *CPools::GetPed(int32 handle) { return ms_pPedPool->GetAt(handle); } diff --git a/src/core/Streaming.cpp b/src/core/Streaming.cpp index 9d9241e4..a7bde91e 100644 --- a/src/core/Streaming.cpp +++ b/src/core/Streaming.cpp @@ -26,6 +26,7 @@ #include "CutsceneMgr.h" #include "CdStream.h" #include "Streaming.h" +#include "main.h" bool &CStreaming::ms_disableStreaming = *(bool*)0x95CD6E; bool &CStreaming::ms_bLoadingBigModel = *(bool*)0x95CDB0; @@ -2427,6 +2428,19 @@ CStreaming::MemoryCardLoad(uint8 *buffer, uint32 length) ms_aInfoForModel[i].m_flags = buffer[i]; } +void +CStreaming::UpdateForAnimViewer(void) +{ + if (CStreaming::ms_channelError == -1) { + CStreaming::AddModelsToRequestList(CVector(0.0f, 0.0f, 0.0f)); + CStreaming::LoadRequestedModels(); + sprintf(gString, "Requested %d, memory size %dK\n", CStreaming::ms_numModelsRequested, 2 * CStreaming::ms_memoryUsed); + } + else { + CStreaming::RetryLoadFile(CStreaming::ms_channelError); + } +} + STARTPATCHES InjectHook(0x406430, CStreaming::Init, PATCH_JUMP); InjectHook(0x406C80, CStreaming::Shutdown, PATCH_JUMP); diff --git a/src/core/Streaming.h b/src/core/Streaming.h index 212a6d71..1100fd1b 100644 --- a/src/core/Streaming.h +++ b/src/core/Streaming.h @@ -185,4 +185,6 @@ public: static void MemoryCardSave(uint8 *buffer, uint32 *length); static void MemoryCardLoad(uint8 *buffer, uint32 length); + + static void UpdateForAnimViewer(void); }; diff --git a/src/core/TempColModels.cpp b/src/core/TempColModels.cpp index a323d7c9..07ac7989 100644 --- a/src/core/TempColModels.cpp +++ b/src/core/TempColModels.cpp @@ -15,3 +15,5 @@ CColModel &CTempColModels::ms_colModelPedGroundHit = *(CColModel*)0x880480; CColModel &CTempColModels::ms_colModelBoot1 = *(CColModel*)0x880670; CColModel &CTempColModels::ms_colModelDoor1 = *(CColModel*)0x880850; CColModel &CTempColModels::ms_colModelBonnet1 = *(CColModel*)0x8808A8; + +WRAPPER void CTempColModels::Initialise(void) { EAXJMP(0x412160); } diff --git a/src/core/TempColModels.h b/src/core/TempColModels.h index 8ac74428..f91ac77e 100644 --- a/src/core/TempColModels.h +++ b/src/core/TempColModels.h @@ -18,4 +18,6 @@ public: static CColModel &ms_colModelBoot1; static CColModel &ms_colModelDoor1; static CColModel &ms_colModelBonnet1; + + static void Initialise(void); }; diff --git a/src/core/World.cpp b/src/core/World.cpp index c6eb831c..9c3aafcf 100644 --- a/src/core/World.cpp +++ b/src/core/World.cpp @@ -28,10 +28,28 @@ bool &CWorld::bSecondShift = *(bool*)0x95CD54; bool &CWorld::bForceProcessControl = *(bool*)0x95CD6C; bool &CWorld::bProcessCutsceneOnly = *(bool*)0x95CD8B; +bool &CWorld::bDoingCarCollisions = *(bool*)0x95CD8C; +bool &CWorld::bIncludeCarTyres = *(bool*)0x95CDAA; + +WRAPPER void CWorld::Process(void) { EAXJMP(0x4B1A60); } +WRAPPER void CWorld::ShutDown(void) { EAXJMP(0x4AE450); } WRAPPER void CWorld::RemoveReferencesToDeletedObject(CEntity*) { EAXJMP(0x4B3BF0); } WRAPPER void CWorld::FindObjectsKindaColliding(const CVector &, float, bool, int16*, int16, CEntity **, bool, bool, bool, bool, bool){ EAXJMP(0x4B2A30); } void +CWorld::Initialise() +{ + pIgnoreEntity = nil; + bDoingCarCollisions = false; + bSecondShift = false; + bNoMoreCollisionTorque = false; + bProcessCutsceneOnly = false; + bIncludeDeadPeds = false; + bForceProcessControl = false; + bIncludeCarTyres = false; +} + +void CWorld::Add(CEntity *ent) { if(ent->IsVehicle() || ent->IsPed()) diff --git a/src/core/World.h b/src/core/World.h index 6c52da5a..c2ca75c4 100644 --- a/src/core/World.h +++ b/src/core/World.h @@ -67,6 +67,8 @@ public: static bool &bSecondShift; static bool &bForceProcessControl; static bool &bProcessCutsceneOnly; + static bool &bDoingCarCollisions; + static bool &bIncludeCarTyres; static void Remove(CEntity *entity); static void Add(CEntity *entity); @@ -111,6 +113,10 @@ public: static int GetSectorIndexY(float f) { return (int)GetSectorY(f); } static float GetWorldX(int x) { return x*SECTOR_SIZE_X + WORLD_MIN_X; } static float GetWorldY(int y) { return y*SECTOR_SIZE_Y + WORLD_MIN_Y; } + + static void Initialise(); + static void ShutDown(); + static void Process(); }; class CPlayerPed; diff --git a/src/core/common.h b/src/core/common.h index 2b4c466a..36f67bfa 100644 --- a/src/core/common.h +++ b/src/core/common.h @@ -118,6 +118,15 @@ public: CRGBA(void) { } CRGBA(uint8 r, uint8 g, uint8 b, uint8 a) : r(r), g(g), b(b), a(a) { } + + CRGBA &CRGBA::operator =(const CRGBA &right) + { + this->r = right.r; + this->g = right.g; + this->b = right.b; + this->a = right.a; + return *this; + } #ifdef RWCORE_H operator RwRGBA &(void) { return rwRGBA; @@ -130,6 +139,15 @@ public: operator RwRGBA (void) const { return rwRGBA; } + + CRGBA &CRGBA::operator =(const RwRGBA &right) + { + this->r = right.red; + this->g = right.green; + this->b = right.blue; + this->a = right.alpha; + return *this; + } #endif }; diff --git a/src/core/main.cpp b/src/core/main.cpp index a4c4de7b..7d60291c 100644 --- a/src/core/main.cpp +++ b/src/core/main.cpp @@ -47,6 +47,7 @@ #include "Text.h" #include "RpAnimBlend.h" #include "Frontend.h" +#include "AnimViewer.h" #define DEFAULT_VIEWWINDOW (Tan(DEGTORAD(CDraw::GetFOV() * 0.5f))) @@ -71,9 +72,10 @@ char version_name[64]; float FramesPerSecond = 30.0f; bool gbPrintShite = false; -bool gbModelViewer; +bool &gbModelViewer = *(bool*)0x95CD93; bool DoRWStuffStartOfFrame_Horizon(int16 TopRed, int16 TopGreen, int16 TopBlue, int16 BottomRed, int16 BottomGreen, int16 BottomBlue, int16 Alpha); +bool DoRWStuffStartOfFrame(int16 TopRed, int16 TopGreen, int16 TopBlue, int16 BottomRed, int16 BottomGreen, int16 BottomBlue, int16 Alpha); void DoRWStuffEndOfFrame(void); void RenderScene(void); @@ -104,6 +106,28 @@ InitialiseGame(void) CGame::Initialise("DATA\\GTA3.DAT"); } +#ifndef MASTER +void +TheModelViewer(void) +{ +#ifdef ASPECT_RATIO_SCALE + CDraw::SetAspectRatio(CDraw::FindAspectRatio()); +#endif + CAnimViewer::Update(); + CTimer::Update(); + SetLightsWithTimeOfDayColour(Scene.world); + CRenderer::ConstructRenderList(); + DoRWStuffStartOfFrame(CTimeCycle::GetSkyTopRed(), CTimeCycle::GetSkyTopGreen(), CTimeCycle::GetSkyTopBlue(), + CTimeCycle::GetSkyBottomRed(), CTimeCycle::GetSkyBottomGreen(), CTimeCycle::GetSkyBottomBlue(), + 255); + + DefinedState(); + CVisibilityPlugins::InitAlphaEntityList(); + CAnimViewer::Render(); + DoRWStuffEndOfFrame(); +} +#endif + void Idle(void *arg) { @@ -976,6 +1000,15 @@ AppEventHandler(RsEvent event, void *param) return rsEVENTPROCESSED; } +#ifndef MASTER + case rsANIMVIEWER: + { + TheModelViewer(); + + return rsEVENTPROCESSED; + } +#endif + default: { return rsEVENTNOTPROCESSED; diff --git a/src/core/main.h b/src/core/main.h index 6d393066..45ba441f 100644 --- a/src/core/main.h +++ b/src/core/main.h @@ -18,7 +18,7 @@ extern wchar *gUString; extern wchar *gUString2; extern bool &b_FoundRecentSavedGameWantToLoad; extern bool gbPrintShite; -extern bool gbModelViewer; +extern bool &gbModelViewer; class CSprite2d; @@ -30,3 +30,6 @@ char *GetLevelSplashScreen(int level); char *GetRandomSplashScreen(void); void LittleTest(void); void ValidateVersion(); +#ifndef MASTER +void TheModelViewer(void); +#endif diff --git a/src/core/re3.cpp b/src/core/re3.cpp index dc501075..ad3838bd 100644 --- a/src/core/re3.cpp +++ b/src/core/re3.cpp @@ -351,7 +351,7 @@ DebugMenuPopulate(void) DebugMenuAddVarBool8("Debug", "Don't render Objects", (int8*)&gbDontRenderObjects, nil); DebugMenuAddCmd("Debug", "Make peds around you follow you", LetThemFollowYou); -#ifndef FINAL +#ifndef MASTER DebugMenuAddVarBool8("Debug", "Toggle unused fight feature", (int8*)&CPed::bUnusedFightThingOnPlayer, nil); #endif diff --git a/src/objects/ParticleObject.cpp b/src/objects/ParticleObject.cpp index f5cd4c94..32d305c6 100644 --- a/src/objects/ParticleObject.cpp +++ b/src/objects/ParticleObject.cpp @@ -1,30 +1,1137 @@ #include "common.h" #include "patcher.h" #include "ParticleObject.h" +#include "Timer.h" +#include "General.h" +#include "ParticleMgr.h" +#include "Particle.h" +#include "Camera.h" +#include "Game.h" -WRAPPER void CParticleObject::AddObject(uint16 type, const CVector &pos, uint8 remove) { EAXJMP(0x4BC4D0); } -WRAPPER void CParticleObject::AddObject(uint16 type, const CVector &pos, float size, uint8 remove) { EAXJMP(0x4BC520); } -WRAPPER void CParticleObject::AddObject(uint16 type, const CVector &pos, const CVector &dir, float size, uint8 remove) { EAXJMP(0x4BC570); } -WRAPPER void CParticleObject::AddObject(uint16 type, const CVector &pos, const CVector &dir, float size, uint32, const RwRGBA &col, uint8 remove) { EAXJMP(0x4BC5B0); } -// Converted from static void __cdecl CParticleObject::Initialise() 0x42C760 -void CParticleObject::Initialise() +CParticleObject (&gPObjectArray)[MAX_PARTICLEOBJECTS] = *(CParticleObject(*)[MAX_PARTICLEOBJECTS])int(0x62A58C); + +CParticleObject *&CParticleObject::pCloseListHead = *(CParticleObject **)int(0x8F4340); +CParticleObject *&CParticleObject::pFarListHead = *(CParticleObject **)int(0x942F78); +CParticleObject *&CParticleObject::pUnusedListHead = *(CParticleObject **)int(0x94128C); + +CAudioHydrant List[MAX_AUDIOHYDRANTS]; + +bool +CAudioHydrant::Add(CParticleObject *particleobject) { - ((void (__cdecl *)())0x4BC440)(); + for ( int32 i = 0; i < MAX_AUDIOHYDRANTS; i++ ) + { + if ( List[i].AudioEntity == AEHANDLE_NONE ) + { + List[i].AudioEntity = DMAudio.CreateEntity(AUDIOTYPE_FIREHYDRANT, particleobject); + + if ( AEHANDLE_IS_FAILED(List[i].AudioEntity) ) + return false; + + DMAudio.SetEntityStatus(List[i].AudioEntity, true); + + List[i].pParticleObject = particleobject; + + return true; + } + } + + return false; } -// Converted from static void __cdecl CParticleObject::UpdateAll() 0x4BCA30 -void CParticleObject::UpdateAll() +void +CAudioHydrant::Remove(CParticleObject *particleobject) { - ((void (__cdecl *)())0x4BCA30)(); + for ( int32 i = 0; i < MAX_AUDIOHYDRANTS; i++ ) + { + if ( List[i].pParticleObject == particleobject ) + { + DMAudio.DestroyEntity(List[i].AudioEntity); + List[i].AudioEntity = AEHANDLE_NONE; + List[i].pParticleObject = NULL; + } + } +} + +CParticleObject::CParticleObject() : + CPlaceable(), + m_nFrameCounter(0), + m_nState(POBJECTSTATE_INITIALISED), + m_pNext(NULL), + m_pPrev(NULL), + m_nRemoveTimer(NULL) + +{ + ; +} + +CParticleObject::~CParticleObject() +{ + +} + +void +CParticleObject::Initialise() +{ + pCloseListHead = NULL; + pFarListHead = NULL; + + pUnusedListHead = &gPObjectArray[0]; + + for ( int32 i = 0; i < MAX_PARTICLEOBJECTS; i++ ) + { + if ( i == 0 ) + gPObjectArray[i].m_pPrev = NULL; + else + gPObjectArray[i].m_pPrev = &gPObjectArray[i - 1]; + + if ( i == MAX_PARTICLEOBJECTS-1 ) + gPObjectArray[i].m_pNext = NULL; + else + gPObjectArray[i].m_pNext = &gPObjectArray[i + 1]; + + gPObjectArray[i].m_nState = POBJECTSTATE_FREE; + } +} + +CParticleObject * +CParticleObject::AddObject(uint16 type, CVector const &pos, uint8 remove) +{ + CRGBA color(0, 0, 0, 0); + CVector target(0.0f, 0.0f, 0.0f); + return AddObject(type, pos, target, 0.0f, 0, color, remove); +} + +CParticleObject * +CParticleObject::AddObject(uint16 type, CVector const &pos, float size, uint8 remove) +{ + CRGBA color(0, 0, 0, 0); + CVector target(0.0f, 0.0f, 0.0f); + return AddObject(type, pos, target, size, 0, color, remove); +} + +CParticleObject * +CParticleObject::AddObject(uint16 type, CVector const &pos, CVector const &target, float size, uint8 remove) +{ + CRGBA color(0, 0, 0, 0); + return AddObject(type, pos, target, size, 0, color, remove); +} + +CParticleObject * +CParticleObject::AddObject(uint16 type, CVector const &pos, CVector const &target, float size, uint32 lifeTime, RwRGBA const &color, uint8 remove) +{ + CParticleObject *pobj = pUnusedListHead; + + ASSERT(pobj != NULL); + + if ( pobj == NULL ) + { + printf("Error: No particle objects available!\n"); + return NULL; + } + + MoveToList(&pUnusedListHead, &pCloseListHead, pobj); + + pobj->m_nState = POBJECTSTATE_UPDATE_CLOSE; + pobj->m_Type = (eParticleObjectType)type; + + pobj->GetPosition() = pos; + pobj->m_vecTarget = target; + + pobj->m_nNumEffectCycles = 1; + pobj->m_nSkipFrames = 1; + pobj->m_nCreationChance = 0; + pobj->m_nFrameCounter = 0; + + pobj->m_bRemove = remove; + + pobj->m_pParticle = NULL; + + if ( lifeTime != 0 ) + pobj->m_nRemoveTimer = CTimer::GetTimeInMilliseconds() + lifeTime; + else + pobj->m_nRemoveTimer = 0; + + if ( color.alpha != 0 ) + RwRGBAAssign(&pobj->m_Color, &color); + else + pobj->m_Color.alpha = 0; + + pobj->m_fSize = size; + pobj->m_fRandVal = 0.0f; + + if ( type <= POBJECT_CATALINAS_SHOTGUNFLASH ) + { + switch ( type ) + { + case POBJECT_PAVEMENT_STEAM: + { + pobj->m_ParticleType = PARTICLE_STEAM_NY; + pobj->m_nNumEffectCycles = 1; + pobj->m_nSkipFrames = 3; + pobj->m_nCreationChance = 8; + break; + } + + case POBJECT_PAVEMENT_STEAM_SLOWMOTION: + { + pobj->m_ParticleType = PARTICLE_STEAM_NY_SLOWMOTION; + pobj->m_nNumEffectCycles = 1; + pobj->m_nSkipFrames = 1; + pobj->m_nCreationChance = 8; + break; + } + + case POBJECT_WALL_STEAM: + { + pobj->m_ParticleType = PARTICLE_STEAM_NY; + pobj->m_nNumEffectCycles = 1; + pobj->m_nSkipFrames = 3; + pobj->m_nCreationChance = 8; + break; + } + + case POBJECT_WALL_STEAM_SLOWMOTION: + { + pobj->m_ParticleType = PARTICLE_STEAM_NY_SLOWMOTION; + pobj->m_nNumEffectCycles = 1; + pobj->m_nSkipFrames = 1; + pobj->m_nCreationChance = 8; + break; + } + + case POBJECT_DARK_SMOKE: + { + pobj->m_ParticleType = PARTICLE_STEAM_NY; + pobj->m_nNumEffectCycles = 1; + pobj->m_nSkipFrames = 3; + pobj->m_nCreationChance = 8; + pobj->m_Color = CRGBA(16, 16, 16, 255); + break; + } + + case POBJECT_FIRE_HYDRANT: + { + pobj->m_ParticleType = PARTICLE_WATER_HYDRANT; + pobj->m_nNumEffectCycles = 4; + pobj->m_nSkipFrames = 1; + pobj->m_nCreationChance = 0; + pobj->m_vecTarget = CVector(0.0f, 0.0f, 0.3f); + pobj->m_nRemoveTimer = CTimer::GetTimeInMilliseconds() + 5000; + CAudioHydrant::Add(pobj); + break; + } + + case POBJECT_CAR_WATER_SPLASH: + case POBJECT_PED_WATER_SPLASH: + { + pobj->m_ParticleType = PARTICLE_CAR_SPLASH; + pobj->m_nNumEffectCycles = 0; + pobj->m_nSkipFrames = 1; + pobj->m_nCreationChance = 0; + break; + } + + case POBJECT_SPLASHES_AROUND: + { + pobj->m_ParticleType = PARTICLE_SPLASH; + pobj->m_nNumEffectCycles = 15; + pobj->m_nSkipFrames = 2; + pobj->m_nCreationChance = 0; + break; + } + + case POBJECT_SMALL_FIRE: + { + pobj->m_ParticleType = PARTICLE_FLAME; + pobj->m_nNumEffectCycles = 1; + pobj->m_nSkipFrames = 2; + pobj->m_nCreationChance = 2; + pobj->m_vecTarget = CVector(0.0f, 0.0f, 0.0f); + break; + } + + case POBJECT_BIG_FIRE: + { + pobj->m_ParticleType = PARTICLE_FLAME; + pobj->m_nNumEffectCycles = 1; + pobj->m_nSkipFrames = 2; + pobj->m_nCreationChance = 4; + pobj->m_vecTarget = CVector(0.0f, 0.0f, 0.0f); + break; + } + + case POBJECT_DRY_ICE: + { + pobj->m_ParticleType = PARTICLE_SMOKE; + pobj->m_nNumEffectCycles = 1; + pobj->m_nSkipFrames = 1; + pobj->m_nCreationChance = 0; + pobj->m_vecTarget = CVector(0.0f, 0.0f, 0.0f); + break; + } + + case POBJECT_DRY_ICE_SLOWMOTION: + { + pobj->m_ParticleType = PARTICLE_SMOKE_SLOWMOTION; + pobj->m_nNumEffectCycles = 1; + pobj->m_nSkipFrames = 1; + pobj->m_nCreationChance = 0; + pobj->m_vecTarget = CVector(0.0f, 0.0f, 0.0f); + break; + } + + case POBJECT_FIRE_TRAIL: + { + pobj->m_ParticleType = PARTICLE_EXPLOSION_MEDIUM; + pobj->m_nNumEffectCycles = 1; + pobj->m_nSkipFrames = 3; + pobj->m_nCreationChance = 2; + pobj->m_fRandVal = 0.01f; + break; + } + + case POBJECT_SMOKE_TRAIL: + { + pobj->m_ParticleType = PARTICLE_FIREBALL_SMOKE; + pobj->m_nNumEffectCycles = 1; + pobj->m_nSkipFrames = 1; + pobj->m_nCreationChance = 2; + pobj->m_fRandVal = 0.02f; + break; + } + + case POBJECT_FIREBALL_AND_SMOKE: + { + pobj->m_ParticleType = PARTICLE_FLAME; + pobj->m_nNumEffectCycles = 1; + pobj->m_nSkipFrames = 1; + pobj->m_nCreationChance = 2; + pobj->m_fRandVal = 0.1f; + break; + } + + case POBJECT_ROCKET_TRAIL: + { + pobj->m_ParticleType = PARTICLE_FLAME; + pobj->m_nNumEffectCycles = 1; + pobj->m_nSkipFrames = 2; + pobj->m_nCreationChance = 8; + pobj->m_fRandVal = 0.1f; + break; + } + + case POBJECT_EXPLOSION_ONCE: + { + pobj->m_ParticleType = PARTICLE_EXPLOSION_LARGE; + pobj->m_nNumEffectCycles = 1; + pobj->m_nSkipFrames = 1; + pobj->m_nCreationChance = 0; + pobj->m_nRemoveTimer = CTimer::GetTimeInMilliseconds(); + break; + } + + case POBJECT_CATALINAS_GUNFLASH: + case POBJECT_CATALINAS_SHOTGUNFLASH: + { + pobj->m_ParticleType = PARTICLE_GUNFLASH_NOANIM; + pobj->m_nNumEffectCycles = 1; + pobj->m_nSkipFrames = 1; + pobj->m_nCreationChance = 0; + pobj->m_nRemoveTimer = CTimer::GetTimeInMilliseconds(); + pobj->m_vecTarget.Normalise(); + break; + } + } + } + + return pobj; +} + +void +CParticleObject::RemoveObject(void) +{ + switch ( this->m_nState ) + { + case POBJECTSTATE_UPDATE_CLOSE: + { + MoveToList(&pCloseListHead, &pUnusedListHead, this); + this->m_nState = POBJECTSTATE_FREE; + break; + } + case POBJECTSTATE_UPDATE_FAR: + { + MoveToList(&pFarListHead, &pUnusedListHead, this); + this->m_nState = POBJECTSTATE_FREE; + break; + } + } +} + +void +CParticleObject::UpdateAll(void) +{ + { + CParticleObject *pobj = pCloseListHead; + CParticleObject *nextpobj; + if ( pobj != NULL ) + { + do + { + nextpobj = pobj->m_pNext; + pobj->UpdateClose(); + pobj = nextpobj; + } + while ( nextpobj != NULL ); + } + } + + { + int32 frame = CTimer::GetFrameCounter() & 31; + int32 counter = 0; + + CParticleObject *pobj = pFarListHead; + CParticleObject *nextpobj; + if ( pobj != NULL ) + { + do + { + nextpobj = pobj->m_pNext; + + if ( counter == counter ) + { + pobj->UpdateFar(); + counter += 32; + } + + counter++; + + pobj = nextpobj; + } + while ( nextpobj != NULL ); + } + } +} + +void CParticleObject::UpdateClose(void) +{ + if ( !CGame::playingIntro ) + { + if ( (this->GetPosition() - TheCamera.GetPosition()).MagnitudeSqr2D() > SQR(100.0f) ) + { + if ( this->m_bRemove ) + { + if ( this->m_Type == POBJECT_FIRE_HYDRANT ) + CAudioHydrant::Remove(this); + + MoveToList(&pCloseListHead, &pUnusedListHead, this); + this->m_nState = POBJECTSTATE_FREE; + } + else + { + MoveToList(&pCloseListHead, &pFarListHead, this); + this->m_nState = POBJECTSTATE_UPDATE_FAR; + } + + return; + } + } + + if ( ++this->m_nFrameCounter >= this->m_nSkipFrames ) + { + this->m_nFrameCounter = 0; + + int32 randVal; // BUG: unitialised can be used ??!! + if ( this->m_nCreationChance != 0 ) + randVal = CGeneral::GetRandomNumber() % this->m_nCreationChance; + + if ( randVal != 0 && this->m_nCreationChance > 0 + || randVal == 0 && (this->m_nCreationChance & 128) != 0 + || this->m_nCreationChance == 0 ) + { + switch ( this->m_Type ) + { + case POBJECT_SMALL_FIRE: + { + CVector pos = this->GetPosition(); + CVector vel = this->m_vecTarget; + float size = this->m_fSize; + + CVector flamevel; + + flamevel.x = vel.x; + flamevel.y = vel.y; + flamevel.z = CGeneral::GetRandomNumberInRange(0.0125f*size, 0.1f*size); + + CParticle::AddParticle(PARTICLE_FLAME, pos, flamevel, NULL, size); + + + CVector possmoke = pos; + + possmoke.x += CGeneral::GetRandomNumberInRange(0.625f*-size, size*0.625f); + possmoke.y += CGeneral::GetRandomNumberInRange(0.625f*-size, size*0.625f); + possmoke.z += CGeneral::GetRandomNumberInRange(0.625f* size, size*2.5f); + + CParticle::AddParticle(PARTICLE_CARFLAME_SMOKE, possmoke, vel); + + break; + } + + case POBJECT_BIG_FIRE: + { + CVector pos = this->GetPosition(); + CVector vel = this->m_vecTarget; + float size = this->m_fSize; + + + float s = 0.7f*size; + + CVector flamevel; + + flamevel.x = vel.x; + flamevel.y = vel.y; + flamevel.z = CGeneral::GetRandomNumberInRange(0.0125f*s, 0.1f*s); + + float flamesize = 0.8f*size; + + CParticle::AddParticle(PARTICLE_FLAME, pos, flamevel, NULL, flamesize); + + + for ( int32 i = 0; i < 4; i++ ) + { + CVector smokepos = pos; + + smokepos.x += CGeneral::GetRandomNumberInRange(0.625f*-size, 0.625f*size); + smokepos.y += CGeneral::GetRandomNumberInRange(0.625f*-size, 0.625f*size); + smokepos.z += CGeneral::GetRandomNumberInRange(0.625f* size, 3.5f *size); + + CParticle::AddParticle(PARTICLE_CARFLAME_SMOKE, smokepos, vel); + } + + break; + } + + case POBJECT_FIREBALL_AND_SMOKE: + { + if ( this->m_pParticle == NULL ) + { + CVector pos = this->GetPosition(); + CVector vel = this->m_vecTarget; + float size = this->m_fSize; + + CVector expvel = 1.2f*vel; + float expsize = 1.2f*size; + this->m_pParticle = CParticle::AddParticle(PARTICLE_EXPLOSION_MEDIUM, pos, expvel, NULL, expsize); + } + else + { + CVector pos = this->GetPosition(); // this->m_pParticle->m_vecPosition ? + CVector vel = this->m_vecTarget; + float size = this->m_fSize; + + CVector veloffset = 0.35f*vel; + CVector fireballvel = vel; + + for ( int32 i = 0; i < this->m_nNumEffectCycles; i++ ) + { + fireballvel.x += CGeneral::GetRandomNumberInRange(-veloffset.x, veloffset.x); + fireballvel.y += CGeneral::GetRandomNumberInRange(-veloffset.y, veloffset.y); + fireballvel.z += CGeneral::GetRandomNumberInRange(-veloffset.z, veloffset.z); + + CParticle::AddParticle(PARTICLE_FIREBALL_SMOKE, pos, fireballvel, NULL, size); + } + } + + break; + } + + case POBJECT_ROCKET_TRAIL: + { + if ( this->m_pParticle == NULL ) + { + CVector pos = this->GetPosition(); + CVector vel = this->m_vecTarget; + float size = this->m_fSize; + + this->m_pParticle = CParticle::AddParticle(PARTICLE_EXPLOSION_MEDIUM, pos, vel, NULL, size); + } + else + { + CVector pos = this->m_pParticle->m_vecPosition; + CVector vel = this->m_vecTarget; + float size = this->m_fSize; + + float fireballsize = size * 1.5f; + CVector fireballvel = vel * -0.8f; + + for ( int32 i = 0; i < this->m_nNumEffectCycles; i++ ) + { + CParticle::AddParticle(PARTICLE_FIREBALL_SMOKE, pos, fireballvel, NULL, fireballsize); + } + } + + break; + } + + case POBJECT_FIRE_TRAIL: + { + for ( int32 i = 0; i < this->m_nNumEffectCycles; i++ ) + { + CVector vel = this->m_vecTarget; + + if ( vel.x != 0.0f ) + vel.x += CGeneral::GetRandomNumberInRange(-this->m_fRandVal, this->m_fRandVal); + + if ( vel.y != 0.0f ) + vel.y += CGeneral::GetRandomNumberInRange(-this->m_fRandVal, this->m_fRandVal); + + if ( vel.z != 0.0f ) + vel.z += CGeneral::GetRandomNumberInRange(-this->m_fRandVal, this->m_fRandVal); + + CParticle::AddParticle(this->m_ParticleType, this->GetPosition(), vel, NULL, this->m_fSize, + CGeneral::GetRandomNumberInRange(-6.0f, 6.0f)); + } + + break; + } + + case POBJECT_PED_WATER_SPLASH: + { + CRGBA colorsmoke(255, 255, 255, 196); + + CVector pos = this->GetPosition(); + CVector vel = this->m_vecTarget; + + for ( int32 i = 0; i < 3; i++ ) + { + int32 angle = 90 * i; + float fCos = CParticle::Cos(angle); + float fSin = CParticle::Sin(angle); + + CVector splashpos; + CVector splashvel; + + splashpos = pos + CVector(0.75f*fCos, 0.75f*fSin, 0.0f); + splashvel = vel + CVector(0.05f*fCos, 0.05f*fSin, CGeneral::GetRandomNumberInRange(0.04f, 0.08f)); + + CParticle::AddParticle(PARTICLE_RUBBER_SMOKE, splashpos, splashvel, NULL, + CGeneral::GetRandomNumberInRange(0.1f, 0.8f), colorsmoke); + CParticle::AddParticle(PARTICLE_CAR_SPLASH, splashpos, splashvel, NULL, + CGeneral::GetRandomNumberInRange(0.1f, 0.5f), this->m_Color); + + + splashpos = pos + CVector(0.75f*fCos, 0.75f*-fSin, 0.0f); + splashvel = vel + CVector(0.05f*fCos, 0.05f*-fSin, CGeneral::GetRandomNumberInRange(0.04f, 0.08f)); + + + CParticle::AddParticle(PARTICLE_RUBBER_SMOKE, splashpos, splashvel, NULL, + CGeneral::GetRandomNumberInRange(0.1f, 0.8f), colorsmoke); + CParticle::AddParticle(PARTICLE_CAR_SPLASH, splashpos, splashvel, NULL, + CGeneral::GetRandomNumberInRange(0.1f, 0.5f), this->m_Color); + + + splashpos = pos + CVector(0.75f*-fCos, 0.75f*fSin, 0.0f); + splashvel = vel + CVector(0.05f*-fCos, 0.05f*fSin, CGeneral::GetRandomNumberInRange(0.04f, 0.08f)); + + + CParticle::AddParticle(PARTICLE_RUBBER_SMOKE, splashpos, splashvel, NULL, + CGeneral::GetRandomNumberInRange(0.1f, 0.8f), colorsmoke); + CParticle::AddParticle(PARTICLE_CAR_SPLASH, splashpos, splashvel, NULL, + CGeneral::GetRandomNumberInRange(0.1f, 0.5f), this->m_Color); + + + splashpos = pos + CVector(0.75f*-fCos, 0.75f*-fSin, 0.0f); + splashvel = vel + CVector(0.05f*-fCos, 0.05f*-fSin, CGeneral::GetRandomNumberInRange(0.04f, 0.08f)); + + CParticle::AddParticle(PARTICLE_RUBBER_SMOKE, splashpos, splashvel, NULL, + CGeneral::GetRandomNumberInRange(0.1f, 0.8f), colorsmoke); + CParticle::AddParticle(PARTICLE_CAR_SPLASH, splashpos, splashvel, NULL, + CGeneral::GetRandomNumberInRange(0.1f, 0.5f), this->m_Color); + } + + for ( int32 i = 0; i < 1; i++ ) + { + int32 angle = 180 * (i + 1); + + float fCos = CParticle::Cos(angle); + float fSin = CParticle::Sin(angle); + + CVector splashpos; + CVector splashvel; + + splashpos = pos + CVector(0.5f*fCos, 0.5f*fSin, 0.0f); + splashvel = vel; + splashvel.x += CGeneral::GetRandomNumberInRange(-0.25f, 0.25f) * fCos; + splashvel.y += CGeneral::GetRandomNumberInRange(-0.25f, 0.25f) * fSin; + splashvel.z += CGeneral::GetRandomNumberInRange(0.05f, 0.25f); + + CParticle::AddParticle(PARTICLE_CAR_SPLASH, splashpos, splashvel, NULL, + CGeneral::GetRandomNumberInRange(0.4f, 1.0f), this->m_Color); + + + splashpos = pos + CVector(0.5f*fCos, 0.5f*-fSin, 0.0f); + splashvel = vel; + splashvel.x += CGeneral::GetRandomNumberInRange(-0.25f, 0.25f) * fCos; + splashvel.y += CGeneral::GetRandomNumberInRange(-0.25f, 0.25f) * -fSin; + splashvel.z += CGeneral::GetRandomNumberInRange(0.05f, 0.25f); + + CParticle::AddParticle(PARTICLE_CAR_SPLASH, splashpos, splashvel, NULL, + CGeneral::GetRandomNumberInRange(0.4f, 1.0f), this->m_Color); + + + splashpos = pos + CVector(0.5f*-fCos, 0.5f*fSin, 0.0f); + splashvel = vel; + splashvel.x += CGeneral::GetRandomNumberInRange(-0.25f, 0.25f) * -fCos; + splashvel.y += CGeneral::GetRandomNumberInRange(-0.25f, 0.25f) * fSin; + splashvel.z += CGeneral::GetRandomNumberInRange(0.05f, 0.25f); + + CParticle::AddParticle(PARTICLE_CAR_SPLASH, splashpos, splashvel, NULL, + CGeneral::GetRandomNumberInRange(0.4f, 1.0f), this->m_Color); + + + splashpos = pos + CVector(0.5f*-fCos, 0.5f*-fSin, 0.0f); + splashvel = vel; + splashvel.x += CGeneral::GetRandomNumberInRange(-0.25f, 0.25f) * -fCos; + splashvel.y += CGeneral::GetRandomNumberInRange(-0.25f, 0.25f) * -fSin; + splashvel.z += CGeneral::GetRandomNumberInRange(0.05f, 0.25f); + + CParticle::AddParticle(PARTICLE_CAR_SPLASH, splashpos, splashvel, NULL, + CGeneral::GetRandomNumberInRange(0.4f, 1.0f), this->m_Color); + } + + break; + } + + case POBJECT_CAR_WATER_SPLASH: + { + CRGBA colorsmoke(255, 255, 255, 196); + + CVector pos = this->GetPosition(); + CVector vel = this->m_vecTarget; + + float size = CGeneral::GetRandomNumberInRange(1.0f, 2.5f); + + for ( int32 i = 0; i < 3; i++ ) + { + int32 angle = 90 * i; + + float fCos = CParticle::Cos(angle); + float fSin = CParticle::Sin(angle); + + CVector splashpos; + CVector splashvel; + + splashpos = pos + CVector(2.0f*fCos, 2.0f*fSin, 0.0f); + splashvel = vel; + splashvel.x += CGeneral::GetRandomNumberInRange(-0.5f, 0.5f) * fCos; + splashvel.y += CGeneral::GetRandomNumberInRange(-0.5f, 0.5f) * fSin; + splashvel.z += CGeneral::GetRandomNumberInRange(0.01f, 0.03f); + + CParticle::AddParticle(PARTICLE_RUBBER_SMOKE, splashpos, splashvel, NULL, size, colorsmoke); + CParticle::AddParticle(PARTICLE_CAR_SPLASH, splashpos, splashvel, NULL, 0.0f, this->m_Color); + + + splashpos = pos + CVector(2.0f*fCos, 2.0f*-fSin, 0.0f); + splashvel = vel; + splashvel.x += CGeneral::GetRandomNumberInRange(-0.5f, 0.5f) * fCos; + splashvel.y += CGeneral::GetRandomNumberInRange(-0.5f, 0.5f) * -fSin; + splashvel.z += CGeneral::GetRandomNumberInRange(0.01f, 0.03f); + + CParticle::AddParticle(PARTICLE_RUBBER_SMOKE, splashpos, splashvel, NULL, size, colorsmoke); + CParticle::AddParticle(PARTICLE_CAR_SPLASH, splashpos, splashvel, NULL, 0.0f, this->m_Color); + + splashpos = pos + CVector(2.0f*-fCos, 2.0f*fSin, 0.0f); + splashvel = vel; + splashvel.x += CGeneral::GetRandomNumberInRange(-0.5f, 0.5f) * -fCos; + splashvel.y += CGeneral::GetRandomNumberInRange(-0.5f, 0.5f) * fSin; + splashvel.z += CGeneral::GetRandomNumberInRange(0.01f, 0.03f); + + CParticle::AddParticle(PARTICLE_RUBBER_SMOKE, splashpos, splashvel, NULL, size, colorsmoke); + CParticle::AddParticle(PARTICLE_CAR_SPLASH, splashpos, splashvel, NULL, 0.0f, this->m_Color); + + splashpos = pos + CVector(2.0f*-fCos, 2.0f*-fSin, 0.0f); + splashvel = vel; + splashvel.x += CGeneral::GetRandomNumberInRange(-0.5f, 0.5f) * -fCos; + splashvel.y += CGeneral::GetRandomNumberInRange(-0.5f, 0.5f) * -fSin; + splashvel.z += CGeneral::GetRandomNumberInRange(0.01f, 0.03f); + + CParticle::AddParticle(PARTICLE_RUBBER_SMOKE, splashpos, splashvel, NULL, size, colorsmoke); + CParticle::AddParticle(PARTICLE_CAR_SPLASH, splashpos, splashvel, NULL, 0.0f, this->m_Color); + } + + for ( int32 i = 0; i < 1; i++ ) + { + int32 angle = 180 * (i + 1); + + float fCos = CParticle::Cos(angle); + float fSin = CParticle::Sin(angle); + + CVector splashpos; + CVector splashvel; + + + splashpos = pos + CVector(1.25f*fCos, 1.25f*fSin, 0.0f); + splashvel = vel; + splashvel.x += CGeneral::GetRandomNumberInRange(-0.1f, 0.1f) * fCos; + splashvel.y += CGeneral::GetRandomNumberInRange(-0.1f, 0.1f) * fSin; + splashvel.z += CGeneral::GetRandomNumberInRange(0.26f, 0.53f); + CParticle::AddParticle(PARTICLE_CAR_SPLASH, splashpos, splashvel, NULL, 0.0f, this->m_Color); + + splashpos = pos + CVector(1.25f*fCos, 1.25f*-fSin, 0.0f); + splashvel = vel; + splashvel.x += CGeneral::GetRandomNumberInRange(-0.1f, 0.1f) * fCos; + splashvel.y += CGeneral::GetRandomNumberInRange(-0.1f, 0.1f) * -fSin; + splashvel.z += CGeneral::GetRandomNumberInRange(0.26f, 0.53f); + CParticle::AddParticle(PARTICLE_CAR_SPLASH, splashpos, splashvel, NULL, 0.0f, this->m_Color); + + splashpos = pos + CVector(1.25f*-fCos, 1.25f*fSin, 0.0f); + splashvel = vel; + splashvel.x += CGeneral::GetRandomNumberInRange(-0.1f, 0.1f) * -fCos; + splashvel.y += CGeneral::GetRandomNumberInRange(-0.1f, 0.1f) * fSin; + splashvel.z += CGeneral::GetRandomNumberInRange(0.26f, 0.53f); + CParticle::AddParticle(PARTICLE_CAR_SPLASH, splashpos, splashvel, NULL, 0.0f, this->m_Color); + + splashpos = pos + CVector(1.25f*-fCos, 1.25f*-fSin, 0.0f); + splashvel = vel; + splashvel.x += CGeneral::GetRandomNumberInRange(-0.1f, 0.1f) * -fCos; + splashvel.y += CGeneral::GetRandomNumberInRange(-0.1f, 0.1f) * -fSin; + splashvel.z += CGeneral::GetRandomNumberInRange(0.26f, 0.53f); + CParticle::AddParticle(PARTICLE_CAR_SPLASH, splashpos, splashvel, NULL, 0.0f, this->m_Color); + } + + break; + } + + case POBJECT_SPLASHES_AROUND: + { + CVector pos = this->GetPosition(); + float size = this->m_fSize; + + for ( int32 i = 0; i < this->m_nNumEffectCycles; i++ ) + { + CVector splashpos = pos; + + splashpos.x += CGeneral::GetRandomNumberInRange(-size, size); + splashpos.y += CGeneral::GetRandomNumberInRange(-size, size); + + if ( CGeneral::GetRandomNumber() & 1 ) + { + CParticle::AddParticle(PARTICLE_RAIN_SPLASH, splashpos, CVector(0.0f, 0.0f, 0.0f), + NULL, 0.1f, this->m_Color); + } + else + { + CParticle::AddParticle(PARTICLE_RAIN_SPLASHUP, splashpos, CVector(0.0f, 0.0f, 0.0f), + NULL, 0.12f, this->m_Color); + } + } + + break; + } + + case POBJECT_CATALINAS_GUNFLASH: + { + CRGBA flashcolor(120, 120, 120, 255); + + CVector vel = this->m_vecTarget; + CVector pos = this->GetPosition(); + + float size = 1.0f; + if ( this->m_fSize != 0.0f ) + size = this->m_fSize; + + CParticle::AddParticle(PARTICLE_GUNFLASH, pos, CVector(0.0f, 0.0f, 0.0f), NULL, 0.12f*size, flashcolor); + + pos += size * (0.06f * vel); + CParticle::AddParticle(PARTICLE_GUNFLASH, pos, CVector(0.0f, 0.0f, 0.0f), NULL, 0.08f*size, flashcolor); + + pos += size * (0.04f * vel); + CParticle::AddParticle(PARTICLE_GUNFLASH, pos, CVector(0.0f, 0.0f, 0.0f), NULL, 0.04f*size, flashcolor); + + CVector smokepos = this->GetPosition(); + CVector smokevel = 0.1f * vel; + CParticle::AddParticle(PARTICLE_GUNSMOKE2, smokepos, smokevel, NULL, 0.005f*size); + + break; + } + + case POBJECT_CATALINAS_SHOTGUNFLASH: + { + CRGBA flashcolor(120, 120, 120, 255); + + CVector vel = this->m_vecTarget; + + float size = 1.0f; + if ( this->m_fSize != 0.0f ) + size = this->m_fSize; + + CVector pos = this->GetPosition(); + + CVector velstep = size * (0.1f * vel); + CVector flashpos = pos; + + flashpos += velstep; + CParticle::AddParticle(PARTICLE_GUNFLASH, flashpos, CVector(0.0f, 0.0f, 0.0f), NULL, 0.0f, flashcolor); + + flashpos += velstep; + CParticle::AddParticle(PARTICLE_GUNFLASH, flashpos, CVector(0.0f, 0.0f, 0.0f), NULL, 0.15f*size, flashcolor); + + flashpos += velstep; + CParticle::AddParticle(PARTICLE_GUNFLASH, flashpos, CVector(0.0f, 0.0f, 0.0f), NULL, 0.2f*size, flashcolor); + + + CParticle::AddParticle(PARTICLE_GUNFLASH, pos, CVector(0.0f, 0.0f, 0.0f), NULL, 0.0f, flashcolor); + + CVector smokepos = this->GetPosition(); + CVector smokevel = 0.1f*vel; + CParticle::AddParticle(PARTICLE_GUNSMOKE2, smokepos, smokevel, NULL, 0.1f*size); + + break; + } + + default: + { + if ( this->m_fRandVal != 0.0f ) + { + for ( int32 i = 0; i < this->m_nNumEffectCycles; i++ ) + { + CVector vel = this->m_vecTarget; + + if ( vel.x != 0.0f ) + vel.x += CGeneral::GetRandomNumberInRange(-this->m_fRandVal, this->m_fRandVal); + + if ( vel.y != 0.0f ) + vel.y += CGeneral::GetRandomNumberInRange(-this->m_fRandVal, this->m_fRandVal); + + if ( vel.z != 0.0f ) + vel.z += CGeneral::GetRandomNumberInRange(-this->m_fRandVal, this->m_fRandVal); + + CParticle::AddParticle(this->m_ParticleType, this->GetPosition(), vel, NULL, + this->m_fSize, this->m_Color); + } + } + else + { + for ( int32 i = 0; i < this->m_nNumEffectCycles; i++ ) + { + CParticle::AddParticle(this->m_ParticleType, this->GetPosition(), this->m_vecTarget, NULL, + this->m_fSize, this->m_Color); + } + } + + break; + } + } + } + } + + if ( this->m_nRemoveTimer != 0 && this->m_nRemoveTimer < CTimer::GetTimeInMilliseconds() ) + { + MoveToList(&pCloseListHead, &pUnusedListHead, this); + this->m_nState = POBJECTSTATE_FREE; + + if ( this->m_Type == POBJECT_FIRE_HYDRANT ) + CAudioHydrant::Remove(this); + } +} + +void +CParticleObject::UpdateFar(void) +{ + if ( this->m_nRemoveTimer != 0 && this->m_nRemoveTimer < CTimer::GetTimeInMilliseconds() ) + { + MoveToList(&pFarListHead, &pUnusedListHead, this); + this->m_nState = POBJECTSTATE_FREE; + + if ( this->m_Type == POBJECT_FIRE_HYDRANT ) + CAudioHydrant::Remove(this); + } + + CVector2D dist = this->GetPosition() - TheCamera.GetPosition(); + if ( dist.MagnitudeSqr() < SQR(100.0f)/*10000.0f*/ ) + { + MoveToList(&pFarListHead, &pCloseListHead, this); + this->m_nState = POBJECTSTATE_UPDATE_CLOSE; + } +} + +bool +CParticleObject::SaveParticle(uint8 *buffer, uint32 *length) +{ + ASSERT( buffer != NULL ); + ASSERT( length != NULL ); + + int32 numObjects = 0; + + for ( CParticleObject *p = pCloseListHead; p != NULL; p = p->m_pNext ) + ++numObjects; + + for ( CParticleObject *p = pFarListHead; p != NULL; p = p->m_pNext ) + ++numObjects; + + *(int32 *)buffer = numObjects; + buffer += sizeof(int32); + + int32 objectsLength = sizeof(CParticleObject) * (numObjects + 1); + int32 dataLength = objectsLength + sizeof(int32); + + for ( CParticleObject *p = pCloseListHead; p != NULL; p = p->m_pNext ) + { + memcpy(buffer, p, sizeof(CParticleObject)); + buffer += sizeof(CParticleObject); + } + + for ( CParticleObject *p = pFarListHead; p != NULL; p = p->m_pNext ) + { + memcpy(buffer, p, sizeof(CParticleObject)); + buffer += sizeof(CParticleObject); + } + + *length = dataLength; + + return true; +} + +bool +CParticleObject::LoadParticle(uint8 *buffer, uint32 length) +{ + ASSERT( buffer != NULL ); + + RemoveAllParticleObjects(); + + int32 numObjects = *(int32 *)buffer; + buffer += sizeof(int32); + + if ( length != sizeof(CParticleObject) * (numObjects + 1) + sizeof(int32) ) + return false; + + if ( numObjects == 0 ) + return true; + + + int32 i = 0; + while ( i < numObjects ) + { + CParticleObject *dst = pUnusedListHead; + CParticleObject *src = (CParticleObject *)buffer; + buffer += sizeof(CParticleObject); + + if ( dst == NULL ) + return false; + + MoveToList(&pUnusedListHead, &pCloseListHead, dst); + + dst->m_nState = POBJECTSTATE_UPDATE_CLOSE; + dst->m_Type = src->m_Type; + dst->m_ParticleType = src->m_ParticleType; + dst->GetPosition() = src->GetPosition(); + dst->m_vecTarget = src->m_vecTarget; + dst->m_nFrameCounter = src->m_nFrameCounter; + dst->m_bRemove = src->m_bRemove; + dst->m_pParticle = NULL; + dst->m_nRemoveTimer = src->m_nRemoveTimer; + dst->m_Color = src->m_Color; + dst->m_fSize = src->m_fSize; + dst->m_fRandVal = src->m_fRandVal; + dst->m_nNumEffectCycles = src->m_nNumEffectCycles; + dst->m_nSkipFrames = src->m_nSkipFrames; + dst->m_nCreationChance = src->m_nCreationChance; + + i++; + } + + return true; +} + +void +CParticleObject::RemoveAllParticleObjects(void) +{ + pUnusedListHead = &gPObjectArray[0]; + + pCloseListHead = NULL; + pFarListHead = NULL; + + for ( int32 i = 0; i < MAX_PARTICLEOBJECTS; i++ ) + { + if ( i == 0 ) + gPObjectArray[i].m_pPrev = NULL; + else + gPObjectArray[i].m_pPrev = &gPObjectArray[i - 1]; + + if ( i == MAX_PARTICLEOBJECTS-1 ) + gPObjectArray[i].m_pNext = NULL; + else + gPObjectArray[i].m_pNext = &gPObjectArray[i + 1]; + + gPObjectArray[i].m_nState = POBJECTSTATE_FREE; + } +} + +void +CParticleObject::MoveToList(CParticleObject **from, CParticleObject **to, CParticleObject *obj) +{ + ASSERT( from != NULL ); + ASSERT( to != NULL ); + ASSERT( obj != NULL ); + + if ( obj->m_pPrev == NULL ) + { + *from = obj->m_pNext; + if ( *from ) + (*from)->m_pPrev = NULL; + } + else + { + if ( obj->m_pNext == NULL ) + obj->m_pPrev->m_pNext = NULL; + else + { + obj->m_pNext->m_pPrev = obj->m_pPrev; + obj->m_pPrev->m_pNext = obj->m_pNext; + } + } + + obj->m_pNext = *to; + obj->m_pPrev = NULL; + *to = obj; + + if ( obj->m_pNext ) + obj->m_pNext->m_pPrev = obj; } class CParticleObject_ : public CParticleObject { public: + void ctor() { CParticleObject::CParticleObject(); } void dtor() { CParticleObject::~CParticleObject(); } }; STARTPATCHES + InjectHook(0x4BC330, CAudioHydrant::Add, PATCH_JUMP); + InjectHook(0x4BC390, CAudioHydrant::Remove, PATCH_JUMP); + + InjectHook(0x4BC3E0, &CParticleObject_::ctor, PATCH_JUMP); InjectHook(0x4BC420, &CParticleObject_::dtor, PATCH_JUMP); + InjectHook(0x4BC440, CParticleObject::Initialise, PATCH_JUMP); + + InjectHook(0x4BC4D0, (CParticleObject *(*)(uint16, CVector const &, uint8))CParticleObject::AddObject, PATCH_JUMP); + InjectHook(0x4BC520, (CParticleObject *(*)(uint16, CVector const &, float, uint8))CParticleObject::AddObject, PATCH_JUMP); + InjectHook(0x4BC570, (CParticleObject *(*)(uint16, CVector const &, CVector const &, float, uint8))CParticleObject::AddObject, PATCH_JUMP); + InjectHook(0x4BC5B0, (CParticleObject *(*)(uint16, CVector const &, CVector const &, float, uint32, RwRGBA const &, uint8))CParticleObject::AddObject, PATCH_JUMP); + + InjectHook(0x4BC9F0, &CParticleObject::RemoveObject, PATCH_JUMP); + InjectHook(0x4BCA30, CParticleObject::UpdateAll, PATCH_JUMP); + InjectHook(0x4BCA80, &CParticleObject::UpdateClose, PATCH_JUMP); + InjectHook(0x4BF9F0, &CParticleObject::UpdateFar, PATCH_JUMP); + InjectHook(0x4BFA80, CParticleObject::SaveParticle, PATCH_JUMP); + InjectHook(0x4BFB30, CParticleObject::LoadParticle, PATCH_JUMP); + InjectHook(0x4BFC80, CParticleObject::RemoveAllParticleObjects, PATCH_JUMP); + InjectHook(0x4BFD10, CParticleObject::MoveToList, PATCH_JUMP); + //InjectHook(0x4BFD70, CParticleObject::~CParticleObject, PATCH_JUMP); // virtual + //InjectHook(0x4BFDB0, `global constructor keyed to'ParticleObject.cpp, PATCH_JUMP); + //InjectHook(0x4BFE00, CAudioHydrant::CAudioHydrant, PATCH_JUMP); + //InjectHook(0x4BFE10, sub_4BFE10, PATCH_JUMP); // destroy gPObjectArray array + + ENDPATCHES diff --git a/src/objects/ParticleObject.h b/src/objects/ParticleObject.h index 192d3703..a0d99b69 100644 --- a/src/objects/ParticleObject.h +++ b/src/objects/ParticleObject.h @@ -1,6 +1,9 @@ #pragma once - #include "Placeable.h" +#include "AudioManager.h" + +#define MAX_PARTICLEOBJECTS 100 +#define MAX_AUDIOHYDRANTS 8 enum eParticleObjectType { @@ -26,13 +29,79 @@ enum eParticleObjectType POBJECT_CATALINAS_SHOTGUNFLASH, }; +enum eParticleObjectState +{ + POBJECTSTATE_INITIALISED = 0, + POBJECTSTATE_UPDATE_CLOSE, + POBJECTSTATE_UPDATE_FAR, + POBJECTSTATE_FREE, +}; + +enum tParticleType; +class CParticle; + class CParticleObject : CPlaceable { public: - static void AddObject(uint16 type, const CVector &pos, uint8 remove); - static void AddObject(uint16 type, const CVector &pos, float size, uint8 remove); - static void AddObject(uint16 type, const CVector &pos, const CVector &dir, float size, uint8 remove); - static void AddObject(uint16 type, const CVector &pos, const CVector &dir, float size, uint32, const RwRGBA &col, uint8 remove); - static void Initialise(); - static void UpdateAll(); + CParticleObject *m_pNext; + CParticleObject *m_pPrev; + CParticle *m_pParticle; + uint32 m_nRemoveTimer; + eParticleObjectType m_Type; + tParticleType m_ParticleType; + uint8 m_nNumEffectCycles; + uint8 m_nSkipFrames; + uint16 m_nFrameCounter; + uint16 m_nState; + char _pad0[2]; + CVector m_vecTarget; + float m_fRandVal; + float m_fSize; + CRGBA m_Color; + uint8 m_bRemove; + int8 m_nCreationChance; + char _pad1[2]; + + static CParticleObject *&pCloseListHead; + static CParticleObject *&pFarListHead; + static CParticleObject *&pUnusedListHead; + + CParticleObject(); + ~CParticleObject(); + + static void Initialise(void); + + static CParticleObject *AddObject(uint16 type, CVector const &pos, uint8 remove); + static CParticleObject *AddObject(uint16 type, CVector const &pos, float size, uint8 remove); + static CParticleObject *AddObject(uint16 type, CVector const &pos, CVector const &target, float size, uint8 remove); + static CParticleObject *AddObject(uint16 type, CVector const &pos, CVector const &target, float size, uint32 lifeTime, RwRGBA const &color, uint8 remove); + + void RemoveObject(void); + + static void UpdateAll(void); + void UpdateClose(void); + void UpdateFar(void); + + static bool SaveParticle(uint8 *buffer, uint32 *length); + static bool LoadParticle(uint8 *buffer, uint32 length); + + static void RemoveAllParticleObjects(void); + static void MoveToList(CParticleObject **from, CParticleObject **to, CParticleObject *obj); }; + +extern CParticleObject (&gPObjectArray)[MAX_PARTICLEOBJECTS]; + +class CAudioHydrant +{ +public: + int32 AudioEntity; + CParticleObject *pParticleObject; + + CAudioHydrant() : + AudioEntity(AEHANDLE_NONE), + pParticleObject(NULL) + { } + + static bool Add (CParticleObject *particleobject); + static void Remove(CParticleObject *particleobject); +};
\ No newline at end of file diff --git a/src/peds/Ped.cpp b/src/peds/Ped.cpp index b8f9f35b..7fcd6525 100644 --- a/src/peds/Ped.cpp +++ b/src/peds/Ped.cpp @@ -34,6 +34,10 @@ #include "Train.h" #include "TrafficLights.h" #include "PedRoutes.h" +#include "Sprite.h" +#include "RwHelper.h" +#include "Font.h" +#include "Text.h" WRAPPER void CPed::KillPedWithCar(CVehicle *veh, float impulse) { EAXJMP(0x4EC430); } WRAPPER void CPed::SpawnFlyingComponent(int, int8) { EAXJMP(0x4EB060); } @@ -81,64 +85,11 @@ CVector &vecPedTrainDoorAnimOffset = *(CVector*)0x62E054; CVector2D &CPed::ms_vec2DFleePosition = *(CVector2D*)0x6EDF70; -#ifndef FINAL -bool CPed::bUnusedFightThingOnPlayer = false; -#endif - void *CPed::operator new(size_t sz) { return CPools::GetPedPool()->New(); } void *CPed::operator new(size_t sz, int handle) { return CPools::GetPedPool()->New(handle); } void CPed::operator delete(void *p, size_t sz) { CPools::GetPedPool()->Delete((CPed*)p); } void CPed::operator delete(void *p, int handle) { CPools::GetPedPool()->Delete((CPed*)p); } -CPed::~CPed(void) -{ - CWorld::Remove(this); - CRadar::ClearBlipForEntity(BLIP_CHAR, CPools::GetPedPool()->GetIndex(this)); - if (bInVehicle && m_pMyVehicle){ - uint8 door_flag = GetCarDoorFlag(m_vehEnterType); - if (m_pMyVehicle->pDriver == this) - m_pMyVehicle->pDriver = nil; - else { - for (int i = 0; i < m_pMyVehicle->m_nNumMaxPassengers; i++) { - if (m_pMyVehicle->pPassengers[i] == this) - m_pMyVehicle->pPassengers[i] = nil; - } - } - if (m_nPedState == PED_EXIT_CAR || m_nPedState == PED_DRAG_FROM_CAR) - m_pMyVehicle->m_nGettingOutFlags &= ~door_flag; - bInVehicle = false; - m_pMyVehicle = nil; - }else if (m_nPedState == PED_ENTER_CAR || m_nPedState == PED_CARJACK){ - QuitEnteringCar(); - } - if (m_pFire) - m_pFire->Extinguish(); - CPopulation::UpdatePedCount(m_nPedType, true); - DMAudio.DestroyEntity(m_audioEntityId); -} - -void -CPed::FlagToDestroyWhenNextProcessed(void) -{ - bRemoveFromWorld = true; - if (!bInVehicle || !m_pMyVehicle) - return; - if (m_pMyVehicle->pDriver == this){ - m_pMyVehicle->pDriver = nil; - if (IsPlayer() && m_pMyVehicle->m_status != STATUS_WRECKED) - m_pMyVehicle->m_status = STATUS_ABANDONED; - }else{ - m_pMyVehicle->RemovePassenger(this); - } - bInVehicle = false; - m_pMyVehicle = nil; - if (CharCreatedBy == MISSION_CHAR) - m_nPedState = PED_DEAD; - else - m_nPedState = PED_NONE; - m_pVehicleAnim = nil; -} - static char ObjectiveText[34][28] = { "No Obj", "Wait on Foot", @@ -294,6 +245,107 @@ static char WaitStateText[21][16] = { "Finish Flee", }; + +#ifndef MASTER +int nDisplayDebugInfo = 0; +bool CPed::bUnusedFightThingOnPlayer = false; + +void +CPed::SwitchDebugDisplay(void) +{ + nDisplayDebugInfo = !nDisplayDebugInfo; +} + +void +CPed::DebugRenderOnePedText(void) +{ + if ((GetPosition() - TheCamera.GetPosition()).MagnitudeSqr() < 900.0f) { + float width, height; + RwV3d screenCoords; + CVector bitAbove = GetPosition(); + bitAbove.z += 2.0f; + if (CSprite::CalcScreenCoors(bitAbove, &screenCoords, &width, &height, true)) { + + float lineHeight = SCREEN_SCALE_Y(min(height/100.0f, 0.7f) * 22.0f); + + DefinedState(); + CFont::SetPropOn(); + CFont::SetBackgroundOn(); + + // Originally both of them were being divided by 60.0f. + float xScale = min(width / 190.0f, 0.7f); + float yScale = min(height / 80.0f, 0.7f); + + CFont::SetScale(SCREEN_SCALE_X(xScale), SCREEN_SCALE_Y(yScale)); + CFont::SetCentreOn(); + CFont::SetCentreSize(SCREEN_WIDTH); + CFont::SetJustifyOff(); + CFont::SetColor(CRGBA(255, 255, 0, 255)); + CFont::SetBackGroundOnlyTextOn(); + CFont::SetFontStyle(0); + AsciiToUnicode(StateText[m_nPedState], gUString); + CFont::PrintString(screenCoords.x, screenCoords.y, gUString); + AsciiToUnicode(ObjectiveText[m_objective], gUString); + CFont::PrintString(screenCoords.x, screenCoords.y + lineHeight, gUString); + AsciiToUnicode(PersonalityTypeText[m_pedStats->m_type], gUString); + CFont::PrintString(screenCoords.x, screenCoords.y + 2 * lineHeight, gUString); + AsciiToUnicode(WaitStateText[m_nWaitState], gUString); + CFont::PrintString(screenCoords.x, screenCoords.y + 3 * lineHeight, gUString); + DefinedState(); + } + } +} +#endif + +CPed::~CPed(void) +{ + CWorld::Remove(this); + CRadar::ClearBlipForEntity(BLIP_CHAR, CPools::GetPedPool()->GetIndex(this)); + if (bInVehicle && m_pMyVehicle){ + uint8 door_flag = GetCarDoorFlag(m_vehEnterType); + if (m_pMyVehicle->pDriver == this) + m_pMyVehicle->pDriver = nil; + else { + for (int i = 0; i < m_pMyVehicle->m_nNumMaxPassengers; i++) { + if (m_pMyVehicle->pPassengers[i] == this) + m_pMyVehicle->pPassengers[i] = nil; + } + } + if (m_nPedState == PED_EXIT_CAR || m_nPedState == PED_DRAG_FROM_CAR) + m_pMyVehicle->m_nGettingOutFlags &= ~door_flag; + bInVehicle = false; + m_pMyVehicle = nil; + }else if (m_nPedState == PED_ENTER_CAR || m_nPedState == PED_CARJACK){ + QuitEnteringCar(); + } + if (m_pFire) + m_pFire->Extinguish(); + CPopulation::UpdatePedCount(m_nPedType, true); + DMAudio.DestroyEntity(m_audioEntityId); +} + +void +CPed::FlagToDestroyWhenNextProcessed(void) +{ + bRemoveFromWorld = true; + if (!bInVehicle || !m_pMyVehicle) + return; + if (m_pMyVehicle->pDriver == this){ + m_pMyVehicle->pDriver = nil; + if (IsPlayer() && m_pMyVehicle->m_status != STATUS_WRECKED) + m_pMyVehicle->m_status = STATUS_ABANDONED; + }else{ + m_pMyVehicle->RemovePassenger(this); + } + bInVehicle = false; + m_pMyVehicle = nil; + if (CharCreatedBy == MISSION_CHAR) + m_nPedState = PED_DEAD; + else + m_nPedState = PED_NONE; + m_pVehicleAnim = nil; +} + CPed::CPed(uint32 pedType) : m_pedIK(this) { m_type = ENTITY_TYPE_PED; @@ -471,7 +523,7 @@ CPed::CPed(uint32 pedType) : m_pedIK(this) if ((CGeneral::GetRandomNumber() & 3) == 0) m_ped_flagD1 = true; - m_audioEntityId = DMAudio.CreateEntity(0, this); + m_audioEntityId = DMAudio.CreateEntity(AUDIOTYPE_PHYSICAL, this); DMAudio.SetEntityStatus(m_audioEntityId, 1); m_fearFlags = CPedType::GetThreats(m_nPedType); m_threatEntity = nil; @@ -2095,6 +2147,12 @@ CPed::SetupLighting(void) ActivateDirectional(); SetAmbientColoursForPedsCarsAndObjects(); +#ifndef MASTER + // Originally this was being called through iteration of Sectors, but putting it here is better. + if (nDisplayDebugInfo && !IsPlayer()) + DebugRenderOnePedText(); +#endif + if (bRenderScorched) { WorldReplaceNormalLightsWithScorched(Scene.world, 0.1f); } else { @@ -4472,7 +4530,7 @@ CPed::StartFightAttack(uint8 buttonPressure) animAssoc->SetFinishCallback(FinishFightMoveCB, this); m_fightUnk2 = 0; m_takeAStepAfterAttack = false; -#ifndef FINAL +#ifndef MASTER m_takeAStepAfterAttack = IsPlayer() && bUnusedFightThingOnPlayer; #endif @@ -4567,7 +4625,7 @@ CPed::LoadFightData(void) // Actually GetLocalDirectionTo(Turn/Look) int -CPed::GetLocalDirection(CVector2D &posOffset) +CPed::GetLocalDirection(CVector2D const &posOffset) { float direction; @@ -4804,7 +4862,7 @@ CPed::SetFlee(CEntity* fleeFrom, int time) } void -CPed::SetFlee(CVector2D &from, int time) +CPed::SetFlee(CVector2D const &from, int time) { if (CTimer::GetTimeInMilliseconds() < m_nPedStateTimer || !IsPedInControl() || bKindaStayInSamePlace) return; @@ -5186,7 +5244,8 @@ CPed::CollideWithPed(CPed *collideWith) animAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_FIGHT_PPUNCH, 8.0f); animAssoc->flags |= ASSOC_FADEOUTWHENDONE; if (!heIsMissionChar) { - int direction = collideWith->GetLocalDirection(CVector2D(posDiff.x, posDiff.y)); + CVector2D posDiff2D(posDiff); + int direction = collideWith->GetLocalDirection(posDiff2D); collideWith->StartFightDefend(direction, 4, 5); } } @@ -7273,61 +7332,63 @@ CPed::GetNearestPassengerDoor(CVehicle *veh, CVector &posToOpen) CVehicleModelInfo *vehModel = (CVehicleModelInfo*)CModelInfo::GetModelInfo(veh->m_modelIndex); - if (veh->m_modelIndex > MI_RHINO || veh->m_modelIndex != MI_BUS) { + switch (veh->m_modelIndex) { + case MI_BUS: + m_vehEnterType = CAR_DOOR_RF; + posToOpen = GetPositionToOpenCarDoor(veh, CAR_DOOR_RF); + return true; + case MI_RHINO: + default: + break; + } - CVector2D rfPosDist(999.0f, 999.0f); - CVector2D lrPosDist(999.0f, 999.0f); - CVector2D rrPosDist(999.0f, 999.0f); + CVector2D rfPosDist(999.0f, 999.0f); + CVector2D lrPosDist(999.0f, 999.0f); + CVector2D rrPosDist(999.0f, 999.0f); - if (!veh->pPassengers[0] - && !(veh->m_nGettingInFlags & CAR_DOOR_FLAG_RF) - && veh->IsRoomForPedToLeaveCar(CAR_DOOR_RF, nil)) { + if (!veh->pPassengers[0] + && !(veh->m_nGettingInFlags & CAR_DOOR_FLAG_RF) + && veh->IsRoomForPedToLeaveCar(CAR_DOOR_RF, nil)) { - rfPos = GetPositionToOpenCarDoor(veh, CAR_DOOR_RF); + rfPos = GetPositionToOpenCarDoor(veh, CAR_DOOR_RF); + canEnter = true; + rfPosDist = rfPos - GetPosition(); + } + if (vehModel->m_numDoors == 4) { + if (!veh->pPassengers[1] + && !(veh->m_nGettingInFlags & CAR_DOOR_FLAG_LR) + && veh->IsRoomForPedToLeaveCar(CAR_DOOR_LR, nil)) { + lrPos = GetPositionToOpenCarDoor(veh, CAR_DOOR_LR); canEnter = true; - rfPosDist = rfPos - GetPosition(); - } - if (vehModel->m_numDoors == 4) { - if (!veh->pPassengers[1] - && !(veh->m_nGettingInFlags & CAR_DOOR_FLAG_LR) - && veh->IsRoomForPedToLeaveCar(CAR_DOOR_LR, nil)) { - lrPos = GetPositionToOpenCarDoor(veh, CAR_DOOR_LR); - canEnter = true; - lrPosDist = lrPos - GetPosition(); - } - if (!veh->pPassengers[2] - && !(veh->m_nGettingInFlags & CAR_DOOR_FLAG_RR) - && veh->IsRoomForPedToLeaveCar(CAR_DOOR_RR, nil)) { - rrPos = GetPositionToOpenCarDoor(veh, CAR_DOOR_RR); - canEnter = true; - rrPosDist = rrPos - GetPosition(); - } - - // When the door we should enter is blocked by some object. - if (!canEnter) - veh->ShufflePassengersToMakeSpace(); + lrPosDist = lrPos - GetPosition(); } - - CVector2D nextToCompare = rfPosDist; - posToOpen = rfPos; - m_vehEnterType = CAR_DOOR_RF; - if (lrPosDist.MagnitudeSqr() < nextToCompare.MagnitudeSqr()) { - m_vehEnterType = CAR_DOOR_LR; - posToOpen = lrPos; - nextToCompare = lrPosDist; + if (!veh->pPassengers[2] + && !(veh->m_nGettingInFlags & CAR_DOOR_FLAG_RR) + && veh->IsRoomForPedToLeaveCar(CAR_DOOR_RR, nil)) { + rrPos = GetPositionToOpenCarDoor(veh, CAR_DOOR_RR); + canEnter = true; + rrPosDist = rrPos - GetPosition(); } - if (rrPosDist.MagnitudeSqr() < nextToCompare.MagnitudeSqr()) { - m_vehEnterType = CAR_DOOR_RR; - posToOpen = rrPos; - } - return canEnter; + // When the door we should enter is blocked by some object. + if (!canEnter) + veh->ShufflePassengersToMakeSpace(); + } - } else { - m_vehEnterType = CAR_DOOR_RF; - posToOpen = GetPositionToOpenCarDoor(veh, CAR_DOOR_RF); - return true; + CVector2D nextToCompare = rfPosDist; + posToOpen = rfPos; + m_vehEnterType = CAR_DOOR_RF; + if (lrPosDist.MagnitudeSqr() < nextToCompare.MagnitudeSqr()) { + m_vehEnterType = CAR_DOOR_LR; + posToOpen = lrPos; + nextToCompare = lrPosDist; + } + + if (rrPosDist.MagnitudeSqr() < nextToCompare.MagnitudeSqr()) { + m_vehEnterType = CAR_DOOR_RR; + posToOpen = rrPos; } + return canEnter; } int @@ -7795,7 +7856,7 @@ STARTPATCHES InjectHook(0x4E5A10, &CPed::Say, PATCH_JUMP); InjectHook(0x4D58D0, &CPed::SetWaitState, PATCH_JUMP); InjectHook(0x4D1D70, (void (CPed::*)(CEntity*, int)) &CPed::SetFlee, PATCH_JUMP); - InjectHook(0x4D1C40, (void (CPed::*)(CVector2D&, int)) &CPed::SetFlee, PATCH_JUMP); + InjectHook(0x4D1C40, (void (CPed::*)(CVector2D const &, int)) &CPed::SetFlee, PATCH_JUMP); InjectHook(0x4EB9A0, &CPed::CollideWithPed, PATCH_JUMP); InjectHook(0x433490, &CPed::CreateDeadPedMoney, PATCH_JUMP); InjectHook(0x433660, &CPed::CreateDeadPedWeaponPickups, PATCH_JUMP); diff --git a/src/peds/Ped.h b/src/peds/Ped.h index 82423529..3085f74d 100644 --- a/src/peds/Ped.h +++ b/src/peds/Ped.h @@ -574,12 +574,12 @@ public: void StartFightAttack(uint8); void SetWaitState(eWaitState, void*); bool FightStrike(CVector&); - int GetLocalDirection(CVector2D&); + int GetLocalDirection(CVector2D const &); void StartFightDefend(uint8, uint8, uint8); void PlayHitSound(CPed*); void SetFall(int, AnimationId, uint8); void SetFlee(CEntity*, int); - void SetFlee(CVector2D&, int); + void SetFlee(CVector2D const &, int); void RemoveInCarAnims(void); void CollideWithPed(CPed*); void SetDirectionToWalkAroundObject(CEntity*); @@ -698,7 +698,9 @@ public: static CVector2D &ms_vec2DFleePosition; static CPedAudioData (&CommentWaitTime)[38]; -#ifndef FINAL +#ifndef MASTER + static void SwitchDebugDisplay(void); + void DebugRenderOnePedText(void); static bool bUnusedFightThingOnPlayer; #endif }; diff --git a/src/render/Draw.cpp b/src/render/Draw.cpp index beb3443d..862fc024 100644 --- a/src/render/Draw.cpp +++ b/src/render/Draw.cpp @@ -11,6 +11,7 @@ float CDraw::ms_fAspectRatio = DEFAULT_ASPECT_RATIO; float &CDraw::ms_fNearClipZ = *(float*)0x8E2DC4; float &CDraw::ms_fFarClipZ = *(float*)0x9434F0; float &CDraw::ms_fFOV = *(float*)0x5FBC6C; +float &CDraw::ms_fLODDistance = *(float*)0x8F2C30; uint8 &CDraw::FadeValue = *(uint8*)0x95CD68; uint8 &CDraw::FadeRed = *(uint8*)0x95CD90; diff --git a/src/render/Draw.h b/src/render/Draw.h index 75b2b75f..50e1e294 100644 --- a/src/render/Draw.h +++ b/src/render/Draw.h @@ -16,7 +16,8 @@ private: static float &ms_fNearClipZ; static float &ms_fFarClipZ; static float &ms_fFOV; - static float ms_fLODDistance; // unused +public: + static float &ms_fLODDistance; // set but unused? #ifdef ASPECT_RATIO_SCALE // we use this variable to scale a lot of 2D elements @@ -24,7 +25,6 @@ private: static float ms_fAspectRatio; #endif -public: static uint8 &FadeValue; static uint8 &FadeRed; static uint8 &FadeGreen; diff --git a/src/render/Particle.cpp b/src/render/Particle.cpp index 23e23f93..e2db55c7 100644 --- a/src/render/Particle.cpp +++ b/src/render/Particle.cpp @@ -1261,7 +1261,7 @@ void CParticle::Update() nil, particle->m_fSize, color, particle->m_nRotationStep, 0, 0, 0); - PlayOneShotScriptObject(_SOUND_BULLET_SHELL_HIT_GROUND_1, particle->m_vecPosition); + PlayOneShotScriptObject(_SCRSOUND_BULLET_SHELL_HIT_GROUND_1, particle->m_vecPosition); } break; @@ -1280,7 +1280,7 @@ void CParticle::Update() nil, particle->m_fSize, color, 0, 0, 0, 0); - PlayOneShotScriptObject(_SOUND_BULLET_SHELL_HIT_GROUND_2, particle->m_vecPosition); + PlayOneShotScriptObject(_SCRSOUND_BULLET_SHELL_HIT_GROUND_2, particle->m_vecPosition); } break; @@ -1410,13 +1410,11 @@ void CParticle::Update() if ( particle->m_fCurrentZRadius != 0.0f ) { - int32 nSinCosIndex = particle->m_nCurrentZRotation % (SIN_COS_TABLE_SIZE - 1); + int32 nRot = particle->m_nCurrentZRotation % (SIN_COS_TABLE_SIZE - 1); - float fX = (m_CosTable[nSinCosIndex] - m_SinTable[nSinCosIndex]) - * particle->m_fCurrentZRadius; + float fX = (Cos(nRot) - Sin(nRot)) * particle->m_fCurrentZRadius; - float fY = (m_SinTable[nSinCosIndex] + m_CosTable[nSinCosIndex]) - * particle->m_fCurrentZRadius; + float fY = (Sin(nRot) + Cos(nRot)) * particle->m_fCurrentZRadius; moveStep -= particle->m_vecParticleMovementOffset; diff --git a/src/render/Particle.h b/src/render/Particle.h index eaacf2f5..4e41ea2d 100644 --- a/src/render/Particle.h +++ b/src/render/Particle.h @@ -60,6 +60,8 @@ public: static float (&m_SinTable)[SIN_COS_TABLE_SIZE]; static float (&m_CosTable)[SIN_COS_TABLE_SIZE]; + static float Sin(int32 value) { return m_SinTable[value]; } + static float Cos(int32 value) { return m_CosTable[value]; } static void ReloadConfig(); static void Initialise(); diff --git a/src/render/WaterLevel.cpp b/src/render/WaterLevel.cpp index 247b9f3d..48e8f83b 100644 --- a/src/render/WaterLevel.cpp +++ b/src/render/WaterLevel.cpp @@ -731,10 +731,10 @@ CWaterLevel::RenderWater() float fAngle = CGeneral::GetRandomNumberInRange(90.0f, 150.0f); - int32 nSinCosIdx = CGeneral::GetRandomNumber() % CParticle::SIN_COS_TABLE_SIZE-1; + int32 nRot = CGeneral::GetRandomNumber() % CParticle::SIN_COS_TABLE_SIZE-1; - float fCos = CParticle::m_CosTable[nSinCosIdx]; - float fSin = CParticle::m_SinTable[nSinCosIdx]; + float fCos = CParticle::Cos(nRot); + float fSin = CParticle::Sin(nRot); vecPos.x += (fCos - fSin) * fAngle; vecPos.y += (fSin + fCos) * fAngle; diff --git a/src/skel/skeleton.cpp b/src/skel/skeleton.cpp index ecc0083d..73dd8bf8 100644 --- a/src/skel/skeleton.cpp +++ b/src/skel/skeleton.cpp @@ -15,6 +15,8 @@ static RwBool DefaultVideoMode = TRUE; +bool TurnOnAnimViewer = false; + //RsGlobalType RsGlobal; RsGlobalType &RsGlobal = *(RsGlobalType*)0x8F4360; @@ -144,7 +146,14 @@ rsPreInitCommandLine(RwChar *arg) return TRUE; } +#ifndef MASTER + if (!strcmp(arg, RWSTRING("-animviewer"))) + { + TurnOnAnimViewer = TRUE; + return TRUE; + } +#endif return FALSE; } diff --git a/src/skel/skeleton.h b/src/skel/skeleton.h index e22c1325..e357905d 100644 --- a/src/skel/skeleton.h +++ b/src/skel/skeleton.h @@ -79,8 +79,11 @@ enum RsEvent rsPADANALOGUERIGHTRESET, rsPREINITCOMMANDLINE, rsACTIVATE, + rsANIMVIEWER, }; +extern bool TurnOnAnimViewer; + typedef enum RsEvent RsEvent; typedef RsEventStatus (*RsInputEventHandler)(RsEvent event, void *param); diff --git a/src/skel/win/win.cpp b/src/skel/win/win.cpp index 04b89803..d4eb71be 100644 --- a/src/skel/win/win.cpp +++ b/src/skel/win/win.cpp @@ -94,6 +94,7 @@ static psGlobalType &PsGlobal = *(psGlobalType*)0x72CF60; #include "Game.h" #include "PCSave.h" #include "Sprite2d.h" +#include "AnimViewer.h" VALIDATE_SIZE(psGlobalType, 0x28); @@ -976,9 +977,9 @@ MainWndProc(HWND window, UINT message, WPARAM wParam, LPARAM lParam) RECT rect; /* redraw window */ - if (RwInitialised && gGameState == GS_PLAYING_GAME) + if (RwInitialised && (gGameState == GS_PLAYING_GAME || gGameState == GS_ANIMVIEWER)) { - RsEventHandler(rsIDLE, (void *)TRUE); + RsEventHandler((gGameState == GS_PLAYING_GAME ? rsIDLE : rsANIMVIEWER), (void *)TRUE); } /* Manually resize window */ @@ -1917,16 +1918,23 @@ _WinMain(HINSTANCE instance, SetErrorMode(SEM_FAILCRITICALERRORS); - + if (!TurnOnAnimViewer) { #ifdef NO_MOVIES - gGameState = GS_INIT_FRONTEND; - TRACE("gGameState = GS_INIT_FRONTEND"); - - LoadingScreen(nil, nil, "loadsc0"); - if ( !CGame::InitialiseOnceAfterRW() ) - RsGlobal.quit = TRUE; -#endif - + gGameState = GS_INIT_FRONTEND; + TRACE("gGameState = GS_INIT_FRONTEND"); + + LoadingScreen(nil, nil, "loadsc0"); + if (!CGame::InitialiseOnceAfterRW()) + RsGlobal.quit = TRUE; +#endif + } else { +#ifndef MASTER + CAnimViewer::Initialise(); + FrontEndMenuManager.m_bGameNotLoaded = false; + gGameState = GS_ANIMVIEWER; + TurnOnAnimViewer = false; +#endif + } while ( TRUE ) { @@ -2114,6 +2122,18 @@ _WinMain(HINSTANCE instance, } break; } +#ifndef MASTER + case GS_ANIMVIEWER: + { + float ms = (float)CTimer::GetCurrentTimeInCycles() / (float)CTimer::GetCyclesPerMillisecond(); + if (RwInitialised) + { + if (!CMenuManager::m_PrefsFrameLimiter || (1000.0f / (float)RsGlobal.maxFPS) < ms) + RsEventHandler(rsANIMVIEWER, (void*)TRUE); + } + break; + } +#endif } } else @@ -2158,6 +2178,8 @@ _WinMain(HINSTANCE instance, { if ( gGameState == GS_PLAYING_GAME ) CGame::ShutDown(); + else if ( gGameState == GS_ANIMVIEWER ) + CAnimViewer::Shutdown(); CTimer::Stop(); @@ -2180,6 +2202,8 @@ _WinMain(HINSTANCE instance, if ( gGameState == GS_PLAYING_GAME ) CGame::ShutDown(); + else if ( gGameState == GS_ANIMVIEWER ) + CAnimViewer::Shutdown(); DMAudio.Terminate(); diff --git a/src/skel/win/win.h b/src/skel/win/win.h index 69d38164..8c32e57d 100644 --- a/src/skel/win/win.h +++ b/src/skel/win/win.h @@ -17,6 +17,7 @@ enum eGameState GS_FRONTEND, GS_INIT_PLAYING_GAME, GS_PLAYING_GAME, + GS_ANIMVIEWER, }; enum eWinVersion diff --git a/src/vehicles/Vehicle.cpp b/src/vehicles/Vehicle.cpp index 5d63b4df..775689f7 100644 --- a/src/vehicles/Vehicle.cpp +++ b/src/vehicles/Vehicle.cpp @@ -92,7 +92,7 @@ CVehicle::CVehicle(uint8 CreatedBy) m_nLastWeaponDamage = -1; field_220 = 0.0; field_21C = field_220; - m_audioEntityId = DMAudio.CreateEntity(0, this); + m_audioEntityId = DMAudio.CreateEntity(AUDIOTYPE_PHYSICAL, this); if(m_audioEntityId) DMAudio.SetEntityStatus(m_audioEntityId, true); m_nRadioStation = CGeneral::GetRandomNumber() % USERTRACK; diff --git a/src/weapons/Weapon.cpp b/src/weapons/Weapon.cpp index f83f2271..3f511358 100644 --- a/src/weapons/Weapon.cpp +++ b/src/weapons/Weapon.cpp @@ -11,6 +11,7 @@ WRAPPER void CWeapon::FireFromCar(CAutomobile *car, bool left) { EAXJMP(0x55C940 WRAPPER void CWeapon::AddGunshell(CEntity*, CVector const&, CVector2D const&, float) { EAXJMP(0x55F770); } WRAPPER void CWeapon::Update(int32 audioEntity) { EAXJMP(0x563A10); } WRAPPER void CWeapon::DoTankDoomAiming(CEntity *playerVehicle, CEntity *playerPed, CVector *start, CVector *end) { EAXJMP(0x563200); } +WRAPPER void CWeapon::InitialiseWeapons(void) { EAXJMP(0x55C2D0); } void CWeapon::Initialise(eWeaponType type, int ammo) diff --git a/src/weapons/Weapon.h b/src/weapons/Weapon.h index 4916284f..2f277c62 100644 --- a/src/weapons/Weapon.h +++ b/src/weapons/Weapon.h @@ -72,5 +72,6 @@ public: bool IsType2Handed(void); static void DoTankDoomAiming(CEntity *playerVehicle, CEntity *playerPed, CVector *start, CVector *end); bool HitsGround(CEntity* holder, CVector* firePos, CEntity* aimingTo); + static void InitialiseWeapons(void); }; static_assert(sizeof(CWeapon) == 0x18, "CWeapon: error"); |