1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-04-15 11:46:56 +02:00

- Parsing propagators and limiters

- Experimental support for chaining limiters
- Added missing abilities, propagators and limiters to artifacts
- Sketch of Calculator for bonuses, ignore it for now
This commit is contained in:
DjWarmonger 2013-01-16 13:02:01 +00:00
parent 53b684180d
commit d7c9377843
5 changed files with 1348 additions and 1172 deletions

View File

@ -1189,10 +1189,18 @@
"id" : 82,
"type" : ["HERO"]
},
"recantersCloak": //TODO: implement?
"recantersCloak":
{
"id" : 83,
"type" : ["HERO"]
"type" : ["HERO"],
"bonuses": [
{
"type" : "BLOCK_MAGIC_ABOVE",
"val" : 2,
"valueType" : "INDEPENDENT_MIN",
"propagator": "BATTLE_WIDE"
}
]
},
"spiritOfOppression":
{
@ -1283,14 +1291,14 @@
{
"bonuses" : [
{
"limiter" : "SHOOTER_ONLY",
"limiters" : ["SHOOTER_ONLY"],
"subtype" : 0,
"type" : "NO_DISTANCE_PENALTY",
"val" : 0,
"valueType" : "ADDITIVE_VALUE"
},
{
"limiter" : "SHOOTER_ONLY",
"limiters" : ["SHOOTER_ONLY"],
"subtype" : 0,
"type" : "NO_WALL_PENALTY",
"val" : 0,
@ -1453,7 +1461,7 @@
{
"bonuses" : [
{
"limiter" : "IS_UNDEAD",
"limiters" : ["IS_UNDEAD"],
"subtype" : "spell.destroyUndead",
"type" : "SPELL_IMMUNITY",
"val" : 0,
@ -1642,30 +1650,70 @@
"id" : 117,
"type" : ["HERO"]
},
"legsOfLegion": //TODO: implement
"legsOfLegion":
{
"id" : 118,
"type" : ["HERO"]
"type" : ["HERO"],
"bonuses" : [
{
"type" : "CREATURE_GROWTH",
"subtype" : 2,
"val" : 5,
"propagator": "VISITED_TOWN_AND_VISITOR"
}
]
},
"loinsOfLegion":
{
"id" : 119,
"type" : ["HERO"]
"type" : ["HERO"],
"bonuses" : [
{
"type" : "CREATURE_GROWTH",
"subtype" : 3,
"val" : 4,
"propagator": "VISITED_TOWN_AND_VISITOR"
}
]
},
"torsoOfLegion":
{
"id" : 120,
"type" : ["HERO"]
"type" : ["HERO"],
"bonuses" : [
{
"type" : "CREATURE_GROWTH",
"subtype" : 4,
"val" : 3,
"propagator": "VISITED_TOWN_AND_VISITOR"
}
]
},
"armsOfLegion":
{
"id" : 121,
"type" : ["HERO"]
"type" : ["HERO"],
"bonuses" : [
{
"type" : "CREATURE_GROWTH",
"subtype" : 5,
"val" : 2,
"propagator": "VISITED_TOWN_AND_VISITOR"
}
]
},
"headOfLegion":
{
"id" : 122,
"type" : ["HERO"]
"type" : ["HERO"],
"bonuses" : [
{
"type" : "CREATURE_GROWTH",
"subtype" : 6,
"val" : 1,
"propagator": "VISITED_TOWN_AND_VISITOR"
}
]
},
"seaCaptainsHat":
{
@ -1709,28 +1757,40 @@
"id" : 124,
"type" : ["HERO"]
},
"shacklesOfWar": //TODO: implement
"shacklesOfWar":
{
"id" : 125,
"type" : ["HERO"]
"type" : ["HERO"],
"bonuses" : [
{
"type" : "BATTLE_NO_FLEEING",
"propagator": "BATTLE_WIDE"
}
]
},
"orbOfInhibition": //TODO: implement
"orbOfInhibition":
{
"id" : 126,
"type" : ["HERO"]
"type" : ["HERO"],
"bonuses" : [
{
"type" : "BLOCK_ALL_MAGIC",
"propagator": "BATTLE_WIDE"
}
]
},
"vialOfDragonBlood": //TODO: limiter
"vialOfDragonBlood":
{
"bonuses" : [
{
"limiter" : "DRAGON_NATURE",
"limiters" : ["DRAGON_NATURE"],
"subtype" : 0,
"type" : "PRIMARY_SKILL",
"val" : 5,
"valueType" : "BASE_NUMBER"
},
{
"limiter" : "DRAGON_NATURE",
"limiters" : ["DRAGON_NATURE"],
"subtype" : 1,
"type" : "PRIMARY_SKILL",
"val" : 5,
@ -1889,7 +1949,7 @@
"ribCage"
]
},
"statueOfLegion": //TODO: implement
"statueOfLegion":
{
"id" : 133,
"type" : ["HERO"],
@ -1900,19 +1960,50 @@
"torsoOfLegion",
"armsOfLegion",
"headOfLegion"
],
"bonuses" : [
{
"type" : "CREATURE_GROWTH_PERCENT",
"val" : 50,
"propagator": "PLAYER_PROPAGATOR"
}
]
},
"powerOfTheDragonFather": //TODO: add stat bonus
"powerOfTheDragonFather":
{
"id" : 134,
"type" : ["HERO"],
"bonuses" : [
{
"type" : "LEVEL_SPELL_IMMUNITY",
"val" : 4,
"valueType" : "INDEPENDENT_MAX"
},
{
"subtype" : 0,
"type" : "PRIMARY_SKILL",
"val" : 6,
"valueType" : "BASE_NUMBER"
},
{
"subtype" : 1,
"type" : "PRIMARY_SKILL",
"val" : 6,
"valueType" : "BASE_NUMBER"
},
{
"subtype" : 2,
"type" : "PRIMARY_SKILL",
"val" : 6,
"valueType" : "BASE_NUMBER"
},
{
"subtype" : 3,
"type" : "PRIMARY_SKILL",
"val" : 6,
"valueType" : "BASE_NUMBER"
}
],
"id" : 134,
"type" : ["HERO"],
"components":
[
"quietEyeOfTheDragon",
@ -1963,25 +2054,27 @@
"seaCaptainsHat"
]
},
"bowOfTheSharpshooter": //TODO: limiters
"bowOfTheSharpshooter":
{
"bonuses" : [
{
"limiter" : "SHOOTER_ONLY",
"limiters" : [
"SHOOTER_ONLY",
],
"subtype" : 0,
"type" : "NO_DISTANCE_PENALTY",
"val" : 0,
"valueType" : "ADDITIVE_VALUE"
},
{
"limiter" : "SHOOTER_ONLY",
"limiters" : ["SHOOTER_ONLY"],
"subtype" : 0,
"type" : "NO_WALL_PENALTY",
"val" : 0,
"valueType" : "ADDITIVE_VALUE"
},
{
"limiter" : "SHOOTER_ONLY",
"limiters" : ["SHOOTER_ONLY"],
"subtype" : 0,
"type" : "FREE_SHOOTING",
"val" : 0,

View File

@ -65,7 +65,8 @@ const bmap<std::string, TLimiterPtr> bonusLimiterMap = boost::assign::map_list_o
const bmap<std::string, TPropagatorPtr> bonusPropagatorMap = boost::assign::map_list_of
("BATTLE_WIDE", make_shared<CPropagatorNodeType>(CBonusSystemNode::BATTLE))
("VISITED_TOWN_AND_VISITOR", make_shared<CPropagatorNodeType>(CBonusSystemNode::TOWN_AND_VISITOR));
("VISITED_TOWN_AND_VISITOR", make_shared<CPropagatorNodeType>(CBonusSystemNode::TOWN_AND_VISITOR))
("PLAYER_PROPAGATOR", make_shared<CPropagatorNodeType>(CBonusSystemNode::PLAYER));
#define BONUS_LOG_LINE(x) tlog5 << x << std::endl
@ -95,6 +96,7 @@ BonusList& BonusList::operator=(const BonusList &bonusList)
int BonusList::totalValue() const
{
int tempVal = 0;
int base = 0;
int percentToBase = 0;
int percentToAll = 0;
@ -108,6 +110,15 @@ 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:
@ -1156,12 +1167,6 @@ Bonus::~Bonus()
{
}
Bonus * Bonus::addLimiter(TLimiterPtr Limiter)
{
limiter = Limiter;
return this;
}
Bonus * Bonus::addPropagator(TPropagatorPtr Propagator)
{
propagator = Propagator;
@ -1314,6 +1319,21 @@ DLL_LINKAGE std::ostream & operator<<(std::ostream &out, const Bonus &bonus)
return out;
}
Bonus * Bonus::addLimiter(TLimiterPtr Limiter)
{
if (next) //insert at the beginning of list
{
TLimiterPtr temp = next;
next = Limiter;
next->next = temp;
}
else
{
next = Limiter;
}
return this;
}
int LimiterDecorator::limit(const BonusLimitationContext &context) const /*return true to drop the bonus */
{

View File

@ -18,13 +18,16 @@ struct Bonus;
class CBonusSystemNode;
class ILimiter;
class IPropagator;
class ICalculator;
class BonusList;
class LimiterDecorator;
struct BonusLimitationContext;
struct BonusCalculationContext;
typedef shared_ptr<BonusList> TBonusListPtr;
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
typedef std::set<CBonusSystemNode*> TNodes;
typedef std::set<const CBonusSystemNode*> TCNodes;
@ -277,6 +280,7 @@ struct DLL_LINKAGE Bonus : public LimiterDecorator
TLimiterPtr limiter;
TPropagatorPtr propagator;
TCalculatorPtr calculator;
std::string description;
@ -354,8 +358,8 @@ struct DLL_LINKAGE Bonus : public LimiterDecorator
std::string Description() const;
Bonus *addLimiter(TLimiterPtr Limiter); //returns this for convenient chain-calls
Bonus *addPropagator(TPropagatorPtr Propagator); //returns this for convenient chain-calls
Bonus * addLimiter(TLimiterPtr Limiter);
Bonus * addPropagator(TPropagatorPtr Propagator); //returns this for convenient chain-calls
int limit(const BonusLimitationContext &context) const; //for backward compatibility
};
@ -500,6 +504,13 @@ struct BonusLimitationContext
const BonusList &alreadyAccepted;
};
struct BonusCalculationContext
{
const Bonus *b;
const CBonusSystemNode &node;
};
class DLL_LINKAGE ILimiter : public LimiterDecorator
{
public:
@ -895,6 +906,18 @@ extern DLL_LINKAGE const std::map<std::string, int> bonusNameMap, bonusValueMap,
extern DLL_LINKAGE const bmap<std::string, TLimiterPtr> bonusLimiterMap;
extern DLL_LINKAGE const bmap<std::string, TPropagatorPtr> bonusPropagatorMap;
class DLL_LINKAGE ICalculator //calculate value of bonus on-the-fly
{
public:
enum EDecision {ACCEPT, DISCARD, NOT_SURE};
virtual si32 val(const BonusCalculationContext &context) const {return 0;};
virtual ~ICalculator(){};
template <typename Handler> void serialize(Handler &h, const int version)
{}
};
// BonusList template that requires full interface of CBonusSystemNode
template <class InputIterator>
void BonusList::insert(const int position, InputIterator first, InputIterator last)

View File

@ -903,25 +903,6 @@ Bonus * JsonUtils::parseBonus (const JsonVector &ability_vec) //TODO: merge with
b->turnsRemain = 0;
return b;
}
template <typename T>
const T & parseByMapStr(const std::map<std::string, T> & map, const std::string & val, std::string err)
{
static T defaultValue;
auto it = map.find(val);
if (it == map.end())
{
tlog1 << "Error: invalid " << err << val << std::endl;
return defaultValue;
}
else
{
return it->second;
}
}
template <typename T>
const T & parseByMap(const std::map<std::string, T> & map, const JsonNode * val, std::string err)
{
@ -929,11 +910,20 @@ const T & parseByMap(const std::map<std::string, T> & map, const JsonNode * val,
if (!val->isNull())
{
std::string type = val->String();
return parseByMapStr(map, type, err);
auto it = map.find(type);
if (it == map.end())
{
tlog1 << "Error: invalid " << err << type << std::endl;
return defaultValue;
}
else
{
return it->second;
}
}
else
return defaultValue;
}
};
void JsonUtils::resolveIdentifier (si32 &var, const JsonNode &node, std::string name)
{
@ -958,6 +948,24 @@ void JsonUtils::resolveIdentifier (si32 &var, const JsonNode &node, std::string
}
}
void JsonUtils::resolveIdentifier (const JsonNode &node, si32 &var)
{
switch (node.getType())
{
case JsonNode::DATA_FLOAT:
var = node.Float();
break;
case JsonNode::DATA_STRING:
VLC->modh->identifiers.requestIdentifier (node.String(), [&](si32 identifier)
{
var = identifier;
});
break;
default:
tlog2 << "Error! Wrong indentifier used for identifier!";
}
}
Bonus * JsonUtils::parseBonus (const JsonNode &ability)
{
@ -1004,25 +1012,56 @@ Bonus * JsonUtils::parseBonus (const JsonNode &ability)
b->valType = parseByMap(bonusLimitEffect, value, "effect range ");
value = &ability["duration"];
if (!value->isNull())
{
int dur = 0;
std::vector<std::string> strs;
boost::split(strs, value->String(), boost::is_any_of("\t "));
BOOST_FOREACH(auto s, strs)
{
dur |=parseByMapStr(bonusDurationMap, s, "duration type ");
}
b->duration = dur;
}
b->valType = parseByMap(bonusDurationMap, value, "duration type ");
value = &ability["source"];
if (!value->isNull())
b->valType = parseByMap(bonusSourceMap, value, "source type ");
value = &ability["limiter"];
value = &ability["limiters"];
if (!value->isNull())
b->limiter = parseByMap(bonusLimiterMap, value, "limiter type ");
{
BOOST_FOREACH (const JsonNode & limiter, value->Vector())
{
switch (limiter.getType())
{
case JsonNode::DATA_STRING: //pre-defined limiters
b->limiter = parseByMap(bonusLimiterMap, &limiter, "limiter type ");
break;
case JsonNode::DATA_STRUCT: //customisable limiters
{
shared_ptr<ILimiter> l;
if (limiter["type"].String() == "CREATURE_TYPE_LIMITER")
{
//continue;
//l = make_shared<CCreatureTypeLimiter>(); //TODO: How the hell resolve pointer to creature?
}
if (limiter["type"].String() == "HAS_ANOTHER_BONUS_LIMITER")
{
shared_ptr<HasAnotherBonusLimiter> l2 = make_shared<HasAnotherBonusLimiter>();
const JsonVector vec = limiter["parameters"].Vector();
std::string anotherBonusType = vec[0].String();
auto it = bonusNameMap.find (anotherBonusType);
if (it == bonusNameMap.end())
{
tlog1 << "Error: invalid ability type " << anotherBonusType << std::endl;
continue;
}
l2->type = it->second;
if (vec.size() > 1 )
{
resolveIdentifier (vec[1], l2->subtype);
l2->isSubtypeRelevant = true;
}
l = l2;
}
b->addLimiter(l);
}
break;
}
}
}
value = &ability["propagator"];
if (!value->isNull())

View File

@ -118,6 +118,7 @@ namespace JsonUtils
DLL_LINKAGE Bonus * parseBonus (const JsonNode &bonus);
DLL_LINKAGE void unparseBonus (JsonNode &node, const Bonus * bonus);
DLL_LINKAGE void resolveIdentifier (si32 &var, const JsonNode &node, std::string name);
DLL_LINKAGE void resolveIdentifier (const JsonNode &node, si32 &var);
/// recursivly merges source into dest, replacing identical fields
/// struct : recursively calls this function