Implements new Effect Parameters in AngelScript/
continuous-integration/drone/push Build is passing Details

This commit is contained in:
Deukhoofd 2020-04-10 20:39:11 +02:00
parent 0700f7cfbd
commit d12267c695
Signed by: Deukhoofd
GPG Key ID: ADF2E9256009EDCE
7 changed files with 153 additions and 4 deletions

View File

@ -13,6 +13,7 @@
#include "TypeRegistry/Battling/RegisterPokemonClass.hpp" #include "TypeRegistry/Battling/RegisterPokemonClass.hpp"
#include "TypeRegistry/Battling/RegisterTurnChoices.hpp" #include "TypeRegistry/Battling/RegisterTurnChoices.hpp"
#include "TypeRegistry/ConstString.hpp" #include "TypeRegistry/ConstString.hpp"
#include "TypeRegistry/Library/RegisterEffectParameter.hpp"
#include "TypeRegistry/Library/RegisterGrowthRateTypes.hpp" #include "TypeRegistry/Library/RegisterGrowthRateTypes.hpp"
#include "TypeRegistry/Library/RegisterItemTypes.hpp" #include "TypeRegistry/Library/RegisterItemTypes.hpp"
#include "TypeRegistry/Library/RegisterMoveTypes.hpp" #include "TypeRegistry/Library/RegisterMoveTypes.hpp"
@ -24,6 +25,26 @@ CreatureLib::Battling::ScriptResolver* PkmnLib::Battling::BattleLibrary::CreateS
return new AngelScripResolver(); return new AngelScripResolver();
} }
static void TranslateException(asIScriptContext *ctx, void* /*userParam*/)
{
try
{
// Retrow the original exception so we can catch it again
throw;
}
catch( std::exception &e )
{
// Tell the VM the type of exception that occurred
ctx->SetException(e.what());
}
catch(...)
{
// The callback must not allow any exception to be thrown, but it is not necessary
// to explicitly set an exception string if the default exception string is sufficient
}
}
void AngelScripResolver::Initialize(CreatureLib::Battling::BattleLibrary* arg) { void AngelScripResolver::Initialize(CreatureLib::Battling::BattleLibrary* arg) {
for (auto scriptCategory : ScriptCategoryHelper::GetValues()) { for (auto scriptCategory : ScriptCategoryHelper::GetValues()) {
_typeDatabase.Insert(scriptCategory, {}); _typeDatabase.Insert(scriptCategory, {});
@ -31,6 +52,7 @@ void AngelScripResolver::Initialize(CreatureLib::Battling::BattleLibrary* arg) {
auto library = (PkmnLib::Battling::BattleLibrary*)arg; auto library = (PkmnLib::Battling::BattleLibrary*)arg;
_engine = asCreateScriptEngine(); _engine = asCreateScriptEngine();
_engine->SetTranslateAppExceptionCallback(asFUNCTION(TranslateException), 0, asCALL_CDECL);
int32_t r = _engine->SetMessageCallback(asFUNCTION(MessageCallback), nullptr, asCALL_CDECL); int32_t r = _engine->SetMessageCallback(asFUNCTION(MessageCallback), nullptr, asCALL_CDECL);
if (r < 0) if (r < 0)
@ -76,6 +98,7 @@ void AngelScripResolver::RegisterTypes() {
RegisterGrowthRateTypes::Register(_engine); RegisterGrowthRateTypes::Register(_engine);
RegisterTypeLibrary::Register(_engine); RegisterTypeLibrary::Register(_engine);
RegisterStaticLibraryTypes::Register(_engine); RegisterStaticLibraryTypes::Register(_engine);
RegisterEffectParameter::Register(_engine);
// Register battle types // Register battle types
RegisterPokemonClass::Register(_engine); RegisterPokemonClass::Register(_engine);

View File

@ -4,6 +4,7 @@
#define ANGELSCRIPT_DLL_LIBRARY_IMPORT #define ANGELSCRIPT_DLL_LIBRARY_IMPORT
#include <CreatureLib/Library/Exceptions/NotImplementedException.hpp> #include <CreatureLib/Library/Exceptions/NotImplementedException.hpp>
#include <angelscript.h> #include <angelscript.h>
#include "../../../extern/angelscript_addons/scriptarray/scriptarray.h"
#include "../../Battling/PkmnScript.hpp" #include "../../Battling/PkmnScript.hpp"
#include "AngelScriptTypeInfo.hpp" #include "AngelScriptTypeInfo.hpp"
#include "ContextPool.hpp" #include "ContextPool.hpp"
@ -73,6 +74,28 @@ public:
ctx->PopState(); \ ctx->PopState(); \
} }
static CScriptArray*
GetEffectParameters(asIScriptContext* ctx,
const Arbutils::Collections::List<CreatureLib::Library::EffectParameter*>& ls) {
asIScriptEngine* engine = ctx->GetEngine();
asITypeInfo* t = engine->GetTypeInfoByDecl("array<EffectParameter@>");
CScriptArray* arr = CScriptArray::Create(t, ls.Count());
for (size_t i = 0; i < ls.Count(); i++) {
arr->SetValue(i, (void**)&ls[i]);
}
return arr;
}
void OnInitialize(const Arbutils::Collections::List<CreatureLib::Library::EffectParameter*>& parameters) override {
CScriptArray* arr = nullptr;
CALL_HOOK(OnInitialize, {
arr = GetEffectParameters(ctx, parameters);
ctx->SetArgAddress(0, arr);
})
if (arr != nullptr){
arr->Release();
}
}
void Stack() override { CALL_HOOK(Stack, ); } void Stack() override { CALL_HOOK(Stack, ); }
void OnRemove() override { CALL_HOOK(OnRemove, ); } void OnRemove() override { CALL_HOOK(OnRemove, ); }

View File

@ -77,6 +77,7 @@ private:
public: \ public: \
const FunctionInfo& Get##name() const { return __##name; } const FunctionInfo& Get##name() const { return __##name; }
SCRIPT_HOOK_FUNCTION(OnInitialize, "void OnInitialize(const array<EffectParameter@> &in parameters)");
SCRIPT_HOOK_FUNCTION(Stack, "void Stack()"); SCRIPT_HOOK_FUNCTION(Stack, "void Stack()");
SCRIPT_HOOK_FUNCTION(OnRemove, "void OnRemove()"); 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)");

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 {
// CreatureLib methods // CreatureLib methods
void OnInitialize(const array<EffectParameter@> &in parameters){};
void Stack(){}; void Stack(){};
void OnRemove(){}; void OnRemove(){};
void PreventAttack(ExecutingMove@ attack, bool& result){}; void PreventAttack(ExecutingMove@ attack, bool& result){};
@ -38,5 +39,4 @@ shared abstract class PkmnScript {
} }
)"); )");
assert(r >= 0); assert(r >= 0);
} }

