mirror of
https://github.com/EasyRPG/Player.git
synced 2026-10-27 10:48:51 +00:00
680 lines
23 KiB
C++
680 lines
23 KiB
C++
#include "test_mock_actor.h"
|
|
#include "enemyai.h"
|
|
#include "rand.h"
|
|
#include "algo.h"
|
|
#include "game_battlealgorithm.h"
|
|
#include "game_switches.h"
|
|
#include "main_data.h"
|
|
#include "doctest.h"
|
|
|
|
#include <iostream>
|
|
|
|
static Game_Enemy MakeEnemy(int id) {
|
|
MakeDBEnemy(id, 100, 100, 1, 1, 1, 1);
|
|
auto& tp = lcf::Data::troops[0];
|
|
tp.members.resize(8);
|
|
tp.members[id - 1].enemy_id = id;
|
|
Main_Data::game_enemyparty->ResetBattle(1);
|
|
auto& enemy = (*Main_Data::game_enemyparty)[id - 1];
|
|
return std::move(enemy);
|
|
}
|
|
|
|
decltype(auto) MakeActor(int id) {
|
|
auto actor = Game_Actor(id);
|
|
return actor;
|
|
}
|
|
|
|
lcf::rpg::Skill* MakeSkill(int id, int type, int scope) {
|
|
auto* s = MakeDBSkill(id, 90, 0, 0, 0, 0);
|
|
s->type = type;
|
|
s->scope = scope;
|
|
return s;
|
|
}
|
|
|
|
TEST_SUITE_BEGIN("EnemyAi");
|
|
|
|
static void testIrregularSkill(bool expect, int type, const Game_Battler& target, bool bugs) {
|
|
REQUIRE_EQ(expect, EnemyAi::IsSkillEffectiveOn(*MakeSkill(1, type, lcf::rpg::Skill::Scope_enemy), target, bugs));
|
|
REQUIRE_EQ(expect, EnemyAi::IsSkillEffectiveOn(*MakeSkill(1, type, lcf::rpg::Skill::Scope_enemies), target, bugs));
|
|
REQUIRE_EQ(expect, EnemyAi::IsSkillEffectiveOn(*MakeSkill(1, type, lcf::rpg::Skill::Scope_self), target, bugs));
|
|
REQUIRE_EQ(expect, EnemyAi::IsSkillEffectiveOn(*MakeSkill(1, type, lcf::rpg::Skill::Scope_ally), target, bugs));
|
|
REQUIRE_EQ(expect, EnemyAi::IsSkillEffectiveOn(*MakeSkill(1, type, lcf::rpg::Skill::Scope_party), target, bugs));
|
|
}
|
|
|
|
static void testNormalSkill(bool expect_enemy, bool expect_ally, lcf::rpg::Skill& skill, const Game_Battler& target, bool bugs) {
|
|
CAPTURE(bugs);
|
|
CAPTURE(target.IsDead());
|
|
CAPTURE(target.IsHidden());
|
|
CAPTURE(target.HasState(2));
|
|
CAPTURE(skill.scope);
|
|
|
|
skill.scope = lcf::rpg::Skill::Scope_enemy;
|
|
REQUIRE_EQ(expect_enemy, EnemyAi::IsSkillEffectiveOn(skill, target, bugs));
|
|
|
|
skill.scope = lcf::rpg::Skill::Scope_enemies;
|
|
REQUIRE_EQ(expect_enemy, EnemyAi::IsSkillEffectiveOn(skill, target, bugs));
|
|
|
|
skill.scope = lcf::rpg::Skill::Scope_self;
|
|
REQUIRE_EQ(expect_ally, EnemyAi::IsSkillEffectiveOn(skill, target, bugs));
|
|
|
|
skill.scope = lcf::rpg::Skill::Scope_ally;
|
|
REQUIRE_EQ(expect_ally, EnemyAi::IsSkillEffectiveOn(skill, target, bugs));
|
|
|
|
skill.scope = lcf::rpg::Skill::Scope_party;
|
|
REQUIRE_EQ(expect_ally, EnemyAi::IsSkillEffectiveOn(skill, target, bugs));
|
|
}
|
|
|
|
TEST_CASE("IsSkillEffectiveOn") {
|
|
const MockActor m;
|
|
|
|
std::vector<Game_Enemy> targets;
|
|
targets.push_back(MakeEnemy(1));
|
|
targets.push_back(MakeEnemy(2));
|
|
targets.back().Kill();
|
|
targets.push_back(MakeEnemy(3));
|
|
targets.back().SetHidden(true);
|
|
targets.push_back(MakeEnemy(4));
|
|
targets.back().Kill();
|
|
targets.back().SetHidden(true);
|
|
targets.push_back(MakeEnemy(5));
|
|
targets.back().AddState(2, true);
|
|
|
|
SUBCASE("Switch") {
|
|
for (auto& t: targets) {
|
|
testIrregularSkill(true, lcf::rpg::Skill::Type_switch, t, true);
|
|
testIrregularSkill(true, lcf::rpg::Skill::Type_switch, t, false);
|
|
}
|
|
}
|
|
|
|
SUBCASE("Escape") {
|
|
for (auto& t: targets) {
|
|
testIrregularSkill(false, lcf::rpg::Skill::Type_escape, t, true);
|
|
testIrregularSkill(false, lcf::rpg::Skill::Type_escape, t, false);
|
|
}
|
|
}
|
|
|
|
SUBCASE("Teleport") {
|
|
for (auto& t: targets) {
|
|
testIrregularSkill(false, lcf::rpg::Skill::Type_teleport, t, true);
|
|
testIrregularSkill(false, lcf::rpg::Skill::Type_teleport, t, false);
|
|
}
|
|
}
|
|
|
|
SUBCASE("Normal") {
|
|
auto* skill = MakeSkill(1, lcf::rpg::Skill::Type_normal, lcf::rpg::Skill::Scope_self);
|
|
|
|
SUBCASE("None") {
|
|
for (auto& t: targets) {
|
|
testNormalSkill(t.Exists(), false, *skill, t, true);
|
|
testNormalSkill(t.Exists(), false, *skill, t, false);
|
|
}
|
|
}
|
|
|
|
SUBCASE("Hp") {
|
|
skill->affect_hp = true;
|
|
for (auto& t: targets) {
|
|
testNormalSkill(t.Exists(), t.Exists(), *skill, t, true);
|
|
testNormalSkill(t.Exists(), t.Exists(), *skill, t, false);
|
|
}
|
|
}
|
|
|
|
SUBCASE("Sp") {
|
|
skill->affect_sp = true;
|
|
for (auto& t: targets) {
|
|
testNormalSkill(t.Exists(), t.Exists(), *skill, t, true);
|
|
testNormalSkill(t.Exists(), t.Exists(), *skill, t, false);
|
|
}
|
|
}
|
|
|
|
SUBCASE("Atk") {
|
|
skill->affect_attack = true;
|
|
for (auto& t: targets) {
|
|
testNormalSkill(t.Exists(), t.Exists(), *skill, t, true);
|
|
testNormalSkill(t.Exists(), t.Exists(), *skill, t, false);
|
|
}
|
|
}
|
|
|
|
SUBCASE("Def") {
|
|
skill->affect_defense = true;
|
|
for (auto& t: targets) {
|
|
testNormalSkill(t.Exists(), t.Exists(), *skill, t, true);
|
|
testNormalSkill(t.Exists(), t.Exists(), *skill, t, false);
|
|
}
|
|
}
|
|
|
|
SUBCASE("Spi") {
|
|
skill->affect_spirit = true;
|
|
for (auto& t: targets) {
|
|
testNormalSkill(t.Exists(), t.Exists(), *skill, t, true);
|
|
testNormalSkill(t.Exists(), t.Exists(), *skill, t, false);
|
|
}
|
|
}
|
|
|
|
SUBCASE("Agi") {
|
|
skill->affect_agility = true;
|
|
for (auto& t: targets) {
|
|
testNormalSkill(t.Exists(), t.Exists(), *skill, t, true);
|
|
testNormalSkill(t.Exists(), t.Exists(), *skill, t, false);
|
|
}
|
|
}
|
|
|
|
SUBCASE("Death") {
|
|
skill->state_effects = { true };
|
|
for (auto& t: targets) {
|
|
testNormalSkill(t.Exists(), !t.Exists(), *skill, t, true);
|
|
testNormalSkill(t.Exists(), t.IsDead(), *skill, t, false);
|
|
}
|
|
}
|
|
|
|
SUBCASE("ReverseDeath") {
|
|
skill->state_effects = { true };
|
|
skill->reverse_state_effect = true;
|
|
for (auto& t: targets) {
|
|
testNormalSkill(t.Exists(), !t.Exists(), *skill, t, true);
|
|
testNormalSkill(t.Exists(), !t.IsDead() && t.Exists(), *skill, t, false);
|
|
}
|
|
}
|
|
|
|
SUBCASE("State") {
|
|
skill->state_effects = { false, true };
|
|
for (auto& t: targets) {
|
|
testNormalSkill(t.Exists(), t.Exists() && t.HasState(2), *skill, t, true);
|
|
testNormalSkill(t.Exists(), t.Exists() && t.HasState(2), *skill, t, false);
|
|
}
|
|
}
|
|
|
|
SUBCASE("ReverseState") {
|
|
skill->state_effects = { false, true };
|
|
skill->reverse_state_effect = true;
|
|
for (auto& t: targets) {
|
|
testNormalSkill(t.Exists(), t.Exists() && t.HasState(2), *skill, t, true);
|
|
testNormalSkill(t.Exists(), t.Exists(), *skill, t, false);
|
|
}
|
|
}
|
|
|
|
SUBCASE("Attribute") {
|
|
skill->attribute_effects = { true };
|
|
for (auto& t: targets) {
|
|
testNormalSkill(t.Exists(), false, *skill, t, true);
|
|
testNormalSkill(t.Exists(), false, *skill, t, false);
|
|
}
|
|
}
|
|
|
|
SUBCASE("AttributeEffect") {
|
|
skill->attribute_effects = { true };
|
|
skill->affect_attr_defence = true;
|
|
for (auto& t: targets) {
|
|
testNormalSkill(t.Exists(), t.Exists(), *skill, t, true);
|
|
testNormalSkill(t.Exists(), t.Exists(), *skill, t, false);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
TEST_CASE("NoActions") {
|
|
const MockActor m;
|
|
|
|
auto enemy = MakeEnemy(1);
|
|
EnemyAi::SelectEnemyAiActionRpgRtCompat(enemy, true);
|
|
REQUIRE_EQ(enemy.GetBattleAlgorithm(), nullptr);
|
|
}
|
|
|
|
namespace {
|
|
struct ActionParams {
|
|
int rating;
|
|
int kind;
|
|
int basic;
|
|
};
|
|
}
|
|
|
|
static std::vector<lcf::rpg::EnemyAction> MakeActions(std::initializer_list<ActionParams> ilist) {
|
|
std::vector<lcf::rpg::EnemyAction> actions;
|
|
for (auto& il: ilist) {
|
|
actions.push_back({});
|
|
actions.back().rating = il.rating;
|
|
actions.back().kind = il.kind;
|
|
actions.back().basic = il.basic;
|
|
}
|
|
return actions;
|
|
}
|
|
|
|
static void testActionType(int start, int end, Game_BattleAlgorithm::Type type_compat, Game_BattleAlgorithm::Type type_improved, Game_Enemy& source) {
|
|
for (int rng = start; rng < end; ++rng) {
|
|
CAPTURE(rng);
|
|
bool bugs = true;
|
|
CAPTURE(bugs);
|
|
|
|
Rand::LockGuard lk(rng);
|
|
bugs = true;
|
|
source.SetBattleAlgorithm(nullptr);
|
|
EnemyAi::SelectEnemyAiActionRpgRtCompat(source, bugs);
|
|
REQUIRE(source.GetBattleAlgorithm());
|
|
REQUIRE_EQ(static_cast<int>(type_compat), static_cast<int>(source.GetBattleAlgorithm()->GetType()));
|
|
|
|
bugs = false;
|
|
source.SetBattleAlgorithm(nullptr);
|
|
EnemyAi::SelectEnemyAiActionRpgRtCompat(source, bugs);
|
|
REQUIRE(source.GetBattleAlgorithm());
|
|
REQUIRE_EQ(static_cast<int>(type_improved), static_cast<int>(source.GetBattleAlgorithm()->GetType()));
|
|
}
|
|
}
|
|
|
|
static void testActionNullptr(int start, int end, Game_Enemy& source) {
|
|
for (int rng = start; rng < end; ++rng) {
|
|
CAPTURE(rng);
|
|
bool bugs = true;
|
|
CAPTURE(bugs);
|
|
|
|
Rand::LockGuard lk(rng);
|
|
bugs = true;
|
|
source.SetBattleAlgorithm(nullptr);
|
|
EnemyAi::SelectEnemyAiActionRpgRtCompat(source, bugs);
|
|
REQUIRE_FALSE(source.GetBattleAlgorithm());
|
|
|
|
bugs = false;
|
|
source.SetBattleAlgorithm(nullptr);
|
|
EnemyAi::SelectEnemyAiActionRpgRtCompat(source, bugs);
|
|
REQUIRE_FALSE(source.GetBattleAlgorithm());
|
|
}
|
|
}
|
|
|
|
TEST_CASE("Ratings") {
|
|
const MockActor m;
|
|
|
|
auto enemy = MakeEnemy(1);
|
|
auto& actions = lcf::Data::enemies[0].actions;
|
|
|
|
SUBCASE("40/50") {
|
|
actions = MakeActions({{40, 0, lcf::rpg::EnemyAction::Basic_attack }, { 50, 0, lcf::rpg::EnemyAction::Basic_defense }});
|
|
testActionType(0, 100, Game_BattleAlgorithm::Type::Defend, Game_BattleAlgorithm::Type::Defend, enemy);
|
|
}
|
|
|
|
SUBCASE("50/40") {
|
|
actions = MakeActions({{50, 0, lcf::rpg::EnemyAction::Basic_attack }, { 40, 0, lcf::rpg::EnemyAction::Basic_defense }});
|
|
testActionType(0, 100, Game_BattleAlgorithm::Type::Normal, Game_BattleAlgorithm::Type::Normal, enemy);
|
|
}
|
|
|
|
SUBCASE("41/50") {
|
|
actions = MakeActions({{41, 0, lcf::rpg::EnemyAction::Basic_attack }, { 50, 0, lcf::rpg::EnemyAction::Basic_defense }});
|
|
testActionType(0, 1, Game_BattleAlgorithm::Type::Normal, Game_BattleAlgorithm::Type::Normal, enemy);
|
|
testActionType(1, 100, Game_BattleAlgorithm::Type::Defend, Game_BattleAlgorithm::Type::Defend, enemy);
|
|
}
|
|
|
|
SUBCASE("45/50") {
|
|
actions = MakeActions({{45, 0, lcf::rpg::EnemyAction::Basic_attack }, { 50, 0, lcf::rpg::EnemyAction::Basic_defense }});
|
|
testActionType(0, 5, Game_BattleAlgorithm::Type::Normal, Game_BattleAlgorithm::Type::Normal, enemy);
|
|
testActionType(5, 100, Game_BattleAlgorithm::Type::Defend, Game_BattleAlgorithm::Type::Defend, enemy);
|
|
}
|
|
|
|
SUBCASE("49/50") {
|
|
actions = MakeActions({{49, 0, lcf::rpg::EnemyAction::Basic_attack }, { 50, 0, lcf::rpg::EnemyAction::Basic_defense }});
|
|
testActionType(0, 9, Game_BattleAlgorithm::Type::Normal, Game_BattleAlgorithm::Type::Normal, enemy);
|
|
testActionType(9, 100, Game_BattleAlgorithm::Type::Defend, Game_BattleAlgorithm::Type::Defend, enemy);
|
|
}
|
|
|
|
SUBCASE("50/50") {
|
|
actions = MakeActions({{50, 0, lcf::rpg::EnemyAction::Basic_attack }, { 50, 0, lcf::rpg::EnemyAction::Basic_defense }});
|
|
testActionType(0, 10, Game_BattleAlgorithm::Type::Normal, Game_BattleAlgorithm::Type::Normal, enemy);
|
|
testActionType(10, 100, Game_BattleAlgorithm::Type::Defend, Game_BattleAlgorithm::Type::Defend, enemy);
|
|
}
|
|
|
|
SUBCASE("50/30/50") {
|
|
actions = MakeActions({{50, 0, lcf::rpg::EnemyAction::Basic_attack }, { 30, 0, lcf::rpg::EnemyAction::Basic_defense }, { 50, 0, lcf::rpg::EnemyAction::Basic_observe }});
|
|
testActionType(0, 10, Game_BattleAlgorithm::Type::Normal, Game_BattleAlgorithm::Type::Normal, enemy);
|
|
testActionType(10, 100, Game_BattleAlgorithm::Type::Observe, Game_BattleAlgorithm::Type::Observe, enemy);
|
|
}
|
|
}
|
|
|
|
TEST_CASE("SkillEffectiveButNotUsable") {
|
|
const MockActor m;
|
|
|
|
auto enemy = MakeEnemy(1);
|
|
auto& actions = lcf::Data::enemies[0].actions;
|
|
auto* skill = MakeSkill(1, lcf::rpg::Skill::Type_normal, lcf::rpg::Skill::Scope_self);
|
|
skill->affect_hp = true;
|
|
skill->sp_cost = 10;
|
|
|
|
actions = MakeActions({{50, lcf::rpg::EnemyAction::Kind_skill, 0}, { 50, 0, lcf::rpg::EnemyAction::Basic_attack }});
|
|
actions.front().skill_id = 1;
|
|
|
|
REQUIRE(EnemyAi::IsSkillEffectiveOn(*skill, enemy, true));
|
|
|
|
SUBCASE("HasSp") {
|
|
enemy.SetSp(100);
|
|
REQUIRE_EQ(100, enemy.GetSp());
|
|
REQUIRE(enemy.IsSkillUsable(1));
|
|
testActionType(0, 10, Game_BattleAlgorithm::Type::Skill, Game_BattleAlgorithm::Type::Skill, enemy);
|
|
testActionType(10, 100, Game_BattleAlgorithm::Type::Normal, Game_BattleAlgorithm::Type::Normal, enemy);
|
|
}
|
|
|
|
SUBCASE("NoSp") {
|
|
enemy.SetSp(0);
|
|
REQUIRE_FALSE(enemy.IsSkillUsable(1));
|
|
testActionType(0, 100, Game_BattleAlgorithm::Type::Normal, Game_BattleAlgorithm::Type::Normal, enemy);
|
|
}
|
|
}
|
|
|
|
TEST_CASE("SkillUsableButNotEffective") {
|
|
const MockActor m;
|
|
|
|
auto enemy = MakeEnemy(1);
|
|
|
|
auto& actions = lcf::Data::enemies[0].actions;
|
|
auto* skill = MakeSkill(1, lcf::rpg::Skill::Type_normal, lcf::rpg::Skill::Scope_self);
|
|
skill->sp_cost = 0;
|
|
skill->state_effects = { false, true };
|
|
lcf::Data::states[1].type = lcf::rpg::State::Persistence_persists;
|
|
|
|
REQUIRE(enemy.IsSkillUsable(1));
|
|
REQUIRE_FALSE(EnemyAi::IsSkillEffectiveOn(*skill, enemy, true));
|
|
|
|
SUBCASE("50/50") {
|
|
actions = MakeActions({{50, lcf::rpg::EnemyAction::Kind_skill, 0}, { 50, 0, lcf::rpg::EnemyAction::Basic_attack }});
|
|
testActionType(0, 100, Game_BattleAlgorithm::Type::Normal, Game_BattleAlgorithm::Type::Normal, enemy);
|
|
}
|
|
|
|
SUBCASE("70/50") {
|
|
// If the only valid action is a not effective skill, it's still chosen, but then rejected.
|
|
actions = MakeActions({{70, lcf::rpg::EnemyAction::Kind_skill, 0}, { 50, 0, lcf::rpg::EnemyAction::Basic_attack }});
|
|
testActionNullptr(0, 100, enemy);
|
|
}
|
|
}
|
|
|
|
TEST_CASE("ConditionSwitch") {
|
|
const MockActor m;
|
|
|
|
auto enemy = MakeEnemy(1);
|
|
auto& actions = lcf::Data::enemies[0].actions;
|
|
|
|
actions = MakeActions({{90, 0, lcf::rpg::EnemyAction::Basic_attack }, { 50, 0, lcf::rpg::EnemyAction::Basic_defense }});
|
|
actions.front().condition_type = lcf::rpg::EnemyAction::ConditionType_switch;
|
|
actions.front().switch_id = 1;
|
|
|
|
SUBCASE("SwOff") {
|
|
Main_Data::game_switches->Set(1, false);
|
|
testActionType(0, 100, Game_BattleAlgorithm::Type::Defend, Game_BattleAlgorithm::Type::Defend, enemy);
|
|
}
|
|
|
|
SUBCASE("SwOn") {
|
|
Main_Data::game_switches->Set(1, true);
|
|
testActionType(0, 100, Game_BattleAlgorithm::Type::Normal, Game_BattleAlgorithm::Type::Normal, enemy);
|
|
}
|
|
}
|
|
|
|
TEST_CASE("ConditionTurns") {
|
|
const MockActor m;
|
|
|
|
auto enemy = MakeEnemy(1);
|
|
auto& actions = lcf::Data::enemies[0].actions;
|
|
|
|
actions = MakeActions({{90, 0, lcf::rpg::EnemyAction::Basic_attack }, { 50, 0, lcf::rpg::EnemyAction::Basic_defense }});
|
|
actions.front().condition_type = lcf::rpg::EnemyAction::ConditionType_turn;
|
|
|
|
Main_Data::game_party->ResetTurns();
|
|
|
|
SUBCASE("0/0") {
|
|
actions.front().condition_param2 = 0;
|
|
actions.front().condition_param1 = 0;
|
|
testActionType(0, 100, Game_BattleAlgorithm::Type::Normal, Game_BattleAlgorithm::Type::Normal, enemy);
|
|
}
|
|
|
|
SUBCASE("1/1") {
|
|
actions.front().condition_param2 = 1;
|
|
actions.front().condition_param1 = 1;
|
|
testActionType(0, 100, Game_BattleAlgorithm::Type::Defend, Game_BattleAlgorithm::Type::Defend, enemy);
|
|
}
|
|
}
|
|
|
|
TEST_CASE("MonsterParty") {
|
|
const MockActor m;
|
|
|
|
auto enemy = MakeEnemy(1);
|
|
auto& actions = lcf::Data::enemies[0].actions;
|
|
|
|
actions = MakeActions({{90, 0, lcf::rpg::EnemyAction::Basic_attack }, { 50, 0, lcf::rpg::EnemyAction::Basic_defense }});
|
|
actions.front().condition_type = lcf::rpg::EnemyAction::ConditionType_actors;
|
|
|
|
std::vector<Game_Battler*> battlers;
|
|
Main_Data::game_enemyparty->GetActiveBattlers(battlers);
|
|
REQUIRE_EQ(8, battlers.size());
|
|
|
|
SUBCASE("1/1") {
|
|
actions.front().condition_param1 = 1;
|
|
actions.front().condition_param2 = 1;
|
|
testActionType(0, 100, Game_BattleAlgorithm::Type::Defend, Game_BattleAlgorithm::Type::Defend, enemy);
|
|
}
|
|
|
|
SUBCASE("1/8") {
|
|
actions.front().condition_param1 = 1;
|
|
actions.front().condition_param2 = 8;
|
|
testActionType(0, 100, Game_BattleAlgorithm::Type::Normal, Game_BattleAlgorithm::Type::Normal, enemy);
|
|
}
|
|
|
|
SUBCASE("1/7") {
|
|
actions.front().condition_param1 = 1;
|
|
actions.front().condition_param2 = 7;
|
|
testActionType(0, 100, Game_BattleAlgorithm::Type::Defend, Game_BattleAlgorithm::Type::Defend, enemy);
|
|
}
|
|
|
|
SUBCASE("9/10") {
|
|
actions.front().condition_param1 = 9;
|
|
actions.front().condition_param2 = 10;
|
|
testActionType(0, 100, Game_BattleAlgorithm::Type::Defend, Game_BattleAlgorithm::Type::Defend, enemy);
|
|
}
|
|
}
|
|
|
|
TEST_CASE("ConditionHp") {
|
|
const MockActor m;
|
|
|
|
auto enemy = MakeEnemy(1);
|
|
auto& actions = lcf::Data::enemies[0].actions;
|
|
|
|
actions = MakeActions({{90, 0, lcf::rpg::EnemyAction::Basic_attack }, { 50, 0, lcf::rpg::EnemyAction::Basic_defense }});
|
|
actions.front().condition_type = lcf::rpg::EnemyAction::ConditionType_hp;
|
|
|
|
REQUIRE_EQ(100, enemy.GetMaxHp());
|
|
enemy.SetHp(50);
|
|
REQUIRE_EQ(50, enemy.GetHp());
|
|
|
|
SUBCASE("0/100") {
|
|
actions.front().condition_param1 = 0;
|
|
actions.front().condition_param2 = 100;
|
|
testActionType(0, 100, Game_BattleAlgorithm::Type::Normal, Game_BattleAlgorithm::Type::Normal, enemy);
|
|
}
|
|
|
|
SUBCASE("50/50") {
|
|
actions.front().condition_param1 = 50;
|
|
actions.front().condition_param2 = 50;
|
|
testActionType(0, 100, Game_BattleAlgorithm::Type::Normal, Game_BattleAlgorithm::Type::Normal, enemy);
|
|
}
|
|
|
|
SUBCASE("51/100") {
|
|
actions.front().condition_param1 = 51;
|
|
actions.front().condition_param2 = 100;
|
|
testActionType(0, 100, Game_BattleAlgorithm::Type::Defend, Game_BattleAlgorithm::Type::Defend, enemy);
|
|
}
|
|
|
|
SUBCASE("0/49") {
|
|
actions.front().condition_param1 = 0;
|
|
actions.front().condition_param2 = 49;
|
|
testActionType(0, 100, Game_BattleAlgorithm::Type::Defend, Game_BattleAlgorithm::Type::Defend, enemy);
|
|
}
|
|
}
|
|
|
|
TEST_CASE("ConditionSp") {
|
|
const MockActor m;
|
|
|
|
auto enemy = MakeEnemy(1);
|
|
auto& actions = lcf::Data::enemies[0].actions;
|
|
|
|
actions = MakeActions({{90, 0, lcf::rpg::EnemyAction::Basic_attack }, { 50, 0, lcf::rpg::EnemyAction::Basic_defense }});
|
|
actions.front().condition_type = lcf::rpg::EnemyAction::ConditionType_sp;
|
|
|
|
REQUIRE_EQ(100, enemy.GetMaxSp());
|
|
enemy.SetSp(50);
|
|
REQUIRE_EQ(50, enemy.GetSp());
|
|
|
|
SUBCASE("0/100") {
|
|
actions.front().condition_param1 = 0;
|
|
actions.front().condition_param2 = 100;
|
|
testActionType(0, 100, Game_BattleAlgorithm::Type::Normal, Game_BattleAlgorithm::Type::Normal, enemy);
|
|
}
|
|
|
|
SUBCASE("50/50") {
|
|
actions.front().condition_param1 = 50;
|
|
actions.front().condition_param2 = 50;
|
|
testActionType(0, 100, Game_BattleAlgorithm::Type::Normal, Game_BattleAlgorithm::Type::Normal, enemy);
|
|
}
|
|
|
|
SUBCASE("51/100") {
|
|
actions.front().condition_param1 = 51;
|
|
actions.front().condition_param2 = 100;
|
|
testActionType(0, 100, Game_BattleAlgorithm::Type::Defend, Game_BattleAlgorithm::Type::Defend, enemy);
|
|
}
|
|
|
|
SUBCASE("0/49") {
|
|
actions.front().condition_param1 = 0;
|
|
actions.front().condition_param2 = 49;
|
|
testActionType(0, 100, Game_BattleAlgorithm::Type::Defend, Game_BattleAlgorithm::Type::Defend, enemy);
|
|
}
|
|
}
|
|
|
|
TEST_CASE("ConditionLevel") {
|
|
const MockActor m;
|
|
|
|
auto enemy = MakeEnemy(1);
|
|
auto& actions = lcf::Data::enemies[0].actions;
|
|
|
|
actions = MakeActions({{90, 0, lcf::rpg::EnemyAction::Basic_attack }, { 50, 0, lcf::rpg::EnemyAction::Basic_defense }});
|
|
actions.front().condition_type = lcf::rpg::EnemyAction::ConditionType_party_lvl;
|
|
|
|
Main_Data::game_party->AddActor(1);
|
|
Main_Data::game_actors->GetActor(1)->SetLevel(20);
|
|
Main_Data::game_party->AddActor(2);
|
|
Main_Data::game_actors->GetActor(2)->SetLevel(10);
|
|
|
|
REQUIRE_EQ(15, Main_Data::game_party->GetAverageLevel());
|
|
|
|
SUBCASE("0/50") {
|
|
actions.front().condition_param1 = 0;
|
|
actions.front().condition_param2 = 50;
|
|
testActionType(0, 100, Game_BattleAlgorithm::Type::Normal, Game_BattleAlgorithm::Type::Normal, enemy);
|
|
}
|
|
|
|
SUBCASE("15/15") {
|
|
actions.front().condition_param1 = 15;
|
|
actions.front().condition_param2 = 15;
|
|
testActionType(0, 100, Game_BattleAlgorithm::Type::Normal, Game_BattleAlgorithm::Type::Normal, enemy);
|
|
}
|
|
|
|
SUBCASE("16/50") {
|
|
actions.front().condition_param1 = 16;
|
|
actions.front().condition_param2 = 50;
|
|
testActionType(0, 100, Game_BattleAlgorithm::Type::Defend, Game_BattleAlgorithm::Type::Defend, enemy);
|
|
}
|
|
|
|
SUBCASE("0/14") {
|
|
actions.front().condition_param1 = 0;
|
|
actions.front().condition_param2 = 14;
|
|
testActionType(0, 100, Game_BattleAlgorithm::Type::Defend, Game_BattleAlgorithm::Type::Defend, enemy);
|
|
}
|
|
}
|
|
|
|
TEST_CASE("ConditionFatigue") {
|
|
const MockActor m;
|
|
|
|
auto enemy = MakeEnemy(1);
|
|
auto& actions = lcf::Data::enemies[0].actions;
|
|
|
|
actions = MakeActions({{90, 0, lcf::rpg::EnemyAction::Basic_attack }, { 50, 0, lcf::rpg::EnemyAction::Basic_defense }});
|
|
actions.front().condition_type = lcf::rpg::EnemyAction::ConditionType_party_fatigue;
|
|
|
|
Main_Data::game_party->AddActor(1);
|
|
Main_Data::game_actors->GetActor(1)->SetBaseMaxHp(100);
|
|
Main_Data::game_actors->GetActor(1)->SetHp(50);
|
|
Main_Data::game_actors->GetActor(1)->SetBaseMaxSp(0);
|
|
Main_Data::game_actors->GetActor(1)->SetSp(0);
|
|
Main_Data::game_party->AddActor(2);
|
|
Main_Data::game_actors->GetActor(2)->SetBaseMaxHp(100);
|
|
Main_Data::game_actors->GetActor(2)->SetHp(80);
|
|
Main_Data::game_actors->GetActor(2)->SetBaseMaxSp(0);
|
|
Main_Data::game_actors->GetActor(2)->SetSp(0);
|
|
|
|
REQUIRE_EQ(57, Main_Data::game_party->GetFatigue());
|
|
|
|
SUBCASE("0/100") {
|
|
actions.front().condition_param1 = 0;
|
|
actions.front().condition_param2 = 100;
|
|
testActionType(0, 100, Game_BattleAlgorithm::Type::Normal, Game_BattleAlgorithm::Type::Normal, enemy);
|
|
}
|
|
|
|
SUBCASE("57/57") {
|
|
actions.front().condition_param1 = 57;
|
|
actions.front().condition_param2 = 57;
|
|
testActionType(0, 100, Game_BattleAlgorithm::Type::Normal, Game_BattleAlgorithm::Type::Normal, enemy);
|
|
}
|
|
|
|
SUBCASE("58/100") {
|
|
actions.front().condition_param1 = 58;
|
|
actions.front().condition_param2 = 100;
|
|
testActionType(0, 100, Game_BattleAlgorithm::Type::Defend, Game_BattleAlgorithm::Type::Defend, enemy);
|
|
}
|
|
|
|
SUBCASE("0/56") {
|
|
actions.front().condition_param1 = 0;
|
|
actions.front().condition_param2 = 56;
|
|
testActionType(0, 100, Game_BattleAlgorithm::Type::Defend, Game_BattleAlgorithm::Type::Defend, enemy);
|
|
}
|
|
}
|
|
|
|
TEST_CASE("SetStateRestrictedAction") {
|
|
const MockActor m;
|
|
|
|
auto enemy = MakeEnemy(1);
|
|
Main_Data::game_party->AddActor(1);
|
|
lcf::Data::states[1].restriction = lcf::rpg::State::Restriction_do_nothing;
|
|
lcf::Data::states[2].restriction = lcf::rpg::State::Restriction_attack_ally;
|
|
lcf::Data::states[3].restriction = lcf::rpg::State::Restriction_attack_enemy;
|
|
|
|
REQUIRE_EQ(nullptr, enemy.GetBattleAlgorithm());
|
|
|
|
SUBCASE("None") {
|
|
REQUIRE_FALSE(EnemyAi::SetStateRestrictedAction(enemy));
|
|
REQUIRE_FALSE(enemy.GetBattleAlgorithm());
|
|
}
|
|
|
|
SUBCASE("Charged") {
|
|
enemy.SetCharged(true);
|
|
REQUIRE(EnemyAi::SetStateRestrictedAction(enemy));
|
|
REQUIRE(enemy.GetBattleAlgorithm());
|
|
REQUIRE_EQ(static_cast<int>(Game_BattleAlgorithm::Type::Normal), static_cast<int>(enemy.GetBattleAlgorithm()->GetType()));
|
|
}
|
|
|
|
SUBCASE("NoAct") {
|
|
enemy.AddState(2, true);
|
|
REQUIRE(EnemyAi::SetStateRestrictedAction(enemy));
|
|
REQUIRE(enemy.GetBattleAlgorithm());
|
|
REQUIRE_EQ(static_cast<int>(Game_BattleAlgorithm::Type::None), static_cast<int>(enemy.GetBattleAlgorithm()->GetType()));
|
|
}
|
|
|
|
SUBCASE("Confuse") {
|
|
enemy.AddState(3, true);
|
|
REQUIRE(EnemyAi::SetStateRestrictedAction(enemy));
|
|
REQUIRE(enemy.GetBattleAlgorithm());
|
|
REQUIRE_EQ(static_cast<int>(Game_BattleAlgorithm::Type::Normal), static_cast<int>(enemy.GetBattleAlgorithm()->GetType()));
|
|
enemy.GetBattleAlgorithm()->Start();
|
|
REQUIRE_EQ(static_cast<int>(Game_Battler::Type_Enemy), static_cast<int>(enemy.GetBattleAlgorithm()->GetTarget()->GetType()));
|
|
}
|
|
|
|
SUBCASE("Provoke") {
|
|
enemy.AddState(4, true);
|
|
REQUIRE(EnemyAi::SetStateRestrictedAction(enemy));
|
|
REQUIRE(enemy.GetBattleAlgorithm());
|
|
REQUIRE_EQ(static_cast<int>(Game_BattleAlgorithm::Type::Normal), static_cast<int>(enemy.GetBattleAlgorithm()->GetType()));
|
|
enemy.GetBattleAlgorithm()->Start();
|
|
REQUIRE_EQ(static_cast<int>(Game_Battler::Type_Ally), static_cast<int>(enemy.GetBattleAlgorithm()->GetTarget()->GetType()));
|
|
}
|
|
}
|
|
|
|
TEST_SUITE_END();
|