mirror of
https://github.com/vcmi/vcmi.git
synced 2024-12-26 22:57:00 +02:00
fix 1556
This commit is contained in:
parent
e5b4b2341d
commit
466ddb37b3
@ -643,7 +643,7 @@ AttackPossibility AttackPossibility::evaluate(const BattleAttackInfo &AttackInfo
|
|||||||
auto attacker = AttackInfo.attacker;
|
auto attacker = AttackInfo.attacker;
|
||||||
auto enemy = AttackInfo.defender;
|
auto enemy = AttackInfo.defender;
|
||||||
|
|
||||||
const int remainingCounterAttacks = getValOr(state.counterAttacksLeft, enemy, enemy->counterAttacks);
|
const int remainingCounterAttacks = getValOr(state.counterAttacksLeft, enemy, enemy->counterAttacksRemaining());
|
||||||
const bool counterAttacksBlocked = attacker->hasBonusOfType(Bonus::BLOCKS_RETALIATION) || enemy->hasBonusOfType(Bonus::NO_RETALIATION);
|
const bool counterAttacksBlocked = attacker->hasBonusOfType(Bonus::BLOCKS_RETALIATION) || enemy->hasBonusOfType(Bonus::NO_RETALIATION);
|
||||||
const int totalAttacks = 1 + AttackInfo.attackerBonuses->getBonuses(Selector::type(Bonus::ADDITIONAL_ATTACK), (Selector::effectRange (Bonus::NO_LIMIT).Or(Selector::effectRange(Bonus::ONLY_MELEE_FIGHT))))->totalValue();
|
const int totalAttacks = 1 + AttackInfo.attackerBonuses->getBonuses(Selector::type(Bonus::ADDITIONAL_ATTACK), (Selector::effectRange (Bonus::NO_LIMIT).Or(Selector::effectRange(Bonus::ONLY_MELEE_FIGHT))))->totalValue();
|
||||||
|
|
||||||
|
@ -763,7 +763,7 @@ CGHeroInstance * BattleInfo::battleGetFightingHero(ui8 side) const
|
|||||||
|
|
||||||
CStack::CStack(const CStackInstance *Base, PlayerColor O, int I, bool AO, SlotID S)
|
CStack::CStack(const CStackInstance *Base, PlayerColor O, int I, bool AO, SlotID S)
|
||||||
: base(Base), ID(I), owner(O), slot(S), attackerOwned(AO),
|
: base(Base), ID(I), owner(O), slot(S), attackerOwned(AO),
|
||||||
counterAttacks(1)
|
counterAttacksPerformed(0),counterAttacksTotalCache(0)
|
||||||
{
|
{
|
||||||
assert(base);
|
assert(base);
|
||||||
type = base->type;
|
type = base->type;
|
||||||
@ -776,7 +776,7 @@ CStack::CStack()
|
|||||||
setNodeType(STACK_BATTLE);
|
setNodeType(STACK_BATTLE);
|
||||||
}
|
}
|
||||||
CStack::CStack(const CStackBasicDescriptor *stack, PlayerColor O, int I, bool AO, SlotID S)
|
CStack::CStack(const CStackBasicDescriptor *stack, PlayerColor O, int I, bool AO, SlotID S)
|
||||||
: base(nullptr), ID(I), owner(O), slot(S), attackerOwned(AO), counterAttacks(1)
|
: base(nullptr), ID(I), owner(O), slot(S), attackerOwned(AO), counterAttacksPerformed(0)
|
||||||
{
|
{
|
||||||
type = stack->type;
|
type = stack->type;
|
||||||
count = baseAmount = stack->count;
|
count = baseAmount = stack->count;
|
||||||
@ -794,7 +794,8 @@ void CStack::init()
|
|||||||
slot = SlotID(255);
|
slot = SlotID(255);
|
||||||
attackerOwned = false;
|
attackerOwned = false;
|
||||||
position = BattleHex();
|
position = BattleHex();
|
||||||
counterAttacks = -1;
|
counterAttacksPerformed = 0;
|
||||||
|
counterAttacksTotalCache = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CStack::postInit()
|
void CStack::postInit()
|
||||||
@ -804,7 +805,8 @@ void CStack::postInit()
|
|||||||
|
|
||||||
firstHPleft = MaxHealth();
|
firstHPleft = MaxHealth();
|
||||||
shots = getCreature()->valOfBonuses(Bonus::SHOTS);
|
shots = getCreature()->valOfBonuses(Bonus::SHOTS);
|
||||||
counterAttacks = 1 + valOfBonuses(Bonus::ADDITIONAL_RETALIATION);
|
counterAttacksPerformed = 0;
|
||||||
|
counterAttacksTotalCache = 0;
|
||||||
casts = valOfBonuses(Bonus::CASTS);
|
casts = valOfBonuses(Bonus::CASTS);
|
||||||
resurrected = 0;
|
resurrected = 0;
|
||||||
}
|
}
|
||||||
@ -1129,12 +1131,25 @@ bool CStack::isMeleeAttackPossible(const CStack * attacker, const CStack * defen
|
|||||||
bool CStack::ableToRetaliate() const //FIXME: crash after clone is killed
|
bool CStack::ableToRetaliate() const //FIXME: crash after clone is killed
|
||||||
{
|
{
|
||||||
return alive()
|
return alive()
|
||||||
&& (counterAttacks > 0 || hasBonusOfType(Bonus::UNLIMITED_RETALIATIONS))
|
&& (counterAttacksPerformed < counterAttacksTotal() || hasBonusOfType(Bonus::UNLIMITED_RETALIATIONS))
|
||||||
&& !hasBonusOfType(Bonus::SIEGE_WEAPON)
|
&& !hasBonusOfType(Bonus::SIEGE_WEAPON)
|
||||||
&& !hasBonusOfType(Bonus::HYPNOTIZED)
|
&& !hasBonusOfType(Bonus::HYPNOTIZED)
|
||||||
&& !hasBonusOfType(Bonus::NO_RETALIATION);
|
&& !hasBonusOfType(Bonus::NO_RETALIATION);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ui8 CStack::counterAttacksTotal() const
|
||||||
|
{
|
||||||
|
//after dispell bonus should remain during current round
|
||||||
|
ui8 val = 1 + valOfBonuses(Bonus::ADDITIONAL_RETALIATION);
|
||||||
|
vstd::amax(counterAttacksTotalCache, val);
|
||||||
|
return counterAttacksTotalCache;
|
||||||
|
}
|
||||||
|
|
||||||
|
si8 CStack::counterAttacksRemaining() const
|
||||||
|
{
|
||||||
|
return counterAttacksTotal() - counterAttacksPerformed;
|
||||||
|
}
|
||||||
|
|
||||||
std::string CStack::getName() const
|
std::string CStack::getName() const
|
||||||
{
|
{
|
||||||
return (count > 1) ? type->namePl : type->nameSing; //War machines can't use base
|
return (count > 1) ? type->namePl : type->nameSing; //War machines can't use base
|
||||||
|
@ -171,7 +171,10 @@ public:
|
|||||||
SlotID slot; //slot - position in garrison (may be 255 for neutrals/called creatures)
|
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)
|
bool attackerOwned; //if true, this stack is owned by attakcer (this one from left hand side of battle)
|
||||||
BattleHex position; //position on battlefield; -2 - keep, -3 - lower tower, -4 - upper tower
|
BattleHex position; //position on battlefield; -2 - keep, -3 - lower tower, -4 - upper tower
|
||||||
ui8 counterAttacks; //how many counter attacks can be performed more in this turn (by default set at the beginning of the round to 1)
|
///how many times this stack has been counterattacked this round
|
||||||
|
ui8 counterAttacksPerformed;
|
||||||
|
///cached total count of counterattacks; should be cleared each round;do not serialize
|
||||||
|
mutable ui8 counterAttacksTotalCache;
|
||||||
si16 shots; //how many shots left
|
si16 shots; //how many shots left
|
||||||
ui8 casts; //how many casts left
|
ui8 casts; //how many casts left
|
||||||
TQuantity resurrected; // these units will be taken back after battle is over
|
TQuantity resurrected; // these units will be taken back after battle is over
|
||||||
@ -191,6 +194,10 @@ public:
|
|||||||
std::string getName() const; //plural or singular
|
std::string getName() const; //plural or singular
|
||||||
bool willMove(int turn = 0) const; //if stack has remaining move this turn
|
bool willMove(int turn = 0) const; //if stack has remaining move this turn
|
||||||
bool ableToRetaliate() const; //if stack can retaliate after attacked
|
bool ableToRetaliate() const; //if stack can retaliate after attacked
|
||||||
|
///how many times this stack can counterattack in one round
|
||||||
|
ui8 counterAttacksTotal() const;
|
||||||
|
///how many times this stack can counterattack in one round more
|
||||||
|
si8 counterAttacksRemaining() const;
|
||||||
bool moved(int turn = 0) const; //if stack was already moved this turn
|
bool moved(int turn = 0) const; //if stack was already moved this turn
|
||||||
bool waited(int turn = 0) const;
|
bool waited(int turn = 0) const;
|
||||||
bool canMove(int turn = 0) const; //if stack can move
|
bool canMove(int turn = 0) const; //if stack can move
|
||||||
@ -231,7 +238,7 @@ public:
|
|||||||
assert(isIndependentNode());
|
assert(isIndependentNode());
|
||||||
h & static_cast<CBonusSystemNode&>(*this);
|
h & static_cast<CBonusSystemNode&>(*this);
|
||||||
h & static_cast<CStackBasicDescriptor&>(*this);
|
h & static_cast<CStackBasicDescriptor&>(*this);
|
||||||
h & ID & baseAmount & firstHPleft & owner & slot & attackerOwned & position & state & counterAttacks
|
h & ID & baseAmount & firstHPleft & owner & slot & attackerOwned & position & state & counterAttacksPerformed
|
||||||
& shots & casts & count & resurrected;
|
& shots & casts & count & resurrected;
|
||||||
|
|
||||||
const CArmedInstance *army = (base ? base->armyObj : nullptr);
|
const CArmedInstance *army = (base ? base->armyObj : nullptr);
|
||||||
|
@ -1095,7 +1095,8 @@ DLL_LINKAGE void BattleNextRound::applyGs( CGameState *gs )
|
|||||||
s->state -= EBattleStackState::HAD_MORALE;
|
s->state -= EBattleStackState::HAD_MORALE;
|
||||||
s->state -= EBattleStackState::FEAR;
|
s->state -= EBattleStackState::FEAR;
|
||||||
s->state -= EBattleStackState::DRAINED_MANA;
|
s->state -= EBattleStackState::DRAINED_MANA;
|
||||||
s->counterAttacks = 1 + s->valOfBonuses(Bonus::ADDITIONAL_RETALIATION);
|
s->counterAttacksPerformed = 0;
|
||||||
|
s->counterAttacksTotalCache = 0;
|
||||||
// new turn effects
|
// new turn effects
|
||||||
s->battleTurnPassed();
|
s->battleTurnPassed();
|
||||||
}
|
}
|
||||||
@ -1255,7 +1256,7 @@ DLL_LINKAGE void BattleAttack::applyGs( CGameState *gs )
|
|||||||
{
|
{
|
||||||
CStack *attacker = gs->curB->getStack(stackAttacking);
|
CStack *attacker = gs->curB->getStack(stackAttacking);
|
||||||
if(counter())
|
if(counter())
|
||||||
attacker->counterAttacks--;
|
attacker->counterAttacksPerformed++;
|
||||||
|
|
||||||
if(shot())
|
if(shot())
|
||||||
{
|
{
|
||||||
|
Loading…
Reference in New Issue
Block a user