1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-01-12 02:28:11 +02:00

HeroBonus: split BonusList

This commit is contained in:
Konstantin 2023-04-30 20:34:25 +03:00
parent 48bcfe74f7
commit 29c76fb9bf
14 changed files with 400 additions and 364 deletions

View File

@ -27,6 +27,7 @@ macro(add_main_lib TARGET_NAME LIBRARY_TYPE)
${MAIN_LIB_DIR}/battle/SiegeInfo.cpp
${MAIN_LIB_DIR}/battle/Unit.cpp
${MAIN_LIB_DIR}/bonuses/BonusList.cpp
${MAIN_LIB_DIR}/bonuses/BonusParams.cpp
${MAIN_LIB_DIR}/bonuses/CBonusProxy.cpp
${MAIN_LIB_DIR}/bonuses/CBonusSystemNode.cpp
@ -308,6 +309,7 @@ macro(add_main_lib TARGET_NAME LIBRARY_TYPE)
${MAIN_LIB_DIR}/battle/SiegeInfo.h
${MAIN_LIB_DIR}/battle/Unit.h
${MAIN_LIB_DIR}/bonuses/BonusList.h
${MAIN_LIB_DIR}/bonuses/BonusParams.h
${MAIN_LIB_DIR}/bonuses/CBonusProxy.h
${MAIN_LIB_DIR}/bonuses/CBonusSystemNode.h

View File

@ -12,6 +12,7 @@
#include "VCMI_Lib.h"
#include "GameConstants.h"
#include "bonuses/BonusList.h"
#include "bonuses/HeroBonus.h"
#include "bonuses/IBonusBearer.h"

View File

@ -17,6 +17,7 @@
#include "../lib/ConstTransitivePtr.h"
#include "GameConstants.h"
#include "bonuses/HeroBonus.h"
#include "bonuses/BonusList.h"
#include "IHandlerBase.h"
VCMI_LIB_NAMESPACE_BEGIN

View File

@ -20,6 +20,7 @@
#include "LogicalExpression.h"
#include "battle/BattleHex.h"
#include "bonuses/HeroBonus.h"
#include "bonuses/BonusList.h"
#include "Point.h"
VCMI_LIB_NAMESPACE_BEGIN

276
lib/bonuses/BonusList.cpp Normal file
View File

