Michał W. Urbańczyk 12 years ago
parent
commit
0e826915ed
4 changed files with 74 additions and 93 deletions
  1. 8 18
      lib/CObjectHandler.cpp
  2. 46 40
      lib/HeroBonus.cpp
  3. 19 34
      lib/HeroBonus.h
  4. 1 1
      lib/RegisterTypes.h

+ 8 - 18
lib/CObjectHandler.cpp

@@ -956,6 +956,7 @@ void CGHeroInstance::initObj() //TODO: use bonus system
 						}
 					}
 
+					bonus->additionalInfo = spec.additionalinfo; //creature id
 					bonus->limiter.reset(new CCreatureTypeLimiter (specCreature, true)); //with upgrades
 					bonus->type = Bonus::PRIMARY_SKILL;
 					bonus->valType = Bonus::ADDITIVE_VALUE;
@@ -1024,6 +1025,7 @@ void CGHeroInstance::initObj() //TODO: use bonus system
 					default:
 						continue;
 				}
+				bonus->additionalInfo = spec.additionalinfo; //creature id
 				bonus->valType = Bonus::ADDITIVE_VALUE;
 				bonus->limiter.reset(new CCreatureTypeLimiter (*VLC->creh->creatures[spec.additionalinfo], true));
 				hs->addNewBonus(bonus);
