File: CBonusSystemNode.h

package info (click to toggle)
vcmi 1.6.5%2Bdfsg-2
  • links: PTS, VCS
  • area: contrib
  • in suites: forky, sid, trixie
  • size: 32,060 kB
  • sloc: cpp: 238,971; python: 265; sh: 224; xml: 157; ansic: 78; objc: 61; makefile: 49
file content (157 lines) | stat: -rw-r--r-- 5,553 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
/*
 * CBonusSystemNode.h, part of VCMI engine
 *
 * Authors: listed in file AUTHORS in main folder
 *
 * License: GNU General Public License v2.0 or later
 * Full text of license available in license.txt file, in main folder
 *
 */
#pragma once

#include "BonusList.h"
#include "IBonusBearer.h"

#include "../serializer/Serializeable.h"

#include <tbb/concurrent_hash_map.h>

VCMI_LIB_NAMESPACE_BEGIN

using TNodes = std::set<CBonusSystemNode *>;
using TCNodes = std::set<const CBonusSystemNode *>;
using TNodesVector = std::vector<CBonusSystemNode *>;
using TCNodesVector = std::vector<const CBonusSystemNode *>;

class DLL_LINKAGE CBonusSystemNode : public virtual IBonusBearer, public virtual Serializeable, public boost::noncopyable
{
public:
	enum ENodeTypes
	{
		NONE = -1, 
		UNKNOWN, STACK_INSTANCE, STACK_BATTLE, SPECIALTY, ARTIFACT, CREATURE, ARTIFACT_INSTANCE, HERO, PLAYER, TEAM,
		TOWN_AND_VISITOR, BATTLE, COMMANDER, GLOBAL_EFFECTS, ALL_CREATURES, TOWN
	};

	struct HashStringCompare {
		static size_t hash(const std::string& data)
		{
			std::hash<std::string> hasher;
			return hasher(data);
		}
		static bool equal(const std::string& x, const std::string& y)
		{
			return x == y;
		}
	};

private:
	BonusList bonuses; //wielded bonuses (local or up-propagated here)
	BonusList exportedBonuses; //bonuses coming from this node (wielded or propagated away)

	TCNodesVector parentsToInherit; // we inherit bonuses from them
	TNodesVector parentsToPropagate; // we may attach our bonuses to them
	TNodesVector children;

	ENodeTypes nodeType;
	bool isHypotheticNode;

	mutable BonusList cachedBonuses;
	mutable int32_t cachedLast;
	std::atomic<int32_t> nodeChanged;

	void invalidateChildrenNodes(int32_t changeCounter);

	// Setting a value to cachingStr before getting any bonuses caches the result for later requests.
	// This string needs to be unique, that's why it has to be set in the following manner:
	// [property key]_[value] => only for selector
	using RequestsMap = tbb::concurrent_hash_map<std::string, std::pair<int32_t, TBonusListPtr>, HashStringCompare>;
	mutable RequestsMap cachedRequests;
	mutable std::shared_mutex sync;

	void getAllBonusesRec(BonusList &out, const CSelector & selector) const;
	TConstBonusListPtr getAllBonusesWithoutCaching(const CSelector &selector, const CSelector &limit) const;
	std::shared_ptr<Bonus> getUpdatedBonus(const std::shared_ptr<Bonus> & b, const TUpdaterPtr & updater) const;
	void limitBonuses(const BonusList &allBonuses, BonusList &out) const; //out will bo populed with bonuses that are not limited here

	void getRedParents(TCNodes &out) const;  //retrieves list of red parent nodes (nodes bonuses propagate from)
	void getRedAncestors(TCNodes &out) const;
	void getRedChildren(TNodes &out);

	void getAllParents(TCNodes & out) const;

	void propagateBonus(const std::shared_ptr<Bonus> & b, const CBonusSystemNode & source);
	void unpropagateBonus(const std::shared_ptr<Bonus> & b);
	bool actsAsBonusSourceOnly() const;

	void newRedDescendant(CBonusSystemNode & descendant) const; //propagation needed
	void removedRedDescendant(CBonusSystemNode & descendant) const; //de-propagation needed

	std::string nodeShortInfo() const;

	void exportBonus(const std::shared_ptr<Bonus> & b);

protected:
	bool isIndependentNode() const; //node is independent when it has no parents nor children
	void exportBonuses();

public:
	explicit CBonusSystemNode(bool isHypotetic = false);
	explicit CBonusSystemNode(ENodeTypes NodeType);
	virtual ~CBonusSystemNode();

	TConstBonusListPtr getAllBonuses(const CSelector &selector, const CSelector &limit, const std::string &cachingStr = "") const override;
	void getParents(TCNodes &out) const;  //retrieves list of parent nodes (nodes to inherit bonuses from),

	/// Returns first bonus matching selector
	std::shared_ptr<const Bonus> getFirstBonus(const CSelector & selector) const;

	/// Provides write access to first bonus from this node that matches selector
	std::shared_ptr<Bonus> getLocalBonus(const CSelector & selector);

	void attachTo(CBonusSystemNode & parent);
	void attachToSource(const CBonusSystemNode & parent);
	void detachFrom(CBonusSystemNode & parent);
	void detachFromSource(const CBonusSystemNode & parent);
	void detachFromAll();
	virtual void addNewBonus(const std::shared_ptr<Bonus>& b);
	void accumulateBonus(const std::shared_ptr<Bonus>& b); //add value of bonus with same type/subtype or create new

	void removeBonus(const std::shared_ptr<Bonus>& b);
	void removeBonuses(const CSelector & selector);
	void removeBonusesRecursive(const CSelector & s);

	///updates count of remaining turns and removes outdated bonuses by selector
	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();

	BonusList & getExportedBonusList();
	const BonusList & getExportedBonusList() const;
	CBonusSystemNode::ENodeTypes getNodeType() const;
	void setNodeType(CBonusSystemNode::ENodeTypes type);
	const TCNodesVector & getParentNodes() const;

	void nodeHasChanged();

	int32_t getTreeVersion() const override;

	virtual PlayerColor getOwner() const
	{
		return PlayerColor::NEUTRAL;
	}

	template <typename Handler> void serialize(Handler &h)
	{
		h & nodeType;
		h & exportedBonuses;
		BONUS_TREE_DESERIALIZATION_FIX
	}

	friend class CBonusProxy;
};

VCMI_LIB_NAMESPACE_END