|
@@ -52,6 +52,7 @@
|
|
|
#include "../../lib/IGameSettings.h"
|
|
|
#include "../../lib/spells/CSpellHandler.h"
|
|
|
#include "../../lib/GameConstants.h"
|
|
|
+#include "../../lib/gameState/UpgradeInfo.h"
|
|
|
#include "../../lib/StartInfo.h"
|
|
|
#include "../../lib/campaign/CampaignState.h"
|
|
|
#include "../../lib/entities/building/CBuilding.h"
|
|
@@ -338,17 +339,92 @@ CHeroGSlot::CHeroGSlot(int x, int y, int updown, const CGHeroInstance * h, HeroS
|
|
|
|
|
|
CHeroGSlot::~CHeroGSlot() = default;
|
|
|
|
|
|
+auto CHeroGSlot::getUpgradableSlots(const CArmedInstance *obj)
|
|
|
+{
|
|
|
+ struct result { bool isCreatureUpgradePossible; bool canAffordAny; bool canAffordAll; TResources totalCosts; std::vector<std::pair<SlotID, UpgradeInfo>> upgradeInfos; };
|
|
|
+
|
|
|
+ auto slots = std::map<SlotID, const CStackInstance*>(obj->Slots().begin(), obj->Slots().end());
|
|
|
+ std::vector<std::pair<SlotID, UpgradeInfo>> upgradeInfos;
|
|
|
+ for(auto & slot : slots)
|
|
|
+ {
|
|
|
+ auto upgradeInfo = std::make_pair(slot.first, UpgradeInfo(slot.second->getCreatureID()));
|
|
|
+ LOCPLINT->cb->fillUpgradeInfo(slot.second->armyObj, slot.first, upgradeInfo.second);
|
|
|
+ bool canUpgrade = obj->tempOwner == LOCPLINT->playerID && upgradeInfo.second.canUpgrade();
|
|
|
+ if(canUpgrade)
|
|
|
+ upgradeInfos.push_back(upgradeInfo);
|
|
|
+ }
|
|
|
+
|
|
|
+ std::sort(upgradeInfos.begin(), upgradeInfos.end(), [&](const std::pair<SlotID, UpgradeInfo> & lhs, const std::pair<SlotID, UpgradeInfo> & rhs) {
|
|
|
+ return lhs.second.oldID.toCreature()->getLevel() > rhs.second.oldID.toCreature()->getLevel();
|
|
|
+ });
|
|
|
+ bool creaturesToUpgrade = static_cast<bool>(upgradeInfos.size());
|
|
|
+
|
|
|
+ TResources costs = TResources();
|
|
|
+ std::vector<SlotID> slotInfosToDelete;
|
|
|
+ for(auto & upgradeInfo : upgradeInfos)
|
|
|
+ {
|
|
|
+ TResources upgradeCosts = upgradeInfo.second.getUpgradeCosts() * slots[upgradeInfo.first]->getCount();
|
|
|
+ if(LOCPLINT->cb->getResourceAmount().canAfford(costs + upgradeCosts))
|
|
|
+ costs += upgradeCosts;
|
|
|
+ else
|
|
|
+ slotInfosToDelete.push_back(upgradeInfo.first);
|
|
|
+ }
|
|
|
+ upgradeInfos.erase(std::remove_if(upgradeInfos.begin(), upgradeInfos.end(), [&slotInfosToDelete](const auto& item) {
|
|
|
+ return std::count(slotInfosToDelete.begin(), slotInfosToDelete.end(), item.first);
|
|
|
+ }), upgradeInfos.end());
|
|
|
+
|
|
|
+ return result { creaturesToUpgrade, static_cast<bool>(upgradeInfos.size()), !slotInfosToDelete.size(), costs, upgradeInfos };
|
|
|
+}
|
|
|
+
|
|
|
void CHeroGSlot::gesture(bool on, const Point & initialPosition, const Point & finalPosition)
|
|
|
{
|
|
|
if(!on)
|
|
|
return;
|
|
|
|
|
|
- if(!hero)
|
|
|
+ const CArmedInstance *obj = hero;
|
|
|
+ if(upg == 0 && !obj)
|
|
|
+ obj = owner->town->getUpperArmy();
|
|
|
+ if(!obj)
|
|
|
return;
|
|
|
|
|
|
+ auto upgradableSlots = getUpgradableSlots(obj);
|
|
|
+ auto upgradeAll = [upgradableSlots, obj](){
|
|
|
+ if(!upgradableSlots.canAffordAny)
|
|
|
+ {
|
|
|
+ LOCPLINT->showInfoDialog(CGI->generaltexth->translate("vcmi.townWindow.upgradeAll.notUpgradable"));
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ std::vector<std::shared_ptr<CComponent>> resComps;
|
|
|
+ for(TResources::nziterator i(upgradableSlots.totalCosts); i.valid(); i++)
|
|
|
+ resComps.push_back(std::make_shared<CComponent>(ComponentType::RESOURCE, i->resType, i->resVal));
|
|
|
+ resComps.back()->newLine = true;
|
|
|
+ for(auto & upgradeInfo : upgradableSlots.upgradeInfos)
|
|
|
+ resComps.push_back(std::make_shared<CComponent>(ComponentType::CREATURE, upgradeInfo.second.getUpgrade(), obj->Slots().at(upgradeInfo.first)->count));
|
|
|
+
|
|
|
+ std::string textID = upgradableSlots.canAffordAll ? "core.genrltxt.207" : "vcmi.townWindow.upgradeAll.notAllUpgradable";
|
|
|
+
|
|
|
+ LOCPLINT->showYesNoDialog(CGI->generaltexth->translate(textID), [upgradableSlots, obj](){
|
|
|
+ for(auto & upgradeInfo : upgradableSlots.upgradeInfos)
|
|
|
+ LOCPLINT->cb->upgradeCreature(obj, upgradeInfo.first, upgradeInfo.second.getUpgrade());
|
|
|
+ }, nullptr, resComps);
|
|
|
+ };
|
|
|
+
|
|
|
if (!settings["input"]["radialWheelGarrisonSwipe"].Bool())
|
|
|
return;
|
|
|
|
|
|
+ if(!hero)
|
|
|
+ {
|
|
|
+ if(upgradableSlots.isCreatureUpgradePossible)
|
|
|
+ {
|
|
|
+ std::vector<RadialMenuConfig> menuElements = {
|
|
|
+ { RadialMenuConfig::ITEM_WW, true, "upgradeCreatures", "vcmi.radialWheel.upgradeCreatures", [upgradeAll](){ upgradeAll(); } },
|
|
|
+ };
|
|
|
+ GH.windows().createAndPushWindow<RadialMenu>(pos.center(), menuElements);
|
|
|
+ }
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
std::shared_ptr<CHeroGSlot> other = upg ? owner->garrisonedHero : owner->visitingHero;
|
|
|
|
|
|
bool twoHeroes = hero && other->hero;
|
|
@@ -361,14 +437,15 @@ void CHeroGSlot::gesture(bool on, const Point & initialPosition, const Point & f
|
|
|
{ RadialMenuConfig::ITEM_NE, twoHeroes, "stackSplitDialog", "vcmi.radialWheel.heroSwapArmy", [heroId, heroOtherId](){CExchangeController(heroId, heroOtherId).swapArmy();} },
|
|
|
{ RadialMenuConfig::ITEM_EE, twoHeroes, "tradeHeroes", "vcmi.radialWheel.heroExchange", [heroId, heroOtherId](){LOCPLINT->showHeroExchange(heroId, heroOtherId);} },
|
|
|
{ RadialMenuConfig::ITEM_SW, twoHeroes, "moveArtifacts", "vcmi.radialWheel.heroGetArtifacts", [heroId, heroOtherId](){CExchangeController(heroId, heroOtherId).moveArtifacts(false, true, true);} },
|
|
|
- { RadialMenuConfig::ITEM_SE, twoHeroes, "swapArtifacts", "vcmi.radialWheel.heroSwapArtifacts", [heroId, heroOtherId](){CExchangeController(heroId, heroOtherId).swapArtifacts(true, true);} },
|
|
|
- { RadialMenuConfig::ITEM_WW, true, "dismissHero", "vcmi.radialWheel.heroDismiss", [this]()
|
|
|
- {
|
|
|
- CFunctionList<void()> ony = [=](){ };
|
|
|
- ony += [=](){ LOCPLINT->cb->dismissHero(hero); };
|
|
|
- LOCPLINT->showYesNoDialog(CGI->generaltexth->allTexts[22], ony, nullptr);
|
|
|
- } },
|
|
|
+ { RadialMenuConfig::ITEM_SE, twoHeroes, "swapArtifacts", "vcmi.radialWheel.heroSwapArtifacts", [heroId, heroOtherId](){CExchangeController(heroId, heroOtherId).swapArtifacts(true, true);} }
|
|
|
};
|
|
|
+ RadialMenuConfig upgradeSlot = { RadialMenuConfig::ITEM_WW, true, "upgradeCreatures", "vcmi.radialWheel.upgradeCreatures", [upgradeAll](){ upgradeAll(); } };
|
|
|
+ RadialMenuConfig dismissSlot = { RadialMenuConfig::ITEM_WW, true, "dismissHero", "vcmi.radialWheel.heroDismiss", [this](){ LOCPLINT->showYesNoDialog(CGI->generaltexth->allTexts[22], [=](){ LOCPLINT->cb->dismissHero(hero); }, nullptr); } };
|
|
|
+
|
|
|
+ if(upgradableSlots.isCreatureUpgradePossible)
|
|
|
+ menuElements.push_back(upgradeSlot);
|
|
|
+ else
|
|
|
+ menuElements.push_back(dismissSlot);
|
|
|
|
|
|
GH.windows().createAndPushWindow<RadialMenu>(pos.center(), menuElements);
|
|
|
}
|