diff --git a/Mods/vcmi/config/vcmi/english.json b/Mods/vcmi/config/vcmi/english.json index 2cb7b5772..a090251a9 100644 --- a/Mods/vcmi/config/vcmi/english.json +++ b/Mods/vcmi/config/vcmi/english.json @@ -687,5 +687,7 @@ "core.bonus.DISINTEGRATE.name": "Disintegrate", "core.bonus.DISINTEGRATE.description": "No corpse remains after death", "core.bonus.INVINCIBLE.name": "Invincible", - "core.bonus.INVINCIBLE.description": "Cannot be affected by anything" + "core.bonus.INVINCIBLE.description": "Cannot be affected by anything", + "core.bonus.PRISM_HEX_ATTACK_BREATH.name": "Prism Breath", + "core.bonus.PRISM_HEX_ATTACK_BREATH.description": "Prism Breath Attack (three directions)" } diff --git a/config/bonuses.json b/config/bonuses.json index 897e0a9b9..f11faaec8 100644 --- a/config/bonuses.json +++ b/config/bonuses.json @@ -548,6 +548,14 @@ } }, + "PRISM_HEX_ATTACK_BREATH": + { + "graphics": + { + "icon": "zvs/Lib1.res/PrismBreath" + } + }, + "THREE_HEADED_ATTACK": { "graphics": diff --git a/docs/modders/Bonus/Bonus_Types.md b/docs/modders/Bonus/Bonus_Types.md index 34e4d0b57..ec025eb3c 100644 --- a/docs/modders/Bonus/Bonus_Types.md +++ b/docs/modders/Bonus/Bonus_Types.md @@ -502,6 +502,10 @@ Affected unit attacks all adjacent creatures (Hydra). Only directly targeted cre Affected unit attacks creature located directly behind targeted tile (Dragons). Only directly targeted creature will attempt to retaliate +### PRISM_HEX_ATTACK_BREATH + +Like `TWO_HEX_ATTACK_BREATH` but affects also two additional cratures (in triangle form from target tile) + ### RETURN_AFTER_STRIKE Affected unit can return to his starting location after attack (Harpies) diff --git a/lib/battle/CBattleInfoCallback.cpp b/lib/battle/CBattleInfoCallback.cpp index 05afc364c..d4ec621c6 100644 --- a/lib/battle/CBattleInfoCallback.cpp +++ b/lib/battle/CBattleInfoCallback.cpp @@ -1392,7 +1392,7 @@ AttackableTiles CBattleInfoCallback::getPotentiallyAttackableHexes( at.friendlyCreaturePositions.insert(tile); } } - else if(attacker->hasBonusOfType(BonusType::TWO_HEX_ATTACK_BREATH)) + else if(attacker->hasBonusOfType(BonusType::TWO_HEX_ATTACK_BREATH) || attacker->hasBonusOfType(BonusType::PRISM_HEX_ATTACK_BREATH)) { auto direction = BattleHex::mutualPosition(attackOriginHex, destinationTile); @@ -1404,27 +1404,39 @@ AttackableTiles CBattleInfoCallback::getPotentiallyAttackableHexes( direction = BattleHex::mutualPosition(attackOriginHex, defender->occupiedHex(defenderPos)); } - if(direction != BattleHex::NONE) //only adjacent hexes are subject of dragon breath calculation + for(int i = 0; i < 3; i++) { - BattleHex nextHex = destinationTile.cloneInDirection(direction, false); - - if ( defender->doubleWide() ) + if(direction != BattleHex::NONE) //only adjacent hexes are subject of dragon breath calculation { - auto secondHex = destinationTile == defenderPos ? defender->occupiedHex(defenderPos) : defenderPos; + BattleHex nextHex = destinationTile.cloneInDirection(direction, false); - // if targeted double-wide creature is attacked from above or below ( -> second hex is also adjacent to attack origin) - // then dragon breath should target tile on the opposite side of targeted creature - if(BattleHex::mutualPosition(attackOriginHex, secondHex) != BattleHex::NONE) - nextHex = secondHex.cloneInDirection(direction, false); + if ( defender->doubleWide() ) + { + auto secondHex = destinationTile == defenderPos ? defender->occupiedHex(defenderPos) : defenderPos; + + // if targeted double-wide creature is attacked from above or below ( -> second hex is also adjacent to attack origin) + // then dragon breath should target tile on the opposite side of targeted creature + if(BattleHex::mutualPosition(attackOriginHex, secondHex) != BattleHex::NONE) + nextHex = secondHex.cloneInDirection(direction, false); + } + + if (nextHex.isValid()) + { + //friendly stacks can also be damaged by Dragon Breath + const auto * st = battleGetUnitByPos(nextHex, true); + if(st != nullptr) + at.friendlyCreaturePositions.insert(nextHex); + } } - if (nextHex.isValid()) - { - //friendly stacks can also be damaged by Dragon Breath - const auto * st = battleGetUnitByPos(nextHex, true); - if(st != nullptr) - at.friendlyCreaturePositions.insert(nextHex); - } + if(!attacker->hasBonusOfType(BonusType::PRISM_HEX_ATTACK_BREATH)) + break; + + // only needed for prism + int tmpDirection = static_cast(direction) + 2; + if(tmpDirection > static_cast(BattleHex::EDir::LEFT)) + tmpDirection -= static_cast(BattleHex::EDir::TOP); + direction = static_cast(tmpDirection); } } return at; diff --git a/lib/bonuses/BonusEnum.h b/lib/bonuses/BonusEnum.h index e68450c08..ec5f586f3 100644 --- a/lib/bonuses/BonusEnum.h +++ b/lib/bonuses/BonusEnum.h @@ -180,6 +180,7 @@ class JsonNode; BONUS_NAME(RESOURCES_TOWN_MULTIPLYING_BOOST) /*Bonus that does not account for propagation and gives extra resources per day with amount multiplied by number of owned towns. val - base resource amount to be multiplied times number of owned towns, subtype - resource type*/ \ BONUS_NAME(DISINTEGRATE) /* after death no corpse remains */ \ BONUS_NAME(INVINCIBLE) /* cannot be target of attacks or spells */ \ + BONUS_NAME(PRISM_HEX_ATTACK_BREATH) /*eg. dragons*/ \ /* end of list */