1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-11-06 09:09:40 +02:00
This commit is contained in:
Michał W. Urbańczyk
2013-01-20 12:06:18 +00:00
parent 14909444b5
commit 0e826915ed
4 changed files with 74 additions and 93 deletions

View File

@@ -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)

View File

@@ -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);
}

View File

@@ -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:

View File

@@ -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>();