#ifdef TESTS_BUILD #include "../../extern/catch.hpp" #include "../../src/Battling/Pokemon/CreatePokemon.hpp" #include "../../src/ScriptResolving/AngelScript/AngelScripResolver.hpp" #include "../TestLibrary/TestLibrary.hpp" #define AS_CLASS(name, contents) \ { #name, "namespace Pokemon{ class " #name " : PkmnScript { " contents "}}" } static std::unordered_map _scripts = std::unordered_map{ AS_CLASS(blankScript, ), AS_CLASS(stackScript, "int value = 0; void Stack() override { value++; } int GetValue() { return value; }"), AS_CLASS(onRemoveScript, "int value = 0; void OnRemove() override { value++; } int GetValue() { return value; }"), {"doubleInheritanceScript", R"( class doubleInheritanceScriptBase : PkmnScript { int value = 0; void Stack() override{ value++; } int GetValue(){ return value; } } class doubleInheritanceScript : doubleInheritanceScriptBase {} )"}, AS_CLASS(preventAttackScript, R"(void PreventAttack(ExecutingMove@ attack, bool& result) override{ result = !result; })"), AS_CLASS(stopBeforeAttackScript, R"( void StopBeforeAttack(ExecutingMove@ attack, bool& result) override{ result = !result; })"), AS_CLASS(OnBeforeAttackScript, "int value = 0; void OnBeforeAttack(ExecutingMove@ attack) override { value++; } " "int GetValue() { return value; }"), AS_CLASS( FailIncomingAttackScript, R"(void FailIncomingAttack(ExecutingMove@ attack, Pokemon@ target, bool& result) override{ result = !result; })"), AS_CLASS( IsInvulnerableScript, R"(void IsInvulnerable(ExecutingMove@ attack, Pokemon@ target, bool& result) override{ result = !result; })"), AS_CLASS(OnAttackMissScript, "int value = 0; void OnAttackMiss(ExecutingMove@ attack, Pokemon@ target) override { value++; } " "int GetValue() { return value; }"), AS_CLASS( ChangeAttackTypeScript, R"(void ChangeAttackType(ExecutingMove@ attack, Pokemon@ target, uint8 hit, uint8& outType) override{outType = 1; };)"), AS_CLASS( OnStatusMoveScript, "int value = 0; void OnStatusMove(ExecutingMove@ attack, Pokemon@ target, uint8 hit) override { value++; } " "int GetValue() { return value; }"), AS_CLASS( PreventSecondaryEffectsScript, R"(void PreventSecondaryEffects(ExecutingMove@ attack, Pokemon@ target, uint8 hit, bool& result) override{ result = !result; })"), AS_CLASS(OnSecondaryEffectScript, "int value = 0; void OnSecondaryEffect(ExecutingMove@ attack, Pokemon@ target, " "uint8 hit) override { value++; } " "int GetValue() { return value; }"), AS_CLASS(OnAfterHitsScript, "int value = 0; void OnAfterHits(ExecutingMove@ attack, Pokemon@ target) override { value++; } " "int GetValue() { return value; }"), AS_CLASS(throwScript, R"(void PreventAttack(ExecutingMove@ attack, bool& result) override{ throw("test exception"); })"), }; static AngelScripResolver* _resolverCache = nullptr; static AngelScripResolver* GetScriptResolver(PkmnLib::Battling::BattleLibrary* mainLib) { if (_resolverCache == nullptr) { _resolverCache = dynamic_cast(PkmnLib::Battling::BattleLibrary::CreateScriptResolver()); _resolverCache->Initialize(mainLib); for (auto kv : _scripts) { _resolverCache->CreateScript(kv.first, kv.second); } _resolverCache->FinalizeModule(); } return _resolverCache; } static AngelScriptScript* GetScript(PkmnLib::Battling::BattleLibrary* mainLib, const ConstString& scriptName) { auto lib = GetScriptResolver(mainLib); auto s = lib->LoadScript(ScriptCategory::Creature, scriptName); auto script = dynamic_cast(s); return script; } TEST_CASE("Invoke non-implemented script function") { auto mainLib = TestLibrary::GetLibrary(); auto script = GetScript(mainLib, "blankScript"_cnc); script->Stack(); delete script; } TEST_CASE("Invoke Stack script function") { auto mainLib = TestLibrary::GetLibrary(); auto script = GetScript(mainLib, "stackScript"_cnc); for (int i = 1; i <= 10; i++) { script->Stack(); auto ctxPool = script->GetContextPool(); auto ctx = ctxPool->RequestContext(); script->PrepareMethod("GetValue"_cnc, ctx); REQUIRE(ctx->Execute() == asEXECUTION_FINISHED); REQUIRE(ctx->GetReturnDWord() == i); ctxPool->ReturnContextToPool(ctx); } delete script; } TEST_CASE("Invoke OnRemove script function") { auto mainLib = TestLibrary::GetLibrary(); auto script = GetScript(mainLib, "onRemoveScript"_cnc); script->OnRemove(); auto ctxPool = script->GetContextPool(); auto ctx = ctxPool->RequestContext(); script->PrepareMethod("GetValue"_cnc, ctx); REQUIRE(ctx->Execute() == asEXECUTION_FINISHED); REQUIRE(ctx->GetReturnDWord() == 1); ctxPool->ReturnContextToPool(ctx); delete script; } TEST_CASE("Invoke Stack script function with implementation in base class") { auto mainLib = TestLibrary::GetLibrary(); auto script = GetScript(mainLib, "doubleInheritanceScript"_cnc); for (int i = 1; i <= 10; i++) { script->Stack(); auto ctxPool = script->GetContextPool(); auto ctx = ctxPool->RequestContext(); script->PrepareMethod("GetValue"_cnc, ctx); REQUIRE(ctx->Execute() == asEXECUTION_FINISHED); REQUIRE(ctx->GetReturnDWord() == i); ctxPool->ReturnContextToPool(ctx); } delete script; } TEST_CASE("Invoke preventAttackScript script function") { auto mainLib = TestLibrary::GetLibrary(); auto script = GetScript(mainLib, "preventAttackScript"_cnc); bool b = false; script->PreventAttack(nullptr, &b); REQUIRE(b); delete script; } TEST_CASE("Invoke StopBeforeAttack script function") { auto mainLib = TestLibrary::GetLibrary(); auto script = GetScript(mainLib, "stopBeforeAttackScript"_cnc); bool b = false; script->StopBeforeAttack(nullptr, &b); REQUIRE(b); delete script; } TEST_CASE("Invoke OnBeforeAttack script function") { auto mainLib = TestLibrary::GetLibrary(); auto script = GetScript(mainLib, "OnBeforeAttackScript"_cnc); script->OnBeforeAttack(nullptr); auto ctxPool = script->GetContextPool(); auto ctx = ctxPool->RequestContext(); script->PrepareMethod("GetValue"_cnc, ctx); REQUIRE(ctx->Execute() == asEXECUTION_FINISHED); REQUIRE(ctx->GetReturnDWord() == 1); ctxPool->ReturnContextToPool(ctx); delete script; } TEST_CASE("Invoke FailIncomingAttack script function") { auto mainLib = TestLibrary::GetLibrary(); auto script = GetScript(mainLib, "FailIncomingAttackScript"_cnc); bool b = false; script->FailIncomingAttack(nullptr, nullptr, &b); REQUIRE(b); delete script; } TEST_CASE("Invoke OnAttackMiss script function") { auto mainLib = TestLibrary::GetLibrary(); auto script = GetScript(mainLib, "OnAttackMissScript"_cnc); script->OnAttackMiss(nullptr, nullptr); auto ctxPool = script->GetContextPool(); auto ctx = ctxPool->RequestContext(); script->PrepareMethod("GetValue"_cnc, ctx); REQUIRE(ctx->Execute() == asEXECUTION_FINISHED); REQUIRE(ctx->GetReturnDWord() == 1); ctxPool->ReturnContextToPool(ctx); delete script; } TEST_CASE("Invoke ChangeAttackType script function") { auto mainLib = TestLibrary::GetLibrary(); auto script = GetScript(mainLib, "ChangeAttackTypeScript"_cnc); uint8_t b = 0; script->ChangeAttackType(nullptr, nullptr, 0, &b); REQUIRE(b == 1); delete script; } TEST_CASE("Invoke OnStatusMove script function") { auto mainLib = TestLibrary::GetLibrary(); auto script = GetScript(mainLib, "OnStatusMoveScript"_cnc); script->OnStatusMove(nullptr, nullptr, 0); auto ctxPool = script->GetContextPool(); auto ctx = ctxPool->RequestContext(); script->PrepareMethod("GetValue"_cnc, ctx); REQUIRE(ctx->Execute() == asEXECUTION_FINISHED); REQUIRE(ctx->GetReturnDWord() == 1); ctxPool->ReturnContextToPool(ctx); delete script; } TEST_CASE("Invoke PreventSecondaryEffects script function") { auto mainLib = TestLibrary::GetLibrary(); auto script = GetScript(mainLib, "PreventSecondaryEffectsScript"_cnc); bool b = false; script->PreventSecondaryEffects(nullptr, nullptr, 0, &b); REQUIRE(b); delete script; } TEST_CASE("Invoke OnSecondaryEffect script function") { auto mainLib = TestLibrary::GetLibrary(); auto script = GetScript(mainLib, "OnSecondaryEffectScript"_cnc); script->OnSecondaryEffect(nullptr, nullptr, 0); auto ctxPool = script->GetContextPool(); auto ctx = ctxPool->RequestContext(); script->PrepareMethod("GetValue"_cnc, ctx); REQUIRE(ctx->Execute() == asEXECUTION_FINISHED); REQUIRE(ctx->GetReturnDWord() == 1); ctxPool->ReturnContextToPool(ctx); delete script; } TEST_CASE("Invoke OnAfterHits script function") { auto mainLib = TestLibrary::GetLibrary(); auto script = GetScript(mainLib, "OnAfterHitsScript"_cnc); script->OnAfterHits(nullptr, nullptr); auto ctxPool = script->GetContextPool(); auto ctx = ctxPool->RequestContext(); script->PrepareMethod("GetValue"_cnc, ctx); REQUIRE(ctx->Execute() == asEXECUTION_FINISHED); REQUIRE(ctx->GetReturnDWord() == 1); ctxPool->ReturnContextToPool(ctx); delete script; } void TryException(AngelScriptScript* script) { bool b = false; script->PreventAttack(nullptr, &b); } TEST_CASE("Handle script exceptions.") { auto mainLib = TestLibrary::GetLibrary(); auto script = GetScript(mainLib, "throwScript"_cnc); CHECK_THROWS_WITH( TryException(script), Catch::Matchers::Equals("Script exception in script 'throwScript', line 1. Message: 'test exception'.")); delete script; } #endif