1
0
mirror of https://github.com/vcmi/vcmi.git synced 2024-12-24 22:14:36 +02:00

Many fixes around bonus system. Some basic propagation mechanism (not clever but works).

This commit is contained in:
Michał W. Urbańczyk 2011-02-21 04:13:00 +00:00
parent 519a4186de
commit 4c9edd3f06
14 changed files with 462 additions and 333 deletions

View File

@ -1922,7 +1922,7 @@ void CAdvMapInt::tileHovered(const int3 &tile)
const CGTownInstance* townObj = dynamic_cast<const CGTownInstance*>(objAtTile);
// Show movement cursor for unguarded enemy towns, otherwise attack cursor.
if (townObj && !townObj->stacksCount())
if (townObj && !townObj->armedGarrison())
CCS->curh->changeGraphic(0, 9 + turns*6);
else
CCS->curh->changeGraphic(0, 5 + turns*6);
@ -1955,7 +1955,7 @@ void CAdvMapInt::tileHovered(const int3 &tile)
const CGGarrison* garrObj = dynamic_cast<const CGGarrison*>(objAtTile); //TODO evil evil cast!
// Show battle cursor for guarded enemy garrisons, otherwise movement cursor.
if (garrObj&& garrObj->stacksCount()
if (garrObj && garrObj->stacksCount()
&& !LOCPLINT->cb->getPlayerRelations( LOCPLINT->playerID, garrObj->tempOwner) )
CCS->curh->changeGraphic(0, 5 + turns*6);
else

View File

@ -89,9 +89,7 @@
+ 66 SPELL_AFTER_ATTACK 0 42 20 //black knights
+ 67 DOUBLE_DAMAGE_CHANCE 20 0 0 //vampire lords
+ 67 SPELL_AFTER_ATTACK 0 42 20 //dread knights
+ 68 ENEMY_MORALE_DECREASING -1 0 0 //bone dragon
+ 68 DRAGON_NATURE 0 0 0 //bone dragon is a dragon
+ 69 ENEMY_MORALE_DECREASING -1 0 0 //ghost dragon
+ 69 SPELL_AFTER_ATTACK 0 75 20 //ghost dragon
+ 69 DRAGON_NATURE 0 0 0 //ghost dragon is a dragon
+ 70 SPELL_IMMUNITY 0 62 0 //troglodytes are immune to blind
@ -190,4 +188,4 @@
- 47 FLYING //cerberus doesn't fly
- 120 DOUBLE_WIDE //psychic elemental
- 121 DOUBLE_WIDE //magic elemental
0
0

View File

@ -1100,27 +1100,6 @@ si8 BattleInfo::canTeleportTo(const CStack * stack, THex destHex, int telportLev
}
// void BattleInfo::getBonuses(BonusList &out, const CSelector &selector, const CBonusSystemNode *root /*= NULL*/) const
// {
// CBonusSystemNode::getBonuses(out, selector, root);
//
// const CStack *dest = dynamic_cast<const CStack*>(root);
// if (!dest)
// return;
//
// //TODO: make it in clean way
// if(Selector::matchesType(selector, Bonus::MORALE) || Selector::matchesType(selector, Bonus::LUCK))
// {
// BOOST_FOREACH(const CStack *s, stacks)
// {
// if(s->owner == dest->owner)
// s->getBonuses(out, selector, Selector::effectRange(Bonus::ONLY_ALLIED_ARMY), this);
// else
// s->getBonuses(out, selector, Selector::effectRange(Bonus::ONLY_ENEMY_ARMY), this);
// }
// }
// }
bool BattleInfo::battleCanShoot(const CStack * stack, THex dest) const
{
const CStack *dst = getStackT(dest);
@ -1223,7 +1202,9 @@ si8 BattleInfo::battleMaxSpellLevel() const
void BattleInfo::localInit()
{
belligerents[0]->battle = belligerents[1]->battle = this;
//TODO: attach battle to belligerents
BOOST_FOREACH(CArmedInstance *b, belligerents)
b->attachTo(this);
BOOST_FOREACH(CStack *s, stacks)
{
@ -1492,39 +1473,6 @@ BattleInfo * BattleInfo::setupBattle( int3 tile, int terrain, int terType, const
}
}
// //giving building bonuses, if siege and we have harrisoned hero
// if (town)
// {
// if (heroes[1])
// {
// for (int i=0; i<4; i++)
// {
// int val = town->defenceBonus(i);
// if (val)
// {
// GiveBonus gs;
// gs.bonus = Bonus(Bonus::ONE_BATTLE, Bonus::PRIMARY_SKILL, Bonus::OBJECT, val, -1, "", i);
// gs.id = heroes[1]->id;
// sendAndApply(&gs);
// }
// }
// }
// else//if we don't have hero - apply separately, if hero present - will be taken from hero bonuses
// {
// if(town->subID == 0 && vstd::contains(town->builtBuildings,22)) //castle, brotherhood of sword built
// for(int g=0; g<stacks.size(); ++g)
// stacks[g]->addNewBonus(makeFeature(Bonus::MORALE, Bonus::ONE_BATTLE, 0, 2, Bonus::TOWN_STRUCTURE));
//
// else if(vstd::contains(town->builtBuildings,5)) //tavern is built
// for(int g=0; g<stacks.size(); ++g)
// stacks[g]->addNewBonus(makeFeature(Bonus::MORALE, Bonus::ONE_BATTLE, 0, 1, Bonus::TOWN_STRUCTURE));
//
// if(town->subID == 1 && vstd::contains(town->builtBuildings,21)) //rampart, fountain of fortune is present
// for(int g=0; g<stacks.size(); ++g)
// stacks[g]->addNewBonus(makeFeature(Bonus::LUCK, Bonus::ONE_BATTLE, 0, 2, Bonus::TOWN_STRUCTURE));
// }
// }
//giving terrain overalay premies
int bonusSubtype = -1;
switch(terType)
@ -1586,12 +1534,13 @@ BattleInfo * BattleInfo::setupBattle( int3 tile, int terrain, int terType, const
if(town) //during siege always take premies for native terrain of faction
terrain = VLC->heroh->nativeTerrains[town->town->typeID];
ILimiter *nativeTerrain = new CreatureNativeTerrainLimiter(terrain);
boost::shared_ptr<ILimiter> nativeTerrain(new CreatureNativeTerrainLimiter(terrain));
curB->addNewBonus(makeFeature(Bonus::STACKS_SPEED, Bonus::ONE_BATTLE, 0, 1, Bonus::TERRAIN_NATIVE)->addLimiter(nativeTerrain));
curB->addNewBonus(makeFeature(Bonus::PRIMARY_SKILL, Bonus::ONE_BATTLE, PrimarySkill::ATTACK, 1, Bonus::TERRAIN_NATIVE)->addLimiter(nativeTerrain));
curB->addNewBonus(makeFeature(Bonus::PRIMARY_SKILL, Bonus::ONE_BATTLE, PrimarySkill::DEFENSE, 1, Bonus::TERRAIN_NATIVE)->addLimiter(nativeTerrain));
//////////////////////////////////////////////////////////////////////////
//tactics
int tacticLvls[2] = {0};
for(int i = 0; i < ARRAY_COUNT(tacticLvls); i++)
{
@ -1607,6 +1556,28 @@ BattleInfo * BattleInfo::setupBattle( int3 tile, int terrain, int terType, const
else
curB->tacticDistance = 0;
// workaround — bonuses affecting only enemy
for(int i = 0; i < 2; i++)
{
TNodes nodes;
curB->belligerents[i]->getRedAncestors(nodes);
BOOST_FOREACH(CBonusSystemNode *n, nodes)
{
BOOST_FOREACH(Bonus *b, n->exportedBonuses)
{
if(b->effectRange == Bonus::ONLY_ENEMY_ARMY/* && b->propagator && b->propagator->shouldBeAttached(curB)*/)
{
Bonus *bCopy = new Bonus(*b);
bCopy->effectRange = Bonus::NO_LIMIT;
bCopy->propagator.reset();
bCopy->limiter.reset(new StackOwnerLimiter(curB->sides[!i]));
curB->addNewBonus(bCopy);
}
}
}
}
return curB;
}

View File

@ -496,7 +496,7 @@ void CArtHandler::giveArtBonus( int aid, Bonus::BonusType type, int val, int sub
added->valType = valType;
added->limiter.reset(limiter);
if(type == Bonus::MORALE || Bonus::LUCK)
added->description = "\n" + artifacts[aid]->Name() + (val > 0 ? " +" : " ") + boost::lexical_cast<std::string>(val);
added->description = artifacts[aid]->Name() + (val > 0 ? " +" : " ") + boost::lexical_cast<std::string>(val);
artifacts[aid]->addNewBonus(added);
}

View File

@ -329,7 +329,7 @@ void CCreatureHandler::loadCreatures()
if(boost::algorithm::find_first(ncre.abilityRefs, "const_raises_morale"))
{
ncre.addBonus(+1, Bonus::MORALE);;
ncre.bonuses.back()->effectRange = Bonus::ONLY_ALLIED_ARMY;
ncre.bonuses.back()->addPropagator(new CPropagatorNodeType(CBonusSystemNode::HERO));
}
if(boost::algorithm::find_first(ncre.abilityRefs, "const_lowers_morale"))
{

View File

@ -3010,7 +3010,7 @@ PlayerState::PlayerState()
: color(-1), currentSelection(0xffffffff), enteredWinningCheatCode(0),
enteredLosingCheatCode(0), status(INGAME), daysWithoutCastle(0)
{
nodeType = PLAYER;
}
std::string PlayerState::nodeName() const
@ -3129,3 +3129,8 @@ DuelParameters::DuelParameters()
terType = TerrainTile::dirt;
bfieldType = 15;
}
TeamState::TeamState()
{
nodeType = TEAM;
}

View File

@ -167,7 +167,7 @@ public:
std::set<ui8> players; // members of this team
std::vector<std::vector<std::vector<ui8> > > fogOfWarMap; //true - visible, false - hidden
//TeamState();
TeamState();
template <typename Handler> void serialize(Handler &h, const int version)
{

View File

@ -977,10 +977,12 @@ void CGHeroInstance::initObj()
bonus->subtype = PrimarySkill::ATTACK;
speciality.addNewBonus(bonus);
bonus = new Bonus(*bonus);
bonus->subtype = PrimarySkill::DEFENSE;
speciality.addNewBonus(bonus);
//values will be calculated later
bonus = new Bonus(*bonus);
bonus->type = Bonus::STACKS_SPEED;
bonus->val = 1; //+1 speed
speciality.addNewBonus(bonus);
@ -993,6 +995,8 @@ void CGHeroInstance::initObj()
bonus->subtype = it->subtype; //skill id
bonus->val = it->val; //value per level, in percent
speciality.addNewBonus(bonus);
bonus = new Bonus(*bonus);
switch (it->additionalinfo)
{
case 0: //normal
@ -1068,13 +1072,16 @@ void CGHeroInstance::initObj()
bonus->subtype = it->subtype; //base id
bonus->additionalInfo = it->additionalinfo; //target id
speciality.addNewBonus(bonus);
bonus = new Bonus(*bonus);
for (std::set<ui32>::iterator i = (*creatures)[it->subtype]->upgrades.begin();
i != (*creatures)[it->subtype]->upgrades.end(); i++)
{
bonus->subtype = *i; //propagate for regular upgrades of base creature
speciality.addNewBonus(bonus);
bonus = new Bonus(*bonus);
}
delNull(bonus);
break;
}
case 10://resource generation
@ -1162,7 +1169,7 @@ void CGHeroInstance::UpdateSpeciality()
void CGHeroInstance::updateSkill(int which, int val)
{
if(which == LEADERSHIP || which == LUCK)
{
{ //luck-> VLC->generaltexth->arraytxt[73+luckSkill]; VLC->generaltexth->arraytxt[104+moraleSkill]
bool luck = which == LUCK;
Bonus::BonusType type[] = {Bonus::MORALE, Bonus::LUCK};
@ -1445,60 +1452,6 @@ void CGHeroInstance::pushPrimSkill(int which, int val)
addNewBonus(new Bonus(Bonus::PERMANENT, Bonus::PRIMARY_SKILL, Bonus::HERO_BASE_SKILL, val, id, which));
}
// void CGHeroInstance::getBonuses(BonusList &out, const CSelector &selector, const CBonusSystemNode *root /*= NULL*/) const
// {
// #define FOREACH_OWNER_TOWN(town) if(const PlayerState *p = cb->getPlayerState(tempOwner)) BOOST_FOREACH(const CGTownInstance *town, p->towns)
//
// CArmedInstance::getBonuses(out, selector, root); ///that's not part of macro!
//
// //TODO eliminate by moving secondary skills effects to bonus system
// if(Selector::matchesType(selector, Bonus::LUCK))
// {
// //luck skill
// if(int luckSkill = getSecSkillLevel(9))
// out.push_back(Bonus(Bonus::PERMANENT, Bonus::LUCK, Bonus::SECONDARY_SKILL, luckSkill, 9, VLC->generaltexth->arraytxt[73+luckSkill]));
//
// //guardian spirit
// FOREACH_OWNER_TOWN(t)
// if(t->subID ==1 && vstd::contains(t->builtBuildings,26)) //rampart with grail
// out.push_back(Bonus(Bonus::PERMANENT, Bonus::LUCK, Bonus::TOWN_STRUCTURE, +2, 26, VLC->generaltexth->buildings[1][26].first + " +2"));
// }
//
// if(Selector::matchesType(selector, Bonus::SEA_MOVEMENT))
// {
// //lighthouses
// FOREACH_OWNER_TOWN(t)
// if(t->subID == 0 && vstd::contains(t->builtBuildings,17)) //castle
// out.push_back(Bonus(Bonus::PERMANENT, Bonus::SEA_MOVEMENT, Bonus::TOWN_STRUCTURE, +500, 17, VLC->generaltexth->buildings[0][17].first + " +500"));
// }
//
// if(Selector::matchesType(selector, Bonus::MORALE))
// {
// //leadership
// if(int moraleSkill = getSecSkillLevel(6))
// out.push_back(Bonus(Bonus::PERMANENT, Bonus::MORALE, Bonus::SECONDARY_SKILL, moraleSkill, 6, VLC->generaltexth->arraytxt[104+moraleSkill]));
//
// //colossus
// FOREACH_OWNER_TOWN(t)
// if(t->subID == 0 && vstd::contains(t->builtBuildings,26)) //castle
// out.push_back(Bonus(Bonus::PERMANENT, Bonus::MORALE, Bonus::TOWN_STRUCTURE, +2, 26, VLC->generaltexth->buildings[0][26].first + " +2"));
// }
//
// if(Selector::matchesTypeSubtype(selector, Bonus::SECONDARY_SKILL_PREMY, 12)) //necromancy
// {
// FOREACH_OWNER_TOWN(t)
// {
// if(t->subID == 4) //necropolis
// {
// if(vstd::contains(t->builtBuildings,21)) //necromancy amplifier
// out.push_back(Bonus(Bonus::PERMANENT, Bonus::SECONDARY_SKILL_PREMY, Bonus::TOWN_STRUCTURE, +10, 21, VLC->generaltexth->buildings[4][21].first + " +10%", 12));
// if(vstd::contains(t->builtBuildings,26)) //grail - Soul prison
// out.push_back(Bonus(Bonus::PERMANENT, Bonus::SECONDARY_SKILL_PREMY, Bonus::TOWN_STRUCTURE, +20, 26, VLC->generaltexth->buildings[4][26].first + " +20%", 12));
// }
// }
// }
// }
EAlignment CGHeroInstance::getAlignment() const
{
return type->heroClass->getAlignment();
@ -1984,39 +1937,6 @@ int CGTownInstance::spellsAtLevel(int level, bool checkGuild) const
return ret;
}
int CGTownInstance::defenceBonus(int type) const
{
int ret=0;
switch (type)
{
/*attack*/ case 0:
if (subID == 6 && vstd::contains(builtBuildings,26))//Stronghold, grail
ret += 12;
if (subID == 7 && vstd::contains(builtBuildings,26))//Fortress, grail
ret += 10;
if (subID == 7 && vstd::contains(builtBuildings,22))//Fortress, Blood Obelisk
ret += 2;
return ret;
/*defence*/ case 1:
if (subID == 7 && vstd::contains(builtBuildings,21))//Fortress, Glyphs of Fear
ret += 2;
if (subID == 7 && vstd::contains(builtBuildings,26))//Fortress, Grail
ret += 10;
return ret;
/*spellpower*/ case 2:
if (subID == 3 && vstd::contains(builtBuildings,21))//Inferno, Brimstone Clouds
ret += 2;
if (subID == 5 && vstd::contains(builtBuildings,26))//Dungeon, Grail
ret += 12;
return ret;
/*knowledge*/ case 3:
if (subID == 2 && vstd::contains(builtBuildings,26))//Tower, Grail
ret += 15;
return ret;
}
return 0;//Why we are here? wrong type?
}
bool CGTownInstance::needsLastStack() const
{
if(garrisonHero)
@ -2028,25 +1948,30 @@ void CGTownInstance::onHeroVisit(const CGHeroInstance * h) const
{
if( !cb->gameState()->getPlayerRelations( getOwner(), h->getOwner() ))//if this is enemy
{
if(stacksCount() > 0 || visitingHero)
if(armedGarrison() || visitingHero)
{
const CGHeroInstance *defendingHero = NULL;
const CArmedInstance *defendingArmy = this;
if(visitingHero)
defendingHero = visitingHero;
else if(garrisonHero)
defendingHero = garrisonHero;
const CArmedInstance *defendingArmy = this;
if(defendingHero)
defendingArmy = defendingHero;
bool outsideTown = (defendingHero == visitingHero && garrisonHero);
//TODO
//"borrowing" army from garrison to visiting hero
cb->startBattleI(h, defendingArmy, getSightCenter(), h, defendingHero, false, boost::bind(&CGTownInstance::fightOver, this, h, _1), (outsideTown ? NULL : this));
}
else
{
cb->setOwner(id, h->tempOwner);
removeCapitols (h->getOwner());
removeCapitols(h->getOwner());
cb->heroVisitCastle(id, h->id);
}
}
@ -2172,7 +2097,7 @@ int3 CGTownInstance::getSightCenter() const
ui8 CGTownInstance::getPassableness() const
{
if ( !stacksCount() )//empty castle - anyone can visit
if (!armedGarrison())//empty castle - anyone can visit
return ALL_PLAYERS;
if ( tempOwner == 255 )//neutral guarded - noone can visit
return 0;
@ -2309,18 +2234,85 @@ void CGTownInstance::deserializationFix()
void CGTownInstance::recreateBuildingsBonuses()
{
bonuses.remove_if(Selector::sourceType(Bonus::TOWN_STRUCTURE)); //TODO memory leak
BonusList bl;
exportedBonuses.getBonuses(bl, Selector::sourceType(Bonus::TOWN_STRUCTURE));
BOOST_FOREACH(Bonus *b, bl)
removeBonus(b);
if(subID == 4 && vstd::contains(builtBuildings, 17))
addNewBonus(new Bonus(Bonus::PERMANENT, Bonus::DARKNESS, Bonus::TOWN_STRUCTURE, 20, 17));
if(subID == 1 && vstd::contains(builtBuildings,21)) //rampart, fountain of fortune
addNewBonus(new Bonus(Bonus::PERMANENT, Bonus::LUCK, Bonus::TOWN_STRUCTURE, +2, 21, VLC->generaltexth->buildings[1][21].first + " +2"));
if(subID != 0 || !addBonusIfBuilt(22, Bonus::MORALE, +2)) //tricky! -> checks tavern only if no bratherhood of sword or not a castle
addBonusIfBuilt(5, Bonus::MORALE, +1);
if(subID == 0) //castle
{
addBonusIfBuilt(17, Bonus::SEA_MOVEMENT, +500, new CPropagatorNodeType(PLAYER)); //lighthouses
addBonusIfBuilt(26, Bonus::MORALE, +2, new CPropagatorNodeType(PLAYER)); //colossus
}
else if(subID == 1) //rampart
{
addBonusIfBuilt(21, Bonus::LUCK, +2); //fountain of fortune
addBonusIfBuilt(21, Bonus::LUCK, +2, new CPropagatorNodeType(PLAYER)); //guardian spirit
}
else if(subID == 2) //tower
{
addBonusIfBuilt(26, Bonus::PRIMARY_SKILL, +15, PrimarySkill::KNOWLEDGE); //grail
}
else if(subID == 3) //Inferno
{
addBonusIfBuilt(21, Bonus::PRIMARY_SKILL, +2, PrimarySkill::SPELL_POWER); //Brimstone Clouds
}
else if(subID == 4) //necropolis
{
addBonusIfBuilt(17, Bonus::DARKNESS, +20);
addBonusIfBuilt(21, Bonus::SECONDARY_SKILL_PREMY, +10, new CPropagatorNodeType(PLAYER), CGHeroInstance::NECROMANCY); //necromancy amplifier
addBonusIfBuilt(26, Bonus::SECONDARY_SKILL_PREMY, +20, new CPropagatorNodeType(PLAYER), CGHeroInstance::NECROMANCY); //Soul prison
}
else if(subID == 5) //Dungeon
{
addBonusIfBuilt(26, Bonus::PRIMARY_SKILL, +12, PrimarySkill::SPELL_POWER); //grail
}
else if(subID == 6) //Stronghold
{
addBonusIfBuilt(26, Bonus::PRIMARY_SKILL, +20, PrimarySkill::ATTACK); //grail
}
else if(subID == 7) //Fortress
{
addBonusIfBuilt(21, Bonus::PRIMARY_SKILL, +2, PrimarySkill::DEFENSE); //Glyphs of Fear
addBonusIfBuilt(22, Bonus::PRIMARY_SKILL, +2, PrimarySkill::ATTACK); //Blood Obelisk
addBonusIfBuilt(26, Bonus::PRIMARY_SKILL, +10, PrimarySkill::ATTACK); //grail
addBonusIfBuilt(26, Bonus::PRIMARY_SKILL, +10, PrimarySkill::DEFENSE); //grail
}
else if(subID == 8)
{
if(subID == 0 && vstd::contains(builtBuildings,22)) //castle, brotherhood of sword built
addNewBonus(new Bonus(Bonus::PERMANENT, Bonus::MORALE, Bonus::TOWN_STRUCTURE, +2, 22, VLC->generaltexth->buildings[0][22].first + " +2"));
else if(vstd::contains(builtBuildings,5)) //tavern is built
addNewBonus(new Bonus(Bonus::PERMANENT, Bonus::MORALE, Bonus::TOWN_STRUCTURE, +1, 5, VLC->generaltexth->buildings[0][5].first + " +1"));
}
}
bool CGTownInstance::addBonusIfBuilt(int building, int type, int val, int subtype /*= -1*/)
{
return addBonusIfBuilt(building, type, val, NULL, subtype);
}
bool CGTownInstance::addBonusIfBuilt(int building, int type, int val, IPropagator *prop, int subtype /*= -1*/)
{
if(vstd::contains(builtBuildings, building))
{
std::ostringstream descr;
descr << VLC->generaltexth->buildings[subID][building].first << " ";
if(val > 0)
descr << "+";
else if(val < 0)
descr << "-";
descr << val;
Bonus *b = new Bonus(Bonus::PERMANENT, type, Bonus::TOWN_STRUCTURE, val, building, descr.str(), subtype);
if(prop)
b->addPropagator(prop);
addNewBonus(b);
return true;
}
return false;
}
void CGTownInstance::setVisitingHero(CGHeroInstance *h)
@ -2370,6 +2362,11 @@ void CGTownInstance::setGarrisonedHero(CGHeroInstance *h)
}
}
bool CGTownInstance::armedGarrison() const
{
return stacksCount() || garrisonHero;
}
void CGVisitableOPH::onHeroVisit( const CGHeroInstance * h ) const
{
if(visitors.find(h->id)==visitors.end())
@ -3099,20 +3096,6 @@ void CGCreature::joinDecision(const CGHeroInstance *h, int cost, ui32 accept) co
cb->giveResource(h->tempOwner,6,-cost);
cb->tryJoiningArmy(this, h, true, false);
// int slot = h->getSlotFor(subID);
// if(slot >= 0) //there is place
// {
// //add creatures
// SetGarrisons sg;
// sg.garrs[h->id] = h->getArmy();
// sg.garrs[h->id].addToSlot(slot, subID, getStackCount(0));
// cb->sendAndApply(&sg);
// cb->removeObject(id);
// }
// else
// {
// cb->showGarrisonDialog(id,h->id,true,boost::bind(&IGameCallback::removeObject,cb,id)); //show garrison window and remove ourselves from map when player ends
// }
}
}
@ -4764,6 +4747,7 @@ void CGMagicSpring::onHeroVisit(const CGHeroInstance * h) const
iw.text << std::pair<ui8,ui32>(11,messageID);
cb->showInfoDialog(&iw);
}
const std::string & CGMagicSpring::getHoverText() const
{
hoverName = VLC->generaltexth->names[ID];
@ -6530,13 +6514,6 @@ void CGLighthouse::giveBonusTo( ui8 player ) const
cb->sendAndApply(&gb);
}
CCreatureSet& CArmedInstance::getArmy() const
{ //do not return itself by value, or it will xplode
// CCreatureSet set = *this; return set;
//WARNING! A DIRTY CONST_CAST! TO BE INVESTIGATED AND PROBABLY REMOVED!
return *(const_cast<CArmedInstance*>(this));
}
void CArmedInstance::randomizeArmy(int type)
{
int max = VLC->creh->creatures.size();
@ -6558,41 +6535,11 @@ void CArmedInstance::randomizeArmy(int type)
return;
}
// void CArmedInstance::getParents(TCNodes &out, const CBonusSystemNode *root /*= NULL*/) const
// {
// /* //already given via PlayerState->getBonuses();
// const PlayerState *p = cb->getPlayerState(tempOwner);
// if (p && p != root)
// out.insert(p);
// */
// out.insert(&cb->gameState()->globalEffects); //global effects are always active I believe
//
// if(battle)
// out.insert(battle);
// }
CArmedInstance::CArmedInstance()
{
battle = NULL;
}
// void CArmedInstance::getBonuses(BonusList &out, const CSelector &selector, const CBonusSystemNode *root /*= NULL*/) const
// {
// CBonusSystemNode::getBonuses(out, selector, root);
//
// if(!battle)
// {
// //TODO do it clean, unify with BattleInfo version
// if(Selector::matchesType(selector, Bonus::MORALE) || Selector::matchesType(selector, Bonus::LUCK))
// {
// for(TSlots::const_iterator i=Slots().begin(); i!=Slots().end(); i++)
// i->second.getBonuses(out, selector, Selector::effectRange(Bonus::ONLY_ALLIED_ARMY), this);
// }
// }
//
// }
int CArmedInstance::valOfGlobalBonuses(CSelector selector) const
{
//if (tempOwner != NEUTRAL_PLAYER)
@ -6640,8 +6587,17 @@ void CArmedInstance::updateMoraleBonusFromArmy()
b->description = boost::str(boost::format(VLC->generaltexth->arraytxt[114]) % factions.size() % b->val); //Troops of %d alignments %d
}
// if(vstd::contains(factions,4))
// out.push_back(Bonus(Bonus::PERMANENT, Bonus::MORALE, Bonus::ARMY, -1, id, VLC->generaltexth->arraytxt[116]));//Undead in group -1
//-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));
if(vstd::contains(factions,4))
{
if(!undeadModifier)
addNewBonus(new Bonus(Bonus::PERMANENT, Bonus::MORALE, Bonus::ARMY, -1, UNDEAD_MODIFIER_ID, VLC->generaltexth->arraytxt[116]));
}
else if(undeadModifier)
removeBonus(undeadModifier);
}
void CArmedInstance::armyChanged()
@ -6963,16 +6919,6 @@ CArtifactInstance* CArtifactSet::getArt(ui16 pos)
{
return const_cast<CArtifactInstance*>((const_cast<const CArtifactSet*>(this))->getArt(pos));
}
// if(pos<19)
// if(vstd::contains(artifWorn,pos))
// return artifWorn.find(pos)->second;
// else
// return NULL;
// else
// if(pos-19 < artifacts.size())
// return artifacts[pos-19];
// else
// return NULL;
si32 CArtifactSet::getArtPos(int aid, bool onlyWorn /*= true*/) const
{

View File

@ -225,7 +225,6 @@ class DLL_EXPORT CArmedInstance: public CGObjectInstance, public CBonusSystemNod
public:
BattleInfo *battle; //set to the current battle, if engaged
CCreatureSet& getArmy() const;
void randomizeArmy(int type);
void updateMoraleBonusFromArmy();
@ -604,6 +603,8 @@ public:
std::string nodeName() const OVERRIDE;
void deserializationFix();
void recreateBuildingsBonuses();
bool addBonusIfBuilt(int building, int type, int val, IPropagator *prop, int subtype = -1); //returns true if building is built and bonus has been added
bool addBonusIfBuilt(int building, int type, int val, int subtype = -1); //convienence version of above
void setVisitingHero(CGHeroInstance *h);
void setGarrisonedHero(CGHeroInstance *h);
// void getParents(TCNodes &out, const CBonusSystemNode *root = NULL) const;
@ -635,7 +636,7 @@ public:
int dailyIncome() const; //calculates daily income of this town
int spellsAtLevel(int level, bool checkGuild) const; //levels are counted from 1 (1 - 5)
void removeCapitols (ui8 owner) const;
int defenceBonus(int type) const;//primary skills bonuses for defending hero
bool armedGarrison() const; //true if town has creatures in garrison or garrisoned hero
CGTownInstance();
virtual ~CGTownInstance();

View File

@ -13,8 +13,10 @@
#include "CGeneralTextHandler.h"
#include "BattleState.h"
#define FOREACH_CONST_PARENT(pname) TCNodes parents; getParents(parents); BOOST_FOREACH(const CBonusSystemNode *pname, parents)
#define FOREACH_PARENT(pname) TNodes parents; getParents(parents); BOOST_FOREACH(CBonusSystemNode *pname, parents)
#define FOREACH_CONST_PARENT(pname) TCNodes lparents; getParents(lparents); BOOST_FOREACH(const CBonusSystemNode *pname, lparents)
#define FOREACH_PARENT(pname) TNodes lparents; getParents(lparents); BOOST_FOREACH(CBonusSystemNode *pname, lparents)
#define FOREACH_RED_CHILD(pname) TNodes lchildren; getRedChildren(lchildren); BOOST_FOREACH(CBonusSystemNode *pname, lchildren)
#define FOREACH_RED_PARENT(pname) TNodes lparents; getRedParents(lparents); BOOST_FOREACH(CBonusSystemNode *pname, lparents)
#define BONUS_NAME(x) ( #x, Bonus::x )
DLL_EXPORT const std::map<std::string, int> bonusNameMap = boost::assign::map_list_of BONUS_LIST;
@ -124,12 +126,6 @@ void DLL_EXPORT BonusList::getBonuses(BonusList &out, const CSelector &selector,
out.push_back(i);
}
void DLL_EXPORT BonusList::removeSpells(Bonus::BonusSource sourceType)
{
remove_if(Selector::sourceType(sourceType));
}
void BonusList::limit(const CBonusSystemNode &node)
{
remove_if(boost::bind(&CBonusSystemNode::isLimitedOnUs, boost::ref(node), _1));
@ -338,19 +334,20 @@ CBonusSystemNode::~CBonusSystemNode()
while(children.size())
children.front()->detachFrom(this);
}
BOOST_FOREACH(Bonus *b, exportedBonuses)
delete b;
}
void CBonusSystemNode::attachTo(CBonusSystemNode *parent)
{
assert(!vstd::contains(parents, parent));
parents.push_back(parent);
// BOOST_FOREACH(Bonus *b, exportedBonuses)
// propagateBonus(b);
//
// if(parent->weActAsBonusSourceOnly())
// {
//
// }
if(parent->actsAsBonusSourceOnly())
parent->newRedDescendant(this);
else
newRedDescendant(parent);
parent->newChildAttached(this);
}
@ -358,16 +355,18 @@ void CBonusSystemNode::attachTo(CBonusSystemNode *parent)
void CBonusSystemNode::detachFrom(CBonusSystemNode *parent)
{
assert(vstd::contains(parents, parent));
parents -= parent;
//unpropagate bonus
if(parent->actsAsBonusSourceOnly())
parent->removedRedDescendant(this);
else
removedRedDescendant(parent);
parents -= parent;
parent->childDetached(this);
}
void CBonusSystemNode::popBonuses(const CSelector &s)
{
//TODO
//prop
BonusList bl;
exportedBonuses.getBonuses(bl, s);
BOOST_FOREACH(Bonus *b, bl)
@ -384,24 +383,22 @@ void CBonusSystemNode::popBonuses(const CSelector &s)
void CBonusSystemNode::addNewBonus(Bonus *b)
{
assert(!vstd::contains(exportedBonuses,b));
exportedBonuses.push_back(b);
propagateBonus(b);
if(b->propagator)
propagateBonus(b);
else
bonuses.push_back(b);
}
void CBonusSystemNode::removeBonus(Bonus *b)
{
exportedBonuses -= b;
CBonusSystemNode *whereIsOurBonus = whereToPropagate(b);
whereIsOurBonus->bonuses -= b;
delNull(b);
}
CBonusSystemNode * CBonusSystemNode::whereToPropagate(Bonus *b)
{
if(b->propagator)
return b->propagator->getDestNode(this);
unpropagateBonus(b);
else
return this;
bonuses -= b;
delNull(b);
}
bool CBonusSystemNode::isLimitedOnUs(Bonus *b) const
@ -409,7 +406,7 @@ bool CBonusSystemNode::isLimitedOnUs(Bonus *b) const
return b->limiter && b->limiter->limit(b, *this);
}
bool CBonusSystemNode::weActAsBonusSourceOnly() const
bool CBonusSystemNode::actsAsBonusSourceOnly() const
{
switch(nodeType)
{
@ -422,14 +419,28 @@ bool CBonusSystemNode::weActAsBonusSourceOnly() const
}
}
TNodesVector & CBonusSystemNode::nodesOnWhichWePropagate()
{
return weActAsBonusSourceOnly() ? children : parents;
}
void CBonusSystemNode::propagateBonus(Bonus * b)
{
whereToPropagate(b)->bonuses.push_back(b);
if(b->propagator->shouldBeAttached(this))
{
bonuses.push_back(b);
BONUS_LOG_LINE("#$# " << b->Description() << " #propagated to# " << nodeName());
}
FOREACH_RED_CHILD(child)
child->propagateBonus(b);
}
void CBonusSystemNode::unpropagateBonus(Bonus * b)
{
if(b->propagator->shouldBeAttached(this))
{
bonuses -= b;
BONUS_LOG_LINE("#$#" << b->Description() << " #is no longer propagated to# " << nodeName());
}
FOREACH_RED_CHILD(child)
child->unpropagateBonus(b);
}
void CBonusSystemNode::newChildAttached(CBonusSystemNode *child)
@ -469,6 +480,92 @@ void CBonusSystemNode::deserializationFix()
tlog2 << "Deserialization fix called on bare CBSN? Shouldn't be...\n";
}
void CBonusSystemNode::getRedParents(TNodes &out)
{
FOREACH_PARENT(pname)
{
if(pname->actsAsBonusSourceOnly())
{
out.insert(pname);
}
}
if(!actsAsBonusSourceOnly())
{
BOOST_FOREACH(CBonusSystemNode *child, children)
{
out.insert(child);
}
}
}
void CBonusSystemNode::getRedChildren(TNodes &out)
{
FOREACH_PARENT(pname)
{
if(!pname->actsAsBonusSourceOnly())
{
out.insert(pname);
}
}
if(actsAsBonusSourceOnly())
{
BOOST_FOREACH(CBonusSystemNode *child, children)
{
out.insert(child);
}
}
}
void CBonusSystemNode::newRedDescendant(CBonusSystemNode *descendant)
{
BOOST_FOREACH(Bonus *b, exportedBonuses)
if(b->propagator)
descendant->propagateBonus(b);
FOREACH_RED_PARENT(parent)
parent->newRedDescendant(descendant);
}
void CBonusSystemNode::removedRedDescendant(CBonusSystemNode *descendant)
{
BOOST_FOREACH(Bonus *b, exportedBonuses)
if(b->propagator)
descendant->unpropagateBonus(b);
FOREACH_RED_PARENT(parent)
parent->removedRedDescendant(descendant);
}
void CBonusSystemNode::getRedAncestors(TNodes &out)
{
getRedParents(out);
FOREACH_RED_PARENT(p)
p->getRedAncestors(out);
}
void CBonusSystemNode::getRedDescendants(TNodes &out)
{
getRedChildren(out);
FOREACH_RED_CHILD(c)
c->getRedChildren(out);
}
void CBonusSystemNode::battleTurnPassed()
{
BonusList bonusesCpy = exportedBonuses; //copy, because removing bonuses invalidates iters
BOOST_FOREACH(Bonus *b, bonusesCpy)
{
if(b->duration & Bonus::N_TURNS)
{
b->turnsRemain--;
if(b->turnsRemain <= 0)
removeBonus(b);
}
}
}
int NBonus::valOf(const CBonusSystemNode *obj, Bonus::BonusType type, int subtype /*= -1*/)
{
if(obj)
@ -562,7 +659,23 @@ Bonus::~Bonus()
Bonus * Bonus::addLimiter(ILimiter *Limiter)
{
limiter.reset(Limiter);
return addLimiter(boost::shared_ptr<ILimiter>(Limiter));
}
Bonus * Bonus::addLimiter(boost::shared_ptr<ILimiter> Limiter)
{
limiter = Limiter;
return this;
}
Bonus * Bonus::addPropagator(IPropagator *Propagator)
{
return addPropagator(boost::shared_ptr<IPropagator>(Propagator));
}
Bonus * Bonus::addPropagator(boost::shared_ptr<IPropagator> Propagator)
{
propagator = Propagator;
return this;
}
@ -618,6 +731,27 @@ namespace Selector
dummy.subtype = subtype;
return sel(&dummy);
}
bool DLL_EXPORT positiveSpellEffects(const Bonus *b)
{
if(b->source == Bonus::SPELL_EFFECT)
{
CSpell *sp = VLC->spellh->spells[b->sid];
return sp->positiveness == 1;
}
return false; //not a spell effect
}
}
const CStack * retreiveStackBattle(const CBonusSystemNode *node)
{
switch(node->nodeType)
{
case CBonusSystemNode::STACK_BATTLE:
return static_cast<const CStack*>(node);
default:
return NULL;
}
}
const CStackInstance * retreiveStackInstance(const CBonusSystemNode *node)
@ -732,9 +866,35 @@ IPropagator::~IPropagator()
}
CBonusSystemNode * IPropagator::getDestNode(CBonusSystemNode *source)
// CBonusSystemNode * IPropagator::getDestNode(CBonusSystemNode *source, CBonusSystemNode *redParent, CBonusSystemNode *redChild)
// {
// tlog1 << "IPropagator::getDestNode called!\n";
// return source;
// }
bool IPropagator::shouldBeAttached(CBonusSystemNode *dest)
{
return source;
return false;
}
// CBonusSystemNode * CPropagatorNodeType::getDestNode(CBonusSystemNode *source, CBonusSystemNode *redParent, CBonusSystemNode *redChild)
// {
// return NULL;
// }
CPropagatorNodeType::CPropagatorNodeType()
{
}
CPropagatorNodeType::CPropagatorNodeType(ui8 NodeType)
: nodeType(NodeType)
{
}
bool CPropagatorNodeType::shouldBeAttached(CBonusSystemNode *dest)
{
return nodeType == dest->nodeType;
}
CreatureNativeTerrainLimiter::CreatureNativeTerrainLimiter(int TerrainType)
@ -749,7 +909,8 @@ CreatureNativeTerrainLimiter::CreatureNativeTerrainLimiter()
bool CreatureNativeTerrainLimiter::limit(const Bonus *b, const CBonusSystemNode &node) const
{
const CCreature *c = retrieveCreature(&node);
return !c || VLC->heroh->nativeTerrains[c->faction] != terrainType; //drop bonus for non-creatures or non-native residents
return !c || !iswith(c->faction, 0, 9) || VLC->heroh->nativeTerrains[c->faction] != terrainType; //drop bonus for non-creatures or non-native residents
//TODO neutral creatues
}
CreatureFactionLimiter::CreatureFactionLimiter(int Faction)
@ -799,10 +960,37 @@ RankRangeLimiter::RankRangeLimiter(ui8 Min, ui8 Max)
{
}
RankRangeLimiter::RankRangeLimiter()
{
minRank = maxRank = -1;
}
bool RankRangeLimiter::limit( const Bonus *b, const CBonusSystemNode &node ) const
{
const CStackInstance *csi = retreiveStackInstance(&node);
if(csi)
return csi->getExpRank() < minRank || csi->getExpRank() > maxRank;
return true;
}
bool StackOwnerLimiter::limit(const Bonus *b, const CBonusSystemNode &node) const
{
const CStack *s = retreiveStackBattle(&node);
if(s)
return s->owner != owner;
const CStackInstance *csi = retreiveStackInstance(&node);
if(csi && csi->armyObj)
return csi->armyObj->tempOwner != owner;
return true;
}
StackOwnerLimiter::StackOwnerLimiter()
: owner(-1)
{
}
StackOwnerLimiter::StackOwnerLimiter(ui8 Owner)
: owner(Owner)
{
}

View File

@ -202,9 +202,7 @@ struct DLL_EXPORT Bonus
{
NO_LIMIT = 0,
ONLY_DISTANCE_FIGHT=1, ONLY_MELEE_FIGHT, //used to mark bonuses for attack/defense primary skills from spells like Precision (distance only)
ONLY_ALLIED_ARMY, ONLY_ENEMY_ARMY,
PLAYR_HEROES,
GLOBAL //Statue of Legion etc.
ONLY_ENEMY_ARMY
};
enum ValueType
@ -303,6 +301,9 @@ struct DLL_EXPORT Bonus
std::string Description() const;
Bonus *addLimiter(ILimiter *Limiter); //returns this for convenient chain-calls
Bonus *addPropagator(IPropagator *Propagator); //returns this for convenient chain-calls
Bonus *addLimiter(boost::shared_ptr<ILimiter> Limiter); //returns this for convenient chain-calls
Bonus *addPropagator(boost::shared_ptr<IPropagator> Propagator); //returns this for convenient chain-calls
};
DLL_EXPORT std::ostream & operator<<(std::ostream &out, const Bonus &bonus);
@ -314,7 +315,6 @@ public:
void DLL_EXPORT getBonuses(BonusList &out, const CSelector &selector, const CBonusSystemNode *source = NULL) const;
void DLL_EXPORT getBonuses(BonusList &out, const CSelector &selector, const CSelector &limit, const CBonusSystemNode *source = NULL) const;
void DLL_EXPORT getModifiersWDescr(TModDescr &out) const;
void DLL_EXPORT removeSpells(Bonus::BonusSource sourceType);
//special find functions
DLL_EXPORT Bonus * getFirst(const CSelector &select);
@ -334,7 +334,26 @@ class DLL_EXPORT IPropagator
{
public:
virtual ~IPropagator();
virtual CBonusSystemNode *getDestNode(CBonusSystemNode *source);
virtual bool shouldBeAttached(CBonusSystemNode *dest);
//virtual CBonusSystemNode *getDestNode(CBonusSystemNode *source, CBonusSystemNode *redParent, CBonusSystemNode *redChild); //called when red relation between parent-childrem is established / removed
template <typename Handler> void serialize(Handler &h, const int version)
{}
};
class DLL_EXPORT CPropagatorNodeType : public IPropagator
{
ui8 nodeType;
public:
CPropagatorNodeType();
CPropagatorNodeType(ui8 NodeType);
bool shouldBeAttached(CBonusSystemNode *dest);
//CBonusSystemNode *getDestNode(CBonusSystemNode *source, CBonusSystemNode *redParent, CBonusSystemNode *redChild) OVERRIDE;
template <typename Handler> void serialize(Handler &h, const int version)
{
h & nodeType;
}
};
class DLL_EXPORT ILimiter
@ -400,7 +419,11 @@ public:
const Bonus *getBonus(const CSelector &selector) const;
//non-const interface
void getParents(TNodes &out); //retrieves list of parent nodes (nodes to inherit bonuses from), source is the prinary asker
void getParents(TNodes &out); //retrieves list of parent nodes (nodes to inherit bonuses from)
void getRedParents(TNodes &out); //retrieves list of red parent nodes (nodes bonuses propagate from)
void getRedAncestors(TNodes &out);
void getRedChildren(TNodes &out);
void getRedDescendants(TNodes &out);
Bonus *getBonus(const CSelector &selector);
void attachTo(CBonusSystemNode *parent);
@ -411,15 +434,17 @@ public:
void newChildAttached(CBonusSystemNode *child);
void childDetached(CBonusSystemNode *child);
void propagateBonus(Bonus * b);
void unpropagateBonus(Bonus * b);
//void addNewBonus(const Bonus &b); //b will copied
void removeBonus(Bonus *b);
void newRedDescendant(CBonusSystemNode *descendant); //propagation needed
void removedRedDescendant(CBonusSystemNode *descendant); //de-propagation needed
TNodesVector &nodesOnWhichWePropagate();
bool isIndependentNode() const; //node is independent when it has no parents nor children
bool weActAsBonusSourceOnly() const;
bool actsAsBonusSourceOnly() const;
bool isLimitedOnUs(Bonus *b) const; //if bonus should be removed from list acquired from this node
CBonusSystemNode *whereToPropagate(Bonus *b);
void battleTurnPassed(); //updates count of remaining turns and removed outdated bonuses
void popBonuses(const CSelector &s);
virtual std::string nodeName() const;
void deserializationFix();
@ -434,7 +459,7 @@ public:
enum ENodeTypes
{
UNKNOWN, STACK_INSTANCE, STACK_BATTLE, SPECIALITY, ARTIFACT, CREATURE, ARTIFACT_INSTANCE, HERO
UNKNOWN, STACK_INSTANCE, STACK_BATTLE, SPECIALITY, ARTIFACT, CREATURE, ARTIFACT_INSTANCE, HERO, PLAYER, TEAM
};
};
@ -619,11 +644,27 @@ public:
}
};
class DLL_EXPORT StackOwnerLimiter : public ILimiter //applies only to creatures of given alignment
{
public:
ui8 owner;
StackOwnerLimiter();
StackOwnerLimiter(ui8 Owner);
bool limit(const Bonus *b, const CBonusSystemNode &node) const OVERRIDE;
template <typename Handler> void serialize(Handler &h, const int version)
{
h & owner;
}
};
class DLL_EXPORT RankRangeLimiter : public ILimiter //applies to creatures with min <= Rank <= max
{
public:
ui8 minRank, maxRank;
RankRangeLimiter();
RankRangeLimiter(ui8 Min, ui8 Max = 255);
bool limit(const Bonus *b, const CBonusSystemNode &node) const OVERRIDE;
@ -651,6 +692,7 @@ namespace Selector
bool DLL_EXPORT matchesType(const CSelector &sel, TBonusType type);
bool DLL_EXPORT matchesTypeSubtype(const CSelector &sel, TBonusType type, TBonusSubtype subtype);
bool DLL_EXPORT positiveSpellEffects(const Bonus *b);
}
extern DLL_EXPORT const std::map<std::string, int> bonusNameMap;

