Explorar el Código

allow configurable battleground graphics

Andrii Danylchenko hace 3 años
padre
commit
3b1d271ae0

+ 58 - 18
config/objects/generic.json

@@ -914,7 +914,7 @@
 	/// Passive objects, terrain overlays
 	"cursedGround" : {
 		"index" : 21,
-		"handler": "generic",
+		"handler": "terrain",
 		"base" : {
 			"sounds" : {
 				"ambient" : ["LOOPCURS"]
@@ -922,13 +922,14 @@
 		},
 		"types" : {
 			"object" : {
-				"index" : 0
+				"index" : 0,
+				"battleground": "cursed_ground"
 			}
 		}
 	},
-	"magicPlains"	: {
+	"magicPlains" : {
 		"index" : 46,
-		"handler" : "generic",
+		"handler" : "terrain",
 		"base" : {
 			"sounds" : {
 				"ambient" : ["LOOPMAGI"]
@@ -936,18 +937,28 @@
 		},
 		"types" : {
 			"object" : {
-				"index" : 0
+				"index" : 0,
+				"battleground": "magic_plains"
 			}
 		}
 	},
-	"swampFoliage" : { "index" :211, "handler": "generic", "types" : { "object" : { "index" : 0} } },
-	"cloverField"	: { "index" :222, "handler": "generic", "types" : { "object" : { "index" : 0} } },
+	"swampFoliage" : {
+		"index" :211,
+		"handler": "terrain",
+		"types" : { "object" : { "index" : 0} }
+	},
+	"cloverField" : {
+		"index" :222, 
+		"handler": "terrain", 
+		"types" : { "object" : { "index" : 0, "battleground": "clover_field" } }
+	},
 	"cursedGroundDUPLICATE"	: {
 		"index" : 223,
-		"handler" : "generic",
+		"handler" : "terrain",
 		"types" : {
 			"object" : {
-				"index" : 0
+				"index" : 0,
+				"battleground": "cursed_ground"
 			}
 		},
 		"base" : {
@@ -956,15 +967,39 @@
 			}
 		}
 	},
-	"evilFog"	: { "index" :224, "handler": "generic", "types" : { "object" : { "index" : 0} } },
-	"favorableWinds" : { "index" :225, "handler": "generic", "types" : { "object" : { "index" : 0} } },
-	"fieryFields"	: { "index" :226, "handler": "generic", "types" : { "object" : { "index" : 0} } },
-	"holyGround" : { "index" :227, "handler": "generic", "types" : { "object" : { "index" : 0} } },
-	"lucidPools" : { "index" :228, "handler": "generic", "types" : { "object" : { "index" : 0} } },
-	"magicClouds"	: { "index" :229, "handler": "generic", "types" : { "object" : { "index" : 0} } },
+	"evilFog" : {
+		"index" :224,
+		"handler": "terrain",
+		"types" : { "object" : { "index" : 0, "battleground": "evil_fog" } }
+	},
+	"favorableWinds" : {
+		"index" :225,
+		"handler": "terrain",
+		"types" : { "object" : { "index" : 0, "battleground": "favorable_winds" } }
+	},
+	"fieryFields": {
+		"index" :226,
+		"handler": "terrain",
+		"types" : { "object" : { "index" : 0, "battleground": "fiery_fields" } }
+	},
+	"holyGround" : {
+		"index" :227,
+		"handler": "terrain",
+		"types" : { "object" : { "index" : 0, "battleground": "holy_ground" } }
+	},
+	"lucidPools" : {
+		"index" :228,
+		"handler": "terrain",
+		"types" : { "object" : { "index" : 0, "battleground": "lucid_pools" } }
+	},
+	"magicClouds" : {
+		"index" :229,
+		"handler": "terrain",
+		"types" : { "object" : { "index" : 0, "battleground": "magic_clouds" } }
+	},
 	"magicPlainsDUPLICATE" : {
 		"index" : 230,
-		"handler": "generic",
+		"handler": "terrain",
 		"base" : {
 			"sounds" : {
 				"ambient" : ["LOOPMAGI"]
@@ -972,11 +1007,16 @@
 		},
 		"types" : {
 			"object" : {
-				"index" : 0
+				"index" : 0,
+				"battleground": "magic_plains"
 			}
 		}
 	},
-	"rocklands"	: { "index" :231, "handler": "generic", "types" : { "object" : { "index" : 0} } },
+	"rocklands"	: {
+		"index" :231,
+		"handler": "terrain",
+		"types" : { "object" : { "index" : 0, "battleground": "rocklands" } }
+	},
 
 	/// Decorations
 	"cactus"						: { "index" :116, "handler": "static", "types" : { "object" : { "index" : 0} } },

+ 17 - 9
config/objects/moddables.json

@@ -237,7 +237,8 @@
 				},
 				"sounds" : {
 					"ambient" : ["LOOPLUMB"]
-				}
+				},
+				"battleground": "subterranean"
 			},
 			"alchemistLab" : {
 				"index" : 1,
@@ -247,7 +248,8 @@
 				},
 				"sounds" : {
 					"ambient" : ["LOOPSTAR"]
-				}
+				},
+				"battleground": "subterranean"
 			},
 			"orePit" : {
 				"index" : 2,
@@ -257,7 +259,8 @@
 				},
 				"sounds" : {
 					"ambient" : ["LOOPSULF"]
-				}
+				},
+				"battleground": "subterranean"
 			},
 			"sulfurDune" : {
 				"index" : 3,
@@ -267,7 +270,8 @@
 				},
 				"sounds" : {
 					"ambient" : ["LOOPSULF"]
-				}
+				},
+				"battleground": "subterranean"
 			},
 			"crystalCavern" : {
 				"index" : 4,
@@ -277,7 +281,8 @@
 				},
 				"sounds" : {
 					"ambient" : ["LOOPCRYS"]
-				}
+				},
+				"battleground": "subterranean"
 			},
 			"gemPond" : {
 				"index" : 5,
@@ -287,7 +292,8 @@
 				},
 				"sounds" : {
 					"ambient" : ["LOOPGEMP"]
-				}
+				},
+				"battleground": "subterranean"
 			},
 			"goldMine" : {
 				"index" : 6,
@@ -297,7 +303,8 @@
 				},
 				"sounds" : {
 					"ambient" : ["LOOPMINE"]
-				}
+				},
+				"battleground": "subterranean"
 			},
 			"abandoned" :	{
 				"index" : 7,
@@ -305,7 +312,8 @@
 				"sounds" : {
 					"ambient" : ["LOOPCAVE"],
 					"visit" : ["MYSTERY"]
-				}
+				},
+				"battleground": "subterranean"
 			}
 		}
 	},
