mirror of
https://github.com/vcmi/vcmi.git
synced 2024-12-24 22:14:36 +02:00
Bonus limiters are now implemented using Decorator design pattern, which allows to chain them.
This commit is contained in:
parent
a1c7beeb83
commit
71cbde7bbc
@ -1021,7 +1021,7 @@ void CBonusSystemNode::limitBonuses(const BonusList &allBonuses, BonusList &out)
|
||||
{
|
||||
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
|
||||
int decision = b->limit(context); //bonuses without limiters will be accepted by default
|
||||
if(decision == ILimiter::DISCARD)
|
||||
{
|
||||
undecided.erase(i);
|
||||
@ -1158,6 +1158,14 @@ Bonus * Bonus::addPropagator(TPropagatorPtr Propagator)
|
||||
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)
|
||||
{
|
||||
return CSelectorsConjunction(first, second);
|
||||
@ -1297,6 +1305,11 @@ DLL_LINKAGE std::ostream & operator<<(std::ostream &out, const Bonus &bonus)
|
||||
return out;
|
||||
}
|
||||
|
||||
int LimiterDecorator::limit(const BonusLimitationContext &context) const /*return true to drop the bonus */
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
ILimiter::~ILimiter()
|
||||
{
|
||||
}
|
||||
@ -1386,6 +1399,16 @@ bool CPropagatorNodeType::shouldBeAttached(CBonusSystemNode *dest)
|
||||
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)
|
||||
: terrainType(TerrainType)
|
||||
{
|
||||
|
@ -19,6 +19,8 @@ class CBonusSystemNode;
|
||||
class ILimiter;
|
||||
class IPropagator;
|
||||
class BonusList;
|
||||
class LimiterDecorator;
|
||||
struct BonusLimitationContext;
|
||||
|
||||
typedef shared_ptr<BonusList> TBonusListPtr;
|
||||
typedef shared_ptr<ILimiter> TLimiterPtr;
|
||||
@ -29,7 +31,14 @@ typedef std::set<const CBonusSystemNode*> TCNodes;
|
||||
typedef std::vector<CBonusSystemNode *> TNodesVector;
|
||||
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();
|
||||
|
||||
@ -207,7 +216,7 @@ typedef boost::function<bool(const Bonus*)> CSelector;
|
||||
BONUS_VALUE(INDEPENDENT_MIN) //used for SECONDARY_SKILL_PREMY bonus
|
||||
|
||||
/// 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
|
||||
{
|
||||
@ -344,6 +353,7 @@ struct DLL_LINKAGE Bonus
|
||||
|
||||
Bonus *addLimiter(TLimiterPtr Limiter); //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);
|
||||
@ -487,15 +497,14 @@ struct BonusLimitationContext
|
||||
const BonusList &alreadyAccepted;
|
||||
};
|
||||
|
||||
class DLL_LINKAGE ILimiter
|
||||
class DLL_LINKAGE ILimiter : public LimiterDecorator
|
||||
{
|
||||
public:
|
||||
enum EDecision {ACCEPT, DISCARD, NOT_SURE};
|
||||
|
||||
virtual int limit(const BonusLimitationContext &context) const;
|
||||
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)
|
||||
{}
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user