diff --git a/Source/dvlnet/tcp_client.cpp b/Source/dvlnet/tcp_client.cpp index ae931eba..59cda100 100644 --- a/Source/dvlnet/tcp_client.cpp +++ b/Source/dvlnet/tcp_client.cpp @@ -18,7 +18,7 @@ namespace net { int tcp_client::create(std::string addrstr) { try { - auto port = sgOptions.Network.nPort; + auto port = *sgOptions.Network.port; local_server = std::make_unique(ioc, addrstr, port, *pktfty); return join(local_server->LocalhostSelf()); } catch (std::system_error &e) { @@ -34,7 +34,7 @@ int tcp_client::join(std::string addrstr) try { std::stringstream port; - port << sgOptions.Network.nPort; + port << *sgOptions.Network.port; asio::connect(sock, resolver.resolve(addrstr, port.str())); asio::ip::tcp::no_delay option(true); sock.set_option(option); diff --git a/Source/engine/demomode.cpp b/Source/engine/demomode.cpp index 0ea8e07d..eec85b98 100644 --- a/Source/engine/demomode.cpp +++ b/Source/engine/demomode.cpp @@ -218,12 +218,12 @@ bool FetchMessage(tagMSG *lpMsg) } if (e.type == SDL_KEYDOWN && e.key.keysym.sym == SDLK_KP_PLUS && sgGameInitInfo.nTickRate < 255) { sgGameInitInfo.nTickRate++; - sgOptions.Gameplay.nTickRate = sgGameInitInfo.nTickRate; + sgOptions.Gameplay.tickRate.SetValue(sgGameInitInfo.nTickRate); gnTickDelay = 1000 / sgGameInitInfo.nTickRate; } if (e.type == SDL_KEYDOWN && e.key.keysym.sym == SDLK_KP_MINUS && sgGameInitInfo.nTickRate > 1) { sgGameInitInfo.nTickRate--; - sgOptions.Gameplay.nTickRate = sgGameInitInfo.nTickRate; + sgOptions.Gameplay.tickRate.SetValue(sgGameInitInfo.nTickRate); gnTickDelay = 1000 / sgGameInitInfo.nTickRate; } } diff --git a/Source/gamemenu.cpp b/Source/gamemenu.cpp index 98ebbc62..c48ea94d 100644 --- a/Source/gamemenu.cpp +++ b/Source/gamemenu.cpp @@ -288,7 +288,7 @@ void GamemenuSpeed(bool bActivate) sgGameInitInfo.nTickRate = gmenu_slider_get(&sgOptionsMenu[3], 20, 50); } - sgOptions.Gameplay.nTickRate = sgGameInitInfo.nTickRate; + sgOptions.Gameplay.tickRate.SetValue(sgGameInitInfo.nTickRate); gnTickDelay = 1000 / sgGameInitInfo.nTickRate; } diff --git a/Source/menu.cpp b/Source/menu.cpp index 48435410..fccc767c 100644 --- a/Source/menu.cpp +++ b/Source/menu.cpp @@ -87,14 +87,14 @@ bool DummyGetHeroInfo(_uiheroinfo * /*pInfo*/) bool mainmenu_select_hero_dialog(GameData *gameData) { - uint32_t *pSaveNumberFromOptions = nullptr; + OptionEntryInt *pSaveNumberFromOptions = nullptr; _selhero_selections dlgresult = SELHERO_NEW_DUNGEON; if (demo::IsRunning()) { pfile_ui_set_hero_infos(DummyGetHeroInfo); gbLoadGame = true; } else if (!gbIsMultiplayer) { pSaveNumberFromOptions = gbIsHellfire ? &sgOptions.Hellfire.lastSinglePlayerHero : &sgOptions.Diablo.lastSinglePlayerHero; - gSaveNumber = *pSaveNumberFromOptions; + gSaveNumber = **pSaveNumberFromOptions; UiSelHeroSingDialog( pfile_ui_set_hero_infos, pfile_ui_save_create, @@ -107,7 +107,7 @@ bool mainmenu_select_hero_dialog(GameData *gameData) gbLoadGame = (dlgresult == SELHERO_CONTINUE); } else { pSaveNumberFromOptions = gbIsHellfire ? &sgOptions.Hellfire.lastMultiplayerHero : &sgOptions.Diablo.lastMultiplayerHero; - gSaveNumber = *pSaveNumberFromOptions; + gSaveNumber = **pSaveNumberFromOptions; UiSelHeroMultDialog( pfile_ui_set_hero_infos, pfile_ui_save_create, @@ -122,7 +122,7 @@ bool mainmenu_select_hero_dialog(GameData *gameData) } if (pSaveNumberFromOptions != nullptr) - *pSaveNumberFromOptions = gSaveNumber; + pSaveNumberFromOptions->SetValue(gSaveNumber); pfile_read_player_from_save(gSaveNumber, Players[MyPlayerId]); diff --git a/Source/multi.cpp b/Source/multi.cpp index 028f5d4c..5c052f99 100644 --- a/Source/multi.cpp +++ b/Source/multi.cpp @@ -472,7 +472,7 @@ void InitGameInfo() sgGameInitInfo.versionMajor = PROJECT_VERSION_MAJOR; sgGameInitInfo.versionMinor = PROJECT_VERSION_MINOR; sgGameInitInfo.versionPatch = PROJECT_VERSION_PATCH; - sgGameInitInfo.nTickRate = sgOptions.Gameplay.nTickRate; + sgGameInitInfo.nTickRate = *sgOptions.Gameplay.tickRate; sgGameInitInfo.bRunInTown = *sgOptions.Gameplay.runInTown ? 1 : 0; sgGameInitInfo.bTheoQuest = *sgOptions.Gameplay.theoQuest ? 1 : 0; sgGameInitInfo.bCowQuest = *sgOptions.Gameplay.cowQuest ? 1 : 0; diff --git a/Source/options.cpp b/Source/options.cpp index a3d9a55c..2982587a 100644 --- a/Source/options.cpp +++ b/Source/options.cpp @@ -324,20 +324,9 @@ void LoadOptions() } } - sgOptions.Diablo.lastSinglePlayerHero = GetIniInt("Diablo", "LastSinglePlayerHero", 0); - sgOptions.Diablo.lastMultiplayerHero = GetIniInt("Diablo", "LastMultiplayerHero", 0); - sgOptions.Hellfire.lastSinglePlayerHero = GetIniInt("Hellfire", "LastSinglePlayerHero", 0); - sgOptions.Hellfire.lastMultiplayerHero = GetIniInt("Hellfire", "LastMultiplayerHero", 0); GetIniValue("Hellfire", "SItem", sgOptions.Hellfire.szItem, sizeof(sgOptions.Hellfire.szItem), ""); - sgOptions.Audio.nSoundVolume = GetIniInt("Audio", "Sound Volume", VOLUME_MAX); - sgOptions.Audio.nMusicVolume = GetIniInt("Audio", "Music Volume", VOLUME_MAX); - - sgOptions.Graphics.nGammaCorrection = GetIniInt("Graphics", "Gamma Correction", 100); - sgOptions.Gameplay.nTickRate = GetIniInt("Game", "Speed", 20); - GetIniValue("Network", "Bind Address", sgOptions.Network.szBindAddress, sizeof(sgOptions.Network.szBindAddress), "0.0.0.0"); - sgOptions.Network.nPort = GetIniInt("Network", "Port", 6112); GetIniValue("Network", "Previous Host", sgOptions.Network.szPreviousHost, sizeof(sgOptions.Network.szPreviousHost), ""); for (size_t i = 0; i < QUICK_MESSAGE_OPTIONS; i++) @@ -366,21 +355,9 @@ void SaveOptions() } } - SetIniValue("Diablo", "LastSinglePlayerHero", sgOptions.Diablo.lastSinglePlayerHero); - SetIniValue("Diablo", "LastMultiplayerHero", sgOptions.Diablo.lastMultiplayerHero); SetIniValue("Hellfire", "SItem", sgOptions.Hellfire.szItem); - SetIniValue("Hellfire", "LastSinglePlayerHero", sgOptions.Hellfire.lastSinglePlayerHero); - SetIniValue("Hellfire", "LastMultiplayerHero", sgOptions.Hellfire.lastMultiplayerHero); - - SetIniValue("Audio", "Sound Volume", sgOptions.Audio.nSoundVolume); - SetIniValue("Audio", "Music Volume", sgOptions.Audio.nMusicVolume); - - SetIniValue("Graphics", "Gamma Correction", sgOptions.Graphics.nGammaCorrection); - - SetIniValue("Game", "Speed", sgOptions.Gameplay.nTickRate); SetIniValue("Network", "Bind Address", sgOptions.Network.szBindAddress); - SetIniValue("Network", "Port", sgOptions.Network.nPort); SetIniValue("Network", "Previous Host", sgOptions.Network.szPreviousHost); for (size_t i = 0; i < QUICK_MESSAGE_OPTIONS; i++) @@ -600,24 +577,36 @@ std::vector StartUpOptions::GetEntries() DiabloOptions::DiabloOptions() : OptionCategoryBase("Diablo", N_("Diablo"), N_("Diablo specific Settings")) + , lastSinglePlayerHero("LastSinglePlayerHero", OptionEntryFlags::Invisible | OptionEntryFlags::OnlyDiablo, "Sample Rate", "Remembers what singleplayer hero/save was last used.", 0) + , lastMultiplayerHero("LastMultiplayerHero", OptionEntryFlags::Invisible | OptionEntryFlags::OnlyDiablo, "Sample Rate", "Remembers what multiplayer hero/save was last used.", 0) { } std::vector DiabloOptions::GetEntries() { - return {}; + return { + &lastSinglePlayerHero, + &lastMultiplayerHero, + }; } HellfireOptions::HellfireOptions() : OptionCategoryBase("Hellfire", N_("Hellfire"), N_("Hellfire specific Settings")) + , lastSinglePlayerHero("LastSinglePlayerHero", OptionEntryFlags::Invisible | OptionEntryFlags::OnlyHellfire, "Sample Rate", "Remembers what singleplayer hero/save was last used.", 0) + , lastMultiplayerHero("LastMultiplayerHero", OptionEntryFlags::Invisible | OptionEntryFlags::OnlyHellfire, "Sample Rate", "Remembers what multiplayer hero/save was last used.", 0) { } std::vector HellfireOptions::GetEntries() { - return {}; + return { + &lastSinglePlayerHero, + &lastMultiplayerHero, + }; } AudioOptions::AudioOptions() : OptionCategoryBase("Audio", N_("Audio"), N_("Audio Settings")) + , soundVolume("Sound Volume", OptionEntryFlags::Invisible, "Sound Volume", "Movie and SFX 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) , itemPickupSound("Item Pickup Sound", OptionEntryFlags::None, N_("Item Pickup Sound"), N_("Picking up items emits the items pickup sound."), false) @@ -634,6 +623,8 @@ AudioOptions::AudioOptions() std::vector AudioOptions::GetEntries() { return { + &soundVolume, + &musicVolume, &walkingSound, &autoEquipSound, &itemPickupSound, @@ -757,6 +748,7 @@ GraphicsOptions::GraphicsOptions() , integerScaling("Integer Scaling", OptionEntryFlags::CantChangeInGame | OptionEntryFlags::RecreateUI, N_("Integer Scaling"), N_("Scales the image using whole number pixel ratio."), false) , vSync("Vertical Sync", OptionEntryFlags::RecreateUI, N_("Vertical Sync"), N_("Forces waiting for Vertical Sync. Prevents tearing effect when drawing a frame. Disabling it can help with mouse lag on some systems."), true) #endif + , gammaCorrection("Gamma Correction", OptionEntryFlags::Invisible, "Gamma Correction", "Gamma correction level.", 100) , colorCycling("Color Cycling", OptionEntryFlags::None, N_("Color Cycling"), N_("Color cycling effect used for water, lava, and acid animation."), true) #if SDL_VERSION_ATLEAST(2, 0, 0) , hardwareCursor("Hardware Cursor", OptionEntryFlags::CantChangeInGame | OptionEntryFlags::RecreateUI | (HardwareCursorSupported() ? OptionEntryFlags::None : OptionEntryFlags::Invisible), N_("Hardware Cursor"), N_("Use a hardware cursor"), HardwareCursorDefault()) @@ -798,6 +790,7 @@ std::vector GraphicsOptions::GetEntries() &integerScaling, &vSync, #endif + &gammaCorrection, &limitFPS, &showFPS, &showHealthValues, @@ -814,6 +807,7 @@ std::vector GraphicsOptions::GetEntries() GameplayOptions::GameplayOptions() : OptionCategoryBase("Game", N_("Gameplay"), N_("Gameplay Settings")) + , tickRate("Speed", OptionEntryFlags::Invisible, "Speed", "Gameplay ticks per second.", 20) , runInTown("Run in Town", OptionEntryFlags::CantChangeInMultiPlayer, N_("Run in Town"), N_("Enable jogging/fast walking in town for Diablo and Hellfire. This option was introduced in the expansion."), false) , grabInput("Grab Input", OptionEntryFlags::None, N_("Grab Input"), N_("When enabled mouse is locked to the game window."), false) , theoQuest("Theo Quest", OptionEntryFlags::CantChangeInGame | OptionEntryFlags::OnlyHellfire, N_("Theo Quest"), N_("Enable Little Girl quest."), false) @@ -851,6 +845,7 @@ GameplayOptions::GameplayOptions() std::vector GameplayOptions::GetEntries() { return { + &tickRate, &grabInput, &runInTown, &adriaRefillsMana, @@ -894,11 +889,14 @@ std::vector ControllerOptions::GetEntries() NetworkOptions::NetworkOptions() : OptionCategoryBase("Network", N_("Network"), N_("Network Settings")) + , port("Port", OptionEntryFlags::Invisible, "Port", "What network port to use.", 6112) { } std::vector NetworkOptions::GetEntries() { - return {}; + return { + &port, + }; } ChatOptions::ChatOptions() diff --git a/Source/options.h b/Source/options.h index 16f0d187..2ac3e33a 100644 --- a/Source/options.h +++ b/Source/options.h @@ -236,6 +236,10 @@ public: AddEntry(static_cast(entry)); } } + OptionEntryInt(string_view key, OptionEntryFlags flags, string_view name, string_view description, T defaultValue) + : OptionEntryInt(key, flags, name, description, defaultValue, { defaultValue }) + { + } [[nodiscard]] T operator*() const { return static_cast(GetValueInternal()); @@ -329,9 +333,9 @@ struct DiabloOptions : OptionCategoryBase { std::vector GetEntries() override; /** @brief Remembers what singleplayer hero/save was last used. */ - std::uint32_t lastSinglePlayerHero; + OptionEntryInt lastSinglePlayerHero; /** @brief Remembers what multiplayer hero/save was last used. */ - std::uint32_t lastMultiplayerHero; + OptionEntryInt lastMultiplayerHero; }; struct HellfireOptions : OptionCategoryBase { @@ -341,9 +345,9 @@ struct HellfireOptions : OptionCategoryBase { /** @brief Cornerstone of the world item. */ char szItem[sizeof(ItemPack) * 2 + 1]; /** @brief Remembers what singleplayer hero/save was last used. */ - std::uint32_t lastSinglePlayerHero; + OptionEntryInt lastSinglePlayerHero; /** @brief Remembers what multiplayer hero/save was last used. */ - std::uint32_t lastMultiplayerHero; + OptionEntryInt lastMultiplayerHero; }; struct AudioOptions : OptionCategoryBase { @@ -351,9 +355,9 @@ struct AudioOptions : OptionCategoryBase { std::vector GetEntries() override; /** @brief Movie and SFX volume. */ - int nSoundVolume; + OptionEntryInt soundVolume; /** @brief Music volume. */ - int nMusicVolume; + OptionEntryInt musicVolume; /** @brief Player emits sound when walking. */ OptionEntryBoolean walkingSound; /** @brief Automatically equipping items on pickup emits the equipment sound. */ @@ -393,7 +397,7 @@ struct GraphicsOptions : OptionCategoryBase { OptionEntryBoolean vSync; #endif /** @brief Gamma correction level. */ - int nGammaCorrection; + OptionEntryInt gammaCorrection; /** @brief Enable color cycling animations. */ OptionEntryBoolean colorCycling; #if SDL_VERSION_ATLEAST(2, 0, 0) @@ -419,7 +423,7 @@ struct GameplayOptions : OptionCategoryBase { std::vector GetEntries() override; /** @brief Gameplay ticks per second. */ - int nTickRate; + OptionEntryInt tickRate; /** @brief Enable double walk speed when in town. */ OptionEntryBoolean runInTown; /** @brief Do not let the mouse leave the application window. */ @@ -507,7 +511,7 @@ struct NetworkOptions : OptionCategoryBase { /** @brief Most recently entered Hostname in join dialog. */ char szPreviousHost[129]; /** @brief What network port to use. */ - uint16_t nPort; + OptionEntryInt port; }; struct ChatOptions : OptionCategoryBase { diff --git a/Source/palette.cpp b/Source/palette.cpp index 91abf7e4..13256211 100644 --- a/Source/palette.cpp +++ b/Source/palette.cpp @@ -28,9 +28,9 @@ bool sgbFadedIn = true; void LoadGamma() { - int gammaValue = sgOptions.Graphics.nGammaCorrection; + int gammaValue = *sgOptions.Graphics.gammaCorrection; gammaValue = clamp(gammaValue, 30, 100); - sgOptions.Graphics.nGammaCorrection = gammaValue - gammaValue % 5; + sgOptions.Graphics.gammaCorrection.SetValue(gammaValue - gammaValue % 5); } Uint8 FindBestMatchForColor(SDL_Color *palette, SDL_Color color, int skipFrom, int skipTo) @@ -178,7 +178,7 @@ void palette_update(int first, int ncolor) void ApplyGamma(SDL_Color *dst, const SDL_Color *src, int n) { - double g = sgOptions.Graphics.nGammaCorrection / 100.0; + double g = *sgOptions.Graphics.gammaCorrection / 100.0; for (int i = 0; i < n; i++) { dst[i].r = static_cast(pow(src[i].r / 256.0, g) * 256.0); @@ -256,10 +256,9 @@ void LoadRndLvlPal(dungeon_type l) void IncreaseGamma() { - if (sgOptions.Graphics.nGammaCorrection < 100) { - sgOptions.Graphics.nGammaCorrection += 5; - if (sgOptions.Graphics.nGammaCorrection > 100) - sgOptions.Graphics.nGammaCorrection = 100; + int gammaValue = *sgOptions.Graphics.gammaCorrection; + if (gammaValue < 100) { + sgOptions.Graphics.gammaCorrection.SetValue(std::min(gammaValue + 5, 100)); ApplyGamma(system_palette, logical_palette, 256); palette_update(); } @@ -267,10 +266,9 @@ void IncreaseGamma() void DecreaseGamma() { - if (sgOptions.Graphics.nGammaCorrection > 30) { - sgOptions.Graphics.nGammaCorrection -= 5; - if (sgOptions.Graphics.nGammaCorrection < 30) - sgOptions.Graphics.nGammaCorrection = 30; + int gammaValue = *sgOptions.Graphics.gammaCorrection; + if (gammaValue > 30) { + sgOptions.Graphics.gammaCorrection.SetValue(std::max(gammaValue - 5, 30)); ApplyGamma(system_palette, logical_palette, 256); palette_update(); } @@ -279,11 +277,11 @@ void DecreaseGamma() int UpdateGamma(int gamma) { if (gamma > 0) { - sgOptions.Graphics.nGammaCorrection = 130 - gamma; + sgOptions.Graphics.gammaCorrection.SetValue(130 - gamma); ApplyGamma(system_palette, logical_palette, 256); palette_update(); } - return 130 - sgOptions.Graphics.nGammaCorrection; + return 130 - *sgOptions.Graphics.gammaCorrection; } void SetFadeLevel(int fadeval) diff --git a/Source/sound.cpp b/Source/sound.cpp index b8215a4e..714a729e 100644 --- a/Source/sound.cpp +++ b/Source/sound.cpp @@ -145,7 +145,7 @@ void snd_play_snd(TSnd *pSnd, int lVolume, int lPan) return; } - sound->Play(lVolume, sgOptions.Audio.nSoundVolume, lPan); + sound->Play(lVolume, *sgOptions.Audio.soundVolume, lPan); pSnd->start_tc = tc; } @@ -191,12 +191,12 @@ TSnd::~TSnd() void snd_init() { - sgOptions.Audio.nSoundVolume = CapVolume(sgOptions.Audio.nSoundVolume); - gbSoundOn = sgOptions.Audio.nSoundVolume > VOLUME_MIN; + sgOptions.Audio.soundVolume.SetValue(CapVolume(*sgOptions.Audio.soundVolume)); + gbSoundOn = *sgOptions.Audio.soundVolume > VOLUME_MIN; sgbSaveSoundOn = gbSoundOn; - sgOptions.Audio.nMusicVolume = CapVolume(sgOptions.Audio.nMusicVolume); - gbMusicOn = sgOptions.Audio.nMusicVolume > VOLUME_MIN; + sgOptions.Audio.musicVolume.SetValue(CapVolume(*sgOptions.Audio.musicVolume)); + gbMusicOn = *sgOptions.Audio.musicVolume > VOLUME_MIN; // Initialize the SDL_audiolib library. Set the output sample rate to // 22kHz, the audio format to 16-bit signed, use 2 output channels @@ -254,7 +254,7 @@ void music_start(uint8_t nTrack) return; } - music->setVolume(VolumeLogToLinear(sgOptions.Audio.nMusicVolume, VOLUME_MIN, VOLUME_MAX)); + music->setVolume(VolumeLogToLinear(*sgOptions.Audio.musicVolume, VOLUME_MIN, VOLUME_MAX)); if (!diablo_is_focused()) music_mute(); if (!music->play(/*iterations=*/0)) { @@ -280,24 +280,24 @@ void sound_disable_music(bool disable) int sound_get_or_set_music_volume(int volume) { if (volume == 1) - return sgOptions.Audio.nMusicVolume; + return *sgOptions.Audio.musicVolume; - sgOptions.Audio.nMusicVolume = volume; + sgOptions.Audio.musicVolume.SetValue(volume); if (music) - music->setVolume(VolumeLogToLinear(sgOptions.Audio.nMusicVolume, VOLUME_MIN, VOLUME_MAX)); + music->setVolume(VolumeLogToLinear(*sgOptions.Audio.musicVolume, VOLUME_MIN, VOLUME_MAX)); - return sgOptions.Audio.nMusicVolume; + return *sgOptions.Audio.musicVolume; } int sound_get_or_set_sound_volume(int volume) { if (volume == 1) - return sgOptions.Audio.nSoundVolume; + return *sgOptions.Audio.soundVolume; - sgOptions.Audio.nSoundVolume = volume; + sgOptions.Audio.soundVolume.SetValue(volume); - return sgOptions.Audio.nSoundVolume; + return *sgOptions.Audio.soundVolume; } void music_mute() diff --git a/Source/storm/storm_svid.cpp b/Source/storm/storm_svid.cpp index ad66f9aa..50d2f0c5 100644 --- a/Source/storm/storm_svid.cpp +++ b/Source/storm/storm_svid.cpp @@ -264,7 +264,7 @@ bool SVidPlayBegin(const char *filename, int flags) SVidAudioDecoder = decoder.get(); SVidAudioStream.emplace(/*rwops=*/nullptr, std::move(decoder), std::make_unique(*sgOptions.Audio.resamplingQuality), /*closeRw=*/false); - const float volume = static_cast(sgOptions.Audio.nSoundVolume - VOLUME_MIN) / -VOLUME_MIN; + const float volume = static_cast(*sgOptions.Audio.soundVolume - VOLUME_MIN) / -VOLUME_MIN; SVidAudioStream->setVolume(volume); if (!diablo_is_focused()) SVidMute();