Fixes for valgrind failure.
continuous-integration/drone/push Build is failing Details

This commit is contained in:
Deukhoofd 2020-02-06 16:25:55 +01:00
parent b425a7e8b9
commit 67d317e22b
Signed by: Deukhoofd
GPG Key ID: ADF2E9256009EDCE
14 changed files with 91 additions and 65 deletions

View File

@ -41,7 +41,7 @@ steps:
- name: conan-data - name: conan-data
path: /root/.conan/data path: /root/.conan/data
commands: commands:
- valgrind --tool=memcheck --gen-suppressions=all --leak-check=full --leak-resolution=med --track-origins=yes --vgdb=no --error-exitcode=1 build-release/bin/pkmnLibTests - valgrind --tool=memcheck --gen-suppressions=all --leak-check=full --leak-resolution=med --track-origins=yes --vgdb=no --error-exitcode=1 --suppressions=angelscript.supp build-release/bin/pkmnLibTests
- name: test-release-windows - name: test-release-windows
image: deukhoofd/windowsbuilder image: deukhoofd/windowsbuilder
volumes: volumes:

View File

@ -38,7 +38,7 @@ if (NOT EXISTS ${CMAKE_BINARY_DIR}/conanbuildinfo.cmake)
endif() endif()
if (NOT WINDOWS) if (NOT WINDOWS)
execute_process(COMMAND conan install ${CMAKE_SOURCE_DIR} --install-folder=${CMAKE_BINARY_DIR} --build missing execute_process(COMMAND conan install ${CMAKE_SOURCE_DIR} --install-folder=${CMAKE_BINARY_DIR} --build missing
-s compiler=clang -s compiler.libcxx=libstdc++11 -s compiler.version=${VERSION}) -s compiler=clang -s compiler.libcxx=libstdc++11 -s compiler.version=${VERSION} -s build_type=Debug)
else() else()
execute_process(COMMAND conan install ${CMAKE_SOURCE_DIR} --install-folder=${CMAKE_BINARY_DIR} --build missing execute_process(COMMAND conan install ${CMAKE_SOURCE_DIR} --install-folder=${CMAKE_BINARY_DIR} --build missing
-s compiler=gcc -s compiler.libcxx=libstdc++11 -s compiler.version=${VERSION} -s os=Windows) -s compiler=gcc -s compiler.libcxx=libstdc++11 -s compiler.version=${VERSION} -s os=Windows)
@ -66,6 +66,7 @@ if (SCRIPT_PROVIDER STREQUAL "angelscript")
"extern/angelscript_addons/*.cpp" "extern/angelscript_addons/*.cpp"
"extern/angelscript_addons/*.h" "extern/angelscript_addons/*.h"
) )
ADD_DEFINITIONS(-D AS_USE_ACCESSORS=1)
endif() endif()
message(STATUS "${FILE_SOURCE}") message(STATUS "${FILE_SOURCE}")
file(GLOB_RECURSE CORE_SRC_FILES ${FILE_SOURCE}) file(GLOB_RECURSE CORE_SRC_FILES ${FILE_SOURCE})

6
angelscript.supp Normal file
View File

@ -0,0 +1,6 @@
{
SkipAngelScriptMemCheck
Memcheck:Cond
fun:_ZN10asCContext11ExecuteNextEv
fun:_ZN10asCContext7ExecuteEv
}

View File

@ -7,7 +7,7 @@ class PkmnLibConan(ConanFile):
license = "TODO" license = "TODO"
url = "https://git.p-epsilon.com/Deukhoofd/CreatureLib" url = "https://git.p-epsilon.com/Deukhoofd/CreatureLib"
description = "The core implementation for turn based battling using creatures." description = "The core implementation for turn based battling using creatures."
settings = "os", "compiler" settings = "os", "compiler", "build_type"
options = {"shared": [True, False], "script_handler": ["angelscript"]} options = {"shared": [True, False], "script_handler": ["angelscript"]}
default_options = {"shared": True, "script_handler": "angelscript"} default_options = {"shared": True, "script_handler": "angelscript"}
generators = "cmake" generators = "cmake"
@ -40,7 +40,7 @@ class PkmnLibConan(ConanFile):
self.options["AngelScript"].link_std_statically = True self.options["AngelScript"].link_std_statically = True
def requirements(self): def requirements(self):
self.requires("CreatureLib/cd7ddcf78ec0ee4ae645d1862f92ec23246af949@creaturelib/master") self.requires("CreatureLib/e45a36d78eda2b4236f13bdb03004493e309e1ca@creaturelib/master")
if self.options.script_handler == "angelscript": if self.options.script_handler == "angelscript":
self.requires("AngelScript/2.34@AngelScript/Deukhoofd") self.requires("AngelScript/2.34@AngelScript/Deukhoofd")
else: else:

