1
0
mirror of https://github.com/vcmi/vcmi.git synced 2024-12-24 22:14:36 +02:00

vcmi: massive refactoring v1

This commit is contained in:
Konstantin 2023-04-05 03:26:29 +03:00
parent ee489f18d2
commit 11b237a23c
129 changed files with 803 additions and 762 deletions

View File

@ -101,7 +101,7 @@ BattleAction CBattleAI::activeStack( const CStack * stack )
try try
{ {
if(stack->type->idNumber == CreatureID::CATAPULT) if(stack->type->getId() == CreatureID::CATAPULT)
return useCatapult(stack); return useCatapult(stack);
if(stack->hasBonusOfType(Bonus::SIEGE_WEAPON) && stack->hasBonusOfType(Bonus::HEALER)) if(stack->hasBonusOfType(Bonus::SIEGE_WEAPON) && stack->hasBonusOfType(Bonus::HEALER))
{ {

View File

@ -435,7 +435,7 @@ int64_t HypotheticBattle::getActualDamage(const DamageRange & damage, int32_t at
int64_t HypotheticBattle::getTreeVersion() const int64_t HypotheticBattle::getTreeVersion() const
{ {
return getBattleNode()->getTreeVersion() + bonusTreeVersion; return getBonusBearer()->getTreeVersion() + bonusTreeVersion;
} }
#if SCRIPTING_ENABLED #if SCRIPTING_ENABLED

View File

@ -1053,7 +1053,7 @@ void AIGateway::recruitCreatures(const CGDwelling * d, const CArmedInstance * re
int count = d->creatures[i].first; int count = d->creatures[i].first;
CreatureID creID = d->creatures[i].second.back(); CreatureID creID = d->creatures[i].second.back();
vstd::amin(count, cb->getResourceAmount() / VLC->creh->objects[creID]->cost); vstd::amin(count, cb->getResourceAmount() / creID.toCreature()->getFullRecruitCost());
if(count > 0) if(count > 0)
cb->recruitCreatures(d, recruiter, creID, count, i); cb->recruitCreatures(d, recruiter, creID, count, i);
} }
@ -1068,7 +1068,7 @@ bool AIGateway::canRecruitAnyHero(const CGTownInstance * t) const
if(!t || !townHasFreeTavern(t)) if(!t || !townHasFreeTavern(t))
return false; return false;
if(cb->getResourceAmount(Res::GOLD) < GameConstants::HERO_GOLD_COST) //TODO: use ResourceManager if(cb->getResourceAmount(EGameResID::GOLD) < GameConstants::HERO_GOLD_COST) //TODO: use ResourceManager
return false; return false;
if(cb->getHeroesInfo().size() >= ALLOWED_ROAMING_HEROES) if(cb->getHeroesInfo().size() >= ALLOWED_ROAMING_HEROES)
return false; return false;
@ -1390,7 +1390,7 @@ void AIGateway::tryRealize(Goals::DigAtTile & g)
void AIGateway::tryRealize(Goals::Trade & g) //trade void AIGateway::tryRealize(Goals::Trade & g) //trade
{ {
if(cb->getResourceAmount((Res::ERes)g.resID) >= g.value) //goal is already fulfilled. Why we need this check, anyway? if(cb->getResourceAmount(GameResID(g.resID)) >= g.value) //goal is already fulfilled. Why we need this check, anyway?
throw goalFulfilledException(sptr(g)); throw goalFulfilledException(sptr(g));
int accquiredResources = 0; int accquiredResources = 0;
@ -1399,10 +1399,10 @@ void AIGateway::tryRealize(Goals::Trade & g) //trade
if(const IMarket * m = IMarket::castFrom(obj, false)) if(const IMarket * m = IMarket::castFrom(obj, false))
{ {
auto freeRes = cb->getResourceAmount(); //trade only resources which are not reserved auto freeRes = cb->getResourceAmount(); //trade only resources which are not reserved
for(auto it = Res::ResourceSet::nziterator(freeRes); it.valid(); it++) for(auto it = ResourceSet::nziterator(freeRes); it.valid(); it++)
{ {
auto res = it->resType; auto res = it->resType;
if(res == g.resID) //sell any other resource if(res.getNum() == g.resID) //sell any other resource
continue; continue;
int toGive, toGet; int toGive, toGet;
@ -1415,7 +1415,7 @@ void AIGateway::tryRealize(Goals::Trade & g) //trade
accquiredResources = static_cast<int>(toGet * (it->resVal / toGive)); accquiredResources = static_cast<int>(toGet * (it->resVal / toGive));
logAi->debug("Traded %d of %s for %d of %s at %s", toGive, res, accquiredResources, g.resID, obj->getObjectName()); logAi->debug("Traded %d of %s for %d of %s at %s", toGive, res, accquiredResources, g.resID, obj->getObjectName());
} }
if (cb->getResourceAmount((Res::ERes)g.resID) >= g.value) if (cb->getResourceAmount(GameResID(g.resID)))
throw goalFulfilledException(sptr(g)); //we traded all we needed throw goalFulfilledException(sptr(g)); //we traded all we needed
} }

View File

@ -20,6 +20,8 @@
#include "../../lib/GameSettings.h" #include "../../lib/GameSettings.h"
#include <vcmi/CreatureService.h>
namespace NKAI namespace NKAI
{ {
@ -278,8 +280,8 @@ creInfo infoFromDC(const dwellingContent & dc)
ci.creID = dc.second.size() ? dc.second.back() : CreatureID(-1); //should never be accessed ci.creID = dc.second.size() ? dc.second.back() : CreatureID(-1); //should never be accessed
if (ci.creID != -1) if (ci.creID != -1)
{ {
ci.cre = VLC->creh->objects[ci.creID].get(); ci.cre = VLC->creatures()->getById(ci.creID);
ci.level = ci.cre->level; //this is cretaure tier, while tryRealize expects dwelling level. Ignore. ci.level = ci.cre->getLevel(); //this is creature tier, while tryRealize expects dwelling level. Ignore.
} }
else else
{ {
@ -398,7 +400,7 @@ bool shouldVisit(const Nullkiller * ai, const CGHeroInstance * h, const CGObject
{ {
if(level.first if(level.first
&& h->getSlotFor(CreatureID(c)) != SlotID() && h->getSlotFor(CreatureID(c)) != SlotID()
&& ai->cb->getResourceAmount().canAfford(c.toCreature()->cost)) && ai->cb->getResourceAmount().canAfford(c.toCreature()->getFullRecruitCost()))
{ {
return true; return true;
} }
@ -411,7 +413,7 @@ bool shouldVisit(const Nullkiller * ai, const CGHeroInstance * h, const CGObject
{ {
for(auto slot : h->Slots()) for(auto slot : h->Slots())
{ {
if(slot.second->type->upgrades.size()) if(slot.second->type->hasUpgrades())
return true; //TODO: check price? return true; //TODO: check price?
} }
return false; return false;
@ -438,7 +440,7 @@ bool shouldVisit(const Nullkiller * ai, const CGHeroInstance * h, const CGObject
return false; return false;
TResources myRes = ai->getFreeResources(); TResources myRes = ai->getFreeResources();
if(myRes[Res::GOLD] < 2000 || myRes[Res::GEMS] < 10) if(myRes[EGameResID::GOLD] < 2000 || myRes[EGameResID::GEMS] < 10)
return false; return false;
break; break;
} }

View File

@ -161,7 +161,7 @@ struct creInfo
{ {
int count; int count;
CreatureID creID; CreatureID creID;
CCreature * cre; const Creature * cre;
int level; int level;
}; };
creInfo infoFromDC(const dwellingContent & dc); creInfo infoFromDC(const dwellingContent & dc);

View File

@ -28,8 +28,8 @@ public:
StackUpgradeInfo(CreatureID initial, CreatureID upgraded, int count) StackUpgradeInfo(CreatureID initial, CreatureID upgraded, int count)
:initialCreature(initial), upgradedCreature(upgraded), count(count) :initialCreature(initial), upgradedCreature(upgraded), count(count)
{ {
cost = (upgradedCreature.toCreature()->cost - initialCreature.toCreature()->cost) * count; cost = (upgradedCreature.toCreature()->getFullRecruitCost() - initialCreature.toCreature()->getFullRecruitCost()) * count;
upgradeValue = (upgradedCreature.toCreature()->AIValue - initialCreature.toCreature()->AIValue) * count; upgradeValue = (upgradedCreature.toCreature()->getAIValue() - initialCreature.toCreature()->getAIValue()) * count;
} }
}; };
@ -50,9 +50,10 @@ std::vector<SlotInfo> ArmyManager::getSortedSlots(const CCreatureSet * target, c
{ {
for(auto & i : armyPtr->Slots()) for(auto & i : armyPtr->Slots())
{ {
auto & slotInfp = creToPower[i.second->type]; auto cre = dynamic_cast<const CCreature*>(i.second->type);
auto & slotInfp = creToPower[cre];
slotInfp.creature = i.second->type; slotInfp.creature = cre;
slotInfp.power += i.second->getPower(); slotInfp.power += i.second->getPower();
slotInfp.count += i.second->count; slotInfp.count += i.second->count;
} }
@ -73,8 +74,8 @@ std::vector<SlotInfo>::iterator ArmyManager::getWeakestCreature(std::vector<Slot
{ {
auto weakest = boost::min_element(army, [](const SlotInfo & left, const SlotInfo & right) -> bool auto weakest = boost::min_element(army, [](const SlotInfo & left, const SlotInfo & right) -> bool
{ {
if(left.creature->level != right.creature->level) if(left.creature->getLevel() != right.creature->getLevel())
return left.creature->level < right.creature->level; return left.creature->getLevel() < right.creature->getLevel();
return left.creature->Speed() > right.creature->Speed(); return left.creature->Speed() > right.creature->Speed();
}); });
@ -99,7 +100,7 @@ std::vector<SlotInfo> ArmyManager::getBestArmy(const IBonusBearer * armyCarrier,
for(auto & slot : sortedSlots) for(auto & slot : sortedSlots)
{ {
alignmentMap[slot.creature->faction] += slot.power; alignmentMap[slot.creature->getFactionIndex()] += slot.power;
} }
std::set<TFaction> allowedFactions; std::set<TFaction> allowedFactions;
@ -133,13 +134,13 @@ std::vector<SlotInfo> ArmyManager::getBestArmy(const IBonusBearer * armyCarrier,
for(auto & slot : sortedSlots) for(auto & slot : sortedSlots)
{ {
if(vstd::contains(allowedFactions, slot.creature->faction)) if(vstd::contains(allowedFactions, slot.creature->getFactionIndex()))
{ {
auto slotID = newArmyInstance.getSlotFor(slot.creature); auto slotID = newArmyInstance.getSlotFor(slot.creature);
if(slotID.validSlot()) if(slotID.validSlot())
{ {
newArmyInstance.setCreature(slotID, slot.creature->idNumber, slot.count); newArmyInstance.setCreature(slotID, slot.creature->getId(), slot.count);
newArmy.push_back(slot); newArmy.push_back(slot);
} }
} }
@ -217,7 +218,7 @@ std::shared_ptr<CCreatureSet> ArmyManager::getArmyAvailableToBuyAsCCreatureSet(
if(!ci.count || ci.creID == -1) if(!ci.count || ci.creID == -1)
continue; continue;
vstd::amin(ci.count, availableRes / ci.cre->cost); //max count we can afford vstd::amin(ci.count, availableRes / ci.cre->getFullRecruitCost()); //max count we can afford
if(!ci.count) if(!ci.count)
continue; continue;
@ -228,7 +229,7 @@ std::shared_ptr<CCreatureSet> ArmyManager::getArmyAvailableToBuyAsCCreatureSet(
break; break;
army->setCreature(dst, ci.creID, ci.count); army->setCreature(dst, ci.creID, ci.count);
availableRes -= ci.cre->cost * ci.count; availableRes -= ci.cre->getFullRecruitCost() * ci.count;
} }
return army; return army;
@ -244,7 +245,7 @@ ui64 ArmyManager::howManyReinforcementsCanBuy(
for(const creInfo & ci : army) for(const creInfo & ci : army)
{ {
aivalue += ci.count * ci.cre->AIValue; aivalue += ci.count * ci.cre->getAIValue();
} }
return aivalue; return aivalue;
@ -279,14 +280,14 @@ std::vector<creInfo> ArmyManager::getArmyAvailableToBuy(
freeHeroSlots--; //new slot will be occupied freeHeroSlots--; //new slot will be occupied
} }
vstd::amin(ci.count, availableRes / ci.cre->cost); //max count we can afford vstd::amin(ci.count, availableRes / ci.cre->getFullRecruitCost()); //max count we can afford
if(!ci.count) if(!ci.count)
continue; continue;
ci.level = i; //this is important for Dungeon Summoning Portal ci.level = i; //this is important for Dungeon Summoning Portal
creaturesInDwellings.push_back(ci); creaturesInDwellings.push_back(ci);
availableRes -= ci.cre->cost * ci.count; availableRes -= ci.cre->getFullRecruitCost() * ci.count;
} }
return creaturesInDwellings; return creaturesInDwellings;
@ -308,7 +309,7 @@ ui64 ArmyManager::howManyReinforcementsCanGet(const IBonusBearer * armyCarrier,
uint64_t ArmyManager::evaluateStackPower(const CCreature * creature, int count) const uint64_t ArmyManager::evaluateStackPower(const CCreature * creature, int count) const
{ {
return creature->AIValue * count; return creature->getAIValue() * count;
} }
SlotInfo ArmyManager::getTotalCreaturesAvailable(CreatureID creatureID) const SlotInfo ArmyManager::getTotalCreaturesAvailable(CreatureID creatureID) const
@ -378,12 +379,12 @@ std::vector<StackUpgradeInfo> ArmyManager::getHillFortUpgrades(const CCreatureSe
CreatureID strongestUpgrade = *vstd::minElementByFun(possibleUpgrades, [](CreatureID cre) -> uint64_t CreatureID strongestUpgrade = *vstd::minElementByFun(possibleUpgrades, [](CreatureID cre) -> uint64_t
{ {
return cre.toCreature()->AIValue; return cre.toCreature()->getAIValue();
}); });
StackUpgradeInfo upgrade = StackUpgradeInfo(initial, strongestUpgrade, creature.second->count); StackUpgradeInfo upgrade = StackUpgradeInfo(initial, strongestUpgrade, creature.second->count);
if(initial.toCreature()->level == 1) if(initial.toCreature()->getLevel() == 1)
upgrade.cost = TResources(); upgrade.cost = TResources();
upgrades.push_back(upgrade); upgrades.push_back(upgrade);
@ -417,7 +418,7 @@ std::vector<StackUpgradeInfo> ArmyManager::getDwellingUpgrades(const CCreatureSe
CreatureID strongestUpgrade = *vstd::minElementByFun(possibleUpgrades, [](CreatureID cre) -> uint64_t CreatureID strongestUpgrade = *vstd::minElementByFun(possibleUpgrades, [](CreatureID cre) -> uint64_t
{ {
return cre.toCreature()->AIValue; return cre.toCreature()->getAIValue();
}); });
StackUpgradeInfo upgrade = StackUpgradeInfo(initial, strongestUpgrade, creature.second->count); StackUpgradeInfo upgrade = StackUpgradeInfo(initial, strongestUpgrade, creature.second->count);
@ -488,7 +489,7 @@ ArmyUpgradeInfo ArmyManager::calculateCreaturesUpgrade(
upgradedArmy.power = evaluateStackPower(upgradedArmy.creature, upgradedArmy.count); upgradedArmy.power = evaluateStackPower(upgradedArmy.creature, upgradedArmy.count);
auto slotToReplace = std::find_if(result.resultingArmy.begin(), result.resultingArmy.end(), [&](const SlotInfo & slot) -> bool { auto slotToReplace = std::find_if(result.resultingArmy.begin(), result.resultingArmy.end(), [&](const SlotInfo & slot) -> bool {
return slot.count == upgradedArmy.count && slot.creature->idNumber == upgrade.initialCreature; return slot.count == upgradedArmy.count && slot.creature->getId() == upgrade.initialCreature;
}); });
resourcesLeft -= upgrade.cost; resourcesLeft -= upgrade.cost;

View File

@ -93,9 +93,9 @@ void BuildAnalyzer::updateOtherBuildings(TownDevelopmentInfo & developmentInfo)
int32_t convertToGold(const TResources & res) int32_t convertToGold(const TResources & res)
{ {
return res[Res::GOLD] return res[EGameResID::GOLD]
+ 75 * (res[Res::WOOD] + res[Res::ORE]) + 75 * (res[EGameResID::WOOD] + res[EGameResID::ORE])
+ 125 * (res[Res::GEMS] + res[Res::CRYSTAL] + res[Res::MERCURY] + res[Res::SULFUR]); + 125 * (res[EGameResID::GEMS] + res[EGameResID::CRYSTAL] + res[EGameResID::MERCURY] + res[EGameResID::SULFUR]);
} }
TResources BuildAnalyzer::getResourcesRequiredNow() const TResources BuildAnalyzer::getResourcesRequiredNow() const
@ -164,8 +164,8 @@ void BuildAnalyzer::update()
} }
else else
{ {
goldPreasure = ai->getLockedResources()[Res::GOLD] / 10000.0f goldPreasure = ai->getLockedResources()[EGameResID::GOLD] / 10000.0f
+ (float)armyCost[Res::GOLD] / (1 + ai->getFreeGold() + (float)dailyIncome[Res::GOLD] * 7.0f); + (float)armyCost[EGameResID::GOLD] / (1 + ai->getFreeGold() + (float)dailyIncome[EGameResID::GOLD] * 7.0f);
} }
logAi->trace("Gold preasure: %f", goldPreasure); logAi->trace("Gold preasure: %f", goldPreasure);
@ -280,7 +280,7 @@ void BuildAnalyzer::updateDailyIncome()
if(mine) if(mine)
{ {
dailyIncome[mine->producedResource] += mine->producedQuantity; dailyIncome[mine->producedResource.getNum()] += mine->producedQuantity;
} }
} }
@ -355,10 +355,10 @@ BuildingInfo::BuildingInfo(
if(creature) if(creature)
{ {
creatureGrows = creature->growth; creatureGrows = creature->getGrowth();
creatureID = creature->idNumber; creatureID = creature->getId();
creatureCost = creature->cost; creatureCost = creature->getFullRecruitCost();
creatureLevel = creature->level; creatureLevel = creature->getLevel();
baseCreatureID = baseCreature; baseCreatureID = baseCreature;
if(exists) if(exists)
@ -367,7 +367,7 @@ BuildingInfo::BuildingInfo(
} }
else else
{ {
creatureGrows = creature->growth; creatureGrows = creature->getGrowth();
if(town->hasBuilt(BuildingID::CASTLE)) if(town->hasBuilt(BuildingID::CASTLE))
creatureGrows *= 2; creatureGrows *= 2;

View File

@ -58,7 +58,7 @@ Goals::TGoalVec BuildingBehavior::decompose() const
{ {
for(auto & buildingInfo : developmentInfo.toBuild) for(auto & buildingInfo : developmentInfo.toBuild)
{ {
if(goldPreasure < MAX_GOLD_PEASURE || buildingInfo.dailyIncome[Res::GOLD] > 0) if(goldPreasure < MAX_GOLD_PEASURE || buildingInfo.dailyIncome[EGameResID::GOLD] > 0)
{ {
if(buildingInfo.notEnoughRes) if(buildingInfo.notEnoughRes)
{ {

View File

@ -162,7 +162,7 @@ void DefenceBehavior::evaluateDefence(Goals::TGoalVec & tasks, const CGTownInsta
if(!town->visitingHero if(!town->visitingHero
&& town->hasBuilt(BuildingID::TAVERN) && town->hasBuilt(BuildingID::TAVERN)
&& cb->getResourceAmount(Res::GOLD) > GameConstants::HERO_GOLD_COST) && cb->getResourceAmount(EGameResID::GOLD) > GameConstants::HERO_GOLD_COST)
{ {
auto heroesInTavern = cb->getAvailableHeroes(town); auto heroesInTavern = cb->getAvailableHeroes(town);

View File

@ -69,7 +69,7 @@ Goals::TGoalVec RecruitHeroBehavior::decompose() const
} }
if(cb->getHeroesInfo().size() < cb->getTownsInfo().size() + 1 if(cb->getHeroesInfo().size() < cb->getTownsInfo().size() + 1
|| (ai->nullkiller->getFreeResources()[Res::GOLD] > 10000 || (ai->nullkiller->getFreeResources()[EGameResID::GOLD] > 10000
&& ai->nullkiller->buildAnalyzer->getGoldPreasure() < MAX_GOLD_PEASURE)) && ai->nullkiller->buildAnalyzer->getGoldPreasure() < MAX_GOLD_PEASURE))
{ {
tasks.push_back(Goals::sptr(Goals::RecruitHero(town).setpriority(3))); tasks.push_back(Goals::sptr(Goals::RecruitHero(town).setpriority(3)));

View File

@ -76,7 +76,7 @@ bool needToRecruitHero(const CGTownInstance * startupTown)
for(auto obj : ai->nullkiller->objectClusterizer->getNearbyObjects()) for(auto obj : ai->nullkiller->objectClusterizer->getNearbyObjects())
{ {
if((obj->ID == Obj::RESOURCE && obj->subID == Res::GOLD) if((obj->ID == Obj::RESOURCE && obj->subID == GameResID(EGameResID::GOLD))
|| obj->ID == Obj::TREASURE_CHEST || obj->ID == Obj::TREASURE_CHEST
|| obj->ID == Obj::CAMPFIRE || obj->ID == Obj::CAMPFIRE
|| obj->ID == Obj::WATER_WHEEL) || obj->ID == Obj::WATER_WHEEL)

View File

@ -65,13 +65,13 @@ armyStructure evaluateArmyStructure(const CArmedInstance * army)
for(auto s : army->Slots()) for(auto s : army->Slots())
{ {
bool walker = true; bool walker = true;
const CCreature * creature = s.second->type; auto bearer = s.second->getType()->getBonusBearer();
if(creature->hasBonus(selectorSHOOTER, keySHOOTER)) if(bearer->hasBonus(selectorSHOOTER, keySHOOTER))
{ {
shootersStrength += s.second->getPower(); shootersStrength += s.second->getPower();
walker = false; walker = false;
} }
if(creature->hasBonus(selectorFLYING, keyFLYING)) if(bearer->hasBonus(selectorFLYING, keyFLYING))
{ {
flyersStrength += s.second->getPower(); flyersStrength += s.second->getPower();
walker = false; walker = false;
@ -79,7 +79,7 @@ armyStructure evaluateArmyStructure(const CArmedInstance * army)
if(walker) if(walker)
walkersStrength += s.second->getPower(); walkersStrength += s.second->getPower();
vstd::amax(maxSpeed, creature->valOfBonuses(selectorSTACKS_SPEED, keySTACKS_SPEED)); vstd::amax(maxSpeed, bearer->valOfBonuses(selectorSTACKS_SPEED, keySTACKS_SPEED));
} }
armyStructure as; armyStructure as;
as.walkers = static_cast<float>(walkersStrength / totalStrength); as.walkers = static_cast<float>(walkersStrength / totalStrength);

View File

@ -85,7 +85,7 @@ public:
void unlockHero(const CGHeroInstance * hero) { lockedHeroes.erase(hero); } void unlockHero(const CGHeroInstance * hero) { lockedHeroes.erase(hero); }
bool arePathHeroesLocked(const AIPath & path) const; bool arePathHeroesLocked(const AIPath & path) const;
TResources getFreeResources() const; TResources getFreeResources() const;
int32_t getFreeGold() const { return getFreeResources()[Res::GOLD]; } int32_t getFreeGold() const { return getFreeResources()[EGameResID::GOLD]; }
void lockResources(const TResources & res); void lockResources(const TResources & res);
const TResources & getLockedResources() const { return lockedResources; } const TResources & getLockedResources() const { return lockedResources; }

View File

@ -148,14 +148,15 @@ uint64_t getCreatureBankArmyReward(const CGObjectInstance * target, const CGHero
for (auto c : creatures) for (auto c : creatures)
{ {
//Only if hero has slot for this creature in the army //Only if hero has slot for this creature in the army
if (hero->getSlotFor(c.data.type).validSlot()) auto ccre = dynamic_cast<const CCreature*>(c.data.type);
if (hero->getSlotFor(ccre).validSlot())
{ {
result += (c.data.type->AIValue * c.data.count) * c.chance; result += (c.data.type->getAIValue() * c.data.count) * c.chance;
} }
else else
{ {
//we will need to discard the weakest stack //we will need to discard the weakest stack
result += (c.data.type->AIValue * c.data.count - weakestStackPower) * c.chance; result += (c.data.type->getAIValue() * c.data.count - weakestStackPower) * c.chance;
} }
} }
result /= 100; //divide by total chance result /= 100; //divide by total chance
@ -173,11 +174,11 @@ uint64_t getDwellingScore(CCallback * cb, const CGObjectInstance * target, bool
if(creLevel.first && creLevel.second.size()) if(creLevel.first && creLevel.second.size())
{ {
auto creature = creLevel.second.back().toCreature(); auto creature = creLevel.second.back().toCreature();
auto creaturesAreFree = creature->level == 1; auto creaturesAreFree = creature->getLevel() == 1;
if(!creaturesAreFree && checkGold && !cb->getResourceAmount().canAfford(creature->cost * creLevel.first)) if(!creaturesAreFree && checkGold && !cb->getResourceAmount().canAfford(creature->getFullRecruitCost() * creLevel.first))
continue; continue;
score += creature->AIValue * creLevel.first; score += creature->getAIValue() * creLevel.first;
} }
} }
@ -194,9 +195,9 @@ int getDwellingArmyCost(const CGObjectInstance * target)
if(creLevel.first && creLevel.second.size()) if(creLevel.first && creLevel.second.size())
{ {
auto creature = creLevel.second.back().toCreature(); auto creature = creLevel.second.back().toCreature();
auto creaturesAreFree = creature->level == 1; auto creaturesAreFree = creature->getLevel() == 1;
if(!creaturesAreFree) if(!creaturesAreFree)
cost += creature->cost[Res::GOLD] * creLevel.first; cost += creature->getRecruitCost(EGameResID::GOLD) * creLevel.first;
} }
} }
@ -300,7 +301,7 @@ int RewardEvaluator::getGoldCost(const CGObjectInstance * target, const CGHeroIn
switch(target->ID) switch(target->ID)
{ {
case Obj::HILL_FORT: case Obj::HILL_FORT:
return ai->armyManager->calculateCreaturesUpgrade(army, target, ai->cb->getResourceAmount()).upgradeCost[Res::GOLD]; return ai->armyManager->calculateCreaturesUpgrade(army, target, ai->cb->getResourceAmount()).upgradeCost[EGameResID::GOLD];
case Obj::SCHOOL_OF_MAGIC: case Obj::SCHOOL_OF_MAGIC:
case Obj::SCHOOL_OF_WAR: case Obj::SCHOOL_OF_WAR:
return 1000; return 1000;
@ -375,12 +376,12 @@ float RewardEvaluator::getStrategicalValue(const CGObjectInstance * target) cons
switch(target->ID) switch(target->ID)
{ {
case Obj::MINE: case Obj::MINE:
return target->subID == Res::GOLD return target->subID == GameResID(EGameResID::GOLD)
? 0.5f ? 0.5f
: 0.4f * getTotalResourceRequirementStrength(target->subID) + 0.1f * getResourceRequirementStrength(target->subID); : 0.4f * getTotalResourceRequirementStrength(target->subID) + 0.1f * getResourceRequirementStrength(target->subID);
case Obj::RESOURCE: case Obj::RESOURCE:
return target->subID == Res::GOLD return target->subID == GameResID(EGameResID::GOLD)
? 0 ? 0
: 0.2f * getTotalResourceRequirementStrength(target->subID) + 0.4f * getResourceRequirementStrength(target->subID); : 0.2f * getTotalResourceRequirementStrength(target->subID) + 0.4f * getResourceRequirementStrength(target->subID);
@ -391,7 +392,7 @@ float RewardEvaluator::getStrategicalValue(const CGObjectInstance * target) cons
for (TResources::nziterator it (resourceReward); it.valid(); it++) for (TResources::nziterator it (resourceReward); it.valid(); it++)
{ {
//Evaluate resources used for construction. Gold is evaluated separately. //Evaluate resources used for construction. Gold is evaluated separately.
if (it->resType != Res::GOLD) if (it->resType != EGameResID::GOLD)
{ {
sum += 0.1f * getResourceRequirementStrength(it->resType); sum += 0.1f * getResourceRequirementStrength(it->resType);
} }
@ -502,7 +503,7 @@ int32_t getArmyCost(const CArmedInstance * army)
for(auto stack : army->Slots()) for(auto stack : army->Slots())
{ {
value += stack.second->getCreatureID().toCreature()->cost[Res::GOLD] * stack.second->count; value += stack.second->getCreatureID().toCreature()->getRecruitCost(EGameResID::GOLD) * stack.second->count;
} }
return value; return value;
@ -517,7 +518,7 @@ int32_t RewardEvaluator::getGoldReward(const CGObjectInstance * target, const CG
const int dailyIncomeMultiplier = 5; const int dailyIncomeMultiplier = 5;
const float enemyArmyEliminationGoldRewardRatio = 0.2f; const float enemyArmyEliminationGoldRewardRatio = 0.2f;
const int32_t heroEliminationBonus = GameConstants::HERO_GOLD_COST / 2; const int32_t heroEliminationBonus = GameConstants::HERO_GOLD_COST / 2;
auto isGold = target->subID == Res::GOLD; // TODO: other resorces could be sold but need to evaluate market power auto isGold = target->subID == GameResID(EGameResID::GOLD); // TODO: other resorces could be sold but need to evaluate market power
switch(target->ID) switch(target->ID)
{ {
@ -540,7 +541,7 @@ int32_t RewardEvaluator::getGoldReward(const CGObjectInstance * target, const CG
case Obj::WAGON: case Obj::WAGON:
return 100; return 100;
case Obj::CREATURE_BANK: case Obj::CREATURE_BANK:
return getCreatureBankResources(target, hero)[Res::GOLD]; return getCreatureBankResources(target, hero)[EGameResID::GOLD];
case Obj::CRYPT: case Obj::CRYPT:
case Obj::DERELICT_SHIP: case Obj::DERELICT_SHIP:
return 3000; return 3000;
@ -627,7 +628,7 @@ private:
continue; continue;
auto creature = creatureInfo.second.back().toCreature(); auto creature = creatureInfo.second.back().toCreature();
result += creature->AIValue * town->getGrowthInfo(creature->getLevel() - 1).totalGrowth(); result += creature->getAIValue() * town->getGrowthInfo(creature->getLevel() - 1).totalGrowth();
} }
return result; return result;
@ -644,7 +645,7 @@ public:
auto & treat = defendTown.getTreat(); auto & treat = defendTown.getTreat();
auto armyIncome = townArmyIncome(town); auto armyIncome = townArmyIncome(town);
auto dailyIncome = town->dailyIncome()[Res::GOLD]; auto dailyIncome = town->dailyIncome()[EGameResID::GOLD];
auto strategicalValue = std::sqrt(armyIncome / 20000.0f) + dailyIncome / 3000.0f; auto strategicalValue = std::sqrt(armyIncome / 20000.0f) + dailyIncome / 3000.0f;
@ -804,10 +805,10 @@ public:
Goals::BuildThis & buildThis = dynamic_cast<Goals::BuildThis &>(*task); Goals::BuildThis & buildThis = dynamic_cast<Goals::BuildThis &>(*task);
auto & bi = buildThis.buildingInfo; auto & bi = buildThis.buildingInfo;
evaluationContext.goldReward += 7 * bi.dailyIncome[Res::GOLD] / 2; // 7 day income but half we already have evaluationContext.goldReward += 7 * bi.dailyIncome[EGameResID::GOLD] / 2; // 7 day income but half we already have
evaluationContext.heroRole = HeroRole::MAIN; evaluationContext.heroRole = HeroRole::MAIN;
evaluationContext.movementCostByRole[evaluationContext.heroRole] += bi.prerequisitesCount; evaluationContext.movementCostByRole[evaluationContext.heroRole] += bi.prerequisitesCount;
evaluationContext.goldCost += bi.buildCostWithPrerequisits[Res::GOLD]; evaluationContext.goldCost += bi.buildCostWithPrerequisits[EGameResID::GOLD];
if(bi.creatureID != CreatureID::NONE) if(bi.creatureID != CreatureID::NONE)
{ {
@ -921,7 +922,7 @@ float PriorityEvaluator::evaluate(Goals::TSubgoal task)
closestHeroRatioVariable->setValue(evaluationContext.closestWayRatio); closestHeroRatioVariable->setValue(evaluationContext.closestWayRatio);
strategicalValueVariable->setValue(evaluationContext.strategicalValue); strategicalValueVariable->setValue(evaluationContext.strategicalValue);
goldPreasureVariable->setValue(ai->buildAnalyzer->getGoldPreasure()); goldPreasureVariable->setValue(ai->buildAnalyzer->getGoldPreasure());
goldCostVariable->setValue(evaluationContext.goldCost / ((float)ai->getFreeResources()[Res::GOLD] + (float)ai->buildAnalyzer->getDailyIncome()[Res::GOLD] + 1.0f)); goldCostVariable->setValue(evaluationContext.goldCost / ((float)ai->getFreeResources()[EGameResID::GOLD] + (float)ai->buildAnalyzer->getDailyIncome()[EGameResID::GOLD] + 1.0f));
turnVariable->setValue(evaluationContext.turn); turnVariable->setValue(evaluationContext.turn);
fearVariable->setValue(evaluationContext.enemyHeroDangerRatio); fearVariable->setValue(evaluationContext.enemyHeroDangerRatio);

View File

@ -57,12 +57,12 @@ void BuyArmy::accept(AIGateway * ai)
if(objid != -1 && ci.creID != objid) if(objid != -1 && ci.creID != objid)
continue; continue;
vstd::amin(ci.count, res / ci.cre->cost); vstd::amin(ci.count, res / ci.cre->getFullRecruitCost());
if(ci.count) if(ci.count)
{ {
cb->recruitCreatures(town, town->getUpperArmy(), ci.creID, ci.count, ci.level); cb->recruitCreatures(town, town->getUpperArmy(), ci.creID, ci.count, ci.level);
valueBought += ci.count * ci.cre->AIValue; valueBought += ci.count * ci.cre->getAIValue();
} }
} }

View File

@ -214,7 +214,7 @@ TGoalVec CompleteQuest::missionResources() const
for(int i = 0; i < q.quest->m7resources.size(); ++i) for(int i = 0; i < q.quest->m7resources.size(); ++i)
{ {
if(q.quest->m7resources[i]) if(q.quest->m7resources[i])
solutions.push_back(sptr(CollectRes(i, q.quest->m7resources[i]))); solutions.push_back(sptr(CollectRes(static_cast<EGameResID>(i), q.quest->m7resources[i])));
} }
} }
} }

View File

@ -162,7 +162,7 @@ TGoalVec GatherArmy::getAllPossibleSubgoals()
for(auto & creatureID : creLevel.second) for(auto & creatureID : creLevel.second)
{ {
auto creature = VLC->creh->creatures[creatureID]; auto creature = VLC->creh->creatures[creatureID];
if(ai->ah->freeResources().canAfford(creature->cost)) if(ai->ah->freeResources().canAfford(creature->getFullRecruitCost()))
objs.push_back(obj); //TODO: reserve resources? objs.push_back(obj); //TODO: reserve resources?
} }
} }

View File

@ -27,10 +27,10 @@ namespace Goals
: CGoal(Goals::TRADE) : CGoal(Goals::TRADE)
{ {
} }
Trade(int rid, int val, int Objid) Trade(GameResID rid, int val, int Objid)
: CGoal(Goals::TRADE) : CGoal(Goals::TRADE)
{ {
resID = rid; resID = rid.getNum();
value = val; value = val;
objid = Objid; objid = Objid;
} }

View File

@ -23,7 +23,7 @@ using namespace Goals;
ArmyUpgrade::ArmyUpgrade(const AIPath & upgradePath, const CGObjectInstance * upgrader, const ArmyUpgradeInfo & upgrade) ArmyUpgrade::ArmyUpgrade(const AIPath & upgradePath, const CGObjectInstance * upgrader, const ArmyUpgradeInfo & upgrade)
: CGoal(Goals::ARMY_UPGRADE), upgrader(upgrader), upgradeValue(upgrade.upgradeValue), : CGoal(Goals::ARMY_UPGRADE), upgrader(upgrader), upgradeValue(upgrade.upgradeValue),
initialValue(upgradePath.heroArmy->getArmyStrength()), goldCost(upgrade.upgradeCost[Res::GOLD]) initialValue(upgradePath.heroArmy->getArmyStrength()), goldCost(upgrade.upgradeCost[EGameResID::GOLD])
{ {
sethero(upgradePath.targetHero); sethero(upgradePath.targetHero);
} }

View File

@ -350,7 +350,7 @@ HeroExchangeArmy * HeroExchangeMap::tryUpgrade(
{ {
auto targetSlot = target->getFreeSlot(); auto targetSlot = target->getFreeSlot();
target->addToSlot(targetSlot, slotInfo.creature->idNumber, TQuantity(slotInfo.count)); target->addToSlot(targetSlot, slotInfo.creature->getId(), TQuantity(slotInfo.count));
} }
resources -= upgradeInfo.upgradeCost; resources -= upgradeInfo.upgradeCost;
@ -372,10 +372,10 @@ HeroExchangeArmy * HeroExchangeMap::tryUpgrade(
for(auto & creatureToBuy : buyArmy) for(auto & creatureToBuy : buyArmy)
{ {
auto targetSlot = target->getSlotFor(creatureToBuy.cre); auto targetSlot = target->getSlotFor(dynamic_cast<const CCreature*>(creatureToBuy.cre));
target->addToSlot(targetSlot, creatureToBuy.creID, creatureToBuy.count); target->addToSlot(targetSlot, creatureToBuy.creID, creatureToBuy.count);
target->armyCost += creatureToBuy.cre->cost * creatureToBuy.count; target->armyCost += creatureToBuy.cre->getFullRecruitCost() * creatureToBuy.count;
target->requireBuyArmy = true; target->requireBuyArmy = true;
} }
} }
@ -399,7 +399,7 @@ HeroExchangeArmy * HeroExchangeMap::pickBestCreatures(const CCreatureSet * army1
{ {
auto targetSlot = target->getFreeSlot(); auto targetSlot = target->getFreeSlot();
target->addToSlot(targetSlot, slotInfo.creature->idNumber, TQuantity(slotInfo.count)); target->addToSlot(targetSlot, slotInfo.creature->getId(), TQuantity(slotInfo.count));
} }
return target; return target;
@ -420,7 +420,7 @@ DwellingActor::DwellingActor(const CGDwelling * dwelling, uint64_t chainMask, bo
{ {
for(auto & slot : creatureSet->Slots()) for(auto & slot : creatureSet->Slots())
{ {
armyCost += slot.second->getCreatureID().toCreature()->cost * slot.second->count; armyCost += slot.second->getCreatureID().toCreature()->getFullRecruitCost() * slot.second->count;
} }
} }
@ -454,7 +454,7 @@ CCreatureSet * DwellingActor::getDwellingCreatures(const CGDwelling * dwelling,
auto creature = creatureInfo.second.back().toCreature(); auto creature = creatureInfo.second.back().toCreature();
dwellingCreatures->addToSlot( dwellingCreatures->addToSlot(
dwellingCreatures->getSlotFor(creature), dwellingCreatures->getSlotFor(creature),
creature->idNumber, creature->getId(),
TQuantity(creatureInfo.first)); TQuantity(creatureInfo.first));
} }

View File

@ -95,7 +95,7 @@ BattleAction CStupidAI::activeStack( const CStack * stack )
ReachabilityInfo dists = cb->getReachability(stack); ReachabilityInfo dists = cb->getReachability(stack);
std::vector<EnemyInfo> enemiesShootable, enemiesReachable, enemiesUnreachable; std::vector<EnemyInfo> enemiesShootable, enemiesReachable, enemiesUnreachable;
if(stack->type->idNumber == CreatureID::CATAPULT) if(stack->type->getId() == CreatureID::CATAPULT)
{ {
BattleAction attack; BattleAction attack;
static const std::vector<int> wallHexes = {50, 183, 182, 130, 78, 29, 12, 95}; static const std::vector<int> wallHexes = {50, 183, 182, 130, 78, 29, 12, 95};

View File

@ -230,8 +230,8 @@ creInfo infoFromDC(const dwellingContent & dc)
ci.creID = dc.second.size() ? dc.second.back() : CreatureID(-1); //should never be accessed ci.creID = dc.second.size() ? dc.second.back() : CreatureID(-1); //should never be accessed
if (ci.creID != -1) if (ci.creID != -1)
{ {
ci.cre = VLC->creh->objects[ci.creID]; ci.cre = VLC->creatures()->getById(ci.creID);
ci.level = ci.cre->level; //this is cretaure tier, while tryRealize expects dwelling level. Ignore. ci.level = ci.cre->getLevel(); //this is creature tier, while tryRealize expects dwelling level. Ignore.
} }
else else
{ {

View File

@ -152,7 +152,7 @@ struct creInfo
{ {
int count; int count;
CreatureID creID; CreatureID creID;
CCreature * cre; const Creature * cre;
int level; int level;
}; };
creInfo infoFromDC(const dwellingContent & dc); creInfo infoFromDC(const dwellingContent & dc);

View File

@ -36,9 +36,10 @@ std::vector<SlotInfo> ArmyManager::getSortedSlots(const CCreatureSet * target, c
{ {
for(auto & i : armyPtr->Slots()) for(auto & i : armyPtr->Slots())
{ {
auto & slotInfp = creToPower[i.second->type]; auto cre = dynamic_cast<const CCreature*>(i.second->type);
auto & slotInfp = creToPower[cre];
slotInfp.creature = i.second->type; slotInfp.creature = cre;
slotInfp.power += i.second->getPower(); slotInfp.power += i.second->getPower();
slotInfp.count += i.second->count; slotInfp.count += i.second->count;
} }
@ -59,8 +60,8 @@ std::vector<SlotInfo>::iterator ArmyManager::getWeakestCreature(std::vector<Slot
{ {
auto weakest = boost::min_element(army, [](const SlotInfo & left, const SlotInfo & right) -> bool auto weakest = boost::min_element(army, [](const SlotInfo & left, const SlotInfo & right) -> bool
{ {
if(left.creature->level != right.creature->level) if(left.creature->getLevel() != right.creature->getLevel())
return left.creature->level < right.creature->level; return left.creature->getLevel() < right.creature->getLevel();
return left.creature->Speed() > right.creature->Speed(); return left.creature->Speed() > right.creature->Speed();
}); });
@ -120,7 +121,7 @@ ui64 ArmyManager::howManyReinforcementsCanBuy(const CCreatureSet * h, const CGDw
if(!ci.count || ci.creID == -1) if(!ci.count || ci.creID == -1)
continue; continue;
vstd::amin(ci.count, availableRes / ci.cre->cost); //max count we can afford vstd::amin(ci.count, availableRes / ci.cre->getFullRecruitCost()); //max count we can afford
if(ci.count && ci.creID != -1) //valid creature at this level if(ci.count && ci.creID != -1) //valid creature at this level
{ {
@ -135,8 +136,8 @@ ui64 ArmyManager::howManyReinforcementsCanBuy(const CCreatureSet * h, const CGDw
} }
//we found matching occupied or free slot //we found matching occupied or free slot
aivalue += ci.count * ci.cre->AIValue; aivalue += ci.count * ci.cre->getAIValue();
availableRes -= ci.cre->cost * ci.count; availableRes -= ci.cre->getFullRecruitCost() * ci.count;
} }
} }

View File

@ -64,13 +64,13 @@ armyStructure evaluateArmyStructure(const CArmedInstance * army)
for(auto s : army->Slots()) for(auto s : army->Slots())
{ {
bool walker = true; bool walker = true;
const CCreature * creature = s.second->type; auto bearer = s.second->getType()->getBonusBearer();
if(creature->hasBonus(selectorSHOOTER, keySHOOTER)) if(bearer->hasBonus(selectorSHOOTER, keySHOOTER))
{ {
shootersStrength += s.second->getPower(); shootersStrength += s.second->getPower();
walker = false; walker = false;
} }
if(creature->hasBonus(selectorFLYING, keyFLYING)) if(bearer->hasBonus(selectorFLYING, keyFLYING))
{ {
flyersStrength += s.second->getPower(); flyersStrength += s.second->getPower();
walker = false; walker = false;
@ -78,7 +78,7 @@ armyStructure evaluateArmyStructure(const CArmedInstance * army)
if(walker) if(walker)
walkersStrength += s.second->getPower(); walkersStrength += s.second->getPower();
vstd::amax(maxSpeed, creature->valOfBonuses(selectorSTACKS_SPEED, keySTACKS_SPEED)); vstd::amax(maxSpeed, bearer->valOfBonuses(selectorSTACKS_SPEED, keySTACKS_SPEED));
} }
armyStructure as; armyStructure as;
as.walkers = static_cast<float>(walkersStrength / totalStrength); as.walkers = static_cast<float>(walkersStrength / totalStrength);

View File

@ -35,7 +35,7 @@ TSubgoal BuyArmy::whatToDoToAchieve()
{ {
//TODO: calculate the actual cost of units instead //TODO: calculate the actual cost of units instead
TResources price; TResources price;
price[Res::GOLD] = static_cast<int>(value * 0.4f); //some approximate value price[EGameResID::GOLD] = static_cast<int>(value * 0.4f); //some approximate value
return ai->ah->whatToDo(price, iAmElementar()); //buy right now or gather resources return ai->ah->whatToDo(price, iAmElementar()); //buy right now or gather resources
} }

View File

@ -46,7 +46,7 @@ TGoalVec CollectRes::getAllPossibleSubgoals()
switch (obj->ID.num) switch (obj->ID.num)
{ {
case Obj::TREASURE_CHEST: case Obj::TREASURE_CHEST:
return resID == Res::GOLD; return resID == GameResID(EGameResID::GOLD);
break; break;
case Obj::RESOURCE: case Obj::RESOURCE:
return obj->subID == resID; return obj->subID == resID;
@ -59,24 +59,24 @@ TGoalVec CollectRes::getAllPossibleSubgoals()
return true; //contains all resources return true; //contains all resources
break; break;
case Obj::WINDMILL: case Obj::WINDMILL:
switch (resID) switch (GameResID(resID).toEnum())
{ {
case Res::GOLD: case EGameResID::GOLD:
case Res::WOOD: case EGameResID::WOOD:
return false; return false;
} }
break; break;
case Obj::WATER_WHEEL: case Obj::WATER_WHEEL:
if (resID != Res::GOLD) if (resID != GameResID(EGameResID::GOLD))
return false; return false;
break; break;
case Obj::MYSTICAL_GARDEN: case Obj::MYSTICAL_GARDEN:
if ((resID != Res::GOLD) && (resID != Res::GEMS)) if ((resID != GameResID(EGameResID::GOLD)) && (resID != GameResID(EGameResID::GEMS)))
return false; return false;
break; break;
case Obj::LEAN_TO: case Obj::LEAN_TO:
case Obj::WAGON: case Obj::WAGON:
if (resID != Res::GOLD) if (resID != GameResID(EGameResID::GOLD))
return false; return false;
break; break;
default: default:
@ -170,12 +170,12 @@ TSubgoal CollectRes::whatToDoToTrade()
const IMarket * m = markets.back(); const IMarket * m = markets.back();
//attempt trade at back (best prices) //attempt trade at back (best prices)
int howManyCanWeBuy = 0; int howManyCanWeBuy = 0;
for (Res::ERes i = Res::WOOD; i <= Res::GOLD; vstd::advance(i, 1)) for (auto i = EGameResID::WOOD; i <= EGameResID::GOLD; vstd::advance(i, 1))
{ {
if (i == resID) if (GameResID(i) == resID)
continue; continue;
int toGive = -1, toReceive = -1; int toGive = -1, toReceive = -1;
m->getOffer(i, resID, toGive, toReceive, EMarketMode::RESOURCE_RESOURCE); m->getOffer(GameResID(i), resID, toGive, toReceive, EMarketMode::RESOURCE_RESOURCE);
assert(toGive > 0 && toReceive > 0); assert(toGive > 0 && toReceive > 0);
howManyCanWeBuy += toReceive * (ai->ah->freeResources()[i] / toGive); howManyCanWeBuy += toReceive * (ai->ah->freeResources()[i] / toGive);
} }
@ -191,7 +191,7 @@ TSubgoal CollectRes::whatToDoToTrade()
} }
else //either it's our town, or we have hero there else //either it's our town, or we have hero there
{ {
return sptr(Trade(resID, value, objid).setisElementar(true)); //we can do this immediately return sptr(Trade(static_cast<EGameResID>(resID), value, objid).setisElementar(true)); //we can do this immediately
} }
} }
} }

View File

@ -24,10 +24,10 @@ namespace Goals
: CGoal(Goals::COLLECT_RES) : CGoal(Goals::COLLECT_RES)
{ {
} }
CollectRes(int rid, int val) CollectRes(GameResID rid, int val)
: CGoal(Goals::COLLECT_RES) : CGoal(Goals::COLLECT_RES)
{ {
resID = rid; resID = rid.getNum();
value = val; value = val;
priority = 2; priority = 2;
} }

View File

@ -172,7 +172,7 @@ TGoalVec CompleteQuest::missionArmy() const
for(auto creature : q.quest->m6creatures) for(auto creature : q.quest->m6creatures)
{ {
solutions.push_back(sptr(GatherTroops(creature.type->idNumber, creature.count))); solutions.push_back(sptr(GatherTroops(creature.type->getId(), creature.count)));
} }
return solutions; return solutions;
@ -235,7 +235,7 @@ TGoalVec CompleteQuest::missionResources() const
for(int i = 0; i < q.quest->m7resources.size(); ++i) for(int i = 0; i < q.quest->m7resources.size(); ++i)
{ {
if(q.quest->m7resources[i]) if(q.quest->m7resources[i])
solutions.push_back(sptr(CollectRes(i, q.quest->m7resources[i]))); solutions.push_back(sptr(CollectRes(static_cast<EGameResID>(i), q.quest->m7resources[i])));
} }
} }
} }

View File

@ -159,7 +159,7 @@ TGoalVec GatherArmy::getAllPossibleSubgoals()
for(auto & creatureID : creLevel.second) for(auto & creatureID : creLevel.second)
{ {
auto creature = VLC->creh->objects[creatureID]; auto creature = VLC->creh->objects[creatureID];
if(ai->ah->freeResources().canAfford(creature->cost)) if(ai->ah->freeResources().canAfford(creature->getFullRecruitCost()))
objs.push_back(obj); //TODO: reserve resources? objs.push_back(obj); //TODO: reserve resources?
} }
} }

View File

@ -93,21 +93,21 @@ TGoalVec GatherTroops::getAllPossibleSubgoals()
continue; continue;
} }
auto creature = VLC->creh->objects[objid]; auto creature = VLC->creatures()->getByIndex(objid);
if(t->subID == creature->faction) //TODO: how to force AI to build unupgraded creatures? :O if(t->subID == creature->getFactionIndex()) //TODO: how to force AI to build unupgraded creatures? :O
{ {
auto creatures = vstd::tryAt(t->town->creatures, creature->level - 1); auto creatures = vstd::tryAt(t->town->creatures, creature->getLevel() - 1);
if(!creatures) if(!creatures)
continue; continue;
int upgradeNumber = vstd::find_pos(*creatures, creature->idNumber); int upgradeNumber = vstd::find_pos(*creatures, creature->getId());
if(upgradeNumber < 0) if(upgradeNumber < 0)
continue; continue;
BuildingID bid(BuildingID::DWELL_FIRST + creature->level - 1 + upgradeNumber * GameConstants::CREATURES_PER_TOWN); BuildingID bid(BuildingID::DWELL_FIRST + creature->getLevel() - 1 + upgradeNumber * GameConstants::CREATURES_PER_TOWN);
if(t->hasBuilt(bid) && ai->ah->freeResources().canAfford(creature->cost)) //this assumes only creatures with dwellings are assigned to faction if(t->hasBuilt(bid) && ai->ah->freeResources().canAfford(creature->getFullRecruitCost())) //this assumes only creatures with dwellings are assigned to faction
{ {
solutions.push_back(sptr(BuyArmy(t, creature->AIValue * this->value).setobjid(objid))); solutions.push_back(sptr(BuyArmy(t, creature->getAIValue() * this->value).setobjid(objid)));
} }
/*else //disable random building requests for now - this code needs to know a lot of town/resource context to do more good than harm /*else //disable random building requests for now - this code needs to know a lot of town/resource context to do more good than harm
{ {
@ -129,7 +129,7 @@ TGoalVec GatherTroops::getAllPossibleSubgoals()
{ {
for(auto type : creature.second) for(auto type : creature.second)
{ {
if(type == objid && ai->ah->freeResources().canAfford(VLC->creh->objects[type]->cost)) if(type == objid && ai->ah->freeResources().canAfford(VLC->creatures()->getById(type)->getFullRecruitCost()))
vstd::concatenate(solutions, ai->ah->howToVisitObj(obj)); vstd::concatenate(solutions, ai->ah->howToVisitObj(obj));
} }
} }

View File

@ -33,6 +33,6 @@ TSubgoal RecruitHero::whatToDoToAchieve()
return sptr(BuildThis(BuildingID::TAVERN).setpriority(2)); return sptr(BuildThis(BuildingID::TAVERN).setpriority(2));
TResources res; TResources res;
res[Res::GOLD] = GameConstants::HERO_GOLD_COST; res[EGameResID::GOLD] = GameConstants::HERO_GOLD_COST;
return ai->ah->whatToDo(res, iAmElementar()); //either buy immediately, or collect res return ai->ah->whatToDo(res, iAmElementar()); //either buy immediately, or collect res
} }

View File

@ -24,10 +24,10 @@ namespace Goals
: CGoal(Goals::TRADE) : CGoal(Goals::TRADE)
{ {
} }
Trade(int rid, int val, int Objid) Trade(GameResID rid, int val, int Objid)
: CGoal(Goals::TRADE) : CGoal(Goals::TRADE)
{ {
resID = rid; resID = rid.getNum();
value = val; value = val;
objid = Objid; objid = Objid;
priority = 3; //trading is instant, but picking resources is free priority = 3; //trading is instant, but picking resources is free

View File

@ -154,7 +154,7 @@ TSubgoal Win::whatToDoToAchieve()
case EventCondition::HAVE_RESOURCES: case EventCondition::HAVE_RESOURCES:
//TODO mines? piles? marketplace? //TODO mines? piles? marketplace?
//save? //save?
return sptr(CollectRes(static_cast<Res::ERes>(goal.objectType), goal.value)); return sptr(CollectRes(static_cast<EGameResID>(goal.objectType), goal.value));
case EventCondition::HAVE_CREATURES: case EventCondition::HAVE_CREATURES:
return sptr(GatherTroops(goal.objectType, goal.value)); return sptr(GatherTroops(goal.objectType, goal.value));
case EventCondition::TRANSPORT: case EventCondition::TRANSPORT:

View File

@ -73,8 +73,8 @@ boost::optional<int> MapObjectsEvaluator::getObjectValue(const CGObjectInstance
{ {
for(auto & creatureID : creLevel.second) for(auto & creatureID : creLevel.second)
{ {
auto creature = VLC->creh->objects[creatureID]; auto creature = VLC->creatures()->getById(creatureID);
aiValue += (creature->AIValue * creature->growth); aiValue += (creature->getAIValue() * creature->getGrowth());
} }
} }
return aiValue; return aiValue;

View File

@ -58,15 +58,15 @@ TResources ResourceManager::estimateIncome() const
{ {
if (obj->ID == Obj::MINE) if (obj->ID == Obj::MINE)
{ {
switch (obj->subID) auto mine = dynamic_cast<const CGMine*>(obj);
switch (mine->producedResource.toEnum())
{ {
case Res::WOOD: case EGameResID::WOOD:
case Res::ORE: case EGameResID::ORE:
ret[obj->subID] += WOOD_ORE_MINE_PRODUCTION; ret[obj->subID] += WOOD_ORE_MINE_PRODUCTION;
break; break;
case Res::GOLD: case EGameResID::GOLD:
case 7: //abandoned mine -> also gold ret[EGameResID::GOLD] += GOLD_MINE_PRODUCTION;
ret[Res::GOLD] += GOLD_MINE_PRODUCTION;
break; break;
default: default:
ret[obj->subID] += RESOURCE_MINE_PRODUCTION; ret[obj->subID] += RESOURCE_MINE_PRODUCTION;
@ -90,11 +90,11 @@ Goals::TSubgoal ResourceManager::collectResourcesForOurGoal(ResourceObjective &o
{ {
auto allResources = cb->getResourceAmount(); auto allResources = cb->getResourceAmount();
auto income = estimateIncome(); auto income = estimateIncome();
Res::ERes resourceType = Res::INVALID; GameResID resourceType = EGameResID::INVALID;
TResource amountToCollect = 0; TResource amountToCollect = 0;
typedef std::pair<Res::ERes, TResource> resPair; using resPair = std::pair<GameResID, TResource>;
std::map<Res::ERes, TResource> missingResources; std::map<GameResID, TResource> missingResources;
//TODO: unit test for complex resource sets //TODO: unit test for complex resource sets
@ -102,10 +102,10 @@ Goals::TSubgoal ResourceManager::collectResourcesForOurGoal(ResourceObjective &o
for (auto it = queue.ordered_begin(); it != queue.ordered_end(); it++) for (auto it = queue.ordered_begin(); it != queue.ordered_end(); it++)
{ {
//choose specific resources we need for this goal (not 0) //choose specific resources we need for this goal (not 0)
for (auto r = Res::ResourceSet::nziterator(o.resources); r.valid(); r++) for (auto r = ResourceSet::nziterator(o.resources); r.valid(); r++)
missingResources[r->resType] += it->resources[r->resType]; //goal it costs r units of resType missingResources[r->resType] += it->resources[r->resType]; //goal it costs r units of resType
} }
for (auto it = Res::ResourceSet::nziterator(o.resources); it.valid(); it++) for (auto it = ResourceSet::nziterator(o.resources); it.valid(); it++)
{ {
missingResources[it->resType] -= allResources[it->resType]; //missing = (what we need) - (what we have) missingResources[it->resType] -= allResources[it->resType]; //missing = (what we need) - (what we have)
vstd::amax(missingResources[it->resType], 0); // if we have more resources than reserved, we don't need them vstd::amax(missingResources[it->resType], 0); // if we have more resources than reserved, we don't need them
@ -129,11 +129,11 @@ Goals::TSubgoal ResourceManager::collectResourcesForOurGoal(ResourceObjective &o
break; break;
} }
} }
if (resourceType == Res::INVALID) //no needed resources has 0 income, if (resourceType == EGameResID::INVALID) //no needed resources has 0 income,
{ {
//find the one which takes longest to collect //find the one which takes longest to collect
typedef std::pair<Res::ERes, float> timePair; using timePair = std::pair<GameResID, float>;
std::map<Res::ERes, float> daysToEarn; std::map<GameResID, float> daysToEarn;
for (auto it : missingResources) for (auto it : missingResources)
daysToEarn[it.first] = (float)missingResources[it.first] / income[it.first]; daysToEarn[it.first] = (float)missingResources[it.first] / income[it.first];
auto incomeComparer = [](const timePair & lhs, const timePair & rhs) -> bool auto incomeComparer = [](const timePair & lhs, const timePair & rhs) -> bool
@ -345,7 +345,7 @@ TResources ResourceManager::freeResources() const
TResource ResourceManager::freeGold() const TResource ResourceManager::freeGold() const
{ {
return freeResources()[Res::GOLD]; return freeResources()[EGameResID::GOLD];
} }
TResources ResourceManager::allResources() const TResources ResourceManager::allResources() const
@ -355,5 +355,5 @@ TResources ResourceManager::allResources() const
TResource ResourceManager::allGold() const TResource ResourceManager::allGold() const
{ {
return cb->getResourceAmount()[Res::GOLD]; return cb->getResourceAmount()[EGameResID::GOLD];
} }

View File

@ -1235,7 +1235,7 @@ void VCAI::recruitCreatures(const CGDwelling * d, const CArmedInstance * recruit
int count = d->creatures[i].first; int count = d->creatures[i].first;
CreatureID creID = d->creatures[i].second.back(); CreatureID creID = d->creatures[i].second.back();
vstd::amin(count, ah->freeResources() / VLC->creh->objects[creID]->cost); vstd::amin(count, ah->freeResources() / VLC->creatures()->getById(creID)->getFullRecruitCost());
if(count > 0) if(count > 0)
cb->recruitCreatures(d, recruiter, creID, count, i); cb->recruitCreatures(d, recruiter, creID, count, i);
} }
@ -1314,7 +1314,7 @@ bool VCAI::canRecruitAnyHero(const CGTownInstance * t) const
t = findTownWithTavern(); t = findTownWithTavern();
if(!t) if(!t)
return false; return false;
if(cb->getResourceAmount(Res::GOLD) < GameConstants::HERO_GOLD_COST) //TODO: use ResourceManager if(cb->getResourceAmount(EGameResID::GOLD) < GameConstants::HERO_GOLD_COST) //TODO: use ResourceManager
return false; return false;
if(cb->getHeroesInfo().size() >= ALLOWED_ROAMING_HEROES) if(cb->getHeroesInfo().size() >= ALLOWED_ROAMING_HEROES)
return false; return false;
@ -1434,7 +1434,7 @@ void VCAI::wander(HeroPtr h)
} }
break; break;
} }
else if(cb->getResourceAmount(Res::GOLD) >= GameConstants::HERO_GOLD_COST) else if(cb->getResourceAmount(EGameResID::GOLD) >= GameConstants::HERO_GOLD_COST)
{ {
std::vector<const CGTownInstance *> towns = cb->getTownsInfo(); std::vector<const CGTownInstance *> towns = cb->getTownsInfo();
vstd::erase_if(towns, [&](const CGTownInstance * t) -> bool vstd::erase_if(towns, [&](const CGTownInstance * t) -> bool
@ -2117,10 +2117,10 @@ void VCAI::tryRealize(Goals::Trade & g) //trade
if(const IMarket * m = IMarket::castFrom(obj, false)) if(const IMarket * m = IMarket::castFrom(obj, false))
{ {
auto freeRes = ah->freeResources(); //trade only resources which are not reserved auto freeRes = ah->freeResources(); //trade only resources which are not reserved
for(auto it = Res::ResourceSet::nziterator(freeRes); it.valid(); it++) for(auto it = ResourceSet::nziterator(freeRes); it.valid(); it++)
{ {
auto res = it->resType; auto res = it->resType;
if(res == g.resID) //sell any other resource if(res.getNum() == g.resID) //sell any other resource
continue; continue;
int toGive, toGet; int toGive, toGet;
@ -2174,7 +2174,7 @@ void VCAI::tryRealize(Goals::BuyArmy & g)
|| t->getUpperArmy()->getSlotFor(ci.creID) == SlotID()) || t->getUpperArmy()->getSlotFor(ci.creID) == SlotID())
continue; continue;
vstd::amin(ci.count, res / ci.cre->cost); //max count we can afford vstd::amin(ci.count, res / ci.cre->getFullRecruitCost()); //max count we can afford
if(!ci.count) if(!ci.count)
continue; continue;
@ -2190,15 +2190,15 @@ void VCAI::tryRealize(Goals::BuyArmy & g)
*boost::max_element(creaturesInDwellings, [](const creInfo & lhs, const creInfo & rhs) *boost::max_element(creaturesInDwellings, [](const creInfo & lhs, const creInfo & rhs)
{ {
//max value of creatures we can buy with our res //max value of creatures we can buy with our res
int value1 = lhs.cre->AIValue * lhs.count, int value1 = lhs.cre->getAIValue() * lhs.count,
value2 = rhs.cre->AIValue * rhs.count; value2 = rhs.cre->getAIValue() * rhs.count;
return value1 < value2; return value1 < value2;
}); });
cb->recruitCreatures(t, t->getUpperArmy(), ci.creID, ci.count, ci.level); cb->recruitCreatures(t, t->getUpperArmy(), ci.creID, ci.count, ci.level);
valueBought += ci.count * ci.cre->AIValue; valueBought += ci.count * ci.cre->getAIValue();
} }
throw goalFulfilledException(sptr(g)); //we bought as many creatures as we wanted throw goalFulfilledException(sptr(g)); //we bought as many creatures as we wanted
@ -2820,7 +2820,7 @@ bool shouldVisit(HeroPtr h, const CGObjectInstance * obj)
{ {
for(auto slot : h->Slots()) for(auto slot : h->Slots())
{ {
if(slot.second->type->upgrades.size()) if(slot.second->type->hasUpgrades())
return true; //TODO: check price? return true; //TODO: check price?
} }
return false; return false;
@ -2844,7 +2844,7 @@ bool shouldVisit(HeroPtr h, const CGObjectInstance * obj)
case Obj::TREE_OF_KNOWLEDGE: case Obj::TREE_OF_KNOWLEDGE:
{ {
TResources myRes = ai->ah->freeResources(); TResources myRes = ai->ah->freeResources();
if(myRes[Res::GOLD] < 2000 || myRes[Res::GEMS] < 10) if(myRes[EGameResID::GOLD] < 2000 || myRes[EGameResID::GEMS] < 10)
return false; return false;
break; break;
} }

View File

@ -279,7 +279,7 @@ template<typename T, size_t N> char (&_ArrayCountObj(const T (&)[N]))[N];
#define VCMI_LIB_NAMESPACE_BEGIN #define VCMI_LIB_NAMESPACE_BEGIN
#define VCMI_LIB_NAMESPACE_END #define VCMI_LIB_NAMESPACE_END
#define VCMI_LIB_USING_NAMESPACE #define VCMI_LIB_USING_NAMESPACE
#define VCMI_LIB_WRAP_NAMESPACE(x) x #define VCMI_LIB_WRAP_NAMESPACE(x) ::x
#endif #endif
/* ---------------------------------------------------------------------------- */ /* ---------------------------------------------------------------------------- */

View File

@ -195,7 +195,7 @@ public:
void showGarrisonDialog(ObjectInstanceID upobj, ObjectInstanceID hid, bool removableUnits) override {}; void showGarrisonDialog(ObjectInstanceID upobj, ObjectInstanceID hid, bool removableUnits) override {};
void showTeleportDialog(TeleportDialog * iw) override {}; void showTeleportDialog(TeleportDialog * iw) override {};
void showThievesGuildWindow(PlayerColor player, ObjectInstanceID requestingObjId) override {}; void showThievesGuildWindow(PlayerColor player, ObjectInstanceID requestingObjId) override {};
void giveResource(PlayerColor player, Res::ERes which, int val) override {}; void giveResource(PlayerColor player, GameResID which, int val) override {};
virtual void giveResources(PlayerColor player, TResources resources) override {}; virtual void giveResources(PlayerColor player, TResources resources) override {};
void giveCreatures(const CArmedInstance * objid, const CGHeroInstance * h, const CCreatureSet & creatures, bool remove) override {}; void giveCreatures(const CArmedInstance * objid, const CGHeroInstance * h, const CCreatureSet & creatures, bool remove) override {};

View File

@ -80,7 +80,7 @@ std::string CResDataBar::buildDateString()
void CResDataBar::draw(SDL_Surface * to) void CResDataBar::draw(SDL_Surface * to)
{ {
//TODO: all this should be labels, but they require proper text update on change //TODO: all this should be labels, but they require proper text update on change
for (auto i=Res::WOOD; i<=Res::GOLD; vstd::advance(i, 1)) for (auto i=GameResID(EGameResID::WOOD); i <= GameResID(EGameResID::GOLD); vstd::advance(i, 1))
{ {
std::string text = std::to_string(LOCPLINT->cb->getResourceAmount(i)); std::string text = std::to_string(LOCPLINT->cb->getResourceAmount(i));

View File

@ -158,7 +158,7 @@ ECreatureAnimType AttackAnimation::findValidGroup( const std::vector<ECreatureAn
const CCreature * AttackAnimation::getCreature() const const CCreature * AttackAnimation::getCreature() const
{ {
if (attackingStack->getCreature()->idNumber == CreatureID::ARROW_TOWERS) if (attackingStack->getCreature()->getId() == CreatureID::ARROW_TOWERS)
return owner.siegeController->getTurretCreature(); return owner.siegeController->getTurretCreature();
else else
return attackingStack->getCreature(); return attackingStack->getCreature();

View File

@ -453,7 +453,7 @@ BattleResultWindow::BattleResultWindow(const BattleResult & br, CPlayerInterface
auto best = vstd::maxElementByFun(stacks, [](const CStack * stack) auto best = vstd::maxElementByFun(stacks, [](const CStack * stack)
{ {
return stack->type->AIValue; return stack->type->getAIValue();
}); });
if(best != stacks.end()) //should be always but to be safe... if(best != stacks.end()) //should be always but to be safe...
@ -715,7 +715,7 @@ void StackQueue::StackBox::setUnit(const battle::Unit * unit, size_t turn)
// if mod is not up to date and does have arrow tower icon yet - second setFrame call will fail and retain previously set image // if mod is not up to date and does have arrow tower icon yet - second setFrame call will fail and retain previously set image
// for 1.2 release & later next line should be moved into 'else' block // for 1.2 release & later next line should be moved into 'else' block
icon->setFrame(unit->creatureIconIndex(), 0); icon->setFrame(unit->creatureIconIndex(), 0);
if (unit->unitType()->idNumber == CreatureID::ARROW_TOWERS) if (unit->unitType()->getId() == CreatureID::ARROW_TOWERS)
icon->setFrame(owner->getSiegeShooterIconID(), 1); icon->setFrame(owner->getSiegeShooterIconID(), 1);
amount->setText(TextOperations::formatMetric(unit->getCount(), 4)); amount->setText(TextOperations::formatMetric(unit->getCount(), 4));

View File

@ -148,7 +148,7 @@ const CCreature & BattleProjectileController::getShooter(const CStack * stack) c
{ {
const CCreature * creature = stack->getCreature(); const CCreature * creature = stack->getCreature();
if(creature->idNumber == CreatureID::ARROW_TOWERS) if(creature->getId() == CreatureID::ARROW_TOWERS)
creature = owner.siegeController->getTurretCreature(); creature = owner.siegeController->getTurretCreature();
if(creature->animation.missleFrameAngles.empty()) if(creature->animation.missleFrameAngles.empty())

View File

@ -200,7 +200,7 @@ void BattleStacksController::stackAdded(const CStack * stack, bool instant)
stackAnimation[stack->ID]->pos.w = stackAnimation[stack->ID]->getWidth(); stackAnimation[stack->ID]->pos.w = stackAnimation[stack->ID]->getWidth();
// FIXME: workaround for visible animation of Medusa tails (animation disabled in H3) // FIXME: workaround for visible animation of Medusa tails (animation disabled in H3)
if (turretCreature->idNumber == CreatureID::MEDUSA ) if (turretCreature->getId() == CreatureID::MEDUSA )
stackAnimation[stack->ID]->pos.w = 250; stackAnimation[stack->ID]->pos.w = 250;
coords = owner.siegeController->getTurretCreaturePosition(stack->initialPosition); coords = owner.siegeController->getTurretCreaturePosition(stack->initialPosition);

View File

@ -309,7 +309,7 @@ void BattleWindow::reallyFlee()
void BattleWindow::reallySurrender() void BattleWindow::reallySurrender()
{ {
if (owner.curInt->cb->getResourceAmount(Res::GOLD) < owner.curInt->cb->battleGetSurrenderCost()) if (owner.curInt->cb->getResourceAmount(EGameResID::GOLD) < owner.curInt->cb->battleGetSurrenderCost())
{ {
owner.curInt->showInfoDialog(CGI->generaltexth->allTexts[29]); //You don't have enough gold! owner.curInt->showInfoDialog(CGI->generaltexth->allTexts[29]); //You don't have enough gold!
} }

View File

@ -126,25 +126,25 @@ size_t OptionsTab::CPlayerSettingsHelper::getImageIndex()
return GOLD; return GOLD;
case PlayerSettings::RESOURCE: case PlayerSettings::RESOURCE:
{ {
switch((*CGI->townh)[factionIndex]->town->primaryRes) switch((*CGI->townh)[factionIndex]->town->primaryRes.toEnum())
{ {
case Res::WOOD_AND_ORE: case EGameResID::WOOD_AND_ORE:
return WOOD_ORE; return WOOD_ORE;
case Res::WOOD: case EGameResID::WOOD:
return WOOD; return WOOD;
case Res::MERCURY: case EGameResID::MERCURY:
return MERCURY; return MERCURY;
case Res::ORE: case EGameResID::ORE:
return ORE; return ORE;
case Res::SULFUR: case EGameResID::SULFUR:
return SULFUR; return SULFUR;
case Res::CRYSTAL: case EGameResID::CRYSTAL:
return CRYSTAL; return CRYSTAL;
case Res::GEMS: case EGameResID::GEMS:
return GEM; return GEM;
case Res::GOLD: case EGameResID::GOLD:
return GOLD; return GOLD;
case Res::MITHRIL: case EGameResID::MITHRIL:
return MITHRIL; return MITHRIL;
} }
} }
@ -268,17 +268,17 @@ std::string OptionsTab::CPlayerSettingsHelper::getSubtitle()
return CGI->generaltexth->allTexts[87]; //500-1000 return CGI->generaltexth->allTexts[87]; //500-1000
case PlayerSettings::RESOURCE: case PlayerSettings::RESOURCE:
{ {
switch((*CGI->townh)[factionIndex]->town->primaryRes) switch((*CGI->townh)[factionIndex]->town->primaryRes.toEnum())
{ {
case Res::MERCURY: case EGameResID::MERCURY:
return CGI->generaltexth->allTexts[694]; return CGI->generaltexth->allTexts[694];
case Res::SULFUR: case EGameResID::SULFUR:
return CGI->generaltexth->allTexts[695]; return CGI->generaltexth->allTexts[695];
case Res::CRYSTAL: case EGameResID::CRYSTAL:
return CGI->generaltexth->allTexts[692]; return CGI->generaltexth->allTexts[692];
case Res::GEMS: case EGameResID::GEMS:
return CGI->generaltexth->allTexts[693]; return CGI->generaltexth->allTexts[693];
case Res::WOOD_AND_ORE: case EGameResID::WOOD_AND_ORE:
return CGI->generaltexth->allTexts[89]; //At the start of the game, 5-10 wood and 5-10 ore are added to your Kingdom's resource pool return CGI->generaltexth->allTexts[89]; //At the start of the game, 5-10 wood and 5-10 ore are added to your Kingdom's resource pool
} }
} }
@ -310,17 +310,17 @@ std::string OptionsTab::CPlayerSettingsHelper::getDescription()
return CGI->generaltexth->allTexts[92]; //At the start of the game, 500-1000 gold is added to your Kingdom's resource pool return CGI->generaltexth->allTexts[92]; //At the start of the game, 500-1000 gold is added to your Kingdom's resource pool
case PlayerSettings::RESOURCE: case PlayerSettings::RESOURCE:
{ {
switch((*CGI->townh)[factionIndex]->town->primaryRes) switch((*CGI->townh)[factionIndex]->town->primaryRes.toEnum())
{ {
case Res::MERCURY: case EGameResID::MERCURY:
return CGI->generaltexth->allTexts[690]; return CGI->generaltexth->allTexts[690];
case Res::SULFUR: case EGameResID::SULFUR:
return CGI->generaltexth->allTexts[691]; return CGI->generaltexth->allTexts[691];
case Res::CRYSTAL: case EGameResID::CRYSTAL:
return CGI->generaltexth->allTexts[688]; return CGI->generaltexth->allTexts[688];
case Res::GEMS: case EGameResID::GEMS:
return CGI->generaltexth->allTexts[689]; return CGI->generaltexth->allTexts[689];
case Res::WOOD_AND_ORE: case EGameResID::WOOD_AND_ORE:
return CGI->generaltexth->allTexts[93]; //At the start of the game, 5-10 wood and 5-10 ore are added to your Kingdom's resource pool return CGI->generaltexth->allTexts[93]; //At the start of the game, 5-10 wood and 5-10 ore are added to your Kingdom's resource pool
} }
} }

View File

@ -26,5 +26,5 @@ private:
using ImagePtr = std::shared_ptr<CAnimImage>; using ImagePtr = std::shared_ptr<CAnimImage>;
LabelPtr title; LabelPtr title;
std::map<int, std::pair<LabelPtr, ImagePtr>> resources; std::map<GameResID, std::pair<LabelPtr, ImagePtr>> resources;
}; };

View File

@ -200,11 +200,11 @@ void CMinorResDataBar::showAll(SDL_Surface * to)
{ {
CIntObject::showAll(to); CIntObject::showAll(to);
for (Res::ERes i=Res::WOOD; i<=Res::GOLD; vstd::advance(i, 1)) for (EGameResID i=EGameResID::WOOD; i<=EGameResID::GOLD; vstd::advance(i, 1))
{ {
std::string text = std::to_string(LOCPLINT->cb->getResourceAmount(i)); std::string text = std::to_string(LOCPLINT->cb->getResourceAmount(i));
graphics->fonts[FONT_SMALL]->renderTextCenter(to, text, Colors::WHITE, Point(pos.x + 50 + 76 * i, pos.y + pos.h/2)); graphics->fonts[FONT_SMALL]->renderTextCenter(to, text, Colors::WHITE, Point(pos.x + 50 + 76 * GameResID(i), pos.y + pos.h/2));
} }
graphics->fonts[FONT_SMALL]->renderTextCenter(to, buildDateString(), Colors::WHITE, Point(pos.x+545+(pos.w-545)/2,pos.y+pos.h/2)); graphics->fonts[FONT_SMALL]->renderTextCenter(to, buildDateString(), Colors::WHITE, Point(pos.x+545+(pos.w-545)/2,pos.y+pos.h/2));
} }
@ -347,10 +347,10 @@ void CTownTooltip::init(const InfoAboutTown & town)
if(town.details->customRes)//silo is built if(town.details->customRes)//silo is built
{ {
if(town.tType->primaryRes == Res::WOOD_AND_ORE )// wood & ore if(town.tType->primaryRes == EGameResID::WOOD_AND_ORE )// wood & ore
{ {
res1 = std::make_shared<CAnimImage>("SMALRES", Res::WOOD, 0, 7, 75); res1 = std::make_shared<CAnimImage>("SMALRES", GameResID(EGameResID::WOOD), 0, 7, 75);
res2 = std::make_shared<CAnimImage>("SMALRES", Res::ORE , 0, 7, 88); res2 = std::make_shared<CAnimImage>("SMALRES", GameResID(EGameResID::ORE), 0, 7, 88);
} }
else else
{ {
@ -448,7 +448,7 @@ CCreaturePic::CCreaturePic(int x, int y, const CCreature * cre, bool Big, bool A
pos.x+=x; pos.x+=x;
pos.y+=y; pos.y+=y;
TFaction faction = cre->faction; TFaction faction = cre->getFactionIndex();
assert(CGI->townh->size() > faction); assert(CGI->townh->size() > faction);

View File

@ -292,10 +292,11 @@ CDwellingInfoBox::CDwellingInfoBox(int centerX, int centerY, const CGTownInstanc
for(int i = 0; i<GameConstants::RESOURCE_QUANTITY; i++) for(int i = 0; i<GameConstants::RESOURCE_QUANTITY; i++)
{ {
if(creature->cost[i]) auto res = static_cast<EGameResID>(i);
if(creature->getRecruitCost(res))
{ {
resPicture.push_back(std::make_shared<CAnimImage>("RESOURCE", i, 0, 0, 0)); resPicture.push_back(std::make_shared<CAnimImage>("RESOURCE", i, 0, 0, 0));
resAmount.push_back(std::make_shared<CLabel>(0,0, FONT_SMALL, ETextAlignment::CENTER, Colors::WHITE, std::to_string(creature->cost[i]))); resAmount.push_back(std::make_shared<CLabel>(0,0, FONT_SMALL, ETextAlignment::CENTER, Colors::WHITE, std::to_string(creature->getRecruitCost(res))));
} }
} }
@ -810,7 +811,7 @@ void CCastleBuildings::enterBlacksmith(ArtifactID artifactID)
auto art = artifactID.toArtifact(); auto art = artifactID.toArtifact();
int price = art->getPrice(); int price = art->getPrice();
bool possible = LOCPLINT->cb->getResourceAmount(Res::GOLD) >= price; bool possible = LOCPLINT->cb->getResourceAmount(EGameResID::GOLD) >= price;
if(possible) if(possible)
{ {
for(auto slot : art->possibleSlots.at(ArtBearer::HERO)) for(auto slot : art->possibleSlots.at(ArtBearer::HERO))
@ -942,7 +943,7 @@ void CCastleBuildings::enterMagesGuild()
// "Yog has given up magic in all its forms..." // "Yog has given up magic in all its forms..."
LOCPLINT->showInfoDialog(CGI->generaltexth->allTexts[736]); LOCPLINT->showInfoDialog(CGI->generaltexth->allTexts[736]);
} }
else if(LOCPLINT->cb->getResourceAmount(Res::GOLD) < 500) //not enough gold to buy spellbook else if(LOCPLINT->cb->getResourceAmount(EGameResID::GOLD) < 500) //not enough gold to buy spellbook
{ {
openMagesGuild(); openMagesGuild();
LOCPLINT->showInfoDialog(CGI->generaltexth->allTexts[213]); LOCPLINT->showInfoDialog(CGI->generaltexth->allTexts[213]);
@ -1100,7 +1101,7 @@ void CCreaInfo::clickRight(tribool down, bool previousState)
if (showAvailable) if (showAvailable)
GH.pushIntT<CDwellingInfoBox>(GH.screenDimensions().x / 2, GH.screenDimensions().y / 2, town, level); GH.pushIntT<CDwellingInfoBox>(GH.screenDimensions().x / 2, GH.screenDimensions().y / 2, town, level);
else else
CRClickPopup::createAndPush(genGrowthText(), std::make_shared<CComponent>(CComponent::creature, creature->idNumber)); CRClickPopup::createAndPush(genGrowthText(), std::make_shared<CComponent>(CComponent::creature, creature->getId()));
} }
} }
@ -1279,7 +1280,7 @@ void CCastleInterface::recreateIcons()
icon->setFrame(iconIndex); icon->setFrame(iconIndex);
TResources townIncome = town->dailyIncome(); TResources townIncome = town->dailyIncome();
income->setText(std::to_string(townIncome[Res::GOLD])); income->setText(std::to_string(townIncome[EGameResID::GOLD]));
hall = std::make_shared<CTownInfo>(80, 413, town, true); hall = std::make_shared<CTownInfo>(80, 413, town, true);
fort = std::make_shared<CTownInfo>(122, 413, town, false); fort = std::make_shared<CTownInfo>(122, 413, town, false);
@ -1870,5 +1871,5 @@ CBlacksmithDialog::CBlacksmithDialog(bool possible, CreatureID creMachineID, Art
else else
buy->block(true); buy->block(true);
costIcon = std::make_shared<CAnimImage>("RESOURCE", Res::GOLD, 0, 148, 244); costIcon = std::make_shared<CAnimImage>("RESOURCE", GameResID(EGameResID::GOLD), 0, 148, 244);
} }

View File

@ -323,7 +323,7 @@ CStackWindow::ButtonsSection::ButtonsSection(CStackWindow * owner, int yOffset)
}; };
auto upgradeBtn = std::make_shared<CButton>(Point(221 + (int)buttonIndex * 40, 5), "stackWindow/upgradeButton", CGI->generaltexth->zelp[446], onClick, SDLK_1); auto upgradeBtn = std::make_shared<CButton>(Point(221 + (int)buttonIndex * 40, 5), "stackWindow/upgradeButton", CGI->generaltexth->zelp[446], onClick, SDLK_1);
upgradeBtn->addOverlay(std::make_shared<CAnimImage>("CPRSMALL", VLC->creh->objects[upgradeInfo.info.newID[buttonIndex]]->iconIndex)); upgradeBtn->addOverlay(std::make_shared<CAnimImage>("CPRSMALL", VLC->creh->objects[upgradeInfo.info.newID[buttonIndex]]->getIconIndex()));
if(buttonsToCreate == 1) // single upgrade avaialbe if(buttonsToCreate == 1) // single upgrade avaialbe
{ {
@ -844,7 +844,7 @@ std::string CStackWindow::generateStackExpDescription()
const CStackInstance * stack = info->stackNode; const CStackInstance * stack = info->stackNode;
const CCreature * creature = info->creature; const CCreature * creature = info->creature;
int tier = stack->type->level; int tier = stack->type->getLevel();
int rank = stack->getExpRank(); int rank = stack->getExpRank();
if (!vstd::iswithin(tier, 1, 7)) if (!vstd::iswithin(tier, 1, 7))
tier = 0; tier = 0;

View File

@ -564,7 +564,7 @@ std::shared_ptr<CIntObject> CKingdomInterface::createMainTab(size_t index)
void CKingdomInterface::generateMinesList(const std::vector<const CGObjectInstance *> & ownedObjects) void CKingdomInterface::generateMinesList(const std::vector<const CGObjectInstance *> & ownedObjects)
{ {
ui32 footerPos = conf.go()->ac.overviewSize * 116; ui32 footerPos = conf.go()->ac.overviewSize * 116;
std::vector<int> minesCount(GameConstants::RESOURCE_QUANTITY, 0); TResources minesCount(GameConstants::RESOURCE_QUANTITY, 0);
int totalIncome=0; int totalIncome=0;
for(const CGObjectInstance * object : ownedObjects) for(const CGObjectInstance * object : ownedObjects)
@ -576,7 +576,7 @@ void CKingdomInterface::generateMinesList(const std::vector<const CGObjectInstan
assert(mine); assert(mine);
minesCount[mine->producedResource]++; minesCount[mine->producedResource]++;
if (mine->producedResource == Res::GOLD) if (mine->producedResource == EGameResID::GOLD)
totalIncome += mine->producedQuantity; totalIncome += mine->producedQuantity;
} }
} }
@ -585,14 +585,14 @@ void CKingdomInterface::generateMinesList(const std::vector<const CGObjectInstan
std::vector<const CGHeroInstance*> heroes = LOCPLINT->cb->getHeroesInfo(true); std::vector<const CGHeroInstance*> heroes = LOCPLINT->cb->getHeroesInfo(true);
for(auto & heroe : heroes) for(auto & heroe : heroes)
{ {
totalIncome += heroe->valOfBonuses(Selector::typeSubtype(Bonus::GENERATE_RESOURCE, Res::GOLD)); totalIncome += heroe->valOfBonuses(Selector::typeSubtype(Bonus::GENERATE_RESOURCE, GameResID(EGameResID::GOLD)));
} }
//Add town income of all towns //Add town income of all towns
std::vector<const CGTownInstance*> towns = LOCPLINT->cb->getTownsInfo(true); std::vector<const CGTownInstance*> towns = LOCPLINT->cb->getTownsInfo(true);
for(auto & town : towns) for(auto & town : towns)
{ {
totalIncome += town->dailyIncome()[Res::GOLD]; totalIncome += town->dailyIncome()[EGameResID::GOLD];
} }
for(int i=0; i<7; i++) for(int i=0; i<7; i++)
{ {
@ -772,7 +772,7 @@ CTownItem::CTownItem(const CGTownInstance * Town)
background = std::make_shared<CAnimImage>("OVSLOT", 6); background = std::make_shared<CAnimImage>("OVSLOT", 6);
name = std::make_shared<CLabel>(74, 8, FONT_SMALL, ETextAlignment::TOPLEFT, Colors::WHITE, town->getNameTranslated()); name = std::make_shared<CLabel>(74, 8, FONT_SMALL, ETextAlignment::TOPLEFT, Colors::WHITE, town->getNameTranslated());
income = std::make_shared<CLabel>( 190, 60, FONT_SMALL, ETextAlignment::CENTER, Colors::WHITE, std::to_string(town->dailyIncome()[Res::GOLD])); income = std::make_shared<CLabel>( 190, 60, FONT_SMALL, ETextAlignment::CENTER, Colors::WHITE, std::to_string(town->dailyIncome()[EGameResID::GOLD]));
hall = std::make_shared<CTownInfo>( 69, 31, town, true); hall = std::make_shared<CTownInfo>( 69, 31, town, true);
fort = std::make_shared<CTownInfo>(111, 31, town, false); fort = std::make_shared<CTownInfo>(111, 31, town, false);
@ -801,7 +801,7 @@ void CTownItem::updateGarrisons()
void CTownItem::update() void CTownItem::update()
{ {
std::string incomeVal = std::to_string(town->dailyIncome()[Res::GOLD]); std::string incomeVal = std::to_string(town->dailyIncome()[EGameResID::GOLD]);
if (incomeVal != income->getText()) if (incomeVal != income->getText())
income->setText(incomeVal); income->setText(incomeVal);

View File

@ -191,7 +191,7 @@ void CTradeWindow::CTradeableItem::clickLeft(tribool down, bool previousState)
aw->arts->markPossibleSlots(art); aw->arts->markPossibleSlots(art);
//aw->arts->commonInfo->dst.AOH = aw->arts; //aw->arts->commonInfo->dst.AOH = aw->arts;
CCS->curh->dragAndDropCursor("artifact", art->artType->iconIndex); CCS->curh->dragAndDropCursor("artifact", art->artType->getIconIndex());
aw->arts->artifactsOnAltar.erase(art); aw->arts->artifactsOnAltar.erase(art);
setID(-1); setID(-1);
@ -447,7 +447,7 @@ std::vector<int> *CTradeWindow::getItemsIds(bool Left)
for(int i = 0; i < 7; i++) for(int i = 0; i < 7; i++)
{ {
if(const CCreature *c = hero->getCreature(SlotID(i))) if(const CCreature *c = hero->getCreature(SlotID(i)))
ids->push_back(c->idNumber); ids->push_back(c->getId());
else else
ids->push_back(-1); ids->push_back(-1);
} }
@ -535,7 +535,7 @@ void CTradeWindow::initSubs(bool Left)
item->subtitle = std::to_string(hero->getStackCount(SlotID(item->serial))); item->subtitle = std::to_string(hero->getStackCount(SlotID(item->serial)));
break; break;
case RESOURCE: case RESOURCE:
item->subtitle = std::to_string(LOCPLINT->cb->getResourceAmount(static_cast<Res::ERes>(item->serial))); item->subtitle = std::to_string(LOCPLINT->cb->getResourceAmount(static_cast<EGameResID>(item->serial)));
break; break;
} }
} }
@ -869,7 +869,7 @@ void CMarketplaceWindow::selectionChanged(bool side)
{ {
int newAmount = -1; int newAmount = -1;
if(itemsType[1] == RESOURCE) if(itemsType[1] == RESOURCE)
newAmount = LOCPLINT->cb->getResourceAmount(static_cast<Res::ERes>(soldItemId)); newAmount = LOCPLINT->cb->getResourceAmount(static_cast<EGameResID>(soldItemId));
else if(itemsType[1] == CREATURE) else if(itemsType[1] == CREATURE)
newAmount = hero->getStackCount(SlotID(hLeft->serial)) - (hero->stacksCount() == 1 && hero->needsLastStack()); newAmount = hero->getStackCount(SlotID(hLeft->serial)) - (hero->stacksCount() == 1 && hero->needsLastStack());
else else
@ -882,7 +882,7 @@ void CMarketplaceWindow::selectionChanged(bool side)
} }
else if(itemsType[1] == RESOURCE) //buying -> check if we can afford transaction else if(itemsType[1] == RESOURCE) //buying -> check if we can afford transaction
{ {
deal->block(LOCPLINT->cb->getResourceAmount(static_cast<Res::ERes>(soldItemId)) < r1); deal->block(LOCPLINT->cb->getResourceAmount(static_cast<EGameResID>(soldItemId)) < r1);
} }
else else
deal->block(false); deal->block(false);
@ -1486,7 +1486,7 @@ void CAltarWindow::showAll(SDL_Surface * to)
CTradeWindow::showAll(to); CTradeWindow::showAll(to);
if(mode == EMarketMode::ARTIFACT_EXP && arts && arts->commonInfo->src.art) if(mode == EMarketMode::ARTIFACT_EXP && arts && arts->commonInfo->src.art)
{ {
artIcon->setFrame(arts->commonInfo->src.art->artType->iconIndex); artIcon->setFrame(arts->commonInfo->src.art->artType->getIconIndex());
artIcon->showAll(to); artIcon->showAll(to);
int dmp, val; int dmp, val;

View File

@ -48,13 +48,13 @@ void CreaturePurchaseCard::initCreatureSwitcherButton()
void CreaturePurchaseCard::switchCreatureLevel() void CreaturePurchaseCard::switchCreatureLevel()
{ {
OBJECT_CONSTRUCTION_CAPTURING(ACTIVATE + DEACTIVATE + UPDATE + SHOWALL + SHARE_POS); OBJECT_CONSTRUCTION_CAPTURING(ACTIVATE + DEACTIVATE + UPDATE + SHOWALL + SHARE_POS);
auto index = vstd::find_pos(upgradesID, creatureOnTheCard->idNumber); auto index = vstd::find_pos(upgradesID, creatureOnTheCard->getId());
auto nextCreatureId = vstd::circularAt(upgradesID, ++index); auto nextCreatureId = vstd::circularAt(upgradesID, ++index);
creatureOnTheCard = nextCreatureId.toCreature(); creatureOnTheCard = nextCreatureId.toCreature();
picture = std::make_shared<CCreaturePic>(parent->pos.x, parent->pos.y, creatureOnTheCard); picture = std::make_shared<CCreaturePic>(parent->pos.x, parent->pos.y, creatureOnTheCard);
creatureClickArea = std::make_shared<CCreatureClickArea>(Point(parent->pos.x, parent->pos.y), picture, creatureOnTheCard); creatureClickArea = std::make_shared<CCreatureClickArea>(Point(parent->pos.x, parent->pos.y), picture, creatureOnTheCard);
parent->updateAllSliders(); parent->updateAllSliders();
cost->set(creatureOnTheCard->cost * slider->getValue()); cost->set(creatureOnTheCard->getFullRecruitCost() * slider->getValue());
} }
void CreaturePurchaseCard::initAmountInfo() void CreaturePurchaseCard::initAmountInfo()
@ -78,13 +78,13 @@ void CreaturePurchaseCard::initSlider()
void CreaturePurchaseCard::initCostBox() void CreaturePurchaseCard::initCostBox()
{ {
cost = std::make_shared<CreatureCostBox>(Rect(pos.x+2, pos.y + 194, 97, 74), ""); cost = std::make_shared<CreatureCostBox>(Rect(pos.x+2, pos.y + 194, 97, 74), "");
cost->createItems(creatureOnTheCard->cost); cost->createItems(creatureOnTheCard->getFullRecruitCost());
} }
void CreaturePurchaseCard::sliderMoved(int to) void CreaturePurchaseCard::sliderMoved(int to)
{ {
updateAmountInfo(to); updateAmountInfo(to);
cost->set(creatureOnTheCard->cost * to); cost->set(creatureOnTheCard->getFullRecruitCost() * to);
parent->updateAllSliders(); parent->updateAllSliders();
} }

View File

@ -135,11 +135,11 @@ void CRecruitmentWindow::select(std::shared_ptr<CCreatureCard> card)
else // if slider already at 0 - emulate call to sliderMoved() else // if slider already at 0 - emulate call to sliderMoved()
sliderMoved(maxAmount); sliderMoved(maxAmount);
costPerTroopValue->createItems(card->creature->cost); costPerTroopValue->createItems(card->creature->getFullRecruitCost());
totalCostValue->createItems(card->creature->cost); totalCostValue->createItems(card->creature->getFullRecruitCost());
costPerTroopValue->set(card->creature->cost); costPerTroopValue->set(card->creature->getFullRecruitCost());
totalCostValue->set(card->creature->cost * maxAmount); totalCostValue->set(card->creature->getFullRecruitCost() * maxAmount);
//Recruit %s //Recruit %s
title->setText(boost::str(boost::format(CGI->generaltexth->tcommands[21]) % card->creature->getNamePluralTranslated())); title->setText(boost::str(boost::format(CGI->generaltexth->tcommands[21]) % card->creature->getNamePluralTranslated()));
@ -151,7 +151,7 @@ void CRecruitmentWindow::select(std::shared_ptr<CCreatureCard> card)
void CRecruitmentWindow::buy() void CRecruitmentWindow::buy()
{ {
CreatureID crid = selected->creature->idNumber; CreatureID crid = selected->creature->getId();
SlotID dstslot = dst-> getSlotFor(crid); SlotID dstslot = dst-> getSlotFor(crid);
if(!dstslot.validSlot() && (selected->creature->warMachine == ArtifactID::NONE)) //no available slot if(!dstslot.validSlot() && (selected->creature->warMachine == ArtifactID::NONE)) //no available slot
@ -296,7 +296,7 @@ void CRecruitmentWindow::sliderMoved(int to)
availableValue->setText(std::to_string(selected->amount - to)); availableValue->setText(std::to_string(selected->amount - to));
toRecruitValue->setText(std::to_string(to)); toRecruitValue->setText(std::to_string(to));
totalCostValue->set(selected->creature->cost * to); totalCostValue->set(selected->creature->getFullRecruitCost() * to);
} }
CSplitWindow::CSplitWindow(const CCreature * creature, std::function<void(int, int)> callback_, int leftMin_, int rightMin_, int leftAmount_, int rightAmount_) CSplitWindow::CSplitWindow(const CCreature * creature, std::function<void(int, int)> callback_, int leftMin_, int rightMin_, int leftAmount_, int rightAmount_)
@ -463,7 +463,7 @@ CTavernWindow::CTavernWindow(const CGObjectInstance * TavernObj)
recruit = std::make_shared<CButton>(Point(272, 355), "TPTAV01.DEF", CButton::tooltip(), std::bind(&CTavernWindow::recruitb, this), SDLK_RETURN); recruit = std::make_shared<CButton>(Point(272, 355), "TPTAV01.DEF", CButton::tooltip(), std::bind(&CTavernWindow::recruitb, this), SDLK_RETURN);
thiefGuild = std::make_shared<CButton>(Point(22, 428), "TPTAV02.DEF", CButton::tooltip(CGI->generaltexth->tavernInfo[5]), std::bind(&CTavernWindow::thievesguildb, this), SDLK_t); thiefGuild = std::make_shared<CButton>(Point(22, 428), "TPTAV02.DEF", CButton::tooltip(CGI->generaltexth->tavernInfo[5]), std::bind(&CTavernWindow::thievesguildb, this), SDLK_t);
if(LOCPLINT->cb->getResourceAmount(Res::GOLD) < GameConstants::HERO_GOLD_COST) //not enough gold if(LOCPLINT->cb->getResourceAmount(EGameResID::GOLD) < GameConstants::HERO_GOLD_COST) //not enough gold
{ {
recruit->addHoverText(CButton::NORMAL, CGI->generaltexth->tavernInfo[0]); //Cannot afford a Hero recruit->addHoverText(CButton::NORMAL, CGI->generaltexth->tavernInfo[0]); //Cannot afford a Hero
recruit->block(true); recruit->block(true);
@ -811,7 +811,7 @@ void CExchangeController::moveArmy(bool leftToRight)
source->Slots(), source->Slots(),
[](const std::pair<SlotID, CStackInstance *> & s) -> int [](const std::pair<SlotID, CStackInstance *> & s) -> int
{ {
return s.second->getCreatureID().toCreature()->AIValue; return s.second->getCreatureID().toCreature()->getAIValue();
}); });
slot = weakestSlot->first; slot = weakestSlot->first;
@ -1093,20 +1093,20 @@ CShipyardWindow::CShipyardWindow(const TResources & cost, int state, int boatTyp
bgShip->center(waterCenter); bgShip->center(waterCenter);
// Create resource icons and costs. // Create resource icons and costs.
std::string goldValue = std::to_string(cost[Res::GOLD]); std::string goldValue = std::to_string(cost[EGameResID::GOLD]);
std::string woodValue = std::to_string(cost[Res::WOOD]); std::string woodValue = std::to_string(cost[EGameResID::WOOD]);
goldCost = std::make_shared<CLabel>(118, 294, FONT_SMALL, ETextAlignment::CENTER, Colors::WHITE, goldValue); goldCost = std::make_shared<CLabel>(118, 294, FONT_SMALL, ETextAlignment::CENTER, Colors::WHITE, goldValue);
woodCost = std::make_shared<CLabel>(212, 294, FONT_SMALL, ETextAlignment::CENTER, Colors::WHITE, woodValue); woodCost = std::make_shared<CLabel>(212, 294, FONT_SMALL, ETextAlignment::CENTER, Colors::WHITE, woodValue);
goldPic = std::make_shared<CAnimImage>("RESOURCE", Res::GOLD, 0, 100, 244); goldPic = std::make_shared<CAnimImage>("RESOURCE",GameResID(EGameResID::GOLD), 0, 100, 244);
woodPic = std::make_shared<CAnimImage>("RESOURCE", Res::WOOD, 0, 196, 244); woodPic = std::make_shared<CAnimImage>("RESOURCE", GameResID(EGameResID::WOOD), 0, 196, 244);
quit = std::make_shared<CButton>(Point(224, 312), "ICANCEL", CButton::tooltip(CGI->generaltexth->allTexts[599]), std::bind(&CShipyardWindow::close, this), SDLK_ESCAPE); quit = std::make_shared<CButton>(Point(224, 312), "ICANCEL", CButton::tooltip(CGI->generaltexth->allTexts[599]), std::bind(&CShipyardWindow::close, this), SDLK_ESCAPE);
build = std::make_shared<CButton>(Point(42, 312), "IBUY30", CButton::tooltip(CGI->generaltexth->allTexts[598]), std::bind(&CShipyardWindow::close, this), SDLK_RETURN); build = std::make_shared<CButton>(Point(42, 312), "IBUY30", CButton::tooltip(CGI->generaltexth->allTexts[598]), std::bind(&CShipyardWindow::close, this), SDLK_RETURN);
build->addCallback(onBuy); build->addCallback(onBuy);
for(Res::ERes i = Res::WOOD; i <= Res::GOLD; vstd::advance(i, 1)) for(auto i = EGameResID::WOOD; i <= EGameResID::GOLD; vstd::advance(i, 1))
{ {
if(cost[i] > LOCPLINT->cb->getResourceAmount(i)) if(cost[i] > LOCPLINT->cb->getResourceAmount(i))
{ {
@ -1141,7 +1141,7 @@ void CTransformerWindow::CItem::clickLeft(tribool down, bool previousState)
void CTransformerWindow::CItem::update() void CTransformerWindow::CItem::update()
{ {
icon->setFrame(parent->army->getCreature(SlotID(id))->idNumber + 2); icon->setFrame(parent->army->getCreature(SlotID(id))->getId() + 2);
} }
CTransformerWindow::CItem::CItem(CTransformerWindow * parent_, int size_, int id_) CTransformerWindow::CItem::CItem(CTransformerWindow * parent_, int size_, int id_)
@ -1157,7 +1157,7 @@ CTransformerWindow::CItem::CItem(CTransformerWindow * parent_, int size_, int id
pos.x += 45 + (id%3)*83 + id/6*83; pos.x += 45 + (id%3)*83 + id/6*83;
pos.y += 109 + (id/3)*98; pos.y += 109 + (id/3)*98;
icon = std::make_shared<CAnimImage>("TWCRPORT", parent->army->getCreature(SlotID(id))->idNumber + 2); icon = std::make_shared<CAnimImage>("TWCRPORT", parent->army->getCreature(SlotID(id))->getId() + 2);
count = std::make_shared<CLabel>(28, 76,FONT_SMALL, ETextAlignment::CENTER, Colors::WHITE, std::to_string(size)); count = std::make_shared<CLabel>(28, 76,FONT_SMALL, ETextAlignment::CENTER, Colors::WHITE, std::to_string(size));
} }
@ -1240,7 +1240,7 @@ void CUniversityWindow::CItem::clickLeft(tribool down, bool previousState)
if(previousState && (!down)) if(previousState && (!down))
{ {
if(state() == 2) if(state() == 2)
GH.pushIntT<CUnivConfirmWindow>(parent, ID, LOCPLINT->cb->getResourceAmount(Res::GOLD) >= 2000); GH.pushIntT<CUnivConfirmWindow>(parent, ID, LOCPLINT->cb->getResourceAmount(EGameResID::GOLD) >= 2000);
} }
} }
@ -1346,7 +1346,7 @@ CUnivConfirmWindow::CUnivConfirmWindow(CUniversityWindow * owner_, int SKILL, bo
icon = std::make_shared<CAnimImage>("SECSKILL", SKILL*3+3, 0, 211, 51); icon = std::make_shared<CAnimImage>("SECSKILL", SKILL*3+3, 0, 211, 51);
level = std::make_shared<CLabel>(230, 107, FONT_SMALL, ETextAlignment::CENTER, Colors::WHITE, CGI->generaltexth->levels[1]); level = std::make_shared<CLabel>(230, 107, FONT_SMALL, ETextAlignment::CENTER, Colors::WHITE, CGI->generaltexth->levels[1]);
costIcon = std::make_shared<CAnimImage>("RESOURCE", Res::GOLD, 0, 210, 210); costIcon = std::make_shared<CAnimImage>("RESOURCE", GameResID(EGameResID::GOLD), 0, 210, 210);
cost = std::make_shared<CLabel>(230, 267, FONT_SMALL, ETextAlignment::CENTER, Colors::WHITE, "2000"); cost = std::make_shared<CLabel>(230, 267, FONT_SMALL, ETextAlignment::CENTER, Colors::WHITE, "2000");
std::string hoverText = CGI->generaltexth->allTexts[609]; std::string hoverText = CGI->generaltexth->allTexts[609];
@ -1531,7 +1531,7 @@ void CHillFortWindow::updateGarrisons()
else//free upgrade - print gold image and "Free" text else//free upgrade - print gold image and "Free" text
{ {
slotIcons[i][0]->visible = true; slotIcons[i][0]->visible = true;
slotIcons[i][0]->setFrame(Res::GOLD); slotIcons[i][0]->setFrame(GameResID(EGameResID::GOLD));
slotLabels[i][0]->setText(CGI->generaltexth->allTexts[344]); slotLabels[i][0]->setText(CGI->generaltexth->allTexts[344]);
} }
} }

View File

@ -93,7 +93,7 @@ void QuickRecruitmentWindow::maxAllCards(std::vector<std::shared_ptr<CreaturePur
i->sliderMoved(maxAmount); i->sliderMoved(maxAmount);
i->slider->moveToMax(); i->slider->moveToMax();
allAvailableResources -= (i->creatureOnTheCard->cost * maxAmount); allAvailableResources -= (i->creatureOnTheCard->getFullRecruitCost() * maxAmount);
} }
maxButton->block(allAvailableResources == LOCPLINT->cb->getResourceAmount()); maxButton->block(allAvailableResources == LOCPLINT->cb->getResourceAmount());
} }
@ -105,8 +105,8 @@ void QuickRecruitmentWindow::purchaseUnits()
{ {
if(selected->slider->getValue()) if(selected->slider->getValue())
{ {
auto onRecruit = [=](CreatureID id, int count){ LOCPLINT->cb->recruitCreatures(town, town->getUpperArmy(), id, count, selected->creatureOnTheCard->level-1); }; auto onRecruit = [=](CreatureID id, int count){ LOCPLINT->cb->recruitCreatures(town, town->getUpperArmy(), id, count, selected->creatureOnTheCard->getLevel()-1); };
CreatureID crid = selected->creatureOnTheCard->idNumber; CreatureID crid = selected->creatureOnTheCard->getId();
SlotID dstslot = town -> getSlotFor(crid); SlotID dstslot = town -> getSlotFor(crid);
if(!dstslot.validSlot()) if(!dstslot.validSlot())
continue; continue;
@ -129,7 +129,7 @@ void QuickRecruitmentWindow::updateAllSliders()
{ {
auto allAvailableResources = LOCPLINT->cb->getResourceAmount(); auto allAvailableResources = LOCPLINT->cb->getResourceAmount();
for(auto i : boost::adaptors::reverse(cards)) for(auto i : boost::adaptors::reverse(cards))
allAvailableResources -= (i->creatureOnTheCard->cost * i->slider->getValue()); allAvailableResources -= (i->creatureOnTheCard->getFullRecruitCost() * i->slider->getValue());
for(auto i : cards) for(auto i : cards)
{ {
si32 maxAmount = i->creatureOnTheCard->maxAmount(allAvailableResources); si32 maxAmount = i->creatureOnTheCard->maxAmount(allAvailableResources);

View File

@ -15,6 +15,8 @@
VCMI_LIB_NAMESPACE_BEGIN VCMI_LIB_NAMESPACE_BEGIN
class CreatureID; class CreatureID;
class ResourceSet;
enum class EGameResID : int8_t;
class DLL_LINKAGE Creature : public EntityWithBonuses<CreatureID> class DLL_LINKAGE Creature : public EntityWithBonuses<CreatureID>
{ {
@ -50,7 +52,10 @@ public:
virtual int32_t getBaseSpeed() const = 0; virtual int32_t getBaseSpeed() const = 0;
virtual int32_t getBaseShots() const = 0; virtual int32_t getBaseShots() const = 0;
virtual int32_t getCost(int32_t resIndex) const = 0; virtual int32_t getRecruitCost(Identifier<EGameResID> resIndex) const = 0;
virtual ResourceSet getFullRecruitCost() const = 0;
virtual bool hasUpgrades() const = 0;
virtual bool isDoubleWide() const = 0; virtual bool isDoubleWide() const = 0;
}; };

View File

@ -14,6 +14,12 @@ VCMI_LIB_NAMESPACE_BEGIN
class IBonusBearer; class IBonusBearer;
class DLL_LINKAGE WithBonuses
{
public:
virtual const IBonusBearer * getBonusBearer() const = 0;
};
class DLL_LINKAGE Entity class DLL_LINKAGE Entity
{ {
public: public:
@ -38,10 +44,8 @@ public:
}; };
template <typename IdType> template <typename IdType>
class DLL_LINKAGE EntityWithBonuses : public EntityT<IdType> class DLL_LINKAGE EntityWithBonuses : public EntityT<IdType>, public WithBonuses
{ {
public:
virtual const IBonusBearer * accessBonuses() const = 0;
}; };
VCMI_LIB_NAMESPACE_END VCMI_LIB_NAMESPACE_END

View File

@ -77,7 +77,7 @@ ArtifactID CArtifact::getId() const
return id; return id;
} }
const IBonusBearer * CArtifact::accessBonuses() const const IBonusBearer * CArtifact::getBonusBearer() const
{ {
return this; return this;
} }

View File

@ -69,7 +69,7 @@ public:
std::string getJsonKey() const override; std::string getJsonKey() const override;
void registerIcons(const IconRegistar & cb) const override; void registerIcons(const IconRegistar & cb) const override;
ArtifactID getId() const override; ArtifactID getId() const override;
virtual const IBonusBearer * accessBonuses() const override; virtual const IBonusBearer * getBonusBearer() const override;
std::string getDescriptionTranslated() const override; std::string getDescriptionTranslated() const override;
std::string getEventTranslated() const override; std::string getEventTranslated() const override;

View File

@ -64,7 +64,7 @@ CreatureID CCreature::getId() const
return idNumber; return idNumber;
} }
const IBonusBearer * CCreature::accessBonuses() const const IBonusBearer * CCreature::getBonusBearer() const
{ {
return this; return this;
} }
@ -162,7 +162,7 @@ int32_t CCreature::getBaseShots() const
return getExportedBonusList().valOfBonuses(SELECTOR); return getExportedBonusList().valOfBonuses(SELECTOR);
} }
int32_t CCreature::getCost(int32_t resIndex) const int32_t CCreature::getRecruitCost(GameResID resIndex) const
{ {
if(resIndex >= 0 && resIndex < cost.size()) if(resIndex >= 0 && resIndex < cost.size())
return cost[resIndex]; return cost[resIndex];
@ -170,6 +170,16 @@ int32_t CCreature::getCost(int32_t resIndex) const
return 0; return 0;
} }
TResources CCreature::getFullRecruitCost() const
{
return cost;
}
bool CCreature::hasUpgrades() const
{
return !upgrades.empty();
}
std::string CCreature::getNameTranslated() const std::string CCreature::getNameTranslated() const
{ {
return getNameSingularTranslated(); return getNameSingularTranslated();
@ -307,7 +317,7 @@ void CCreature::addBonus(int val, Bonus::BonusType type, int subtype)
bool CCreature::isMyUpgrade(const CCreature *anotherCre) const bool CCreature::isMyUpgrade(const CCreature *anotherCre) const
{ {
//TODO upgrade of upgrade? //TODO upgrade of upgrade?
return vstd::contains(upgrades, anotherCre->idNumber); return vstd::contains(upgrades, anotherCre->getId());
} }
bool CCreature::valid() const bool CCreature::valid() const
@ -614,7 +624,7 @@ CCreature * CCreatureHandler::loadFromJson(const std::string & scope, const Json
JsonDeserializer handler(nullptr, node); JsonDeserializer handler(nullptr, node);
cre->serializeJson(handler); cre->serializeJson(handler);
cre->cost = Res::ResourceSet(node["cost"]); cre->cost = ResourceSet(node["cost"]);
VLC->generaltexth->registerString(scope, cre->getNameSingularTextID(), node["name"]["singular"].String()); VLC->generaltexth->registerString(scope, cre->getNameSingularTextID(), node["name"]["singular"].String());
VLC->generaltexth->registerString(scope, cre->getNamePluralTextID(), node["name"]["plural"].String()); VLC->generaltexth->registerString(scope, cre->getNamePluralTextID(), node["name"]["plural"].String());
@ -647,18 +657,18 @@ CCreature * CCreatureHandler::loadFromJson(const std::string & scope, const Json
JsonNode conf; JsonNode conf;
conf.setMeta(scope); conf.setMeta(scope);
VLC->objtypeh->loadSubObject(cre->identifier, conf, Obj::MONSTER, cre->idNumber.num); VLC->objtypeh->loadSubObject(cre->identifier, conf, Obj::MONSTER, cre->getId().num);
if (!cre->advMapDef.empty()) if (!cre->advMapDef.empty())
{ {
JsonNode templ; JsonNode templ;
templ["animation"].String() = cre->advMapDef; templ["animation"].String() = cre->advMapDef;
templ.setMeta(scope); templ.setMeta(scope);
VLC->objtypeh->getHandlerFor(Obj::MONSTER, cre->idNumber.num)->addTemplate(templ); VLC->objtypeh->getHandlerFor(Obj::MONSTER, cre->getId().num)->addTemplate(templ);
} }
// object does not have any templates - this is not usable object (e.g. pseudo-creature like Arrow Tower) // object does not have any templates - this is not usable object (e.g. pseudo-creature like Arrow Tower)
if (VLC->objtypeh->getHandlerFor(Obj::MONSTER, cre->idNumber.num)->getTemplates().empty()) if (VLC->objtypeh->getHandlerFor(Obj::MONSTER, cre->getId().num)->getTemplates().empty())
VLC->objtypeh->removeSubObject(Obj::MONSTER, cre->idNumber.num); VLC->objtypeh->removeSubObject(Obj::MONSTER, cre->getId().num);
}); });
return cre; return cre;
@ -1335,7 +1345,7 @@ CreatureID CCreatureHandler::pickRandomMonster(CRandomGenerator & rand, int tier
{ {
do do
{ {
r = (*RandomGeneratorUtil::nextItem(objects, rand))->idNumber; r = (*RandomGeneratorUtil::nextItem(objects, rand))->getId();
} while (objects[r] && objects[r]->special); // find first "not special" creature } while (objects[r] && objects[r]->special); // find first "not special" creature
} }
else else
@ -1347,7 +1357,7 @@ CreatureID CCreatureHandler::pickRandomMonster(CRandomGenerator & rand, int tier
assert(b->getNodeType() == CBonusSystemNode::CREATURE); assert(b->getNodeType() == CBonusSystemNode::CREATURE);
const auto * crea = dynamic_cast<const CCreature *>(b); const auto * crea = dynamic_cast<const CCreature *>(b);
if(crea && !crea->special) if(crea && !crea->special)
allowed.push_back(crea->idNumber); allowed.push_back(crea->getId());
} }
if(allowed.empty()) if(allowed.empty())

View File

@ -9,9 +9,6 @@
*/ */
#pragma once #pragma once
#include <vcmi/Creature.h>
#include <vcmi/CreatureService.h>
#include "HeroBonus.h" #include "HeroBonus.h"
#include "ConstTransitivePtr.h" #include "ConstTransitivePtr.h"
#include "ResourceSet.h" #include "ResourceSet.h"
@ -21,6 +18,9 @@
#include "CRandomGenerator.h" #include "CRandomGenerator.h"
#include "Color.h" #include "Color.h"
#include <vcmi/Creature.h>
#include <vcmi/CreatureService.h>
VCMI_LIB_NAMESPACE_BEGIN VCMI_LIB_NAMESPACE_BEGIN
class CLegacyConfigParser; class CLegacyConfigParser;
@ -37,7 +37,6 @@ class DLL_LINKAGE CCreature : public Creature, public CBonusSystemNode
std::string getNameTranslated() const override; std::string getNameTranslated() const override;
std::string getNameTextID() const override; std::string getNameTextID() const override;
public:
CreatureID idNumber; CreatureID idNumber;
TFaction faction = 0; TFaction faction = 0;
@ -45,17 +44,22 @@ public:
//stats that are not handled by bonus system //stats that are not handled by bonus system
ui32 fightValue, AIValue, growth, hordeGrowth; ui32 fightValue, AIValue, growth, hordeGrowth;
ui32 ammMin, ammMax; // initial size of stack of these creatures on adventure map (if not set in editor)
bool doubleWide = false; bool doubleWide = false;
bool special = true; // Creature is not available normally (war machines, commanders, several unused creatures, etc
si32 iconIndex = -1; // index of icon in files like twcrport
TResources cost; //cost[res_id] - amount of that resource required to buy creature from dwelling TResources cost; //cost[res_id] - amount of that resource required to buy creature from dwelling
public:
ui32 ammMin, ammMax; // initial size of stack of these creatures on adventure map (if not set in editor)
bool special = true; // Creature is not available normally (war machines, commanders, several unused creatures, etc
std::set<CreatureID> upgrades; // IDs of creatures to which this creature can be upgraded std::set<CreatureID> upgrades; // IDs of creatures to which this creature can be upgraded
std::string animDefName; // creature animation used during battles std::string animDefName; // creature animation used during battles
std::string advMapDef; //for new creatures only, image for adventure map std::string advMapDef; //for new creatures only, image for adventure map
si32 iconIndex = -1; // index of icon in files like twcrport
/// names of files with appropriate icons. Used only during loading /// names of files with appropriate icons. Used only during loading
std::string smallIconName; std::string smallIconName;
@ -168,7 +172,7 @@ public:
std::string getJsonKey() const override; std::string getJsonKey() const override;
void registerIcons(const IconRegistar & cb) const override; void registerIcons(const IconRegistar & cb) const override;
CreatureID getId() const override; CreatureID getId() const override;
virtual const IBonusBearer * accessBonuses() const override; virtual const IBonusBearer * getBonusBearer() const override;
uint32_t getMaxHealth() const override; uint32_t getMaxHealth() const override;
int32_t getAdvMapAmountMin() const override; int32_t getAdvMapAmountMin() const override;
@ -189,8 +193,10 @@ public:
int32_t getBaseSpeed() const override; int32_t getBaseSpeed() const override;
int32_t getBaseShots() const override; int32_t getBaseShots() const override;
int32_t getCost(int32_t resIndex) const override; int32_t getRecruitCost(GameResID resIndex) const override;
TResources getFullRecruitCost() const override;
bool isDoubleWide() const override; //returns true if unit is double wide on battlefield bool isDoubleWide() const override; //returns true if unit is double wide on battlefield
bool hasUpgrades() const override;
bool isGood () const; bool isGood () const;
bool isEvil () const; bool isEvil () const;

View File

@ -590,12 +590,12 @@ bool CCreatureSet::canBeMergedWith(const CCreatureSet &cs, bool allowMergingStac
//get types of creatures that need their own slot //get types of creatures that need their own slot
for(const auto & elem : cs.stacks) for(const auto & elem : cs.stacks)
if ((j = cres.getSlotFor(elem.second->type)).validSlot()) if ((j = cres.getSlotFor(elem.second->type)).validSlot())
cres.addToSlot(j, elem.second->type->idNumber, 1, true); //merge if possible cres.addToSlot(j, elem.second->type->getId(), 1, true); //merge if possible
//cres.addToSlot(elem.first, elem.second->type->idNumber, 1, true); //cres.addToSlot(elem.first, elem.second->type->getId(), 1, true);
for(const auto & elem : stacks) for(const auto & elem : stacks)
{ {
if ((j = cres.getSlotFor(elem.second->type)).validSlot()) if ((j = cres.getSlotFor(elem.second->type)).validSlot())
cres.addToSlot(j, elem.second->type->idNumber, 1, true); //merge if possible cres.addToSlot(j, elem.second->type->getId(), 1, true); //merge if possible
else else
return false; //no place found return false; //no place found
} }
@ -706,7 +706,7 @@ int CStackInstance::getExpRank() const
{ {
if (!VLC->settings()->getBoolean(EGameSettings::MODULE_STACK_EXPERIENCE)) if (!VLC->settings()->getBoolean(EGameSettings::MODULE_STACK_EXPERIENCE))
return 0; return 0;
int tier = type->level; int tier = type->getLevel();
if (vstd::iswithin(tier, 1, 7)) if (vstd::iswithin(tier, 1, 7))
{ {
for(int i = static_cast<int>(VLC->creh->expRanks[tier].size()) - 2; i > -1; --i) //sic! for(int i = static_cast<int>(VLC->creh->expRanks[tier].size()) - 2; i > -1; --i) //sic!
@ -729,7 +729,7 @@ int CStackInstance::getExpRank() const
int CStackInstance::getLevel() const int CStackInstance::getLevel() const
{ {
return std::max(1, static_cast<int>(type->level)); return std::max(1, static_cast<int>(type->getLevel()));
} }
si32 CStackInstance::magicResistance() const si32 CStackInstance::magicResistance() const
@ -741,7 +741,7 @@ si32 CStackInstance::magicResistance() const
void CStackInstance::giveStackExp(TExpType exp) void CStackInstance::giveStackExp(TExpType exp)
{ {
int level = type->level; int level = type->getLevel();
if (!vstd::iswithin(level, 1, 7)) if (!vstd::iswithin(level, 1, 7))
level = 0; level = 0;
@ -816,7 +816,7 @@ bool CStackInstance::valid(bool allowUnrandomized) const
bool isRand = (idRand != -1); bool isRand = (idRand != -1);
if(!isRand) if(!isRand)
{ {
return (type && type == VLC->creh->objects[type->idNumber]); return (type && type == VLC->creh->objects[type->getId()]);
} }
else else
return allowUnrandomized; return allowUnrandomized;
@ -852,7 +852,7 @@ void CStackInstance::deserializationFix()
CreatureID CStackInstance::getCreatureID() const CreatureID CStackInstance::getCreatureID() const
{ {
if(type) if(type)
return type->idNumber; return type->getId();
else else
return CreatureID::NONE; return CreatureID::NONE;
} }
@ -865,7 +865,7 @@ std::string CStackInstance::getName() const
ui64 CStackInstance::getPower() const ui64 CStackInstance::getPower() const
{ {
assert(type); assert(type);
return type->AIValue * count; return type->getAIValue() * count;
} }
ArtBearer::ArtBearer CStackInstance::bearerType() const ArtBearer::ArtBearer CStackInstance::bearerType() const

View File

@ -43,7 +43,7 @@ public:
{ {
if(h.saving) if(h.saving)
{ {
CreatureID idNumber = type ? type->idNumber : CreatureID(CreatureID::NONE); auto idNumber = type ? type->getId() : CreatureID(CreatureID::NONE);
h & idNumber; h & idNumber;
} }
else else
@ -51,7 +51,7 @@ public:
CreatureID idNumber; CreatureID idNumber;
h & idNumber; h & idNumber;
if(idNumber != CreatureID::NONE) if(idNumber != CreatureID::NONE)
setType(VLC->creh->objects[idNumber]); setType(dynamic_cast<const CCreature*>(VLC->creatures()->getByIndex(idNumber)));
else else
type = nullptr; type = nullptr;
} }

View File

@ -37,7 +37,7 @@ PlayerColor CGameInfoCallback::getOwner(ObjectInstanceID heroID) const
return obj->tempOwner; return obj->tempOwner;
} }
int CGameInfoCallback::getResource(PlayerColor Player, Res::ERes which) const int CGameInfoCallback::getResource(PlayerColor Player, GameResID which) const
{ {
const PlayerState *p = getPlayerState(Player); const PlayerState *p = getPlayerState(Player);
ERROR_RET_VAL_IF(!p, "No player info!", -1); ERROR_RET_VAL_IF(!p, "No player info!", -1);
@ -323,9 +323,9 @@ bool CGameInfoCallback::getHeroInfo(const CGObjectInstance * hero, InfoAboutHero
for(auto & elem : info.army) for(auto & elem : info.army)
{ {
if(static_cast<int>(elem.second.type->AIValue) > maxAIValue) if(static_cast<int>(elem.second.type->getAIValue()) > maxAIValue)
{ {
maxAIValue = elem.second.type->AIValue; maxAIValue = elem.second.type->getAIValue();
mostStrong = elem.second.type; mostStrong = elem.second.type;
} }
} }
@ -359,9 +359,9 @@ bool CGameInfoCallback::getHeroInfo(const CGObjectInstance * hero, InfoAboutHero
for(auto creature : VLC->creh->objects) for(auto creature : VLC->creh->objects)
{ {
if(static_cast<si16>(creature->faction) == factionIndex && static_cast<int>(creature->AIValue) > maxAIValue) if(static_cast<si16>(creature->getFactionIndex()) == factionIndex && static_cast<int>(creature->getAIValue()) > maxAIValue)
{ {
maxAIValue = creature->AIValue; maxAIValue = creature->getAIValue();
mostStrong = creature; mostStrong = creature;
} }
} }
@ -860,7 +860,7 @@ const CGTownInstance* CPlayerSpecificInfoCallback::getTownBySerial(int serialId)
return p->towns[serialId]; return p->towns[serialId];
} }
int CPlayerSpecificInfoCallback::getResourceAmount(Res::ERes type) const int CPlayerSpecificInfoCallback::getResourceAmount(GameResID type) const
{ {
//boost::shared_lock<boost::shared_mutex> lock(*gs->mx); //boost::shared_lock<boost::shared_mutex> lock(*gs->mx);
ERROR_RET_VAL_IF(!player, "Applicable only for player callbacks", -1); ERROR_RET_VAL_IF(!player, "Applicable only for player callbacks", -1);

View File

@ -10,7 +10,7 @@
#pragma once #pragma once
#include "int3.h" #include "int3.h"
#include "ResourceSet.h" // for Res::ERes #include "ResourceSet.h" // for Res
#include "battle/CCallbackBase.h" #include "battle/CCallbackBase.h"
VCMI_LIB_NAMESPACE_BEGIN VCMI_LIB_NAMESPACE_BEGIN
@ -58,7 +58,7 @@ public:
//player //player
virtual const Player * getPlayer(PlayerColor color) const = 0; virtual const Player * getPlayer(PlayerColor color) const = 0;
// virtual int getResource(PlayerColor Player, Res::ERes which) const = 0; // virtual int getResource(PlayerColor Player, EGameResID which) const = 0;
// bool isVisible(int3 pos) const; // bool isVisible(int3 pos) const;
// PlayerRelations::PlayerRelations getPlayerRelations(PlayerColor color1, PlayerColor color2) const; // PlayerRelations::PlayerRelations getPlayerRelations(PlayerColor color1, PlayerColor color2) const;
// void getThievesGuildInfo(SThievesGuildInfo & thi, const CGObjectInstance * obj); //get thieves' guild info obtainable while visiting given object // void getThievesGuildInfo(SThievesGuildInfo & thi, const CGObjectInstance * obj); //get thieves' guild info obtainable while visiting given object
@ -148,7 +148,7 @@ public:
//player //player
const Player * getPlayer(PlayerColor color) const override; const Player * getPlayer(PlayerColor color) const override;
virtual const PlayerState * getPlayerState(PlayerColor color, bool verbose = true) const; virtual const PlayerState * getPlayerState(PlayerColor color, bool verbose = true) const;
virtual int getResource(PlayerColor Player, Res::ERes which) const; virtual int getResource(PlayerColor Player, GameResID which) const;
virtual PlayerRelations::PlayerRelations getPlayerRelations(PlayerColor color1, PlayerColor color2) const; virtual PlayerRelations::PlayerRelations getPlayerRelations(PlayerColor color1, PlayerColor color2) const;
virtual void getThievesGuildInfo(SThievesGuildInfo & thi, const CGObjectInstance * obj); //get thieves' guild info obtainable while visiting given object virtual void getThievesGuildInfo(SThievesGuildInfo & thi, const CGObjectInstance * obj); //get thieves' guild info obtainable while visiting given object
virtual EPlayerStatus::EStatus getPlayerStatus(PlayerColor player, bool verbose = true) const; //-1 if no such player virtual EPlayerStatus::EStatus getPlayerStatus(PlayerColor player, bool verbose = true) const; //-1 if no such player
@ -245,7 +245,7 @@ public:
virtual std::vector <const CGObjectInstance * > getMyObjects() const; //returns all objects flagged by belonging player virtual std::vector <const CGObjectInstance * > getMyObjects() const; //returns all objects flagged by belonging player
virtual std::vector <QuestInfo> getMyQuests() const; virtual std::vector <QuestInfo> getMyQuests() const;
virtual int getResourceAmount(Res::ERes type) const; virtual int getResourceAmount(GameResID type) const;
virtual TResources getResourceAmount() const; virtual TResources getResourceAmount() const;
virtual std::shared_ptr<const boost::multi_array<ui8, 3>> getVisibilityMap() const; //returns visibility map virtual std::shared_ptr<const boost::multi_array<ui8, 3>> getVisibilityMap() const; //returns visibility map
//virtual const PlayerSettings * getPlayerSettings(PlayerColor color) const; //virtual const PlayerSettings * getPlayerSettings(PlayerColor color) const;

View File

@ -293,7 +293,7 @@ void MetaString::addCreReplacement(const CreatureID & id, TQuantity count) //add
void MetaString::addReplacement(const CStackBasicDescriptor & stack) void MetaString::addReplacement(const CStackBasicDescriptor & stack)
{ {
assert(stack.type); //valid type assert(stack.type); //valid type
addCreReplacement(stack.type->idNumber, stack.count); addCreReplacement(stack.type->getId(), stack.count);
} }
static CGObjectInstance * createObject(const Obj & id, int subid, const int3 & pos, const PlayerColor & owner) static CGObjectInstance * createObject(const Obj & id, int subid, const int3 & pos, const PlayerColor & owner)
@ -1443,10 +1443,14 @@ void CGameState::initStartingResources()
res.push_back(chosenBonus->info1); res.push_back(chosenBonus->info1);
break; break;
case 0xFD: //wood+ore case 0xFD: //wood+ore
res.push_back(Res::WOOD); res.push_back(Res::ORE); res.push_back(GameResID(EGameResID::WOOD));
res.push_back(GameResID(EGameResID::ORE));
break; break;
case 0xFE: //rare case 0xFE: //rare
res.push_back(Res::MERCURY); res.push_back(Res::SULFUR); res.push_back(Res::CRYSTAL); res.push_back(Res::GEMS); res.push_back(GameResID(EGameResID::MERCURY));
res.push_back(GameResID(EGameResID::SULFUR));
res.push_back(GameResID(EGameResID::CRYSTAL));
res.push_back(GameResID(EGameResID::GEMS));
break; break;
default: default:
assert(0); assert(0);
@ -1664,16 +1668,16 @@ void CGameState::initStartingBonus()
switch(scenarioOps->playerInfos[elem.first].bonus) switch(scenarioOps->playerInfos[elem.first].bonus)
{ {
case PlayerSettings::GOLD: case PlayerSettings::GOLD:
elem.second.resources[Res::GOLD] += getRandomGenerator().nextInt(5, 10) * 100; elem.second.resources[EGameResID::GOLD] += getRandomGenerator().nextInt(5, 10) * 100;
break; break;
case PlayerSettings::RESOURCE: case PlayerSettings::RESOURCE:
{ {
int res = (*VLC->townh)[scenarioOps->playerInfos[elem.first].castle]->town->primaryRes; auto res = (*VLC->townh)[scenarioOps->playerInfos[elem.first].castle]->town->primaryRes;
if(res == Res::WOOD_AND_ORE) if(res == EGameResID::WOOD_AND_ORE)
{ {
int amount = getRandomGenerator().nextInt(5, 10); int amount = getRandomGenerator().nextInt(5, 10);
elem.second.resources[Res::WOOD] += amount; elem.second.resources[EGameResID::WOOD] += amount;
elem.second.resources[Res::ORE] += amount; elem.second.resources[EGameResID::ORE] += amount;
} }
else else
{ {
@ -2016,14 +2020,14 @@ UpgradeInfo CGameState::fillUpgradeInfo(const CStackInstance &stack) const
t = dynamic_cast<const CGTownInstance *>(stack.armyObj); t = dynamic_cast<const CGTownInstance *>(stack.armyObj);
else if(h) else if(h)
{ //hero specialty { //hero specialty
TConstBonusListPtr lista = h->getBonuses(Selector::typeSubtype(Bonus::SPECIAL_UPGRADE, base->idNumber)); TConstBonusListPtr lista = h->getBonuses(Selector::typeSubtype(Bonus::SPECIAL_UPGRADE, base->getId()));
for(const auto & it : *lista) for(const auto & it : *lista)
{ {
auto nid = CreatureID(it->additionalInfo[0]); auto nid = CreatureID(it->additionalInfo[0]);
if (nid != base->idNumber) //in very specific case the upgrade is available by default (?) if (nid != base->getId()) //in very specific case the upgrade is available by default (?)
{ {
ret.newID.push_back(nid); ret.newID.push_back(nid);
ret.cost.push_back(VLC->creh->objects[nid]->cost - base->cost); ret.cost.push_back(nid.toCreature()->getFullRecruitCost() - base->getFullRecruitCost());
} }
} }
t = h->visitedTown; t = h->visitedTown;
@ -2032,14 +2036,14 @@ UpgradeInfo CGameState::fillUpgradeInfo(const CStackInstance &stack) const
{ {
for(const CGTownInstance::TCreaturesSet::value_type & dwelling : t->creatures) for(const CGTownInstance::TCreaturesSet::value_type & dwelling : t->creatures)
{ {
if (vstd::contains(dwelling.second, base->idNumber)) //Dwelling with our creature if (vstd::contains(dwelling.second, base->getId())) //Dwelling with our creature
{ {
for(const auto & upgrID : dwelling.second) for(const auto & upgrID : dwelling.second)
{ {
if(vstd::contains(base->upgrades, upgrID)) //possible upgrade if(vstd::contains(base->upgrades, upgrID)) //possible upgrade
{ {
ret.newID.push_back(upgrID); ret.newID.push_back(upgrID);
ret.cost.push_back(VLC->creh->objects[upgrID]->cost - base->cost); ret.cost.push_back(upgrID.toCreature()->getFullRecruitCost() - base->getFullRecruitCost());
} }
} }
} }
@ -2050,19 +2054,19 @@ UpgradeInfo CGameState::fillUpgradeInfo(const CStackInstance &stack) const
if(h && map->getTile(h->visitablePos()).visitableObjects.front()->ID == Obj::HILL_FORT) if(h && map->getTile(h->visitablePos()).visitableObjects.front()->ID == Obj::HILL_FORT)
{ {
static const int costModifiers[] = {0, 25, 50, 75, 100}; //we get cheaper upgrades depending on level static const int costModifiers[] = {0, 25, 50, 75, 100}; //we get cheaper upgrades depending on level
const int costModifier = costModifiers[std::min<int>(std::max((int)base->level - 1, 0), ARRAY_COUNT(costModifiers) - 1)]; const int costModifier = costModifiers[std::min<int>(std::max((int)base->getLevel() - 1, 0), ARRAY_COUNT(costModifiers) - 1)];
for(const auto & nid : base->upgrades) for(const auto & nid : base->upgrades)
{ {
ret.newID.push_back(nid); ret.newID.push_back(nid);
ret.cost.push_back((VLC->creh->objects[nid]->cost - base->cost) * costModifier / 100); ret.cost.push_back((nid.toCreature()->getFullRecruitCost() - base->getFullRecruitCost()) * costModifier / 100);
} }
} }
if(!ret.newID.empty()) if(!ret.newID.empty())
ret.oldID = base->idNumber; ret.oldID = base->getId();
for (Res::ResourceSet &cost : ret.cost) for (ResourceSet &cost : ret.cost)
cost.positive(); //upgrade cost can't be negative, ignore missing resources cost.positive(); //upgrade cost can't be negative, ignore missing resources
return ret; return ret;
@ -2346,7 +2350,7 @@ bool CGameState::checkForVictory(const PlayerColor & player, const EventConditio
&& (ai = dynamic_cast<const CArmedInstance *>(object.get()))) //contains army && (ai = dynamic_cast<const CArmedInstance *>(object.get()))) //contains army
{ {
for(const auto & elem : ai->Slots()) //iterate through army for(const auto & elem : ai->Slots()) //iterate through army
if(elem.second->type->idNumber == condition.objectType) //it's searched creature if(elem.second->type->getId() == condition.objectType) //it's searched creature
total += elem.second->count; total += elem.second->count;
} }
} }
@ -2584,7 +2588,7 @@ struct statsHLP
//Heroes can produce gold as well - skill, specialty or arts //Heroes can produce gold as well - skill, specialty or arts
for(const auto & h : ps->heroes) for(const auto & h : ps->heroes)
{ {
totalIncome += h->valOfBonuses(Selector::typeSubtype(Bonus::GENERATE_RESOURCE, Res::GOLD)); totalIncome += h->valOfBonuses(Selector::typeSubtype(Bonus::GENERATE_RESOURCE, GameResID(EGameResID::GOLD)));
if(!heroOrTown) if(!heroOrTown)
heroOrTown = h; heroOrTown = h;
@ -2593,7 +2597,7 @@ struct statsHLP
//Add town income of all towns //Add town income of all towns
for(const auto & t : ps->towns) for(const auto & t : ps->towns)
{ {
totalIncome += t->dailyIncome()[Res::GOLD]; totalIncome += t->dailyIncome()[EGameResID::GOLD];
if(!heroOrTown) if(!heroOrTown)
heroOrTown = t; heroOrTown = t;
@ -2618,7 +2622,7 @@ struct statsHLP
const auto * mine = dynamic_cast<const CGMine *>(object); const auto * mine = dynamic_cast<const CGMine *>(object);
assert(mine); assert(mine);
if (mine->producedResource == Res::GOLD) if (mine->producedResource == EGameResID::GOLD)
totalIncome += mine->producedQuantity; totalIncome += mine->producedQuantity;
} }
} }
@ -2677,15 +2681,15 @@ void CGameState::obtainPlayersStats(SThievesGuildInfo & tgi, int level)
} }
if(level >= 2) //gold if(level >= 2) //gold
{ {
FILL_FIELD(gold, g->second.resources[Res::GOLD]) FILL_FIELD(gold, g->second.resources[EGameResID::GOLD])
} }
if(level >= 2) //wood & ore if(level >= 2) //wood & ore
{ {
FILL_FIELD(woodOre, g->second.resources[Res::WOOD] + g->second.resources[Res::ORE]) FILL_FIELD(woodOre, g->second.resources[EGameResID::WOOD] + g->second.resources[EGameResID::ORE])
} }
if(level >= 3) //mercury, sulfur, crystal, gems if(level >= 3) //mercury, sulfur, crystal, gems
{ {
FILL_FIELD(mercSulfCrystGems, g->second.resources[Res::MERCURY] + g->second.resources[Res::SULFUR] + g->second.resources[Res::CRYSTAL] + g->second.resources[Res::GEMS]) FILL_FIELD(mercSulfCrystGems, g->second.resources[EGameResID::MERCURY] + g->second.resources[EGameResID::SULFUR] + g->second.resources[EGameResID::CRYSTAL] + g->second.resources[EGameResID::GEMS])
} }
if(level >= 3) //obelisks found if(level >= 3) //obelisks found
{ {
@ -2744,8 +2748,8 @@ void CGameState::obtainPlayersStats(SThievesGuildInfo & tgi, int level)
{ {
for(const auto & it : elem->Slots()) for(const auto & it : elem->Slots())
{ {
int toCmp = it.second->type->idNumber; //ID of creature we should compare with the best one int toCmp = it.second->type->getId(); //ID of creature we should compare with the best one
if(bestCre == -1 || VLC->creh->objects[bestCre]->AIValue < VLC->creh->objects[toCmp]->AIValue) if(bestCre == -1 || VLC->creh->objects[bestCre]->getAIValue() < VLC->creh->objects[toCmp]->getAIValue())
{ {
bestCre = toCmp; bestCre = toCmp;
} }
@ -3138,7 +3142,7 @@ void InfoAboutTown::initFromTown(const CGTownInstance *t, bool detailed)
//include details about hero //include details about hero
details = new Details(); details = new Details();
TResources income = t->dailyIncome(); TResources income = t->dailyIncome();
details->goldIncome = income[Res::GOLD]; details->goldIncome = income[EGameResID::GOLD];
details->customRes = t->hasBuilt(BuildingID::RESOURCE_SILO); details->customRes = t->hasBuilt(BuildingID::RESOURCE_SILO);
details->hallLevel = t->hallLevel(); details->hallLevel = t->hallLevel();
details->garrisonedHero = t->garrisonHero; details->garrisonedHero = t->garrisonHero;
@ -3169,12 +3173,12 @@ int ArmyDescriptor::getStrength() const
if(isDetailed) if(isDetailed)
{ {
for(const auto & elem : *this) for(const auto & elem : *this)
ret += elem.second.type->AIValue * elem.second.count; ret += elem.second.type->getAIValue() * elem.second.count;
} }
else else
{ {
for(const auto & elem : *this) for(const auto & elem : *this)
ret += elem.second.type->AIValue * CCreature::estimateCreatureCount(elem.second.count); ret += elem.second.type->getAIValue() * CCreature::estimateCreatureCount(elem.second.count);
} }
return static_cast<int>(ret); return static_cast<int>(ret);
} }

View File

@ -164,7 +164,7 @@ private:
{ {
} }
si32 intValue; // uses EResult si32 intValue; // uses EResultult
}; };
/*static std::ostream & operator<<(std::ostream & os, const EVictoryLossCheckResult & victoryLossCheckResult) /*static std::ostream & operator<<(std::ostream & os, const EVictoryLossCheckResult & victoryLossCheckResult)

View File

@ -529,7 +529,7 @@ static std::vector<std::shared_ptr<Bonus>> createCreatureSpecialty(CreatureID ba
for(CreatureID cid : targets) for(CreatureID cid : targets)
{ {
const CCreature &specCreature = *VLC->creh->objects[cid]; const CCreature &specCreature = *VLC->creh->objects[cid];
int stepSize = specCreature.level ? specCreature.level : 5; int stepSize = specCreature.getLevel() ? specCreature.getLevel() : 5;
{ {
std::shared_ptr<Bonus> bonus = std::make_shared<Bonus>(); std::shared_ptr<Bonus> bonus = std::make_shared<Bonus>();

View File

@ -86,7 +86,7 @@ bool PlayerState::isHuman() const
return human; return human;
} }
const IBonusBearer * PlayerState::accessBonuses() const const IBonusBearer * PlayerState::getBonusBearer() const
{ {
return this; return this;
} }

View File

@ -48,7 +48,7 @@ public:
PlayerColor getId() const override; PlayerColor getId() const override;
TeamID getTeam() const override; TeamID getTeam() const override;
bool isHuman() const override; bool isHuman() const override;
const IBonusBearer * accessBonuses() const override; const IBonusBearer * getBonusBearer() const override;
int getResourceAmount(int type) const override; int getResourceAmount(int type) const override;
int32_t getIndex() const override; int32_t getIndex() const override;

View File

@ -88,7 +88,7 @@ ui32 CStack::level() const
if(base) if(base)
return base->getLevel(); //creature or commander return base->getLevel(); //creature or commander
else else
return std::max(1, static_cast<int>(getCreature()->level)); //war machine, clone etc return std::max(1, static_cast<int>(getCreature()->getLevel())); //war machine, clone etc
} }
si32 CStack::magicResistance() const si32 CStack::magicResistance() const
@ -342,7 +342,7 @@ bool CStack::unitHasAmmoCart(const battle::Unit * unit) const
{ {
for(const CStack * st : battle->stacks) for(const CStack * st : battle->stacks)
{ {
if(battle->battleMatchOwner(st, unit, true) && st->getCreature()->idNumber == CreatureID::AMMO_CART) if(battle->battleMatchOwner(st, unit, true) && st->getCreature()->getId() == CreatureID::AMMO_CART)
{ {
return st->alive(); return st->alive();
} }

View File

@ -24,6 +24,7 @@
#include "mapObjects/CObjectClassesHandler.h" #include "mapObjects/CObjectClassesHandler.h"
#include "mapObjects/CObjectHandler.h" #include "mapObjects/CObjectHandler.h"
#include "HeroBonus.h" #include "HeroBonus.h"
#include "ResourceSet.h"
VCMI_LIB_NAMESPACE_BEGIN VCMI_LIB_NAMESPACE_BEGIN
@ -635,21 +636,21 @@ void CTownHandler::loadBuilding(CTown * town, const std::string & stringID, cons
if(!ret->produce.nonZero()) if(!ret->produce.nonZero())
{ {
switch (ret->bid) { switch (ret->bid) {
break; case BuildingID::VILLAGE_HALL: ret->produce[Res::GOLD] = 500; break; case BuildingID::VILLAGE_HALL: ret->produce[EGameResID::GOLD] = 500;
break; case BuildingID::TOWN_HALL : ret->produce[Res::GOLD] = 1000; break; case BuildingID::TOWN_HALL : ret->produce[EGameResID::GOLD] = 1000;
break; case BuildingID::CITY_HALL : ret->produce[Res::GOLD] = 2000; break; case BuildingID::CITY_HALL : ret->produce[EGameResID::GOLD] = 2000;
break; case BuildingID::CAPITOL : ret->produce[Res::GOLD] = 4000; break; case BuildingID::CAPITOL : ret->produce[EGameResID::GOLD] = 4000;
break; case BuildingID::GRAIL : ret->produce[Res::GOLD] = 5000; break; case BuildingID::GRAIL : ret->produce[EGameResID::GOLD] = 5000;
break; case BuildingID::RESOURCE_SILO : break; case BuildingID::RESOURCE_SILO :
{ {
switch (ret->town->primaryRes) switch (ret->town->primaryRes.toEnum())
{ {
case Res::GOLD: case EGameResID::GOLD:
ret->produce[ret->town->primaryRes] = 500; ret->produce[ret->town->primaryRes] = 500;
break; break;
case Res::WOOD_AND_ORE: case EGameResID::WOOD_AND_ORE:
ret->produce[Res::WOOD] = 1; ret->produce[EGameResID::WOOD] = 1;
ret->produce[Res::ORE] = 1; ret->produce[EGameResID::ORE] = 1;
break; break;
default: default:
ret->produce[ret->town->primaryRes] = 1; ret->produce[ret->town->primaryRes] = 1;
@ -880,9 +881,9 @@ void CTownHandler::loadTown(CTown * town, const JsonNode & source)
{ {
const auto * resIter = boost::find(GameConstants::RESOURCE_NAMES, source["primaryResource"].String()); const auto * resIter = boost::find(GameConstants::RESOURCE_NAMES, source["primaryResource"].String());
if(resIter == std::end(GameConstants::RESOURCE_NAMES)) if(resIter == std::end(GameConstants::RESOURCE_NAMES))
town->primaryRes = Res::WOOD_AND_ORE; //Wood + Ore town->primaryRes = GameResID(EGameResID::WOOD_AND_ORE); //Wood + Ore
else else
town->primaryRes = static_cast<ui16>(resIter - std::begin(GameConstants::RESOURCE_NAMES)); town->primaryRes = GameResID(resIter - std::begin(GameConstants::RESOURCE_NAMES));
warMachinesToLoad[town] = source["warMachine"]; warMachinesToLoad[town] = source["warMachine"];

View File

@ -271,7 +271,7 @@ public:
// should be removed at least from configs in favor of auto-detection // should be removed at least from configs in favor of auto-detection
std::map<int,int> hordeLvl; //[0] - first horde building creature level; [1] - second horde building (-1 if not present) std::map<int,int> hordeLvl; //[0] - first horde building creature level; [1] - second horde building (-1 if not present)
ui32 mageLevel; //max available mage guild level ui32 mageLevel; //max available mage guild level
ui16 primaryRes; GameResID primaryRes;
ArtifactID warMachine; ArtifactID warMachine;
SpellID moatAbility; SpellID moatAbility;
// default chance for hero of specific class to appear in tavern, if field "tavern" was not set // default chance for hero of specific class to appear in tavern, if field "tavern" was not set

View File

@ -205,6 +205,11 @@ public:
bool operator > (const BaseForID & b) const { return num > b.num; } bool operator > (const BaseForID & b) const { return num > b.num; }
BaseForID & operator++() { ++num; return *this; } BaseForID & operator++() { ++num; return *this; }
operator NumericType() const
{
return num;
}
}; };
template < typename T> template < typename T>
@ -267,6 +272,11 @@ public:
++num; ++num;
return ret; return ret;
} }
operator NumericType() const
{
return num;
}
}; };

View File

@ -1775,7 +1775,7 @@ BonusParams::BonusParams(std::string deprecatedTypeStr, std::string deprecatedSu
else if(deprecatedSubtype == SecondarySkill::ESTATES || deprecatedSubtypeStr == "skill.estates") else if(deprecatedSubtype == SecondarySkill::ESTATES || deprecatedSubtypeStr == "skill.estates")
{ {
type = Bonus::GENERATE_RESOURCE; type = Bonus::GENERATE_RESOURCE;
subtype = Res::GOLD; subtype = GameResID(EGameResID::GOLD);
subtypeRelevant = true; subtypeRelevant = true;
} }
else if(deprecatedSubtype == SecondarySkill::AIR_MAGIC || deprecatedSubtypeStr == "skill.airMagic") else if(deprecatedSubtype == SecondarySkill::AIR_MAGIC || deprecatedSubtypeStr == "skill.airMagic")
@ -2380,7 +2380,7 @@ CreatureFactionLimiter::CreatureFactionLimiter():
ILimiter::EDecision CreatureFactionLimiter::limit(const BonusLimitationContext &context) const ILimiter::EDecision CreatureFactionLimiter::limit(const BonusLimitationContext &context) const
{ {
const CCreature *c = retrieveCreature(&context.node); const CCreature *c = retrieveCreature(&context.node);
auto accept = c && c->faction == faction; auto accept = c && c->getFactionIndex() == faction;
return accept ? ILimiter::EDecision::ACCEPT : ILimiter::EDecision::DISCARD; //drop bonus for non-creatures or non-native residents return accept ? ILimiter::EDecision::ACCEPT : ILimiter::EDecision::DISCARD; //drop bonus for non-creatures or non-native residents
} }
@ -2731,7 +2731,7 @@ std::shared_ptr<Bonus> TimesStackLevelUpdater::createUpdatedBonus(const std::sha
//otherwise we'd end up multiplying twice //otherwise we'd end up multiplying twice
if(stack.base == nullptr) if(stack.base == nullptr)
{ {
int level = stack.type->level; int level = stack.type->getLevel();
std::shared_ptr<Bonus> newBonus = std::make_shared<Bonus>(*b); std::shared_ptr<Bonus> newBonus = std::make_shared<Bonus>(*b);
newBonus->val *= level; newBonus->val *= level;
return newBonus; return newBonus;

View File

@ -93,7 +93,7 @@ public:
virtual void showGarrisonDialog(ObjectInstanceID upobj, ObjectInstanceID hid, bool removableUnits) =0; //cb will be called when player closes garrison window virtual void showGarrisonDialog(ObjectInstanceID upobj, ObjectInstanceID hid, bool removableUnits) =0; //cb will be called when player closes garrison window
virtual void showTeleportDialog(TeleportDialog *iw) =0; virtual void showTeleportDialog(TeleportDialog *iw) =0;
virtual void showThievesGuildWindow(PlayerColor player, ObjectInstanceID requestingObjId) =0; virtual void showThievesGuildWindow(PlayerColor player, ObjectInstanceID requestingObjId) =0;
virtual void giveResource(PlayerColor player, Res::ERes which, int val)=0; virtual void giveResource(PlayerColor player, GameResID which, int val)=0;
virtual void giveResources(PlayerColor player, TResources resources)=0; virtual void giveResources(PlayerColor player, TResources resources)=0;
virtual void giveCreatures(const CArmedInstance *objid, const CGHeroInstance * h, const CCreatureSet &creatures, bool remove) =0; virtual void giveCreatures(const CArmedInstance *objid, const CGHeroInstance * h, const CCreatureSet &creatures, bool remove) =0;

View File

@ -1759,7 +1759,7 @@ void RebalanceStacks::applyGs(CGameState * gs)
else //split stack to an empty slot else //split stack to an empty slot
{ {
src.army->changeStackCount(src.slot, -count); src.army->changeStackCount(src.slot, -count);
dst.army->addToSlot(dst.slot, srcType->idNumber, count, false); dst.army->addToSlot(dst.slot, srcType->getId(), count, false);
if (stackExp) if (stackExp)
dst.army->setStackExp(dst.slot, src.army->getStackExperience(src.slot)); dst.army->setStackExp(dst.slot, src.army->getStackExperience(src.slot));
} }
@ -2508,7 +2508,7 @@ void YourTurn::applyGs(CGameState * gs) const
Component::Component(const CStackBasicDescriptor & stack) Component::Component(const CStackBasicDescriptor & stack)
: id(EComponentType::CREATURE) : id(EComponentType::CREATURE)
, subtype(stack.type->idNumber) , subtype(stack.type->getId())
, val(stack.count) , val(stack.count)
{ {
} }

View File

@ -19,26 +19,26 @@
VCMI_LIB_NAMESPACE_BEGIN VCMI_LIB_NAMESPACE_BEGIN
Res::ResourceSet::ResourceSet(const JsonNode & node) ResourceSet::ResourceSet(const JsonNode & node)
{ {
for(auto i = 0; i < GameConstants::RESOURCE_QUANTITY; i++) for(auto i = 0; i < GameConstants::RESOURCE_QUANTITY; i++)
container[i] = static_cast<int>(node[GameConstants::RESOURCE_NAMES[i]].Float()); container[i] = static_cast<int>(node[GameConstants::RESOURCE_NAMES[i]].Float());
} }
Res::ResourceSet::ResourceSet(TResource wood, TResource mercury, TResource ore, TResource sulfur, TResource crystal, ResourceSet::ResourceSet(TResource wood, TResource mercury, TResource ore, TResource sulfur, TResource crystal,
TResource gems, TResource gold, TResource mithril) TResource gems, TResource gold, TResource mithril)
{ {
container[Res::WOOD] = wood; container[GameResID(EGameResID::WOOD)] = wood;
container[Res::MERCURY] = mercury; container[GameResID(EGameResID::MERCURY)] = mercury;
container[Res::ORE] = ore; container[GameResID(EGameResID::ORE)] = ore;
container[Res::SULFUR] = sulfur; container[GameResID(EGameResID::SULFUR)] = sulfur;
container[Res::CRYSTAL] = crystal; container[GameResID(EGameResID::CRYSTAL)] = crystal;
container[Res::GEMS] = gems; container[GameResID(EGameResID::GEMS)] = gems;
container[Res::GOLD] = gold; container[GameResID(EGameResID::GOLD)] = gold;
container[Res::MITHRIL] = mithril; container[GameResID(EGameResID::MITHRIL)] = mithril;
} }
void Res::ResourceSet::serializeJson(JsonSerializeFormat & handler, const std::string & fieldName) void ResourceSet::serializeJson(JsonSerializeFormat & handler, const std::string & fieldName)
{ {
if(handler.saving && !nonZero()) if(handler.saving && !nonZero())
return; return;
@ -49,7 +49,7 @@ void Res::ResourceSet::serializeJson(JsonSerializeFormat & handler, const std::s
handler.serializeInt(GameConstants::RESOURCE_NAMES[idx], this->operator[](idx), 0); handler.serializeInt(GameConstants::RESOURCE_NAMES[idx], this->operator[](idx), 0);
} }
bool Res::ResourceSet::nonZero() const bool ResourceSet::nonZero() const
{ {
for(const auto & elem : *this) for(const auto & elem : *this)
if(elem) if(elem)
@ -58,35 +58,25 @@ bool Res::ResourceSet::nonZero() const
return false; return false;
} }
void Res::ResourceSet::amax(const TResourceCap &val) void ResourceSet::amax(const TResourceCap &val)
{ {
for(auto & elem : *this) for(auto & elem : *this)
vstd::amax(elem, val); vstd::amax(elem, val);
} }
void Res::ResourceSet::amin(const TResourceCap &val) void ResourceSet::amin(const TResourceCap &val)
{ {
for(auto & elem : *this) for(auto & elem : *this)
vstd::amin(elem, val); vstd::amin(elem, val);
} }
void Res::ResourceSet::positive() void ResourceSet::positive()
{ {
for(auto & elem : *this) for(auto & elem : *this)
vstd::amax(elem, 0); vstd::amax(elem, 0);
} }
bool Res::ResourceSet::canBeAfforded(const ResourceSet &res) const static bool canAfford(const ResourceSet &res, const ResourceSet &price)
{
return Res::canAfford(res, *this);
}
bool Res::ResourceSet::canAfford(const ResourceSet &price) const
{
return Res::canAfford(*this, price);
}
bool Res::canAfford(const ResourceSet &res, const ResourceSet &price)
{ {
assert(res.size() == price.size() && price.size() == GameConstants::RESOURCE_QUANTITY); assert(res.size() == price.size() && price.size() == GameConstants::RESOURCE_QUANTITY);
for(int i = 0; i < GameConstants::RESOURCE_QUANTITY; i++) for(int i = 0; i < GameConstants::RESOURCE_QUANTITY; i++)
@ -96,7 +86,17 @@ bool Res::canAfford(const ResourceSet &res, const ResourceSet &price)
return true; return true;
} }
TResourceCap Res::ResourceSet::marketValue() const bool ResourceSet::canBeAfforded(const ResourceSet &res) const
{
return VCMI_LIB_WRAP_NAMESPACE(canAfford(res, *this));
}
bool ResourceSet::canAfford(const ResourceSet &price) const
{
return VCMI_LIB_WRAP_NAMESPACE(canAfford(*this, price));
}
TResourceCap ResourceSet::marketValue() const
{ {
TResourceCap total = 0; TResourceCap total = 0;
for(int i = 0; i < GameConstants::RESOURCE_QUANTITY; i++) for(int i = 0; i < GameConstants::RESOURCE_QUANTITY; i++)
@ -104,7 +104,7 @@ TResourceCap Res::ResourceSet::marketValue() const
return total; return total;
} }
std::string Res::ResourceSet::toString() const std::string ResourceSet::toString() const
{ {
std::ostringstream out; std::ostringstream out;
out << "["; out << "[";
@ -117,35 +117,35 @@ std::string Res::ResourceSet::toString() const
return out.str(); return out.str();
} }
bool Res::ResourceSet::nziterator::valid() const bool ResourceSet::nziterator::valid() const
{ {
return cur.resType < GameConstants::RESOURCE_QUANTITY && cur.resVal; return cur.resType < GameConstants::RESOURCE_QUANTITY && cur.resVal;
} }
Res::ResourceSet::nziterator Res::ResourceSet::nziterator::operator++() ResourceSet::nziterator ResourceSet::nziterator::operator++()
{ {
advance(); advance();
return *this; return *this;
} }
Res::ResourceSet::nziterator Res::ResourceSet::nziterator::operator++(int) ResourceSet::nziterator ResourceSet::nziterator::operator++(int)
{ {
nziterator ret = *this; nziterator ret = *this;
advance(); advance();
return ret; return ret;
} }
const Res::ResourceSet::nziterator::ResEntry& Res::ResourceSet::nziterator::operator*() const const ResourceSet::nziterator::ResEntry& ResourceSet::nziterator::operator*() const
{ {
return cur; return cur;
} }
const Res::ResourceSet::nziterator::ResEntry * Res::ResourceSet::nziterator::operator->() const const ResourceSet::nziterator::ResEntry * ResourceSet::nziterator::operator->() const
{ {
return &cur; return &cur;
} }
void Res::ResourceSet::nziterator::advance() void ResourceSet::nziterator::advance()
{ {
do do
{ {
@ -156,11 +156,11 @@ void Res::ResourceSet::nziterator::advance()
cur.resVal = -1; cur.resVal = -1;
} }
Res::ResourceSet::nziterator::nziterator(const ResourceSet &RS) ResourceSet::nziterator::nziterator(const ResourceSet &RS)
: rs(RS) : rs(RS)
{ {
cur.resType = WOOD; cur.resType = EGameResID::WOOD;
cur.resVal = rs[WOOD]; cur.resVal = rs[EGameResID::WOOD];
if(!valid()) if(!valid())
advance(); advance();

View File

@ -11,6 +11,7 @@
#pragma once #pragma once
#include "GameConstants.h" #include "GameConstants.h"
VCMI_LIB_NAMESPACE_BEGIN VCMI_LIB_NAMESPACE_BEGIN
using TResource = int32_t; using TResource = int32_t;
@ -19,25 +20,24 @@ using TResourceCap = int64_t; //to avoid overflow when adding integers. Signed v
class JsonNode; class JsonNode;
class JsonSerializeFormat; class JsonSerializeFormat;
namespace Res class ResourceSet;
{
class ResourceSet;
bool canAfford(const ResourceSet &res, const ResourceSet &price); //can a be used to pay price b
enum ERes enum class EGameResID : int8_t
{ {
WOOD = 0, MERCURY, ORE, SULFUR, CRYSTAL, GEMS, GOLD, MITHRIL, WOOD = 0, MERCURY, ORE, SULFUR, CRYSTAL, GEMS, GOLD, MITHRIL,
WOOD_AND_ORE = 127, // special case for town bonus resource WOOD_AND_ORE = 127, // special case for town bonus resource
INVALID = -1 INVALID = -1
}; };
//class to be representing a vector of resource using GameResID = Identifier<EGameResID>;
class ResourceSet
{ //class to be representing a vector of resource
private: class ResourceSet
{
private:
std::array<TResource, GameConstants::RESOURCE_QUANTITY> container; std::array<TResource, GameConstants::RESOURCE_QUANTITY> container;
public: public:
// read resources set from json. Format example: { "gold": 500, "wood":5 } // read resources set from json. Format example: { "gold": 500, "wood":5 }
DLL_LINKAGE ResourceSet(const JsonNode & node); DLL_LINKAGE ResourceSet(const JsonNode & node);
DLL_LINKAGE ResourceSet(TResource wood = 0, TResource mercury = 0, TResource ore = 0, TResource sulfur = 0, TResource crystal = 0, DLL_LINKAGE ResourceSet(TResource wood = 0, TResource mercury = 0, TResource ore = 0, TResource sulfur = 0, TResource crystal = 0,
@ -93,14 +93,14 @@ namespace Res
using iterator = decltype(container)::iterator; using iterator = decltype(container)::iterator;
// Array-like interface // Array-like interface
TResource & operator[](Res::ERes index) TResource & operator[](GameResID index)
{ {
return operator[](static_cast<size_t>(index)); return operator[](index.getNum());
} }
const TResource & operator[](Res::ERes index) const const TResource & operator[](GameResID index) const
{ {
return operator[](static_cast<size_t>(index)); return operator[](index.getNum());
} }
TResource & operator[](size_t index) TResource & operator[](size_t index)
@ -180,8 +180,8 @@ namespace Res
return this->container == rhs.container; return this->container == rhs.container;
} }
// WARNING: comparison operators are used for "can afford" relation: a <= b means that foreach i a[i] <= b[i] // WARNING: comparison operators are used for "can afford" relation: a <= b means that foreach i a[i] <= b[i]
// that doesn't work the other way: a > b doesn't mean that a cannot be afforded with b, it's still b can afford a // that doesn't work the other way: a > b doesn't mean that a cannot be afforded with b, it's still b can afford a
// bool operator<(const ResourceSet &rhs) // bool operator<(const ResourceSet &rhs)
// { // {
// for(int i = 0; i < size(); i++) // for(int i = 0; i < size(); i++)
@ -213,7 +213,7 @@ namespace Res
{ {
struct ResEntry struct ResEntry
{ {
Res::ERes resType; GameResID resType;
TResourceCap resVal; TResourceCap resVal;
} cur; } cur;
const ResourceSet &rs; const ResourceSet &rs;
@ -226,14 +226,12 @@ namespace Res
nziterator operator++(int); nziterator operator++(int);
const ResEntry& operator*() const; const ResEntry& operator*() const;
const ResEntry* operator->() const; const ResEntry* operator->() const;
}; };
}; };
}
using TResources = Res::ResourceSet; using TResources = ResourceSet;
VCMI_LIB_NAMESPACE_END VCMI_LIB_NAMESPACE_END

View File

@ -653,7 +653,7 @@ int32_t BattleInfo::getEnchanterCounter(ui8 side) const
return sides.at(side).enchanterCounter; return sides.at(side).enchanterCounter;
} }
const IBonusBearer * BattleInfo::asBearer() const const IBonusBearer * BattleInfo::getBonusBearer() const
{ {
return this; return this;
} }

View File

@ -93,7 +93,7 @@ public:
uint32_t getCastSpells(ui8 side) const override; uint32_t getCastSpells(ui8 side) const override;
int32_t getEnchanterCounter(ui8 side) const override; int32_t getEnchanterCounter(ui8 side) const override;
const IBonusBearer * asBearer() const override; const IBonusBearer * getBonusBearer() const override;
uint32_t nextUnitId() const override; uint32_t nextUnitId() const override;

View File

@ -108,9 +108,9 @@ int32_t BattleProxy::getEnchanterCounter(ui8 side) const
return subject->battleGetEnchanterCounter(side); return subject->battleGetEnchanterCounter(side);
} }
const IBonusBearer * BattleProxy::asBearer() const const IBonusBearer * BattleProxy::getBonusBearer() const
{ {
return subject->getBattleNode(); return subject->getBonusBearer();
} }

View File

@ -50,7 +50,7 @@ public:
uint32_t getCastSpells(ui8 side) const override; uint32_t getCastSpells(ui8 side) const override;
int32_t getEnchanterCounter(ui8 side) const override; int32_t getEnchanterCounter(ui8 side) const override;
const IBonusBearer * asBearer() const override; const IBonusBearer * getBonusBearer() const override;
protected: protected:
Subject subject; Subject subject;
}; };

View File

@ -33,7 +33,7 @@ uint64_t getFightingStrength(const std::vector<const battle::Unit *> & stacks, c
for(const battle::Unit * stack : stacks) for(const battle::Unit * stack : stacks)
{ {
result += stack->creatureId().toCreature()->AIValue * stack->getCount(); result += stack->creatureId().toCreature()->getAIValue() * stack->getCount();
} }
if(hero) if(hero)

View File

@ -1721,7 +1721,7 @@ si8 CBattleInfoCallback::battleMinSpellLevel(ui8 side) const
if(const CGHeroInstance * h = battleGetFightingHero(side)) if(const CGHeroInstance * h = battleGetFightingHero(side))
node = h; node = h;
else else
node = getBattleNode(); node = getBonusBearer();
if(!node) if(!node)
return 0; return 0;
@ -1739,7 +1739,7 @@ si8 CBattleInfoCallback::battleMaxSpellLevel(ui8 side) const
if(const CGHeroInstance * h = battleGetFightingHero(side)) if(const CGHeroInstance * h = battleGetFightingHero(side))
node = h; node = h;
else else
node = getBattleNode(); node = getBonusBearer();
if(!node) if(!node)
return GameConstants::SPELL_LEVELS; return GameConstants::SPELL_LEVELS;

View File

@ -252,9 +252,9 @@ uint32_t CBattleInfoEssentials::battleCastSpells(ui8 side) const
return getBattle()->getCastSpells(side); return getBattle()->getCastSpells(side);
} }
const IBonusBearer * CBattleInfoEssentials::getBattleNode() const const IBonusBearer * CBattleInfoEssentials::getBonusBearer() const
{ {
return getBattle()->asBearer(); return getBattle()->getBonusBearer();
} }
bool CBattleInfoEssentials::battleCanFlee(const PlayerColor & player) const bool CBattleInfoEssentials::battleCanFlee(const PlayerColor & player) const

View File

@ -46,7 +46,7 @@ public:
}; };
BattlePerspective::BattlePerspective battleGetMySide() const; BattlePerspective::BattlePerspective battleGetMySide() const;
const IBonusBearer * getBattleNode() const; const IBonusBearer * getBonusBearer() const override;
TerrainId battleTerrainType() const override; TerrainId battleTerrainType() const override;
BattleField battleGetBattlefieldType() const override; BattleField battleGetBattlefieldType() const override;

View File

@ -395,22 +395,22 @@ CreatureID CUnitState::creatureId() const
int32_t CUnitState::creatureLevel() const int32_t CUnitState::creatureLevel() const
{ {
return static_cast<int32_t>(unitType()->level); return static_cast<int32_t>(unitType()->getLevel());
} }
bool CUnitState::doubleWide() const bool CUnitState::doubleWide() const
{ {
return unitType()->doubleWide; return unitType()->isDoubleWide();
} }
int32_t CUnitState::creatureCost() const int32_t CUnitState::creatureCost() const
{ {
return unitType()->cost[Res::GOLD]; return unitType()->getRecruitCost(EGameResID::GOLD);
} }
int32_t CUnitState::creatureIconIndex() const int32_t CUnitState::creatureIconIndex() const
{ {
return unitType()->iconIndex; return unitType()->getIconIndex();
} }
int32_t CUnitState::getCasterUnitId() const int32_t CUnitState::getCasterUnitId() const

View File

@ -145,7 +145,7 @@ int DamageCalculator::getActorAttackSlayer() const
int attackBonus = SpellID(SpellID::SLAYER).toSpell()->getLevelPower(spLevel); int attackBonus = SpellID(SpellID::SLAYER).toSpell()->getLevelPower(spLevel);
if(info.attacker->hasBonusOfType(Bonus::SPECIAL_PECULIAR_ENCHANT, SpellID::SLAYER)) if(info.attacker->hasBonusOfType(Bonus::SPECIAL_PECULIAR_ENCHANT, SpellID::SLAYER))
{ {
ui8 attackerTier = info.attacker->unitType()->level; ui8 attackerTier = info.attacker->unitType()->getLevel();
ui8 specialtyBonus = std::max(5 - attackerTier, 0); ui8 specialtyBonus = std::max(5 - attackerTier, 0);
attackBonus += specialtyBonus; attackBonus += specialtyBonus;
} }

View File

@ -13,6 +13,8 @@
#include "GameConstants.h" #include "GameConstants.h"
#include "BattleHex.h" #include "BattleHex.h"
#include <vcmi/Entity.h>
VCMI_LIB_NAMESPACE_BEGIN VCMI_LIB_NAMESPACE_BEGIN
struct CObstacleInstance; struct CObstacleInstance;
@ -45,7 +47,7 @@ namespace scripting
} }
#endif #endif
class DLL_LINKAGE IBattleInfoCallback class DLL_LINKAGE IBattleInfoCallback : public WithBonuses
{ {
public: public:
#if SCRIPTING_ENABLED #if SCRIPTING_ENABLED

View File

@ -30,7 +30,7 @@ namespace battle
class UnitInfo; class UnitInfo;
} }
class DLL_LINKAGE IBattleInfo class DLL_LINKAGE IBattleInfo : public WithBonuses
{ {
public: public:
using ObstacleCList = std::vector<std::shared_ptr<const CObstacleInstance>>; using ObstacleCList = std::vector<std::shared_ptr<const CObstacleInstance>>;
@ -62,8 +62,6 @@ public:
virtual ui8 getTacticDist() const = 0; virtual ui8 getTacticDist() const = 0;
virtual ui8 getTacticsSide() const = 0; virtual ui8 getTacticsSide() const = 0;
virtual const IBonusBearer * asBearer() const = 0;
virtual uint32_t nextUnitId() const = 0; virtual uint32_t nextUnitId() const = 0;
virtual int64_t getActualDamage(const DamageRange & damage, int32_t attackerCount, vstd::RNG & rng) const = 0; virtual int64_t getActualDamage(const DamageRange & damage, int32_t attackerCount, vstd::RNG & rng) const = 0;

View File

@ -76,7 +76,7 @@ void CArmedInstance::updateMoraleBonusFromArmy()
const CStackInstance * inst = slot.second; const CStackInstance * inst = slot.second;
const CCreature * creature = VLC->creh->objects[inst->getCreatureID()]; const CCreature * creature = VLC->creh->objects[inst->getCreatureID()];
factions.insert(creature->faction); factions.insert(creature->getFactionIndex());
// Check for undead flag instead of faction (undead mummies are neutral) // Check for undead flag instead of faction (undead mummies are neutral)
if (!hasUndead) if (!hasUndead)
{ {

View File

@ -229,7 +229,7 @@ void CBank::doVisit(const CGHeroInstance * hero) const
loot << "%d %s"; loot << "%d %s";
loot.addReplacement(iw.components.back().val); loot.addReplacement(iw.components.back().val);
loot.addReplacement(MetaString::RES_NAMES, iw.components.back().subtype); loot.addReplacement(MetaString::RES_NAMES, iw.components.back().subtype);
cb->giveResource(hero->getOwner(), static_cast<Res::ERes>(it), bc->resources[it]); cb->giveResource(hero->getOwner(), static_cast<EGameResID>(it), bc->resources[it]);
} }
} }
//grant artifacts //grant artifacts
@ -246,9 +246,9 @@ void CBank::doVisit(const CGHeroInstance * hero) const
iw.text.addTxt(MetaString::ADVOB_TXT, textID); iw.text.addTxt(MetaString::ADVOB_TXT, textID);
if (textID == 34) if (textID == 34)
{ {
const CCreature * strongest = boost::range::max_element(bc->guards, [](const CStackBasicDescriptor & a, const CStackBasicDescriptor & b) const auto * strongest = boost::range::max_element(bc->guards, [](const CStackBasicDescriptor & a, const CStackBasicDescriptor & b)
{ {
return a.type->fightValue < b.type->fightValue; return a.type->getFightValue() < b.type->getFightValue();
})->type; })->type;
iw.text.addReplacement(MetaString::CRE_PL_NAMES, strongest->getId()); iw.text.addReplacement(MetaString::CRE_PL_NAMES, strongest->getId());
@ -305,7 +305,7 @@ void CBank::doVisit(const CGHeroInstance * hero) const
CCreatureSet ourArmy; CCreatureSet ourArmy;
for(const auto & slot : bc->creatures) for(const auto & slot : bc->creatures)
{ {
ourArmy.addToSlot(ourArmy.getSlotFor(slot.type->idNumber), slot.type->getId(), slot.count); ourArmy.addToSlot(ourArmy.getSlotFor(slot.type->getId()), slot.type->getId(), slot.count);
} }
for(const auto & elem : ourArmy.Slots()) for(const auto & elem : ourArmy.Slots())

View File

@ -325,7 +325,7 @@ void CGHeroInstance::initHero(CRandomGenerator & rand)
if (VLC->settings()->getBoolean(EGameSettings::MODULE_COMMANDERS) && !commander) if (VLC->settings()->getBoolean(EGameSettings::MODULE_COMMANDERS) && !commander)
{ {
commander = new CCommanderInstance(type->heroClass->commander->idNumber); commander = new CCommanderInstance(type->heroClass->commander->getId());
commander->setArmyObj (castToArmyObj()); //TODO: separate function for setting commanders commander->setArmyObj (castToArmyObj()); //TODO: separate function for setting commanders
commander->giveStackExp (exp); //after our exp is set commander->giveStackExp (exp); //after our exp is set
} }
@ -790,7 +790,7 @@ CStackBasicDescriptor CGHeroInstance::calculateNecromancy (const BattleResult &b
}; };
int maxCasualtyLevel = 1; int maxCasualtyLevel = 1;
for(const auto & casualty : casualties) for(const auto & casualty : casualties)
vstd::amax(maxCasualtyLevel, VLC->creh->objects[casualty.first]->level); vstd::amax(maxCasualtyLevel, VLC->creatures()->getByIndex(casualty.first)->getLevel());
// pick best bonus available // pick best bonus available
std::shared_ptr<Bonus> topPick; std::shared_ptr<Bonus> topPick;
for(const std::shared_ptr<Bonus> & newPick : *improvedNecromancy) for(const std::shared_ptr<Bonus> & newPick : *improvedNecromancy)
@ -806,8 +806,8 @@ CStackBasicDescriptor CGHeroInstance::calculateNecromancy (const BattleResult &b
{ {
auto quality = [getCreatureID](const std::shared_ptr<Bonus> & pick) -> std::tuple<int, int, int> auto quality = [getCreatureID](const std::shared_ptr<Bonus> & pick) -> std::tuple<int, int, int>
{ {
const CCreature * c = VLC->creh->objects[getCreatureID(pick)]; const auto * c = getCreatureID(pick).toCreature();
return std::tuple<int, int, int> {c->level, static_cast<int>(c->cost.marketValue()), -pick->additionalInfo[1]}; return std::tuple<int, int, int> {c->getLevel(), static_cast<int>(c->getFullRecruitCost().marketValue()), -pick->additionalInfo[1]};
}; };
if(quality(topPick) < quality(newPick)) if(quality(topPick) < quality(newPick))
topPick = newPick; topPick = newPick;
@ -840,7 +840,7 @@ CStackBasicDescriptor CGHeroInstance::calculateNecromancy (const BattleResult &b
{ {
const CCreature * c = VLC->creh->objects[casualty.first]; const CCreature * c = VLC->creh->objects[casualty.first];
double raisedFromCasualty = std::min(c->MaxHealth() / raisedUnitHealth, 1.0) * casualty.second * necromancySkill; double raisedFromCasualty = std::min(c->MaxHealth() / raisedUnitHealth, 1.0) * casualty.second * necromancySkill;
if(c->level < requiredCasualtyLevel) if(c->getLevel() < requiredCasualtyLevel)
raisedFromCasualty *= 0.5; raisedFromCasualty *= 0.5;
raisedUnits += raisedFromCasualty; raisedUnits += raisedFromCasualty;
} }

View File

@ -50,7 +50,7 @@ bool IMarket::getOffer(int id1, int id2, int &val1, int &val2, EMarketMode::EMar
const double effectivenessArray[] = {0.0, 0.3, 0.45, 0.50, 0.65, 0.7, 0.85, 0.9, 1.0}; const double effectivenessArray[] = {0.0, 0.3, 0.45, 0.50, 0.65, 0.7, 0.85, 0.9, 1.0};
double effectiveness = effectivenessArray[std::min(getMarketEfficiency(), 8)]; double effectiveness = effectivenessArray[std::min(getMarketEfficiency(), 8)];
double r = VLC->creh->objects[id1]->cost[6]; //value of given creature in gold double r = VLC->creatures()->getByIndex(id1)->getRecruitCost(EGameResID::GOLD); //value of given creature in gold
double g = VLC->objh->resVals[id2] / effectiveness; //value of wanted resource double g = VLC->objh->resVals[id2] / effectiveness; //value of wanted resource
if(r>g) //if given resource is more expensive than wanted if(r>g) //if given resource is more expensive than wanted
@ -98,7 +98,7 @@ bool IMarket::getOffer(int id1, int id2, int &val1, int &val2, EMarketMode::EMar
case EMarketMode::CREATURE_EXP: case EMarketMode::CREATURE_EXP:
{ {
val1 = 1; val1 = 1;
val2 = (VLC->creh->objects[id1]->AIValue / 40) * 5; val2 = (VLC->creh->objects[id1]->getAIValue() / 40) * 5;
} }
break; break;
case EMarketMode::ARTIFACT_EXP: case EMarketMode::ARTIFACT_EXP:

View File

@ -263,7 +263,7 @@ void CGDwelling::newTurn(CRandomGenerator & rand) const
creaturesAccumulate = VLC->settings()->getBoolean(EGameSettings::DWELLINGS_ACCUMULATE_WHEN_NEUTRAL); creaturesAccumulate = VLC->settings()->getBoolean(EGameSettings::DWELLINGS_ACCUMULATE_WHEN_NEUTRAL);
CCreature *cre = VLC->creh->objects[creatures[i].second[0]]; CCreature *cre = VLC->creh->objects[creatures[i].second[0]];
TQuantity amount = cre->growth * (1 + cre->valOfBonuses(Bonus::CREATURE_GROWTH_PERCENT)/100) + cre->valOfBonuses(Bonus::CREATURE_GROWTH); TQuantity amount = cre->getGrowth() * (1 + cre->valOfBonuses(Bonus::CREATURE_GROWTH_PERCENT)/100) + cre->valOfBonuses(Bonus::CREATURE_GROWTH);
if (creaturesAccumulate && ID != Obj::REFUGEE_CAMP) //camp should not try to accumulate different kinds of creatures if (creaturesAccumulate && ID != Obj::REFUGEE_CAMP) //camp should not try to accumulate different kinds of creatures
sac.creatures[i].first += amount; sac.creatures[i].first += amount;
else else
@ -287,7 +287,7 @@ void CGDwelling::updateGuards() const
//default condition - creatures are of level 5 or higher //default condition - creatures are of level 5 or higher
for (auto creatureEntry : creatures) for (auto creatureEntry : creatures)
{ {
if (VLC->creh->objects[creatureEntry.second.at(0)]->level >= 5 && ID != Obj::REFUGEE_CAMP) if (VLC->creatures()->getByIndex(creatureEntry.second.at(0))->getLevel() >= 5 && ID != Obj::REFUGEE_CAMP)
{ {
guarded = true; guarded = true;
break; break;
@ -299,14 +299,14 @@ void CGDwelling::updateGuards() const
for (auto creatureEntry : creatures) for (auto creatureEntry : creatures)
{ {
const CCreature * crea = VLC->creh->objects[creatureEntry.second.at(0)]; const CCreature * crea = VLC->creh->objects[creatureEntry.second.at(0)];
SlotID slot = getSlotFor(crea->idNumber); SlotID slot = getSlotFor(crea->getId());
if (hasStackAtSlot(slot)) //stack already exists, overwrite it if (hasStackAtSlot(slot)) //stack already exists, overwrite it
{ {
ChangeStackCount csc; ChangeStackCount csc;
csc.army = this->id; csc.army = this->id;
csc.slot = slot; csc.slot = slot;
csc.count = crea->growth * 3; csc.count = crea->getGrowth() * 3;
csc.absoluteValue = true; csc.absoluteValue = true;
cb->sendAndApply(&csc); cb->sendAndApply(&csc);
} }
@ -315,8 +315,8 @@ void CGDwelling::updateGuards() const
InsertNewStack ns; InsertNewStack ns;
ns.army = this->id; ns.army = this->id;
ns.slot = slot; ns.slot = slot;
ns.type = crea->idNumber; ns.type = crea->getId();
ns.count = crea->growth * 3; ns.count = crea->getGrowth() * 3;
cb->sendAndApply(&ns); cb->sendAndApply(&ns);
} }
} }
@ -326,10 +326,10 @@ void CGDwelling::updateGuards() const
void CGDwelling::heroAcceptsCreatures( const CGHeroInstance *h) const void CGDwelling::heroAcceptsCreatures( const CGHeroInstance *h) const
{ {
CreatureID crid = creatures[0].second[0]; CreatureID crid = creatures[0].second[0];
CCreature *crs = VLC->creh->objects[crid]; auto *crs = crid.toCreature();
TQuantity count = creatures[0].first; TQuantity count = creatures[0].first;
if(crs->level == 1 && ID != Obj::REFUGEE_CAMP) //first level - creatures are for free if(crs->getLevel() == 1 && ID != Obj::REFUGEE_CAMP) //first level - creatures are for free
{ {
if(count) //there are available creatures if(count) //there are available creatures
{ {
@ -538,7 +538,7 @@ GrowthInfo CGTownInstance::getGrowthInfo(int level) const
return ret; //no dwelling return ret; //no dwelling
const CCreature *creature = VLC->creh->objects[creatures[level].second.back()]; const CCreature *creature = VLC->creh->objects[creatures[level].second.back()];
const int base = creature->growth; const int base = creature->getGrowth();
int castleBonus = 0; int castleBonus = 0;
ret.entries.emplace_back(VLC->generaltexth->allTexts[590], base); // \n\nBasic growth %d" ret.entries.emplace_back(VLC->generaltexth->allTexts[590], base); // \n\nBasic growth %d"
@ -550,11 +550,11 @@ GrowthInfo CGTownInstance::getGrowthInfo(int level) const
if(town->hordeLvl.at(0) == level)//horde 1 if(town->hordeLvl.at(0) == level)//horde 1
if(hasBuilt(BuildingID::HORDE_1)) if(hasBuilt(BuildingID::HORDE_1))
ret.entries.emplace_back(subID, BuildingID::HORDE_1, creature->hordeGrowth); ret.entries.emplace_back(subID, BuildingID::HORDE_1, creature->getHorde());
if(town->hordeLvl.at(1) == level)//horde 2 if(town->hordeLvl.at(1) == level)//horde 2
if(hasBuilt(BuildingID::HORDE_2)) if(hasBuilt(BuildingID::HORDE_2))
ret.entries.emplace_back(subID, BuildingID::HORDE_2, creature->hordeGrowth); ret.entries.emplace_back(subID, BuildingID::HORDE_2, creature->getHorde());
//statue-of-legion-like bonus: % to base+castle //statue-of-legion-like bonus: % to base+castle
TConstBonusListPtr bonuses2 = getBonuses(Selector::type()(Bonus::CREATURE_GROWTH_PERCENT)); TConstBonusListPtr bonuses2 = getBonuses(Selector::type()(Bonus::CREATURE_GROWTH_PERCENT));
@ -915,7 +915,7 @@ void CGTownInstance::newTurn(CRandomGenerator & rand) const
int resID = rand.nextInt(2, 5); //bonus to random rare resource int resID = rand.nextInt(2, 5); //bonus to random rare resource
resID = (resID==2)?1:resID; resID = (resID==2)?1:resID;
int resVal = rand.nextInt(1, 4);//with size 1..4 int resVal = rand.nextInt(1, 4);//with size 1..4
cb->giveResource(tempOwner, static_cast<Res::ERes>(resID), resVal); cb->giveResource(tempOwner, static_cast<EGameResID>(resID), resVal);
cb->setObjProperty (id, ObjProperty::BONUS_VALUE_FIRST, resID); cb->setObjProperty (id, ObjProperty::BONUS_VALUE_FIRST, resID);
cb->setObjProperty (id, ObjProperty::BONUS_VALUE_SECOND, resVal); cb->setObjProperty (id, ObjProperty::BONUS_VALUE_SECOND, resVal);
} }
@ -938,7 +938,7 @@ void CGTownInstance::newTurn(CRandomGenerator & rand) const
std::vector<SlotID> nativeCrits; //slots std::vector<SlotID> nativeCrits; //slots
for(const auto & elem : Slots()) for(const auto & elem : Slots())
{ {
if (elem.second->type->faction == subID) //native if (elem.second->type->getFactionIndex() == subID) //native
{ {
nativeCrits.push_back(elem.first); //collect matching slots nativeCrits.push_back(elem.first); //collect matching slots
} }
@ -951,7 +951,7 @@ void CGTownInstance::newTurn(CRandomGenerator & rand) const
const CCreature *c = getCreature(pos); const CCreature *c = getCreature(pos);
if (rand.nextInt(99) < 90 || c->upgrades.empty()) //increase number if no upgrade available if (rand.nextInt(99) < 90 || c->upgrades.empty()) //increase number if no upgrade available
{ {
cb->changeStackCount(sl, c->growth); cb->changeStackCount(sl, c->getGrowth());
} }
else //upgrade else //upgrade
{ {
@ -968,7 +968,7 @@ void CGTownInstance::newTurn(CRandomGenerator & rand) const
TQuantity count = creatureGrowth(i); TQuantity count = creatureGrowth(i);
if (!count) // no dwelling if (!count) // no dwelling
count = VLC->creh->objects[c]->growth; count = VLC->creh->objects[c]->getGrowth();
{//no lower tiers or above current month {//no lower tiers or above current month

View File

@ -494,8 +494,8 @@ void IBoatGenerator::getProblemText(MetaString &out, const CGHeroInstance *visit
void IShipyard::getBoatCost(TResources & cost) const void IShipyard::getBoatCost(TResources & cost) const
{ {
cost[Res::WOOD] = 10; cost[EGameResID::WOOD] = 10;
cost[Res::GOLD] = 1000; cost[EGameResID::GOLD] = 1000;
} }
IShipyard::IShipyard(const CGObjectInstance *O) IShipyard::IShipyard(const CGObjectInstance *O)

View File

@ -163,7 +163,7 @@ bool CQuest::checkQuest(const CGHeroInstance * h) const
case MISSION_ARMY: case MISSION_ARMY:
return checkMissionArmy(this, h); return checkMissionArmy(this, h);
case MISSION_RESOURCES: case MISSION_RESOURCES:
for(Res::ERes i = Res::WOOD; i <= Res::GOLD; vstd::advance(i, +1)) //including Mithril ? for(auto i = EGameResID::WOOD; i <= EGameResID::GOLD; vstd::advance(i, +1)) //including Mithril ?
{ //Quest has no direct access to callback { //Quest has no direct access to callback
if(CGHeroInstance::cb->getResource(h->tempOwner, i) < static_cast<int>(m7resources[i])) if(CGHeroInstance::cb->getResource(h->tempOwner, i) < static_cast<int>(m7resources[i]))
return false; return false;
@ -821,7 +821,7 @@ void CGSeerHut::finishQuest(const CGHeroInstance * h, ui32 accept) const
case CQuest::MISSION_RESOURCES: case CQuest::MISSION_RESOURCES:
for (int i = 0; i < 7; ++i) for (int i = 0; i < 7; ++i)
{ {
cb->giveResource(h->getOwner(), static_cast<Res::ERes>(i), -static_cast<int>(quest->m7resources[i])); cb->giveResource(h->getOwner(), static_cast<EGameResID>(i), -static_cast<int>(quest->m7resources[i]));
} }
break; break;
default: default:
@ -858,7 +858,7 @@ void CGSeerHut::completeQuest (const CGHeroInstance * h) const //reward
} }
break; break;
case RESOURCES: case RESOURCES:
cb->giveResource(h->getOwner(), static_cast<Res::ERes>(rID), rVal); cb->giveResource(h->getOwner(), static_cast<EGameResID>(rID), rVal);
break; break;
case PRIMARY_SKILL: case PRIMARY_SKILL:
cb->changePrimSkill(h, static_cast<PrimarySkill::PrimarySkill>(rID), rVal, false); cb->changePrimSkill(h, static_cast<PrimarySkill::PrimarySkill>(rID), rVal, false);

View File

@ -12,6 +12,7 @@
#include "CObjectHandler.h" #include "CObjectHandler.h"
#include "CArmedInstance.h" #include "CArmedInstance.h"
#include "../ResourceSet.h"
#include "../CCreatureSet.h" #include "../CCreatureSet.h"
#include "../NetPacksBase.h" #include "../NetPacksBase.h"
@ -58,7 +59,7 @@ public:
std::vector<ui32> m2stats; std::vector<ui32> m2stats;
std::vector<ArtifactID> m5arts; // artifact IDs. Add IDs through addArtifactID(), not directly to the field. std::vector<ArtifactID> m5arts; // artifact IDs. Add IDs through addArtifactID(), not directly to the field.
std::vector<CStackBasicDescriptor> m6creatures; //pair[cre id, cre count], CreatureSet info irrelevant std::vector<CStackBasicDescriptor> m6creatures; //pair[cre id, cre count], CreatureSet info irrelevant
std::vector<ui32> m7resources; //TODO: use resourceset? TResources m7resources;
// following fields are used only for kill creature/hero missions, the original // following fields are used only for kill creature/hero missions, the original
// objects became inaccessible after their removal, so we need to store info // objects became inaccessible after their removal, so we need to store info

View File

@ -455,7 +455,7 @@ void CRewardInfo::loadComponents(std::vector<Component> & comps,
comps.emplace_back(Component::EComponentType::SPELL, entry, 1, 0); comps.emplace_back(Component::EComponentType::SPELL, entry, 1, 0);
for(const auto & entry : creatures) for(const auto & entry : creatures)
comps.emplace_back(Component::EComponentType::CREATURE, entry.type->idNumber, entry.count, 0); comps.emplace_back(Component::EComponentType::CREATURE, entry.type->getId(), entry.count, 0);
for (size_t i=0; i<resources.size(); i++) for (size_t i=0; i<resources.size(); i++)
{ {

Some files were not shown because too many files have changed in this diff Show More