Skip to content

Commit f76e063

Browse files
authored
Add easy support for ExecuteEnhancedScript call
1 parent 69fee57 commit f76e063

File tree

1 file changed

+187
-0
lines changed

1 file changed

+187
-0
lines changed

src/hook/scriptManagement.h

+187
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,187 @@
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

Comments
 (0)