forked from lStewieAl/Geck-Extender
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathNavmeshHooks.cpp
More file actions
254 lines (219 loc) · 6.86 KB
/
Copy pathNavmeshHooks.cpp
File metadata and controls
254 lines (219 loc) · 6.86 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
#include "GameData.h"
namespace NavmeshHooks
{
const char* NavmeshConfirmMessage = "Are you sure you want to find cover edges?";
__HOOK RenderWindowNavMeshConfirmFindCover()
{
static const UInt32 skipAddr = 0x462C7A;
_asm
{
push MB_TASKMODAL | MB_ICONWARNING | MB_YESNO
push 0xD2D1F4 // "Navmesh: Find Cover"
push NavmeshConfirmMessage
push 0
call MessageBoxA
cmp eax, IDNO
je skip
push 0
mov ecx, 0xF073F8
push 0x456F2E // retnAddr
mov eax, 0x6F51B0 // Navmesh::FindCoverEdges
jmp eax
skip:
jmp skipAddr
}
}
__HOOK MainWindowNavMeshConfirmFindCover()
{
static const UInt32 skipAddr = 0x44382F;
_asm
{
push MB_TASKMODAL | MB_ICONWARNING | MB_YESNO
push 0xD2D1F4 // "Navmesh: Find Cover"
push NavmeshConfirmMessage
push 0
call MessageBoxA
cmp eax, IDNO
je skip
push 0
mov ecx, 0xF073F8
push 0x44451D // retnAddr
mov eax, 0x6F51B0 // Navmesh::FindCoverEdges
jmp eax
skip:
jmp skipAddr
}
}
__HOOK NavMeshToolbarConfirmFindCover()
{
static const UInt32 skipAddr = 0x40AC87;
_asm
{
push MB_TASKMODAL | MB_ICONWARNING | MB_YESNO
push 0xD2D1F4 // "Navmesh: Find Cover"
push NavmeshConfirmMessage
push 0
call MessageBoxA
cmp eax, IDNO
je skip
// doNavmesh
push 0
mov ecx, 0xF073F8
push 0x40AC7B // retnAddr
mov eax, 0x6F51B0 // Navmesh::FindCoverEdges
jmp eax
skip:
jmp skipAddr
}
}
void __fastcall OnMainWindowUndo(TESUndo* apUndo, void* edx, int formal)
{
if (NavMeshManager::IsActive())
{
NavMeshManager::GetSingleton()->Undo();
}
else
{
apUndo->Undo();
}
}
void __stdcall OnTAllocZeroMemory(int* pMemory, int size, int numAllocs, void* initFn, void* destroyFn)
{
memset(pMemory, 0, 4 * numAllocs);
}
void __fastcall NavMeshManager__OnMergeVertices(NavMeshManager* navMeshManager)
{
if (navMeshManager->HasMultipleNavmeshesSelected())
{
if (MessageBoxA(MainWindow::GetWindow(), "You are about to merge Navmesh records which will cause one to be deleted, do you wish to proceed?", "Geck Extender", MB_YESNOCANCEL) != IDYES)
{
return;
}
}
ThisCall(0x4267B0, navMeshManager);
}
void __fastcall NavMeshManager__OnCreateTriangle(NavMeshManager* navMeshManager)
{
if (navMeshManager->HasMultipleNavmeshesSelected())
{
if (MessageBoxA(MainWindow::GetWindow(), "You are about to merge Navmesh records which will cause one to be deleted, do you wish to proceed?", "Geck Extender", MB_YESNOCANCEL) != IDYES)
{
return;
}
}
ThisCall(0x427650, navMeshManager);
}
void __fastcall NavMeshManager__OnCreateQuad(NavMeshManager* navMeshManager, void* edx, char a2)
{
if (navMeshManager->HasMultipleNavmeshesSelected())
{
if (MessageBoxA(MainWindow::GetWindow(), "You are about to merge Navmesh records which will cause one to be deleted, do you wish to proceed?", "Geck Extender", MB_YESNOCANCEL) != IDYES)
{
return;
}
}
ThisCall(0x427770, navMeshManager, a2);
}
__HOOK NavMeshManager__PostRenderCellClearPrintHook()
{
static const char* EmptyString = "";
_asm
{
push EmptyString
push 0x3
mov eax, 0x4657A0 // TESCSMain::WriteToStatusBar
call eax
add esp, 0x14
ret 0xC
}
}
__HOOK NavMeshInfoMap__CheckInfosHook()
{
_asm
{
test edx, edx
je skip
cmp byte ptr ds : [edx + 0x04] , bl
jne skip
inc esi
skip:
mov edx, 0x6ED488
jmp edx
}
}
UInt32 forceFinalizeNavMeshModIndex = -1;
void __fastcall NavMeshManager__ShowFinalizeAllNavMeshesPopup(NavMeshManager* navMeshManager)
{
if (*config.sForceFinalizeNavMeshModName)
{
auto mod = DataHandler::GetSingleton()->LookupModByName(config.sForceFinalizeNavMeshModName);
if (mod)
{
forceFinalizeNavMeshModIndex = mod->modIndex;
}
else
{
Console_Print("Force Finalize NavMesh: Unable to find mod %s", config.sForceFinalizeNavMeshModName);
}
}
ThisCall(0x426160, navMeshManager);
forceFinalizeNavMeshModIndex = -1;
}
void* __fastcall OnForceFinalizeShouldProcessCell(TESObjectCELL* cell)
{
if (forceFinalizeNavMeshModIndex != -1)
{
if (cell->modIndex != forceFinalizeNavMeshModIndex)
{
return nullptr;
}
}
return cell->navMeshArray;
}
int __cdecl OnForceFinalizeShowMessageBox(char* DstBuf, size_t SizeInBytes, char* Format, UInt32 numCellsToFinalize)
{
if (forceFinalizeNavMeshModIndex != -1)
{
return CdeclCall<int>(0x401190, DstBuf, SizeInBytes, "About to finalize %d cells with navmeshes for file %s. Finalizing and saving the entire worldspace could take a larger amount of time. Continue?", numCellsToFinalize, config.sForceFinalizeNavMeshModName);
}
return CdeclCall<int>(0x401190, DstBuf, SizeInBytes, Format, numCellsToFinalize);
}
void Init()
{
if (config.bNavmeshFindCoverConfirmPrompt)
{
WriteRelJump(0x456F22, UInt32(RenderWindowNavMeshConfirmFindCover));
WriteRelJump(0x444511, UInt32(MainWindowNavMeshConfirmFindCover));
WriteRelJump(0x40AC6F, UInt32(NavMeshToolbarConfirmFindCover)); // skip 0x40AC87, retn 0x40AC7B
}
// fix the undo menu button for NavMesh
WriteRelCall(0x44104A, UInt32(OnMainWindowUndo));
SafeWrite16(0x6C07D8, 0x07EB); // fix unnecessary duplicate function call in NavMeshRender::AttachEdge
WriteRelCall(0x6778C2, UInt32(OnTAllocZeroMemory)); // microoptimize TAlloc::Allocate
// fix NavMeshRenderer creating a new child slot whenever attaching children
SafeWrite8(0x6BF799, 1); // sets bFirstAvail to true
SafeWrite8(0x6C06F7, 1);
SafeWrite8(0x6C20CF, 1);
// prevent x/y/z keys moving the mouse when pressed during navmesh mode
SafeWriteBuf(0x41F3A0, "\xC2\x04\x00", 3);
// show a warning when merging vertices from different navmeshes
WriteRelCall(0x40AAA7, UInt32(NavMeshManager__OnMergeVertices));
WriteRelCall(0x457E23, UInt32(NavMeshManager__OnMergeVertices));
WriteRelCall(0x40A9FF, UInt32(NavMeshManager__OnCreateTriangle));
WriteRelCall(0x4288AC, UInt32(NavMeshManager__OnCreateTriangle));
WriteRelCall(0x4298CE, UInt32(NavMeshManager__OnCreateTriangle));
WriteRelCall(0x456FBF, UInt32(NavMeshManager__OnCreateTriangle));
WriteRelCall(0x4288BF, UInt32(NavMeshManager__OnCreateQuad));
WriteRelCall(0x40AA20, UInt32(NavMeshManager__OnCreateQuad));
WriteRelCall(0x456FD9, UInt32(NavMeshManager__OnCreateQuad));
// clear the 'Creating Editor NavMeshes' print when it's done
WriteRelJump(0x42216C, UInt32(NavMeshManager__PostRenderCellClearPrintHook));
WriteRelJump(0x4220E2, UInt32(NavMeshManager__PostRenderCellClearPrintHook));
// fix crash when saving with a single vertex in a cell with no navmeshes
WriteRelJump(0x6ED482, UInt32(NavMeshInfoMap__CheckInfosHook));
// add option for only finalizing navmeshes for cells from a specified esm
WriteRelCall(0x4446E1, UInt32(NavMeshManager__ShowFinalizeAllNavMeshesPopup));
WriteRelCall(0x426248, UInt32(OnForceFinalizeShouldProcessCell));
WriteRelCall(0x4262CF, UInt32(OnForceFinalizeShowMessageBox));
}
}