File: CArtHandler.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 (364 lines) | stat: -rw-r--r-- 13,266 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
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
/*
 * CArtHandler.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 "../lib/HeroBonus.h"
//#include "../lib/ConstTransitivePtr.h"
//#include "JsonNode.h"
#include "GameConstants.h"
#include "IHandlerBase.h"

class CArtHandler;
class CArtifact;
class CGHeroInstance;
struct ArtifactLocation;
class CArtifactSet;
class CArtifactInstance;
class CRandomGenerator;
class CMap;
class JsonSerializeFormat;

#define ART_BEARER_LIST \
	ART_BEARER(HERO)\
	ART_BEARER(CREATURE)\
	ART_BEARER(COMMANDER)

namespace ArtBearer
{
	enum ArtBearer
	{
#define ART_BEARER(x) x,
		ART_BEARER_LIST
#undef ART_BEARER
	};
}

class DLL_LINKAGE CArtifact : public CBonusSystemNode //container for artifacts
{
protected:
	std::string name, description; //set if custom
	std::string eventText; //short story displayed upon picking
public:
	enum EartClass {ART_SPECIAL=1, ART_TREASURE=2, ART_MINOR=4, ART_MAJOR=8, ART_RELIC=16}; //artifact classes

	std::string identifier;
	std::string image;
	std::string large; // big image for cutom artifacts, used in drag & drop
	std::string advMapDef; //used for adventure map object
	si32 iconIndex;
	ui32 price;
	std::map<ArtBearer::ArtBearer, std::vector<ArtifactPosition> > possibleSlots; //Bearer Type => ids of slots where artifact can be placed
	std::unique_ptr<std::vector<CArtifact *> > constituents; // Artifacts IDs a combined artifact consists of, or nullptr.
	std::vector<CArtifact *> constituentOf; // Reverse map of constituents - combined arts that include this art
	EartClass aClass;
	ArtifactID id;
	CreatureID warMachine;

	const std::string &Name() const; //getter
	const std::string &Description() const; //getter
	const std::string &EventText() const;

	bool isBig () const;
	bool isTradable () const;

	int getArtClassSerial() const; //0 - treasure, 1 - minor, 2 - major, 3 - relic, 4 - spell scroll, 5 - other
	std::string nodeName() const override;
	void addNewBonus(const std::shared_ptr<Bonus>& b) override;

	virtual void levelUpArtifact (CArtifactInstance * art){};

	template <typename Handler> void serialize(Handler &h, const int version)
	{
		h & static_cast<CBonusSystemNode&>(*this);
		h & name;
		h & description;
		h & eventText;
		h & image;
		h & large;
		h & advMapDef;
		h & iconIndex;
		h & price;
		h & possibleSlots;
		h & constituents;
		h & constituentOf;
		h & aClass;
		h & id;
		if(version >= 759)
		{
			h & identifier;
		}

		if(version >= 771)
		{
			h & warMachine;
		}
		else if(!h.saving)
		{
			fillWarMachine();
		}
	}

	CArtifact();
	~CArtifact();

	friend class CArtHandler;
private:
	void fillWarMachine();
};

class DLL_LINKAGE CGrowingArtifact : public CArtifact //for example commander artifacts getting bonuses after battle
{
public:
	std::vector <std::pair <ui16, Bonus> > bonusesPerLevel; //bonus given each n levels
	std::vector <std::pair <ui16, Bonus> > thresholdBonuses; //after certain level they will be added once

	void levelUpArtifact(CArtifactInstance * art) override;

	template <typename Handler> void serialize(Handler &h, const int version)
	{
		h & static_cast<CArtifact&>(*this);
		h & bonusesPerLevel;
		h & thresholdBonuses;
	}
};

class DLL_LINKAGE CArtifactInstance : public CBonusSystemNode
{
protected:
	void init();
	CArtifactInstance(CArtifact *Art);
public:
	CArtifactInstance();

	ConstTransitivePtr<CArtifact> artType;
	ArtifactInstanceID id;

	//CArtifactInstance(int aid);

	std::string nodeName() const override;
	void deserializationFix();
	void setType(CArtifact *Art);

	std::string getEffectiveDescription(const CGHeroInstance *hero = nullptr) const;
	ArtifactPosition firstAvailableSlot(const CArtifactSet *h) const;
	ArtifactPosition firstBackpackSlot(const CArtifactSet *h) const;
	SpellID getGivenSpellID() const; //to be used with scrolls (and similar arts), -1 if none

	virtual bool canBePutAt(const CArtifactSet *artSet, ArtifactPosition slot, bool assumeDestRemoved = false) const;
	bool canBePutAt(const ArtifactLocation & al, bool assumeDestRemoved = false) const;  //forwards to the above one
	virtual bool canBeDisassembled() const;
	virtual void putAt(ArtifactLocation al);
	virtual void removeFrom(ArtifactLocation al);
	/// Checks if this a part of this artifact: artifact instance is a part
	/// of itself, additionally truth is returned for constituents of combined arts
	virtual bool isPart(const CArtifactInstance *supposedPart) const;

	std::vector<const CArtifact *> assemblyPossibilities(const CArtifactSet *h) const;
	void move(ArtifactLocation src, ArtifactLocation dst);

	template <typename Handler> void serialize(Handler &h, const int version)
	{
		h & static_cast<CBonusSystemNode&>(*this);
		h & artType;
		h & id;
		BONUS_TREE_DESERIALIZATION_FIX
	}

	static CArtifactInstance *createScroll(const CSpell *s);
	static CArtifactInstance *createScroll(SpellID sid);
	static CArtifactInstance *createNewArtifactInstance(CArtifact *Art);
	static CArtifactInstance *createNewArtifactInstance(int aid);

	/**
	 * Creates an artifact instance.
	 *
	 * @param aid the id of the artifact
	 * @param spellID optional. the id of a spell if a spell scroll object should be created
	 * @return the created artifact instance
	 */
	static CArtifactInstance * createArtifact(CMap * map, int aid, int spellID = -1);
};

