Browse Source

Add melee monster TTS and audio cues volume

access
mojsior 3 months ago
parent
commit
114b5793ee
  1. 75
      Source/diablo.cpp
  2. 11
      Source/engine/sound.cpp
  3. 1
      Source/engine/sound.h
  4. 11
      Source/engine/sound_pool.cpp
  5. 1
      Source/engine/sound_stubs.cpp
  6. 55
      Source/gamemenu.cpp
  7. 2
      Source/options.cpp
  8. 2
      Source/options.h

75
Source/diablo.cpp

@ -1901,6 +1901,80 @@ void UpdateBossHealthAnnouncements()
}
}
void UpdateAttackableMonsterAnnouncements()
{
static std::optional<int> LastAttackableMonsterId;
if (MyPlayer == nullptr) {
LastAttackableMonsterId = std::nullopt;
return;
}
if (leveltype == DTYPE_TOWN) {
LastAttackableMonsterId = std::nullopt;
return;
}
if (MyPlayerIsDead || MyPlayer->_pmode == PM_DEATH || MyPlayer->hasNoLife()) {
LastAttackableMonsterId = std::nullopt;
return;
}
if (InGameMenu() || invflag) {
LastAttackableMonsterId = std::nullopt;
return;
}
const Player &player = *MyPlayer;
const Point playerPosition = player.position.tile;
int bestRotations = 5;
std::optional<int> bestId;
for (size_t i = 0; i < ActiveMonsterCount; i++) {
const int monsterId = static_cast<int>(ActiveMonsters[i]);
const Monster &monster = Monsters[monsterId];
if (monster.isInvalid)
continue;
if ((monster.flags & MFLAG_HIDDEN) != 0)
continue;
if (monster.hitPoints <= 0)
continue;
if (monster.isPlayerMinion())
continue;
if (!monster.isPossibleToHit())
continue;
const Point monsterPosition = monster.position.tile;
if (playerPosition.WalkingDistance(monsterPosition) > 1)
continue;
const int d1 = static_cast<int>(player._pdir);
const int d2 = static_cast<int>(GetDirection(playerPosition, monsterPosition));
int rotations = std::abs(d1 - d2);
if (rotations > 4)
rotations = 4 - (rotations % 4);
if (!bestId || rotations < bestRotations || (rotations == bestRotations && monsterId < *bestId)) {
bestRotations = rotations;
bestId = monsterId;
}
}
if (!bestId) {
LastAttackableMonsterId = std::nullopt;
return;
}
if (LastAttackableMonsterId && *LastAttackableMonsterId == *bestId)
return;
LastAttackableMonsterId = *bestId;
const std::string_view name = Monsters[*bestId].name();
if (!name.empty())
SpeakText(name, /*force=*/true);
}
void GameLogic()
{
if (!ProcessInput()) {
@ -1929,6 +2003,7 @@ void GameLogic()
ProcessVisionList();
UpdateBossHealthAnnouncements();
UpdateProximityAudioCues();
UpdateAttackableMonsterAnnouncements();
} else {
gGameLogicStep = GameLogicStep::ProcessTowners;
ProcessTowners();

11
Source/engine/sound.cpp

@ -247,6 +247,7 @@ TSnd::~TSnd()
void snd_init()
{
GetOptions().Audio.soundVolume.SetValue(CapVolume(*GetOptions().Audio.soundVolume));
GetOptions().Audio.audioCuesVolume.SetValue(CapVolume(*GetOptions().Audio.audioCuesVolume));
gbSoundOn = *GetOptions().Audio.soundVolume > VOLUME_MIN;
sgbSaveSoundOn = gbSoundOn;
@ -391,6 +392,16 @@ int sound_get_or_set_sound_volume(int volume)
return *GetOptions().Audio.soundVolume;
}
int sound_get_or_set_audio_cues_volume(int volume)
{
if (volume == 1)
return *GetOptions().Audio.audioCuesVolume;
GetOptions().Audio.audioCuesVolume.SetValue(volume);
return *GetOptions().Audio.audioCuesVolume;
}
void music_mute()
{
if (music.IsLoaded())

1
Source/engine/sound.h

@ -75,6 +75,7 @@ void music_start(_music_id nTrack);
void sound_disable_music(bool disable);
int sound_get_or_set_music_volume(int volume);
int sound_get_or_set_sound_volume(int volume);
int sound_get_or_set_audio_cues_volume(int volume);
void music_mute();
void music_unmute();

11
Source/engine/sound_pool.cpp

@ -116,7 +116,16 @@ struct SoundPool::Impl {
if (sample.IsPlaying())
sample.Stop();
return sample.PlayWithVolumeAndPan(logVolume, sound_get_or_set_sound_volume(/*volume=*/1), logPan);
const int soundVolume = sound_get_or_set_sound_volume(/*volume=*/1);
const int cuesVolume = sound_get_or_set_audio_cues_volume(/*volume=*/1);
const int range = VOLUME_MAX - VOLUME_MIN;
const int soundOffset = std::clamp(soundVolume - VOLUME_MIN, 0, range);
const int cuesOffset = std::clamp(cuesVolume - VOLUME_MIN, 0, range);
const int combinedOffset = (soundOffset * cuesOffset + range / 2) / range;
const int combinedVolume = VOLUME_MIN + combinedOffset;
return sample.PlayWithVolumeAndPan(logVolume, combinedVolume, logPan);
}
};

1
Source/engine/sound_stubs.cpp

@ -20,6 +20,7 @@ void music_start(_music_id nTrack) { }
void sound_disable_music(bool disable) { }
int sound_get_or_set_music_volume(int volume) { return 0; }
int sound_get_or_set_sound_volume(int volume) { return 0; }
int sound_get_or_set_audio_cues_volume(int volume) { return 0; }
void music_mute() { }
void music_unmute() { }
_music_id GetLevelMusic(dungeon_type dungeonType) { return TMUSIC_TOWN; }

55
Source/gamemenu.cpp

@ -42,6 +42,7 @@ void GamemenuNewGame(bool bActivate);
void GamemenuOptions(bool bActivate);
void GamemenuMusicVolume(bool bActivate);
void GamemenuSoundVolume(bool bActivate);
void GamemenuAudioCuesVolume(bool bActivate);
void GamemenuBrightness(bool bActivate);
void GamemenuSpeed(bool bActivate);
@ -72,6 +73,7 @@ TMenuItem sgOptionsMenu[] = {
// dwFlags, pszStr, fnMenu
{ GMENU_ENABLED | GMENU_SLIDER, nullptr, &GamemenuMusicVolume },
{ GMENU_ENABLED | GMENU_SLIDER, nullptr, &GamemenuSoundVolume },
{ GMENU_ENABLED | GMENU_SLIDER, nullptr, &GamemenuAudioCuesVolume },
{ GMENU_ENABLED | GMENU_SLIDER, N_("Gamma"), &GamemenuBrightness },
{ GMENU_ENABLED | GMENU_SLIDER, N_("Speed"), &GamemenuSpeed },
{ GMENU_ENABLED , N_("Previous Menu"), &GamemenuPrevious },
@ -88,6 +90,11 @@ const char *const SoundToggleNames[] = {
N_("Sound"),
N_("Sound Disabled"),
};
/** Specifies the menu names for navigation audio cues enabled and disabled. */
const char *const AudioCuesToggleNames[] = {
N_("Audio Cues"),
N_("Audio Cues Disabled"),
};
void GamemenuUpdateSingle()
{
@ -149,43 +156,49 @@ void GamemenuGetSound()
GamemenuSoundMusicToggle(SoundToggleNames, &sgOptionsMenu[1], sound_get_or_set_sound_volume(1));
}
void GamemenuGetAudioCues()
{
GamemenuSoundMusicToggle(AudioCuesToggleNames, &sgOptionsMenu[2], sound_get_or_set_audio_cues_volume(1));
}
void GamemenuGetBrightness()
{
gmenu_slider_steps(&sgOptionsMenu[2], 21);
gmenu_slider_set(&sgOptionsMenu[2], 0, 100, UpdateBrightness(-1));
gmenu_slider_steps(&sgOptionsMenu[3], 21);
gmenu_slider_set(&sgOptionsMenu[3], 0, 100, UpdateBrightness(-1));
}
void GamemenuGetSpeed()
{
if (gbIsMultiplayer) {
sgOptionsMenu[3].removeFlags(GMENU_ENABLED | GMENU_SLIDER);
sgOptionsMenu[4].removeFlags(GMENU_ENABLED | GMENU_SLIDER);
if (sgGameInitInfo.nTickRate >= 50)
sgOptionsMenu[3].pszStr = _("Speed: Fastest").data();
sgOptionsMenu[4].pszStr = _("Speed: Fastest").data();
else if (sgGameInitInfo.nTickRate >= 40)
sgOptionsMenu[3].pszStr = _("Speed: Faster").data();
sgOptionsMenu[4].pszStr = _("Speed: Faster").data();
else if (sgGameInitInfo.nTickRate >= 30)
sgOptionsMenu[3].pszStr = _("Speed: Fast").data();
sgOptionsMenu[4].pszStr = _("Speed: Fast").data();
else if (sgGameInitInfo.nTickRate == 20)
sgOptionsMenu[3].pszStr = _("Speed: Normal").data();
sgOptionsMenu[4].pszStr = _("Speed: Normal").data();
return;
}
sgOptionsMenu[3].addFlags(GMENU_ENABLED | GMENU_SLIDER);
sgOptionsMenu[4].addFlags(GMENU_ENABLED | GMENU_SLIDER);
sgOptionsMenu[3].pszStr = _("Speed").data();
gmenu_slider_steps(&sgOptionsMenu[3], 46);
gmenu_slider_set(&sgOptionsMenu[3], 20, 50, sgGameInitInfo.nTickRate);
sgOptionsMenu[4].pszStr = _("Speed").data();
gmenu_slider_steps(&sgOptionsMenu[4], 46);
gmenu_slider_set(&sgOptionsMenu[4], 20, 50, sgGameInitInfo.nTickRate);
}
int GamemenuSliderBrightness()
{
return gmenu_slider_get(&sgOptionsMenu[2], 0, 100);
return gmenu_slider_get(&sgOptionsMenu[3], 0, 100);
}
void GamemenuOptions(bool /*bActivate*/)
{
GamemenuGetMusic();
GamemenuGetSound();
GamemenuGetAudioCues();
GamemenuGetBrightness();
GamemenuGetSpeed();
gmenu_set_items(sgOptionsMenu, nullptr);
@ -247,6 +260,20 @@ void GamemenuSoundVolume(bool bActivate)
GamemenuGetSound();
}
void GamemenuAudioCuesVolume(bool bActivate)
{
if (bActivate) {
const int volume = sound_get_or_set_audio_cues_volume(1) == VOLUME_MIN ? VOLUME_MAX : VOLUME_MIN;
sound_get_or_set_audio_cues_volume(volume);
} else {
const int volume = GamemenuSliderMusicSound(&sgOptionsMenu[2]);
sound_get_or_set_audio_cues_volume(volume);
}
PlaySFX(SfxID::MenuMove);
GamemenuGetAudioCues();
}
void GamemenuBrightness(bool bActivate)
{
int brightness;
@ -268,9 +295,9 @@ void GamemenuSpeed(bool bActivate)
sgGameInitInfo.nTickRate = 20;
else
sgGameInitInfo.nTickRate = 50;
gmenu_slider_set(&sgOptionsMenu[3], 20, 50, sgGameInitInfo.nTickRate);
gmenu_slider_set(&sgOptionsMenu[4], 20, 50, sgGameInitInfo.nTickRate);
} else {
sgGameInitInfo.nTickRate = gmenu_slider_get(&sgOptionsMenu[3], 20, 50);
sgGameInitInfo.nTickRate = gmenu_slider_get(&sgOptionsMenu[4], 20, 50);
}
GetOptions().Gameplay.tickRate.SetValue(sgGameInitInfo.nTickRate);

2
Source/options.cpp

@ -511,6 +511,7 @@ std::vector<OptionEntryBase *> HellfireOptions::GetEntries()
AudioOptions::AudioOptions()
: OptionCategoryBase("Audio", N_("Audio"), N_("Audio Settings"))
, soundVolume("Sound Volume", OptionEntryFlags::Invisible, "Sound Volume", "Movie and SFX volume.", VOLUME_MAX)
, audioCuesVolume("Audio Cues Volume", OptionEntryFlags::Invisible, "Audio Cues Volume", "Navigation audio cues volume.", VOLUME_MAX)
, musicVolume("Music Volume", OptionEntryFlags::Invisible, "Music Volume", "Music Volume.", VOLUME_MAX)
, walkingSound("Walking Sound", OptionEntryFlags::None, N_("Walking Sound"), N_("Player emits sound when walking."), true)
, autoEquipSound("Auto Equip Sound", OptionEntryFlags::None, N_("Auto Equip Sound"), N_("Automatically equipping items on pickup emits the equipment sound."), false)
@ -526,6 +527,7 @@ std::vector<OptionEntryBase *> AudioOptions::GetEntries()
// clang-format off
return {
&soundVolume,
&audioCuesVolume,
&musicVolume,
&walkingSound,
&autoEquipSound,

2
Source/options.h

@ -487,6 +487,8 @@ struct AudioOptions : OptionCategoryBase {
/** @brief Movie and SFX volume. */
OptionEntryInt<int> soundVolume;
/** @brief Navigation audio cues volume. */
OptionEntryInt<int> audioCuesVolume;
/** @brief Music volume. */
OptionEntryInt<int> musicVolume;
/** @brief Player emits sound when walking. */

Loading…
Cancel
Save