1
0
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:
Ivan Savenko 2014-05-16 23:50:02 +03:00
parent d805376ab8
commit b5160acbac
16 changed files with 184 additions and 195 deletions

View File

@ -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;
} }

View File

@ -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();

View File

@ -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);
} }
} }
} }

View File

@ -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);
} }
} }
} }

View File

@ -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();
} }

View File

@ -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;
} }
}; };

View File

@ -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;

View File

@ -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);
} }
} }

View File

@ -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;
} }

View File

@ -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;

View File

@ -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)

View File

@ -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
} }
} }

View File

@ -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];

View File

@ -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;

View File

@ -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)
{ {

View File

@ -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));