mirror of
https://github.com/vcmi/vcmi.git
synced 2025-11-06 09:09:40 +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->limiter.reset(new CCreatureTypeLimiter (specCreature, true)); //with upgrades
|
||||||
bonus->type = Bonus::PRIMARY_SKILL;
|
bonus->type = Bonus::PRIMARY_SKILL;
|
||||||
bonus->valType = Bonus::ADDITIVE_VALUE;
|
bonus->valType = Bonus::ADDITIVE_VALUE;
|
||||||
@@ -1024,6 +1025,7 @@ void CGHeroInstance::initObj() //TODO: use bonus system
|
|||||||
default:
|
default:
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
bonus->additionalInfo = spec.additionalinfo; //creature id
|
||||||
bonus->valType = Bonus::ADDITIVE_VALUE;
|
bonus->valType = Bonus::ADDITIVE_VALUE;
|
||||||
bonus->limiter.reset(new CCreatureTypeLimiter (*VLC->creh->creatures[spec.additionalinfo], true));
|
bonus->limiter.reset(new CCreatureTypeLimiter (*VLC->creh->creatures[spec.additionalinfo], true));
|
||||||
hs->addNewBonus(bonus);
|
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
|
break; //use only hero skills as bonuses to avoid feedback loop
|
||||||
case Bonus::PRIMARY_SKILL: //for creatures, that is
|
case Bonus::PRIMARY_SKILL: //for creatures, that is
|
||||||
{
|
{
|
||||||
CCreatureTypeLimiter * foundLimiter = NULL;
|
|
||||||
CCreature * cre = NULL;
|
|
||||||
int creLevel = 0;
|
int creLevel = 0;
|
||||||
TLimiterPtr limiterNode (b);
|
if (auto creatureLimiter = std::dynamic_pointer_cast<CCreatureTypeLimiter>(b->limiter)) //TODO: more general eveluation of bonuses?
|
||||||
while (limiterNode->limiter)
|
|
||||||
{
|
{
|
||||||
limiterNode = limiterNode->limiter; //search list
|
creLevel = creatureLimiter->creature->level;
|
||||||
if (foundLimiter = dynamic_cast<CCreatureTypeLimiter*>(limiterNode.get())) //TODO: more general eveluation of bonuses?
|
if(!creLevel)
|
||||||
{
|
{
|
||||||
cre = const_cast<CCreature*>(foundLimiter->creature);
|
creLevel = 5; //treat ballista as tier 5
|
||||||
creLevel = cre->level;
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!foundLimiter)
|
else
|
||||||
{
|
{
|
||||||
tlog2 << "Primary skill specialty growth supported only with creature type limiters\n";
|
tlog2 << "Primary skill specialty growth supported only with creature type limiters\n";
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (cre)
|
|
||||||
{
|
|
||||||
creLevel = cre->level;
|
|
||||||
}
|
|
||||||
if(!creLevel)
|
|
||||||
{
|
|
||||||
creLevel = 5; //treat ballista as tier 5
|
|
||||||
}
|
|
||||||
double primSkillModifier = (int)(level / creLevel) / 20.0;
|
double primSkillModifier = (int)(level / creLevel) / 20.0;
|
||||||
int param;
|
int param;
|
||||||
switch (b->subtype)
|
switch (b->subtype)
|
||||||
|
|||||||
@@ -96,7 +96,6 @@ BonusList& BonusList::operator=(const BonusList &bonusList)
|
|||||||
|
|
||||||
int BonusList::totalValue() const
|
int BonusList::totalValue() const
|
||||||
{
|
{
|
||||||
int tempVal = 0;
|
|
||||||
int base = 0;
|
int base = 0;
|
||||||
int percentToBase = 0;
|
int percentToBase = 0;
|
||||||
int percentToAll = 0;
|
int percentToAll = 0;
|
||||||
@@ -110,15 +109,6 @@ int BonusList::totalValue() const
|
|||||||
{
|
{
|
||||||
Bonus *b = bonuses[i];
|
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)
|
switch(b->valType)
|
||||||
{
|
{
|
||||||
case Bonus::BASE_NUMBER:
|
case Bonus::BASE_NUMBER:
|
||||||
@@ -471,7 +461,9 @@ ui32 IBonusBearer::getMaxDamage() const
|
|||||||
|
|
||||||
si32 IBonusBearer::manaLimit() 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
|
int IBonusBearer::getPrimSkillLevel(int id) const
|
||||||
@@ -1042,7 +1034,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->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)
|
if(decision == ILimiter::DISCARD)
|
||||||
{
|
{
|
||||||
undecided.erase(i);
|
undecided.erase(i);
|
||||||
@@ -1173,14 +1165,6 @@ 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);
|
||||||
@@ -1319,25 +1303,28 @@ DLL_LINKAGE std::ostream & operator<<(std::ostream &out, const Bonus &bonus)
|
|||||||
|
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
Bonus * Bonus::addLimiter(TLimiterPtr Limiter)
|
Bonus * Bonus::addLimiter(TLimiterPtr Limiter)
|
||||||
{
|
{
|
||||||
if (limiter) //insert at the beginning of list
|
if (limiter)
|
||||||
{
|
{
|
||||||
TLimiterPtr temp = limiter;
|
//If we already have limiter list, retreive it
|
||||||
limiter = Limiter;
|
auto limiterList = std::dynamic_pointer_cast<LimiterList>(limiter);
|
||||||
limiter->limiter = temp;
|
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
|
else
|
||||||
{
|
{
|
||||||
limiter = Limiter;
|
limiter = Limiter;
|
||||||
}
|
}
|
||||||
return this;
|
return this;
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
int LimiterDecorator::limit(const BonusLimitationContext &context) const /*return true to drop the bonus */
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ILimiter::~ILimiter()
|
ILimiter::~ILimiter()
|
||||||
@@ -1434,16 +1421,6 @@ bool CPropagatorNodeType::shouldBeAttached(CBonusSystemNode *dest)
|
|||||||
return nodeType == dest->getNodeType();
|
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)
|
CreatureNativeTerrainLimiter::CreatureNativeTerrainLimiter(int TerrainType)
|
||||||
: terrainType(TerrainType)
|
: terrainType(TerrainType)
|
||||||
{
|
{
|
||||||
@@ -1547,3 +1524,32 @@ StackOwnerLimiter::StackOwnerLimiter(ui8 Owner)
|
|||||||
: owner(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 IPropagator;
|
||||||
class ICalculator;
|
class ICalculator;
|
||||||
class BonusList;
|
class BonusList;
|
||||||
class LimiterDecorator;
|
|
||||||
struct BonusLimitationContext;
|
|
||||||
struct BonusCalculationContext;
|
struct BonusCalculationContext;
|
||||||
|
|
||||||
typedef shared_ptr<BonusList> TBonusListPtr;
|
typedef shared_ptr<BonusList> TBonusListPtr;
|
||||||
typedef shared_ptr<LimiterDecorator> TLimiterPtr;
|
typedef shared_ptr<ILimiter> TLimiterPtr;
|
||||||
typedef shared_ptr<IPropagator> TPropagatorPtr;
|
typedef shared_ptr<IPropagator> TPropagatorPtr;
|
||||||
typedef shared_ptr<ICalculator> TCalculatorPtr;
|
typedef shared_ptr<ICalculator> TCalculatorPtr;
|
||||||
typedef std::vector<std::pair<int,std::string> > TModDescr; //modifiers values and their descriptions
|
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 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 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();
|
#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
|
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 : public LimiterDecorator
|
struct DLL_LINKAGE Bonus
|
||||||
{
|
{
|
||||||
enum BonusType
|
enum BonusType
|
||||||
{
|
{
|
||||||
@@ -283,6 +266,7 @@ struct DLL_LINKAGE Bonus : public LimiterDecorator
|
|||||||
si32 additionalInfo;
|
si32 additionalInfo;
|
||||||
ui8 effectRange; //if not NO_LIMIT, bonus will be omitted by default
|
ui8 effectRange; //if not NO_LIMIT, bonus will be omitted by default
|
||||||
|
|
||||||
|
TLimiterPtr limiter;
|
||||||
TPropagatorPtr propagator;
|
TPropagatorPtr propagator;
|
||||||
TCalculatorPtr calculator;
|
TCalculatorPtr calculator;
|
||||||
|
|
||||||
@@ -307,8 +291,7 @@ struct DLL_LINKAGE Bonus : public LimiterDecorator
|
|||||||
|
|
||||||
template <typename Handler> void serialize(Handler &h, const int version)
|
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 & limiter & propagator;
|
||||||
h & duration & type & subtype & source & val & sid & description & additionalInfo & turnsRemain & valType & effectRange & propagator;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool compareByAdditionalInfo(const Bonus *a, const Bonus *b)
|
static bool compareByAdditionalInfo(const Bonus *a, const Bonus *b)
|
||||||
@@ -363,9 +346,8 @@ struct DLL_LINKAGE Bonus : public LimiterDecorator
|
|||||||
|
|
||||||
std::string Description() const;
|
std::string Description() const;
|
||||||
|
|
||||||
Bonus * addLimiter(TLimiterPtr Limiter);
|
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 OVERRIDE; //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);
|
||||||
@@ -509,24 +491,17 @@ struct BonusLimitationContext
|
|||||||
const BonusList &alreadyAccepted;
|
const BonusList &alreadyAccepted;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct BonusCalculationContext
|
class DLL_LINKAGE ILimiter
|
||||||
{
|
|
||||||
const Bonus *b;
|
|
||||||
const CBonusSystemNode &node;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
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 OVERRIDE;
|
|
||||||
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)
|
||||||
{
|
{
|
||||||
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)
|
class DLL_LINKAGE CCreatureTypeLimiter : public ILimiter //affect only stacks of given creature (and optionally it's upgrades)
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|||||||
@@ -76,8 +76,8 @@ void registerTypes1(Serializer &s)
|
|||||||
s.template registerType<IPropagator>();
|
s.template registerType<IPropagator>();
|
||||||
s.template registerType<CPropagatorNodeType>();
|
s.template registerType<CPropagatorNodeType>();
|
||||||
|
|
||||||
s.template registerType<LimiterDecorator>();
|
|
||||||
s.template registerType<ILimiter>();
|
s.template registerType<ILimiter>();
|
||||||
|
s.template registerType<LimiterList>();
|
||||||
s.template registerType<CCreatureTypeLimiter>();
|
s.template registerType<CCreatureTypeLimiter>();
|
||||||
s.template registerType<HasAnotherBonusLimiter>();
|
s.template registerType<HasAnotherBonusLimiter>();
|
||||||
s.template registerType<CreatureNativeTerrainLimiter>();
|
s.template registerType<CreatureNativeTerrainLimiter>();
|
||||||
|
|||||||
Reference in New Issue
Block a user