2021-05-24 08:31:15 +00:00
|
|
|
#include "ResolveTarget.hpp"
|
|
|
|
using namespace ArbUt;
|
|
|
|
using namespace CreatureLib::Library;
|
|
|
|
using namespace CreatureLib::Battling;
|
|
|
|
|
2021-05-24 08:34:42 +00:00
|
|
|
using TargetList = List<OptionalBorrowedPtr<Creature>>;
|
|
|
|
|
2022-03-23 12:56:45 +00:00
|
|
|
static inline constexpr u8 GetOppositeSide(u8 v) {
|
2021-05-24 08:31:15 +00:00
|
|
|
if (v == 1) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2021-05-24 08:34:42 +00:00
|
|
|
static inline TargetList GetAll(const BorrowedPtr<Battle>& battle) {
|
|
|
|
TargetList arr(battle->GetCreaturesPerSide() * battle->GetSides().Count());
|
2021-05-24 08:31:15 +00:00
|
|
|
for (auto* side : battle->GetSides()) {
|
|
|
|
for (const auto& mon : side->GetCreatures()) {
|
|
|
|
arr.Append(mon);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return arr;
|
|
|
|
}
|
|
|
|
|
2021-05-24 08:34:42 +00:00
|
|
|
static inline TargetList GetAllAdjacent(const CreatureIndex& index, const BorrowedPtr<Battle>& battle) {
|
2021-05-24 08:31:15 +00:00
|
|
|
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())};
|
|
|
|
}
|
|
|
|
|
2021-05-24 08:34:42 +00:00
|
|
|
static inline TargetList GetAllAdjacentOpponent(const CreatureIndex& index, const BorrowedPtr<Battle>& battle) {
|
2021-05-24 08:31:15 +00:00
|
|
|
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)};
|
|
|
|
}
|
|
|
|
|
2021-05-24 08:34:42 +00:00
|
|
|
TargetList TargetResolver::ResolveTargets(const CreatureIndex& index, AttackTarget target,
|
|
|
|
const BorrowedPtr<Battle>& battle) {
|
2021-05-24 08:31:15 +00:00
|
|
|
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: {
|
2021-05-24 08:34:42 +00:00
|
|
|
TargetList arr(battle->GetCreaturesPerSide());
|
2021-05-24 08:31:15 +00:00
|
|
|
for (const auto& mon : battle->GetSides()[index.GetSideIndex()]->GetCreatures()) {
|
|
|
|
arr.Append(mon);
|
|
|
|
}
|
|
|
|
return arr;
|
|
|
|
}
|
|
|
|
case AttackTarget::AllOpponent: {
|
2021-05-24 08:34:42 +00:00
|
|
|
TargetList arr(battle->GetCreaturesPerSide());
|
2021-05-24 08:31:15 +00:00
|
|
|
for (const auto& mon : battle->GetSides()[index.GetSideIndex()]->GetCreatures()) {
|
|
|
|
arr.Append(mon);
|
|
|
|
}
|
2021-05-24 08:34:42 +00:00
|
|
|
return arr;
|
2021-05-24 08:31:15 +00:00
|
|
|
}
|
|
|
|
}
|
2021-11-21 11:39:07 +00:00
|
|
|
THROW("Unknown attack target kind: '", AttackTargetHelper::ToString(target), "'.")
|
2021-05-24 08:31:15 +00:00
|
|
|
}
|
2021-05-24 08:57:17 +00:00
|
|
|
|
|
|
|
bool TargetResolver::IsValidTarget(const CreatureIndex& index, CreatureLib::Library::AttackTarget target,
|
|
|
|
const BorrowedPtr<Creature>& 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;
|
|
|
|
}
|
|
|
|
}
|
2021-11-21 11:39:07 +00:00
|
|
|
THROW("Unknown attack target kind: '", AttackTargetHelper::ToString(target), "'.")
|
2021-05-24 08:57:17 +00:00
|
|
|
}
|