浏览代码

Implemented support for fixed monster def's from hota

Ivan Savenko 2 年之前
父节点
当前提交
8dde8018d0

+ 10 - 3
lib/CCreatureHandler.cpp

@@ -625,17 +625,25 @@ CCreature * CCreatureHandler::loadFromJson(const std::string & scope, const Json
 			registerObject(scope, type_name, extraName.String(), cre->getIndex());
 	}
 
+	JsonNode advMapFile = node["graphics"]["map"];
+	JsonNode advMapMask = node["graphics"]["mapMask"];
+
 	VLC->modh->identifiers.requestIdentifier(scope, "object", "monster", [=](si32 index)
 	{
 		JsonNode conf;
 		conf.setMeta(scope);
 
 		VLC->objtypeh->loadSubObject(cre->identifier, conf, Obj::MONSTER, cre->getId().num);
-		if (!cre->advMapDef.empty())
+		if (!advMapFile.isNull())
 		{
 			JsonNode templ;
-			templ["animation"].String() = cre->advMapDef;
+			templ["animation"] = advMapFile;
+			if (!advMapMask.isNull())
+				templ["mask"] = advMapMask;
 			templ.setMeta(scope);
+
+			// if creature has custom advMapFile, reset any potentially imported H3M templates and use provided file instead
+			VLC->objtypeh->getHandlerFor(Obj::MONSTER, cre->getId().num)->clearTemplates();
 			VLC->objtypeh->getHandlerFor(Obj::MONSTER, cre->getId().num)->addTemplate(templ);
 		}
 
@@ -871,7 +879,6 @@ void CCreatureHandler::loadJsonAnimation(CCreature * cre, const JsonNode & graph
 	cre->animation.attackClimaxFrame = static_cast<int>(missile["attackClimaxFrame"].Float());
 	cre->animation.missleFrameAngles = missile["frameAngles"].convertTo<std::vector<double> >();
 
-	cre->advMapDef = graphics["map"].String();
 	cre->smallIconName = graphics["iconSmall"].String();
 	cre->largeIconName = graphics["iconLarge"].String();
 }

+ 0 - 2
lib/CCreatureHandler.h

@@ -58,7 +58,6 @@ public:
 	std::set<CreatureID> upgrades; // IDs of creatures to which this creature can be upgraded
 
 	std::string animDefName; // creature animation used during battles
-	std::string advMapDef; //for new creatures only, image for adventure map
 
 	si32 iconIndex = -1; // index of icon in files like twcrport, used in tests now.
 	/// names of files with appropriate icons. Used only during loading
@@ -230,7 +229,6 @@ public:
 		h & ammMax;
 		h & level;
 		h & animDefName;
-		h & advMapDef;
 		h & iconIndex;
 		h & smallIconName;
 		h & largeIconName;

+ 1 - 1
lib/CGameState.cpp

@@ -649,7 +649,7 @@ void CGameState::randomizeObject(CGObjectInstance *cur)
 	std::pair<Obj,int> ran = pickObject(cur);
 	if(ran.first == Obj::NO_OBJ || ran.second<0) //this is not a random object, or we couldn't find anything
 	{
-		if(cur->ID==Obj::TOWN)
+		if(cur->ID==Obj::TOWN || cur->ID==Obj::MONSTER)
 			cur->setType(cur->ID, cur->subID); // update def, if necessary
 	}
 	else if(ran.first==Obj::HERO)//special code for hero

+ 5 - 0
lib/mapObjectConstructors/AObjectTypeHandler.cpp

@@ -148,6 +148,11 @@ SObjectSounds AObjectTypeHandler::getSounds() const
 	return sounds;
 }
 
+void AObjectTypeHandler::clearTemplates()
+{
+	templates.clear();
+}
+
 void AObjectTypeHandler::addTemplate(const std::shared_ptr<const ObjectTemplate> & templ)
 {
 	templates.push_back(templ);

+ 1 - 0
lib/mapObjectConstructors/AObjectTypeHandler.h

@@ -70,6 +70,7 @@ public:
 
 	void addTemplate(const std::shared_ptr<const ObjectTemplate> & templ);
 	void addTemplate(JsonNode config);
+	void clearTemplates();
 
 	/// returns all templates matching parameters
 	std::vector<std::shared_ptr<const ObjectTemplate>> getTemplates() const;

+ 15 - 11
lib/mapObjects/CGObjectInstance.cpp

@@ -105,7 +105,7 @@ std::set<int3> CGObjectInstance::getBlockedOffsets() const
 	return appearance->getBlockedOffsets();
 }
 
-void CGObjectInstance::setType(si32 ID, si32 subID)
+void CGObjectInstance::setType(si32 newID, si32 newSubID)
 {
 	auto position = visitablePos();
 	auto oldOffset = getVisitableOffset();
@@ -113,10 +113,10 @@ void CGObjectInstance::setType(si32 ID, si32 subID)
 
 	//recalculate blockvis tiles - new appearance might have different blockmap than before
 	cb->gameState()->map->removeBlockVisTiles(this, true);
-	auto handler = VLC->objtypeh->getHandlerFor(ID, subID);
+	auto handler = VLC->objtypeh->getHandlerFor(newID, newSubID);
 	if(!handler)
 	{
-		logGlobal->error("Unknown object type %d:%d at %s", ID, subID, visitablePos().toString());
+		logGlobal->error("Unknown object type %d:%d at %s", newID, newSubID, visitablePos().toString());
 		return;
 	}
 	if(!handler->getTemplates(tile.terType->getId()).empty())
@@ -125,22 +125,26 @@ void CGObjectInstance::setType(si32 ID, si32 subID)
 	}
 	else
 	{
-		logGlobal->warn("Object %d:%d at %s has no templates suitable for terrain %s", ID, subID, visitablePos().toString(), tile.terType->getNameTranslated());
+		logGlobal->warn("Object %d:%d at %s has no templates suitable for terrain %s", newID, newSubID, visitablePos().toString(), tile.terType->getNameTranslated());
 		appearance = handler->getTemplates()[0]; // get at least some appearance since alternative is crash
 	}
 
-	if(this->ID == Obj::PRISON && ID == Obj::HERO)
+	bool needToAdjustOffset = false;
+
+	// FIXME: potentially unused code - setType is NOT called when releasing hero from prison
+	// instead, appearance update & pos adjustment occurs in GiveHero::applyGs
+	needToAdjustOffset |= this->ID == Obj::PRISON && newID == Obj::HERO;
+	needToAdjustOffset |= newID == Obj::MONSTER;
+
+	if(needToAdjustOffset)
 	{
+		// adjust position since object visitable offset might have changed
 		auto newOffset = getVisitableOffset();
-		// FIXME: potentially unused code - setType is NOT called when releasing hero from prison
-		// instead, appearance update & pos adjustment occurs in GiveHero::applyGs
-
-		// adjust position since hero and prison may have different visitable offset
 		pos = pos - oldOffset + newOffset;
 	}
 
-	this->ID = Obj(ID);
-	this->subID = subID;
+	this->ID = Obj(newID);
+	this->subID = newSubID;
 
 	cb->gameState()->map->addBlockVisTiles(this);
 }