1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-07-15 01:24:45 +02:00

Fix client & server compilation

This commit is contained in:
Ivan Savenko
2023-10-05 18:18:14 +03:00
parent 0a10fc30b8
commit 910ad50417
23 changed files with 112 additions and 108 deletions

View File

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

View File

@ -984,7 +984,7 @@ std::vector<CGPathNode *> AINodeStorage::calculateTeleportations(
struct TowmPortalFinder struct TowmPortalFinder
{ {
const std::vector<CGPathNode *> & initialNodes; const std::vector<CGPathNode *> & initialNodes;
MasteryLevel townPortalSkillLevel; MasteryLevel::Type townPortalSkillLevel;
uint64_t movementNeeded; uint64_t movementNeeded;
const ChainActor * actor; const ChainActor * actor;
const CGHeroInstance * hero; const CGHeroInstance * hero;
@ -1006,7 +1006,7 @@ struct TowmPortalFinder
townPortal = spellID.toSpell(); townPortal = spellID.toSpell();
// TODO: Copy/Paste from TownPortalMechanics // TODO: Copy/Paste from TownPortalMechanics
townPortalSkillLevel = MasteryLevel(hero->getSpellSchoolLevel(townPortal)); townPortalSkillLevel = MasteryLevel::Type(hero->getSpellSchoolLevel(townPortal));
movementNeeded = GameConstants::BASE_MOVEMENT_COST * (townPortalSkillLevel >= MasteryLevel::EXPERT ? 2 : 3); movementNeeded = GameConstants::BASE_MOVEMENT_COST * (townPortalSkillLevel >= MasteryLevel::EXPERT ? 2 : 3);
} }

View File

@ -118,14 +118,12 @@ Determines chance for affected heroes to learn spell casted by enemy hero after
Allows affected heroes to learn spell casted by enemy hero after battle Allows affected heroes to learn spell casted by enemy hero after battle
- subtype: must be set to -1
- val: maximal level of spell that can be learned - val: maximal level of spell that can be learned
### LEARN_MEETING_SPELL_LIMIT ### LEARN_MEETING_SPELL_LIMIT
Allows affected heroes to learn spells from each other during hero exchange Allows affected heroes to learn spells from each other during hero exchange
- subtype: must be set to -1
- val: maximal level of spell that can be learned - val: maximal level of spell that can be learned
### ROUGH_TERRAIN_DISCOUNT ### ROUGH_TERRAIN_DISCOUNT

View File

@ -60,6 +60,15 @@ static const TBonusSubtype visionsTowns; // 2
static const TBonusSubtype immunityBattleWide; // 0 static const TBonusSubtype immunityBattleWide; // 0
static const TBonusSubtype immunityEnemyHero; // 1 static const TBonusSubtype immunityEnemyHero; // 1
static const TBonusSubtype transmutationPerHealth; // 0
static const TBonusSubtype transmutationPerUnit; // 1
static const TBonusSubtype destructionKillPercentage; // 0
static const TBonusSubtype destructionKillAmount; // 1
static const TBonusSubtype soulStealPermanent; // 0
static const TBonusSubtype soulStealBattle; // 1
TBonusSubtype spellLevel(int level); TBonusSubtype spellLevel(int level);
TBonusSubtype creatureLevel(int level); TBonusSubtype creatureLevel(int level);

View File

@ -81,7 +81,7 @@ 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(ESpellSchool::ANY); subtype = TBonusSubtype(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;
@ -120,22 +120,22 @@ BonusParams::BonusParams(std::string deprecatedTypeStr, std::string deprecatedSu
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(ESpellSchool::AIR); subtype = TBonusSubtype(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(ESpellSchool::WATER); subtype = TBonusSubtype(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(ESpellSchool::FIRE); subtype = TBonusSubtype(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(ESpellSchool::EARTH); subtype = TBonusSubtype(SpellSchool::EARTH);
} }
else if (deprecatedSubtype == SecondarySkill::ARTILLERY || deprecatedSubtypeStr == "skill.artillery") else if (deprecatedSubtype == SecondarySkill::ARTILLERY || deprecatedSubtypeStr == "skill.artillery")
{ {

View File

@ -978,7 +978,6 @@ public:
// Deprecated // Deprecated
// TODO: remove // TODO: remove
using ESpellSchool = SpellSchool;
using ETownType = FactionID; using ETownType = FactionID;
using EGameResID = GameResID; using EGameResID = GameResID;
using River = RiverId; using River = RiverId;

View File

@ -28,7 +28,7 @@ CIdentifierStorage::CIdentifierStorage()
for (auto i = 0; i < GameConstants::DEFAULT_SCHOOLS; ++i) for (auto i = 0; i < GameConstants::DEFAULT_SCHOOLS; ++i)
registerObject(ModScope::scopeBuiltin(), "spellSchool", SpellConfig::SCHOOL[i].jsonName, SpellConfig::SCHOOL[i].id); registerObject(ModScope::scopeBuiltin(), "spellSchool", SpellConfig::SCHOOL[i].jsonName, SpellConfig::SCHOOL[i].id);
registerObject(ModScope::scopeBuiltin(), "spellSchool", "any", SpellSchool(ESpellSchool::ANY)); registerObject(ModScope::scopeBuiltin(), "spellSchool", "any", SpellSchool(SpellSchool::ANY));
for (int i = 0; i < GameConstants::RESOURCE_QUANTITY; ++i) for (int i = 0; i < GameConstants::RESOURCE_QUANTITY; ++i)
registerObject(ModScope::scopeBuiltin(), "resource", GameConstants::RESOURCE_NAMES[i], i); registerObject(ModScope::scopeBuiltin(), "resource", GameConstants::RESOURCE_NAMES[i], i);

View File

@ -42,19 +42,19 @@ static const std::string LEVEL_NAMES[] = {"none", "basic", "advanced", "expert"}
const spells::SchoolInfo SCHOOL[4] = const spells::SchoolInfo SCHOOL[4] =
{ {
{ {
ESpellSchool::AIR, SpellSchool::AIR,
"air" "air"
}, },
{ {
ESpellSchool::FIRE, SpellSchool::FIRE,
"fire" "fire"
}, },
{ {
ESpellSchool::WATER, SpellSchool::WATER,
"water" "water"
}, },
{ {
ESpellSchool::EARTH, SpellSchool::EARTH,
"earth" "earth"
} }
}; };
@ -62,10 +62,10 @@ const spells::SchoolInfo SCHOOL[4] =
//order as described in http://bugs.vcmi.eu/view.php?id=91 //order as described in http://bugs.vcmi.eu/view.php?id=91
static const SpellSchool SCHOOL_ORDER[4] = static const SpellSchool SCHOOL_ORDER[4] =
{ {
ESpellSchool::AIR, //=0 SpellSchool::AIR, //=0
ESpellSchool::FIRE, //=1 SpellSchool::FIRE, //=1
ESpellSchool::EARTH,//=3(!) SpellSchool::EARTH,//=3(!)
ESpellSchool::WATER //=2(!) SpellSchool::WATER //=2(!)
}; };
} //namespace SpellConfig } //namespace SpellConfig

View File

@ -229,7 +229,6 @@ void CGameHandler::levelUpCommander (const CCommanderInstance * c, int skill)
return; return;
} }
scp.accumulatedBonus.subtype = 0;
scp.accumulatedBonus.additionalInfo = 0; scp.accumulatedBonus.additionalInfo = 0;
scp.accumulatedBonus.duration = BonusDuration::PERMANENT; scp.accumulatedBonus.duration = BonusDuration::PERMANENT;
scp.accumulatedBonus.turnsRemain = 0; scp.accumulatedBonus.turnsRemain = 0;
@ -249,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 = static_cast<int>(PrimarySkill::ATTACK); scp.accumulatedBonus.subtype = TBonusSubtype(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 = static_cast<int>(PrimarySkill::DEFENSE); scp.accumulatedBonus.subtype = TBonusSubtype(PrimarySkill::DEFENSE);
break; break;
case ECommander::HEALTH: case ECommander::HEALTH:
scp.accumulatedBonus.type = BonusType::STACK_HEALTH; scp.accumulatedBonus.type = BonusType::STACK_HEALTH;
@ -261,7 +260,6 @@ void CGameHandler::levelUpCommander (const CCommanderInstance * c, int skill)
break; break;
case ECommander::DAMAGE: case ECommander::DAMAGE:
scp.accumulatedBonus.type = BonusType::CREATURE_DAMAGE; scp.accumulatedBonus.type = BonusType::CREATURE_DAMAGE;
scp.accumulatedBonus.subtype = 0;
scp.accumulatedBonus.valType = BonusValueType::PERCENT_TO_BASE; scp.accumulatedBonus.valType = BonusValueType::PERCENT_TO_BASE;
break; break;
case ECommander::SPEED: case ECommander::SPEED:
@ -788,9 +786,9 @@ void CGameHandler::onNewTurn()
if (!firstTurn) //not first day if (!firstTurn) //not first day
{ {
for (int k = 0; k < GameConstants::RESOURCE_QUANTITY; k++) for (GameResID k = GameResID::WOOD; k < GameResID::COUNT; k++)
{ {
n.res[elem.first][k] += h->valOfBonuses(BonusType::GENERATE_RESOURCE, k); n.res[elem.first][k] += h->valOfBonuses(BonusType::GENERATE_RESOURCE, TBonusSubtype(k));
} }
} }
} }
@ -1539,8 +1537,8 @@ void CGameHandler::useScholarSkill(ObjectInstanceID fromHero, ObjectInstanceID t
{ {
const CGHeroInstance * h1 = getHero(fromHero); const CGHeroInstance * h1 = getHero(fromHero);
const CGHeroInstance * h2 = getHero(toHero); const CGHeroInstance * h2 = getHero(toHero);
int h1_scholarSpellLevel = h1->valOfBonuses(BonusType::LEARN_MEETING_SPELL_LIMIT, -1); int h1_scholarSpellLevel = h1->valOfBonuses(BonusType::LEARN_MEETING_SPELL_LIMIT);
int h2_scholarSpellLevel = h2->valOfBonuses(BonusType::LEARN_MEETING_SPELL_LIMIT, -1); int h2_scholarSpellLevel = h2->valOfBonuses(BonusType::LEARN_MEETING_SPELL_LIMIT);
if (h1_scholarSpellLevel < h2_scholarSpellLevel) if (h1_scholarSpellLevel < h2_scholarSpellLevel)
{ {

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, -1, static_cast<int32_t>(PrimarySkill::DEFENSE), BonusValueType::PERCENT_TO_ALL); Bonus defenseBonusToAdd(BonusDuration::STACK_GETS_TURN, BonusType::PRIMARY_SKILL, BonusSource::OTHER, 20, -1, TBonusSubtype(PrimarySkill::DEFENSE), BonusValueType::PERCENT_TO_ALL);
Bonus bonus2(BonusDuration::STACK_GETS_TURN, BonusType::PRIMARY_SKILL, BonusSource::OTHER, stack->valOfBonuses(BonusType::DEFENSIVE_STANCE), -1, static_cast<int32_t>(PrimarySkill::DEFENSE), BonusValueType::ADDITIVE_VALUE); Bonus bonus2(BonusDuration::STACK_GETS_TURN, BonusType::PRIMARY_SKILL, BonusSource::OTHER, stack->valOfBonuses(BonusType::DEFENSIVE_STANCE), -1, TBonusSubtype(PrimarySkill::DEFENSE), BonusValueType::ADDITIVE_VALUE);
Bonus alternativeWeakCreatureBonus(BonusDuration::STACK_GETS_TURN, BonusType::PRIMARY_SKILL, BonusSource::OTHER, 1, -1, static_cast<int32_t>(PrimarySkill::DEFENSE), BonusValueType::ADDITIVE_VALUE); Bonus alternativeWeakCreatureBonus(BonusDuration::STACK_GETS_TURN, BonusType::PRIMARY_SKILL, BonusSource::OTHER, 1, -1, TBonusSubtype(PrimarySkill::DEFENSE), BonusValueType::ADDITIVE_VALUE);
BonusList defence = *stack->getBonuses(Selector::typeSubtype(BonusType::PRIMARY_SKILL, static_cast<int32_t>(PrimarySkill::DEFENSE))); BonusList defence = *stack->getBonuses(Selector::typeSubtype(BonusType::PRIMARY_SKILL, TBonusSubtype(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, stack->creatureIndex()); totalAttacks += attackingHero->valOfBonuses(BonusType::HERO_GRANTS_ATTACKS, TBonusSubtype(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, stack->creatureIndex()); totalRangedAttacks += attackingHero->valOfBonuses(BonusType::HERO_GRANTS_ATTACKS, TBonusSubtype(stack->creatureId()));
} }
for(int i = 1; i < totalRangedAttacks; ++i) for(int i = 1; i < totalRangedAttacks; ++i)
@ -382,13 +382,13 @@ 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 < 0) if(!catapultAbility || catapultAbility->subtype == TBonusSubtype::NONE)
{ {
gameHandler->complain("We do not know how to shoot :P"); gameHandler->complain("We do not know how to shoot :P");
} }
else else
{ {
const CSpell * spell = SpellID(catapultAbility->subtype).toSpell(); const CSpell * spell = catapultAbility->subtype.as<SpellID>().toSpell();
spells::BattleCast parameters(&battle, stack, spells::Mode::SPELL_LIKE_ATTACK, spell); //We can shot infinitely by catapult spells::BattleCast parameters(&battle, stack, spells::Mode::SPELL_LIKE_ATTACK, spell); //We can shot infinitely by catapult
auto shotLevel = stack->valOfBonuses(Selector::typeSubtype(BonusType::CATAPULT_EXTRA_SHOTS, catapultAbility->subtype)); auto shotLevel = stack->valOfBonuses(Selector::typeSubtype(BonusType::CATAPULT_EXTRA_SHOTS, catapultAbility->subtype));
parameters.setSpellLevel(shotLevel); parameters.setSpellLevel(shotLevel);
@ -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, spellID)); std::shared_ptr<const Bonus> spellcaster = stack->getBonus(Selector::typeSubtype(BonusType::SPELLCASTER, TBonusSubtype(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,13 +452,13 @@ 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 < 0) if(stack == nullptr || destStack == nullptr || !healerAbility || healerAbility->subtype == TBonusSubtype::NONE)
{ {
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");
} }
else else
{ {
const CSpell * spell = SpellID(healerAbility->subtype).toSpell(); const CSpell * spell = healerAbility->subtype.as<SpellID>().toSpell();
spells::BattleCast parameters(&battle, stack, spells::Mode::SPELL_LIKE_ATTACK, spell); //We can heal infinitely by first aid tent spells::BattleCast parameters(&battle, stack, spells::Mode::SPELL_LIKE_ATTACK, spell); //We can heal infinitely by first aid tent
auto dest = battle::Destination(destStack, target.at(0).hexValue); auto dest = battle::Destination(destStack, target.at(0).hexValue);
parameters.setSpellLevel(0); parameters.setSpellLevel(0);
@ -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, attacker->creatureIndex()); int chance = owner->valOfBonuses(BonusType::BONUS_DAMAGE_CHANCE, TBonusSubtype(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;
} }
@ -931,7 +931,7 @@ void BattleActionProcessor::makeAttack(const CBattleInfoCallback & battle, const
{ {
//this is need for displaying hit animation //this is need for displaying hit animation
bat.flags |= BattleAttack::SPELL_LIKE; bat.flags |= BattleAttack::SPELL_LIKE;
bat.spellID = SpellID(bonus->subtype); bat.spellID = bonus->subtype.as<SpellID>();
//TODO: should spell override creature`s projectile? //TODO: should spell override creature`s projectile?
@ -962,7 +962,7 @@ void BattleActionProcessor::makeAttack(const CBattleInfoCallback & battle, const
{ {
//this is need for displaying affect animation //this is need for displaying affect animation
bsa.flags |= BattleStackAttacked::SPELL_EFFECT; bsa.flags |= BattleStackAttacked::SPELL_EFFECT;
bsa.spellID = SpellID(bonus->subtype); bsa.spellID = bonus->subtype.as<SpellID>();
} }
} }
} }
@ -1084,7 +1084,7 @@ void BattleActionProcessor::attackCasting(const CBattleInfoCallback & battle, bo
TConstBonusListPtr spells = attacker->getBonuses(Selector::type()(attackMode)); TConstBonusListPtr spells = attacker->getBonuses(Selector::type()(attackMode));
for(const auto & sf : *spells) for(const auto & sf : *spells)
{ {
spellsToCast.insert(SpellID(sf->subtype)); spellsToCast.insert(sf->subtype.as<SpellID>());
} }
for(SpellID spellID : spellsToCast) for(SpellID spellID : spellsToCast)
{ {
@ -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, spellID)); TConstBonusListPtr spellsByType = attacker->getBonuses(Selector::typeSubtype(attackMode, TBonusSubtype(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, spellID))); int chance = attacker->valOfBonuses((Selector::typeSubtype(attackMode, TBonusSubtype(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, 0) / 100.0f; double chanceToKill = attacker->valOfBonuses(BonusType::DEATH_STARE, BonusSubtypes::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, 1)) / defender->level(); staredCreatures += (attacker->level() * attacker->valOfBonuses(BonusType::DEATH_STARE, BonusSubtypes::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), 0)) if(attacker->hasBonusOfType((BonusType::TRANSMUTATION), BonusSubtypes::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), 1)) else if (attacker->hasBonusOfType((BonusType::TRANSMUTATION), BonusSubtypes::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, 0) || attacker->hasBonusOfType(BonusType::DESTRUCTION, 1)) if(attacker->hasBonusOfType(BonusType::DESTRUCTION, BonusSubtypes::destructionKillPercentage) || attacker->hasBonusOfType(BonusType::DESTRUCTION, BonusSubtypes::destructionKillAmount))
{ {
double chanceToTrigger = 0; double chanceToTrigger = 0;
int amountToDie = 0; int amountToDie = 0;
if(attacker->hasBonusOfType(BonusType::DESTRUCTION, 0)) //killing by percentage if(attacker->hasBonusOfType(BonusType::DESTRUCTION, BonusSubtypes::destructionKillPercentage)) //killing by percentage
{ {
chanceToTrigger = attacker->valOfBonuses(BonusType::DESTRUCTION, 0) / 100.0f; chanceToTrigger = attacker->valOfBonuses(BonusType::DESTRUCTION, BonusSubtypes::destructionKillPercentage) / 100.0f;
int percentageToDie = attacker->getBonus(Selector::type()(BonusType::DESTRUCTION).And(Selector::subtype()(0)))->additionalInfo[0]; int percentageToDie = attacker->getBonus(Selector::type()(BonusType::DESTRUCTION).And(Selector::subtype()(BonusSubtypes::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, 1)) //killing by count else if(attacker->hasBonusOfType(BonusType::DESTRUCTION, BonusSubtypes::destructionKillAmount)) //killing by count
{ {
chanceToTrigger = attacker->valOfBonuses(BonusType::DESTRUCTION, 1) / 100.0f; chanceToTrigger = attacker->valOfBonuses(BonusType::DESTRUCTION, BonusSubtypes::destructionKillAmount) / 100.0f;
amountToDie = attacker->getBonus(Selector::type()(BonusType::DESTRUCTION).And(Selector::subtype()(1)))->additionalInfo[0]; amountToDie = attacker->getBonus(Selector::type()(BonusType::DESTRUCTION).And(Selector::subtype()(BonusSubtypes::destructionKillAmount)))->additionalInfo[0];
} }
vstd::amin(chanceToTrigger, 1); //cap trigger chance at 100% vstd::amin(chanceToTrigger, 1); //cap trigger chance at 100%
@ -1348,12 +1348,13 @@ 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(si32 subtype = 1; subtype >= 0; subtype--) for(const auto & subtype : { BonusSubtypes::soulStealBattle, BonusSubtypes::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();
attackerState->heal(toHeal, EHealLevel::OVERHEAL, ((subtype == 0) ? EHealPower::ONE_BATTLE : EHealPower::PERMANENT)); bool permanent = subtype == BonusSubtypes::soulStealPermanent;
attackerState->heal(toHeal, EHealLevel::OVERHEAL, (permanent ? EHealPower::PERMANENT : EHealPower::ONE_BATTLE));
drainedLife += toHeal; drainedLife += toHeal;
break; break;
} }
@ -1365,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, SpellSchool(ESpellSchool::FIRE)) && !attackerState->hasBonusOfType(BonusType::SPELL_SCHOOL_IMMUNITY, TBonusSubtype(SpellSchool::FIRE)) &&
!attackerState->hasBonusOfType(BonusType::NEGATIVE_EFFECTS_IMMUNITY, SpellSchool(ESpellSchool::FIRE)) && !attackerState->hasBonusOfType(BonusType::NEGATIVE_EFFECTS_IMMUNITY, TBonusSubtype(SpellSchool::FIRE)) &&
attackerState->valOfBonuses(BonusType::SPELL_DAMAGE_REDUCTION, SpellSchool(ESpellSchool::FIRE)) < 100 && attackerState->valOfBonuses(BonusType::SPELL_DAMAGE_REDUCTION, TBonusSubtype(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

@ -144,7 +144,7 @@ void BattleFlowProcessor::trySummonGuardians(const CBattleInfoCallback & battle,
std::shared_ptr<const Bonus> summonInfo = stack->getBonus(Selector::type()(BonusType::SUMMON_GUARDIANS)); std::shared_ptr<const Bonus> summonInfo = stack->getBonus(Selector::type()(BonusType::SUMMON_GUARDIANS));
auto accessibility = battle.getAccesibility(); auto accessibility = battle.getAccesibility();
CreatureID creatureData = CreatureID(summonInfo->subtype); CreatureID creatureData = summonInfo->subtype.as<CreatureID>();
std::vector<BattleHex> targetHexes; std::vector<BattleHex> targetHexes;
const bool targetIsBig = stack->unitType()->isDoubleWide(); //target = creature to guard const bool targetIsBig = stack->unitType()->isDoubleWide(); //target = creature to guard
const bool guardianIsBig = creatureData.toCreature()->isDoubleWide(); const bool guardianIsBig = creatureData.toCreature()->isDoubleWide();
@ -198,7 +198,7 @@ void BattleFlowProcessor::castOpeningSpells(const CBattleInfoCallback & battle)
{ {
spells::BonusCaster caster(h, b); spells::BonusCaster caster(h, b);
const CSpell * spell = SpellID(b->subtype).toSpell(); const CSpell * spell = b->subtype.as<SpellID>().toSpell();
spells::BattleCast parameters(&battle, &caster, spells::Mode::PASSIVE, spell); spells::BattleCast parameters(&battle, &caster, spells::Mode::PASSIVE, spell);
parameters.setSpellLevel(3); parameters.setSpellLevel(3);
@ -380,10 +380,10 @@ bool BattleFlowProcessor::tryMakeAutomaticAction(const CBattleInfoCallback & bat
} }
const CGHeroInstance * curOwner = battle.battleGetOwnerHero(next); const CGHeroInstance * curOwner = battle.battleGetOwnerHero(next);
const int 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, stackCreatureId))) && (!curOwner || gameHandler->getRandomGenerator().nextInt(99) >= curOwner->valOfBonuses(BonusType::MANUAL_CONTROL, TBonusSubtype(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, CreatureID::CATAPULT)) if (!curOwner || gameHandler->getRandomGenerator().nextInt(99) >= curOwner->valOfBonuses(BonusType::MANUAL_CONTROL, TBonusSubtype(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, CreatureID::FIRST_AID_TENT)) if (!curOwner || gameHandler->getRandomGenerator().nextInt(99) >= curOwner->valOfBonuses(BonusType::MANUAL_CONTROL, TBonusSubtype(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();
@ -583,7 +583,7 @@ void BattleFlowProcessor::stackEnchantedTrigger(const CBattleInfoCallback & batt
auto bl = *(st->getBonuses(Selector::type()(BonusType::ENCHANTED))); auto bl = *(st->getBonuses(Selector::type()(BonusType::ENCHANTED)));
for(auto b : bl) for(auto b : bl)
{ {
const CSpell * sp = SpellID(b->subtype).toSpell(); const CSpell * sp = b->subtype.as<SpellID>().toSpell();
if(!sp) if(!sp)
continue; continue;
@ -719,7 +719,7 @@ void BattleFlowProcessor::stackTurnTrigger(const CBattleInfoCallback & battle, c
while(!bl.empty() && !cast) while(!bl.empty() && !cast)
{ {
auto bonus = *RandomGeneratorUtil::nextItem(bl, gameHandler->getRandomGenerator()); auto bonus = *RandomGeneratorUtil::nextItem(bl, gameHandler->getRandomGenerator());
auto spellID = SpellID(bonus->subtype); auto spellID = bonus->subtype.as<SpellID>();
const CSpell * spell = SpellID(spellID).toSpell(); const CSpell * spell = SpellID(spellID).toSpell();
bl.remove_if([&bonus](const Bonus * b) bl.remove_if([&bonus](const Bonus * b)
{ {

View File

@ -316,9 +316,9 @@ void BattleResultProcessor::endBattleConfirm(const CBattleInfoCallback & battle)
if(!finishingBattle->isDraw() && finishingBattle->winnerHero) if(!finishingBattle->isDraw() && finishingBattle->winnerHero)
{ {
if (int eagleEyeLevel = finishingBattle->winnerHero->valOfBonuses(BonusType::LEARN_BATTLE_SPELL_LEVEL_LIMIT, -1)) if (int eagleEyeLevel = finishingBattle->winnerHero->valOfBonuses(BonusType::LEARN_BATTLE_SPELL_LEVEL_LIMIT))
{ {
double eagleEyeChance = finishingBattle->winnerHero->valOfBonuses(BonusType::LEARN_BATTLE_SPELL_CHANCE, 0); double eagleEyeChance = finishingBattle->winnerHero->valOfBonuses(BonusType::LEARN_BATTLE_SPELL_CHANCE);
for(auto & spellId : battle.getBattle()->getUsedSpells(battle.otherSide(battleResult->winner))) for(auto & spellId : battle.getBattle()->getUsedSpells(battle.otherSide(battleResult->winner)))
{ {
auto spell = spellId.toSpell(VLC->spells()); auto spell = spellId.toSpell(VLC->spells());

View File

@ -144,7 +144,7 @@ void PlayerMessageProcessor::cheatGiveSpells(PlayerColor player, const CGHeroIns
//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 = level; giveBonus.bonus.subtype = BonusSubtypes::spellLevel(level);
gameHandler->sendAndApply(&giveBonus); gameHandler->sendAndApply(&giveBonus);
} }

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, 0, DEFAULT_SPELL_INDEX)); bonusMock.addNewBonus(std::make_shared<Bonus>(BonusDuration::PERMANENT, BonusType::SPELLCASTER, BonusSource::CREATURE_ABILITY, DEFAULT_SCHOOL_LEVEL, 0, TBonusSubtype(SpellID(DEFAULT_SPELL_INDEX))));
} }
}; };
@ -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, 0, DEFAULT_SPELL_INDEX)); bonusMock.addNewBonus(std::make_shared<Bonus>(BonusDuration::PERMANENT, BonusType::SPECIFIC_SPELL_POWER, BonusSource::CREATURE_ABILITY, EFFECT_VALUE, 0, TBonusSubtype(SpellID(DEFAULT_SPELL_INDEX))));
makeNormalCaster(); makeNormalCaster();
EXPECT_EQ(subject.getEffectValue(&spellMock), EFFECT_VALUE * DEFAULT_AMOUNT); EXPECT_EQ(subject.getEffectValue(&spellMock), EFFECT_VALUE * DEFAULT_AMOUNT);

View File

@ -53,8 +53,8 @@ public:
{ {
bonusMock.addNewBonus(std::make_shared<Bonus>(BonusDuration::PERMANENT, BonusType::STACKS_SPEED, BonusSource::CREATURE_ABILITY, DEFAULT_SPEED, 0)); bonusMock.addNewBonus(std::make_shared<Bonus>(BonusDuration::PERMANENT, BonusType::STACKS_SPEED, BonusSource::CREATURE_ABILITY, DEFAULT_SPEED, 0));
bonusMock.addNewBonus(std::make_shared<Bonus>(BonusDuration::PERMANENT, BonusType::PRIMARY_SKILL, BonusSource::CREATURE_ABILITY, DEFAULT_ATTACK, 0, static_cast<int>(PrimarySkill::ATTACK))); bonusMock.addNewBonus(std::make_shared<Bonus>(BonusDuration::PERMANENT, BonusType::PRIMARY_SKILL, BonusSource::CREATURE_ABILITY, DEFAULT_ATTACK, 0, TBonusSubtype(PrimarySkill::ATTACK)));
bonusMock.addNewBonus(std::make_shared<Bonus>(BonusDuration::PERMANENT, BonusType::PRIMARY_SKILL, BonusSource::CREATURE_ABILITY, DEFAULT_DEFENCE, 0, static_cast<int>(PrimarySkill::DEFENSE))); bonusMock.addNewBonus(std::make_shared<Bonus>(BonusDuration::PERMANENT, BonusType::PRIMARY_SKILL, BonusSource::CREATURE_ABILITY, DEFAULT_DEFENCE, 0, TBonusSubtype(PrimarySkill::DEFENSE)));
bonusMock.addNewBonus(std::make_shared<Bonus>(BonusDuration::PERMANENT, BonusType::STACK_HEALTH, BonusSource::CREATURE_ABILITY, DEFAULT_HP, 0)); bonusMock.addNewBonus(std::make_shared<Bonus>(BonusDuration::PERMANENT, BonusType::STACK_HEALTH, BonusSource::CREATURE_ABILITY, DEFAULT_HP, 0));
@ -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, 0, 0); auto bonus = std::make_shared<Bonus>(BonusDuration::PERMANENT, BonusType::CREATURE_DAMAGE, BonusSource::SPELL_EFFECT, 30, 0, BonusSubtypes::creatureDamageBoth);
bonusMock.addNewBonus(bonus); bonusMock.addNewBonus(bonus);
bonus = std::make_shared<Bonus>(BonusDuration::PERMANENT, BonusType::CREATURE_DAMAGE, BonusSource::SPELL_EFFECT, -20, 0, 1); bonus = std::make_shared<Bonus>(BonusDuration::PERMANENT, BonusType::CREATURE_DAMAGE, BonusSource::SPELL_EFFECT, -20, 0, BonusSubtypes::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, 0, 0); auto bonus = std::make_shared<Bonus>(BonusDuration::PERMANENT, BonusType::CREATURE_DAMAGE, BonusSource::SPELL_EFFECT, 30, 0, BonusSubtypes::creatureDamageBoth);
bonusMock.addNewBonus(bonus); bonusMock.addNewBonus(bonus);
bonus = std::make_shared<Bonus>(BonusDuration::PERMANENT, BonusType::CREATURE_DAMAGE, BonusSource::SPELL_EFFECT, -20, 0, 2); bonus = std::make_shared<Bonus>(BonusDuration::PERMANENT, BonusType::CREATURE_DAMAGE, BonusSource::SPELL_EFFECT, -20, 0, BonusSubtypes::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, 42, 43, BonusValueType::BASE_NUMBER); std::shared_ptr<Bonus> b = std::make_shared<Bonus>(BonusDuration::PERMANENT, BonusType::BLOCKS_RETALIATION, BonusSource::CREATURE_ABILITY, 17, 42, TBonusSubtype(CreatureID(43)), BonusValueType::BASE_NUMBER);
JsonNode & toAdd = data["bonuses"]["toAdd"]; JsonNode & toAdd = data["bonuses"]["toAdd"];
@ -122,7 +122,7 @@ TEST_F(CCreatureTest, JsonAddBonus)
&& (bonus->source == BonusSource::CREATURE_ABILITY) && (bonus->source == BonusSource::CREATURE_ABILITY)
&& (bonus->val == 17) && (bonus->val == 17)
&& (bonus->sid == 42) && (bonus->sid == 42)
&& (bonus->subtype == 43) && (bonus->subtype.as<CreatureID>().getNum() == 43)
&& (bonus->valType == BonusValueType::BASE_NUMBER); && (bonus->valType == BonusValueType::BASE_NUMBER);
}; };
@ -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, 42, 43, BonusValueType::BASE_NUMBER); std::shared_ptr<Bonus> b1 = std::make_shared<Bonus>(BonusDuration::PERMANENT, BonusType::BLOCKS_RETALIATION, BonusSource::CREATURE_ABILITY, 17, 42, TBonusSubtype(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, 42, 43, BonusValueType::BASE_NUMBER); std::shared_ptr<Bonus> b2 = std::make_shared<Bonus>(BonusDuration::PERMANENT, BonusType::BLOCKS_RETALIATION, BonusSource::CREATURE_ABILITY, 18, 42, TBonusSubtype(CreatureID(43)), BonusValueType::BASE_NUMBER);
subject->addNewBonus(b2); subject->addNewBonus(b2);
@ -153,7 +153,7 @@ TEST_F(CCreatureTest, JsonRemoveBonus)
&& (bonus->source == BonusSource::CREATURE_ABILITY) && (bonus->source == BonusSource::CREATURE_ABILITY)
&& (bonus->val == 17) && (bonus->val == 17)
&& (bonus->sid == 42) && (bonus->sid == 42)
&& (bonus->subtype == 43) && (bonus->subtype.as<CreatureID>().getNum() == 43)
&& (bonus->valType == BonusValueType::BASE_NUMBER); && (bonus->valType == BonusValueType::BASE_NUMBER);
}; };
@ -166,7 +166,6 @@ TEST_F(CCreatureTest, JsonRemoveBonus)
&& (bonus->source == BonusSource::CREATURE_ABILITY) && (bonus->source == BonusSource::CREATURE_ABILITY)
&& (bonus->val == 18) && (bonus->val == 18)
&& (bonus->sid == 42) && (bonus->sid == 42)
&& (bonus->subtype == 43)
&& (bonus->valType == BonusValueType::BASE_NUMBER); && (bonus->valType == BonusValueType::BASE_NUMBER);
}; };

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

View File

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

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

View File

@ -49,7 +49,7 @@ TEST_F(BonusConditionTest, ReceptiveIfMatchesType)
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, SpellSchool(ESpellSchool::FIRE))); unitBonuses.addNewBonus(std::make_shared<Bonus>(BonusDuration::ONE_BATTLE, BonusType::SPELL_SCHOOL_IMMUNITY, BonusSource::OTHER, 0, SpellSchool(SpellSchool::FIRE)));
EXPECT_FALSE(subject->isReceptive(&mechanicsMock, &unitMock)); EXPECT_FALSE(subject->isReceptive(&mechanicsMock, &unitMock));
} }

View File

@ -30,8 +30,8 @@ public:
EXPECT_CALL(spellMock, forEachSchool(NotNull())).Times(AtLeast(1)).WillRepeatedly([](const spells::Spell::SchoolCallback & cb) EXPECT_CALL(spellMock, forEachSchool(NotNull())).Times(AtLeast(1)).WillRepeatedly([](const spells::Spell::SchoolCallback & cb)
{ {
bool stop = false; bool stop = false;
cb(SpellSchool(ESpellSchool::AIR), stop); cb(SpellSchool(SpellSchool::AIR), stop);
cb(SpellSchool(ESpellSchool::FIRE), stop); cb(SpellSchool(SpellSchool::FIRE), stop);
}); });
EXPECT_CALL(mechanicsMock, isPositiveSpell()).WillRepeatedly(Return(isPositive)); EXPECT_CALL(mechanicsMock, isPositiveSpell()).WillRepeatedly(Return(isPositive));
@ -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, 0, SpellSchool(ESpellSchool::AIR))); unitBonuses.addNewBonus(std::make_shared<Bonus>(BonusDuration::ONE_BATTLE, BonusType::SPELL_SCHOOL_IMMUNITY, BonusSource::SPELL_EFFECT, 0, 0, TBonusSubtype(SpellSchool::AIR)));
EXPECT_FALSE(subject->isReceptive(&mechanicsMock, &unitMock)); EXPECT_FALSE(subject->isReceptive(&mechanicsMock, &unitMock));
} }
@ -64,7 +64,7 @@ TEST_P(ElementalConditionTest, ImmuneIfBonusMatches)
TEST_P(ElementalConditionTest, NotImmuneIfBonusMismatches) TEST_P(ElementalConditionTest, NotImmuneIfBonusMismatches)
{ {
setDefaultExpectations(); setDefaultExpectations();
unitBonuses.addNewBonus(std::make_shared<Bonus>(BonusDuration::ONE_BATTLE, BonusType::SPELL_SCHOOL_IMMUNITY, BonusSource::SPELL_EFFECT, 0, 0, SpellSchool(ESpellSchool::WATER))); unitBonuses.addNewBonus(std::make_shared<Bonus>(BonusDuration::ONE_BATTLE, BonusType::SPELL_SCHOOL_IMMUNITY, BonusSource::SPELL_EFFECT, 0, 0, TBonusSubtype(SpellSchool::WATER)));
EXPECT_TRUE(subject->isReceptive(&mechanicsMock, &unitMock)); EXPECT_TRUE(subject->isReceptive(&mechanicsMock, &unitMock));
} }
@ -72,7 +72,7 @@ TEST_P(ElementalConditionTest, NotImmuneIfBonusMismatches)
TEST_P(ElementalConditionTest, DependsOnPositivness) TEST_P(ElementalConditionTest, DependsOnPositivness)
{ {
setDefaultExpectations(); setDefaultExpectations();
unitBonuses.addNewBonus(std::make_shared<Bonus>(BonusDuration::ONE_BATTLE, BonusType::NEGATIVE_EFFECTS_IMMUNITY, BonusSource::SPELL_EFFECT, 0, 0, SpellSchool(ESpellSchool::AIR))); unitBonuses.addNewBonus(std::make_shared<Bonus>(BonusDuration::ONE_BATTLE, BonusType::NEGATIVE_EFFECTS_IMMUNITY, BonusSource::SPELL_EFFECT, 0, 0, TBonusSubtype(SpellSchool::AIR)));
EXPECT_EQ(isPositive, subject->isReceptive(&mechanicsMock, &unitMock)); EXPECT_EQ(isPositive, subject->isReceptive(&mechanicsMock, &unitMock));
} }
@ -80,8 +80,8 @@ TEST_P(ElementalConditionTest, DependsOnPositivness)
TEST_P(ElementalConditionTest, ImmuneIfBothBonusesPresent) TEST_P(ElementalConditionTest, ImmuneIfBothBonusesPresent)
{ {
setDefaultExpectations(); setDefaultExpectations();
unitBonuses.addNewBonus(std::make_shared<Bonus>(BonusDuration::ONE_BATTLE, BonusType::SPELL_SCHOOL_IMMUNITY, BonusSource::SPELL_EFFECT, 0, 0, SpellSchool(ESpellSchool::AIR))); unitBonuses.addNewBonus(std::make_shared<Bonus>(BonusDuration::ONE_BATTLE, BonusType::SPELL_SCHOOL_IMMUNITY, BonusSource::SPELL_EFFECT, 0, 0, TBonusSubtype(SpellSchool::AIR)));
unitBonuses.addNewBonus(std::make_shared<Bonus>(BonusDuration::ONE_BATTLE, BonusType::NEGATIVE_EFFECTS_IMMUNITY, BonusSource::SPELL_EFFECT, 0, 0, SpellSchool(ESpellSchool::AIR))); unitBonuses.addNewBonus(std::make_shared<Bonus>(BonusDuration::ONE_BATTLE, BonusType::NEGATIVE_EFFECTS_IMMUNITY, BonusSource::SPELL_EFFECT, 0, 0, TBonusSubtype(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, 0, 1)); unitBonuses.addNewBonus(std::make_shared<Bonus>(BonusDuration::ONE_BATTLE, BonusType::NEGATE_ALL_NATURAL_IMMUNITIES, BonusSource::OTHER, 0, 0, BonusSubtypes::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, 0, 0)); unitBonuses.addNewBonus(std::make_shared<Bonus>(BonusDuration::ONE_BATTLE, BonusType::NEGATE_ALL_NATURAL_IMMUNITIES, BonusSource::OTHER, 0, 0, BonusSubtypes::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

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