From 4576719abe136fe965e3416b6c4da1e284bbb740 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20W=2E=20Urba=C5=84czyk?= Date: Tue, 2 Jul 2013 12:08:30 +0000 Subject: [PATCH] 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, 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 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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) --- AI/BattleAI/BattleAI.cpp | 2 +- AI/FuzzyLite/defs.h | 2 +- Global.h | 4 ++ client/CCreatureWindow.cpp | 4 +- client/CCreatureWindow.h | 4 +- client/FunctionList.h | 2 + client/GUIClasses.cpp | 4 +- client/GUIClasses.h | 6 +-- lib/BattleState.cpp | 6 +-- lib/CBattleCallback.cpp | 18 +++++-- lib/CCreatureHandler.h | 2 +- lib/CObjectHandler.cpp | 13 ++--- lib/HeroBonus.cpp | 51 +++++++++--------- lib/HeroBonus.h | 89 +++++++++++++++++--------------- lib/NetPacksLib.cpp | 9 ++-- lib/mapping/CCampaignHandler.cpp | 8 +-- lib/mapping/CMapInfo.cpp | 8 +++ lib/mapping/CMapInfo.h | 2 + server/CGameHandler.cpp | 12 ++--- 19 files changed, 137 insertions(+), 109 deletions(-) diff --git a/AI/BattleAI/BattleAI.cpp b/AI/BattleAI/BattleAI.cpp index 1ece8e934..9b8d29418 100644 --- a/AI/BattleAI/BattleAI.cpp +++ b/AI/BattleAI/BattleAI.cpp @@ -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}; diff --git a/AI/FuzzyLite/defs.h b/AI/FuzzyLite/defs.h index 90a98dd07..d75906efd 100644 --- a/AI/FuzzyLite/defs.h +++ b/AI/FuzzyLite/defs.h @@ -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) diff --git a/Global.h b/Global.h index f96dbabc7..76778210c 100644 --- a/Global.h +++ b/Global.h @@ -441,6 +441,9 @@ namespace vstd ptr = nullptr; } +#if _MSC_VER >= 1800 + using std::make_unique; +#else template std::unique_ptr make_unique() { @@ -466,6 +469,7 @@ namespace vstd { return std::unique_ptr(new T(std::forward(arg1), std::forward(arg2), std::forward(arg3), std::forward(arg4))); } +#endif template typename Container::const_reference circularAt(const Container &r, size_t index) diff --git a/client/CCreatureWindow.cpp b/client/CCreatureWindow.cpp index 16224f478..ca34f712c 100644 --- a/client/CCreatureWindow.cpp +++ b/client/CCreatureWindow.cpp @@ -106,7 +106,7 @@ CCreatureWindow::CCreatureWindow(const CStackInstance &st, CreWinType Type, std: fs += Upg; fs += std::bind(&CCreatureWindow::close,this); CFunctionList 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()) { diff --git a/client/CCreatureWindow.h b/client/CCreatureWindow.h index 204eb84d7..4b2022fd4 100644 --- a/client/CCreatureWindow.h +++ b/client/CCreatureWindow.h @@ -146,7 +146,7 @@ public: CAdventureMapButton * dismiss, * upgrade, * ok; - CCreInfoWindow(const CStackInstance & st, bool LClicked, std::function Upg = 0, std::function Dsm = 0, UpgradeInfo * ui = nullptr); + CCreInfoWindow(const CStackInstance & st, bool LClicked, std::function Upg = nullptr, std::function 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 Upg = 0, std::function Dsm = 0, UpgradeInfo *ui = nullptr); +CIntObject *createCreWindow(const CStackInstance *s, CCreatureWindow::CreWinType type, std::function Upg = nullptr, std::function Dsm = nullptr, UpgradeInfo *ui = nullptr); diff --git a/client/FunctionList.h b/client/FunctionList.h index de9750899..3fcddb6ce 100644 --- a/client/FunctionList.h +++ b/client/FunctionList.h @@ -33,6 +33,8 @@ public: { funcs.push_back(first); } + CFunctionList(std::nullptr_t) + {} CFunctionList & operator+=(const boost::function &first) { funcs.push_back(first); diff --git a/client/GUIClasses.cpp b/client/GUIClasses.cpp index 5b6ac8302..ec4a025d5 100644 --- a/client/GUIClasses.cpp +++ b/client/GUIClasses.cpp @@ -321,8 +321,8 @@ void CGarrisonSlot::clickLeft(tribool down, bool previousState) bool canDismiss = getObj()->tempOwner == LOCPLINT->playerID && (getObj()->stacksCount()>1 || !getObj()->needsLastStack()); std::function upgr = nullptr; std::function 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); diff --git a/client/GUIClasses.h b/client/GUIClasses.h index 07e7de0de..5801809e7 100644 --- a/client/GUIClasses.h +++ b/client/GUIClasses.h @@ -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 OnSelect = 0); //c-tor - CSelectableComponent(const Component &c, std::function OnSelect = 0); //c-tor + CSelectableComponent(Etype Type, int Sub, int Val, ESize imageSize=large, std::function OnSelect = nullptr); //c-tor + CSelectableComponent(const Component &c, std::function 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 components, Rect position, std::function onSelect = 0); + CComponentBox(std::vector components, Rect position, std::function onSelect = nullptr); }; //////////////////////////////////////////////////////////////////////////////// diff --git a/lib/BattleState.cpp b/lib/BattleState.cpp index 2a46aaf5b..2cf4da8d7 100644 --- a/lib/BattleState.cpp +++ b/lib/BattleState.cpp @@ -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 diff --git a/lib/CBattleCallback.cpp b/lib/CBattleCallback.cpp index e4f13aa67..ae13ec580 100644 --- a/lib/CBattleCallback.cpp +++ b/lib/CBattleCallback.cpp @@ -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) diff --git a/lib/CCreatureHandler.h b/lib/CCreatureHandler.h index 32572d6fb..b5ae8fbe8 100644 --- a/lib/CCreatureHandler.h +++ b/lib/CCreatureHandler.h @@ -184,7 +184,7 @@ public: std::vector > > skillRequirements; // first - Bonus, second - which two skills are needed to use it void deserializationFix(); - CreatureID pickRandomMonster(const std::function &randGen = 0, int tier = -1) const; //tier <1 - CREATURES_PER_TOWN> or -1 for any + CreatureID pickRandomMonster(const std::function &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); diff --git a/lib/CObjectHandler.cpp b/lib/CObjectHandler.cpp index 1ec3bfb8c..7199006e0 100644 --- a/lib/CObjectHandler.cpp +++ b/lib/CObjectHandler.cpp @@ -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); diff --git a/lib/HeroBonus.cpp b/lib/HeroBonus.cpp index 2de1c2f1d..ed66f74f2 100644 --- a/lib/HeroBonus.cpp +++ b/lib/HeroBonus.cpp @@ -311,7 +311,7 @@ void BonusList::insert(std::vector::iterator position, std::vector type(&Bonus::type, Bonus::NONE); - DLL_LINKAGE CSelectFieldEqual subtype(&Bonus::subtype, 0); - DLL_LINKAGE CSelectFieldEqual info(&Bonus::additionalInfo, 0); - DLL_LINKAGE CSelectFieldEqual duration(&Bonus::duration, 0); - DLL_LINKAGE CSelectFieldEqual sourceType(&Bonus::source, Bonus::OTHER); - DLL_LINKAGE CSelectFieldEqual effectRange(&Bonus::effectRange, Bonus::NO_LIMIT); + DLL_LINKAGE CSelectFieldEqual type(&Bonus::type); + DLL_LINKAGE CSelectFieldEqual subtype(&Bonus::subtype); + DLL_LINKAGE CSelectFieldEqual info(&Bonus::additionalInfo); + DLL_LINKAGE CSelectFieldEqual duration(&Bonus::duration); + DLL_LINKAGE CSelectFieldEqual sourceType(&Bonus::source); + DLL_LINKAGE CSelectFieldEqual effectRange(&Bonus::effectRange); DLL_LINKAGE CWillLastTurns turns; - DLL_LINKAGE CSelectFieldAny anyRange (&Bonus::effectRange); - DLL_LINKAGE CSelectFieldEqualOrEvery everySubtype (&Bonus::subtype, 0); + DLL_LINKAGE CSelectFieldAny 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::type, type) && CSelectFieldEqual(&Bonus::subtype, subtype) && CSelectFieldEqual(&Bonus::additionalInfo, info); + return CSelectFieldEqual(&Bonus::type)(type) + .And(CSelectFieldEqual(&Bonus::subtype)(subtype)) + .And(CSelectFieldEqual(&Bonus::additionalInfo)(info)); } CSelector DLL_LINKAGE source(Bonus::BonusSource source, ui32 sourceID) { - return CSelectFieldEqual(&Bonus::source, source) && CSelectFieldEqual(&Bonus::sid, sourceID); + return CSelectFieldEqual(&Bonus::source)(source) + .And(CSelectFieldEqual(&Bonus::sid)(sourceID)); } CSelector DLL_EXPORT durationType(ui16 duration) { - return CSelectFieldEqual(&Bonus::duration, duration); + return CSelectFieldEqual(&Bonus::duration)(duration); } CSelector DLL_LINKAGE sourceTypeSel(Bonus::BonusSource source) { - return CSelectFieldEqual(&Bonus::source, source); + return CSelectFieldEqual(&Bonus::source)(source); } bool DLL_LINKAGE matchesType(const CSelector &sel, Bonus::BonusType type) diff --git a/lib/HeroBonus.h b/lib/HeroBonus.h index dcad82476..f5d82dbc8 100644 --- a/lib/HeroBonus.h +++ b/lib/HeroBonus.h @@ -27,7 +27,45 @@ typedef std::vector > TModDescr; //modifiers values a typedef std::set TNodes; typedef std::set TCNodes; typedef std::vector TNodesVector; -typedef std::function CSelector; + +class CSelector : std::function +{ + typedef std::function TBase; +public: + CSelector() {} + template + 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, std::is_function> ::value>::type *dummy = nullptr) + : TBase(t) + {} + + CSelector(std::nullptr_t) + {} + //CSelector(std::function f) : std::function(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(*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 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 effectRange; extern DLL_LINKAGE CWillLastTurns turns; extern DLL_LINKAGE CSelectFieldAny anyRange; - extern DLL_LINKAGE CSelectFieldEqualOrEvery everySubtype; CSelector DLL_LINKAGE typeSubtype(Bonus::BonusType Type, TBonusSubtype Subtype); CSelector DLL_LINKAGE typeSubtypeInfo(Bonus::BonusType type, TBonusSubtype subtype, si32 info); diff --git a/lib/NetPacksLib.cpp b/lib/NetPacksLib.cpp index 3bbb943ba..c9d3069c8 100644 --- a/lib/NetPacksLib.cpp +++ b/lib/NetPacksLib.cpp @@ -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); diff --git a/lib/mapping/CCampaignHandler.cpp b/lib/mapping/CCampaignHandler.cpp index 1059c22ae..4715c61fc 100644 --- a/lib/mapping/CCampaignHandler.cpp +++ b/lib/mapping/CCampaignHandler.cpp @@ -342,9 +342,11 @@ void CCampaignScenario::prepareCrossoverHeroes( std::vector he { for(int g=0; ggetBonusLocalFirst(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]; } } } diff --git a/lib/mapping/CMapInfo.cpp b/lib/mapping/CMapInfo.cpp index 783244e9d..6c2b04343 100644 --- a/lib/mapping/CMapInfo.cpp +++ b/lib/mapping/CMapInfo.cpp @@ -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; diff --git a/lib/mapping/CMapInfo.h b/lib/mapping/CMapInfo.h index 7b08d1849..927746b67 100644 --- a/lib/mapping/CMapInfo.h +++ b/lib/mapping/CMapInfo.h @@ -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(); diff --git a/server/CGameHandler.cpp b/server/CGameHandler.cpp index dd9879830..800fed01e 100644 --- a/server/CGameHandler.cpp +++ b/server/CGameHandler.cpp @@ -1137,13 +1137,13 @@ void CGameHandler::newTurn() n.specialWeek = NewTurn::DOUBLE_GROWTH; if (VLC->modh->settings.ALL_CREATURES_GET_DOUBLE_MONTHS) { - std::pair newMonster(54, VLC->creh->pickRandomMonster(std::ref(rand))); + std::pair newMonster(54, VLC->creh->pickRandomMonster([]{ return rand(); })); n.creatureid = newMonster.second; } else if(VLC->creh->doubledCreatures.size()) { const std::vector 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 newMonster (54, VLC->creh->pickRandomMonster(std::ref(rand))); + std::pair 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)));