diff --git a/AI/GeniusAI/BattleLogic.cpp b/AI/GeniusAI/BattleLogic.cpp index 2b4583ad5..7636a683d 100644 --- a/AI/GeniusAI/BattleLogic.cpp +++ b/AI/GeniusAI/BattleLogic.cpp @@ -138,7 +138,7 @@ void CBattleLogic::MakeStatistics(int currentCreatureId) m_statHitPoints.push_back(std::pair(id, hitPoints)); m_statMaxSpeed.push_back(std::pair(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(id, cs)); - if (st->type->isShooting() && st->shots > 0) + if (st->getCreature()->isShooting() && st->shots > 0) { m_statDistanceFromShooters.push_back(std::pair(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(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(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 { diff --git a/CCallback.cpp b/CCallback.cpp index 69a5d9261..c2ae72573 100644 --- a/CCallback.cpp +++ b/CCallback.cpp @@ -578,7 +578,7 @@ CCreature CCallback::battleGetCreature(int number) for(size_t h=0; hcurB->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"); diff --git a/client/CBattleInterface.cpp b/client/CBattleInterface.cpp index 1b1704554..ff6ed09d2 100644 --- a/client/CBattleInterface.cpp +++ b/client/CBattleInterface.cpp @@ -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::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::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; ssecond.type->idNumber]->ourImages.size(); ++s) //alpha transforming + for(int s=0; ssecond.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); diff --git a/client/CPlayerInterface.cpp b/client/CPlayerInterface.cpp index 4fe252d14..70f99c3d2 100644 --- a/client/CPlayerInterface.cpp +++ b/client/CPlayerInterface.cpp @@ -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); } diff --git a/lib/CCreatureSet.cpp b/lib/CCreatureSet.cpp index a60803a47..db5801ea0 100644 --- a/lib/CCreatureSet.cpp +++ b/lib/CCreatureSet.cpp @@ -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(); diff --git a/lib/CCreatureSet.h b/lib/CCreatureSet.h index 0aebcbedb..7b893fc4d 100644 --- a/lib/CCreatureSet.h +++ b/lib/CCreatureSet.h @@ -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 &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 diff --git a/lib/CGameState.cpp b/lib/CGameState.cpp index 16565e16d..ec9fa150f 100644 --- a/lib/CGameState.cpp +++ b/lib/CGameState.cpp @@ -687,19 +687,24 @@ std::pair< std::vector, 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 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 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 BattleInfo::calculateDmgRange( const CStack* attacker, con for(unsigned int g=0; gtype->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 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 *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 BattleInfo::getAttackedCreatures( const CSpell * s, int skillL { for(int it=0; itid == 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 &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 { diff --git a/lib/CGameState.h b/lib/CGameState.h index c54738804..eaa5aa980 100644 --- a/lib/CGameState.h +++ b/lib/CGameState.h @@ -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 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 void serialize(Handler &h, const int version) { - h & static_cast(*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 { diff --git a/lib/HeroBonus.cpp b/lib/HeroBonus.cpp index 71372fe3b..a6092fd7a 100644 --- a/lib/HeroBonus.cpp +++ b/lib/HeroBonus.cpp @@ -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) diff --git a/lib/HeroBonus.h b/lib/HeroBonus.h index ad9c3c162..752484168 100644 --- a/lib/HeroBonus.h +++ b/lib/HeroBonus.h @@ -30,6 +30,7 @@ class IPropagator; typedef std::vector > TModDescr; //modifiers values and their descriptions typedef std::set TNodes; typedef std::set TCNodes; +typedef std::vector TNodesVector; typedef boost::function CSelector; namespace PrimarySkill @@ -361,7 +362,7 @@ public: BonusList bonuses; //wielded bonuses (local and up-propagated here) BonusList exportedBonuses; - std::vector 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 }; }; diff --git a/lib/NetPacksLib.cpp b/lib/NetPacksLib.cpp index 27ea95b05..34d1c61c1 100644 --- a/lib/NetPacksLib.cpp +++ b/lib/NetPacksLib.cpp @@ -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; diff --git a/server/CGameHandler.cpp b/server/CGameHandler.cpp index aa5689e31..87ccb856c 100644 --- a/server/CGameHandler.cpp +++ b/server/CGameHandler.cpp @@ -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;