#include "ResolveTarget.hpp" using namespace ArbUt; using namespace CreatureLib::Library; using namespace CreatureLib::Battling; using TargetList = List>; static inline constexpr u8 GetOppositeSide(u8 v) { if (v == 1) { return 0; } return 1; } static inline TargetList GetAll(const BorrowedPtr& battle) { TargetList arr(battle->GetCreaturesPerSide() * battle->GetSides().Count()); for (auto* side : battle->GetSides()) { for (const auto& mon : side->GetCreatures()) { arr.Append(mon); } } return arr; } static inline TargetList GetAllAdjacent(const CreatureIndex& index, const BorrowedPtr& battle) { auto left = index.GetCreatureIndex() - 1; auto right = index.GetCreatureIndex() + 1; if (left < 0 && right >= battle->GetCreaturesPerSide()) { return {battle->GetCreature(index), battle->GetCreature(GetOppositeSide(index.GetSideIndex()), index.GetCreatureIndex())}; } if (left >= 0) { if (right < battle->GetCreaturesPerSide()) { return {battle->GetCreature(index), battle->GetCreature(index.GetSideIndex(), left), battle->GetCreature(index.GetSideIndex(), right), battle->GetCreature(GetOppositeSide(index.GetSideIndex()), index.GetCreatureIndex())}; } return {battle->GetCreature(index), battle->GetCreature(index.GetSideIndex(), left), battle->GetCreature(GetOppositeSide(index.GetSideIndex()), index.GetCreatureIndex())}; } return {battle->GetCreature(index), battle->GetCreature(index.GetSideIndex(), right), battle->GetCreature(GetOppositeSide(index.GetSideIndex()), index.GetCreatureIndex())}; } static inline TargetList GetAllAdjacentOpponent(const CreatureIndex& index, const BorrowedPtr& battle) { auto left = index.GetCreatureIndex() - 1; auto right = index.GetCreatureIndex() + 1; if (left < 0 && right >= battle->GetCreaturesPerSide()) { return {battle->GetCreature(index)}; } if (left >= 0) { if (right < battle->GetCreaturesPerSide()) { return {battle->GetCreature(index), battle->GetCreature(index.GetSideIndex(), left), battle->GetCreature(index.GetSideIndex(), right)}; } return {battle->GetCreature(index), battle->GetCreature(index.GetSideIndex(), left)}; } return {battle->GetCreature(index), battle->GetCreature(index.GetSideIndex(), right)}; } TargetList TargetResolver::ResolveTargets(const CreatureIndex& index, AttackTarget target, const BorrowedPtr& battle) { switch (target) { // Single targets should just return the mon at the index. case AttackTarget::Adjacent: case AttackTarget::AdjacentAlly: case AttackTarget::AdjacentAllySelf: case AttackTarget::AdjacentOpponent: case AttackTarget::Any: case AttackTarget::RandomOpponent: case AttackTarget::Self: { return {battle->GetCreature(index)}; } case AttackTarget::All: { return GetAll(battle); } case AttackTarget::AllAdjacent: { return GetAllAdjacent(index, battle); } case AttackTarget::AllAdjacentOpponent: { return GetAllAdjacentOpponent(index, battle); } case AttackTarget::AllAlly: { TargetList arr(battle->GetCreaturesPerSide()); for (const auto& mon : battle->GetSides()[index.GetSideIndex()]->GetCreatures()) { arr.Append(mon); } return arr; } case AttackTarget::AllOpponent: { TargetList arr(battle->GetCreaturesPerSide()); for (const auto& mon : battle->GetSides()[index.GetSideIndex()]->GetCreatures()) { arr.Append(mon); } return arr; } } THROW("Unknown attack target kind: '", AttackTargetHelper::ToString(target), "'.") } bool TargetResolver::IsValidTarget(const CreatureIndex& index, CreatureLib::Library::AttackTarget target, const BorrowedPtr& user) { auto userIndex = user->GetBattleIndex(); switch (target) { case AttackTarget::Adjacent: case AttackTarget::AllAdjacent: { auto diff = abs(index.GetCreatureIndex() - userIndex.GetCreatureIndex()); // If the difference is 0, ensure the move is not targeting self. if (diff == 0) { return index.GetSideIndex() != userIndex.GetSideIndex(); } // Otherwise check if the difference is max 1. return diff <= 1; } case AttackTarget::AdjacentAlly: { if (index.GetSideIndex() != userIndex.GetSideIndex()) { return false; } auto diff = abs(index.GetCreatureIndex() - userIndex.GetCreatureIndex()); return diff == 1; } case AttackTarget::AdjacentAllySelf: { if (index.GetSideIndex() != userIndex.GetSideIndex()) { return false; } auto diff = abs(index.GetCreatureIndex() - userIndex.GetCreatureIndex()); return diff <= 1; } case AttackTarget::AdjacentOpponent: case AttackTarget::AllAdjacentOpponent: { if (index.GetSideIndex() == userIndex.GetSideIndex()) { return false; } auto diff = abs(index.GetCreatureIndex() - userIndex.GetCreatureIndex()); return diff <= 1; } case AttackTarget::All: case AttackTarget::Any: case AttackTarget::RandomOpponent: { return true; } case AttackTarget::AllAlly: { return index.GetSideIndex() == userIndex.GetSideIndex(); } case AttackTarget::AllOpponent: { return index.GetSideIndex() != userIndex.GetSideIndex(); } case AttackTarget::Self: { return index == userIndex; } } THROW("Unknown attack target kind: '", AttackTargetHelper::ToString(target), "'.") }