1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-01-12 02:28:11 +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;
objh = VLC->objh;
spellh = VLC->spellh;
dobjinfo = VLC->dobjinfo;
objtypeh = VLC->objtypeh;
}

View File

@ -23,7 +23,7 @@ class CBuildingHandler;
class CObjectHandler;
class CSoundHandler;
class CMusicHandler;
class CDefObjInfoHandler;
class CObjectTypesHandler;
class CTownHandler;
class CGeneralTextHandler;
class CConsoleHandler;
@ -57,11 +57,10 @@ public:
ConstTransitivePtr<CCreatureHandler> creh;
ConstTransitivePtr<CSpellHandler> spellh;
ConstTransitivePtr<CObjectHandler> objh;
ConstTransitivePtr<CDefObjInfoHandler> dobjinfo;
ConstTransitivePtr<CObjectTypesHandler> objtypeh;
CGeneralTextHandler * generaltexth;
CMapHandler * mh;
CTownHandler * townh;
//CTownHandler * townh;
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
ObjectTemplate base = VLC->dobjinfo->pickCandidates(Obj::ARTIFACT, 10).front();
ObjectTemplate base = VLC->objtypeh->getHandlerFor(Obj::ARTIFACT, 10)->getTemplates().front();
for (CArtifact * art : artifacts)
{
if (!art->advMapDef.empty())
@ -656,10 +656,9 @@ void CArtHandler::afterLoadFinalization()
base.animationFile = art->advMapDef;
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
VLC->dobjinfo->eraseAll(Obj::ARTIFACT, art->id);
VLC->dobjinfo->registerTemplate(base);
VLC->objtypeh->getHandlerFor(Obj::ARTIFACT, art->id)->addTemplate(base);
}
}
}

View File

@ -1114,7 +1114,7 @@ void CCreatureHandler::buildBonusTreeForTiers()
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)
{
if (!crea->advMapDef.empty())
@ -1124,8 +1124,7 @@ void CCreatureHandler::afterLoadFinalization()
// replace existing (if any) and add new template.
// Necessary for objects added via mods that don't have any templates in H3
VLC->dobjinfo->eraseAll(Obj::MONSTER, crea->idNumber);
VLC->dobjinfo->registerTemplate(base);
VLC->objtypeh->getHandlerFor(Obj::MONSTER, crea->idNumber)->addTemplate(base);
}
}
}

View File

