1
0
mirror of https://github.com/vcmi/vcmi.git synced 2024-12-26 22:57:00 +02:00

Merge pull request #1017 from vcmi/fix-mine-templates

Fix incorrect templates for mines in HoTA
This commit is contained in:
Andrii Danylchenko 2022-10-09 11:25:59 +03:00 committed by GitHub
commit 360f079bb7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 48 additions and 85 deletions

View File

@ -116,13 +116,15 @@ std::vector<JsonNode> CObjectClassesHandler::loadLegacyData(size_t dataSize)
size_t totalNumber = static_cast<size_t>(parser.readNumber()); // first line contains number of objects to read and nothing else
parser.endLine();
for (size_t i=0; i<totalNumber; i++)
for (size_t i = 0; i < totalNumber; i++)
{
auto templ = new ObjectTemplate;
templ->readTxt(parser);
auto tmpl = new ObjectTemplate;
tmpl->readTxt(parser);
parser.endLine();
std::pair<si32, si32> key(templ->id.num, templ->subid);
legacyTemplates.insert(std::make_pair(key, std::shared_ptr<const ObjectTemplate>(templ)));
std::pair<si32, si32> key(tmpl->id.num, tmpl->subid);
legacyTemplates.insert(std::make_pair(key, std::shared_ptr<const ObjectTemplate>(tmpl)));
}
std::vector<JsonNode> ret(dataSize);// create storage for 256 objects
@ -560,10 +562,6 @@ SObjectSounds AObjectTypeHandler::getSounds() const
void AObjectTypeHandler::addTemplate(std::shared_ptr<const ObjectTemplate> templ)
{
//Otherwise the template remains constant
auto ptr = const_cast<ObjectTemplate*>(templ.get());
ptr->id = Obj(type);
ptr->subid = subtype;
templates.push_back(templ);
}

View File

@ -33,19 +33,11 @@ protected:
auto obj = new ObjectType();
preInitObject(obj);
//Set custom template or leave null
if (tmpl)
{
obj->appearance = tmpl;
}
else
{
auto templates = getTemplates();
if (templates.empty())
{
throw std::runtime_error("No handler for created object");
}
obj->appearance = templates.front(); //just any template for now, will be initialized later
}
return obj;
}

View File

@ -490,6 +490,7 @@ bool ObjectManager::addGuard(rmg::Object & object, si32 strength, bool zoneGuard
auto & instance = object.addInstance(*guard);
instance.setPosition(guardPos - object.getPosition());
instance.setAnyTemplate(); //terrain is irrelevant for monsters, but monsters need some template now
return true;
}

View File