class DLL_LINKAGE CCombinedArtifactInstance : public CArtifactInstance
{
	CCombinedArtifactInstance(CArtifact *Art);
public:
	struct ConstituentInfo
	{
		ConstTransitivePtr<CArtifactInstance> art;
		ArtifactPosition slot;
		template <typename Handler> void serialize(Handler &h, const int version)
		{
			h & art;
			h & slot;
		}

		bool operator==(const ConstituentInfo &rhs) const;
		ConstituentInfo(CArtifactInstance *art = nullptr, ArtifactPosition slot = ArtifactPosition::PRE_FIRST);
	};

	std::vector<ConstituentInfo> constituentsInfo;

	bool canBePutAt(const CArtifactSet *artSet, ArtifactPosition slot, bool assumeDestRemoved = false) const override;
	bool canBeDisassembled() const override;
	void putAt(ArtifactLocation al) override;
	void removeFrom(ArtifactLocation al) override;
	bool isPart(const CArtifactInstance *supposedPart) const override;

	void createConstituents();
	void addAsConstituent(CArtifactInstance *art, ArtifactPosition slot);
	CArtifactInstance *figureMainConstituent(const ArtifactLocation al); //main constituent is replaced with us (combined art), not lock

	CCombinedArtifactInstance();

	void deserializationFix();

	friend class CArtifactInstance;
	friend struct AssembledArtifact;
	template <typename Handler> void serialize(Handler &h, const int version)
	{
		h & static_cast<CArtifactInstance&>(*this);
		h & constituentsInfo;
		BONUS_TREE_DESERIALIZATION_FIX
	}
};

class DLL_LINKAGE CArtHandler : public IHandlerBase //handles artifacts
{
public:
	std::vector<CArtifact*> treasures, minors, majors, relics; //tmp vectors!!! do not touch if you don't know what you are doing!!!

	std::vector< ConstTransitivePtr<CArtifact> > artifacts;
	std::vector<CArtifact *> allowedArtifacts;
	std::set<ArtifactID> growingArtifacts;

	void addBonuses(CArtifact *art, const JsonNode &bonusList);

	void fillList(std::vector<CArtifact*> &listToBeFilled, CArtifact::EartClass artifactClass); //fills given empty list with allowed artifacts of gibven class. No side effects

	boost::optional<std::vector<CArtifact*>&> listFromClass(CArtifact::EartClass artifactClass);

	ArtifactPosition stringToSlot(std::string slotName);
	CArtifact::EartClass stringToClass(std::string className);

	/// Gets a artifact ID randomly and removes the selected artifact from this handler.
	ArtifactID pickRandomArtifact(CRandomGenerator & rand, int flags);
	ArtifactID pickRandomArtifact(CRandomGenerator & rand, std::function<bool(ArtifactID)> accepts);
	ArtifactID pickRandomArtifact(CRandomGenerator & rand, int flags, std::function<bool(ArtifactID)> accepts);

	bool legalArtifact(ArtifactID id);
	void initAllowedArtifactsList(const std::vector<bool> &allowed); //allowed[art_id] -> 0 if not allowed, 1 if allowed
	void makeItCreatureArt (CArtifact * a, bool onlyCreature = true);
	void makeItCreatureArt (ArtifactID aid, bool onlyCreature = true);
	void makeItCommanderArt (CArtifact * a, bool onlyCommander = true);
	void makeItCommanderArt (ArtifactID aid, bool onlyCommander = true);

	CArtHandler();
	~CArtHandler();

	std::vector<JsonNode> loadLegacyData(size_t dataSize) override;

