1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-06-15 00:05:02 +02:00

Refactored player-specific data into single struct BattleState.

This commit is contained in:
Michał W. Urbańczyk
2013-07-21 22:01:29 +00:00
parent 491bd557ef
commit d8a27d8f3c
13 changed files with 212 additions and 137 deletions

View File

@ -428,8 +428,8 @@ void CGameHandler::endBattle(int3 tile, const CGHeroInstance *hero1, const CGHer
if (hero2)
battleResult.data->exp[1] = hero2->calculateXp(battleResult.data->exp[1]);
const CArmedInstance *bEndArmy1 = gs->curB->belligerents[0];
const CArmedInstance *bEndArmy2 = gs->curB->belligerents[1];
const CArmedInstance *bEndArmy1 = gs->curB->sides[0].armyObject;
const CArmedInstance *bEndArmy2 = gs->curB->sides[1].armyObject;
const BattleResult::EResult result = battleResult.get()->result;
auto findBattleQuery = [this] () -> shared_ptr<CBattleQuery>
@ -452,8 +452,8 @@ void CGameHandler::endBattle(int3 tile, const CGHeroInstance *hero1, const CGHer
battleQuery = make_shared<CBattleQuery>(gs->curB);
}
}
if(battleQuery != queries.topQuery(gs->curB->sides[0]))
complain("Player " + boost::lexical_cast<std::string>(gs->curB->sides[0]) + " although in battle has no battle query at the top!");
if(battleQuery != queries.topQuery(gs->curB->sides[0].color))
complain("Player " + boost::lexical_cast<std::string>(gs->curB->sides[0].color) + " although in battle has no battle query at the top!");
battleQuery->result = *battleResult.data;
@ -480,7 +480,7 @@ void CGameHandler::endBattle(int3 tile, const CGHeroInstance *hero1, const CGHer
{
int maxLevel = eagleEyeLevel + 1;
double eagleEyeChance = finishingBattle->winnerHero->valOfBonuses(Bonus::SECONDARY_SKILL_PREMY, SecondarySkill::EAGLE_EYE);
for(const CSpell *sp : gs->curB->usedSpellsHistory[!battleResult.data->winner])
for(const CSpell *sp : gs->curB->sides[!battleResult.data->winner].usedSpellsHistory)
if(sp->level <= maxLevel && !vstd::contains(finishingBattle->winnerHero->spells, sp->id) && rand() % 100 < eagleEyeChance)
cs.spells.insert(sp->id);
}
@ -534,7 +534,7 @@ void CGameHandler::endBattle(int3 tile, const CGHeroInstance *hero1, const CGHer
}
}
}
for (auto armySlot : gs->curB->belligerents[!battleResult.data->winner]->stacks)
for (auto armySlot : gs->curB->battleGetArmyObject(!battleResult.data->winner)->stacks)
{
auto artifactsWorn = armySlot.second->artifactsWorn;
for (auto artSlot : artifactsWorn)
@ -647,7 +647,7 @@ void CGameHandler::battleAfterLevelUp( const BattleResult &result )
logGlobal->traceStream() << "Decremented queries count to " << finishingBattle->remainingBattleQueriesCount;
if(finishingBattle->remainingBattleQueriesCount > 0)
//Battle results will be hndled when all battle queries are closed
//Battle results will be handled when all battle queries are closed
return;
//TODO consider if we really want it to work like above. ATM each player as unblocked as soon as possible
@ -657,7 +657,7 @@ void CGameHandler::battleAfterLevelUp( const BattleResult &result )
// Necromancy if applicable.
const CStackBasicDescriptor raisedStack = finishingBattle->winnerHero ? finishingBattle->winnerHero->calculateNecromancy(*battleResult.data) : CStackBasicDescriptor();
// Give raised units to winner and show dialog, if any were raised,
// units will be given after casualities are taken
// units will be given after casualties are taken
const SlotID necroSlot = raisedStack.type ? finishingBattle->winnerHero->getSlotFor(raisedStack.type) : SlotID();
if (necroSlot != SlotID())
@ -706,12 +706,11 @@ void CGameHandler::prepareAttack(BattleAttack &bat, const CStack *att, const CSt
{
bat.bsa.clear();
bat.stackAttacking = att->ID;
int attackerLuck = att->LuckVal();
const CGHeroInstance * h0 = gs->curB->heroes[0],
* h1 = gs->curB->heroes[1];
const int attackerLuck = att->LuckVal();
auto sideHeroBlocksLuck = [](const SideInBattle &side){ return NBonus::hasOfType(side.hero, Bonus::BLOCK_LUCK); };
if(!(h0 && NBonus::hasOfType(h0, Bonus::BLOCK_LUCK)) &&
!(h1 && NBonus::hasOfType(h1, Bonus::BLOCK_LUCK)))
if(!vstd::contains_if(gs->curB->sides, sideHeroBlocksLuck))
{
if(attackerLuck > 0 && rand()%24 < attackerLuck)
{
@ -3339,7 +3338,7 @@ bool CGameHandler::makeBattleAction( BattleAction &ba )
}
case Battle::RETREAT: //retreat/flee
{
if(!gs->curB->battleCanFlee(gs->curB->sides[ba.side]))
if(!gs->curB->battleCanFlee(gs->curB->sides[ba.side].color))
complain("Cannot retreat!");
else
setBattleResult(BattleResult::ESCAPE, !ba.side); //surrendering side loses
@ -3347,7 +3346,7 @@ bool CGameHandler::makeBattleAction( BattleAction &ba )
}
case Battle::SURRENDER:
{
PlayerColor player = gs->curB->sides[ba.side];
PlayerColor player = gs->curB->sides[ba.side].color;
int cost = gs->curB->battleGetSurrenderCost(player);
if(cost < 0)
complain("Cannot surrender!");
@ -3477,7 +3476,7 @@ bool CGameHandler::makeBattleAction( BattleAction &ba )
//second shot for ballista, only if hero has advanced artillery
const CGHeroInstance * attackingHero = gs->curB->heroes[ba.side];
const CGHeroInstance * attackingHero = gs->curB->battleGetFightingHero(ba.side);
if( destStack->alive()
&& (stack->getCreature()->idNumber == CreatureID::BALLISTA)
@ -3516,7 +3515,7 @@ bool CGameHandler::makeBattleAction( BattleAction &ba )
{
StartAction start_action(ba);
sendAndApply(&start_action);
const CGHeroInstance * attackingHero = gs->curB->heroes[ba.side];
const CGHeroInstance * attackingHero = gs->curB->battleGetFightingHero(ba.side);
CHeroHandler::SBallisticsLevelInfo sbi = VLC->heroh->ballistics[attackingHero->getSecSkillLevel(SecondarySkill::BALLISTICS)];
EWallParts::EWallParts attackedPart = gs->curB->battleHexToWallPart(ba.destinationTile);
@ -3620,7 +3619,7 @@ bool CGameHandler::makeBattleAction( BattleAction &ba )
{
StartAction start_action(ba);
sendAndApply(&start_action);
const CGHeroInstance * attackingHero = gs->curB->heroes[ba.side];
const CGHeroInstance * attackingHero = gs->curB->battleGetFightingHero(ba.side);
const CStack *healer = gs->curB->battleGetStackByID(ba.stackNumber),
*destStack = gs->curB->battleGetStackByPos(ba.destinationTile);
@ -4385,7 +4384,7 @@ void CGameHandler::handleSpellCasting( SpellID spellID, int spellLvl, BattleHex
std::vector<CStack *> & battleStacks = gs->curB->stacks;
for (auto & battleStack : battleStacks)
{
if(battleStack->owner == gs->curB->sides[casterSide]) //get enemy stacks which can be affected by this spell
if(battleStack->owner == gs->curB->sides[casterSide].color) //get enemy stacks which can be affected by this spell
{
if (!gs->curB->battleIsImmune(nullptr, spell, ECastingMode::MAGIC_MIRROR, battleStack->position))
mirrorTargets.push_back(battleStack);
@ -4410,8 +4409,8 @@ bool CGameHandler::makeCustomAction( BattleAction &ba )
COMPLAIN_RET_FALSE_IF(ba.side > 1, "Side must be 0 or 1!");
const CGHeroInstance *h = gs->curB->heroes[ba.side];
const CGHeroInstance *secondHero = gs->curB->heroes[!ba.side];
const CGHeroInstance *h = gs->curB->battleGetFightingHero(ba.side);
const CGHeroInstance *secondHero = gs->curB->battleGetFightingHero(!ba.side);
if(!h)
{
logGlobal->warnStream() << "Wrong caster!";
@ -4534,10 +4533,11 @@ void CGameHandler::stackTurnTrigger(const CStack * st)
if (st->hasBonusOfType(Bonus::MANA_DRAIN) && !vstd::contains(st->state, EBattleStackState::DRAINED_MANA))
{
const CGHeroInstance * enemy = gs->curB->getHero(gs->curB->theOtherPlayer(st->owner));
const CGHeroInstance * owner = gs->curB->getHero(st->owner);
if (enemy)
{
ui32 manaDrained = st->valOfBonuses(Bonus::MANA_DRAIN);
vstd::amin (manaDrained, gs->curB->heroes[0]->mana);
vstd::amin(manaDrained, gs->curB->battleGetFightingHero(0)->mana);
if (manaDrained)
{
bte.effect = Bonus::MANA_DRAIN;
@ -4569,7 +4569,7 @@ void CGameHandler::stackTurnTrigger(const CStack * st)
}
BonusList bl = *(st->getBonuses(Selector::type(Bonus::ENCHANTER)));
int side = gs->curB->whatSide(st->owner);
if (bl.size() && st->casts && !gs->curB->enchanterCounter[side])
if (bl.size() && st->casts && !gs->curB->sides[side].enchanterCounter)
{
int index = rand() % bl.size();
SpellID spellID = SpellID(bl[index]->subtype);
@ -4624,7 +4624,7 @@ void CGameHandler::handleDamageFromObstacle(const CObstacleInstance &obstacle, c
//helper info
const SpellCreatedObstacle *spellObstacle = dynamic_cast<const SpellCreatedObstacle*>(&obstacle); //not nice but we may need spell params
const ui8 side = curStack->attackerOwned; //if enemy is defending (false = 0), side of our hero is also 0 (attacker)
const CGHeroInstance *hero = gs->curB->heroes[side];
const CGHeroInstance *hero = gs->curB->battleGetFightingHero(side);
if(obstacle.obstacleType == CObstacleInstance::MOAT)
{
@ -5819,14 +5819,15 @@ void CGameHandler::runBattle()
}
//spells opening battle
for(int i=0; i<ARRAY_COUNT(gs->curB->heroes); ++i)
for(int i = 0; i < 2; ++i)
{
if(gs->curB->heroes[i] && gs->curB->heroes[i]->hasBonusOfType(Bonus::OPENING_BATTLE_SPELL))
auto h = gs->curB->battleGetFightingHero(i);
if(h && h->hasBonusOfType(Bonus::OPENING_BATTLE_SPELL))
{
TBonusListPtr bl = gs->curB->heroes[i]->getBonuses(Selector::type(Bonus::OPENING_BATTLE_SPELL));
TBonusListPtr bl = h->getBonuses(Selector::type(Bonus::OPENING_BATTLE_SPELL));
for (Bonus *b : *bl)
{
handleSpellCasting(SpellID(b->subtype), 3, -1, 0, gs->curB->heroes[i]->tempOwner, nullptr, gs->curB->heroes[1-i], b->val, ECastingMode::HERO_CASTING, nullptr);
handleSpellCasting(SpellID(b->subtype), 3, -1, 0, h->tempOwner, nullptr, gs->curB->battleGetFightingHero(1-i), b->val, ECastingMode::HERO_CASTING, nullptr);
}
}
}
@ -5853,7 +5854,8 @@ void CGameHandler::runBattle()
//check for bad morale => freeze
int nextStackMorale = next->MoraleVal();
if( nextStackMorale < 0 &&
!(NBonus::hasOfType(gs->curB->heroes[0], Bonus::BLOCK_MORALE) || NBonus::hasOfType(gs->curB->heroes[1], Bonus::BLOCK_MORALE)) //checking if gs->curB->heroes have (or don't have) morale blocking bonuses)
!(NBonus::hasOfType(gs->curB->battleGetFightingHero(0), Bonus::BLOCK_MORALE)
|| NBonus::hasOfType(gs->curB->battleGetFightingHero(1), Bonus::BLOCK_MORALE)) //checking if gs->curB->heroes have (or don't have) morale blocking bonuses)
)
{
if( rand()%24 < -2 * nextStackMorale)
@ -6005,7 +6007,8 @@ void CGameHandler::runBattle()
&& !vstd::contains(next->state, EBattleStackState::FEAR)
&& next->alive()
&& nextStackMorale > 0
&& !(NBonus::hasOfType(gs->curB->heroes[0], Bonus::BLOCK_MORALE) || NBonus::hasOfType(gs->curB->heroes[1], Bonus::BLOCK_MORALE)) //checking if gs->curB->heroes have (or don't have) morale blocking bonuses
&& !(NBonus::hasOfType(gs->curB->battleGetFightingHero(0), Bonus::BLOCK_MORALE)
|| NBonus::hasOfType(gs->curB->battleGetFightingHero(1), Bonus::BLOCK_MORALE)) //checking if gs->curB->heroes have (or don't have) morale blocking bonuses
)
{
if(rand()%24 < nextStackMorale) //this stack hasn't got morale this turn
@ -6033,7 +6036,7 @@ void CGameHandler::runBattle()
}
}
endBattle(gs->curB->tile, gs->curB->heroes[0], gs->curB->heroes[1]);
endBattle(gs->curB->tile, gs->curB->battleGetFightingHero(0), gs->curB->battleGetFightingHero(1));
}
bool CGameHandler::makeAutomaticAction(const CStack *stack, BattleAction &ba)
@ -6210,7 +6213,7 @@ bool CGameHandler::isVisitCoveredByAnotherQuery(const CGObjectInstance *obj, con
void CGameHandler::duelFinished()
{
auto si = getStartInfo();
auto getName = [&](int i){ return si->getIthPlayersSettings(gs->curB->sides[i]).name; };
auto getName = [&](int i){ return si->getIthPlayersSettings(gs->curB->sides[i].color).name; };
int casualtiesPoints = 0;
logGlobal->debugStream() << boost::format("Winner side %d\nWinner casualties:")
@ -6310,10 +6313,10 @@ CGameHandler::FinishingBattleHelper::FinishingBattleHelper(shared_ptr<const CBat
auto &result = *Query->result;
auto &info = *Query->bi;
winnerHero = result.winner != 0 ? info.heroes[1] : info.heroes[0];
loserHero = result.winner != 0 ? info.heroes[0] : info.heroes[1];
victor = info.sides[result.winner];
loser = info.sides[!result.winner];
winnerHero = result.winner != 0 ? info.sides[1].hero : info.sides[0].hero;
loserHero = result.winner != 0 ? info.sides[0].hero : info.sides[1].hero;
victor = info.sides[result.winner].color;
loser = info.sides[!result.winner].color;
duel = Duel;
remainingBattleQueriesCount = RemainingBattleQueriesCount;
}