1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-03-25 21:38:59 +02:00

* Bonus system caching updated, partially rewritten, much more robust, thread-safe

* Adjusted projectile speed, trebuchet canon speed
This commit is contained in:
beegee1 2011-07-13 18:39:02 +00:00
parent a7577ccb6b
commit 55e7959fd9
19 changed files with 396 additions and 173 deletions

View File

@ -631,8 +631,8 @@ bool CBattleStackMoved::init()
}
//unit reversed
if(owner->moveSh <= 0)
owner->moveSh = CCS->soundh->playSound(battle_sound(movedStack->getCreature(), move), -1);
// if(owner->moveSh <= 0)
// owner->moveSh = CCS->soundh->playSound(battle_sound(movedStack->getCreature(), move), -1);
//step shift calculation
posX = owner->creAnims[stack->ID]->pos.x, posY = owner->creAnims[stack->ID]->pos.y; // for precise calculations ;]
@ -1008,7 +1008,7 @@ bool CShootingAnim::init()
Point xycoord = CBattleHex::getXYUnitAnim(shooter->position, true, shooter, owner);
Point destcoord;
int animSpeed = 40; // flight speed of projectile
// The "master" point where all projectile positions relate to.
static const Point projectileOrigin(181, 252);
@ -1037,7 +1037,8 @@ bool CShootingAnim::init()
spi.x = xycoord.x + projectileOrigin.x + shooterInfo->rightMissleOffsetX;
spi.y = xycoord.y + projectileOrigin.y + shooterInfo->rightMissleOffsetY;
}
double animSpeed = 23.0 * owner->getAnimSpeed(); // flight speed of projectile
spi.lastStep = sqrt((float)((destcoord.x - spi.x)*(destcoord.x - spi.x) + (destcoord.y - spi.y) * (destcoord.y - spi.y))) / animSpeed;
if(spi.lastStep == 0)
spi.lastStep = 1;
@ -1069,12 +1070,12 @@ bool CShootingAnim::init()
{
int curveID = it->second;
spi.catapultInfo = trajectoryCurves[curveID];
animSpeed /= 2;
double animSpeed = 3.318 * owner->getAnimSpeed();
spi.lastStep = (spi.catapultInfo->toX - spi.catapultInfo->fromX) / animSpeed;
spi.dx = animSpeed;
spi.dy = 0;
spi.x = xycoord.x + projectileOrigin.x + shooterInfo->rightMissleOffsetX + 17;
spi.y = xycoord.y + projectileOrigin.y + shooterInfo->rightMissleOffsetY + 10;
spi.x = xycoord.x + projectileOrigin.x + shooterInfo->rightMissleOffsetX + 17.;
spi.y = xycoord.y + projectileOrigin.y + shooterInfo->rightMissleOffsetY + 10.;
// Add explosion anim
int xEnd = spi.x + spi.lastStep * spi.dx;
@ -3333,7 +3334,6 @@ void CBattleInterface::setAnimSpeed(int set)
int CBattleInterface::getAnimSpeed() const
{
return curInt->sysOpts.animSpeed;
curInt->sysOpts.settingsChanged();
}
void CBattleInterface::activateStack()
@ -3654,8 +3654,8 @@ void CBattleInterface::projectileShowHelper(SDL_Surface * to)
// of it for drawing
if (it->catapultInfo)
{
dst.x -= 17;
dst.y -= 10;
dst.x -= 17.;
dst.y -= 10.;
}
if(it->reverse)
@ -4790,7 +4790,7 @@ void CStackQueue::StackBox::hover( bool on )
}
int CatapultProjectileInfo::calculateY(int x)
double CatapultProjectileInfo::calculateY(double x)
{
return (facA * pow(10., -3.)) * pow(x, 2.0) + facB * x + facC;
}

View File

@ -51,8 +51,8 @@ struct SStackAttackedInfo
/// Small struct which contains information about the position and the velocity of a projectile
struct SProjectileInfo
{
int x, y; //position on the screen
int dx, dy; //change in position in one step
double x, y; //position on the screen
double dx, dy; //change in position in one step
int step, lastStep; //to know when finish showing this projectile
int creID; //ID of creature that shot this projectile
int stackID; //ID of stack
@ -407,7 +407,7 @@ struct CatapultProjectileInfo
CatapultProjectileInfo(double factorA, double factorB, double factorC, int fromXX, int toXX) : facA(factorA), facB(factorB), facC(factorC),
fromX(fromXX), toX(toXX) { };
int calculateY(int x);
double calculateY(double x);
};
/// Big class which handles the overall battle interface actions and it is also responsible for

View File

@ -1147,7 +1147,7 @@ void CCreaInfo::clickRight(tribool down, bool previousState)
{
boost::shared_ptr<BonusList> blAppend = hero->getAllBonuses(Selector::type(Bonus::CREATURE_GROWTH) && Selector::subtype(level)
&& Selector::sourceType(Bonus::ARTIFACT), 0, hero);
bl->insert(bl->end(), blAppend->begin(), blAppend->end()) ;
bl->insert(bl->size(), blAppend->begin(), blAppend->end()) ;
}
if (bl->size())

View File

@ -131,17 +131,17 @@ void CCreatureWindow::init(const CStackInstance *Stack, const CBonusSystemNode *
//Basic graphics - need to calculate size
CBonusSystemNode node = CBonusSystemNode() ;
node.bonuses = *(stackNode->getBonuses(Selector::durationType(Bonus::PERMANENT)));
BonusList bl;
BonusList bl, blTemp;
blTemp = (*(stackNode->getBonuses(Selector::durationType(Bonus::PERMANENT))));
while (node.bonuses.size())
while (blTemp.size())
{
Bonus * b = node.bonuses.front();
Bonus * b = blTemp.front();
bl.push_back (new Bonus(*b));
bl.back()->val = node.valOfBonuses(Selector::typeSubtype(b->type, b->subtype)); //merge multiple bonuses into one
node.bonuses.remove_if (Selector::typeSubtype(b->type, b->subtype)); //remove used bonuses
bl.back()->val = blTemp.valOfBonuses(Selector::typeSubtype(b->type, b->subtype)); //merge multiple bonuses into one
blTemp.remove_if (Selector::typeSubtype(b->type, b->subtype)); //remove used bonuses
}
std::string text;

View File

@ -44,7 +44,7 @@
extern SDL_Surface * screen;
using namespace boost::assign;
const boost::shared_ptr<BonusList> CHeroWithMaybePickedArtifact::getAllBonuses(const CSelector &selector, const CSelector &limit, const CBonusSystemNode *root /*= NULL*/) const
const boost::shared_ptr<BonusList> CHeroWithMaybePickedArtifact::getAllBonuses(const CSelector &selector, const CSelector &limit, const CBonusSystemNode *root /*= NULL*/, const std::string &cachingStr /*= ""*/) const
{
boost::shared_ptr<BonusList> out(new BonusList);
boost::shared_ptr<BonusList> heroBonuses = hero->getAllBonuses(selector, limit, hero);

View File

@ -46,7 +46,7 @@ public:
CWindowWithArtifacts *cww;
CHeroWithMaybePickedArtifact(CWindowWithArtifacts *Cww, const CGHeroInstance *Hero);
const boost::shared_ptr<BonusList> getAllBonuses(const CSelector &selector, const CSelector &limit, const CBonusSystemNode *root = NULL) const OVERRIDE;
const boost::shared_ptr<BonusList> getAllBonuses(const CSelector &selector, const CSelector &limit, const CBonusSystemNode *root = NULL, const std::string &cachingStr = "") const OVERRIDE;
};
class CHeroWindow: public CWindowWithGarrison, public CWindowWithArtifacts

View File

@ -469,14 +469,14 @@ void processCommand(const std::string &message)
else if(cn == "bonuses")
{
tlog0 << "Bonuses of " << adventureInt->selection->getHoverText() << std::endl
<< adventureInt->selection->bonuses << std::endl;
<< adventureInt->selection->getBonusList() << 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;
tlog0 << "\nBonuses from " << typeid(*parent).name() << std::endl << parent->getBonusList() << std::endl;
}
}
else if(cn == "not dialog")

