Skip to content

Commit edc229f

Browse files
authored
Merge pull request #80 from Septirage/feature/AllowToSwitchCNWSMessage
Allow to switch CNWSMessage for ExecuteScript*
2 parents bc07f0f + b5dfc27 commit edc229f

File tree

4 files changed

+112
-11
lines changed

4 files changed

+112
-11
lines changed

include/nwnx_cplugin.h

+10-2
Original file line numberDiff line numberDiff line change
@@ -29,15 +29,23 @@ struct NWNXCPlugin_InitInfo {
2929
/// Bound to NWScript ExecuteScript function
3030
/// @param outExecuted If not null, the bool will be set to true if the script
3131
/// has been successfully executed.
32-
typedef void(ExecuteScriptFn)(const char* sScript, uint32_t oTarget, bool* outExecuted);
32+
/// @param bReplaceCNWSMsg If true, the CNWSMessage will be switched for this call
33+
/// avoiding issues if used during message construction
34+
typedef void(ExecuteScriptFn)(const char* sScript,
35+
uint32_t oTarget,
36+
bool* outExecuted,
37+
bool bReplaceCNWSMsg);
3338
/// Bound to NWScript ExecuteScriptEnhanced function
3439
/// @param outExecuted If not null, the bool will be set to true if the script
3540
/// has been successfully executed. This is used to differenciate between a
3641
/// script returning the value -1 and a script not being executed.
42+
/// @param bReplaceCNWSMsg If true, the CNWSMessage will be switched for this call
43+
/// avoiding issues if used during message construction
3744
typedef int32_t(ExecuteScriptEnhancedFn)(const char* sScriptName,
3845
uint32_t oTarget,
3946
bool bClearParams,
40-
bool* outExecuted);
47+
bool* outExecuted,
48+
bool bReplaceCNWSMsg);
4149
/// Bound to NWScript AddScriptParameterInt function. Bound values are not
4250
/// shared between the NWScript and CPlugin environments
4351
typedef void(AddScriptParameterIntFn)(int32_t nParam);

src/hook/scriptManagement.cpp

+91-2
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
#include <string>
77

88
#include "../misc/log.h"
9+
#include "nwn2heap.h"
910
extern std::unique_ptr<LogNWNX> logger;
1011

1112
constexpr uint32_t NWN_DEFAULT_EXECUTESCRIPT_ENH_PARAMS_LEN = 32;
@@ -79,25 +80,110 @@ static CVirtualMachine_ExecuteScriptEnhanced_t CVirtualMachine_ExecuteScriptEnha
7980

