mirror of
https://github.com/vcmi/vcmi.git
synced 2024-12-22 22:13:35 +02:00
battlefields in VLC and custom bonuses for terrain patches
This commit is contained in:
parent
2228a6f9bf
commit
ac2bd4f79c
@ -37,6 +37,7 @@ void CGameInfo::setFromLib()
|
||||
spellh = VLC->spellh;
|
||||
skillh = VLC->skillh;
|
||||
objtypeh = VLC->objtypeh;
|
||||
battleFieldHandler = VLC->battlefieldsHandler;
|
||||
}
|
||||
|
||||
const ArtifactService * CGameInfo::artifacts() const
|
||||
@ -44,6 +45,11 @@ const ArtifactService * CGameInfo::artifacts() const
|
||||
return globalServices->artifacts();
|
||||
}
|
||||
|
||||
const BattleFieldService * CGameInfo::battlefields() const
|
||||
{
|
||||
return globalServices->battlefields();
|
||||
}
|
||||
|
||||
const CreatureService * CGameInfo::creatures() const
|
||||
{
|
||||
return globalServices->creatures();
|
||||
|
@ -31,6 +31,7 @@ class CCursorHandler;
|
||||
class CGameState;
|
||||
class IMainVideoPlayer;
|
||||
class CServerHandler;
|
||||
class BattleFieldHandler;
|
||||
|
||||
class CMap;
|
||||
|
||||
@ -60,6 +61,7 @@ public:
|
||||
const scripting::Service * scripts() const override;
|
||||
const spells::Service * spells() const override;
|
||||
const SkillService * skills() const override;
|
||||
const BattleFieldService * battlefields() const override;
|
||||
|
||||
void updateEntity(Metatype metatype, int32_t index, const JsonNode & data) override;
|
||||
|
||||
@ -68,6 +70,7 @@ public:
|
||||
|
||||
|
||||
ConstTransitivePtr<CModHandler> modh; //public?
|
||||
ConstTransitivePtr<BattleFieldHandler> battleFieldHandler;
|
||||
ConstTransitivePtr<CHeroHandler> heroh;
|
||||
ConstTransitivePtr<CCreatureHandler> creh;
|
||||
ConstTransitivePtr<CSpellHandler> spellh;
|
||||
|
@ -109,12 +109,6 @@ void Graphics::initializeBattleGraphics()
|
||||
|
||||
const JsonNode config(mod, ResourceID("config/battles_graphics.json"));
|
||||
|
||||
if(!config["backgrounds"].isNull())
|
||||
for(auto & t : config["backgrounds"].Struct())
|
||||
{
|
||||
battleBacks[t.first] = t.second.String();
|
||||
}
|
||||
|
||||
//initialization of AC->def name mapping
|
||||
if(!config["ac_mapping"].isNull())
|
||||
for(const JsonNode &ac : config["ac_mapping"].Vector())
|
||||
|
@ -87,7 +87,6 @@ public:
|
||||
//towns
|
||||
std::map<int, std::string> ERMUtoPicture[GameConstants::F_NUMBER]; //maps building ID to it's picture's name for each town type
|
||||
//for battles
|
||||
std::map<std::string, std::string> battleBacks; //maps BattleField to it's picture's name
|
||||
std::map< int, std::vector < std::string > > battleACToDef; //maps AC format to vector of appropriate def names
|
||||
|
||||
//functions
|
||||
|
@ -41,6 +41,7 @@
|
||||
#include "../../lib/spells/ISpellMechanics.h"
|
||||
#include "../../lib/spells/Problem.h"
|
||||
#include "../../lib/CTownHandler.h"
|
||||
#include "../../lib/BattleFieldHandler.h"
|
||||
#include "../../lib/CGameState.h"
|
||||
#include "../../lib/mapping/CMap.h"
|
||||
#include "../../lib/NetPacks.h"
|
||||
@ -201,13 +202,14 @@ CBattleInterface::CBattleInterface(const CCreatureSet *army1, const CCreatureSet
|
||||
else
|
||||
{
|
||||
auto bfieldType = curInt->cb->battleGetBattlefieldType();
|
||||
if(!vstd::contains(graphics->battleBacks, bfieldType))
|
||||
|
||||
if(bfieldType == BattleField::NONE)
|
||||
{
|
||||
logGlobal->error("%s is not valid battlefield type!", static_cast<std::string>(bfieldType));
|
||||
logGlobal->error("Invalid battlefield returned for current battle");
|
||||
}
|
||||
else
|
||||
{
|
||||
background = BitmapHandler::loadBitmap(graphics->battleBacks[bfieldType], false);
|
||||
background = BitmapHandler::loadBitmap(bfieldType.getInfo()->graphics, false);
|
||||
}
|
||||
}
|
||||
|
||||
|
173
config/battlefields.json
Normal file
173
config/battlefields.json
Normal file
@ -0,0 +1,173 @@
|
||||
{
|
||||
"sand_shore": { "graphics" : "CMBKBCH.BMP" },
|
||||
"sand_mesas": { "graphics" : "CMBKDES.BMP" },
|
||||
"dirt_birches": { "graphics" : "CMBKDRTR.BMP" },
|
||||
"dirt_hills": { "graphics" : "CMBKDRMT.BMP" },
|
||||
"dirt_pines": { "graphics" : "CMBKDRDD.BMP" },
|
||||
"grass_hills": { "graphics" : "CMBKGRMT.BMP" },
|
||||
"grass_pines": { "graphics" : "CMBKGRTR.BMP" },
|
||||
"lava": { "graphics" :"CMBKLAVA.BMP" },
|
||||
"magic_plains": {
|
||||
"graphics": "CMBKMAG.BMP",
|
||||
"isSpecial" : true,
|
||||
"bonuses": [
|
||||
{
|
||||
"type" : "MAGIC_SCHOOL_SKILL",
|
||||
"subtype" : 0,
|
||||
"val" : 3,
|
||||
"valueType" : "BASE_NUMBER"
|
||||
}
|
||||
]
|
||||
},
|
||||
"snow_mountains": { "graphics" : "CMBKSNMT.BMP" },
|
||||
"snow_trees": { "graphics" : "CMBKSNTR.BMP" },
|
||||
"subterranean": { "graphics" : "CMBKSUB.BMP", "isSpecial" : true },
|
||||
"swamp_trees": { "graphics" : "CMBKSWMP.BMP" },
|
||||
"fiery_fields": {
|
||||
"graphics": "CMBKFF.BMP",
|
||||
"isSpecial" : true,
|
||||
"bonuses": [
|
||||
{
|
||||
"type" : "MAGIC_SCHOOL_SKILL",
|
||||
"subtype" : 2,
|
||||
"val" : 3,
|
||||
"valueType" : "BASE_NUMBER"
|
||||
}
|
||||
]
|
||||
},
|
||||
"rocklands": {
|
||||
"graphics": "CMBKRK.BMP",
|
||||
"isSpecial" : true,
|
||||
"bonuses": [
|
||||
{
|
||||
"type" : "MAGIC_SCHOOL_SKILL",
|
||||
"subtype" : 8,
|
||||
"val" : 3,
|
||||
"valueType" : "BASE_NUMBER"
|
||||
}
|
||||
]
|
||||
},
|
||||
"magic_clouds": {
|
||||
"graphics": "CMBKMC.BMP",
|
||||
"isSpecial" : true,
|
||||
"bonuses": [
|
||||
{
|
||||
"type" : "MAGIC_SCHOOL_SKILL",
|
||||
"subtype" : 1,
|
||||
"val" : 3,
|
||||
"valueType" : "BASE_NUMBER"
|
||||
}
|
||||
]
|
||||
},
|
||||
"lucid_pools": {
|
||||
"graphics": "CMBKLP.BMP",
|
||||
"isSpecial" : true,
|
||||
"bonuses": [
|
||||
{
|
||||
"type" : "MAGIC_SCHOOL_SKILL",
|
||||
"subtype" : 4,
|
||||
"val" : 3,
|
||||
"valueType" : "BASE_NUMBER"
|
||||
}
|
||||
]
|
||||
},
|
||||
"holy_ground": {
|
||||
"graphics": "CMBKHG.BMP",
|
||||
"isSpecial" : true,
|
||||
"bonuses": [
|
||||
{
|
||||
"type" : "MORALE",
|
||||
"val" : 1,
|
||||
"valueType" : "BASE_NUMBER",
|
||||
"description" : "Creatures of good town alignment on Holly Ground",
|
||||
"limiters": [{ "type" : "CREATURE_ALIGNMENT_LIMITER", "parameters" : ["good"] }]
|
||||
},
|
||||
{
|
||||
"type" : "MORALE",
|
||||
"val" : -1,
|
||||
"valueType" : "BASE_NUMBER",
|
||||
"description" : "Creatures of evil town alignment on Holly Ground",
|
||||
"limiters": [{ "type" : "CREATURE_ALIGNMENT_LIMITER", "parameters" : ["evil"] }]
|
||||
}
|
||||
]
|
||||
},
|
||||
"clover_field": {
|
||||
"graphics": "CMBKCF.BMP",
|
||||
"isSpecial" : true,
|
||||
"bonuses": [
|
||||
{
|
||||
"type" : "LUCK",
|
||||
"val" : 2,
|
||||
"valueType" : "BASE_NUMBER",
|
||||
"description" : "Creatures of neutral town alignment on Clover Field",
|
||||
"limiters": [{ "type" : "CREATURE_ALIGNMENT_LIMITER", "parameters" : ["neutral"] }]
|
||||
}
|
||||
]
|
||||
},
|
||||
"evil_fog": {
|
||||
"graphics": "CMBKEF.BMP",
|
||||
"isSpecial" : true,
|
||||
"bonuses": [
|
||||
{
|
||||
"type" : "MORALE",
|
||||
"val" : -1,
|
||||
"valueType" : "BASE_NUMBER",
|
||||
"description" : "Creatures of good town alignment on Evil Fog",
|
||||
"limiters": [{ "type" : "CREATURE_ALIGNMENT_LIMITER", "parameters" : ["good"] }]
|
||||
},
|
||||
{
|
||||
"type" : "MORALE",
|
||||
"val" : 1,
|
||||
"valueType" : "BASE_NUMBER",
|
||||
"description" : "Creatures of evil town alignment on Evil Fog",
|
||||
"limiters": [{ "type" : "CREATURE_ALIGNMENT_LIMITER", "parameters" : ["evil"] }]
|
||||
}
|
||||
]
|
||||
},
|
||||
"favorable_winds": {
|
||||
"graphics": "CMBKFW.BMP",
|
||||
"isSpecial" : true
|
||||
},
|
||||
"cursed_ground": {
|
||||
"graphics": "CMBKCUR.BMP",
|
||||
"isSpecial" : true,
|
||||
"bonuses": [
|
||||
{
|
||||
"type" : "NO_MORALE",
|
||||
"subtype" : 0,
|
||||
"val" : 0,
|
||||
"valueType" : "INDEPENDENT_MIN",
|
||||
"description" : "Creatures on Cursed Ground"
|
||||
},
|
||||
{
|
||||
"type" : "NO_LUCK",
|
||||
"subtype" : 0,
|
||||
"val" : 0,
|
||||
"valueType" : "INDEPENDENT_MIN",
|
||||
"description" : "Creatures on Cursed Ground"
|
||||
},
|
||||
{
|
||||
"type" : "BLOCK_MAGIC_ABOVE",
|
||||
"subtype" : 0,
|
||||
"val" : 1,
|
||||
"valueType" : "INDEPENDENT_MIN"
|
||||
}
|
||||
]
|
||||
},
|
||||
"rough": { "graphics" : "CMBKRGH.BMP" },
|
||||
"ship_to_ship":
|
||||
{
|
||||
"graphics" : "CMBKBOAT.BMP"
|
||||
"impassableHexes" : [
|
||||
6, 7, 8, 9,
|
||||
24, 25, 26,
|
||||
58, 59, 60,
|
||||
75, 76, 77,
|
||||
92, 93, 94,
|
||||
109, 110, 111,
|
||||
126, 127, 128,
|
||||
159, 160, 161, 162, 163,
|
||||
176, 177, 178, 179, 180]
|
||||
},
|
||||
"ship": { "graphics" : "CMBKDECK.BMP" }
|
||||
}
|
@ -1,33 +1,4 @@
|
||||
{
|
||||
// backgrounds of terrains battles can be fought on
|
||||
"backgrounds": {
|
||||
"sand_shore": "CMBKBCH.BMP",
|
||||
"sand_mesas": "CMBKDES.BMP",
|
||||
"dirt_birches": "CMBKDRTR.BMP",
|
||||
"dirt_hills": "CMBKDRMT.BMP",
|
||||
"dirt_pines": "CMBKDRDD.BMP",
|
||||
"grass_hills": "CMBKGRMT.BMP",
|
||||
"grass_pines": "CMBKGRTR.BMP",
|
||||
"lava": "CMBKLAVA.BMP",
|
||||
"magic_plains": "CMBKMAG.BMP",
|
||||
"snow_mountains": "CMBKSNMT.BMP",
|
||||
"snow_trees": "CMBKSNTR.BMP",
|
||||
"subterranean": "CMBKSUB.BMP",
|
||||
"swamp_trees": "CMBKSWMP.BMP",
|
||||
"fiery_fields": "CMBKFF.BMP",
|
||||
"rocklands": "CMBKRK.BMP",
|
||||
"magic_clouds": "CMBKMC.BMP",
|
||||
"lucid_pools": "CMBKLP.BMP",
|
||||
"holy_ground": "CMBKHG.BMP",
|
||||
"clover_field": "CMBKCF.BMP",
|
||||
"evil_fog": "CMBKEF.BMP",
|
||||
"favorable_winds": "CMBKFW.BMP",
|
||||
"cursed_ground": "CMBKCUR.BMP",
|
||||
"rough": "CMBKRGH.BMP",
|
||||
"ship_to_ship": "CMBKBOAT.BMP",
|
||||
"ship": "CMBKDECK.BMP"
|
||||
},
|
||||
|
||||
// WoG_Ac_format_to_def_names_mapping
|
||||
"ac_mapping": [
|
||||
{ "id": 0, "defnames": [ "C10SPW.DEF" ] },//merged
|
||||
|
@ -84,5 +84,9 @@
|
||||
"terrains":
|
||||
[
|
||||
"config/terrains.json"
|
||||
],
|
||||
"battlefields":
|
||||
[
|
||||
"config/battlefields.json"
|
||||
]
|
||||
}
|
||||
|
35
config/schemas/battlefield.json
Normal file
35
config/schemas/battlefield.json
Normal file
@ -0,0 +1,35 @@
|
||||
{
|
||||
"type":"object",
|
||||
"$schema": "http://json-schema.org/draft-04/schema",
|
||||
"title" : "VCMI battlefield format",
|
||||
"description" : "Format used to define new artifacts in VCMI",
|
||||
"required" : [ "graphics" ],
|
||||
|
||||
"additionalProperties" : false,
|
||||
"properties":{
|
||||
"bonuses": {
|
||||
"type":"array",
|
||||
"description": "Bonuses provided by this battleground using bonus system",
|
||||
"items": { "$ref" : "bonus.json" }
|
||||
},
|
||||
"name": {
|
||||
"type":"string",
|
||||
"description": "Name of the battleground"
|
||||
},
|
||||
"graphics": {
|
||||
"type":"string",
|
||||
"description": "BMP battleground resource"
|
||||
},
|
||||
"isSpecial": {
|
||||
"type":"boolean",
|
||||
"description": "Shows if this battleground has own obstacles"
|
||||
},
|
||||
"impassableHexes": {
|
||||
"type":"array",
|
||||
"description": "Battle hexes always impassable for this type of battlefield (ship to ship for instance)",
|
||||
"items": {
|
||||
"type":"number"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -112,6 +112,12 @@
|
||||
"description": "List of configuration files for RMG templates",
|
||||
"items": { "type":"string", "format" : "textFile" }
|
||||
|
||||
},
|
||||
"battlefields":{
|
||||
"type":"array",
|
||||
"description": "List of configuration files for battlefields",
|
||||
"items": { "type":"string", "format" : "textFile" }
|
||||
|
||||
},
|
||||
|
||||
"changelog" : {
|
||||
|
@ -19,6 +19,7 @@ class HeroClassService;
|
||||
class HeroTypeService;
|
||||
class SkillService;
|
||||
class JsonNode;
|
||||
class BattleFieldService;
|
||||
|
||||
namespace spells
|
||||
{
|
||||
@ -48,6 +49,7 @@ public:
|
||||
virtual const scripting::Service * scripts() const = 0;
|
||||
virtual const spells::Service * spells() const = 0;
|
||||
virtual const SkillService * skills() const = 0;
|
||||
virtual const BattleFieldService * battlefields() const = 0;
|
||||
|
||||
virtual void updateEntity(Metatype metatype, int32_t index, const JsonNode & data) = 0;
|
||||
|
||||
|
108
lib/BattleFieldHandler.cpp
Normal file
108
lib/BattleFieldHandler.cpp
Normal file
@ -0,0 +1,108 @@
|
||||
/*
|
||||
* BattleFieldHandler.h, part of VCMI engine
|
||||
*
|
||||
* Authors: listed in file AUTHORS in main folder
|
||||
*
|
||||
* License: GNU General Public License v2.0 or later
|
||||
* Full text of license available in license.txt file, in main folder
|
||||
*
|
||||
*/
|
||||
#include "StdInc.h"
|
||||
|
||||
#include <vcmi/Entity.h>
|
||||
#include "BattleFieldHandler.h"
|
||||
|
||||
BattleFieldInfo * BattleFieldHandler::loadFromJson(const std::string & scope, const JsonNode & json, const std::string & identifier, size_t index)
|
||||
{
|
||||
BattleFieldInfo * info = new BattleFieldInfo(BattleField(index), identifier);
|
||||
|
||||
if(json["graphics"].getType() == JsonNode::JsonType::DATA_STRING)
|
||||
{
|
||||
info->graphics = json["graphics"].String();
|
||||
}
|
||||
|
||||
if(json["icon"].getType() == JsonNode::JsonType::DATA_STRING)
|
||||
{
|
||||
info->icon = json["icon"].String();
|
||||
}
|
||||
|
||||
if(json["name"].getType() == JsonNode::JsonType::DATA_STRING)
|
||||
{
|
||||
info->name = json["name"].String();
|
||||
}
|
||||
|
||||
if(json["bonuses"].getType() == JsonNode::JsonType::DATA_VECTOR)
|
||||
{
|
||||
for(auto b : json["bonuses"].Vector())
|
||||
{
|
||||
auto bonus = JsonUtils::parseBonus(b);
|
||||
|
||||
bonus->source = Bonus::TERRAIN_OVERLAY;
|
||||
bonus->sid = info->getIndex();
|
||||
bonus->duration = Bonus::ONE_BATTLE;
|
||||
|
||||
info->bonuses.push_back(bonus);
|
||||
}
|
||||
}
|
||||
|
||||
if(json["isSpecial"].getType() == JsonNode::JsonType::DATA_BOOL)
|
||||
{
|
||||
info->isSpecial = json["isSpecial"].Bool();
|
||||
}
|
||||
|
||||
if(json["impassableHexes"].getType() == JsonNode::JsonType::DATA_VECTOR)
|
||||
{
|
||||
for(auto node : json["impassableHexes"].Vector())
|
||||
info->impassableHexes.push_back(BattleHex(node.Integer()));
|
||||
}
|
||||
|
||||
|
||||
return info;
|
||||
}
|
||||
|
||||
std::vector<JsonNode> BattleFieldHandler::loadLegacyData(size_t dataSize)
|
||||
{
|
||||
return std::vector<JsonNode>();
|
||||
}
|
||||
|
||||
const std::vector<std::string> & BattleFieldHandler::getTypeNames() const
|
||||
{
|
||||
static const std::vector<std::string> types = std::vector<std::string> { "battlefield" };
|
||||
|
||||
return types;
|
||||
}
|
||||
|
||||
std::vector<bool> BattleFieldHandler::getDefaultAllowed() const
|
||||
{
|
||||
return std::vector<bool>();
|
||||
}
|
||||
|
||||
int32_t BattleFieldInfo::getIndex() const
|
||||
{
|
||||
return battlefield.getNum();
|
||||
}
|
||||
|
||||
int32_t BattleFieldInfo::getIconIndex() const
|
||||
{
|
||||
return iconIndex;
|
||||
}
|
||||
|
||||
const std::string & BattleFieldInfo::getName() const
|
||||
{
|
||||
return name;
|
||||
}
|
||||
|
||||
const std::string & BattleFieldInfo::getJsonKey() const
|
||||
{
|
||||
return identifier;
|
||||
}
|
||||
|
||||
void BattleFieldInfo::registerIcons(const IconRegistar & cb) const
|
||||
{
|
||||
//cb(getIconIndex(), "BATTLEFIELD", icon);
|
||||
}
|
||||
|
||||
BattleField BattleFieldInfo::getId() const
|
||||
{
|
||||
return battlefield;
|
||||
}
|
85
lib/BattleFieldHandler.h
Normal file
85
lib/BattleFieldHandler.h
Normal file
@ -0,0 +1,85 @@
|
||||
/*
|
||||
* BattleFieldHandler.h, part of VCMI engine
|
||||
*
|
||||
* Authors: listed in file AUTHORS in main folder
|
||||
*
|
||||
* License: GNU General Public License v2.0 or later
|
||||
* Full text of license available in license.txt file, in main folder
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <vcmi/EntityService.h>
|
||||
#include "HeroBonus.h"
|
||||
#include "GameConstants.h"
|
||||
#include "IHandlerBase.h"
|
||||
#include "Terrain.h"
|
||||
#include "battle/BattleHex.h"
|
||||
|
||||
class BattleFieldInfo : public EntityT<BattleField>
|
||||
{
|
||||
public:
|
||||
BattleField battlefield;
|
||||
std::vector<std::shared_ptr<Bonus>> bonuses;
|
||||
bool isSpecial;
|
||||
std::string graphics;
|
||||
std::string name;
|
||||
std::string identifier;
|
||||
std::string icon;
|
||||
si32 iconIndex;
|
||||
std::vector<BattleHex> impassableHexes;
|
||||
|
||||
BattleFieldInfo()
|
||||
: BattleFieldInfo(BattleField::NONE, "")
|
||||
{
|
||||
}
|
||||
|
||||
BattleFieldInfo(BattleField battlefield, std::string identifier)
|
||||
:bonuses(), isSpecial(false), battlefield(battlefield), identifier(identifier), graphics(), icon(), iconIndex(battlefield.getNum()), impassableHexes(), name(identifier)
|
||||
{
|
||||
}
|
||||
|
||||
int32_t getIndex() const override;
|
||||
int32_t getIconIndex() const override;
|
||||
const std::string & getName() const override;
|
||||
const std::string & getJsonKey() const override;
|
||||
void registerIcons(const IconRegistar & cb) const override;
|
||||
BattleField getId() const override;
|
||||
|
||||
template <typename Handler> void serialize(Handler & h, const int version)
|
||||
{
|
||||
h & name;
|
||||
h & identifier;
|
||||
h & isSpecial;
|
||||
h & graphics;
|
||||
h & icon;
|
||||
h & iconIndex;
|
||||
h & battlefield;
|
||||
h & impassableHexes;
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
class DLL_LINKAGE BattleFieldService : public EntityServiceT<BattleField, BattleFieldInfo>
|
||||
{
|
||||
public:
|
||||
};
|
||||
|
||||
class BattleFieldHandler : public CHandlerBase<BattleField, BattleFieldInfo, BattleFieldInfo, BattleFieldService>
|
||||
{
|
||||
public:
|
||||
virtual BattleFieldInfo * loadFromJson(
|
||||
const std::string & scope,
|
||||
const JsonNode & json,
|
||||
const std::string & identifier,
|
||||
size_t index) override;
|
||||
|
||||
virtual const std::vector<std::string> & getTypeNames() const override;
|
||||
virtual std::vector<JsonNode> loadLegacyData(size_t dataSize) override;
|
||||
virtual std::vector<bool> getDefaultAllowed() const override;
|
||||
|
||||
template <typename Handler> void serialize(Handler & h, const int version)
|
||||
{
|
||||
h & objects;
|
||||
}
|
||||
};
|
@ -1922,9 +1922,10 @@ BattleField CGameState::battleGetBattlefieldType(int3 tile, CRandomGenerator & r
|
||||
}
|
||||
|
||||
if(map->isCoastalTile(tile)) //coastal tile is always ground
|
||||
return BattleField("sand_shore");
|
||||
return BattleField::fromString("sand_shore");
|
||||
|
||||
return *RandomGeneratorUtil::nextItem(Terrain::Manager::getInfo(t.terType).battleFields, rand);
|
||||
return BattleField::fromString(
|
||||
*RandomGeneratorUtil::nextItem(Terrain::Manager::getInfo(t.terType).battleFields, rand));
|
||||
}
|
||||
|
||||
UpgradeInfo CGameState::getUpgradeInfo(const CStackInstance &stack)
|
||||
|
@ -25,6 +25,7 @@
|
||||
#include <math.h>
|
||||
|
||||
#include "mapObjects/CObjectClassesHandler.h"
|
||||
#include "BattleFieldHandler.h"
|
||||
|
||||
CHero::CHero() = default;
|
||||
CHero::~CHero() = default;
|
||||
@ -179,8 +180,10 @@ std::vector<BattleHex> CObstacleInfo::getBlocked(BattleHex hex) const
|
||||
|
||||
bool CObstacleInfo::isAppropriate(const Terrain & terrainType, const BattleField & battlefield) const
|
||||
{
|
||||
if(battlefield.isSpecial())
|
||||
return vstd::contains(allowedSpecialBfields, battlefield);
|
||||
auto bgInfo = battlefield.getInfo();
|
||||
|
||||
if(bgInfo->isSpecial)
|
||||
return vstd::contains(allowedSpecialBfields, bgInfo->identifier);
|
||||
|
||||
return vstd::contains(allowedTerrains, terrainType);
|
||||
}
|
||||
|
@ -227,7 +227,7 @@ struct DLL_LINKAGE CObstacleInfo
|
||||
{
|
||||
std::string defName;
|
||||
std::vector<Terrain> allowedTerrains;
|
||||
std::vector<BattleField> allowedSpecialBfields;
|
||||
std::vector<std::string> allowedSpecialBfields;
|
||||
|
||||
ui8 isAbsoluteObstacle; //there may only one such obstacle in battle and its position is always the same
|
||||
si32 width, height; //how much space to the right and up is needed to place obstacle (affects only placement algorithm)
|
||||
|
@ -129,7 +129,8 @@ set(lib_SRCS
|
||||
spells/effects/Sacrifice.cpp
|
||||
|
||||
vstd/StringUtils.cpp
|
||||
|
||||
|
||||
BattleFieldHandler.cpp
|
||||
CAndroidVMHelper.cpp
|
||||
CArtHandler.cpp
|
||||
CBonusTypeHandler.cpp
|
||||
@ -338,6 +339,7 @@ set(lib_HEADERS
|
||||
spells/effects/Sacrifice.h
|
||||
|
||||
AI_Base.h
|
||||
BattleFieldHandler.h
|
||||
CAndroidVMHelper.h
|
||||
CArtHandler.h
|
||||
CBonusTypeHandler.h
|
||||
|
@ -25,6 +25,7 @@
|
||||
#include "spells/CSpellHandler.h"
|
||||
#include "CSkillHandler.h"
|
||||
#include "ScriptHandler.h"
|
||||
#include "BattleFieldHandler.h"
|
||||
|
||||
#include <vstd/StringUtils.h>
|
||||
|
||||
@ -433,6 +434,7 @@ void CContentHandler::init()
|
||||
handlers.insert(std::make_pair("skills", ContentTypeHandler(VLC->skillh, "skill")));
|
||||
handlers.insert(std::make_pair("templates", ContentTypeHandler((IHandlerBase *)VLC->tplh, "template")));
|
||||
handlers.insert(std::make_pair("scripts", ContentTypeHandler(VLC->scriptHandler, "script")));
|
||||
handlers.insert(std::make_pair("battlefields", ContentTypeHandler(VLC->battlefieldsHandler, "battlefield")));
|
||||
//TODO: any other types of moddables?
|
||||
}
|
||||
|
||||
|
@ -34,6 +34,7 @@
|
||||
#include "StringConstants.h"
|
||||
#include "CGeneralTextHandler.h"
|
||||
#include "CModHandler.h"//todo: remove
|
||||
#include "BattleFieldHandler.h"
|
||||
|
||||
const SlotID SlotID::COMMANDER_SLOT_PLACEHOLDER = SlotID(-2);
|
||||
const SlotID SlotID::SUMMONED_SLOT_PLACEHOLDER = SlotID(-3);
|
||||
@ -255,3 +256,40 @@ std::ostream & operator<<(std::ostream & os, const EPathfindingLayer pathfinding
|
||||
if (it == pathfinderLayerToString.end()) return os << "<Unknown type>";
|
||||
else return os << it->second;
|
||||
}
|
||||
|
||||
const BattleField BattleField::NONE;
|
||||
|
||||
bool operator==(const BattleField & l, const BattleField & r)
|
||||
{
|
||||
return l.num == r.num;
|
||||
}
|
||||
|
||||
bool operator!=(const BattleField & l, const BattleField & r)
|
||||
{
|
||||
return l.num != r.num;
|
||||
}
|
||||
|
||||
bool operator<(const BattleField & l, const BattleField & r)
|
||||
{
|
||||
return l.num < r.num;
|
||||
}
|
||||
|
||||
BattleField::operator std::string() const
|
||||
{
|
||||
return getInfo()->identifier;
|
||||
}
|
||||
|
||||
const BattleFieldInfo * BattleField::getInfo() const
|
||||
{
|
||||
return VLC->battlefields()->getById(*this);
|
||||
}
|
||||
|
||||
BattleField BattleField::fromString(std::string identifier)
|
||||
{
|
||||
auto rawId = VLC->modh->identifiers.getIdentifier("core", "battlefield", identifier);
|
||||
|
||||
if(rawId)
|
||||
return BattleField(rawId.get());
|
||||
else
|
||||
return BattleField::NONE;
|
||||
}
|
@ -1109,6 +1109,23 @@ public:
|
||||
|
||||
ID_LIKE_OPERATORS(SpellID, SpellID::ESpellID)
|
||||
|
||||
class BattleFieldInfo;
|
||||
class BattleField : public BaseForID<BattleField, si32>
|
||||
{
|
||||
INSTID_LIKE_CLASS_COMMON(BattleField, si32)
|
||||
|
||||
DLL_LINKAGE static const BattleField NONE;
|
||||
|
||||
DLL_LINKAGE friend bool operator==(const BattleField & l, const BattleField & r);
|
||||
DLL_LINKAGE friend bool operator!=(const BattleField & l, const BattleField & r);
|
||||
DLL_LINKAGE friend bool operator<(const BattleField & l, const BattleField & r);
|
||||
|
||||
DLL_LINKAGE operator std::string() const;
|
||||
DLL_LINKAGE const BattleFieldInfo * getInfo() const;
|
||||
|
||||
DLL_LINKAGE static BattleField fromString(std::string identifier);
|
||||
};
|
||||
|
||||
enum class ESpellSchool: ui8
|
||||
{
|
||||
AIR = 0,
|
||||
|
@ -16,6 +16,7 @@
|
||||
#include "NetPacks.h"
|
||||
#include "CBonusTypeHandler.h"
|
||||
#include "CModHandler.h"
|
||||
#include "BattleFieldHandler.h"
|
||||
|
||||
#include "serializer/CSerializer.h" // for SAVEGAME_MAGIC
|
||||
#include "serializer/BinaryDeserializer.h"
|
||||
|
@ -18,8 +18,6 @@
|
||||
|
||||
const Terrain Terrain::ANY("ANY");
|
||||
|
||||
const BattleField BattleField::NONE("");
|
||||
|
||||
Terrain Terrain::createTerrainTypeH3M(int tId)
|
||||
{
|
||||
static std::array<std::string, 10> terrainsH3M
|
||||
@ -227,27 +225,3 @@ bool Terrain::isTransitionRequired() const
|
||||
{
|
||||
return Terrain::Manager::getInfo(*this).transitionRequired;
|
||||
}
|
||||
|
||||
bool operator==(const BattleField & l, const BattleField & r)
|
||||
{
|
||||
return l.name == r.name;
|
||||
}
|
||||
|
||||
bool operator!=(const BattleField & l, const BattleField & r)
|
||||
{
|
||||
return l.name != r.name;
|
||||
}
|
||||
|
||||
bool operator<(const BattleField & l, const BattleField & r)
|
||||
{
|
||||
return l.name < r.name;
|
||||
}
|
||||
BattleField::operator std::string() const
|
||||
{
|
||||
return name;
|
||||
}
|
||||
|
||||
int BattleField::hash() const
|
||||
{
|
||||
return std::hash<std::string>{}(name);
|
||||
}
|
||||
|
@ -11,47 +11,9 @@
|
||||
#pragma once
|
||||
|
||||
#include "ConstTransitivePtr.h"
|
||||
#include "GameConstants.h"
|
||||
#include "JsonNode.h"
|
||||
|
||||
class DLL_LINKAGE BattleField
|
||||
{
|
||||
public:
|
||||
// 1. sand/shore 2. sand/mesas 3. dirt/birches 4. dirt/hills 5. dirt/pines 6. grass/hills 7. grass/pines
|
||||
//8. lava 9. magic plains 10. snow/mountains 11. snow/trees 12. subterranean 13. swamp/trees 14. fiery fields
|
||||
//15. rock lands 16. magic clouds 17. lucid pools 18. holy ground 19. clover field 20. evil fog
|
||||
//21. "favorable winds" text on magic plains background 22. cursed ground 23. rough 24. ship to ship 25. ship
|
||||
/*enum EBFieldType {NONE = -1, NONE2, SAND_SHORE, SAND_MESAS, DIRT_BIRCHES, DIRT_HILLS, DIRT_PINES, GRASS_HILLS,
|
||||
GRASS_PINES, LAVA, MAGIC_PLAINS, SNOW_MOUNTAINS, SNOW_TREES, SUBTERRANEAN, SWAMP_TREES, FIERY_FIELDS,
|
||||
ROCKLANDS, MAGIC_CLOUDS, LUCID_POOLS, HOLY_GROUND, CLOVER_FIELD, EVIL_FOG, FAVORABLE_WINDS, CURSED_GROUND,
|
||||
ROUGH, SHIP_TO_SHIP, SHIP
|
||||
};*/
|
||||
|
||||
BattleField(const std::string & type = "") : name(type)
|
||||
{}
|
||||
|
||||
static const BattleField NONE;
|
||||
|
||||
DLL_LINKAGE friend bool operator==(const BattleField & l, const BattleField & r);
|
||||
DLL_LINKAGE friend bool operator!=(const BattleField & l, const BattleField & r);
|
||||
DLL_LINKAGE friend bool operator<(const BattleField & l, const BattleField & r);
|
||||
|
||||
operator std::string() const;
|
||||
int hash() const;
|
||||
|
||||
template <typename Handler> void serialize(Handler &h, const int version)
|
||||
{
|
||||
h & name;
|
||||
}
|
||||
|
||||
bool isSpecial() const
|
||||
{
|
||||
return name.find('_') >= 0; // hack for special battlefields, move to JSON
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
std::string name;
|
||||
};
|
||||
|
||||
class DLL_LINKAGE Terrain
|
||||
{
|
||||
@ -77,7 +39,7 @@ public:
|
||||
std::string terrainViewPatterns;
|
||||
int horseSoundId;
|
||||
Type type;
|
||||
std::vector<BattleField> battleFields;
|
||||
std::vector<std::string> battleFields;
|
||||
};
|
||||
|
||||
class DLL_LINKAGE Manager
|
||||
|
@ -32,6 +32,7 @@
|
||||
#include "rmg/CRmgTemplateStorage.h"
|
||||
#include "mapping/CMapEditManager.h"
|
||||
#include "ScriptHandler.h"
|
||||
#include "BattleFieldHandler.h"
|
||||
|
||||
LibClasses * VLC = nullptr;
|
||||
|
||||
@ -110,6 +111,11 @@ spells::effects::Registry * LibClasses::spellEffects()
|
||||
return spells::effects::GlobalRegistry::get();
|
||||
}
|
||||
|
||||
const BattleFieldService * LibClasses::battlefields() const
|
||||
{
|
||||
return battlefieldsHandler;
|
||||
}
|
||||
|
||||
void LibClasses::updateEntity(Metatype metatype, int32_t index, const JsonNode & data)
|
||||
{
|
||||
switch(metatype)
|
||||
@ -205,6 +211,8 @@ void LibClasses::init(bool onlyEssential)
|
||||
|
||||
createHandler(scriptHandler, "Script", pomtime);
|
||||
|
||||
createHandler(battlefieldsHandler, "Battlefields", pomtime);
|
||||
|
||||
logGlobal->info("\tInitializing handlers: %d ms", totalTime.getDiff());
|
||||
|
||||
modh->load();
|
||||
@ -231,6 +239,7 @@ void LibClasses::clear()
|
||||
delete tplh;
|
||||
delete terviewh;
|
||||
delete scriptHandler;
|
||||
delete battlefieldsHandler;
|
||||
makeNull();
|
||||
}
|
||||
|
||||
@ -250,6 +259,7 @@ void LibClasses::makeNull()
|
||||
tplh = nullptr;
|
||||
terviewh = nullptr;
|
||||
scriptHandler = nullptr;
|
||||
battlefieldsHandler = nullptr;
|
||||
}
|
||||
|
||||
LibClasses::LibClasses()
|
||||
|
@ -24,6 +24,7 @@ class CTownHandler;
|
||||
class CGeneralTextHandler;
|
||||
class CModHandler;
|
||||
class CContentHandler;
|
||||
class BattleFieldHandler;
|
||||
class IBonusTypeHandler;
|
||||
class CBonusTypeHandler;
|
||||
class CTerrainViewPatternConfig;
|
||||
@ -56,6 +57,7 @@ public:
|
||||
const scripting::Service * scripts() const override;
|
||||
const spells::Service * spells() const override;
|
||||
const SkillService * skills() const override;
|
||||
const BattleFieldService * battlefields() const override;
|
||||
|
||||
void updateEntity(Metatype metatype, int32_t index, const JsonNode & data) override;
|
||||
|
||||
@ -76,6 +78,7 @@ public:
|
||||
CModHandler * modh;
|
||||
CTerrainViewPatternConfig * terviewh;
|
||||
CRmgTemplateStorage * tplh;
|
||||
BattleFieldHandler * battlefieldsHandler;
|
||||
scripting::ScriptHandler * scriptHandler;
|
||||
|
||||
LibClasses(); //c-tor, loads .lods and NULLs handlers
|
||||
@ -104,6 +107,8 @@ public:
|
||||
h & objtypeh;
|
||||
h & spellh;
|
||||
h & skillh;
|
||||
h & battlefieldsHandler;
|
||||
|
||||
if(!h.saving)
|
||||
{
|
||||
//modh will be changed and modh->content will be empty after deserialization
|
||||
|
@ -16,6 +16,7 @@
|
||||
#include "../mapObjects/CGTownInstance.h"
|
||||
#include "../CGeneralTextHandler.h"
|
||||
#include "../Terrain.h"
|
||||
#include "../BattleFieldHandler.h"
|
||||
|
||||
//TODO: remove
|
||||
#include "../IGameCallback.h"
|
||||
@ -458,64 +459,12 @@ BattleInfo * BattleInfo::setupBattle(const int3 & tile, const Terrain & terrain,
|
||||
auto good = std::make_shared<CreatureAlignmentLimiter>(EAlignment::GOOD);
|
||||
auto evil = std::make_shared<CreatureAlignmentLimiter>(EAlignment::EVIL);
|
||||
|
||||
//giving terrain overlay premies
|
||||
int bonusSubtype = -1;
|
||||
auto bgInfo = VLC->battlefields()->getById(battlefieldType);
|
||||
|
||||
if(battlefieldType == BattleField("magic_plains"))
|
||||
for(const std::shared_ptr<Bonus> & bonus : bgInfo->bonuses)
|
||||
{
|
||||
bonusSubtype = 0;
|
||||
curB->addNewBonus(bonus);
|
||||
}
|
||||
if(battlefieldType == BattleField("fiery_fields"))
|
||||
{
|
||||
if(bonusSubtype == -1) bonusSubtype = 2;
|
||||
}
|
||||
if(battlefieldType == BattleField("rocklands"))
|
||||
{
|
||||
if(bonusSubtype == -1) bonusSubtype = 8;
|
||||
}
|
||||
if(battlefieldType == BattleField("magic_clouds"))
|
||||
{
|
||||
if(bonusSubtype == -1) bonusSubtype = 1;
|
||||
}
|
||||
if(battlefieldType == BattleField("lucid_pools"))
|
||||
{
|
||||
if(bonusSubtype == -1) bonusSubtype = 4;
|
||||
}
|
||||
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));
|
||||
}
|
||||
else if(battlefieldType == BattleField("holy_ground"))
|
||||
{
|
||||
std::string goodArmyDesc = VLC->generaltexth->arraytxt[123];
|
||||
goodArmyDesc.erase(goodArmyDesc.size() - 2, 2); //omitting hardcoded +1 in description
|
||||
std::string evilArmyDesc = VLC->generaltexth->arraytxt[124];
|
||||
evilArmyDesc.erase(evilArmyDesc.size() - 2, 2);
|
||||
curB->addNewBonus(std::make_shared<Bonus>(Bonus::ONE_BATTLE, Bonus::MORALE, Bonus::TERRAIN_OVERLAY, +1, battlefieldType.hash(), goodArmyDesc, 0)->addLimiter(good));
|
||||
curB->addNewBonus(std::make_shared<Bonus>(Bonus::ONE_BATTLE, Bonus::MORALE, Bonus::TERRAIN_OVERLAY, -1, battlefieldType.hash(), evilArmyDesc, 0)->addLimiter(evil));
|
||||
}
|
||||
else if(battlefieldType == BattleField("clover_field"))
|
||||
{ //+2 luck bonus for neutral creatures
|
||||
std::string desc = VLC->generaltexth->arraytxt[83];
|
||||
desc.erase(desc.size() - 2, 2);
|
||||
curB->addNewBonus(std::make_shared<Bonus>(Bonus::ONE_BATTLE, Bonus::LUCK, Bonus::TERRAIN_OVERLAY, +2, battlefieldType.hash(), desc, 0)->addLimiter(neutral));
|
||||
}
|
||||
else if(battlefieldType == BattleField("evil_fog"))
|
||||
{
|
||||
std::string goodArmyDesc = VLC->generaltexth->arraytxt[126];
|
||||
goodArmyDesc.erase(goodArmyDesc.size() - 2, 2);
|
||||
std::string evilArmyDesc = VLC->generaltexth->arraytxt[125];
|
||||
evilArmyDesc.erase(evilArmyDesc.size() - 2, 2);
|
||||
curB->addNewBonus(std::make_shared<Bonus>(Bonus::ONE_BATTLE, Bonus::MORALE, Bonus::TERRAIN_OVERLAY, -1, battlefieldType.hash(), goodArmyDesc, 0)->addLimiter(good));
|
||||
curB->addNewBonus(std::make_shared<Bonus>(Bonus::ONE_BATTLE, Bonus::MORALE, Bonus::TERRAIN_OVERLAY, +1, battlefieldType.hash(), evilArmyDesc, 0)->addLimiter(evil));
|
||||
}
|
||||
else if(battlefieldType == BattleField("cursed_ground"))
|
||||
{
|
||||
curB->addNewBonus(std::make_shared<Bonus>(Bonus::ONE_BATTLE, Bonus::NO_MORALE, Bonus::TERRAIN_OVERLAY, 0, battlefieldType.hash(), VLC->generaltexth->arraytxt[112], 0));
|
||||
curB->addNewBonus(std::make_shared<Bonus>(Bonus::ONE_BATTLE, Bonus::NO_LUCK, Bonus::TERRAIN_OVERLAY, 0, battlefieldType.hash(), VLC->generaltexth->arraytxt[81], 0));
|
||||
curB->addNewBonus(std::make_shared<Bonus>(Bonus::ONE_BATTLE, Bonus::BLOCK_MAGIC_ABOVE, Bonus::TERRAIN_OVERLAY, 1, battlefieldType.hash(), 0, Bonus::INDEPENDENT_MIN));
|
||||
}
|
||||
//overlay premies given
|
||||
|
||||
//native terrain bonuses
|
||||
static auto nativeTerrain = std::make_shared<CreatureTerrainLimiter>();
|
||||
|
@ -17,6 +17,7 @@
|
||||
#include "../NetPacks.h"
|
||||
#include "../spells/CSpellHandler.h"
|
||||
#include "../mapObjects/CGTownInstance.h"
|
||||
#include "../BattleFieldHandler.h"
|
||||
|
||||
namespace SiegeStuffThatShouldBeMovedToHandlers // <=== TODO
|
||||
{
|
||||
@ -1058,24 +1059,15 @@ AccessibilityInfo CBattleInfoCallback::getAccesibility() const
|
||||
}
|
||||
|
||||
//special battlefields with logically unavailable tiles
|
||||
std::vector<BattleHex> impassableHexes;
|
||||
if(battleGetBattlefieldType() == BattleField("ship_to_ship"))
|
||||
auto bFieldType = battleGetBattlefieldType();
|
||||
|
||||
if(bFieldType != BattleField::NONE)
|
||||
{
|
||||
impassableHexes =
|
||||
{
|
||||
6, 7, 8, 9,
|
||||
24, 25, 26,
|
||||
58, 59, 60,
|
||||
75, 76, 77,
|
||||
92, 93, 94,
|
||||
109, 110, 111,
|
||||
126, 127, 128,
|
||||
159, 160, 161, 162, 163,
|
||||
176, 177, 178, 179, 180
|
||||
};
|
||||
std::vector<BattleHex> impassableHexes = bFieldType.getInfo()->impassableHexes;
|
||||
|
||||
for(auto hex : impassableHexes)
|
||||
ret[hex] = EAccessibility::UNAVAILABLE;
|
||||
}
|
||||
for(auto hex : impassableHexes)
|
||||
ret[hex] = EAccessibility::UNAVAILABLE;
|
||||
|
||||
//gate -> should be before stacks
|
||||
if(battleGetSiegeLevel() > 0)
|
||||
|
@ -515,10 +515,10 @@ 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;
|
||||
if(input["battleground"].getType() == JsonNode::JsonType::DATA_STRING)
|
||||
battlefield = input["battleground"].String();
|
||||
else
|
||||
battlefield = BattleField(input["battleground"].String());
|
||||
battlefield = boost::none;
|
||||
|
||||
initTypeData(input);
|
||||
}
|
||||
@ -577,7 +577,7 @@ std::vector<ObjectTemplate> AObjectTypeHandler::getTemplates() const
|
||||
|
||||
BattleField AObjectTypeHandler::getBattlefield() const
|
||||
{
|
||||
return battlefield;
|
||||
return battlefield ? BattleField::fromString(battlefield.get()) : BattleField::NONE;
|
||||
}
|
||||
|
||||
std::vector<ObjectTemplate> AObjectTypeHandler::getTemplates(const Terrain & terrainType) const
|
||||
|
@ -150,7 +150,7 @@ class DLL_LINKAGE AObjectTypeHandler : public boost::noncopyable
|
||||
|
||||
boost::optional<si32> aiValue;
|
||||
|
||||
BattleField battlefield;
|
||||
boost::optional<std::string> battlefield;
|
||||
|
||||
protected:
|
||||
void preInitObject(CGObjectInstance * obj) const;
|
||||
@ -219,6 +219,7 @@ public:
|
||||
h & subTypeName;
|
||||
h & sounds;
|
||||
h & aiValue;
|
||||
h & battlefield;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -461,12 +461,15 @@ const std::vector<CTerrainViewPatternConfig::TVPVector> & CTerrainViewPatternCon
|
||||
return iter->second;
|
||||
}
|
||||
|
||||
boost::optional<const TerrainViewPattern &> CTerrainViewPatternConfig::getTerrainViewPatternById(const Terrain & terrain, const std::string & id) const
|
||||
boost::optional<const TerrainViewPattern &> CTerrainViewPatternConfig::getTerrainViewPatternById(std::string patternId, const std::string & id) const
|
||||
{
|
||||
const std::vector<TVPVector> & groupPatterns = getTerrainViewPatterns(terrain);
|
||||
auto iter = terrainViewPatterns.find(patternId);
|
||||
const std::vector<TVPVector> & groupPatterns = (iter == terrainViewPatterns.end()) ? terrainViewPatterns.at("normal") : iter->second;
|
||||
|
||||
for (const TVPVector & patternFlips : groupPatterns)
|
||||
{
|
||||
const TerrainViewPattern & pattern = patternFlips.front();
|
||||
|
||||
if(id == pattern.id)
|
||||
{
|
||||
return boost::optional<const TerrainViewPattern &>(pattern);
|
||||
|
@ -327,7 +327,7 @@ public:
|
||||
~CTerrainViewPatternConfig();
|
||||
|
||||
const std::vector<TVPVector> & getTerrainViewPatterns(const Terrain & terrain) const;
|
||||
boost::optional<const TerrainViewPattern &> getTerrainViewPatternById(const Terrain & terrain, const std::string & id) const;
|
||||
boost::optional<const TerrainViewPattern &> getTerrainViewPatternById(std::string patternId, const std::string & id) const;
|
||||
boost::optional<const TVPVector &> getTerrainViewPatternsById(const Terrain & terrain, const std::string & id) const;
|
||||
const TVPVector * getTerrainTypePatternById(const std::string & id) const;
|
||||
void flipPattern(TerrainViewPattern & pattern, int flip) const;
|
||||
|
@ -55,6 +55,7 @@ void registerTypesMapObjects1(Serializer &s)
|
||||
s.template registerType<CGObjectInstance, CGShipyard>(); s.template registerType<IShipyard, CGShipyard>();
|
||||
s.template registerType<CGObjectInstance, CGDenOfthieves>();
|
||||
s.template registerType<CGObjectInstance, CGLighthouse>();
|
||||
s.template registerType<CGObjectInstance, CGTerrainPatch>();
|
||||
s.template registerType<CGObjectInstance, CGMarket>(); s.template registerType<IMarket, CGMarket>();
|
||||
s.template registerType<CGMarket, CGBlackMarket>();
|
||||
s.template registerType<CGMarket, CGUniversity>();
|
||||
@ -108,6 +109,7 @@ void registerTypesMapObjectTypes(Serializer &s)
|
||||
REGISTER_GENERIC_HANDLER(CGHeroInstance);
|
||||
REGISTER_GENERIC_HANDLER(CGKeymasterTent);
|
||||
REGISTER_GENERIC_HANDLER(CGLighthouse);
|
||||
REGISTER_GENERIC_HANDLER(CGTerrainPatch);
|
||||
REGISTER_GENERIC_HANDLER(CGMagi);
|
||||
REGISTER_GENERIC_HANDLER(CGMagicSpring);
|
||||
REGISTER_GENERIC_HANDLER(CGMagicWell);
|
||||
|
@ -246,8 +246,18 @@ void CMapGenOptions::finalize(CRandomGenerator & rand)
|
||||
|
||||
if(waterContent == EWaterContent::RANDOM)
|
||||
{
|
||||
waterContent = *RandomGeneratorUtil::nextItem(mapTemplate->getWaterContentAllowed(), rand);
|
||||
auto allowedContent = mapTemplate->getWaterContentAllowed();
|
||||
|
||||
if(allowedContent.size())
|
||||
{
|
||||
waterContent = *RandomGeneratorUtil::nextItem(mapTemplate->getWaterContentAllowed(), rand);
|
||||
}
|
||||
else
|
||||
{
|
||||
waterContent = EWaterContent::NONE;
|
||||
}
|
||||
}
|
||||
|
||||
if(monsterStrength == EMonsterStrength::RANDOM)
|
||||
{
|
||||
monsterStrength = static_cast<EMonsterStrength::EMonsterStrength>(rand.nextInt(EMonsterStrength::GLOBAL_WEAK, EMonsterStrength::GLOBAL_STRONG));
|
||||
|
@ -2019,6 +2019,10 @@ int3 CRmgTemplateZone::makeBoat(TRmgTemplateZoneId land, const std::set<int3> &
|
||||
{
|
||||
std::set<int3> lakeCoast;
|
||||
std::set_intersection(gen->getZones()[land]->getCoastTiles().begin(), gen->getZones()[land]->getCoastTiles().end(), lake.begin(), lake.end(), std::inserter(lakeCoast, lakeCoast.begin()));
|
||||
|
||||
if(lakeCoast.empty())
|
||||
return int3(-1, -1, -1);
|
||||
|
||||
for(int randomAttempts = 0; randomAttempts<5; ++randomAttempts)
|
||||
{
|
||||
auto coastTile = *RandomGeneratorUtil::nextItem(lakeCoast, gen->rand);
|
||||
|
@ -12,6 +12,7 @@
|
||||
#include "ISpellMechanics.h"
|
||||
|
||||
#include "../CRandomGenerator.h"
|
||||
#include "../VCMI_Lib.h"
|
||||
|
||||
#include "../HeroBonus.h"
|
||||
#include "../battle/CBattleInfoCallback.h"
|
||||
@ -39,6 +40,7 @@
|
||||
|
||||
#include "../CHeroHandler.h"//todo: remove
|
||||
#include "../IGameCallback.h"//todo: remove
|
||||
#include "../BattleFieldHandler.h"
|
||||
|
||||
namespace spells
|
||||
{
|
||||
@ -520,7 +522,7 @@ bool BaseMechanics::adaptProblem(ESpellCastProblem::ESpellCastProblem source, Pr
|
||||
caster->getCasterName(text);
|
||||
target.add(std::move(text), spells::Problem::NORMAL);
|
||||
}
|
||||
else if(b && b->source == Bonus::TERRAIN_OVERLAY && b->sid == BattleField("cursed_ground").hash())
|
||||
else if(b && b->source == Bonus::TERRAIN_OVERLAY && VLC->battlefields()->getByIndex(b->sid)->identifier == "cursed_ground")
|
||||
{
|
||||
text.addTxt(MetaString::GENERAL_TXT, 537);
|
||||
target.add(std::move(text), spells::Problem::NORMAL);
|
||||
|
@ -10,12 +10,14 @@
|
||||
#include "StdInc.h"
|
||||
|
||||
#include "BattleCb.h"
|
||||
#include <vcmi/Entity.h>
|
||||
|
||||
#include "../LuaStack.h"
|
||||
#include "../LuaCallWrapper.h"
|
||||
|
||||
#include "../../../lib/GameConstants.h"
|
||||
#include "../../../lib/battle/Unit.h"
|
||||
#include "../../../lib/BattleFieldHandler.h"
|
||||
|
||||
namespace scripting
|
||||
{
|
||||
@ -73,7 +75,7 @@ int BattleCbProxy::getBattlefieldType(lua_State * L)
|
||||
|
||||
auto ret = object->battleGetBattlefieldType();
|
||||
|
||||
return LuaStack::quickRetStr(L, ret);
|
||||
return LuaStack::quickRetStr(L, ret.getInfo()->identifier);
|
||||
}
|
||||
|
||||
int BattleCbProxy::getTerrainType(lua_State * L)
|
||||
|
@ -55,16 +55,16 @@ end
|
||||
|
||||
local SPECIAL_FIELDS = {}
|
||||
|
||||
SPECIAL_FIELDS[0] = 0
|
||||
SPECIAL_FIELDS[22] = 1
|
||||
SPECIAL_FIELDS[9] = 2
|
||||
SPECIAL_FIELDS[18] = 3
|
||||
SPECIAL_FIELDS[20] = 4
|
||||
SPECIAL_FIELDS[19] = 5
|
||||
SPECIAL_FIELDS[17] = 6
|
||||
SPECIAL_FIELDS[14] = 7
|
||||
SPECIAL_FIELDS[15] = 8
|
||||
SPECIAL_FIELDS[16] = 9
|
||||
SPECIAL_FIELDS['sand_shore'] = 0
|
||||
SPECIAL_FIELDS['cursed_ground'] = 1
|
||||
SPECIAL_FIELDS['magic_plains'] = 2
|
||||
SPECIAL_FIELDS['holy_ground'] = 3
|
||||
SPECIAL_FIELDS['evil_fog'] = 4
|
||||
SPECIAL_FIELDS['clover_field'] = 5
|
||||
SPECIAL_FIELDS['lucid_pools'] = 6
|
||||
SPECIAL_FIELDS['fiery_fields'] = 7
|
||||
SPECIAL_FIELDS['rocklands'] = 8
|
||||
SPECIAL_FIELDS['magic_clouds'] = 9
|
||||
|
||||
|
||||
function BU:G(x, p1)
|
||||
|
@ -2221,7 +2221,7 @@ void CGameHandler::setupBattle(int3 tile, const CArmedInstance *armies[2], const
|
||||
|
||||
BattleField terType = gs->battleGetBattlefieldType(tile, getRandomGenerator());
|
||||
if (heroes[0] && heroes[0]->boat && heroes[1] && heroes[1]->boat)
|
||||
terType = BattleField("ship_to_ship");
|
||||
terType = BattleField::fromString("ship_to_ship");
|
||||
|
||||
//send info about battles
|
||||
BattleStart bs;
|
||||
|
@ -10,6 +10,7 @@
|
||||
#include "StdInc.h"
|
||||
|
||||
#include "../../lib/battle/CBattleInfoCallback.h"
|
||||
#include "../../lib/battle/CUnitState.h"
|
||||
|
||||
#include <vstd/RNG.h>
|
||||
|
||||
@ -25,7 +26,15 @@ using namespace testing;
|
||||
|
||||
class UnitFake : public UnitMock
|
||||
{
|
||||
private:
|
||||
std::shared_ptr<CUnitState> state;
|
||||
|
||||
public:
|
||||
UnitFake()
|
||||
{
|
||||
state.reset(new CUnitStateDetached(this, this));
|
||||
}
|
||||
|
||||
void addNewBonus(const std::shared_ptr<Bonus> & b)
|
||||
{
|
||||
bonusFake.addNewBonus(b);
|
||||
@ -58,6 +67,13 @@ public:
|
||||
EXPECT_CALL(*this, unitSlot()).WillRepeatedly(Return(SlotID(0)));
|
||||
EXPECT_CALL(*this, creatureIndex()).WillRepeatedly(Return(0));
|
||||
}
|
||||
|
||||
void setDefaultState()
|
||||
{
|
||||
EXPECT_CALL(*this, isClone()).WillRepeatedly(Return(false));
|
||||
EXPECT_CALL(*this, isCaster()).WillRepeatedly(Return(false));
|
||||
EXPECT_CALL(*this, acquireState()).WillRepeatedly(Return(state));
|
||||
}
|
||||
private:
|
||||
BonusBearerMock bonusFake;
|
||||
};
|
||||
@ -207,6 +223,7 @@ TEST_F(BattleFinishedTest, LastAliveUnitWins)
|
||||
{
|
||||
UnitFake & unit = unitsFake.add(1);
|
||||
unit.makeAlive();
|
||||
unit.setDefaultState();
|
||||
|
||||
setDefaultExpectations();
|
||||
startBattle();
|
||||
@ -232,6 +249,7 @@ TEST_F(BattleFinishedTest, LastWarMachineNotWins)
|
||||
UnitFake & unit = unitsFake.add(0);
|
||||
unit.makeAlive();
|
||||
unit.makeWarMachine();
|
||||
unit.setDefaultState();
|
||||
|
||||
setDefaultExpectations();
|
||||
startBattle();
|
||||
@ -241,17 +259,26 @@ TEST_F(BattleFinishedTest, LastWarMachineNotWins)
|
||||
|
||||
TEST_F(BattleFinishedTest, LastWarMachineLoose)
|
||||
{
|
||||
UnitFake & unit1 = unitsFake.add(0);
|
||||
unit1.makeAlive();
|
||||
try
|
||||
{
|
||||
UnitFake & unit1 = unitsFake.add(0);
|
||||
unit1.makeAlive();
|
||||
unit1.setDefaultState();
|
||||
|
||||
UnitFake & unit2 = unitsFake.add(1);
|
||||
unit2.makeAlive();
|
||||
unit2.makeWarMachine();
|
||||
UnitFake & unit2 = unitsFake.add(1);
|
||||
unit2.makeAlive();
|
||||
unit2.makeWarMachine();
|
||||
unit2.setDefaultState();
|
||||
|
||||
setDefaultExpectations();
|
||||
startBattle();
|
||||
setDefaultExpectations();
|
||||
startBattle();
|
||||
|
||||
expectBattleWinner(0);
|
||||
expectBattleWinner(0);
|
||||
}
|
||||
catch(std::exception e)
|
||||
{
|
||||
logGlobal->error(e.what());
|
||||
}
|
||||
}
|
||||
|
||||
class BattleMatchOwnerTest : public CBattleInfoCallbackTest
|
||||
|
@ -155,7 +155,7 @@ TEST_F(ERM_BU_G, Get)
|
||||
source << "!?PI;" << std::endl;
|
||||
source << "!!BU:G?v1;" << std::endl;
|
||||
|
||||
EXPECT_CALL(binfoMock, battleGetBattlefieldType()).WillOnce(Return(BattleField("snow_trees")));
|
||||
EXPECT_CALL(binfoMock, battleGetBattlefieldType()).WillOnce(Return(BattleField::fromString("snow_trees")));
|
||||
|
||||
|
||||
loadScript(VLC->scriptHandler->erm, source.str());
|
||||
@ -169,12 +169,14 @@ TEST_F(ERM_BU_G, Get)
|
||||
|
||||
TEST_F(ERM_BU_G, Get2)
|
||||
{
|
||||
const int EXPECTED_ERM_FOG_CODE = 4;
|
||||
|
||||
std::stringstream source;
|
||||
source << "VERM" << std::endl;
|
||||
source << "!?PI;" << std::endl;
|
||||
source << "!!BU:G?v1;" << std::endl;
|
||||
|
||||
EXPECT_CALL(binfoMock, battleGetBattlefieldType()).WillOnce(Return(BattleField("evil_fog")));
|
||||
EXPECT_CALL(binfoMock, battleGetBattlefieldType()).WillOnce(Return(BattleField::fromString("evil_fog")));
|
||||
|
||||
loadScript(VLC->scriptHandler->erm, source.str());
|
||||
runServer();
|
||||
@ -182,7 +184,7 @@ TEST_F(ERM_BU_G, Get2)
|
||||
JsonNode actualState = context->saveState();
|
||||
|
||||
|
||||
EXPECT_EQ(actualState["ERM"]["v"]["1"], JsonUtils::floatNode(4)) << actualState.toJson(true);
|
||||
EXPECT_EQ(actualState["ERM"]["v"]["1"], JsonUtils::floatNode(EXPECTED_ERM_FOG_CODE)) << actualState.toJson(true);
|
||||
}
|
||||
|
||||
//TODO: ERM_BU_G Set
|
||||
|
@ -194,7 +194,7 @@ public:
|
||||
const auto t = gameCallback->getTile(tile);
|
||||
|
||||
Terrain terrain = t->terType;
|
||||
BattleField terType = BattleField("grass_hills");
|
||||
BattleField terType = BattleField::fromString("grass_hills");
|
||||
|
||||
//send info about battles
|
||||
|
||||
|
@ -132,7 +132,7 @@ TEST(MapManager, DrawTerrain_View)
|
||||
const auto & id = patternParts[1];
|
||||
|
||||
// Get mapping range
|
||||
const auto & pattern = VLC->terviewh->getTerrainViewPatternById(groupStr, id);
|
||||
const auto & pattern = VLC->terviewh->getTerrainViewPatternById(groupStr, id);
|
||||
const auto & mapping = (*pattern).mapping;
|
||||
|
||||
const auto & positionsNode = node["pos"].Vector();
|
||||
|
@ -23,6 +23,7 @@
|
||||
|
||||
#include "MapComparer.h"
|
||||
#include "../JsonComparer.h"
|
||||
#include "mock/ZoneOptionsFake.h"
|
||||
|
||||
static const int TEST_RANDOM_SEED = 1337;
|
||||
|
||||
@ -43,10 +44,12 @@ TEST(MapFormat, Random)
|
||||
|
||||
CMapGenOptions opt;
|
||||
CRmgTemplate tmpl;
|
||||
std::shared_ptr<ZoneOptionsFake> zoneOptions = std::make_shared<ZoneOptionsFake>();
|
||||
|
||||
const_cast<CRmgTemplate::CPlayerCountRange &>(tmpl.getCpuPlayers()).addRange(1, 4);
|
||||
const_cast<CRmgTemplate::Zones &>(tmpl.getZones())[0] = std::make_shared<rmg::ZoneOptions>();
|
||||
const_cast<CRmgTemplate::Zones &>(tmpl.getZones())[0] = zoneOptions;
|
||||
|
||||
zoneOptions->setOwner(1);
|
||||
opt.setMapTemplate(&tmpl);
|
||||
|
||||
opt.setHeight(CMapHeader::MAP_SIZE_MIDDLE);
|
||||
|
@ -92,7 +92,7 @@ void BattleFake::setupEmptyBattlefield()
|
||||
{
|
||||
EXPECT_CALL(*this, getDefendedTown()).WillRepeatedly(Return(nullptr));
|
||||
EXPECT_CALL(*this, getAllObstacles()).WillRepeatedly(Return(IBattleInfo::ObstacleCList()));
|
||||
EXPECT_CALL(*this, getBattlefieldType()).WillRepeatedly(Return(BattleField::NONE));
|
||||
EXPECT_CALL(*this, getBattlefieldType()).WillRepeatedly(Return(BattleField::fromString("grass_hills")));
|
||||
}
|
||||
|
||||
|
||||
|
23
test/mock/ZoneOptionsFake.h
Normal file
23
test/mock/ZoneOptionsFake.h
Normal file
@ -0,0 +1,23 @@
|
||||
/*
|
||||
* BattleFake.h, part of VCMI engine
|
||||
*
|
||||
* Authors: listed in file AUTHORS in main folder
|
||||
*
|
||||
* License: GNU General Public License v2.0 or later
|
||||
* Full text of license available in license.txt file, in main folder
|
||||
*
|
||||
*/
|
||||
#include "../../../lib/mapping/CMap.h"
|
||||
#include "../../../lib/rmg/CMapGenOptions.h"
|
||||
#include "../../../lib/rmg/CMapGenerator.h"
|
||||
|
||||
#pragma once
|
||||
|
||||
class ZoneOptionsFake : public rmg::ZoneOptions
|
||||
{
|
||||
public:
|
||||
void setOwner(int ow)
|
||||
{
|
||||
this->owner = ow;
|
||||
}
|
||||
};
|
@ -23,7 +23,8 @@ public:
|
||||
MOCK_CONST_METHOD0(heroTypes, const HeroTypeService *());
|
||||
MOCK_CONST_METHOD0(scripts, const scripting::Service *());
|
||||
MOCK_CONST_METHOD0(spells, const spells::Service *());
|
||||
MOCK_CONST_METHOD0(skills, const SkillService *());
|
||||
MOCK_CONST_METHOD0(skills, const SkillService * ());
|
||||
MOCK_CONST_METHOD0(battlefields, const BattleFieldService *());
|
||||
|
||||
MOCK_METHOD3(updateEntity, void(Metatype, int32_t, const JsonNode &));
|
||||
|
||||
|
@ -232,7 +232,7 @@ TEST_F(CloneApplyTest, SetsLifetimeMarker)
|
||||
{
|
||||
setDefaultExpectations();
|
||||
|
||||
EXPECT_CALL(*battleFake, addUnitBonus(_,_)).WillOnce(Invoke(this, &CloneApplyTest::checkCloneLifetimeMarker));
|
||||
EXPECT_CALL(*battleFake, addUnitBonus(_, _)).WillOnce(Invoke(this, &CloneApplyTest::checkCloneLifetimeMarker));
|
||||
|
||||
subject->apply(&serverMock, &mechanicsMock, target);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user