mirror of
https://github.com/vcmi/vcmi.git
synced 2025-09-16 09:26:28 +02:00
Preparation for user-defined bonus types
This commit is contained in:
@@ -45,14 +45,19 @@ CBonusTypeHandler::CBonusTypeHandler()
|
||||
{
|
||||
//register predefined bonus types
|
||||
|
||||
#define BONUS_NAME(x) \
|
||||
#define BONUS_NAME(x) { #x },
|
||||
bonusNames = {
|
||||
BONUS_LIST
|
||||
};
|
||||
#undef BONUS_NAME
|
||||
|
||||
#define BONUS_NAME(x) \
|
||||
do { \
|
||||
bonusTypes.push_back(CBonusType()); \
|
||||
} while(0);
|
||||
|
||||
|
||||
BONUS_LIST;
|
||||
#undef BONUS_NAME
|
||||
#undef BONUS_NAME
|
||||
}
|
||||
|
||||
CBonusTypeHandler::~CBonusTypeHandler() = default;
|
||||
@@ -117,19 +122,12 @@ std::vector<JsonNode> CBonusTypeHandler::loadLegacyData()
|
||||
|
||||
void CBonusTypeHandler::loadObject(std::string scope, std::string name, const JsonNode & data)
|
||||
{
|
||||
auto it = bonusNameMap.find(name);
|
||||
BonusType bonus = stringToBonus(name);
|
||||
|
||||
if(it == bonusNameMap.end())
|
||||
{
|
||||
logBonus->warn("Unrecognized bonus name! (%s)", name);
|
||||
}
|
||||
else
|
||||
{
|
||||
CBonusType & bt = bonusTypes[vstd::to_underlying(it->second)];
|
||||
CBonusType & bt = bonusTypes[vstd::to_underlying(bonus)];
|
||||
|
||||
loadItem(data, bt, name);
|
||||
logBonus->trace("Loaded bonus type %s", name);
|
||||
}
|
||||
loadItem(data, bt, name);
|
||||
logBonus->trace("Loaded bonus type %s", name);
|
||||
}
|
||||
|
||||
void CBonusTypeHandler::loadObject(std::string scope, std::string name, const JsonNode & data, size_t index)
|
||||
@@ -185,4 +183,27 @@ void CBonusTypeHandler::loadItem(const JsonNode & source, CBonusType & dest, con
|
||||
}
|
||||
}
|
||||
|
||||
BonusType CBonusTypeHandler::stringToBonus(const std::string & name) const
|
||||
{
|
||||
auto it = boost::range::find(bonusNames, name);
|
||||
|
||||
if (it != bonusNames.end())
|
||||
return static_cast<BonusType>(it - bonusNames.begin());
|
||||
return BonusType::NONE;
|
||||
}
|
||||
|
||||
const std::string CBonusTypeHandler::bonusToString(BonusType bonus) const
|
||||
{
|
||||
return bonusNames.at(static_cast<int>(bonus));
|
||||
}
|
||||
|
||||
std::vector<BonusType> CBonusTypeHandler::getAllObjets() const
|
||||
{
|
||||
std::vector<BonusType> ret;
|
||||
for (int i = 0; i < bonusNames.size(); ++i)
|
||||
ret.push_back(static_cast<BonusType>(i));
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
VCMI_LIB_NAMESPACE_END
|
||||
|
@@ -41,6 +41,7 @@ private:
|
||||
|
||||
class DLL_LINKAGE CBonusTypeHandler : public IBonusTypeHandler
|
||||
{
|
||||
std::vector<std::string> bonusNames;
|
||||
public:
|
||||
CBonusTypeHandler();
|
||||
virtual ~CBonusTypeHandler();
|
||||
@@ -52,6 +53,10 @@ public:
|
||||
void loadObject(std::string scope, std::string name, const JsonNode & data) override;
|
||||
void loadObject(std::string scope, std::string name, const JsonNode & data, size_t index) override;
|
||||
|
||||
BonusType stringToBonus(const std::string & name) const;
|
||||
const std::string bonusToString(BonusType bonus) const;
|
||||
|
||||
std::vector<BonusType> getAllObjets() const;
|
||||
private:
|
||||
void loadItem(const JsonNode & source, CBonusType & dest, const std::string & name) const;
|
||||
|
||||
|
@@ -14,6 +14,7 @@
|
||||
#include "Updaters.h"
|
||||
#include "Propagators.h"
|
||||
|
||||
#include "../CBonusTypeHandler.h"
|
||||
#include "../CCreatureHandler.h"
|
||||
#include "../CCreatureSet.h"
|
||||
#include "../CSkillHandler.h"
|
||||
@@ -172,7 +173,7 @@ JsonNode Bonus::toJsonNode() const
|
||||
{
|
||||
JsonNode root;
|
||||
// only add values that might reasonably be found in config files
|
||||
root["type"].String() = vstd::findKey(bonusNameMap, type);
|
||||
root["type"].String() = LIBRARY->bth->bonusToString(type);
|
||||
if(subtype != BonusSubtypeID())
|
||||
root["subtype"].String() = subtype.toString();
|
||||
if(additionalInfo != CAddInfo::NONE)
|
||||
@@ -243,9 +244,7 @@ std::shared_ptr<Bonus> Bonus::addPropagator(const TPropagatorPtr & Propagator)
|
||||
|
||||
DLL_LINKAGE std::ostream & operator<<(std::ostream &out, const Bonus &bonus)
|
||||
{
|
||||
for(const auto & i : bonusNameMap)
|
||||
if(i.second == bonus.type)
|
||||
out << "\tType: " << i.first << " \t";
|
||||
out << "\tType: " << LIBRARY->bth->bonusToString(bonus.type) << " \t";
|
||||
|
||||
#define printField(field) out << "\t" #field ": " << (int)bonus.field << "\n"
|
||||
printField(val);
|
||||
|
@@ -65,9 +65,8 @@ struct DLL_LINKAGE Bonus : public std::enable_shared_from_this<Bonus>, public Se
|
||||
BonusValueType valType = BonusValueType::ADDITIVE_VALUE; // 1 byte
|
||||
BonusSource source = BonusSource::OTHER; //source type" uses BonusSource values - what gave that bonus - 1 byte
|
||||
BonusSource targetSourceType = BonusSource::OTHER;//Bonuses of what origin this amplifies, uses BonusSource values. Needed for PERCENT_TO_TARGET_TYPE. - 1 byte
|
||||
BonusType type = BonusType::NONE; //uses BonusType values - says to what is this bonus - 1 byte
|
||||
BonusLimitEffect effectRange = BonusLimitEffect::NO_LIMIT; // 1 byte
|
||||
// 1 bytes padding
|
||||
BonusType type = BonusType::NONE; //uses BonusType values - says to what is this bonus - 2 bytes
|
||||
|
||||
BonusSubtypeID subtype;
|
||||
BonusSourceID sid; //source id: id of object/artifact/spell
|
||||
|
@@ -14,12 +14,6 @@
|
||||
|
||||
VCMI_LIB_NAMESPACE_BEGIN
|
||||
|
||||
#define BONUS_NAME(x) { #x, BonusType::x },
|
||||
const std::map<std::string, BonusType> bonusNameMap = {
|
||||
BONUS_LIST
|
||||
};
|
||||
#undef BONUS_NAME
|
||||
|
||||
#define BONUS_VALUE(x) { #x, BonusValueType::x },
|
||||
const std::map<std::string, BonusValueType> bonusValueMap = { BONUS_VALUE_LIST };
|
||||
#undef BONUS_VALUE
|
||||
|
@@ -224,11 +224,12 @@ class JsonNode;
|
||||
BONUS_VALUE(INDEPENDENT_MIN) //used for SECONDARY_SKILL_PREMY bonus
|
||||
|
||||
|
||||
enum class BonusType : uint8_t
|
||||
enum class BonusType : uint16_t
|
||||
{
|
||||
#define BONUS_NAME(x) x,
|
||||
BONUS_LIST
|
||||
#undef BONUS_NAME
|
||||
BUILTIN_BONUSES_COUNT
|
||||
};
|
||||
namespace BonusDuration //when bonus is automatically removed
|
||||
{
|
||||
@@ -273,7 +274,6 @@ enum class BonusValueType : uint8_t
|
||||
#undef BONUS_VALUE
|
||||
};
|
||||
|
||||
extern DLL_LINKAGE const std::map<std::string, BonusType> bonusNameMap;
|
||||
extern DLL_LINKAGE const std::map<std::string, BonusValueType> bonusValueMap;
|
||||
extern DLL_LINKAGE const std::map<std::string, BonusSource> bonusSourceMap;
|
||||
extern DLL_LINKAGE const std::map<std::string, BonusDuration::Type> bonusDurationMap;
|
||||
|
@@ -12,6 +12,7 @@
|
||||
#include "Limiters.h"
|
||||
#include "Updaters.h"
|
||||
|
||||
#include "../CBonusTypeHandler.h"
|
||||
#include "../GameLibrary.h"
|
||||
#include "../entities/faction/CFaction.h"
|
||||
#include "../entities/faction/CTownHandler.h"
|
||||
@@ -189,7 +190,7 @@ ILimiter::EDecision HasAnotherBonusLimiter::limit(const BonusLimitationContext &
|
||||
|
||||
std::string HasAnotherBonusLimiter::toString() const
|
||||
{
|
||||
std::string typeName = vstd::findKey(bonusNameMap, type);
|
||||
std::string typeName = LIBRARY->bth->bonusToString(type);
|
||||
if(isSubtypeRelevant)
|
||||
{
|
||||
boost::format fmt("HasAnotherBonusLimiter(type=%s, subtype=%s)");
|
||||
@@ -207,7 +208,7 @@ std::string HasAnotherBonusLimiter::toString() const
|
||||
JsonNode HasAnotherBonusLimiter::toJsonNode() const
|
||||
{
|
||||
JsonNode root;
|
||||
std::string typeName = vstd::findKey(bonusNameMap, type);
|
||||
std::string typeName = LIBRARY->bth->bonusToString(type);
|
||||
auto sourceTypeName = vstd::findKey(bonusSourceMap, source);
|
||||
|
||||
root["type"].String() = "HAS_ANOTHER_BONUS_LIMITER";
|
||||
|
@@ -78,12 +78,8 @@ public:
|
||||
class DLL_LINKAGE TimesStackLevelUpdater : public IUpdater
|
||||
{
|
||||
std::shared_ptr<Bonus> apply(const std::shared_ptr<Bonus> & b, int level) const;
|
||||
public:
|
||||
template <typename Handler> void serialize(Handler & h)
|
||||
{
|
||||
h & static_cast<IUpdater &>(*this);
|
||||
}
|
||||
|
||||
public:
|
||||
std::shared_ptr<Bonus> createUpdatedBonus(const std::shared_ptr<Bonus> & b, const CBonusSystemNode & context) const override;
|
||||
std::string toString() const override;
|
||||
JsonNode toJsonNode() const override;
|
||||
@@ -92,12 +88,8 @@ public:
|
||||
class DLL_LINKAGE DivideStackLevelUpdater : public IUpdater
|
||||
{
|
||||
std::shared_ptr<Bonus> apply(const std::shared_ptr<Bonus> & b, int level) const;
|
||||
public:
|
||||
template <typename Handler> void serialize(Handler & h)
|
||||
{
|
||||
h & static_cast<IUpdater &>(*this);
|
||||
}
|
||||
|
||||
public:
|
||||
std::shared_ptr<Bonus> createUpdatedBonus(const std::shared_ptr<Bonus> & b, const CBonusSystemNode & context) const override;
|
||||
std::string toString() const override;
|
||||
JsonNode toJsonNode() const override;
|
||||
@@ -125,11 +117,6 @@ public:
|
||||
class DLL_LINKAGE OwnerUpdater : public IUpdater
|
||||
{
|
||||
public:
|
||||
template <typename Handler> void serialize(Handler& h)
|
||||
{
|
||||
h & static_cast<IUpdater &>(*this);
|
||||
}
|
||||
|
||||
std::shared_ptr<Bonus> createUpdatedBonus(const std::shared_ptr<Bonus>& b, const CBonusSystemNode& context) const override;
|
||||
std::string toString() const override;
|
||||
JsonNode toJsonNode() const override;
|
||||
|
@@ -9,6 +9,7 @@
|
||||
*/
|
||||
|
||||
#include "StdInc.h"
|
||||
#include "CBonusTypeHandler.h"
|
||||
#include "JsonBonus.h"
|
||||
|
||||
#include "JsonValidator.h"
|
||||
@@ -184,10 +185,10 @@ static void loadBonusSubtype(BonusSubtypeID & subtype, BonusType type, const Jso
|
||||
break;
|
||||
}
|
||||
default:
|
||||
for(const auto & i : bonusNameMap)
|
||||
if(i.second == type)
|
||||
logMod->warn("Bonus type %s does not supports subtypes!", i.first );
|
||||
{
|
||||
logMod->warn("Bonus type %s does not supports subtypes!", LIBRARY->bth->bonusToString(type));
|
||||
subtype = BonusSubtypeID();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -258,10 +259,7 @@ static void loadBonusAddInfo(CAddInfo & var, BonusType type, const JsonNode & no
|
||||
}
|
||||
break;
|
||||
default:
|
||||
for(const auto & i : bonusNameMap)
|
||||
if(i.second == type)
|
||||
logMod->warn("Bonus type %s does not supports addInfo!", i.first );
|
||||
|
||||
logMod->warn("Bonus type %s does not supports addInfo!", LIBRARY->bth->bonusToString(type) );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -414,14 +412,8 @@ std::shared_ptr<Bonus> JsonUtils::parseBonus(const JsonVector & ability_vec)
|
||||
{
|
||||
auto b = std::make_shared<Bonus>();
|
||||
std::string type = ability_vec[0].String();
|
||||
auto it = bonusNameMap.find(type);
|
||||
if (it == bonusNameMap.end())
|
||||
{
|
||||
logMod->error("Error: invalid ability type %s.", type);
|
||||
return b;
|
||||
}
|
||||
b->type = it->second;
|
||||
|
||||
b->type = LIBRARY->bth->stringToBonus(type);
|
||||
b->val = static_cast<si32>(ability_vec[1].Float());
|
||||
loadBonusSubtype(b->subtype, b->type, ability_vec[2]);
|
||||
b->additionalInfo = static_cast<si32>(ability_vec[3].Float());
|
||||
@@ -505,15 +497,7 @@ std::shared_ptr<const ILimiter> JsonUtils::parseLimiter(const JsonNode & limiter
|
||||
if (!parameters[0].isNull())
|
||||
{
|
||||
std::string anotherBonusType = parameters[0].String();
|
||||
auto it = bonusNameMap.find(anotherBonusType);
|
||||
if(it != bonusNameMap.end())
|
||||
{
|
||||
bonusLimiter->type = it->second;
|
||||
}
|
||||
else
|
||||
{
|
||||
logMod->error("Error: invalid ability type %s.", anotherBonusType);
|
||||
}
|
||||
bonusLimiter->type = LIBRARY->bth->stringToBonus(anotherBonusType);
|
||||
}
|
||||
|
||||
auto findSource = [&](const JsonNode & parameter)
|
||||
@@ -627,15 +611,7 @@ bool JsonUtils::parseBonus(const JsonNode &ability, Bonus *b, const TextIdentifi
|
||||
{
|
||||
const JsonNode * value = nullptr;
|
||||
|
||||
std::string type = ability["type"].String();
|
||||
auto it = bonusNameMap.find(type);
|
||||
if (it == bonusNameMap.end())
|
||||
{
|
||||
logMod->error("Error: invalid ability type %s.", type);
|
||||
return false;
|
||||
}
|
||||
else
|
||||
b->type = it->second;
|
||||
b->type = LIBRARY->bth->stringToBonus(ability["type"].String());
|
||||
|
||||
loadBonusSubtype(b->subtype, b->type, ability["subtype"]);
|
||||
|
||||
@@ -771,12 +747,7 @@ CSelector JsonUtils::parseSelector(const JsonNode & ability)
|
||||
value = &ability["type"];
|
||||
if(value->isString())
|
||||
{
|
||||
auto it = bonusNameMap.find(value->String());
|
||||
if(it != bonusNameMap.end())
|
||||
{
|
||||
type = it->second;
|
||||
ret = ret.And(Selector::type()(it->second));
|
||||
}
|
||||
ret = ret.And(Selector::type()(LIBRARY->bth->stringToBonus(value->String())));
|
||||
}
|
||||
value = &ability["subtype"];
|
||||
if(!value->isNull() && type != BonusType::NONE)
|
||||
|
@@ -12,6 +12,7 @@
|
||||
|
||||
#include <cctype>
|
||||
|
||||
#include "CBonusTypeHandler.h"
|
||||
#include "CSpellHandler.h"
|
||||
#include "Problem.h"
|
||||
|
||||
@@ -473,26 +474,14 @@ JsonNode CSpell::convertTargetCondition(const BTVector & immunity, const BTVecto
|
||||
static const std::string CONDITION_NORMAL = "normal";
|
||||
static const std::string CONDITION_ABSOLUTE = "absolute";
|
||||
|
||||
#define BONUS_NAME(x) { BonusType::x, #x },
|
||||
static const std::map<BonusType, std::string> bonusNameRMap = { BONUS_LIST };
|
||||
#undef BONUS_NAME
|
||||
|
||||
JsonNode res;
|
||||
|
||||
auto convertVector = [&](const std::string & targetName, const BTVector & source, const std::string & value)
|
||||
{
|
||||
for(auto bonusType : source)
|
||||
{
|
||||
auto iter = bonusNameRMap.find(bonusType);
|
||||
if(iter != bonusNameRMap.end())
|
||||
{
|
||||
auto fullId = ModUtility::makeFullIdentifier("", "bonus", iter->second);
|
||||
res[targetName][fullId].String() = value;
|
||||
}
|
||||
else
|
||||
{
|
||||
logGlobal->error("Invalid bonus type %d", static_cast<int32_t>(bonusType));
|
||||
}
|
||||
std::string bonusName = LIBRARY->bth->bonusToString(bonusType);
|
||||
res[targetName][bonusName].String() = value;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -886,19 +875,6 @@ std::shared_ptr<CSpell> CSpellHandler::loadFromJson(const std::string & scope, c
|
||||
|
||||
spell->onlyOnWaterMap = json["onlyOnWaterMap"].Bool();
|
||||
|
||||
auto findBonus = [&](const std::string & name, std::vector<BonusType> & vec)
|
||||
{
|
||||
auto it = bonusNameMap.find(name);
|
||||
if(it == bonusNameMap.end())
|
||||
{
|
||||
logMod->error("Spell %s: invalid bonus name %s", spell->getNameTranslated(), name);
|
||||
}
|
||||
else
|
||||
{
|
||||
vec.push_back(static_cast<BonusType>(it->second));
|
||||
}
|
||||
};
|
||||
|
||||
auto readBonusStruct = [&](const std::string & name, std::vector<BonusType> & vec)
|
||||
{
|
||||
for(auto bonusData: json[name].Struct())
|
||||
@@ -907,7 +883,7 @@ std::shared_ptr<CSpell> CSpellHandler::loadFromJson(const std::string & scope, c
|
||||
const bool flag = bonusData.second.Bool();
|
||||
|
||||
if(flag)
|
||||
findBonus(bonusId, vec);
|
||||
vec.push_back(LIBRARY->bth->stringToBonus(bonusId));
|
||||
}
|
||||
};
|
||||
|
||||
|
@@ -355,12 +355,7 @@ public:
|
||||
{
|
||||
if(type == "bonus")
|
||||
{
|
||||
//TODO: support custom bonus types
|
||||
auto it = bonusNameMap.find(identifier);
|
||||
if(it != bonusNameMap.end())
|
||||
return std::make_shared<SelectorCondition>(Selector::type()(it->second));
|
||||
|
||||
logMod->error("Invalid bonus type %s in spell target condition.", identifier);
|
||||
return std::make_shared<SelectorCondition>(Selector::type()(LIBRARY->bth->stringToBonus(identifier)));
|
||||
}
|
||||
else if(type == "creature")
|
||||
{
|
||||
|
@@ -8,6 +8,7 @@
|
||||
*
|
||||
*/
|
||||
#include "StdInc.h"
|
||||
#include "CBonusTypeHandler.h"
|
||||
#include "rewardswidget.h"
|
||||
#include "ui_rewardswidget.h"
|
||||
#include "../lib/GameLibrary.h"
|
||||
@@ -183,8 +184,8 @@ RewardsWidget::RewardsWidget(CMap & m, CRewardableObject & p, QWidget *parent) :
|
||||
//fill bonuses
|
||||
for(auto & s : bonusDurationMap)
|
||||
ui->bonusDuration->addItem(QString::fromStdString(s.first));
|
||||
for(auto & s : bonusNameMap)
|
||||
ui->bonusType->addItem(QString::fromStdString(s.first));
|
||||
for(auto & s : LIBRARY->bth->getAllObjets())
|
||||
ui->bonusType->addItem(QString::fromStdString(LIBRARY->bth->bonusToString(s)));
|
||||
|
||||
//set default values
|
||||
if(dynamic_cast<CGPandoraBox*>(&object))
|
||||
@@ -340,7 +341,7 @@ void RewardsWidget::saveCurrentVisitInfo(int index)
|
||||
for(int i = 0; i < ui->bonuses->rowCount(); ++i)
|
||||
{
|
||||
auto dur = bonusDurationMap.at(ui->bonuses->item(i, 0)->text().toStdString());
|
||||
auto typ = bonusNameMap.at(ui->bonuses->item(i, 1)->text().toStdString());
|
||||
auto typ = LIBRARY->bth->stringToBonus(ui->bonuses->item(i, 1)->text().toStdString());
|
||||
auto val = ui->bonuses->item(i, 2)->data(Qt::UserRole).toInt();
|
||||
vinfo.reward.heroBonuses.emplace_back(dur, typ, BonusSource::OBJECT_INSTANCE, val, BonusSourceID(object.id));
|
||||
}
|
||||
@@ -490,7 +491,7 @@ void RewardsWidget::loadCurrentVisitInfo(int index)
|
||||
}
|
||||
}
|
||||
|
||||
auto typ = vstd::findKey(bonusNameMap, i.type);
|
||||
std::string typ = LIBRARY->bth->bonusToString(i.type);
|
||||
for(int i = 0; i < ui->bonusType->count(); ++i)
|
||||
{
|
||||
if(ui->bonusType->itemText(i) == QString::fromStdString(typ))
|
||||
@@ -816,7 +817,8 @@ void RewardsDelegate::updateModelData(QAbstractItemModel * model, const QModelIn
|
||||
QStringList bonusesList;
|
||||
for (auto & bonus : vinfo.reward.heroBonuses)
|
||||
{
|
||||
bonusesList += QString("%1 %2 (%3)").arg(QString::fromStdString(vstd::findKey(bonusDurationMap, bonus.duration))).arg(QString::fromStdString(vstd::findKey(bonusNameMap, bonus.type))).arg(bonus.val);
|
||||
std::string bonusName = LIBRARY->bth->bonusToString(bonus.type);
|
||||
bonusesList += QString("%1 %2 (%3)").arg(QString::fromStdString(vstd::findKey(bonusDurationMap, bonus.duration))).arg(QString::fromStdString(bonusName)).arg(bonus.val);
|
||||
}
|
||||
textList += QObject::tr("Bonuses: %1").arg(bonusesList.join(", "));
|
||||
}
|
||||
|
@@ -187,7 +187,6 @@ static void publishMap(lua_State * L, const std::map<T , std::bitset<N>> & map)
|
||||
|
||||
void BonusProxy::adjustStaticTable(lua_State * L) const
|
||||
{
|
||||
publishMap(L, bonusNameMap);
|
||||
publishMap(L, bonusValueMap);
|
||||
publishMap(L, bonusSourceMap);
|
||||
publishMap(L, bonusDurationMap);
|
||||
|
Reference in New Issue
Block a user