View File

@ -249,13 +249,13 @@ void GiveBonus::applyCl( CClient *cl )
case HERO:
{
const CGHeroInstance *h = GS(cl)->getHero(id);
INTERFACE_CALL_IF_PRESENT(h->tempOwner, heroBonusChanged, h, *h->bonuses.back(),true);
INTERFACE_CALL_IF_PRESENT(h->tempOwner, heroBonusChanged, h, *h->getBonusList().back(),true);
}
break;
case PLAYER:
{
const PlayerState *p = GS(cl)->getPlayer(id);
INTERFACE_CALL_IF_PRESENT(id, playerBonusChanged, *p->bonuses.back(), true);
INTERFACE_CALL_IF_PRESENT(id, playerBonusChanged, *p->getBonusList().back(), true);
}
break;
}

View File

@ -490,7 +490,7 @@ TDmgRange BattleInfo::calculateDmgRange( const CStack* attacker, const CStack* d
for(int g = 0; g < VLC->creh->creatures.size(); ++g)
{
BOOST_FOREACH(const Bonus *b, VLC->creh->creatures[g]->bonuses)
BOOST_FOREACH(const Bonus *b, VLC->creh->creatures[g]->getBonusList())
{
if ( (b->type == Bonus::KING3 && spLevel >= 3) || //expert
(b->type == Bonus::KING2 && spLevel >= 2) || //adv +
@ -602,7 +602,7 @@ TDmgRange BattleInfo::calculateDmgRange( const CStack* attacker, const CStack* d
static bool hasAdvancedAirShield(const CStack * stack)
{
BOOST_FOREACH(const Bonus *it, stack->bonuses)
BOOST_FOREACH(const Bonus *it, stack->getBonusList())
{
if (it->source == Bonus::SPELL_EFFECT && it->sid == 28 && it->val >= 2)
{
@ -1718,7 +1718,7 @@ BattleInfo * BattleInfo::setupBattle( int3 tile, int terrain, int terType, const
curB->belligerents[i]->getRedAncestors(nodes);
BOOST_FOREACH(CBonusSystemNode *n, nodes)
{
BOOST_FOREACH(Bonus *b, n->exportedBonuses)
BOOST_FOREACH(Bonus *b, n->getExportedBonusList())
{
if(b->effectRange == Bonus::ONLY_ENEMY_ARMY/* && b->propagator && b->propagator->shouldBeAttached(curB)*/)
{
@ -1944,7 +1944,8 @@ SpellCasting::ESpellCastProblem BattleInfo::battleIsImmune(const CGHeroInstance
boost::shared_ptr<BonusList> immunities = subject->getBonuses(Selector::type(Bonus::LEVEL_SPELL_IMMUNITY));
if(subject->hasBonusOfType(Bonus::NEGATE_ALL_NATURAL_IMMUNITIES))
{
std::remove_if(immunities->begin(), immunities->end(), NegateRemover);
//std::remove_if(immunities->begin(), immunities->end(), NegateRemover);
immunities->remove_if(NegateRemover);
}
if(subject->hasBonusOfType(Bonus::SPELL_IMMUNITY, spell->id) ||
@ -2074,13 +2075,13 @@ CStack::CStack(const CStackInstance *Base, int O, int I, bool AO, int S)
assert(base);
type = base->type;
count = baseAmount = base->count;
nodeType = STACK_BATTLE;
setNodeType(STACK_BATTLE);
}
CStack::CStack()
{
init();
nodeType = STACK_BATTLE;
setNodeType(STACK_BATTLE);
}
CStack::CStack(const CStackBasicDescriptor *stack, int O, int I, bool AO, int S)
@ -2088,7 +2089,7 @@ CStack::CStack(const CStackBasicDescriptor *stack, int O, int I, bool AO, int S)
{
type = stack->type;
count = baseAmount = stack->count;
nodeType = STACK_BATTLE;
setNodeType(STACK_BATTLE);
}
void CStack::init()
@ -2108,7 +2109,7 @@ void CStack::init()
void CStack::postInit()
{
assert(type);
assert(parents.size());
assert(getParentNodes().size());
firstHPleft = valOfBonuses(Bonus::STACK_HEALTH);
shots = getCreature()->valOfBonuses(Bonus::SHOTS);
@ -2127,7 +2128,7 @@ ui32 CStack::Speed( int turn /*= 0*/ ) const
int speed = valOfBonuses(Selector::type(Bonus::STACKS_SPEED) && Selector::turns(turn));
int percentBonus = 0;
BOOST_FOREACH(const Bonus *b, bonuses)
BOOST_FOREACH(const Bonus *b, getBonusList())
{
if(b->type == Bonus::STACKS_SPEED)
{
@ -2148,7 +2149,7 @@ ui32 CStack::Speed( int turn /*= 0*/ ) const
const Bonus * CStack::getEffect( ui16 id, int turn /*= 0*/ ) const
{
BOOST_FOREACH(Bonus *it, bonuses)
BOOST_FOREACH(Bonus *it, getBonusList())
{
if(it->source == Bonus::SPELL_EFFECT && it->sid == id)
{
@ -2328,7 +2329,7 @@ void CStack::stackEffectToFeature(std::vector<Bonus> & sf, const Bonus & sse)
ui8 CStack::howManyEffectsSet(ui16 id) const
{
ui8 ret = 0;
BOOST_FOREACH(const Bonus *it, bonuses)
BOOST_FOREACH(const Bonus *it, getBonusList())
if(it->source == Bonus::SPELL_EFFECT && it->sid == id) //effect found
{
++ret;
@ -2453,8 +2454,8 @@ const CGHeroInstance * CStack::getMyHero() const
if(base)
return dynamic_cast<const CGHeroInstance *>(base->armyObj);
else //we are attached directly?
BOOST_FOREACH(const CBonusSystemNode *n, parents)
if(n->nodeType == HERO)
BOOST_FOREACH(const CBonusSystemNode *n, getParentNodes())
if(n->getNodeType() == HERO)
dynamic_cast<const CGHeroInstance *>(n);
return NULL;

View File

@ -147,7 +147,7 @@ bool CArtifact::isBig () const
CArtifact::CArtifact()
{
nodeType = ARTIFACT;
setNodeType(ARTIFACT);
}
CArtifact::~CArtifact()
@ -1116,7 +1116,7 @@ void CCombinedArtifactInstance::createConstituents()
void CCombinedArtifactInstance::addAsConstituent(CArtifactInstance *art, int slot)
{
assert(vstd::contains(*artType->constituents, art->artType->id));
assert(art->parents.size() == 1 && art->parents.front() == art->artType);
assert(art->getParentNodes().size() == 1 && art->getParentNodes().front() == art->artType);
constituentsInfo.push_back(ConstituentInfo(art, slot));
attachTo(art);
}

View File

@ -49,10 +49,10 @@ CCreatureHandler::CCreatureHandler()
factionAlignments += 1, 1, 1, -1, -1, -1, 0, 0, 0;
doubledCreatures += 4, 14, 20, 28, 42, 44, 60, 70, 72, 85, 86, 100, 104; //according to Strategija
allCreatures.description = "All creatures";
creaturesOfLevel[0].description = "Creatures of unnormalized tier";
allCreatures.setDescription("All creatures");
creaturesOfLevel[0].setDescription("Creatures of unnormalized tier");
for(int i = 1; i < ARRAY_COUNT(creaturesOfLevel); i++)
creaturesOfLevel[i].description = "Creatures of tier " + boost::lexical_cast<std::string>(i);
creaturesOfLevel[i].setDescription("Creatures of tier " + boost::lexical_cast<std::string>(i));
}
int CCreature::getQuantityID(const int & quantity)
@ -129,7 +129,7 @@ si32 CCreature::maxAmount(const std::vector<si32> &res) const //how many creatur
CCreature::CCreature()
{
doubleWide = false;
nodeType = CBonusSystemNode::CREATURE;
setNodeType(CBonusSystemNode::CREATURE);
}
void CCreature::addBonus(int val, int type, int subtype /*= -1*/)
{
@ -330,12 +330,12 @@ void CCreatureHandler::loadCreatures()
if(boost::algorithm::find_first(ncre.abilityRefs, "const_raises_morale"))
{
ncre.addBonus(+1, Bonus::MORALE);;
ncre.bonuses.back()->addPropagator(new CPropagatorNodeType(CBonusSystemNode::HERO));
ncre.getBonusList().back()->addPropagator(new CPropagatorNodeType(CBonusSystemNode::HERO));
}
if(boost::algorithm::find_first(ncre.abilityRefs, "const_lowers_morale"))
{
ncre.addBonus(-1, Bonus::MORALE);;
ncre.bonuses.back()->effectRange = Bonus::ONLY_ENEMY_ARMY;
ncre.getBonusList().back()->effectRange = Bonus::ONLY_ENEMY_ARMY;
}
if(boost::algorithm::find_first(ncre.abilityRefs, "KING_1"))
ncre.addBonus(0, Bonus::KING1);
@ -399,12 +399,12 @@ void CCreatureHandler::loadCreatures()
else if(type == "ENEMY_MORALE_DECREASING")
{
cre->addBonus(-1, Bonus::MORALE);
cre->bonuses.back()->effectRange = Bonus::ONLY_ENEMY_ARMY;
cre->getBonusList().back()->effectRange = Bonus::ONLY_ENEMY_ARMY;
}
else if(type == "ENEMY_LUCK_DECREASING")
{
cre->addBonus(-1, Bonus::LUCK);
cre->bonuses.back()->effectRange = Bonus::ONLY_ENEMY_ARMY;
cre->getBonusList().back()->effectRange = Bonus::ONLY_ENEMY_ARMY;
}
else
tlog1 << "Error: invalid type " << type << " in cr_abils.txt" << std::endl;
@ -678,7 +678,7 @@ void CCreatureHandler::loadCreatures()
{
loadToIt(creid, buf, it, 4); //get index
b.sid = creid; //id = this particular creature ID
loadStackExp(b, creatures[creid]->bonuses, buf, it); //add directly to CCreature Node
loadStackExp(b, creatures[creid]->getBonusList(), buf, it); //add directly to CCreature Node
loadToIt (dump2, buf, it, 3); //crop comment
} while (it < buf.size());
@ -1110,7 +1110,7 @@ void CCreatureHandler::loadMindImmunity(Bonus & b, BonusList & bl, std::string &
for (int g=0; g < mindSpells.size(); ++g)
{
b.subtype = mindSpells[g];
cre->bonuses.push_back(new Bonus(b));
cre->getBonusList().push_back(new Bonus(b));
}
}
@ -1151,9 +1151,9 @@ int CCreatureHandler::pickRandomMonster(const boost::function<int()> &randGen, i
{
assert(iswith(tier, 1, 7));
std::vector<int> allowed;
BOOST_FOREACH(const CBonusSystemNode *b, creaturesOfLevel[tier].children)
BOOST_FOREACH(const CBonusSystemNode *b, creaturesOfLevel[tier].getChildrenNodes())
{
assert(b->nodeType == CBonusSystemNode::CREATURE);
assert(b->getNodeType() == CBonusSystemNode::CREATURE);
int creid = static_cast<const CCreature*>(b)->idNumber;
if(!vstd::contains(notUsedMonsters, creid))

View File

@ -469,7 +469,7 @@ void CStackInstance::init()
type = NULL;
idRand = -1;
_armyObj = NULL;
nodeType = STACK_INSTANCE;
setNodeType(STACK_INSTANCE);
}
int CStackInstance::getQuantityID() const

View File

@ -799,7 +799,7 @@ CGameState::CGameState()
applierGs = new CApplier<CBaseForGSApply>;
registerTypes2(*applierGs);
objCaller = new CObjectCallersHandler;
globalEffects.description = "Global effects";
globalEffects.setDescription("Global effects");
}
CGameState::~CGameState()
{
@ -2900,7 +2900,7 @@ PlayerState::PlayerState()
: color(-1), currentSelection(0xffffffff), enteredWinningCheatCode(0),
enteredLosingCheatCode(0), status(INGAME), daysWithoutCastle(0)
{
nodeType = PLAYER;
setNodeType(PLAYER);
}
std::string PlayerState::nodeName() const
@ -3022,5 +3022,5 @@ DuelParameters::DuelParameters()
TeamState::TeamState()
{
nodeType = TEAM;
setNodeType(TEAM);
}

View File

@ -182,7 +182,7 @@ public:
template <typename Handler> void serialize(Handler &h, const int version)
{
h & color & human & currentSelection & team & resources & status;
h & heroes & towns & availableHeroes & dwellings & bonuses;
h & heroes & towns & availableHeroes & dwellings & getBonusList();
h & status & daysWithoutCastle;
h & enteredLosingCheatCode & enteredWinningCheatCode;
h & static_cast<CBonusSystemNode&>(*this);

View File

@ -722,7 +722,7 @@ int CGHeroInstance::maxMovePoints(bool onLand) const
CGHeroInstance::CGHeroInstance()
: IBoatGenerator(this)
{
nodeType = HERO;
setNodeType(HERO);
ID = HEROI_TYPE;
tacticFormationEnabled = inTownGarrison = false;
mana = movement = portrait = level = -1;
@ -733,7 +733,7 @@ CGHeroInstance::CGHeroInstance()
type = NULL;
boat = NULL;
secSkills.push_back(std::make_pair(-1, -1));
speciality.nodeType = CBonusSystemNode::SPECIALITY;
speciality.setNodeType(CBonusSystemNode::SPECIALITY);
attachTo(&speciality); //do we evert need to detach it?
}
@ -1124,7 +1124,7 @@ void CGHeroInstance::UpdateSpeciality()
{
std::vector< ConstTransitivePtr<CCreature> > & creatures = VLC->creh->creatures;
BOOST_FOREACH(Bonus *it, speciality.bonuses)
BOOST_FOREACH(Bonus *it, speciality.getBonusList())
{
switch (it->type)
{
@ -1230,7 +1230,7 @@ void CGHeroInstance::updateSkill(int which, int val)
int skillValType = skillVal ? Bonus::BASE_NUMBER : Bonus::INDEPENDENT_MIN;
if(Bonus * b = bonuses.getFirst(Selector::typeSubtype(Bonus::SECONDARY_SKILL_PREMY, which) && Selector::sourceType(Bonus::SECONDARY_SKILL))) //only local hero bonus
if(Bonus * b = getBonusList().getFirst(Selector::typeSubtype(Bonus::SECONDARY_SKILL_PREMY, which) && Selector::sourceType(Bonus::SECONDARY_SKILL))) //only local hero bonus
{
b->val = skillVal;
b->valType = skillValType;
@ -2262,7 +2262,7 @@ void CGTownInstance::deserializationFix()
void CGTownInstance::recreateBuildingsBonuses()
{
boost::shared_ptr<BonusList> bl(new BonusList);
exportedBonuses.getBonuses(bl, Selector::sourceType(Bonus::TOWN_STRUCTURE));
getExportedBonusList().getBonuses(bl, Selector::sourceType(Bonus::TOWN_STRUCTURE));
BOOST_FOREACH(Bonus *b, *bl)
removeBonus(b);
@ -3704,7 +3704,7 @@ void CGArtifact::initObj()
subID = 1;
assert(storedArtifact->artType);
assert(storedArtifact->parents.size());
assert(storedArtifact->getParentNodes().size());
}
void CGArtifact::onHeroVisit( const CGHeroInstance * h ) const
@ -6692,7 +6692,7 @@ void CArmedInstance::updateMoraleBonusFromArmy()
if(!validTypes(false)) //object not randomized, don't bother
return;
Bonus *b = bonuses.getFirst(Selector::sourceType(Bonus::ARMY) && Selector::type(Bonus::MORALE));
Bonus *b = getBonusList().getFirst(Selector::sourceType(Bonus::ARMY) && Selector::type(Bonus::MORALE));
if(!b)
{
b = new Bonus(Bonus::PERMANENT, Bonus::MORALE, Bonus::ARMY, 0, -1);
@ -6731,7 +6731,7 @@ void CArmedInstance::updateMoraleBonusFromArmy()
//-1 modifier for any Necropolis unit in army
const ui8 UNDEAD_MODIFIER_ID = -2;
Bonus *undeadModifier = bonuses.getFirst(Selector::source(Bonus::ARMY, UNDEAD_MODIFIER_ID));
Bonus *undeadModifier = getBonusList().getFirst(Selector::source(Bonus::ARMY, UNDEAD_MODIFIER_ID));
if(vstd::contains(factions,4))
{
if(!undeadModifier)

View File

@ -25,9 +25,29 @@
#define BONUS_LOG_LINE(x) tlog5 << x << std::endl
int CBonusSystemNode::treeChanged = 1;
const bool CBonusSystemNode::cachingEnabled = false;
const bool CBonusSystemNode::cachingEnabled = true;
int DLL_EXPORT BonusList::totalValue() const
BonusList::BonusList(bool BelongsToTree /* =false */) : belongsToTree(BelongsToTree)
{
}
BonusList::BonusList(const BonusList &bonusList)
{
bonuses.resize(bonusList.size());
std::copy(bonusList.begin(), bonusList.end(), bonuses.begin());
belongsToTree = false;
}
BonusList& BonusList::operator=(const BonusList &bonusList)
{
bonuses.resize(bonusList.size());
std::copy(bonusList.begin(), bonusList.end(), bonuses.begin());
belongsToTree = false;
return *this;
}
int BonusList::totalValue() const
{
int base = 0;
int percentToBase = 0;
@ -38,7 +58,7 @@ int DLL_EXPORT BonusList::totalValue() const
int indepMin = 0;
bool hasIndepMin = false;
BOOST_FOREACH(Bonus *i, *this)
BOOST_FOREACH(Bonus *i, bonuses)
{
switch(i->valType)
{
@ -93,35 +113,35 @@ int DLL_EXPORT BonusList::totalValue() const
return valFirst;
}
const DLL_EXPORT Bonus * BonusList::getFirst(const CSelector &selector) const
const Bonus * BonusList::getFirst(const CSelector &selector) const
{
for (int i = 0; i < this->size(); i++)
for (unsigned int i = 0; i < bonuses.size(); i++)
{
const Bonus *b = (*this)[i];
const Bonus *b = bonuses[i];
if(selector(b))
return &*b;
}
return NULL;
}
DLL_EXPORT Bonus * BonusList::getFirst(const CSelector &select)
Bonus * BonusList::getFirst(const CSelector &select)
{
for (int i = 0; i < this->size(); i++)
for (unsigned int i = 0; i < bonuses.size(); i++)
{
Bonus *b = (*this)[i];
Bonus *b = bonuses[i];
if(select(b))
return &*b;
}
return NULL;
}
void DLL_EXPORT BonusList::getModifiersWDescr(TModDescr &out) const
void BonusList::getModifiersWDescr(TModDescr &out) const
{
BOOST_FOREACH(Bonus *i, *this)
BOOST_FOREACH(Bonus *i, bonuses)
out.push_back(std::make_pair(i->val, i->Description()));
}
void DLL_EXPORT BonusList::getBonuses(boost::shared_ptr<BonusList> out, const CSelector &selector) const
void BonusList::getBonuses(boost::shared_ptr<BonusList> out, const CSelector &selector) const
{
// BOOST_FOREACH(Bonus *i, *this)
// if(selector(i) && i->effectRange == Bonus::NO_LIMIT)
@ -130,11 +150,11 @@ void DLL_EXPORT BonusList::getBonuses(boost::shared_ptr<BonusList> out, const CS
getBonuses(out, selector, 0);
}
void DLL_EXPORT BonusList::getBonuses(boost::shared_ptr<BonusList> out, const CSelector &selector, const CSelector &limit, const bool caching /*= false*/) const
void BonusList::getBonuses(boost::shared_ptr<BonusList> out, const CSelector &selector, const CSelector &limit, const bool caching /*= false*/) const
{
for (int i = 0; i < this->size(); i++)
for (unsigned int i = 0; i < bonuses.size(); i++)
{
Bonus *b = (*this)[i];
Bonus *b = bonuses[i];
//add matching bonuses that matches limit predicate or have NO_LIMIT if no given predicate
if(caching || (selector(b) && ((!limit && b->effectRange == Bonus::NO_LIMIT) || (limit && limit(b)))))
@ -142,16 +162,76 @@ void DLL_EXPORT BonusList::getBonuses(boost::shared_ptr<BonusList> out, const CS
}
}
int BonusList::valOfBonuses(const CSelector &select) const
{
boost::shared_ptr<BonusList> ret(new BonusList());
CSelector limit = 0;
getBonuses(ret, select, limit, false);
ret->eliminateDuplicates();
return ret->totalValue();
}
void BonusList::limit(const CBonusSystemNode &node)
{
remove_if(boost::bind(&CBonusSystemNode::isLimitedOnUs, boost::ref(node), _1));
}
void DLL_EXPORT BonusList::eliminateDuplicates()
void BonusList::eliminateDuplicates()
{
sort( begin(), end() );
erase( unique( begin(), end() ), end() );
sort( bonuses.begin(), bonuses.end() );
bonuses.erase( unique( bonuses.begin(), bonuses.end() ), bonuses.end() );
}
void BonusList::push_back(Bonus* const &x)
{
bonuses.push_back(x);
if (belongsToTree)
CBonusSystemNode::incrementTreeChangedNum();
}
std::vector<Bonus*>::iterator BonusList::erase(std::vector<Bonus*>::const_iterator position)
{
if (belongsToTree)
CBonusSystemNode::incrementTreeChangedNum();
return bonuses.erase(position);
}
void BonusList::clear()
{
bonuses.clear();
if (belongsToTree)
CBonusSystemNode::incrementTreeChangedNum();
}
std::vector<BonusList*>::size_type BonusList::operator-=(Bonus* const &i)
{
std::vector<Bonus*>::iterator itr = std::find(bonuses.begin(), bonuses.end(), i);
if(itr == bonuses.end())
return false;
bonuses.erase(itr);
if (belongsToTree)
CBonusSystemNode::incrementTreeChangedNum();
return true;
}
void BonusList::resize(std::vector<Bonus*>::size_type sz, Bonus* c )
{
bonuses.resize(sz, c);
if (belongsToTree)
CBonusSystemNode::incrementTreeChangedNum();
}
void BonusList::insert(std::vector<Bonus*>::iterator position, std::vector<Bonus*>::size_type n, Bonus* const &x)
{
bonuses.insert(position, n, x);
if (belongsToTree)
CBonusSystemNode::incrementTreeChangedNum();
}
int IBonusBearer::valOfBonuses(Bonus::BonusType type, const CSelector &selector) const
@ -174,24 +254,24 @@ int IBonusBearer::valOfBonuses(const CSelector &selector) const
boost::shared_ptr<BonusList> hlp = getAllBonuses(selector, limit, NULL);
return hlp->totalValue();
}
bool IBonusBearer::hasBonus(const CSelector &selector) const
bool IBonusBearer::hasBonus(const CSelector &selector, const std::string &cachingStr /*= ""*/) const
{
return getBonuses(selector)->size() > 0;
return getBonuses(selector, cachingStr)->size() > 0;
}
bool IBonusBearer::hasBonusOfType(Bonus::BonusType type, int subtype /*= -1*/) const
{
CSelector s = Selector::type(type);
std::string cachingStr = "";
if(subtype != -1)
s = s && Selector::subtype(subtype);
else
{
std::string str = "type_";
str += ((char) type);
setCachingStr(str);
cachingStr = "type_";
cachingStr += ((char) type);
}
return hasBonus(s);
return hasBonus(s, cachingStr);
}
void IBonusBearer::getModifiersWDescr(TModDescr &out, Bonus::BonusType type, int subtype /*= -1 */) const
@ -213,14 +293,14 @@ int IBonusBearer::getBonusesCount(const CSelector &selector) const
return getBonuses(selector)->size();
}
const boost::shared_ptr<BonusList> IBonusBearer::getBonuses(const CSelector &selector) const
const boost::shared_ptr<BonusList> IBonusBearer::getBonuses(const CSelector &selector, const std::string &cachingStr /*= ""*/) const
{
return getAllBonuses(selector, 0, NULL);
return getAllBonuses(selector, 0, NULL, cachingStr);
}
const boost::shared_ptr<BonusList> IBonusBearer::getBonuses(const CSelector &selector, const CSelector &limit) const
const boost::shared_ptr<BonusList> IBonusBearer::getBonuses(const CSelector &selector, const CSelector &limit, const std::string &cachingStr /*= ""*/) const
{
return getAllBonuses(selector, limit, NULL);
return getAllBonuses(selector, limit, NULL, cachingStr);
}
bool IBonusBearer::hasBonusFrom(ui8 source, ui32 sourceID) const
@ -324,21 +404,11 @@ bool IBonusBearer::isLiving() const //TODO: theoreticaly there exists "LIVING" b
return(!hasBonus(Selector::type(Bonus::UNDEAD) || Selector::type(Bonus::NON_LIVING)));
}
void IBonusBearer::setCachingStr(const std::string &request) const
{
}
const boost::shared_ptr<BonusList> IBonusBearer::getSpellBonuses() const
{
std::string str = "source_";
str += (char) Bonus::SPELL_EFFECT;
setCachingStr(str);
return getBonuses(Selector::sourceType(Bonus::SPELL_EFFECT));
}
void CBonusSystemNode::setCachingStr(const std::string &request) const
{
cachingStr = request;
std::string cachingStr = "source_";
cachingStr += (char) Bonus::SPELL_EFFECT;
return getBonuses(Selector::sourceType(Bonus::SPELL_EFFECT), cachingStr);
}
Bonus * CBonusSystemNode::getBonus(const CSelector &selector)
@ -364,7 +434,7 @@ const Bonus * CBonusSystemNode::getBonus( const CSelector &selector ) const
void CBonusSystemNode::getParents(TCNodes &out) const /*retreives list of parent nodes (nodes to inherit bonuses from) */
{
for (int i = 0; i < parents.size(); i++)
for (unsigned int i = 0; i < parents.size(); i++)
{
const CBonusSystemNode *parent = parents[i];
out.insert(parent);
@ -373,7 +443,7 @@ void CBonusSystemNode::getParents(TCNodes &out) const /*retreives list of parent
void CBonusSystemNode::getParents(TNodes &out)
{
for (int i = 0; i < parents.size(); i++)
for (unsigned int i = 0; i < parents.size(); i++)
{
const CBonusSystemNode *parent = parents[i];
out.insert(const_cast<CBonusSystemNode*>(parent));
@ -393,11 +463,14 @@ void CBonusSystemNode::getAllBonusesRec(boost::shared_ptr<BonusList> out, const
out->limit(*this);
}
const boost::shared_ptr<BonusList> CBonusSystemNode::getAllBonuses(const CSelector &selector, const CSelector &limit, const CBonusSystemNode *root /*= NULL*/) const
const boost::shared_ptr<BonusList> CBonusSystemNode::getAllBonuses(const CSelector &selector, const CSelector &limit, const CBonusSystemNode *root /*= NULL*/, const std::string &cachingStr /*= ""*/) const
{
boost::shared_ptr<BonusList> ret(new BonusList());
if (CBonusSystemNode::cachingEnabled)
{
static boost::mutex m;
boost::mutex::scoped_lock lock(m);
if (cachedLast != treeChanged)
{
getAllBonusesRec(ret, selector, limit, this, true);
@ -414,11 +487,10 @@ const boost::shared_ptr<BonusList> CBonusSystemNode::getAllBonuses(const CSelect
if (cachedRequests.size() > 0 && it != cachedRequests.end())
{
ret = it->second;
cachingStr = "";
return ret;
}
}
cachedBonuses.getBonuses(ret, selector, limit, false);
if (!root)
ret->limit(*this);
@ -426,7 +498,6 @@ const boost::shared_ptr<BonusList> CBonusSystemNode::getAllBonuses(const CSelect
if (cachingStr != "")
cachedRequests[cachingStr] = ret;
cachingStr = "";
return ret;
}
@ -438,7 +509,7 @@ const boost::shared_ptr<BonusList> CBonusSystemNode::getAllBonuses(const CSelect
}
}
CBonusSystemNode::CBonusSystemNode() : cachedLast(0), nodeType(UNKNOWN)
CBonusSystemNode::CBonusSystemNode() : bonuses(true), exportedBonuses(true), nodeType(UNKNOWN), cachedLast(0)
{
}
@ -452,7 +523,7 @@ CBonusSystemNode::~CBonusSystemNode()
while(children.size())
children.front()->detachFrom(this);
}
BOOST_FOREACH(Bonus *b, exportedBonuses)
delete b;
}
@ -675,7 +746,7 @@ void CBonusSystemNode::getRedDescendants(TNodes &out)
void CBonusSystemNode::battleTurnPassed()
{
BonusList bonusesCpy = exportedBonuses; //copy, because removing bonuses invalidates iters
for (int i = 0; i < bonusesCpy.size(); i++)
for (unsigned int i = 0; i < bonusesCpy.size(); i++)
{
Bonus *b = bonusesCpy[i];
@ -694,6 +765,8 @@ void CBonusSystemNode::exportBonus(Bonus * b)
propagateBonus(b);
else
bonuses.push_back(b);
CBonusSystemNode::treeChanged++;
}
void CBonusSystemNode::exportBonuses()
@ -702,6 +775,56 @@ void CBonusSystemNode::exportBonuses()
exportBonus(b);
}
const ui8 CBonusSystemNode::getNodeType() const
{
return nodeType;
}
BonusList& CBonusSystemNode::getBonusList()
{
return bonuses;
}
const BonusList& CBonusSystemNode::getBonusList() const
{
return bonuses;
}
const TNodesVector& CBonusSystemNode::getParentNodes() const
{
return parents;
}
const TNodesVector& CBonusSystemNode::getChildrenNodes() const
{
return children;
}
void CBonusSystemNode::setNodeType(ui8 type)
{
nodeType = type;
}
BonusList& CBonusSystemNode::getExportedBonusList()
{
return exportedBonuses;
}
const std::string& CBonusSystemNode::getDescription() const
{
return description;
}
void CBonusSystemNode::setDescription(const std::string &description)
{
this->description = description;
}
void CBonusSystemNode::incrementTreeChangedNum()
{
treeChanged++;
}
int NBonus::valOf(const CBonusSystemNode *obj, Bonus::BonusType type, int subtype /*= -1*/)
{
if(obj)
@ -888,7 +1011,7 @@ namespace Selector
const CStack * retreiveStackBattle(const CBonusSystemNode *node)
{
switch(node->nodeType)
switch(node->getNodeType())
{
case CBonusSystemNode::STACK_BATTLE:
return static_cast<const CStack*>(node);
@ -899,7 +1022,7 @@ const CStack * retreiveStackBattle(const CBonusSystemNode *node)
const CStackInstance * retreiveStackInstance(const CBonusSystemNode *node)
{
switch(node->nodeType)
switch(node->getNodeType())
{
case CBonusSystemNode::STACK_INSTANCE:
return (static_cast<const CStackInstance *>(node));
@ -912,7 +1035,7 @@ const CStackInstance * retreiveStackInstance(const CBonusSystemNode *node)
const CCreature * retrieveCreature(const CBonusSystemNode *node)
{
switch(node->nodeType)
switch(node->getNodeType())
{
case CBonusSystemNode::CREATURE:
return (static_cast<const CCreature *>(node));
@ -926,7 +1049,7 @@ const CCreature * retrieveCreature(const CBonusSystemNode *node)
DLL_EXPORT std::ostream & operator<<(std::ostream &out, const BonusList &bonusList)
{
for (int i = 0; i < bonusList.size(); i++)
for (unsigned int i = 0; i < bonusList.size(); i++)
{
Bonus *b = bonusList[i];
out << "Bonus " << i << "\n" << *b << std::endl;
@ -1039,7 +1162,7 @@ CPropagatorNodeType::CPropagatorNodeType(ui8 NodeType)
bool CPropagatorNodeType::shouldBeAttached(CBonusSystemNode *dest)
{
return nodeType == dest->nodeType;
return nodeType == dest->getNodeType();
}
CreatureNativeTerrainLimiter::CreatureNativeTerrainLimiter(int TerrainType)

View File

@ -4,6 +4,8 @@
#include <set>
#include <boost/function.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/range.hpp>
#include <boost/thread/mutex.hpp>
/*
* HeroBonus.h, part of VCMI engine
@ -320,44 +322,107 @@ struct DLL_EXPORT Bonus
DLL_EXPORT std::ostream & operator<<(std::ostream &out, const Bonus &bonus);
class BonusList : public std::vector<Bonus*>
{
public:
int DLL_EXPORT totalValue() const; //subtype -> subtype of bonus, if -1 then any
void DLL_EXPORT getBonuses(boost::shared_ptr<BonusList> out, const CSelector &selector, const CSelector &limit, const bool caching = false) const;
void DLL_EXPORT getModifiersWDescr(TModDescr &out) const;
void DLL_EXPORT getBonuses(boost::shared_ptr<BonusList> out, const CSelector &selector) const;
class DLL_EXPORT BonusList
{
private:
std::vector<Bonus*> bonuses;
bool belongsToTree;
public:
BonusList(bool BelongsToTree = false);
BonusList(const BonusList &bonusList);
BonusList& operator=(const BonusList &bonusList);
// wrapper functions of the STL vector container
std::vector<Bonus*>::size_type size() const { return bonuses.size(); }
void push_back(Bonus* const &x);
std::vector<Bonus*>::iterator erase (std::vector<Bonus*>::const_iterator position);
void clear();
void resize(std::vector<Bonus*>::size_type sz, Bonus* c = NULL );
void insert(std::vector<Bonus*>::iterator position, std::vector<Bonus*>::size_type n, Bonus* const &x);
(Bonus *const) &operator[] (std::vector<Bonus*>::size_type n) { return bonuses[n]; }
(Bonus *const) &operator[] (std::vector<Bonus*>::size_type n) const { return bonuses[n]; }
(Bonus *const) &back() { return bonuses.back(); }
(Bonus *const) &front() { return bonuses.front(); }
(Bonus *const) &back() const { return bonuses.back(); }
(Bonus *const) &front() const { return bonuses.front(); }
std::vector<Bonus*>::const_iterator begin() { return bonuses.begin(); }
std::vector<Bonus*>::const_iterator end() { return bonuses.end(); }
std::vector<Bonus*>::const_iterator begin() const { return bonuses.begin(); }
std::vector<Bonus*>::const_iterator end() const { return bonuses.end(); }
std::vector<Bonus*>::size_type operator-=(Bonus* const &i);
// BonusList functions
int totalValue() const; //subtype -> subtype of bonus, if -1 then any
void getBonuses(boost::shared_ptr<BonusList> out, const CSelector &selector, const CSelector &limit, const bool caching = false) const;
void getModifiersWDescr(TModDescr &out) const;
void getBonuses(boost::shared_ptr<BonusList> out, const CSelector &selector) const;
//special find functions
DLL_EXPORT Bonus * getFirst(const CSelector &select);
DLL_EXPORT const Bonus * getFirst(const CSelector &select) const;
Bonus *getFirst(const CSelector &select);
const Bonus *getFirst(const CSelector &select) const;
int valOfBonuses(const CSelector &select) const;
void limit(const CBonusSystemNode &node); //erases bonuses using limitor
void DLL_EXPORT eliminateDuplicates();
void eliminateDuplicates();
// remove_if implementation for STL vector types
template <class Predicate>
void remove_if(Predicate pred)
{
BonusList newList;
for (int i = 0; i < this->size(); i++)
for (unsigned int i = 0; i < bonuses.size(); i++)
{
Bonus *b = (*this)[i];
Bonus *b = bonuses[i];
if (!pred(b))
newList.push_back(b);
}
this->clear();
this->resize(newList.size());
std::copy(newList.begin(), newList.end(), this->begin());
bonuses.clear();
bonuses.resize(newList.size());
std::copy(newList.begin(), newList.end(), bonuses.begin());
}
template <class InputIterator>
void insert(const int position, InputIterator first, InputIterator last)
{
bonuses.insert(bonuses.begin() + position, first, last);
if (belongsToTree)
CBonusSystemNode::incrementTreeChangedNum();
}
template <typename Handler> void serialize(Handler &h, const int version)
{
h & static_cast<std::vector<Bonus*>&>(*this);
h & static_cast<std::vector<Bonus*>&>(bonuses);
}
friend inline std::vector<Bonus*>::iterator range_begin(BonusList & x);
friend inline std::vector<Bonus*>::iterator range_end(BonusList & x);
};
// Extensions for BOOST_FOREACH to enable iterating of BonusList objects
inline std::vector<Bonus*>::iterator range_begin(BonusList & x)
{
return x.bonuses.begin();
}
inline std::vector<Bonus*>::iterator range_end(BonusList & x)
{
return x.bonuses.end();
}
inline std::vector<Bonus*>::const_iterator range_begin(BonusList const &x)
{
return x.begin();
}
inline std::vector<Bonus*>::const_iterator range_end(BonusList const &x)
{
return x.end();
}
DLL_EXPORT std::ostream & operator<<(std::ostream &out, const BonusList &bonusList);
class DLL_EXPORT IPropagator
@ -404,14 +469,13 @@ public:
// * selector is predicate that tests if HeroBonus matches our criteria
// * root is node on which call was made (NULL will be replaced with this)
//interface
virtual const boost::shared_ptr<BonusList> getAllBonuses(const CSelector &selector, const CSelector &limit, const CBonusSystemNode *root = NULL) const = 0;
virtual void setCachingStr(const std::string &request) const;
virtual const boost::shared_ptr<BonusList> getAllBonuses(const CSelector &selector, const CSelector &limit, const CBonusSystemNode *root = NULL, const std::string &cachingStr = "") const = 0;
void getModifiersWDescr(TModDescr &out, const CSelector &selector) const; //out: pairs<modifier value, modifier description>
int getBonusesCount(const CSelector &selector) const;
int valOfBonuses(const CSelector &selector) const;
bool hasBonus(const CSelector &selector) const;
const boost::shared_ptr<BonusList> getBonuses(const CSelector &selector, const CSelector &limit) const;
const boost::shared_ptr<BonusList> getBonuses(const CSelector &selector) const;
bool hasBonus(const CSelector &selector, const std::string &cachingStr = "") const;
const boost::shared_ptr<BonusList> getBonuses(const CSelector &selector, const CSelector &limit, const std::string &cachingStr = "") const;
const boost::shared_ptr<BonusList> getBonuses(const CSelector &selector, const std::string &cachingStr = "") const;
//legacy interface
int valOfBonuses(Bonus::BonusType type, const CSelector &selector) const;
@ -439,6 +503,16 @@ public:
class DLL_EXPORT CBonusSystemNode : public IBonusBearer
{
private:
BonusList bonuses; //wielded bonuses (local or up-propagated here)
BonusList exportedBonuses; //bonuses coming from this node (wielded or propagated away)
TNodesVector parents; //parents -> we inherit bonuses from them, we may attach our bonuses to them
TNodesVector children;
ui8 nodeType;
std::string description;
static const bool cachingEnabled;
mutable BonusList cachedBonuses;
mutable int cachedLast;
@ -447,26 +521,16 @@ class DLL_EXPORT CBonusSystemNode : public IBonusBearer
// Setting a value to cachingStr before getting any bonuses caches the result for later requests.
// This string needs to be unique, that's why it has to be setted in the following manner:
// [property key]_[value] => only for selector
mutable std::string cachingStr;
mutable std::map<std::string, boost::shared_ptr<BonusList> > cachedRequests;
void getAllBonusesRec(boost::shared_ptr<BonusList> out, const CSelector &selector, const CSelector &limit, const CBonusSystemNode *root = NULL, const bool caching = false) const;
public:
BonusList bonuses; //wielded bonuses (local or up-propagated here)
BonusList exportedBonuses; //bonuses coming from this node (wielded or propagated away)
TNodesVector parents; //parents -> we inherit bonuses from them, we may attach our bonuses to them
TNodesVector children;
ui8 nodeType;
std::string description;
explicit CBonusSystemNode();
virtual ~CBonusSystemNode();
const boost::shared_ptr<BonusList> getAllBonuses(const CSelector &selector, const CSelector &limit, const CBonusSystemNode *root = NULL) const;
void setCachingStr(const std::string &request) const;
const boost::shared_ptr<BonusList> getAllBonuses(const CSelector &selector, const CSelector &limit, const CBonusSystemNode *root = NULL, const std::string &cachingStr = "") const;
void getParents(TCNodes &out) const; //retrieves list of parent nodes (nodes to inherit bonuses from),
const Bonus *getBonus(const CSelector &selector) const;
@ -504,6 +568,17 @@ public:
void deserializationFix();
void exportBonus(Bonus * b);
void exportBonuses();
static void incrementTreeChangedNum();
BonusList &getBonusList();
const BonusList &getBonusList() const;
BonusList &getExportedBonusList();
const ui8 getNodeType() const;
void setNodeType(ui8 type);
const TNodesVector &getParentNodes() const;
const TNodesVector &getChildrenNodes() const;
const std::string &getDescription() const;
void setDescription(const std::string &description);
template <typename Handler> void serialize(Handler &h, const int version)
{
@ -754,3 +829,20 @@ namespace Selector
}
extern DLL_EXPORT const std::map<std::string, int> bonusNameMap;
// Extensions for BOOST_FOREACH to enable iterating of BonusList objects
namespace boost
{
template<>
struct range_mutable_iterator<BonusList>
{
typedef std::vector<Bonus*>::iterator type;
};
template<>
struct range_const_iterator<::BonusList>
{
typedef std::vector<Bonus*>::const_iterator type;
};
}

View File

@ -515,7 +515,7 @@ void CPrivilagedInfoCallback::getAllowedSpells(std::vector<ui16> &out, ui16 leve
{
CSpell *spell;
for (int i = 0; i < gs->map->allowedSpell.size(); i++) //spellh size appears to be greater (?)
for (unsigned int i = 0; i < gs->map->allowedSpell.size(); i++) //spellh size appears to be greater (?)
{
spell = VLC->spellh->spells[i];
if (isAllowed (0, spell->id) && spell->level == level)
@ -974,7 +974,7 @@ int CGameInfoCallback::getHeroCount( int player, bool includeGarrisoned ) const
if(includeGarrisoned)
return p->heroes.size();
else
for(int i=0; i < p->heroes.size(); i++)
for(unsigned int i = 0; i < p->heroes.size(); i++)
if(!p->heroes[i]->inTownGarrison)
ret++;
return ret;
@ -1018,7 +1018,7 @@ std::vector < const CGTownInstance *> CPlayerSpecificInfoCallback::getTownsInfo(
std::vector < const CGTownInstance *> ret = std::vector < const CGTownInstance *>();
for ( std::map<ui8, PlayerState>::iterator i=gs->players.begin() ; i!=gs->players.end();i++)
{
for (size_t j=0; j < (*i).second.towns.size(); ++j)
for (size_t j = 0; j < (*i).second.towns.size(); ++j)
{
if ((*i).first==player
|| (isVisible((*i).second.towns[j],player) && !onlyOur))
@ -1205,7 +1205,7 @@ void IGameEventRealizer::setObjProperty(int objid, int prop, si64 val)
SetObjectProperty sob;
sob.id = objid;
sob.what = prop;
sob.val = val;
sob.val = static_cast<ui32>(val);
commitPackage(&sob);
}

View File

@ -217,14 +217,21 @@ DLL_EXPORT void PlayerEndsGame::applyGs( CGameState *gs )
DLL_EXPORT void RemoveBonus::applyGs( CGameState *gs )
{
BonusList &bonuses = (who == HERO ? gs->getHero(whoID)->bonuses : gs->getPlayer(whoID)->bonuses);
CBonusSystemNode *node;
if (who == HERO)
node = gs->getHero(whoID);
else
node = gs->getPlayer(whoID);
for(BonusList::iterator i = bonuses.begin(); i != bonuses.end(); i++)
BonusList &bonuses = node->getBonusList();
for (int i = 0; i < bonuses.size(); i++)
{
if((*i)->source == source && (*i)->sid == id)
Bonus *b = bonuses[i];
if(b->source == source && b->sid == id)
{
bonus = **i; //backup bonus (to show to interfaces later)
bonuses.erase(i);
bonus = *b; //backup bonus (to show to interfaces later)
bonuses.erase(bonuses.begin() + i);
break;
}
}
@ -513,7 +520,7 @@ DLL_EXPORT void NewArtifact::applyGs( CGameState *gs )
assert(!vstd::contains(gs->map->artInstances, art));
gs->map->addNewArtifactInstance(art);
assert(!art->parents.size());
assert(!art->getParentNodes().size());
art->setType(art->artType);
if (CCombinedArtifactInstance* cart = dynamic_cast<CCombinedArtifactInstance*>(art.get()))
cart->createConstituents();
@ -922,7 +929,7 @@ DLL_EXPORT void BattleSetActiveStack::applyGs( CGameState *gs )
}
//remove bonuses that last until when stack gets new turn
st->bonuses.remove_if(Bonus::UntilGetsTurn);
st->getBonusList().remove_if(Bonus::UntilGetsTurn);
if(vstd::contains(st->state,MOVED)) //if stack is moving second time this turn it must had a high morale bonus
st->state.insert(HAD_MORALE);
@ -946,11 +953,11 @@ void BattleResult::applyGs( CGameState *gs )
CGHeroInstance *h;
h = gs->curB->heroes[0];
if(h)
h->bonuses.remove_if(Bonus::OneBattle);
h->getBonusList().remove_if(Bonus::OneBattle);
h = gs->curB->heroes[1];
if(h)
h->bonuses.remove_if(Bonus::OneBattle);
h->getBonusList().remove_if(Bonus::OneBattle);
if (STACK_EXP)
{
@ -1018,12 +1025,12 @@ DLL_EXPORT void BattleAttack::applyGs( CGameState *gs )
BOOST_FOREACH(BattleStackAttacked stackAttacked, bsa)
stackAttacked.applyGs(gs);
attacker->bonuses.remove_if(Bonus::UntilAttack);
attacker->getBonusList().remove_if(Bonus::UntilAttack);
for(std::vector<BattleStackAttacked>::const_iterator it = bsa.begin(); it != bsa.end(); ++it)
{
CStack * stack = gs->curB->getStack(it->stackAttacked, false);
stack->bonuses.remove_if(Bonus::UntilBeingAttacked);
stack->getBonusList().remove_if(Bonus::UntilBeingAttacked);
}
}
@ -1160,7 +1167,7 @@ void actualizeEffect(CStack * s, const std::vector<Bonus> & ef)
BOOST_FOREACH(const Bonus &fromEffect, ef)
{
BOOST_FOREACH(Bonus *stackBonus, s->bonuses) //TODO: optimize
BOOST_FOREACH(Bonus *stackBonus, s->getBonusList()) //TODO: optimize
{
if(stackBonus->source == Bonus::SPELL_EFFECT && stackBonus->type == fromEffect.type && stackBonus->subtype == fromEffect.subtype)
{
@ -1171,7 +1178,7 @@ void actualizeEffect(CStack * s, const std::vector<Bonus> & ef)
}
void actualizeEffect(CStack * s, const Bonus & ef)
{
BOOST_FOREACH(Bonus *stackBonus, s->bonuses) //TODO: optimize
BOOST_FOREACH(Bonus *stackBonus, s->getBonusList()) //TODO: optimize
{
if(stackBonus->source == Bonus::SPELL_EFFECT && stackBonus->type == ef.type && stackBonus->subtype == ef.subtype)
{
@ -1279,7 +1286,7 @@ DLL_EXPORT void StacksHealedOrResurrected::applyGs( CGameState *gs )
// }
//removing all features from negative spells
BonusList tmpFeatures = changedStack->bonuses;
const BonusList tmpFeatures = changedStack->getBonusList();
//changedStack->bonuses.clear();
BOOST_FOREACH(Bonus *b, tmpFeatures)