diff --git a/Client/game_sa/Audio/CAudioZonesSA.cpp b/Client/game_sa/Audio/CAudioZonesSA.cpp new file mode 100644 index 00000000000..c3253fd15a3 --- /dev/null +++ b/Client/game_sa/Audio/CAudioZonesSA.cpp @@ -0,0 +1,49 @@ +/***************************************************************************** +* +* PROJECT: Multi Theft Auto +* LICENSE: See LICENSE in the top level directory +* FILE: game_sa/Audio/CAudioZonesSA.cpp +* PURPOSE: Source file for audio zones class +* +* Multi Theft Auto is available from https://www.multitheftauto.com/ +* +*****************************************************************************/ +#include "StdInc.h" +#include "CAudioZonesSA.h" + +// 0xB6DC6C CAudioZones::m_aActiveBoxes +// 0xB6DC94 CAudioZones::m_aActiveSpheres +// 0xB6DCBC CAudioZones::m_NumActiveBoxes +// 0xB6DCC0 CAudioZones::m_NumActiveSpheres +// 0xB6DCC4 CAudioZones::m_NumBoxes +// 0xB6DCC8 CAudioZones::m_NumSpheres +// 0xB6EBB0 CAudioZones::m_aSpheres + +#define VAR_CAudioZonesSA__m_aBoxes 0xB6DCD0 + +CAudioZoneBoxSAInterface ( * CAudioZonesSA::m_aBoxes ) [100] = reinterpret_cast < decltype ( CAudioZonesSA::m_aBoxes ) > ( VAR_CAudioZonesSA__m_aBoxes ); + +void CAudioZonesSA::Init ( void ) +{ + // 0x5081A0 void __cdecl CAudioZones::Init(void) +} + +void CAudioZonesSA::RegisterAudioBox ( const char * szZoneName, int16_t wBank, bool bEnabled, float minX, float minY, float minZ, float maxX, float maxY, float maxZ ) +{ + // 0x508240 void __cdecl CAudioZones::RegisterAudioBox(const char *, int16_t, bool, float, float, float, float, float, float) +} + +void CAudioZonesSA::RegisterAudioSphere ( const char * szZoneName, int16_t wBank, bool bEnabled, float centerX, float centerY, float centerZ ) +{ + // 0x5081C0 void __cdecl CAudioZones::RegisterAudioSphere(const char *, in16_t, bool, float, float, float, float) +} + +void CAudioZonesSA::SwitchAudioZone ( const char * szZoneName, bool bEnabled ) +{ + // 0x508320 void __cdecl CAudioZones::SwitchAudioZone(const char *, bool) +} + +void CAudioZonesSA::Update ( bool bForced ) +{ + // 0x5083C0 CAudioZones::Update(bool) +} diff --git a/Client/game_sa/Audio/CAudioZonesSA.h b/Client/game_sa/Audio/CAudioZonesSA.h new file mode 100644 index 00000000000..8bb6abe3e11 --- /dev/null +++ b/Client/game_sa/Audio/CAudioZonesSA.h @@ -0,0 +1,47 @@ +/***************************************************************************** +* +* PROJECT: Multi Theft Auto +* LICENSE: See LICENSE in the top level directory +* FILE: game_sa/Audio/CAudioZonesSA.h +* PURPOSE: Header file for audio zones class +* +* Multi Theft Auto is available from https://www.multitheftauto.com/ +* +*****************************************************************************/ +#pragma once + +#include + +struct CAudioZoneBoxSAInterface +{ + char szName[8]; // + 0x00 + int16_t wBank; // + 0x08 + bool bEnabled; // + 0x0A + int8_t field_B; + uint16_t wMinX; // + 0x0C + uint16_t wMinY; // + 0x0E + uint16_t wMinZ; // + 0x10 + uint16_t wMaxX; // + 0x12 + uint16_t wMaxY; // + 0x14 + uint16_t wMaxZ; // + 0x16 +}; +static_assert(sizeof(CAudioZoneBoxSAInterface) == 0x18, "Invalid size of CAudioZoneBoxSAInterface"); + +struct CAudioZoneSphereSAInterface +{ + +}; +// static_assert(sizeof(CAudioZoneSphereSAInterface) == 0x18, "Invalid size of CAudioZoneSphereSAInterface"); + +class CAudioZonesSA +{ +public: + static void Init ( void ); + static void RegisterAudioBox ( const char * szZoneName, int16_t wBank, bool bEnabled, float minX, float minY, float minZ, float maxX, float maxY, float maxZ ); + static void RegisterAudioSphere ( const char * szZoneName, int16_t wBank, bool bEnabled, float centerX, float centerY, float centerZ ); + static void SwitchAudioZone ( const char * szZoneName, bool bEnabled ); + static void Update ( bool bForced ); + +public: + static CAudioZoneBoxSAInterface ( *m_aBoxes ) [100]; +}; diff --git a/Client/game_sa/CAESoundManagerSA.h b/Client/game_sa/CAESoundManagerSA.h index 270941d2247..440dda8cf90 100644 --- a/Client/game_sa/CAESoundManagerSA.h +++ b/Client/game_sa/CAESoundManagerSA.h @@ -14,10 +14,26 @@ #define CLASS_CAESoundManager 0xB62CB0 +#pragma pack(push, 1) class CAESoundManagerSAInterface { - + int16_t m_wNumAvailableChannels; // + 0x0000 // = CAEAudioHardware::GetNumAvailableChannels(...), [10, 300] + int16_t m_wChannel; // + 0x0002 // = CAEAudioHardware::AllocateChannels(...), could be -1 + CAESound m_aSound [300]; // + 0x0004 + int16_t * m_aChannelSoundTable; // + 0x87F4 // = new short[m_wNumAvailableChannels] + int16_t * m_aChannelSoundPosition; // + 0x87F8 // = new short[m_wNumAvailableChannels] + int16_t * m_aChannelSoundUncancellable; // + 0x87FC // = new short[m_wNumAvailableChannels] + int16_t m_wSoundLength [300]; // + 0x8800 // = -1 (0xFFFF) when initialized + int16_t m_wSoundLoopStartTime [300]; // + 0x8A58 // = -1 (0xFFFF) when initialized + uint32_t m_uiUpdateTime; // + 0x8CB0 + int8_t m_bPauseTimeInUse; // + 0x8CB4 + int8_t m_bPaused; // + 0x8CB5 + int8_t field_8CB6; + int8_t field_8CB7; + uint32_t m_uiPauseUpdateTime; // + 0x8CB8 }; +#pragma pack(pop) +static_assert(sizeof(CAESoundManagerSAInterface) == 0x8CBC, "Invalid size for CAESoundManagerSAInterface"); class CAESoundManagerSA : public CAESoundManager { diff --git a/Client/game_sa/CAudioEngineSA.cpp b/Client/game_sa/CAudioEngineSA.cpp index d75d9e8a0ae..1adc4520970 100644 --- a/Client/game_sa/CAudioEngineSA.cpp +++ b/Client/game_sa/CAudioEngineSA.cpp @@ -492,7 +492,7 @@ void CAudioEngineSA::ResetWorldSounds ( void ) m_DisabledWorldSounds = CRanges (); } -void CAudioEngineSA::SetWorldSoundHandler ( WorldSoundHandler * pHandler ) +void CAudioEngineSA::SetWorldSoundHandler ( WorldSoundHandler pHandler ) { m_pWorldSoundHandler = pHandler; } @@ -502,8 +502,13 @@ bool CAudioEngineSA::OnWorldSound ( CAESound* pAESound ) if ( !IsWorldSoundEnabled ( pAESound->usGroup, pAESound->usIndex ) ) return false; - if ( m_pWorldSoundHandler ) - m_pWorldSoundHandler ( pAESound->usGroup, pAESound->usIndex ); + if ( m_pWorldSoundHandler ) { + bool bCanceled = !m_pWorldSoundHandler ( pAESound->usGroup, pAESound->usIndex, pAESound->pGameEntity, pAESound->m_vCurrPosn ); + + if ( bCanceled ) { + return false; + } + } return true; } diff --git a/Client/game_sa/CAudioEngineSA.h b/Client/game_sa/CAudioEngineSA.h index 4ba7eb9434f..d583d29124a 100644 --- a/Client/game_sa/CAudioEngineSA.h +++ b/Client/game_sa/CAudioEngineSA.h @@ -113,7 +113,7 @@ class CAESound short m_wPlayingState; // +104 char unk6[2]; // +106 float m_fSoundHeadRoom; // +108 - short unk7; // +112 + short m_wSoundLength; // +112 short unk8; // +114 }; @@ -145,7 +145,7 @@ class CAudioEngineSA : public CAudioEngine VOID SetWorldSoundEnabled ( uint uiGroup, uint uiIndex, bool bEnabled, bool bImmediate ); bool IsWorldSoundEnabled ( uint uiGroup, uint uiIndex ); void ResetWorldSounds ( void ); - void SetWorldSoundHandler ( WorldSoundHandler * pHandler ); + void SetWorldSoundHandler ( WorldSoundHandler pHandler ); void ReportBulletHit ( CEntity * pEntity, unsigned char ucSurfaceType, CVector * pvecPosition, float f_2 ); void ReportWeaponEvent ( int iEvent, eWeaponType weaponType, CPhysical * pPhysical ); @@ -153,14 +153,14 @@ class CAudioEngineSA : public CAudioEngine bool OnWorldSound ( CAESound* pAESound ); private: - bool m_bRadioOn; - bool m_bRadioMuted; - unsigned char m_ucRadioChannel; - bool m_bAmbientSoundsPaused; - bool m_bAmbientGeneralEnabled; - bool m_bAmbientGunfireEnabled; - CRanges m_DisabledWorldSounds; - WorldSoundHandler* m_pWorldSoundHandler; + bool m_bRadioOn; + bool m_bRadioMuted; + unsigned char m_ucRadioChannel; + bool m_bAmbientSoundsPaused; + bool m_bAmbientGeneralEnabled; + bool m_bAmbientGunfireEnabled; + CRanges m_DisabledWorldSounds; + WorldSoundHandler m_pWorldSoundHandler; CAudioEngineSAInterface * m_pInterface; }; diff --git a/Client/mods/deathmatch/logic/CClientGame.cpp b/Client/mods/deathmatch/logic/CClientGame.cpp index b964cb4e35a..ecab174b629 100644 --- a/Client/mods/deathmatch/logic/CClientGame.cpp +++ b/Client/mods/deathmatch/logic/CClientGame.cpp @@ -288,6 +288,7 @@ CClientGame::CClientGame ( bool bLocalPlay ) g_pGame->SetPreWeaponFireHandler ( CClientGame::PreWeaponFire ); g_pGame->SetPostWeaponFireHandler ( CClientGame::PostWeaponFire ); g_pGame->SetTaskSimpleBeHitHandler ( CClientGame::StaticTaskSimpleBeHitHandler ); + g_pGame->GetAudio ()->SetWorldSoundHandler ( CClientGame::StaticWorldSoundHandler ); g_pCore->SetMessageProcessor ( CClientGame::StaticProcessMessage ); g_pCore->GetKeyBinds ()->SetKeyStrokeHandler ( CClientGame::StaticKeyStrokeHandler ); g_pCore->GetKeyBinds ()->SetCharacterKeyHandler ( CClientGame::StaticCharacterKeyHandler ); @@ -2925,8 +2926,10 @@ void CClientGame::AddBuiltInEvents ( void ) // Misc events m_Events.AddEvent ( "onClientFileDownloadComplete", "fileName, success", NULL, false ); - + m_Events.AddEvent ( "onClientWeaponFire", "ped, x, y, z", NULL, false ); + + m_Events.AddEvent ( "onClientWorldSound", "group, index, x, y, z", NULL, false ); } @@ -6370,11 +6373,6 @@ void CClientGame::SetDevelopmentMode ( bool bEnable, bool bEnableWeb ) { m_bDevelopmentMode = bEnable; - if ( m_bDevelopmentMode ) - g_pGame->GetAudio ()->SetWorldSoundHandler ( CClientGame::StaticWorldSoundHandler ); - else - g_pGame->GetAudio ()->SetWorldSoundHandler ( NULL ); - if ( g_pCore->IsWebCoreLoaded() ) g_pCore->GetWebCore()->SetTestModeEnabled ( bEnableWeb ); } @@ -6387,9 +6385,9 @@ void CClientGame::SetDevelopmentMode ( bool bEnable, bool bEnableWeb ) // Handle callback from CAudioSA when a world sound is played // ////////////////////////////////////////////////////////////////// -void CClientGame::StaticWorldSoundHandler ( uint uiGroup, uint uiIndex ) +bool CClientGame::StaticWorldSoundHandler ( uint uiGroup, uint uiIndex, CEntitySAInterface* pEntityInterface, const CVector& vecPosition ) { - g_pClientGame->WorldSoundHandler ( uiGroup, uiIndex ); + return g_pClientGame->WorldSoundHandler ( uiGroup, uiIndex, pEntityInterface, vecPosition ); } @@ -6400,10 +6398,30 @@ void CClientGame::StaticWorldSoundHandler ( uint uiGroup, uint uiIndex ) // Handle callback from CAudioSA when a world sound is played // ////////////////////////////////////////////////////////////////// -void CClientGame::WorldSoundHandler ( uint uiGroup, uint uiIndex ) +bool CClientGame::WorldSoundHandler ( uint uiGroup, uint uiIndex, CEntitySAInterface* pEntityInterface, const CVector& vecPosition ) { if ( m_bShowSound ) m_pScriptDebugging->LogInformation ( NULL, "%s - World sound group:%d index:%d", *GetLocalTimeString ( false, true ), uiGroup, uiIndex ); + + if ( pEntityInterface ) { + CClientEntity* pEntity = g_pClientGame->GetGameEntityXRefManager()->FindClientEntity( pEntityInterface ); + + if ( pEntity && ( pEntity->GetType() == CCLIENTPED || pEntity->GetType() == CCLIENTPLAYER ) ) { + CLuaArguments Arguments; + Arguments.PushNumber( uiGroup ); + Arguments.PushNumber( uiIndex ); + Arguments.PushNumber( vecPosition.fX ); + Arguments.PushNumber( vecPosition.fY ); + Arguments.PushNumber( vecPosition.fZ ); + bool bCanceled = !pEntity->CallEvent( "onClientWorldSound", Arguments, pEntity != m_pRootEntity ); + + if ( bCanceled ) { + return false; + } + } + } + + return true; } diff --git a/Client/mods/deathmatch/logic/CClientGame.h b/Client/mods/deathmatch/logic/CClientGame.h index b5ab362ed23..172dc5e1f53 100644 --- a/Client/mods/deathmatch/logic/CClientGame.h +++ b/Client/mods/deathmatch/logic/CClientGame.h @@ -517,7 +517,7 @@ class CClientGame static void StaticGamePlayerDestructHandler ( CEntitySAInterface* pPlayer ); static void StaticGameProjectileDestructHandler ( CEntitySAInterface* pProjectile ); static void StaticGameModelRemoveHandler ( ushort usModelId ); - static void StaticWorldSoundHandler ( uint uiGroup, uint uiIndex ); + static bool StaticWorldSoundHandler ( uint uiGroup, uint uiIndex, CEntitySAInterface* pEntityInterface, const CVector& vecPosition ); static void StaticGameEntityRenderHandler ( CEntitySAInterface* pEntity ); static void StaticTaskSimpleBeHitHandler ( CPedSAInterface* pPedAttacker, ePedPieceTypes hitBodyPart, int hitBodySide, int weaponId ); static void StaticFxSystemDestructionHandler ( void * pFxSAInterface ); @@ -548,7 +548,7 @@ class CClientGame void GamePlayerDestructHandler ( CEntitySAInterface* pPlayer ); void GameProjectileDestructHandler ( CEntitySAInterface* pProjectile ); void GameModelRemoveHandler ( ushort usModelId ); - void WorldSoundHandler ( uint uiGroup, uint uiIndex ); + bool WorldSoundHandler ( uint uiGroup, uint uiIndex, CEntitySAInterface* pEntityInterface, const CVector& vecPosition ); void TaskSimpleBeHitHandler ( CPedSAInterface* pPedAttacker, ePedPieceTypes hitBodyPart, int hitBodySide, int weaponId ); AnimationId DrivebyAnimationHandler ( AnimationId animGroup, AssocGroupId animId ); diff --git a/Client/sdk/game/CAudioEngine.h b/Client/sdk/game/CAudioEngine.h index 1f7fe31e76b..7cc1ef31572 100644 --- a/Client/sdk/game/CAudioEngine.h +++ b/Client/sdk/game/CAudioEngine.h @@ -9,13 +9,12 @@ * *****************************************************************************/ -#ifndef __CGAME_AUDIOENGINE -#define __CGAME_AUDIOENGINE +#pragma once #include #include "CVehicle.h" -typedef void ( WorldSoundHandler ) ( uint uiGroup, uint uiIndex ); +using WorldSoundHandler = bool (*) ( uint uiGroup, uint uiIndex, CEntitySAInterface* pEntityInterface, const CVector& vecPosition ); enum eSurfaceType { @@ -60,9 +59,7 @@ class CAudioEngine virtual VOID SetWorldSoundEnabled ( uint uiGroup, uint uiIndex, bool bEnabled, bool bForceCancel ) = 0; virtual bool IsWorldSoundEnabled ( uint uiGroup, uint uiIndex ) = 0; virtual void ResetWorldSounds ( void ) = 0; - virtual void SetWorldSoundHandler ( WorldSoundHandler * pHandler ) = 0; + virtual void SetWorldSoundHandler ( WorldSoundHandler pHandler ) = 0; virtual void ReportBulletHit ( CEntity * pEntity, unsigned char ucSurfaceType, CVector * pvecPosition, float f_2 ) = 0; virtual void ReportWeaponEvent ( int iEvent, eWeaponType weaponType, CPhysical * pPhysical ) = 0; }; - -#endif