Files
GTASource/game/audio/emitteraudioentity.h
expvintl 419f2e4752 init
2025-02-23 17:40:52 +08:00

343 lines
9.2 KiB
C++

#ifndef EMITTERAUDIOENTITY_H_INCLUDED
#define EMITTERAUDIOENTITY_H_INCLUDED
//
// audio/emitteraudioentity.h
//
// Copyright (C) 1999-2006 Rockstar Games. All Rights Reserved.
//
#include "gameobjects.h"
#include "radioemitter.h"
#include "audioentity.h"
#include "audioengine/entity.h"
#include "audioengine/widgets.h"
#include "audioengine/curve.h"
#include "audioengine/engineutil.h"
#include "atl/bitset.h"
#include "bank/bank.h"
#include "scene/RegdRefTypes.h"
#include "system/memops.h"
#include "vector/quaternion.h"
const u32 g_audMaxStaticEmitters = 700;
const u32 g_audMaxEntityEmitters = 160;
const u32 g_audNumEntitiesPerBin = 8;
const u32 g_audNumBuildingAnimEvents = 24;
namespace rage
{
class audSound;
}
class audStreamSlot;
class CEntity;
struct CAudioAttr;
class naEnvironmentGroup;
struct audBuildingAnimEvent
{
audBuildingAnimEvent()
{
hash = 0;
}
Vec3V pos;
u32 hash;
};
struct StaticEmitterEntry
{
StaticEmitterEntry()
{
Reset();
}
void Reset()
{
lastTriggerTime = 0;
sound = NULL;
damageSound = NULL;
streamSlot = NULL;
linkedObject = NULL;
emitter = NULL;
alarmSettings = NULL;
playingRadioStation = 0;
isScriptLinkedEmitter = false;
}
s32 GetRequestedPCMChannel() const;
bool IsHighPriorityEmitter() const;
bool IsClubEmitter() const;
Vector3 position;
NA_RADIO_ENABLED_ONLY(audStaticRadioEmitter radioEmitter);
StaticEmitter *emitter;
audSound *sound;
audSound *damageSound;
audStreamSlot *streamSlot;
u32 lastTriggerTime;
RegdEnt linkedObject;
naEnvironmentGroup *occlusionGroup;
u32 nameHash;
u32 nextDamageFlipTime;
AlarmSettings* alarmSettings;
u32 playingRadioStation;
bool isScriptLinkedEmitter;
};
// Split the flags out from StaticEmitterEntry to avoid L2cache misses when iterating over the staticEmitter array. [2/1/2013 mdawe]
struct StaticEmitterFlags
{
StaticEmitterFlags()
{
Reset();
}
void Reset()
{
bWasBrokenLastFrame = false;
bNeedsInteriorInfo = false;
bIsPlayingRadio = false;
bIsLinked = false;
bFilterByAngle = false;
bIsScanner = false;
bIsEnabled = false;
bWasValidTime = false;
bIsActive24h = true;
bStartStopImmediatelyAtTimeLimits = true;
bWasActive = false;
bIsStreamingSound = false;
}
bool bWasBrokenLastFrame : 1;
bool bNeedsInteriorInfo : 1;
bool bIsPlayingRadio : 1;
bool bIsLinked : 1;
bool bFilterByAngle : 1;
bool bIsScanner : 1;
bool bIsEnabled : 1;
bool bWasValidTime : 1;
bool bIsActive24h : 1;
bool bStartStopImmediatelyAtTimeLimits : 1;
bool bWasActive : 1;
bool bIsStreamingSound : 1;
};
class C2dEffect;
struct EntityEmitterEntry
{
EntityEmitterEntry()
{
lastTriggerTime = 0;
randomSeed = 0.0f;
sound = NULL;
emitter = NULL;
frequentUpdates = false;
prevEmitterIdx = 0xffff;
}
Vector3 offset;
audCompressedQuat rotation;
CEntity *entity;
audSound *sound;
EntityEmitter* emitter;
u32 lastTriggerTime;
f32 randomSeed;
u16 localRandomSeed;
u16 prevEmitterIdx;
bool frequentUpdates;
inline bool IsOccluded() {return emitter && AUD_GET_TRISTATE_VALUE(emitter->Flags, FLAG_ID_ENTITYEMITTER_COMPUTEOCCLUSION)==AUD_TRISTATE_TRUE;}
inline bool IsConed() {return emitter && AUD_GET_TRISTATE_VALUE(emitter->Flags, FLAG_ID_ENTITYEMITTER_VOLUMECONE)==AUD_TRISTATE_TRUE;}
inline bool IsWindAffected() {return emitter && AUD_GET_TRISTATE_VALUE(emitter->Flags, FLAG_ID_ENTITYEMITTER_WINDBASEDVOLUME)==AUD_TRISTATE_TRUE;}
inline bool ShouldStopOnRain() {return emitter && AUD_GET_TRISTATE_VALUE(emitter->Flags, FLAG_ID_ENTITYEMITTER_STOPWHENRAINING)==AUD_TRISTATE_TRUE;}
inline bool GeneratesTreeRain() {return emitter && AUD_GET_TRISTATE_VALUE(emitter->Flags, FLAG_ID_ENTITYEMITTER_GENERATESTREERAIN)==AUD_TRISTATE_TRUE;}
inline bool OnlyWhenRaining() {return emitter && AUD_GET_TRISTATE_VALUE(emitter->Flags, FLAG_ID_ENTITYEMITTER_ONLYWHENRAINING)==AUD_TRISTATE_TRUE;}
};
struct tEntityBin
{
tEntityBin()
{
numEntities = 0;
sysMemZeroBytes<sizeof(entities)>(&entities);
sysMemSet(&tailEmitters, 0xff, sizeof(tailEmitters));
}
atRangeArray<CEntity *, g_audNumEntitiesPerBin> entities;
atRangeArray<u16, g_audNumEntitiesPerBin> tailEmitters;
u16 numEntities;
};
class audEmitterAudioEntity : naAudioEntity
{
public:
AUDIO_ENTITY_NAME(audEmitterAudioEntity);
audEmitterAudioEntity()
{
m_CurrentStaticEmitterIndex = 0;
m_PreserveEntityEmitters = false;
}
virtual ~audEmitterAudioEntity(){}
void Init();
void Shutdown();
void Update();
void ResetTimers();
void InitStaticEmitters();
void ReInitStaticEmitters();
void StopAndResetStaticEmitters();
// only call from the non game-audio thread
void CheckStaticEmittersForInteriorInfo();
void SetActive(const bool active)
{
m_IsActive = active;
}
// PURPOSE
// Called by the entity for each 2dEffect audio emitter attached to the entity.
// PARAMS
// entity - owning entity
// hash - emitter game object reference
// offset - offset is space from entity position
// direction - emitter direction
void RegisterEntityEmitter(CEntity *entity, u32 hash, Vector3 &offset, Quaternion &rotation);
void UpdateLightAudio(CLightEntity* lightEntity, CEntity *parentEntity, const C2dEffect *effect, const bool isLightOn, const u32 slotIndex);
// PURPOSE
// Called when the specified entity is being removed from the world. Removes all active emitters
// owned by that entity.
void UnregisterEmittersForEntity(CEntity *entity);
void AddStaticEmitter(u32 emitterName, const u16 gameTimeMinutes);
void UpdateStaticEmitterPosition(StaticEmitter* emitter);
void SetStaticEmitterInteriorInfo(const u32 i);
void UpdateStaticEmitterEnvironmentGroup(const u32 i);
#if __BANK
void RetuneEmittersToStation(audRadioStation* station);
void CreateOrUpdateEmitter(u32 nameHash);
#endif
// PURPOSE
// Called when a loud sound (gunshot etc) happens
void NotifyLoudSound();
virtual void UpdateSound(audSound *sound, audRequestedSettings *reqSets, u32 timeInMs);
void StopEmitter(u32 emitterIndex);
bool IsEmitterActive(u32 emitterIndex);
static bool OnStopCallback(u32 emitterIndex);
static bool HasStoppedCallback(u32 emitterIndex);
static naEnvironmentGroup* CreateStaticEmitterEnvironmentGroup(const StaticEmitter* staticEmitter, const Vector3& pos);
#if __BANK
static void AddWidgets(bkBank &bank);
static bool sm_ShouldDrawEntityEmitters;
static bool sm_ShouldDrawStaticEmitters;
static bool sm_DrawStaticEmitterOpennessValues;
void HandleRaveStaticEmitterCreatedNotification(u32 nameHash);
#endif
u32 GetNumEntityEmitters() const
{
return m_NumEntityEmitters;
}
bool GetGeneratesWindAudio(const CAudioAttr *audioAttr) const;
void SetPreserveEntityEmitters(const bool preserve)
{
m_PreserveEntityEmitters = preserve;
}
void SetEmitterLinkedObject(const char *emitterName, CEntity* entity, bool isScriptLinkedEmitter = false);
void SetEmitterRadioStation(const char *emitterName, const char *radioStationName);
bool SetEmitterEnabled(const char *emitterName, const bool enabled);
void AddBuildingAnimEvent(u32 hash, Vec3V_In inPos);
void ClearBuildingAnimEvents();
bool IsWithinRangeOfRadio(const Vector3& inPosition, float fRange);
private:
u32 GetRadioStationForEmitter(const u32 emitterIdx) const;
bool IsEntityEnabled(const u32 index) const { return m_EntityEnabledList.IsSet(index); }
#if __BANK
void DrawDebug();
#endif
void FindAudioBinAndIndex(CEntity *entity, u32 &bin, u32 &idx);
void UpdateStaticEmitters();
void UpdateEntityEmitters();
void UpdateBuildingAnimEvents();
void CreateStaticEmitters();
void UpdateScriptPositionedEmitter(u32 emitterIndex);
f32 ComputeEntityEmitterConeAttenuation(u32 emitterIdx);
bool ShouldStaticEmitterBePlaying(u32 emitterIdx, const bool playerSwitchActive, const bool gameWorldHidden, const u16 gameTimeMinutes);
bool ShouldStaticEmitterBeStopped(u32 emitterIdx, const u16 gameTimeMinutes);
bool ShouldEntityEmitterBePlaying(u32 emitterIdx, bool updateCheckTime, const bool playerSwitchActive);
bool ShouldEntityEmitterBeRegistered(EntityEmitter *emitter, const Vector3& pos);
void GetEntityEmitterPosition(u32 emittedIdx, Vector3 &pos);
void GetEntityEmitterPositionAndOrientation(u32 emitterIdx, Vector3 &pos,audCompressedQuat &orientation);
naEnvironmentGroup* CreateEntityEmitterEnvironmentGroup(EntityEmitterEntry* entityEmitter, Vector3& pos, u8 maxPathDepth);
Vec3V m_LastListenerPos;
atRangeArray<StaticEmitterEntry, g_audMaxStaticEmitters> m_StaticEmitterList;
atRangeArray<StaticEmitterFlags, g_audMaxStaticEmitters> m_StaticEmitterFlags;
atRangeArray<EntityEmitterEntry,g_audMaxEntityEmitters> m_EntityEmitterList;
atRangeArray<audBuildingAnimEvent, g_audNumBuildingAnimEvents> m_BuildingAnimEvents;
audCurve m_ConeCurve;
u32 m_CurrentStaticEmitterIndex;
atBitSet m_EntityEnabledList;
u32 m_EntityCheckTimes[g_audMaxEntityEmitters];
u32 m_NumEntityEmitters;
audSimpleSmoother m_FillsInteriorSpaceDuckingSmoother;
tEntityBin m_EntityBins[255];
u32 m_NumEntities;
u32 m_FirstFreeBin;
bool m_IsActive;
bool m_HasInitialisedStaticEmitters;
bool m_PreserveEntityEmitters;
bool m_FirstUpdate;
#if __BANK
struct audEntityEmitterDebugInfo
{
CEntity* entity;
u32 hash;
Vector3 offset;
};
atArray<audEntityEmitterDebugInfo> m_EntityEmitterDebugInfo;
#endif
};
extern audEmitterAudioEntity g_EmitterAudioEntity;
#endif // EMITTERAUDIOENTITY_H_INCLUDED