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

Reduce usage of pointers to VLC entities

Final goal (of multiple PR's) is to remove all remaining pointers from
serializeable game state, and replace them with either identifiers or
with shared/unique pointers.

CGTownInstance::town and CGHeroInstance::type members have been removed.
Now this data is computed dynamically using subID member.

VLC entity of a town can now be accessed via following methods:
- getFactionID() returns ID of a faction
- getFaction() returns pointer to a faction
- getTown() returns pointer to a town

VLC entity of a hero can now be accessed via following methods:
- getHeroTypeID() returns ID of a hero
- getHeroClassID() returns ID of a hero class
- getHeroType() returns pointer to a hero
- getHeroClass() returns pointer to a hero class
This commit is contained in:
Ivan Savenko 2024-10-05 19:37:52 +00:00
parent 81f0222c68
commit 3dd4fa2528
83 changed files with 445 additions and 468 deletions

View File

@ -1454,7 +1454,7 @@ bool AIGateway::moveHeroToTile(int3 dst, HeroPtr h)
void AIGateway::buildStructure(const CGTownInstance * t, BuildingID building)
{
auto name = t->town->buildings.at(building)->getNameTranslated();
auto name = t->getTown()->buildings.at(building)->getNameTranslated();
logAi->debug("Player %d will build %s in town of %s at %s", ai->playerID, name, t->getNameTranslated(), t->anchorPos().toString());
cb->buildBuilding(t, building); //just do this;
}

View File

@ -144,7 +144,7 @@ std::vector<SlotInfo> ArmyManager::getBestArmy(const IBonusBearer * armyCarrier,
for(auto & slot : sortedSlots)
{
alignmentMap[slot.creature->getFaction()] += slot.power;
alignmentMap[slot.creature->getFactionID()] += slot.power;
}
std::set<FactionID> allowedFactions;
@ -178,7 +178,7 @@ std::vector<SlotInfo> ArmyManager::getBestArmy(const IBonusBearer * armyCarrier,
for(auto & slot : sortedSlots)
{
if(vstd::contains(allowedFactions, slot.creature->getFaction()))
if(vstd::contains(allowedFactions, slot.creature->getFactionID()))
{
auto slotID = newArmyInstance.getSlotFor(slot.creature->getId());

View File

@ -17,7 +17,7 @@ namespace NKAI
void BuildAnalyzer::updateTownDwellings(TownDevelopmentInfo & developmentInfo)
{
auto townInfo = developmentInfo.town->town;
auto townInfo = developmentInfo.town->getTown();
auto creatures = townInfo->creatures;
auto buildings = townInfo->getAllBuildings();
@ -31,7 +31,7 @@ void BuildAnalyzer::updateTownDwellings(TownDevelopmentInfo & developmentInfo)
}
}
for(int level = 0; level < developmentInfo.town->town->creatures.size(); level++)
for(int level = 0; level < developmentInfo.town->getTown()->creatures.size(); level++)
{
logAi->trace("Checking dwelling level %d", level);
BuildingInfo nextToBuild = BuildingInfo();
@ -82,7 +82,7 @@ void BuildAnalyzer::updateOtherBuildings(TownDevelopmentInfo & developmentInfo)
{
for(auto & buildingID : buildingSet)
{
if(!developmentInfo.town->hasBuilt(buildingID) && developmentInfo.town->town->buildings.count(buildingID))
if(!developmentInfo.town->hasBuilt(buildingID) && developmentInfo.town->getTown()->buildings.count(buildingID))
{
developmentInfo.addBuildingToBuild(getBuildingOrPrerequisite(developmentInfo.town, buildingID));
@ -198,7 +198,7 @@ BuildingInfo BuildAnalyzer::getBuildingOrPrerequisite(
bool excludeDwellingDependencies) const
{
BuildingID building = toBuild;
auto townInfo = town->town;
auto townInfo = town->getTown();
const CBuilding * buildPtr = townInfo->buildings.at(building);
const CCreature * creature = nullptr;
@ -327,7 +327,7 @@ bool BuildAnalyzer::hasAnyBuilding(int32_t alignment, BuildingID bid) const
{
for(auto tdi : developmentInfos)
{
if(tdi.town->getFaction() == alignment && tdi.town->hasBuilt(bid))
if(tdi.town->getFactionID() == alignment && tdi.town->hasBuilt(bid))
return true;
}

View File

@ -71,7 +71,7 @@ float HeroManager::evaluateSecSkill(SecondarySkill skill, const CGHeroInstance *
float HeroManager::evaluateSpeciality(const CGHeroInstance * hero) const
{
auto heroSpecial = Selector::source(BonusSource::HERO_SPECIAL, BonusSourceID(hero->type->getId()));
auto heroSpecial = Selector::source(BonusSource::HERO_SPECIAL, BonusSourceID(hero->getHeroTypeID()));
auto secondarySkillBonus = Selector::targetSourceType()(BonusSource::SECONDARY_SKILL);
auto specialSecondarySkillBonuses = hero->getBonuses(heroSpecial.And(secondarySkillBonus));
auto secondarySkillBonuses = hero->getBonuses(Selector::sourceTypeSel(BonusSource::SECONDARY_SKILL));

View File

@ -1120,7 +1120,7 @@ public:
uint64_t RewardEvaluator::getUpgradeArmyReward(const CGTownInstance * town, const BuildingInfo & bi) const
{
if(ai->buildAnalyzer->hasAnyBuilding(town->getFaction(), bi.id))
if(ai->buildAnalyzer->hasAnyBuilding(town->getFactionID(), bi.id))
return 0;
auto creaturesToUpgrade = ai->armyManager->getTotalCreaturesAvailable(bi.baseCreatureID);

View File

@ -23,7 +23,7 @@ BuildThis::BuildThis(BuildingID Bid, const CGTownInstance * tid)
: ElementarGoal(Goals::BUILD_STRUCTURE)
{
buildingInfo = BuildingInfo(
tid->town->buildings.at(Bid),
tid->getTown()->buildings.at(Bid),
nullptr,
CreatureID::NONE,
tid,
@ -52,7 +52,7 @@ void BuildThis::accept(AIGateway * ai)
if(cb->canBuildStructure(town, b) == EBuildingState::ALLOWED)
{
logAi->debug("Player %d will build %s in town of %s at %s",
ai->playerID, town->town->buildings.at(b)->getNameTranslated(), town->getNameTranslated(), town->anchorPos().toString());
ai->playerID, town->getTown()->buildings.at(b)->getNameTranslated(), town->getNameTranslated(), town->anchorPos().toString());
cb->buildBuilding(town, b);
return;

View File

@ -23,13 +23,13 @@ bool BuildingManager::tryBuildThisStructure(const CGTownInstance * t, BuildingID
return false;
}
if (!vstd::contains(t->town->buildings, building))
if (!vstd::contains(t->getTown()->buildings, building))
return false; // no such building in town
if (t->hasBuilt(building)) //Already built? Shouldn't happen in general
return true;
const CBuilding * buildPtr = t->town->buildings.at(building);
const CBuilding * buildPtr = t->getTown()->buildings.at(building);
auto toBuild = buildPtr->requirements.getFulfillmentCandidates([&](const BuildingID & buildID)
{
@ -51,7 +51,7 @@ bool BuildingManager::tryBuildThisStructure(const CGTownInstance * t, BuildingID
for (const auto & buildID : toBuild)
{
const CBuilding * b = t->town->buildings.at(buildID);
const CBuilding * b = t->getTown()->buildings.at(buildID);
EBuildingState canBuild = cb->canBuildStructure(t, buildID);
if (canBuild == EBuildingState::ALLOWED)
@ -220,7 +220,7 @@ bool BuildingManager::getBuildingOptions(const CGTownInstance * t)
//at the end, try to get and build any extra buildings with nonstandard slots (for example HotA 3rd level dwelling)
std::vector<BuildingID> extraBuildings;
for (auto buildingInfo : t->town->buildings)
for (auto buildingInfo : t->getTown()->buildings)
{
if (buildingInfo.first > BuildingID::DWELL_UP2_FIRST)
extraBuildings.push_back(buildingInfo.first);

View File

@ -56,7 +56,7 @@ TSubgoal BuildThis::whatToDoToAchieve()
case EBuildingState::ALLOWED:
case EBuildingState::NO_RESOURCES:
{
auto res = town->town->buildings.at(BuildingID(bid))->resources;
auto res = town->getTown()->buildings.at(BuildingID(bid))->resources;
return ai->ah->whatToDo(res, iAmElementar()); //realize immediately or gather resources
}
break;

View File

@ -88,13 +88,13 @@ TGoalVec GatherTroops::getAllPossibleSubgoals()
}
auto creature = VLC->creatures()->getByIndex(objid);
if(t->getFaction() == creature->getFaction()) //TODO: how to force AI to build unupgraded creatures? :O
if(t->getFactionID() == creature->getFactionID()) //TODO: how to force AI to build unupgraded creatures? :O
{
auto tryFindCreature = [&]() -> std::optional<std::vector<CreatureID>>
{
if(vstd::isValidIndex(t->town->creatures, creature->getLevel() - 1))
if(vstd::isValidIndex(t->getTown()->creatures, creature->getLevel() - 1))
{
auto itr = t->town->creatures.begin();
auto itr = t->getTown()->creatures.begin();
std::advance(itr, creature->getLevel() - 1);
return make_optional(*itr);
}
@ -109,7 +109,7 @@ TGoalVec GatherTroops::getAllPossibleSubgoals()
if(upgradeNumber < 0)
continue;
BuildingID bid(BuildingID::DWELL_FIRST + creature->getLevel() - 1 + upgradeNumber * t->town->creatures.size());
BuildingID bid(BuildingID::DWELL_FIRST + creature->getLevel() - 1 + upgradeNumber * t->getTown()->creatures.size());
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->getAIValue() * this->value).setobjid(objid)));

View File

@ -69,7 +69,7 @@ std::optional<int> MapObjectsEvaluator::getObjectValue(const CGObjectInstance *
{
//special case handling: in-game heroes have hero ID as object subID, but when reading configs available hero object subID's are hero classes
auto hero = dynamic_cast<const CGHeroInstance*>(obj);
return getObjectValue(obj->ID, hero->type->heroClass->getIndex());
return getObjectValue(obj->ID, hero->getHeroClassID());
}
else if(obj->ID == Obj::PRISON)
{

View File

@ -1994,7 +1994,7 @@ bool VCAI::moveHeroToTile(int3 dst, HeroPtr h)
void VCAI::buildStructure(const CGTownInstance * t, BuildingID building)
{
auto name = t->town->buildings.at(building)->getNameTranslated();
auto name = t->getTown()->buildings.at(building)->getNameTranslated();
logAi->debug("Player %d will build %s in town of %s at %s", ai->playerID, name, t->getNameTranslated(), t->anchorPos().toString());
cb->buildBuilding(t, building); //just do this;
}
@ -2081,7 +2081,7 @@ void VCAI::tryRealize(Goals::BuildThis & g)
if (cb->canBuildStructure(t, b) == EBuildingState::ALLOWED)
{
logAi->debug("Player %d will build %s in town of %s at %s",
playerID, t->town->buildings.at(b)->getNameTranslated(), t->getNameTranslated(), t->anchorPos().toString());
playerID, t->getTown()->buildings.at(b)->getNameTranslated(), t->getNameTranslated(), t->anchorPos().toString());
cb->buildBuilding(t, b);
throw goalFulfilledException(sptr(g));
}

View File

@ -319,7 +319,7 @@ void CCallback::recruitHero(const CGObjectInstance *townOrTavern, const CGHeroIn
assert(townOrTavern);
assert(hero);
HireHero pack(hero->getHeroType(), townOrTavern->id, nextHero);
HireHero pack(hero->getHeroTypeID(), townOrTavern->id, nextHero);
pack.player = *player;
sendRequest(pack);
}

View File

@ -1138,7 +1138,7 @@ void CPlayerInterface::showMapObjectSelectDialog(QueryID askID, const Component
const CGTownInstance * t = dynamic_cast<const CGTownInstance *>(cb->getObj(obj));
if(t)
{
auto image = GH.renderHandler().loadImage(AnimationPath::builtin("ITPA"), t->town->clientInfo.icons[t->hasFort()][false] + 2, 0, EImageBlitMode::OPAQUE);
auto image = GH.renderHandler().loadImage(AnimationPath::builtin("ITPA"), t->getTown()->clientInfo.icons[t->hasFort()][false] + 2, 0, EImageBlitMode::OPAQUE);
image->scaleTo(Point(35, 23));
images.push_back(image);
}

View File

@ -453,7 +453,7 @@ void ClientCommandManager::handleTellCommand(std::istringstream& singleWordBuffe
if(what == "hs")
{
for(const CGHeroInstance* h : LOCPLINT->cb->getHeroesInfo())
if(h->type->getIndex() == id1)
if(h->getHeroTypeID().getNum() == id1)
if(const CArtifactInstance* a = h->getArt(ArtifactPosition(id2)))
printCommandMessage(a->nodeName());
}

View File

@ -671,7 +671,7 @@ void ApplyClientNetPackVisitor::visitSetHeroesInTown(SetHeroesInTown & pack)
void ApplyClientNetPackVisitor::visitHeroRecruited(HeroRecruited & pack)
{
CGHeroInstance *h = gs.map->heroesOnMap.back();
if(h->getHeroType() != pack.hid)
if(h->getHeroTypeID() != pack.hid)
{
logNetwork->error("Something wrong with hero recruited!");
}

View File

@ -432,7 +432,7 @@ std::shared_ptr<CIntObject> CTownList::CTownItem::genSelection()
void CTownList::CTownItem::update()
{
size_t iconIndex = town->town->clientInfo.icons[town->hasFort()][town->built >= LOCPLINT->cb->getSettings().getInteger(EGameSettings::TOWNS_BUILDINGS_PER_TURN_CAP)];
size_t iconIndex = town->getTown()->clientInfo.icons[town->hasFort()][town->built >= LOCPLINT->cb->getSettings().getInteger(EGameSettings::TOWNS_BUILDINGS_PER_TURN_CAP)];
picture->setFrame(iconIndex + 2);
redraw();

View File

@ -389,13 +389,13 @@ BattleHero::BattleHero(const BattleInterface & owner, const CGHeroInstance * her
{
AnimationPath animationPath;
if(!hero->type->battleImage.empty())
animationPath = hero->type->battleImage;
if(!hero->getHeroType()->battleImage.empty())
animationPath = hero->getHeroType()->battleImage;
else
if(hero->gender == EHeroGender::FEMALE)
animationPath = hero->type->heroClass->imageBattleFemale;
animationPath = hero->getHeroClass()->imageBattleFemale;
else
animationPath = hero->type->heroClass->imageBattleMale;
animationPath = hero->getHeroClass()->imageBattleMale;
animation = GH.renderHandler().loadAnimation(animationPath, EImageBlitMode::ALPHA);
@ -1027,7 +1027,7 @@ void StackQueue::update()
int32_t StackQueue::getSiegeShooterIconID()
{
return owner.siegeController->getSiegedTown()->town->faction->getIndex();
return owner.siegeController->getSiegedTown()->getFactionID().getNum();
}
std::optional<uint32_t> StackQueue::getHoveredUnitIdIfAny() const

View File

@ -58,14 +58,14 @@ ImagePath BattleSiegeController::getWallPieceImageName(EWallVisual::EWallVisual
};
};
const std::string & prefix = town->town->clientInfo.siegePrefix;
const std::string & prefix = town->getTown()->clientInfo.siegePrefix;
std::string addit = std::to_string(getImageIndex());
switch(what)
{
case EWallVisual::BACKGROUND_WALL:
{
auto faction = town->town->faction->getIndex();
auto faction = town->getFactionID();
if (faction == ETownType::RAMPART || faction == ETownType::NECROPOLIS || faction == ETownType::DUNGEON || faction == ETownType::STRONGHOLD)
return ImagePath::builtinTODO(prefix + "TPW1.BMP");
@ -111,7 +111,7 @@ ImagePath BattleSiegeController::getWallPieceImageName(EWallVisual::EWallVisual
void BattleSiegeController::showWallPiece(Canvas & canvas, EWallVisual::EWallVisual what)
{
auto & ci = town->town->clientInfo;
auto & ci = town->getTown()->clientInfo;
auto const & pos = ci.siegePositions[what];
if ( wallPieceImages[what] && pos.isValid())
@ -120,7 +120,7 @@ void BattleSiegeController::showWallPiece(Canvas & canvas, EWallVisual::EWallVis
ImagePath BattleSiegeController::getBattleBackgroundName() const
{
const std::string & prefix = town->town->clientInfo.siegePrefix;
const std::string & prefix = town->getTown()->clientInfo.siegePrefix;
return ImagePath::builtinTODO(prefix + "BACK.BMP");
}
@ -130,8 +130,8 @@ bool BattleSiegeController::getWallPieceExistence(EWallVisual::EWallVisual what)
switch (what)
{
case EWallVisual::MOAT: return fortifications.hasMoat && town->town->clientInfo.siegePositions.at(EWallVisual::MOAT).isValid();
case EWallVisual::MOAT_BANK: return fortifications.hasMoat && town->town->clientInfo.siegePositions.at(EWallVisual::MOAT_BANK).isValid();
case EWallVisual::MOAT: return fortifications.hasMoat && town->getTown()->clientInfo.siegePositions.at(EWallVisual::MOAT).isValid();
case EWallVisual::MOAT_BANK: return fortifications.hasMoat && town->getTown()->clientInfo.siegePositions.at(EWallVisual::MOAT_BANK).isValid();
case EWallVisual::KEEP_BATTLEMENT: return fortifications.citadelHealth > 0 && owner.getBattle()->battleGetWallState(EWallPart::KEEP) != EWallState::DESTROYED;
case EWallVisual::UPPER_BATTLEMENT: return fortifications.upperTowerHealth > 0 && owner.getBattle()->battleGetWallState(EWallPart::UPPER_TOWER) != EWallState::DESTROYED;
case EWallVisual::BOTTOM_BATTLEMENT: return fortifications.lowerTowerHealth > 0 && owner.getBattle()->battleGetWallState(EWallPart::BOTTOM_TOWER) != EWallState::DESTROYED;
@ -218,8 +218,8 @@ Point BattleSiegeController::getTurretCreaturePosition( BattleHex position ) con
if (posID != 0)
{
return {
town->town->clientInfo.siegePositions[posID].x,
town->town->clientInfo.siegePositions[posID].y
town->getTown()->clientInfo.siegePositions[posID].x,
town->getTown()->clientInfo.siegePositions[posID].y
};
}

View File

@ -468,8 +468,8 @@ void CInteractableTownTooltip::init(const CGTownInstance * town)
LOCPLINT->showTavernWindow(town, nullptr, QueryID::NONE);
}
}, [town]{
if(!town->town->faction->getDescriptionTranslated().empty())
CRClickPopup::createAndPush(town->town->faction->getDescriptionTranslated());
if(!town->getFaction()->getDescriptionTranslated().empty())
CRClickPopup::createAndPush(town->getFaction()->getDescriptionTranslated());
});
fastMarket = std::make_shared<LRClickableArea>(Rect(143, 31, 30, 34), []()
{
@ -532,8 +532,7 @@ CreatureTooltip::CreatureTooltip(Point pos, const CGCreature * creature)
{
OBJECT_CONSTRUCTION;
auto creatureID = creature->getCreature();
int32_t creatureIconIndex = CGI->creatures()->getById(creatureID)->getIconIndex();
int32_t creatureIconIndex = creature->getCreature()->getIconIndex();
creatureImage = std::make_shared<CAnimImage>(AnimationPath::builtin("TWCRPORT"), creatureIconIndex);
creatureImage->center(Point(parent->pos.x + parent->pos.w / 2, parent->pos.y + creatureImage->pos.h / 2 + 11));
@ -633,7 +632,7 @@ CCreaturePic::CCreaturePic(int x, int y, const CCreature * cre, bool Big, bool A
pos.x+=x;
pos.y+=y;
auto faction = cre->getFaction();
auto faction = cre->getFactionID();
assert(CGI->townh->size() > faction);

View File

@ -82,7 +82,7 @@ CBuildingRect::CBuildingRect(CCastleBuildings * Par, const CGTownInstance * Town
// special animation frame manipulation for castle shipyard with and without ship
// done due to .def used in special way, not to animate building - first image is for shipyard without citadel moat, 2nd image is for including moat
if(Town->town->faction->getId() == FactionID::CASTLE && Str->building &&
if(Town->getFactionID() == FactionID::CASTLE && Str->building &&
(Str->building->bid == BuildingID::SHIPYARD || Str->building->bid == BuildingID::SHIP))
{
if(Town->hasBuilt(BuildingID::CITADEL))
@ -107,7 +107,7 @@ const CBuilding * CBuildingRect::getBuilding()
return nullptr;
if (str->hiddenUpgrade) // hidden upgrades, e.g. hordes - return base (dwelling for hordes)
return town->town->buildings.at(str->building->getBase());
return town->getTown()->buildings.at(str->building->getBase());
return str->building;
}
@ -156,7 +156,7 @@ void CBuildingRect::showPopupWindow(const Point & cursorPosition)
return;
BuildingID bid = getBuilding()->bid;
const CBuilding *bld = town->town->buildings.at(bid);
const CBuilding *bld = town->getTown()->buildings.at(bid);
if (bid < BuildingID::DWELL_FIRST)
{
CRClickPopup::createAndPush(CInfoWindow::genText(bld->getNameTranslated(), bld->getDescriptionTranslated()),
@ -235,10 +235,10 @@ std::string CBuildingRect::getSubtitle()//hover text for building
int bid = getBuilding()->bid;
if (bid<30)//non-dwellings - only building name
return town->town->buildings.at(getBuilding()->bid)->getNameTranslated();
return town->getTown()->buildings.at(getBuilding()->bid)->getNameTranslated();
else//dwellings - recruit %creature%
{
auto & availableCreatures = town->creatures[(bid-30)%town->town->creatures.size()].second;
auto & availableCreatures = town->creatures[(bid-30)%town->getTown()->creatures.size()].second;
if(availableCreatures.size())
{
int creaID = availableCreatures.back();//taking last of available creatures
@ -566,7 +566,7 @@ CCastleBuildings::CCastleBuildings(const CGTownInstance* Town):
{
OBJECT_CONSTRUCTION;
background = std::make_shared<CPicture>(town->town->clientInfo.townBackground);
background = std::make_shared<CPicture>(town->getTown()->clientInfo.townBackground);
background->needRefresh = true;
background->getSurface()->setBlitMode(EImageBlitMode::OPAQUE);
pos.w = background->pos.w;
@ -602,7 +602,7 @@ void CCastleBuildings::recreate()
}
}
for(const CStructure * structure : town->town->clientInfo.structures)
for(const CStructure * structure : town->getTown()->clientInfo.structures)
{
if(!structure->building)
{
@ -617,7 +617,7 @@ void CCastleBuildings::recreate()
for(auto & entry : groups)
{
const CBuilding * build = town->town->buildings.at(entry.first);
const CBuilding * build = town->getTown()->buildings.at(entry.first);
const CStructure * toAdd = *boost::max_element(entry.second, [=](const CStructure * a, const CStructure * b)
{
@ -648,7 +648,7 @@ void CCastleBuildings::recreate()
void CCastleBuildings::addBuilding(BuildingID building)
{
//FIXME: implement faster method without complete recreation of town
BuildingID base = town->town->buildings.at(building)->getBase();
BuildingID base = town->getTown()->buildings.at(building)->getBase();
recreate();
@ -687,7 +687,7 @@ void CCastleBuildings::buildingClicked(BuildingID building)
BuildingID buildingToEnter = building;
for(;;)
{
const CBuilding *b = town->town->buildings.find(buildingToEnter)->second;
const CBuilding *b = town->getTown()->buildings.find(buildingToEnter)->second;
if (buildingTryActivateCustomUI(buildingToEnter, building))
return;
@ -705,7 +705,7 @@ void CCastleBuildings::buildingClicked(BuildingID building)
bool CCastleBuildings::buildingTryActivateCustomUI(BuildingID buildingToTest, BuildingID buildingTarget)
{
logGlobal->trace("You've clicked on %d", (int)buildingToTest.toEnum());
const CBuilding *b = town->town->buildings.at(buildingToTest);
const CBuilding *b = town->getTown()->buildings.at(buildingToTest);
if (town->getWarMachineInBuilding(buildingToTest).hasValue())
{
@ -744,7 +744,7 @@ bool CCastleBuildings::buildingTryActivateCustomUI(BuildingID buildingToTest, Bu
}
}
if (town->rewardableBuildings.count(buildingToTest) && town->town->buildings.at(buildingToTest)->manualHeroVisit)
if (town->rewardableBuildings.count(buildingToTest) && town->getTown()->buildings.at(buildingToTest)->manualHeroVisit)
{
enterRewardable(buildingToTest);
return true;
@ -820,10 +820,10 @@ bool CCastleBuildings::buildingTryActivateCustomUI(BuildingID buildingToTest, Bu
return false;
case BuildingSubID::PORTAL_OF_SUMMONING:
if (town->creatures[town->town->creatures.size()].second.empty())//No creatures
if (town->creatures[town->getTown()->creatures.size()].second.empty())//No creatures
LOCPLINT->showInfoDialog(CGI->generaltexth->tcommands[30]);
else
enterDwelling(town->town->creatures.size());
enterDwelling(town->getTown()->creatures.size());
return true;
case BuildingSubID::BANK:
@ -850,7 +850,7 @@ void CCastleBuildings::enterRewardable(BuildingID building)
{
MetaString message;
message.appendTextID("core.genrltxt.273"); // only visiting heroes may visit %s
message.replaceTextID(town->town->buildings.at(building)->getNameTextID());
message.replaceTextID(town->getTown()->buildings.at(building)->getNameTextID());
LOCPLINT->showInfoDialog(message.toString());
}
@ -868,7 +868,7 @@ void CCastleBuildings::enterBlacksmith(BuildingID building, ArtifactID artifactI
const CGHeroInstance *hero = town->visitingHero;
if(!hero)
{
LOCPLINT->showInfoDialog(boost::str(boost::format(CGI->generaltexth->allTexts[273]) % town->town->buildings.find(building)->second->getNameTranslated()));
LOCPLINT->showInfoDialog(boost::str(boost::format(CGI->generaltexth->allTexts[273]) % town->getTown()->buildings.find(building)->second->getNameTranslated()));
return;
}
auto art = artifactID.toArtifact();
@ -897,8 +897,8 @@ void CCastleBuildings::enterBlacksmith(BuildingID building, ArtifactID artifactI
void CCastleBuildings::enterBuilding(BuildingID building)
{
std::vector<std::shared_ptr<CComponent>> comps(1, std::make_shared<CComponent>(ComponentType::BUILDING, BuildingTypeUniqueID(town->getFaction(), building)));
LOCPLINT->showInfoDialog( town->town->buildings.find(building)->second->getDescriptionTranslated(), comps);
std::vector<std::shared_ptr<CComponent>> comps(1, std::make_shared<CComponent>(ComponentType::BUILDING, BuildingTypeUniqueID(town->getFactionID(), building)));
LOCPLINT->showInfoDialog( town->getTown()->buildings.find(building)->second->getDescriptionTranslated(), comps);
}
void CCastleBuildings::enterCastleGate()
@ -915,20 +915,20 @@ void CCastleBuildings::enterCastleGate()
{
const CGTownInstance *t = Town;
if (t->id != this->town->id && t->visitingHero == nullptr && //another town, empty and this is
t->town->faction->getId() == town->town->faction->getId() && //the town of the same faction
t->getFactionID() == town->getFactionID() && //the town of the same faction
t->hasBuilt(BuildingSubID::CASTLE_GATE)) //and the town has a castle gate
{
availableTowns.push_back(t->id.getNum());//add to the list
if(settings["general"]["enableUiEnhancements"].Bool())
{
auto image = GH.renderHandler().loadImage(AnimationPath::builtin("ITPA"), t->town->clientInfo.icons[t->hasFort()][false] + 2, 0, EImageBlitMode::OPAQUE);
auto image = GH.renderHandler().loadImage(AnimationPath::builtin("ITPA"), t->getTown()->clientInfo.icons[t->hasFort()][false] + 2, 0, EImageBlitMode::OPAQUE);
image->scaleTo(Point(35, 23));
images.push_back(image);
}
}
}
auto gateIcon = std::make_shared<CAnimImage>(town->town->clientInfo.buildingsIcons, BuildingID::CASTLE_GATE);//will be deleted by selection window
auto gateIcon = std::make_shared<CAnimImage>(town->getTown()->clientInfo.buildingsIcons, BuildingID::CASTLE_GATE);//will be deleted by selection window
auto wnd = std::make_shared<CObjectListWindow>(availableTowns, gateIcon, CGI->generaltexth->jktexts[40],
CGI->generaltexth->jktexts[41], std::bind (&CCastleInterface::castleTeleport, LOCPLINT->castleInt, _1), 0, images);
wnd->onPopup = [availableTowns](int index) { CRClickPopup::createAndPush(LOCPLINT->cb->getObjInstance(ObjectInstanceID(availableTowns[index])), GH.getCursorPosition()); };
@ -940,7 +940,7 @@ void CCastleBuildings::enterDwelling(int level)
if (level < 0 || level >= town->creatures.size() || town->creatures[level].second.empty())
{
assert(0);
logGlobal->error("Attempt to enter into invalid dwelling of level %d in town %s (%s)", level, town->getNameTranslated(), town->town->faction->getNameTranslated());
logGlobal->error("Attempt to enter into invalid dwelling of level %d in town %s (%s)", level, town->getNameTranslated(), town->getFaction()->getNameTranslated());
return;
}
@ -954,8 +954,8 @@ void CCastleBuildings::enterDwelling(int level)
void CCastleBuildings::enterToTheQuickRecruitmentWindow()
{
const auto beginIt = town->creatures.cbegin();
const auto afterLastIt = town->creatures.size() > town->town->creatures.size()
? std::next(beginIt, town->town->creatures.size())
const auto afterLastIt = town->creatures.size() > town->getTown()->creatures.size()
? std::next(beginIt, town->getTown()->creatures.size())
: town->creatures.cend();
const auto hasSomeoneToRecruit = std::any_of(beginIt, afterLastIt,
[](const auto & creatureInfo) { return creatureInfo.first > 0; });
@ -967,8 +967,8 @@ void CCastleBuildings::enterToTheQuickRecruitmentWindow()
void CCastleBuildings::enterFountain(const BuildingID & building, BuildingSubID::EBuildingSubID subID, BuildingID upgrades)
{
std::vector<std::shared_ptr<CComponent>> comps(1, std::make_shared<CComponent>(ComponentType::BUILDING, BuildingTypeUniqueID(town->getFaction(), building)));
std::string descr = town->town->buildings.find(building)->second->getDescriptionTranslated();
std::vector<std::shared_ptr<CComponent>> comps(1, std::make_shared<CComponent>(ComponentType::BUILDING, BuildingTypeUniqueID(town->getFactionID(), building)));
std::string descr = town->getTown()->buildings.find(building)->second->getDescriptionTranslated();
std::string hasNotProduced;
std::string hasProduced;
@ -977,10 +977,10 @@ void CCastleBuildings::enterFountain(const BuildingID & building, BuildingSubID:
bool isMysticPondOrItsUpgrade = subID == BuildingSubID::MYSTIC_POND
|| (upgrades != BuildingID::NONE
&& town->town->buildings.find(BuildingID(upgrades))->second->subId == BuildingSubID::MYSTIC_POND);
&& town->getTown()->buildings.find(BuildingID(upgrades))->second->subId == BuildingSubID::MYSTIC_POND);
if(upgrades != BuildingID::NONE)
descr += "\n\n"+town->town->buildings.find(BuildingID(upgrades))->second->getDescriptionTranslated();
descr += "\n\n"+town->getTown()->buildings.find(BuildingID(upgrades))->second->getDescriptionTranslated();
if(isMysticPondOrItsUpgrade) //for vanila Rampart like towns
{
@ -1056,7 +1056,7 @@ void CCastleBuildings::enterTownHall()
void CCastleBuildings::openMagesGuild()
{
auto mageGuildBackground = LOCPLINT->castleInt->town->town->clientInfo.guildBackground;
auto mageGuildBackground = LOCPLINT->castleInt->town->getTown()->clientInfo.guildBackground;
GH.windows().createAndPushWindow<CMageGuildScreen>(LOCPLINT->castleInt, mageGuildBackground);
}
@ -1247,7 +1247,7 @@ CTownInfo::CTownInfo(int posX, int posY, const CGTownInstance * Town, bool townH
return;//FIXME: suspicious statement, fix or comment
picture = std::make_shared<CAnimImage>(AnimationPath::builtin("ITMCL.DEF"), town->fortLevel()-1);
}
building = town->town->buildings.at(BuildingID(buildID));
building = town->getTown()->buildings.at(BuildingID(buildID));
pos = picture->pos;
}
@ -1322,7 +1322,7 @@ CCastleInterface::CCastleInterface(const CGTownInstance * Town, const CGTownInst
recreateIcons();
if (!from)
adventureInt->onAudioPaused();
CCS->musich->playMusicFromSet("faction", town->town->faction->getJsonKey(), true, false);
CCS->musich->playMusicFromSet("faction", town->getFaction()->getJsonKey(), true, false);
}
CCastleInterface::~CCastleInterface()
@ -1403,7 +1403,7 @@ void CCastleInterface::removeBuilding(BuildingID bid)
void CCastleInterface::recreateIcons()
{
OBJECT_CONSTRUCTION;
size_t iconIndex = town->town->clientInfo.icons[town->hasFort()][town->built >= LOCPLINT->cb->getSettings().getInteger(EGameSettings::TOWNS_BUILDINGS_PER_TURN_CAP)];
size_t iconIndex = town->getTown()->clientInfo.icons[town->hasFort()][town->built >= LOCPLINT->cb->getSettings().getInteger(EGameSettings::TOWNS_BUILDINGS_PER_TURN_CAP)];
icon->setFrame(iconIndex);
TResources townIncome = town->dailyIncome();
@ -1425,8 +1425,8 @@ void CCastleInterface::recreateIcons()
if(town->hasBuilt(BuildingID::TAVERN))
LOCPLINT->showTavernWindow(town, nullptr, QueryID::NONE);
}, [this]{
if(!town->town->faction->getDescriptionTranslated().empty())
CRClickPopup::createAndPush(town->town->faction->getDescriptionTranslated());
if(!town->getFaction()->getDescriptionTranslated().empty())
CRClickPopup::createAndPush(town->getFaction()->getDescriptionTranslated());
});
creainfo.clear();
@ -1527,7 +1527,7 @@ CHallInterface::CBuildingBox::CBuildingBox(int x, int y, const CGTownInstance *
-1, -1, -1, 0, 0, 1, 2, -1, 1, 1, -1, -1
};
icon = std::make_shared<CAnimImage>(town->town->clientInfo.buildingsIcons, building->bid, 0, 2, 2);
icon = std::make_shared<CAnimImage>(town->getTown()->clientInfo.buildingsIcons, building->bid, 0, 2, 2);
header = std::make_shared<CAnimImage>(AnimationPath::builtin("TPTHBAR"), panelIndex[static_cast<int>(state)], 0, 1, 73);
if(iconIndex[static_cast<int>(state)] >=0)
mark = std::make_shared<CAnimImage>(AnimationPath::builtin("TPTHCHK"), iconIndex[static_cast<int>(state)], 0, 136, 56);
@ -1569,7 +1569,7 @@ void CHallInterface::CBuildingBox::showPopupWindow(const Point & cursorPosition)
}
CHallInterface::CHallInterface(const CGTownInstance * Town):
CWindowObject(PLAYER_COLORED | BORDERED, Town->town->clientInfo.hallBackground),
CWindowObject(PLAYER_COLORED | BORDERED, Town->getTown()->clientInfo.hallBackground),
town(Town)
{
OBJECT_CONSTRUCTION;
@ -1581,10 +1581,10 @@ CHallInterface::CHallInterface(const CGTownInstance * Town):
auto statusbarBackground = std::make_shared<CPicture>(background->getSurface(), barRect, 5, 556);
statusbar = CGStatusBar::create(statusbarBackground);
title = std::make_shared<CLabel>(399, 12, FONT_MEDIUM, ETextAlignment::CENTER, Colors::WHITE, town->town->buildings.at(BuildingID(town->hallLevel()+BuildingID::VILLAGE_HALL))->getNameTranslated());
title = std::make_shared<CLabel>(399, 12, FONT_MEDIUM, ETextAlignment::CENTER, Colors::WHITE, town->getTown()->buildings.at(BuildingID(town->hallLevel()+BuildingID::VILLAGE_HALL))->getNameTranslated());
exit = std::make_shared<CButton>(Point(748, 556), AnimationPath::builtin("TPMAGE1.DEF"), CButton::tooltip(CGI->generaltexth->hcommands[8]), [&](){close();}, EShortcut::GLOBAL_RETURN);
auto & boxList = town->town->clientInfo.hallSlots;
auto & boxList = town->getTown()->clientInfo.hallSlots;
boxes.resize(boxList.size());
for(size_t row=0; row<boxList.size(); row++) //for each row
{
@ -1595,11 +1595,11 @@ CHallInterface::CHallInterface(const CGTownInstance * Town):
{
if (!buildingID.hasValue())
{
logMod->warn("Invalid building ID found in hallSlots of town '%s'", town->town->faction->getJsonKey() );
logMod->warn("Invalid building ID found in hallSlots of town '%s'", town->getFaction()->getJsonKey() );
continue;
}
const CBuilding * current = town->town->buildings.at(buildingID);
const CBuilding * current = town->getTown()->buildings.at(buildingID);
if(town->hasBuilt(buildingID))
{
building = current;
@ -1629,7 +1629,7 @@ CBuildWindow::CBuildWindow(const CGTownInstance *Town, const CBuilding * Buildin
{
OBJECT_CONSTRUCTION;
icon = std::make_shared<CAnimImage>(town->town->clientInfo.buildingsIcons, building->bid, 0, 125, 50);
icon = std::make_shared<CAnimImage>(town->getTown()->clientInfo.buildingsIcons, building->bid, 0, 125, 50);
auto statusbarBackground = std::make_shared<CPicture>(background->getSurface(), Rect(8, pos.h - 26, pos.w - 16, 19), 8, pos.h - 26);
statusbar = CGStatusBar::create(statusbarBackground);
@ -1711,7 +1711,7 @@ std::string CBuildWindow::getTextForState(EBuildingState state)
{
auto toStr = [&](const BuildingID build) -> std::string
{
return town->town->buildings.at(build)->getNameTranslated();
return town->getTown()->buildings.at(build)->getNameTranslated();
};
ret = CGI->generaltexth->allTexts[52];
@ -1721,7 +1721,7 @@ std::string CBuildWindow::getTextForState(EBuildingState state)
case EBuildingState::MISSING_BASE:
{
std::string msg = CGI->generaltexth->translate("vcmi.townHall.missingBase");
ret = boost::str(boost::format(msg) % town->town->buildings.at(building->upgrade)->getNameTranslated());
ret = boost::str(boost::format(msg) % town->getTown()->buildings.at(building->upgrade)->getNameTranslated());
break;
}
}
@ -1780,11 +1780,11 @@ CFortScreen::CFortScreen(const CGTownInstance * town):
{
OBJECT_CONSTRUCTION;
ui32 fortSize = static_cast<ui32>(town->creatures.size());
if(fortSize > town->town->creatures.size() && town->creatures.back().second.empty())
if(fortSize > town->getTown()->creatures.size() && town->creatures.back().second.empty())
fortSize--;
fortSize = std::min(fortSize, static_cast<ui32>(GameConstants::CREATURES_PER_TOWN)); // for 8 creatures + portal of summoning
const CBuilding * fortBuilding = town->town->buildings.at(BuildingID(town->fortLevel()+6));
const CBuilding * fortBuilding = town->getTown()->buildings.at(BuildingID(town->fortLevel()+6));
title = std::make_shared<CLabel>(400, 12, FONT_BIG, ETextAlignment::CENTER, Colors::WHITE, fortBuilding->getNameTranslated());
std::string text = boost::str(boost::format(CGI->generaltexth->fcommands[6]) % fortBuilding->getNameTranslated());
@ -1810,7 +1810,7 @@ CFortScreen::CFortScreen(const CGTownInstance * town):
for(ui32 i=0; i<fortSize; i++)
{
BuildingID buildingID;
if(fortSize == town->town->creatures.size())
if(fortSize == town->getTown()->creatures.size())
{
BuildingID dwelling = BuildingID::getDwellingFromLevel(i, 1);
@ -1839,7 +1839,7 @@ CFortScreen::CFortScreen(const CGTownInstance * town):
ImagePath CFortScreen::getBgName(const CGTownInstance * town)
{
ui32 fortSize = static_cast<ui32>(town->creatures.size());
if(fortSize > town->town->creatures.size() && town->creatures.back().second.empty())
if(fortSize > town->getTown()->creatures.size() && town->creatures.back().second.empty())
fortSize--;
fortSize = std::min(fortSize, static_cast<ui32>(GameConstants::CREATURES_PER_TOWN)); // for 8 creatures + portal of summoning
@ -1877,7 +1877,7 @@ CFortScreen::RecruitArea::RecruitArea(int posX, int posY, const CGTownInstance *
if(getMyBuilding() != nullptr)
{
buildingIcon = std::make_shared<CAnimImage>(town->town->clientInfo.buildingsIcons, getMyBuilding()->bid, 0, 4, 21);
buildingIcon = std::make_shared<CAnimImage>(town->getTown()->clientInfo.buildingsIcons, getMyBuilding()->bid, 0, 4, 21);
buildingName = std::make_shared<CLabel>(78, 101, FONT_SMALL, ETextAlignment::CENTER, Colors::WHITE, getMyBuilding()->getNameTranslated(), 152);
if(town->hasBuilt(getMyBuilding()->bid))
@ -1913,8 +1913,8 @@ const CCreature * CFortScreen::RecruitArea::getMyCreature()
{
if(!town->creatures.at(level).second.empty()) // built
return town->creatures.at(level).second.back().toCreature();
if(!town->town->creatures.at(level).empty()) // there are creatures on this level
return town->town->creatures.at(level).front().toCreature();
if(!town->getTown()->creatures.at(level).empty()) // there are creatures on this level
return town->getTown()->creatures.at(level).front().toCreature();
return nullptr;
}
@ -1922,17 +1922,17 @@ const CBuilding * CFortScreen::RecruitArea::getMyBuilding()
{
BuildingID myID = BuildingID(BuildingID::getDwellingFromLevel(level, 0));
if (level == town->town->creatures.size())
return town->town->getSpecialBuilding(BuildingSubID::PORTAL_OF_SUMMONING);
if (level == town->getTown()->creatures.size())
return town->getTown()->getSpecialBuilding(BuildingSubID::PORTAL_OF_SUMMONING);
if (!town->town->buildings.count(myID))
if (!town->getTown()->buildings.count(myID))
return nullptr;
const CBuilding * build = town->town->buildings.at(myID);
while (town->town->buildings.count(myID))
const CBuilding * build = town->getTown()->buildings.at(myID);
while (town->getTown()->buildings.count(myID))
{
if (town->hasBuilt(myID))
build = town->town->buildings.at(myID);
build = town->getTown()->buildings.at(myID);
BuildingID::advanceDwelling(myID);
}
@ -1972,7 +1972,7 @@ CMageGuildScreen::CMageGuildScreen(CCastleInterface * owner, const ImagePath & i
{
OBJECT_CONSTRUCTION;
window = std::make_shared<CPicture>(owner->town->town->clientInfo.guildWindow, 332, 76);
window = std::make_shared<CPicture>(owner->town->getTown()->clientInfo.guildWindow, 332, 76);
resdatabar = std::make_shared<CMinorResDataBar>();
resdatabar->moveBy(pos.topLeft(), true);
@ -2007,7 +2007,7 @@ void CMageGuildScreen::updateSpells(ObjectInstanceID tID)
const CGTownInstance * town = LOCPLINT->cb->getTown(townId);
for(size_t i=0; i<town->town->mageLevel; i++)
for(size_t i=0; i<town->getTown()->mageLevel; i++)
{
size_t spellCount = town->spellsAtLevel((int)i+1,false); //spell at level with -1 hmmm?
for(size_t j=0; j<spellCount; j++)

View File

@ -84,7 +84,7 @@ CExchangeWindow::CExchangeWindow(ObjectInstanceID hero1, ObjectInstanceID hero2,
for(int m=0; m < hero->secSkills.size(); ++m)
secSkillIcons[leftRight].push_back(std::make_shared<CAnimImage>(AnimationPath::builtin("SECSK32"), 0, 0, 32 + 36 * m + 454 * leftRight, qeLayout ? 83 : 88));
specImages[leftRight] = std::make_shared<CAnimImage>(AnimationPath::builtin("UN32"), hero->type->imageIndex, 0, 67 + 490 * leftRight, qeLayout ? 41 : 45);
specImages[leftRight] = std::make_shared<CAnimImage>(AnimationPath::builtin("UN32"), hero->getHeroType()->imageIndex, 0, 67 + 490 * leftRight, qeLayout ? 41 : 45);
expImages[leftRight] = std::make_shared<CAnimImage>(AnimationPath::builtin("PSKIL32"), 4, 0, 103 + 490 * leftRight, qeLayout ? 41 : 45);
expValues[leftRight] = std::make_shared<CLabel>(119 + 490 * leftRight, qeLayout ? 66 : 71, FONT_SMALL, ETextAlignment::CENTER, Colors::WHITE);
@ -151,7 +151,7 @@ CExchangeWindow::CExchangeWindow(ObjectInstanceID hero1, ObjectInstanceID hero2,
specialtyAreas[b] = std::make_shared<LRClickableAreaWText>();
specialtyAreas[b]->pos = Rect(Point(pos.x + 69 + 490 * b, pos.y + (qeLayout ? 41 : 45)), Point(32, 32));
specialtyAreas[b]->hoverText = CGI->generaltexth->heroscrn[27];
specialtyAreas[b]->text = hero->type->getSpecialtyDescriptionTranslated();
specialtyAreas[b]->text = hero->getHeroType()->getSpecialtyDescriptionTranslated();
experienceAreas[b] = std::make_shared<LRClickableAreaWText>();
experienceAreas[b]->pos = Rect(Point(pos.x + 105 + 490 * b, pos.y + (qeLayout ? 41 : 45)), Point(32, 32));

View File

@ -184,9 +184,9 @@ void CHeroWindow::update()
name->setText(curHero->getNameTranslated());
title->setText((boost::format(CGI->generaltexth->allTexts[342]) % curHero->level % curHero->getClassNameTranslated()).str());
specArea->text = curHero->type->getSpecialtyDescriptionTranslated();
specImage->setFrame(curHero->type->imageIndex);
specName->setText(curHero->type->getSpecialtyNameTranslated());
specArea->text = curHero->getHeroType()->getSpecialtyDescriptionTranslated();
specImage->setFrame(curHero->getHeroType()->imageIndex);
specName->setText(curHero->getHeroType()->getSpecialtyNameTranslated());
tacticsButton = std::make_shared<CToggleButton>(Point(539, 483), AnimationPath::builtin("hsbtns8.def"), std::make_pair(heroscrn[26], heroscrn[31]), 0, EShortcut::HERO_TOGGLE_TACTICS);
tacticsButton->addHoverText(EButtonState::HIGHLIGHTED, CGI->generaltexth->heroscrn[25]);

View File

@ -300,7 +300,7 @@ int InfoBoxHeroData::getSubID()
else
return 0;
case HERO_SPECIAL:
return hero->type->getIndex();
return hero->getHeroTypeID().getNum();
case HERO_MANA:
case HERO_EXPERIENCE:
return 0;
@ -800,7 +800,7 @@ CTownItem::CTownItem(const CGTownInstance * Town)
garr = std::make_shared<CGarrisonInt>(Point(313, 3), 4, Point(232,0), town->getUpperArmy(), town->visitingHero, true, true, CGarrisonInt::ESlotsLayout::TWO_ROWS);
heroes = std::make_shared<HeroSlots>(town, Point(244,6), Point(475,6), garr, false);
size_t iconIndex = town->town->clientInfo.icons[town->hasFort()][town->built >= LOCPLINT->cb->getSettings().getInteger(EGameSettings::TOWNS_BUILDINGS_PER_TURN_CAP)];
size_t iconIndex = town->getTown()->clientInfo.icons[town->hasFort()][town->built >= LOCPLINT->cb->getSettings().getInteger(EGameSettings::TOWNS_BUILDINGS_PER_TURN_CAP)];
picture = std::make_shared<CAnimImage>(AnimationPath::builtin("ITPT"), iconIndex, 0, 5, 6);
openTown = std::make_shared<LRClickableAreaOpenTown>(Rect(5, 6, 58, 64), town);
@ -823,8 +823,8 @@ CTownItem::CTownItem(const CGTownInstance * Town)
if(town->hasBuilt(BuildingID::TAVERN))
LOCPLINT->showTavernWindow(town, nullptr, QueryID::NONE);
}, [&]{
if(!town->town->faction->getDescriptionTranslated().empty())
CRClickPopup::createAndPush(town->town->faction->getDescriptionTranslated());
if(!town->getTown()->faction->getDescriptionTranslated().empty())
CRClickPopup::createAndPush(town->getFaction()->getDescriptionTranslated());
});
fastMarket = std::make_shared<LRClickableArea>(Rect(153, 6, 65, 64), []()
{

View File

@ -192,7 +192,7 @@ std::string CMarketWindow::getMarketTitle(const ObjectInstanceID marketId, const
{
for(const auto & buildingId : town->getBuildings())
{
if(const auto building = town->town->buildings.at(buildingId); vstd::contains(building->marketModes, mode))
if(const auto building = town->getTown()->buildings.at(buildingId); vstd::contains(building->marketModes, mode))
return building->getNameTranslated();
}
}

View File

@ -522,9 +522,9 @@ CTavernWindow::CTavernWindow(const CGObjectInstance * TavernObj, const std::func
recruit->block(true);
}
if(LOCPLINT->castleInt)
videoPlayer = std::make_shared<VideoWidget>(Point(70, 56), LOCPLINT->castleInt->town->town->clientInfo.tavernVideo, false);
videoPlayer = std::make_shared<VideoWidget>(Point(70, 56), LOCPLINT->castleInt->town->getTown()->clientInfo.tavernVideo, false);
else if(const auto * townObj = dynamic_cast<const CGTownInstance *>(TavernObj))
videoPlayer = std::make_shared<VideoWidget>(Point(70, 56), townObj->town->clientInfo.tavernVideo, false);
videoPlayer = std::make_shared<VideoWidget>(Point(70, 56), townObj->getTown()->clientInfo.tavernVideo, false);
else
videoPlayer = std::make_shared<VideoWidget>(Point(70, 56), VideoPath::builtin("TAVERN.BIK"), false);
@ -548,7 +548,7 @@ void CTavernWindow::addInvite()
if(!inviteableHeroes.empty())
{
int imageIndex = heroToInvite ? (*CGI->heroh)[heroToInvite->getHeroType()]->imageIndex : 156; // 156 => special id for random
int imageIndex = heroToInvite ? heroToInvite->getIconIndex() : 156; // 156 => special id for random
if(!heroToInvite)
heroToInvite = (*RandomGeneratorUtil::nextItem(inviteableHeroes, CRandomGenerator::getDefault())).second;
@ -563,7 +563,7 @@ void CTavernWindow::recruitb()
const CGHeroInstance *toBuy = (selected ? h2 : h1)->h;
const CGObjectInstance *obj = tavernObj;
LOCPLINT->cb->recruitHero(obj, toBuy, heroToInvite ? heroToInvite->getHeroType() : HeroTypeID::NONE);
LOCPLINT->cb->recruitHero(obj, toBuy, heroToInvite ? heroToInvite->getHeroTypeID() : HeroTypeID::NONE);
close();
}
@ -963,7 +963,7 @@ CUniversityWindow::CUniversityWindow(const CGHeroInstance * _hero, BuildingID bu
if(auto town = dynamic_cast<const CGTownInstance *>(_market))
{
auto faction = town->town->faction->getId();
auto faction = town->getTown()->faction->getId();
titlePic = std::make_shared<CAnimImage>((*CGI->townh)[faction]->town->clientInfo.buildingsIcons, building);
}
else if(auto uni = dynamic_cast<const CGUniversity *>(_market); uni->appearance)

View File

@ -51,9 +51,9 @@ void QuickRecruitmentWindow::setCreaturePurchaseCards()
{
int availableAmount = getAvailableCreatures();
Point position = Point((pos.w - 100*availableAmount - 8*(availableAmount-1))/2,64);
for (int i = 0; i < town->town->creatures.size(); i++)
for (int i = 0; i < town->getTown()->creatures.size(); i++)
{
if(!town->town->creatures.at(i).empty() && !town->creatures.at(i).second.empty() && town->creatures[i].first)
if(!town->getTown()->creatures.at(i).empty() && !town->creatures.at(i).second.empty() && town->creatures[i].first)
{
cards.push_back(std::make_shared<CreaturePurchaseCard>(town->creatures[i].second, position, town->creatures[i].first, this));
position.x += 108;
@ -108,7 +108,7 @@ void QuickRecruitmentWindow::purchaseUnits()
{
int level = 0;
int i = 0;
for(auto c : town->town->creatures)
for(auto c : town->getTown()->creatures)
{
for(auto c2 : c)
if(c2 == selected->creatureOnTheCard->getId())
@ -129,8 +129,8 @@ void QuickRecruitmentWindow::purchaseUnits()
int QuickRecruitmentWindow::getAvailableCreatures()
{
int creaturesAmount = 0;
for (int i=0; i< town->town->creatures.size(); i++)
if(!town->town->creatures.at(i).empty() && !town->creatures.at(i).second.empty() && town->creatures[i].first)
for (int i=0; i< town->getTown()->creatures.size(); i++)
if(!town->getTown()->creatures.at(i).empty() && !town->creatures.at(i).second.empty() && town->creatures[i].first)
creaturesAmount++;
return creaturesAmount;
}

View File

@ -26,7 +26,7 @@ class DLL_LINKAGE INativeTerrainProvider
{
public:
virtual TerrainId getNativeTerrain() const = 0;
virtual FactionID getFaction() const = 0;
virtual FactionID getFactionID() const = 0;
virtual bool isNativeTerrain(TerrainId terrain) const;
};

View File

@ -38,7 +38,7 @@ TerrainId AFactionMember::getNativeTerrain() const
//this code is used in the CreatureTerrainLimiter::limit to setup battle bonuses
//and in the CGHeroInstance::getNativeTerrain() to setup movement bonuses or/and penalties.
return getBonusBearer()->hasBonus(selectorNoTerrainPenalty, cachingStringNoTerrainPenalty)
? TerrainId::ANY_TERRAIN : VLC->factions()->getById(getFaction())->getNativeTerrain();
? TerrainId::ANY_TERRAIN : getFactionID().toEntity(VLC)->getNativeTerrain();
}
int32_t AFactionMember::magicResistance() const

View File

@ -117,7 +117,7 @@ int32_t CCreature::getHorde() const
return hordeGrowth;
}
FactionID CCreature::getFaction() const
FactionID CCreature::getFactionID() const
{
return FactionID(faction);
}

View File

@ -127,7 +127,7 @@ public:
std::string getNamePluralTextID() const override;
std::string getNameSingularTextID() const override;
FactionID getFaction() const override;
FactionID getFactionID() const override;
int32_t getIndex() const override;
int32_t getIconIndex() const override;
std::string getJsonKey() const override;

View File

@ -912,10 +912,10 @@ void CStackInstance::serializeJson(JsonSerializeFormat & handler)
}
}
FactionID CStackInstance::getFaction() const
FactionID CStackInstance::getFactionID() const
{
if(type)
return type->getFaction();
return type->getFactionID();
return FactionID::NEUTRAL;
}

View File

@ -106,7 +106,7 @@ public:
//IConstBonusProvider
const IBonusBearer* getBonusBearer() const override;
//INativeTerrainProvider
FactionID getFaction() const override;
FactionID getFactionID() const override;
virtual ui64 getPower() const;
CCreature::CreatureQuantityId getQuantityID() const;

View File

@ -381,7 +381,7 @@ bool CGameInfoCallback::getHeroInfo(const CGObjectInstance * hero, InfoAboutHero
for(const auto & creature : VLC->creh->objects)
{
if(creature->getFaction() == factionIndex && static_cast<int>(creature->getAIValue()) > maxAIValue)
if(creature->getFactionID() == factionIndex && static_cast<int>(creature->getAIValue()) > maxAIValue)
{
maxAIValue = creature->getAIValue();
mostStrong = creature.get();
@ -575,10 +575,10 @@ EBuildingState CGameInfoCallback::canBuildStructure( const CGTownInstance *t, Bu
{
ERROR_RET_VAL_IF(!canGetFullInfo(t), "Town is not owned!", EBuildingState::TOWN_NOT_OWNED);
if(!t->town->buildings.count(ID))
if(!t->getTown()->buildings.count(ID))
return EBuildingState::BUILDING_ERROR;
const CBuilding * building = t->town->buildings.at(ID);
const CBuilding * building = t->getTown()->buildings.at(ID);
if(t->hasBuilt(ID)) //already built

View File

@ -416,9 +416,9 @@ int32_t CUnitState::creatureIconIndex() const
return unitType()->getIconIndex();
}
FactionID CUnitState::getFaction() const
FactionID CUnitState::getFactionID() const
{
return unitType()->getFaction();
return unitType()->getFactionID();
}
int32_t CUnitState::getCasterUnitId() const

View File

@ -253,7 +253,7 @@ public:
void localInit(const IUnitEnvironment * env_);
void serializeJson(JsonSerializeFormat & handler);
FactionID getFaction() const override;
FactionID getFactionID() const override;
void afterAttack(bool ranged, bool counter);

View File

@ -300,15 +300,15 @@ ILimiter::EDecision FactionLimiter::limit(const BonusLimitationContext &context)
if(bearer)
{
if(faction != FactionID::DEFAULT)
return bearer->getFaction() == faction ? ILimiter::EDecision::ACCEPT : ILimiter::EDecision::DISCARD;
return bearer->getFactionID() == faction ? ILimiter::EDecision::ACCEPT : ILimiter::EDecision::DISCARD;
switch(context.b.source)
{
case BonusSource::CREATURE_ABILITY:
return bearer->getFaction() == context.b.sid.as<CreatureID>().toCreature()->getFaction() ? ILimiter::EDecision::ACCEPT : ILimiter::EDecision::DISCARD;
return bearer->getFactionID() == context.b.sid.as<CreatureID>().toCreature()->getFactionID() ? ILimiter::EDecision::ACCEPT : ILimiter::EDecision::DISCARD;
case BonusSource::TOWN_STRUCTURE:
return bearer->getFaction() == context.b.sid.as<BuildingTypeUniqueID>().getFaction() ? ILimiter::EDecision::ACCEPT : ILimiter::EDecision::DISCARD;
return bearer->getFactionID() == context.b.sid.as<BuildingTypeUniqueID>().getFaction() ? ILimiter::EDecision::ACCEPT : ILimiter::EDecision::DISCARD;
//TODO: other sources of bonuses
}

View File

@ -351,14 +351,14 @@ void CampaignState::setCurrentMapAsConquered(std::vector<CGHeroInstance *> heroe
{
JsonNode node = CampaignState::crossoverSerialize(hero);
if (reservedHeroes.count(hero->getHeroType()))
if (reservedHeroes.count(hero->getHeroTypeID()))
{
logGlobal->info("Hero crossover: %d (%s) exported to global pool", hero->getHeroType(), hero->getNameTranslated());
globalHeroPool[hero->getHeroType()] = node;
logGlobal->info("Hero crossover: %d (%s) exported to global pool", hero->getHeroTypeID(), hero->getNameTranslated());
globalHeroPool[hero->getHeroTypeID()] = node;
}
else
{
logGlobal->info("Hero crossover: %d (%s) exported to scenario pool", hero->getHeroType(), hero->getNameTranslated());
logGlobal->info("Hero crossover: %d (%s) exported to scenario pool", hero->getHeroTypeID(), hero->getNameTranslated());
scenarioHeroPool[*currentMap].push_back(node);
}
}

View File

@ -92,7 +92,7 @@ FactionID CFaction::getId() const
return FactionID(index);
}
FactionID CFaction::getFaction() const
FactionID CFaction::getFactionID() const
{
return FactionID(index);
}

View File

@ -39,7 +39,7 @@ class DLL_LINKAGE CFaction : public Faction
FactionID index = FactionID::NEUTRAL;
FactionID getFaction() const override; //This function should not be used
FactionID getFactionID() const override; //This function should not be used
public:
TerrainId nativeTerrain;

View File

@ -599,7 +599,7 @@ void CGameState::initHeroes()
}
hero->initHero(getRandomGenerator());
map->allHeroes[hero->getHeroType().getNum()] = hero;
map->allHeroes[hero->getHeroTypeID().getNum()] = hero;
}
// generate boats for all heroes on water
@ -629,20 +629,20 @@ void CGameState::initHeroes()
{
auto * hero = dynamic_cast<CGHeroInstance*>(obj.get());
hero->initHero(getRandomGenerator());
map->allHeroes[hero->getHeroType().getNum()] = hero;
map->allHeroes[hero->getHeroTypeID().getNum()] = hero;
}
}
std::set<HeroTypeID> heroesToCreate = getUnusedAllowedHeroes(); //ids of heroes to be created and put into the pool
for(auto ph : map->predefinedHeroes)
{
if(!vstd::contains(heroesToCreate, ph->getHeroType()))
if(!vstd::contains(heroesToCreate, ph->getHeroTypeID()))
continue;
ph->initHero(getRandomGenerator());
heroesPool->addHeroToPool(ph);
heroesToCreate.erase(ph->type->getId());
heroesToCreate.erase(ph->getHeroTypeID());
map->allHeroes[ph->getHeroType().getNum()] = ph;
map->allHeroes[ph->getHeroTypeID().getNum()] = ph;
}
for(const HeroTypeID & htype : heroesToCreate) //all not used allowed heroes go with default state into the pool
@ -756,12 +756,12 @@ void CGameState::initTownNames()
for(auto & vti : map->towns)
{
assert(vti->town);
assert(vti->getTown());
if(!vti->getNameTextID().empty())
continue;
FactionID faction = vti->getFaction();
FactionID faction = vti->getFactionID();
if(availableNames.empty())
{
@ -798,8 +798,8 @@ void CGameState::initTowns()
for (auto & vti : map->towns)
{
assert(vti->town);
assert(vti->town->creatures.size() <= GameConstants::CREATURES_PER_TOWN);
assert(vti->getTown());
assert(vti->getTown()->creatures.size() <= GameConstants::CREATURES_PER_TOWN);
constexpr std::array basicDwellings = { BuildingID::DWELL_FIRST, BuildingID::DWELL_LVL_2, BuildingID::DWELL_LVL_3, BuildingID::DWELL_LVL_4, BuildingID::DWELL_LVL_5, BuildingID::DWELL_LVL_6, BuildingID::DWELL_LVL_7, BuildingID::DWELL_LVL_8 };
constexpr std::array upgradedDwellings = { BuildingID::DWELL_UP_FIRST, BuildingID::DWELL_LVL_2_UP, BuildingID::DWELL_LVL_3_UP, BuildingID::DWELL_LVL_4_UP, BuildingID::DWELL_LVL_5_UP, BuildingID::DWELL_LVL_6_UP, BuildingID::DWELL_LVL_7_UP, BuildingID::DWELL_LVL_8_UP };
@ -828,7 +828,7 @@ void CGameState::initTowns()
vti->addBuilding(BuildingID::VILLAGE_HALL);
//init hordes
for (int i = 0; i < vti->town->creatures.size(); i++)
for (int i = 0; i < vti->getTown()->creatures.size(); i++)
{
if(vti->hasBuilt(hordes[i])) //if we have horde for this level
{
@ -894,7 +894,7 @@ void CGameState::initTowns()
int sel = -1;
for(ui32 ps=0;ps<vti->possibleSpells.size();ps++)
total += vti->possibleSpells[ps].toSpell()->getProbability(vti->getFaction());
total += vti->possibleSpells[ps].toSpell()->getProbability(vti->getFactionID());
if (total == 0) // remaining spells have 0 probability
break;
@ -902,7 +902,7 @@ void CGameState::initTowns()
auto r = getRandomGenerator().nextInt(total - 1);
for(ui32 ps=0; ps<vti->possibleSpells.size();ps++)
{
r -= vti->possibleSpells[ps].toSpell()->getProbability(vti->getFaction());
r -= vti->possibleSpells[ps].toSpell()->getProbability(vti->getFactionID());
if(r<0)
{
sel = ps;
@ -1655,18 +1655,13 @@ std::set<HeroTypeID> CGameState::getUnusedAllowedHeroes(bool alsoIncludeNotAllow
}
for(auto hero : map->heroesOnMap) //heroes instances initialization
{
if(hero->type)
ret -= hero->type->getId();
else
ret -= hero->getHeroType();
}
ret -= hero->getHeroTypeID();
for(auto obj : map->objects) //prisons
{
auto * hero = dynamic_cast<const CGHeroInstance *>(obj.get());
if(hero && hero->ID == Obj::PRISON)
ret -= hero->getHeroType();
ret -= hero->getHeroTypeID();
}
return ret;
@ -1690,7 +1685,7 @@ CGHeroInstance * CGameState::getUsedHero(const HeroTypeID & hid) const
auto * hero = dynamic_cast<CGHeroInstance *>(obj.get());
assert(hero);
if (hero->getHeroType() == hid)
if (hero->getHeroTypeID() == hid)
return hero;
}

View File

@ -86,7 +86,7 @@ void CGameStateCampaign::trimCrossoverHeroesParameters(const CampaignTravel & tr
.And(Selector::subtype()(BonusSubtypeID(g)))
.And(Selector::sourceType()(BonusSource::HERO_BASE_SKILL));
hero.hero->getLocalBonus(sel)->val = hero.hero->type->heroClass->primarySkillInitial[g.getNum()];
hero.hero->getLocalBonus(sel)->val = hero.hero->getHeroClass()->primarySkillInitial[g.getNum()];
}
}
}
@ -96,7 +96,7 @@ void CGameStateCampaign::trimCrossoverHeroesParameters(const CampaignTravel & tr
//trimming sec skills
for(auto & hero : campaignHeroReplacements)
{
hero.hero->secSkills = hero.hero->type->secSkillsInit;
hero.hero->secSkills = hero.hero->getHeroType()->secSkillsInit;
hero.hero->recreateSecondarySkillsBonuses();
}
}
@ -240,7 +240,7 @@ void CGameStateCampaign::placeCampaignHeroes()
for(auto & replacement : campaignHeroReplacements)
if (replacement.heroPlaceholderId.hasValue())
heroesToRemove.insert(replacement.hero->getHeroType());
heroesToRemove.insert(replacement.hero->getHeroTypeID());
for(auto & heroID : heroesToRemove)
{
@ -369,8 +369,8 @@ void CGameStateCampaign::replaceHeroesPlaceholders()
if(heroPlaceholder->tempOwner.isValidPlayer())
heroToPlace->tempOwner = heroPlaceholder->tempOwner;
heroToPlace->setAnchorPos(heroPlaceholder->anchorPos());
heroToPlace->type = heroToPlace->getHeroType().toHeroType();
heroToPlace->appearance = VLC->objtypeh->getHandlerFor(Obj::HERO, heroToPlace->type->heroClass->getIndex())->getTemplates().front();
heroToPlace->setHeroType(heroToPlace->getHeroTypeID());
heroToPlace->appearance = VLC->objtypeh->getHandlerFor(Obj::HERO, heroToPlace->getHeroTypeID())->getTemplates().front();
gameState->map->removeBlockVisTiles(heroPlaceholder, true);
gameState->map->objects[heroPlaceholder->id.getNum()] = nullptr;
@ -563,7 +563,7 @@ void CGameStateCampaign::initHeroes()
{
for (auto & hero : heroes)
{
if (hero->getHeroType().getNum() == chosenBonus->info1)
if (hero->getHeroTypeID().getNum() == chosenBonus->info1)
{
giveCampaignBonusToHero(hero);
break;
@ -662,7 +662,7 @@ void CGameStateCampaign::initTowns()
if(gameState->scenarioOps->campState->formatVCMI())
newBuilding = BuildingID(chosenBonus->info1);
else
newBuilding = CBuildingHandler::campToERMU(chosenBonus->info1, town->getFaction(), town->getBuildings());
newBuilding = CBuildingHandler::campToERMU(chosenBonus->info1, town->getFactionID(), town->getBuildings());
// Build granted building & all prerequisites - e.g. Mages Guild Lvl 3 should also give Mages Guild Lvl 1 & 2
while(true)
@ -675,7 +675,7 @@ void CGameStateCampaign::initTowns()
town->addBuilding(newBuilding);
auto building = town->town->buildings.at(newBuilding);
auto building = town->getTown()->buildings.at(newBuilding);
newBuilding = building->upgrade;
}
break;

View File

@ -381,7 +381,7 @@ float Statistic::getTownBuiltRatio(const PlayerState * ps)
for(const auto & t : ps->getTowns())
{
built += t->getBuildings().size();
for(const auto & b : t->town->buildings)
for(const auto & b : t->getTown()->buildings)
if(!t->forbiddenBuildings.count(b.first))
total += 1;
}

View File

@ -115,7 +115,7 @@ void InfoAboutHero::initFromHero(const CGHeroInstance *h, InfoAboutHero::EInfoLe
initFromArmy(h, detailed);
hclass = h->type->heroClass;
hclass = h->getHeroClass();
name = h->getNameTranslated();
portraitSource = h->getPortraitSource();

View File

@ -25,7 +25,7 @@ std::map<HeroTypeID, CGHeroInstance*> TavernHeroesPool::unusedHeroesFromPool() c
{
std::map<HeroTypeID, CGHeroInstance*> pool = heroesPool;
for(const auto & slot : currentTavern)
pool.erase(slot.hero->getHeroType());
pool.erase(slot.hero->getHeroTypeID());
return pool;
}
@ -34,7 +34,7 @@ TavernSlotRole TavernHeroesPool::getSlotRole(HeroTypeID hero) const
{
for (auto const & slot : currentTavern)
{
if (slot.hero->getHeroType() == hero)
if (slot.hero->getHeroTypeID() == hero)
return slot.role;
}
return TavernSlotRole::NONE;
@ -106,7 +106,7 @@ CGHeroInstance * TavernHeroesPool::takeHeroFromPool(HeroTypeID hero)
heroesPool.erase(hero);
vstd::erase_if(currentTavern, [&](const TavernSlot & entry){
return entry.hero->type->getId() == hero;
return entry.hero->getHeroTypeID() == hero;
});
assert(result);
@ -138,7 +138,7 @@ void TavernHeroesPool::onNewDay()
void TavernHeroesPool::addHeroToPool(CGHeroInstance * hero)
{
heroesPool[hero->getHeroType()] = hero;
heroesPool[hero->getHeroTypeID()] = hero;
}
void TavernHeroesPool::setAvailability(HeroTypeID hero, std::set<PlayerColor> mask)

View File

@ -96,7 +96,6 @@ bool CTownInstanceConstructor::objectFilter(const CGObjectInstance * object, std
void CTownInstanceConstructor::initializeObject(CGTownInstance * obj) const
{
obj->town = faction->town;
obj->tempOwner = PlayerColor::NEUTRAL;
}
@ -144,7 +143,7 @@ bool CHeroInstanceConstructor::objectFilter(const CGObjectInstance * object, std
auto heroTest = [&](const HeroTypeID & id)
{
return hero->type->getId() == id;
return hero->getHeroTypeID() == id;
};
if(filters.count(templ->stringID))
@ -154,11 +153,6 @@ bool CHeroInstanceConstructor::objectFilter(const CGObjectInstance * object, std
return false;
}
void CHeroInstanceConstructor::initializeObject(CGHeroInstance * obj) const
{
obj->type = nullptr; //FIXME: set to valid value. somehow.
}
void CHeroInstanceConstructor::randomizeObject(CGHeroInstance * object, vstd::RNG & rng) const
{

View File

@ -81,7 +81,6 @@ public:
const CHeroClass * heroClass = nullptr;
std::map<std::string, LogicalExpression<HeroTypeID>> filters;
void initializeObject(CGHeroInstance * object) const override;
void randomizeObject(CGHeroInstance * object, vstd::RNG & rng) const override;
void afterLoadFinalization() override;

View File

@ -78,7 +78,7 @@ void CArmedInstance::updateMoraleBonusFromArmy()
const CStackInstance * inst = slot.second;
const auto * creature = inst->getCreatureID().toEntity(VLC);
factions.insert(creature->getFaction());
factions.insert(creature->getFactionID());
// Check for undead flag instead of faction (undead mummies are neutral)
if (!hasUndead)
{

View File

@ -45,7 +45,7 @@ std::string CGCreature::getHoverText(PlayerColor player) const
else
ms.appendLocalString(EMetaText::ARRAY_TXT, quantityTextIndex);
ms.appendRawString(" ");
ms.appendNamePlural(getCreature());
ms.appendNamePlural(getCreatureID());
return ms.toString();
}
@ -57,7 +57,7 @@ std::string CGCreature::getHoverText(const CGHeroInstance * hero) const
MetaString ms;
ms.appendNumber(stacks.begin()->second->count);
ms.appendRawString(" ");
ms.appendName(getCreature(), stacks.begin()->second->count);
ms.appendName(getCreatureID(), stacks.begin()->second->count);
return ms.toString();
}
else
@ -69,11 +69,11 @@ std::string CGCreature::getHoverText(const CGHeroInstance * hero) const
std::string CGCreature::getMonsterLevelText() const
{
std::string monsterLevel = VLC->generaltexth->translate("vcmi.adventureMap.monsterLevel");
bool isRanged = VLC->creatures()->getById(getCreature())->getBonusBearer()->hasBonusOfType(BonusType::SHOOTER);
bool isRanged = getCreature()->getBonusBearer()->hasBonusOfType(BonusType::SHOOTER);
std::string attackTypeKey = isRanged ? "vcmi.adventureMap.monsterRangedType" : "vcmi.adventureMap.monsterMeleeType";
std::string attackType = VLC->generaltexth->translate(attackTypeKey);
boost::replace_first(monsterLevel, "%TOWN", (*VLC->townh)[VLC->creatures()->getById(getCreature())->getFaction()]->getNameTranslated());
boost::replace_first(monsterLevel, "%LEVEL", std::to_string(VLC->creatures()->getById(getCreature())->getLevel()));
boost::replace_first(monsterLevel, "%TOWN", getCreature()->getFactionID().toEntity(VLC)->getNameTranslated());
boost::replace_first(monsterLevel, "%LEVEL", std::to_string(getCreature()->getLevel()));
boost::replace_first(monsterLevel, "%ATTACK_TYPE", attackType);
return monsterLevel;
}
@ -150,7 +150,7 @@ std::string CGCreature::getPopupText(PlayerColor player) const
std::vector<Component> CGCreature::getPopupComponents(PlayerColor player) const
{
return {
Component(ComponentType::CREATURE, getCreature())
Component(ComponentType::CREATURE, getCreatureID())
};
}
@ -182,7 +182,7 @@ void CGCreature::onHeroVisit( const CGHeroInstance * h ) const
BlockingDialog ynd(true,false);
ynd.player = h->tempOwner;
ynd.text.appendLocalString(EMetaText::ADVOB_TXT, 86);
ynd.text.replaceName(getCreature(), getStackCount(SlotID(0)));
ynd.text.replaceName(getCreatureID(), getStackCount(SlotID(0)));
cb->showBlockingDialog(this, &ynd);
break;
}
@ -197,7 +197,7 @@ void CGCreature::onHeroVisit( const CGHeroInstance * h ) const
std::string tmp = VLC->generaltexth->advobtxt[90];
boost::algorithm::replace_first(tmp, "%d", std::to_string(getStackCount(SlotID(0))));
boost::algorithm::replace_first(tmp, "%d", std::to_string(action));
boost::algorithm::replace_first(tmp,"%s",VLC->creatures()->getById(getCreature())->getNamePluralTranslated());
boost::algorithm::replace_first(tmp,"%s",getCreature()->getNamePluralTranslated());
ynd.text.appendRawString(tmp);
cb->showBlockingDialog(this, &ynd);
break;
@ -205,11 +205,16 @@ void CGCreature::onHeroVisit( const CGHeroInstance * h ) const
}
}
CreatureID CGCreature::getCreature() const
CreatureID CGCreature::getCreatureID() const
{
return CreatureID(getObjTypeIndex().getNum());
}
const CCreature * CGCreature::getCreature() const
{
return getCreatureID().toCreature();
}
void CGCreature::pickRandomObject(vstd::RNG & rand)
{
switch(ID.toEnum())
@ -279,7 +284,7 @@ void CGCreature::initObj(vstd::RNG & rand)
stacks[SlotID(0)]->setType(getCreature());
TQuantity &amount = stacks[SlotID(0)]->count;
const Creature * c = VLC->creatures()->getById(getCreature());
const Creature * c = getCreature();
if(amount == 0)
{
amount = rand.nextInt(c->getAdvMapAmountMin(), c->getAdvMapAmountMax());
@ -353,8 +358,8 @@ int CGCreature::takenAction(const CGHeroInstance *h, bool allowJoin) const
for(const auto & elem : h->Slots())
{
bool isOurUpgrade = vstd::contains(getCreature().toCreature()->upgrades, elem.second->getCreatureID());
bool isOurDowngrade = vstd::contains(elem.second->type->upgrades, getCreature());
bool isOurUpgrade = vstd::contains(getCreature()->upgrades, elem.second->getCreatureID());
bool isOurDowngrade = vstd::contains(elem.second->type->upgrades, getCreatureID());
if(isOurUpgrade || isOurDowngrade)
count += elem.second->count;
@ -380,7 +385,7 @@ int CGCreature::takenAction(const CGHeroInstance *h, bool allowJoin) const
if(diplomacy * 2 + sympathy + 1 >= character)
{
int32_t recruitCost = VLC->creatures()->getById(getCreature())->getRecruitCost(EGameResID::GOLD);
int32_t recruitCost = getCreature()->getRecruitCost(EGameResID::GOLD);
int32_t stackCount = getStackCount(SlotID(0));
return recruitCost * stackCount; //join for gold
}
@ -493,7 +498,7 @@ void CGCreature::flee( const CGHeroInstance * h ) const
BlockingDialog ynd(true,false);
ynd.player = h->tempOwner;
ynd.text.appendLocalString(EMetaText::ADVOB_TXT,91);
ynd.text.replaceName(getCreature(), getStackCount(SlotID(0)));
ynd.text.replaceName(getCreatureID(), getStackCount(SlotID(0)));
cb->showBlockingDialog(this, &ynd);
}
@ -513,7 +518,7 @@ void CGCreature::battleFinished(const CGHeroInstance *hero, const BattleResult &
{
//merge stacks into one
TSlots::const_iterator i;
const CCreature * cre = getCreature().toCreature();
const CCreature * cre = getCreature();
for(i = stacks.begin(); i != stacks.end(); i++)
{
if(cre->isMyUpgrade(i->second->type))

View File

@ -49,7 +49,8 @@ public:
void newTurn(vstd::RNG & rand) const override;
void battleFinished(const CGHeroInstance *hero, const BattleResult &result) const override;
void blockingDialogAnswered(const CGHeroInstance *hero, int32_t answer) const override;
CreatureID getCreature() const;
CreatureID getCreatureID() const;
const CCreature * getCreature() const;
//stack formation depends on position,
bool containsUpgradedStack() const;

View File

@ -93,7 +93,7 @@ FactionID CGDwelling::randomizeFaction(vstd::RNG & rand)
assert(linkedTown->ID == Obj::TOWN);
if(linkedTown->ID==Obj::TOWN)
return linkedTown->getFaction();
return linkedTown->getFactionID();
}
if(!randomizationInfo->allowedFactions.empty())

View File

@ -116,9 +116,9 @@ ui32 CGHeroInstance::getTileMovementCost(const TerrainTile & dest, const Terrain
return static_cast<ui32>(ret);
}
FactionID CGHeroInstance::getFaction() const
FactionID CGHeroInstance::getFactionID() const
{
return FactionID(type->heroClass->faction);
return getHeroClass()->faction;
}
const IBonusBearer* CGHeroInstance::getBonusBearer() const
@ -229,10 +229,10 @@ bool CGHeroInstance::canLearnSkill(const SecondarySkill & which) const
if (getSecSkillLevel(which) > 0)
return false;
if (type->heroClass->secSkillProbability.count(which) == 0)
if (getHeroClass()->secSkillProbability.count(which) == 0)
return false;
if (type->heroClass->secSkillProbability.at(which) == 0)
if (getHeroClass()->secSkillProbability.at(which) == 0)
return false;
return true;
@ -282,7 +282,6 @@ int CGHeroInstance::movementPointsLimitCached(bool onLand, const TurnInfo * ti)
CGHeroInstance::CGHeroInstance(IGameCallback * cb)
: CArmedInstance(cb),
type(nullptr),
tacticFormationEnabled(false),
inTownGarrison(false),
moveDir(4),
@ -303,14 +302,30 @@ PlayerColor CGHeroInstance::getOwner() const
return tempOwner;
}
HeroTypeID CGHeroInstance::getHeroType() const
const CHeroClass * CGHeroInstance::getHeroClass() const
{
return getHeroType()->heroClass;
}
HeroClassID CGHeroInstance::getHeroClassID() const
{
return getHeroType()->heroClass->getId();
}
const CHero * CGHeroInstance::getHeroType() const
{
return getHeroTypeID().toHeroType();
}
HeroTypeID CGHeroInstance::getHeroTypeID() const
{
if (ID == Obj::RANDOM_HERO)
return HeroTypeID::NONE;
return HeroTypeID(getObjTypeIndex().getNum());
}
void CGHeroInstance::setHeroType(HeroTypeID heroType)
{
assert(type == nullptr);
subID = heroType;
}
@ -323,16 +338,14 @@ void CGHeroInstance::initHero(vstd::RNG & rand, const HeroTypeID & SUBID)
void CGHeroInstance::initHero(vstd::RNG & rand)
{
assert(validTypes(true));
if(!type)
type = getHeroType().toHeroType();
if (ID == Obj::HERO)
appearance = VLC->objtypeh->getHandlerFor(Obj::HERO, type->heroClass->getIndex())->getTemplates().front();
appearance = VLC->objtypeh->getHandlerFor(Obj::HERO, getHeroClass()->getIndex())->getTemplates().front();
if(!vstd::contains(spells, SpellID::PRESET))
{
// hero starts with default spells
for(const auto & spellID : type->spells)
for(const auto & spellID : getHeroType()->spells)
spells.insert(spellID);
}
else //remove placeholder
@ -341,7 +354,7 @@ void CGHeroInstance::initHero(vstd::RNG & rand)
if(!vstd::contains(spells, SpellID::SPELLBOOK_PRESET))
{
// hero starts with default spellbook presence status
if(!getArt(ArtifactPosition::SPELLBOOK) && type->haveSpellBook)
if(!getArt(ArtifactPosition::SPELLBOOK) && getHeroType()->haveSpellBook)
{
auto artifact = ArtifactUtils::createArtifact(ArtifactID::SPELLBOOK);
putArtifact(ArtifactPosition::SPELLBOOK, artifact);
@ -360,14 +373,14 @@ void CGHeroInstance::initHero(vstd::RNG & rand)
{
for(int g=0; g<GameConstants::PRIMARY_SKILLS; ++g)
{
pushPrimSkill(static_cast<PrimarySkill>(g), type->heroClass->primarySkillInitial[g]);
pushPrimSkill(static_cast<PrimarySkill>(g), getHeroClass()->primarySkillInitial[g]);
}
}
if(secSkills.size() == 1 && secSkills[0] == std::pair<SecondarySkill,ui8>(SecondarySkill::NONE, -1)) //set secondary skills to default
secSkills = type->secSkillsInit;
secSkills = getHeroType()->secSkillsInit;
if (gender == EHeroGender::DEFAULT)
gender = type->gender;
gender = getHeroType()->gender;
setFormation(EArmyFormation::LOOSE);
if (!stacksCount()) //standard army//initial army
@ -403,9 +416,9 @@ void CGHeroInstance::initHero(vstd::RNG & rand)
addNewBonus(bonus);
}
if (cb->getSettings().getBoolean(EGameSettings::MODULE_COMMANDERS) && !commander && type->heroClass->commander.hasValue())
if (cb->getSettings().getBoolean(EGameSettings::MODULE_COMMANDERS) && !commander && getHeroClass()->commander.hasValue())
{
commander = new CCommanderInstance(type->heroClass->commander);
commander = new CCommanderInstance(getHeroClass()->commander);
commander->setArmyObj (castToArmyObj()); //TODO: separate function for setting commanders
commander->giveStackExp (exp); //after our exp is set
}
@ -413,7 +426,7 @@ void CGHeroInstance::initHero(vstd::RNG & rand)
skillsInfo = SecondarySkillsInfo();
//copy active (probably growing) bonuses from hero prototype to hero object
for(const std::shared_ptr<Bonus> & b : type->specialty)
for(const std::shared_ptr<Bonus> & b : getHeroType()->specialty)
addNewBonus(b);
//initialize bonuses
@ -433,14 +446,14 @@ void CGHeroInstance::initArmy(vstd::RNG & rand, IArmyDescriptor * dst)
auto stacksCountChances = cb->getSettings().getVector(EGameSettings::HEROES_STARTING_STACKS_CHANCES);
int stacksCountInitRandomNumber = rand.nextInt(1, 100);
size_t maxStacksCount = std::min(stacksCountChances.size(), type->initialArmy.size());
size_t maxStacksCount = std::min(stacksCountChances.size(), getHeroType()->initialArmy.size());
for(int stackNo=0; stackNo < maxStacksCount; stackNo++)
{
if (stacksCountInitRandomNumber > stacksCountChances[stackNo])
continue;
auto & stack = type->initialArmy[stackNo];
auto & stack = getHeroType()->initialArmy[stackNo];
int count = rand.nextInt(stack.minAmount, stack.maxAmount);
@ -588,11 +601,11 @@ std::string CGHeroInstance::getMovementPointsTextIfOwner(PlayerColor player) con
ui8 CGHeroInstance::maxlevelsToMagicSchool() const
{
return type->heroClass->isMagicHero() ? 3 : 4;
return getHeroClass()->isMagicHero() ? 3 : 4;
}
ui8 CGHeroInstance::maxlevelsToWisdom() const
{
return type->heroClass->isMagicHero() ? 3 : 6;
return getHeroClass()->isMagicHero() ? 3 : 6;
}
CGHeroInstance::SecondarySkillsInfo::SecondarySkillsInfo():
@ -617,11 +630,8 @@ void CGHeroInstance::pickRandomObject(vstd::RNG & rand)
{
ID = Obj::HERO;
subID = cb->gameState()->pickNextHeroType(getOwner());
type = getHeroType().toHeroType();
randomizeArmy(type->heroClass->faction);
randomizeArmy(getHeroClass()->faction);
}
else
type = getHeroType().toHeroType();
auto oldSubID = subID;
@ -629,7 +639,7 @@ void CGHeroInstance::pickRandomObject(vstd::RNG & rand)
// after setType subID used to store unique hero identify id. Check issue 2277 for details
// exclude prisons which should use appearance as set in map, via map editor or RMG
if (ID != Obj::PRISON)
setType(ID, type->heroClass->getIndex());
setType(ID, getHeroClass()->getIndex());
this->subID = oldSubID;
}
@ -1041,7 +1051,7 @@ si32 CGHeroInstance::getManaNewTurn() const
BoatId CGHeroInstance::getBoatType() const
{
return BoatId(VLC->townh->getById(type->heroClass->faction)->getBoatType());
return BoatId(VLC->townh->getById(getHeroClass()->faction)->getBoatType());
}
void CGHeroInstance::getOutOffsets(std::vector<int3> &offsets) const
@ -1080,7 +1090,7 @@ void CGHeroInstance::pushPrimSkill( PrimarySkill which, int val )
EAlignment CGHeroInstance::getAlignment() const
{
return type->heroClass->getAlignment();
return getHeroClass()->getAlignment();
}
void CGHeroInstance::initExp(vstd::RNG & rand)
@ -1104,12 +1114,12 @@ HeroTypeID CGHeroInstance::getPortraitSource() const
if (customPortraitSource.isValid())
return customPortraitSource;
else
return getHeroType();
return getHeroTypeID();
}
int32_t CGHeroInstance::getIconIndex() const
{
return VLC->heroTypes()->getById(getPortraitSource())->getIconIndex();
return getPortraitSource().toEntity(VLC)->getIconIndex();
}
std::string CGHeroInstance::getNameTranslated() const
@ -1126,15 +1136,15 @@ std::string CGHeroInstance::getClassNameTextID() const
{
if (isCampaignGem())
return "core.genrltxt.735";
return type->heroClass->getNameTextID();
return getHeroClass()->getNameTextID();
}
std::string CGHeroInstance::getNameTextID() const
{
if (!nameCustomTextId.empty())
return nameCustomTextId;
if (type)
return type->getNameTextID();
if (getHeroTypeID().hasValue())
return getHeroType()->getNameTextID();
// FIXME: called by logging from some specialties (mods?) before type is set on deserialization
// assert(0);
@ -1150,8 +1160,8 @@ std::string CGHeroInstance::getBiographyTextID() const
{
if (!biographyCustomTextId.empty())
return biographyCustomTextId;
if (type)
return type->getBiographyTextID();
if (getHeroTypeID().hasValue())
return getHeroType()->getBiographyTextID();
return ""; //for random hero
}
@ -1349,11 +1359,11 @@ std::vector<SecondarySkill> CGHeroInstance::getLevelUpProposedSecondarySkills(vs
SecondarySkill selection;
if (selectWisdom)
selection = type->heroClass->chooseSecSkill(intersect(options, wisdomList), rand);
selection = getHeroClass()->chooseSecSkill(intersect(options, wisdomList), rand);
else if (selectSchool)
selection = type->heroClass->chooseSecSkill(intersect(options, schoolList), rand);
selection = getHeroClass()->chooseSecSkill(intersect(options, schoolList), rand);
else
selection = type->heroClass->chooseSecSkill(options, rand);
selection = getHeroClass()->chooseSecSkill(options, rand);
skills.push_back(selection);
options.erase(selection);
@ -1384,7 +1394,7 @@ PrimarySkill CGHeroInstance::nextPrimarySkill(vstd::RNG & rand) const
{
assert(gainsLevel());
const auto isLowLevelHero = level < GameConstants::HERO_HIGH_LEVEL;
const auto & skillChances = isLowLevelHero ? type->heroClass->primarySkillLowLevel : type->heroClass->primarySkillHighLevel;
const auto & skillChances = isLowLevelHero ? getHeroClass()->primarySkillLowLevel : getHeroClass()->primarySkillHighLevel;
if (isCampaignYog())
{
@ -1524,25 +1534,15 @@ bool CGHeroInstance::hasVisions(const CGObjectInstance * target, BonusSubtypeID
std::string CGHeroInstance::getHeroTypeName() const
{
if(ID == Obj::HERO || ID == Obj::PRISON)
{
if(type)
{
return type->getJsonKey();
}
else
{
return getHeroType().toEntity(VLC)->getJsonKey();
}
}
return getHeroType()->getJsonKey();
return "";
}
void CGHeroInstance::afterAddToMap(CMap * map)
{
if(ID != Obj::PRISON)
{
map->heroesOnMap.emplace_back(this);
}
}
void CGHeroInstance::afterRemoveFromMap(CMap* map)
{
@ -1729,8 +1729,7 @@ void CGHeroInstance::serializeJsonOptions(JsonSerializeFormat & handler)
if(!appearance)
{
// crossoverDeserialize
type = getHeroType().toHeroType();
appearance = VLC->objtypeh->getHandlerFor(Obj::HERO, type->heroClass->getIndex())->getTemplates().front();
appearance = VLC->objtypeh->getHandlerFor(Obj::HERO, getHeroClassID())->getTemplates().front();
}
}
@ -1817,7 +1816,7 @@ bool CGHeroInstance::isCampaignYog() const
if (!boost::starts_with(campaign, "DATA/YOG")) // "Birth of a Barbarian"
return false;
if (getHeroType() != HeroTypeID::SOLMYR) // Yog (based on Solmyr)
if (getHeroTypeID() != HeroTypeID::SOLMYR) // Yog (based on Solmyr)
return false;
return true;
@ -1835,7 +1834,7 @@ bool CGHeroInstance::isCampaignGem() const
if (!boost::starts_with(campaign, "DATA/GEM") && !boost::starts_with(campaign, "DATA/FINAL")) // "New Beginning" and "Unholy Alliance"
return false;
if (getHeroType() != HeroTypeID::GEM) // Yog (based on Solmyr)
if (getHeroTypeID() != HeroTypeID::GEM) // Yog (based on Solmyr)
return false;
return true;

View File

@ -72,7 +72,6 @@ public:
//////////////////////////////////////////////////////////////////////////
const CHero * type;
TExpType exp; //experience points
ui32 level; //current level of hero
@ -171,7 +170,7 @@ public:
const IOwnableObject * asOwnable() const final;
//INativeTerrainProvider
FactionID getFaction() const override;
FactionID getFactionID() const override;
TerrainId getNativeTerrain() const override;
int getLowestCreatureSpeed() const;
si32 manaRegain() const; //how many points of mana can hero regain "naturally" in one day
@ -235,7 +234,11 @@ public:
//////////////////////////////////////////////////////////////////////////
HeroTypeID getHeroType() const;
const CHeroClass * getHeroClass() const;
HeroClassID getHeroClassID() const;
const CHero * getHeroType() const;
HeroTypeID getHeroTypeID() const;
void setHeroType(HeroTypeID type);
void initHero(vstd::RNG & rand);
@ -352,7 +355,11 @@ public:
h & skillsInfo;
h & visitedTown;
h & boat;
h & type;
if (h.version < Handler::Version::REMOVE_TOWN_PTR)
{
CHero * type = nullptr;
h & type;
}
h & commander;
h & visitedObjects;
BONUS_TREE_DESERIALIZATION_FIX

View File

@ -45,7 +45,7 @@ int CGTownInstance::getSightRadius() const //returns sight distance
for(const auto & bid : builtBuildings)
{
auto height = town->buildings.at(bid)->height;
auto height = getTown()->buildings.at(bid)->height;
if(ret < height)
ret = height;
}
@ -115,7 +115,7 @@ int CGTownInstance::mageGuildLevel() const
int CGTownInstance::getHordeLevel(const int & HID) const//HID - 0 or 1; returns creature level or -1 if that horde structure is not present
{
return town->hordeLvl.at(HID);
return getTown()->hordeLvl.at(HID);
}
int CGTownInstance::creatureGrowth(const int & level) const
@ -127,7 +127,7 @@ GrowthInfo CGTownInstance::getGrowthInfo(int level) const
{
GrowthInfo ret;
if (level<0 || level >=town->creatures.size())
if (level<0 || level >=getTown()->creatures.size())
return ret;
if (creatures[level].second.empty())
return ret; //no dwelling
@ -151,11 +151,11 @@ GrowthInfo CGTownInstance::getGrowthInfo(int level) const
else if (hasBuilt(BuildingID::CITADEL))
ret.entries.emplace_back(subID, BuildingID::CITADEL, castleBonus = base / 2);
if(town->hordeLvl.at(0) == level)//horde 1
if(getTown()->hordeLvl.at(0) == level)//horde 1
if(hasBuilt(BuildingID::HORDE_1))
ret.entries.emplace_back(subID, BuildingID::HORDE_1, creature->getHorde());
if(town->hordeLvl.at(1) == level)//horde 2
if(getTown()->hordeLvl.at(1) == level)//horde 2
if(hasBuilt(BuildingID::HORDE_2))
ret.entries.emplace_back(subID, BuildingID::HORDE_2, creature->getHorde());
@ -209,11 +209,11 @@ int CGTownInstance::getDwellingBonus(const std::vector<CreatureID>& creatureIds,
TResources CGTownInstance::dailyIncome() const
{
TResources ret;
for(const auto & p : town->buildings)
for(const auto & p : getTown()->buildings)
{
BuildingID buildingUpgrade;
for(const auto & p2 : town->buildings)
for(const auto & p2 : getTown()->buildings)
{
if (p2.second->upgrade == p.first)
{
@ -251,10 +251,10 @@ bool CGTownInstance::hasCapitol() const
TownFortifications CGTownInstance::fortificationsLevel() const
{
auto result = town->fortifications;
auto result = getTown()->fortifications;
for (auto const & buildingID : builtBuildings)
result += town->buildings.at(buildingID)->fortifications;
result += getTown()->buildings.at(buildingID)->fortifications;
if (result.wallsHealth == 0)
return TownFortifications();
@ -264,7 +264,6 @@ TownFortifications CGTownInstance::fortificationsLevel() const
CGTownInstance::CGTownInstance(IGameCallback *cb):
CGDwelling(cb),
town(nullptr),
built(0),
destroyed(0),
identifier(0),
@ -379,17 +378,17 @@ void CGTownInstance::onHeroLeave(const CGHeroInstance * h) const
std::string CGTownInstance::getObjectName() const
{
return getNameTranslated() + ", " + town->faction->getNameTranslated();
return getNameTranslated() + ", " + getTown()->faction->getNameTranslated();
}
bool CGTownInstance::townEnvisagesBuilding(BuildingSubID::EBuildingSubID subId) const
{
return town->getBuildingType(subId) != BuildingID::NONE;
return getTown()->getBuildingType(subId) != BuildingID::NONE;
}
void CGTownInstance::initializeConfigurableBuildings(vstd::RNG & rand)
{
for(const auto & kvp : town->buildings)
for(const auto & kvp : getTown()->buildings)
{
if(!kvp.second->rewardableObjectInfo.getParameters().isNull())
rewardableBuildings[kvp.first] = new TownRewardableBuildingInstance(this, kvp.second->bid, rand);
@ -457,8 +456,7 @@ void CGTownInstance::pickRandomObject(vstd::RNG & rand)
assert(ID == Obj::TOWN); // just in case
setType(ID, subID);
town = (*VLC->townh)[getFaction()]->town;
randomizeArmy(getFaction());
randomizeArmy(getFactionID());
updateAppearance();
}
@ -467,19 +465,19 @@ void CGTownInstance::initObj(vstd::RNG & rand) ///initialize town structures
blockVisit = true;
if(townEnvisagesBuilding(BuildingSubID::PORTAL_OF_SUMMONING)) //Dungeon for example
creatures.resize(town->creatures.size() + 1);
creatures.resize(getTown()->creatures.size() + 1);
else
creatures.resize(town->creatures.size());
creatures.resize(getTown()->creatures.size());
for (int level = 0; level < town->creatures.size(); level++)
for (int level = 0; level < getTown()->creatures.size(); level++)
{
BuildingID buildID = BuildingID(BuildingID::getDwellingFromLevel(level, 0));
int upgradeNum = 0;
for (; town->buildings.count(buildID); upgradeNum++, BuildingID::advanceDwelling(buildID))
for (; getTown()->buildings.count(buildID); upgradeNum++, BuildingID::advanceDwelling(buildID))
{
if (hasBuilt(buildID) && town->creatures.at(level).size() > upgradeNum)
creatures[level].second.push_back(town->creatures[level][upgradeNum]);
if (hasBuilt(buildID) && getTown()->creatures.at(level).size() > upgradeNum)
creatures[level].second.push_back(getTown()->creatures[level][upgradeNum]);
}
}
initializeConfigurableBuildings(rand);
@ -623,9 +621,9 @@ void CGTownInstance::removeCapitols(const PlayerColor & owner) const
if (hasCapitol()) // search if there's an older capitol
{
PlayerState* state = cb->gameState()->getPlayerState(owner); //get all towns owned by player
for (const auto & town : state->getTowns())
for (const auto & otherTown : state->getTowns())
{
if (town != this && town->hasCapitol())
if (otherTown != this && otherTown->hasCapitol())
{
RazeStructures rs;
rs.tid = id;
@ -648,7 +646,7 @@ void CGTownInstance::clearArmy() const
BoatId CGTownInstance::getBoatType() const
{
return town->faction->boatType;
return getTown()->faction->boatType;
}
int CGTownInstance::getMarketEfficiency() const
@ -703,7 +701,7 @@ void CGTownInstance::updateAppearance()
std::string CGTownInstance::nodeName() const
{
return "Town (" + (town ? town->faction->getNameTranslated() : "unknown") + ") of " + getNameTranslated();
return "Town (" + getTown()->faction->getNameTranslated() + ") of " + getNameTranslated();
}
void CGTownInstance::deserializationFix()
@ -752,7 +750,7 @@ void CGTownInstance::recreateBuildingsBonuses()
for(const auto & upgradeID : builtBuildings)
{
const auto & upgrade = town->buildings.at(upgradeID);
const auto & upgrade = getTown()->buildings.at(upgradeID);
if (upgrade->getBase() == bid && upgrade->upgradeReplacesBonuses)
bonusesReplacedByUpgrade = true;
}
@ -761,7 +759,7 @@ void CGTownInstance::recreateBuildingsBonuses()
if (bonusesReplacedByUpgrade)
continue;
auto building = town->buildings.at(bid);
auto building = getTown()->buildings.at(bid);
if(building->buildingBonuses.empty())
continue;
@ -828,21 +826,6 @@ bool CGTownInstance::armedGarrison() const
return !stacks.empty() || garrisonHero;
}
const CTown * CGTownInstance::getTown() const
{
if(ID == Obj::RANDOM_TOWN)
return VLC->townh->randomTown;
else
{
if(nullptr == town)
{
return (*VLC->townh)[getFaction()]->town;
}
else
return town;
}
}
int CGTownInstance::getTownLevel() const
{
// count all buildings that are not upgrades
@ -850,7 +833,7 @@ int CGTownInstance::getTownLevel() const
for(const auto & bid : builtBuildings)
{
if(town->buildings.at(bid)->upgrade == BuildingID::NONE)
if(getTown()->buildings.at(bid)->upgrade == BuildingID::NONE)
level++;
}
return level;
@ -892,7 +875,7 @@ bool CGTownInstance::hasBuilt(BuildingSubID::EBuildingSubID buildingID) const
{
for(const auto & bid : builtBuildings)
{
if(town->buildings.at(bid)->subId == buildingID)
if(getTown()->buildings.at(bid)->subId == buildingID)
return true;
}
return false;
@ -905,7 +888,7 @@ bool CGTownInstance::hasBuilt(const BuildingID & buildingID) const
bool CGTownInstance::hasBuilt(const BuildingID & buildingID, FactionID townID) const
{
if (townID == town->faction->getId() || townID == FactionID::ANY)
if (townID == getTown()->faction->getId() || townID == FactionID::ANY)
return hasBuilt(buildingID);
return false;
}
@ -923,7 +906,7 @@ std::set<EMarketMode> CGTownInstance::availableModes() const
std::set<EMarketMode> result;
for (const auto & buildingID : builtBuildings)
{
const auto * buildingPtr = town->buildings.at(buildingID).get();
const auto * buildingPtr = getTown()->buildings.at(buildingID).get();
result.insert(buildingPtr->marketModes.begin(), buildingPtr->marketModes.end());
}
@ -950,8 +933,8 @@ std::set<BuildingID> CGTownInstance::getBuildings() const
TResources CGTownInstance::getBuildingCost(const BuildingID & buildingID) const
{
if (vstd::contains(town->buildings, buildingID))
return town->buildings.at(buildingID)->resources;
if (vstd::contains(getTown()->buildings, buildingID))
return getTown()->buildings.at(buildingID)->resources;
else
{
logGlobal->error("Town %s at %s has no possible building %d!", getNameTranslated(), anchorPos().toString(), buildingID.toEnum());
@ -962,7 +945,7 @@ TResources CGTownInstance::getBuildingCost(const BuildingID & buildingID) const
CBuilding::TRequired CGTownInstance::genBuildingRequirements(const BuildingID & buildID, bool deep) const
{
const CBuilding * building = town->buildings.at(buildID);
const CBuilding * building = getTown()->buildings.at(buildID);
//TODO: find better solution to prevent infinite loops
std::set<BuildingID> processed;
@ -970,13 +953,13 @@ CBuilding::TRequired CGTownInstance::genBuildingRequirements(const BuildingID &
std::function<CBuilding::TRequired::Variant(const BuildingID &)> dependTest =
[&](const BuildingID & id) -> CBuilding::TRequired::Variant
{
if (town->buildings.count(id) == 0)
if (getTown()->buildings.count(id) == 0)
{
logMod->error("Invalid building ID %d in building dependencies!", id.getNum());
return CBuilding::TRequired::OperatorAll();
}
const CBuilding * build = town->buildings.at(id);
const CBuilding * build = getTown()->buildings.at(id);
CBuilding::TRequired::OperatorAll requirements;
if (!hasBuilt(id))
@ -1001,7 +984,7 @@ CBuilding::TRequired CGTownInstance::genBuildingRequirements(const BuildingID &
CBuilding::TRequired::OperatorAll requirements;
if (building->upgrade != BuildingID::NONE)
{
const CBuilding * upgr = town->buildings.at(building->upgrade);
const CBuilding * upgr = getTown()->buildings.at(building->upgrade);
requirements.expressions.push_back(dependTest(upgr->bid));
processed.clear();
@ -1151,14 +1134,27 @@ void CGTownInstance::serializeJsonOptions(JsonSerializeFormat & handler)
}
}
FactionID CGTownInstance::getFaction() const
const CFaction * CGTownInstance::getFaction() const
{
return FactionID(subID.getNum());
return getFactionID().toFaction();
}
const CTown * CGTownInstance::getTown() const
{
if(ID == Obj::RANDOM_TOWN)
return VLC->townh->randomTown;
return getFaction()->town;
}
FactionID CGTownInstance::getFactionID() const
{
return FactionID(subID.getNum());
}
TerrainId CGTownInstance::getNativeTerrain() const
{
return town->faction->getNativeTerrain();
return getTown()->faction->getNativeTerrain();
}
ArtifactID CGTownInstance::getWarMachineInBuilding(BuildingID building) const
@ -1166,21 +1162,21 @@ ArtifactID CGTownInstance::getWarMachineInBuilding(BuildingID building) const
if (builtBuildings.count(building) == 0)
return ArtifactID::NONE;
if (building == BuildingID::BLACKSMITH && town->warMachineDeprecated.hasValue())
return town->warMachineDeprecated.toCreature()->warMachine;
if (building == BuildingID::BLACKSMITH && getTown()->warMachineDeprecated.hasValue())
return getTown()->warMachineDeprecated.toCreature()->warMachine;
return town->buildings.at(building)->warMachine;
return getTown()->buildings.at(building)->warMachine;
}
bool CGTownInstance::isWarMachineAvailable(ArtifactID warMachine) const
{
for (auto const & buildingID : builtBuildings)
if (town->buildings.at(buildingID)->warMachine == warMachine)
if (getTown()->buildings.at(buildingID)->warMachine == warMachine)
return true;
if (builtBuildings.count(BuildingID::BLACKSMITH) &&
town->warMachineDeprecated.hasValue() &&
town->warMachineDeprecated.toCreature()->warMachine == warMachine)
getTown()->warMachineDeprecated.hasValue() &&
getTown()->warMachineDeprecated.toCreature()->warMachine == warMachine)
return true;
return false;
@ -1200,7 +1196,7 @@ GrowthInfo::Entry::Entry(int subID, const BuildingID & building, int _count): co
{
MetaString formatter;
formatter.appendRawString("%s %+d");
formatter.replaceRawString((*VLC->townh)[subID]->town->buildings.at(building)->getNameTranslated());
formatter.replaceRawString(FactionID(subID).toFaction()->town->buildings.at(building)->getNameTranslated());
formatter.replacePositiveNumber(count);
description = formatter.toString();

View File

@ -50,6 +50,7 @@ struct DLL_LINKAGE GrowthInfo
class DLL_LINKAGE CGTownInstance : public CGDwelling, public IShipyard, public IMarket, public INativeTerrainProvider, public ICreatureUpgrader
{
friend class CTownInstanceConstructor;
std::string nameTextId; // name of town
std::map<BuildingID, TownRewardableBuildingInstance*> convertOldBuildings(std::vector<TownRewardableBuildingInstance*> oldVector);
@ -59,7 +60,6 @@ public:
enum EFortLevel {NONE = 0, FORT = 1, CITADEL = 2, CASTLE = 3};
CTownAndVisitingHero townAndVis;
const CTown * town;
si32 built; //how many buildings has been built this turn
si32 destroyed; //how many buildings has been destroyed this turn
ConstTransitivePtr<CGHeroInstance> garrisonHero, visitingHero;
@ -112,16 +112,21 @@ public:
rewardableBuildings = convertOldBuildings(oldVector);
}
if (h.saving)
if (h.version < Handler::Version::REMOVE_TOWN_PTR)
{
CFaction * faction = town ? town->faction : nullptr;
h & faction;
}
else
{
CFaction * faction = nullptr;
h & faction;
town = faction ? faction->town : nullptr;
CTown * town = nullptr;
if (h.saving)
{
CFaction * faction = town ? town->faction : nullptr;
h & faction;
}
else
{
CFaction * faction = nullptr;
h & faction;
town = faction ? faction->town : nullptr;
}
}
h & townAndVis;
@ -213,9 +218,10 @@ public:
DamageRange getKeepDamageRange() const;
const CTown * getTown() const;
const CFaction * getFaction() const;
/// INativeTerrainProvider
FactionID getFaction() const override;
FactionID getFactionID() const override;
TerrainId getNativeTerrain() const override;
/// Returns ID of war machine that is produced by specified building or NONE if this is not built or if building does not produce war machines

View File

@ -431,7 +431,7 @@ void CGSeerHut::setObjToKill()
if(getCreatureToKill(true))
{
quest->stackToKill = getCreatureToKill(false)->getCreature();
quest->stackToKill = getCreatureToKill(false)->getCreatureID();
assert(quest->stackToKill != CreatureID::NONE);
quest->stackDirection = checkDirection();
}

View File

@ -73,14 +73,14 @@ TownRewardableBuildingInstance::TownRewardableBuildingInstance(CGTownInstance *
void TownRewardableBuildingInstance::initObj(vstd::RNG & rand)
{
assert(town && town->town);
assert(town && town->getTown());
configuration = generateConfiguration(rand);
}
Rewardable::Configuration TownRewardableBuildingInstance::generateConfiguration(vstd::RNG & rand) const
{
Rewardable::Configuration result;
auto building = town->town->buildings.at(getBuildingType());
auto building = town->getTown()->buildings.at(getBuildingType());
building->rewardableObjectInfo.configureObject(result, rand, cb);
for(auto & rewardInfo : result.info)

View File

@ -302,7 +302,7 @@ void CMap::calculateGuardingGreaturePositions()
CGHeroInstance * CMap::getHero(HeroTypeID heroID)
{
for(auto & elem : heroesOnMap)
if(elem->getHeroType() == heroID)
if(elem->getHeroTypeID() == heroID)
return elem;
return nullptr;
}

View File

@ -896,7 +896,7 @@ void CMapLoaderH3M::readPredefinedHeroes()
}
map->predefinedHeroes.emplace_back(hero);
logGlobal->debug("Map '%s': Hero predefined in map: %s", mapName, VLC->heroh->getById(hero->getHeroType())->getJsonKey());
logGlobal->debug("Map '%s': Hero predefined in map: %s", mapName, hero->getHeroType()->getJsonKey());
}
}
@ -913,7 +913,7 @@ void CMapLoaderH3M::loadArtifactsOfHero(CGHeroInstance * hero)
if(!hero->artifactsWorn.empty() || !hero->artifactsInBackpack.empty())
{
logGlobal->debug("Hero %d at %s has set artifacts twice (in map properties and on adventure map instance). Using the latter set...", hero->getHeroType().getNum(), hero->anchorPos().toString());
logGlobal->debug("Hero %d at %s has set artifacts twice (in map properties and on adventure map instance). Using the latter set...", hero->getHeroTypeID().getNum(), hero->anchorPos().toString());
hero->artifactsInBackpack.clear();
while(!hero->artifactsWorn.empty())
@ -1778,7 +1778,7 @@ CGObjectInstance * CMapLoaderH3M::readHero(const int3 & mapPosition, const Objec
for(auto & elem : map->disposedHeroes)
{
if(elem.heroId == object->getHeroType())
if(elem.heroId == object->getHeroTypeID())
{
object->nameCustomTextId = elem.name;
object->customPortraitSource = elem.portrait;
@ -1788,7 +1788,7 @@ CGObjectInstance * CMapLoaderH3M::readHero(const int3 & mapPosition, const Objec
bool hasName = reader->readBool();
if(hasName)
object->nameCustomTextId = readLocalizedString(TextIdentifier("heroes", object->getHeroType().getNum(), "name"));
object->nameCustomTextId = readLocalizedString(TextIdentifier("heroes", object->getHeroTypeID().getNum(), "name"));
if(features.levelSOD)
{
@ -1891,7 +1891,7 @@ CGObjectInstance * CMapLoaderH3M::readHero(const int3 & mapPosition, const Objec
auto ps = object->getAllBonuses(Selector::type()(BonusType::PRIMARY_SKILL).And(Selector::sourceType()(BonusSource::HERO_BASE_SKILL)), nullptr);
if(ps->size())
{
logGlobal->debug("Hero %s has set primary skills twice (in map properties and on adventure map instance). Using the latter set...", object->getHeroType().getNum() );
logGlobal->debug("Hero %s has set primary skills twice (in map properties and on adventure map instance). Using the latter set...", object->getHeroTypeID().getNum() );
for(const auto & b : *ps)
object->removeBonus(b);
}
@ -1904,7 +1904,7 @@ CGObjectInstance * CMapLoaderH3M::readHero(const int3 & mapPosition, const Objec
}
if (object->subID != MapObjectSubID())
logGlobal->debug("Map '%s': Hero on map: %s at %s, owned by %s", mapName, VLC->heroh->getById(object->getHeroType())->getJsonKey(), mapPosition.toString(), object->getOwner().toString());
logGlobal->debug("Map '%s': Hero on map: %s at %s, owned by %s", mapName, object->getHeroType()->getJsonKey(), mapPosition.toString(), object->getOwner().toString());
else
logGlobal->debug("Map '%s': Hero on map: (random) at %s, owned by %s", mapName, mapPosition.toString(), object->getOwner().toString());

View File

@ -436,10 +436,8 @@ void CMapFormatJson::serializePlayerInfo(JsonSerializeFormat & handler)
if(hero->ID == Obj::HERO)
{
std::string temp;
if(hero->type)
temp = hero->type->getJsonKey();
else
temp = hero->getHeroType().toEntity(VLC)->getJsonKey();
if(hero->getHeroTypeID().hasValue())
temp = hero->getHeroType()->getJsonKey();
handler.serializeString("type", temp);
}
@ -1154,10 +1152,10 @@ void CMapLoaderJson::readObjects()
auto * hero = dynamic_cast<const CGHeroInstance *>(object.get());
if (debugHeroesOnMap.count(hero->getHeroType()))
if (debugHeroesOnMap.count(hero->getHeroTypeID()))
logGlobal->error("Hero is already on the map at %s", hero->visitablePos().toString());
debugHeroesOnMap.insert(hero->getHeroType());
debugHeroesOnMap.insert(hero->getHeroTypeID());
}
}

View File

@ -1355,7 +1355,7 @@ void NewStructures::applyGs(CGameState *gs)
for(const auto & id : bid)
{
assert(t->town->buildings.at(id) != nullptr);
assert(t->getTown()->buildings.at(id) != nullptr);
t->addBuilding(id);
}
t->updateAppearance();
@ -1470,7 +1470,7 @@ void GiveHero::applyGs(CGameState *gs)
auto oldVisitablePos = h->visitablePos();
gs->map->removeBlockVisTiles(h,true);
h->appearance = VLC->objtypeh->getHandlerFor(Obj::HERO, h->type->heroClass->getIndex())->getTemplates().front();
h->appearance = VLC->objtypeh->getHandlerFor(Obj::HERO, h->getHeroClassID().getNum())->getTemplates().front();
h->setOwner(player);
h->setMovementPoints(h->movementPointsLimit(true));

View File

@ -292,7 +292,7 @@ TeleporterTilesVector CPathfinderHelper::getTeleportExits(const PathNodeInfo & s
{
auto * town = dynamic_cast<const CGTownInstance *>(source.nodeObject);
assert(town);
if (town && town->getFaction() == FactionID::INFERNO)
if (town && town->getFactionID() == FactionID::INFERNO)
{
/// TODO: Find way to reuse CPlayerSpecificInfoCallback::getTownsInfo
/// This may be handy if we allow to use teleportation to friendly towns

View File

@ -173,10 +173,10 @@ bool Rewardable::Limiter::heroAllowed(const CGHeroInstance * hero) const
if(!players.empty() && !vstd::contains(players, hero->getOwner()))
return false;
if(!heroes.empty() && !vstd::contains(heroes, hero->type->getId()))
if(!heroes.empty() && !vstd::contains(heroes, hero->getHeroTypeID()))
return false;
if(!heroClasses.empty() && !vstd::contains(heroClasses, hero->type->heroClass->getId()))
if(!heroClasses.empty() && !vstd::contains(heroClasses, hero->getHeroClassID()))
return false;

View File

@ -733,7 +733,7 @@ CGCreature * ObjectManager::chooseGuard(si32 strength, bool zoneGuard)
continue;
if(!cre->getAIValue()) //bug #2681
continue;
if(!vstd::contains(zone.getMonsterTypes(), cre->getFaction()))
if(!vstd::contains(zone.getMonsterTypes(), cre->getFactionID()))
continue;
if((static_cast<si32>(cre->getAIValue() * (cre->ammMin + cre->ammMax) / 2) < strength) && (strength < static_cast<si32>(cre->getAIValue()) * 100)) //at least one full monster. size between average size of given stack and 100
{

View File

@ -90,7 +90,7 @@ void TownPlacer::placeTowns(ObjectManager & manager)
totalTowns++;
//register MAIN town of zone only
map.registerZone(town->getFaction());
map.registerZone(town->getFactionID());
if(player.isValidPlayer()) //configure info for owning player
{
@ -213,7 +213,7 @@ void TownPlacer::addNewTowns(int count, bool hasFort, const PlayerColor & player
{
//FIXME: discovered bug with small zones - getPos is close to map boarder and we have outOfMap exception
//register MAIN town of zone
map.registerZone(town->getFaction());
map.registerZone(town->getFactionID());
//first town in zone goes in the middle
placeMainTown(manager, *town);
}

View File

@ -51,7 +51,7 @@ void TreasurePlacer::process()
// Add all native creatures
for(auto const & cre : VLC->creh->objects)
{
if(!cre->special && cre->getFaction() == zone.getTownType())
if(!cre->special && cre->getFactionID() == zone.getTownType())
{
creatures.push_back(cre.get());
}
@ -192,7 +192,7 @@ void TreasurePlacer::addPrisons()
{
// Hero can be used again
auto* hero = dynamic_cast<CGHeroInstance*>(obj);
prisonHeroPlacer->restoreDrawnHero(hero->getHeroType());
prisonHeroPlacer->restoreDrawnHero(hero->getHeroTypeID());
};
oi.setTemplates(Obj::PRISON, 0, zone.getTerrainType());
@ -236,9 +236,9 @@ void TreasurePlacer::addDwellings()
continue;
const auto * cre = creatures.front();
if(cre->getFaction() == zone.getTownType())
if(cre->getFactionID() == zone.getTownType())
{
auto nativeZonesCount = static_cast<float>(map.getZoneCount(cre->getFaction()));
auto nativeZonesCount = static_cast<float>(map.getZoneCount(cre->getFactionID()));
ObjectInfo oi(dwellingType, secondaryID);
setBasicProperties(oi, CompoundMapObjectID(dwellingType, secondaryID));
@ -375,7 +375,7 @@ void TreasurePlacer::addPandoraBoxesWithCreatures()
return obj;
};
oi.setTemplates(Obj::PANDORAS_BOX, 0, zone.getTerrainType());
oi.value = static_cast<ui32>(creature->getAIValue() * creaturesAmount * (1 + static_cast<float>(map.getZoneCount(creature->getFaction())) / map.getTotalZoneCount()));
oi.value = static_cast<ui32>(creature->getAIValue() * creaturesAmount * (1 + static_cast<float>(map.getZoneCount(creature->getFactionID())) / map.getTotalZoneCount()));
oi.probability = 3;
if(!oi.templates.empty())
addObjectToRandomPool(oi);
@ -555,7 +555,7 @@ void TreasurePlacer::addSeerHuts()
oi.destroyObject = destroyObject;
oi.probability = 3;
oi.setTemplates(Obj::SEER_HUT, randomAppearance, zone.getTerrainType());
oi.value = static_cast<ui32>(((2 * (creature->getAIValue()) * creaturesAmount * (1 + static_cast<float>(map.getZoneCount(creature->getFaction())) / map.getTotalZoneCount())) - 4000) / 3);
oi.value = static_cast<ui32>(((2 * (creature->getAIValue()) * creaturesAmount * (1 + static_cast<float>(map.getZoneCount(creature->getFactionID())) / map.getTotalZoneCount())) - 4000) / 3);
if (oi.value > zone.getMaxTreasureValue())
{
continue;

View File

@ -26,7 +26,7 @@ void CSerializer::addStdVecItems(CGameState *gs, LibClasses *lib)
registerVectoredType<CGObjectInstance, ObjectInstanceID>(&gs->map->objects,
[](const CGObjectInstance &obj){ return obj.id; });
registerVectoredType<CGHeroInstance, HeroTypeID>(&gs->map->allHeroes,
[](const CGHeroInstance &h){ return h.type->getId(); });
[](const CGHeroInstance &h){ return h.getHeroType()->getId(); });
registerVectoredType<CArtifactInstance, ArtifactInstanceID>(&gs->map->artInstances,
[](const CArtifactInstance &artInst){ return artInst.getId(); });
registerVectoredType<CQuest, si32>(&gs->map->quests,

View File

@ -63,6 +63,7 @@ enum class ESerializationVersion : int32_t
REGION_LABEL, // 864 - labels for campaign regions
SPELL_RESEARCH, // 865 - spell research
LOCAL_PLAYER_STATE_DATA, // 866 - player state contains arbitrary client-side data
REMOVE_TOWN_PTR, // 867 - removed pointer to CTown from CGTownInstance
CURRENT = LOCAL_PLAYER_STATE_DATA
CURRENT = REMOVE_TOWN_PTR
};

View File

@ -88,7 +88,7 @@ void Moat::convertBonus(const Mechanics * m, std::vector<Bonus> & converted) con
if(m->battle()->battleGetDefendedTown() && m->battle()->battleGetFortifications().hasMoat)
{
nb.sid = BonusSourceID(m->battle()->battleGetDefendedTown()->town->buildings.at(BuildingID::CITADEL)->getUniqueTypeID());
nb.sid = BonusSourceID(m->battle()->battleGetDefendedTown()->getTown()->buildings.at(BuildingID::CITADEL)->getUniqueTypeID());
nb.source = BonusSource::TOWN_STRUCTURE;
}
else

View File

@ -79,7 +79,7 @@ bool Summon::applicable(Problem & problem, const Mechanics * m) const
text.replaceNamePlural(elemental->creatureId());
if(caster->type->gender == EHeroGender::FEMALE)
if(caster->gender == EHeroGender::FEMALE)
text.replaceLocalString(EMetaText::GENERAL_TXT, 540);
else
text.replaceLocalString(EMetaText::GENERAL_TXT, 539);

View File

@ -138,25 +138,11 @@ void Initializer::initialize(CGHeroInstance * o)
o->subID = 0;
o->tempOwner = PlayerColor::NEUTRAL;
}
if(o->ID == Obj::HERO)
if(o->getHeroTypeID().hasValue())
{
for(auto const & t : VLC->heroh->objects)
{
if(t->heroClass->getId() == HeroClassID(o->subID))
{
o->type = t.get();
break;
}
}
}
if(o->type)
{
// o->type = VLC->heroh->objects.at(o->subID);
o->gender = o->type->gender;
o->randomizeArmy(o->type->heroClass->faction);
o->gender = o->getHeroType()->gender;
o->randomizeArmy(o->getFactionID());
}
}
@ -304,7 +290,7 @@ void Inspector::updateProperties(CGHeroInstance * o)
auto isPrison = o->ID == Obj::PRISON;
addProperty("Owner", o->tempOwner, new OwnerDelegate(controller, isPrison), isPrison); //field is not editable for prison
addProperty<int>("Experience", o->exp, false);
addProperty("Hero class", o->type ? o->type->heroClass->getNameTranslated() : "", true);
addProperty("Hero class", o->getHeroClassID().hasValue() ? o->getHeroClass()->getNameTranslated() : "", true);
{ //Gender
auto * delegate = new InspectorDelegate;
@ -319,20 +305,20 @@ void Inspector::updateProperties(CGHeroInstance * o)
addProperty("Skills", PropertyEditorPlaceholder(), delegate, false);
addProperty("Spells", PropertyEditorPlaceholder(), new HeroSpellDelegate(*o), false);
if(o->type || o->ID == Obj::PRISON)
if(o->getHeroTypeID().hasValue() || o->ID == Obj::PRISON)
{ //Hero type
auto * delegate = new InspectorDelegate;
for(int i = 0; i < VLC->heroh->objects.size(); ++i)
for(const auto & heroPtr : VLC->heroh->objects)
{
if(controller.map()->allowedHeroes.count(HeroTypeID(i)) != 0)
if(controller.map()->allowedHeroes.count(heroPtr->getId()) != 0)
{
if(o->ID == Obj::PRISON || (o->type && VLC->heroh->objects[i]->heroClass->getIndex() == o->type->heroClass->getIndex()))
if(o->ID == Obj::PRISON || heroPtr->heroClass->getIndex() == o->getHeroClassID())
{
delegate->options.push_back({QObject::tr(VLC->heroh->objects[i]->getNameTranslated().c_str()), QVariant::fromValue(VLC->heroh->objects[i]->getId().getNum())});
delegate->options.push_back({QObject::tr(heroPtr->getNameTranslated().c_str()), QVariant::fromValue(heroPtr->getIndex())});
}
}
}
addProperty("Hero type", o->type ? o->type->getNameTranslated() : "", delegate, false);
addProperty("Hero type", o->getHeroTypeID().hasValue() ? o->getHeroType()->getNameTranslated() : "", delegate, false);
}
}
@ -706,13 +692,10 @@ void Inspector::setProperty(CGHeroInstance * o, const QString & key, const QVari
for(auto const & t : VLC->heroh->objects)
{
if(t->getId() == value.toInt())
{
o->subID = value.toInt();
o->type = t.get();
}
}
o->gender = o->type->gender;
o->randomizeArmy(o->type->heroClass->faction);
o->gender = o->getHeroType()->gender;
o->randomizeArmy(o->getHeroType()->heroClass->faction);
updateProperties(); //updating other properties after change
}
}

View File

@ -331,7 +331,7 @@ void TownBuildingsDelegate::setEditorData(QWidget *editor, const QModelIndex &in
{
if(auto * ed = qobject_cast<TownBuildingsWidget *>(editor))
{
auto * ctown = town.town;
auto * ctown = town.getTown();
if(!ctown)
ctown = VLC->townh->randomTown;
if(!ctown)

View File

@ -100,7 +100,7 @@ void TownEventDialog::initResources()
void TownEventDialog::initBuildings()
{
auto * ctown = town.town;
auto * ctown = town.getTown();
if (!ctown)
ctown = VLC->townh->randomTown;
if (!ctown)
@ -156,7 +156,7 @@ QStandardItem * TownEventDialog::addBuilding(const CTown& ctown, BuildingID buil
void TownEventDialog::initCreatures()
{
auto creatures = params.value("creatures").toList();
auto * ctown = town.town;
auto * ctown = town.getTown();
if (!ctown)
ui->creaturesTable->setRowCount(GameConstants::CREATURES_PER_TOWN);
else

View File

@ -138,7 +138,7 @@ void MapController::repairMap(CMap * map) const
// FIXME: How about custom scenarios where defeated hero cannot be hired again?
map->allowedHeroes.insert(nih->getHeroType());
map->allowedHeroes.insert(nih->getHeroTypeID());
auto const & type = VLC->heroh->objects[nih->subID];
assert(type->heroClass);
@ -154,10 +154,6 @@ void MapController::repairMap(CMap * map) const
nih->subTypeName = "prison";
nih->subID = 0;
}
if(obj->ID != Obj::RANDOM_HERO)
nih->type = type.get();
if(nih->ID == Obj::HERO) //not prison
nih->appearance = VLC->objtypeh->getHandlerFor(Obj::HERO, type->heroClass->getIndex())->getTemplates().front();
//fix spellbook

View File

@ -77,12 +77,10 @@ PlayerParams::PlayerParams(MapController & ctrl, int playerId, QWidget *parent)
{
if(auto town = dynamic_cast<CGTownInstance*>(controller.map()->objects[i].get()))
{
auto * ctown = town->town;
auto * ctown = town->getTown();
if(!ctown)
{
ctown = VLC->townh->randomTown;
town->town = ctown;
}
if(ctown && town->getOwner().getNum() == playerColor)
{
if(playerInfo.hasMainTown && playerInfo.posOfMainTown == town->pos)

View File

@ -122,13 +122,13 @@ std::set<Validator::Issue> Validator::validate(const CMap * map)
++amountOfHeroes[ins->getOwner()];
}
if(ins->type)
if(ins->getHeroTypeID().hasValue())
{
if(map->allowedHeroes.count(ins->getHeroType()) == 0)
issues.insert({ tr("Hero %1 is prohibited by map settings").arg(ins->type->getNameTranslated().c_str()), false });
if(map->allowedHeroes.count(ins->getHeroTypeID()) == 0)
issues.insert({ tr("Hero %1 is prohibited by map settings").arg(ins->getHeroType()->getNameTranslated().c_str()), false });
if(!allHeroesOnMap.insert(ins->type).second)
issues.insert({ tr("Hero %1 has duplicate on map").arg(ins->type->getNameTranslated().c_str()), false });
if(!allHeroesOnMap.insert(ins->getHeroType()).second)
issues.insert({ tr("Hero %1 has duplicate on map").arg(ins->getHeroType()->getNameTranslated().c_str()), false });
}
else if(ins->ID != Obj::RANDOM_HERO)
issues.insert({ tr("Hero %1 has an empty type and must be removed").arg(ins->instanceName.c_str()), true });

View File

@ -46,7 +46,7 @@ const std::vector<CreatureProxy::CustomRegType> CreatureProxy::REGISTER_CUSTOM =
{"getLevel", LuaMethodWrapper<Creature, decltype(&Creature::getLevel), &Creature::getLevel>::invoke, false},
{"getGrowth", LuaMethodWrapper<Creature, decltype(&Creature::getGrowth), &Creature::getGrowth>::invoke, false},
{"getHorde", LuaMethodWrapper<Creature, decltype(&Creature::getHorde), &Creature::getHorde>::invoke, false},
{"getFaction", LuaMethodWrapper<Creature, decltype(&Creature::getFaction), &Creature::getFaction>::invoke, false},
{"getFactionID", LuaMethodWrapper<Creature, decltype(&Creature::getFactionID), &Creature::getFactionID>::invoke, false},
{"getBaseAttack", LuaMethodWrapper<Creature, decltype(&Creature::getBaseAttack), &Creature::getBaseAttack>::invoke, false},
{"getBaseDefense", LuaMethodWrapper<Creature, decltype(&Creature::getBaseDefense), &Creature::getBaseDefense>::invoke, false},

View File

@ -162,7 +162,7 @@ void CGameHandler::levelUpHero(const CGHeroInstance * hero)
hlu.player = hero->tempOwner;
hlu.heroId = hero->id;
hlu.primskill = primarySkill;
hlu.skills = hero->getLevelUpProposedSecondarySkills(heroPool->getHeroSkillsRandomGenerator(hero->getHeroType()));
hlu.skills = hero->getLevelUpProposedSecondarySkills(heroPool->getHeroSkillsRandomGenerator(hero->getHeroTypeID()));
if (hlu.skills.size() == 0)
{
@ -553,7 +553,7 @@ void CGameHandler::init(StartInfo *si, Load::ProgressAccumulator & progressTrack
for (auto & elem : gs->map->allHeroes)
{
if(elem)
heroPool->getHeroSkillsRandomGenerator(elem->getHeroType()); // init RMG seed
heroPool->getHeroSkillsRandomGenerator(elem->getHeroTypeID()); // init RMG seed
}
reinitScripting();
@ -569,12 +569,12 @@ void CGameHandler::setPortalDwelling(const CGTownInstance * town, bool forced=fa
return;
}
if (forced || town->creatures.at(town->town->creatures.size()).second.empty())//we need to change creature
if (forced || town->creatures.at(town->getTown()->creatures.size()).second.empty())//we need to change creature
{
SetAvailableCreatures ssi;
ssi.tid = town->id;
ssi.creatures = town->creatures;
ssi.creatures[town->town->creatures.size()].second.clear();//remove old one
ssi.creatures[town->getTown()->creatures.size()].second.clear();//remove old one
std::set<CreatureID> availableCreatures;
for (const auto & dwelling : p->getOwnedObjects())
@ -590,13 +590,13 @@ void CGameHandler::setPortalDwelling(const CGTownInstance * town, bool forced=fa
if (clear)
{
ssi.creatures[town->town->creatures.size()].first = std::max(1, (creatureId.toEntity(VLC)->getGrowth())/2);
ssi.creatures[town->getTown()->creatures.size()].first = std::max(1, (creatureId.toEntity(VLC)->getGrowth())/2);
}
else
{
ssi.creatures[town->town->creatures.size()].first = creatureId.toEntity(VLC)->getGrowth();
ssi.creatures[town->getTown()->creatures.size()].first = creatureId.toEntity(VLC)->getGrowth();
}
ssi.creatures[town->town->creatures.size()].second.push_back(creatureId);
ssi.creatures[town->getTown()->creatures.size()].second.push_back(creatureId);
sendAndApply(ssi);
}
}
@ -657,7 +657,7 @@ void CGameHandler::onNewTurn()
PlayerColor player = t->tempOwner;
if(t->hasBuilt(BuildingID::GRAIL)
&& t->town->buildings.at(BuildingID::GRAIL)->height == CBuilding::HEIGHT_SKYSHIP)
&& t->getTown()->buildings.at(BuildingID::GRAIL)->height == CBuilding::HEIGHT_SKYSHIP)
{
// Skyship, probably easier to handle same as Veil of darkness
// do it every new day before veils
@ -1048,7 +1048,7 @@ bool CGameHandler::teleportHero(ObjectInstanceID hid, ObjectInstanceID dstid, ui
if (((h->getOwner() != t->getOwner())
&& complain("Cannot teleport hero to another player"))
|| (from->town->faction->getId() != t->town->faction->getId()
|| (from->getFactionID() != t->getFactionID()
&& complain("Source town and destination town should belong to the same faction"))
|| ((!from || !from->hasBuilt(BuildingSubID::CASTLE_GATE))
@ -1212,7 +1212,7 @@ void CGameHandler::visitCastleObjects(const CGTownInstance * t, std::vector<cons
for (auto & building : t->rewardableBuildings)
{
if (!t->town->buildings.at(building.first)->manualHeroVisit && t->hasBuilt(building.first))
if (!t->getTown()->buildings.at(building.first)->manualHeroVisit && t->hasBuilt(building.first))
buildingsToVisit.push_back(building.first);
}
@ -2036,12 +2036,12 @@ bool CGameHandler::buildStructure(ObjectInstanceID tid, BuildingID requestedID,
const CGTownInstance * t = getTown(tid);
if(!t)
COMPLAIN_RETF("No such town (ID=%s)!", tid);
if(!t->town->buildings.count(requestedID))
COMPLAIN_RETF("Town of faction %s does not have info about building ID=%s!", t->town->faction->getNameTranslated() % requestedID);
if(!t->getTown()->buildings.count(requestedID))
COMPLAIN_RETF("Town of faction %s does not have info about building ID=%s!", t->getFaction()->getNameTranslated() % requestedID);
if(t->hasBuilt(requestedID))
COMPLAIN_RETF("Building %s is already built in %s", t->town->buildings.at(requestedID)->getNameTranslated() % t->getNameTranslated());
COMPLAIN_RETF("Building %s is already built in %s", t->getTown()->buildings.at(requestedID)->getNameTranslated() % t->getNameTranslated());
const CBuilding * requestedBuilding = t->town->buildings.at(requestedID);
const CBuilding * requestedBuilding = t->getTown()->buildings.at(requestedID);
//Vector with future list of built building and buildings in auto-mode that are not yet built.
std::vector<const CBuilding*> remainingAutoBuildings;
@ -2081,7 +2081,7 @@ bool CGameHandler::buildStructure(ObjectInstanceID tid, BuildingID requestedID,
int level = BuildingID::getLevelFromDwelling(buildingID);
int upgradeNumber = BuildingID::getUpgradedFromDwelling(buildingID);
if(upgradeNumber >= t->town->creatures.at(level).size())
if(upgradeNumber >= t->getTown()->creatures.at(level).size())
{
complain(boost::str(boost::format("Error encountered when building dwelling (bid=%s):"
"no creature found (upgrade number %d, level %d!")
@ -2089,7 +2089,7 @@ bool CGameHandler::buildStructure(ObjectInstanceID tid, BuildingID requestedID,
return;
}
const CCreature * crea = t->town->creatures.at(level).at(upgradeNumber).toCreature();
const CCreature * crea = t->getTown()->creatures.at(level).at(upgradeNumber).toCreature();
SetAvailableCreatures ssi;
ssi.tid = t->id;
@ -2099,7 +2099,7 @@ bool CGameHandler::buildStructure(ObjectInstanceID tid, BuildingID requestedID,
ssi.creatures[level].second.push_back(crea->getId());
sendAndApply(ssi);
}
if(t->town->buildings.at(buildingID)->subId == BuildingSubID::PORTAL_OF_SUMMONING)
if(t->getTown()->buildings.at(buildingID)->subId == BuildingSubID::PORTAL_OF_SUMMONING)
{
setPortalDwelling(t);
}
@ -2110,9 +2110,9 @@ bool CGameHandler::buildStructure(ObjectInstanceID tid, BuildingID requestedID,
{
auto isMageGuild = (buildingID <= BuildingID::MAGES_GUILD_5 && buildingID >= BuildingID::MAGES_GUILD_1);
auto isLibrary = isMageGuild ? false
: t->town->buildings.at(buildingID)->subId == BuildingSubID::EBuildingSubID::LIBRARY;
: t->getTown()->buildings.at(buildingID)->subId == BuildingSubID::EBuildingSubID::LIBRARY;
if(isMageGuild || isLibrary || (t->getFaction() == ETownType::CONFLUX && buildingID == BuildingID::GRAIL))
if(isMageGuild || isLibrary || (t->getFactionID() == ETownType::CONFLUX && buildingID == BuildingID::GRAIL))
{
if(t->visitingHero)
giveSpells(t,t->visitingHero);
@ -2128,7 +2128,7 @@ bool CGameHandler::buildStructure(ObjectInstanceID tid, BuildingID requestedID,
};
//Init the vectors
for(auto & build : t->town->buildings)
for(auto & build : t->getTown()->buildings)
{
if(t->hasBuilt(build.first))
{
@ -2212,7 +2212,7 @@ bool CGameHandler::visitTownBuilding(ObjectInstanceID tid, BuildingID bid)
if(!t->hasBuilt(bid))
return false;
auto subID = t->town->buildings.at(bid)->subId;
auto subID = t->getTown()->buildings.at(bid)->subId;
if(subID == BuildingSubID::EBuildingSubID::BANK)
{
@ -2224,7 +2224,7 @@ bool CGameHandler::visitTownBuilding(ObjectInstanceID tid, BuildingID bid)
return true;
}
if (t->rewardableBuildings.count(bid) && t->visitingHero && t->town->buildings.at(bid)->manualHeroVisit)
if (t->rewardableBuildings.count(bid) && t->visitingHero && t->getTown()->buildings.at(bid)->manualHeroVisit)
{
std::vector<BuildingID> buildingsToVisit;
std::vector<const CGHeroInstance*> visitors;

View File

@ -47,8 +47,8 @@ TavernHeroSlot HeroPoolProcessor::selectSlotForRole(const PlayerColor & player,
// try to find "better" slot to overwrite
// we want to avoid overwriting retreated heroes when tavern still has slot with random hero
// as well as avoid overwriting surrendered heroes if we can overwrite retreated hero
auto roleLeft = heroesPool->getSlotRole(heroes[0]->getHeroType());
auto roleRight = heroesPool->getSlotRole(heroes[1]->getHeroType());
auto roleLeft = heroesPool->getSlotRole(heroes[0]->getHeroTypeID());
auto roleRight = heroesPool->getSlotRole(heroes[1]->getHeroTypeID());
if (roleLeft > roleRight)
return TavernHeroSlot::RANDOM;
@ -70,7 +70,7 @@ void HeroPoolProcessor::onHeroSurrendered(const PlayerColor & color, const CGHer
sah.slotID = selectSlotForRole(color, sah.roleID);
sah.player = color;
sah.hid = hero->getHeroType();
sah.hid = hero->getHeroTypeID();
sah.replenishPoints = false;
gameHandler->sendAndApply(sah);
}
@ -82,9 +82,9 @@ void HeroPoolProcessor::onHeroEscaped(const PlayerColor & color, const CGHeroIns
sah.slotID = selectSlotForRole(color, sah.roleID);
sah.player = color;
sah.hid = hero->getHeroType();
sah.hid = hero->getHeroTypeID();
sah.army.clearSlots();
sah.army.setCreature(SlotID(0), hero->type->initialArmy.at(0).creature, 1);
sah.army.setCreature(SlotID(0), hero->getHeroType()->initialArmy.at(0).creature, 1);
sah.replenishPoints = false;
gameHandler->sendAndApply(sah);
@ -112,7 +112,7 @@ void HeroPoolProcessor::selectNewHeroForSlot(const PlayerColor & color, TavernHe
if (newHero)
{
sah.hid = newHero->getHeroType();
sah.hid = newHero->getHeroTypeID();
if (giveArmy)
{
@ -123,7 +123,7 @@ void HeroPoolProcessor::selectNewHeroForSlot(const PlayerColor & color, TavernHe
{
sah.roleID = TavernSlotRole::SINGLE_UNIT;
sah.army.clearSlots();
sah.army.setCreature(SlotID(0), newHero->type->initialArmy[0].creature, 1);
sah.army.setCreature(SlotID(0), newHero->getHeroType()->initialArmy[0].creature, 1);
}
}
else
@ -208,7 +208,7 @@ bool HeroPoolProcessor::hireHero(const ObjectInstanceID & objectID, const HeroTy
for(const auto & hero : recruitableHeroes)
{
if(hero->getHeroType() == heroToRecruit)
if(hero->getHeroTypeID() == heroToRecruit)
recruitedHero = hero;
}
@ -221,7 +221,7 @@ bool HeroPoolProcessor::hireHero(const ObjectInstanceID & objectID, const HeroTy
HeroRecruited hr;
hr.tid = mapObject->id;
hr.hid = recruitedHero->getHeroType();
hr.hid = recruitedHero->getHeroTypeID();
hr.player = player;
hr.tile = recruitedHero->convertFromVisitablePos(targetPos );
if(gameHandler->getTile(targetPos)->isWater() && !recruitedHero->boat)
@ -258,14 +258,14 @@ std::vector<const CHeroClass *> HeroPoolProcessor::findAvailableClassesFor(const
for(const auto & elem : heroesPool->unusedHeroesFromPool())
{
if (vstd::contains(result, elem.second->type->heroClass))
if (vstd::contains(result, elem.second->getHeroClass()))
continue;
bool heroAvailable = heroesPool->isHeroAvailableFor(elem.first, player);
bool heroClassBanned = elem.second->type->heroClass->tavernProbability(factionID) == 0;
bool heroClassBanned = elem.second->getHeroClass()->tavernProbability(factionID) == 0;
if(heroAvailable && !heroClassBanned)
result.push_back(elem.second->type->heroClass);
result.push_back(elem.second->getHeroClass());
}
return result;
@ -282,7 +282,7 @@ std::vector<CGHeroInstance *> HeroPoolProcessor::findAvailableHeroesFor(const Pl
assert(!vstd::contains(result, elem.second));
bool heroAvailable = heroesPool->isHeroAvailableFor(elem.first, player);
bool heroClassMatches = elem.second->type->heroClass == heroClass;
bool heroClassMatches = elem.second->getHeroClass() == heroClass;
if(heroAvailable && heroClassMatches)
result.push_back(elem.second);
@ -318,7 +318,7 @@ const CHeroClass * HeroPoolProcessor::pickClassFor(bool isNative, const PlayerCo
continue;
bool hasSameClass = vstd::contains_if(currentTavern, [&](const CGHeroInstance * hero){
return hero->type->heroClass == heroClass;
return hero->getHeroClass() == heroClass;
});
if (hasSameClass)

View File

@ -95,10 +95,10 @@ void NewTurnProcessor::handleTownEvents(const CGTownInstance * town)
// 1. Building exists in town (don't attempt to build Lvl 5 guild in Fortress
// 2. Building was not built yet
// othervice, silently ignore / skip it
if (town->town->buildings.count(i) && !town->hasBuilt(i))
if (town->getTown()->buildings.count(i) && !town->hasBuilt(i))
{
gameHandler->buildStructure(town->id, i, true);
iw.components.emplace_back(ComponentType::BUILDING, BuildingTypeUniqueID(town->getFaction(), i));
iw.components.emplace_back(ComponentType::BUILDING, BuildingTypeUniqueID(town->getFactionID(), i));
}
}
@ -246,7 +246,7 @@ SetAvailableCreatures NewTurnProcessor::generateTownGrowth(const CGTownInstance
sac.tid = t->id;
sac.creatures = t->creatures;
for (int k=0; k < t->town->creatures.size(); k++)
for (int k=0; k < t->getTown()->creatures.size(); k++)
{
if (t->creatures.at(k).second.empty())
continue;
@ -345,7 +345,7 @@ void NewTurnProcessor::updateNeutralTownGarrison(const CGTownInstance * t, int c
{
const auto * creature = slot.second->type;
if (creature->getFaction() != t->getFaction())
if (creature->getFactionID() != t->getFactionID())
continue;
if (creature->getLevel() != tierToGrow)
@ -518,7 +518,7 @@ std::tuple<EWeekType, CreatureID> NewTurnProcessor::pickWeekType(bool newMonth)
{
newMonster.second = VLC->creh->pickRandomMonster(gameHandler->getRandomGenerator());
} while (VLC->creh->objects[newMonster.second] &&
(*VLC->townh)[VLC->creatures()->getById(newMonster.second)->getFaction()]->town == nullptr); // find first non neutral creature
(*VLC->townh)[VLC->creatures()->getById(newMonster.second)->getFactionID()]->town == nullptr); // find first non neutral creature
return { EWeekType::BONUS_GROWTH, newMonster.second};
}

View File

@ -370,7 +370,7 @@ void PlayerMessageProcessor::cheatBuildTown(PlayerColor player, const CGTownInst
if (!town)
return;
for (auto & build : town->town->buildings)
for (auto & build : town->getTown()->buildings)
{
if (!town->hasBuilt(build.first)
&& !build.second->getNameTranslated().empty()

View File

@ -100,7 +100,7 @@ TEST_F(CCreatureTest, DISABLED_JsonUpdate)
EXPECT_EQ(subject->getFightValue(), 2420);
EXPECT_EQ(subject->getLevel(), 6);
EXPECT_EQ(subject->getFaction().getNum(), 55);
EXPECT_EQ(subject->getFactionID().getNum(), 55);
EXPECT_TRUE(subject->isDoubleWide());
}

View File

@ -44,7 +44,7 @@ public:
MOCK_CONST_METHOD0(getLevel, int32_t());
MOCK_CONST_METHOD0(getGrowth, int32_t());
MOCK_CONST_METHOD0(getHorde, int32_t());
MOCK_CONST_METHOD0(getFaction, FactionID());
MOCK_CONST_METHOD0(getFactionID, FactionID());
MOCK_CONST_METHOD0(getBaseAttack, int32_t());
MOCK_CONST_METHOD0(getBaseDefense, int32_t());

View File

@ -82,7 +82,7 @@ public:
MOCK_CONST_METHOD1(willMove, bool(int));
MOCK_CONST_METHOD1(waited, bool(int));
MOCK_CONST_METHOD0(getFaction, FactionID());
MOCK_CONST_METHOD0(getFactionID, FactionID());
MOCK_CONST_METHOD1(battleQueuePhase, battle::BattlePhases::Type(int));