@@ -319,7 +327,7 @@
 			}
 		},
 		"types" : {
-			"mine" : { "index" : 7 }
+			"mine" : { "index" : 7, "battleground": "subterranean" }
 		}
 	},
 

+ 10 - 26
lib/CGameState.cpp

@@ -1902,9 +1902,12 @@ BattleField CGameState::battleGetBattlefieldType(int3 tile, CRandomGenerator & r
 		return BattleField::NONE;
 
 	const TerrainTile &t = map->getTile(tile);
-	//fight in mine -> subterranean
-	if(dynamic_cast<const CGMine *>(t.visitableObjects.front()))
-		return BattleField("subterranean");
+
+	auto topObject = t.visitableObjects.front();
+	if(topObject && topObject->getBattlefield() != BattleField::NONE)
+	{
+		return topObject->getBattlefield();
+	}
 
 	for(auto &obj : map->objects)
 	{
@@ -1912,29 +1915,10 @@ BattleField CGameState::battleGetBattlefieldType(int3 tile, CRandomGenerator & r
 		if( !obj || obj->pos.z != tile.z || !obj->coveringAt(tile.x, tile.y))
 			continue;
 
-		switch(obj->ID)
-		{
-		case Obj::CLOVER_FIELD:
-			return BattleField("clover_field");
-		case Obj::CURSED_GROUND1: case Obj::CURSED_GROUND2:
-			return BattleField("cursed_ground");
-		case Obj::EVIL_FOG:
-			return BattleField("evil_fog");
-		case Obj::FAVORABLE_WINDS:
-			return BattleField("favorable_winds");
-		case Obj::FIERY_FIELDS:
-			return BattleField("fiery_fields");
-		case Obj::HOLY_GROUNDS:
-			return BattleField("holy_ground");
-		case Obj::LUCID_POOLS:
-			return BattleField("lucid_pools");
-		case Obj::MAGIC_CLOUDS:
-			return BattleField("magic_clouds");
-		case Obj::MAGIC_PLAINS1: case Obj::MAGIC_PLAINS2:
-			return BattleField("magic_plains");
-		case Obj::ROCKLANDS:
-			return BattleField("rocklands");
-		}
+		auto customBattlefield = obj->getBattlefield();
+
+		if(customBattlefield != BattleField::NONE)
+			return customBattlefield;
 	}
 
 	if(map->isCoastalTile(tile)) //coastal tile is always ground

+ 3 - 3
lib/CHeroHandler.cpp

@@ -177,10 +177,10 @@ std::vector<BattleHex> CObstacleInfo::getBlocked(BattleHex hex) const
 	return ret;
 }
 
-bool CObstacleInfo::isAppropriate(const Terrain & terrainType, const BattleField & specialBattlefield) const
+bool CObstacleInfo::isAppropriate(const Terrain & terrainType, const BattleField & battlefield) const
 {
-	if(!allowedSpecialBfields.empty() && specialBattlefield != BattleField::NONE)
-		return vstd::contains(allowedSpecialBfields, specialBattlefield);
+	if(battlefield.isSpecial())
+		return vstd::contains(allowedSpecialBfields, battlefield);
 
 	return vstd::contains(allowedTerrains, terrainType);
 }

+ 5 - 0
lib/Terrain.h

@@ -42,6 +42,11 @@ public:
 	{
 		h & name;
 	}
+
+	bool isSpecial() const
+	{
+		return name.find('_') >= 0; // hack for special battlefields, move to JSON
+	}
 	
 protected:
 	

+ 3 - 3
lib/battle/BattleInfo.cpp

@@ -467,7 +467,7 @@ BattleInfo * BattleInfo::setupBattle(const int3 & tile, const Terrain & terrain,
 	}
 	if(battlefieldType == BattleField("fiery_fields"))
 	{
-		if(bonusSubtype == -1) bonusSubtype = 1;
+		if(bonusSubtype == -1) bonusSubtype = 2;
 	}
 	if(battlefieldType == BattleField("rocklands"))
 	{
@@ -475,13 +475,13 @@ BattleInfo * BattleInfo::setupBattle(const int3 & tile, const Terrain & terrain,
 	}
 	if(battlefieldType == BattleField("magic_clouds"))
 	{
-		if(bonusSubtype == -1) bonusSubtype = 2;
+		if(bonusSubtype == -1) bonusSubtype = 1;
 	}
 	if(battlefieldType == BattleField("lucid_pools"))
 	{
 		if(bonusSubtype == -1) bonusSubtype = 4;
 	}
-	if(bonusSubtype == -1)
+	if(bonusSubtype != -1)
 	{ //common part for cases 9, 14, 15, 16, 17
 		curB->addNewBonus(std::make_shared<Bonus>(Bonus::ONE_BATTLE, Bonus::MAGIC_SCHOOL_SKILL,Bonus::TERRAIN_OVERLAY, 3, battlefieldType.hash(), bonusSubtype));
 	}

+ 11 - 0
lib/mapObjects/CObjectClassesHandler.cpp

@@ -97,6 +97,7 @@ CObjectClassesHandler::CObjectClassesHandler()
 	SET_HANDLER("oncePerHero", CGVisitableOPH);
 	SET_HANDLER("oncePerWeek", CGVisitableOPW);
 	SET_HANDLER("witch", CGWitchHut);
+	SET_HANDLER("terrain", CGTerrainPatch);
 
 #undef SET_HANDLER_CLASS
 #undef SET_HANDLER
@@ -514,6 +515,11 @@ void AObjectTypeHandler::init(const JsonNode & input, boost::optional<std::strin
 	else
 		aiValue = static_cast<boost::optional<si32>>(input["aiValue"].Integer());
 
+	if(input["battleground"].isNull())
+		battlefield = BattleField::NONE;
+	else
+		battlefield = BattleField(input["battleground"].String());
+
 	initTypeData(input);
 }
 
@@ -569,6 +575,11 @@ std::vector<ObjectTemplate> AObjectTypeHandler::getTemplates() const
 	return templates;
 }
 
+BattleField AObjectTypeHandler::getBattlefield() const
+{
+	return battlefield;
+}
+
 std::vector<ObjectTemplate> AObjectTypeHandler::getTemplates(const Terrain & terrainType) const
 {
 	std::vector<ObjectTemplate> templates = getTemplates();

+ 5 - 0
lib/mapObjects/CObjectClassesHandler.h

@@ -15,6 +15,7 @@
 #include "../ConstTransitivePtr.h"
 #include "../IHandlerBase.h"
 #include "../JsonNode.h"
+#include "Terrain.h"
 
 class JsonNode;
 class CRandomGenerator;
@@ -148,6 +149,9 @@ class DLL_LINKAGE AObjectTypeHandler : public boost::noncopyable
 	SObjectSounds sounds;
 
 	boost::optional<si32> aiValue;
+
+	BattleField battlefield;
+
 protected:
 	void preInitObject(CGObjectInstance * obj) const;
 	virtual bool objectFilter(const CGObjectInstance *, const ObjectTemplate &) const;
@@ -179,6 +183,7 @@ public:
 	/// returns all templates matching parameters
 	std::vector<ObjectTemplate> getTemplates() const;
 	std::vector<ObjectTemplate> getTemplates(const Terrain & terrainType) const;
+	BattleField getBattlefield() const;
 
 	/// returns preferred template for this object, if present (e.g. one of 3 possible templates for town - village, fort and castle)
 	/// note that appearance will not be changed - this must be done separately (either by assignment or via pack from server)

+ 5 - 0
lib/mapObjects/CObjectHandler.cpp

@@ -400,6 +400,11 @@ void CGObjectInstance::serializeJsonOwner(JsonSerializeFormat & handler)
 		tempOwner = PlayerColor(temp);
 }
 
+BattleField CGObjectInstance::getBattlefield() const
+{
+	return VLC->objtypeh->getHandlerFor(ID, subID)->getBattlefield();
+}
+
 CGObjectInstanceBySubIdFinder::CGObjectInstanceBySubIdFinder(CGObjectInstance * obj) : obj(obj)
 {
 

+ 3 - 15
lib/mapObjects/CObjectHandler.h

@@ -159,21 +159,9 @@ public:
 	std::set<int3> getBlockedOffsets() const; //returns set of relative positions blocked by this object
 	bool isVisitable() const; //returns true if object is visitable
 
-	bool isTile2Terrain() const
-	{
-		return ID.num == Obj::CLOVER_FIELD
-			|| ID.num == Obj::CURSED_GROUND1
-			|| ID.num == Obj::CURSED_GROUND2
-			|| ID.num == Obj::EVIL_FOG
-			|| ID.num == Obj::FAVORABLE_WINDS
-			|| ID.num == Obj::FIERY_FIELDS
-			|| ID.num == Obj::HOLY_GROUNDS
-			|| ID.num == Obj::LUCID_POOLS
-			|| ID.num == Obj::MAGIC_CLOUDS
-			|| ID.num == Obj::MAGIC_PLAINS1
-			|| ID.num == Obj::MAGIC_PLAINS2
-			|| ID.num == Obj::ROCKLANDS;
-	}
+	BattleField getBattlefield() const;
+
+	virtual bool isTile2Terrain() const { return false; }
 
 	boost::optional<std::string> getAmbientSound() const;
 	boost::optional<std::string> getVisitSound() const;

+ 1 - 1
lib/mapObjects/MiscObjects.cpp

@@ -2199,4 +2199,4 @@ void CGLighthouse::giveBonusTo(PlayerColor player, bool onInit) const
 void CGLighthouse::serializeJsonOptions(JsonSerializeFormat& handler)
 {
 	serializeJsonOwner(handler);
-}
+}

+ 11 - 0
lib/mapObjects/MiscObjects.h

@@ -529,3 +529,14 @@ public:
 protected:
 	void serializeJsonOptions(JsonSerializeFormat & handler) override;
 };
+
+class DLL_LINKAGE CGTerrainPatch : public CGObjectInstance
+{
+public:
+	CGTerrainPatch() = default;
+
+	virtual bool isTile2Terrain() const override
+	{
+		return true;
+	}
+};