mirror of
https://github.com/vcmi/vcmi.git
synced 2025-11-27 22:49:25 +02:00
Fixed #1035.
Support for commander artifacts that accumulate bonus after battle.
This commit is contained in:
@@ -542,7 +542,7 @@ void CCreatureWindow::showAll(SDL_Surface * to)
|
|||||||
skillPictures[i]->showAll (to);
|
skillPictures[i]->showAll (to);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (upgradeOptions[selectedOption] >= 100) //add frame to selected skill
|
if (type == COMMANDER_LEVEL_UP && upgradeOptions[selectedOption] >= 100) //add frame to selected skill
|
||||||
{
|
{
|
||||||
int index = selectedOption - selectableSkills.size(); //this is screwed
|
int index = selectedOption - selectableSkills.size(); //this is screwed
|
||||||
CSDL_Ext::drawBorder(to, Rect::around(selectableBonuses[index]->pos), int3(Colors::MetallicGold.r, Colors::MetallicGold.g, Colors::MetallicGold.b));
|
CSDL_Ext::drawBorder(to, Rect::around(selectableBonuses[index]->pos), int3(Colors::MetallicGold.r, Colors::MetallicGold.g, Colors::MetallicGold.b));
|
||||||
|
|||||||
@@ -51,5 +51,86 @@
|
|||||||
{"ability": ["JOUSTING", 0, 0, 0 ], "skills": [3, 4]},
|
{"ability": ["JOUSTING", 0, 0, 0 ], "skills": [3, 4]},
|
||||||
{"ability": ["DEATH_STARE", 1, 1, 0 ], "skills": [3,5]},
|
{"ability": ["DEATH_STARE", 1, 1, 0 ], "skills": [3,5]},
|
||||||
{"ability": ["FLYING", 0, 0, 0 ], "skills": [4,5]}
|
{"ability": ["FLYING", 0, 0, 0 ], "skills": [4,5]}
|
||||||
|
],
|
||||||
|
"artifacts":
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"id": 146, //axe of smashing
|
||||||
|
"bonusesPerLevel":
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"level": 6,
|
||||||
|
"bonus": ["PRIMARY_SKILL", 1, 0, 0]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 147, //mithril mail
|
||||||
|
"bonusesPerLevel":
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"level": 1,
|
||||||
|
"bonus": ["STACK_HEALTH", 1, 0, 0]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 148, //sword of sharpness
|
||||||
|
"bonusesPerLevel":
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"level": 1,
|
||||||
|
"bonus": ["CREATURE_DAMAGE", 1, 0, 0]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 150, //pendant of sorcery
|
||||||
|
"bonusesPerLevel":
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"level": 10,
|
||||||
|
"bonus": ["CREATURE_ENCHANT_POWER", 1, 0, 0]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 151, //boots of haste
|
||||||
|
"bonusesPerLevel":
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"level": 10,
|
||||||
|
"bonus": ["STACKS_SPEED", 1, 0, 0]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 152, //bow of seeking
|
||||||
|
"thresholdBonuses":
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"level": 5,
|
||||||
|
"bonus": ["SHOOTER", 0, 0, 0]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"level": 25,
|
||||||
|
"bonus": ["NO_WALL_PENALTY", 0, 0, 0]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"level": 50,
|
||||||
|
"bonus": ["NO_DISTANCE_PENALTY", 0, 0, 0]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 153, //hardened shield
|
||||||
|
"bonusesPerLevel":
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"level": 6,
|
||||||
|
"bonus": ["PRIMARY_SKILL", 1, 1, 0]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
@@ -8,6 +8,7 @@
|
|||||||
#include "CSpellHandler.h"
|
#include "CSpellHandler.h"
|
||||||
#include "CObjectHandler.h"
|
#include "CObjectHandler.h"
|
||||||
#include "NetPacks.h"
|
#include "NetPacks.h"
|
||||||
|
#include "../lib/JsonNode.h"
|
||||||
|
|
||||||
extern CLodHandler *bitmaph;
|
extern CLodHandler *bitmaph;
|
||||||
using namespace boost::assign;
|
using namespace boost::assign;
|
||||||
@@ -23,6 +24,7 @@ using namespace boost::assign;
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
extern boost::rand48 ran;
|
extern boost::rand48 ran;
|
||||||
|
extern Bonus * ParseBonus (const JsonVector &ability_vec);
|
||||||
|
|
||||||
const std::string & CArtifact::Name() const
|
const std::string & CArtifact::Name() const
|
||||||
{
|
{
|
||||||
@@ -44,11 +46,6 @@ bool CArtifact::isBig () const
|
|||||||
{
|
{
|
||||||
return VLC->arth->isBigArtifact(id);
|
return VLC->arth->isBigArtifact(id);
|
||||||
}
|
}
|
||||||
//
|
|
||||||
// bool CArtifact::isModable () const
|
|
||||||
// {
|
|
||||||
// return (bool)dynamic_cast<const IModableArt *>(this);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// /**
|
// /**
|
||||||
// * Checks whether the artifact fits at a given slot.
|
// * Checks whether the artifact fits at a given slot.
|
||||||
@@ -193,6 +190,30 @@ void CArtifact::setDescription (std::string desc)
|
|||||||
description = desc;
|
description = desc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CGrowingArtifact::levelUpArtifact (CArtifactInstance * art)
|
||||||
|
{
|
||||||
|
Bonus b;
|
||||||
|
b.type = Bonus::LEVEL_COUNTER;
|
||||||
|
b.val = 1;
|
||||||
|
b.duration = Bonus::COMMANDER_KILLED;
|
||||||
|
art->accumulateBonus (b);
|
||||||
|
|
||||||
|
BOOST_FOREACH (auto bonus, bonusesPerLevel)
|
||||||
|
{
|
||||||
|
if (art->valOfBonuses(Bonus::LEVEL_COUNTER) % bonus.first == 0) //every n levels
|
||||||
|
{
|
||||||
|
art->accumulateBonus (bonus.second);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
BOOST_FOREACH (auto bonus, thresholdBonuses)
|
||||||
|
{
|
||||||
|
if (art->valOfBonuses(Bonus::LEVEL_COUNTER) == bonus.first) //every n levels
|
||||||
|
{
|
||||||
|
art->addNewBonus (&bonus.second);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
CArtHandler::CArtHandler()
|
CArtHandler::CArtHandler()
|
||||||
{
|
{
|
||||||
VLC->arth = this;
|
VLC->arth = this;
|
||||||
@@ -215,6 +236,7 @@ void CArtHandler::loadArtifacts(bool onlyTxt)
|
|||||||
{
|
{
|
||||||
std::vector<ui16> slots;
|
std::vector<ui16> slots;
|
||||||
slots += 17, 16, 15, 14, 13, 18, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0;
|
slots += 17, 16, 15, 14, 13, 18, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0;
|
||||||
|
growingArtifacts += 146, 147, 148, 150, 151, 152, 153;
|
||||||
static std::map<char, CArtifact::EartClass> classes =
|
static std::map<char, CArtifact::EartClass> classes =
|
||||||
map_list_of('S',CArtifact::ART_SPECIAL)('T',CArtifact::ART_TREASURE)('N',CArtifact::ART_MINOR)('J',CArtifact::ART_MAJOR)('R',CArtifact::ART_RELIC);
|
map_list_of('S',CArtifact::ART_SPECIAL)('T',CArtifact::ART_TREASURE)('N',CArtifact::ART_MINOR)('J',CArtifact::ART_MAJOR)('R',CArtifact::ART_RELIC);
|
||||||
std::string buf = bitmaph->getTextFile("ARTRAITS.TXT"), dump, pom;
|
std::string buf = bitmaph->getTextFile("ARTRAITS.TXT"), dump, pom;
|
||||||
@@ -226,10 +248,18 @@ void CArtHandler::loadArtifacts(bool onlyTxt)
|
|||||||
VLC->generaltexth->artifNames.resize(GameConstants::ARTIFACTS_QUANTITY);
|
VLC->generaltexth->artifNames.resize(GameConstants::ARTIFACTS_QUANTITY);
|
||||||
VLC->generaltexth->artifDescriptions.resize(GameConstants::ARTIFACTS_QUANTITY);
|
VLC->generaltexth->artifDescriptions.resize(GameConstants::ARTIFACTS_QUANTITY);
|
||||||
std::map<ui32,ui8>::iterator itr;
|
std::map<ui32,ui8>::iterator itr;
|
||||||
|
|
||||||
for (int i=0; i<GameConstants::ARTIFACTS_QUANTITY; i++)
|
for (int i=0; i<GameConstants::ARTIFACTS_QUANTITY; i++)
|
||||||
{
|
{
|
||||||
CArtifact *art = new CArtifact();
|
CArtifact *art;
|
||||||
|
if (vstd::contains (growingArtifacts, i))
|
||||||
|
{
|
||||||
|
art = new CGrowingArtifact();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
art = new CArtifact();
|
||||||
|
}
|
||||||
CArtifact &nart = *art;
|
CArtifact &nart = *art;
|
||||||
nart.id=i;
|
nart.id=i;
|
||||||
loadToIt(VLC->generaltexth->artifNames[i],buf,it,4);
|
loadToIt(VLC->generaltexth->artifNames[i],buf,it,4);
|
||||||
@@ -329,6 +359,23 @@ void CArtHandler::loadArtifacts(bool onlyTxt)
|
|||||||
|
|
||||||
artifacts.push_back(&nart);
|
artifacts.push_back(&nart);
|
||||||
}
|
}
|
||||||
|
if (GameConstants::COMMANDERS)
|
||||||
|
{ //TODO: move all artifacts config to separate json file
|
||||||
|
const JsonNode config(GameConstants::DATA_DIR + "/config/commanders.json");
|
||||||
|
BOOST_FOREACH(const JsonNode &artifact, config["artifacts"].Vector())
|
||||||
|
{
|
||||||
|
auto ga = dynamic_cast <CGrowingArtifact *>(artifacts[artifact["id"].Float()].get());
|
||||||
|
BOOST_FOREACH (auto b, artifact["bonusesPerLevel"].Vector())
|
||||||
|
{
|
||||||
|
ga->bonusesPerLevel.push_back (std::pair <ui16, Bonus> (b["level"].Float(), *ParseBonus (b["bonus"].Vector())));
|
||||||
|
}
|
||||||
|
BOOST_FOREACH (auto b, artifact["thresholdBonuses"].Vector())
|
||||||
|
{
|
||||||
|
ga->bonusesPerLevel.push_back (std::pair <ui16, Bonus> (b["level"].Float(), *ParseBonus (b["bonus"].Vector())));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
sortArts();
|
sortArts();
|
||||||
if(onlyTxt)
|
if(onlyTxt)
|
||||||
return;
|
return;
|
||||||
@@ -1112,7 +1159,17 @@ void CArtifactInstance::move(ArtifactLocation src, ArtifactLocation dst)
|
|||||||
CArtifactInstance * CArtifactInstance::createNewArtifactInstance(CArtifact *Art)
|
CArtifactInstance * CArtifactInstance::createNewArtifactInstance(CArtifact *Art)
|
||||||
{
|
{
|
||||||
if(!Art->constituents)
|
if(!Art->constituents)
|
||||||
return new CArtifactInstance(Art);
|
{
|
||||||
|
auto ret = new CArtifactInstance(Art);
|
||||||
|
if (dynamic_cast<CGrowingArtifact *>(Art))
|
||||||
|
{
|
||||||
|
Bonus * bonus = new Bonus;
|
||||||
|
bonus->type = Bonus::LEVEL_COUNTER;
|
||||||
|
bonus->val = 0;
|
||||||
|
ret->addNewBonus (bonus);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
CCombinedArtifactInstance * ret = new CCombinedArtifactInstance(Art);
|
CCombinedArtifactInstance * ret = new CCombinedArtifactInstance(Art);
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ class CArtifact;
|
|||||||
class CGHeroInstance;
|
class CGHeroInstance;
|
||||||
struct ArtifactLocation;
|
struct ArtifactLocation;
|
||||||
class CArtifactSet;
|
class CArtifactSet;
|
||||||
|
class CArtifactInstance;
|
||||||
|
|
||||||
namespace ArtifactPosition
|
namespace ArtifactPosition
|
||||||
{
|
{
|
||||||
@@ -55,6 +56,8 @@ public:
|
|||||||
int getArtClassSerial() const; //0 - treasure, 1 - minor, 2 - major, 3 - relic, 4 - spell scroll, 5 - other
|
int getArtClassSerial() const; //0 - treasure, 1 - minor, 2 - major, 3 - relic, 4 - spell scroll, 5 - other
|
||||||
std::string nodeName() const OVERRIDE;
|
std::string nodeName() const OVERRIDE;
|
||||||
|
|
||||||
|
virtual void levelUpArtifact (CArtifactInstance * art){};
|
||||||
|
|
||||||
ui32 price;
|
ui32 price;
|
||||||
bmap<ui8, std::vector<ui16> > possibleSlots; //Bearer Type => ids of slots where artifact can be placed
|
bmap<ui8, std::vector<ui16> > possibleSlots; //Bearer Type => ids of slots where artifact can be placed
|
||||||
std::vector<ui32> * constituents; // Artifacts IDs a combined artifact consists of, or NULL.
|
std::vector<ui32> * constituents; // Artifacts IDs a combined artifact consists of, or NULL.
|
||||||
@@ -75,6 +78,21 @@ public:
|
|||||||
//void getParents(TCNodes &out, const CBonusSystemNode *root = NULL) const;
|
//void getParents(TCNodes &out, const CBonusSystemNode *root = NULL) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class DLL_LINKAGE CGrowingArtifact : public CArtifact //for example commander artifacts getting bonuses after battle
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
std::vector <std::pair <ui16, Bonus> > bonusesPerLevel; //bonus given each n levels
|
||||||
|
std::vector <std::pair <ui16, Bonus> > thresholdBonuses; //after certain level they will be added once
|
||||||
|
|
||||||
|
void levelUpArtifact (CArtifactInstance * art);
|
||||||
|
|
||||||
|
template <typename Handler> void serialize(Handler &h, const int version)
|
||||||
|
{
|
||||||
|
h & static_cast<CArtifact&>(*this);
|
||||||
|
h & bonusesPerLevel & thresholdBonuses;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
class DLL_LINKAGE CArtifactInstance : public CBonusSystemNode
|
class DLL_LINKAGE CArtifactInstance : public CBonusSystemNode
|
||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
@@ -170,7 +188,7 @@ public:
|
|||||||
std::vector< ConstTransitivePtr<CArtifact> > artifacts;
|
std::vector< ConstTransitivePtr<CArtifact> > artifacts;
|
||||||
std::vector<CArtifact *> allowedArtifacts;
|
std::vector<CArtifact *> allowedArtifacts;
|
||||||
std::set<ui32> bigArtifacts; // Artifacts that cannot be moved to backpack, e.g. war machines.
|
std::set<ui32> bigArtifacts; // Artifacts that cannot be moved to backpack, e.g. war machines.
|
||||||
//std::map<ui32, ui8> modableArtifacts; //1-scroll, 2-banner, 3-commander art with progressive bonus
|
std::set<ui32> growingArtifacts;
|
||||||
|
|
||||||
void loadArtifacts(bool onlyTxt);
|
void loadArtifacts(bool onlyTxt);
|
||||||
void sortArts();
|
void sortArts();
|
||||||
@@ -194,7 +212,8 @@ public:
|
|||||||
|
|
||||||
template <typename Handler> void serialize(Handler &h, const int version)
|
template <typename Handler> void serialize(Handler &h, const int version)
|
||||||
{
|
{
|
||||||
h & artifacts & allowedArtifacts & treasures & minors & majors & relics;
|
h & artifacts & allowedArtifacts & treasures & minors & majors & relics
|
||||||
|
& growingArtifacts;
|
||||||
//if(!h.saving) sortArts();
|
//if(!h.saving) sortArts();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -202,24 +202,6 @@ bool CCreatureHandler::isEvil (si8 faction) const
|
|||||||
{
|
{
|
||||||
return faction != -1 && factionAlignments[faction] == -1;
|
return faction != -1 && factionAlignments[faction] == -1;
|
||||||
}
|
}
|
||||||
static Bonus * ParseBonus (const JsonVector &ability_vec) //TODO: merge with AddAbility, create universal parser for all bonus properties
|
|
||||||
{
|
|
||||||
Bonus * b = new Bonus();
|
|
||||||
std::string type = ability_vec[0].String();
|
|
||||||
auto it = bonusNameMap.find(type);
|
|
||||||
if (it == bonusNameMap.end())
|
|
||||||
{
|
|
||||||
tlog1 << "Error: invalid ability type " << type << " in creatures.txt" << std::endl;
|
|
||||||
return b;
|
|
||||||
}
|
|
||||||
b->type = it->second;
|
|
||||||
b->val = ability_vec[1].Float();
|
|
||||||
b->subtype = ability_vec[2].Float();
|
|
||||||
b->additionalInfo = ability_vec[3].Float();
|
|
||||||
b->duration = Bonus::PERMANENT;
|
|
||||||
b->turnsRemain = 0;
|
|
||||||
return b;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void AddAbility(CCreature *cre, const JsonVector &ability_vec)
|
static void AddAbility(CCreature *cre, const JsonVector &ability_vec)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1010,7 +1010,7 @@ void CCommanderInstance::setAlive (bool Alive)
|
|||||||
alive = Alive;
|
alive = Alive;
|
||||||
if (!alive)
|
if (!alive)
|
||||||
{
|
{
|
||||||
//remove all bonuses from artifacts
|
getBonusList().remove_if (Bonus::UntilCommanderKilled);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -35,6 +35,7 @@ typedef boost::function<bool(const Bonus*)> CSelector;
|
|||||||
|
|
||||||
#define BONUS_LIST \
|
#define BONUS_LIST \
|
||||||
BONUS_NAME(NONE) \
|
BONUS_NAME(NONE) \
|
||||||
|
BONUS_NAME(LEVEL_COUNTER) /* for commander artifacts*/ \
|
||||||
BONUS_NAME(MOVEMENT) /*both water/land*/ \
|
BONUS_NAME(MOVEMENT) /*both water/land*/ \
|
||||||
BONUS_NAME(LAND_MOVEMENT) \
|
BONUS_NAME(LAND_MOVEMENT) \
|
||||||
BONUS_NAME(SEA_MOVEMENT) \
|
BONUS_NAME(SEA_MOVEMENT) \
|
||||||
@@ -194,7 +195,8 @@ struct DLL_LINKAGE Bonus
|
|||||||
N_DAYS = 32,
|
N_DAYS = 32,
|
||||||
UNITL_BEING_ATTACKED = 64,/*removed after attack and counterattacks are performed*/
|
UNITL_BEING_ATTACKED = 64,/*removed after attack and counterattacks are performed*/
|
||||||
UNTIL_ATTACK = 128, /*removed after attack and counterattacks are performed*/
|
UNTIL_ATTACK = 128, /*removed after attack and counterattacks are performed*/
|
||||||
STACK_GETS_TURN = 256 /*removed when stack gets its turn - used for defensive stance*/
|
STACK_GETS_TURN = 256, /*removed when stack gets its turn - used for defensive stance*/
|
||||||
|
COMMANDER_KILLED = 512
|
||||||
};
|
};
|
||||||
enum BonusSource
|
enum BonusSource
|
||||||
{
|
{
|
||||||
@@ -303,6 +305,10 @@ struct DLL_LINKAGE Bonus
|
|||||||
{
|
{
|
||||||
return hb->duration & Bonus::UNITL_BEING_ATTACKED;
|
return hb->duration & Bonus::UNITL_BEING_ATTACKED;
|
||||||
}
|
}
|
||||||
|
static bool UntilCommanderKilled(const Bonus *hb)
|
||||||
|
{
|
||||||
|
return hb->duration & Bonus::COMMANDER_KILLED;
|
||||||
|
}
|
||||||
static bool IsFrom(const Bonus &hb, ui8 source, ui32 id) //if id==0xffffff then id doesn't matter
|
static bool IsFrom(const Bonus &hb, ui8 source, ui32 id) //if id==0xffffff then id doesn't matter
|
||||||
{
|
{
|
||||||
return hb.source==source && (id==0xffffff || hb.sid==id);
|
return hb.source==source && (id==0xffffff || hb.sid==id);
|
||||||
|
|||||||
@@ -1,6 +1,9 @@
|
|||||||
#include "StdInc.h"
|
#include "StdInc.h"
|
||||||
#include "JsonNode.h"
|
#include "JsonNode.h"
|
||||||
|
|
||||||
|
|
||||||
|
class Bonus;
|
||||||
|
|
||||||
const JsonNode JsonNode::nullNode;
|
const JsonNode JsonNode::nullNode;
|
||||||
|
|
||||||
JsonNode::JsonNode(JsonType Type):
|
JsonNode::JsonNode(JsonType Type):
|
||||||
@@ -869,4 +872,4 @@ JsonValidator::JsonValidator(JsonNode &root, const JsonNode &schema, bool Minimi
|
|||||||
if (schema.isNull())
|
if (schema.isNull())
|
||||||
addMessage("Schema not found!");
|
addMessage("Schema not found!");
|
||||||
tlog3<<errors;
|
tlog3<<errors;
|
||||||
}
|
}
|
||||||
413
lib/JsonNode.h
413
lib/JsonNode.h
@@ -1,200 +1,221 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "HeroBonus.h"
|
||||||
|
|
||||||
class JsonNode;
|
class JsonNode;
|
||||||
typedef std::map <std::string, JsonNode> JsonMap;
|
typedef std::map <std::string, JsonNode> JsonMap;
|
||||||
typedef std::vector <JsonNode> JsonVector;
|
typedef std::vector <JsonNode> JsonVector;
|
||||||
|
|
||||||
class DLL_LINKAGE JsonNode
|
class Bonus;
|
||||||
{
|
|
||||||
public:
|
class DLL_LINKAGE JsonNode
|
||||||
enum JsonType
|
{
|
||||||
{
|
public:
|
||||||
DATA_NULL,
|
enum JsonType
|
||||||
DATA_BOOL,
|
{
|
||||||
DATA_FLOAT,
|
DATA_NULL,
|
||||||
DATA_STRING,
|
DATA_BOOL,
|
||||||
DATA_VECTOR,
|
DATA_FLOAT,
|
||||||
DATA_STRUCT
|
DATA_STRING,
|
||||||
};
|
DATA_VECTOR,
|
||||||
|
DATA_STRUCT
|
||||||
private:
|
};
|
||||||
union JsonData
|
|
||||||
{
|
private:
|
||||||
bool Bool;
|
union JsonData
|
||||||
double Float;
|
{
|
||||||
std::string* String;
|
bool Bool;
|
||||||
JsonVector* Vector;
|
double Float;
|
||||||
JsonMap* Struct;
|
std::string* String;
|
||||||
};
|
JsonVector* Vector;
|
||||||
|
JsonMap* Struct;
|
||||||
JsonType type;
|
};
|
||||||
JsonData data;
|
|
||||||
|
JsonType type;
|
||||||
public:
|
JsonData data;
|
||||||
//Create empty node
|
|
||||||
JsonNode(JsonType Type = DATA_NULL);
|
public:
|
||||||
//Create tree from Json-formatted input
|
//Create empty node
|
||||||
explicit JsonNode(const char * data, size_t datasize);
|
JsonNode(JsonType Type = DATA_NULL);
|
||||||
//Create tree from JSON file
|
//Create tree from Json-formatted input
|
||||||
explicit JsonNode(std::string filename);
|
explicit JsonNode(const char * data, size_t datasize);
|
||||||
//Copy c-tor
|
//Create tree from JSON file
|
||||||
JsonNode(const JsonNode ©);
|
explicit JsonNode(std::string filename);
|
||||||
|
//Copy c-tor
|
||||||
~JsonNode();
|
JsonNode(const JsonNode ©);
|
||||||
|
|
||||||
void swap(JsonNode &b);
|
~JsonNode();
|
||||||
JsonNode& operator =(JsonNode node);
|
|
||||||
|
void swap(JsonNode &b);
|
||||||
bool operator == (const JsonNode &other) const;
|
JsonNode& operator =(JsonNode node);
|
||||||
bool operator != (const JsonNode &other) const;
|
|
||||||
|
bool operator == (const JsonNode &other) const;
|
||||||
//removes all nodes that are identical to default entry in schema
|
bool operator != (const JsonNode &other) const;
|
||||||
void minimize(const JsonNode& schema);
|
|
||||||
//check schema
|
//removes all nodes that are identical to default entry in schema
|
||||||
void validate(const JsonNode& schema);
|
void minimize(const JsonNode& schema);
|
||||||
|
//check schema
|
||||||
//Convert node to another type. Converting to NULL will clear all data
|
void validate(const JsonNode& schema);
|
||||||
void setType(JsonType Type);
|
|
||||||
JsonType getType() const;
|
//Convert node to another type. Converting to NULL will clear all data
|
||||||
|
void setType(JsonType Type);
|
||||||
bool isNull() const;
|
JsonType getType() const;
|
||||||
|
|
||||||
//non-const accessors, node will change type on type mismatch
|
bool isNull() const;
|
||||||
bool & Bool();
|
|
||||||
double & Float();
|
//non-const accessors, node will change type on type mismatch
|
||||||
std::string & String();
|
bool & Bool();
|
||||||
JsonVector & Vector();
|
double & Float();
|
||||||
JsonMap & Struct();
|
std::string & String();
|
||||||
|
JsonVector & Vector();
|
||||||
//const accessors, will cause assertion failure on type mismatch
|
JsonMap & Struct();
|
||||||
const bool & Bool() const;
|
|
||||||
const double & Float() const;
|
//const accessors, will cause assertion failure on type mismatch
|
||||||
const std::string & String() const;
|
const bool & Bool() const;
|
||||||
const JsonVector & Vector() const;
|
const double & Float() const;
|
||||||
const JsonMap & Struct() const;
|
const std::string & String() const;
|
||||||
|
const JsonVector & Vector() const;
|
||||||
template<typename T>
|
const JsonMap & Struct() const;
|
||||||
std::vector<T> StdVector() const
|
|
||||||
{
|
template<typename T>
|
||||||
static_assert(std::is_arithmetic<T>::value, "This works with numbers only.");
|
std::vector<T> StdVector() const
|
||||||
|
{
|
||||||
|
static_assert(std::is_arithmetic<T>::value, "This works with numbers only.");
|
||||||
std::vector<T> ret;
|
std::vector<T> ret;
|
||||||
BOOST_FOREACH(const JsonNode &node, Vector())
|
BOOST_FOREACH(const JsonNode &node, Vector())
|
||||||
{
|
{
|
||||||
ret.push_back(node.Float());
|
ret.push_back(node.Float());
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
//operator [], for structs only - get child node by name
|
//operator [], for structs only - get child node by name
|
||||||
JsonNode & operator[](std::string child);
|
JsonNode & operator[](std::string child);
|
||||||
const JsonNode & operator[](std::string child) const;
|
const JsonNode & operator[](std::string child) const;
|
||||||
|
|
||||||
//error value for const operator[]
|
//error value for const operator[]
|
||||||
static const JsonNode nullNode;
|
static const JsonNode nullNode;
|
||||||
};
|
};
|
||||||
|
|
||||||
class JsonWriter
|
class JsonWriter
|
||||||
{
|
{
|
||||||
//prefix for each line (tabulation)
|
//prefix for each line (tabulation)
|
||||||
std::string prefix;
|
std::string prefix;
|
||||||
std::ostream &out;
|
std::ostream &out;
|
||||||
public:
|
public:
|
||||||
template<typename Iterator>
|
template<typename Iterator>
|
||||||
void writeContainer(Iterator begin, Iterator end);
|
void writeContainer(Iterator begin, Iterator end);
|
||||||
void writeEntry(JsonMap::const_iterator entry);
|
void writeEntry(JsonMap::const_iterator entry);
|
||||||
void writeEntry(JsonVector::const_iterator entry);
|
void writeEntry(JsonVector::const_iterator entry);
|
||||||
void writeString(const std::string &string);
|
void writeString(const std::string &string);
|
||||||
void writeNode(const JsonNode &node);
|
void writeNode(const JsonNode &node);
|
||||||
JsonWriter(std::ostream &output, const JsonNode &node);
|
JsonWriter(std::ostream &output, const JsonNode &node);
|
||||||
};
|
};
|
||||||
|
|
||||||
DLL_LINKAGE std::ostream & operator<<(std::ostream &out, const JsonNode &node);
|
DLL_LINKAGE std::ostream & operator<<(std::ostream &out, const JsonNode &node);
|
||||||
|
|
||||||
//Tiny string class that uses const char* as data for speed, members are private
|
//Tiny string class that uses const char* as data for speed, members are private
|
||||||
//for ease of debugging and some compatibility with std::string
|
//for ease of debugging and some compatibility with std::string
|
||||||
class constString
|
class constString
|
||||||
{
|
{
|
||||||
const char *data;
|
const char *data;
|
||||||
const size_t datasize;
|
const size_t datasize;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
constString(const char * inputString, size_t stringSize):
|
constString(const char * inputString, size_t stringSize):
|
||||||
data(inputString),
|
data(inputString),
|
||||||
datasize(stringSize)
|
datasize(stringSize)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
inline size_t size() const
|
inline size_t size() const
|
||||||
{
|
{
|
||||||
return datasize;
|
return datasize;
|
||||||
};
|
};
|
||||||
|
|
||||||
inline const char& operator[] (size_t position)
|
inline const char& operator[] (size_t position)
|
||||||
{
|
{
|
||||||
assert (position < datasize);
|
assert (position < datasize);
|
||||||
return data[position];
|
return data[position];
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
//Internal class for string -> JsonNode conversion
|
//Internal class for string -> JsonNode conversion
|
||||||
class JsonParser
|
class JsonParser
|
||||||
{
|
{
|
||||||
std::string errors; // Contains description of all encountered errors
|
std::string errors; // Contains description of all encountered errors
|
||||||
constString input; // Input data
|
constString input; // Input data
|
||||||
ui32 lineCount; // Currently parsed line, starting from 1
|
ui32 lineCount; // Currently parsed line, starting from 1
|
||||||
size_t lineStart; // Position of current line start
|
size_t lineStart; // Position of current line start
|
||||||
size_t pos; // Current position of parser
|
size_t pos; // Current position of parser
|
||||||
|
|
||||||
//Helpers
|
//Helpers
|
||||||
bool extractEscaping(std::string &str);
|
bool extractEscaping(std::string &str);
|
||||||
bool extractLiteral(const std::string &literal);
|
bool extractLiteral(const std::string &literal);
|
||||||
bool extractString(std::string &string);
|
bool extractString(std::string &string);
|
||||||
bool extractWhitespace(bool verbose = true);
|
bool extractWhitespace(bool verbose = true);
|
||||||
bool extractSeparator();
|
bool extractSeparator();
|
||||||
bool extractElement(JsonNode &node, char terminator);
|
bool extractElement(JsonNode &node, char terminator);
|
||||||
|
|
||||||
//Methods for extracting JSON data
|
//Methods for extracting JSON data
|
||||||
bool extractArray(JsonNode &node);
|
bool extractArray(JsonNode &node);
|
||||||
bool extractFalse(JsonNode &node);
|
bool extractFalse(JsonNode &node);
|
||||||
bool extractFloat(JsonNode &node);
|
bool extractFloat(JsonNode &node);
|
||||||
bool extractNull(JsonNode &node);
|
bool extractNull(JsonNode &node);
|
||||||
bool extractString(JsonNode &node);
|
bool extractString(JsonNode &node);
|
||||||
bool extractStruct(JsonNode &node);
|
bool extractStruct(JsonNode &node);
|
||||||
bool extractTrue(JsonNode &node);
|
bool extractTrue(JsonNode &node);
|
||||||
bool extractValue(JsonNode &node);
|
bool extractValue(JsonNode &node);
|
||||||
|
|
||||||
//Add error\warning message to list
|
//Add error\warning message to list
|
||||||
bool error(const std::string &message, bool warning=false);
|
bool error(const std::string &message, bool warning=false);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
JsonParser(const char * inputString, size_t stringSize, JsonNode &root);
|
JsonParser(const char * inputString, size_t stringSize, JsonNode &root);
|
||||||
};
|
};
|
||||||
|
|
||||||
//Internal class for Json validation, used automaticaly in JsonNode constructor. Behaviour:
|
//Internal class for Json validation, used automaticaly in JsonNode constructor. Behaviour:
|
||||||
// - "schema" entry from root node is used for validation and will be removed
|
// - "schema" entry from root node is used for validation and will be removed
|
||||||
// - any missing entries will be replaced with default value from schema (if present)
|
// - any missing entries will be replaced with default value from schema (if present)
|
||||||
// - if entry uses different type than defined in schema it will be removed
|
// - if entry uses different type than defined in schema it will be removed
|
||||||
// - entries nod described in schema will be kept unchanged
|
// - entries nod described in schema will be kept unchanged
|
||||||
class JsonValidator
|
class JsonValidator
|
||||||
{
|
{
|
||||||
std::string errors; // Contains description of all encountered errors
|
std::string errors; // Contains description of all encountered errors
|
||||||
std::list<std::string> currentPath; // path from root node to current one
|
std::list<std::string> currentPath; // path from root node to current one
|
||||||
bool minimize;
|
bool minimize;
|
||||||
|
|
||||||
bool validateType(JsonNode &node, const JsonNode &schema, JsonNode::JsonType type);
|
bool validateType(JsonNode &node, const JsonNode &schema, JsonNode::JsonType type);
|
||||||
bool validateSchema(JsonNode::JsonType &type, const JsonNode &schema);
|
bool validateSchema(JsonNode::JsonType &type, const JsonNode &schema);
|
||||||
bool validateNode(JsonNode &node, const JsonNode &schema, const std::string &name);
|
bool validateNode(JsonNode &node, const JsonNode &schema, const std::string &name);
|
||||||
bool validateItems(JsonNode &node, const JsonNode &schema);
|
bool validateItems(JsonNode &node, const JsonNode &schema);
|
||||||
bool validateProperties(JsonNode &node, const JsonNode &schema);
|
bool validateProperties(JsonNode &node, const JsonNode &schema);
|
||||||
|
|
||||||
bool addMessage(const std::string &message);
|
bool addMessage(const std::string &message);
|
||||||
public:
|
public:
|
||||||
// validate node with "schema" entry
|
// validate node with "schema" entry
|
||||||
JsonValidator(JsonNode &root, bool minimize=false);
|
JsonValidator(JsonNode &root, bool minimize=false);
|
||||||
// validate with external schema
|
// validate with external schema
|
||||||
JsonValidator(JsonNode &root, const JsonNode &schema, bool minimize=false);
|
JsonValidator(JsonNode &root, const JsonNode &schema, bool minimize=false);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
//Bonus * ParseBonus (const JsonVector &ability_vec);
|
||||||
|
|
||||||
|
static Bonus * ParseBonus (const JsonVector &ability_vec) //TODO: merge with AddAbility, create universal parser for all bonus properties
|
||||||
|
{
|
||||||
|
Bonus * b = new Bonus();
|
||||||
|
std::string type = ability_vec[0].String();
|
||||||
|
auto it = bonusNameMap.find(type);
|
||||||
|
if (it == bonusNameMap.end())
|
||||||
|
{
|
||||||
|
tlog1 << "Error: invalid ability type " << type << " in creatures.txt" << std::endl;
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
b->type = it->second;
|
||||||
|
b->val = ability_vec[1].Float();
|
||||||
|
b->subtype = ability_vec[2].Float();
|
||||||
|
b->additionalInfo = ability_vec[3].Float();
|
||||||
|
b->duration = Bonus::PERMANENT;
|
||||||
|
b->turnsRemain = 0;
|
||||||
|
return b;
|
||||||
|
}
|
||||||
@@ -1032,6 +1032,8 @@ DLL_LINKAGE void BattleObstaclePlaced::applyGs( CGameState *gs )
|
|||||||
void BattleResult::applyGs( CGameState *gs )
|
void BattleResult::applyGs( CGameState *gs )
|
||||||
{
|
{
|
||||||
//stack with SUMMONED flag but coming from garrison -> most likely resurrected, needs to be removed
|
//stack with SUMMONED flag but coming from garrison -> most likely resurrected, needs to be removed
|
||||||
|
|
||||||
|
//TODO: switch commander status to dead
|
||||||
BOOST_FOREACH(CStack *s, gs->curB->stacks)
|
BOOST_FOREACH(CStack *s, gs->curB->stacks)
|
||||||
{
|
{
|
||||||
if(s->base && s->base->armyObj && vstd::contains(s->state, EBattleStackState::SUMMONED))
|
if(s->base && s->base->armyObj && vstd::contains(s->state, EBattleStackState::SUMMONED))
|
||||||
@@ -1043,14 +1045,20 @@ void BattleResult::applyGs( CGameState *gs )
|
|||||||
for (unsigned i = 0; i < gs->curB->stacks.size(); i++)
|
for (unsigned i = 0; i < gs->curB->stacks.size(); i++)
|
||||||
delete gs->curB->stacks[i];
|
delete gs->curB->stacks[i];
|
||||||
|
|
||||||
//remove any "until next battle" bonuses
|
|
||||||
CGHeroInstance *h;
|
CGHeroInstance *h;
|
||||||
for (int i = 0; i < 2; ++i)
|
for (int i = 0; i < 2; ++i)
|
||||||
{
|
{
|
||||||
h = gs->curB->heroes[i];
|
h = gs->curB->heroes[i];
|
||||||
if (h)
|
if (h)
|
||||||
{
|
{
|
||||||
h->getBonusList().remove_if(Bonus::OneBattle);
|
h->getBonusList().remove_if(Bonus::OneBattle); //remove any "until next battle" bonuses
|
||||||
|
if (h->commander && h->commander->alive)
|
||||||
|
{
|
||||||
|
BOOST_FOREACH (auto art, h->commander->artifactsWorn) //increment bonuses for commander artifacts
|
||||||
|
{
|
||||||
|
art.second.artifact->artType->levelUpArtifact (art.second.artifact);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user