diff --git a/Common/Sound/sound.h b/Common/Sound/sound.h index 0eb4bae31..c7e7042a4 100644 --- a/Common/Sound/sound.h +++ b/Common/Sound/sound.h @@ -101,13 +101,14 @@ struct SampleInfo struct SoundTrackInfo { - std::string Name; - SOUNDTRACK_PLAYTYPE Mode; - int Mask; + std::string Name{}; + SOUNDTRACK_PLAYTYPE Mode{ SOUNDTRACK_PLAYTYPE::OneShot }; + int Mask{ 0 }; }; extern std::map SoundTrackMap; -extern std::vector SoundTracks; +extern std::unordered_map SoundTracks; +extern int SecretSoundIndex; long SoundEffect(int effectID, PHD_3DPOS* position, int env_flags, float pitchMultiplier = 1.0f, float gainMultiplier = 1.0f); void StopSoundEffect(short effectID); @@ -124,6 +125,7 @@ void PlaySecretTrack(); void SayNo(); void PlaySoundSources(); int GetShatterSound(int shatterID); +void EnumerateLegacyTracks(); std::pair GetSoundTrackNameAndPosition(SOUNDTRACK_PLAYTYPE type); diff --git a/Scripting/src/GameFlowScript.cpp b/Scripting/src/GameFlowScript.cpp index cc849e5bc..61783d0ff 100644 --- a/Scripting/src/GameFlowScript.cpp +++ b/Scripting/src/GameFlowScript.cpp @@ -85,17 +85,6 @@ settings.lua shouldn't be bundled with any finished levels/games. */ m_lua->set_function("SetAnimations", &GameFlow::SetAnimations, this); -/*** tracks.lua. -__TODO CONFIRM PROPER BEHAVIOUR__ -@section trackslua -*/ -/*** -@function SetAudioTracks -@tparam table table array-style table with @{AudioTrack} objects -*/ -//TODO confirm proper behaviour - m_lua->set_function("SetAudioTracks", &GameFlow::SetAudioTracks, this); - /*** strings.lua. These functions used in strings.lua, which is generated by TombIDE. You will not need to call them manually. @@ -181,24 +170,9 @@ void GameFlow::SetGameFarView(byte val) } } -void GameFlow::SetAudioTracks(sol::as_table_t>&& src) -{ - std::vector tracks = std::move(src); - SoundTracks.clear(); - - for (auto t : tracks) { - SoundTrackInfo track; - track.Name = t.trackName; - track.Mask = 0; - track.Mode = t.looped ? SOUNDTRACK_PLAYTYPE::BGM : SOUNDTRACK_PLAYTYPE::OneShot; - SoundTracks.push_back(track); - } -} - void GameFlow::LoadGameFlowScript() { ExecuteScript("Scripts/Enums.lua"); - ExecuteScript("Scripts/Tracks.lua"); ExecuteScript("Scripts/Gameflow.lua"); ExecuteScript("Scripts/Strings.lua"); ExecuteScript("Scripts/Settings.lua"); diff --git a/Scripting/src/GameFlowScript.h b/Scripting/src/GameFlowScript.h index eed2e112d..f5c61ede4 100644 --- a/Scripting/src/GameFlowScript.h +++ b/Scripting/src/GameFlowScript.h @@ -38,7 +38,6 @@ public: ~GameFlow(); void AddLevel(GameScriptLevel const& level); - void SetAudioTracks(sol::as_table_t>&& src); void LoadGameFlowScript(); char const * GetString(const char* id) const; void SetStrings(sol::nested>> && src); diff --git a/TR5Main/Game/savegame.cpp b/TR5Main/Game/savegame.cpp index 0ec1f40a3..60b4ecf76 100644 --- a/TR5Main/Game/savegame.cpp +++ b/TR5Main/Game/savegame.cpp @@ -474,7 +474,7 @@ bool SaveGame::Save(int slot) // Legacy soundtrack map std::vector soundTrackMap; - for (auto& track : SoundTracks) { soundTrackMap.push_back(track.Mask); } + for (auto& track : SoundTracks) { soundTrackMap.push_back(track.second.Mask); } auto soundtrackMapOffset = fbb.CreateVector(soundTrackMap); // Flipmaps diff --git a/TR5Main/Sound/sound.cpp b/TR5Main/Sound/sound.cpp index fb935a272..b31144f99 100644 --- a/TR5Main/Sound/sound.cpp +++ b/TR5Main/Sound/sound.cpp @@ -2,6 +2,7 @@ #include "Sound/sound.h" #include +#include #include "Game/camera.h" #include "Game/Lara/lara.h" #include "Game/room.h" @@ -29,7 +30,8 @@ const BASS_BFX_FREEVERB BASS_ReverbTypes[(int)REVERB_TYPE::Count] = // Reverb const std::string TRACKS_PATH = "Audio\\"; std::map SoundTrackMap; -std::vector SoundTracks; +std::unordered_map SoundTracks; +int SecretSoundIndex; static int GlobalMusicVolume; static int GlobalFXVolume; @@ -310,6 +312,35 @@ void FreeSamples() Sound_FreeSample(i); } +void EnumerateLegacyTracks() +{ + auto dir = std::filesystem::path(TRACKS_PATH); + // capture three-digit filenames, or those which start with three digits. + std::regex upToThreeDigits("\\\\((\\d{1,3})[^\\.]*)"); + std::smatch result; + for (const auto& file : std::filesystem::directory_iterator{ dir }) + { + std::string fileName = file.path().string(); + auto bResult = std::regex_search(fileName, result, upToThreeDigits); + if (!result.empty()) + { + // result[0] is the whole match including the leading backslash, so ignore it + // result[1] is the full file name, not including the extension + int index = std::stoi(result[2].str()); + SoundTrackInfo s; + + // TRLE default looping tracks + if (index >= 98 && index <= 111) + { + s.Mode = SOUNDTRACK_PLAYTYPE::BGM; + } + s.Name = result[1]; + SoundTracks.insert(std::make_pair(index, s)); + SecretSoundIndex = std::max(SecretSoundIndex, index); + } + } +} + void PlaySoundTrack(std::string track, SOUNDTRACK_PLAYTYPE mode, QWORD position) { if (track.empty()) @@ -456,7 +487,7 @@ void StopSoundTracks() void ClearSoundTrackMasks() { - for (auto& track : SoundTracks) { track.Mask = 0; } + for (auto& track : SoundTracks) { track.second.Mask = 0; } } // Returns specified soundtrack type's stem name and playhead position. @@ -801,7 +832,7 @@ void SayNo() void PlaySecretTrack() { // Secret soundtrack should be always last one on a list. - PlaySoundTrack(SoundTracks.back().Name, SOUNDTRACK_PLAYTYPE::OneShot); + PlaySoundTrack(SoundTracks.at(SecretSoundIndex).Name, SOUNDTRACK_PLAYTYPE::OneShot); } int GetShatterSound(int shatterID) diff --git a/TR5Main/Specific/winmain.cpp b/TR5Main/Specific/winmain.cpp index c1bdd6739..357d69a9d 100644 --- a/TR5Main/Specific/winmain.cpp +++ b/TR5Main/Specific/winmain.cpp @@ -157,6 +157,9 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine InitTENLog(); + // Collect numbered tracks + EnumerateLegacyTracks(); + // Initialise the new scripting system ScriptInterfaceState::Init();