audio: stop precast sound on spell completion, failure, or interrupt

Add AudioEngine::playSound2DStoppable() + stopSound() so callers can
hold a handle and cancel playback early. SpellSoundManager::playPrecast()
now stores the handle in activePrecastId_; stopPrecast() cuts the sound.

playCast() calls stopPrecast() before playing the release sound, so the
channeling audio never bleeds past cast time. SMSG_SPELL_FAILURE and
SMSG_CAST_FAILED both call stopPrecast() so interrupted casts silence
immediately.
This commit is contained in:
Kelsi 2026-03-09 21:04:24 -07:00
parent e0d47040d3
commit 9d1616a11b
5 changed files with 100 additions and 3 deletions

View file

@ -45,6 +45,11 @@ public:
bool playSound2D(const std::vector<uint8_t>& wavData, float volume = 1.0f, float pitch = 1.0f);
bool playSound2D(const std::string& mpqPath, float volume = 1.0f, float pitch = 1.0f);
// Stoppable 2D sound — returns a non-zero handle, or 0 on failure
uint32_t playSound2DStoppable(const std::vector<uint8_t>& wavData, float volume = 1.0f);
// Stop a sound started with playSound2DStoppable (no-op if already finished)
void stopSound(uint32_t id);
// 3D positional sound playback
bool playSound3D(const std::vector<uint8_t>& wavData, const glm::vec3& position,
float volume = 1.0f, float pitch = 1.0f, float maxDistance = 100.0f);
@ -70,8 +75,10 @@ private:
ma_sound* sound;
void* buffer; // ma_audio_buffer* - Keep audio buffer alive
std::shared_ptr<const std::vector<uint8_t>> pcmDataRef; // Keep decoded PCM alive
uint32_t id = 0; // 0 = anonymous (not stoppable)
};
std::vector<ActiveSound> activeSounds_;
uint32_t nextSoundId_ = 1;
// Music track state
ma_sound* musicSound_ = nullptr;

View file

@ -45,6 +45,7 @@ public:
// Spell casting sounds
void playPrecast(MagicSchool school, SpellPower power); // Channeling/preparation
void stopPrecast(); // Stop precast sound early
void playCast(MagicSchool school); // When spell fires
void playImpact(MagicSchool school, SpellPower power); // When spell hits target
@ -96,6 +97,7 @@ private:
// State tracking
float volumeScale_ = 1.0f;
bool initialized_ = false;
uint32_t activePrecastId_ = 0; // Handle from AudioEngine::playSound2DStoppable()
// Helper methods
bool loadSound(const std::string& path, SpellSample& sample, pipeline::AssetManager* assets);