@@ -1143,33 +1145,21 @@ void CGHeroInstance::Updatespecialty() //TODO: calculate special value of bonuse
 						break; //use only hero skills as bonuses to avoid feedback loop
 					case Bonus::PRIMARY_SKILL: //for creatures, that is
 					{
-						CCreatureTypeLimiter * foundLimiter = NULL;
-						CCreature * cre = NULL;
 						int creLevel = 0;
-						TLimiterPtr limiterNode (b);
-						while (limiterNode->limiter)
+						if (auto creatureLimiter = std::dynamic_pointer_cast<CCreatureTypeLimiter>(b->limiter)) //TODO: more general eveluation of bonuses?
 						{
-							limiterNode = limiterNode->limiter; //search list
-							if (foundLimiter = dynamic_cast<CCreatureTypeLimiter*>(limiterNode.get())) //TODO: more general eveluation of bonuses?
+							creLevel = creatureLimiter->creature->level;
+							if(!creLevel)
 							{
-								cre = const_cast<CCreature*>(foundLimiter->creature);
-								creLevel = cre->level;
-								break;
+								creLevel = 5; //treat ballista as tier 5
 							}
 						}
-						if (!foundLimiter)
+						else
 						{
 							tlog2 << "Primary skill specialty growth supported only with creature type limiters\n";
 							break;
 						}
-						if (cre)
-						{
-							creLevel = cre->level;
-						}
-						if(!creLevel)
-						{
-							creLevel = 5; //treat ballista as tier 5
-						}
+
 						double primSkillModifier = (int)(level / creLevel) / 20.0;
 						int param;
 						switch (b->subtype)

+ 46 - 40
lib/HeroBonus.cpp

@@ -96,7 +96,6 @@ BonusList& BonusList::operator=(const BonusList &bonusList)
 
 int BonusList::totalValue() const
 {
-	int tempVal = 0;
 	int base = 0;
 	int percentToBase = 0;
 	int percentToAll = 0;
@@ -110,15 +109,6 @@ int BonusList::totalValue() const
 	{
 		Bonus *b = bonuses[i];
 
-		if (b->calculator)
-		{
-			assert (false);
-			BonusCalculationContext bcc = {b, CBonusSystemNode()};
-			tempVal = b->calculator->val (bcc);
-		}
-		else
-			tempVal = b->val;
-
 		switch(b->valType)
 		{
 		case Bonus::BASE_NUMBER:
@@ -471,7 +461,9 @@ ui32 IBonusBearer::getMaxDamage() const
 
 si32 IBonusBearer::manaLimit() const
 {
-	return si32(getPrimSkillLevel(3) * (100.0 + valOfBonuses(Bonus::SECONDARY_SKILL_PREMY, 24)) / 10.0);
+	return si32(getPrimSkillLevel(PrimarySkill::KNOWLEDGE) 
+		* (100.0 + valOfBonuses(Bonus::SECONDARY_SKILL_PREMY, CGHeroInstance::INTELLIGENCE)) 
+		/ 10.0);
 }
 
 int IBonusBearer::getPrimSkillLevel(int id) const
@@ -1042,7 +1034,7 @@ void CBonusSystemNode::limitBonuses(const BonusList &allBonuses, BonusList &out)
 		{
 			Bonus *b = undecided[i];
 			BonusLimitationContext context = {b, *this, out};
-			int decision = b->limit(context); //bonuses without limiters will be accepted by default
+			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);
@@ -1173,14 +1165,6 @@ 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);
@@ -1319,25 +1303,28 @@ DLL_LINKAGE std::ostream & operator<<(std::ostream &out, const Bonus &bonus)
 
 	return out;
 }
+
 Bonus * Bonus::addLimiter(TLimiterPtr Limiter)
 {
-	if (limiter) //insert at the beginning of list
+	if (limiter)
 	{
-		TLimiterPtr temp = limiter;
-		limiter = Limiter;
-		limiter->limiter = temp;
+		//If we already have limiter list, retreive it
+		auto limiterList = std::dynamic_pointer_cast<LimiterList>(limiter);
+		if(!limiterList)
+		{
+			//Create a new limiter list with old limiter and the new one will be pushed later
+			limiterList = make_shared<LimiterList>();
+			limiterList->add(limiter);
+			limiter = limiterList;
+		}
+
+		limiterList->add(Limiter);
 	}
 	else
 	{
 		limiter = Limiter;
 	}
 	return this;
-
-}
-
-int LimiterDecorator::limit(const BonusLimitationContext &context) const /*return true to drop the bonus */
-{
-	return false;
 }
 
 ILimiter::~ILimiter()
@@ -1434,16 +1421,6 @@ bool CPropagatorNodeType::shouldBeAttached(CBonusSystemNode *dest)
 	return nodeType == dest->getNodeType();
 }
 
-int LimiterDecorator::callNext(const BonusLimitationContext &context) const
-{
-	if (limiter)
-	{
-		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)
 {
@@ -1547,3 +1524,32 @@ StackOwnerLimiter::StackOwnerLimiter(ui8 Owner)
 	: owner(Owner)
 {
 }
+// int Bonus::limit(const BonusLimitationContext &context) const 
+//  	1162	{ 
+//  	1163	        if (limiter) 
+//  	1164	                return limiter->callNext(context); 
+//  	1165	        else 
+//  	1166	                return ILimiter::ACCEPT; //accept if there's no limiter 
+//  	1167	} 
+ 	//1168	 
+
+int LimiterList::limit( const BonusLimitationContext &context ) const 
+{
+	bool wasntSure = false;
+
+	BOOST_FOREACH(auto limiter, limiters)
+	{
+		auto result = limiter->limit(context);
+		if(result == ILimiter::DISCARD)
+			return result;
+		if(result == ILimiter::NOT_SURE)
+			wasntSure = true;
+	}
+
+	return wasntSure ? ILimiter::NOT_SURE : ILimiter::ACCEPT;
+}
+
+void LimiterList::add( TLimiterPtr limiter )
+{
+	limiters.push_back(limiter);
+}

+ 19 - 34
lib/HeroBonus.h

@@ -20,12 +20,10 @@ class ILimiter;
 class IPropagator;
 class ICalculator;
 class BonusList;
-class LimiterDecorator;
-struct BonusLimitationContext;
 struct BonusCalculationContext;
 
 typedef shared_ptr<BonusList> TBonusListPtr;
-typedef shared_ptr<LimiterDecorator> TLimiterPtr;
+typedef shared_ptr<ILimiter> TLimiterPtr;
 typedef shared_ptr<IPropagator> TPropagatorPtr;
 typedef shared_ptr<ICalculator> TCalculatorPtr;
 typedef std::vector<std::pair<int,std::string> > TModDescr; //modifiers values and their descriptions
@@ -34,22 +32,7 @@ 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 limiter; //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;
-
-	virtual ~LimiterDecorator()
-	{}
 
-	template <typename Handler> void serialize(Handler &h, const int version)
-	{
-		h & limiter;
-	}
-};
 
 #define BONUS_TREE_DESERIALIZATION_FIX if(!h.saving && h.smartPointerSerialization) deserializationFix();
 
@@ -227,7 +210,7 @@ public:
 	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 : public LimiterDecorator
+struct DLL_LINKAGE Bonus
 {
 	enum BonusType
 	{
@@ -283,6 +266,7 @@ struct DLL_LINKAGE Bonus : public LimiterDecorator
 	si32 additionalInfo;
 	ui8 effectRange; //if not NO_LIMIT, bonus will be omitted by default
 
+	TLimiterPtr limiter;
 	TPropagatorPtr propagator;
 	TCalculatorPtr calculator;
 
@@ -307,8 +291,7 @@ struct DLL_LINKAGE Bonus : public LimiterDecorator
 
 	template <typename Handler> void serialize(Handler &h, const int version)
 	{
-		h & static_cast<LimiterDecorator&>(*this);
-		h & duration & type & subtype & source & val & sid & description & additionalInfo & turnsRemain & valType & effectRange & propagator;
+		h & duration & type & subtype & source & val & sid & description & additionalInfo & turnsRemain & valType & effectRange & limiter & propagator;
 	}
 
 	static bool compareByAdditionalInfo(const Bonus *a, const Bonus *b)
@@ -363,9 +346,8 @@ struct DLL_LINKAGE Bonus : public LimiterDecorator
 
 	std::string Description() const;
 
-	Bonus * addLimiter(TLimiterPtr Limiter);
-	Bonus * addPropagator(TPropagatorPtr Propagator); //returns this for convenient chain-calls
-	int limit(const BonusLimitationContext &context) const OVERRIDE; //for backward compatibility
+	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);
@@ -509,24 +491,17 @@ struct BonusLimitationContext
 	const BonusList &alreadyAccepted;
 };
 
-struct BonusCalculationContext
-{
-	const Bonus *b;
-	const CBonusSystemNode &node;
-};
-
-
-class DLL_LINKAGE ILimiter : public LimiterDecorator
+class DLL_LINKAGE ILimiter
 {
 public:
 	enum EDecision {ACCEPT, DISCARD, NOT_SURE};
 
-	virtual int limit(const BonusLimitationContext &context) const OVERRIDE;
 	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)
 	{
-		h & static_cast<LimiterDecorator&>(*this);
 	}
 };
 
@@ -776,6 +751,16 @@ public:
 	}
 };
 
+//Stores multiple limiters. If any of them fails -> bonus is dropped.
+class DLL_LINKAGE LimiterList : public ILimiter
+{
+	std::vector<TLimiterPtr> limiters;
+
+public:
+	int limit(const BonusLimitationContext &context) const OVERRIDE;
+	void add(TLimiterPtr limiter);
+};
+
 class DLL_LINKAGE CCreatureTypeLimiter : public ILimiter //affect only stacks of given creature (and optionally it's upgrades)
 {
 public:

+ 1 - 1
lib/RegisterTypes.h

@@ -76,8 +76,8 @@ void registerTypes1(Serializer &s)
 	s.template registerType<IPropagator>();
 	s.template registerType<CPropagatorNodeType>();
 
-	s.template registerType<LimiterDecorator>();
 	s.template registerType<ILimiter>();
+	s.template registerType<LimiterList>();
 	s.template registerType<CCreatureTypeLimiter>();
 	s.template registerType<HasAnotherBonusLimiter>();
 	s.template registerType<CreatureNativeTerrainLimiter>();