mirror of
https://github.com/vcmi/vcmi.git
synced 2025-07-17 01:32:21 +02:00
Fixed #484. Preliminary support for bonus limiters/
This commit is contained in:
@ -48,6 +48,7 @@
|
||||
#ifdef _WIN32
|
||||
#include "SDL_syswm.h"
|
||||
#endif
|
||||
#include <boost/foreach.hpp>
|
||||
|
||||
#if __MINGW32__
|
||||
#undef main
|
||||
@ -427,6 +428,19 @@ void processCommand(const std::string &message)
|
||||
if(const CGHeroInstance *h = dynamic_cast<const CGHeroInstance *>(adventureInt->selection))
|
||||
tlog0 << h->movement << "; max: " << h->maxMovePoints(true) << "/" << h->maxMovePoints(false) << std::endl;
|
||||
}
|
||||
else if(cn == "bonuses")
|
||||
{
|
||||
tlog0 << "Bonuses of " << adventureInt->selection->getHoverText() << std::endl
|
||||
<< adventureInt->selection->bonuses << std::endl;
|
||||
|
||||
tlog0 << "\nInherited bonuses:\n";
|
||||
TCNodes parents;
|
||||
adventureInt->selection->getParents(parents);
|
||||
BOOST_FOREACH(const CBonusSystemNode *parent, parents)
|
||||
{
|
||||
tlog0 << "\nBonuses from " << typeid(*parent).name() << std::endl << parent->bonuses << std::endl;
|
||||
}
|
||||
}
|
||||
else if(client && client->serv && client->serv->connected) //send to server
|
||||
{
|
||||
PlayerMessage pm(LOCPLINT->playerID,message);
|
||||
|
@ -128,6 +128,12 @@ void CCreature::addBonus(int val, int type, int subtype /*= -1*/)
|
||||
bonuses.push_back(added);
|
||||
}
|
||||
|
||||
bool CCreature::isMyUpgrade(const CCreature *anotherCre) const
|
||||
{
|
||||
//TODO upgrade of upgrade?
|
||||
return vstd::contains(upgrades, anotherCre->idNumber);
|
||||
}
|
||||
|
||||
int readNumber(int & befi, int & i, int andame, std::string & buf) //helper function for void CCreatureHandler::loadCreatures() and loadUnitAnimInfo()
|
||||
{
|
||||
befi=i;
|
||||
@ -338,11 +344,6 @@ void CCreatureHandler::loadCreatures()
|
||||
}
|
||||
}
|
||||
|
||||
// Map types names
|
||||
#define BONUS_NAME(x) ( #x, Bonus::x )
|
||||
static const std::map<std::string, int> type_list = map_list_of BONUS_LIST;
|
||||
#undef BONUS_NAME
|
||||
|
||||
////second part of reading cr_abils.txt////
|
||||
bool contReading = true;
|
||||
while(contReading) //main reading loop
|
||||
@ -363,10 +364,10 @@ void CCreatureHandler::loadCreatures()
|
||||
reader >> creatureID;
|
||||
reader >> type;
|
||||
|
||||
std::map<std::string, int>::const_iterator it = type_list.find(type);
|
||||
std::map<std::string, int>::const_iterator it = bonusNameMap.find(type);
|
||||
CCreature *cre = creatures[creatureID];
|
||||
|
||||
if (it == type_list.end())
|
||||
if (it == bonusNameMap.end())
|
||||
{
|
||||
if(type == "DOUBLE_WIDE")
|
||||
cre->doubleWide = true;
|
||||
@ -403,8 +404,8 @@ void CCreatureHandler::loadCreatures()
|
||||
std::string type;
|
||||
reader >> creatureID;
|
||||
reader >> type;
|
||||
std::map<std::string, int>::const_iterator it = type_list.find(type);
|
||||
if (it == type_list.end())
|
||||
std::map<std::string, int>::const_iterator it = bonusNameMap.find(type);
|
||||
if (it == bonusNameMap.end())
|
||||
{
|
||||
if(type == "DOUBLE_WIDE")
|
||||
creatures[creatureID]->doubleWide = false;
|
||||
|
@ -55,9 +55,11 @@ public:
|
||||
bool isEvil () const;
|
||||
si32 maxAmount(const std::vector<si32> &res) const; //how many creatures can be bought
|
||||
static int getQuantityID(const int & quantity); //0 - a few, 1 - several, 2 - pack, 3 - lots, 4 - horde, 5 - throng, 6 - swarm, 7 - zounds, 8 - legion
|
||||
bool isMyUpgrade(const CCreature *anotherCre) const;
|
||||
|
||||
void addBonus(int val, int type, int subtype = -1);
|
||||
|
||||
|
||||
template<typename RanGen>
|
||||
int getRandomAmount(RanGen &ranGen)
|
||||
{
|
||||
|
@ -973,50 +973,60 @@ void CGHeroInstance::initObj()
|
||||
{
|
||||
case 1:// creature speciality
|
||||
{
|
||||
speciality.growthsWithLevel = true;
|
||||
|
||||
bonus.type = Bonus::SPECIAL_CREATURE_LEV; // general info to indicate type of growing bonus
|
||||
bonus.additionalInfo = it->additionalinfo; //base creature ID
|
||||
speciality.bonuses.push_back (bonus);
|
||||
|
||||
std::vector<CCreature*>* creatures = &VLC->creh->creatures;
|
||||
int creLevel = (*creatures)[it->additionalinfo]->level;
|
||||
const CCreature &specCreature = *VLC->creh->creatures[it->additionalinfo]; //creature in which we have specialty
|
||||
|
||||
int creLevel = specCreature.level;
|
||||
if(!creLevel) //TODO: set fixed level for War Machines
|
||||
{
|
||||
if(it->additionalinfo == 146)
|
||||
creLevel = 5; //treat ballista as 5-level
|
||||
else
|
||||
{
|
||||
tlog2 << "Warning: unknown level of " << (*creatures)[it->additionalinfo]->namePl << std::endl;
|
||||
tlog2 << "Warning: unknown level of " << specCreature.namePl << std::endl;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
speciality.growthsWithLevel = true;
|
||||
bonus.type = Bonus::PRIMARY_SKILL; //TODO: limit to specific creature type
|
||||
bonus.valType = Bonus::ADDITIVE_VALUE;
|
||||
bonus.subtype = 1; //attack
|
||||
bonus.val = level * (*creatures)[it->additionalinfo]->attack / creLevel /20;
|
||||
speciality.bonuses.push_back (bonus);
|
||||
bonus.subtype = 2; //defense
|
||||
bonus.val = level * (*creatures)[it->additionalinfo]->defence / creLevel /20;
|
||||
speciality.bonuses.push_back (bonus);
|
||||
bonus.type = Bonus::STACKS_SPEED;
|
||||
bonus.val = 1; //+1 speed
|
||||
speciality.bonuses.push_back (bonus);
|
||||
for (std::set<ui32>::iterator i = (*creatures)[it->additionalinfo]->upgrades.begin();
|
||||
i != VLC->creh->creatures[it->additionalinfo]->upgrades.end(); i++)
|
||||
{
|
||||
bonus.val = (*i); // for all direct upgrades of that creature
|
||||
int levelFactor = level / creLevel; //round down
|
||||
double primSkillModifier = levelFactor / 20.0;
|
||||
|
||||
bonus.limiter = new CCreatureTypeLimiter(specCreature);
|
||||
bonus.type = Bonus::PRIMARY_SKILL;
|
||||
bonus.subtype = 1; //attack
|
||||
bonus.val = level * (*creatures)[*i]->attack / (*creatures)[*i]->level /20;
|
||||
bonus.valType = Bonus::ADDITIVE_VALUE;
|
||||
|
||||
bonus.subtype = PrimarySkill::ATTACK;
|
||||
bonus.val = std::ceil(primSkillModifier * specCreature.attack);
|
||||
speciality.bonuses.push_back (bonus);
|
||||
bonus.subtype = 2; //defense
|
||||
bonus.val = level * (*creatures)[*i]->defence / (*creatures)[*i]->level /20;
|
||||
|
||||
bonus.subtype = PrimarySkill::DEFENSE;
|
||||
bonus.val = std::ceil(primSkillModifier * specCreature.defence);
|
||||
speciality.bonuses.push_back (bonus);
|
||||
|
||||
bonus.type = Bonus::STACKS_SPEED;
|
||||
bonus.val = 1; //+1 speed
|
||||
speciality.bonuses.push_back (bonus);
|
||||
}
|
||||
|
||||
// for (std::set<ui32>::iterator i = (*creatures)[it->additionalinfo]->upgrades.begin();
|
||||
// i != VLC->creh->creatures[it->additionalinfo]->upgrades.end(); i++)
|
||||
// {
|
||||
// bonus.val = (*i); // for all direct upgrades of that creature
|
||||
// bonus.type = Bonus::PRIMARY_SKILL;
|
||||
// bonus.subtype = 1; //attack
|
||||
// bonus.val = level * (*creatures)[*i]->attack / (*creatures)[*i]->level /20;
|
||||
// speciality.bonuses.push_back (bonus);
|
||||
// bonus.subtype = 2; //defense
|
||||
// bonus.val = level * (*creatures)[*i]->defence / (*creatures)[*i]->level /20;
|
||||
// speciality.bonuses.push_back (bonus);
|
||||
// bonus.type = Bonus::STACKS_SPEED;
|
||||
// bonus.val = 1; //+1 speed
|
||||
// speciality.bonuses.push_back (bonus);
|
||||
// }
|
||||
}
|
||||
break;
|
||||
case 2://secondary skill
|
||||
|
@ -252,6 +252,7 @@ void CStackInstance::init()
|
||||
type = NULL;
|
||||
idRand = -1;
|
||||
armyObj = NULL;
|
||||
nodeType = STACK;
|
||||
}
|
||||
|
||||
int CStackInstance::getQuantityID() const
|
||||
|
@ -117,11 +117,11 @@ class CObjectCaller : public IObjectCaller
|
||||
public:
|
||||
void preInit()
|
||||
{
|
||||
T::preInit();
|
||||
//T::preInit();
|
||||
}
|
||||
void postInit()
|
||||
{
|
||||
T::postInit();
|
||||
//T::postInit();
|
||||
}
|
||||
};
|
||||
|
||||
@ -148,14 +148,14 @@ public:
|
||||
|
||||
void preInit()
|
||||
{
|
||||
for (size_t i = 0; i < apps.size(); i++)
|
||||
apps[i]->preInit();
|
||||
// for (size_t i = 0; i < apps.size(); i++)
|
||||
// apps[i]->preInit();
|
||||
}
|
||||
|
||||
void postInit()
|
||||
{
|
||||
for (size_t i = 0; i < apps.size(); i++)
|
||||
apps[i]->postInit();
|
||||
// for (size_t i = 0; i < apps.size(); i++)
|
||||
// apps[i]->postInit();
|
||||
}
|
||||
} *objCaller = NULL;
|
||||
|
||||
@ -2365,7 +2365,7 @@ int3 CGameState::guardingCreaturePosition (int3 pos) const
|
||||
if (map->isInTheMap(pos))
|
||||
{
|
||||
TerrainTile &tile = map->terrain[pos.x][pos.y][pos.z];
|
||||
if (tile.visitable)
|
||||
if (tile.visitable && (tile.tertype == TerrainTile::water) == (posTile.tertype == TerrainTile::water))
|
||||
{
|
||||
BOOST_FOREACH (CGObjectInstance* obj, tile.visitableObjects)
|
||||
{
|
||||
|
@ -5,10 +5,16 @@
|
||||
#include "../hch/CSpellHandler.h"
|
||||
#include <sstream>
|
||||
#include "../hch/CCreatureHandler.h"
|
||||
#include <boost/assign/list_of.hpp>
|
||||
#include "CCreatureSet.h"
|
||||
|
||||
#define FOREACH_CONST_PARENT(pname, source) TCNodes parents; getParents(parents, source); BOOST_FOREACH(const CBonusSystemNode *pname, parents)
|
||||
#define FOREACH_PARENT(pname, source) TNodes parents; getParents(parents, source); BOOST_FOREACH(CBonusSystemNode *pname, parents)
|
||||
|
||||
#define BONUS_NAME(x) ( #x, Bonus::x )
|
||||
DLL_EXPORT const std::map<std::string, int> bonusNameMap = boost::assign::map_list_of BONUS_LIST;
|
||||
#undef BONUS_NAME
|
||||
|
||||
int DLL_EXPORT BonusList::totalValue() const
|
||||
{
|
||||
int base = 0;
|
||||
@ -75,6 +81,19 @@ void DLL_EXPORT BonusList::getBonuses(BonusList &out, const CSelector &selector,
|
||||
out.push_back(*i);
|
||||
}
|
||||
|
||||
void BonusList::limit(const CBonusSystemNode &node)
|
||||
{
|
||||
for(const_iterator i = begin(); i != end(); i++)
|
||||
{
|
||||
if(i->limiter && i->limiter->limit(*i, node))
|
||||
{
|
||||
const_iterator toErase = i;
|
||||
i--;
|
||||
erase(toErase);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int CBonusSystemNode::valOfBonuses(Bonus::BonusType type, int subtype /*= -1*/) const
|
||||
{
|
||||
CSelector s = Selector::type(type);
|
||||
@ -161,6 +180,9 @@ void CBonusSystemNode::getBonuses(BonusList &out, const CSelector &selector, con
|
||||
bonuses.getBonuses(out, selector);
|
||||
FOREACH_CONST_PARENT(p, root ? root : this)
|
||||
p->getBonuses(out, selector, root ? root : this);
|
||||
|
||||
if(!root)
|
||||
out.limit(*this);
|
||||
}
|
||||
|
||||
BonusList CBonusSystemNode::getBonuses(const CSelector &selector, const CBonusSystemNode *root /*= NULL*/) const
|
||||
@ -175,6 +197,9 @@ void CBonusSystemNode::getBonuses(BonusList &out, const CSelector &selector, con
|
||||
bonuses.getBonuses(out, selector, limit);
|
||||
FOREACH_CONST_PARENT(p, root ? root : this)
|
||||
p->getBonuses(out, selector, limit, root ? root : this);
|
||||
|
||||
if(!root)
|
||||
out.limit(*this);
|
||||
}
|
||||
|
||||
BonusList CBonusSystemNode::getBonuses(const CSelector &selector, const CSelector &limit, const CBonusSystemNode *root /*= NULL*/) const
|
||||
@ -245,6 +270,16 @@ ui16 CBonusSystemNode::MaxHealth() const
|
||||
return valOfBonuses(Bonus::STACK_HEALTH);
|
||||
}
|
||||
|
||||
CBonusSystemNode::CBonusSystemNode()
|
||||
{
|
||||
nodeType = UNKNOWN;
|
||||
}
|
||||
|
||||
CBonusSystemNode::~CBonusSystemNode()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
int NBonus::valOf(const CBonusSystemNode *obj, Bonus::BonusType type, int subtype /*= -1*/)
|
||||
{
|
||||
if(obj)
|
||||
@ -347,3 +382,64 @@ namespace Selector
|
||||
return sel(dummy);
|
||||
}
|
||||
}
|
||||
|
||||
DLL_EXPORT std::ostream & operator<<(std::ostream &out, const BonusList &bonusList)
|
||||
{
|
||||
int i = 0;
|
||||
BOOST_FOREACH(const Bonus &b, bonusList)
|
||||
{
|
||||
out << "Bonus " << i++ << "\n" << b << std::endl;
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
DLL_EXPORT std::ostream & operator<<(std::ostream &out, const Bonus &bonus)
|
||||
{
|
||||
for(std::map<std::string, int>::const_iterator i = bonusNameMap.begin(); i != bonusNameMap.end(); i++)
|
||||
if(i->second == bonus.type)
|
||||
out << "\tType: " << i->first << " \t";
|
||||
|
||||
#define printField(field) out << "\t" #field ": " << (int)bonus.field << "\n"
|
||||
printField(val);
|
||||
printField(subtype);
|
||||
printField(duration);
|
||||
printField(source);
|
||||
printField(id);
|
||||
printField(additionalInfo);
|
||||
printField(turnsRemain);
|
||||
printField(valType);
|
||||
printField(effectRange);
|
||||
#undef printField
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
ILimiter::~ILimiter()
|
||||
{
|
||||
}
|
||||
|
||||
bool ILimiter::limit(const Bonus &b, const CBonusSystemNode &node) const /*return true to drop the bonus */
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CCreatureTypeLimiter::limit(const Bonus &b, const CBonusSystemNode &node) const
|
||||
{
|
||||
if(node.nodeType != CBonusSystemNode::STACK)
|
||||
return true;
|
||||
|
||||
const CCreature *c = (static_cast<const CStackInstance *>(&node))->type;
|
||||
|
||||
return c != creature && (!includeUpgrades || !creature->isMyUpgrade(c)); //drop bonus if it's not our creature and (we dont check upgrades or its not our upgrade)
|
||||
}
|
||||
|
||||
CCreatureTypeLimiter::CCreatureTypeLimiter(const CCreature &Creature, ui8 IncludeUpgrades /*= true*/)
|
||||
:creature(&Creature), includeUpgrades(IncludeUpgrades)
|
||||
{
|
||||
}
|
||||
|
||||
CCreatureTypeLimiter::CCreatureTypeLimiter()
|
||||
{
|
||||
creature = NULL;
|
||||
includeUpgrades = false;
|
||||
}
|
@ -19,17 +19,17 @@
|
||||
typedef ui8 TBonusType;
|
||||
typedef si32 TBonusSubtype;
|
||||
|
||||
|
||||
class CCreature;
|
||||
class CSpell;
|
||||
struct Bonus;
|
||||
class CBonusSystemNode;
|
||||
class ILimiter;
|
||||
|
||||
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;
|
||||
typedef boost::function<bool(const Bonus&)> CSelector;
|
||||
|
||||
|
||||
namespace PrimarySkill
|
||||
{
|
||||
enum { ATTACK, DEFENSE, SPELL_POWER, KNOWLEDGE};
|
||||
@ -223,6 +223,8 @@ struct DLL_EXPORT Bonus
|
||||
si32 additionalInfo;
|
||||
ui8 effectRange; //if not NO_LIMIT, bonus will be ommitted by default
|
||||
|
||||
ILimiter *limiter;
|
||||
|
||||
std::string description;
|
||||
|
||||
Bonus(ui8 Dur, ui8 Type, ui8 Src, si32 Val, ui32 ID, std::string Desc, si32 Subtype=-1)
|
||||
@ -232,6 +234,7 @@ struct DLL_EXPORT Bonus
|
||||
turnsRemain = 0;
|
||||
valType = ADDITIVE_VALUE;
|
||||
effectRange = NO_LIMIT;
|
||||
limiter = NULL;
|
||||
}
|
||||
Bonus(ui8 Dur, ui8 Type, ui8 Src, si32 Val, ui32 ID, si32 Subtype=-1, ui8 ValType = ADDITIVE_VALUE)
|
||||
:duration(Dur), type(Type), subtype(Subtype), source(Src), val(Val), id(ID), valType(ValType)
|
||||
@ -239,6 +242,7 @@ struct DLL_EXPORT Bonus
|
||||
additionalInfo = -1;
|
||||
turnsRemain = 0;
|
||||
effectRange = NO_LIMIT;
|
||||
limiter = NULL;
|
||||
}
|
||||
Bonus()
|
||||
{
|
||||
@ -247,6 +251,7 @@ struct DLL_EXPORT Bonus
|
||||
turnsRemain = 0;
|
||||
valType = ADDITIVE_VALUE;
|
||||
effectRange = NO_LIMIT;
|
||||
limiter = NULL;
|
||||
}
|
||||
|
||||
// //comparison
|
||||
@ -263,7 +268,7 @@ struct DLL_EXPORT Bonus
|
||||
|
||||
template <typename Handler> void serialize(Handler &h, const int version)
|
||||
{
|
||||
h & duration & type & subtype & source & val & id & description & additionalInfo & turnsRemain & valType & effectRange;
|
||||
h & duration & type & subtype & source & val & id & description & additionalInfo & turnsRemain & valType & effectRange & limiter;
|
||||
}
|
||||
|
||||
static bool OneDay(const Bonus &hb)
|
||||
@ -307,6 +312,8 @@ struct DLL_EXPORT Bonus
|
||||
std::string Description() const;
|
||||
};
|
||||
|
||||
DLL_EXPORT std::ostream & operator<<(std::ostream &out, const Bonus &bonus);
|
||||
|
||||
class BonusList : public std::list<Bonus>
|
||||
{
|
||||
public:
|
||||
@ -319,16 +326,35 @@ public:
|
||||
DLL_EXPORT Bonus * getFirst(const CSelector &select);
|
||||
DLL_EXPORT const Bonus * getFirst(const CSelector &select) const;
|
||||
|
||||
void limit(const CBonusSystemNode &node); //erases bonuses using limitor
|
||||
|
||||
template <typename Handler> void serialize(Handler &h, const int version)
|
||||
{
|
||||
h & static_cast<std::list<Bonus>&>(*this);
|
||||
}
|
||||
};
|
||||
|
||||
DLL_EXPORT std::ostream & operator<<(std::ostream &out, const BonusList &bonusList);
|
||||
|
||||
class DLL_EXPORT ILimiter
|
||||
{
|
||||
public:
|
||||
virtual ~ILimiter();
|
||||
|
||||
virtual bool limit(const Bonus &b, const CBonusSystemNode &node) const; //return true to drop the bonus
|
||||
|
||||
template <typename Handler> void serialize(Handler &h, const int version)
|
||||
{}
|
||||
};
|
||||
|
||||
class DLL_EXPORT CBonusSystemNode
|
||||
{
|
||||
public:
|
||||
BonusList bonuses;
|
||||
ui8 nodeType;
|
||||
|
||||
CBonusSystemNode();
|
||||
virtual ~CBonusSystemNode();
|
||||
|
||||
//new bonusing node interface
|
||||
// * selector is predicate that tests if HeroBonus matches our criteria
|
||||
@ -366,8 +392,13 @@ public:
|
||||
|
||||
template <typename Handler> void serialize(Handler &h, const int version)
|
||||
{
|
||||
h & bonuses;
|
||||
h & bonuses & nodeType;
|
||||
}
|
||||
|
||||
enum ENodeTypes
|
||||
{
|
||||
UNKNOWN, STACK
|
||||
};
|
||||
};
|
||||
|
||||
namespace NBonus
|
||||
@ -450,6 +481,23 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
class CCreatureTypeLimiter : public ILimiter //affect only stacks of given creature (and optionally it's upgrades)
|
||||
{
|
||||
public:
|
||||
const CCreature *creature;
|
||||
ui8 includeUpgrades;
|
||||
|
||||
CCreatureTypeLimiter();
|
||||
CCreatureTypeLimiter(const CCreature &Creature, ui8 IncludeUpgrades = true);
|
||||
|
||||
bool limit(const Bonus &b, const CBonusSystemNode &node) const;
|
||||
|
||||
template <typename Handler> void serialize(Handler &h, const int version)
|
||||
{
|
||||
h & creature & includeUpgrades;
|
||||
}
|
||||
};
|
||||
|
||||
namespace Selector
|
||||
{
|
||||
extern DLL_EXPORT CSelectFieldEqual<TBonusType> type;
|
||||
@ -466,3 +514,5 @@ namespace Selector
|
||||
bool DLL_EXPORT matchesType(const CSelector &sel, TBonusType type);
|
||||
bool DLL_EXPORT matchesTypeSubtype(const CSelector &sel, TBonusType type, TBonusSubtype subtype);
|
||||
}
|
||||
|
||||
extern DLL_EXPORT const std::map<std::string, int> bonusNameMap;
|
@ -20,6 +20,7 @@
|
||||
template<typename Serializer> DLL_EXPORT
|
||||
void registerTypes1(Serializer &s)
|
||||
{
|
||||
//map objects
|
||||
s.template registerType<CGHeroPlaceholder>();
|
||||
s.template registerType<CGHeroInstance>();
|
||||
s.template registerType<CGTownInstance>();
|
||||
@ -64,6 +65,9 @@ void registerTypes1(Serializer &s)
|
||||
s.template registerType<CGLighthouse>();
|
||||
s.template registerType<CGMarket>();
|
||||
s.template registerType<CGBlackMarket>();
|
||||
//end of objects
|
||||
s.template registerType<ILimiter>();
|
||||
s.template registerType<CCreatureTypeLimiter>();
|
||||
}
|
||||
|
||||
template<typename Serializer> DLL_EXPORT
|
||||
|
Reference in New Issue
Block a user