Kelsidavis-WoWee/src/audio/ui_sound_manager.cpp
Kelsi 39bf8fb01e feat: play audio notification when a whisper is received
Adds UiSoundManager::playWhisperReceived() which uses the dedicated
Whisper_TellMale/Female.wav files (or falls back to iSelectTarget.wav
if absent). The sound is triggered once per new incoming CHAT_MSG_WHISPER
message by scanning new chat history entries in the raid warning overlay
update loop.
2026-03-12 06:12:37 -07:00

240 lines
10 KiB
C++

#include "audio/ui_sound_manager.hpp"
#include "audio/audio_engine.hpp"
#include "pipeline/asset_manager.hpp"
#include "core/logger.hpp"
namespace wowee {
namespace audio {
bool UiSoundManager::initialize(pipeline::AssetManager* assets) {
if (!assets) {
LOG_ERROR("UISoundManager: AssetManager is null");
return false;
}
LOG_INFO("UISoundManager: Initializing...");
// Load window sounds
bagOpenSounds_.resize(1);
bool bagOpenLoaded = loadSound("Sound\\Interface\\iBackPackOpen.wav", bagOpenSounds_[0], assets);
bagCloseSounds_.resize(1);
bool bagCloseLoaded = loadSound("Sound\\Interface\\iBackPackClose.wav", bagCloseSounds_[0], assets);
questLogOpenSounds_.resize(1);
bool questLogOpenLoaded = loadSound("Sound\\Interface\\iQuestLogOpenA.wav", questLogOpenSounds_[0], assets);
questLogCloseSounds_.resize(1);
bool questLogCloseLoaded = loadSound("Sound\\Interface\\iQuestLogCloseA.wav", questLogCloseSounds_[0], assets);
characterSheetOpenSounds_.resize(1);
bool charSheetOpenLoaded = loadSound("Sound\\Interface\\iAbilitiesOpenA.wav", characterSheetOpenSounds_[0], assets);
characterSheetCloseSounds_.resize(1);
bool charSheetCloseLoaded = loadSound("Sound\\Interface\\iAbilitiesCloseA.wav", characterSheetCloseSounds_[0], assets);
auctionOpenSounds_.resize(1);
loadSound("Sound\\Interface\\AuctionWindowOpen.wav", auctionOpenSounds_[0], assets);
auctionCloseSounds_.resize(1);
loadSound("Sound\\Interface\\AuctionWindowClose.wav", auctionCloseSounds_[0], assets);
guildBankOpenSounds_.resize(1);
loadSound("Sound\\Interface\\GuildVaultOpen.wav", guildBankOpenSounds_[0], assets);
guildBankCloseSounds_.resize(1);
loadSound("Sound\\Interface\\GuildVaultClose.wav", guildBankCloseSounds_[0], assets);
// Load button sounds
buttonClickSounds_.resize(1);
bool buttonClickLoaded = loadSound("Sound\\Interface\\iUiInterfaceButtonA.wav", buttonClickSounds_[0], assets);
menuButtonSounds_.resize(1);
bool menuButtonLoaded = loadSound("Sound\\Interface\\iUIMainMenuButtonA.wav", menuButtonSounds_[0], assets);
// Load quest sounds
questActivateSounds_.resize(1);
bool questActivateLoaded = loadSound("Sound\\Interface\\iQuestActivate.wav", questActivateSounds_[0], assets);
questCompleteSounds_.resize(1);
bool questCompleteLoaded = loadSound("Sound\\Interface\\iQuestComplete.wav", questCompleteSounds_[0], assets);
questFailedSounds_.resize(1);
bool questFailedLoaded = loadSound("Sound\\Interface\\igQuestFailed.wav", questFailedSounds_[0], assets);
questUpdateSounds_.resize(1);
loadSound("Sound\\Interface\\iQuestUpdate.wav", questUpdateSounds_[0], assets);
// Load loot sounds
lootCoinSmallSounds_.resize(1);
bool lootCoinSmallLoaded = loadSound("Sound\\Interface\\LootCoinSmall.wav", lootCoinSmallSounds_[0], assets);
lootCoinLargeSounds_.resize(1);
bool lootCoinLargeLoaded = loadSound("Sound\\Interface\\LootCoinLarge.wav", lootCoinLargeSounds_[0], assets);
lootItemSounds_.resize(1);
bool lootItemLoaded = loadSound("Sound\\Interface\\igLootCreature.wav", lootItemSounds_[0], assets);
// Load item pickup sounds
dropSounds_.resize(1);
bool dropLoaded = loadSound("Sound\\Interface\\DropOnGround.wav", dropSounds_[0], assets);
pickupBagSounds_.resize(1);
bool pickupBagLoaded = loadSound("Sound\\Interface\\PickUp\\PickUpBag.wav", pickupBagSounds_[0], assets);
pickupBookSounds_.resize(1);
bool pickupBookLoaded = loadSound("Sound\\Interface\\PickUp\\PickUpBook.wav", pickupBookSounds_[0], assets);
pickupClothSounds_.resize(1);
loadSound("Sound\\Interface\\PickUp\\PickUpCloth_Leather01.wav", pickupClothSounds_[0], assets);
pickupFoodSounds_.resize(1);
loadSound("Sound\\Interface\\PickUp\\PickUpFoodGeneric.wav", pickupFoodSounds_[0], assets);
pickupGemSounds_.resize(1);
loadSound("Sound\\Interface\\PickUp\\PickUpGems.wav", pickupGemSounds_[0], assets);
// Load eating/drinking sounds
eatingSounds_.resize(1);
bool eatingLoaded = loadSound("Sound\\Interface\\iEating1.wav", eatingSounds_[0], assets);
drinkingSounds_.resize(1);
bool drinkingLoaded = loadSound("Sound\\Interface\\iDrinking1.wav", drinkingSounds_[0], assets);
// Load level up sound
levelUpSounds_.resize(1);
bool levelUpLoaded = loadSound("Sound\\Interface\\LevelUp.wav", levelUpSounds_[0], assets);
// Load achievement sound (WotLK: Sound\Interface\AchievementSound.wav)
achievementSounds_.resize(1);
if (!loadSound("Sound\\Interface\\AchievementSound.wav", achievementSounds_[0], assets)) {
// Fallback to level-up sound if achievement sound is missing
achievementSounds_ = levelUpSounds_;
}
// Load error/feedback sounds
errorSounds_.resize(1);
loadSound("Sound\\Interface\\Error.wav", errorSounds_[0], assets);
selectTargetSounds_.resize(1);
loadSound("Sound\\Interface\\iSelectTarget.wav", selectTargetSounds_[0], assets);
deselectTargetSounds_.resize(1);
loadSound("Sound\\Interface\\iDeselectTarget.wav", deselectTargetSounds_[0], assets);
// Whisper notification (falls back to iSelectTarget if the dedicated file is absent)
whisperSounds_.resize(1);
if (!loadSound("Sound\\Interface\\Whisper_TellMale.wav", whisperSounds_[0], assets)) {
if (!loadSound("Sound\\Interface\\Whisper_TellFemale.wav", whisperSounds_[0], assets)) {
whisperSounds_ = selectTargetSounds_;
}
}
LOG_INFO("UISoundManager: Window sounds - Bag: ", (bagOpenLoaded && bagCloseLoaded) ? "YES" : "NO",
", QuestLog: ", (questLogOpenLoaded && questLogCloseLoaded) ? "YES" : "NO",
", CharSheet: ", (charSheetOpenLoaded && charSheetCloseLoaded) ? "YES" : "NO");
LOG_INFO("UISoundManager: Button sounds - Click: ", buttonClickLoaded ? "YES" : "NO",
", Menu: ", menuButtonLoaded ? "YES" : "NO");
LOG_INFO("UISoundManager: Quest sounds - Activate: ", questActivateLoaded ? "YES" : "NO",
", Complete: ", questCompleteLoaded ? "YES" : "NO",
", Failed: ", questFailedLoaded ? "YES" : "NO");
LOG_INFO("UISoundManager: Loot sounds - Coins: ", (lootCoinSmallLoaded && lootCoinLargeLoaded) ? "YES" : "NO",
", Items: ", lootItemLoaded ? "YES" : "NO");
LOG_INFO("UISoundManager: Item sounds - Pickup: ", (pickupBagLoaded && pickupBookLoaded) ? "YES" : "NO",
", Drop: ", dropLoaded ? "YES" : "NO");
LOG_INFO("UISoundManager: Misc sounds - Eating: ", eatingLoaded ? "YES" : "NO",
", Drinking: ", drinkingLoaded ? "YES" : "NO",
", LevelUp: ", levelUpLoaded ? "YES" : "NO");
initialized_ = true;
LOG_INFO("UISoundManager: Initialization complete");
return true;
}
void UiSoundManager::shutdown() {
initialized_ = false;
}
bool UiSoundManager::loadSound(const std::string& path, UISample& sample, pipeline::AssetManager* assets) {
sample.path = path;
sample.loaded = false;
try {
sample.data = assets->readFile(path);
if (!sample.data.empty()) {
sample.loaded = true;
return true;
}
} catch (const std::exception& e) {
LOG_ERROR("UISoundManager: Failed to load ", path, ": ", e.what());
}
return false;
}
void UiSoundManager::playSound(const std::vector<UISample>& library) {
if (!initialized_ || library.empty() || !library[0].loaded) return;
float volume = 0.7f * volumeScale_;
AudioEngine::instance().playSound2D(library[0].data, volume, 1.0f);
}
void UiSoundManager::setVolumeScale(float scale) {
volumeScale_ = std::max(0.0f, std::min(1.0f, scale));
}
// Window sounds
void UiSoundManager::playBagOpen() { playSound(bagOpenSounds_); }
void UiSoundManager::playBagClose() { playSound(bagCloseSounds_); }
void UiSoundManager::playQuestLogOpen() { playSound(questLogOpenSounds_); }
void UiSoundManager::playQuestLogClose() { playSound(questLogCloseSounds_); }
void UiSoundManager::playCharacterSheetOpen() { playSound(characterSheetOpenSounds_); }
void UiSoundManager::playCharacterSheetClose() { playSound(characterSheetCloseSounds_); }
void UiSoundManager::playAuctionHouseOpen() { playSound(auctionOpenSounds_); }
void UiSoundManager::playAuctionHouseClose() { playSound(auctionCloseSounds_); }
void UiSoundManager::playGuildBankOpen() { playSound(guildBankOpenSounds_); }
void UiSoundManager::playGuildBankClose() { playSound(guildBankCloseSounds_); }
// Button sounds
void UiSoundManager::playButtonClick() { playSound(buttonClickSounds_); }
void UiSoundManager::playMenuButtonClick() { playSound(menuButtonSounds_); }
// Quest sounds
void UiSoundManager::playQuestActivate() { playSound(questActivateSounds_); }
void UiSoundManager::playQuestComplete() { playSound(questCompleteSounds_); }
void UiSoundManager::playQuestFailed() { playSound(questFailedSounds_); }
void UiSoundManager::playQuestUpdate() { playSound(questUpdateSounds_); }
// Loot sounds
void UiSoundManager::playLootCoinSmall() { playSound(lootCoinSmallSounds_); }
void UiSoundManager::playLootCoinLarge() { playSound(lootCoinLargeSounds_); }
void UiSoundManager::playLootItem() { playSound(lootItemSounds_); }
// Item sounds
void UiSoundManager::playDropOnGround() { playSound(dropSounds_); }
void UiSoundManager::playPickupBag() { playSound(pickupBagSounds_); }
void UiSoundManager::playPickupBook() { playSound(pickupBookSounds_); }
void UiSoundManager::playPickupCloth() { playSound(pickupClothSounds_); }
void UiSoundManager::playPickupFood() { playSound(pickupFoodSounds_); }
void UiSoundManager::playPickupGem() { playSound(pickupGemSounds_); }
// Eating/drinking
void UiSoundManager::playEating() { playSound(eatingSounds_); }
void UiSoundManager::playDrinking() { playSound(drinkingSounds_); }
// Level up
void UiSoundManager::playLevelUp() { playSound(levelUpSounds_); }
// Achievement
void UiSoundManager::playAchievementAlert() { playSound(achievementSounds_); }
// Error/feedback
void UiSoundManager::playError() { playSound(errorSounds_); }
void UiSoundManager::playTargetSelect() { playSound(selectTargetSounds_); }
void UiSoundManager::playTargetDeselect() { playSound(deselectTargetSounds_); }
// Chat notifications
void UiSoundManager::playWhisperReceived() { playSound(whisperSounds_); }
} // namespace audio
} // namespace wowee