Bläddra i källkod

Some refactoring, commiting current state after tests

Tomasz Zieliński 2 år sedan
förälder
incheckning
03fa75c51e
3 ändrade filer med 48 tillägg och 23 borttagningar
  1. 39 22
      lib/rmg/RmgObject.cpp
  2. 4 0
      lib/rmg/RmgObject.h
  3. 5 1
      lib/rmg/modificators/TreasurePlacer.cpp

+ 39 - 22
lib/rmg/RmgObject.cpp

@@ -40,7 +40,9 @@ const Area & Object::Instance::getBlockedArea() const
 	{
 		dBlockedAreaCache.assign(dObject.getBlockedPos());
 		if(dObject.isVisitable() || dBlockedAreaCache.empty())
-			dBlockedAreaCache.add(dObject.visitablePos());
+			if (!dObject.isBlockedVisitable())
+				// Do no assume blocked tile is accessible
+				dBlockedAreaCache.add(dObject.visitablePos());
 	}
 	return dBlockedAreaCache;
 }
@@ -85,9 +87,7 @@ void Object::Instance::setPosition(const int3 & position)
 	
 	dBlockedAreaCache.clear();
 	dAccessibleAreaCache.clear();
-	dParent.dAccessibleAreaCache.clear();
-	dParent.dAccessibleAreaFullCache.clear();
-	dParent.dFullAreaCache.clear();
+	dParent.clearCachedArea();
 }
 
 void Object::Instance::setPositionRaw(const int3 & position)
@@ -97,9 +97,7 @@ void Object::Instance::setPositionRaw(const int3 & position)
 		dObject.pos = dPosition + dParent.getPosition();
 		dBlockedAreaCache.clear();
 		dAccessibleAreaCache.clear();
-		dParent.dAccessibleAreaCache.clear();
-		dParent.dAccessibleAreaFullCache.clear();
-		dParent.dFullAreaCache.clear();
+		dParent.clearCachedArea();
 	}
 		
 	auto shift = position + dParent.getPosition() - dObject.pos;
@@ -141,9 +139,7 @@ void Object::Instance::clear()
 	delete &dObject;
 	dBlockedAreaCache.clear();
 	dAccessibleAreaCache.clear();
-	dParent.dAccessibleAreaCache.clear();
-	dParent.dAccessibleAreaFullCache.clear();
-	dParent.dFullAreaCache.clear();
+	dParent.clearCachedArea();
 }
 
 bool Object::Instance::isVisitableFrom(const int3 & position) const
@@ -152,6 +148,11 @@ bool Object::Instance::isVisitableFrom(const int3 & position) const
 	return dObject.appearance->isVisitableFrom(relPosition.x, relPosition.y);
 }
 
+bool Object::Instance::isBlockedVisitable() const
+{
+	return dObject.isBlockedVisitable();
+}
+
 CGObjectInstance & Object::Instance::object()
 {
 	return dObject;
@@ -205,9 +206,7 @@ void Object::addInstance(Instance & object)
 	setGuardedIfMonster(object);
 	dInstances.push_back(object);
 
-	dFullAreaCache.clear();
-	dAccessibleAreaCache.clear();
-	dAccessibleAreaFullCache.clear();
+	clearCachedArea();
 }
 
 Object::Instance & Object::addInstance(CGObjectInstance & object)
@@ -215,9 +214,7 @@ Object::Instance & Object::addInstance(CGObjectInstance & object)
 	dInstances.emplace_back(*this, object);
 	setGuardedIfMonster(dInstances.back());
 
-	dFullAreaCache.clear();
-	dAccessibleAreaCache.clear();
-	dAccessibleAreaFullCache.clear();
+	clearCachedArea();
 	return dInstances.back();
 }
 
@@ -226,9 +223,7 @@ Object::Instance & Object::addInstance(CGObjectInstance & object, const int3 & p
 	dInstances.emplace_back(*this, object, position);
 	setGuardedIfMonster(dInstances.back());
 
-	dFullAreaCache.clear();
-	dAccessibleAreaCache.clear();
-	dAccessibleAreaFullCache.clear();
+	clearCachedArea();
 	return dInstances.back();
 }
 
