mirror of
https://github.com/vcmi/vcmi.git
synced 2025-02-03 13:01:33 +02:00
Merge pull request #1882 from rilian-la-te/native-terrain-refactor
Native terrain refactor
This commit is contained in:
commit
ff66592fad
@ -96,14 +96,14 @@ public:
|
|||||||
std::vector<SlotInfo> ArmyManager::getBestArmy(const IBonusBearer * armyCarrier, const CCreatureSet * target, const CCreatureSet * source) const
|
std::vector<SlotInfo> ArmyManager::getBestArmy(const IBonusBearer * armyCarrier, const CCreatureSet * target, const CCreatureSet * source) const
|
||||||
{
|
{
|
||||||
auto sortedSlots = getSortedSlots(target, source);
|
auto sortedSlots = getSortedSlots(target, source);
|
||||||
std::map<TFaction, uint64_t> alignmentMap;
|
std::map<FactionID, uint64_t> alignmentMap;
|
||||||
|
|
||||||
for(auto & slot : sortedSlots)
|
for(auto & slot : sortedSlots)
|
||||||
{
|
{
|
||||||
alignmentMap[slot.creature->getFactionIndex()] += slot.power;
|
alignmentMap[slot.creature->getFaction()] += slot.power;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::set<TFaction> allowedFactions;
|
std::set<FactionID> allowedFactions;
|
||||||
std::vector<SlotInfo> resultingArmy;
|
std::vector<SlotInfo> resultingArmy;
|
||||||
uint64_t armyValue = 0;
|
uint64_t armyValue = 0;
|
||||||
|
|
||||||
@ -121,7 +121,7 @@ std::vector<SlotInfo> ArmyManager::getBestArmy(const IBonusBearer * armyCarrier,
|
|||||||
|
|
||||||
while(allowedFactions.size() < alignmentMap.size())
|
while(allowedFactions.size() < alignmentMap.size())
|
||||||
{
|
{
|
||||||
auto strongestAlignment = vstd::maxElementByFun(alignmentMap, [&](std::pair<TFaction, uint64_t> pair) -> uint64_t
|
auto strongestAlignment = vstd::maxElementByFun(alignmentMap, [&](std::pair<FactionID, uint64_t> pair) -> uint64_t
|
||||||
{
|
{
|
||||||
return vstd::contains(allowedFactions, pair.first) ? 0 : pair.second;
|
return vstd::contains(allowedFactions, pair.first) ? 0 : pair.second;
|
||||||
});
|
});
|
||||||
@ -134,7 +134,7 @@ std::vector<SlotInfo> ArmyManager::getBestArmy(const IBonusBearer * armyCarrier,
|
|||||||
|
|
||||||
for(auto & slot : sortedSlots)
|
for(auto & slot : sortedSlots)
|
||||||
{
|
{
|
||||||
if(vstd::contains(allowedFactions, slot.creature->getFactionIndex()))
|
if(vstd::contains(allowedFactions, slot.creature->getFaction()))
|
||||||
{
|
{
|
||||||
auto slotID = newArmyInstance.getSlotFor(slot.creature);
|
auto slotID = newArmyInstance.getSlotFor(slot.creature);
|
||||||
|
|
||||||
|
@ -94,7 +94,7 @@ TGoalVec GatherTroops::getAllPossibleSubgoals()
|
|||||||
}
|
}
|
||||||
|
|
||||||
auto creature = VLC->creatures()->getByIndex(objid);
|
auto creature = VLC->creatures()->getByIndex(objid);
|
||||||
if(t->subID == creature->getFactionIndex()) //TODO: how to force AI to build unupgraded creatures? :O
|
if(t->subID == creature->getFaction()) //TODO: how to force AI to build unupgraded creatures? :O
|
||||||
{
|
{
|
||||||
auto creatures = vstd::tryAt(t->town->creatures, creature->getLevel() - 1);
|
auto creatures = vstd::tryAt(t->town->creatures, creature->getLevel() - 1);
|
||||||
if(!creatures)
|
if(!creatures)
|
||||||
|
@ -448,7 +448,7 @@ CCreaturePic::CCreaturePic(int x, int y, const CCreature * cre, bool Big, bool A
|
|||||||
pos.x+=x;
|
pos.x+=x;
|
||||||
pos.y+=y;
|
pos.y+=y;
|
||||||
|
|
||||||
TFaction faction = cre->getFactionIndex();
|
auto faction = cre->getFaction();
|
||||||
|
|
||||||
assert(CGI->townh->size() > faction);
|
assert(CGI->townh->size() > faction);
|
||||||
|
|
||||||
|
@ -892,7 +892,7 @@ void CCastleBuildings::enterFountain(const BuildingID & building, BuildingSubID:
|
|||||||
std::string hasNotProduced;
|
std::string hasNotProduced;
|
||||||
std::string hasProduced;
|
std::string hasProduced;
|
||||||
|
|
||||||
if(this->town->town->faction->getIndex() == (TFaction)ETownType::RAMPART)
|
if(this->town->town->faction->getIndex() == ETownType::RAMPART)
|
||||||
{
|
{
|
||||||
hasNotProduced = CGI->generaltexth->allTexts[677];
|
hasNotProduced = CGI->generaltexth->allTexts[677];
|
||||||
hasProduced = CGI->generaltexth->allTexts[678];
|
hasProduced = CGI->generaltexth->allTexts[678];
|
||||||
|
@ -163,6 +163,7 @@ macro(add_main_lib TARGET_NAME LIBRARY_TYPE)
|
|||||||
|
|
||||||
${MAIN_LIB_DIR}/vstd/StringUtils.cpp
|
${MAIN_LIB_DIR}/vstd/StringUtils.cpp
|
||||||
|
|
||||||
|
${MAIN_LIB_DIR}/BasicTypes.cpp
|
||||||
${MAIN_LIB_DIR}/BattleFieldHandler.cpp
|
${MAIN_LIB_DIR}/BattleFieldHandler.cpp
|
||||||
${MAIN_LIB_DIR}/CAndroidVMHelper.cpp
|
${MAIN_LIB_DIR}/CAndroidVMHelper.cpp
|
||||||
${MAIN_LIB_DIR}/CArtHandler.cpp
|
${MAIN_LIB_DIR}/CArtHandler.cpp
|
||||||
|
@ -18,7 +18,7 @@ class CreatureID;
|
|||||||
class ResourceSet;
|
class ResourceSet;
|
||||||
enum class EGameResID : int8_t;
|
enum class EGameResID : int8_t;
|
||||||
|
|
||||||
class DLL_LINKAGE Creature : public EntityWithBonuses<CreatureID>
|
class DLL_LINKAGE Creature : public EntityWithNativeTerrain<CreatureID>
|
||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
// use getNamePlural/Singular instead
|
// use getNamePlural/Singular instead
|
||||||
@ -41,7 +41,6 @@ public:
|
|||||||
virtual int32_t getLevel() const = 0;
|
virtual int32_t getLevel() const = 0;
|
||||||
virtual int32_t getGrowth() const = 0;
|
virtual int32_t getGrowth() const = 0;
|
||||||
virtual int32_t getHorde() const = 0;
|
virtual int32_t getHorde() const = 0;
|
||||||
virtual int32_t getFactionIndex() const = 0;
|
|
||||||
|
|
||||||
virtual int32_t getBaseAttack() const = 0;
|
virtual int32_t getBaseAttack() const = 0;
|
||||||
virtual int32_t getBaseDefense() const = 0;
|
virtual int32_t getBaseDefense() const = 0;
|
||||||
|
@ -13,13 +13,33 @@
|
|||||||
VCMI_LIB_NAMESPACE_BEGIN
|
VCMI_LIB_NAMESPACE_BEGIN
|
||||||
|
|
||||||
class IBonusBearer;
|
class IBonusBearer;
|
||||||
|
class FactionID;
|
||||||
|
enum class ETerrainId;
|
||||||
|
template<typename T> class Identifier;
|
||||||
|
|
||||||
class DLL_LINKAGE WithBonuses
|
class DLL_LINKAGE IConstBonusProvider
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual const IBonusBearer * getBonusBearer() const = 0;
|
virtual const IBonusBearer * getBonusBearer() const = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class DLL_LINKAGE INativeTerrainProvider
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual Identifier<ETerrainId> getNativeTerrain() const = 0;
|
||||||
|
virtual FactionID getFaction() const = 0;
|
||||||
|
virtual bool isNativeTerrain(Identifier<ETerrainId> terrain) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
class DLL_LINKAGE IConstBonusNativeTerrainProvider: public IConstBonusProvider, public INativeTerrainProvider
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
Returns native terrain considering some terrain bonuses.
|
||||||
|
*/
|
||||||
|
virtual Identifier<ETerrainId> getNativeTerrain() const;
|
||||||
|
};
|
||||||
|
|
||||||
class DLL_LINKAGE Entity
|
class DLL_LINKAGE Entity
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -44,7 +64,12 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
template <typename IdType>
|
template <typename IdType>
|
||||||
class DLL_LINKAGE EntityWithBonuses : public EntityT<IdType>, public WithBonuses
|
class DLL_LINKAGE EntityWithBonuses : public EntityT<IdType>, public IConstBonusProvider
|
||||||
|
{
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename IdType>
|
||||||
|
class DLL_LINKAGE EntityWithNativeTerrain : public EntityT<IdType>, public IConstBonusNativeTerrainProvider
|
||||||
{
|
{
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -15,15 +15,12 @@
|
|||||||
VCMI_LIB_NAMESPACE_BEGIN
|
VCMI_LIB_NAMESPACE_BEGIN
|
||||||
|
|
||||||
class FactionID;
|
class FactionID;
|
||||||
enum class ETerrainId;
|
|
||||||
enum class EAlignment : uint8_t;
|
enum class EAlignment : uint8_t;
|
||||||
template<typename T> class Identifier;
|
|
||||||
|
|
||||||
class DLL_LINKAGE Faction : public EntityT<FactionID>
|
class DLL_LINKAGE Faction : public EntityT<FactionID>, public INativeTerrainProvider
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual bool hasTown() const = 0;
|
virtual bool hasTown() const = 0;
|
||||||
virtual Identifier<ETerrainId> getNativeTerrain() const = 0;
|
|
||||||
virtual EAlignment getAlignment() const = 0;
|
virtual EAlignment getAlignment() const = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
41
lib/BasicTypes.cpp
Normal file
41
lib/BasicTypes.cpp
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
/*
|
||||||
|
* BasicTypes.cpp, part of VCMI engine
|
||||||
|
*
|
||||||
|
* Authors: listed in file AUTHORS in main folder
|
||||||
|
*
|
||||||
|
* License: GNU General Public License v2.0 or later
|
||||||
|
* Full text of license available in license.txt file, in main folder
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "StdInc.h"
|
||||||
|
|
||||||
|
#include "VCMI_Lib.h"
|
||||||
|
#include "GameConstants.h"
|
||||||
|
#include "HeroBonus.h"
|
||||||
|
|
||||||
|
#include <vcmi/Entity.h>
|
||||||
|
#include <vcmi/Faction.h>
|
||||||
|
#include <vcmi/FactionService.h>
|
||||||
|
|
||||||
|
VCMI_LIB_NAMESPACE_BEGIN
|
||||||
|
|
||||||
|
bool INativeTerrainProvider::isNativeTerrain(TerrainId terrain) const
|
||||||
|
{
|
||||||
|
auto native = getNativeTerrain();
|
||||||
|
return native == terrain || native == ETerrainId::ANY_TERRAIN;
|
||||||
|
}
|
||||||
|
|
||||||
|
TerrainId IConstBonusNativeTerrainProvider::getNativeTerrain() const
|
||||||
|
{
|
||||||
|
constexpr auto any = TerrainId(ETerrainId::ANY_TERRAIN);
|
||||||
|
const std::string cachingStringNoTerrainPenalty = "type_NO_TERRAIN_PENALTY_sANY";
|
||||||
|
static const auto selectorNoTerrainPenalty = Selector::typeSubtype(Bonus::NO_TERRAIN_PENALTY, any);
|
||||||
|
|
||||||
|
//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)
|
||||||
|
? any : VLC->factions()->getById(getFaction())->getNativeTerrain();
|
||||||
|
}
|
||||||
|
|
||||||
|
VCMI_LIB_NAMESPACE_END
|
@ -109,9 +109,9 @@ int32_t CCreature::getHorde() const
|
|||||||
return hordeGrowth;
|
return hordeGrowth;
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t CCreature::getFactionIndex() const
|
FactionID CCreature::getFaction() const
|
||||||
{
|
{
|
||||||
return faction;
|
return FactionID(faction);
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t CCreature::getBaseAttack() const
|
int32_t CCreature::getBaseAttack() const
|
||||||
@ -330,24 +330,6 @@ std::string CCreature::nodeName() const
|
|||||||
return "\"" + getNamePluralTextID() + "\"";
|
return "\"" + getNamePluralTextID() + "\"";
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CCreature::isItNativeTerrain(TerrainId terrain) const
|
|
||||||
{
|
|
||||||
auto native = getNativeTerrain();
|
|
||||||
return native == terrain || native == ETerrainId::ANY_TERRAIN;
|
|
||||||
}
|
|
||||||
|
|
||||||
TerrainId CCreature::getNativeTerrain() const
|
|
||||||
{
|
|
||||||
const std::string cachingStringNoTerrainPenalty = "type_NO_TERRAIN_PENALTY_sANY";
|
|
||||||
static const auto selectorNoTerrainPenalty = Selector::typeSubtype(Bonus::NO_TERRAIN_PENALTY, static_cast<int>(ETerrainId::ANY_TERRAIN));
|
|
||||||
|
|
||||||
//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 hasBonus(selectorNoTerrainPenalty, cachingStringNoTerrainPenalty)
|
|
||||||
? TerrainId(ETerrainId::ANY_TERRAIN)
|
|
||||||
: VLC->factions()->getByIndex(faction)->getNativeTerrain();
|
|
||||||
}
|
|
||||||
|
|
||||||
void CCreature::updateFrom(const JsonNode & data)
|
void CCreature::updateFrom(const JsonNode & data)
|
||||||
{
|
{
|
||||||
JsonUpdater handler(nullptr, data);
|
JsonUpdater handler(nullptr, data);
|
||||||
@ -421,13 +403,6 @@ CCreatureHandler::CCreatureHandler()
|
|||||||
: expAfterUpgrade(0)
|
: expAfterUpgrade(0)
|
||||||
{
|
{
|
||||||
VLC->creh = this;
|
VLC->creh = this;
|
||||||
|
|
||||||
allCreatures.setDescription("All creatures");
|
|
||||||
allCreatures.setNodeType(CBonusSystemNode::ENodeTypes::ALL_CREATURES);
|
|
||||||
creaturesOfLevel[0].setDescription("Creatures of unnormalized tier");
|
|
||||||
|
|
||||||
for(int i = 1; i < ARRAY_COUNT(creaturesOfLevel); i++)
|
|
||||||
creaturesOfLevel[i].setDescription("Creatures of tier " + std::to_string(i));
|
|
||||||
loadCommanders();
|
loadCommanders();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -692,10 +667,24 @@ std::vector<bool> CCreatureHandler::getDefaultAllowed() const
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CCreatureHandler::loadCrExpBon()
|
void CCreatureHandler::loadCrExpBon(CBonusSystemNode & globalEffects)
|
||||||
{
|
{
|
||||||
if (VLC->settings()->getBoolean(EGameSettings::MODULE_STACK_EXPERIENCE)) //reading default stack experience bonuses
|
if (VLC->settings()->getBoolean(EGameSettings::MODULE_STACK_EXPERIENCE)) //reading default stack experience bonuses
|
||||||
{
|
{
|
||||||
|
logGlobal->debug("\tLoading stack experience bonuses");
|
||||||
|
auto addBonusForAllCreatures = [&](std::shared_ptr<Bonus> b) {
|
||||||
|
auto limiter = std::make_shared<CreatureLevelLimiter>();
|
||||||
|
b->addLimiter(limiter);
|
||||||
|
globalEffects.addNewBonus(b);
|
||||||
|
};
|
||||||
|
auto addBonusForTier = [&](int tier, std::shared_ptr<Bonus> b) {
|
||||||
|
assert(vstd::iswithin(tier, 1, 7));
|
||||||
|
//bonuses from level 7 are given to high-level creatures too
|
||||||
|
auto max = tier == GameConstants::CREATURES_PER_TOWN ? std::numeric_limits<int>::max() : tier + 1;
|
||||||
|
auto limiter = std::make_shared<CreatureLevelLimiter>(tier, max);
|
||||||
|
b->addLimiter(limiter);
|
||||||
|
globalEffects.addNewBonus(b);
|
||||||
|
};
|
||||||
CLegacyConfigParser parser("DATA/CREXPBON.TXT");
|
CLegacyConfigParser parser("DATA/CREXPBON.TXT");
|
||||||
|
|
||||||
Bonus b; //prototype with some default properties
|
Bonus b; //prototype with some default properties
|
||||||
@ -733,10 +722,7 @@ void CCreatureHandler::loadCrExpBon()
|
|||||||
bl.clear();
|
bl.clear();
|
||||||
loadStackExp(b, bl, parser);
|
loadStackExp(b, bl, parser);
|
||||||
for(const auto & b : bl)
|
for(const auto & b : bl)
|
||||||
{
|
|
||||||
addBonusForTier(7, b);
|
addBonusForTier(7, b);
|
||||||
creaturesOfLevel[0].addNewBonus(b); //bonuses from level 7 are given to high-level creatures
|
|
||||||
}
|
|
||||||
parser.endLine();
|
parser.endLine();
|
||||||
}
|
}
|
||||||
do //parse everything that's left
|
do //parse everything that's left
|
||||||
@ -924,7 +910,7 @@ void CCreatureHandler::loadCreatureJson(CCreature * creature, const JsonNode & c
|
|||||||
|
|
||||||
VLC->modh->identifiers.requestIdentifier("faction", config["faction"], [=](si32 faction)
|
VLC->modh->identifiers.requestIdentifier("faction", config["faction"], [=](si32 faction)
|
||||||
{
|
{
|
||||||
creature->faction = faction;
|
creature->faction = FactionID(faction);
|
||||||
});
|
});
|
||||||
|
|
||||||
for(const JsonNode &value : config["upgrades"].Vector())
|
for(const JsonNode &value : config["upgrades"].Vector())
|
||||||
@ -1352,12 +1338,10 @@ CreatureID CCreatureHandler::pickRandomMonster(CRandomGenerator & rand, int tier
|
|||||||
{
|
{
|
||||||
assert(vstd::iswithin(tier, 1, 7));
|
assert(vstd::iswithin(tier, 1, 7));
|
||||||
std::vector<CreatureID> allowed;
|
std::vector<CreatureID> allowed;
|
||||||
for(const CBonusSystemNode *b : creaturesOfLevel[tier].getChildrenNodes())
|
for(const auto & creature : objects)
|
||||||
{
|
{
|
||||||
assert(b->getNodeType() == CBonusSystemNode::CREATURE);
|
if(!creature->special && creature->level == tier)
|
||||||
const auto * crea = dynamic_cast<const CCreature *>(b);
|
allowed.push_back(creature->getId());
|
||||||
if(crea && !crea->special)
|
|
||||||
allowed.push_back(crea->getId());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(allowed.empty())
|
if(allowed.empty())
|
||||||
@ -1372,49 +1356,10 @@ CreatureID CCreatureHandler::pickRandomMonster(CRandomGenerator & rand, int tier
|
|||||||
return CreatureID(r);
|
return CreatureID(r);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CCreatureHandler::addBonusForTier(int tier, const std::shared_ptr<Bonus> & b)
|
|
||||||
{
|
|
||||||
assert(vstd::iswithin(tier, 1, 7));
|
|
||||||
creaturesOfLevel[tier].addNewBonus(b);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CCreatureHandler::addBonusForAllCreatures(const std::shared_ptr<Bonus> & b)
|
|
||||||
{
|
|
||||||
const auto & exportedBonuses = allCreatures.getExportedBonusList();
|
|
||||||
for(const auto & bonus : exportedBonuses)
|
|
||||||
{
|
|
||||||
if(bonus->type == b->type && bonus->subtype == b->subtype)
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
allCreatures.addNewBonus(b);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CCreatureHandler::removeBonusesFromAllCreatures()
|
|
||||||
{
|
|
||||||
allCreatures.removeBonuses(Selector::all);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CCreatureHandler::buildBonusTreeForTiers()
|
|
||||||
{
|
|
||||||
for(CCreature * c : objects)
|
|
||||||
{
|
|
||||||
if(vstd::isbetween(c->level, 0, ARRAY_COUNT(creaturesOfLevel)))
|
|
||||||
c->attachTo(creaturesOfLevel[c->level]);
|
|
||||||
else
|
|
||||||
c->attachTo(creaturesOfLevel[0]);
|
|
||||||
}
|
|
||||||
for(CBonusSystemNode &b : creaturesOfLevel)
|
|
||||||
b.attachTo(allCreatures);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CCreatureHandler::afterLoadFinalization()
|
void CCreatureHandler::afterLoadFinalization()
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CCreatureHandler::deserializationFix()
|
|
||||||
{
|
|
||||||
buildBonusTreeForTiers();
|
|
||||||
}
|
|
||||||
|
|
||||||
VCMI_LIB_NAMESPACE_END
|
VCMI_LIB_NAMESPACE_END
|
||||||
|
@ -39,7 +39,7 @@ class DLL_LINKAGE CCreature : public Creature, public CBonusSystemNode
|
|||||||
|
|
||||||
CreatureID idNumber;
|
CreatureID idNumber;
|
||||||
|
|
||||||
TFaction faction = 0;
|
FactionID faction = FactionID::NEUTRAL;
|
||||||
ui8 level = 0; // 0 - unknown; 1-7 for "usual" creatures
|
ui8 level = 0; // 0 - unknown; 1-7 for "usual" creatures
|
||||||
|
|
||||||
//stats that are not handled by bonus system
|
//stats that are not handled by bonus system
|
||||||
@ -162,11 +162,7 @@ public:
|
|||||||
std::string getNamePluralTextID() const override;
|
std::string getNamePluralTextID() const override;
|
||||||
std::string getNameSingularTextID() const override;
|
std::string getNameSingularTextID() const override;
|
||||||
|
|
||||||
bool isItNativeTerrain(TerrainId terrain) const;
|
FactionID getFaction() const override;
|
||||||
/**
|
|
||||||
Returns creature native terrain considering some terrain bonuses.
|
|
||||||
*/
|
|
||||||
TerrainId getNativeTerrain() const;
|
|
||||||
int32_t getIndex() const override;
|
int32_t getIndex() const override;
|
||||||
int32_t getIconIndex() const override;
|
int32_t getIconIndex() const override;
|
||||||
std::string getJsonKey() const override;
|
std::string getJsonKey() const override;
|
||||||
@ -182,7 +178,6 @@ public:
|
|||||||
int32_t getLevel() const override;
|
int32_t getLevel() const override;
|
||||||
int32_t getGrowth() const override;
|
int32_t getGrowth() const override;
|
||||||
int32_t getHorde() const override;
|
int32_t getHorde() const override;
|
||||||
int32_t getFactionIndex() const override;
|
|
||||||
|
|
||||||
int32_t getBaseAttack() const override;
|
int32_t getBaseAttack() const override;
|
||||||
int32_t getBaseDefense() const override;
|
int32_t getBaseDefense() const override;
|
||||||
@ -262,9 +257,6 @@ private:
|
|||||||
class DLL_LINKAGE CCreatureHandler : public CHandlerBase<CreatureID, Creature, CCreature, CreatureService>
|
class DLL_LINKAGE CCreatureHandler : public CHandlerBase<CreatureID, Creature, CCreature, CreatureService>
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
CBonusSystemNode allCreatures;
|
|
||||||
CBonusSystemNode creaturesOfLevel[GameConstants::CREATURES_PER_TOWN + 1];//index 0 is used for creatures of unknown tier or outside <1-7> range
|
|
||||||
|
|
||||||
void loadJsonAnimation(CCreature * creature, const JsonNode & graphics) const;
|
void loadJsonAnimation(CCreature * creature, const JsonNode & graphics) const;
|
||||||
void loadStackExperience(CCreature * creature, const JsonNode & input) const;
|
void loadStackExperience(CCreature * creature, const JsonNode & input) const;
|
||||||
void loadCreatureJson(CCreature * creature, const JsonNode & config) const;
|
void loadCreatureJson(CCreature * creature, const JsonNode & config) const;
|
||||||
@ -304,19 +296,13 @@ public:
|
|||||||
|
|
||||||
const CCreature * getCreature(const std::string & scope, const std::string & identifier) const;
|
const CCreature * getCreature(const std::string & scope, const std::string & identifier) const;
|
||||||
|
|
||||||
void deserializationFix();
|
|
||||||
CreatureID pickRandomMonster(CRandomGenerator & rand, int tier = -1) const; //tier <1 - CREATURES_PER_TOWN> or -1 for any
|
CreatureID pickRandomMonster(CRandomGenerator & rand, int tier = -1) const; //tier <1 - CREATURES_PER_TOWN> or -1 for any
|
||||||
void addBonusForTier(int tier, const std::shared_ptr<Bonus> & b); //tier must be <1-7>
|
|
||||||
void addBonusForAllCreatures(const std::shared_ptr<Bonus> & b); //due to CBonusSystem::addNewBonus(const std::shared_ptr<Bonus>& b);
|
|
||||||
void removeBonusesFromAllCreatures();
|
|
||||||
|
|
||||||
CCreatureHandler();
|
CCreatureHandler();
|
||||||
~CCreatureHandler();
|
~CCreatureHandler();
|
||||||
|
|
||||||
/// load all creatures from H3 files
|
/// load all stack experience bonuses from H3 files
|
||||||
void loadCrExpBon();
|
void loadCrExpBon(CBonusSystemNode & globalEffects);
|
||||||
/// generates tier-specific bonus tree entries
|
|
||||||
void buildBonusTreeForTiers();
|
|
||||||
|
|
||||||
void afterLoadFinalization() override;
|
void afterLoadFinalization() override;
|
||||||
|
|
||||||
@ -335,9 +321,6 @@ public:
|
|||||||
h & skillLevels;
|
h & skillLevels;
|
||||||
h & skillRequirements;
|
h & skillRequirements;
|
||||||
h & commanderLevelPremy;
|
h & commanderLevelPremy;
|
||||||
h & allCreatures;
|
|
||||||
h & creaturesOfLevel;
|
|
||||||
BONUS_TREE_DESERIALIZATION_FIX
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -25,6 +25,9 @@
|
|||||||
#include "serializer/JsonSerializeFormat.h"
|
#include "serializer/JsonSerializeFormat.h"
|
||||||
#include "NetPacksBase.h"
|
#include "NetPacksBase.h"
|
||||||
|
|
||||||
|
#include <vcmi/FactionService.h>
|
||||||
|
#include <vcmi/Faction.h>
|
||||||
|
|
||||||
VCMI_LIB_NAMESPACE_BEGIN
|
VCMI_LIB_NAMESPACE_BEGIN
|
||||||
|
|
||||||
|
|
||||||
@ -912,6 +915,19 @@ void CStackInstance::serializeJson(JsonSerializeFormat & handler)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FactionID CStackInstance::getFaction() const
|
||||||
|
{
|
||||||
|
if(type)
|
||||||
|
return type->getFaction();
|
||||||
|
|
||||||
|
return FactionID::NEUTRAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
const IBonusBearer* CStackInstance::getBonusBearer() const
|
||||||
|
{
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
CCommanderInstance::CCommanderInstance()
|
CCommanderInstance::CCommanderInstance()
|
||||||
{
|
{
|
||||||
init();
|
init();
|
||||||
|
@ -14,6 +14,8 @@
|
|||||||
#include "CArtHandler.h"
|
#include "CArtHandler.h"
|
||||||
#include "CCreatureHandler.h"
|
#include "CCreatureHandler.h"
|
||||||
|
|
||||||
|
#include <vcmi/Entity.h>
|
||||||
|
|
||||||
VCMI_LIB_NAMESPACE_BEGIN
|
VCMI_LIB_NAMESPACE_BEGIN
|
||||||
|
|
||||||
class JsonNode;
|
class JsonNode;
|
||||||
@ -61,7 +63,7 @@ public:
|
|||||||
void serializeJson(JsonSerializeFormat & handler);
|
void serializeJson(JsonSerializeFormat & handler);
|
||||||
};
|
};
|
||||||
|
|
||||||
class DLL_LINKAGE CStackInstance : public CBonusSystemNode, public CStackBasicDescriptor, public CArtifactSet
|
class DLL_LINKAGE CStackInstance : public CBonusSystemNode, public CStackBasicDescriptor, public CArtifactSet, public IConstBonusNativeTerrainProvider
|
||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
const CArmedInstance *_armyObj; //stack must be part of some army, army must be part of some object
|
const CArmedInstance *_armyObj; //stack must be part of some army, army must be part of some object
|
||||||
@ -92,6 +94,11 @@ public:
|
|||||||
std::string bonusToString(const std::shared_ptr<Bonus>& bonus, bool description) const override; // how would bonus description look for this particular type of node
|
std::string bonusToString(const std::shared_ptr<Bonus>& bonus, bool description) const override; // how would bonus description look for this particular type of node
|
||||||
std::string bonusToGraphics(const std::shared_ptr<Bonus> & bonus) const; //file name of graphics from StackSkills , in future possibly others
|
std::string bonusToGraphics(const std::shared_ptr<Bonus> & bonus) const; //file name of graphics from StackSkills , in future possibly others
|
||||||
|
|
||||||
|
//IConstBonusProvider
|
||||||
|
const IBonusBearer* getBonusBearer() const override;
|
||||||
|
//INativeTerrainProvider
|
||||||
|
FactionID getFaction() const override;
|
||||||
|
|
||||||
virtual ui64 getPower() const;
|
virtual ui64 getPower() const;
|
||||||
CCreature::CreatureQuantityId getQuantityID() const;
|
CCreature::CreatureQuantityId getQuantityID() const;
|
||||||
std::string getQuantityTXT(bool capitalized = true) const;
|
std::string getQuantityTXT(bool capitalized = true) const;
|
||||||
|
@ -359,7 +359,7 @@ bool CGameInfoCallback::getHeroInfo(const CGObjectInstance * hero, InfoAboutHero
|
|||||||
|
|
||||||
for(auto creature : VLC->creh->objects)
|
for(auto creature : VLC->creh->objects)
|
||||||
{
|
{
|
||||||
if(static_cast<si16>(creature->getFactionIndex()) == factionIndex && static_cast<int>(creature->getAIValue()) > maxAIValue)
|
if(creature->getFaction() == factionIndex && static_cast<int>(creature->getAIValue()) > maxAIValue)
|
||||||
{
|
{
|
||||||
maxAIValue = creature->getAIValue();
|
maxAIValue = creature->getAIValue();
|
||||||
mostStrong = creature;
|
mostStrong = creature;
|
||||||
|
@ -372,7 +372,7 @@ CGHeroInstance * CGameState::HeroesPool::pickHeroFor(bool native,
|
|||||||
( !bannedClass || elem.second->type->heroClass != bannedClass) ) // and his class is not same as other hero
|
( !bannedClass || elem.second->type->heroClass != bannedClass) ) // and his class is not same as other hero
|
||||||
{
|
{
|
||||||
pool.push_back(elem.second);
|
pool.push_back(elem.second);
|
||||||
sum += elem.second->type->heroClass->selectionProbability[town->faction->getIndex()]; //total weight
|
sum += elem.second->type->heroClass->selectionProbability[town->faction->getId()]; //total weight
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(pool.empty() || sum == 0)
|
if(pool.empty() || sum == 0)
|
||||||
@ -384,7 +384,7 @@ CGHeroInstance * CGameState::HeroesPool::pickHeroFor(bool native,
|
|||||||
r = rand.nextInt(sum - 1);
|
r = rand.nextInt(sum - 1);
|
||||||
for (auto & elem : pool)
|
for (auto & elem : pool)
|
||||||
{
|
{
|
||||||
r -= elem->type->heroClass->selectionProbability[town->faction->getIndex()];
|
r -= elem->type->heroClass->selectionProbability[town->faction->getId()];
|
||||||
if(r < 0)
|
if(r < 0)
|
||||||
{
|
{
|
||||||
ret = elem;
|
ret = elem;
|
||||||
@ -958,6 +958,7 @@ void CGameState::initGlobalBonuses()
|
|||||||
bonus->sid = -1; //there is one global object
|
bonus->sid = -1; //there is one global object
|
||||||
globalEffects.addNewBonus(bonus);
|
globalEffects.addNewBonus(bonus);
|
||||||
}
|
}
|
||||||
|
VLC->creh->loadCrExpBon(globalEffects);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CGameState::initGrailPosition()
|
void CGameState::initGrailPosition()
|
||||||
@ -1746,8 +1747,8 @@ void CGameState::initTowns()
|
|||||||
}
|
}
|
||||||
if(vti->getNameTranslated().empty())
|
if(vti->getNameTranslated().empty())
|
||||||
{
|
{
|
||||||
size_t nameID = getRandomGenerator().nextInt(vti->town->getRandomNamesCount() - 1);
|
size_t nameID = getRandomGenerator().nextInt(vti->getTown()->getRandomNamesCount() - 1);
|
||||||
vti->setNameTranslated(vti->town->getRandomNameTranslated(nameID));
|
vti->setNameTranslated(vti->getTown()->getRandomNameTranslated(nameID));
|
||||||
}
|
}
|
||||||
|
|
||||||
//init buildings
|
//init buildings
|
||||||
@ -1777,14 +1778,14 @@ void CGameState::initTowns()
|
|||||||
if (vstd::contains(vti->builtBuildings, (BuildingID::HORDE_PLACEHOLDER1 - i))) //if we have horde for this level
|
if (vstd::contains(vti->builtBuildings, (BuildingID::HORDE_PLACEHOLDER1 - i))) //if we have horde for this level
|
||||||
{
|
{
|
||||||
vti->builtBuildings.erase(BuildingID(BuildingID::HORDE_PLACEHOLDER1 - i));//remove old ID
|
vti->builtBuildings.erase(BuildingID(BuildingID::HORDE_PLACEHOLDER1 - i));//remove old ID
|
||||||
if (vti->town->hordeLvl.at(0) == i)//if town first horde is this one
|
if (vti->getTown()->hordeLvl.at(0) == i)//if town first horde is this one
|
||||||
{
|
{
|
||||||
vti->builtBuildings.insert(BuildingID::HORDE_1);//add it
|
vti->builtBuildings.insert(BuildingID::HORDE_1);//add it
|
||||||
//if we have upgraded dwelling as well
|
//if we have upgraded dwelling as well
|
||||||
if (vstd::contains(vti->builtBuildings, (BuildingID::DWELL_UP_FIRST + i)))
|
if (vstd::contains(vti->builtBuildings, (BuildingID::DWELL_UP_FIRST + i)))
|
||||||
vti->builtBuildings.insert(BuildingID::HORDE_1_UPGR);//add it as well
|
vti->builtBuildings.insert(BuildingID::HORDE_1_UPGR);//add it as well
|
||||||
}
|
}
|
||||||
if (vti->town->hordeLvl.at(1) == i)//if town second horde is this one
|
if (vti->getTown()->hordeLvl.at(1) == i)//if town second horde is this one
|
||||||
{
|
{
|
||||||
vti->builtBuildings.insert(BuildingID::HORDE_2);
|
vti->builtBuildings.insert(BuildingID::HORDE_2);
|
||||||
if (vstd::contains(vti->builtBuildings, (BuildingID::DWELL_UP_FIRST + i)))
|
if (vstd::contains(vti->builtBuildings, (BuildingID::DWELL_UP_FIRST + i)))
|
||||||
@ -1797,7 +1798,7 @@ void CGameState::initTowns()
|
|||||||
//But DO NOT remove horde placeholders before they are replaced
|
//But DO NOT remove horde placeholders before they are replaced
|
||||||
vstd::erase_if(vti->builtBuildings, [vti](const BuildingID & bid)
|
vstd::erase_if(vti->builtBuildings, [vti](const BuildingID & bid)
|
||||||
{
|
{
|
||||||
return !vti->town->buildings.count(bid) || !vti->town->buildings.at(bid);
|
return !vti->getTown()->buildings.count(bid) || !vti->getTown()->buildings.at(bid);
|
||||||
});
|
});
|
||||||
|
|
||||||
if (vstd::contains(vti->builtBuildings, BuildingID::SHIPYARD) && vti->shipyardStatus()==IBoatGenerator::TILE_BLOCKED)
|
if (vstd::contains(vti->builtBuildings, BuildingID::SHIPYARD) && vti->shipyardStatus()==IBoatGenerator::TILE_BLOCKED)
|
||||||
@ -1806,7 +1807,7 @@ void CGameState::initTowns()
|
|||||||
//Early check for #1444-like problems
|
//Early check for #1444-like problems
|
||||||
for(const auto & building : vti->builtBuildings)
|
for(const auto & building : vti->builtBuildings)
|
||||||
{
|
{
|
||||||
assert(vti->town->buildings.at(building) != nullptr);
|
assert(vti->getTown()->buildings.at(building) != nullptr);
|
||||||
MAYBE_UNUSED(building);
|
MAYBE_UNUSED(building);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1817,9 +1818,9 @@ void CGameState::initTowns()
|
|||||||
if (vstd::contains(ev.buildings,(-31-i))) //if we have horde for this level
|
if (vstd::contains(ev.buildings,(-31-i))) //if we have horde for this level
|
||||||
{
|
{
|
||||||
ev.buildings.erase(BuildingID(-31-i));
|
ev.buildings.erase(BuildingID(-31-i));
|
||||||
if (vti->town->hordeLvl.at(0) == i)
|
if (vti->getTown()->hordeLvl.at(0) == i)
|
||||||
ev.buildings.insert(BuildingID::HORDE_1);
|
ev.buildings.insert(BuildingID::HORDE_1);
|
||||||
if (vti->town->hordeLvl.at(1) == i)
|
if (vti->getTown()->hordeLvl.at(1) == i)
|
||||||
ev.buildings.insert(BuildingID::HORDE_2);
|
ev.buildings.insert(BuildingID::HORDE_2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1838,7 +1839,7 @@ void CGameState::initTowns()
|
|||||||
int sel = -1;
|
int sel = -1;
|
||||||
|
|
||||||
for(ui32 ps=0;ps<vti->possibleSpells.size();ps++)
|
for(ui32 ps=0;ps<vti->possibleSpells.size();ps++)
|
||||||
total += vti->possibleSpells[ps].toSpell()->getProbability(vti->subID);
|
total += vti->possibleSpells[ps].toSpell()->getProbability(vti->getFaction());
|
||||||
|
|
||||||
if (total == 0) // remaining spells have 0 probability
|
if (total == 0) // remaining spells have 0 probability
|
||||||
break;
|
break;
|
||||||
@ -1846,7 +1847,7 @@ void CGameState::initTowns()
|
|||||||
auto r = getRandomGenerator().nextInt(total - 1);
|
auto r = getRandomGenerator().nextInt(total - 1);
|
||||||
for(ui32 ps=0; ps<vti->possibleSpells.size();ps++)
|
for(ui32 ps=0; ps<vti->possibleSpells.size();ps++)
|
||||||
{
|
{
|
||||||
r -= vti->possibleSpells[ps].toSpell()->getProbability(vti->subID);
|
r -= vti->possibleSpells[ps].toSpell()->getProbability(vti->getFaction());
|
||||||
if(r<0)
|
if(r<0)
|
||||||
{
|
{
|
||||||
sel = ps;
|
sel = ps;
|
||||||
@ -1869,7 +1870,6 @@ void CGameState::initTowns()
|
|||||||
void CGameState::initMapObjects()
|
void CGameState::initMapObjects()
|
||||||
{
|
{
|
||||||
logGlobal->debug("\tObject initialization");
|
logGlobal->debug("\tObject initialization");
|
||||||
VLC->creh->removeBonusesFromAllCreatures();
|
|
||||||
|
|
||||||
// objCaller->preInit();
|
// objCaller->preInit();
|
||||||
for(CGObjectInstance *obj : map->objects)
|
for(CGObjectInstance *obj : map->objects)
|
||||||
@ -3133,7 +3133,7 @@ void InfoAboutTown::initFromTown(const CGTownInstance *t, bool detailed)
|
|||||||
built = t->builded;
|
built = t->builded;
|
||||||
fortLevel = t->fortLevel();
|
fortLevel = t->fortLevel();
|
||||||
name = t->getNameTranslated();
|
name = t->getNameTranslated();
|
||||||
tType = t->town;
|
tType = t->getTown();
|
||||||
|
|
||||||
vstd::clear_pointer(details);
|
vstd::clear_pointer(details);
|
||||||
|
|
||||||
|
@ -289,7 +289,7 @@ CHeroClass * CHeroClassHandler::loadFromJson(const std::string & scope, const Js
|
|||||||
VLC->modh->identifiers.requestIdentifier(tavern.second.meta, "faction", tavern.first,
|
VLC->modh->identifiers.requestIdentifier(tavern.second.meta, "faction", tavern.first,
|
||||||
[=](si32 factionID)
|
[=](si32 factionID)
|
||||||
{
|
{
|
||||||
heroClass->selectionProbability[factionID] = value;
|
heroClass->selectionProbability[FactionID(factionID)] = value;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -361,11 +361,11 @@ void CHeroClassHandler::afterLoadFinalization()
|
|||||||
{
|
{
|
||||||
if (!faction->town)
|
if (!faction->town)
|
||||||
continue;
|
continue;
|
||||||
if (heroClass->selectionProbability.count(faction->getIndex()))
|
if (heroClass->selectionProbability.count(faction->getId()))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
auto chance = static_cast<float>(heroClass->defaultTavernChance * faction->town->defaultTavernChance);
|
auto chance = static_cast<float>(heroClass->defaultTavernChance * faction->town->defaultTavernChance);
|
||||||
heroClass->selectionProbability[faction->getIndex()] = static_cast<int>(sqrt(chance) + 0.5); //FIXME: replace with std::round once MVS supports it
|
heroClass->selectionProbability[faction->getId()] = static_cast<int>(sqrt(chance) + 0.5); //FIXME: replace with std::round once MVS supports it
|
||||||
}
|
}
|
||||||
// set default probabilities for gaining secondary skills where not loaded previously
|
// set default probabilities for gaining secondary skills where not loaded previously
|
||||||
heroClass->secSkillProbability.resize(VLC->skillh->size(), -1);
|
heroClass->secSkillProbability.resize(VLC->skillh->size(), -1);
|
||||||
|
@ -131,7 +131,7 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
//double aggression; // not used in vcmi.
|
//double aggression; // not used in vcmi.
|
||||||
TFaction faction;
|
FactionID faction;
|
||||||
ui8 affinity; // affinity, using EClassAffinity enum
|
ui8 affinity; // affinity, using EClassAffinity enum
|
||||||
|
|
||||||
// default chance for hero of specific class to appear in tavern, if field "tavern" was not set
|
// default chance for hero of specific class to appear in tavern, if field "tavern" was not set
|
||||||
@ -146,7 +146,7 @@ public:
|
|||||||
|
|
||||||
std::vector<int> secSkillProbability; //probabilities of gaining secondary skills (out of 112), in id order
|
std::vector<int> secSkillProbability; //probabilities of gaining secondary skills (out of 112), in id order
|
||||||
|
|
||||||
std::map<TFaction, int> selectionProbability; //probability of selection in towns
|
std::map<FactionID, int> selectionProbability; //probability of selection in towns
|
||||||
|
|
||||||
std::string imageBattleMale;
|
std::string imageBattleMale;
|
||||||
std::string imageBattleFemale;
|
std::string imageBattleFemale;
|
||||||
|
@ -1170,10 +1170,6 @@ void CModHandler::load()
|
|||||||
allMods[modName].validation = CModInfo::FAILED;
|
allMods[modName].validation = CModInfo::FAILED;
|
||||||
|
|
||||||
logMod->info("\tLoading mod data: %d ms", timer.getDiff());
|
logMod->info("\tLoading mod data: %d ms", timer.getDiff());
|
||||||
|
|
||||||
VLC->creh->loadCrExpBon();
|
|
||||||
VLC->creh->buildBonusTreeForTiers(); //do that after all new creatures are loaded
|
|
||||||
|
|
||||||
identifiers.finalize();
|
identifiers.finalize();
|
||||||
logMod->info("\tResolving identifiers: %d ms", timer.getDiff());
|
logMod->info("\tResolving identifiers: %d ms", timer.getDiff());
|
||||||
|
|
||||||
|
@ -78,7 +78,7 @@ void CStack::localInit(BattleInfo * battleInfo)
|
|||||||
attachTo(*army);
|
attachTo(*army);
|
||||||
attachTo(const_cast<CCreature&>(*type));
|
attachTo(const_cast<CCreature&>(*type));
|
||||||
}
|
}
|
||||||
nativeTerrain = type->getNativeTerrain(); //save nativeTerrain in the variable on the battle start to avoid dead lock
|
nativeTerrain = getNativeTerrain(); //save nativeTerrain in the variable on the battle start to avoid dead lock
|
||||||
CUnitState::localInit(this); //it causes execution of the CStack::isOnNativeTerrain where nativeTerrain will be considered
|
CUnitState::localInit(this); //it causes execution of the CStack::isOnNativeTerrain where nativeTerrain will be considered
|
||||||
position = initialPosition;
|
position = initialPosition;
|
||||||
}
|
}
|
||||||
@ -338,6 +338,11 @@ int32_t CStack::unitBaseAmount() const
|
|||||||
return baseAmount;
|
return baseAmount;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const IBonusBearer* CStack::getBonusBearer() const
|
||||||
|
{
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
bool CStack::unitHasAmmoCart(const battle::Unit * unit) const
|
bool CStack::unitHasAmmoCart(const battle::Unit * unit) const
|
||||||
{
|
{
|
||||||
for(const CStack * st : battle->stacks)
|
for(const CStack * st : battle->stacks)
|
||||||
|
@ -84,6 +84,8 @@ public:
|
|||||||
|
|
||||||
void spendMana(ServerCallback * server, const int spellCost) const override;
|
void spendMana(ServerCallback * server, const int spellCost) const override;
|
||||||
|
|
||||||
|
const IBonusBearer* getBonusBearer() const override;
|
||||||
|
|
||||||
PlayerColor getOwner() const override
|
PlayerColor getOwner() const override
|
||||||
{
|
{
|
||||||
return this->owner;
|
return this->owner;
|
||||||
|
@ -157,6 +157,11 @@ FactionID CFaction::getId() const
|
|||||||
return FactionID(index);
|
return FactionID(index);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FactionID CFaction::getFaction() const
|
||||||
|
{
|
||||||
|
return FactionID(index);
|
||||||
|
}
|
||||||
|
|
||||||
bool CFaction::hasTown() const
|
bool CFaction::hasTown() const
|
||||||
{
|
{
|
||||||
return town != nullptr;
|
return town != nullptr;
|
||||||
@ -562,13 +567,7 @@ void CTownHandler::loadSpecialBuildingBonuses(const JsonNode & source, BonusList
|
|||||||
if(bonus == nullptr)
|
if(bonus == nullptr)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if(bonus->limiter != nullptr)
|
bonus->sid = Bonus::getSid32(building->town->faction->getIndex(), building->bid);
|
||||||
{
|
|
||||||
auto * limPtr = dynamic_cast<CreatureFactionLimiter *>(bonus->limiter.get());
|
|
||||||
|
|
||||||
if(limPtr != nullptr && limPtr->faction == static_cast<TFaction>(-1))
|
|
||||||
limPtr->faction = building->town->faction->getIndex();
|
|
||||||
}
|
|
||||||
//JsonUtils::parseBuildingBonus produces UNKNOWN type propagator instead of empty.
|
//JsonUtils::parseBuildingBonus produces UNKNOWN type propagator instead of empty.
|
||||||
if(bonus->propagator != nullptr
|
if(bonus->propagator != nullptr
|
||||||
&& bonus->propagator->getPropagatorType() == CBonusSystemNode::ENodeTypes::UNKNOWN)
|
&& bonus->propagator->getPropagatorType() == CBonusSystemNode::ENodeTypes::UNKNOWN)
|
||||||
@ -947,7 +946,7 @@ void CTownHandler::loadTown(CTown * town, const JsonNode & source)
|
|||||||
|
|
||||||
VLC->modh->identifiers.requestIdentifier(node.second.meta, "heroClass",node.first, [=](si32 classID)
|
VLC->modh->identifiers.requestIdentifier(node.second.meta, "heroClass",node.first, [=](si32 classID)
|
||||||
{
|
{
|
||||||
VLC->heroh->classes[HeroClassID(classID)]->selectionProbability[town->faction->getIndex()] = chance;
|
VLC->heroh->classes[HeroClassID(classID)]->selectionProbability[town->faction->getId()] = chance;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -957,7 +956,7 @@ void CTownHandler::loadTown(CTown * town, const JsonNode & source)
|
|||||||
|
|
||||||
VLC->modh->identifiers.requestIdentifier(node.second.meta, "spell", node.first, [=](si32 spellID)
|
VLC->modh->identifiers.requestIdentifier(node.second.meta, "spell", node.first, [=](si32 spellID)
|
||||||
{
|
{
|
||||||
VLC->spellh->objects.at(spellID)->probabilities[town->faction->getIndex()] = chance;
|
VLC->spellh->objects.at(spellID)->probabilities[town->faction->getId()] = chance;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1003,7 +1002,7 @@ CFaction * CTownHandler::loadFromJson(const std::string & scope, const JsonNode
|
|||||||
|
|
||||||
auto * faction = new CFaction();
|
auto * faction = new CFaction();
|
||||||
|
|
||||||
faction->index = static_cast<TFaction>(index);
|
faction->index = static_cast<FactionID>(index);
|
||||||
faction->modScope = scope;
|
faction->modScope = scope;
|
||||||
faction->identifier = identifier;
|
faction->identifier = identifier;
|
||||||
|
|
||||||
@ -1206,9 +1205,9 @@ std::vector<bool> CTownHandler::getDefaultAllowed() const
|
|||||||
return allowedFactions;
|
return allowedFactions;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::set<TFaction> CTownHandler::getAllowedFactions(bool withTown) const
|
std::set<FactionID> CTownHandler::getAllowedFactions(bool withTown) const
|
||||||
{
|
{
|
||||||
std::set<TFaction> allowedFactions;
|
std::set<FactionID> allowedFactions;
|
||||||
std::vector<bool> allowed;
|
std::vector<bool> allowed;
|
||||||
if (withTown)
|
if (withTown)
|
||||||
allowed = getDefaultAllowed();
|
allowed = getDefaultAllowed();
|
||||||
@ -1217,7 +1216,7 @@ std::set<TFaction> CTownHandler::getAllowedFactions(bool withTown) const
|
|||||||
|
|
||||||
for (size_t i=0; i<allowed.size(); i++)
|
for (size_t i=0; i<allowed.size(); i++)
|
||||||
if (allowed[i])
|
if (allowed[i])
|
||||||
allowedFactions.insert(static_cast<TFaction>(i));
|
allowedFactions.insert(static_cast<FactionID>(i));
|
||||||
|
|
||||||
return allowedFactions;
|
return allowedFactions;
|
||||||
}
|
}
|
||||||
|
@ -190,7 +190,9 @@ class DLL_LINKAGE CFaction : public Faction
|
|||||||
std::string modScope;
|
std::string modScope;
|
||||||
std::string identifier;
|
std::string identifier;
|
||||||
|
|
||||||
TFaction index = 0;
|
FactionID index = FactionID::NEUTRAL;
|
||||||
|
|
||||||
|
FactionID getFaction() const override; //This function should not be used
|
||||||
|
|
||||||
public:
|
public:
|
||||||
TerrainId nativeTerrain;
|
TerrainId nativeTerrain;
|
||||||
@ -421,7 +423,7 @@ public:
|
|||||||
void afterLoadFinalization() override;
|
void afterLoadFinalization() override;
|
||||||
|
|
||||||
std::vector<bool> getDefaultAllowed() const override;
|
std::vector<bool> getDefaultAllowed() const override;
|
||||||
std::set<TFaction> getAllowedFactions(bool withTown = true) const;
|
std::set<FactionID> getAllowedFactions(bool withTown = true) const;
|
||||||
|
|
||||||
static void loadSpecialBuildingBonuses(const JsonNode & source, BonusList & bonusList, CBuilding * building);
|
static void loadSpecialBuildingBonuses(const JsonNode & source, BonusList & bonusList, CBuilding * building);
|
||||||
|
|
||||||
|
@ -187,7 +187,8 @@ std::string PlayerColor::getStrCap(bool L10n) const
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
const FactionID FactionID::ANY = FactionID(-1);
|
const FactionID FactionID::NONE = FactionID(-2);
|
||||||
|
const FactionID FactionID::DEFAULT = FactionID(-1);
|
||||||
const FactionID FactionID::CASTLE = FactionID(0);
|
const FactionID FactionID::CASTLE = FactionID(0);
|
||||||
const FactionID FactionID::RAMPART = FactionID(1);
|
const FactionID FactionID::RAMPART = FactionID(1);
|
||||||
const FactionID FactionID::TOWER = FactionID(2);
|
const FactionID FactionID::TOWER = FactionID(2);
|
||||||
@ -205,7 +206,7 @@ si32 FactionID::decode(const std::string & identifier)
|
|||||||
if(rawId)
|
if(rawId)
|
||||||
return rawId.get();
|
return rawId.get();
|
||||||
else
|
else
|
||||||
return -1;
|
return FactionID::DEFAULT;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string FactionID::encode(const si32 index)
|
std::string FactionID::encode(const si32 index)
|
||||||
|
@ -442,7 +442,8 @@ class FactionID : public BaseForID<FactionID, int32_t>
|
|||||||
{
|
{
|
||||||
INSTID_LIKE_CLASS_COMMON(FactionID, si32)
|
INSTID_LIKE_CLASS_COMMON(FactionID, si32)
|
||||||
|
|
||||||
DLL_LINKAGE static const FactionID ANY;
|
DLL_LINKAGE static const FactionID NONE;
|
||||||
|
DLL_LINKAGE static const FactionID DEFAULT;
|
||||||
DLL_LINKAGE static const FactionID CASTLE;
|
DLL_LINKAGE static const FactionID CASTLE;
|
||||||
DLL_LINKAGE static const FactionID RAMPART;
|
DLL_LINKAGE static const FactionID RAMPART;
|
||||||
DLL_LINKAGE static const FactionID TOWER;
|
DLL_LINKAGE static const FactionID TOWER;
|
||||||
@ -1313,7 +1314,6 @@ enum class EHealPower : ui8
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Typedef declarations
|
// Typedef declarations
|
||||||
typedef ui8 TFaction;
|
|
||||||
typedef si64 TExpType;
|
typedef si64 TExpType;
|
||||||
typedef si32 TBonusSubtype;
|
typedef si32 TBonusSubtype;
|
||||||
typedef si32 TQuantity;
|
typedef si32 TQuantity;
|
||||||
|
@ -75,9 +75,10 @@ const std::map<std::string, TLimiterPtr> bonusLimiterMap =
|
|||||||
{"DRAGON_NATURE", std::make_shared<HasAnotherBonusLimiter>(Bonus::DRAGON_NATURE)},
|
{"DRAGON_NATURE", std::make_shared<HasAnotherBonusLimiter>(Bonus::DRAGON_NATURE)},
|
||||||
{"IS_UNDEAD", std::make_shared<HasAnotherBonusLimiter>(Bonus::UNDEAD)},
|
{"IS_UNDEAD", std::make_shared<HasAnotherBonusLimiter>(Bonus::UNDEAD)},
|
||||||
{"CREATURE_NATIVE_TERRAIN", std::make_shared<CreatureTerrainLimiter>()},
|
{"CREATURE_NATIVE_TERRAIN", std::make_shared<CreatureTerrainLimiter>()},
|
||||||
{"CREATURE_FACTION", std::make_shared<CreatureFactionLimiter>()},
|
{"CREATURE_FACTION", std::make_shared<AllOfLimiter>(std::initializer_list<TLimiterPtr>{std::make_shared<CreatureLevelLimiter>(), std::make_shared<FactionLimiter>()})},
|
||||||
|
{"SAME_FACTION", std::make_shared<FactionLimiter>()},
|
||||||
|
{"CREATURES_ONLY", std::make_shared<CreatureLevelLimiter>()},
|
||||||
{"OPPOSITE_SIDE", std::make_shared<OppositeSideLimiter>()},
|
{"OPPOSITE_SIDE", std::make_shared<OppositeSideLimiter>()},
|
||||||
{"UNIT_ON_HEXES", std::make_shared<UnitOnHexLimiter>()}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const std::map<std::string, TPropagatorPtr> bonusPropagatorMap =
|
const std::map<std::string, TPropagatorPtr> bonusPropagatorMap =
|
||||||
@ -87,8 +88,7 @@ const std::map<std::string, TPropagatorPtr> bonusPropagatorMap =
|
|||||||
{"PLAYER_PROPAGATOR", std::make_shared<CPropagatorNodeType>(CBonusSystemNode::PLAYER)},
|
{"PLAYER_PROPAGATOR", std::make_shared<CPropagatorNodeType>(CBonusSystemNode::PLAYER)},
|
||||||
{"HERO", std::make_shared<CPropagatorNodeType>(CBonusSystemNode::HERO)},
|
{"HERO", std::make_shared<CPropagatorNodeType>(CBonusSystemNode::HERO)},
|
||||||
{"TEAM_PROPAGATOR", std::make_shared<CPropagatorNodeType>(CBonusSystemNode::TEAM)}, //untested
|
{"TEAM_PROPAGATOR", std::make_shared<CPropagatorNodeType>(CBonusSystemNode::TEAM)}, //untested
|
||||||
{"GLOBAL_EFFECT", std::make_shared<CPropagatorNodeType>(CBonusSystemNode::GLOBAL_EFFECTS)},
|
{"GLOBAL_EFFECT", std::make_shared<CPropagatorNodeType>(CBonusSystemNode::GLOBAL_EFFECTS)}
|
||||||
{"ALL_CREATURES", std::make_shared<CPropagatorNodeType>(CBonusSystemNode::ALL_CREATURES)}
|
|
||||||
}; //untested
|
}; //untested
|
||||||
|
|
||||||
const std::map<std::string, TUpdaterPtr> bonusUpdaterMap =
|
const std::map<std::string, TUpdaterPtr> bonusUpdaterMap =
|
||||||
@ -2301,12 +2301,6 @@ CBonusSystemNode::ENodeTypes IPropagator::getPropagatorType() const
|
|||||||
return CBonusSystemNode::ENodeTypes::NONE;
|
return CBonusSystemNode::ENodeTypes::NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
CPropagatorNodeType::CPropagatorNodeType()
|
|
||||||
:nodeType(CBonusSystemNode::ENodeTypes::UNKNOWN)
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
CPropagatorNodeType::CPropagatorNodeType(CBonusSystemNode::ENodeTypes NodeType)
|
CPropagatorNodeType::CPropagatorNodeType(CBonusSystemNode::ENodeTypes NodeType)
|
||||||
: nodeType(NodeType)
|
: nodeType(NodeType)
|
||||||
{
|
{
|
||||||
@ -2367,40 +2361,82 @@ JsonNode CreatureTerrainLimiter::toJsonNode() const
|
|||||||
return root;
|
return root;
|
||||||
}
|
}
|
||||||
|
|
||||||
CreatureFactionLimiter::CreatureFactionLimiter(TFaction creatureFaction)
|
FactionLimiter::FactionLimiter(FactionID creatureFaction)
|
||||||
: faction(creatureFaction)
|
: faction(creatureFaction)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
CreatureFactionLimiter::CreatureFactionLimiter():
|
ILimiter::EDecision FactionLimiter::limit(const BonusLimitationContext &context) const
|
||||||
faction(static_cast<TFaction>(-1))
|
|
||||||
{
|
{
|
||||||
|
const auto * bearer = dynamic_cast<const INativeTerrainProvider*>(&context.node);
|
||||||
|
|
||||||
|
if(bearer)
|
||||||
|
{
|
||||||
|
if(faction != FactionID::DEFAULT)
|
||||||
|
return bearer->getFaction() == faction ? ILimiter::EDecision::ACCEPT : ILimiter::EDecision::DISCARD;
|
||||||
|
|
||||||
|
switch(context.b->source)
|
||||||
|
{
|
||||||
|
case Bonus::CREATURE_ABILITY:
|
||||||
|
return faction == CreatureID(context.b->sid).toCreature()->getFaction() ? ILimiter::EDecision::ACCEPT : ILimiter::EDecision::DISCARD;
|
||||||
|
|
||||||
|
case Bonus::TOWN_STRUCTURE:
|
||||||
|
return faction == FactionID(Bonus::getHighFromSid32(context.b->sid)) ? ILimiter::EDecision::ACCEPT : ILimiter::EDecision::DISCARD;
|
||||||
|
|
||||||
|
//TODO: other sources of bonuses
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ILimiter::EDecision::DISCARD; //Discard by default
|
||||||
}
|
}
|
||||||
|
|
||||||
ILimiter::EDecision CreatureFactionLimiter::limit(const BonusLimitationContext &context) const
|
std::string FactionLimiter::toString() const
|
||||||
{
|
{
|
||||||
const CCreature *c = retrieveCreature(&context.node);
|
boost::format fmt("FactionLimiter(faction=%s)");
|
||||||
auto accept = c && c->getFactionIndex() == faction;
|
|
||||||
return accept ? ILimiter::EDecision::ACCEPT : ILimiter::EDecision::DISCARD; //drop bonus for non-creatures or non-native residents
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string CreatureFactionLimiter::toString() const
|
|
||||||
{
|
|
||||||
boost::format fmt("CreatureFactionLimiter(faction=%s)");
|
|
||||||
fmt % VLC->factions()->getByIndex(faction)->getJsonKey();
|
fmt % VLC->factions()->getByIndex(faction)->getJsonKey();
|
||||||
return fmt.str();
|
return fmt.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
JsonNode CreatureFactionLimiter::toJsonNode() const
|
JsonNode FactionLimiter::toJsonNode() const
|
||||||
{
|
{
|
||||||
JsonNode root(JsonNode::JsonType::DATA_STRUCT);
|
JsonNode root(JsonNode::JsonType::DATA_STRUCT);
|
||||||
|
|
||||||
root["type"].String() = "CREATURE_FACTION_LIMITER";
|
root["type"].String() = "FACTION_LIMITER";
|
||||||
root["parameters"].Vector().push_back(JsonUtils::stringNode(VLC->factions()->getByIndex(faction)->getJsonKey()));
|
root["parameters"].Vector().push_back(JsonUtils::stringNode(VLC->factions()->getByIndex(faction)->getJsonKey()));
|
||||||
|
|
||||||
return root;
|
return root;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CreatureLevelLimiter::CreatureLevelLimiter(uint32_t minLevel, uint32_t maxLevel) :
|
||||||
|
minLevel(minLevel),
|
||||||
|
maxLevel(maxLevel)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
ILimiter::EDecision CreatureLevelLimiter::limit(const BonusLimitationContext &context) const
|
||||||
|
{
|
||||||
|
const auto *c = retrieveCreature(&context.node);
|
||||||
|
auto accept = c && (c->getLevel() < maxLevel && c->getLevel() >= minLevel);
|
||||||
|
return accept ? ILimiter::EDecision::ACCEPT : ILimiter::EDecision::DISCARD; //drop bonus for non-creatures or non-native residents
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string CreatureLevelLimiter::toString() const
|
||||||
|
{
|
||||||
|
boost::format fmt("CreatureLevelLimiter(minLevel=%d,maxLevel=%d)");
|
||||||
|
fmt % minLevel % maxLevel;
|
||||||
|
return fmt.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
JsonNode CreatureLevelLimiter::toJsonNode() const
|
||||||
|
{
|
||||||
|
JsonNode root(JsonNode::JsonType::DATA_STRUCT);
|
||||||
|
|
||||||
|
root["type"].String() = "CREATURE_LEVEL_LIMITER";
|
||||||
|
root["parameters"].Vector().push_back(JsonUtils::intNode(minLevel));
|
||||||
|
root["parameters"].Vector().push_back(JsonUtils::intNode(maxLevel));
|
||||||
|
|
||||||
|
return root;
|
||||||
|
}
|
||||||
|
|
||||||
CreatureAlignmentLimiter::CreatureAlignmentLimiter(EAlignment Alignment)
|
CreatureAlignmentLimiter::CreatureAlignmentLimiter(EAlignment Alignment)
|
||||||
: alignment(Alignment)
|
: alignment(Alignment)
|
||||||
{
|
{
|
||||||
@ -2461,35 +2497,8 @@ ILimiter::EDecision RankRangeLimiter::limit(const BonusLimitationContext &contex
|
|||||||
return ILimiter::EDecision::DISCARD;
|
return ILimiter::EDecision::DISCARD;
|
||||||
}
|
}
|
||||||
|
|
||||||
ILimiter::EDecision StackOwnerLimiter::limit(const BonusLimitationContext &context) const
|
OppositeSideLimiter::OppositeSideLimiter(PlayerColor Owner):
|
||||||
{
|
owner(std::move(Owner))
|
||||||
const CStack * s = retrieveStackBattle(&context.node);
|
|
||||||
if(s && s->owner == owner)
|
|
||||||
return ILimiter::EDecision::ACCEPT;
|
|
||||||
|
|
||||||
const CStackInstance * csi = retrieveStackInstance(&context.node);
|
|
||||||
if(csi && csi->armyObj && csi->armyObj->tempOwner == owner)
|
|
||||||
return ILimiter::EDecision::ACCEPT;
|
|
||||||
return ILimiter::EDecision::DISCARD;
|
|
||||||
}
|
|
||||||
|
|
||||||
StackOwnerLimiter::StackOwnerLimiter()
|
|
||||||
: owner(-1)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
StackOwnerLimiter::StackOwnerLimiter(const PlayerColor & Owner):
|
|
||||||
owner(Owner)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
OppositeSideLimiter::OppositeSideLimiter():
|
|
||||||
owner(PlayerColor::CANNOT_DETERMINE)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
OppositeSideLimiter::OppositeSideLimiter(const PlayerColor & Owner):
|
|
||||||
owner(Owner)
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2502,6 +2511,11 @@ ILimiter::EDecision OppositeSideLimiter::limit(const BonusLimitationContext & co
|
|||||||
|
|
||||||
// Aggregate/Boolean Limiters
|
// Aggregate/Boolean Limiters
|
||||||
|
|
||||||
|
AggregateLimiter::AggregateLimiter(std::vector<TLimiterPtr> limiters):
|
||||||
|
limiters(std::move(limiters))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
void AggregateLimiter::add(const TLimiterPtr & limiter)
|
void AggregateLimiter::add(const TLimiterPtr & limiter)
|
||||||
{
|
{
|
||||||
if(limiter)
|
if(limiter)
|
||||||
@ -2523,6 +2537,11 @@ const std::string & AllOfLimiter::getAggregator() const
|
|||||||
return aggregator;
|
return aggregator;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
AllOfLimiter::AllOfLimiter(std::vector<TLimiterPtr> limiters):
|
||||||
|
AggregateLimiter(limiters)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
ILimiter::EDecision AllOfLimiter::limit(const BonusLimitationContext & context) const
|
ILimiter::EDecision AllOfLimiter::limit(const BonusLimitationContext & context) const
|
||||||
{
|
{
|
||||||
bool wasntSure = false;
|
bool wasntSure = false;
|
||||||
@ -2545,6 +2564,11 @@ const std::string & AnyOfLimiter::getAggregator() const
|
|||||||
return aggregator;
|
return aggregator;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
AnyOfLimiter::AnyOfLimiter(std::vector<TLimiterPtr> limiters):
|
||||||
|
AggregateLimiter(limiters)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
ILimiter::EDecision AnyOfLimiter::limit(const BonusLimitationContext & context) const
|
ILimiter::EDecision AnyOfLimiter::limit(const BonusLimitationContext & context) const
|
||||||
{
|
{
|
||||||
bool wasntSure = false;
|
bool wasntSure = false;
|
||||||
@ -2567,6 +2591,11 @@ const std::string & NoneOfLimiter::getAggregator() const
|
|||||||
return aggregator;
|
return aggregator;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NoneOfLimiter::NoneOfLimiter(std::vector<TLimiterPtr> limiters):
|
||||||
|
AggregateLimiter(limiters)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
ILimiter::EDecision NoneOfLimiter::limit(const BonusLimitationContext & context) const
|
ILimiter::EDecision NoneOfLimiter::limit(const BonusLimitationContext & context) const
|
||||||
{
|
{
|
||||||
bool wasntSure = false;
|
bool wasntSure = false;
|
||||||
|
@ -12,6 +12,7 @@
|
|||||||
#include "GameConstants.h"
|
#include "GameConstants.h"
|
||||||
#include "JsonNode.h"
|
#include "JsonNode.h"
|
||||||
#include "battle/BattleHex.h"
|
#include "battle/BattleHex.h"
|
||||||
|
#include <limits>
|
||||||
|
|
||||||
VCMI_LIB_NAMESPACE_BEGIN
|
VCMI_LIB_NAMESPACE_BEGIN
|
||||||
|
|
||||||
@ -522,6 +523,16 @@ struct DLL_LINKAGE Bonus : public std::enable_shared_from_this<Bonus>
|
|||||||
return (high << 16) + low;
|
return (high << 16) + low;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
STRONG_INLINE static ui32 getHighFromSid32(ui32 sid)
|
||||||
|
{
|
||||||
|
return sid >> 16;
|
||||||
|
}
|
||||||
|
|
||||||
|
STRONG_INLINE static ui32 getLowFromSid32(ui32 sid)
|
||||||
|
{
|
||||||
|
return sid & 0x0000FFFF;
|
||||||
|
}
|
||||||
|
|
||||||
std::string Description(boost::optional<si32> customValue = {}) const;
|
std::string Description(boost::optional<si32> customValue = {}) const;
|
||||||
JsonNode toJsonNode() const;
|
JsonNode toJsonNode() const;
|
||||||
std::string nameForBonus() const; // generate suitable name for bonus - e.g. for storing in json struct
|
std::string nameForBonus() const; // generate suitable name for bonus - e.g. for storing in json struct
|
||||||
@ -894,8 +905,7 @@ class DLL_LINKAGE CPropagatorNodeType : public IPropagator
|
|||||||
CBonusSystemNode::ENodeTypes nodeType;
|
CBonusSystemNode::ENodeTypes nodeType;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
CPropagatorNodeType();
|
CPropagatorNodeType(CBonusSystemNode::ENodeTypes NodeType = CBonusSystemNode::ENodeTypes::UNKNOWN);
|
||||||
CPropagatorNodeType(CBonusSystemNode::ENodeTypes NodeType);
|
|
||||||
bool shouldBeAttached(CBonusSystemNode *dest) override;
|
bool shouldBeAttached(CBonusSystemNode *dest) override;
|
||||||
CBonusSystemNode::ENodeTypes getPropagatorType() const override;
|
CBonusSystemNode::ENodeTypes getPropagatorType() const override;
|
||||||
|
|
||||||
@ -995,6 +1005,7 @@ class DLL_LINKAGE AggregateLimiter : public ILimiter
|
|||||||
protected:
|
protected:
|
||||||
std::vector<TLimiterPtr> limiters;
|
std::vector<TLimiterPtr> limiters;
|
||||||
virtual const std::string & getAggregator() const = 0;
|
virtual const std::string & getAggregator() const = 0;
|
||||||
|
AggregateLimiter(std::vector<TLimiterPtr> limiters = {});
|
||||||
public:
|
public:
|
||||||
void add(const TLimiterPtr & limiter);
|
void add(const TLimiterPtr & limiter);
|
||||||
JsonNode toJsonNode() const override;
|
JsonNode toJsonNode() const override;
|
||||||
@ -1011,6 +1022,7 @@ class DLL_LINKAGE AllOfLimiter : public AggregateLimiter
|
|||||||
protected:
|
protected:
|
||||||
const std::string & getAggregator() const override;
|
const std::string & getAggregator() const override;
|
||||||
public:
|
public:
|
||||||
|
AllOfLimiter(std::vector<TLimiterPtr> limiters = {});
|
||||||
static const std::string aggregator;
|
static const std::string aggregator;
|
||||||
EDecision limit(const BonusLimitationContext & context) const override;
|
EDecision limit(const BonusLimitationContext & context) const override;
|
||||||
};
|
};
|
||||||
@ -1020,6 +1032,7 @@ class DLL_LINKAGE AnyOfLimiter : public AggregateLimiter
|
|||||||
protected:
|
protected:
|
||||||
const std::string & getAggregator() const override;
|
const std::string & getAggregator() const override;
|
||||||
public:
|
public:
|
||||||
|
AnyOfLimiter(std::vector<TLimiterPtr> limiters = {});
|
||||||
static const std::string aggregator;
|
static const std::string aggregator;
|
||||||
EDecision limit(const BonusLimitationContext & context) const override;
|
EDecision limit(const BonusLimitationContext & context) const override;
|
||||||
};
|
};
|
||||||
@ -1029,6 +1042,7 @@ class DLL_LINKAGE NoneOfLimiter : public AggregateLimiter
|
|||||||
protected:
|
protected:
|
||||||
const std::string & getAggregator() const override;
|
const std::string & getAggregator() const override;
|
||||||
public:
|
public:
|
||||||
|
NoneOfLimiter(std::vector<TLimiterPtr> limiters = {});
|
||||||
static const std::string aggregator;
|
static const std::string aggregator;
|
||||||
EDecision limit(const BonusLimitationContext & context) const override;
|
EDecision limit(const BonusLimitationContext & context) const override;
|
||||||
};
|
};
|
||||||
@ -1106,12 +1120,31 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class DLL_LINKAGE CreatureFactionLimiter : public ILimiter //applies only to creatures of given faction
|
class DLL_LINKAGE CreatureLevelLimiter : public ILimiter //applies only to creatures of given faction
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
TFaction faction;
|
uint32_t minLevel;
|
||||||
CreatureFactionLimiter();
|
uint32_t maxLevel;
|
||||||
CreatureFactionLimiter(TFaction faction);
|
//accept all levels by default, accept creatures of minLevel <= creature->getLevel() < maxLevel
|
||||||
|
CreatureLevelLimiter(uint32_t minLevel = std::numeric_limits<uint32_t>::min(), uint32_t maxLevel = std::numeric_limits<uint32_t>::max());
|
||||||
|
|
||||||
|
EDecision limit(const BonusLimitationContext &context) const override;
|
||||||
|
std::string toString() const override;
|
||||||
|
JsonNode toJsonNode() const override;
|
||||||
|
|
||||||
|
template <typename Handler> void serialize(Handler &h, const int version)
|
||||||
|
{
|
||||||
|
h & static_cast<ILimiter&>(*this);
|
||||||
|
h & minLevel;
|
||||||
|
h & maxLevel;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class DLL_LINKAGE FactionLimiter : public ILimiter //applies only to creatures of given faction
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
FactionID faction;
|
||||||
|
FactionLimiter(FactionID faction = FactionID::DEFAULT);
|
||||||
|
|
||||||
EDecision limit(const BonusLimitationContext &context) const override;
|
EDecision limit(const BonusLimitationContext &context) const override;
|
||||||
std::string toString() const override;
|
std::string toString() const override;
|
||||||
@ -1141,28 +1174,11 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class DLL_LINKAGE StackOwnerLimiter : public ILimiter //applies only to creatures of given alignment
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
PlayerColor owner;
|
|
||||||
StackOwnerLimiter();
|
|
||||||
StackOwnerLimiter(const PlayerColor & Owner);
|
|
||||||
|
|
||||||
EDecision limit(const BonusLimitationContext &context) const override;
|
|
||||||
|
|
||||||
template <typename Handler> void serialize(Handler &h, const int version)
|
|
||||||
{
|
|
||||||
h & static_cast<ILimiter&>(*this);
|
|
||||||
h & owner;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
class DLL_LINKAGE OppositeSideLimiter : public ILimiter //applies only to creatures of enemy army during combat
|
class DLL_LINKAGE OppositeSideLimiter : public ILimiter //applies only to creatures of enemy army during combat
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
PlayerColor owner;
|
PlayerColor owner;
|
||||||
OppositeSideLimiter();
|
OppositeSideLimiter(PlayerColor Owner = PlayerColor::CANNOT_DETERMINE);
|
||||||
OppositeSideLimiter(const PlayerColor & Owner);
|
|
||||||
|
|
||||||
EDecision limit(const BonusLimitationContext &context) const override;
|
EDecision limit(const BonusLimitationContext &context) const override;
|
||||||
|
|
||||||
|
@ -749,15 +749,26 @@ std::shared_ptr<ILimiter> JsonUtils::parseLimiter(const JsonNode & limiter)
|
|||||||
else
|
else
|
||||||
return std::make_shared<CreatureAlignmentLimiter>(static_cast<EAlignment>(alignment));
|
return std::make_shared<CreatureAlignmentLimiter>(static_cast<EAlignment>(alignment));
|
||||||
}
|
}
|
||||||
else if(limiterType == "CREATURE_FACTION_LIMITER")
|
else if(limiterType == "FACTION_LIMITER")
|
||||||
{
|
{
|
||||||
std::shared_ptr<CreatureFactionLimiter> factionLimiter = std::make_shared<CreatureFactionLimiter>();
|
std::shared_ptr<FactionLimiter> factionLimiter = std::make_shared<FactionLimiter>();
|
||||||
VLC->modh->identifiers.requestIdentifier("faction", parameters[0], [=](si32 faction)
|
VLC->modh->identifiers.requestIdentifier("faction", parameters[0], [=](si32 faction)
|
||||||
{
|
{
|
||||||
factionLimiter->faction = faction;
|
factionLimiter->faction = FactionID(faction);
|
||||||
});
|
});
|
||||||
return factionLimiter;
|
return factionLimiter;
|
||||||
}
|
}
|
||||||
|
else if(limiterType == "CREATURE_LEVEL_LIMITER")
|
||||||
|
{
|
||||||
|
auto levelLimiter = std::make_shared<CreatureLevelLimiter>();
|
||||||
|
if(!parameters.empty()) //If parameters is empty, level limiter works as CREATURES_ONLY limiter
|
||||||
|
{
|
||||||
|
levelLimiter->minLevel = parameters[0].Integer();
|
||||||
|
if(parameters[1].isNumber())
|
||||||
|
levelLimiter->maxLevel = parameters[1].Integer();
|
||||||
|
}
|
||||||
|
return levelLimiter;
|
||||||
|
}
|
||||||
else if(limiterType == "CREATURE_TERRAIN_LIMITER")
|
else if(limiterType == "CREATURE_TERRAIN_LIMITER")
|
||||||
{
|
{
|
||||||
std::shared_ptr<CreatureTerrainLimiter> terrainLimiter = std::make_shared<CreatureTerrainLimiter>();
|
std::shared_ptr<CreatureTerrainLimiter> terrainLimiter = std::make_shared<CreatureTerrainLimiter>();
|
||||||
@ -991,7 +1002,17 @@ bool JsonUtils::parseBonus(const JsonNode &ability, Bonus *b)
|
|||||||
|
|
||||||
value = &ability["propagator"];
|
value = &ability["propagator"];
|
||||||
if (!value->isNull())
|
if (!value->isNull())
|
||||||
b->propagator = parseByMap(bonusPropagatorMap, value, "propagator type ");
|
{
|
||||||
|
//ALL_CREATURES old propagator compatibility
|
||||||
|
if(value->String() == "ALL_CREATURES")
|
||||||
|
{
|
||||||
|
logMod->warn("ALL_CREATURES propagator is deprecated. Use GLOBAL_EFFECT propagator with CREATURES_ONLY limiter");
|
||||||
|
b->addLimiter(std::make_shared<CreatureLevelLimiter>());
|
||||||
|
b->propagator = bonusPropagatorMap.at("GLOBAL_EFFECT");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
b->propagator = parseByMap(bonusPropagatorMap, value, "propagator type ");
|
||||||
|
}
|
||||||
|
|
||||||
value = &ability["updater"];
|
value = &ability["updater"];
|
||||||
if(!value->isNull())
|
if(!value->isNull())
|
||||||
|
@ -85,9 +85,9 @@ bool CBattleInfoEssentials::battleHasNativeStack(ui8 side) const
|
|||||||
{
|
{
|
||||||
RETURN_IF_NOT_BATTLE(false);
|
RETURN_IF_NOT_BATTLE(false);
|
||||||
|
|
||||||
for(const CStack * s : battleGetAllStacks())
|
for(const auto * s : battleGetAllStacks())
|
||||||
{
|
{
|
||||||
if(s->side == side && s->getCreature()->isItNativeTerrain(getBattle()->getTerrainType()))
|
if(s->side == side && s->isNativeTerrain(getBattle()->getTerrainType()))
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -413,6 +413,11 @@ int32_t CUnitState::creatureIconIndex() const
|
|||||||
return unitType()->getIconIndex();
|
return unitType()->getIconIndex();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FactionID CUnitState::getFaction() const
|
||||||
|
{
|
||||||
|
return unitType()->getFaction();
|
||||||
|
}
|
||||||
|
|
||||||
int32_t CUnitState::getCasterUnitId() const
|
int32_t CUnitState::getCasterUnitId() const
|
||||||
{
|
{
|
||||||
return static_cast<int32_t>(unitId());
|
return static_cast<int32_t>(unitId());
|
||||||
|
@ -248,6 +248,8 @@ public:
|
|||||||
void localInit(const IUnitEnvironment * env_);
|
void localInit(const IUnitEnvironment * env_);
|
||||||
void serializeJson(JsonSerializeFormat & handler);
|
void serializeJson(JsonSerializeFormat & handler);
|
||||||
|
|
||||||
|
FactionID getFaction() const override;
|
||||||
|
|
||||||
void afterAttack(bool ranged, bool counter);
|
void afterAttack(bool ranged, bool counter);
|
||||||
|
|
||||||
void afterNewRound();
|
void afterNewRound();
|
||||||
|
@ -47,7 +47,7 @@ namespace scripting
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
class DLL_LINKAGE IBattleInfoCallback : public WithBonuses
|
class DLL_LINKAGE IBattleInfoCallback : public IConstBonusProvider
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
#if SCRIPTING_ENABLED
|
#if SCRIPTING_ENABLED
|
||||||
|
@ -30,7 +30,7 @@ namespace battle
|
|||||||
class UnitInfo;
|
class UnitInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
class DLL_LINKAGE IBattleInfo : public WithBonuses
|
class DLL_LINKAGE IBattleInfo : public IConstBonusProvider
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
using ObstacleCList = std::vector<std::shared_ptr<const CObstacleInstance>>;
|
using ObstacleCList = std::vector<std::shared_ptr<const CObstacleInstance>>;
|
||||||
|
@ -18,6 +18,9 @@
|
|||||||
#include "../serializer/JsonDeserializer.h"
|
#include "../serializer/JsonDeserializer.h"
|
||||||
#include "../serializer/JsonSerializer.h"
|
#include "../serializer/JsonSerializer.h"
|
||||||
|
|
||||||
|
#include <vcmi/Faction.h>
|
||||||
|
#include <vcmi/FactionService.h>
|
||||||
|
|
||||||
VCMI_LIB_NAMESPACE_BEGIN
|
VCMI_LIB_NAMESPACE_BEGIN
|
||||||
|
|
||||||
namespace battle
|
namespace battle
|
||||||
@ -43,6 +46,12 @@ std::string Unit::getDescription() const
|
|||||||
return fmt.str();
|
return fmt.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//TODO: deduplicate these functions
|
||||||
|
const IBonusBearer* Unit::getBonusBearer() const
|
||||||
|
{
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
std::vector<BattleHex> Unit::getSurroundingHexes(BattleHex assumedPosition) const
|
std::vector<BattleHex> Unit::getSurroundingHexes(BattleHex assumedPosition) const
|
||||||
{
|
{
|
||||||
BattleHex hex = (assumedPosition != BattleHex::INVALID) ? assumedPosition : getPosition(); //use hypothetical position
|
BattleHex hex = (assumedPosition != BattleHex::INVALID) ? assumedPosition : getPosition(); //use hypothetical position
|
||||||
|
@ -10,6 +10,7 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <vcmi/Entity.h>
|
||||||
#include <vcmi/spells/Caster.h>
|
#include <vcmi/spells/Caster.h>
|
||||||
|
|
||||||
#include "../HeroBonus.h"
|
#include "../HeroBonus.h"
|
||||||
@ -40,7 +41,7 @@ namespace BattlePhases
|
|||||||
|
|
||||||
class CUnitState;
|
class CUnitState;
|
||||||
|
|
||||||
class DLL_LINKAGE Unit : public IUnitInfo, public spells::Caster, public virtual IBonusBearer
|
class DLL_LINKAGE Unit : public IUnitInfo, public spells::Caster, public virtual IBonusBearer, public IConstBonusNativeTerrainProvider
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual ~Unit();
|
virtual ~Unit();
|
||||||
@ -126,6 +127,9 @@ public:
|
|||||||
|
|
||||||
int getRawSurrenderCost() const;
|
int getRawSurrenderCost() const;
|
||||||
|
|
||||||
|
//IConstBonusProvider
|
||||||
|
const IBonusBearer* getBonusBearer() const override;
|
||||||
|
|
||||||
//NOTE: save could possibly be const, but this requires heavy changes to Json serialization,
|
//NOTE: save could possibly be const, but this requires heavy changes to Json serialization,
|
||||||
//also this method should be called only after modifying object
|
//also this method should be called only after modifying object
|
||||||
virtual void save(JsonNode & data) = 0;
|
virtual void save(JsonNode & data) = 0;
|
||||||
|
@ -65,7 +65,7 @@ void CArmedInstance::updateMoraleBonusFromArmy()
|
|||||||
}
|
}
|
||||||
|
|
||||||
//number of alignments and presence of undead
|
//number of alignments and presence of undead
|
||||||
std::set<TFaction> factions;
|
std::set<FactionID> factions;
|
||||||
bool hasUndead = false;
|
bool hasUndead = false;
|
||||||
|
|
||||||
const std::string undeadCacheKey = "type_UNDEAD";
|
const std::string undeadCacheKey = "type_UNDEAD";
|
||||||
@ -76,7 +76,7 @@ void CArmedInstance::updateMoraleBonusFromArmy()
|
|||||||
const CStackInstance * inst = slot.second;
|
const CStackInstance * inst = slot.second;
|
||||||
const CCreature * creature = VLC->creh->objects[inst->getCreatureID()];
|
const CCreature * creature = VLC->creh->objects[inst->getCreatureID()];
|
||||||
|
|
||||||
factions.insert(creature->getFactionIndex());
|
factions.insert(creature->getFaction());
|
||||||
// Check for undead flag instead of faction (undead mummies are neutral)
|
// Check for undead flag instead of faction (undead mummies are neutral)
|
||||||
if (!hasUndead)
|
if (!hasUndead)
|
||||||
{
|
{
|
||||||
@ -91,7 +91,7 @@ void CArmedInstance::updateMoraleBonusFromArmy()
|
|||||||
{
|
{
|
||||||
size_t mixableFactions = 0;
|
size_t mixableFactions = 0;
|
||||||
|
|
||||||
for(TFaction f : factions)
|
for(auto f : factions)
|
||||||
{
|
{
|
||||||
if (VLC->factions()->getByIndex(f)->getAlignment() != EAlignment::EVIL)
|
if (VLC->factions()->getByIndex(f)->getAlignment() != EAlignment::EVIL)
|
||||||
mixableFactions++;
|
mixableFactions++;
|
||||||
@ -156,4 +156,9 @@ CBonusSystemNode & CArmedInstance::whatShouldBeAttached()
|
|||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const IBonusBearer* CArmedInstance::getBonusBearer() const
|
||||||
|
{
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
VCMI_LIB_NAMESPACE_END
|
VCMI_LIB_NAMESPACE_END
|
||||||
|
@ -17,7 +17,7 @@ VCMI_LIB_NAMESPACE_BEGIN
|
|||||||
class BattleInfo;
|
class BattleInfo;
|
||||||
class CGameState;
|
class CGameState;
|
||||||
|
|
||||||
class DLL_LINKAGE CArmedInstance: public CGObjectInstance, public CBonusSystemNode, public CCreatureSet
|
class DLL_LINKAGE CArmedInstance: public CGObjectInstance, public CBonusSystemNode, public CCreatureSet, public IConstBonusProvider
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
CCheckProxy nonEvilAlignmentMix;
|
CCheckProxy nonEvilAlignmentMix;
|
||||||
@ -32,6 +32,8 @@ public:
|
|||||||
void armyChanged() override;
|
void armyChanged() override;
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
//IConstBonusProvider
|
||||||
|
const IBonusBearer* getBonusBearer() const override;
|
||||||
// int valOfGlobalBonuses(CSelector selector) const; //used only for castle interface ???
|
// int valOfGlobalBonuses(CSelector selector) const; //used only for castle interface ???
|
||||||
virtual CBonusSystemNode & whereShouldBeAttached(CGameState * gs);
|
virtual CBonusSystemNode & whereShouldBeAttached(CGameState * gs);
|
||||||
virtual CBonusSystemNode & whatShouldBeAttached();
|
virtual CBonusSystemNode & whatShouldBeAttached();
|
||||||
|
@ -84,6 +84,16 @@ ui32 CGHeroInstance::getTileCost(const TerrainTile & dest, const TerrainTile & f
|
|||||||
return static_cast<ui32>(ret);
|
return static_cast<ui32>(ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FactionID CGHeroInstance::getFaction() const
|
||||||
|
{
|
||||||
|
return FactionID(type->heroClass->faction);
|
||||||
|
}
|
||||||
|
|
||||||
|
const IBonusBearer* CGHeroInstance::getBonusBearer() const
|
||||||
|
{
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
TerrainId CGHeroInstance::getNativeTerrain() const
|
TerrainId CGHeroInstance::getNativeTerrain() const
|
||||||
{
|
{
|
||||||
// NOTE: in H3 neutral stacks will ignore terrain penalty only if placed as topmost stack(s) in hero army.
|
// NOTE: in H3 neutral stacks will ignore terrain penalty only if placed as topmost stack(s) in hero army.
|
||||||
@ -96,7 +106,7 @@ TerrainId CGHeroInstance::getNativeTerrain() const
|
|||||||
|
|
||||||
for(const auto & stack : stacks)
|
for(const auto & stack : stacks)
|
||||||
{
|
{
|
||||||
TerrainId stackNativeTerrain = stack.second->type->getNativeTerrain(); //consider terrain bonuses e.g. Lodestar.
|
TerrainId stackNativeTerrain = stack.second->getNativeTerrain(); //consider terrain bonuses e.g. Lodestar.
|
||||||
|
|
||||||
if(stackNativeTerrain == ETerrainId::NONE)
|
if(stackNativeTerrain == ETerrainId::NONE)
|
||||||
continue;
|
continue;
|
||||||
|
@ -40,7 +40,7 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
class DLL_LINKAGE CGHeroInstance : public CArmedInstance, public IBoatGenerator, public CArtifactSet, public spells::Caster
|
class DLL_LINKAGE CGHeroInstance : public CArmedInstance, public IBoatGenerator, public CArtifactSet, public spells::Caster, public IConstBonusNativeTerrainProvider
|
||||||
{
|
{
|
||||||
// We serialize heroes into JSON for crossover
|
// We serialize heroes into JSON for crossover
|
||||||
friend class CCampaignState;
|
friend class CCampaignState;
|
||||||
@ -102,20 +102,6 @@ public:
|
|||||||
}
|
}
|
||||||
} patrol;
|
} patrol;
|
||||||
|
|
||||||
// deprecated - used only for loading of old saves
|
|
||||||
struct HeroSpecial : CBonusSystemNode
|
|
||||||
{
|
|
||||||
bool growsWithLevel;
|
|
||||||
|
|
||||||
HeroSpecial(){growsWithLevel = false;};
|
|
||||||
|
|
||||||
template <typename Handler> void serialize(Handler &h, const int version)
|
|
||||||
{
|
|
||||||
h & static_cast<CBonusSystemNode&>(*this);
|
|
||||||
h & growsWithLevel;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
struct DLL_LINKAGE SecondarySkillsInfo
|
struct DLL_LINKAGE SecondarySkillsInfo
|
||||||
{
|
{
|
||||||
//skills are determined, initialized at map start
|
//skills are determined, initialized at map start
|
||||||
@ -170,7 +156,9 @@ public:
|
|||||||
bool needsLastStack()const override;
|
bool needsLastStack()const override;
|
||||||
|
|
||||||
ui32 getTileCost(const TerrainTile & dest, const TerrainTile & from, const TurnInfo * ti) const; //move cost - applying pathfinding skill, road and terrain modifiers. NOT includes diagonal move penalty, last move levelling
|
ui32 getTileCost(const TerrainTile & dest, const TerrainTile & from, const TurnInfo * ti) const; //move cost - applying pathfinding skill, road and terrain modifiers. NOT includes diagonal move penalty, last move levelling
|
||||||
TerrainId getNativeTerrain() const;
|
//INativeTerrainProvider
|
||||||
|
FactionID getFaction() const override;
|
||||||
|
TerrainId getNativeTerrain() const override;
|
||||||
int getLowestCreatureSpeed() const;
|
int getLowestCreatureSpeed() const;
|
||||||
si32 manaRegain() const; //how many points of mana can hero regain "naturally" in one day
|
si32 manaRegain() const; //how many points of mana can hero regain "naturally" in one day
|
||||||
si32 getManaNewTurn() const; //calculate how much mana this hero is going to have the next day
|
si32 getManaNewTurn() const; //calculate how much mana this hero is going to have the next day
|
||||||
@ -260,6 +248,9 @@ public:
|
|||||||
std::string nodeName() const override;
|
std::string nodeName() const override;
|
||||||
si32 manaLimit() const override;
|
si32 manaLimit() const override;
|
||||||
|
|
||||||
|
///IConstBonusProvider
|
||||||
|
const IBonusBearer* getBonusBearer() const override;
|
||||||
|
|
||||||
CBonusSystemNode * whereShouldBeAttachedOnSiege(const bool isBattleOutsideTown) const;
|
CBonusSystemNode * whereShouldBeAttachedOnSiege(const bool isBattleOutsideTown) const;
|
||||||
CBonusSystemNode * whereShouldBeAttachedOnSiege(CGameState * gs);
|
CBonusSystemNode * whereShouldBeAttachedOnSiege(CGameState * gs);
|
||||||
|
|
||||||
|
@ -938,7 +938,7 @@ void CGTownInstance::newTurn(CRandomGenerator & rand) const
|
|||||||
std::vector<SlotID> nativeCrits; //slots
|
std::vector<SlotID> nativeCrits; //slots
|
||||||
for(const auto & elem : Slots())
|
for(const auto & elem : Slots())
|
||||||
{
|
{
|
||||||
if (elem.second->type->getFactionIndex() == subID) //native
|
if (elem.second->type->getFaction() == subID) //native
|
||||||
{
|
{
|
||||||
nativeCrits.push_back(elem.first); //collect matching slots
|
nativeCrits.push_back(elem.first); //collect matching slots
|
||||||
}
|
}
|
||||||
@ -1232,12 +1232,7 @@ void CGTownInstance::recreateBuildingsBonuses()
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
for(auto & bonus : building->buildingBonuses)
|
for(auto & bonus : building->buildingBonuses)
|
||||||
{
|
addNewBonus(bonus);
|
||||||
if(bonus->propagator != nullptr && bonus->propagator->getPropagatorType() == ALL_CREATURES)
|
|
||||||
VLC->creh->addBonusForAllCreatures(bonus);
|
|
||||||
else
|
|
||||||
addNewBonus(bonus);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1617,6 +1612,16 @@ void CGTownInstance::serializeJsonOptions(JsonSerializeFormat & handler)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FactionID CGTownInstance::getFaction() const
|
||||||
|
{
|
||||||
|
return town->faction->getId();
|
||||||
|
}
|
||||||
|
|
||||||
|
TerrainId CGTownInstance::getNativeTerrain() const
|
||||||
|
{
|
||||||
|
return town->faction->getNativeTerrain();
|
||||||
|
}
|
||||||
|
|
||||||
PlayerColor CGTownBuilding::getOwner() const
|
PlayerColor CGTownBuilding::getOwner() const
|
||||||
{
|
{
|
||||||
return town->getOwner();
|
return town->getOwner();
|
||||||
@ -1764,7 +1769,7 @@ void CTownBonus::onHeroVisit (const CGHeroInstance * h) const
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case BuildingSubID::CUSTOM_VISITING_BONUS:
|
case BuildingSubID::CUSTOM_VISITING_BONUS:
|
||||||
const auto building = town->town->buildings.at(bID);
|
const auto building = town->getTown()->buildings.at(bID);
|
||||||
if(!h->hasBonusFrom(Bonus::TOWN_STRUCTURE, Bonus::getSid32(building->town->faction->getIndex(), building->bid)))
|
if(!h->hasBonusFrom(Bonus::TOWN_STRUCTURE, Bonus::getSid32(building->town->faction->getIndex(), building->bid)))
|
||||||
{
|
{
|
||||||
const auto & bonuses = building->onVisitBonuses;
|
const auto & bonuses = building->onVisitBonuses;
|
||||||
@ -1848,7 +1853,7 @@ int GrowthInfo::totalGrowth() const
|
|||||||
|
|
||||||
std::string CGTownBuilding::getVisitingBonusGreeting() const
|
std::string CGTownBuilding::getVisitingBonusGreeting() const
|
||||||
{
|
{
|
||||||
auto bonusGreeting = town->town->getGreeting(bType);
|
auto bonusGreeting = town->getTown()->getGreeting(bType);
|
||||||
|
|
||||||
if(!bonusGreeting.empty())
|
if(!bonusGreeting.empty())
|
||||||
return bonusGreeting;
|
return bonusGreeting;
|
||||||
@ -1874,15 +1879,15 @@ std::string CGTownBuilding::getVisitingBonusGreeting() const
|
|||||||
bonusGreeting = std::string(VLC->generaltexth->translate("vcmi.townHall.greetingDefence"));
|
bonusGreeting = std::string(VLC->generaltexth->translate("vcmi.townHall.greetingDefence"));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
auto buildingName = town->town->getSpecialBuilding(bType)->getNameTranslated();
|
auto buildingName = town->getTown()->getSpecialBuilding(bType)->getNameTranslated();
|
||||||
|
|
||||||
if(bonusGreeting.empty())
|
if(bonusGreeting.empty())
|
||||||
{
|
{
|
||||||
bonusGreeting = "Error: Bonus greeting for '%s' is not localized.";
|
bonusGreeting = "Error: Bonus greeting for '%s' is not localized.";
|
||||||
logGlobal->error("'%s' building of '%s' faction has not localized bonus greeting.", buildingName, town->town->faction->getNameTranslated());
|
logGlobal->error("'%s' building of '%s' faction has not localized bonus greeting.", buildingName, town->getTown()->faction->getNameTranslated());
|
||||||
}
|
}
|
||||||
boost::algorithm::replace_first(bonusGreeting, "%s", buildingName);
|
boost::algorithm::replace_first(bonusGreeting, "%s", buildingName);
|
||||||
town->town->setGreeting(bType, bonusGreeting);
|
town->getTown()->setGreeting(bType, bonusGreeting);
|
||||||
return bonusGreeting;
|
return bonusGreeting;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1891,7 +1896,7 @@ std::string CGTownBuilding::getCustomBonusGreeting(const Bonus & bonus) const
|
|||||||
if(bonus.type == Bonus::TOWN_MAGIC_WELL)
|
if(bonus.type == Bonus::TOWN_MAGIC_WELL)
|
||||||
{
|
{
|
||||||
auto bonusGreeting = std::string(VLC->generaltexth->translate("vcmi.townHall.greetingInTownMagicWell"));
|
auto bonusGreeting = std::string(VLC->generaltexth->translate("vcmi.townHall.greetingInTownMagicWell"));
|
||||||
auto buildingName = town->town->getSpecialBuilding(bType)->getNameTranslated();
|
auto buildingName = town->getTown()->getSpecialBuilding(bType)->getNameTranslated();
|
||||||
boost::algorithm::replace_first(bonusGreeting, "%s", buildingName);
|
boost::algorithm::replace_first(bonusGreeting, "%s", buildingName);
|
||||||
return bonusGreeting;
|
return bonusGreeting;
|
||||||
}
|
}
|
||||||
|
@ -202,7 +202,7 @@ struct DLL_LINKAGE GrowthInfo
|
|||||||
int totalGrowth() const;
|
int totalGrowth() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
class DLL_LINKAGE CGTownInstance : public CGDwelling, public IShipyard, public IMarket
|
class DLL_LINKAGE CGTownInstance : public CGDwelling, public IShipyard, public IMarket, public INativeTerrainProvider
|
||||||
{
|
{
|
||||||
std::string name; // name of town
|
std::string name; // name of town
|
||||||
public:
|
public:
|
||||||
@ -341,7 +341,11 @@ public:
|
|||||||
/// Returns damage range for central tower(keep) of this town
|
/// Returns damage range for central tower(keep) of this town
|
||||||
DamageRange getKeepDamageRange() const;
|
DamageRange getKeepDamageRange() const;
|
||||||
|
|
||||||
const CTown * getTown() const ;
|
const CTown * getTown() const;
|
||||||
|
|
||||||
|
/// INativeTerrainProvider
|
||||||
|
FactionID getFaction() const override;
|
||||||
|
TerrainId getNativeTerrain() const override;
|
||||||
|
|
||||||
CGTownInstance();
|
CGTownInstance();
|
||||||
virtual ~CGTownInstance();
|
virtual ~CGTownInstance();
|
||||||
|
@ -15,7 +15,7 @@
|
|||||||
VCMI_LIB_NAMESPACE_BEGIN
|
VCMI_LIB_NAMESPACE_BEGIN
|
||||||
|
|
||||||
class JsonNode;
|
class JsonNode;
|
||||||
typedef std::vector<JsonNode> JsonVector;
|
using JsonVector = std::vector<JsonNode>;
|
||||||
class CRandomGenerator;
|
class CRandomGenerator;
|
||||||
|
|
||||||
struct Bonus;
|
struct Bonus;
|
||||||
|
@ -67,7 +67,7 @@ struct DLL_LINKAGE PlayerInfo
|
|||||||
bool canComputerPlay;
|
bool canComputerPlay;
|
||||||
EAiTactic::EAiTactic aiTactic; /// The default value is EAiTactic::RANDOM.
|
EAiTactic::EAiTactic aiTactic; /// The default value is EAiTactic::RANDOM.
|
||||||
|
|
||||||
std::set<TFaction> allowedFactions;
|
std::set<FactionID> allowedFactions;
|
||||||
bool isFactionRandom;
|
bool isFactionRandom;
|
||||||
|
|
||||||
///main hero instance (VCMI maps only)
|
///main hero instance (VCMI maps only)
|
||||||
|
@ -251,10 +251,10 @@ void CMapLoaderH3M::readPlayerInfo()
|
|||||||
{
|
{
|
||||||
mapHeader->players[i].allowedFactions.clear();
|
mapHeader->players[i].allowedFactions.clear();
|
||||||
|
|
||||||
for(int fact = 0; fact < totalFactions; ++fact)
|
for(auto fact = 0; fact < totalFactions; ++fact)
|
||||||
{
|
{
|
||||||
if(allowedFactions & (1 << fact))
|
if(allowedFactions & (1 << fact))
|
||||||
mapHeader->players[i].allowedFactions.insert(fact);
|
mapHeader->players[i].allowedFactions.insert(FactionID(fact));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -382,7 +382,7 @@ RoadType * CMapFormatJson::getRoadByCode(const std::string & code)
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CMapFormatJson::serializeAllowedFactions(JsonSerializeFormat & handler, std::set<TFaction> & value) const
|
void CMapFormatJson::serializeAllowedFactions(JsonSerializeFormat & handler, std::set<FactionID> & value) const
|
||||||
{
|
{
|
||||||
//TODO: unify allowed factions with others - make them std::vector<bool>
|
//TODO: unify allowed factions with others - make them std::vector<bool>
|
||||||
|
|
||||||
@ -404,7 +404,7 @@ void CMapFormatJson::serializeAllowedFactions(JsonSerializeFormat & handler, std
|
|||||||
value.clear();
|
value.clear();
|
||||||
for (std::size_t i=0; i<temp.size(); i++)
|
for (std::size_t i=0; i<temp.size(); i++)
|
||||||
if(temp[i])
|
if(temp[i])
|
||||||
value.insert(static_cast<TFaction>(i));
|
value.insert(static_cast<FactionID>(i));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -64,7 +64,7 @@ protected:
|
|||||||
static RiverType * getRiverByCode(const std::string & code);
|
static RiverType * getRiverByCode(const std::string & code);
|
||||||
static RoadType * getRoadByCode(const std::string & code);
|
static RoadType * getRoadByCode(const std::string & code);
|
||||||
|
|
||||||
void serializeAllowedFactions(JsonSerializeFormat & handler, std::set<TFaction> & value) const;
|
void serializeAllowedFactions(JsonSerializeFormat & handler, std::set<FactionID> & value) const;
|
||||||
|
|
||||||
///common part of header saving/loading
|
///common part of header saving/loading
|
||||||
void serializeHeader(JsonSerializeFormat & handler);
|
void serializeHeader(JsonSerializeFormat & handler);
|
||||||
|
@ -179,10 +179,10 @@ void registerTypesMapObjects2(Serializer &s)
|
|||||||
s.template registerType<ILimiter, CCreatureTypeLimiter>();
|
s.template registerType<ILimiter, CCreatureTypeLimiter>();
|
||||||
s.template registerType<ILimiter, HasAnotherBonusLimiter>();
|
s.template registerType<ILimiter, HasAnotherBonusLimiter>();
|
||||||
s.template registerType<ILimiter, CreatureTerrainLimiter>();
|
s.template registerType<ILimiter, CreatureTerrainLimiter>();
|
||||||
s.template registerType<ILimiter, CreatureFactionLimiter>();
|
s.template registerType<ILimiter, FactionLimiter>();
|
||||||
|
s.template registerType<ILimiter, CreatureLevelLimiter>();
|
||||||
s.template registerType<ILimiter, CreatureAlignmentLimiter>();
|
s.template registerType<ILimiter, CreatureAlignmentLimiter>();
|
||||||
s.template registerType<ILimiter, RankRangeLimiter>();
|
s.template registerType<ILimiter, RankRangeLimiter>();
|
||||||
s.template registerType<ILimiter, StackOwnerLimiter>();
|
|
||||||
s.template registerType<ILimiter, UnitOnHexLimiter>();
|
s.template registerType<ILimiter, UnitOnHexLimiter>();
|
||||||
|
|
||||||
// s.template registerType<CBonusSystemNode>();
|
// s.template registerType<CBonusSystemNode>();
|
||||||
@ -194,7 +194,6 @@ void registerTypesMapObjects2(Serializer &s)
|
|||||||
s.template registerType<CBonusSystemNode, PlayerState>();
|
s.template registerType<CBonusSystemNode, PlayerState>();
|
||||||
s.template registerType<CBonusSystemNode, TeamState>();
|
s.template registerType<CBonusSystemNode, TeamState>();
|
||||||
//s.template registerType<CGameState>(); //TODO
|
//s.template registerType<CGameState>(); //TODO
|
||||||
s.template registerType<CBonusSystemNode, CGHeroInstance::HeroSpecial>();
|
|
||||||
//s.template registerType<CArmedInstance>();
|
//s.template registerType<CArmedInstance>();
|
||||||
s.template registerType<CBonusSystemNode, CStack>();
|
s.template registerType<CBonusSystemNode, CStack>();
|
||||||
s.template registerType<CBonusSystemNode, BattleInfo>();
|
s.template registerType<CBonusSystemNode, BattleInfo>();
|
||||||
|
@ -135,14 +135,14 @@ void CMapGenOptions::setMonsterStrength(EMonsterStrength::EMonsterStrength value
|
|||||||
void CMapGenOptions::resetPlayersMap()
|
void CMapGenOptions::resetPlayersMap()
|
||||||
{
|
{
|
||||||
|
|
||||||
std::map<PlayerColor, TFaction> rememberTownTypes;
|
std::map<PlayerColor, FactionID> rememberTownTypes;
|
||||||
std::map<PlayerColor, TeamID> rememberTeam;
|
std::map<PlayerColor, TeamID> rememberTeam;
|
||||||
|
|
||||||
for(const auto & p : players)
|
for(const auto & p : players)
|
||||||
{
|
{
|
||||||
auto town = p.second.getStartingTown();
|
auto town = p.second.getStartingTown();
|
||||||
if (town != RANDOM_SIZE)
|
if (town != RANDOM_SIZE)
|
||||||
rememberTownTypes[p.first] = town;
|
rememberTownTypes[p.first] = FactionID(town);
|
||||||
rememberTeam[p.first] = p.second.getTeam();
|
rememberTeam[p.first] = p.second.getTeam();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -199,33 +199,33 @@ void ZoneOptions::setTerrainTypes(const std::set<TerrainId> & value)
|
|||||||
terrainTypes = value;
|
terrainTypes = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::set<TFaction> ZoneOptions::getDefaultTownTypes() const
|
std::set<FactionID> ZoneOptions::getDefaultTownTypes() const
|
||||||
{
|
{
|
||||||
std::set<TFaction> defaultTowns;
|
std::set<FactionID> defaultTowns;
|
||||||
auto towns = VLC->townh->getDefaultAllowed();
|
auto towns = VLC->townh->getDefaultAllowed();
|
||||||
for(int i = 0; i < towns.size(); ++i)
|
for(int i = 0; i < towns.size(); ++i)
|
||||||
{
|
{
|
||||||
if(towns[i]) defaultTowns.insert(i);
|
if(towns[i]) defaultTowns.insert(FactionID(i));
|
||||||
}
|
}
|
||||||
return defaultTowns;
|
return defaultTowns;
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::set<TFaction> & ZoneOptions::getTownTypes() const
|
const std::set<FactionID> & ZoneOptions::getTownTypes() const
|
||||||
{
|
{
|
||||||
return townTypes;
|
return townTypes;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ZoneOptions::setTownTypes(const std::set<TFaction> & value)
|
void ZoneOptions::setTownTypes(const std::set<FactionID> & value)
|
||||||
{
|
{
|
||||||
townTypes = value;
|
townTypes = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ZoneOptions::setMonsterTypes(const std::set<TFaction> & value)
|
void ZoneOptions::setMonsterTypes(const std::set<FactionID> & value)
|
||||||
{
|
{
|
||||||
monsterTypes = value;
|
monsterTypes = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::set<TFaction> & ZoneOptions::getMonsterTypes() const
|
const std::set<FactionID> & ZoneOptions::getMonsterTypes() const
|
||||||
{
|
{
|
||||||
return monsterTypes;
|
return monsterTypes;
|
||||||
}
|
}
|
||||||
@ -373,8 +373,8 @@ void ZoneOptions::serializeJson(JsonSerializeFormat & handler)
|
|||||||
}
|
}
|
||||||
|
|
||||||
handler.serializeBool("townsAreSameType", townsAreSameType, false);
|
handler.serializeBool("townsAreSameType", townsAreSameType, false);
|
||||||
handler.serializeIdArray<TFaction, FactionID>("allowedMonsters", monsterTypes, VLC->townh->getAllowedFactions(false));
|
handler.serializeIdArray<FactionID, FactionID>("allowedMonsters", monsterTypes, VLC->townh->getAllowedFactions(false));
|
||||||
handler.serializeIdArray<TFaction, FactionID>("allowedTowns", townTypes, VLC->townh->getAllowedFactions(true));
|
handler.serializeIdArray<FactionID, FactionID>("allowedTowns", townTypes, VLC->townh->getAllowedFactions(true));
|
||||||
|
|
||||||
{
|
{
|
||||||
//TODO: add support for std::map to serializeEnum
|
//TODO: add support for std::map to serializeEnum
|
||||||
|
@ -131,12 +131,12 @@ public:
|
|||||||
|
|
||||||
const CTownInfo & getPlayerTowns() const;
|
const CTownInfo & getPlayerTowns() const;
|
||||||
const CTownInfo & getNeutralTowns() const;
|
const CTownInfo & getNeutralTowns() const;
|
||||||
std::set<TFaction> getDefaultTownTypes() const;
|
std::set<FactionID> getDefaultTownTypes() const;
|
||||||
const std::set<TFaction> & getTownTypes() const;
|
const std::set<FactionID> & getTownTypes() const;
|
||||||
const std::set<TFaction> & getMonsterTypes() const;
|
const std::set<FactionID> & getMonsterTypes() const;
|
||||||
|
|
||||||
void setTownTypes(const std::set<TFaction> & value);
|
void setTownTypes(const std::set<FactionID> & value);
|
||||||
void setMonsterTypes(const std::set<TFaction> & value);
|
void setMonsterTypes(const std::set<FactionID> & value);
|
||||||
|
|
||||||
void setMinesInfo(const std::map<TResource, ui16> & value);
|
void setMinesInfo(const std::map<TResource, ui16> & value);
|
||||||
std::map<TResource, ui16> getMinesInfo() const;
|
std::map<TResource, ui16> getMinesInfo() const;
|
||||||
@ -173,8 +173,8 @@ protected:
|
|||||||
std::set<TerrainId> terrainTypes;
|
std::set<TerrainId> terrainTypes;
|
||||||
bool townsAreSameType;
|
bool townsAreSameType;
|
||||||
|
|
||||||
std::set<TFaction> townTypes;
|
std::set<FactionID> townTypes;
|
||||||
std::set<TFaction> monsterTypes;
|
std::set<FactionID> monsterTypes;
|
||||||
|
|
||||||
std::map<TResource, ui16> mines; //obligatory mines to spawn in this zone
|
std::map<TResource, ui16> mines; //obligatory mines to spawn in this zone
|
||||||
|
|
||||||
|
@ -426,7 +426,7 @@ CGCreature * ObjectManager::chooseGuard(si32 strength, bool zoneGuard)
|
|||||||
continue;
|
continue;
|
||||||
if(!cre->getAIValue()) //bug #2681
|
if(!cre->getAIValue()) //bug #2681
|
||||||
continue;
|
continue;
|
||||||
if(!vstd::contains(zone.getMonsterTypes(), cre->getFactionIndex()))
|
if(!vstd::contains(zone.getMonsterTypes(), cre->getFaction()))
|
||||||
continue;
|
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
|
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
|
||||||
{
|
{
|
||||||
|
@ -274,13 +274,13 @@ float RmgMap::getNearestObjectDistance(const int3 &tile) const
|
|||||||
return tiles[tile.x][tile.y][tile.z].getNearestObjectDistance();
|
return tiles[tile.x][tile.y][tile.z].getNearestObjectDistance();
|
||||||
}
|
}
|
||||||
|
|
||||||
void RmgMap::registerZone(TFaction faction)
|
void RmgMap::registerZone(FactionID faction)
|
||||||
{
|
{
|
||||||
zonesPerFaction[faction]++;
|
zonesPerFaction[faction]++;
|
||||||
zonesTotal++;
|
zonesTotal++;
|
||||||
}
|
}
|
||||||
|
|
||||||
ui32 RmgMap::getZoneCount(TFaction faction)
|
ui32 RmgMap::getZoneCount(FactionID faction)
|
||||||
{
|
{
|
||||||
return zonesPerFaction[faction];
|
return zonesPerFaction[faction];
|
||||||
}
|
}
|
||||||
|
@ -60,8 +60,8 @@ public:
|
|||||||
|
|
||||||
Zones & getZones();
|
Zones & getZones();
|
||||||
|
|
||||||
void registerZone(TFaction faction);
|
void registerZone(FactionID faction);
|
||||||
ui32 getZoneCount(TFaction faction);
|
ui32 getZoneCount(FactionID faction);
|
||||||
ui32 getTotalZoneCount() const;
|
ui32 getTotalZoneCount() const;
|
||||||
void initTiles(CMapGenerator & generator);
|
void initTiles(CMapGenerator & generator);
|
||||||
void addModificators();
|
void addModificators();
|
||||||
@ -75,7 +75,7 @@ private:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
Zones zones;
|
Zones zones;
|
||||||
std::map<TFaction, ui32> zonesPerFaction;
|
std::map<FactionID, ui32> zonesPerFaction;
|
||||||
ui32 zonesTotal; //zones that have their main town only
|
ui32 zonesTotal; //zones that have their main town only
|
||||||
const CMapGenOptions& mapGenOptions;
|
const CMapGenOptions& mapGenOptions;
|
||||||
boost::multi_array<TileInfo, 3> tiles; //[x][y][z]
|
boost::multi_array<TileInfo, 3> tiles; //[x][y][z]
|
||||||
|
@ -85,7 +85,7 @@ void TownPlacer::placeTowns(ObjectManager & manager)
|
|||||||
|
|
||||||
totalTowns++;
|
totalTowns++;
|
||||||
//register MAIN town of zone only
|
//register MAIN town of zone only
|
||||||
map.registerZone(town->subID);
|
map.registerZone(town->getFaction());
|
||||||
|
|
||||||
if(playerInfo.canAnyonePlay()) //configure info for owning player
|
if(playerInfo.canAnyonePlay()) //configure info for owning player
|
||||||
{
|
{
|
||||||
@ -201,7 +201,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
|
//FIXME: discovered bug with small zones - getPos is close to map boarder and we have outOfMap exception
|
||||||
//register MAIN town of zone
|
//register MAIN town of zone
|
||||||
map.registerZone(town->subID);
|
map.registerZone(town->getFaction());
|
||||||
//first town in zone goes in the middle
|
//first town in zone goes in the middle
|
||||||
placeMainTown(manager, *town);
|
placeMainTown(manager, *town);
|
||||||
}
|
}
|
||||||
@ -216,8 +216,8 @@ si32 TownPlacer::getRandomTownType(bool matchUndergroundType)
|
|||||||
auto townTypesAllowed = (!zone.getTownTypes().empty() ? zone.getTownTypes() : zone.getDefaultTownTypes());
|
auto townTypesAllowed = (!zone.getTownTypes().empty() ? zone.getTownTypes() : zone.getDefaultTownTypes());
|
||||||
if(matchUndergroundType)
|
if(matchUndergroundType)
|
||||||
{
|
{
|
||||||
std::set<TFaction> townTypesVerify;
|
std::set<FactionID> townTypesVerify;
|
||||||
for(TFaction factionIdx : townTypesAllowed)
|
for(auto factionIdx : townTypesAllowed)
|
||||||
{
|
{
|
||||||
bool preferUnderground = (*VLC->townh)[factionIdx]->preferUndergroundPlacement;
|
bool preferUnderground = (*VLC->townh)[factionIdx]->preferUndergroundPlacement;
|
||||||
if(zone.isUnderground() ? preferUnderground : !preferUnderground)
|
if(zone.isUnderground() ? preferUnderground : !preferUnderground)
|
||||||
|
@ -135,7 +135,7 @@ void TreasurePlacer::addAllPossibleObjects()
|
|||||||
std::vector<CCreature *> creatures; //native creatures for this zone
|
std::vector<CCreature *> creatures; //native creatures for this zone
|
||||||
for(auto cre : VLC->creh->objects)
|
for(auto cre : VLC->creh->objects)
|
||||||
{
|
{
|
||||||
if(!cre->special && cre->getFactionIndex() == zone.getTownType())
|
if(!cre->special && cre->getFaction() == zone.getTownType())
|
||||||
{
|
{
|
||||||
creatures.push_back(cre);
|
creatures.push_back(cre);
|
||||||
}
|
}
|
||||||
@ -164,9 +164,9 @@ void TreasurePlacer::addAllPossibleObjects()
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
const auto * cre = creatures.front();
|
const auto * cre = creatures.front();
|
||||||
if(cre->getFactionIndex() == zone.getTownType())
|
if(cre->getFaction() == zone.getTownType())
|
||||||
{
|
{
|
||||||
auto nativeZonesCount = static_cast<float>(map.getZoneCount(cre->getFactionIndex()));
|
auto nativeZonesCount = static_cast<float>(map.getZoneCount(cre->getFaction()));
|
||||||
oi.value = static_cast<ui32>(cre->getAIValue() * cre->getGrowth() * (1 + (nativeZonesCount / map.getTotalZoneCount()) + (nativeZonesCount / 2)));
|
oi.value = static_cast<ui32>(cre->getAIValue() * cre->getGrowth() * (1 + (nativeZonesCount / map.getTotalZoneCount()) + (nativeZonesCount / 2)));
|
||||||
oi.probability = 40;
|
oi.probability = 40;
|
||||||
|
|
||||||
@ -294,7 +294,7 @@ void TreasurePlacer::addAllPossibleObjects()
|
|||||||
return obj;
|
return obj;
|
||||||
};
|
};
|
||||||
oi.setTemplate(Obj::PANDORAS_BOX, 0, zone.getTerrainType());
|
oi.setTemplate(Obj::PANDORAS_BOX, 0, zone.getTerrainType());
|
||||||
oi.value = static_cast<ui32>((2 * (creature->getAIValue()) * creaturesAmount * (1 + static_cast<float>(map.getZoneCount(creature->getFactionIndex())) / map.getTotalZoneCount())) / 3);
|
oi.value = static_cast<ui32>((2 * (creature->getAIValue()) * creaturesAmount * (1 + static_cast<float>(map.getZoneCount(creature->getFaction())) / map.getTotalZoneCount())) / 3);
|
||||||
oi.probability = 3;
|
oi.probability = 3;
|
||||||
addObjectToRandomPool(oi);
|
addObjectToRandomPool(oi);
|
||||||
}
|
}
|
||||||
@ -453,7 +453,7 @@ void TreasurePlacer::addAllPossibleObjects()
|
|||||||
return obj;
|
return obj;
|
||||||
};
|
};
|
||||||
oi.setTemplate(Obj::SEER_HUT, randomAppearance, zone.getTerrainType());
|
oi.setTemplate(Obj::SEER_HUT, randomAppearance, zone.getTerrainType());
|
||||||
oi.value = static_cast<ui32>(((2 * (creature->getAIValue()) * creaturesAmount * (1 + static_cast<float>(map.getZoneCount(creature->getFactionIndex())) / map.getTotalZoneCount())) - 4000) / 3);
|
oi.value = static_cast<ui32>(((2 * (creature->getAIValue()) * creaturesAmount * (1 + static_cast<float>(map.getZoneCount(creature->getFaction())) / map.getTotalZoneCount())) - 4000) / 3);
|
||||||
oi.probability = 3;
|
oi.probability = 3;
|
||||||
addObjectToRandomPool(oi);
|
addObjectToRandomPool(oi);
|
||||||
}
|
}
|
||||||
|
@ -123,9 +123,9 @@ rmg::Area & Zone::freePaths()
|
|||||||
return dAreaFree;
|
return dAreaFree;
|
||||||
}
|
}
|
||||||
|
|
||||||
si32 Zone::getTownType() const
|
FactionID Zone::getTownType() const
|
||||||
{
|
{
|
||||||
return townType;
|
return FactionID(townType);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Zone::setTownType(si32 town)
|
void Zone::setTownType(si32 town)
|
||||||
|
@ -98,7 +98,7 @@ public:
|
|||||||
void clearTiles();
|
void clearTiles();
|
||||||
void fractalize();
|
void fractalize();
|
||||||
|
|
||||||
si32 getTownType() const;
|
FactionID getTownType() const;
|
||||||
void setTownType(si32 town);
|
void setTownType(si32 town);
|
||||||
TerrainId getTerrainType() const;
|
TerrainId getTerrainType() const;
|
||||||
void setTerrainType(TerrainId terrain);
|
void setTerrainType(TerrainId terrain);
|
||||||
|
@ -14,8 +14,8 @@
|
|||||||
|
|
||||||
VCMI_LIB_NAMESPACE_BEGIN
|
VCMI_LIB_NAMESPACE_BEGIN
|
||||||
|
|
||||||
const ui32 SERIALIZATION_VERSION = 821;
|
const ui32 SERIALIZATION_VERSION = 822;
|
||||||
const ui32 MINIMAL_SERIALIZATION_VERSION = 821;
|
const ui32 MINIMAL_SERIALIZATION_VERSION = 822;
|
||||||
const std::string SAVEGAME_MAGIC = "VCMISVG";
|
const std::string SAVEGAME_MAGIC = "VCMISVG";
|
||||||
|
|
||||||
class CHero;
|
class CHero;
|
||||||
|
@ -340,7 +340,7 @@ int32_t CSpell::getLevelPower(const int32_t skillLevel) const
|
|||||||
return getLevelInfo(skillLevel).power;
|
return getLevelInfo(skillLevel).power;
|
||||||
}
|
}
|
||||||
|
|
||||||
si32 CSpell::getProbability(const TFaction factionId) const
|
si32 CSpell::getProbability(const FactionID & factionId) const
|
||||||
{
|
{
|
||||||
if(!vstd::contains(probabilities,factionId))
|
if(!vstd::contains(probabilities,factionId))
|
||||||
{
|
{
|
||||||
@ -722,7 +722,7 @@ CSpell * CSpellHandler::loadFromJson(const std::string & scope, const JsonNode &
|
|||||||
|
|
||||||
VLC->modh->identifiers.requestIdentifier(node.second.meta, "faction", node.first, [=](si32 factionID)
|
VLC->modh->identifiers.requestIdentifier(node.second.meta, "faction", node.first, [=](si32 factionID)
|
||||||
{
|
{
|
||||||
spell->probabilities[factionID] = chance;
|
spell->probabilities[FactionID(factionID)] = chance;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -192,7 +192,7 @@ public:
|
|||||||
|
|
||||||
si32 power; //spell's power
|
si32 power; //spell's power
|
||||||
|
|
||||||
std::map<TFaction, si32> probabilities; //% chance to gain for castles
|
std::map<FactionID, si32> probabilities; //% chance to gain for castles
|
||||||
|
|
||||||
bool combat; //is this spell combat (true) or adventure (false)
|
bool combat; //is this spell combat (true) or adventure (false)
|
||||||
bool creatureAbility; //if true, only creatures can use this spell
|
bool creatureAbility; //if true, only creatures can use this spell
|
||||||
@ -223,7 +223,7 @@ public:
|
|||||||
|
|
||||||
int32_t getCost(const int32_t skillLevel) const override;
|
int32_t getCost(const int32_t skillLevel) const override;
|
||||||
|
|
||||||
si32 getProbability(const TFaction factionId) const;
|
si32 getProbability(const FactionID & factionId) const;
|
||||||
|
|
||||||
int32_t getBasePower() const override;
|
int32_t getBasePower() const override;
|
||||||
int32_t getLevelPower(const int32_t skillLevel) const override;
|
int32_t getLevelPower(const int32_t skillLevel) const override;
|
||||||
|
@ -87,7 +87,7 @@ void Moat::convertBonus(const Mechanics * m, std::vector<Bonus> & converted) con
|
|||||||
|
|
||||||
if(m->battle()->battleGetDefendedTown() && m->battle()->battleGetSiegeLevel() >= CGTownInstance::CITADEL)
|
if(m->battle()->battleGetDefendedTown() && m->battle()->battleGetSiegeLevel() >= CGTownInstance::CITADEL)
|
||||||
{
|
{
|
||||||
nb.sid = Bonus::getSid32(m->battle()->battleGetDefendedTown()->town->faction->getIndex(), BuildingID::CITADEL);
|
nb.sid = Bonus::getSid32(m->battle()->battleGetDefendedTown()->getFaction(), BuildingID::CITADEL);
|
||||||
nb.source = Bonus::TOWN_STRUCTURE;
|
nb.source = Bonus::TOWN_STRUCTURE;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -29,7 +29,7 @@ PlayerParams::PlayerParams(MapController & ctrl, int playerId, QWidget *parent)
|
|||||||
{
|
{
|
||||||
CFaction * faction = VLC->townh->objects.at(idx);
|
CFaction * faction = VLC->townh->objects.at(idx);
|
||||||
auto * item = new QListWidgetItem(QString::fromStdString(faction->getNameTranslated()));
|
auto * item = new QListWidgetItem(QString::fromStdString(faction->getNameTranslated()));
|
||||||
item->setData(Qt::UserRole, QVariant::fromValue(idx));
|
item->setData(Qt::UserRole, QVariant::fromValue(idx.getNum()));
|
||||||
item->setFlags(item->flags() | Qt::ItemIsUserCheckable);
|
item->setFlags(item->flags() | Qt::ItemIsUserCheckable);
|
||||||
ui->allowedFactions->addItem(item);
|
ui->allowedFactions->addItem(item);
|
||||||
if(playerInfo.allowedFactions.count(idx))
|
if(playerInfo.allowedFactions.count(idx))
|
||||||
@ -124,9 +124,9 @@ void PlayerParams::on_randomFaction_stateChanged(int arg1)
|
|||||||
void PlayerParams::allowedFactionsCheck(QListWidgetItem * item)
|
void PlayerParams::allowedFactionsCheck(QListWidgetItem * item)
|
||||||
{
|
{
|
||||||
if(item->checkState() == Qt::Checked)
|
if(item->checkState() == Qt::Checked)
|
||||||
playerInfo.allowedFactions.insert(item->data(Qt::UserRole).toInt());
|
playerInfo.allowedFactions.insert(FactionID(item->data(Qt::UserRole).toInt()));
|
||||||
else
|
else
|
||||||
playerInfo.allowedFactions.erase(item->data(Qt::UserRole).toInt());
|
playerInfo.allowedFactions.erase(FactionID(item->data(Qt::UserRole).toInt()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -34,7 +34,7 @@ const std::vector<ArtifactProxy::CustomRegType> ArtifactProxy::REGISTER_CUSTOM =
|
|||||||
{"getName", LuaMethodWrapper<Artifact, decltype(&Entity::getNameTranslated), &Entity::getNameTranslated>::invoke, false},
|
{"getName", LuaMethodWrapper<Artifact, decltype(&Entity::getNameTranslated), &Entity::getNameTranslated>::invoke, false},
|
||||||
|
|
||||||
{"getId", LuaMethodWrapper<Artifact, decltype(&EntityT<ArtifactID>::getId), &EntityT<ArtifactID>::getId>::invoke, false},
|
{"getId", LuaMethodWrapper<Artifact, decltype(&EntityT<ArtifactID>::getId), &EntityT<ArtifactID>::getId>::invoke, false},
|
||||||
{"getBonusBearer", LuaMethodWrapper<Artifact, decltype(&EntityWithBonuses<ArtifactID>::getBonusBearer), &EntityWithBonuses<ArtifactID>::getBonusBearer>::invoke, false},
|
{"getBonusBearer", LuaMethodWrapper<Artifact, decltype(&IConstBonusProvider::getBonusBearer), &IConstBonusProvider::getBonusBearer>::invoke, false},
|
||||||
|
|
||||||
{"getDescription", LuaMethodWrapper<Artifact, decltype(&Artifact::getDescriptionTranslated), &Artifact::getDescriptionTranslated>::invoke, false},
|
{"getDescription", LuaMethodWrapper<Artifact, decltype(&Artifact::getDescriptionTranslated), &Artifact::getDescriptionTranslated>::invoke, false},
|
||||||
{"getEventText", LuaMethodWrapper<Artifact, decltype(&Artifact::getEventTranslated), &Artifact::getEventTranslated>::invoke, false},
|
{"getEventText", LuaMethodWrapper<Artifact, decltype(&Artifact::getEventTranslated), &Artifact::getEventTranslated>::invoke, false},
|
||||||
|
@ -32,7 +32,7 @@ const std::vector<CreatureProxy::CustomRegType> CreatureProxy::REGISTER_CUSTOM =
|
|||||||
{"getIndex", LuaMethodWrapper<Creature, decltype(&Entity::getIndex), &Entity::getIndex>::invoke, false},
|
{"getIndex", LuaMethodWrapper<Creature, decltype(&Entity::getIndex), &Entity::getIndex>::invoke, false},
|
||||||
{"getJsonKey", LuaMethodWrapper<Creature, decltype(&Entity::getJsonKey), &Entity::getJsonKey>::invoke, false},
|
{"getJsonKey", LuaMethodWrapper<Creature, decltype(&Entity::getJsonKey), &Entity::getJsonKey>::invoke, false},
|
||||||
{"getName", LuaMethodWrapper<Creature, decltype(&Entity::getNameTranslated), &Entity::getNameTranslated>::invoke, false},
|
{"getName", LuaMethodWrapper<Creature, decltype(&Entity::getNameTranslated), &Entity::getNameTranslated>::invoke, false},
|
||||||
{"getBonusBearer", LuaMethodWrapper<Creature, decltype(&EntityWithBonuses<CreatureID>::getBonusBearer), &EntityWithBonuses<CreatureID>::getBonusBearer>::invoke, false},
|
{"getBonusBearer", LuaMethodWrapper<Creature, decltype(&IConstBonusProvider::getBonusBearer), &IConstBonusProvider::getBonusBearer>::invoke, false},
|
||||||
|
|
||||||
{"getMaxHealth", LuaMethodWrapper<Creature,decltype(&Creature::getMaxHealth), &Creature::getMaxHealth>::invoke, false},
|
{"getMaxHealth", LuaMethodWrapper<Creature,decltype(&Creature::getMaxHealth), &Creature::getMaxHealth>::invoke, false},
|
||||||
{"getPluralName", LuaMethodWrapper<Creature, decltype(&Creature::getNamePluralTranslated), &Creature::getNamePluralTranslated>::invoke, false},
|
{"getPluralName", LuaMethodWrapper<Creature, decltype(&Creature::getNamePluralTranslated), &Creature::getNamePluralTranslated>::invoke, false},
|
||||||
@ -45,7 +45,7 @@ const std::vector<CreatureProxy::CustomRegType> CreatureProxy::REGISTER_CUSTOM =
|
|||||||
{"getLevel", LuaMethodWrapper<Creature, decltype(&Creature::getLevel), &Creature::getLevel>::invoke, false},
|
{"getLevel", LuaMethodWrapper<Creature, decltype(&Creature::getLevel), &Creature::getLevel>::invoke, false},
|
||||||
{"getGrowth", LuaMethodWrapper<Creature, decltype(&Creature::getGrowth), &Creature::getGrowth>::invoke, false},
|
{"getGrowth", LuaMethodWrapper<Creature, decltype(&Creature::getGrowth), &Creature::getGrowth>::invoke, false},
|
||||||
{"getHorde", LuaMethodWrapper<Creature, decltype(&Creature::getHorde), &Creature::getHorde>::invoke, false},
|
{"getHorde", LuaMethodWrapper<Creature, decltype(&Creature::getHorde), &Creature::getHorde>::invoke, false},
|
||||||
{"getFactionIndex", LuaMethodWrapper<Creature, decltype(&Creature::getFactionIndex), &Creature::getFactionIndex>::invoke, false},
|
{"getFaction", LuaMethodWrapper<Creature, decltype(&Creature::getFaction), &Creature::getFaction>::invoke, false},
|
||||||
|
|
||||||
{"getBaseAttack", LuaMethodWrapper<Creature, decltype(&Creature::getBaseAttack), &Creature::getBaseAttack>::invoke, false},
|
{"getBaseAttack", LuaMethodWrapper<Creature, decltype(&Creature::getBaseAttack), &Creature::getBaseAttack>::invoke, false},
|
||||||
{"getBaseDefense", LuaMethodWrapper<Creature, decltype(&Creature::getBaseDefense), &Creature::getBaseDefense>::invoke, false},
|
{"getBaseDefense", LuaMethodWrapper<Creature, decltype(&Creature::getBaseDefense), &Creature::getBaseDefense>::invoke, false},
|
||||||
|
@ -80,7 +80,7 @@ MA.I = createModifier({}, "aiValue" ,"getAIValue")
|
|||||||
MA.L = createModifier({}, "level" , "getLevel")
|
MA.L = createModifier({}, "level" , "getLevel")
|
||||||
MA.M = createModifier({"damage"}, "min", "getBaseDamageMin")
|
MA.M = createModifier({"damage"}, "min", "getBaseDamageMin")
|
||||||
MA.N = createModifier({}, "shots" , "getBaseShots")
|
MA.N = createModifier({}, "shots" , "getBaseShots")
|
||||||
MA.O = createModifier({}, "faction" ,"getFactionIndex")
|
MA.O = createModifier({}, "faction" ,"getFaction")
|
||||||
MA.P = createModifier({}, "hitPoints" ,"getBaseHitPoints")
|
MA.P = createModifier({}, "hitPoints" ,"getBaseHitPoints")
|
||||||
MA.R = createModifier({}, "horde" , "getHorde")
|
MA.R = createModifier({}, "horde" , "getHorde")
|
||||||
MA.S = createModifier({}, "speed" , "getBaseSpeed")
|
MA.S = createModifier({}, "speed" , "getBaseSpeed")
|
||||||
|
@ -1732,7 +1732,7 @@ void CGameHandler::newTurn()
|
|||||||
{
|
{
|
||||||
newMonster.second = VLC->creh->pickRandomMonster(getRandomGenerator());
|
newMonster.second = VLC->creh->pickRandomMonster(getRandomGenerator());
|
||||||
} while (VLC->creh->objects[newMonster.second] &&
|
} while (VLC->creh->objects[newMonster.second] &&
|
||||||
(*VLC->townh)[VLC->creatures()->getById(newMonster.second)->getFactionIndex()]->town == nullptr); // find first non neutral creature
|
(*VLC->townh)[VLC->creatures()->getById(newMonster.second)->getFaction()]->town == nullptr); // find first non neutral creature
|
||||||
n.creatureid = newMonster.second;
|
n.creatureid = newMonster.second;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -853,7 +853,7 @@ void CVCMIServer::optionNextCastle(PlayerColor player, int dir)
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
assert(dir >= -1 && dir <= 1); //othervice std::advance may go out of range
|
assert(dir >= -1 && dir <= 1); //othervice std::advance may go out of range
|
||||||
auto iter = allowed.find((ui8)cur);
|
auto iter = allowed.find(FactionID(cur));
|
||||||
std::advance(iter, dir);
|
std::advance(iter, dir);
|
||||||
cur = *iter;
|
cur = *iter;
|
||||||
}
|
}
|
||||||
|
@ -96,7 +96,7 @@ TEST_F(CCreatureTest, JsonUpdate)
|
|||||||
|
|
||||||
EXPECT_EQ(subject->getFightValue(), 2420);
|
EXPECT_EQ(subject->getFightValue(), 2420);
|
||||||
EXPECT_EQ(subject->getLevel(), 6);
|
EXPECT_EQ(subject->getLevel(), 6);
|
||||||
EXPECT_EQ(subject->getFactionIndex(), 55);
|
EXPECT_EQ(subject->getFaction(), 55);
|
||||||
EXPECT_TRUE(subject->isDoubleWide());
|
EXPECT_TRUE(subject->isDoubleWide());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -111,7 +111,7 @@ TEST_F(ERM_MA, Example)
|
|||||||
EXPECT_CALL(oldCreature, getAIValue()).WillOnce(Return(AI_VALUE));
|
EXPECT_CALL(oldCreature, getAIValue()).WillOnce(Return(AI_VALUE));
|
||||||
EXPECT_CALL(oldCreature, getFightValue()).WillOnce(Return(FIGHT_VALUE));
|
EXPECT_CALL(oldCreature, getFightValue()).WillOnce(Return(FIGHT_VALUE));
|
||||||
EXPECT_CALL(oldCreature, getLevel()).WillOnce(Return(LEVEL));
|
EXPECT_CALL(oldCreature, getLevel()).WillOnce(Return(LEVEL));
|
||||||
EXPECT_CALL(oldCreature, getFactionIndex()).WillOnce(Return(FACTION));
|
EXPECT_CALL(oldCreature, getFaction()).WillOnce(Return(FACTION));
|
||||||
|
|
||||||
EXPECT_CALL(oldCreature, isDoubleWide()).WillRepeatedly(Return(false));
|
EXPECT_CALL(oldCreature, isDoubleWide()).WillRepeatedly(Return(false));
|
||||||
|
|
||||||
|
@ -13,6 +13,7 @@
|
|||||||
#include <vcmi/Creature.h>
|
#include <vcmi/Creature.h>
|
||||||
|
|
||||||
class IBonusBearer;
|
class IBonusBearer;
|
||||||
|
class FactionID;
|
||||||
|
|
||||||
class CreatureMock : public Creature
|
class CreatureMock : public Creature
|
||||||
{
|
{
|
||||||
@ -36,7 +37,7 @@ public:
|
|||||||
MOCK_CONST_METHOD0(getLevel, int32_t());
|
MOCK_CONST_METHOD0(getLevel, int32_t());
|
||||||
MOCK_CONST_METHOD0(getGrowth, int32_t());
|
MOCK_CONST_METHOD0(getGrowth, int32_t());
|
||||||
MOCK_CONST_METHOD0(getHorde, int32_t());
|
MOCK_CONST_METHOD0(getHorde, int32_t());
|
||||||
MOCK_CONST_METHOD0(getFactionIndex, int32_t());
|
MOCK_CONST_METHOD0(getFaction, FactionID());
|
||||||
|
|
||||||
MOCK_CONST_METHOD0(getBaseAttack, int32_t());
|
MOCK_CONST_METHOD0(getBaseAttack, int32_t());
|
||||||
MOCK_CONST_METHOD0(getBaseDefense, int32_t());
|
MOCK_CONST_METHOD0(getBaseDefense, int32_t());
|
||||||
|
Loading…
x
Reference in New Issue
Block a user