Add complete NPC voice library from Wowhead database

Added all standard NPC greeting sounds for all playable races:
- Human (male/female): 6/5 greetings
- Dwarf (male): 6 greetings
- Gnome (male/female): 6/6 greetings
- Night Elf (male/female): 8/6 greetings
- Orc (male/female): 5/6 greetings
- Tauren (male/female): 5/5 greetings (note: male was missing from Wowhead, added anyway)
- Troll (male/female): 6/5 greetings
- Undead (male/female): 6/6 greetings

Paths from Wowhead: Sound\Creature\[Race][Gender]StandardNPC\
Note: Human male uses "Greetings" (plural), others use "Greeting" (singular)
This commit is contained in:
Kelsi 2026-02-09 01:54:21 -08:00
parent 44a75928ba
commit 838b82e503

View file

@ -23,12 +23,12 @@ bool NpcVoiceManager::initialize(pipeline::AssetManager* assets) {
// Probe for actual sound file paths (NPC sounds are in Sound\Creature\) // Probe for actual sound file paths (NPC sounds are in Sound\Creature\)
LOG_INFO("=== Probing for NPC voice files ==="); LOG_INFO("=== Probing for NPC voice files ===");
std::vector<std::string> testPaths = { std::vector<std::string> testPaths = {
"Sound\\Creature\\humanfemalestandardnpc\\humanfemalestandardnpcgreeting01.ogg", "Sound\\Creature\\HumanMaleStandardNPC\\HumanMaleStandardNPCGreetings01.ogg",
"Sound\\Creature\\humanfemalestandardnpc\\humanfemalestandardnpcgreeting02.ogg", "Sound\\Creature\\HumanFemaleStandardNPC\\HumanFemaleStandardNPCGreeting01.ogg",
"Sound\\Creature\\humanmalestandardnpc\\humanmalestandardnpcgreeting01.ogg", "Sound\\Creature\\DwarfMaleStandardNPC\\DwarfMaleStandardNPCGreeting01.ogg",
"Sound\\Creature\\humanmalestandardnpc\\humanmalestandardnpcgreeting02.ogg", "Sound\\Creature\\NightElfMaleStandardNPC\\NightElfMaleStandardNPCGreeting01.ogg",
"Sound\\Creature\\NPCGhoul\\NPCGhoulVendor01.ogg", "Sound\\Creature\\OrcMaleStandardNPC\\OrcMaleStandardNPCGreeting01.ogg",
"Sound\\Creature\\NPCGhoul\\NPCGhoulVendor02.ogg", "Sound\\Creature\\TaurenFemaleStandardNPC\\TaurenFemaleStandardNPCGreeting01.ogg",
}; };
for (const auto& path : testPaths) { for (const auto& path : testPaths) {
bool exists = assetManager_->fileExists(path); bool exists = assetManager_->fileExists(path);
@ -65,55 +65,142 @@ void NpcVoiceManager::shutdown() {
void NpcVoiceManager::loadVoiceSounds() { void NpcVoiceManager::loadVoiceSounds() {
if (!assetManager_) return; if (!assetManager_) return;
// Generic NPC greetings (using standard NPC creature sounds in .ogg format) // Load all standard NPC greetings from Wowhead database
// These are the actual NPC vendor/innkeeper greetings from Sound/Creature/ // Note: Human male uses "Greetings" (plural), others use "Greeting" (singular)
std::vector<std::string> genericPaths = {
"Sound\\Creature\\humanfemalestandardnpc\\humanfemalestandardnpcgreeting01.ogg",
"Sound\\Creature\\humanfemalestandardnpc\\humanfemalestandardnpcgreeting02.ogg",
"Sound\\Creature\\humanfemalestandardnpc\\humanfemalestandardnpcgreeting03.ogg",
"Sound\\Creature\\humanmalestandardnpc\\humanmalestandardnpcgreeting01.ogg",
"Sound\\Creature\\humanmalestandardnpc\\humanmalestandardnpcgreeting02.ogg",
"Sound\\Creature\\humanmalestandardnpc\\humanmalestandardnpcgreeting03.ogg",
};
// Generic - mix of all races for variety
auto& genericVoices = voiceLibrary_[VoiceType::GENERIC]; auto& genericVoices = voiceLibrary_[VoiceType::GENERIC];
for (const auto& path : genericPaths) { 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",
}) {
VoiceSample sample; VoiceSample sample;
if (loadSound(path, sample)) { if (loadSound(path, sample)) genericVoices.push_back(std::move(sample));
genericVoices.push_back(std::move(sample));
}
} }
// Human male NPCs // Human Male
std::vector<std::string> humanMalePaths = {
"Sound\\Creature\\humanmalestandardnpc\\humanmalestandardnpcgreeting01.ogg",
"Sound\\Creature\\humanmalestandardnpc\\humanmalestandardnpcgreeting02.ogg",
"Sound\\Creature\\humanmalestandardnpc\\humanmalestandardnpcgreeting03.ogg",
};
auto& humanMale = voiceLibrary_[VoiceType::HUMAN_MALE]; auto& humanMale = voiceLibrary_[VoiceType::HUMAN_MALE];
for (const auto& path : humanMalePaths) { for (int i = 1; i <= 6; ++i) {
std::string path = "Sound\\Creature\\HumanMaleStandardNPC\\HumanMaleStandardNPCGreetings0" + std::to_string(i) + ".ogg";
VoiceSample sample; VoiceSample sample;
if (loadSound(path, sample)) { if (loadSound(path, sample)) humanMale.push_back(std::move(sample));
humanMale.push_back(std::move(sample));
}
} }
// Human female NPCs // Human Female
std::vector<std::string> humanFemalePaths = {
"Sound\\Creature\\humanfemalestandardnpc\\humanfemalestandardnpcgreeting01.ogg",
"Sound\\Creature\\humanfemalestandardnpc\\humanfemalestandardnpcgreeting02.ogg",
"Sound\\Creature\\humanfemalestandardnpc\\humanfemalestandardnpcgreeting03.ogg",
};
auto& humanFemale = voiceLibrary_[VoiceType::HUMAN_FEMALE]; auto& humanFemale = voiceLibrary_[VoiceType::HUMAN_FEMALE];
for (const auto& path : humanFemalePaths) { for (int i = 1; i <= 5; ++i) {
std::string path = "Sound\\Creature\\HumanFemaleStandardNPC\\HumanFemaleStandardNPCGreeting0" + std::to_string(i) + ".ogg";
VoiceSample sample; VoiceSample sample;
if (loadSound(path, sample)) { if (loadSound(path, sample)) humanFemale.push_back(std::move(sample));
humanFemale.push_back(std::move(sample));
}
} }
// TODO: Add other race-specific NPC greetings when needed // Dwarf Male
// For now, all NPCs will use human standard greetings as fallback 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";
VoiceSample sample;
if (loadSound(path, sample)) dwarfMale.push_back(std::move(sample));
}
// 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";
VoiceSample sample;
if (loadSound(path, sample)) gnomeMale.push_back(std::move(sample));
}
// 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";
VoiceSample sample;
if (loadSound(path, sample)) gnomeFemale.push_back(std::move(sample));
}
// 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";
VoiceSample sample;
if (loadSound(path, sample)) nelfMale.push_back(std::move(sample));
}
// 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";
VoiceSample sample;
if (loadSound(path, sample)) nelfFemale.push_back(std::move(sample));
}
// 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";
VoiceSample sample;
if (loadSound(path, sample)) orcMale.push_back(std::move(sample));
}
// 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";
VoiceSample sample;
if (loadSound(path, sample)) orcFemale.push_back(std::move(sample));
}
// 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";
VoiceSample sample;
if (loadSound(path, sample)) taurenMale.push_back(std::move(sample));
}
// 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";
VoiceSample sample;
if (loadSound(path, sample)) taurenFemale.push_back(std::move(sample));
}
// 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";
VoiceSample sample;
if (loadSound(path, sample)) trollMale.push_back(std::move(sample));
}
// 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";
VoiceSample sample;
if (loadSound(path, sample)) trollFemale.push_back(std::move(sample));
}
// 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";
VoiceSample sample;
if (loadSound(path, sample)) undeadMale.push_back(std::move(sample));
}
// 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";
VoiceSample sample;
if (loadSound(path, sample)) undeadFemale.push_back(std::move(sample));
}
// Log loaded voice types // Log loaded voice types
int totalLoaded = 0; int totalLoaded = 0;