#pragma once #include "skse64_common/Utilities.h" #include "skse64/PapyrusVM.h" #include class VMState; class VMValue; class VMClassRegistry; struct StaticFunctionTag; class EffectSetting; class VMArgList { public: VMArgList(); ~VMArgList(); MEMBER_FN_PREFIX(VMArgList); DEFINE_MEMBER_FN(GetOffset, UInt32, 0x0136F0E0, VMState * state); // FB33603AEC8921D8A9361F52478B667E583E54A1+20 DEFINE_MEMBER_FN(Get, VMValue *, 0x0136F150, VMState * state, UInt32 idx, UInt32 offset); }; template class VMArray { public: VMValue::ArrayData * arr; UInt32 Length() const { return arr ? arr->len : 0; } void Get(T * dst, const UInt32 idx) { UnpackValue(dst, arr->GetData()+idx); } void Set(T * src, const UInt32 idx) { VMClassRegistry * registry = (*g_skyrimVM)->GetClassRegistry(); PackValue(arr->GetData()+idx, src, registry); } }; template class VMResultArray : public std::vector { public: void PackArray(VMValue::ArrayData * data, VMClassRegistry * registry) { // Copy the contents from the reference array to the VM array UInt32 i = 0; for(std::vector::iterator it = begin(); it != end(); ++it, i++) { VMValue * value = data->GetData() + i; PackValue(value, (T*)&(*it), registry); value->type = GetTypeID(registry); // Always pack the type, even if empty data } } }; template void PackValue(VMValue * dst, VMResultArray * src, VMClassRegistry * registry) { // Clear out old contents if any dst->SetNone(); if(src->size() > 0) { VMValue::ArrayData * data = NULL; // Request the VM allocate a new array registry->CreateArray(dst, src->size(), &data); if(data) { src->PackArray(data, registry); // Set the appropriate TypeID and assign the new data array dst->type = GetTypeID>(registry); dst->data.arr = data; } } // Clear the temp contents of the reference array src->clear(); } template void UnpackValue(VMArray * dst, VMValue * src) { UnpackArray(dst, src, GetTypeIDFromFormTypeID(T::kTypeID, (*g_skyrimVM)->GetClassRegistry()) | VMValue::kType_Identifier); } template void PackValue(VMValue * dst, T * src, VMClassRegistry * registry); template void UnpackValue(T * dst, VMValue * src); template <> void PackValue (VMValue * dst, void * src, VMClassRegistry * registry); template <> void PackValue (VMValue * dst, UInt32 * src, VMClassRegistry * registry); template <> void PackValue (VMValue * dst, SInt32 * src, VMClassRegistry * registry); template <> void PackValue (VMValue * dst, float * src, VMClassRegistry * registry); template <> void PackValue (VMValue * dst, bool * src, VMClassRegistry * registry); template <> void PackValue (VMValue * dst, BSFixedString * src, VMClassRegistry * registry); void PackHandle(VMValue * dst, void * src, UInt32 typeID, VMClassRegistry * registry); template void PackValue(VMValue * dst, T ** src, VMClassRegistry * registry) { typedef std::remove_pointer ::type BaseType; PackHandle(dst, *src, BaseType::kTypeID, registry); } template <> void UnpackValue (float * dst, VMValue * src); template <> void UnpackValue (UInt32 * dst, VMValue * src); template <> void UnpackValue (SInt32 * dst, VMValue * src); template <> void UnpackValue (bool * dst, VMValue * src); template <> void UnpackValue (BSFixedString * dst, VMValue * src); template <> void UnpackValue >(VMArray * dst, VMValue * src); template <> void UnpackValue >(VMArray * dst, VMValue * src); template <> void UnpackValue >(VMArray * dst, VMValue * src); template <> void UnpackValue >(VMArray * dst, VMValue * src); template <> void UnpackValue >(VMArray * dst, VMValue * src); void * UnpackHandle(VMValue * src, UInt32 typeID); template void UnpackValue(T ** dst, VMValue * src) { *dst = (T *)UnpackHandle(src, T::kTypeID); } template void UnpackArray(VMArray * dst, VMValue * src, const UInt64 type) { VMValue::ArrayData * arrData; if (src->type != type || (arrData = src->data.arr, !arrData)) { dst->arr = NULL; return; } dst->arr = arrData; } UInt64 GetTypeIDFromFormTypeID(UInt32 formTypeID, VMClassRegistry * registry); template struct IsArrayType { enum { value = 0 }; typedef T TypedArg; }; template struct IsArrayType> { enum { value = 1 }; typedef T TypedArg; }; template struct IsArrayType> { enum { value = 1 }; typedef T TypedArg; }; template auto GetTypeID(VMClassRegistry* registry) -> std::enable_if_t::value && !IsArrayType::value, UInt64>; template <> UInt64 GetTypeID (VMClassRegistry * registry); template <> UInt64 GetTypeID (VMClassRegistry * registry); template <> UInt64 GetTypeID (VMClassRegistry * registry); template <> UInt64 GetTypeID (VMClassRegistry * registry); template <> UInt64 GetTypeID (VMClassRegistry * registry); template <> UInt64 GetTypeID (VMClassRegistry * registry); template <> UInt64 GetTypeID (VMClassRegistry * registry); template <> UInt64 GetTypeID >(VMClassRegistry * registry); template <> UInt64 GetTypeID >(VMClassRegistry * registry); template <> UInt64 GetTypeID >(VMClassRegistry * registry); template <> UInt64 GetTypeID >(VMClassRegistry * registry); template <> UInt64 GetTypeID >(VMClassRegistry * registry); template <> UInt64 GetTypeID >(VMClassRegistry * registry); template <> UInt64 GetTypeID >(VMClassRegistry * registry); template <> UInt64 GetTypeID >(VMClassRegistry * registry); template <> UInt64 GetTypeID >(VMClassRegistry * registry); template <> UInt64 GetTypeID >(VMClassRegistry * registry); template <> UInt64 GetTypeID >(VMClassRegistry * registry); template <> UInt64 GetTypeID >(VMClassRegistry * registry); template auto GetTypeID(VMClassRegistry * registry) -> std::enable_if_t::value, UInt64> { return GetTypeIDFromFormTypeID(IsArrayType::TypedArg::kTypeID, registry) | VMValue::kType_Identifier; } template auto GetTypeID(VMClassRegistry * registry) -> std::enable_if_t::value && !IsArrayType>::value, UInt64> { return GetTypeIDFromFormTypeID(std::remove_pointer::type::kTypeID, registry); } template struct IsStaticType { enum { value = 0 }; }; template <> struct IsStaticType { enum { value = 1 }; };