mirror of
https://github.com/vcmi/vcmi.git
synced 2024-12-24 22:14:36 +02:00
Merge pull request #662 from ShubusCorporation/do_fix_morale
Fix: Morale bonus should be shown correctly
This commit is contained in:
commit
1f0f58a111
3
.gitignore
vendored
3
.gitignore
vendored
@ -42,11 +42,14 @@ VCMI_VS11.opensdf
|
||||
*.suo
|
||||
*.user
|
||||
/AI/*/RD
|
||||
/AI/BattleAI/*/RD
|
||||
/client/RD
|
||||
/launcher/RD
|
||||
/lib/RD
|
||||
/lib/minizip/RD
|
||||
/lib/minizip/*/RD
|
||||
/scripting/erm/RD
|
||||
/scripting/erm/*/RD
|
||||
/server/RD
|
||||
/test/RD
|
||||
/VCMI_VS11.VC.opendb
|
||||
|
@ -66,7 +66,7 @@ AttackPossibility AttackPossibility::evaluate(const BattleAttackInfo & attackInf
|
||||
auto attacker = attackInfo.attacker;
|
||||
auto defender = attackInfo.defender;
|
||||
const std::string cachingStringBlocksRetaliation = "type_BLOCKS_RETALIATION";
|
||||
static const auto selectorBlocksRetaliation = Selector::type(Bonus::BLOCKS_RETALIATION);
|
||||
static const auto selectorBlocksRetaliation = Selector::type()(Bonus::BLOCKS_RETALIATION);
|
||||
const auto attackerSide = getCbc()->playerToSide(getCbc()->battleGetOwner(attacker));
|
||||
const bool counterAttacksBlocked = attacker->hasBonus(selectorBlocksRetaliation, cachingStringBlocksRetaliation);
|
||||
|
||||
|
@ -52,13 +52,13 @@ armyStructure evaluateArmyStructure(const CArmedInstance * army)
|
||||
double shootersStrength = 0;
|
||||
ui32 maxSpeed = 0;
|
||||
|
||||
static const CSelector selectorSHOOTER = Selector::type(Bonus::SHOOTER);
|
||||
static const CSelector selectorSHOOTER = Selector::type()(Bonus::SHOOTER);
|
||||
static const std::string keySHOOTER = "type_"+std::to_string((int32_t)Bonus::SHOOTER);
|
||||
|
||||
static const CSelector selectorFLYING = Selector::type(Bonus::FLYING);
|
||||
static const CSelector selectorFLYING = Selector::type()(Bonus::FLYING);
|
||||
static const std::string keyFLYING = "type_"+std::to_string((int32_t)Bonus::FLYING);
|
||||
|
||||
static const CSelector selectorSTACKS_SPEED = Selector::type(Bonus::STACKS_SPEED);
|
||||
static const CSelector selectorSTACKS_SPEED = Selector::type()(Bonus::STACKS_SPEED);
|
||||
static const std::string keySTACKS_SPEED = "type_"+std::to_string((int32_t)Bonus::STACKS_SPEED);
|
||||
|
||||
for(auto s : army->Slots())
|
||||
|
@ -493,7 +493,7 @@ bool CMovementAnimation::init()
|
||||
distanceX = endPosition.x - begPosition.x;
|
||||
distanceY = endPosition.y - begPosition.y;
|
||||
|
||||
if (stack->hasBonus(Selector::type(Bonus::FLYING)))
|
||||
if (stack->hasBonus(Selector::type()(Bonus::FLYING)))
|
||||
{
|
||||
float distance = static_cast<float>(sqrt(distanceX * distanceX + distanceY * distanceY));
|
||||
|
||||
|
@ -904,7 +904,7 @@ void CBattleInterface::bSpellf()
|
||||
{
|
||||
//TODO: move to spell mechanics, add more information to spell cast problem
|
||||
//Handle Orb of Inhibition-like effects -> we want to display dialog with info, why casting is impossible
|
||||
auto blockingBonus = currentHero()->getBonusLocalFirst(Selector::type(Bonus::BLOCK_ALL_MAGIC));
|
||||
auto blockingBonus = currentHero()->getBonusLocalFirst(Selector::type()(Bonus::BLOCK_ALL_MAGIC));
|
||||
if (!blockingBonus)
|
||||
return;
|
||||
|
||||
@ -1638,8 +1638,8 @@ void CBattleInterface::activateStack()
|
||||
redrawBackgroundWithHexes(activeStack);
|
||||
|
||||
//set casting flag to true if creature can use it to not check it every time
|
||||
const auto spellcaster = s->getBonusLocalFirst(Selector::type(Bonus::SPELLCASTER)),
|
||||
randomSpellcaster = s->getBonusLocalFirst(Selector::type(Bonus::RANDOM_SPELLCASTER));
|
||||
const auto spellcaster = s->getBonusLocalFirst(Selector::type()(Bonus::SPELLCASTER)),
|
||||
randomSpellcaster = s->getBonusLocalFirst(Selector::type()(Bonus::RANDOM_SPELLCASTER));
|
||||
if(s->canCast() && (spellcaster || randomSpellcaster))
|
||||
{
|
||||
stackCanCastSpell = true;
|
||||
|
@ -367,19 +367,11 @@ void MoraleLuckBox::set(const IBonusBearer * node)
|
||||
const int neutralDescr[] = {60, 86}; //eg {Neutral Morale} \n\n Neutral morale means your armies will neither be blessed with extra attacks or freeze in combat.
|
||||
const int componentType[] = {CComponent::luck, CComponent::morale};
|
||||
const int hoverTextBase[] = {7, 4};
|
||||
const Bonus::BonusType bonusType[] = {Bonus::LUCK, Bonus::MORALE};
|
||||
int (IBonusBearer::*getValue[])() const = {&IBonusBearer::LuckVal, &IBonusBearer::MoraleVal};
|
||||
TConstBonusListPtr modifierList(new BonusList());
|
||||
TConstBonusListPtr modifierList = std::make_shared<const BonusList>();
|
||||
bonusValue = 0;
|
||||
|
||||
if(node)
|
||||
{
|
||||
modifierList = node->getBonuses(Selector::type(bonusType[morale]));
|
||||
bonusValue = (node->*getValue[morale])();
|
||||
}
|
||||
else
|
||||
{
|
||||
bonusValue = 0;
|
||||
}
|
||||
bonusValue = morale ? node->MoraleValAndBonusList(modifierList) : node->LuckValAndBonusList(modifierList);
|
||||
|
||||
int mrlt = (bonusValue>0)-(bonusValue<0); //signum: -1 - bad luck / morale, 0 - neutral, 1 - good
|
||||
hoverText = CGI->generaltexth->heroscrn[hoverTextBase[morale] - mrlt];
|
||||
@ -402,13 +394,13 @@ void MoraleLuckBox::set(const IBonusBearer * node)
|
||||
}
|
||||
else if(morale && node && node->hasBonusOfType(Bonus::NO_MORALE))
|
||||
{
|
||||
auto noMorale = node->getBonus(Selector::type(Bonus::NO_MORALE));
|
||||
auto noMorale = node->getBonus(Selector::type()(Bonus::NO_MORALE));
|
||||
text += "\n" + noMorale->Description();
|
||||
bonusValue = 0;
|
||||
}
|
||||
else if (!morale && node && node->hasBonusOfType(Bonus::NO_LUCK))
|
||||
{
|
||||
auto noLuck = node->getBonus(Selector::type(Bonus::NO_LUCK));
|
||||
auto noLuck = node->getBonus(Selector::type()(Bonus::NO_LUCK));
|
||||
text += "\n" + noLuck->Description();
|
||||
bonusValue = 0;
|
||||
}
|
||||
|
@ -990,7 +990,7 @@ void CArtifactInstance::deserializationFix()
|
||||
|
||||
SpellID CArtifactInstance::getGivenSpellID() const
|
||||
{
|
||||
const auto b = getBonusLocalFirst(Selector::type(Bonus::SPELL));
|
||||
const auto b = getBonusLocalFirst(Selector::type()(Bonus::SPELL));
|
||||
if(!b)
|
||||
{
|
||||
logMod->warn("Warning: %s doesn't bear any spell!", nodeName());
|
||||
|
@ -595,7 +595,7 @@ int CStackInstance::getLevel() const
|
||||
|
||||
si32 CStackInstance::magicResistance() const
|
||||
{
|
||||
si32 val = valOfBonuses(Selector::type(Bonus::MAGIC_RESISTANCE));
|
||||
si32 val = valOfBonuses(Selector::type()(Bonus::MAGIC_RESISTANCE));
|
||||
if (const CGHeroInstance * hero = dynamic_cast<const CGHeroInstance *>(_armyObj))
|
||||
{
|
||||
//resistance skill
|
||||
|
@ -1172,9 +1172,9 @@ void CGameState::prepareCrossoverHeroes(std::vector<CGameState::CampaignHeroRepl
|
||||
{
|
||||
for(int g=0; g<GameConstants::PRIMARY_SKILLS; ++g)
|
||||
{
|
||||
auto sel = Selector::type(Bonus::PRIMARY_SKILL)
|
||||
.And(Selector::subtype(g))
|
||||
.And(Selector::sourceType(Bonus::HERO_BASE_SKILL));
|
||||
auto sel = Selector::type()(Bonus::PRIMARY_SKILL)
|
||||
.And(Selector::subtype()(g))
|
||||
.And(Selector::sourceType()(Bonus::HERO_BASE_SKILL));
|
||||
|
||||
cgh->getBonusLocalFirst(sel)->val = cgh->type->heroClass->primarySkillInitial[g];
|
||||
}
|
||||
|
@ -1021,14 +1021,14 @@ TurnInfo::BonusCache::BonusCache(TConstBonusListPtr bl)
|
||||
for(int i = 0; i < ETerrainType::ROCK; i++)
|
||||
{
|
||||
noTerrainPenalty.push_back(static_cast<bool>(
|
||||
bl->getFirst(Selector::type(Bonus::NO_TERRAIN_PENALTY).And(Selector::subtype(i)))));
|
||||
bl->getFirst(Selector::type()(Bonus::NO_TERRAIN_PENALTY).And(Selector::subtype()(i)))));
|
||||
}
|
||||
|
||||
freeShipBoarding = static_cast<bool>(bl->getFirst(Selector::type(Bonus::FREE_SHIP_BOARDING)));
|
||||
flyingMovement = static_cast<bool>(bl->getFirst(Selector::type(Bonus::FLYING_MOVEMENT)));
|
||||
flyingMovementVal = bl->valOfBonuses(Selector::type(Bonus::FLYING_MOVEMENT));
|
||||
waterWalking = static_cast<bool>(bl->getFirst(Selector::type(Bonus::WATER_WALKING)));
|
||||
waterWalkingVal = bl->valOfBonuses(Selector::type(Bonus::WATER_WALKING));
|
||||
freeShipBoarding = static_cast<bool>(bl->getFirst(Selector::type()(Bonus::FREE_SHIP_BOARDING)));
|
||||
flyingMovement = static_cast<bool>(bl->getFirst(Selector::type()(Bonus::FLYING_MOVEMENT)));
|
||||
flyingMovementVal = bl->valOfBonuses(Selector::type()(Bonus::FLYING_MOVEMENT));
|
||||
waterWalking = static_cast<bool>(bl->getFirst(Selector::type()(Bonus::WATER_WALKING)));
|
||||
waterWalkingVal = bl->valOfBonuses(Selector::type()(Bonus::WATER_WALKING));
|
||||
}
|
||||
|
||||
TurnInfo::TurnInfo(const CGHeroInstance * Hero, const int turn)
|
||||
@ -1074,7 +1074,7 @@ bool TurnInfo::hasBonusOfType(Bonus::BonusType type, int subtype) const
|
||||
}
|
||||
|
||||
return static_cast<bool>(
|
||||
bonuses->getFirst(Selector::type(type).And(Selector::subtype(subtype))));
|
||||
bonuses->getFirst(Selector::type()(type).And(Selector::subtype()(subtype))));
|
||||
}
|
||||
|
||||
int TurnInfo::valOfBonuses(Bonus::BonusType type, int subtype) const
|
||||
@ -1087,7 +1087,7 @@ int TurnInfo::valOfBonuses(Bonus::BonusType type, int subtype) const
|
||||
return bonusCache->waterWalkingVal;
|
||||
}
|
||||
|
||||
return bonuses->valOfBonuses(Selector::type(type).And(Selector::subtype(subtype)));
|
||||
return bonuses->valOfBonuses(Selector::type()(type).And(Selector::subtype()(subtype)));
|
||||
}
|
||||
|
||||
int TurnInfo::getMaxMovePoints(const EPathfindingLayer layer) const
|
||||
|
@ -135,7 +135,7 @@ std::vector<si32> CStack::activeSpells() const
|
||||
|
||||
std::stringstream cachingStr;
|
||||
cachingStr << "!type_" << Bonus::NONE << "source_" << Bonus::SPELL_EFFECT;
|
||||
CSelector selector = Selector::sourceType(Bonus::SPELL_EFFECT)
|
||||
CSelector selector = Selector::sourceType()(Bonus::SPELL_EFFECT)
|
||||
.And(CSelector([](const Bonus * b)->bool
|
||||
{
|
||||
return b->type != Bonus::NONE;
|
||||
|
@ -92,82 +92,80 @@ const std::map<std::string, TUpdaterPtr> bonusUpdaterMap =
|
||||
|
||||
///CBonusProxy
|
||||
CBonusProxy::CBonusProxy(const IBonusBearer * Target, CSelector Selector)
|
||||
: cachedLast(0),
|
||||
: bonusListCachedLast(0),
|
||||
target(Target),
|
||||
selector(Selector),
|
||||
data()
|
||||
bonusList()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
CBonusProxy::CBonusProxy(const CBonusProxy & other)
|
||||
: cachedLast(other.cachedLast),
|
||||
: bonusListCachedLast(other.bonusListCachedLast),
|
||||
target(other.target),
|
||||
selector(other.selector),
|
||||
data(other.data)
|
||||
bonusList(other.bonusList)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
CBonusProxy::CBonusProxy(CBonusProxy && other)
|
||||
: cachedLast(0),
|
||||
: bonusListCachedLast(0),
|
||||
target(other.target),
|
||||
selector(),
|
||||
data()
|
||||
bonusList()
|
||||
{
|
||||
std::swap(cachedLast, other.cachedLast);
|
||||
std::swap(bonusListCachedLast, other.bonusListCachedLast);
|
||||
std::swap(selector, other.selector);
|
||||
std::swap(data, other.data);
|
||||
std::swap(bonusList, other.bonusList);
|
||||
}
|
||||
|
||||
CBonusProxy & CBonusProxy::operator=(const CBonusProxy & other)
|
||||
{
|
||||
cachedLast = other.cachedLast;
|
||||
bonusListCachedLast = other.bonusListCachedLast;
|
||||
selector = other.selector;
|
||||
data = other.data;
|
||||
bonusList = other.bonusList;
|
||||
return *this;
|
||||
}
|
||||
|
||||
CBonusProxy & CBonusProxy::operator=(CBonusProxy && other)
|
||||
{
|
||||
std::swap(cachedLast, other.cachedLast);
|
||||
std::swap(bonusListCachedLast, other.bonusListCachedLast);
|
||||
std::swap(selector, other.selector);
|
||||
std::swap(data, other.data);
|
||||
std::swap(bonusList, other.bonusList);
|
||||
return *this;
|
||||
}
|
||||
|
||||
TConstBonusListPtr CBonusProxy::get() const
|
||||
TConstBonusListPtr CBonusProxy::getBonusList() const
|
||||
{
|
||||
if(target->getTreeVersion() != cachedLast || !data)
|
||||
if(target->getTreeVersion() != bonusListCachedLast || !bonusList)
|
||||
{
|
||||
//TODO: support limiters
|
||||
data = target->getAllBonuses(selector, Selector::all);
|
||||
cachedLast = target->getTreeVersion();
|
||||
bonusList = target->getAllBonuses(selector, Selector::all);
|
||||
bonusListCachedLast = target->getTreeVersion();
|
||||
}
|
||||
return data;
|
||||
return bonusList;
|
||||
}
|
||||
|
||||
const BonusList * CBonusProxy::operator->() const
|
||||
{
|
||||
return get().get();
|
||||
return getBonusList().get();
|
||||
}
|
||||
|
||||
CTotalsProxy::CTotalsProxy(const IBonusBearer * Target, CSelector Selector, int InitialValue)
|
||||
: target(Target),
|
||||
selector(Selector),
|
||||
: CBonusProxy(Target, Selector),
|
||||
initialValue(InitialValue),
|
||||
meleeCachedLast(0),
|
||||
meleeValue(0),
|
||||
rangedCachedLast(0),
|
||||
rangedValue(0),
|
||||
value(0),
|
||||
cachedLast(0)
|
||||
valueCachedLast(0)
|
||||
{
|
||||
}
|
||||
|
||||
CTotalsProxy::CTotalsProxy(const CTotalsProxy & other)
|
||||
: target(other.target),
|
||||
selector(other.selector),
|
||||
: CBonusProxy(other),
|
||||
initialValue(other.initialValue),
|
||||
meleeCachedLast(other.meleeCachedLast),
|
||||
meleeValue(other.meleeValue),
|
||||
@ -178,13 +176,14 @@ CTotalsProxy::CTotalsProxy(const CTotalsProxy & other)
|
||||
|
||||
CTotalsProxy & CTotalsProxy::operator=(const CTotalsProxy & other)
|
||||
{
|
||||
CBonusProxy::operator=(other);
|
||||
initialValue = other.initialValue;
|
||||
meleeCachedLast = other.meleeCachedLast;
|
||||
meleeValue = other.meleeValue;
|
||||
rangedCachedLast = other.rangedCachedLast;
|
||||
rangedValue = other.rangedValue;
|
||||
value = other.value;
|
||||
cachedLast = other.cachedLast;
|
||||
valueCachedLast = other.valueCachedLast;
|
||||
|
||||
return *this;
|
||||
}
|
||||
@ -193,20 +192,32 @@ int CTotalsProxy::getValue() const
|
||||
{
|
||||
const auto treeVersion = target->getTreeVersion();
|
||||
|
||||
if(treeVersion != cachedLast)
|
||||
if(treeVersion != valueCachedLast)
|
||||
{
|
||||
auto bonuses = target->getBonuses(selector);
|
||||
auto bonuses = getBonusList();
|
||||
|
||||
value = initialValue + bonuses->totalValue();
|
||||
cachedLast = treeVersion;
|
||||
valueCachedLast = treeVersion;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
int CTotalsProxy::getValueAndList(TConstBonusListPtr & outBonusList) const
|
||||
{
|
||||
const auto treeVersion = target->getTreeVersion();
|
||||
outBonusList = getBonusList();
|
||||
|
||||
if(treeVersion != valueCachedLast)
|
||||
{
|
||||
value = initialValue + outBonusList->totalValue();
|
||||
valueCachedLast = treeVersion;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
int CTotalsProxy::getMeleeValue() const
|
||||
{
|
||||
static const auto limit = Selector::effectRange(Bonus::NO_LIMIT).Or(Selector::effectRange(Bonus::ONLY_MELEE_FIGHT));
|
||||
static const auto limit = Selector::effectRange()(Bonus::NO_LIMIT).Or(Selector::effectRange()(Bonus::ONLY_MELEE_FIGHT));
|
||||
|
||||
const auto treeVersion = target->getTreeVersion();
|
||||
|
||||
@ -222,7 +233,7 @@ int CTotalsProxy::getMeleeValue() const
|
||||
|
||||
int CTotalsProxy::getRangedValue() const
|
||||
{
|
||||
static const auto limit = Selector::effectRange(Bonus::NO_LIMIT).Or(Selector::effectRange(Bonus::ONLY_DISTANCE_FIGHT));
|
||||
static const auto limit = Selector::effectRange()(Bonus::NO_LIMIT).Or(Selector::effectRange()(Bonus::ONLY_DISTANCE_FIGHT));
|
||||
|
||||
const auto treeVersion = target->getTreeVersion();
|
||||
|
||||
@ -582,24 +593,28 @@ void BonusList::insert(BonusList::TInternalContainer::iterator position, BonusLi
|
||||
}
|
||||
|
||||
CSelector IBonusBearer::anaffectedByMoraleSelector
|
||||
= Selector::type(Bonus::NON_LIVING)
|
||||
.Or(Selector::type(Bonus::UNDEAD))
|
||||
.Or(Selector::type(Bonus::NO_MORALE))
|
||||
.Or(Selector::type(Bonus::SIEGE_WEAPON));
|
||||
= Selector::type()(Bonus::NON_LIVING)
|
||||
.Or(Selector::type()(Bonus::UNDEAD))
|
||||
.Or(Selector::type()(Bonus::NO_MORALE))
|
||||
.Or(Selector::type()(Bonus::SIEGE_WEAPON));
|
||||
|
||||
CSelector IBonusBearer::moraleSelector = Selector::type(Bonus::MORALE);
|
||||
CSelector IBonusBearer::selfMoraleSelector = Selector::type(Bonus::SELF_MORALE);
|
||||
CSelector IBonusBearer::moraleSelector = Selector::type()(Bonus::MORALE);
|
||||
CSelector IBonusBearer::luckSelector = Selector::type()(Bonus::LUCK);
|
||||
CSelector IBonusBearer::selfMoraleSelector = Selector::type()(Bonus::SELF_MORALE);
|
||||
CSelector IBonusBearer::selfLuckSelector = Selector::type()(Bonus::SELF_LUCK);
|
||||
|
||||
IBonusBearer::IBonusBearer()
|
||||
:anaffectedByMorale(this, anaffectedByMoraleSelector),
|
||||
moraleValue(this, moraleSelector, 0),
|
||||
selfMorale(this, selfMoraleSelector)
|
||||
luckValue(this, luckSelector, 0),
|
||||
selfMorale(this, selfMoraleSelector),
|
||||
selfLuck(this, selfLuckSelector)
|
||||
{
|
||||
}
|
||||
|
||||
int IBonusBearer::valOfBonuses(Bonus::BonusType type, const CSelector &selector) const
|
||||
{
|
||||
return valOfBonuses(Selector::type(type).And(selector));
|
||||
return valOfBonuses(Selector::type()(type).And(selector));
|
||||
}
|
||||
|
||||
int IBonusBearer::valOfBonuses(Bonus::BonusType type, int subtype) const
|
||||
@ -607,9 +622,9 @@ int IBonusBearer::valOfBonuses(Bonus::BonusType type, int subtype) const
|
||||
boost::format fmt("type_%ds_%d");
|
||||
fmt % (int)type % subtype;
|
||||
|
||||
CSelector s = Selector::type(type);
|
||||
CSelector s = Selector::type()(type);
|
||||
if(subtype != -1)
|
||||
s = s.And(Selector::subtype(subtype));
|
||||
s = s.And(Selector::subtype()(subtype));
|
||||
|
||||
return valOfBonuses(s, fmt.str());
|
||||
}
|
||||
@ -635,9 +650,9 @@ bool IBonusBearer::hasBonusOfType(Bonus::BonusType type, int subtype) const
|
||||
boost::format fmt("type_%ds_%d");
|
||||
fmt % (int)type % subtype;
|
||||
|
||||
CSelector s = Selector::type(type);
|
||||
CSelector s = Selector::type()(type);
|
||||
if(subtype != -1)
|
||||
s = s.And(Selector::subtype(subtype));
|
||||
s = s.And(Selector::subtype()(subtype));
|
||||
|
||||
return hasBonus(s, fmt.str());
|
||||
}
|
||||
@ -678,9 +693,41 @@ int IBonusBearer::LuckVal() const
|
||||
if(hasBonusOfType(Bonus::NO_LUCK))
|
||||
return 0;
|
||||
|
||||
int ret = valOfBonuses(Bonus::LUCK);
|
||||
int ret = luckValue.getValue();
|
||||
|
||||
if(hasBonusOfType(Bonus::SELF_LUCK)) //eg. halfling
|
||||
if(selfLuck.getHasBonus()) //eg. halfling
|
||||
vstd::amax(ret, +1);
|
||||
|
||||
return vstd::abetween(ret, -3, +3);
|
||||
}
|
||||
|
||||
int IBonusBearer::MoraleValAndBonusList(TConstBonusListPtr & bonusList) const
|
||||
{
|
||||
if(anaffectedByMorale.getHasBonus())
|
||||
{
|
||||
if(!bonusList->empty())
|
||||
bonusList = std::make_shared<const BonusList>();
|
||||
return 0;
|
||||
}
|
||||
int ret = moraleValue.getValueAndList(bonusList);
|
||||
|
||||
if(selfMorale.getHasBonus()) //eg. minotaur
|
||||
vstd::amax(ret, +1);
|
||||
|
||||
return vstd::abetween(ret, -3, +3);
|
||||
}
|
||||
|
||||
int IBonusBearer::LuckValAndBonusList(TConstBonusListPtr & bonusList) const
|
||||
{
|
||||
if(hasBonusOfType(Bonus::NO_LUCK))
|
||||
{
|
||||
if(!bonusList->empty())
|
||||
bonusList = std::make_shared<const BonusList>();
|
||||
return 0;
|
||||
}
|
||||
int ret = luckValue.getValueAndList(bonusList);
|
||||
|
||||
if(selfLuck.getHasBonus()) //eg. halfling
|
||||
vstd::amax(ret, +1);
|
||||
|
||||
return vstd::abetween(ret, -3, +3);
|
||||
@ -689,7 +736,7 @@ int IBonusBearer::LuckVal() const
|
||||
ui32 IBonusBearer::MaxHealth() const
|
||||
{
|
||||
const std::string cachingStr = "type_STACK_HEALTH";
|
||||
static const auto selector = Selector::type(Bonus::STACK_HEALTH);
|
||||
static const auto selector = Selector::type()(Bonus::STACK_HEALTH);
|
||||
auto value = valOfBonuses(selector, cachingStr);
|
||||
return std::max(1, value); //never 0
|
||||
}
|
||||
@ -735,12 +782,12 @@ si32 IBonusBearer::manaLimit() const
|
||||
|
||||
int IBonusBearer::getPrimSkillLevel(PrimarySkill::PrimarySkill id) const
|
||||
{
|
||||
static const CSelector selectorAllSkills = Selector::type(Bonus::PRIMARY_SKILL);
|
||||
static const CSelector selectorAllSkills = Selector::type()(Bonus::PRIMARY_SKILL);
|
||||
static const std::string keyAllSkills = "type_PRIMARY_SKILL";
|
||||
|
||||
auto allSkills = getBonuses(selectorAllSkills, keyAllSkills);
|
||||
|
||||
int ret = allSkills->valOfBonuses(Selector::subtype(id));
|
||||
int ret = allSkills->valOfBonuses(Selector::subtype()(id));
|
||||
|
||||
vstd::amax(ret, id/2); //minimal value is 0 for attack and defense and 1 for spell power and knowledge
|
||||
return ret;
|
||||
@ -754,26 +801,26 @@ si32 IBonusBearer::magicResistance() const
|
||||
ui32 IBonusBearer::Speed(int turn, bool useBind) const
|
||||
{
|
||||
//war machines cannot move
|
||||
if(hasBonus(Selector::type(Bonus::SIEGE_WEAPON).And(Selector::turns(turn))))
|
||||
if(hasBonus(Selector::type()(Bonus::SIEGE_WEAPON).And(Selector::turns(turn))))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
//bind effect check - doesn't influence stack initiative
|
||||
if(useBind && hasBonus(Selector::type(Bonus::BIND_EFFECT).And(Selector::turns(turn))))
|
||||
if(useBind && hasBonus(Selector::type()(Bonus::BIND_EFFECT).And(Selector::turns(turn))))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
return valOfBonuses(Selector::type(Bonus::STACKS_SPEED).And(Selector::turns(turn)));
|
||||
return valOfBonuses(Selector::type()(Bonus::STACKS_SPEED).And(Selector::turns(turn)));
|
||||
}
|
||||
|
||||
bool IBonusBearer::isLiving() const //TODO: theoreticaly there exists "LIVING" bonus in stack experience documentation
|
||||
{
|
||||
static const std::string cachingStr = "IBonusBearer::isLiving";
|
||||
static const CSelector selector = Selector::type(Bonus::UNDEAD)
|
||||
.Or(Selector::type(Bonus::NON_LIVING))
|
||||
.Or(Selector::type(Bonus::GARGOYLE))
|
||||
.Or(Selector::type(Bonus::SIEGE_WEAPON));
|
||||
static const CSelector selector = Selector::type()(Bonus::UNDEAD)
|
||||
.Or(Selector::type()(Bonus::NON_LIVING))
|
||||
.Or(Selector::type()(Bonus::GARGOYLE))
|
||||
.Or(Selector::type()(Bonus::SIEGE_WEAPON));
|
||||
|
||||
return !hasBonus(selector, cachingStr);
|
||||
}
|
||||
@ -1561,17 +1608,42 @@ std::shared_ptr<Bonus> Bonus::addPropagator(TPropagatorPtr Propagator)
|
||||
|
||||
namespace Selector
|
||||
{
|
||||
DLL_LINKAGE CSelectFieldEqual<Bonus::BonusType> type(&Bonus::type);
|
||||
DLL_LINKAGE CSelectFieldEqual<TBonusSubtype> subtype(&Bonus::subtype);
|
||||
DLL_LINKAGE CSelectFieldEqual<CAddInfo> info(&Bonus::additionalInfo);
|
||||
DLL_LINKAGE CSelectFieldEqual<Bonus::BonusSource> sourceType(&Bonus::source);
|
||||
DLL_LINKAGE CSelectFieldEqual<Bonus::LimitEffect> effectRange(&Bonus::effectRange);
|
||||
DLL_LINKAGE CSelectFieldEqual<Bonus::BonusType> & type()
|
||||
{
|
||||
static CSelectFieldEqual<Bonus::BonusType> stype(&Bonus::type);
|
||||
return stype;
|
||||
}
|
||||
|
||||
DLL_LINKAGE CSelectFieldEqual<TBonusSubtype> & subtype()
|
||||
{
|
||||
static CSelectFieldEqual<TBonusSubtype> ssubtype(&Bonus::subtype);
|
||||
return ssubtype;
|
||||
}
|
||||
|
||||
DLL_LINKAGE CSelectFieldEqual<CAddInfo> & info()
|
||||
{
|
||||
static CSelectFieldEqual<CAddInfo> sinfo(&Bonus::additionalInfo);
|
||||
return sinfo;
|
||||
}
|
||||
|
||||
DLL_LINKAGE CSelectFieldEqual<Bonus::BonusSource> & sourceType()
|
||||
{
|
||||
static CSelectFieldEqual<Bonus::BonusSource> ssourceType(&Bonus::source);
|
||||
return ssourceType;
|
||||
}
|
||||
|
||||
DLL_LINKAGE CSelectFieldEqual<Bonus::LimitEffect> & effectRange()
|
||||
{
|
||||
static CSelectFieldEqual<Bonus::LimitEffect> seffectRange(&Bonus::effectRange);
|
||||
return seffectRange;
|
||||
}
|
||||
|
||||
DLL_LINKAGE CWillLastTurns turns;
|
||||
DLL_LINKAGE CWillLastDays days;
|
||||
|
||||
CSelector DLL_LINKAGE typeSubtype(Bonus::BonusType Type, TBonusSubtype Subtype)
|
||||
{
|
||||
return type(Type).And(subtype(Subtype));
|
||||
return type()(Type).And(subtype()(Subtype));
|
||||
}
|
||||
|
||||
CSelector DLL_LINKAGE typeSubtypeInfo(Bonus::BonusType type, TBonusSubtype subtype, CAddInfo info)
|
||||
@ -1796,7 +1868,7 @@ int HasAnotherBonusLimiter::limit(const BonusLimitationContext &context) const
|
||||
{
|
||||
CSelector mySelector = isSubtypeRelevant
|
||||
? Selector::typeSubtype(type, subtype)
|
||||
: Selector::type(type);
|
||||
: Selector::type()(type);
|
||||
|
||||
//if we have a bonus of required type accepted, limiter should accept also this bonus
|
||||
if(context.alreadyAccepted.getFirst(mySelector))
|
||||
|
@ -77,18 +77,17 @@ public:
|
||||
|
||||
CBonusProxy & operator=(CBonusProxy && other);
|
||||
CBonusProxy & operator=(const CBonusProxy & other);
|
||||
|
||||
TConstBonusListPtr get() const;
|
||||
|
||||
const BonusList * operator->() const;
|
||||
private:
|
||||
mutable int64_t cachedLast;
|
||||
const IBonusBearer * target;
|
||||
TConstBonusListPtr getBonusList() const;
|
||||
|
||||
protected:
|
||||
CSelector selector;
|
||||
mutable TConstBonusListPtr data;
|
||||
const IBonusBearer * target;
|
||||
mutable int64_t bonusListCachedLast;
|
||||
mutable TConstBonusListPtr bonusList;
|
||||
};
|
||||
|
||||
class DLL_LINKAGE CTotalsProxy
|
||||
class DLL_LINKAGE CTotalsProxy : public CBonusProxy
|
||||
{
|
||||
public:
|
||||
CTotalsProxy(const IBonusBearer * Target, CSelector Selector, int InitialValue);
|
||||
@ -101,13 +100,17 @@ public:
|
||||
int getMeleeValue() const;
|
||||
int getRangedValue() const;
|
||||
int getValue() const;
|
||||
/**
|
||||
Returns total value of all selected bonuses and sets bonusList as a pointer to the list of selected bonuses
|
||||
@param bonusList is the out list of all selected bonuses
|
||||
@return total value of all selected bonuses and 0 otherwise
|
||||
*/
|
||||
int getValueAndList(TConstBonusListPtr & bonusList) const;
|
||||
|
||||
private:
|
||||
const IBonusBearer * target;
|
||||
CSelector selector;
|
||||
int initialValue;
|
||||
|
||||
mutable int64_t cachedLast;
|
||||
mutable int64_t valueCachedLast;
|
||||
mutable int value;
|
||||
|
||||
mutable int64_t meleeCachedLast;
|
||||
@ -692,8 +695,12 @@ private:
|
||||
CCheckProxy anaffectedByMorale;
|
||||
static CSelector moraleSelector;
|
||||
CTotalsProxy moraleValue;
|
||||
static CSelector luckSelector;
|
||||
CTotalsProxy luckValue;
|
||||
static CSelector selfMoraleSelector;
|
||||
CCheckProxy selfMorale;
|
||||
static CSelector selfLuckSelector;
|
||||
CCheckProxy selfLuck;
|
||||
|
||||
public:
|
||||
//new bonusing node interface
|
||||
@ -726,6 +733,14 @@ public:
|
||||
|
||||
int MoraleVal() const; //range [-3, +3]
|
||||
int LuckVal() const; //range [-3, +3]
|
||||
/**
|
||||
Returns total value of all morale bonuses and sets bonusList as a pointer to the list of selected bonuses.
|
||||
@param bonusList is the out param it's list of all selected bonuses
|
||||
@return total value of all morale in the range [-3, +3] and 0 otherwise
|
||||
*/
|
||||
int MoraleValAndBonusList(TConstBonusListPtr & bonusList) const;
|
||||
int LuckValAndBonusList(TConstBonusListPtr & bonusList) const;
|
||||
|
||||
ui32 MaxHealth() const; //get max HP of stack with all modifiers
|
||||
bool isLiving() const; //non-undead, non-non living or alive
|
||||
virtual si32 magicResistance() const;
|
||||
@ -864,7 +879,10 @@ public:
|
||||
CSelector operator()(const T &valueToCompareAgainst) const
|
||||
{
|
||||
auto ptr2 = ptr; //We need a COPY because we don't want to reference this (might be outlived by lambda)
|
||||
return [ptr2, valueToCompareAgainst](const Bonus *bonus) { return bonus->*ptr2 == valueToCompareAgainst; };
|
||||
return [ptr2, valueToCompareAgainst](const Bonus *bonus)
|
||||
{
|
||||
return bonus->*ptr2 == valueToCompareAgainst;
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
@ -1112,11 +1130,11 @@ public:
|
||||
|
||||
namespace Selector
|
||||
{
|
||||
extern DLL_LINKAGE CSelectFieldEqual<Bonus::BonusType> type;
|
||||
extern DLL_LINKAGE CSelectFieldEqual<TBonusSubtype> subtype;
|
||||
extern DLL_LINKAGE CSelectFieldEqual<CAddInfo> info;
|
||||
extern DLL_LINKAGE CSelectFieldEqual<Bonus::BonusSource> sourceType;
|
||||
extern DLL_LINKAGE CSelectFieldEqual<Bonus::LimitEffect> effectRange;
|
||||
extern DLL_LINKAGE CSelectFieldEqual<Bonus::BonusType> & type();
|
||||
extern DLL_LINKAGE CSelectFieldEqual<TBonusSubtype> & subtype();
|
||||
extern DLL_LINKAGE CSelectFieldEqual<CAddInfo> & info();
|
||||
extern DLL_LINKAGE CSelectFieldEqual<Bonus::BonusSource> & sourceType();
|
||||
extern DLL_LINKAGE CSelectFieldEqual<Bonus::LimitEffect> & effectRange();
|
||||
extern DLL_LINKAGE CWillLastTurns turns;
|
||||
extern DLL_LINKAGE CWillLastDays days;
|
||||
|
||||
|
@ -1310,7 +1310,7 @@ DLL_LINKAGE void BattleTriggerEffect::applyGs(CGameState *gs)
|
||||
case Bonus::POISON:
|
||||
{
|
||||
auto b = st->getBonusLocalFirst(Selector::source(Bonus::SPELL_EFFECT, SpellID::POISON)
|
||||
.And(Selector::type(Bonus::STACK_HEALTH)));
|
||||
.And(Selector::type()(Bonus::STACK_HEALTH)));
|
||||
if (b)
|
||||
b->val = val;
|
||||
break;
|
||||
@ -1601,7 +1601,7 @@ DLL_LINKAGE void BattleSetStackProperty::applyGs(CGameState * gs)
|
||||
}
|
||||
case UNBIND:
|
||||
{
|
||||
stack->removeBonusesRecursive(Selector::type(Bonus::BIND_EFFECT));
|
||||
stack->removeBonusesRecursive(Selector::type()(Bonus::BIND_EFFECT));
|
||||
break;
|
||||
}
|
||||
case CLONED:
|
||||
|
@ -164,7 +164,7 @@ bool CBattleInfoCallback::battleHasWallPenalty(const IBonusBearer * shooter, Bat
|
||||
return false;
|
||||
|
||||
const std::string cachingStrNoWallPenalty = "type_NO_WALL_PENALTY";
|
||||
static const auto selectorNoWallPenalty = Selector::type(Bonus::NO_WALL_PENALTY);
|
||||
static const auto selectorNoWallPenalty = Selector::type()(Bonus::NO_WALL_PENALTY);
|
||||
|
||||
if(shooter->hasBonus(selectorNoWallPenalty, cachingStrNoWallPenalty))
|
||||
return false;
|
||||
@ -680,10 +680,10 @@ bool CBattleInfoCallback::battleCanShoot(const battle::Unit * attacker) const
|
||||
return false;
|
||||
|
||||
//forgetfulness
|
||||
TConstBonusListPtr forgetfulList = attacker->getBonuses(Selector::type(Bonus::FORGETFULL));
|
||||
TConstBonusListPtr forgetfulList = attacker->getBonuses(Selector::type()(Bonus::FORGETFULL));
|
||||
if (!forgetfulList->empty())
|
||||
{
|
||||
int forgetful = forgetfulList->valOfBonuses(Selector::type(Bonus::FORGETFULL));
|
||||
int forgetful = forgetfulList->valOfBonuses(Selector::type()(Bonus::FORGETFULL));
|
||||
|
||||
//advanced+ level
|
||||
if (forgetful > 1)
|
||||
@ -712,10 +712,10 @@ TDmgRange CBattleInfoCallback::calculateDmgRange(const BattleAttackInfo & info)
|
||||
{
|
||||
auto battleBonusValue = [&](const IBonusBearer * bearer, CSelector selector) -> int
|
||||
{
|
||||
auto noLimit = Selector::effectRange(Bonus::NO_LIMIT);
|
||||
auto noLimit = Selector::effectRange()(Bonus::NO_LIMIT);
|
||||
auto limitMatches = info.shooting
|
||||
? Selector::effectRange(Bonus::ONLY_DISTANCE_FIGHT)
|
||||
: Selector::effectRange(Bonus::ONLY_MELEE_FIGHT);
|
||||
? Selector::effectRange()(Bonus::ONLY_DISTANCE_FIGHT)
|
||||
: Selector::effectRange()(Bonus::ONLY_MELEE_FIGHT);
|
||||
|
||||
//any regular bonuses or just ones for melee/ranged
|
||||
return bearer->getBonuses(selector, noLimit.Or(limitMatches))->totalValue();
|
||||
@ -743,7 +743,7 @@ TDmgRange CBattleInfoCallback::calculateDmgRange(const BattleAttackInfo & info)
|
||||
}
|
||||
|
||||
const std::string cachingStrSiedgeWeapon = "type_SIEGE_WEAPON";
|
||||
static const auto selectorSiedgeWeapon = Selector::type(Bonus::SIEGE_WEAPON);
|
||||
static const auto selectorSiedgeWeapon = Selector::type()(Bonus::SIEGE_WEAPON);
|
||||
|
||||
if(attackerBonuses->hasBonus(selectorSiedgeWeapon, cachingStrSiedgeWeapon) && info.attacker->creatureIndex() != CreatureID::ARROW_TOWERS) //any siege weapon, but only ballista can attack (second condition - not arrow turret)
|
||||
{ //minDmg and maxDmg are multiplied by hero attack + 1
|
||||
@ -760,14 +760,14 @@ TDmgRange CBattleInfoCallback::calculateDmgRange(const BattleAttackInfo & info)
|
||||
|
||||
double attackDefenceDifference = 0.0;
|
||||
|
||||
double multAttackReduction = 1.0 - battleBonusValue(attackerBonuses, Selector::type(Bonus::GENERAL_ATTACK_REDUCTION)) / 100.0;
|
||||
double multAttackReduction = 1.0 - battleBonusValue(attackerBonuses, Selector::type()(Bonus::GENERAL_ATTACK_REDUCTION)) / 100.0;
|
||||
attackDefenceDifference += info.attacker->getAttack(info.shooting) * multAttackReduction;
|
||||
|
||||
double multDefenceReduction = 1.0 - battleBonusValue(attackerBonuses, Selector::type(Bonus::ENEMY_DEFENCE_REDUCTION)) / 100.0;
|
||||
double multDefenceReduction = 1.0 - battleBonusValue(attackerBonuses, Selector::type()(Bonus::ENEMY_DEFENCE_REDUCTION)) / 100.0;
|
||||
attackDefenceDifference -= info.defender->getDefence(info.shooting) * multDefenceReduction;
|
||||
|
||||
const std::string cachingStrSlayer = "type_SLAYER";
|
||||
static const auto selectorSlayer = Selector::type(Bonus::SLAYER);
|
||||
static const auto selectorSlayer = Selector::type()(Bonus::SLAYER);
|
||||
|
||||
//slayer handling //TODO: apply only ONLY_MELEE_FIGHT / DISTANCE_FIGHT?
|
||||
auto slayerEffects = attackerBonuses->getBonuses(selectorSlayer, cachingStrSlayer);
|
||||
@ -807,10 +807,10 @@ TDmgRange CBattleInfoCallback::calculateDmgRange(const BattleAttackInfo & info)
|
||||
}
|
||||
|
||||
const std::string cachingStrJousting = "type_JOUSTING";
|
||||
static const auto selectorJousting = Selector::type(Bonus::JOUSTING);
|
||||
static const auto selectorJousting = Selector::type()(Bonus::JOUSTING);
|
||||
|
||||
const std::string cachingStrChargeImmunity = "type_CHARGE_IMMUNITY";
|
||||
static const auto selectorChargeImmunity = Selector::type(Bonus::CHARGE_IMMUNITY);
|
||||
static const auto selectorChargeImmunity = Selector::type()(Bonus::CHARGE_IMMUNITY);
|
||||
|
||||
//applying jousting bonus
|
||||
if(info.chargedFields > 0 && attackerBonuses->hasBonus(selectorJousting, cachingStrJousting) && !defenderBonuses->hasBonus(selectorChargeImmunity, cachingStrChargeImmunity))
|
||||
@ -836,11 +836,11 @@ TDmgRange CBattleInfoCallback::calculateDmgRange(const BattleAttackInfo & info)
|
||||
//handling hate effect
|
||||
//assume that unit have only few HATE features and cache them all
|
||||
const std::string cachingStrHate = "type_HATE";
|
||||
static const auto selectorHate = Selector::type(Bonus::HATE);
|
||||
static const auto selectorHate = Selector::type()(Bonus::HATE);
|
||||
|
||||
auto allHateEffects = attackerBonuses->getBonuses(selectorHate, cachingStrHate);
|
||||
|
||||
additiveBonus += allHateEffects->valOfBonuses(Selector::subtype(info.defender->creatureIndex())) / 100.0;
|
||||
additiveBonus += allHateEffects->valOfBonuses(Selector::subtype()(info.defender->creatureIndex())) / 100.0;
|
||||
|
||||
const std::string cachingStrMeleeReduction = "type_GENERAL_DAMAGE_REDUCTIONs_0";
|
||||
static const auto selectorMeleeReduction = Selector::typeSubtype(Bonus::GENERAL_DAMAGE_REDUCTION, 0);
|
||||
@ -863,7 +863,7 @@ TDmgRange CBattleInfoCallback::calculateDmgRange(const BattleAttackInfo & info)
|
||||
//todo: set actual percentage in spell bonus configuration instead of just level; requires non trivial backward compatibility handling
|
||||
|
||||
//get list first, total value of 0 also counts
|
||||
TConstBonusListPtr forgetfulList = attackerBonuses->getBonuses(Selector::type(Bonus::FORGETFULL),"type_FORGETFULL");
|
||||
TConstBonusListPtr forgetfulList = attackerBonuses->getBonuses(Selector::type()(Bonus::FORGETFULL),"type_FORGETFULL");
|
||||
|
||||
if(!forgetfulList->empty())
|
||||
{
|
||||
@ -878,10 +878,10 @@ TDmgRange CBattleInfoCallback::calculateDmgRange(const BattleAttackInfo & info)
|
||||
}
|
||||
|
||||
const std::string cachingStrForcedMinDamage = "type_ALWAYS_MINIMUM_DAMAGE";
|
||||
static const auto selectorForcedMinDamage = Selector::type(Bonus::ALWAYS_MINIMUM_DAMAGE);
|
||||
static const auto selectorForcedMinDamage = Selector::type()(Bonus::ALWAYS_MINIMUM_DAMAGE);
|
||||
|
||||
const std::string cachingStrForcedMaxDamage = "type_ALWAYS_MAXIMUM_DAMAGE";
|
||||
static const auto selectorForcedMaxDamage = Selector::type(Bonus::ALWAYS_MAXIMUM_DAMAGE);
|
||||
static const auto selectorForcedMaxDamage = Selector::type()(Bonus::ALWAYS_MAXIMUM_DAMAGE);
|
||||
|
||||
TConstBonusListPtr curseEffects = attackerBonuses->getBonuses(selectorForcedMinDamage, cachingStrForcedMinDamage);
|
||||
TConstBonusListPtr blessEffects = attackerBonuses->getBonuses(selectorForcedMaxDamage, cachingStrForcedMaxDamage);
|
||||
@ -920,7 +920,7 @@ TDmgRange CBattleInfoCallback::calculateDmgRange(const BattleAttackInfo & info)
|
||||
else
|
||||
{
|
||||
const std::string cachingStrNoMeleePenalty = "type_NO_MELEE_PENALTY";
|
||||
static const auto selectorNoMeleePenalty = Selector::type(Bonus::NO_MELEE_PENALTY);
|
||||
static const auto selectorNoMeleePenalty = Selector::type()(Bonus::NO_MELEE_PENALTY);
|
||||
|
||||
if(info.attacker->isShooter() && !attackerBonuses->hasBonus(selectorNoMeleePenalty, cachingStrNoMeleePenalty))
|
||||
multBonus *= 0.5;
|
||||
@ -930,7 +930,7 @@ TDmgRange CBattleInfoCallback::calculateDmgRange(const BattleAttackInfo & info)
|
||||
if(info.attacker->creatureIndex() == CreatureID::PSYCHIC_ELEMENTAL)
|
||||
{
|
||||
const std::string cachingStrMindImmunity = "type_MIND_IMMUNITY";
|
||||
static const auto selectorMindImmunity = Selector::type(Bonus::MIND_IMMUNITY);
|
||||
static const auto selectorMindImmunity = Selector::type()(Bonus::MIND_IMMUNITY);
|
||||
|
||||
if(defenderBonuses->hasBonus(selectorMindImmunity, cachingStrMindImmunity))
|
||||
multBonus *= 0.5;
|
||||
@ -1596,7 +1596,7 @@ bool CBattleInfoCallback::battleHasDistancePenalty(const IBonusBearer * shooter,
|
||||
RETURN_IF_NOT_BATTLE(false);
|
||||
|
||||
const std::string cachingStrNoDistancePenalty = "type_NO_DISTANCE_PENALTY";
|
||||
static const auto selectorNoDistancePenalty = Selector::type(Bonus::NO_DISTANCE_PENALTY);
|
||||
static const auto selectorNoDistancePenalty = Selector::type()(Bonus::NO_DISTANCE_PENALTY);
|
||||
|
||||
if(shooter->hasBonus(selectorNoDistancePenalty, cachingStrNoDistancePenalty))
|
||||
return false;
|
||||
@ -1831,9 +1831,9 @@ SpellID CBattleInfoCallback::getRandomBeneficialSpell(CRandomGenerator & rand, c
|
||||
{
|
||||
auto kingMonster = getAliveEnemy([&](const CStack * stack) -> bool //look for enemy, non-shooting stack
|
||||
{
|
||||
const auto isKing = Selector::type(Bonus::KING1)
|
||||
.Or(Selector::type(Bonus::KING2))
|
||||
.Or(Selector::type(Bonus::KING3));
|
||||
const auto isKing = Selector::type()(Bonus::KING1)
|
||||
.Or(Selector::type()(Bonus::KING2))
|
||||
.Or(Selector::type()(Bonus::KING3));
|
||||
|
||||
return stack->hasBonus(isKing);
|
||||
});
|
||||
@ -1860,7 +1860,7 @@ SpellID CBattleInfoCallback::getRandomCastedSpell(CRandomGenerator & rand,const
|
||||
{
|
||||
RETURN_IF_NOT_BATTLE(SpellID::NONE);
|
||||
|
||||
TConstBonusListPtr bl = caster->getBonuses(Selector::type(Bonus::SPELLCASTER));
|
||||
TConstBonusListPtr bl = caster->getBonuses(Selector::type()(Bonus::SPELLCASTER));
|
||||
if (!bl->size())
|
||||
return SpellID::NONE;
|
||||
int totalWeight = 0;
|
||||
@ -1917,7 +1917,7 @@ si8 CBattleInfoCallback::battleMinSpellLevel(ui8 side) const
|
||||
if(!node)
|
||||
return 0;
|
||||
|
||||
auto b = node->getBonuses(Selector::type(Bonus::BLOCK_MAGIC_BELOW));
|
||||
auto b = node->getBonuses(Selector::type()(Bonus::BLOCK_MAGIC_BELOW));
|
||||
if(b->size())
|
||||
return b->totalValue();
|
||||
|
||||
@ -1936,7 +1936,7 @@ si8 CBattleInfoCallback::battleMaxSpellLevel(ui8 side) const
|
||||
return GameConstants::SPELL_LEVELS;
|
||||
|
||||
//We can't "just get value" - it'd be 0 if there are bonuses (and all would be blocked)
|
||||
auto b = node->getBonuses(Selector::type(Bonus::BLOCK_MAGIC_ABOVE));
|
||||
auto b = node->getBonuses(Selector::type()(Bonus::BLOCK_MAGIC_ABOVE));
|
||||
if(b->size())
|
||||
return b->totalValue();
|
||||
|
||||
|
@ -386,7 +386,7 @@ PlayerColor CBattleInfoEssentials::battleGetOwner(const battle::Unit * unit) con
|
||||
|
||||
PlayerColor initialOwner = getBattle()->getSidePlayer(unit->unitSide());
|
||||
|
||||
static CSelector selector = Selector::type(Bonus::HYPNOTIZED);
|
||||
static CSelector selector = Selector::type()(Bonus::HYPNOTIZED);
|
||||
static std::string cachingString = "type_103s-1";
|
||||
|
||||
if(unit->hasBonus(selector, cachingString))
|
||||
|
@ -89,8 +89,8 @@ void CAmmo::serializeJson(JsonSerializeFormat & handler)
|
||||
|
||||
///CShots
|
||||
CShots::CShots(const battle::Unit * Owner)
|
||||
: CAmmo(Owner, Selector::type(Bonus::SHOTS)),
|
||||
shooter(Owner, Selector::type(Bonus::SHOOTER))
|
||||
: CAmmo(Owner, Selector::type()(Bonus::SHOTS)),
|
||||
shooter(Owner, Selector::type()(Bonus::SHOOTER))
|
||||
{
|
||||
}
|
||||
|
||||
@ -128,7 +128,7 @@ int32_t CShots::total() const
|
||||
|
||||
///CCasts
|
||||
CCasts::CCasts(const battle::Unit * Owner):
|
||||
CAmmo(Owner, Selector::type(Bonus::CASTS))
|
||||
CAmmo(Owner, Selector::type()(Bonus::CASTS))
|
||||
{
|
||||
}
|
||||
|
||||
@ -145,10 +145,10 @@ CCasts & CCasts::operator=(const CCasts & other)
|
||||
|
||||
///CRetaliations
|
||||
CRetaliations::CRetaliations(const battle::Unit * Owner)
|
||||
: CAmmo(Owner, Selector::type(Bonus::ADDITIONAL_RETALIATION)),
|
||||
: CAmmo(Owner, Selector::type()(Bonus::ADDITIONAL_RETALIATION)),
|
||||
totalCache(0),
|
||||
noRetaliation(Owner, Selector::type(Bonus::SIEGE_WEAPON).Or(Selector::type(Bonus::HYPNOTIZED)).Or(Selector::type(Bonus::NO_RETALIATION))),
|
||||
unlimited(Owner, Selector::type(Bonus::UNLIMITED_RETALIATIONS))
|
||||
noRetaliation(Owner, Selector::type()(Bonus::SIEGE_WEAPON).Or(Selector::type()(Bonus::HYPNOTIZED)).Or(Selector::type()(Bonus::NO_RETALIATION))),
|
||||
unlimited(Owner, Selector::type()(Bonus::UNLIMITED_RETALIATIONS))
|
||||
{
|
||||
}
|
||||
|
||||
@ -388,13 +388,13 @@ CUnitState::CUnitState()
|
||||
counterAttacks(this),
|
||||
health(this),
|
||||
shots(this),
|
||||
totalAttacks(this, Selector::type(Bonus::ADDITIONAL_ATTACK), 1),
|
||||
totalAttacks(this, Selector::type()(Bonus::ADDITIONAL_ATTACK), 1),
|
||||
minDamage(this, Selector::typeSubtype(Bonus::CREATURE_DAMAGE, 0).Or(Selector::typeSubtype(Bonus::CREATURE_DAMAGE, 1)), 0),
|
||||
maxDamage(this, Selector::typeSubtype(Bonus::CREATURE_DAMAGE, 0).Or(Selector::typeSubtype(Bonus::CREATURE_DAMAGE, 2)), 0),
|
||||
attack(this, Selector::typeSubtype(Bonus::PRIMARY_SKILL, PrimarySkill::ATTACK), 0),
|
||||
defence(this, Selector::typeSubtype(Bonus::PRIMARY_SKILL, PrimarySkill::DEFENSE), 0),
|
||||
inFrenzy(this, Selector::type(Bonus::IN_FRENZY)),
|
||||
cloneLifetimeMarker(this, Selector::type(Bonus::NONE).And(Selector::source(Bonus::SPELL_EFFECT, SpellID::CLONE))),
|
||||
inFrenzy(this, Selector::type()(Bonus::IN_FRENZY)),
|
||||
cloneLifetimeMarker(this, Selector::type()(Bonus::NONE).And(Selector::source(Bonus::SPELL_EFFECT, SpellID::CLONE))),
|
||||
cloneID(-1),
|
||||
position()
|
||||
{
|
||||
@ -618,12 +618,12 @@ void CUnitState::setPosition(BattleHex hex)
|
||||
|
||||
int32_t CUnitState::getInitiative(int turn) const
|
||||
{
|
||||
return valOfBonuses(Selector::type(Bonus::STACKS_SPEED).And(Selector::turns(turn)));
|
||||
return valOfBonuses(Selector::type()(Bonus::STACKS_SPEED).And(Selector::turns(turn)));
|
||||
}
|
||||
|
||||
bool CUnitState::canMove(int turn) const
|
||||
{
|
||||
return alive() && !hasBonus(Selector::type(Bonus::NOT_ACTIVE).And(Selector::turns(turn))); //eg. Ammo Cart or blinded creature
|
||||
return alive() && !hasBonus(Selector::type()(Bonus::NOT_ACTIVE).And(Selector::turns(turn))); //eg. Ammo Cart or blinded creature
|
||||
}
|
||||
|
||||
bool CUnitState::defended(int turn) const
|
||||
|
@ -37,7 +37,7 @@ void CArmedInstance::randomizeArmy(int type)
|
||||
}
|
||||
|
||||
// Take Angelic Alliance troop-mixing freedom of non-evil units into account.
|
||||
CSelector CArmedInstance::nonEvilAlignmentMixSelector = Selector::type(Bonus::NONEVIL_ALIGNMENT_MIX);
|
||||
CSelector CArmedInstance::nonEvilAlignmentMixSelector = Selector::type()(Bonus::NONEVIL_ALIGNMENT_MIX);
|
||||
|
||||
CArmedInstance::CArmedInstance()
|
||||
:nonEvilAlignmentMix(this, nonEvilAlignmentMixSelector)
|
||||
@ -50,7 +50,7 @@ void CArmedInstance::updateMoraleBonusFromArmy()
|
||||
if(!validTypes(false)) //object not randomized, don't bother
|
||||
return;
|
||||
|
||||
auto b = getExportedBonusList().getFirst(Selector::sourceType(Bonus::ARMY).And(Selector::type(Bonus::MORALE)));
|
||||
auto b = getExportedBonusList().getFirst(Selector::sourceType()(Bonus::ARMY).And(Selector::type()(Bonus::MORALE)));
|
||||
if(!b)
|
||||
{
|
||||
b = std::make_shared<Bonus>(Bonus::PERMANENT, Bonus::MORALE, Bonus::ARMY, 0, -1);
|
||||
@ -62,7 +62,7 @@ void CArmedInstance::updateMoraleBonusFromArmy()
|
||||
bool hasUndead = false;
|
||||
|
||||
const std::string undeadCacheKey = "type_UNDEAD";
|
||||
static const CSelector undeadSelector = Selector::type(Bonus::UNDEAD);
|
||||
static const CSelector undeadSelector = Selector::type()(Bonus::UNDEAD);
|
||||
|
||||
for(auto slot : Slots())
|
||||
{
|
||||
|
@ -56,7 +56,7 @@ static int lowestSpeed(const CGHeroInstance * chi)
|
||||
auto i = chi->Slots().begin();
|
||||
//TODO? should speed modifiers (eg from artifacts) affect hero movement?
|
||||
|
||||
static const CSelector selectorSTACKS_SPEED = Selector::type(Bonus::STACKS_SPEED);
|
||||
static const CSelector selectorSTACKS_SPEED = Selector::type()(Bonus::STACKS_SPEED);
|
||||
static const std::string keySTACKS_SPEED = "type_"+std::to_string((si32)Bonus::STACKS_SPEED);
|
||||
|
||||
int ret = (i++)->second->valOfBonuses(selectorSTACKS_SPEED, keySTACKS_SPEED);
|
||||
@ -289,7 +289,7 @@ void CGHeroInstance::initHero(CRandomGenerator & rand)
|
||||
|
||||
if(portrait < 0 || portrait == 255)
|
||||
portrait = type->imageIndex;
|
||||
if(!hasBonus(Selector::sourceType(Bonus::HERO_BASE_SKILL)))
|
||||
if(!hasBonus(Selector::sourceType()(Bonus::HERO_BASE_SKILL)))
|
||||
{
|
||||
for(int g=0; g<GameConstants::PRIMARY_SKILLS; ++g)
|
||||
{
|
||||
@ -534,7 +534,7 @@ void CGHeroInstance::initObj(CRandomGenerator & rand)
|
||||
|
||||
void CGHeroInstance::recreateSecondarySkillsBonuses()
|
||||
{
|
||||
auto secondarySkillsBonuses = getBonuses(Selector::sourceType(Bonus::SECONDARY_SKILL));
|
||||
auto secondarySkillsBonuses = getBonuses(Selector::sourceType()(Bonus::SECONDARY_SKILL));
|
||||
for(auto bonus : *secondarySkillsBonuses)
|
||||
removeBonus(bonus);
|
||||
|
||||
@ -816,7 +816,7 @@ CStackBasicDescriptor CGHeroInstance::calculateNecromancy (const BattleResult &b
|
||||
// figure out what to raise - pick strongest creature meeting requirements
|
||||
CreatureID creatureTypeRaised = CreatureID::SKELETON;
|
||||
int requiredCasualtyLevel = 1;
|
||||
TConstBonusListPtr improvedNecromancy = getBonuses(Selector::type(Bonus::IMPROVED_NECROMANCY));
|
||||
TConstBonusListPtr improvedNecromancy = getBonuses(Selector::type()(Bonus::IMPROVED_NECROMANCY));
|
||||
if(!improvedNecromancy->empty())
|
||||
{
|
||||
auto getCreatureID = [necromancyLevel](std::shared_ptr<Bonus> bonus) -> CreatureID
|
||||
@ -988,7 +988,7 @@ int CGHeroInstance::getSpellCost(const CSpell * sp) const
|
||||
void CGHeroInstance::pushPrimSkill( PrimarySkill::PrimarySkill which, int val )
|
||||
{
|
||||
assert(!hasBonus(Selector::typeSubtype(Bonus::PRIMARY_SKILL, which)
|
||||
.And(Selector::sourceType(Bonus::HERO_BASE_SKILL))));
|
||||
.And(Selector::sourceType()(Bonus::HERO_BASE_SKILL))));
|
||||
addNewBonus(std::make_shared<Bonus>(Bonus::PERMANENT, Bonus::PRIMARY_SKILL, Bonus::HERO_BASE_SKILL, val, id.getNum(), which));
|
||||
}
|
||||
|
||||
@ -1257,9 +1257,9 @@ void CGHeroInstance::setPrimarySkill(PrimarySkill::PrimarySkill primarySkill, si
|
||||
{
|
||||
if(primarySkill < PrimarySkill::EXPERIENCE)
|
||||
{
|
||||
auto skill = getBonusLocalFirst(Selector::type(Bonus::PRIMARY_SKILL)
|
||||
.And(Selector::subtype(primarySkill))
|
||||
.And(Selector::sourceType(Bonus::HERO_BASE_SKILL)));
|
||||
auto skill = getBonusLocalFirst(Selector::type()(Bonus::PRIMARY_SKILL)
|
||||
.And(Selector::subtype()(primarySkill))
|
||||
.And(Selector::sourceType()(Bonus::HERO_BASE_SKILL)));
|
||||
assert(skill);
|
||||
|
||||
if(abs)
|
||||
@ -1427,7 +1427,7 @@ void CGHeroInstance::serializeCommonOptions(JsonSerializeFormat & handler)
|
||||
//primary skills
|
||||
if(handler.saving)
|
||||
{
|
||||
const bool haveSkills = hasBonus(Selector::type(Bonus::PRIMARY_SKILL).And(Selector::sourceType(Bonus::HERO_BASE_SKILL)));
|
||||
const bool haveSkills = hasBonus(Selector::type()(Bonus::PRIMARY_SKILL).And(Selector::sourceType()(Bonus::HERO_BASE_SKILL)));
|
||||
|
||||
if(haveSkills)
|
||||
{
|
||||
@ -1435,7 +1435,7 @@ void CGHeroInstance::serializeCommonOptions(JsonSerializeFormat & handler)
|
||||
|
||||
for(int i = 0; i < GameConstants::PRIMARY_SKILLS; ++i)
|
||||
{
|
||||
int value = valOfBonuses(Selector::typeSubtype(Bonus::PRIMARY_SKILL, i).And(Selector::sourceType(Bonus::HERO_BASE_SKILL)));
|
||||
int value = valOfBonuses(Selector::typeSubtype(Bonus::PRIMARY_SKILL, i).And(Selector::sourceType()(Bonus::HERO_BASE_SKILL)));
|
||||
|
||||
handler.serializeInt(PrimarySkill::names[i], value, 0);
|
||||
}
|
||||
|
@ -562,12 +562,12 @@ GrowthInfo CGTownInstance::getGrowthInfo(int level) const
|
||||
ret.entries.push_back(GrowthInfo::Entry(VLC->generaltexth->allTexts[591], dwellingBonus));// \nExternal dwellings %+d
|
||||
|
||||
//other *-of-legion-like bonuses (%d to growth cumulative with grail)
|
||||
TConstBonusListPtr bonuses = getBonuses(Selector::type(Bonus::CREATURE_GROWTH).And(Selector::subtype(level)));
|
||||
TConstBonusListPtr bonuses = getBonuses(Selector::type()(Bonus::CREATURE_GROWTH).And(Selector::subtype()(level)));
|
||||
for(const auto & b : *bonuses)
|
||||
ret.entries.push_back(GrowthInfo::Entry(b->val, b->Description()));
|
||||
|
||||
//statue-of-legion-like bonus: % to base+castle
|
||||
TConstBonusListPtr bonuses2 = getBonuses(Selector::type(Bonus::CREATURE_GROWTH_PERCENT));
|
||||
TConstBonusListPtr bonuses2 = getBonuses(Selector::type()(Bonus::CREATURE_GROWTH_PERCENT));
|
||||
for(const auto & b : *bonuses2)
|
||||
ret.entries.push_back(GrowthInfo::Entry(b->val * (base + castleBonus) / 100, b->Description()));
|
||||
|
||||
@ -1166,7 +1166,7 @@ void CGTownInstance::deserializationFix()
|
||||
|
||||
void CGTownInstance::updateMoraleBonusFromArmy()
|
||||
{
|
||||
auto b = getExportedBonusList().getFirst(Selector::sourceType(Bonus::ARMY).And(Selector::type(Bonus::MORALE)));
|
||||
auto b = getExportedBonusList().getFirst(Selector::sourceType()(Bonus::ARMY).And(Selector::type()(Bonus::MORALE)));
|
||||
if(!b)
|
||||
{
|
||||
b = std::make_shared<Bonus>(Bonus::PERMANENT, Bonus::MORALE, Bonus::ARMY, 0, -1);
|
||||
@ -1187,7 +1187,7 @@ void CGTownInstance::recreateBuildingsBonuses()
|
||||
static TPropagatorPtr playerProp(new CPropagatorNodeType(PLAYER));
|
||||
|
||||
BonusList bl;
|
||||
getExportedBonusList().getBonuses(bl, Selector::sourceType(Bonus::TOWN_STRUCTURE));
|
||||
getExportedBonusList().getBonuses(bl, Selector::sourceType()(Bonus::TOWN_STRUCTURE));
|
||||
for(auto b : bl)
|
||||
removeBonus(b);
|
||||
|
||||
|
@ -1422,7 +1422,7 @@ void CGArtifact::serializeJsonOptions(JsonSerializeFormat& handler)
|
||||
|
||||
if(handler.saving && ID == Obj::SPELL_SCROLL)
|
||||
{
|
||||
const std::shared_ptr<Bonus> b = storedArtifact->getBonusLocalFirst(Selector::type(Bonus::SPELL));
|
||||
const std::shared_ptr<Bonus> b = storedArtifact->getBonusLocalFirst(Selector::type()(Bonus::SPELL));
|
||||
SpellID spellId(b->subtype);
|
||||
|
||||
handler.serializeId("spell", spellId, SpellID::NONE);
|
||||
|
@ -1712,8 +1712,8 @@ CGObjectInstance * CMapLoaderH3M::readHero(ObjectInstanceID idToBeGiven, const i
|
||||
bool hasCustomPrimSkills = reader.readBool();
|
||||
if(hasCustomPrimSkills)
|
||||
{
|
||||
auto ps = nhi->getAllBonuses(Selector::type(Bonus::PRIMARY_SKILL)
|
||||
.And(Selector::sourceType(Bonus::HERO_BASE_SKILL)), nullptr);
|
||||
auto ps = nhi->getAllBonuses(Selector::type()(Bonus::PRIMARY_SKILL)
|
||||
.And(Selector::sourceType()(Bonus::HERO_BASE_SKILL)), nullptr);
|
||||
if(ps->size())
|
||||
{
|
||||
logGlobal->warn("Hero %s subID=%d has set primary skills twice (in map properties and on adventure map instance). Using the latter set...", nhi->name, nhi->subID);
|
||||
|
@ -437,7 +437,7 @@ int64_t CSpell::adjustRawDamage(const spells::Caster * caster, const battle::Uni
|
||||
}
|
||||
});
|
||||
|
||||
CSelector selector = Selector::type(Bonus::SPELL_DAMAGE_REDUCTION).And(Selector::subtype(-1));
|
||||
CSelector selector = Selector::type()(Bonus::SPELL_DAMAGE_REDUCTION).And(Selector::subtype()(-1));
|
||||
|
||||
//general spell dmg reduction
|
||||
if(bearer->hasBonus(selector))
|
||||
|
@ -302,7 +302,7 @@ void BattleCast::cast(const SpellCastEnvironment * env)
|
||||
if(tryMagicMirror)
|
||||
{
|
||||
const std::string magicMirrorCacheStr = "type_MAGIC_MIRROR";
|
||||
static const auto magicMirrorSelector = Selector::type(Bonus::MAGIC_MIRROR);
|
||||
static const auto magicMirrorSelector = Selector::type()(Bonus::MAGIC_MIRROR);
|
||||
|
||||
auto rangeGen = env->getRandomGenerator().getInt64Range(0, 99);
|
||||
|
||||
@ -534,7 +534,7 @@ bool BaseMechanics::adaptProblem(ESpellCastProblem::ESpellCastProblem source, Pr
|
||||
return adaptGenericProblem(target);
|
||||
|
||||
//Recanter's Cloak or similar effect. Try to retrieve bonus
|
||||
const auto b = hero->getBonusLocalFirst(Selector::type(Bonus::BLOCK_MAGIC_ABOVE));
|
||||
const auto b = hero->getBonusLocalFirst(Selector::type()(Bonus::BLOCK_MAGIC_ABOVE));
|
||||
//TODO what about other values and non-artifact sources?
|
||||
if(b && b->val == 2 && b->source == Bonus::ARTIFACT)
|
||||
{
|
||||
|
@ -75,7 +75,7 @@ public:
|
||||
protected:
|
||||
bool check(const Mechanics * m, const battle::Unit * target) const override
|
||||
{
|
||||
return target->hasBonus(Selector::type(type));
|
||||
return target->hasBonus(Selector::type()(type));
|
||||
}
|
||||
|
||||
private:
|
||||
@ -115,7 +115,7 @@ protected:
|
||||
std::stringstream cachingStr;
|
||||
cachingStr << "type_" << Bonus::LEVEL_SPELL_IMMUNITY << "addInfo_1";
|
||||
|
||||
TConstBonusListPtr levelImmunities = target->getBonuses(Selector::type(Bonus::LEVEL_SPELL_IMMUNITY).And(Selector::info(1)), cachingStr.str());
|
||||
TConstBonusListPtr levelImmunities = target->getBonuses(Selector::type()(Bonus::LEVEL_SPELL_IMMUNITY).And(Selector::info()(1)), cachingStr.str());
|
||||
|
||||
return levelImmunities->size() == 0 ||
|
||||
levelImmunities->totalValue() < m->getSpellLevel() ||
|
||||
@ -190,7 +190,7 @@ public:
|
||||
protected:
|
||||
bool check(const Mechanics * m, const battle::Unit * target) const override
|
||||
{
|
||||
TConstBonusListPtr levelImmunities = target->getBonuses(Selector::type(Bonus::LEVEL_SPELL_IMMUNITY));
|
||||
TConstBonusListPtr levelImmunities = target->getBonuses(Selector::type()(Bonus::LEVEL_SPELL_IMMUNITY));
|
||||
return levelImmunities->size() == 0 ||
|
||||
levelImmunities->totalValue() < m->getSpellLevel() ||
|
||||
m->getSpellLevel() <= 0;
|
||||
@ -263,7 +263,7 @@ class ReceptiveFeatureCondition : public TargetConditionItemBase
|
||||
public:
|
||||
ReceptiveFeatureCondition()
|
||||
{
|
||||
selector = Selector::type(Bonus::RECEPTIVE);
|
||||
selector = Selector::type()(Bonus::RECEPTIVE);
|
||||
cachingString = "type_RECEPTIVE";
|
||||
}
|
||||
|
||||
|
@ -120,7 +120,7 @@ void Timed::describeEffect(std::vector<MetaString> & log, const Mechanics * m, c
|
||||
{
|
||||
if(bonus.val < 0)
|
||||
{
|
||||
BonusList unitHealth = *target->getBonuses(Selector::type(Bonus::STACK_HEALTH));
|
||||
BonusList unitHealth = *target->getBonuses(Selector::type()(Bonus::STACK_HEALTH));
|
||||
|
||||
auto oldHealth = unitHealth.totalValue();
|
||||
unitHealth.push_back(std::make_shared<Bonus>(bonus));
|
||||
|
@ -1016,7 +1016,7 @@ void CGameHandler::makeAttack(const CStack * attacker, const CStack * defender,
|
||||
applyBattleEffects(bat, attackerState, fireShield, stack, distance, true);
|
||||
}
|
||||
|
||||
std::shared_ptr<const Bonus> bonus = attacker->getBonusLocalFirst(Selector::type(Bonus::SPELL_LIKE_ATTACK));
|
||||
std::shared_ptr<const Bonus> bonus = attacker->getBonusLocalFirst(Selector::type()(Bonus::SPELL_LIKE_ATTACK));
|
||||
if(bonus && ranged) //TODO: make it work in melee?
|
||||
{
|
||||
//this is need for displaying hit animation
|
||||
@ -1883,7 +1883,7 @@ void CGameHandler::newTurn()
|
||||
{
|
||||
if (getPlayerStatus(player.first) == EPlayerStatus::INGAME &&
|
||||
getPlayerRelations(player.first, t->tempOwner) == PlayerRelations::ENEMIES)
|
||||
changeFogOfWar(t->visitablePos(), t->getBonusLocalFirst(Selector::type(Bonus::DARKNESS))->val, player.first, true);
|
||||
changeFogOfWar(t->visitablePos(), t->getBonusLocalFirst(Selector::type()(Bonus::DARKNESS))->val, player.first, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -4463,7 +4463,7 @@ bool CGameHandler::makeBattleAction(BattleAction &ba)
|
||||
const CStack * summoner = gs->curB->battleGetStackByID(ba.stackNumber);
|
||||
const CStack * destStack = gs->curB->battleGetStackByPos(target.at(0).hexValue, false);
|
||||
|
||||
CreatureID summonedType(summoner->getBonusLocalFirst(Selector::type(Bonus::DAEMON_SUMMONING))->subtype);//in case summoner can summon more than one type of monsters... scream!
|
||||
CreatureID summonedType(summoner->getBonusLocalFirst(Selector::type()(Bonus::DAEMON_SUMMONING))->subtype);//in case summoner can summon more than one type of monsters... scream!
|
||||
|
||||
ui64 risedHp = summoner->getCount() * summoner->valOfBonuses(Bonus::DAEMON_SUMMONING, summonedType.toEnum());
|
||||
ui64 targetHealth = destStack->getCreature()->MaxHealth() * destStack->baseAmount;
|
||||
@ -4508,7 +4508,7 @@ bool CGameHandler::makeBattleAction(BattleAction &ba)
|
||||
const CStack * stack = gs->curB->battleGetStackByID(ba.stackNumber);
|
||||
SpellID spellID = SpellID(ba.actionSubtype);
|
||||
|
||||
std::shared_ptr<const Bonus> randSpellcaster = stack->getBonusLocalFirst(Selector::type(Bonus::RANDOM_SPELLCASTER));
|
||||
std::shared_ptr<const Bonus> randSpellcaster = stack->getBonusLocalFirst(Selector::type()(Bonus::RANDOM_SPELLCASTER));
|
||||
std::shared_ptr<const Bonus> spellcaster = stack->getBonusLocalFirst(Selector::typeSubtype(Bonus::SPELLCASTER, spellID));
|
||||
|
||||
//TODO special bonus for genies ability
|
||||
@ -4669,7 +4669,7 @@ bool CGameHandler::makeCustomAction(BattleAction & ba)
|
||||
|
||||
void CGameHandler::stackEnchantedTrigger(const CStack * st)
|
||||
{
|
||||
auto bl = *(st->getBonuses(Selector::type(Bonus::ENCHANTED)));
|
||||
auto bl = *(st->getBonuses(Selector::type()(Bonus::ENCHANTED)));
|
||||
for(auto b : bl)
|
||||
{
|
||||
const CSpell * sp = SpellID(b->subtype).toSpell();
|
||||
@ -4708,10 +4708,10 @@ void CGameHandler::stackTurnTrigger(const CStack *st)
|
||||
if (st->alive())
|
||||
{
|
||||
//unbind
|
||||
if (st->hasBonus(Selector::type(Bonus::BIND_EFFECT)))
|
||||
if (st->hasBonus(Selector::type()(Bonus::BIND_EFFECT)))
|
||||
{
|
||||
bool unbind = true;
|
||||
BonusList bl = *(st->getBonuses(Selector::type(Bonus::BIND_EFFECT)));
|
||||
BonusList bl = *(st->getBonuses(Selector::type()(Bonus::BIND_EFFECT)));
|
||||
auto adjacent = gs->curB->battleAdjacentUnits(st);
|
||||
|
||||
for (auto b : bl)
|
||||
@ -4754,7 +4754,7 @@ void CGameHandler::stackTurnTrigger(const CStack *st)
|
||||
|
||||
if (st->hasBonusOfType(Bonus::POISON))
|
||||
{
|
||||
std::shared_ptr<const Bonus> b = st->getBonusLocalFirst(Selector::source(Bonus::SPELL_EFFECT, SpellID::POISON).And(Selector::type(Bonus::STACK_HEALTH)));
|
||||
std::shared_ptr<const Bonus> b = st->getBonusLocalFirst(Selector::source(Bonus::SPELL_EFFECT, SpellID::POISON).And(Selector::type()(Bonus::STACK_HEALTH)));
|
||||
if (b) //TODO: what if not?...
|
||||
{
|
||||
bte.val = std::max (b->val - 10, -(st->valOfBonuses(Bonus::POISON)));
|
||||
@ -4802,7 +4802,7 @@ void CGameHandler::stackTurnTrigger(const CStack *st)
|
||||
}
|
||||
}
|
||||
}
|
||||
BonusList bl = *(st->getBonuses(Selector::type(Bonus::ENCHANTER)));
|
||||
BonusList bl = *(st->getBonuses(Selector::type()(Bonus::ENCHANTER)));
|
||||
int side = gs->curB->whatSide(st->owner);
|
||||
if(st->canCast() && gs->curB->battleGetEnchanterCounter(side) == 0)
|
||||
{
|
||||
@ -5428,7 +5428,7 @@ void CGameHandler::attackCasting(bool ranged, Bonus::BonusType attackMode, const
|
||||
if(attacker->hasBonusOfType(attackMode))
|
||||
{
|
||||
std::set<SpellID> spellsToCast;
|
||||
TConstBonusListPtr spells = attacker->getBonuses(Selector::type(attackMode));
|
||||
TConstBonusListPtr spells = attacker->getBonuses(Selector::type()(attackMode));
|
||||
for(const auto & sf : *spells)
|
||||
{
|
||||
spellsToCast.insert(SpellID(sf->subtype));
|
||||
@ -5538,7 +5538,7 @@ void CGameHandler::handleAfterAttackCasting(bool ranged, const CStack * attacker
|
||||
return;
|
||||
|
||||
int64_t acidDamage = 0;
|
||||
TConstBonusListPtr acidBreath = attacker->getBonuses(Selector::type(Bonus::ACID_BREATH));
|
||||
TConstBonusListPtr acidBreath = attacker->getBonuses(Selector::type()(Bonus::ACID_BREATH));
|
||||
for(const auto & b : *acidBreath)
|
||||
{
|
||||
if(b->additionalInfo[0] > getRandomGenerator().nextInt(99))
|
||||
@ -5569,7 +5569,7 @@ void CGameHandler::handleAfterAttackCasting(bool ranged, const CStack * attacker
|
||||
if(getRandomGenerator().getDoubleRange(0, 1)() > chanceToTrigger)
|
||||
return;
|
||||
|
||||
int bonusAdditionalInfo = attacker->getBonus(Selector::type(Bonus::TRANSMUTATION))->additionalInfo[0];
|
||||
int bonusAdditionalInfo = attacker->getBonus(Selector::type()(Bonus::TRANSMUTATION))->additionalInfo[0];
|
||||
|
||||
if(defender->getCreature()->idNumber == bonusAdditionalInfo ||
|
||||
(bonusAdditionalInfo == CAddInfo::NONE && defender->getCreature()->idNumber == attacker->getCreature()->idNumber))
|
||||
@ -5611,13 +5611,13 @@ void CGameHandler::handleAfterAttackCasting(bool ranged, const CStack * attacker
|
||||
if(attacker->hasBonusOfType(Bonus::DESTRUCTION, 0)) //killing by percentage
|
||||
{
|
||||
chanceToTrigger = attacker->valOfBonuses(Bonus::DESTRUCTION, 0) / 100.0f;
|
||||
int percentageToDie = attacker->getBonus(Selector::type(Bonus::DESTRUCTION).And(Selector::subtype(0)))->additionalInfo[0];
|
||||
int percentageToDie = attacker->getBonus(Selector::type()(Bonus::DESTRUCTION).And(Selector::subtype()(0)))->additionalInfo[0];
|
||||
amountToDie = static_cast<int>(defender->getCount() * percentageToDie * 0.01f);
|
||||
}
|
||||
else if(attacker->hasBonusOfType(Bonus::DESTRUCTION, 1)) //killing by count
|
||||
{
|
||||
chanceToTrigger = attacker->valOfBonuses(Bonus::DESTRUCTION, 1) / 100.0f;
|
||||
amountToDie = attacker->getBonus(Selector::type(Bonus::DESTRUCTION).And(Selector::subtype(1)))->additionalInfo[0];
|
||||
amountToDie = attacker->getBonus(Selector::type()(Bonus::DESTRUCTION).And(Selector::subtype()(1)))->additionalInfo[0];
|
||||
}
|
||||
|
||||
vstd::amin(chanceToTrigger, 1); //cap trigger chance at 100%
|
||||
@ -5932,7 +5932,7 @@ void CGameHandler::runBattle()
|
||||
{
|
||||
if (stack->hasBonusOfType(Bonus::SUMMON_GUARDIANS))
|
||||
{
|
||||
std::shared_ptr<const Bonus> summonInfo = stack->getBonus(Selector::type(Bonus::SUMMON_GUARDIANS));
|
||||
std::shared_ptr<const Bonus> summonInfo = stack->getBonus(Selector::type()(Bonus::SUMMON_GUARDIANS));
|
||||
auto accessibility = getAccesibility();
|
||||
CreatureID creatureData = CreatureID(summonInfo->subtype);
|
||||
std::vector<BattleHex> targetHexes;
|
||||
@ -5977,7 +5977,7 @@ void CGameHandler::runBattle()
|
||||
auto h = gs->curB->battleGetFightingHero(i);
|
||||
if (h)
|
||||
{
|
||||
TConstBonusListPtr bl = h->getBonuses(Selector::type(Bonus::OPENING_BATTLE_SPELL));
|
||||
TConstBonusListPtr bl = h->getBonuses(Selector::type()(Bonus::OPENING_BATTLE_SPELL));
|
||||
|
||||
for (auto b : *bl)
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user