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:
parent
a7577ccb6b
commit
55e7959fd9
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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())
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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")
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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))
|
||||
|
||||
|
@ -469,7 +469,7 @@ void CStackInstance::init()
|
||||
type = NULL;
|
||||
idRand = -1;
|
||||
_armyObj = NULL;
|
||||
nodeType = STACK_INSTANCE;
|
||||
setNodeType(STACK_INSTANCE);
|
||||
}
|
||||
|
||||
int CStackInstance::getQuantityID() const
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
156
lib/HeroBonus.h
156
lib/HeroBonus.h
@ -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;
|
||||
};
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
|
Loading…
x
Reference in New Issue
Block a user