View File

@ -800,15 +800,33 @@ DLL_EXPORT void SetObjectProperty::applyGs( CGameState *gs )
if(what == ObjProperty::OWNER)
{
CBonusSystemNode *nodeToMove = NULL;
if(obj->ID == TOWNI_TYPE)
{
CGTownInstance *t = static_cast<CGTownInstance*>(obj);
nodeToMove = &t->townAndVis;
if(t->tempOwner < PLAYER_LIMIT)
gs->getPlayer(t->tempOwner)->towns -= t;
if(val < PLAYER_LIMIT)
gs->getPlayer(val)->towns.push_back(t);
}
if(CArmedInstance *cai = dynamic_cast<CArmedInstance *>(obj))
{
if(!nodeToMove)
nodeToMove = cai;
if(obj->tempOwner < PLAYER_LIMIT)
nodeToMove->detachFrom(gs->getPlayer(obj->tempOwner));
else
nodeToMove->detachFrom(&gs->globalEffects);
if(val < PLAYER_LIMIT)
nodeToMove->attachTo(gs->getPlayer(val));
else
nodeToMove->attachTo(&gs->globalEffects);
}
}
obj->setProperty(what,val);
@ -852,34 +870,7 @@ DLL_EXPORT void BattleNextRound::applyGs( CGameState *gs )
if( s->hasBonusOfType(Bonus::FULL_HP_REGENERATION) && s->alive() )
s->firstHPleft = s->MaxHealth();
//remove effects and restore only those with remaining turns in duration
BonusList tmpEffects = s->bonuses;
s->bonuses.removeSpells(Bonus::SPELL_EFFECT);
BOOST_FOREACH(Bonus *it, tmpEffects)
{
it->turnsRemain--;
if(it->turnsRemain > 0)
s->addNewBonus(it);
}
//the same as above for features
BonusList tmpFeatures = s->bonuses;
s->bonuses.clear();
BOOST_FOREACH(Bonus *b, tmpFeatures)
{
if((b->duration & Bonus::N_TURNS) != 0)
{
b->turnsRemain--;
if(b->turnsRemain > 0)
s->addNewBonus(b);
}
else
{
s->addNewBonus(b);
}
}
s->battleTurnPassed();
}
}
@ -1048,28 +1039,10 @@ DLL_EXPORT void BattleSpellCast::applyGs( CGameState *gs )
CStack *s = gs->curB->getStack(*it);
if(s && !vstd::contains(resisted, s->ID)) //if stack exists and it didn't resist
{
BonusList remainingEff;
//WTF?
for (BonusList::iterator it = remainingEff.begin(); it != remainingEff.end(); it++)
{
if (onlyHelpful && VLC->spellh->spells[ (*it)->sid ]->positiveness != 1)
{
remainingEff.push_back(*it);
}
}
s->bonuses.removeSpells(Bonus::SPELL_EFFECT); //removing all effects
s->bonuses = remainingEff; //assigning effects that should remain
//removing all features from spells
BonusList tmpFeatures = s->bonuses;
s->bonuses.clear();
BOOST_FOREACH(Bonus *b, tmpFeatures)
{
const CSpell *sp = b->sourceSpell();
if(sp && sp->positiveness != 1) //if(b->source != HeroBonus::SPELL_EFFECT || b.positiveness != 1)
s->addNewBonus(b);
}
if(onlyHelpful)
s->popBonuses(Selector::positiveSpellEffects);
else
s->popBonuses(Selector::sourceType(Bonus::SPELL_EFFECT));
}
}
}

