File: CCreatureSet.h

package info (click to toggle)
vcmi 0.99%2Bdfsg%2Bgit20190113.f06c8a87-2
  • links: PTS, VCS
  • area: contrib
  • in suites: bullseye
  • size: 11,136 kB
  • sloc: cpp: 142,615; sh: 315; objc: 248; makefile: 32; ansic: 28; python: 13
file content (235 lines) | stat: -rw-r--r-- 9,091 bytes parent folder | download | duplicates (2)
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
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
/*
 * CCreatureSet.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 "HeroBonus.h"
#include "GameConstants.h"
#include "CArtHandler.h"

class JsonNode;
class CCreature;
class CGHeroInstance;
class CArmedInstance;
class CCreatureArtifactSet;
class JsonSerializeFormat;

class DLL_LINKAGE CStackBasicDescriptor
{
public:
	const CCreature *type;
	TQuantity count;

	CStackBasicDescriptor();
	CStackBasicDescriptor(CreatureID id, TQuantity Count);
	CStackBasicDescriptor(const CCreature *c, TQuantity Count);
	virtual ~CStackBasicDescriptor() = default;

	virtual void setType(const CCreature * c);

	template <typename Handler> void serialize(Handler &h, const int version)
	{
		h & type;
		h & count;
	}

	void serializeJson(JsonSerializeFormat & handler);
};

class DLL_LINKAGE CStackInstance : public CBonusSystemNode, public CStackBasicDescriptor, public CArtifactSet
{
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
	// idRand / 2 -> level
	// idRand % 2 -> upgrade number
	int idRand;

	const CArmedInstance * const & armyObj; //stack must be part of some army, army must be part of some object
	TExpType experience;//commander needs same amount of exp as hero

	template <typename Handler> void serialize(Handler &h, const int version)
	{
		h & static_cast<CBonusSystemNode&>(*this);
		h & static_cast<CStackBasicDescriptor&>(*this);
		h & static_cast<CArtifactSet&>(*this);
		h & _armyObj;
		h & experience;
		BONUS_TREE_DESERIALIZATION_FIX
	}

	void serializeJson(JsonSerializeFormat & handler);

	//overrides CBonusSystemNode
	std::string bonusToString(const std::shared_ptr<Bonus>& bonus, bool description) const override; // how would bonus description look for this particular type of node
	std::string bonusToGraphics(const std::shared_ptr<Bonus>& bonus) const; //file name of graphics from StackSkills , in future possibly others

	virtual ui64 getPower() const;
	int getQuantityID() const;
	std::string getQuantityTXT(bool capitalized = true) const;
	virtual int getExpRank() const;
	virtual int getLevel() const; //different for regular stack and commander
	si32 magicResistance() const override;
	CreatureID getCreatureID() const; //-1 if not available
	std::string getName() const; //plural or singular
	virtual void init();
	CStackInstance();
	CStackInstance(CreatureID id, TQuantity count);
	CStackInstance(const CCreature *cre, TQuantity count);
	virtual ~CStackInstance();

	void setType(CreatureID creID);
	void setType(const CCreature * c) override;
	void setArmyObj(const CArmedInstance *ArmyObj);
	virtual void giveStackExp(TExpType exp);
	bool valid(bool allowUnrandomized) const;
	void putArtifact(ArtifactPosition pos, CArtifactInstance * art) override;//from CArtifactSet
	ArtBearer::ArtBearer bearerType() const override; //from CArtifactSet
	virtual std::string nodeName() const override; //from CBonusSystemnode
	void deserializationFix();
};

class DLL_LINKAGE CCommanderInstance : public CStackInstance
{
public:
	//TODO: what if Commander is not a part of creature set?

	//commander class is determined by its base creature
	ui8 alive; //maybe change to bool when breaking save compatibility?
	ui8 level; //required only to count callbacks
	std::string name; // each Commander has different name
	std::vector <ui8> secondarySkills; //ID -> level
	std::set <ui8> specialSKills;
	//std::vector <CArtifactInstance *> arts;
	void init() override;
	CCommanderInstance();
	CCommanderInstance (CreatureID id);
	virtual ~CCommanderInstance();
	void setAlive (bool alive);
	void giveStackExp (TExpType exp) override;
	void levelUp ();

	bool gainsLevel() const; //true if commander has lower level than should upon his experience
	ui64 getPower() const override {return 0;};
	int getExpRank() const override;
	int getLevel() const override;
	ArtBearer::ArtBearer bearerType() const override; //from CArtifactSet

	template <typename Handler> void serialize(Handler &h, const int version)
	{
		h & static_cast<CStackInstance&>(*this);
		h & alive;
		h & level;
		h & name;
		h & secondarySkills;
		h & specialSKills;
	}
};

typedef std::map<SlotID, CStackInstance*> TSlots;
typedef std::map<SlotID, std::pair<CreatureID, TQuantity>> TSimpleSlots;

class IArmyDescriptor
{
public:
	virtual void clear() = 0;
	virtual bool setCreature(SlotID slot, CreatureID cre, TQuantity count) = 0;
};

//simplified version of CCreatureSet
class DLL_LINKAGE CSimpleArmy : public IArmyDescriptor
{
public:
	TSimpleSlots army;
	void clear() override;
	bool setCreature(SlotID slot, CreatureID cre, TQuantity count) override;
	operator bool() const;

	template <typename Handler> void serialize(Handler &h, const int version)
	{
		h & army;
	}
};

class DLL_LINKAGE CCreatureSet : public IArmyDescriptor //seven combined creatures
{
	CCreatureSet(const CCreatureSet&);
	CCreatureSet &operator=(const CCreatureSet&);
public:
	TSlots stacks; //slots[slot_id]->> pair(creature_id,creature_quantity)
	ui8 formation; //false - wide, true - tight

	CCreatureSet();
	virtual ~CCreatureSet();
	virtual void armyChanged();

	const CStackInstance &operator[](SlotID slot) const;

	const TSlots &Slots() const {return stacks;}

	void addToSlot(SlotID slot, CreatureID cre, TQuantity count, bool allowMerging = true); //Adds stack to slot. Slot must be empty or with same type creature
	void addToSlot(SlotID slot, CStackInstance *stack, bool allowMerging = true); //Adds stack to slot. Slot must be empty or with same type creature
	void clear() override;
	void setFormation(bool tight);
	CArmedInstance *castToArmyObj();

	//basic operations
	void putStack(SlotID slot, CStackInstance *stack); //adds new stack to the army, slot must be empty
	void setStackCount(SlotID slot, TQuantity count); //stack must exist!
	CStackInstance *detachStack(SlotID slot); //removes stack from army but doesn't destroy it (so it can be moved somewhere else or safely deleted)
	void setStackType(SlotID slot, CreatureID type);
	void giveStackExp(TExpType exp);
	void setStackExp(SlotID slot, TExpType exp);

	//derivative
	void eraseStack(SlotID slot); //slot must be occupied
	void joinStack(SlotID slot, CStackInstance * stack); //adds new stack to the existing stack of the same type
	void changeStackCount(SlotID slot, TQuantity toAdd); //stack must exist!
	bool setCreature (SlotID slot, CreatureID type, TQuantity quantity) override; //replaces creature in stack; slots 0 to 6, if quantity=0 erases stack
	void setToArmy(CSimpleArmy &src); //erases all our army and moves stacks from src to us; src MUST NOT be an armed object! WARNING: use it wisely. Or better do not use at all.

	const CStackInstance& getStack(SlotID slot) const; //stack must exist
	const CStackInstance* getStackPtr(SlotID slot) const; //if stack doesn't exist, returns nullptr
	const CCreature* getCreature(SlotID slot) const; //workaround of map issue;
	int getStackCount (SlotID slot) const;
	TExpType getStackExperience(SlotID slot) const;
	SlotID findStack(const CStackInstance *stack) const; //-1 if none
	SlotID getSlotFor(CreatureID creature, ui32 slotsAmount = GameConstants::ARMY_SIZE) const; //returns -1 if no slot available
	SlotID getSlotFor(const CCreature *c, ui32 slotsAmount = GameConstants::ARMY_SIZE) const; //returns -1 if no slot available
	SlotID getFreeSlot(ui32 slotsAmount = GameConstants::ARMY_SIZE) const;
	bool mergableStacks(std::pair<SlotID, SlotID> &out, SlotID preferable = SlotID()) const; //looks for two same stacks, returns slot positions;
	bool validTypes(bool allowUnrandomized = false) const; //checks if all types of creatures are set properly
	bool slotEmpty(SlotID slot) const;
	int stacksCount() const;
	virtual bool needsLastStack() const; //true if last stack cannot be taken
	ui64 getArmyStrength() const; //sum of AI values of creatures
	ui64 getPower (SlotID slot) const; //value of specific stack
	std::string getRoughAmount(SlotID slot, int mode = 0) const; //rough size of specific stack
	std::string getArmyDescription() const;
	bool hasStackAtSlot(SlotID slot) const;

	bool contains(const CStackInstance *stack) const;
	bool canBeMergedWith(const CCreatureSet &cs, bool allowMergingStacks = true) const;

	template <typename Handler> void serialize(Handler &h, const int version)
	{
		h & stacks;
		h & formation;
	}

	void serializeJson(JsonSerializeFormat & handler, const std::string & fieldName, const boost::optional<int> fixedSize = boost::none);

	operator bool() const
	{
		return !stacks.empty();
	}
	void sweep();
};