1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-11-06 09:09:40 +02:00

Working fir for Corpse issue:

- Do not place guard next to blockVis object, if possible
- Do not place two blockVis objects next to each other
This commit is contained in:
Tomasz Zieliński
2023-12-06 20:49:28 +01:00
parent 03fa75c51e
commit 6cd19b81dd
11 changed files with 149 additions and 28 deletions

View File

@@ -10,7 +10,11 @@
} }
}, },
"types" : { "types" : {
"prison" : { "index" : 0, "aiValue" : 5000 } "prison" : {
"index" : 0,
"aiValue" : 5000,
"removable": true
}
} }
}, },
@@ -136,6 +140,7 @@
"object" : { "object" : {
"index" : 0, "index" : 0,
"aiValue" : 10000, "aiValue" : 10000,
"removable": true,
"templates" : { "templates" : {
"normal" : { "animation" : "ava0128.def", "visitableFrom" : [ "+++", "+-+", "+++" ], "mask" : [ "VV", "VA"] } "normal" : { "animation" : "ava0128.def", "visitableFrom" : [ "+++", "+-+", "+++" ], "mask" : [ "VV", "VA"] }
}, },
@@ -150,6 +155,7 @@
"types" : { "types" : {
"object" : { "object" : {
"index" : 0, "index" : 0,
"removable": true,
"rmg" : { "rmg" : {
} }
} }
@@ -313,6 +319,7 @@
"object" : { "object" : {
"index" : 0, "index" : 0,
"aiValue" : 0, "aiValue" : 0,
"removable": true,
"rmg" : { "rmg" : {
} }
} }
@@ -444,6 +451,7 @@
"object" : { "object" : {
"index" : 0, "index" : 0,
"aiValue" : 10000, "aiValue" : 10000,
"removable": true,
"rmg" : { "rmg" : {
} }
} }
@@ -495,6 +503,7 @@
"types" : { "types" : {
"object" : { "object" : {
"index" : 0, "index" : 0,
"removable": true,
"rmg" : { "rmg" : {
"value" : 2000, "value" : 2000,
"rarity" : 150 "rarity" : 150
@@ -511,6 +520,7 @@
"types" : { "types" : {
"object" : { "object" : {
"index" : 0, "index" : 0,
"removable": true,
"rmg" : { "rmg" : {
"value" : 5000, "value" : 5000,
"rarity" : 150 "rarity" : 150
@@ -527,6 +537,7 @@
"types" : { "types" : {
"object" : { "object" : {
"index" : 0, "index" : 0,
"removable": true,
"rmg" : { "rmg" : {
"value" : 10000, "value" : 10000,
"rarity" : 150 "rarity" : 150
@@ -543,6 +554,7 @@
"types" : { "types" : {
"object" : { "object" : {
"index" : 0, "index" : 0,
"removable": true,
"rmg" : { "rmg" : {
"value" : 20000, "value" : 20000,
"rarity" : 150 "rarity" : 150
@@ -572,6 +584,7 @@
"types" : { "types" : {
"object" : { "object" : {
"index" : 0, "index" : 0,
"removable": true,
"templates" : { "templates" : {
"normal" : { "animation" : "AVWmon1", "visitableFrom" : [ "+++", "+-+", "+++" ], "mask" : [ "VV", "VA"] } "normal" : { "animation" : "AVWmon1", "visitableFrom" : [ "+++", "+-+", "+++" ], "mask" : [ "VV", "VA"] }
} }
@@ -584,6 +597,7 @@
"types" : { "types" : {
"object" : { "object" : {
"index" : 0, "index" : 0,
"removable": true,
"templates" : { "templates" : {
"normal" : { "animation" : "AVWmon2", "visitableFrom" : [ "+++", "+-+", "+++" ], "mask" : [ "VV", "VA"] } "normal" : { "animation" : "AVWmon2", "visitableFrom" : [ "+++", "+-+", "+++" ], "mask" : [ "VV", "VA"] }
} }
@@ -596,6 +610,7 @@
"types" : { "types" : {
"object" : { "object" : {
"index" : 0, "index" : 0,
"removable": true,
"templates" : { "templates" : {
"normal" : { "animation" : "AVWmon3", "visitableFrom" : [ "+++", "+-+", "+++" ], "mask" : [ "VV", "VA"] } "normal" : { "animation" : "AVWmon3", "visitableFrom" : [ "+++", "+-+", "+++" ], "mask" : [ "VV", "VA"] }
} }
@@ -608,6 +623,7 @@
"types" : { "types" : {
"object" : { "object" : {
"index" : 0, "index" : 0,
"removable": true,
"templates" : { "templates" : {
"normal" : { "animation" : "AVWmon4", "visitableFrom" : [ "+++", "+-+", "+++" ], "mask" : [ "VV", "VA"] } "normal" : { "animation" : "AVWmon4", "visitableFrom" : [ "+++", "+-+", "+++" ], "mask" : [ "VV", "VA"] }
} }
@@ -632,6 +648,7 @@
"types" : { "types" : {
"object" : { "object" : {
"index" : 0, "index" : 0,
"removable": true,
"templates" : { "templates" : {
"normal" : { "animation" : "AVWmon6", "visitableFrom" : [ "+++", "+-+", "+++" ], "mask" : [ "VV", "VA"] } "normal" : { "animation" : "AVWmon6", "visitableFrom" : [ "+++", "+-+", "+++" ], "mask" : [ "VV", "VA"] }
} }
@@ -644,6 +661,7 @@
"types" : { "types" : {
"object" : { "object" : {
"index" : 0, "index" : 0,
"removable": true,
"templates" : { "templates" : {
"normal" : { "animation" : "AVWmon7", "visitableFrom" : [ "+++", "+-+", "+++" ], "mask" : [ "VV", "VA"] } "normal" : { "animation" : "AVWmon7", "visitableFrom" : [ "+++", "+-+", "+++" ], "mask" : [ "VV", "VA"] }
} }
@@ -687,6 +705,7 @@
"object" : { "object" : {
"index" : 0, "index" : 0,
"aiValue" : 0, "aiValue" : 0,
"removable": true,
"rmg" : { "rmg" : {
} }
} }
@@ -723,6 +742,7 @@
"index" :95, "index" :95,
"handler": "generic", "handler": "generic",
"base" : { "base" : {
"blockVisit": true,
"sounds" : { "sounds" : {
"ambient" : ["LOOPTAV"], "ambient" : ["LOOPTAV"],
"visit" : ["STORE"] "visit" : ["STORE"]

View File

@@ -8,6 +8,7 @@
"index" :5, "index" :5,
"handler": "artifact", "handler": "artifact",
"base" : { "base" : {
"removable": true,
"base" : { "base" : {
"visitableFrom" : [ "+++", "+-+", "+++" ], "visitableFrom" : [ "+++", "+-+", "+++" ],
"mask" : [ "VV", "VA"] "mask" : [ "VV", "VA"]
@@ -25,6 +26,7 @@
"handler": "hero", "handler": "hero",
"base" : { "base" : {
"aiValue" : 7500, "aiValue" : 7500,
"removable": true,
"base" : { "base" : {
"visitableFrom" : [ "+++", "+-+", "+++" ], "visitableFrom" : [ "+++", "+-+", "+++" ],
"mask" : [ "VVV", "VAV"] "mask" : [ "VVV", "VAV"]
@@ -40,6 +42,7 @@
"index" :54, "index" :54,
"handler": "monster", "handler": "monster",
"base" : { "base" : {
"removable": true,
"base" : { "base" : {
"visitableFrom" : [ "+++", "+-+", "+++" ], "visitableFrom" : [ "+++", "+-+", "+++" ],
"mask" : [ "VV", "VA"] "mask" : [ "VV", "VA"]
@@ -55,6 +58,7 @@
"index" :76, "index" :76,
"handler": "randomResource", "handler": "randomResource",
"base" : { "base" : {
"removable": true,
"base" : { "base" : {
"visitableFrom" : [ "+++", "+-+", "+++" ], "visitableFrom" : [ "+++", "+-+", "+++" ],
"mask" : [ "VA" ] "mask" : [ "VA" ]
@@ -85,6 +89,7 @@
"handler": "resource", "handler": "resource",
"lastReservedIndex" : 6, "lastReservedIndex" : 6,
"base" : { "base" : {
"removable": true,
"base" : { "base" : {
"visitableFrom" : [ "+++", "+-+", "+++" ], "visitableFrom" : [ "+++", "+-+", "+++" ],
"mask" : [ "VA" ] "mask" : [ "VA" ]
@@ -138,6 +143,7 @@
"lastReservedIndex" : 2, "lastReservedIndex" : 2,
"base" : { "base" : {
"aiValue" : 0, "aiValue" : 0,
"removable": true,
"layer" : "sail", "layer" : "sail",
"onboardAssaultAllowed" : true, "onboardAssaultAllowed" : true,
"onboardVisitAllowed" : true, "onboardVisitAllowed" : true,
@@ -175,6 +181,7 @@
"lastReservedIndex" : 7, "lastReservedIndex" : 7,
"base" : { "base" : {
"aiValue" : 0, "aiValue" : 0,
"removable": true,
"sounds" : { "sounds" : {
"visit" : ["CAVEHEAD"], "visit" : ["CAVEHEAD"],
"removal" : [ "PICKUP01", "PICKUP02", "PICKUP03", "PICKUP04", "PICKUP05", "PICKUP06", "PICKUP07" ] "removal" : [ "PICKUP01", "PICKUP02", "PICKUP03", "PICKUP04", "PICKUP05", "PICKUP06", "PICKUP07" ]

View File

@@ -19,6 +19,7 @@
"value" : 2000, "value" : 2000,
"rarity" : 500 "rarity" : 500
}, },
"removable": true,
"compatibilityIdentifiers" : [ "object" ], "compatibilityIdentifiers" : [ "object" ],
"blockedVisitable" : true, "blockedVisitable" : true,
@@ -61,6 +62,7 @@
"value" : 2000, "value" : 2000,
"rarity" : 100 "rarity" : 100
}, },
"removable": true,
"compatibilityIdentifiers" : [ "object" ], "compatibilityIdentifiers" : [ "object" ],
"blockedVisitable" : true, "blockedVisitable" : true,
@@ -119,6 +121,7 @@
"value" : 1500, "value" : 1500,
"rarity" : 500 "rarity" : 500
}, },
"removable": true,
"compatibilityIdentifiers" : [ "object" ], "compatibilityIdentifiers" : [ "object" ],
"blockedVisitable" : true, "blockedVisitable" : true,
@@ -170,6 +173,7 @@
"value" : 1500, "value" : 1500,
"rarity" : 50 "rarity" : 50
}, },
"removable": true,
"compatibilityIdentifiers" : [ "object" ], "compatibilityIdentifiers" : [ "object" ],
"blockedVisitable" : true, "blockedVisitable" : true,
@@ -221,6 +225,7 @@
"value" : 1500, "value" : 1500,
"rarity" : 1000 "rarity" : 1000
}, },
"removable": true,
"compatibilityIdentifiers" : [ "object" ], "compatibilityIdentifiers" : [ "object" ],
"blockedVisitable" : true, "blockedVisitable" : true,

View File

@@ -96,6 +96,18 @@ void AObjectTypeHandler::init(const JsonNode & input)
else else
aiValue = static_cast<std::optional<si32>>(input["aiValue"].Integer()); aiValue = static_cast<std::optional<si32>>(input["aiValue"].Integer());
// TODO: Define properties, move them to actual object instance
if(input["blockVisit"].isNull())
blockVisit = false;
else
blockVisit = input["blockVisit"].Bool();
if(input["removable"].isNull())
removable = false;
else
removable = input["removable"].Bool();
battlefield = BattleField::NONE; battlefield = BattleField::NONE;
if(!input["battleground"].isNull()) if(!input["battleground"].isNull())
@@ -120,6 +132,8 @@ void AObjectTypeHandler::preInitObject(CGObjectInstance * obj) const
obj->subID = subtype; obj->subID = subtype;
obj->typeName = typeName; obj->typeName = typeName;
obj->subTypeName = subTypeName; obj->subTypeName = subTypeName;
obj->blockVisit = blockVisit;
obj->removable = removable;
} }
void AObjectTypeHandler::initTypeData(const JsonNode & input) void AObjectTypeHandler::initTypeData(const JsonNode & input)

View File

@@ -43,6 +43,9 @@ class DLL_LINKAGE AObjectTypeHandler : public boost::noncopyable
si32 type; si32 type;
si32 subtype; si32 subtype;
bool blockVisit;
bool removable;
protected: protected:
void preInitObject(CGObjectInstance * obj) const; void preInitObject(CGObjectInstance * obj) const;
virtual bool objectFilter(const CGObjectInstance * obj, std::shared_ptr<const ObjectTemplate> tmpl) const; virtual bool objectFilter(const CGObjectInstance * obj, std::shared_ptr<const ObjectTemplate> tmpl) const;

View File

@@ -33,7 +33,8 @@ CGObjectInstance::CGObjectInstance():
ID(Obj::NO_OBJ), ID(Obj::NO_OBJ),
subID(-1), subID(-1),
tempOwner(PlayerColor::UNFLAGGABLE), tempOwner(PlayerColor::UNFLAGGABLE),
blockVisit(false) blockVisit(false),
removable(false)
{ {
} }
@@ -173,12 +174,7 @@ void CGObjectInstance::pickRandomObject(CRandomGenerator & rand)
void CGObjectInstance::initObj(CRandomGenerator & rand) void CGObjectInstance::initObj(CRandomGenerator & rand)
{ {
switch(ID.toEnum()) // no-op
{
case Obj::TAVERN:
blockVisit = true;
break;
}
} }
void CGObjectInstance::setProperty( ObjProperty what, ObjPropertyID identifier ) void CGObjectInstance::setProperty( ObjProperty what, ObjPropertyID identifier )
@@ -191,6 +187,7 @@ void CGObjectInstance::setProperty( ObjProperty what, ObjPropertyID identifier )
tempOwner = identifier.as<PlayerColor>(); tempOwner = identifier.as<PlayerColor>();
break; break;
case ObjProperty::BLOCKVIS: case ObjProperty::BLOCKVIS:
// Never actually used in code, but possible in ERM
blockVisit = identifier.getNum(); blockVisit = identifier.getNum();
break; break;
case ObjProperty::ID: case ObjProperty::ID:
@@ -327,9 +324,16 @@ bool CGObjectInstance::isVisitable() const
bool CGObjectInstance::isBlockedVisitable() const bool CGObjectInstance::isBlockedVisitable() const
{ {
// TODO: Read from json
return blockVisit; return blockVisit;
} }
bool CGObjectInstance::isRemovable() const
{
// TODO: Read from json
return removable;
}
bool CGObjectInstance::isCoastVisitable() const bool CGObjectInstance::isCoastVisitable() const
{ {
return false; return false;

View File

@@ -54,6 +54,7 @@ public:
int3 getSightCenter() const; int3 getSightCenter() const;
/// If true hero can visit this object only from neighbouring tiles and can't stand on this object /// If true hero can visit this object only from neighbouring tiles and can't stand on this object
bool blockVisit; bool blockVisit;
bool removable;
PlayerColor getOwner() const override PlayerColor getOwner() const override
{ {
@@ -85,6 +86,9 @@ public:
/// If true hero can visit this object only from neighbouring tiles and can't stand on this object /// If true hero can visit this object only from neighbouring tiles and can't stand on this object
virtual bool isBlockedVisitable() const; virtual bool isBlockedVisitable() const;
// If true, can be possibly removed from the map
virtual bool isRemovable() const;
/// If true this object can be visited by hero standing on the coast /// If true this object can be visited by hero standing on the coast
virtual bool isCoastVisitable() const; virtual bool isCoastVisitable() const;
@@ -144,6 +148,7 @@ public:
h & id; h & id;
h & tempOwner; h & tempOwner;
h & blockVisit; h & blockVisit;
h & removable;
h & appearance; h & appearance;
//definfo is handled by map serializer //definfo is handled by map serializer
} }

View File

@@ -153,6 +153,11 @@ bool Object::Instance::isBlockedVisitable() const
return dObject.isBlockedVisitable(); return dObject.isBlockedVisitable();
} }
bool Object::Instance::isRemovable() const
{
return dObject.isRemovable();
}
CGObjectInstance & Object::Instance::object() CGObjectInstance & Object::Instance::object()
{ {
return dObject; return dObject;
@@ -269,21 +274,52 @@ const rmg::Area & Object::getBlockVisitableArea() const
{ {
if(dInstances.empty()) if(dInstances.empty())
return dBlockVisitableCache; return dBlockVisitableCache;
for(auto i = dInstances.begin(); i != std::prev(dInstances.end()); ++i)
for(const auto i : dInstances)
{ {
// FIXME: Account for blockvis objects with multiple visitable tiles // FIXME: Account for blockvis objects with multiple visitable tiles
if (i->isBlockedVisitable()) if (i.isBlockedVisitable())
dAccessibleAreaCache.add(i->getVisitablePosition()); dBlockVisitableCache.add(i.getVisitablePosition());
} }
return dBlockVisitableCache; return dBlockVisitableCache;
} }
const rmg::Area & Object::getRemovableArea() const
{
if(dInstances.empty())
return dRemovableAreaCache;
for(const auto i : dInstances)
{
if (i.isRemovable())
dRemovableAreaCache.unite(i.getBlockedArea());
}
return dRemovableAreaCache;
}
const rmg::Area Object::getEntrableArea() const
{
// Calculate Area that hero can freely pass
// Do not use blockVisitTiles, unless they belong to removable objects (resources etc.)
// area = accessibleArea - (blockVisitableArea - removableArea)
rmg::Area entrableArea = getAccessibleArea();
rmg::Area blockVisitableArea = getBlockVisitableArea();
blockVisitableArea.subtract(getRemovableArea());
entrableArea.subtract(blockVisitableArea);
return entrableArea;
}
void Object::setPosition(const int3 & position) void Object::setPosition(const int3 & position)
{ {
dAccessibleAreaCache.translate(position - dPosition); dAccessibleAreaCache.translate(position - dPosition);
dAccessibleAreaFullCache.translate(position - dPosition); dAccessibleAreaFullCache.translate(position - dPosition);
dBlockVisitableCache.translate(position - dPosition); dBlockVisitableCache.translate(position - dPosition);
dRemovableAreaCache.translate(position - dPosition);
dFullAreaCache.translate(position - dPosition); dFullAreaCache.translate(position - dPosition);
dPosition = position; dPosition = position;
@@ -390,6 +426,7 @@ void Object::clearCachedArea() const
dAccessibleAreaCache.clear(); dAccessibleAreaCache.clear();
dAccessibleAreaFullCache.clear(); dAccessibleAreaFullCache.clear();
dBlockVisitableCache.clear(); dBlockVisitableCache.clear();
dRemovableAreaCache.clear();
} }
void Object::clear() void Object::clear()

View File

@@ -36,6 +36,7 @@ public:
int3 getVisitablePosition() const; int3 getVisitablePosition() const;
bool isVisitableFrom(const int3 & tile) const; bool isVisitableFrom(const int3 & tile) const;
bool isBlockedVisitable() const; bool isBlockedVisitable() const;
bool isRemovable() const;
const Area & getAccessibleArea() const; const Area & getAccessibleArea() const;
void setTemplate(TerrainId terrain, CRandomGenerator &); //cache invalidation void setTemplate(TerrainId terrain, CRandomGenerator &); //cache invalidation
void setAnyTemplate(CRandomGenerator &); //cache invalidation void setAnyTemplate(CRandomGenerator &); //cache invalidation
@@ -73,6 +74,8 @@ public:
int3 getVisitablePosition() const; int3 getVisitablePosition() const;
const Area & getAccessibleArea(bool exceptLast = false) const; const Area & getAccessibleArea(bool exceptLast = false) const;
const Area & getBlockVisitableArea() const; const Area & getBlockVisitableArea() const;
const Area & getRemovableArea() const;
const Area getEntrableArea() const;
const int3 & getPosition() const; const int3 & getPosition() const;
void setPosition(const int3 & position); void setPosition(const int3 & position);
@@ -93,6 +96,7 @@ private:
mutable Area dFullAreaCache; mutable Area dFullAreaCache;
mutable Area dAccessibleAreaCache, dAccessibleAreaFullCache; mutable Area dAccessibleAreaCache, dAccessibleAreaFullCache;
mutable Area dBlockVisitableCache; mutable Area dBlockVisitableCache;
mutable Area dRemovableAreaCache;
int3 dPosition; int3 dPosition;
ui32 dStrength; ui32 dStrength;
bool guarded; bool guarded;

View File

@@ -664,7 +664,19 @@ bool ObjectManager::addGuard(rmg::Object & object, si32 strength, bool zoneGuard
if(!guard) if(!guard)
return false; return false;
rmg::Area visitablePos({object.getVisitablePosition()}); // Prefer non-blocking tiles, if any
auto entrableTiles = object.getEntrableArea().getTiles();
int3 entrableTile;
if (entrableTiles.empty())
{
entrableTile = object.getVisitablePosition();
}
else
{
*RandomGeneratorUtil::nextItem(entrableTiles, zone.getRand());
}
rmg::Area visitablePos({entrableTile});
visitablePos.unite(visitablePos.getBorderOutside()); visitablePos.unite(visitablePos.getBorderOutside());
auto accessibleArea = object.getAccessibleArea(); auto accessibleArea = object.getAccessibleArea();

View File

@@ -625,20 +625,31 @@ rmg::Object TreasurePlacer::constructTreasurePile(const std::vector<ObjectInfo*>
for(const auto & oi : treasureInfos) for(const auto & oi : treasureInfos)
{ {
auto blockedArea = rmgObject.getArea(); auto blockedArea = rmgObject.getArea();
auto accessibleArea = rmgObject.getAccessibleArea(); auto entrableArea = rmgObject.getEntrableArea();
if(rmgObject.instances().empty()) if(rmgObject.instances().empty())
accessibleArea.add(int3()); entrableArea.add(int3());
auto * object = oi->generateObject(); auto * object = oi->generateObject();
if(oi->templates.empty()) if(oi->templates.empty())
continue; continue;
object->appearance = *RandomGeneratorUtil::nextItem(oi->templates, zone.getRand()); object->appearance = *RandomGeneratorUtil::nextItem(oi->templates, zone.getRand());
auto blockingIssue = object->isBlockedVisitable() && !object->isRemovable();
if (blockingIssue)
{
// Do not place next to another such object (Corpse issue)
// Calculate this before instance is added to rmgObject
auto blockVisitProximity = rmgObject.getBlockVisitableArea().getBorderOutside();
entrableArea.subtract(blockVisitProximity);
}
auto & instance = rmgObject.addInstance(*object); auto & instance = rmgObject.addInstance(*object);
do do
{ {
if(accessibleArea.empty()) if(entrableArea.empty())
{ {
//fail - fallback //fail - fallback
rmgObject.clear(); rmgObject.clear();
@@ -649,12 +660,14 @@ rmg::Object TreasurePlacer::constructTreasurePile(const std::vector<ObjectInfo*>
if(densePlacement) if(densePlacement)
{ {
int bestPositionsWeight = std::numeric_limits<int>::max(); int bestPositionsWeight = std::numeric_limits<int>::max();
for(const auto & t : accessibleArea.getTilesVector()) for(const auto & t : entrableArea.getTilesVector())
{ {
instance.setPosition(t); instance.setPosition(t);
int w = rmgObject.getAccessibleArea().getTilesVector().size(); int w = rmgObject.getEntrableArea().getTilesVector().size();
if(w < bestPositionsWeight)
if(w && w < bestPositionsWeight)
{ {
// Minimum 1 position must be entrable
bestPositions.clear(); bestPositions.clear();
bestPositions.push_back(t); bestPositions.push_back(t);
bestPositionsWeight = w; bestPositionsWeight = w;
@@ -664,10 +677,12 @@ rmg::Object TreasurePlacer::constructTreasurePile(const std::vector<ObjectInfo*>
bestPositions.push_back(t); bestPositions.push_back(t);
} }
} }
} }
else
if (bestPositions.empty())
{ {
bestPositions = accessibleArea.getTilesVector(); bestPositions = entrableArea.getTilesVector();
} }
int3 nextPos = *RandomGeneratorUtil::nextItem(bestPositions, zone.getRand()); int3 nextPos = *RandomGeneratorUtil::nextItem(bestPositions, zone.getRand());
@@ -676,7 +691,6 @@ rmg::Object TreasurePlacer::constructTreasurePile(const std::vector<ObjectInfo*>
auto instanceAccessibleArea = instance.getAccessibleArea(); auto instanceAccessibleArea = instance.getAccessibleArea();
if(instance.getBlockedArea().getTilesVector().size() == 1) if(instance.getBlockedArea().getTilesVector().size() == 1)
{ {
//TOOD: Move hardcoded option to template
if(instance.object().appearance->isVisitableFromTop() && !instance.object().isBlockedVisitable()) if(instance.object().appearance->isVisitableFromTop() && !instance.object().isBlockedVisitable())
instanceAccessibleArea.add(instance.getVisitablePosition()); instanceAccessibleArea.add(instance.getVisitablePosition());
} }
@@ -684,16 +698,12 @@ rmg::Object TreasurePlacer::constructTreasurePile(const std::vector<ObjectInfo*>
//first object is good //first object is good
if(rmgObject.instances().size() == 1) if(rmgObject.instances().size() == 1)
break; break;
// TODO: Do not place blockvis objects so that they block access to existing accessible area
// Either object must be removable, or both must be accessible independently
//condition for good position if(!blockedArea.overlap(instance.getBlockedArea()) && entrableArea.overlap(instanceAccessibleArea))
if(!blockedArea.overlap(instance.getBlockedArea()) && accessibleArea.overlap(instanceAccessibleArea))
break; break;
//fail - new position //fail - new position
accessibleArea.erase(nextPos); entrableArea.erase(nextPos);
} while(true); } while(true);
} }
return rmgObject; return rmgObject;