	void loadObject(std::string scope, std::string name, const JsonNode & data) override;
	void loadObject(std::string scope, std::string name, const JsonNode & data, size_t index) override;
	void afterLoadFinalization() override;

	std::vector<bool> getDefaultAllowed() const override;

	template <typename Handler> void serialize(Handler &h, const int version)
	{
		h & artifacts;
		h & allowedArtifacts;
		h & treasures;
		h & minors;
		h & majors;
		h & relics;
		h & growingArtifacts;
	}

private:
	CArtifact * loadFromJson(const JsonNode & node, const std::string & identifier);

	void addSlot(CArtifact * art, const std::string & slotID);
	void loadSlots(CArtifact * art, const JsonNode & node);
	void loadClass(CArtifact * art, const JsonNode & node);
	void loadType(CArtifact * art, const JsonNode & node);
	void loadComponents(CArtifact * art, const JsonNode & node);
	void loadGrowingArt(CGrowingArtifact * art, const JsonNode & node);

	void giveArtBonus(ArtifactID aid, Bonus::BonusType type, int val, int subtype = -1, Bonus::ValueType valType = Bonus::BASE_NUMBER, std::shared_ptr<ILimiter> limiter = std::shared_ptr<ILimiter>(), int additionalinfo = 0);
	void giveArtBonus(ArtifactID aid, Bonus::BonusType type, int val, int subtype, std::shared_ptr<IPropagator> propagator, int additionalinfo = 0);
	void giveArtBonus(ArtifactID aid, std::shared_ptr<Bonus> bonus);

	void erasePickedArt(ArtifactID id);
};

struct DLL_LINKAGE ArtSlotInfo
{
	ConstTransitivePtr<CArtifactInstance> artifact;
	ui8 locked; //if locked, then artifact points to the combined artifact

	ArtSlotInfo() : locked(false) {}

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

class DLL_LINKAGE CArtifactSet
{
public:
	std::vector<ArtSlotInfo> artifactsInBackpack; //hero's artifacts from bag
	std::map<ArtifactPosition, ArtSlotInfo> artifactsWorn; //map<position,artifact_id>; positions: 0 - head; 1 - shoulders; 2 - neck; 3 - right hand; 4 - left hand; 5 - torso; 6 - right ring; 7 - left ring; 8 - feet; 9 - misc1; 10 - misc2; 11 - misc3; 12 - misc4; 13 - mach1; 14 - mach2; 15 - mach3; 16 - mach4; 17 - spellbook; 18 - misc5

	ArtSlotInfo & retrieveNewArtSlot(ArtifactPosition slot);
	void setNewArtSlot(ArtifactPosition slot, CArtifactInstance *art, bool locked);
	void eraseArtSlot(ArtifactPosition slot);

	const ArtSlotInfo *getSlot(ArtifactPosition pos) const;
	const CArtifactInstance* getArt(ArtifactPosition pos, bool excludeLocked = true) const; //nullptr - no artifact
	CArtifactInstance* getArt(ArtifactPosition pos, bool excludeLocked = true); //nullptr - no artifact
	/// Looks for equipped artifact with given ID and returns its slot ID or -1 if none
	/// (if more than one such artifact lower ID is returned)
	ArtifactPosition getArtPos(int aid, bool onlyWorn = true) const;
	ArtifactPosition getArtPos(const CArtifactInstance *art) const;
	const CArtifactInstance *getArtByInstanceId(ArtifactInstanceID artInstId) const;
	/// Search for constituents of assemblies in backpack which do not have an ArtifactPosition
	const CArtifactInstance *getHiddenArt(int aid) const;
	const CCombinedArtifactInstance *getAssemblyByConstituent(int aid) const;
	/// Checks if hero possess artifact of given id (either in backack or worn)
	bool hasArt(ui32 aid, bool onlyWorn = false, bool searchBackpackAssemblies = false) const;
	bool isPositionFree(ArtifactPosition pos, bool onlyLockCheck = false) const;

	virtual ArtBearer::ArtBearer bearerType() const = 0;
	virtual void putArtifact(ArtifactPosition pos, CArtifactInstance * art) = 0;
	virtual ~CArtifactSet();

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

	void artDeserializationFix(CBonusSystemNode *node);

	void serializeJsonArtifacts(JsonSerializeFormat & handler, const std::string & fieldName, CMap * map);
protected:


	std::pair<const CCombinedArtifactInstance *, const CArtifactInstance *> searchForConstituent(int aid) const;
private:
	void serializeJsonHero(JsonSerializeFormat & handler, CMap * map);
	void serializeJsonCreature(JsonSerializeFormat & handler, CMap * map);
	void serializeJsonCommander(JsonSerializeFormat & handler, CMap * map);

	void serializeJsonSlot(JsonSerializeFormat & handler, const ArtifactPosition & slot, CMap * map);//normal slots
};