From 500cf7f15d62a8e6acdf467d30c47bed598bc9de Mon Sep 17 00:00:00 2001 From: Ivan Savenko Date: Fri, 13 Jan 2023 00:35:58 +0200 Subject: [PATCH] EWallPart & EWallState are now enum class --- AI/BattleAI/BattleAI.cpp | 6 ++-- AI/BattleAI/StackWithBonuses.cpp | 2 +- AI/BattleAI/StackWithBonuses.h | 2 +- client/battle/BattleSiegeController.cpp | 14 ++++---- client/battle/BattleSiegeController.h | 2 +- lib/GameConstants.h | 30 +++++++---------- lib/NetPacks.h | 2 +- lib/NetPacksLib.cpp | 2 +- lib/battle/BattleInfo.cpp | 8 ++--- lib/battle/BattleInfo.h | 4 +-- lib/battle/BattleProxy.cpp | 2 +- lib/battle/BattleProxy.h | 2 +- lib/battle/CBattleInfoCallback.cpp | 24 ++++++------- lib/battle/CBattleInfoCallback.h | 6 ++-- lib/battle/CBattleInfoEssentials.cpp | 2 +- lib/battle/CBattleInfoEssentials.h | 2 +- lib/battle/IBattleState.h | 4 +-- lib/battle/SiegeInfo.cpp | 6 ++-- lib/battle/SiegeInfo.h | 4 +-- lib/spells/effects/Catapult.cpp | 45 ++++++++++--------------- lib/spells/effects/Obstacle.cpp | 2 +- server/CGameHandler.cpp | 14 ++++---- 22 files changed, 84 insertions(+), 101 deletions(-) diff --git a/AI/BattleAI/BattleAI.cpp b/AI/BattleAI/BattleAI.cpp index 1bbc2f09e..0ae8a183d 100644 --- a/AI/BattleAI/BattleAI.cpp +++ b/AI/BattleAI/BattleAI.cpp @@ -46,14 +46,14 @@ std::vector CBattleAI::getBrokenWallMoatHexes() const { std::vector result; - for(int wallPart = EWallPart::BOTTOM_WALL; wallPart < EWallPart::UPPER_WALL; wallPart++) + for(EWallPart wallPart : { EWallPart::BOTTOM_WALL, EWallPart::BELOW_GATE, EWallPart::OVER_GATE, EWallPart::UPPER_WALL }) { auto state = cb->battleGetWallState(wallPart); if(state != EWallState::DESTROYED) continue; - auto wallHex = cb->wallPartToBattleHex((EWallPart::EWallPart)wallPart); + auto wallHex = cb->wallPartToBattleHex((EWallPart)wallPart); auto moatHex = wallHex.cloneInDirection(BattleHex::LEFT); result.push_back(moatHex); @@ -364,7 +364,7 @@ BattleAction CBattleAI::useCatapult(const CStack * stack) } else { - EWallPart::EWallPart wallParts[] = { + EWallPart wallParts[] = { EWallPart::KEEP, EWallPart::BOTTOM_TOWER, EWallPart::UPPER_TOWER, diff --git a/AI/BattleAI/StackWithBonuses.cpp b/AI/BattleAI/StackWithBonuses.cpp index b843b7b4e..e698c3014 100644 --- a/AI/BattleAI/StackWithBonuses.cpp +++ b/AI/BattleAI/StackWithBonuses.cpp @@ -403,7 +403,7 @@ void HypotheticBattle::removeUnitBonus(uint32_t id, const std::vector & b bonusTreeVersion++; } -void HypotheticBattle::setWallState(int partOfWall, si8 state) +void HypotheticBattle::setWallState(EWallPart partOfWall, EWallState state) { //TODO:HypotheticBattle::setWallState } diff --git a/AI/BattleAI/StackWithBonuses.h b/AI/BattleAI/StackWithBonuses.h index a2ebafd70..48070ca40 100644 --- a/AI/BattleAI/StackWithBonuses.h +++ b/AI/BattleAI/StackWithBonuses.h @@ -130,7 +130,7 @@ public: void updateUnitBonus(uint32_t id, const std::vector & bonus) override; void removeUnitBonus(uint32_t id, const std::vector & bonus) override; - void setWallState(int partOfWall, si8 state) override; + void setWallState(EWallPart partOfWall, EWallState state) override; void addObstacle(const ObstacleChanges & changes) override; void updateObstacle(const ObstacleChanges& changes) override; diff --git a/client/battle/BattleSiegeController.cpp b/client/battle/BattleSiegeController.cpp index 0d6b76895..0f6a76f7f 100644 --- a/client/battle/BattleSiegeController.cpp +++ b/client/battle/BattleSiegeController.cpp @@ -28,7 +28,7 @@ #include "../../lib/CStack.h" #include "../../lib/mapObjects/CGTownInstance.h" -std::string BattleSiegeController::getWallPieceImageName(EWallVisual::EWallVisual what, EWallState::EWallState state) const +std::string BattleSiegeController::getWallPieceImageName(EWallVisual::EWallVisual what, EWallState state) const { auto getImageIndex = [&]() -> int { @@ -130,9 +130,9 @@ bool BattleSiegeController::getWallPieceExistance(EWallVisual::EWallVisual what) { case EWallVisual::MOAT: return town->hasBuilt(BuildingID::CITADEL) && town->town->faction->index != ETownType::TOWER; case EWallVisual::MOAT_BANK: return town->hasBuilt(BuildingID::CITADEL) && town->town->faction->index != ETownType::TOWER && town->town->faction->index != ETownType::NECROPOLIS; - case EWallVisual::KEEP_BATTLEMENT: return town->hasBuilt(BuildingID::CITADEL) && EWallState::EWallState(owner.curInt->cb->battleGetWallState(EWallPart::KEEP)) != EWallState::DESTROYED; - case EWallVisual::UPPER_BATTLEMENT: return town->hasBuilt(BuildingID::CASTLE) && EWallState::EWallState(owner.curInt->cb->battleGetWallState(EWallPart::UPPER_TOWER)) != EWallState::DESTROYED; - case EWallVisual::BOTTOM_BATTLEMENT: return town->hasBuilt(BuildingID::CASTLE) && EWallState::EWallState(owner.curInt->cb->battleGetWallState(EWallPart::BOTTOM_TOWER)) != EWallState::DESTROYED; + case EWallVisual::KEEP_BATTLEMENT: return town->hasBuilt(BuildingID::CITADEL) && EWallState(owner.curInt->cb->battleGetWallState(EWallPart::KEEP)) != EWallState::DESTROYED; + case EWallVisual::UPPER_BATTLEMENT: return town->hasBuilt(BuildingID::CASTLE) && EWallState(owner.curInt->cb->battleGetWallState(EWallPart::UPPER_TOWER)) != EWallState::DESTROYED; + case EWallVisual::BOTTOM_BATTLEMENT: return town->hasBuilt(BuildingID::CASTLE) && EWallState(owner.curInt->cb->battleGetWallState(EWallPart::BOTTOM_TOWER)) != EWallState::DESTROYED; default: return true; } } @@ -321,7 +321,7 @@ bool BattleSiegeController::isAttackableByCatapult(BattleHex hex) const if (!owner.curInt->cb->isWallPartPotentiallyAttackable(wallPart)) return false; - auto state = owner.curInt->cb->battleGetWallState(static_cast(wallPart)); + auto state = owner.curInt->cb->battleGetWallState(wallPart); return state != EWallState::DESTROYED && state != EWallState::NONE; } @@ -354,12 +354,12 @@ void BattleSiegeController::stackIsCatapulting(const CatapultAttack & ca) for (auto attackInfo : ca.attackedParts) { - int wallId = attackInfo.attackedPart + EWallVisual::DESTRUCTIBLE_FIRST; + int wallId = static_cast(attackInfo.attackedPart) + EWallVisual::DESTRUCTIBLE_FIRST; //gate state changing handled separately if (wallId == EWallVisual::GATE) continue; - auto wallState = EWallState::EWallState(owner.curInt->cb->battleGetWallState(attackInfo.attackedPart)); + auto wallState = EWallState(owner.curInt->cb->battleGetWallState(attackInfo.attackedPart)); wallPieceImages[wallId] = IImage::createFromFile(getWallPieceImageName(EWallVisual::EWallVisual(wallId), wallState)); } diff --git a/client/battle/BattleSiegeController.h b/client/battle/BattleSiegeController.h index 90e304c46..dd4795afc 100644 --- a/client/battle/BattleSiegeController.h +++ b/client/battle/BattleSiegeController.h @@ -76,7 +76,7 @@ class BattleSiegeController std::array, EWallVisual::WALL_LAST + 1> wallPieceImages; /// return URI for image for a wall piece - std::string getWallPieceImageName(EWallVisual::EWallVisual what, EWallState::EWallState state) const; + std::string getWallPieceImageName(EWallVisual::EWallVisual what, EWallState state) const; /// returns BattleHex to which chosen wall piece is bound BattleHex getWallPiecePosition(EWallVisual::EWallVisual what) const; diff --git a/lib/GameConstants.h b/lib/GameConstants.h index b995bc089..5d50073bc 100644 --- a/lib/GameConstants.h +++ b/lib/GameConstants.h @@ -615,28 +615,22 @@ namespace ECommander const int MAX_SKILL_LEVEL = 5; } -namespace EWallPart +enum class EWallPart : int8_t { - enum EWallPart - { - INDESTRUCTIBLE_PART_OF_GATE = -3, INDESTRUCTIBLE_PART = -2, INVALID = -1, - KEEP = 0, BOTTOM_TOWER, BOTTOM_WALL, BELOW_GATE, OVER_GATE, UPPER_WALL, UPPER_TOWER, GATE, - PARTS_COUNT /* This constant SHOULD always stay as the last item in the enum. */ - }; -} + INDESTRUCTIBLE_PART_OF_GATE = -3, INDESTRUCTIBLE_PART = -2, INVALID = -1, + KEEP = 0, BOTTOM_TOWER, BOTTOM_WALL, BELOW_GATE, OVER_GATE, UPPER_WALL, UPPER_TOWER, GATE, + PARTS_COUNT /* This constant SHOULD always stay as the last item in the enum. */ +}; -namespace EWallState +enum class EWallState : int8_t { - enum EWallState - { - NONE = -1, //no wall - DESTROYED, - DAMAGED, - INTACT - }; -} + NONE = -1, //no wall + DESTROYED, + DAMAGED, + INTACT +}; -enum class EGateState : ui8 +enum class EGateState : uint8_t { NONE, CLOSED, diff --git a/lib/NetPacks.h b/lib/NetPacks.h index 82df6ab91..76a93c497 100644 --- a/lib/NetPacks.h +++ b/lib/NetPacks.h @@ -1827,7 +1827,7 @@ struct ELF_VISIBILITY CatapultAttack : public CPackForClient struct AttackInfo { si16 destinationTile; - ui8 attackedPart; + EWallPart attackedPart; ui8 damageDealt; template void serialize(Handler & h, const int version) diff --git a/lib/NetPacksLib.cpp b/lib/NetPacksLib.cpp index 5e4e869ea..0be775aa8 100644 --- a/lib/NetPacksLib.cpp +++ b/lib/NetPacksLib.cpp @@ -1707,7 +1707,7 @@ DLL_LINKAGE void CatapultAttack::applyBattle(IBattleState * battleState) for(const auto & part : attackedParts) { - auto newWallState = SiegeInfo::applyDamage(EWallState::EWallState(battleState->getWallState(part.attackedPart)), part.damageDealt); + auto newWallState = SiegeInfo::applyDamage(EWallState(battleState->getWallState(part.attackedPart)), part.damageDealt); battleState->setWallState(part.attackedPart, newWallState); } } diff --git a/lib/battle/BattleInfo.cpp b/lib/battle/BattleInfo.cpp index f1687ccef..74024b8a4 100644 --- a/lib/battle/BattleInfo.cpp +++ b/lib/battle/BattleInfo.cpp @@ -225,7 +225,7 @@ BattleInfo * BattleInfo::setupBattle(const int3 & tile, TerrainId terrain, const for (int b = 0; b < curB->si.wallState.size(); ++b) { - curB->si.wallState[b] = EWallState::INTACT; + curB->si.wallState[EWallPart(b)] = EWallState::INTACT; } if (!town->hasBuilt(BuildingID::CITADEL)) @@ -610,7 +610,7 @@ const CGTownInstance * BattleInfo::getDefendedTown() const return town; } -si8 BattleInfo::getWallState(int partOfWall) const +EWallState BattleInfo::getWallState(EWallPart partOfWall) const { return si.wallState.at(partOfWall); } @@ -913,9 +913,9 @@ void BattleInfo::addOrUpdateUnitBonus(CStack * sta, const Bonus & value, bool fo } } -void BattleInfo::setWallState(int partOfWall, si8 state) +void BattleInfo::setWallState(EWallPart partOfWall, EWallState state) { - si.wallState.at(partOfWall) = state; + si.wallState[partOfWall] = state; } void BattleInfo::addObstacle(const ObstacleChanges & changes) diff --git a/lib/battle/BattleInfo.h b/lib/battle/BattleInfo.h index 76d3a9db2..1bafc74dd 100644 --- a/lib/battle/BattleInfo.h +++ b/lib/battle/BattleInfo.h @@ -87,7 +87,7 @@ public: ui8 getTacticsSide() const override; const CGTownInstance * getDefendedTown() const override; - si8 getWallState(int partOfWall) const override; + EWallState getWallState(EWallPart partOfWall) const override; EGateState getGateState() const override; uint32_t getCastSpells(ui8 side) const override; @@ -115,7 +115,7 @@ public: void updateUnitBonus(uint32_t id, const std::vector & bonus) override; void removeUnitBonus(uint32_t id, const std::vector & bonus) override; - void setWallState(int partOfWall, si8 state) override; + void setWallState(EWallPart partOfWall, EWallState state) override; void addObstacle(const ObstacleChanges & changes) override; void updateObstacle(const ObstacleChanges& changes) override; diff --git a/lib/battle/BattleProxy.cpp b/lib/battle/BattleProxy.cpp index 0ebb475ba..67e4aae16 100644 --- a/lib/battle/BattleProxy.cpp +++ b/lib/battle/BattleProxy.cpp @@ -89,7 +89,7 @@ const CGTownInstance * BattleProxy::getDefendedTown() const return subject->battleGetDefendedTown(); } -si8 BattleProxy::getWallState(int partOfWall) const +EWallState BattleProxy::getWallState(EWallPart partOfWall) const { return subject->battleGetWallState(partOfWall); } diff --git a/lib/battle/BattleProxy.h b/lib/battle/BattleProxy.h index 8a7b0e13d..0e07e707c 100644 --- a/lib/battle/BattleProxy.h +++ b/lib/battle/BattleProxy.h @@ -44,7 +44,7 @@ public: ui8 getTacticsSide() const override; const CGTownInstance * getDefendedTown() const override; - si8 getWallState(int partOfWall) const override; + EWallState getWallState(EWallPart partOfWall) const override; EGateState getGateState() const override; uint32_t getCastSpells(ui8 side) const override; diff --git a/lib/battle/CBattleInfoCallback.cpp b/lib/battle/CBattleInfoCallback.cpp index 1e6358d7c..05ce607bb 100644 --- a/lib/battle/CBattleInfoCallback.cpp +++ b/lib/battle/CBattleInfoCallback.cpp @@ -71,7 +71,7 @@ static bool sameSideOfWall(BattleHex pos1, BattleHex pos2) } // parts of wall -static const std::pair wallParts[] = +static const std::pair wallParts[] = { std::make_pair(50, EWallPart::KEEP), std::make_pair(183, EWallPart::BOTTOM_TOWER), @@ -89,7 +89,7 @@ static const std::pair wallParts[] = std::make_pair(165, EWallPart::INDESTRUCTIBLE_PART) }; -static EWallPart::EWallPart hexToWallPart(BattleHex hex) +static EWallPart hexToWallPart(BattleHex hex) { for(auto & elem : wallParts) { @@ -100,7 +100,7 @@ static EWallPart::EWallPart hexToWallPart(BattleHex hex) return EWallPart::INVALID; //not found! } -static BattleHex WallPartToHex(EWallPart::EWallPart part) +static BattleHex WallPartToHex(EWallPart part) { for(auto & elem : wallParts) { @@ -1109,13 +1109,13 @@ AccessibilityInfo CBattleInfoCallback::getAccesibility() const ret[hex] = EAccessibility::UNAVAILABLE; //TODO likely duplicated logic - static const std::pair lockedIfNotDestroyed[] = + static const std::pair lockedIfNotDestroyed[] = { //which part of wall, which hex is blocked if this part of wall is not destroyed - std::make_pair(2, BattleHex(ESiegeHex::DESTRUCTIBLE_WALL_4)), - std::make_pair(3, BattleHex(ESiegeHex::DESTRUCTIBLE_WALL_3)), - std::make_pair(4, BattleHex(ESiegeHex::DESTRUCTIBLE_WALL_2)), - std::make_pair(5, BattleHex(ESiegeHex::DESTRUCTIBLE_WALL_1)) + std::make_pair(EWallPart::BOTTOM_WALL, BattleHex(ESiegeHex::DESTRUCTIBLE_WALL_4)), + std::make_pair(EWallPart::BELOW_GATE, BattleHex(ESiegeHex::DESTRUCTIBLE_WALL_3)), + std::make_pair(EWallPart::OVER_GATE, BattleHex(ESiegeHex::DESTRUCTIBLE_WALL_2)), + std::make_pair(EWallPart::UPPER_WALL, BattleHex(ESiegeHex::DESTRUCTIBLE_WALL_1)) }; for(auto & elem : lockedIfNotDestroyed) @@ -1604,19 +1604,19 @@ bool CBattleInfoCallback::battleHasDistancePenalty(const IBonusBearer * shooter, return true; } -BattleHex CBattleInfoCallback::wallPartToBattleHex(EWallPart::EWallPart part) const +BattleHex CBattleInfoCallback::wallPartToBattleHex(EWallPart part) const { RETURN_IF_NOT_BATTLE(BattleHex::INVALID); return WallPartToHex(part); } -EWallPart::EWallPart CBattleInfoCallback::battleHexToWallPart(BattleHex hex) const +EWallPart CBattleInfoCallback::battleHexToWallPart(BattleHex hex) const { RETURN_IF_NOT_BATTLE(EWallPart::INVALID); return hexToWallPart(hex); } -bool CBattleInfoCallback::isWallPartPotentiallyAttackable(EWallPart::EWallPart wallPart) const +bool CBattleInfoCallback::isWallPartPotentiallyAttackable(EWallPart wallPart) const { RETURN_IF_NOT_BATTLE(false); return wallPart != EWallPart::INDESTRUCTIBLE_PART && wallPart != EWallPart::INDESTRUCTIBLE_PART_OF_GATE && @@ -1632,7 +1632,7 @@ std::vector CBattleInfoCallback::getAttackableBattleHexes() const { if(isWallPartPotentiallyAttackable(wallPartPair.second)) { - auto wallState = static_cast(battleGetWallState(static_cast(wallPartPair.second))); + auto wallState = static_cast(battleGetWallState(wallPartPair.second)); if(wallState == EWallState::INTACT || wallState == EWallState::DAMAGED) { attackableBattleHexes.push_back(BattleHex(wallPartPair.first)); diff --git a/lib/battle/CBattleInfoCallback.h b/lib/battle/CBattleInfoCallback.h index 75fc6bf81..259313fd8 100644 --- a/lib/battle/CBattleInfoCallback.h +++ b/lib/battle/CBattleInfoCallback.h @@ -110,9 +110,9 @@ public: bool battleHasWallPenalty(const IBonusBearer * shooter, BattleHex shooterPosition, BattleHex destHex) const; bool battleHasShootingPenalty(const battle::Unit * shooter, BattleHex destHex) const; - BattleHex wallPartToBattleHex(EWallPart::EWallPart part) const; - EWallPart::EWallPart battleHexToWallPart(BattleHex hex) const; //returns part of destructible wall / gate / keep under given hex or -1 if not found - bool isWallPartPotentiallyAttackable(EWallPart::EWallPart wallPart) const; // returns true if the wall part is potentially attackable (independent of wall state), false if not + BattleHex wallPartToBattleHex(EWallPart part) const; + EWallPart battleHexToWallPart(BattleHex hex) const; //returns part of destructible wall / gate / keep under given hex or -1 if not found + bool isWallPartPotentiallyAttackable(EWallPart wallPart) const; // returns true if the wall part is potentially attackable (independent of wall state), false if not std::vector getAttackableBattleHexes() const; si8 battleMinSpellLevel(ui8 side) const; //calculates maximum spell level possible to be cast on battlefield - takes into account artifacts of both heroes; if no effects are set, 0 is returned diff --git a/lib/battle/CBattleInfoEssentials.cpp b/lib/battle/CBattleInfoEssentials.cpp index 53fcd6dd8..e7e0062aa 100644 --- a/lib/battle/CBattleInfoEssentials.cpp +++ b/lib/battle/CBattleInfoEssentials.cpp @@ -364,7 +364,7 @@ bool CBattleInfoEssentials::battleHasHero(ui8 side) const return getBattle()->getSideHero(side) != nullptr; } -si8 CBattleInfoEssentials::battleGetWallState(int partOfWall) const +EWallState CBattleInfoEssentials::battleGetWallState(EWallPart partOfWall) const { RETURN_IF_NOT_BATTLE(EWallState::NONE); if(battleGetSiegeLevel() == CGTownInstance::NONE) diff --git a/lib/battle/CBattleInfoEssentials.h b/lib/battle/CBattleInfoEssentials.h index 6903e66bc..117e352b3 100644 --- a/lib/battle/CBattleInfoEssentials.h +++ b/lib/battle/CBattleInfoEssentials.h @@ -94,7 +94,7 @@ public: // for determining state of a part of the wall; format: parameter [0] - keep, [1] - bottom tower, [2] - bottom wall, // [3] - below gate, [4] - over gate, [5] - upper wall, [6] - uppert tower, [7] - gate; returned value: 1 - intact, 2 - damaged, 3 - destroyed; 0 - no battle - si8 battleGetWallState(int partOfWall) const; + EWallState battleGetWallState(EWallPart partOfWall) const; EGateState battleGetGateState() const; //helpers diff --git a/lib/battle/IBattleState.h b/lib/battle/IBattleState.h index 62536f4c1..7165ed5b2 100644 --- a/lib/battle/IBattleState.h +++ b/lib/battle/IBattleState.h @@ -49,7 +49,7 @@ public: virtual ObstacleCList getAllObstacles() const = 0; virtual const CGTownInstance * getDefendedTown() const = 0; - virtual si8 getWallState(int partOfWall) const = 0; + virtual EWallState getWallState(EWallPart partOfWall) const = 0; virtual EGateState getGateState() const = 0; virtual PlayerColor getSidePlayer(ui8 side) const = 0; @@ -87,7 +87,7 @@ public: virtual void updateUnitBonus(uint32_t id, const std::vector & bonus) = 0; virtual void removeUnitBonus(uint32_t id, const std::vector & bonus) = 0; - virtual void setWallState(int partOfWall, si8 state) = 0; + virtual void setWallState(EWallPart partOfWall, EWallState state) = 0; virtual void addObstacle(const ObstacleChanges & changes) = 0; virtual void updateObstacle(const ObstacleChanges & changes) = 0; diff --git a/lib/battle/SiegeInfo.cpp b/lib/battle/SiegeInfo.cpp index 13c2dc468..c11a5a6d9 100644 --- a/lib/battle/SiegeInfo.cpp +++ b/lib/battle/SiegeInfo.cpp @@ -15,14 +15,14 @@ VCMI_LIB_NAMESPACE_BEGIN SiegeInfo::SiegeInfo() { - for(int i = 0; i < wallState.size(); ++i) + for(int i = 0; i < int(EWallPart::PARTS_COUNT); ++i) { - wallState[i] = EWallState::NONE; + wallState[EWallPart(i)] = EWallState::NONE; } gateState = EGateState::NONE; } -EWallState::EWallState SiegeInfo::applyDamage(EWallState::EWallState state, unsigned int value) +EWallState SiegeInfo::applyDamage(EWallState state, unsigned int value) { if(value == 0) return state; diff --git a/lib/battle/SiegeInfo.h b/lib/battle/SiegeInfo.h index f508c1f14..680888201 100644 --- a/lib/battle/SiegeInfo.h +++ b/lib/battle/SiegeInfo.h @@ -15,13 +15,13 @@ VCMI_LIB_NAMESPACE_BEGIN //only for use in BattleInfo struct DLL_LINKAGE SiegeInfo { - std::array wallState; + std::map wallState; EGateState gateState; SiegeInfo(); // return EWallState decreased by value of damage points - static EWallState::EWallState applyDamage(EWallState::EWallState state, unsigned int value); + static EWallState applyDamage(EWallState state, unsigned int value); template void serialize(Handler &h, const int version) { diff --git a/lib/spells/effects/Catapult.cpp b/lib/spells/effects/Catapult.cpp index 62c9363f3..8f98f2a53 100644 --- a/lib/spells/effects/Catapult.cpp +++ b/lib/spells/effects/Catapult.cpp @@ -68,7 +68,7 @@ bool Catapult::applicable(Problem & problem, const Mechanics * m) const void Catapult::apply(ServerCallback * server, const Mechanics * m, const EffectTarget & /* eTarget */) const { //start with all destructible parts - static const std::set potentialTargets = + static const std::set potentialTargets = { EWallPart::KEEP, EWallPart::BOTTOM_TOWER, @@ -80,9 +80,9 @@ void Catapult::apply(ServerCallback * server, const Mechanics * m, const EffectT EWallPart::GATE }; - assert(potentialTargets.size() == EWallPart::PARTS_COUNT); + assert(potentialTargets.size() == size_t(EWallPart::PARTS_COUNT)); - std::set allowedTargets; + std::set allowedTargets; for (auto const & target : potentialTargets) { @@ -98,16 +98,13 @@ void Catapult::apply(ServerCallback * server, const Mechanics * m, const EffectT CatapultAttack ca; ca.attacker = -1; - BattleUnitsChanged removeUnits; - for(int i = 0; i < targetsToAttack; i++) { // Hit on any existing, not destroyed targets are allowed // Multiple hit on same target are allowed. // Potential overshots (more hits on same targets than remaining HP) are allowed - EWallPart::EWallPart target = *RandomGeneratorUtil::nextItem(allowedTargets, *server->getRNG()); + EWallPart target = *RandomGeneratorUtil::nextItem(allowedTargets, *server->getRNG()); - auto state = m->battle()->battleGetWallState(target); auto attackInfo = ca.attackedParts.begin(); for ( ; attackInfo != ca.attackedParts.end(); ++attackInfo) @@ -127,11 +124,19 @@ void Catapult::apply(ServerCallback * server, const Mechanics * m, const EffectT { attackInfo->damageDealt += 1; } + } + server->apply(&ca); + + BattleUnitsChanged removeUnits; + + for (auto const wallPart : { EWallPart::KEEP, EWallPart::BOTTOM_TOWER, EWallPart::UPPER_TOWER }) + { //removing creatures in turrets / keep if one is destroyed BattleHex posRemove; + auto state = m->battle()->battleGetWallState(wallPart); - switch(target) + switch(wallPart) { case EWallPart::KEEP: posRemove = BattleHex::CASTLE_CENTRAL_TOWER; @@ -144,35 +149,19 @@ void Catapult::apply(ServerCallback * server, const Mechanics * m, const EffectT break; } - if(posRemove != BattleHex::INVALID && state - attackInfo->damageDealt <= 0) //HP enum subtraction not intuitive, consider using SiegeInfo::applyDamage + if(state == EWallState::DESTROYED) //HP enum subtraction not intuitive, consider using SiegeInfo::applyDamage { auto all = m->battle()->battleGetUnitsIf([=](const battle::Unit * unit) { - return !unit->isGhost(); + return !unit->isGhost() && unit->getPosition() == posRemove; }); + assert(all.size() == 0 || all.size() == 1); for(auto & elem : all) - { - if(elem->getPosition() != posRemove) - continue; - - // if tower was hit multiple times, it may have been destroyed already - bool stackWasRemovedBefore = false; - for(auto & removed : removeUnits.changedStacks) - { - if (removed.id == elem->unitId()) - stackWasRemovedBefore = true; - } - - if (!stackWasRemovedBefore) - removeUnits.changedStacks.emplace_back(elem->unitId(), UnitChanges::EOperation::REMOVE); - break; - } + removeUnits.changedStacks.emplace_back(elem->unitId(), UnitChanges::EOperation::REMOVE); } } - server->apply(&ca); - if(!removeUnits.changedStacks.empty()) server->apply(&removeUnits); } diff --git a/lib/spells/effects/Obstacle.cpp b/lib/spells/effects/Obstacle.cpp index 4c381ce9c..402ccc155 100644 --- a/lib/spells/effects/Obstacle.cpp +++ b/lib/spells/effects/Obstacle.cpp @@ -256,7 +256,7 @@ bool Obstacle::isHexAvailable(const CBattleInfoCallback * cb, const BattleHex & if(cb->battleGetSiegeLevel() != 0) { - EWallPart::EWallPart part = cb->battleHexToWallPart(hex); + EWallPart part = cb->battleHexToWallPart(hex); if(part == EWallPart::INVALID || part == EWallPart::INDESTRUCTIBLE_PART_OF_GATE) return true;//no fortification here diff --git a/server/CGameHandler.cpp b/server/CGameHandler.cpp index fc1b94cd3..985f7bbd7 100644 --- a/server/CGameHandler.cpp +++ b/server/CGameHandler.cpp @@ -4790,7 +4790,7 @@ bool CGameHandler::makeBattleAction(BattleAction &ba) case EActionType::CATAPULT: { //TODO: unify with spells::effects:Catapult - auto getCatapultHitChance = [](EWallPart::EWallPart part, const CHeroHandler::SBallisticsLevelInfo & sbi) -> int + auto getCatapultHitChance = [](EWallPart part, const CHeroHandler::SBallisticsLevelInfo & sbi) -> int { switch(part) { @@ -4829,7 +4829,7 @@ bool CGameHandler::makeBattleAction(BattleAction &ba) } }; - auto isWallPartAttackable = [this] (EWallPart::EWallPart part) + auto isWallPartAttackable = [this] (EWallPart part) { return (gs->curB->si.wallState[part] == EWallState::INTACT || gs->curB->si.wallState[part] == EWallState::DAMAGED); }; @@ -4851,13 +4851,13 @@ bool CGameHandler::makeBattleAction(BattleAction &ba) } else { - static const std::array walls = { EWallPart::BOTTOM_WALL, EWallPart::BELOW_GATE, EWallPart::OVER_GATE, EWallPart::UPPER_WALL }; - static const std::array towers= { EWallPart::BOTTOM_TOWER, EWallPart::KEEP, EWallPart::UPPER_TOWER }; - static const EWallPart::EWallPart gates = EWallPart::GATE; + static const std::array walls = { EWallPart::BOTTOM_WALL, EWallPart::BELOW_GATE, EWallPart::OVER_GATE, EWallPart::UPPER_WALL }; + static const std::array towers= { EWallPart::BOTTOM_TOWER, EWallPart::KEEP, EWallPart::UPPER_TOWER }; + static const EWallPart gates = EWallPart::GATE; // in H3, catapult under automatic control will attack objects in following order: // walls, gates, towers - std::vector potentialTargets; + std::vector potentialTargets; for (auto & part : walls ) if (isWallPartAttackable(part)) potentialTargets.push_back(part); @@ -4906,7 +4906,7 @@ bool CGameHandler::makeBattleAction(BattleAction &ba) logGlobal->trace("Catapult attacks %d dealing %d damage", (int)attack.attackedPart, (int)attack.damageDealt); //removing creatures in turrets / keep if one is destroyed - if (gs->curB->si.wallState[actualTarget] <= 0 && (actualTarget == EWallPart::KEEP || actualTarget == EWallPart::BOTTOM_TOWER || actualTarget == EWallPart::UPPER_TOWER)) + if (gs->curB->si.wallState[actualTarget] == EWallState::DESTROYED && (actualTarget == EWallPart::KEEP || actualTarget == EWallPart::BOTTOM_TOWER || actualTarget == EWallPart::UPPER_TOWER)) { int posRemove = -1; switch(actualTarget)