mirror of
https://github.com/vcmi/vcmi.git
synced 2024-12-28 23:06:24 +02:00
CStack refactoring
* removed all occurrences of attackerOwned * Use BattleSide enum * more tweaks
This commit is contained in:
parent
29e50cc21c
commit
4f8c7bd4bb
@ -24,7 +24,7 @@ struct CurrentOffensivePotential
|
||||
{
|
||||
for(auto stack : cbc->battleGetStacks())
|
||||
{
|
||||
if(stack->attackerOwned == !side)
|
||||
if(stack->side == side)
|
||||
ourAttacks[stack] = PotentialTargets(stack);
|
||||
else
|
||||
enemyAttacks[stack] = PotentialTargets(stack);
|
||||
|
@ -18,7 +18,7 @@ PotentialTargets::PotentialTargets(const CStack *attacker, const HypotheticChang
|
||||
for(const CStack *enemy : getCbc()->battleGetStacks())
|
||||
{
|
||||
//Consider only stacks of different owner
|
||||
if(enemy->attackerOwned == attacker->attackerOwned)
|
||||
if(enemy->side == attacker->side)
|
||||
continue;
|
||||
|
||||
auto GenerateAttackInfo = [&](bool shooting, BattleHex hex) -> AttackPossibility
|
||||
|
@ -31,7 +31,7 @@ ThreatMap::ThreatMap(const CStack *Endangered) : endangered(Endangered)
|
||||
for(const CStack *enemy : getCbc()->battleGetStacks())
|
||||
{
|
||||
//Consider only stacks of different owner
|
||||
if(enemy->attackerOwned == endangered->attackerOwned)
|
||||
if(enemy->side == endangered->side)
|
||||
continue;
|
||||
|
||||
//Look-up which tiles can be melee-attacked
|
||||
|
@ -855,7 +855,7 @@ void CClient::commenceTacticPhaseForInt(std::shared_ptr<CBattleGameInterface> ba
|
||||
battleInt->yourTacticPhase(gs->curB->tacticDistance);
|
||||
if(gs && !!gs->curB && gs->curB->tacticDistance) //while awaiting for end of tactics phase, many things can happen (end of battle... or game)
|
||||
{
|
||||
MakeAction ma(BattleAction::makeEndOFTacticPhase(gs->curB->playerToSide(battleInt->playerID)));
|
||||
MakeAction ma(BattleAction::makeEndOFTacticPhase(gs->curB->playerToSide(battleInt->playerID).get()));
|
||||
sendRequest(&ma, battleInt->playerID);
|
||||
}
|
||||
}
|
||||
|
@ -338,7 +338,7 @@ bool CMeleeAttackAnimation::init()
|
||||
static const CCreatureAnim::EAnimType mutPosToGroup[] = {CCreatureAnim::ATTACK_UP, CCreatureAnim::ATTACK_UP,
|
||||
CCreatureAnim::ATTACK_FRONT, CCreatureAnim::ATTACK_DOWN, CCreatureAnim::ATTACK_DOWN, CCreatureAnim::ATTACK_FRONT};
|
||||
|
||||
int revShiftattacker = (attackingStack->attackerOwned ? -1 : 1);
|
||||
int revShiftattacker = (attackingStack->side == BattleSide::ATTACKER ? -1 : 1);
|
||||
|
||||
int mutPos = BattleHex::mutualPosition(attackingStackPosBeforeReturn, dest);
|
||||
if(mutPos == -1 && attackingStack->doubleWide())
|
||||
@ -988,7 +988,7 @@ bool CSpellEffectAnimation::init()
|
||||
|
||||
// Correction for 2-hex creatures.
|
||||
if (destStack != nullptr && destStack->doubleWide())
|
||||
be.x += (destStack->attackerOwned ? -1 : 1)*tilePos.w/2;
|
||||
be.x += (destStack->side == BattleSide::ATTACKER ? -1 : 1)*tilePos.w/2;
|
||||
|
||||
//Indicate if effect should be drawn on top of everything or just on top of the hex
|
||||
be.position = destTile;
|
||||
|
@ -949,7 +949,7 @@ void CBattleInterface::bConsoleDownf()
|
||||
|
||||
void CBattleInterface::newStack(const CStack *stack)
|
||||
{
|
||||
creDir[stack->ID] = stack->attackerOwned; // must be set before getting stack position
|
||||
creDir[stack->ID] = stack->side == BattleSide::ATTACKER; // must be set before getting stack position
|
||||
|
||||
Point coords = CClickableHex::getXYUnitAnim(stack->position, stack, this);
|
||||
|
||||
@ -1180,15 +1180,15 @@ bool CBattleInterface::isCatapultAttackable(BattleHex hex) const
|
||||
return state != EWallState::DESTROYED && state != EWallState::NONE;
|
||||
}
|
||||
|
||||
const CGHeroInstance *CBattleInterface::getActiveHero()
|
||||
const CGHeroInstance * CBattleInterface::getActiveHero()
|
||||
{
|
||||
const CStack *attacker = activeStack;
|
||||
if (!attacker)
|
||||
if(!attacker)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (attacker->attackerOwned)
|
||||
if(attacker->side == BattleSide::ATTACKER)
|
||||
{
|
||||
return attackingHeroInstance;
|
||||
}
|
||||
@ -1801,7 +1801,7 @@ void CBattleInterface::endAction(const BattleAction* action)
|
||||
|
||||
for (const CStack *s : stacks)
|
||||
{
|
||||
if (s && creDir[s->ID] != bool(s->attackerOwned) && s->alive()
|
||||
if (s && creDir[s->ID] != (s->side == BattleSide::ATTACKER) && s->alive()
|
||||
&& creAnims[s->ID]->isIdle())
|
||||
{
|
||||
addNewAnim(new CReverseAnimation(this, s, s->position, false));
|
||||
@ -2033,10 +2033,10 @@ std::string formatDmgRange(std::pair<ui32, ui32> dmgRange)
|
||||
return (boost::format("%d") % dmgRange.first).str();
|
||||
}
|
||||
|
||||
bool CBattleInterface::canStackMoveHere (const CStack *activeStack, BattleHex myNumber)
|
||||
bool CBattleInterface::canStackMoveHere(const CStack * activeStack, BattleHex myNumber)
|
||||
{
|
||||
std::vector<BattleHex> acc = curInt->cb->battleGetAvailableHexes (activeStack, false);
|
||||
int shiftedDest = myNumber + (activeStack->attackerOwned ? 1 : -1);
|
||||
BattleHex shiftedDest = myNumber + activeStack->destShiftDir();
|
||||
|
||||
if (vstd::contains(acc, myNumber))
|
||||
return true;
|
||||
@ -2262,14 +2262,14 @@ void CBattleInterface::handleHex(BattleHex myNumber, int eventType)
|
||||
|
||||
realizeAction = [=]
|
||||
{
|
||||
if (activeStack->doubleWide())
|
||||
if(activeStack->doubleWide())
|
||||
{
|
||||
std::vector<BattleHex> acc = curInt->cb->battleGetAvailableHexes(activeStack, false);
|
||||
int shiftedDest = myNumber + (activeStack->attackerOwned ? 1 : -1);
|
||||
if (vstd::contains(acc, myNumber))
|
||||
giveCommand (Battle::WALK ,myNumber, activeStack->ID);
|
||||
else if (vstd::contains(acc, shiftedDest))
|
||||
giveCommand (Battle::WALK, shiftedDest, activeStack->ID);
|
||||
BattleHex shiftedDest = myNumber + activeStack->destShiftDir();
|
||||
if(vstd::contains(acc, myNumber))
|
||||
giveCommand(Battle::WALK, myNumber, activeStack->ID);
|
||||
else if(vstd::contains(acc, shiftedDest))
|
||||
giveCommand(Battle::WALK, shiftedDest, activeStack->ID);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -2547,17 +2547,17 @@ BattleHex CBattleInterface::fromWhichHexAttack(BattleHex myNumber)
|
||||
{
|
||||
bool doubleWide = activeStack->doubleWide();
|
||||
destHex = myNumber + ( (myNumber/GameConstants::BFIELD_WIDTH)%2 ? GameConstants::BFIELD_WIDTH : GameConstants::BFIELD_WIDTH+1 ) +
|
||||
(activeStack->attackerOwned && doubleWide ? 1 : 0);
|
||||
if (vstd::contains(occupyableHexes, destHex))
|
||||
(activeStack->side == BattleSide::ATTACKER && doubleWide ? 1 : 0);
|
||||
if(vstd::contains(occupyableHexes, destHex))
|
||||
return destHex;
|
||||
else if (activeStack->attackerOwned) //if we are attacker
|
||||
else if(activeStack->side == BattleSide::ATTACKER)
|
||||
{
|
||||
if (vstd::contains(occupyableHexes, destHex+1))
|
||||
return destHex+1;
|
||||
}
|
||||
else //if we are defender
|
||||
{
|
||||
if (vstd::contains(occupyableHexes, destHex-1))
|
||||
if(vstd::contains(occupyableHexes, destHex-1))
|
||||
return destHex-1;
|
||||
}
|
||||
break;
|
||||
@ -2567,21 +2567,21 @@ BattleHex CBattleInterface::fromWhichHexAttack(BattleHex myNumber)
|
||||
destHex = myNumber + ( (myNumber/GameConstants::BFIELD_WIDTH)%2 ? GameConstants::BFIELD_WIDTH-1 : GameConstants::BFIELD_WIDTH );
|
||||
if (vstd::contains(occupyableHexes, destHex))
|
||||
return destHex;
|
||||
else if (activeStack->attackerOwned) //if we are attacker
|
||||
else if(activeStack->side == BattleSide::ATTACKER)
|
||||
{
|
||||
if (vstd::contains(occupyableHexes, destHex+1))
|
||||
if(vstd::contains(occupyableHexes, destHex+1))
|
||||
return destHex+1;
|
||||
}
|
||||
else //if we are defender
|
||||
else //we are defender
|
||||
{
|
||||
if (vstd::contains(occupyableHexes, destHex-1))
|
||||
if(vstd::contains(occupyableHexes, destHex-1))
|
||||
return destHex-1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 8: //from left
|
||||
{
|
||||
if (activeStack->doubleWide() && !activeStack->attackerOwned)
|
||||
if(activeStack->doubleWide() && activeStack->side == activeStack->side == BattleSide::DEFENDER)
|
||||
{
|
||||
std::vector<BattleHex> acc = curInt->cb->battleGetAvailableHexes(activeStack, false);
|
||||
if (vstd::contains(acc, myNumber))
|
||||
@ -2597,17 +2597,17 @@ BattleHex CBattleInterface::fromWhichHexAttack(BattleHex myNumber)
|
||||
}
|
||||
case 9: //from top left
|
||||
{
|
||||
destHex = myNumber - ( (myNumber/GameConstants::BFIELD_WIDTH)%2 ? GameConstants::BFIELD_WIDTH+1 : GameConstants::BFIELD_WIDTH );
|
||||
if (vstd::contains(occupyableHexes, destHex))
|
||||
destHex = myNumber - ((myNumber/GameConstants::BFIELD_WIDTH) % 2 ? GameConstants::BFIELD_WIDTH + 1 : GameConstants::BFIELD_WIDTH);
|
||||
if(vstd::contains(occupyableHexes, destHex))
|
||||
return destHex;
|
||||
else if (activeStack->attackerOwned) //if we are attacker
|
||||
else if(activeStack->side == BattleSide::ATTACKER)
|
||||
{
|
||||
if (vstd::contains(occupyableHexes, destHex+1))
|
||||
if(vstd::contains(occupyableHexes, destHex+1))
|
||||
return destHex+1;
|
||||
}
|
||||
else //if we are defender
|
||||
{
|
||||
if (vstd::contains(occupyableHexes, destHex-1))
|
||||
if(vstd::contains(occupyableHexes, destHex-1))
|
||||
return destHex-1;
|
||||
}
|
||||
break;
|
||||
@ -2616,27 +2616,27 @@ BattleHex CBattleInterface::fromWhichHexAttack(BattleHex myNumber)
|
||||
{
|
||||
bool doubleWide = activeStack->doubleWide();
|
||||
destHex = myNumber - ( (myNumber/GameConstants::BFIELD_WIDTH)%2 ? GameConstants::BFIELD_WIDTH : GameConstants::BFIELD_WIDTH-1 ) +
|
||||
(activeStack->attackerOwned && doubleWide ? 1 : 0);
|
||||
if (vstd::contains(occupyableHexes, destHex))
|
||||
(activeStack->side == BattleSide::ATTACKER && doubleWide ? 1 : 0);
|
||||
if(vstd::contains(occupyableHexes, destHex))
|
||||
return destHex;
|
||||
else if (activeStack->attackerOwned) //if we are attacker
|
||||
else if(activeStack->side == BattleSide::ATTACKER)
|
||||
{
|
||||
if (vstd::contains(occupyableHexes, destHex+1))
|
||||
if(vstd::contains(occupyableHexes, destHex+1))
|
||||
return destHex+1;
|
||||
}
|
||||
else //if we are defender
|
||||
{
|
||||
if (vstd::contains(occupyableHexes, destHex-1))
|
||||
if(vstd::contains(occupyableHexes, destHex-1))
|
||||
return destHex-1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 11: //from right
|
||||
{
|
||||
if (activeStack->doubleWide() && activeStack->attackerOwned)
|
||||
if(activeStack->doubleWide() && activeStack->side == BattleSide::ATTACKER)
|
||||
{
|
||||
std::vector<BattleHex> acc = curInt->cb->battleGetAvailableHexes(activeStack, false);
|
||||
if (vstd::contains(acc, myNumber))
|
||||
if(vstd::contains(acc, myNumber))
|
||||
return myNumber + 1;
|
||||
else
|
||||
return myNumber + 2;
|
||||
@ -2650,16 +2650,16 @@ BattleHex CBattleInterface::fromWhichHexAttack(BattleHex myNumber)
|
||||
case 13: //from bottom
|
||||
{
|
||||
destHex = myNumber + ( (myNumber/GameConstants::BFIELD_WIDTH)%2 ? GameConstants::BFIELD_WIDTH : GameConstants::BFIELD_WIDTH+1 );
|
||||
if (vstd::contains(occupyableHexes, destHex))
|
||||
if(vstd::contains(occupyableHexes, destHex))
|
||||
return destHex;
|
||||
else if (attackingHeroInstance->tempOwner == curInt->cb->getMyColor()) //if we are attacker
|
||||
else if(activeStack->side == BattleSide::ATTACKER)
|
||||
{
|
||||
if (vstd::contains(occupyableHexes, destHex+1))
|
||||
if(vstd::contains(occupyableHexes, destHex+1))
|
||||
return destHex+1;
|
||||
}
|
||||
else //if we are defender
|
||||
{
|
||||
if (vstd::contains(occupyableHexes, destHex-1))
|
||||
if(vstd::contains(occupyableHexes, destHex-1))
|
||||
return destHex-1;
|
||||
}
|
||||
break;
|
||||
@ -2669,14 +2669,14 @@ BattleHex CBattleInterface::fromWhichHexAttack(BattleHex myNumber)
|
||||
destHex = myNumber - ( (myNumber/GameConstants::BFIELD_WIDTH)%2 ? GameConstants::BFIELD_WIDTH : GameConstants::BFIELD_WIDTH-1 );
|
||||
if (vstd::contains(occupyableHexes, destHex))
|
||||
return destHex;
|
||||
else if (attackingHeroInstance->tempOwner == curInt->cb->getMyColor()) //if we are attacker
|
||||
else if(activeStack->side == BattleSide::ATTACKER)
|
||||
{
|
||||
if (vstd::contains(occupyableHexes, destHex+1))
|
||||
if(vstd::contains(occupyableHexes, destHex+1))
|
||||
return destHex+1;
|
||||
}
|
||||
else //if we are defender
|
||||
{
|
||||
if (vstd::contains(occupyableHexes, destHex-1))
|
||||
if(vstd::contains(occupyableHexes, destHex-1))
|
||||
return destHex-1;
|
||||
}
|
||||
break;
|
||||
@ -3082,52 +3082,52 @@ void CBattleInterface::showAbsoluteObstacles(SDL_Surface *to)
|
||||
|
||||
void CBattleInterface::showHighlightedHexes(SDL_Surface *to)
|
||||
{
|
||||
for (int b=0; b<GameConstants::BFIELD_SIZE; ++b)
|
||||
for(int b=0; b<GameConstants::BFIELD_SIZE; ++b)
|
||||
{
|
||||
if (bfield[b]->strictHovered && bfield[b]->hovered)
|
||||
if(bfield[b]->strictHovered && bfield[b]->hovered)
|
||||
{
|
||||
if (previouslyHoveredHex == -1)
|
||||
if(previouslyHoveredHex == -1)
|
||||
previouslyHoveredHex = b; //something to start with
|
||||
if (currentlyHoveredHex == -1)
|
||||
if(currentlyHoveredHex == -1)
|
||||
currentlyHoveredHex = b; //something to start with
|
||||
|
||||
if (currentlyHoveredHex != b) //repair hover info
|
||||
if(currentlyHoveredHex != b) //repair hover info
|
||||
{
|
||||
previouslyHoveredHex = currentlyHoveredHex;
|
||||
currentlyHoveredHex = b;
|
||||
}
|
||||
if (settings["battle"]["mouseShadow"].Bool())
|
||||
if(settings["battle"]["mouseShadow"].Bool())
|
||||
{
|
||||
const ISpellCaster *caster = nullptr;
|
||||
const CSpell *spell = nullptr;
|
||||
|
||||
if (spellToCast)//hero casts spell
|
||||
if(spellToCast)//hero casts spell
|
||||
{
|
||||
spell = SpellID(spellToCast->additionalInfo).toSpell();
|
||||
caster = activeStack->attackerOwned ? attackingHeroInstance : defendingHeroInstance;
|
||||
caster = activeStack->side == BattleSide::ATTACKER ? attackingHeroInstance : defendingHeroInstance;
|
||||
}
|
||||
else if (creatureSpellToCast >= 0 && stackCanCastSpell && creatureCasting)//stack casts spell
|
||||
else if(creatureSpellToCast >= 0 && stackCanCastSpell && creatureCasting)//stack casts spell
|
||||
{
|
||||
spell = SpellID(creatureSpellToCast).toSpell();
|
||||
caster = activeStack;
|
||||
}
|
||||
|
||||
if (caster && spell) //when casting spell
|
||||
if(caster && spell) //when casting spell
|
||||
{
|
||||
//calculating spell school level
|
||||
ui8 schoolLevel = caster->getSpellSchoolLevel(spell);
|
||||
|
||||
// printing shaded hex(es)
|
||||
auto shaded = spell->rangeInHexes(currentlyHoveredHex, schoolLevel, curInt->cb->battleGetMySide());
|
||||
for (BattleHex shadedHex : shaded)
|
||||
for(BattleHex shadedHex : shaded)
|
||||
{
|
||||
if ((shadedHex.getX() != 0) && (shadedHex.getX() != GameConstants::BFIELD_WIDTH -1))
|
||||
if((shadedHex.getX() != 0) && (shadedHex.getX() != GameConstants::BFIELD_WIDTH - 1))
|
||||
showHighlightedHex(to, shadedHex);
|
||||
}
|
||||
}
|
||||
else if (active)//always highlight pointed hex
|
||||
else if(active)//always highlight pointed hex
|
||||
{
|
||||
if (currentlyHoveredHex.getX() != 0
|
||||
if(currentlyHoveredHex.getX() != 0
|
||||
&& currentlyHoveredHex.getX() != GameConstants::BFIELD_WIDTH - 1)
|
||||
showHighlightedHex(to, currentlyHoveredHex);
|
||||
}
|
||||
@ -3135,18 +3135,18 @@ void CBattleInterface::showHighlightedHexes(SDL_Surface *to)
|
||||
}
|
||||
}
|
||||
|
||||
if (activeStack && settings["battle"]["stackRange"].Bool())
|
||||
if(activeStack && settings["battle"]["stackRange"].Bool())
|
||||
{
|
||||
std::set<BattleHex> set = curInt->cb->battleGetAttackedHexes(activeStack, currentlyHoveredHex, attackingHex);
|
||||
for (BattleHex hex : set)
|
||||
for(BattleHex hex : set)
|
||||
showHighlightedHex(to, hex);
|
||||
|
||||
// display the movement shadow of the stack at b (i.e. stack under mouse)
|
||||
const CStack *const shere = curInt->cb->battleGetStackByPos(currentlyHoveredHex, false);
|
||||
if (shere && shere != activeStack && shere->alive())
|
||||
const CStack * const shere = curInt->cb->battleGetStackByPos(currentlyHoveredHex, false);
|
||||
if(shere && shere != activeStack && shere->alive())
|
||||
{
|
||||
std::vector<BattleHex> v = curInt->cb->battleGetAvailableHexes(shere, true );
|
||||
for (BattleHex hex : v)
|
||||
for(BattleHex hex : v)
|
||||
showHighlightedHex(to, hex);
|
||||
}
|
||||
}
|
||||
@ -3321,13 +3321,15 @@ void CBattleInterface::showAliveStacks(SDL_Surface *to, std::vector<const CStack
|
||||
//printing amount
|
||||
if (isAmountBoxVisible(stack))
|
||||
{
|
||||
const BattleHex nextPos = stack->position + (stack->attackerOwned ? 1 : -1);
|
||||
const bool edge = stack->position % GameConstants::BFIELD_WIDTH == (stack->attackerOwned ? GameConstants::BFIELD_WIDTH - 2 : 1);
|
||||
const int sideShift = stack->side == BattleSide::ATTACKER ? 1 : -1;
|
||||
const int reverseSideShift = stack->side == BattleSide::ATTACKER ? -1 : 1;
|
||||
const BattleHex nextPos = stack->position + sideShift;
|
||||
const bool edge = stack->position % GameConstants::BFIELD_WIDTH == (stack->side == BattleSide::ATTACKER ? GameConstants::BFIELD_WIDTH - 2 : 1);
|
||||
const bool moveInside = !edge && !stackCountOutsideHexes[nextPos];
|
||||
int xAdd = (stack->attackerOwned ? 220 : 202) +
|
||||
(stack->doubleWide() ? 44 : 0) *(stack->attackerOwned ? +1 : -1) +
|
||||
(moveInside ? amountNormal->w + 10 : 0) *(stack->attackerOwned ? -1 : +1);
|
||||
int yAdd = 260 + ((stack->attackerOwned || moveInside) ? 0 : -15);
|
||||
int xAdd = (stack->side == BattleSide::ATTACKER ? 220 : 202) +
|
||||
(stack->doubleWide() ? 44 : 0) * sideShift +
|
||||
(moveInside ? amountNormal->w + 10 : 0) * reverseSideShift;
|
||||
int yAdd = 260 + ((stack->side == BattleSide::ATTACKER || moveInside) ? 0 : -15);
|
||||
|
||||
//blitting amount background box
|
||||
SDL_Surface *amountBG = amountNormal;
|
||||
|
@ -384,7 +384,7 @@ CBattleResultWindow::CBattleResultWindow(const BattleResult &br, const SDL_Rect
|
||||
{
|
||||
auto stacks = owner.cb->battleGetAllStacks();
|
||||
vstd::erase_if(stacks, [i](const CStack *stack) //erase stack of other side and not coming from garrison
|
||||
{ return stack->attackerOwned == i || !stack->base; });
|
||||
{ return stack->side != i || !stack->base; });
|
||||
|
||||
auto best = vstd::maxElementByFun(stacks, [](const CStack *stack){ return stack->type->AIValue; });
|
||||
if(best != stacks.end()) //should be always but to be safe...
|
||||
@ -548,7 +548,7 @@ Point CClickableHex::getXYUnitAnim(BattleHex hexNum, const CStack * stack, CBatt
|
||||
//shifting position for double - hex creatures
|
||||
if(stack->doubleWide())
|
||||
{
|
||||
if(stack->attackerOwned)
|
||||
if(stack->side == BattleSide::ATTACKER)
|
||||
{
|
||||
if(cbi->creDir[stack->ID])
|
||||
ret.x -= 44;
|
||||
|
@ -15,8 +15,8 @@
|
||||
#include "NetPacks.h"
|
||||
|
||||
|
||||
CStack::CStack(const CStackInstance *Base, PlayerColor O, int I, bool AO, SlotID S)
|
||||
: base(Base), ID(I), owner(O), slot(S), attackerOwned(AO),
|
||||
CStack::CStack(const CStackInstance *Base, PlayerColor O, int I, ui8 Side, SlotID S)
|
||||
: base(Base), ID(I), owner(O), slot(S), side(Side),
|
||||
counterAttacksPerformed(0),counterAttacksTotalCache(0), cloneID(-1),
|
||||
firstHPleft(-1), position(), shots(0), casts(0), resurrected(0)
|
||||
{
|
||||
@ -30,8 +30,8 @@ CStack::CStack()
|
||||
init();
|
||||
setNodeType(STACK_BATTLE);
|
||||
}
|
||||
CStack::CStack(const CStackBasicDescriptor *stack, PlayerColor O, int I, bool AO, SlotID S)
|
||||
: base(nullptr), ID(I), owner(O), slot(S), attackerOwned(AO),
|
||||
CStack::CStack(const CStackBasicDescriptor *stack, PlayerColor O, int I, ui8 Side, SlotID S)
|
||||
: base(nullptr), ID(I), owner(O), slot(S), side(Side),
|
||||
counterAttacksPerformed(0), counterAttacksTotalCache(0), cloneID(-1),
|
||||
firstHPleft(-1), position(), shots(0), casts(0), resurrected(0)
|
||||
{
|
||||
@ -49,7 +49,7 @@ void CStack::init()
|
||||
firstHPleft = -1;
|
||||
owner = PlayerColor::NEUTRAL;
|
||||
slot = SlotID(255);
|
||||
attackerOwned = false;
|
||||
side = 1;
|
||||
position = BattleHex();
|
||||
counterAttacksPerformed = 0;
|
||||
counterAttacksTotalCache = 0;
|
||||
@ -145,9 +145,9 @@ BattleHex CStack::occupiedHex() const
|
||||
|
||||
BattleHex CStack::occupiedHex(BattleHex assumedPos) const
|
||||
{
|
||||
if (doubleWide())
|
||||
if(doubleWide())
|
||||
{
|
||||
if (attackerOwned)
|
||||
if(side == BattleSide::ATTACKER)
|
||||
return assumedPos - 1;
|
||||
else
|
||||
return assumedPos + 1;
|
||||
@ -165,17 +165,17 @@ std::vector<BattleHex> CStack::getHexes() const
|
||||
|
||||
std::vector<BattleHex> CStack::getHexes(BattleHex assumedPos) const
|
||||
{
|
||||
return getHexes(assumedPos, doubleWide(), attackerOwned);
|
||||
return getHexes(assumedPos, doubleWide(), side);
|
||||
}
|
||||
|
||||
std::vector<BattleHex> CStack::getHexes(BattleHex assumedPos, bool twoHex, bool AttackerOwned)
|
||||
std::vector<BattleHex> CStack::getHexes(BattleHex assumedPos, bool twoHex, ui8 side)
|
||||
{
|
||||
std::vector<BattleHex> hexes;
|
||||
hexes.push_back(assumedPos);
|
||||
|
||||
if (twoHex)
|
||||
if(twoHex)
|
||||
{
|
||||
if (AttackerOwned)
|
||||
if(side == BattleSide::ATTACKER)
|
||||
hexes.push_back(assumedPos - 1);
|
||||
else
|
||||
hexes.push_back(assumedPos + 1);
|
||||
@ -193,10 +193,10 @@ std::vector<BattleHex> CStack::getSurroundingHexes(BattleHex attackerPos) const
|
||||
{
|
||||
BattleHex hex = (attackerPos != BattleHex::INVALID) ? attackerPos : position; //use hypothetical position
|
||||
std::vector<BattleHex> hexes;
|
||||
if (doubleWide())
|
||||
if(doubleWide())
|
||||
{
|
||||
const int WN = GameConstants::BFIELD_WIDTH;
|
||||
if(attackerOwned)
|
||||
if(side == BattleSide::ATTACKER)
|
||||
{ //position is equal to front hex
|
||||
BattleHex::checkAndPush(hex - ( (hex/WN)%2 ? WN+2 : WN+1 ), hexes);
|
||||
BattleHex::checkAndPush(hex - ( (hex/WN)%2 ? WN+1 : WN ), hexes);
|
||||
@ -226,6 +226,21 @@ std::vector<BattleHex> CStack::getSurroundingHexes(BattleHex attackerPos) const
|
||||
}
|
||||
}
|
||||
|
||||
BattleHex::EDir CStack::destShiftDir() const
|
||||
{
|
||||
if(doubleWide())
|
||||
{
|
||||
if(side == BattleSide::ATTACKER)
|
||||
return BattleHex::EDir::RIGHT;
|
||||
else
|
||||
return BattleHex::EDir::LEFT;
|
||||
}
|
||||
else
|
||||
{
|
||||
return BattleHex::EDir::NONE;
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<si32> CStack::activeSpells() const
|
||||
{
|
||||
std::vector<si32> ret;
|
||||
@ -382,11 +397,11 @@ bool CStack::isMeleeAttackPossible(const CStack * attacker, const CStack * defen
|
||||
return
|
||||
(BattleHex::mutualPosition(attackerPos, defenderPos) >= 0) //front <=> front
|
||||
|| (attacker->doubleWide() //back <=> front
|
||||
&& BattleHex::mutualPosition(attackerPos + (attacker->attackerOwned ? -1 : 1), defenderPos) >= 0)
|
||||
&& BattleHex::mutualPosition(attackerPos + (attacker->side == BattleSide::ATTACKER ? -1 : 1), defenderPos) >= 0)
|
||||
|| (defender->doubleWide() //front <=> back
|
||||
&& BattleHex::mutualPosition(attackerPos, defenderPos + (defender->attackerOwned ? -1 : 1)) >= 0)
|
||||
&& BattleHex::mutualPosition(attackerPos, defenderPos + (defender->side == BattleSide::ATTACKER ? -1 : 1)) >= 0)
|
||||
|| (defender->doubleWide() && attacker->doubleWide()//back <=> back
|
||||
&& BattleHex::mutualPosition(attackerPos + (attacker->attackerOwned ? -1 : 1), defenderPos + (defender->attackerOwned ? -1 : 1)) >= 0);
|
||||
&& BattleHex::mutualPosition(attackerPos + (attacker->side == BattleSide::ATTACKER ? -1 : 1), defenderPos + (defender->side == BattleSide::ATTACKER ? -1 : 1)) >= 0);
|
||||
|
||||
}
|
||||
|
||||
|
12
lib/CStack.h
12
lib/CStack.h
@ -24,7 +24,7 @@ public:
|
||||
ui32 firstHPleft; //HP of first creature in stack
|
||||
PlayerColor owner; //owner - player colour (255 for neutrals)
|
||||
SlotID slot; //slot - position in garrison (may be 255 for neutrals/called creatures)
|
||||
bool attackerOwned; //if true, this stack is owned by attakcer (this one from left hand side of battle)
|
||||
ui8 side;
|
||||
BattleHex position; //position on battlefield; -2 - keep, -3 - lower tower, -4 - upper tower
|
||||
///how many times this stack has been counterattacked this round
|
||||
ui8 counterAttacksPerformed;
|
||||
@ -39,8 +39,8 @@ public:
|
||||
//overrides
|
||||
const CCreature* getCreature() const {return type;}
|
||||
|
||||
CStack(const CStackInstance *base, PlayerColor O, int I, bool AO, SlotID S); //c-tor
|
||||
CStack(const CStackBasicDescriptor *stack, PlayerColor O, int I, bool AO, SlotID S = SlotID(255)); //c-tor
|
||||
CStack(const CStackInstance *base, PlayerColor O, int I, ui8 Side, SlotID S); //c-tor
|
||||
CStack(const CStackBasicDescriptor *stack, PlayerColor O, int I, ui8 Side, SlotID S = SlotID(255)); //c-tor
|
||||
CStack(); //c-tor
|
||||
~CStack();
|
||||
std::string nodeName() const override;
|
||||
@ -73,10 +73,12 @@ public:
|
||||
BattleHex occupiedHex(BattleHex assumedPos) const; //returns number of occupied hex (not the position) if stack is double wide and would stand on assumedPos; otherwise -1
|
||||
std::vector<BattleHex> getHexes() const; //up to two occupied hexes, starting from front
|
||||
std::vector<BattleHex> getHexes(BattleHex assumedPos) const; //up to two occupied hexes, starting from front
|
||||
static std::vector<BattleHex> getHexes(BattleHex assumedPos, bool twoHex, bool AttackerOwned); //up to two occupied hexes, starting from front
|
||||
static std::vector<BattleHex> getHexes(BattleHex assumedPos, bool twoHex, ui8 side); //up to two occupied hexes, starting from front
|
||||
bool coversPos(BattleHex position) const; //checks also if unit is double-wide
|
||||
std::vector<BattleHex> getSurroundingHexes(BattleHex attackerPos = BattleHex::INVALID) const; // get six or 8 surrounding hexes depending on creature size
|
||||
|
||||
BattleHex::EDir destShiftDir() const;
|
||||
|
||||
std::pair<int,int> countKilledByAttack(int damageReceived) const; //returns pair<killed count, new left HP>
|
||||
void prepareAttacked(BattleStackAttacked &bsa, CRandomGenerator & rand, boost::optional<int> customCount = boost::none) const; //requires bsa.damageAmout filled
|
||||
|
||||
@ -110,7 +112,7 @@ public:
|
||||
assert(isIndependentNode());
|
||||
h & static_cast<CBonusSystemNode&>(*this);
|
||||
h & static_cast<CStackBasicDescriptor&>(*this);
|
||||
h & ID & baseAmount & firstHPleft & owner & slot & attackerOwned & position & state & counterAttacksPerformed
|
||||
h & ID & baseAmount & firstHPleft & owner & slot & side & position & state & counterAttacksPerformed
|
||||
& shots & casts & count & resurrected;
|
||||
|
||||
const CArmedInstance *army = (base ? base->armyObj : nullptr);
|
||||
|
@ -11,6 +11,7 @@
|
||||
|
||||
|
||||
#include "battle/BattleHex.h"
|
||||
#include "GameConstants.h"
|
||||
#include "int3.h"
|
||||
|
||||
class CGTownInstance;
|
||||
|
@ -1628,13 +1628,13 @@ struct BattleStacksRemoved : public CPackForClient
|
||||
struct BattleStackAdded : public CPackForClient
|
||||
{
|
||||
BattleStackAdded()
|
||||
: attacker(0), amount(0), pos(0), summoned(0), newStackID(0)
|
||||
: side(0), amount(0), pos(0), summoned(0), newStackID(0)
|
||||
{};
|
||||
|
||||
DLL_LINKAGE void applyGs(CGameState *gs);
|
||||
void applyCl(CClient *cl);
|
||||
|
||||
int attacker; // if true, stack belongs to attacker
|
||||
ui8 side;
|
||||
CreatureID creID;
|
||||
int amount;
|
||||
int pos;
|
||||
@ -1645,7 +1645,7 @@ struct BattleStackAdded : public CPackForClient
|
||||
|
||||
template <typename Handler> void serialize(Handler &h, const int version)
|
||||
{
|
||||
h & attacker & creID & amount & pos & summoned;
|
||||
h & side & creID & amount & pos & summoned;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -1384,7 +1384,7 @@ void BattleStackMoved::applyGs(CGameState *gs)
|
||||
{
|
||||
SpellCreatedObstacle *sands = dynamic_cast<SpellCreatedObstacle*>(oi.get());
|
||||
assert(sands);
|
||||
if(sands->casterSide != !s->attackerOwned)
|
||||
if(sands->casterSide != s->side)
|
||||
sands->visibleForAnotherSide = true;
|
||||
}
|
||||
}
|
||||
@ -1803,7 +1803,7 @@ DLL_LINKAGE void BattleStackAdded::applyGs(CGameState *gs)
|
||||
}
|
||||
|
||||
CStackBasicDescriptor csbd(creID, amount);
|
||||
CStack * addedStack = gs->curB->generateNewStack(csbd, attacker, SlotID::SUMMONED_SLOT_PLACEHOLDER, pos); //TODO: netpacks?
|
||||
CStack * addedStack = gs->curB->generateNewStack(csbd, side, SlotID::SUMMONED_SLOT_PLACEHOLDER, pos); //TODO: netpacks?
|
||||
if (summoned)
|
||||
addedStack->state.insert(EBattleStackState::SUMMONED);
|
||||
|
||||
|
@ -10,16 +10,17 @@
|
||||
#include "../StdInc.h"
|
||||
#include "AccessibilityInfo.h"
|
||||
#include "../CStack.h"
|
||||
#include "../GameConstants.h"
|
||||
|
||||
bool AccessibilityInfo::accessible(BattleHex tile, const CStack * stack) const
|
||||
{
|
||||
return accessible(tile, stack->doubleWide(), stack->attackerOwned);
|
||||
return accessible(tile, stack->doubleWide(), stack->side);
|
||||
}
|
||||
|
||||
bool AccessibilityInfo::accessible(BattleHex tile, bool doubleWide, bool attackerOwned) const
|
||||
bool AccessibilityInfo::accessible(BattleHex tile, bool doubleWide, ui8 side) const
|
||||
{
|
||||
// All hexes that stack would cover if standing on tile have to be accessible.
|
||||
for(auto hex : CStack::getHexes(tile, doubleWide, attackerOwned))
|
||||
for(auto hex : CStack::getHexes(tile, doubleWide, side))
|
||||
{
|
||||
// If the hex is out of range then the tile isn't accessible
|
||||
if(!hex.isValid())
|
||||
@ -27,25 +28,10 @@ bool AccessibilityInfo::accessible(BattleHex tile, bool doubleWide, bool attacke
|
||||
// If we're no defender which step on gate and the hex isn't accessible, then the tile
|
||||
// isn't accessible
|
||||
else if(at(hex) != EAccessibility::ACCESSIBLE &&
|
||||
!(at(hex) == EAccessibility::GATE && !attackerOwned))
|
||||
!(at(hex) == EAccessibility::GATE && side == BattleSide::DEFENDER))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool AccessibilityInfo::occupiable(const CStack * stack, BattleHex tile) const
|
||||
{
|
||||
//obviously, we can occupy tile by standing on it
|
||||
if(accessible(tile, stack))
|
||||
return true;
|
||||
if(stack->doubleWide())
|
||||
{
|
||||
//Check the tile next to -> if stack stands there, it'll also occupy considered hex
|
||||
const BattleHex anotherTile = tile + (stack->attackerOwned ? BattleHex::RIGHT : BattleHex::LEFT);
|
||||
if(accessible(anotherTile, stack))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
@ -9,6 +9,7 @@
|
||||
*/
|
||||
#pragma once
|
||||
#include "BattleHex.h"
|
||||
#include "../GameConstants.h"
|
||||
|
||||
class CStack;
|
||||
|
||||
@ -29,7 +30,6 @@ typedef std::array<EAccessibility, GameConstants::BFIELD_SIZE> TAccessibilityArr
|
||||
|
||||
struct DLL_LINKAGE AccessibilityInfo : TAccessibilityArray
|
||||
{
|
||||
bool occupiable(const CStack * stack, BattleHex tile) const;
|
||||
bool accessible(BattleHex tile, const CStack * stack) const; //checks for both tiles if stack is double wide
|
||||
bool accessible(BattleHex tile, bool doubleWide, bool attackerOwned) const; //checks for both tiles if stack is double wide
|
||||
bool accessible(BattleHex tile, bool doubleWide, ui8 side) const; //checks for both tiles if stack is double wide
|
||||
};
|
||||
|
@ -27,7 +27,7 @@ BattleAction::BattleAction():
|
||||
BattleAction BattleAction::makeHeal(const CStack * healer, const CStack * healed)
|
||||
{
|
||||
BattleAction ba;
|
||||
ba.side = !healer->attackerOwned;
|
||||
ba.side = healer->side;
|
||||
ba.actionType = STACK_HEAL;
|
||||
ba.stackNumber = healer->ID;
|
||||
ba.destinationTile = healed->position;
|
||||
@ -37,7 +37,7 @@ BattleAction BattleAction::makeHeal(const CStack * healer, const CStack * healed
|
||||
BattleAction BattleAction::makeDefend(const CStack * stack)
|
||||
{
|
||||
BattleAction ba;
|
||||
ba.side = !stack->attackerOwned;
|
||||
ba.side = stack->side;
|
||||
ba.actionType = DEFEND;
|
||||
ba.stackNumber = stack->ID;
|
||||
return ba;
|
||||
@ -47,7 +47,7 @@ BattleAction BattleAction::makeDefend(const CStack * stack)
|
||||
BattleAction BattleAction::makeMeleeAttack(const CStack * stack, const CStack * attacked, BattleHex attackFrom /*= BattleHex::INVALID*/)
|
||||
{
|
||||
BattleAction ba;
|
||||
ba.side = !stack->attackerOwned;
|
||||
ba.side = stack->side;
|
||||
ba.actionType = WALK_AND_ATTACK;
|
||||
ba.stackNumber = stack->ID;
|
||||
ba.destinationTile = attackFrom;
|
||||
@ -58,7 +58,7 @@ BattleAction BattleAction::makeMeleeAttack(const CStack * stack, const CStack *
|
||||
BattleAction BattleAction::makeWait(const CStack * stack)
|
||||
{
|
||||
BattleAction ba;
|
||||
ba.side = !stack->attackerOwned;
|
||||
ba.side = stack->side;
|
||||
ba.actionType = WAIT;
|
||||
ba.stackNumber = stack->ID;
|
||||
return ba;
|
||||
@ -67,7 +67,7 @@ BattleAction BattleAction::makeWait(const CStack * stack)
|
||||
BattleAction BattleAction::makeShotAttack(const CStack * shooter, const CStack * target)
|
||||
{
|
||||
BattleAction ba;
|
||||
ba.side = !shooter->attackerOwned;
|
||||
ba.side = shooter->side;
|
||||
ba.actionType = SHOOT;
|
||||
ba.stackNumber = shooter->ID;
|
||||
ba.destinationTile = target->position;
|
||||
@ -77,7 +77,7 @@ BattleAction BattleAction::makeShotAttack(const CStack * shooter, const CStack *
|
||||
BattleAction BattleAction::makeMove(const CStack * stack, BattleHex dest)
|
||||
{
|
||||
BattleAction ba;
|
||||
ba.side = !stack->attackerOwned;
|
||||
ba.side = stack->side;
|
||||
ba.actionType = WALK;
|
||||
ba.stackNumber = stack->ID;
|
||||
ba.destinationTile = dest;
|
||||
|
@ -9,6 +9,7 @@
|
||||
*/
|
||||
#pragma once
|
||||
#include "BattleHex.h"
|
||||
#include "../GameConstants.h"
|
||||
|
||||
class CStack;
|
||||
|
||||
|
@ -9,6 +9,7 @@
|
||||
*/
|
||||
#include "../StdInc.h"
|
||||
#include "BattleHex.h"
|
||||
#include "../GameConstants.h"
|
||||
|
||||
BattleHex::BattleHex() : hex(INVALID) {}
|
||||
|
||||
@ -99,6 +100,8 @@ BattleHex& BattleHex::moveInDirection(EDir dir, bool hasToBeValid)
|
||||
case LEFT:
|
||||
setXY(x-1, y, hasToBeValid);
|
||||
break;
|
||||
case NONE:
|
||||
break;
|
||||
default:
|
||||
throw std::runtime_error("Disaster: wrong direction in BattleHex::operator+=!\n");
|
||||
break;
|
||||
@ -160,7 +163,7 @@ void BattleHex::checkAndPush(BattleHex tile, std::vector<BattleHex> & ret)
|
||||
ret.push_back(tile);
|
||||
}
|
||||
|
||||
BattleHex BattleHex::getClosestTile(bool attackerOwned, BattleHex initialPos, std::set<BattleHex> & possibilities)
|
||||
BattleHex BattleHex::getClosestTile(ui8 side, BattleHex initialPos, std::set<BattleHex> & possibilities)
|
||||
{
|
||||
std::vector<BattleHex> sortedTiles (possibilities.begin(), possibilities.end()); //set can't be sorted properly :(
|
||||
BattleHex initialHex = BattleHex(initialPos);
|
||||
@ -175,11 +178,11 @@ BattleHex BattleHex::getClosestTile(bool attackerOwned, BattleHex initialPos, st
|
||||
return closestDistance < here.getDistance (initialPos, here);
|
||||
};
|
||||
vstd::erase_if(sortedTiles, notClosest); //only closest tiles are interesting
|
||||
auto compareHorizontal = [attackerOwned, initialPos](const BattleHex left, const BattleHex right) -> bool
|
||||
auto compareHorizontal = [side, initialPos](const BattleHex left, const BattleHex right) -> bool
|
||||
{
|
||||
if(left.getX() != right.getX())
|
||||
{
|
||||
if (attackerOwned)
|
||||
if(side == BattleSide::ATTACKER)
|
||||
return left.getX() > right.getX(); //find furthest right
|
||||
else
|
||||
return left.getX() < right.getX(); //find furthest left
|
||||
|
@ -8,14 +8,35 @@
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
#include "../GameConstants.h"
|
||||
|
||||
//TODO: change to enum class
|
||||
|
||||
namespace BattleSide
|
||||
{
|
||||
enum
|
||||
{
|
||||
ATTACKER = 0,
|
||||
DEFENDER = 1
|
||||
};
|
||||
}
|
||||
|
||||
typedef boost::optional<ui8> BattleSideOpt;
|
||||
|
||||
// for battle stacks' positions
|
||||
struct DLL_LINKAGE BattleHex //TODO: decide if this should be changed to class for better code design
|
||||
{
|
||||
si16 hex;
|
||||
static const si16 INVALID = -1;
|
||||
enum EDir { TOP_LEFT, TOP_RIGHT, RIGHT, BOTTOM_RIGHT, BOTTOM_LEFT, LEFT};
|
||||
enum EDir
|
||||
{
|
||||
TOP_LEFT,
|
||||
TOP_RIGHT,
|
||||
RIGHT,
|
||||
BOTTOM_RIGHT,
|
||||
BOTTOM_LEFT,
|
||||
LEFT,
|
||||
NONE
|
||||
};
|
||||
|
||||
BattleHex();
|
||||
BattleHex(si16 _hex);
|
||||
@ -39,7 +60,7 @@ struct DLL_LINKAGE BattleHex //TODO: decide if this should be changed to class f
|
||||
static signed char mutualPosition(BattleHex hex1, BattleHex hex2);
|
||||
static char getDistance(BattleHex hex1, BattleHex hex2);
|
||||
static void checkAndPush(BattleHex tile, std::vector<BattleHex> & ret);
|
||||
static BattleHex getClosestTile(bool attackerOwned, BattleHex initialPos, std::set<BattleHex> & possibilities); //TODO: vector or set? copying one to another is bad
|
||||
static BattleHex getClosestTile(ui8 side, BattleHex initialPos, std::set<BattleHex> & possibilities); //TODO: vector or set? copying one to another is bad
|
||||
|
||||
template <typename Handler>
|
||||
void serialize(Handler &h, const int version)
|
||||
|
@ -26,7 +26,7 @@ const CStack * BattleInfo::getNextStack() const
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
int BattleInfo::getAvaliableHex(CreatureID creID, bool attackerOwned, int initialPos) const
|
||||
int BattleInfo::getAvaliableHex(CreatureID creID, ui8 side, int initialPos) const
|
||||
{
|
||||
bool twoHex = VLC->creh->creatures[creID]->isDoubleWide();
|
||||
//bool flying = VLC->creh->creatures[creID]->isFlying();
|
||||
@ -36,7 +36,7 @@ int BattleInfo::getAvaliableHex(CreatureID creID, bool attackerOwned, int initia
|
||||
pos = initialPos;
|
||||
else //summon elementals depending on player side
|
||||
{
|
||||
if (attackerOwned)
|
||||
if(side == BattleSide::ATTACKER)
|
||||
pos = 0; //top left
|
||||
else
|
||||
pos = GameConstants::BFIELD_WIDTH - 1; //top right
|
||||
@ -46,7 +46,7 @@ int BattleInfo::getAvaliableHex(CreatureID creID, bool attackerOwned, int initia
|
||||
|
||||
std::set<BattleHex> occupyable;
|
||||
for(int i = 0; i < accessibility.size(); i++)
|
||||
if(accessibility.accessible(i, twoHex, attackerOwned))
|
||||
if(accessibility.accessible(i, twoHex, side))
|
||||
occupyable.insert(i);
|
||||
|
||||
if (occupyable.empty())
|
||||
@ -54,7 +54,7 @@ int BattleInfo::getAvaliableHex(CreatureID creID, bool attackerOwned, int initia
|
||||
return BattleHex::INVALID; //all tiles are covered
|
||||
}
|
||||
|
||||
return BattleHex::getClosestTile(attackerOwned, pos, occupyable);
|
||||
return BattleHex::getClosestTile(side, pos, occupyable);
|
||||
}
|
||||
|
||||
std::pair< std::vector<BattleHex>, int > BattleInfo::getPath(BattleHex start, BattleHex dest, const CStack * stack)
|
||||
@ -104,28 +104,28 @@ void BattleInfo::calculateCasualties(std::map<ui32,si32> * casualties) const
|
||||
si32 killed = (st->alive() ? (st->baseAmount - st->count + st->resurrected) : st->baseAmount);
|
||||
vstd::amax(killed, 0);
|
||||
if(killed)
|
||||
casualties[!st->attackerOwned][st->getCreature()->idNumber] += killed;
|
||||
casualties[st->side][st->getCreature()->idNumber] += killed;
|
||||
}
|
||||
}
|
||||
|
||||
CStack * BattleInfo::generateNewStack(const CStackInstance &base, bool attackerOwned, SlotID slot, BattleHex position) const
|
||||
CStack * BattleInfo::generateNewStack(const CStackInstance & base, ui8 side, SlotID slot, BattleHex position) const
|
||||
{
|
||||
int stackID = getIdForNewStack();
|
||||
PlayerColor owner = sides[attackerOwned ? 0 : 1].color;
|
||||
PlayerColor owner = sides[side].color;
|
||||
assert((owner >= PlayerColor::PLAYER_LIMIT) ||
|
||||
(base.armyObj && base.armyObj->tempOwner == owner));
|
||||
|
||||
auto ret = new CStack(&base, owner, stackID, attackerOwned, slot);
|
||||
ret->position = getAvaliableHex (base.getCreatureID(), attackerOwned, position); //TODO: what if no free tile on battlefield was found?
|
||||
auto ret = new CStack(&base, owner, stackID, side, slot);
|
||||
ret->position = getAvaliableHex(base.getCreatureID(), side, position); //TODO: what if no free tile on battlefield was found?
|
||||
ret->state.insert(EBattleStackState::ALIVE); //alive state indication
|
||||
return ret;
|
||||
}
|
||||
|
||||
CStack * BattleInfo::generateNewStack(const CStackBasicDescriptor &base, bool attackerOwned, SlotID slot, BattleHex position) const
|
||||
CStack * BattleInfo::generateNewStack(const CStackBasicDescriptor & base, ui8 side, SlotID slot, BattleHex position) const
|
||||
{
|
||||
int stackID = getIdForNewStack();
|
||||
PlayerColor owner = sides[attackerOwned ? 0 : 1].color;
|
||||
auto ret = new CStack(&base, owner, stackID, attackerOwned, slot);
|
||||
PlayerColor owner = sides[side].color;
|
||||
auto ret = new CStack(&base, owner, stackID, side, slot);
|
||||
ret->position = position;
|
||||
ret->state.insert(EBattleStackState::ALIVE); //alive state indication
|
||||
return ret;
|
||||
@ -155,7 +155,7 @@ void BattleInfo::localInitStack(CStack * s)
|
||||
}
|
||||
else //attach directly to obj to which stack belongs and creature type
|
||||
{
|
||||
CArmedInstance *army = battleGetArmyObject(!s->attackerOwned);
|
||||
CArmedInstance *army = battleGetArmyObject(s->side);
|
||||
s->attachTo(army);
|
||||
assert(s->type);
|
||||
s->attachTo(const_cast<CCreature*>(s->type));
|
||||
@ -486,7 +486,7 @@ BattleInfo * BattleInfo::setupBattle(int3 tile, ETerrainType terrain, BFieldType
|
||||
if(creatureBank && i->second->type->isDoubleWide())
|
||||
pos += side ? BattleHex::LEFT : BattleHex::RIGHT;
|
||||
|
||||
CStack * stack = curB->generateNewStack(*i->second, !side, i->first, pos);
|
||||
CStack * stack = curB->generateNewStack(*i->second, side, i->first, pos);
|
||||
stacks.push_back(stack);
|
||||
}
|
||||
}
|
||||
@ -496,7 +496,7 @@ BattleInfo * BattleInfo::setupBattle(int3 tile, ETerrainType terrain, BFieldType
|
||||
{
|
||||
if (heroes[i] && heroes[i]->commander && heroes[i]->commander->alive)
|
||||
{
|
||||
CStack * stack = curB->generateNewStack (*heroes[i]->commander, !i, SlotID::COMMANDER_SLOT_PLACEHOLDER,
|
||||
CStack * stack = curB->generateNewStack (*heroes[i]->commander, i, SlotID::COMMANDER_SLOT_PLACEHOLDER,
|
||||
creatureBank ? commanderBank[i] : commanderField[i]);
|
||||
stacks.push_back(stack);
|
||||
}
|
||||
@ -506,15 +506,15 @@ BattleInfo * BattleInfo::setupBattle(int3 tile, ETerrainType terrain, BFieldType
|
||||
if (curB->town && curB->town->fortLevel() >= CGTownInstance::CITADEL)
|
||||
{
|
||||
// keep tower
|
||||
CStack * stack = curB->generateNewStack(CStackBasicDescriptor(CreatureID::ARROW_TOWERS, 1), false, SlotID::ARROW_TOWERS_SLOT, -2);
|
||||
CStack * stack = curB->generateNewStack(CStackBasicDescriptor(CreatureID::ARROW_TOWERS, 1), 1, SlotID::ARROW_TOWERS_SLOT, -2);
|
||||
stacks.push_back(stack);
|
||||
|
||||
if (curB->town->fortLevel() >= CGTownInstance::CASTLE)
|
||||
{
|
||||
// lower tower + upper tower
|
||||
CStack * stack = curB->generateNewStack(CStackBasicDescriptor(CreatureID::ARROW_TOWERS, 1), false, SlotID::ARROW_TOWERS_SLOT, -4);
|
||||
CStack * stack = curB->generateNewStack(CStackBasicDescriptor(CreatureID::ARROW_TOWERS, 1), 1, SlotID::ARROW_TOWERS_SLOT, -4);
|
||||
stacks.push_back(stack);
|
||||
stack = curB->generateNewStack(CStackBasicDescriptor(CreatureID::ARROW_TOWERS, 1), false, SlotID::ARROW_TOWERS_SLOT, -3);
|
||||
stack = curB->generateNewStack(CStackBasicDescriptor(CreatureID::ARROW_TOWERS, 1), 1, SlotID::ARROW_TOWERS_SLOT, -3);
|
||||
stacks.push_back(stack);
|
||||
}
|
||||
|
||||
|
@ -55,28 +55,17 @@ struct DLL_LINKAGE BattleInfo : public CBonusSystemNode, public CBattleInfoCallb
|
||||
CGHeroInstance * battleGetFightingHero(ui8 side) const;
|
||||
|
||||
const CStack * getNextStack() const; //which stack will have turn after current one
|
||||
//void getStackQueue(std::vector<const CStack *> &out, int howMany, int turn = 0, int lastMoved = -1) const; //returns stack in order of their movement action
|
||||
|
||||
//void getAccessibilityMap(bool *accessibility, bool twoHex, bool attackerOwned, bool addOccupiable, std::set<BattleHex> & occupyable, bool flying, const CStack* stackToOmmit = nullptr) const; //send pointer to at least 187 allocated bytes
|
||||
//static bool isAccessible(BattleHex hex, bool * accessibility, bool twoHex, bool attackerOwned, bool flying, bool lastPos); //helper for makeBFS
|
||||
int getAvaliableHex(CreatureID creID, bool attackerOwned, int initialPos = -1) const; //find place for summon / clone effects
|
||||
//void makeBFS(BattleHex start, bool*accessibility, BattleHex *predecessor, int *dists, bool twoHex, bool attackerOwned, bool flying, bool fillPredecessors) const; //*accessibility must be prepared bool[187] array; last two pointers must point to the at least 187-elements int arrays - there is written result
|
||||
int getAvaliableHex(CreatureID creID, ui8 side, int initialPos = -1) const; //find place for summon / clone effects
|
||||
std::pair< std::vector<BattleHex>, int > getPath(BattleHex start, BattleHex dest, const CStack * stack); //returned value: pair<path, length>; length may be different than number of elements in path since flying vreatures jump between distant hexes
|
||||
//std::vector<BattleHex> getAccessibility(const CStack * stack, bool addOccupiable, std::vector<BattleHex> * attackable = nullptr, bool forPassingBy = false) const; //returns vector of accessible tiles (taking into account the creature range)
|
||||
|
||||
//bool isObstacleVisibleForSide(const CObstacleInstance &obstacle, ui8 side) const;
|
||||
std::shared_ptr<CObstacleInstance> getObstacleOnTile(BattleHex tile) const;
|
||||
std::set<BattleHex> getStoppers(bool whichSidePerspective) const;
|
||||
|
||||
ui32 calculateDmg(const CStack * attacker, const CStack * defender, bool shooting, ui8 charge, bool lucky, bool unlucky, bool deathBlow, bool ballistaDoubleDmg, CRandomGenerator & rand); //charge - number of hexes travelled before attack (for champion's jousting)
|
||||
void calculateCasualties(std::map<ui32,si32> * casualties) const; //casualties are array of maps size 2 (attacker, defeneder), maps are (crid => amount)
|
||||
|
||||
//void getPotentiallyAttackableHexes(AttackableTiles &at, const CStack* attacker, BattleHex destinationTile, BattleHex attackerPos); //hexes around target that could be attacked in melee
|
||||
//std::set<CStack*> getAttackedCreatures(const CStack* attacker, BattleHex destinationTile, BattleHex attackerPos = BattleHex::INVALID); //calculates range of multi-hex attacks
|
||||
//std::set<BattleHex> getAttackedHexes(const CStack* attacker, BattleHex destinationTile, BattleHex attackerPos = BattleHex::INVALID); //calculates range of multi-hex attacks
|
||||
|
||||
CStack * generateNewStack(const CStackInstance &base, bool attackerOwned, SlotID slot, BattleHex position) const; //helper for CGameHandler::setupBattle and spells addign new stacks to the battlefield
|
||||
CStack * generateNewStack(const CStackBasicDescriptor &base, bool attackerOwned, SlotID slot, BattleHex position) const; //helper for CGameHandler::setupBattle and spells addign new stacks to the battlefield
|
||||
CStack * generateNewStack(const CStackInstance &base, ui8 side, SlotID slot, BattleHex position) const; //helper for CGameHandler::setupBattle and spells addign new stacks to the battlefield
|
||||
CStack * generateNewStack(const CStackBasicDescriptor &base, ui8 side, SlotID slot, BattleHex position) const; //helper for CGameHandler::setupBattle and spells addign new stacks to the battlefield
|
||||
int getIdForNewStack() const; //suggest a currently unused ID that'd suitable for generating a new stack
|
||||
|
||||
const CGHeroInstance * getHero(PlayerColor player) const; //returns fighting hero that belongs to given player
|
||||
|
@ -103,10 +103,10 @@ ESpellCastProblem::ESpellCastProblem CBattleInfoCallback::battleCanCastSpell(con
|
||||
return ESpellCastProblem::INVALID;
|
||||
}
|
||||
const PlayerColor player = caster->getOwner();
|
||||
const si8 side = playerToSide(player);
|
||||
if(side < 0)
|
||||
const auto side = playerToSide(player);
|
||||
if(!side)
|
||||
return ESpellCastProblem::INVALID;
|
||||
if(!battleDoWeKnowAbout(side))
|
||||
if(!battleDoWeKnowAbout(side.get()))
|
||||
{
|
||||
logGlobal->warnStream() << "You can't check if enemy can cast given spell!";
|
||||
return ESpellCastProblem::INVALID;
|
||||
@ -119,7 +119,7 @@ ESpellCastProblem::ESpellCastProblem CBattleInfoCallback::battleCanCastSpell(con
|
||||
{
|
||||
case ECastingMode::HERO_CASTING:
|
||||
{
|
||||
if(battleCastSpells(side) > 0)
|
||||
if(battleCastSpells(side.get()) > 0)
|
||||
return ESpellCastProblem::ALREADY_CASTED_THIS_TURN;
|
||||
|
||||
auto hero = dynamic_cast<const CGHeroInstance *>(caster);
|
||||
@ -255,7 +255,7 @@ void CBattleInfoCallback::battleGetStackQueue(std::vector<const CStack *> &out,
|
||||
int bestSpeed = fastest->Speed(turn);
|
||||
|
||||
//FIXME: comparison between bool and integer. Logic does not makes sense either
|
||||
if(fastest->attackerOwned != lastMoved)
|
||||
if(fastest->side != lastMoved)
|
||||
{
|
||||
ret = fastest;
|
||||
}
|
||||
@ -264,7 +264,7 @@ void CBattleInfoCallback::battleGetStackQueue(std::vector<const CStack *> &out,
|
||||
for(j = i + 1; j < st.size(); j++)
|
||||
{
|
||||
if(!st[j]) continue;
|
||||
if(st[j]->attackerOwned != lastMoved || st[j]->Speed(turn) != bestSpeed)
|
||||
if(st[j]->side != lastMoved || st[j]->Speed(turn) != bestSpeed)
|
||||
break;
|
||||
}
|
||||
|
||||
@ -288,7 +288,7 @@ void CBattleInfoCallback::battleGetStackQueue(std::vector<const CStack *> &out,
|
||||
else
|
||||
st[j] = nullptr;
|
||||
|
||||
lastMoved = ret->attackerOwned;
|
||||
lastMoved = ret->side;
|
||||
return ret;
|
||||
};
|
||||
|
||||
@ -362,9 +362,9 @@ void CBattleInfoCallback::battleGetStackQueue(std::vector<const CStack *> &out,
|
||||
{
|
||||
//FIXME: both branches contain same code!!!
|
||||
if(out.size() && out.front() == active)
|
||||
lastMoved = active->attackerOwned;
|
||||
lastMoved = active->side;
|
||||
else
|
||||
lastMoved = active->attackerOwned;
|
||||
lastMoved = active->side;
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -418,7 +418,7 @@ std::vector<BattleHex> CBattleInfoCallback::battleGetAvailableHexes(const CStack
|
||||
if(!reachability.isReachable(i))
|
||||
continue;
|
||||
|
||||
if(battleTacticDist() && battleGetTacticsSide() == !stack->attackerOwned)
|
||||
if(battleTacticDist() && battleGetTacticsSide() == stack->side)
|
||||
{
|
||||
//Stack has to perform tactic-phase movement -> can enter any reachable tile within given range
|
||||
if(!isInTacticRange(i))
|
||||
@ -453,7 +453,7 @@ std::vector<BattleHex> CBattleInfoCallback::battleGetAvailableHexes(const CStack
|
||||
});
|
||||
return availableNeighbor != ret.end();
|
||||
};
|
||||
for(const CStack * otherSt : battleAliveStacks(stack->attackerOwned))
|
||||
for(const CStack * otherSt : battleAliveStacks(1-stack->side))
|
||||
{
|
||||
if(!otherSt->isValidTarget(false))
|
||||
continue;
|
||||
@ -800,7 +800,6 @@ std::pair<ui32, ui32> CBattleInfoCallback::battleEstimateDamage(CRandomGenerator
|
||||
RETURN_IF_NOT_BATTLE(std::make_pair(0, 0));
|
||||
|
||||
//const bool shooting = battleCanShoot(bai.attacker, bai.defenderPosition); //TODO handle bonus bearer
|
||||
//const ui8 mySide = !attacker->attackerOwned;
|
||||
|
||||
TDmgRange ret = calculateDmgRange(bai);
|
||||
|
||||
@ -965,7 +964,7 @@ ReachabilityInfo CBattleInfoCallback::makeBFS(const AccessibilityInfo &accessibi
|
||||
const int costToNeighbour = ret.distances[curHex] + 1;
|
||||
for(BattleHex neighbour : curHex.neighbouringTiles())
|
||||
{
|
||||
const bool accessible = accessibility.accessible(neighbour, params.doubleWide, params.attackerOwned);
|
||||
const bool accessible = accessibility.accessible(neighbour, params.doubleWide, params.side);
|
||||
const int costFoundSoFar = ret.distances[neighbour];
|
||||
|
||||
if(accessible && costToNeighbour < costFoundSoFar)
|
||||
@ -1001,7 +1000,7 @@ std::set<BattleHex> CBattleInfoCallback::getStoppers(BattlePerspective::BattlePe
|
||||
return ret;
|
||||
}
|
||||
|
||||
std::pair<const CStack *, BattleHex> CBattleInfoCallback::getNearestStack(const CStack * closest, boost::logic::tribool attackerOwned) const
|
||||
std::pair<const CStack *, BattleHex> CBattleInfoCallback::getNearestStack(const CStack * closest, BattleSideOpt side) const
|
||||
{
|
||||
auto reachability = getReachability(closest);
|
||||
auto avHexes = battleGetAvailableHexes(closest, false);
|
||||
@ -1018,7 +1017,7 @@ std::pair<const CStack *, BattleHex> CBattleInfoCallback::getNearestStack(const
|
||||
|
||||
std::vector<const CStack *> possibleStacks = battleGetStacksIf([=](const CStack * s)
|
||||
{
|
||||
return s->isValidTarget(false) && s != closest && (boost::logic::indeterminate(attackerOwned) || s->attackerOwned == attackerOwned);
|
||||
return s->isValidTarget(false) && s != closest && (!side || side.get() == s->side);
|
||||
});
|
||||
|
||||
for(const CStack * st : possibleStacks)
|
||||
@ -1064,7 +1063,7 @@ ReachabilityInfo CBattleInfoCallback::getReachability(const CStack *stack) const
|
||||
{
|
||||
ReachabilityInfo::Parameters params(stack);
|
||||
|
||||
if(!battleDoWeKnowAbout(!stack->attackerOwned))
|
||||
if(!battleDoWeKnowAbout(stack->side))
|
||||
{
|
||||
//Stack is held by enemy, we can't use his perspective to check for reachability.
|
||||
// Happens ie. when hovering enemy stack for its range. The arg could be set properly, but it's easier to fix it here.
|
||||
@ -1089,7 +1088,7 @@ ReachabilityInfo CBattleInfoCallback::getFlyingReachability(const ReachabilityIn
|
||||
|
||||
for(int i = 0; i < GameConstants::BFIELD_SIZE; i++)
|
||||
{
|
||||
if(ret.accessibility.accessible(i, params.doubleWide, params.attackerOwned))
|
||||
if(ret.accessibility.accessible(i, params.doubleWide, params.side))
|
||||
{
|
||||
ret.predecessors[i] = params.startPosition;
|
||||
ret.distances[i] = BattleHex::getDistance(params.startPosition, i);
|
||||
@ -1103,7 +1102,7 @@ AttackableTiles CBattleInfoCallback::getPotentiallyAttackableHexes (const CStack
|
||||
{
|
||||
//does not return hex attacked directly
|
||||
//TODO: apply rotation to two-hex attackers
|
||||
bool isAttacker = attacker->attackerOwned;
|
||||
bool isAttacker = attacker->side == BattleSide::ATTACKER;
|
||||
|
||||
AttackableTiles at;
|
||||
RETURN_IF_NOT_BATTLE(at);
|
||||
@ -1482,7 +1481,7 @@ SpellID CBattleInfoCallback::getRandomBeneficialSpell(CRandomGenerator & rand, c
|
||||
case SpellID::PROTECTION_FROM_FIRE:
|
||||
case SpellID::PROTECTION_FROM_WATER:
|
||||
{
|
||||
const ui8 enemySide = (ui8)subject->attackerOwned;
|
||||
const ui8 enemySide = 1 - subject->side;
|
||||
//todo: only if enemy has spellbook
|
||||
if (!battleHasHero(enemySide)) //only if there is enemy hero
|
||||
continue;
|
||||
@ -1567,17 +1566,17 @@ int CBattleInfoCallback::battleGetSurrenderCost(PlayerColor Player) const
|
||||
if(!battleCanSurrender(Player))
|
||||
return -1;
|
||||
|
||||
const si8 playerSide = playerToSide(Player);
|
||||
if(playerSide < 0)
|
||||
const auto side = playerToSide(Player);
|
||||
if(!side)
|
||||
return -1;
|
||||
|
||||
int ret = 0;
|
||||
double discount = 0;
|
||||
for(const CStack *s : battleAliveStacks(playerSide))
|
||||
for(const CStack * s : battleAliveStacks(side.get()))
|
||||
if(s->base) //we pay for our stack that comes from our army slots - condition eliminates summoned cres and war machines
|
||||
ret += s->getCreature()->cost[Res::GOLD] * s->count;
|
||||
|
||||
if(const CGHeroInstance * h = battleGetFightingHero(playerSide))
|
||||
if(const CGHeroInstance * h = battleGetFightingHero(side.get()))
|
||||
discount += h->valOfBonuses(Bonus::SURRENDER_DISCOUNT);
|
||||
|
||||
ret *= (100.0 - discount) / 100.0;
|
||||
@ -1616,7 +1615,7 @@ boost::optional<int> CBattleInfoCallback::battleIsFinished() const
|
||||
{
|
||||
if(stack->alive() && !stack->hasBonusOfType(Bonus::SIEGE_WEAPON))
|
||||
{
|
||||
hasStack[1-stack->attackerOwned] = true;
|
||||
hasStack[stack->side] = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -101,7 +101,7 @@ public:
|
||||
AccessibilityInfo getAccesibility() const;
|
||||
AccessibilityInfo getAccesibility(const CStack *stack) const; //Hexes ocupied by stack will be marked as accessible.
|
||||
AccessibilityInfo getAccesibility(const std::vector<BattleHex> & accessibleHexes) const; //given hexes will be marked as accessible
|
||||
std::pair<const CStack *, BattleHex> getNearestStack(const CStack * closest, boost::logic::tribool attackerOwned) const;
|
||||
std::pair<const CStack *, BattleHex> getNearestStack(const CStack * closest, BattleSideOpt side) const;
|
||||
protected:
|
||||
ReachabilityInfo getFlyingReachability(const ReachabilityInfo::Parameters & params) const;
|
||||
ReachabilityInfo makeBFS(const AccessibilityInfo & accessibility, const ReachabilityInfo::Parameters & params) const;
|
||||
|
@ -67,7 +67,7 @@ bool CBattleInfoEssentials::battleHasNativeStack(ui8 side) const
|
||||
|
||||
for(const CStack * s : battleGetAllStacks())
|
||||
{
|
||||
if(s->attackerOwned == !side && s->getCreature()->isItNativeTerrain(getBattle()->terrainType))
|
||||
if(s->side == side && s->getCreature()->isItNativeTerrain(getBattle()->terrainType))
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -102,7 +102,7 @@ TStacks CBattleInfoEssentials::battleAliveStacks() const
|
||||
TStacks CBattleInfoEssentials::battleAliveStacks(ui8 side) const
|
||||
{
|
||||
return battleGetStacksIf([=](const CStack * s){
|
||||
return s->isValidTarget(false) && s->attackerOwned == !side;
|
||||
return s->isValidTarget(false) && s->side == side;
|
||||
});
|
||||
}
|
||||
|
||||
@ -237,8 +237,11 @@ const IBonusBearer * CBattleInfoEssentials::getBattleNode() const
|
||||
bool CBattleInfoEssentials::battleCanFlee(PlayerColor player) const
|
||||
{
|
||||
RETURN_IF_NOT_BATTLE(false);
|
||||
const si8 mySide = playerToSide(player);
|
||||
const CGHeroInstance *myHero = battleGetFightingHero(mySide);
|
||||
const auto side = playerToSide(player);
|
||||
if(!side)
|
||||
return false;
|
||||
|
||||
const CGHeroInstance *myHero = battleGetFightingHero(side.get());
|
||||
|
||||
//current player have no hero
|
||||
if(!myHero)
|
||||
@ -249,7 +252,7 @@ bool CBattleInfoEssentials::battleCanFlee(PlayerColor player) const
|
||||
return false;
|
||||
|
||||
//we are besieged defender
|
||||
if(mySide == BattleSide::DEFENDER && battleGetSiegeLevel())
|
||||
if(side.get() == BattleSide::DEFENDER && battleGetSiegeLevel())
|
||||
{
|
||||
auto town = battleGetDefendedTown();
|
||||
if(!town->hasBuilt(BuildingID::ESCAPE_TUNNEL, ETownType::STRONGHOLD))
|
||||
@ -259,23 +262,31 @@ bool CBattleInfoEssentials::battleCanFlee(PlayerColor player) const
|
||||
return true;
|
||||
}
|
||||
|
||||
si8 CBattleInfoEssentials::playerToSide(PlayerColor player) const
|
||||
BattleSideOpt CBattleInfoEssentials::playerToSide(PlayerColor player) const
|
||||
{
|
||||
RETURN_IF_NOT_BATTLE(-1);
|
||||
RETURN_IF_NOT_BATTLE(boost::none);
|
||||
int ret = vstd::find_pos_if(getBattle()->sides, [=](const SideInBattle &side){ return side.color == player; });
|
||||
if(ret < 0)
|
||||
logGlobal->warnStream() << "Cannot find side for player " << player;
|
||||
|
||||
return ret;
|
||||
return BattleSideOpt(ret);
|
||||
}
|
||||
|
||||
ui8 CBattleInfoEssentials::otherSide(ui8 side) const
|
||||
{
|
||||
if(side == BattleSide::ATTACKER)
|
||||
return BattleSide::DEFENDER;
|
||||
else
|
||||
return BattleSide::ATTACKER;
|
||||
}
|
||||
|
||||
bool CBattleInfoEssentials::playerHasAccessToHeroInfo(PlayerColor player, const CGHeroInstance * h) const
|
||||
{
|
||||
RETURN_IF_NOT_BATTLE(false);
|
||||
const si8 playerSide = playerToSide(player);
|
||||
if (playerSide >= 0)
|
||||
const auto side = playerToSide(player);
|
||||
if(side)
|
||||
{
|
||||
if (getBattle()->sides[!playerSide].hero == h)
|
||||
if (getBattle()->sides[otherSide(side.get())].hero == h)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@ -290,10 +301,12 @@ ui8 CBattleInfoEssentials::battleGetSiegeLevel() const
|
||||
bool CBattleInfoEssentials::battleCanSurrender(PlayerColor player) const
|
||||
{
|
||||
RETURN_IF_NOT_BATTLE(false);
|
||||
ui8 mySide = playerToSide(player);
|
||||
bool iAmSiegeDefender = (mySide == BattleSide::DEFENDER && battleGetSiegeLevel());
|
||||
const auto side = playerToSide(player);
|
||||
if(!side)
|
||||
return false;
|
||||
bool iAmSiegeDefender = (side.get() == BattleSide::DEFENDER && battleGetSiegeLevel());
|
||||
//conditions like for fleeing (except escape tunnel presence) + enemy must have a hero
|
||||
return battleCanFlee(player) && !iAmSiegeDefender && battleHasHero(!mySide);
|
||||
return battleCanFlee(player) && !iAmSiegeDefender && battleHasHero(otherSide(side.get()));
|
||||
}
|
||||
|
||||
bool CBattleInfoEssentials::battleHasHero(ui8 side) const
|
||||
@ -334,7 +347,10 @@ PlayerColor CBattleInfoEssentials::battleGetOwner(const CStack * stack) const
|
||||
const CGHeroInstance * CBattleInfoEssentials::battleGetOwnerHero(const CStack * stack) const
|
||||
{
|
||||
RETURN_IF_NOT_BATTLE(nullptr);
|
||||
return getBattle()->sides.at(playerToSide(battleGetOwner(stack))).hero;
|
||||
const auto side = playerToSide(battleGetOwner(stack));
|
||||
if(!side)
|
||||
return nullptr;
|
||||
return getBattle()->sides.at(side.get()).hero;
|
||||
}
|
||||
|
||||
bool CBattleInfoEssentials::battleMatchOwner(const CStack * attacker, const CStack * defender, const boost::logic::tribool positivness /* = false*/) const
|
||||
|
@ -9,6 +9,7 @@
|
||||
*/
|
||||
#pragma once
|
||||
#include "CCallbackBase.h"
|
||||
#include "BattleHex.h"
|
||||
|
||||
class CGTownInstance;
|
||||
class CGHeroInstance;
|
||||
@ -32,12 +33,6 @@ namespace BattlePerspective
|
||||
};
|
||||
}
|
||||
|
||||
namespace BattleSide
|
||||
{
|
||||
enum {ATTACKER = 0, DEFENDER = 1};
|
||||
}
|
||||
|
||||
|
||||
class DLL_LINKAGE CBattleInfoEssentials : public virtual CCallbackBase
|
||||
{
|
||||
protected:
|
||||
@ -71,7 +66,8 @@ public:
|
||||
si8 battleGetTacticsSide() const; //returns which side is in tactics phase, undefined if none (?)
|
||||
bool battleCanFlee(PlayerColor player) const;
|
||||
bool battleCanSurrender(PlayerColor player) const;
|
||||
si8 playerToSide(PlayerColor player) const;
|
||||
ui8 otherSide(ui8 side) const;
|
||||
BattleSideOpt playerToSide(PlayerColor player) const;
|
||||
bool playerHasAccessToHeroInfo(PlayerColor player, const CGHeroInstance * h) const;
|
||||
ui8 battleGetSiegeLevel() const; //returns 0 when there is no siege, 1 if fort, 2 is citadel, 3 is castle
|
||||
bool battleHasHero(ui8 side) const;
|
||||
|
@ -17,16 +17,17 @@ ReachabilityInfo::Parameters::Parameters()
|
||||
{
|
||||
stack = nullptr;
|
||||
perspective = BattlePerspective::ALL_KNOWING;
|
||||
attackerOwned = doubleWide = flying = false;
|
||||
side = 0;
|
||||
doubleWide = flying = false;
|
||||
}
|
||||
|
||||
ReachabilityInfo::Parameters::Parameters(const CStack * Stack)
|
||||
{
|
||||
stack = Stack;
|
||||
perspective = (BattlePerspective::BattlePerspective)(!Stack->attackerOwned);
|
||||
perspective = (BattlePerspective::BattlePerspective)(Stack->side);
|
||||
startPosition = Stack->position;
|
||||
doubleWide = stack->doubleWide();
|
||||
attackerOwned = stack->attackerOwned;
|
||||
side = stack->side;
|
||||
flying = stack->hasBonusOfType(Bonus::FLYING);
|
||||
knownAccessible = stack->getHexes();
|
||||
}
|
||||
|
@ -27,7 +27,7 @@ struct DLL_LINKAGE ReachabilityInfo
|
||||
{
|
||||
const CStack * stack; //stack for which calculation is mage => not required (kept for debugging mostly), following variables are enough
|
||||
|
||||
bool attackerOwned;
|
||||
ui8 side;
|
||||
bool doubleWide;
|
||||
bool flying;
|
||||
std::vector<BattleHex> knownAccessible; //hexes that will be treated as accessible, even if they're occupied by stack (by default - tiles occupied by stack we do reachability for, so it doesn't block itself)
|
||||
|
@ -104,7 +104,7 @@ std::vector<const CStack *> ChainLightningMechanics::calculateAffectedStacks(con
|
||||
}
|
||||
if(possibleHexes.empty()) //not enough targets
|
||||
break;
|
||||
lightningHex = BattleHex::getClosestTile(stack->attackerOwned, lightningHex, possibleHexes);
|
||||
lightningHex = BattleHex::getClosestTile(stack->side, lightningHex, possibleHexes);
|
||||
}
|
||||
|
||||
return res;
|
||||
@ -121,13 +121,12 @@ void CloneMechanics::applyBattleEffects(const SpellCastEnvironment * env, const
|
||||
env->complain ("No target stack to clone!");
|
||||
return;
|
||||
}
|
||||
const int attacker = !(bool)parameters.casterSide;
|
||||
|
||||
BattleStackAdded bsa;
|
||||
bsa.creID = clonedStack->type->idNumber;
|
||||
bsa.attacker = attacker;
|
||||
bsa.side = parameters.casterSide;
|
||||
bsa.summoned = true;
|
||||
bsa.pos = parameters.cb->getAvaliableHex(bsa.creID, attacker); //TODO: unify it
|
||||
bsa.pos = parameters.cb->getAvaliableHex(bsa.creID, parameters.casterSide);
|
||||
bsa.amount = clonedStack->count;
|
||||
env->sendAndApply(&bsa);
|
||||
|
||||
@ -370,8 +369,11 @@ ESpellCastProblem::ESpellCastProblem EarthquakeMechanics::canBeCast(const CBattl
|
||||
CSpell::TargetInfo ti(owner, caster->getSpellSchoolLevel(owner));
|
||||
if(ti.smart)
|
||||
{
|
||||
const auto side = cb->playerToSide(caster->getOwner());
|
||||
if(!side)
|
||||
return ESpellCastProblem::INVALID;
|
||||
//if spell targeting is smart, then only attacker can use it
|
||||
if(cb->playerToSide(caster->getOwner()) != BattleSide::ATTACKER)
|
||||
if(side.get() != BattleSide::ATTACKER)
|
||||
return ESpellCastProblem::NO_APPROPRIATE_TARGET;
|
||||
}
|
||||
|
||||
@ -407,13 +409,13 @@ ESpellCastProblem::ESpellCastProblem HypnotizeMechanics::isImmuneByStack(const I
|
||||
///ObstacleMechanics
|
||||
ESpellCastProblem::ESpellCastProblem ObstacleMechanics::canBeCast(const CBattleInfoCallback * cb, const SpellTargetingContext & ctx) const
|
||||
{
|
||||
const si8 side = cb->playerToSide(ctx.caster->getOwner());
|
||||
if(side < 0)
|
||||
const auto side = cb->playerToSide(ctx.caster->getOwner());
|
||||
if(!side)
|
||||
return ESpellCastProblem::INVALID;
|
||||
|
||||
bool hexesOutsideBattlefield = false;
|
||||
|
||||
auto tilesThatMustBeClear = owner->rangeInHexes(ctx.destination, ctx.schoolLvl, side, &hexesOutsideBattlefield);
|
||||
auto tilesThatMustBeClear = owner->rangeInHexes(ctx.destination, ctx.schoolLvl, side.get(), &hexesOutsideBattlefield);
|
||||
|
||||
for(const BattleHex & hex : tilesThatMustBeClear)
|
||||
if(!isHexAviable(cb, hex, ctx.ti.clearAffected))
|
||||
@ -499,11 +501,11 @@ void PatchObstacleMechanics::applyBattleEffects(const SpellCastEnvironment * env
|
||||
ESpellCastProblem::ESpellCastProblem LandMineMechanics::canBeCast(const CBattleInfoCallback * cb, const ECastingMode::ECastingMode mode, const ISpellCaster * caster) const
|
||||
{
|
||||
//LandMine are useless if enemy has native stack and can see mines, check for LandMine damage immunity is done in general way by CSpell
|
||||
const si8 playerSide = cb->playerToSide(caster->getOwner());
|
||||
if(playerSide < 0)
|
||||
const auto side = cb->playerToSide(caster->getOwner());
|
||||
if(!side)
|
||||
return ESpellCastProblem::INVALID;
|
||||
|
||||
const si8 otherSide = !playerSide;
|
||||
const ui8 otherSide = cb->otherSide(side.get());
|
||||
|
||||
if(cb->battleHasNativeStack(otherSide))
|
||||
return ESpellCastProblem::NO_APPROPRIATE_TARGET;
|
||||
@ -887,9 +889,9 @@ void SummonMechanics::applyBattleEffects(const SpellCastEnvironment * env, const
|
||||
{
|
||||
BattleStackAdded bsa;
|
||||
bsa.creID = creatureToSummon;
|
||||
bsa.attacker = !(bool)parameters.casterSide;
|
||||
bsa.side = parameters.casterSide;
|
||||
bsa.summoned = true;
|
||||
bsa.pos = parameters.cb->getAvaliableHex(creatureToSummon, !(bool)parameters.casterSide); //TODO: unify it
|
||||
bsa.pos = parameters.cb->getAvaliableHex(creatureToSummon, parameters.casterSide); //TODO: unify it
|
||||
|
||||
//TODO stack casting -> probably power will be zero; set the proper number of creatures manually
|
||||
int percentBonus = parameters.casterHero ? parameters.casterHero->valOfBonuses(Bonus::SPECIFIC_SPELL_DAMAGE, owner->id.toEnum()) : 0;
|
||||
|
@ -649,10 +649,10 @@ std::vector<const CStack *> DefaultSpellMechanics::calculateAffectedStacks(const
|
||||
{
|
||||
std::set<const CStack* > attackedCres;//std::set to exclude multiple occurrences of two hex creatures
|
||||
|
||||
const si8 playerSide = cb->playerToSide(ctx.caster->getOwner());
|
||||
if(playerSide < 0)
|
||||
const auto side = cb->playerToSide(ctx.caster->getOwner());
|
||||
if(!side)
|
||||
return std::vector<const CStack *>();
|
||||
auto attackedHexes = rangeInHexes(ctx.destination, ctx.schoolLvl, playerSide);
|
||||
auto attackedHexes = rangeInHexes(ctx.destination, ctx.schoolLvl, side.get());
|
||||
|
||||
//hackfix for banned creature massive spells
|
||||
if(!ctx.ti.massive && owner->getLevelInfo(ctx.schoolLvl).range == "X")
|
||||
|
@ -186,15 +186,15 @@ ESpellCastProblem::ESpellCastProblem CSpell::canBeCast(const CBattleInfoCallback
|
||||
return ESpellCastProblem::ADVMAP_SPELL_INSTEAD_OF_BATTLE_SPELL;
|
||||
|
||||
const PlayerColor player = caster->getOwner();
|
||||
const si8 side = cb->playerToSide(player);
|
||||
const auto side = cb->playerToSide(player);
|
||||
|
||||
if(side < 0)
|
||||
if(!side)
|
||||
return ESpellCastProblem::INVALID;
|
||||
|
||||
//effect like Recanter's Cloak. Blocks also passive casting.
|
||||
//TODO: check creature abilities to block
|
||||
//TODO: check any possible caster
|
||||
if(cb->battleMaxSpellLevel(side) < level)
|
||||
if(cb->battleMaxSpellLevel(side.get()) < level)
|
||||
return ESpellCastProblem::SPELL_LEVEL_LIMIT_EXCEEDED;
|
||||
|
||||
const ESpellCastProblem::ESpellCastProblem specificProblem = mechanics->canBeCast(cb, mode, caster);
|
||||
|
@ -138,11 +138,13 @@ static void giveExp(BattleResult &r)
|
||||
}
|
||||
}
|
||||
|
||||
static void summonGuardiansHelper(std::vector<BattleHex> & output, const BattleHex & targetPosition, bool targetIsAttacker, bool targetIsTwoHex) //return hexes for summoning two hex monsters in output, target = unit to guard
|
||||
static void summonGuardiansHelper(std::vector<BattleHex> & output, const BattleHex & targetPosition, ui8 side, bool targetIsTwoHex) //return hexes for summoning two hex monsters in output, target = unit to guard
|
||||
{
|
||||
int x = targetPosition.getX();
|
||||
int y = targetPosition.getY();
|
||||
|
||||
const bool targetIsAttacker = side == BattleSide::ATTACKER;
|
||||
|
||||
if (targetIsAttacker) //handle front guardians, TODO: should we handle situation when units start battle near opposite side of the battlefield? Cannot happen in normal H3...
|
||||
BattleHex::checkAndPush(targetPosition.cloneInDirection(BattleHex::EDir::RIGHT, false).cloneInDirection(BattleHex::EDir::RIGHT, false), output);
|
||||
else
|
||||
@ -1160,21 +1162,15 @@ int CGameHandler::moveStack(int stack, BattleHex dest)
|
||||
auto accessibility = getAccesibility(curStack);
|
||||
|
||||
//shifting destination (if we have double wide stack and we can occupy dest but not be exactly there)
|
||||
if (!stackAtEnd && curStack->doubleWide() && !accessibility.accessible(dest, curStack))
|
||||
if(!stackAtEnd && curStack->doubleWide() && !accessibility.accessible(dest, curStack))
|
||||
{
|
||||
if (curStack->attackerOwned)
|
||||
{
|
||||
if (accessibility.accessible(dest+1, curStack))
|
||||
dest += BattleHex::RIGHT;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (accessibility.accessible(dest-1, curStack))
|
||||
dest += BattleHex::LEFT;
|
||||
}
|
||||
BattleHex shifted = dest.cloneInDirection(curStack->destShiftDir());
|
||||
|
||||
if(accessibility.accessible(shifted, curStack))
|
||||
dest = shifted;
|
||||
}
|
||||
|
||||
if ((stackAtEnd && stackAtEnd!=curStack && stackAtEnd->alive()) || !accessibility.accessible(dest, curStack))
|
||||
if((stackAtEnd && stackAtEnd!=curStack && stackAtEnd->alive()) || !accessibility.accessible(dest, curStack))
|
||||
{
|
||||
complain("Given destination is not accessible!");
|
||||
return 0;
|
||||
@ -1182,7 +1178,7 @@ int CGameHandler::moveStack(int stack, BattleHex dest)
|
||||
|
||||
bool canUseGate = false;
|
||||
auto dbState = gs->curB->si.gateState;
|
||||
if (battleGetSiegeLevel() > 0 && !curStack->attackerOwned &&
|
||||
if(battleGetSiegeLevel() > 0 && curStack->side == BattleSide::DEFENDER &&
|
||||
dbState != EGateState::DESTROYED &&
|
||||
dbState != EGateState::BLOCKED)
|
||||
{
|
||||
@ -3857,7 +3853,7 @@ bool CGameHandler::makeBattleAction(BattleAction &ba)
|
||||
|
||||
if (battleTacticDist())
|
||||
{
|
||||
if (stack && !stack->attackerOwned != battleGetTacticsSide())
|
||||
if (stack && stack->side != battleGetTacticsSide())
|
||||
{
|
||||
complain("This is not a stack of side that has tactics!");
|
||||
return false;
|
||||
@ -3951,10 +3947,8 @@ bool CGameHandler::makeBattleAction(BattleAction &ba)
|
||||
|
||||
logGlobal->trace("%s will attack %s", stack->nodeName(), destinationStack->nodeName());
|
||||
|
||||
if (stack->position != ba.destinationTile //we wasn't able to reach destination tile
|
||||
&& !(stack->doubleWide()
|
||||
&& (stack->position == ba.destinationTile + (stack->attackerOwned ? +1 : -1))
|
||||
) //nor occupy specified hex
|
||||
if(stack->position != ba.destinationTile //we wasn't able to reach destination tile
|
||||
&& !(stack->doubleWide() && (stack->position == ba.destinationTile.cloneInDirection(stack->destShiftDir()))) //nor occupy specified hex
|
||||
)
|
||||
{
|
||||
complain("We cannot move this stack to its destination " + stack->getCreature()->namePl);
|
||||
@ -4292,7 +4286,7 @@ bool CGameHandler::makeBattleAction(BattleAction &ba)
|
||||
|
||||
CreatureID summonedType(summoner->getBonusLocalFirst(Selector::type(Bonus::DAEMON_SUMMONING))->subtype);//in case summoner can summon more than one type of monsters... scream!
|
||||
BattleStackAdded bsa;
|
||||
bsa.attacker = summoner->attackerOwned;
|
||||
bsa.side = summoner->side;
|
||||
|
||||
bsa.creID = summonedType;
|
||||
ui64 risedHp = summoner->count * summoner->valOfBonuses(Bonus::DAEMON_SUMMONING, bsa.creID.toEnum());
|
||||
@ -4303,7 +4297,7 @@ bool CGameHandler::makeBattleAction(BattleAction &ba)
|
||||
|
||||
bsa.amount = std::min(canRiseAmount, destStack->baseAmount);
|
||||
|
||||
bsa.pos = gs->curB->getAvaliableHex(bsa.creID, bsa.attacker, destStack->position);
|
||||
bsa.pos = gs->curB->getAvaliableHex(bsa.creID, bsa.side, destStack->position);
|
||||
bsa.summoned = false;
|
||||
|
||||
if (bsa.amount) //there's rare possibility single creature cannot rise desired type
|
||||
@ -4661,7 +4655,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 enemy hero is 1 (true)
|
||||
const ui8 side = curStack->side; //if enemy is defending (false = 0), side of enemy hero is 1 (true)
|
||||
const CGHeroInstance *hero = gs->curB->battleGetFightingHero(side);//FIXME: there may be no hero - landmines in Tower
|
||||
|
||||
if (obstacle.obstacleType == CObstacleInstance::MOAT)
|
||||
@ -5416,6 +5410,7 @@ void CGameHandler::handleAfterAttackCasting(const BattleAttack & bat)
|
||||
|
||||
BattleStackAdded resurrectInfo;
|
||||
resurrectInfo.pos = defender->position;
|
||||
resurrectInfo.side = defender->side;
|
||||
|
||||
if (bonusAdditionalInfo != -1)
|
||||
resurrectInfo.creID = (CreatureID)bonusAdditionalInfo;
|
||||
@ -5515,7 +5510,7 @@ void CGameHandler::makeStackDoNothing(const CStack * next)
|
||||
doNothing.actionType = Battle::NO_ACTION;
|
||||
doNothing.additionalInfo = 0;
|
||||
doNothing.destinationTile = -1;
|
||||
doNothing.side = !next->attackerOwned;
|
||||
doNothing.side = next->side;
|
||||
doNothing.stackNumber = next->ID;
|
||||
|
||||
makeAutomaticAction(next, doNothing);
|
||||
@ -5708,16 +5703,16 @@ void CGameHandler::runBattle()
|
||||
if (!guardianIsBig)
|
||||
targetHexes = stack->getSurroundingHexes();
|
||||
else
|
||||
summonGuardiansHelper(targetHexes, stack->position, stack->attackerOwned, targetIsBig);
|
||||
summonGuardiansHelper(targetHexes, stack->position, stack->side, targetIsBig);
|
||||
|
||||
for (auto hex : targetHexes)
|
||||
{
|
||||
if (accessibility.accessible(hex, guardianIsBig, stack->attackerOwned)) //without this multiple creatures can occupy one hex
|
||||
if (accessibility.accessible(hex, guardianIsBig, stack->side)) //without this multiple creatures can occupy one hex
|
||||
{
|
||||
BattleStackAdded newStack;
|
||||
newStack.amount = std::max(1, (int)(stack->count * 0.01 * summonInfo->val));
|
||||
newStack.creID = creatureData.num;
|
||||
newStack.attacker = stack->attackerOwned;
|
||||
newStack.side = stack->side;
|
||||
newStack.summoned = true;
|
||||
newStack.pos = hex.hex;
|
||||
sendAndApply(&newStack);
|
||||
@ -5808,7 +5803,7 @@ void CGameHandler::runBattle()
|
||||
BattleAction ba;
|
||||
ba.actionType = Battle::BAD_MORALE;
|
||||
ba.additionalInfo = 1;
|
||||
ba.side = !next->attackerOwned;
|
||||
ba.side = next->side;
|
||||
ba.stackNumber = next->ID;
|
||||
|
||||
makeAutomaticAction(next, ba);
|
||||
@ -5819,12 +5814,12 @@ void CGameHandler::runBattle()
|
||||
if (next->hasBonusOfType(Bonus::ATTACKS_NEAREST_CREATURE)) //while in berserk
|
||||
{
|
||||
logGlobal->debug("Handle Berserk effect");
|
||||
std::pair<const CStack *, int> attackInfo = curB.getNearestStack(next, boost::logic::indeterminate);
|
||||
std::pair<const CStack *, int> attackInfo = curB.getNearestStack(next, boost::none);
|
||||
if (attackInfo.first != nullptr)
|
||||
{
|
||||
BattleAction attack;
|
||||
attack.actionType = Battle::WALK_AND_ATTACK;
|
||||
attack.side = !next->attackerOwned;
|
||||
attack.side = next->side;
|
||||
attack.stackNumber = next->ID;
|
||||
attack.additionalInfo = attackInfo.first->position;
|
||||
attack.destinationTile = attackInfo.second;
|
||||
@ -5847,7 +5842,7 @@ void CGameHandler::runBattle()
|
||||
{
|
||||
BattleAction attack;
|
||||
attack.actionType = Battle::SHOOT;
|
||||
attack.side = !next->attackerOwned;
|
||||
attack.side = next->side;
|
||||
attack.stackNumber = next->ID;
|
||||
|
||||
for (auto & elem : gs->curB->stacks)
|
||||
@ -5880,7 +5875,7 @@ void CGameHandler::runBattle()
|
||||
getRandomGenerator());
|
||||
attack.actionType = Battle::CATAPULT;
|
||||
attack.additionalInfo = 0;
|
||||
attack.side = !next->attackerOwned;
|
||||
attack.side = next->side;
|
||||
attack.stackNumber = next->ID;
|
||||
|
||||
makeAutomaticAction(next, attack);
|
||||
@ -5910,7 +5905,7 @@ void CGameHandler::runBattle()
|
||||
heal.actionType = Battle::STACK_HEAL;
|
||||
heal.additionalInfo = 0;
|
||||
heal.destinationTile = toBeHealed->position;
|
||||
heal.side = !next->attackerOwned;
|
||||
heal.side = next->side;
|
||||
heal.stackNumber = next->ID;
|
||||
|
||||
makeAutomaticAction(next, heal);
|
||||
|
@ -91,16 +91,16 @@ BOOST_AUTO_TEST_CASE(getClosestTile)
|
||||
possibilities.insert(119);
|
||||
possibilities.insert(186);
|
||||
|
||||
BOOST_TEST(mainHex.getClosestTile(true,mainHex,possibilities)==3);
|
||||
BOOST_TEST(mainHex.getClosestTile(0,mainHex,possibilities)==3);
|
||||
mainHex = 139;
|
||||
BOOST_TEST(mainHex.getClosestTile(false,mainHex,possibilities)==119);
|
||||
BOOST_TEST(mainHex.getClosestTile(1,mainHex,possibilities)==119);
|
||||
mainHex = 16;
|
||||
BOOST_TEST(mainHex.getClosestTile(false,mainHex,possibilities)==100);
|
||||
BOOST_TEST(mainHex.getClosestTile(1,mainHex,possibilities)==100);
|
||||
mainHex = 166;
|
||||
BOOST_TEST(mainHex.getClosestTile(true,mainHex,possibilities)==186);
|
||||
BOOST_TEST(mainHex.getClosestTile(0,mainHex,possibilities)==186);
|
||||
mainHex = 76;
|
||||
BOOST_TEST(mainHex.getClosestTile(false,mainHex,possibilities)==3);
|
||||
BOOST_TEST(mainHex.getClosestTile(true,mainHex,possibilities)==100);
|
||||
BOOST_TEST(mainHex.getClosestTile(1,mainHex,possibilities)==3);
|
||||
BOOST_TEST(mainHex.getClosestTile(0,mainHex,possibilities)==100);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(moveEDir)
|
||||
@ -118,6 +118,8 @@ BOOST_AUTO_TEST_CASE(moveEDir)
|
||||
BOOST_TEST(mainHex==3);
|
||||
mainHex.moveInDirection(BattleHex::EDir::BOTTOM_LEFT);
|
||||
BOOST_TEST(mainHex==20);
|
||||
mainHex.moveInDirection(BattleHex::EDir::NONE);
|
||||
BOOST_TEST(mainHex==20);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END()
|
||||
|
Loading…
Reference in New Issue
Block a user