1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-01-02 00:10:22 +02:00

MetaIdentifier now uses std::variant internally

This commit is contained in:
Ivan Savenko 2023-10-14 18:13:59 +03:00
parent b394158dc9
commit 80e6485965
61 changed files with 487 additions and 421 deletions

View File

@ -11,7 +11,6 @@
#include <limits> #include <limits>
#include "Nullkiller.h" #include "Nullkiller.h"
#include "../../../lib/bonuses/BonusSubtypes.h"
#include "../../../lib/mapObjectConstructors/AObjectTypeHandler.h" #include "../../../lib/mapObjectConstructors/AObjectTypeHandler.h"
#include "../../../lib/mapObjectConstructors/CObjectClassesHandler.h" #include "../../../lib/mapObjectConstructors/CObjectClassesHandler.h"
#include "../../../lib/mapObjectConstructors/CBankInstanceConstructor.h" #include "../../../lib/mapObjectConstructors/CBankInstanceConstructor.h"
@ -243,7 +242,7 @@ uint64_t evaluateArtifactArmyValue(CArtifactInstance * art)
return 1500; return 1500;
auto statsValue = auto statsValue =
10 * art->valOfBonuses(BonusType::MOVEMENT, BonusSubtypes::heroMovementLand) 10 * art->valOfBonuses(BonusType::MOVEMENT, BonusSubtypeID::heroMovementLand)
+ 1200 * art->valOfBonuses(BonusType::STACKS_SPEED) + 1200 * art->valOfBonuses(BonusType::STACKS_SPEED)
+ 700 * art->valOfBonuses(BonusType::MORALE) + 700 * art->valOfBonuses(BonusType::MORALE)
+ 700 * art->valOfBonuses(BonusType::PRIMARY_SKILL, TBonusSubtype(PrimarySkill::ATTACK)) + 700 * art->valOfBonuses(BonusType::PRIMARY_SKILL, TBonusSubtype(PrimarySkill::ATTACK))

View File

