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:
@ -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;
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
@ -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);
|
||||||
|
|
||||||
|
@ -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")
|
||||||
{
|
{
|
||||||
|
@ -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;
|
||||||
|
@ -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);
|
||||||
|
@ -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
|
||||||
|
|
||||||
|
@ -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)
|
||||||
{
|
{
|
||||||
|
@ -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)
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
|
@ -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)
|
||||||
{
|
{
|
||||||
|
@ -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());
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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);
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -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));
|
||||||
|
@ -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);
|
||||||
|
@ -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));
|
||||||
}
|
}
|
||||||
|
@ -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));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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));
|
||||||
}
|
}
|
||||||
|
@ -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));
|
||||||
|
@ -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));
|
||||||
|
Reference in New Issue
Block a user