mirror of
https://github.com/vcmi/vcmi.git
synced 2025-01-12 02:28:11 +02:00
* Replaced boost::shared_ptr with std::shared_ptr.
* Brought shared_ptr and unique_ptr and their factories (make_shared, make_unique) to the global scope. * Removed excessive usage of shared_ptr in bonus system interface. * Fixed bonus system limiters/caching interactions. That covers #823, #859 and a number of rare edge-cases. * Implemented multiple-step limiters applying, fixing hasAnotherBonusLimiter and allowing transitional dependencies between bonuses. * Bonus system should be slightly faster, since we cache limited bonuses. Some rare usages (limiting query against a foreign node) however can't use caching.
This commit is contained in:
parent
0ef1085555
commit
d0e259864e
@ -232,9 +232,9 @@ void CBattleCallback::sendRequest(const CPack* request)
|
||||
|
||||
if(waitTillRealize)
|
||||
{
|
||||
std::unique_ptr<vstd::unlock_shared_guard> unlocker; //optional, if flag set
|
||||
unique_ptr<vstd::unlock_shared_guard> unlocker; //optional, if flag set
|
||||
if(unlockGsWhenWaiting)
|
||||
unlocker = vstd::make_unique<vstd::unlock_shared_guard>(vstd::makeUnlockSharedGuard(getGsMutex()));
|
||||
unlocker = make_unique<vstd::unlock_shared_guard>(vstd::makeUnlockSharedGuard(getGsMutex()));
|
||||
|
||||
cl->waitingRequest.waitWhileTrue();
|
||||
}
|
||||
|
@ -100,11 +100,12 @@ public:
|
||||
class CCallback : public CPlayerSpecificInfoCallback, public IGameActionCallback, public CBattleCallback
|
||||
{
|
||||
private:
|
||||
CCallback(CGameState * GS, int Player, CClient *C);
|
||||
|
||||
void validatePaths(); //recalcualte paths if necessary
|
||||
|
||||
public:
|
||||
CCallback(CGameState * GS, int Player, CClient *C);
|
||||
|
||||
//client-specific functionalities (pathfinding)
|
||||
virtual bool getPath(int3 src, int3 dest, const CGHeroInstance * hero, CPath &ret); //DEPRACATED!!!
|
||||
virtual const CGPathNode *getPathInfo(int3 tile); //uses main, client pathfinder info
|
||||
|
704
Global.h
704
Global.h
@ -1,357 +1,363 @@
|
||||
#pragma once
|
||||
|
||||
// Standard include file
|
||||
// Contents:
|
||||
// Includes C/C++ libraries, STL libraries, IOStream and String libraries
|
||||
// Includes the most important boost headers
|
||||
// Defines the import + export, override and exception handling macros
|
||||
// Defines the vstd library
|
||||
// Includes the logger
|
||||
|
||||
// This file shouldn't be changed, except if there is a important header file missing which is shared among several projects.
|
||||
|
||||
/*
|
||||
* Global.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
|
||||
*
|
||||
*/
|
||||
|
||||
#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
|
||||
#include <cstdio>
|
||||
#include <stdio.h>
|
||||
#ifdef _WIN32
|
||||
#include <tchar.h>
|
||||
#else
|
||||
#include "tchar_amigaos4.h"
|
||||
#endif
|
||||
|
||||
#include <cmath>
|
||||
#include <cassert>
|
||||
#include <assert.h>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <map>
|
||||
#include <queue>
|
||||
#include <set>
|
||||
#include <utility>
|
||||
#include <numeric>
|
||||
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
#include <iomanip>
|
||||
|
||||
#include <algorithm>
|
||||
#include <memory>
|
||||
#include <cstdlib>
|
||||
|
||||
//filesystem version 3 causes problems (and it's default as of boost 1.46)
|
||||
#define BOOST_FILESYSTEM_VERSION 2
|
||||
|
||||
#include <boost/algorithm/string.hpp>
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/assign.hpp>
|
||||
#include <boost/bind.hpp>
|
||||
#include <boost/cstdint.hpp>
|
||||
#include <boost/date_time/posix_time/posix_time.hpp>
|
||||
#include <boost/filesystem.hpp>
|
||||
#include <boost/foreach.hpp>
|
||||
#include <boost/format.hpp>
|
||||
#include <boost/function.hpp>
|
||||
#include <boost/lexical_cast.hpp>
|
||||
#include <boost/logic/tribool.hpp>
|
||||
#include <boost/program_options.hpp>
|
||||
#include <boost/thread.hpp>
|
||||
#include <boost/unordered_set.hpp>
|
||||
|
||||
#ifdef ANDROID
|
||||
#include <android/log.h>
|
||||
#endif
|
||||
|
||||
// Integral data types
|
||||
typedef boost::uint64_t ui64; //unsigned int 64 bits (8 bytes)
|
||||
typedef boost::uint32_t ui32; //unsigned int 32 bits (4 bytes)
|
||||
typedef boost::uint16_t ui16; //unsigned int 16 bits (2 bytes)
|
||||
typedef boost::uint8_t ui8; //unsigned int 8 bits (1 byte)
|
||||
typedef boost::int64_t si64; //signed int 64 bits (8 bytes)
|
||||
typedef boost::int32_t si32; //signed int 32 bits (4 bytes)
|
||||
typedef boost::int16_t si16; //signed int 16 bits (2 bytes)
|
||||
typedef boost::int8_t si8; //signed int 8 bits (1 byte)
|
||||
|
||||
#ifdef __GNUC__
|
||||
#define GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__ )
|
||||
#endif
|
||||
|
||||
// Import + Export macro declarations
|
||||
#ifdef _WIN32
|
||||
#define DLL_EXPORT __declspec(dllexport)
|
||||
#else
|
||||
#if defined(__GNUC__) && GCC_VERSION >= 400
|
||||
#define DLL_EXPORT __attribute__ ((visibility("default")))
|
||||
#else
|
||||
#define DLL_EXPORT
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
#define DLL_IMPORT __declspec(dllimport)
|
||||
#else
|
||||
#if defined(__GNUC__) && GCC_VERSION >= 400
|
||||
#define DLL_IMPORT __attribute__ ((visibility("default")))
|
||||
#else
|
||||
#define DLL_IMPORT
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef VCMI_DLL
|
||||
#define DLL_LINKAGE DLL_EXPORT
|
||||
#else
|
||||
#define DLL_LINKAGE DLL_IMPORT
|
||||
#endif
|
||||
|
||||
//defining available c++11 features
|
||||
|
||||
//initialization lists - only gcc-4.4 or later
|
||||
#if defined(__GNUC__) && (GCC_VERSION >= 404)
|
||||
#define CPP11_USE_INITIALIZERS_LIST
|
||||
#endif
|
||||
|
||||
//nullptr - only msvc and gcc-4.6 or later, othervice define it as NULL
|
||||
#if !defined(_MSC_VER) && !(defined(__GNUC__) && (GCC_VERSION >= 406))
|
||||
#define nullptr NULL
|
||||
#endif
|
||||
|
||||
//override keyword - only msvc and gcc-4.7 or later.
|
||||
#if !defined(_MSC_VER) && !(defined(__GNUC__) && (GCC_VERSION >= 407))
|
||||
#define override
|
||||
#endif
|
||||
|
||||
//workaround to support existing code
|
||||
#define OVERRIDE override
|
||||
|
||||
//a normal std::map with a const operator[] for sanity
|
||||
template<typename KeyT, typename ValT>
|
||||
class bmap : public std::map<KeyT, ValT>
|
||||
{
|
||||
public:
|
||||
const ValT & operator[](KeyT key) const
|
||||
{
|
||||
return find(key)->second;
|
||||
}
|
||||
ValT & operator[](KeyT key)
|
||||
{
|
||||
return static_cast<std::map<KeyT, ValT> &>(*this)[key];
|
||||
}
|
||||
template <typename Handler> void serialize(Handler &h, const int version)
|
||||
{
|
||||
h & static_cast<std::map<KeyT, ValT> &>(*this);
|
||||
}
|
||||
};
|
||||
|
||||
namespace vstd
|
||||
{
|
||||
//returns true if container c contains item i
|
||||
template <typename Container, typename Item>
|
||||
bool contains(const Container & c, const Item &i)
|
||||
{
|
||||
return std::find(c.begin(),c.end(),i) != c.end();
|
||||
}
|
||||
|
||||
//returns true if map c contains item i
|
||||
template <typename V, typename Item, typename Item2>
|
||||
bool contains(const std::map<Item,V> & c, const Item2 &i)
|
||||
{
|
||||
return c.find(i)!=c.end();
|
||||
}
|
||||
|
||||
//returns true if bmap c contains item i
|
||||
template <typename V, typename Item, typename Item2>
|
||||
bool contains(const bmap<Item,V> & c, const Item2 &i)
|
||||
{
|
||||
return c.find(i)!=c.end();
|
||||
}
|
||||
|
||||
//returns true if unordered set c contains item i
|
||||
template <typename Item>
|
||||
bool contains(const boost::unordered_set<Item> & c, const Item &i)
|
||||
{
|
||||
return c.find(i)!=c.end();
|
||||
}
|
||||
|
||||
//returns position of first element in vector c equal to s, if there is no such element, -1 is returned
|
||||
template <typename T1, typename T2>
|
||||
int find_pos(const std::vector<T1> & c, const T2 &s)
|
||||
{
|
||||
for(size_t i=0; i < c.size(); ++i)
|
||||
if(c[i] == s)
|
||||
return i;
|
||||
return -1;
|
||||
}
|
||||
|
||||
//Func(T1,T2) must say if these elements matches
|
||||
template <typename T1, typename T2, typename Func>
|
||||
int find_pos(const std::vector<T1> & c, const T2 &s, const Func &f)
|
||||
{
|
||||
for(size_t i=0; i < c.size(); ++i)
|
||||
if(f(c[i],s))
|
||||
return i;
|
||||
return -1;
|
||||
}
|
||||
|
||||
//returns iterator to the given element if present in container, end() if not
|
||||
template <typename Container, typename Item>
|
||||
typename Container::iterator find(Container & c, const Item &i)
|
||||
{
|
||||
return std::find(c.begin(),c.end(),i);
|
||||
}
|
||||
|
||||
//returns const iterator to the given element if present in container, end() if not
|
||||
template <typename Container, typename Item>
|
||||
typename Container::const_iterator find(const Container & c, const Item &i)
|
||||
{
|
||||
return std::find(c.begin(),c.end(),i);
|
||||
}
|
||||
|
||||
//removes element i from container c, returns false if c does not contain i
|
||||
template <typename Container, typename Item>
|
||||
typename Container::size_type operator-=(Container &c, const Item &i)
|
||||
{
|
||||
typename Container::iterator itr = find(c,i);
|
||||
if(itr == c.end())
|
||||
return false;
|
||||
c.erase(itr);
|
||||
return true;
|
||||
}
|
||||
|
||||
//assigns greater of (a, b) to a and returns maximum of (a, b)
|
||||
template <typename t1, typename t2>
|
||||
t1 &amax(t1 &a, const t2 &b)
|
||||
{
|
||||
if(a >= b)
|
||||
return a;
|
||||
else
|
||||
{
|
||||
a = b;
|
||||
return a;
|
||||
}
|
||||
}
|
||||
|
||||
//assigns smaller of (a, b) to a and returns minimum of (a, b)
|
||||
template <typename t1, typename t2>
|
||||
t1 &amin(t1 &a, const t2 &b)
|
||||
{
|
||||
if(a <= b)
|
||||
return a;
|
||||
else
|
||||
{
|
||||
a = b;
|
||||
return a;
|
||||
}
|
||||
}
|
||||
|
||||
//makes a to fit the range <b, c>
|
||||
template <typename t1, typename t2, typename t3>
|
||||
t1 &abetween(t1 &a, const t2 &b, const t3 &c)
|
||||
{
|
||||
amax(a,b);
|
||||
amin(a,c);
|
||||
return a;
|
||||
}
|
||||
|
||||
//checks if a is between b and c
|
||||
template <typename t1, typename t2, typename t3>
|
||||
bool isbetween(const t1 &a, const t2 &b, const t3 &c)
|
||||
{
|
||||
return a > b && a < c;
|
||||
}
|
||||
|
||||
//checks if a is within b and c
|
||||
template <typename t1, typename t2, typename t3>
|
||||
bool iswithin(const t1 &a, const t2 &b, const t3 &c)
|
||||
{
|
||||
return a >= b && a <= c;
|
||||
}
|
||||
|
||||
template <typename t1, typename t2>
|
||||
struct assigner
|
||||
{
|
||||
public:
|
||||
t1 &op1;
|
||||
t2 op2;
|
||||
assigner(t1 &a1, const t2 & a2)
|
||||
:op1(a1), op2(a2)
|
||||
{}
|
||||
void operator()()
|
||||
{
|
||||
op1 = op2;
|
||||
}
|
||||
};
|
||||
|
||||
// Assigns value a2 to a1. The point of time of the real operation can be controlled
|
||||
// with the () operator.
|
||||
template <typename t1, typename t2>
|
||||
assigner<t1,t2> assigno(t1 &a1, const t2 &a2)
|
||||
{
|
||||
return assigner<t1,t2>(a1,a2);
|
||||
}
|
||||
|
||||
//deleted pointer and sets it to NULL
|
||||
template <typename T>
|
||||
void clear_pointer(T* &ptr)
|
||||
{
|
||||
delete ptr;
|
||||
ptr = NULL;
|
||||
}
|
||||
|
||||
#pragma once
|
||||
|
||||
// Standard include file
|
||||
// Contents:
|
||||
// Includes C/C++ libraries, STL libraries, IOStream and String libraries
|
||||
// Includes the most important boost headers
|
||||
// Defines the import + export, override and exception handling macros
|
||||
// Defines the vstd library
|
||||
// Includes the logger
|
||||
|
||||
// This file shouldn't be changed, except if there is a important header file missing which is shared among several projects.
|
||||
|
||||
/*
|
||||
* Global.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
|
||||
*
|
||||
*/
|
||||
|
||||
#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
|
||||
#include <cstdio>
|
||||
#include <stdio.h>
|
||||
#ifdef _WIN32
|
||||
#include <tchar.h>
|
||||
#else
|
||||
#include "tchar_amigaos4.h"
|
||||
#endif
|
||||
|
||||
#include <cmath>
|
||||
#include <cassert>
|
||||
#include <assert.h>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <map>
|
||||
#include <queue>
|
||||
#include <set>
|
||||
#include <utility>
|
||||
#include <numeric>
|
||||
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
#include <iomanip>
|
||||
|
||||
#include <algorithm>
|
||||
#include <memory>
|
||||
#include <cstdlib>
|
||||
|
||||
//filesystem version 3 causes problems (and it's default as of boost 1.46)
|
||||
#define BOOST_FILESYSTEM_VERSION 2
|
||||
|
||||
#include <boost/algorithm/string.hpp>
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/assign.hpp>
|
||||
#include <boost/bind.hpp>
|
||||
#include <boost/cstdint.hpp>
|
||||
#include <boost/date_time/posix_time/posix_time.hpp>
|
||||
#include <boost/filesystem.hpp>
|
||||
#include <boost/foreach.hpp>
|
||||
#include <boost/format.hpp>
|
||||
#include <boost/function.hpp>
|
||||
#include <boost/lexical_cast.hpp>
|
||||
#include <boost/logic/tribool.hpp>
|
||||
#include <boost/program_options.hpp>
|
||||
#include <boost/thread.hpp>
|
||||
#include <boost/unordered_set.hpp>
|
||||
|
||||
#ifdef ANDROID
|
||||
#include <android/log.h>
|
||||
#endif
|
||||
|
||||
// Integral data types
|
||||
typedef boost::uint64_t ui64; //unsigned int 64 bits (8 bytes)
|
||||
typedef boost::uint32_t ui32; //unsigned int 32 bits (4 bytes)
|
||||
typedef boost::uint16_t ui16; //unsigned int 16 bits (2 bytes)
|
||||
typedef boost::uint8_t ui8; //unsigned int 8 bits (1 byte)
|
||||
typedef boost::int64_t si64; //signed int 64 bits (8 bytes)
|
||||
typedef boost::int32_t si32; //signed int 32 bits (4 bytes)
|
||||
typedef boost::int16_t si16; //signed int 16 bits (2 bytes)
|
||||
typedef boost::int8_t si8; //signed int 8 bits (1 byte)
|
||||
|
||||
#ifdef __GNUC__
|
||||
#define GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__ )
|
||||
#endif
|
||||
|
||||
// Import + Export macro declarations
|
||||
#ifdef _WIN32
|
||||
#define DLL_EXPORT __declspec(dllexport)
|
||||
#else
|
||||
#if defined(__GNUC__) && GCC_VERSION >= 400
|
||||
#define DLL_EXPORT __attribute__ ((visibility("default")))
|
||||
#else
|
||||
#define DLL_EXPORT
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
#define DLL_IMPORT __declspec(dllimport)
|
||||
#else
|
||||
#if defined(__GNUC__) && GCC_VERSION >= 400
|
||||
#define DLL_IMPORT __attribute__ ((visibility("default")))
|
||||
#else
|
||||
#define DLL_IMPORT
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef VCMI_DLL
|
||||
#define DLL_LINKAGE DLL_EXPORT
|
||||
#else
|
||||
#define DLL_LINKAGE DLL_IMPORT
|
||||
#endif
|
||||
|
||||
//defining available c++11 features
|
||||
|
||||
//initialization lists - only gcc-4.4 or later
|
||||
#if defined(__GNUC__) && (GCC_VERSION >= 404)
|
||||
#define CPP11_USE_INITIALIZERS_LIST
|
||||
#endif
|
||||
|
||||
//nullptr - only msvc and gcc-4.6 or later, othervice define it as NULL
|
||||
#if !defined(_MSC_VER) && !(defined(__GNUC__) && (GCC_VERSION >= 406))
|
||||
#define nullptr NULL
|
||||
#endif
|
||||
|
||||
//override keyword - only msvc and gcc-4.7 or later.
|
||||
#if !defined(_MSC_VER) && !(defined(__GNUC__) && (GCC_VERSION >= 407))
|
||||
#define override
|
||||
#endif
|
||||
|
||||
//workaround to support existing code
|
||||
#define OVERRIDE override
|
||||
|
||||
//a normal std::map with a const operator[] for sanity
|
||||
template<typename KeyT, typename ValT>
|
||||
class bmap : public std::map<KeyT, ValT>
|
||||
{
|
||||
public:
|
||||
const ValT & operator[](KeyT key) const
|
||||
{
|
||||
return find(key)->second;
|
||||
}
|
||||
ValT & operator[](KeyT key)
|
||||
{
|
||||
return static_cast<std::map<KeyT, ValT> &>(*this)[key];
|
||||
}
|
||||
template <typename Handler> void serialize(Handler &h, const int version)
|
||||
{
|
||||
h & static_cast<std::map<KeyT, ValT> &>(*this);
|
||||
}
|
||||
};
|
||||
|
||||
namespace vstd
|
||||
{
|
||||
//returns true if container c contains item i
|
||||
template <typename Container, typename Item>
|
||||
bool contains(const Container & c, const Item &i)
|
||||
{
|
||||
return std::find(c.begin(),c.end(),i) != c.end();
|
||||
}
|
||||
|
||||
//returns true if map c contains item i
|
||||
template <typename V, typename Item, typename Item2>
|
||||
bool contains(const std::map<Item,V> & c, const Item2 &i)
|
||||
{
|
||||
return c.find(i)!=c.end();
|
||||
}
|
||||
|
||||
//returns true if bmap c contains item i
|
||||
template <typename V, typename Item, typename Item2>
|
||||
bool contains(const bmap<Item,V> & c, const Item2 &i)
|
||||
{
|
||||
return c.find(i)!=c.end();
|
||||
}
|
||||
|
||||
//returns true if unordered set c contains item i
|
||||
template <typename Item>
|
||||
bool contains(const boost::unordered_set<Item> & c, const Item &i)
|
||||
{
|
||||
return c.find(i)!=c.end();
|
||||
}
|
||||
|
||||
//returns position of first element in vector c equal to s, if there is no such element, -1 is returned
|
||||
template <typename T1, typename T2>
|
||||
int find_pos(const std::vector<T1> & c, const T2 &s)
|
||||
{
|
||||
for(size_t i=0; i < c.size(); ++i)
|
||||
if(c[i] == s)
|
||||
return i;
|
||||
return -1;
|
||||
}
|
||||
|
||||
//Func(T1,T2) must say if these elements matches
|
||||
template <typename T1, typename T2, typename Func>
|
||||
int find_pos(const std::vector<T1> & c, const T2 &s, const Func &f)
|
||||
{
|
||||
for(size_t i=0; i < c.size(); ++i)
|
||||
if(f(c[i],s))
|
||||
return i;
|
||||
return -1;
|
||||
}
|
||||
|
||||
//returns iterator to the given element if present in container, end() if not
|
||||
template <typename Container, typename Item>
|
||||
typename Container::iterator find(Container & c, const Item &i)
|
||||
{
|
||||
return std::find(c.begin(),c.end(),i);
|
||||
}
|
||||
|
||||
//returns const iterator to the given element if present in container, end() if not
|
||||
template <typename Container, typename Item>
|
||||
typename Container::const_iterator find(const Container & c, const Item &i)
|
||||
{
|
||||
return std::find(c.begin(),c.end(),i);
|
||||
}
|
||||
|
||||
//removes element i from container c, returns false if c does not contain i
|
||||
template <typename Container, typename Item>
|
||||
typename Container::size_type operator-=(Container &c, const Item &i)
|
||||
{
|
||||
typename Container::iterator itr = find(c,i);
|
||||
if(itr == c.end())
|
||||
return false;
|
||||
c.erase(itr);
|
||||
return true;
|
||||
}
|
||||
|
||||
//assigns greater of (a, b) to a and returns maximum of (a, b)
|
||||
template <typename t1, typename t2>
|
||||
t1 &amax(t1 &a, const t2 &b)
|
||||
{
|
||||
if(a >= b)
|
||||
return a;
|
||||
else
|
||||
{
|
||||
a = b;
|
||||
return a;
|
||||
}
|
||||
}
|
||||
|
||||
//assigns smaller of (a, b) to a and returns minimum of (a, b)
|
||||
template <typename t1, typename t2>
|
||||
t1 &amin(t1 &a, const t2 &b)
|
||||
{
|
||||
if(a <= b)
|
||||
return a;
|
||||
else
|
||||
{
|
||||
a = b;
|
||||
return a;
|
||||
}
|
||||
}
|
||||
|
||||
//makes a to fit the range <b, c>
|
||||
template <typename t1, typename t2, typename t3>
|
||||
t1 &abetween(t1 &a, const t2 &b, const t3 &c)
|
||||
{
|
||||
amax(a,b);
|
||||
amin(a,c);
|
||||
return a;
|
||||
}
|
||||
|
||||
//checks if a is between b and c
|
||||
template <typename t1, typename t2, typename t3>
|
||||
bool isbetween(const t1 &a, const t2 &b, const t3 &c)
|
||||
{
|
||||
return a > b && a < c;
|
||||
}
|
||||
|
||||
//checks if a is within b and c
|
||||
template <typename t1, typename t2, typename t3>
|
||||
bool iswithin(const t1 &a, const t2 &b, const t3 &c)
|
||||
{
|
||||
return a >= b && a <= c;
|
||||
}
|
||||
|
||||
template <typename t1, typename t2>
|
||||
struct assigner
|
||||
{
|
||||
public:
|
||||
t1 &op1;
|
||||
t2 op2;
|
||||
assigner(t1 &a1, const t2 & a2)
|
||||
:op1(a1), op2(a2)
|
||||
{}
|
||||
void operator()()
|
||||
{
|
||||
op1 = op2;
|
||||
}
|
||||
};
|
||||
|
||||
// Assigns value a2 to a1. The point of time of the real operation can be controlled
|
||||
// with the () operator.
|
||||
template <typename t1, typename t2>
|
||||
assigner<t1,t2> assigno(t1 &a1, const t2 &a2)
|
||||
{
|
||||
return assigner<t1,t2>(a1,a2);
|
||||
}
|
||||
|
||||
//deleted pointer and sets it to NULL
|
||||
template <typename T>
|
||||
void clear_pointer(T* &ptr)
|
||||
{
|
||||
delete ptr;
|
||||
ptr = NULL;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
std::unique_ptr<T> make_unique()
|
||||
{
|
||||
return std::unique_ptr<T>(new T());
|
||||
}
|
||||
}
|
||||
template<typename T, typename Arg1>
|
||||
std::unique_ptr<T> make_unique(Arg1&& arg1)
|
||||
{
|
||||
return std::unique_ptr<T>(new T(std::forward<Arg1>(arg1)));
|
||||
}
|
||||
}
|
||||
using vstd::operator-=;
|
||||
|
||||
// can be used for counting arrays
|
||||
template<typename T, size_t N> char (&_ArrayCountObj(const T (&)[N]))[N];
|
||||
#define ARRAY_COUNT(arr) (sizeof(_ArrayCountObj(arr)))
|
||||
|
||||
//XXX pls dont - 'debug macros' are usually more trouble than it's worth
|
||||
#define HANDLE_EXCEPTION \
|
||||
catch (const std::exception& e) { \
|
||||
tlog1 << e.what() << std::endl; \
|
||||
throw; \
|
||||
} \
|
||||
catch (const std::exception * e) \
|
||||
{ \
|
||||
tlog1 << e->what()<< std::endl; \
|
||||
throw; \
|
||||
} \
|
||||
catch (const std::string& e) { \
|
||||
tlog1 << e << std::endl; \
|
||||
throw; \
|
||||
}
|
||||
|
||||
#define HANDLE_EXCEPTIONC(COMMAND) \
|
||||
catch (const std::exception& e) { \
|
||||
COMMAND; \
|
||||
tlog1 << e.what() << std::endl; \
|
||||
throw; \
|
||||
} \
|
||||
catch (const std::string &e) \
|
||||
{ \
|
||||
COMMAND; \
|
||||
tlog1 << e << std::endl; \
|
||||
throw; \
|
||||
}
|
||||
|
||||
|
||||
#include "lib/CLogger.h"
|
||||
}
|
||||
}
|
||||
|
||||
using std::shared_ptr;
|
||||
using std::unique_ptr;
|
||||
using std::make_shared;
|
||||
using vstd::make_unique;
|
||||
|
||||
using vstd::operator-=;
|
||||
|
||||
// can be used for counting arrays
|
||||
template<typename T, size_t N> char (&_ArrayCountObj(const T (&)[N]))[N];
|
||||
#define ARRAY_COUNT(arr) (sizeof(_ArrayCountObj(arr)))
|
||||
|
||||
//XXX pls dont - 'debug macros' are usually more trouble than it's worth
|
||||
#define HANDLE_EXCEPTION \
|
||||
catch (const std::exception& e) { \
|
||||
tlog1 << e.what() << std::endl; \
|
||||
throw; \
|
||||
} \
|
||||
catch (const std::exception * e) \
|
||||
{ \
|
||||
tlog1 << e->what()<< std::endl; \
|
||||
throw; \
|
||||
} \
|
||||
catch (const std::string& e) { \
|
||||
tlog1 << e << std::endl; \
|
||||
throw; \
|
||||
}
|
||||
|
||||
#define HANDLE_EXCEPTIONC(COMMAND) \
|
||||
catch (const std::exception& e) { \
|
||||
COMMAND; \
|
||||
tlog1 << e.what() << std::endl; \
|
||||
throw; \
|
||||
} \
|
||||
catch (const std::string &e) \
|
||||
{ \
|
||||
COMMAND; \
|
||||
tlog1 << e << std::endl; \
|
||||
throw; \
|
||||
}
|
||||
|
||||
|
||||
#include "lib/CLogger.h"
|
||||
|
@ -145,8 +145,8 @@ private:
|
||||
SettingsListener listener;
|
||||
void onVolumeChange(const JsonNode &volumeNode);
|
||||
|
||||
std::unique_ptr<MusicEntry> current;
|
||||
std::unique_ptr<MusicEntry> next;
|
||||
unique_ptr<MusicEntry> current;
|
||||
unique_ptr<MusicEntry> next;
|
||||
|
||||
void queueNext(MusicEntry *queued);
|
||||
public:
|
||||
|
@ -367,7 +367,7 @@ void CClient::newGame( CConnection *con, StartInfo *si )
|
||||
|
||||
if(si->mode != StartInfo::DUEL)
|
||||
{
|
||||
CCallback *cb = new CCallback(gs,color,this);
|
||||
auto cb = make_shared<CCallback>(gs,color,this);
|
||||
if(!it->second.human)
|
||||
{
|
||||
std::string AItoGive = settings["server"]["playerAI"].String();
|
||||
@ -385,8 +385,8 @@ void CClient::newGame( CConnection *con, StartInfo *si )
|
||||
}
|
||||
battleints[color] = playerint[color];
|
||||
|
||||
playerint[color]->init(cb);
|
||||
callbacks[color] = boost::shared_ptr<CCallback>(cb);
|
||||
playerint[color]->init(cb.get());
|
||||
callbacks[color] = cb;
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -473,7 +473,7 @@ void CClient::serialize( Handler &h, const int version )
|
||||
else
|
||||
nInt = new CPlayerInterface(pid);
|
||||
|
||||
callbacks[pid] = boost::shared_ptr<CCallback>(new CCallback(gs,pid,this));
|
||||
callbacks[pid] = make_shared<CCallback>(gs,pid,this);
|
||||
battleints[pid] = playerint[pid] = nInt;
|
||||
nInt->init(callbacks[pid].get());
|
||||
nInt->serialize(h, version);
|
||||
|
@ -61,7 +61,7 @@ class CClient : public IGameCallback
|
||||
{
|
||||
public:
|
||||
CCallback *cb;
|
||||
std::map<ui8,boost::shared_ptr<CCallback> > callbacks; //callbacks given to player interfaces
|
||||
std::map<ui8,shared_ptr<CCallback> > callbacks; //callbacks given to player interfaces
|
||||
std::vector<IGameEventsReceiver*> privilagedGameEventReceivers; //scripting modules, spectator interfaces
|
||||
std::vector<IBattleEventsReceiver*> privilagedBattleEventReceivers; //scripting modules, spectator interfaces
|
||||
std::map<ui8,CGameInterface *> playerint;
|
||||
|
@ -1727,19 +1727,19 @@ BattleInfo * BattleInfo::setupBattle( int3 tile, int terrain, int terType, const
|
||||
|
||||
case 18: //holy ground
|
||||
{
|
||||
curB->addNewBonus(makeFeature(Bonus::MORALE, Bonus::ONE_BATTLE, 0, +1, Bonus::TERRAIN_OVERLAY)->addLimiter(new CreatureAlignmentLimiter(EAlignment::GOOD)));
|
||||
curB->addNewBonus(makeFeature(Bonus::MORALE, Bonus::ONE_BATTLE, 0, -1, Bonus::TERRAIN_OVERLAY)->addLimiter(new CreatureAlignmentLimiter(EAlignment::EVIL)));
|
||||
curB->addNewBonus(makeFeature(Bonus::MORALE, Bonus::ONE_BATTLE, 0, +1, Bonus::TERRAIN_OVERLAY)->addLimiter(make_shared<CreatureAlignmentLimiter>(EAlignment::GOOD)));
|
||||
curB->addNewBonus(makeFeature(Bonus::MORALE, Bonus::ONE_BATTLE, 0, -1, Bonus::TERRAIN_OVERLAY)->addLimiter(make_shared<CreatureAlignmentLimiter>(EAlignment::EVIL)));
|
||||
break;
|
||||
}
|
||||
case 19: //clover field
|
||||
{ //+2 luck bonus for neutral creatures
|
||||
curB->addNewBonus(makeFeature(Bonus::LUCK, Bonus::ONE_BATTLE, 0, +2, Bonus::TERRAIN_OVERLAY)->addLimiter(new CreatureFactionLimiter(-1)));
|
||||
curB->addNewBonus(makeFeature(Bonus::LUCK, Bonus::ONE_BATTLE, 0, +2, Bonus::TERRAIN_OVERLAY)->addLimiter(make_shared<CreatureFactionLimiter>(-1)));
|
||||
break;
|
||||
}
|
||||
case 20: //evil fog
|
||||
{
|
||||
curB->addNewBonus(makeFeature(Bonus::MORALE, Bonus::ONE_BATTLE, 0, -1, Bonus::TERRAIN_OVERLAY)->addLimiter(new CreatureAlignmentLimiter(EAlignment::GOOD)));
|
||||
curB->addNewBonus(makeFeature(Bonus::MORALE, Bonus::ONE_BATTLE, 0, +1, Bonus::TERRAIN_OVERLAY)->addLimiter(new CreatureAlignmentLimiter(EAlignment::EVIL)));
|
||||
curB->addNewBonus(makeFeature(Bonus::MORALE, Bonus::ONE_BATTLE, 0, -1, Bonus::TERRAIN_OVERLAY)->addLimiter(make_shared<CreatureAlignmentLimiter>(EAlignment::GOOD)));
|
||||
curB->addNewBonus(makeFeature(Bonus::MORALE, Bonus::ONE_BATTLE, 0, +1, Bonus::TERRAIN_OVERLAY)->addLimiter(make_shared<CreatureAlignmentLimiter>(EAlignment::EVIL)));
|
||||
break;
|
||||
}
|
||||
case 22: //cursed ground
|
||||
@ -1758,7 +1758,7 @@ BattleInfo * BattleInfo::setupBattle( int3 tile, int terrain, int terType, const
|
||||
if(town) //during siege always take premies for native terrain of faction
|
||||
terrain = VLC->heroh->nativeTerrains[town->town->typeID];
|
||||
|
||||
boost::shared_ptr<ILimiter> nativeTerrain(new CreatureNativeTerrainLimiter(terrain));
|
||||
auto nativeTerrain = make_shared<CreatureNativeTerrainLimiter>(terrain);
|
||||
curB->addNewBonus(makeFeature(Bonus::STACKS_SPEED, Bonus::ONE_BATTLE, 0, 1, Bonus::TERRAIN_NATIVE)->addLimiter(nativeTerrain));
|
||||
curB->addNewBonus(makeFeature(Bonus::PRIMARY_SKILL, Bonus::ONE_BATTLE, PrimarySkill::ATTACK, 1, Bonus::TERRAIN_NATIVE)->addLimiter(nativeTerrain));
|
||||
curB->addNewBonus(makeFeature(Bonus::PRIMARY_SKILL, Bonus::ONE_BATTLE, PrimarySkill::DEFENSE, 1, Bonus::TERRAIN_NATIVE)->addLimiter(nativeTerrain));
|
||||
|
@ -363,7 +363,7 @@ void CCreatureHandler::loadCreatures()
|
||||
if(boost::algorithm::find_first(ncre.abilityRefs, "const_raises_morale"))
|
||||
{
|
||||
ncre.addBonus(+1, Bonus::MORALE);;
|
||||
ncre.getBonusList().back()->addPropagator(new CPropagatorNodeType(CBonusSystemNode::HERO));
|
||||
ncre.getBonusList().back()->addPropagator(make_shared<CPropagatorNodeType>(CBonusSystemNode::HERO));
|
||||
}
|
||||
if(boost::algorithm::find_first(ncre.abilityRefs, "const_lowers_morale"))
|
||||
{
|
||||
|
@ -2274,9 +2274,9 @@ void CGTownInstance::deserializationFix()
|
||||
|
||||
void CGTownInstance::recreateBuildingsBonuses()
|
||||
{
|
||||
TBonusListPtr bl(new BonusList);
|
||||
BonusList bl;
|
||||
getExportedBonusList().getBonuses(bl, Selector::sourceType(Bonus::TOWN_STRUCTURE));
|
||||
BOOST_FOREACH(Bonus *b, *bl)
|
||||
BOOST_FOREACH(Bonus *b, bl)
|
||||
removeBonus(b);
|
||||
|
||||
|
||||
@ -2285,13 +2285,13 @@ void CGTownInstance::recreateBuildingsBonuses()
|
||||
|
||||
if(subID == 0) //castle
|
||||
{
|
||||
addBonusIfBuilt(17, Bonus::SEA_MOVEMENT, +500, new CPropagatorNodeType(PLAYER)); //lighthouses
|
||||
addBonusIfBuilt(26, Bonus::MORALE, +2, new CPropagatorNodeType(PLAYER)); //colossus
|
||||
addBonusIfBuilt(17, Bonus::SEA_MOVEMENT, +500, make_shared<CPropagatorNodeType>(PLAYER)); //lighthouses
|
||||
addBonusIfBuilt(26, Bonus::MORALE, +2, make_shared<CPropagatorNodeType>(PLAYER)); //colossus
|
||||
}
|
||||
else if(subID == 1) //rampart
|
||||
{
|
||||
addBonusIfBuilt(21, Bonus::LUCK, +2); //fountain of fortune
|
||||
addBonusIfBuilt(21, Bonus::LUCK, +2, new CPropagatorNodeType(PLAYER)); //guardian spirit
|
||||
addBonusIfBuilt(21, Bonus::LUCK, +2, make_shared<CPropagatorNodeType>(PLAYER)); //guardian spirit
|
||||
}
|
||||
else if(subID == 2) //tower
|
||||
{
|
||||
@ -2304,8 +2304,8 @@ void CGTownInstance::recreateBuildingsBonuses()
|
||||
else if(subID == 4) //necropolis
|
||||
{
|
||||
addBonusIfBuilt(17, Bonus::DARKNESS, +20);
|
||||
addBonusIfBuilt(21, Bonus::SECONDARY_SKILL_PREMY, +10, new CPropagatorNodeType(PLAYER), CGHeroInstance::NECROMANCY); //necromancy amplifier
|
||||
addBonusIfBuilt(26, Bonus::SECONDARY_SKILL_PREMY, +20, new CPropagatorNodeType(PLAYER), CGHeroInstance::NECROMANCY); //Soul prison
|
||||
addBonusIfBuilt(21, Bonus::SECONDARY_SKILL_PREMY, +10, make_shared<CPropagatorNodeType>(PLAYER), CGHeroInstance::NECROMANCY); //necromancy amplifier
|
||||
addBonusIfBuilt(26, Bonus::SECONDARY_SKILL_PREMY, +20, make_shared<CPropagatorNodeType>(PLAYER), CGHeroInstance::NECROMANCY); //Soul prison
|
||||
}
|
||||
else if(subID == 5) //Dungeon
|
||||
{
|
||||
@ -2333,7 +2333,7 @@ bool CGTownInstance::addBonusIfBuilt(int building, int type, int val, int subtyp
|
||||
return addBonusIfBuilt(building, type, val, NULL, subtype);
|
||||
}
|
||||
|
||||
bool CGTownInstance::addBonusIfBuilt(int building, int type, int val, IPropagator *prop, int subtype /*= -1*/)
|
||||
bool CGTownInstance::addBonusIfBuilt(int building, int type, int val, TPropagatorPtr prop, int subtype /*= -1*/)
|
||||
{
|
||||
if(vstd::contains(builtBuildings, building))
|
||||
{
|
||||
|
@ -584,7 +584,7 @@ public:
|
||||
std::string nodeName() const OVERRIDE;
|
||||
void deserializationFix();
|
||||
void recreateBuildingsBonuses();
|
||||
bool addBonusIfBuilt(int building, int type, int val, IPropagator *prop, int subtype = -1); //returns true if building is built and bonus has been added
|
||||
bool addBonusIfBuilt(int building, int type, int val, TPropagatorPtr prop, int subtype = -1); //returns true if building is built and bonus has been added
|
||||
bool addBonusIfBuilt(int building, int type, int val, int subtype = -1); //convienence version of above
|
||||
void setVisitingHero(CGHeroInstance *h);
|
||||
void setGarrisonedHero(CGHeroInstance *h);
|
||||
|
@ -495,7 +495,7 @@ public:
|
||||
const_cast<T&>(data).serialize(*this,version);
|
||||
}
|
||||
template <typename T>
|
||||
void saveSerializable(const boost::shared_ptr<T> &data)
|
||||
void saveSerializable(const shared_ptr<T> &data)
|
||||
{
|
||||
T *internalPtr = data.get();
|
||||
*this << internalPtr;
|
||||
@ -762,7 +762,7 @@ public:
|
||||
|
||||
|
||||
template <typename T>
|
||||
void loadSerializable(boost::shared_ptr<T> &data)
|
||||
void loadSerializable(shared_ptr<T> &data)
|
||||
{
|
||||
T *internalPtr;
|
||||
*this >> internalPtr;
|
||||
|
@ -12,6 +12,7 @@
|
||||
#include "GameConstants.h"
|
||||
|
||||
#define FOREACH_PARENT(pname) TNodes lparents; getParents(lparents); BOOST_FOREACH(CBonusSystemNode *pname, lparents)
|
||||
#define FOREACH_CPARENT(pname) TCNodes lparents; getParents(lparents); BOOST_FOREACH(const CBonusSystemNode *pname, lparents)
|
||||
#define FOREACH_RED_CHILD(pname) TNodes lchildren; getRedChildren(lchildren); BOOST_FOREACH(CBonusSystemNode *pname, lchildren)
|
||||
#define FOREACH_RED_PARENT(pname) TNodes lparents; getRedParents(lparents); BOOST_FOREACH(CBonusSystemNode *pname, lparents)
|
||||
|
||||
@ -143,7 +144,7 @@ void BonusList::getModifiersWDescr(TModDescr &out) const
|
||||
}
|
||||
}
|
||||
|
||||
void BonusList::getBonuses(TBonusListPtr out, const CSelector &selector) const
|
||||
void BonusList::getBonuses(BonusList & out, const CSelector &selector) const
|
||||
{
|
||||
// BOOST_FOREACH(Bonus *i, *this)
|
||||
// if(selector(i) && i->effectRange == Bonus::NO_LIMIT)
|
||||
@ -152,31 +153,37 @@ void BonusList::getBonuses(TBonusListPtr out, const CSelector &selector) const
|
||||
getBonuses(out, selector, 0);
|
||||
}
|
||||
|
||||
void BonusList::getBonuses(TBonusListPtr out, const CSelector &selector, const CSelector &limit, const bool caching /*= false*/) const
|
||||
void BonusList::getBonuses(BonusList & out, const CSelector &selector, const CSelector &limit) const
|
||||
{
|
||||
for (ui32 i = 0; i < bonuses.size(); i++)
|
||||
{
|
||||
Bonus *b = bonuses[i];
|
||||
|
||||
//add matching bonuses that matches limit predicate or have NO_LIMIT if no given predicate
|
||||
if(caching || (selector(b) && ((!limit && b->effectRange == Bonus::NO_LIMIT) || (limit && limit(b)))))
|
||||
out->push_back(b);
|
||||
if(selector(b) && ((!limit && b->effectRange == Bonus::NO_LIMIT) || (limit && limit(b))))
|
||||
out.push_back(b);
|
||||
}
|
||||
}
|
||||
|
||||
void BonusList::getAllBonuses(BonusList &out) const
|
||||
{
|
||||
BOOST_FOREACH(Bonus *b, bonuses)
|
||||
out.push_back(b);
|
||||
}
|
||||
|
||||
int BonusList::valOfBonuses(const CSelector &select) const
|
||||
{
|
||||
TBonusListPtr ret(new BonusList());
|
||||
BonusList ret;
|
||||
CSelector limit = 0;
|
||||
getBonuses(ret, select, limit, false);
|
||||
ret->eliminateDuplicates();
|
||||
return ret->totalValue();
|
||||
getBonuses(ret, select, limit);
|
||||
ret.eliminateDuplicates();
|
||||
return ret.totalValue();
|
||||
}
|
||||
|
||||
void BonusList::limit(const CBonusSystemNode &node)
|
||||
{
|
||||
remove_if(boost::bind(&CBonusSystemNode::isLimitedOnUs, boost::ref(node), _1));
|
||||
}
|
||||
// void BonusList::limit(const CBonusSystemNode &node)
|
||||
// {
|
||||
// remove_if(boost::bind(&CBonusSystemNode::isLimitedOnUs, boost::ref(node), _1));
|
||||
// }
|
||||
|
||||
|
||||
void BonusList::eliminateDuplicates()
|
||||
@ -464,20 +471,30 @@ void CBonusSystemNode::getParents(TNodes &out)
|
||||
}
|
||||
}
|
||||
|
||||
void CBonusSystemNode::getAllBonusesRec(TBonusListPtr out, const CSelector &selector, const CSelector &limit, const CBonusSystemNode *root /*= NULL*/, const bool caching /*= false*/) const
|
||||
void CBonusSystemNode::getBonusesRec(BonusList &out, const CSelector &selector, const CSelector &limit) const
|
||||
{
|
||||
TCNodes lparents;
|
||||
getParents(lparents);
|
||||
BOOST_FOREACH(const CBonusSystemNode *p, lparents)
|
||||
p->getAllBonusesRec(out, selector, limit, root ? root : this, caching);
|
||||
|
||||
bonuses.getBonuses(out, selector, limit, caching);
|
||||
FOREACH_CPARENT(p)
|
||||
{
|
||||
p->getBonusesRec(out, selector, limit);
|
||||
}
|
||||
|
||||
bonuses.getBonuses(out, selector, limit);
|
||||
}
|
||||
|
||||
void CBonusSystemNode::getAllBonusesRec(BonusList &out) const
|
||||
{
|
||||
FOREACH_CPARENT(p)
|
||||
{
|
||||
p->getAllBonusesRec(out);
|
||||
}
|
||||
|
||||
bonuses.getAllBonuses(out);
|
||||
}
|
||||
|
||||
const TBonusListPtr CBonusSystemNode::getAllBonuses(const CSelector &selector, const CSelector &limit, const CBonusSystemNode *root /*= NULL*/, const std::string &cachingStr /*= ""*/) const
|
||||
{
|
||||
TBonusListPtr ret(new BonusList());
|
||||
if (CBonusSystemNode::cachingEnabled)
|
||||
bool limitOnUs = (!root || root == this); //caching won't work when we want to limit bonuses against an external node
|
||||
if (CBonusSystemNode::cachingEnabled && limitOnUs)
|
||||
{
|
||||
// Exclusive access for one thread
|
||||
static boost::mutex m;
|
||||
@ -487,11 +504,14 @@ const TBonusListPtr CBonusSystemNode::getAllBonuses(const CSelector &selector, c
|
||||
// cache all bonus objects. Selector objects doesn't matter.
|
||||
if (cachedLast != treeChanged)
|
||||
{
|
||||
getAllBonusesRec(ret, selector, limit, this, true);
|
||||
ret->eliminateDuplicates();
|
||||
cachedBonuses = *ret;
|
||||
ret->clear();
|
||||
cachedBonuses.clear();
|
||||
cachedRequests.clear();
|
||||
|
||||
BonusList allBonuses;
|
||||
getAllBonusesRec(allBonuses);
|
||||
allBonuses.eliminateDuplicates();
|
||||
limitBonuses(allBonuses, cachedBonuses);
|
||||
|
||||
cachedLast = treeChanged;
|
||||
}
|
||||
|
||||
@ -499,43 +519,70 @@ const TBonusListPtr CBonusSystemNode::getAllBonuses(const CSelector &selector, c
|
||||
// pre-calculated bonus results. Limiters can't be cached so they have to be calculated.
|
||||
if (cachingStr != "")
|
||||
{
|
||||
std::map<std::string, TBonusListPtr >::iterator it(cachedRequests.find(cachingStr));
|
||||
if (cachedRequests.size() > 0 && it != cachedRequests.end())
|
||||
auto it = cachedRequests.find(cachingStr);
|
||||
if(it != cachedRequests.end())
|
||||
{
|
||||
ret = it->second;
|
||||
if (!root)
|
||||
ret->limit(*this);
|
||||
|
||||
return ret;
|
||||
//Cached list contains bonuses for our query with applied limiters
|
||||
return it->second;
|
||||
}
|
||||
}
|
||||
|
||||
// Get the bonus results
|
||||
cachedBonuses.getBonuses(ret, selector, limit, false);
|
||||
|
||||
// Sets the results with the given caching string into the map
|
||||
if (cachingStr != "")
|
||||
//We still don't have the bonuses (didn't returned them from cache)
|
||||
//Perform bonus selection
|
||||
auto ret = make_shared<BonusList>();
|
||||
cachedBonuses.getBonuses(*ret, selector, limit);
|
||||
|
||||
// Save the results in the cache
|
||||
if(cachingStr != "")
|
||||
cachedRequests[cachingStr] = ret;
|
||||
|
||||
// Calculate limiters
|
||||
if (!root)
|
||||
ret->limit(*this);
|
||||
|
||||
return ret;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Get bonus results without caching enabled.
|
||||
getAllBonusesRec(ret, selector, limit, root, false);
|
||||
ret->eliminateDuplicates();
|
||||
|
||||
if(!root)
|
||||
ret->limit(*this);
|
||||
|
||||
return ret;
|
||||
return getAllBonusesWithoutCaching(selector, limit, root);
|
||||
}
|
||||
}
|
||||
|
||||
const TBonusListPtr CBonusSystemNode::getAllBonusesWithoutCaching(const CSelector &selector, const CSelector &limit, const CBonusSystemNode *root /*= NULL*/) const
|
||||
{
|
||||
auto ret = make_shared<BonusList>();
|
||||
|
||||
// Get bonus results without caching enabled.
|
||||
BonusList beforeLimiting, afterLimiting;
|
||||
getAllBonusesRec(beforeLimiting);
|
||||
beforeLimiting.eliminateDuplicates();
|
||||
|
||||
if(!root || root == this)
|
||||
{
|
||||
limitBonuses(beforeLimiting, afterLimiting);
|
||||
afterLimiting.getBonuses(*ret, selector, limit);
|
||||
}
|
||||
else if(root)
|
||||
{
|
||||
//We want to limit our query against an external node. We get all its bonuses,
|
||||
// add the ones we're considering and see if they're cut out by limiters
|
||||
BonusList rootBonuses, limitedRootBonuses;
|
||||
getAllBonusesRec(rootBonuses);
|
||||
|
||||
BOOST_FOREACH(Bonus *b, beforeLimiting)
|
||||
rootBonuses.push_back(b);
|
||||
|
||||
rootBonuses.eliminateDuplicates();
|
||||
root->limitBonuses(rootBonuses, limitedRootBonuses);
|
||||
|
||||
BOOST_FOREACH(Bonus *b, beforeLimiting)
|
||||
if(vstd::contains(limitedRootBonuses, b))
|
||||
afterLimiting.push_back(b);
|
||||
|
||||
afterLimiting.getBonuses(*ret, selector, limit);
|
||||
}
|
||||
else
|
||||
beforeLimiting.getBonuses(*ret, selector, limit);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
CBonusSystemNode::CBonusSystemNode() : bonuses(true), exportedBonuses(true), nodeType(UNKNOWN), cachedLast(0)
|
||||
{
|
||||
}
|
||||
@ -585,9 +632,9 @@ void CBonusSystemNode::detachFrom(CBonusSystemNode *parent)
|
||||
|
||||
void CBonusSystemNode::popBonuses(const CSelector &s)
|
||||
{
|
||||
TBonusListPtr bl(new BonusList);
|
||||
BonusList bl;
|
||||
exportedBonuses.getBonuses(bl, s);
|
||||
BOOST_FOREACH(Bonus *b, *bl)
|
||||
BOOST_FOREACH(Bonus *b, bl)
|
||||
removeBonus(b);
|
||||
|
||||
BOOST_FOREACH(CBonusSystemNode *child, children)
|
||||
@ -618,11 +665,6 @@ void CBonusSystemNode::removeBonus(Bonus *b)
|
||||
CBonusSystemNode::treeChanged++;
|
||||
}
|
||||
|
||||
bool CBonusSystemNode::isLimitedOnUs(Bonus *b) const
|
||||
{
|
||||
return b->limiter && b->limiter->limit(b, *this);
|
||||
}
|
||||
|
||||
bool CBonusSystemNode::actsAsBonusSourceOnly() const
|
||||
{
|
||||
switch(nodeType)
|
||||
@ -852,6 +894,53 @@ void CBonusSystemNode::incrementTreeChangedNum()
|
||||
treeChanged++;
|
||||
}
|
||||
|
||||
void CBonusSystemNode::limitBonuses(const BonusList &allBonuses, BonusList &out) const
|
||||
{
|
||||
assert(&allBonuses != &out); //todo should it work in-place?
|
||||
|
||||
BonusList undecided = allBonuses,
|
||||
&accepted = out;
|
||||
|
||||
while(true)
|
||||
{
|
||||
int undecidedCount = undecided.size();
|
||||
for(int i = 0; i < undecided.size(); i++)
|
||||
{
|
||||
Bonus *b = undecided[i];
|
||||
BonusLimitationContext context = {b, *this, out};
|
||||
int decision = b->limiter ? b->limiter->limit(context) : ILimiter::ACCEPT; //bonuses without limiters will be accepted by default
|
||||
if(decision == ILimiter::DISCARD)
|
||||
{
|
||||
undecided.erase(i);
|
||||
i--; continue;
|
||||
}
|
||||
else if(decision == ILimiter::ACCEPT)
|
||||
{
|
||||
accepted.push_back(b);
|
||||
undecided.erase(i);
|
||||
i--; continue;
|
||||
}
|
||||
else
|
||||
assert(decision == ILimiter::NOT_SURE);
|
||||
}
|
||||
|
||||
if(undecided.size() == undecidedCount) //we haven't moved a single bonus -> limiters reached a stable state
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
TBonusListPtr CBonusSystemNode::limitBonuses(const BonusList &allBonuses) const
|
||||
{
|
||||
auto ret = make_shared<BonusList>();
|
||||
limitBonuses(allBonuses, *ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void CBonusSystemNode::treeHasChanged()
|
||||
{
|
||||
treeChanged++;
|
||||
}
|
||||
|
||||
int NBonus::valOf(const CBonusSystemNode *obj, Bonus::BonusType type, int subtype /*= -1*/)
|
||||
{
|
||||
if(obj)
|
||||
@ -944,23 +1033,13 @@ Bonus::~Bonus()
|
||||
{
|
||||
}
|
||||
|
||||
Bonus * Bonus::addLimiter(ILimiter *Limiter)
|
||||
{
|
||||
return addLimiter(boost::shared_ptr<ILimiter>(Limiter));
|
||||
}
|
||||
|
||||
Bonus * Bonus::addLimiter(boost::shared_ptr<ILimiter> Limiter)
|
||||
Bonus * Bonus::addLimiter(TLimiterPtr Limiter)
|
||||
{
|
||||
limiter = Limiter;
|
||||
return this;
|
||||
}
|
||||
|
||||
Bonus * Bonus::addPropagator(IPropagator *Propagator)
|
||||
{
|
||||
return addPropagator(boost::shared_ptr<IPropagator>(Propagator));
|
||||
}
|
||||
|
||||
Bonus * Bonus::addPropagator(boost::shared_ptr<IPropagator> Propagator)
|
||||
Bonus * Bonus::addPropagator(TPropagatorPtr Propagator)
|
||||
{
|
||||
propagator = Propagator;
|
||||
return this;
|
||||
@ -1109,14 +1188,14 @@ ILimiter::~ILimiter()
|
||||
{
|
||||
}
|
||||
|
||||
bool ILimiter::limit(const Bonus *b, const CBonusSystemNode &node) const /*return true to drop the bonus */
|
||||
int ILimiter::limit(const BonusLimitationContext &context) const /*return true to drop the bonus */
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CCreatureTypeLimiter::limit(const Bonus *b, const CBonusSystemNode &node) const
|
||||
int CCreatureTypeLimiter::limit(const BonusLimitationContext &context) const
|
||||
{
|
||||
const CCreature *c = retrieveCreature(&node);
|
||||
const CCreature *c = retrieveCreature(&context.node);
|
||||
if(!c)
|
||||
return true;
|
||||
return c != creature && (!includeUpgrades || !creature->isMyUpgrade(c));
|
||||
@ -1144,16 +1223,18 @@ HasAnotherBonusLimiter::HasAnotherBonusLimiter( TBonusType bonus, TBonusSubtype
|
||||
{
|
||||
}
|
||||
|
||||
bool HasAnotherBonusLimiter::limit( const Bonus *b, const CBonusSystemNode &node ) const
|
||||
int HasAnotherBonusLimiter::limit(const BonusLimitationContext &context) const
|
||||
{
|
||||
if(isSubtypeRelevant)
|
||||
{
|
||||
return !node.hasBonusOfType(static_cast<Bonus::BonusType>(type), subtype);
|
||||
}
|
||||
else
|
||||
{
|
||||
return !node.hasBonusOfType(static_cast<Bonus::BonusType>(type));
|
||||
}
|
||||
CSelector mySelector = isSubtypeRelevant
|
||||
? Selector::typeSubtype(type, subtype)
|
||||
: Selector::type(type);
|
||||
|
||||
//if we have a bonus of required type accepted, limiter should accept also this bonus
|
||||
if(context.alreadyAccepted.getFirst(mySelector))
|
||||
return ACCEPT;
|
||||
|
||||
//do not accept for now but it may change if more bonuses gets included
|
||||
return NOT_SURE;
|
||||
}
|
||||
|
||||
IPropagator::~IPropagator()
|
||||
@ -1201,9 +1282,10 @@ CreatureNativeTerrainLimiter::CreatureNativeTerrainLimiter()
|
||||
{
|
||||
|
||||
}
|
||||
bool CreatureNativeTerrainLimiter::limit(const Bonus *b, const CBonusSystemNode &node) const
|
||||
|
||||
int CreatureNativeTerrainLimiter::limit(const BonusLimitationContext &context) const
|
||||
{
|
||||
const CCreature *c = retrieveCreature(&node);
|
||||
const CCreature *c = retrieveCreature(&context.node);
|
||||
return !c || !vstd::iswithin(c->faction, 0, 9) || VLC->heroh->nativeTerrains[c->faction] != terrainType; //drop bonus for non-creatures or non-native residents
|
||||
//TODO neutral creatues
|
||||
}
|
||||
@ -1216,9 +1298,10 @@ CreatureFactionLimiter::CreatureFactionLimiter(int Faction)
|
||||
CreatureFactionLimiter::CreatureFactionLimiter()
|
||||
{
|
||||
}
|
||||
bool CreatureFactionLimiter::limit(const Bonus *b, const CBonusSystemNode &node) const
|
||||
|
||||
int CreatureFactionLimiter::limit(const BonusLimitationContext &context) const
|
||||
{
|
||||
const CCreature *c = retrieveCreature(&node);
|
||||
const CCreature *c = retrieveCreature(&context.node);
|
||||
return !c || c->faction != faction; //drop bonus for non-creatures or non-native residents
|
||||
}
|
||||
|
||||
@ -1231,9 +1314,9 @@ CreatureAlignmentLimiter::CreatureAlignmentLimiter(si8 Alignment)
|
||||
{
|
||||
}
|
||||
|
||||
bool CreatureAlignmentLimiter::limit(const Bonus *b, const CBonusSystemNode &node) const
|
||||
int CreatureAlignmentLimiter::limit(const BonusLimitationContext &context) const
|
||||
{
|
||||
const CCreature *c = retrieveCreature(&node);
|
||||
const CCreature *c = retrieveCreature(&context.node);
|
||||
if(!c)
|
||||
return true;
|
||||
switch(alignment)
|
||||
@ -1260,21 +1343,21 @@ RankRangeLimiter::RankRangeLimiter()
|
||||
minRank = maxRank = -1;
|
||||
}
|
||||
|
||||
bool RankRangeLimiter::limit( const Bonus *b, const CBonusSystemNode &node ) const
|
||||
int RankRangeLimiter::limit(const BonusLimitationContext &context) const
|
||||
{
|
||||
const CStackInstance *csi = retreiveStackInstance(&node);
|
||||
const CStackInstance *csi = retreiveStackInstance(&context.node);
|
||||
if(csi)
|
||||
return csi->getExpRank() < minRank || csi->getExpRank() > maxRank;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool StackOwnerLimiter::limit(const Bonus *b, const CBonusSystemNode &node) const
|
||||
int StackOwnerLimiter::limit(const BonusLimitationContext &context) const
|
||||
{
|
||||
const CStack *s = retreiveStackBattle(&node);
|
||||
const CStack *s = retreiveStackBattle(&context.node);
|
||||
if(s)
|
||||
return s->owner != owner;
|
||||
|
||||
const CStackInstance *csi = retreiveStackInstance(&node);
|
||||
const CStackInstance *csi = retreiveStackInstance(&context.node);
|
||||
if(csi && csi->armyObj)
|
||||
return csi->armyObj->tempOwner != owner;
|
||||
return true;
|
||||
|
@ -22,7 +22,9 @@ class ILimiter;
|
||||
class IPropagator;
|
||||
class BonusList;
|
||||
|
||||
typedef boost::shared_ptr<BonusList> TBonusListPtr;
|
||||
typedef shared_ptr<BonusList> TBonusListPtr;
|
||||
typedef shared_ptr<ILimiter> TLimiterPtr;
|
||||
typedef shared_ptr<IPropagator> TPropagatorPtr;
|
||||
typedef std::vector<std::pair<int,std::string> > TModDescr; //modifiers values and their descriptions
|
||||
typedef std::set<CBonusSystemNode*> TNodes;
|
||||
typedef std::set<const CBonusSystemNode*> TCNodes;
|
||||
@ -247,8 +249,8 @@ struct DLL_LINKAGE Bonus
|
||||
si32 additionalInfo;
|
||||
ui8 effectRange; //if not NO_LIMIT, bonus will be omitted by default
|
||||
|
||||
boost::shared_ptr<ILimiter> limiter;
|
||||
boost::shared_ptr<IPropagator> propagator;
|
||||
TLimiterPtr limiter;
|
||||
TPropagatorPtr propagator;
|
||||
|
||||
std::string description;
|
||||
|
||||
@ -322,10 +324,8 @@ struct DLL_LINKAGE Bonus
|
||||
|
||||
std::string Description() const;
|
||||
|
||||
Bonus *addLimiter(ILimiter *Limiter); //returns this for convenient chain-calls
|
||||
Bonus *addPropagator(IPropagator *Propagator); //returns this for convenient chain-calls
|
||||
Bonus *addLimiter(boost::shared_ptr<ILimiter> Limiter); //returns this for convenient chain-calls
|
||||
Bonus *addPropagator(boost::shared_ptr<IPropagator> Propagator); //returns this for convenient chain-calls
|
||||
Bonus *addLimiter(TLimiterPtr Limiter); //returns this for convenient chain-calls
|
||||
Bonus *addPropagator(TPropagatorPtr Propagator); //returns this for convenient chain-calls
|
||||
};
|
||||
|
||||
DLL_LINKAGE std::ostream & operator<<(std::ostream &out, const Bonus &bonus);
|
||||
@ -363,17 +363,18 @@ public:
|
||||
|
||||
// BonusList functions
|
||||
int totalValue() const; //subtype -> subtype of bonus, if -1 then any
|
||||
void getBonuses(TBonusListPtr out, const CSelector &selector, const CSelector &limit, const bool caching = false) const;
|
||||
void getBonuses(BonusList &out, const CSelector &selector, const CSelector &limit) const;
|
||||
void getAllBonuses(BonusList &out) const;
|
||||
void getModifiersWDescr(TModDescr &out) const;
|
||||
|
||||
void getBonuses(TBonusListPtr out, const CSelector &selector) const;
|
||||
void getBonuses(BonusList & out, const CSelector &selector) const;
|
||||
|
||||
//special find functions
|
||||
Bonus *getFirst(const CSelector &select);
|
||||
const Bonus *getFirst(const CSelector &select) const;
|
||||
int valOfBonuses(const CSelector &select) const;
|
||||
|
||||
void limit(const CBonusSystemNode &node); //erases bonuses using limitor
|
||||
//void limit(const CBonusSystemNode &node); //erases bonuses using limitor
|
||||
void eliminateDuplicates();
|
||||
|
||||
// remove_if implementation for STL vector types
|
||||
@ -454,13 +455,22 @@ public:
|
||||
h & nodeType;
|
||||
}
|
||||
};
|
||||
|
||||
struct BonusLimitationContext
|
||||
{
|
||||
const Bonus *b;
|
||||
const CBonusSystemNode &node;
|
||||
const BonusList &alreadyAccepted;
|
||||
};
|
||||
|
||||
class DLL_LINKAGE ILimiter
|
||||
{
|
||||
public:
|
||||
enum EDecision {ACCEPT, DISCARD, NOT_SURE};
|
||||
|
||||
virtual ~ILimiter();
|
||||
|
||||
virtual bool limit(const Bonus *b, const CBonusSystemNode &node) const; //return true to drop the bonus
|
||||
virtual int limit(const BonusLimitationContext &context) const; //0 - accept bonus; 1 - drop bonus; 2 - delay (drops eventually)
|
||||
|
||||
template <typename Handler> void serialize(Handler &h, const int version)
|
||||
{}
|
||||
@ -527,13 +537,17 @@ private:
|
||||
// [property key]_[value] => only for selector
|
||||
mutable std::map<std::string, TBonusListPtr > cachedRequests;
|
||||
|
||||
void getAllBonusesRec(TBonusListPtr out, const CSelector &selector, const CSelector &limit, const CBonusSystemNode *root = NULL, const bool caching = false) const;
|
||||
void getBonusesRec(BonusList &out, const CSelector &selector, const CSelector &limit) const;
|
||||
void getAllBonusesRec(BonusList &out) const;
|
||||
const TBonusListPtr getAllBonusesWithoutCaching(const CSelector &selector, const CSelector &limit, const CBonusSystemNode *root = NULL) const;
|
||||
|
||||
public:
|
||||
|
||||
explicit CBonusSystemNode();
|
||||
virtual ~CBonusSystemNode();
|
||||
|
||||
void limitBonuses(const BonusList &allBonuses, BonusList &out) const; //out will bo populed with bonuses that are not limited here
|
||||
TBonusListPtr limitBonuses(const BonusList &allBonuses) const; //same as above, returns out by val for convienence
|
||||
const TBonusListPtr getAllBonuses(const CSelector &selector, const CSelector &limit, const CBonusSystemNode *root = NULL, const std::string &cachingStr = "") const;
|
||||
void getParents(TCNodes &out) const; //retrieves list of parent nodes (nodes to inherit bonuses from),
|
||||
const Bonus *getBonus(const CSelector &selector) const;
|
||||
@ -563,7 +577,7 @@ public:
|
||||
|
||||
bool isIndependentNode() const; //node is independent when it has no parents nor children
|
||||
bool actsAsBonusSourceOnly() const;
|
||||
bool isLimitedOnUs(Bonus *b) const; //if bonus should be removed from list acquired from this node
|
||||
//bool isLimitedOnUs(Bonus *b) const; //if bonus should be removed from list acquired from this node
|
||||
|
||||
void popBonuses(const CSelector &s);
|
||||
virtual std::string bonusToString(Bonus *bonus, bool description) const {return "";}; //description or bonus name
|
||||
@ -584,6 +598,8 @@ public:
|
||||
const std::string &getDescription() const;
|
||||
void setDescription(const std::string &description);
|
||||
|
||||
static void treeHasChanged();
|
||||
|
||||
template <typename Handler> void serialize(Handler &h, const int version)
|
||||
{
|
||||
h & /*bonuses & */nodeType;
|
||||
@ -708,7 +724,7 @@ public:
|
||||
CCreatureTypeLimiter();
|
||||
CCreatureTypeLimiter(const CCreature &Creature, ui8 IncludeUpgrades = true);
|
||||
|
||||
bool limit(const Bonus *b, const CBonusSystemNode &node) const OVERRIDE;
|
||||
int limit(const BonusLimitationContext &context) const OVERRIDE;
|
||||
|
||||
template <typename Handler> void serialize(Handler &h, const int version)
|
||||
{
|
||||
@ -726,7 +742,7 @@ public:
|
||||
HasAnotherBonusLimiter(TBonusType bonus = Bonus::NONE);
|
||||
HasAnotherBonusLimiter(TBonusType bonus, TBonusSubtype _subtype);
|
||||
|
||||
bool limit(const Bonus *b, const CBonusSystemNode &node) const OVERRIDE;
|
||||
int limit(const BonusLimitationContext &context) const OVERRIDE;
|
||||
|
||||
template <typename Handler> void serialize(Handler &h, const int version)
|
||||
{
|
||||
@ -741,7 +757,7 @@ public:
|
||||
CreatureNativeTerrainLimiter();
|
||||
CreatureNativeTerrainLimiter(int TerrainType);
|
||||
|
||||
bool limit(const Bonus *b, const CBonusSystemNode &node) const OVERRIDE;
|
||||
int limit(const BonusLimitationContext &context) const OVERRIDE;
|
||||
|
||||
template <typename Handler> void serialize(Handler &h, const int version)
|
||||
{
|
||||
@ -756,7 +772,7 @@ public:
|
||||
CreatureFactionLimiter();
|
||||
CreatureFactionLimiter(int TerrainType);
|
||||
|
||||
bool limit(const Bonus *b, const CBonusSystemNode &node) const OVERRIDE;
|
||||
int limit(const BonusLimitationContext &context) const OVERRIDE;
|
||||
|
||||
template <typename Handler> void serialize(Handler &h, const int version)
|
||||
{
|
||||
@ -771,7 +787,7 @@ public:
|
||||
CreatureAlignmentLimiter();
|
||||
CreatureAlignmentLimiter(si8 Alignment);
|
||||
|
||||
bool limit(const Bonus *b, const CBonusSystemNode &node) const OVERRIDE;
|
||||
int limit(const BonusLimitationContext &context) const OVERRIDE;
|
||||
|
||||
template <typename Handler> void serialize(Handler &h, const int version)
|
||||
{
|
||||
@ -786,7 +802,7 @@ public:
|
||||
StackOwnerLimiter();
|
||||
StackOwnerLimiter(ui8 Owner);
|
||||
|
||||
bool limit(const Bonus *b, const CBonusSystemNode &node) const OVERRIDE;
|
||||
int limit(const BonusLimitationContext &context) const OVERRIDE;
|
||||
|
||||
template <typename Handler> void serialize(Handler &h, const int version)
|
||||
{
|
||||
@ -801,7 +817,7 @@ public:
|
||||
|
||||
RankRangeLimiter();
|
||||
RankRangeLimiter(ui8 Min, ui8 Max = 255);
|
||||
bool limit(const Bonus *b, const CBonusSystemNode &node) const OVERRIDE;
|
||||
int limit(const BonusLimitationContext &context) const OVERRIDE;
|
||||
|
||||
template <typename Handler> void serialize(Handler &h, const int version)
|
||||
{
|
||||
|
@ -655,6 +655,8 @@ DLL_LINKAGE void RebalanceStacks::applyGs( CGameState *gs )
|
||||
dst.army->setStackExp(dst.slot, src.army->getStackExperience(src.slot));
|
||||
}
|
||||
}
|
||||
|
||||
CBonusSystemNode::treeHasChanged();
|
||||
}
|
||||
|
||||
DLL_LINKAGE void PutArtifact::applyGs( CGameState *gs )
|
||||
@ -941,6 +943,8 @@ void BattleResult::applyGs( CGameState *gs )
|
||||
gs->curB->belligerents[0]->giveStackExp(exp[0]);
|
||||
if (exp[1])
|
||||
gs->curB->belligerents[1]->giveStackExp(exp[1]);
|
||||
|
||||
CBonusSystemNode::treeHasChanged();
|
||||
}
|
||||
|
||||
gs->curB->belligerents[0]->battle = gs->curB->belligerents[1]->battle = NULL;
|
||||
|
Loading…
Reference in New Issue
Block a user