View File

@ -31,22 +31,22 @@ END_AS_NAMESPACE
class CStdStringFactory : public asIStringFactory class CStdStringFactory : public asIStringFactory
{ {
public: public:
CStdStringFactory() {} CStdStringFactory() = default;
~CStdStringFactory() ~CStdStringFactory() override
{ {
// The script engine must release each string // The script engine must release each string
// constant that it has requested // constant that it has requested
assert(stringCache.size() == 0); assert(stringCache.empty());
} }
const void *GetStringConstant(const char *data, asUINT length) const void *GetStringConstant(const char *data, asUINT length) override
{ {
// The string factory might be modified from multiple // The string factory might be modified from multiple
// threads, so it is necessary to use a mutex. // threads, so it is necessary to use a mutex.
asAcquireExclusiveLock(); asAcquireExclusiveLock();
string str(data, length); string str(data, length);
map_t::iterator it = stringCache.find(str); auto it = stringCache.find(str);
if (it != stringCache.end()) if (it != stringCache.end())
it->second++; it->second++;
else else
@ -57,9 +57,9 @@ public:
return reinterpret_cast<const void*>(&it->first); return reinterpret_cast<const void*>(&it->first);
} }
int ReleaseStringConstant(const void *str) int ReleaseStringConstant(const void *str) override
{ {
if (str == 0) if (str == nullptr)
return asERROR; return asERROR;
int ret = asSUCCESS; int ret = asSUCCESS;
@ -68,7 +68,7 @@ public:
// threads, so it is necessary to use a mutex. // threads, so it is necessary to use a mutex.
asAcquireExclusiveLock(); asAcquireExclusiveLock();
map_t::iterator it = stringCache.find(*reinterpret_cast<const string*>(str)); auto it = stringCache.find(*reinterpret_cast<const string*>(str));
if (it == stringCache.end()) if (it == stringCache.end())
ret = asERROR; ret = asERROR;
else else
@ -83,9 +83,9 @@ public:
return ret; return ret;
} }
int GetRawStringData(const void *str, char *data, asUINT *length) const int GetRawStringData(const void *str, char *data, asUINT *length) const override
{ {
if (str == 0) if (str == nullptr)
return asERROR; return asERROR;
if (length) if (length)
@ -98,17 +98,17 @@ public:
} }
// THe access to the string cache is protected with the common mutex provided by AngelScript // THe access to the string cache is protected with the common mutex provided by AngelScript
map_t stringCache; map_t stringCache = {};
}; };
static CStdStringFactory *stringFactory = 0; static CStdStringFactory *stringFactory = nullptr;
// TODO: Make this public so the application can also use the string // TODO: Make this public so the application can also use the string
// factory and share the string constants if so desired, or to // factory and share the string constants if so desired, or to
// monitor the size of the string factory cache. // monitor the size of the string factory cache.
CStdStringFactory *GetStdStringFactorySingleton() CStdStringFactory *GetStdStringFactorySingleton()
{ {
if( stringFactory == 0 ) if( stringFactory == nullptr )
{ {
// The following instance will be destroyed by the global // The following instance will be destroyed by the global
// CStdStringFactoryCleaner instance upon application shutdown // CStdStringFactoryCleaner instance upon application shutdown
@ -122,7 +122,7 @@ class CStdStringFactoryCleaner
public: public:
~CStdStringFactoryCleaner() ~CStdStringFactoryCleaner()
{ {
if (stringFactory) if (stringFactory != nullptr)
{ {
// Only delete the string factory if the stringCache is empty // Only delete the string factory if the stringCache is empty
// If it is not empty, it means that someone might still attempt // If it is not empty, it means that someone might still attempt
@ -133,13 +133,13 @@ public:
if (stringFactory->stringCache.empty()) if (stringFactory->stringCache.empty())
{ {
delete stringFactory; delete stringFactory;
stringFactory = 0; stringFactory = nullptr;
} }
} }
} }
}; };
static CStdStringFactoryCleaner cleaner; static CStdStringFactoryCleaner cleaner = {};
static void ConstructString(string *thisPointer) static void ConstructString(string *thisPointer)
@ -461,12 +461,12 @@ static void StringResize(asUINT l, string &str)
// string formatInt(int64 val, const string &in options, uint width) // string formatInt(int64 val, const string &in options, uint width)
static string formatInt(asINT64 value, const string &options, asUINT width) static string formatInt(asINT64 value, const string &options, asUINT width)
{ {
bool leftJustify = options.find("l") != string::npos; bool leftJustify = options.find('l') != string::npos;
bool padWithZero = options.find("0") != string::npos; bool padWithZero = options.find('0') != string::npos;
bool alwaysSign = options.find("+") != string::npos; bool alwaysSign = options.find('+') != string::npos;
bool spaceOnSign = options.find(" ") != string::npos; bool spaceOnSign = options.find(' ') != string::npos;
bool hexSmall = options.find("h") != string::npos; bool hexSmall = options.find('h') != string::npos;
bool hexLarge = options.find("H") != string::npos; bool hexLarge = options.find('H') != string::npos;
string fmt = "%"; string fmt = "%";
if( leftJustify ) fmt += "-"; if( leftJustify ) fmt += "-";
@ -505,12 +505,12 @@ static string formatInt(asINT64 value, const string &options, asUINT width)
// string formatUInt(uint64 val, const string &in options, uint width) // string formatUInt(uint64 val, const string &in options, uint width)
static string formatUInt(asQWORD value, const string &options, asUINT width) static string formatUInt(asQWORD value, const string &options, asUINT width)
{ {
bool leftJustify = options.find("l") != string::npos; bool leftJustify = options.find('l') != string::npos;
bool padWithZero = options.find("0") != string::npos; bool padWithZero = options.find('0') != string::npos;
bool alwaysSign = options.find("+") != string::npos; bool alwaysSign = options.find('+') != string::npos;
bool spaceOnSign = options.find(" ") != string::npos; bool spaceOnSign = options.find(' ') != string::npos;
bool hexSmall = options.find("h") != string::npos; bool hexSmall = options.find('h') != string::npos;
bool hexLarge = options.find("H") != string::npos; bool hexLarge = options.find('H') != string::npos;
string fmt = "%"; string fmt = "%";
if( leftJustify ) fmt += "-"; if( leftJustify ) fmt += "-";
@ -549,12 +549,12 @@ static string formatUInt(asQWORD value, const string &options, asUINT width)
// string formatFloat(double val, const string &in options, uint width, uint precision) // string formatFloat(double val, const string &in options, uint width, uint precision)
static string formatFloat(double value, const string &options, asUINT width, asUINT precision) static string formatFloat(double value, const string &options, asUINT width, asUINT precision)
{ {
bool leftJustify = options.find("l") != string::npos; bool leftJustify = options.find('l') != string::npos;
bool padWithZero = options.find("0") != string::npos; bool padWithZero = options.find('0') != string::npos;
bool alwaysSign = options.find("+") != string::npos; bool alwaysSign = options.find('+') != string::npos;
bool spaceOnSign = options.find(" ") != string::npos; bool spaceOnSign = options.find(' ') != string::npos;
bool expSmall = options.find("e") != string::npos; bool expSmall = options.find('e') != string::npos;
bool expLarge = options.find("E") != string::npos; bool expLarge = options.find('E') != string::npos;
string fmt = "%"; string fmt = "%";
if( leftJustify ) fmt += "-"; if( leftJustify ) fmt += "-";

View File

@ -1,11 +1,9 @@
#include "AngelScripResolver.hpp" #include "AngelScripResolver.hpp"
#define AS_USE_ACCESSORS
#include "../../../extern/angelscript_addons/scriptarray/scriptarray.h" #include "../../../extern/angelscript_addons/scriptarray/scriptarray.h"
#undef AS_USE_ACCESSORS
#include <cassert>
#include "../../../extern/angelscript_addons/scripthandle/scripthandle.h" #include "../../../extern/angelscript_addons/scripthandle/scripthandle.h"
#include "../../../extern/angelscript_addons/scripthelper/scripthelper.h" #include "../../../extern/angelscript_addons/scripthelper/scripthelper.h"
#include "../../../extern/angelscript_addons/scriptstdstring/scriptstdstring.h" #include "../../../extern/angelscript_addons/scriptstdstring/scriptstdstring.h"
#include <cassert>
#include "TypeRegistry/BasicScriptClass.hpp" #include "TypeRegistry/BasicScriptClass.hpp"
#include "TypeRegistry/Battling/RegisterExecutingAttack.hpp" #include "TypeRegistry/Battling/RegisterExecutingAttack.hpp"
#include "TypeRegistry/Battling/RegisterPokemonClass.hpp" #include "TypeRegistry/Battling/RegisterPokemonClass.hpp"
@ -35,6 +33,7 @@ void AngelScripResolver::Initialize(CreatureLib::Battling::BattleLibrary* arg) {
_engine->SetEngineProperty(asEP_AUTO_GARBAGE_COLLECT, false); _engine->SetEngineProperty(asEP_AUTO_GARBAGE_COLLECT, false);
_engine->SetEngineProperty(asEP_REQUIRE_ENUM_SCOPE, true); _engine->SetEngineProperty(asEP_REQUIRE_ENUM_SCOPE, true);
_engine->SetEngineProperty(asEP_PROPERTY_ACCESSOR_MODE, 2); _engine->SetEngineProperty(asEP_PROPERTY_ACCESSOR_MODE, 2);
_engine->SetEngineProperty(asEP_COMPILER_WARNINGS , 2);
RegisterStdString(_engine); RegisterStdString(_engine);

View File

@ -43,7 +43,9 @@ public:
} \ } \
_ctxPool->ReturnContextToPool(ctx); _ctxPool->ReturnContextToPool(ctx);
void Stack() override { CALLHOOK(Stack, {}); } void Stack() override { CALLHOOK(Stack,); }
void OnRemove() override { CALLHOOK(OnRemove,); }
void OnBeforeTurn(const CreatureLib::Battling::BaseTurnChoice* choice) override { void OnBeforeTurn(const CreatureLib::Battling::BaseTurnChoice* choice) override {
throw NotImplementedException(); // TODO throw NotImplementedException(); // TODO

View File

@ -70,6 +70,7 @@ public:
const FunctionInfo& Get##name() const { return __##name; } const FunctionInfo& Get##name() const { return __##name; }
SCRIPT_HOOK_FUNCTION(Stack, "void Stack()"); SCRIPT_HOOK_FUNCTION(Stack, "void Stack()");
SCRIPT_HOOK_FUNCTION(OnRemove, "void OnRemove()");
SCRIPT_HOOK_FUNCTION(PreventAttack, "void PreventAttack(ExecutingMove@ attack, bool& result)"); SCRIPT_HOOK_FUNCTION(PreventAttack, "void PreventAttack(ExecutingMove@ attack, bool& result)");
SCRIPT_HOOK_FUNCTION(FailAttack, "void FailAttack(ExecutingMove@ attack, bool& result)"); SCRIPT_HOOK_FUNCTION(FailAttack, "void FailAttack(ExecutingMove@ attack, bool& result)");
SCRIPT_HOOK_FUNCTION(StopBeforeAttack, "void StopBeforeAttack(ExecutingMove@ attack, bool& result)"); SCRIPT_HOOK_FUNCTION(StopBeforeAttack, "void StopBeforeAttack(ExecutingMove@ attack, bool& result)");

View File

@ -7,6 +7,7 @@ void BasicScriptClass::Register(asIScriptEngine* engine) {
[[maybe_unused]] int r = engine->GetModuleByIndex(0)->AddScriptSection("PkmnScript", R"( [[maybe_unused]] int r = engine->GetModuleByIndex(0)->AddScriptSection("PkmnScript", R"(
shared abstract class PkmnScript { shared abstract class PkmnScript {
void Stack(){}; void Stack(){};
void OnRemove(){};
void PreventAttack(ExecutingMove@ attack, bool& result){}; void PreventAttack(ExecutingMove@ attack, bool& result){};
void FailAttack(ExecutingMove@ attack, bool& result){}; void FailAttack(ExecutingMove@ attack, bool& result){};
void StopBeforeAttack(ExecutingMove@ attack, bool& result){}; void StopBeforeAttack(ExecutingMove@ attack, bool& result){};

View File

@ -10,6 +10,7 @@
static std::unordered_map<const char*, const char*> _scripts = std::unordered_map<const char*, const char*>{ static std::unordered_map<const char*, const char*> _scripts = std::unordered_map<const char*, const char*>{
AS_CLASS(blankScript, ), AS_CLASS(blankScript, ),
AS_CLASS(stackScript, "int value = 0; void Stack() override { value++; } int GetValue() { return value; }"), AS_CLASS(stackScript, "int value = 0; void Stack() override { value++; } int GetValue() { return value; }"),
AS_CLASS(onRemoveScript, "int value = 0; void OnRemove() override { value++; } int GetValue() { return value; }"),
{"doubleInheritanceScript", R"( {"doubleInheritanceScript", R"(
class doubleInheritanceScriptBase : PkmnScript { class doubleInheritanceScriptBase : PkmnScript {
int value = 0; int value = 0;
@ -105,6 +106,22 @@ TEST_CASE("Invoke Stack script function") {
delete script; delete script;
} }
TEST_CASE("Invoke OnRemove script function") {
auto mainLib = TestLibrary::GetLibrary();
auto script = GetScript(mainLib, "onRemoveScript");
script->OnRemove();
auto ctxPool = script->GetContextPool();
auto ctx = ctxPool->RequestContext();
script->PrepareMethod("GetValue", ctx);
REQUIRE(ctx->Execute() == asEXECUTION_FINISHED);
REQUIRE(ctx->GetReturnDWord() == 1);
ctxPool->ReturnContextToPool(ctx);
delete script;
}
TEST_CASE("Invoke Stack script function with implementation in base class") { TEST_CASE("Invoke Stack script function with implementation in base class") {
auto mainLib = TestLibrary::GetLibrary(); auto mainLib = TestLibrary::GetLibrary();
auto script = GetScript(mainLib, "doubleInheritanceScript"); auto script = GetScript(mainLib, "doubleInheritanceScript");

View File

@ -15,7 +15,7 @@ class testScript1 {
bool testShiny(Pokemon@ p, bool shiny){ return p.Shiny == shiny; } bool testShiny(Pokemon@ p, bool shiny){ return p.Shiny == shiny; }
bool testHeldItem(Pokemon@ p, Item@ item){ return p.HeldItem is item; } bool testHeldItem(Pokemon@ p, Item@ item){ return p.HeldItem is item; }
bool testCurrentHealth(Pokemon@ p, uint health){ return p.CurrentHealth == health; } bool testCurrentHealth(Pokemon@ p, uint health){ return p.CurrentHealth == health; }
bool testNickname(Pokemon@ p, const string &in name){ return p.Nickname == name; } bool testNickname(Pokemon@ p, const string& name){ return p.Nickname == name; }
bool testActiveAbility(Pokemon@ p, const string &in ability){ return p.ActiveAbility == ability; } bool testActiveAbility(Pokemon@ p, const string &in ability){ return p.ActiveAbility == ability; }
bool testIsFainted(Pokemon@ p, bool b){ return p.IsFainted == b; } bool testIsFainted(Pokemon@ p, bool b){ return p.IsFainted == b; }
bool testType(Pokemon@ p, uint index, uint8 type){ return p.GetTypes()[index] == type; } bool testType(Pokemon@ p, uint index, uint8 type){ return p.GetTypes()[index] == type; }
@ -29,10 +29,10 @@ class testScript1 {
static const char* _testLoadFunc(const char* name) { return _scripts[name]; } static const char* _testLoadFunc(const char* name) { return _scripts[name]; }
struct ScriptData { struct ScriptData {
AngelScriptScript* Script; AngelScriptScript* Script = nullptr;
AngelScripResolver* Resolver; AngelScripResolver* Resolver = nullptr;
asIScriptFunction* Func; asIScriptFunction* Func = nullptr;
asIScriptContext* Context; asIScriptContext* Context = nullptr;
~ScriptData() { ~ScriptData() {
Script->GetContextPool()->ReturnContextToPool(Context); Script->GetContextPool()->ReturnContextToPool(Context);
@ -207,7 +207,7 @@ TEST_CASE("Validate Pokemon Active Ability in Script") {
.WithForme("default") .WithForme("default")
->WithGender(CreatureLib::Library::Gender::Male) ->WithGender(CreatureLib::Library::Gender::Male)
->Build(); ->Build();
data.Context->SetArgObject(0, const_cast<PkmnLib::Battling::Pokemon*>(mon)); data.Context->SetArgObject(0, (void*)mon);
auto name = mon->GetActiveTalent(); auto name = mon->GetActiveTalent();
data.Context->SetArgAddress(1, &name); data.Context->SetArgAddress(1, &name);

View File

@ -20,10 +20,10 @@ class testScript1 {
static const char* _testLoadFunc(const char* name) { return _scripts[name]; } static const char* _testLoadFunc(const char* name) { return _scripts[name]; }
struct ScriptData { struct ScriptData {
AngelScriptScript* Script; AngelScriptScript* Script = nullptr;
AngelScripResolver* Resolver; AngelScripResolver* Resolver = nullptr;
asIScriptFunction* Func; asIScriptFunction* Func = nullptr;
asIScriptContext* Context; asIScriptContext* Context = nullptr;
~ScriptData() { ~ScriptData() {
Script->GetContextPool()->ReturnContextToPool(Context); Script->GetContextPool()->ReturnContextToPool(Context);
@ -32,8 +32,8 @@ struct ScriptData {
}; };
static AngelScripResolver* _resolverCache = nullptr; static AngelScripResolver* _resolverCache = nullptr;
static AngelScripResolver* GetScriptResolver(PkmnLib::Battling::BattleLibrary* mainLib){ static AngelScripResolver* GetScriptResolver(PkmnLib::Battling::BattleLibrary* mainLib) {
if (_resolverCache == nullptr){ if (_resolverCache == nullptr) {
_resolverCache = dynamic_cast<AngelScripResolver*>(PkmnLib::Battling::BattleLibrary::CreateScriptResolver()); _resolverCache = dynamic_cast<AngelScripResolver*>(PkmnLib::Battling::BattleLibrary::CreateScriptResolver());
_resolverCache->Initialize(mainLib); _resolverCache->Initialize(mainLib);
_resolverCache->SetCreateFunction(&_testLoadFunc); _resolverCache->SetCreateFunction(&_testLoadFunc);
@ -171,5 +171,4 @@ TEST_CASE("Validate Forme GetAbility in Script") {
REQUIRE((bool)data.Context->GetReturnWord()); REQUIRE((bool)data.Context->GetReturnWord());
} }
#endif #endif

View File

@ -16,10 +16,10 @@ class testScript1 {
static const char* _testLoadFunc(const char* name) { return _scripts[name]; } static const char* _testLoadFunc(const char* name) { return _scripts[name]; }
struct ScriptData { struct ScriptData {
AngelScriptScript* Script; AngelScriptScript* Script = nullptr;
AngelScripResolver* Resolver; AngelScripResolver* Resolver = nullptr;
asIScriptFunction* Func; asIScriptFunction* Func = nullptr;
asIScriptContext* Context; asIScriptContext* Context = nullptr;
~ScriptData() { ~ScriptData() {
Script->GetContextPool()->ReturnContextToPool(Context); Script->GetContextPool()->ReturnContextToPool(Context);

View File

@ -20,10 +20,10 @@ class testScript1 {
static const char* _testLoadFunc(const char* name) { return _scripts[name]; } static const char* _testLoadFunc(const char* name) { return _scripts[name]; }
struct ScriptData { struct ScriptData {
AngelScriptScript* Script; AngelScriptScript* Script = nullptr;
AngelScripResolver* Resolver; AngelScripResolver* Resolver = nullptr;
asIScriptFunction* Func; asIScriptFunction* Func = nullptr;
asIScriptContext* Context; asIScriptContext* Context = nullptr;
~ScriptData() { ~ScriptData() {
Script->GetContextPool()->ReturnContextToPool(Context); Script->GetContextPool()->ReturnContextToPool(Context);
@ -61,7 +61,7 @@ TEST_CASE("Validate Move Name in Script") {
auto data = GetScript(mainLib, "testName"); auto data = GetScript(mainLib, "testName");
auto move = mainLib->GetMoveLibrary()->GetAttack("testMove"); auto move = mainLib->GetMoveLibrary()->GetAttack("testMove");
data.Context->SetArgObject(0, const_cast<PkmnLib::Library::MoveData*>(move)); data.Context->SetArgObject(0, (void*)move);
auto name = move->GetName(); auto name = move->GetName();
data.Context->SetArgAddress(1, &name); data.Context->SetArgAddress(1, &name);