mirror of
				https://github.com/vcmi/vcmi.git
				synced 2025-10-31 00:07:39 +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:
		| @@ -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)); | ||||
|   | ||||
		Reference in New Issue
	
	Block a user