浏览代码

hacks to optimize a few bonus requests

Andrii Danylchenko 5 年之前
父节点
当前提交
d782ee39df
共有 6 个文件被更改,包括 200 次插入141 次删除
  1. 133 4
      lib/HeroBonus.cpp
  2. 54 0
      lib/HeroBonus.h
  3. 0 93
      lib/battle/CUnitState.cpp
  4. 0 41
      lib/battle/CUnitState.h
  5. 9 3
      lib/mapObjects/CArmedInstance.cpp
  6. 4 0
      lib/mapObjects/CArmedInstance.h

+ 133 - 4
lib/HeroBonus.cpp

@@ -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);

+ 54 - 0
lib/HeroBonus.h

@@ -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;

+ 0 - 93
lib/battle/CUnitState.cpp

@@ -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),

+ 0 - 41
lib/battle/CUnitState.h

@@ -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:

+ 9 - 3
lib/mapObjects/CArmedInstance.cpp

@@ -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;
 

+ 4 - 0
lib/mapObjects/CArmedInstance.h

@@ -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