mirror of
https://github.com/vcmi/vcmi.git
synced 2025-04-23 12:08:45 +02:00
Merge remote-tracking branch 'upstream/develop' into battle-dialog
This commit is contained in:
commit
bfc75ccd39
@ -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))
|
||||||
{
|
{
|
||||||
@ -271,7 +271,7 @@ BattleAction CBattleAI::activeStack( const CStack * stack )
|
|||||||
BattleAction CBattleAI::goTowardsNearest(const CStack * stack, std::vector<BattleHex> hexes) const
|
BattleAction CBattleAI::goTowardsNearest(const CStack * stack, std::vector<BattleHex> hexes) const
|
||||||
{
|
{
|
||||||
auto reachability = cb->getReachability(stack);
|
auto reachability = cb->getReachability(stack);
|
||||||
auto avHexes = cb->battleGetAvailableHexes(reachability, stack);
|
auto avHexes = cb->battleGetAvailableHexes(reachability, stack, true);
|
||||||
|
|
||||||
if(!avHexes.size() || !hexes.size()) //we are blocked or dest is blocked
|
if(!avHexes.size() || !hexes.size()) //we are blocked or dest is blocked
|
||||||
{
|
{
|
||||||
|
@ -271,7 +271,7 @@ std::vector<const battle::Unit *> BattleExchangeEvaluator::getAdjacentUnits(cons
|
|||||||
auto hexes = stack->getSurroundingHexes();
|
auto hexes = stack->getSurroundingHexes();
|
||||||
for(auto hex : hexes)
|
for(auto hex : hexes)
|
||||||
{
|
{
|
||||||
auto neighbor = cb->battleGetStackByPos(hex);
|
auto neighbor = cb->battleGetUnitByPos(hex);
|
||||||
|
|
||||||
if(neighbor && neighbor->unitSide() == stack->unitSide() && !vstd::contains(checkedStacks, neighbor))
|
if(neighbor && neighbor->unitSide() == stack->unitSide() && !vstd::contains(checkedStacks, neighbor))
|
||||||
{
|
{
|
||||||
|
@ -15,7 +15,7 @@ PotentialTargets::PotentialTargets(const battle::Unit * attacker, const Hypothet
|
|||||||
{
|
{
|
||||||
auto attackerInfo = state.battleGetUnitByID(attacker->unitId());
|
auto attackerInfo = state.battleGetUnitByID(attacker->unitId());
|
||||||
auto reachability = state.getReachability(attackerInfo);
|
auto reachability = state.getReachability(attackerInfo);
|
||||||
auto avHexes = state.battleGetAvailableHexes(reachability, attackerInfo);
|
auto avHexes = state.battleGetAvailableHexes(reachability, attackerInfo, true);
|
||||||
|
|
||||||
//FIXME: this should part of battleGetAvailableHexes
|
//FIXME: this should part of battleGetAvailableHexes
|
||||||
bool forceTarget = false;
|
bool forceTarget = false;
|
||||||
|
@ -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
|
||||||
|
@ -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;
|
||||||
@ -1396,7 +1396,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;
|
||||||
@ -1405,10 +1405,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;
|
||||||
@ -1421,7 +1421,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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
|
@ -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;
|
||||||
|
@ -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;
|
||||||
|
@ -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)
|
||||||
{
|
{
|
||||||
|
@ -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);
|
||||||
|
|
||||||
|
@ -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)));
|
||||||
|
@ -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)
|
||||||
|
@ -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);
|
||||||
|
@ -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; }
|
||||||
|
|
||||||
|
@ -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);
|
||||||
|
|
||||||
|
@ -60,7 +60,7 @@ std::string AbstractGoal::toString() const //TODO: virtualize
|
|||||||
desc = "GATHER TROOPS";
|
desc = "GATHER TROOPS";
|
||||||
break;
|
break;
|
||||||
case GET_ART_TYPE:
|
case GET_ART_TYPE:
|
||||||
desc = "GET ARTIFACT OF TYPE " + VLC->arth->objects[aid]->getNameTranslated();
|
desc = "GET ARTIFACT OF TYPE " + VLC->artifacts()->getByIndex(aid)->getNameTranslated();
|
||||||
break;
|
break;
|
||||||
case DIG_AT_TILE:
|
case DIG_AT_TILE:
|
||||||
desc = "DIG AT TILE " + tile.toString();
|
desc = "DIG AT TILE " + tile.toString();
|
||||||
|
@ -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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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])));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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?
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -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));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -80,7 +80,7 @@ static bool willSecondHexBlockMoreEnemyShooters(const BattleHex &h1, const Battl
|
|||||||
for(int i = 0; i < 2; i++)
|
for(int i = 0; i < 2; i++)
|
||||||
{
|
{
|
||||||
for (auto & neighbour : (i ? h2 : h1).neighbouringTiles())
|
for (auto & neighbour : (i ? h2 : h1).neighbouringTiles())
|
||||||
if(const CStack * s = cbc->battleGetStackByPos(neighbour))
|
if(const auto * s = cbc->battleGetUnitByPos(neighbour))
|
||||||
if(s->isShooter())
|
if(s->isShooter())
|
||||||
shooters[i]++;
|
shooters[i]++;
|
||||||
}
|
}
|
||||||
@ -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};
|
||||||
@ -120,7 +120,7 @@ BattleAction CStupidAI::activeStack( const CStack * stack )
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
std::vector<BattleHex> avHexes = cb->battleGetAvailableHexes(stack);
|
std::vector<BattleHex> avHexes = cb->battleGetAvailableHexes(stack, true);
|
||||||
|
|
||||||
for (BattleHex hex : avHexes)
|
for (BattleHex hex : avHexes)
|
||||||
{
|
{
|
||||||
@ -238,7 +238,7 @@ void CStupidAI::print(const std::string &text) const
|
|||||||
BattleAction CStupidAI::goTowards(const CStack * stack, std::vector<BattleHex> hexes) const
|
BattleAction CStupidAI::goTowards(const CStack * stack, std::vector<BattleHex> hexes) const
|
||||||
{
|
{
|
||||||
auto reachability = cb->getReachability(stack);
|
auto reachability = cb->getReachability(stack);
|
||||||
auto avHexes = cb->battleGetAvailableHexes(reachability, stack);
|
auto avHexes = cb->battleGetAvailableHexes(reachability, stack, false);
|
||||||
|
|
||||||
if(!avHexes.size() || !hexes.size()) //we are blocked or dest is blocked
|
if(!avHexes.size() || !hexes.size()) //we are blocked or dest is blocked
|
||||||
{
|
{
|
||||||
|
@ -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
|
||||||
{
|
{
|
||||||
|
@ -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);
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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);
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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])));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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?
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
|
@ -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:
|
||||||
|
@ -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;
|
||||||
|
@ -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];
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
@ -2123,10 +2123,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;
|
||||||
@ -2180,7 +2180,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;
|
||||||
@ -2196,15 +2196,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
|
||||||
@ -2826,7 +2826,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;
|
||||||
@ -2850,7 +2850,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;
|
||||||
}
|
}
|
||||||
|
@ -185,6 +185,12 @@ void CCallback::bulkMoveArtifacts(ObjectInstanceID srcHero, ObjectInstanceID dst
|
|||||||
sendRequest(&bma);
|
sendRequest(&bma);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CCallback::eraseArtifactByClient(const ArtifactLocation & al)
|
||||||
|
{
|
||||||
|
EraseArtifactByClient ea(al);
|
||||||
|
sendRequest(&ea);
|
||||||
|
}
|
||||||
|
|
||||||
bool CCallback::buildBuilding(const CGTownInstance *town, BuildingID buildingID)
|
bool CCallback::buildBuilding(const CGTownInstance *town, BuildingID buildingID)
|
||||||
{
|
{
|
||||||
if(town->tempOwner!=player)
|
if(town->tempOwner!=player)
|
||||||
|
@ -85,6 +85,7 @@ public:
|
|||||||
//virtual bool swapArtifacts(const CGHeroInstance * hero1, ui16 pos1, const CGHeroInstance * hero2, ui16 pos2)=0; //swaps artifacts between two given heroes
|
//virtual bool swapArtifacts(const CGHeroInstance * hero1, ui16 pos1, const CGHeroInstance * hero2, ui16 pos2)=0; //swaps artifacts between two given heroes
|
||||||
virtual bool swapArtifacts(const ArtifactLocation &l1, const ArtifactLocation &l2)=0;
|
virtual bool swapArtifacts(const ArtifactLocation &l1, const ArtifactLocation &l2)=0;
|
||||||
virtual bool assembleArtifacts(const CGHeroInstance * hero, ArtifactPosition artifactSlot, bool assemble, ArtifactID assembleTo)=0;
|
virtual bool assembleArtifacts(const CGHeroInstance * hero, ArtifactPosition artifactSlot, bool assemble, ArtifactID assembleTo)=0;
|
||||||
|
virtual void eraseArtifactByClient(const ArtifactLocation & al)=0;
|
||||||
virtual bool dismissCreature(const CArmedInstance *obj, SlotID stackPos)=0;
|
virtual bool dismissCreature(const CArmedInstance *obj, SlotID stackPos)=0;
|
||||||
virtual void endTurn()=0;
|
virtual void endTurn()=0;
|
||||||
virtual void buyArtifact(const CGHeroInstance *hero, ArtifactID aid)=0; //used to buy artifacts in towns (including spell book in the guild and war machines in blacksmith)
|
virtual void buyArtifact(const CGHeroInstance *hero, ArtifactID aid)=0; //used to buy artifacts in towns (including spell book in the guild and war machines in blacksmith)
|
||||||
@ -159,6 +160,7 @@ public:
|
|||||||
bool swapArtifacts(const ArtifactLocation &l1, const ArtifactLocation &l2) override;
|
bool swapArtifacts(const ArtifactLocation &l1, const ArtifactLocation &l2) override;
|
||||||
bool assembleArtifacts(const CGHeroInstance * hero, ArtifactPosition artifactSlot, bool assemble, ArtifactID assembleTo) override;
|
bool assembleArtifacts(const CGHeroInstance * hero, ArtifactPosition artifactSlot, bool assemble, ArtifactID assembleTo) override;
|
||||||
void bulkMoveArtifacts(ObjectInstanceID srcHero, ObjectInstanceID dstHero, bool swap) override;
|
void bulkMoveArtifacts(ObjectInstanceID srcHero, ObjectInstanceID dstHero, bool swap) override;
|
||||||
|
void eraseArtifactByClient(const ArtifactLocation & al) override;
|
||||||
bool buildBuilding(const CGTownInstance *town, BuildingID buildingID) override;
|
bool buildBuilding(const CGTownInstance *town, BuildingID buildingID) override;
|
||||||
void recruitCreatures(const CGDwelling * obj, const CArmedInstance * dst, CreatureID ID, ui32 amount, si32 level=-1) override;
|
void recruitCreatures(const CGDwelling * obj, const CArmedInstance * dst, CreatureID ID, ui32 amount, si32 level=-1) override;
|
||||||
bool dismissCreature(const CArmedInstance *obj, SlotID stackPos) override;
|
bool dismissCreature(const CArmedInstance *obj, SlotID stackPos) override;
|
||||||
|
@ -61,6 +61,8 @@
|
|||||||
"description": "VCMI Linux GCC",
|
"description": "VCMI Linux GCC",
|
||||||
"inherits": "linux-release",
|
"inherits": "linux-release",
|
||||||
"cacheVariables": {
|
"cacheVariables": {
|
||||||
|
"ENABLE_LUA" : "ON",
|
||||||
|
"ENABLE_PCH" : "OFF",
|
||||||
"CMAKE_C_COMPILER": "/usr/bin/gcc",
|
"CMAKE_C_COMPILER": "/usr/bin/gcc",
|
||||||
"CMAKE_CXX_COMPILER": "/usr/bin/g++"
|
"CMAKE_CXX_COMPILER": "/usr/bin/g++"
|
||||||
}
|
}
|
||||||
|
8
Global.h
8
Global.h
@ -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
|
||||||
|
|
||||||
/* ---------------------------------------------------------------------------- */
|
/* ---------------------------------------------------------------------------- */
|
||||||
@ -753,6 +753,12 @@ namespace vstd
|
|||||||
if(i < 0) return -i;
|
if(i < 0) return -i;
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///C++23
|
||||||
|
template< class Enum > constexpr std::underlying_type_t<Enum> to_underlying( Enum e ) noexcept
|
||||||
|
{
|
||||||
|
return static_cast<std::underlying_type_t<Enum>>(e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
using vstd::operator-=;
|
using vstd::operator-=;
|
||||||
|
|
||||||
|
BIN
Mods/vcmi/Data/UnitMaxMovementHighlight.png
Normal file
BIN
Mods/vcmi/Data/UnitMaxMovementHighlight.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 422 B |
BIN
Mods/vcmi/Data/UnitMovementHighlight.png
Normal file
BIN
Mods/vcmi/Data/UnitMovementHighlight.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 272 B |
@ -79,6 +79,10 @@
|
|||||||
"vcmi.battleOptions.animationsSpeed1.help": "Set animation speed to very slow",
|
"vcmi.battleOptions.animationsSpeed1.help": "Set animation speed to very slow",
|
||||||
"vcmi.battleOptions.animationsSpeed5.help": "Set animation speed to very fast",
|
"vcmi.battleOptions.animationsSpeed5.help": "Set animation speed to very fast",
|
||||||
"vcmi.battleOptions.animationsSpeed6.help": "Set animation speed to instantaneous",
|
"vcmi.battleOptions.animationsSpeed6.help": "Set animation speed to instantaneous",
|
||||||
|
"vcmi.battleOptions.touchscreenMode.hover": "Touchscreen mode",
|
||||||
|
"vcmi.battleOptions.touchscreenMode.help": "{Touchscreen mode}\n\nIf enabled, second click is required to confirm and execute action. This is more suitable for touchscreen devices.",
|
||||||
|
"vcmi.battleOptions.movementHighlightOnHover.hover": "Movement Highlight on Hover",
|
||||||
|
"vcmi.battleOptions.movementHighlightOnHover.help": "{Movement Highlight on Hover}\n\nHighlight unit's movement range when you hover over it.",
|
||||||
"vcmi.battleOptions.skipBattleIntroMusic.hover": "Skip Intro Music",
|
"vcmi.battleOptions.skipBattleIntroMusic.hover": "Skip Intro Music",
|
||||||
"vcmi.battleOptions.skipBattleIntroMusic.help": "{Skip Intro Music}\n\nAllow actions during the intro music that plays at the beginning of each battle",
|
"vcmi.battleOptions.skipBattleIntroMusic.help": "{Skip Intro Music}\n\nAllow actions during the intro music that plays at the beginning of each battle",
|
||||||
"vcmi.battleWindow.pressKeyToSkipIntro" : "Press any key to start battle immediately",
|
"vcmi.battleWindow.pressKeyToSkipIntro" : "Press any key to start battle immediately",
|
||||||
|
@ -50,6 +50,7 @@
|
|||||||
"description" : "Ключові файли необхідні для повноцінної роботи VCMI",
|
"description" : "Ключові файли необхідні для повноцінної роботи VCMI",
|
||||||
"author" : "Команда VCMI",
|
"author" : "Команда VCMI",
|
||||||
|
|
||||||
|
"skipValidation" : true,
|
||||||
"translations" : [
|
"translations" : [
|
||||||
"config/vcmi/ukrainian.json"
|
"config/vcmi/ukrainian.json"
|
||||||
]
|
]
|
||||||
|
@ -1928,7 +1928,6 @@ void CPlayerInterface::artifactPut(const ArtifactLocation &al)
|
|||||||
EVENT_HANDLER_CALLED_BY_CLIENT;
|
EVENT_HANDLER_CALLED_BY_CLIENT;
|
||||||
auto hero = boost::apply_visitor(HeroObjectRetriever(), al.artHolder);
|
auto hero = boost::apply_visitor(HeroObjectRetriever(), al.artHolder);
|
||||||
updateInfo(hero);
|
updateInfo(hero);
|
||||||
askToAssembleArtifact(al);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CPlayerInterface::artifactRemoved(const ArtifactLocation &al)
|
void CPlayerInterface::artifactRemoved(const ArtifactLocation &al)
|
||||||
|
@ -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 {};
|
||||||
@ -231,6 +231,7 @@ public:
|
|||||||
void changeObjPos(ObjectInstanceID objid, int3 newPos) override {};
|
void changeObjPos(ObjectInstanceID objid, int3 newPos) override {};
|
||||||
void sendAndApply(CPackForClient * pack) override {};
|
void sendAndApply(CPackForClient * pack) override {};
|
||||||
void heroExchange(ObjectInstanceID hero1, ObjectInstanceID hero2) override {};
|
void heroExchange(ObjectInstanceID hero1, ObjectInstanceID hero2) override {};
|
||||||
|
void castSpell(const spells::Caster * caster, SpellID spellID, const int3 &pos) override {};
|
||||||
|
|
||||||
void changeFogOfWar(int3 center, ui32 radius, PlayerColor player, bool hide) override {}
|
void changeFogOfWar(int3 center, ui32 radius, PlayerColor player, bool hide) override {}
|
||||||
void changeFogOfWar(std::unordered_set<int3, ShashInt3> & tiles, PlayerColor player, bool hide) override {}
|
void changeFogOfWar(std::unordered_set<int3, ShashInt3> & tiles, PlayerColor player, bool hide) override {}
|
||||||
|
@ -255,6 +255,8 @@ void ApplyClientNetPackVisitor::visitBulkSmartRebalanceStacks(BulkSmartRebalance
|
|||||||
void ApplyClientNetPackVisitor::visitPutArtifact(PutArtifact & pack)
|
void ApplyClientNetPackVisitor::visitPutArtifact(PutArtifact & pack)
|
||||||
{
|
{
|
||||||
callInterfaceIfPresent(cl, pack.al.owningPlayer(), &IGameEventsReceiver::artifactPut, pack.al);
|
callInterfaceIfPresent(cl, pack.al.owningPlayer(), &IGameEventsReceiver::artifactPut, pack.al);
|
||||||
|
if(pack.askAssemble)
|
||||||
|
callInterfaceIfPresent(cl, pack.al.owningPlayer(), &IGameEventsReceiver::askToAssembleArtifact, pack.al);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ApplyClientNetPackVisitor::visitEraseArtifact(EraseArtifact & pack)
|
void ApplyClientNetPackVisitor::visitEraseArtifact(EraseArtifact & pack)
|
||||||
|
@ -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));
|
||||||
|
|
||||||
|
@ -115,7 +115,9 @@ BattleActionsController::BattleActionsController(BattleInterface & owner):
|
|||||||
owner(owner),
|
owner(owner),
|
||||||
selectedStack(nullptr),
|
selectedStack(nullptr),
|
||||||
heroSpellToCast(nullptr)
|
heroSpellToCast(nullptr)
|
||||||
{}
|
{
|
||||||
|
touchscreenMode = settings["battle"]["touchscreenMode"].Bool();
|
||||||
|
}
|
||||||
|
|
||||||
void BattleActionsController::endCastingSpell()
|
void BattleActionsController::endCastingSpell()
|
||||||
{
|
{
|
||||||
@ -621,7 +623,7 @@ void BattleActionsController::actionRealize(PossiblePlayerBattleAction action, B
|
|||||||
{
|
{
|
||||||
if(owner.stacksController->getActiveStack()->doubleWide())
|
if(owner.stacksController->getActiveStack()->doubleWide())
|
||||||
{
|
{
|
||||||
std::vector<BattleHex> acc = owner.curInt->cb->battleGetAvailableHexes(owner.stacksController->getActiveStack());
|
std::vector<BattleHex> acc = owner.curInt->cb->battleGetAvailableHexes(owner.stacksController->getActiveStack(), true);
|
||||||
BattleHex shiftedDest = targetHex.cloneInDirection(owner.stacksController->getActiveStack()->destShiftDir(), false);
|
BattleHex shiftedDest = targetHex.cloneInDirection(owner.stacksController->getActiveStack()->destShiftDir(), false);
|
||||||
if(vstd::contains(acc, targetHex))
|
if(vstd::contains(acc, targetHex))
|
||||||
owner.giveCommand(EActionType::WALK, targetHex);
|
owner.giveCommand(EActionType::WALK, targetHex);
|
||||||
@ -826,6 +828,10 @@ void BattleActionsController::onHoverEnded()
|
|||||||
|
|
||||||
void BattleActionsController::onHexLeftClicked(BattleHex clickedHex)
|
void BattleActionsController::onHexLeftClicked(BattleHex clickedHex)
|
||||||
{
|
{
|
||||||
|
static BattleHex lastSelectedHex;
|
||||||
|
static BattleHex lastDirectionalHex;
|
||||||
|
static PossiblePlayerBattleAction::Actions lastSelectedAction;
|
||||||
|
|
||||||
if (owner.stacksController->getActiveStack() == nullptr)
|
if (owner.stacksController->getActiveStack() == nullptr)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@ -836,9 +842,24 @@ void BattleActionsController::onHexLeftClicked(BattleHex clickedHex)
|
|||||||
if (!actionIsLegal(action, clickedHex))
|
if (!actionIsLegal(action, clickedHex))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
actionRealize(action, clickedHex);
|
auto directionalHex = lastDirectionalHex;
|
||||||
|
if(action.get() == PossiblePlayerBattleAction::ATTACK
|
||||||
|
|| action.get() == PossiblePlayerBattleAction::WALK_AND_ATTACK
|
||||||
|
|| action.get() == PossiblePlayerBattleAction::ATTACK_AND_RETURN)
|
||||||
|
directionalHex = owner.fieldController->fromWhichHexAttack(clickedHex);
|
||||||
|
|
||||||
GH.statusbar->clear();
|
if(!touchscreenMode || (lastSelectedAction == action.get() && lastSelectedHex == clickedHex && lastDirectionalHex == directionalHex))
|
||||||
|
{
|
||||||
|
actionRealize(action, clickedHex);
|
||||||
|
|
||||||
|
GH.statusbar->clear();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
lastSelectedAction = action.get();
|
||||||
|
lastSelectedHex = clickedHex;
|
||||||
|
lastDirectionalHex = directionalHex;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void BattleActionsController::tryActivateStackSpellcasting(const CStack *casterStack)
|
void BattleActionsController::tryActivateStackSpellcasting(const CStack *casterStack)
|
||||||
@ -905,7 +926,7 @@ bool BattleActionsController::isCastingPossibleHere(const CSpell * currentSpell,
|
|||||||
|
|
||||||
bool BattleActionsController::canStackMoveHere(const CStack * stackToMove, BattleHex myNumber) const
|
bool BattleActionsController::canStackMoveHere(const CStack * stackToMove, BattleHex myNumber) const
|
||||||
{
|
{
|
||||||
std::vector<BattleHex> acc = owner.curInt->cb->battleGetAvailableHexes(stackToMove);
|
std::vector<BattleHex> acc = owner.curInt->cb->battleGetAvailableHexes(stackToMove, false);
|
||||||
BattleHex shiftedDest = myNumber.cloneInDirection(stackToMove->destShiftDir(), false);
|
BattleHex shiftedDest = myNumber.cloneInDirection(stackToMove->destShiftDir(), false);
|
||||||
|
|
||||||
if (vstd::contains(acc, myNumber))
|
if (vstd::contains(acc, myNumber))
|
||||||
@ -994,3 +1015,8 @@ void BattleActionsController::pushFrontPossibleAction(PossiblePlayerBattleAction
|
|||||||
{
|
{
|
||||||
possibleActions.insert(possibleActions.begin(), action);
|
possibleActions.insert(possibleActions.begin(), action);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void BattleActionsController::setTouchScreenMode(bool enabled)
|
||||||
|
{
|
||||||
|
touchscreenMode = enabled;
|
||||||
|
}
|
||||||
|
@ -35,6 +35,9 @@ class BattleActionsController
|
|||||||
{
|
{
|
||||||
BattleInterface & owner;
|
BattleInterface & owner;
|
||||||
|
|
||||||
|
/// mouse or touchscreen click mode
|
||||||
|
bool touchscreenMode = false;
|
||||||
|
|
||||||
/// all actions possible to call at the moment by player
|
/// all actions possible to call at the moment by player
|
||||||
std::vector<PossiblePlayerBattleAction> possibleActions;
|
std::vector<PossiblePlayerBattleAction> possibleActions;
|
||||||
|
|
||||||
@ -129,4 +132,5 @@ public:
|
|||||||
/// inserts possible action in the beggining in order to prioritize it
|
/// inserts possible action in the beggining in order to prioritize it
|
||||||
void pushFrontPossibleAction(PossiblePlayerBattleAction);
|
void pushFrontPossibleAction(PossiblePlayerBattleAction);
|
||||||
|
|
||||||
|
void setTouchScreenMode(bool enabled);
|
||||||
};
|
};
|
||||||
|
@ -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();
|
||||||
@ -970,13 +970,13 @@ bool EffectAnimation::init()
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
const CStack * destStack = owner.getCurrentPlayerInterface()->cb->battleGetStackByPos(battlehexes[i], false);
|
const auto * destStack = owner.getCurrentPlayerInterface()->cb->battleGetUnitByPos(battlehexes[i], false);
|
||||||
Rect tilePos = owner.fieldController->hexPositionLocal(battlehexes[i]);
|
Rect tilePos = owner.fieldController->hexPositionLocal(battlehexes[i]);
|
||||||
|
|
||||||
be.pos.x = tilePos.x + tilePos.w/2 - first->width()/2;
|
be.pos.x = tilePos.x + tilePos.w/2 - first->width()/2;
|
||||||
|
|
||||||
if(destStack && destStack->doubleWide()) // Correction for 2-hex creatures.
|
if(destStack && destStack->doubleWide()) // Correction for 2-hex creatures.
|
||||||
be.pos.x += (destStack->side == BattleSide::ATTACKER ? -1 : 1)*tilePos.w/2;
|
be.pos.x += (destStack->unitSide() == BattleSide::ATTACKER ? -1 : 1)*tilePos.w/2;
|
||||||
|
|
||||||
if (alignToBottom())
|
if (alignToBottom())
|
||||||
be.pos.y = tilePos.y + tilePos.h - first->height();
|
be.pos.y = tilePos.y + tilePos.h - first->height();
|
||||||
|
@ -44,6 +44,8 @@ BattleFieldController::BattleFieldController(BattleInterface & owner):
|
|||||||
//preparing cells and hexes
|
//preparing cells and hexes
|
||||||
cellBorder = IImage::createFromFile("CCELLGRD.BMP", EImageBlitMode::COLORKEY);
|
cellBorder = IImage::createFromFile("CCELLGRD.BMP", EImageBlitMode::COLORKEY);
|
||||||
cellShade = IImage::createFromFile("CCELLSHD.BMP");
|
cellShade = IImage::createFromFile("CCELLSHD.BMP");
|
||||||
|
cellUnitMovementHighlight = IImage::createFromFile("UnitMovementHighlight.PNG", EImageBlitMode::COLORKEY);
|
||||||
|
cellUnitMaxMovementHighlight = IImage::createFromFile("UnitMaxMovementHighlight.PNG", EImageBlitMode::COLORKEY);
|
||||||
|
|
||||||
if(!owner.siegeController)
|
if(!owner.siegeController)
|
||||||
{
|
{
|
||||||
@ -138,7 +140,6 @@ void BattleFieldController::showBackground(Canvas & canvas)
|
|||||||
showBackgroundImage(canvas);
|
showBackgroundImage(canvas);
|
||||||
|
|
||||||
showHighlightedHexes(canvas);
|
showHighlightedHexes(canvas);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void BattleFieldController::showBackgroundImage(Canvas & canvas)
|
void BattleFieldController::showBackgroundImage(Canvas & canvas)
|
||||||
@ -172,32 +173,34 @@ void BattleFieldController::redrawBackgroundWithHexes()
|
|||||||
{
|
{
|
||||||
const CStack *activeStack = owner.stacksController->getActiveStack();
|
const CStack *activeStack = owner.stacksController->getActiveStack();
|
||||||
std::vector<BattleHex> attackableHexes;
|
std::vector<BattleHex> attackableHexes;
|
||||||
if (activeStack)
|
if(activeStack)
|
||||||
occupyableHexes = owner.curInt->cb->battleGetAvailableHexes(activeStack, true, &attackableHexes);
|
occupiableHexes = owner.curInt->cb->battleGetAvailableHexes(activeStack, true, true, &attackableHexes);
|
||||||
|
|
||||||
//prepare background graphic with hexes and shaded hexes
|
// prepare background graphic with hexes and shaded hexes
|
||||||
backgroundWithHexes->draw(background, Point(0,0));
|
backgroundWithHexes->draw(background, Point(0,0));
|
||||||
owner.obstacleController->showAbsoluteObstacles(*backgroundWithHexes);
|
owner.obstacleController->showAbsoluteObstacles(*backgroundWithHexes);
|
||||||
if ( owner.siegeController )
|
if(owner.siegeController)
|
||||||
owner.siegeController->showAbsoluteObstacles(*backgroundWithHexes);
|
owner.siegeController->showAbsoluteObstacles(*backgroundWithHexes);
|
||||||
|
|
||||||
if (settings["battle"]["stackRange"].Bool())
|
// show shaded hexes for active's stack valid movement and the hexes that it can attack
|
||||||
|
if(settings["battle"]["stackRange"].Bool())
|
||||||
{
|
{
|
||||||
std::vector<BattleHex> hexesToShade = occupyableHexes;
|
std::vector<BattleHex> hexesToShade = occupiableHexes;
|
||||||
hexesToShade.insert(hexesToShade.end(), attackableHexes.begin(), attackableHexes.end());
|
hexesToShade.insert(hexesToShade.end(), attackableHexes.begin(), attackableHexes.end());
|
||||||
for (BattleHex hex : hexesToShade)
|
for(BattleHex hex : hexesToShade)
|
||||||
{
|
{
|
||||||
backgroundWithHexes->draw(cellShade, hexPositionLocal(hex).topLeft());
|
showHighlightedHex(*backgroundWithHexes, cellShade, hex, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// draw cell borders
|
||||||
if(settings["battle"]["cellBorders"].Bool())
|
if(settings["battle"]["cellBorders"].Bool())
|
||||||
{
|
{
|
||||||
for (int i=0; i<GameConstants::BFIELD_SIZE; ++i)
|
for(int i=0; i<GameConstants::BFIELD_SIZE; ++i)
|
||||||
{
|
{
|
||||||
if ( i % GameConstants::BFIELD_WIDTH == 0)
|
if(i % GameConstants::BFIELD_WIDTH == 0)
|
||||||
continue;
|
continue;
|
||||||
if ( i % GameConstants::BFIELD_WIDTH == GameConstants::BFIELD_WIDTH - 1)
|
if(i % GameConstants::BFIELD_WIDTH == GameConstants::BFIELD_WIDTH - 1)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
backgroundWithHexes->draw(cellBorder, hexPositionLocal(i).topLeft());
|
backgroundWithHexes->draw(cellBorder, hexPositionLocal(i).topLeft());
|
||||||
@ -205,23 +208,23 @@ void BattleFieldController::redrawBackgroundWithHexes()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void BattleFieldController::showHighlightedHex(Canvas & canvas, BattleHex hex, bool darkBorder)
|
void BattleFieldController::showHighlightedHex(Canvas & canvas, std::shared_ptr<IImage> highlight, BattleHex hex, bool darkBorder)
|
||||||
{
|
{
|
||||||
Point hexPos = hexPositionLocal(hex).topLeft();
|
Point hexPos = hexPositionLocal(hex).topLeft();
|
||||||
|
|
||||||
canvas.draw(cellShade, hexPos);
|
canvas.draw(highlight, hexPos);
|
||||||
if(!darkBorder && settings["battle"]["cellBorders"].Bool())
|
if(!darkBorder && settings["battle"]["cellBorders"].Bool())
|
||||||
canvas.draw(cellBorder, hexPos);
|
canvas.draw(cellBorder, hexPos);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::set<BattleHex> BattleFieldController::getHighlightedHexesStackRange()
|
std::set<BattleHex> BattleFieldController::getHighlightedHexesForActiveStack()
|
||||||
{
|
{
|
||||||
std::set<BattleHex> result;
|
std::set<BattleHex> result;
|
||||||
|
|
||||||
if ( !owner.stacksController->getActiveStack())
|
if(!owner.stacksController->getActiveStack())
|
||||||
return result;
|
return result;
|
||||||
|
|
||||||
if ( !settings["battle"]["stackRange"].Bool())
|
if(!settings["battle"]["stackRange"].Bool())
|
||||||
return result;
|
return result;
|
||||||
|
|
||||||
auto hoveredHex = getHoveredHex();
|
auto hoveredHex = getHoveredHex();
|
||||||
@ -230,18 +233,33 @@ std::set<BattleHex> BattleFieldController::getHighlightedHexesStackRange()
|
|||||||
for(BattleHex hex : set)
|
for(BattleHex hex : set)
|
||||||
result.insert(hex);
|
result.insert(hex);
|
||||||
|
|
||||||
// display the movement shadow of stack under mouse
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::set<BattleHex> BattleFieldController::getMovementRangeForHoveredStack()
|
||||||
|
{
|
||||||
|
std::set<BattleHex> result;
|
||||||
|
|
||||||
|
if (!owner.stacksController->getActiveStack())
|
||||||
|
return result;
|
||||||
|
|
||||||
|
if (!settings["battle"]["movementHighlightOnHover"].Bool())
|
||||||
|
return result;
|
||||||
|
|
||||||
|
auto hoveredHex = getHoveredHex();
|
||||||
|
|
||||||
|
// add possible movement hexes for stack under mouse
|
||||||
const CStack * const hoveredStack = owner.curInt->cb->battleGetStackByPos(hoveredHex, true);
|
const CStack * const hoveredStack = owner.curInt->cb->battleGetStackByPos(hoveredHex, true);
|
||||||
if(hoveredStack && hoveredStack != owner.stacksController->getActiveStack())
|
if(hoveredStack)
|
||||||
{
|
{
|
||||||
std::vector<BattleHex> v = owner.curInt->cb->battleGetAvailableHexes(hoveredStack, true, nullptr);
|
std::vector<BattleHex> v = owner.curInt->cb->battleGetAvailableHexes(hoveredStack, false, true, nullptr);
|
||||||
for(BattleHex hex : v)
|
for(BattleHex hex : v)
|
||||||
result.insert(hex);
|
result.insert(hex);
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::set<BattleHex> BattleFieldController::getHighlightedHexesSpellRange()
|
std::set<BattleHex> BattleFieldController::getHighlightedHexesForSpellRange()
|
||||||
{
|
{
|
||||||
std::set<BattleHex> result;
|
std::set<BattleHex> result;
|
||||||
auto hoveredHex = getHoveredHex();
|
auto hoveredHex = getHoveredHex();
|
||||||
@ -260,9 +278,9 @@ std::set<BattleHex> BattleFieldController::getHighlightedHexesSpellRange()
|
|||||||
{
|
{
|
||||||
// printing shaded hex(es)
|
// printing shaded hex(es)
|
||||||
spells::BattleCast event(owner.curInt->cb.get(), caster, mode, spell);
|
spells::BattleCast event(owner.curInt->cb.get(), caster, mode, spell);
|
||||||
auto shaded = spell->battleMechanics(&event)->rangeInHexes(hoveredHex);
|
auto shadedHexes = spell->battleMechanics(&event)->rangeInHexes(hoveredHex);
|
||||||
|
|
||||||
for(BattleHex shadedHex : shaded)
|
for(BattleHex shadedHex : shadedHexes)
|
||||||
{
|
{
|
||||||
if((shadedHex.getX() != 0) && (shadedHex.getX() != GameConstants::BFIELD_WIDTH - 1))
|
if((shadedHex.getX() != 0) && (shadedHex.getX() != GameConstants::BFIELD_WIDTH - 1))
|
||||||
result.insert(shadedHex);
|
result.insert(shadedHex);
|
||||||
@ -276,72 +294,73 @@ std::set<BattleHex> BattleFieldController::getHighlightedHexesMovementTarget()
|
|||||||
const CStack * stack = owner.stacksController->getActiveStack();
|
const CStack * stack = owner.stacksController->getActiveStack();
|
||||||
auto hoveredHex = getHoveredHex();
|
auto hoveredHex = getHoveredHex();
|
||||||
|
|
||||||
if (stack)
|
if(!stack)
|
||||||
|
return {};
|
||||||
|
|
||||||
|
std::vector<BattleHex> availableHexes = owner.curInt->cb->battleGetAvailableHexes(stack, true, false, nullptr);
|
||||||
|
|
||||||
|
auto hoveredStack = owner.curInt->cb->battleGetStackByPos(hoveredHex, true);
|
||||||
|
if(owner.curInt->cb->battleCanAttack(stack, hoveredStack, hoveredHex))
|
||||||
{
|
{
|
||||||
std::vector<BattleHex> v = owner.curInt->cb->battleGetAvailableHexes(stack, false, nullptr);
|
if(isTileAttackable(hoveredHex))
|
||||||
|
|
||||||
auto hoveredStack = owner.curInt->cb->battleGetStackByPos(hoveredHex, true);
|
|
||||||
if(owner.curInt->cb->battleCanAttack(stack, hoveredStack, hoveredHex))
|
|
||||||
{
|
{
|
||||||
if (isTileAttackable(hoveredHex))
|
BattleHex attackFromHex = fromWhichHexAttack(hoveredHex);
|
||||||
{
|
|
||||||
BattleHex attackFromHex = fromWhichHexAttack(hoveredHex);
|
|
||||||
|
|
||||||
if (stack->doubleWide())
|
if(stack->doubleWide())
|
||||||
return {attackFromHex, stack->occupiedHex(attackFromHex)};
|
return {attackFromHex, stack->occupiedHex(attackFromHex)};
|
||||||
else
|
|
||||||
return {attackFromHex};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (vstd::contains(v,hoveredHex))
|
|
||||||
{
|
|
||||||
if (stack->doubleWide())
|
|
||||||
return {hoveredHex, stack->occupiedHex(hoveredHex)};
|
|
||||||
else
|
else
|
||||||
return {hoveredHex};
|
return {attackFromHex};
|
||||||
}
|
|
||||||
if (stack->doubleWide())
|
|
||||||
{
|
|
||||||
for (auto const & hex : v)
|
|
||||||
{
|
|
||||||
if (stack->occupiedHex(hex) == hoveredHex)
|
|
||||||
return { hoveredHex, hex };
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(vstd::contains(availableHexes, hoveredHex))
|
||||||
|
{
|
||||||
|
if(stack->doubleWide())
|
||||||
|
return {hoveredHex, stack->occupiedHex(hoveredHex)};
|
||||||
|
else
|
||||||
|
return {hoveredHex};
|
||||||
|
}
|
||||||
|
|
||||||
|
if(stack->doubleWide())
|
||||||
|
{
|
||||||
|
for(auto const & hex : availableHexes)
|
||||||
|
{
|
||||||
|
if(stack->occupiedHex(hex) == hoveredHex)
|
||||||
|
return {hoveredHex, hex};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
void BattleFieldController::showHighlightedHexes(Canvas & canvas)
|
void BattleFieldController::showHighlightedHexes(Canvas & canvas)
|
||||||
{
|
{
|
||||||
std::set<BattleHex> hoveredStack = getHighlightedHexesStackRange();
|
std::set<BattleHex> hoveredStackMovementRangeHexes = getMovementRangeForHoveredStack();
|
||||||
std::set<BattleHex> hoveredSpell = getHighlightedHexesSpellRange();
|
std::set<BattleHex> hoveredSpellHexes = getHighlightedHexesForSpellRange();
|
||||||
std::set<BattleHex> hoveredMove = getHighlightedHexesMovementTarget();
|
std::set<BattleHex> hoveredMoveHexes = getHighlightedHexesMovementTarget();
|
||||||
|
|
||||||
if (getHoveredHex() == BattleHex::INVALID)
|
if(getHoveredHex() == BattleHex::INVALID)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
auto const & hoveredMouse = owner.actionsController->currentActionSpellcasting(getHoveredHex()) ? hoveredSpell : hoveredMove;
|
auto const & hoveredMouseHexes = owner.actionsController->currentActionSpellcasting(getHoveredHex()) ? hoveredSpellHexes : hoveredMoveHexes;
|
||||||
|
|
||||||
for(int b=0; b<GameConstants::BFIELD_SIZE; ++b)
|
for(int hex = 0; hex < GameConstants::BFIELD_SIZE; ++hex)
|
||||||
{
|
{
|
||||||
bool stack = hoveredStack.count(b);
|
bool stackMovement = hoveredStackMovementRangeHexes.count(hex);
|
||||||
bool mouse = hoveredMouse.count(b);
|
bool mouse = hoveredMouseHexes.count(hex);
|
||||||
|
|
||||||
if ( stack && mouse )
|
if(stackMovement && mouse) // area where hovered stackMovement can move shown with highlight. Because also affected by mouse cursor, shade as well
|
||||||
{
|
{
|
||||||
// area where enemy stack can move AND affected by mouse cursor - create darker highlight by blitting twice
|
showHighlightedHex(canvas, cellUnitMovementHighlight, hex, false);
|
||||||
showHighlightedHex(canvas, b, true);
|
showHighlightedHex(canvas, cellShade, hex, true);
|
||||||
showHighlightedHex(canvas, b, true);
|
|
||||||
}
|
}
|
||||||
if ( !stack && mouse )
|
if(!stackMovement && mouse) // hexes affected only at mouse cursor shown as shaded
|
||||||
{
|
{
|
||||||
showHighlightedHex(canvas, b, true);
|
showHighlightedHex(canvas, cellShade, hex, true);
|
||||||
}
|
}
|
||||||
if ( stack && !mouse )
|
if(stackMovement && !mouse) // hexes where hovered stackMovement can move shown with highlight
|
||||||
{
|
{
|
||||||
showHighlightedHex(canvas, b, false);
|
showHighlightedHex(canvas, cellUnitMovementHighlight, hex, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -438,18 +457,18 @@ BattleHex::EDir BattleFieldController::selectAttackDirection(BattleHex myNumber,
|
|||||||
// | - - | - - | - - | - o o | o o - | - - | - - | o o
|
// | - - | - - | - - | - o o | o o - | - - | - - | o o
|
||||||
|
|
||||||
for (size_t i : { 1, 2, 3})
|
for (size_t i : { 1, 2, 3})
|
||||||
attackAvailability[i] = vstd::contains(occupyableHexes, neighbours[i]) && vstd::contains(occupyableHexes, neighbours[i].cloneInDirection(BattleHex::RIGHT, false));
|
attackAvailability[i] = vstd::contains(occupiableHexes, neighbours[i]) && vstd::contains(occupiableHexes, neighbours[i].cloneInDirection(BattleHex::RIGHT, false));
|
||||||
|
|
||||||
for (size_t i : { 4, 5, 0})
|
for (size_t i : { 4, 5, 0})
|
||||||
attackAvailability[i] = vstd::contains(occupyableHexes, neighbours[i]) && vstd::contains(occupyableHexes, neighbours[i].cloneInDirection(BattleHex::LEFT, false));
|
attackAvailability[i] = vstd::contains(occupiableHexes, neighbours[i]) && vstd::contains(occupiableHexes, neighbours[i].cloneInDirection(BattleHex::LEFT, false));
|
||||||
|
|
||||||
attackAvailability[6] = vstd::contains(occupyableHexes, neighbours[0]) && vstd::contains(occupyableHexes, neighbours[1]);
|
attackAvailability[6] = vstd::contains(occupiableHexes, neighbours[0]) && vstd::contains(occupiableHexes, neighbours[1]);
|
||||||
attackAvailability[7] = vstd::contains(occupyableHexes, neighbours[3]) && vstd::contains(occupyableHexes, neighbours[4]);
|
attackAvailability[7] = vstd::contains(occupiableHexes, neighbours[3]) && vstd::contains(occupiableHexes, neighbours[4]);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
for (size_t i = 0; i < 6; ++i)
|
for (size_t i = 0; i < 6; ++i)
|
||||||
attackAvailability[i] = vstd::contains(occupyableHexes, neighbours[i]);
|
attackAvailability[i] = vstd::contains(occupiableHexes, neighbours[i]);
|
||||||
|
|
||||||
attackAvailability[6] = false;
|
attackAvailability[6] = false;
|
||||||
attackAvailability[7] = false;
|
attackAvailability[7] = false;
|
||||||
@ -561,7 +580,7 @@ BattleHex BattleFieldController::fromWhichHexAttack(BattleHex attackTarget)
|
|||||||
|
|
||||||
bool BattleFieldController::isTileAttackable(const BattleHex & number) const
|
bool BattleFieldController::isTileAttackable(const BattleHex & number) const
|
||||||
{
|
{
|
||||||
for (auto & elem : occupyableHexes)
|
for (auto & elem : occupiableHexes)
|
||||||
{
|
{
|
||||||
if (BattleHex::mutualPosition(elem, number) != -1 || elem == number)
|
if (BattleHex::mutualPosition(elem, number) != -1 || elem == number)
|
||||||
return true;
|
return true;
|
||||||
|
@ -32,6 +32,8 @@ class BattleFieldController : public CIntObject
|
|||||||
|
|
||||||
std::shared_ptr<IImage> background;
|
std::shared_ptr<IImage> background;
|
||||||
std::shared_ptr<IImage> cellBorder;
|
std::shared_ptr<IImage> cellBorder;
|
||||||
|
std::shared_ptr<IImage> cellUnitMovementHighlight;
|
||||||
|
std::shared_ptr<IImage> cellUnitMaxMovementHighlight;
|
||||||
std::shared_ptr<IImage> cellShade;
|
std::shared_ptr<IImage> cellShade;
|
||||||
|
|
||||||
/// Canvas that contains background, hex grid (if enabled), absolute obstacles and movement range of active stack
|
/// Canvas that contains background, hex grid (if enabled), absolute obstacles and movement range of active stack
|
||||||
@ -41,15 +43,16 @@ class BattleFieldController : public CIntObject
|
|||||||
BattleHex attackingHex;
|
BattleHex attackingHex;
|
||||||
|
|
||||||
/// hexes to which currently active stack can move
|
/// hexes to which currently active stack can move
|
||||||
std::vector<BattleHex> occupyableHexes;
|
std::vector<BattleHex> occupiableHexes;
|
||||||
|
|
||||||
/// hexes that when in front of a unit cause it's amount box to move back
|
/// hexes that when in front of a unit cause it's amount box to move back
|
||||||
std::array<bool, GameConstants::BFIELD_SIZE> stackCountOutsideHexes;
|
std::array<bool, GameConstants::BFIELD_SIZE> stackCountOutsideHexes;
|
||||||
|
|
||||||
void showHighlightedHex(Canvas & to, BattleHex hex, bool darkBorder);
|
void showHighlightedHex(Canvas & to, std::shared_ptr<IImage> highlight, BattleHex hex, bool darkBorder);
|
||||||
|
|
||||||
std::set<BattleHex> getHighlightedHexesStackRange();
|
std::set<BattleHex> getHighlightedHexesForActiveStack();
|
||||||
std::set<BattleHex> getHighlightedHexesSpellRange();
|
std::set<BattleHex> getMovementRangeForHoveredStack();
|
||||||
|
std::set<BattleHex> getHighlightedHexesForSpellRange();
|
||||||
std::set<BattleHex> getHighlightedHexesMovementTarget();
|
std::set<BattleHex> getHighlightedHexesMovementTarget();
|
||||||
|
|
||||||
void showBackground(Canvas & canvas);
|
void showBackground(Canvas & canvas);
|
||||||
|
@ -460,7 +460,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...
|
||||||
@ -733,7 +733,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));
|
||||||
|
@ -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())
|
||||||
|
@ -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);
|
||||||
|
@ -198,6 +198,23 @@ void BattleWindow::keyPressed(const SDL_Keycode & key)
|
|||||||
{
|
{
|
||||||
owner.actionsController->endCastingSpell();
|
owner.actionsController->endCastingSpell();
|
||||||
}
|
}
|
||||||
|
else if(GH.isKeyboardShiftDown())
|
||||||
|
{
|
||||||
|
// save and activate setting
|
||||||
|
Settings movementHighlightOnHover = settings.write["battle"]["movementHighlightOnHover"];
|
||||||
|
movementHighlightOnHoverCache = movementHighlightOnHover->Bool();
|
||||||
|
movementHighlightOnHover->Bool() = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void BattleWindow::keyReleased(const SDL_Keycode & key)
|
||||||
|
{
|
||||||
|
if(!GH.isKeyboardShiftDown())
|
||||||
|
{
|
||||||
|
// set back to initial state
|
||||||
|
Settings movementHighlightOnHover = settings.write["battle"]["movementHighlightOnHover"];
|
||||||
|
movementHighlightOnHover->Bool() = movementHighlightOnHoverCache;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void BattleWindow::clickRight(tribool down, bool previousState)
|
void BattleWindow::clickRight(tribool down, bool previousState)
|
||||||
@ -309,7 +326,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!
|
||||||
}
|
}
|
||||||
|
@ -85,6 +85,7 @@ public:
|
|||||||
void activate() override;
|
void activate() override;
|
||||||
void deactivate() override;
|
void deactivate() override;
|
||||||
void keyPressed(const SDL_Keycode & key) override;
|
void keyPressed(const SDL_Keycode & key) override;
|
||||||
|
void keyReleased(const SDL_Keycode& key) override;
|
||||||
void clickRight(tribool down, bool previousState) override;
|
void clickRight(tribool down, bool previousState) override;
|
||||||
void show(SDL_Surface *to) override;
|
void show(SDL_Surface *to) override;
|
||||||
void showAll(SDL_Surface *to) override;
|
void showAll(SDL_Surface *to) override;
|
||||||
@ -98,5 +99,8 @@ public:
|
|||||||
/// Set possible alternative options. If more than 1 - the last will be considered as default option
|
/// Set possible alternative options. If more than 1 - the last will be considered as default option
|
||||||
void setAlternativeActions(const std::list<PossiblePlayerBattleAction> &);
|
void setAlternativeActions(const std::list<PossiblePlayerBattleAction> &);
|
||||||
|
|
||||||
|
private:
|
||||||
|
/// used to save the state of this setting on toggle.
|
||||||
|
bool movementHighlightOnHoverCache;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -418,7 +418,7 @@ void CGuiHandler::handleCurrentEvent( SDL_Event & current )
|
|||||||
for(auto i = miCopy.begin(); i != miCopy.end() && continueEventHandling; i++)
|
for(auto i = miCopy.begin(); i != miCopy.end() && continueEventHandling; i++)
|
||||||
if(vstd::contains(keyinterested,*i) && (!keysCaptured || (*i)->captureThisKey(key.keysym.sym)))
|
if(vstd::contains(keyinterested,*i) && (!keysCaptured || (*i)->captureThisKey(key.keysym.sym)))
|
||||||
{
|
{
|
||||||
if (key.state == SDL_PRESSED)
|
if (key.state == SDL_PRESSED && key.repeat == 0) // function like key_DOWN, and not like a periodic key_Pressed check
|
||||||
(**i).keyPressed(key.keysym.sym);
|
(**i).keyPressed(key.keysym.sym);
|
||||||
if (key.state == SDL_RELEASED)
|
if (key.state == SDL_RELEASED)
|
||||||
(**i).keyReleased(key.keysym.sym);
|
(**i).keyReleased(key.keysym.sym);
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -654,7 +654,7 @@ CArtifactsOfHero::~CArtifactsOfHero()
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
//TODO remove artifact
|
LOCPLINT->cb->eraseArtifactByClient(ArtifactLocation(curHero, ArtifactPosition::TRANSITION_POS));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
};
|
};
|
||||||
|
@ -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);
|
||||||
|
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
|
@ -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);
|
||||||
|
|
||||||
|
@ -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;
|
||||||
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
|
@ -13,6 +13,7 @@
|
|||||||
#include "CConfigHandler.h"
|
#include "CConfigHandler.h"
|
||||||
|
|
||||||
#include "../../battle/BattleInterface.h"
|
#include "../../battle/BattleInterface.h"
|
||||||
|
#include "../../battle/BattleActionsController.h"
|
||||||
#include "../../gui/CGuiHandler.h"
|
#include "../../gui/CGuiHandler.h"
|
||||||
#include "../../../lib/filesystem/ResourceID.h"
|
#include "../../../lib/filesystem/ResourceID.h"
|
||||||
#include "../../../lib/CGeneralTextHandler.h"
|
#include "../../../lib/CGeneralTextHandler.h"
|
||||||
@ -33,6 +34,10 @@ BattleOptionsTab::BattleOptionsTab(BattleInterface * owner)
|
|||||||
{
|
{
|
||||||
movementShadowChangedCallback(value, owner);
|
movementShadowChangedCallback(value, owner);
|
||||||
});
|
});
|
||||||
|
addCallback("movementHighlightOnHoverChanged", [this, owner](bool value)
|
||||||
|
{
|
||||||
|
movementHighlightOnHoverChangedCallback(value, owner);
|
||||||
|
});
|
||||||
addCallback("mouseShadowChanged", [this](bool value)
|
addCallback("mouseShadowChanged", [this](bool value)
|
||||||
{
|
{
|
||||||
mouseShadowChangedCallback(value);
|
mouseShadowChangedCallback(value);
|
||||||
@ -53,6 +58,10 @@ BattleOptionsTab::BattleOptionsTab(BattleInterface * owner)
|
|||||||
{
|
{
|
||||||
skipBattleIntroMusicChangedCallback(value);
|
skipBattleIntroMusicChangedCallback(value);
|
||||||
});
|
});
|
||||||
|
addCallback("touchscreenModeChanged", [this, owner](bool value)
|
||||||
|
{
|
||||||
|
touchscreenModeChangedCallback(value, owner);
|
||||||
|
});
|
||||||
build(config);
|
build(config);
|
||||||
|
|
||||||
std::shared_ptr<CToggleGroup> animationSpeedToggle = widget<CToggleGroup>("animationSpeedPicker");
|
std::shared_ptr<CToggleGroup> animationSpeedToggle = widget<CToggleGroup>("animationSpeedPicker");
|
||||||
@ -67,9 +76,15 @@ BattleOptionsTab::BattleOptionsTab(BattleInterface * owner)
|
|||||||
std::shared_ptr<CToggleButton> movementShadowCheckbox = widget<CToggleButton>("movementShadowCheckbox");
|
std::shared_ptr<CToggleButton> movementShadowCheckbox = widget<CToggleButton>("movementShadowCheckbox");
|
||||||
movementShadowCheckbox->setSelected(settings["battle"]["stackRange"].Bool());
|
movementShadowCheckbox->setSelected(settings["battle"]["stackRange"].Bool());
|
||||||
|
|
||||||
|
std::shared_ptr<CToggleButton> movementHighlightOnHoverCheckbox = widget<CToggleButton>("movementHighlightOnHoverCheckbox");
|
||||||
|
movementHighlightOnHoverCheckbox->setSelected(settings["battle"]["movementHighlightOnHover"].Bool());
|
||||||
|
|
||||||
std::shared_ptr<CToggleButton> mouseShadowCheckbox = widget<CToggleButton>("mouseShadowCheckbox");
|
std::shared_ptr<CToggleButton> mouseShadowCheckbox = widget<CToggleButton>("mouseShadowCheckbox");
|
||||||
mouseShadowCheckbox->setSelected(settings["battle"]["mouseShadow"].Bool());
|
mouseShadowCheckbox->setSelected(settings["battle"]["mouseShadow"].Bool());
|
||||||
|
|
||||||
|
std::shared_ptr<CToggleButton> touchscreenModeCheckbox = widget<CToggleButton>("touchscreenModeCheckbox");
|
||||||
|
touchscreenModeCheckbox->setSelected(settings["battle"]["touchscreenMode"].Bool());
|
||||||
|
|
||||||
std::shared_ptr<CToggleButton> skipBattleIntroMusicCheckbox = widget<CToggleButton>("skipBattleIntroMusicCheckbox");
|
std::shared_ptr<CToggleButton> skipBattleIntroMusicCheckbox = widget<CToggleButton>("skipBattleIntroMusicCheckbox");
|
||||||
skipBattleIntroMusicCheckbox->setSelected(settings["gameTweaks"]["skipBattleIntroMusic"].Bool());
|
skipBattleIntroMusicCheckbox->setSelected(settings["gameTweaks"]["skipBattleIntroMusic"].Bool());
|
||||||
}
|
}
|
||||||
@ -130,12 +145,28 @@ void BattleOptionsTab::movementShadowChangedCallback(bool value, BattleInterface
|
|||||||
parentBattleInterface->redrawBattlefield();
|
parentBattleInterface->redrawBattlefield();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void BattleOptionsTab::movementHighlightOnHoverChangedCallback(bool value, BattleInterface * parentBattleInterface)
|
||||||
|
{
|
||||||
|
Settings stackRange = settings.write["battle"]["movementHighlightOnHover"];
|
||||||
|
stackRange->Bool() = value;
|
||||||
|
if(parentBattleInterface)
|
||||||
|
parentBattleInterface->redrawBattlefield();
|
||||||
|
}
|
||||||
|
|
||||||
void BattleOptionsTab::mouseShadowChangedCallback(bool value)
|
void BattleOptionsTab::mouseShadowChangedCallback(bool value)
|
||||||
{
|
{
|
||||||
Settings shadow = settings.write["battle"]["mouseShadow"];
|
Settings shadow = settings.write["battle"]["mouseShadow"];
|
||||||
shadow->Bool() = value;
|
shadow->Bool() = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void BattleOptionsTab::touchscreenModeChangedCallback(bool value, BattleInterface * parentBattleInterface)
|
||||||
|
{
|
||||||
|
Settings touchcreenMode = settings.write["battle"]["touchscreenMode"];
|
||||||
|
touchcreenMode->Bool() = value;
|
||||||
|
if(parentBattleInterface)
|
||||||
|
parentBattleInterface->actionsController->setTouchScreenMode(value);
|
||||||
|
}
|
||||||
|
|
||||||
void BattleOptionsTab::animationSpeedChangedCallback(int value)
|
void BattleOptionsTab::animationSpeedChangedCallback(int value)
|
||||||
{
|
{
|
||||||
Settings speed = settings.write["battle"]["speedFactor"];
|
Settings speed = settings.write["battle"]["speedFactor"];
|
||||||
|
@ -24,11 +24,13 @@ private:
|
|||||||
std::string getQueueSizeStringFromId(int value) const;
|
std::string getQueueSizeStringFromId(int value) const;
|
||||||
void viewGridChangedCallback(bool value, BattleInterface * parentBattleInterface);
|
void viewGridChangedCallback(bool value, BattleInterface * parentBattleInterface);
|
||||||
void movementShadowChangedCallback(bool value, BattleInterface * parentBattleInterface);
|
void movementShadowChangedCallback(bool value, BattleInterface * parentBattleInterface);
|
||||||
|
void movementHighlightOnHoverChangedCallback(bool value, BattleInterface * parentBattleInterface);
|
||||||
void mouseShadowChangedCallback(bool value);
|
void mouseShadowChangedCallback(bool value);
|
||||||
void animationSpeedChangedCallback(int value);
|
void animationSpeedChangedCallback(int value);
|
||||||
void showQueueChangedCallback(bool value, BattleInterface * parentBattleInterface);
|
void showQueueChangedCallback(bool value, BattleInterface * parentBattleInterface);
|
||||||
void queueSizeChangedCallback(int value, BattleInterface * parentBattleInterface);
|
void queueSizeChangedCallback(int value, BattleInterface * parentBattleInterface);
|
||||||
void skipBattleIntroMusicChangedCallback(bool value);
|
void skipBattleIntroMusicChangedCallback(bool value);
|
||||||
|
void touchscreenModeChangedCallback(bool value, BattleInterface * parentBattleInterface);
|
||||||
public:
|
public:
|
||||||
BattleOptionsTab(BattleInterface * owner = nullptr);
|
BattleOptionsTab(BattleInterface * owner = nullptr);
|
||||||
};
|
};
|
||||||
|
@ -134,6 +134,7 @@ macro(add_main_lib TARGET_NAME LIBRARY_TYPE)
|
|||||||
${MAIN_LIB_DIR}/spells/BattleSpellMechanics.cpp
|
${MAIN_LIB_DIR}/spells/BattleSpellMechanics.cpp
|
||||||
${MAIN_LIB_DIR}/spells/BonusCaster.cpp
|
${MAIN_LIB_DIR}/spells/BonusCaster.cpp
|
||||||
${MAIN_LIB_DIR}/spells/CSpellHandler.cpp
|
${MAIN_LIB_DIR}/spells/CSpellHandler.cpp
|
||||||
|
${MAIN_LIB_DIR}/spells/ExternalCaster.cpp
|
||||||
${MAIN_LIB_DIR}/spells/ISpellMechanics.cpp
|
${MAIN_LIB_DIR}/spells/ISpellMechanics.cpp
|
||||||
${MAIN_LIB_DIR}/spells/ObstacleCasterProxy.cpp
|
${MAIN_LIB_DIR}/spells/ObstacleCasterProxy.cpp
|
||||||
${MAIN_LIB_DIR}/spells/Problem.cpp
|
${MAIN_LIB_DIR}/spells/Problem.cpp
|
||||||
@ -397,7 +398,9 @@ macro(add_main_lib TARGET_NAME LIBRARY_TYPE)
|
|||||||
${MAIN_LIB_DIR}/spells/BattleSpellMechanics.h
|
${MAIN_LIB_DIR}/spells/BattleSpellMechanics.h
|
||||||
${MAIN_LIB_DIR}/spells/BonusCaster.h
|
${MAIN_LIB_DIR}/spells/BonusCaster.h
|
||||||
${MAIN_LIB_DIR}/spells/CSpellHandler.h
|
${MAIN_LIB_DIR}/spells/CSpellHandler.h
|
||||||
|
${MAIN_LIB_DIR}/spells/ExternalCaster.h
|
||||||
${MAIN_LIB_DIR}/spells/ISpellMechanics.h
|
${MAIN_LIB_DIR}/spells/ISpellMechanics.h
|
||||||
|
${MAIN_LIB_DIR}/spells/ObstacleCasterProxy.h
|
||||||
${MAIN_LIB_DIR}/spells/Problem.h
|
${MAIN_LIB_DIR}/spells/Problem.h
|
||||||
${MAIN_LIB_DIR}/spells/ProxyCaster.h
|
${MAIN_LIB_DIR}/spells/ProxyCaster.h
|
||||||
${MAIN_LIB_DIR}/spells/TargetCondition.h
|
${MAIN_LIB_DIR}/spells/TargetCondition.h
|
||||||
|
@ -290,7 +290,7 @@
|
|||||||
"type" : "object",
|
"type" : "object",
|
||||||
"additionalProperties" : false,
|
"additionalProperties" : false,
|
||||||
"default": {},
|
"default": {},
|
||||||
"required" : [ "speedFactor", "mouseShadow", "cellBorders", "stackRange", "showQueue", "queueSize" ],
|
"required" : [ "speedFactor", "mouseShadow", "cellBorders", "stackRange", "movementHighlightOnHover", "showQueue", "queueSize", "touchscreenMode" ],
|
||||||
"properties" : {
|
"properties" : {
|
||||||
"speedFactor" : {
|
"speedFactor" : {
|
||||||
"type" : "number",
|
"type" : "number",
|
||||||
@ -304,10 +304,18 @@
|
|||||||
"type" : "boolean",
|
"type" : "boolean",
|
||||||
"default" : false
|
"default" : false
|
||||||
},
|
},
|
||||||
|
"touchscreenMode" : {
|
||||||
|
"type" : "boolean",
|
||||||
|
"default" : false
|
||||||
|
},
|
||||||
"stackRange" : {
|
"stackRange" : {
|
||||||
"type" : "boolean",
|
"type" : "boolean",
|
||||||
"default" : true
|
"default" : true
|
||||||
},
|
},
|
||||||
|
"movementHighlightOnHover" : {
|
||||||
|
"type" : "boolean",
|
||||||
|
"default" : true
|
||||||
|
},
|
||||||
"showQueue" : {
|
"showQueue" : {
|
||||||
"type" : "boolean",
|
"type" : "boolean",
|
||||||
"default" : true
|
"default" : true
|
||||||
|
@ -5,13 +5,13 @@
|
|||||||
"name": "lineCreatureInfo",
|
"name": "lineCreatureInfo",
|
||||||
"type": "texture",
|
"type": "texture",
|
||||||
"image": "settingsWindow/lineHorizontal",
|
"image": "settingsWindow/lineHorizontal",
|
||||||
"rect": { "x" : 5, "y" : 199, "w": 365, "h": 3}
|
"rect": { "x" : 5, "y" : 229, "w": 365, "h": 3}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "lineAnimationSpeed",
|
"name": "lineAnimationSpeed",
|
||||||
"type": "texture",
|
"type": "texture",
|
||||||
"image": "settingsWindow/lineHorizontal",
|
"image": "settingsWindow/lineHorizontal",
|
||||||
"rect": { "x" : 5, "y" : 289, "w": 365, "h": 3}
|
"rect": { "x" : 5, "y" : 319, "w": 365, "h": 3}
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
@ -28,7 +28,7 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"text": "core.genrltxt.397", // Creature info
|
"text": "core.genrltxt.397", // Creature info
|
||||||
"position": {"x": 10, "y": 205}
|
"position": {"x": 10, "y": 235}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
@ -104,11 +104,11 @@
|
|||||||
[
|
[
|
||||||
{
|
{
|
||||||
"text": "core.genrltxt.402", // All Stats
|
"text": "core.genrltxt.402", // All Stats
|
||||||
"position": {"x": 45, "y": 235}
|
"position": {"x": 45, "y": 265}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"text": "core.genrltxt.403", // Spells only
|
"text": "core.genrltxt.403", // Spells only
|
||||||
"position": {"x": 45, "y": 265}
|
"position": {"x": 45, "y": 295}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
@ -116,13 +116,13 @@
|
|||||||
"name": "creatureInfoAllPlaceholder",
|
"name": "creatureInfoAllPlaceholder",
|
||||||
"type": "picture",
|
"type": "picture",
|
||||||
"image": "settingsWindow/checkBoxEmpty",
|
"image": "settingsWindow/checkBoxEmpty",
|
||||||
"position": {"x": 10, "y": 233},
|
"position": {"x": 10, "y": 263},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "creatureInfoSpellsPlaceholder",
|
"name": "creatureInfoSpellsPlaceholder",
|
||||||
"type": "picture",
|
"type": "picture",
|
||||||
"image": "settingsWindow/checkBoxEmpty",
|
"image": "settingsWindow/checkBoxEmpty",
|
||||||
"position": {"x": 10, "y": 263},
|
"position": {"x": 10, "y": 293},
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
@ -142,16 +142,24 @@
|
|||||||
"position": {"x": 45, "y": 85}
|
"position": {"x": 45, "y": 85}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"text": "core.genrltxt.406",
|
"text": "vcmi.battleOptions.movementHighlightOnHover.hover",
|
||||||
"position": {"x": 45, "y": 115}
|
"position": {"x": 45, "y": 115}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"text": "core.genrltxt.407",
|
"text": "core.genrltxt.406",
|
||||||
"position": {"x": 45, "y": 145}
|
"position": {"x": 45, "y": 145}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"text": "core.genrltxt.407",
|
||||||
|
"position": {"x": 45, "y": 175}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"text": "vcmi.battleOptions.skipBattleIntroMusic.hover",
|
"text": "vcmi.battleOptions.skipBattleIntroMusic.hover",
|
||||||
"position": {"x": 45, "y": 175}
|
"position": {"x": 45, "y": 175}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"text": "vcmi.battleOptions.touchscreenMode.hover",
|
||||||
|
"position": {"x": 45, "y": 205}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
@ -172,28 +180,44 @@
|
|||||||
"position": {"x": 10, "y": 83},
|
"position": {"x": 10, "y": 83},
|
||||||
"callback": "movementShadowChanged"
|
"callback": "movementShadowChanged"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "movementHighlightOnHoverCheckbox",
|
||||||
|
"type": "toggleButton",
|
||||||
|
"image": "sysopchk.def",
|
||||||
|
"help": "vcmi.battleOptions.movementHighlightOnHover",
|
||||||
|
"position": {"x": 10, "y": 113},
|
||||||
|
"callback": "movementHighlightOnHoverChanged"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "mouseShadowCheckbox",
|
"name": "mouseShadowCheckbox",
|
||||||
"type": "toggleButton",
|
"type": "toggleButton",
|
||||||
"image": "sysopchk.def",
|
"image": "sysopchk.def",
|
||||||
"help": "core.help.429",
|
"help": "core.help.429",
|
||||||
"position": {"x": 10, "y": 113},
|
"position": {"x": 10, "y": 143},
|
||||||
"callback": "mouseShadowChanged"
|
"callback": "mouseShadowChanged"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "battleFieldCasualtiesPlaceholder",
|
"name": "battleFieldCasualtiesPlaceholder",
|
||||||
"type": "picture",
|
"type": "picture",
|
||||||
"image": "settingsWindow/checkBoxEmpty",
|
"image": "settingsWindow/checkBoxEmpty",
|
||||||
"position": {"x": 10, "y": 143},
|
"position": {"x": 10, "y": 173},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "skipBattleIntroMusicCheckbox",
|
"name": "skipBattleIntroMusicCheckbox",
|
||||||
"type": "toggleButton",
|
"type": "toggleButton",
|
||||||
"image": "sysopchk.def",
|
"image": "sysopchk.def",
|
||||||
"help": "vcmi.battleOptions.skipBattleIntroMusic",
|
"help": "vcmi.battleOptions.skipBattleIntroMusic",
|
||||||
"position": {"x": 10, "y": 173},
|
"position": {"x": 10, "y": 203},
|
||||||
"callback": "skipBattleIntroMusicChanged"
|
"callback": "skipBattleIntroMusicChanged"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "touchscreenModeCheckbox",
|
||||||
|
"type": "toggleButton",
|
||||||
|
"image": "sysopchk.def",
|
||||||
|
"help": "vcmi.battleOptions.touchscreenMode",
|
||||||
|
"position": {"x": 10, "y": 203},
|
||||||
|
"callback": "touchscreenModeChanged"
|
||||||
|
},
|
||||||
/////////////////////////////////////// Bottom section - Animation Speed and Turn Order
|
/////////////////////////////////////// Bottom section - Animation Speed and Turn Order
|
||||||
{
|
{
|
||||||
"name": "frameAnimationSpeed",
|
"name": "frameAnimationSpeed",
|
||||||
|
@ -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;
|
||||||
};
|
};
|
||||||
|
@ -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
|
||||||
|
@ -15,12 +15,16 @@
|
|||||||
VCMI_LIB_NAMESPACE_BEGIN
|
VCMI_LIB_NAMESPACE_BEGIN
|
||||||
|
|
||||||
class FactionID;
|
class FactionID;
|
||||||
|
enum class ETerrainId;
|
||||||
|
enum class EAlignment : uint8_t;
|
||||||
|
template<typename T> class Identifier;
|
||||||
|
|
||||||
class DLL_LINKAGE Faction : public EntityT<FactionID>
|
class DLL_LINKAGE Faction : public EntityT<FactionID>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual bool hasTown() const = 0;
|
virtual bool hasTown() const = 0;
|
||||||
|
virtual Identifier<ETerrainId> getNativeTerrain() const = 0;
|
||||||
|
virtual EAlignment getAlignment() const = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
VCMI_LIB_NAMESPACE_END
|
VCMI_LIB_NAMESPACE_END
|
||||||
|
@ -10,19 +10,18 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "Entity.h"
|
||||||
VCMI_LIB_NAMESPACE_BEGIN
|
VCMI_LIB_NAMESPACE_BEGIN
|
||||||
|
|
||||||
class PlayerColor;
|
class PlayerColor;
|
||||||
class TeamID;
|
class TeamID;
|
||||||
class IBonusBearer;
|
class IBonusBearer;
|
||||||
|
|
||||||
class DLL_LINKAGE Player
|
class DLL_LINKAGE Player : public EntityWithBonuses<PlayerColor>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual PlayerColor getColor() const = 0;
|
|
||||||
virtual TeamID getTeam() const = 0;
|
virtual TeamID getTeam() const = 0;
|
||||||
virtual bool isHuman() const = 0;
|
virtual bool isHuman() const = 0;
|
||||||
virtual const IBonusBearer * accessBonuses() const = 0;
|
|
||||||
virtual int getResourceAmount(int type) const = 0;
|
virtual int getResourceAmount(int type) const = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -15,6 +15,7 @@ VCMI_LIB_NAMESPACE_BEGIN
|
|||||||
class PlayerColor;
|
class PlayerColor;
|
||||||
struct MetaString;
|
struct MetaString;
|
||||||
class ServerCallback;
|
class ServerCallback;
|
||||||
|
class CGHeroInstance;
|
||||||
|
|
||||||
namespace battle
|
namespace battle
|
||||||
{
|
{
|
||||||
@ -65,6 +66,9 @@ public:
|
|||||||
virtual void getCastDescription(const Spell * spell, const std::vector<const battle::Unit *> & attacked, MetaString & text) const = 0;
|
virtual void getCastDescription(const Spell * spell, const std::vector<const battle::Unit *> & attacked, MetaString & text) const = 0;
|
||||||
|
|
||||||
virtual void spendMana(ServerCallback * server, const int32_t spellCost) const = 0;
|
virtual void spendMana(ServerCallback * server, const int32_t spellCost) const = 0;
|
||||||
|
|
||||||
|
///used to identify actual hero caster
|
||||||
|
virtual const CGHeroInstance * getHeroCaster() const = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -102,6 +102,7 @@ void FirstLaunchView::on_comboBoxLanguage_currentIndexChanged(int index)
|
|||||||
|
|
||||||
void FirstLaunchView::enterSetup()
|
void FirstLaunchView::enterSetup()
|
||||||
{
|
{
|
||||||
|
setupPlatformSettings();
|
||||||
Languages::fillLanguages(ui->listWidgetLanguage, false);
|
Languages::fillLanguages(ui->listWidgetLanguage, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -158,6 +159,19 @@ void FirstLaunchView::exitSetup()
|
|||||||
mainWindow->exitSetup();
|
mainWindow->exitSetup();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Initial platform-dependend settings
|
||||||
|
void FirstLaunchView::setupPlatformSettings()
|
||||||
|
{
|
||||||
|
#if defined(VCMI_MOBILE)
|
||||||
|
bool touchscreenMode = true;
|
||||||
|
#else
|
||||||
|
bool touchscreenMode = false;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
Settings node = settings.write["battle"]["touchscreenMode"];
|
||||||
|
node->Bool() = touchscreenMode;
|
||||||
|
}
|
||||||
|
|
||||||
// Tab Language
|
// Tab Language
|
||||||
void FirstLaunchView::languageSelected(const QString & selectedLanguage)
|
void FirstLaunchView::languageSelected(const QString & selectedLanguage)
|
||||||
{
|
{
|
||||||
|
@ -38,6 +38,9 @@ class FirstLaunchView : public QWidget
|
|||||||
void activateTabModPreset();
|
void activateTabModPreset();
|
||||||
void exitSetup();
|
void exitSetup();
|
||||||
|
|
||||||
|
// Initial platform-dependend settings
|
||||||
|
void setupPlatformSettings();
|
||||||
|
|
||||||
// Tab Language
|
// Tab Language
|
||||||
void languageSelected(const QString & languageCode);
|
void languageSelected(const QString & languageCode);
|
||||||
|
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
|
@ -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();
|
||||||
@ -256,7 +266,7 @@ bool CCreature::isDoubleWide() const
|
|||||||
*/
|
*/
|
||||||
bool CCreature::isGood () const
|
bool CCreature::isGood () const
|
||||||
{
|
{
|
||||||
return (*VLC->townh)[faction]->alignment == EAlignment::GOOD;
|
return VLC->factions()->getByIndex(faction)->getAlignment() == EAlignment::GOOD;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -265,7 +275,7 @@ bool CCreature::isGood () const
|
|||||||
*/
|
*/
|
||||||
bool CCreature::isEvil () const
|
bool CCreature::isEvil () const
|
||||||
{
|
{
|
||||||
return (*VLC->townh)[faction]->alignment == EAlignment::EVIL;
|
return VLC->factions()->getByIndex(faction)->getAlignment() == EAlignment::EVIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
si32 CCreature::maxAmount(const TResources &res) const //how many creatures can be bought
|
si32 CCreature::maxAmount(const TResources &res) const //how many creatures can be bought
|
||||||
@ -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
|
||||||
@ -335,7 +345,7 @@ TerrainId CCreature::getNativeTerrain() const
|
|||||||
//and in the CGHeroInstance::getNativeTerrain() to setup movement bonuses or/and penalties.
|
//and in the CGHeroInstance::getNativeTerrain() to setup movement bonuses or/and penalties.
|
||||||
return hasBonus(selectorNoTerrainPenalty, cachingStringNoTerrainPenalty)
|
return hasBonus(selectorNoTerrainPenalty, cachingStringNoTerrainPenalty)
|
||||||
? TerrainId(ETerrainId::ANY_TERRAIN)
|
? TerrainId(ETerrainId::ANY_TERRAIN)
|
||||||
: (*VLC->townh)[faction]->nativeTerrain;
|
: VLC->factions()->getByIndex(faction)->getNativeTerrain();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CCreature::updateFrom(const JsonNode & data)
|
void CCreature::updateFrom(const JsonNode & data)
|
||||||
@ -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())
|
||||||
|
@ -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;
|
||||||
|
@ -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
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
|
@ -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;
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -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)
|
||||||
|
@ -147,9 +147,9 @@ bool CHeroClass::isMagicHero() const
|
|||||||
return affinity == MAGIC;
|
return affinity == MAGIC;
|
||||||
}
|
}
|
||||||
|
|
||||||
EAlignment::EAlignment CHeroClass::getAlignment() const
|
EAlignment CHeroClass::getAlignment() const
|
||||||
{
|
{
|
||||||
return ((*VLC->townh)[faction]->alignment);
|
return VLC->factions()->getByIndex(faction)->getAlignment();
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t CHeroClass::getIndex() const
|
int32_t CHeroClass::getIndex() const
|
||||||
@ -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>();
|
||||||
|
@ -196,7 +196,7 @@ public:
|
|||||||
secSkillProbability[i] = 0;
|
secSkillProbability[i] = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
EAlignment::EAlignment getAlignment() const;
|
EAlignment getAlignment() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
class DLL_LINKAGE CHeroClassHandler : public CHandlerBase<HeroClassID, HeroClass, CHeroClass, HeroClassService>
|
class DLL_LINKAGE CHeroClassHandler : public CHandlerBase<HeroClassID, HeroClass, CHeroClass, HeroClassService>
|
||||||
|
@ -45,11 +45,37 @@ std::string PlayerState::nodeName() const
|
|||||||
return "Player " + color.getStrCap(false);
|
return "Player " + color.getStrCap(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
PlayerColor PlayerState::getColor() const
|
PlayerColor PlayerState::getId() const
|
||||||
{
|
{
|
||||||
return color;
|
return color;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int32_t PlayerState::getIndex() const
|
||||||
|
{
|
||||||
|
return color.getNum();
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t PlayerState::getIconIndex() const
|
||||||
|
{
|
||||||
|
return color.getNum();
|
||||||
|
}
|
||||||
|
std::string PlayerState::getJsonKey() const
|
||||||
|
{
|
||||||
|
return color.getStr(false);
|
||||||
|
}
|
||||||
|
std::string PlayerState::getNameTranslated() const
|
||||||
|
{
|
||||||
|
return color.getStr(true);
|
||||||
|
}
|
||||||
|
std::string PlayerState::getNameTextID() const
|
||||||
|
{
|
||||||
|
return color.getStr(false);
|
||||||
|
}
|
||||||
|
void PlayerState::registerIcons(const IconRegistar & cb) const
|
||||||
|
{
|
||||||
|
//We cannot register new icons for players
|
||||||
|
}
|
||||||
|
|
||||||
TeamID PlayerState::getTeam() const
|
TeamID PlayerState::getTeam() const
|
||||||
{
|
{
|
||||||
return team;
|
return team;
|
||||||
@ -60,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;
|
||||||
}
|
}
|
||||||
|
@ -45,12 +45,19 @@ public:
|
|||||||
|
|
||||||
std::string nodeName() const override;
|
std::string nodeName() const override;
|
||||||
|
|
||||||
PlayerColor getColor() 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 getIconIndex() const override;
|
||||||
|
std::string getJsonKey() const override;
|
||||||
|
std::string getNameTranslated() const override;
|
||||||
|
std::string getNameTextID() const override;
|
||||||
|
void registerIcons(const IconRegistar & cb) const override;
|
||||||
|
|
||||||
bool checkVanquished() const
|
bool checkVanquished() const
|
||||||
{
|
{
|
||||||
return heroes.empty() && towns.empty();
|
return heroes.empty() && towns.empty();
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user