diff --git a/config/SOUE01/splits.txt b/config/SOUE01/splits.txt index ced03afb..13fb8d6c 100644 --- a/config/SOUE01/splits.txt +++ b/config/SOUE01/splits.txt @@ -2453,13 +2453,15 @@ d/snd/d_snd_anim_sound.cpp: .text start:0x80382150 end:0x8038240C align:16 .sdata2 start:0x8057DB50 end:0x8057DB68 -d/snd/d_snd_mgr_unk_14.cpp: +d/snd/d_snd_source_mgr.cpp: .text start:0x80382410 end:0x803864C8 align:16 .ctors start:0x804DB91C end:0x804DB920 -d/snd/d_snd_mgr_unk_13.cpp: +d/snd/d_snd_source_group.cpp: .text start:0x803864D0 end:0x803889BC align:16 .data start:0x8054A680 end:0x8054A7D0 + .sdata start:0x805743D0 end:0x80574708 + .sdata2 start:0x8057DBC0 end:0x8057DCB0 d/snd/d_snd_source.cpp: .text start:0x803889C0 end:0x8038C408 align:16 diff --git a/config/SOUE01/symbols.txt b/config/SOUE01/symbols.txt index 937bcc97..0090fe28 100644 --- a/config/SOUE01/symbols.txt +++ b/config/SOUE01/symbols.txt @@ -19838,7 +19838,7 @@ __ct__11dSndActor_cFRQ34nw4r3snd18SoundArchivePlayer = .text:0x8035A560; // type __dt__Q34nw4r3snd11SoundHandleFv = .text:0x8035A5A0; // type:function size:0x54 scope:weak __cl__22SoundPropertiesCheckerFRQ34nw4r3snd11SoundHandle = .text:0x8035A600; // type:function size:0x240 __dt__11dSndActor_cFv = .text:0x8035A840; // type:function size:0x58 scope:weak -__ct__13dSnd3DActor_cFPvUc = .text:0x8035A8A0; // type:function size:0xE8 +__ct__13dSnd3DActor_cFP15dSndSourceParamUc = .text:0x8035A8A0; // type:function size:0xE8 d_vt_0x34__13dSnd3DActor_cFRCQ34nw4r4math4VEC3 = .text:0x8035A990; // type:function size:0x40 resetCachedRelativePositions__13dSnd3DActor_cFv = .text:0x8035A9D0; // type:function size:0x2C fn_8035AA00 = .text:0x8035AA00; // type:function size:0x30 @@ -20065,7 +20065,7 @@ fn_80362390 = .text:0x80362390; // type:function size:0x6C fn_80362400 = .text:0x80362400; // type:function size:0x10 fn_80362410 = .text:0x80362410; // type:function size:0xC fn_80362420 = .text:0x80362420; // type:function size:0x18 -isNotInStage = .text:0x80362440; // type:function size:0x34 +isInStage = .text:0x80362440; // type:function size:0x34 fn_80362480 = .text:0x80362480; // type:function size:0x6C fn_803624F0 = .text:0x803624F0; // type:function size:0xF4 fn_803625F0 = .text:0x803625F0; // type:function size:0x140 @@ -20128,15 +20128,15 @@ fn_803651A0 = .text:0x803651A0; // type:function size:0xA0 fn_80365240 = .text:0x80365240; // type:function size:0x1F8 fn_80365440 = .text:0x80365440; // type:function size:0x10C fn_80365550 = .text:0x80365550; // type:function size:0x1A8 -fn_80365700 = .text:0x80365700; // type:function size:0xCC +setUnderwaterLpfFreq = .text:0x80365700; // type:function size:0xCC fn_803657D0 = .text:0x803657D0; // type:function size:0x78 fn_80365850 = .text:0x80365850; // type:function size:0x70 fn_803658C0 = .text:0x803658C0; // type:function size:0x5C fn_80365920 = .text:0x80365920; // type:function size:0x4C fn_80365970 = .text:0x80365970; // type:function size:0x8 fn_80365980 = .text:0x80365980; // type:function size:0x54 -fn_803659E0 = .text:0x803659E0; // type:function size:0x4C -fn_80365A30 = .text:0x80365A30; // type:function size:0x48 +resetBgmAndStageEffectLpfFreq = .text:0x803659E0; // type:function size:0x4C +resetBgmLpfFreq = .text:0x80365A30; // type:function size:0x48 fn_80365A80 = .text:0x80365A80; // type:function size:0x4C fn_80365AD0 = .text:0x80365AD0; // type:function size:0xA8 fn_80365B80 = .text:0x80365B80; // type:function size:0x5C @@ -21111,26 +21111,26 @@ fn_80386470 = .text:0x80386470; // type:function size:0x8 @4@d_vt_0x58__14dSoundSource_cFv = .text:0x803864A0; // type:function size:0x8 fn_803864B0 = .text:0x803864B0; // type:function size:0x8 fn_803864C0 = .text:0x803864C0; // type:function size:0x8 -fn_803864D0 = .text:0x803864D0; // type:function size:0x164 -fn_80386640 = .text:0x80386640; // type:function size:0x2C -fn_80386670 = .text:0x80386670; // type:function size:0x118 +set__17dSndSourceGroup_cFlPCc = .text:0x803864D0; // type:function size:0x164 +resetSoundSourceParam__17dSndSourceGroup_cFv = .text:0x80386640; // type:function size:0x2C +__ct__17dSndSourceGroup_cFv = .text:0x80386670; // type:function size:0x118 fn_80386790 = .text:0x80386790; // type:function size:0x120 -fn_803868B0 = .text:0x803868B0; // type:function size:0x54 +__dt__17dSndSourceGroup_cFv = .text:0x803868B0; // type:function size:0x54 fn_80386910 = .text:0x80386910; // type:function size:0xEC fn_80386A00 = .text:0x80386A00; // type:function size:0xB0 fn_80386AB0 = .text:0x80386AB0; // type:function size:0xBC fn_80386B70 = .text:0x80386B70; // type:function size:0xBC -fn_80386C30 = .text:0x80386C30; // type:function size:0x10 -fn_80386C40 = .text:0x80386C40; // type:function size:0x8 -fn_80386C50 = .text:0x80386C50; // type:function size:0x14 -fn_80386C70 = .text:0x80386C70; // type:function size:0x14 -fn_80386C90 = .text:0x80386C90; // type:function size:0x58 -fn_80386CF0 = .text:0x80386CF0; // type:function size:0xEC -fn_80386DE0 = .text:0x80386DE0; // type:function size:0x110 +calc__17dSndSourceGroup_cFv = .text:0x80386C30; // type:function size:0x10 +getNumSources__17dSndSourceGroup_cCFv = .text:0x80386C40; // type:function size:0x8 +registerSource__17dSndSourceGroup_cFP14dSoundSource_c = .text:0x80386C50; // type:function size:0x14 +unregisterSource__17dSndSourceGroup_cFP14dSoundSource_c = .text:0x80386C70; // type:function size:0x14 +clearList__17dSndSourceGroup_cFv = .text:0x80386C90; // type:function size:0x58 +getSourceClosestToListener__17dSndSourceGroup_cFv = .text:0x80386CF0; // type:function size:0xEC +getSourceClosestToPlayer__17dSndSourceGroup_cFv = .text:0x80386DE0; // type:function size:0x110 fn_80386EF0 = .text:0x80386EF0; // type:function size:0x80 -fn_80386F70 = .text:0x80386F70; // type:function size:0x1A4C +setParamFromName__17dSndSourceGroup_cFPCc = .text:0x80386F70; // type:function size:0x1A4C soundForActorInitRelated_803889c0 = .text:0x803889C0; // type:function size:0x4 -__ct__14dSoundSource_cFUcP9dAcBase_cii = .text:0x803889D0; // type:function size:0x108 +__ct__14dSoundSource_cFUcP9dAcBase_ciP17dSndSourceGroup_c = .text:0x803889D0; // type:function size:0x108 __dt__14dSoundSource_cFv = .text:0x80388AE0; // type:function size:0xC4 vt_0x0C__14dSoundSource_cFv = .text:0x80388BB0; // type:function size:0x118 vt_0x44__14dSoundSource_cFv = .text:0x80388CD0; // type:function size:0x9C diff --git a/configure.py b/configure.py index 0bef48dc..9491767d 100644 --- a/configure.py +++ b/configure.py @@ -724,8 +724,8 @@ config.libs = [ Object(NonMatching, "d/snd/d_snd_small_effect_mgr.cpp"), Object(NonMatching, "d/snd/d_snd_harp_mgr.cpp"), Object(NonMatching, "d/snd/d_snd_anim_sound.cpp"), - Object(NonMatching, "d/snd/d_snd_mgr_unk_14.cpp"), - Object(NonMatching, "d/snd/d_snd_mgr_unk_13.cpp"), + Object(NonMatching, "d/snd/d_snd_source_mgr.cpp"), + Object(NonMatching, "d/snd/d_snd_source_group.cpp"), Object(NonMatching, "d/snd/d_snd_source.cpp"), Object(NonMatching, "d/snd/d_snd_mgr_unk_7.cpp"), Object(NonMatching, "d/snd/d_snd_mgr_unk_8.cpp"), diff --git a/include/d/snd/d_snd_3d_actor.h b/include/d/snd/d_snd_3d_actor.h index 98735baf..0d9c5e95 100644 --- a/include/d/snd/d_snd_3d_actor.h +++ b/include/d/snd/d_snd_3d_actor.h @@ -2,6 +2,7 @@ #define D_SND_ACTOR_H #include "common.h" +#include "d/snd/d_snd_misc.h" #include "nw4r/math/math_types.h" #include "nw4r/snd/snd_Sound3DActor.h" @@ -9,7 +10,7 @@ class dSnd3DActor_c : public nw4r::snd::Sound3DActor { static const u32 NUM_SOUNDS = 4; public: - dSnd3DActor_c(UNKTYPE *, u8); + dSnd3DActor_c(dSndSourceParam *pAmbientParam, u8); virtual ~dSnd3DActor_c() {} @@ -59,6 +60,11 @@ public: mFlags |= flag; } + f32 getDistanceToListener() { + updateDistanceToListener(); + return mDistanceToListener; + } + bool hasPlayingSounds() const; bool isPlayingSound(u32 id); @@ -82,7 +88,7 @@ protected: /* 0xAC */ nw4r::math::VEC3 mPositionTransformedByListener; /* 0xB8 */ f32 mDistanceToCameraTarget; /* 0xBC */ nw4r::math::VEC3 mPositionRelativeToCameraTarget; - /* 0xC8 */ UNKTYPE *a_field_0xC8; + /* 0xC8 */ dSndSourceParam *mpFloatBundle; /* 0xCC */ u16 mFlags; /* 0xD0 */ nw4r::math::VEC3 mPositionRelativeToPlayer; /* 0xDC */ f32 mDistanceToPlayer; diff --git a/include/d/snd/d_snd_misc.h b/include/d/snd/d_snd_misc.h new file mode 100644 index 00000000..f5bfaa7f --- /dev/null +++ b/include/d/snd/d_snd_misc.h @@ -0,0 +1,29 @@ +#ifndef D_SND_MISC_H +#define D_SND_MISC_H + +#include "common.h" + +// This is at least accessed by dSnd3DEngine_c's functions that +// are called as part of UpdateAmbientParam. Appears to be +// related to the biquadFilterValue. +struct dSndSourceParam { + dSndSourceParam() { + reset(); + } + + void reset() { + field_0x00 = 300.0; + field_0x04 = 1000.0f; + field_0x08 = 100.0f; + field_0x0C = 400.0f; + field_0x10 = 5000.0f; + } + + /* 0x00 */ f32 field_0x00; + /* 0x04 */ f32 field_0x04; + /* 0x08 */ f32 field_0x08; + /* 0x0C */ f32 field_0x0C; + /* 0x10 */ f32 field_0x10; +}; + +#endif diff --git a/include/d/snd/d_snd_source.h b/include/d/snd/d_snd_source.h index 2ae4c739..238bbef0 100644 --- a/include/d/snd/d_snd_source.h +++ b/include/d/snd/d_snd_source.h @@ -6,13 +6,16 @@ #include "d/snd/d_snd_source_if.h" #include "nw4r/ut/ut_list.h" +class dSndSourceGroup_c; + /** Manages sound relating to a particular actor. */ +/** Size: probably 0x15C */ class dSoundSource_c : public dSoundSourceIf_c, public dSnd3DActor_c { public: - dSoundSource_c(u8, dAcBase_c *, UNKWORD, UNKWORD); + dSoundSource_c(u8, dAcBase_c *, UNKWORD, dSndSourceGroup_c *pOwnerGroup); virtual ~dSoundSource_c(); - static u32 getCharacterTalkSoundId(u32 baseSoundId, dSoundSource_c* source); + static u32 getCharacterTalkSoundId(u32 baseSoundId, dSoundSource_c *source); u32 getRemoConSoundVariant(u32 soundId) const; // This is where it gets a bit wild and this class starts mixing in overrides between @@ -94,13 +97,12 @@ private: /* 0x11C */ UNKWORD field_0x11C; /* 0x120 */ nw4r::ut::List field_0x120; // node offset 0x4 /* 0x12C */ nw4r::ut::List field_0x12C; // node offset 0x4 - /* 0x138 */ nw4r::ut::Node mNode; - /* 0x140 */ UNKWORD field_0x140; + /* 0x138 */ nw4r::ut::Node mGroupLink; // node for list in dSndSourceGroup_c + /* 0x140 */ dSndSourceGroup_c *mpOwnerGroup; /* 0x144 */ u8 _0x144[0x154 - 0x144]; /* 0x154 */ UNKWORD field_0x154; /* 0x158 */ s16 field_0x158; /* 0x15A */ s16 field_0x15A; - /* 0x15C */ nw4r::ut::Node mNode2; }; #endif diff --git a/include/d/snd/d_snd_source_group.h b/include/d/snd/d_snd_source_group.h new file mode 100644 index 00000000..273df135 --- /dev/null +++ b/include/d/snd/d_snd_source_group.h @@ -0,0 +1,62 @@ +#ifndef D_SND_SOURCE_GROUP_H +#define D_SND_SOURCE_GROUP_H + +#include "common.h" +#include "d/snd/d_snd_misc.h" +#include "nw4r/ut/ut_list.h" +#include "sized_string.h" + +class dSoundSource_c; + +/** + * All similar dSoundSource_c's are put in a group. The game can then find the closest + * source for a given type by name/id, for example for changing things about the music + * depending on proximity to a certain object or enemy. + * + * Through its dSndSourceParam, it can also "send" parameters to all dSnd3DActors + * corresponding to these sound sources. + * + * Size: 0x70 + */ +class dSndSourceGroup_c { +public: + dSndSourceGroup_c(); + ~dSndSourceGroup_c(); + + void registerSource(dSoundSource_c *); + void unregisterSource(dSoundSource_c *); + + dSndSourceParam* getAmbientParam() { + return &mParam; + } + + dSoundSource_c *getSourceClosestToListener(); + dSoundSource_c *getSourceClosestToPlayer(); + + s32 getNumSources() const; + void set(s32 type, const char *name); + void calc(); + +private: + bool setParamFromName(const char *name); + void resetSoundSourceParam(); + void clearList(); + + /* 0x00 */ nw4r::ut::Node mNode; + /* 0x08 */ u8 _0x08[0x10 - 0x08]; + /* 0x10 */ UNKWORD field_0x10; + /* 0x14 */ UNKWORD field_0x14; + /* 0x18 */ UNKWORD field_0x18; + /* 0x1C */ u8 field_0x1C; + /* 0x1D */ u8 field_0x1D; + /* 0x1E */ SizedString<32> mName; + /* 0x40 */ UNKWORD field_0x40; + /* 0x44 */ nw4r::ut::List mSourceList; + /* 0x50 */ dSndSourceParam mParam; + /* 0x64 */ dSoundSource_c *mpCachedClosestSourceToListener; + /* 0x68 */ dSoundSource_c *mpCachedClosestSourceToPlayer; + /* 0x6C */ bool mCalculatedClosestToListener; + /* 0x6C */ bool mCalculatedClosestToPlayer; +}; + +#endif diff --git a/include/d/snd/d_snd_source_if.h b/include/d/snd/d_snd_source_if.h index 8a77ff67..e1edb145 100644 --- a/include/d/snd/d_snd_source_if.h +++ b/include/d/snd/d_snd_source_if.h @@ -14,7 +14,7 @@ public: SOUNDSOURCE_VIRTUAL(0x0C); SOUNDSOURCE_VIRTUAL(0x10); SOUNDSOURCE_VIRTUAL(0x14); - SOUNDSOURCE_VIRTUAL(0x18); + virtual s32 getActorType() const; SOUNDSOURCE_VIRTUAL(0x1C); SOUNDSOURCE_VIRTUAL(0x20); SOUNDSOURCE_VIRTUAL(0x24); diff --git a/include/toBeSorted/music_mgrs.h b/include/toBeSorted/music_mgrs.h index 63c1ceb4..97082aac 100644 --- a/include/toBeSorted/music_mgrs.h +++ b/include/toBeSorted/music_mgrs.h @@ -32,6 +32,19 @@ extern "C" void fn_80364D00(void *, s32); // ENEMY_BGM_RELATED_MGR -> dSndSourceMgr_c // 0x3870 = player sound source // 0x3874 = Fi + +// 0 - "" - Link +// ActorLink::initModels +// 0x2C - NpcKenT +// 0x20 - Door, TBox, CharE (Chair), Tubo +// 0x35 - TgSound +// 0x2D - PyBird +// 0x22 - Bamboo +// 0x23 - Item + +// 0x19 - Nusi*, BKr, BBs +// 0x1A - MgRArm, MgLArm +// 0x1B - Mgtail extern "C" void *ENEMY_BGM_RELATED_MGR; extern "C" void fn_80384570(void *, bool); extern "C" void fn_803858D0(void *); diff --git a/src/d/snd/d_snd_3d_actor.cpp b/src/d/snd/d_snd_3d_actor.cpp index 41f506aa..bf0ddd05 100644 --- a/src/d/snd/d_snd_3d_actor.cpp +++ b/src/d/snd/d_snd_3d_actor.cpp @@ -9,7 +9,7 @@ #include -dSnd3DActor_c::dSnd3DActor_c(UNKTYPE *a1, u8 a2) +dSnd3DActor_c::dSnd3DActor_c(dSndSourceParam *pFloatBundle, u8 a2) : nw4r::snd::Sound3DActor( dSndPlayerMgr_c::GetInstance()->getSoundArchivePlayerForType(a2), dSnd3DManager_c::GetInstance()->getManager() ), @@ -24,7 +24,7 @@ dSnd3DActor_c::dSnd3DActor_c(UNKTYPE *a1, u8 a2) mDistanceToListener(INFINITY), mCameraDirectionDot(0.0f), a_field_0x9C(0.0f), - a_field_0xC8(a1), + mpFloatBundle(pFloatBundle), mFlags(0), mDistanceToPlayer(INFINITY), a_field_0xE0(0.0f) { diff --git a/src/d/snd/d_snd_source.cpp b/src/d/snd/d_snd_source.cpp index 96b554a5..4e582666 100644 --- a/src/d/snd/d_snd_source.cpp +++ b/src/d/snd/d_snd_source.cpp @@ -5,13 +5,12 @@ #include "d/snd/d_snd_3d_manager.h" #include "d/snd/d_snd_mgr.h" #include "d/snd/d_snd_player_mgr.h" +#include "d/snd/d_snd_source_group.h" #include "nw4r/snd/snd_SoundStartable.h" #include "nw4r/ut/ut_list.h" #include "sized_string.h" extern "C" u8 fn_80382590(u8, UNKWORD); -extern "C" void fn_80386C50(UNKWORD, dSoundSource_c *); -extern "C" void fn_80386C70(dSoundSource_c *); struct d_snd_mgr_unk_6_sinit { d_snd_mgr_unk_6_sinit() : field_0x00(0), field_0x04(0.0f) {} @@ -26,8 +25,8 @@ const char *help_i_need_data() { return "%s_%s_%d"; } -dSoundSource_c::dSoundSource_c(u8 a1, dAcBase_c *player, UNKWORD a3, UNKWORD a4) - : dSnd3DActor_c(((char *)a4) + 0x50, a1), +dSoundSource_c::dSoundSource_c(u8 a1, dAcBase_c *player, UNKWORD a3, dSndSourceGroup_c *pOwnerGroup) + : dSnd3DActor_c(pOwnerGroup->getAmbientParam(), a1), field_0x0F0(a3), field_0x0F4(0), mpPlayer(player), @@ -41,7 +40,7 @@ dSoundSource_c::dSoundSource_c(u8 a1, dAcBase_c *player, UNKWORD a3, UNKWORD a4) field_0x108(0), field_0x10C(0), field_0x11C(0), - field_0x140(a4), + mpOwnerGroup(pOwnerGroup), field_0x154(0), field_0x158(-1), field_0x15A(-1) { @@ -50,13 +49,14 @@ dSoundSource_c::dSoundSource_c(u8 a1, dAcBase_c *player, UNKWORD a3, UNKWORD a4) nw4r::ut::List_Init(&field_0x110, 0xEC); nw4r::ut::List_Init(&field_0x120, 0x04); nw4r::ut::List_Init(&field_0x12C, 0x04); - fn_80386C50(a4, this); + pOwnerGroup->registerSource(this); } dSoundSource_c::~dSoundSource_c() { SetUserParam(0); vt_0x44(); - fn_80386C70(this); + d_s_vt_0x1BC(); + mpOwnerGroup->unregisterSource(this); } const nw4r::math::VEC3 &dSoundSource_c::getListenerPosition() const { diff --git a/src/d/snd/d_snd_source_group.cpp b/src/d/snd/d_snd_source_group.cpp new file mode 100644 index 00000000..91e2542e --- /dev/null +++ b/src/d/snd/d_snd_source_group.cpp @@ -0,0 +1,169 @@ + +#include "d/snd/d_snd_source_group.h" + +#include "common.h" +#include "d/snd/d_snd_source.h" +#include "nw4r/ut/ut_list.h" + +#include + +extern "C" bool isInStage(const char *stageName); + +void dSndSourceGroup_c::set(s32 type, const char *name) { + resetSoundSourceParam(); + bool assignedParam = false; + + switch (field_0x14) { + case 0: { + assignedParam = true; + mParam.field_0x10 = INFINITY; + break; + } + case 1: + if (type == 7) { + assignedParam = true; + mParam.field_0x00 = 1500.0f; + mParam.field_0x10 = INFINITY; + } + break; + } + + if (!assignedParam && (type == 44 || type == 58)) { + assignedParam = true; + mParam.field_0x10 = INFINITY; + } + + if (!assignedParam) { + assignedParam = setParamFromName(name); + } + + if (!assignedParam) { + switch (type) { + case 51: { + mParam.field_0x00 = 300.0f; + mParam.field_0x04 = 800.0; + mParam.field_0x10 = 2200.0; + break; + } + case 48: { + if (isInStage("F401")) { + mParam.field_0x00 = 500.0f; + mParam.field_0x04 = 4000.0; + } else if (isInStage("F402")) { + mParam.field_0x00 = 400.0f; + mParam.field_0x04 = 3500.0; + } else { + mParam.field_0x00 = 300.0f; + mParam.field_0x04 = 800.0; + mParam.field_0x10 = 2200.0; + } + + mParam.field_0x10 = INFINITY; + } + } + } +} + +void dSndSourceGroup_c::resetSoundSourceParam() { + mParam.reset(); +} + +dSndSourceGroup_c::dSndSourceGroup_c() + : field_0x18(0), + field_0x1C(0), + field_0x1D(0), + mName(""), + field_0x40(0), + mpCachedClosestSourceToListener(nullptr), + mpCachedClosestSourceToPlayer(nullptr), + mCalculatedClosestToListener(false), + mCalculatedClosestToPlayer(false) { + // TODO offsetof + nw4r::ut::List_Init(&mSourceList, 0x138); + resetSoundSourceParam(); +} + +dSndSourceGroup_c::~dSndSourceGroup_c() { + clearList(); +} + +void dSndSourceGroup_c::calc() { + // Reset freshness flags, computed on-demand + mCalculatedClosestToPlayer = false; + mCalculatedClosestToListener = false; +} + +s32 dSndSourceGroup_c::getNumSources() const { + return nw4r::ut::List_GetSize(&mSourceList); +} + +void dSndSourceGroup_c::registerSource(dSoundSource_c *source) { + if (source != nullptr) { + nw4r::ut::List_Append(&mSourceList, source); + } +} + +void dSndSourceGroup_c::unregisterSource(dSoundSource_c *source) { + if (source != nullptr) { + nw4r::ut::List_Remove(&mSourceList, source); + } +} + +void dSndSourceGroup_c::clearList() { + dSoundSource_c *source = static_cast(nw4r::ut::List_GetNext(&mSourceList, nullptr)); + while (source != nullptr) { + nw4r::ut::List_Remove(&mSourceList, source); + source = static_cast(nw4r::ut::List_GetNext(&mSourceList, nullptr)); + } +} + +dSoundSource_c *dSndSourceGroup_c::getSourceClosestToListener() { + if (mCalculatedClosestToListener) { + return mpCachedClosestSourceToListener; + } + + mpCachedClosestSourceToListener = nullptr; + f32 closest = INFINITY; + for (dSoundSource_c *source = static_cast(nw4r::ut::List_GetNext(&mSourceList, nullptr)); + source != nullptr; source = static_cast(nw4r::ut::List_GetNext(&mSourceList, source))) { + if (source->getActorType() != 1 && source->getActorType() != 48) { + f32 dist = source->getDistanceToListener(); + if (dist < closest) { + closest = dist; + mpCachedClosestSourceToListener = source; + } + } + } + mCalculatedClosestToListener = true; + return mpCachedClosestSourceToListener; +} + +dSoundSource_c *dSndSourceGroup_c::getSourceClosestToPlayer() { + if (mCalculatedClosestToPlayer) { + return mpCachedClosestSourceToPlayer; + } + + if ((s32)nw4r::ut::List_GetSize(&mSourceList) <= 1) { + return static_cast(nw4r::ut::List_GetNext(&mSourceList, nullptr)); + } + + mpCachedClosestSourceToPlayer = nullptr; + f32 closest = INFINITY; + for (dSoundSource_c *source = static_cast(nw4r::ut::List_GetNext(&mSourceList, nullptr)); + source != nullptr; source = static_cast(nw4r::ut::List_GetNext(&mSourceList, source))) { + if (source->getActorType() != 1 && source->getActorType() != 48) { + f32 dist = source->getDistanceToPlayer(); + if (dist < closest) { + closest = dist; + mpCachedClosestSourceToPlayer = source; + } + } + } + mCalculatedClosestToPlayer = true; + return mpCachedClosestSourceToPlayer; +} + +bool dSndSourceGroup_c::setParamFromName(const char*) { + // TODO + return false; +}