Actual implementation of Angelscript hooks into battle library.
continuous-integration/drone/push Build is failing
Details
continuous-integration/drone/push Build is failing
Details
This commit is contained in:
parent
0455fec875
commit
bcc038b49d
|
@ -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/c3b573c7daa3f2815e063c9dabfaa5dbfe6dbb20@creaturelib/master")
|
self.requires("CreatureLib/cd7ddcf78ec0ee4ae645d1862f92ec23246af949@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:
|
||||||
|
|
|
@ -0,0 +1,360 @@
|
||||||
|
#include "scripthandle.h"
|
||||||
|
#include <new>
|
||||||
|
#include <assert.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
BEGIN_AS_NAMESPACE
|
||||||
|
|
||||||
|
static void Construct(CScriptHandle *self) { new(self) CScriptHandle(); }
|
||||||
|
static void Construct(CScriptHandle *self, const CScriptHandle &o) { new(self) CScriptHandle(o); }
|
||||||
|
// This one is not static because it needs to be friend with the CScriptHandle class
|
||||||
|
void Construct(CScriptHandle *self, void *ref, int typeId) { new(self) CScriptHandle(ref, typeId); }
|
||||||
|
static void Destruct(CScriptHandle *self) { self->~CScriptHandle(); }
|
||||||
|
|
||||||
|
CScriptHandle::CScriptHandle()
|
||||||
|
{
|
||||||
|
m_ref = 0;
|
||||||
|
m_type = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
CScriptHandle::CScriptHandle(const CScriptHandle &other)
|
||||||
|
{
|
||||||
|
m_ref = other.m_ref;
|
||||||
|
m_type = other.m_type;
|
||||||
|
|
||||||
|
AddRefHandle();
|
||||||
|
}
|
||||||
|
|
||||||
|
CScriptHandle::CScriptHandle(void *ref, asITypeInfo *type)
|
||||||
|
{
|
||||||
|
m_ref = ref;
|
||||||
|
m_type = type;
|
||||||
|
|
||||||
|
AddRefHandle();
|
||||||
|
}
|
||||||
|
|
||||||
|
// This constructor shouldn't be called from the application
|
||||||
|
// directly as it requires an active script context
|
||||||
|
CScriptHandle::CScriptHandle(void *ref, int typeId)
|
||||||
|
{
|
||||||
|
m_ref = 0;
|
||||||
|
m_type = 0;
|
||||||
|
|
||||||
|
Assign(ref, typeId);
|
||||||
|
}
|
||||||
|
|
||||||
|
CScriptHandle::~CScriptHandle()
|
||||||
|
{
|
||||||
|
ReleaseHandle();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CScriptHandle::ReleaseHandle()
|
||||||
|
{
|
||||||
|
if( m_ref && m_type )
|
||||||
|
{
|
||||||
|
asIScriptEngine *engine = m_type->GetEngine();
|
||||||
|
engine->ReleaseScriptObject(m_ref, m_type);
|
||||||
|
|
||||||
|
engine->Release();
|
||||||
|
|
||||||
|
m_ref = 0;
|
||||||
|
m_type = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CScriptHandle::AddRefHandle()
|
||||||
|
{
|
||||||
|
if( m_ref && m_type )
|
||||||
|
{
|
||||||
|
asIScriptEngine *engine = m_type->GetEngine();
|
||||||
|
engine->AddRefScriptObject(m_ref, m_type);
|
||||||
|
|
||||||
|
// Hold on to the engine so it isn't destroyed while
|
||||||
|
// a reference to a script object is still held
|
||||||
|
engine->AddRef();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CScriptHandle &CScriptHandle::operator =(const CScriptHandle &other)
|
||||||
|
{
|
||||||
|
Set(other.m_ref, other.m_type);
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CScriptHandle::Set(void *ref, asITypeInfo *type)
|
||||||
|
{
|
||||||
|
if( m_ref == ref ) return;
|
||||||
|
|
||||||
|
ReleaseHandle();
|
||||||
|
|
||||||
|
m_ref = ref;
|
||||||
|
m_type = type;
|
||||||
|
|
||||||
|
AddRefHandle();
|
||||||
|
}
|
||||||
|
|
||||||
|
void *CScriptHandle::GetRef()
|
||||||
|
{
|
||||||
|
return m_ref;
|
||||||
|
}
|
||||||
|
|
||||||
|
asITypeInfo *CScriptHandle::GetType() const
|
||||||
|
{
|
||||||
|
return m_type;
|
||||||
|
}
|
||||||
|
|
||||||
|
int CScriptHandle::GetTypeId() const
|
||||||
|
{
|
||||||
|
if( m_type == 0 ) return 0;
|
||||||
|
|
||||||
|
return m_type->GetTypeId() | asTYPEID_OBJHANDLE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// This method shouldn't be called from the application
|
||||||
|
// directly as it requires an active script context
|
||||||
|
CScriptHandle &CScriptHandle::Assign(void *ref, int typeId)
|
||||||
|
{
|
||||||
|
// When receiving a null handle we just clear our memory
|
||||||
|
if( typeId == 0 )
|
||||||
|
{
|
||||||
|
Set(0, 0);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Dereference received handles to get the object
|
||||||
|
if( typeId & asTYPEID_OBJHANDLE )
|
||||||
|
{
|
||||||
|
// Store the actual reference
|
||||||
|
ref = *(void**)ref;
|
||||||
|
typeId &= ~asTYPEID_OBJHANDLE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the object type
|
||||||
|
asIScriptContext *ctx = asGetActiveContext();
|
||||||
|
asIScriptEngine *engine = ctx->GetEngine();
|
||||||
|
asITypeInfo *type = engine->GetTypeInfoById(typeId);
|
||||||
|
|
||||||
|
// If the argument is another CScriptHandle, we should copy the content instead
|
||||||
|
if( type && strcmp(type->GetName(), "ref") == 0 )
|
||||||
|
{
|
||||||
|
CScriptHandle *r = (CScriptHandle*)ref;
|
||||||
|
ref = r->m_ref;
|
||||||
|
type = r->m_type;
|
||||||
|
}
|
||||||
|
|
||||||
|
Set(ref, type);
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CScriptHandle::operator==(const CScriptHandle &o) const
|
||||||
|
{
|
||||||
|
if( m_ref == o.m_ref &&
|
||||||
|
m_type == o.m_type )
|
||||||
|
return true;
|
||||||
|
|
||||||
|
// TODO: If type is not the same, we should attempt to do a dynamic cast,
|
||||||
|
// which may change the pointer for application registered classes
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CScriptHandle::operator!=(const CScriptHandle &o) const
|
||||||
|
{
|
||||||
|
return !(*this == o);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CScriptHandle::Equals(void *ref, int typeId) const
|
||||||
|
{
|
||||||
|
// Null handles are received as reference to a null handle
|
||||||
|
if( typeId == 0 )
|
||||||
|
ref = 0;
|
||||||
|
|
||||||
|
// Dereference handles to get the object
|
||||||
|
if( typeId & asTYPEID_OBJHANDLE )
|
||||||
|
{
|
||||||
|
// Compare the actual reference
|
||||||
|
ref = *(void**)ref;
|
||||||
|
typeId &= ~asTYPEID_OBJHANDLE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: If typeId is not the same, we should attempt to do a dynamic cast,
|
||||||
|
// which may change the pointer for application registered classes
|
||||||
|
|
||||||
|
if( ref == m_ref ) return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// AngelScript: used as '@obj = cast<obj>(ref);'
|
||||||
|
void CScriptHandle::Cast(void **outRef, int typeId)
|
||||||
|
{
|
||||||
|
// If we hold a null handle, then just return null
|
||||||
|
if( m_type == 0 )
|
||||||
|
{
|
||||||
|
*outRef = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// It is expected that the outRef is always a handle
|
||||||
|
assert( typeId & asTYPEID_OBJHANDLE );
|
||||||
|
|
||||||
|
// Compare the type id of the actual object
|
||||||
|
typeId &= ~asTYPEID_OBJHANDLE;
|
||||||
|
asIScriptEngine *engine = m_type->GetEngine();
|
||||||
|
asITypeInfo *type = engine->GetTypeInfoById(typeId);
|
||||||
|
|
||||||
|
*outRef = 0;
|
||||||
|
|
||||||
|
// RefCastObject will increment the refCount of the returned object if successful
|
||||||
|
engine->RefCastObject(m_ref, m_type, type, outRef);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CScriptHandle::EnumReferences(asIScriptEngine *inEngine)
|
||||||
|
{
|
||||||
|
// If we're holding a reference, we'll notify the garbage collector of it
|
||||||
|
if (m_ref)
|
||||||
|
inEngine->GCEnumCallback(m_ref);
|
||||||
|
|
||||||
|
// The object type itself is also garbage collected
|
||||||
|
if( m_type)
|
||||||
|
inEngine->GCEnumCallback(m_type);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CScriptHandle::ReleaseReferences(asIScriptEngine *inEngine)
|
||||||
|
{
|
||||||
|
// Simply clear the content to release the references
|
||||||
|
Set(0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void RegisterScriptHandle_Native(asIScriptEngine *engine)
|
||||||
|
{
|
||||||
|
int r;
|
||||||
|
|
||||||
|
#if AS_CAN_USE_CPP11
|
||||||
|
// With C++11 it is possible to use asGetTypeTraits to automatically determine the flags that represent the C++ class
|
||||||
|
r = engine->RegisterObjectType("ref", sizeof(CScriptHandle), asOBJ_VALUE | asOBJ_ASHANDLE | asOBJ_GC | asGetTypeTraits<CScriptHandle>()); assert( r >= 0 );
|
||||||
|
#else
|
||||||
|
r = engine->RegisterObjectType("ref", sizeof(CScriptHandle), asOBJ_VALUE | asOBJ_ASHANDLE | asOBJ_GC | asOBJ_APP_CLASS_CDAK); assert( r >= 0 );
|
||||||
|
#endif
|
||||||
|
r = engine->RegisterObjectBehaviour("ref", asBEHAVE_CONSTRUCT, "void f()", asFUNCTIONPR(Construct, (CScriptHandle *), void), asCALL_CDECL_OBJFIRST); assert( r >= 0 );
|
||||||
|
r = engine->RegisterObjectBehaviour("ref", asBEHAVE_CONSTRUCT, "void f(const ref &in)", asFUNCTIONPR(Construct, (CScriptHandle *, const CScriptHandle &), void), asCALL_CDECL_OBJFIRST); assert( r >= 0 );
|
||||||
|
r = engine->RegisterObjectBehaviour("ref", asBEHAVE_CONSTRUCT, "void f(const ?&in)", asFUNCTIONPR(Construct, (CScriptHandle *, void *, int), void), asCALL_CDECL_OBJFIRST); assert( r >= 0 );
|
||||||
|
r = engine->RegisterObjectBehaviour("ref", asBEHAVE_DESTRUCT, "void f()", asFUNCTIONPR(Destruct, (CScriptHandle *), void), asCALL_CDECL_OBJFIRST); assert( r >= 0 );
|
||||||
|
r = engine->RegisterObjectBehaviour("ref", asBEHAVE_ENUMREFS, "void f(int&in)", asMETHOD(CScriptHandle,EnumReferences), asCALL_THISCALL); assert(r >= 0);
|
||||||
|
r = engine->RegisterObjectBehaviour("ref", asBEHAVE_RELEASEREFS, "void f(int&in)", asMETHOD(CScriptHandle, ReleaseReferences), asCALL_THISCALL); assert(r >= 0);
|
||||||
|
r = engine->RegisterObjectMethod("ref", "void opCast(?&out)", asMETHODPR(CScriptHandle, Cast, (void **, int), void), asCALL_THISCALL); assert( r >= 0 );
|
||||||
|
r = engine->RegisterObjectMethod("ref", "ref &opHndlAssign(const ref &in)", asMETHOD(CScriptHandle, operator=), asCALL_THISCALL); assert( r >= 0 );
|
||||||
|
r = engine->RegisterObjectMethod("ref", "ref &opHndlAssign(const ?&in)", asMETHOD(CScriptHandle, Assign), asCALL_THISCALL); assert( r >= 0 );
|
||||||
|
r = engine->RegisterObjectMethod("ref", "bool opEquals(const ref &in) const", asMETHODPR(CScriptHandle, operator==, (const CScriptHandle &) const, bool), asCALL_THISCALL); assert( r >= 0 );
|
||||||
|
r = engine->RegisterObjectMethod("ref", "bool opEquals(const ?&in) const", asMETHODPR(CScriptHandle, Equals, (void*, int) const, bool), asCALL_THISCALL); assert( r >= 0 );
|
||||||
|
}
|
||||||
|
|
||||||
|
void CScriptHandle_Construct_Generic(asIScriptGeneric *gen)
|
||||||
|
{
|
||||||
|
CScriptHandle *self = reinterpret_cast<CScriptHandle*>(gen->GetObject());
|
||||||
|
new(self) CScriptHandle();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CScriptHandle_ConstructCopy_Generic(asIScriptGeneric *gen)
|
||||||
|
{
|
||||||
|
CScriptHandle *other = reinterpret_cast<CScriptHandle*>(gen->GetArgAddress(0));
|
||||||
|
CScriptHandle *self = reinterpret_cast<CScriptHandle*>(gen->GetObject());
|
||||||
|
new(self) CScriptHandle(*other);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CScriptHandle_ConstructVar_Generic(asIScriptGeneric *gen)
|
||||||
|
{
|
||||||
|
void *ref = gen->GetArgAddress(0);
|
||||||
|
int typeId = gen->GetArgTypeId(0);
|
||||||
|
CScriptHandle *self = reinterpret_cast<CScriptHandle*>(gen->GetObject());
|
||||||
|
Construct(self, ref, typeId);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CScriptHandle_Destruct_Generic(asIScriptGeneric *gen)
|
||||||
|
{
|
||||||
|
CScriptHandle *self = reinterpret_cast<CScriptHandle*>(gen->GetObject());
|
||||||
|
self->~CScriptHandle();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CScriptHandle_Cast_Generic(asIScriptGeneric *gen)
|
||||||
|
{
|
||||||
|
void **ref = reinterpret_cast<void**>(gen->GetArgAddress(0));
|
||||||
|
int typeId = gen->GetArgTypeId(0);
|
||||||
|
CScriptHandle *self = reinterpret_cast<CScriptHandle*>(gen->GetObject());
|
||||||
|
self->Cast(ref, typeId);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CScriptHandle_Assign_Generic(asIScriptGeneric *gen)
|
||||||
|
{
|
||||||
|
CScriptHandle *other = reinterpret_cast<CScriptHandle*>(gen->GetArgAddress(0));
|
||||||
|
CScriptHandle *self = reinterpret_cast<CScriptHandle*>(gen->GetObject());
|
||||||
|
*self = *other;
|
||||||
|
gen->SetReturnAddress(self);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CScriptHandle_AssignVar_Generic(asIScriptGeneric *gen)
|
||||||
|
{
|
||||||
|
void *ref = gen->GetArgAddress(0);
|
||||||
|
int typeId = gen->GetArgTypeId(0);
|
||||||
|
CScriptHandle *self = reinterpret_cast<CScriptHandle*>(gen->GetObject());
|
||||||
|
self->Assign(ref, typeId);
|
||||||
|
gen->SetReturnAddress(self);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CScriptHandle_Equals_Generic(asIScriptGeneric *gen)
|
||||||
|
{
|
||||||
|
CScriptHandle *other = reinterpret_cast<CScriptHandle*>(gen->GetArgAddress(0));
|
||||||
|
CScriptHandle *self = reinterpret_cast<CScriptHandle*>(gen->GetObject());
|
||||||
|
gen->SetReturnByte(*self == *other);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CScriptHandle_EqualsVar_Generic(asIScriptGeneric *gen)
|
||||||
|
{
|
||||||
|
void *ref = gen->GetArgAddress(0);
|
||||||
|
int typeId = gen->GetArgTypeId(0);
|
||||||
|
CScriptHandle *self = reinterpret_cast<CScriptHandle*>(gen->GetObject());
|
||||||
|
gen->SetReturnByte(self->Equals(ref, typeId));
|
||||||
|
}
|
||||||
|
|
||||||
|
void CScriptHandle_EnumReferences_Generic(asIScriptGeneric *gen)
|
||||||
|
{
|
||||||
|
CScriptHandle *self = reinterpret_cast<CScriptHandle*>(gen->GetObject());
|
||||||
|
self->EnumReferences(gen->GetEngine());
|
||||||
|
}
|
||||||
|
|
||||||
|
void CScriptHandle_ReleaseReferences_Generic(asIScriptGeneric *gen)
|
||||||
|
{
|
||||||
|
CScriptHandle *self = reinterpret_cast<CScriptHandle*>(gen->GetObject());
|
||||||
|
self->ReleaseReferences(gen->GetEngine());
|
||||||
|
}
|
||||||
|
|
||||||
|
void RegisterScriptHandle_Generic(asIScriptEngine *engine)
|
||||||
|
{
|
||||||
|
int r;
|
||||||
|
|
||||||
|
r = engine->RegisterObjectType("ref", sizeof(CScriptHandle), asOBJ_VALUE | asOBJ_ASHANDLE | asOBJ_GC | asOBJ_APP_CLASS_CDAK); assert( r >= 0 );
|
||||||
|
r = engine->RegisterObjectBehaviour("ref", asBEHAVE_CONSTRUCT, "void f()", asFUNCTION(CScriptHandle_Construct_Generic), asCALL_GENERIC); assert( r >= 0 );
|
||||||
|
r = engine->RegisterObjectBehaviour("ref", asBEHAVE_CONSTRUCT, "void f(const ref &in)", asFUNCTION(CScriptHandle_ConstructCopy_Generic), asCALL_GENERIC); assert( r >= 0 );
|
||||||
|
r = engine->RegisterObjectBehaviour("ref", asBEHAVE_CONSTRUCT, "void f(const ?&in)", asFUNCTION(CScriptHandle_ConstructVar_Generic), asCALL_GENERIC); assert( r >= 0 );
|
||||||
|
r = engine->RegisterObjectBehaviour("ref", asBEHAVE_DESTRUCT, "void f()", asFUNCTION(CScriptHandle_Destruct_Generic), asCALL_GENERIC); assert( r >= 0 );
|
||||||
|
r = engine->RegisterObjectBehaviour("ref", asBEHAVE_ENUMREFS, "void f(int&in)", asFUNCTION(CScriptHandle_EnumReferences_Generic), asCALL_GENERIC); assert(r >= 0);
|
||||||
|
r = engine->RegisterObjectBehaviour("ref", asBEHAVE_RELEASEREFS, "void f(int&in)", asFUNCTION(CScriptHandle_ReleaseReferences_Generic), asCALL_GENERIC); assert(r >= 0);
|
||||||
|
r = engine->RegisterObjectMethod("ref", "void opCast(?&out)", asFUNCTION(CScriptHandle_Cast_Generic), asCALL_GENERIC); assert( r >= 0 );
|
||||||
|
r = engine->RegisterObjectMethod("ref", "ref &opHndlAssign(const ref &in)", asFUNCTION(CScriptHandle_Assign_Generic), asCALL_GENERIC); assert( r >= 0 );
|
||||||
|
r = engine->RegisterObjectMethod("ref", "ref &opHndlAssign(const ?&in)", asFUNCTION(CScriptHandle_AssignVar_Generic), asCALL_GENERIC); assert( r >= 0 );
|
||||||
|
r = engine->RegisterObjectMethod("ref", "bool opEquals(const ref &in) const", asFUNCTION(CScriptHandle_Equals_Generic), asCALL_GENERIC); assert( r >= 0 );
|
||||||
|
r = engine->RegisterObjectMethod("ref", "bool opEquals(const ?&in) const", asFUNCTION(CScriptHandle_EqualsVar_Generic), asCALL_GENERIC); assert( r >= 0 );
|
||||||
|
}
|
||||||
|
|
||||||
|
void RegisterScriptHandle(asIScriptEngine *engine)
|
||||||
|
{
|
||||||
|
if( strstr(asGetLibraryOptions(), "AS_MAX_PORTABILITY") )
|
||||||
|
RegisterScriptHandle_Generic(engine);
|
||||||
|
else
|
||||||
|
RegisterScriptHandle_Native(engine);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
END_AS_NAMESPACE
|
|
@ -0,0 +1,69 @@
|
||||||
|
#ifndef SCRIPTHANDLE_H
|
||||||
|
#define SCRIPTHANDLE_H
|
||||||
|
|
||||||
|
#ifndef ANGELSCRIPT_H
|
||||||
|
// Avoid having to inform include path if header is already include before
|
||||||
|
#include <angelscript.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
BEGIN_AS_NAMESPACE
|
||||||
|
|
||||||
|
class CScriptHandle
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
// Constructors
|
||||||
|
CScriptHandle();
|
||||||
|
CScriptHandle(const CScriptHandle &other);
|
||||||
|
CScriptHandle(void *ref, asITypeInfo *type);
|
||||||
|
~CScriptHandle();
|
||||||
|
|
||||||
|
// Copy the stored value from another any object
|
||||||
|
CScriptHandle &operator=(const CScriptHandle &other);
|
||||||
|
|
||||||
|
// Set the reference
|
||||||
|
void Set(void *ref, asITypeInfo *type);
|
||||||
|
|
||||||
|
// Compare equalness
|
||||||
|
bool operator==(const CScriptHandle &o) const;
|
||||||
|
bool operator!=(const CScriptHandle &o) const;
|
||||||
|
bool Equals(void *ref, int typeId) const;
|
||||||
|
|
||||||
|
// Dynamic cast to desired handle type
|
||||||
|
void Cast(void **outRef, int typeId);
|
||||||
|
|
||||||
|
// Returns the type of the reference held
|
||||||
|
asITypeInfo *GetType() const;
|
||||||
|
int GetTypeId() const;
|
||||||
|
|
||||||
|
// Get the reference
|
||||||
|
void *GetRef();
|
||||||
|
|
||||||
|
// GC callback
|
||||||
|
void EnumReferences(asIScriptEngine *engine);
|
||||||
|
void ReleaseReferences(asIScriptEngine *engine);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
// These functions need to have access to protected
|
||||||
|
// members in order to call them from the script engine
|
||||||
|
friend void Construct(CScriptHandle *self, void *ref, int typeId);
|
||||||
|
friend void RegisterScriptHandle_Native(asIScriptEngine *engine);
|
||||||
|
friend void CScriptHandle_AssignVar_Generic(asIScriptGeneric *gen);
|
||||||
|
|
||||||
|
void ReleaseHandle();
|
||||||
|
void AddRefHandle();
|
||||||
|
|
||||||
|
// These shouldn't be called directly by the
|
||||||
|
// application as they requires an active context
|
||||||
|
CScriptHandle(void *ref, int typeId);
|
||||||
|
CScriptHandle &Assign(void *ref, int typeId);
|
||||||
|
|
||||||
|
void *m_ref;
|
||||||
|
asITypeInfo *m_type;
|
||||||
|
};
|
||||||
|
|
||||||
|
void RegisterScriptHandle(asIScriptEngine *engine);
|
||||||
|
|
||||||
|
END_AS_NAMESPACE
|
||||||
|
|
||||||
|
#endif
|
|
@ -2,8 +2,11 @@
|
||||||
#define AS_USE_ACCESSORS
|
#define AS_USE_ACCESSORS
|
||||||
#include "../../../extern/angelscript_addons/scriptarray/scriptarray.h"
|
#include "../../../extern/angelscript_addons/scriptarray/scriptarray.h"
|
||||||
#undef AS_USE_ACCESSORS
|
#undef AS_USE_ACCESSORS
|
||||||
|
#include <cassert>
|
||||||
|
#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 "TypeRegistry/BasicScriptClass.hpp"
|
||||||
#include "TypeRegistry/Battling/RegisterExecutingAttack.hpp"
|
#include "TypeRegistry/Battling/RegisterExecutingAttack.hpp"
|
||||||
#include "TypeRegistry/Battling/RegisterPokemonClass.hpp"
|
#include "TypeRegistry/Battling/RegisterPokemonClass.hpp"
|
||||||
#include "TypeRegistry/Library/RegisterGrowthRateTypes.hpp"
|
#include "TypeRegistry/Library/RegisterGrowthRateTypes.hpp"
|
||||||
|
@ -17,7 +20,8 @@ CreatureLib::Battling::ScriptResolver* PkmnLib::Battling::BattleLibrary::CreateS
|
||||||
return new AngelScripResolver();
|
return new AngelScripResolver();
|
||||||
}
|
}
|
||||||
|
|
||||||
void AngelScripResolver::Initialize(CreatureLib::Battling::BattleLibrary* library) {
|
void AngelScripResolver::Initialize(CreatureLib::Battling::BattleLibrary* arg) {
|
||||||
|
auto library = (PkmnLib::Battling::BattleLibrary*)arg;
|
||||||
_engine = asCreateScriptEngine();
|
_engine = asCreateScriptEngine();
|
||||||
|
|
||||||
int32_t r = _engine->SetMessageCallback(asFUNCTION(MessageCallback), nullptr, asCALL_CDECL);
|
int32_t r = _engine->SetMessageCallback(asFUNCTION(MessageCallback), nullptr, asCALL_CDECL);
|
||||||
|
@ -25,10 +29,13 @@ void AngelScripResolver::Initialize(CreatureLib::Battling::BattleLibrary* librar
|
||||||
throw CreatureException("Registering message callback failed.");
|
throw CreatureException("Registering message callback failed.");
|
||||||
|
|
||||||
_engine->SetEngineProperty(asEP_DISALLOW_EMPTY_LIST_ELEMENTS, true);
|
_engine->SetEngineProperty(asEP_DISALLOW_EMPTY_LIST_ELEMENTS, true);
|
||||||
_engine->SetEngineProperty(asEP_DISALLOW_VALUE_ASSIGN_FOR_REF_TYPE, true);
|
_engine->SetEngineProperty(asEP_DISALLOW_VALUE_ASSIGN_FOR_REF_TYPE, false);
|
||||||
|
_engine->SetEngineProperty(asEP_ALLOW_UNSAFE_REFERENCES, true);
|
||||||
_engine->SetEngineProperty(asEP_ALWAYS_IMPL_DEFAULT_CONSTRUCT, true);
|
_engine->SetEngineProperty(asEP_ALWAYS_IMPL_DEFAULT_CONSTRUCT, true);
|
||||||
_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);
|
||||||
|
|
||||||
|
|
||||||
RegisterStdString(_engine);
|
RegisterStdString(_engine);
|
||||||
|
|
||||||
|
@ -38,11 +45,15 @@ void AngelScripResolver::Initialize(CreatureLib::Battling::BattleLibrary* librar
|
||||||
r = _engine->RegisterGlobalFunction("void print(const string &in)", asFUNCTION(Print), asCALL_CDECL);
|
r = _engine->RegisterGlobalFunction("void print(const string &in)", asFUNCTION(Print), asCALL_CDECL);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
throw CreatureException("Registering print function failed.");
|
throw CreatureException("Registering print function failed.");
|
||||||
|
RegisterScriptHandle(_engine);
|
||||||
|
|
||||||
|
_mainModule = _engine->GetModule("pkmn", asGM_ALWAYS_CREATE);
|
||||||
|
|
||||||
RegisterTypes();
|
RegisterTypes();
|
||||||
RegisterExceptionRoutines(_engine);
|
RegisterExceptionRoutines(_engine);
|
||||||
|
|
||||||
_mainModule = _engine->GetModule("pkmn", asGM_ALWAYS_CREATE);
|
auto staticLib = library->GetStaticLib();
|
||||||
|
_engine->RegisterGlobalProperty("const StaticLibrary@ StaticLib", &staticLib);
|
||||||
|
|
||||||
_contextPool = new ContextPool(_engine);
|
_contextPool = new ContextPool(_engine);
|
||||||
}
|
}
|
||||||
|
@ -59,6 +70,9 @@ void AngelScripResolver::RegisterTypes() {
|
||||||
// Register battle types
|
// Register battle types
|
||||||
RegisterPokemonClass::Register(_engine);
|
RegisterPokemonClass::Register(_engine);
|
||||||
RegisterExecutingAttack::Register(_engine);
|
RegisterExecutingAttack::Register(_engine);
|
||||||
|
|
||||||
|
// Register base script
|
||||||
|
BasicScriptClass::Register(_engine);
|
||||||
}
|
}
|
||||||
|
|
||||||
AngelScriptTypeInfo* AngelScripResolver::GetTypeInfo(const std::string& name) {
|
AngelScriptTypeInfo* AngelScripResolver::GetTypeInfo(const std::string& name) {
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
#include <Battling/ScriptHandling/Script.hpp>
|
#include <Battling/ScriptHandling/Script.hpp>
|
||||||
#define ANGELSCRIPT_DLL_LIBRARY_IMPORT
|
#define ANGELSCRIPT_DLL_LIBRARY_IMPORT
|
||||||
#include <angelscript.h>
|
#include <angelscript.h>
|
||||||
|
#include <Core/Exceptions/NotImplementedException.hpp>
|
||||||
#include "AngelScriptTypeInfo.hpp"
|
#include "AngelScriptTypeInfo.hpp"
|
||||||
#include "ContextPool.hpp"
|
#include "ContextPool.hpp"
|
||||||
|
|
||||||
|
@ -19,25 +20,6 @@ public:
|
||||||
|
|
||||||
~AngelScriptScript() override { _obj->Release(); }
|
~AngelScriptScript() override { _obj->Release(); }
|
||||||
|
|
||||||
void InvokeMethod(const char* name) {
|
|
||||||
auto func = _type->GetFunction(name);
|
|
||||||
if (func == nullptr)
|
|
||||||
return;
|
|
||||||
auto ctx = _ctxPool->RequestContext();
|
|
||||||
ctx->Prepare(func);
|
|
||||||
ctx->SetObject(_obj);
|
|
||||||
auto result = ctx->Execute();
|
|
||||||
if (result != asEXECUTION_FINISHED) {
|
|
||||||
if (result == asEXECUTION_EXCEPTION) {
|
|
||||||
throw CreatureException(ctx->GetExceptionString());
|
|
||||||
}
|
|
||||||
throw CreatureException("Function failed.");
|
|
||||||
}
|
|
||||||
_ctxPool->ReturnContextToPool(ctx);
|
|
||||||
}
|
|
||||||
|
|
||||||
asIScriptObject* GetScriptObject() { return _obj; }
|
|
||||||
|
|
||||||
asIScriptFunction* PrepareMethod(const char* name, asIScriptContext* ctx) {
|
asIScriptFunction* PrepareMethod(const char* name, asIScriptContext* ctx) {
|
||||||
auto func = _type->GetFunction(name);
|
auto func = _type->GetFunction(name);
|
||||||
ctx->Prepare(func);
|
ctx->Prepare(func);
|
||||||
|
@ -46,6 +28,89 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
ContextPool* GetContextPool() { return _ctxPool; }
|
ContextPool* GetContextPool() { return _ctxPool; }
|
||||||
|
|
||||||
|
#define CALLHOOK(name, setup) \
|
||||||
|
auto s = _type->Get##name(); \
|
||||||
|
if (!s.Exists) \
|
||||||
|
return; \
|
||||||
|
auto ctx = _ctxPool->RequestContext(); \
|
||||||
|
ctx->Prepare(s.Function); \
|
||||||
|
ctx->SetObject(_obj); \
|
||||||
|
setup; \
|
||||||
|
auto scriptResult = ctx->Execute(); \
|
||||||
|
if (scriptResult != 0) { \
|
||||||
|
throw CreatureException("Script didn't finish properly; message " + std::to_string(scriptResult)); \
|
||||||
|
} \
|
||||||
|
_ctxPool->ReturnContextToPool(ctx);
|
||||||
|
|
||||||
|
void Stack() override { CALLHOOK(Stack, {}); }
|
||||||
|
|
||||||
|
void OnBeforeTurn(const CreatureLib::Battling::BaseTurnChoice* choice) override {
|
||||||
|
throw NotImplementedException(); //TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
void ChangeAttack(CreatureLib::Battling::AttackTurnChoice* choice, std::string* outAttack) override {
|
||||||
|
throw NotImplementedException(); //TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
void PreventAttack(CreatureLib::Battling::ExecutingAttack* attack, bool* outResult) override {
|
||||||
|
CALLHOOK(PreventAttack, {
|
||||||
|
ctx->SetArgObject(0, (void*)attack);
|
||||||
|
ctx->SetArgAddress(1, outResult);
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
void FailAttack(CreatureLib::Battling::ExecutingAttack* attack, bool* outFailed) override {
|
||||||
|
CALLHOOK(FailAttack, {
|
||||||
|
ctx->SetArgObject(0, (void*)attack);
|
||||||
|
ctx->SetArgAddress(1, outFailed);
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
void StopBeforeAttack(CreatureLib::Battling::ExecutingAttack* attack, bool* outResult) override {
|
||||||
|
CALLHOOK(StopBeforeAttack, {
|
||||||
|
ctx->SetArgObject(0, (void*)attack);
|
||||||
|
ctx->SetArgAddress(1, outResult);
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
void OnBeforeAttack(CreatureLib::Battling::ExecutingAttack* attack) override { Script::OnBeforeAttack(attack); }
|
||||||
|
void FailIncomingAttack(CreatureLib::Battling::ExecutingAttack* attack, CreatureLib::Battling::Creature* target,
|
||||||
|
bool* outResult) override {
|
||||||
|
Script::FailIncomingAttack(attack, target, outResult);
|
||||||
|
}
|
||||||
|
void IsInvulnerable(CreatureLib::Battling::ExecutingAttack* attack, CreatureLib::Battling::Creature* target,
|
||||||
|
bool* outResult) override {
|
||||||
|
Script::IsInvulnerable(attack, target, outResult);
|
||||||
|
}
|
||||||
|
void OnAttackMiss(CreatureLib::Battling::ExecutingAttack* attack,
|
||||||
|
CreatureLib::Battling::Creature* target) override {
|
||||||
|
Script::OnAttackMiss(attack, target);
|
||||||
|
}
|
||||||
|
void ChangeAttackType(CreatureLib::Battling::ExecutingAttack* attack, CreatureLib::Battling::Creature* target,
|
||||||
|
uint8_t hitNumber, uint8_t* outType) override {
|
||||||
|
Script::ChangeAttackType(attack, target, hitNumber, outType);
|
||||||
|
}
|
||||||
|
void OnStatusMove(const CreatureLib::Battling::ExecutingAttack* attack, CreatureLib::Battling::Creature* target,
|
||||||
|
uint8_t hitNumber) override {
|
||||||
|
Script::OnStatusMove(attack, target, hitNumber);
|
||||||
|
}
|
||||||
|
void PreventSecondaryEffects(const CreatureLib::Battling::ExecutingAttack* attack,
|
||||||
|
CreatureLib::Battling::Creature* target, uint8_t hitNumber, bool* outResult) override {
|
||||||
|
Script::PreventSecondaryEffects(attack, target, hitNumber, outResult);
|
||||||
|
}
|
||||||
|
void OnSecondaryEffect(const CreatureLib::Battling::ExecutingAttack* attack,
|
||||||
|
CreatureLib::Battling::Creature* target, uint8_t hitNumber) override {
|
||||||
|
Script::OnSecondaryEffect(attack, target, hitNumber);
|
||||||
|
}
|
||||||
|
void OnAfterHits(const CreatureLib::Battling::ExecutingAttack* attack,
|
||||||
|
CreatureLib::Battling::Creature* target) override {
|
||||||
|
Script::OnAfterHits(attack, target);
|
||||||
|
}
|
||||||
|
void PreventSelfSwitch(const CreatureLib::Battling::SwitchTurnChoice* choice, bool* outResult) override {
|
||||||
|
Script::PreventSelfSwitch(choice, outResult);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#undef CALLHOOK
|
||||||
#endif // PKMNLIB_ANGELSCRIPTSCRIPT_HPP
|
#endif // PKMNLIB_ANGELSCRIPTSCRIPT_HPP
|
||||||
|
|
|
@ -2,42 +2,59 @@
|
||||||
#define PKMNLIB_ANGELSCRIPTTYPEINFO_HPP
|
#define PKMNLIB_ANGELSCRIPTTYPEINFO_HPP
|
||||||
|
|
||||||
#define ANGELSCRIPT_DLL_LIBRARY_IMPORT
|
#define ANGELSCRIPT_DLL_LIBRARY_IMPORT
|
||||||
#include <angelscript.h>
|
|
||||||
#include <unordered_map>
|
|
||||||
#include <Core/Exceptions/CreatureException.hpp>
|
#include <Core/Exceptions/CreatureException.hpp>
|
||||||
|
#include <angelscript.h>
|
||||||
|
#include <cstring>
|
||||||
|
#include <unordered_map>
|
||||||
|
|
||||||
class AngelScriptTypeInfo {
|
class AngelScriptTypeInfo {
|
||||||
private:
|
private:
|
||||||
asITypeInfo* _type = nullptr;
|
asITypeInfo* _type = nullptr;
|
||||||
std::unordered_map<std::string, asIScriptFunction*> _functions;
|
std::unordered_map<std::string, asIScriptFunction*> _functions;
|
||||||
|
|
||||||
|
struct FunctionInfo {
|
||||||
|
bool Exists = false;
|
||||||
|
asIScriptFunction* Function = nullptr;
|
||||||
|
};
|
||||||
|
|
||||||
|
FunctionInfo Initialize(const std::string& decl) {
|
||||||
|
auto val = _type->GetMethodByDecl(decl.c_str(), false);
|
||||||
|
if (val == nullptr){
|
||||||
|
return FunctionInfo{.Exists = false, .Function = nullptr};
|
||||||
|
}
|
||||||
|
if (!val->IsOverride()){
|
||||||
|
return FunctionInfo{.Exists = false, .Function = nullptr};
|
||||||
|
}
|
||||||
|
return FunctionInfo{.Exists = true, .Function = val};
|
||||||
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit AngelScriptTypeInfo(asITypeInfo* type) : _type(type){}
|
explicit AngelScriptTypeInfo(asITypeInfo* type) : _type(type) {}
|
||||||
~AngelScriptTypeInfo(){
|
~AngelScriptTypeInfo() {
|
||||||
for (const auto& f: _functions){
|
for (const auto& f : _functions) {
|
||||||
f.second->Release();
|
f.second->Release();
|
||||||
}
|
}
|
||||||
_functions.clear();
|
_functions.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
asIScriptFunction* GetFunction(const std::string& functionName){
|
asIScriptFunction* GetFunction(const std::string& functionName) {
|
||||||
auto find = _functions.find(functionName);
|
auto find = _functions.find(functionName);
|
||||||
if (find != _functions.end()){
|
if (find != _functions.end()) {
|
||||||
return find->second;
|
return find->second;
|
||||||
}
|
}
|
||||||
auto func = _type->GetMethodByName(functionName.c_str());
|
auto func = _type->GetMethodByName(functionName.c_str());
|
||||||
if (func != nullptr){
|
if (func != nullptr) {
|
||||||
func->AddRef();
|
func->AddRef();
|
||||||
}
|
}
|
||||||
_functions.insert({functionName, func});
|
_functions.insert({functionName, func});
|
||||||
return func;
|
return func;
|
||||||
}
|
}
|
||||||
|
|
||||||
asIScriptObject* Instantiate(asIScriptContext* ctx){
|
asIScriptObject* Instantiate(asIScriptContext* ctx) {
|
||||||
auto factory = _type->GetFactoryByIndex(0);
|
auto factory = _type->GetFactoryByIndex(0);
|
||||||
ctx->Prepare(factory);
|
ctx->Prepare(factory);
|
||||||
auto result = ctx->Execute();
|
auto result = ctx->Execute();
|
||||||
if (result != asEXECUTION_FINISHED){
|
if (result != asEXECUTION_FINISHED) {
|
||||||
throw CreatureException("Instantiation failed.");
|
throw CreatureException("Instantiation failed.");
|
||||||
}
|
}
|
||||||
asIScriptObject* obj = *(asIScriptObject**)ctx->GetAddressOfReturnValue();
|
asIScriptObject* obj = *(asIScriptObject**)ctx->GetAddressOfReturnValue();
|
||||||
|
@ -45,6 +62,16 @@ public:
|
||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define SCRIPT_HOOK_FUNCTION(name, decl) \
|
||||||
|
private: FunctionInfo __##name = Initialize(decl); \
|
||||||
|
public: const FunctionInfo& Get##name() const { return __##name; }
|
||||||
|
|
||||||
|
SCRIPT_HOOK_FUNCTION(Stack, "void Stack()");
|
||||||
|
SCRIPT_HOOK_FUNCTION(PreventAttack, "void PreventAttack(ExecutingMove@ attack, bool& result)");
|
||||||
|
SCRIPT_HOOK_FUNCTION(FailAttack, "void FailAttack(ExecutingMove@ attack, bool& result)");
|
||||||
|
SCRIPT_HOOK_FUNCTION(StopBeforeAttack, "void StopBeforeAttack(ExecutingMove@ attack, bool& result)");
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#undef SCRIPT_HOOK_FUNCTION
|
||||||
#endif // PKMNLIB_ANGELSCRIPTTYPEINFO_HPP
|
#endif // PKMNLIB_ANGELSCRIPTTYPEINFO_HPP
|
||||||
|
|
|
@ -0,0 +1,15 @@
|
||||||
|
#include "BasicScriptClass.hpp"
|
||||||
|
#include <cassert>
|
||||||
|
|
||||||
|
void BasicScriptClass::Register(asIScriptEngine* engine) {
|
||||||
|
[[maybe_unused]] int r = engine->GetModuleByIndex(0)->AddScriptSection("PkmnScript", R"(
|
||||||
|
shared abstract class PkmnScript {
|
||||||
|
void Stack(){};
|
||||||
|
void PreventAttack(ExecutingMove@ attack, bool& result){};
|
||||||
|
void FailAttack(ExecutingMove@ attack, bool& result){};
|
||||||
|
void StopBeforeAttack(ExecutingMove@ attack, bool& result){};
|
||||||
|
}
|
||||||
|
)");
|
||||||
|
assert(r >= 0);
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,10 @@
|
||||||
|
#ifndef PKMNLIB_BASICSCRIPTCLASS_HPP
|
||||||
|
#define PKMNLIB_BASICSCRIPTCLASS_HPP
|
||||||
|
|
||||||
|
#include <angelscript.h>
|
||||||
|
class BasicScriptClass {
|
||||||
|
public:
|
||||||
|
static void Register(asIScriptEngine* engine);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // PKMNLIB_BASICSCRIPTCLASS_HPP
|
|
@ -10,10 +10,13 @@ void RegisterStaticLibraryTypes::Register(asIScriptEngine* engine) {
|
||||||
void RegisterStaticLibraryTypes::RegisterLibrarySettingsType(asIScriptEngine* engine) {
|
void RegisterStaticLibraryTypes::RegisterLibrarySettingsType(asIScriptEngine* engine) {
|
||||||
[[maybe_unused]] int r = engine->RegisterObjectType("LibrarySettings", 0, asOBJ_REF | asOBJ_NOCOUNT);
|
[[maybe_unused]] int r = engine->RegisterObjectType("LibrarySettings", 0, asOBJ_REF | asOBJ_NOCOUNT);
|
||||||
r = engine->RegisterObjectMethod("LibrarySettings", "uint8 get_MaximalLevel() const property",
|
r = engine->RegisterObjectMethod("LibrarySettings", "uint8 get_MaximalLevel() const property",
|
||||||
asMETHOD(CreatureLib::Library::LibrarySettings, GetMaximalLevel), asCALL_THISCALL);
|
asMETHOD(PkmnLib::Library::LibrarySettings, GetMaximalLevel), asCALL_THISCALL);
|
||||||
assert(r >= 0);
|
assert(r >= 0);
|
||||||
r = engine->RegisterObjectMethod("LibrarySettings", "uint8 get_MaximalMoves() const property",
|
r = engine->RegisterObjectMethod("LibrarySettings", "uint8 get_MaximalMoves() const property",
|
||||||
asMETHOD(CreatureLib::Library::LibrarySettings, GetMaximalMoves), asCALL_THISCALL);
|
asMETHOD(PkmnLib::Library::LibrarySettings, GetMaximalMoves), asCALL_THISCALL);
|
||||||
|
assert(r >= 0);
|
||||||
|
r = engine->RegisterObjectMethod("LibrarySettings", "uint16 get_ShinyRate() const property",
|
||||||
|
asMETHOD(PkmnLib::Library::LibrarySettings, GetShinyRate), asCALL_THISCALL);
|
||||||
assert(r >= 0);
|
assert(r >= 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,119 @@
|
||||||
|
#ifdef TESTS_BUILD
|
||||||
|
#include "../../extern/catch.hpp"
|
||||||
|
#include "../../src/Battling/Pokemon/CreatePokemon.hpp"
|
||||||
|
#include "../../src/ScriptResolving/AngelScript/AngelScripResolver.hpp"
|
||||||
|
#include "../TestLibrary/TestLibrary.hpp"
|
||||||
|
|
||||||
|
#define AS_CLASS(name, contents) { #name, "class " #name " : PkmnScript { " contents "}" }
|
||||||
|
|
||||||
|
static std::unordered_map<const char*, const char*> _scripts = std::unordered_map<const char*, const char*> {
|
||||||
|
AS_CLASS(blankScript, ),
|
||||||
|
AS_CLASS( stackScript, "int value = 0; void Stack() override { value++; } int GetValue() { return value; }"),
|
||||||
|
{"doubleInheritanceScript", R"(
|
||||||
|
class doubleInheritanceScriptBase : PkmnScript {
|
||||||
|
int value = 0;
|
||||||
|
void Stack() override{
|
||||||
|
value++;
|
||||||
|
}
|
||||||
|
|
||||||
|
int GetValue(){ return value; }
|
||||||
|
}
|
||||||
|
class doubleInheritanceScript : doubleInheritanceScriptBase {}
|
||||||
|
)"},
|
||||||
|
AS_CLASS( preventAttackScript, R"(
|
||||||
|
void PreventAttack(ExecutingMove@ attack, bool& result) override{
|
||||||
|
result = !result;
|
||||||
|
})"),
|
||||||
|
AS_CLASS( stopBeforeAttackScript, R"(
|
||||||
|
void StopBeforeAttack(ExecutingMove@ attack, bool& result) override{
|
||||||
|
result = !result;
|
||||||
|
})"),
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
static const char* _testLoadFunc(const char* name) { return _scripts[name]; }
|
||||||
|
|
||||||
|
static AngelScripResolver* _resolverCache = nullptr;
|
||||||
|
static AngelScripResolver* GetScriptResolver(PkmnLib::Battling::BattleLibrary* mainLib) {
|
||||||
|
if (_resolverCache == nullptr) {
|
||||||
|
_resolverCache = dynamic_cast<AngelScripResolver*>(PkmnLib::Battling::BattleLibrary::CreateScriptResolver());
|
||||||
|
_resolverCache->Initialize(mainLib);
|
||||||
|
_resolverCache->SetCreateFunction(&_testLoadFunc);
|
||||||
|
for (auto kv : _scripts) {
|
||||||
|
_resolverCache->CreateScript(kv.first);
|
||||||
|
}
|
||||||
|
_resolverCache->FinalizeModule();
|
||||||
|
}
|
||||||
|
return _resolverCache;
|
||||||
|
}
|
||||||
|
|
||||||
|
static AngelScriptScript* GetScript(PkmnLib::Battling::BattleLibrary* mainLib, const char* scriptName) {
|
||||||
|
auto lib = GetScriptResolver(mainLib);
|
||||||
|
auto s = lib->LoadScript(AngelScripResolver::ScriptCategory::Creature, scriptName);
|
||||||
|
auto script = dynamic_cast<AngelScriptScript*>(s);
|
||||||
|
return script;
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("Invoke non-implemented script function") {
|
||||||
|
auto mainLib = TestLibrary::GetLibrary();
|
||||||
|
auto script = GetScript(mainLib, "blankScript");
|
||||||
|
script->Stack();
|
||||||
|
delete script;
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("Invoke Stack script function") {
|
||||||
|
auto mainLib = TestLibrary::GetLibrary();
|
||||||
|
auto script = GetScript(mainLib, "stackScript");
|
||||||
|
for (int i = 1; i <= 10; i++) {
|
||||||
|
script->Stack();
|
||||||
|
|
||||||
|
auto ctxPool = script->GetContextPool();
|
||||||
|
auto ctx = ctxPool->RequestContext();
|
||||||
|
script->PrepareMethod("GetValue", ctx);
|
||||||
|
REQUIRE(ctx->Execute() == asEXECUTION_FINISHED);
|
||||||
|
REQUIRE(ctx->GetReturnDWord() == i);
|
||||||
|
ctxPool->ReturnContextToPool(ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
delete script;
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("Invoke Stack script function with implementation in base class") {
|
||||||
|
auto mainLib = TestLibrary::GetLibrary();
|
||||||
|
auto script = GetScript(mainLib, "doubleInheritanceScript");
|
||||||
|
for (int i = 1; i <= 10; i++) {
|
||||||
|
script->Stack();
|
||||||
|
|
||||||
|
auto ctxPool = script->GetContextPool();
|
||||||
|
auto ctx = ctxPool->RequestContext();
|
||||||
|
script->PrepareMethod("GetValue", ctx);
|
||||||
|
REQUIRE(ctx->Execute() == asEXECUTION_FINISHED);
|
||||||
|
REQUIRE(ctx->GetReturnDWord() == i);
|
||||||
|
ctxPool->ReturnContextToPool(ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
delete script;
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("Invoke preventAttackScript script function") {
|
||||||
|
auto mainLib = TestLibrary::GetLibrary();
|
||||||
|
auto script = GetScript(mainLib, "preventAttackScript");
|
||||||
|
bool b = false;
|
||||||
|
script->PreventAttack(nullptr, &b);
|
||||||
|
REQUIRE(b);
|
||||||
|
|
||||||
|
delete script;
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("Invoke StopBeforeAttack script function") {
|
||||||
|
auto mainLib = TestLibrary::GetLibrary();
|
||||||
|
auto script = GetScript(mainLib, "stopBeforeAttackScript");
|
||||||
|
bool b = false;
|
||||||
|
script->StopBeforeAttack(nullptr, &b);
|
||||||
|
REQUIRE(b);
|
||||||
|
|
||||||
|
delete script;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
|
@ -89,41 +89,4 @@ TEST_CASE("Build script resolver, create object, invoke addition method") {
|
||||||
delete lib;
|
delete lib;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
TEST_CASE("Test whether species object was properly registered.") {
|
|
||||||
auto lib = dynamic_cast<AngelScripResolver*>(PkmnLib::Battling::BattleLibrary::CreateScriptResolver());
|
|
||||||
auto mainLib = TestLibrary::GetLibrary();
|
|
||||||
lib->Initialize(mainLib);
|
|
||||||
lib->SetCreateFunction(&_testLoadFunc);
|
|
||||||
lib->CreateScript("testScript1");
|
|
||||||
lib->FinalizeModule();
|
|
||||||
auto species = mainLib->GetSpeciesLibrary()->GetPkmnSpecies("testSpecies2");
|
|
||||||
|
|
||||||
auto obj =
|
|
||||||
dynamic_cast<AngelScriptScript*>(lib->LoadScript(AngelScripResolver::ScriptCategory::Creature, "testScript1"));
|
|
||||||
|
|
||||||
auto ctxPool = obj->GetContextPool();
|
|
||||||
auto ctx = ctxPool->RequestContext();
|
|
||||||
|
|
||||||
obj->PrepareMethod("testFunc2", ctx);
|
|
||||||
ctx->SetArgObject(0, const_cast<PkmnLib::Library::PokemonSpecies*>(species));
|
|
||||||
auto result = ctx->Execute();
|
|
||||||
if (result == asEXECUTION_EXCEPTION){
|
|
||||||
FAIL(ctx->GetExceptionString());
|
|
||||||
}
|
|
||||||
ctx->Unprepare();
|
|
||||||
|
|
||||||
species = mainLib->GetSpeciesLibrary()->GetPkmnSpecies("testSpecies");
|
|
||||||
|
|
||||||
obj->PrepareMethod("testFunc2", ctx);
|
|
||||||
ctx->SetArgObject(0, const_cast<PkmnLib::Library::PokemonSpecies*>(species));
|
|
||||||
result = ctx->Execute();
|
|
||||||
REQUIRE(result == asEXECUTION_EXCEPTION);
|
|
||||||
|
|
||||||
ctxPool->ReturnContextToPool(ctx);
|
|
||||||
delete obj;
|
|
||||||
delete lib;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
Loading…
Reference in New Issue