mirror of
https://github.com/vcmi/vcmi.git
synced 2025-01-26 03:52:01 +02:00
Finalization of object type handler interface
- updated code to use new interface - removed old DefObjHandler (todo - rename file) Summary: - most code but loading is now in place - type names may deserve improvements (some of them are too similar) - still barely compiles and not tested
This commit is contained in:
parent
d805376ab8
commit
b5160acbac
@ -31,5 +31,5 @@ void CGameInfo::setFromLib()
|
|||||||
heroh = VLC->heroh;
|
heroh = VLC->heroh;
|
||||||
objh = VLC->objh;
|
objh = VLC->objh;
|
||||||
spellh = VLC->spellh;
|
spellh = VLC->spellh;
|
||||||
dobjinfo = VLC->dobjinfo;
|
objtypeh = VLC->objtypeh;
|
||||||
}
|
}
|
||||||
|
@ -23,7 +23,7 @@ class CBuildingHandler;
|
|||||||
class CObjectHandler;
|
class CObjectHandler;
|
||||||
class CSoundHandler;
|
class CSoundHandler;
|
||||||
class CMusicHandler;
|
class CMusicHandler;
|
||||||
class CDefObjInfoHandler;
|
class CObjectTypesHandler;
|
||||||
class CTownHandler;
|
class CTownHandler;
|
||||||
class CGeneralTextHandler;
|
class CGeneralTextHandler;
|
||||||
class CConsoleHandler;
|
class CConsoleHandler;
|
||||||
@ -57,11 +57,10 @@ public:
|
|||||||
ConstTransitivePtr<CCreatureHandler> creh;
|
ConstTransitivePtr<CCreatureHandler> creh;
|
||||||
ConstTransitivePtr<CSpellHandler> spellh;
|
ConstTransitivePtr<CSpellHandler> spellh;
|
||||||
ConstTransitivePtr<CObjectHandler> objh;
|
ConstTransitivePtr<CObjectHandler> objh;
|
||||||
ConstTransitivePtr<CDefObjInfoHandler> dobjinfo;
|
ConstTransitivePtr<CObjectTypesHandler> objtypeh;
|
||||||
CGeneralTextHandler * generaltexth;
|
CGeneralTextHandler * generaltexth;
|
||||||
CMapHandler * mh;
|
CMapHandler * mh;
|
||||||
CTownHandler * townh;
|
CTownHandler * townh;
|
||||||
//CTownHandler * townh;
|
|
||||||
|
|
||||||
void setFromLib();
|
void setFromLib();
|
||||||
|
|
||||||
|
@ -648,7 +648,7 @@ void CArtHandler::afterLoadFinalization()
|
|||||||
}
|
}
|
||||||
|
|
||||||
//Note: "10" is used here because H3 text files don't define any template for art with ID 0
|
//Note: "10" is used here because H3 text files don't define any template for art with ID 0
|
||||||
ObjectTemplate base = VLC->dobjinfo->pickCandidates(Obj::ARTIFACT, 10).front();
|
ObjectTemplate base = VLC->objtypeh->getHandlerFor(Obj::ARTIFACT, 10)->getTemplates().front();
|
||||||
for (CArtifact * art : artifacts)
|
for (CArtifact * art : artifacts)
|
||||||
{
|
{
|
||||||
if (!art->advMapDef.empty())
|
if (!art->advMapDef.empty())
|
||||||
@ -656,10 +656,9 @@ void CArtHandler::afterLoadFinalization()
|
|||||||
base.animationFile = art->advMapDef;
|
base.animationFile = art->advMapDef;
|
||||||
base.subid = art->id;
|
base.subid = art->id;
|
||||||
|
|
||||||
// replace existing (if any) and add new template.
|
// add new template.
|
||||||
// Necessary for objects added via mods that don't have any templates in H3
|
// Necessary for objects added via mods that don't have any templates in H3
|
||||||
VLC->dobjinfo->eraseAll(Obj::ARTIFACT, art->id);
|
VLC->objtypeh->getHandlerFor(Obj::ARTIFACT, art->id)->addTemplate(base);
|
||||||
VLC->dobjinfo->registerTemplate(base);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1114,7 +1114,7 @@ void CCreatureHandler::buildBonusTreeForTiers()
|
|||||||
|
|
||||||
void CCreatureHandler::afterLoadFinalization()
|
void CCreatureHandler::afterLoadFinalization()
|
||||||
{
|
{
|
||||||
ObjectTemplate base = VLC->dobjinfo->pickCandidates(Obj::MONSTER, 0).front();
|
ObjectTemplate base = VLC->objtypeh->getHandlerFor(Obj::MONSTER, 0)->getTemplates().front();
|
||||||
for (CCreature * crea : creatures)
|
for (CCreature * crea : creatures)
|
||||||
{
|
{
|
||||||
if (!crea->advMapDef.empty())
|
if (!crea->advMapDef.empty())
|
||||||
@ -1124,8 +1124,7 @@ void CCreatureHandler::afterLoadFinalization()
|
|||||||
|
|
||||||
// replace existing (if any) and add new template.
|
// replace existing (if any) and add new template.
|
||||||
// Necessary for objects added via mods that don't have any templates in H3
|
// Necessary for objects added via mods that don't have any templates in H3
|
||||||
VLC->dobjinfo->eraseAll(Obj::MONSTER, crea->idNumber);
|
VLC->objtypeh->getHandlerFor(Obj::MONSTER, crea->idNumber)->addTemplate(base);
|
||||||
VLC->dobjinfo->registerTemplate(base);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,6 +7,7 @@
|
|||||||
#include "GameConstants.h"
|
#include "GameConstants.h"
|
||||||
#include "StringConstants.h"
|
#include "StringConstants.h"
|
||||||
#include "CGeneralTextHandler.h"
|
#include "CGeneralTextHandler.h"
|
||||||
|
#include "CObjectHandler.h"
|
||||||
#include "CModHandler.h"
|
#include "CModHandler.h"
|
||||||
#include "JsonNode.h"
|
#include "JsonNode.h"
|
||||||
|
|
||||||
@ -327,7 +328,7 @@ bool ObjectTemplate::canBePlacedAt(ETerrainType terrain) const
|
|||||||
{
|
{
|
||||||
return allowedTerrains.count(terrain) != 0;
|
return allowedTerrains.count(terrain) != 0;
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
void CDefObjInfoHandler::readTextFile(std::string path)
|
void CDefObjInfoHandler::readTextFile(std::string path)
|
||||||
{
|
{
|
||||||
CLegacyConfigParser parser(path);
|
CLegacyConfigParser parser(path);
|
||||||
@ -347,81 +348,82 @@ CDefObjInfoHandler::CDefObjInfoHandler()
|
|||||||
{
|
{
|
||||||
readTextFile("Data/Objects.txt");
|
readTextFile("Data/Objects.txt");
|
||||||
readTextFile("Data/Heroes.txt");
|
readTextFile("Data/Heroes.txt");
|
||||||
/*
|
}
|
||||||
// TODO: merge into modding system
|
|
||||||
JsonNode node = JsonUtils::assembleFromFiles("config/objectTemplates.json");
|
|
||||||
node.setMeta("core");
|
|
||||||
std::vector<ObjectTemplate> newTemplates;
|
|
||||||
newTemplates.reserve(node.Struct().size());
|
|
||||||
|
|
||||||
// load all new templates
|
|
||||||
for (auto & entry : node.Struct())
|
|
||||||
{
|
|
||||||
JsonUtils::validate(entry.second, "vcmi:objectTemplate", entry.first);
|
|
||||||
|
|
||||||
ObjectTemplate templ;
|
|
||||||
templ.stringID = entry.first;
|
|
||||||
templ.readJson(entry.second);
|
|
||||||
newTemplates.push_back(templ);
|
|
||||||
}
|
|
||||||
|
|
||||||
// erase old ones to avoid conflicts
|
|
||||||
for (auto & entry : newTemplates)
|
|
||||||
eraseAll(entry.id, entry.subid);
|
|
||||||
|
|
||||||
// merge new templates into storage
|
|
||||||
objects.insert(objects.end(), newTemplates.begin(), newTemplates.end());
|
|
||||||
*/
|
*/
|
||||||
|
void CObjectTypesHandler::init()
|
||||||
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CDefObjInfoHandler::eraseAll(Obj type, si32 subtype)
|
TObjectTypeHandler CObjectTypesHandler::getHandlerFor(si32 type, si32 subtype) const
|
||||||
{
|
{
|
||||||
auto it = std::remove_if(objects.begin(), objects.end(), [&](const ObjectTemplate & obj)
|
if (objectTypes.count(type))
|
||||||
{
|
{
|
||||||
return obj.id == type && obj.subid == subtype;
|
if (objectTypes.at(type).count(subtype))
|
||||||
});
|
return objectTypes.at(type).at(subtype);
|
||||||
objects.erase(it, objects.end());
|
}
|
||||||
|
assert(0); // FIXME: throw error?
|
||||||
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CDefObjInfoHandler::registerTemplate(ObjectTemplate obj)
|
void AObjectTypeHandler::init(si32 type, si32 subtype)
|
||||||
{
|
{
|
||||||
objects.push_back(obj);
|
this->type = type;
|
||||||
|
this->subtype = subtype;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<ObjectTemplate> CDefObjInfoHandler::pickCandidates(Obj type, si32 subtype) const
|
void AObjectTypeHandler::load(const JsonNode & input)
|
||||||
{
|
{
|
||||||
std::vector<ObjectTemplate> ret;
|
for (auto entry : input["templates"].Struct())
|
||||||
|
|
||||||
std::copy_if(objects.begin(), objects.end(), std::back_inserter(ret), [&](const ObjectTemplate & obj)
|
|
||||||
{
|
{
|
||||||
return obj.id == type && obj.subid == subtype;
|
JsonNode data = input["base"];
|
||||||
});
|
JsonUtils::merge(data, entry.second);
|
||||||
if (ret.empty())
|
|
||||||
logGlobal->errorStream() << "Failed to find template for " << type << ":" << subtype;
|
|
||||||
|
|
||||||
assert(!ret.empty()); // Can't create object of this type/subtype
|
ObjectTemplate tmpl;
|
||||||
return ret;
|
tmpl.id = Obj(type);
|
||||||
|
tmpl.subid = subtype;
|
||||||
|
tmpl.stringID = entry.first; // FIXME: create "fullID" - type.object.template?
|
||||||
|
tmpl.readJson(data);
|
||||||
|
templates.push_back(tmpl);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<ObjectTemplate> CDefObjInfoHandler::pickCandidates(Obj type, si32 subtype, ETerrainType terrain) const
|
bool AObjectTypeHandler::objectFilter(const CGObjectInstance *, const ObjectTemplate &) const
|
||||||
{
|
{
|
||||||
std::vector<ObjectTemplate> ret = pickCandidates(type, subtype);
|
return true; // by default - accept all.
|
||||||
|
}
|
||||||
|
|
||||||
|
void AObjectTypeHandler::addTemplate(const ObjectTemplate & templ)
|
||||||
|
{
|
||||||
|
templates.push_back(templ);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<ObjectTemplate> AObjectTypeHandler::getTemplates() const
|
||||||
|
{
|
||||||
|
return templates;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<ObjectTemplate> AObjectTypeHandler::getTemplates(si32 terrainType) const// FIXME: replace with ETerrainType
|
||||||
|
{
|
||||||
|
std::vector<ObjectTemplate> ret = getTemplates();
|
||||||
std::vector<ObjectTemplate> filtered;
|
std::vector<ObjectTemplate> filtered;
|
||||||
|
|
||||||
std::copy_if(ret.begin(), ret.end(), std::back_inserter(filtered), [&](const ObjectTemplate & obj)
|
std::copy_if(ret.begin(), ret.end(), std::back_inserter(filtered), [&](const ObjectTemplate & obj)
|
||||||
{
|
{
|
||||||
return obj.canBePlacedAt(terrain);
|
return obj.canBePlacedAt(ETerrainType(terrainType));
|
||||||
});
|
});
|
||||||
// it is possible that there are no templates usable on specific terrain. In this case - return list before filtering
|
// it is possible that there are no templates usable on specific terrain. In this case - return list before filtering
|
||||||
return filtered.empty() ? ret : filtered;
|
return filtered.empty() ? ret : filtered;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<ObjectTemplate> CDefObjInfoHandler::pickCandidates(Obj type, si32 subtype, ETerrainType terrain, std::function<bool(ObjectTemplate &)> filter) const
|
ObjectTemplate AObjectTypeHandler::selectTemplate(si32 terrainType, CGObjectInstance * object) const
|
||||||
{
|
{
|
||||||
std::vector<ObjectTemplate> ret = pickCandidates(type, subtype, terrain);
|
std::vector<ObjectTemplate> ret = getTemplates(terrainType);
|
||||||
std::vector<ObjectTemplate> filtered;
|
for (auto & tmpl : ret)
|
||||||
|
{
|
||||||
std::copy_if(ret.begin(), ret.end(), std::back_inserter(filtered), filter);
|
if (objectFilter(object, tmpl))
|
||||||
// it is possible that there are no templates usable on specific terrain. In this case - return list before filtering
|
return tmpl;
|
||||||
return filtered.empty() ? ret : filtered;
|
}
|
||||||
|
// FIXME: no matches found. Warn? Ask for torches? Die?
|
||||||
|
return ret.front();
|
||||||
}
|
}
|
||||||
|
@ -78,37 +78,6 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class DLL_LINKAGE CDefObjInfoHandler
|
|
||||||
{
|
|
||||||
/// list of all object templates loaded from text files
|
|
||||||
/// actual object have ObjectTemplate as member "appearance"
|
|
||||||
std::vector<ObjectTemplate> objects;
|
|
||||||
|
|
||||||
/// reads one of H3 text files that contain object templates description
|
|
||||||
void readTextFile(std::string path);
|
|
||||||
public:
|
|
||||||
|
|
||||||
CDefObjInfoHandler();
|
|
||||||
|
|
||||||
/// Erases all templates with given type/subtype
|
|
||||||
void eraseAll(Obj type, si32 subtype);
|
|
||||||
|
|
||||||
/// Add new template into the list
|
|
||||||
void registerTemplate(ObjectTemplate obj);
|
|
||||||
|
|
||||||
/// picks all possible candidates for specific pair <type, subtype>
|
|
||||||
std::vector<ObjectTemplate> pickCandidates(Obj type, si32 subtype) const;
|
|
||||||
/// picks all candidates for <type, subtype> and of possible - also filters them by terrain
|
|
||||||
std::vector<ObjectTemplate> pickCandidates(Obj type, si32 subtype, ETerrainType terrain) const;
|
|
||||||
/// as above, but also filters out templates that are not applicable according to accepted test
|
|
||||||
std::vector<ObjectTemplate> pickCandidates(Obj type, si32 subtype, ETerrainType terrain, std::function<bool(ObjectTemplate &)> filter) const;
|
|
||||||
|
|
||||||
template <typename Handler> void serialize(Handler &h, const int version)
|
|
||||||
{
|
|
||||||
h & objects;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
class IObjectInfo
|
class IObjectInfo
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -130,40 +99,57 @@ public:
|
|||||||
|
|
||||||
class CGObjectInstance;
|
class CGObjectInstance;
|
||||||
|
|
||||||
class IObjectTypesHandler
|
class AObjectTypeHandler
|
||||||
{
|
{
|
||||||
|
si32 type;
|
||||||
|
si32 subtype;
|
||||||
|
|
||||||
|
std::vector<ObjectTemplate> templates;
|
||||||
|
protected:
|
||||||
|
void init(si32 type, si32 subtype);
|
||||||
|
|
||||||
|
/// loads templates from Json structure using fields "base" and "templates"
|
||||||
|
void load(const JsonNode & input);
|
||||||
|
|
||||||
|
virtual bool objectFilter(const CGObjectInstance *, const ObjectTemplate &) const;
|
||||||
public:
|
public:
|
||||||
virtual std::vector<ObjectTemplate> getTemplates(si32 type, si32 subType) const = 0;
|
void addTemplate(const ObjectTemplate & templ);
|
||||||
|
|
||||||
|
/// returns all templates, without any filters
|
||||||
|
std::vector<ObjectTemplate> getTemplates() const;
|
||||||
|
|
||||||
|
/// returns all templates that can be placed on specific terrain type
|
||||||
|
std::vector<ObjectTemplate> getTemplates(si32 terrainType) const;
|
||||||
|
|
||||||
|
/// returns template suitable for object. If returned template is not equal to current one
|
||||||
|
/// it must be replaced with this one (and properly updated on all clients)
|
||||||
|
ObjectTemplate selectTemplate(si32 terrainType, CGObjectInstance * object) const;
|
||||||
|
|
||||||
|
|
||||||
virtual CGObjectInstance * create(ObjectTemplate tmpl) const = 0;
|
virtual CGObjectInstance * create(ObjectTemplate tmpl) const = 0;
|
||||||
|
|
||||||
virtual bool handlesID(ObjectTemplate tmpl) const = 0;
|
|
||||||
|
|
||||||
virtual void configureObject(CGObjectInstance * object) const = 0;
|
virtual void configureObject(CGObjectInstance * object) const = 0;
|
||||||
|
|
||||||
virtual const IObjectInfo * getObjectInfo(ObjectTemplate tmpl) const = 0;
|
virtual const IObjectInfo * getObjectInfo(ObjectTemplate tmpl) const = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef std::shared_ptr<IObjectTypesHandler> TObjectTypeHandler;
|
typedef std::shared_ptr<AObjectTypeHandler> TObjectTypeHandler;
|
||||||
|
|
||||||
class CObjectGroupsHandler
|
class CObjectTypesHandler
|
||||||
{
|
{
|
||||||
/// list of object handlers, each of them handles 1 or more object type
|
/// list of object handlers, each of them handles only one type
|
||||||
std::vector<TObjectTypeHandler> objectTypes;
|
std::map<si32, std::map<si32, TObjectTypeHandler> > objectTypes;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
void init();
|
||||||
|
|
||||||
/// returns handler for specified object (ID-based). ObjectHandler keeps ownership
|
/// returns handler for specified object (ID-based). ObjectHandler keeps ownership
|
||||||
IObjectTypesHandler * getHandlerFor(ObjectTemplate tmpl) const;
|
TObjectTypeHandler getHandlerFor(si32 type, si32 subtype) const;
|
||||||
|
|
||||||
/// creates object based on specified template
|
template <typename Handler> void serialize(Handler &h, const int version)
|
||||||
CGObjectInstance * createObject(ObjectTemplate tmpl);
|
|
||||||
|
|
||||||
template<typename CObjectClass>
|
|
||||||
CObjectClass * createObjectTyped(ObjectTemplate tmpl)
|
|
||||||
{
|
{
|
||||||
auto objInst = createObject(tmpl);
|
//h & objects;
|
||||||
auto objClass = dynamic_cast<CObjectClass*>(objInst);
|
if (!h.saving)
|
||||||
assert(objClass);
|
init(); // TODO: implement serialization
|
||||||
return objClass;
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -342,9 +342,11 @@ static CGObjectInstance * createObject(Obj id, int subid, int3 pos, PlayerColor
|
|||||||
switch(id)
|
switch(id)
|
||||||
{
|
{
|
||||||
case Obj::HERO:
|
case Obj::HERO:
|
||||||
nobj = new CGHeroInstance();
|
{
|
||||||
nobj->appearance = VLC->dobjinfo->pickCandidates(id, VLC->heroh->heroes[subid]->heroClass->id).front();
|
auto handler = VLC->objtypeh->getHandlerFor(id, VLC->heroh->heroes[subid]->heroClass->id);
|
||||||
break;
|
nobj = handler->create(handler->getTemplates().front());
|
||||||
|
break;
|
||||||
|
}
|
||||||
case Obj::TOWN:
|
case Obj::TOWN:
|
||||||
nobj = new CGTownInstance;
|
nobj = new CGTownInstance;
|
||||||
break;
|
break;
|
||||||
@ -357,7 +359,7 @@ static CGObjectInstance * createObject(Obj id, int subid, int3 pos, PlayerColor
|
|||||||
nobj->pos = pos;
|
nobj->pos = pos;
|
||||||
nobj->tempOwner = owner;
|
nobj->tempOwner = owner;
|
||||||
if (id != Obj::HERO)
|
if (id != Obj::HERO)
|
||||||
nobj->appearance = VLC->dobjinfo->pickCandidates(id, subid).front();
|
nobj->appearance = VLC->objtypeh->getHandlerFor(id, subid)->getTemplates().front();
|
||||||
|
|
||||||
return nobj;
|
return nobj;
|
||||||
}
|
}
|
||||||
@ -654,7 +656,7 @@ void CGameState::randomizeObject(CGObjectInstance *cur)
|
|||||||
const TerrainTile &tile = map->getTile(cur->visitablePos());
|
const TerrainTile &tile = map->getTile(cur->visitablePos());
|
||||||
CGTownInstance *t = dynamic_cast<CGTownInstance*>(cur);
|
CGTownInstance *t = dynamic_cast<CGTownInstance*>(cur);
|
||||||
t->town = VLC->townh->factions[t->subID]->town;
|
t->town = VLC->townh->factions[t->subID]->town;
|
||||||
t->appearance = VLC->dobjinfo->pickCandidates(Obj::TOWN, t->subID, tile.terType).front();
|
t->appearance = VLC->objtypeh->getHandlerFor(Obj::TOWN, t->subID)->selectTemplate(tile.terType, t);
|
||||||
t->updateAppearance();
|
t->updateAppearance();
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
@ -675,12 +677,12 @@ void CGameState::randomizeObject(CGObjectInstance *cur)
|
|||||||
{
|
{
|
||||||
const TerrainTile &tile = map->getTile(cur->visitablePos());
|
const TerrainTile &tile = map->getTile(cur->visitablePos());
|
||||||
CGTownInstance *t = dynamic_cast<CGTownInstance*>(cur);
|
CGTownInstance *t = dynamic_cast<CGTownInstance*>(cur);
|
||||||
if(!t) {logGlobal->warnStream()<<"Wrong random town at "<<cur->pos; return;}
|
if(!t) {logGlobal->warnStream()<<"Wrong random town at "<<cur->pos; return;}
|
||||||
cur->ID = ran.first;
|
cur->ID = ran.first;
|
||||||
cur->subID = ran.second;
|
cur->subID = ran.second;
|
||||||
//FIXME: copy-pasted from above
|
//FIXME: copy-pasted from above
|
||||||
t->town = VLC->townh->factions[t->subID]->town;
|
t->town = VLC->townh->factions[t->subID]->town;
|
||||||
t->appearance = VLC->dobjinfo->pickCandidates(Obj::TOWN,t->subID, tile.terType).front();
|
t->appearance = VLC->objtypeh->getHandlerFor(Obj::TOWN, t->subID)->selectTemplate(tile.terType, t);
|
||||||
t->updateAppearance();
|
t->updateAppearance();
|
||||||
|
|
||||||
t->randomizeArmy(t->subID);
|
t->randomizeArmy(t->subID);
|
||||||
@ -693,7 +695,7 @@ void CGameState::randomizeObject(CGObjectInstance *cur)
|
|||||||
ran.second != cur->appearance.subid)
|
ran.second != cur->appearance.subid)
|
||||||
{
|
{
|
||||||
const TerrainTile &tile = map->getTile(cur->visitablePos());
|
const TerrainTile &tile = map->getTile(cur->visitablePos());
|
||||||
cur->appearance = VLC->dobjinfo->pickCandidates(Obj(ran.first),ran.second, tile.terType).front();
|
cur->appearance = VLC->objtypeh->getHandlerFor(ran.first, ran.second)->selectTemplate(tile.terType, cur);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//we have to replace normal random object
|
//we have to replace normal random object
|
||||||
@ -3315,9 +3317,9 @@ void CPathfinder::calculatePaths(int3 src /*= int3(-1,-1,-1)*/, int movement /*=
|
|||||||
int maxMovePointsLand = hero->maxMovePoints(true);
|
int maxMovePointsLand = hero->maxMovePoints(true);
|
||||||
int maxMovePointsWater = hero->maxMovePoints(false);
|
int maxMovePointsWater = hero->maxMovePoints(false);
|
||||||
|
|
||||||
auto maxMovePoints = [&](CGPathNode *cp) -> int
|
auto maxMovePoints = [&](CGPathNode *cp) -> int
|
||||||
{
|
{
|
||||||
return cp->land ? maxMovePointsLand : maxMovePointsWater;
|
return cp->land ? maxMovePointsLand : maxMovePointsWater;
|
||||||
};
|
};
|
||||||
|
|
||||||
out.hero = hero;
|
out.hero = hero;
|
||||||
|
@ -229,7 +229,7 @@ void CHeroClassHandler::afterLoadFinalization()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ObjectTemplate base = VLC->dobjinfo->pickCandidates(Obj::HERO, 0).front();
|
ObjectTemplate base = VLC->objtypeh->getHandlerFor(Obj::HERO, 0)->getTemplates().front();
|
||||||
for (CHeroClass * hc : heroClasses)
|
for (CHeroClass * hc : heroClasses)
|
||||||
{
|
{
|
||||||
base.animationFile = hc->imageMapMale;
|
base.animationFile = hc->imageMapMale;
|
||||||
@ -237,8 +237,7 @@ void CHeroClassHandler::afterLoadFinalization()
|
|||||||
|
|
||||||
// replace existing (if any) and add new template.
|
// replace existing (if any) and add new template.
|
||||||
// Necessary for objects added via mods that don't have any templates in H3
|
// Necessary for objects added via mods that don't have any templates in H3
|
||||||
VLC->dobjinfo->eraseAll(Obj::HERO, hc->id);
|
VLC->objtypeh->getHandlerFor(Obj::HERO, base.subid)->addTemplate(base);
|
||||||
VLC->dobjinfo->registerTemplate(base);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -11,64 +11,78 @@
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
void CRandomRewardObjectInfo::init(const JsonNode & objectConfig)
|
||||||
|
{
|
||||||
|
parameters = objectConfig;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CRandomRewardObjectInfo::configureObject(CObjectWithReward * object) const
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CRandomRewardObjectInfo::givesResources() const
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CRandomRewardObjectInfo::givesExperience() const
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CRandomRewardObjectInfo::givesMana() const
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CRandomRewardObjectInfo::givesMovement() const
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CRandomRewardObjectInfo::givesPrimarySkills() const
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CRandomRewardObjectInfo::givesSecondarySkills() const
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CRandomRewardObjectInfo::givesArtifacts() const
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CRandomRewardObjectInfo::givesCreatures() const
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CRandomRewardObjectInfo::givesSpells() const
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CRandomRewardObjectInfo::givesBonuses() const
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
CObjectWithRewardConstructor::CObjectWithRewardConstructor()
|
CObjectWithRewardConstructor::CObjectWithRewardConstructor()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void CObjectWithRewardConstructor::init(const JsonNode & config)
|
void CObjectWithRewardConstructor::init(const JsonNode & config)
|
||||||
{
|
{
|
||||||
int id = config["id"].Float();
|
objectInfo.init(config);
|
||||||
std::string name = config["name"].String();
|
|
||||||
for (auto & entry : config["types"].Struct()) // for each object type
|
|
||||||
{
|
|
||||||
JsonNode typeConf = entry.second;
|
|
||||||
|
|
||||||
int subID = typeConf["id"].Float();
|
|
||||||
|
|
||||||
objectInfos[id][subID].info.init(typeConf["properties"]);
|
|
||||||
for (auto entry : typeConf["templates"].Struct())
|
|
||||||
{
|
|
||||||
ObjectTemplate tmpl;
|
|
||||||
tmpl.id = Obj(id);
|
|
||||||
tmpl.subid = subID;
|
|
||||||
tmpl.readJson(entry.second);
|
|
||||||
objectInfos[id][subID].templates.push_back(tmpl);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<ObjectTemplate> CObjectWithRewardConstructor::getTemplates(si32 type, si32 subType) const
|
|
||||||
{
|
|
||||||
assert(handlesID(type, subtype));
|
|
||||||
return objectInfos.at(type).at(subType).templates;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
CGObjectInstance * CObjectWithRewardConstructor::create(ObjectTemplate tmpl) const
|
CGObjectInstance * CObjectWithRewardConstructor::create(ObjectTemplate tmpl) const
|
||||||
{
|
{
|
||||||
assert(handlesID(tmpl));
|
|
||||||
auto ret = new CObjectWithReward();
|
auto ret = new CObjectWithReward();
|
||||||
ret->appearance = tmpl;
|
ret->appearance = tmpl;
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CObjectWithRewardConstructor::handlesID(si32 id, si32 subID) const
|
|
||||||
{
|
|
||||||
return objectInfos.count(id) && objectInfos.at(id).count(subID);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CObjectWithRewardConstructor::handlesID(ObjectTemplate tmpl) const
|
|
||||||
{
|
|
||||||
return handlesID(tmpl.id, tmpl.subid);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CObjectWithRewardConstructor::configureObject(CGObjectInstance * object) const
|
void CObjectWithRewardConstructor::configureObject(CGObjectInstance * object) const
|
||||||
{
|
{
|
||||||
assert(handlesID(object->appearance));
|
objectInfo.configureObject(dynamic_cast<CObjectWithReward*>(object));
|
||||||
objectInfos.at(object->ID).at(object->subID).info.configureObject(dynamic_cast<CObjectWithReward*>(object));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const IObjectInfo * CObjectWithRewardConstructor::getObjectInfo(ObjectTemplate tmpl) const
|
const IObjectInfo * CObjectWithRewardConstructor::getObjectInfo(ObjectTemplate tmpl) const
|
||||||
{
|
{
|
||||||
assert(handlesID(tmpl));
|
return &objectInfo;
|
||||||
return &objectInfos.at(tmpl.id).at(tmpl.subid).info;
|
|
||||||
}
|
}
|
||||||
|
@ -41,26 +41,16 @@ public:
|
|||||||
void init(const JsonNode & objectConfig);
|
void init(const JsonNode & objectConfig);
|
||||||
};
|
};
|
||||||
|
|
||||||
class CObjectWithRewardConstructor : public IObjectTypesHandler
|
class CObjectWithRewardConstructor : public AObjectTypeHandler
|
||||||
{
|
{
|
||||||
struct ObjectInfo
|
CRandomRewardObjectInfo objectInfo;
|
||||||
{
|
|
||||||
CRandomRewardObjectInfo info;
|
|
||||||
std::vector<ObjectTemplate> templates;
|
|
||||||
};
|
|
||||||
std::map<ui32, std::map<ui32, ObjectInfo> > objectInfos;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
CObjectWithRewardConstructor();
|
CObjectWithRewardConstructor();
|
||||||
void init(const JsonNode & config);
|
void init(const JsonNode & config);
|
||||||
|
|
||||||
std::vector<ObjectTemplate> getTemplates(si32 type, si32 subType) const override;
|
|
||||||
|
|
||||||
CGObjectInstance * create(ObjectTemplate tmpl) const override;
|
CGObjectInstance * create(ObjectTemplate tmpl) const override;
|
||||||
|
|
||||||
bool handlesID(si32 id, si32 subID) const;
|
|
||||||
bool handlesID(ObjectTemplate tmpl) const override;
|
|
||||||
|
|
||||||
void configureObject(CGObjectInstance * object) const override;
|
void configureObject(CGObjectInstance * object) const override;
|
||||||
|
|
||||||
const IObjectInfo * getObjectInfo(ObjectTemplate tmpl) const override;
|
const IObjectInfo * getObjectInfo(ObjectTemplate tmpl) const override;
|
||||||
|
@ -727,7 +727,7 @@ void CGHeroInstance::initHero()
|
|||||||
type = VLC->heroh->heroes[subID];
|
type = VLC->heroh->heroes[subID];
|
||||||
|
|
||||||
if (ID == Obj::HERO)
|
if (ID == Obj::HERO)
|
||||||
appearance = VLC->dobjinfo->pickCandidates(Obj::HERO, type->heroClass->id).front();
|
appearance = VLC->objtypeh->getHandlerFor(Obj::HERO, type->heroClass->id)->getTemplates().front();
|
||||||
|
|
||||||
if(!vstd::contains(spells, SpellID::PRESET)) //hero starts with a spell
|
if(!vstd::contains(spells, SpellID::PRESET)) //hero starts with a spell
|
||||||
{
|
{
|
||||||
@ -3493,7 +3493,7 @@ void CGTeleport::onHeroVisit( const CGHeroInstance * h ) const
|
|||||||
if(vstd::contains(objs,Obj::MONOLITH2) && vstd::contains(objs[Obj::MONOLITH2],subID) && objs[Obj::MONOLITH2][subID].size())
|
if(vstd::contains(objs,Obj::MONOLITH2) && vstd::contains(objs[Obj::MONOLITH2],subID) && objs[Obj::MONOLITH2][subID].size())
|
||||||
destinationid = objs[Obj::MONOLITH2][subID][rand()%objs[Obj::MONOLITH2][subID].size()];
|
destinationid = objs[Obj::MONOLITH2][subID][rand()%objs[Obj::MONOLITH2][subID].size()];
|
||||||
else
|
else
|
||||||
logGlobal->warnStream() << "Cannot find corresponding exit monolith for "<< id;
|
logGlobal->warnStream() << "Cannot find corresponding exit monolith for "<< id;
|
||||||
break;
|
break;
|
||||||
case Obj::MONOLITH3://two way monolith - pick any other one
|
case Obj::MONOLITH3://two way monolith - pick any other one
|
||||||
case Obj::WHIRLPOOL: //Whirlpool
|
case Obj::WHIRLPOOL: //Whirlpool
|
||||||
@ -3530,7 +3530,7 @@ void CGTeleport::onHeroVisit( const CGHeroInstance * h ) const
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
logGlobal->warnStream() << "Cannot find corresponding exit monolith for "<< id;
|
logGlobal->warnStream() << "Cannot find corresponding exit monolith for "<< id;
|
||||||
break;
|
break;
|
||||||
case Obj::SUBTERRANEAN_GATE: //find nearest subterranean gate on the other level
|
case Obj::SUBTERRANEAN_GATE: //find nearest subterranean gate on the other level
|
||||||
{
|
{
|
||||||
@ -3544,7 +3544,7 @@ void CGTeleport::onHeroVisit( const CGHeroInstance * h ) const
|
|||||||
}
|
}
|
||||||
if(destinationid == ObjectInstanceID())
|
if(destinationid == ObjectInstanceID())
|
||||||
{
|
{
|
||||||
logGlobal->warnStream() << "Cannot find exit... (obj at " << pos << ") :( ";
|
logGlobal->warnStream() << "Cannot find exit... (obj at " << pos << ") :( ";
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (ID == Obj::WHIRLPOOL)
|
if (ID == Obj::WHIRLPOOL)
|
||||||
|
@ -711,7 +711,7 @@ void CTownHandler::loadObject(std::string scope, std::string name, const JsonNod
|
|||||||
void CTownHandler::afterLoadFinalization()
|
void CTownHandler::afterLoadFinalization()
|
||||||
{
|
{
|
||||||
initializeRequirements();
|
initializeRequirements();
|
||||||
ObjectTemplate base = VLC->dobjinfo->pickCandidates(Obj::TOWN, 0).front();
|
ObjectTemplate base = VLC->objtypeh->getHandlerFor(Obj::TOWN, 0)->getTemplates().front();
|
||||||
for (CFaction * fact : factions)
|
for (CFaction * fact : factions)
|
||||||
{
|
{
|
||||||
if (fact->town)
|
if (fact->town)
|
||||||
@ -721,13 +721,12 @@ void CTownHandler::afterLoadFinalization()
|
|||||||
|
|
||||||
// replace existing (if any) and add new template.
|
// replace existing (if any) and add new template.
|
||||||
// Necessary for objects added via mods that don't have any templates in H3
|
// Necessary for objects added via mods that don't have any templates in H3
|
||||||
VLC->dobjinfo->eraseAll(Obj::TOWN, fact->index);
|
VLC->objtypeh->getHandlerFor(Obj::TOWN, fact->index)->addTemplate(base);
|
||||||
VLC->dobjinfo->registerTemplate(base);
|
|
||||||
|
|
||||||
assert(fact->town->dwellings.size() == fact->town->dwellingNames.size());
|
assert(fact->town->dwellings.size() == fact->town->dwellingNames.size());
|
||||||
for (size_t i=0; i<fact->town->dwellings.size(); i++)
|
for (size_t i=0; i<fact->town->dwellings.size(); i++)
|
||||||
{
|
{
|
||||||
ObjectTemplate base = VLC->dobjinfo->pickCandidates(Obj::CREATURE_GENERATOR1, 0).front();
|
ObjectTemplate base = VLC->objtypeh->getHandlerFor(Obj::CREATURE_GENERATOR1, 0)->getTemplates().front();
|
||||||
|
|
||||||
//both unupgraded and upgraded get same dwelling
|
//both unupgraded and upgraded get same dwelling
|
||||||
for (auto cre : fact->town->creatures[i])
|
for (auto cre : fact->town->creatures[i])
|
||||||
@ -736,7 +735,7 @@ void CTownHandler::afterLoadFinalization()
|
|||||||
base.animationFile = fact->town->dwellings[i];
|
base.animationFile = fact->town->dwellings[i];
|
||||||
if (VLC->objh->cregens.count(cre) == 0)
|
if (VLC->objh->cregens.count(cre) == 0)
|
||||||
{
|
{
|
||||||
VLC->dobjinfo->registerTemplate(base);
|
VLC->objtypeh->getHandlerFor(Obj::CREATURE_GENERATOR1, 80 + cre)->addTemplate(base);
|
||||||
VLC->objh->cregens[80 + cre] = cre; //map of dwelling -> creature id
|
VLC->objh->cregens[80 + cre] = cre; //map of dwelling -> creature id
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -582,7 +582,7 @@ DLL_LINKAGE void GiveHero::applyGs( CGameState *gs )
|
|||||||
//bonus system
|
//bonus system
|
||||||
h->detachFrom(&gs->globalEffects);
|
h->detachFrom(&gs->globalEffects);
|
||||||
h->attachTo(gs->getPlayer(player));
|
h->attachTo(gs->getPlayer(player));
|
||||||
h->appearance = VLC->dobjinfo->pickCandidates(Obj::HERO, h->type->heroClass->id).front();
|
h->appearance = VLC->objtypeh->getHandlerFor(Obj::HERO, h->type->heroClass->id)->getTemplates().front();
|
||||||
|
|
||||||
gs->map->removeBlockVisTiles(h,true);
|
gs->map->removeBlockVisTiles(h,true);
|
||||||
h->setOwner(player);
|
h->setOwner(player);
|
||||||
@ -623,7 +623,7 @@ DLL_LINKAGE void NewObject::applyGs( CGameState *gs )
|
|||||||
o->subID = subID;
|
o->subID = subID;
|
||||||
o->pos = pos;
|
o->pos = pos;
|
||||||
const TerrainTile &t = gs->map->getTile(pos);
|
const TerrainTile &t = gs->map->getTile(pos);
|
||||||
o->appearance = VLC->dobjinfo->pickCandidates(o->ID, o->subID, t.terType).front();
|
o->appearance = VLC->objtypeh->getHandlerFor(o->ID, o->subID)->selectTemplate(t.terType, o);
|
||||||
id = o->id = ObjectInstanceID(gs->map->objects.size());
|
id = o->id = ObjectInstanceID(gs->map->objects.size());
|
||||||
o->hoverName = VLC->generaltexth->names[ID];
|
o->hoverName = VLC->generaltexth->names[ID];
|
||||||
|
|
||||||
|
@ -109,7 +109,7 @@ void LibClasses::init()
|
|||||||
|
|
||||||
createHandler(objh, "Object", pomtime);
|
createHandler(objh, "Object", pomtime);
|
||||||
|
|
||||||
createHandler(dobjinfo, "Def information", pomtime);
|
createHandler(objtypeh, "Object types information", pomtime);
|
||||||
|
|
||||||
createHandler(spellh, "Spell", pomtime);
|
createHandler(spellh, "Spell", pomtime);
|
||||||
|
|
||||||
@ -135,7 +135,7 @@ void LibClasses::clear()
|
|||||||
delete creh;
|
delete creh;
|
||||||
delete townh;
|
delete townh;
|
||||||
delete objh;
|
delete objh;
|
||||||
delete dobjinfo;
|
delete objtypeh;
|
||||||
delete spellh;
|
delete spellh;
|
||||||
delete modh;
|
delete modh;
|
||||||
delete bth;
|
delete bth;
|
||||||
@ -152,7 +152,7 @@ void LibClasses::makeNull()
|
|||||||
creh = nullptr;
|
creh = nullptr;
|
||||||
townh = nullptr;
|
townh = nullptr;
|
||||||
objh = nullptr;
|
objh = nullptr;
|
||||||
dobjinfo = nullptr;
|
objtypeh = nullptr;
|
||||||
spellh = nullptr;
|
spellh = nullptr;
|
||||||
modh = nullptr;
|
modh = nullptr;
|
||||||
bth = nullptr;
|
bth = nullptr;
|
||||||
|
@ -16,7 +16,7 @@ class CCreatureHandler;
|
|||||||
class CSpellHandler;
|
class CSpellHandler;
|
||||||
class CBuildingHandler;
|
class CBuildingHandler;
|
||||||
class CObjectHandler;
|
class CObjectHandler;
|
||||||
class CDefObjInfoHandler;
|
class CObjectTypesHandler;
|
||||||
class CTownHandler;
|
class CTownHandler;
|
||||||
class CGeneralTextHandler;
|
class CGeneralTextHandler;
|
||||||
class CModHandler;
|
class CModHandler;
|
||||||
@ -42,7 +42,7 @@ public:
|
|||||||
CCreatureHandler * creh;
|
CCreatureHandler * creh;
|
||||||
CSpellHandler * spellh;
|
CSpellHandler * spellh;
|
||||||
CObjectHandler * objh;
|
CObjectHandler * objh;
|
||||||
CDefObjInfoHandler * dobjinfo;
|
CObjectTypesHandler * objtypeh;
|
||||||
CTownHandler * townh;
|
CTownHandler * townh;
|
||||||
CGeneralTextHandler * generaltexth;
|
CGeneralTextHandler * generaltexth;
|
||||||
CModHandler * modh;
|
CModHandler * modh;
|
||||||
@ -60,7 +60,7 @@ public:
|
|||||||
|
|
||||||
template <typename Handler> void serialize(Handler &h, const int version)
|
template <typename Handler> void serialize(Handler &h, const int version)
|
||||||
{
|
{
|
||||||
h & heroh & arth & creh & townh & objh & dobjinfo & spellh & modh & IS_AI_ENABLED;
|
h & heroh & arth & creh & townh & objh & objtypeh & spellh & modh & IS_AI_ENABLED;
|
||||||
h & bth;
|
h & bth;
|
||||||
if(!h.saving)
|
if(!h.saving)
|
||||||
{
|
{
|
||||||
|
@ -166,7 +166,7 @@ void CMapGenerator::genTowns()
|
|||||||
}
|
}
|
||||||
town->subID = townId;
|
town->subID = townId;
|
||||||
town->tempOwner = owner;
|
town->tempOwner = owner;
|
||||||
town->appearance = VLC->dobjinfo->pickCandidates(town->ID, town->subID, map->getTile(townPos[side]).terType).front();
|
town->appearance = VLC->objtypeh->getHandlerFor(town->ID, town->subID)->selectTemplate(map->getTile(townPos[side]).terType, town);
|
||||||
town->builtBuildings.insert(BuildingID::FORT);
|
town->builtBuildings.insert(BuildingID::FORT);
|
||||||
town->builtBuildings.insert(BuildingID::DEFAULT);
|
town->builtBuildings.insert(BuildingID::DEFAULT);
|
||||||
editManager->insertObject(town, int3(townPos[side].x, townPos[side].y + (i / 2) * 5, 0));
|
editManager->insertObject(town, int3(townPos[side].x, townPos[side].y + (i / 2) * 5, 0));
|
||||||
|
Loading…
x
Reference in New Issue
Block a user