@ -0,0 +1,276 @@
/*
* BonusList.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 "CBonusSystemNode.h"
VCMI_LIB_NAMESPACE_BEGIN
BonusList::BonusList(bool BelongsToTree) : belongsToTree(BelongsToTree)
{
}
BonusList::BonusList(const BonusList & bonusList): belongsToTree(false)
{
bonuses.resize(bonusList.size());
std::copy(bonusList.begin(), bonusList.end(), bonuses.begin());
}
BonusList::BonusList(BonusList && other) noexcept: belongsToTree(false)
{
std::swap(belongsToTree, other.belongsToTree);
std::swap(bonuses, other.bonuses);
}
BonusList& BonusList::operator=(const BonusList &bonusList)
{
bonuses.resize(bonusList.size());
std::copy(bonusList.begin(), bonusList.end(), bonuses.begin());
belongsToTree = false;
return *this;
}
void BonusList::changed() const
{
if(belongsToTree)
CBonusSystemNode::treeHasChanged();
}
void BonusList::stackBonuses()
{
boost::sort(bonuses, [](const std::shared_ptr<Bonus> & b1, const std::shared_ptr<Bonus> & b2) -> bool
{
if(b1 == b2)
return false;
#define COMPARE_ATT(ATT) if(b1->ATT != b2->ATT) return b1->ATT < b2->ATT
COMPARE_ATT(stacking);
COMPARE_ATT(type);
COMPARE_ATT(subtype);
COMPARE_ATT(valType);
#undef COMPARE_ATT
return b1->val > b2->val;
});
// remove non-stacking
size_t next = 1;
while(next < bonuses.size())
{
bool remove = false;
std::shared_ptr<Bonus> last = bonuses[next-1];
std::shared_ptr<Bonus> current = bonuses[next];
if(current->stacking.empty())
remove = current == last;
else if(current->stacking == "ALWAYS")
remove = false;
else
remove = current->stacking == last->stacking
&& current->type == last->type
&& current->subtype == last->subtype
&& current->valType == last->valType;
if(remove)
bonuses.erase(bonuses.begin() + next);
else
next++;
}
}
int BonusList::totalValue() const
{
struct BonusCollection
{
int base = 0;
int percentToBase = 0;
int percentToAll = 0;
int additive = 0;
int percentToSource = 0;
int indepMin = std::numeric_limits<int>::max();
int indepMax = std::numeric_limits<int>::min();
};
auto percent = [](int64_t base, int64_t percent) -> int {
return static_cast<int>(std::clamp<int64_t>((base * (100 + percent)) / 100, std::numeric_limits<int>::min(), std::numeric_limits<int>::max()));
};
std::array <BonusCollection, Bonus::BonusSource::NUM_BONUS_SOURCE> sources = {};
BonusCollection any;
bool hasIndepMax = false;
bool hasIndepMin = false;
for(const auto & b : bonuses)
{
switch(b->valType)
{
case Bonus::BASE_NUMBER:
sources[b->source].base += b->val;
break;
case Bonus::PERCENT_TO_ALL:
sources[b->source].percentToAll += b->val;
break;
case Bonus::PERCENT_TO_BASE:
sources[b->source].percentToBase += b->val;
break;
case Bonus::PERCENT_TO_SOURCE:
sources[b->source].percentToSource += b->val;
break;
case Bonus::PERCENT_TO_TARGET_TYPE:
sources[b->targetSourceType].percentToSource += b->val;
break;
case Bonus::ADDITIVE_VALUE:
sources[b->source].additive += b->val;
break;
case Bonus::INDEPENDENT_MAX:
hasIndepMax = true;
vstd::amax(sources[b->source].indepMax, b->val);
break;
case Bonus::INDEPENDENT_MIN:
hasIndepMin = true;
vstd::amin(sources[b->source].indepMin, b->val);
break;
}
}
for(const auto & src : sources)
{
any.base += percent(src.base, src.percentToSource);
any.percentToBase += percent(src.percentToBase, src.percentToSource);
any.percentToAll += percent(src.percentToAll, src.percentToSource);
any.additive += percent(src.additive, src.percentToSource);
if(hasIndepMin)
vstd::amin(any.indepMin, percent(src.indepMin, src.percentToSource));
if(hasIndepMax)
vstd::amax(any.indepMax, percent(src.indepMax, src.percentToSource));
}
any.base = percent(any.base, any.percentToBase);
any.base += any.additive;
auto valFirst = percent(any.base ,any.percentToAll);
if(hasIndepMin && hasIndepMax && any.indepMin < any.indepMax)
any.indepMax = any.indepMin;
const int notIndepBonuses = static_cast<int>(std::count_if(bonuses.cbegin(), bonuses.cend(), [](const std::shared_ptr<Bonus>& b)
{
return b->valType != Bonus::INDEPENDENT_MAX && b->valType != Bonus::INDEPENDENT_MIN;
}));
if(notIndepBonuses)
return std::clamp(valFirst, any.indepMax, any.indepMin);
return hasIndepMin ? any.indepMin : hasIndepMax ? any.indepMax : 0;
}
std::shared_ptr<Bonus> BonusList::getFirst(const CSelector &select)
{
for (auto & b : bonuses)
{
if(select(b.get()))
return b;
}
return nullptr;
}
std::shared_ptr<const Bonus> BonusList::getFirst(const CSelector &selector) const
{
for(const auto & b : bonuses)
{
if(selector(b.get()))
return b;
}
return nullptr;
}
void BonusList::getBonuses(BonusList & out, const CSelector &selector, const CSelector &limit) const
{
out.reserve(bonuses.size());
for(const auto & b : bonuses)
{
//add matching bonuses that matches limit predicate or have NO_LIMIT if no given predicate
auto noFightLimit = b->effectRange == Bonus::NO_LIMIT;
if(selector(b.get()) && ((!limit && noFightLimit) || ((bool)limit && limit(b.get()))))
out.push_back(b);
}
}
void BonusList::getAllBonuses(BonusList &out) const
{
for(const auto & b : bonuses)
out.push_back(b);
}
int BonusList::valOfBonuses(const CSelector &select) const
{
BonusList ret;
CSelector limit = nullptr;
getBonuses(ret, select, limit);
return ret.totalValue();
}
JsonNode BonusList::toJsonNode() const
{
JsonNode node(JsonNode::JsonType::DATA_VECTOR);
for(const std::shared_ptr<Bonus> & b : bonuses)
node.Vector().push_back(b->toJsonNode());
return node;
}
void BonusList::push_back(const std::shared_ptr<Bonus> & x)
{
bonuses.push_back(x);
changed();
}
BonusList::TInternalContainer::iterator BonusList::erase(const int position)
{
changed();
return bonuses.erase(bonuses.begin() + position);
}
void BonusList::clear()
{
bonuses.clear();
changed();
}
std::vector<BonusList *>::size_type BonusList::operator-=(const std::shared_ptr<Bonus> & i)
{
auto itr = std::find(bonuses.begin(), bonuses.end(), i);
if(itr == bonuses.end())
return false;
bonuses.erase(itr);
changed();
return true;
}
void BonusList::resize(BonusList::TInternalContainer::size_type sz, const std::shared_ptr<Bonus> & c)
{
bonuses.resize(sz, c);
changed();
}
void BonusList::reserve(TInternalContainer::size_type sz)
{
bonuses.reserve(sz);
}
void BonusList::insert(BonusList::TInternalContainer::iterator position, BonusList::TInternalContainer::size_type n, const std::shared_ptr<Bonus> & x)
{
bonuses.insert(position, n, x);
changed();
}
DLL_LINKAGE std::ostream & operator<<(std::ostream &out, const BonusList &bonusList)
{
for (ui32 i = 0; i < bonusList.size(); i++)
{
const auto & b = bonusList[i];
out << "Bonus " << i << "\n" << *b << std::endl;
}
return out;
}
VCMI_LIB_NAMESPACE_END

113
lib/bonuses/BonusList.h Normal file
View File

@ -0,0 +1,113 @@
/*
* BonusList.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 "HeroBonus.h"
VCMI_LIB_NAMESPACE_BEGIN
class DLL_LINKAGE BonusList
{
public:
using TInternalContainer = std::vector<std::shared_ptr<Bonus>>;
private:
TInternalContainer bonuses;
bool belongsToTree;
void changed() const;
public:
using const_reference = TInternalContainer::const_reference;
using value_type = TInternalContainer::value_type;
using const_iterator = TInternalContainer::const_iterator;
using iterator = TInternalContainer::iterator;
BonusList(bool BelongsToTree = false);
BonusList(const BonusList &bonusList);
BonusList(BonusList && other) noexcept;
BonusList& operator=(const BonusList &bonusList);
// wrapper functions of the STL vector container
TInternalContainer::size_type size() const { return bonuses.size(); }
void push_back(const std::shared_ptr<Bonus> & x);
TInternalContainer::iterator erase (const int position);
void clear();
bool empty() const { return bonuses.empty(); }
void resize(TInternalContainer::size_type sz, const std::shared_ptr<Bonus> & c = nullptr);
void reserve(TInternalContainer::size_type sz);
TInternalContainer::size_type capacity() const { return bonuses.capacity(); }
STRONG_INLINE std::shared_ptr<Bonus> &operator[] (TInternalContainer::size_type n) { return bonuses[n]; }
STRONG_INLINE const std::shared_ptr<Bonus> &operator[] (TInternalContainer::size_type n) const { return bonuses[n]; }
std::shared_ptr<Bonus> &back() { return bonuses.back(); }
std::shared_ptr<Bonus> &front() { return bonuses.front(); }
const std::shared_ptr<Bonus> &back() const { return bonuses.back(); }
const std::shared_ptr<Bonus> &front() const { return bonuses.front(); }
// There should be no non-const access to provide solid,robust bonus caching
TInternalContainer::const_iterator begin() const { return bonuses.begin(); }
TInternalContainer::const_iterator end() const { return bonuses.end(); }
TInternalContainer::size_type operator-=(const std::shared_ptr<Bonus> & i);
// BonusList functions
void stackBonuses();
int totalValue() const;
void getBonuses(BonusList &out, const CSelector &selector, const CSelector &limit = nullptr) const;
void getAllBonuses(BonusList &out) const;
//special find functions
std::shared_ptr<Bonus> getFirst(const CSelector &select);
std::shared_ptr<const Bonus> getFirst(const CSelector &select) const;
int valOfBonuses(const CSelector &select) const;
// conversion / output
JsonNode toJsonNode() const;
// remove_if implementation for STL vector types
template <class Predicate>
void remove_if(Predicate pred)
{
BonusList newList;
for(const auto & b : bonuses)
{
if (!pred(b.get()))
newList.push_back(b);
}
bonuses.clear();
bonuses.resize(newList.size());
std::copy(newList.begin(), newList.end(), bonuses.begin());
}
template <class InputIterator>
void insert(const int position, InputIterator first, InputIterator last);
void insert(TInternalContainer::iterator position, TInternalContainer::size_type n, const std::shared_ptr<Bonus> & x);
template <typename Handler>
void serialize(Handler &h, const int version)
{
h & static_cast<TInternalContainer&>(bonuses);
}
// C++ for range support
auto begin () -> decltype (bonuses.begin())
{
return bonuses.begin();
}
auto end () -> decltype (bonuses.end())
{
return bonuses.end();
}
};
DLL_LINKAGE std::ostream & operator<<(std::ostream &out, const BonusList &bonusList);
VCMI_LIB_NAMESPACE_END

View File

@ -9,6 +9,7 @@
*/
#include "StdInc.h"
#include "BonusList.h"
#include "CBonusProxy.h"
#include "IBonusBearer.h"

