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:
parent
d805376ab8
commit
b5160acbac
@ -31,5 +31,5 @@ void CGameInfo::setFromLib()
|
||||
heroh = VLC->heroh;
|
||||
objh = VLC->objh;
|
||||
spellh = VLC->spellh;
|
||||
dobjinfo = VLC->dobjinfo;
|
||||
objtypeh = VLC->objtypeh;
|
||||
}
|
||||
|
@ -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();
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
};
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
}
|
||||
}
|
||||
|
@ -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];
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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));
|
||||
|
Loading…
Reference in New Issue
Block a user