Browse Source

Nullkiller: replace a hack with temporary bonus node concept

Andrii Danylchenko 4 years ago
parent
commit
70ed3f55a5

+ 4 - 0
AI/Nullkiller/Analyzers/ArmyManager.cpp

@@ -84,6 +84,10 @@ class TemporaryArmy : public CArmedInstance
 {
 public:
 	void armyChanged() override {}
+	TemporaryArmy()
+	{
+		CBonusSystemNode::isHypotheticNode = true;
+	}
 };
 
 std::vector<SlotInfo> ArmyManager::getBestArmy(const IBonusBearer * armyCarrier, const CCreatureSet * target, const CCreatureSet * source) const

+ 0 - 6
AI/Nullkiller/Pathfinding/AINodeStorage.cpp

@@ -115,9 +115,7 @@ void AINodeStorage::initialize(const PathfinderOptions & options, const CGameSta
 
 void AINodeStorage::clear()
 {
-	CCreature::DisableChildLinkage = true;
 	actors.clear();
-	CCreature::DisableChildLinkage = false;
 	heroChainPass = EHeroChainPass::INITIAL;
 	heroChainTurn = 0;
 	heroChainMaxTurns = 1;
@@ -499,8 +497,6 @@ bool AINodeStorage::calculateHeroChain()
 
 	std::vector<int3> data(commitedTiles.begin(), commitedTiles.end());
 
-	CCreature::DisableChildLinkage = true;
-
 	if(data.size() > 100)
 	{
 		boost::mutex resultMutex;
@@ -530,8 +526,6 @@ bool AINodeStorage::calculateHeroChain()
 		task.flushResult(heroChain);
 	}
 
-	CCreature::DisableChildLinkage = false;
-
 	commitedTiles.clear();
 
 	return !heroChain.empty();

+ 0 - 4
AI/Nullkiller/Pathfinding/Actors.cpp

@@ -196,8 +196,6 @@ HeroExchangeMap::HeroExchangeMap(const HeroActor * actor, const Nullkiller * ai)
 
 HeroExchangeMap::~HeroExchangeMap()
 {
-	CCreature::DisableChildLinkage = true;
-
 	for(auto & exchange : exchangeMap)
 	{
 		if(!exchange.second) continue;
@@ -205,8 +203,6 @@ HeroExchangeMap::~HeroExchangeMap()
 		delete exchange.second->creatureSet;
 	}
 
-	CCreature::DisableChildLinkage = false;
-
 	for(auto & exchange : exchangeMap)
 	{
 		if(!exchange.second) continue;

+ 3 - 2
AI/Nullkiller/Pathfinding/Actors.h

@@ -21,7 +21,7 @@ class ChainActor;
 class HeroActor;
 class Nullkiller;
 
-class HeroExchangeArmy : public CCreatureSet
+class HeroExchangeArmy : public CArmedInstance
 {
 public:
 	TResources armyCost;
@@ -29,8 +29,9 @@ public:
 	virtual bool needsLastStack() const override;
 	std::shared_ptr<SpecialAction> getActorAction() const;
 
-	HeroExchangeArmy() : CCreatureSet(), armyCost(), requireBuyArmy(false)
+	HeroExchangeArmy() : CArmedInstance(), armyCost(), requireBuyArmy(false)
 	{
+		CBonusSystemNode::isHypotheticNode = true;
 	}
 };
 

+ 8 - 3
lib/CCreatureSet.cpp

@@ -58,7 +58,10 @@ bool CCreatureSet::setCreature(SlotID slot, CreatureID type, TQuantity quantity)
 	if(hasStackAtSlot(slot)) //remove old creature
 		eraseStack(slot);
 
-	putStack(slot, new CStackInstance(type, quantity));
+	auto armyObj = castToArmyObj();
+	bool isHypotheticArmy = armyObj ? armyObj->isHypothetic() : false;
+
+	putStack(slot, new CStackInstance(type, quantity, isHypotheticArmy));
 	return true;
 }
 
@@ -532,20 +535,22 @@ CStackInstance::CStackInstance()
 	init();
 }
 
-CStackInstance::CStackInstance(CreatureID id, TQuantity Count)
+CStackInstance::CStackInstance(CreatureID id, TQuantity Count, bool isHypothetic)
 	: armyObj(_armyObj)
 {
 	init();
 	setType(id);
 	count = Count;
+	CBonusSystemNode::isHypotheticNode = isHypothetic;
 }
 
-CStackInstance::CStackInstance(const CCreature *cre, TQuantity Count)
+CStackInstance::CStackInstance(const CCreature *cre, TQuantity Count, bool isHypothetic)
 	: armyObj(_armyObj)
 {
 	init();
 	setType(cre);
 	count = Count;
+	CBonusSystemNode::isHypotheticNode = isHypothetic;
 }
 
 void CStackInstance::init()

+ 3 - 2
lib/CCreatureSet.h

@@ -49,6 +49,7 @@ class DLL_LINKAGE CStackInstance : public CBonusSystemNode, public CStackBasicDe
 {
 protected:
 	const CArmedInstance *_armyObj; //stack must be part of some army, army must be part of some object
+
 public:
 	// hlp variable used during loading map, when object (hero or town) have creatures that must have same alignment.
 	// idRand < 0 -> normal, non-random creature
@@ -85,8 +86,8 @@ public:
 	std::string getName() const; //plural or singular
 	virtual void init();
 	CStackInstance();
-	CStackInstance(CreatureID id, TQuantity count);
-	CStackInstance(const CCreature *cre, TQuantity count);
+	CStackInstance(CreatureID id, TQuantity count, bool isHypothetic = false);
+	CStackInstance(const CCreature *cre, TQuantity count, bool isHypothetic = false);
 	virtual ~CStackInstance();
 
 	void setType(CreatureID creID);

+ 28 - 13
lib/HeroBonus.cpp

@@ -993,7 +993,8 @@ CBonusSystemNode::CBonusSystemNode()
 	exportedBonuses(true),
 	nodeType(UNKNOWN),
 	cachedLast(0),
-	sync()
+	sync(),
+	isHypotheticNode(false)
 {
 }
 
@@ -1002,7 +1003,8 @@ CBonusSystemNode::CBonusSystemNode(ENodeTypes NodeType)
 	exportedBonuses(true),
 	nodeType(NodeType),
 	cachedLast(0),
-	sync()
+	sync(),
+	isHypotheticNode(false)
 {
 }
 
@@ -1012,7 +1014,8 @@ CBonusSystemNode::CBonusSystemNode(CBonusSystemNode && other):
 	nodeType(other.nodeType),
 	description(other.description),
 	cachedLast(0),
-	sync()
+	sync(),
+	isHypotheticNode(false)
 {
 	std::swap(parents, other.parents);
 	std::swap(children, other.children);
@@ -1053,12 +1056,16 @@ void CBonusSystemNode::attachTo(CBonusSystemNode *parent)
 	assert(!vstd::contains(parents, parent));
 	parents.push_back(parent);
 
-	if(parent->actsAsBonusSourceOnly())
-		parent->newRedDescendant(this);
-	else
-		newRedDescendant(parent);
+	if(!isHypothetic())
+	{
+		if(parent->actsAsBonusSourceOnly())
+			parent->newRedDescendant(this);
+		else
+			newRedDescendant(parent);
+
+		parent->newChildAttached(this);
+	}
 
-	parent->newChildAttached(this);
 	CBonusSystemNode::treeHasChanged();
 }
 
@@ -1066,13 +1073,21 @@ void CBonusSystemNode::detachFrom(CBonusSystemNode *parent)
 {
 	assert(vstd::contains(parents, parent));
 
-	if(parent->actsAsBonusSourceOnly())
-		parent->removedRedDescendant(this);
-	else
-		removedRedDescendant(parent);
+	if(!isHypothetic())
+	{
+		if(parent->actsAsBonusSourceOnly())
+			parent->removedRedDescendant(this);
+		else
+			removedRedDescendant(parent);
+	}
 
 	parents -= parent;
-	parent->childDetached(this);
+
+	if(!isHypothetic())
+	{
+		parent->childDetached(this);
+	}
+
 	CBonusSystemNode::treeHasChanged();
 }
 

+ 4 - 0
lib/HeroBonus.h

@@ -768,6 +768,9 @@ private:
 	TConstBonusListPtr getAllBonusesWithoutCaching(const CSelector &selector, const CSelector &limit, const CBonusSystemNode *root = nullptr) const;
 	std::shared_ptr<Bonus> update(const std::shared_ptr<Bonus> & b) const;
 
+protected:
+	bool isHypotheticNode;
+
 public:
 	explicit CBonusSystemNode();
 	explicit CBonusSystemNode(ENodeTypes NodeType);
@@ -810,6 +813,7 @@ public:
 	void reduceBonusDurations(const CSelector &s);
 	virtual std::string bonusToString(const std::shared_ptr<Bonus>& bonus, bool description) const {return "";}; //description or bonus name
 	virtual std::string nodeName() const;
+	bool isHypothetic() const { return isHypotheticNode; }
 
 	void deserializationFix();
 	void exportBonus(std::shared_ptr<Bonus> b);