1
+ #if !defined(SCRIPTMANAGEMENT_H_INCLUDED)
2
+ #define SCRIPTMANAGEMENT_H_INCLUDED
3
+
4
+ #define DLLEXPORT extern " C" __declspec(dllexport)
5
+
6
+ #include < iostream>
7
+ #include " ../NWN2Lib/NWN2.h"
8
+ #include " ../NWN2Lib/NWN2Common.h"
9
+
10
+
11
+ namespace ScriptManagement {
12
+ // 1.23
13
+ // g_pVirtualMachine
14
+ constexpr uintptr_t NWN2_OFFSET_CVIRTUALMACHINE = 0x00864424 ;
15
+ // CVirtualMachine::ExecuteScript
16
+ constexpr uintptr_t NWN2_OFFSET_EXECUTESCRIPT = 0x0072B380 ;
17
+ constexpr uintptr_t NWN2_OFFSET_EXECUTESCRIPT_ENH = 0x0072B050 ;
18
+
19
+ constexpr uintptr_t NWN2_OFFSET_InitParam = 0x0055EA40 ;
20
+ constexpr uintptr_t NWN2_OFFSET_CleanParam = 0x006b5cd0 ;
21
+
22
+
23
+ struct CVirtualMachine { };
24
+
25
+ using CVirtualMachine_ExecuteScript_t = BOOL(__thiscall*)(CVirtualMachine* thisVM,
26
+ const NWN::CExoString& scriptName, NWN::OBJECTID objectId, uint32_t unknown1, uint32_t unknown2);
27
+ CVirtualMachine_ExecuteScript_t CVirtualMachine_ExecuteScript =
28
+ std::bit_cast<CVirtualMachine_ExecuteScript_t>(NWN2_OFFSET_EXECUTESCRIPT);
29
+
30
+ using CVirtualMachine_ExecuteScriptEnhanced_t = int (__thiscall*)(CVirtualMachine* thisVM,
31
+ const NWN::CExoString& scriptName, NWN::OBJECTID objectID, void * ParamList, uint32_t unknow1, uint32_t unknow2);
32
+ CVirtualMachine_ExecuteScriptEnhanced_t CVirtualMachine_ExecuteScriptEnhanced =
33
+ std::bit_cast<CVirtualMachine_ExecuteScriptEnhanced_t>(NWN2_OFFSET_EXECUTESCRIPT_ENH);
34
+
35
+ using CVirtualMachine_InitParam_t = void (__thiscall*)(void * paramLst, uint32_t iNb);
36
+ using CVirtualMachine_CleanParam_t = void (__thiscall*)(void * paramLst);
37
+
38
+ CVirtualMachine_InitParam_t CVirtualMachine_InitParam =
39
+ std::_Bit_cast<CVirtualMachine_InitParam_t>(NWN2_OFFSET_InitParam);
40
+ CVirtualMachine_CleanParam_t CVirtualMachine_CleanParam =
41
+ std::_Bit_cast<CVirtualMachine_CleanParam_t>(NWN2_OFFSET_CleanParam);
42
+
43
+ CVirtualMachine*
44
+ GetNwn2VirtualMachine ()
45
+ {
46
+ const auto vm = std::bit_cast<CVirtualMachine**>(NWN2_OFFSET_CVIRTUALMACHINE);
47
+ return *vm;
48
+ }
49
+
50
+
51
+
52
+
53
+
54
+ // Add this redirection just so, in case of literal value, don't need to type 3.5f instead of 3.5
55
+ void AddFParam (uint32_t * ptrParams, float fParam )
56
+ {
57
+ // float Param
58
+ ptrParams[1 ] = *(uint32_t *)(&fParam ); // Set Value
59
+ ptrParams[4 ] = 1 ; // Set Type
60
+ }
61
+
62
+ void AddParam (uint32_t * ptrParams, float fParam )
63
+ {
64
+ AddFParam (ptrParams, fParam );
65
+ }
66
+
67
+ void AddParam (uint32_t * ptrParams, double dParam)
68
+ {
69
+ AddFParam (ptrParams, dParam);
70
+ }
71
+
72
+
73
+ void AddParam (uint32_t * ptrParams, NWN::OBJECTID oParam)
74
+ {
75
+ // NwnObject Param
76
+ ptrParams[1 ] = (uint32_t )oParam; // Set Value
77
+ ptrParams[4 ] = 4 ; // Set Type
78
+ }
79
+
80
+ void AddParam (uint32_t * ptrParams, const char * sParam )
81
+ {
82
+ // For string it's a little different
83
+ ptrParams[1 ] = 0 ; // No "data"
84
+ ptrParams[2 ] = (uint32_t )(sParam ); // Set dataptr
85
+ ptrParams[3 ] = strlen (sParam )+1 ; // set datasize (including endofchar)
86
+ ptrParams[4 ] = 2 ; // Set type
87
+ }
88
+
89
+ void AddParam (uint32_t * ptrParams, int iParam)
90
+ {
91
+ // Int Param
92
+ ptrParams[1 ] = *(uint32_t *)(&iParam); // Set Value
93
+ ptrParams[4 ] = 0 ; // Set Type
94
+ }
95
+
96
+
97
+ void AddParameters (uint32_t * ptrParams){}
98
+
99
+ template <typename T, typename ... Targs>
100
+ void AddParameters (uint32_t * ptrParams,T value, Targs... Fargs)
101
+ {
102
+ // call the build for the "first param"
103
+ AddParam (ptrParams, value);
104
+
105
+ // Call for the nexts parameters
106
+ AddParameters (ptrParams+5 , Fargs...);
107
+ }
108
+
109
+ // Because we don't really create new NWString, just "cheat" a little
110
+ // and remove them from the parameters list (change them in int)
111
+ void PrepareCleanParameter (uint32_t * ptrParams, int iSize)
112
+ {
113
+ for (int i = 0 ; i < iSize; i++)
114
+ {
115
+ // We have a string ?
116
+ if (ptrParams[4 ] == 2 )
117
+ {
118
+ // change it to a "0" int.
119
+ ptrParams[1 ] = 0 ;
120
+ ptrParams[2 ] = 0 ;
121
+ ptrParams[3 ] = 0 ;
122
+ ptrParams[4 ] = 0 ;
123
+ }
124
+ ptrParams += 5 ;
125
+ }
126
+ }
127
+ }
128
+
129
+
130
+
131
+ template <typename ... Targs>
132
+ int ExecuteEnhancedScript_sp (std::string sScriptName , NWN::OBJECTID oTarget, Targs... Parameters)
133
+ {
134
+ int retValue = -1 ;
135
+ const NWN::CExoString script = { .m_sString = (sScriptName ).data (),
136
+ .m_nBufferLength = (sScriptName .size () + 1 ) };
137
+
138
+ int iSize = sizeof ...(Parameters);
139
+
140
+ void * param1 = (void *)0x0086F15C ;
141
+
142
+ uint32_t * save = new uint32_t [iSize];
143
+
144
+ for (int i = 0 ; i < iSize; i++)
145
+ {
146
+ save[i] = ((uint32_t *)param1)[i];
147
+ }
148
+
149
+ ScriptManagement::CVirtualMachine_InitParam (param1, iSize);
150
+
151
+ uint32_t * ptrParams = *(uint32_t **)param1;
152
+ ((uint32_t *)param1)[1 ] = iSize;
153
+
154
+ // Prepare Parameters
155
+ ScriptManagement::AddParameters (ptrParams, Parameters...);
156
+
157
+ // call the script
158
+ const auto vm = ScriptManagement::GetNwn2VirtualMachine ();
159
+ retValue = ScriptManagement::CVirtualMachine_ExecuteScriptEnhanced (vm, script, oTarget, (void *)0x0086F15C , 1 , 1 );
160
+
161
+
162
+ // Is the script ok?
163
+ if (retValue != 0 )
164
+ retValue = ((uint32_t *)vm)[1 ];
165
+ else
166
+ retValue = -1 ;
167
+
168
+
169
+ ScriptManagement::PrepareCleanParameter (ptrParams, iSize);
170
+ param1 = (void *)0x0086F15C ;
171
+ ScriptManagement::CVirtualMachine_CleanParam (param1); // Problème si string ?
172
+
173
+
174
+
175
+
176
+ // Pop the saved values
177
+ for (int i = 0 ; i < iSize; i++)
178
+ {
179
+ ((uint32_t *)param1)[i] = save[i];
180
+ }
181
+
182
+ delete[] save;
183
+
184
+ return retValue;
185
+ };
186
+
187
+ #endif
0 commit comments