@ -105,20 +105,26 @@ void Object::Instance::setPositionRaw(const int3 & position)
dObject.pos = dPosition + dParent.getPosition();
}
void Object::Instance::setTemplate(const TerrainId & terrain)
void Object::Instance::setAnyTemplate()
{
if(dObject.appearance->id == Obj::NO_OBJ)
auto templates = VLC->objtypeh->getHandlerFor(dObject.ID, dObject.subID)->getTemplates();
if(templates.empty())
throw rmgException(boost::to_string(boost::format("Did not find any graphics for object (%d,%d)") % dObject.ID % dObject.subID));
dObject.appearance = templates.front();
dAccessibleAreaCache.clear();
setPosition(getPosition(false));
}
void Object::Instance::setTemplate(TerrainId terrain)
{
auto templates = VLC->objtypeh->getHandlerFor(dObject.ID, dObject.subID)->getTemplates(terrain);
if (templates.empty())
{
auto templates = VLC->objtypeh->getHandlerFor(dObject.ID, dObject.subID)->getTemplates(terrain);
auto terrainName = VLC->terrainTypeHandler->terrains()[terrain].name;
if (templates.empty())
{
throw rmgException(boost::to_string(boost::format("Did not find graphics for object (%d,%d) at %s") %
dObject.ID % dObject.subID % terrainName));
}
dObject.appearance = templates.front();
throw rmgException(boost::to_string(boost::format("Did not find graphics for object (%d,%d) at %s") % dObject.ID % dObject.subID % terrainName));
}
dObject.appearance = templates.front();
dAccessibleAreaCache.clear();
setPosition(getPosition(false));
}
@ -283,6 +289,21 @@ void Object::Instance::finalize(RmgMap & map)
if(!map.isOnMap(getPosition(true)))
throw rmgException(boost::to_string(boost::format("Position of object %d at %s is outside the map") % dObject.id % getPosition(true).toString()));
//If no specific template was defined for this object, select any matching
if (!dObject.appearance)
{
auto terrainType = map.map().getTile(getPosition(true)).terType;
auto templates = VLC->objtypeh->getHandlerFor(dObject.ID, dObject.subID)->getTemplates(terrainType->id);
if (templates.empty())
{
throw rmgException(boost::to_string(boost::format("Did not find graphics for object (%d,%d) at %s (terrain %d)") % dObject.ID % dObject.subID % getPosition(true).toString() % terrainType));
}
else
{
setTemplate(terrainType->id);
}
}
if (dObject.isVisitable() && !map.isOnMap(dObject.visitablePos()))
throw rmgException(boost::to_string(boost::format("Visitable tile %s of object %d at %s is outside the map") % dObject.visitablePos().toString() % dObject.id % dObject.pos.toString()));
@ -292,17 +313,6 @@ void Object::Instance::finalize(RmgMap & map)
throw rmgException(boost::to_string(boost::format("Tile %s of object %d at %s is outside the map") % tile.toString() % dObject.id % dObject.pos.toString()));
}
if (dObject.appearance->id == Obj::NO_OBJ)
{
auto terrainType = map.map().getTile(getPosition(true)).terType;
auto templates = VLC->objtypeh->getHandlerFor(dObject.ID, dObject.subID)->getTemplates(terrainType->id);
if (templates.empty())
throw rmgException(boost::to_string(boost::format("Did not find graphics for object (%d,%d) at %s (terrain %d)") %
dObject.ID % dObject.subID % getPosition(true).toString() % terrainType->name));
setTemplate(terrainType->id);
}
for(auto & tile : getBlockedArea().getTilesVector())
{
map.setOccupied(tile, ETileType::ETileType::USED);

View File

@ -35,7 +35,8 @@ public:
int3 getVisitablePosition() const;
bool isVisitableFrom(const int3 & tile) const;
const Area & getAccessibleArea() const;
void setTemplate(const TerrainId & terrain); //cache invalidation
void setTemplate(TerrainId terrain); //cache invalidation
void setAnyTemplate(); //cache invalidation
int3 getPosition(bool isAbsolute = false) const;
void setPosition(const int3 & position); //cache invalidation

View File

@ -391,56 +391,17 @@ public:
else
data.reset();
}
template <typename T>
void load(std::shared_ptr<const T> &data) //version of the above for const ptr
void load(std::shared_ptr<const T> & data)
{
typedef typename std::remove_const<T>::type NonConstT;
NonConstT *internalPtr;
load(internalPtr);
std::shared_ptr<T> nonConstData;
void *internalPtrDerived = typeList.castToMostDerived(internalPtr);
load(nonConstData);
if(internalPtr)
{
auto itr = loadedSharedPointers.find(internalPtrDerived);
if(itr != loadedSharedPointers.end())
{
// This pointer is already loaded. The "data" needs to be pointed to it,
// so their shared state is actually shared.
try
{
auto actualType = typeList.getTypeInfo(internalPtr);
auto typeWeNeedToReturn = typeList.getTypeInfo<T>();
if(*actualType == *typeWeNeedToReturn)
{
// No casting needed, just unpack already stored shared_ptr and return it
data = boost::any_cast<std::shared_ptr<const T>>(itr->second);
}
else
{
// We need to perform series of casts
auto ret = typeList.castShared(itr->second, actualType, typeWeNeedToReturn);
data = boost::any_cast<std::shared_ptr<const T>>(ret);
}
}
catch(std::exception &e)
{
logGlobal->error(e.what());
logGlobal->error("Failed to cast stored shared ptr. Real type: %s. Needed type %s. FIXME FIXME FIXME", itr->second.type().name(), typeid(std::shared_ptr<T>).name());
//TODO scenario with inheritance -> we can have stored ptr to base and load ptr to derived (or vice versa)
throw;
}
}
else
{
auto hlp = std::shared_ptr<const T>(internalPtr);
data = hlp; //possibly adds const
loadedSharedPointers[internalPtrDerived] = typeList.castSharedToMostDerived(hlp);
}
}
else
data.reset();
data = nonConstData;
}
template <typename T>
void load(std::unique_ptr<T> &data)
{