mirror of
https://github.com/zeldaret/ss
synced 2026-06-22 08:35:39 -04:00
447 lines
15 KiB
C++
447 lines
15 KiB
C++
#include "d/snd/d_snd_small_effect_mgr.h"
|
|
|
|
#include "common.h"
|
|
#include "d/snd/d_snd_bgm_mgr.h"
|
|
#include "d/snd/d_snd_checkers.h"
|
|
#include "d/snd/d_snd_control_player_mgr.h"
|
|
#include "d/snd/d_snd_distant_sound_actor_pool.h"
|
|
#include "d/snd/d_snd_mgr.h"
|
|
#include "d/snd/d_snd_player_mgr.h"
|
|
#include "d/snd/d_snd_source.h"
|
|
#include "d/snd/d_snd_source_enums.h"
|
|
#include "d/snd/d_snd_util.h"
|
|
#include "d/snd/d_snd_wzsound.h"
|
|
#include "egg/audio/eggAudioRmtSpeakerMgr.h"
|
|
#include "nw4r/snd/snd_SeqSoundHandle.h"
|
|
#include "nw4r/snd/snd_SoundHandle.h"
|
|
#include "nw4r/snd/snd_SoundStartable.h"
|
|
#include "nw4r/snd/snd_global.h"
|
|
#include "rvl/OS/OSFastCast.h"
|
|
#include "toBeSorted/music_mgrs.h"
|
|
|
|
SND_DISPOSER_DEFINE(dSndSmallEffectMgr_c)
|
|
|
|
dSndSmallEffectMgr_c::dSndSmallEffectMgr_c()
|
|
: field_0x10(0), mTextboxAdvanceSound(-1), field_0x40(0), field_0x42(0), field_0x44(0) {
|
|
for (int i = 0; i < NUM_DELAYED_SOUNDS; i++) {
|
|
mDelayedSoundIds[i] = -1;
|
|
mDelayedSoundTimers[i] = 0;
|
|
}
|
|
}
|
|
|
|
void dSndSmallEffectMgr_c::calc() {
|
|
if (!dSndPlayerMgr_c::GetInstance()->checkFlag(0x4)) {
|
|
for (int i = 0; i < NUM_DELAYED_SOUNDS; i++) {
|
|
if (mDelayedSoundIds[i] != -1) {
|
|
mDelayedSoundTimers[i]--;
|
|
if (mDelayedSoundTimers[i] <= 0) {
|
|
playSoundInternalChecked(mDelayedSoundIds[i], nullptr);
|
|
mDelayedSoundIds[i] = -1;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
bool dSndSmallEffectMgr_c::playSound(u32 soundId) {
|
|
if (soundId >= SE_S_BUTTON_CALL_L && soundId <= SE_S_PLAY_GUIDE_BUTTON_BLINK) {
|
|
soundId = SE_S_BUTTON_CALL_L;
|
|
} else if (soundId >= SE_S_BUTTON_CALL_R && soundId <= SE_S_2_BUTTON_BLINK) {
|
|
soundId = SE_S_BUTTON_CALL_R;
|
|
} else {
|
|
switch (soundId) {
|
|
case SE_S_BOSS_KEY_TRANS: {
|
|
stopSounds(dSndPlayerMgr_c::PLAYER_SMALL_NORMAL, SE_S_BOSS_KEY_TRANS_OFF, 5);
|
|
break;
|
|
}
|
|
case SE_S_BOSS_KEY_TRANS_OFF: {
|
|
stopSounds(dSndPlayerMgr_c::PLAYER_SMALL_NORMAL, SE_S_BOSS_KEY_TRANS, 5);
|
|
break;
|
|
}
|
|
case SE_S_HP_GAUGE_UP: {
|
|
if (isPlayingSound(dSndPlayerMgr_c::PLAYER_SMALL_NORMAL, SE_S_HEART_PIECE_GET)) {
|
|
return false;
|
|
}
|
|
break;
|
|
}
|
|
case SE_S_HEART_PIECE_GET: {
|
|
if (isPlayingSound(dSndPlayerMgr_c::PLAYER_SMALL_NORMAL, SE_S_HP_GAUGE_UP)) {
|
|
return false;
|
|
}
|
|
break;
|
|
}
|
|
case SE_S_MAP_OPEN:
|
|
case SE_S_MENU_IN: {
|
|
stopSounds(dSndPlayerMgr_c::PLAYER_SMALL_NORMAL, SE_S_HELP_OUT, 1);
|
|
break;
|
|
}
|
|
case SE_S_HELP_OUT: {
|
|
if (isPlayingSound(dSndPlayerMgr_c::PLAYER_SMALL_NORMAL, SE_S_MENU_IN) ||
|
|
isPlayingSound(dSndPlayerMgr_c::PLAYER_SMALL_NORMAL, SE_S_MAP_OPEN)) {
|
|
return false;
|
|
}
|
|
break;
|
|
}
|
|
case SE_S_MENU_SELECT_TURN_PAGE_LEFT: {
|
|
if (isPlayingSound(dSndPlayerMgr_c::PLAYER_SMALL_NORMAL, SE_S_SHOP_STK_STOCK_SELECT_TURN_PAGE_LEFT)) {
|
|
return false;
|
|
}
|
|
break;
|
|
}
|
|
case SE_S_MENU_SELECT_TURN_PAGE_RIGHT: {
|
|
if (isPlayingSound(dSndPlayerMgr_c::PLAYER_SMALL_NORMAL, SE_S_SHOP_STK_STOCK_SELECT_TURN_PAGE_RIGHT)) {
|
|
return false;
|
|
}
|
|
break;
|
|
}
|
|
case SE_S_ITEM_SELECT_START: {
|
|
if (isPlayingSound(dSndPlayerMgr_c::PLAYER_SMALL_NORMAL, SE_S_BM_KEEP_ERROR)) {
|
|
soundId = SE_S_ITEM_SELECT_START_WAIT;
|
|
}
|
|
break;
|
|
}
|
|
case SE_S_SKIP: {
|
|
if (fn_80364DA0(ENEMY_SOUND_MGR)) {
|
|
fn_80365020(ENEMY_SOUND_MGR);
|
|
}
|
|
break;
|
|
}
|
|
case SE_S_WINDOW_PRESS_A: {
|
|
if (isPlayingSound(dSndPlayerMgr_c::PLAYER_SMALL_IMPORTANT, SE_S_POINTER_OK)) {
|
|
return false;
|
|
}
|
|
break;
|
|
}
|
|
case SE_S_MENU_P1_HOLD_POINTER: {
|
|
stopSounds(dSndPlayerMgr_c::PLAYER_SMALL_NORMAL, SE_S_MENU_P1_POINT_ITEM, 0);
|
|
break;
|
|
}
|
|
case SE_S_MENU_P1_POINT_ITEM: {
|
|
if (isPlayingSound(dSndPlayerMgr_c::PLAYER_SMALL_NORMAL, SE_S_MENU_P1_HOLD_POINTER)) {
|
|
return false;
|
|
}
|
|
break;
|
|
}
|
|
case SE_S_FIRST_PERSON_ON:
|
|
case SE_S_FIRST_PERSON_OFF: {
|
|
if (!isPlayingSound(dSndPlayerMgr_c::PLAYER_SMALL_NORMAL, SE_S_DOWSING_SELECT_START)) {
|
|
playSound(SE_S_DOWSING_SELECT_START);
|
|
}
|
|
break;
|
|
}
|
|
case SE_S_DOWSING_WAIT:
|
|
if (isPlayingSound(dSndPlayerMgr_c::PLAYER_SMALL_NORMAL, SE_S_FIRST_PERSON_ON)) {
|
|
return false;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
return playSoundInternal(soundId);
|
|
}
|
|
|
|
bool dSndSmallEffectMgr_c::playSoundWithPan(u32 soundId, f32 pan) {
|
|
bool ok = playSoundInternal(soundId);
|
|
if (ok) {
|
|
if (pan > 1.0f) {
|
|
pan = 1.0f;
|
|
} else if (pan < -1.0f) {
|
|
pan = -1.0f;
|
|
}
|
|
mNormalSound.SetPan(pan);
|
|
}
|
|
return ok;
|
|
}
|
|
|
|
nw4r::snd::SoundHandle *dSndSmallEffectMgr_c::getHoldSoundHandle(u32 soundId) {
|
|
// Find an existing handle holding this sound
|
|
for (int i = 0; i < NUM_HOLD_SOUNDS; i++) {
|
|
nw4r::snd::SoundHandle *h = &mHoldSoundHandles[i];
|
|
if (h->GetId() == soundId) {
|
|
return h;
|
|
}
|
|
}
|
|
|
|
// Find a free handle
|
|
for (int i = 0; i < NUM_HOLD_SOUNDS; i++) {
|
|
nw4r::snd::SoundHandle *h = &mHoldSoundHandles[i];
|
|
if (!h->IsAttachedSound()) {
|
|
return h;
|
|
}
|
|
}
|
|
|
|
// Drop a lower-priority sound
|
|
nw4r::snd::SoundHandle *least = nullptr;
|
|
nw4r::snd::SoundArchive::SoundInfo info;
|
|
dSndMgr_c::GetInstance()->getArchive()->ReadSoundInfo(soundId, &info);
|
|
s32 newPriority = info.playerPriority;
|
|
|
|
for (int i = 0; i < NUM_HOLD_SOUNDS; i++) {
|
|
nw4r::snd::SoundHandle *h = &mHoldSoundHandles[i];
|
|
dSndMgr_c::GetInstance()->getArchive()->ReadSoundInfo(h->GetId(), &info);
|
|
if (info.playerPriority < newPriority) {
|
|
newPriority = info.playerPriority;
|
|
least = h;
|
|
}
|
|
}
|
|
return least;
|
|
}
|
|
|
|
bool dSndSmallEffectMgr_c::holdSound(u32 soundId) {
|
|
nw4r::snd::SoundHandle *h = getHoldSoundHandle(soundId);
|
|
if (h != nullptr) {
|
|
return holdSound(soundId, h);
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool dSndSmallEffectMgr_c::holdSoundWithPitch(u32 soundId, f32 pitch) {
|
|
nw4r::snd::SoundHandle *h = getHoldSoundHandle(soundId);
|
|
bool ok = false;
|
|
if (h != nullptr) {
|
|
ok = holdSound(soundId, h);
|
|
}
|
|
if (ok && soundId == SE_S_GAUGE_SHIELD_UP_LV) {
|
|
f32 actualPitch = pitch + 1.0f;
|
|
if (actualPitch > 2.0f) {
|
|
actualPitch = 2.0f;
|
|
}
|
|
h->SetPitch(actualPitch);
|
|
}
|
|
return ok;
|
|
}
|
|
|
|
bool dSndSmallEffectMgr_c::holdSound(u32 soundId, nw4r::snd::SoundHandle *handle) {
|
|
if (handle == nullptr) {
|
|
return false;
|
|
}
|
|
u32 param = dSndPlayerMgr_c::GetInstance()->getSomeUserParam(soundId);
|
|
if ((param & 0x80000000) != 0) {
|
|
return false;
|
|
}
|
|
nw4r::snd::SoundStartable::StartResult result =
|
|
dSndMgr_c::GetInstance()->getPlayer().HoldSoundReturnStatus(handle, soundId, nullptr);
|
|
if (result == nw4r::snd::SoundStartable::START_SUCCESS) {
|
|
if ((param & 0x8) != 0) {
|
|
if (EGG::AudioRmtSpeakerMgr::getWpadVolume() != 0) {
|
|
handle->SetOutputLineFlag(nw4r::snd::OUTPUT_LINE_REMOTE_1);
|
|
}
|
|
} else if ((param & 0x4) != 0) {
|
|
handle->SetOutputLineFlag(nw4r::snd::OUTPUT_LINE_MAIN | nw4r::snd::OUTPUT_LINE_REMOTE_1);
|
|
}
|
|
}
|
|
|
|
return result == nw4r::snd::SoundStartable::START_SUCCESS;
|
|
}
|
|
|
|
bool dSndSmallEffectMgr_c::playSoundAtPosition(u32 soundId, const nw4r::math::VEC3 *position) {
|
|
return dSndDistantSoundActorPool_c::GetInstance()->startSound(soundId, position);
|
|
}
|
|
|
|
bool dSndSmallEffectMgr_c::playSoundAtPosition2(u32 soundId, const nw4r::math::VEC3 *position) {
|
|
return dSndDistantSoundActorPool_c::GetInstance()->startSound(soundId, position);
|
|
}
|
|
|
|
bool dSndSmallEffectMgr_c::holdBowChargeSound(f32 remainingChargeAmount) {
|
|
nw4r::snd::SoundHandle *pHandle = getHoldSoundHandle(SE_S_BW_FOCUS_LV);
|
|
bool ok = false;
|
|
if (pHandle != nullptr) {
|
|
ok = holdSound(SE_S_BW_FOCUS_LV, pHandle);
|
|
}
|
|
if (ok) {
|
|
f32 chargeProgress = 1.0f - remainingChargeAmount;
|
|
if (chargeProgress < 0.0f) {
|
|
chargeProgress = 0.0f;
|
|
}
|
|
|
|
// Bow charge sound increases in volume as it's charging up
|
|
f32 volume = chargeProgress / 2.0f;
|
|
volume += 0.5f;
|
|
if (volume > 1.0f) {
|
|
volume = 1.0f;
|
|
}
|
|
pHandle->SetVolume(volume, 0);
|
|
|
|
// Bow charge sound pitches up by 25% until it's complete
|
|
f32 pitch = chargeProgress / 4.0f + 1.0f;
|
|
pHandle->SetPitch(pitch);
|
|
}
|
|
return ok;
|
|
}
|
|
|
|
bool dSndSmallEffectMgr_c::holdFinisherPromptSound(const nw4r::math::VEC3 *position) {
|
|
if (fn_80364DA0(ENEMY_SOUND_MGR)) {
|
|
return false;
|
|
}
|
|
return dSndDistantSoundActorPool_c::GetInstance()->holdSound(SE_S_FOCUS_FINISHER_LV, position);
|
|
}
|
|
|
|
bool dSndSmallEffectMgr_c::playDowsingPingSound(f32 volume, f32 pitch) {
|
|
bool result = playSoundInternal(SE_S_DOWSING_SOUND, &mDowsingSoundHandle);
|
|
if (result) {
|
|
mDowsingSoundHandle.SetVolume(volume, 0);
|
|
if (pitch < 0.8408964f) {
|
|
pitch = 0.8408964f;
|
|
} else if (pitch < 1.0594631f) {
|
|
pitch = 1.0f;
|
|
} else if (pitch < 1.122462f) {
|
|
pitch = 1.0594631f;
|
|
} else if (pitch < 1.1892071f) {
|
|
pitch = 1.122462f;
|
|
} else if (pitch < 1.2599211f) {
|
|
pitch = 1.1892071f;
|
|
} else if (pitch < 1.3348398f) {
|
|
pitch = 1.2599211f;
|
|
} else if (pitch < 1.4142135f) {
|
|
pitch = 1.3348398f;
|
|
} else if (pitch < 1.4983071f) {
|
|
pitch = 1.4142135f; // sqrt(2)
|
|
} else if (pitch > 1.4983071f) {
|
|
pitch = 1.4983071f;
|
|
}
|
|
mDowsingSoundHandle.SetPitch(pitch);
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
bool dSndSmallEffectMgr_c::holdDowsingNearestSound() {
|
|
return holdSound(SE_S_DOWSING_SOUND_NEAREST, &mDowsingSoundHandle);
|
|
}
|
|
|
|
bool dSndSmallEffectMgr_c::playSkbSound(u32 soundId) {
|
|
switch (soundId) {
|
|
case SE_S_SK_POINT:
|
|
case SE_S_SK_INPUT:
|
|
if (isPlayingSound(SE_S_SK_INPUT_DECIDE)) {
|
|
return false;
|
|
}
|
|
break;
|
|
case SE_S_SK_INPUT_DECIDE:
|
|
stopSounds(dSndPlayerMgr_c::PLAYER_SMALL_NORMAL, SE_S_SK_POINT, 0);
|
|
stopSounds(dSndPlayerMgr_c::PLAYER_SMALL_NORMAL, SE_S_SK_INPUT, 0);
|
|
break;
|
|
case SE_S_SK_DELETE_ERROR: stopSounds(dSndPlayerMgr_c::PLAYER_SMALL_NORMAL, SE_S_SK_INPUT, 0); break;
|
|
}
|
|
return playSound(soundId);
|
|
}
|
|
|
|
void dSndSmallEffectMgr_c::stopSounds(u32 playerIdx, u32 soundId, s32 fadeFrames) {
|
|
SoundStopper stopper(soundId, fadeFrames);
|
|
dSndControlPlayerMgr_c::GetInstance()->getPlayer1(playerIdx)->ForEachSound(stopper, false);
|
|
}
|
|
|
|
void dSndSmallEffectMgr_c::stopSounds(u32 soundId, s32 fadeFrames) {
|
|
for (s32 playerId = dSndPlayerMgr_c::PLAYER_SMALL_IMPORTANT; playerId <= dSndControlPlayerMgr_c::sPlayerMax;
|
|
playerId++) {
|
|
stopSounds(playerId, soundId, fadeFrames);
|
|
}
|
|
}
|
|
|
|
bool dSndSmallEffectMgr_c::isPlayingSound(u32 playerIdx, u32 soundId) {
|
|
bool isPlaying = false;
|
|
IsCurrentSoundIdChecker check(soundId, &isPlaying);
|
|
dSndControlPlayerMgr_c::GetInstance()->getPlayer1(playerIdx)->ForEachSound(check, false);
|
|
return isPlaying;
|
|
}
|
|
|
|
bool dSndSmallEffectMgr_c::isPlayingSound(u32 soundId) {
|
|
for (s32 playerId = dSndPlayerMgr_c::PLAYER_SMALL_IMPORTANT; playerId <= dSndControlPlayerMgr_c::sPlayerMax;
|
|
playerId++) {
|
|
if (isPlayingSound(playerId, soundId)) {
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool dSndSmallEffectMgr_c::playButtonPressSoundWhenAdvancingTextBoxes(f32 ratio) {
|
|
if (mTextboxAdvanceSound == -1) {
|
|
return false;
|
|
}
|
|
|
|
bool ok = playSound(mTextboxAdvanceSound);
|
|
if (ok) {
|
|
s16 varValue;
|
|
f32 value = ratio * 100.0f;
|
|
OSf32tos16(&value, &varValue);
|
|
nw4r::snd::SeqSoundHandle handle(&mNormalSound);
|
|
handle.WriteVariable(10, varValue);
|
|
}
|
|
|
|
return ok;
|
|
}
|
|
|
|
void dSndSmallEffectMgr_c::resetButtonPressSound() {
|
|
mTextboxAdvanceSound = -1;
|
|
}
|
|
|
|
void dSndSmallEffectMgr_c::setButtonPressSound(dSoundSource_c *source) {
|
|
resetButtonPressSound();
|
|
if (source != nullptr) {
|
|
mTextboxAdvanceSound = dSoundSource_c::modifySoundId(SE_S_TALK_CHAR, source);
|
|
if (mTextboxAdvanceSound == SE_S_TALK_CHAR) {
|
|
resetButtonPressSound();
|
|
}
|
|
}
|
|
}
|
|
|
|
bool dSndSmallEffectMgr_c::playBattleHitSound(BattleHitSound_e type, dSoundSource_c *source) {
|
|
// if we're not in battle, don't play any of the hit effects
|
|
if (!dSndBgmMgr_c::GetInstance()->isPlayingAnyBattleMusic()) {
|
|
return false;
|
|
}
|
|
|
|
if (source != nullptr) {
|
|
const char *name = source->getName();
|
|
s32 sourceType = source->getSourceType();
|
|
if (sourceType == SND_SOURCE_OBJECT_40) {
|
|
return false;
|
|
}
|
|
|
|
switch (type) {
|
|
case BATTLE_TUTTI_GUARDJUST:
|
|
if (sourceType >= SND_SOURCE_BULLET) {
|
|
// Do not play battle effects for countering bullets
|
|
return false;
|
|
}
|
|
break;
|
|
case BATTLE_TUTTI_FINISH:
|
|
if (streq(name, "BLasBos")) {
|
|
// Do not play finish effect for finishing Demise
|
|
return false;
|
|
}
|
|
break;
|
|
default: break;
|
|
}
|
|
}
|
|
u32 soundId = BGM_BATTLE_TUTTI;
|
|
switch (type) {
|
|
case BATTLE_TUTTI_TURN: soundId = BGM_BATTLE_TUTTI_TURN; break;
|
|
case BATTLE_TUTTI_JUMP: soundId = BGM_BATTLE_TUTTI_JUMP; break;
|
|
case BATTLE_TUTTI_FINISH: soundId = BGM_BATTLE_TUTTI_FINISH; break;
|
|
case BATTLE_TUTTI_GUARDJUST: soundId = BGM_BATTLE_TUTTI_GUARDJUST; break;
|
|
default: break;
|
|
}
|
|
|
|
if (mBattleTuttiHandle.IsAttachedSound()) {
|
|
u32 alreadyPlayingSound = mBattleTuttiHandle.GetId();
|
|
// BGM_BATTLE_TUTTI_ sounds are ordered by priority apparently
|
|
if (alreadyPlayingSound > soundId) {
|
|
return false;
|
|
}
|
|
if (alreadyPlayingSound == BGM_BATTLE_TUTTI) {
|
|
nw4r::snd::SeqSoundHandle handle(&mBattleTuttiHandle);
|
|
// Do not allow stopping BGM_BATTLE_TUTTI too early
|
|
if ((s32)handle.GetTick() < 12) {
|
|
return false;
|
|
}
|
|
}
|
|
mBattleTuttiHandle.Stop(5);
|
|
}
|
|
|
|
// TODO ...
|
|
|
|
return true;
|
|
}
|