Browse Source

Implemented foreground/background obstacles:

- obstacles now have "foreground" field
- if "foreground" field set, obstacle will appear on top of other
objects, such as units
- if "foreground" is not set, obstacle will appear below units
- updated schema and cleared up obstacles config
Ivan Savenko 2 years ago
parent
commit
428fb832c6

+ 5 - 1
client/battle/BattleObstacleController.cpp

@@ -148,7 +148,11 @@ void BattleObstacleController::collectRenderableObjects(BattleRenderer & rendere
 		if (obstacle->obstacleType == CObstacleInstance::MOAT)
 			continue;
 
-		renderer.insert(EBattleFieldLayer::OBSTACLES, obstacle->pos, [this, obstacle]( BattleRenderer::RendererRef canvas ){
+		bool isForeground = obstacle->obstacleType == CObstacleInstance::USUAL && obstacle->getInfo().isForegroundObstacle;
+
+		auto layer = isForeground ? EBattleFieldLayer::OBSTACLES_FG : EBattleFieldLayer::OBSTACLES_BG;
+
+		renderer.insert(layer, obstacle->pos, [this, obstacle]( BattleRenderer::RendererRef canvas ){
 			auto img = getObstacleImage(*obstacle);
 			if(img)
 			{

+ 2 - 2
client/battle/BattleRenderer.h

@@ -16,12 +16,12 @@ class BattleInterface;
 
 enum class EBattleFieldLayer {
 					   // confirmed ordering requirements:
-	OBSTACLES     = 0,
+	OBSTACLES_BG  = 0,
 	CORPSES       = 0,
 	WALLS         = 1,
 	HEROES        = 2,
 	STACKS        = 2, // after corpses, obstacles, walls
-	BATTLEMENTS   = 3, // after stacks
+	OBSTACLES_FG  = 3, // after stacks
 	STACK_AMOUNTS = 3, // after stacks, obstacles, corpses
 	EFFECTS       = 4, // after obstacles, battlements
 };

+ 1 - 1
client/battle/BattleSiegeController.cpp

@@ -307,7 +307,7 @@ void BattleSiegeController::collectRenderableObjects(BattleRenderer & renderer)
 			renderer.insert( EBattleFieldLayer::STACKS, getWallPiecePosition(wallPiece), [this, wallPiece](BattleRenderer::RendererRef canvas){
 				owner.stacksController->showStack(canvas, getTurretStack(wallPiece));
 			});
-			renderer.insert( EBattleFieldLayer::BATTLEMENTS, getWallPiecePosition(wallPiece), [this, wallPiece](BattleRenderer::RendererRef canvas){
+			renderer.insert( EBattleFieldLayer::OBSTACLES_FG, getWallPiecePosition(wallPiece), [this, wallPiece](BattleRenderer::RendererRef canvas){
 				showWallPiece(canvas, wallPiece);
 			});
 		}

File diff suppressed because it is too large
+ 36 - 169
config/obstacles.json


+ 12 - 4
config/schemas/obstacle.json

@@ -3,7 +3,15 @@
 	"$schema" : "http://json-schema.org/draft-04/schema",
 	"title" : "VCMI obstacle format",
 	"description" : "Format used to define new obstacles in VCMI",
-	"required" : [ "animation" ],
+	"required" : [ "animation", "width", "height", "blockedTiles" ],
+	"anyOf" : [
+		{
+			"required" : [ "allowedTerrains" ]
+		},
+		{
+			"required" : [ "specialBattlefields" ]
+		}
+	],
 	"additionalProperties" : false,
 	"properties" : {
 		"allowedTerrains" : {
@@ -41,9 +49,9 @@
 				{ "format" : "imageFile" }
 			]
 		},
-		"unknown" : {
-			"type" : "number",
-			"description" : "Unknown field"
+		"foreground" : {
+			"type" : "boolean",
+			"description" : "If set to true, obstacle will appear in front of units or other battlefield objects"
 		}
 	}
 }

+ 1 - 0
lib/ObstacleHandler.cpp

@@ -103,6 +103,7 @@ ObstacleInfo * ObstacleHandler::loadFromJson(const std::string & scope, const Js
 		info->allowedSpecialBfields.emplace_back(t.String());
 	info->blockedTiles = json["blockedTiles"].convertTo<std::vector<si16>>();
 	info->isAbsoluteObstacle = json["absolute"].Bool();
+	info->isForegroundObstacle = json["foreground"].Bool();
 
 	objects.emplace_back(info);
 

+ 5 - 7
lib/ObstacleHandler.h

@@ -20,11 +20,11 @@ VCMI_LIB_NAMESPACE_BEGIN
 class DLL_LINKAGE ObstacleInfo : public EntityT<Obstacle>
 {
 public:
-	ObstacleInfo(): obstacle(-1), width(0), height(0), isAbsoluteObstacle(false), iconIndex(0)
+	ObstacleInfo(): obstacle(-1), width(0), height(0), isAbsoluteObstacle(false), iconIndex(0), isForegroundObstacle(false)
 	{}
 	
 	ObstacleInfo(Obstacle obstacle, std::string identifier)
-	: obstacle(obstacle), identifier(identifier), iconIndex(obstacle.getNum()), width(0), height(0), isAbsoluteObstacle(false)
+	: obstacle(obstacle), identifier(identifier), iconIndex(obstacle.getNum()), width(0), height(0), isAbsoluteObstacle(false), isForegroundObstacle(false)
 	{
 	}
 	
@@ -35,10 +35,8 @@ public:
 	std::vector<TerrainId> allowedTerrains;
 	std::vector<std::string> allowedSpecialBfields;
 	
-	//TODO: here is extra field to implement it's logic in the future but save backward compatibility
-	int obstacleType = -1;
-	
-	ui8 isAbsoluteObstacle; //there may only one such obstacle in battle and its position is always the same
+	bool isAbsoluteObstacle; //there may only one such obstacle in battle and its position is always the same
+	bool isForegroundObstacle;
 	si32 width, height; //how much space to the right and up is needed to place obstacle (affects only placement algorithm)
 	std::vector<si16> blockedTiles; //offsets relative to obstacle position (that is its left bottom corner)
 	
@@ -57,7 +55,6 @@ public:
 	template <typename Handler> void serialize(Handler &h, const int version)
 	{
 		h & obstacle;
-		h & obstacleType;
 		h & iconIndex;
 		h & identifier;
 		h & animation;
@@ -66,6 +63,7 @@ public:
 		h & allowedTerrains;
 		h & allowedSpecialBfields;
 		h & isAbsoluteObstacle;
+		h & isForegroundObstacle;
 		h & width;
 		h & height;
 		h & blockedTiles;

Some files were not shown because too many files changed in this diff