1
0
mirror of https://github.com/vcmi/vcmi.git synced 2024-12-20 20:23:03 +02:00

allow configurable battleground graphics

This commit is contained in:
Andrii Danylchenko 2022-06-26 10:21:05 +03:00
parent c4035134e5
commit 3b1d271ae0
12 changed files with 132 additions and 75 deletions

View File

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

View File

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

View File

@ -1902,9 +1902,12 @@ BattleField CGameState::battleGetBattlefieldType(int3 tile, CRandomGenerator & r
return BattleField::NONE; return BattleField::NONE;
const TerrainTile &t = map->getTile(tile); const TerrainTile &t = map->getTile(tile);
//fight in mine -> subterranean
if(dynamic_cast<const CGMine *>(t.visitableObjects.front())) auto topObject = t.visitableObjects.front();
return BattleField("subterranean"); if(topObject && topObject->getBattlefield() != BattleField::NONE)
{
return topObject->getBattlefield();
}
for(auto &obj : map->objects) 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)) if( !obj || obj->pos.z != tile.z || !obj->coveringAt(tile.x, tile.y))
continue; continue;
switch(obj->ID) auto customBattlefield = obj->getBattlefield();
{
case Obj::CLOVER_FIELD: if(customBattlefield != BattleField::NONE)
return BattleField("clover_field"); return customBattlefield;
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");
}
} }
if(map->isCoastalTile(tile)) //coastal tile is always ground if(map->isCoastalTile(tile)) //coastal tile is always ground

View File

@ -177,10 +177,10 @@ std::vector<BattleHex> CObstacleInfo::getBlocked(BattleHex hex) const
return ret; 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) if(battlefield.isSpecial())
return vstd::contains(allowedSpecialBfields, specialBattlefield); return vstd::contains(allowedSpecialBfields, battlefield);
return vstd::contains(allowedTerrains, terrainType); return vstd::contains(allowedTerrains, terrainType);
} }

View File

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

View File

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

View File

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

View File

@ -15,6 +15,7 @@
#include "../ConstTransitivePtr.h" #include "../ConstTransitivePtr.h"
#include "../IHandlerBase.h" #include "../IHandlerBase.h"
#include "../JsonNode.h" #include "../JsonNode.h"
#include "Terrain.h"
class JsonNode; class JsonNode;
class CRandomGenerator; class CRandomGenerator;
@ -148,6 +149,9 @@ class DLL_LINKAGE AObjectTypeHandler : public boost::noncopyable
SObjectSounds sounds; SObjectSounds sounds;
boost::optional<si32> aiValue; boost::optional<si32> aiValue;
BattleField battlefield;
protected: protected:
void preInitObject(CGObjectInstance * obj) const; void preInitObject(CGObjectInstance * obj) const;
virtual bool objectFilter(const CGObjectInstance *, const ObjectTemplate &) const; virtual bool objectFilter(const CGObjectInstance *, const ObjectTemplate &) const;
@ -179,6 +183,7 @@ public:
/// returns all templates matching parameters /// returns all templates matching parameters
std::vector<ObjectTemplate> getTemplates() const; std::vector<ObjectTemplate> getTemplates() const;
std::vector<ObjectTemplate> getTemplates(const Terrain & terrainType) 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) /// 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) /// note that appearance will not be changed - this must be done separately (either by assignment or via pack from server)

View File

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

View File

@ -159,21 +159,9 @@ public:
std::set<int3> getBlockedOffsets() const; //returns set of relative positions blocked by this object std::set<int3> getBlockedOffsets() const; //returns set of relative positions blocked by this object
bool isVisitable() const; //returns true if object is visitable bool isVisitable() const; //returns true if object is visitable
bool isTile2Terrain() const BattleField getBattlefield() const;
{
return ID.num == Obj::CLOVER_FIELD virtual bool isTile2Terrain() const { return false; }
|| 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;
}
boost::optional<std::string> getAmbientSound() const; boost::optional<std::string> getAmbientSound() const;
boost::optional<std::string> getVisitSound() const; boost::optional<std::string> getVisitSound() const;

View File

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