1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-09-16 09:26:28 +02:00

Merge branch 'develop' into timed_events_objects_removal

This commit is contained in:
Dydzio
2024-12-03 17:27:24 +01:00
1025 changed files with 27590 additions and 17644 deletions

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());
@@ -166,7 +166,7 @@ GrowthInfo CGTownInstance::getGrowthInfo(int level) const
const auto growth = b->val * (base + castleBonus) / 100;
if (growth)
{
ret.entries.emplace_back(growth, b->Description(growth));
ret.entries.emplace_back(growth, b->Description(cb, growth));
}
}
@@ -174,7 +174,7 @@ GrowthInfo CGTownInstance::getGrowthInfo(int level) const
// Note: bonus uses 1-based levels (Pikeman is level 1), town list uses 0-based (Pikeman in 0-th creatures entry)
TConstBonusListPtr bonuses = getBonuses(Selector::typeSubtype(BonusType::CREATURE_GROWTH, BonusCustomSubtype::creatureLevel(level+1)));
for(const auto & b : *bonuses)
ret.entries.emplace_back(b->val, b->Description());
ret.entries.emplace_back(b->val, b->Description(cb));
int dwellingBonus = 0;
if(const PlayerState *p = cb->getPlayerState(tempOwner, false))
@@ -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,11 +264,13 @@ TownFortifications CGTownInstance::fortificationsLevel() const
CGTownInstance::CGTownInstance(IGameCallback *cb):
CGDwelling(cb),
town(nullptr),
built(0),
destroyed(0),
identifier(0),
alignmentToPlayer(PlayerColor::NEUTRAL)
alignmentToPlayer(PlayerColor::NEUTRAL),
spellResearchCounterDay(0),
spellResearchAcceptedCounter(0),
spellResearchAllowed(true)
{
this->setNodeType(CBonusSystemNode::TOWN);
}
@@ -347,7 +349,7 @@ void CGTownInstance::onHeroVisit(const CGHeroInstance * h) const
scp.heroid = h->id;
scp.which = SetCommanderProperty::ALIVE;
scp.amount = 1;
cb->sendAndApply(&scp);
cb->sendAndApply(scp);
}
cb->heroVisitCastle(this, h);
// TODO(vmarkovtsev): implement payment for rising the commander
@@ -376,17 +378,17 @@ void CGTownInstance::onHeroLeave(const CGHeroInstance * h) const
std::string CGTownInstance::getObjectName() const
{
return getNameTranslated() + ", " + (ID == Obj::RANDOM_TOWN ? "Random town" : getFaction().toEntity(VLC)->getNameTranslated());
return getNameTranslated() + ", " + (ID == Obj::RANDOM_TOWN ? "Random town" : 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);
@@ -454,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();
}
@@ -464,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);
@@ -620,15 +621,15 @@ 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;
rs.bid.insert(BuildingID::CAPITOL);
rs.destroyed = destroyed;
cb->sendAndApply(&rs);
cb->sendAndApply(rs);
return;
}
}
@@ -645,7 +646,7 @@ void CGTownInstance::clearArmy() const
BoatId CGTownInstance::getBoatType() const
{
return town->faction->boatType;
return getTown()->faction->boatType;
}
int CGTownInstance::getMarketEfficiency() const
@@ -669,11 +670,9 @@ std::vector<TradeItemBuy> CGTownInstance::availableItemsIds(EMarketMode mode) co
if(mode == EMarketMode::RESOURCE_ARTIFACT)
{
std::vector<TradeItemBuy> ret;
for(const CArtifact *a : cb->gameState()->map->townMerchantArtifacts)
if(a)
ret.push_back(a->getId());
else
ret.push_back(ArtifactID{});
for(const ArtifactID a : cb->gameState()->map->townMerchantArtifacts)
ret.push_back(a);
return ret;
}
else if ( mode == EMarketMode::RESOURCE_SKILL )
@@ -691,7 +690,7 @@ ObjectInstanceID CGTownInstance::getObjInstanceID() const
void CGTownInstance::updateAppearance()
{
auto terrain = cb->gameState()->getTile(visitablePos())->terType->getId();
auto terrain = cb->gameState()->getTile(visitablePos())->getTerrainID();
//FIXME: not the best way to do this
auto app = getObjectHandler()->getOverride(terrain, this);
if (app)
@@ -700,7 +699,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()
@@ -749,7 +748,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;
}
@@ -758,7 +757,7 @@ void CGTownInstance::recreateBuildingsBonuses()
if (bonusesReplacedByUpgrade)
continue;
auto building = town->buildings.at(bid);
auto building = getTown()->buildings.at(bid);
if(building->buildingBonuses.empty())
continue;
@@ -825,21 +824,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
@@ -847,7 +831,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;
@@ -889,7 +873,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;
@@ -902,7 +886,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;
}
@@ -920,7 +904,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());
}
@@ -947,11 +931,11 @@ 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(), pos.toString(), buildingID.toEnum());
logGlobal->error("Town %s at %s has no possible building %d!", getNameTranslated(), anchorPos().toString(), buildingID.toEnum());
return TResources();
}
@@ -959,7 +943,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;
@@ -967,13 +951,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))
@@ -998,7 +982,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();
@@ -1148,14 +1132,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
@@ -1163,21 +1160,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;
@@ -1197,7 +1194,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();
@@ -1228,14 +1225,14 @@ void CGTownInstance::fillUpgradeInfo(UpgradeInfo & info, const CStackInstance &s
{
for(const CGTownInstance::TCreaturesSet::value_type & dwelling : creatures)
{
if (vstd::contains(dwelling.second, stack.type->getId())) //Dwelling with our creature
if (vstd::contains(dwelling.second, stack.getId())) //Dwelling with our creature
{
for(const auto & upgrID : dwelling.second)
{
if(vstd::contains(stack.type->upgrades, upgrID)) //possible upgrade
if(vstd::contains(stack.getCreature()->upgrades, upgrID)) //possible upgrade
{
info.newID.push_back(upgrID);
info.cost.push_back(upgrID.toCreature()->getFullRecruitCost() - stack.type->getFullRecruitCost());
info.cost.push_back(upgrID.toCreature()->getFullRecruitCost() - stack.getType()->getFullRecruitCost());
}
}
}