From aac6c83bcfcc4de737f216f4d7bcd44e286ad9d4 Mon Sep 17 00:00:00 2001 From: Deukhoofd Date: Mon, 16 May 2022 18:16:15 +0200 Subject: [PATCH] Loads of WASM type registry. --- src/Library/Items/ItemLibrary.hpp | 14 +- src/Library/Moves/MoveLibrary.hpp | 10 +- src/Library/Natures/NatureLibrary.hpp | 17 ++- src/Library/Species/SpeciesLibrary.hpp | 19 ++- .../WASM/InterfaceMethods/CoreMethods.cpp | 86 ------------ .../WASM/InterfaceMethods/CoreMethods.hpp | 14 -- .../Library/LibraryMethods.cpp | 131 ++++++++++++++---- .../Library/LibraryMethods.hpp | 2 +- .../Library/WASMMoveDataRegistry.cpp | 29 ++++ .../Library/WASMMoveDataRegistry.hpp | 14 ++ .../WASM/InterfaceMethods/TypeRegistry.hpp | 22 +++ .../WASM/InterfaceMethods/WASMCoreMethods.cpp | 45 ++++++ .../WASM/InterfaceMethods/WASMCoreMethods.hpp | 13 ++ ...{WasmHelperFile.hpp => WASMHelperFile.hpp} | 61 +++++--- .../WASM/InterfaceMethods/WASMStringView.cpp | 28 ++++ .../WASM/InterfaceMethods/WASMStringView.hpp | 10 ++ .../InterfaceMethods/gen7_scripts_rs.wasm | Bin 0 -> 28462 bytes .../WASM/InterfaceMethods/pkmn_lib.wit | 111 +++++++++++++++ .../WASM/WebAssemblyScriptResolver.cpp | 8 +- tests/ScriptTests/WASM/gen7_scripts_rs.wasm | Bin 28705 -> 28446 bytes tests/TestLibrary/TestLibrary.cpp | 18 +-- 21 files changed, 466 insertions(+), 186 deletions(-) delete mode 100644 src/ScriptResolving/WASM/InterfaceMethods/CoreMethods.cpp delete mode 100644 src/ScriptResolving/WASM/InterfaceMethods/CoreMethods.hpp create mode 100644 src/ScriptResolving/WASM/InterfaceMethods/Library/WASMMoveDataRegistry.cpp create mode 100644 src/ScriptResolving/WASM/InterfaceMethods/Library/WASMMoveDataRegistry.hpp create mode 100644 src/ScriptResolving/WASM/InterfaceMethods/TypeRegistry.hpp create mode 100644 src/ScriptResolving/WASM/InterfaceMethods/WASMCoreMethods.cpp create mode 100644 src/ScriptResolving/WASM/InterfaceMethods/WASMCoreMethods.hpp rename src/ScriptResolving/WASM/InterfaceMethods/{WasmHelperFile.hpp => WASMHelperFile.hpp} (80%) create mode 100644 src/ScriptResolving/WASM/InterfaceMethods/WASMStringView.cpp create mode 100644 src/ScriptResolving/WASM/InterfaceMethods/WASMStringView.hpp create mode 100755 src/ScriptResolving/WASM/InterfaceMethods/gen7_scripts_rs.wasm create mode 100644 src/ScriptResolving/WASM/InterfaceMethods/pkmn_lib.wit diff --git a/src/Library/Items/ItemLibrary.hpp b/src/Library/Items/ItemLibrary.hpp index 5ad39cd..4bb4e5d 100644 --- a/src/Library/Items/ItemLibrary.hpp +++ b/src/Library/Items/ItemLibrary.hpp @@ -6,17 +6,23 @@ namespace PkmnLib::Library { class ItemLibrary final : public CreatureLib::Library::ItemLibrary { public: - inline std::optional> TryGet(const ArbUt::BasicStringView& name) const { - auto res = CreatureLib::Library::ItemLibrary::TryGet(name.GetHash()); + inline std::optional> TryGet(const ArbUt::StringView& name) const { + auto res = CreatureLib::Library::ItemLibrary::TryGet(name); + if (!res.has_value()) + return {}; + return res.value().ForceAs(); + } + inline std::optional> TryGet(u32 hashedKey) const { + auto res = CreatureLib::Library::ItemLibrary::TryGetByHash(hashedKey); if (!res.has_value()) return {}; return res.value().ForceAs(); } - inline ArbUt::BorrowedPtr Get(const ArbUt::BasicStringView& name) const { + inline ArbUt::BorrowedPtr Get(const ArbUt::StringView& name) const { return CreatureLib::Library::ItemLibrary::Get(name).ForceAs(); } - inline ArbUt::BorrowedPtr operator[](const ArbUt::BasicStringView& name) const { return Get(name); } + inline ArbUt::BorrowedPtr operator[](const ArbUt::StringView& name) const { return Get(name); } }; } diff --git a/src/Library/Moves/MoveLibrary.hpp b/src/Library/Moves/MoveLibrary.hpp index 4e4a770..27c195e 100644 --- a/src/Library/Moves/MoveLibrary.hpp +++ b/src/Library/Moves/MoveLibrary.hpp @@ -12,24 +12,24 @@ namespace PkmnLib::Library { return Get(name); } - inline std::optional> TryGet(const ArbUt::BasicStringView& name) const { + inline std::optional> TryGet(const ArbUt::StringView& name) const { auto res = CreatureLib::Library::AttackLibrary::TryGet(name); if (!res.has_value()) return {}; return res.value().ForceAs(); } - inline std::optional> TryGet(u32 hash) const { - auto res = CreatureLib::Library::AttackLibrary::TryGet(hash); + inline std::optional> TryGetByHash(u32 hash) const { + auto res = CreatureLib::Library::AttackLibrary::TryGetByHash(hash); if (!res.has_value()) return {}; return res.value().ForceAs(); } - inline ArbUt::BorrowedPtr Get(const ArbUt::BasicStringView& name) const { + inline ArbUt::BorrowedPtr Get(const ArbUt::StringView& name) const { return CreatureLib::Library::AttackLibrary::Get(name).As(); } inline ArbUt::BorrowedPtr Get(u32 hash) const { - return CreatureLib::Library::AttackLibrary::Get(hash).As(); + return CreatureLib::Library::AttackLibrary::GetByHash(hash).As(); } }; } diff --git a/src/Library/Natures/NatureLibrary.hpp b/src/Library/Natures/NatureLibrary.hpp index 7119134..86a8dca 100644 --- a/src/Library/Natures/NatureLibrary.hpp +++ b/src/Library/Natures/NatureLibrary.hpp @@ -1,6 +1,7 @@ #ifndef PKMNLIB_NATURELIBRARY_HPP #define PKMNLIB_NATURELIBRARY_HPP +#include #include #include #include @@ -9,7 +10,7 @@ namespace PkmnLib::Library { class NatureLibrary { private: - std::unordered_map> _items; + ArbUt::StringViewDictionary> _items; public: explicit NatureLibrary(size_t size = 32) noexcept : _items(size) {} @@ -17,19 +18,23 @@ namespace PkmnLib::Library { ~NatureLibrary() = default; inline void LoadNature(const ArbUt::StringView& name, const Nature* nature) { - _items.insert({name, std::unique_ptr(nature)}); + _items.GetStdMap().insert({name, std::unique_ptr(nature)}); } inline ArbUt::BorrowedPtr GetNatureByName(const ArbUt::StringView& name) const { - return _items.at(name); + return _items.Get(name); + } + + inline ArbUt::BorrowedPtr GetNatureByHash(u32 hash) const { + return _items.GetFromHash(hash); } inline const ArbUt::StringView& GetRandomNatureName(ArbUt::Random rand = ArbUt::Random()) const { - auto i = rand.Get(_items.size()); + auto i = rand.Get(_items.Count()); return std::next(std::begin(_items), i)->first; } - inline ArbUt::StringView GetNatureName(ArbUt::BorrowedPtr nature) { + inline const ArbUt::StringView& GetNatureName(ArbUt::BorrowedPtr nature) { for (const auto& v : _items) { if (v.second.get() == nature.GetRaw()) { return v.first; @@ -38,7 +43,7 @@ namespace PkmnLib::Library { throw ArbUt::Exception("Nature not found."); } - size_t GetNatureCount() const noexcept { return _items.size(); } + size_t GetNatureCount() const noexcept { return _items.Count(); } inline const ArbUt::StringView& GetNatureFromIndex(size_t index) const { return std::next(std::begin(_items), index)->first; } diff --git a/src/Library/Species/SpeciesLibrary.hpp b/src/Library/Species/SpeciesLibrary.hpp index a82825c..7791c8f 100644 --- a/src/Library/Species/SpeciesLibrary.hpp +++ b/src/Library/Species/SpeciesLibrary.hpp @@ -12,19 +12,28 @@ namespace PkmnLib::Library { public: SpeciesLibrary(size_t initialCapacity = 32) : CreatureLib::Library::SpeciesLibrary(initialCapacity) {} - inline std::optional> - TryGet(const ArbUt::BasicStringView& name) const { + inline std::optional> TryGet(const ArbUt::StringView& name) const { auto res = CreatureLib::Library::SpeciesLibrary::TryGet(name); if (!res.has_value()) return {}; return res.value().ForceAs(); } - inline ArbUt::BorrowedPtr Get(const ArbUt::BasicStringView& name) const { - return CreatureLib::Library::SpeciesLibrary::Get(name).As(); + inline std::optional> TryGetByHash(u32 hashedKey) const { + auto res = CreatureLib::Library::SpeciesLibrary::TryGetByHash(hashedKey); + if (!res.has_value()) + return {}; + return res.value().ForceAs(); } - ArbUt::BorrowedPtr operator[](const ArbUt::BasicStringView& name) const { + inline ArbUt::BorrowedPtr Get(const ArbUt::StringView& name) const { + return CreatureLib::Library::SpeciesLibrary::Get(name).As(); + } + inline ArbUt::BorrowedPtr GetByHash(u32 hashedKey) const { + return CreatureLib::Library::SpeciesLibrary::GetByHash(hashedKey).As(); + } + + ArbUt::BorrowedPtr operator[](const ArbUt::StringView& name) const { return Get(name); } diff --git a/src/ScriptResolving/WASM/InterfaceMethods/CoreMethods.cpp b/src/ScriptResolving/WASM/InterfaceMethods/CoreMethods.cpp deleted file mode 100644 index edef7e6..0000000 --- a/src/ScriptResolving/WASM/InterfaceMethods/CoreMethods.cpp +++ /dev/null @@ -1,86 +0,0 @@ -#include "CoreMethods.hpp" -#include -#include "../WebAssemblyScriptResolver.hpp" -#include "WasmHelperFile.hpp" -#include "wasm.h" - -wasm_func_t* CreateErrorFunc(wasm_store_t* store, WebAssemblyScriptResolver* resolver) { - // This is probably the most horrific function we need to expose. As we do not want the scripting library to be - // responsible for string formatting for size reasons, we pass a lot of data separately. This includes several - // strings. - return WasmHelpers::CreateFunc( - store, resolver, [](void* env, const wasm_val_vec_t* args, wasm_val_vec_t*) -> wasm_trap_t* { - auto msg = args->data[0].of.i32; - auto msg_len = args->data[1].of.i32; - auto file = args->data[2].of.i32; - auto file_len = args->data[3].of.i32; - auto line = args->data[4].of.i32; - auto position = args->data[5].of.i32; - - auto* resolver = (WebAssemblyScriptResolver*)env; - auto* msgPointer = wasm_memory_data(resolver->GetMemory()) + msg; - auto* filePointer = wasm_memory_data(resolver->GetMemory()) + file; - - auto msgString = std::string_view(msgPointer, msg_len); - auto fileString = std::string_view(filePointer, file_len); - - std::stringstream fullMessage; - fullMessage << "WASM Error with message: " << msgString << std::endl - << "in file: " << fileString << ". Line: " << line << ":" << position; - - wasm_message_t message; - wasm_name_new_from_string_nt(&message, fullMessage.str().c_str()); - wasm_trap_t* trap = wasm_trap_new(resolver->GetStore(), &message); - wasm_name_delete(&message); - return trap; - }); -} - -wasm_func_t* CreatePrintFunc(wasm_store_t* store, WebAssemblyScriptResolver* resolver) { - return WasmHelpers::CreateFunc( - store, resolver, [](void* env, const wasm_val_vec_t* args, wasm_val_vec_t*) -> wasm_trap_t* { - auto msg = args->data[0].of.i32; - auto msg_len = args->data[1].of.i32; - auto resolver = (WebAssemblyScriptResolver*)env; - auto* msgPointer = wasm_memory_data(resolver->GetMemory()) + msg; - auto msgString = std::string_view(msgPointer, msg_len); - std::cout << msgString << std::endl; - return nullptr; - }); - ; -} - -wasm_func_t* ConstString_GetHash(wasm_store_t* store, WebAssemblyScriptResolver* resolver) { - return WasmHelpers::CreateFunc2( - store, resolver, - std::function( - [](WebAssemblyScriptResolver*, const ArbUt::StringView* sv) -> u32 { return sv->GetHash(); })); -} - -wasm_func_t* ConstString_GetStr(wasm_store_t* store, WebAssemblyScriptResolver* resolver) { - return WasmHelpers::CreateFunc( - store, resolver, [](void* env, const wasm_val_vec_t* args, wasm_val_vec_t* returns) -> wasm_trap_t* { - auto resolver = (WebAssemblyScriptResolver*)env; - auto& constString = *(ArbUt::StringView*)args->data[0].of.i64; - - // To allow webassembly to access the C String, we need to allocate it inside it's memory. - // Length + 1 to make room for the '\0' - auto stringPointer = resolver->AllocateMemory(constString.Length() + 1, std::alignment_of()); - - // After we have the pointer to the memory allocated for the string, copy the string with specified length - // to it, then suffix it with the null byte to end it. - strncpy(reinterpret_cast(stringPointer.first), constString.c_str(), constString.Length()); - stringPointer.first[constString.Length()] = '\0'; - - returns->data[0] = WASM_I32_VAL(stringPointer.second); - return nullptr; - }); -} - -void WebAssemblyCoreMethods::Register(wasm_store_t* store, ArbUt::Dictionary& externs, - WebAssemblyScriptResolver* resolver) { - externs.Insert("_error", CreateErrorFunc(store, resolver)); - externs.Insert("_print", CreatePrintFunc(store, resolver)); - externs.Insert("arbutils_const_string_get_hash", ConstString_GetHash(store, resolver)); - externs.Insert("arbutils_const_string_get_str", ConstString_GetStr(store, resolver)); -} diff --git a/src/ScriptResolving/WASM/InterfaceMethods/CoreMethods.hpp b/src/ScriptResolving/WASM/InterfaceMethods/CoreMethods.hpp deleted file mode 100644 index 0bf9bf6..0000000 --- a/src/ScriptResolving/WASM/InterfaceMethods/CoreMethods.hpp +++ /dev/null @@ -1,14 +0,0 @@ -#ifndef PKMNLIB_COREMETHODS_HPP -#define PKMNLIB_COREMETHODS_HPP - -#include -#include - -class WebAssemblyScriptResolver; -class WebAssemblyCoreMethods { -public: - static void Register(wasm_store_t* store, ArbUt::Dictionary& externs, - WebAssemblyScriptResolver* resolver); -}; - -#endif // PKMNLIB_COREMETHODS_HPP diff --git a/src/ScriptResolving/WASM/InterfaceMethods/Library/LibraryMethods.cpp b/src/ScriptResolving/WASM/InterfaceMethods/Library/LibraryMethods.cpp index 58c7cec..ddf6b32 100644 --- a/src/ScriptResolving/WASM/InterfaceMethods/Library/LibraryMethods.cpp +++ b/src/ScriptResolving/WASM/InterfaceMethods/Library/LibraryMethods.cpp @@ -2,38 +2,115 @@ #include #include "../../../../Battling/Library/BattleLibrary.hpp" #include "../../WebAssemblyScriptResolver.hpp" -#include "../WasmHelperFile.hpp" +#include "../WASMHelperFile.hpp" #include "wasm.h" -wasm_func_t* MoveLibrary_GetMoveByHash(wasm_store_t* store) { - wasm_functype_t* type = - wasm_functype_new_2_1(wasm_valtype_new_i64(), wasm_valtype_new_i32(), wasm_valtype_new_i64()); - auto* f = wasm_func_new(store, type, [](const wasm_val_vec_t* args, wasm_val_vec_t* returns) -> wasm_trap_t* { - auto moveLibrary = (PkmnLib::Library::MoveLibrary*)args->data[0].of.i64; - auto hash = (u32)args->data[1].of.i32; - auto opt = moveLibrary->TryGet(hash); - if (!opt.has_value()) { - returns->data[0] = WASM_I64_VAL(0); - } else{ - returns->data[0] = WASM_I64_VAL(reinterpret_cast(moveLibrary->Get(hash).GetRaw())); - } - return nullptr; - }); - wasm_functype_delete(type); - return f; +using namespace PkmnLib::Library; + +#define BASELIBRARY_GET_VALUE_FUNC(type, value_type) \ + wasm_func_t* type##Library_Get##type##ByHash(WebAssemblyScriptResolver* resolver) { \ + return WasmHelpers::CreateFunc( \ + resolver, {[](WebAssemblyScriptResolver*, type##Library* lib, u32 hash) -> const value_type* { \ + auto opt = lib->TryGetByHash(hash); \ + if (!opt.has_value()) { \ + return nullptr; \ + } \ + return opt.value(); \ + }}); \ + } + +BASELIBRARY_GET_VALUE_FUNC(Species, PokemonSpecies) +BASELIBRARY_GET_VALUE_FUNC(Move, MoveData) +BASELIBRARY_GET_VALUE_FUNC(Item, CreatureLib::Library::Item) + +#define REGISTER_BASE_LIB_FUNCS(typeName, type) \ + externs.Insert(typeName "_library_get_" typeName "_by_hash", type##Library_Get##type##ByHash(resolver)) + +wasm_func_t* GrowthRates_CalculateLevelWithHash(WebAssemblyScriptResolver* resolver) { + return WasmHelpers::CreateFunc( + resolver, {[](WebAssemblyScriptResolver*, CreatureLib::Library::GrowthRateLibrary* lib, u32 hash, + u32 experience) -> level_int_t { return lib->CalculateLevel(hash, experience); }}); } -void LibraryMethods::Register(wasm_store_t* store, ArbUt::Dictionary& externs, +wasm_func_t* GrowthRates_CalculateExperienceWithHash(WebAssemblyScriptResolver* resolver) { + return WasmHelpers::CreateFunc( + resolver, {[](WebAssemblyScriptResolver*, CreatureLib::Library::GrowthRateLibrary* lib, u32 hash, + level_int_t level) -> u32 { return lib->CalculateExperience(hash, level); }}); +} + +wasm_func_t* TypeLibrary_GetTypeIdFromHash(WebAssemblyScriptResolver* resolver) { + return WasmHelpers::CreateFunc( + resolver, {[](WebAssemblyScriptResolver*, CreatureLib::Library::TypeLibrary* lib, u32 hash) -> u8 { + return lib->GetTypeIdByHash(hash); + }}); +} + +wasm_func_t* TypeLibrary_GetSingleEffectiveness(WebAssemblyScriptResolver* resolver) { + return WasmHelpers::CreateFunc( + resolver, {[](WebAssemblyScriptResolver*, CreatureLib::Library::TypeLibrary* lib, u8 attacking, + u8 defensive) -> float { return lib->GetSingleEffectiveness(attacking, defensive); }}); +} + +wasm_func_t* TypeLibrary_GetTypeName(WebAssemblyScriptResolver* resolver) { + return WasmHelpers::CreateFunc( + resolver, {[](WebAssemblyScriptResolver*, CreatureLib::Library::TypeLibrary* lib, + u8 type) -> const ArbUt::StringView* { return &lib->GetTypeName(type); }}); +} + +wasm_func_t* NatureLibrary_GetNatureByHash(WebAssemblyScriptResolver* resolver) { + return WasmHelpers::CreateFunc( + resolver, {[](WebAssemblyScriptResolver*, NatureLibrary* lib, u32 hash) -> const Nature* { + return lib->GetNatureByHash(hash); + }}); +} + +wasm_func_t* NatureLibrary_GetNatureName(WebAssemblyScriptResolver* resolver) { + return WasmHelpers::CreateFunc( + resolver, {[](WebAssemblyScriptResolver*, NatureLibrary* lib, + const Nature* nature) -> const ArbUt::StringView* { return &lib->GetNatureName(nature); }}); +} + +void LibraryMethods::Register(ArbUt::Dictionary& externs, WebAssemblyScriptResolver* resolver) { - REGISTER_GETTER("battling_battle_library_get_data_library", PkmnLib::Battling::BattleLibrary, GetStaticLib, store, - resolver); - REGISTER_GETTER("library_data_library_get_move_library", PkmnLib::Library::PokemonLibrary, GetMoveLibrary, store, - resolver); - externs.Insert("library_move_library_get_move_by_hash", MoveLibrary_GetMoveByHash(store)); + REGISTER_GETTER("battle_library_get_data_library", PkmnLib::Battling::BattleLibrary, GetStaticLib, resolver) - REGISTER_GETTER("library_move_data_get_base_power", CreatureLib::Library::AttackData, GetBasePower, store, - resolver); + // Data Library + REGISTER_GETTER("data_library_get_settings", PokemonLibrary, GetSettings, resolver) + REGISTER_GETTER("data_library_get_species_library", PokemonLibrary, GetSpeciesLibrary, resolver) + REGISTER_GETTER("data_library_get_move_library", PokemonLibrary, GetMoveLibrary, resolver) + REGISTER_GETTER("data_library_get_item_library", PokemonLibrary, GetItemLibrary, resolver) + REGISTER_GETTER("data_library_get_growth_rates", CreatureLib::Library::DataLibrary, GetGrowthRates, resolver) + REGISTER_GETTER("data_library_get_type_library", CreatureLib::Library::DataLibrary, GetTypeLibrary, resolver) + REGISTER_GETTER("data_library_get_talent_library", CreatureLib::Library::DataLibrary, GetTalentLibrary, resolver) + REGISTER_GETTER("data_library_get_nature_library", PokemonLibrary, GetNatureLibrary, resolver) - REGISTER_GETTER("library_move_data_get_name", CreatureLib::Library::AttackData, GetName, store, - resolver); + // Library Settings + REGISTER_GETTER("settings_get_max_level", CreatureLib::Library::LibrarySettings, GetMaximalLevel, resolver) + REGISTER_GETTER("settings_get_max_moves", CreatureLib::Library::LibrarySettings, GetMaximalAttacks, resolver) + REGISTER_GETTER("settings_get_shiny_rate", LibrarySettings, GetShinyRate, resolver) + + // Base libraries + REGISTER_BASE_LIB_FUNCS("species", Species); + REGISTER_BASE_LIB_FUNCS("move", Move); + REGISTER_BASE_LIB_FUNCS("item", Item); + + // Growth Rates + externs.Insert("growthrate_library_calculate_level_by_hash", GrowthRates_CalculateLevelWithHash(resolver)); + externs.Insert("growthrate_library_calculate_experience_by_hash", + GrowthRates_CalculateExperienceWithHash(resolver)); + + // Type Library + externs.Insert("type_library_get_type_id_by_hash", TypeLibrary_GetTypeIdFromHash(resolver)); + externs.Insert("type_library_get_single_effectiveness", TypeLibrary_GetSingleEffectiveness(resolver)); + externs.Insert("type_library_get_type_name", TypeLibrary_GetTypeName(resolver)); + + // Nature Library + externs.Insert("nature_library_get_nature_by_hash", NatureLibrary_GetNatureByHash(resolver)); + externs.Insert("nature_library_get_nature_name", NatureLibrary_GetNatureName(resolver)); + + // Natures + REGISTER_GETTER("nature_get_increased_modifier", Nature, GetIncreaseModifier, resolver) + REGISTER_GETTER("nature_get_decreased_modifier", Nature, GetDecreaseModifier, resolver) + REGISTER_GETTER("nature_get_increased_stat", Nature, GetIncreasedStat, resolver) + REGISTER_GETTER("nature_get_decreased_stat", Nature, GetDecreasedStat, resolver) } diff --git a/src/ScriptResolving/WASM/InterfaceMethods/Library/LibraryMethods.hpp b/src/ScriptResolving/WASM/InterfaceMethods/Library/LibraryMethods.hpp index 6220258..46c51d0 100644 --- a/src/ScriptResolving/WASM/InterfaceMethods/Library/LibraryMethods.hpp +++ b/src/ScriptResolving/WASM/InterfaceMethods/Library/LibraryMethods.hpp @@ -6,7 +6,7 @@ class WebAssemblyScriptResolver; class LibraryMethods { public: - static void Register(wasm_store_t* store, ArbUt::Dictionary& externs, + static void Register(ArbUt::Dictionary& externs, WebAssemblyScriptResolver* resolver); }; diff --git a/src/ScriptResolving/WASM/InterfaceMethods/Library/WASMMoveDataRegistry.cpp b/src/ScriptResolving/WASM/InterfaceMethods/Library/WASMMoveDataRegistry.cpp new file mode 100644 index 0000000..b3cf725 --- /dev/null +++ b/src/ScriptResolving/WASM/InterfaceMethods/Library/WASMMoveDataRegistry.cpp @@ -0,0 +1,29 @@ +#include "WASMMoveDataRegistry.hpp" +#include +#include "../../../../Battling/Library/BattleLibrary.hpp" +#include "../../WebAssemblyScriptResolver.hpp" +#include "../WASMHelperFile.hpp" +#include "wasm.h" + +using namespace CreatureLib::Library; + +wasm_func_t* MoveData_HasFlagByHash(WebAssemblyScriptResolver* resolver) { + return WasmHelpers::CreateFunc( + resolver, {[](WebAssemblyScriptResolver*, AttackData* move, u32 flag) -> bool { + return move->HasFlag(flag); + }}); +} + +void WASMMoveDataRegistry::Register(ArbUt::Dictionary& externs, + WebAssemblyScriptResolver* resolver) { + REGISTER_GETTER("move_data_get_name", AttackData, GetName, resolver) + REGISTER_GETTER("move_data_get_type", AttackData, GetType, resolver) + REGISTER_GETTER("move_data_get_category", AttackData, GetCategory, resolver) + REGISTER_GETTER("move_data_get_base_power", AttackData, GetBasePower, resolver); + REGISTER_GETTER("move_data_get_accuracy", AttackData, GetAccuracy, resolver); + REGISTER_GETTER("move_data_get_base_usages", AttackData, GetBaseUsages, resolver); + REGISTER_GETTER("move_data_get_target", AttackData, GetTarget, resolver); + REGISTER_GETTER("move_data_get_priority", AttackData, GetPriority, resolver); + REGISTER_GETTER("move_data_has_secondary_effect", AttackData, HasSecondaryEffect, resolver); + externs.Insert("move_data_has_flag_by_hash", MoveData_HasFlagByHash(resolver)); +} diff --git a/src/ScriptResolving/WASM/InterfaceMethods/Library/WASMMoveDataRegistry.hpp b/src/ScriptResolving/WASM/InterfaceMethods/Library/WASMMoveDataRegistry.hpp new file mode 100644 index 0000000..c32d905 --- /dev/null +++ b/src/ScriptResolving/WASM/InterfaceMethods/Library/WASMMoveDataRegistry.hpp @@ -0,0 +1,14 @@ +#ifndef PKMNLIB_WASMMOVEDATAREGISTRY_H +#define PKMNLIB_WASMMOVEDATAREGISTRY_H + +#include +#include + +class WebAssemblyScriptResolver; +class WASMMoveDataRegistry { +public: + static void Register(ArbUt::Dictionary& externs, + WebAssemblyScriptResolver* resolver); +}; + +#endif // PKMNLIB_WASMMOVEDATAREGISTRY_H diff --git a/src/ScriptResolving/WASM/InterfaceMethods/TypeRegistry.hpp b/src/ScriptResolving/WASM/InterfaceMethods/TypeRegistry.hpp new file mode 100644 index 0000000..bb9833f --- /dev/null +++ b/src/ScriptResolving/WASM/InterfaceMethods/TypeRegistry.hpp @@ -0,0 +1,22 @@ +#ifndef PKMNLIB_TYPEREGISTRY_HPP +#define PKMNLIB_TYPEREGISTRY_HPP + +#include +#include "../WebAssemblyScriptResolver.hpp" +#include "Arbutils/Collections/Dictionary.hpp" +#include "Library/LibraryMethods.hpp" +#include "Library/WASMMoveDataRegistry.hpp" +#include "WASMCoreMethods.hpp" +#include "WASMStringView.hpp" + +class TypeRegistry { +public: + static void Register(ArbUt::Dictionary& externs, WebAssemblyScriptResolver* resolver) { + WASMCoreMethods::Register(externs, resolver); + WASMStringView::Register(externs, resolver); + LibraryMethods::Register(externs, resolver); + WASMMoveDataRegistry::Register(externs, resolver); + } +}; + +#endif // PKMNLIB_TYPEREGISTRY_HPP diff --git a/src/ScriptResolving/WASM/InterfaceMethods/WASMCoreMethods.cpp b/src/ScriptResolving/WASM/InterfaceMethods/WASMCoreMethods.cpp new file mode 100644 index 0000000..0d2c3bc --- /dev/null +++ b/src/ScriptResolving/WASM/InterfaceMethods/WASMCoreMethods.cpp @@ -0,0 +1,45 @@ +#include "WASMCoreMethods.hpp" +#include +#include "../WebAssemblyScriptResolver.hpp" +#include "WASMHelperFile.hpp" +#include "wasm.h" + +wasm_func_t* CreateErrorFunc(WebAssemblyScriptResolver* resolver) { + // This is probably the most horrific function we need to expose. As we do not want the scripting library to be + // responsible for string formatting for size reasons, we pass a lot of data separately. This includes several + // strings. + return WasmHelpers::CreateFunc( + resolver, {[](WebAssemblyScriptResolver* resolver, i32 msg, i32 msg_len, i32 file, i32 file_len, i32 line, + i32 position) -> wasm_trap_t* { + auto* msgPointer = wasm_memory_data(resolver->GetMemory()) + msg; + auto* filePointer = wasm_memory_data(resolver->GetMemory()) + file; + + auto msgString = std::string_view(msgPointer, msg_len); + auto fileString = std::string_view(filePointer, file_len); + + std::stringstream fullMessage; + fullMessage << "WASM Error with message: " << msgString << std::endl + << "in file: " << fileString << ". Line: " << line << ":" << position; + + wasm_message_t message; + wasm_name_new_from_string_nt(&message, fullMessage.str().c_str()); + wasm_trap_t* trap = wasm_trap_new(resolver->GetStore(), &message); + wasm_name_delete(&message); + return trap; + }}); +} + +wasm_func_t* CreatePrintFunc(WebAssemblyScriptResolver* resolver) { + return WasmHelpers::CreateFunc(resolver, + {[](WebAssemblyScriptResolver* resolver, i32 msg, i32 msg_len) { + auto* msgPointer = wasm_memory_data(resolver->GetMemory()) + msg; + auto msgString = std::string_view(msgPointer, msg_len); + std::cout << msgString << std::endl; + }}); +} + +void WASMCoreMethods::Register(ArbUt::Dictionary& externs, + WebAssemblyScriptResolver* resolver) { + externs.Insert("_error", CreateErrorFunc(resolver)); + externs.Insert("_print", CreatePrintFunc(resolver)); +} diff --git a/src/ScriptResolving/WASM/InterfaceMethods/WASMCoreMethods.hpp b/src/ScriptResolving/WASM/InterfaceMethods/WASMCoreMethods.hpp new file mode 100644 index 0000000..3b1a22e --- /dev/null +++ b/src/ScriptResolving/WASM/InterfaceMethods/WASMCoreMethods.hpp @@ -0,0 +1,13 @@ +#ifndef PKMNLIB_WASMCOREMETHODS_HPP +#define PKMNLIB_WASMCOREMETHODS_HPP + +#include +#include + +class WebAssemblyScriptResolver; +class WASMCoreMethods { +public: + static void Register(ArbUt::Dictionary& externs, WebAssemblyScriptResolver* resolver); +}; + +#endif // PKMNLIB_WASMCOREMETHODS_HPP diff --git a/src/ScriptResolving/WASM/InterfaceMethods/WasmHelperFile.hpp b/src/ScriptResolving/WASM/InterfaceMethods/WASMHelperFile.hpp similarity index 80% rename from src/ScriptResolving/WASM/InterfaceMethods/WasmHelperFile.hpp rename to src/ScriptResolving/WASM/InterfaceMethods/WASMHelperFile.hpp index b86b738..a6f2cd1 100644 --- a/src/ScriptResolving/WASM/InterfaceMethods/WasmHelperFile.hpp +++ b/src/ScriptResolving/WASM/InterfaceMethods/WASMHelperFile.hpp @@ -39,10 +39,10 @@ public: } template - static wasm_func_t* RegisterGetter(wasm_store_t* store, WebAssemblyScriptResolver* resolver) { + static wasm_func_t* RegisterGetter(WebAssemblyScriptResolver* resolver) { wasm_functype_t* type = wasm_functype_new_1_1(wasm_valtype_new_i64(), GetValType()); auto* f = wasm_func_new_with_env( - store, type, + resolver->GetStore(), type, [](void* env, const wasm_val_vec_t* args, wasm_val_vec_t* returns) -> wasm_trap_t* { try { auto obj = (const T*)args->data[0].of.i64; @@ -59,26 +59,17 @@ public: return f; } - template - static wasm_func_t* CreateFunc(wasm_store_t* store, WebAssemblyScriptResolver* resolver, - wasm_func_callback_with_env_t func) { - auto funcType = GetFuncType(); - auto* f = wasm_func_new_with_env(store, funcType, func, resolver, nullptr); - wasm_functype_delete(funcType); - return f; - } - template inline static T ConvertAllArguments(const wasm_val_vec_t* t, std::size_t& index) { return FromVal(t->data[index++]); } template - static wasm_func_t* CreateFunc2(wasm_store_t* store, WebAssemblyScriptResolver* resolver, - std::function func) { + static wasm_func_t* CreateFunc(WebAssemblyScriptResolver* resolver, + R (*func)(WebAssemblyScriptResolver*, Args...)) { auto funcType = GetFuncType(); struct Env { WebAssemblyScriptResolver* Resolver; - std::function Func; + R (*Func)(WebAssemblyScriptResolver*, Args...); ~Env() {} }; @@ -86,13 +77,19 @@ public: new (env) Env{.Resolver = resolver, .Func = func}; resolver->Temp_WasmerBug2_2_1_Bypass.Append(env); auto* f = wasm_func_new_with_env( - store, funcType, + resolver->GetStore(), funcType, [](void* env, const wasm_val_vec_t* parameters, wasm_val_vec_t* results) -> wasm_trap_t* { auto e = *(Env*)env; size_t index = 0; try { - R result = e.Func(e.Resolver, ConvertAllArguments(parameters, index)...); - results->data[0] = ToVal(result); + if constexpr (std::is_void()) { + e.Func(e.Resolver, ConvertAllArguments(parameters, index)...); + } else if constexpr (std::is_same()) { + return e.Func(e.Resolver, ConvertAllArguments(parameters, index)...); + } else { + R result = e.Func(e.Resolver, ConvertAllArguments(parameters, index)...); + results->data[0] = ToVal(result); + } } catch (ArbUt::Exception& exception) { return CreateTrapFromException(exception, e.Resolver); } catch (std::exception& exception) { @@ -117,10 +114,16 @@ private: } else { return wasm_valtype_new_i32(); } + } else if constexpr (std::is_floating_point()) { + if constexpr (sizeof(T) > 4) { + return wasm_valtype_new_f64(); + } else { + return wasm_valtype_new_f32(); + } } else if constexpr (std::is_same()) { return wasm_valtype_new_i64(); } - THROW("Unhandled value type: ", typeid(T).name()); + THROW("Unhandled value type: ", std::string(typeid(T).name())); } template inline static wasm_val_t ToVal(const T& val) { @@ -138,6 +141,12 @@ private: } else { return WASM_I32_VAL((i32)val); } + } else if constexpr (std::is_floating_point()) { + if constexpr (sizeof(T) > 4) { + return WASM_F64_VAL((f64)val); + } else { + return WASM_F32_VAL((f32)val); + } } else if constexpr (std::is_same()) { auto v = &val; return WASM_I64_VAL(reinterpret_cast(v)); @@ -156,9 +165,15 @@ private: return dynamic_cast(reinterpret_cast(val.of.i64)); } else if constexpr (std::is_enum() || std::is_integral()) { if constexpr (sizeof(T) > 4) { - return reinterpret_cast(val.of.i64); + return static_cast(val.of.i64); } else { - return reinterpret_cast(val.of.i32); + return static_cast(val.of.i32); + } + } else if constexpr (std::is_floating_point()) { + if constexpr (sizeof(T) > 4) { + return static_cast(val.of.f64); + } else { + return static_cast(val.of.f32); } } THROW("Unhandled value type: ", typeid(T).name()); @@ -177,7 +192,7 @@ private: AppendArgument<0, Args...>(ps); wasm_valtype_vec_t params, results; - if constexpr (std::is_void()) { + if constexpr (std::is_void() || std::is_same()) { results = WASM_EMPTY_VEC; } else { wasm_valtype_t* rs[1] = {GetValType()}; @@ -188,10 +203,10 @@ private: } }; -#define REGISTER_GETTER(name, cType, cFunc, store, resolver) \ +#define REGISTER_GETTER(name, cType, cFunc, resolver) \ externs.Insert( \ name, \ WasmHelpers::RegisterGetter::type, &cType::cFunc>( \ - store, resolver)); + resolver)); #endif // PKMNLIB_HELPERFILE_H diff --git a/src/ScriptResolving/WASM/InterfaceMethods/WASMStringView.cpp b/src/ScriptResolving/WASM/InterfaceMethods/WASMStringView.cpp new file mode 100644 index 0000000..4628c17 --- /dev/null +++ b/src/ScriptResolving/WASM/InterfaceMethods/WASMStringView.cpp @@ -0,0 +1,28 @@ +#include "WASMStringView.hpp" +#include "WASMHelperFile.hpp" + +wasm_func_t* ConstString_GetHash(WebAssemblyScriptResolver* resolver) { + return WasmHelpers::CreateFunc( + resolver, {[](WebAssemblyScriptResolver*, const ArbUt::StringView* sv) -> u32 { return sv->GetHash(); }}); +} + +wasm_func_t* ConstString_GetStr(WebAssemblyScriptResolver* resolver) { + return WasmHelpers::CreateFunc( + resolver, {[](WebAssemblyScriptResolver* resolver, const ArbUt::StringView* constString) -> i32 { + // To allow webassembly to access the C String, we need to allocate it inside it's memory. + // Length + 1 to make room for the '\0' + auto stringPointer = resolver->AllocateMemory(constString->Length() + 1, std::alignment_of()); + + // After we have the pointer to the memory allocated for the string, copy the string with specified length + // to it, then suffix it with the null byte to end it. + strncpy(reinterpret_cast(stringPointer.first), constString->c_str(), constString->Length()); + stringPointer.first[constString->Length()] = '\0'; + return stringPointer.second; + }}); +} + +void WASMStringView::Register(ArbUt::Dictionary& externs, + WebAssemblyScriptResolver* resolver) { + externs.Insert("arbutils_const_string_get_hash", ConstString_GetHash(resolver)); + externs.Insert("arbutils_const_string_get_str", ConstString_GetStr(resolver)); +} diff --git a/src/ScriptResolving/WASM/InterfaceMethods/WASMStringView.hpp b/src/ScriptResolving/WASM/InterfaceMethods/WASMStringView.hpp new file mode 100644 index 0000000..86c831b --- /dev/null +++ b/src/ScriptResolving/WASM/InterfaceMethods/WASMStringView.hpp @@ -0,0 +1,10 @@ +#ifndef PKMNLIB_WASMSTRINGVIEW_HPP +#define PKMNLIB_WASMSTRINGVIEW_HPP +#include "../WebAssemblyScriptResolver.hpp" + +class WASMStringView { +public: + static void Register(ArbUt::Dictionary& externs, WebAssemblyScriptResolver* resolver); +}; + +#endif // PKMNLIB_WASMSTRINGVIEW_HPP diff --git a/src/ScriptResolving/WASM/InterfaceMethods/gen7_scripts_rs.wasm b/src/ScriptResolving/WASM/InterfaceMethods/gen7_scripts_rs.wasm new file mode 100755 index 0000000000000000000000000000000000000000..89c7b41fb2bafd11d8b990efdd4ff42dd82ae774 GIT binary patch literal 28462 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 literal 0 HcmV?d00001 diff --git a/src/ScriptResolving/WASM/InterfaceMethods/pkmn_lib.wit b/src/ScriptResolving/WASM/InterfaceMethods/pkmn_lib.wit new file mode 100644 index 0000000..cc5eaf7 --- /dev/null +++ b/src/ScriptResolving/WASM/InterfaceMethods/pkmn_lib.wit @@ -0,0 +1,111 @@ +// This file documents the entire interface API currently used by the WebAssembly script resolver. +// Currently, we only define a bunch of functions, but in the future when interface types are actually implemented, +// we'd like to implement those as well. + +// Core functions +// These are the core utility functions for use. +// _error can be used for crash handling in the script handler. It takes a message string, file name string, line and position. +_error: function(i32 message_pointer, s32 message_length, i32 file_pointer, i32 file_length, i32 line, i32 position) +// _print can be used to print a message to the hosts stdout +_print: function(i32 message_pointer, s32 message_length) + +// StringView class +type const_string = u64; +arbutils_const_string_get_hash: function(const_string ptr) -> u32 +// Returns a pointer to the WASM memory where the string can be found. +// NOTE: This requires us to copy the string into WASM memory. +arbutils_const_string_get_str: function(const_string ptr) -> s32 + +// Library types +type pokemon_library = u64 +type library_settings = u64 +type species_library = u64 +type move_library = u64 +type item_library = u64 +type growth_rate_library = u64 +type type_library = u64 +type talent_library = u64 +type nature_library = u64 + +type level_int = u8 + +type species = u64 +type move = u64 +type item = u64 +type nature = u64 + +enum Statistic { + Health, + Attack, + Defense + SpecialAttack, + SpecialDefense, + Speed, +} + +// PokemonLibrary class +data_library_get_settings: function(pokemon_library ptr) -> library_settings +data_library_get_species_library: function(pokemon_library ptr) -> species_library +data_library_get_move_library: function(pokemon_library ptr) -> move_library +data_library_get_item_library: function(pokemon_library ptr) -> item_library +data_library_get_growth_rates: function(pokemon_library ptr) -> growth_rate_library +data_library_get_type_library: function(pokemon_library ptr) -> type_library +data_library_get_talent_library: function(pokemon_library ptr) -> talent_library +data_library_get_nature_library: function(pokemon_library ptr) -> nature_library + +// LibrarySettings class +library_settings_get_max_level: function(library_settings ptr) -> level_int +library_settings_get_max_moves: function(library_settings ptr) -> u8 +library_settings_get_shiny_rate: function(library_settings ptr) -> u16 + +// SpeciesLibrary class +species_library_get_species_by_hash: function(species_library library, u32 hash) -> species + +// MoveLibrary class +move_library_get_move_by_hash: function(move_library library, u32 hash) -> move + +// ItemLibrary class +item_library_get_item_by_hash: function(item_library library, u32 hash) -> item + +// GrowthRateLibrary class +growthrate_library_calculate_level_by_hash: function(growth_rate_library library, u32 hash, u32 experience) -> level_int +growthrate_library_calculate_experience_by_hash: function(growth_rate_library library, u32 hash, level_int level) -> u32 + +// TypeLibrary class +type_library_get_type_id_by_hash: function(type_library, u32 hash) -> u8 +type_library_get_single_effectiveness: function(type_library, u8 attacking, u8 offensive) -> f32 +type_library_get_type_name: function(type_library, u8 type) -> const_string + +// NatureLibrary class +nature_library_get_nature_by_hash: function(nature_library, u32 hash) -> nature +nature_library_get_nature_name: function(nature_library, nature) -> const_string + +// Nature class +nature_get_increased_modifier: function(nature) -> f32 +nature_get_decreased_modifier: function(nature) -> f32 +nature_get_increased_stat: function(nature) -> Statistic +nature_get_decreased_stat: function(nature) -> Statistic + +// MoveData class +enum MoveCategory { + Physical, Special, Status, +} +enum MoveTarget { + Adjacent, AdjacentAlly, AdjacentAllySelf, AdjacentOpponent, + All, AllAdjacent, AllAdjacentOpponent, AllAlly, AllOpponent, + Any, + RandomOpponent, Self +} + +move_data_get_name: function(move) -> const_string +move_data_get_type: function(move) -> u8 +move_data_get_category: function(move) -> MoveCategory +move_data_get_base_power: function(move) -> u8 +move_data_get_accuracy: function(move) -> u8 +move_data_get_base_usages: function(move) -> u8 +move_data_get_target: function(move) -> MoveTarget +move_data_get_priority: function(move) -> s8 +move_data_has_secondary_effect: function(move) -> bool +move_data_has_flag_by_hash: function(move, u32 hash) -> bool + + diff --git a/src/ScriptResolving/WASM/WebAssemblyScriptResolver.cpp b/src/ScriptResolving/WASM/WebAssemblyScriptResolver.cpp index f7eb1e8..0949ebb 100644 --- a/src/ScriptResolving/WASM/WebAssemblyScriptResolver.cpp +++ b/src/ScriptResolving/WASM/WebAssemblyScriptResolver.cpp @@ -2,8 +2,7 @@ #include #include #include -#include "InterfaceMethods/CoreMethods.hpp" -#include "InterfaceMethods/Library/LibraryMethods.hpp" +#include "InterfaceMethods/TypeRegistry.hpp" #include "WebAssemblyBattleScript.hpp" #include "WebAssemblyFunctionCall.hpp" #include "wasm.h" @@ -80,10 +79,7 @@ u8 WebAssemblyScriptResolver::LoadWatFromString(const std::string& data) { void WebAssemblyScriptResolver::RegisterFunction() {} -void WebAssemblyScriptResolver::RegisterDefaultMethods() { - WebAssemblyCoreMethods::Register(_store, _imports, this); - LibraryMethods::Register(_store, _imports, this); -} +void WebAssemblyScriptResolver::RegisterDefaultMethods() { TypeRegistry::Register(_imports, this); } void WebAssemblyScriptResolver::Finalize() { RegisterDefaultMethods(); diff --git a/tests/ScriptTests/WASM/gen7_scripts_rs.wasm b/tests/ScriptTests/WASM/gen7_scripts_rs.wasm index fce3ea377084603dc56ed5f696da1a4ee25f31e2..7ef8adae8c99345c7d1d4fc57b670fdfad4864bd 100755 GIT binary patch literal 28446 zcmeI5eUM$}UEj~kecQde(v>X7itQxl-YAJo?A3jLu@mr-b8RbjY{zlzBv4lOi3 ztKHS^O14VKZh|2RIEjG(DP%fsp%ZAsG-ViYXEGqBX(xpg(kU~9soQ3z{)3sej63BI zIyFr{-{(2!-n-hBte7zL4`lD2x98>e{`NfQtkc^(?>dg-{Hs{wa zjXT9{rf*H!^e-=-?QNcQvKl9|xW2Kpy5;z~IBYtYku~dT?|c-G)Z6G^+*(@MTpX;e zZf-4ZZqezC8In^cr_M)rckcH#qs8^Lr=$4so3A~DfyRuHS&TL|);63O|EVWuXY+Z- zO?lp&@9AGE<$I3nI&dwDlzwLxy`NGsO`_J9k%=zg2+Qwzi$*-*S zhKrknjivQ1Cp<8Wz#eM;4SL)J80XR1MJo!? z>d<%di;HKY-uj{_?Rzud=Q^RAKlb+GiG^D8_BXxxE%mn^d*JSS-u3RzLzRci?|bC2 z#uFcW@~Mw}`2CN6VD=|I<39PPuAAQW?)B~soa0`uqjjWqo!jvOkE!}8iCpk0{&SK!2gHmW~O+O5>L|8JjuLoiYFqwC2Bh6k>OP-3-wdy zO1UW>Wv6+Rg;s_)F|TqH9_51!a~5-k?_y2%YSv`0W=-~L46_o1gfZT|OyV&P19R{m z75w29f4MXR0X@h#12j4cW=>*Zk#Ly%Y8&`XPokI;e;F|ym~jlK5;$)waF)Zb`O8Jm zzc=uXdk$1H#7o`de$}VF)AU|MSi%%dG}8m~PClRigKLvJbHYVV9FbcyNCgsdqXOnS zz7J|B$-d;y7?lvYjl3|9j=724fThT77^Y|N>?(1|?MF=5GbUyxd>*>aFzPfh1<^Dy z1vAgp))F%lWbXmP2{8>Io+V~xIsCl0TuejEw1_DqAnS0C`$!b{d-IDt#6&*>tM)c-rz^|s&2)s7Pu&Xv4l z=9IAv=yLjY1VgKStu`j;rS~&FgV3TK3ImoqH7uedefT&045LT zWMERu;j5qHVd39uvZ4!kNXs13B|Y*&tY18sG(g>Q%i%ZFBYb(fU&yo=&8BUwo`q!# zb>QazJniPD(D8Sn0}`G^!nJsXpyI};I3WNF<7dzmE61tuV;4$k-F2r>%Ya(ZHOAWq zv%-H6IuOg;al((HZ?p(MdZCmP33FoNOz2*)Er21VXR~@#G^ld`r&+Q8!fmCLI;DaX zz99531i1|nS0k28KW1`el$_#>0kW8uw$7+&nsI6EnAXKqKFBhpe?fO*gkYz+M1n79 zoScC!^wdjCFf#zP3p}|AJZ_M>%RxpjXlg;0Vk`!P4eBNYH8TLU2%4I};|7^2f&y7W zP{_7FLFo@cjeelDV~Hn93!K7Fi(uGPoqxfeKY~GswK_Oga$@~(!rPYD|e}4TEK&tFt>f3pj%2myKzO(flLV^{2=-u^w0>Sq1mhJZexRQp1`_42gTT zN<3s#Of0rUbLSqqEw&G7nmfgm6az;nB4Lv02c2{$C3t-LilK#H6v&tdnNEqU4|wL3 z=g4m1^OhRs0!JzkM0l8PbdB~wYzGhK3qNBU|E6mk1EV5=j~L)RAaa4oyVw3_j4AWc z2D6$f`R3HMZRfBeau>#_py3|o7MKKd;WL`TXuXDy+tXmGJ*|;_=@Y`6V&aL7z^N5! zS)@Y@zogC}l)s7%vAAg#c|zuf4PzECkXT^IxDN|bh6TP@fVYh0)UtrtecdI%F+z-x zPO(9FiVc$7m<^)Om<_rp!pAGkoHjk}!#=4$Rz_-$RG$UMtj8b6*7eMHDdgftE5OTr9-5g_vmzhn^5 zGf`Ng>;f%@MW_%`Vm2K5@0xQyndOR^GxUsAv7%RaL9{Hw{IOgS=KTA#JDV6PY@#3AL_a*n zsImzpjCVW71OFtwVQ|aOfhh0IOf+pCdE=%B!~^^A!D!Y zb4gQfnYlzBX4aIY%)Eo~5$Wd)Xht<1awnxrF-)+Xc%GQVKn$Y0VY5bc3>!4s3me>5 z#*$es$yMT`4G|5Lu;*m(X%W&PSJo6J04o${nJLdt))JD(hI$8l*YU7Agl1dCIXx%D zn_Di;VK>50h#U_>_y`sd(400&H_0UnBEAaUwc$(4LS#lVnU z!6sP_e8UkkzeE60+e2h|1fY^-3(L!~ zIN>|PZ+(_y;n(%VncV%e>AP5jIp^g6{PmyvPy3+FFI-q#tSmrN3DPZGR<{K~HI&C&$V->!m=vz{seEtuekBAW_X3>5BUQ}*|yp>uAsSUv*O?FDDldt@X?T-b{ zN553cU=I8X;mgjdg7U5K+X8&~gyY=fsEY70)oQ-Dy@F2JhF3T78CHJuh=R9W;F=)8U@Mcu zG-(7BSCtRn5%}kdxzH`9k%^t1uR&Hx7e$Z@rR;6!U?zOiR``~SRt_%|XA`Ow?er2d zNia#tY~feM4>X6HM}s_xmV|-fcH7BfdMZc*12?vOb9BhU4O1Nna~I|nSNXwQkUm$+ z6z4<6y~_!x!B8l<|2EQ<1HSKizEm!~3jk#CwE#%TuFVG-t5jfniJ4US(b>Ed7=w#; zS@^MVjF>7?lVsrHoOdtM;~P@SP|T5pk;fLMj0{?B;KH;U@G^$B_lq{WC^cuuMCV2)R{X885C$5XvdqUYzKnE$JvI z?i z;X56tK3s2hu9Oc3Bt#x}#ziUr2UQAE=i#x5Lvv3C-9!C6?cGl zmiB=>`bRJDES|KO4`!|KL;gFFH_dHsdeR7U(~ECXJ_{)&r@4!OWtrQ-Po}%`DIQ#L z&976pmGUA92A_&+ao$iSAHIs4J;05UGnNwtv8b1!%WP4YII)8S_{}hT2_!O?Ho}j8 z;@R82=j8wBB-GSz&SX}ET6ueN0V_bkgSDg!#WXDN#=;>dmkVDd56dDy zBEl2_NSF)(GW!r<|7Vr}`#uu^_Iof*06?dJX(UFD4M-^>0aR8wzAxwzc-=*;5)`OS zTlpsbvnZH5puv*Plt{Z{DTayHl5e_L`A)!)(dy2NC{v?Babr#$2#I`qq?Epa78yiV zjo%>_&54xPMth=6$VH+huf=L9vO&}nS%ms-&65_lB6kyPTlJs=zpO^c>e1UJBEeU5v$YkQq{E z6vbnjCPAP{rf_gJ2(;mlGV~Jpw+lNk=zGE;qQ8TR0A**qB&4CO3^J{!0}~5*9Q9=a zl4!IK&`^jNkZVlA<873TWc5#*2d>fTXWdEka>c=E#Ni7OyNY#bg(x`=R2YwNAOtF4FG(Ct3YiYy zwH*GKqA`UpX@yj`^Z1)Kg*?jXv-V+~zRGD7Na?J=S=*fDI4g7KD7jS<{3wI0IA9rP zkO{(HRM-^)+I12BN2b-a$nve!WSwrRY?cTSK3p0os;k=0IWlLmiZp_&RT9EUgY9^Y zfne4yWO(6op8`M#7P>_jiGpl&VEy3*Q2}}JLh3rV*aHg|2mmYCNGLTDYMtR>6@CaR zyzmfp6`iN7yfGG8r_0iroHZvU7ggbi%jOxmxPmcij*>>xpzu#LrGyS^BwKVp2YF)@ zl5zm+#zo`(WgaL0DO^*WRV2;|U-~n!pvTk82hus;byZVx!qWZoX%6qWAMZ&U#>Lb+ z;c1d=;=BLiJUUNM3JwmyWb)xlFEhwonv<7wLSFaMi#j1KeCZF>1|@&#YdWDelTyDh zbt(L&WLCro3xt#5!3$G&j&5y)FHwi3zzRZc)47THOv`%|DJxLO_k)i1z;628pQ)vxHv7G=y9 z3GHd1B(V(|FK$D5FDXJAEYQ$p?h6f)a-oqG8mi}k2Kj2ZuKH?LXb|ly_J3TzK!f#a z;x`p96Eu92J4#~2?sM2qd2@noMZ1JA+T9?WJeAL21648ppLN2|OBuu2dP zMFH={d9teIocuVdQczxog36A0O1+)@3pZ!ArB6IfnV)!B^V^t7{}_FCoQdY_cSdF1 zcM7IqL323azkd0b|MW)-rUqL|Jtp!LUetq9dj5bNVM2O^=@Zf`YPGvlw2`DZBYB7X zvq46M9z%8HKorjvXGQV6C_bkkd6`yP1AyXrQ9KXDQ^DNh`t`(ZaSo{%*-$*CD9TjR zm4_j78OE3*bH<2H1_3MljsYFIYEKDMVENb~;+|xw;dFpDw)_v-19)h`^ve>W(2-{` z(#2i67}1&&TZ37XBkQIzDmI)@N0GRN`BU>L(Fahp6$C@Uti_ykch;W9Pk&_jfakf$ z&un-ZyrB}oxHT?1P1BgzKLI@(gA9^Js^wY8gi3jXkmQuQvZbRRev_3j-O`4gnef}r zcuyL#%GM{EwfqO6@SN7PG!m9}=3J0}U>@b8=Zps9Ia}z=h8PI19aDP1kmei<7(X=o z>kJfr*w&Iwi8@pGb&Lb22h3a;j=;aef3W4ZE$IT$jG1${QCtw_^njGCwumE-@f40c z$W6IgJ6ho<#ll;;FzZ64gTegt*liXaAUcJjPkE*iZbn7ouug?wu6PKc^n?5fHVA3A zN|_5>AEBw-JQ-~X7Ty`t_OO^Ji+hu}$EfT^Qx*$L4DZt6n0IOMPVV-m3GZ%-d6&)? ze%FZI)x0}$ZQdQgP-x%a%`x|8!FG)1>@?%Dfrc3~j#|WijGHygy4f-gj_zgJe6W{C zvqr?Az;f}36_c6ZFa`}*e&m7qStM55v?LC(wgCwnsi}*v^?_N^FPre9=kj$kZQHBs2fhu`=(Pr~EjU+6e)akXx4VjsaczDF<==Di#*Xzl#e6x`we*%3D7@XOQKgzU=ZZV-NT*InGi@z{BYvBr%M z-i%!*+w|f&p3^a*P55;a0OSilCJM^PO#agjM;7-?wIgeT=yY7g$;c>yUEx`ED_qfU zVit8UhFxw+>Znawa2*-vNivXP5|&z7FmUE=Oq$V9KW+w@wfd_vl{GT*$b_bfcQgo& zfo-3vI2`s1$?{``e$5ie?D zWzY@sK~d-@424`^!rjd+hlXONCLWqc)+!N~v9eF2EOH=|<%h>PYm2dnO%mXlMO*)5 zpllR3WPBh^Rb-b_dERr?Xw&RN9C3-yeuDd)LdiIX143o) zT6<39N*A}=g<|sz-p0FJ0a5GK@gg#o#GY|a>Yp3$g_S)y1_5>)iV;B)nTCI%*~6Nh zKm4M(x}wae5Od-Dt{t?F9U?I55^rdo3%^DMl3S2;{~fKU7CT{0bHH_B*7IHh0sW?S zxZcQY-~6s;yK;@${@`$WhNydXI`V#A-qK=eIR5$P#U7{d+ajHcQWFK=|4fGD3+iO@ zGF_P=iqp9nI~%0AM8CGa8AsQo{x&VkDY_>6SSBq~v_qVg4Fg5WO7)9W_<|WEx-_e# zhF^P=8WUpM9i>TjX7+Jkm7OWX{<_6XAvW(gc(M-K(QZR*(s_m0<^a+fj*vwmqwr!(KcJs_5KD|akQ-%=Tj~omRouo zVMcEwKvL^9cX%?R*Ad2d{t`br9g(wyD}QaCufrT7a#>FxHxYUE0p-PvZXY7G z1h8~?9Q|pBP3b0+B-%KK=^x_^hGWBC^y9>ziK$Ky#T^M|i#OxGfbInERw%H4kPAvZ zYzUAkc3DY8gx(XEINl&3A`UCwVg(7uW}40Q^Q6n;uP4|tR00GUSeuGe8x3zM|oWDM+BZUdc3OtV%@6A3nn#*Ko& zWJGm|cVLN<3QOW0vat|Cv8H!L!bVOpF~?KpmQz*gVlxXTX$S|X=o$|2PLMJ^FXlGM zhiY0TWwu687fL>6g_15L!1iSzYadkmBUpe^7`>Q|IrDCocG*tuh>pgH#%|aNbEKD#x}yU;?~5tu-ucNZiohAgzFOhIgcvIytdfL8Ay#Pfk!O{+ zB$4nqr!fs|I`a8l4X%8e=HbEc6&=SZVlD}FhlJ7r8c#SGFSwa1EvR9MrtUk3CikI> z8kbleN*RY~8&aJhnM;Cu0%CCeoW{xjmg}aH&C~3dcPF8&ed*1ep6SRTlebz37?BFM zah+y1vKr`-D zvH<4KPUfDxWDp~pO!}4UO=_S_W@Dn;r|CKov-}$zMm3qEY)+EGX)WPK5}#MT`^3jj z$Q$fRvwj$agV(F%seqm!X`&H1S_g&L4*sr71UFOP*8u>5PD%R zeM88+`duUQ$~BO&i!t{1@?@oXnv>w_E*Zmu_jJz%j;g{g$xrw>ZFUadY2+mQs=4^8 zd1>l5L=o%??cx`Npw&dC%^J`zxw{0%kLBG6qf$+9`0kQ{Yt| zR<}^0ams8G=kd#<#{TK$QLBwc=gfX7O+hq zK+OAGxPPi(M4o6@z?)s+CwEdR8x}6zONJY2O)YdobXEv&l{~pkX}n6JJ3H)L?TY1Nx)Bq1fU>x7jKEyc05Ws6)Fc-Us_t13?pJ7Z8YB{E`o-X9I9 z(v#KkoI*42P$t;ZB*n_3eF+jw%_^>TcWCjNp1h8hXI7dy)KF=rjYmv2M@dp|NK(I| zh!x}+hRr&`O!9`L9h7$y=scq~jK~;jqp=uC?>Xu`#cEEF1}ME9sa0Py7ooa^Q4zCQ zHHRzeXjmeXh;ssGgKR)TYt5-eHm_MtYXDX*O5B@17i5u3OBbVqXyEj6vSB#pY?h5J zL5_aJ)@Wq<0v?g_yan3KX@}O!s{mlLY6{)Dn$;V?X>k$;h+LW{m5|Rc4!II?WYwbPMrqc}AVM>sSj|JjNE*(DKWbjLwPb~Q zCDF}PKF!;rI)yxvMh(h_RN;|Uaz*-(s8DQFe-PE{1DA7aGP6O5II~v?QWT$=f-BcgYfuuK;XW4w~jrfuS+Z z%uaboK`Nsownf);6v0Iqy);o&+B|MeTM7_ncJ`K9bL=r%$+dl;gj&TA zu;R~s=)lfWkr{$$BbOmu`dpDLotFW$6#%Hw8j=}9YieolMGutQuF!WMPaP<)gNDGLFevA$$Szj^ZO}bCWKHbM`6r84qc};dA zaK05d^C1Iv;KTyQcGQ>%vB24nBTNe%Uq~@%%@}$!1H7WV6%%2`3Y^MKiNG20yh`9= zBJ347e?Nf}AB@16(aAoqD{wK_#1_Oo%iCKBoY}8PJuDVC@ZBwLQ+OJ3OMz6!c1iNs zOiF|z-$86)wq>|bKNgzFI0y|wp9l?t^A8IyzG>%*lmC37x49W@Y%Q&=2BY56N;JGX zSQYRwbpmf4~L+8Zi#^A(YZDl1IXo}4f{jH5CITvV!VC!rYK(AnFGYI(jl)1JIx#RqA<_ehOjb6by%yEt%{S$rW z`MEoAoNr_coH@?Jv;iciTrOA2)pD&|FE`4~a;w}fcPiydrBbcbD)maE(yX*9?MkOw zu2!nmYOPwYHmc2PtJdktq-mZ5V zNS3r&(@Rn$>2lS#LI)&1S3FZgyJbR;5*K)mrsdqt$G+TJ2V+ zU2a#})po62Z#UY_cB|cPcRGOBVfqe3cj(sPRzj(b-s+i1{0lZ$mIjfC2f@y4oedHe z4fwc}5q#6&gdrcCvK{$|RA31TZI=83lIS?cIhHuSm*ZPFp5jMxV)*oM?=nm>r>|ER z#}M^42TMzm8pruEb7`I}e%{KD=Fg=HhL=z9v8@l7FKc2{S!RG?+v=( zpRRA=M+o-T*ZH;?n2maa2>UwuI-DrzIA3ARB1h3rV z-CNm+dc(_D3E7fpm|UN~xYg^gOzz7L>0bi-8|~%wVDAn1oLYZH?g0CmDL8MYk7zIc z@5MFIvGHf`OusME@9nf_)3U)Yxvt081DJs=J^kpqjO*QZUtE29qqlzij?)2duNRzt zWNkG%9bD?IT#S;Yk4KvqSGKNhx*D8D5#y$gk$eVm8g#J@CY_@1{?e_)2{$<)u}HeT$=|txD@`bJ*(j`EM|4wMWgtpga3_gfWB}mU{!D zm1?im84Ws}W;g$fHzG0h|34+>lw8JYZ{>R=HJ$#bMp{trMTA}DVYxf^cf=X1)G%s| z%2B)C>-Ve8el%n;b#YOt)FQ4_pBFuF2Gi53F3MCq9Yu?=-ai#Zp&lQ*SS=sxZJL9^ zw}pkc!I_n{es5)A;Q@2BZPDo1h_&#hgF&-Qc2CH zRy)0NztSA_huy-hF^&dS`&rpV6W~P~hjKhSv$(c){&0J2bX#%$RB0vY(_)f7F@CKv zXb#$=VYSlZdAZ-csZ7th$kAEvtu77D5jWbiMY17!R64^^pX4B_cY2V%(>>A}&lOXs zZQ-%>wjk1R*oa!yMx{??Fo^2SUiapElBr}X_2u2orNJg}nqVs;R#+rEC9M@5hW*~K zU#UfdX4I@z8{IeDopi3Pt#7tR7gtUC+q{4E(bYlJQH-&;#+e|FDp9Xd>y6s|cCFHH zcW=4(1|V)DXOU7mMi?|A606Rz9(AhqdNk-B%^5j^(r^6mc&ss{JCFCCeli+J?4H1N zgfa%LjRTwRUev{MYW@THQNzWyA+}H_tAfAxNap zs2MO+qT|)!vJ6v32R3DJ`wHu9Ed)O{_-}FHNQ#Sgimc+6~ z*`C^~dCIgGp4wR2GQP9(w9fQ3X3>R2vE1x+>b)w7`?ov2(Nbl>vVgx4xa3uiW}mRp?)0#A?oBa2!pLWOd!abncmwndqL2kmN-mtgM z$)>`u^`&UIuyCI_iq*EA$+s64Z1YpJ)gvnb#^ovSX`O8}sWebr=(SP$dUMo0)&-PW z(?|mC_t@Rl%L@zP>Sd!STbI|P#ib#`G;6hCzcw7z`<>RXQK@&|Hm19~-BA#B!GyOxWH)VTb)ewNs_` z)vI*6CmzsHR+41rt~pfHzj$U!exgdRU!^WqZ&hkI(|)%sXVSC=)9TwGS|JdbDlqO< z9t-7FLxXI;67@$>W7z38dgX5AhctA}pu2bIq+of2qu2WVW~DY7G$}eZn!SFvDpzGV zD8E8hU#ZywfDyJx%1j-*UIie$ai`a4RJyfZ(q~#(8WjWL4J)K^KCwO$1)^D$ETd|_ z-Ht}x`r}N|m`2(V%M|)<5LMh^t6#4VhRsT6)T-9I4cU=qXNr(<)QGL1h`6vYRZP6W zIfnK65Lp;ihEcoPBam&rPJyb_2eoFk-LI895h6P5wjLD$41oJ2-!+P4)yl~ySTA^A zZ(Ww$X2=qCzWoo=>coXjNZM(%hUHd&)NTJY2ORX94XVmb;%1_RR;}C7fR)CXXtfm= zJ~tOPHf;n+=-ITD(WWhxR_gr4fvG<&APDh)6^uxA*zDA6t##XuHtN*d!&Yn5YEtB{ci;6(e>*@`nu1EnNb(0IfUb%&tX0dy+K_yTQc3sS zU-(;suD0usS^!!v>R?2hof;}SWQnEw{qGqoRinT54A!lAa_t$Z&p6tz)K;UXiNo~Q zG4Q;MQm+jOgjh4e>GtaFR`&;9&nO*MR@%MMsNQ0AWzdhh_ddCw`c!JW%GZ_Zbp5(g zxlak!2h5*35u89b8a1P+IvOCbG-_76556AalVkOo!(k7nS0ig~ zbWhcRw==FRR9ZGCe|l-_EGgb-X+>ey5T46_;Oiq+y6WBczMi>9)g}QS%pno(5H55d zdjB-7>U&eO>o|E!lxlM{D6=d$7!t!YMz!w4kL((ONhBs!~0+#u}*2LgHH0RLAKS z%vr6<>?mejR9Zj6vGdoJHjO8*3`m3q#9yN-5n;dk_>K(h-yAHJ+Idn@1B=i@6Iz2> z)Gt#6ue738uior_;Aj74L8w(X&#qlu8S*!VHqKD~8!l6}SfwH_x(G6gO(dE1_JHCl zOWLDKV=(MKv0J{{d$>PE|A%`Fd=(QI6B}J_4O@+JuQnJFICekyG_-En!2WvOr!wQI zW>-yc9WJ-Z4cttFYI?0t8L8fVa`k&S@m`h^9umxV2IYvo0?@Jh)W^lr?-iyu#K7`^ zJq+bRy~NPpjJuzvaP zHJC`%)bs0XI@(z5UtC&YH_T>@$4%P=QSFr}M^IvEH(TWab++ygH?Q5T6;DCGLA5m^ zZ6T1X)nR|Tn?3A02N$W?^#BNT@$vqsfQ>BGyULBbDvdjw pg@apCLO2`s*w7PgdheV)PX@YV)|%gW5J$}R1S-LIsj#&9{{RP-FfIT9 literal 28705 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 kLBGNP`>(Insert("testSpecies"_cnc.GetHash(), + lib->Insert("testSpecies"_cnc, new PkmnLib::Library::PokemonSpecies( 1, "testSpecies"_cnc, new PkmnLib::Library::PokemonForme( @@ -13,7 +13,7 @@ PkmnLib::Library::SpeciesLibrary* TestLibrary::BuildSpeciesLibrary(CreatureLib:: {talentLibrary->Get("testAbility"_cnc)}, {talentLibrary->Get("testHiddenAbility"_cnc)}, new PkmnLib::Library::LearnableMoves(100)), 0.5f, "testGrowthRate"_cnc, 100, 100, {"testEggGroup"_cnc})); - lib->Insert("testSpecies2"_cnc.GetHash(), + lib->Insert("testSpecies2"_cnc, new PkmnLib::Library::PokemonSpecies( 2, "testSpecies2"_cnc, new PkmnLib::Library::PokemonForme( @@ -22,7 +22,7 @@ PkmnLib::Library::SpeciesLibrary* TestLibrary::BuildSpeciesLibrary(CreatureLib:: {talentLibrary->Get("testAbility"_cnc)}, {talentLibrary->Get("testHiddenAbility"_cnc)}, new PkmnLib::Library::LearnableMoves(100)), 0.5f, "testGrowthRate"_cnc, 100, 100, {"testEggGroup"_cnc})); - lib->Insert("statTestSpecies1"_cnc.GetHash(), + lib->Insert("statTestSpecies1"_cnc, new PkmnLib::Library::PokemonSpecies( 3, "statTestSpecies1"_cnc, new PkmnLib::Library::PokemonForme( @@ -31,7 +31,7 @@ PkmnLib::Library::SpeciesLibrary* TestLibrary::BuildSpeciesLibrary(CreatureLib:: {talentLibrary->Get("testAbility"_cnc)}, {talentLibrary->Get("testHiddenAbility"_cnc)}, new PkmnLib::Library::LearnableMoves(100)), 0.5f, "testGrowthRate"_cnc, 100, 100, {"testEggGroup"_cnc})); - lib->Insert("testSpecies3"_cnc.GetHash(), + lib->Insert("testSpecies3"_cnc, new PkmnLib::Library::PokemonSpecies( 4, "testSpecies3"_cnc, new PkmnLib::Library::PokemonForme( @@ -41,7 +41,7 @@ PkmnLib::Library::SpeciesLibrary* TestLibrary::BuildSpeciesLibrary(CreatureLib:: new PkmnLib::Library::LearnableMoves(100)), 0.5f, "testGrowthRate"_cnc, 100, 100, {"testEggGroup"_cnc})); - lib->Insert("testCharizard"_cnc.GetHash(), + lib->Insert("testCharizard"_cnc, new PkmnLib::Library::PokemonSpecies( 5, "testCharizard"_cnc, new PkmnLib::Library::PokemonForme( @@ -50,7 +50,7 @@ PkmnLib::Library::SpeciesLibrary* TestLibrary::BuildSpeciesLibrary(CreatureLib:: {talentLibrary->Get("testAbility"_cnc)}, {talentLibrary->Get("testHiddenAbility"_cnc)}, new PkmnLib::Library::LearnableMoves(100)), 0.5f, "testGrowthRate"_cnc, 100, 100, {"testEggGroup"_cnc})); - lib->Insert("testVenusaur"_cnc.GetHash(), + lib->Insert("testVenusaur"_cnc, new PkmnLib::Library::PokemonSpecies( 6, "testVenusaur"_cnc, new PkmnLib::Library::PokemonForme( @@ -64,11 +64,11 @@ PkmnLib::Library::SpeciesLibrary* TestLibrary::BuildSpeciesLibrary(CreatureLib:: } PkmnLib::Library::MoveLibrary* TestLibrary::BuildMoveLibrary() { auto lib = new PkmnLib::Library::MoveLibrary(); - lib->Insert("testMove"_cnc.GetHash(), + lib->Insert("testMove"_cnc, new PkmnLib::Library::MoveData("testMove"_cnc, 0, PkmnLib::Library::MoveCategory::Physical, 50, 100, 20, CreatureLib::Library::AttackTarget::Adjacent, 0, new CreatureLib::Library::SecondaryEffect(), {})); - lib->Insert("testMove2"_cnc.GetHash(), + lib->Insert("testMove2"_cnc, new PkmnLib::Library::MoveData("testMove2"_cnc, 0, PkmnLib::Library::MoveCategory::Special, 30, 100, 10, CreatureLib::Library::AttackTarget::Adjacent, 0, new CreatureLib::Library::SecondaryEffect(), {})); @@ -76,7 +76,7 @@ PkmnLib::Library::MoveLibrary* TestLibrary::BuildMoveLibrary() { } PkmnLib::Library::ItemLibrary* TestLibrary::BuildItemLibrary() { auto lib = new PkmnLib::Library::ItemLibrary(); - lib->Insert("testItem"_cnc.GetHash(), + lib->Insert("testItem"_cnc, new PkmnLib::Library::Item("testItem"_cnc, CreatureLib::Library::ItemCategory::MiscItem, CreatureLib::Library::BattleItemCategory::None, 0, nullptr, nullptr, {}, 0)); return lib;