diff --git a/conanfile.py b/conanfile.py index 1827ce3..734a440 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/bb9b9609a6e595ff8e6d4f4682b4be5b5e8d9d7e@creaturelib/master") + self.requires("CreatureLib/fc5826edb1d164a261a33aebb164af7df8ab7ef4@creaturelib/master") if self.options.script_handler == "angelscript": self.requires("AngelScript/2.34@AngelScript/Deukhoofd") else: diff --git a/src/Battling/Pokemon/CreatePokemon.cpp b/src/Battling/Pokemon/CreatePokemon.cpp index b3b62f7..90c5f41 100644 --- a/src/Battling/Pokemon/CreatePokemon.cpp +++ b/src/Battling/Pokemon/CreatePokemon.cpp @@ -40,7 +40,7 @@ PkmnLib::Battling::CreatePokemon* PkmnLib::Battling::CreatePokemon::WithEffortVa PkmnLib::Battling::Pokemon* PkmnLib::Battling::CreatePokemon::Build() { auto rand = CreatureLib::Core::Random(); const PkmnLib::Library::PokemonSpecies* species = nullptr; - if (!this->_library->GetSpeciesLibrary()->TryGetPkmnSpecies(this->_species, species)){ + if (!this->_library->GetSpeciesLibrary()->TryGetPkmnSpecies(this->_species, species)) { throw CreatureException("Invalid species: " + _species); } auto forme = species->GetForme(this->_forme); @@ -60,7 +60,7 @@ PkmnLib::Battling::Pokemon* PkmnLib::Battling::CreatePokemon::Build() { } const Library::Item* heldItem = nullptr; if (!this->_heldItem.empty()) { - if (!_library->GetItemLibrary()->TryGetItem(this->_heldItem, heldItem)){ + if (!_library->GetItemLibrary()->TryGetItem(this->_heldItem, heldItem)) { throw CreatureException("Unknown Item: " + this->_heldItem); } } @@ -79,10 +79,9 @@ PkmnLib::Battling::Pokemon* PkmnLib::Battling::CreatePokemon::Build() { } auto shiny = false; - if (_shininessSet){ + if (_shininessSet) { shiny = _isShiny; - } - else{ + } else { shiny = rand.Get(_library->GetSettings()->GetShinyRate()) == 0; } @@ -134,3 +133,15 @@ PkmnLib::Battling::CreatePokemon* PkmnLib::Battling::CreatePokemon::WithHeldItem _heldItem = item; return this; } +PkmnLib::Battling::CreatePokemon* +PkmnLib::Battling::CreatePokemon::LearnMove(const std::string& moveName, CreatureLib::Battling::AttackLearnMethod method) { + const PkmnLib::Library::MoveData* move; + if (!_library->GetMoveLibrary()->TryGetMove(moveName, move)){ + throw CreatureException("Invalid Move given: " + moveName); + } + if (_attacks.size() >= _library->GetSettings()->GetMaximalMoves()){ + throw CreatureException("This pokemon already has the maximal allowed moves."); + } + _attacks.emplace_back(move, method); + return this; +} diff --git a/src/Battling/Pokemon/CreatePokemon.hpp b/src/Battling/Pokemon/CreatePokemon.hpp index 642d951..67fdad4 100644 --- a/src/Battling/Pokemon/CreatePokemon.hpp +++ b/src/Battling/Pokemon/CreatePokemon.hpp @@ -44,6 +44,7 @@ namespace PkmnLib::Battling { CreatePokemon* WithGender(CreatureLib::Library::Gender gender); CreatePokemon* IsShiny(bool value); CreatePokemon* WithHeldItem(const std::string& item); + CreatePokemon* LearnMove(const std::string& move, CreatureLib::Battling::AttackLearnMethod method); CreatePokemon* WithRandomIndividualValues(CreatureLib::Core::Random rand = CreatureLib::Core::Random()); CreatePokemon* WithIndividualValue(CreatureLib::Core::Statistic stat, uint8_t value); diff --git a/src/Battling/Pokemon/Pokemon.hpp b/src/Battling/Pokemon/Pokemon.hpp index aa45342..5ebb9a2 100644 --- a/src/Battling/Pokemon/Pokemon.hpp +++ b/src/Battling/Pokemon/Pokemon.hpp @@ -33,8 +33,10 @@ namespace PkmnLib::Battling { return dynamic_cast(GetVariant()); } - const bool IsShiny() const{ - return _coloring == 1; + const bool IsShiny() const { return _coloring == 1; } + + const std::vector& GetMoves() const { + return (const std::vector&)_attacks; } const Library::Nature& GetNature() const; diff --git a/src/ScriptResolving/AngelScript/TypeRegistry/Battling/RegisterPokemonClass.cpp b/src/ScriptResolving/AngelScript/TypeRegistry/Battling/RegisterPokemonClass.cpp index 21f9c4c..abf97ba 100644 --- a/src/ScriptResolving/AngelScript/TypeRegistry/Battling/RegisterPokemonClass.cpp +++ b/src/ScriptResolving/AngelScript/TypeRegistry/Battling/RegisterPokemonClass.cpp @@ -68,6 +68,22 @@ CScriptArray* GetTypes(const PkmnLib::Battling::Pokemon* obj) { return nullptr; } +CScriptArray* GetMoves(const PkmnLib::Battling::Pokemon* obj) { + asIScriptContext* ctx = asGetActiveContext(); + if (ctx) { + asIScriptEngine* engine = ctx->GetEngine(); + asITypeInfo* t = engine->GetTypeInfoByDecl("array"); + auto a = obj->GetMoves(); + 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); assert(r >= 0); @@ -119,8 +135,8 @@ void RegisterPokemonClass::RegisterPokemonType(asIScriptEngine* engine) { r = engine->RegisterObjectMethod("Pokemon", "void OverrideActiveAbility(const string &in ability)", asMETHOD(PkmnLib::Battling::Pokemon, OverrideActiveTalent), asCALL_THISCALL); assert(r >= 0); - r = engine->RegisterObjectMethod("Pokemon", "LearnedMove@[]@ get_Moves() const property", - asMETHOD(PkmnLib::Battling::Pokemon, GetAttacks), asCALL_THISCALL); + r = engine->RegisterObjectMethod("Pokemon", "LearnedMove@[]@ GetMoves() const", + asFUNCTION(GetMoves), asCALL_CDECL_OBJLAST); assert(r >= 0); r = engine->RegisterObjectMethod("Pokemon", "const Species@ get_DisplaySpecies() const property", asMETHOD(PkmnLib::Battling::Pokemon, GetDisplaySpecies), asCALL_THISCALL); diff --git a/tests/ScriptTests/ScriptTypeTests/Battle/PokemonTests.cpp b/tests/ScriptTests/ScriptTypeTests/Battle/PokemonTests.cpp index 71b44e6..6eb7df7 100644 --- a/tests/ScriptTests/ScriptTypeTests/Battle/PokemonTests.cpp +++ b/tests/ScriptTests/ScriptTypeTests/Battle/PokemonTests.cpp @@ -1,7 +1,7 @@ #ifdef TESTS_BUILD #include "../../../../extern/catch.hpp" -#include "../../../../src/ScriptResolving/AngelScript/AngelScripResolver.hpp" #include "../../../../src/Battling/Pokemon/CreatePokemon.hpp" +#include "../../../../src/ScriptResolving/AngelScript/AngelScripResolver.hpp" #include "../../../TestLibrary/TestLibrary.hpp" static std::unordered_map _scripts = @@ -19,6 +19,10 @@ class testScript1 { 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; } + bool testHasType(Pokemon@ p, uint8 type){ return p.HasType(type); } + void testDamage(Pokemon@ p, uint32 damage, DamageSource source){ p.Damage(damage, source); } + bool testMove(Pokemon@ p, uint index, LearnedMove@ move){ return p.GetMoves()[index] is move; } + } )"}}; @@ -232,10 +236,10 @@ 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 (size_t i = 0; i < mon->GetTypes().size(); i++){ + .WithForme("default") + ->WithGender(CreatureLib::Library::Gender::Male) + ->Build(); + for (size_t i = 0; i < mon->GetTypes().size(); i++) { auto data = GetScript(mainLib, "testType"); data.Context->SetArgObject(0, const_cast(mon)); @@ -244,12 +248,71 @@ TEST_CASE("Validate Pokemon GetTypes in Script") { REQUIRE(data.Context->Execute() == asEXECUTION_FINISHED); REQUIRE((bool)data.Context->GetReturnWord()); - } + delete mon; +} +TEST_CASE("Validate Pokemon HasType in Script") { + auto mainLib = TestLibrary::GetLibrary(); + + auto mon = PkmnLib::Battling::CreatePokemon(mainLib, "testSpecies3", 30) + .WithForme("default") + ->WithGender(CreatureLib::Library::Gender::Male) + ->Build(); + for (size_t i = 0; i < mon->GetTypes().size(); i++) { + auto data = GetScript(mainLib, "testHasType"); + + data.Context->SetArgObject(0, const_cast(mon)); + data.Context->SetArgByte(1, mon->GetTypes()[i]); + + REQUIRE(data.Context->Execute() == asEXECUTION_FINISHED); + REQUIRE((bool)data.Context->GetReturnWord()); + } + delete mon; +} + +TEST_CASE("Validate Pokemon Damage in Script") { + auto mainLib = TestLibrary::GetLibrary(); + + auto mon = PkmnLib::Battling::CreatePokemon(mainLib, "testSpecies3", 30) + .WithForme("default") + ->WithGender(CreatureLib::Library::Gender::Male) + ->Build(); + auto data = GetScript(mainLib, "testDamage"); + + data.Context->SetArgObject(0, const_cast(mon)); + data.Context->SetArgDWord(1, 30); + data.Context->SetArgDWord(2, (asDWORD)CreatureLib::Battling::DamageSource::AttackDamage); + + REQUIRE(data.Context->Execute() == asEXECUTION_FINISHED); + REQUIRE(mon->GetCurrentHealth() == mon->GetBoostedStat(PkmnLib::Library::Statistic::HealthPoints) - 30); + + delete mon; +} + +TEST_CASE("Validate Pokemon GetMoves in Script") { + auto mainLib = TestLibrary::GetLibrary(); + + auto mon = PkmnLib::Battling::CreatePokemon(mainLib, "testSpecies3", 30) + .WithForme("default") + ->LearnMove("testMove", CreatureLib::Battling::AttackLearnMethod::Level) + ->LearnMove("testMove2", CreatureLib::Battling::AttackLearnMethod::Unknown) + ->Build(); + + for (size_t i = 0; i < mon->GetMoves().size(); i++) { + auto data = GetScript(mainLib, "testMove"); + + data.Context->SetArgObject(0, const_cast(mon)); + data.Context->SetArgDWord(1, i); + data.Context->SetArgObject(2, (void*)mon->GetMoves()[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/TestLibrary/TestLibrary.cpp b/tests/TestLibrary/TestLibrary.cpp index d0fd6c5..33c93d6 100644 --- a/tests/TestLibrary/TestLibrary.cpp +++ b/tests/TestLibrary/TestLibrary.cpp @@ -43,6 +43,9 @@ PkmnLib::Library::MoveLibrary* TestLibrary::BuildMoveLibrary() { lib->LoadMove("testMove", new PkmnLib::Library::MoveData("testMove", 0, PkmnLib::Library::MoveCategory::Physical, 50, 100, 20, CreatureLib::Library::AttackTarget::Adjacent, 0, {})); + lib->LoadMove("testMove2", + new PkmnLib::Library::MoveData("testMove2", 0, PkmnLib::Library::MoveCategory::Special, 30, 100, 10, + CreatureLib::Library::AttackTarget::Adjacent, 0, {})); return lib; } PkmnLib::Library::ItemLibrary* TestLibrary::BuildItemLibrary() {