diff --git a/Source/diablo.cpp b/Source/diablo.cpp index f3f780d4f..019eefb83 100644 --- a/Source/diablo.cpp +++ b/Source/diablo.cpp @@ -410,6 +410,9 @@ void ReleaseKey(int vkey) AltPressed(false); if (vkey == DVL_VK_RCONTROL) ToggleItemLabelHighlight(); + if (sgnTimeoutCurs != CURSOR_NONE || dropGoldFlag) + return; + sgOptions.Keymapper.KeyReleased(vkey); } void ClosePanels() @@ -466,14 +469,15 @@ void PressKey(int vkey) diablo_pause_game(); return; } + + sgOptions.Keymapper.KeyPressed(vkey); + if (PauseMode == 2) { if (vkey == DVL_VK_RETURN && GetAsyncKeyState(DVL_VK_MENU)) sgOptions.Graphics.fullscreen.SetValue(!IsFullScreen()); return; } - sgOptions.Keymapper.KeyPressed(vkey); - if (vkey == DVL_VK_RETURN) { if (GetAsyncKeyState(DVL_VK_MENU)) { sgOptions.Graphics.fullscreen.SetValue(!IsFullScreen()); @@ -1382,6 +1386,16 @@ bool IsPlayerDead() return Players[MyPlayerId]._pmode == PM_DEATH || MyPlayerIsDead; } +bool IsGameRunning() +{ + return PauseMode != 2; +} + +bool CanPlayerTakeAction() +{ + return !IsPlayerDead() && IsGameRunning(); +} + void InitKeymapActions() { for (int i = 0; i < 8; ++i) { @@ -1396,7 +1410,8 @@ void InitKeymapActions() UseInvItem(MyPlayerId, INVITEM_BELT_FIRST + i); } }, - [&]() { return !IsPlayerDead(); }, + nullptr, + CanPlayerTakeAction, i + 1); } for (int i = 0; i < 4; ++i) { @@ -1415,7 +1430,8 @@ void InitKeymapActions() else QuickCast(i); }, - [&]() { return !IsPlayerDead(); }, + nullptr, + CanPlayerTakeAction, i + 1); } sgOptions.Keymapper.AddAction( @@ -1424,21 +1440,24 @@ void InitKeymapActions() N_("Open Speedbook."), 'S', DisplaySpellsKeyPressed, - [&]() { return !IsPlayerDead(); }); + nullptr, + CanPlayerTakeAction); sgOptions.Keymapper.AddAction( "QuickSave", N_("Quick save"), N_("Saves the game."), DVL_VK_F2, [] { gamemenu_save_game(false); }, - [&]() { return !gbIsMultiplayer && !IsPlayerDead(); }); + nullptr, + [&]() { return !gbIsMultiplayer && CanPlayerTakeAction(); }); sgOptions.Keymapper.AddAction( "QuickLoad", N_("Quick load"), N_("Loads the game."), DVL_VK_F3, [] { gamemenu_load_game(false); }, - [&]() { return !gbIsMultiplayer && gbValidSaveFile && stextflag == STORE_NONE; }); + nullptr, + [&]() { return !gbIsMultiplayer && gbValidSaveFile && stextflag == STORE_NONE && IsGameRunning(); }); sgOptions.Keymapper.AddAction( "QuitGame", N_("Quit game"), @@ -1451,7 +1470,8 @@ void InitKeymapActions() N_("Stops walking and cancel pending actions."), DVL_VK_INVALID, [] { Players[MyPlayerId].Stop(); }, - [&]() { return !IsPlayerDead(); }); + nullptr, + CanPlayerTakeAction); sgOptions.Keymapper.AddAction( "Inventory", @@ -1459,28 +1479,32 @@ void InitKeymapActions() N_("Open Inventory screen."), 'I', InventoryKeyPressed, - [&]() { return !IsPlayerDead(); }); + nullptr, + CanPlayerTakeAction); sgOptions.Keymapper.AddAction( "Character", N_("Character"), N_("Open Character screen."), 'C', CharacterSheetKeyPressed, - [&]() { return !IsPlayerDead(); }); + nullptr, + CanPlayerTakeAction); sgOptions.Keymapper.AddAction( "QuestLog", N_("Quest log"), N_("Open Quest log."), 'Q', QuestLogKeyPressed, - [&]() { return !IsPlayerDead(); }); + nullptr, + CanPlayerTakeAction); sgOptions.Keymapper.AddAction( "SpellBook", N_("Spellbook"), N_("Open Spellbook."), 'B', SpellBookKeyPressed, - [&]() { return !IsPlayerDead(); }); + nullptr, + CanPlayerTakeAction); for (int i = 0; i < 4; ++i) { sgOptions.Keymapper.AddAction( "QuickMessage{}", @@ -1488,7 +1512,8 @@ void InitKeymapActions() N_("Use Quick Message in chat."), DVL_VK_F9 + i, [i]() { DiabloHotkeyMsg(i); }, - [] { return true; }, + nullptr, + nullptr, i + 1); } sgOptions.Keymapper.AddAction( @@ -1500,28 +1525,31 @@ void InitKeymapActions() zoomflag = !zoomflag; CalcViewportGeometry(); }, - [&]() { return !IsPlayerDead(); }); + nullptr, + CanPlayerTakeAction); sgOptions.Keymapper.AddAction( "DecreaseGamma", N_("Decrease Gamma"), N_("Reduce screen brightness."), 'G', DecreaseGamma, - [&]() { return !IsPlayerDead(); }); + nullptr, + CanPlayerTakeAction); sgOptions.Keymapper.AddAction( "IncreaseGamma", N_("Increase Gamma"), N_("Increase screen brightness."), 'F', IncreaseGamma, - [&]() { return !IsPlayerDead(); }); + CanPlayerTakeAction); sgOptions.Keymapper.AddAction( "Help", N_("Help"), N_("Open Help Screen."), DVL_VK_F1, HelpKeyPressed, - [&]() { return !IsPlayerDead(); }); + nullptr, + CanPlayerTakeAction); sgOptions.Keymapper.AddAction( "GameInfo", N_("Game info"), @@ -1534,7 +1562,8 @@ void InitKeymapActions() PROJECT_VERSION), UiFlags::ColorWhite); }, - [&]() { return !IsPlayerDead(); }); + nullptr, + CanPlayerTakeAction); #ifdef _DEBUG sgOptions.Keymapper.AddAction( "DebugToggle", @@ -1543,11 +1572,9 @@ void InitKeymapActions() 'X', [] { DebugToggle = !DebugToggle; - }, - [&]() { return true; }); + }); #endif } - } // namespace void FreeGameMem() diff --git a/Source/options.cpp b/Source/options.cpp index bb795bb24..c7ed58994 100644 --- a/Source/options.cpp +++ b/Source/options.cpp @@ -1063,11 +1063,12 @@ std::vector KeymapperOptions::GetEntries() return entries; } -KeymapperOptions::Action::Action(string_view key, string_view name, string_view description, int defaultKey, std::function action, std::function enable, int index) +KeymapperOptions::Action::Action(string_view key, string_view name, string_view description, int defaultKey, std::function actionPressed, std::function actionReleased, std::function enable, int index) : OptionEntryBase(key, OptionEntryFlags::None, name, description) , defaultKey(defaultKey) - , action(action) - , enable(enable) + , actionPressed(std::move(actionPressed)) + , actionReleased(std::move(actionReleased)) + , enable(std::move(enable)) , dynamicIndex(index) { if (index >= 0) { @@ -1164,9 +1165,9 @@ bool KeymapperOptions::Action::SetValue(int value) return true; } -void KeymapperOptions::AddAction(string_view key, string_view name, string_view description, int defaultKey, std::function action, std::function enable, int index) +void KeymapperOptions::AddAction(string_view key, string_view name, string_view description, int defaultKey, std::function actionPressed, std::function actionReleased, std::function enable, int index) { - actions.push_back(std::unique_ptr(new Action(key, name, description, defaultKey, std::move(action), std::move(enable), index))); + actions.push_back(std::unique_ptr(new Action(key, name, description, defaultKey, std::move(actionPressed), std::move(actionReleased), std::move(enable), index))); } void KeymapperOptions::KeyPressed(int key) const @@ -1175,14 +1176,30 @@ void KeymapperOptions::KeyPressed(int key) const if (it == keyIDToAction.end()) return; // Ignore unmapped keys. - const auto &action = it->second; + const Action &action = it->second.get(); // Check that the action can be triggered and that the chat textbox is not // open. - if (!action.get().enable() || talkflag) + if (!action.actionPressed || (action.enable && !action.enable()) || talkflag) return; - action.get().action(); + action.actionPressed(); +} + +void KeymapperOptions::KeyReleased(int key) const +{ + auto it = keyIDToAction.find(key); + if (it == keyIDToAction.end()) + return; // Ignore unmapped keys. + + const Action &action = it->second.get(); + + // Check that the action can be triggered and that the chat textbox is not + // open. + if (!action.actionReleased || (action.enable && !action.enable()) || talkflag) + return; + + action.actionReleased(); } string_view KeymapperOptions::KeyNameForAction(string_view actionName) const diff --git a/Source/options.h b/Source/options.h index 160c86903..805dd76f5 100644 --- a/Source/options.h +++ b/Source/options.h @@ -543,9 +543,10 @@ struct KeymapperOptions : OptionCategoryBase { bool SetValue(int value); private: - Action(string_view key, string_view name, string_view description, int defaultKey, std::function action, std::function enable, int index); + Action(string_view key, string_view name, string_view description, int defaultKey, std::function actionPressed, std::function actionReleased, std::function enable, int index); int defaultKey; - std::function action; + std::function actionPressed; + std::function actionReleased; std::function enable; int boundKey = DVL_VK_INVALID; int dynamicIndex; @@ -560,8 +561,9 @@ struct KeymapperOptions : OptionCategoryBase { void AddAction( string_view key, string_view name, string_view description, int defaultKey, - std::function action, std::function enable = [] { return true; }, int index = -1); + std::function actionPressed, std::function actionReleased = nullptr, std::function enable = nullptr, int index = -1); void KeyPressed(int key) const; + void KeyReleased(int key) const; string_view KeyNameForAction(string_view actionName) const; private: