File: CObjectClassesHandler.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 (329 lines) | stat: -rw-r--r-- 9,755 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
/*
 * CObjectClassesHandler.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 "ObjectTemplate.h"

#include "../GameConstants.h"
#include "../ConstTransitivePtr.h"
#include "../IHandlerBase.h"
#include "../JsonNode.h"

class JsonNode;
class CRandomGenerator;


struct SObjectSounds
{
	std::vector<std::string> ambient;
	std::vector<std::string> visit;
	std::vector<std::string> removal;

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

/// Structure that describes placement rules for this object in random map
struct DLL_LINKAGE RandomMapInfo
{
	/// How valuable this object is, 1k = worthless, 10k = Utopia-level
	ui32 value;

	/// How many of such objects can be placed on map, 0 = object can not be placed by RMG
	ui32 mapLimit;

	/// How many of such objects can be placed in one zone, 0 = unplaceable
	ui32 zoneLimit;

	/// Rarity of object, 5 = extremely rare, 100 = common
	ui32 rarity;

	RandomMapInfo():
		value(0),
		mapLimit(0),
		zoneLimit(0),
		rarity(0)
	{}

	template <typename Handler> void serialize(Handler &h, const int version)
	{
		h & value;
		h & mapLimit;
		h & zoneLimit;
		h & rarity;
	}
};

struct DLL_LINKAGE CompoundMapObjectID
{
	si32 primaryID;
	si32 secondaryID;

	CompoundMapObjectID(si32 primID, si32 secID) : primaryID(primID), secondaryID(secID) {};

	bool operator<(const CompoundMapObjectID& other) const
	{
		if(this->primaryID != other.primaryID)
			return this->primaryID < other.primaryID;
		else
			return this->secondaryID < other.secondaryID;
	}

	bool operator==(const CompoundMapObjectID& other) const
	{
		return (this->primaryID == other.primaryID) && (this->secondaryID == other.secondaryID);
	}
};

class DLL_LINKAGE IObjectInfo
{
public:
	struct CArmyStructure
	{
		ui32 totalStrength;
		ui32 shootersStrength;
		ui32 flyersStrength;
		ui32 walkersStrength;

		CArmyStructure() :
			totalStrength(0),
			shootersStrength(0),
			flyersStrength(0),
			walkersStrength(0)
		{}

		bool operator <(const CArmyStructure & other) const
		{
			return this->totalStrength < other.totalStrength;
		}
	};

	/// Returns possible composition of guards. Actual guards would be
	/// somewhere between these two values
	virtual CArmyStructure minGuards() const { return CArmyStructure(); }
	virtual CArmyStructure maxGuards() const { return CArmyStructure(); }

	virtual bool givesResources() const { return false; }

	virtual bool givesExperience() const { return false; }
	virtual bool givesMana() const { return false; }
	virtual bool givesMovement() const { return false; }

	virtual bool givesPrimarySkills() const { return false; }
	virtual bool givesSecondarySkills() const { return false; }

	virtual bool givesArtifacts() const { return false; }
	virtual bool givesCreatures() const { return false; }
	virtual bool givesSpells() const { return false; }

	virtual bool givesBonuses() const { return false; }

	virtual ~IObjectInfo() = default;
};

class CGObjectInstance;

class DLL_LINKAGE AObjectTypeHandler : public boost::noncopyable
{
	RandomMapInfo rmgInfo;

	/// Human-readable name of this object, used for objects like banks and dwellings, if set
	boost::optional<std::string> objectName;

	JsonNode base; /// describes base template

	std::vector<ObjectTemplate> templates;

	SObjectSounds sounds;

	boost::optional<si32> aiValue;
protected:
	void preInitObject(CGObjectInstance * obj) const;
	virtual bool objectFilter(const CGObjectInstance *, const ObjectTemplate &) const;

	/// initialization for classes that inherit this one
	virtual void initTypeData(const JsonNode & input);
public:
	std::string typeName;
	std::string subTypeName;

	si32 type;
	si32 subtype;
	AObjectTypeHandler();
	virtual ~AObjectTypeHandler();

	void setType(si32 type, si32 subtype);
	void setTypeName(std::string type, std::string subtype);

	/// loads generic data from Json structure and passes it towards type-specific constructors
	void init(const JsonNode & input, boost::optional<std::string> name = boost::optional<std::string>());

	/// Returns object-specific name, if set
	boost::optional<std::string> getCustomName() const;
	SObjectSounds getSounds() const;

	void addTemplate(const ObjectTemplate & templ);
	void addTemplate(JsonNode config);

	/// returns all templates matching parameters
	std::vector<ObjectTemplate> getTemplates() const;
	std::vector<ObjectTemplate> getTemplates(si32 terrainType) const;

	/// returns preferred template for this object, if present (e.g. one of 3 possible templates for town - village, fort and castle)
	/// note that appearance will not be changed - this must be done separately (either by assignment or via pack from server)
	boost::optional<ObjectTemplate> getOverride(si32 terrainType, const CGObjectInstance * object) const;

	const RandomMapInfo & getRMGInfo();

	boost::optional<si32> getAiValue() const;

	virtual bool isStaticObject();

	virtual void afterLoadFinalization();

	/// Creates object and set up core properties (like ID/subID). Object is NOT initialized
	/// to allow creating objects before game start (e.g. map loading)
	virtual CGObjectInstance * create(const ObjectTemplate & tmpl) const = 0;

	/// Configures object properties. Should be re-entrable, resetting state of the object if necessarily
	/// This should set remaining properties, including randomized or depending on map
	virtual void configureObject(CGObjectInstance * object, CRandomGenerator & rng) const = 0;

	/// Returns object configuration, if available. Otherwise returns NULL
	virtual std::unique_ptr<IObjectInfo> getObjectInfo(const ObjectTemplate & tmpl) const = 0;

	template <typename Handler> void serialize(Handler &h, const int version)
	{
		h & type;
		h & subtype;
		h & templates;
		h & rmgInfo;
		h & objectName;
		if(version >= 759)
		{
			h & typeName;
			h & subTypeName;
		}
		if(version >= 778)
		{
			h & sounds;
		}
		if(version >= 789)
		{
			h & aiValue;
		}
	}
};

typedef std::shared_ptr<AObjectTypeHandler> TObjectTypeHandler;

class DLL_LINKAGE CObjectClassesHandler : public IHandlerBase
{
	/// Small internal structure that contains information on specific group of objects
	/// (creating separate entity is overcomplicating at least at this point)
	struct ObjectContainter
	{
		si32 id;
		std::string identifier;
		std::string name; // human-readable name
		std::string handlerName; // ID of handler that controls this object, should be determined using handlerConstructor map

		JsonNode base;
		std::map<si32, TObjectTypeHandler> subObjects;
		std::map<std::string, si32> subIds;//full id from core scope -> subtype

		SObjectSounds sounds;

		boost::optional<si32> groupDefaultAiValue;

		template <typename Handler> void serialize(Handler &h, const int version)
		{
			h & name;
			h & handlerName;
			h & base;
			h & subObjects;
			if(version >= 759)
			{
				h & identifier;
				h & subIds;
			}
			if(version >= 778)
			{
				h & sounds;
			}
			if(version >= 789)
			{
				h & groupDefaultAiValue;
			}
		}
	};

	/// list of object handlers, each of them handles only one type
	std::map<si32, ObjectContainter * > objects;

	/// map that is filled during contruction with all known handlers. Not serializeable due to usage of std::function
	std::map<std::string, std::function<TObjectTypeHandler()> > handlerConstructors;

	/// container with H3 templates, used only during loading, no need to serialize it
	typedef std::multimap<std::pair<si32, si32>, ObjectTemplate> TTemplatesContainer;
	TTemplatesContainer legacyTemplates;

	/// contains list of custom names for H3 objects (e.g. Dwellings), used to load H3 data
	/// format: customNames[primaryID][secondaryID] -> name
	std::map<si32, std::vector<std::string>> customNames;

	void loadObjectEntry(const std::string & identifier, const JsonNode & entry, ObjectContainter * obj);
	ObjectContainter * loadFromJson(const JsonNode & json, const std::string & name);
public:
	CObjectClassesHandler();
	~CObjectClassesHandler();

	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 loadSubObject(const std::string & identifier, JsonNode config, si32 ID, boost::optional<si32> subID = boost::optional<si32>());
	void removeSubObject(si32 ID, si32 subID);

	void beforeValidate(JsonNode & object) override;
	void afterLoadFinalization() override;

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

	/// Queries to detect loaded objects
	std::set<si32> knownObjects() const;
	std::set<si32> knownSubObjects(si32 primaryID) const;

	/// returns handler for specified object (ID-based). ObjectHandler keeps ownership
	TObjectTypeHandler getHandlerFor(si32 type, si32 subtype) const;
	TObjectTypeHandler getHandlerFor(std::string type, std::string subtype) const;
	TObjectTypeHandler getHandlerFor(CompoundMapObjectID compoundIdentifier) const;

	std::string getObjectName(si32 type) const;
	std::string getObjectName(si32 type, si32 subtype) const;

	SObjectSounds getObjectSounds(si32 type) const;
	SObjectSounds getObjectSounds(si32 type, si32 subtype) const;

	/// Returns handler string describing the handler (for use in client)
	std::string getObjectHandlerName(si32 type) const;

	boost::optional<si32> getObjGroupAiValue(si32 primaryID) const; //default AI value of objects belonging to particular primaryID

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