Spellforce-Spell-framework
Loading...
Searching...
No Matches
sf_menu_hook.c
Go to the documentation of this file.
1
10#include "../sf_wrappers.h"
11#include "sf_menu_hook.h"
12#include "../sf_hooks.h"
13#include "../sf_modloader.h"
15
16#include <stdint.h>
17#include <stdlib.h>
18#include <stdio.h>
19#include <string.h>
20
21static menu_label_ptr s_initialize_menu_label;
22static initialize_menu_container_ptr s_initialize_menu_container;
23static original_menu_func_ptr s_menu_func;
24static construct_default_sf_string_ptr s_construct_default_sf_string;
25static message_box_ptr s_show_message_box;
26static menu_label_set_data_ptr s_menu_label_set_color;
27
43
62
67
69{
70 // Retrieve function pointers using the Memory Address of Intercepted Function
71 // These addresses are found using a Reverse Engineering program called Ghidra
72
73 s_initialize_menu_label = (menu_label_ptr)(ASI::AddrOf(0x51a180));
74 s_initialize_menu_container =
76 s_construct_default_sf_string =
78 s_menu_func = (original_menu_func_ptr)(ASI::AddrOf(0x197b10));
79 s_menu_label_set_color = (menu_label_set_data_ptr)(ASI::AddrOf(0x530330));
80 s_show_message_box = (message_box_ptr)(ASI::AddrOf(0x198660));
81
85 g_menu_return_addr = (ASI::AddrOf(0x182799));
86 g_ui_hook_fix_addr = (ASI::AddrOf(0x5D119E));
87 g_ui_hook_fix_addr2 = (ASI::AddrOf(0x5d0a7e));
94 g_get_font = (get_font_ptr)(ASI::AddrOf(0x535180));
97
99
109
119
120 vfun163 = (vfun163_ptr)(ASI::AddrOf(0x513C80));
121 vfun164 = (vfun164_ptr)(ASI::AddrOf(0x50F8B0));
122 vfun41 = (vfun41_ptr)(ASI::AddrOf(0x510d70));
123
126
129
132}
133
135void __attribute__((no_caller_saved_registers,
136 thiscall)) sf_menu_hook(uint32_t _CAppMenu)
137{
138 log_info("Starting Menu Hook");
139 // String to display in the new label we're attaching to the menu
140 char sfsf_info[256];
141 sprintf(sfsf_info, "Spell Framework %s\n%d Mod(s) Loaded with %d Error(s)",
143 // Manually move the pointer in order to access the CMNuContainer, We'll need to annotate the CAppMenu Structure more to
144 // Switch to a more convential method.
145 uint32_t CAppMenu_data = *(uint32_t *)(_CAppMenu + 0x4);
146 uint32_t container_hack_ptr = *(uint32_t *)(_CAppMenu + 0x58);
147 CMnuContainer *container_hack = (CMnuContainer *)container_hack_ptr;
148
150 attach_new_label(sfsf_version_label, container_hack, sfsf_info, 6, 10, 729,
151 strlen(sfsf_info) * 4, 100);
152 char sfsf_test_button_default[256];
153 char sfsf_test_button_pressed[256];
154 char sfsf_test_button_disabled[256];
155 char sfsf_test_button_highlight[256];
156 char sfsf_test_button_label[256];
157
158 sprintf(sfsf_test_button_default, "ui_mainmenu_button_default.msh");
159 sprintf(sfsf_test_button_pressed, "ui_mainmenu_button_pressed.msh");
160 sprintf(sfsf_test_button_highlight, "");
161 sprintf(sfsf_test_button_disabled, "ui_mainmenu_button_disabled.msh");
162 sprintf(sfsf_test_button_label, "SHOW MOD LIST");
163
164 // Initialize struct members
165 mod_struct.toggle = 0;
166 mod_struct.index = 0;
167
168 log_info("Adding Mod List Button");
169 int button_index = 15;
170 attach_new_button(container_hack, sfsf_test_button_default,
171 sfsf_test_button_pressed, sfsf_test_button_highlight,
172 sfsf_test_button_disabled, sfsf_test_button_label, 7, 822,
173 705, 192, 36, button_index,
174 (uint32_t)&show_mod_list_callback);
175
176 // Call original menu function to show the menu
177 // char vid_loc[256];
178 // sprintf(vid_loc, "videos\\sfsf");
179 // attachVideo((CAppMenu*)_CAppMenu, container_hack, vid_loc);
180
181 s_menu_func(_CAppMenu);
182}
183
184bool hasThisAuraRunning(SF_CGdFigureToolbox *_this, uint16_t aura_spell_id,
185 uint16_t figure_id)
186{
187 if (figureAPI.isAlive(_this->CGdFigure, figure_id))
188 {
189 if (figureAPI.isFlagSet(_this->CGdFigure, figure_id, AURA_RUNNING))
190 {
191 uint16_t node_id = figureAPI.getSpellJobStartNode(_this->CGdFigure,
192 figure_id);
193 while (node_id != 0)
194 {
195 uint16_t spell_index =
197 node_id);
198 uint16_t spell_id = spellAPI.getSpellID(_this->CGdSpell,
199 spell_index);
200 if (spell_id == aura_spell_id)
201 {
202 return 1;
203 }
205 node_id);
206 }
207 }
208 }
209 return false;
210}
211
212// CUiMain::FUN_009e6840
213void __attribute__((thiscall)) sf_click_vertical_button(SF_CUiMain *_this,
214 uint16_t figure_id,
215 uint8_t entity_type,
216 uint16_t target_id,
217 SF_UIElement *element)
218{
219 log_info("Called SF_CLICK_VERTICAL_BUTTON");
220 uint16_t actionID = element->actionType_id;
221 uint16_t subActionID = element->actionSubtype_id;
222 uint32_t _figure_id = figure_id;
223 if ((actionID == 10000) || (actionID == 10001) || (actionID == 10002))
224 {
225 uint_list_node ac113;
226 fun_00a27530(&ac113);
227 uint32_t *puvar5 = fun_0086dd60(&_figure_id, 1, _figure_id & 0xffff);
228 fun_00a278c0(&ac113, *puvar5);
229 SF_CGdTargetData data;
230 data.entity_index = target_id;
231 data.entity_type = entity_type;
232 data.position.X = 0;
233 data.position.Y = 0;
234 uint32_t uVar3 = fun_00a2ald0(&ac113,
236 fun_006a0140(_this->CUiMain_data.CGdControllerClient, uVar3, &data, 0,
237 0);
238 if (ac113.first != 0)
239 {
240 fun_009a2790(&ac113, ac113.first,
241 (uint32_t)ac113.post_last - (uint32_t)ac113.first >>
242 2);
243 return;
244 }
245 }
246 if ((actionID != 0) && (actionID < 10000))
247 {
249 {
251 subActionID, figure_id))
252 {
254 figure_id);
255 return;
256 }
257 }
258 CGdFigureTask task =
259 _this->CUiMain_data.CGdFigure->figures[figure_id].ac_1.task;
260 SF_CGdTargetData data;
261 data.entity_index = target_id;
262 data.entity_type = entity_type;
263 data.position.X = 0;
264 data.position.Y = 0;
265 uint32_t some_flag = 0;
266 if (task == TASK_MAINCHAR)
267 {
268 some_flag =
269 (uint32_t)(*(uint32_t *)&(_this->CUiMain_data.unkn5[0x2A0]) ==
270 2);
271 }
273 element->unknown_flag, element->unknown_config_param,
274 &data, some_flag, 0);
275 }
276}
277
278uint16_t __attribute__((thiscall)) sf_ui_overlay_fix(SF_CGdFigure *_this, void *CGdResource, uint16_t spell_id,
279 uint16_t figure_id)
280{
281 if ((_this->figures[figure_id].race != 0) && (_this->figures[figure_id].race < 7))
282 {
283 if (_this->figures[figure_id].owner != 0)
284 {
285 spell_id = spellAPI.getLeveledSpellID(CGdResource, spell_id, _this->figures[figure_id].level);
286 }
287 }
288 return spell_id;
289}
290
291void __attribute__((thiscall)) sf_click_horizontal_button(SF_CUiMain *_this,
292 uint_list_node *param1,
293 SF_UIElement *param2)
294{
295 uint16_t action_id = param2->actionType_id;
296 uint16_t subAction_id = param2->actionSubtype_id;
297 uint32_t unused;
298 uint16_t figure_id = ((*fun_00a28d60(param1, &unused, 0)) >> 8) & 0xffff;
299 if (action_id == 0)
300 {
301 action_id = param2->actionSubtype_id;
302 if (action_id < 9)
303 {
304 return;
305 }
306 if (action_id > 0xe)
307 {
308 return;
309 }
310 uint32_t general_address = (ASI::AddrOf(0x806a86));
312 *(uint32_t *)(general_address +
313 ((uint8_t)_this->CUiMain_data.CGdFigure->figures[figure_id].race * 4) + 2));
314 if (_this->CUiMain_data.unknown_action_type == 2)
315 {
316 return;
317 }
323 return;
324 }
325 if (action_id > 9999)
326 {
327 return;
328 }
329 SF_CGdResourceSpell spell_data;
330 spellAPI.getResourceSpellData(_this->CUiMain_data.CGdResource, &spell_data, subAction_id);
331 SF_CGdTargetData data;
332 data.entity_index = 0;
333 data.entity_type = 0;
334 data.position.X = 0;
335 data.position.Y = 0;
336
338 {
340 spell_data.spell_line_id))
341 {
344 fun_009de190(node, param1);
346 param2->actionSubtype_id, param2->unknown_flag,
347 param2->unknown_config_param);
348 return;
349 }
350 if (spell_data.cast_type2 == 5)
351 {
352 data.position.X =
353 _this->CUiMain_data.CGdFigure->figures[figure_id].position.X;
354 data.position.Y =
355 _this->CUiMain_data.CGdFigure->figures[figure_id].position.Y;
356 data.entity_type = 5;
357 }
358 else
359 {
360 data.entity_type = 1;
361 data.entity_index = figure_id;
362 }
365 fun_009de190(node, param1);
366 }
367 else
368 {
370 param2->actionSubtype_id, figure_id))
371 {
372 fun_0069f8d0((_this->CUiMain_data.CGdControllerClient), figure_id);
375 return;
376 }
377 if (!fun_006f8c06(_this->CUiMain_data.CGdFigureToolBox, figure_id,
378 param2->actionSubtype_id, figure_id, 1, 0,
379 1, 1, 1))
380 {
381 uint32_t *unknown_field = (uint32_t *)vfun41(_this);
382 fun_00910de0(unknown_field, _this, 0x140);
385 return;
386 }
387
388 data.entity_type = 1;
389 data.entity_index = figure_id;
390 }
392 param2->unknown_flag, param2->unknown_config_param, &data, 1,
393 1);
396 return;
397}
398
399
400
SpellFunctions * spellAPI
Definition TestMod.cpp:11
FigureFunctions * figureAPI
Definition TestMod.cpp:13
ToolboxFunctions * toolboxAPI
Definition TestMod.cpp:12
fun_009de190_ptr fun_009de190
new_operator_ptr g_new_operator
uint32_t g_menu_return_addr
fun_0086dd60_ptr fun_0086dd60
get_smth_fonts_ptr g_get_smth_fonts
fun_00910de0_ptr fun_00910de0
SFSF_ModlistStruct mod_struct
cuiVideoSequence_constructor_ptr cuiVideoSequence_constructor
fun_006a0140_ptr fun_006a0140
fun_0069fb90_ptr fun_0069fb90
uint32_t g_ui_hook_fix_addr
uint32_t g_ui_hook_fix_addr2
fun_006f8c06_ptr fun_006f8c06
fun_009a2790_ptr fun_009a2790
vfun163_ptr vfun163
get_font_ptr g_get_font
fun_00a49b10_ptr fun_00a49b10
fun_00a2a1d0_ptr fun_00a2ald0
menu_label_set_font_ptr g_menu_label_set_font
void sf_click_horizontal_button(SF_CUiMain *_this, uint_list_node *param1, SF_UIElement *param2)
vfun41_ptr vfun41
CMnuScreen_attach_control_ptr CMnuScreen_attach_control
void sf_menu_hook(uint32_t _CAppMenu)
void initialize_menu_data_hooks()
uint16_t sf_ui_overlay_fix(SF_CGdFigure *_this, void *CGdResource, uint16_t spell_id, uint16_t figure_id)
autoclass113_fun_00a27530_ptr fun_00a27530
fun_009a4020_ptr fun_009a4020
fun_009cd1f0_ptr fun_009cd1f0
bool hasThisAuraRunning(SF_CGdFigureToolbox *_this, uint16_t aura_spell_id, uint16_t figure_id)
autoclass113_fun_00a278c0_ptr fun_00a278c0
mnu_label_init_data_ptr g_init_menu_element
create_option_ptr f_create_menu_option
fun_009a0750_ptr fun_009a0750
fun_009a1fd0_ptr fun_009a1fd0
fun_0099f610_ptr fun_0099f610
fun_00a28d60_ptr fun_00a28d60
getSpellLineIsTargetSelf_ptr getSpellLineIsTargetSelf
vfun164_ptr vfun164
menu_label_set_string_ptr g_menu_label_set_string
menu_label_constructor_ptr g_menu_label_constructor
container_add_control_ptr g_container_add_control
void sf_click_vertical_button(SF_CUiMain *_this, uint16_t figure_id, uint8_t entity_type, uint16_t target_id, SF_UIElement *element)
set_label_flags_ptr g_set_label_flags
fun_0069f8d0_ptr fun_0069f8d0
CMnuLabel *__thiscall attach_new_label(CMnuLabel *label_ptr, CMnuContainer *parent, char *label_text, uint8_t font_index, uint16_t x_pos, uint16_t y_pos, uint16_t width, uint16_t height)
void __thiscall attach_new_button(CMnuContainer *parent, char *button_mesh_default, char *button_mesh_pressed, char *button_mesh_highlight, char *button_mesh_disabled, char *label_char, uint8_t font_index, uint16_t x_pos, uint16_t y_pos, uint16_t width, uint16_t height, int button_index, uint32_t callback_function_pointer)
void log_info(const char *message)
Definition sf_wrappers.c:89
void __fastcall show_mod_list_callback(CMnuSmpButton *button, int32_t *cui_menu_ptr_maybe)
int AddrOf(int offset)
returns "real" virtual address of given memory offset
Definition sf_asi.h:135
void(__thiscall * CMnuScreen_attach_control_ptr)(void *_CMnuScreen_ptr, CMnuBase *base, char flag)
void(__thiscall * autoclass113_fun_00a27530_ptr)(void *_this_autoclass113)
void(__thiscall * fun_00910de0_ptr)(void *_this, void *param1, uint32_t param2)
void(__thiscall * fun_009a4020_ptr)(void *_this, uint32_t param1)
void(__thiscall * fun_009a1fd0_ptr)(void *SF_CUiGame, uint32_t param1)
void(__thiscall * menu_label_constructor_ptr)(CMnuLabel *_this)
uint32_t(__thiscall * fun_0069f8d0_ptr)(void *_this, uint32_t p1)
void(__thiscall * menu_label_set_string_ptr)(CMnuLabel *_this, SF_String *string)
void(__fastcall * original_menu_func_ptr)(uint32_t param1)
void(__thiscall * mnu_label_init_data_ptr)(void *_this, float xpos, float ypos, float width, float height, SF_String *string)
void(__thiscall * fun_00a49b10_ptr)(CGdControllerClient *_this, uint8_t param1)
uint32_t(__thiscall * fun_0069fb90_ptr)(void *_this, uint16_t figure_id, uint8_t po2, uint16_t unkn_p3, SF_CGdTargetData *data, uint32_t p5, uint32_t p6)
@ TASK_MAINCHAR
SF_FontStruct *(__thiscall * get_smth_fonts_ptr)(void)
SF_String *(__thiscall * construct_default_sf_string_ptr)(SF_String *_this)
void *(__thiscall * vfun41_ptr)(void *CMnuContainer)
void(__thiscall * vfun164_ptr)(void *CMnuContainer)
void(__thiscall * fun_009cd1f0_ptr)(void *SF_CUiBottom, uint8_t param1)
void(__thiscall * autoclass113_fun_00a278c0_ptr)(void *_this_autoclass113, uint32_t p1)
SF_Font *(__thiscall * get_font_ptr)(SF_FontStruct *_this, uint32_t font_id)
void(__thiscall * menu_label_set_font_ptr)(void *_this, SF_Font *font)
void(__thiscall * vfun163_ptr)(void *CMnuContainer, uint8_t param1)
void(__thiscall * menu_label_ptr)(CMnuLabel *_this)
void(__thiscall * fun_0099f610_ptr)(void *_this, uint16_t param1, uint16_t param2, uint8_t param3, uint16_t param4)
uint32_t(__thiscall * fun_006a0140_ptr)(void *_this, uint16_t p1, SF_CGdTargetData *p2_ptr, uint8_t p3, uint8_t p4)
void(__thiscall * message_box_ptr)(uint32_t CAppMenu, uint16_t description_id, SF_String *string_ptr, uint16_t hasOffset)
bool(__thiscall * getSpellLineIsTargetSelf_ptr)(void *_this, uint16_t spell_line_id)
uint32_t *(__thiscall * fun_00a28d60_ptr)(void *_this, void *param1, uint32_t param2)
void *(__cdecl * new_operator_ptr)(uint32_t param_1)
uint32_t *(__thiscall * fun_0086dd60_ptr)(void *_this, uint8_t p1, uint32_t p2)
uint16_t(__cdecl * fun_00a2a1d0_ptr)(void *some_ptr, void *some_ptr_2)
void(__thiscall * menu_label_set_data_ptr)(CMnuLabel *_this, uint32_t color_red, uint32_t color_green, uint32_t color_blue, uint8_t unknchar)
void(__thiscall * initialize_menu_container_ptr)(CMnuContainer *_this)
void(__thiscall * set_label_flags_ptr)(CMnuLabel *_this, uint32_t flags)
uint32_t(__thiscall * fun_006f8c06_ptr)(SF_CGdFigureToolbox *_this, uint16_t figure_id, uint16_t spell_id, uint32_t target_id, uint8_t param4, uint32_t param5, uint32_t param6, uint32_t param7, uint32_t param8)
CUiOption *(__thiscall * create_option_ptr)(CUiOption *_this)
void *(__thiscall * fun_009de190_ptr)(void *_this, void *param_1)
uint32_t(__thiscall * cuiVideoSequence_constructor_ptr)(SF_CUiVideo *_this, SF_String *p1)
void *(__thiscall * fun_009a0750_ptr)(void *_this)
void(__thiscall * container_add_control_ptr)(CMnuContainer *_this, CMnuBase *CMnubase, char c1, char c2, uint32_t p4)
void(__thiscall * fun_009a2790_ptr)(void *_this, void *_p1, uint32_t p2)
CMnuLabel * sfsf_version_label
int g_mod_count
int g_error_count
SFMod * g_framework_mod
SF_CGdFigureToolbox * CGdFigureToolBox
SF_CGdFigure * CGdFigure
uint8_t unkn5[0x2A4]
CGdControllerClient * CGdControllerClient
isFlagSet_ptr isFlagSet
getSpellJobStartNode_ptr getSpellJobStartNode
A structure for the global list of figures and related statistics for them.
GdFigure figures[2000]
CUiMain_data CUiMain_data
char mod_version[24]
getResourceSpellData_ptr getResourceSpellData
hasSpellTag_ptr hasSpellTag
Checks if a spell has a specific tag.
getLeveledSpellID_ptr getLeveledSpellID
getSpellID_ptr getSpellID
Retrieves the Spell Effect ID for a given spell index. The spell effect ID can be used to obtain spel...
getNextNode_ptr getNextNode
getSpellIndexFromDLL_ptr getSpellIndexFromDLL
uint32_t * post_last