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
"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} } },

View File

@ -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" }
}
},

View File

@ -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

View File

@ -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);
}

View File

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

View File

@ -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));
}

View File

@ -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();

View File

@ -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)

View File

@ -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)
{

View File

@ -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;

View File

@ -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;
}
};