1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-11-25 22:42:04 +02:00

Add tests for bonus system propagation, fix discovered issues

This commit is contained in:
Ivan Savenko
2025-08-04 12:23:38 +03:00
parent 396470d962
commit 1d2d189e4a
5 changed files with 322 additions and 45 deletions

View File

@@ -35,7 +35,7 @@ std::shared_ptr<const Bonus> CBonusSystemNode::getFirstBonus(const CSelector & s
return ret;
TCNodes lparents;
getParents(lparents);
getDirectParents(lparents);
for(const CBonusSystemNode *pname : lparents)
{
ret = pname->getFirstBonus(selector);
@@ -46,25 +46,12 @@ std::shared_ptr<const Bonus> CBonusSystemNode::getFirstBonus(const CSelector & s
return nullptr;
}
void CBonusSystemNode::getParents(TCNodes & out) const /*retrieves list of parent nodes (nodes to inherit bonuses from) */
void CBonusSystemNode::getDirectParents(TCNodes & out) const /*retrieves list of parent nodes (nodes to inherit bonuses from) */
{
for(const auto * elem : parentsToInherit)
out.insert(elem);
}
void CBonusSystemNode::getAllParents(TCNodes & out) const //retrieves list of parent nodes (nodes to inherit bonuses from)
{
for(auto * parent : parentsToInherit)
{
// Diamond found! One of the parents of the targeted node can be discovered in two ways.
// For example, a hero has been attached to both the player node and the global node (to which the player node is also attached).
// This is illegal and can be a source of duplicate bonuses.
assert(out.count(parent) == 0);
out.insert(parent);
parent->getAllParents(out);
}
}
void CBonusSystemNode::getAllBonusesRec(BonusList &out) const
{
BonusList beforeUpdate;
@@ -219,13 +206,15 @@ void CBonusSystemNode::attachToSource(const CBonusSystemNode & parent)
assert(!vstd::contains(parentsToInherit, &parent));
parentsToInherit.push_back(&parent);
++globalCounter;
if(!isHypothetic())
{
if(parent.actsAsBonusSourceOnly())
parent.newRedDescendant(*this);
}
nodeHasChanged();
invalidateChildrenNodes(globalCounter);
}
void CBonusSystemNode::detachFrom(CBonusSystemNode & parent)
@@ -268,6 +257,8 @@ void CBonusSystemNode::detachFromSource(const CBonusSystemNode & parent)
{
assert(vstd::contains(parentsToInherit, &parent));
++globalCounter;
if(!isHypothetic())
{
if(parent.actsAsBonusSourceOnly())
@@ -284,7 +275,7 @@ void CBonusSystemNode::detachFromSource(const CBonusSystemNode & parent)
nodeShortInfo(), static_cast<int>(nodeType), parent.nodeShortInfo(), static_cast<int>(parent.nodeType));
}
nodeHasChanged();
invalidateChildrenNodes(globalCounter);
}
void CBonusSystemNode::removeBonusesRecursive(const CSelector & s)
@@ -371,7 +362,7 @@ void CBonusSystemNode::propagateBonus(const std::shared_ptr<Bonus> & b, const CB
{
if(b->propagator->shouldBeAttached(this))
{
auto propagated = b->propagationUpdater
auto propagated = b->propagationUpdater
? source.getUpdatedBonus(b, b->propagationUpdater)
: b;
bonuses.push_back(propagated);
@@ -442,7 +433,7 @@ std::string CBonusSystemNode::nodeShortInfo() const
void CBonusSystemNode::getRedParents(TCNodes & out) const
{
TCNodes lparents;
getParents(lparents);
getDirectParents(lparents);
for(const CBonusSystemNode *pname : lparents)
{
if(pname->actsAsBonusSourceOnly())
@@ -606,23 +597,6 @@ void CBonusSystemNode::nodeHasChanged()
invalidateChildrenNodes(++globalCounter);
}
void CBonusSystemNode::recomputePropagationUpdaters(const CBonusSystemNode & source)
{
for(const auto & b : exportedBonuses)
{
if (b->propagator && b->propagationUpdater)
{
unpropagateBonus(b);
propagateBonus(b, source);
}
}
for(const CBonusSystemNode * parent : source.parentsToInherit)
if (parent->actsAsBonusSourceOnly())
recomputePropagationUpdaters(*parent);
}
void CBonusSystemNode::invalidateChildrenNodes(int32_t changeCounter)
{
if (nodeChanged == changeCounter)
@@ -630,8 +604,6 @@ void CBonusSystemNode::invalidateChildrenNodes(int32_t changeCounter)
nodeChanged = changeCounter;
recomputePropagationUpdaters(*this);
for(CBonusSystemNode * child : children)
child->invalidateChildrenNodes(changeCounter);
}