mirror of
https://github.com/vcmi/vcmi.git
synced 2025-08-13 19:54:17 +02:00
Bonus limiters are now implemented using Decorator design pattern, which allows to chain them.
This commit is contained in:
@@ -1021,7 +1021,7 @@ void CBonusSystemNode::limitBonuses(const BonusList &allBonuses, BonusList &out)
|
|||||||
{
|
{
|
||||||
Bonus *b = undecided[i];
|
Bonus *b = undecided[i];
|
||||||
BonusLimitationContext context = {b, *this, out};
|
BonusLimitationContext context = {b, *this, out};
|
||||||
int decision = b->limiter ? b->limiter->limit(context) : ILimiter::ACCEPT; //bonuses without limiters will be accepted by default
|
int decision = b->limit(context); //bonuses without limiters will be accepted by default
|
||||||
if(decision == ILimiter::DISCARD)
|
if(decision == ILimiter::DISCARD)
|
||||||
{
|
{
|
||||||
undecided.erase(i);
|
undecided.erase(i);
|
||||||
@@ -1158,6 +1158,14 @@ Bonus * Bonus::addPropagator(TPropagatorPtr Propagator)
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int Bonus::limit(const BonusLimitationContext &context) const
|
||||||
|
{
|
||||||
|
if (limiter)
|
||||||
|
return limiter->callNext(context);
|
||||||
|
else
|
||||||
|
return ILimiter::ACCEPT; //accept if there's no limiter
|
||||||
|
}
|
||||||
|
|
||||||
CSelector DLL_LINKAGE operator&&(const CSelector &first, const CSelector &second)
|
CSelector DLL_LINKAGE operator&&(const CSelector &first, const CSelector &second)
|
||||||
{
|
{
|
||||||
return CSelectorsConjunction(first, second);
|
return CSelectorsConjunction(first, second);
|
||||||
@@ -1297,6 +1305,11 @@ DLL_LINKAGE std::ostream & operator<<(std::ostream &out, const Bonus &bonus)
|
|||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int LimiterDecorator::limit(const BonusLimitationContext &context) const /*return true to drop the bonus */
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
ILimiter::~ILimiter()
|
ILimiter::~ILimiter()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@@ -1386,6 +1399,16 @@ bool CPropagatorNodeType::shouldBeAttached(CBonusSystemNode *dest)
|
|||||||
return nodeType == dest->getNodeType();
|
return nodeType == dest->getNodeType();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int LimiterDecorator::callNext(const BonusLimitationContext &context) const
|
||||||
|
{
|
||||||
|
if (next)
|
||||||
|
{
|
||||||
|
return (limit(context) || callNext(context)); //either of limiters will cause bonus to drop
|
||||||
|
}
|
||||||
|
else //we are last on the list
|
||||||
|
return limit (context);
|
||||||
|
}
|
||||||
|
|
||||||
CreatureNativeTerrainLimiter::CreatureNativeTerrainLimiter(int TerrainType)
|
CreatureNativeTerrainLimiter::CreatureNativeTerrainLimiter(int TerrainType)
|
||||||
: terrainType(TerrainType)
|
: terrainType(TerrainType)
|
||||||
{
|
{
|
||||||
|
@@ -19,6 +19,8 @@ class CBonusSystemNode;
|
|||||||
class ILimiter;
|
class ILimiter;
|
||||||
class IPropagator;
|
class IPropagator;
|
||||||
class BonusList;
|
class BonusList;
|
||||||
|
class LimiterDecorator;
|
||||||
|
struct BonusLimitationContext;
|
||||||
|
|
||||||
typedef shared_ptr<BonusList> TBonusListPtr;
|
typedef shared_ptr<BonusList> TBonusListPtr;
|
||||||
typedef shared_ptr<ILimiter> TLimiterPtr;
|
typedef shared_ptr<ILimiter> TLimiterPtr;
|
||||||
@@ -29,7 +31,14 @@ typedef std::set<const CBonusSystemNode*> TCNodes;
|
|||||||
typedef std::vector<CBonusSystemNode *> TNodesVector;
|
typedef std::vector<CBonusSystemNode *> TNodesVector;
|
||||||
typedef boost::function<bool(const Bonus*)> CSelector;
|
typedef boost::function<bool(const Bonus*)> CSelector;
|
||||||
|
|
||||||
|
class DLL_LINKAGE LimiterDecorator //follows decorator design pattern
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
TLimiterPtr next; //forms a list
|
||||||
|
|
||||||
|
virtual int limit(const BonusLimitationContext &context) const; //0 - accept bonus; 1 - drop bonus; 2 - delay (drops eventually)
|
||||||
|
virtual int callNext(const BonusLimitationContext &context) const;
|
||||||
|
};
|
||||||
|
|
||||||
#define BONUS_TREE_DESERIALIZATION_FIX if(!h.saving && h.smartPointerSerialization) deserializationFix();
|
#define BONUS_TREE_DESERIALIZATION_FIX if(!h.saving && h.smartPointerSerialization) deserializationFix();
|
||||||
|
|
||||||
@@ -207,7 +216,7 @@ typedef boost::function<bool(const Bonus*)> CSelector;
|
|||||||
BONUS_VALUE(INDEPENDENT_MIN) //used for SECONDARY_SKILL_PREMY bonus
|
BONUS_VALUE(INDEPENDENT_MIN) //used for SECONDARY_SKILL_PREMY bonus
|
||||||
|
|
||||||
/// Struct for handling bonuses of several types. Can be transferred to any hero
|
/// Struct for handling bonuses of several types. Can be transferred to any hero
|
||||||
struct DLL_LINKAGE Bonus
|
struct DLL_LINKAGE Bonus : public LimiterDecorator
|
||||||
{
|
{
|
||||||
enum BonusType
|
enum BonusType
|
||||||
{
|
{
|
||||||
@@ -344,6 +353,7 @@ struct DLL_LINKAGE Bonus
|
|||||||
|
|
||||||
Bonus *addLimiter(TLimiterPtr Limiter); //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
|
Bonus *addPropagator(TPropagatorPtr Propagator); //returns this for convenient chain-calls
|
||||||
|
int limit(const BonusLimitationContext &context) const; //for backward compatibility
|
||||||
};
|
};
|
||||||
|
|
||||||
DLL_LINKAGE std::ostream & operator<<(std::ostream &out, const Bonus &bonus);
|
DLL_LINKAGE std::ostream & operator<<(std::ostream &out, const Bonus &bonus);
|
||||||
@@ -487,15 +497,14 @@ struct BonusLimitationContext
|
|||||||
const BonusList &alreadyAccepted;
|
const BonusList &alreadyAccepted;
|
||||||
};
|
};
|
||||||
|
|
||||||
class DLL_LINKAGE ILimiter
|
class DLL_LINKAGE ILimiter : public LimiterDecorator
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
enum EDecision {ACCEPT, DISCARD, NOT_SURE};
|
enum EDecision {ACCEPT, DISCARD, NOT_SURE};
|
||||||
|
|
||||||
|
virtual int limit(const BonusLimitationContext &context) const;
|
||||||
virtual ~ILimiter();
|
virtual ~ILimiter();
|
||||||
|
|
||||||
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)
|
template <typename Handler> void serialize(Handler &h, const int version)
|
||||||
{}
|
{}
|
||||||
};
|
};
|
||||||
|
Reference in New Issue
Block a user