mirror of
https://github.com/vcmi/vcmi.git
synced 2025-11-23 22:37:55 +02:00
Implemented support for fixed monster def's from hota
This commit is contained in:
@@ -625,17 +625,25 @@ CCreature * CCreatureHandler::loadFromJson(const std::string & scope, const Json
|
|||||||
registerObject(scope, type_name, extraName.String(), cre->getIndex());
|
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)
|
VLC->modh->identifiers.requestIdentifier(scope, "object", "monster", [=](si32 index)
|
||||||
{
|
{
|
||||||
JsonNode conf;
|
JsonNode conf;
|
||||||
conf.setMeta(scope);
|
conf.setMeta(scope);
|
||||||
|
|
||||||
VLC->objtypeh->loadSubObject(cre->identifier, conf, Obj::MONSTER, cre->getId().num);
|
VLC->objtypeh->loadSubObject(cre->identifier, conf, Obj::MONSTER, cre->getId().num);
|
||||||
if (!cre->advMapDef.empty())
|
if (!advMapFile.isNull())
|
||||||
{
|
{
|
||||||
JsonNode templ;
|
JsonNode templ;
|
||||||
templ["animation"].String() = cre->advMapDef;
|
templ["animation"] = advMapFile;
|
||||||
|
if (!advMapMask.isNull())
|
||||||
|
templ["mask"] = advMapMask;
|
||||||
templ.setMeta(scope);
|
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);
|
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.attackClimaxFrame = static_cast<int>(missile["attackClimaxFrame"].Float());
|
||||||
cre->animation.missleFrameAngles = missile["frameAngles"].convertTo<std::vector<double> >();
|
cre->animation.missleFrameAngles = missile["frameAngles"].convertTo<std::vector<double> >();
|
||||||
|
|
||||||
cre->advMapDef = graphics["map"].String();
|
|
||||||
cre->smallIconName = graphics["iconSmall"].String();
|
cre->smallIconName = graphics["iconSmall"].String();
|
||||||
cre->largeIconName = graphics["iconLarge"].String();
|
cre->largeIconName = graphics["iconLarge"].String();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -58,7 +58,6 @@ public:
|
|||||||
std::set<CreatureID> upgrades; // IDs of creatures to which this creature can be upgraded
|
std::set<CreatureID> upgrades; // IDs of creatures to which this creature can be upgraded
|
||||||
|
|
||||||
std::string animDefName; // creature animation used during battles
|
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.
|
si32 iconIndex = -1; // index of icon in files like twcrport, used in tests now.
|
||||||
/// names of files with appropriate icons. Used only during loading
|
/// names of files with appropriate icons. Used only during loading
|
||||||
@@ -230,7 +229,6 @@ public:
|
|||||||
h & ammMax;
|
h & ammMax;
|
||||||
h & level;
|
h & level;
|
||||||
h & animDefName;
|
h & animDefName;
|
||||||
h & advMapDef;
|
|
||||||
h & iconIndex;
|
h & iconIndex;
|
||||||
h & smallIconName;
|
h & smallIconName;
|
||||||
h & largeIconName;
|
h & largeIconName;
|
||||||
|
|||||||
@@ -649,7 +649,7 @@ void CGameState::randomizeObject(CGObjectInstance *cur)
|
|||||||
std::pair<Obj,int> ran = pickObject(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(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
|
cur->setType(cur->ID, cur->subID); // update def, if necessary
|
||||||
}
|
}
|
||||||
else if(ran.first==Obj::HERO)//special code for hero
|
else if(ran.first==Obj::HERO)//special code for hero
|
||||||
|
|||||||
@@ -148,6 +148,11 @@ SObjectSounds AObjectTypeHandler::getSounds() const
|
|||||||
return sounds;
|
return sounds;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void AObjectTypeHandler::clearTemplates()
|
||||||
|
{
|
||||||
|
templates.clear();
|
||||||
|
}
|
||||||
|
|
||||||
void AObjectTypeHandler::addTemplate(const std::shared_ptr<const ObjectTemplate> & templ)
|
void AObjectTypeHandler::addTemplate(const std::shared_ptr<const ObjectTemplate> & templ)
|
||||||
{
|
{
|
||||||
templates.push_back(templ);
|
templates.push_back(templ);
|
||||||
|
|||||||
@@ -70,6 +70,7 @@ public:
|
|||||||
|
|
||||||
void addTemplate(const std::shared_ptr<const ObjectTemplate> & templ);
|
void addTemplate(const std::shared_ptr<const ObjectTemplate> & templ);
|
||||||
void addTemplate(JsonNode config);
|
void addTemplate(JsonNode config);
|
||||||
|
void clearTemplates();
|
||||||
|
|
||||||
/// returns all templates matching parameters
|
/// returns all templates matching parameters
|
||||||
std::vector<std::shared_ptr<const ObjectTemplate>> getTemplates() const;
|
std::vector<std::shared_ptr<const ObjectTemplate>> getTemplates() const;
|
||||||
|
|||||||
@@ -105,7 +105,7 @@ std::set<int3> CGObjectInstance::getBlockedOffsets() const
|
|||||||
return appearance->getBlockedOffsets();
|
return appearance->getBlockedOffsets();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CGObjectInstance::setType(si32 ID, si32 subID)
|
void CGObjectInstance::setType(si32 newID, si32 newSubID)
|
||||||
{
|
{
|
||||||
auto position = visitablePos();
|
auto position = visitablePos();
|
||||||
auto oldOffset = getVisitableOffset();
|
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
|
//recalculate blockvis tiles - new appearance might have different blockmap than before
|
||||||
cb->gameState()->map->removeBlockVisTiles(this, true);
|
cb->gameState()->map->removeBlockVisTiles(this, true);
|
||||||
auto handler = VLC->objtypeh->getHandlerFor(ID, subID);
|
auto handler = VLC->objtypeh->getHandlerFor(newID, newSubID);
|
||||||
if(!handler)
|
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;
|
return;
|
||||||
}
|
}
|
||||||
if(!handler->getTemplates(tile.terType->getId()).empty())
|
if(!handler->getTemplates(tile.terType->getId()).empty())
|
||||||
@@ -125,22 +125,26 @@ void CGObjectInstance::setType(si32 ID, si32 subID)
|
|||||||
}
|
}
|
||||||
else
|
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
|
appearance = handler->getTemplates()[0]; // get at least some appearance since alternative is crash
|
||||||
}
|
}
|
||||||
|
|
||||||
if(this->ID == Obj::PRISON && ID == Obj::HERO)
|
bool needToAdjustOffset = false;
|
||||||
{
|
|
||||||
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
|
// 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();
|
||||||
pos = pos - oldOffset + newOffset;
|
pos = pos - oldOffset + newOffset;
|
||||||
}
|
}
|
||||||
|
|
||||||
this->ID = Obj(ID);
|
this->ID = Obj(newID);
|
||||||
this->subID = subID;
|
this->subID = newSubID;
|
||||||
|
|
||||||
cb->gameState()->map->addBlockVisTiles(this);
|
cb->gameState()->map->addBlockVisTiles(this);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user