From 0db826649544d4acc991427923e2655160126e47 Mon Sep 17 00:00:00 2001 From: Ivan Savenko Date: Sat, 18 May 2024 20:45:06 +0000 Subject: [PATCH] Implemented some of the requested shortcuts --- client/adventureMap/AdventureMapShortcuts.cpp | 22 +++++ client/adventureMap/AdventureMapShortcuts.h | 2 + client/battle/BattleWindow.cpp | 25 ++++++ client/battle/BattleWindow.h | 2 + client/globalLobby/GlobalLobbyRoomWindow.cpp | 1 + client/gui/Shortcut.h | 17 +++- client/gui/ShortcutHandler.cpp | 2 +- client/lobby/CLobbyScreen.cpp | 2 +- client/windows/CCastleInterface.cpp | 80 +++++++++++++++---- client/windows/CCastleInterface.h | 4 +- client/windows/GUIClasses.cpp | 4 +- 11 files changed, 137 insertions(+), 24 deletions(-) diff --git a/client/adventureMap/AdventureMapShortcuts.cpp b/client/adventureMap/AdventureMapShortcuts.cpp index dc7f371b9..2ed8a6d15 100644 --- a/client/adventureMap/AdventureMapShortcuts.cpp +++ b/client/adventureMap/AdventureMapShortcuts.cpp @@ -77,6 +77,7 @@ std::vector AdventureMapShortcuts::getShortcuts() { EShortcut::ADVENTURE_CAST_SPELL, optionHeroSelected(), [this]() { this->showSpellbook(); } }, { EShortcut::ADVENTURE_GAME_OPTIONS, optionInMapView(), [this]() { this->adventureOptions(); } }, { EShortcut::GLOBAL_OPTIONS, optionInMapView(), [this]() { this->systemOptions(); } }, + { EShortcut::ADVENTURE_FIRST_HERO, optionInMapView(), [this]() { this->firstHero(); } }, { EShortcut::ADVENTURE_NEXT_HERO, optionHasNextHero(), [this]() { this->nextHero(); } }, { EShortcut::GAME_END_TURN, optionCanEndTurn(), [this]() { this->endTurn(); } }, { EShortcut::ADVENTURE_THIEVES_GUILD, optionInMapView(), [this]() { this->showThievesGuild(); } }, @@ -92,6 +93,7 @@ std::vector AdventureMapShortcuts::getShortcuts() { EShortcut::ADVENTURE_ZOOM_IN, optionSidePanelActive(),[this]() { this->zoom(+1); } }, { EShortcut::ADVENTURE_ZOOM_OUT, optionSidePanelActive(),[this]() { this->zoom(-1); } }, { EShortcut::ADVENTURE_ZOOM_RESET, optionSidePanelActive(),[this]() { this->zoom( 0); } }, + { EShortcut::ADVENTURE_FIRST_TOWN, optionInMapView(), [this]() { this->firstTown(); } }, { EShortcut::ADVENTURE_NEXT_TOWN, optionInMapView(), [this]() { this->nextTown(); } }, { EShortcut::ADVENTURE_NEXT_OBJECT, optionInMapView(), [this]() { this->nextObject(); } }, { EShortcut::ADVENTURE_MOVE_HERO_SW, optionHeroSelected(), [this]() { this->moveHeroDirectional({-1, +1}); } }, @@ -223,6 +225,16 @@ void AdventureMapShortcuts::systemOptions() GH.windows().createAndPushWindow(); } +void AdventureMapShortcuts::firstHero() +{ + if (!LOCPLINT->localState->getWanderingHeroes().empty()) + { + const auto * hero = LOCPLINT->localState->getWanderingHero(0); + LOCPLINT->localState->setSelection(hero); + owner.centerOnObject(hero); + } +} + void AdventureMapShortcuts::nextHero() { const auto * currHero = LOCPLINT->localState->getCurrentHero(); @@ -366,6 +378,16 @@ void AdventureMapShortcuts::showMarketplace() LOCPLINT->showInfoDialog(CGI->generaltexth->translate("vcmi.adventureMap.noTownWithMarket")); } +void AdventureMapShortcuts::firstTown() +{ + if (!LOCPLINT->localState->getOwnedTowns().empty()) + { + const auto * town = LOCPLINT->localState->getOwnedTown(0); + LOCPLINT->localState->setSelection(town); + owner.centerOnObject(town); + } +} + void AdventureMapShortcuts::nextTown() { owner.hotkeyNextTown(); diff --git a/client/adventureMap/AdventureMapShortcuts.h b/client/adventureMap/AdventureMapShortcuts.h index 3ba463b91..d2bf35ffc 100644 --- a/client/adventureMap/AdventureMapShortcuts.h +++ b/client/adventureMap/AdventureMapShortcuts.h @@ -49,6 +49,7 @@ class AdventureMapShortcuts void showSpellbook(); void adventureOptions(); void systemOptions(); + void firstHero(); void nextHero(); void endTurn(); void showThievesGuild(); @@ -61,6 +62,7 @@ class AdventureMapShortcuts void visitObject(); void openObject(); void showMarketplace(); + void firstTown(); void nextTown(); void nextObject(); void zoom( int distance); diff --git a/client/battle/BattleWindow.cpp b/client/battle/BattleWindow.cpp index c750b620d..a51d48a42 100644 --- a/client/battle/BattleWindow.cpp +++ b/client/battle/BattleWindow.cpp @@ -27,6 +27,7 @@ #include "../widgets/Buttons.h" #include "../widgets/Images.h" #include "../windows/CMessage.h" +#include "../windows/CCreatureWindow.h" #include "../render/CAnimation.h" #include "../render/Canvas.h" #include "../render/IRenderHandler.h" @@ -77,6 +78,8 @@ BattleWindow::BattleWindow(BattleInterface & owner): addShortcut(EShortcut::BATTLE_TACTICS_NEXT, std::bind(&BattleWindow::bTacticNextStack, this)); addShortcut(EShortcut::BATTLE_TACTICS_END, std::bind(&BattleWindow::bTacticPhaseEnd, this)); addShortcut(EShortcut::BATTLE_SELECT_ACTION, std::bind(&BattleWindow::bSwitchActionf, this)); + addShortcut(EShortcut::BATTLE_OPEN_ACTIVE_UNIT, std::bind(&BattleWindow::bOpenActiveUnit, this)); + addShortcut(EShortcut::BATTLE_OPEN_HOVERED_UNIT, std::bind(&BattleWindow::bOpenHoveredUnit, this)); addShortcut(EShortcut::BATTLE_TOGGLE_QUEUE, [this](){ this->toggleQueueVisibility();}); addShortcut(EShortcut::BATTLE_TOGGLE_HEROES_STATS, [this](){ this->toggleStickyHeroWindowsVisibility();}); @@ -755,6 +758,8 @@ void BattleWindow::blockUI(bool on) bool canWait = owner.stacksController->getActiveStack() ? !owner.stacksController->getActiveStack()->waitedThisTurn : false; setShortcutBlocked(EShortcut::GLOBAL_OPTIONS, on); + setShortcutBlocked(EShortcut::BATTLE_OPEN_ACTIVE_UNIT, on); + setShortcutBlocked(EShortcut::BATTLE_OPEN_HOVERED_UNIT, on); setShortcutBlocked(EShortcut::BATTLE_RETREAT, on || !owner.getBattle()->battleCanFlee()); setShortcutBlocked(EShortcut::BATTLE_SURRENDER, on || owner.getBattle()->battleGetSurrenderCost() < 0); setShortcutBlocked(EShortcut::BATTLE_CAST_SPELL, on || owner.tacticsMode || !canCastSpells); @@ -769,6 +774,26 @@ void BattleWindow::blockUI(bool on) setShortcutBlocked(EShortcut::BATTLE_CONSOLE_UP, on && !owner.tacticsMode); } +void BattleWindow::bOpenActiveUnit() +{ + const auto * unit = owner.stacksController->getActiveStack(); + + if (unit) + GH.windows().createAndPushWindow(unit, false);; +} + +void BattleWindow::bOpenHoveredUnit() +{ + const auto units = owner.stacksController->getHoveredStacksUnitIds(); + + if (!units.empty()) + { + const auto * unit = owner.getBattle()->battleGetStackByID(units[0]); + if (unit) + GH.windows().createAndPushWindow(unit, false); + } +} + std::optional BattleWindow::getQueueHoveredUnitId() { return queue->getHoveredUnitIdIfAny(); diff --git a/client/battle/BattleWindow.h b/client/battle/BattleWindow.h index 654ab71a7..5498812b1 100644 --- a/client/battle/BattleWindow.h +++ b/client/battle/BattleWindow.h @@ -56,6 +56,8 @@ class BattleWindow : public InterfaceObjectConfigurable void bConsoleDownf(); void bTacticNextStack(); void bTacticPhaseEnd(); + void bOpenActiveUnit(); + void bOpenHoveredUnit(); /// functions for handling actions after they were confirmed by popup window void reallyFlee(); diff --git a/client/globalLobby/GlobalLobbyRoomWindow.cpp b/client/globalLobby/GlobalLobbyRoomWindow.cpp index 317f32b18..65ec73857 100644 --- a/client/globalLobby/GlobalLobbyRoomWindow.cpp +++ b/client/globalLobby/GlobalLobbyRoomWindow.cpp @@ -26,6 +26,7 @@ #include "../widgets/GraphicalPrimitiveCanvas.h" #include "../widgets/ObjectLists.h" +#include "../../lib/CGeneralTextHandler.h" #include "../../lib/MetaString.h" #include "../../lib/modding/CModHandler.h" #include "../../lib/modding/CModInfo.h" diff --git a/client/gui/Shortcut.h b/client/gui/Shortcut.h index 508e21e84..2be9f16b0 100644 --- a/client/gui/Shortcut.h +++ b/client/gui/Shortcut.h @@ -81,7 +81,7 @@ enum class EShortcut LOBBY_LOAD_GAME, // l, Return LOBBY_SAVE_GAME, // s, Return LOBBY_RANDOM_MAP, // Open random map tab - LOBBY_HIDE_CHAT, + LOBBY_TOGGLE_CHAT, LOBBY_ADDITIONAL_OPTIONS, // Open additional options tab LOBBY_SELECT_SCENARIO, // Open map list tab LOBBY_REPLAY_VIDEO, @@ -129,9 +129,9 @@ enum class EShortcut ADVENTURE_VIEW_SELECTED,// Open window with currently selected hero/town ADVENTURE_NEXT_TOWN, ADVENTURE_NEXT_HERO, - ADVENTURE_NEXT_OBJECT, // TODO: context-sensitive next object - select next hero/town, depending on current selection - ADVENTURE_FIRST_TOWN, // TODO: select first available town in the list - ADVENTURE_FIRST_HERO, // TODO: select first available hero in the list + ADVENTURE_NEXT_OBJECT, // context-sensitive next object - select next hero/town, depending on current selection + ADVENTURE_FIRST_TOWN, // select first available town in the list + ADVENTURE_FIRST_HERO, // select first available hero in the list ADVENTURE_VIEW_SCENARIO,// View Scenario Information window ADVENTURE_REPLAY_TURN, ADVENTURE_DIG_GRAIL, @@ -177,6 +177,8 @@ enum class EShortcut BATTLE_TACTICS_END, BATTLE_SELECT_ACTION, // Alternative actions toggle BATTLE_TOGGLE_HEROES_STATS, + BATTLE_OPEN_ACTIVE_UNIT, + BATTLE_OPEN_HOVERED_UNIT, MARKET_DEAL, MARKET_MAX_AMOUNT, @@ -198,7 +200,14 @@ enum class EShortcut TOWN_OPEN_TAVERN, TOWN_OPEN_HALL, TOWN_OPEN_FORT, + TOWN_OPEN_MARKET, + TOWN_OPEN_MAGE_GUILD, + TOWN_OPEN_THIEVES_GUILD, TOWN_OPEN_RECRUITMENT, + TOWN_OPEN_HERO_EXCHANGE, + TOWN_OPEN_HERO, + TOWN_OPEN_VISITING_HERO, + TOWN_OPEN_GARRISONED_HERO, TOWN_SWAP_ARMIES, // Swap garrisoned and visiting armies // Creature & creature recruitment screen diff --git a/client/gui/ShortcutHandler.cpp b/client/gui/ShortcutHandler.cpp index 15b36de98..257ca5e64 100644 --- a/client/gui/ShortcutHandler.cpp +++ b/client/gui/ShortcutHandler.cpp @@ -137,7 +137,7 @@ EShortcut ShortcutHandler::findShortcut(const std::string & identifier ) const {"lobbyLoadGame", EShortcut::LOBBY_LOAD_GAME }, {"lobbySaveGame", EShortcut::LOBBY_SAVE_GAME }, {"lobbyRandomMap", EShortcut::LOBBY_RANDOM_MAP }, - {"lobbyHideChat", EShortcut::LOBBY_HIDE_CHAT }, + {"lobbyToggleChat", EShortcut::LOBBY_TOGGLE_CHAT }, {"lobbyAdditionalOptions", EShortcut::LOBBY_ADDITIONAL_OPTIONS }, {"lobbySelectScenario", EShortcut::LOBBY_SELECT_SCENARIO }, {"gameEndTurn", EShortcut::GAME_END_TURN }, diff --git a/client/lobby/CLobbyScreen.cpp b/client/lobby/CLobbyScreen.cpp index 2e61a653c..fac1bd173 100644 --- a/client/lobby/CLobbyScreen.cpp +++ b/client/lobby/CLobbyScreen.cpp @@ -62,7 +62,7 @@ CLobbyScreen::CLobbyScreen(ESelectionScreen screenType) } }; - buttonChat = std::make_shared(Point(619, 80), AnimationPath::builtin("GSPBUT2.DEF"), CGI->generaltexth->zelp[48], std::bind(&CLobbyScreen::toggleChat, this), EShortcut::LOBBY_HIDE_CHAT); + buttonChat = std::make_shared(Point(619, 80), AnimationPath::builtin("GSPBUT2.DEF"), CGI->generaltexth->zelp[48], std::bind(&CLobbyScreen::toggleChat, this), EShortcut::LOBBY_TOGGLE_CHAT); buttonChat->setTextOverlay(CGI->generaltexth->allTexts[532], FONT_SMALL, Colors::WHITE); switch(screenType) diff --git a/client/windows/CCastleInterface.cpp b/client/windows/CCastleInterface.cpp index 0a5ba3df7..025db7140 100644 --- a/client/windows/CCastleInterface.cpp +++ b/client/windows/CCastleInterface.cpp @@ -1034,6 +1034,40 @@ void CCastleBuildings::openTownHall() GH.windows().createAndPushWindow(town); } +void CCastleBuildings::enterAnyThievesGuild() +{ + std::vector towns = LOCPLINT->cb->getTownsInfo(true); + for(auto & town : towns) + { + if(town->builtBuildings.count(BuildingID::TAVERN)) + { + LOCPLINT->showThievesGuildWindow(town); + return; + } + } + LOCPLINT->showInfoDialog(CGI->generaltexth->translate("vcmi.adventureMap.noTownWithTavern")); +} + +void CCastleBuildings::enterAnyMarket() +{ + if(town->builtBuildings.count(BuildingID::MARKETPLACE)) + { + GH.windows().createAndPushWindow(town, nullptr, nullptr, EMarketMode::RESOURCE_RESOURCE); + return; + } + + std::vector towns = LOCPLINT->cb->getTownsInfo(true); + for(auto & town : towns) + { + if(town->builtBuildings.count(BuildingID::MARKETPLACE)) + { + GH.windows().createAndPushWindow(town, nullptr, nullptr, EMarketMode::RESOURCE_RESOURCE); + return; + } + } + LOCPLINT->showInfoDialog(CGI->generaltexth->translate("vcmi.adventureMap.noTownWithMarket")); +} + CCreaInfo::CCreaInfo(Point position, const CGTownInstance * Town, int Level, bool compact, bool _showAvailable): town(Town), level(Level), @@ -1333,20 +1367,7 @@ void CCastleInterface::recreateIcons() fastArmyPurchase = std::make_shared(Point(122, 413), AnimationPath::builtin("castleInterfaceQuickAccess"), CButton::tooltip(), [this](){ builds->enterToTheQuickRecruitmentWindow(); }, EShortcut::TOWN_OPEN_RECRUITMENT); fastArmyPurchase->setOverlay(std::make_shared(AnimationPath::builtin("itmcl"), imageIndex)); - fastMarket = std::make_shared(Rect(163, 410, 64, 42), [&]() - { - std::vector towns = LOCPLINT->cb->getTownsInfo(true); - for(auto & town : towns) - { - if(town->builtBuildings.count(BuildingID::MARKETPLACE)) - { - GH.windows().createAndPushWindow(town, nullptr, nullptr, EMarketMode::RESOURCE_RESOURCE); - return; - } - } - LOCPLINT->showInfoDialog(CGI->generaltexth->translate("vcmi.adventureMap.noTownWithMarket")); - }); - + fastMarket = std::make_shared(Rect(163, 410, 64, 42), [this]() { builds->enterAnyMarket(); }); fastTavern = std::make_shared(Rect(15, 387, 58, 64), [&]() { if(town->builtBuildings.count(BuildingID::TAVERN)) @@ -1367,13 +1388,42 @@ void CCastleInterface::recreateIcons() for(size_t i=0; i<4; i++) creainfo.push_back(std::make_shared(Point(14 + 55 * (int)i, 507), town, (int)i + 4, compactCreatureInfo, useAvailableCreaturesForLabel)); - } void CCastleInterface::keyPressed(EShortcut key) { switch(key) { + case EShortcut::TOWN_OPEN_FORT: + GH.windows().createAndPushWindow(town); + break; + case EShortcut::TOWN_OPEN_MARKET: + builds->enterAnyMarket(); + break; + case EShortcut::TOWN_OPEN_MAGE_GUILD: + if(town->hasBuilt(BuildingID::MAGES_GUILD_1)) + builds->enterMagesGuild(); + break; + case EShortcut::TOWN_OPEN_THIEVES_GUILD: + break; + case EShortcut::TOWN_OPEN_HERO_EXCHANGE: + if (town->visitingHero && town->garrisonHero) + LOCPLINT->showHeroExchange(town->visitingHero->id, town->garrisonHero->id); + break; + case EShortcut::TOWN_OPEN_HERO: + if (town->visitingHero) + LOCPLINT->openHeroWindow(town->visitingHero); + else if (town->garrisonHero) + LOCPLINT->openHeroWindow(town->garrisonHero); + break; + case EShortcut::TOWN_OPEN_VISITING_HERO: + if (town->visitingHero) + LOCPLINT->openHeroWindow(town->visitingHero); + break; + case EShortcut::TOWN_OPEN_GARRISONED_HERO: + if (town->garrisonHero) + LOCPLINT->openHeroWindow(town->garrisonHero); + break; case EShortcut::TOWN_SWAP_ARMIES: heroes->swapArmies(); break; diff --git a/client/windows/CCastleInterface.h b/client/windows/CCastleInterface.h index 32c1d426c..7c3b62add 100644 --- a/client/windows/CCastleInterface.h +++ b/client/windows/CCastleInterface.h @@ -154,7 +154,6 @@ class CCastleBuildings : public CIntObject void enterBuilding(BuildingID building);//for buildings with simple description + pic left-click messages void enterCastleGate(); void enterFountain(const BuildingID & building, BuildingSubID::EBuildingSubID subID, BuildingID upgrades);//Rampart's fountains - void enterMagesGuild(); void openMagesGuild(); void openTownHall(); @@ -168,6 +167,9 @@ public: void enterDwelling(int level); void enterTownHall(); + void enterMagesGuild(); + void enterAnyMarket(); + void enterAnyThievesGuild(); void enterToTheQuickRecruitmentWindow(); void buildingClicked(BuildingID building, BuildingSubID::EBuildingSubID subID = BuildingSubID::NONE, BuildingID upgrades = BuildingID::NONE); diff --git a/client/windows/GUIClasses.cpp b/client/windows/GUIClasses.cpp index 84614776e..d55efb978 100644 --- a/client/windows/GUIClasses.cpp +++ b/client/windows/GUIClasses.cpp @@ -845,8 +845,8 @@ CExchangeWindow::CExchangeWindow(ObjectInstanceID hero1, ObjectInstanceID hero2, garr = std::make_shared(Point(69, qeLayout ? 122 : 131), 4, Point(418,0), heroInst[0], heroInst[1], true, true); auto splitButtonCallback = [&](){ garr->splitClick(); }; - garr->addSplitBtn(std::make_shared( Point( 10, qeLayout ? 122 : 132), AnimationPath::builtin("TSBTNS.DEF"), CButton::tooltip(CGI->generaltexth->tcommands[3]), splitButtonCallback), EShortcut::HERO_ARMY_SPLIT); - garr->addSplitBtn(std::make_shared( Point(744, qeLayout ? 122 : 132), AnimationPath::builtin("TSBTNS.DEF"), CButton::tooltip(CGI->generaltexth->tcommands[3]), splitButtonCallback), EShortcut::HERO_ARMY_SPLIT); + garr->addSplitBtn(std::make_shared( Point( 10, qeLayout ? 122 : 132), AnimationPath::builtin("TSBTNS.DEF"), CButton::tooltip(CGI->generaltexth->tcommands[3]), splitButtonCallback, EShortcut::HERO_ARMY_SPLIT)); + garr->addSplitBtn(std::make_shared( Point(744, qeLayout ? 122 : 132), AnimationPath::builtin("TSBTNS.DEF"), CButton::tooltip(CGI->generaltexth->tcommands[3]), splitButtonCallback, EShortcut::HERO_ARMY_SPLIT)); if(qeLayout) {