mirror of
https://github.com/vcmi/vcmi.git
synced 2025-08-13 19:54:17 +02:00
Fixed #1176.
This commit is contained in:
@@ -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)
|
||||
|
@@ -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);
|
||||
}
|
||||
|
@@ -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:
|
||||
|
@@ -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>();
|
||||
|
Reference in New Issue
Block a user