1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-05-31 22:59:54 +02:00

Renamed new types for consistency with code style

This commit is contained in:
Ivan Savenko 2023-10-21 14:50:42 +03:00
parent 31cf3442af
commit ac925bb786
94 changed files with 564 additions and 566 deletions

View File

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

View File

@ -242,13 +242,13 @@ uint64_t evaluateArtifactArmyValue(CArtifactInstance * art)
return 1500; return 1500;
auto statsValue = auto statsValue =
10 * art->valOfBonuses(BonusType::MOVEMENT, BonusSubtypeID::heroMovementLand) 10 * art->valOfBonuses(BonusType::MOVEMENT, BonusCustomSubtype::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, BonusSubtypeID(PrimarySkill::ATTACK))
+ 700 * art->valOfBonuses(BonusType::PRIMARY_SKILL, TBonusSubtype(PrimarySkill::DEFENSE)) + 700 * art->valOfBonuses(BonusType::PRIMARY_SKILL, BonusSubtypeID(PrimarySkill::DEFENSE))
+ 700 * art->valOfBonuses(BonusType::PRIMARY_SKILL, TBonusSubtype(PrimarySkill::KNOWLEDGE)) + 700 * art->valOfBonuses(BonusType::PRIMARY_SKILL, BonusSubtypeID(PrimarySkill::KNOWLEDGE))
+ 700 * art->valOfBonuses(BonusType::PRIMARY_SKILL, TBonusSubtype(PrimarySkill::SPELL_POWER)) + 700 * art->valOfBonuses(BonusType::PRIMARY_SKILL, BonusSubtypeID(PrimarySkill::SPELL_POWER))
+ 500 * art->valOfBonuses(BonusType::LUCK); + 500 * art->valOfBonuses(BonusType::LUCK);
auto classValue = 0; auto classValue = 0;

View File

