mirror of
https://github.com/Kelsidavis/WoWee.git
synced 2026-03-22 23:30:14 +00:00
Fix NPC voices to use correct WAV format and gender detection
WotLK 3.3.5a uses .wav files for NPC voices, not .ogg as shown in retail Wowhead. Fixed audio engine to preserve original sample rate from WAV files (preventing chipmunk playback). Implemented race/gender detection using CreatureDisplayInfo.dbc and CreatureDisplayInfoExtra.dbc to play correct voice types for each NPC.
This commit is contained in:
parent
5f57a83332
commit
4a7e599764
4 changed files with 84 additions and 48 deletions
|
|
@ -16,6 +16,7 @@ namespace ui { class UIManager; }
|
|||
namespace auth { class AuthHandler; }
|
||||
namespace game { class GameHandler; class World; class NpcManager; }
|
||||
namespace pipeline { class AssetManager; }
|
||||
namespace audio { enum class VoiceType; }
|
||||
|
||||
namespace core {
|
||||
|
||||
|
|
@ -91,6 +92,7 @@ private:
|
|||
void despawnOnlineGameObject(uint64_t guid);
|
||||
void buildGameObjectDisplayLookups();
|
||||
std::string getGameObjectModelPathForDisplayId(uint32_t displayId) const;
|
||||
audio::VoiceType detectVoiceTypeFromDisplayId(uint32_t displayId) const;
|
||||
|
||||
static Application* instance;
|
||||
|
||||
|
|
|
|||
|
|
@ -182,6 +182,7 @@ bool AudioEngine::playSound2D(const std::vector<uint8_t>& wavData, float volume,
|
|||
pcmData.data(),
|
||||
nullptr // No custom allocator
|
||||
);
|
||||
bufferConfig.sampleRate = sampleRate; // Critical: preserve original sample rate!
|
||||
|
||||
ma_audio_buffer* audioBuffer = new ma_audio_buffer();
|
||||
result = ma_audio_buffer_init(&bufferConfig, audioBuffer);
|
||||
|
|
@ -242,8 +243,6 @@ bool AudioEngine::playSound3D(const std::vector<uint8_t>& wavData, const glm::ve
|
|||
return false;
|
||||
}
|
||||
|
||||
(void)pitch; // Pitch not supported yet
|
||||
|
||||
// Decode WAV data first
|
||||
ma_decoder decoder;
|
||||
ma_decoder_config decoderConfig = ma_decoder_config_init_default();
|
||||
|
|
@ -255,6 +254,7 @@ bool AudioEngine::playSound3D(const std::vector<uint8_t>& wavData, const glm::ve
|
|||
);
|
||||
|
||||
if (result != MA_SUCCESS) {
|
||||
LOG_WARNING("playSound3D: Failed to decode WAV, error: ", result);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -262,6 +262,8 @@ bool AudioEngine::playSound3D(const std::vector<uint8_t>& wavData, const glm::ve
|
|||
ma_uint32 channels = decoder.outputChannels;
|
||||
ma_uint32 sampleRate = decoder.outputSampleRate;
|
||||
|
||||
LOG_DEBUG("playSound3D: Decoded WAV - format:", format, " channels:", channels, " sampleRate:", sampleRate, " pitch:", pitch);
|
||||
|
||||
ma_uint64 totalFrames;
|
||||
result = ma_decoder_get_length_in_pcm_frames(&decoder, &totalFrames);
|
||||
if (result != MA_SUCCESS) {
|
||||
|
|
@ -286,7 +288,7 @@ bool AudioEngine::playSound3D(const std::vector<uint8_t>& wavData, const glm::ve
|
|||
|
||||
pcmData.resize(framesRead * channels * ma_get_bytes_per_sample(format));
|
||||
|
||||
// Create audio buffer
|
||||
// Create audio buffer with correct sample rate
|
||||
ma_audio_buffer_config bufferConfig = ma_audio_buffer_config_init(
|
||||
format,
|
||||
channels,
|
||||
|
|
@ -294,6 +296,7 @@ bool AudioEngine::playSound3D(const std::vector<uint8_t>& wavData, const glm::ve
|
|||
pcmData.data(),
|
||||
nullptr
|
||||
);
|
||||
bufferConfig.sampleRate = sampleRate; // Critical: preserve original sample rate!
|
||||
|
||||
ma_audio_buffer* audioBuffer = new ma_audio_buffer();
|
||||
result = ma_audio_buffer_init(&bufferConfig, audioBuffer);
|
||||
|
|
@ -302,17 +305,18 @@ bool AudioEngine::playSound3D(const std::vector<uint8_t>& wavData, const glm::ve
|
|||
return false;
|
||||
}
|
||||
|
||||
// Create 3D sound (spatialization enabled)
|
||||
// Create 3D sound (spatialization enabled, pitch enabled)
|
||||
ma_sound* sound = new ma_sound();
|
||||
result = ma_sound_init_from_data_source(
|
||||
engine_,
|
||||
audioBuffer,
|
||||
MA_SOUND_FLAG_DECODE | MA_SOUND_FLAG_ASYNC | MA_SOUND_FLAG_NO_PITCH,
|
||||
MA_SOUND_FLAG_DECODE | MA_SOUND_FLAG_ASYNC, // Removed NO_PITCH flag
|
||||
nullptr,
|
||||
sound
|
||||
);
|
||||
|
||||
if (result != MA_SUCCESS) {
|
||||
LOG_WARNING("playSound3D: Failed to create sound, error: ", result);
|
||||
ma_audio_buffer_uninit(audioBuffer);
|
||||
delete audioBuffer;
|
||||
delete sound;
|
||||
|
|
@ -322,6 +326,7 @@ bool AudioEngine::playSound3D(const std::vector<uint8_t>& wavData, const glm::ve
|
|||
// Set 3D position and attenuation
|
||||
ma_sound_set_position(sound, position.x, position.y, position.z);
|
||||
ma_sound_set_volume(sound, volume * masterVolume_);
|
||||
ma_sound_set_pitch(sound, pitch); // Enable pitch variation
|
||||
ma_sound_set_attenuation_model(sound, ma_attenuation_model_inverse);
|
||||
ma_sound_set_min_gain(sound, 0.0f);
|
||||
ma_sound_set_max_gain(sound, 1.0f);
|
||||
|
|
|
|||
|
|
@ -20,26 +20,13 @@ bool NpcVoiceManager::initialize(pipeline::AssetManager* assets) {
|
|||
return false;
|
||||
}
|
||||
|
||||
// Comprehensive probe - try forward slashes (MPQ internal format)
|
||||
LOG_INFO("=== Searching for NPC voice files (testing patterns) ===");
|
||||
// Files are .WAV not .OGG in WotLK 3.3.5a!
|
||||
LOG_INFO("=== Probing for NPC voice files (.wav format) ===");
|
||||
std::vector<std::string> testPaths = {
|
||||
// Forward slashes (MPQ internal format)
|
||||
"Sound/Creature/HumanMaleStandardNPC/HumanMaleStandardNPCGreetings01.ogg",
|
||||
"Sound/Creature/HumanFemaleStandardNPC/HumanFemaleStandardNPCGreeting01.ogg",
|
||||
|
||||
// Backslashes (Windows format)
|
||||
"Sound\\Creature\\HumanMaleStandardNPC\\HumanMaleStandardNPCGreetings01.ogg",
|
||||
"Sound\\Creature\\HumanFemaleStandardNPC\\HumanFemaleStandardNPCGreeting01.ogg",
|
||||
|
||||
// Lowercase with forward slashes
|
||||
"sound/creature/humanmalestandardnpc/humanmalestandardnpcgreetings01.ogg",
|
||||
|
||||
// PC voice files with forward slashes
|
||||
"Sound/Character/Human/HumanVocMaleHello01.wav",
|
||||
"Sound/Character/Human/HumanVocFemaleHello01.wav",
|
||||
|
||||
// PC voice files with backslashes
|
||||
"Sound\\Character\\Human\\HumanVocMaleHello01.wav",
|
||||
"Sound\\Creature\\HumanMaleStandardNPC\\HumanMaleStandardNPCGreeting01.wav",
|
||||
"Sound\\Creature\\HumanFemaleStandardNPC\\HumanFemaleStandardNPCGreeting01.wav",
|
||||
"Sound\\Creature\\DwarfMaleStandardNPC\\DwarfMaleStandardNPCGreeting01.wav",
|
||||
"Sound\\Creature\\OrcMaleStandardNPC\\OrcMaleStandardNPCGreeting01.wav",
|
||||
};
|
||||
for (const auto& path : testPaths) {
|
||||
bool exists = assetManager_->fileExists(path);
|
||||
|
|
@ -76,18 +63,18 @@ void NpcVoiceManager::shutdown() {
|
|||
void NpcVoiceManager::loadVoiceSounds() {
|
||||
if (!assetManager_) return;
|
||||
|
||||
// Load all standard NPC greetings from Wowhead database
|
||||
// Note: Human male uses "Greetings" (plural), others use "Greeting" (singular)
|
||||
// WotLK 3.3.5a uses .WAV files, not .OGG!
|
||||
// Files use "Greeting" (singular) not "Greetings"
|
||||
|
||||
// Generic - mix of all races for variety
|
||||
auto& genericVoices = voiceLibrary_[VoiceType::GENERIC];
|
||||
for (const auto& path : {
|
||||
"Sound\\Creature\\HumanMaleStandardNPC\\HumanMaleStandardNPCGreetings01.ogg",
|
||||
"Sound\\Creature\\HumanFemaleStandardNPC\\HumanFemaleStandardNPCGreeting01.ogg",
|
||||
"Sound\\Creature\\DwarfMaleStandardNPC\\DwarfMaleStandardNPCGreeting01.ogg",
|
||||
"Sound\\Creature\\GnomeMaleStandardNPC\\GnomeMaleStandardNPCGreeting01.ogg",
|
||||
"Sound\\Creature\\NightElfMaleStandardNPC\\NightElfMaleStandardNPCGreeting01.ogg",
|
||||
"Sound\\Creature\\OrcMaleStandardNPC\\OrcMaleStandardNPCGreeting01.ogg",
|
||||
"Sound\\Creature\\HumanMaleStandardNPC\\HumanMaleStandardNPCGreeting01.wav",
|
||||
"Sound\\Creature\\HumanFemaleStandardNPC\\HumanFemaleStandardNPCGreeting01.wav",
|
||||
"Sound\\Creature\\DwarfMaleStandardNPC\\DwarfMaleStandardNPCGreeting01.wav",
|
||||
"Sound\\Creature\\GnomeMaleStandardNPC\\GnomeMaleStandardNPCGreeting01.wav",
|
||||
"Sound\\Creature\\NightElfMaleStandardNPC\\NightElfMaleStandardNPCGreeting01.wav",
|
||||
"Sound\\Creature\\OrcMaleStandardNPC\\OrcMaleStandardNPCGreeting01.wav",
|
||||
}) {
|
||||
VoiceSample sample;
|
||||
if (loadSound(path, sample)) genericVoices.push_back(std::move(sample));
|
||||
|
|
@ -96,7 +83,7 @@ void NpcVoiceManager::loadVoiceSounds() {
|
|||
// Human Male
|
||||
auto& humanMale = voiceLibrary_[VoiceType::HUMAN_MALE];
|
||||
for (int i = 1; i <= 6; ++i) {
|
||||
std::string path = "Sound\\Creature\\HumanMaleStandardNPC\\HumanMaleStandardNPCGreetings0" + std::to_string(i) + ".ogg";
|
||||
std::string path = "Sound\\Creature\\HumanMaleStandardNPC\\HumanMaleStandardNPCGreeting0" + std::to_string(i) + ".wav";
|
||||
VoiceSample sample;
|
||||
if (loadSound(path, sample)) humanMale.push_back(std::move(sample));
|
||||
}
|
||||
|
|
@ -104,7 +91,7 @@ void NpcVoiceManager::loadVoiceSounds() {
|
|||
// Human Female
|
||||
auto& humanFemale = voiceLibrary_[VoiceType::HUMAN_FEMALE];
|
||||
for (int i = 1; i <= 5; ++i) {
|
||||
std::string path = "Sound\\Creature\\HumanFemaleStandardNPC\\HumanFemaleStandardNPCGreeting0" + std::to_string(i) + ".ogg";
|
||||
std::string path = "Sound\\Creature\\HumanFemaleStandardNPC\\HumanFemaleStandardNPCGreeting0" + std::to_string(i) + ".wav";
|
||||
VoiceSample sample;
|
||||
if (loadSound(path, sample)) humanFemale.push_back(std::move(sample));
|
||||
}
|
||||
|
|
@ -112,7 +99,7 @@ void NpcVoiceManager::loadVoiceSounds() {
|
|||
// Dwarf Male
|
||||
auto& dwarfMale = voiceLibrary_[VoiceType::DWARF_MALE];
|
||||
for (int i = 1; i <= 6; ++i) {
|
||||
std::string path = "Sound\\Creature\\DwarfMaleStandardNPC\\DwarfMaleStandardNPCGreeting0" + std::to_string(i) + ".ogg";
|
||||
std::string path = "Sound\\Creature\\DwarfMaleStandardNPC\\DwarfMaleStandardNPCGreeting0" + std::to_string(i) + ".wav";
|
||||
VoiceSample sample;
|
||||
if (loadSound(path, sample)) dwarfMale.push_back(std::move(sample));
|
||||
}
|
||||
|
|
@ -120,7 +107,7 @@ void NpcVoiceManager::loadVoiceSounds() {
|
|||
// Gnome Male
|
||||
auto& gnomeMale = voiceLibrary_[VoiceType::GNOME_MALE];
|
||||
for (int i = 1; i <= 6; ++i) {
|
||||
std::string path = "Sound\\Creature\\GnomeMaleStandardNPC\\GnomeMaleStandardNPCGreeting0" + std::to_string(i) + ".ogg";
|
||||
std::string path = "Sound\\Creature\\GnomeMaleStandardNPC\\GnomeMaleStandardNPCGreeting0" + std::to_string(i) + ".wav";
|
||||
VoiceSample sample;
|
||||
if (loadSound(path, sample)) gnomeMale.push_back(std::move(sample));
|
||||
}
|
||||
|
|
@ -128,7 +115,7 @@ void NpcVoiceManager::loadVoiceSounds() {
|
|||
// Gnome Female
|
||||
auto& gnomeFemale = voiceLibrary_[VoiceType::GNOME_FEMALE];
|
||||
for (int i = 1; i <= 6; ++i) {
|
||||
std::string path = "Sound\\Creature\\GnomeFemaleStandardNPC\\GnomeFemaleStandardNPCGreeting0" + std::to_string(i) + ".ogg";
|
||||
std::string path = "Sound\\Creature\\GnomeFemaleStandardNPC\\GnomeFemaleStandardNPCGreeting0" + std::to_string(i) + ".wav";
|
||||
VoiceSample sample;
|
||||
if (loadSound(path, sample)) gnomeFemale.push_back(std::move(sample));
|
||||
}
|
||||
|
|
@ -136,7 +123,7 @@ void NpcVoiceManager::loadVoiceSounds() {
|
|||
// Night Elf Male
|
||||
auto& nelfMale = voiceLibrary_[VoiceType::NIGHTELF_MALE];
|
||||
for (int i = 1; i <= 8; ++i) {
|
||||
std::string path = "Sound\\Creature\\NightElfMaleStandardNPC\\NightElfMaleStandardNPCGreeting0" + std::to_string(i) + ".ogg";
|
||||
std::string path = "Sound\\Creature\\NightElfMaleStandardNPC\\NightElfMaleStandardNPCGreeting0" + std::to_string(i) + ".wav";
|
||||
VoiceSample sample;
|
||||
if (loadSound(path, sample)) nelfMale.push_back(std::move(sample));
|
||||
}
|
||||
|
|
@ -144,7 +131,7 @@ void NpcVoiceManager::loadVoiceSounds() {
|
|||
// Night Elf Female
|
||||
auto& nelfFemale = voiceLibrary_[VoiceType::NIGHTELF_FEMALE];
|
||||
for (int i = 1; i <= 6; ++i) {
|
||||
std::string path = "Sound\\Creature\\NightElfFemaleStandardNPC\\NightElfFemaleStandardNPCGreeting0" + std::to_string(i) + ".ogg";
|
||||
std::string path = "Sound\\Creature\\NightElfFemaleStandardNPC\\NightElfFemaleStandardNPCGreeting0" + std::to_string(i) + ".wav";
|
||||
VoiceSample sample;
|
||||
if (loadSound(path, sample)) nelfFemale.push_back(std::move(sample));
|
||||
}
|
||||
|
|
@ -152,7 +139,7 @@ void NpcVoiceManager::loadVoiceSounds() {
|
|||
// Orc Male
|
||||
auto& orcMale = voiceLibrary_[VoiceType::ORC_MALE];
|
||||
for (int i = 1; i <= 5; ++i) {
|
||||
std::string path = "Sound\\Creature\\OrcMaleStandardNPC\\OrcMaleStandardNPCGreeting0" + std::to_string(i) + ".ogg";
|
||||
std::string path = "Sound\\Creature\\OrcMaleStandardNPC\\OrcMaleStandardNPCGreeting0" + std::to_string(i) + ".wav";
|
||||
VoiceSample sample;
|
||||
if (loadSound(path, sample)) orcMale.push_back(std::move(sample));
|
||||
}
|
||||
|
|
@ -160,7 +147,7 @@ void NpcVoiceManager::loadVoiceSounds() {
|
|||
// Orc Female
|
||||
auto& orcFemale = voiceLibrary_[VoiceType::ORC_FEMALE];
|
||||
for (int i = 1; i <= 6; ++i) {
|
||||
std::string path = "Sound\\Creature\\OrcFemaleStandardNPC\\OrcFemaleStandardNPCGreeting0" + std::to_string(i) + ".ogg";
|
||||
std::string path = "Sound\\Creature\\OrcFemaleStandardNPC\\OrcFemaleStandardNPCGreeting0" + std::to_string(i) + ".wav";
|
||||
VoiceSample sample;
|
||||
if (loadSound(path, sample)) orcFemale.push_back(std::move(sample));
|
||||
}
|
||||
|
|
@ -168,7 +155,7 @@ void NpcVoiceManager::loadVoiceSounds() {
|
|||
// Tauren Male
|
||||
auto& taurenMale = voiceLibrary_[VoiceType::TAUREN_MALE];
|
||||
for (int i = 1; i <= 5; ++i) {
|
||||
std::string path = "Sound\\Creature\\TaurenMaleStandardNPC\\TaurenMaleStandardNPCGreeting0" + std::to_string(i) + ".ogg";
|
||||
std::string path = "Sound\\Creature\\TaurenMaleStandardNPC\\TaurenMaleStandardNPCGreeting0" + std::to_string(i) + ".wav";
|
||||
VoiceSample sample;
|
||||
if (loadSound(path, sample)) taurenMale.push_back(std::move(sample));
|
||||
}
|
||||
|
|
@ -176,7 +163,7 @@ void NpcVoiceManager::loadVoiceSounds() {
|
|||
// Tauren Female
|
||||
auto& taurenFemale = voiceLibrary_[VoiceType::TAUREN_FEMALE];
|
||||
for (int i = 1; i <= 5; ++i) {
|
||||
std::string path = "Sound\\Creature\\TaurenFemaleStandardNPC\\TaurenFemaleStandardNPCGreeting0" + std::to_string(i) + ".ogg";
|
||||
std::string path = "Sound\\Creature\\TaurenFemaleStandardNPC\\TaurenFemaleStandardNPCGreeting0" + std::to_string(i) + ".wav";
|
||||
VoiceSample sample;
|
||||
if (loadSound(path, sample)) taurenFemale.push_back(std::move(sample));
|
||||
}
|
||||
|
|
@ -184,7 +171,7 @@ void NpcVoiceManager::loadVoiceSounds() {
|
|||
// Troll Male
|
||||
auto& trollMale = voiceLibrary_[VoiceType::TROLL_MALE];
|
||||
for (int i = 1; i <= 6; ++i) {
|
||||
std::string path = "Sound\\Creature\\TrollMaleStandardNPC\\TrollMaleStandardNPCGreeting0" + std::to_string(i) + ".ogg";
|
||||
std::string path = "Sound\\Creature\\TrollMaleStandardNPC\\TrollMaleStandardNPCGreeting0" + std::to_string(i) + ".wav";
|
||||
VoiceSample sample;
|
||||
if (loadSound(path, sample)) trollMale.push_back(std::move(sample));
|
||||
}
|
||||
|
|
@ -192,7 +179,7 @@ void NpcVoiceManager::loadVoiceSounds() {
|
|||
// Troll Female
|
||||
auto& trollFemale = voiceLibrary_[VoiceType::TROLL_FEMALE];
|
||||
for (int i = 1; i <= 5; ++i) {
|
||||
std::string path = "Sound\\Creature\\TrollFemaleStandardNPC\\TrollFemaleStandardNPCGreeting0" + std::to_string(i) + ".ogg";
|
||||
std::string path = "Sound\\Creature\\TrollFemaleStandardNPC\\TrollFemaleStandardNPCGreeting0" + std::to_string(i) + ".wav";
|
||||
VoiceSample sample;
|
||||
if (loadSound(path, sample)) trollFemale.push_back(std::move(sample));
|
||||
}
|
||||
|
|
@ -200,7 +187,7 @@ void NpcVoiceManager::loadVoiceSounds() {
|
|||
// Undead Male
|
||||
auto& undeadMale = voiceLibrary_[VoiceType::UNDEAD_MALE];
|
||||
for (int i = 1; i <= 6; ++i) {
|
||||
std::string path = "Sound\\Creature\\UndeadMaleStandardNPC\\UndeadMaleStandardNPCGreeting0" + std::to_string(i) + ".ogg";
|
||||
std::string path = "Sound\\Creature\\UndeadMaleStandardNPC\\UndeadMaleStandardNPCGreeting0" + std::to_string(i) + ".wav";
|
||||
VoiceSample sample;
|
||||
if (loadSound(path, sample)) undeadMale.push_back(std::move(sample));
|
||||
}
|
||||
|
|
@ -208,7 +195,7 @@ void NpcVoiceManager::loadVoiceSounds() {
|
|||
// Undead Female
|
||||
auto& undeadFemale = voiceLibrary_[VoiceType::UNDEAD_FEMALE];
|
||||
for (int i = 1; i <= 6; ++i) {
|
||||
std::string path = "Sound\\Creature\\UndeadFemaleStandardNPC\\UndeadFemaleStandardNPCGreeting0" + std::to_string(i) + ".ogg";
|
||||
std::string path = "Sound\\Creature\\UndeadFemaleStandardNPC\\UndeadFemaleStandardNPCGreeting0" + std::to_string(i) + ".wav";
|
||||
VoiceSample sample;
|
||||
if (loadSound(path, sample)) undeadFemale.push_back(std::move(sample));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -820,7 +820,17 @@ void Application::setupUICallbacks() {
|
|||
if (renderer && renderer->getNpcVoiceManager()) {
|
||||
// Convert canonical to render coords for 3D audio
|
||||
glm::vec3 renderPos = core::coords::canonicalToRender(position);
|
||||
renderer->getNpcVoiceManager()->playGreeting(guid, audio::VoiceType::GENERIC, renderPos);
|
||||
|
||||
// Detect voice type from NPC display ID
|
||||
audio::VoiceType voiceType = audio::VoiceType::GENERIC;
|
||||
auto entity = gameHandler->getEntityManager().getEntity(guid);
|
||||
if (entity && entity->getType() == game::ObjectType::UNIT) {
|
||||
auto unit = std::static_pointer_cast<game::Unit>(entity);
|
||||
uint32_t displayId = unit->getDisplayId();
|
||||
voiceType = detectVoiceTypeFromDisplayId(displayId);
|
||||
}
|
||||
|
||||
renderer->getNpcVoiceManager()->playGreeting(guid, voiceType, renderPos);
|
||||
}
|
||||
});
|
||||
|
||||
|
|
@ -1926,6 +1936,38 @@ std::string Application::getModelPathForDisplayId(uint32_t displayId) const {
|
|||
return itPath->second;
|
||||
}
|
||||
|
||||
audio::VoiceType Application::detectVoiceTypeFromDisplayId(uint32_t displayId) const {
|
||||
// Look up display data
|
||||
auto itDisplay = displayDataMap_.find(displayId);
|
||||
if (itDisplay == displayDataMap_.end() || itDisplay->second.extraDisplayId == 0) {
|
||||
return audio::VoiceType::GENERIC; // Not a humanoid or no extra data
|
||||
}
|
||||
|
||||
// Look up humanoid extra data (race/sex info)
|
||||
auto itExtra = humanoidExtraMap_.find(itDisplay->second.extraDisplayId);
|
||||
if (itExtra == humanoidExtraMap_.end()) {
|
||||
return audio::VoiceType::GENERIC;
|
||||
}
|
||||
|
||||
uint8_t raceId = itExtra->second.raceId;
|
||||
uint8_t sexId = itExtra->second.sexId;
|
||||
|
||||
// Map (raceId, sexId) to VoiceType
|
||||
// Race IDs: 1=Human, 2=Orc, 3=Dwarf, 4=NightElf, 5=Undead, 6=Tauren, 7=Gnome, 8=Troll
|
||||
// Sex IDs: 0=Male, 1=Female
|
||||
switch (raceId) {
|
||||
case 1: return (sexId == 0) ? audio::VoiceType::HUMAN_MALE : audio::VoiceType::HUMAN_FEMALE;
|
||||
case 2: return (sexId == 0) ? audio::VoiceType::ORC_MALE : audio::VoiceType::ORC_FEMALE;
|
||||
case 3: return (sexId == 0) ? audio::VoiceType::DWARF_MALE : audio::VoiceType::GENERIC; // No dwarf female voices loaded
|
||||
case 4: return (sexId == 0) ? audio::VoiceType::NIGHTELF_MALE : audio::VoiceType::NIGHTELF_FEMALE;
|
||||
case 5: return (sexId == 0) ? audio::VoiceType::UNDEAD_MALE : audio::VoiceType::UNDEAD_FEMALE;
|
||||
case 6: return (sexId == 0) ? audio::VoiceType::TAUREN_MALE : audio::VoiceType::TAUREN_FEMALE;
|
||||
case 7: return (sexId == 0) ? audio::VoiceType::GNOME_MALE : audio::VoiceType::GNOME_FEMALE;
|
||||
case 8: return (sexId == 0) ? audio::VoiceType::TROLL_MALE : audio::VoiceType::TROLL_FEMALE;
|
||||
default: return audio::VoiceType::GENERIC;
|
||||
}
|
||||
}
|
||||
|
||||
void Application::buildGameObjectDisplayLookups() {
|
||||
if (gameObjectLookupsBuilt_ || !assetManager || !assetManager->isInitialized()) return;
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue