1
0
mirror of https://github.com/vcmi/vcmi.git synced 2024-11-24 08:32:34 +02:00

First part of implementation of some type-specific handlers.

TODO:
- merge dwellings.json into object configs
- proper implementation of overrides for towns
- fully connect new API to RMG/H3M
This commit is contained in:
Ivan Savenko 2014-06-14 18:42:13 +03:00
parent 44742814cd
commit 7cfd9a0903
10 changed files with 350 additions and 74 deletions

View File

@ -4,7 +4,7 @@
"altarOfSacrifice" : { "index" :2, "handler": "market" },
"tradingPost" : { "index" :221, "handler": "market" },
"tradingPostDUPLICATE" : { "index" :99, "handler": "market" },
"tradingPostDUPLICATE" : { "index" :99, "handler": "market" },
"freelancersGuild" : { "index" :213, "handler": "market" },
"blackMarket" : { "index" :7, "handler": "blackMarket" },
@ -93,41 +93,41 @@
"rocklands" : { "index" :231, "handler": "generic" },
/// Decorations
"cactus" : { "index" :116, "handler": "generic" },
"canyon" : { "index" :117, "handler": "generic" },
"crater" : { "index" :118, "handler": "generic" },
"deadVegetation" : { "index" :119, "handler": "generic" },
"flowers" : { "index" :120, "handler": "generic" },
"frozenLake" : { "index" :121, "handler": "generic" },
"hole" : { "index" :124, "handler": "generic" },
"kelp" : { "index" :125, "handler": "generic" },
"lake" : { "index" :126, "handler": "generic" },
"lavaFlow" : { "index" :127, "handler": "generic" },
"lavaLake" : { "index" :128, "handler": "generic" },
"mushrooms" : { "index" :129, "handler": "generic" },
"log" : { "index" :130, "handler": "generic" },
"mandrake" : { "index" :131, "handler": "generic" },
"moss" : { "index" :132, "handler": "generic" },
"mound" : { "index" :133, "handler": "generic" },
"mountain" : { "index" :134, "handler": "generic" },
"oakTrees" : { "index" :135, "handler": "generic" },
"outcropping" : { "index" :136, "handler": "generic" },
"pineTrees" : { "index" :137, "handler": "generic" },
"riverDelta" : { "index" :143, "handler": "generic" },
"rock" : { "index" :147, "handler": "generic" },
"sandDune" : { "index" :148, "handler": "generic" },
"sandPit" : { "index" :149, "handler": "generic" },
"shrub" : { "index" :150, "handler": "generic" },
"skull" : { "index" :151, "handler": "generic" },
"stump" : { "index" :153, "handler": "generic" },
"trees" : { "index" :155, "handler": "generic" },
"volcano" : { "index" :158, "handler": "generic" },
"reef" : { "index" :161, "handler": "generic" },
"lakeDUPLICATE" : { "index" :177, "handler": "generic" },
"treesDUPLICATE" : { "index" :199, "handler": "generic" },
"desertHills" : { "index" :206, "handler": "generic" },
"dirtHills" : { "index" :207, "handler": "generic" },
"grassHills" : { "index" :208, "handler": "generic" },
"roughHills" : { "index" :209, "handler": "generic" },
"subterraneanRocks" : { "index" :210, "handler": "generic" }
"cactus" : { "index" :116, "handler": "static" },
"canyon" : { "index" :117, "handler": "static" },
"crater" : { "index" :118, "handler": "static" },
"deadVegetation" : { "index" :119, "handler": "static" },
"flowers" : { "index" :120, "handler": "static" },
"frozenLake" : { "index" :121, "handler": "static" },
"hole" : { "index" :124, "handler": "static" },
"kelp" : { "index" :125, "handler": "static" },
"lake" : { "index" :126, "handler": "static" },
"lavaFlow" : { "index" :127, "handler": "static" },
"lavaLake" : { "index" :128, "handler": "static" },
"mushrooms" : { "index" :129, "handler": "static" },
"log" : { "index" :130, "handler": "static" },
"mandrake" : { "index" :131, "handler": "static" },
"moss" : { "index" :132, "handler": "static" },
"mound" : { "index" :133, "handler": "static" },
"mountain" : { "index" :134, "handler": "static" },
"oakTrees" : { "index" :135, "handler": "static" },
"outcropping" : { "index" :136, "handler": "static" },
"pineTrees" : { "index" :137, "handler": "static" },
"riverDelta" : { "index" :143, "handler": "static" },
"rock" : { "index" :147, "handler": "static" },
"sandDune" : { "index" :148, "handler": "static" },
"sandPit" : { "index" :149, "handler": "static" },
"shrub" : { "index" :150, "handler": "static" },
"skull" : { "index" :151, "handler": "static" },
"stump" : { "index" :153, "handler": "static" },
"trees" : { "index" :155, "handler": "static" },
"volcano" : { "index" :158, "handler": "static" },
"reef" : { "index" :161, "handler": "static" },
"lakeDUPLICATE" : { "index" :177, "handler": "static" },
"treesDUPLICATE" : { "index" :199, "handler": "static" },
"desertHills" : { "index" :206, "handler": "static" },
"dirtHills" : { "index" :207, "handler": "static" },
"grassHills" : { "index" :208, "handler": "static" },
"roughHills" : { "index" :209, "handler": "static" },
"subterraneanRocks" : { "index" :210, "handler": "static" }
}

