diff options
author | aap <aap@papnet.eu> | 2019-08-15 14:39:30 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-08-15 14:39:30 +0200 |
commit | 88fcac85d32e5bef978a3a1e4d3ace0fcce09815 (patch) | |
tree | 53c3fb8df01552a4742ef96f418d469677409a9c | |
parent | Merge pull request #189 from Nick007J/master (diff) | |
parent | fix (diff) | |
download | re3-88fcac85d32e5bef978a3a1e4d3ace0fcce09815.tar re3-88fcac85d32e5bef978a3a1e4d3ace0fcce09815.tar.gz re3-88fcac85d32e5bef978a3a1e4d3ace0fcce09815.tar.bz2 re3-88fcac85d32e5bef978a3a1e4d3ace0fcce09815.tar.lz re3-88fcac85d32e5bef978a3a1e4d3ace0fcce09815.tar.xz re3-88fcac85d32e5bef978a3a1e4d3ace0fcce09815.tar.zst re3-88fcac85d32e5bef978a3a1e4d3ace0fcce09815.zip |
-rw-r--r-- | src/audio/AudioManager.cpp | 61 | ||||
-rw-r--r-- | src/audio/AudioManager.h | 47 | ||||
-rw-r--r-- | src/audio/AudioScriptObject.h | 250 | ||||
-rw-r--r-- | src/audio/DMAudio.cpp | 402 | ||||
-rw-r--r-- | src/audio/DMAudio.h | 94 | ||||
-rw-r--r-- | src/audio/MusicManager.cpp | 41 | ||||
-rw-r--r-- | src/audio/MusicManager.h | 9 | ||||
-rw-r--r-- | src/audio/sampman.cpp | 64 | ||||
-rw-r--r-- | src/audio/sampman.h | 37 | ||||
-rw-r--r-- | src/control/Replay.cpp | 4 | ||||
-rw-r--r-- | src/control/Script.cpp | 14 | ||||
-rw-r--r-- | src/core/common.h | 18 | ||||
-rw-r--r-- | src/objects/ParticleObject.cpp | 1127 | ||||
-rw-r--r-- | src/objects/ParticleObject.h | 83 | ||||
-rw-r--r-- | src/peds/Ped.cpp | 2 | ||||
-rw-r--r-- | src/render/Particle.cpp | 12 | ||||
-rw-r--r-- | src/render/Particle.h | 2 | ||||
-rw-r--r-- | src/render/WaterLevel.cpp | 6 | ||||
-rw-r--r-- | src/vehicles/Vehicle.cpp | 2 |
19 files changed, 1983 insertions, 292 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/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/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/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 2a62288d..d0ceedff 100644 --- a/src/peds/Ped.cpp +++ b/src/peds/Ped.cpp @@ -471,7 +471,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; 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/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; |