@ -534,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, BonusSubtypeID::movementFlying))) if (!stack->hasBonus(Selector::typeSubtype(BonusType::FLYING, BonusCustomSubtype::movementFlying)))
{ {
owner.addToAnimationStage(EAnimationEvents::MOVEMENT, [&]() owner.addToAnimationStage(EAnimationEvents::MOVEMENT, [&]()
{ {
@ -797,7 +797,7 @@ void BattleStacksController::removeExpiredColorFilters()
{ {
if (!filter.persistent) if (!filter.persistent)
{ {
if (filter.source && !filter.target->hasBonus(Selector::source(BonusSource::SPELL_EFFECT, TBonusSourceID(filter.source->id)), Selector::all)) if (filter.source && !filter.target->hasBonus(Selector::source(BonusSource::SPELL_EFFECT, BonusSourceID(filter.source->id)), Selector::all))
return true; return true;
if (filter.effect == ColorFilter::genEmptyShifter()) if (filter.effect == ColorFilter::genEmptyShifter())
return true; return true;

View File

@ -224,7 +224,7 @@ CStackWindow::ActiveSpellsSection::ActiveSpellsSection(CStackWindow * owner, int
spellText = CGI->generaltexth->allTexts[610]; //"%s, duration: %d rounds." spellText = CGI->generaltexth->allTexts[610]; //"%s, duration: %d rounds."
boost::replace_first(spellText, "%s", spell->getNameTranslated()); boost::replace_first(spellText, "%s", spell->getNameTranslated());
//FIXME: support permanent duration //FIXME: support permanent duration
int duration = battleStack->getBonusLocalFirst(Selector::source(BonusSource::SPELL_EFFECT, TBonusSourceID(effect)))->turnsRemain; int duration = battleStack->getBonusLocalFirst(Selector::source(BonusSource::SPELL_EFFECT, BonusSourceID(effect)))->turnsRemain;
boost::replace_first(spellText, "%d", std::to_string(duration)); boost::replace_first(spellText, "%d", std::to_string(duration));
spellIcons.push_back(std::make_shared<CAnimImage>(AnimationPath::builtin("SpellInt"), effect + 1, 0, firstPos.x + offset.x * printed, firstPos.y + offset.y * printed)); spellIcons.push_back(std::make_shared<CAnimImage>(AnimationPath::builtin("SpellInt"), effect + 1, 0, firstPos.x + offset.x * printed, firstPos.y + offset.y * printed));

View File

@ -579,7 +579,7 @@ void CKingdomInterface::generateMinesList(const std::vector<const CGObjectInstan
std::vector<const CGHeroInstance*> heroes = LOCPLINT->cb->getHeroesInfo(true); std::vector<const CGHeroInstance*> heroes = LOCPLINT->cb->getHeroesInfo(true);
for(auto & heroe : heroes) for(auto & heroe : heroes)
{ {
totalIncome += heroe->valOfBonuses(Selector::typeSubtype(BonusType::GENERATE_RESOURCE, TBonusSubtype(GameResID(EGameResID::GOLD)))); totalIncome += heroe->valOfBonuses(Selector::typeSubtype(BonusType::GENERATE_RESOURCE, BonusSubtypeID(GameResID(EGameResID::GOLD))));
} }
//Add town income of all towns //Add town income of all towns

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/BonusSubtypeID.cpp ${MAIN_LIB_DIR}/bonuses/BonusCustomTypes.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
@ -358,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/BonusSubtypeID.h ${MAIN_LIB_DIR}/bonuses/BonusCustomTypes.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

@ -145,7 +145,7 @@ DLL_LINKAGE CArtifactInstance * ArtifactUtils::createScroll(const SpellID & sid)
{ {
auto ret = new CArtifactInstance(VLC->arth->objects[ArtifactID::SPELL_SCROLL]); auto ret = new CArtifactInstance(VLC->arth->objects[ArtifactID::SPELL_SCROLL]);
auto bonus = std::make_shared<Bonus>(BonusDuration::PERMANENT, BonusType::SPELL, auto bonus = std::make_shared<Bonus>(BonusDuration::PERMANENT, BonusType::SPELL,
BonusSource::ARTIFACT_INSTANCE, -1, TBonusSourceID(ArtifactID(ArtifactID::SPELL_SCROLL)), TBonusSubtype(sid)); BonusSource::ARTIFACT_INSTANCE, -1, BonusSourceID(ArtifactID(ArtifactID::SPELL_SCROLL)), BonusSubtypeID(sid));
ret->addNewBonus(bonus); ret->addNewBonus(bonus);
return ret; return ret;
} }

View File

@ -35,7 +35,7 @@ TerrainId AFactionMember::getNativeTerrain() const
{ {
constexpr auto any = TerrainId(ETerrainId::ANY_TERRAIN); constexpr auto any = TerrainId(ETerrainId::ANY_TERRAIN);
const std::string cachingStringNoTerrainPenalty = "type_NO_TERRAIN_PENALTY_sANY"; const std::string cachingStringNoTerrainPenalty = "type_NO_TERRAIN_PENALTY_sANY";
static const auto selectorNoTerrainPenalty = Selector::typeSubtype(BonusType::NO_TERRAIN_PENALTY, TBonusSubtype(any)); static const auto selectorNoTerrainPenalty = Selector::typeSubtype(BonusType::NO_TERRAIN_PENALTY, BonusSubtypeID(any));
//this code is used in the CreatureTerrainLimiter::limit to setup battle bonuses //this code is used in the CreatureTerrainLimiter::limit to setup battle bonuses
//and in the CGHeroInstance::getNativeTerrain() to setup movement bonuses or/and penalties. //and in the CGHeroInstance::getNativeTerrain() to setup movement bonuses or/and penalties.
@ -54,7 +54,7 @@ int AFactionMember::getAttack(bool ranged) const
{ {
const std::string cachingStr = "type_PRIMARY_SKILLs_ATTACK"; const std::string cachingStr = "type_PRIMARY_SKILLs_ATTACK";
static const auto selector = Selector::typeSubtype(BonusType::PRIMARY_SKILL, TBonusSubtype(PrimarySkill::ATTACK)); static const auto selector = Selector::typeSubtype(BonusType::PRIMARY_SKILL, BonusSubtypeID(PrimarySkill::ATTACK));
return getBonusBearer()->valOfBonuses(selector, cachingStr); return getBonusBearer()->valOfBonuses(selector, cachingStr);
} }
@ -63,7 +63,7 @@ int AFactionMember::getDefense(bool ranged) const
{ {
const std::string cachingStr = "type_PRIMARY_SKILLs_DEFENSE"; const std::string cachingStr = "type_PRIMARY_SKILLs_DEFENSE";
static const auto selector = Selector::typeSubtype(BonusType::PRIMARY_SKILL, TBonusSubtype(PrimarySkill::DEFENSE)); static const auto selector = Selector::typeSubtype(BonusType::PRIMARY_SKILL, BonusSubtypeID(PrimarySkill::DEFENSE));
return getBonusBearer()->valOfBonuses(selector, cachingStr); return getBonusBearer()->valOfBonuses(selector, cachingStr);
} }
@ -71,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, BonusSubtypeID::creatureDamageBoth).Or(Selector::typeSubtype(BonusType::CREATURE_DAMAGE, BonusSubtypeID::creatureDamageMin)); static const auto selector = Selector::typeSubtype(BonusType::CREATURE_DAMAGE, BonusCustomSubtype::creatureDamageBoth).Or(Selector::typeSubtype(BonusType::CREATURE_DAMAGE, BonusCustomSubtype::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, BonusSubtypeID::creatureDamageBoth).Or(Selector::typeSubtype(BonusType::CREATURE_DAMAGE, BonusSubtypeID::creatureDamageMax)); static const auto selector = Selector::typeSubtype(BonusType::CREATURE_DAMAGE, BonusCustomSubtype::creatureDamageBoth).Or(Selector::typeSubtype(BonusType::CREATURE_DAMAGE, BonusCustomSubtype::creatureDamageMax));
return getBonusBearer()->valOfBonuses(selector, cachingStr); return getBonusBearer()->valOfBonuses(selector, cachingStr);
} }
@ -87,7 +87,7 @@ int AFactionMember::getPrimSkillLevel(PrimarySkill id) const
static const CSelector selectorAllSkills = Selector::type()(BonusType::PRIMARY_SKILL); static const CSelector selectorAllSkills = Selector::type()(BonusType::PRIMARY_SKILL);
static const std::string keyAllSkills = "type_PRIMARY_SKILL"; static const std::string keyAllSkills = "type_PRIMARY_SKILL";
auto allSkills = getBonusBearer()->getBonuses(selectorAllSkills, keyAllSkills); auto allSkills = getBonusBearer()->getBonuses(selectorAllSkills, keyAllSkills);
auto ret = allSkills->valOfBonuses(Selector::subtype()(TBonusSubtype(id))); auto ret = allSkills->valOfBonuses(Selector::subtype()(BonusSubtypeID(id)));
auto minSkillValue = (id == PrimarySkill::SPELL_POWER || id == PrimarySkill::KNOWLEDGE) ? 1 : 0; auto minSkillValue = (id == PrimarySkill::SPELL_POWER || id == PrimarySkill::KNOWLEDGE) ? 1 : 0;
return std::max(ret, minSkillValue); //otherwise, some artifacts may cause negative skill value effect, sp=0 works in old saves return std::max(ret, minSkillValue); //otherwise, some artifacts may cause negative skill value effect, sp=0 works in old saves
} }

View File

@ -29,7 +29,7 @@ BattleFieldInfo * BattleFieldHandler::loadFromJson(const std::string & scope, co
auto bonus = JsonUtils::parseBonus(b); auto bonus = JsonUtils::parseBonus(b);
bonus->source = BonusSource::TERRAIN_OVERLAY; bonus->source = BonusSource::TERRAIN_OVERLAY;
bonus->sid = TBonusSourceID(info->getId()); bonus->sid = BonusSourceID(info->getId());
bonus->duration = BonusDuration::ONE_BATTLE; bonus->duration = BonusDuration::ONE_BATTLE;
info->bonuses.push_back(bonus); info->bonuses.push_back(bonus);

View File

@ -751,7 +751,7 @@ void CArtHandler::afterLoadFinalization()
{ {
assert(art == objects[art->id]); assert(art == objects[art->id]);
assert(bonus->source == BonusSource::ARTIFACT); assert(bonus->source == BonusSource::ARTIFACT);
bonus->sid = TBonusSourceID(art->id); bonus->sid = BonusSourceID(art->id);
} }
} }
CBonusSystemNode::treeHasChanged(); CBonusSystemNode::treeHasChanged();

View File

@ -168,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 == BonusSubtypeID::damageTypeMelee) if (bonus->subtype == BonusCustomSubtype::damageTypeMelee)
fileName = "DamageReductionMelee.bmp"; fileName = "DamageReductionMelee.bmp";
if (bonus->subtype == BonusSubtypeID::damageTypeRanged) if (bonus->subtype == BonusCustomSubtype::damageTypeRanged)
fileName = "DamageReductionRanged.bmp"; fileName = "DamageReductionRanged.bmp";
break; break;

View File

@ -113,25 +113,25 @@ FactionID CCreature::getFaction() const
int32_t CCreature::getBaseAttack() const int32_t CCreature::getBaseAttack() const
{ {
static const auto SELECTOR = Selector::typeSubtype(BonusType::PRIMARY_SKILL, TBonusSubtype(PrimarySkill::ATTACK)).And(Selector::sourceTypeSel(BonusSource::CREATURE_ABILITY)); static const auto SELECTOR = Selector::typeSubtype(BonusType::PRIMARY_SKILL, BonusSubtypeID(PrimarySkill::ATTACK)).And(Selector::sourceTypeSel(BonusSource::CREATURE_ABILITY));
return getExportedBonusList().valOfBonuses(SELECTOR); return getExportedBonusList().valOfBonuses(SELECTOR);
} }
int32_t CCreature::getBaseDefense() const int32_t CCreature::getBaseDefense() const
{ {
static const auto SELECTOR = Selector::typeSubtype(BonusType::PRIMARY_SKILL, TBonusSubtype(PrimarySkill::DEFENSE)).And(Selector::sourceTypeSel(BonusSource::CREATURE_ABILITY)); static const auto SELECTOR = Selector::typeSubtype(BonusType::PRIMARY_SKILL, BonusSubtypeID(PrimarySkill::DEFENSE)).And(Selector::sourceTypeSel(BonusSource::CREATURE_ABILITY));
return getExportedBonusList().valOfBonuses(SELECTOR); return getExportedBonusList().valOfBonuses(SELECTOR);
} }
int32_t CCreature::getBaseDamageMin() const int32_t CCreature::getBaseDamageMin() const
{ {
static const auto SELECTOR = Selector::typeSubtype(BonusType::CREATURE_DAMAGE, BonusSubtypeID::creatureDamageMin).And(Selector::sourceTypeSel(BonusSource::CREATURE_ABILITY)); static const auto SELECTOR = Selector::typeSubtype(BonusType::CREATURE_DAMAGE, BonusCustomSubtype::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, BonusSubtypeID::creatureDamageMax).And(Selector::sourceTypeSel(BonusSource::CREATURE_ABILITY)); static const auto SELECTOR = Selector::typeSubtype(BonusType::CREATURE_DAMAGE, BonusCustomSubtype::creatureDamageMax).And(Selector::sourceTypeSel(BonusSource::CREATURE_ABILITY));
return getExportedBonusList().valOfBonuses(SELECTOR); return getExportedBonusList().valOfBonuses(SELECTOR);
} }
@ -293,12 +293,12 @@ CCreature::CCreature()
void CCreature::addBonus(int val, BonusType type) void CCreature::addBonus(int val, BonusType type)
{ {
addBonus(val, type, TBonusSubtype()); addBonus(val, type, BonusSubtypeID());
} }
void CCreature::addBonus(int val, BonusType type, TBonusSubtype subtype) void CCreature::addBonus(int val, BonusType type, BonusSubtypeID subtype)
{ {
auto selector = Selector::typeSubtype(type, subtype).And(Selector::source(BonusSource::CREATURE_ABILITY, TBonusSourceID(getId()))); auto selector = Selector::typeSubtype(type, subtype).And(Selector::source(BonusSource::CREATURE_ABILITY, BonusSourceID(getId())));
BonusList & exported = getExportedBonusList(); BonusList & exported = getExportedBonusList();
BonusList existing; BonusList existing;
@ -306,7 +306,7 @@ void CCreature::addBonus(int val, BonusType type, TBonusSubtype subtype)
if(existing.empty()) if(existing.empty())
{ {
auto added = std::make_shared<Bonus>(BonusDuration::PERMANENT, type, BonusSource::CREATURE_ABILITY, val, TBonusSourceID(getId()), subtype, BonusValueType::BASE_NUMBER); auto added = std::make_shared<Bonus>(BonusDuration::PERMANENT, type, BonusSource::CREATURE_ABILITY, val, BonusSourceID(getId()), subtype, BonusValueType::BASE_NUMBER);
addNewBonus(added); addNewBonus(added);
} }
else else
@ -350,16 +350,16 @@ void CCreature::updateFrom(const JsonNode & data)
addBonus(configNode["speed"].Integer(), BonusType::STACKS_SPEED); addBonus(configNode["speed"].Integer(), BonusType::STACKS_SPEED);
if(!configNode["attack"].isNull()) if(!configNode["attack"].isNull())
addBonus(configNode["attack"].Integer(), BonusType::PRIMARY_SKILL, TBonusSubtype(PrimarySkill::ATTACK)); addBonus(configNode["attack"].Integer(), BonusType::PRIMARY_SKILL, BonusSubtypeID(PrimarySkill::ATTACK));
if(!configNode["defense"].isNull()) if(!configNode["defense"].isNull())
addBonus(configNode["defense"].Integer(), BonusType::PRIMARY_SKILL, TBonusSubtype(PrimarySkill::DEFENSE)); addBonus(configNode["defense"].Integer(), BonusType::PRIMARY_SKILL, BonusSubtypeID(PrimarySkill::DEFENSE));
if(!configNode["damage"]["min"].isNull()) if(!configNode["damage"]["min"].isNull())
addBonus(configNode["damage"]["min"].Integer(), BonusType::CREATURE_DAMAGE, BonusSubtypeID::creatureDamageMin); addBonus(configNode["damage"]["min"].Integer(), BonusType::CREATURE_DAMAGE, BonusCustomSubtype::creatureDamageMin);
if(!configNode["damage"]["max"].isNull()) if(!configNode["damage"]["max"].isNull())
addBonus(configNode["damage"]["max"].Integer(), BonusType::CREATURE_DAMAGE, BonusSubtypeID::creatureDamageMax); addBonus(configNode["damage"]["max"].Integer(), BonusType::CREATURE_DAMAGE, BonusCustomSubtype::creatureDamageMax);
if(!configNode["shots"].isNull()) if(!configNode["shots"].isNull())
addBonus(configNode["shots"].Integer(), BonusType::SHOTS); addBonus(configNode["shots"].Integer(), BonusType::SHOTS);
@ -609,11 +609,11 @@ CCreature * CCreatureHandler::loadFromJson(const std::string & scope, const Json
cre->addBonus(node["hitPoints"].Integer(), BonusType::STACK_HEALTH); cre->addBonus(node["hitPoints"].Integer(), BonusType::STACK_HEALTH);
cre->addBonus(node["speed"].Integer(), BonusType::STACKS_SPEED); cre->addBonus(node["speed"].Integer(), BonusType::STACKS_SPEED);
cre->addBonus(node["attack"].Integer(), BonusType::PRIMARY_SKILL, TBonusSubtype(PrimarySkill::ATTACK)); cre->addBonus(node["attack"].Integer(), BonusType::PRIMARY_SKILL, BonusSubtypeID(PrimarySkill::ATTACK));
cre->addBonus(node["defense"].Integer(), BonusType::PRIMARY_SKILL, TBonusSubtype(PrimarySkill::DEFENSE)); cre->addBonus(node["defense"].Integer(), BonusType::PRIMARY_SKILL, BonusSubtypeID(PrimarySkill::DEFENSE));
cre->addBonus(node["damage"]["min"].Integer(), BonusType::CREATURE_DAMAGE, BonusSubtypeID::creatureDamageMin); cre->addBonus(node["damage"]["min"].Integer(), BonusType::CREATURE_DAMAGE, BonusCustomSubtype::creatureDamageMin);
cre->addBonus(node["damage"]["max"].Integer(), BonusType::CREATURE_DAMAGE, BonusSubtypeID::creatureDamageMax); cre->addBonus(node["damage"]["max"].Integer(), BonusType::CREATURE_DAMAGE, BonusCustomSubtype::creatureDamageMax);
assert(node["damage"]["min"].Integer() <= node["damage"]["max"].Integer()); assert(node["damage"]["min"].Integer() <= node["damage"]["max"].Integer());
@ -792,7 +792,7 @@ void CCreatureHandler::loadCrExpBon(CBonusSystemNode & globalEffects)
{ {
CreatureID sid = static_cast<ui32>(parser.readNumber()); //id = this particular creature ID CreatureID sid = static_cast<ui32>(parser.readNumber()); //id = this particular creature ID
b.sid = TBonusSourceID(sid); b.sid = BonusSourceID(sid);
bl.clear(); bl.clear();
loadStackExp(b, bl, parser); loadStackExp(b, bl, parser);
for(const auto & b : bl) for(const auto & b : bl)
@ -898,7 +898,7 @@ void CCreatureHandler::loadCreatureJson(CCreature * creature, const JsonNode & c
{ {
auto b = JsonUtils::parseBonus(ability.second); auto b = JsonUtils::parseBonus(ability.second);
b->source = BonusSource::CREATURE_ABILITY; b->source = BonusSource::CREATURE_ABILITY;
b->sid = TBonusSourceID(creature->getId()); b->sid = BonusSourceID(creature->getId());
b->duration = BonusDuration::PERMANENT; b->duration = BonusDuration::PERMANENT;
creature->addNewBonus(b); creature->addNewBonus(b);
} }
@ -916,7 +916,7 @@ void CCreatureHandler::loadCreatureJson(CCreature * creature, const JsonNode & c
{ {
auto b = JsonUtils::parseBonus(ability); auto b = JsonUtils::parseBonus(ability);
b->source = BonusSource::CREATURE_ABILITY; b->source = BonusSource::CREATURE_ABILITY;
b->sid = TBonusSourceID(creature->getId()); b->sid = BonusSourceID(creature->getId());
b->duration = BonusDuration::PERMANENT; b->duration = BonusDuration::PERMANENT;
creature->addNewBonus(b); creature->addNewBonus(b);
} }
@ -1030,19 +1030,19 @@ void CCreatureHandler::loadStackExp(Bonus & b, BonusList & bl, CLegacyConfigPars
break; break;
case 'A': case 'A':
b.type = BonusType::PRIMARY_SKILL; b.type = BonusType::PRIMARY_SKILL;
b.subtype = TBonusSubtype(PrimarySkill::ATTACK); b.subtype = BonusSubtypeID(PrimarySkill::ATTACK);
break; break;
case 'D': case 'D':
b.type = BonusType::PRIMARY_SKILL; b.type = BonusType::PRIMARY_SKILL;
b.subtype = TBonusSubtype(PrimarySkill::DEFENSE); b.subtype = BonusSubtypeID(PrimarySkill::DEFENSE);
break; break;
case 'M': //Max damage case 'M': //Max damage
b.type = BonusType::CREATURE_DAMAGE; b.type = BonusType::CREATURE_DAMAGE;
b.subtype = BonusSubtypeID::creatureDamageMax; b.subtype = BonusCustomSubtype::creatureDamageMax;
break; break;
case 'm': //Min damage case 'm': //Min damage
b.type = BonusType::CREATURE_DAMAGE; b.type = BonusType::CREATURE_DAMAGE;
b.subtype = BonusSubtypeID::creatureDamageMin; b.subtype = BonusCustomSubtype::creatureDamageMin;
break; break;
case 'S': case 'S':
b.type = BonusType::STACKS_SPEED; break; b.type = BonusType::STACKS_SPEED; break;
@ -1059,13 +1059,13 @@ 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 = BonusSubtypeID::deathStareGorgon; b.subtype = BonusCustomSubtype::deathStareGorgon;
break; break;
case 'F': case 'F':
b.type = BonusType::FEAR; break; b.type = BonusType::FEAR; break;
case 'g': case 'g':
b.type = BonusType::SPELL_DAMAGE_REDUCTION; b.type = BonusType::SPELL_DAMAGE_REDUCTION;
b.subtype = TBonusSubtype(SpellSchool::ANY); b.subtype = BonusSubtypeID(SpellSchool::ANY);
break; break;
case 'P': case 'P':
b.type = BonusType::CASTS; break; b.type = BonusType::CASTS; break;
@ -1106,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 = BonusSubtypeID::rebirthRegular; b.subtype = BonusCustomSubtype::rebirthRegular;
b.val = 20; //arbitrary value b.val = 20; //arbitrary value
break; break;
case 'R': case 'R':
@ -1129,42 +1129,42 @@ void CCreatureHandler::loadStackExp(Bonus & b, BonusList & bl, CLegacyConfigPars
{ {
case 'B': //Blind case 'B': //Blind
b.type = BonusType::SPELL_IMMUNITY; b.type = BonusType::SPELL_IMMUNITY;
b.subtype = TBonusSubtype(SpellID(SpellID::BLIND)); b.subtype = BonusSubtypeID(SpellID(SpellID::BLIND));
b.additionalInfo = 0;//normal immunity b.additionalInfo = 0;//normal immunity
break; break;
case 'H': //Hypnotize case 'H': //Hypnotize
b.type = BonusType::SPELL_IMMUNITY; b.type = BonusType::SPELL_IMMUNITY;
b.subtype = TBonusSubtype(SpellID(SpellID::HYPNOTIZE)); b.subtype = BonusSubtypeID(SpellID(SpellID::HYPNOTIZE));
b.additionalInfo = 0;//normal immunity b.additionalInfo = 0;//normal immunity
break; break;
case 'I': //Implosion case 'I': //Implosion
b.type = BonusType::SPELL_IMMUNITY; b.type = BonusType::SPELL_IMMUNITY;
b.subtype = TBonusSubtype(SpellID(SpellID::IMPLOSION)); b.subtype = BonusSubtypeID(SpellID(SpellID::IMPLOSION));
b.additionalInfo = 0;//normal immunity b.additionalInfo = 0;//normal immunity
break; break;
case 'K': //Berserk case 'K': //Berserk
b.type = BonusType::SPELL_IMMUNITY; b.type = BonusType::SPELL_IMMUNITY;
b.subtype = TBonusSubtype(SpellID(SpellID::BERSERK)); b.subtype = BonusSubtypeID(SpellID(SpellID::BERSERK));
b.additionalInfo = 0;//normal immunity b.additionalInfo = 0;//normal immunity
break; break;
case 'M': //Meteor Shower case 'M': //Meteor Shower
b.type = BonusType::SPELL_IMMUNITY; b.type = BonusType::SPELL_IMMUNITY;
b.subtype = TBonusSubtype(SpellID(SpellID::METEOR_SHOWER)); b.subtype = BonusSubtypeID(SpellID(SpellID::METEOR_SHOWER));
b.additionalInfo = 0;//normal immunity b.additionalInfo = 0;//normal immunity
break; break;
case 'N': //dispell beneficial spells case 'N': //dispell beneficial spells
b.type = BonusType::SPELL_IMMUNITY; b.type = BonusType::SPELL_IMMUNITY;
b.subtype = TBonusSubtype(SpellID(SpellID::DISPEL_HELPFUL_SPELLS)); b.subtype = BonusSubtypeID(SpellID(SpellID::DISPEL_HELPFUL_SPELLS));
b.additionalInfo = 0;//normal immunity b.additionalInfo = 0;//normal immunity
break; break;
case 'R': //Armageddon case 'R': //Armageddon
b.type = BonusType::SPELL_IMMUNITY; b.type = BonusType::SPELL_IMMUNITY;
b.subtype = TBonusSubtype(SpellID(SpellID::ARMAGEDDON)); b.subtype = BonusSubtypeID(SpellID(SpellID::ARMAGEDDON));
b.additionalInfo = 0;//normal immunity b.additionalInfo = 0;//normal immunity
break; break;
case 'S': //Slow case 'S': //Slow
b.type = BonusType::SPELL_IMMUNITY; b.type = BonusType::SPELL_IMMUNITY;
b.subtype = TBonusSubtype(SpellID(SpellID::SLOW)); b.subtype = BonusSubtypeID(SpellID(SpellID::SLOW));
b.additionalInfo = 0;//normal immunity b.additionalInfo = 0;//normal immunity
break; break;
case '6': case '6':
@ -1180,51 +1180,51 @@ void CCreatureHandler::loadStackExp(Bonus & b, BonusList & bl, CLegacyConfigPars
break; break;
case 'F': case 'F':
b.type = BonusType::NEGATIVE_EFFECTS_IMMUNITY; b.type = BonusType::NEGATIVE_EFFECTS_IMMUNITY;
b.subtype = TBonusSubtype(SpellSchool::FIRE); b.subtype = BonusSubtypeID(SpellSchool::FIRE);
break; break;
case 'O': case 'O':
b.type = BonusType::SPELL_DAMAGE_REDUCTION; b.type = BonusType::SPELL_DAMAGE_REDUCTION;
b.subtype = TBonusSubtype(SpellSchool::FIRE); b.subtype = BonusSubtypeID(SpellSchool::FIRE);
b.val = 100; //Full damage immunity b.val = 100; //Full damage immunity
break; break;
case 'f': case 'f':
b.type = BonusType::SPELL_SCHOOL_IMMUNITY; b.type = BonusType::SPELL_SCHOOL_IMMUNITY;
b.subtype = TBonusSubtype(SpellSchool::FIRE); b.subtype = BonusSubtypeID(SpellSchool::FIRE);
break; break;
case 'C': case 'C':
b.type = BonusType::NEGATIVE_EFFECTS_IMMUNITY; b.type = BonusType::NEGATIVE_EFFECTS_IMMUNITY;
b.subtype = TBonusSubtype(SpellSchool::WATER); b.subtype = BonusSubtypeID(SpellSchool::WATER);
break; break;
case 'W': case 'W':
b.type = BonusType::SPELL_DAMAGE_REDUCTION; b.type = BonusType::SPELL_DAMAGE_REDUCTION;
b.subtype = TBonusSubtype(SpellSchool::WATER); b.subtype = BonusSubtypeID(SpellSchool::WATER);
b.val = 100; //Full damage immunity b.val = 100; //Full damage immunity
break; break;
case 'w': case 'w':
b.type = BonusType::SPELL_SCHOOL_IMMUNITY; b.type = BonusType::SPELL_SCHOOL_IMMUNITY;
b.subtype = TBonusSubtype(SpellSchool::WATER); b.subtype = BonusSubtypeID(SpellSchool::WATER);
break; break;
case 'E': case 'E':
b.type = BonusType::SPELL_DAMAGE_REDUCTION; b.type = BonusType::SPELL_DAMAGE_REDUCTION;
b.subtype = TBonusSubtype(SpellSchool::EARTH); b.subtype = BonusSubtypeID(SpellSchool::EARTH);
b.val = 100; //Full damage immunity b.val = 100; //Full damage immunity
break; break;
case 'e': case 'e':
b.type = BonusType::SPELL_SCHOOL_IMMUNITY; b.type = BonusType::SPELL_SCHOOL_IMMUNITY;
b.subtype = TBonusSubtype(SpellSchool::EARTH); b.subtype = BonusSubtypeID(SpellSchool::EARTH);
break; break;
case 'A': case 'A':
b.type = BonusType::SPELL_DAMAGE_REDUCTION; b.type = BonusType::SPELL_DAMAGE_REDUCTION;
b.subtype = TBonusSubtype(SpellSchool::AIR); b.subtype = BonusSubtypeID(SpellSchool::AIR);
b.val = 100; //Full damage immunity b.val = 100; //Full damage immunity
break; break;
case 'a': case 'a':
b.type = BonusType::SPELL_SCHOOL_IMMUNITY; b.type = BonusType::SPELL_SCHOOL_IMMUNITY;
b.subtype = TBonusSubtype(SpellSchool::AIR); b.subtype = BonusSubtypeID(SpellSchool::AIR);
break; break;
case 'D': case 'D':
b.type = BonusType::SPELL_DAMAGE_REDUCTION; b.type = BonusType::SPELL_DAMAGE_REDUCTION;
b.subtype = TBonusSubtype(SpellSchool::ANY); b.subtype = BonusSubtypeID(SpellSchool::ANY);
b.val = 100; //Full damage immunity b.val = 100; //Full damage immunity
break; break;
case '0': case '0':
@ -1253,16 +1253,16 @@ void CCreatureHandler::loadStackExp(Bonus & b, BonusList & bl, CLegacyConfigPars
case 'K': case 'K':
case 'k': case 'k':
b.type = BonusType::SPELL_AFTER_ATTACK; b.type = BonusType::SPELL_AFTER_ATTACK;
b.subtype = TBonusSubtype(SpellID(stringToNumber(mod))); b.subtype = BonusSubtypeID(SpellID(stringToNumber(mod)));
break; break;
case 'h': case 'h':
b.type = BonusType::HATE; b.type = BonusType::HATE;
b.subtype = TBonusSubtype(CreatureID(stringToNumber(mod))); b.subtype = BonusSubtypeID(CreatureID(stringToNumber(mod)));
break; break;
case 'p': case 'p':
case 'J': case 'J':
b.type = BonusType::SPELL_BEFORE_ATTACK; b.type = BonusType::SPELL_BEFORE_ATTACK;
b.subtype = TBonusSubtype(SpellID(stringToNumber(mod))); b.subtype = BonusSubtypeID(SpellID(stringToNumber(mod)));
b.additionalInfo = 3; //always expert? b.additionalInfo = 3; //always expert?
break; break;
case 'r': case 'r':
@ -1271,7 +1271,7 @@ void CCreatureHandler::loadStackExp(Bonus & b, BonusList & bl, CLegacyConfigPars
break; break;
case 's': case 's':
b.type = BonusType::ENCHANTED; b.type = BonusType::ENCHANTED;
b.subtype = TBonusSubtype(SpellID(stringToNumber(mod))); b.subtype = BonusSubtypeID(SpellID(stringToNumber(mod)));
b.valType = BonusValueType::INDEPENDENT_MAX; b.valType = BonusValueType::INDEPENDENT_MAX;
break; break;
default: default:

View File

@ -195,7 +195,7 @@ public:
bool valid() const; bool valid() const;
void addBonus(int val, BonusType type); void addBonus(int val, BonusType type);
void addBonus(int val, BonusType type, TBonusSubtype subtype); void addBonus(int val, BonusType type, BonusSubtypeID subtype);
std::string nodeName() const override; std::string nodeName() const override;
template<typename RanGen> template<typename RanGen>

View File

@ -268,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, BonusSubtypeID::visionsTowns); detailed = selectedHero->hasVisions(town, BonusCustomSubtype::visionsTowns);
} }
dest.initFromTown(dynamic_cast<const CGTownInstance *>(town), detailed); dest.initFromTown(dynamic_cast<const CGTownInstance *>(town), detailed);
@ -322,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, BonusSubtypeID::visionsHeroes)) if(selectedHero->hasVisions(hero, BonusCustomSubtype::visionsHeroes))
infoLevel = InfoAboutHero::EInfoLevel::DETAILED; infoLevel = InfoAboutHero::EInfoLevel::DETAILED;
} }

View File

@ -547,7 +547,7 @@ static std::vector<std::shared_ptr<Bonus>> createCreatureSpecialty(CreatureID ba
{ {
std::shared_ptr<Bonus> bonus = std::make_shared<Bonus>(); std::shared_ptr<Bonus> bonus = std::make_shared<Bonus>();
bonus->type = BonusType::PRIMARY_SKILL; bonus->type = BonusType::PRIMARY_SKILL;
bonus->subtype = TBonusSubtype(PrimarySkill::ATTACK); bonus->subtype = BonusSubtypeID(PrimarySkill::ATTACK);
bonus->val = 0; bonus->val = 0;
bonus->limiter.reset(new CCreatureTypeLimiter(specCreature, false)); bonus->limiter.reset(new CCreatureTypeLimiter(specCreature, false));
bonus->updater.reset(new GrowsWithLevelUpdater(specCreature.getAttack(false), stepSize)); bonus->updater.reset(new GrowsWithLevelUpdater(specCreature.getAttack(false), stepSize));
@ -557,7 +557,7 @@ static std::vector<std::shared_ptr<Bonus>> createCreatureSpecialty(CreatureID ba
{ {
std::shared_ptr<Bonus> bonus = std::make_shared<Bonus>(); std::shared_ptr<Bonus> bonus = std::make_shared<Bonus>();
bonus->type = BonusType::PRIMARY_SKILL; bonus->type = BonusType::PRIMARY_SKILL;
bonus->subtype = TBonusSubtype(PrimarySkill::DEFENSE); bonus->subtype = BonusSubtypeID(PrimarySkill::DEFENSE);
bonus->val = 0; bonus->val = 0;
bonus->limiter.reset(new CCreatureTypeLimiter(specCreature, false)); bonus->limiter.reset(new CCreatureTypeLimiter(specCreature, false));
bonus->updater.reset(new GrowsWithLevelUpdater(specCreature.getDefense(false), stepSize)); bonus->updater.reset(new GrowsWithLevelUpdater(specCreature.getDefense(false), stepSize));
@ -605,7 +605,7 @@ void CHeroHandler::loadHeroSpecialty(CHero * hero, const JsonNode & node)
{ {
bonus->duration = BonusDuration::PERMANENT; bonus->duration = BonusDuration::PERMANENT;
bonus->source = BonusSource::HERO_SPECIAL; bonus->source = BonusSource::HERO_SPECIAL;
bonus->sid = TBonusSourceID(hero->getId()); bonus->sid = BonusSourceID(hero->getId());
return bonus; return bonus;
}; };

View File

@ -93,7 +93,7 @@ SecondarySkill CSkill::getId() const
void CSkill::addNewBonus(const std::shared_ptr<Bonus> & b, int level) void CSkill::addNewBonus(const std::shared_ptr<Bonus> & b, int level)
{ {
b->source = BonusSource::SECONDARY_SKILL; b->source = BonusSource::SECONDARY_SKILL;
b->sid = TBonusSourceID(id); b->sid = BonusSourceID(id);
b->duration = BonusDuration::PERMANENT; b->duration = BonusDuration::PERMANENT;
b->description = getNameTranslated(); b->description = getNameTranslated();
levels[level-1].effects.push_back(b); levels[level-1].effects.push_back(b);

View File

@ -220,7 +220,7 @@ void CStack::prepareAttacked(BattleStackAttacked & bsa, vstd::RNG & rand, const
resurrectedCount += 1; resurrectedCount += 1;
} }
if(customState->hasBonusOfType(BonusType::REBIRTH, BonusSubtypeID::rebirthSpecial)) if(customState->hasBonusOfType(BonusType::REBIRTH, BonusCustomSubtype::rebirthSpecial))
{ {
// resurrect at least one Sacred Phoenix // resurrect at least one Sacred Phoenix
vstd::amax(resurrectedCount, 1); vstd::amax(resurrectedCount, 1);

View File

@ -551,16 +551,16 @@ void CTownHandler::addBonusesForVanilaBuilding(CBuilding * building) const
b = createBonus(building, BonusType::LUCK, +2); b = createBonus(building, BonusType::LUCK, +2);
break; break;
case BuildingSubID::SPELL_POWER_GARRISON_BONUS: case BuildingSubID::SPELL_POWER_GARRISON_BONUS:
b = createBonus(building, BonusType::PRIMARY_SKILL, +2, TBonusSubtype(PrimarySkill::SPELL_POWER)); b = createBonus(building, BonusType::PRIMARY_SKILL, +2, BonusSubtypeID(PrimarySkill::SPELL_POWER));
break; break;
case BuildingSubID::ATTACK_GARRISON_BONUS: case BuildingSubID::ATTACK_GARRISON_BONUS:
b = createBonus(building, BonusType::PRIMARY_SKILL, +2, TBonusSubtype(PrimarySkill::ATTACK)); b = createBonus(building, BonusType::PRIMARY_SKILL, +2, BonusSubtypeID(PrimarySkill::ATTACK));
break; break;
case BuildingSubID::DEFENSE_GARRISON_BONUS: case BuildingSubID::DEFENSE_GARRISON_BONUS:
b = createBonus(building, BonusType::PRIMARY_SKILL, +2, TBonusSubtype(PrimarySkill::DEFENSE)); b = createBonus(building, BonusType::PRIMARY_SKILL, +2, BonusSubtypeID(PrimarySkill::DEFENSE));
break; break;
case BuildingSubID::LIGHTHOUSE: case BuildingSubID::LIGHTHOUSE:
b = createBonus(building, BonusType::MOVEMENT, +500, BonusSubtypeID::heroMovementSea, playerPropagator); b = createBonus(building, BonusType::MOVEMENT, +500, BonusCustomSubtype::heroMovementSea, playerPropagator);
break; break;
} }
@ -570,15 +570,15 @@ 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(), emptyPropagator()); return createBonus(build, type, val, BonusSubtypeID(), 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, BonusSubtypeID subtype) const
{ {
return createBonus(build, type, val, subtype, emptyPropagator()); return createBonus(build, type, val, subtype, emptyPropagator());
} }
std::shared_ptr<Bonus> CTownHandler::createBonus(CBuilding * build, BonusType type, int val, TBonusSubtype subtype, TPropagatorPtr & prop) const std::shared_ptr<Bonus> CTownHandler::createBonus(CBuilding * build, BonusType type, int val, BonusSubtypeID subtype, TPropagatorPtr & prop) const
{ {
std::ostringstream descr; std::ostringstream descr;
descr << build->getNameTranslated(); descr << build->getNameTranslated();
@ -591,7 +591,7 @@ std::shared_ptr<Bonus> CTownHandler::createBonusImpl(const BuildingID & building
int val, int val,
TPropagatorPtr & prop, TPropagatorPtr & prop,
const std::string & description, const std::string & description,
TBonusSubtype subtype) const BonusSubtypeID subtype) const
{ {
auto b = std::make_shared<Bonus>(BonusDuration::PERMANENT, type, BonusSource::TOWN_STRUCTURE, val, BuildingTypeUniqueID(faction, building), subtype, description); auto b = std::make_shared<Bonus>(BonusDuration::PERMANENT, type, BonusSource::TOWN_STRUCTURE, val, BuildingTypeUniqueID(faction, building), subtype, description);
@ -610,7 +610,7 @@ void CTownHandler::loadSpecialBuildingBonuses(const JsonNode & source, BonusList
if(bonus == nullptr) if(bonus == nullptr)
continue; continue;
bonus->sid = TBonusSourceID(building->getUniqueTypeID()); bonus->sid = BonusSourceID(building->getUniqueTypeID());
//JsonUtils::parseBuildingBonus produces UNKNOWN type propagator instead of empty. //JsonUtils::parseBuildingBonus produces UNKNOWN type propagator instead of empty.
if(bonus->propagator != nullptr if(bonus->propagator != nullptr
&& bonus->propagator->getPropagatorType() == CBonusSystemNode::ENodeTypes::UNKNOWN) && bonus->propagator->getPropagatorType() == CBonusSystemNode::ENodeTypes::UNKNOWN)
@ -674,7 +674,7 @@ void CTownHandler::loadBuilding(CTown * town, const std::string & stringID, cons
ret->subId = BuildingSubID::CUSTOM_VISITING_BONUS; ret->subId = BuildingSubID::CUSTOM_VISITING_BONUS;
for(auto & bonus : ret->onVisitBonuses) for(auto & bonus : ret->onVisitBonuses)
bonus->sid = TBonusSourceID(ret->getUniqueTypeID()); bonus->sid = BonusSourceID(ret->getUniqueTypeID());
} }
if(source["type"].String() == "configurable" && ret->subId == BuildingSubID::NONE) if(source["type"].String() == "configurable" && ret->subId == BuildingSubID::NONE)

View File

@ -392,15 +392,15 @@ class DLL_LINKAGE CTownHandler : public CHandlerBase<FactionID, Faction, CFactio
void loadBuildings(CTown * town, const JsonNode & source); void loadBuildings(CTown * town, const JsonNode & source);
std::shared_ptr<Bonus> createBonus(CBuilding * build, BonusType type, int val) const; std::shared_ptr<Bonus> createBonus(CBuilding * build, BonusType type, int val) 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, BonusSubtypeID 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, BonusSubtypeID subtype, TPropagatorPtr & prop) const;
std::shared_ptr<Bonus> createBonusImpl(const BuildingID & building, std::shared_ptr<Bonus> createBonusImpl(const BuildingID & building,
const FactionID & faction, 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; BonusSubtypeID subtype) const;
/// loads CStructure's into town /// loads CStructure's into town
void loadStructure(CTown & town, const std::string & stringID, const JsonNode & source) const; void loadStructure(CTown & town, const std::string & stringID, const JsonNode & source) const;

View File

@ -417,25 +417,25 @@ std::string JsonNode::toJson(bool compact) const
///JsonUtils ///JsonUtils
static void loadBonusSubtype(TBonusSubtype & subtype, BonusType type, const JsonNode & node) static void loadBonusSubtype(BonusSubtypeID & subtype, BonusType type, const JsonNode & node)
{ {
if (node.isNull()) if (node.isNull())
{ {
subtype = TBonusSubtype(); subtype = BonusSubtypeID();
return; return;
} }
if (node.isNumber()) // Compatibility code for 1.3 or older if (node.isNumber()) // Compatibility code for 1.3 or older
{ {
logMod->warn("Bonus subtype must be string!"); logMod->warn("Bonus subtype must be string!");
subtype = BonusSubtypeID(node.Integer()); subtype = BonusCustomSubtype(node.Integer());
return; return;
} }
if (!node.isString()) if (!node.isString())
{ {
logMod->warn("Bonus subtype must be string!"); logMod->warn("Bonus subtype must be string!");
subtype = TBonusSubtype(); subtype = BonusSubtypeID();
return; return;
} }
@ -538,7 +538,7 @@ static void loadBonusSubtype(TBonusSubtype & subtype, BonusType type, const Json
{ {
VLC->identifiers()->requestIdentifier( "bonusSubtype", node, [&subtype](int32_t identifier) VLC->identifiers()->requestIdentifier( "bonusSubtype", node, [&subtype](int32_t identifier)
{ {
subtype = BonusSubtypeID(identifier); subtype = BonusCustomSubtype(identifier);
}); });
break; break;
} }
@ -546,29 +546,29 @@ static void loadBonusSubtype(TBonusSubtype & subtype, BonusType type, const Json
for(const auto & i : bonusNameMap) for(const auto & i : bonusNameMap)
if(i.second == type) if(i.second == type)
logMod->warn("Bonus type %s does not supports subtypes!", i.first ); logMod->warn("Bonus type %s does not supports subtypes!", i.first );
subtype = TBonusSubtype(); subtype = BonusSubtypeID();
} }
} }
static void loadBonusSourceInstance(TBonusSourceID & sourceInstance, BonusSource sourceType, const JsonNode & node) static void loadBonusSourceInstance(BonusSourceID & sourceInstance, BonusSource sourceType, const JsonNode & node)
{ {
if (node.isNull()) if (node.isNull())
{ {
sourceInstance = BonusSourceID(); sourceInstance = BonusCustomSource();
return; return;
} }
if (node.isNumber()) // Compatibility code for 1.3 or older if (node.isNumber()) // Compatibility code for 1.3 or older
{ {
logMod->warn("Bonus source must be string!"); logMod->warn("Bonus source must be string!");
sourceInstance = BonusSourceID(node.Integer()); sourceInstance = BonusCustomSource(node.Integer());
return; return;
} }
if (!node.isString()) if (!node.isString())
{ {
logMod->warn("Bonus source must be string!"); logMod->warn("Bonus source must be string!");
sourceInstance = BonusSourceID(); sourceInstance = BonusCustomSource();
return; return;
} }
@ -643,7 +643,7 @@ static void loadBonusSourceInstance(TBonusSourceID & sourceInstance, BonusSource
case BonusSource::TERRAIN_NATIVE: case BonusSource::TERRAIN_NATIVE:
case BonusSource::OTHER: case BonusSource::OTHER:
default: default:
sourceInstance = TBonusSourceID(); sourceInstance = BonusSourceID();
break; break;
} }
} }
@ -1181,13 +1181,13 @@ CSelector JsonUtils::parseSelector(const JsonNode & ability)
value = &ability["subtype"]; value = &ability["subtype"];
if(!value->isNull() && type != BonusType::NONE) if(!value->isNull() && type != BonusType::NONE)
{ {
TBonusSubtype subtype; BonusSubtypeID subtype;
loadBonusSubtype(subtype, type, ability); loadBonusSubtype(subtype, type, ability);
ret = ret.And(Selector::subtype()(subtype)); ret = ret.And(Selector::subtype()(subtype));
} }
value = &ability["sourceType"]; value = &ability["sourceType"];
std::optional<BonusSource> src = std::nullopt; //Fixes for GCC false maybe-uninitialized std::optional<BonusSource> src = std::nullopt; //Fixes for GCC false maybe-uninitialized
std::optional<TBonusSourceID> id = std::nullopt; std::optional<BonusSourceID> id = std::nullopt;
if(value->isString()) if(value->isString())
{ {
auto it = bonusSourceMap.find(value->String()); auto it = bonusSourceMap.find(value->String());

View File

@ -497,7 +497,7 @@ struct DLL_LINKAGE RemoveBonus : public CPackForClient
//vars to identify bonus: its source //vars to identify bonus: its source
BonusSource source; BonusSource source;
TBonusSourceID id; //source id BonusSourceID id; //source id
//used locally: copy of removed bonus //used locally: copy of removed bonus
Bonus bonus; Bonus bonus;

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())->addLimiter(nativeTerrain)); curB->addNewBonus(std::make_shared<Bonus>(BonusDuration::ONE_BATTLE, BonusType::STACKS_SPEED, BonusSource::TERRAIN_NATIVE, 1, BonusSourceID())->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, BonusSourceID(), BonusSubtypeID(PrimarySkill::ATTACK))->addLimiter(nativeTerrain));
curB->addNewBonus(std::make_shared<Bonus>(BonusDuration::ONE_BATTLE, BonusType::PRIMARY_SKILL, BonusSource::TERRAIN_NATIVE, 1, TBonusSourceID(), TBonusSubtype(PrimarySkill::DEFENSE))->addLimiter(nativeTerrain)); curB->addNewBonus(std::make_shared<Bonus>(BonusDuration::ONE_BATTLE, BonusType::PRIMARY_SKILL, BonusSource::TERRAIN_NATIVE, 1, BonusSourceID(), BonusSubtypeID(PrimarySkill::DEFENSE))->addLimiter(nativeTerrain));
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
//tactics //tactics

View File

@ -1658,7 +1658,7 @@ SpellID CBattleInfoCallback::getRandomBeneficialSpell(CRandomGenerator & rand, c
std::stringstream cachingStr; std::stringstream cachingStr;
cachingStr << "source_" << vstd::to_underlying(BonusSource::SPELL_EFFECT) << "id_" << spellID.num; cachingStr << "source_" << vstd::to_underlying(BonusSource::SPELL_EFFECT) << "id_" << spellID.num;
if(subject->hasBonus(Selector::source(BonusSource::SPELL_EFFECT, TBonusSourceID(spellID)), Selector::all, cachingStr.str()) if(subject->hasBonus(Selector::source(BonusSource::SPELL_EFFECT, BonusSourceID(spellID)), Selector::all, cachingStr.str())
//TODO: this ability has special limitations //TODO: this ability has special limitations
|| !(spellID.toSpell()->canBeCast(this, spells::Mode::CREATURE_ACTIVE, subject))) || !(spellID.toSpell()->canBeCast(this, spells::Mode::CREATURE_ACTIVE, subject)))
continue; continue;

View File

@ -340,12 +340,12 @@ 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, BonusSubtypeID::creatureDamageBoth).Or(Selector::typeSubtype(BonusType::CREATURE_DAMAGE, BonusSubtypeID::creatureDamageMin)), 0), minDamage(this, Selector::typeSubtype(BonusType::CREATURE_DAMAGE, BonusCustomSubtype::creatureDamageBoth).Or(Selector::typeSubtype(BonusType::CREATURE_DAMAGE, BonusCustomSubtype::creatureDamageMin)), 0),
maxDamage(this, Selector::typeSubtype(BonusType::CREATURE_DAMAGE, BonusSubtypeID::creatureDamageBoth).Or(Selector::typeSubtype(BonusType::CREATURE_DAMAGE, BonusSubtypeID::creatureDamageMax)), 0), maxDamage(this, Selector::typeSubtype(BonusType::CREATURE_DAMAGE, BonusCustomSubtype::creatureDamageBoth).Or(Selector::typeSubtype(BonusType::CREATURE_DAMAGE, BonusCustomSubtype::creatureDamageMax)), 0),
attack(this, Selector::typeSubtype(BonusType::PRIMARY_SKILL, TBonusSubtype(PrimarySkill::ATTACK)), 0), attack(this, Selector::typeSubtype(BonusType::PRIMARY_SKILL, BonusSubtypeID(PrimarySkill::ATTACK)), 0),
defence(this, Selector::typeSubtype(BonusType::PRIMARY_SKILL, TBonusSubtype(PrimarySkill::DEFENSE)), 0), defence(this, Selector::typeSubtype(BonusType::PRIMARY_SKILL, BonusSubtypeID(PrimarySkill::DEFENSE)), 0),
inFrenzy(this, Selector::type()(BonusType::IN_FRENZY)), inFrenzy(this, Selector::type()(BonusType::IN_FRENZY)),
cloneLifetimeMarker(this, Selector::type()(BonusType::NONE).And(Selector::source(BonusSource::SPELL_EFFECT, TBonusSourceID(SpellID(SpellID::CLONE))))), cloneLifetimeMarker(this, Selector::type()(BonusType::NONE).And(Selector::source(BonusSource::SPELL_EFFECT, BonusSourceID(SpellID(SpellID::CLONE))))),
cloneID(-1) cloneID(-1)
{ {
@ -430,7 +430,7 @@ const CGHeroInstance * CUnitState::getHeroCaster() const
int32_t CUnitState::getSpellSchoolLevel(const spells::Spell * spell, int32_t * outSelectedSchool) const int32_t CUnitState::getSpellSchoolLevel(const spells::Spell * spell, int32_t * outSelectedSchool) const
{ {
int32_t skill = valOfBonuses(Selector::typeSubtype(BonusType::SPELLCASTER, TBonusSubtype(spell->getId()))); int32_t skill = valOfBonuses(Selector::typeSubtype(BonusType::SPELLCASTER, BonusSubtypeID(spell->getId())));
vstd::abetween(skill, 0, 3); vstd::abetween(skill, 0, 3);
return skill; return skill;
} }
@ -466,7 +466,7 @@ int32_t CUnitState::getEnchantPower(const spells::Spell * spell) const
int64_t CUnitState::getEffectValue(const spells::Spell * spell) const int64_t CUnitState::getEffectValue(const spells::Spell * spell) const
{ {
return static_cast<int64_t>(getCount()) * valOfBonuses(BonusType::SPECIFIC_SPELL_POWER, TBonusSubtype(spell->getId())); return static_cast<int64_t>(getCount()) * valOfBonuses(BonusType::SPECIFIC_SPELL_POWER, BonusSubtypeID(spell->getId()));
} }
PlayerColor CUnitState::getCasterOwner() const PlayerColor CUnitState::getCasterOwner() const
@ -511,7 +511,7 @@ bool CUnitState::isGhost() const
bool CUnitState::isFrozen() const bool CUnitState::isFrozen() const
{ {
return hasBonus(Selector::source(BonusSource::SPELL_EFFECT, TBonusSourceID(SpellID(SpellID::STONE_GAZE))), Selector::all); return hasBonus(Selector::source(BonusSource::SPELL_EFFECT, BonusSourceID(SpellID(SpellID::STONE_GAZE))), Selector::all);
} }
bool CUnitState::isValidTarget(bool allowDead) const bool CUnitState::isValidTarget(bool allowDead) const

View File

@ -52,7 +52,7 @@ DamageRange DamageCalculator::getBaseDamageSingle() const
{ {
auto retrieveHeroPrimSkill = [&](PrimarySkill skill) -> int auto retrieveHeroPrimSkill = [&](PrimarySkill skill) -> int
{ {
std::shared_ptr<const Bonus> b = info.attacker->getBonus(Selector::sourceTypeSel(BonusSource::HERO_BASE_SKILL).And(Selector::typeSubtype(BonusType::PRIMARY_SKILL, TBonusSubtype(skill)))); std::shared_ptr<const Bonus> b = info.attacker->getBonus(Selector::sourceTypeSel(BonusSource::HERO_BASE_SKILL).And(Selector::typeSubtype(BonusType::PRIMARY_SKILL, BonusSubtypeID(skill))));
return b ? b->val : 0; return b ? b->val : 0;
}; };
@ -144,7 +144,7 @@ int DamageCalculator::getActorAttackSlayer() const
{ {
SpellID spell(SpellID::SLAYER); SpellID spell(SpellID::SLAYER);
int attackBonus = spell.toSpell()->getLevelPower(spLevel); int attackBonus = spell.toSpell()->getLevelPower(spLevel);
if(info.attacker->hasBonusOfType(BonusType::SPECIAL_PECULIAR_ENCHANT, TBonusSubtype(spell))) if(info.attacker->hasBonusOfType(BonusType::SPECIAL_PECULIAR_ENCHANT, BonusSubtypeID(spell)))
{ {
ui8 attackerTier = info.attacker->unitType()->getLevel(); ui8 attackerTier = info.attacker->unitType()->getLevel();
ui8 specialtyBonus = std::max(5 - attackerTier, 0); ui8 specialtyBonus = std::max(5 - attackerTier, 0);
@ -206,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, BonusSubtypeID::damageTypeRanged); static const auto selectorArchery = Selector::typeSubtype(BonusType::PERCENTAGE_DAMAGE_BOOST, BonusCustomSubtype::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, BonusSubtypeID::damageTypeMelee); static const auto selectorOffence = Selector::typeSubtype(BonusType::PERCENTAGE_DAMAGE_BOOST, BonusCustomSubtype::damageTypeMelee);
return info.attacker->valOfBonuses(selectorOffence, cachingStrOffence) / 100.0; return info.attacker->valOfBonuses(selectorOffence, cachingStrOffence) / 100.0;
} }
@ -232,7 +232,7 @@ double DamageCalculator::getAttackDoubleDamageFactor() const
{ {
if(info.doubleDamage) { if(info.doubleDamage) {
const auto cachingStr = "type_BONUS_DAMAGE_PERCENTAGEs_" + std::to_string(info.attacker->creatureIndex()); const auto cachingStr = "type_BONUS_DAMAGE_PERCENTAGEs_" + std::to_string(info.attacker->creatureIndex());
const auto selector = Selector::typeSubtype(BonusType::BONUS_DAMAGE_PERCENTAGE, TBonusSubtype(info.attacker->creatureId())); const auto selector = Selector::typeSubtype(BonusType::BONUS_DAMAGE_PERCENTAGE, BonusSubtypeID(info.attacker->creatureId()));
return info.attacker->valOfBonuses(selector, cachingStr) / 100.0; return info.attacker->valOfBonuses(selector, cachingStr) / 100.0;
} }
return 0.0; return 0.0;
@ -260,7 +260,7 @@ double DamageCalculator::getAttackHateFactor() const
auto allHateEffects = info.attacker->getBonuses(selectorHate, cachingStrHate); auto allHateEffects = info.attacker->getBonuses(selectorHate, cachingStrHate);
return allHateEffects->valOfBonuses(Selector::subtype()(TBonusSubtype(info.defender->creatureId()))) / 100.0; return allHateEffects->valOfBonuses(Selector::subtype()(BonusSubtypeID(info.defender->creatureId()))) / 100.0;
} }
double DamageCalculator::getDefenseSkillFactor() const double DamageCalculator::getDefenseSkillFactor() const
@ -282,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, BonusSubtypeID::damageTypeAll).And(Selector::sourceTypeSel(BonusSource::SPELL_EFFECT).Not()); static const auto selectorArmorer = Selector::typeSubtype(BonusType::GENERAL_DAMAGE_REDUCTION, BonusCustomSubtype::damageTypeAll).And(Selector::sourceTypeSel(BonusSource::SPELL_EFFECT).Not());
return info.defender->valOfBonuses(selectorArmorer, cachingStrArmorer) / 100.0; return info.defender->valOfBonuses(selectorArmorer, cachingStrArmorer) / 100.0;
} }
@ -290,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, BonusSubtypeID::damageTypeMelee); static const auto selectorMeleeReduction = Selector::typeSubtype(BonusType::GENERAL_DAMAGE_REDUCTION, BonusCustomSubtype::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, BonusSubtypeID::damageTypeRanged); static const auto selectorRangedReduction = Selector::typeSubtype(BonusType::GENERAL_DAMAGE_REDUCTION, BonusCustomSubtype::damageTypeRanged);
//handling spell effects - shield and air shield //handling spell effects - shield and air shield
if(info.shooting) if(info.shooting)
@ -313,7 +313,7 @@ double DamageCalculator::getDefenseRangePenaltiesFactor() const
auto isAdvancedAirShield = [](const Bonus* bonus) auto isAdvancedAirShield = [](const Bonus* bonus)
{ {
return bonus->source == BonusSource::SPELL_EFFECT return bonus->source == BonusSource::SPELL_EFFECT
&& bonus->sid == TBonusSourceID(SpellID(SpellID::AIR_SHIELD)) && bonus->sid == BonusSourceID(SpellID(SpellID::AIR_SHIELD))
&& bonus->val >= MasteryLevel::ADVANCED; && bonus->val >= MasteryLevel::ADVANCED;
}; };
@ -387,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, BonusSubtypeID::damageTypeAll).And(Selector::sourceTypeSel(BonusSource::SPELL_EFFECT)); static const auto selectorAllReduction = Selector::typeSubtype(BonusType::GENERAL_DAMAGE_REDUCTION, BonusCustomSubtype::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()) if(subtype != BonusSubtypeID())
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()) if(sid != BonusSourceID())
root["sourceID"].String() = sid.toString(); root["sourceID"].String() = sid.toString();
if(val != 0) if(val != 0)
root["val"].Integer() = val; root["val"].Integer() = val;
@ -183,19 +183,19 @@ JsonNode Bonus::toJsonNode() const
return root; return root;
} }
Bonus::Bonus(BonusDuration::Type Duration, BonusType Type, BonusSource Src, si32 Val, TBonusSourceID ID) Bonus::Bonus(BonusDuration::Type Duration, BonusType Type, BonusSource Src, si32 Val, BonusSourceID ID)
: Bonus(Duration, Type, Src, Val, ID, TBonusSubtype(), std::string()) : Bonus(Duration, Type, Src, Val, ID, BonusSubtypeID(), 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, BonusSourceID ID, std::string Desc)
: Bonus(Duration, Type, Src, Val, ID, TBonusSubtype(), Desc) : Bonus(Duration, Type, Src, Val, ID, BonusSubtypeID(), 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, BonusSourceID ID, BonusSubtypeID Subtype)
: Bonus(Duration, Type, Src, Val, ID, Subtype, std::string()) : Bonus(Duration, Type, Src, Val, ID, Subtype, std::string())
{} {}
Bonus::Bonus(BonusDuration::Type Duration, BonusType Type, BonusSource Src, si32 Val, TBonusSourceID ID, TBonusSubtype Subtype, std::string Desc): Bonus::Bonus(BonusDuration::Type Duration, BonusType Type, BonusSource Src, si32 Val, BonusSourceID ID, BonusSubtypeID Subtype, std::string Desc):
duration(Duration), duration(Duration),
type(Type), type(Type),
subtype(Subtype), subtype(Subtype),
@ -208,7 +208,7 @@ Bonus::Bonus(BonusDuration::Type Duration, BonusType Type, BonusSource Src, si32
targetSourceType = BonusSource::OTHER; targetSourceType = BonusSource::OTHER;
} }
Bonus::Bonus(BonusDuration::Type Duration, BonusType Type, BonusSource Src, si32 Val, TBonusSourceID ID, TBonusSubtype Subtype, BonusValueType ValType): Bonus::Bonus(BonusDuration::Type Duration, BonusType Type, BonusSource Src, si32 Val, BonusSourceID ID, BonusSubtypeID Subtype, BonusValueType ValType):
duration(Duration), duration(Duration),
type(Type), type(Type),
subtype(Subtype), subtype(Subtype),

View File

@ -10,7 +10,7 @@
#pragma once #pragma once
#include "BonusEnum.h" #include "BonusEnum.h"
#include "BonusSubtypeID.h" #include "BonusCustomTypes.h"
#include "../constants/VariantIdentifier.h" #include "../constants/VariantIdentifier.h"
#include "../constants/EntityIdentifiers.h" #include "../constants/EntityIdentifiers.h"
@ -25,8 +25,8 @@ class IUpdater;
class BonusList; class BonusList;
class CSelector; class CSelector;
using TBonusSubtype = VariantIdentifier<BonusSubtypeID, SpellID, CreatureID, PrimarySkill, TerrainId, GameResID, SpellSchool>; using BonusSubtypeID = VariantIdentifier<BonusCustomSubtype, SpellID, CreatureID, PrimarySkill, TerrainId, GameResID, SpellSchool>;
using TBonusSourceID = VariantIdentifier<BonusSourceID, SpellID, CreatureID, ArtifactID, CampaignScenarioID, SecondarySkill, HeroTypeID, Obj, ObjectInstanceID, BuildingTypeUniqueID, BattleField>; using BonusSourceID = VariantIdentifier<BonusCustomSource, 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>;
@ -60,12 +60,12 @@ struct DLL_LINKAGE Bonus : public std::enable_shared_from_this<Bonus>
si16 turnsRemain = 0; //used if duration is N_TURNS, N_DAYS or ONE_WEEK si16 turnsRemain = 0; //used if duration is N_TURNS, N_DAYS or ONE_WEEK
BonusType type = BonusType::NONE; //uses BonusType values - says to what is this bonus - 1 byte BonusType type = BonusType::NONE; //uses BonusType values - says to what is this bonus - 1 byte
TBonusSubtype subtype; BonusSubtypeID subtype;
BonusSource source = BonusSource::OTHER; //source type" uses BonusSource values - what gave that bonus BonusSource source = BonusSource::OTHER; //source type" uses BonusSource values - what gave that bonus
BonusSource targetSourceType;//Bonuses of what origin this amplifies, uses BonusSource values. Needed for PERCENT_TO_TARGET_TYPE. BonusSource targetSourceType;//Bonuses of what origin this amplifies, uses BonusSource values. Needed for PERCENT_TO_TARGET_TYPE.
si32 val = 0; si32 val = 0;
TBonusSourceID sid; //source id: id of object/artifact/spell BonusSourceID sid; //source id: id of object/artifact/spell
BonusValueType valType = BonusValueType::ADDITIVE_VALUE; BonusValueType valType = BonusValueType::ADDITIVE_VALUE;
std::string stacking; // bonuses with the same stacking value don't stack (e.g. Angel/Archangel morale bonus) std::string stacking; // bonuses with the same stacking value don't stack (e.g. Angel/Archangel morale bonus)
@ -79,11 +79,11 @@ struct DLL_LINKAGE Bonus : public std::enable_shared_from_this<Bonus>
std::string description; std::string description;
Bonus(BonusDuration::Type Duration, BonusType Type, BonusSource Src, si32 Val, TBonusSourceID sourceID); Bonus(BonusDuration::Type Duration, BonusType Type, BonusSource Src, si32 Val, BonusSourceID sourceID);
Bonus(BonusDuration::Type Duration, BonusType Type, BonusSource Src, si32 Val, TBonusSourceID sourceID, std::string Desc); Bonus(BonusDuration::Type Duration, BonusType Type, BonusSource Src, si32 Val, BonusSourceID sourceID, std::string Desc);
Bonus(BonusDuration::Type Duration, BonusType Type, BonusSource Src, si32 Val, TBonusSourceID sourceID, TBonusSubtype subtype); Bonus(BonusDuration::Type Duration, BonusType Type, BonusSource Src, si32 Val, BonusSourceID sourceID, BonusSubtypeID subtype);
Bonus(BonusDuration::Type Duration, BonusType Type, BonusSource Src, si32 Val, TBonusSourceID sourceID, TBonusSubtype subtype, std::string Desc); Bonus(BonusDuration::Type Duration, BonusType Type, BonusSource Src, si32 Val, BonusSourceID sourceID, BonusSubtypeID subtype, std::string Desc);
Bonus(BonusDuration::Type Duration, BonusType Type, BonusSource Src, si32 Val, TBonusSourceID sourceID, TBonusSubtype subtype, BonusValueType ValType); Bonus(BonusDuration::Type Duration, BonusType Type, BonusSource Src, si32 Val, BonusSourceID sourceID, BonusSubtypeID subtype, BonusValueType ValType);
Bonus() = default; Bonus() = default;
template <typename Handler> void serialize(Handler &h, const int version) template <typename Handler> void serialize(Handler &h, const int version)

View File

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

View File

@ -0,0 +1,75 @@
/*
* BonusCustomTypes.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 BonusCustomSource : public Identifier<BonusCustomSource>
{
public:
using Identifier<BonusCustomSource>::Identifier;
static std::string encode(int32_t index);
static si32 decode(const std::string & identifier);
static const BonusCustomSource undeadMoraleDebuff; // -2
};
class DLL_LINKAGE BonusCustomSubtype : public Identifier<BonusCustomSubtype>
{
public:
using Identifier<BonusCustomSubtype>::Identifier;
static std::string encode(int32_t index);
static si32 decode(const std::string & identifier);
static const BonusCustomSubtype creatureDamageBoth; // 0
static const BonusCustomSubtype creatureDamageMin; // 1
static const BonusCustomSubtype creatureDamageMax; // 2
static const BonusCustomSubtype damageTypeAll; // -1
static const BonusCustomSubtype damageTypeMelee; // 0
static const BonusCustomSubtype damageTypeRanged; // 1
static const BonusCustomSubtype heroMovementLand; // 1
static const BonusCustomSubtype heroMovementSea; // 0
static const BonusCustomSubtype deathStareGorgon; // 0
static const BonusCustomSubtype deathStareCommander;
static const BonusCustomSubtype rebirthRegular; // 0
static const BonusCustomSubtype rebirthSpecial; // 1
static const BonusCustomSubtype visionsMonsters; // 0
static const BonusCustomSubtype visionsHeroes; // 1
static const BonusCustomSubtype visionsTowns; // 2
static const BonusCustomSubtype immunityBattleWide; // 0
static const BonusCustomSubtype immunityEnemyHero; // 1
static const BonusCustomSubtype transmutationPerHealth; // 0
static const BonusCustomSubtype transmutationPerUnit; // 1
static const BonusCustomSubtype destructionKillPercentage; // 0
static const BonusCustomSubtype destructionKillAmount; // 1
static const BonusCustomSubtype soulStealPermanent; // 0
static const BonusCustomSubtype soulStealBattle; // 1
static const BonusCustomSubtype movementFlying; // 0
static const BonusCustomSubtype movementTeleporting; // 1
static BonusCustomSubtype spellLevel(int level);
static BonusCustomSubtype creatureLevel(int level);
};
VCMI_LIB_NAMESPACE_END

View File

@ -84,66 +84,66 @@ BonusParams::BonusParams(std::string deprecatedTypeStr, std::string deprecatedSu
else if(deprecatedSubtype == SecondarySkill::SORCERY || deprecatedSubtypeStr == "skill.sorcery") else if(deprecatedSubtype == SecondarySkill::SORCERY || deprecatedSubtypeStr == "skill.sorcery")
{ {
type = BonusType::SPELL_DAMAGE; type = BonusType::SPELL_DAMAGE;
subtype = TBonusSubtype(SpellSchool::ANY); subtype = BonusSubtypeID(SpellSchool::ANY);
} }
else if(deprecatedSubtype == SecondarySkill::SCHOLAR || deprecatedSubtypeStr == "skill.scholar") else if(deprecatedSubtype == SecondarySkill::SCHOLAR || deprecatedSubtypeStr == "skill.scholar")
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 = BonusSubtypeID::damageTypeRanged; subtype = BonusCustomSubtype::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 = BonusSubtypeID::damageTypeMelee; subtype = BonusCustomSubtype::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 = BonusSubtypeID::damageTypeAll; subtype = BonusCustomSubtype::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 = BonusSubtypeID::heroMovementSea; subtype = BonusCustomSubtype::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 = BonusSubtypeID::heroMovementLand; subtype = BonusCustomSubtype::heroMovementLand;
valueType = BonusValueType::PERCENT_TO_BASE; valueType = BonusValueType::PERCENT_TO_BASE;
type = BonusType::MOVEMENT; type = BonusType::MOVEMENT;
} }
else if(deprecatedSubtype == SecondarySkill::ESTATES || deprecatedSubtypeStr == "skill.estates") else if(deprecatedSubtype == SecondarySkill::ESTATES || deprecatedSubtypeStr == "skill.estates")
{ {
type = BonusType::GENERATE_RESOURCE; type = BonusType::GENERATE_RESOURCE;
subtype = TBonusSubtype(GameResID(EGameResID::GOLD)); subtype = BonusSubtypeID(GameResID(EGameResID::GOLD));
} }
else if(deprecatedSubtype == SecondarySkill::AIR_MAGIC || deprecatedSubtypeStr == "skill.airMagic") else if(deprecatedSubtype == SecondarySkill::AIR_MAGIC || deprecatedSubtypeStr == "skill.airMagic")
{ {
type = BonusType::MAGIC_SCHOOL_SKILL; type = BonusType::MAGIC_SCHOOL_SKILL;
subtype = TBonusSubtype(SpellSchool::AIR); subtype = BonusSubtypeID(SpellSchool::AIR);
} }
else if(deprecatedSubtype == SecondarySkill::WATER_MAGIC || deprecatedSubtypeStr == "skill.waterMagic") else if(deprecatedSubtype == SecondarySkill::WATER_MAGIC || deprecatedSubtypeStr == "skill.waterMagic")
{ {
type = BonusType::MAGIC_SCHOOL_SKILL; type = BonusType::MAGIC_SCHOOL_SKILL;
subtype = TBonusSubtype(SpellSchool::WATER); subtype = BonusSubtypeID(SpellSchool::WATER);
} }
else if(deprecatedSubtype == SecondarySkill::FIRE_MAGIC || deprecatedSubtypeStr == "skill.fireMagic") else if(deprecatedSubtype == SecondarySkill::FIRE_MAGIC || deprecatedSubtypeStr == "skill.fireMagic")
{ {
type = BonusType::MAGIC_SCHOOL_SKILL; type = BonusType::MAGIC_SCHOOL_SKILL;
subtype = TBonusSubtype(SpellSchool::FIRE); subtype = BonusSubtypeID(SpellSchool::FIRE);
} }
else if(deprecatedSubtype == SecondarySkill::EARTH_MAGIC || deprecatedSubtypeStr == "skill.earthMagic") else if(deprecatedSubtype == SecondarySkill::EARTH_MAGIC || deprecatedSubtypeStr == "skill.earthMagic")
{ {
type = BonusType::MAGIC_SCHOOL_SKILL; type = BonusType::MAGIC_SCHOOL_SKILL;
subtype = TBonusSubtype(SpellSchool::EARTH); subtype = BonusSubtypeID(SpellSchool::EARTH);
} }
else if (deprecatedSubtype == SecondarySkill::ARTILLERY || deprecatedSubtypeStr == "skill.artillery") else if (deprecatedSubtype == SecondarySkill::ARTILLERY || deprecatedSubtypeStr == "skill.artillery")
{ {
type = BonusType::BONUS_DAMAGE_CHANCE; type = BonusType::BONUS_DAMAGE_CHANCE;
subtype = TBonusSubtype(CreatureID(CreatureID::BALLISTA)); subtype = BonusSubtypeID(CreatureID(CreatureID::BALLISTA));
} }
else if (deprecatedSubtype == SecondarySkill::FIRST_AID || deprecatedSubtypeStr == "skill.firstAid") else if (deprecatedSubtype == SecondarySkill::FIRST_AID || deprecatedSubtypeStr == "skill.firstAid")
{ {
@ -165,20 +165,20 @@ BonusParams::BonusParams(std::string deprecatedTypeStr, std::string deprecatedSu
else if (deprecatedSubtype == SecondarySkill::ARTILLERY || deprecatedSubtypeStr == "skill.artillery") else if (deprecatedSubtype == SecondarySkill::ARTILLERY || deprecatedSubtypeStr == "skill.artillery")
{ {
type = BonusType::HERO_GRANTS_ATTACKS; type = BonusType::HERO_GRANTS_ATTACKS;
subtype = TBonusSubtype(CreatureID(CreatureID::BALLISTA)); subtype = BonusSubtypeID(CreatureID(CreatureID::BALLISTA));
} }
else else
isConverted = false; isConverted = false;
} }
else if (deprecatedTypeStr == "SEA_MOVEMENT") else if (deprecatedTypeStr == "SEA_MOVEMENT")
{ {
subtype = BonusSubtypeID::heroMovementSea; subtype = BonusCustomSubtype::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 = BonusSubtypeID::heroMovementLand; subtype = BonusCustomSubtype::heroMovementLand;
valueType = BonusValueType::ADDITIVE_VALUE; valueType = BonusValueType::ADDITIVE_VALUE;
type = BonusType::MOVEMENT; type = BonusType::MOVEMENT;
} }
@ -226,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 = TBonusSubtype(SpellSchool::ANY); subtype = BonusSubtypeID(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 = TBonusSubtype(SpellSchool::AIR); subtype = BonusSubtypeID(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 = TBonusSubtype(SpellSchool::FIRE); subtype = BonusSubtypeID(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 = TBonusSubtype(SpellSchool::WATER); subtype = BonusSubtypeID(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 = TBonusSubtype(SpellSchool::EARTH); subtype = BonusSubtypeID(SpellSchool::EARTH);
} }
else if (deprecatedTypeStr == "AIR_SPELLS") else if (deprecatedTypeStr == "AIR_SPELLS")
{ {
type = BonusType::SPELLS_OF_SCHOOL; type = BonusType::SPELLS_OF_SCHOOL;
subtype = TBonusSubtype(SpellSchool::AIR); subtype = BonusSubtypeID(SpellSchool::AIR);
} }
else if (deprecatedTypeStr == "FIRE_SPELLS") else if (deprecatedTypeStr == "FIRE_SPELLS")
{ {
type = BonusType::SPELLS_OF_SCHOOL; type = BonusType::SPELLS_OF_SCHOOL;
subtype = TBonusSubtype(SpellSchool::FIRE); subtype = BonusSubtypeID(SpellSchool::FIRE);
} }
else if (deprecatedTypeStr == "WATER_SPELLS") else if (deprecatedTypeStr == "WATER_SPELLS")
{ {
type = BonusType::SPELLS_OF_SCHOOL; type = BonusType::SPELLS_OF_SCHOOL;
subtype = TBonusSubtype(SpellSchool::WATER); subtype = BonusSubtypeID(SpellSchool::WATER);
} }
else if (deprecatedTypeStr == "EARTH_SPELLS") else if (deprecatedTypeStr == "EARTH_SPELLS")
{ {
type = BonusType::SPELLS_OF_SCHOOL; type = BonusType::SPELLS_OF_SCHOOL;
subtype = TBonusSubtype(SpellSchool::EARTH); subtype = BonusSubtypeID(SpellSchool::EARTH);
} }
else if (deprecatedTypeStr == "AIR_IMMUNITY") else if (deprecatedTypeStr == "AIR_IMMUNITY")
{ {
subtype = TBonusSubtype(SpellSchool::AIR); subtype = BonusSubtypeID(SpellSchool::AIR);
switch(deprecatedSubtype) switch(deprecatedSubtype)
{ {
case 0: case 0:
@ -287,7 +287,7 @@ BonusParams::BonusParams(std::string deprecatedTypeStr, std::string deprecatedSu
} }
else if (deprecatedTypeStr == "FIRE_IMMUNITY") else if (deprecatedTypeStr == "FIRE_IMMUNITY")
{ {
subtype = TBonusSubtype(SpellSchool::FIRE); subtype = BonusSubtypeID(SpellSchool::FIRE);
switch(deprecatedSubtype) switch(deprecatedSubtype)
{ {
case 0: case 0:
@ -303,7 +303,7 @@ BonusParams::BonusParams(std::string deprecatedTypeStr, std::string deprecatedSu
} }
else if (deprecatedTypeStr == "WATER_IMMUNITY") else if (deprecatedTypeStr == "WATER_IMMUNITY")
{ {
subtype = TBonusSubtype(SpellSchool::WATER); subtype = BonusSubtypeID(SpellSchool::WATER);
switch(deprecatedSubtype) switch(deprecatedSubtype)
{ {
case 0: case 0:
@ -319,7 +319,7 @@ BonusParams::BonusParams(std::string deprecatedTypeStr, std::string deprecatedSu
} }
else if (deprecatedTypeStr == "EARTH_IMMUNITY") else if (deprecatedTypeStr == "EARTH_IMMUNITY")
{ {
subtype = TBonusSubtype(SpellSchool::EARTH); subtype = BonusSubtypeID(SpellSchool::EARTH);
switch(deprecatedSubtype) switch(deprecatedSubtype)
{ {
case 0: case 0:

View File

@ -19,7 +19,7 @@ VCMI_LIB_NAMESPACE_BEGIN
struct DLL_LINKAGE BonusParams { struct DLL_LINKAGE BonusParams {
bool isConverted; bool isConverted;
BonusType type = BonusType::NONE; BonusType type = BonusType::NONE;
std::optional<TBonusSubtype> subtype = std::nullopt; std::optional<BonusSubtypeID> subtype = std::nullopt;
std::optional<BonusValueType> valueType = std::nullopt; std::optional<BonusValueType> valueType = std::nullopt;
std::optional<si32> val = std::nullopt; std::optional<si32> val = std::nullopt;
std::optional<BonusSource> targetType = std::nullopt; std::optional<BonusSource> targetType = std::nullopt;

View File

@ -21,9 +21,9 @@ namespace Selector
return stype; return stype;
} }
DLL_LINKAGE CSelectFieldEqual<TBonusSubtype> & subtype() DLL_LINKAGE CSelectFieldEqual<BonusSubtypeID> & subtype()
{ {
static CSelectFieldEqual<TBonusSubtype> ssubtype(&Bonus::subtype); static CSelectFieldEqual<BonusSubtypeID> ssubtype(&Bonus::subtype);
return ssubtype; return ssubtype;
} }
@ -54,22 +54,22 @@ namespace Selector
DLL_LINKAGE CWillLastTurns turns; DLL_LINKAGE CWillLastTurns turns;
DLL_LINKAGE CWillLastDays days; DLL_LINKAGE CWillLastDays days;
CSelector DLL_LINKAGE typeSubtype(BonusType Type, TBonusSubtype Subtype) CSelector DLL_LINKAGE typeSubtype(BonusType Type, BonusSubtypeID Subtype)
{ {
return type()(Type).And(subtype()(Subtype)); return type()(Type).And(subtype()(Subtype));
} }
CSelector DLL_LINKAGE typeSubtypeInfo(BonusType type, TBonusSubtype subtype, const CAddInfo & info) CSelector DLL_LINKAGE typeSubtypeInfo(BonusType type, BonusSubtypeID subtype, const CAddInfo & info)
{ {
return CSelectFieldEqual<BonusType>(&Bonus::type)(type) return CSelectFieldEqual<BonusType>(&Bonus::type)(type)
.And(CSelectFieldEqual<TBonusSubtype>(&Bonus::subtype)(subtype)) .And(CSelectFieldEqual<BonusSubtypeID>(&Bonus::subtype)(subtype))
.And(CSelectFieldEqual<CAddInfo>(&Bonus::additionalInfo)(info)); .And(CSelectFieldEqual<CAddInfo>(&Bonus::additionalInfo)(info));
} }
CSelector DLL_LINKAGE source(BonusSource source, TBonusSourceID sourceID) CSelector DLL_LINKAGE source(BonusSource source, BonusSourceID sourceID)
{ {
return CSelectFieldEqual<BonusSource>(&Bonus::source)(source) return CSelectFieldEqual<BonusSource>(&Bonus::source)(source)
.And(CSelectFieldEqual<TBonusSourceID>(&Bonus::sid)(sourceID)); .And(CSelectFieldEqual<BonusSourceID>(&Bonus::sid)(sourceID));
} }
CSelector DLL_LINKAGE sourceTypeSel(BonusSource source) CSelector DLL_LINKAGE sourceTypeSel(BonusSource source)

View File

@ -126,7 +126,7 @@ public:
namespace Selector namespace Selector
{ {
extern DLL_LINKAGE CSelectFieldEqual<BonusType> & type(); extern DLL_LINKAGE CSelectFieldEqual<BonusType> & type();
extern DLL_LINKAGE CSelectFieldEqual<TBonusSubtype> & subtype(); extern DLL_LINKAGE CSelectFieldEqual<BonusSubtypeID> & subtype();
extern DLL_LINKAGE CSelectFieldEqual<CAddInfo> & info(); extern DLL_LINKAGE CSelectFieldEqual<CAddInfo> & info();
extern DLL_LINKAGE CSelectFieldEqual<BonusSource> & sourceType(); extern DLL_LINKAGE CSelectFieldEqual<BonusSource> & sourceType();
extern DLL_LINKAGE CSelectFieldEqual<BonusSource> & targetSourceType(); extern DLL_LINKAGE CSelectFieldEqual<BonusSource> & targetSourceType();
@ -134,9 +134,9 @@ namespace Selector
extern DLL_LINKAGE CWillLastTurns turns; extern DLL_LINKAGE CWillLastTurns turns;
extern DLL_LINKAGE CWillLastDays days; extern DLL_LINKAGE CWillLastDays days;
CSelector DLL_LINKAGE typeSubtype(BonusType Type, TBonusSubtype Subtype); CSelector DLL_LINKAGE typeSubtype(BonusType Type, BonusSubtypeID Subtype);
CSelector DLL_LINKAGE typeSubtypeInfo(BonusType type, TBonusSubtype subtype, const CAddInfo & info); CSelector DLL_LINKAGE typeSubtypeInfo(BonusType type, BonusSubtypeID subtype, const CAddInfo & info);
CSelector DLL_LINKAGE source(BonusSource source, TBonusSourceID sourceID); CSelector DLL_LINKAGE source(BonusSource source, BonusSourceID sourceID);
CSelector DLL_LINKAGE sourceTypeSel(BonusSource source); CSelector DLL_LINKAGE sourceTypeSel(BonusSource source);
CSelector DLL_LINKAGE valueType(BonusValueType valType); CSelector DLL_LINKAGE valueType(BonusValueType valType);

View File

@ -1,74 +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 "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::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

@ -1,75 +0,0 @@
/*
* 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 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

@ -62,7 +62,7 @@ bool IBonusBearer::hasBonusOfType(BonusType type) const
return hasBonus(s, cachingStr); return hasBonus(s, cachingStr);
} }
int IBonusBearer::valOfBonuses(BonusType type, TBonusSubtype subtype) const int IBonusBearer::valOfBonuses(BonusType type, BonusSubtypeID subtype) const
{ {
//This part is performance-critical //This part is performance-critical
std::string cachingStr = "type_" + std::to_string(static_cast<int>(type)) + "_" + subtype.toString(); std::string cachingStr = "type_" + std::to_string(static_cast<int>(type)) + "_" + subtype.toString();
@ -72,7 +72,7 @@ int IBonusBearer::valOfBonuses(BonusType type, TBonusSubtype subtype) const
return valOfBonuses(s, cachingStr); return valOfBonuses(s, cachingStr);
} }
bool IBonusBearer::hasBonusOfType(BonusType type, TBonusSubtype subtype) const bool IBonusBearer::hasBonusOfType(BonusType type, BonusSubtypeID subtype) const
{ {
//This part is performance-critical //This part is performance-critical
std::string cachingStr = "type_" + std::to_string(static_cast<int>(type)) + "_" + subtype.toString(); std::string cachingStr = "type_" + std::to_string(static_cast<int>(type)) + "_" + subtype.toString();
@ -82,7 +82,7 @@ bool IBonusBearer::hasBonusOfType(BonusType type, TBonusSubtype subtype) const
return hasBonus(s, cachingStr); return hasBonus(s, cachingStr);
} }
bool IBonusBearer::hasBonusFrom(BonusSource source, TBonusSourceID sourceID) const bool IBonusBearer::hasBonusFrom(BonusSource source, BonusSourceID sourceID) const
{ {
boost::format fmt("source_%did_%s"); boost::format fmt("source_%did_%s");
fmt % static_cast<int>(source) % sourceID.toString(); fmt % static_cast<int>(source) % sourceID.toString();

View File

@ -35,9 +35,9 @@ public:
//Optimized interface (with auto-caching) //Optimized interface (with auto-caching)
int valOfBonuses(BonusType type) const; //subtype -> subtype of bonus; int valOfBonuses(BonusType type) const; //subtype -> subtype of bonus;
bool hasBonusOfType(BonusType type) const;//determines if hero has a bonus of given type (and optionally subtype) bool hasBonusOfType(BonusType type) const;//determines if hero has a bonus of given type (and optionally subtype)
int valOfBonuses(BonusType type, TBonusSubtype subtype) const; //subtype -> subtype of bonus; int valOfBonuses(BonusType type, BonusSubtypeID subtype) const; //subtype -> subtype of bonus;
bool hasBonusOfType(BonusType type, TBonusSubtype subtype) const;//determines if hero has a bonus of given type (and optionally subtype) bool hasBonusOfType(BonusType type, BonusSubtypeID subtype) const;//determines if hero has a bonus of given type (and optionally subtype)
bool hasBonusFrom(BonusSource source, TBonusSourceID sourceID) const; bool hasBonusFrom(BonusSource source, BonusSourceID sourceID) const;
virtual int64_t getTreeVersion() const = 0; virtual int64_t getTreeVersion() const = 0;
}; };

View File

@ -140,7 +140,7 @@ HasAnotherBonusLimiter::HasAnotherBonusLimiter( BonusType bonus )
{ {
} }
HasAnotherBonusLimiter::HasAnotherBonusLimiter( BonusType bonus, TBonusSubtype _subtype ) HasAnotherBonusLimiter::HasAnotherBonusLimiter( BonusType bonus, BonusSubtypeID _subtype )
: type(bonus), subtype(_subtype), isSubtypeRelevant(true), isSourceRelevant(false), isSourceIDRelevant(false) : type(bonus), subtype(_subtype), isSubtypeRelevant(true), isSourceRelevant(false), isSourceIDRelevant(false)
{ {
} }
@ -150,7 +150,7 @@ HasAnotherBonusLimiter::HasAnotherBonusLimiter(BonusType bonus, BonusSource src)
{ {
} }
HasAnotherBonusLimiter::HasAnotherBonusLimiter(BonusType bonus, TBonusSubtype _subtype, BonusSource src) HasAnotherBonusLimiter::HasAnotherBonusLimiter(BonusType bonus, BonusSubtypeID _subtype, BonusSource src)
: type(bonus), subtype(_subtype), isSubtypeRelevant(true), source(src), isSourceRelevant(true), isSourceIDRelevant(false) : type(bonus), subtype(_subtype), isSubtypeRelevant(true), source(src), isSourceRelevant(true), isSourceIDRelevant(false)
{ {
} }

View File

@ -116,17 +116,17 @@ class DLL_LINKAGE HasAnotherBonusLimiter : public ILimiter //applies only to nod
{ {
public: public:
BonusType type; BonusType type;
TBonusSubtype subtype; BonusSubtypeID subtype;
BonusSource source; BonusSource source;
TBonusSourceID sid; BonusSourceID sid;
bool isSubtypeRelevant; //check for subtype only if this is true bool isSubtypeRelevant; //check for subtype only if this is true
bool isSourceRelevant; //check for bonus source only if this is true bool isSourceRelevant; //check for bonus source only if this is true
bool isSourceIDRelevant; //check for bonus source only if this is true bool isSourceIDRelevant; //check for bonus source only if this is true
HasAnotherBonusLimiter(BonusType bonus = BonusType::NONE); HasAnotherBonusLimiter(BonusType bonus = BonusType::NONE);
HasAnotherBonusLimiter(BonusType bonus, TBonusSubtype _subtype); HasAnotherBonusLimiter(BonusType bonus, BonusSubtypeID _subtype);
HasAnotherBonusLimiter(BonusType bonus, BonusSource src); HasAnotherBonusLimiter(BonusType bonus, BonusSource src);
HasAnotherBonusLimiter(BonusType bonus, TBonusSubtype _subtype, BonusSource src); HasAnotherBonusLimiter(BonusType bonus, BonusSubtypeID _subtype, BonusSource src);
EDecision limit(const BonusLimitationContext &context) const override; EDecision limit(const BonusLimitationContext &context) const override;
std::string toString() const override; std::string toString() const override;

View File

@ -11,8 +11,6 @@
VCMI_LIB_NAMESPACE_BEGIN VCMI_LIB_NAMESPACE_BEGIN
#include "../constants/EntityIdentifiers.h"
enum class CampaignVersion : uint8_t enum class CampaignVersion : uint8_t
{ {
NONE = 0, NONE = 0,

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(); //there is one global object bonus->sid = BonusSourceID(); //there is one global object
globalEffects.addNewBonus(bonus); globalEffects.addNewBonus(bonus);
} }
VLC->creh->loadCrExpBon(globalEffects); VLC->creh->loadCrExpBon(globalEffects);
@ -1871,7 +1871,7 @@ struct statsHLP
//Heroes can produce gold as well - skill, specialty or arts //Heroes can produce gold as well - skill, specialty or arts
for(const auto & h : ps->heroes) for(const auto & h : ps->heroes)
{ {
totalIncome += h->valOfBonuses(Selector::typeSubtype(BonusType::GENERATE_RESOURCE, TBonusSubtype(GameResID(GameResID::GOLD)))); totalIncome += h->valOfBonuses(Selector::typeSubtype(BonusType::GENERATE_RESOURCE, BonusSubtypeID(GameResID(GameResID::GOLD))));
if(!heroOrTown) if(!heroOrTown)
heroOrTown = h; heroOrTown = h;

View File

@ -87,7 +87,7 @@ void CGameStateCampaign::trimCrossoverHeroesParameters(std::vector<CampaignHeroR
for(auto g = PrimarySkill::BEGIN; g < PrimarySkill::END; ++g) for(auto g = PrimarySkill::BEGIN; g < PrimarySkill::END; ++g)
{ {
auto sel = Selector::type()(BonusType::PRIMARY_SKILL) auto sel = Selector::type()(BonusType::PRIMARY_SKILL)
.And(Selector::subtype()(TBonusSubtype(g))) .And(Selector::subtype()(BonusSubtypeID(g)))
.And(Selector::sourceType()(BonusSource::HERO_BASE_SKILL)); .And(Selector::sourceType()(BonusSource::HERO_BASE_SKILL));
cgh->getBonusLocalFirst(sel)->val = cgh->type->heroClass->primarySkillInitial[g]; cgh->getBonusLocalFirst(sel)->val = cgh->type->heroClass->primarySkillInitial[g];
@ -315,7 +315,7 @@ void CGameStateCampaign::giveCampaignBonusToHero(CGHeroInstance * hero)
continue; continue;
auto currentScenario = *gameState->scenarioOps->campState->currentScenario(); auto currentScenario = *gameState->scenarioOps->campState->currentScenario();
auto bb = std::make_shared<Bonus>( BonusDuration::PERMANENT, BonusType::PRIMARY_SKILL, BonusSource::CAMPAIGN_BONUS, val, TBonusSourceID(currentScenario), TBonusSubtype(g) ); auto bb = std::make_shared<Bonus>( BonusDuration::PERMANENT, BonusType::PRIMARY_SKILL, BonusSource::CAMPAIGN_BONUS, val, BonusSourceID(currentScenario), BonusSubtypeID(g) );
hero->addNewBonus(bb); hero->addNewBonus(bb);
} }
break; break;

View File

@ -50,7 +50,7 @@ void CRewardableConstructor::configureObject(CGObjectInstance * object, CRandomG
for (auto & bonus : rewardInfo.reward.bonuses) for (auto & bonus : rewardInfo.reward.bonuses)
{ {
bonus.source = BonusSource::OBJECT; bonus.source = BonusSource::OBJECT;
bonus.sid = TBonusSourceID(rewardableObject->ID); bonus.sid = BonusSourceID(rewardableObject->ID);
} }
} }
assert(!rewardableObject->configuration.info.empty()); assert(!rewardableObject->configuration.info.empty());

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()); b = std::make_shared<Bonus>(BonusDuration::PERMANENT, BonusType::MORALE, BonusSource::ARMY, 0, BonusSourceID());
addNewBonus(b); addNewBonus(b);
} }
@ -120,12 +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
auto undeadModifier = getExportedBonusList().getFirst(Selector::source(BonusSource::ARMY, BonusSourceID::undeadMoraleDebuff)); auto undeadModifier = getExportedBonusList().getFirst(Selector::source(BonusSource::ARMY, BonusCustomSource::undeadMoraleDebuff));
if(hasUndead) if(hasUndead)
{ {
if(!undeadModifier) if(!undeadModifier)
{ {
undeadModifier = std::make_shared<Bonus>(BonusDuration::PERMANENT, BonusType::MORALE, BonusSource::ARMY, -1, BonusSourceID::undeadMoraleDebuff, VLC->generaltexth->arraytxt[116]); undeadModifier = std::make_shared<Bonus>(BonusDuration::PERMANENT, BonusType::MORALE, BonusSource::ARMY, -1, BonusCustomSource::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

@ -213,7 +213,7 @@ void CBank::doVisit(const CGHeroInstance * hero) const
gbonus.id = hero->id.getNum(); gbonus.id = hero->id.getNum();
gbonus.bonus.duration = BonusDuration::ONE_BATTLE; gbonus.bonus.duration = BonusDuration::ONE_BATTLE;
gbonus.bonus.source = BonusSource::OBJECT; gbonus.bonus.source = BonusSource::OBJECT;
gbonus.bonus.sid = TBonusSourceID(ID); gbonus.bonus.sid = BonusSourceID(ID);
gbonus.bonus.type = BonusType::MORALE; gbonus.bonus.type = BonusType::MORALE;
gbonus.bonus.val = -1; gbonus.bonus.val = -1;
switch (ID) switch (ID)
@ -239,7 +239,7 @@ void CBank::doVisit(const CGHeroInstance * hero) const
case Obj::PYRAMID: case Obj::PYRAMID:
{ {
GiveBonus gb; GiveBonus gb;
gb.bonus = Bonus(BonusDuration::ONE_BATTLE, BonusType::LUCK, BonusSource::OBJECT, -2, TBonusSourceID(id), VLC->generaltexth->arraytxt[70]); gb.bonus = Bonus(BonusDuration::ONE_BATTLE, BonusType::LUCK, BonusSource::OBJECT, -2, BonusSourceID(id), VLC->generaltexth->arraytxt[70]);
gb.id = hero->id.getNum(); gb.id = hero->id.getNum();
cb->giveHeroBonus(&gb); cb->giveHeroBonus(&gb);
textID = 107; textID = 107;

View File

@ -46,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, BonusSubtypeID::visionsMonsters)) if(hero->hasVisions(this, BonusCustomSubtype::visionsMonsters))
{ {
MetaString ms; MetaString ms;
ms.appendNumber(stacks.begin()->second->count); ms.appendNumber(stacks.begin()->second->count);

View File

@ -95,7 +95,7 @@ ui32 CGHeroInstance::getTileMovementCost(const TerrainTile & dest, const Terrain
} }
else if(ti->nativeTerrain != from.terType->getId() &&//the terrain is not native else if(ti->nativeTerrain != from.terType->getId() &&//the terrain is not native
ti->nativeTerrain != ETerrainId::ANY_TERRAIN && //no special creature bonus ti->nativeTerrain != ETerrainId::ANY_TERRAIN && //no special creature bonus
!ti->hasBonusOfType(BonusType::NO_TERRAIN_PENALTY, TBonusSubtype(from.terType->getId()))) //no special movement bonus !ti->hasBonusOfType(BonusType::NO_TERRAIN_PENALTY, BonusSubtypeID(from.terType->getId()))) //no special movement bonus
{ {
ret = VLC->terrainTypeHandler->getById(from.terType->getId())->moveCost; ret = VLC->terrainTypeHandler->getById(from.terType->getId())->moveCost;
@ -249,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 ? BonusSubtypeID::heroMovementLand : BonusSubtypeID::heroMovementSea)); ti->updateHeroBonuses(BonusType::MOVEMENT, Selector::subtype()(onLand ? BonusCustomSubtype::heroMovementLand : BonusCustomSubtype::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 ? BonusSubtypeID::heroMovementLand : BonusSubtypeID::heroMovementSea); return ti->valOfBonuses(BonusType::MOVEMENT, onLand ? BonusCustomSubtype::heroMovementLand : BonusCustomSubtype::heroMovementSea);
} }
CGHeroInstance::CGHeroInstance(): CGHeroInstance::CGHeroInstance():
@ -369,7 +369,7 @@ void CGHeroInstance::initHero(CRandomGenerator & rand)
{ {
auto bonus = JsonUtils::parseBonus(b.second); auto bonus = JsonUtils::parseBonus(b.second);
bonus->source = BonusSource::HERO_BASE_SKILL; bonus->source = BonusSource::HERO_BASE_SKILL;
bonus->sid = TBonusSourceID(id); bonus->sid = BonusSourceID(id);
bonus->duration = BonusDuration::PERMANENT; bonus->duration = BonusDuration::PERMANENT;
addNewBonus(bonus); addNewBonus(bonus);
} }
@ -589,7 +589,7 @@ void CGHeroInstance::recreateSecondarySkillsBonuses()
void CGHeroInstance::updateSkillBonus(const SecondarySkill & which, int val) void CGHeroInstance::updateSkillBonus(const SecondarySkill & which, int val)
{ {
removeBonuses(Selector::source(BonusSource::SECONDARY_SKILL, TBonusSourceID(which))); removeBonuses(Selector::source(BonusSource::SECONDARY_SKILL, BonusSourceID(which)));
auto skillBonus = (*VLC->skillh)[which]->at(val).effects; auto skillBonus = (*VLC->skillh)[which]->at(val).effects;
for(const auto & b : skillBonus) for(const auto & b : skillBonus)
addNewBonus(std::make_shared<Bonus>(*b)); addNewBonus(std::make_shared<Bonus>(*b));
@ -638,7 +638,7 @@ int32_t CGHeroInstance::getSpellSchoolLevel(const spells::Spell * spell, int32_t
spell->forEachSchool([&, this](const SpellSchool & cnf, bool & stop) spell->forEachSchool([&, this](const SpellSchool & cnf, bool & stop)
{ {
int32_t thisSchool = valOfBonuses(BonusType::MAGIC_SCHOOL_SKILL, TBonusSubtype(cnf)); //FIXME: Bonus shouldn't be additive (Witchking Artifacts : Crown of Skies) int32_t thisSchool = valOfBonuses(BonusType::MAGIC_SCHOOL_SKILL, BonusSubtypeID(cnf)); //FIXME: Bonus shouldn't be additive (Witchking Artifacts : Crown of Skies)
if(thisSchool > skill) if(thisSchool > skill)
{ {
skill = thisSchool; skill = thisSchool;
@ -647,8 +647,8 @@ int32_t CGHeroInstance::getSpellSchoolLevel(const spells::Spell * spell, int32_t
} }
}); });
vstd::amax(skill, valOfBonuses(BonusType::MAGIC_SCHOOL_SKILL, TBonusSubtype(SpellSchool::ANY))); //any school bonus vstd::amax(skill, valOfBonuses(BonusType::MAGIC_SCHOOL_SKILL, BonusSubtypeID(SpellSchool::ANY))); //any school bonus
vstd::amax(skill, valOfBonuses(BonusType::SPELL, TBonusSubtype(spell->getId()))); //given by artifact or other effect vstd::amax(skill, valOfBonuses(BonusType::SPELL, BonusSubtypeID(spell->getId()))); //given by artifact or other effect
vstd::amax(skill, 0); //in case we don't know any school vstd::amax(skill, 0); //in case we don't know any school
vstd::amin(skill, 3); vstd::amin(skill, 3);
@ -660,28 +660,28 @@ int64_t CGHeroInstance::getSpellBonus(const spells::Spell * spell, int64_t base,
//applying sorcery secondary skill //applying sorcery secondary skill
if(spell->isMagical()) if(spell->isMagical())
base = static_cast<int64_t>(base * (valOfBonuses(BonusType::SPELL_DAMAGE, TBonusSubtype(SpellSchool::ANY))) / 100.0); base = static_cast<int64_t>(base * (valOfBonuses(BonusType::SPELL_DAMAGE, BonusSubtypeID(SpellSchool::ANY))) / 100.0);
base = static_cast<int64_t>(base * (100 + valOfBonuses(BonusType::SPECIFIC_SPELL_DAMAGE, TBonusSubtype(spell->getId()))) / 100.0); base = static_cast<int64_t>(base * (100 + valOfBonuses(BonusType::SPECIFIC_SPELL_DAMAGE, BonusSubtypeID(spell->getId()))) / 100.0);
int maxSchoolBonus = 0; int maxSchoolBonus = 0;
spell->forEachSchool([&maxSchoolBonus, this](const SpellSchool & cnf, bool & stop) spell->forEachSchool([&maxSchoolBonus, this](const SpellSchool & cnf, bool & stop)
{ {
vstd::amax(maxSchoolBonus, valOfBonuses(BonusType::SPELL_DAMAGE, TBonusSubtype(cnf))); vstd::amax(maxSchoolBonus, valOfBonuses(BonusType::SPELL_DAMAGE, BonusSubtypeID(cnf)));
}); });
base = static_cast<int64_t>(base * (100 + maxSchoolBonus) / 100.0); base = static_cast<int64_t>(base * (100 + maxSchoolBonus) / 100.0);
if(affectedStack && affectedStack->creatureLevel() > 0) //Hero specials like Solmyr, Deemer if(affectedStack && affectedStack->creatureLevel() > 0) //Hero specials like Solmyr, Deemer
base = static_cast<int64_t>(base * static_cast<double>(100 + valOfBonuses(BonusType::SPECIAL_SPELL_LEV, TBonusSubtype(spell->getId())) / affectedStack->creatureLevel()) / 100.0); base = static_cast<int64_t>(base * static_cast<double>(100 + valOfBonuses(BonusType::SPECIAL_SPELL_LEV, BonusSubtypeID(spell->getId())) / affectedStack->creatureLevel()) / 100.0);
return base; return base;
} }
int64_t CGHeroInstance::getSpecificSpellBonus(const spells::Spell * spell, int64_t base) const int64_t CGHeroInstance::getSpecificSpellBonus(const spells::Spell * spell, int64_t base) const
{ {
base = static_cast<int64_t>(base * (100 + valOfBonuses(BonusType::SPECIFIC_SPELL_DAMAGE, TBonusSubtype(spell->getId()))) / 100.0); base = static_cast<int64_t>(base * (100 + valOfBonuses(BonusType::SPECIFIC_SPELL_DAMAGE, BonusSubtypeID(spell->getId()))) / 100.0);
return base; return base;
} }
@ -751,19 +751,19 @@ bool CGHeroInstance::canCastThisSpell(const spells::Spell * spell) const
const bool isAllowed = IObjectInterface::cb->isAllowed(0, spell->getIndex()); const bool isAllowed = IObjectInterface::cb->isAllowed(0, spell->getIndex());
const bool inSpellBook = vstd::contains(spells, spell->getId()) && hasSpellbook(); const bool inSpellBook = vstd::contains(spells, spell->getId()) && hasSpellbook();
const bool specificBonus = hasBonusOfType(BonusType::SPELL, TBonusSubtype(spell->getId())); const bool specificBonus = hasBonusOfType(BonusType::SPELL, BonusSubtypeID(spell->getId()));
bool schoolBonus = false; bool schoolBonus = false;
spell->forEachSchool([this, &schoolBonus](const SpellSchool & cnf, bool & stop) spell->forEachSchool([this, &schoolBonus](const SpellSchool & cnf, bool & stop)
{ {
if(hasBonusOfType(BonusType::SPELLS_OF_SCHOOL, TBonusSubtype(cnf))) if(hasBonusOfType(BonusType::SPELLS_OF_SCHOOL, BonusSubtypeID(cnf)))
{ {
schoolBonus = stop = true; schoolBonus = stop = true;
} }
}); });
const bool levelBonus = hasBonusOfType(BonusType::SPELLS_OF_LEVEL, BonusSubtypeID::spellLevel(spell->getLevel())); const bool levelBonus = hasBonusOfType(BonusType::SPELLS_OF_LEVEL, BonusCustomSubtype::spellLevel(spell->getLevel()));
if(spell->isSpecial()) if(spell->isSpecial())
{ {
@ -1008,12 +1008,12 @@ int32_t CGHeroInstance::getSpellCost(const spells::Spell * sp) const
void CGHeroInstance::pushPrimSkill( PrimarySkill which, int val ) void CGHeroInstance::pushPrimSkill( PrimarySkill which, int val )
{ {
auto sel = Selector::typeSubtype(BonusType::PRIMARY_SKILL, TBonusSubtype(which)) auto sel = Selector::typeSubtype(BonusType::PRIMARY_SKILL, BonusSubtypeID(which))
.And(Selector::sourceType()(BonusSource::HERO_BASE_SKILL)); .And(Selector::sourceType()(BonusSource::HERO_BASE_SKILL));
if(hasBonus(sel)) if(hasBonus(sel))
removeBonuses(sel); removeBonuses(sel);
addNewBonus(std::make_shared<Bonus>(BonusDuration::PERMANENT, BonusType::PRIMARY_SKILL, BonusSource::HERO_BASE_SKILL, val, TBonusSourceID(id), TBonusSubtype(which))); addNewBonus(std::make_shared<Bonus>(BonusDuration::PERMANENT, BonusType::PRIMARY_SKILL, BonusSource::HERO_BASE_SKILL, val, BonusSourceID(id), BonusSubtypeID(which)));
} }
EAlignment CGHeroInstance::getAlignment() const EAlignment CGHeroInstance::getAlignment() const
@ -1396,7 +1396,7 @@ void CGHeroInstance::setPrimarySkill(PrimarySkill primarySkill, si64 value, ui8
if(primarySkill < PrimarySkill::EXPERIENCE) if(primarySkill < PrimarySkill::EXPERIENCE)
{ {
auto skill = getBonusLocalFirst(Selector::type()(BonusType::PRIMARY_SKILL) auto skill = getBonusLocalFirst(Selector::type()(BonusType::PRIMARY_SKILL)
.And(Selector::subtype()(TBonusSubtype(primarySkill))) .And(Selector::subtype()(BonusSubtypeID(primarySkill)))
.And(Selector::sourceType()(BonusSource::HERO_BASE_SKILL))); .And(Selector::sourceType()(BonusSource::HERO_BASE_SKILL)));
assert(skill); assert(skill);
@ -1467,7 +1467,7 @@ void CGHeroInstance::levelUpAutomatically(CRandomGenerator & rand)
} }
} }
bool CGHeroInstance::hasVisions(const CGObjectInstance * target, TBonusSubtype subtype) const bool CGHeroInstance::hasVisions(const CGObjectInstance * target, BonusSubtypeID subtype) const
{ {
//VISIONS spell support //VISIONS spell support
const int visionsMultiplier = valOfBonuses(BonusType::VISIONS, subtype); const int visionsMultiplier = valOfBonuses(BonusType::VISIONS, subtype);
@ -1559,7 +1559,7 @@ void CGHeroInstance::serializeCommonOptions(JsonSerializeFormat & handler)
for(auto i = PrimarySkill::BEGIN; i < PrimarySkill::END; ++i) for(auto i = PrimarySkill::BEGIN; i < PrimarySkill::END; ++i)
{ {
int value = valOfBonuses(Selector::typeSubtype(BonusType::PRIMARY_SKILL, TBonusSubtype(i)).And(Selector::sourceType()(BonusSource::HERO_BASE_SKILL))); int value = valOfBonuses(Selector::typeSubtype(BonusType::PRIMARY_SKILL, BonusSubtypeID(i)).And(Selector::sourceType()(BonusSource::HERO_BASE_SKILL)));
handler.serializeInt(NPrimarySkill::names[i.getNum()], value, 0); handler.serializeInt(NPrimarySkill::names[i.getNum()], value, 0);
} }
@ -1752,7 +1752,7 @@ bool CGHeroInstance::isMissionCritical() const
void CGHeroInstance::fillUpgradeInfo(UpgradeInfo & info, const CStackInstance &stack) const void CGHeroInstance::fillUpgradeInfo(UpgradeInfo & info, const CStackInstance &stack) const
{ {
TConstBonusListPtr lista = getBonuses(Selector::typeSubtype(BonusType::SPECIAL_UPGRADE, TBonusSubtype(stack.type->getId()))); TConstBonusListPtr lista = getBonuses(Selector::typeSubtype(BonusType::SPECIAL_UPGRADE, BonusSubtypeID(stack.type->getId())));
for(const auto & it : *lista) for(const auto & it : *lista)
{ {
auto nid = CreatureID(it->additionalInfo[0]); auto nid = CreatureID(it->additionalInfo[0]);

View File

@ -248,7 +248,7 @@ public:
void fillUpgradeInfo(UpgradeInfo & info, const CStackInstance &stack) const override; void fillUpgradeInfo(UpgradeInfo & info, const CStackInstance &stack) const override;
bool hasVisions(const CGObjectInstance * target, TBonusSubtype masteryLevel) const; bool hasVisions(const CGObjectInstance * target, BonusSubtypeID masteryLevel) const;
/// If this hero perishes, the scenario is failed /// If this hero perishes, the scenario is failed
bool isMissionCritical() const; bool isMissionCritical() const;

View File

@ -222,7 +222,7 @@ void CGObjectInstance::giveDummyBonus(const ObjectInstanceID & heroID, BonusDura
gbonus.id = heroID.getNum(); gbonus.id = heroID.getNum();
gbonus.bonus.duration = duration; gbonus.bonus.duration = duration;
gbonus.bonus.source = BonusSource::OBJECT; gbonus.bonus.source = BonusSource::OBJECT;
gbonus.bonus.sid = TBonusSourceID(ID); gbonus.bonus.sid = BonusSourceID(ID);
cb->giveHeroBonus(&gbonus); cb->giveHeroBonus(&gbonus);
} }

View File

@ -227,11 +227,11 @@ void CGPandoraBox::serializeJsonOptions(JsonSerializeFormat & handler)
int val; int val;
handler.serializeInt("morale", val, 0); handler.serializeInt("morale", val, 0);
if(val) if(val)
vinfo.reward.bonuses.emplace_back(BonusDuration::ONE_BATTLE, BonusType::MORALE, BonusSource::OBJECT, val, TBonusSourceID(id)); vinfo.reward.bonuses.emplace_back(BonusDuration::ONE_BATTLE, BonusType::MORALE, BonusSource::OBJECT, val, BonusSourceID(id));
handler.serializeInt("luck", val, 0); handler.serializeInt("luck", val, 0);
if(val) if(val)
vinfo.reward.bonuses.emplace_back(BonusDuration::ONE_BATTLE, BonusType::LUCK, BonusSource::OBJECT, val, TBonusSourceID(id)); vinfo.reward.bonuses.emplace_back(BonusDuration::ONE_BATTLE, BonusType::LUCK, BonusSource::OBJECT, val, BonusSourceID(id));
vinfo.reward.resources.serializeJson(handler, "resources"); vinfo.reward.resources.serializeJson(handler, "resources");
{ {

View File

@ -143,10 +143,10 @@ void COPWBonus::onHeroVisit (const CGHeroInstance * h) const
switch (this->bType) switch (this->bType)
{ {
case BuildingSubID::STABLES: case BuildingSubID::STABLES:
if(!h->hasBonusFrom(BonusSource::OBJECT, TBonusSourceID(Obj(Obj::STABLES)))) //does not stack with advMap Stables if(!h->hasBonusFrom(BonusSource::OBJECT, BonusSourceID(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)), BonusSubtypeID::heroMovementLand, VLC->generaltexth->arraytxt[100]); gb.bonus = Bonus(BonusDuration::ONE_WEEK, BonusType::MOVEMENT, BonusSource::OBJECT, 600, BonusSourceID(Obj(Obj::STABLES)), BonusCustomSubtype::heroMovementLand, VLC->generaltexth->arraytxt[100]);
gb.id = heroID.getNum(); gb.id = heroID.getNum();
cb->giveHeroBonus(&gb); cb->giveHeroBonus(&gb);
@ -235,7 +235,7 @@ void CTownBonus::onHeroVisit (const CGHeroInstance * h) const
case BuildingSubID::CUSTOM_VISITING_BONUS: case BuildingSubID::CUSTOM_VISITING_BONUS:
const auto building = town->getTown()->buildings.at(bID); const auto building = town->getTown()->buildings.at(bID);
if(!h->hasBonusFrom(BonusSource::TOWN_STRUCTURE, TBonusSourceID(building->getUniqueTypeID()))) if(!h->hasBonusFrom(BonusSource::TOWN_STRUCTURE, BonusSourceID(building->getUniqueTypeID())))
{ {
const auto & bonuses = building->onVisitBonuses; const auto & bonuses = building->onVisitBonuses;
applyBonuses(const_cast<CGHeroInstance *>(h), bonuses); applyBonuses(const_cast<CGHeroInstance *>(h), bonuses);
@ -306,7 +306,7 @@ void CTownRewardableBuilding::initObj(CRandomGenerator & rand)
for (auto & bonus : rewardInfo.reward.bonuses) for (auto & bonus : rewardInfo.reward.bonuses)
{ {
bonus.source = BonusSource::TOWN_STRUCTURE; bonus.source = BonusSource::TOWN_STRUCTURE;
bonus.sid = TBonusSourceID(building->getUniqueTypeID()); bonus.sid = BonusSourceID(building->getUniqueTypeID());
} }
} }
} }
@ -395,7 +395,7 @@ bool CTownRewardableBuilding::wasVisitedBefore(const CGHeroInstance * contextHer
case Rewardable::VISIT_BONUS: case Rewardable::VISIT_BONUS:
{ {
const auto building = town->getTown()->buildings.at(bID); const auto building = town->getTown()->buildings.at(bID);
return contextHero->hasBonusFrom(BonusSource::TOWN_STRUCTURE, TBonusSourceID(building->getUniqueTypeID())); return contextHero->hasBonusFrom(BonusSource::TOWN_STRUCTURE, BonusSourceID(building->getUniqueTypeID()));
} }
case Rewardable::VISIT_HERO: case Rewardable::VISIT_HERO:
return visitors.find(contextHero->id) != visitors.end(); return visitors.find(contextHero->id) != visitors.end();

View File

@ -160,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, BonusSubtypeID::creatureLevel(level))); TConstBonusListPtr bonuses = getBonuses(Selector::typeSubtype(BonusType::CREATURE_GROWTH, BonusCustomSubtype::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());
@ -787,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()); b = std::make_shared<Bonus>(BonusDuration::PERMANENT, BonusType::MORALE, BonusSource::ARMY, 0, BonusSourceID());
addNewBonus(b); addNewBonus(b);
} }

View File

@ -676,9 +676,9 @@ void CGSeerHut::serializeJsonOptions(JsonSerializeFormat & handler)
if(metaTypeName == "mana") if(metaTypeName == "mana")
reward.manaDiff = val; reward.manaDiff = val;
if(metaTypeName == "morale") if(metaTypeName == "morale")
reward.bonuses.emplace_back(BonusDuration::ONE_BATTLE, BonusType::MORALE, BonusSource::OBJECT, val, TBonusSourceID(id)); reward.bonuses.emplace_back(BonusDuration::ONE_BATTLE, BonusType::MORALE, BonusSource::OBJECT, val, BonusSourceID(id));
if(metaTypeName == "luck") if(metaTypeName == "luck")
reward.bonuses.emplace_back(BonusDuration::ONE_BATTLE, BonusType::LUCK, BonusSource::OBJECT, val, TBonusSourceID(id)); reward.bonuses.emplace_back(BonusDuration::ONE_BATTLE, BonusType::LUCK, BonusSource::OBJECT, val, BonusSourceID(id));
if(metaTypeName == "resource") if(metaTypeName == "resource")
{ {
auto rawId = *VLC->identifiers()->getIdentifier(ModScope::scopeMap(), fullIdentifier, false); auto rawId = *VLC->identifiers()->getIdentifier(ModScope::scopeMap(), fullIdentifier, false);

View File

@ -197,7 +197,7 @@ bool CRewardableObject::wasVisitedBefore(const CGHeroInstance * contextHero) con
case Rewardable::VISIT_PLAYER: case Rewardable::VISIT_PLAYER:
return vstd::contains(cb->getPlayerState(contextHero->getOwner())->visitedObjects, ObjectInstanceID(id)); return vstd::contains(cb->getPlayerState(contextHero->getOwner())->visitedObjects, ObjectInstanceID(id));
case Rewardable::VISIT_BONUS: case Rewardable::VISIT_BONUS:
return contextHero->hasBonusFrom(BonusSource::OBJECT, TBonusSourceID(ID)); return contextHero->hasBonusFrom(BonusSource::OBJECT, BonusSourceID(ID));
case Rewardable::VISIT_HERO: case Rewardable::VISIT_HERO:
return contextHero->visitedObjects.count(ObjectInstanceID(id)); return contextHero->visitedObjects.count(ObjectInstanceID(id));
case Rewardable::VISIT_LIMITER: case Rewardable::VISIT_LIMITER:
@ -234,7 +234,7 @@ bool CRewardableObject::wasVisited(const CGHeroInstance * h) const
switch (configuration.visitMode) switch (configuration.visitMode)
{ {
case Rewardable::VISIT_BONUS: case Rewardable::VISIT_BONUS:
return h->hasBonusFrom(BonusSource::OBJECT, TBonusSourceID(ID)); return h->hasBonusFrom(BonusSource::OBJECT, BonusSourceID(ID));
case Rewardable::VISIT_HERO: case Rewardable::VISIT_HERO:
return h->visitedObjects.count(ObjectInstanceID(id)); return h->visitedObjects.count(ObjectInstanceID(id));
case Rewardable::VISIT_LIMITER: case Rewardable::VISIT_LIMITER:

View File

@ -987,14 +987,14 @@ void CGSirens::initObj(CRandomGenerator & rand)
std::string CGSirens::getHoverText(const CGHeroInstance * hero) const std::string CGSirens::getHoverText(const CGHeroInstance * hero) const
{ {
return getObjectName() + " " + visitedTxt(hero->hasBonusFrom(BonusSource::OBJECT, TBonusSourceID(ID))); return getObjectName() + " " + visitedTxt(hero->hasBonusFrom(BonusSource::OBJECT, BonusSourceID(ID)));
} }
void CGSirens::onHeroVisit( const CGHeroInstance * h ) const void CGSirens::onHeroVisit( const CGHeroInstance * h ) const
{ {
InfoWindow iw; InfoWindow iw;
iw.player = h->tempOwner; iw.player = h->tempOwner;
if(h->hasBonusFrom(BonusSource::OBJECT, TBonusSourceID(ID))) //has already visited Sirens if(h->hasBonusFrom(BonusSource::OBJECT, BonusSourceID(ID))) //has already visited Sirens
{ {
iw.type = EInfoWindowMode::AUTO; iw.type = EInfoWindowMode::AUTO;
iw.text.appendLocalString(EMetaText::ADVOB_TXT,133); iw.text.appendLocalString(EMetaText::ADVOB_TXT,133);
@ -1180,7 +1180,7 @@ void CGLighthouse::onHeroVisit( const CGHeroInstance * h ) const
RemoveBonus rb(GiveBonus::ETarget::PLAYER); RemoveBonus rb(GiveBonus::ETarget::PLAYER);
rb.whoID = oldOwner.getNum(); rb.whoID = oldOwner.getNum();
rb.source = BonusSource::OBJECT; rb.source = BonusSource::OBJECT;
rb.id = TBonusSourceID(id); rb.id = BonusSourceID(id);
cb->sendAndApply(&rb); cb->sendAndApply(&rb);
} }
} }
@ -1203,8 +1203,8 @@ void CGLighthouse::giveBonusTo(const PlayerColor & player, bool onInit) const
gb.id = player.getNum(); gb.id = player.getNum();
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 = BonusSourceID(id);
gb.bonus.subtype = BonusSubtypeID::heroMovementSea; gb.bonus.subtype = BonusCustomSubtype::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

@ -1040,9 +1040,9 @@ void CMapLoaderH3M::readBoxContent(CGPandoraBox * object, const int3 & mapPositi
reward.heroExperience = reader->readUInt32(); reward.heroExperience = reader->readUInt32();
reward.manaDiff = reader->readInt32(); reward.manaDiff = reader->readInt32();
if(auto val = reader->readUInt8()) if(auto val = reader->readUInt8())
reward.bonuses.emplace_back(BonusDuration::ONE_BATTLE, BonusType::MORALE, BonusSource::OBJECT, val, TBonusSourceID(idToBeGiven)); reward.bonuses.emplace_back(BonusDuration::ONE_BATTLE, BonusType::MORALE, BonusSource::OBJECT, val, BonusSourceID(idToBeGiven));
if(auto val = reader->readUInt8()) if(auto val = reader->readUInt8())
reward.bonuses.emplace_back(BonusDuration::ONE_BATTLE, BonusType::LUCK, BonusSource::OBJECT, val, TBonusSourceID(idToBeGiven)); reward.bonuses.emplace_back(BonusDuration::ONE_BATTLE, BonusType::LUCK, BonusSource::OBJECT, val, BonusSourceID(idToBeGiven));
reader->readResourses(reward.resources); reader->readResourses(reward.resources);
for(int x = 0; x < GameConstants::PRIMARY_SKILLS; ++x) for(int x = 0; x < GameConstants::PRIMARY_SKILLS; ++x)
@ -2008,12 +2008,12 @@ void CMapLoaderH3M::readSeerHutQuest(CGSeerHut * hut, const int3 & position, con
} }
case ESeerHutRewardType::MORALE: case ESeerHutRewardType::MORALE:
{ {
reward.bonuses.emplace_back(BonusDuration::ONE_BATTLE, BonusType::MORALE, BonusSource::OBJECT, reader->readUInt8(), TBonusSourceID(idToBeGiven)); reward.bonuses.emplace_back(BonusDuration::ONE_BATTLE, BonusType::MORALE, BonusSource::OBJECT, reader->readUInt8(), BonusSourceID(idToBeGiven));
break; break;
} }
case ESeerHutRewardType::LUCK: case ESeerHutRewardType::LUCK:
{ {
reward.bonuses.emplace_back(BonusDuration::ONE_BATTLE, BonusType::LUCK, BonusSource::OBJECT, reader->readUInt8(), TBonusSourceID(idToBeGiven)); reward.bonuses.emplace_back(BonusDuration::ONE_BATTLE, BonusType::LUCK, BonusSource::OBJECT, reader->readUInt8(), BonusSourceID(idToBeGiven));
break; break;
} }
case ESeerHutRewardType::RESOURCES: case ESeerHutRewardType::RESOURCES:

View File

@ -23,7 +23,7 @@ TurnInfo::BonusCache::BonusCache(const TConstBonusListPtr & bl)
for(const auto & terrain : VLC->terrainTypeHandler->objects) for(const auto & terrain : VLC->terrainTypeHandler->objects)
{ {
noTerrainPenalty.push_back(static_cast<bool>( noTerrainPenalty.push_back(static_cast<bool>(
bl->getFirst(Selector::type()(BonusType::NO_TERRAIN_PENALTY).And(Selector::subtype()(TBonusSubtype(terrain->getId())))))); bl->getFirst(Selector::type()(BonusType::NO_TERRAIN_PENALTY).And(Selector::subtype()(BonusSubtypeID(terrain->getId()))))));
} }
freeShipBoarding = static_cast<bool>(bl->getFirst(Selector::type()(BonusType::FREE_SHIP_BOARDING))); freeShipBoarding = static_cast<bool>(bl->getFirst(Selector::type()(BonusType::FREE_SHIP_BOARDING)));
@ -73,10 +73,10 @@ bool TurnInfo::isLayerAvailable(const EPathfindingLayer & layer) const
bool TurnInfo::hasBonusOfType(BonusType type) const bool TurnInfo::hasBonusOfType(BonusType type) const
{ {
return hasBonusOfType(type, TBonusSubtype()); return hasBonusOfType(type, BonusSubtypeID());
} }
bool TurnInfo::hasBonusOfType(BonusType type, TBonusSubtype subtype) const bool TurnInfo::hasBonusOfType(BonusType type, BonusSubtypeID subtype) const
{ {
switch(type) switch(type)
{ {
@ -96,10 +96,10 @@ bool TurnInfo::hasBonusOfType(BonusType type, TBonusSubtype subtype) const
int TurnInfo::valOfBonuses(BonusType type) const int TurnInfo::valOfBonuses(BonusType type) const
{ {
return valOfBonuses(type, TBonusSubtype()); return valOfBonuses(type, BonusSubtypeID());
} }
int TurnInfo::valOfBonuses(BonusType type, TBonusSubtype subtype) const int TurnInfo::valOfBonuses(BonusType type, BonusSubtypeID subtype) const
{ {
switch(type) switch(type)
{ {

View File

@ -43,9 +43,9 @@ struct DLL_LINKAGE TurnInfo
TurnInfo(const CGHeroInstance * Hero, const int Turn = 0); TurnInfo(const CGHeroInstance * Hero, const int Turn = 0);
bool isLayerAvailable(const EPathfindingLayer & layer) const; bool isLayerAvailable(const EPathfindingLayer & layer) const;
bool hasBonusOfType(const BonusType type) const; bool hasBonusOfType(const BonusType type) const;
bool hasBonusOfType(const BonusType type, const TBonusSubtype subtype) const; bool hasBonusOfType(const BonusType type, const BonusSubtypeID subtype) const;
int valOfBonuses(const BonusType type) const; int valOfBonuses(const BonusType type) const;
int valOfBonuses(const BonusType type, const TBonusSubtype subtype) const; int valOfBonuses(const BonusType type, const BonusSubtypeID subtype) const;
void updateHeroBonuses(BonusType type, const CSelector& sel) const; void updateHeroBonuses(BonusType type, const CSelector& sel) const;
int getMaxMovePoints(const EPathfindingLayer & layer) const; int getMaxMovePoints(const EPathfindingLayer & layer) const;
}; };

View File

@ -35,7 +35,7 @@ int32_t AbilityCaster::getSpellSchoolLevel(const Spell * spell, int32_t * outSel
if(spell->getLevel() > 0) if(spell->getLevel() > 0)
{ {
vstd::amax(skill, unit->valOfBonuses(BonusType::MAGIC_SCHOOL_SKILL, TBonusSubtype(SpellSchool::ANY))); vstd::amax(skill, unit->valOfBonuses(BonusType::MAGIC_SCHOOL_SKILL, BonusSubtypeID(SpellSchool::ANY)));
} }
vstd::amax(skill, 0); vstd::amax(skill, 0);

View File

@ -312,7 +312,7 @@ ESpellCastResult DimensionDoorMechanics::applyAdventureEffects(SpellCastEnvironm
std::stringstream cachingStr; std::stringstream cachingStr;
cachingStr << "source_" << vstd::to_underlying(BonusSource::SPELL_EFFECT) << "id_" << owner->id.num; cachingStr << "source_" << vstd::to_underlying(BonusSource::SPELL_EFFECT) << "id_" << owner->id.num;
if(parameters.caster->getHeroCaster()->getBonuses(Selector::source(BonusSource::SPELL_EFFECT, TBonusSourceID(owner->id)), Selector::all, cachingStr.str())->size() >= owner->getLevelPower(schoolLevel)) //limit casts per turn if(parameters.caster->getHeroCaster()->getBonuses(Selector::source(BonusSource::SPELL_EFFECT, BonusSourceID(owner->id)), Selector::all, cachingStr.str())->size() >= owner->getLevelPower(schoolLevel)) //limit casts per turn
{ {
InfoWindow iw; InfoWindow iw;
iw.player = parameters.caster->getCasterOwner(); iw.player = parameters.caster->getCasterOwner();
@ -324,7 +324,7 @@ ESpellCastResult DimensionDoorMechanics::applyAdventureEffects(SpellCastEnvironm
GiveBonus gb; GiveBonus gb;
gb.id = parameters.caster->getCasterUnitId(); gb.id = parameters.caster->getCasterUnitId();
gb.bonus = Bonus(BonusDuration::ONE_DAY, BonusType::NONE, BonusSource::SPELL_EFFECT, 0, TBonusSourceID(owner->id)); gb.bonus = Bonus(BonusDuration::ONE_DAY, BonusType::NONE, BonusSource::SPELL_EFFECT, 0, BonusSourceID(owner->id));
env->apply(&gb); env->apply(&gb);
if(!dest->isClear(curr)) //wrong dest tile if(!dest->isClear(curr)) //wrong dest tile

View File

@ -383,15 +383,15 @@ int64_t CSpell::adjustRawDamage(const spells::Caster * caster, const battle::Uni
//applying protections - when spell has more then one elements, only one protection should be applied (I think) //applying protections - when spell has more then one elements, only one protection should be applied (I think)
forEachSchool([&](const SpellSchool & cnf, bool & stop) forEachSchool([&](const SpellSchool & cnf, bool & stop)
{ {
if(bearer->hasBonusOfType(BonusType::SPELL_DAMAGE_REDUCTION, TBonusSubtype(cnf))) if(bearer->hasBonusOfType(BonusType::SPELL_DAMAGE_REDUCTION, BonusSubtypeID(cnf)))
{ {
ret *= 100 - bearer->valOfBonuses(BonusType::SPELL_DAMAGE_REDUCTION, TBonusSubtype(cnf)); ret *= 100 - bearer->valOfBonuses(BonusType::SPELL_DAMAGE_REDUCTION, BonusSubtypeID(cnf));
ret /= 100; ret /= 100;
stop = true; //only bonus from one school is used stop = true; //only bonus from one school is used
} }
}); });
CSelector selector = Selector::typeSubtype(BonusType::SPELL_DAMAGE_REDUCTION, TBonusSubtype(SpellSchool::ANY)); CSelector selector = Selector::typeSubtype(BonusType::SPELL_DAMAGE_REDUCTION, BonusSubtypeID(SpellSchool::ANY));
auto cachingStr = "type_SPELL_DAMAGE_REDUCTION_s_ANY"; auto cachingStr = "type_SPELL_DAMAGE_REDUCTION_s_ANY";
//general spell dmg reduction, works only on magical effects //general spell dmg reduction, works only on magical effects
@ -402,9 +402,9 @@ int64_t CSpell::adjustRawDamage(const spells::Caster * caster, const battle::Uni
} }
//dmg increasing //dmg increasing
if(bearer->hasBonusOfType(BonusType::MORE_DAMAGE_FROM_SPELL, TBonusSubtype(id))) if(bearer->hasBonusOfType(BonusType::MORE_DAMAGE_FROM_SPELL, BonusSubtypeID(id)))
{ {
ret *= 100 + bearer->valOfBonuses(BonusType::MORE_DAMAGE_FROM_SPELL, TBonusSubtype(id)); ret *= 100 + bearer->valOfBonuses(BonusType::MORE_DAMAGE_FROM_SPELL, BonusSubtypeID(id));
ret /= 100; ret /= 100;
} }
} }
@ -925,7 +925,7 @@ CSpell * CSpellHandler::loadFromJson(const std::string & scope, const JsonNode &
auto b = JsonUtils::parseBonus(bonusNode); auto b = JsonUtils::parseBonus(bonusNode);
const bool usePowerAsValue = bonusNode["val"].isNull(); const bool usePowerAsValue = bonusNode["val"].isNull();
b->sid = TBonusSourceID(spell->id); //for all b->sid = BonusSourceID(spell->id); //for all
b->source = BonusSource::SPELL_EFFECT;//for all b->source = BonusSource::SPELL_EFFECT;//for all
if(usePowerAsValue) if(usePowerAsValue)
@ -940,7 +940,7 @@ CSpell * CSpellHandler::loadFromJson(const std::string & scope, const JsonNode &
auto b = JsonUtils::parseBonus(bonusNode); auto b = JsonUtils::parseBonus(bonusNode);
const bool usePowerAsValue = bonusNode["val"].isNull(); const bool usePowerAsValue = bonusNode["val"].isNull();
b->sid = TBonusSourceID(spell->id); //for all b->sid = BonusSourceID(spell->id); //for all
b->source = BonusSource::SPELL_EFFECT;//for all b->source = BonusSource::SPELL_EFFECT;//for all
if(usePowerAsValue) if(usePowerAsValue)

View File

@ -157,7 +157,7 @@ protected:
{ {
std::stringstream cachingStr; std::stringstream cachingStr;
cachingStr << "type_" << vstd::to_underlying(BonusType::SPELL_IMMUNITY) << "subtype_" << m->getSpellIndex() << "addInfo_1"; cachingStr << "type_" << vstd::to_underlying(BonusType::SPELL_IMMUNITY) << "subtype_" << m->getSpellIndex() << "addInfo_1";
return !target->hasBonus(Selector::typeSubtypeInfo(BonusType::SPELL_IMMUNITY, TBonusSubtype(m->getSpellId()), 1), cachingStr.str()); return !target->hasBonus(Selector::typeSubtypeInfo(BonusType::SPELL_IMMUNITY, BonusSubtypeID(m->getSpellId()), 1), cachingStr.str());
} }
}; };
@ -179,14 +179,14 @@ protected:
m->getSpell()->forEachSchool([&](const SpellSchool & cnf, bool & stop) m->getSpell()->forEachSchool([&](const SpellSchool & cnf, bool & stop)
{ {
if (bearer->hasBonusOfType(BonusType::SPELL_SCHOOL_IMMUNITY, TBonusSubtype(cnf))) if (bearer->hasBonusOfType(BonusType::SPELL_SCHOOL_IMMUNITY, BonusSubtypeID(cnf)))
{ {
elementalImmune = true; elementalImmune = true;
stop = true; //only bonus from one school is used stop = true; //only bonus from one school is used
} }
else if(!m->isPositiveSpell()) //negative or indifferent else if(!m->isPositiveSpell()) //negative or indifferent
{ {
if (bearer->hasBonusOfType(BonusType::NEGATIVE_EFFECTS_IMMUNITY, TBonusSubtype(cnf))) if (bearer->hasBonusOfType(BonusType::NEGATIVE_EFFECTS_IMMUNITY, BonusSubtypeID(cnf)))
{ {
elementalImmune = true; elementalImmune = true;
stop = true; //only bonus from one school is used stop = true; //only bonus from one school is used
@ -231,7 +231,7 @@ public:
protected: protected:
bool check(const Mechanics * m, const battle::Unit * target) const override bool check(const Mechanics * m, const battle::Unit * target) const override
{ {
return !target->hasBonusOfType(BonusType::SPELL_IMMUNITY, TBonusSubtype(m->getSpellId())); return !target->hasBonusOfType(BonusType::SPELL_IMMUNITY, BonusSubtypeID(m->getSpellId()));
} }
}; };
@ -259,7 +259,7 @@ public:
builder << "source_" << vstd::to_underlying(BonusSource::SPELL_EFFECT) << "id_" << spellID.num; builder << "source_" << vstd::to_underlying(BonusSource::SPELL_EFFECT) << "id_" << spellID.num;
cachingString = builder.str(); cachingString = builder.str();
selector = Selector::source(BonusSource::SPELL_EFFECT, TBonusSourceID(spellID)); selector = Selector::source(BonusSource::SPELL_EFFECT, BonusSourceID(spellID));
} }
protected: protected:
@ -292,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, BonusSubtypeID::immunityBattleWide); const bool battleWideNegation = target->hasBonusOfType(BonusType::NEGATE_ALL_NATURAL_IMMUNITIES, BonusCustomSubtype::immunityBattleWide);
const bool heroNegation = target->hasBonusOfType(BonusType::NEGATE_ALL_NATURAL_IMMUNITIES, BonusSubtypeID::immunityEnemyHero); const bool heroNegation = target->hasBonusOfType(BonusType::NEGATE_ALL_NATURAL_IMMUNITIES, BonusCustomSubtype::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

@ -94,7 +94,7 @@ void Clone::apply(ServerCallback * server, const Mechanics * m, const EffectTarg
SetStackEffect sse; SetStackEffect sse;
sse.battleID = m->battle()->getBattle()->getBattleID(); sse.battleID = m->battle()->getBattle()->getBattleID();
Bonus lifeTimeMarker(BonusDuration::N_TURNS, BonusType::NONE, BonusSource::SPELL_EFFECT, 0, TBonusSourceID(SpellID(SpellID::CLONE))); //TODO: use special bonus type Bonus lifeTimeMarker(BonusDuration::N_TURNS, BonusType::NONE, BonusSource::SPELL_EFFECT, 0, BonusSourceID(SpellID(SpellID::CLONE))); //TODO: use special bonus type
lifeTimeMarker.turnsRemain = m->getEffectDuration(); lifeTimeMarker.turnsRemain = m->getEffectDuration();
std::vector<Bonus> buffer; std::vector<Bonus> buffer;
buffer.push_back(lifeTimeMarker); buffer.push_back(lifeTimeMarker);

View File

@ -89,11 +89,11 @@ bool Damage::isReceptive(const Mechanics * m, const battle::Unit * unit) const
if(!UnitEffect::isReceptive(m, unit)) if(!UnitEffect::isReceptive(m, unit))
return false; return false;
bool isImmune = m->getSpell()->isMagical() && (unit->getBonusBearer()->valOfBonuses(BonusType::SPELL_DAMAGE_REDUCTION, TBonusSubtype(SpellSchool::ANY)) >= 100); //General spell damage immunity bool isImmune = m->getSpell()->isMagical() && (unit->getBonusBearer()->valOfBonuses(BonusType::SPELL_DAMAGE_REDUCTION, BonusSubtypeID(SpellSchool::ANY)) >= 100); //General spell damage immunity
//elemental immunity for damage //elemental immunity for damage
m->getSpell()->forEachSchool([&](const SpellSchool & cnf, bool & stop) m->getSpell()->forEachSchool([&](const SpellSchool & cnf, bool & stop)
{ {
isImmune |= (unit->getBonusBearer()->valOfBonuses(BonusType::SPELL_DAMAGE_REDUCTION, TBonusSubtype(cnf)) >= 100); //100% reduction is immunity isImmune |= (unit->getBonusBearer()->valOfBonuses(BonusType::SPELL_DAMAGE_REDUCTION, BonusSubtypeID(cnf)) >= 100); //100% reduction is immunity
}); });
return !isImmune; return !isImmune;

View File

@ -84,12 +84,12 @@ void Moat::convertBonus(const Mechanics * m, std::vector<Bonus> & converted) con
if(m->battle()->battleGetDefendedTown() && m->battle()->battleGetSiegeLevel() >= CGTownInstance::CITADEL) if(m->battle()->battleGetDefendedTown() && m->battle()->battleGetSiegeLevel() >= CGTownInstance::CITADEL)
{ {
nb.sid = TBonusSourceID(m->battle()->battleGetDefendedTown()->town->buildings.at(BuildingID::CITADEL)->getUniqueTypeID()); nb.sid = BonusSourceID(m->battle()->battleGetDefendedTown()->town->buildings.at(BuildingID::CITADEL)->getUniqueTypeID());
nb.source = BonusSource::TOWN_STRUCTURE; nb.source = BonusSource::TOWN_STRUCTURE;
} }
else else
{ {
nb.sid = TBonusSourceID(m->getSpellId()); //for all nb.sid = BonusSourceID(m->getSpellId()); //for all
nb.source = BonusSource::SPELL_EFFECT;//for all nb.source = BonusSource::SPELL_EFFECT;//for all
} }
std::set<BattleHex> flatMoatHexes; std::set<BattleHex> flatMoatHexes;

View File

@ -109,9 +109,9 @@ void Timed::apply(ServerCallback * server, const Mechanics * m, const EffectTarg
const auto *casterHero = dynamic_cast<const CGHeroInstance *>(m->caster); const auto *casterHero = dynamic_cast<const CGHeroInstance *>(m->caster);
if(casterHero) if(casterHero)
{ {
peculiarBonus = casterHero->getBonusLocalFirst(Selector::typeSubtype(BonusType::SPECIAL_PECULIAR_ENCHANT, TBonusSubtype(m->getSpellId()))); peculiarBonus = casterHero->getBonusLocalFirst(Selector::typeSubtype(BonusType::SPECIAL_PECULIAR_ENCHANT, BonusSubtypeID(m->getSpellId())));
addedValueBonus = casterHero->getBonusLocalFirst(Selector::typeSubtype(BonusType::SPECIAL_ADD_VALUE_ENCHANT, TBonusSubtype(m->getSpellId()))); addedValueBonus = casterHero->getBonusLocalFirst(Selector::typeSubtype(BonusType::SPECIAL_ADD_VALUE_ENCHANT, BonusSubtypeID(m->getSpellId())));
fixedValueBonus = casterHero->getBonusLocalFirst(Selector::typeSubtype(BonusType::SPECIAL_FIXED_VALUE_ENCHANT, TBonusSubtype(m->getSpellId()))); fixedValueBonus = casterHero->getBonusLocalFirst(Selector::typeSubtype(BonusType::SPECIAL_FIXED_VALUE_ENCHANT, BonusSubtypeID(m->getSpellId())));
} }
//TODO: does hero specialty should affects his stack casting spells? //TODO: does hero specialty should affects his stack casting spells?
@ -222,7 +222,7 @@ void Timed::convertBonus(const Mechanics * m, int32_t & duration, std::vector<Bo
nb.turnsRemain = duration; nb.turnsRemain = duration;
vstd::amax(maxDuration, nb.turnsRemain); vstd::amax(maxDuration, nb.turnsRemain);
nb.sid = TBonusSourceID(m->getSpellId()); //for all nb.sid = BonusSourceID(m->getSpellId()); //for all
nb.source = BonusSource::SPELL_EFFECT;//for all nb.source = BonusSource::SPELL_EFFECT;//for all
//fix to original config: shield should display damage reduction //fix to original config: shield should display damage reduction

View File

@ -253,7 +253,7 @@ bool UnitEffect::isReceptive(const Mechanics * m, const battle::Unit * unit) con
//SPELL_IMMUNITY absolute case //SPELL_IMMUNITY absolute case
std::stringstream cachingStr; std::stringstream cachingStr;
cachingStr << "type_" << vstd::to_underlying(BonusType::SPELL_IMMUNITY) << "subtype_" << m->getSpellIndex() << "addInfo_1"; cachingStr << "type_" << vstd::to_underlying(BonusType::SPELL_IMMUNITY) << "subtype_" << m->getSpellIndex() << "addInfo_1";
return !unit->hasBonus(Selector::typeSubtypeInfo(BonusType::SPELL_IMMUNITY, TBonusSubtype(m->getSpellId()), 1), cachingStr.str()); return !unit->hasBonus(Selector::typeSubtypeInfo(BonusType::SPELL_IMMUNITY, BonusSubtypeID(m->getSpellId()), 1), cachingStr.str());
} }
else else
{ {

View File

@ -333,7 +333,7 @@ void RewardsWidget::saveCurrentVisitInfo(int index)
auto dur = bonusDurationMap.at(ui->bonuses->item(i, 0)->text().toStdString()); auto dur = bonusDurationMap.at(ui->bonuses->item(i, 0)->text().toStdString());
auto typ = bonusNameMap.at(ui->bonuses->item(i, 1)->text().toStdString()); auto typ = bonusNameMap.at(ui->bonuses->item(i, 1)->text().toStdString());
auto val = ui->bonuses->item(i, 2)->data(Qt::UserRole).toInt(); auto val = ui->bonuses->item(i, 2)->data(Qt::UserRole).toInt();
vinfo.reward.bonuses.emplace_back(dur, typ, BonusSource::OBJECT, val, TBonusSourceID(object.id)); vinfo.reward.bonuses.emplace_back(dur, typ, BonusSource::OBJECT, val, BonusSourceID(object.id));
} }
vinfo.limiter.dayOfWeek = ui->lDayOfWeek->currentIndex(); vinfo.limiter.dayOfWeek = ui->lDayOfWeek->currentIndex();

View File

@ -248,11 +248,11 @@ void CGameHandler::levelUpCommander (const CCommanderInstance * c, int skill)
{ {
case ECommander::ATTACK: case ECommander::ATTACK:
scp.accumulatedBonus.type = BonusType::PRIMARY_SKILL; scp.accumulatedBonus.type = BonusType::PRIMARY_SKILL;
scp.accumulatedBonus.subtype = TBonusSubtype(PrimarySkill::ATTACK); scp.accumulatedBonus.subtype = BonusSubtypeID(PrimarySkill::ATTACK);
break; break;
case ECommander::DEFENSE: case ECommander::DEFENSE:
scp.accumulatedBonus.type = BonusType::PRIMARY_SKILL; scp.accumulatedBonus.type = BonusType::PRIMARY_SKILL;
scp.accumulatedBonus.subtype = TBonusSubtype(PrimarySkill::DEFENSE); scp.accumulatedBonus.subtype = BonusSubtypeID(PrimarySkill::DEFENSE);
break; break;
case ECommander::HEALTH: case ECommander::HEALTH:
scp.accumulatedBonus.type = BonusType::STACK_HEALTH; scp.accumulatedBonus.type = BonusType::STACK_HEALTH;
@ -788,7 +788,7 @@ void CGameHandler::onNewTurn()
{ {
for (GameResID k = GameResID::WOOD; k < GameResID::COUNT; k++) for (GameResID k = GameResID::WOOD; k < GameResID::COUNT; k++)
{ {
n.res[elem.first][k] += h->valOfBonuses(BonusType::GENERATE_RESOURCE, TBonusSubtype(k)); n.res[elem.first][k] += h->valOfBonuses(BonusType::GENERATE_RESOURCE, BonusSubtypeID(k));
} }
} }
} }

View File

@ -162,11 +162,11 @@ 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(), TBonusSubtype(PrimarySkill::DEFENSE), BonusValueType::PERCENT_TO_ALL); Bonus defenseBonusToAdd(BonusDuration::STACK_GETS_TURN, BonusType::PRIMARY_SKILL, BonusSource::OTHER, 20, BonusSourceID(), BonusSubtypeID(PrimarySkill::DEFENSE), BonusValueType::PERCENT_TO_ALL);
Bonus bonus2(BonusDuration::STACK_GETS_TURN, BonusType::PRIMARY_SKILL, BonusSource::OTHER, stack->valOfBonuses(BonusType::DEFENSIVE_STANCE), TBonusSourceID(), TBonusSubtype(PrimarySkill::DEFENSE), BonusValueType::ADDITIVE_VALUE); Bonus bonus2(BonusDuration::STACK_GETS_TURN, BonusType::PRIMARY_SKILL, BonusSource::OTHER, stack->valOfBonuses(BonusType::DEFENSIVE_STANCE), BonusSourceID(), BonusSubtypeID(PrimarySkill::DEFENSE), BonusValueType::ADDITIVE_VALUE);
Bonus alternativeWeakCreatureBonus(BonusDuration::STACK_GETS_TURN, BonusType::PRIMARY_SKILL, BonusSource::OTHER, 1, TBonusSourceID(), TBonusSubtype(PrimarySkill::DEFENSE), BonusValueType::ADDITIVE_VALUE); Bonus alternativeWeakCreatureBonus(BonusDuration::STACK_GETS_TURN, BonusType::PRIMARY_SKILL, BonusSource::OTHER, 1, BonusSourceID(), BonusSubtypeID(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, BonusSubtypeID(PrimarySkill::DEFENSE)));
int oldDefenceValue = defence.totalValue(); int oldDefenceValue = defence.totalValue();
defence.push_back(std::make_shared<Bonus>(defenseBonusToAdd)); defence.push_back(std::make_shared<Bonus>(defenseBonusToAdd));
@ -263,7 +263,7 @@ bool BattleActionProcessor::doAttackAction(const CBattleInfoCallback & battle, c
const auto * attackingHero = battle.battleGetFightingHero(ba.side); const auto * attackingHero = battle.battleGetFightingHero(ba.side);
if(attackingHero) if(attackingHero)
{ {
totalAttacks += attackingHero->valOfBonuses(BonusType::HERO_GRANTS_ATTACKS, TBonusSubtype(stack->creatureId())); totalAttacks += attackingHero->valOfBonuses(BonusType::HERO_GRANTS_ATTACKS, BonusSubtypeID(stack->creatureId()));
} }
const bool firstStrike = destinationStack->hasBonusOfType(BonusType::FIRST_STRIKE); const bool firstStrike = destinationStack->hasBonusOfType(BonusType::FIRST_STRIKE);
@ -355,7 +355,7 @@ bool BattleActionProcessor::doShootAction(const CBattleInfoCallback & battle, co
const auto * attackingHero = battle.battleGetFightingHero(ba.side); const auto * attackingHero = battle.battleGetFightingHero(ba.side);
if(attackingHero) if(attackingHero)
{ {
totalRangedAttacks += attackingHero->valOfBonuses(BonusType::HERO_GRANTS_ATTACKS, TBonusSubtype(stack->creatureId())); totalRangedAttacks += attackingHero->valOfBonuses(BonusType::HERO_GRANTS_ATTACKS, BonusSubtypeID(stack->creatureId()));
} }
for(int i = 1; i < totalRangedAttacks; ++i) for(int i = 1; i < totalRangedAttacks; ++i)
@ -382,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()) if(!catapultAbility || catapultAbility->subtype == BonusSubtypeID())
{ {
gameHandler->complain("We do not know how to shoot :P"); gameHandler->complain("We do not know how to shoot :P");
} }
@ -407,7 +407,7 @@ bool BattleActionProcessor::doUnitSpellAction(const CBattleInfoCallback & battle
return false; return false;
std::shared_ptr<const Bonus> randSpellcaster = stack->getBonus(Selector::type()(BonusType::RANDOM_SPELLCASTER)); std::shared_ptr<const Bonus> randSpellcaster = stack->getBonus(Selector::type()(BonusType::RANDOM_SPELLCASTER));
std::shared_ptr<const Bonus> spellcaster = stack->getBonus(Selector::typeSubtype(BonusType::SPELLCASTER, TBonusSubtype(spellID))); std::shared_ptr<const Bonus> spellcaster = stack->getBonus(Selector::typeSubtype(BonusType::SPELLCASTER, BonusSubtypeID(spellID)));
//TODO special bonus for genies ability //TODO special bonus for genies ability
if (randSpellcaster && battle.battleGetRandomStackSpell(gameHandler->getRandomGenerator(), stack, CBattleInfoCallback::RANDOM_AIMED) == SpellID::NONE) if (randSpellcaster && battle.battleGetRandomStackSpell(gameHandler->getRandomGenerator(), stack, CBattleInfoCallback::RANDOM_AIMED) == SpellID::NONE)
@ -452,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()) if(stack == nullptr || destStack == nullptr || !healerAbility || healerAbility->subtype == BonusSubtypeID())
{ {
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");
} }
@ -907,7 +907,7 @@ void BattleActionProcessor::makeAttack(const CBattleInfoCallback & battle, const
const auto * owner = battle.battleGetFightingHero(attacker->unitSide()); const auto * owner = battle.battleGetFightingHero(attacker->unitSide());
if(owner) if(owner)
{ {
int chance = owner->valOfBonuses(BonusType::BONUS_DAMAGE_CHANCE, TBonusSubtype(attacker->creatureId())); int chance = owner->valOfBonuses(BonusType::BONUS_DAMAGE_CHANCE, BonusSubtypeID(attacker->creatureId()));
if (chance > gameHandler->getRandomGenerator().nextInt(99)) if (chance > gameHandler->getRandomGenerator().nextInt(99))
bat.flags |= BattleAttack::BALLISTA_DOUBLE_DMG; bat.flags |= BattleAttack::BALLISTA_DOUBLE_DMG;
} }
@ -1095,7 +1095,7 @@ void BattleActionProcessor::attackCasting(const CBattleInfoCallback & battle, bo
return; return;
} }
int32_t spellLevel = 0; int32_t spellLevel = 0;
TConstBonusListPtr spellsByType = attacker->getBonuses(Selector::typeSubtype(attackMode, TBonusSubtype(spellID))); TConstBonusListPtr spellsByType = attacker->getBonuses(Selector::typeSubtype(attackMode, BonusSubtypeID(spellID)));
for(const auto & sf : *spellsByType) for(const auto & sf : *spellsByType)
{ {
int meleeRanged; int meleeRanged;
@ -1113,7 +1113,7 @@ void BattleActionProcessor::attackCasting(const CBattleInfoCallback & battle, bo
if (meleeRanged == 0 || (meleeRanged == 1 && ranged) || (meleeRanged == 2 && !ranged)) if (meleeRanged == 0 || (meleeRanged == 1 && ranged) || (meleeRanged == 2 && !ranged))
castMe = true; castMe = true;
} }
int chance = attacker->valOfBonuses((Selector::typeSubtype(attackMode, TBonusSubtype(spellID)))); int chance = attacker->valOfBonuses((Selector::typeSubtype(attackMode, BonusSubtypeID(spellID))));
vstd::amin(chance, 100); vstd::amin(chance, 100);
const CSpell * spell = SpellID(spellID).toSpell(); const CSpell * spell = SpellID(spellID).toSpell();
@ -1168,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, BonusSubtypeID::deathStareGorgon) / 100.0f; double chanceToKill = attacker->valOfBonuses(BonusType::DEATH_STARE, BonusCustomSubtype::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);
@ -1179,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, BonusSubtypeID::deathStareCommander)) / defender->level(); staredCreatures += (attacker->level() * attacker->valOfBonuses(BonusType::DEATH_STARE, BonusCustomSubtype::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...
@ -1249,9 +1249,9 @@ void BattleActionProcessor::handleAfterAttackCasting(const CBattleInfoCallback &
else else
resurrectInfo.type = attacker->creatureId(); resurrectInfo.type = attacker->creatureId();
if(attacker->hasBonusOfType((BonusType::TRANSMUTATION), BonusSubtypeID::transmutationPerHealth)) if(attacker->hasBonusOfType((BonusType::TRANSMUTATION), BonusCustomSubtype::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), BonusSubtypeID::transmutationPerUnit)) else if (attacker->hasBonusOfType((BonusType::TRANSMUTATION), BonusCustomSubtype::transmutationPerUnit))
resurrectInfo.count = defender->getCount(); resurrectInfo.count = defender->getCount();
else else
return; //wrong subtype return; //wrong subtype
@ -1273,21 +1273,21 @@ void BattleActionProcessor::handleAfterAttackCasting(const CBattleInfoCallback &
gameHandler->sendAndApply(&fakeEvent); gameHandler->sendAndApply(&fakeEvent);
} }
if(attacker->hasBonusOfType(BonusType::DESTRUCTION, BonusSubtypeID::destructionKillPercentage) || attacker->hasBonusOfType(BonusType::DESTRUCTION, BonusSubtypeID::destructionKillAmount)) if(attacker->hasBonusOfType(BonusType::DESTRUCTION, BonusCustomSubtype::destructionKillPercentage) || attacker->hasBonusOfType(BonusType::DESTRUCTION, BonusCustomSubtype::destructionKillAmount))
{ {
double chanceToTrigger = 0; double chanceToTrigger = 0;
int amountToDie = 0; int amountToDie = 0;
if(attacker->hasBonusOfType(BonusType::DESTRUCTION, BonusSubtypeID::destructionKillPercentage)) //killing by percentage if(attacker->hasBonusOfType(BonusType::DESTRUCTION, BonusCustomSubtype::destructionKillPercentage)) //killing by percentage
{ {
chanceToTrigger = attacker->valOfBonuses(BonusType::DESTRUCTION, BonusSubtypeID::destructionKillPercentage) / 100.0f; chanceToTrigger = attacker->valOfBonuses(BonusType::DESTRUCTION, BonusCustomSubtype::destructionKillPercentage) / 100.0f;
int percentageToDie = attacker->getBonus(Selector::type()(BonusType::DESTRUCTION).And(Selector::subtype()(BonusSubtypeID::destructionKillPercentage)))->additionalInfo[0]; int percentageToDie = attacker->getBonus(Selector::type()(BonusType::DESTRUCTION).And(Selector::subtype()(BonusCustomSubtype::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, BonusSubtypeID::destructionKillAmount)) //killing by count else if(attacker->hasBonusOfType(BonusType::DESTRUCTION, BonusCustomSubtype::destructionKillAmount)) //killing by count
{ {
chanceToTrigger = attacker->valOfBonuses(BonusType::DESTRUCTION, BonusSubtypeID::destructionKillAmount) / 100.0f; chanceToTrigger = attacker->valOfBonuses(BonusType::DESTRUCTION, BonusCustomSubtype::destructionKillAmount) / 100.0f;
amountToDie = attacker->getBonus(Selector::type()(BonusType::DESTRUCTION).And(Selector::subtype()(BonusSubtypeID::destructionKillAmount)))->additionalInfo[0]; amountToDie = attacker->getBonus(Selector::type()(BonusType::DESTRUCTION).And(Selector::subtype()(BonusCustomSubtype::destructionKillAmount)))->additionalInfo[0];
} }
vstd::amin(chanceToTrigger, 1); //cap trigger chance at 100% vstd::amin(chanceToTrigger, 1); //cap trigger chance at 100%
@ -1348,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 : { BonusSubtypeID::soulStealBattle, BonusSubtypeID::soulStealPermanent}) for(const auto & subtype : { BonusCustomSubtype::soulStealBattle, BonusCustomSubtype::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 == BonusSubtypeID::soulStealPermanent; bool permanent = subtype == BonusCustomSubtype::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;
@ -1366,9 +1366,9 @@ int64_t BattleActionProcessor::applyBattleEffects(const CBattleInfoCallback & ba
if(!bat.shot() && if(!bat.shot() &&
!def->isClone() && !def->isClone() &&
def->hasBonusOfType(BonusType::FIRE_SHIELD) && def->hasBonusOfType(BonusType::FIRE_SHIELD) &&
!attackerState->hasBonusOfType(BonusType::SPELL_SCHOOL_IMMUNITY, TBonusSubtype(SpellSchool::FIRE)) && !attackerState->hasBonusOfType(BonusType::SPELL_SCHOOL_IMMUNITY, BonusSubtypeID(SpellSchool::FIRE)) &&
!attackerState->hasBonusOfType(BonusType::NEGATIVE_EFFECTS_IMMUNITY, TBonusSubtype(SpellSchool::FIRE)) && !attackerState->hasBonusOfType(BonusType::NEGATIVE_EFFECTS_IMMUNITY, BonusSubtypeID(SpellSchool::FIRE)) &&
attackerState->valOfBonuses(BonusType::SPELL_DAMAGE_REDUCTION, TBonusSubtype(SpellSchool::FIRE)) < 100 && attackerState->valOfBonuses(BonusType::SPELL_DAMAGE_REDUCTION, BonusSubtypeID(SpellSchool::FIRE)) < 100 &&
CStack::isMeleeAttackPossible(attackerState.get(), def) // attacked needs to be adjacent to defender for fire shield to trigger (e.g. Dragon Breath attack) CStack::isMeleeAttackPossible(attackerState.get(), def) // attacked needs to be adjacent to defender for fire shield to trigger (e.g. Dragon Breath attack)
) )
{ {

View File

@ -383,7 +383,7 @@ bool BattleFlowProcessor::tryMakeAutomaticAction(const CBattleInfoCallback & bat
const CreatureID stackCreatureId = next->unitType()->getId(); const CreatureID stackCreatureId = next->unitType()->getId();
if ((stackCreatureId == CreatureID::ARROW_TOWERS || stackCreatureId == CreatureID::BALLISTA) if ((stackCreatureId == CreatureID::ARROW_TOWERS || stackCreatureId == CreatureID::BALLISTA)
&& (!curOwner || gameHandler->getRandomGenerator().nextInt(99) >= curOwner->valOfBonuses(BonusType::MANUAL_CONTROL, TBonusSubtype(stackCreatureId)))) && (!curOwner || gameHandler->getRandomGenerator().nextInt(99) >= curOwner->valOfBonuses(BonusType::MANUAL_CONTROL, BonusSubtypeID(stackCreatureId))))
{ {
BattleAction attack; BattleAction attack;
attack.actionType = EActionType::SHOOT; attack.actionType = EActionType::SHOOT;
@ -428,7 +428,7 @@ bool BattleFlowProcessor::tryMakeAutomaticAction(const CBattleInfoCallback & bat
return true; return true;
} }
if (!curOwner || gameHandler->getRandomGenerator().nextInt(99) >= curOwner->valOfBonuses(BonusType::MANUAL_CONTROL, TBonusSubtype(CreatureID(CreatureID::CATAPULT)))) if (!curOwner || gameHandler->getRandomGenerator().nextInt(99) >= curOwner->valOfBonuses(BonusType::MANUAL_CONTROL, BonusSubtypeID(CreatureID(CreatureID::CATAPULT))))
{ {
BattleAction attack; BattleAction attack;
attack.actionType = EActionType::CATAPULT; attack.actionType = EActionType::CATAPULT;
@ -453,7 +453,7 @@ bool BattleFlowProcessor::tryMakeAutomaticAction(const CBattleInfoCallback & bat
return true; return true;
} }
if (!curOwner || gameHandler->getRandomGenerator().nextInt(99) >= curOwner->valOfBonuses(BonusType::MANUAL_CONTROL, TBonusSubtype(CreatureID(CreatureID::FIRST_AID_TENT)))) if (!curOwner || gameHandler->getRandomGenerator().nextInt(99) >= curOwner->valOfBonuses(BonusType::MANUAL_CONTROL, BonusSubtypeID(CreatureID(CreatureID::FIRST_AID_TENT))))
{ {
RandomGeneratorUtil::randomShuffle(possibleStacks, gameHandler->getRandomGenerator()); RandomGeneratorUtil::randomShuffle(possibleStacks, gameHandler->getRandomGenerator());
const CStack * toBeHealed = possibleStacks.front(); const CStack * toBeHealed = possibleStacks.front();
@ -663,7 +663,7 @@ void BattleFlowProcessor::stackTurnTrigger(const CBattleInfoCallback & battle, c
if (st->hasBonusOfType(BonusType::POISON)) if (st->hasBonusOfType(BonusType::POISON))
{ {
std::shared_ptr<const Bonus> b = st->getBonusLocalFirst(Selector::source(BonusSource::SPELL_EFFECT, TBonusSourceID(SpellID(SpellID::POISON))).And(Selector::type()(BonusType::STACK_HEALTH))); std::shared_ptr<const Bonus> b = st->getBonusLocalFirst(Selector::source(BonusSource::SPELL_EFFECT, BonusSourceID(SpellID(SpellID::POISON))).And(Selector::type()(BonusType::STACK_HEALTH)));
if (b) //TODO: what if not?... if (b) //TODO: what if not?...
{ {
bte.val = std::max (b->val - 10, -(st->valOfBonuses(BonusType::POISON))); bte.val = std::max (b->val - 10, -(st->valOfBonuses(BonusType::POISON)));

View File

@ -140,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()); giveBonus.bonus = Bonus(BonusDuration::PERMANENT, BonusType::SPELLS_OF_LEVEL, BonusSource::OTHER, 0, BonusSourceID());
//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 = BonusSubtypeID::spellLevel(level); giveBonus.bonus.subtype = BonusCustomSubtype::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())); addNewBonus(std::make_shared<Bonus>(BonusDuration::PERMANENT, BonusType::SIEGE_WEAPON, BonusSource::CREATURE_ABILITY, 1, BonusSourceID()));
} }
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())); unit1.addNewBonus(std::make_shared<Bonus>(BonusDuration::PERMANENT, BonusType::HYPNOTIZED, BonusSource::CREATURE_ABILITY, 0, BonusSourceID()));
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())); unit1.addNewBonus(std::make_shared<Bonus>(BonusDuration::PERMANENT, BonusType::HYPNOTIZED, BonusSource::CREATURE_ABILITY, 0, BonusSourceID()));
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())); unit2.addNewBonus(std::make_shared<Bonus>(BonusDuration::PERMANENT, BonusType::HYPNOTIZED, BonusSource::CREATURE_ABILITY, 0, BonusSourceID()));
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())); unit1.addNewBonus(std::make_shared<Bonus>(BonusDuration::PERMANENT, BonusType::HYPNOTIZED, BonusSource::CREATURE_ABILITY, 0, BonusSourceID()));
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())); unit2.addNewBonus(std::make_shared<Bonus>(BonusDuration::PERMANENT, BonusType::HYPNOTIZED, BonusSource::CREATURE_ABILITY, 0, BonusSourceID()));
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())); unit1.addNewBonus(std::make_shared<Bonus>(BonusDuration::PERMANENT, BonusType::HYPNOTIZED, BonusSource::CREATURE_ABILITY, 0, BonusSourceID()));
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())); unit2.addNewBonus(std::make_shared<Bonus>(BonusDuration::PERMANENT, BonusType::HYPNOTIZED, BonusSource::CREATURE_ABILITY, 0, BonusSourceID()));
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())); unit1.addNewBonus(std::make_shared<Bonus>(BonusDuration::PERMANENT, BonusType::HYPNOTIZED, BonusSource::CREATURE_ABILITY, 0, BonusSourceID()));
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())); unit2.addNewBonus(std::make_shared<Bonus>(BonusDuration::PERMANENT, BonusType::HYPNOTIZED, BonusSource::CREATURE_ABILITY, 0, BonusSourceID()));
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())); bonusMock.addNewBonus(std::make_shared<Bonus>(BonusDuration::PERMANENT, BonusType::STACK_HEALTH, BonusSource::CREATURE_ABILITY, UNIT_HEALTH, BonusSourceID()));
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())); bonusMock.addNewBonus(std::make_shared<Bonus>(BonusDuration::PERMANENT, BonusType::STACK_HEALTH, BonusSource::CREATURE_ABILITY, 300, BonusSourceID()));
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(), TBonusSubtype(SpellID(DEFAULT_SPELL_INDEX)))); bonusMock.addNewBonus(std::make_shared<Bonus>(BonusDuration::PERMANENT, BonusType::SPELLCASTER, BonusSource::CREATURE_ABILITY, DEFAULT_SCHOOL_LEVEL, BonusSourceID(), BonusSubtypeID(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())); bonusMock.addNewBonus(std::make_shared<Bonus>(BonusDuration::PERMANENT, BonusType::CASTS, BonusSource::CREATURE_ABILITY, 567, BonusSourceID()));
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())); bonusMock.addNewBonus(std::make_shared<Bonus>(BonusDuration::PERMANENT, BonusType::CREATURE_SPELL_POWER, BonusSource::CREATURE_ABILITY, EFFECT_POWER, BonusSourceID()));
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())); bonusMock.addNewBonus(std::make_shared<Bonus>(BonusDuration::PERMANENT, BonusType::CREATURE_ENCHANT_POWER, BonusSource::CREATURE_ABILITY, ENCHANT_POWER, BonusSourceID()));
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(), TBonusSubtype(SpellID(DEFAULT_SPELL_INDEX)))); bonusMock.addNewBonus(std::make_shared<Bonus>(BonusDuration::PERMANENT, BonusType::SPECIFIC_SPELL_POWER, BonusSource::CREATURE_ABILITY, EFFECT_VALUE, BonusSourceID(), BonusSubtypeID(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())); bonusMock.addNewBonus(std::make_shared<Bonus>(BonusDuration::PERMANENT, BonusType::CASTS, BonusSource::CREATURE_ABILITY, 1, BonusSourceID()));
initUnit(); initUnit();

View File

@ -51,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())); bonusMock.addNewBonus(std::make_shared<Bonus>(BonusDuration::PERMANENT, BonusType::STACKS_SPEED, BonusSource::CREATURE_ABILITY, DEFAULT_SPEED, BonusSourceID()));
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_ATTACK, BonusSourceID(), BonusSubtypeID(PrimarySkill::ATTACK)));
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::PRIMARY_SKILL, BonusSource::CREATURE_ABILITY, DEFAULT_DEFENCE, BonusSourceID(), BonusSubtypeID(PrimarySkill::DEFENSE)));
bonusMock.addNewBonus(std::make_shared<Bonus>(BonusDuration::PERMANENT, BonusType::STACK_HEALTH, BonusSource::CREATURE_ABILITY, DEFAULT_HP, TBonusSourceID())); bonusMock.addNewBonus(std::make_shared<Bonus>(BonusDuration::PERMANENT, BonusType::STACK_HEALTH, BonusSource::CREATURE_ABILITY, DEFAULT_HP, BonusSourceID()));
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));
@ -66,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())); bonusMock.addNewBonus(std::make_shared<Bonus>(BonusDuration::PERMANENT, BonusType::SHOOTER, BonusSource::CREATURE_ABILITY, 1, BonusSourceID()));
bonusMock.addNewBonus(std::make_shared<Bonus>(BonusDuration::PERMANENT, BonusType::SHOTS, BonusSource::CREATURE_ABILITY, ammo, TBonusSourceID())); bonusMock.addNewBonus(std::make_shared<Bonus>(BonusDuration::PERMANENT, BonusType::SHOTS, BonusSource::CREATURE_ABILITY, ammo, BonusSourceID()));
} }
void initUnit() void initUnit()
@ -179,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())); bonusMock.addNewBonus(std::make_shared<Bonus>(BonusDuration::PERMANENT, BonusType::IN_FRENZY, BonusSource::SPELL_EFFECT, 50, BonusSourceID()));
int expectedAttack = static_cast<int>(DEFAULT_ATTACK + 0.5 * DEFAULT_DEFENCE); int expectedAttack = static_cast<int>(DEFAULT_ATTACK + 0.5 * DEFAULT_DEFENCE);
@ -191,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())); bonusMock.addNewBonus(std::make_shared<Bonus>(BonusDuration::PERMANENT, BonusType::IN_FRENZY, BonusSource::SPELL_EFFECT, 50, BonusSourceID()));
int expectedDefence = 0; int expectedDefence = 0;
@ -204,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()); auto bonus = std::make_shared<Bonus>(BonusDuration::PERMANENT, BonusType::ADDITIONAL_ATTACK, BonusSource::SPELL_EFFECT, 41, BonusSourceID());
bonusMock.addNewBonus(bonus); bonusMock.addNewBonus(bonus);
} }
@ -218,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()); auto bonus = std::make_shared<Bonus>(BonusDuration::PERMANENT, BonusType::ADDITIONAL_ATTACK, BonusSource::SPELL_EFFECT, 41, BonusSourceID());
bonus->effectRange = BonusLimitEffect::ONLY_MELEE_FIGHT; bonus->effectRange = BonusLimitEffect::ONLY_MELEE_FIGHT;
bonusMock.addNewBonus(bonus); bonusMock.addNewBonus(bonus);
@ -233,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()); auto bonus = std::make_shared<Bonus>(BonusDuration::PERMANENT, BonusType::ADDITIONAL_ATTACK, BonusSource::SPELL_EFFECT, 41, BonusSourceID());
bonus->effectRange = BonusLimitEffect::ONLY_DISTANCE_FIGHT; bonus->effectRange = BonusLimitEffect::ONLY_DISTANCE_FIGHT;
bonusMock.addNewBonus(bonus); bonusMock.addNewBonus(bonus);
@ -248,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(), BonusSubtypeID::creatureDamageBoth); auto bonus = std::make_shared<Bonus>(BonusDuration::PERMANENT, BonusType::CREATURE_DAMAGE, BonusSource::SPELL_EFFECT, 30, BonusSourceID(), BonusCustomSubtype::creatureDamageBoth);
bonusMock.addNewBonus(bonus); bonusMock.addNewBonus(bonus);
bonus = std::make_shared<Bonus>(BonusDuration::PERMANENT, BonusType::CREATURE_DAMAGE, BonusSource::SPELL_EFFECT, -20, TBonusSourceID(), BonusSubtypeID::creatureDamageMin); bonus = std::make_shared<Bonus>(BonusDuration::PERMANENT, BonusType::CREATURE_DAMAGE, BonusSource::SPELL_EFFECT, -20, BonusSourceID(), BonusCustomSubtype::creatureDamageMin);
bonusMock.addNewBonus(bonus); bonusMock.addNewBonus(bonus);
} }
@ -264,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(), BonusSubtypeID::creatureDamageBoth); auto bonus = std::make_shared<Bonus>(BonusDuration::PERMANENT, BonusType::CREATURE_DAMAGE, BonusSource::SPELL_EFFECT, 30, BonusSourceID(), BonusCustomSubtype::creatureDamageBoth);
bonusMock.addNewBonus(bonus); bonusMock.addNewBonus(bonus);
bonus = std::make_shared<Bonus>(BonusDuration::PERMANENT, BonusType::CREATURE_DAMAGE, BonusSource::SPELL_EFFECT, -20, TBonusSourceID(), BonusSubtypeID::creatureDamageMax); bonus = std::make_shared<Bonus>(BonusDuration::PERMANENT, BonusType::CREATURE_DAMAGE, BonusSource::SPELL_EFFECT, -20, BonusSourceID(), BonusCustomSubtype::creatureDamageMax);
bonusMock.addNewBonus(bonus); bonusMock.addNewBonus(bonus);
} }

View File

@ -107,7 +107,7 @@ TEST_F(CCreatureTest, JsonAddBonus)
{ {
JsonNode data(JsonNode::JsonType::DATA_STRUCT); JsonNode data(JsonNode::JsonType::DATA_STRUCT);
std::shared_ptr<Bonus> b = std::make_shared<Bonus>(BonusDuration::PERMANENT, BonusType::BLOCKS_RETALIATION, BonusSource::CREATURE_ABILITY, 17, TBonusSourceID(CreatureID(42)), TBonusSubtype(CreatureID(43)), BonusValueType::BASE_NUMBER); std::shared_ptr<Bonus> b = std::make_shared<Bonus>(BonusDuration::PERMANENT, BonusType::BLOCKS_RETALIATION, BonusSource::CREATURE_ABILITY, 17, BonusSourceID(CreatureID(42)), BonusSubtypeID(CreatureID(43)), BonusValueType::BASE_NUMBER);
JsonNode & toAdd = data["bonuses"]["toAdd"]; JsonNode & toAdd = data["bonuses"]["toAdd"];
@ -133,10 +133,10 @@ TEST_F(CCreatureTest, JsonRemoveBonus)
{ {
JsonNode data(JsonNode::JsonType::DATA_STRUCT); JsonNode data(JsonNode::JsonType::DATA_STRUCT);
std::shared_ptr<Bonus> b1 = std::make_shared<Bonus>(BonusDuration::PERMANENT, BonusType::BLOCKS_RETALIATION, BonusSource::CREATURE_ABILITY, 17, TBonusSourceID(CreatureID(42)), TBonusSubtype(CreatureID(43)), BonusValueType::BASE_NUMBER); std::shared_ptr<Bonus> b1 = std::make_shared<Bonus>(BonusDuration::PERMANENT, BonusType::BLOCKS_RETALIATION, BonusSource::CREATURE_ABILITY, 17, BonusSourceID(CreatureID(42)), BonusSubtypeID(CreatureID(43)), BonusValueType::BASE_NUMBER);
subject->addNewBonus(b1); subject->addNewBonus(b1);
std::shared_ptr<Bonus> b2 = std::make_shared<Bonus>(BonusDuration::PERMANENT, BonusType::BLOCKS_RETALIATION, BonusSource::CREATURE_ABILITY, 18, TBonusSourceID(CreatureID(42)), TBonusSubtype(CreatureID(43)), BonusValueType::BASE_NUMBER); std::shared_ptr<Bonus> b2 = std::make_shared<Bonus>(BonusDuration::PERMANENT, BonusType::BLOCKS_RETALIATION, BonusSource::CREATURE_ABILITY, 18, BonusSourceID(CreatureID(42)), BonusSubtypeID(CreatureID(43)), BonusValueType::BASE_NUMBER);
subject->addNewBonus(b2); subject->addNewBonus(b2);

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(), TBonusSubtype(SpellSchool::ANY))); casterBonuses.addNewBonus(std::make_shared<Bonus>(BonusDuration::ONE_BATTLE, BonusType::MAGIC_SCHOOL_SKILL, BonusSource::OTHER, 2, BonusSourceID(), BonusSubtypeID(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(), TBonusSubtype(SpellSchool::AIR))); casterBonuses.addNewBonus(std::make_shared<Bonus>(BonusDuration::ONE_BATTLE, BonusType::MAGIC_SCHOOL_SKILL, BonusSource::OTHER, 2, BonusSourceID(), BonusSubtypeID(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

@ -138,7 +138,7 @@ public:
EXPECT_EQ(marker.duration, BonusDuration::N_TURNS); EXPECT_EQ(marker.duration, BonusDuration::N_TURNS);
EXPECT_EQ(marker.turnsRemain, effectDuration); EXPECT_EQ(marker.turnsRemain, effectDuration);
EXPECT_EQ(marker.source, BonusSource::SPELL_EFFECT); EXPECT_EQ(marker.source, BonusSource::SPELL_EFFECT);
EXPECT_EQ(marker.sid, TBonusSourceID(SpellID(SpellID::CLONE))); EXPECT_EQ(marker.sid, BonusSourceID(SpellID(SpellID::CLONE)));
} }
void setDefaultExpectations() void setDefaultExpectations()

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())); targetUnit.addNewBonus(std::make_shared<Bonus>(BonusDuration::PERMANENT, BonusType::STACK_HEALTH, BonusSource::CREATURE_ABILITY, unitHP, BonusSourceID()));
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())); targetUnit.addNewBonus(std::make_shared<Bonus>(BonusDuration::PERMANENT, BonusType::STACK_HEALTH, BonusSource::CREATURE_ABILITY, unitHP, BonusSourceID()));
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())); targetUnit.addNewBonus(std::make_shared<Bonus>(BonusDuration::PERMANENT, BonusType::STACK_HEALTH, BonusSource::CREATURE_ABILITY, unitHP, BonusSourceID()));
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

@ -74,7 +74,7 @@ TEST_F(DispelTest, ApplicableToAliveUnitWithTimedEffect)
auto & unit = unitsFake.add(BattleSide::ATTACKER); auto & unit = unitsFake.add(BattleSide::ATTACKER);
unit.addNewBonus(std::make_shared<Bonus>(BonusDuration::PERMANENT, BonusType::PRIMARY_SKILL, BonusSource::SPELL_EFFECT, 1, TBonusSourceID(SpellID(negativeID)))); unit.addNewBonus(std::make_shared<Bonus>(BonusDuration::PERMANENT, BonusType::PRIMARY_SKILL, BonusSource::SPELL_EFFECT, 1, BonusSourceID(SpellID(negativeID))));
EXPECT_CALL(unit, isValidTarget(Eq(false))).WillOnce(Return(true)); EXPECT_CALL(unit, isValidTarget(Eq(false))).WillOnce(Return(true));
@ -101,7 +101,7 @@ TEST_F(DispelTest, IgnoresOwnEffects)
} }
auto & unit = unitsFake.add(BattleSide::ATTACKER); auto & unit = unitsFake.add(BattleSide::ATTACKER);
unit.addNewBonus(std::make_shared<Bonus>(BonusDuration::PERMANENT, BonusType::PRIMARY_SKILL, BonusSource::SPELL_EFFECT, 1, TBonusSourceID(SpellID(neutralID)))); unit.addNewBonus(std::make_shared<Bonus>(BonusDuration::PERMANENT, BonusType::PRIMARY_SKILL, BonusSource::SPELL_EFFECT, 1, BonusSourceID(SpellID(neutralID))));
EXPECT_CALL(unit, isValidTarget(Eq(false))).Times(AtMost(1)).WillRepeatedly(Return(true)); EXPECT_CALL(unit, isValidTarget(Eq(false))).Times(AtMost(1)).WillRepeatedly(Return(true));
@ -182,23 +182,23 @@ TEST_F(DispelApplyTest, RemovesEffects)
EXPECT_CALL(unit1, unitId()).Times(AtLeast(1)).WillRepeatedly(Return(unitIds[1])); EXPECT_CALL(unit1, unitId()).Times(AtLeast(1)).WillRepeatedly(Return(unitIds[1]));
{ {
auto bonus = std::make_shared<Bonus>(BonusDuration::PERMANENT, BonusType::PRIMARY_SKILL, BonusSource::SPELL_EFFECT, 1, TBonusSourceID(negativeID)); auto bonus = std::make_shared<Bonus>(BonusDuration::PERMANENT, BonusType::PRIMARY_SKILL, BonusSource::SPELL_EFFECT, 1, BonusSourceID(negativeID));
expectedBonus[0].emplace_back(*bonus); expectedBonus[0].emplace_back(*bonus);
unit0.addNewBonus(bonus); unit0.addNewBonus(bonus);
bonus = std::make_shared<Bonus>(BonusDuration::PERMANENT, BonusType::PRIMARY_SKILL, BonusSource::SPELL_EFFECT, 1, TBonusSourceID(negativeID)); bonus = std::make_shared<Bonus>(BonusDuration::PERMANENT, BonusType::PRIMARY_SKILL, BonusSource::SPELL_EFFECT, 1, BonusSourceID(negativeID));
expectedBonus[0].emplace_back(*bonus); expectedBonus[0].emplace_back(*bonus);
unit0.addNewBonus(bonus); unit0.addNewBonus(bonus);
bonus = std::make_shared<Bonus>(BonusDuration::N_TURNS, BonusType::GENERAL_ATTACK_REDUCTION, BonusSource::SPELL_EFFECT, 3, TBonusSourceID(negativeID)); bonus = std::make_shared<Bonus>(BonusDuration::N_TURNS, BonusType::GENERAL_ATTACK_REDUCTION, BonusSource::SPELL_EFFECT, 3, BonusSourceID(negativeID));
expectedBonus[0].emplace_back(*bonus); expectedBonus[0].emplace_back(*bonus);
unit0.addNewBonus(bonus); unit0.addNewBonus(bonus);
bonus = std::make_shared<Bonus>(BonusDuration::PERMANENT, BonusType::PRIMARY_SKILL, BonusSource::SPELL_EFFECT, 5, TBonusSourceID(positiveID)); bonus = std::make_shared<Bonus>(BonusDuration::PERMANENT, BonusType::PRIMARY_SKILL, BonusSource::SPELL_EFFECT, 5, BonusSourceID(positiveID));
expectedBonus[1].emplace_back(*bonus); expectedBonus[1].emplace_back(*bonus);
unit1.addNewBonus(bonus); unit1.addNewBonus(bonus);
bonus = std::make_shared<Bonus>(BonusDuration::N_TURNS, BonusType::GENERAL_ATTACK_REDUCTION, BonusSource::SPELL_EFFECT, 3, TBonusSourceID(positiveID)); bonus = std::make_shared<Bonus>(BonusDuration::N_TURNS, BonusType::GENERAL_ATTACK_REDUCTION, BonusSource::SPELL_EFFECT, 3, BonusSourceID(positiveID));
expectedBonus[1].emplace_back(*bonus); expectedBonus[1].emplace_back(*bonus);
unit1.addNewBonus(bonus); unit1.addNewBonus(bonus);
} }

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())); unit.addNewBonus(std::make_shared<Bonus>(BonusDuration::PERMANENT, BonusType::STACK_HEALTH, BonusSource::CREATURE_ABILITY, 200, BonusSourceID()));
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())); unit.addNewBonus(std::make_shared<Bonus>(BonusDuration::PERMANENT, BonusType::STACK_HEALTH, BonusSource::CREATURE_ABILITY, 200, BonusSourceID()));
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())); unit.addNewBonus(std::make_shared<Bonus>(BonusDuration::PERMANENT, BonusType::STACK_HEALTH, BonusSource::CREATURE_ABILITY, 200, BonusSourceID()));
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())); unit.addNewBonus(std::make_shared<Bonus>(BonusDuration::PERMANENT, BonusType::STACK_HEALTH, BonusSource::CREATURE_ABILITY, 200, BonusSourceID()));
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())); targetUnit.addNewBonus(std::make_shared<Bonus>(BonusDuration::PERMANENT, BonusType::STACK_HEALTH, BonusSource::CREATURE_ABILITY, unitHP, BonusSourceID()));
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())); targetUnit.addNewBonus(std::make_shared<Bonus>(BonusDuration::PERMANENT, BonusType::STACK_HEALTH, BonusSource::CREATURE_ABILITY, unitHP, BonusSourceID()));
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())); victim.addNewBonus(std::make_shared<Bonus>(BonusDuration::PERMANENT, BonusType::STACK_HEALTH, BonusSource::CREATURE_ABILITY, victimUnitHP, BonusSourceID()));
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())); acquired->addNewBonus(std::make_shared<Bonus>(BonusDuration::PERMANENT, BonusType::STACK_HEALTH, BonusSource::CREATURE_ABILITY, unitHealth, BonusSourceID()));
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())); unit.addNewBonus(std::make_shared<Bonus>(BonusDuration::PERMANENT, BonusType::STACK_HEALTH, BonusSource::CREATURE_ABILITY, unitHealth, BonusSourceID()));
{ {
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(), TBonusSubtype(PrimarySkill::KNOWLEDGE)); Bonus testBonus1(BonusDuration::PERMANENT, BonusType::PRIMARY_SKILL, BonusSource::OTHER, 3, BonusSourceID(), BonusSubtypeID(PrimarySkill::KNOWLEDGE));
Bonus testBonus2(BonusDuration::N_TURNS, BonusType::PRIMARY_SKILL, BonusSource::OTHER, 3, TBonusSourceID(), TBonusSubtype(PrimarySkill::KNOWLEDGE)); Bonus testBonus2(BonusDuration::N_TURNS, BonusType::PRIMARY_SKILL, BonusSource::OTHER, 3, BonusSourceID(), BonusSubtypeID(PrimarySkill::KNOWLEDGE));
testBonus2.turnsRemain = 4; testBonus2.turnsRemain = 4;
JsonNode options(JsonNode::JsonType::DATA_STRUCT); JsonNode options(JsonNode::JsonType::DATA_STRUCT);
@ -103,7 +103,7 @@ TEST_P(TimedApplyTest, ChangesBonuses)
for(auto & bonus : expectedBonus) for(auto & bonus : expectedBonus)
{ {
bonus.source = BonusSource::SPELL_EFFECT; bonus.source = BonusSource::SPELL_EFFECT;
bonus.sid = TBonusSourceID(SpellID(spellIndex)); bonus.sid = BonusSourceID(SpellID(spellIndex));
} }
if(cumulative) if(cumulative)

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()); auto bonus = std::make_shared<Bonus>(BonusDuration::ONE_BATTLE, BonusType::LEVEL_SPELL_IMMUNITY, BonusSource::OTHER, 3, BonusSourceID());
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()); auto bonus = std::make_shared<Bonus>(BonusDuration::ONE_BATTLE, BonusType::LEVEL_SPELL_IMMUNITY, BonusSource::OTHER, 5, BonusSourceID());
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()); auto bonus = std::make_shared<Bonus>(BonusDuration::ONE_BATTLE, BonusType::LEVEL_SPELL_IMMUNITY, BonusSource::OTHER, 4, BonusSourceID());
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()); auto bonus = std::make_shared<Bonus>(BonusDuration::ONE_BATTLE, BonusType::LEVEL_SPELL_IMMUNITY, BonusSource::OTHER, 4, BonusSourceID());
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(), TBonusSubtype(SpellID(immuneSpell))); auto bonus = std::make_shared<Bonus>(BonusDuration::ONE_BATTLE, BonusType::SPELL_IMMUNITY, BonusSource::OTHER, 4, BonusSourceID(), BonusSubtypeID(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(), TBonusSubtype(SpellID(immuneSpell))); auto bonus = std::make_shared<Bonus>(BonusDuration::ONE_BATTLE, BonusType::SPELL_IMMUNITY, BonusSource::OTHER, 4, BonusSourceID(), BonusSubtypeID(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())); unitBonuses.addNewBonus(std::make_shared<Bonus>(BonusDuration::ONE_BATTLE, BonusType::SPELL_DAMAGE_REDUCTION, BonusSource::OTHER, 100, BonusSourceID()));
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(), TBonusSubtype(SpellSchool::FIRE))); unitBonuses.addNewBonus(std::make_shared<Bonus>(BonusDuration::ONE_BATTLE, BonusType::SPELL_SCHOOL_IMMUNITY, BonusSource::OTHER, 0, BonusSourceID(), BonusSubtypeID(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(), TBonusSubtype(SpellSchool::AIR))); unitBonuses.addNewBonus(std::make_shared<Bonus>(BonusDuration::ONE_BATTLE, BonusType::SPELL_SCHOOL_IMMUNITY, BonusSource::SPELL_EFFECT, 0, BonusSourceID(), BonusSubtypeID(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(), TBonusSubtype(SpellSchool::WATER))); unitBonuses.addNewBonus(std::make_shared<Bonus>(BonusDuration::ONE_BATTLE, BonusType::SPELL_SCHOOL_IMMUNITY, BonusSource::SPELL_EFFECT, 0, BonusSourceID(), BonusSubtypeID(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(), TBonusSubtype(SpellSchool::AIR))); unitBonuses.addNewBonus(std::make_shared<Bonus>(BonusDuration::ONE_BATTLE, BonusType::NEGATIVE_EFFECTS_IMMUNITY, BonusSource::SPELL_EFFECT, 0, BonusSourceID(), BonusSubtypeID(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(), TBonusSubtype(SpellSchool::AIR))); unitBonuses.addNewBonus(std::make_shared<Bonus>(BonusDuration::ONE_BATTLE, BonusType::SPELL_SCHOOL_IMMUNITY, BonusSource::SPELL_EFFECT, 0, BonusSourceID(), BonusSubtypeID(SpellSchool::AIR)));
unitBonuses.addNewBonus(std::make_shared<Bonus>(BonusDuration::ONE_BATTLE, BonusType::NEGATIVE_EFFECTS_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, BonusSourceID(), BonusSubtypeID(SpellSchool::AIR)));
EXPECT_FALSE(subject->isReceptive(&mechanicsMock, &unitMock)); EXPECT_FALSE(subject->isReceptive(&mechanicsMock, &unitMock));
} }

View File

@ -57,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(), BonusSubtypeID::immunityEnemyHero)); unitBonuses.addNewBonus(std::make_shared<Bonus>(BonusDuration::ONE_BATTLE, BonusType::NEGATE_ALL_NATURAL_IMMUNITIES, BonusSource::OTHER, 0, BonusSourceID(), BonusCustomSubtype::immunityEnemyHero));
EXPECT_EQ(isMagicalEffect, subject->isReceptive(&mechanicsMock, &unitMock)); EXPECT_EQ(isMagicalEffect, subject->isReceptive(&mechanicsMock, &unitMock));
} }
@ -66,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(), BonusSubtypeID::immunityBattleWide)); unitBonuses.addNewBonus(std::make_shared<Bonus>(BonusDuration::ONE_BATTLE, BonusType::NEGATE_ALL_NATURAL_IMMUNITIES, BonusSource::OTHER, 0, BonusSourceID(), BonusCustomSubtype::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())); unitBonuses.addNewBonus(std::make_shared<Bonus>(BonusDuration::ONE_BATTLE, BonusType::LEVEL_SPELL_IMMUNITY, BonusSource::OTHER, 3, BonusSourceID()));
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())); unitBonuses.addNewBonus(std::make_shared<Bonus>(BonusDuration::ONE_BATTLE, BonusType::LEVEL_SPELL_IMMUNITY, BonusSource::OTHER, 5, BonusSourceID()));
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())); unitBonuses.addNewBonus(std::make_shared<Bonus>(BonusDuration::ONE_BATTLE, BonusType::LEVEL_SPELL_IMMUNITY, BonusSource::OTHER, 4, BonusSourceID()));
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(), TBonusSubtype(SpellID(immuneSpell))); auto bonus = std::make_shared<Bonus>(BonusDuration::ONE_BATTLE, BonusType::SPELL_IMMUNITY, BonusSource::OTHER, 4, BonusSourceID(), BonusSubtypeID(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(), TBonusSubtype(SpellID(immuneSpell))); auto bonus = std::make_shared<Bonus>(BonusDuration::ONE_BATTLE, BonusType::SPELL_IMMUNITY, BonusSource::OTHER, 4, BonusSourceID(), BonusSubtypeID(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())); unitBonuses.addNewBonus(std::make_shared<Bonus>(BonusDuration::ONE_BATTLE, BonusType::RECEPTIVE, BonusSource::OTHER, 0, BonusSourceID()));
} }
protected: protected:

View File

@ -45,7 +45,7 @@ TEST_F(SpellEffectConditionTest, ImmuneByDefault)
TEST_F(SpellEffectConditionTest, ReceptiveIfHasEffectFromDesiredSpell) TEST_F(SpellEffectConditionTest, ReceptiveIfHasEffectFromDesiredSpell)
{ {
setDefaultExpectations(); setDefaultExpectations();
unitBonuses.addNewBonus(std::make_shared<Bonus>(BonusDuration::ONE_BATTLE, BonusType::STACK_HEALTH, BonusSource::SPELL_EFFECT, 3, TBonusSourceID(SpellID(SpellID::AGE)))); unitBonuses.addNewBonus(std::make_shared<Bonus>(BonusDuration::ONE_BATTLE, BonusType::STACK_HEALTH, BonusSource::SPELL_EFFECT, 3, BonusSourceID(SpellID(SpellID::AGE))));
EXPECT_TRUE(subject->isReceptive(&mechanicsMock, &unitMock)); EXPECT_TRUE(subject->isReceptive(&mechanicsMock, &unitMock));
} }
@ -53,14 +53,14 @@ TEST_F(SpellEffectConditionTest, ReceptiveIfHasEffectFromDesiredSpell)
TEST_F(SpellEffectConditionTest, ImmuneIfHasEffectFromOtherSpell) TEST_F(SpellEffectConditionTest, ImmuneIfHasEffectFromOtherSpell)
{ {
setDefaultExpectations(); setDefaultExpectations();
unitBonuses.addNewBonus(std::make_shared<Bonus>(BonusDuration::ONE_BATTLE, BonusType::STACK_HEALTH, BonusSource::SPELL_EFFECT, 3, TBonusSourceID(SpellID(SpellID::AIR_SHIELD)))); unitBonuses.addNewBonus(std::make_shared<Bonus>(BonusDuration::ONE_BATTLE, BonusType::STACK_HEALTH, BonusSource::SPELL_EFFECT, 3, BonusSourceID(SpellID(SpellID::AIR_SHIELD))));
EXPECT_FALSE(subject->isReceptive(&mechanicsMock, &unitMock)); EXPECT_FALSE(subject->isReceptive(&mechanicsMock, &unitMock));
} }
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())); unitBonuses.addNewBonus(std::make_shared<Bonus>(BonusDuration::ONE_BATTLE, BonusType::STACK_HEALTH, BonusSource::CREATURE_ABILITY, 3, BonusSourceID()));
EXPECT_FALSE(subject->isReceptive(&mechanicsMock, &unitMock)); EXPECT_FALSE(subject->isReceptive(&mechanicsMock, &unitMock));
} }