mirror of
https://github.com/vcmi/vcmi.git
synced 2024-12-10 09:50:17 +02:00
10dbbead2d
That wouldn't be as big issue if problem affected few files, but it everywhere in codebase. Fixed it everywhere since in most files that is the only code with wrong indentation.
316 lines
6.8 KiB
C++
316 lines
6.8 KiB
C++
/*
|
|
* CBonusTypeHandler.cpp, 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 "CBonusTypeHandler.h"
|
|
|
|
#include "JsonNode.h"
|
|
#include "filesystem/Filesystem.h"
|
|
|
|
#include "GameConstants.h"
|
|
#include "CCreatureHandler.h"
|
|
#include "spells/CSpellHandler.h"
|
|
|
|
///MacroString
|
|
|
|
MacroString::MacroString(const std::string &format)
|
|
{
|
|
static const std::string MACRO_START = "${";
|
|
static const std::string MACRO_END = "}";
|
|
static const size_t MACRO_START_L = 2;
|
|
static const size_t MACRO_END_L = 1;
|
|
|
|
size_t end_pos = 0;
|
|
size_t start_pos = std::string::npos;
|
|
|
|
do
|
|
{
|
|
start_pos = format.find(MACRO_START, end_pos);
|
|
|
|
if (!(start_pos == std::string::npos))
|
|
{
|
|
//chunk before macro
|
|
items.push_back(Item(Item::STRING,format.substr(end_pos, start_pos-end_pos)));
|
|
|
|
start_pos += MACRO_START_L;
|
|
end_pos = format.find(MACRO_END, start_pos);
|
|
|
|
if (end_pos == std::string::npos)
|
|
{
|
|
logBonus->warnStream() << "Format error in: " << format;
|
|
end_pos = start_pos;
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
items.push_back(Item(Item::MACRO,format.substr(start_pos,end_pos-start_pos)));
|
|
end_pos += MACRO_END_L;
|
|
}
|
|
}
|
|
}
|
|
while (start_pos != std::string::npos);
|
|
|
|
//no more macros
|
|
items.push_back(Item(Item::STRING,format.substr(end_pos)));
|
|
}
|
|
|
|
std::string MacroString::build(const GetValue& getValue) const
|
|
{
|
|
std::string result;
|
|
|
|
for(const Item &i : items)
|
|
{
|
|
switch (i.type)
|
|
{
|
|
case Item::MACRO:
|
|
{
|
|
result += getValue(i.value);
|
|
break;
|
|
}
|
|
case Item::STRING:
|
|
{
|
|
result += i.value;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
///CBonusType
|
|
|
|
CBonusType::CBonusType()
|
|
{
|
|
hidden = true;
|
|
icon = nameTemplate = descriptionTemplate = "";
|
|
}
|
|
|
|
CBonusType::~CBonusType()
|
|
{
|
|
|
|
}
|
|
|
|
void CBonusType::buildMacros()
|
|
{
|
|
name = MacroString(nameTemplate);
|
|
description = MacroString(descriptionTemplate);
|
|
}
|
|
|
|
|
|
///CBonusTypeHandler
|
|
|
|
CBonusTypeHandler::CBonusTypeHandler()
|
|
{
|
|
//register predefined bonus types
|
|
|
|
#define BONUS_NAME(x) \
|
|
do{\
|
|
bonusTypes.push_back(CBonusType());\
|
|
}while (0);
|
|
|
|
|
|
BONUS_LIST;
|
|
#undef BONUS_NAME
|
|
|
|
load();
|
|
}
|
|
|
|
CBonusTypeHandler::~CBonusTypeHandler()
|
|
{
|
|
//dtor
|
|
}
|
|
|
|
std::string CBonusTypeHandler::bonusToString(const Bonus *bonus, const IBonusBearer *bearer, bool description) const
|
|
{
|
|
auto getValue = [=](const std::string &name) -> std::string
|
|
{
|
|
if (name == "val")
|
|
{
|
|
return boost::lexical_cast<std::string>(bearer->valOfBonuses(Selector::typeSubtype(bonus->type, bonus->subtype)));
|
|
}
|
|
else if (name == "subtype.creature")
|
|
{
|
|
const CreatureID cre(bonus->subtype);
|
|
return cre.toCreature()->namePl;
|
|
}
|
|
else if (name == "subtype.spell")
|
|
{
|
|
const SpellID sp(bonus->subtype);
|
|
return sp.toSpell()->name;
|
|
}
|
|
else if (name == "MR")
|
|
{
|
|
return boost::lexical_cast<std::string>(bearer->magicResistance());
|
|
}
|
|
else
|
|
{
|
|
logBonus->warnStream() << "Unknown macro in bonus config: " << name;
|
|
return "[error]";
|
|
}
|
|
};
|
|
|
|
const CBonusType& bt = bonusTypes[bonus->type];
|
|
if(bt.hidden)
|
|
return "";
|
|
const MacroString& macro = description ? bt.description : bt.name;
|
|
|
|
return macro.build(getValue);
|
|
}
|
|
|
|
std::string CBonusTypeHandler::bonusToGraphics(const Bonus* bonus) const
|
|
{
|
|
std::string fileName;
|
|
bool fullPath = false;
|
|
|
|
switch (bonus->type)
|
|
{
|
|
case Bonus::SECONDARY_SKILL_PREMY:
|
|
if (bonus->subtype == SecondarySkill::RESISTANCE)
|
|
{
|
|
fileName = "E_DWARF.bmp";
|
|
}
|
|
break;
|
|
case Bonus::SPELL_IMMUNITY:
|
|
{
|
|
fullPath = true;
|
|
const CSpell * sp = SpellID(bonus->subtype).toSpell();
|
|
fileName = sp->getIconImmune();
|
|
break;
|
|
}
|
|
case Bonus::FIRE_IMMUNITY:
|
|
switch (bonus->subtype)
|
|
{
|
|
case 0:
|
|
fileName = "E_SPFIRE.bmp"; break; //all
|
|
case 1:
|
|
fileName = "E_SPFIRE1.bmp"; break; //not positive
|
|
case 2:
|
|
fileName = "E_FIRE.bmp"; break; //direct damage
|
|
}
|
|
break;
|
|
case Bonus::WATER_IMMUNITY:
|
|
switch (bonus->subtype)
|
|
{
|
|
case 0:
|
|
fileName = "E_SPWATER.bmp"; break; //all
|
|
case 1:
|
|
fileName = "E_SPWATER1.bmp"; break; //not positive
|
|
case 2:
|
|
fileName = "E_SPCOLD.bmp"; break; //direct damage
|
|
}
|
|
break;
|
|
case Bonus::AIR_IMMUNITY:
|
|
switch (bonus->subtype)
|
|
{
|
|
case 0:
|
|
fileName = "E_SPAIR.bmp"; break; //all
|
|
case 1:
|
|
fileName = "E_SPAIR1.bmp"; break; //not positive
|
|
case 2:
|
|
fileName = "E_LIGHT.bmp"; break;//direct damage
|
|
}
|
|
break;
|
|
case Bonus::EARTH_IMMUNITY:
|
|
switch (bonus->subtype)
|
|
{
|
|
case 0:
|
|
fileName = "E_SPEATH.bmp"; break; //all
|
|
case 1:
|
|
case 2: //no specific icon for direct damage immunity
|
|
fileName = "E_SPEATH1.bmp"; break; //not positive
|
|
}
|
|
break;
|
|
case Bonus::LEVEL_SPELL_IMMUNITY:
|
|
{
|
|
if (vstd::iswithin(bonus->val, 1 , 5))
|
|
{
|
|
fileName = "E_SPLVL" + boost::lexical_cast<std::string>(bonus->val) + ".bmp";
|
|
}
|
|
break;
|
|
}
|
|
case Bonus::GENERAL_DAMAGE_REDUCTION:
|
|
{
|
|
switch (bonus->subtype)
|
|
{
|
|
case 0:
|
|
fileName = "DamageReductionMelee.bmp"; break;
|
|
case 1:
|
|
fileName = "DamageReductionRanged.bmp"; break;
|
|
}
|
|
break;
|
|
}
|
|
|
|
default:
|
|
{
|
|
|
|
const CBonusType& bt = bonusTypes[bonus->type];
|
|
|
|
fileName = bt.icon;
|
|
fullPath = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if(!fileName.empty() && !fullPath)
|
|
fileName = "zvs/Lib1.res/" + fileName;
|
|
return fileName;
|
|
}
|
|
|
|
|
|
void CBonusTypeHandler::load()
|
|
{
|
|
const JsonNode gameConf(ResourceID("config/gameConfig.json"));
|
|
const JsonNode config(JsonUtils::assembleFromFiles(gameConf["bonuses"].convertTo<std::vector<std::string> >()));
|
|
load(config);
|
|
}
|
|
|
|
void CBonusTypeHandler::load(const JsonNode& config)
|
|
{
|
|
for(auto & node : config.Struct())
|
|
{
|
|
auto it = bonusNameMap.find(node.first);
|
|
|
|
if(it == bonusNameMap.end())
|
|
{
|
|
//TODO: new bonus
|
|
// CBonusType bt;
|
|
// loadItem(node.second, bt);
|
|
//
|
|
// auto new_id = bonusTypes.size();
|
|
//
|
|
// bonusTypes.push_back(bt);
|
|
|
|
logBonus->warnStream() << "Adding new bonuses not implemented (" << node.first << ")";
|
|
}
|
|
else
|
|
{
|
|
CBonusType& bt = bonusTypes[it->second];
|
|
|
|
loadItem(node.second, bt);
|
|
logBonus->traceStream() << "Loaded bonus type " << node.first;
|
|
}
|
|
}
|
|
}
|
|
|
|
void CBonusTypeHandler::loadItem(const JsonNode& source, CBonusType& dest)
|
|
{
|
|
dest.nameTemplate = source["name"].String();
|
|
dest.descriptionTemplate = source["description"].String();
|
|
dest.hidden = source["hidden"].Bool(); //Null -> false
|
|
|
|
const JsonNode& graphics = source["graphics"];
|
|
|
|
if(!graphics.isNull())
|
|
{
|
|
dest.icon = graphics["icon"].String();
|
|
}
|
|
dest.buildMacros();
|
|
}
|
|
|