diff --git a/lib/battle/CBattleInfoCallback.cpp b/lib/battle/CBattleInfoCallback.cpp index f33c98207..ce0fae897 100644 --- a/lib/battle/CBattleInfoCallback.cpp +++ b/lib/battle/CBattleInfoCallback.cpp @@ -280,8 +280,11 @@ std::vector CBattleInfoCallback::getClientActionsFor if(stack->hasBonusOfType(BonusType::RETURN_AFTER_STRIKE)) allowedActionList.push_back(PossiblePlayerBattleAction::ATTACK_AND_RETURN); - allowedActionList.push_back(PossiblePlayerBattleAction::ATTACK); //all active stacks can attack - allowedActionList.push_back(PossiblePlayerBattleAction::WALK_AND_ATTACK); //not all stacks can always walk, but we will check this elsewhere + if (stack->isMeleeAttacker()) //not all stacks can actually attack or walk and attack, check this elsewhere + { + allowedActionList.push_back(PossiblePlayerBattleAction::ATTACK); + allowedActionList.push_back(PossiblePlayerBattleAction::WALK_AND_ATTACK); + } if(stack->canMove() && stack->getMovementRange(0)) //probably no reason to try move war machines or bound stacks allowedActionList.push_back(PossiblePlayerBattleAction::MOVE_STACK); @@ -683,6 +686,9 @@ bool CBattleInfoCallback::battleCanAttack(const battle::Unit * stack, const batt if(!battleMatchOwner(stack, target)) return false; + if (!stack->isMeleeAttacker()) + return false; + if (stack->getPosition() != dest) { for (const auto & obstacle : battleGetAllObstacles()) @@ -695,10 +701,6 @@ bool CBattleInfoCallback::battleCanAttack(const battle::Unit * stack, const batt } } - auto id = stack->unitType()->getId(); - if (id == CreatureID::FIRST_AID_TENT || id == CreatureID::CATAPULT) - return false; - return target->alive(); } diff --git a/lib/battle/CUnitState.cpp b/lib/battle/CUnitState.cpp index a6b64a472..237d8eef5 100644 --- a/lib/battle/CUnitState.cpp +++ b/lib/battle/CUnitState.cpp @@ -545,6 +545,22 @@ bool CUnitState::isShooter() const return shots.total() > 0; } +bool CUnitState::isMeleeAttacker() const +{ + //exclude non melee attackers + static const std::set nonMeleeAttackers{ + CreatureID::FIRST_AID_TENT, + CreatureID::CATAPULT, + CreatureID::BALLISTA, + CreatureID::AMMO_CART, + CreatureID::ARROW_TOWERS + }; + if (vstd::contains(nonMeleeAttackers, creatureId())) + return false; + + return true; +} + int32_t CUnitState::getKilled() const { int32_t res = unitBaseAmount() - health.getCount() + health.getResurrected(); diff --git a/lib/battle/CUnitState.h b/lib/battle/CUnitState.h index b1ec4a6d4..9dede8c62 100644 --- a/lib/battle/CUnitState.h +++ b/lib/battle/CUnitState.h @@ -205,6 +205,7 @@ public: bool canShootBlocked() const override; bool canShoot() const override; bool isShooter() const override; + bool isMeleeAttacker() const override; int32_t getKilled() const override; int32_t getCount() const override; diff --git a/lib/battle/Unit.h b/lib/battle/Unit.h index 37affcc0f..439ab0102 100644 --- a/lib/battle/Unit.h +++ b/lib/battle/Unit.h @@ -97,6 +97,7 @@ public: virtual bool canShootBlocked() const = 0; virtual bool canShoot() const = 0; virtual bool isShooter() const = 0; + virtual bool isMeleeAttacker() const = 0; /// returns initial size of this unit virtual int32_t getCount() const = 0;