From f33d96d9224d0f3884174311d901a791b3f1a314 Mon Sep 17 00:00:00 2001 From: Deukhoofd Date: Sat, 1 Feb 2020 16:56:09 +0100 Subject: [PATCH] Many tweaks and fixes relating to AngelScript, implements shininess. --- conanfile.py | 2 +- src/AngelScript/AngelScriptTypeInfo.hpp | 4 +- .../Battling/RegisterPokemonClass.cpp | 23 +- .../Library/RegisterStaticLibraryTypes.cpp | 2 +- src/Battling/Library/BattleLibrary.hpp | 4 + src/Battling/Pokemon/CreatePokemon.cpp | 55 +++- src/Battling/Pokemon/CreatePokemon.hpp | 11 +- src/Battling/Pokemon/Pokemon.hpp | 4 + src/Library/Items/ItemLibrary.hpp | 3 + src/Library/LibrarySettings.hpp | 18 ++ src/Library/Moves/MoveLibrary.hpp | 3 + src/Library/PokemonLibrary.hpp | 7 +- src/Library/Species/SpeciesLibrary.hpp | 5 + .../ScriptTypeTests/Battle/PokemonTests.cpp | 255 ++++++++++++++++++ .../ScriptTypeTests/Library/FormesTests.cpp | 19 +- .../ScriptTypeTests/Library/ItemDataTests.cpp | 19 +- .../ScriptTypeTests/Library/MoveTests.cpp | 19 +- .../ScriptTypeTests/Library/SpeciesTests.cpp | 32 +-- .../Library/StaticLibraryTests.cpp | 23 +- tests/TestLibrary/TestLibrary.cpp | 9 + tests/TestLibrary/TestLibrary.hpp | 2 +- 21 files changed, 458 insertions(+), 61 deletions(-) create mode 100644 src/Library/LibrarySettings.hpp create mode 100644 tests/ScriptTests/ScriptTypeTests/Battle/PokemonTests.cpp diff --git a/conanfile.py b/conanfile.py index f8ab0d6..1827ce3 100644 --- a/conanfile.py +++ b/conanfile.py @@ -40,7 +40,7 @@ class PkmnLibConan(ConanFile): self.options["AngelScript"].link_std_statically = True def requirements(self): - self.requires("CreatureLib/7e0a1ec033f476dba24a7d091df997f31e2ac076@creaturelib/master") + self.requires("CreatureLib/bb9b9609a6e595ff8e6d4f4682b4be5b5e8d9d7e@creaturelib/master") if self.options.script_handler == "angelscript": self.requires("AngelScript/2.34@AngelScript/Deukhoofd") else: diff --git a/src/AngelScript/AngelScriptTypeInfo.hpp b/src/AngelScript/AngelScriptTypeInfo.hpp index 74a8e94..be3ee48 100644 --- a/src/AngelScript/AngelScriptTypeInfo.hpp +++ b/src/AngelScript/AngelScriptTypeInfo.hpp @@ -26,7 +26,9 @@ public: return find->second; } auto func = _type->GetMethodByName(functionName.c_str()); - func->AddRef(); + if (func != nullptr){ + func->AddRef(); + } _functions.insert({functionName, func}); return func; } diff --git a/src/AngelScript/TypeRegistry/Battling/RegisterPokemonClass.cpp b/src/AngelScript/TypeRegistry/Battling/RegisterPokemonClass.cpp index 4ae4b22..362ee44 100644 --- a/src/AngelScript/TypeRegistry/Battling/RegisterPokemonClass.cpp +++ b/src/AngelScript/TypeRegistry/Battling/RegisterPokemonClass.cpp @@ -1,6 +1,7 @@ #include "RegisterPokemonClass.hpp" #include #include +#include "../../../../extern/angelscript_addons/scriptarray/scriptarray.h" #include "../../../Battling/Pokemon/Pokemon.hpp" // Hack to handle AngelScript not recognizing different sized enums on fields, and returning invalid values due to it. @@ -52,8 +53,23 @@ void RegisterPokemonClass::RegisterLearnedAttack(asIScriptEngine* engine) { ENUM__SIZE_WRAPPER(Pkmn_GenderWrapper, PkmnLib::Battling::Pokemon, GetGender) +CScriptArray* GetTypes(const PkmnLib::Battling::Pokemon* obj) { + asIScriptContext* ctx = asGetActiveContext(); + if (ctx) { + asIScriptEngine* engine = ctx->GetEngine(); + asITypeInfo* t = engine->GetTypeInfoByDecl("array"); + auto a = obj->GetTypes(); + CScriptArray* arr = CScriptArray::Create(t, a.size()); + for (size_t i = 0; i < a.size(); i++){ + arr->SetValue(i, &a[i]); + } + return arr; + } + return nullptr; +} + void RegisterPokemonClass::RegisterPokemonType(asIScriptEngine* engine) { - [[maybe_unused]]int r = engine->RegisterObjectType("Pokemon", 0, asOBJ_REF | asOBJ_NOCOUNT); + [[maybe_unused]] int r = engine->RegisterObjectType("Pokemon", 0, asOBJ_REF | asOBJ_NOCOUNT); assert(r >= 0); r = engine->RegisterObjectMethod("Pokemon", "const Species@ get_Species() const property", asMETHOD(PkmnLib::Battling::Pokemon, GetSpecies), asCALL_THISCALL); @@ -73,6 +89,9 @@ void RegisterPokemonClass::RegisterPokemonType(asIScriptEngine* engine) { r = engine->RegisterObjectMethod("Pokemon", "uint8 get_Coloring() const property", asMETHOD(PkmnLib::Battling::Pokemon, GetColoring), asCALL_THISCALL); assert(r >= 0); + r = engine->RegisterObjectMethod("Pokemon", "bool get_Shiny() const property", + asMETHOD(PkmnLib::Battling::Pokemon, IsShiny), asCALL_THISCALL); + assert(r >= 0); r = engine->RegisterObjectMethod("Pokemon", "const Item@ get_HeldItem() const property", asMETHOD(PkmnLib::Battling::Pokemon, GetHeldItem), asCALL_THISCALL); assert(r >= 0); @@ -89,7 +108,7 @@ void RegisterPokemonClass::RegisterPokemonType(asIScriptEngine* engine) { asMETHOD(PkmnLib::Battling::Pokemon, IsFainted), asCALL_THISCALL); assert(r >= 0); r = engine->RegisterObjectMethod("Pokemon", "uint8[]@ GetTypes() const", - asMETHOD(PkmnLib::Battling::Pokemon, GetTypes), asCALL_THISCALL); + asFUNCTION(GetTypes), asCALL_CDECL_OBJLAST); assert(r >= 0); r = engine->RegisterObjectMethod("Pokemon", "bool HasType(uint8 type) const", asMETHOD(PkmnLib::Battling::Pokemon, HasType), asCALL_THISCALL); diff --git a/src/AngelScript/TypeRegistry/Library/RegisterStaticLibraryTypes.cpp b/src/AngelScript/TypeRegistry/Library/RegisterStaticLibraryTypes.cpp index 460ae2e..1cb8ea8 100644 --- a/src/AngelScript/TypeRegistry/Library/RegisterStaticLibraryTypes.cpp +++ b/src/AngelScript/TypeRegistry/Library/RegisterStaticLibraryTypes.cpp @@ -20,7 +20,7 @@ void RegisterStaticLibraryTypes::RegisterLibrarySettingsType(asIScriptEngine* en void RegisterStaticLibraryTypes::RegisterLibraryType(asIScriptEngine* engine) { [[maybe_unused]] int r = engine->RegisterObjectType("StaticLibrary", 0, asOBJ_REF | asOBJ_NOCOUNT); assert(r >= 0); - r = engine->RegisterObjectMethod("StaticLibrary", "const LibrarySettings& get_Settings() const property", + r = engine->RegisterObjectMethod("StaticLibrary", "const LibrarySettings@ get_Settings() const property", asMETHOD(PkmnLib::Library::PokemonLibrary, GetSettings), asCALL_THISCALL); assert(r >= 0); r = engine->RegisterObjectMethod("StaticLibrary", "const SpeciesLibrary@ get_SpeciesLibrary() const property", diff --git a/src/Battling/Library/BattleLibrary.hpp b/src/Battling/Library/BattleLibrary.hpp index 71d3531..00b0b02 100644 --- a/src/Battling/Library/BattleLibrary.hpp +++ b/src/Battling/Library/BattleLibrary.hpp @@ -17,6 +17,10 @@ namespace PkmnLib::Battling { : CreatureLib::Battling::BattleLibrary(staticLib, statCalculator, damageLibrary, experienceLibrary, scriptResolver, miscLibrary) {} + const Library::LibrarySettings* GetSettings() const{ + return static_cast(_staticLib->GetSettings()); + } + const Library::PokemonLibrary* GetStaticLib() const{ return dynamic_cast(CreatureLib::Battling::BattleLibrary::_staticLib); } diff --git a/src/Battling/Pokemon/CreatePokemon.cpp b/src/Battling/Pokemon/CreatePokemon.cpp index 00f4282..b3b62f7 100644 --- a/src/Battling/Pokemon/CreatePokemon.cpp +++ b/src/Battling/Pokemon/CreatePokemon.cpp @@ -1,6 +1,7 @@ #include "CreatePokemon.hpp" -PkmnLib::Battling::CreatePokemon* PkmnLib::Battling::CreatePokemon::WithRandomIndividualValues(CreatureLib::Core::Random rand) { +PkmnLib::Battling::CreatePokemon* +PkmnLib::Battling::CreatePokemon::WithRandomIndividualValues(CreatureLib::Core::Random rand) { _ivHp = rand.Get(0, 32); _ivAttack = rand.Get(0, 32); _ivDefense = rand.Get(0, 32); @@ -10,7 +11,8 @@ PkmnLib::Battling::CreatePokemon* PkmnLib::Battling::CreatePokemon::WithRandomIn return this; } -PkmnLib::Battling::CreatePokemon* PkmnLib::Battling::CreatePokemon::WithIndividualValue(CreatureLib::Core::Statistic stat, uint8_t value) { +PkmnLib::Battling::CreatePokemon* +PkmnLib::Battling::CreatePokemon::WithIndividualValue(CreatureLib::Core::Statistic stat, uint8_t value) { switch (stat) { case PkmnLib::Library::Statistic::HealthPoints: _ivHp = value; break; case PkmnLib::Library::Statistic::PhysicalAttack: _ivAttack = value; break; @@ -22,7 +24,8 @@ PkmnLib::Battling::CreatePokemon* PkmnLib::Battling::CreatePokemon::WithIndividu return this; } -PkmnLib::Battling::CreatePokemon* PkmnLib::Battling::CreatePokemon::WithEffortValue(CreatureLib::Core::Statistic stat, uint8_t value) { +PkmnLib::Battling::CreatePokemon* PkmnLib::Battling::CreatePokemon::WithEffortValue(CreatureLib::Core::Statistic stat, + uint8_t value) { switch (stat) { case PkmnLib::Library::Statistic::HealthPoints: _evHp = value; break; case PkmnLib::Library::Statistic::PhysicalAttack: _evAttack = value; break; @@ -36,8 +39,11 @@ PkmnLib::Battling::CreatePokemon* PkmnLib::Battling::CreatePokemon::WithEffortVa PkmnLib::Battling::Pokemon* PkmnLib::Battling::CreatePokemon::Build() { auto rand = CreatureLib::Core::Random(); - auto species = this->_library->GetSpeciesLibrary()->GetPkmnSpecies(this->_species); - auto forme = species->GetForme(this->_variant); + const PkmnLib::Library::PokemonSpecies* species = nullptr; + if (!this->_library->GetSpeciesLibrary()->TryGetPkmnSpecies(this->_species, species)){ + throw CreatureException("Invalid species: " + _species); + } + auto forme = species->GetForme(this->_forme); int8_t ability; if (this->_ability.empty()) { ability = forme->GetRandomTalent(&rand); @@ -54,7 +60,9 @@ PkmnLib::Battling::Pokemon* PkmnLib::Battling::CreatePokemon::Build() { } const Library::Item* heldItem = nullptr; if (!this->_heldItem.empty()) { - heldItem = _library->GetItemLibrary()->GetItem(this->_heldItem); + if (!_library->GetItemLibrary()->TryGetItem(this->_heldItem, heldItem)){ + throw CreatureException("Unknown Item: " + this->_heldItem); + } } auto experience = _library->GetGrowthRateLibrary()->CalculateExperience(species->GetGrowthRate(), _level); @@ -66,12 +74,20 @@ PkmnLib::Battling::Pokemon* PkmnLib::Battling::CreatePokemon::Build() { auto ivs = CreatureLib::Core::StatisticSet(_ivHp, _ivAttack, _ivDefense, _ivSpAtt, _ivSpDef, _ivSpeed); auto evs = CreatureLib::Core::StatisticSet(_evHp, _evAttack, _evDefense, _evSpAtt, _evSpDef, _evSpeed); - if (_nature == 255){ + if (_nature == 255) { _nature = _library->GetNatureLibrary()->GetRandomNature(rand); } - auto pkmn = new Pokemon(_library, species, forme, _level, experience, identifier, gender, _coloring, heldItem, _nickname, - ability, attacks, ivs, evs,_nature); + auto shiny = false; + if (_shininessSet){ + shiny = _isShiny; + } + else{ + shiny = rand.Get(_library->GetSettings()->GetShinyRate()) == 0; + } + + auto pkmn = new Pokemon(_library, species, forme, _level, experience, identifier, gender, shiny, heldItem, + _nickname, ability, attacks, ivs, evs, _nature); pkmn->Initialize(); return pkmn; } @@ -85,7 +101,7 @@ PkmnLib::Battling::CreatePokemon* PkmnLib::Battling::CreatePokemon::WithIndividu _ivHp = hp; _ivAttack = att; _ivDefense = def; - _ivSpAtt = spAtt; + _ivSpAtt = spAtt; _ivSpDef = spDef; _ivSpeed = speed; return this; @@ -96,8 +112,25 @@ PkmnLib::Battling::CreatePokemon* PkmnLib::Battling::CreatePokemon::WithEffortVa _evHp = hp; _evAttack = att; _evDefense = def; - _evSpAtt = spAtt; + _evSpAtt = spAtt; _evSpDef = spDef; _evSpeed = speed; return this; } +PkmnLib::Battling::CreatePokemon* PkmnLib::Battling::CreatePokemon::WithForme(const std::string& forme) { + _forme = forme; + return this; +} +PkmnLib::Battling::CreatePokemon* PkmnLib::Battling::CreatePokemon::WithGender(CreatureLib::Library::Gender gender) { + _gender = gender; + return this; +} +PkmnLib::Battling::CreatePokemon* PkmnLib::Battling::CreatePokemon::IsShiny(bool value) { + _shininessSet = true; + _isShiny = value; + return this; +} +PkmnLib::Battling::CreatePokemon* PkmnLib::Battling::CreatePokemon::WithHeldItem(const std::string& item) { + _heldItem = item; + return this; +} diff --git a/src/Battling/Pokemon/CreatePokemon.hpp b/src/Battling/Pokemon/CreatePokemon.hpp index 7a8d203..642d951 100644 --- a/src/Battling/Pokemon/CreatePokemon.hpp +++ b/src/Battling/Pokemon/CreatePokemon.hpp @@ -8,14 +8,13 @@ namespace PkmnLib::Battling { private: const BattleLibrary* _library; std::string _species; - std::string _variant = "default"; + std::string _forme = "default"; uint8_t _level; std::string _nickname = ""; std::string _ability = ""; uint8_t _nature = 255; CreatureLib::Library::Gender _gender = static_cast(-1); - uint8_t _coloring = 0; std::string _heldItem = ""; uint32_t _identifier = 0; std::vector> _attacks = {}; @@ -34,10 +33,18 @@ namespace PkmnLib::Battling { uint8_t _evSpDef = 0; uint8_t _evSpeed = 0; + bool _shininessSet = false; + bool _isShiny = false; + public: CreatePokemon(const BattleLibrary* library, std::string species, uint8_t level) : _library(library), _species(std::move(species)), _level(level) {} + CreatePokemon* WithForme(const std::string& forme); + CreatePokemon* WithGender(CreatureLib::Library::Gender gender); + CreatePokemon* IsShiny(bool value); + CreatePokemon* WithHeldItem(const std::string& item); + CreatePokemon* WithRandomIndividualValues(CreatureLib::Core::Random rand = CreatureLib::Core::Random()); CreatePokemon* WithIndividualValue(CreatureLib::Core::Statistic stat, uint8_t value); CreatePokemon* WithIndividualValues(uint8_t hp, uint8_t att, uint8_t def, uint8_t spAtt, uint8_t spDef, diff --git a/src/Battling/Pokemon/Pokemon.hpp b/src/Battling/Pokemon/Pokemon.hpp index cef9e34..aa45342 100644 --- a/src/Battling/Pokemon/Pokemon.hpp +++ b/src/Battling/Pokemon/Pokemon.hpp @@ -33,6 +33,10 @@ namespace PkmnLib::Battling { return dynamic_cast(GetVariant()); } + const bool IsShiny() const{ + return _coloring == 1; + } + const Library::Nature& GetNature() const; uint8_t GetIndividualValue(CreatureLib::Core::Statistic stat) const { return _individualValues.GetStat(stat); } uint8_t GetEffortValue(CreatureLib::Core::Statistic stat) const { return _effortValues.GetStat(stat); } diff --git a/src/Library/Items/ItemLibrary.hpp b/src/Library/Items/ItemLibrary.hpp index b6a0ce3..4b5d07a 100644 --- a/src/Library/Items/ItemLibrary.hpp +++ b/src/Library/Items/ItemLibrary.hpp @@ -6,6 +6,9 @@ namespace PkmnLib::Library { class ItemLibrary : public CreatureLib::Library::ItemLibrary { public: + inline bool TryGetItem(const std::string& name, const Item*& item) const { + return CreatureLib::Library::ItemLibrary::TryGetItem(name, (const CreatureLib::Library::Item*&)item); + } const Item* GetItem(const std::string& name) const { return reinterpret_cast(CreatureLib::Library::ItemLibrary::GetItem(name)); } diff --git a/src/Library/LibrarySettings.hpp b/src/Library/LibrarySettings.hpp new file mode 100644 index 0000000..b2ec08b --- /dev/null +++ b/src/Library/LibrarySettings.hpp @@ -0,0 +1,18 @@ +#ifndef PKMNLIB_LIBRARYSETTINGS_HPP +#define PKMNLIB_LIBRARYSETTINGS_HPP + +#include + +namespace PkmnLib::Library { + class LibrarySettings : public CreatureLib::Library::LibrarySettings { + uint16_t _shinyRate; + + public: + LibrarySettings(uint8_t maximalLevel, uint8_t maximalMoves, uint16_t shinyRate) + : CreatureLib::Library::LibrarySettings(maximalLevel, maximalMoves), _shinyRate(shinyRate) {} + + uint16_t GetShinyRate() const { return _shinyRate; } + }; +} + +#endif // PKMNLIB_LIBRARYSETTINGS_HPP diff --git a/src/Library/Moves/MoveLibrary.hpp b/src/Library/Moves/MoveLibrary.hpp index 249828f..04500ab 100644 --- a/src/Library/Moves/MoveLibrary.hpp +++ b/src/Library/Moves/MoveLibrary.hpp @@ -10,6 +10,9 @@ namespace PkmnLib::Library { virtual const MoveData* operator[](const std::string& name) const { return GetAttack(name); } + inline bool TryGetMove(const std::string& name, const MoveData*& move) const{ + return TryGetAttack(name, (const CreatureLib::Library::AttackData*&)move); + } const MoveData* GetMove(const std::string& name) const { return GetAttack(name); } const MoveData* GetAttack(const std::string& name) const { diff --git a/src/Library/PokemonLibrary.hpp b/src/Library/PokemonLibrary.hpp index c34c355..9da4067 100644 --- a/src/Library/PokemonLibrary.hpp +++ b/src/Library/PokemonLibrary.hpp @@ -3,6 +3,7 @@ #include #include "Items/ItemLibrary.hpp" +#include "LibrarySettings.hpp" #include "Moves/MoveLibrary.hpp" #include "Natures/NatureLibrary.hpp" #include "Species/SpeciesLibrary.hpp" @@ -17,11 +18,15 @@ namespace PkmnLib::Library { delete _natures; } - PokemonLibrary(CreatureLib::Library::LibrarySettings settings, SpeciesLibrary* species, MoveLibrary* moves, + PokemonLibrary(PkmnLib::Library::LibrarySettings* settings, SpeciesLibrary* species, MoveLibrary* moves, ItemLibrary* items, CreatureLib::Library::GrowthRateLibrary* growthRates, CreatureLib::Library::TypeLibrary* typeLibrary, NatureLibrary* natures) : DataLibrary(settings, species, moves, items, growthRates, typeLibrary), _natures(natures) {} + const PkmnLib::Library::LibrarySettings* GetSettings() const{ + return static_cast(CreatureLib::Library::DataLibrary::GetSettings()); + } + [[nodiscard]] const SpeciesLibrary* GetSpeciesLibrary() const { return (const SpeciesLibrary*)(CreatureLib::Library::DataLibrary::GetSpeciesLibrary()); } diff --git a/src/Library/Species/SpeciesLibrary.hpp b/src/Library/Species/SpeciesLibrary.hpp index d446b8c..bfde5ab 100644 --- a/src/Library/Species/SpeciesLibrary.hpp +++ b/src/Library/Species/SpeciesLibrary.hpp @@ -7,6 +7,11 @@ namespace PkmnLib::Library { class SpeciesLibrary : public CreatureLib::Library::SpeciesLibrary { public: + + inline bool TryGetPkmnSpecies(const std::string& name, const PokemonSpecies*& outSpecies) const{ + return TryGetSpecies(name, (const CreatureLib::Library::CreatureSpecies*&)outSpecies); + } + inline const PokemonSpecies* GetPkmnSpecies(const std::string& name) const { return reinterpret_cast(CreatureLib::Library::SpeciesLibrary::GetSpecies(name)); } diff --git a/tests/ScriptTests/ScriptTypeTests/Battle/PokemonTests.cpp b/tests/ScriptTests/ScriptTypeTests/Battle/PokemonTests.cpp new file mode 100644 index 0000000..c1a49b5 --- /dev/null +++ b/tests/ScriptTests/ScriptTypeTests/Battle/PokemonTests.cpp @@ -0,0 +1,255 @@ +#ifdef TESTS_BUILD +#include "../../../../extern/catch.hpp" +#include "../../../../src/AngelScript/AngelScripResolver.hpp" +#include "../../../../src/Battling/Pokemon/CreatePokemon.hpp" +#include "../../../TestLibrary/TestLibrary.hpp" + +static std::unordered_map _scripts = + std::unordered_map{{"testScript1", R"( +class testScript1 { + bool testSpecies(Pokemon@ p, const Species@ species){ return p.Species is species; } + bool testForme(Pokemon@ p, const Forme@ forme){ return p.Forme is forme; } + bool testLevel(Pokemon@ p, uint8 level){ return p.Level == level; } + bool testExperience(Pokemon@ p, uint experience){ return p.Experience == experience; } + bool testGender(Pokemon@ p, Gender gender){ return p.Gender == gender; } + bool testShiny(Pokemon@ p, bool shiny){ return p.Shiny == shiny; } + bool testHeldItem(Pokemon@ p, Item@ item){ return p.HeldItem is item; } + bool testCurrentHealth(Pokemon@ p, uint health){ return p.CurrentHealth == health; } + bool testNickname(Pokemon@ p, const string &in name){ return p.Nickname == name; } + bool testActiveAbility(Pokemon@ p, const string &in ability){ return p.ActiveAbility == ability; } + bool testIsFainted(Pokemon@ p, bool b){ return p.IsFainted == b; } + bool testType(Pokemon@ p, uint index, uint8 type){ return p.GetTypes()[index] == type; } +} +)"}}; + +static const char* _testLoadFunc(const char* name) { return _scripts[name]; } + +struct ScriptData { + AngelScriptScript* Script; + AngelScripResolver* Resolver; + asIScriptFunction* Func; + asIScriptContext* Context; + + ~ScriptData() { + Script->GetContextPool()->ReturnContextToPool(Context); + delete Script; + } +}; + +static AngelScripResolver* _resolverCache = nullptr; +static AngelScripResolver* GetScriptResolver(PkmnLib::Battling::BattleLibrary* mainLib) { + if (_resolverCache == nullptr) { + _resolverCache = dynamic_cast(PkmnLib::Battling::BattleLibrary::CreateScriptResolver()); + _resolverCache->Initialize(mainLib); + _resolverCache->SetCreateFunction(&_testLoadFunc); + _resolverCache->CreateScript("testScript1"); + _resolverCache->FinalizeModule(); + } + return _resolverCache; +} + +static ScriptData GetScript(PkmnLib::Battling::BattleLibrary* mainLib, const char* funcName) { + auto lib = GetScriptResolver(mainLib); + auto s = lib->LoadScript(AngelScripResolver::ScriptCategory::Creature, "testScript1"); + auto script = dynamic_cast(s); + auto ctxPool = script->GetContextPool(); + auto ctx = ctxPool->RequestContext(); + + auto func = script->PrepareMethod(funcName, ctx); + REQUIRE(func != nullptr); + + return {.Script = script, .Resolver = lib, .Func = func, .Context = ctx}; +} + +TEST_CASE("Validate Pokemon Species in Script") { + auto mainLib = TestLibrary::GetLibrary(); + auto data = GetScript(mainLib, "testSpecies"); + + auto mon = PkmnLib::Battling::CreatePokemon(mainLib, "testSpecies", 30).Build(); + data.Context->SetArgObject(0, const_cast(mon)); + data.Context->SetArgObject(1, (void*)mon->GetSpecies()); + + REQUIRE(data.Context->Execute() == asEXECUTION_FINISHED); + REQUIRE((bool)data.Context->GetReturnWord()); + delete mon; +} + +TEST_CASE("Validate Pokemon Forme in Script") { + auto mainLib = TestLibrary::GetLibrary(); + auto data = GetScript(mainLib, "testForme"); + + auto mon = PkmnLib::Battling::CreatePokemon(mainLib, "testSpecies", 30).WithForme("default")->Build(); + data.Context->SetArgObject(0, const_cast(mon)); + data.Context->SetArgObject(1, (void*)mon->GetForme()); + + REQUIRE(data.Context->Execute() == asEXECUTION_FINISHED); + REQUIRE((bool)data.Context->GetReturnWord()); + delete mon; +} + +TEST_CASE("Validate Pokemon Level in Script") { + auto mainLib = TestLibrary::GetLibrary(); + auto data = GetScript(mainLib, "testLevel"); + + auto mon = PkmnLib::Battling::CreatePokemon(mainLib, "testSpecies", 30).WithForme("default")->Build(); + data.Context->SetArgObject(0, const_cast(mon)); + data.Context->SetArgByte(1, mon->GetLevel()); + + REQUIRE(data.Context->Execute() == asEXECUTION_FINISHED); + REQUIRE((bool)data.Context->GetReturnWord()); + delete mon; +} + +TEST_CASE("Validate Pokemon Experience in Script") { + auto mainLib = TestLibrary::GetLibrary(); + auto data = GetScript(mainLib, "testExperience"); + + auto mon = PkmnLib::Battling::CreatePokemon(mainLib, "testSpecies", 30).WithForme("default")->Build(); + data.Context->SetArgObject(0, const_cast(mon)); + data.Context->SetArgDWord(1, mon->GetExperience()); + + REQUIRE(data.Context->Execute() == asEXECUTION_FINISHED); + REQUIRE((bool)data.Context->GetReturnWord()); + delete mon; +} + +TEST_CASE("Validate Pokemon Gender in Script") { + auto mainLib = TestLibrary::GetLibrary(); + auto data = GetScript(mainLib, "testGender"); + + auto mon = PkmnLib::Battling::CreatePokemon(mainLib, "testSpecies", 30) + .WithForme("default") + ->WithGender(CreatureLib::Library::Gender::Male) + ->Build(); + data.Context->SetArgObject(0, const_cast(mon)); + data.Context->SetArgDWord(1, (int)mon->GetGender()); + + REQUIRE(data.Context->Execute() == asEXECUTION_FINISHED); + REQUIRE((bool)data.Context->GetReturnWord()); + delete mon; +} + +TEST_CASE("Validate Pokemon Shininess in Script") { + auto mainLib = TestLibrary::GetLibrary(); + auto data = GetScript(mainLib, "testShiny"); + + auto mon = PkmnLib::Battling::CreatePokemon(mainLib, "testSpecies", 30) + .WithForme("default") + ->WithGender(CreatureLib::Library::Gender::Male) + ->Build(); + data.Context->SetArgObject(0, const_cast(mon)); + data.Context->SetArgByte(1, mon->IsShiny()); + + REQUIRE(data.Context->Execute() == asEXECUTION_FINISHED); + REQUIRE((bool)data.Context->GetReturnWord()); + delete mon; +} + +TEST_CASE("Validate Pokemon HeldItem in Script") { + auto mainLib = TestLibrary::GetLibrary(); + auto data = GetScript(mainLib, "testHeldItem"); + + auto mon = PkmnLib::Battling::CreatePokemon(mainLib, "testSpecies", 30) + .WithForme("default") + ->WithHeldItem("testItem") + ->WithGender(CreatureLib::Library::Gender::Male) + ->Build(); + data.Context->SetArgObject(0, const_cast(mon)); + data.Context->SetArgObject(1, (void*)mon->GetHeldItem()); + + REQUIRE(data.Context->Execute() == asEXECUTION_FINISHED); + REQUIRE((bool)data.Context->GetReturnWord()); + delete mon; +} + +TEST_CASE("Validate Pokemon CurrentHealth in Script") { + auto mainLib = TestLibrary::GetLibrary(); + auto data = GetScript(mainLib, "testCurrentHealth"); + + auto mon = PkmnLib::Battling::CreatePokemon(mainLib, "testSpecies", 30) + .WithForme("default") + ->WithGender(CreatureLib::Library::Gender::Male) + ->Build(); + data.Context->SetArgObject(0, const_cast(mon)); + data.Context->SetArgDWord(1, mon->GetCurrentHealth()); + + REQUIRE(data.Context->Execute() == asEXECUTION_FINISHED); + REQUIRE((bool)data.Context->GetReturnWord()); + delete mon; +} + +TEST_CASE("Validate Pokemon Nickname in Script") { + auto mainLib = TestLibrary::GetLibrary(); + auto data = GetScript(mainLib, "testNickname"); + + auto mon = PkmnLib::Battling::CreatePokemon(mainLib, "testSpecies", 30) + .WithForme("default") + ->WithGender(CreatureLib::Library::Gender::Male) + ->Build(); + data.Context->SetArgObject(0, const_cast(mon)); + auto name = mon->GetNickname(); + data.Context->SetArgAddress(1, &name); + + REQUIRE(data.Context->Execute() == asEXECUTION_FINISHED); + REQUIRE((bool)data.Context->GetReturnWord()); + delete mon; +} + +TEST_CASE("Validate Pokemon Active Ability in Script") { + auto mainLib = TestLibrary::GetLibrary(); + auto data = GetScript(mainLib, "testActiveAbility"); + + auto mon = PkmnLib::Battling::CreatePokemon(mainLib, "testSpecies", 30) + .WithForme("default") + ->WithGender(CreatureLib::Library::Gender::Male) + ->Build(); + data.Context->SetArgObject(0, const_cast(mon)); + auto name = mon->GetActiveTalent(); + data.Context->SetArgAddress(1, &name); + + REQUIRE(data.Context->Execute() == asEXECUTION_FINISHED); + REQUIRE((bool)data.Context->GetReturnWord()); + delete mon; +} + +TEST_CASE("Validate Pokemon IsFainted in Script") { + auto mainLib = TestLibrary::GetLibrary(); + auto data = GetScript(mainLib, "testIsFainted"); + + auto mon = PkmnLib::Battling::CreatePokemon(mainLib, "testSpecies", 30) + .WithForme("default") + ->WithGender(CreatureLib::Library::Gender::Male) + ->Build(); + data.Context->SetArgObject(0, const_cast(mon)); + data.Context->SetArgByte(1, mon->IsFainted()); + + REQUIRE(data.Context->Execute() == asEXECUTION_FINISHED); + REQUIRE((bool)data.Context->GetReturnWord()); + delete mon; +} + +TEST_CASE("Validate Pokemon GetTypes in Script") { + auto mainLib = TestLibrary::GetLibrary(); + + auto mon = PkmnLib::Battling::CreatePokemon(mainLib, "testSpecies3", 30) + .WithForme("default") + ->WithGender(CreatureLib::Library::Gender::Male) + ->Build(); + for (auto i = 0; i < mon->GetTypes().size(); i++){ + auto data = GetScript(mainLib, "testType"); + + data.Context->SetArgObject(0, const_cast(mon)); + data.Context->SetArgDWord(1, i); + data.Context->SetArgByte(2, mon->GetTypes()[i]); + + REQUIRE(data.Context->Execute() == asEXECUTION_FINISHED); + REQUIRE((bool)data.Context->GetReturnWord()); + + } + + + delete mon; +} + + +#endif \ No newline at end of file diff --git a/tests/ScriptTests/ScriptTypeTests/Library/FormesTests.cpp b/tests/ScriptTests/ScriptTypeTests/Library/FormesTests.cpp index 513be39..a3560ce 100644 --- a/tests/ScriptTests/ScriptTypeTests/Library/FormesTests.cpp +++ b/tests/ScriptTests/ScriptTypeTests/Library/FormesTests.cpp @@ -28,16 +28,23 @@ struct ScriptData { ~ScriptData() { Script->GetContextPool()->ReturnContextToPool(Context); delete Script; - delete Resolver; } }; +static AngelScripResolver* _resolverCache = nullptr; +static AngelScripResolver* GetScriptResolver(PkmnLib::Battling::BattleLibrary* mainLib){ + if (_resolverCache == nullptr){ + _resolverCache = dynamic_cast(PkmnLib::Battling::BattleLibrary::CreateScriptResolver()); + _resolverCache->Initialize(mainLib); + _resolverCache->SetCreateFunction(&_testLoadFunc); + _resolverCache->CreateScript("testScript1"); + _resolverCache->FinalizeModule(); + } + return _resolverCache; +} + static ScriptData GetScript(PkmnLib::Battling::BattleLibrary* mainLib, const char* funcName) { - auto lib = dynamic_cast(PkmnLib::Battling::BattleLibrary::CreateScriptResolver()); - lib->Initialize(mainLib); - lib->SetCreateFunction(&_testLoadFunc); - lib->CreateScript("testScript1"); - lib->FinalizeModule(); + auto lib = GetScriptResolver(mainLib); auto s = lib->LoadScript(AngelScripResolver::ScriptCategory::Creature, "testScript1"); auto script = dynamic_cast(s); auto ctxPool = script->GetContextPool(); diff --git a/tests/ScriptTests/ScriptTypeTests/Library/ItemDataTests.cpp b/tests/ScriptTests/ScriptTypeTests/Library/ItemDataTests.cpp index 437ec08..562668d 100644 --- a/tests/ScriptTests/ScriptTypeTests/Library/ItemDataTests.cpp +++ b/tests/ScriptTests/ScriptTypeTests/Library/ItemDataTests.cpp @@ -24,16 +24,23 @@ struct ScriptData { ~ScriptData() { Script->GetContextPool()->ReturnContextToPool(Context); delete Script; - delete Resolver; } }; +static AngelScripResolver* _resolverCache = nullptr; +static AngelScripResolver* GetScriptResolver(PkmnLib::Battling::BattleLibrary* mainLib){ + if (_resolverCache == nullptr){ + _resolverCache = dynamic_cast(PkmnLib::Battling::BattleLibrary::CreateScriptResolver()); + _resolverCache->Initialize(mainLib); + _resolverCache->SetCreateFunction(&_testLoadFunc); + _resolverCache->CreateScript("testScript1"); + _resolverCache->FinalizeModule(); + } + return _resolverCache; +} + static ScriptData GetScript(PkmnLib::Battling::BattleLibrary* mainLib, const char* funcName) { - auto lib = dynamic_cast(PkmnLib::Battling::BattleLibrary::CreateScriptResolver()); - lib->Initialize(mainLib); - lib->SetCreateFunction(&_testLoadFunc); - lib->CreateScript("testScript1"); - lib->FinalizeModule(); + auto lib = GetScriptResolver(mainLib); auto s = lib->LoadScript(AngelScripResolver::ScriptCategory::Creature, "testScript1"); auto script = dynamic_cast(s); auto ctxPool = script->GetContextPool(); diff --git a/tests/ScriptTests/ScriptTypeTests/Library/MoveTests.cpp b/tests/ScriptTests/ScriptTypeTests/Library/MoveTests.cpp index cfe417e..d3fae1b 100644 --- a/tests/ScriptTests/ScriptTypeTests/Library/MoveTests.cpp +++ b/tests/ScriptTests/ScriptTypeTests/Library/MoveTests.cpp @@ -28,16 +28,23 @@ struct ScriptData { ~ScriptData() { Script->GetContextPool()->ReturnContextToPool(Context); delete Script; - delete Resolver; } }; +static AngelScripResolver* _resolverCache = nullptr; +static AngelScripResolver* GetScriptResolver(PkmnLib::Battling::BattleLibrary* mainLib){ + if (_resolverCache == nullptr){ + _resolverCache = dynamic_cast(PkmnLib::Battling::BattleLibrary::CreateScriptResolver()); + _resolverCache->Initialize(mainLib); + _resolverCache->SetCreateFunction(&_testLoadFunc); + _resolverCache->CreateScript("testScript1"); + _resolverCache->FinalizeModule(); + } + return _resolverCache; +} + static ScriptData GetScript(PkmnLib::Battling::BattleLibrary* mainLib, const char* funcName) { - auto lib = dynamic_cast(PkmnLib::Battling::BattleLibrary::CreateScriptResolver()); - lib->Initialize(mainLib); - lib->SetCreateFunction(&_testLoadFunc); - lib->CreateScript("testScript1"); - lib->FinalizeModule(); + auto lib = GetScriptResolver(mainLib); auto s = lib->LoadScript(AngelScripResolver::ScriptCategory::Creature, "testScript1"); auto script = dynamic_cast(s); auto ctxPool = script->GetContextPool(); diff --git a/tests/ScriptTests/ScriptTypeTests/Library/SpeciesTests.cpp b/tests/ScriptTests/ScriptTypeTests/Library/SpeciesTests.cpp index 95bec04..2fcf859 100644 --- a/tests/ScriptTests/ScriptTypeTests/Library/SpeciesTests.cpp +++ b/tests/ScriptTests/ScriptTypeTests/Library/SpeciesTests.cpp @@ -17,25 +17,32 @@ class testScript1 { static const char* _testLoadFunc(const char* name) { return _scripts[name]; } -struct ScriptData{ +struct ScriptData { AngelScriptScript* Script; AngelScripResolver* Resolver; asIScriptFunction* Func; asIScriptContext* Context; - ~ScriptData(){ + ~ScriptData() { Script->GetContextPool()->ReturnContextToPool(Context); delete Script; - delete Resolver; } }; -static ScriptData GetScript(PkmnLib::Battling::BattleLibrary* mainLib, const char* funcName){ - auto lib = dynamic_cast(PkmnLib::Battling::BattleLibrary::CreateScriptResolver()); - lib->Initialize(mainLib); - lib->SetCreateFunction(&_testLoadFunc); - lib->CreateScript("testScript1"); - lib->FinalizeModule(); +static AngelScripResolver* _resolverCache = nullptr; +static AngelScripResolver* GetScriptResolver(PkmnLib::Battling::BattleLibrary* mainLib){ + if (_resolverCache == nullptr){ + _resolverCache = dynamic_cast(PkmnLib::Battling::BattleLibrary::CreateScriptResolver()); + _resolverCache->Initialize(mainLib); + _resolverCache->SetCreateFunction(&_testLoadFunc); + _resolverCache->CreateScript("testScript1"); + _resolverCache->FinalizeModule(); + } + return _resolverCache; +} + +static ScriptData GetScript(PkmnLib::Battling::BattleLibrary* mainLib, const char* funcName) { + auto lib = GetScriptResolver(mainLib); auto s = lib->LoadScript(AngelScripResolver::ScriptCategory::Creature, "testScript1"); auto script = dynamic_cast(s); auto ctxPool = script->GetContextPool(); @@ -44,12 +51,7 @@ static ScriptData GetScript(PkmnLib::Battling::BattleLibrary* mainLib, const cha auto func = script->PrepareMethod(funcName, ctx); REQUIRE(func != nullptr); - return { - .Script = script, - .Resolver = lib, - .Func = func, - .Context = ctx - }; + return {.Script = script, .Resolver = lib, .Func = func, .Context = ctx}; } TEST_CASE("Validate Species Name in Script") { diff --git a/tests/ScriptTests/ScriptTypeTests/Library/StaticLibraryTests.cpp b/tests/ScriptTests/ScriptTypeTests/Library/StaticLibraryTests.cpp index 08715a9..83e8895 100644 --- a/tests/ScriptTests/ScriptTypeTests/Library/StaticLibraryTests.cpp +++ b/tests/ScriptTests/ScriptTypeTests/Library/StaticLibraryTests.cpp @@ -27,16 +27,23 @@ struct ScriptData { ~ScriptData() { Script->GetContextPool()->ReturnContextToPool(Context); delete Script; - delete Resolver; } }; +static AngelScripResolver* _resolverCache = nullptr; +static AngelScripResolver* GetScriptResolver(PkmnLib::Battling::BattleLibrary* mainLib){ + if (_resolverCache == nullptr){ + _resolverCache = dynamic_cast(PkmnLib::Battling::BattleLibrary::CreateScriptResolver()); + _resolverCache->Initialize(mainLib); + _resolverCache->SetCreateFunction(&_testLoadFunc); + _resolverCache->CreateScript("testScript1"); + _resolverCache->FinalizeModule(); + } + return _resolverCache; +} + static ScriptData GetScript(PkmnLib::Battling::BattleLibrary* mainLib, const char* funcName) { - auto lib = dynamic_cast(PkmnLib::Battling::BattleLibrary::CreateScriptResolver()); - lib->Initialize(mainLib); - lib->SetCreateFunction(&_testLoadFunc); - lib->CreateScript("testScript1"); - lib->FinalizeModule(); + auto lib = GetScriptResolver(mainLib); auto s = lib->LoadScript(AngelScripResolver::ScriptCategory::Creature, "testScript1"); auto script = dynamic_cast(s); auto ctxPool = script->GetContextPool(); @@ -53,7 +60,7 @@ TEST_CASE("Validate StaticLibrary Maximum Level in Script") { auto data = GetScript(mainLib, "testMaximumLevel"); data.Context->SetArgObject(0, const_cast(mainLib->GetStaticLib())); - data.Context->SetArgByte(1, mainLib->GetStaticLib()->GetSettings().GetMaximalLevel()); + data.Context->SetArgByte(1, mainLib->GetStaticLib()->GetSettings()->GetMaximalLevel()); auto result = data.Context->Execute(); REQUIRE(result == asEXECUTION_FINISHED); @@ -66,7 +73,7 @@ TEST_CASE("Validate StaticLibrary Maximum Moves in Script") { auto data = GetScript(mainLib, "testMaximumMoves"); data.Context->SetArgObject(0, const_cast(mainLib->GetStaticLib())); - data.Context->SetArgByte(1, mainLib->GetStaticLib()->GetSettings().GetMaximalMoves()); + data.Context->SetArgByte(1, mainLib->GetStaticLib()->GetSettings()->GetMaximalMoves()); auto result = data.Context->Execute(); REQUIRE(result == asEXECUTION_FINISHED); diff --git a/tests/TestLibrary/TestLibrary.cpp b/tests/TestLibrary/TestLibrary.cpp index 19079cb..d0fd6c5 100644 --- a/tests/TestLibrary/TestLibrary.cpp +++ b/tests/TestLibrary/TestLibrary.cpp @@ -26,6 +26,15 @@ PkmnLib::Library::SpeciesLibrary* TestLibrary::BuildSpeciesLibrary() { CreatureLib::Core::StatisticSet(100, 100, 100, 100, 100, 100), {"testAbility"}, {"testHiddenAbility"}, new CreatureLib::Library::LearnableAttacks(100)), 0.5f, "testGrowthRate", 100, 100)); + lib->LoadSpecies("testSpecies3", + new PkmnLib::Library::PokemonSpecies( + 2, "testSpecies3", + new PkmnLib::Library::PokemonForme( + "default", 1.0f, 1.0f, 100, {0, 4}, + CreatureLib::Core::StatisticSet(100, 100, 100, 100, 100, 100), {"testAbility"}, + {"testHiddenAbility"}, new CreatureLib::Library::LearnableAttacks(100)), + 0.5f, "testGrowthRate", 100, 100)); + return lib; } diff --git a/tests/TestLibrary/TestLibrary.hpp b/tests/TestLibrary/TestLibrary.hpp index b8ba8d2..7aa5826 100644 --- a/tests/TestLibrary/TestLibrary.hpp +++ b/tests/TestLibrary/TestLibrary.hpp @@ -31,7 +31,7 @@ public: } static PkmnLib::Library::PokemonLibrary* BuildStaticLibrary() { - return new PkmnLib::Library::PokemonLibrary(CreatureLib::Library::LibrarySettings(100, 4), + return new PkmnLib::Library::PokemonLibrary(new PkmnLib::Library::LibrarySettings(100, 4, 4096), BuildSpeciesLibrary(), BuildMoveLibrary(), BuildItemLibrary(), BuildGrowthRateLibrary(), BuildTypeLibrary(), BuildNatureLibrary()); }