1
0
mirror of https://github.com/vcmi/vcmi.git synced 2024-11-24 08:32:34 +02:00

Visual Studio 2013 Preview compile fixes:

* 0 is not convertible to std::function, nullptr should be used
* std::ref(rand) is not convertible to function<int()>, used lambdas (why we dont just pass "rand" ? )
* CFunctionList needs to be constructible from nullptr
* move constructor for CMapInfo (Visual cannot generate them :( )
* #ifdefed some stuff that is not needed anymore since cmath is updated with C99 stuff
* using std::make_unique instead of our vstd implementation

CSelector: 
* introduced a class in place of typedef
* Having an overloaded && || operators over sth that is convertible to bool… Wasn't a good idea after all. Purged the operators, replaced  with And/Or methods (chaining-style).
* constructor that is present only when constructing from class or function (SFINAE). std::function has an implicit converting constructor from T causing ambiguities (even if the overload would cause compile error in the body)
This commit is contained in:
Michał W. Urbańczyk 2013-07-02 12:08:30 +00:00
parent f82122d9be
commit 4576719abe
19 changed files with 137 additions and 109 deletions

View File

@ -627,7 +627,7 @@ AttackPossibility AttackPossibility::evaluate(const BattleAttackInfo &AttackInfo
const int remainingCounterAttacks = getValOr(state.counterAttacksLeft, enemy, enemy->counterAttacks);
const bool counterAttacksBlocked = attacker->hasBonusOfType(Bonus::BLOCKS_RETALIATION) || enemy->hasBonusOfType(Bonus::NO_RETALIATION);
const int totalAttacks = 1 + AttackInfo.attackerBonuses->getBonuses(Selector::type(Bonus::ADDITIONAL_ATTACK), (Selector::effectRange (Bonus::NO_LIMIT) || Selector::effectRange(Bonus::ONLY_MELEE_FIGHT)))->totalValue();
const int totalAttacks = 1 + AttackInfo.attackerBonuses->getBonuses(Selector::type(Bonus::ADDITIONAL_ATTACK), (Selector::effectRange (Bonus::NO_LIMIT).Or(Selector::effectRange(Bonus::ONLY_MELEE_FIGHT))))->totalValue();
AttackPossibility ap = {enemy, hex, AttackInfo, 0, 0, 0};

View File

@ -22,7 +22,7 @@
#ifndef FL_DEFS_H
#define FL_DEFS_H
#ifdef _MSC_VER
#if _MSC_VER < 1800
#ifndef NAN
static const unsigned long __nan[2] = {0xffffffff, 0x7fffffff};
#define NAN (*(const float *) __nan)

View File

@ -441,6 +441,9 @@ namespace vstd
ptr = nullptr;
}
#if _MSC_VER >= 1800
using std::make_unique;
#else
template<typename T>
std::unique_ptr<T> make_unique()
{
@ -466,6 +469,7 @@ namespace vstd
{
return std::unique_ptr<T>(new T(std::forward<Arg1>(arg1), std::forward<Arg2>(arg2), std::forward<Arg3>(arg3), std::forward<Arg4>(arg4)));
}
#endif
template <typename Container>
typename Container::const_reference circularAt(const Container &r, size_t index)

View File

@ -106,7 +106,7 @@ CCreatureWindow::CCreatureWindow(const CStackInstance &st, CreWinType Type, std:
fs += Upg;
fs += std::bind(&CCreatureWindow::close,this);
CFunctionList<void()> cfl;
cfl = std::bind(&CPlayerInterface::showYesNoDialog, LOCPLINT, CGI->generaltexth->allTexts[207], fs, 0, false, std::ref(upgResCost));
cfl = std::bind(&CPlayerInterface::showYesNoDialog, LOCPLINT, CGI->generaltexth->allTexts[207], fs, nullptr, false, std::ref(upgResCost));
upgrade = new CAdventureMapButton("",CGI->generaltexth->zelp[446].second,cfl,385, 148,"IVIEWCR.DEF",SDLK_u);
}
else
@ -248,7 +248,7 @@ void CCreatureWindow::init(const CStackInstance *Stack, const CBonusSystemNode *
}
BonusList bl, blTemp;
blTemp = (*(stackNode->getBonuses(Selector::durationType(Bonus::PERMANENT) && Selector::anyRange())));
blTemp = (*(stackNode->getBonuses(Selector::durationType(Bonus::PERMANENT).And(Selector::anyRange()))));
while (blTemp.size())
{

View File

@ -146,7 +146,7 @@ public:
CAdventureMapButton * dismiss, * upgrade, * ok;
CCreInfoWindow(const CStackInstance & st, bool LClicked, std::function<void()> Upg = 0, std::function<void()> Dsm = 0, UpgradeInfo * ui = nullptr);
CCreInfoWindow(const CStackInstance & st, bool LClicked, std::function<void()> Upg = nullptr, std::function<void()> Dsm = nullptr, UpgradeInfo * ui = nullptr);
CCreInfoWindow(const CStack & st, bool LClicked = 0);
CCreInfoWindow(int Cid, bool LClicked, int creatureCount);
~CCreInfoWindow();
@ -159,4 +159,4 @@ public:
CIntObject *createCreWindow(const CStack *s, bool lclick = false);
CIntObject *createCreWindow(CreatureID Cid, CCreatureWindow::CreWinType Type, int creatureCount);
CIntObject *createCreWindow(const CStackInstance *s, CCreatureWindow::CreWinType type, std::function<void()> Upg = 0, std::function<void()> Dsm = 0, UpgradeInfo *ui = nullptr);
CIntObject *createCreWindow(const CStackInstance *s, CCreatureWindow::CreWinType type, std::function<void()> Upg = nullptr, std::function<void()> Dsm = nullptr, UpgradeInfo *ui = nullptr);

View File

@ -33,6 +33,8 @@ public:
{
funcs.push_back(first);
}
CFunctionList(std::nullptr_t)
{}
CFunctionList & operator+=(const boost::function<Signature> &first)
{
funcs.push_back(first);

View File

@ -321,8 +321,8 @@ void CGarrisonSlot::clickLeft(tribool down, bool previousState)
bool canDismiss = getObj()->tempOwner == LOCPLINT->playerID && (getObj()->stacksCount()>1 || !getObj()->needsLastStack());
std::function<void()> upgr = nullptr;
std::function<void()> dism = nullptr;
if (canUpgrade) upgr = std::bind(&CCallback::upgradeCreature, LOCPLINT->cb.get(), getObj(), ID, pom.newID[0]);
if (canDismiss) dism = std::bind(&CCallback::dismissCreature, LOCPLINT->cb.get(), getObj(), ID);
if(canUpgrade) upgr = [=] { LOCPLINT->cb->upgradeCreature(getObj(), ID, pom.newID[0]); };
if(canDismiss) dism = [=] { LOCPLINT->cb->dismissCreature(getObj(), ID); };
owner->selectSlot(nullptr);
owner->setSplittingMode(false);

View File

@ -233,8 +233,8 @@ public:
void select(bool on);
void clickLeft(tribool down, bool previousState); //call-in
CSelectableComponent(Etype Type, int Sub, int Val, ESize imageSize=large, std::function<void()> OnSelect = 0); //c-tor
CSelectableComponent(const Component &c, std::function<void()> OnSelect = 0); //c-tor
CSelectableComponent(Etype Type, int Sub, int Val, ESize imageSize=large, std::function<void()> OnSelect = nullptr); //c-tor
CSelectableComponent(const Component &c, std::function<void()> OnSelect = nullptr); //c-tor
};
/// box with multiple components (up to 8?)
@ -269,7 +269,7 @@ public:
/// constructor for selectable components
/// will also create "or" labels between components
/// onSelect - optional function that will be called every time on selection change
CComponentBox(std::vector<CSelectableComponent *> components, Rect position, std::function<void(int newID)> onSelect = 0);
CComponentBox(std::vector<CSelectableComponent *> components, Rect position, std::function<void(int newID)> onSelect = nullptr);
};
////////////////////////////////////////////////////////////////////////////////

View File

@ -890,10 +890,10 @@ void CStack::postInit()
ui32 CStack::Speed( int turn /*= 0*/ , bool useBind /* = false*/) const
{
if(hasBonus(Selector::type(Bonus::SIEGE_WEAPON) && Selector::turns(turn))) //war machines cannot move
if(hasBonus(Selector::type(Bonus::SIEGE_WEAPON).And(Selector::turns(turn)))) //war machines cannot move
return 0;
int speed = valOfBonuses(Selector::type(Bonus::STACKS_SPEED) && Selector::turns(turn));
int speed = valOfBonuses(Selector::type(Bonus::STACKS_SPEED).And(Selector::turns(turn)));
int percentBonus = 0;
for(const Bonus *b : getBonusList())
@ -970,7 +970,7 @@ bool CStack::willMove(int turn /*= 0*/) const
bool CStack::canMove( int turn /*= 0*/ ) const
{
return alive()
&& !hasBonus(Selector::type(Bonus::NOT_ACTIVE) && Selector::turns(turn)); //eg. Ammo Cart or blinded creature
&& !hasBonus(Selector::type(Bonus::NOT_ACTIVE).And(Selector::turns(turn))); //eg. Ammo Cart or blinded creature
}
bool CStack::moved( int turn /*= 0*/ ) const

View File

@ -780,8 +780,13 @@ TDmgRange CBattleInfoCallback::calculateDmgRange(const BattleAttackInfo &info) c
{
auto battleBonusValue = [&](const IBonusBearer * bearer, CSelector selector) -> int
{
return bearer->getBonuses(selector, Selector::effectRange(Bonus::NO_LIMIT) || //any regular bonuses or just ones for melee/ranged
(info.shooting ? Selector::effectRange(Bonus::ONLY_DISTANCE_FIGHT) : Selector::effectRange(Bonus::ONLY_MELEE_FIGHT)))->totalValue();
auto noLimit = Selector::effectRange(Bonus::NO_LIMIT);
auto limitMatches = info.shooting
? Selector::effectRange(Bonus::ONLY_DISTANCE_FIGHT)
: Selector::effectRange(Bonus::ONLY_MELEE_FIGHT);
//any regular bonuses or just ones for melee/ranged
return bearer->getBonuses(selector, noLimit.Or(limitMatches))->totalValue();
};
double additiveBonus = 1.0, multBonus = 1.0,
@ -800,7 +805,7 @@ TDmgRange CBattleInfoCallback::calculateDmgRange(const BattleAttackInfo &info) c
{ //minDmg and maxDmg are multiplied by hero attack + 1
auto retreiveHeroPrimSkill = [&](int skill) -> int
{
const Bonus *b = info.attackerBonuses->getBonus(Selector::sourceTypeSel(Bonus::HERO_BASE_SKILL) && Selector::typeSubtype(Bonus::PRIMARY_SKILL, skill));
const Bonus *b = info.attackerBonuses->getBonus(Selector::sourceTypeSel(Bonus::HERO_BASE_SKILL).And(Selector::typeSubtype(Bonus::PRIMARY_SKILL, skill)));
return b ? b->val : 0; //if there is no hero or no info on his primary skill, return 0
};
@ -2103,8 +2108,11 @@ SpellID CBattleInfoCallback::getRandomBeneficialSpell(const CStack * subject) co
{
auto kingMonster = getStackIf([&](const CStack *stack) //look for enemy, non-shooting stack
{
return stack->owner != subject->owner
&& (stack->hasBonus(Selector::type(Bonus::KING1) || Selector::type(Bonus::KING2) || Selector::type(Bonus::KING3)));
const auto isKing = Selector::type(Bonus::KING1)
.Or(Selector::type(Bonus::KING2))
.Or(Selector::type(Bonus::KING3));
return stack->owner != subject->owner && stack->hasBonus(isKing);
});
if (!kingMonster)

View File

@ -184,7 +184,7 @@ public:
std::vector <std::pair <Bonus*, std::pair <ui8, ui8> > > skillRequirements; // first - Bonus, second - which two skills are needed to use it
void deserializationFix();
CreatureID pickRandomMonster(const std::function<int()> &randGen = 0, int tier = -1) const; //tier <1 - CREATURES_PER_TOWN> or -1 for any
CreatureID pickRandomMonster(const std::function<int()> &randGen = nullptr, int tier = -1) const; //tier <1 - CREATURES_PER_TOWN> or -1 for any
void addBonusForTier(int tier, Bonus *b); //tier must be <1-7>
void addBonusForAllCreatures(Bonus *b);

View File

@ -1250,7 +1250,7 @@ void CGHeroInstance::updateSkill(SecondarySkill which, int val)
bool luck = which == SecondarySkill::LUCK;
Bonus::BonusType type[] = {Bonus::MORALE, Bonus::LUCK};
Bonus *b = getBonusLocalFirst(Selector::type(type[luck]) && Selector::sourceType(Bonus::SECONDARY_SKILL));
Bonus *b = getBonusLocalFirst(Selector::type(type[luck]).And(Selector::sourceType(Bonus::SECONDARY_SKILL)));
if(!b)
{
b = new Bonus(Bonus::PERMANENT, type[luck], Bonus::SECONDARY_SKILL, +val, which, which, Bonus::BASE_NUMBER);
@ -1262,7 +1262,7 @@ void CGHeroInstance::updateSkill(SecondarySkill which, int val)
else if(which == SecondarySkill::DIPLOMACY) //surrender discount: 20% per level
{
if(Bonus *b = getBonusLocalFirst(Selector::type(Bonus::SURRENDER_DISCOUNT) && Selector::sourceType(Bonus::SECONDARY_SKILL)))
if(Bonus *b = getBonusLocalFirst(Selector::type(Bonus::SURRENDER_DISCOUNT).And(Selector::sourceType(Bonus::SECONDARY_SKILL))))
b->val = +val;
else
addNewBonus(new Bonus(Bonus::PERMANENT, Bonus::SURRENDER_DISCOUNT, Bonus::SECONDARY_SKILL, val * 20, which));
@ -1312,7 +1312,8 @@ void CGHeroInstance::updateSkill(SecondarySkill which, int val)
Bonus::ValueType skillValType = skillVal ? Bonus::BASE_NUMBER : Bonus::INDEPENDENT_MIN;
if(Bonus * b = getBonusList().getFirst(Selector::typeSubtype(Bonus::SECONDARY_SKILL_PREMY, which) && Selector::sourceType(Bonus::SECONDARY_SKILL))) //only local hero bonus
if(Bonus * b = getBonusList().getFirst(Selector::typeSubtype(Bonus::SECONDARY_SKILL_PREMY, which)
.And(Selector::sourceType(Bonus::SECONDARY_SKILL)))) //only local hero bonus
{
b->val = skillVal;
b->valType = skillValType;
@ -2090,7 +2091,7 @@ GrowthInfo CGTownInstance::getGrowthInfo(int level) const
ret.entries.push_back(GrowthInfo::Entry(VLC->generaltexth->allTexts[591], dwellingBonus));// \nExternal dwellings %+d
//other *-of-legion-like bonuses (%d to growth cumulative with grail)
TBonusListPtr bonuses = getBonuses(Selector::type(Bonus::CREATURE_GROWTH) && Selector::subtype(level));
TBonusListPtr bonuses = getBonuses(Selector::type(Bonus::CREATURE_GROWTH).And(Selector::subtype(level)));
for(const Bonus *b : *bonuses)
ret.entries.push_back(GrowthInfo::Entry(b->Description() + " %+d", b->val));
@ -2465,7 +2466,7 @@ void CGTownInstance::deserializationFix()
void CGTownInstance::updateMoraleBonusFromArmy()
{
Bonus *b = getBonusList().getFirst(Selector::sourceType(Bonus::ARMY) && Selector::type(Bonus::MORALE));
Bonus *b = getBonusList().getFirst(Selector::sourceType(Bonus::ARMY).And(Selector::type(Bonus::MORALE)));
if(!b)
{
b = new Bonus(Bonus::PERMANENT, Bonus::MORALE, Bonus::ARMY, 0, -1);
@ -7063,7 +7064,7 @@ void CArmedInstance::updateMoraleBonusFromArmy()
if(!validTypes(false)) //object not randomized, don't bother
return;
Bonus *b = getBonusList().getFirst(Selector::sourceType(Bonus::ARMY) && Selector::type(Bonus::MORALE));
Bonus *b = getBonusList().getFirst(Selector::sourceType(Bonus::ARMY).And(Selector::type(Bonus::MORALE)));
if(!b)
{
b = new Bonus(Bonus::PERMANENT, Bonus::MORALE, Bonus::ARMY, 0, -1);

View File

@ -311,7 +311,7 @@ void BonusList::insert(std::vector<Bonus*>::iterator position, std::vector<Bonus
int IBonusBearer::valOfBonuses(Bonus::BonusType type, const CSelector &selector) const
{
return valOfBonuses(Selector::type(type) && selector);
return valOfBonuses(Selector::type(type).And(selector));
}
int IBonusBearer::valOfBonuses(Bonus::BonusType type, int subtype /*= -1*/) const
@ -321,7 +321,7 @@ int IBonusBearer::valOfBonuses(Bonus::BonusType type, int subtype /*= -1*/) cons
CSelector s = Selector::type(type);
if(subtype != -1)
s = s && Selector::subtype(subtype);
s = s.And(Selector::subtype(subtype));
return valOfBonuses(s, cachingStr.str());
}
@ -344,7 +344,7 @@ bool IBonusBearer::hasBonusOfType(Bonus::BonusType type, int subtype /*= -1*/) c
CSelector s = Selector::type(type);
if(subtype != -1)
s = s && Selector::subtype(subtype);
s = s.And(Selector::subtype(subtype));
return hasBonus(s, cachingStr.str());
}
@ -451,13 +451,13 @@ ui32 IBonusBearer::getMinDamage() const
{
std::stringstream cachingStr;
cachingStr << "type_" << Bonus::CREATURE_DAMAGE << "s_0Otype_" << Bonus::CREATURE_DAMAGE << "s_1";
return valOfBonuses(Selector::typeSubtype(Bonus::CREATURE_DAMAGE, 0) || Selector::typeSubtype(Bonus::CREATURE_DAMAGE, 1), cachingStr.str());
return valOfBonuses(Selector::typeSubtype(Bonus::CREATURE_DAMAGE, 0).Or(Selector::typeSubtype(Bonus::CREATURE_DAMAGE, 1)), cachingStr.str());
}
ui32 IBonusBearer::getMaxDamage() const
{
std::stringstream cachingStr;
cachingStr << "type_" << Bonus::CREATURE_DAMAGE << "s_0Otype_" << Bonus::CREATURE_DAMAGE << "s_2";
return valOfBonuses(Selector::typeSubtype(Bonus::CREATURE_DAMAGE, 0) || Selector::typeSubtype(Bonus::CREATURE_DAMAGE, 2), cachingStr.str());
return valOfBonuses(Selector::typeSubtype(Bonus::CREATURE_DAMAGE, 0).Or(Selector::typeSubtype(Bonus::CREATURE_DAMAGE, 2)), cachingStr.str());
}
si32 IBonusBearer::manaLimit() const
@ -490,7 +490,9 @@ bool IBonusBearer::isLiving() const //TODO: theoreticaly there exists "LIVING" b
{
std::stringstream cachingStr;
cachingStr << "type_" << Bonus::UNDEAD << "s_-1Otype_" << Bonus::NON_LIVING << "s_-11type_" << Bonus::SIEGE_WEAPON; //I don't relaly get what string labels mean?
return(!hasBonus(Selector::type(Bonus::UNDEAD) || Selector::type(Bonus::NON_LIVING) || Selector::type(Bonus::SIEGE_WEAPON), cachingStr.str()));
return !hasBonus(Selector::type(Bonus::UNDEAD)
.Or(Selector::type(Bonus::NON_LIVING))
.Or(Selector::type(Bonus::SIEGE_WEAPON)), cachingStr.str());
}
const TBonusListPtr IBonusBearer::getSpellBonuses() const
@ -1171,50 +1173,43 @@ Bonus * Bonus::addPropagator(TPropagatorPtr Propagator)
return this;
}
CSelector DLL_LINKAGE operator&&(const CSelector &first, const CSelector &second)
{
return CSelectorsConjunction(first, second);
}
CSelector DLL_LINKAGE operator||(const CSelector &first, const CSelector &second)
{
return CSelectorsAlternative(first, second);
}
namespace Selector
{
DLL_LINKAGE CSelectFieldEqual<Bonus::BonusType> type(&Bonus::type, Bonus::NONE);
DLL_LINKAGE CSelectFieldEqual<TBonusSubtype> subtype(&Bonus::subtype, 0);
DLL_LINKAGE CSelectFieldEqual<si32> info(&Bonus::additionalInfo, 0);
DLL_LINKAGE CSelectFieldEqual<ui16> duration(&Bonus::duration, 0);
DLL_LINKAGE CSelectFieldEqual<Bonus::BonusSource> sourceType(&Bonus::source, Bonus::OTHER);
DLL_LINKAGE CSelectFieldEqual<Bonus::LimitEffect> effectRange(&Bonus::effectRange, Bonus::NO_LIMIT);
DLL_LINKAGE CSelectFieldEqual<Bonus::BonusType> type(&Bonus::type);
DLL_LINKAGE CSelectFieldEqual<TBonusSubtype> subtype(&Bonus::subtype);
DLL_LINKAGE CSelectFieldEqual<si32> info(&Bonus::additionalInfo);
DLL_LINKAGE CSelectFieldEqual<ui16> duration(&Bonus::duration);
DLL_LINKAGE CSelectFieldEqual<Bonus::BonusSource> sourceType(&Bonus::source);
DLL_LINKAGE CSelectFieldEqual<Bonus::LimitEffect> effectRange(&Bonus::effectRange);
DLL_LINKAGE CWillLastTurns turns;
DLL_LINKAGE CSelectFieldAny<Bonus::LimitEffect> anyRange (&Bonus::effectRange);
DLL_LINKAGE CSelectFieldEqualOrEvery<TBonusSubtype> everySubtype (&Bonus::subtype, 0);
DLL_LINKAGE CSelectFieldAny<Bonus::LimitEffect> anyRange(&Bonus::effectRange);
CSelector DLL_LINKAGE typeSubtype(Bonus::BonusType Type, TBonusSubtype Subtype)
{
return type(Type) && subtype(Subtype);
return type(Type).And(subtype(Subtype));
}
CSelector DLL_LINKAGE typeSubtypeInfo(Bonus::BonusType type, TBonusSubtype subtype, si32 info)
{
return CSelectFieldEqual<Bonus::BonusType>(&Bonus::type, type) && CSelectFieldEqual<TBonusSubtype>(&Bonus::subtype, subtype) && CSelectFieldEqual<si32>(&Bonus::additionalInfo, info);
return CSelectFieldEqual<Bonus::BonusType>(&Bonus::type)(type)
.And(CSelectFieldEqual<TBonusSubtype>(&Bonus::subtype)(subtype))
.And(CSelectFieldEqual<si32>(&Bonus::additionalInfo)(info));
}
CSelector DLL_LINKAGE source(Bonus::BonusSource source, ui32 sourceID)
{
return CSelectFieldEqual<Bonus::BonusSource>(&Bonus::source, source) && CSelectFieldEqual<ui32>(&Bonus::sid, sourceID);
return CSelectFieldEqual<Bonus::BonusSource>(&Bonus::source)(source)
.And(CSelectFieldEqual<ui32>(&Bonus::sid)(sourceID));
}
CSelector DLL_EXPORT durationType(ui16 duration)
{
return CSelectFieldEqual<ui16>(&Bonus::duration, duration);
return CSelectFieldEqual<ui16>(&Bonus::duration)(duration);
}
CSelector DLL_LINKAGE sourceTypeSel(Bonus::BonusSource source)
{
return CSelectFieldEqual<Bonus::BonusSource>(&Bonus::source, source);
return CSelectFieldEqual<Bonus::BonusSource>(&Bonus::source)(source);
}
bool DLL_LINKAGE matchesType(const CSelector &sel, Bonus::BonusType type)

View File

@ -27,7 +27,45 @@ typedef std::vector<std::pair<int,std::string> > TModDescr; //modifiers values a
typedef std::set<CBonusSystemNode*> TNodes;
typedef std::set<const CBonusSystemNode*> TCNodes;
typedef std::vector<CBonusSystemNode *> TNodesVector;
typedef std::function<bool(const Bonus*)> CSelector;
class CSelector : std::function<bool(const Bonus*)>
{
typedef std::function<bool(const Bonus*)> TBase;
public:
CSelector() {}
template<typename T>
CSelector(const T &t, //SFINAE trick -> include this c-tor in overload resolution only if parameter is class
//(includes functors, lambdas) or function. Without that VC is going mad about ambiguities.
typename std::enable_if < boost::mpl::or_ < std::is_class<T>, std::is_function<T >> ::value>::type *dummy = nullptr)
: TBase(t)
{}
CSelector(std::nullptr_t)
{}
//CSelector(std::function<bool(const Bonus*)> f) : std::function<bool(const Bonus*)>(std::move(f)) {}
CSelector And(CSelector rhs) const
{
//lambda may likely outlive "this" (it can be even a temporary) => we copy the OBJECT (not pointer)
auto thisCopy = *this;
return [thisCopy, rhs](const Bonus *b) mutable { return thisCopy(b) && rhs(b); };
}
CSelector Or(CSelector rhs) const
{
auto thisCopy = *this;
return [thisCopy, rhs](const Bonus *b) mutable { return thisCopy(b) && rhs(b); };
}
bool operator()(const Bonus *b) const
{
return TBase::operator()(b);
}
operator bool() const
{
return !!static_cast<const TBase&>(*this);
}
};
@ -694,55 +732,21 @@ inline Bonus * makeFeature(Bonus::BonusType type, ui8 duration, si16 subtype, si
return new Bonus(makeFeatureVal(type, duration, subtype, value, source, turnsRemain, additionalInfo));
}
class DLL_LINKAGE CSelectorsConjunction
{
const CSelector first, second;
public:
CSelectorsConjunction(const CSelector &First, const CSelector &Second)
:first(First), second(Second)
{
}
bool operator()(const Bonus *bonus) const
{
return first(bonus) && second(bonus);
}
};
CSelector DLL_LINKAGE operator&&(const CSelector &first, const CSelector &second);
class DLL_LINKAGE CSelectorsAlternative
{
const CSelector first, second;
public:
CSelectorsAlternative(const CSelector &First, const CSelector &Second)
:first(First), second(Second)
{
}
bool operator()(const Bonus *bonus) const
{
return first(bonus) || second(bonus);
}
};
CSelector DLL_LINKAGE operator||(const CSelector &first, const CSelector &second);
template<typename T>
class CSelectFieldEqual
{
T Bonus::*ptr;
T val;
public:
CSelectFieldEqual(T Bonus::*Ptr, const T &Val)
: ptr(Ptr), val(Val)
CSelectFieldEqual(T Bonus::*Ptr)
: ptr(Ptr)
{
}
bool operator()(const Bonus *bonus) const
CSelector operator()(const T &valueToCompareAgainst) const
{
return bonus->*ptr == val;
}
CSelectFieldEqual& operator()(const T &setVal)
{
val = setVal;
return *this;
auto ptr2 = ptr; //We need a COPY because we don't want to reference this (might be outlived by lambda)
return [ptr2, valueToCompareAgainst](const Bonus *bonus) { return bonus->*ptr2 == valueToCompareAgainst; };
}
};
@ -944,7 +948,6 @@ namespace Selector
extern DLL_LINKAGE CSelectFieldEqual<Bonus::LimitEffect> effectRange;
extern DLL_LINKAGE CWillLastTurns turns;
extern DLL_LINKAGE CSelectFieldAny<Bonus::LimitEffect> anyRange;
extern DLL_LINKAGE CSelectFieldEqualOrEvery<TBonusSubtype> everySubtype;
CSelector DLL_LINKAGE typeSubtype(Bonus::BonusType Type, TBonusSubtype Subtype);
CSelector DLL_LINKAGE typeSubtypeInfo(Bonus::BonusType type, TBonusSubtype subtype, si32 info);

View File

@ -54,7 +54,9 @@ DLL_LINKAGE void SetPrimSkill::applyGs( CGameState *gs )
if(which < PrimarySkill::EXPERIENCE)
{
Bonus *skill = hero->getBonusLocalFirst(Selector::type(Bonus::PRIMARY_SKILL) && Selector::subtype(which) && Selector::sourceType(Bonus::HERO_BASE_SKILL));
Bonus *skill = hero->getBonusLocalFirst(Selector::type(Bonus::PRIMARY_SKILL)
.And(Selector::subtype(which))
.And(Selector::sourceType(Bonus::HERO_BASE_SKILL)));
assert(skill);
if(abs)
@ -1069,7 +1071,8 @@ DLL_LINKAGE void BattleTriggerEffect::applyGs( CGameState *gs )
}
case Bonus::POISON:
{
Bonus * b = st->getBonusLocalFirst(Selector::source(Bonus::SPELL_EFFECT, 71) && Selector::type(Bonus::STACK_HEALTH));
Bonus * b = st->getBonusLocalFirst(Selector::source(Bonus::SPELL_EFFECT, 71)
.And(Selector::type(Bonus::STACK_HEALTH)));
if (b)
b->val = val;
break;
@ -1365,7 +1368,7 @@ DLL_LINKAGE void SetStackEffect::applyGs( CGameState *gs )
CStack *s = gs->curB->getStack(para.first);
if (s)
{
if (!s->hasBonus(Selector::source(Bonus::SPELL_EFFECT, spellid) && Selector::typeSubtype(para.second.type, para.second.subtype)))
if (!s->hasBonus(Selector::source(Bonus::SPELL_EFFECT, spellid).And(Selector::typeSubtype(para.second.type, para.second.subtype))))
s->addNewBonus(new Bonus(para.second));
else
actualizeEffect(s, effect);

View File

@ -342,9 +342,11 @@ void CCampaignScenario::prepareCrossoverHeroes( std::vector<CGHeroInstance *> he
{
for(int g=0; g<GameConstants::PRIMARY_SKILLS; ++g)
{
cgh->getBonusLocalFirst(Selector::type(Bonus::PRIMARY_SKILL) &&
Selector::subtype(g) && Selector::sourceType(Bonus::HERO_BASE_SKILL) )->val
= cgh->type->heroClass->primarySkillInitial[g];
auto sel = Selector::type(Bonus::PRIMARY_SKILL)
.And(Selector::subtype(g))
.And(Selector::sourceType(Bonus::HERO_BASE_SKILL));
cgh->getBonusLocalFirst(sel)->val = cgh->type->heroClass->primarySkillInitial[g];
}
}
}

View File

@ -35,6 +35,14 @@ CMapInfo::CMapInfo() : scenarioOpts(nullptr), playerAmnt(0), humanPlayers(0),
}
#define STEAL(x) x(std::move(tmp.x))
CMapInfo::CMapInfo(CMapInfo && tmp)
: STEAL(mapHeader), STEAL(campaignHeader), STEAL(scenarioOpts), STEAL(fileURI), STEAL(date),
STEAL(playerAmnt), STEAL(humanPlayers), STEAL(actualHumanPlayers), STEAL(isRandomMap)
{}
void CMapInfo::mapInit(const std::string & fname)
{
fileURI = fname;

View File

@ -31,6 +31,8 @@ public:
bool isRandomMap; // true if the map will be created randomly, false if not
CMapInfo();
CMapInfo(CMapInfo && tmp);
void mapInit(const std::string & fname);
void campaignInit();
void countPlayers();

View File

@ -1137,13 +1137,13 @@ void CGameHandler::newTurn()
n.specialWeek = NewTurn::DOUBLE_GROWTH;
if (VLC->modh->settings.ALL_CREATURES_GET_DOUBLE_MONTHS)
{
std::pair<int,CreatureID> newMonster(54, VLC->creh->pickRandomMonster(std::ref(rand)));
std::pair<int, CreatureID> newMonster(54, VLC->creh->pickRandomMonster([]{ return rand(); }));
n.creatureid = newMonster.second;
}
else if(VLC->creh->doubledCreatures.size())
{
const std::vector<CreatureID> doubledCreatures (VLC->creh->doubledCreatures.begin(), VLC->creh->doubledCreatures.end());
n.creatureid = vstd::pickRandomElementOf (doubledCreatures, std::ref(rand));
n.creatureid = vstd::pickRandomElementOf(doubledCreatures, []{ return rand(); });
}
else
{
@ -1159,7 +1159,7 @@ void CGameHandler::newTurn()
if (monthType < 25)
{
n.specialWeek = NewTurn::BONUS_GROWTH; //+5
std::pair<int, CreatureID> newMonster (54, VLC->creh->pickRandomMonster(std::ref(rand)));
std::pair<int, CreatureID> newMonster(54, VLC->creh->pickRandomMonster([]{ return rand(); }));
//TODO do not pick neutrals
n.creatureid = newMonster.second;
}
@ -3409,7 +3409,7 @@ bool CGameHandler::makeBattleAction( BattleAction &ba )
//attack
int totalAttacks = 1 + stack->getBonuses(Selector::type (Bonus::ADDITIONAL_ATTACK),
(Selector::effectRange (Bonus::NO_LIMIT) || Selector::effectRange(Bonus::ONLY_MELEE_FIGHT)))->totalValue(); //all unspicified attacks + melee attacks
(Selector::effectRange(Bonus::NO_LIMIT).Or(Selector::effectRange(Bonus::ONLY_MELEE_FIGHT))))->totalValue(); //all unspicified attacks + melee attacks
for (int i = 0; i < totalAttacks; ++i)
{
@ -3479,7 +3479,7 @@ bool CGameHandler::makeBattleAction( BattleAction &ba )
//allow more than one additional attack
int additionalAttacks = stack->getBonuses(Selector::type (Bonus::ADDITIONAL_ATTACK),
(Selector::effectRange (Bonus::NO_LIMIT) || Selector::effectRange(Bonus::ONLY_DISTANCE_FIGHT)))->totalValue();
(Selector::effectRange(Bonus::NO_LIMIT).Or(Selector::effectRange(Bonus::ONLY_DISTANCE_FIGHT))))->totalValue();
for (int i = 0; i < additionalAttacks; ++i)
{
if(
@ -4494,7 +4494,7 @@ void CGameHandler::stackTurnTrigger(const CStack * st)
if(st->hasBonusOfType(Bonus::POISON))
{
const Bonus * b = st->getBonusLocalFirst(Selector::source(Bonus::SPELL_EFFECT, SpellID::POISON) && Selector::type(Bonus::STACK_HEALTH));
const Bonus * b = st->getBonusLocalFirst(Selector::source(Bonus::SPELL_EFFECT, SpellID::POISON).And(Selector::type(Bonus::STACK_HEALTH)));
if (b) //TODO: what if not?...
{
bte.val = std::max (b->val - 10, -(st->valOfBonuses(Bonus::POISON)));