mirror of
https://github.com/Kelsidavis/WoWee.git
synced 2026-03-25 08:30:13 +00:00
Implement mount ambient sounds
Added full mount sound system with: - Wing flap sounds for flying mounts (gryphon/wyvern) when moving - Wing idle/hovering sounds when stationary in air - Breathing/snorting sounds for ground mounts when idle - Occasional whinny sounds for ground mounts when moving Sounds are loaded from MPQ files and played via AudioEngine with randomized pitch/volume variation. Mount sound manager tracks mount type, movement state, and flying state to play appropriate ambient sounds at natural intervals. Updated setMounted() to accept creature display ID and notify the mount sound manager, which uses display ID ranges to detect mount type (flying vs ground).
This commit is contained in:
parent
0b6b403848
commit
0fed931aa0
5 changed files with 221 additions and 23 deletions
|
|
@ -2,11 +2,14 @@
|
|||
#include "audio/audio_engine.hpp"
|
||||
#include "pipeline/asset_manager.hpp"
|
||||
#include "core/logger.hpp"
|
||||
#include <random>
|
||||
|
||||
namespace wowee {
|
||||
namespace audio {
|
||||
|
||||
MountSoundManager::MountSoundManager() = default;
|
||||
MountSoundManager::MountSoundManager() {
|
||||
lastSoundUpdate_ = std::chrono::steady_clock::now();
|
||||
}
|
||||
|
||||
MountSoundManager::~MountSoundManager() {
|
||||
shutdown();
|
||||
|
|
@ -14,23 +17,125 @@ MountSoundManager::~MountSoundManager() {
|
|||
|
||||
bool MountSoundManager::initialize(pipeline::AssetManager* assets) {
|
||||
assetManager_ = assets;
|
||||
LOG_INFO("Mount sound manager initialized");
|
||||
if (!assetManager_) {
|
||||
LOG_WARNING("Mount sound manager: no asset manager");
|
||||
return false;
|
||||
}
|
||||
|
||||
loadMountSounds();
|
||||
|
||||
int totalSamples = wingFlapSounds_.size() + wingIdleSounds_.size() +
|
||||
horseBreathSounds_.size() + horseMoveSounds_.size();
|
||||
LOG_INFO("Mount sound manager initialized (", totalSamples, " clips)");
|
||||
return true;
|
||||
}
|
||||
|
||||
void MountSoundManager::shutdown() {
|
||||
stopAllMountSounds();
|
||||
mounted_ = false;
|
||||
wingFlapSounds_.clear();
|
||||
wingIdleSounds_.clear();
|
||||
horseBreathSounds_.clear();
|
||||
horseMoveSounds_.clear();
|
||||
assetManager_ = nullptr;
|
||||
}
|
||||
|
||||
void MountSoundManager::update(float deltaTime) {
|
||||
(void)deltaTime;
|
||||
void MountSoundManager::loadMountSounds() {
|
||||
if (!assetManager_) return;
|
||||
|
||||
// Flying mount wing flaps (movement)
|
||||
std::vector<std::string> wingFlapPaths = {
|
||||
"Sound\\Creature\\Gryphon\\GryphonWingFlap1.wav",
|
||||
"Sound\\Creature\\Gryphon\\GryphonWingFlap2.wav",
|
||||
"Sound\\Creature\\Gryphon\\GryphonWingFlap3.wav",
|
||||
"Sound\\Creature\\WindRider\\WindRiderWingFlap1.wav",
|
||||
"Sound\\Creature\\WindRider\\WindRiderWingFlap2.wav",
|
||||
};
|
||||
|
||||
for (const auto& path : wingFlapPaths) {
|
||||
MountSample sample;
|
||||
if (loadSound(path, sample)) {
|
||||
wingFlapSounds_.push_back(std::move(sample));
|
||||
}
|
||||
}
|
||||
|
||||
// Flying mount idle/hovering
|
||||
std::vector<std::string> wingIdlePaths = {
|
||||
"Sound\\Creature\\Gryphon\\GryphonIdle1.wav",
|
||||
"Sound\\Creature\\Gryphon\\GryphonIdle2.wav",
|
||||
"Sound\\Creature\\WindRider\\WindRiderIdle1.wav",
|
||||
};
|
||||
|
||||
for (const auto& path : wingIdlePaths) {
|
||||
MountSample sample;
|
||||
if (loadSound(path, sample)) {
|
||||
wingIdleSounds_.push_back(std::move(sample));
|
||||
}
|
||||
}
|
||||
|
||||
// Ground mount breathing/idle
|
||||
std::vector<std::string> horseBreathPaths = {
|
||||
"Sound\\Creature\\Horse\\HorseBreath1.wav",
|
||||
"Sound\\Creature\\Horse\\HorseBreath2.wav",
|
||||
"Sound\\Creature\\Horse\\HorseSnort1.wav",
|
||||
};
|
||||
|
||||
for (const auto& path : horseBreathPaths) {
|
||||
MountSample sample;
|
||||
if (loadSound(path, sample)) {
|
||||
horseBreathSounds_.push_back(std::move(sample));
|
||||
}
|
||||
}
|
||||
|
||||
// Ground mount movement ambient
|
||||
std::vector<std::string> horseMovePaths = {
|
||||
"Sound\\Creature\\Horse\\HorseWhinny1.wav",
|
||||
"Sound\\Creature\\Horse\\HorseWhinny2.wav",
|
||||
};
|
||||
|
||||
for (const auto& path : horseMovePaths) {
|
||||
MountSample sample;
|
||||
if (loadSound(path, sample)) {
|
||||
horseMoveSounds_.push_back(std::move(sample));
|
||||
}
|
||||
}
|
||||
|
||||
if (!wingFlapSounds_.empty()) {
|
||||
LOG_INFO("Loaded ", wingFlapSounds_.size(), " wing flap sounds");
|
||||
}
|
||||
if (!wingIdleSounds_.empty()) {
|
||||
LOG_INFO("Loaded ", wingIdleSounds_.size(), " wing idle sounds");
|
||||
}
|
||||
if (!horseBreathSounds_.empty()) {
|
||||
LOG_INFO("Loaded ", horseBreathSounds_.size(), " horse breath sounds");
|
||||
}
|
||||
if (!horseMoveSounds_.empty()) {
|
||||
LOG_INFO("Loaded ", horseMoveSounds_.size(), " horse move sounds");
|
||||
}
|
||||
}
|
||||
|
||||
bool MountSoundManager::loadSound(const std::string& path, MountSample& sample) {
|
||||
if (!assetManager_ || !assetManager_->fileExists(path)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
auto data = assetManager_->readFile(path);
|
||||
if (data.empty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
sample.path = path;
|
||||
sample.data = std::move(data);
|
||||
return true;
|
||||
}
|
||||
|
||||
void MountSoundManager::update(float deltaTime) {
|
||||
if (!mounted_) {
|
||||
soundLoopTimer_ = 0.0f;
|
||||
return;
|
||||
}
|
||||
|
||||
soundLoopTimer_ += deltaTime;
|
||||
updateMountSounds();
|
||||
}
|
||||
|
||||
|
|
@ -104,29 +209,83 @@ void MountSoundManager::updateMountSounds() {
|
|||
return;
|
||||
}
|
||||
|
||||
// TODO: Implement actual mount sound playback
|
||||
// For now, just log state changes
|
||||
static bool lastMoving = false;
|
||||
static bool lastFlying = false;
|
||||
static std::mt19937 rng(std::random_device{}());
|
||||
|
||||
if (moving_ != lastMoving || flying_ != lastFlying) {
|
||||
LOG_INFO("Mount sound state: moving=", moving_, " flying=", flying_,
|
||||
" type=", static_cast<int>(currentMountType_));
|
||||
lastMoving = moving_;
|
||||
lastFlying = flying_;
|
||||
// Flying mounts
|
||||
if (currentMountType_ == MountType::FLYING && flying_) {
|
||||
if (moving_ && !wingFlapSounds_.empty()) {
|
||||
// Wing flaps when moving (play periodically for continuous flapping sound)
|
||||
if (soundLoopTimer_ >= 1.2f) {
|
||||
std::uniform_int_distribution<size_t> dist(0, wingFlapSounds_.size() - 1);
|
||||
const auto& sample = wingFlapSounds_[dist(rng)];
|
||||
std::uniform_real_distribution<float> volumeDist(0.4f, 0.5f);
|
||||
std::uniform_real_distribution<float> pitchDist(0.95f, 1.05f);
|
||||
AudioEngine::instance().playSound2D(
|
||||
sample.data,
|
||||
volumeDist(rng) * volumeScale_,
|
||||
pitchDist(rng)
|
||||
);
|
||||
soundLoopTimer_ = 0.0f;
|
||||
playingMovementSound_ = true;
|
||||
}
|
||||
} else if (!moving_ && !wingIdleSounds_.empty()) {
|
||||
// Idle/hovering sounds (less frequent)
|
||||
if (soundLoopTimer_ >= 3.5f) {
|
||||
std::uniform_int_distribution<size_t> dist(0, wingIdleSounds_.size() - 1);
|
||||
const auto& sample = wingIdleSounds_[dist(rng)];
|
||||
std::uniform_real_distribution<float> volumeDist(0.3f, 0.4f);
|
||||
std::uniform_real_distribution<float> pitchDist(0.98f, 1.02f);
|
||||
AudioEngine::instance().playSound2D(
|
||||
sample.data,
|
||||
volumeDist(rng) * volumeScale_,
|
||||
pitchDist(rng)
|
||||
);
|
||||
soundLoopTimer_ = 0.0f;
|
||||
playingIdleSound_ = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Ground mounts
|
||||
else if (currentMountType_ == MountType::GROUND && !flying_) {
|
||||
if (moving_ && !horseMoveSounds_.empty()) {
|
||||
// Occasional whinny/ambient sounds while moving
|
||||
if (soundLoopTimer_ >= 8.0f) {
|
||||
std::uniform_int_distribution<size_t> dist(0, horseMoveSounds_.size() - 1);
|
||||
const auto& sample = horseMoveSounds_[dist(rng)];
|
||||
std::uniform_real_distribution<float> volumeDist(0.35f, 0.45f);
|
||||
std::uniform_real_distribution<float> pitchDist(0.97f, 1.03f);
|
||||
AudioEngine::instance().playSound2D(
|
||||
sample.data,
|
||||
volumeDist(rng) * volumeScale_,
|
||||
pitchDist(rng)
|
||||
);
|
||||
soundLoopTimer_ = 0.0f;
|
||||
playingMovementSound_ = true;
|
||||
}
|
||||
} else if (!moving_ && !horseBreathSounds_.empty()) {
|
||||
// Breathing/snorting when idle
|
||||
if (soundLoopTimer_ >= 4.5f) {
|
||||
std::uniform_int_distribution<size_t> dist(0, horseBreathSounds_.size() - 1);
|
||||
const auto& sample = horseBreathSounds_[dist(rng)];
|
||||
std::uniform_real_distribution<float> volumeDist(0.25f, 0.35f);
|
||||
std::uniform_real_distribution<float> pitchDist(0.98f, 1.02f);
|
||||
AudioEngine::instance().playSound2D(
|
||||
sample.data,
|
||||
volumeDist(rng) * volumeScale_,
|
||||
pitchDist(rng)
|
||||
);
|
||||
soundLoopTimer_ = 0.0f;
|
||||
playingIdleSound_ = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Load and play appropriate looping sounds:
|
||||
// - Flying + moving: wing flaps (fast loop)
|
||||
// - Flying + idle: wing flaps (slow loop) or hovering sound
|
||||
// - Ground + moving: galloping/hoofbeats (pace based on speed)
|
||||
// - Ground + idle: breathing, fidgeting sounds (occasional)
|
||||
}
|
||||
|
||||
void MountSoundManager::stopAllMountSounds() {
|
||||
// TODO: Stop any active looping mount sounds
|
||||
// Reset state flags
|
||||
playingMovementSound_ = false;
|
||||
playingIdleSound_ = false;
|
||||
soundLoopTimer_ = 0.0f;
|
||||
}
|
||||
|
||||
} // namespace audio
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue