mirror of
https://github.com/vcmi/vcmi.git
synced 2025-11-25 22:42:04 +02:00
Fix AI to use hillFort all available upgrades. UpgradeInfo refactor.
This commit is contained in:
@@ -788,14 +788,29 @@ bool AIGateway::makePossibleUpgrades(const CArmedInstance * obj)
|
||||
{
|
||||
if(const CStackInstance * s = obj->getStackPtr(SlotID(i)))
|
||||
{
|
||||
UpgradeInfo ui;
|
||||
myCb->fillUpgradeInfo(obj, SlotID(i), ui);
|
||||
if(ui.oldID != CreatureID::NONE && nullkiller->getFreeResources().canAfford(ui.cost[0] * s->count))
|
||||
UpgradeInfo ui(s->getId());
|
||||
do
|
||||
{
|
||||
myCb->upgradeCreature(obj, SlotID(i), ui.newID[0]);
|
||||
myCb->fillUpgradeInfo(obj, SlotID(i), ui);
|
||||
|
||||
if(ui.hasUpgrades())
|
||||
{
|
||||
// creature at given slot might have alternative upgrades, pick best one
|
||||
CreatureID upgID = *vstd::maxElementByFun(ui.getAvailableUpgrades(), [](const CreatureID & id)
|
||||
{
|
||||
return id.toCreature()->getAIValue();
|
||||
});
|
||||
if(nullkiller->getFreeResources().canAfford(ui.getUpgradeCostsFor(upgID) * s->count))
|
||||
{
|
||||
myCb->upgradeCreature(obj, SlotID(i), upgID);
|
||||
upgraded = true;
|
||||
logAi->debug("Upgraded %d %s to %s", s->count, ui.oldID.toCreature()->getNamePluralTranslated(), ui.newID[0].toCreature()->getNamePluralTranslated());
|
||||
logAi->debug("Upgraded %d %s to %s", s->count, ui.oldID.toCreature()->getNamePluralTranslated(), ui.getNextUpgrade().toCreature()->getNamePluralTranslated());
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
}
|
||||
while(ui.hasUpgrades());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -754,12 +754,28 @@ void makePossibleUpgrades(const CArmedInstance * obj)
|
||||
{
|
||||
if(const CStackInstance * s = obj->getStackPtr(SlotID(i)))
|
||||
{
|
||||
UpgradeInfo ui;
|
||||
cb->fillUpgradeInfo(obj, SlotID(i), ui);
|
||||
if(ui.oldID != CreatureID::NONE && cb->getResourceAmount().canAfford(ui.cost[0] * s->count))
|
||||
UpgradeInfo ui(s->getId());
|
||||
do
|
||||
{
|
||||
cb->upgradeCreature(obj, SlotID(i), ui.newID[0]);
|
||||
cb->fillUpgradeInfo(obj, SlotID(i), ui);
|
||||
|
||||
if(ui.hasUpgrades())
|
||||
{
|
||||
// creature at given slot might have alternative upgrades, pick best one
|
||||
CreatureID upgID = *vstd::maxElementByFun(ui.getAvailableUpgrades(), [](const CreatureID & id)
|
||||
{
|
||||
return id.toCreature()->getAIValue();
|
||||
});
|
||||
if(cb->getResourceAmount().canAfford(ui.getUpgradeCostsFor(upgID) * s->count))
|
||||
{
|
||||
cb->upgradeCreature(obj, SlotID(i), upgID);
|
||||
logAi->debug("Upgraded %d %s to %s", s->count, ui.oldID.toCreature()->getNamePluralTranslated(), ui.getNextUpgrade().toCreature()->getNamePluralTranslated());
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
}
|
||||
while(ui.hasUpgrades());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,7 +24,7 @@ class CCreature;
|
||||
struct CGPath;
|
||||
class CCreatureSet;
|
||||
class CGObjectInstance;
|
||||
struct UpgradeInfo;
|
||||
class UpgradeInfo;
|
||||
class ConditionalWait;
|
||||
struct CPathsInfo;
|
||||
|
||||
|
||||
@@ -162,10 +162,10 @@ std::function<void()> CGarrisonSlot::getDismiss() const
|
||||
/// @return Whether the view should be refreshed
|
||||
bool CGarrisonSlot::viewInfo()
|
||||
{
|
||||
UpgradeInfo pom;
|
||||
UpgradeInfo pom(ID.getNum());
|
||||
LOCPLINT->cb->fillUpgradeInfo(getObj(), ID, pom);
|
||||
|
||||
bool canUpgrade = getObj()->tempOwner == LOCPLINT->playerID && pom.oldID != CreatureID::NONE; //upgrade is possible
|
||||
bool canUpgrade = getObj()->tempOwner == LOCPLINT->playerID && pom.canUpgrade(); //upgrade is possible
|
||||
std::function<void(CreatureID)> upgr = nullptr;
|
||||
auto dism = getDismiss();
|
||||
if(canUpgrade) upgr = [=] (CreatureID newID) { LOCPLINT->cb->upgradeCreature(getObj(), ID, newID); };
|
||||
@@ -177,7 +177,7 @@ bool CGarrisonSlot::viewInfo()
|
||||
elem->block(true);
|
||||
|
||||
redraw();
|
||||
GH.windows().createAndPushWindow<CStackWindow>(myStack, dism, pom, upgr);
|
||||
GH.windows().createAndPushWindow<CStackWindow>(myStack, dism, std::move(pom), upgr);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -57,6 +57,10 @@ public:
|
||||
};
|
||||
struct StackUpgradeInfo
|
||||
{
|
||||
StackUpgradeInfo() = delete;
|
||||
StackUpgradeInfo(UpgradeInfo && upgradeInfo)
|
||||
: info(std::move(upgradeInfo))
|
||||
{ }
|
||||
UpgradeInfo info;
|
||||
std::function<void(CreatureID)> callback;
|
||||
};
|
||||
@@ -355,15 +359,15 @@ CStackWindow::ButtonsSection::ButtonsSection(CStackWindow * owner, int yOffset)
|
||||
// besides - should commander really be upgradeable?
|
||||
|
||||
auto & upgradeInfo = parent->info->upgradeInfo.value();
|
||||
const size_t buttonsToCreate = std::min<size_t>(upgradeInfo.info.newID.size(), upgrade.size());
|
||||
const size_t buttonsToCreate = std::min<size_t>(upgradeInfo.info.size(), upgrade.size());
|
||||
|
||||
for(size_t buttonIndex = 0; buttonIndex < buttonsToCreate; buttonIndex++)
|
||||
{
|
||||
TResources totalCost = upgradeInfo.info.cost[buttonIndex] * parent->info->creatureCount;
|
||||
TResources totalCost = upgradeInfo.info.getUpgradeCosts().at(buttonIndex) * parent->info->creatureCount;
|
||||
|
||||
auto onUpgrade = [=]()
|
||||
{
|
||||
upgradeInfo.callback(upgradeInfo.info.newID[buttonIndex]);
|
||||
upgradeInfo.callback(upgradeInfo.info.getAvailableUpgrades().at(buttonIndex));
|
||||
parent->close();
|
||||
};
|
||||
auto onClick = [=]()
|
||||
@@ -385,7 +389,7 @@ CStackWindow::ButtonsSection::ButtonsSection(CStackWindow * owner, int yOffset)
|
||||
};
|
||||
auto upgradeBtn = std::make_shared<CButton>(Point(221 + (int)buttonIndex * 40, 5), AnimationPath::builtin("stackWindow/upgradeButton"), CGI->generaltexth->zelp[446], onClick);
|
||||
|
||||
upgradeBtn->setOverlay(std::make_shared<CAnimImage>(AnimationPath::builtin("CPRSMALL"), VLC->creh->objects[upgradeInfo.info.newID[buttonIndex]]->getIconIndex()));
|
||||
upgradeBtn->setOverlay(std::make_shared<CAnimImage>(AnimationPath::builtin("CPRSMALL"), VLC->creh->objects[upgradeInfo.info.getAvailableUpgrades()[buttonIndex]]->getIconIndex()));
|
||||
|
||||
if(buttonsToCreate == 1) // single upgrade available
|
||||
upgradeBtn->assignedKey = EShortcut::RECRUITMENT_UPGRADE;
|
||||
@@ -755,7 +759,7 @@ CStackWindow::CStackWindow(const CStackInstance * stack, bool popup)
|
||||
init();
|
||||
}
|
||||
|
||||
CStackWindow::CStackWindow(const CStackInstance * stack, std::function<void()> dismiss, const UpgradeInfo & upgradeInfo, std::function<void(CreatureID)> callback)
|
||||
CStackWindow::CStackWindow(const CStackInstance * stack, std::function<void()> dismiss, UpgradeInfo && upgradeInfo, std::function<void(CreatureID)> callback)
|
||||
: CWindowObject(BORDERED),
|
||||
info(new UnitView())
|
||||
{
|
||||
@@ -763,9 +767,8 @@ CStackWindow::CStackWindow(const CStackInstance * stack, std::function<void()> d
|
||||
info->creature = stack->getCreature();
|
||||
info->creatureCount = stack->count;
|
||||
|
||||
info->upgradeInfo = std::make_optional(UnitView::StackUpgradeInfo());
|
||||
info->upgradeInfo = std::make_optional(UnitView::StackUpgradeInfo(std::move(upgradeInfo)));
|
||||
info->dismissInfo = std::make_optional(UnitView::StackDismissInfo());
|
||||
info->upgradeInfo->info = upgradeInfo;
|
||||
info->upgradeInfo->callback = callback;
|
||||
info->dismissInfo->callback = dismiss;
|
||||
info->owner = dynamic_cast<const CGHeroInstance *> (stack->armyObj);
|
||||
|
||||
@@ -19,7 +19,7 @@ VCMI_LIB_NAMESPACE_BEGIN
|
||||
class CCommanderInstance;
|
||||
class CStackInstance;
|
||||
class CStack;
|
||||
struct UpgradeInfo;
|
||||
class UpgradeInfo;
|
||||
|
||||
VCMI_LIB_NAMESPACE_END
|
||||
|
||||
@@ -204,7 +204,7 @@ public:
|
||||
|
||||
// for normal stacks in armies
|
||||
CStackWindow(const CStackInstance * stack, bool popup);
|
||||
CStackWindow(const CStackInstance * stack, std::function<void()> dismiss, const UpgradeInfo & info, std::function<void(CreatureID)> callback);
|
||||
CStackWindow(const CStackInstance * stack, std::function<void()> dismiss, UpgradeInfo && info, std::function<void(CreatureID)> callback);
|
||||
|
||||
// for commanders & commander level-up dialog
|
||||
CStackWindow(const CCommanderInstance * commander, bool popup);
|
||||
|
||||
@@ -1153,14 +1153,17 @@ void CHillFortWindow::updateGarrisons()
|
||||
State newState = getState(SlotID(i));
|
||||
if(newState != State::EMPTY)
|
||||
{
|
||||
UpgradeInfo info;
|
||||
LOCPLINT->cb->fillUpgradeInfo(hero, SlotID(i), info);
|
||||
if(info.newID.size())//we have upgrades here - update costs
|
||||
if(const CStackInstance * s = hero->getStackPtr(SlotID(i)))
|
||||
{
|
||||
costs[i] = info.cost.back() * hero->getStackCount(SlotID(i));
|
||||
UpgradeInfo info(s->getCreature()->getId());
|
||||
LOCPLINT->cb->fillUpgradeInfo(hero, SlotID(i), info);
|
||||
if(info.canUpgrade()) //we have upgrades here - update costs
|
||||
{
|
||||
costs[i] = info.getNextUpgradeCosts() * hero->getStackCount(SlotID(i));
|
||||
totalSum += costs[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
currState[i] = newState;
|
||||
upgrade[i]->setImage(AnimationPath::builtin(slotImages[getImgIdx(currState[i])]));
|
||||
@@ -1264,9 +1267,12 @@ void CHillFortWindow::makeDeal(SlotID slot)
|
||||
{
|
||||
if(slot.getNum() == i || ( slot.getNum() == slotsCount && currState[i] == State::MAKE_UPGRADE ))//this is activated slot or "upgrade all"
|
||||
{
|
||||
UpgradeInfo info;
|
||||
if(const CStackInstance * s = hero->getStackPtr(SlotID(i)))
|
||||
{
|
||||
UpgradeInfo info(s->getCreatureID());
|
||||
LOCPLINT->cb->fillUpgradeInfo(hero, SlotID(i), info);
|
||||
LOCPLINT->cb->upgradeCreature(hero, SlotID(i), info.newID.back());
|
||||
LOCPLINT->cb->upgradeCreature(hero, SlotID(i), info.getNextUpgrade());
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -1295,18 +1301,15 @@ CHillFortWindow::State CHillFortWindow::getState(SlotID slot)
|
||||
if(hero->slotEmpty(slot))
|
||||
return State::EMPTY;
|
||||
|
||||
UpgradeInfo info;
|
||||
UpgradeInfo info(hero->getStackPtr(slot)->getCreatureID());
|
||||
LOCPLINT->cb->fillUpgradeInfo(hero, slot, info);
|
||||
if (info.newID.empty())
|
||||
{
|
||||
// Hill Fort may limit level of upgradeable creatures, e.g. mini Hill Fort from HOTA
|
||||
if (hero->getCreature(slot)->hasUpgrades())
|
||||
return State::UNAVAILABLE;
|
||||
if(info.hasUpgrades() && !info.canUpgrade())
|
||||
return State::UNAVAILABLE; // Hill Fort may limit level of upgradeable creatures, e.g. mini Hill Fort from HOTA
|
||||
|
||||
if(!info.hasUpgrades())
|
||||
return State::ALREADY_UPGRADED;
|
||||
}
|
||||
|
||||
if(!(info.cost.back() * hero->getStackCount(slot)).canBeAfforded(myRes))
|
||||
if(!(info.getNextUpgradeCosts() * hero->getStackCount(slot)).canBeAfforded(myRes))
|
||||
return State::UNAFFORDABLE;
|
||||
|
||||
return State::MAKE_UPGRADE;
|
||||
|
||||
@@ -183,7 +183,7 @@ const IMarket * CGameInfoCallback::getMarket(ObjectInstanceID objid) const
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void CGameInfoCallback::fillUpgradeInfo(const CArmedInstance *obj, SlotID stackPos, UpgradeInfo &out) const
|
||||
void CGameInfoCallback::fillUpgradeInfo(const CArmedInstance *obj, SlotID stackPos, UpgradeInfo & out) const
|
||||
{
|
||||
//boost::shared_lock<boost::shared_mutex> lock(*gs->mx);
|
||||
ERROR_RET_IF(!canGetFullInfo(obj), "Cannot get info about not owned object!");
|
||||
|
||||
@@ -33,7 +33,7 @@ struct CPathsInfo;
|
||||
struct InfoAboutHero;
|
||||
struct InfoAboutTown;
|
||||
|
||||
struct UpgradeInfo;
|
||||
class UpgradeInfo;
|
||||
struct SThievesGuildInfo;
|
||||
class CMapHeader;
|
||||
struct TeamState;
|
||||
@@ -172,7 +172,7 @@ public:
|
||||
|
||||
|
||||
//armed object
|
||||
virtual void fillUpgradeInfo(const CArmedInstance *obj, SlotID stackPos, UpgradeInfo &out)const;
|
||||
virtual void fillUpgradeInfo(const CArmedInstance *obj, SlotID stackPos, UpgradeInfo &out) const;
|
||||
|
||||
//hero
|
||||
const CGHeroInstance * getHero(ObjectInstanceID objid) const override;
|
||||
|
||||
@@ -1088,11 +1088,12 @@ void CGameState::fillUpgradeInfo(const CArmedInstance *obj, SlotID stackPos, Upg
|
||||
out = fillUpgradeInfo(obj->getStack(stackPos));
|
||||
}
|
||||
|
||||
UpgradeInfo CGameState::fillUpgradeInfo(const CStackInstance &stack) const
|
||||
UpgradeInfo CGameState::fillUpgradeInfo(const CStackInstance & stack) const
|
||||
{
|
||||
UpgradeInfo ret;
|
||||
const CCreature *base = stack.getCreature();
|
||||
|
||||
UpgradeInfo ret(base->getId());
|
||||
|
||||
if (stack.armyObj->ID == Obj::HERO)
|
||||
{
|
||||
auto hero = dynamic_cast<const CGHeroInstance *>(stack.armyObj);
|
||||
@@ -1117,12 +1118,6 @@ UpgradeInfo CGameState::fillUpgradeInfo(const CStackInstance &stack) const
|
||||
town->fillUpgradeInfo(ret, stack);
|
||||
}
|
||||
|
||||
if(!ret.newID.empty())
|
||||
ret.oldID = base->getId();
|
||||
|
||||
for (ResourceSet &cost : ret.cost)
|
||||
cost.positive(); //upgrade cost can't be negative, ignore missing resources
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -1784,4 +1779,22 @@ ArtifactID CGameState::pickRandomArtifact(vstd::RNG & rand, int flags)
|
||||
return pickRandomArtifact(rand, flags, [](const ArtifactID &) { return true; });
|
||||
}
|
||||
|
||||
void UpgradeInfo::addUpgrade(const CreatureID & upgradeID, ResourceSet && upgradeCost, bool available)
|
||||
{
|
||||
isAvailable = available;
|
||||
upgradesIDs.push_back(upgradeID);
|
||||
|
||||
upgradeCost.positive(); //upgrade cost can't be negative, ignore missing resources
|
||||
upgradesCosts.push_back(std::move(upgradeCost));
|
||||
|
||||
// sort from highest ID to smallest
|
||||
size_t pos = upgradesIDs.size() - 1;
|
||||
while(pos > 0 && upgradesIDs[pos] > upgradesIDs[pos - 1])
|
||||
{
|
||||
std::swap(upgradesIDs[pos], upgradesIDs[pos - 1]);
|
||||
std::swap(upgradesCosts[pos], upgradesCosts[pos - 1]);
|
||||
--pos;
|
||||
}
|
||||
}
|
||||
|
||||
VCMI_LIB_NAMESPACE_END
|
||||
|
||||
@@ -39,12 +39,67 @@ struct SThievesGuildInfo;
|
||||
class CRandomGenerator;
|
||||
class GameSettings;
|
||||
|
||||
struct UpgradeInfo
|
||||
class UpgradeInfo
|
||||
{
|
||||
public:
|
||||
UpgradeInfo() = delete;
|
||||
UpgradeInfo(CreatureID base)
|
||||
: oldID(base), isAvailable(true)
|
||||
{ }
|
||||
|
||||
CreatureID oldID; //creature to be upgraded
|
||||
std::vector<CreatureID> newID; //possible upgrades
|
||||
std::vector<ResourceSet> cost; // cost[upgrade_serial] -> set of pairs<resource_ID,resource_amount>; cost is for single unit (not entire stack)
|
||||
UpgradeInfo(){oldID = CreatureID::NONE;};
|
||||
|
||||
const auto & getAvailableUpgrades() const
|
||||
{
|
||||
return upgradesIDs;
|
||||
}
|
||||
|
||||
const CreatureID & getNextUpgrade() const
|
||||
{
|
||||
return upgradesIDs.back();
|
||||
}
|
||||
|
||||
const auto & getUpgradeCostsFor(CreatureID id) const
|
||||
{
|
||||
auto idIt = std::find(upgradesIDs.begin(), upgradesIDs.end(), id);
|
||||
|
||||
assert(idIt != upgradesIDs.end());
|
||||
|
||||
return upgradesCosts[std::distance(upgradesIDs.begin(), idIt)];
|
||||
}
|
||||
|
||||
const auto & getUpgradeCosts() const
|
||||
{
|
||||
return upgradesCosts;
|
||||
}
|
||||
|
||||
const auto & getNextUpgradeCosts() const
|
||||
{
|
||||
return upgradesCosts.back();
|
||||
}
|
||||
|
||||
bool canUpgrade() const
|
||||
{
|
||||
return !upgradesIDs.empty() && isAvailable;
|
||||
}
|
||||
|
||||
bool hasUpgrades() const
|
||||
{
|
||||
return !upgradesIDs.empty();
|
||||
}
|
||||
|
||||
// Adds a new upgrade and ensures alignment and sorted order
|
||||
void addUpgrade(const CreatureID & upgradeID, ResourceSet && upgradeCost, bool available = true);
|
||||
|
||||
auto size() const
|
||||
{
|
||||
return upgradesIDs.size();
|
||||
}
|
||||
|
||||
private:
|
||||
std::vector<CreatureID> upgradesIDs; //possible upgrades
|
||||
std::vector<ResourceSet> upgradesCosts; // cost[upgrade_serial] -> set of pairs<resource_ID,resource_amount>; cost is for single unit (not entire stack)
|
||||
bool isAvailable; // flag for unavailableUpgrades like in miniHillFort from HoTA
|
||||
};
|
||||
|
||||
class BattleInfo;
|
||||
|
||||
@@ -1855,8 +1855,7 @@ void CGHeroInstance::fillUpgradeInfo(UpgradeInfo & info, const CStackInstance &s
|
||||
auto nid = CreatureID(it->additionalInfo[0]);
|
||||
if (nid != stack.getId()) //in very specific case the upgrade is available by default (?)
|
||||
{
|
||||
info.newID.push_back(nid);
|
||||
info.cost.push_back(nid.toCreature()->getFullRecruitCost() - stack.getType()->getFullRecruitCost());
|
||||
info.addUpgrade(std::move(nid), nid.toCreature()->getFullRecruitCost() - stack.getType()->getFullRecruitCost());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1234,8 +1234,7 @@ void CGTownInstance::fillUpgradeInfo(UpgradeInfo & info, const CStackInstance &s
|
||||
{
|
||||
if(vstd::contains(stack.getCreature()->upgrades, upgrID)) //possible upgrade
|
||||
{
|
||||
info.newID.push_back(upgrID);
|
||||
info.cost.push_back(upgrID.toCreature()->getFullRecruitCost() - stack.getType()->getFullRecruitCost());
|
||||
info.addUpgrade(upgrID, upgrID.toCreature()->getFullRecruitCost() - stack.getType()->getFullRecruitCost());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@ class RNG;
|
||||
}
|
||||
|
||||
struct BattleResult;
|
||||
struct UpgradeInfo;
|
||||
class UpgradeInfo;
|
||||
class BoatId;
|
||||
class CGObjectInstance;
|
||||
class CStackInstance;
|
||||
|
||||
@@ -1323,13 +1323,12 @@ void HillFort::fillUpgradeInfo(UpgradeInfo & info, const CStackInstance &stack)
|
||||
|
||||
int costModifier = upgradeCostPercentage[index];
|
||||
|
||||
if (costModifier < 0)
|
||||
return; // upgrade not allowed
|
||||
if(costModifier < 0)
|
||||
return;
|
||||
|
||||
for(const auto & nid : stack.getCreature()->upgrades)
|
||||
{
|
||||
info.newID.push_back(nid);
|
||||
info.cost.push_back((nid.toCreature()->getFullRecruitCost() - stack.getType()->getFullRecruitCost()) * costModifier / 100);
|
||||
info.addUpgrade(nid, (nid, (nid.toCreature()->getFullRecruitCost() - stack.getType()->getFullRecruitCost()) * costModifier / 100), costModifier >= 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -2414,19 +2414,19 @@ bool CGameHandler::upgradeCreature(ObjectInstanceID objid, SlotID pos, CreatureI
|
||||
{
|
||||
COMPLAIN_RET("Cannot upgrade, no stack at slot " + std::to_string(pos));
|
||||
}
|
||||
UpgradeInfo ui;
|
||||
UpgradeInfo ui(obj->getStackPtr(pos)->getId());
|
||||
fillUpgradeInfo(obj, pos, ui);
|
||||
PlayerColor player = obj->tempOwner;
|
||||
const PlayerState *p = getPlayerState(player);
|
||||
int crQuantity = obj->stacks.at(pos)->count;
|
||||
int newIDpos= vstd::find_pos(ui.newID, upgID);//get position of new id in UpgradeInfo
|
||||
int newIDpos= vstd::find_pos(ui.getAvailableUpgrades(), upgID);//get position of new id in UpgradeInfo
|
||||
|
||||
//check if upgrade is possible
|
||||
if ((ui.oldID == CreatureID::NONE || newIDpos == -1) && complain("That upgrade is not possible!"))
|
||||
if (!ui.hasUpgrades() && complain("That upgrade is not possible!"))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
TResources totalCost = ui.cost.at(newIDpos) * crQuantity;
|
||||
TResources totalCost = ui.getUpgradeCostsFor(upgID) * crQuantity;
|
||||
|
||||
//check if player has enough resources
|
||||
if (!p->resources.canAfford(totalCost))
|
||||
|
||||
Reference in New Issue
Block a user