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
|
/*
* 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"
#include "Terrain.h"
VCMI_LIB_NAMESPACE_BEGIN
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<std::shared_ptr<const ObjectTemplate>> templates;
SObjectSounds sounds;
boost::optional<si32> aiValue;
boost::optional<std::string> battlefield;
protected:
void preInitObject(CGObjectInstance * obj) const;
virtual bool objectFilter(const CGObjectInstance *, std::shared_ptr<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(std::shared_ptr<const ObjectTemplate> templ);
void addTemplate(JsonNode config);
/// returns all templates matching parameters
std::vector<std::shared_ptr<const ObjectTemplate>> getTemplates() const;
std::vector<std::shared_ptr<const ObjectTemplate>> getTemplates(const TerrainId 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)
std::shared_ptr<const ObjectTemplate> getOverride(TerrainId terrainType, const CGObjectInstance * object) const;
BattleField getBattlefield() 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)
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(std::shared_ptr<const ObjectTemplate> tmpl = nullptr) 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(std::shared_ptr<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;
h & typeName;
h & subTypeName;
h & sounds;
h & aiValue;
h & battlefield;
}
};
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;
h & identifier;
h & subIds;
h & sounds;
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>, std::shared_ptr<const 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, bool isSubobject = false);
ObjectContainter * loadFromJson(const std::string & scope, 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 scope, 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;
}
};
VCMI_LIB_NAMESPACE_END
|