@@ -270,10 +265,25 @@ const rmg::Area & Object::getAccessibleArea(bool exceptLast) const
 		return dAccessibleAreaFullCache;
 }
 
+const rmg::Area & Object::getBlockVisitableArea() const
+{
+	if(dInstances.empty())
+		return dBlockVisitableCache;
+	for(auto i = dInstances.begin(); i != std::prev(dInstances.end()); ++i)
+	{
+		// FIXME: Account for blockvis objects with multiple visitable tiles
+		if (i->isBlockedVisitable())
+			dAccessibleAreaCache.add(i->getVisitablePosition());
+	}
+
+	return dBlockVisitableCache;
+}
+
 void Object::setPosition(const int3 & position)
 {
 	dAccessibleAreaCache.translate(position - dPosition);
 	dAccessibleAreaFullCache.translate(position - dPosition);
+	dBlockVisitableCache.translate(position - dPosition);
 	dFullAreaCache.translate(position - dPosition);
 	
 	dPosition = position;
@@ -374,14 +384,21 @@ void Object::finalize(RmgMap & map, CRandomGenerator & rng)
 	}
 }
 
+void Object::clearCachedArea() const
+{
+	dFullAreaCache.clear();
+	dAccessibleAreaCache.clear();
+	dAccessibleAreaFullCache.clear();
+	dBlockVisitableCache.clear();
+}
+
 void Object::clear()
 {
 	for(auto & instance : dInstances)
 		instance.clear();
 	dInstances.clear();
-	dFullAreaCache.clear();
-	dAccessibleAreaCache.clear();
-	dAccessibleAreaFullCache.clear();
+
+	clearCachedArea();
 }
  
 

+ 4 - 0
lib/rmg/RmgObject.h

@@ -35,6 +35,7 @@ public:
 		
 		int3 getVisitablePosition() const;
 		bool isVisitableFrom(const int3 & tile) const;
+		bool isBlockedVisitable() const;
 		const Area & getAccessibleArea() const;
 		void setTemplate(TerrainId terrain, CRandomGenerator &); //cache invalidation
 		void setAnyTemplate(CRandomGenerator &); //cache invalidation
@@ -71,6 +72,7 @@ public:
 	
 	int3 getVisitablePosition() const;
 	const Area & getAccessibleArea(bool exceptLast = false) const;
+	const Area & getBlockVisitableArea() const;
 	
 	const int3 & getPosition() const;
 	void setPosition(const int3 & position);
@@ -83,12 +85,14 @@ public:
 	void setGuardedIfMonster(const Instance & object);
 	
 	void finalize(RmgMap & map, CRandomGenerator &);
+	void clearCachedArea() const;
 	void clear();
 	
 private:
 	std::list<Instance> dInstances;
 	mutable Area dFullAreaCache;
 	mutable Area dAccessibleAreaCache, dAccessibleAreaFullCache;
+	mutable Area dBlockVisitableCache;
 	int3 dPosition;
 	ui32 dStrength;
 	bool guarded;

+ 5 - 1
lib/rmg/modificators/TreasurePlacer.cpp

@@ -676,7 +676,8 @@ rmg::Object TreasurePlacer::constructTreasurePile(const std::vector<ObjectInfo*>
 			auto instanceAccessibleArea = instance.getAccessibleArea();
 			if(instance.getBlockedArea().getTilesVector().size() == 1)
 			{
-				if(instance.object().appearance->isVisitableFromTop() && instance.object().ID != Obj::CORPSE)
+				//TOOD: Move hardcoded option to template
+				if(instance.object().appearance->isVisitableFromTop() && !instance.object().isBlockedVisitable())
 					instanceAccessibleArea.add(instance.getVisitablePosition());
 			}
 			
@@ -684,6 +685,9 @@ rmg::Object TreasurePlacer::constructTreasurePile(const std::vector<ObjectInfo*>
 			if(rmgObject.instances().size() == 1)
 				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()) && accessibleArea.overlap(instanceAccessibleArea))
 				break;