1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-01-24 03:47:18 +02:00

Separated CStack and CStackInstance.

This commit is contained in:
Michał W. Urbańczyk 2010-11-20 17:36:02 +00:00
parent 27f83ea8c3
commit 9250cc8adf
12 changed files with 132 additions and 79 deletions

View File

@ -138,7 +138,7 @@ void CBattleLogic::MakeStatistics(int currentCreatureId)
m_statHitPoints.push_back(std::pair<int, int>(id, hitPoints));
m_statMaxSpeed.push_back(std::pair<int, int>(id, stackHP));
totalEnemyDamage += (st->type->damageMax + st->type->damageMin) * st->count / 2;
totalEnemyDamage += (st->getCreature()->damageMax + st->getCreature()->damageMin) * st->count / 2;
totalEnemyHitPoints += hitPoints;
// calculate casualties
@ -195,12 +195,12 @@ void CBattleLogic::MakeStatistics(int currentCreatureId)
m_statCasualties.push_back(std::pair<int, SCreatureCasualties>(id, cs));
if (st->type->isShooting() && st->shots > 0)
if (st->getCreature()->isShooting() && st->shots > 0)
{
m_statDistanceFromShooters.push_back(std::pair<int, int>(id, m_battleHelper.GetShortestDistance(currentStack->position, st->position)));
}
if (currentStack->hasBonusOfType(Bonus::FLYING) || (currentStack->type->isShooting() && currentStack->shots > 0))
if (currentStack->hasBonusOfType(Bonus::FLYING) || (currentStack->getCreature()->isShooting() && currentStack->shots > 0))
{
m_statDistance.push_back(std::pair<int, int>(id, m_battleHelper.GetShortestDistance(currentStack->position, st->position)));
}
@ -259,7 +259,7 @@ void CBattleLogic::MakeStatistics(int currentCreatureId)
BattleAction CBattleLogic::MakeDecision(int stackID)
{
const CStack *currentStack = m_cb->battleGetStackByID(stackID);
if(currentStack->position < 0 || currentStack->type->idNumber == 147) //turret or first aid kit
if(currentStack->position < 0 || currentStack->getCreature()->idNumber == 147) //turret or first aid kit
{
return MakeDefend(stackID);
}
@ -762,9 +762,9 @@ void CBattleLogic::PrintBattleAction(const BattleAction &action) // for debug pu
message += ", " + boost::lexical_cast<std::string>(m_battleHelper.DecodeYPosition(action.additionalInfo));
message += ", creature - ";
const CStack *c = m_cb->battleGetStackByPos(action.additionalInfo);
if (c && c->type)
if (c && c->getCreature())
{
message += c->type->nameRef;
message += c->getCreature()->nameRef;
}
else
{

View File

@ -578,7 +578,7 @@ CCreature CCallback::battleGetCreature(int number)
for(size_t h=0; h<gs->curB->stacks.size(); ++h)
{
if(gs->curB->stacks[h]->ID == number) //creature found
return *(gs->curB->stacks[h]->type);
return *(gs->curB->stacks[h]->getCreature());
}
#ifndef __GNUC__
throw new std::exception("Cannot find the creature");

View File

@ -475,7 +475,7 @@ bool CDefenceAnim::init()
if(IDby != -1)
{
int attackerAnimType = owner->creAnims[IDby]->getType();
if( attackerAnimType == 11 && attackerAnimType == 12 && attackerAnimType == 13 && owner->creAnims[IDby]->getFrame() < attacker->type->attackClimaxFrame )
if( attackerAnimType == 11 && attackerAnimType == 12 && attackerAnimType == 13 && owner->creAnims[IDby]->getFrame() < attacker->getCreature()->attackClimaxFrame )
return false;
}
@ -506,7 +506,7 @@ bool CDefenceAnim::init()
{
for(std::list<SProjectileInfo>::const_iterator it = owner->projectiles.begin(); it != owner->projectiles.end(); ++it)
{
if(it->creID == attacker->type->idNumber)
if(it->creID == attacker->getCreature()->idNumber)
{
return false;
}
@ -516,13 +516,13 @@ bool CDefenceAnim::init()
//initializing
if(killed)
{
CGI->soundh->playSound(battle_sound(attacked->type, killed));
CGI->soundh->playSound(battle_sound(attacked->getCreature(), killed));
owner->creAnims[stackID]->setType(5); //death
}
else
{
// TODO: this block doesn't seems correct if the unit is defending.
CGI->soundh->playSound(battle_sound(attacked->type, wince));
CGI->soundh->playSound(battle_sound(attacked->getCreature(), wince));
owner->creAnims[stackID]->setType(3); //getting hit
}
@ -626,7 +626,7 @@ bool CBattleStackMoved::init()
//unit reversed
if(owner->moveSh <= 0)
owner->moveSh = CGI->soundh->playSound(battle_sound(movedStack->type, move), -1);
owner->moveSh = CGI->soundh->playSound(battle_sound(movedStack->getCreature(), move), -1);
//step shift calculation
posX = owner->creAnims[stackID]->pos.x, posY = owner->creAnims[stackID]->pos.y; // for precise calculations ;]
@ -742,7 +742,7 @@ bool CBattleMoveStart::init()
return false;
}
CGI->soundh->playSound(battle_sound(movedStack->type, startMoving));
CGI->soundh->playSound(battle_sound(movedStack->getCreature(), startMoving));
return true;
}
@ -787,7 +787,7 @@ bool CBattleMoveEnd::init()
return false;
}
CGI->soundh->playSound(battle_sound(movedStack->type, endMoving));
CGI->soundh->playSound(battle_sound(movedStack->getCreature(), endMoving));
owner->creAnims[stackID]->setType(21);
@ -828,9 +828,9 @@ void CBattleAttack::nextFrame()
if(owner->creAnims[stackID]->onFirstFrameInGroup())
{
if(shooting)
CGI->soundh->playSound(battle_sound(attackingStack->type, shoot));
CGI->soundh->playSound(battle_sound(attackingStack->getCreature(), shoot));
else
CGI->soundh->playSound(battle_sound(attackingStack->type, attack));
CGI->soundh->playSound(battle_sound(attackingStack->getCreature(), attack));
}
else if(owner->creAnims[stackID]->onLastFrameInGroup())
{
@ -852,7 +852,7 @@ CBattleAttack::CBattleAttack(CBattleInterface * _owner, int _stackID, int _dest,
attackingStack = owner->curInt->cb->battleGetStackByID(_stackID, false);
assert(attackingStack && "attackingStack is NULL in CBattleAttack::CBattleAttack !\n");
if(attackingStack->type->idNumber != 145) //catapult is allowed to attack not-creature
if(attackingStack->getCreature()->idNumber != 145) //catapult is allowed to attack not-creature
{
assert(attackedStack && "attackedStack is NULL in CBattleAttack::CBattleAttack !\n");
}
@ -981,7 +981,7 @@ bool CShootingAnim::init()
projectileAngle = -projectileAngle;
SProjectileInfo spi;
spi.creID = shooter->type->idNumber;
spi.creID = shooter->getCreature()->idNumber;
spi.reverse = !shooter->attackerOwned;
spi.step = 0;
@ -1009,18 +1009,18 @@ bool CShootingAnim::init()
if(projectileAngle > straightAngle) //upper shot
{
spi.x = xycoord.x + 200 + shooter->type->upperRightMissleOffsetX;
spi.y = xycoord.y + 100 - shooter->type->upperRightMissleOffsetY;
spi.x = xycoord.x + 200 + shooter->getCreature()->upperRightMissleOffsetX;
spi.y = xycoord.y + 100 - shooter->getCreature()->upperRightMissleOffsetY;
}
else if(projectileAngle < -straightAngle) //lower shot
{
spi.x = xycoord.x + 200 + shooter->type->lowerRightMissleOffsetX;
spi.y = xycoord.y + 150 - shooter->type->lowerRightMissleOffsetY;
spi.x = xycoord.x + 200 + shooter->getCreature()->lowerRightMissleOffsetX;
spi.y = xycoord.y + 150 - shooter->getCreature()->lowerRightMissleOffsetY;
}
else //straight shot
{
spi.x = xycoord.x + 200 + shooter->type->rightMissleOffsetX;
spi.y = xycoord.y + 125 - shooter->type->rightMissleOffsetY;
spi.x = xycoord.x + 200 + shooter->getCreature()->rightMissleOffsetX;
spi.y = xycoord.y + 125 - shooter->getCreature()->rightMissleOffsetY;
}
spi.lastStep = sqrt((float)((destcoord.x - spi.x)*(destcoord.x - spi.x) + (destcoord.y - spi.y) * (destcoord.y - spi.y))) / 40;
if(spi.lastStep == 0)
@ -1273,25 +1273,25 @@ CBattleInterface::CBattleInterface(const CCreatureSet * army1, const CCreatureSe
//loading projectiles for units
for(std::map<int, CStack>::iterator g = stacks.begin(); g != stacks.end(); ++g)
{
int creID = (g->second.type->idNumber == 149) ? CGI->creh->factionToTurretCreature[siegeH->town->town->typeID] : g->second.type->idNumber; //id of creature whose shots should be loaded
if(g->second.type->isShooting() && CGI->creh->idToProjectile.find(creID) != CGI->creh->idToProjectile.end())
int creID = (g->second.getCreature()->idNumber == 149) ? CGI->creh->factionToTurretCreature[siegeH->town->town->typeID] : g->second.getCreature()->idNumber; //id of creature whose shots should be loaded
if(g->second.getCreature()->isShooting() && CGI->creh->idToProjectile.find(creID) != CGI->creh->idToProjectile.end())
{
idToProjectile[g->second.type->idNumber] = CDefHandler::giveDef(CGI->creh->idToProjectile.find(creID)->second);
idToProjectile[g->second.getCreature()->idNumber] = CDefHandler::giveDef(CGI->creh->idToProjectile.find(creID)->second);
if(idToProjectile[g->second.type->idNumber]->ourImages.size() > 2) //add symmetric images
if(idToProjectile[g->second.getCreature()->idNumber]->ourImages.size() > 2) //add symmetric images
{
for(int k = idToProjectile[g->second.type->idNumber]->ourImages.size()-2; k > 1; --k)
for(int k = idToProjectile[g->second.getCreature()->idNumber]->ourImages.size()-2; k > 1; --k)
{
Cimage ci;
ci.bitmap = CSDL_Ext::rotate01(idToProjectile[g->second.type->idNumber]->ourImages[k].bitmap);
ci.bitmap = CSDL_Ext::rotate01(idToProjectile[g->second.getCreature()->idNumber]->ourImages[k].bitmap);
ci.groupNumber = 0;
ci.imName = std::string();
idToProjectile[g->second.type->idNumber]->ourImages.push_back(ci);
idToProjectile[g->second.getCreature()->idNumber]->ourImages.push_back(ci);
}
}
for(int s=0; s<idToProjectile[g->second.type->idNumber]->ourImages.size(); ++s) //alpha transforming
for(int s=0; s<idToProjectile[g->second.getCreature()->idNumber]->ourImages.size(); ++s) //alpha transforming
{
CSDL_Ext::alphaTransform(idToProjectile[g->second.type->idNumber]->ourImages[s].bitmap);
CSDL_Ext::alphaTransform(idToProjectile[g->second.getCreature()->idNumber]->ourImages[s].bitmap);
}
}
}
@ -1794,7 +1794,7 @@ void CBattleInterface::mouseMoved(const SDL_MouseMotionEvent &sEvent)
}
//setting console text
char buf[500];
sprintf(buf, CGI->generaltexth->allTexts[297].c_str(), shere->count == 1 ? shere->type->nameSing.c_str() : shere->type->namePl.c_str());
sprintf(buf, CGI->generaltexth->allTexts[297].c_str(), shere->count == 1 ? shere->getCreature()->nameSing.c_str() : shere->getCreature()->namePl.c_str());
console->alterTxt = buf;
console->whoSetAlter = 0;
mouseHoveredStack = shere->ID;
@ -1822,7 +1822,7 @@ void CBattleInterface::mouseMoved(const SDL_MouseMotionEvent &sEvent)
std::ostringstream estDmg;
estDmg << estimatedDmg.first << " - " << estimatedDmg.second;
//printing
sprintf(buf, CGI->generaltexth->allTexts[296].c_str(), shere->count == 1 ? shere->type->nameSing.c_str() : shere->type->namePl.c_str(), sactive->shots, estDmg.str().c_str());
sprintf(buf, CGI->generaltexth->allTexts[296].c_str(), shere->count == 1 ? shere->getCreature()->nameSing.c_str() : shere->getCreature()->namePl.c_str(), sactive->shots, estDmg.str().c_str());
console->alterTxt = buf;
console->whoSetAlter = 0;
}
@ -1972,7 +1972,7 @@ void CBattleInterface::mouseMoved(const SDL_MouseMotionEvent &sEvent)
std::ostringstream estDmg;
estDmg << estimatedDmg.first << " - " << estimatedDmg.second;
//printing
sprintf(buf, CGI->generaltexth->allTexts[36].c_str(), shere->count == 1 ? shere->type->nameSing.c_str() : shere->type->namePl.c_str(), estDmg.str().c_str());
sprintf(buf, CGI->generaltexth->allTexts[36].c_str(), shere->count == 1 ? shere->getCreature()->nameSing.c_str() : shere->getCreature()->namePl.c_str(), estDmg.str().c_str());
console->alterTxt = buf;
console->whoSetAlter = 0;
}
@ -2006,12 +2006,12 @@ void CBattleInterface::mouseMoved(const SDL_MouseMotionEvent &sEvent)
if(sactive->hasBonusOfType(Bonus::FLYING))
{
CGI->curh->changeGraphic(1,2);
sprintf(buf, CGI->generaltexth->allTexts[295].c_str(), sactive->count == 1 ? sactive->type->nameSing.c_str() : sactive->type->namePl.c_str());
sprintf(buf, CGI->generaltexth->allTexts[295].c_str(), sactive->count == 1 ? sactive->getCreature()->nameSing.c_str() : sactive->getCreature()->namePl.c_str());
}
else
{
CGI->curh->changeGraphic(1,1);
sprintf(buf, CGI->generaltexth->allTexts[294].c_str(), sactive->count == 1 ? sactive->type->nameSing.c_str() : sactive->type->namePl.c_str());
sprintf(buf, CGI->generaltexth->allTexts[294].c_str(), sactive->count == 1 ? sactive->getCreature()->nameSing.c_str() : sactive->getCreature()->namePl.c_str());
}
console->alterTxt = buf;
@ -2076,7 +2076,7 @@ void CBattleInterface::mouseMoved(const SDL_MouseMotionEvent &sEvent)
CGI->curh->changeGraphic(3, 0);
//setting console text
char buf[500];
std::string creName = stackUnder->count > 1 ? stackUnder->type->namePl : stackUnder->type->nameSing;
std::string creName = stackUnder->count > 1 ? stackUnder->getCreature()->namePl : stackUnder->getCreature()->nameSing;
sprintf(buf, CGI->generaltexth->allTexts[27].c_str(), CGI->spellh->spells[spellToCast->additionalInfo].name.c_str(), creName.c_str());
console->alterTxt = buf;
console->whoSetAlter = 0;
@ -2236,7 +2236,7 @@ void CBattleInterface::newStack(int stackID)
}
else
{
creAnims[stackID] = new CCreatureAnimation(newStack->type->animDefName);
creAnims[stackID] = new CCreatureAnimation(newStack->getCreature()->animDefName);
}
creAnims[stackID]->setType(2);
creAnims[stackID]->pos = Rect(coords.x, coords.y, creAnims[newStack->ID]->fullWidth, creAnims[newStack->ID]->fullHeight);
@ -2779,7 +2779,7 @@ void CBattleInterface::spellCast(BattleSpellCast * sc)
boost::algorithm::replace_first(text, "%s", "Creature"); //TODO: better fix
}
boost::algorithm::replace_first(text, "%s", CGI->spellh->spells[sc->id].name);
boost::algorithm::replace_first(text, "%s", curInt->cb->battleGetStackByID(*sc->affectedCres.begin(), false)->type->namePl );
boost::algorithm::replace_first(text, "%s", curInt->cb->battleGetStackByID(*sc->affectedCres.begin(), false)->getCreature()->namePl );
console->addText(text);
}
else
@ -3154,17 +3154,17 @@ void CBattleInterface::printConsoleAttacked(int ID, int dmg, int killed, int IDb
const CStack * attacker = curInt->cb->battleGetStackByID(IDby, false);
const CStack * defender = curInt->cb->battleGetStackByID(ID, false);
int end = sprintf(tabh, CGI->generaltexth->allTexts[attacker->count > 1 ? 377 : 376].c_str(),
(attacker->count > 1 ? attacker->type->namePl.c_str() : attacker->type->nameSing.c_str()),
(attacker->count > 1 ? attacker->getCreature()->namePl.c_str() : attacker->getCreature()->nameSing.c_str()),
dmg);
if(killed > 0)
{
if(killed > 1)
{
sprintf(tabh + end, CGI->generaltexth->allTexts[379].c_str(), killed, defender->type->namePl.c_str());
sprintf(tabh + end, CGI->generaltexth->allTexts[379].c_str(), killed, defender->getCreature()->namePl.c_str());
}
else //killed == 1
{
sprintf(tabh + end, CGI->generaltexth->allTexts[378].c_str(), defender->type->nameSing.c_str());
sprintf(tabh + end, CGI->generaltexth->allTexts[378].c_str(), defender->getCreature()->nameSing.c_str());
}
}
@ -3334,7 +3334,7 @@ void CBattleInterface::startAction(const BattleAction* action)
if(txtid)
{
sprintf(txt, CGI->generaltexth->allTexts[txtid].c_str(), (stack->count != 1) ? stack->type->namePl.c_str() : stack->type->nameSing.c_str(), 0);
sprintf(txt, CGI->generaltexth->allTexts[txtid].c_str(), (stack->count != 1) ? stack->getCreature()->namePl.c_str() : stack->getCreature()->nameSing.c_str(), 0);
console->addText(txt);
}
@ -3591,7 +3591,7 @@ void CBattleHex::mouseMoved(const SDL_MouseMotionEvent &sEvent)
{
char tabh[160];
const CStack * attackedStack = myInterface->curInt->cb->battleGetStackByPos(myNumber);
const std::string & attackedName = attackedStack->count == 1 ? attackedStack->type->nameSing : attackedStack->type->namePl;
const std::string & attackedName = attackedStack->count == 1 ? attackedStack->getCreature()->nameSing : attackedStack->getCreature()->namePl;
sprintf(tabh, CGI->generaltexth->allTexts[220].c_str(), attackedName.c_str());
myInterface->console->alterTxt = std::string(tabh);
setAlterText = true;
@ -3621,7 +3621,7 @@ void CBattleHex::clickRight(tribool down, bool previousState)
if(!myst.alive()) return;
if(down)
{
GH.pushInt(new CCreInfoWindow(myst));
GH.pushInt(new CCreInfoWindow(*myst.base));
}
}
}
@ -4207,13 +4207,13 @@ void CStackQueue::StackBox::showAll( SDL_Surface *to )
//SDL_UpdateRect(bg, 0, 0, 0, 0);
CSDL_Ext::blit8bppAlphaTo24bpp(bg, NULL, to, &genRect(bg->h, bg->w, pos.x, pos.y));
//blitAt(bg, pos, to);
blitAt(graphics->bigImgs[my->type->idNumber], pos.x +9, pos.y + 1, to);
blitAt(graphics->bigImgs[my->getCreature()->idNumber], pos.x +9, pos.y + 1, to);
printAtMiddleLoc(makeNumberShort(my->count), pos.w/2, pos.h - 12, FONT_MEDIUM, zwykly, to);
}
else
{
blitAt(graphics->smallImgs[-2], pos, to);
blitAt(graphics->smallImgs[my->type->idNumber], pos, to);
blitAt(graphics->smallImgs[my->getCreature()->idNumber], pos, to);
const SDL_Color &ownerColor = (my->owner == 255 ? *graphics->neutralColor : graphics->playerColors[my->owner]);
CSDL_Ext::drawBorder(to, pos, int3(ownerColor.r, ownerColor.g, ownerColor.b));
printAtMiddleLoc(makeNumberShort(my->count), pos.w/2, pos.h - 8, FONT_TINY, zwykly, to);

View File

@ -698,7 +698,7 @@ BattleAction CPlayerInterface::activeStack(int stackID) //called when it's turn
if(vstd::contains(stack->state,MOVED)) //this stack has moved and makes second action -> high morale
{
std::string hlp = CGI->generaltexth->allTexts[33];
boost::algorithm::replace_first(hlp,"%s",(stack->count != 1) ? stack->type->namePl : stack->type->nameSing);
boost::algorithm::replace_first(hlp,"%s",(stack->count != 1) ? stack->getCreature()->namePl : stack->getCreature()->nameSing);
battleInt->displayEffect(20,stack->position);
battleInt->console->addText(hlp);
}
@ -808,7 +808,7 @@ void CPlayerInterface::battleAttack(BattleAttack *ba)
{
const CStack *stack = cb->battleGetStackByID(ba->stackAttacking);
std::string hlp = CGI->generaltexth->allTexts[45];
boost::algorithm::replace_first(hlp,"%s",(stack->count != 1) ? stack->type->namePl.c_str() : stack->type->nameSing.c_str());
boost::algorithm::replace_first(hlp,"%s",(stack->count != 1) ? stack->getCreature()->namePl.c_str() : stack->getCreature()->nameSing.c_str());
battleInt->console->addText(hlp);
battleInt->displayEffect(18,stack->position);
}

View File

@ -225,6 +225,18 @@ bool CCreatureSet::contains(const CStackInstance *stack) const
return false;
}
TSlot CCreatureSet::findStack(const CStackInstance *stack) const
{
if(!stack)
return -1;
for(TSlots::const_iterator i = slots.begin(); i != slots.end(); ++i)
if(&i->second == stack)
return i->first;
return -1;
}
CStackInstance::CStackInstance()
{
init();

View File

@ -73,6 +73,7 @@ public:
const CStackInstance& getStack(TSlot slot) const;
const CCreature* getCreature(TSlot slot) const; //workaround of map issue;
int getAmount (TSlot slot) const;
TSlot findStack(const CStackInstance *stack) const; //-1 if none
TSlot getSlotFor(TCreature creature, ui32 slotsAmount=ARMY_SIZE) const; //returns -1 if no slot available
bool mergableStacks(std::pair<TSlot, TSlot> &out, TSlot preferable = -1) const; //looks for two same stacks, returns slot positions;
bool validTypes(bool allowUnrandomized = false) const; //checks if all types of creatures are set properly

View File

@ -687,19 +687,24 @@ std::pair< std::vector<int>, int > BattleInfo::getPath(int start, int dest, bool
return std::make_pair(path, dist[dest]);
}
CStack::CStack(const CStackInstance *base, int O, int I, bool AO, int S)
: CStackInstance(*base), ID(I), owner(O), slot(S), attackerOwned(AO), position(-1),
CStack::CStack(const CStackInstance *Base, int O, int I, bool AO, int S)
: base(Base), ID(I), owner(O), slot(S), attackerOwned(AO), position(-1),
counterAttacks(1)
{
baseAmount = base->count;
count = baseAmount = base->count;
firstHPleft = valOfBonuses(Bonus::STACK_HEALTH);
shots = type->shots;
shots = getCreature()->shots;
counterAttacks += valOfBonuses(Bonus::ADDITIONAL_RETALIATION);
//alive state indication
state.insert(ALIVE);
}
CStack::CStack() : base(NULL), ID(-1), baseAmount(-1), firstHPleft(-1), owner(255), slot(255), attackerOwned(true), position(-1), counterAttacks(1)
{
}
ui32 CStack::Speed( int turn /*= 0*/ ) const
{
if(hasBonus(Selector::type(Bonus::SIEGE_WEAPON) && Selector::turns(turn))) //war machines cannot move
@ -941,7 +946,7 @@ bool CStack::moved( int turn /*= 0*/ ) const
bool CStack::doubleWide() const
{
return type->doubleWide;
return getCreature()->doubleWide;
}
int CStack::occupiedHex() const
@ -3079,7 +3084,7 @@ std::pair<ui32, ui32> BattleInfo::calculateDmgRange( const CStack* attacker, con
minDmg = attacker->getMinDamage() * attacker->count,
maxDmg = attacker->getMaxDamage() * attacker->count;
if(attacker->type->idNumber == 149) //arrow turret
if(attacker->getCreature()->idNumber == 149) //arrow turret
{
switch(attacker->position)
{
@ -3094,7 +3099,7 @@ std::pair<ui32, ui32> BattleInfo::calculateDmgRange( const CStack* attacker, con
}
}
if(attacker->hasBonusOfType(Bonus::SIEGE_WEAPON) && attacker->type->idNumber != 149) //any siege weapon, but only ballista can attack (second condition - not arrow turret)
if(attacker->hasBonusOfType(Bonus::SIEGE_WEAPON) && attacker->getCreature()->idNumber != 149) //any siege weapon, but only ballista can attack (second condition - not arrow turret)
{ //minDmg and maxDmg are multiplied by hero attack + 1
minDmg *= attackerHero->getPrimSkillLevel(0) + 1;
maxDmg *= attackerHero->getPrimSkillLevel(0) + 1;
@ -3150,7 +3155,7 @@ std::pair<ui32, ui32> BattleInfo::calculateDmgRange( const CStack* attacker, con
for(unsigned int g=0; g<affectedIds.size(); ++g)
{
if(defender->type->idNumber == affectedIds[g])
if(defender->getCreature()->idNumber == affectedIds[g])
{
attackDefenceDifference += VLC->spellh->spells[55].powers[attacker->getEffect(55)->val];
break;
@ -3209,7 +3214,7 @@ std::pair<ui32, ui32> BattleInfo::calculateDmgRange( const CStack* attacker, con
}
//handling hate effect
if( attacker->hasBonusOfType(Bonus::HATE, defender->type->idNumber) )
if( attacker->hasBonusOfType(Bonus::HATE, defender->getCreature()->idNumber) )
additiveBonus += 0.5f;
//luck bonus
@ -3316,7 +3321,7 @@ void BattleInfo::calculateCasualties( std::map<ui32,si32> *casualties ) const
si32 killed = (st->alive() ? st->baseAmount - st->count : st->baseAmount);
amax(killed, 0);
if(killed)
casualties[!st->attackerOwned][st->type->idNumber] += killed;
casualties[!st->attackerOwned][st->getCreature()->idNumber] += killed;
}
}
@ -3361,8 +3366,8 @@ std::set<CStack*> BattleInfo::getAttackedCreatures( const CSpell * s, int skillL
{
for(int it=0; it<stacks.size(); ++it)
{
if((s->id == 24 && !stacks[it]->type->isUndead()) //death ripple
|| (s->id == 25 && stacks[it]->type->isUndead()) //destroy undead
if((s->id == 24 && !stacks[it]->getCreature()->isUndead()) //death ripple
|| (s->id == 25 && stacks[it]->getCreature()->isUndead()) //destroy undead
|| (s->id == 26) //Armageddon
)
{
@ -3558,7 +3563,7 @@ ui32 BattleInfo::calculateSpellBonus(ui32 baseDamage, const CSpell * sp, const C
ret *= (100.0f + caster->valOfBonuses(Bonus::EARTH_SPELL_DMG_PREMY)) / 100.0f;
if (affectedCreature) //Hero specials like Solmyr, Deemer
ret *= (100.f + ((caster->valOfBonuses(Bonus::SPECIAL_SPELL_LEV, sp->id) * caster->level) / affectedCreature->type->level)) / 100.0f;
ret *= (100.f + ((caster->valOfBonuses(Bonus::SPECIAL_SPELL_LEV, sp->id) * caster->level) / affectedCreature->getCreature()->level)) / 100.0f;
}
return ret;
}
@ -3659,7 +3664,7 @@ bool CGameState::battleCanShoot(int ID, int dest)
if(our->hasBonusOfType(Bonus::FORGETFULL)) //forgetfulness
return false;
if(our->type->idNumber == 145 && dst) //catapult cannot attack creatures
if(our->getCreature()->idNumber == 145 && dst) //catapult cannot attack creatures
return false;
if(our->hasBonusOfType(Bonus::SHOOTER)//it's shooter
@ -4173,7 +4178,7 @@ void BattleInfo::getStackQueue( std::vector<const CStack *> &out, int howMany, i
else
p = 3;
}
else if(s->type->idNumber == 145 || s->type->idNumber == 149) //catapult and turrets are first
else if(s->getCreature()->idNumber == 145 || s->getCreature()->idNumber == 149) //catapult and turrets are first
{
p = 0;
}
@ -4447,7 +4452,7 @@ bool CMP_stack::operator()( const CStack* a, const CStack* b )
switch(phase)
{
case 0: //catapult moves after turrets
return a->type->idNumber < b->type->idNumber; //catapult is 145 and turrets are 149
return a->getCreature()->idNumber < b->getCreature()->idNumber; //catapult is 145 and turrets are 149
//TODO? turrets order
case 1: //fastest first, upper slot first
{

View File

@ -250,10 +250,13 @@ struct DLL_EXPORT BattleInfo : public CBonusSystemNode
si8 canTeleportTo(int stackID, int destHex, int telportLevel); //determines if given stack can teleport to given place
};
class DLL_EXPORT CStack : public CStackInstance
class DLL_EXPORT CStack : public CBonusSystemNode
{
public:
const CStackInstance *base;
ui32 ID; //unique ID of stack
ui32 count;
ui32 baseAmount;
ui32 firstHPleft; //HP of first creature in stack
ui8 owner, slot; //owner - player colour (255 for neutrals), slot - position in garrison (may be 255 for neutrals/called creatures)
@ -264,10 +267,10 @@ public:
std::set<ECombatInfo> state;
//overrides
const CCreature* getCreature() const {return type;}
const CCreature* getCreature() const {return base->type;}
CStack(const CStackInstance *base, int O, int I, bool AO, int S); //c-tor
CStack() : ID(-1), baseAmount(-1), firstHPleft(-1), owner(255), slot(255), attackerOwned(true), position(-1), counterAttacks(1) {} //c-tor
CStack(); //c-tor
const Bonus * getEffect(ui16 id, int turn = 0) const; //effect id (SP)
ui8 howManyEffectsSet(ui16 id) const; //returns amount of effects with given id set for this stack
bool willMove(int turn = 0) const; //if stack has remaining move this turn
@ -299,9 +302,20 @@ public:
template <typename Handler> void serialize(Handler &h, const int version)
{
h & static_cast<CStackInstance&>(*this);
TSlot slot = (base ? base->armyObj->findStack(base) : -1);
const CArmedInstance *army = (base ? base->armyObj : NULL);
if(h.saving)
{
h & army & slot;
}
else
{
h & army & slot;
base = &army->getStack(slot);
}
h & ID & baseAmount & firstHPleft & owner & slot & attackerOwned & position & state & counterAttacks
& shots;
& shots & count;
}
bool alive() const //determines if stack is alive
{

View File

@ -358,6 +358,24 @@ bool CBonusSystemNode::isLimitedOnUs(Bonus *b) const
return b->limiter && b->limiter->limit(b, *this);
}
bool CBonusSystemNode::weActAsBonusSourceOnly() const
{
switch(nodeType)
{
case CREATURE:
case ARTIFACT:
case ARTIFACT_INSTANCE:
return true;
default:
return false;
}
}
TNodesVector & CBonusSystemNode::nodesOnWhichWePropagate()
{
return weActAsBonusSourceOnly() ? children : parents;
}
int NBonus::valOf(const CBonusSystemNode *obj, Bonus::BonusType type, int subtype /*= -1*/)
{
if(obj)

View File

@ -30,6 +30,7 @@ class IPropagator;
typedef std::vector<std::pair<int,std::string> > TModDescr; //modifiers values and their descriptions
typedef std::set<CBonusSystemNode*> TNodes;
typedef std::set<const CBonusSystemNode*> TCNodes;
typedef std::vector<CBonusSystemNode *> TNodesVector;
typedef boost::function<bool(const Bonus*)> CSelector;
namespace PrimarySkill
@ -361,7 +362,7 @@ public:
BonusList bonuses; //wielded bonuses (local and up-propagated here)
BonusList exportedBonuses;
std::vector<CBonusSystemNode *> parents, //parents -> we inherit bonuses from them, we may attach our bonuses to them
TNodesVector parents, //parents -> we inherit bonuses from them, we may attach our bonuses to them
children;
ui8 nodeType;
@ -413,6 +414,8 @@ public:
//void addNewBonus(const Bonus &b); //b will copied
void removeBonus(Bonus *b);
TNodesVector &nodesOnWhichWePropagate();
bool weActAsBonusSourceOnly() const;
bool isLimitedOnUs(Bonus *b) const; //if bonus should be removed from list acquired from this node
CBonusSystemNode *whereToPropagate(Bonus *b);
@ -425,7 +428,7 @@ public:
enum ENodeTypes
{
UNKNOWN, STACK, SPECIALITY, ARTIFACT, CREATURE
UNKNOWN, STACK, SPECIALITY, ARTIFACT, CREATURE, ARTIFACT_INSTANCE
};
};

View File

@ -860,7 +860,7 @@ DLL_EXPORT void BattleAttack::applyGs( CGameState *gs )
bool hasAmmoCart = false;
BOOST_FOREACH(const CStack * st, gs->curB->stacks)
{
if(st->owner == attacker->owner && st->type->idNumber == 148 && st->alive())
if(st->owner == attacker->owner && st->getCreature()->idNumber == 148 && st->alive())
{
hasAmmoCart = true;
break;

View File

@ -436,7 +436,7 @@ void CGameHandler::startBattle(const CArmedInstance *army1, const CArmedInstance
const CGHeroInstance * curOwner = gs->battleGetOwner(next->ID);
if( (next->position < 0 && (!curOwner || curOwner->getSecSkillLevel(10) == 0)) //arrow turret, hero has no ballistics
|| (next->type->idNumber == 146 && (!curOwner || curOwner->getSecSkillLevel(20) == 0))) //ballista, hero has no artillery
|| (next->getCreature()->idNumber == 146 && (!curOwner || curOwner->getSecSkillLevel(20) == 0))) //ballista, hero has no artillery
{
BattleAction attack;
attack.actionType = 7;
@ -458,7 +458,7 @@ void CGameHandler::startBattle(const CArmedInstance *army1, const CArmedInstance
continue;
}
if(next->type->idNumber == 145 && (!curOwner || curOwner->getSecSkillLevel(10) == 0)) //catapult, hero has no ballistics
if(next->getCreature()->idNumber == 145 && (!curOwner || curOwner->getSecSkillLevel(10) == 0)) //catapult, hero has no ballistics
{
BattleAction attack;
static const int wallHexes[] = {50, 183, 182, 130, 62, 29, 12, 95};
@ -473,7 +473,7 @@ void CGameHandler::startBattle(const CArmedInstance *army1, const CArmedInstance
continue;
}
if(next->type->idNumber == 147 && (!curOwner || curOwner->getSecSkillLevel(27) == 0)) //first aid tent, hero has no first aid
if(next->getCreature()->idNumber == 147 && (!curOwner || curOwner->getSecSkillLevel(27) == 0)) //first aid tent, hero has no first aid
{
BattleAction heal;
@ -3751,7 +3751,7 @@ bool CGameHandler::makeBattleAction( BattleAction &ba )
) //nor occupy specified hex
)
{
std::string problem = "We cannot move this stack to its destination " + curStack->type->namePl;
std::string problem = "We cannot move this stack to its destination " + curStack->getCreature()->namePl;
tlog3 << problem << std::endl;
complain(problem);
ok = false;