8081
namespace NWScript {
8182

82-
void ExecuteScript(const char* sScript, NWN::OBJECTID oTarget, bool* outExecuted)
83+
static int OriginalCNWSMsgAddr = 0;
84+
85+
int* GetPtrToCNWSMessage()
86+
{
87+
int ptr = *(int*)OFFS_g_pAppManager;
88+
ptr = *(int*)(ptr + 4);
89+
ptr = *(int*)(ptr + 4);
90+
return (int*)(ptr + 0x10020);
91+
}
92+
93+
void ApplyScriptCNWSMessage()
94+
{
95+
int* ptrToCNWSMessage = GetPtrToCNWSMessage();
96+
97+
static unsigned char* scriptCNWSMsg;
98+
static bool isInit = false;
99+
100+
if (!isInit) {
101+
OriginalCNWSMsgAddr = *ptrToCNWSMessage;
102+
NWN2_HeapMgr* pHeapMgr = NWN2_HeapMgr::Instance();
103+
NWN2_Heap* pHeap = pHeapMgr->GetDefaultHeap();
104+
scriptCNWSMsg = (unsigned char*)pHeap->Allocate(0x58);
105+
unsigned char* Msg1 = (unsigned char*)pHeap->Allocate(0x80);
106+
unsigned char* Msg2 = (unsigned char*)pHeap->Allocate(0x80);
107+
108+
scriptCNWSMsg[0] = 0xC0;
109+
scriptCNWSMsg[1] = 0x42;
110+
scriptCNWSMsg[2] = 0x80;
111+
scriptCNWSMsg[3] = 0x00;
112+
113+
((uint32_t*)scriptCNWSMsg)[0x14] = 0xFFFFFFFF;
114+
((uint32_t*)scriptCNWSMsg)[0x15] = 0x7F000000;
115+
116+
((uint32_t*)scriptCNWSMsg)[1] = (int)Msg1;
117+
((uint32_t*)scriptCNWSMsg)[2] = 0x80;
118+
((uint32_t*)scriptCNWSMsg)[3] = 0x0;
119+
120+
((uint32_t*)scriptCNWSMsg)[4] = (int)Msg2;
121+
((uint32_t*)scriptCNWSMsg)[5] = 0x80;
122+
((uint32_t*)scriptCNWSMsg)[6] = 0;
123+
((uint32_t*)scriptCNWSMsg)[7] = 0;
124+
125+
scriptCNWSMsg[0x20] = 0;
126+
127+
((uint32_t*)scriptCNWSMsg)[9] = 0x0;
128+
((uint32_t*)scriptCNWSMsg)[0xa] = 0x0;
129+
((uint32_t*)scriptCNWSMsg)[0xb] = 0x0;
130+
((uint32_t*)scriptCNWSMsg)[0xc] = 0x0;
131+
132+
((uint32_t*)scriptCNWSMsg)[0xd] = 0x0;
133+
((uint32_t*)scriptCNWSMsg)[0xe] = 0x0;
134+
((uint32_t*)scriptCNWSMsg)[0xf] = 0x0;
135+
((uint32_t*)scriptCNWSMsg)[0x10] = 0x0;
136+
scriptCNWSMsg[0x44] = 0x0;
137+
scriptCNWSMsg[0x45] = 0x0;
138+
isInit = true;
139+
}
140+
141+
if (scriptCNWSMsg != NULL)
142+
*ptrToCNWSMessage = (int)(scriptCNWSMsg);
143+
}
144+
145+
void RestoreOriginalCNWSMessage()
146+
{
147+
// Be sure to not restore before saving the Original CNWSMsg
148+
if (OriginalCNWSMsgAddr != 0) {
149+
int* ptrToCNWSMessage = GetPtrToCNWSMessage();
150+
*ptrToCNWSMessage = OriginalCNWSMsgAddr;
151+
}
152+
}
153+
154+
void ExecuteScript(const char* sScript,
155+
NWN::OBJECTID oTarget,
156+
bool* outExecuted,
157+
bool bReplaceCNWSMsg)
83158
{
84159
logger->Trace("ExecuteScript %s, %lu", sScript, oTarget);
160+
161+
if (bReplaceCNWSMsg)
162+
ApplyScriptCNWSMessage();
163+
85164
auto executed = CVirtualMachine_ExecuteScript(
86165
*nwn2_vm,
87166
NWN::CExoString {.m_sString = (char*)sScript, // un-const cast, safe as param is read only
88167
.m_nBufferLength = strlen(sScript)},
89168
oTarget, 1, 1);
90169
if (outExecuted != nullptr)
91170
*outExecuted = executed;
171+
172+
if (bReplaceCNWSMsg)
173+
RestoreOriginalCNWSMessage();
92174
}
93175

94176
int32_t ExecuteScriptEnhanced(const char* sScriptName,
95177
NWN::OBJECTID oTarget,
96178
bool bClearParams,
97-
bool* outExecuted)
179+
bool* outExecuted,
180+
bool bReplaceCNWSMsg)
98181
{
99182
logger->Trace("ExecuteScriptEnhanced %s, %lu", sScriptName, oTarget);
100183

184+
if (bReplaceCNWSMsg)
185+
ApplyScriptCNWSMessage();
186+
101187
const NWN::CExoString script
102188
= {.m_sString = (char*)sScriptName, .m_nBufferLength = strlen(sScriptName)};
103189

@@ -121,6 +207,9 @@ int32_t ExecuteScriptEnhanced(const char* sScriptName,
121207

122208
*nwn2_scriptparams = save;
123209

210+
if (bReplaceCNWSMsg)
211+
RestoreOriginalCNWSMessage();
212+
124213
return retValue;
125214
}
126215
void AddScriptParameterInt(int32_t nParam)

src/hook/scriptManagement.h

+6-2
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,15 @@
1010
namespace NWScript {
1111

1212
extern "C" {
13-
void ExecuteScript(const char* sScript, NWN::OBJECTID oTarget, bool* outExecuted = NULL);
13+
void ExecuteScript(const char* sScript,
14+
NWN::OBJECTID oTarget,
15+
bool* outExecuted = NULL,
16+
bool bReplaceCNWSMsg = false);
1417
int32_t ExecuteScriptEnhanced(const char* sScriptName,
1518
NWN::OBJECTID oTarget,
1619
bool bClearParams,
17-
bool* outExecuted = NULL);
20+
bool* outExecuted = NULL,
21+
bool bReplaceCNWSMsg = false);
1822
void AddScriptParameterInt(int32_t nParam);
1923
void AddScriptParameterString(const char* sParam);
2024
void AddScriptParameterFloat(float fParam);

src/plugins/xp_example_cplugin/cplugin_example.cpp

+5-5
Original file line numberDiff line numberDiff line change
@@ -106,12 +106,12 @@ NWNXCPlugin_GetInt(void* cplugin, const char* sFunction, const char* sParam1, in
106106
} else if (function == "TEST_EXECUTESCRIPT") {
107107
constexpr uint32_t OBJID_MODULE = 0;
108108
bool executed = false;
109-
plugin->hooks.ExecuteScript("gui_test_executescript", OBJID_MODULE, &executed);
109+
plugin->hooks.ExecuteScript("gui_test_executescript", OBJID_MODULE, &executed, false);
110110
return executed == true ? 12 : 0;
111111
} else if (function == "TEST_EXECUTESCRIPTBAD") {
112112
constexpr uint32_t OBJID_MODULE = 0;
113113
bool executed = true;
114-
plugin->hooks.ExecuteScript("euqsgdihohcqsc", OBJID_MODULE, &executed);
114+
plugin->hooks.ExecuteScript("euqsgdihohcqsc", OBJID_MODULE, &executed, false);
115115
return executed == false ? 13 : 0;
116116
} else if (function == "TEST_EXECUTESCRIPTENH") {
117117
constexpr uint32_t OBJID_MODULE = 0;
@@ -122,15 +122,15 @@ NWNXCPlugin_GetInt(void* cplugin, const char* sFunction, const char* sParam1, in
122122
plugin->hooks.AddScriptParameterObject(0x01020304);
123123
bool executed = false;
124124
auto res = plugin->hooks.ExecuteScriptEnhanced("gui_test_executescriptenh", OBJID_MODULE,
125-
true, &executed);
125+
true, &executed, false);
126126
if (!executed)
127127
res -= 1000;
128128
return res;
129129
} else if (function == "TEST_EXECUTESCRIPTENHBAD") {
130130
constexpr uint32_t OBJID_MODULE = 0;
131131
bool executed = true;
132-
auto res
133-
= plugin->hooks.ExecuteScriptEnhanced("euqsgdihohcqsc", OBJID_MODULE, true, &executed);
132+
auto res = plugin->hooks.ExecuteScriptEnhanced("euqsgdihohcqsc", OBJID_MODULE, true,
133+
&executed, false);
134134
if (executed)
135135
res -= 1000;
136136
return res;

0 commit comments

Comments
 (0)