View File

@ -56,6 +56,16 @@
"index" :98,
"handler": "town",
"base" : {
"filter" : {
// village image - fort not present
"village" : [ "noneOf", [ "fort" ] ],
// fort image - fort is here but not capitol
"fort" : [ "allOf", [ "fort" ], [ "noneOf", ["capitol" ] ] ],
// capitol image only when capitol is built
"capitol" : [ "capitol" ]
},
// "faction" : "stringID", // should be set by engine
"base" : {
"visitableFrom" : [ "---", "+++", "+++" ],
"mask" : [

View File

@ -27,6 +27,7 @@ set(lib_SRCS
mapObjects/CGTownInstance.cpp
mapObjects/CObjectClassesHandler.cpp
mapObjects/CObjectHandler.cpp
mapObjects/CommonConstructors.cpp
mapObjects/CQuest.cpp
mapObjects/CRewardableConstructor.cpp
mapObjects/CRewardableObject.cpp

View File

@ -11,6 +11,7 @@
#include "../JsonNode.h"
#include "CRewardableConstructor.h"
#include "CommonConstructors.h"
#include "MapObjects.h"
/*
@ -31,10 +32,14 @@ CObjectClassesHandler::CObjectClassesHandler()
// list of all known handlers, hardcoded for now since the only way to add new objects is via C++ code
//WARNING: should be in sync with registerTypesMapObjectTypes function
SET_HANDLER_CLASS("configurable", CRewardableConstructor);
SET_HANDLER_CLASS("dwelling", CDwellingInstanceConstructor);
SET_HANDLER_CLASS("hero", CHeroInstanceConstructor);
SET_HANDLER_CLASS("town", CTownInstanceConstructor);
SET_HANDLER_CLASS("static", CObstacleConstructor);
SET_HANDLER_CLASS("", CObstacleConstructor);
SET_HANDLER("", CGObjectInstance);
SET_HANDLER("generic", CGObjectInstance);
SET_HANDLER("market", CGMarket);
SET_HANDLER("bank", CBank);
SET_HANDLER("cartographer", CCartographer);
@ -46,10 +51,8 @@ CObjectClassesHandler::CObjectClassesHandler()
SET_HANDLER("borderGuard", CGBorderGuard);
SET_HANDLER("monster", CGCreature);
SET_HANDLER("denOfThieves", CGDenOfthieves);
SET_HANDLER("dwelling", CGDwelling);
SET_HANDLER("event", CGEvent);
SET_HANDLER("garrison", CGGarrison);
SET_HANDLER("hero", CGHeroInstance);
SET_HANDLER("heroPlaceholder", CGHeroPlaceholder);
SET_HANDLER("keymaster", CGKeymasterTent);
SET_HANDLER("lighthouse", CGLighthouse);
@ -73,7 +76,6 @@ CObjectClassesHandler::CObjectClassesHandler()
SET_HANDLER("sign", CGSignBottle);
SET_HANDLER("siren", CGSirens);
SET_HANDLER("teleport", CGTeleport);
SET_HANDLER("town", CGTownInstance);
SET_HANDLER("university", CGUniversity);
SET_HANDLER("oncePerHero", CGVisitableOPH);
SET_HANDLER("oncePerWeek", CGVisitableOPW);
@ -197,7 +199,7 @@ void CObjectClassesHandler::loadSubObject(std::string name, JsonNode config, si3
}
JsonUtils::inherit(config, objects.at(ID)->base);
logGlobal->errorStream() << "JSON: " << config;
loadObjectEntry(config, objects[ID]);
}
@ -265,6 +267,7 @@ void CObjectClassesHandler::afterLoadFinalization()
{
for (auto obj : entry.second->objects)
{
obj.second->afterLoadFinalization();
if (obj.second->getTemplates().empty())
logGlobal->warnStream() << "No templates found for " << entry.first << ":" << obj.first;
}
@ -315,6 +318,7 @@ void AObjectTypeHandler::init(const JsonNode & input)
tmpl.readJson(entry.second);
templates.push_back(tmpl);
}
initTypeData(input);
}
bool AObjectTypeHandler::objectFilter(const CGObjectInstance *, const ObjectTemplate &) const
@ -322,6 +326,10 @@ bool AObjectTypeHandler::objectFilter(const CGObjectInstance *, const ObjectTemp
return false; // by default there are no overrides
}
void AObjectTypeHandler::initTypeData(const JsonNode & input)
{
}
void AObjectTypeHandler::addTemplate(ObjectTemplate templ)
{
templ.id = Obj(type);
@ -331,6 +339,9 @@ void AObjectTypeHandler::addTemplate(ObjectTemplate templ)
void AObjectTypeHandler::addTemplate(JsonNode config)
{
logGlobal->errorStream() << "INPUT FOR: " << type << ":" << subtype << " " << config;
logGlobal->errorStream() << "BASE FOR: " << type << ":" << subtype << " " << base;
config.setType(JsonNode::DATA_STRUCT); // ensure that input is not null
JsonUtils::inherit(config, base);
ObjectTemplate tmpl;
@ -338,6 +349,7 @@ void AObjectTypeHandler::addTemplate(JsonNode config)
tmpl.subid = subtype;
tmpl.stringID = ""; // TODO?
tmpl.readJson(config);
logGlobal->errorStream() << "DATA FOR: " << type << ":" << subtype << " " << config;
addTemplate(tmpl);
}
@ -374,3 +386,12 @@ const RandomMapInfo & AObjectTypeHandler::getRMGInfo()
{
return rmgInfo;
}
bool AObjectTypeHandler::isStaticObject()
{
return false; // most of classes are not static
}
void AObjectTypeHandler::afterLoadFinalization()
{
}

View File

@ -81,13 +81,16 @@ class AObjectTypeHandler
protected:
virtual bool objectFilter(const CGObjectInstance *, const ObjectTemplate &) const;
/// initialization for classes that inherit this one
virtual void initTypeData(const JsonNode & input);
public:
virtual ~AObjectTypeHandler(){}
void setType(si32 type, si32 subtype);
/// loads generic data from Json structure
virtual void init(const JsonNode & input);
/// loads generic data from Json structure and passes it towards type-specific constructors
void init(const JsonNode & input);
void addTemplate(ObjectTemplate templ);
void addTemplate(JsonNode config);
@ -102,11 +105,16 @@ public:
const RandomMapInfo & getRMGInfo();
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(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. Othervice returns NULL
@ -118,29 +126,6 @@ public:
}
};
/// Class that is used for objects that do not have dedicated handler
template<class ObjectType>
class CDefaultObjectTypeHandler : public AObjectTypeHandler
{
CGObjectInstance * create(ObjectTemplate tmpl) const
{
auto obj = new ObjectType();
obj->ID = tmpl.id;
obj->subID = tmpl.subid;
obj->appearance = tmpl;
return obj;
}
virtual void configureObject(CGObjectInstance * object, CRandomGenerator & rng) const
{
}
virtual const IObjectInfo * getObjectInfo(ObjectTemplate tmpl) const
{
return nullptr;
}
};
typedef std::shared_ptr<AObjectTypeHandler> TObjectTypeHandler;
class DLL_LINKAGE CObjectClassesHandler : public IHandlerBase

View File

@ -266,7 +266,7 @@ CRewardableConstructor::CRewardableConstructor()
{
}
void CRewardableConstructor::init(const JsonNode & config)
void CRewardableConstructor::initTypeData(const JsonNode & config)
{
AObjectTypeHandler::init(config);
objectInfo.init(config);

View File

@ -46,9 +46,9 @@ class CRewardableConstructor : public AObjectTypeHandler
{
CRandomRewardObjectInfo objectInfo;
void initTypeData(const JsonNode & config) override;
public:
CRewardableConstructor();
void init(const JsonNode & config) override;
CGObjectInstance * create(ObjectTemplate tmpl) const override;

View File

@ -0,0 +1,153 @@
#include "StdInc.h"
#include "CommonConstructors.h"
#include "CGTownInstance.h"
#include "CGHeroInstance.h"
#include "../mapping/CMap.h"
#include "../CHeroHandler.h"
#include "../CCreatureHandler.h"
/*
* CommonConstructors.cpp, 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
*
*/
CObstacleConstructor::CObstacleConstructor()
{
}
bool CObstacleConstructor::isStaticObject()
{
return true;
}
CTownInstanceConstructor::CTownInstanceConstructor()
{
}
void CTownInstanceConstructor::initTypeData(const JsonNode & input)
{
VLC->modh->identifiers.requestIdentifier("faction", input["faction"],
[&](si32 index) { faction = VLC->townh->factions[index]; });
filtersJson = input["filters"];
}
void CTownInstanceConstructor::afterLoadFinalization()
{
for (auto entry : filtersJson.Struct())
{
filters[entry.first] = LogicalExpression<BuildingID>(entry.second, [&](const JsonNode & node)
{
return BuildingID(VLC->modh->identifiers.getIdentifier("building." + faction->identifier, node.Vector()[0]).get());
});
}
}
bool CTownInstanceConstructor::objectFilter(const CGObjectInstance * object, const ObjectTemplate & templ) const
{
auto town = dynamic_cast<const CGTownInstance *>(object);
auto buildTest = [&](const BuildingID & id)
{
return town->hasBuilt(id);
};
if (filters.count(templ.stringID))
return filters.at(templ.stringID).test(buildTest);
return false;
}
CGObjectInstance * CTownInstanceConstructor::create(ObjectTemplate tmpl) const
{
CGTownInstance * obj = createTyped(tmpl);
obj->town = faction->town;
obj->tempOwner = PlayerColor::NEUTRAL;
return obj;
}
void CTownInstanceConstructor::configureObject(CGObjectInstance * object, CRandomGenerator & rng) const
{
auto templ = getOverride(object->cb->getTile(object->pos)->terType, object);
if (templ)
object->appearance = templ.get();
}
CHeroInstanceConstructor::CHeroInstanceConstructor()
{
}
void CHeroInstanceConstructor::initTypeData(const JsonNode & input)
{
VLC->modh->identifiers.requestIdentifier("heroClass", input["heroClass"],
[&](si32 index) { heroClass = VLC->heroh->classes.heroClasses[index]; });
}
bool CHeroInstanceConstructor::objectFilter(const CGObjectInstance * object, const ObjectTemplate & templ) const
{
return false;
}
CGObjectInstance * CHeroInstanceConstructor::create(ObjectTemplate tmpl) const
{
CGHeroInstance * obj = createTyped(tmpl);
obj->type = nullptr; //FIXME: set to valid value. somehow.
return obj;
}
void CHeroInstanceConstructor::configureObject(CGObjectInstance * object, CRandomGenerator & rng) const
{
}
CDwellingInstanceConstructor::CDwellingInstanceConstructor()
{
}
void CDwellingInstanceConstructor::initTypeData(const JsonNode & input)
{
const JsonVector & levels = input["creatures"].Vector();
availableCreatures.resize(levels.size());
for (size_t i=0; i<levels.size(); i++)
{
const JsonVector & creatures = levels[i].Vector();
availableCreatures[i].resize(creatures.size());
for (size_t j=0; j<creatures.size(); j++)
{
VLC->modh->identifiers.requestIdentifier("creature", creatures[j], [&] (si32 index)
{
availableCreatures[i][j] = VLC->creh->creatures[index];
});
}
}
}
bool CDwellingInstanceConstructor::objectFilter(const CGObjectInstance *, const ObjectTemplate &) const
{
return false;
}
CGObjectInstance * CDwellingInstanceConstructor::create(ObjectTemplate tmpl) const
{
CGDwelling * obj = createTyped(tmpl);
for (auto entry : availableCreatures)
{
obj->creatures.resize(obj->creatures.size()+1);
for (const CCreature * cre : entry)
obj->creatures.back().second.push_back(cre->idNumber);
}
return obj;
}
void CDwellingInstanceConstructor::configureObject(CGObjectInstance * object, CRandomGenerator & rng) const
{
}

View File

@ -0,0 +1,104 @@
#pragma once
#include "CObjectClassesHandler.h"
#include "../CTownHandler.h" // for building ID-based filters
/*
* CommonConstructors.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
*
*/
class CGTownInstance;
class CGHeroInstance;
class CGDwelling;
//class CGArtifact;
//class CGCreature;
class CHeroClass;
/// Class that is used for objects that do not have dedicated handler
template<class ObjectType>
class CDefaultObjectTypeHandler : public AObjectTypeHandler
{
protected:
ObjectType * createTyped(ObjectTemplate tmpl) const
{
auto obj = new ObjectType();
obj->ID = tmpl.id;
obj->subID = tmpl.subid;
obj->appearance = tmpl;
return obj;
}
public:
CDefaultObjectTypeHandler(){}
CGObjectInstance * create(ObjectTemplate tmpl) const
{
return createTyped(tmpl);
}
virtual void configureObject(CGObjectInstance * object, CRandomGenerator & rng) const
{
}
virtual const IObjectInfo * getObjectInfo(ObjectTemplate tmpl) const
{
return nullptr;
}
};
class CObstacleConstructor : public CDefaultObjectTypeHandler<CGObjectInstance>
{
public:
CObstacleConstructor();
bool isStaticObject();
};
class CTownInstanceConstructor : public CDefaultObjectTypeHandler<CGTownInstance>
{
JsonNode filtersJson;
protected:
bool objectFilter(const CGObjectInstance *, const ObjectTemplate &) const;
public:
CFaction * faction;
std::map<std::string, LogicalExpression<BuildingID>> filters;
CTownInstanceConstructor();
CGObjectInstance * create(ObjectTemplate tmpl) const;
void initTypeData(const JsonNode & input);
void configureObject(CGObjectInstance * object, CRandomGenerator & rng) const;
void afterLoadFinalization();
};
class CHeroInstanceConstructor : public CDefaultObjectTypeHandler<CGHeroInstance>
{
protected:
bool objectFilter(const CGObjectInstance *, const ObjectTemplate &) const;
public:
CHeroClass * heroClass;
CHeroInstanceConstructor();
CGObjectInstance * create(ObjectTemplate tmpl) const;
void initTypeData(const JsonNode & input);
void configureObject(CGObjectInstance * object, CRandomGenerator & rng) const;
};
class CDwellingInstanceConstructor : public CDefaultObjectTypeHandler<CGDwelling>
{
protected:
bool objectFilter(const CGObjectInstance *, const ObjectTemplate &) const;
public:
std::vector<std::vector<CCreature *>> availableCreatures;
CDwellingInstanceConstructor();
CGObjectInstance * create(ObjectTemplate tmpl) const;
void initTypeData(const JsonNode & input);
void configureObject(CGObjectInstance * object, CRandomGenerator & rng) const;
};

View File

@ -10,6 +10,7 @@
#include "../CModHandler.h" //needed?
#include "../mapObjects/CObjectClassesHandler.h"
#include "../mapObjects/CRewardableConstructor.h"
#include "../mapObjects/CommonConstructors.h"
#include "../mapObjects/MapObjects.h"
/*
@ -77,6 +78,10 @@ template<typename Serializer>
void registerTypesMapObjectTypes(Serializer &s)
{
s.template registerType<AObjectTypeHandler, CRewardableConstructor>();
s.template registerType<AObjectTypeHandler, CHeroInstanceConstructor>();
s.template registerType<AObjectTypeHandler, CTownInstanceConstructor>();
s.template registerType<AObjectTypeHandler, CDwellingInstanceConstructor>();
s.template registerType<AObjectTypeHandler, CObstacleConstructor>();
#define REGISTER_GENERIC_HANDLER(TYPENAME) s.template registerType<AObjectTypeHandler, CDefaultObjectTypeHandler<TYPENAME> >()
@ -92,10 +97,8 @@ void registerTypesMapObjectTypes(Serializer &s)
REGISTER_GENERIC_HANDLER(CGBorderGuard);
REGISTER_GENERIC_HANDLER(CGCreature);
REGISTER_GENERIC_HANDLER(CGDenOfthieves);
REGISTER_GENERIC_HANDLER(CGDwelling);
REGISTER_GENERIC_HANDLER(CGEvent);
REGISTER_GENERIC_HANDLER(CGGarrison);
REGISTER_GENERIC_HANDLER(CGHeroInstance);
REGISTER_GENERIC_HANDLER(CGHeroPlaceholder);
REGISTER_GENERIC_HANDLER(CGKeymasterTent);
REGISTER_GENERIC_HANDLER(CGLighthouse);
@ -119,7 +122,6 @@ void registerTypesMapObjectTypes(Serializer &s)
REGISTER_GENERIC_HANDLER(CGSignBottle);
REGISTER_GENERIC_HANDLER(CGSirens);
REGISTER_GENERIC_HANDLER(CGTeleport);
REGISTER_GENERIC_HANDLER(CGTownInstance);
REGISTER_GENERIC_HANDLER(CGUniversity);
REGISTER_GENERIC_HANDLER(CGVisitableOPH);
REGISTER_GENERIC_HANDLER(CGVisitableOPW);