View File

@ -0,0 +1,38 @@
#include "RegisterEffectParameter.hpp"
#include <Arbutils/Assert.hpp>
#include <CreatureLib/Library/EffectParameter.hpp>
static CreatureLib::Library::EffectParameter* Ref_Factory() { return new CreatureLib::Library::EffectParameter(); }
static std::string AsString(const CreatureLib::Library::EffectParameter* p) { return p->AsString(); }
void RegisterEffectParameter::Register(asIScriptEngine* engine) {
[[maybe_unused]] int r = engine->RegisterEnum("EffectParameterType");
Assert(r >= 0);
for (auto val : CreatureLib::Library::EffectParameterTypeHelper::GetValues()) {
r = engine->RegisterEnumValue("EffectParameterType",
CreatureLib::Library::EffectParameterTypeHelper::ToString(val), (int)val);
Assert(r >= 0);
}
r = engine->RegisterObjectType("EffectParameter", 0, asOBJ_REF | asOBJ_NOCOUNT);
Assert(r >= 0);
r = engine->RegisterObjectBehaviour("EffectParameter", asBEHAVE_FACTORY, "EffectParameter@ f()",
asFUNCTION(Ref_Factory), asCALL_CDECL);
Assert(r >= 0);
r = engine->RegisterObjectMethod("EffectParameter", "EffectParameterType GetType() const",
asMETHOD(CreatureLib::Library::EffectParameter, GetType), asCALL_THISCALL);
Assert(r >= 0);
r = engine->RegisterObjectMethod("EffectParameter", "bool AsBool() const",
asMETHOD(CreatureLib::Library::EffectParameter, AsBool), asCALL_THISCALL);
Assert(r >= 0);
r = engine->RegisterObjectMethod("EffectParameter", "int64 AsInt() const",
asMETHOD(CreatureLib::Library::EffectParameter, AsInt), asCALL_THISCALL);
Assert(r >= 0);
r = engine->RegisterObjectMethod(
"EffectParameter", "string AsString() const",
asFUNCTIONPR(AsString, (const CreatureLib::Library::EffectParameter*), std::string), asCALL_CDECL_OBJFIRST);
Assert(r >= 0);
}

