mirror of
https://github.com/vcmi/vcmi.git
synced 2024-12-24 22:14:36 +02:00
hacks to optimize a few bonus requests
This commit is contained in:
parent
cc75b859d4
commit
d782ee39df
@ -152,6 +152,120 @@ const BonusList * CBonusProxy::operator->() const
|
||||
return get().get();
|
||||
}
|
||||
|
||||
CTotalsProxy::CTotalsProxy(const IBonusBearer * Target, CSelector Selector, int InitialValue)
|
||||
: target(Target),
|
||||
selector(Selector),
|
||||
initialValue(InitialValue),
|
||||
meleeCachedLast(0),
|
||||
meleeValue(0),
|
||||
rangedCachedLast(0),
|
||||
rangedValue(0),
|
||||
value(0),
|
||||
cachedLast(0)
|
||||
{
|
||||
}
|
||||
|
||||
CTotalsProxy::CTotalsProxy(const CTotalsProxy & other)
|
||||
: target(other.target),
|
||||
selector(other.selector),
|
||||
initialValue(other.initialValue),
|
||||
meleeCachedLast(other.meleeCachedLast),
|
||||
meleeValue(other.meleeValue),
|
||||
rangedCachedLast(other.rangedCachedLast),
|
||||
rangedValue(other.rangedValue)
|
||||
{
|
||||
}
|
||||
|
||||
CTotalsProxy & CTotalsProxy::operator=(const CTotalsProxy & other)
|
||||
{
|
||||
initialValue = other.initialValue;
|
||||
meleeCachedLast = other.meleeCachedLast;
|
||||
meleeValue = other.meleeValue;
|
||||
rangedCachedLast = other.rangedCachedLast;
|
||||
rangedValue = other.rangedValue;
|
||||
value = other.value;
|
||||
cachedLast = other.cachedLast;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
int CTotalsProxy::getValue() const
|
||||
{
|
||||
const auto treeVersion = target->getTreeVersion();
|
||||
|
||||
if(treeVersion != cachedLast)
|
||||
{
|
||||
auto bonuses = target->getBonuses(selector);
|
||||
|
||||
value = initialValue + bonuses->totalValue();
|
||||
cachedLast = treeVersion;
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
int CTotalsProxy::getMeleeValue() const
|
||||
{
|
||||
static const auto limit = Selector::effectRange(Bonus::NO_LIMIT).Or(Selector::effectRange(Bonus::ONLY_MELEE_FIGHT));
|
||||
|
||||
const auto treeVersion = target->getTreeVersion();
|
||||
|
||||
if(treeVersion != meleeCachedLast)
|
||||
{
|
||||
auto bonuses = target->getBonuses(selector, limit);
|
||||
meleeValue = initialValue + bonuses->totalValue();
|
||||
meleeCachedLast = treeVersion;
|
||||
}
|
||||
|
||||
return meleeValue;
|
||||
}
|
||||
|
||||
int CTotalsProxy::getRangedValue() const
|
||||
{
|
||||
static const auto limit = Selector::effectRange(Bonus::NO_LIMIT).Or(Selector::effectRange(Bonus::ONLY_DISTANCE_FIGHT));
|
||||
|
||||
const auto treeVersion = target->getTreeVersion();
|
||||
|
||||
if(treeVersion != rangedCachedLast)
|
||||
{
|
||||
auto bonuses = target->getBonuses(selector, limit);
|
||||
rangedValue = initialValue + bonuses->totalValue();
|
||||
rangedCachedLast = treeVersion;
|
||||
}
|
||||
|
||||
return rangedValue;
|
||||
}
|
||||
|
||||
///CCheckProxy
|
||||
CCheckProxy::CCheckProxy(const IBonusBearer * Target, CSelector Selector)
|
||||
: target(Target),
|
||||
selector(Selector),
|
||||
cachedLast(0),
|
||||
hasBonus(false)
|
||||
{
|
||||
}
|
||||
|
||||
CCheckProxy::CCheckProxy(const CCheckProxy & other)
|
||||
: target(other.target),
|
||||
selector(other.selector),
|
||||
cachedLast(other.cachedLast),
|
||||
hasBonus(other.hasBonus)
|
||||
{
|
||||
}
|
||||
|
||||
bool CCheckProxy::getHasBonus() const
|
||||
{
|
||||
const auto treeVersion = target->getTreeVersion();
|
||||
|
||||
if(treeVersion != cachedLast)
|
||||
{
|
||||
hasBonus = target->hasBonus(selector);
|
||||
cachedLast = treeVersion;
|
||||
}
|
||||
|
||||
return hasBonus;
|
||||
}
|
||||
|
||||
CAddInfo::CAddInfo()
|
||||
{
|
||||
}
|
||||
@ -467,6 +581,22 @@ void BonusList::insert(BonusList::TInternalContainer::iterator position, BonusLi
|
||||
changed();
|
||||
}
|
||||
|
||||
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));
|
||||
|
||||
CSelector IBonusBearer::moraleSelector = Selector::type(Bonus::MORALE);
|
||||
CSelector IBonusBearer::selfMoraleSelector = Selector::type(Bonus::SELF_MORALE);
|
||||
|
||||
IBonusBearer::IBonusBearer()
|
||||
:anaffectedByMorale(this, anaffectedByMoraleSelector),
|
||||
moraleValue(this, moraleSelector, 0),
|
||||
selfMorale(this, selfMoraleSelector)
|
||||
{
|
||||
}
|
||||
|
||||
int IBonusBearer::valOfBonuses(Bonus::BonusType type, const CSelector &selector) const
|
||||
{
|
||||
return valOfBonuses(Selector::type(type).And(selector));
|
||||
@ -532,13 +662,12 @@ bool IBonusBearer::hasBonusFrom(Bonus::BonusSource source, ui32 sourceID) const
|
||||
|
||||
int IBonusBearer::MoraleVal() const
|
||||
{
|
||||
if(hasBonusOfType(Bonus::NON_LIVING) || hasBonusOfType(Bonus::UNDEAD) ||
|
||||
hasBonusOfType(Bonus::NO_MORALE) || hasBonusOfType(Bonus::SIEGE_WEAPON))
|
||||
if(anaffectedByMorale.getHasBonus())
|
||||
return 0;
|
||||
|
||||
int ret = valOfBonuses(Bonus::MORALE);
|
||||
int ret = moraleValue.getValue();
|
||||
|
||||
if(hasBonusOfType(Bonus::SELF_MORALE)) //eg. minotaur
|
||||
if(selfMorale.getHasBonus()) //eg. minotaur
|
||||
vstd::amax(ret, +1);
|
||||
|
||||
return vstd::abetween(ret, -3, +3);
|
||||
|
@ -87,6 +87,51 @@ private:
|
||||
mutable TBonusListPtr data;
|
||||
};
|
||||
|
||||
class DLL_LINKAGE CTotalsProxy
|
||||
{
|
||||
public:
|
||||
CTotalsProxy(const IBonusBearer * Target, CSelector Selector, int InitialValue);
|
||||
CTotalsProxy(const CTotalsProxy & other);
|
||||
CTotalsProxy(CTotalsProxy && other) = delete;
|
||||
|
||||
CTotalsProxy & operator=(const CTotalsProxy & other);
|
||||
CTotalsProxy & operator=(CTotalsProxy && other) = delete;
|
||||
|
||||
int getMeleeValue() const;
|
||||
int getRangedValue() const;
|
||||
int getValue() const;
|
||||
|
||||
private:
|
||||
const IBonusBearer * target;
|
||||
CSelector selector;
|
||||
int initialValue;
|
||||
|
||||
mutable int64_t cachedLast;
|
||||
mutable int value;
|
||||
|
||||
mutable int64_t meleeCachedLast;
|
||||
mutable int meleeValue;
|
||||
|
||||
mutable int64_t rangedCachedLast;
|
||||
mutable int rangedValue;
|
||||
};
|
||||
|
||||
class DLL_LINKAGE CCheckProxy
|
||||
{
|
||||
public:
|
||||
CCheckProxy(const IBonusBearer * Target, CSelector Selector);
|
||||
CCheckProxy(const CCheckProxy & other);
|
||||
|
||||
bool getHasBonus() const;
|
||||
|
||||
private:
|
||||
const IBonusBearer * target;
|
||||
CSelector selector;
|
||||
|
||||
mutable int64_t cachedLast;
|
||||
mutable bool hasBonus;
|
||||
};
|
||||
|
||||
class DLL_LINKAGE CAddInfo : public std::vector<si32>
|
||||
{
|
||||
public:
|
||||
@ -641,11 +686,20 @@ public:
|
||||
|
||||
class DLL_LINKAGE IBonusBearer
|
||||
{
|
||||
private:
|
||||
static CSelector anaffectedByMoraleSelector;
|
||||
CCheckProxy anaffectedByMorale;
|
||||
static CSelector moraleSelector;
|
||||
CTotalsProxy moraleValue;
|
||||
static CSelector selfMoraleSelector;
|
||||
CCheckProxy selfMorale;
|
||||
|
||||
public:
|
||||
//new bonusing node interface
|
||||
// * selector is predicate that tests if HeroBonus matches our criteria
|
||||
// * root is node on which call was made (nullptr will be replaced with this)
|
||||
//interface
|
||||
IBonusBearer();
|
||||
virtual const TBonusListPtr getAllBonuses(const CSelector &selector, const CSelector &limit, const CBonusSystemNode *root = nullptr, const std::string &cachingStr = "") const = 0;
|
||||
int valOfBonuses(const CSelector &selector, const std::string &cachingStr = "") const;
|
||||
bool hasBonus(const CSelector &selector, const std::string &cachingStr = "") const;
|
||||
|
@ -19,99 +19,6 @@
|
||||
|
||||
namespace battle
|
||||
{
|
||||
|
||||
CTotalsProxy::CTotalsProxy(const IBonusBearer * Target, CSelector Selector, int InitialValue)
|
||||
: target(Target),
|
||||
selector(Selector),
|
||||
initialValue(InitialValue),
|
||||
meleeCachedLast(0),
|
||||
meleeValue(0),
|
||||
rangedCachedLast(0),
|
||||
rangedValue(0)
|
||||
{
|
||||
}
|
||||
|
||||
CTotalsProxy::CTotalsProxy(const CTotalsProxy & other)
|
||||
: target(other.target),
|
||||
selector(other.selector),
|
||||
initialValue(other.initialValue),
|
||||
meleeCachedLast(other.meleeCachedLast),
|
||||
meleeValue(other.meleeValue),
|
||||
rangedCachedLast(other.rangedCachedLast),
|
||||
rangedValue(other.rangedValue)
|
||||
{
|
||||
}
|
||||
|
||||
CTotalsProxy & CTotalsProxy::operator=(const CTotalsProxy & other)
|
||||
{
|
||||
initialValue = other.initialValue;
|
||||
meleeCachedLast = other.meleeCachedLast;
|
||||
meleeValue = other.meleeValue;
|
||||
rangedCachedLast = other.rangedCachedLast;
|
||||
rangedValue = other.rangedValue;
|
||||
return *this;
|
||||
}
|
||||
|
||||
int CTotalsProxy::getMeleeValue() const
|
||||
{
|
||||
static const auto limit = Selector::effectRange(Bonus::NO_LIMIT).Or(Selector::effectRange(Bonus::ONLY_MELEE_FIGHT));
|
||||
|
||||
const auto treeVersion = target->getTreeVersion();
|
||||
|
||||
if(treeVersion != meleeCachedLast)
|
||||
{
|
||||
auto bonuses = target->getBonuses(selector, limit);
|
||||
meleeValue = initialValue + bonuses->totalValue();
|
||||
meleeCachedLast = treeVersion;
|
||||
}
|
||||
return meleeValue;
|
||||
}
|
||||
|
||||
int CTotalsProxy::getRangedValue() const
|
||||
{
|
||||
static const auto limit = Selector::effectRange(Bonus::NO_LIMIT).Or(Selector::effectRange(Bonus::ONLY_DISTANCE_FIGHT));
|
||||
|
||||
const auto treeVersion = target->getTreeVersion();
|
||||
|
||||
if(treeVersion != rangedCachedLast)
|
||||
{
|
||||
auto bonuses = target->getBonuses(selector, limit);
|
||||
rangedValue = initialValue + bonuses->totalValue();
|
||||
rangedCachedLast = treeVersion;
|
||||
}
|
||||
return rangedValue;
|
||||
}
|
||||
|
||||
///CCheckProxy
|
||||
CCheckProxy::CCheckProxy(const IBonusBearer * Target, CSelector Selector)
|
||||
: target(Target),
|
||||
selector(Selector),
|
||||
cachedLast(0),
|
||||
hasBonus(false)
|
||||
{
|
||||
}
|
||||
|
||||
CCheckProxy::CCheckProxy(const CCheckProxy & other)
|
||||
: target(other.target),
|
||||
selector(other.selector),
|
||||
cachedLast(other.cachedLast),
|
||||
hasBonus(other.hasBonus)
|
||||
{
|
||||
}
|
||||
|
||||
bool CCheckProxy::getHasBonus() const
|
||||
{
|
||||
const auto treeVersion = target->getTreeVersion();
|
||||
|
||||
if(treeVersion != cachedLast)
|
||||
{
|
||||
hasBonus = target->hasBonus(selector);
|
||||
cachedLast = treeVersion;
|
||||
}
|
||||
|
||||
return hasBonus;
|
||||
}
|
||||
|
||||
///CAmmo
|
||||
CAmmo::CAmmo(const battle::Unit * Owner, CSelector totalSelector)
|
||||
: used(0),
|
||||
|
@ -24,47 +24,6 @@ namespace battle
|
||||
{
|
||||
class CUnitState;
|
||||
|
||||
class DLL_LINKAGE CTotalsProxy
|
||||
{
|
||||
public:
|
||||
CTotalsProxy(const IBonusBearer * Target, CSelector Selector, int InitialValue);
|
||||
CTotalsProxy(const CTotalsProxy & other);
|
||||
CTotalsProxy(CTotalsProxy && other) = delete;
|
||||
|
||||
CTotalsProxy & operator=(const CTotalsProxy & other);
|
||||
CTotalsProxy & operator=(CTotalsProxy && other) = delete;
|
||||
|
||||
int getMeleeValue() const;
|
||||
int getRangedValue() const;
|
||||
|
||||
private:
|
||||
const IBonusBearer * target;
|
||||
CSelector selector;
|
||||
int initialValue;
|
||||
|
||||
mutable int64_t meleeCachedLast;
|
||||
mutable int meleeValue;
|
||||
|
||||
mutable int64_t rangedCachedLast;
|
||||
mutable int rangedValue;
|
||||
};
|
||||
|
||||
class DLL_LINKAGE CCheckProxy
|
||||
{
|
||||
public:
|
||||
CCheckProxy(const IBonusBearer * Target, CSelector Selector);
|
||||
CCheckProxy(const CCheckProxy & other);
|
||||
|
||||
bool getHasBonus() const;
|
||||
|
||||
private:
|
||||
const IBonusBearer * target;
|
||||
CSelector selector;
|
||||
|
||||
mutable int64_t cachedLast;
|
||||
mutable bool hasBonus;
|
||||
};
|
||||
|
||||
class DLL_LINKAGE CAmmo
|
||||
{
|
||||
public:
|
||||
|
@ -36,7 +36,11 @@ void CArmedInstance::randomizeArmy(int type)
|
||||
return;
|
||||
}
|
||||
|
||||
// Take Angelic Alliance troop-mixing freedom of non-evil units into account.
|
||||
CSelector CArmedInstance::nonEvilAlignmentMixSelector = Selector::type(Bonus::NONEVIL_ALIGNMENT_MIX);
|
||||
|
||||
CArmedInstance::CArmedInstance()
|
||||
:nonEvilAlignmentMix(this, nonEvilAlignmentMixSelector)
|
||||
{
|
||||
battle = nullptr;
|
||||
}
|
||||
@ -57,6 +61,9 @@ void CArmedInstance::updateMoraleBonusFromArmy()
|
||||
std::set<TFaction> factions;
|
||||
bool hasUndead = false;
|
||||
|
||||
const std::string undeadCacheKey = "type_UNDEAD";
|
||||
static const CSelector undeadSelector = Selector::type(Bonus::UNDEAD);
|
||||
|
||||
for(auto slot : Slots())
|
||||
{
|
||||
const CStackInstance * inst = slot.second;
|
||||
@ -64,13 +71,12 @@ void CArmedInstance::updateMoraleBonusFromArmy()
|
||||
|
||||
factions.insert(creature->faction);
|
||||
// Check for undead flag instead of faction (undead mummies are neutral)
|
||||
hasUndead |= inst->hasBonusOfType(Bonus::UNDEAD);
|
||||
hasUndead |= inst->hasBonus(undeadSelector, undeadCacheKey);
|
||||
}
|
||||
|
||||
size_t factionsInArmy = factions.size(); //town garrison seems to take both sets into account
|
||||
|
||||
// Take Angelic Alliance troop-mixing freedom of non-evil units into account.
|
||||
if (hasBonusOfType(Bonus::NONEVIL_ALIGNMENT_MIX))
|
||||
if (nonEvilAlignmentMix.getHasBonus())
|
||||
{
|
||||
size_t mixableFactions = 0;
|
||||
|
||||
|
@ -17,6 +17,10 @@ class CGameState;
|
||||
|
||||
class DLL_LINKAGE CArmedInstance: public CGObjectInstance, public CBonusSystemNode, public CCreatureSet
|
||||
{
|
||||
private:
|
||||
CCheckProxy nonEvilAlignmentMix;
|
||||
static CSelector nonEvilAlignmentMixSelector;
|
||||
|
||||
public:
|
||||
BattleInfo *battle; //set to the current battle, if engaged
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user