mirror of
				https://github.com/vcmi/vcmi.git
				synced 2025-10-31 00:07:39 +02:00 
			
		
		
		
	Do not place object visible tiles over the top of the map.
This commit is contained in:
		| @@ -133,6 +133,11 @@ int3 CGObjectInstance::getPosition() const | ||||
| 	return pos; | ||||
| } | ||||
|  | ||||
| int3 CGObjectInstance::getTopVisiblePos() const | ||||
| { | ||||
| 	return pos - appearance->getTopVisibleOffset(); | ||||
| } | ||||
|  | ||||
| void CGObjectInstance::setOwner(const PlayerColor & ow) | ||||
| { | ||||
| 	tempOwner = ow; | ||||
|   | ||||
| @@ -159,6 +159,7 @@ public: | ||||
| 	bool visitableAt(int x, int y) const; //returns true if object is visitable at location (x, y) (h3m pos) | ||||
| 	int3 visitablePos() const override; | ||||
| 	int3 getPosition() const override; | ||||
| 	int3 getTopVisiblePos() const; | ||||
| 	bool blockingAt(int x, int y) const; //returns true if object is blocking location (x, y) (h3m pos) | ||||
| 	bool coveringAt(int x, int y) const; //returns true if object covers with picture location (x, y) (h3m pos) | ||||
| 	std::set<int3> getBlockedPos() const; //returns set of positions blocked by this object | ||||
|   | ||||
| @@ -524,6 +524,22 @@ bool ObjectTemplate::isVisitableFrom(si8 X, si8 Y) const | ||||
| 	return dirMap[dy][dx] != 0; | ||||
| } | ||||
|  | ||||
| void ObjectTemplate::calculateTopVisibleOffset() | ||||
| { | ||||
| 	for(int y = static_cast<int>(getHeight()) - 1; y >= 0; y--) //Templates start from bottom-right corner | ||||
| 	{ | ||||
| 		for(int x = 0; x < static_cast<int>(getWidth()); x++) | ||||
| 		{ | ||||
| 			if (isVisibleAt(x, y)) | ||||
| 			{ | ||||
| 				topVisibleOffset = int3(x, y, 0); | ||||
| 				return; | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 	topVisibleOffset = int3(0, 0, 0); | ||||
| } | ||||
|  | ||||
| void ObjectTemplate::calculateVisitableOffset() | ||||
| { | ||||
| 	for(int y = 0; y < static_cast<int>(getHeight()); y++) | ||||
| @@ -559,6 +575,7 @@ void ObjectTemplate::recalculate() | ||||
| 	calculateBlockedOffsets(); | ||||
| 	calculateBlockMapOffset(); | ||||
| 	calculateVisitableOffset(); | ||||
| 	calculateTopVisibleOffset(); | ||||
|  | ||||
| 	if (visitable && visitDir == 0) | ||||
| 		logMod->warn("Template for %s is visitable but has no visitable directions!", animationFile); | ||||
|   | ||||
| @@ -87,7 +87,12 @@ public: | ||||
| 	inline int3 getBlockMapOffset() const | ||||
| 	{ | ||||
| 		return blockMapOffset;  | ||||
| 	};  | ||||
| 	}; | ||||
|  | ||||
| 	inline int3 getTopVisibleOffset() const | ||||
| 	{ | ||||
| 		return topVisibleOffset; | ||||
| 	} | ||||
|  | ||||
| 	// Checks if object is visitable from certain direction. X and Y must be between -1..+1 | ||||
| 	bool isVisitableFrom(si8 X, si8 Y) const; | ||||
| @@ -137,6 +142,7 @@ private: | ||||
| 	std::set<int3> blockedOffsets; | ||||
| 	int3 blockMapOffset; | ||||
| 	int3 visitableOffset; | ||||
| 	int3 topVisibleOffset; | ||||
|  | ||||
| 	void recalculate(); | ||||
|  | ||||
| @@ -146,6 +152,7 @@ private: | ||||
| 	void calculateBlockedOffsets(); | ||||
| 	void calculateBlockMapOffset(); | ||||
| 	void calculateVisitableOffset(); | ||||
| 	void calculateTopVisibleOffset(); | ||||
|  | ||||
| public: | ||||
| 	template <typename Handler> void serialize(Handler &h, const int version) | ||||
|   | ||||
| @@ -112,6 +112,9 @@ int3 ObjectManager::findPlaceForObject(const rmg::Area & searchArea, rmg::Object | ||||
| 				continue; | ||||
| 			 | ||||
| 			obj.setPosition(tile); | ||||
|  | ||||
| 			if (obj.getVisibleTop().y < 0) | ||||
| 				continue; | ||||
| 			 | ||||
| 			if(!searchArea.contains(obj.getArea()) || !searchArea.overlap(obj.getAccessibleArea())) | ||||
| 				continue; | ||||
| @@ -131,6 +134,9 @@ int3 ObjectManager::findPlaceForObject(const rmg::Area & searchArea, rmg::Object | ||||
| 		for(const auto & tile : searchArea.getTiles()) | ||||
| 		{ | ||||
| 			obj.setPosition(tile); | ||||
|  | ||||
| 			if (obj.getVisibleTop().y < 0) | ||||
| 				continue; | ||||
| 			 | ||||
| 			if(!searchArea.contains(obj.getArea()) || !searchArea.overlap(obj.getAccessibleArea())) | ||||
| 				continue; | ||||
|   | ||||
| @@ -45,6 +45,11 @@ const Area & Object::Instance::getBlockedArea() const | ||||
| 	return dBlockedAreaCache; | ||||
| } | ||||
|  | ||||
| int3 Object::Instance::getTopTile() const | ||||
| { | ||||
| 	return object().getTopVisiblePos(); | ||||
| } | ||||
|  | ||||
| int3 Object::Instance::getPosition(bool isAbsolute) const | ||||
| { | ||||
| 	if(isAbsolute) | ||||
| @@ -284,6 +289,19 @@ const Area & Object::getArea() const | ||||
| 	return dFullAreaCache; | ||||
| } | ||||
|  | ||||
| const int3 Object::getVisibleTop() const | ||||
| { | ||||
| 	int3 topTile(-1, 10000, -1); //Start at the bottom | ||||
| 	for (const auto& i : dInstances) | ||||
| 	{ | ||||
| 		if (i.getTopTile().y < topTile.y) | ||||
| 		{ | ||||
| 			topTile = i.getTopTile(); | ||||
| 		} | ||||
| 	} | ||||
| 	return topTile; | ||||
| } | ||||
|  | ||||
| void Object::Instance::finalize(RmgMap & map) | ||||
| { | ||||
| 	if(!map.isOnMap(getPosition(true))) | ||||
|   | ||||
| @@ -38,6 +38,7 @@ public: | ||||
| 		void setTemplate(TerrainId terrain); //cache invalidation | ||||
| 		void setAnyTemplate(); //cache invalidation | ||||
| 		 | ||||
| 		int3 getTopTile() const; | ||||
| 		int3 getPosition(bool isAbsolute = false) const; | ||||
| 		void setPosition(const int3 & position); //cache invalidation | ||||
| 		void setPositionRaw(const int3 & position); //no cache invalidation | ||||
| @@ -75,6 +76,7 @@ public: | ||||
| 	void setTemplate(const TerrainId & terrain); | ||||
| 	 | ||||
| 	const Area & getArea() const;  //lazy cache invalidation | ||||
| 	const int3 getVisibleTop() const; | ||||
| 	 | ||||
| 	void finalize(RmgMap & map); | ||||
| 	void clear(); | ||||
|   | ||||
		Reference in New Issue
	
	Block a user