1
0
mirror of https://github.com/vcmi/vcmi.git synced 2024-12-24 22:14:36 +02:00

FIRST_STRIKE now supports ranged / melee subtypes, BLOCKS_RETALIATION

will properly block FIRST_STRIKE
This commit is contained in:
Ivan Savenko 2024-01-13 15:55:38 +02:00
parent bb670cfb82
commit fc6a9924ee
3 changed files with 16 additions and 4 deletions

View File

@ -587,6 +587,11 @@ Affected unit will attack units on all hexes that surround attacked hex
Affected unit will retaliate before enemy attacks, if able
- subtype:
- damageTypeMelee: only melee attacks affected
- damageTypeRanged: only ranged attacks affected. Note that unit also requires ability to retaliate in ranged, such as RANGED_RETALIATION bonus
- damageTypeAll: any attacks are affected
### SHOOTS_ALL_ADJACENT
Affected unit will attack units on all hexes that surround attacked hex in ranged attacks

View File

@ -537,6 +537,7 @@ static void loadBonusSubtype(BonusSubtypeID & subtype, BonusType type, const Jso
case BonusType::NEGATE_ALL_NATURAL_IMMUNITIES:
case BonusType::CREATURE_DAMAGE:
case BonusType::FLYING:
case BonusType::FIRST_STRIKE:
case BonusType::GENERAL_DAMAGE_REDUCTION:
case BonusType::PERCENTAGE_DAMAGE_BOOST:
case BonusType::SOUL_STEAL:

View File

@ -268,7 +268,9 @@ bool BattleActionProcessor::doAttackAction(const CBattleInfoCallback & battle, c
totalAttacks += attackingHero->valOfBonuses(BonusType::HERO_GRANTS_ATTACKS, BonusSubtypeID(stack->creatureId()));
}
const bool firstStrike = destinationStack->hasBonusOfType(BonusType::FIRST_STRIKE);
static const auto firstStrikeSelector = Selector::typeSubtype(BonusType::FIRST_STRIKE, BonusCustomSubtype::damageTypeAll).Or(Selector::typeSubtype(BonusType::FIRST_STRIKE, BonusCustomSubtype::damageTypeMelee));
const bool firstStrike = destinationStack->hasBonus(firstStrikeSelector);
const bool retaliation = destinationStack->ableToRetaliate();
bool ferocityApplied = false;
int32_t defenderInitialQuantity = destinationStack->getCount();
@ -276,7 +278,7 @@ bool BattleActionProcessor::doAttackAction(const CBattleInfoCallback & battle, c
for (int i = 0; i < totalAttacks; ++i)
{
//first strike
if(i == 0 && firstStrike && retaliation)
if(i == 0 && firstStrike && retaliation && !stack->hasBonusOfType(BonusType::BLOCKS_RETALIATION))
{
makeAttack(battle, destinationStack, stack, 0, stack->getPosition(), true, false, true);
}
@ -353,7 +355,11 @@ bool BattleActionProcessor::doShootAction(const CBattleInfoCallback & battle, co
return false;
}
makeAttack(battle, stack, destinationStack, 0, destination, true, true, false);
static const auto firstStrikeSelector = Selector::typeSubtype(BonusType::FIRST_STRIKE, BonusCustomSubtype::damageTypeAll).Or(Selector::typeSubtype(BonusType::FIRST_STRIKE, BonusCustomSubtype::damageTypeRanged));
const bool firstStrike = destinationStack->hasBonus(firstStrikeSelector);
if (!firstStrike)
makeAttack(battle, stack, destinationStack, 0, destination, true, true, false);
//ranged counterattack
if (destinationStack->hasBonusOfType(BonusType::RANGED_RETALIATION)
@ -375,7 +381,7 @@ bool BattleActionProcessor::doShootAction(const CBattleInfoCallback & battle, co
totalRangedAttacks += attackingHero->valOfBonuses(BonusType::HERO_GRANTS_ATTACKS, BonusSubtypeID(stack->creatureId()));
}
for(int i = 1; i < totalRangedAttacks; ++i)
for(int i = firstStrike ? 0:1; i < totalRangedAttacks; ++i)
{
if(
stack->alive()