mirror of
https://github.com/vcmi/vcmi.git
synced 2025-03-25 21:38:59 +02:00
Fixed loading of maps with objects owned by non-existing players
This commit is contained in:
parent
f997241da1
commit
f84665b5ec
@ -1070,17 +1070,17 @@ CGObjectInstance * CMapLoaderH3M::readScholar()
|
||||
object->bonusType = static_cast<CGScholar::EBonusType>(reader->readUInt8());
|
||||
object->bonusID = reader->readUInt8();
|
||||
reader->skipZero(6);
|
||||
return object;
|
||||
}
|
||||
|
||||
CGObjectInstance * CMapLoaderH3M::readGarrison()
|
||||
{
|
||||
auto * object = new CGGarrison();
|
||||
|
||||
object->setOwner(reader->readPlayer32());
|
||||
readCreatureSet(object, 7);
|
||||
if(features.levelAB)
|
||||
object->removableUnits = reader->readBool();
|
||||
return object;
|
||||
}
|
||||
|
||||
CGObjectInstance * CMapLoaderH3M::readGarrison(const int3 & mapPosition)
|
||||
{
|
||||
auto * object = new CGGarrison();
|
||||
|
||||
setOwnerAndValidate(mapPosition, object, reader->readPlayer32());
|
||||
readCreatureSet(object, 7);
|
||||
if(features.levelAB)
|
||||
object->removableUnits = reader->readBool();
|
||||
else
|
||||
object->removableUnits = true;
|
||||
|
||||
@ -1129,26 +1129,26 @@ CGObjectInstance * CMapLoaderH3M::readResource(const int3 & mapPosition, std::sh
|
||||
|
||||
CGObjectInstance * CMapLoaderH3M::readMine(const int3 & mapPosition, std::shared_ptr<const ObjectTemplate> objectTemplate)
|
||||
{
|
||||
auto * object = new CGMine();
|
||||
if(objectTemplate->subid < 7)
|
||||
{
|
||||
object->setOwner(reader->readPlayer32());
|
||||
}
|
||||
else
|
||||
{
|
||||
auto * object = new CGMine();
|
||||
if(objectTemplate->subid < 7)
|
||||
{
|
||||
setOwnerAndValidate(mapPosition, object, reader->readPlayer32());
|
||||
}
|
||||
else
|
||||
{
|
||||
object->setOwner(PlayerColor::NEUTRAL);
|
||||
reader->readBitmask(object->abandonedMineResources, features.resourcesBytes, features.resourcesCount, false);
|
||||
}
|
||||
return object;
|
||||
}
|
||||
|
||||
CGObjectInstance * CMapLoaderH3M::readDwelling(const int3 & position)
|
||||
{
|
||||
auto * object = new CGDwelling();
|
||||
object->setOwner(reader->readPlayer32());
|
||||
return object;
|
||||
}
|
||||
|
||||
CGObjectInstance * CMapLoaderH3M::readDwelling(const int3 & position)
|
||||
{
|
||||
auto * object = new CGDwelling();
|
||||
setOwnerAndValidate(position, object, reader->readPlayer32());
|
||||
return object;
|
||||
}
|
||||
|
||||
CGObjectInstance * CMapLoaderH3M::readDwellingRandom(const int3 & mapPosition, std::shared_ptr<const ObjectTemplate> objectTemplate)
|
||||
{
|
||||
auto * object = new CGDwelling();
|
||||
@ -1167,13 +1167,13 @@ CGObjectInstance * CMapLoaderH3M::readDwellingRandom(const int3 & mapPosition, s
|
||||
break;
|
||||
default:
|
||||
throw std::runtime_error("Invalid random dwelling format");
|
||||
}
|
||||
spec->owner = object;
|
||||
|
||||
object->setOwner(reader->readPlayer32());
|
||||
|
||||
//216 and 217
|
||||
if(auto * castleSpec = dynamic_cast<CCreGenAsCastleInfo *>(spec))
|
||||
}
|
||||
spec->owner = object;
|
||||
|
||||
setOwnerAndValidate(mapPosition, object, reader->readPlayer32());
|
||||
|
||||
//216 and 217
|
||||
if(auto * castleSpec = dynamic_cast<CCreGenAsCastleInfo *>(spec))
|
||||
{
|
||||
castleSpec->instanceId = "";
|
||||
castleSpec->identifier = reader->readUInt32();
|
||||
@ -1218,13 +1218,13 @@ CGObjectInstance * CMapLoaderH3M::readShrine()
|
||||
}
|
||||
|
||||
CGObjectInstance * CMapLoaderH3M::readHeroPlaceholder(const int3 & mapPosition)
|
||||
{
|
||||
auto * object = new CGHeroPlaceholder();
|
||||
|
||||
object->setOwner(reader->readPlayer());
|
||||
|
||||
HeroTypeID htid = reader->readHero(); //hero type id
|
||||
object->subID = htid.getNum();
|
||||
{
|
||||
auto * object = new CGHeroPlaceholder();
|
||||
|
||||
setOwnerAndValidate(mapPosition, object, reader->readPlayer());
|
||||
|
||||
HeroTypeID htid = reader->readHero(); //hero type id
|
||||
object->subID = htid.getNum();
|
||||
|
||||
if(htid.getNum() == -1)
|
||||
{
|
||||
@ -1268,16 +1268,16 @@ CGObjectInstance * CMapLoaderH3M::readQuestGuard(const int3 & mapPosition)
|
||||
{
|
||||
auto * guard = new CGQuestGuard();
|
||||
readQuest(guard, mapPosition);
|
||||
return guard;
|
||||
}
|
||||
|
||||
CGObjectInstance * CMapLoaderH3M::readShipyard()
|
||||
{
|
||||
auto * object = new CGShipyard();
|
||||
object->setOwner(reader->readPlayer32());
|
||||
return object;
|
||||
}
|
||||
|
||||
return guard;
|
||||
}
|
||||
|
||||
CGObjectInstance * CMapLoaderH3M::readShipyard(const int3 & mapPosition)
|
||||
{
|
||||
auto * object = new CGShipyard();
|
||||
setOwnerAndValidate(mapPosition, object, reader->readPlayer32());
|
||||
return object;
|
||||
}
|
||||
|
||||
CGObjectInstance * CMapLoaderH3M::readBorderGuard()
|
||||
{
|
||||
return new CGBorderGuard();
|
||||
@ -1293,16 +1293,16 @@ CGObjectInstance * CMapLoaderH3M::readBorderGate(const int3 & mapPosition, std::
|
||||
return new CGObjectInstance();
|
||||
|
||||
logGlobal->warn("Map '%s: Quest gates at %s are not implemented!", mapName, mapPosition.toString());
|
||||
return readQuestGuard(mapPosition);
|
||||
}
|
||||
|
||||
CGObjectInstance * CMapLoaderH3M::readLighthouse()
|
||||
{
|
||||
auto * object = new CGLighthouse();
|
||||
object->tempOwner = reader->readPlayer32();
|
||||
return object;
|
||||
}
|
||||
|
||||
return readQuestGuard(mapPosition);
|
||||
}
|
||||
|
||||
CGObjectInstance * CMapLoaderH3M::readLighthouse(const int3 & mapPosition)
|
||||
{
|
||||
auto * object = new CGLighthouse();
|
||||
setOwnerAndValidate(mapPosition, object, reader->readPlayer32());
|
||||
return object;
|
||||
}
|
||||
|
||||
CGObjectInstance * CMapLoaderH3M::readBank(const int3 & mapPosition, std::shared_ptr<const ObjectTemplate> objectTemplate)
|
||||
{
|
||||
if(features.levelHOTA3)
|
||||
@ -1376,13 +1376,13 @@ CGObjectInstance * CMapLoaderH3M::readObject(std::shared_ptr<const ObjectTemplat
|
||||
return readWitchHut();
|
||||
case Obj::SCHOLAR:
|
||||
return readScholar();
|
||||
|
||||
case Obj::GARRISON:
|
||||
case Obj::GARRISON2:
|
||||
return readGarrison();
|
||||
|
||||
case Obj::ARTIFACT:
|
||||
case Obj::RANDOM_ART:
|
||||
|
||||
case Obj::GARRISON:
|
||||
case Obj::GARRISON2:
|
||||
return readGarrison(mapPosition);
|
||||
|
||||
case Obj::ARTIFACT:
|
||||
case Obj::RANDOM_ART:
|
||||
case Obj::RANDOM_TREASURE_ART:
|
||||
case Obj::RANDOM_MINOR_ART:
|
||||
case Obj::RANDOM_MAJOR_ART:
|
||||
@ -1424,13 +1424,13 @@ CGObjectInstance * CMapLoaderH3M::readObject(std::shared_ptr<const ObjectTemplat
|
||||
return readDwellingRandom(mapPosition, objectTemplate);
|
||||
|
||||
case Obj::QUEST_GUARD:
|
||||
return readQuestGuard(mapPosition);
|
||||
|
||||
case Obj::SHIPYARD:
|
||||
return readShipyard();
|
||||
|
||||
case Obj::HERO_PLACEHOLDER:
|
||||
return readHeroPlaceholder(mapPosition);
|
||||
return readQuestGuard(mapPosition);
|
||||
|
||||
case Obj::SHIPYARD:
|
||||
return readShipyard(mapPosition);
|
||||
|
||||
case Obj::HERO_PLACEHOLDER:
|
||||
return readHeroPlaceholder(mapPosition);
|
||||
|
||||
case Obj::BORDERGUARD:
|
||||
return readBorderGuard();
|
||||
@ -1439,13 +1439,13 @@ CGObjectInstance * CMapLoaderH3M::readObject(std::shared_ptr<const ObjectTemplat
|
||||
return readBorderGate(mapPosition, objectTemplate);
|
||||
|
||||
case Obj::PYRAMID:
|
||||
return readPyramid(mapPosition, objectTemplate);
|
||||
|
||||
case Obj::LIGHTHOUSE:
|
||||
return readLighthouse();
|
||||
|
||||
case Obj::CREATURE_BANK:
|
||||
case Obj::DERELICT_SHIP:
|
||||
return readPyramid(mapPosition, objectTemplate);
|
||||
|
||||
case Obj::LIGHTHOUSE:
|
||||
return readLighthouse(mapPosition);
|
||||
|
||||
case Obj::CREATURE_BANK:
|
||||
case Obj::DERELICT_SHIP:
|
||||
case Obj::DRAGON_UTOPIA:
|
||||
case Obj::CRYPT:
|
||||
case Obj::SHIPWRECK:
|
||||
@ -1538,12 +1538,40 @@ void CMapLoaderH3M::readCreatureSet(CCreatureSet * out, int number)
|
||||
out->putStack(SlotID(index), result);
|
||||
}
|
||||
|
||||
out->validTypes(true);
|
||||
}
|
||||
|
||||
CGObjectInstance * CMapLoaderH3M::readHero(const int3 & mapPosition, const ObjectInstanceID & objectInstanceID)
|
||||
{
|
||||
auto * object = new CGHeroInstance();
|
||||
out->validTypes(true);
|
||||
}
|
||||
|
||||
void CMapLoaderH3M::setOwnerAndValidate(const int3 & mapPosition, CGObjectInstance * object, const PlayerColor & owner)
|
||||
{
|
||||
assert(owner.isValidPlayer() || owner == PlayerColor::NEUTRAL);
|
||||
|
||||
if(owner == PlayerColor::NEUTRAL)
|
||||
{
|
||||
object->setOwner(PlayerColor::NEUTRAL);
|
||||
return;
|
||||
}
|
||||
|
||||
if(!owner.isValidPlayer())
|
||||
{
|
||||
object->setOwner(PlayerColor::NEUTRAL);
|
||||
logGlobal->warn("Map '%s': Object at %s - owned by invalid player %d! Will be set to neutral!", mapName, mapPosition.toString(), int(owner.getNum()));
|
||||
return;
|
||||
}
|
||||
|
||||
if(!mapHeader->players[owner.getNum()].canAnyonePlay())
|
||||
{
|
||||
object->setOwner(PlayerColor::NEUTRAL);
|
||||
logGlobal->warn("Map '%s': Object at %s - owned by non-existing player %d! Will be set to neutral!", mapName, mapPosition.toString(), int(owner.getNum())
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
object->setOwner(owner);
|
||||
}
|
||||
|
||||
CGObjectInstance * CMapLoaderH3M::readHero(const int3 & mapPosition, const ObjectInstanceID & objectInstanceID)
|
||||
{
|
||||
auto * object = new CGHeroInstance();
|
||||
|
||||
if(features.levelAB)
|
||||
{
|
||||
@ -1564,13 +1592,13 @@ CGObjectInstance * CMapLoaderH3M::readHero(const int3 & mapPosition, const Objec
|
||||
delete object;
|
||||
object = elem;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
object->setOwner(owner);
|
||||
object->portrait = object->subID;
|
||||
|
||||
for(auto & elem : map->disposedHeroes)
|
||||
}
|
||||
}
|
||||
|
||||
setOwnerAndValidate(mapPosition, object, owner);
|
||||
object->portrait = object->subID;
|
||||
|
||||
for(auto & elem : map->disposedHeroes)
|
||||
{
|
||||
if(elem.heroId == object->subID)
|
||||
{
|
||||
@ -1945,13 +1973,14 @@ void CMapLoaderH3M::readQuest(IQuestObject * guard, const int3 & position)
|
||||
CGObjectInstance * CMapLoaderH3M::readTown(const int3 & position, std::shared_ptr<const ObjectTemplate> objectTemplate)
|
||||
{
|
||||
auto * object = new CGTownInstance();
|
||||
if(features.levelAB)
|
||||
object->identifier = reader->readUInt32();
|
||||
|
||||
object->tempOwner = reader->readPlayer();
|
||||
bool hasName = reader->readBool();
|
||||
if(hasName)
|
||||
object->setNameTranslated(readLocalizedString(TextIdentifier("town", position.x, position.y, position.z, "name")));
|
||||
if(features.levelAB)
|
||||
object->identifier = reader->readUInt32();
|
||||
|
||||
setOwnerAndValidate(position, object, reader->readPlayer());
|
||||
|
||||
bool hasName = reader->readBool();
|
||||
if(hasName)
|
||||
object->setNameTranslated(readLocalizedString(TextIdentifier("town", position.x, position.y, position.z, "name")));
|
||||
|
||||
bool hasGarrison = reader->readBool();
|
||||
if(hasGarrison)
|
||||
|
@ -31,6 +31,7 @@ class ObjectInstanceID;
|
||||
class BuildingID;
|
||||
class ObjectTemplate;
|
||||
class SpellID;
|
||||
class PlayerColor;
|
||||
class int3;
|
||||
|
||||
class DLL_LINKAGE CMapLoaderH3M : public IMapLoader
|
||||
@ -165,7 +166,7 @@ private:
|
||||
CGObjectInstance * readSign(const int3 & position);
|
||||
CGObjectInstance * readWitchHut();
|
||||
CGObjectInstance * readScholar();
|
||||
CGObjectInstance * readGarrison();
|
||||
CGObjectInstance * readGarrison(const int3 & mapPosition);
|
||||
CGObjectInstance * readArtifact(const int3 & position, std::shared_ptr<const ObjectTemplate> objTempl);
|
||||
CGObjectInstance * readResource(const int3 & position, std::shared_ptr<const ObjectTemplate> objTempl);
|
||||
CGObjectInstance * readMine(const int3 & position, std::shared_ptr<const ObjectTemplate> objTempl);
|
||||
@ -179,8 +180,8 @@ private:
|
||||
CGObjectInstance * readBorderGuard();
|
||||
CGObjectInstance * readBorderGate(const int3 & position, std::shared_ptr<const ObjectTemplate> objTempl);
|
||||
CGObjectInstance * readQuestGuard(const int3 & position);
|
||||
CGObjectInstance * readShipyard();
|
||||
CGObjectInstance * readLighthouse();
|
||||
CGObjectInstance * readShipyard(const int3 & mapPosition);
|
||||
CGObjectInstance * readLighthouse(const int3 & mapPosition);
|
||||
CGObjectInstance * readGeneric(const int3 & position, std::shared_ptr<const ObjectTemplate> objectTemplate);
|
||||
CGObjectInstance * readBank(const int3 & position, std::shared_ptr<const ObjectTemplate> objectTemplate);
|
||||
|
||||
@ -234,6 +235,7 @@ private:
|
||||
/// reads string from input stream, converts it to unicode and attempts to translate it
|
||||
std::string readLocalizedString(const TextIdentifier & identifier);
|
||||
|
||||
void setOwnerAndValidate(const int3 & mapPosition, CGObjectInstance * object, const PlayerColor & owner);
|
||||
void readSpells(std::set<SpellID> & dest);
|
||||
|
||||
void afterRead();
|
||||
|
Loading…
x
Reference in New Issue
Block a user