View File

@ -0,0 +1,10 @@
#ifndef PKMNLIB_REGISTEREFFECTPARAMETER_HPP
#define PKMNLIB_REGISTEREFFECTPARAMETER_HPP
#include <angelscript.h>
class RegisterEffectParameter {
public:
static void Register(asIScriptEngine* engine);
};
#endif // PKMNLIB_REGISTEREFFECTPARAMETER_HPP

View File

@ -9,6 +9,20 @@
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(initializeScript, R"(
bool boolValue = false;
int64 intValue = 0;
string stringValue = "";
void OnInitialize(const array<EffectParameter@> &in parameters) override {
boolValue = parameters[0].AsBool();
intValue = parameters[1].AsInt();
stringValue = parameters[2].AsString();
}
bool GetBoolValue() { return boolValue; }
int64 GetIntValue() { return intValue; }
string GetStringValue() { return stringValue; }
)"),
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; }"), AS_CLASS(onRemoveScript, "int value = 0; void OnRemove() override { value++; } int GetValue() { return value; }"),
{"doubleInheritanceScript", R"( {"doubleInheritanceScript", R"(
@ -93,6 +107,47 @@ TEST_CASE("Invoke non-implemented script function") {
delete script; delete script;
} }
TEST_CASE("Invoke OnInitialize script function") {
auto mainLib = TestLibrary::GetLibrary();
auto script = GetScript(mainLib, "initializeScript"_cnc);
REQUIRE(script != nullptr);
auto parameters = {
new CreatureLib::Library::EffectParameter(true),
new CreatureLib::Library::EffectParameter((int64_t)684),
new CreatureLib::Library::EffectParameter(std::string("foobar"))
};
script->OnInitialize(parameters);
auto ctxPool = script->GetContextPool();
auto ctx = ctxPool->RequestContext();
script->PrepareMethod("GetBoolValue"_cnc, ctx);
REQUIRE(ctx->Execute() == asEXECUTION_FINISHED);
REQUIRE((bool)ctx->GetReturnDWord());
ctxPool->ReturnContextToPool(ctx);
ctx = ctxPool->RequestContext();
script->PrepareMethod("GetIntValue"_cnc, ctx);
REQUIRE(ctx->Execute() == asEXECUTION_FINISHED);
REQUIRE(ctx->GetReturnQWord() == 684);
ctxPool->ReturnContextToPool(ctx);
ctx = ctxPool->RequestContext();
script->PrepareMethod("GetStringValue"_cnc, ctx);
REQUIRE(ctx->Execute() == asEXECUTION_FINISHED);
std::string s;
s = *(std::string*)ctx->GetReturnAddress();
REQUIRE(s == "foobar");
ctxPool->ReturnContextToPool(ctx);
for (auto p : parameters){
delete p;
}
delete script;
}
TEST_CASE("Invoke Stack script function") { TEST_CASE("Invoke Stack script function") {
auto mainLib = TestLibrary::GetLibrary(); auto mainLib = TestLibrary::GetLibrary();
auto script = GetScript(mainLib, "stackScript"_cnc); auto script = GetScript(mainLib, "stackScript"_cnc);
@ -296,7 +351,6 @@ TEST_CASE("Get script name.") {
delete script; delete script;
} }
TEST_CASE("Handle script exceptions.") { TEST_CASE("Handle script exceptions.") {
auto mainLib = TestLibrary::GetLibrary(); auto mainLib = TestLibrary::GetLibrary();
auto script = GetScript(mainLib, "throwScript"_cnc); auto script = GetScript(mainLib, "throwScript"_cnc);