@ -7,6 +7,7 @@
#include "GameConstants.h"
#include "StringConstants.h"
#include "CGeneralTextHandler.h"
#include "CObjectHandler.h"
#include "CModHandler.h"
#include "JsonNode.h"
@ -327,7 +328,7 @@ bool ObjectTemplate::canBePlacedAt(ETerrainType terrain) const
{
return allowedTerrains.count(terrain) != 0;
}
/*
void CDefObjInfoHandler::readTextFile(std::string path)
{
CLegacyConfigParser parser(path);
@ -347,81 +348,82 @@ CDefObjInfoHandler::CDefObjInfoHandler()
{
readTextFile("Data/Objects.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;
});
objects.erase(it, objects.end());
if (objectTypes.at(type).count(subtype))
return objectTypes.at(type).at(subtype);
}
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;
std::copy_if(objects.begin(), objects.end(), std::back_inserter(ret), [&](const ObjectTemplate & obj)
for (auto entry : input["templates"].Struct())
{
return obj.id == type && obj.subid == subtype;
});
if (ret.empty())
logGlobal->errorStream() << "Failed to find template for " << type << ":" << subtype;
JsonNode data = input["base"];
JsonUtils::merge(data, entry.second);
assert(!ret.empty()); // Can't create object of this type/subtype
return ret;
ObjectTemplate tmpl;
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::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
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> filtered;
std::copy_if(ret.begin(), ret.end(), std::back_inserter(filtered), filter);
// it is possible that there are no templates usable on specific terrain. In this case - return list before filtering
return filtered.empty() ? ret : filtered;
std::vector<ObjectTemplate> ret = getTemplates(terrainType);
for (auto & tmpl : ret)
{
if (objectFilter(object, tmpl))
return tmpl;
}
// 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
{
public:
@ -130,40 +99,57 @@ public:
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:
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 bool handlesID(ObjectTemplate tmpl) const = 0;
virtual void configureObject(CGObjectInstance * object) 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
std::vector<TObjectTypeHandler> objectTypes;
/// list of object handlers, each of them handles only one type
std::map<si32, std::map<si32, TObjectTypeHandler> > objectTypes;
public:
void init();
/// 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
CGObjectInstance * createObject(ObjectTemplate tmpl);
template<typename CObjectClass>
CObjectClass * createObjectTyped(ObjectTemplate tmpl)
template <typename Handler> void serialize(Handler &h, const int version)
{
auto objInst = createObject(tmpl);
auto objClass = dynamic_cast<CObjectClass*>(objInst);
assert(objClass);
return objClass;
//h & objects;
if (!h.saving)
init(); // TODO: implement serialization
}
};

View File

@ -342,9 +342,11 @@ static CGObjectInstance * createObject(Obj id, int subid, int3 pos, PlayerColor
switch(id)
{
case Obj::HERO:
nobj = new CGHeroInstance();
nobj->appearance = VLC->dobjinfo->pickCandidates(id, VLC->heroh->heroes[subid]->heroClass->id).front();
break;
{
auto handler = VLC->objtypeh->getHandlerFor(id, VLC->heroh->heroes[subid]->heroClass->id);
nobj = handler->create(handler->getTemplates().front());
break;
}
case Obj::TOWN:
nobj = new CGTownInstance;
break;
@ -357,7 +359,7 @@ static CGObjectInstance * createObject(Obj id, int subid, int3 pos, PlayerColor
nobj->pos = pos;
nobj->tempOwner = owner;
if (id != Obj::HERO)
nobj->appearance = VLC->dobjinfo->pickCandidates(id, subid).front();
nobj->appearance = VLC->objtypeh->getHandlerFor(id, subid)->getTemplates().front();
return nobj;
}
@ -654,7 +656,7 @@ void CGameState::randomizeObject(CGObjectInstance *cur)
const TerrainTile &tile = map->getTile(cur->visitablePos());
CGTownInstance *t = dynamic_cast<CGTownInstance*>(cur);
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();
}
return;
@ -675,12 +677,12 @@ void CGameState::randomizeObject(CGObjectInstance *cur)
{
const TerrainTile &tile = map->getTile(cur->visitablePos());
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->subID = ran.second;
//FIXME: copy-pasted from above
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->randomizeArmy(t->subID);
@ -693,7 +695,7 @@ void CGameState::randomizeObject(CGObjectInstance *cur)
ran.second != cur->appearance.subid)
{
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
@ -3315,9 +3317,9 @@ void CPathfinder::calculatePaths(int3 src /*= int3(-1,-1,-1)*/, int movement /*=
int maxMovePointsLand = hero->maxMovePoints(true);
int maxMovePointsWater = hero->maxMovePoints(false);
auto maxMovePoints = [&](CGPathNode *cp) -> int
{
return cp->land ? maxMovePointsLand : maxMovePointsWater;
auto maxMovePoints = [&](CGPathNode *cp) -> int
{
return cp->land ? maxMovePointsLand : maxMovePointsWater;
};
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)
{
base.animationFile = hc->imageMapMale;
@ -237,8 +237,7 @@ void CHeroClassHandler::afterLoadFinalization()
// replace existing (if any) and add new template.
// Necessary for objects added via mods that don't have any templates in H3
VLC->dobjinfo->eraseAll(Obj::HERO, hc->id);
VLC->dobjinfo->registerTemplate(base);
VLC->objtypeh->getHandlerFor(Obj::HERO, base.subid)->addTemplate(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()
{
}
void CObjectWithRewardConstructor::init(const JsonNode & config)
{
int id = config["id"].Float();
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;
objectInfo.init(config);
}
CGObjectInstance * CObjectWithRewardConstructor::create(ObjectTemplate tmpl) const
{
assert(handlesID(tmpl));
auto ret = new CObjectWithReward();
ret->appearance = tmpl;
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
{
assert(handlesID(object->appearance));
objectInfos.at(object->ID).at(object->subID).info.configureObject(dynamic_cast<CObjectWithReward*>(object));
objectInfo.configureObject(dynamic_cast<CObjectWithReward*>(object));
}
const IObjectInfo * CObjectWithRewardConstructor::getObjectInfo(ObjectTemplate tmpl) const
{
assert(handlesID(tmpl));
return &objectInfos.at(tmpl.id).at(tmpl.subid).info;
return &objectInfo;
}

View File

@ -41,26 +41,16 @@ public:
void init(const JsonNode & objectConfig);
};
class CObjectWithRewardConstructor : public IObjectTypesHandler
class CObjectWithRewardConstructor : public AObjectTypeHandler
{
struct ObjectInfo
{
CRandomRewardObjectInfo info;
std::vector<ObjectTemplate> templates;
};
std::map<ui32, std::map<ui32, ObjectInfo> > objectInfos;
CRandomRewardObjectInfo objectInfo;
public:
CObjectWithRewardConstructor();
void init(const JsonNode & config);
std::vector<ObjectTemplate> getTemplates(si32 type, si32 subType) 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;
const IObjectInfo * getObjectInfo(ObjectTemplate tmpl) const override;

View File

@ -727,7 +727,7 @@ void CGHeroInstance::initHero()
type = VLC->heroh->heroes[subID];
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
{
@ -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())
destinationid = objs[Obj::MONOLITH2][subID][rand()%objs[Obj::MONOLITH2][subID].size()];
else
logGlobal->warnStream() << "Cannot find corresponding exit monolith for "<< id;
logGlobal->warnStream() << "Cannot find corresponding exit monolith for "<< id;
break;
case Obj::MONOLITH3://two way monolith - pick any other one
case Obj::WHIRLPOOL: //Whirlpool
@ -3530,7 +3530,7 @@ void CGTeleport::onHeroVisit( const CGHeroInstance * h ) const
}
}
else
logGlobal->warnStream() << "Cannot find corresponding exit monolith for "<< id;
logGlobal->warnStream() << "Cannot find corresponding exit monolith for "<< id;
break;
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())
{
logGlobal->warnStream() << "Cannot find exit... (obj at " << pos << ") :( ";
logGlobal->warnStream() << "Cannot find exit... (obj at " << pos << ") :( ";
return;
}
if (ID == Obj::WHIRLPOOL)

View File

@ -711,7 +711,7 @@ void CTownHandler::loadObject(std::string scope, std::string name, const JsonNod
void CTownHandler::afterLoadFinalization()
{
initializeRequirements();
ObjectTemplate base = VLC->dobjinfo->pickCandidates(Obj::TOWN, 0).front();
ObjectTemplate base = VLC->objtypeh->getHandlerFor(Obj::TOWN, 0)->getTemplates().front();
for (CFaction * fact : factions)
{
if (fact->town)
@ -721,13 +721,12 @@ void CTownHandler::afterLoadFinalization()
// replace existing (if any) and add new template.
// Necessary for objects added via mods that don't have any templates in H3
VLC->dobjinfo->eraseAll(Obj::TOWN, fact->index);
VLC->dobjinfo->registerTemplate(base);
VLC->objtypeh->getHandlerFor(Obj::TOWN, fact->index)->addTemplate(base);
assert(fact->town->dwellings.size() == fact->town->dwellingNames.size());
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
for (auto cre : fact->town->creatures[i])
@ -736,7 +735,7 @@ void CTownHandler::afterLoadFinalization()
base.animationFile = fact->town->dwellings[i];
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
}
}

View File

@ -582,7 +582,7 @@ DLL_LINKAGE void GiveHero::applyGs( CGameState *gs )
//bonus system
h->detachFrom(&gs->globalEffects);
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);
h->setOwner(player);
@ -623,7 +623,7 @@ DLL_LINKAGE void NewObject::applyGs( CGameState *gs )
o->subID = subID;
o->pos = 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());
o->hoverName = VLC->generaltexth->names[ID];

View File

@ -109,7 +109,7 @@ void LibClasses::init()
createHandler(objh, "Object", pomtime);
createHandler(dobjinfo, "Def information", pomtime);
createHandler(objtypeh, "Object types information", pomtime);
createHandler(spellh, "Spell", pomtime);
@ -135,7 +135,7 @@ void LibClasses::clear()
delete creh;
delete townh;
delete objh;
delete dobjinfo;
delete objtypeh;
delete spellh;
delete modh;
delete bth;
@ -152,7 +152,7 @@ void LibClasses::makeNull()
creh = nullptr;
townh = nullptr;
objh = nullptr;
dobjinfo = nullptr;
objtypeh = nullptr;
spellh = nullptr;
modh = nullptr;
bth = nullptr;

View File

@ -16,7 +16,7 @@ class CCreatureHandler;
class CSpellHandler;
class CBuildingHandler;
class CObjectHandler;
class CDefObjInfoHandler;
class CObjectTypesHandler;
class CTownHandler;
class CGeneralTextHandler;
class CModHandler;
@ -42,7 +42,7 @@ public:
CCreatureHandler * creh;
CSpellHandler * spellh;
CObjectHandler * objh;
CDefObjInfoHandler * dobjinfo;
CObjectTypesHandler * objtypeh;
CTownHandler * townh;
CGeneralTextHandler * generaltexth;
CModHandler * modh;
@ -60,7 +60,7 @@ public:
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;
if(!h.saving)
{

View File

@ -166,7 +166,7 @@ void CMapGenerator::genTowns()
}
town->subID = townId;
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::DEFAULT);
editManager->insertObject(town, int3(townPos[side].x, townPos[side].y + (i / 2) * 5, 0));