View File

@ -75,12 +75,17 @@ void registerTypes1(Serializer &s)
s.template registerType<CGBlackMarket>();
s.template registerType<CGUniversity>();
//end of objects
s.template registerType<IPropagator>();
s.template registerType<CPropagatorNodeType>();
s.template registerType<ILimiter>();
s.template registerType<CCreatureTypeLimiter>();
s.template registerType<HasAnotherBonusLimiter>();
s.template registerType<CreatureNativeTerrainLimiter>();
s.template registerType<CreatureFactionLimiter>();
s.template registerType<CreatureAlignmentLimiter>();
s.template registerType<RankRangeLimiter>();
s.template registerType<StackOwnerLimiter>();
s.template registerType<CBonusSystemNode>();
s.template registerType<CArtifact>();

View File

@ -2064,8 +2064,8 @@ bool CGameHandler::arrangeStacks( si32 id1, si32 id2, ui8 what, ui8 p1, ui8 p2,
}
else if(what==3) //split
{
if ( (s1->tempOwner != player && S1.stacks[p1]->count < s1->getArmy().getStackCount(p1) )
|| (s2->tempOwner != player && S2.stacks[p2]->count < s2->getArmy().getStackCount(p2) ) )
if ( (s1->tempOwner != player && S1.stacks[p1]->count < s1->getStackCount(p1) )
|| (s2->tempOwner != player && S2.stacks[p2]->count < s2->getStackCount(p2) ) )
{
complain("Can't move troops of another player!");
return false;