Spellforce-Spell-framework
Loading...
Searching...
No Matches
sf_menu_hook.c
Go to the documentation of this file.
1
9
10#include "../sf_wrappers.h"
11#include "../sf_ui_wrappers.h"
12#include "sf_menu_hook.h"
13#include "../sf_hooks.h"
14#include "sf_campaign_hook.h"
15#include "../sf_modloader.h"
17
18#include <stdint.h>
19#include <stdlib.h>
20#include <stdio.h>
21#include <string.h>
22
23
24static menu_label_ptr s_initialize_menu_label;
25static initialize_menu_container_ptr s_initialize_menu_container;
26static original_menu_func_ptr s_menu_func;
27static construct_default_sf_string_ptr s_construct_default_sf_string;
28static message_box_ptr s_show_message_box;
29
30
40
59
64
65
67{
68 s_initialize_menu_label = (menu_label_ptr)(ASI::AddrOf(0x51a180));
69 s_initialize_menu_container = (initialize_menu_container_ptr)(ASI::AddrOf(0x505780));
70 s_construct_default_sf_string = (construct_default_sf_string_ptr)(ASI::AddrOf(0x383900));
71 s_menu_func = (original_menu_func_ptr)(ASI::AddrOf(0x197b10));
72 s_show_message_box = (message_box_ptr)(ASI::AddrOf(0x198660));
73
75 g_menu_return_addr = (ASI::AddrOf(0x182799));
76 g_ui_hook_fix_addr = (ASI::AddrOf(0x5D119E));
77 g_ui_hook_fix_addr2 = (ASI::AddrOf(0x5d0a7e));
78
79 g_sf_enchant_addr = (ASI::AddrOf(0x5d0bbd));
80 g_sf_enchant_addr2 = (ASI::AddrOf(0x5d12e7));
81
83
93
103
104 vfun163 = (vfun163_ptr)(ASI::AddrOf(0x513C80));
105 vfun164 = (vfun164_ptr)(ASI::AddrOf(0x50F8B0));
106 vfun41 = (vfun41_ptr)(ASI::AddrOf(0x510d70));
107
109
112}
113
116
119
120void __attribute__((no_caller_saved_registers, thiscall))
121sf_menu_hook(uint32_t _CAppMenu)
122{
123 log_info("Starting Menu Hook");
124
126
128
129 char sfsf_info[256];
130 snprintf(sfsf_info, sizeof(sfsf_info),
131 "Spell Framework %s\n%d Mod(s) Loaded with %d Error(s)",
133
134 CMnuContainer *container = *(CMnuContainer **)(_CAppMenu + 0x58);
135
136 sfsf_version_label = uiAPI.attachLabel(sfsf_version_label, container, sfsf_info,
137 6, 10, 729, strlen(sfsf_info) * 4, 100);
138
139 char button_default[32] = "ui_mainmenu_button_default.msh";
140 char button_pressed[32] = "ui_mainmenu_button_pressed.msh";
141 char button_disabled[32] = "ui_mainmenu_button_disabled.msh";
142 char button_highlight[32] = "";
143 char button_label[32] = "SHOW MOD LIST";
144
145 mod_struct.toggle = 0;
146 mod_struct.index = 0;
147
148 log_info("Adding Mod List Button");
149
150 const int BUTTON_INDEX = 15;
151 const int BUTTON_X = 822;
152 const int BUTTON_Y = 705;
153 const int BUTTON_WIDTH = 192;
154 const int BUTTON_HEIGHT = 36;
155 const int BUTTON_FONT_INDEX = 7;
156
157 show_mod_list_button = uiAPI.attachNewButton(container,
158 button_default,
159 button_pressed,
160 button_highlight,
161 button_disabled,
162 button_label,
163 BUTTON_FONT_INDEX,
164 BUTTON_X,
165 BUTTON_Y,
166 BUTTON_WIDTH,
167 BUTTON_HEIGHT,
168 BUTTON_INDEX,
169 (uint32_t)&show_mod_list);
170
171 if (g_campaign_count > 0)
172 {
173 char campaign_label[32] = "CUSTOM CAMPAIGNS";
174 open_campaign_screen = uiAPI.attachNewButton(container,
175 button_default,
176 button_pressed,
177 button_highlight,
178 button_disabled,
179 campaign_label,
180 BUTTON_FONT_INDEX,
181 BUTTON_X,
182 BUTTON_Y - 44, // one slot above mod list
183 BUTTON_WIDTH,
184 BUTTON_HEIGHT,
185 16,
186 (uint32_t)&show_custom_campaign_screen);
187 }
188
189 s_menu_func(_CAppMenu);
190}
191
192bool hasThisAuraRunning(SF_CGdFigureToolbox *_this, uint16_t aura_spell_id, uint16_t figure_id)
193{
194 if (figureAPI.isAlive(_this->CGdFigure, figure_id))
195 {
196 if (figureAPI.isFlagSet(_this->CGdFigure, figure_id, AURA_RUNNING))
197 {
198 uint16_t node_id = figureAPI.getSpellJobStartNode(_this->CGdFigure,
199 figure_id);
200 while (node_id != 0)
201 {
202 uint16_t spell_index = toolboxAPI.getSpellIndexFromDLL(_this->CGdDoubleLinkedList, node_id);
203 uint16_t spell_id = spellAPI.getSpellID(_this->CGdSpell, spell_index);
204 if (spell_id == aura_spell_id)
205 {
206 return 1;
207 }
208 node_id = toolboxAPI.getNextNode(_this->CGdDoubleLinkedList, node_id);
209 }
210 }
211 }
212 return false;
213}
214
215// CUiMain::FUN_009e6840
216void __attribute__((thiscall)) sf_click_vertical_button(SF_CUiMain *_this,
217 uint16_t figure_id,
218 uint8_t entity_type,
219 uint16_t target_id,
220 SF_UIElement *element)
221{
222 uint16_t actionID = element->actionType_id;
223 uint16_t subActionID = element->actionSubtype_id;
224 uint32_t _figure_id = figure_id;
225 if ((actionID == 10000) || (actionID == 10001) || (actionID == 10002))
226 {
227 uint_list_node ac113;
228 fun_00a27530(&ac113);
229 uint32_t *puvar5 = fun_0086dd60(&_figure_id, 1, _figure_id & 0xffff);
230 fun_00a278c0(&ac113, *puvar5);
231 SF_CGdTargetData data;
232 data.entity_index = target_id;
233 data.entity_type = entity_type;
234 data.position.X = 0;
235 data.position.Y = 0;
236 uint32_t uVar3 = fun_00a2ald0(&ac113, _this->CUiMain_data.CGdControllerClient);
237 fun_006a0140(_this->CUiMain_data.CGdControllerClient, uVar3, &data, 0,
238 0);
239 if (ac113.first != 0)
240 {
241 fun_009a2790(&ac113, ac113.first, ((uint32_t)ac113.post_last - (uint32_t)ac113.first) >> 2);
242 return;
243 }
244 }
245 if ((actionID != 0) && (actionID < 10000))
246 {
247 if (spellAPI.hasSpellTag(actionID, SpellTag::AURA_SPELL) ||
248 spellAPI.hasSpellTag(actionID, SpellTag::SIEGE_AURA_SPELL))
249 {
250 if (hasThisAuraRunning(_this->CUiMain_data.CGdFigureToolBox, subActionID, figure_id))
251 {
253 return;
254 }
255 }
257 SF_CGdTargetData data;
258 data.entity_index = target_id;
259 data.entity_type = entity_type;
260 data.position.X = 0;
261 data.position.Y = 0;
262 uint32_t some_flag = 0;
263 if (task == TASK_MAINCHAR)
264 {
265 some_flag = (uint32_t)(*(uint32_t *)&(_this->CUiMain_data.unkn5[0x2A0]) == 2);
266 }
268 element->unknown_flag, element->unknown_config_param,
269 &data, some_flag, 0);
270 }
271}
272
273uint16_t __attribute__((thiscall)) sf_ui_overlay_fix(SF_CGdFigure *_this, void *CGdResource, uint16_t spell_id,
274 uint16_t figure_id)
275{
276 if ((_this->figures[figure_id].race != 0) && (_this->figures[figure_id].race < 7))
277 {
278 if (_this->figures[figure_id].owner != 0)
279 {
280 spell_id = spellAPI.getLeveledSpellID(CGdResource, spell_id, _this->figures[figure_id].level);
281 }
282 }
283 return spell_id;
284}
285
286void __attribute__((thiscall)) sf_click_horizontal_button(SF_CUiMain *_this,
287 uint_list_node *param1,
288 SF_UIElement *param2)
289{
290 uint16_t action_id = param2->actionType_id;
291 uint16_t subAction_id = param2->actionSubtype_id;
292 uint32_t unused;
293 uint16_t figure_id = ((*fun_00a28d60(param1, &unused, 0)) >> 8) & 0xffff;
294 if (action_id == 0)
295 {
296 action_id = param2->actionSubtype_id;
297 if (action_id < 9)
298 {
299 return;
300 }
301 if (action_id > 0xe)
302 {
303 return;
304 }
305 uint32_t general_address = (ASI::AddrOf(0x806a86));
307 *(uint32_t *)(general_address +
308 ((uint8_t)_this->CUiMain_data.CGdFigure->figures[figure_id].race * 4) + 2));
309 if (_this->CUiMain_data.unknown_action_type == 2)
310 {
311 return;
312 }
318 return;
319 }
320 if (action_id > 9999)
321 {
322 return;
323 }
324 SF_CGdResourceSpell spell_data;
325 spellAPI.getResourceSpellData(_this->CUiMain_data.CGdResource, &spell_data, subAction_id);
326 SF_CGdTargetData data;
327 data.entity_index = 0;
328 data.entity_type = 0;
329 data.position.X = 0;
330 data.position.Y = 0;
331
332 if ((!spellAPI.hasSpellTag(spell_data.spell_line_id, SpellTag::AURA_SPELL)) &&
333 (!spellAPI.hasSpellTag(spell_data.spell_line_id, SpellTag::SIEGE_AURA_SPELL)))
334 {
336 {
338 fun_009de190(node, param1);
340 param2->actionSubtype_id, param2->unknown_flag,
341 param2->unknown_config_param);
342 return;
343 }
344 if (spell_data.cast_type2 == 5)
345 {
346 data.position.X = _this->CUiMain_data.CGdFigure->figures[figure_id].position.X;
347 data.position.Y = _this->CUiMain_data.CGdFigure->figures[figure_id].position.Y;
348 data.entity_type = 5;
349 }
350 else
351 {
352 data.entity_type = 1;
353 data.entity_index = figure_id;
354 }
356 fun_009de190(node, param1);
357 }
358 else
359 {
361 param2->actionSubtype_id, figure_id))
362 {
363 fun_0069f8d0((_this->CUiMain_data.CGdControllerClient), figure_id);
366 return;
367 }
368 if (!fun_006f8c06(_this->CUiMain_data.CGdFigureToolBox, figure_id,
369 param2->actionSubtype_id, figure_id, 1, 0,
370 1, 1, 1))
371 {
372 uint32_t *unknown_field = (uint32_t *)vfun41(_this);
373 fun_00910de0(unknown_field, _this, 0x140);
376 return;
377 }
378
379 data.entity_type = 1;
380 data.entity_index = figure_id;
381 }
383 param2->unknown_flag, param2->unknown_config_param, &data, 1,
384 1);
387 return;
388}
389
390
391
SpellFunctions * spellAPI
Definition TestMod.cpp:11
FigureFunctions * figureAPI
Definition TestMod.cpp:13
ToolboxFunctions * toolboxAPI
Definition TestMod.cpp:12
uint32_t g_campaign_count
void __thiscall show_custom_campaign_screen(CMnuSmpButton *_this)
Builds the campaign screen.
void campaign_hook_on_main_menu(CAppMenu *app_menu)
UiFunctions uiAPI
Definition sf_hooks.c:50
fun_009de190_ptr fun_009de190
uint32_t g_menu_return_addr
fun_0086dd60_ptr fun_0086dd60
fun_00910de0_ptr fun_00910de0
SFSF_ModlistStruct mod_struct
cuiVideoSequence_constructor_ptr cuiVideoSequence_constructor
fun_006a0140_ptr fun_006a0140
CMnuSmpButton * open_campaign_screen
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
fun_00a49b10_ptr fun_00a49b10
fun_00a2a1d0_ptr fun_00a2ald0
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()
CMnuLabel * sfsf_version_label
uint32_t g_sf_enchant_addr2
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
uint32_t g_sf_enchant_addr
fun_009cd1f0_ptr fun_009cd1f0
bool hasThisAuraRunning(SF_CGdFigureToolbox *_this, uint16_t aura_spell_id, uint16_t figure_id)
CMnuSmpButton * show_mod_list_button
autoclass113_fun_00a278c0_ptr fun_00a278c0
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
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
void log_info(const char *format,...)
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)
uint32_t(__thiscall * fun_0069f8d0_ptr)(void *_this, uint32_t p1)
void(__fastcall * original_menu_func_ptr)(uint32_t param1)
void(__thiscall * fun_00a49b10_ptr)(CGdControllerClient *_this, uint8_t param1)
@ SIEGE_AURA_SPELL
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)
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)
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)
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 * 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 * fun_009a2790_ptr)(void *_this, void *_p1, uint32_t p2)
int g_mod_count
int g_error_count
SFMod * g_framework_mod
void reset_mod_list_screen()
Drops every cached mod list pointer, this will ensure we don't crash after a map load.
void __thiscall show_mod_list(CMnuSmpButton *button)
SF_CGdFigureToolbox * CGdFigureToolBox
SF_CGdFigure * CGdFigure
CGdControllerClient * CGdControllerClient
FigureJobData current_job
A structure for the global list of figures and related statistics for them.
GdFigure figures[2000]
CUiMain_data CUiMain_data