View File

@ -9,6 +9,7 @@
*/
#pragma once
#include "BonusList.h"
#include "IBonusBearer.h"
VCMI_LIB_NAMESPACE_BEGIN

View File

@ -147,258 +147,6 @@ JsonNode CAddInfo::toJsonNode() const
return node;
}
}
BonusList::BonusList(bool BelongsToTree) : belongsToTree(BelongsToTree)
{
}
BonusList::BonusList(const BonusList & bonusList): belongsToTree(false)
{
bonuses.resize(bonusList.size());
std::copy(bonusList.begin(), bonusList.end(), bonuses.begin());
}
BonusList::BonusList(BonusList && other) noexcept: belongsToTree(false)
{
std::swap(belongsToTree, other.belongsToTree);
std::swap(bonuses, other.bonuses);
}
BonusList& BonusList::operator=(const BonusList &bonusList)
{
bonuses.resize(bonusList.size());
std::copy(bonusList.begin(), bonusList.end(), bonuses.begin());
belongsToTree = false;
return *this;
}
void BonusList::changed() const
{
if(belongsToTree)
CBonusSystemNode::treeHasChanged();
}
void BonusList::stackBonuses()
{
boost::sort(bonuses, [](const std::shared_ptr<Bonus> & b1, const std::shared_ptr<Bonus> & b2) -> bool
{
if(b1 == b2)
return false;
#define COMPARE_ATT(ATT) if(b1->ATT != b2->ATT) return b1->ATT < b2->ATT
COMPARE_ATT(stacking);
COMPARE_ATT(type);
COMPARE_ATT(subtype);
COMPARE_ATT(valType);
#undef COMPARE_ATT
return b1->val > b2->val;
});
// remove non-stacking
size_t next = 1;
while(next < bonuses.size())
{
bool remove = false;
std::shared_ptr<Bonus> last = bonuses[next-1];
std::shared_ptr<Bonus> current = bonuses[next];
if(current->stacking.empty())
remove = current == last;
else if(current->stacking == "ALWAYS")
remove = false;
else
remove = current->stacking == last->stacking
&& current->type == last->type
&& current->subtype == last->subtype
&& current->valType == last->valType;
if(remove)
bonuses.erase(bonuses.begin() + next);
else
next++;
}
}
int BonusList::totalValue() const
{
struct BonusCollection
{
int base = 0;
int percentToBase = 0;
int percentToAll = 0;
int additive = 0;
int percentToSource = 0;
int indepMin = std::numeric_limits<int>::max();
int indepMax = std::numeric_limits<int>::min();
};
auto percent = [](int64_t base, int64_t percent) -> int {
return static_cast<int>(std::clamp<int64_t>((base * (100 + percent)) / 100, std::numeric_limits<int>::min(), std::numeric_limits<int>::max()));
};
std::array <BonusCollection, Bonus::BonusSource::NUM_BONUS_SOURCE> sources = {};
BonusCollection any;
bool hasIndepMax = false;
bool hasIndepMin = false;
for(const auto & b : bonuses)
{
switch(b->valType)
{
case Bonus::BASE_NUMBER:
sources[b->source].base += b->val;
break;
case Bonus::PERCENT_TO_ALL:
sources[b->source].percentToAll += b->val;
break;
case Bonus::PERCENT_TO_BASE:
sources[b->source].percentToBase += b->val;
break;
case Bonus::PERCENT_TO_SOURCE:
sources[b->source].percentToSource += b->val;
break;
case Bonus::PERCENT_TO_TARGET_TYPE:
sources[b->targetSourceType].percentToSource += b->val;
break;
case Bonus::ADDITIVE_VALUE:
sources[b->source].additive += b->val;
break;
case Bonus::INDEPENDENT_MAX:
hasIndepMax = true;
vstd::amax(sources[b->source].indepMax, b->val);
break;
case Bonus::INDEPENDENT_MIN:
hasIndepMin = true;
vstd::amin(sources[b->source].indepMin, b->val);
break;
}
}
for(const auto & src : sources)
{
any.base += percent(src.base, src.percentToSource);
any.percentToBase += percent(src.percentToBase, src.percentToSource);
any.percentToAll += percent(src.percentToAll, src.percentToSource);
any.additive += percent(src.additive, src.percentToSource);
if(hasIndepMin)
vstd::amin(any.indepMin, percent(src.indepMin, src.percentToSource));
if(hasIndepMax)
vstd::amax(any.indepMax, percent(src.indepMax, src.percentToSource));
}
any.base = percent(any.base, any.percentToBase);
any.base += any.additive;
auto valFirst = percent(any.base ,any.percentToAll);
if(hasIndepMin && hasIndepMax && any.indepMin < any.indepMax)
any.indepMax = any.indepMin;
const int notIndepBonuses = static_cast<int>(std::count_if(bonuses.cbegin(), bonuses.cend(), [](const std::shared_ptr<Bonus>& b)
{
return b->valType != Bonus::INDEPENDENT_MAX && b->valType != Bonus::INDEPENDENT_MIN;
}));
if(notIndepBonuses)
return std::clamp(valFirst, any.indepMax, any.indepMin);
return hasIndepMin ? any.indepMin : hasIndepMax ? any.indepMax : 0;
}
std::shared_ptr<Bonus> BonusList::getFirst(const CSelector &select)
{
for (auto & b : bonuses)
{
if(select(b.get()))
return b;
}
return nullptr;
}
std::shared_ptr<const Bonus> BonusList::getFirst(const CSelector &selector) const
{
for(const auto & b : bonuses)
{
if(selector(b.get()))
return b;
}
return nullptr;
}
void BonusList::getBonuses(BonusList & out, const CSelector &selector, const CSelector &limit) const
{
out.reserve(bonuses.size());
for(const auto & b : bonuses)
{
//add matching bonuses that matches limit predicate or have NO_LIMIT if no given predicate
auto noFightLimit = b->effectRange == Bonus::NO_LIMIT;
if(selector(b.get()) && ((!limit && noFightLimit) || ((bool)limit && limit(b.get()))))
out.push_back(b);
}
}
void BonusList::getAllBonuses(BonusList &out) const
{
for(const auto & b : bonuses)
out.push_back(b);
}
int BonusList::valOfBonuses(const CSelector &select) const
{
BonusList ret;
CSelector limit = nullptr;
getBonuses(ret, select, limit);
return ret.totalValue();
}
JsonNode BonusList::toJsonNode() const
{
JsonNode node(JsonNode::JsonType::DATA_VECTOR);
for(const std::shared_ptr<Bonus> & b : bonuses)
node.Vector().push_back(b->toJsonNode());
return node;
}
void BonusList::push_back(const std::shared_ptr<Bonus> & x)
{
bonuses.push_back(x);
changed();
}
BonusList::TInternalContainer::iterator BonusList::erase(const int position)
{
changed();
return bonuses.erase(bonuses.begin() + position);
}
void BonusList::clear()
{
bonuses.clear();
changed();
}
std::vector<BonusList *>::size_type BonusList::operator-=(const std::shared_ptr<Bonus> & i)
{
auto itr = std::find(bonuses.begin(), bonuses.end(), i);
if(itr == bonuses.end())
return false;
bonuses.erase(itr);
changed();
return true;
}
void BonusList::resize(BonusList::TInternalContainer::size_type sz, const std::shared_ptr<Bonus> & c)
{
bonuses.resize(sz, c);
changed();
}
void BonusList::reserve(TInternalContainer::size_type sz)
{
bonuses.reserve(sz);
}
void BonusList::insert(BonusList::TInternalContainer::iterator position, BonusList::TInternalContainer::size_type n, const std::shared_ptr<Bonus> & x)
{
bonuses.insert(position, n, x);
changed();
}
std::string Bonus::Description(std::optional<si32> customValue) const
{
std::ostringstream str;
@ -679,16 +427,6 @@ namespace Selector
DLL_LINKAGE CSelector none([](const Bonus * b){return false;});
}
DLL_LINKAGE std::ostream & operator<<(std::ostream &out, const BonusList &bonusList)
{
for (ui32 i = 0; i < bonusList.size(); i++)
{
const auto & b = bonusList[i];
out << "Bonus " << i << "\n" << *b << std::endl;
}
return out;
}
DLL_LINKAGE std::ostream & operator<<(std::ostream &out, const Bonus &bonus)
{
for(const auto & i : bonusNameMap)

View File

@ -464,100 +464,6 @@ struct DLL_LINKAGE Bonus : public std::enable_shared_from_this<Bonus>
DLL_LINKAGE std::ostream & operator<<(std::ostream &out, const Bonus &bonus);
class DLL_LINKAGE BonusList
{
public:
using TInternalContainer = std::vector<std::shared_ptr<Bonus>>;
private:
TInternalContainer bonuses;
bool belongsToTree;
void changed() const;
public:
using const_reference = TInternalContainer::const_reference;
using value_type = TInternalContainer::value_type;
using const_iterator = TInternalContainer::const_iterator;
using iterator = TInternalContainer::iterator;
BonusList(bool BelongsToTree = false);
BonusList(const BonusList &bonusList);
BonusList(BonusList && other) noexcept;
BonusList& operator=(const BonusList &bonusList);
// wrapper functions of the STL vector container
TInternalContainer::size_type size() const { return bonuses.size(); }
void push_back(const std::shared_ptr<Bonus> & x);
TInternalContainer::iterator erase (const int position);
void clear();
bool empty() const { return bonuses.empty(); }
void resize(TInternalContainer::size_type sz, const std::shared_ptr<Bonus> & c = nullptr);
void reserve(TInternalContainer::size_type sz);
TInternalContainer::size_type capacity() const { return bonuses.capacity(); }
STRONG_INLINE std::shared_ptr<Bonus> &operator[] (TInternalContainer::size_type n) { return bonuses[n]; }
STRONG_INLINE const std::shared_ptr<Bonus> &operator[] (TInternalContainer::size_type n) const { return bonuses[n]; }
std::shared_ptr<Bonus> &back() { return bonuses.back(); }
std::shared_ptr<Bonus> &front() { return bonuses.front(); }
const std::shared_ptr<Bonus> &back() const { return bonuses.back(); }
const std::shared_ptr<Bonus> &front() const { return bonuses.front(); }
// There should be no non-const access to provide solid,robust bonus caching
TInternalContainer::const_iterator begin() const { return bonuses.begin(); }
TInternalContainer::const_iterator end() const { return bonuses.end(); }
TInternalContainer::size_type operator-=(const std::shared_ptr<Bonus> & i);
// BonusList functions
void stackBonuses();
int totalValue() const;
void getBonuses(BonusList &out, const CSelector &selector, const CSelector &limit = nullptr) const;
void getAllBonuses(BonusList &out) const;
//special find functions
std::shared_ptr<Bonus> getFirst(const CSelector &select);
std::shared_ptr<const Bonus> getFirst(const CSelector &select) const;
int valOfBonuses(const CSelector &select) const;
// conversion / output
JsonNode toJsonNode() const;
// remove_if implementation for STL vector types
template <class Predicate>
void remove_if(Predicate pred)
{
BonusList newList;
for(const auto & b : bonuses)
{
if (!pred(b.get()))
newList.push_back(b);
}
bonuses.clear();
bonuses.resize(newList.size());
std::copy(newList.begin(), newList.end(), bonuses.begin());
}
template <class InputIterator>
void insert(const int position, InputIterator first, InputIterator last);
void insert(TInternalContainer::iterator position, TInternalContainer::size_type n, const std::shared_ptr<Bonus> & x);
template <typename Handler>
void serialize(Handler &h, const int version)
{
h & static_cast<TInternalContainer&>(bonuses);
}
// C++ for range support
auto begin () -> decltype (bonuses.begin())
{
return bonuses.begin();
}
auto end () -> decltype (bonuses.end())
{
return bonuses.end();
}
};
DLL_LINKAGE std::ostream & operator<<(std::ostream &out, const BonusList &bonusList);
template<typename T>
@ -662,12 +568,4 @@ extern DLL_LINKAGE const std::map<std::string, ui16> bonusDurationMap;
extern DLL_LINKAGE const std::map<std::string, Bonus::LimitEffect> bonusLimitEffect;
extern DLL_LINKAGE const std::set<std::string> deprecatedBonusSet;
// BonusList template that requires full interface of CBonusSystemNode
template <class InputIterator>
void BonusList::insert(const int position, InputIterator first, InputIterator last)
{
bonuses.insert(bonuses.begin() + position, first, last);
changed();
}
VCMI_LIB_NAMESPACE_END

View File

@ -11,6 +11,7 @@
#include "StdInc.h"
#include "CBonusSystemNode.h"
#include "BonusList.h"
VCMI_LIB_NAMESPACE_BEGIN

View File

@ -16,6 +16,7 @@
#include "../battle/CBattleInfoCallback.h"
#include "../battle/Unit.h"
#include "../bonuses/BonusParams.h"
#include "../bonuses/BonusList.h"
#include "../serializer/JsonSerializeFormat.h"
#include "../VCMI_Lib.h"

View File

@ -11,6 +11,7 @@
#include "BonusSystem.h"
#include "../../../lib/bonuses/BonusList.h"
#include "../../../lib/bonuses/HeroBonus.h"
#include "../../../lib/bonuses/IBonusBearer.h"

View File

@ -10,6 +10,7 @@
#pragma once
#include "../../lib/bonuses/BonusList.h"
#include "../../lib/bonuses/HeroBonus.h"
#include "../../lib/bonuses/IBonusBearer.h"