@ -34,7 +34,6 @@
#include "../../lib/spells/ISpellMechanics.h" #include "../../lib/spells/ISpellMechanics.h"
#include "../../lib/battle/BattleAction.h" #include "../../lib/battle/BattleAction.h"
#include "../../lib/battle/BattleHex.h" #include "../../lib/battle/BattleHex.h"
#include "../../lib/bonuses/BonusSubtypes.h"
#include "../../lib/CStack.h" #include "../../lib/CStack.h"
#include "../../lib/CondSh.h" #include "../../lib/CondSh.h"
#include "../../lib/TextOperations.h" #include "../../lib/TextOperations.h"
@ -535,7 +534,7 @@ void BattleStacksController::stackMoved(const CStack *stack, std::vector<BattleH
addNewAnim(new MovementStartAnimation(owner, stack)); addNewAnim(new MovementStartAnimation(owner, stack));
}); });
if (!stack->hasBonus(Selector::typeSubtype(BonusType::FLYING, BonusSubtypes::movementFlying))) if (!stack->hasBonus(Selector::typeSubtype(BonusType::FLYING, BonusSubtypeID::movementFlying)))
{ {
owner.addToAnimationStage(EAnimationEvents::MOVEMENT, [&]() owner.addToAnimationStage(EAnimationEvents::MOVEMENT, [&]()
{ {

View File

@ -31,7 +31,7 @@ macro(add_main_lib TARGET_NAME LIBRARY_TYPE)
${MAIN_LIB_DIR}/bonuses/BonusList.cpp ${MAIN_LIB_DIR}/bonuses/BonusList.cpp
${MAIN_LIB_DIR}/bonuses/BonusParams.cpp ${MAIN_LIB_DIR}/bonuses/BonusParams.cpp
${MAIN_LIB_DIR}/bonuses/BonusSelector.cpp ${MAIN_LIB_DIR}/bonuses/BonusSelector.cpp
${MAIN_LIB_DIR}/bonuses/BonusSubtypes.cpp ${MAIN_LIB_DIR}/bonuses/BonusSubtypeID.cpp
${MAIN_LIB_DIR}/bonuses/CBonusProxy.cpp ${MAIN_LIB_DIR}/bonuses/CBonusProxy.cpp
${MAIN_LIB_DIR}/bonuses/CBonusSystemNode.cpp ${MAIN_LIB_DIR}/bonuses/CBonusSystemNode.cpp
${MAIN_LIB_DIR}/bonuses/IBonusBearer.cpp ${MAIN_LIB_DIR}/bonuses/IBonusBearer.cpp
@ -43,7 +43,6 @@ macro(add_main_lib TARGET_NAME LIBRARY_TYPE)
${MAIN_LIB_DIR}/campaign/CampaignState.cpp ${MAIN_LIB_DIR}/campaign/CampaignState.cpp
${MAIN_LIB_DIR}/constants/EntityIdentifiers.cpp ${MAIN_LIB_DIR}/constants/EntityIdentifiers.cpp
${MAIN_LIB_DIR}/constants/MetaIdentifier.cpp
${MAIN_LIB_DIR}/events/ApplyDamage.cpp ${MAIN_LIB_DIR}/events/ApplyDamage.cpp
${MAIN_LIB_DIR}/events/GameResumed.cpp ${MAIN_LIB_DIR}/events/GameResumed.cpp
@ -359,7 +358,7 @@ macro(add_main_lib TARGET_NAME LIBRARY_TYPE)
${MAIN_LIB_DIR}/bonuses/BonusList.h ${MAIN_LIB_DIR}/bonuses/BonusList.h
${MAIN_LIB_DIR}/bonuses/BonusParams.h ${MAIN_LIB_DIR}/bonuses/BonusParams.h
${MAIN_LIB_DIR}/bonuses/BonusSelector.h ${MAIN_LIB_DIR}/bonuses/BonusSelector.h
${MAIN_LIB_DIR}/bonuses/BonusSubtypes.h ${MAIN_LIB_DIR}/bonuses/BonusSubtypeID.h
${MAIN_LIB_DIR}/bonuses/CBonusProxy.h ${MAIN_LIB_DIR}/bonuses/CBonusProxy.h
${MAIN_LIB_DIR}/bonuses/CBonusSystemNode.h ${MAIN_LIB_DIR}/bonuses/CBonusSystemNode.h
${MAIN_LIB_DIR}/bonuses/IBonusBearer.h ${MAIN_LIB_DIR}/bonuses/IBonusBearer.h

View File

@ -17,7 +17,6 @@
#include "bonuses/BonusList.h" #include "bonuses/BonusList.h"
#include "bonuses/Bonus.h" #include "bonuses/Bonus.h"
#include "bonuses/IBonusBearer.h" #include "bonuses/IBonusBearer.h"
#include "bonuses/BonusSubtypes.h"
#include <vcmi/Creature.h> #include <vcmi/Creature.h>
#include <vcmi/Faction.h> #include <vcmi/Faction.h>
@ -72,14 +71,14 @@ int AFactionMember::getDefense(bool ranged) const
int AFactionMember::getMinDamage(bool ranged) const int AFactionMember::getMinDamage(bool ranged) const
{ {
const std::string cachingStr = "type_CREATURE_DAMAGEs_0Otype_CREATURE_DAMAGEs_1"; const std::string cachingStr = "type_CREATURE_DAMAGEs_0Otype_CREATURE_DAMAGEs_1";
static const auto selector = Selector::typeSubtype(BonusType::CREATURE_DAMAGE, BonusSubtypes::creatureDamageBoth).Or(Selector::typeSubtype(BonusType::CREATURE_DAMAGE, BonusSubtypes::creatureDamageMin)); static const auto selector = Selector::typeSubtype(BonusType::CREATURE_DAMAGE, BonusSubtypeID::creatureDamageBoth).Or(Selector::typeSubtype(BonusType::CREATURE_DAMAGE, BonusSubtypeID::creatureDamageMin));
return getBonusBearer()->valOfBonuses(selector, cachingStr); return getBonusBearer()->valOfBonuses(selector, cachingStr);
} }
int AFactionMember::getMaxDamage(bool ranged) const int AFactionMember::getMaxDamage(bool ranged) const
{ {
const std::string cachingStr = "type_CREATURE_DAMAGEs_0Otype_CREATURE_DAMAGEs_2"; const std::string cachingStr = "type_CREATURE_DAMAGEs_0Otype_CREATURE_DAMAGEs_2";
static const auto selector = Selector::typeSubtype(BonusType::CREATURE_DAMAGE, BonusSubtypes::creatureDamageBoth).Or(Selector::typeSubtype(BonusType::CREATURE_DAMAGE, BonusSubtypes::creatureDamageMax)); static const auto selector = Selector::typeSubtype(BonusType::CREATURE_DAMAGE, BonusSubtypeID::creatureDamageBoth).Or(Selector::typeSubtype(BonusType::CREATURE_DAMAGE, BonusSubtypeID::creatureDamageMax));
return getBonusBearer()->valOfBonuses(selector, cachingStr); return getBonusBearer()->valOfBonuses(selector, cachingStr);
} }

View File

@ -20,7 +20,6 @@
#include "CCreatureHandler.h" #include "CCreatureHandler.h"
#include "CGeneralTextHandler.h" #include "CGeneralTextHandler.h"
#include "spells/CSpellHandler.h" #include "spells/CSpellHandler.h"
#include "bonuses/BonusSubtypes.h"
template class std::vector<VCMI_LIB_WRAP_NAMESPACE(CBonusType)>; template class std::vector<VCMI_LIB_WRAP_NAMESPACE(CBonusType)>;
@ -169,10 +168,10 @@ ImagePath CBonusTypeHandler::bonusToGraphics(const std::shared_ptr<Bonus> & bonu
} }
case BonusType::GENERAL_DAMAGE_REDUCTION: case BonusType::GENERAL_DAMAGE_REDUCTION:
{ {
if (bonus->subtype == BonusSubtypes::damageTypeMelee) if (bonus->subtype == BonusSubtypeID::damageTypeMelee)
fileName = "DamageReductionMelee.bmp"; fileName = "DamageReductionMelee.bmp";
if (bonus->subtype == BonusSubtypes::damageTypeRanged) if (bonus->subtype == BonusSubtypeID::damageTypeRanged)
fileName = "DamageReductionRanged.bmp"; fileName = "DamageReductionRanged.bmp";
break; break;

View File

@ -19,7 +19,6 @@
#include "constants/StringConstants.h" #include "constants/StringConstants.h"
#include "bonuses/Limiters.h" #include "bonuses/Limiters.h"
#include "bonuses/Updaters.h" #include "bonuses/Updaters.h"
#include "bonuses/BonusSubtypes.h"
#include "serializer/JsonDeserializer.h" #include "serializer/JsonDeserializer.h"
#include "serializer/JsonUpdater.h" #include "serializer/JsonUpdater.h"
#include "mapObjectConstructors/AObjectTypeHandler.h" #include "mapObjectConstructors/AObjectTypeHandler.h"
@ -126,13 +125,13 @@ int32_t CCreature::getBaseDefense() const
int32_t CCreature::getBaseDamageMin() const int32_t CCreature::getBaseDamageMin() const
{ {
static const auto SELECTOR = Selector::typeSubtype(BonusType::CREATURE_DAMAGE, BonusSubtypes::creatureDamageMin).And(Selector::sourceTypeSel(BonusSource::CREATURE_ABILITY)); static const auto SELECTOR = Selector::typeSubtype(BonusType::CREATURE_DAMAGE, BonusSubtypeID::creatureDamageMin).And(Selector::sourceTypeSel(BonusSource::CREATURE_ABILITY));
return getExportedBonusList().valOfBonuses(SELECTOR); return getExportedBonusList().valOfBonuses(SELECTOR);
} }
int32_t CCreature::getBaseDamageMax() const int32_t CCreature::getBaseDamageMax() const
{ {
static const auto SELECTOR = Selector::typeSubtype(BonusType::CREATURE_DAMAGE, BonusSubtypes::creatureDamageMax).And(Selector::sourceTypeSel(BonusSource::CREATURE_ABILITY)); static const auto SELECTOR = Selector::typeSubtype(BonusType::CREATURE_DAMAGE, BonusSubtypeID::creatureDamageMax).And(Selector::sourceTypeSel(BonusSource::CREATURE_ABILITY));
return getExportedBonusList().valOfBonuses(SELECTOR); return getExportedBonusList().valOfBonuses(SELECTOR);
} }
@ -294,7 +293,7 @@ CCreature::CCreature()
void CCreature::addBonus(int val, BonusType type) void CCreature::addBonus(int val, BonusType type)
{ {
addBonus(val, type, TBonusSubtype::NONE); addBonus(val, type, TBonusSubtype());
} }
void CCreature::addBonus(int val, BonusType type, TBonusSubtype subtype) void CCreature::addBonus(int val, BonusType type, TBonusSubtype subtype)
@ -357,10 +356,10 @@ void CCreature::updateFrom(const JsonNode & data)
addBonus(configNode["defense"].Integer(), BonusType::PRIMARY_SKILL, TBonusSubtype(PrimarySkill::DEFENSE)); addBonus(configNode["defense"].Integer(), BonusType::PRIMARY_SKILL, TBonusSubtype(PrimarySkill::DEFENSE));
if(!configNode["damage"]["min"].isNull()) if(!configNode["damage"]["min"].isNull())
addBonus(configNode["damage"]["min"].Integer(), BonusType::CREATURE_DAMAGE, BonusSubtypes::creatureDamageMin); addBonus(configNode["damage"]["min"].Integer(), BonusType::CREATURE_DAMAGE, BonusSubtypeID::creatureDamageMin);
if(!configNode["damage"]["max"].isNull()) if(!configNode["damage"]["max"].isNull())
addBonus(configNode["damage"]["max"].Integer(), BonusType::CREATURE_DAMAGE, BonusSubtypes::creatureDamageMax); addBonus(configNode["damage"]["max"].Integer(), BonusType::CREATURE_DAMAGE, BonusSubtypeID::creatureDamageMax);
if(!configNode["shots"].isNull()) if(!configNode["shots"].isNull())
addBonus(configNode["shots"].Integer(), BonusType::SHOTS); addBonus(configNode["shots"].Integer(), BonusType::SHOTS);
@ -613,8 +612,8 @@ CCreature * CCreatureHandler::loadFromJson(const std::string & scope, const Json
cre->addBonus(node["attack"].Integer(), BonusType::PRIMARY_SKILL, TBonusSubtype(PrimarySkill::ATTACK)); cre->addBonus(node["attack"].Integer(), BonusType::PRIMARY_SKILL, TBonusSubtype(PrimarySkill::ATTACK));
cre->addBonus(node["defense"].Integer(), BonusType::PRIMARY_SKILL, TBonusSubtype(PrimarySkill::DEFENSE)); cre->addBonus(node["defense"].Integer(), BonusType::PRIMARY_SKILL, TBonusSubtype(PrimarySkill::DEFENSE));
cre->addBonus(node["damage"]["min"].Integer(), BonusType::CREATURE_DAMAGE, BonusSubtypes::creatureDamageMin); cre->addBonus(node["damage"]["min"].Integer(), BonusType::CREATURE_DAMAGE, BonusSubtypeID::creatureDamageMin);
cre->addBonus(node["damage"]["max"].Integer(), BonusType::CREATURE_DAMAGE, BonusSubtypes::creatureDamageMax); cre->addBonus(node["damage"]["max"].Integer(), BonusType::CREATURE_DAMAGE, BonusSubtypeID::creatureDamageMax);
assert(node["damage"]["min"].Integer() <= node["damage"]["max"].Integer()); assert(node["damage"]["min"].Integer() <= node["damage"]["max"].Integer());
@ -1039,11 +1038,11 @@ void CCreatureHandler::loadStackExp(Bonus & b, BonusList & bl, CLegacyConfigPars
break; break;
case 'M': //Max damage case 'M': //Max damage
b.type = BonusType::CREATURE_DAMAGE; b.type = BonusType::CREATURE_DAMAGE;
b.subtype = BonusSubtypes::creatureDamageMax; b.subtype = BonusSubtypeID::creatureDamageMax;
break; break;
case 'm': //Min damage case 'm': //Min damage
b.type = BonusType::CREATURE_DAMAGE; b.type = BonusType::CREATURE_DAMAGE;
b.subtype = BonusSubtypes::creatureDamageMin; b.subtype = BonusSubtypeID::creatureDamageMin;
break; break;
case 'S': case 'S':
b.type = BonusType::STACKS_SPEED; break; b.type = BonusType::STACKS_SPEED; break;
@ -1060,7 +1059,7 @@ void CCreatureHandler::loadStackExp(Bonus & b, BonusList & bl, CLegacyConfigPars
break; break;
case 'E': case 'E':
b.type = BonusType::DEATH_STARE; b.type = BonusType::DEATH_STARE;
b.subtype = BonusSubtypes::deathStareGorgon; b.subtype = BonusSubtypeID::deathStareGorgon;
break; break;
case 'F': case 'F':
b.type = BonusType::FEAR; break; b.type = BonusType::FEAR; break;
@ -1107,7 +1106,7 @@ void CCreatureHandler::loadStackExp(Bonus & b, BonusList & bl, CLegacyConfigPars
b.type = BonusType::MIND_IMMUNITY; break; b.type = BonusType::MIND_IMMUNITY; break;
case 'r': case 'r':
b.type = BonusType::REBIRTH; //on/off? makes sense? b.type = BonusType::REBIRTH; //on/off? makes sense?
b.subtype = BonusSubtypes::rebirthRegular; b.subtype = BonusSubtypeID::rebirthRegular;
b.val = 20; //arbitrary value b.val = 20; //arbitrary value
break; break;
case 'R': case 'R':

View File

@ -17,7 +17,6 @@
#include "CGeneralTextHandler.h" #include "CGeneralTextHandler.h"
#include "StartInfo.h" // for StartInfo #include "StartInfo.h" // for StartInfo
#include "battle/BattleInfo.h" // for BattleInfo #include "battle/BattleInfo.h" // for BattleInfo
#include "bonuses/BonusSubtypes.h"
#include "NetPacks.h" // for InfoWindow #include "NetPacks.h" // for InfoWindow
#include "GameSettings.h" #include "GameSettings.h"
#include "TerrainHandler.h" #include "TerrainHandler.h"
@ -269,7 +268,7 @@ bool CGameInfoCallback::getTownInfo(const CGObjectInstance * town, InfoAboutTown
{ {
const auto * selectedHero = dynamic_cast<const CGHeroInstance *>(selectedObject); const auto * selectedHero = dynamic_cast<const CGHeroInstance *>(selectedObject);
if(nullptr != selectedHero) if(nullptr != selectedHero)
detailed = selectedHero->hasVisions(town, BonusSubtypes::visionsTowns); detailed = selectedHero->hasVisions(town, BonusSubtypeID::visionsTowns);
} }
dest.initFromTown(dynamic_cast<const CGTownInstance *>(town), detailed); dest.initFromTown(dynamic_cast<const CGTownInstance *>(town), detailed);
@ -323,7 +322,7 @@ bool CGameInfoCallback::getHeroInfo(const CGObjectInstance * hero, InfoAboutHero
{ {
const auto * selectedHero = dynamic_cast<const CGHeroInstance *>(selectedObject); const auto * selectedHero = dynamic_cast<const CGHeroInstance *>(selectedObject);
if(nullptr != selectedHero) if(nullptr != selectedHero)
if(selectedHero->hasVisions(hero, BonusSubtypes::visionsHeroes)) if(selectedHero->hasVisions(hero, BonusSubtypeID::visionsHeroes))
infoLevel = InfoAboutHero::EInfoLevel::DETAILED; infoLevel = InfoAboutHero::EInfoLevel::DETAILED;
} }

View File

@ -17,7 +17,6 @@
#include "CGeneralTextHandler.h" #include "CGeneralTextHandler.h"
#include "battle/BattleInfo.h" #include "battle/BattleInfo.h"
#include "bonuses/BonusSubtypes.h"
#include "spells/CSpellHandler.h" #include "spells/CSpellHandler.h"
#include "NetPacks.h" #include "NetPacks.h"
@ -221,7 +220,7 @@ void CStack::prepareAttacked(BattleStackAttacked & bsa, vstd::RNG & rand, const
resurrectedCount += 1; resurrectedCount += 1;
} }
if(customState->hasBonusOfType(BonusType::REBIRTH, BonusSubtypes::rebirthSpecial)) if(customState->hasBonusOfType(BonusType::REBIRTH, BonusSubtypeID::rebirthSpecial))
{ {
// resurrect at least one Sacred Phoenix // resurrect at least one Sacred Phoenix
vstd::amax(resurrectedCount, 1); vstd::amax(resurrectedCount, 1);

View File

@ -23,7 +23,6 @@
#include "filesystem/Filesystem.h" #include "filesystem/Filesystem.h"
#include "bonuses/Bonus.h" #include "bonuses/Bonus.h"
#include "bonuses/Propagators.h" #include "bonuses/Propagators.h"
#include "bonuses/BonusSubtypes.h"
#include "ResourceSet.h" #include "ResourceSet.h"
#include "mapObjectConstructors/AObjectTypeHandler.h" #include "mapObjectConstructors/AObjectTypeHandler.h"
#include "mapObjectConstructors/CObjectClassesHandler.h" #include "mapObjectConstructors/CObjectClassesHandler.h"
@ -561,7 +560,7 @@ void CTownHandler::addBonusesForVanilaBuilding(CBuilding * building) const
b = createBonus(building, BonusType::PRIMARY_SKILL, +2, TBonusSubtype(PrimarySkill::DEFENSE)); b = createBonus(building, BonusType::PRIMARY_SKILL, +2, TBonusSubtype(PrimarySkill::DEFENSE));
break; break;
case BuildingSubID::LIGHTHOUSE: case BuildingSubID::LIGHTHOUSE:
b = createBonus(building, BonusType::MOVEMENT, +500, BonusSubtypes::heroMovementSea, playerPropagator); b = createBonus(building, BonusType::MOVEMENT, +500, BonusSubtypeID::heroMovementSea, playerPropagator);
break; break;
} }
@ -571,7 +570,7 @@ void CTownHandler::addBonusesForVanilaBuilding(CBuilding * building) const
std::shared_ptr<Bonus> CTownHandler::createBonus(CBuilding * build, BonusType type, int val) const std::shared_ptr<Bonus> CTownHandler::createBonus(CBuilding * build, BonusType type, int val) const
{ {
return createBonus(build, type, val, TBonusSubtype::NONE, emptyPropagator()); return createBonus(build, type, val, TBonusSubtype(), emptyPropagator());
} }
std::shared_ptr<Bonus> CTownHandler::createBonus(CBuilding * build, BonusType type, int val, TBonusSubtype subtype) const std::shared_ptr<Bonus> CTownHandler::createBonus(CBuilding * build, BonusType type, int val, TBonusSubtype subtype) const
@ -583,17 +582,18 @@ std::shared_ptr<Bonus> CTownHandler::createBonus(CBuilding * build, BonusType ty
{ {
std::ostringstream descr; std::ostringstream descr;
descr << build->getNameTranslated(); descr << build->getNameTranslated();
return createBonusImpl(build->bid, type, val, prop, descr.str(), subtype); return createBonusImpl(build->bid, build->town->faction->getId(), type, val, prop, descr.str(), subtype);
} }
std::shared_ptr<Bonus> CTownHandler::createBonusImpl(const BuildingID & building, std::shared_ptr<Bonus> CTownHandler::createBonusImpl(const BuildingID & building,
const FactionID & faction,
BonusType type, BonusType type,
int val, int val,
TPropagatorPtr & prop, TPropagatorPtr & prop,
const std::string & description, const std::string & description,
TBonusSubtype subtype) const TBonusSubtype subtype) const
{ {
auto b = std::make_shared<Bonus>(BonusDuration::PERMANENT, type, BonusSource::TOWN_STRUCTURE, val, TBonusSourceID(building), subtype, description); auto b = std::make_shared<Bonus>(BonusDuration::PERMANENT, type, BonusSource::TOWN_STRUCTURE, val, BuildingTypeUniqueID(faction, building), subtype, description);
if(prop) if(prop)
b->addPropagator(prop); b->addPropagator(prop);
@ -605,7 +605,7 @@ void CTownHandler::loadSpecialBuildingBonuses(const JsonNode & source, BonusList
{ {
for(const auto & b : source.Vector()) for(const auto & b : source.Vector())
{ {
auto bonus = JsonUtils::parseBuildingBonus(b, building->bid, building->getNameTranslated()); auto bonus = JsonUtils::parseBuildingBonus(b, building->town->faction->getId(), building->bid, building->getNameTranslated());
if(bonus == nullptr) if(bonus == nullptr)
continue; continue;

View File

@ -395,6 +395,7 @@ class DLL_LINKAGE CTownHandler : public CHandlerBase<FactionID, Faction, CFactio
std::shared_ptr<Bonus> createBonus(CBuilding * build, BonusType type, int val, TBonusSubtype subtype) const; std::shared_ptr<Bonus> createBonus(CBuilding * build, BonusType type, int val, TBonusSubtype subtype) const;
std::shared_ptr<Bonus> createBonus(CBuilding * build, BonusType type, int val, TBonusSubtype subtype, TPropagatorPtr & prop) const; std::shared_ptr<Bonus> createBonus(CBuilding * build, BonusType type, int val, TBonusSubtype subtype, TPropagatorPtr & prop) const;
std::shared_ptr<Bonus> createBonusImpl(const BuildingID & building, std::shared_ptr<Bonus> createBonusImpl(const BuildingID & building,
const FactionID & faction,
BonusType type, BonusType type,
int val, int val,
TPropagatorPtr & prop, TPropagatorPtr & prop,

View File

@ -421,21 +421,21 @@ static void loadBonusSubtype(TBonusSubtype & subtype, BonusType type, const Json
{ {
if (node.isNull()) if (node.isNull())
{ {
subtype = TBonusSubtype::NONE; subtype = TBonusSubtype();
return; return;
} }
if (!node.isString()) if (!node.isString())
{ {
logMod->warn("Bonus subtype must be string!"); logMod->warn("Bonus subtype must be string!");
subtype = TBonusSubtype::NONE; subtype = TBonusSubtype();
return; return;
} }
VLC->identifiers()->requestIdentifier(node, [&subtype, node](int32_t identifier) VLC->identifiers()->requestIdentifier(node, [&subtype, node](int32_t identifier)
{ {
assert(0); //TODO assert(0); //TODO
subtype = TBonusSubtype("type", node.String(), identifier); subtype = BonusSubtypeID(identifier);
}); });
} }
@ -735,13 +735,13 @@ std::shared_ptr<Bonus> JsonUtils::parseBonus(const JsonNode &ability)
return b; return b;
} }
std::shared_ptr<Bonus> JsonUtils::parseBuildingBonus(const JsonNode & ability, const BuildingID & building, const std::string & description) std::shared_ptr<Bonus> JsonUtils::parseBuildingBonus(const JsonNode & ability, const FactionID & faction, const BuildingID & building, const std::string & description)
{ {
/* duration = BonusDuration::PERMANENT /* duration = BonusDuration::PERMANENT
source = BonusSource::TOWN_STRUCTURE source = BonusSource::TOWN_STRUCTURE
bonusType, val, subtype - get from json bonusType, val, subtype - get from json
*/ */
auto b = std::make_shared<Bonus>(BonusDuration::PERMANENT, BonusType::NONE, BonusSource::TOWN_STRUCTURE, 0, TBonusSourceID(building), description); auto b = std::make_shared<Bonus>(BonusDuration::PERMANENT, BonusType::NONE, BonusSource::TOWN_STRUCTURE, 0, BuildingTypeUniqueID(faction, building), description);
if(!parseBonus(ability, b.get())) if(!parseBonus(ability, b.get()))
return nullptr; return nullptr;

View File

@ -129,7 +129,7 @@ namespace JsonUtils
{ {
DLL_LINKAGE std::shared_ptr<Bonus> parseBonus(const JsonVector & ability_vec); DLL_LINKAGE std::shared_ptr<Bonus> parseBonus(const JsonVector & ability_vec);
DLL_LINKAGE std::shared_ptr<Bonus> parseBonus(const JsonNode & ability); DLL_LINKAGE std::shared_ptr<Bonus> parseBonus(const JsonNode & ability);
DLL_LINKAGE std::shared_ptr<Bonus> parseBuildingBonus(const JsonNode & ability, const BuildingID & building, const std::string & description); DLL_LINKAGE std::shared_ptr<Bonus> parseBuildingBonus(const JsonNode & ability, const FactionID & faction, const BuildingID & building, const std::string & description);
DLL_LINKAGE bool parseBonus(const JsonNode & ability, Bonus * placement); DLL_LINKAGE bool parseBonus(const JsonNode & ability, Bonus * placement);
DLL_LINKAGE std::shared_ptr<ILimiter> parseLimiter(const JsonNode & limiter); DLL_LINKAGE std::shared_ptr<ILimiter> parseLimiter(const JsonNode & limiter);
DLL_LINKAGE CSelector parseSelector(const JsonNode &ability); DLL_LINKAGE CSelector parseSelector(const JsonNode &ability);

View File

@ -2201,7 +2201,7 @@ void BattleTriggerEffect::applyGs(CGameState * gs) const
} }
case BonusType::POISON: case BonusType::POISON:
{ {
auto b = st->getBonusLocalFirst(Selector::source(BonusSource::SPELL_EFFECT, TBonusSubtype(SpellID(SpellID::POISON))) auto b = st->getBonusLocalFirst(Selector::source(BonusSource::SPELL_EFFECT, SpellID(SpellID::POISON))
.And(Selector::type()(BonusType::STACK_HEALTH))); .And(Selector::type()(BonusType::STACK_HEALTH)));
if (b) if (b)
b->val = val; b->val = val;

View File

@ -442,9 +442,9 @@ BattleInfo * BattleInfo::setupBattle(const int3 & tile, TerrainId terrain, const
//native terrain bonuses //native terrain bonuses
static auto nativeTerrain = std::make_shared<CreatureTerrainLimiter>(); static auto nativeTerrain = std::make_shared<CreatureTerrainLimiter>();
curB->addNewBonus(std::make_shared<Bonus>(BonusDuration::ONE_BATTLE, BonusType::STACKS_SPEED, BonusSource::TERRAIN_NATIVE, 1, TBonusSourceID::NONE)->addLimiter(nativeTerrain)); curB->addNewBonus(std::make_shared<Bonus>(BonusDuration::ONE_BATTLE, BonusType::STACKS_SPEED, BonusSource::TERRAIN_NATIVE, 1, TBonusSourceID())->addLimiter(nativeTerrain));
curB->addNewBonus(std::make_shared<Bonus>(BonusDuration::ONE_BATTLE, BonusType::PRIMARY_SKILL, BonusSource::TERRAIN_NATIVE, 1, TBonusSourceID::NONE, TBonusSubtype(PrimarySkill::ATTACK))->addLimiter(nativeTerrain)); curB->addNewBonus(std::make_shared<Bonus>(BonusDuration::ONE_BATTLE, BonusType::PRIMARY_SKILL, BonusSource::TERRAIN_NATIVE, 1, TBonusSourceID(), TBonusSubtype(PrimarySkill::ATTACK))->addLimiter(nativeTerrain));
curB->addNewBonus(std::make_shared<Bonus>(BonusDuration::ONE_BATTLE, BonusType::PRIMARY_SKILL, BonusSource::TERRAIN_NATIVE, 1, TBonusSourceID::NONE, TBonusSubtype(PrimarySkill::DEFENSE))->addLimiter(nativeTerrain)); curB->addNewBonus(std::make_shared<Bonus>(BonusDuration::ONE_BATTLE, BonusType::PRIMARY_SKILL, BonusSource::TERRAIN_NATIVE, 1, TBonusSourceID(), TBonusSubtype(PrimarySkill::DEFENSE))->addLimiter(nativeTerrain));
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
//tactics //tactics

View File

@ -16,8 +16,6 @@
#include "../NetPacks.h" #include "../NetPacks.h"
#include "../CCreatureHandler.h" #include "../CCreatureHandler.h"
#include "../bonuses/BonusSubtypes.h"
#include "../serializer/JsonDeserializer.h" #include "../serializer/JsonDeserializer.h"
#include "../serializer/JsonSerializer.h" #include "../serializer/JsonSerializer.h"
@ -342,8 +340,8 @@ CUnitState::CUnitState():
health(this), health(this),
shots(this), shots(this),
totalAttacks(this, Selector::type()(BonusType::ADDITIONAL_ATTACK), 1), totalAttacks(this, Selector::type()(BonusType::ADDITIONAL_ATTACK), 1),
minDamage(this, Selector::typeSubtype(BonusType::CREATURE_DAMAGE, BonusSubtypes::creatureDamageBoth).Or(Selector::typeSubtype(BonusType::CREATURE_DAMAGE, BonusSubtypes::creatureDamageMin)), 0), minDamage(this, Selector::typeSubtype(BonusType::CREATURE_DAMAGE, BonusSubtypeID::creatureDamageBoth).Or(Selector::typeSubtype(BonusType::CREATURE_DAMAGE, BonusSubtypeID::creatureDamageMin)), 0),
maxDamage(this, Selector::typeSubtype(BonusType::CREATURE_DAMAGE, BonusSubtypes::creatureDamageBoth).Or(Selector::typeSubtype(BonusType::CREATURE_DAMAGE, BonusSubtypes::creatureDamageMax)), 0), maxDamage(this, Selector::typeSubtype(BonusType::CREATURE_DAMAGE, BonusSubtypeID::creatureDamageBoth).Or(Selector::typeSubtype(BonusType::CREATURE_DAMAGE, BonusSubtypeID::creatureDamageMax)), 0),
attack(this, Selector::typeSubtype(BonusType::PRIMARY_SKILL, TBonusSubtype(PrimarySkill::ATTACK)), 0), attack(this, Selector::typeSubtype(BonusType::PRIMARY_SKILL, TBonusSubtype(PrimarySkill::ATTACK)), 0),
defence(this, Selector::typeSubtype(BonusType::PRIMARY_SKILL, TBonusSubtype(PrimarySkill::DEFENSE)), 0), defence(this, Selector::typeSubtype(BonusType::PRIMARY_SKILL, TBonusSubtype(PrimarySkill::DEFENSE)), 0),
inFrenzy(this, Selector::type()(BonusType::IN_FRENZY)), inFrenzy(this, Selector::type()(BonusType::IN_FRENZY)),

View File

@ -14,7 +14,6 @@
#include "Unit.h" #include "Unit.h"
#include "../bonuses/Bonus.h" #include "../bonuses/Bonus.h"
#include "../bonuses/BonusSubtypes.h"
#include "../mapObjects/CGTownInstance.h" #include "../mapObjects/CGTownInstance.h"
#include "../spells/CSpellHandler.h" #include "../spells/CSpellHandler.h"
#include "../GameSettings.h" #include "../GameSettings.h"
@ -207,11 +206,11 @@ double DamageCalculator::getAttackOffenseArcheryFactor() const
if(info.shooting) if(info.shooting)
{ {
const std::string cachingStrArchery = "type_PERCENTAGE_DAMAGE_BOOSTs_1"; const std::string cachingStrArchery = "type_PERCENTAGE_DAMAGE_BOOSTs_1";
static const auto selectorArchery = Selector::typeSubtype(BonusType::PERCENTAGE_DAMAGE_BOOST, BonusSubtypes::damageTypeRanged); static const auto selectorArchery = Selector::typeSubtype(BonusType::PERCENTAGE_DAMAGE_BOOST, BonusSubtypeID::damageTypeRanged);
return info.attacker->valOfBonuses(selectorArchery, cachingStrArchery) / 100.0; return info.attacker->valOfBonuses(selectorArchery, cachingStrArchery) / 100.0;
} }
const std::string cachingStrOffence = "type_PERCENTAGE_DAMAGE_BOOSTs_0"; const std::string cachingStrOffence = "type_PERCENTAGE_DAMAGE_BOOSTs_0";
static const auto selectorOffence = Selector::typeSubtype(BonusType::PERCENTAGE_DAMAGE_BOOST, BonusSubtypes::damageTypeMelee); static const auto selectorOffence = Selector::typeSubtype(BonusType::PERCENTAGE_DAMAGE_BOOST, BonusSubtypeID::damageTypeMelee);
return info.attacker->valOfBonuses(selectorOffence, cachingStrOffence) / 100.0; return info.attacker->valOfBonuses(selectorOffence, cachingStrOffence) / 100.0;
} }
@ -283,7 +282,7 @@ double DamageCalculator::getDefenseSkillFactor() const
double DamageCalculator::getDefenseArmorerFactor() const double DamageCalculator::getDefenseArmorerFactor() const
{ {
const std::string cachingStrArmorer = "type_GENERAL_DAMAGE_REDUCTIONs_N1_NsrcSPELL_EFFECT"; const std::string cachingStrArmorer = "type_GENERAL_DAMAGE_REDUCTIONs_N1_NsrcSPELL_EFFECT";
static const auto selectorArmorer = Selector::typeSubtype(BonusType::GENERAL_DAMAGE_REDUCTION, BonusSubtypes::damageTypeAll).And(Selector::sourceTypeSel(BonusSource::SPELL_EFFECT).Not()); static const auto selectorArmorer = Selector::typeSubtype(BonusType::GENERAL_DAMAGE_REDUCTION, BonusSubtypeID::damageTypeAll).And(Selector::sourceTypeSel(BonusSource::SPELL_EFFECT).Not());
return info.defender->valOfBonuses(selectorArmorer, cachingStrArmorer) / 100.0; return info.defender->valOfBonuses(selectorArmorer, cachingStrArmorer) / 100.0;
} }
@ -291,10 +290,10 @@ double DamageCalculator::getDefenseArmorerFactor() const
double DamageCalculator::getDefenseMagicShieldFactor() const double DamageCalculator::getDefenseMagicShieldFactor() const
{ {
const std::string cachingStrMeleeReduction = "type_GENERAL_DAMAGE_REDUCTIONs_0"; const std::string cachingStrMeleeReduction = "type_GENERAL_DAMAGE_REDUCTIONs_0";
static const auto selectorMeleeReduction = Selector::typeSubtype(BonusType::GENERAL_DAMAGE_REDUCTION, BonusSubtypes::damageTypeMelee); static const auto selectorMeleeReduction = Selector::typeSubtype(BonusType::GENERAL_DAMAGE_REDUCTION, BonusSubtypeID::damageTypeMelee);
const std::string cachingStrRangedReduction = "type_GENERAL_DAMAGE_REDUCTIONs_1"; const std::string cachingStrRangedReduction = "type_GENERAL_DAMAGE_REDUCTIONs_1";
static const auto selectorRangedReduction = Selector::typeSubtype(BonusType::GENERAL_DAMAGE_REDUCTION, BonusSubtypes::damageTypeRanged); static const auto selectorRangedReduction = Selector::typeSubtype(BonusType::GENERAL_DAMAGE_REDUCTION, BonusSubtypeID::damageTypeRanged);
//handling spell effects - shield and air shield //handling spell effects - shield and air shield
if(info.shooting) if(info.shooting)
@ -388,7 +387,7 @@ double DamageCalculator::getDefensePetrificationFactor() const
{ {
// Creatures that are petrified by a Basilisk's Petrifying attack or a Medusa's Stone gaze take 50% damage (R8 = 0.50) from ranged and melee attacks. Taking damage also deactivates the effect. // Creatures that are petrified by a Basilisk's Petrifying attack or a Medusa's Stone gaze take 50% damage (R8 = 0.50) from ranged and melee attacks. Taking damage also deactivates the effect.
const std::string cachingStrAllReduction = "type_GENERAL_DAMAGE_REDUCTIONs_N1_srcSPELL_EFFECT"; const std::string cachingStrAllReduction = "type_GENERAL_DAMAGE_REDUCTIONs_N1_srcSPELL_EFFECT";
static const auto selectorAllReduction = Selector::typeSubtype(BonusType::GENERAL_DAMAGE_REDUCTION, BonusSubtypes::damageTypeAll).And(Selector::sourceTypeSel(BonusSource::SPELL_EFFECT)); static const auto selectorAllReduction = Selector::typeSubtype(BonusType::GENERAL_DAMAGE_REDUCTION, BonusSubtypeID::damageTypeAll).And(Selector::sourceTypeSel(BonusSource::SPELL_EFFECT));
return info.defender->valOfBonuses(selectorAllReduction, cachingStrAllReduction) / 100.0; return info.defender->valOfBonuses(selectorAllReduction, cachingStrAllReduction) / 100.0;
} }

View File

@ -150,7 +150,7 @@ JsonNode Bonus::toJsonNode() const
JsonNode root(JsonNode::JsonType::DATA_STRUCT); JsonNode root(JsonNode::JsonType::DATA_STRUCT);
// only add values that might reasonably be found in config files // only add values that might reasonably be found in config files
root["type"].String() = vstd::findKey(bonusNameMap, type); root["type"].String() = vstd::findKey(bonusNameMap, type);
if(subtype != TBonusSubtype::NONE) if(subtype != TBonusSubtype())
root["subtype"].String() = subtype.toString(); root["subtype"].String() = subtype.toString();
if(additionalInfo != CAddInfo::NONE) if(additionalInfo != CAddInfo::NONE)
root["addInfo"] = additionalInfoToJson(type, additionalInfo); root["addInfo"] = additionalInfoToJson(type, additionalInfo);
@ -158,7 +158,7 @@ JsonNode Bonus::toJsonNode() const
root["sourceType"].String() = vstd::findKey(bonusSourceMap, source); root["sourceType"].String() = vstd::findKey(bonusSourceMap, source);
if(targetSourceType != BonusSource::OTHER) if(targetSourceType != BonusSource::OTHER)
root["targetSourceType"].String() = vstd::findKey(bonusSourceMap, targetSourceType); root["targetSourceType"].String() = vstd::findKey(bonusSourceMap, targetSourceType);
if(sid != TBonusSourceID::NONE) if(sid != TBonusSourceID())
root["sourceID"].String() = sid.toString(); root["sourceID"].String() = sid.toString();
if(val != 0) if(val != 0)
root["val"].Integer() = val; root["val"].Integer() = val;
@ -184,11 +184,11 @@ JsonNode Bonus::toJsonNode() const
} }
Bonus::Bonus(BonusDuration::Type Duration, BonusType Type, BonusSource Src, si32 Val, TBonusSourceID ID) Bonus::Bonus(BonusDuration::Type Duration, BonusType Type, BonusSource Src, si32 Val, TBonusSourceID ID)
: Bonus(Duration, Type, Src, Val, ID, TBonusSubtype::NONE, std::string()) : Bonus(Duration, Type, Src, Val, ID, TBonusSubtype(), std::string())
{} {}
Bonus::Bonus(BonusDuration::Type Duration, BonusType Type, BonusSource Src, si32 Val, TBonusSourceID ID, std::string Desc) Bonus::Bonus(BonusDuration::Type Duration, BonusType Type, BonusSource Src, si32 Val, TBonusSourceID ID, std::string Desc)
: Bonus(Duration, Type, Src, Val, ID, TBonusSubtype::NONE, Desc) : Bonus(Duration, Type, Src, Val, ID, TBonusSubtype(), Desc)
{} {}
Bonus::Bonus(BonusDuration::Type Duration, BonusType Type, BonusSource Src, si32 Val, TBonusSourceID ID, TBonusSubtype Subtype) Bonus::Bonus(BonusDuration::Type Duration, BonusType Type, BonusSource Src, si32 Val, TBonusSourceID ID, TBonusSubtype Subtype)

View File

@ -10,7 +10,9 @@
#pragma once #pragma once
#include "BonusEnum.h" #include "BonusEnum.h"
#include "BonusSubtypeID.h"
#include "../constants/MetaIdentifier.h" #include "../constants/MetaIdentifier.h"
#include "../constants/EntityIdentifiers.h"
VCMI_LIB_NAMESPACE_BEGIN VCMI_LIB_NAMESPACE_BEGIN
@ -23,8 +25,8 @@ class IUpdater;
class BonusList; class BonusList;
class CSelector; class CSelector;
using TBonusSubtype = MetaIdentifier; using TBonusSubtype = MetaIdentifier<BonusSubtypeID, SpellID, CreatureID, PrimarySkill, TerrainId, GameResID, SpellSchool>;
using TBonusSourceID = MetaIdentifier; using TBonusSourceID = MetaIdentifier<BonusSourceID, SpellID, CreatureID, ArtifactID, CampaignScenarioID, SecondarySkill, HeroTypeID, Obj, ObjectInstanceID, BuildingTypeUniqueID, BattleField>;
using TBonusListPtr = std::shared_ptr<BonusList>; using TBonusListPtr = std::shared_ptr<BonusList>;
using TConstBonusListPtr = std::shared_ptr<const BonusList>; using TConstBonusListPtr = std::shared_ptr<const BonusList>;
using TLimiterPtr = std::shared_ptr<ILimiter>; using TLimiterPtr = std::shared_ptr<ILimiter>;

View File

@ -13,9 +13,11 @@
#include "BonusEnum.h" #include "BonusEnum.h"
#include "BonusParams.h" #include "BonusParams.h"
#include "BonusSelector.h" #include "BonusSelector.h"
#include "BonusSubtypes.h"
#include "../ResourceSet.h" #include "../ResourceSet.h"
#include "../VCMI_Lib.h"
#include "../modding/IdentifierStorage.h"
#include "../modding/ModScope.h"
VCMI_LIB_NAMESPACE_BEGIN VCMI_LIB_NAMESPACE_BEGIN
@ -88,28 +90,28 @@ BonusParams::BonusParams(std::string deprecatedTypeStr, std::string deprecatedSu
type = BonusType::LEARN_MEETING_SPELL_LIMIT; type = BonusType::LEARN_MEETING_SPELL_LIMIT;
else if(deprecatedSubtype == SecondarySkill::ARCHERY|| deprecatedSubtypeStr == "skill.archery") else if(deprecatedSubtype == SecondarySkill::ARCHERY|| deprecatedSubtypeStr == "skill.archery")
{ {
subtype = BonusSubtypes::damageTypeRanged; subtype = BonusSubtypeID::damageTypeRanged;
type = BonusType::PERCENTAGE_DAMAGE_BOOST; type = BonusType::PERCENTAGE_DAMAGE_BOOST;
} }
else if(deprecatedSubtype == SecondarySkill::OFFENCE || deprecatedSubtypeStr == "skill.offence") else if(deprecatedSubtype == SecondarySkill::OFFENCE || deprecatedSubtypeStr == "skill.offence")
{ {
subtype = BonusSubtypes::damageTypeMelee; subtype = BonusSubtypeID::damageTypeMelee;
type = BonusType::PERCENTAGE_DAMAGE_BOOST; type = BonusType::PERCENTAGE_DAMAGE_BOOST;
} }
else if(deprecatedSubtype == SecondarySkill::ARMORER || deprecatedSubtypeStr == "skill.armorer") else if(deprecatedSubtype == SecondarySkill::ARMORER || deprecatedSubtypeStr == "skill.armorer")
{ {
subtype = BonusSubtypes::damageTypeAll; subtype = BonusSubtypeID::damageTypeAll;
type = BonusType::GENERAL_DAMAGE_REDUCTION; type = BonusType::GENERAL_DAMAGE_REDUCTION;
} }
else if(deprecatedSubtype == SecondarySkill::NAVIGATION || deprecatedSubtypeStr == "skill.navigation") else if(deprecatedSubtype == SecondarySkill::NAVIGATION || deprecatedSubtypeStr == "skill.navigation")
{ {
subtype = BonusSubtypes::heroMovementSea; subtype = BonusSubtypeID::heroMovementSea;
valueType = BonusValueType::PERCENT_TO_BASE; valueType = BonusValueType::PERCENT_TO_BASE;
type = BonusType::MOVEMENT; type = BonusType::MOVEMENT;
} }
else if(deprecatedSubtype == SecondarySkill::LOGISTICS || deprecatedSubtypeStr == "skill.logistics") else if(deprecatedSubtype == SecondarySkill::LOGISTICS || deprecatedSubtypeStr == "skill.logistics")
{ {
subtype = BonusSubtypes::heroMovementLand; subtype = BonusSubtypeID::heroMovementLand;
valueType = BonusValueType::PERCENT_TO_BASE; valueType = BonusValueType::PERCENT_TO_BASE;
type = BonusType::MOVEMENT; type = BonusType::MOVEMENT;
} }
@ -146,12 +148,12 @@ BonusParams::BonusParams(std::string deprecatedTypeStr, std::string deprecatedSu
else if (deprecatedSubtype == SecondarySkill::FIRST_AID || deprecatedSubtypeStr == "skill.firstAid") else if (deprecatedSubtype == SecondarySkill::FIRST_AID || deprecatedSubtypeStr == "skill.firstAid")
{ {
type = BonusType::SPECIFIC_SPELL_POWER; type = BonusType::SPECIFIC_SPELL_POWER;
subtype = TBonusSubtype("spell", "firstAid"); subtype = SpellID(*VLC->identifiers()->getIdentifier( ModScope::scopeGame(), "spell", "firstAid"));
} }
else if (deprecatedSubtype == SecondarySkill::BALLISTICS || deprecatedSubtypeStr == "skill.ballistics") else if (deprecatedSubtype == SecondarySkill::BALLISTICS || deprecatedSubtypeStr == "skill.ballistics")
{ {
type = BonusType::CATAPULT_EXTRA_SHOTS; type = BonusType::CATAPULT_EXTRA_SHOTS;
subtype = TBonusSubtype("spell", "catapultShot"); subtype = SpellID(*VLC->identifiers()->getIdentifier( ModScope::scopeGame(), "spell", "catapultShot"));
} }
else else
isConverted = false; isConverted = false;
@ -170,20 +172,20 @@ BonusParams::BonusParams(std::string deprecatedTypeStr, std::string deprecatedSu
} }
else if (deprecatedTypeStr == "SEA_MOVEMENT") else if (deprecatedTypeStr == "SEA_MOVEMENT")
{ {
subtype = BonusSubtypes::heroMovementSea; subtype = BonusSubtypeID::heroMovementSea;
valueType = BonusValueType::ADDITIVE_VALUE; valueType = BonusValueType::ADDITIVE_VALUE;
type = BonusType::MOVEMENT; type = BonusType::MOVEMENT;
} }
else if (deprecatedTypeStr == "LAND_MOVEMENT") else if (deprecatedTypeStr == "LAND_MOVEMENT")
{ {
subtype = BonusSubtypes::heroMovementLand; subtype = BonusSubtypeID::heroMovementLand;
valueType = BonusValueType::ADDITIVE_VALUE; valueType = BonusValueType::ADDITIVE_VALUE;
type = BonusType::MOVEMENT; type = BonusType::MOVEMENT;
} }
else if (deprecatedTypeStr == "MAXED_SPELL") else if (deprecatedTypeStr == "MAXED_SPELL")
{ {
type = BonusType::SPELL; type = BonusType::SPELL;
subtype = TBonusSubtype("spell", deprecatedSubtypeStr); subtype = SpellID(*VLC->identifiers()->getIdentifier( ModScope::scopeGame(), "spell", deprecatedSubtypeStr));
valueType = BonusValueType::INDEPENDENT_MAX; valueType = BonusValueType::INDEPENDENT_MAX;
val = 3; val = 3;
} }
@ -224,52 +226,52 @@ BonusParams::BonusParams(std::string deprecatedTypeStr, std::string deprecatedSu
else if (deprecatedTypeStr == "DIRECT_DAMAGE_IMMUNITY") else if (deprecatedTypeStr == "DIRECT_DAMAGE_IMMUNITY")
{ {
type = BonusType::SPELL_DAMAGE_REDUCTION; type = BonusType::SPELL_DAMAGE_REDUCTION;
subtype = MetaIdentifier(SpellSchool::ANY); subtype = TBonusSubtype(SpellSchool::ANY);
val = 100; val = 100;
} }
else if (deprecatedTypeStr == "AIR_SPELL_DMG_PREMY") else if (deprecatedTypeStr == "AIR_SPELL_DMG_PREMY")
{ {
type = BonusType::SPELL_DAMAGE; type = BonusType::SPELL_DAMAGE;
subtype = MetaIdentifier(SpellSchool::AIR); subtype = TBonusSubtype(SpellSchool::AIR);
} }
else if (deprecatedTypeStr == "FIRE_SPELL_DMG_PREMY") else if (deprecatedTypeStr == "FIRE_SPELL_DMG_PREMY")
{ {
type = BonusType::SPELL_DAMAGE; type = BonusType::SPELL_DAMAGE;
subtype = MetaIdentifier(SpellSchool::FIRE); subtype = TBonusSubtype(SpellSchool::FIRE);
} }
else if (deprecatedTypeStr == "WATER_SPELL_DMG_PREMY") else if (deprecatedTypeStr == "WATER_SPELL_DMG_PREMY")
{ {
type = BonusType::SPELL_DAMAGE; type = BonusType::SPELL_DAMAGE;
subtype = MetaIdentifier(SpellSchool::WATER); subtype = TBonusSubtype(SpellSchool::WATER);
} }
else if (deprecatedTypeStr == "EARTH_SPELL_DMG_PREMY") else if (deprecatedTypeStr == "EARTH_SPELL_DMG_PREMY")
{ {
type = BonusType::SPELL_DAMAGE; type = BonusType::SPELL_DAMAGE;
subtype = MetaIdentifier(SpellSchool::EARTH); subtype = TBonusSubtype(SpellSchool::EARTH);
} }
else if (deprecatedTypeStr == "AIR_SPELLS") else if (deprecatedTypeStr == "AIR_SPELLS")
{ {
type = BonusType::SPELLS_OF_SCHOOL; type = BonusType::SPELLS_OF_SCHOOL;
subtype = MetaIdentifier(SpellSchool::AIR); subtype = TBonusSubtype(SpellSchool::AIR);
} }
else if (deprecatedTypeStr == "FIRE_SPELLS") else if (deprecatedTypeStr == "FIRE_SPELLS")
{ {
type = BonusType::SPELLS_OF_SCHOOL; type = BonusType::SPELLS_OF_SCHOOL;
subtype = MetaIdentifier(SpellSchool::FIRE); subtype = TBonusSubtype(SpellSchool::FIRE);
} }
else if (deprecatedTypeStr == "WATER_SPELLS") else if (deprecatedTypeStr == "WATER_SPELLS")
{ {
type = BonusType::SPELLS_OF_SCHOOL; type = BonusType::SPELLS_OF_SCHOOL;
subtype = MetaIdentifier(SpellSchool::WATER); subtype = TBonusSubtype(SpellSchool::WATER);
} }
else if (deprecatedTypeStr == "EARTH_SPELLS") else if (deprecatedTypeStr == "EARTH_SPELLS")
{ {
type = BonusType::SPELLS_OF_SCHOOL; type = BonusType::SPELLS_OF_SCHOOL;
subtype = MetaIdentifier(SpellSchool::EARTH); subtype = TBonusSubtype(SpellSchool::EARTH);
} }
else if (deprecatedTypeStr == "AIR_IMMUNITY") else if (deprecatedTypeStr == "AIR_IMMUNITY")
{ {
subtype = MetaIdentifier(SpellSchool::AIR); subtype = TBonusSubtype(SpellSchool::AIR);
switch(deprecatedSubtype) switch(deprecatedSubtype)
{ {
case 0: case 0:
@ -285,7 +287,7 @@ BonusParams::BonusParams(std::string deprecatedTypeStr, std::string deprecatedSu
} }
else if (deprecatedTypeStr == "FIRE_IMMUNITY") else if (deprecatedTypeStr == "FIRE_IMMUNITY")
{ {
subtype = MetaIdentifier(SpellSchool::FIRE); subtype = TBonusSubtype(SpellSchool::FIRE);
switch(deprecatedSubtype) switch(deprecatedSubtype)
{ {
case 0: case 0:
@ -301,7 +303,7 @@ BonusParams::BonusParams(std::string deprecatedTypeStr, std::string deprecatedSu
} }
else if (deprecatedTypeStr == "WATER_IMMUNITY") else if (deprecatedTypeStr == "WATER_IMMUNITY")
{ {
subtype = MetaIdentifier(SpellSchool::WATER); subtype = TBonusSubtype(SpellSchool::WATER);
switch(deprecatedSubtype) switch(deprecatedSubtype)
{ {
case 0: case 0:
@ -317,7 +319,7 @@ BonusParams::BonusParams(std::string deprecatedTypeStr, std::string deprecatedSu
} }
else if (deprecatedTypeStr == "EARTH_IMMUNITY") else if (deprecatedTypeStr == "EARTH_IMMUNITY")
{ {
subtype = MetaIdentifier(SpellSchool::EARTH); subtype = TBonusSubtype(SpellSchool::EARTH);
switch(deprecatedSubtype) switch(deprecatedSubtype)
{ {
case 0: case 0:

View File

@ -0,0 +1,76 @@
/*
* Bonus.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 "BonusSubtypeID.h"
VCMI_LIB_NAMESPACE_BEGIN
const BonusSubtypeID BonusSubtypeID::creatureDamageBoth(0);
const BonusSubtypeID BonusSubtypeID::creatureDamageMin(1);
const BonusSubtypeID BonusSubtypeID::creatureDamageMax(2);
const BonusSubtypeID BonusSubtypeID::damageTypeAll(-1);
const BonusSubtypeID BonusSubtypeID::damageTypeMelee(0);
const BonusSubtypeID BonusSubtypeID::damageTypeRanged(1);
const BonusSubtypeID BonusSubtypeID::heroMovementLand(1);
const BonusSubtypeID BonusSubtypeID::heroMovementSea(0);
const BonusSubtypeID BonusSubtypeID::heroMovementPenalty(2);
const BonusSubtypeID BonusSubtypeID::heroMovementFull(1);
const BonusSubtypeID BonusSubtypeID::deathStareGorgon(0);
const BonusSubtypeID BonusSubtypeID::deathStareCommander(1);
const BonusSubtypeID BonusSubtypeID::rebirthRegular(0);
const BonusSubtypeID BonusSubtypeID::rebirthSpecial(1);
const BonusSubtypeID BonusSubtypeID::visionsMonsters(0);
const BonusSubtypeID BonusSubtypeID::visionsHeroes(1);
const BonusSubtypeID BonusSubtypeID::visionsTowns(2);
const BonusSubtypeID BonusSubtypeID::immunityBattleWide(0);
const BonusSubtypeID BonusSubtypeID::immunityEnemyHero(1);
const BonusSubtypeID BonusSubtypeID::transmutationPerHealth(0);
const BonusSubtypeID BonusSubtypeID::transmutationPerUnit(1);
const BonusSubtypeID BonusSubtypeID::destructionKillPercentage(0);
const BonusSubtypeID BonusSubtypeID::destructionKillAmount(1);
const BonusSubtypeID BonusSubtypeID::soulStealPermanent(0);
const BonusSubtypeID BonusSubtypeID::soulStealBattle(1);
const BonusSubtypeID BonusSubtypeID::movementFlying(0);
const BonusSubtypeID BonusSubtypeID::movementTeleporting(1);
const BonusSourceID BonusSourceID::undeadMoraleDebuff(-2);
BonusSubtypeID BonusSubtypeID::spellLevel(int level)
{
return BonusSubtypeID(level);
}
BonusSubtypeID BonusSubtypeID::creatureLevel(int level)
{
return BonusSubtypeID(level);
}
si32 BonusSubtypeID::decode(const std::string & identifier)
{
return std::stoi(identifier);
}
std::string BonusSubtypeID::encode(const si32 index)
{
return std::to_string(index);
}
si32 BonusSourceID::decode(const std::string & identifier)
{
return std::stoi(identifier);
}
std::string BonusSourceID::encode(const si32 index)
{
return std::to_string(index);
}
VCMI_LIB_NAMESPACE_END

View File

@ -0,0 +1,78 @@
/*
* BonusSubtypeID.h, 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
*
*/
#pragma once
#include "../constants/EntityIdentifiers.h"
VCMI_LIB_NAMESPACE_BEGIN
class DLL_LINKAGE BonusSourceID : public Identifier<BonusSourceID>
{
public:
using Identifier<BonusSourceID>::Identifier;
static std::string encode(int32_t index);
static si32 decode(const std::string & identifier);
static const BonusSourceID undeadMoraleDebuff; // -2
};
class DLL_LINKAGE BonusSubtypeID : public Identifier<BonusSubtypeID>
{
public:
using Identifier<BonusSubtypeID>::Identifier;
static std::string encode(int32_t index);
static si32 decode(const std::string & identifier);
static const BonusSubtypeID creatureDamageBoth; // 0
static const BonusSubtypeID creatureDamageMin; // 1
static const BonusSubtypeID creatureDamageMax; // 2
static const BonusSubtypeID damageTypeAll; // -1
static const BonusSubtypeID damageTypeMelee; // 0
static const BonusSubtypeID damageTypeRanged; // 1
static const BonusSubtypeID heroMovementLand; // 1
static const BonusSubtypeID heroMovementSea; // 0
static const BonusSubtypeID heroMovementPenalty; // 2
static const BonusSubtypeID heroMovementFull; // 1
static const BonusSubtypeID deathStareGorgon; // 0
static const BonusSubtypeID deathStareCommander;
static const BonusSubtypeID rebirthRegular; // 0
static const BonusSubtypeID rebirthSpecial; // 1
static const BonusSubtypeID visionsMonsters; // 0
static const BonusSubtypeID visionsHeroes; // 1
static const BonusSubtypeID visionsTowns; // 2
static const BonusSubtypeID immunityBattleWide; // 0
static const BonusSubtypeID immunityEnemyHero; // 1
static const BonusSubtypeID transmutationPerHealth; // 0
static const BonusSubtypeID transmutationPerUnit; // 1
static const BonusSubtypeID destructionKillPercentage; // 0
static const BonusSubtypeID destructionKillAmount; // 1
static const BonusSubtypeID soulStealPermanent; // 0
static const BonusSubtypeID soulStealBattle; // 1
static const BonusSubtypeID movementFlying; // 0
static const BonusSubtypeID movementTeleporting; // 1
static BonusSubtypeID spellLevel(int level);
static BonusSubtypeID creatureLevel(int level);
};
VCMI_LIB_NAMESPACE_END

View File

@ -1,56 +0,0 @@
/*
* Bonus.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 "BonusSubtypes.h"
VCMI_LIB_NAMESPACE_BEGIN
const TBonusSubtype BonusSubtypes::creatureDamageBoth("", "", 0);
const TBonusSubtype BonusSubtypes::creatureDamageMin("", "", 1);
const TBonusSubtype BonusSubtypes::creatureDamageMax("", "", 2);
const TBonusSubtype BonusSubtypes::damageTypeAll("", "", -1);
const TBonusSubtype BonusSubtypes::damageTypeMelee("", "", 0);
const TBonusSubtype BonusSubtypes::damageTypeRanged("", "", 1);
const TBonusSubtype BonusSubtypes::heroMovementLand("", "", 1);
const TBonusSubtype BonusSubtypes::heroMovementSea("", "", 0);
const TBonusSubtype BonusSubtypes::heroMovementPenalty("", "", 2);
const TBonusSubtype BonusSubtypes::heroMovementFull("", "", 1);
const TBonusSubtype BonusSubtypes::deathStareGorgon("", "", 0);
const TBonusSubtype BonusSubtypes::deathStareCommander("", "", 1);
const TBonusSubtype BonusSubtypes::rebirthRegular("", "", 0);
const TBonusSubtype BonusSubtypes::rebirthSpecial("", "", 1);
const TBonusSubtype BonusSubtypes::visionsMonsters("", "", 0);
const TBonusSubtype BonusSubtypes::visionsHeroes("", "", 1);
const TBonusSubtype BonusSubtypes::visionsTowns("", "", 2);
const TBonusSubtype BonusSubtypes::immunityBattleWide("", "", 0);
const TBonusSubtype BonusSubtypes::immunityEnemyHero("", "", 1);
const TBonusSubtype BonusSubtypes::transmutationPerHealth("", "", 0);
const TBonusSubtype BonusSubtypes::transmutationPerUnit("", "", 1);
const TBonusSubtype BonusSubtypes::destructionKillPercentage("", "", 0);
const TBonusSubtype BonusSubtypes::destructionKillAmount("", "", 1);
const TBonusSubtype BonusSubtypes::soulStealPermanent("", "", 0);
const TBonusSubtype BonusSubtypes::soulStealBattle("", "", 1);
const TBonusSubtype BonusSubtypes::movementFlying("", "", 0);
const TBonusSubtype BonusSubtypes::movementTeleporting("", "", 1);
TBonusSubtype BonusSubtypes::spellLevel(int level)
{
assert(0); //todo
return TBonusSubtype();
}
TBonusSubtype BonusSubtypes::creatureLevel(int level)
{
assert(0); //todo
return TBonusSubtype();
}
VCMI_LIB_NAMESPACE_END

View File

@ -1,64 +0,0 @@
/*
* BonusSubtypes.h, 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
*
*/
#pragma once
#include "../constants/MetaIdentifier.h"
VCMI_LIB_NAMESPACE_BEGIN
using TBonusSubtype = MetaIdentifier;
class DLL_LINKAGE BonusSubtypes
{
public:
static const TBonusSubtype creatureDamageBoth; // 0
static const TBonusSubtype creatureDamageMin; // 1
static const TBonusSubtype creatureDamageMax; // 2
static const TBonusSubtype damageTypeAll; // -1
static const TBonusSubtype damageTypeMelee; // 0
static const TBonusSubtype damageTypeRanged; // 1
static const TBonusSubtype heroMovementLand; // 1
static const TBonusSubtype heroMovementSea; // 0
static const TBonusSubtype heroMovementPenalty; // 2
static const TBonusSubtype heroMovementFull; // 1
static const TBonusSubtype deathStareGorgon; // 0
static const TBonusSubtype deathStareCommander;
static const TBonusSubtype rebirthRegular; // 0
static const TBonusSubtype rebirthSpecial; // 1
static const TBonusSubtype visionsMonsters; // 0
static const TBonusSubtype visionsHeroes; // 1
static const TBonusSubtype visionsTowns; // 2
static const TBonusSubtype immunityBattleWide; // 0
static const TBonusSubtype immunityEnemyHero; // 1
static const TBonusSubtype transmutationPerHealth; // 0
static const TBonusSubtype transmutationPerUnit; // 1
static const TBonusSubtype destructionKillPercentage; // 0
static const TBonusSubtype destructionKillAmount; // 1
static const TBonusSubtype soulStealPermanent; // 0
static const TBonusSubtype soulStealBattle; // 1
static const TBonusSubtype movementFlying; // 0
static const TBonusSubtype movementTeleporting; // 1
static TBonusSubtype spellLevel(int level);
static TBonusSubtype creatureLevel(int level);
};
VCMI_LIB_NAMESPACE_END

View File

@ -37,6 +37,8 @@
#include "TerrainHandler.h" //TODO: remove #include "TerrainHandler.h" //TODO: remove
#include "BattleFieldHandler.h" #include "BattleFieldHandler.h"
#include "ObstacleHandler.h" #include "ObstacleHandler.h"
#include "CTownHandler.h"
#include "mapObjectConstructors/CObjectClassesHandler.h"
VCMI_LIB_NAMESPACE_BEGIN VCMI_LIB_NAMESPACE_BEGIN
@ -134,6 +136,40 @@ std::string HeroClassID::entityType()
return "heroClass"; return "heroClass";
} }
si32 ObjectInstanceID::decode(const std::string & identifier)
{
return std::stoi(identifier);
}
std::string ObjectInstanceID::encode(const si32 index)
{
return std::to_string(index);
}
si32 CampaignScenarioID::decode(const std::string & identifier)
{
return std::stoi(identifier);
}
std::string CampaignScenarioID::encode(const si32 index)
{
return std::to_string(index);
}
std::string Obj::encode(int32_t index)
{
return VLC->objtypeh->getObjectHandlerName(index);
}
si32 Obj::decode(const std::string & identifier)
{
auto rawId = VLC->identifiers()->getIdentifier(ModScope::scopeGame(), "objects", identifier);
if(rawId)
return rawId.value();
else
return -1;
}
si32 HeroTypeID::decode(const std::string & identifier) si32 HeroTypeID::decode(const std::string & identifier)
{ {
auto rawId = VLC->identifiers()->getIdentifier(ModScope::scopeMap(), "hero", identifier); auto rawId = VLC->identifiers()->getIdentifier(ModScope::scopeMap(), "hero", identifier);
@ -182,6 +218,20 @@ std::string ArtifactID::entityType()
return "artifact"; return "artifact";
} }
si32 SecondarySkill::decode(const std::string& identifier)
{
auto rawId = VLC->identifiers()->getIdentifier(ModScope::scopeGame(), "secondarySkill", identifier);
if(rawId)
return rawId.value();
else
return -1;
}
std::string SecondarySkill::encode(const si32 index)
{
return VLC->skills()->getById(SecondarySkill(index))->getJsonKey();
}
const CCreature * CreatureIDBase::toCreature() const const CCreature * CreatureIDBase::toCreature() const
{ {
return VLC->creh->objects.at(num); return VLC->creh->objects.at(num);
@ -240,6 +290,20 @@ std::string SpellID::encode(const si32 index)
return VLC->spells()->getByIndex(index)->getJsonKey(); return VLC->spells()->getByIndex(index)->getJsonKey();
} }
si32 BattleField::decode(const std::string & identifier)
{
auto rawId = VLC->identifiers()->getIdentifier(ModScope::scopeGame(), "spell", identifier);
if(rawId)
return rawId.value();
else
return -1;
}
std::string BattleField::encode(const si32 index)
{
return VLC->spells()->getByIndex(index)->getJsonKey();
}
std::string SpellID::entityType() std::string SpellID::entityType()
{ {
return "spell"; return "spell";
@ -257,8 +321,6 @@ bool PlayerColor::isSpectator() const
std::string PlayerColor::toString() const std::string PlayerColor::toString() const
{ {
if (num == -1)
return "neutral";
return encode(num); return encode(num);
} }
@ -269,6 +331,9 @@ si32 PlayerColor::decode(const std::string & identifier)
std::string PlayerColor::encode(const si32 index) std::string PlayerColor::encode(const si32 index)
{ {
if (index == -1)
return "neutral";
if (index < 0 || index >= std::size(GameConstants::PLAYER_COLOR_NAMES)) if (index < 0 || index >= std::size(GameConstants::PLAYER_COLOR_NAMES))
{ {
assert(0); assert(0);
@ -373,6 +438,18 @@ std::string GameResID::encode(const si32 index)
return GameConstants::RESOURCE_NAMES[index]; return GameConstants::RESOURCE_NAMES[index];
} }
si32 BuildingTypeUniqueID::decode(const std::string & identifier)
{
assert(0); //TODO
return -1;
}
std::string BuildingTypeUniqueID::encode(const si32 index)
{
assert(0); // TODO
return "";
}
std::string GameResID::entityType() std::string GameResID::entityType()
{ {
return "resource"; return "resource";

View File

@ -552,10 +552,13 @@ public:
}; };
}; };
class Obj : public IdentifierWithEnum<Obj, ObjBase> class DLL_LINKAGE Obj : public IdentifierWithEnum<Obj, ObjBase>
{ {
public: public:
using IdentifierWithEnum<Obj, ObjBase>::IdentifierWithEnum; using IdentifierWithEnum<Obj, ObjBase>::IdentifierWithEnum;
static std::string encode(int32_t index);
static si32 decode(const std::string & identifier);
}; };
class DLL_LINKAGE RoadId : public Identifier<RoadId> class DLL_LINKAGE RoadId : public Identifier<RoadId>
@ -830,6 +833,9 @@ public:
static const BattleField NONE; static const BattleField NONE;
const BattleFieldInfo * getInfo() const; const BattleFieldInfo * getInfo() const;
static si32 decode(const std::string & identifier);
static std::string encode(const si32 index);
}; };
class DLL_LINKAGE BoatId : public Identifier<BoatId> class DLL_LINKAGE BoatId : public Identifier<BoatId>
@ -935,6 +941,9 @@ class BuildingTypeUniqueID : public Identifier<BuildingTypeUniqueID>
public: public:
BuildingTypeUniqueID(FactionID faction, BuildingID building ); BuildingTypeUniqueID(FactionID faction, BuildingID building );
static si32 decode(const std::string & identifier);
static std::string encode(const si32 index);
BuildingID getBuilding() const; BuildingID getBuilding() const;
FactionID getFaction() const; FactionID getFaction() const;
@ -946,6 +955,9 @@ class DLL_LINKAGE CampaignScenarioID : public Identifier<CampaignScenarioID>
public: public:
using Identifier<CampaignScenarioID>::Identifier; using Identifier<CampaignScenarioID>::Identifier;
static si32 decode(const std::string & identifier);
static std::string encode(int32_t index);
static const CampaignScenarioID NONE; static const CampaignScenarioID NONE;
}; };

View File

@ -1,67 +0,0 @@
/*
* EntityIdentifiers.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 "MetaIdentifier.h"
VCMI_LIB_NAMESPACE_BEGIN
const MetaIdentifier MetaIdentifier::NONE("", "", -1);
MetaIdentifier::MetaIdentifier():
integerForm(-1)
{}
MetaIdentifier::MetaIdentifier(const std::string & entityType, const std::string & identifier)
: stringForm(identifier)
, integerForm(-1)
{
onDeserialized();
}
MetaIdentifier::MetaIdentifier(const std::string & entityType, const std::string & identifier, int32_t value)
: stringForm(identifier)
, integerForm(value)
{
}
bool MetaIdentifier::operator == (const MetaIdentifier & other) const
{
assert( (stringForm == other.stringForm) ? (integerForm == other.integerForm) : true );
return stringForm == other.stringForm;
}
bool MetaIdentifier::operator != (const MetaIdentifier & other) const
{
return !(*this == other);
}
bool MetaIdentifier::operator < (const MetaIdentifier & other) const
{
assert(0);
}
int32_t MetaIdentifier::getNum() const
{
return integerForm;
}
std::string MetaIdentifier::toString() const
{
return stringForm;
}
void MetaIdentifier::onDeserialized()
{
assert(0); //TODO
}
VCMI_LIB_NAMESPACE_END

View File

@ -14,49 +14,69 @@
VCMI_LIB_NAMESPACE_BEGIN VCMI_LIB_NAMESPACE_BEGIN
/// This class represents field that may contain value of multiple different identifer types /// This class represents field that may contain value of multiple different identifer types
template<typename... Types>
class DLL_LINKAGE MetaIdentifier class DLL_LINKAGE MetaIdentifier
{ {
std::string stringForm; std::variant<Types...> value;
int32_t integerForm;
void onDeserialized();
public: public:
static const MetaIdentifier NONE; MetaIdentifier()
{}
MetaIdentifier();
MetaIdentifier(const std::string & entityType, const std::string & identifier);
MetaIdentifier(const std::string & entityType, const std::string & identifier, int32_t value);
template<typename IdentifierType> template<typename IdentifierType>
explicit MetaIdentifier(const IdentifierType & identifier) MetaIdentifier(const IdentifierType & identifier)
: integerForm(identifier.getNum()) : value(identifier)
{}
int32_t getNum() const
{ {
static_assert(std::is_base_of<IdentifierBase, IdentifierType>::value, "MetaIdentifier can only be constructed from Identifer class"); std::optional<int32_t> result;
std::visit([&result] (const auto& v) { result = v.getNum(); }, value);
assert(result.has_value());
return result.value_or(-1);
} }
int32_t getNum() const; std::string toString() const
std::string toString() const; {
std::optional<std::string> result;
std::visit([&result] (const auto& v) { result = v.encode(v.getNum()); }, value);
assert(result.has_value());
return result.value_or("");
}
template<typename IdentifierType> template<typename IdentifierType>
IdentifierType as() const IdentifierType as() const
{ {
static_assert(std::is_base_of<IdentifierBase, IdentifierType>::value, "MetaIdentifier can only be converted to Identifer class"); auto * result = std::get_if<IdentifierType>(&value);
IdentifierType result(integerForm); assert(result);
return result;
if (result)
return *result;
else
return IdentifierType();
} }
template <typename Handler> void serialize(Handler &h, const int version) template <typename Handler> void serialize(Handler &h, const int version)
{ {
h & integerForm; h & value;
if (!h.saving)
onDeserialized();
} }
bool operator == (const MetaIdentifier & other) const; bool operator == (const MetaIdentifier & other) const
bool operator != (const MetaIdentifier & other) const; {
bool operator < (const MetaIdentifier & other) const; return value == other.value;
}
bool operator != (const MetaIdentifier & other) const
{
return value != other.value;
}
bool operator < (const MetaIdentifier & other) const
{
return value < other.value;
}
}; };
VCMI_LIB_NAMESPACE_END VCMI_LIB_NAMESPACE_END

View File

@ -655,7 +655,7 @@ void CGameState::initGlobalBonuses()
{ {
auto bonus = JsonUtils::parseBonus(b.second); auto bonus = JsonUtils::parseBonus(b.second);
bonus->source = BonusSource::GLOBAL;//for all bonus->source = BonusSource::GLOBAL;//for all
bonus->sid = TBonusSourceID::NONE; //there is one global object bonus->sid = TBonusSourceID(); //there is one global object
globalEffects.addNewBonus(bonus); globalEffects.addNewBonus(bonus);
} }
VLC->creh->loadCrExpBon(globalEffects); VLC->creh->loadCrExpBon(globalEffects);

View File

@ -488,4 +488,9 @@ std::string CObjectClassesHandler::getObjectHandlerName(si32 type) const
return objects.at(type)->handlerName; return objects.at(type)->handlerName;
} }
std::string CObjectClassesHandler::getJsonKey(si32 type) const
{
return objects.at(type)->getJsonKey();
}
VCMI_LIB_NAMESPACE_END VCMI_LIB_NAMESPACE_END

View File

@ -129,6 +129,8 @@ public:
/// Returns handler string describing the handler (for use in client) /// Returns handler string describing the handler (for use in client)
std::string getObjectHandlerName(si32 type) const; std::string getObjectHandlerName(si32 type) const;
std::string getJsonKey(si32 type) const;
template <typename Handler> void serialize(Handler &h, const int version) template <typename Handler> void serialize(Handler &h, const int version)
{ {
h & objects; h & objects;

View File

@ -59,7 +59,7 @@ void CArmedInstance::updateMoraleBonusFromArmy()
auto b = getExportedBonusList().getFirst(Selector::sourceType()(BonusSource::ARMY).And(Selector::type()(BonusType::MORALE))); auto b = getExportedBonusList().getFirst(Selector::sourceType()(BonusSource::ARMY).And(Selector::type()(BonusType::MORALE)));
if(!b) if(!b)
{ {
b = std::make_shared<Bonus>(BonusDuration::PERMANENT, BonusType::MORALE, BonusSource::ARMY, 0, TBonusSourceID::NONE); b = std::make_shared<Bonus>(BonusDuration::PERMANENT, BonusType::MORALE, BonusSource::ARMY, 0, TBonusSourceID());
addNewBonus(b); addNewBonus(b);
} }
@ -120,13 +120,12 @@ void CArmedInstance::updateMoraleBonusFromArmy()
CBonusSystemNode::treeHasChanged(); CBonusSystemNode::treeHasChanged();
//-1 modifier for any Undead unit in army //-1 modifier for any Undead unit in army
const TBonusSourceID UNDEAD_MODIFIER_ID( "", "", -2); auto undeadModifier = getExportedBonusList().getFirst(Selector::source(BonusSource::ARMY, BonusSourceID::undeadMoraleDebuff));
auto undeadModifier = getExportedBonusList().getFirst(Selector::source(BonusSource::ARMY, UNDEAD_MODIFIER_ID));
if(hasUndead) if(hasUndead)
{ {
if(!undeadModifier) if(!undeadModifier)
{ {
undeadModifier = std::make_shared<Bonus>(BonusDuration::PERMANENT, BonusType::MORALE, BonusSource::ARMY, -1, UNDEAD_MODIFIER_ID, VLC->generaltexth->arraytxt[116]); undeadModifier = std::make_shared<Bonus>(BonusDuration::PERMANENT, BonusType::MORALE, BonusSource::ARMY, -1, BonusSourceID::undeadMoraleDebuff, VLC->generaltexth->arraytxt[116]);
undeadModifier->description = undeadModifier->description.substr(0, undeadModifier->description.size()-2);//trim value undeadModifier->description = undeadModifier->description.substr(0, undeadModifier->description.size()-2);//trim value
addNewBonus(undeadModifier); addNewBonus(undeadModifier);
} }

View File

@ -16,7 +16,6 @@
#include "../CConfigHandler.h" #include "../CConfigHandler.h"
#include "../GameSettings.h" #include "../GameSettings.h"
#include "../IGameCallback.h" #include "../IGameCallback.h"
#include "../bonuses/BonusSubtypes.h"
#include "../serializer/JsonSerializeFormat.h" #include "../serializer/JsonSerializeFormat.h"
VCMI_LIB_NAMESPACE_BEGIN VCMI_LIB_NAMESPACE_BEGIN
@ -47,7 +46,7 @@ std::string CGCreature::getHoverText(PlayerColor player) const
std::string CGCreature::getHoverText(const CGHeroInstance * hero) const std::string CGCreature::getHoverText(const CGHeroInstance * hero) const
{ {
std::string hoverName; std::string hoverName;
if(hero->hasVisions(this, BonusSubtypes::visionsMonsters)) if(hero->hasVisions(this, BonusSubtypeID::visionsMonsters))
{ {
MetaString ms; MetaString ms;
ms.appendNumber(stacks.begin()->second->count); ms.appendNumber(stacks.begin()->second->count);

View File

@ -37,7 +37,6 @@
#include "../modding/ModScope.h" #include "../modding/ModScope.h"
#include "../constants/StringConstants.h" #include "../constants/StringConstants.h"
#include "../battle/Unit.h" #include "../battle/Unit.h"
#include "../bonuses/BonusSubtypes.h"
VCMI_LIB_NAMESPACE_BEGIN VCMI_LIB_NAMESPACE_BEGIN
@ -250,14 +249,14 @@ void CGHeroInstance::updateArmyMovementBonus(bool onLand, const TurnInfo * ti) c
lowestCreatureSpeed = realLowestSpeed; lowestCreatureSpeed = realLowestSpeed;
//Let updaters run again //Let updaters run again
treeHasChanged(); treeHasChanged();
ti->updateHeroBonuses(BonusType::MOVEMENT, Selector::subtype()(onLand ? BonusSubtypes::heroMovementLand : BonusSubtypes::heroMovementSea)); ti->updateHeroBonuses(BonusType::MOVEMENT, Selector::subtype()(onLand ? BonusSubtypeID::heroMovementLand : BonusSubtypeID::heroMovementSea));
} }
} }
int CGHeroInstance::movementPointsLimitCached(bool onLand, const TurnInfo * ti) const int CGHeroInstance::movementPointsLimitCached(bool onLand, const TurnInfo * ti) const
{ {
updateArmyMovementBonus(onLand, ti); updateArmyMovementBonus(onLand, ti);
return ti->valOfBonuses(BonusType::MOVEMENT, onLand ? BonusSubtypes::heroMovementLand : BonusSubtypes::heroMovementSea); return ti->valOfBonuses(BonusType::MOVEMENT, onLand ? BonusSubtypeID::heroMovementLand : BonusSubtypeID::heroMovementSea);
} }
CGHeroInstance::CGHeroInstance(): CGHeroInstance::CGHeroInstance():
@ -764,7 +763,7 @@ bool CGHeroInstance::canCastThisSpell(const spells::Spell * spell) const
} }
}); });
const bool levelBonus = hasBonusOfType(BonusType::SPELLS_OF_LEVEL, BonusSubtypes::spellLevel(spell->getLevel())); const bool levelBonus = hasBonusOfType(BonusType::SPELLS_OF_LEVEL, BonusSubtypeID::spellLevel(spell->getLevel()));
if(spell->isSpecial()) if(spell->isSpecial())
{ {

View File

@ -15,7 +15,6 @@
#include "../NetPacks.h" #include "../NetPacks.h"
#include "../IGameCallback.h" #include "../IGameCallback.h"
#include "../gameState/CGameState.h" #include "../gameState/CGameState.h"
#include "../bonuses/BonusSubtypes.h"
VCMI_LIB_NAMESPACE_BEGIN VCMI_LIB_NAMESPACE_BEGIN
@ -147,7 +146,7 @@ void COPWBonus::onHeroVisit (const CGHeroInstance * h) const
if(!h->hasBonusFrom(BonusSource::OBJECT, TBonusSourceID(Obj(Obj::STABLES)))) //does not stack with advMap Stables if(!h->hasBonusFrom(BonusSource::OBJECT, TBonusSourceID(Obj(Obj::STABLES)))) //does not stack with advMap Stables
{ {
GiveBonus gb; GiveBonus gb;
gb.bonus = Bonus(BonusDuration::ONE_WEEK, BonusType::MOVEMENT, BonusSource::OBJECT, 600, TBonusSourceID(Obj(Obj::STABLES)), BonusSubtypes::heroMovementLand, VLC->generaltexth->arraytxt[100]); gb.bonus = Bonus(BonusDuration::ONE_WEEK, BonusType::MOVEMENT, BonusSource::OBJECT, 600, TBonusSourceID(Obj(Obj::STABLES)), BonusSubtypeID::heroMovementLand, VLC->generaltexth->arraytxt[100]);
gb.id = heroID.getNum(); gb.id = heroID.getNum();
cb->giveHeroBonus(&gb); cb->giveHeroBonus(&gb);

View File

@ -13,7 +13,6 @@
#include "CGTownBuilding.h" #include "CGTownBuilding.h"
#include "../spells/CSpellHandler.h" #include "../spells/CSpellHandler.h"
#include "../bonuses/Bonus.h" #include "../bonuses/Bonus.h"
#include "../bonuses/BonusSubtypes.h"
#include "../battle/IBattleInfoCallback.h" #include "../battle/IBattleInfoCallback.h"
#include "../NetPacks.h" #include "../NetPacks.h"
#include "../CConfigHandler.h" #include "../CConfigHandler.h"
@ -161,7 +160,7 @@ GrowthInfo CGTownInstance::getGrowthInfo(int level) const
} }
//other *-of-legion-like bonuses (%d to growth cumulative with grail) //other *-of-legion-like bonuses (%d to growth cumulative with grail)
TConstBonusListPtr bonuses = getBonuses(Selector::typeSubtype(BonusType::CREATURE_GROWTH, BonusSubtypes::creatureLevel(level))); TConstBonusListPtr bonuses = getBonuses(Selector::typeSubtype(BonusType::CREATURE_GROWTH, BonusSubtypeID::creatureLevel(level)));
for(const auto & b : *bonuses) for(const auto & b : *bonuses)
ret.entries.emplace_back(b->val, b->Description()); ret.entries.emplace_back(b->val, b->Description());
@ -788,7 +787,7 @@ void CGTownInstance::updateMoraleBonusFromArmy()
auto b = getExportedBonusList().getFirst(Selector::sourceType()(BonusSource::ARMY).And(Selector::type()(BonusType::MORALE))); auto b = getExportedBonusList().getFirst(Selector::sourceType()(BonusSource::ARMY).And(Selector::type()(BonusType::MORALE)));
if(!b) if(!b)
{ {
b = std::make_shared<Bonus>(BonusDuration::PERMANENT, BonusType::MORALE, BonusSource::ARMY, 0, TBonusSourceID::NONE); b = std::make_shared<Bonus>(BonusDuration::PERMANENT, BonusType::MORALE, BonusSource::ARMY, 0, TBonusSourceID());
addNewBonus(b); addNewBonus(b);
} }

View File

@ -25,7 +25,6 @@
#include "../mapObjectConstructors/AObjectTypeHandler.h" #include "../mapObjectConstructors/AObjectTypeHandler.h"
#include "../mapObjectConstructors/CObjectClassesHandler.h" #include "../mapObjectConstructors/CObjectClassesHandler.h"
#include "../modding/ModScope.h" #include "../modding/ModScope.h"
#include "../bonuses/BonusSubtypes.h"
VCMI_LIB_NAMESPACE_BEGIN VCMI_LIB_NAMESPACE_BEGIN
@ -1205,7 +1204,7 @@ void CGLighthouse::giveBonusTo(const PlayerColor & player, bool onInit) const
gb.bonus.duration = BonusDuration::PERMANENT; gb.bonus.duration = BonusDuration::PERMANENT;
gb.bonus.source = BonusSource::OBJECT; gb.bonus.source = BonusSource::OBJECT;
gb.bonus.sid = TBonusSourceID(id); gb.bonus.sid = TBonusSourceID(id);
gb.bonus.subtype = BonusSubtypes::heroMovementSea; gb.bonus.subtype = BonusSubtypeID::heroMovementSea;
// FIXME: This is really dirty hack // FIXME: This is really dirty hack
// Proper fix would be to make CGLighthouse into bonus system node // Proper fix would be to make CGLighthouse into bonus system node

View File

@ -73,7 +73,7 @@ bool TurnInfo::isLayerAvailable(const EPathfindingLayer & layer) const
bool TurnInfo::hasBonusOfType(BonusType type) const bool TurnInfo::hasBonusOfType(BonusType type) const
{ {
return hasBonusOfType(type, TBonusSubtype::NONE); return hasBonusOfType(type, TBonusSubtype());
} }
bool TurnInfo::hasBonusOfType(BonusType type, TBonusSubtype subtype) const bool TurnInfo::hasBonusOfType(BonusType type, TBonusSubtype subtype) const
@ -96,7 +96,7 @@ bool TurnInfo::hasBonusOfType(BonusType type, TBonusSubtype subtype) const
int TurnInfo::valOfBonuses(BonusType type) const int TurnInfo::valOfBonuses(BonusType type) const
{ {
return valOfBonuses(type, TBonusSubtype::NONE); return valOfBonuses(type, TBonusSubtype());
} }
int TurnInfo::valOfBonuses(BonusType type, TBonusSubtype subtype) const int TurnInfo::valOfBonuses(BonusType type, TBonusSubtype subtype) const

View File

@ -17,7 +17,6 @@
#include "../battle/Unit.h" #include "../battle/Unit.h"
#include "../bonuses/BonusParams.h" #include "../bonuses/BonusParams.h"
#include "../bonuses/BonusList.h" #include "../bonuses/BonusList.h"
#include "../bonuses/BonusSubtypes.h"
#include "../modding/IdentifierStorage.h" #include "../modding/IdentifierStorage.h"
#include "../modding/ModUtility.h" #include "../modding/ModUtility.h"
@ -293,8 +292,8 @@ class ImmunityNegationCondition : public TargetConditionItemBase
protected: protected:
bool check(const Mechanics * m, const battle::Unit * target) const override bool check(const Mechanics * m, const battle::Unit * target) const override
{ {
const bool battleWideNegation = target->hasBonusOfType(BonusType::NEGATE_ALL_NATURAL_IMMUNITIES, BonusSubtypes::immunityBattleWide); const bool battleWideNegation = target->hasBonusOfType(BonusType::NEGATE_ALL_NATURAL_IMMUNITIES, BonusSubtypeID::immunityBattleWide);
const bool heroNegation = target->hasBonusOfType(BonusType::NEGATE_ALL_NATURAL_IMMUNITIES, BonusSubtypes::immunityEnemyHero); const bool heroNegation = target->hasBonusOfType(BonusType::NEGATE_ALL_NATURAL_IMMUNITIES, BonusSubtypeID::immunityEnemyHero);
//Non-magical effects is not affected by orb of vulnerability //Non-magical effects is not affected by orb of vulnerability
if(!m->isMagicalEffect()) if(!m->isMagicalEffect())
return false; return false;

View File

@ -20,7 +20,6 @@
#include "../../lib/battle/CBattleInfoCallback.h" #include "../../lib/battle/CBattleInfoCallback.h"
#include "../../lib/battle/IBattleState.h" #include "../../lib/battle/IBattleState.h"
#include "../../lib/battle/BattleAction.h" #include "../../lib/battle/BattleAction.h"
#include "../../lib/bonuses/BonusSubtypes.h"
#include "../../lib/gameState/CGameState.h" #include "../../lib/gameState/CGameState.h"
#include "../../lib/NetPacks.h" #include "../../lib/NetPacks.h"
#include "../../lib/spells/AbilityCaster.h" #include "../../lib/spells/AbilityCaster.h"
@ -163,9 +162,9 @@ bool BattleActionProcessor::doDefendAction(const CBattleInfoCallback & battle, c
SetStackEffect sse; SetStackEffect sse;
sse.battleID = battle.getBattle()->getBattleID(); sse.battleID = battle.getBattle()->getBattleID();
Bonus defenseBonusToAdd(BonusDuration::STACK_GETS_TURN, BonusType::PRIMARY_SKILL, BonusSource::OTHER, 20, TBonusSourceID::NONE, TBonusSubtype(PrimarySkill::DEFENSE), BonusValueType::PERCENT_TO_ALL); Bonus defenseBonusToAdd(BonusDuration::STACK_GETS_TURN, BonusType::PRIMARY_SKILL, BonusSource::OTHER, 20, TBonusSourceID(), TBonusSubtype(PrimarySkill::DEFENSE), BonusValueType::PERCENT_TO_ALL);
Bonus bonus2(BonusDuration::STACK_GETS_TURN, BonusType::PRIMARY_SKILL, BonusSource::OTHER, stack->valOfBonuses(BonusType::DEFENSIVE_STANCE), TBonusSourceID::NONE, TBonusSubtype(PrimarySkill::DEFENSE), BonusValueType::ADDITIVE_VALUE); Bonus bonus2(BonusDuration::STACK_GETS_TURN, BonusType::PRIMARY_SKILL, BonusSource::OTHER, stack->valOfBonuses(BonusType::DEFENSIVE_STANCE), TBonusSourceID(), TBonusSubtype(PrimarySkill::DEFENSE), BonusValueType::ADDITIVE_VALUE);
Bonus alternativeWeakCreatureBonus(BonusDuration::STACK_GETS_TURN, BonusType::PRIMARY_SKILL, BonusSource::OTHER, 1, TBonusSourceID::NONE, TBonusSubtype(PrimarySkill::DEFENSE), BonusValueType::ADDITIVE_VALUE); Bonus alternativeWeakCreatureBonus(BonusDuration::STACK_GETS_TURN, BonusType::PRIMARY_SKILL, BonusSource::OTHER, 1, TBonusSourceID(), TBonusSubtype(PrimarySkill::DEFENSE), BonusValueType::ADDITIVE_VALUE);
BonusList defence = *stack->getBonuses(Selector::typeSubtype(BonusType::PRIMARY_SKILL, TBonusSubtype(PrimarySkill::DEFENSE))); BonusList defence = *stack->getBonuses(Selector::typeSubtype(BonusType::PRIMARY_SKILL, TBonusSubtype(PrimarySkill::DEFENSE)));
int oldDefenceValue = defence.totalValue(); int oldDefenceValue = defence.totalValue();
@ -383,7 +382,7 @@ bool BattleActionProcessor::doCatapultAction(const CBattleInfoCallback & battle,
return false; return false;
std::shared_ptr<const Bonus> catapultAbility = stack->getBonusLocalFirst(Selector::type()(BonusType::CATAPULT)); std::shared_ptr<const Bonus> catapultAbility = stack->getBonusLocalFirst(Selector::type()(BonusType::CATAPULT));
if(!catapultAbility || catapultAbility->subtype == TBonusSubtype::NONE) if(!catapultAbility || catapultAbility->subtype == TBonusSubtype())
{ {
gameHandler->complain("We do not know how to shoot :P"); gameHandler->complain("We do not know how to shoot :P");
} }
@ -453,7 +452,7 @@ bool BattleActionProcessor::doHealAction(const CBattleInfoCallback & battle, con
else else
destStack = battle.battleGetUnitByPos(target.at(0).hexValue); destStack = battle.battleGetUnitByPos(target.at(0).hexValue);
if(stack == nullptr || destStack == nullptr || !healerAbility || healerAbility->subtype == TBonusSubtype::NONE) if(stack == nullptr || destStack == nullptr || !healerAbility || healerAbility->subtype == TBonusSubtype())
{ {
gameHandler->complain("There is either no healer, no destination, or healer cannot heal :P"); gameHandler->complain("There is either no healer, no destination, or healer cannot heal :P");
} }
@ -1169,7 +1168,7 @@ void BattleActionProcessor::handleAfterAttackCasting(const CBattleInfoCallback &
// each gorgon have 10% chance to kill (counted separately in H3) -> binomial distribution // each gorgon have 10% chance to kill (counted separately in H3) -> binomial distribution
//original formula x = min(x, (gorgons_count + 9)/10); //original formula x = min(x, (gorgons_count + 9)/10);
double chanceToKill = attacker->valOfBonuses(BonusType::DEATH_STARE, BonusSubtypes::deathStareGorgon) / 100.0f; double chanceToKill = attacker->valOfBonuses(BonusType::DEATH_STARE, BonusSubtypeID::deathStareGorgon) / 100.0f;
vstd::amin(chanceToKill, 1); //cap at 100% vstd::amin(chanceToKill, 1); //cap at 100%
std::binomial_distribution<> distribution(attacker->getCount(), chanceToKill); std::binomial_distribution<> distribution(attacker->getCount(), chanceToKill);
@ -1180,7 +1179,7 @@ void BattleActionProcessor::handleAfterAttackCasting(const CBattleInfoCallback &
int maxToKill = static_cast<int>((attacker->getCount() + cap - 1) / cap); //not much more than chance * count int maxToKill = static_cast<int>((attacker->getCount() + cap - 1) / cap); //not much more than chance * count
vstd::amin(staredCreatures, maxToKill); vstd::amin(staredCreatures, maxToKill);
staredCreatures += (attacker->level() * attacker->valOfBonuses(BonusType::DEATH_STARE, BonusSubtypes::deathStareCommander)) / defender->level(); staredCreatures += (attacker->level() * attacker->valOfBonuses(BonusType::DEATH_STARE, BonusSubtypeID::deathStareCommander)) / defender->level();
if(staredCreatures) if(staredCreatures)
{ {
//TODO: death stare was not originally available for multiple-hex attacks, but... //TODO: death stare was not originally available for multiple-hex attacks, but...
@ -1250,9 +1249,9 @@ void BattleActionProcessor::handleAfterAttackCasting(const CBattleInfoCallback &
else else
resurrectInfo.type = attacker->creatureId(); resurrectInfo.type = attacker->creatureId();
if(attacker->hasBonusOfType((BonusType::TRANSMUTATION), BonusSubtypes::transmutationPerHealth)) if(attacker->hasBonusOfType((BonusType::TRANSMUTATION), BonusSubtypeID::transmutationPerHealth))
resurrectInfo.count = std::max((defender->getCount() * defender->getMaxHealth()) / resurrectInfo.type.toCreature()->getMaxHealth(), 1u); resurrectInfo.count = std::max((defender->getCount() * defender->getMaxHealth()) / resurrectInfo.type.toCreature()->getMaxHealth(), 1u);
else if (attacker->hasBonusOfType((BonusType::TRANSMUTATION), BonusSubtypes::transmutationPerUnit)) else if (attacker->hasBonusOfType((BonusType::TRANSMUTATION), BonusSubtypeID::transmutationPerUnit))
resurrectInfo.count = defender->getCount(); resurrectInfo.count = defender->getCount();
else else
return; //wrong subtype return; //wrong subtype
@ -1274,21 +1273,21 @@ void BattleActionProcessor::handleAfterAttackCasting(const CBattleInfoCallback &
gameHandler->sendAndApply(&fakeEvent); gameHandler->sendAndApply(&fakeEvent);
} }
if(attacker->hasBonusOfType(BonusType::DESTRUCTION, BonusSubtypes::destructionKillPercentage) || attacker->hasBonusOfType(BonusType::DESTRUCTION, BonusSubtypes::destructionKillAmount)) if(attacker->hasBonusOfType(BonusType::DESTRUCTION, BonusSubtypeID::destructionKillPercentage) || attacker->hasBonusOfType(BonusType::DESTRUCTION, BonusSubtypeID::destructionKillAmount))
{ {
double chanceToTrigger = 0; double chanceToTrigger = 0;
int amountToDie = 0; int amountToDie = 0;
if(attacker->hasBonusOfType(BonusType::DESTRUCTION, BonusSubtypes::destructionKillPercentage)) //killing by percentage if(attacker->hasBonusOfType(BonusType::DESTRUCTION, BonusSubtypeID::destructionKillPercentage)) //killing by percentage
{ {
chanceToTrigger = attacker->valOfBonuses(BonusType::DESTRUCTION, BonusSubtypes::destructionKillPercentage) / 100.0f; chanceToTrigger = attacker->valOfBonuses(BonusType::DESTRUCTION, BonusSubtypeID::destructionKillPercentage) / 100.0f;
int percentageToDie = attacker->getBonus(Selector::type()(BonusType::DESTRUCTION).And(Selector::subtype()(BonusSubtypes::destructionKillPercentage)))->additionalInfo[0]; int percentageToDie = attacker->getBonus(Selector::type()(BonusType::DESTRUCTION).And(Selector::subtype()(BonusSubtypeID::destructionKillPercentage)))->additionalInfo[0];
amountToDie = static_cast<int>(defender->getCount() * percentageToDie * 0.01f); amountToDie = static_cast<int>(defender->getCount() * percentageToDie * 0.01f);
} }
else if(attacker->hasBonusOfType(BonusType::DESTRUCTION, BonusSubtypes::destructionKillAmount)) //killing by count else if(attacker->hasBonusOfType(BonusType::DESTRUCTION, BonusSubtypeID::destructionKillAmount)) //killing by count
{ {
chanceToTrigger = attacker->valOfBonuses(BonusType::DESTRUCTION, BonusSubtypes::destructionKillAmount) / 100.0f; chanceToTrigger = attacker->valOfBonuses(BonusType::DESTRUCTION, BonusSubtypeID::destructionKillAmount) / 100.0f;
amountToDie = attacker->getBonus(Selector::type()(BonusType::DESTRUCTION).And(Selector::subtype()(BonusSubtypes::destructionKillAmount)))->additionalInfo[0]; amountToDie = attacker->getBonus(Selector::type()(BonusType::DESTRUCTION).And(Selector::subtype()(BonusSubtypeID::destructionKillAmount)))->additionalInfo[0];
} }
vstd::amin(chanceToTrigger, 1); //cap trigger chance at 100% vstd::amin(chanceToTrigger, 1); //cap trigger chance at 100%
@ -1349,12 +1348,12 @@ int64_t BattleActionProcessor::applyBattleEffects(const CBattleInfoCallback & ba
{ {
//we can have two bonuses - one with subtype 0 and another with subtype 1 //we can have two bonuses - one with subtype 0 and another with subtype 1
//try to use permanent first, use only one of two //try to use permanent first, use only one of two
for(const auto & subtype : { BonusSubtypes::soulStealBattle, BonusSubtypes::soulStealPermanent}) for(const auto & subtype : { BonusSubtypeID::soulStealBattle, BonusSubtypeID::soulStealPermanent})
{ {
if(attackerState->hasBonusOfType(BonusType::SOUL_STEAL, subtype)) if(attackerState->hasBonusOfType(BonusType::SOUL_STEAL, subtype))
{ {
int64_t toHeal = bsa.killedAmount * attackerState->valOfBonuses(BonusType::SOUL_STEAL, subtype) * attackerState->getMaxHealth(); int64_t toHeal = bsa.killedAmount * attackerState->valOfBonuses(BonusType::SOUL_STEAL, subtype) * attackerState->getMaxHealth();
bool permanent = subtype == BonusSubtypes::soulStealPermanent; bool permanent = subtype == BonusSubtypeID::soulStealPermanent;
attackerState->heal(toHeal, EHealLevel::OVERHEAL, (permanent ? EHealPower::PERMANENT : EHealPower::ONE_BATTLE)); attackerState->heal(toHeal, EHealLevel::OVERHEAL, (permanent ? EHealPower::PERMANENT : EHealPower::ONE_BATTLE));
drainedLife += toHeal; drainedLife += toHeal;
break; break;

View File

@ -16,7 +16,6 @@
#include "../../lib/serializer/Connection.h" #include "../../lib/serializer/Connection.h"
#include "../../lib/CGeneralTextHandler.h" #include "../../lib/CGeneralTextHandler.h"
#include "../../lib/CHeroHandler.h" #include "../../lib/CHeroHandler.h"
#include "../../lib/bonuses/BonusSubtypes.h"
#include "../../lib/modding/IdentifierStorage.h" #include "../../lib/modding/IdentifierStorage.h"
#include "../../lib/CPlayerState.h" #include "../../lib/CPlayerState.h"
#include "../../lib/GameConstants.h" #include "../../lib/GameConstants.h"
@ -141,11 +140,11 @@ void PlayerMessageProcessor::cheatGiveSpells(PlayerColor player, const CGHeroIns
///Give all spells with bonus (to allow banned spells) ///Give all spells with bonus (to allow banned spells)
GiveBonus giveBonus(GiveBonus::ETarget::HERO); GiveBonus giveBonus(GiveBonus::ETarget::HERO);
giveBonus.id = hero->id.getNum(); giveBonus.id = hero->id.getNum();
giveBonus.bonus = Bonus(BonusDuration::PERMANENT, BonusType::SPELLS_OF_LEVEL, BonusSource::OTHER, 0, TBonusSourceID::NONE); giveBonus.bonus = Bonus(BonusDuration::PERMANENT, BonusType::SPELLS_OF_LEVEL, BonusSource::OTHER, 0, TBonusSourceID());
//start with level 0 to skip abilities //start with level 0 to skip abilities
for (int level = 1; level <= GameConstants::SPELL_LEVELS; level++) for (int level = 1; level <= GameConstants::SPELL_LEVELS; level++)
{ {
giveBonus.bonus.subtype = BonusSubtypes::spellLevel(level); giveBonus.bonus.subtype = BonusSubtypeID::spellLevel(level);
gameHandler->sendAndApply(&giveBonus); gameHandler->sendAndApply(&giveBonus);
} }

View File

@ -49,7 +49,7 @@ public:
void makeWarMachine() void makeWarMachine()
{ {
addNewBonus(std::make_shared<Bonus>(BonusDuration::PERMANENT, BonusType::SIEGE_WEAPON, BonusSource::CREATURE_ABILITY, 1, TBonusSourceID::NONE)); addNewBonus(std::make_shared<Bonus>(BonusDuration::PERMANENT, BonusType::SIEGE_WEAPON, BonusSource::CREATURE_ABILITY, 1, TBonusSourceID()));
} }
void redirectBonusesToFake() void redirectBonusesToFake()
@ -331,7 +331,7 @@ TEST_F(BattleMatchOwnerTest, hypnotizedToSelf)
{ {
UnitFake & unit1 = unitsFake.add(BattleSide::ATTACKER); UnitFake & unit1 = unitsFake.add(BattleSide::ATTACKER);
EXPECT_CALL(unit1, unitId()).WillRepeatedly(Return(42)); EXPECT_CALL(unit1, unitId()).WillRepeatedly(Return(42));
unit1.addNewBonus(std::make_shared<Bonus>(BonusDuration::PERMANENT, BonusType::HYPNOTIZED, BonusSource::CREATURE_ABILITY, 0, TBonusSourceID::NONE)); unit1.addNewBonus(std::make_shared<Bonus>(BonusDuration::PERMANENT, BonusType::HYPNOTIZED, BonusSource::CREATURE_ABILITY, 0, TBonusSourceID()));
setDefaultExpectations(); setDefaultExpectations();
@ -362,7 +362,7 @@ TEST_F(BattleMatchOwnerTest, hypnotizedToNormalAlly)
{ {
UnitFake & unit1 = unitsFake.add(BattleSide::ATTACKER); UnitFake & unit1 = unitsFake.add(BattleSide::ATTACKER);
EXPECT_CALL(unit1, unitId()).WillRepeatedly(Return(42)); EXPECT_CALL(unit1, unitId()).WillRepeatedly(Return(42));
unit1.addNewBonus(std::make_shared<Bonus>(BonusDuration::PERMANENT, BonusType::HYPNOTIZED, BonusSource::CREATURE_ABILITY, 0, TBonusSourceID::NONE)); unit1.addNewBonus(std::make_shared<Bonus>(BonusDuration::PERMANENT, BonusType::HYPNOTIZED, BonusSource::CREATURE_ABILITY, 0, TBonusSourceID()));
UnitFake & unit2 = unitsFake.add(BattleSide::ATTACKER); UnitFake & unit2 = unitsFake.add(BattleSide::ATTACKER);
EXPECT_CALL(unit2, unitId()).WillRepeatedly(Return(4242)); EXPECT_CALL(unit2, unitId()).WillRepeatedly(Return(4242));
@ -382,7 +382,7 @@ TEST_F(BattleMatchOwnerTest, normalToHypnotizedAlly)
EXPECT_CALL(unit1, unitId()).WillRepeatedly(Return(42)); EXPECT_CALL(unit1, unitId()).WillRepeatedly(Return(42));
UnitFake & unit2 = unitsFake.add(BattleSide::ATTACKER); UnitFake & unit2 = unitsFake.add(BattleSide::ATTACKER);
EXPECT_CALL(unit2, unitId()).WillRepeatedly(Return(4242)); EXPECT_CALL(unit2, unitId()).WillRepeatedly(Return(4242));
unit2.addNewBonus(std::make_shared<Bonus>(BonusDuration::PERMANENT, BonusType::HYPNOTIZED, BonusSource::CREATURE_ABILITY, 0, TBonusSourceID::NONE)); unit2.addNewBonus(std::make_shared<Bonus>(BonusDuration::PERMANENT, BonusType::HYPNOTIZED, BonusSource::CREATURE_ABILITY, 0, TBonusSourceID()));
setDefaultExpectations(); setDefaultExpectations();
@ -397,11 +397,11 @@ TEST_F(BattleMatchOwnerTest, hypnotizedToHypnotizedAlly)
{ {
UnitFake & unit1 = unitsFake.add(BattleSide::ATTACKER); UnitFake & unit1 = unitsFake.add(BattleSide::ATTACKER);
EXPECT_CALL(unit1, unitId()).WillRepeatedly(Return(42)); EXPECT_CALL(unit1, unitId()).WillRepeatedly(Return(42));
unit1.addNewBonus(std::make_shared<Bonus>(BonusDuration::PERMANENT, BonusType::HYPNOTIZED, BonusSource::CREATURE_ABILITY, 0, TBonusSourceID::NONE)); unit1.addNewBonus(std::make_shared<Bonus>(BonusDuration::PERMANENT, BonusType::HYPNOTIZED, BonusSource::CREATURE_ABILITY, 0, TBonusSourceID()));
UnitFake & unit2 = unitsFake.add(BattleSide::ATTACKER); UnitFake & unit2 = unitsFake.add(BattleSide::ATTACKER);
EXPECT_CALL(unit2, unitId()).WillRepeatedly(Return(4242)); EXPECT_CALL(unit2, unitId()).WillRepeatedly(Return(4242));
unit2.addNewBonus(std::make_shared<Bonus>(BonusDuration::PERMANENT, BonusType::HYPNOTIZED, BonusSource::CREATURE_ABILITY, 0, TBonusSourceID::NONE)); unit2.addNewBonus(std::make_shared<Bonus>(BonusDuration::PERMANENT, BonusType::HYPNOTIZED, BonusSource::CREATURE_ABILITY, 0, TBonusSourceID()));
setDefaultExpectations(); setDefaultExpectations();
@ -433,7 +433,7 @@ TEST_F(BattleMatchOwnerTest, hypnotizedToNormalEnemy)
{ {
UnitFake & unit1 = unitsFake.add(BattleSide::ATTACKER); UnitFake & unit1 = unitsFake.add(BattleSide::ATTACKER);
EXPECT_CALL(unit1, unitId()).WillRepeatedly(Return(42)); EXPECT_CALL(unit1, unitId()).WillRepeatedly(Return(42));
unit1.addNewBonus(std::make_shared<Bonus>(BonusDuration::PERMANENT, BonusType::HYPNOTIZED, BonusSource::CREATURE_ABILITY, 0, TBonusSourceID::NONE)); unit1.addNewBonus(std::make_shared<Bonus>(BonusDuration::PERMANENT, BonusType::HYPNOTIZED, BonusSource::CREATURE_ABILITY, 0, TBonusSourceID()));
UnitFake & unit2 = unitsFake.add(BattleSide::DEFENDER); UnitFake & unit2 = unitsFake.add(BattleSide::DEFENDER);
EXPECT_CALL(unit2, unitId()).WillRepeatedly(Return(4242)); EXPECT_CALL(unit2, unitId()).WillRepeatedly(Return(4242));
@ -453,7 +453,7 @@ TEST_F(BattleMatchOwnerTest, normalToHypnotizedEnemy)
EXPECT_CALL(unit1, unitId()).WillRepeatedly(Return(42)); EXPECT_CALL(unit1, unitId()).WillRepeatedly(Return(42));
UnitFake & unit2 = unitsFake.add(BattleSide::DEFENDER); UnitFake & unit2 = unitsFake.add(BattleSide::DEFENDER);
EXPECT_CALL(unit2, unitId()).WillRepeatedly(Return(4242)); EXPECT_CALL(unit2, unitId()).WillRepeatedly(Return(4242));
unit2.addNewBonus(std::make_shared<Bonus>(BonusDuration::PERMANENT, BonusType::HYPNOTIZED, BonusSource::CREATURE_ABILITY, 0, TBonusSourceID::NONE)); unit2.addNewBonus(std::make_shared<Bonus>(BonusDuration::PERMANENT, BonusType::HYPNOTIZED, BonusSource::CREATURE_ABILITY, 0, TBonusSourceID()));
setDefaultExpectations(); setDefaultExpectations();
@ -468,11 +468,11 @@ TEST_F(BattleMatchOwnerTest, hypnotizedToHypnotizedEnemy)
{ {
UnitFake & unit1 = unitsFake.add(BattleSide::ATTACKER); UnitFake & unit1 = unitsFake.add(BattleSide::ATTACKER);
EXPECT_CALL(unit1, unitId()).WillRepeatedly(Return(42)); EXPECT_CALL(unit1, unitId()).WillRepeatedly(Return(42));
unit1.addNewBonus(std::make_shared<Bonus>(BonusDuration::PERMANENT, BonusType::HYPNOTIZED, BonusSource::CREATURE_ABILITY, 0, TBonusSourceID::NONE)); unit1.addNewBonus(std::make_shared<Bonus>(BonusDuration::PERMANENT, BonusType::HYPNOTIZED, BonusSource::CREATURE_ABILITY, 0, TBonusSourceID()));
UnitFake & unit2 = unitsFake.add(BattleSide::DEFENDER); UnitFake & unit2 = unitsFake.add(BattleSide::DEFENDER);
EXPECT_CALL(unit2, unitId()).WillRepeatedly(Return(4242)); EXPECT_CALL(unit2, unitId()).WillRepeatedly(Return(4242));
unit2.addNewBonus(std::make_shared<Bonus>(BonusDuration::PERMANENT, BonusType::HYPNOTIZED, BonusSource::CREATURE_ABILITY, 0, TBonusSourceID::NONE)); unit2.addNewBonus(std::make_shared<Bonus>(BonusDuration::PERMANENT, BonusType::HYPNOTIZED, BonusSource::CREATURE_ABILITY, 0, TBonusSourceID()));
setDefaultExpectations(); setDefaultExpectations();

View File

@ -33,7 +33,7 @@ public:
EXPECT_CALL(mock, getAllBonuses(_, _, _, _)).WillRepeatedly(Invoke(&bonusMock, &BonusBearerMock::getAllBonuses)); EXPECT_CALL(mock, getAllBonuses(_, _, _, _)).WillRepeatedly(Invoke(&bonusMock, &BonusBearerMock::getAllBonuses));
EXPECT_CALL(mock, getTreeVersion()).WillRepeatedly(Return(1)); EXPECT_CALL(mock, getTreeVersion()).WillRepeatedly(Return(1));
bonusMock.addNewBonus(std::make_shared<Bonus>(BonusDuration::PERMANENT, BonusType::STACK_HEALTH, BonusSource::CREATURE_ABILITY, UNIT_HEALTH, TBonusSourceID::NONE)); bonusMock.addNewBonus(std::make_shared<Bonus>(BonusDuration::PERMANENT, BonusType::STACK_HEALTH, BonusSource::CREATURE_ABILITY, UNIT_HEALTH, TBonusSourceID()));
EXPECT_CALL(mock, unitBaseAmount()).WillRepeatedly(Return(UNIT_AMOUNT)); EXPECT_CALL(mock, unitBaseAmount()).WillRepeatedly(Return(UNIT_AMOUNT));
} }
@ -239,7 +239,7 @@ TEST_F(HealthTest, singleUnitStack)
EXPECT_CALL(mock, getAllBonuses(_, _, _, _)).WillRepeatedly(Invoke(&bonusMock, &BonusBearerMock::getAllBonuses)); EXPECT_CALL(mock, getAllBonuses(_, _, _, _)).WillRepeatedly(Invoke(&bonusMock, &BonusBearerMock::getAllBonuses));
EXPECT_CALL(mock, getTreeVersion()).WillRepeatedly(Return(1)); EXPECT_CALL(mock, getTreeVersion()).WillRepeatedly(Return(1));
bonusMock.addNewBonus(std::make_shared<Bonus>(BonusDuration::PERMANENT, BonusType::STACK_HEALTH, BonusSource::CREATURE_ABILITY, 300, TBonusSourceID::NONE)); bonusMock.addNewBonus(std::make_shared<Bonus>(BonusDuration::PERMANENT, BonusType::STACK_HEALTH, BonusSource::CREATURE_ABILITY, 300, TBonusSourceID()));
EXPECT_CALL(mock, unitBaseAmount()).WillRepeatedly(Return(1)); EXPECT_CALL(mock, unitBaseAmount()).WillRepeatedly(Return(1));

View File

@ -55,7 +55,7 @@ public:
void makeNormalCaster() void makeNormalCaster()
{ {
bonusMock.addNewBonus(std::make_shared<Bonus>(BonusDuration::PERMANENT, BonusType::SPELLCASTER, BonusSource::CREATURE_ABILITY, DEFAULT_SCHOOL_LEVEL, TBonusSourceID::NONE, TBonusSubtype(SpellID(DEFAULT_SPELL_INDEX)))); bonusMock.addNewBonus(std::make_shared<Bonus>(BonusDuration::PERMANENT, BonusType::SPELLCASTER, BonusSource::CREATURE_ABILITY, DEFAULT_SCHOOL_LEVEL, TBonusSourceID(), TBonusSubtype(SpellID(DEFAULT_SPELL_INDEX))));
} }
}; };
@ -63,7 +63,7 @@ TEST_F(UnitStateMagicTest, initialNormal)
{ {
setDefaultExpectations(); setDefaultExpectations();
bonusMock.addNewBonus(std::make_shared<Bonus>(BonusDuration::PERMANENT, BonusType::CASTS, BonusSource::CREATURE_ABILITY, 567, TBonusSourceID::NONE)); bonusMock.addNewBonus(std::make_shared<Bonus>(BonusDuration::PERMANENT, BonusType::CASTS, BonusSource::CREATURE_ABILITY, 567, TBonusSourceID()));
initUnit(); initUnit();
@ -125,7 +125,7 @@ TEST_F(UnitStateMagicTest, effectPower)
const int32_t EFFECT_POWER = 12 * 100; const int32_t EFFECT_POWER = 12 * 100;
bonusMock.addNewBonus(std::make_shared<Bonus>(BonusDuration::PERMANENT, BonusType::CREATURE_SPELL_POWER, BonusSource::CREATURE_ABILITY, EFFECT_POWER, TBonusSourceID::NONE)); bonusMock.addNewBonus(std::make_shared<Bonus>(BonusDuration::PERMANENT, BonusType::CREATURE_SPELL_POWER, BonusSource::CREATURE_ABILITY, EFFECT_POWER, TBonusSourceID()));
makeNormalCaster(); makeNormalCaster();
EXPECT_EQ(subject.getEffectPower(&spellMock), 12 * DEFAULT_AMOUNT); EXPECT_EQ(subject.getEffectPower(&spellMock), 12 * DEFAULT_AMOUNT);
@ -148,7 +148,7 @@ TEST_F(UnitStateMagicTest, enchantPower)
const int32_t ENCHANT_POWER = 42; const int32_t ENCHANT_POWER = 42;
bonusMock.addNewBonus(std::make_shared<Bonus>(BonusDuration::PERMANENT, BonusType::CREATURE_ENCHANT_POWER, BonusSource::CREATURE_ABILITY, ENCHANT_POWER, TBonusSourceID::NONE)); bonusMock.addNewBonus(std::make_shared<Bonus>(BonusDuration::PERMANENT, BonusType::CREATURE_ENCHANT_POWER, BonusSource::CREATURE_ABILITY, ENCHANT_POWER, TBonusSourceID()));
makeNormalCaster(); makeNormalCaster();
@ -171,7 +171,7 @@ TEST_F(UnitStateMagicTest, effectValue)
const int32_t EFFECT_VALUE = 456; const int32_t EFFECT_VALUE = 456;
bonusMock.addNewBonus(std::make_shared<Bonus>(BonusDuration::PERMANENT, BonusType::SPECIFIC_SPELL_POWER, BonusSource::CREATURE_ABILITY, EFFECT_VALUE, TBonusSourceID::NONE, TBonusSubtype(SpellID(DEFAULT_SPELL_INDEX)))); bonusMock.addNewBonus(std::make_shared<Bonus>(BonusDuration::PERMANENT, BonusType::SPECIFIC_SPELL_POWER, BonusSource::CREATURE_ABILITY, EFFECT_VALUE, TBonusSourceID(), TBonusSubtype(SpellID(DEFAULT_SPELL_INDEX))));
makeNormalCaster(); makeNormalCaster();
EXPECT_EQ(subject.getEffectValue(&spellMock), EFFECT_VALUE * DEFAULT_AMOUNT); EXPECT_EQ(subject.getEffectValue(&spellMock), EFFECT_VALUE * DEFAULT_AMOUNT);
@ -201,7 +201,7 @@ TEST_F(UnitStateMagicTest, spendMana)
{ {
setDefaultExpectations(); setDefaultExpectations();
bonusMock.addNewBonus(std::make_shared<Bonus>(BonusDuration::PERMANENT, BonusType::CASTS, BonusSource::CREATURE_ABILITY, 1, TBonusSourceID::NONE)); bonusMock.addNewBonus(std::make_shared<Bonus>(BonusDuration::PERMANENT, BonusType::CASTS, BonusSource::CREATURE_ABILITY, 1, TBonusSourceID()));
initUnit(); initUnit();

View File

@ -12,7 +12,6 @@
#include "mock/mock_BonusBearer.h" #include "mock/mock_BonusBearer.h"
#include "mock/mock_UnitInfo.h" #include "mock/mock_UnitInfo.h"
#include "mock/mock_UnitEnvironment.h" #include "mock/mock_UnitEnvironment.h"
#include "../../lib/bonuses/BonusSubtypes.h"
#include "../../lib/battle/CUnitState.h" #include "../../lib/battle/CUnitState.h"
#include "../../lib/CCreatureHandler.h" #include "../../lib/CCreatureHandler.h"
@ -52,12 +51,12 @@ public:
void setDefaultExpectations() void setDefaultExpectations()
{ {
bonusMock.addNewBonus(std::make_shared<Bonus>(BonusDuration::PERMANENT, BonusType::STACKS_SPEED, BonusSource::CREATURE_ABILITY, DEFAULT_SPEED, TBonusSourceID::NONE)); bonusMock.addNewBonus(std::make_shared<Bonus>(BonusDuration::PERMANENT, BonusType::STACKS_SPEED, BonusSource::CREATURE_ABILITY, DEFAULT_SPEED, TBonusSourceID()));
bonusMock.addNewBonus(std::make_shared<Bonus>(BonusDuration::PERMANENT, BonusType::PRIMARY_SKILL, BonusSource::CREATURE_ABILITY, DEFAULT_ATTACK, TBonusSourceID::NONE, TBonusSubtype(PrimarySkill::ATTACK))); bonusMock.addNewBonus(std::make_shared<Bonus>(BonusDuration::PERMANENT, BonusType::PRIMARY_SKILL, BonusSource::CREATURE_ABILITY, DEFAULT_ATTACK, TBonusSourceID(), TBonusSubtype(PrimarySkill::ATTACK)));
bonusMock.addNewBonus(std::make_shared<Bonus>(BonusDuration::PERMANENT, BonusType::PRIMARY_SKILL, BonusSource::CREATURE_ABILITY, DEFAULT_DEFENCE, TBonusSourceID::NONE, TBonusSubtype(PrimarySkill::DEFENSE))); bonusMock.addNewBonus(std::make_shared<Bonus>(BonusDuration::PERMANENT, BonusType::PRIMARY_SKILL, BonusSource::CREATURE_ABILITY, DEFAULT_DEFENCE, TBonusSourceID(), TBonusSubtype(PrimarySkill::DEFENSE)));
bonusMock.addNewBonus(std::make_shared<Bonus>(BonusDuration::PERMANENT, BonusType::STACK_HEALTH, BonusSource::CREATURE_ABILITY, DEFAULT_HP, TBonusSourceID::NONE)); bonusMock.addNewBonus(std::make_shared<Bonus>(BonusDuration::PERMANENT, BonusType::STACK_HEALTH, BonusSource::CREATURE_ABILITY, DEFAULT_HP, TBonusSourceID()));
EXPECT_CALL(infoMock, unitBaseAmount()).WillRepeatedly(Return(DEFAULT_AMOUNT)); EXPECT_CALL(infoMock, unitBaseAmount()).WillRepeatedly(Return(DEFAULT_AMOUNT));
EXPECT_CALL(infoMock, unitType()).WillRepeatedly(Return(pikeman)); EXPECT_CALL(infoMock, unitType()).WillRepeatedly(Return(pikeman));
@ -67,8 +66,8 @@ public:
void makeShooter(int32_t ammo) void makeShooter(int32_t ammo)
{ {
bonusMock.addNewBonus(std::make_shared<Bonus>(BonusDuration::PERMANENT, BonusType::SHOOTER, BonusSource::CREATURE_ABILITY, 1, TBonusSourceID::NONE)); bonusMock.addNewBonus(std::make_shared<Bonus>(BonusDuration::PERMANENT, BonusType::SHOOTER, BonusSource::CREATURE_ABILITY, 1, TBonusSourceID()));
bonusMock.addNewBonus(std::make_shared<Bonus>(BonusDuration::PERMANENT, BonusType::SHOTS, BonusSource::CREATURE_ABILITY, ammo, TBonusSourceID::NONE)); bonusMock.addNewBonus(std::make_shared<Bonus>(BonusDuration::PERMANENT, BonusType::SHOTS, BonusSource::CREATURE_ABILITY, ammo, TBonusSourceID()));
} }
void initUnit() void initUnit()
@ -180,7 +179,7 @@ TEST_F(UnitStateTest, attackWithFrenzy)
{ {
setDefaultExpectations(); setDefaultExpectations();
bonusMock.addNewBonus(std::make_shared<Bonus>(BonusDuration::PERMANENT, BonusType::IN_FRENZY, BonusSource::SPELL_EFFECT, 50, TBonusSourceID::NONE)); bonusMock.addNewBonus(std::make_shared<Bonus>(BonusDuration::PERMANENT, BonusType::IN_FRENZY, BonusSource::SPELL_EFFECT, 50, TBonusSourceID()));
int expectedAttack = static_cast<int>(DEFAULT_ATTACK + 0.5 * DEFAULT_DEFENCE); int expectedAttack = static_cast<int>(DEFAULT_ATTACK + 0.5 * DEFAULT_DEFENCE);
@ -192,7 +191,7 @@ TEST_F(UnitStateTest, defenceWithFrenzy)
{ {
setDefaultExpectations(); setDefaultExpectations();
bonusMock.addNewBonus(std::make_shared<Bonus>(BonusDuration::PERMANENT, BonusType::IN_FRENZY, BonusSource::SPELL_EFFECT, 50, TBonusSourceID::NONE)); bonusMock.addNewBonus(std::make_shared<Bonus>(BonusDuration::PERMANENT, BonusType::IN_FRENZY, BonusSource::SPELL_EFFECT, 50, TBonusSourceID()));
int expectedDefence = 0; int expectedDefence = 0;
@ -205,7 +204,7 @@ TEST_F(UnitStateTest, additionalAttack)
setDefaultExpectations(); setDefaultExpectations();
{ {
auto bonus = std::make_shared<Bonus>(BonusDuration::PERMANENT, BonusType::ADDITIONAL_ATTACK, BonusSource::SPELL_EFFECT, 41, TBonusSourceID::NONE); auto bonus = std::make_shared<Bonus>(BonusDuration::PERMANENT, BonusType::ADDITIONAL_ATTACK, BonusSource::SPELL_EFFECT, 41, TBonusSourceID());
bonusMock.addNewBonus(bonus); bonusMock.addNewBonus(bonus);
} }
@ -219,7 +218,7 @@ TEST_F(UnitStateTest, additionalMeleeAttack)
setDefaultExpectations(); setDefaultExpectations();
{ {
auto bonus = std::make_shared<Bonus>(BonusDuration::PERMANENT, BonusType::ADDITIONAL_ATTACK, BonusSource::SPELL_EFFECT, 41, TBonusSourceID::NONE); auto bonus = std::make_shared<Bonus>(BonusDuration::PERMANENT, BonusType::ADDITIONAL_ATTACK, BonusSource::SPELL_EFFECT, 41, TBonusSourceID());
bonus->effectRange = BonusLimitEffect::ONLY_MELEE_FIGHT; bonus->effectRange = BonusLimitEffect::ONLY_MELEE_FIGHT;
bonusMock.addNewBonus(bonus); bonusMock.addNewBonus(bonus);
@ -234,7 +233,7 @@ TEST_F(UnitStateTest, additionalRangedAttack)
setDefaultExpectations(); setDefaultExpectations();
{ {
auto bonus = std::make_shared<Bonus>(BonusDuration::PERMANENT, BonusType::ADDITIONAL_ATTACK, BonusSource::SPELL_EFFECT, 41, TBonusSourceID::NONE); auto bonus = std::make_shared<Bonus>(BonusDuration::PERMANENT, BonusType::ADDITIONAL_ATTACK, BonusSource::SPELL_EFFECT, 41, TBonusSourceID());
bonus->effectRange = BonusLimitEffect::ONLY_DISTANCE_FIGHT; bonus->effectRange = BonusLimitEffect::ONLY_DISTANCE_FIGHT;
bonusMock.addNewBonus(bonus); bonusMock.addNewBonus(bonus);
@ -249,10 +248,10 @@ TEST_F(UnitStateTest, getMinDamage)
setDefaultExpectations(); setDefaultExpectations();
{ {
auto bonus = std::make_shared<Bonus>(BonusDuration::PERMANENT, BonusType::CREATURE_DAMAGE, BonusSource::SPELL_EFFECT, 30, TBonusSourceID::NONE, BonusSubtypes::creatureDamageBoth); auto bonus = std::make_shared<Bonus>(BonusDuration::PERMANENT, BonusType::CREATURE_DAMAGE, BonusSource::SPELL_EFFECT, 30, TBonusSourceID(), BonusSubtypeID::creatureDamageBoth);
bonusMock.addNewBonus(bonus); bonusMock.addNewBonus(bonus);
bonus = std::make_shared<Bonus>(BonusDuration::PERMANENT, BonusType::CREATURE_DAMAGE, BonusSource::SPELL_EFFECT, -20, TBonusSourceID::NONE, BonusSubtypes::creatureDamageMin); bonus = std::make_shared<Bonus>(BonusDuration::PERMANENT, BonusType::CREATURE_DAMAGE, BonusSource::SPELL_EFFECT, -20, TBonusSourceID(), BonusSubtypeID::creatureDamageMin);
bonusMock.addNewBonus(bonus); bonusMock.addNewBonus(bonus);
} }
@ -265,10 +264,10 @@ TEST_F(UnitStateTest, getMaxDamage)
setDefaultExpectations(); setDefaultExpectations();
{ {
auto bonus = std::make_shared<Bonus>(BonusDuration::PERMANENT, BonusType::CREATURE_DAMAGE, BonusSource::SPELL_EFFECT, 30, TBonusSourceID::NONE, BonusSubtypes::creatureDamageBoth); auto bonus = std::make_shared<Bonus>(BonusDuration::PERMANENT, BonusType::CREATURE_DAMAGE, BonusSource::SPELL_EFFECT, 30, TBonusSourceID(), BonusSubtypeID::creatureDamageBoth);
bonusMock.addNewBonus(bonus); bonusMock.addNewBonus(bonus);
bonus = std::make_shared<Bonus>(BonusDuration::PERMANENT, BonusType::CREATURE_DAMAGE, BonusSource::SPELL_EFFECT, -20, TBonusSourceID::NONE, BonusSubtypes::creatureDamageMax); bonus = std::make_shared<Bonus>(BonusDuration::PERMANENT, BonusType::CREATURE_DAMAGE, BonusSource::SPELL_EFFECT, -20, TBonusSourceID(), BonusSubtypeID::creatureDamageMax);
bonusMock.addNewBonus(bonus); bonusMock.addNewBonus(bonus);
} }

View File

@ -56,7 +56,7 @@ TEST_F(AbilityCasterTest, MagicAbilityAffectedByGenericBonus)
{ {
EXPECT_CALL(spellMock, getLevel()).WillRepeatedly(Return(1)); EXPECT_CALL(spellMock, getLevel()).WillRepeatedly(Return(1));
casterBonuses.addNewBonus(std::make_shared<Bonus>(BonusDuration::ONE_BATTLE, BonusType::MAGIC_SCHOOL_SKILL, BonusSource::OTHER, 2, TBonusSourceID::NONE, TBonusSubtype(SpellSchool::ANY))); casterBonuses.addNewBonus(std::make_shared<Bonus>(BonusDuration::ONE_BATTLE, BonusType::MAGIC_SCHOOL_SKILL, BonusSource::OTHER, 2, TBonusSourceID(), TBonusSubtype(SpellSchool::ANY)));
EXPECT_CALL(actualCaster, getAllBonuses(_, _, _, _)).Times(AtLeast(1)); EXPECT_CALL(actualCaster, getAllBonuses(_, _, _, _)).Times(AtLeast(1));
EXPECT_CALL(actualCaster, getTreeVersion()).Times(AtLeast(0)); EXPECT_CALL(actualCaster, getTreeVersion()).Times(AtLeast(0));
@ -70,7 +70,7 @@ TEST_F(AbilityCasterTest, MagicAbilityIngoresSchoolBonus)
{ {
EXPECT_CALL(spellMock, getLevel()).WillRepeatedly(Return(1)); EXPECT_CALL(spellMock, getLevel()).WillRepeatedly(Return(1));
casterBonuses.addNewBonus(std::make_shared<Bonus>(BonusDuration::ONE_BATTLE, BonusType::MAGIC_SCHOOL_SKILL, BonusSource::OTHER, 2, TBonusSourceID::NONE, TBonusSubtype(SpellSchool::AIR))); casterBonuses.addNewBonus(std::make_shared<Bonus>(BonusDuration::ONE_BATTLE, BonusType::MAGIC_SCHOOL_SKILL, BonusSource::OTHER, 2, TBonusSourceID(), TBonusSubtype(SpellSchool::AIR)));
EXPECT_CALL(actualCaster, getAllBonuses(_, _, _, _)).Times(AtLeast(1)); EXPECT_CALL(actualCaster, getAllBonuses(_, _, _, _)).Times(AtLeast(1));
EXPECT_CALL(actualCaster, getTreeVersion()).Times(AtLeast(0)); EXPECT_CALL(actualCaster, getTreeVersion()).Times(AtLeast(0));

View File

@ -95,7 +95,7 @@ TEST_F(DamageApplyTest, DoesDamageToAliveUnit)
const uint32_t unitId = 42; const uint32_t unitId = 42;
auto & targetUnit = unitsFake.add(BattleSide::ATTACKER); auto & targetUnit = unitsFake.add(BattleSide::ATTACKER);
targetUnit.addNewBonus(std::make_shared<Bonus>(BonusDuration::PERMANENT, BonusType::STACK_HEALTH, BonusSource::CREATURE_ABILITY, unitHP, TBonusSourceID::NONE)); targetUnit.addNewBonus(std::make_shared<Bonus>(BonusDuration::PERMANENT, BonusType::STACK_HEALTH, BonusSource::CREATURE_ABILITY, unitHP, TBonusSourceID()));
EXPECT_CALL(targetUnit, unitId()).WillRepeatedly(Return(unitId)); EXPECT_CALL(targetUnit, unitId()).WillRepeatedly(Return(unitId));
EXPECT_CALL(targetUnit, unitBaseAmount()).WillRepeatedly(Return(unitAmount)); EXPECT_CALL(targetUnit, unitBaseAmount()).WillRepeatedly(Return(unitAmount));
EXPECT_CALL(targetUnit, alive()).WillRepeatedly(Return(true)); EXPECT_CALL(targetUnit, alive()).WillRepeatedly(Return(true));
@ -157,7 +157,7 @@ TEST_F(DamageApplyTest, DoesDamageByPercent)
const uint32_t unitId = 42; const uint32_t unitId = 42;
auto & targetUnit = unitsFake.add(BattleSide::ATTACKER); auto & targetUnit = unitsFake.add(BattleSide::ATTACKER);
targetUnit.addNewBonus(std::make_shared<Bonus>(BonusDuration::PERMANENT, BonusType::STACK_HEALTH, BonusSource::CREATURE_ABILITY, unitHP, TBonusSourceID::NONE)); targetUnit.addNewBonus(std::make_shared<Bonus>(BonusDuration::PERMANENT, BonusType::STACK_HEALTH, BonusSource::CREATURE_ABILITY, unitHP, TBonusSourceID()));
EXPECT_CALL(targetUnit, unitId()).WillRepeatedly(Return(unitId)); EXPECT_CALL(targetUnit, unitId()).WillRepeatedly(Return(unitId));
EXPECT_CALL(targetUnit, unitBaseAmount()).WillRepeatedly(Return(unitAmount)); EXPECT_CALL(targetUnit, unitBaseAmount()).WillRepeatedly(Return(unitAmount));
EXPECT_CALL(targetUnit, getCount()).WillOnce(Return(unitAmount)); EXPECT_CALL(targetUnit, getCount()).WillOnce(Return(unitAmount));
@ -202,7 +202,7 @@ TEST_F(DamageApplyTest, DoesDamageByCount)
const uint32_t unitId = 42; const uint32_t unitId = 42;
auto & targetUnit = unitsFake.add(BattleSide::ATTACKER); auto & targetUnit = unitsFake.add(BattleSide::ATTACKER);
targetUnit.addNewBonus(std::make_shared<Bonus>(BonusDuration::PERMANENT, BonusType::STACK_HEALTH, BonusSource::CREATURE_ABILITY, unitHP, TBonusSourceID::NONE)); targetUnit.addNewBonus(std::make_shared<Bonus>(BonusDuration::PERMANENT, BonusType::STACK_HEALTH, BonusSource::CREATURE_ABILITY, unitHP, TBonusSourceID()));
EXPECT_CALL(targetUnit, unitId()).WillRepeatedly(Return(unitId)); EXPECT_CALL(targetUnit, unitId()).WillRepeatedly(Return(unitId));
EXPECT_CALL(targetUnit, unitBaseAmount()).WillRepeatedly(Return(unitAmount)); EXPECT_CALL(targetUnit, unitBaseAmount()).WillRepeatedly(Return(unitAmount));
EXPECT_CALL(targetUnit, alive()).WillRepeatedly(Return(true)); EXPECT_CALL(targetUnit, alive()).WillRepeatedly(Return(true));

View File

@ -91,7 +91,7 @@ TEST_F(HealTest, ApplicableIfActuallyResurrects)
EXPECT_CALL(mechanicsMock, getEffectValue()).Times(AtLeast(1)).WillRepeatedly(Return(1000)); EXPECT_CALL(mechanicsMock, getEffectValue()).Times(AtLeast(1)).WillRepeatedly(Return(1000));
EXPECT_CALL(mechanicsMock, isSmart()).WillOnce(Return(false)); EXPECT_CALL(mechanicsMock, isSmart()).WillOnce(Return(false));
unit.addNewBonus(std::make_shared<Bonus>(BonusDuration::PERMANENT, BonusType::STACK_HEALTH, BonusSource::CREATURE_ABILITY, 200, TBonusSourceID::NONE)); unit.addNewBonus(std::make_shared<Bonus>(BonusDuration::PERMANENT, BonusType::STACK_HEALTH, BonusSource::CREATURE_ABILITY, 200, TBonusSourceID()));
unitsFake.setDefaultBonusExpectations(); unitsFake.setDefaultBonusExpectations();
EffectTarget target; EffectTarget target;
@ -117,7 +117,7 @@ TEST_F(HealTest, NotApplicableIfNotEnoughCasualties)
EXPECT_CALL(mechanicsMock, getEffectValue()).Times(AtLeast(1)).WillRepeatedly(Return(999)); EXPECT_CALL(mechanicsMock, getEffectValue()).Times(AtLeast(1)).WillRepeatedly(Return(999));
EXPECT_CALL(mechanicsMock, isSmart()).WillRepeatedly(Return(false)); EXPECT_CALL(mechanicsMock, isSmart()).WillRepeatedly(Return(false));
unit.addNewBonus(std::make_shared<Bonus>(BonusDuration::PERMANENT, BonusType::STACK_HEALTH, BonusSource::CREATURE_ABILITY, 200, TBonusSourceID::NONE)); unit.addNewBonus(std::make_shared<Bonus>(BonusDuration::PERMANENT, BonusType::STACK_HEALTH, BonusSource::CREATURE_ABILITY, 200, TBonusSourceID()));
unitsFake.setDefaultBonusExpectations(); unitsFake.setDefaultBonusExpectations();
EffectTarget target; EffectTarget target;
@ -143,7 +143,7 @@ TEST_F(HealTest, NotApplicableIfResurrectsLessThanRequired)
EXPECT_CALL(mechanicsMock, getEffectValue()).Times(AtLeast(1)).WillRepeatedly(Return(999)); EXPECT_CALL(mechanicsMock, getEffectValue()).Times(AtLeast(1)).WillRepeatedly(Return(999));
EXPECT_CALL(mechanicsMock, isSmart()).WillRepeatedly(Return(false)); EXPECT_CALL(mechanicsMock, isSmart()).WillRepeatedly(Return(false));
unit.addNewBonus(std::make_shared<Bonus>(BonusDuration::PERMANENT, BonusType::STACK_HEALTH, BonusSource::CREATURE_ABILITY, 200, TBonusSourceID::NONE)); unit.addNewBonus(std::make_shared<Bonus>(BonusDuration::PERMANENT, BonusType::STACK_HEALTH, BonusSource::CREATURE_ABILITY, 200, TBonusSourceID()));
unitsFake.setDefaultBonusExpectations(); unitsFake.setDefaultBonusExpectations();
EffectTarget target; EffectTarget target;
@ -271,7 +271,7 @@ TEST_F(HealTest, NotApplicableIfEffectValueTooLow)
EXPECT_CALL(unit, getTotalHealth()).WillOnce(Return(200)); EXPECT_CALL(unit, getTotalHealth()).WillOnce(Return(200));
EXPECT_CALL(unit, getAvailableHealth()).WillOnce(Return(100)); EXPECT_CALL(unit, getAvailableHealth()).WillOnce(Return(100));
unit.addNewBonus(std::make_shared<Bonus>(BonusDuration::PERMANENT, BonusType::STACK_HEALTH, BonusSource::CREATURE_ABILITY, 200, TBonusSourceID::NONE)); unit.addNewBonus(std::make_shared<Bonus>(BonusDuration::PERMANENT, BonusType::STACK_HEALTH, BonusSource::CREATURE_ABILITY, 200, TBonusSourceID()));
EXPECT_CALL(mechanicsMock, getEffectValue()).Times(AtLeast(1)).WillRepeatedly(Return(199)); EXPECT_CALL(mechanicsMock, getEffectValue()).Times(AtLeast(1)).WillRepeatedly(Return(199));
@ -348,7 +348,7 @@ TEST_P(HealApplyTest, Heals)
EXPECT_CALL(targetUnit, unitId()).WillRepeatedly(Return(unitId)); EXPECT_CALL(targetUnit, unitId()).WillRepeatedly(Return(unitId));
EXPECT_CALL(targetUnit, unitType()).WillRepeatedly(Return(pikeman)); EXPECT_CALL(targetUnit, unitType()).WillRepeatedly(Return(pikeman));
targetUnit.addNewBonus(std::make_shared<Bonus>(BonusDuration::PERMANENT, BonusType::STACK_HEALTH, BonusSource::CREATURE_ABILITY, unitHP, TBonusSourceID::NONE)); targetUnit.addNewBonus(std::make_shared<Bonus>(BonusDuration::PERMANENT, BonusType::STACK_HEALTH, BonusSource::CREATURE_ABILITY, unitHP, TBonusSourceID()));
unitsFake.setDefaultBonusExpectations(); unitsFake.setDefaultBonusExpectations();

View File

@ -179,13 +179,13 @@ TEST_F(SacrificeApplyTest, ResurrectsTarget)
EXPECT_CALL(mechanicsMock, applySpellBonus(_, Eq(&targetUnit))).WillOnce(ReturnArg<0>()); EXPECT_CALL(mechanicsMock, applySpellBonus(_, Eq(&targetUnit))).WillOnce(ReturnArg<0>());
EXPECT_CALL(mechanicsMock, calculateRawEffectValue(_,_)).WillOnce(Return(effectValue)); EXPECT_CALL(mechanicsMock, calculateRawEffectValue(_,_)).WillOnce(Return(effectValue));
targetUnit.addNewBonus(std::make_shared<Bonus>(BonusDuration::PERMANENT, BonusType::STACK_HEALTH, BonusSource::CREATURE_ABILITY, unitHP, TBonusSourceID::NONE)); targetUnit.addNewBonus(std::make_shared<Bonus>(BonusDuration::PERMANENT, BonusType::STACK_HEALTH, BonusSource::CREATURE_ABILITY, unitHP, TBonusSourceID()));
auto & victim = unitsFake.add(BattleSide::ATTACKER); auto & victim = unitsFake.add(BattleSide::ATTACKER);
EXPECT_CALL(victim, unitId()).Times(AtLeast(1)).WillRepeatedly(Return(victimId)); EXPECT_CALL(victim, unitId()).Times(AtLeast(1)).WillRepeatedly(Return(victimId));
EXPECT_CALL(victim, getCount()).Times(AtLeast(1)).WillRepeatedly(Return(victimCount)); EXPECT_CALL(victim, getCount()).Times(AtLeast(1)).WillRepeatedly(Return(victimCount));
victim.addNewBonus(std::make_shared<Bonus>(BonusDuration::PERMANENT, BonusType::STACK_HEALTH, BonusSource::CREATURE_ABILITY, victimUnitHP, TBonusSourceID::NONE)); victim.addNewBonus(std::make_shared<Bonus>(BonusDuration::PERMANENT, BonusType::STACK_HEALTH, BonusSource::CREATURE_ABILITY, victimUnitHP, TBonusSourceID()));
EXPECT_CALL(*battleFake, setUnitState(Eq(unitId), _, Eq(expectedHealValue))).Times(1); EXPECT_CALL(*battleFake, setUnitState(Eq(unitId), _, Eq(expectedHealValue))).Times(1);

View File

@ -244,12 +244,12 @@ TEST_P(SummonApplyTest, UpdatesOldUnit)
setDefaultExpectaions(); setDefaultExpectaions();
acquired = std::make_shared<battle::UnitFake>(); acquired = std::make_shared<battle::UnitFake>();
acquired->addNewBonus(std::make_shared<Bonus>(BonusDuration::PERMANENT, BonusType::STACK_HEALTH, BonusSource::CREATURE_ABILITY, unitHealth, TBonusSourceID::NONE)); acquired->addNewBonus(std::make_shared<Bonus>(BonusDuration::PERMANENT, BonusType::STACK_HEALTH, BonusSource::CREATURE_ABILITY, unitHealth, TBonusSourceID()));
acquired->redirectBonusesToFake(); acquired->redirectBonusesToFake();
acquired->expectAnyBonusSystemCall(); acquired->expectAnyBonusSystemCall();
auto & unit = unitsFake.add(BattleSide::ATTACKER); auto & unit = unitsFake.add(BattleSide::ATTACKER);
unit.addNewBonus(std::make_shared<Bonus>(BonusDuration::PERMANENT, BonusType::STACK_HEALTH, BonusSource::CREATURE_ABILITY, unitHealth, TBonusSourceID::NONE)); unit.addNewBonus(std::make_shared<Bonus>(BonusDuration::PERMANENT, BonusType::STACK_HEALTH, BonusSource::CREATURE_ABILITY, unitHealth, TBonusSourceID()));
{ {
EXPECT_CALL(unit, acquire()).WillOnce(Return(acquired)); EXPECT_CALL(unit, acquire()).WillOnce(Return(acquired));

View File

@ -71,9 +71,9 @@ protected:
TEST_P(TimedApplyTest, ChangesBonuses) TEST_P(TimedApplyTest, ChangesBonuses)
{ {
Bonus testBonus1(BonusDuration::PERMANENT, BonusType::PRIMARY_SKILL, BonusSource::OTHER, 3, TBonusSourceID::NONE, TBonusSubtype(PrimarySkill::KNOWLEDGE)); Bonus testBonus1(BonusDuration::PERMANENT, BonusType::PRIMARY_SKILL, BonusSource::OTHER, 3, TBonusSourceID(), TBonusSubtype(PrimarySkill::KNOWLEDGE));
Bonus testBonus2(BonusDuration::N_TURNS, BonusType::PRIMARY_SKILL, BonusSource::OTHER, 3, TBonusSourceID::NONE, TBonusSubtype(PrimarySkill::KNOWLEDGE)); Bonus testBonus2(BonusDuration::N_TURNS, BonusType::PRIMARY_SKILL, BonusSource::OTHER, 3, TBonusSourceID(), TBonusSubtype(PrimarySkill::KNOWLEDGE));
testBonus2.turnsRemain = 4; testBonus2.turnsRemain = 4;
JsonNode options(JsonNode::JsonType::DATA_STRUCT); JsonNode options(JsonNode::JsonType::DATA_STRUCT);

View File

@ -54,7 +54,7 @@ TEST_F(AbsoluteLevelConditionTest, ReceptiveNormalSpell)
{ {
setDefaultExpectations(); setDefaultExpectations();
auto bonus = std::make_shared<Bonus>(BonusDuration::ONE_BATTLE, BonusType::LEVEL_SPELL_IMMUNITY, BonusSource::OTHER, 3, TBonusSourceID::NONE); auto bonus = std::make_shared<Bonus>(BonusDuration::ONE_BATTLE, BonusType::LEVEL_SPELL_IMMUNITY, BonusSource::OTHER, 3, TBonusSourceID());
bonus->additionalInfo = 1; bonus->additionalInfo = 1;
unitBonuses.addNewBonus(bonus); unitBonuses.addNewBonus(bonus);
@ -67,7 +67,7 @@ TEST_F(AbsoluteLevelConditionTest, ReceptiveAbility)
{ {
setDefaultExpectations(); setDefaultExpectations();
auto bonus = std::make_shared<Bonus>(BonusDuration::ONE_BATTLE, BonusType::LEVEL_SPELL_IMMUNITY, BonusSource::OTHER, 5, TBonusSourceID::NONE); auto bonus = std::make_shared<Bonus>(BonusDuration::ONE_BATTLE, BonusType::LEVEL_SPELL_IMMUNITY, BonusSource::OTHER, 5, TBonusSourceID());
bonus->additionalInfo = 1; bonus->additionalInfo = 1;
unitBonuses.addNewBonus(bonus); unitBonuses.addNewBonus(bonus);
@ -79,7 +79,7 @@ TEST_F(AbsoluteLevelConditionTest, ImmuneNormalSpell)
{ {
setDefaultExpectations(); setDefaultExpectations();
auto bonus = std::make_shared<Bonus>(BonusDuration::ONE_BATTLE, BonusType::LEVEL_SPELL_IMMUNITY, BonusSource::OTHER, 4, TBonusSourceID::NONE); auto bonus = std::make_shared<Bonus>(BonusDuration::ONE_BATTLE, BonusType::LEVEL_SPELL_IMMUNITY, BonusSource::OTHER, 4, TBonusSourceID());
bonus->additionalInfo = 1; bonus->additionalInfo = 1;
unitBonuses.addNewBonus(bonus); unitBonuses.addNewBonus(bonus);
@ -90,7 +90,7 @@ TEST_F(AbsoluteLevelConditionTest, ImmuneNormalSpell)
TEST_F(AbsoluteLevelConditionTest, IgnoresNormalCase) TEST_F(AbsoluteLevelConditionTest, IgnoresNormalCase)
{ {
setDefaultExpectations(); setDefaultExpectations();
auto bonus = std::make_shared<Bonus>(BonusDuration::ONE_BATTLE, BonusType::LEVEL_SPELL_IMMUNITY, BonusSource::OTHER, 4, TBonusSourceID::NONE); auto bonus = std::make_shared<Bonus>(BonusDuration::ONE_BATTLE, BonusType::LEVEL_SPELL_IMMUNITY, BonusSource::OTHER, 4, TBonusSourceID());
unitBonuses.addNewBonus(bonus); unitBonuses.addNewBonus(bonus);
EXPECT_TRUE(subject->isReceptive(&mechanicsMock, &unitMock)); EXPECT_TRUE(subject->isReceptive(&mechanicsMock, &unitMock));
} }

View File

@ -43,7 +43,7 @@ public:
TEST_P(AbsoluteSpellConditionTest, ChecksAbsoluteCase) TEST_P(AbsoluteSpellConditionTest, ChecksAbsoluteCase)
{ {
setDefaultExpectations(); setDefaultExpectations();
auto bonus = std::make_shared<Bonus>(BonusDuration::ONE_BATTLE, BonusType::SPELL_IMMUNITY, BonusSource::OTHER, 4, TBonusSourceID::NONE, TBonusSubtype(SpellID(immuneSpell))); auto bonus = std::make_shared<Bonus>(BonusDuration::ONE_BATTLE, BonusType::SPELL_IMMUNITY, BonusSource::OTHER, 4, TBonusSourceID(), TBonusSubtype(SpellID(immuneSpell)));
bonus->additionalInfo = 1; bonus->additionalInfo = 1;
unitBonuses.addNewBonus(bonus); unitBonuses.addNewBonus(bonus);
@ -57,7 +57,7 @@ TEST_P(AbsoluteSpellConditionTest, ChecksAbsoluteCase)
TEST_P(AbsoluteSpellConditionTest, IgnoresNormalCase) TEST_P(AbsoluteSpellConditionTest, IgnoresNormalCase)
{ {
setDefaultExpectations(); setDefaultExpectations();
auto bonus = std::make_shared<Bonus>(BonusDuration::ONE_BATTLE, BonusType::SPELL_IMMUNITY, BonusSource::OTHER, 4, TBonusSourceID::NONE, TBonusSubtype(SpellID(immuneSpell))); auto bonus = std::make_shared<Bonus>(BonusDuration::ONE_BATTLE, BonusType::SPELL_IMMUNITY, BonusSource::OTHER, 4, TBonusSourceID(), TBonusSubtype(SpellID(immuneSpell)));
unitBonuses.addNewBonus(bonus); unitBonuses.addNewBonus(bonus);
EXPECT_TRUE(subject->isReceptive(&mechanicsMock, &unitMock)); EXPECT_TRUE(subject->isReceptive(&mechanicsMock, &unitMock));
} }

View File

@ -42,14 +42,14 @@ TEST_F(BonusConditionTest, ImmuneByDefault)
TEST_F(BonusConditionTest, ReceptiveIfMatchesType) TEST_F(BonusConditionTest, ReceptiveIfMatchesType)
{ {
setDefaultExpectations(); setDefaultExpectations();
unitBonuses.addNewBonus(std::make_shared<Bonus>(BonusDuration::ONE_BATTLE, BonusType::SPELL_DAMAGE_REDUCTION, BonusSource::OTHER, 100, TBonusSourceID::NONE)); unitBonuses.addNewBonus(std::make_shared<Bonus>(BonusDuration::ONE_BATTLE, BonusType::SPELL_DAMAGE_REDUCTION, BonusSource::OTHER, 100, TBonusSourceID()));
EXPECT_TRUE(subject->isReceptive(&mechanicsMock, &unitMock)); EXPECT_TRUE(subject->isReceptive(&mechanicsMock, &unitMock));
} }
TEST_F(BonusConditionTest, ImmuneIfTypeMismatch) TEST_F(BonusConditionTest, ImmuneIfTypeMismatch)
{ {
setDefaultExpectations(); setDefaultExpectations();
unitBonuses.addNewBonus(std::make_shared<Bonus>(BonusDuration::ONE_BATTLE, BonusType::SPELL_SCHOOL_IMMUNITY, BonusSource::OTHER, 0, TBonusSourceID(SpellSchool::FIRE))); unitBonuses.addNewBonus(std::make_shared<Bonus>(BonusDuration::ONE_BATTLE, BonusType::SPELL_SCHOOL_IMMUNITY, BonusSource::OTHER, 0, TBonusSourceID(), TBonusSubtype(SpellSchool::FIRE)));
EXPECT_FALSE(subject->isReceptive(&mechanicsMock, &unitMock)); EXPECT_FALSE(subject->isReceptive(&mechanicsMock, &unitMock));
} }

View File

@ -56,7 +56,7 @@ TEST_P(ElementalConditionTest, ReceptiveIfNoBonus)
TEST_P(ElementalConditionTest, ImmuneIfBonusMatches) TEST_P(ElementalConditionTest, ImmuneIfBonusMatches)
{ {
setDefaultExpectations(); setDefaultExpectations();
unitBonuses.addNewBonus(std::make_shared<Bonus>(BonusDuration::ONE_BATTLE, BonusType::SPELL_SCHOOL_IMMUNITY, BonusSource::SPELL_EFFECT, 0, TBonusSourceID::NONE, TBonusSubtype(SpellSchool::AIR))); unitBonuses.addNewBonus(std::make_shared<Bonus>(BonusDuration::ONE_BATTLE, BonusType::SPELL_SCHOOL_IMMUNITY, BonusSource::SPELL_EFFECT, 0, TBonusSourceID(), TBonusSubtype(SpellSchool::AIR)));
EXPECT_FALSE(subject->isReceptive(&mechanicsMock, &unitMock)); EXPECT_FALSE(subject->isReceptive(&mechanicsMock, &unitMock));
} }
@ -64,7 +64,7 @@ TEST_P(ElementalConditionTest, ImmuneIfBonusMatches)
TEST_P(ElementalConditionTest, NotImmuneIfBonusMismatches) TEST_P(ElementalConditionTest, NotImmuneIfBonusMismatches)
{ {
setDefaultExpectations(); setDefaultExpectations();
unitBonuses.addNewBonus(std::make_shared<Bonus>(BonusDuration::ONE_BATTLE, BonusType::SPELL_SCHOOL_IMMUNITY, BonusSource::SPELL_EFFECT, 0, TBonusSourceID::NONE, TBonusSubtype(SpellSchool::WATER))); unitBonuses.addNewBonus(std::make_shared<Bonus>(BonusDuration::ONE_BATTLE, BonusType::SPELL_SCHOOL_IMMUNITY, BonusSource::SPELL_EFFECT, 0, TBonusSourceID(), TBonusSubtype(SpellSchool::WATER)));
EXPECT_TRUE(subject->isReceptive(&mechanicsMock, &unitMock)); EXPECT_TRUE(subject->isReceptive(&mechanicsMock, &unitMock));
} }
@ -72,7 +72,7 @@ TEST_P(ElementalConditionTest, NotImmuneIfBonusMismatches)
TEST_P(ElementalConditionTest, DependsOnPositivness) TEST_P(ElementalConditionTest, DependsOnPositivness)
{ {
setDefaultExpectations(); setDefaultExpectations();
unitBonuses.addNewBonus(std::make_shared<Bonus>(BonusDuration::ONE_BATTLE, BonusType::NEGATIVE_EFFECTS_IMMUNITY, BonusSource::SPELL_EFFECT, 0, TBonusSourceID::NONE, TBonusSubtype(SpellSchool::AIR))); unitBonuses.addNewBonus(std::make_shared<Bonus>(BonusDuration::ONE_BATTLE, BonusType::NEGATIVE_EFFECTS_IMMUNITY, BonusSource::SPELL_EFFECT, 0, TBonusSourceID(), TBonusSubtype(SpellSchool::AIR)));
EXPECT_EQ(isPositive, subject->isReceptive(&mechanicsMock, &unitMock)); EXPECT_EQ(isPositive, subject->isReceptive(&mechanicsMock, &unitMock));
} }
@ -80,8 +80,8 @@ TEST_P(ElementalConditionTest, DependsOnPositivness)
TEST_P(ElementalConditionTest, ImmuneIfBothBonusesPresent) TEST_P(ElementalConditionTest, ImmuneIfBothBonusesPresent)
{ {
setDefaultExpectations(); setDefaultExpectations();
unitBonuses.addNewBonus(std::make_shared<Bonus>(BonusDuration::ONE_BATTLE, BonusType::SPELL_SCHOOL_IMMUNITY, BonusSource::SPELL_EFFECT, 0, TBonusSourceID::NONE, TBonusSubtype(SpellSchool::AIR))); unitBonuses.addNewBonus(std::make_shared<Bonus>(BonusDuration::ONE_BATTLE, BonusType::SPELL_SCHOOL_IMMUNITY, BonusSource::SPELL_EFFECT, 0, TBonusSourceID(), TBonusSubtype(SpellSchool::AIR)));
unitBonuses.addNewBonus(std::make_shared<Bonus>(BonusDuration::ONE_BATTLE, BonusType::NEGATIVE_EFFECTS_IMMUNITY, BonusSource::SPELL_EFFECT, 0, TBonusSourceID::NONE, TBonusSubtype(SpellSchool::AIR))); unitBonuses.addNewBonus(std::make_shared<Bonus>(BonusDuration::ONE_BATTLE, BonusType::NEGATIVE_EFFECTS_IMMUNITY, BonusSource::SPELL_EFFECT, 0, TBonusSourceID(), TBonusSubtype(SpellSchool::AIR)));
EXPECT_FALSE(subject->isReceptive(&mechanicsMock, &unitMock)); EXPECT_FALSE(subject->isReceptive(&mechanicsMock, &unitMock));
} }

View File

@ -10,7 +10,6 @@
#include "StdInc.h" #include "StdInc.h"
#include "TargetConditionItemFixture.h" #include "TargetConditionItemFixture.h"
#include "../../../lib/bonuses/BonusSubtypes.h"
//FIXME: Orb of vulnerability mechanics is not such trivial (mantis issue 1791) //FIXME: Orb of vulnerability mechanics is not such trivial (mantis issue 1791)
//TODO: NEGATE_ALL_NATURAL_IMMUNITIES special cases: dispel, chain lightning //TODO: NEGATE_ALL_NATURAL_IMMUNITIES special cases: dispel, chain lightning
@ -58,7 +57,7 @@ TEST_P(ImmunityNegationConditionTest, WithHeroNegation)
{ {
setDefaultExpectations(); setDefaultExpectations();
unitBonuses.addNewBonus(std::make_shared<Bonus>(BonusDuration::ONE_BATTLE, BonusType::NEGATE_ALL_NATURAL_IMMUNITIES, BonusSource::OTHER, 0, TBonusSourceID::NONE, BonusSubtypes::immunityEnemyHero)); unitBonuses.addNewBonus(std::make_shared<Bonus>(BonusDuration::ONE_BATTLE, BonusType::NEGATE_ALL_NATURAL_IMMUNITIES, BonusSource::OTHER, 0, TBonusSourceID(), BonusSubtypeID::immunityEnemyHero));
EXPECT_EQ(isMagicalEffect, subject->isReceptive(&mechanicsMock, &unitMock)); EXPECT_EQ(isMagicalEffect, subject->isReceptive(&mechanicsMock, &unitMock));
} }
@ -67,7 +66,7 @@ TEST_P(ImmunityNegationConditionTest, WithBattleWideNegation)
{ {
setDefaultExpectations(); setDefaultExpectations();
unitBonuses.addNewBonus(std::make_shared<Bonus>(BonusDuration::ONE_BATTLE, BonusType::NEGATE_ALL_NATURAL_IMMUNITIES, BonusSource::OTHER, 0, TBonusSourceID::NONE, BonusSubtypes::immunityBattleWide)); unitBonuses.addNewBonus(std::make_shared<Bonus>(BonusDuration::ONE_BATTLE, BonusType::NEGATE_ALL_NATURAL_IMMUNITIES, BonusSource::OTHER, 0, TBonusSourceID(), BonusSubtypeID::immunityBattleWide));
//This should return if ownerMatches, because anyone should cast onto owner's stacks, but not on enemyStacks //This should return if ownerMatches, because anyone should cast onto owner's stacks, but not on enemyStacks
EXPECT_EQ(ownerMatches && isMagicalEffect, subject->isReceptive(&mechanicsMock, &unitMock)); EXPECT_EQ(ownerMatches && isMagicalEffect, subject->isReceptive(&mechanicsMock, &unitMock));

View File

@ -56,7 +56,7 @@ TEST_P(NormalLevelConditionTest, DefaultForNormal)
TEST_P(NormalLevelConditionTest, ReceptiveNormal) TEST_P(NormalLevelConditionTest, ReceptiveNormal)
{ {
setDefaultExpectations(); setDefaultExpectations();
unitBonuses.addNewBonus(std::make_shared<Bonus>(BonusDuration::ONE_BATTLE, BonusType::LEVEL_SPELL_IMMUNITY, BonusSource::OTHER, 3, TBonusSourceID::NONE)); unitBonuses.addNewBonus(std::make_shared<Bonus>(BonusDuration::ONE_BATTLE, BonusType::LEVEL_SPELL_IMMUNITY, BonusSource::OTHER, 3, TBonusSourceID()));
if(isMagicalEffect) if(isMagicalEffect)
EXPECT_CALL(mechanicsMock, getSpellLevel()).Times(AtLeast(1)).WillRepeatedly(Return(4)); EXPECT_CALL(mechanicsMock, getSpellLevel()).Times(AtLeast(1)).WillRepeatedly(Return(4));
EXPECT_TRUE(subject->isReceptive(&mechanicsMock, &unitMock)); EXPECT_TRUE(subject->isReceptive(&mechanicsMock, &unitMock));
@ -66,7 +66,7 @@ TEST_P(NormalLevelConditionTest, ReceptiveNormal)
TEST_P(NormalLevelConditionTest, ReceptiveAbility) TEST_P(NormalLevelConditionTest, ReceptiveAbility)
{ {
setDefaultExpectations(); setDefaultExpectations();
unitBonuses.addNewBonus(std::make_shared<Bonus>(BonusDuration::ONE_BATTLE, BonusType::LEVEL_SPELL_IMMUNITY, BonusSource::OTHER, 5, TBonusSourceID::NONE)); unitBonuses.addNewBonus(std::make_shared<Bonus>(BonusDuration::ONE_BATTLE, BonusType::LEVEL_SPELL_IMMUNITY, BonusSource::OTHER, 5, TBonusSourceID()));
if(isMagicalEffect) if(isMagicalEffect)
EXPECT_CALL(mechanicsMock, getSpellLevel()).Times(AtLeast(1)).WillRepeatedly(Return(0)); EXPECT_CALL(mechanicsMock, getSpellLevel()).Times(AtLeast(1)).WillRepeatedly(Return(0));
EXPECT_TRUE(subject->isReceptive(&mechanicsMock, &unitMock)); EXPECT_TRUE(subject->isReceptive(&mechanicsMock, &unitMock));
@ -75,7 +75,7 @@ TEST_P(NormalLevelConditionTest, ReceptiveAbility)
TEST_P(NormalLevelConditionTest, ImmuneNormal) TEST_P(NormalLevelConditionTest, ImmuneNormal)
{ {
setDefaultExpectations(); setDefaultExpectations();
unitBonuses.addNewBonus(std::make_shared<Bonus>(BonusDuration::ONE_BATTLE, BonusType::LEVEL_SPELL_IMMUNITY, BonusSource::OTHER, 4, TBonusSourceID::NONE)); unitBonuses.addNewBonus(std::make_shared<Bonus>(BonusDuration::ONE_BATTLE, BonusType::LEVEL_SPELL_IMMUNITY, BonusSource::OTHER, 4, TBonusSourceID()));
if(isMagicalEffect) if(isMagicalEffect)
EXPECT_CALL(mechanicsMock, getSpellLevel()).Times(AtLeast(1)).WillRepeatedly(Return(2)); EXPECT_CALL(mechanicsMock, getSpellLevel()).Times(AtLeast(1)).WillRepeatedly(Return(2));
EXPECT_EQ(!isMagicalEffect, subject->isReceptive(&mechanicsMock, &unitMock)); EXPECT_EQ(!isMagicalEffect, subject->isReceptive(&mechanicsMock, &unitMock));

View File

@ -43,7 +43,7 @@ public:
TEST_P(NormalSpellConditionTest, ChecksAbsoluteCase) TEST_P(NormalSpellConditionTest, ChecksAbsoluteCase)
{ {
setDefaultExpectations(); setDefaultExpectations();
auto bonus = std::make_shared<Bonus>(BonusDuration::ONE_BATTLE, BonusType::SPELL_IMMUNITY, BonusSource::OTHER, 4, TBonusSourceID::NONE, TBonusSubtype(SpellID(immuneSpell))); auto bonus = std::make_shared<Bonus>(BonusDuration::ONE_BATTLE, BonusType::SPELL_IMMUNITY, BonusSource::OTHER, 4, TBonusSourceID(), TBonusSubtype(SpellID(immuneSpell)));
bonus->additionalInfo = 1; bonus->additionalInfo = 1;
unitBonuses.addNewBonus(bonus); unitBonuses.addNewBonus(bonus);
@ -57,7 +57,7 @@ TEST_P(NormalSpellConditionTest, ChecksAbsoluteCase)
TEST_P(NormalSpellConditionTest, ChecksNormalCase) TEST_P(NormalSpellConditionTest, ChecksNormalCase)
{ {
setDefaultExpectations(); setDefaultExpectations();
auto bonus = std::make_shared<Bonus>(BonusDuration::ONE_BATTLE, BonusType::SPELL_IMMUNITY, BonusSource::OTHER, 4, TBonusSourceID::NONE, TBonusSubtype(SpellID(immuneSpell))); auto bonus = std::make_shared<Bonus>(BonusDuration::ONE_BATTLE, BonusType::SPELL_IMMUNITY, BonusSource::OTHER, 4, TBonusSourceID(), TBonusSubtype(SpellID(immuneSpell)));
unitBonuses.addNewBonus(bonus); unitBonuses.addNewBonus(bonus);
if(immuneSpell == castSpell) if(immuneSpell == castSpell)
EXPECT_FALSE(subject->isReceptive(&mechanicsMock, &unitMock)); EXPECT_FALSE(subject->isReceptive(&mechanicsMock, &unitMock));

View File

@ -31,7 +31,7 @@ public:
EXPECT_CALL(unitMock, getTreeVersion()).Times(AtLeast(0)); EXPECT_CALL(unitMock, getTreeVersion()).Times(AtLeast(0));
EXPECT_CALL(mechanicsMock, isPositiveSpell()).WillRepeatedly(Return(isPositive)); EXPECT_CALL(mechanicsMock, isPositiveSpell()).WillRepeatedly(Return(isPositive));
if(hasBonus) if(hasBonus)
unitBonuses.addNewBonus(std::make_shared<Bonus>(BonusDuration::ONE_BATTLE, BonusType::RECEPTIVE, BonusSource::OTHER, 0, TBonusSourceID::NONE)); unitBonuses.addNewBonus(std::make_shared<Bonus>(BonusDuration::ONE_BATTLE, BonusType::RECEPTIVE, BonusSource::OTHER, 0, TBonusSourceID()));
} }
protected: protected:

View File

@ -60,7 +60,7 @@ TEST_F(SpellEffectConditionTest, ImmuneIfHasEffectFromOtherSpell)
TEST_F(SpellEffectConditionTest, ImmuneIfHasNoSpellEffects) TEST_F(SpellEffectConditionTest, ImmuneIfHasNoSpellEffects)
{ {
setDefaultExpectations(); setDefaultExpectations();
unitBonuses.addNewBonus(std::make_shared<Bonus>(BonusDuration::ONE_BATTLE, BonusType::STACK_HEALTH, BonusSource::CREATURE_ABILITY, 3, TBonusSourceID::NONE)); unitBonuses.addNewBonus(std::make_shared<Bonus>(BonusDuration::ONE_BATTLE, BonusType::STACK_HEALTH, BonusSource::CREATURE_ABILITY, 3, TBonusSourceID()));
EXPECT_FALSE(subject->isReceptive(&mechanicsMock, &unitMock)); EXPECT_FALSE(subject->isReceptive(&mechanicsMock, &unitMock));
} }