1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-08-13 19:54:17 +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->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)

View File

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

View File

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

View File

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