mirror of
https://github.com/vcmi/vcmi.git
synced 2024-12-24 22:14:36 +02:00
Add SYNERGY_TARGET and [wip]-SHOOTS_ALL_ADJACENT
This commit is contained in:
parent
1df939bf70
commit
4cab76900f
@ -150,12 +150,13 @@
|
|||||||
"description": "Immune to all Fire school spells"
|
"description": "Immune to all Fire school spells"
|
||||||
},
|
},
|
||||||
|
|
||||||
"FIRE_SHIELD": {
|
"FIRE_SHIELD":
|
||||||
"name": "Fire Shield (${val}%)",
|
{
|
||||||
"description": "Reflects part of melee damage"
|
"name": "Fire Shield (${val}%)",
|
||||||
},
|
"description": "Reflects part of melee damage"
|
||||||
|
},
|
||||||
|
|
||||||
"FIRST_STRIKE":
|
"FIRST_STRIKE":
|
||||||
{
|
{
|
||||||
"name": "First Strike",
|
"name": "First Strike",
|
||||||
"description": "This creature attacks first instead of retaliating"
|
"description": "This creature attacks first instead of retaliating"
|
||||||
@ -353,6 +354,12 @@
|
|||||||
"description": "Creature can shoot"
|
"description": "Creature can shoot"
|
||||||
},
|
},
|
||||||
|
|
||||||
|
"SHOOTS_ALL_ADJACENT":
|
||||||
|
{
|
||||||
|
"name": "Shoot all around",
|
||||||
|
"description": "This creature's ranged attacks strike all targets in a small area"
|
||||||
|
},
|
||||||
|
|
||||||
"SOUL_STEAL":
|
"SOUL_STEAL":
|
||||||
{
|
{
|
||||||
"name": "Soul Steal",
|
"name": "Soul Steal",
|
||||||
@ -407,6 +414,12 @@
|
|||||||
"description": "At battle start summons ${subtype.creature} (${val}%)"
|
"description": "At battle start summons ${subtype.creature} (${val}%)"
|
||||||
},
|
},
|
||||||
|
|
||||||
|
"SYNERGY_TARGET":
|
||||||
|
{
|
||||||
|
"name": "Synergizable",
|
||||||
|
"description": "This creature is vulnerable to synergy effect"
|
||||||
|
},
|
||||||
|
|
||||||
"TWO_HEX_ATTACK_BREATH":
|
"TWO_HEX_ATTACK_BREATH":
|
||||||
{
|
{
|
||||||
"name": "Breath",
|
"name": "Breath",
|
||||||
|
@ -235,8 +235,10 @@ private:
|
|||||||
BONUS_NAME(CATAPULT_EXTRA_SHOTS) /*val - number of additional shots, requires CATAPULT bonus to work*/\
|
BONUS_NAME(CATAPULT_EXTRA_SHOTS) /*val - number of additional shots, requires CATAPULT bonus to work*/\
|
||||||
BONUS_NAME(RANGED_RETALIATION) /*allows shooters to perform ranged retaliation*/\
|
BONUS_NAME(RANGED_RETALIATION) /*allows shooters to perform ranged retaliation*/\
|
||||||
BONUS_NAME(BLOCKS_RANGED_RETALIATION) /*disallows ranged retaliation for shooter unit, BLOCKS_RETALIATION bonus is for melee retaliation only*/\
|
BONUS_NAME(BLOCKS_RANGED_RETALIATION) /*disallows ranged retaliation for shooter unit, BLOCKS_RETALIATION bonus is for melee retaliation only*/\
|
||||||
BONUS_NAME(WIDE_BREATH) /* Kuririn skill */\
|
BONUS_NAME(WIDE_BREATH) /* initial desigh: dragon breath affecting multiple nearby hexes */\
|
||||||
BONUS_NAME(FIRST_STRIKE) /* Witchking skill */\
|
BONUS_NAME(FIRST_STRIKE) /* first counterattack, then attack if possible */\
|
||||||
|
BONUS_NAME(SYNERGY_TARGET) /* dummy skill for alternative upgrades mod */\
|
||||||
|
BONUS_NAME(SHOOTS_ALL_ADJACENT) /* H4 Cyclops-like shoot (attacks all hexes neighboring with target) without spell-like mechanics */\
|
||||||
/* end of list */
|
/* end of list */
|
||||||
|
|
||||||
|
|
||||||
|
@ -1120,7 +1120,7 @@ ReachabilityInfo CBattleInfoCallback::getFlyingReachability(const ReachabilityIn
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
AttackableTiles CBattleInfoCallback::getPotentiallyAttackableHexes (const CStack* attacker, BattleHex destinationTile, BattleHex attackerPos) const
|
AttackableTiles CBattleInfoCallback::getPotentiallyAttackableHexes (const CStack* attacker, BattleHex destinationTile, BattleHex attackerPos, bool rangedAttack) const
|
||||||
{
|
{
|
||||||
//does not return hex attacked directly
|
//does not return hex attacked directly
|
||||||
//TODO: apply rotation to two-hex attackers
|
//TODO: apply rotation to two-hex attackers
|
||||||
@ -1129,210 +1129,221 @@ AttackableTiles CBattleInfoCallback::getPotentiallyAttackableHexes (const CStack
|
|||||||
AttackableTiles at;
|
AttackableTiles at;
|
||||||
RETURN_IF_NOT_BATTLE(at);
|
RETURN_IF_NOT_BATTLE(at);
|
||||||
|
|
||||||
const int WN = GameConstants::BFIELD_WIDTH;
|
if(rangedAttack)
|
||||||
BattleHex hex = (attackerPos != BattleHex::INVALID) ? attackerPos.hex : attacker->position.hex; //real or hypothetical (cursor) position
|
|
||||||
|
|
||||||
//FIXME: dragons or cerbers can rotate before attack, making their base hex different (#1124)
|
|
||||||
bool reverse = isToReverse (hex, destinationTile, isAttacker, attacker->doubleWide(), isAttacker);
|
|
||||||
if (reverse && attacker->doubleWide())
|
|
||||||
{
|
{
|
||||||
hex = attacker->occupiedHex(hex); //the other hex stack stands on
|
if(attacker->hasBonusOfType(Bonus::SHOOTS_ALL_ADJACENT) && !vstd::contains(attackerPos.neighbouringTiles(), destinationTile))
|
||||||
}
|
|
||||||
if (attacker->hasBonusOfType(Bonus::ATTACKS_ALL_ADJACENT))
|
|
||||||
{
|
|
||||||
boost::copy (attacker->getSurroundingHexes (attackerPos), vstd::set_inserter (at.hostileCreaturePositions));
|
|
||||||
}
|
|
||||||
if (attacker->hasBonusOfType(Bonus::THREE_HEADED_ATTACK))
|
|
||||||
{
|
|
||||||
std::vector<BattleHex> hexes = attacker->getSurroundingHexes(attackerPos);
|
|
||||||
for (BattleHex tile : hexes)
|
|
||||||
{
|
{
|
||||||
if ((BattleHex::mutualPosition(tile, destinationTile) > -1 && BattleHex::mutualPosition (tile, hex) > -1)) //adjacent both to attacker's head and attacked tile
|
std::vector<BattleHex> targetHexes = destinationTile.neighbouringTiles();
|
||||||
|
targetHexes.push_back(destinationTile);
|
||||||
|
boost::copy(targetHexes, vstd::set_inserter(at.hostileCreaturePositions));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
else
|
||||||
|
{
|
||||||
|
const int WN = GameConstants::BFIELD_WIDTH;
|
||||||
|
BattleHex hex = (attackerPos != BattleHex::INVALID) ? attackerPos.hex : attacker->position.hex; //real or hypothetical (cursor) position
|
||||||
|
|
||||||
|
//FIXME: dragons or cerbers can rotate before attack, making their base hex different (#1124)
|
||||||
|
bool reverse = isToReverse(hex, destinationTile, isAttacker, attacker->doubleWide(), isAttacker);
|
||||||
|
if(reverse && attacker->doubleWide())
|
||||||
|
{
|
||||||
|
hex = attacker->occupiedHex(hex); //the other hex stack stands on
|
||||||
|
}
|
||||||
|
if(attacker->hasBonusOfType(Bonus::ATTACKS_ALL_ADJACENT))
|
||||||
|
{
|
||||||
|
boost::copy(attacker->getSurroundingHexes(attackerPos), vstd::set_inserter(at.hostileCreaturePositions));
|
||||||
|
}
|
||||||
|
if(attacker->hasBonusOfType(Bonus::THREE_HEADED_ATTACK))
|
||||||
|
{
|
||||||
|
std::vector<BattleHex> hexes = attacker->getSurroundingHexes(attackerPos);
|
||||||
|
for(BattleHex tile : hexes)
|
||||||
{
|
{
|
||||||
const CStack * st = battleGetStackByPos(tile, true);
|
if((BattleHex::mutualPosition(tile, destinationTile) > -1 && BattleHex::mutualPosition(tile, hex) > -1)) //adjacent both to attacker's head and attacked tile
|
||||||
if(st && st->owner != attacker->owner) //only hostile stacks - does it work well with Berserk?
|
|
||||||
{
|
{
|
||||||
at.hostileCreaturePositions.insert(tile);
|
const CStack * st = battleGetStackByPos(tile, true);
|
||||||
|
if(st && st->owner != attacker->owner) //only hostile stacks - does it work well with Berserk?
|
||||||
|
{
|
||||||
|
at.hostileCreaturePositions.insert(tile);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
if(attacker->hasBonusOfType(Bonus::WIDE_BREATH))
|
||||||
if (attacker->hasBonusOfType(Bonus::WIDE_BREATH))
|
|
||||||
{
|
|
||||||
std::vector<BattleHex> hexes;
|
|
||||||
const int WN = GameConstants::BFIELD_WIDTH;
|
|
||||||
// atack stand
|
|
||||||
if (hex == destinationTile.cloneInDirection(BattleHex::EDir::LEFT, false)) {
|
|
||||||
if (destinationTile.getY() % 2 == 0)
|
|
||||||
{
|
|
||||||
BattleHex::checkAndPush(destinationTile, hexes);
|
|
||||||
BattleHex::checkAndPush(destinationTile + 1, hexes);
|
|
||||||
BattleHex::checkAndPush(destinationTile + WN, hexes);
|
|
||||||
BattleHex::checkAndPush(destinationTile + WN + 1, hexes);
|
|
||||||
BattleHex::checkAndPush(destinationTile + (2 * WN) - 1, hexes);
|
|
||||||
BattleHex::checkAndPush(destinationTile + (2 * WN), hexes);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
BattleHex::checkAndPush(destinationTile, hexes);
|
|
||||||
BattleHex::checkAndPush(destinationTile + 1, hexes);
|
|
||||||
BattleHex::checkAndPush(destinationTile + WN, hexes);
|
|
||||||
BattleHex::checkAndPush(destinationTile + WN - 1, hexes);
|
|
||||||
BattleHex::checkAndPush(destinationTile + (2 * WN) - 1, hexes);
|
|
||||||
BattleHex::checkAndPush(destinationTile + (2 * WN), hexes);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
if (hex == destinationTile.cloneInDirection(BattleHex::EDir::RIGHT, false)) {
|
|
||||||
if (destinationTile.getY() % 2 == 0)
|
|
||||||
{
|
|
||||||
BattleHex::checkAndPush(destinationTile, hexes);
|
|
||||||
BattleHex::checkAndPush(destinationTile - 1, hexes);
|
|
||||||
BattleHex::checkAndPush(destinationTile + WN, hexes);
|
|
||||||
BattleHex::checkAndPush(destinationTile + WN + 1, hexes);
|
|
||||||
BattleHex::checkAndPush(destinationTile + (2 * WN), hexes);
|
|
||||||
BattleHex::checkAndPush(destinationTile + (2 * WN) + 1, hexes);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
BattleHex::checkAndPush(destinationTile, hexes);
|
|
||||||
BattleHex::checkAndPush(destinationTile - 1, hexes);
|
|
||||||
BattleHex::checkAndPush(destinationTile + WN, hexes);
|
|
||||||
BattleHex::checkAndPush(destinationTile + WN - 1, hexes);
|
|
||||||
BattleHex::checkAndPush(destinationTile + (2 * WN), hexes);
|
|
||||||
BattleHex::checkAndPush(destinationTile + (2 * WN) + 1, hexes);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// atack down
|
|
||||||
if (hex == destinationTile.cloneInDirection(BattleHex::EDir::TOP_LEFT, false)) {
|
|
||||||
if (destinationTile.getY() % 2 == 1)
|
|
||||||
{
|
|
||||||
BattleHex::checkAndPush(destinationTile, hexes);
|
|
||||||
BattleHex::checkAndPush(destinationTile - 1, hexes);
|
|
||||||
BattleHex::checkAndPush(destinationTile - 2, hexes);
|
|
||||||
BattleHex::checkAndPush(destinationTile + WN, hexes);
|
|
||||||
BattleHex::checkAndPush(destinationTile + WN - 1, hexes);
|
|
||||||
BattleHex::checkAndPush(destinationTile + WN - 2, hexes);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
BattleHex::checkAndPush(destinationTile, hexes);
|
|
||||||
BattleHex::checkAndPush(destinationTile - 1, hexes);
|
|
||||||
BattleHex::checkAndPush(destinationTile - 2, hexes);
|
|
||||||
BattleHex::checkAndPush(destinationTile + WN, hexes);
|
|
||||||
BattleHex::checkAndPush(destinationTile + WN + 1, hexes);
|
|
||||||
BattleHex::checkAndPush(destinationTile + WN - 1, hexes);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (hex == destinationTile.cloneInDirection(BattleHex::EDir::TOP_RIGHT, false)) {
|
|
||||||
|
|
||||||
if (destinationTile.getY() % 2 == 1)
|
|
||||||
{
|
|
||||||
BattleHex::checkAndPush(destinationTile, hexes);
|
|
||||||
BattleHex::checkAndPush(destinationTile + 1, hexes);
|
|
||||||
BattleHex::checkAndPush(destinationTile + 2, hexes);
|
|
||||||
BattleHex::checkAndPush(destinationTile + WN - 1, hexes);
|
|
||||||
BattleHex::checkAndPush(destinationTile + WN, hexes);
|
|
||||||
BattleHex::checkAndPush(destinationTile + WN + 1, hexes);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
BattleHex::checkAndPush(destinationTile, hexes);
|
|
||||||
BattleHex::checkAndPush(destinationTile + 1, hexes);
|
|
||||||
BattleHex::checkAndPush(destinationTile + 2, hexes);
|
|
||||||
BattleHex::checkAndPush(destinationTile + WN, hexes);
|
|
||||||
BattleHex::checkAndPush(destinationTile + WN + 1, hexes);
|
|
||||||
BattleHex::checkAndPush(destinationTile + WN + 2, hexes);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
// attack up
|
|
||||||
if (hex == destinationTile.cloneInDirection(BattleHex::EDir::BOTTOM_LEFT, false)) {
|
|
||||||
if (destinationTile.getY() % 2 == 1)
|
|
||||||
{
|
|
||||||
BattleHex::checkAndPush(destinationTile, hexes);
|
|
||||||
BattleHex::checkAndPush(destinationTile + 1, hexes);
|
|
||||||
BattleHex::checkAndPush(destinationTile + WN, hexes);
|
|
||||||
BattleHex::checkAndPush(destinationTile + WN + 1, hexes);
|
|
||||||
BattleHex::checkAndPush(destinationTile - WN, hexes);
|
|
||||||
BattleHex::checkAndPush(destinationTile - WN - 1, hexes);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
BattleHex::checkAndPush(destinationTile, hexes);
|
|
||||||
BattleHex::checkAndPush(destinationTile + 1, hexes);
|
|
||||||
BattleHex::checkAndPush(destinationTile + WN + 1, hexes);
|
|
||||||
BattleHex::checkAndPush(destinationTile + WN + 2, hexes);
|
|
||||||
BattleHex::checkAndPush(destinationTile - WN, hexes);
|
|
||||||
BattleHex::checkAndPush(destinationTile - WN + 1, hexes);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (hex == destinationTile.cloneInDirection(BattleHex::EDir::BOTTOM_RIGHT, false)) {
|
|
||||||
|
|
||||||
if (destinationTile.getY() % 2 == 1)
|
|
||||||
{
|
|
||||||
BattleHex::checkAndPush(destinationTile, hexes);
|
|
||||||
BattleHex::checkAndPush(destinationTile - 1, hexes);
|
|
||||||
BattleHex::checkAndPush(destinationTile + WN - 1, hexes);
|
|
||||||
BattleHex::checkAndPush(destinationTile + WN - 2, hexes);
|
|
||||||
BattleHex::checkAndPush(destinationTile - WN, hexes);
|
|
||||||
BattleHex::checkAndPush(destinationTile - WN - 1, hexes);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
BattleHex::checkAndPush(destinationTile, hexes);
|
|
||||||
BattleHex::checkAndPush(destinationTile - 1, hexes);
|
|
||||||
BattleHex::checkAndPush(destinationTile + WN, hexes);
|
|
||||||
BattleHex::checkAndPush(destinationTile + WN - 1, hexes);
|
|
||||||
BattleHex::checkAndPush(destinationTile - WN, hexes);
|
|
||||||
BattleHex::checkAndPush(destinationTile - WN + 1, hexes);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
for (BattleHex tile : hexes)
|
|
||||||
{
|
{
|
||||||
//friendly stacks can also be damaged by Dragon Breath
|
std::vector<BattleHex> hexes;
|
||||||
if (battleGetStackByPos(tile, true))
|
// attack stand
|
||||||
at.friendlyCreaturePositions.insert(tile);
|
if(hex == destinationTile.cloneInDirection(BattleHex::EDir::LEFT, false)) {
|
||||||
|
if(destinationTile.getY() % 2 == 0)
|
||||||
|
{
|
||||||
|
BattleHex::checkAndPush(destinationTile, hexes);
|
||||||
|
BattleHex::checkAndPush(destinationTile + 1, hexes);
|
||||||
|
BattleHex::checkAndPush(destinationTile + WN, hexes);
|
||||||
|
BattleHex::checkAndPush(destinationTile + WN + 1, hexes);
|
||||||
|
BattleHex::checkAndPush(destinationTile + (2 * WN) - 1, hexes);
|
||||||
|
BattleHex::checkAndPush(destinationTile + (2 * WN), hexes);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
BattleHex::checkAndPush(destinationTile, hexes);
|
||||||
|
BattleHex::checkAndPush(destinationTile + 1, hexes);
|
||||||
|
BattleHex::checkAndPush(destinationTile + WN, hexes);
|
||||||
|
BattleHex::checkAndPush(destinationTile + WN - 1, hexes);
|
||||||
|
BattleHex::checkAndPush(destinationTile + (2 * WN) - 1, hexes);
|
||||||
|
BattleHex::checkAndPush(destinationTile + (2 * WN), hexes);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
if(hex == destinationTile.cloneInDirection(BattleHex::EDir::RIGHT, false)) {
|
||||||
|
if(destinationTile.getY() % 2 == 0)
|
||||||
|
{
|
||||||
|
BattleHex::checkAndPush(destinationTile, hexes);
|
||||||
|
BattleHex::checkAndPush(destinationTile - 1, hexes);
|
||||||
|
BattleHex::checkAndPush(destinationTile + WN, hexes);
|
||||||
|
BattleHex::checkAndPush(destinationTile + WN + 1, hexes);
|
||||||
|
BattleHex::checkAndPush(destinationTile + (2 * WN), hexes);
|
||||||
|
BattleHex::checkAndPush(destinationTile + (2 * WN) + 1, hexes);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
BattleHex::checkAndPush(destinationTile, hexes);
|
||||||
|
BattleHex::checkAndPush(destinationTile - 1, hexes);
|
||||||
|
BattleHex::checkAndPush(destinationTile + WN, hexes);
|
||||||
|
BattleHex::checkAndPush(destinationTile + WN - 1, hexes);
|
||||||
|
BattleHex::checkAndPush(destinationTile + (2 * WN), hexes);
|
||||||
|
BattleHex::checkAndPush(destinationTile + (2 * WN) + 1, hexes);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// attack down
|
||||||
|
if(hex == destinationTile.cloneInDirection(BattleHex::EDir::TOP_LEFT, false)) {
|
||||||
|
if(destinationTile.getY() % 2 == 1)
|
||||||
|
{
|
||||||
|
BattleHex::checkAndPush(destinationTile, hexes);
|
||||||
|
BattleHex::checkAndPush(destinationTile - 1, hexes);
|
||||||
|
BattleHex::checkAndPush(destinationTile - 2, hexes);
|
||||||
|
BattleHex::checkAndPush(destinationTile + WN, hexes);
|
||||||
|
BattleHex::checkAndPush(destinationTile + WN - 1, hexes);
|
||||||
|
BattleHex::checkAndPush(destinationTile + WN - 2, hexes);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
BattleHex::checkAndPush(destinationTile, hexes);
|
||||||
|
BattleHex::checkAndPush(destinationTile - 1, hexes);
|
||||||
|
BattleHex::checkAndPush(destinationTile - 2, hexes);
|
||||||
|
BattleHex::checkAndPush(destinationTile + WN, hexes);
|
||||||
|
BattleHex::checkAndPush(destinationTile + WN + 1, hexes);
|
||||||
|
BattleHex::checkAndPush(destinationTile + WN - 1, hexes);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(hex == destinationTile.cloneInDirection(BattleHex::EDir::TOP_RIGHT, false)) {
|
||||||
|
|
||||||
|
if(destinationTile.getY() % 2 == 1)
|
||||||
|
{
|
||||||
|
BattleHex::checkAndPush(destinationTile, hexes);
|
||||||
|
BattleHex::checkAndPush(destinationTile + 1, hexes);
|
||||||
|
BattleHex::checkAndPush(destinationTile + 2, hexes);
|
||||||
|
BattleHex::checkAndPush(destinationTile + WN - 1, hexes);
|
||||||
|
BattleHex::checkAndPush(destinationTile + WN, hexes);
|
||||||
|
BattleHex::checkAndPush(destinationTile + WN + 1, hexes);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
BattleHex::checkAndPush(destinationTile, hexes);
|
||||||
|
BattleHex::checkAndPush(destinationTile + 1, hexes);
|
||||||
|
BattleHex::checkAndPush(destinationTile + 2, hexes);
|
||||||
|
BattleHex::checkAndPush(destinationTile + WN, hexes);
|
||||||
|
BattleHex::checkAndPush(destinationTile + WN + 1, hexes);
|
||||||
|
BattleHex::checkAndPush(destinationTile + WN + 2, hexes);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
// attack up
|
||||||
|
if(hex == destinationTile.cloneInDirection(BattleHex::EDir::BOTTOM_LEFT, false)) {
|
||||||
|
if(destinationTile.getY() % 2 == 1)
|
||||||
|
{
|
||||||
|
BattleHex::checkAndPush(destinationTile, hexes);
|
||||||
|
BattleHex::checkAndPush(destinationTile + 1, hexes);
|
||||||
|
BattleHex::checkAndPush(destinationTile + WN, hexes);
|
||||||
|
BattleHex::checkAndPush(destinationTile + WN + 1, hexes);
|
||||||
|
BattleHex::checkAndPush(destinationTile - WN, hexes);
|
||||||
|
BattleHex::checkAndPush(destinationTile - WN - 1, hexes);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
BattleHex::checkAndPush(destinationTile, hexes);
|
||||||
|
BattleHex::checkAndPush(destinationTile + 1, hexes);
|
||||||
|
BattleHex::checkAndPush(destinationTile + WN + 1, hexes);
|
||||||
|
BattleHex::checkAndPush(destinationTile + WN + 2, hexes);
|
||||||
|
BattleHex::checkAndPush(destinationTile - WN, hexes);
|
||||||
|
BattleHex::checkAndPush(destinationTile - WN + 1, hexes);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(hex == destinationTile.cloneInDirection(BattleHex::EDir::BOTTOM_RIGHT, false)) {
|
||||||
|
|
||||||
|
if(destinationTile.getY() % 2 == 1)
|
||||||
|
{
|
||||||
|
BattleHex::checkAndPush(destinationTile, hexes);
|
||||||
|
BattleHex::checkAndPush(destinationTile - 1, hexes);
|
||||||
|
BattleHex::checkAndPush(destinationTile + WN - 1, hexes);
|
||||||
|
BattleHex::checkAndPush(destinationTile + WN - 2, hexes);
|
||||||
|
BattleHex::checkAndPush(destinationTile - WN, hexes);
|
||||||
|
BattleHex::checkAndPush(destinationTile - WN - 1, hexes);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
BattleHex::checkAndPush(destinationTile, hexes);
|
||||||
|
BattleHex::checkAndPush(destinationTile - 1, hexes);
|
||||||
|
BattleHex::checkAndPush(destinationTile + WN, hexes);
|
||||||
|
BattleHex::checkAndPush(destinationTile + WN - 1, hexes);
|
||||||
|
BattleHex::checkAndPush(destinationTile - WN, hexes);
|
||||||
|
BattleHex::checkAndPush(destinationTile - WN + 1, hexes);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
for(BattleHex tile : hexes)
|
||||||
|
{
|
||||||
|
//friendly stacks can also be damaged by Dragon Breath
|
||||||
|
if(battleGetStackByPos(tile, true))
|
||||||
|
at.friendlyCreaturePositions.insert(tile);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
else if(attacker->hasBonusOfType(Bonus::TWO_HEX_ATTACK_BREATH) && BattleHex::mutualPosition(destinationTile.hex, hex) > -1) //only adjacent hexes are subject of dragon breath calculation
|
||||||
|
{
|
||||||
|
std::vector<BattleHex> hexes; //only one, in fact
|
||||||
|
int pseudoVector = destinationTile.hex - hex;
|
||||||
|
switch(pseudoVector)
|
||||||
|
{
|
||||||
|
case 1:
|
||||||
|
case -1:
|
||||||
|
BattleHex::checkAndPush(destinationTile.hex + pseudoVector, hexes);
|
||||||
|
break;
|
||||||
|
case WN: //17 //left-down or right-down
|
||||||
|
case -WN: //-17 //left-up or right-up
|
||||||
|
case WN + 1: //18 //right-down
|
||||||
|
case -WN + 1: //-16 //right-up
|
||||||
|
BattleHex::checkAndPush(destinationTile.hex + pseudoVector + (((hex / WN) % 2) ? 1 : -1), hexes);
|
||||||
|
break;
|
||||||
|
case WN - 1: //16 //left-down
|
||||||
|
case -WN - 1: //-18 //left-up
|
||||||
|
BattleHex::checkAndPush(destinationTile.hex + pseudoVector + (((hex / WN) % 2) ? 1 : 0), hexes);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
for(BattleHex tile : hexes)
|
||||||
|
{
|
||||||
|
//friendly stacks can also be damaged by Dragon Breath
|
||||||
|
if(battleGetStackByPos(tile, true))
|
||||||
|
at.friendlyCreaturePositions.insert(tile);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (attacker->hasBonusOfType(Bonus::TWO_HEX_ATTACK_BREATH) && BattleHex::mutualPosition(destinationTile.hex, hex) > -1) //only adjacent hexes are subject of dragon breath calculation
|
|
||||||
{
|
|
||||||
std::vector<BattleHex> hexes; //only one, in fact
|
|
||||||
int pseudoVector = destinationTile.hex - hex;
|
|
||||||
switch (pseudoVector)
|
|
||||||
{
|
|
||||||
case 1:
|
|
||||||
case -1:
|
|
||||||
BattleHex::checkAndPush(destinationTile.hex + pseudoVector, hexes);
|
|
||||||
break;
|
|
||||||
case WN: //17 //left-down or right-down
|
|
||||||
case -WN: //-17 //left-up or right-up
|
|
||||||
case WN + 1: //18 //right-down
|
|
||||||
case -WN + 1: //-16 //right-up
|
|
||||||
BattleHex::checkAndPush(destinationTile.hex + pseudoVector + (((hex / WN) % 2) ? 1 : -1), hexes);
|
|
||||||
break;
|
|
||||||
case WN - 1: //16 //left-down
|
|
||||||
case -WN - 1: //-18 //left-up
|
|
||||||
BattleHex::checkAndPush(destinationTile.hex + pseudoVector + (((hex / WN) % 2) ? 1 : 0), hexes);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
for (BattleHex tile : hexes)
|
|
||||||
{
|
|
||||||
//friendly stacks can also be damaged by Dragon Breath
|
|
||||||
if (battleGetStackByPos(tile, true))
|
|
||||||
at.friendlyCreaturePositions.insert(tile);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return at;
|
return at;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::set<const CStack*> CBattleInfoCallback::getAttackedCreatures(const CStack* attacker, BattleHex destinationTile, BattleHex attackerPos) const
|
std::set<const CStack*> CBattleInfoCallback::getAttackedCreatures(const CStack* attacker, BattleHex destinationTile, bool rangedAttack, BattleHex attackerPos) const
|
||||||
{
|
{
|
||||||
std::set<const CStack*> attackedCres;
|
std::set<const CStack*> attackedCres;
|
||||||
RETURN_IF_NOT_BATTLE(attackedCres);
|
RETURN_IF_NOT_BATTLE(attackedCres);
|
||||||
|
|
||||||
AttackableTiles at = getPotentiallyAttackableHexes(attacker, destinationTile, attackerPos);
|
AttackableTiles at = getPotentiallyAttackableHexes(attacker, destinationTile, attackerPos, rangedAttack);
|
||||||
for (BattleHex tile : at.hostileCreaturePositions) //all around & three-headed attack
|
for (BattleHex tile : at.hostileCreaturePositions) //all around & three-headed attack
|
||||||
{
|
{
|
||||||
const CStack * st = battleGetStackByPos(tile, true);
|
const CStack * st = battleGetStackByPos(tile, true);
|
||||||
|
@ -92,8 +92,8 @@ public:
|
|||||||
bool isInTacticRange(BattleHex dest) const;
|
bool isInTacticRange(BattleHex dest) const;
|
||||||
si8 battleGetTacticDist() const; //returns tactic distance for calling player or 0 if this player is not in tactic phase (for ALL_KNOWING actual distance for tactic side)
|
si8 battleGetTacticDist() const; //returns tactic distance for calling player or 0 if this player is not in tactic phase (for ALL_KNOWING actual distance for tactic side)
|
||||||
|
|
||||||
AttackableTiles getPotentiallyAttackableHexes(const CStack* attacker, BattleHex destinationTile, BattleHex attackerPos) const; //TODO: apply rotation to two-hex attacker
|
AttackableTiles getPotentiallyAttackableHexes(const CStack* attacker, BattleHex destinationTile, BattleHex attackerPos, bool rangedAttack) const; //TODO: apply rotation to two-hex attacker
|
||||||
std::set<const CStack*> getAttackedCreatures(const CStack* attacker, BattleHex destinationTile, BattleHex attackerPos = BattleHex::INVALID) const; //calculates range of multi-hex attacks
|
std::set<const CStack*> getAttackedCreatures(const CStack* attacker, BattleHex destinationTile, bool rangedAttack, BattleHex attackerPos = BattleHex::INVALID) const; //calculates range of multi-hex attacks
|
||||||
bool isToReverse(BattleHex hexFrom, BattleHex hexTo, bool curDir /*if true, creature is in attacker's direction*/, bool toDoubleWide, bool toDir) const; //determines if creature should be reversed (it stands on hexFrom and should 'see' hexTo)
|
bool isToReverse(BattleHex hexFrom, BattleHex hexTo, bool curDir /*if true, creature is in attacker's direction*/, bool toDoubleWide, bool toDir) const; //determines if creature should be reversed (it stands on hexFrom and should 'see' hexTo)
|
||||||
bool isToReverseHlp(BattleHex hexFrom, BattleHex hexTo, bool curDir) const; //helper for isToReverse
|
bool isToReverseHlp(BattleHex hexFrom, BattleHex hexTo, bool curDir) const; //helper for isToReverse
|
||||||
|
|
||||||
|
@ -892,16 +892,14 @@ void CGameHandler::prepareAttack(BattleAttack &bat, const CStack *att, const CSt
|
|||||||
// only primary target
|
// only primary target
|
||||||
applyBattleEffects(bat, att, def, distance, false);
|
applyBattleEffects(bat, att, def, distance, false);
|
||||||
|
|
||||||
if (!bat.shot()) //multiple-hex attack - only in meele
|
//multiple-hex normal attack
|
||||||
{
|
std::set<const CStack*> attackedCreatures = gs->curB->getAttackedCreatures(att, targetHex, bat.shot()); //creatures other than primary target
|
||||||
std::set<const CStack*> attackedCreatures = gs->curB->getAttackedCreatures(att, targetHex); //creatures other than primary target
|
|
||||||
|
|
||||||
for (const CStack * stack : attackedCreatures)
|
for (const CStack * stack : attackedCreatures)
|
||||||
|
{
|
||||||
|
if (stack != def) //do not hit same stack twice
|
||||||
{
|
{
|
||||||
if (stack != def) //do not hit same stack twice
|
applyBattleEffects(bat, att, stack, distance, true);
|
||||||
{
|
|
||||||
applyBattleEffects(bat, att, stack, distance, true);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -914,11 +912,11 @@ void CGameHandler::prepareAttack(BattleAttack &bat, const CStack *att, const CSt
|
|||||||
|
|
||||||
//TODO: should spell override creature`s projectile?
|
//TODO: should spell override creature`s projectile?
|
||||||
|
|
||||||
auto attackedCreatures = SpellID(bonus->subtype).toSpell()->getAffectedStacks(gs->curB, ECastingMode::SPELL_LIKE_ATTACK, att, bonus->val, targetHex);
|
auto affectedCreatures = SpellID(bonus->subtype).toSpell()->getAffectedStacks(gs->curB, ECastingMode::SPELL_LIKE_ATTACK, att, bonus->val, targetHex);
|
||||||
|
|
||||||
//TODO: get exact attacked hex for defender
|
//TODO: get exact attacked hex for defender
|
||||||
|
|
||||||
for (const CStack * stack : attackedCreatures)
|
for (const CStack * stack : affectedCreatures)
|
||||||
{
|
{
|
||||||
if (stack != def) //do not hit same stack twice
|
if (stack != def) //do not hit same stack twice
|
||||||
{
|
{
|
||||||
|
Loading…
Reference in New Issue
Block a user