Spellforce-Spell-framework
Loading...
Searching...
No Matches
sf_vanilla_fix_hook.c
Go to the documentation of this file.
1#include "../sf_wrappers.h"
5#define _USE_MATH_DEFINES
6#include <math.h>
7#include <vector>
8
10#include "sf_endspell_hook.h"
11
19extern AiFunctions aiAPI;
20extern UiFunctions uiAPI;
21
22typedef void (__thiscall *add_item_ptr)(ushort_list_node *_this,uint16_t *item);
24
25typedef SF_String *(__thiscall *AC95_get_figure_name_ptr)(void *AC95, SF_String *name_buffer, uint32_t figure_id);
26typedef void (__cdecl *GetColoredText_ptr)(SF_String *param_1, uint32_t param_2);
27typedef void (__thiscall *GetDescriptionText_ptr)(void *_this,uint32_t param_1,SF_String *name_buffer);
28typedef void (__thiscall *GetTextById_ptr)(void *_this,uint16_t text_id,SF_String *out_string);
29typedef SF_String *(__thiscall *ExpandSpellDescription_ptr)(AutoClass101 *_this, SF_String *out_string,
30 SF_String *in_string, SF_CGdResourceSpell *param_3);
31
32typedef SF_String *(__thiscall *GetItemInfo_ptr)(SF_CGdResource *_this, CGdResourceWeaponData *stats,
33 uint16_t item_id);
34typedef uint8_t (__thiscall *GetWeaponType_ptr)(SF_CGdResource *_this, uint16_t item_id);
35typedef uint32_t (__thiscall *GetDamageMultiplierPerLevel_ptr)(SF_CGdResource *_this, uint8_t level);
36typedef uint16_t *(__thiscall *GetWeaponEffects_ptr)(SF_CGdResource *_this, uint16_t *param_1, uint16_t item_id);
37typedef uint32_t (__thiscall *AC34calculateWeaponSpeed_ptr) (void *_this,uint32_t base_fight_speed,uint8_t race,
38 uint16_t item_id, uint32_t dual_wield,uint32_t is_ranged);
39typedef void *(__thiscall *CGdMainGetAC34_ptr)(void *_this);
40
41typedef SF_String *(__cdecl *getSpecialDesc_ptr)(SF_String *param_1,uint32_t param_2);
42typedef void (__stdcall *getWeaponRangeDescription_ptr)(SF_String *param_1, uint16_t param_2,uint16_t param_3,
43 SF_String *param_4, uint8_t param_5);
44
45typedef uint32_t (__thiscall *GetResourceSpellLine_ptr)(SF_CGdResource *_this, uint16_t spell_line_id,
47
48typedef uint16_t (__thiscall *getUnitStringID_ptr)(SF_CGdResource *_this,uint16_t unit_id);
49typedef bool (__thiscall *getTextString_ptr)(SF_CGdResource *_this,uint16_t text_id,char *out_string);
50
51typedef void (__thiscall *onFigureBattleEnd_ptr)(SF_CGdFigureToolbox *_this, uint16_t figure_id);
52
56
71
72
74 uint32_t angle, uint16_t *ranges, uint32_t target_count,
75 ushort_list_node *output)
76{
78 uint16_t next_figure = 0;
79 SF_Coord source_pos = _this->CGdFigure->figures[source->entity_index].position;
80 SF_Coord target_pos = target->position;
81 // log_info("Salvo source_pos X: %d, Y: %d ", source_pos.X, source_pos.Y);
82 // log_info("Salvo target_pos X: %d, Y: %d ", target_pos.X, target_pos.Y);
83
84 uint32_t distance = toolboxAPI.getDistance(&source_pos, &target_pos);
85
86 uint32_t radius = (uint32_t)round((distance << 10) * tan((angle*M_PI_2)/180)) >> 10;
87 // log_info("Salvo distance %d, radius %d, angle %d", distance, radius, angle);
88 uint16_t min_range = ranges[0];
89 uint16_t max_range = ranges[1];
90 // log_info("Salvo min range %d, max range %d", min_range, max_range);
91
92 output->data = output->first;
93 iteratorAPI.figureIteratorInit(&iter, 0, 0, 0x3ff, 0x3ff);
94 iteratorAPI.figureIteratorSetPointers(&iter, _this->CGdFigure, _this->AutoClass22, _this->CGdWorld);
95 iteratorAPI.iteratorSetArea(&iter, &target_pos, radius);
96 next_figure = iteratorAPI.getNextFigure(&iter);
97 while ((next_figure != 0) && (target_count != 0))
98 {
99 SF_Coord secondary_pos = _this->CGdFigure->figures[next_figure].position;
100 distance = toolboxAPI.getDistance(&source_pos, &secondary_pos);
101 if ((distance > min_range) && (distance < max_range))
102 {
103 if (toolboxAPI.figuresCheckHostile(_this->CGdFigureToolBox, source->entity_index, next_figure))
104 {
105 add_item(output, &next_figure);
106 target_count--;
107 }
108 }
109 next_figure = iteratorAPI.getNextFigure(&iter);
110 }
111 iteratorAPI.disposeFigureIterator(&iter);
112 return (((uint32_t)output->data - (uint32_t)output->first) != 0);
113}
114
115uint16_t __thiscall get_figure_statistic_max_hp(SF_CGdFigure *_this, uint16_t figure_id)
116{
117 int32_t base_val = _this->figures[figure_id].health.base_val;
118 int32_t bonus_val = _this->figures[figure_id].health.bonus_val;
119 int32_t total_flat = base_val+bonus_val;
120 uint16_t result = 1;
121 if (total_flat >= 0)
122 {
123 int16_t multiplier = _this->figures[figure_id].health.bonus_multiplier + 100;
124 (multiplier < 0) ? (multiplier = 1) : (multiplier);
125 result = (uint16_t)((total_flat * multiplier) / 100);
126 }
127 (result == 0) ? (result = 1) : (result);
128 return result;
129}
130
131uint16_t __thiscall get_figure_statistic_max_mp(SF_CGdFigure *_this, uint16_t figure_id)
132{
133 int32_t base_val = _this->figures[figure_id].mana.base_val;
134 int32_t bonus_val = _this->figures[figure_id].mana.bonus_val;
135 int32_t total_flat = base_val+bonus_val;
136 uint16_t result = 1;
137 if (total_flat >= 0)
138 {
139 int16_t multiplier = _this->figures[figure_id].mana.bonus_multiplier + 100;
140 (multiplier < 0) ? (multiplier = 1) : (multiplier);
141 result = (uint16_t)((total_flat * multiplier) / 100);
142 }
143 (result == 0) ? (result = 1) : (result);
144 return result;
145}
146
147uint16_t __thiscall get_figure_statistic_max_sta(SF_CGdFigure *_this, uint16_t figure_id)
148{
149 int32_t base_val = _this->figures[figure_id].stamina.base_val;
150 int32_t bonus_val = _this->figures[figure_id].stamina.bonus_val;
151 int32_t total_flat = base_val+bonus_val;
152 uint16_t result = 1;
153 if (total_flat >= 0)
154 {
155 int16_t multiplier = _this->figures[figure_id].stamina.bonus_multiplier + 100;
156 (multiplier < 0) ? (multiplier = 1) : (multiplier);
157 result = (uint16_t)((total_flat * multiplier) / 100);
158 }
159 (result == 0) ? (result = 1) : (result);
160 return result;
161}
162
163uint16_t __thiscall get_figure_statistic_current_ac(SF_CGdFigure *_this, uint16_t figure_id)
164{
165 int32_t base_val = _this->figures[figure_id].armor.base_val;
166 int32_t bonus_val = _this->figures[figure_id].armor.bonus_val;
167 int32_t total_flat = base_val+bonus_val;
168 uint16_t result = 1;
169 if (total_flat >= 0)
170 {
171 int16_t multiplier = _this->figures[figure_id].armor.bonus_multiplier + 100;
172 (multiplier < 0) ? (multiplier = 1) : (multiplier);
173 result = (uint16_t)((total_flat * multiplier) / 100);
174 }
175 (result == 0) ? (result = 1) : (result);
176 return result;
177}
178
179uint16_t __thiscall get_figure_statistic_current_agi(SF_CGdFigure *_this, uint16_t figure_id)
180{
181 int32_t base_val = _this->figures[figure_id].agility.base_val;
182 int32_t bonus_val = _this->figures[figure_id].agility.bonus_val;
183 int32_t total_flat = base_val+bonus_val;
184 uint16_t result = 1;
185 if (total_flat >= 0)
186 {
187 int16_t multiplier = _this->figures[figure_id].agility.bonus_multiplier + 100;
188 (multiplier < 0) ? (multiplier = 1) : (multiplier);
189 result = (uint16_t)((total_flat * multiplier) / 100);
190 }
191 (result == 0) ? (result = 1) : (result);
192 return result;
193}
194
195uint16_t __thiscall get_figure_statistic_current_cha(SF_CGdFigure *_this, uint16_t figure_id)
196{
197 int32_t base_val = _this->figures[figure_id].charisma.base_val;
198 int32_t bonus_val = _this->figures[figure_id].charisma.bonus_val;
199 int32_t total_flat = base_val+bonus_val;
200 uint16_t result = 1;
201 if (total_flat >= 0)
202 {
203 int16_t multiplier = _this->figures[figure_id].charisma.bonus_multiplier + 100;
204 (multiplier < 0) ? (multiplier = 1) : (multiplier);
205 result = (uint16_t)((total_flat * multiplier) / 100);
206 }
207 (result == 0) ? (result = 1) : (result);
208 return result;
209}
210
211uint16_t __thiscall get_figure_statistic_current_dex(SF_CGdFigure *_this, uint16_t figure_id)
212{
213 int32_t base_val = _this->figures[figure_id].dexterity.base_val;
214 int32_t bonus_val = _this->figures[figure_id].dexterity.bonus_val;
215 int32_t total_flat = base_val+bonus_val;
216 uint16_t result = 1;
217 if (total_flat >= 0)
218 {
219 int16_t multiplier = _this->figures[figure_id].dexterity.bonus_multiplier + 100;
220 (multiplier < 0) ? (multiplier = 1) : (multiplier);
221 result = (uint16_t)((total_flat * multiplier) / 100);
222 }
223 (result == 0) ? (result = 1) : (result);
224 return result;
225}
226
227uint16_t __thiscall get_figure_statistic_current_hp(SF_CGdFigure *_this, uint16_t figure_id)
228{
229 int32_t base_val = _this->figures[figure_id].health.base_val;
230 int32_t bonus_val = _this->figures[figure_id].health.bonus_val;
231 int32_t total_flat = base_val+bonus_val;
232 uint16_t result = 0;
233 if (total_flat >= 0)
234 {
235 int16_t multiplier = _this->figures[figure_id].health.bonus_multiplier + 100;
236 uint16_t missing_val = _this->figures[figure_id].health.missing_val;
237 (multiplier < 0) ? (multiplier = 1) : (multiplier);
238 result = (uint16_t)((total_flat * multiplier) / 100);
239 (result - missing_val < 0) ? (result = 0) : (result -= missing_val);
240 }
241 return result;
242}
243
244uint16_t __thiscall get_figure_statistic_current_int(SF_CGdFigure *_this, uint16_t figure_id)
245{
246 int32_t base_val = _this->figures[figure_id].intelligence.base_val;
247 int32_t bonus_val = _this->figures[figure_id].intelligence.bonus_val;
248 int32_t total_flat = base_val+bonus_val;
249 uint16_t result = 1;
250 if (total_flat >= 0)
251 {
252 int16_t multiplier = _this->figures[figure_id].intelligence.bonus_multiplier + 100;
253 (multiplier < 0) ? (multiplier = 1) : (multiplier);
254 result = (uint16_t)((total_flat * multiplier) / 100);
255 }
256 (result == 0) ? (result = 1) : (result);
257 return result;
258}
259
260uint16_t __thiscall get_figure_statistic_current_mp(SF_CGdFigure *_this, uint16_t figure_id)
261{
262 int32_t base_val = _this->figures[figure_id].mana.base_val;
263 int32_t bonus_val = _this->figures[figure_id].mana.bonus_val;
264 int32_t total_flat = base_val+bonus_val;
265 uint16_t result = 0;
266 if (total_flat >= 0)
267 {
268 int16_t multiplier = _this->figures[figure_id].mana.bonus_multiplier + 100;
269 uint16_t missing_val = _this->figures[figure_id].mana.missing_val;
270 (multiplier < 0) ? (multiplier = 1) : (multiplier);
271 result = (uint16_t)((total_flat * multiplier) / 100);
272 (result - missing_val < 0) ? (result = 0) : (result -= missing_val);
273 }
274 return result;
275}
276
277uint16_t __thiscall get_figure_statistic_current_sta(SF_CGdFigure *_this, uint16_t figure_id)
278{
279 int32_t base_val = _this->figures[figure_id].stamina.base_val;
280 int32_t bonus_val = _this->figures[figure_id].stamina.bonus_val;
281 int32_t total_flat = base_val+bonus_val;
282 uint16_t result = 1;
283 if (total_flat >= 0)
284 {
285 int16_t multiplier = _this->figures[figure_id].stamina.bonus_multiplier + 100;
286 uint16_t missing_val = _this->figures[figure_id].stamina.missing_val;
287 (multiplier < 0) ? (multiplier = 1) : (multiplier);
288 result = (uint16_t)((total_flat * multiplier) / 100);
289 (result - missing_val < 0) ? (result = 1) : (result -= missing_val);
290 }
291 return result;
292}
293
294uint16_t __thiscall get_figure_statistic_current_str(SF_CGdFigure *_this, uint16_t figure_id)
295{
296 int32_t base_val = _this->figures[figure_id].strength.base_val;
297 int32_t bonus_val = _this->figures[figure_id].strength.bonus_val;
298 int32_t total_flat = base_val+bonus_val;
299 uint16_t result = 1;
300 if (total_flat >= 0)
301 {
302 int16_t multiplier = _this->figures[figure_id].strength.bonus_multiplier + 100;
303 (multiplier < 0) ? (multiplier = 1) : (multiplier);
304 result = (uint16_t)((total_flat * multiplier) / 100);
305 }
306 (result == 0) ? (result = 1) : (result);
307 return result;
308}
309
310uint16_t __thiscall get_figure_statistic_current_wis(SF_CGdFigure *_this, uint16_t figure_id)
311{
312 int32_t base_val = _this->figures[figure_id].wisdom.base_val;
313 int32_t bonus_val = _this->figures[figure_id].wisdom.bonus_val;
314 int32_t total_flat = base_val+bonus_val;
315 uint16_t result = 1;
316 if (total_flat >= 0)
317 {
318 int16_t multiplier = _this->figures[figure_id].wisdom.bonus_multiplier + 100;
319 (multiplier < 0) ? (multiplier = 1) : (multiplier);
320 result = (uint16_t)((total_flat * multiplier) / 100);
321 }
322 (result == 0) ? (result = 1) : (result);
323 return result;
324}
325
326uint16_t __thiscall get_figure_statistic_current_fire_res(SF_CGdFigure *_this, uint16_t figure_id)
327{
328 int32_t base_val = _this->figures[figure_id].resistance_fire.base_val;
329 int32_t bonus_val = _this->figures[figure_id].resistance_fire.bonus_val;
330 int32_t total_flat = base_val+bonus_val;
331 uint16_t result = 1;
332 if (total_flat >= 0)
333 {
334 int16_t multiplier = _this->figures[figure_id].resistance_fire.bonus_multiplier + 100;
335 (multiplier < 0) ? (multiplier = 1) : (multiplier);
336 result = (uint16_t)((total_flat * multiplier) / 100);
337 }
338 (result == 0) ? (result = 1) : (result);
339 return result;
340}
341
342uint16_t __thiscall get_figure_statistic_current_ice_res(SF_CGdFigure *_this, uint16_t figure_id)
343{
344 int32_t base_val = _this->figures[figure_id].resistance_ice.base_val;
345 int32_t bonus_val = _this->figures[figure_id].resistance_ice.bonus_val;
346 int32_t total_flat = base_val+bonus_val;
347 uint16_t result = 1;
348 if (total_flat >= 0)
349 {
350 int16_t multiplier = _this->figures[figure_id].resistance_ice.bonus_multiplier + 100;
351 (multiplier < 0) ? (multiplier = 1) : (multiplier);
352 result = (uint16_t)((total_flat * multiplier) / 100);
353 }
354 (result == 0) ? (result = 1) : (result);
355 return result;
356}
357
358uint16_t __thiscall get_figure_statistic_current_mental_res(SF_CGdFigure *_this, uint16_t figure_id)
359{
360 int32_t base_val = _this->figures[figure_id].resistance_mental.base_val;
361 int32_t bonus_val = _this->figures[figure_id].resistance_mental.bonus_val;
362 int32_t total_flat = base_val+bonus_val;
363 uint16_t result = 1;
364 if (total_flat >= 0)
365 {
366 int16_t multiplier = _this->figures[figure_id].resistance_mental.bonus_multiplier + 100;
367 (multiplier < 0) ? (multiplier = 1) : (multiplier);
368 result = (uint16_t)((total_flat * multiplier) / 100);
369 }
370 (result == 0) ? (result = 1) : (result);
371 return result;
372}
373
374uint16_t __thiscall get_figure_statistic_current_black_res(SF_CGdFigure *_this, uint16_t figure_id)
375{
376 int32_t base_val = _this->figures[figure_id].resistance_black.base_val;
377 int32_t bonus_val = _this->figures[figure_id].resistance_black.bonus_val;
378 int32_t total_flat = base_val+bonus_val;
379 uint16_t result = 1;
380 if (total_flat >= 0)
381 {
382 int16_t multiplier = _this->figures[figure_id].resistance_black.bonus_multiplier + 100;
383 (multiplier < 0) ? (multiplier = 1) : (multiplier);
384 result = (uint16_t)((total_flat * multiplier) / 100);
385 }
386 (result == 0) ? (result = 1) : (result);
387 return result;
388}
389
390uint16_t __thiscall get_figure_statistic_current_walk_spd(SF_CGdFigure *_this, uint16_t figure_id)
391{
392 int32_t base_val = _this->figures[figure_id].walk_speed.base_val;
393 int32_t bonus_val = _this->figures[figure_id].walk_speed.bonus_val;
394 int32_t total_flat = base_val+bonus_val;
395 uint16_t result = 1;
396 if (total_flat >= 0)
397 {
398 int16_t multiplier = _this->figures[figure_id].walk_speed.bonus_multiplier + 100;
399 (multiplier < 0) ? (multiplier = 1) : (multiplier);
400 result = (uint16_t)((total_flat * multiplier) / 100);
401 }
402 (result == 0) ? (result = 1) : (result);
403 return result;
404}
405
406uint16_t __thiscall get_figure_statistic_current_fight_spd(SF_CGdFigure *_this, uint16_t figure_id)
407{
408 int32_t base_val = _this->figures[figure_id].fight_speed.base_val;
409 int32_t bonus_val = _this->figures[figure_id].fight_speed.bonus_val;
410 int32_t total_flat = base_val+bonus_val;
411 uint16_t result = 1;
412 if (total_flat >= 0)
413 {
414 int16_t multiplier = _this->figures[figure_id].fight_speed.bonus_multiplier + 100;
415 (multiplier < 0) ? (multiplier = 1) : (multiplier);
416 result = (uint16_t)((total_flat * multiplier) / 100);
417 }
418 (result == 0) ? (result = 1) : (result);
419 return result;
420}
421
422uint16_t __thiscall get_figure_statistic_current_cast_spd(SF_CGdFigure *_this, uint16_t figure_id)
423{
424 int32_t base_val = _this->figures[figure_id].cast_speed.base_val;
425 int32_t bonus_val = _this->figures[figure_id].cast_speed.bonus_val;
426 int32_t total_flat = base_val+bonus_val;
427 uint16_t result = 1;
428 if (total_flat >= 0)
429 {
430 int16_t multiplier = _this->figures[figure_id].cast_speed.bonus_multiplier + 100;
431 (multiplier < 0) ? (multiplier = 1) : (multiplier);
432 result = (uint16_t)((total_flat * multiplier) / 100);
433 }
434 (result == 0) ? (result = 1) : (result);
435 return result;
436}
437
438uint8_t __thiscall getEffectiveRace(SF_CGdFigure *_this, uint16_t figure_id)
439{
440 uint16_t master_id = _this->figures[figure_id].master_figure;
441
442 while (master_id != 0)
443 {
444 if ((_this->figures[figure_id].flags & FOLLOW_MODE) == 0)
445 {
446 figure_id = master_id;
447 master_id = _this->figures[figure_id].master_figure;
448 }
449 else
450 {
451 break;
452 }
453 }
454 return _this->figures[figure_id].race;
455}
456
458{
459 uint16_t figure_id = _this->battleData.current_figure;
460 _this->battleData.CGdFigure->figures[figure_id].flags &= ~(GOT_AGGRO);
461 _this->battleData.CGdFigure->figures[figure_id].flags &= ~(RETREAT);
462 std::vector<uint16_t> spell_indices;
463 if ((figureAPI.isFlagSet(_this->battleData.CGdFigure, figure_id, AURA_RUNNING))
464 && (_this->battleData.current_figure_is_hero == 0)
465 && (_this->battleData.current_figure_is_mainchar == 0))
466 {
467 for (uint16_t i = figureAPI.getSpellJobStartNode(_this->battleData.CGdFigure, figure_id); i != 0;
468 i = toolboxAPI.getNextNode(_this->battleData.CGdDoubleLinkList, i))
469 {
470 uint16_t spell_index = toolboxAPI.getSpellIndexFromDLL(_this->battleData.CGdDoubleLinkList, i);
471 uint16_t spell_line = spellAPI.getSpellLine(_this->battleData.CGdSpell, spell_index);
472 if (((spellAPI.hasSpellTag(spell_line, SpellTag::AURA_SPELL))
473 || (spellAPI.hasSpellTag(spell_line, SpellTag::SIEGE_AURA_SPELL)))
474 && (_this->battleData.enemy_figures.entityCount == 0))
475 {
476 spell_indices.push_back(spell_index);
477 }
478 }
479 while (spell_indices.size() != 0)
480 {
481 uint16_t spell_index = spell_indices.back();
482 spell_indices.pop_back();
483 sf_endspell_hook(_this->battleData.CGdSpell, spell_index);
484 }
485 }
487}
488
489static void figure_turn_off_battle_mode_hook()
490{
491 ASI::MemoryRegion mreg(ASI::AddrOf(0x3607a7), 5);
492 ASI::BeginRewrite(mreg);
493 *(unsigned char *)(ASI::AddrOf(0x3607a7)) = 0xE9; // jmp instruction
494 *(int *)(ASI::AddrOf(0x3607a8)) = (int)(&figureTurnOffBattleMode)- ASI::AddrOf((0x3607ac));
495 ASI::EndRewrite(mreg);
496
497}
498
499/* Figure Statistics */
500static void figure_statistic_hook_current_ac()
501{
502 ASI::MemoryRegion ac_mreg (ASI::AddrOf(0x2b18e0), 7);
503 ASI::BeginRewrite(ac_mreg);
504 *(unsigned char *)(ASI::AddrOf(0x2b18e0)) = 0x90; // nop
505 *(unsigned char *)(ASI::AddrOf(0x2b18e1)) = 0x90; // nop
506 *(unsigned char *)(ASI::AddrOf(0x2b18e2)) = 0xE9; // jmp instruction
507 *(int *)(ASI::AddrOf(0x2b18e3)) = (int)(&get_figure_statistic_current_ac) - ASI::AddrOf((0x2b18e7));
508 ASI::EndRewrite(ac_mreg);
509}
510
511static void figure_statistic_hook_current_agi()
512{
513 ASI::MemoryRegion ac_mreg (ASI::AddrOf(0x2b1af0), 7);
514 ASI::BeginRewrite(ac_mreg);
515 *(unsigned char *)(ASI::AddrOf(0x2b1af0)) = 0x90; // nop
516 *(unsigned char *)(ASI::AddrOf(0x2b1af1)) = 0x90; // nop
517 *(unsigned char *)(ASI::AddrOf(0x2b1af2)) = 0xE9; // jmp instruction
518 *(int *)(ASI::AddrOf(0x2b1af3)) = (int)(&get_figure_statistic_current_agi) - ASI::AddrOf((0x2b1af7));
519 ASI::EndRewrite(ac_mreg);
520}
521
522static void figure_statistic_hook_current_cha()
523{
524 ASI::MemoryRegion ac_mreg (ASI::AddrOf(0x2b1c30), 7);
525 ASI::BeginRewrite(ac_mreg);
526 *(unsigned char *)(ASI::AddrOf(0x2b1c30)) = 0x90; // nop
527 *(unsigned char *)(ASI::AddrOf(0x2b1c31)) = 0x90; // nop
528 *(unsigned char *)(ASI::AddrOf(0x2b1c32)) = 0xE9; // jmp instruction
529 *(int *)(ASI::AddrOf(0x2b1c33)) = (int)(&get_figure_statistic_current_cha) - ASI::AddrOf((0x2b1c37));
530 ASI::EndRewrite(ac_mreg);
531}
532
533static void figure_statistic_hook_current_dex()
534{
535 ASI::MemoryRegion ac_mreg (ASI::AddrOf(0x2b2600), 7);
536 ASI::BeginRewrite(ac_mreg);
537 *(unsigned char *)(ASI::AddrOf(0x2b2600)) = 0x90; // nop
538 *(unsigned char *)(ASI::AddrOf(0x2b2601)) = 0x90; // nop
539 *(unsigned char *)(ASI::AddrOf(0x2b2602)) = 0xE9; // jmp instruction
540 *(int *)(ASI::AddrOf(0x2b2603)) = (int)(&get_figure_statistic_current_dex) - ASI::AddrOf((0x2b2607));
541 ASI::EndRewrite(ac_mreg);
542}
543
544static void figure_statistic_hook_current_int()
545{
546 ASI::MemoryRegion ac_mreg (ASI::AddrOf(0x2b28a0), 7);
547 ASI::BeginRewrite(ac_mreg);
548 *(unsigned char *)(ASI::AddrOf(0x2b28a0)) = 0x90; // nop
549 *(unsigned char *)(ASI::AddrOf(0x2b28a1)) = 0x90; // nop
550 *(unsigned char *)(ASI::AddrOf(0x2b28a2)) = 0xE9; // jmp instruction
551 *(int *)(ASI::AddrOf(0x2b28a3)) = (int)(&get_figure_statistic_current_int) - ASI::AddrOf((0x2b28a7));
552 ASI::EndRewrite(ac_mreg);
553}
554
555static void figure_statistic_hook_current_hp()
556{
557 ASI::MemoryRegion ac_mreg (ASI::AddrOf(0x279350), 7);
558 ASI::BeginRewrite(ac_mreg);
559 *(unsigned char *)(ASI::AddrOf(0x279350)) = 0x90; // nop
560 *(unsigned char *)(ASI::AddrOf(0x279351)) = 0x90; // nop
561 *(unsigned char *)(ASI::AddrOf(0x279352)) = 0xE9; // jmp instruction
562 *(int *)(ASI::AddrOf(0x279353)) = (int)(&get_figure_statistic_current_hp) - ASI::AddrOf((0x279357));
563 ASI::EndRewrite(ac_mreg);
564
565 ASI::MemoryRegion ac_mreg2 (ASI::AddrOf(0x2b2970), 7);
566 ASI::BeginRewrite(ac_mreg2);
567 *(unsigned char *)(ASI::AddrOf(0x2b2970)) = 0x90; // nop
568 *(unsigned char *)(ASI::AddrOf(0x2b2971)) = 0x90; // nop
569 *(unsigned char *)(ASI::AddrOf(0x2b2972)) = 0xE9; // jmp instruction
570 *(int *)(ASI::AddrOf(0x2b2973)) = (int)(&get_figure_statistic_max_hp) - ASI::AddrOf((0x2b2977));
571 ASI::EndRewrite(ac_mreg2);
572
573}
574
575static void figure_statistic_hook_current_mp()
576{
577 ASI::MemoryRegion ac_mreg (ASI::AddrOf(0x2b29c0), 7);
578 ASI::BeginRewrite(ac_mreg);
579 *(unsigned char *)(ASI::AddrOf(0x2b29c0)) = 0x90; // nop
580 *(unsigned char *)(ASI::AddrOf(0x2b29c1)) = 0x90; // nop
581 *(unsigned char *)(ASI::AddrOf(0x2b29c2)) = 0xE9; // jmp instruction
582 *(int *)(ASI::AddrOf(0x2b29c3)) = (int)(&get_figure_statistic_current_mp) - ASI::AddrOf((0x2b29c7));
583 ASI::EndRewrite(ac_mreg);
584
585 ASI::MemoryRegion ac_mreg2 (ASI::AddrOf(0x2b2a20), 7);
586 ASI::BeginRewrite(ac_mreg2);
587 *(unsigned char *)(ASI::AddrOf(0x2b2a20)) = 0x90; // nop
588 *(unsigned char *)(ASI::AddrOf(0x2b2a21)) = 0x90; // nop
589 *(unsigned char *)(ASI::AddrOf(0x2b2a22)) = 0xE9; // jmp instruction
590 *(int *)(ASI::AddrOf(0x2b2a23)) = (int)(&get_figure_statistic_max_mp) - ASI::AddrOf((0x2b2a27));
591 ASI::EndRewrite(ac_mreg2);
592
593}
594
595static void figure_statistic_hook_current_sta()
596{
597 ASI::MemoryRegion ac_mreg (ASI::AddrOf(0x2b2e00), 7);
598 ASI::BeginRewrite(ac_mreg);
599 *(unsigned char *)(ASI::AddrOf(0x2b2e00)) = 0x90; // nop
600 *(unsigned char *)(ASI::AddrOf(0x2b2e01)) = 0x90; // nop
601 *(unsigned char *)(ASI::AddrOf(0x2b2e02)) = 0xE9; // jmp instruction
602 *(int *)(ASI::AddrOf(0x2b2e03)) = (int)(&get_figure_statistic_current_sta) - ASI::AddrOf((0x2b2e07));
603 ASI::EndRewrite(ac_mreg);
604}
605
606static void figure_statistic_hook_current_str()
607{
608 ASI::MemoryRegion ac_mreg (ASI::AddrOf(0x2b2eb0), 7);
609 ASI::BeginRewrite(ac_mreg);
610 *(unsigned char *)(ASI::AddrOf(0x2b2eb0)) = 0x90; // nop
611 *(unsigned char *)(ASI::AddrOf(0x2b2eb1)) = 0x90; // nop
612 *(unsigned char *)(ASI::AddrOf(0x2b2eb2)) = 0xE9; // jmp instruction
613 *(int *)(ASI::AddrOf(0x2b2eb3)) = (int)(&get_figure_statistic_current_str) - ASI::AddrOf((0x2b2eb7));
614 ASI::EndRewrite(ac_mreg);
615}
616
617static void figure_statistic_hook_current_wis()
618{
619 ASI::MemoryRegion ac_mreg (ASI::AddrOf(0x2b3160), 7);
620 ASI::BeginRewrite(ac_mreg);
621 *(unsigned char *)(ASI::AddrOf(0x2b3160)) = 0x90; // nop
622 *(unsigned char *)(ASI::AddrOf(0x2b3161)) = 0x90; // nop
623 *(unsigned char *)(ASI::AddrOf(0x2b3162)) = 0xE9; // jmp instruction
624 *(int *)(ASI::AddrOf(0x2b3163)) = (int)(&get_figure_statistic_current_wis) - ASI::AddrOf((0x2b3167));
625 ASI::EndRewrite(ac_mreg);
626}
627
628static void figure_statistic_hook_current_fire_res()
629{
630 ASI::MemoryRegion ac_mreg (ASI::AddrOf(0x2b2c00), 7);
631 ASI::BeginRewrite(ac_mreg);
632 *(unsigned char *)(ASI::AddrOf(0x2b2c00)) = 0x90; // nop
633 *(unsigned char *)(ASI::AddrOf(0x2b2c01)) = 0x90; // nop
634 *(unsigned char *)(ASI::AddrOf(0x2b2c02)) = 0xE9; // jmp instruction
635 *(int *)(ASI::AddrOf(0x2b2c03)) = (int)(&get_figure_statistic_current_fire_res) - ASI::AddrOf((0x2b2c07));
636 ASI::EndRewrite(ac_mreg);
637}
638
639static void figure_statistic_hook_current_ice_res()
640{
641 ASI::MemoryRegion ac_mreg (ASI::AddrOf(0x2b2ca0), 7);
642 ASI::BeginRewrite(ac_mreg);
643 *(unsigned char *)(ASI::AddrOf(0x2b2ca0)) = 0x90; // nop
644 *(unsigned char *)(ASI::AddrOf(0x2b2ca1)) = 0x90; // nop
645 *(unsigned char *)(ASI::AddrOf(0x2b2ca2)) = 0xE9; // jmp instruction
646 *(int *)(ASI::AddrOf(0x2b2ca3)) = (int)(&get_figure_statistic_current_ice_res) - ASI::AddrOf((0x2b2ca7));
647 ASI::EndRewrite(ac_mreg);
648}
649
650static void figure_statistic_hook_current_mental_res()
651{
652 ASI::MemoryRegion ac_mreg (ASI::AddrOf(0x2b2d40), 7);
653 ASI::BeginRewrite(ac_mreg);
654 *(unsigned char *)(ASI::AddrOf(0x2b2d40)) = 0x90; // nop
655 *(unsigned char *)(ASI::AddrOf(0x2b2d41)) = 0x90; // nop
656 *(unsigned char *)(ASI::AddrOf(0x2b2d42)) = 0xE9; // jmp instruction
657 *(int *)(ASI::AddrOf(0x2b2d43)) = (int)(&get_figure_statistic_current_mental_res) - ASI::AddrOf((0x2b2d47));
658 ASI::EndRewrite(ac_mreg);
659}
660
661static void figure_statistic_hook_current_black_res()
662{
663 ASI::MemoryRegion ac_mreg (ASI::AddrOf(0x2b2b60), 7);
664 ASI::BeginRewrite(ac_mreg);
665 *(unsigned char *)(ASI::AddrOf(0x2b2b60)) = 0x90; // nop
666 *(unsigned char *)(ASI::AddrOf(0x2b2b61)) = 0x90; // nop
667 *(unsigned char *)(ASI::AddrOf(0x2b2b62)) = 0xE9; // jmp instruction
668 *(int *)(ASI::AddrOf(0x2b2b63)) = (int)(&get_figure_statistic_current_black_res) - ASI::AddrOf((0x2b2b67));
669 ASI::EndRewrite(ac_mreg);
670}
671
672static void figure_statistic_hook_current_walk_spd()
673{
674 ASI::MemoryRegion ac_mreg (ASI::AddrOf(0x2b2fb0), 7);
675 ASI::BeginRewrite(ac_mreg);
676 *(unsigned char *)(ASI::AddrOf(0x2b2fb0)) = 0x90; // nop
677 *(unsigned char *)(ASI::AddrOf(0x2b2fb1)) = 0x90; // nop
678 *(unsigned char *)(ASI::AddrOf(0x2b2fb2)) = 0xE9; // jmp instruction
679 *(int *)(ASI::AddrOf(0x2b2fb3)) = (int)(&get_figure_statistic_current_walk_spd) - ASI::AddrOf((0x2b2fb7));
680 ASI::EndRewrite(ac_mreg);
681}
682
683static void figure_statistic_hook_current_fight_spd()
684{
685 ASI::MemoryRegion ac_mreg (ASI::AddrOf(0x2b26d0), 7);
686 ASI::BeginRewrite(ac_mreg);
687 *(unsigned char *)(ASI::AddrOf(0x2b26d0)) = 0x90; // nop
688 *(unsigned char *)(ASI::AddrOf(0x2b26d1)) = 0x90; // nop
689 *(unsigned char *)(ASI::AddrOf(0x2b26d2)) = 0xE9; // jmp instruction
690 *(int *)(ASI::AddrOf(0x2b26d3)) = (int)(&get_figure_statistic_current_fight_spd) - ASI::AddrOf((0x2b26d7));
691 ASI::EndRewrite(ac_mreg);
692}
693
694static void figure_statistic_hook_current_cast_spd()
695{
696 ASI::MemoryRegion ac_mreg (ASI::AddrOf(0x2b1b90), 7);
697 ASI::BeginRewrite(ac_mreg);
698 *(unsigned char *)(ASI::AddrOf(0x2b1b90)) = 0x90; // nop
699 *(unsigned char *)(ASI::AddrOf(0x2b1b91)) = 0x90; // nop
700 *(unsigned char *)(ASI::AddrOf(0x2b1b92)) = 0xE9; // jmp instruction
701 *(int *)(ASI::AddrOf(0x2b1b93)) = (int)(&get_figure_statistic_current_cast_spd) - ASI::AddrOf((0x2b1b97));
702 ASI::EndRewrite(ac_mreg);
703}
704
705static void salvo_fix_hook()
706{
707 ASI::MemoryRegion salvo_mreg1 (ASI::AddrOf(0x2eb294), 5);
708 ASI::BeginRewrite(salvo_mreg1);
709 *(unsigned char *)(ASI::AddrOf(0x2eb294)) = 0xE8;
710 *(int *)(ASI::AddrOf(0x2eb295)) = (int)(&get_salvo_target_list) - ASI::AddrOf((0x2eb299));
711 ASI::EndRewrite(salvo_mreg1);
712
713}
714
715static void get_race_fix_hook()
716{
717 ASI::MemoryRegion race_mreg1 (ASI::AddrOf(0x29b230), 7);
718 ASI::BeginRewrite(race_mreg1);
719 *(unsigned char *)(ASI::AddrOf(0x29b230)) = 0x90;
720 *(unsigned char *)(ASI::AddrOf(0x29b231)) = 0x90;
721 *(unsigned char *)(ASI::AddrOf(0x29b232)) = 0xE9;
722 *(int *)(ASI::AddrOf(0x29b233)) = (int)(&getEffectiveRace) - ASI::AddrOf((0x29b237));
723 ASI::EndRewrite(race_mreg1);
724}
725
726bool __thiscall isTitan(SF_CGdFigure *_this, uint16_t figure_id)
727{
728 uint16_t figure_data_id = _this->figures[figure_id].unit_data_id;
729 bool result = false;
730
731 switch (figure_data_id)
732 {
733 case 1047:
734 case 1079:
735 case 1098:
736 case 1099:
737 case 1100:
738 case 1101:
739 case 2281:
740 case 2282:
741 case 2283:
742 case 2284:
743 case 2285:
744 case 2286:
745 {
746 result = true;
747 break;
748 }
749 default:
750 {
751 result = false;
752 break;
753 }
754 }
755 return result;
756}
757
758bool __thiscall isSwarm(SF_CGdFigure *_this, uint16_t figure_id)
759{
760 uint16_t figure_data_id = _this->figures[figure_id].unit_data_id;
761 bool result = ((figure_data_id > 2219) && (figure_data_id < 2226));
762 return result;
763}
764void __thiscall decreaseUsedArmyUnitCount(SF_CGdPlayer *_this, uint16_t owner, uint8_t side)
765{
766 uint16_t unit_count = _this->players[owner].warrior_count[side];
767 if (unit_count != 0)
768 {
769 unit_count--;
770 }
771 _this->players[owner].warrior_count[side] = unit_count;
772}
773
774uint32_t __thiscall decreaseUnitCount(AutoClass46 *_this, uint16_t figure_id)
775{
776 uint8_t race = _this->CGdFigure->figures[figure_id].race;
777 uint16_t owner = _this->CGdFigure->figures[figure_id].owner;
778 if ((owner != 0) && (race != 0) && (race < 7))
779 {
780 if ((_this->CGdFigure->figures[figure_id].flags & ILLUSION) != 0)
781 {
782 return 0;
783 }
784 if ((!isTitan(_this->CGdFigure, figure_id)) && (!isSwarm(_this->CGdFigure, figure_id)))
785 {
786 if (!figureAPI.isWarrior(_this->CGdFigure, figure_id))
787 {
788 uint16_t worker_count = _this->CGdPlayer->players[owner].civilian_count[race - 1];
789 if (worker_count > 0)
790 {
791 worker_count--;
792 }
793 _this->CGdPlayer->players[owner].civilian_count[race - 1] = worker_count;
794 return 0;
795 }
796 else
797 {
798 bool side = ((race != 3) && (race != 2) && (race != 1));
799 decreaseUsedArmyUnitCount(_this->CGdPlayer, owner, side);
800 if (figureAPI.isSiegeUnit(_this->CGdFigure, figure_id))
801 {
802 decreaseUsedArmyUnitCount(_this->CGdPlayer, owner, side);
803 decreaseUsedArmyUnitCount(_this->CGdPlayer, owner, side);
804 }
805 }
806 }
807
808 }
809 return 0;
810}
811
812static void army_size_fix_hook()
813{
814 ASI::MemoryRegion race_mreg1 (ASI::AddrOf(0x326e40), 5);
815 ASI::BeginRewrite(race_mreg1);
816 *(unsigned char *)(ASI::AddrOf(0x326e40)) = 0xE9;
817 *(int *)(ASI::AddrOf(0x326e41)) = (int)(&decreaseUnitCount) - ASI::AddrOf((0x326e45));
818 ASI::EndRewrite(race_mreg1);
819}
820
821static SF_CGdFigure * getFigurePtr(void *CGdMain)
822{
823 return (SF_CGdFigure *)(*(uint32_t *)((uint32_t)CGdMain + 0x30));
824}
825
826
827void prepareDamageString(AutoClass101 *_this, SF_CGdFigure *figures, uint16_t figure_id,
828 CGdResourceWeaponData *weapon_data, SF_String *out_string)
829{
830 uint32_t lvl_mult = 0;
831 SF_String description;
832 uiAPI.SFStringConstructor(&description);
833
834 //TASK_MAIN_CHAR or TASK_HERO
835 if ((figures->figures[figure_id].current_job.task == 0xa) ||
836 (figures->figures[figure_id].current_job.task == 0x9))
837 {
838 lvl_mult = 100;
839 }
840 else
841 {
842 lvl_mult = GetDamageMultiplierPerLevel(_this->SF_CGdResource, figures->figures[figure_id].level);
843 }
844 uint32_t str_mult = figureAPI.getCurrentStat(figures, figure_id, STRENGTH);
845 str_mult *= 3 * (figures->figures[figure_id].level + 9);
846 GetDescriptionText(_this->UiDbProxy, 4531, &description);
847 if (weapon_data->min_dmg == weapon_data->max_dmg)
848 {
849 uint32_t damage = (weapon_data->max_dmg * str_mult * lvl_mult + 50000) / 100000;
850 uiAPI.SFprintf(out_string,L"%s %i ", description.raw_data, damage);
851 }
852 else
853 {
854 uint32_t max_damage = (weapon_data->max_dmg * str_mult * lvl_mult + 50000) / 100000;
855 uint32_t min_damage = (weapon_data->min_dmg * str_mult * lvl_mult + 50000) / 100000;
856 uiAPI.SFprintf(out_string,L"%s %i-%i ", description.raw_data, min_damage,max_damage);
857 }
858 uiAPI.SFStringDestructor(&description);
859}
860
861
862void prepareHPString(AutoClass101 *_this, SF_CGdFigure *figures, uint16_t figure_id, SF_String *out_string)
863{
864 SF_String full_desc;
865 SF_String description;
866
867 uiAPI.SFStringConstructor(&full_desc);
868 uiAPI.SFStringConstructor(&description);
869
870 uint32_t max_hp = figureAPI.getMaxStat(figures, figure_id, HEALTH);
871 uint32_t hp = figureAPI.getCurrentStat(figures, figure_id, HEALTH);
872 uiAPI.SFprintf(&full_desc, L"%i/%i", hp, max_hp);
873 GetColoredText(&full_desc, 280);
874 GetDescriptionText(_this->UiDbProxy, 4407, &description);
875 uiAPI.SFprintf(out_string, L"%s: %s", description.raw_data, full_desc.raw_data);
876
877 uiAPI.SFStringDestructor(&description);
878 uiAPI.SFStringDestructor(&full_desc);
879}
880
881void prepareMPString(AutoClass101 *_this, SF_CGdFigure *figures, uint16_t figure_id, SF_String *out_string)
882{
883 SF_String full_desc;
884 SF_String description;
885
886 uiAPI.SFStringConstructor(&full_desc);
887 uiAPI.SFStringConstructor(&description);
888
889 uint32_t max_mp = figureAPI.getMaxStat(figures, figure_id, MANA);
890 uint32_t mp = figureAPI.getCurrentStat(figures, figure_id, MANA);
891 uiAPI.SFprintf(&full_desc, L"%i/%i", mp, max_mp);
892 GetColoredText(&full_desc, 280);
893 GetDescriptionText(_this->UiDbProxy, 4408, &description);
894 uiAPI.SFprintf(out_string, L"%s: %s", description.raw_data, full_desc.raw_data);
895
896 uiAPI.SFStringDestructor(&description);
897 uiAPI.SFStringDestructor(&full_desc);
898}
899
901{
902 SF_String header_string;
903 SF_String desc_str1;
904 SF_String desc_str2;
905 SF_String newline;
906
907 uiAPI.SFStringFromWchar(&header_string, L'\n', 1);
908 uiAPI.SFStringFromWchar(&newline, L'\n', 1);
909 uiAPI.SFStringConstructor(&desc_str1);
910 uiAPI.SFStringConstructor(&desc_str2);
911
912 GetDescriptionText(_this->UiDbProxy, 4802, &desc_str1);
913 uiAPI.SFprintf(&desc_str2, L"%s ", desc_str1);
914 uiAPI.SFStringConcat(&header_string, &desc_str2);
915 uiAPI.SFprintf(&header_string, L"%%c%x%s%%d",0xc0d0ff,header_string.raw_data);
916// uiAPI.SFStringConcat(&header_string, &newline);
917
918 uiAPI.SFStringCopy(out_string, &header_string);
919
920 uiAPI.SFStringDestructor(&newline);
921 uiAPI.SFStringDestructor(&header_string);
922 uiAPI.SFStringDestructor(&desc_str1);
923 uiAPI.SFStringDestructor(&desc_str2);
924}
925
926void prepareSpellString(AutoClass101 *_this, SF_String *out_string, uint16_t spell_id)
927{
928 SF_CGdResourceSpell spell_data;
929 SF_CGdResourceSpellLine spell_line_data;
930
931 SF_String spell_string;
932 SF_String newline;
933 SF_String desc_str1;
934 SF_String desc_str2;
935 SF_String full_desc;
936
937 uiAPI.SFStringConstructor(&desc_str1);
938 uiAPI.SFStringConstructor(&desc_str2);
939 uiAPI.SFStringFromWchar(&spell_string, L'\n', 1);
940 uiAPI.SFStringFromWchar(&newline, L'\n', 1);
941
942 spellAPI.getResourceSpellData(_this->SF_CGdResource, &spell_data, spell_id);
943 if ((GetResourceSpellLine(_this->SF_CGdResource, spell_data.spell_line_id,
944 &spell_line_data) != 0) && (spell_line_data.description_id != 0))
945 {
946 GetTextById(_this->UiDbProxy, spell_line_data.text_id, &desc_str1);
947 GetColoredText(&desc_str1, 278);
948 uiAPI.SFStringConcat(&spell_string, &desc_str1);
949 uiAPI.SFStringConcat(&spell_string, &newline);
950
951 GetDescriptionText(_this->UiDbProxy, spell_line_data.description_id, &desc_str2);
952 ExpandSpellDescription(_this,&full_desc, &desc_str2, &spell_data);
953 uiAPI.SFStringConcat(&spell_string, &full_desc);
954 }
955 if (spell_string.str_length > 1)
956 {
957 uiAPI.SFStringCopy(out_string, &spell_string);
958 }
959
960 uiAPI.SFStringDestructor(&desc_str1);
961 uiAPI.SFStringDestructor(&desc_str2);
962
963 uiAPI.SFStringDestructor(&full_desc);
964 uiAPI.SFStringDestructor(&spell_string);
965 uiAPI.SFStringDestructor(&newline);
966}
967
968void prepareEffectString(AutoClass101 *_this, SF_CGdFigure *figures, uint16_t figure_id, uint16_t effect_id,
969 SF_String *out_string)
970{
971 SF_String desc_str1;
972 SF_String desc_str2;
973 SF_String description;
974 SF_String newline;
975 SF_String chance_string;
976
977 uiAPI.SFStringConstructor(&chance_string);
978 uiAPI.SFStringConstructor(&desc_str1);
979 uiAPI.SFStringConstructor(&desc_str2);
980 uiAPI.SFStringConstructor(&description);
981 uiAPI.SFStringFromWchar(&newline, L'\n', 1);
982
983 SF_CGdResourceSpell spell_data;
984 spellAPI.getResourceSpellData(_this->SF_CGdResource, &spell_data, effect_id);
985 SF_CGdResourceSpellLine spell_line_data;
986 GetResourceSpellLine(_this->SF_CGdResource, spell_data.spell_line_id, &spell_line_data);
987 if (spell_data.spell_line_id != 0 && spell_line_data.description_id != 0)
988 {
989 GetDescriptionText(_this->UiDbProxy, 6550, &desc_str1);
990 uiAPI.SFprintf(out_string,L"%%c%x%s:%%d ",0xc0d0ff,desc_str1.raw_data);
991 GetTextById(_this->UiDbProxy, spell_line_data.text_id, &description);
992 GetColoredText(&description, 278);
993 uiAPI.SFStringConcat(out_string, &description);
995 uint16_t chance = handler(figures, figure_id);
996 uiAPI.SFprintf(&chance_string,L" (%.1f%%%%)", (double)((float)chance / 100.0));
997 uiAPI.SFStringConcat(out_string, &chance_string);
998
999 GetDescriptionText(_this->UiDbProxy, spell_line_data.description_id, &desc_str2);
1000 SF_String temp_str;
1001 ExpandSpellDescription(_this, &temp_str, &desc_str2, &spell_data);
1002 uiAPI.SFStringConcat(&newline, &temp_str);
1003 uiAPI.SFStringConcat(out_string, &newline);
1004
1005 uiAPI.SFStringDestructor(&temp_str);
1006 }
1007 uiAPI.SFStringDestructor(&desc_str1);
1008 uiAPI.SFStringDestructor(&desc_str2);
1009
1010 uiAPI.SFStringDestructor(&description);
1011 uiAPI.SFStringDestructor(&chance_string);
1012 uiAPI.SFStringDestructor(&newline);
1013}
1014
1015SF_String * __thiscall portrait_overlay_hook(AutoClass101 *_this, SF_String *param_1, uint16_t figure_id,
1016 uint32_t param3,
1017 uint32_t param4, uint32_t param5)
1018{
1019 SF_String figure_name;
1020 SF_String full_desc;
1021 SF_String description;
1022
1023 SF_String result_string;
1024 SF_String newline;
1025 SF_String aspd_string;
1026
1027 uiAPI.SFStringConstructor(&full_desc);
1028 uiAPI.SFStringConstructor(&description);
1029 uiAPI.SFStringConstructor(&aspd_string);
1030 uiAPI.SFStringConstructor(&figure_name);
1031
1032 uiAPI.SFStringConstructor_char(&result_string, "");
1033 uiAPI.SFStringFromWchar(&newline, L'\n', 1);
1034
1035
1036 SF_CGdFigure *SF_Figures = getFigurePtr(_this->CGdMain);
1037
1038 if (SF_Figures->figures[figure_id].owner != (uint16_t)(-1))
1039 {
1040 AC95_get_figure_name(_this->AC95, &figure_name, figure_id);
1041 GetColoredText(&figure_name, 282);
1042 GetDescriptionText(_this->UiDbProxy, 4425, &description);
1043 if (param3 == 0)
1044 {
1045 uiAPI.SFprintf(&full_desc, L"%s", figure_name.raw_data);
1046 }
1047 else
1048 {
1049 uint8_t level = SF_Figures->figures[figure_id].level;
1050 uiAPI.SFprintf(&full_desc, L"%s (%s %i)", figure_name.raw_data, description.raw_data, level);
1051 }
1052 uiAPI.SFStringConcat(&result_string, &full_desc);
1053 if (param3 != 0)
1054 {
1055 uiAPI.SFStringConcat(&result_string, &newline); //concatenate newline
1056 SF_String hp_string;
1057 uiAPI.SFStringConstructor(&hp_string);
1058 prepareHPString(_this, SF_Figures, figure_id, &hp_string);
1059 uiAPI.SFStringConcat(&result_string, &hp_string);
1060 uiAPI.SFStringDestructor(&hp_string);
1061 }
1062 if (param4 != 0)
1063 {
1064 SF_String mp_string;
1065 uiAPI.SFStringConstructor(&mp_string);
1066 uiAPI.SFStringConcat(&result_string, &newline); //concatenate newline
1067 prepareMPString(_this, SF_Figures, figure_id, &mp_string);
1068 uiAPI.SFStringConcat(&result_string, &mp_string);
1069 uiAPI.SFStringDestructor(&mp_string);
1070 }
1071 if (param5 != 0)
1072 {
1073 bool both_hands = true;
1074 uint32_t dual_wield = 0;
1075 CGdResourceWeaponData l_item_info;
1076 CGdResourceWeaponData r_item_info;
1077 CGdResourceWeaponData *active_hand_info = nullptr;
1078 SF_String desc_str1;
1079 SF_String desc_str2;
1080
1081 uiAPI.SFStringConstructor(&desc_str1);
1082 uiAPI.SFStringConstructor(&desc_str2);
1083
1084 uint8_t r_type;
1085 uint8_t l_type;
1086 uint16_t r_item_id = SF_Figures->figures[figure_id].equipment[1];
1087 GetItemInfo(_this->SF_CGdResource,&r_item_info, r_item_id);
1088
1089 uint16_t l_item_id = SF_Figures->figures[figure_id].equipment[3];
1090 GetItemInfo(_this->SF_CGdResource,&l_item_info, l_item_id);
1091
1092 r_type = GetWeaponType(_this->SF_CGdResource, r_item_id);
1093 l_type = GetWeaponType(_this->SF_CGdResource, l_item_id);
1094 active_hand_info = &r_item_info;
1095 if ((l_item_info.min_dmg == 0) || (r_item_info.min_dmg == 0))
1096 {
1097 both_hands = false;
1098 if (l_item_info.min_dmg != 0)
1099 {
1100 active_hand_info = &l_item_info;
1101 r_type = l_type;
1102 r_item_id = l_item_id;
1103 }
1104 }
1105 else
1106 {
1107 GetDescriptionText(_this->UiDbProxy, 4800, &desc_str1);
1108 GetDescriptionText(_this->UiDbProxy, 4801, &desc_str2);
1109 if ((r_type != 7) || (l_type != 7))
1110 {
1111 dual_wield = 0;
1112 }
1113 else
1114 {
1115 dual_wield = 1;
1116 }
1117 }
1118 if (active_hand_info != nullptr)
1119 {
1120 SF_String damage_string;
1121 uiAPI.SFStringConstructor(&damage_string);
1122
1123 uiAPI.SFStringConcat(&result_string, &newline);
1124 uiAPI.SFStringSetLength(&full_desc, 0);
1125 if (both_hands)
1126 {
1127 uiAPI.SFprintf(&full_desc, L"%s: ", desc_str2.raw_data);
1128 }
1129 prepareDamageString(_this, SF_Figures, figure_id, active_hand_info, &damage_string);
1130 GetColoredText(&damage_string, 280);
1131 uiAPI.SFStringConcat(&full_desc, &damage_string);
1132 uiAPI.SFStringDestructor(&damage_string);
1133
1134
1135 GetDescriptionText(_this->UiDbProxy, 4803, &aspd_string);
1136 uiAPI.SFprintf(&description, L"%s, ", aspd_string.raw_data);
1137
1138 uint8_t race = SF_Figures->figures[figure_id].race;
1139 uint32_t aspd = figureAPI.getCurrentStat(SF_Figures, figure_id, FIGHT_SPEED);
1140 uint32_t *AC34 = (uint32_t *)CGdMainGetAC34(_this->CGdMain);
1141 aspd = AC34calculateWeaponSpeed(AC34, aspd, race, r_item_id, dual_wield, (r_type == 12));
1142
1143 double disp_aspd = static_cast<double>(aspd) / 1000.0;
1144 uiAPI.SFprintf(&description, description.raw_data, disp_aspd);
1145 uiAPI.SFStringConcat(&full_desc, &description);
1146
1147 GetDescriptionText(_this->UiDbProxy, 4532, &description);
1148 GetColoredText(&description, 280);
1149
1150 if (active_hand_info->min_rng == active_hand_info->max_rng)
1151 {
1152 SF_String temp_str;
1153 uiAPI.SFStringConstructor(&temp_str);
1154
1155 if (active_hand_info->min_rng != 0)
1156 {
1157 getSpecialDesc(&figure_name, 280);
1158 uiAPI.SFprintf(&temp_str, L"%s_%s%i%s%c ", description.raw_data, figure_name.raw_data,
1159 active_hand_info->min_rng, L"%d", L',');
1160 uiAPI.SFStringDestructor(&figure_name);
1161 }
1162 uiAPI.SFStringConcat(&full_desc, &temp_str);
1163 uiAPI.SFStringDestructor(&temp_str);
1164 }
1165 else
1166 {
1167 getWeaponRangeDescription(&full_desc, active_hand_info->min_rng, active_hand_info->max_rng,
1168 &description, 0x01);
1169 }
1170 if (full_desc.str_length != 0)
1171 {
1172 uiAPI.SFStringConcat(&result_string, &full_desc);
1173 }
1174
1175 uiAPI.SFStringDestructor(&full_desc);
1176 uiAPI.SFStringDestructor(&description);
1177
1178 uiAPI.SFStringConstructor(&full_desc);
1179 uiAPI.SFStringConstructor(&description);
1180
1181 uint16_t effects[4];
1182 GetWeaponEffects(_this->SF_CGdResource, effects, r_item_id);
1183 for (int i = 1; i < 4; i++)
1184 {
1185 SF_String effect_string;
1186 uiAPI.SFStringConstructor(&effect_string);
1187
1188 if (effects[i] == 0)
1189 {
1190 break;
1191 }
1192 uint16_t effect_id = effects[i];
1193 if ((SF_Figures->figures[figure_id].race != 0) && (SF_Figures->figures[figure_id].race < 7))
1194 {
1195 if (SF_Figures->figures[figure_id].owner != 0)
1196 {
1197 effect_id = spellAPI.getLeveledSpellID(_this->SF_CGdResource, effect_id,
1198 SF_Figures->figures[figure_id].level);
1199 }
1200 }
1201 uiAPI.SFStringConcat(&full_desc, &newline);
1202 prepareEffectString(_this, SF_Figures, figure_id, effect_id, &effect_string);
1203 uiAPI.SFStringConcat(&full_desc, &effect_string);
1204 }
1205 if (full_desc.str_length != 0)
1206 {
1207 uiAPI.SFStringConcat(&result_string, &full_desc);
1208 }
1209 if (both_hands)
1210 {
1211 SF_String damage_string;
1212 uiAPI.SFStringConstructor(&damage_string);
1213
1214 uiAPI.SFStringConcat(&result_string, &newline);
1215 uiAPI.SFStringSetLength(&full_desc, 0);
1216 if (both_hands)
1217 {
1218 uiAPI.SFprintf(&full_desc, L"%s: ", desc_str1.raw_data);
1219 }
1220 prepareDamageString(_this, SF_Figures, figure_id, &l_item_info, &damage_string);
1221 GetColoredText(&damage_string, 280);
1222 uiAPI.SFStringConcat(&full_desc, &damage_string);
1223 uiAPI.SFStringDestructor(&damage_string);
1224
1225 GetDescriptionText(_this->UiDbProxy, 4803, &aspd_string);
1226 uiAPI.SFprintf(&description, L"%s, ", aspd_string.raw_data);
1227
1228 uint8_t race = SF_Figures->figures[figure_id].race;
1229 uint32_t aspd = figureAPI.getCurrentStat(SF_Figures, figure_id, FIGHT_SPEED);
1230 uint32_t *AC34 = (uint32_t *)CGdMainGetAC34(_this->CGdMain);
1231 aspd = AC34calculateWeaponSpeed(AC34, aspd, race, l_item_id, dual_wield, (l_type == 12));
1232
1233 double disp_aspd = static_cast<double>(aspd) / 1000.0;
1234 uiAPI.SFprintf(&description, description.raw_data, disp_aspd);
1235 uiAPI.SFStringConcat(&full_desc, &description);
1236
1237 GetDescriptionText(_this->UiDbProxy, 4532, &description);
1238 GetColoredText(&description, 280);
1239
1240 if (l_item_info.min_rng == l_item_info.max_rng)
1241 {
1242 SF_String temp_str;
1243 uiAPI.SFStringConstructor(&temp_str);
1244
1245 if (l_item_info.min_rng != 0)
1246 {
1247 getSpecialDesc(&figure_name, 280);
1248 uiAPI.SFprintf(&temp_str, L"%s_%s%i%s%c ", description.raw_data, figure_name.raw_data,
1249 l_item_info.min_rng, L"%d", L',');
1250 uiAPI.SFStringDestructor(&figure_name);
1251 }
1252 uiAPI.SFStringConcat(&full_desc, &temp_str);
1253 uiAPI.SFStringDestructor(&temp_str);
1254 }
1255 else
1256 {
1257 getWeaponRangeDescription(&full_desc, l_item_info.min_rng, l_item_info.max_rng, &description,
1258 0x01);
1259 }
1260 if (full_desc.str_length != 0)
1261 {
1262 uiAPI.SFStringConcat(&result_string, &full_desc);
1263 }
1264
1265 uiAPI.SFStringDestructor(&full_desc);
1266 uiAPI.SFStringDestructor(&description);
1267
1268 uiAPI.SFStringConstructor(&full_desc);
1269 uiAPI.SFStringConstructor(&description);
1270
1271 uint16_t effects[4];
1272 GetWeaponEffects(_this->SF_CGdResource, effects, l_item_id);
1273 for (int i = 1; i < 4; i++)
1274 {
1275 SF_String effect_string;
1276 uiAPI.SFStringConstructor(&effect_string);
1277
1278 if (effects[i] == 0)
1279 {
1280 break;
1281 }
1282 uint16_t effect_id = effects[i];
1283 if ((SF_Figures->figures[figure_id].race != 0) && (SF_Figures->figures[figure_id].race < 7))
1284 {
1285 if (SF_Figures->figures[figure_id].owner != 0)
1286 {
1287 effect_id = spellAPI.getLeveledSpellID(_this->SF_CGdResource, effect_id,
1288 SF_Figures->figures[figure_id].level);
1289 }
1290 }
1291 uiAPI.SFStringConcat(&full_desc, &newline);
1292 prepareEffectString(_this, SF_Figures, figure_id, effect_id, &effect_string);
1293 uiAPI.SFStringConcat(&full_desc, &effect_string);
1294 }
1295 if (full_desc.str_length != 0)
1296 {
1297 uiAPI.SFStringConcat(&result_string, &full_desc);
1298 }
1299 }
1300 }
1301 uint8_t spells_count = 0;
1302 for (uint8_t i = 0; i < 15; i++)
1303 {
1304 SF_SGtFigureAction action;
1305 memset(&action, 0, sizeof(SF_SGtFigureAction));
1306 aiAPI.getFigureAction(SF_Figures, &action, figure_id, i);
1307 if (action.type == 0)
1308 {
1309 continue;
1310 }
1311 if ((action.type < 9999) && (action.type != 241))
1312 {
1313 spells_count++;
1314 }
1315 }
1316 if (spells_count != 0)
1317 {
1318 SF_String header_string;
1319 uiAPI.SFStringConstructor(&header_string);
1320 prepareSpellsHeaderString(_this, &header_string);
1321 for (int i = 0; i < 15; i++)
1322 {
1323 SF_SGtFigureAction action;
1324 memset(&action, 0, sizeof(SF_SGtFigureAction));
1325 aiAPI.getFigureAction(SF_Figures, &action, figure_id, i);
1326 if (action.type == 0)
1327 {
1328 continue;
1329 }
1330 if ((action.type < 9999) && (action.type != 241))
1331 {
1332 SF_String spell_string;
1333 uint16_t spell_id = action.subtype;
1334 if ((SF_Figures->figures[figure_id].race != 0) && (SF_Figures->figures[figure_id].race < 7))
1335 {
1336 if (SF_Figures->figures[figure_id].owner != 0)
1337 {
1338 spell_id = spellAPI.getLeveledSpellID(_this->SF_CGdResource, spell_id,
1339 SF_Figures->figures[figure_id].level);
1340 }
1341 }
1342 uiAPI.SFStringConstructor(&spell_string);
1343 prepareSpellString(_this, &spell_string, spell_id);
1344 if (spell_string.str_length != 0)
1345 {
1346 uiAPI.SFStringConcat(&header_string, &spell_string);
1347 }
1348 uiAPI.SFStringDestructor(&spell_string);
1349 }
1350 }
1351 uiAPI.SFStringConcat(&result_string, &header_string);
1352 uiAPI.SFStringDestructor(&header_string);
1353 }
1354 }
1355 }
1356 uiAPI.SFStringCopy(param_1, &result_string);
1357 uiAPI.SFStringDestructor(&result_string);
1358 uiAPI.SFStringDestructor(&figure_name);
1359 uiAPI.SFStringDestructor(&full_desc);
1360 uiAPI.SFStringDestructor(&description);
1361 uiAPI.SFStringDestructor(&newline);
1362 return param_1;
1363}
1364
1365
1366SF_String * __thiscall getSpecialFigureName(SF_CGdFigureToolbox *_this, SF_String *in_string, uint16_t figure_id)
1367{
1368 SF_String out_string;
1369 uiAPI.SFStringConstructor(&out_string);
1370 uint8_t figure_task = _this->CGdFigure->figures[figure_id].current_job.task;
1371 switch (figure_task)
1372 {
1373 case TASK_HERO:
1374 {
1375 uint16_t owner = _this->CGdFigure->figures[figure_id].owner;
1376 uint8_t hero_index = 0xff;
1377 for (int i = 0; i < 5; i++)
1378 {
1379 if (_this->CGdPlayer->players[owner].hero_figure_index[i] == figure_id)
1380 {
1381 hero_index = i;
1382 break;
1383 }
1384 }
1385 if (hero_index != 0xff)
1386 {
1387 uiAPI.SFStringCopy(&out_string, &_this->CGdPlayer->players[owner].hero_names[hero_index]);
1388 }
1389 break;
1390 }
1391 case TASK_MAINCHAR:
1392 {
1393 uint16_t owner = _this->CGdFigure->figures[figure_id].owner;
1394 uint16_t avatar_id = _this->CGdPlayer->players[owner].avatar_figure_index;
1395 if (avatar_id != 0)
1396 {
1397 uiAPI.SFStringCopy(&out_string, &_this->CGdPlayer->players[owner].avatar_name);
1398 }
1399 break;
1400 }
1401 default:
1402 {
1403 if ((_this->CGdFigure->figures[figure_id].flags & ILLUSION) != 0)
1404 {
1405 uint16_t master_id = _this->CGdFigure->figures[figure_id].master_figure;
1406 SF_String master_name;
1407 uiAPI.SFStringConstructor(&master_name);
1408
1409 getSpecialFigureName(_this, &master_name, master_id);
1410 uiAPI.SFStringCopy(&out_string, &master_name);
1411 uiAPI.SFStringDestructor(&master_name);
1412 }
1413 else
1414 {
1415 uint16_t data_id = _this->CGdFigure->figures[figure_id].unit_data_id;
1416 if (data_id == 0)
1417 {
1418 SF_String empty;
1419 uiAPI.SFStringConstructor_char(&empty, "");
1420 uiAPI.SFStringCopy(&out_string, &empty);
1421 uiAPI.SFStringDestructor(&empty);
1422 }
1423 else
1424 {
1425 uint16_t unit_str_id = getUnitStringID(_this->CGdResource, data_id);
1426 char resource_str[512];
1427 getTextString(_this->CGdResource, unit_str_id, resource_str);
1428 SF_String sf_resource_str;
1429 uiAPI.SFStringConstructor_char(&sf_resource_str, resource_str);
1430 uiAPI.SFStringCopy(&out_string, &sf_resource_str);
1431 uiAPI.SFStringDestructor(&sf_resource_str);
1432 }
1433 }
1434 break;
1435 }
1436 }
1437
1438 uiAPI.SFStringCopy(in_string, &out_string);
1439 return in_string;
1440}
1441
1442typedef struct __attribute__((packed))
1443{
1444 wchar_t *filename;
1445 uint32_t length;
1446 uint32_t ukn1;
1447 uint32_t ukn2;
1448} D_String;
1449
1450typedef struct __attribute__((packed))
1451{
1452 void *FILE;
1454} FileWrapper;
1455
1456
1457
1459{
1460 SF_CGdMain *main = _this->data.CGdMain;
1461 SF_CGdWorld *world = main->data.CGdWorld;
1462 log_info("Map name %ls", world->map_name.raw_data);
1463}
1464
1465typedef void (__thiscall *createSplashScreen_ptr)(CAppMenu *_this, CMnuContainer **param_1, SF_String *param_2);
1466typedef void *(__thiscall *AC57_Init_ptr)(void *_this, FileWrapper *fileWrapper);
1467typedef void (__thiscall *AC57_Dispose_ptr)(void *_this);
1468typedef D_String *(__thiscall *DStringConstructor_char_ptr)(D_String *_this, char *source);
1469typedef int (__thiscall *FileWrapperOpen_ptr)(FileWrapper *_this, D_String *path, int param_2);
1470typedef void (__thiscall *FileWrapperClose_ptr)(FileWrapper *_this);
1471typedef void (__thiscall *readMapNameFromSave_ptr)(SF_CGdWorld *_this, void *AC57);
1472
1474
1481
1483
1484void CreateSplashScreenHelper (CAppMenu *_this, CMnuContainer **param_1, SF_String *param_2, SF_String *map_name)
1485{
1486 SF_String screen_name;
1487 uiAPI.SFStringConstructor_char(&screen_name, "<Cont>Splash");
1488 uiAPI.SFStringDeepCopy(param_2, &screen_name);
1489 uiAPI.SFStringDestructor(&screen_name);
1490
1491 //187 is likely polymorphed version of setControllerName for different class (screen?)
1492 uint32_t vfun187_result = uiAPI.setScreenName(_this->CAppMenu_data.splash_screen, param_2);
1493 if (vfun187_result)
1494 {
1495 return;
1496 }
1497
1498 CMnuContainer *some_container = (CMnuContainer *)uiAPI.newOperator(0x340);
1499 if (some_container != NULL)
1500 {
1501 uiAPI.initializeMenuContainer(some_container);
1502 }
1503 uiAPI.CMnuBaseSetName((CMnuBase *)some_container, param_2);
1504
1505 SF_String c_bgr;
1506 SF_String c_brdr;
1507 uiAPI.SFStringConstructor_char(&c_bgr, "");
1508 uiAPI.SFStringConstructor_char(&c_brdr, "");
1509 uiAPI.setupMenuContainerData(some_container, 0.0, 0.0, 0.0, 0.0, &c_bgr, &c_brdr);
1510 uiAPI.SFStringDestructor(&c_brdr);
1511 uiAPI.SFStringDestructor(&c_bgr);
1512
1513 uiAPI.setCanFocus((CMnuBase *)some_container, 0);
1514 //black magic, vfunction 182 equivalent pass through using 0x512ef0
1515 *(uint32_t *)(&some_container->CMnuContainer_data[0x78]) = 1;
1516 //CMnuScreen::AttachControl
1517 uiAPI.attachControlToScreen(_this->CAppMenu_data.splash_screen, (CMnuBase *)some_container, 0);
1518 *param_1 = some_container;
1519
1520 CMnuContainer *another_container = (CMnuContainer *)uiAPI.newOperator(0x340);
1521 if (another_container != NULL)
1522 {
1523 uiAPI.initializeMenuContainer(another_container);
1524 }
1525 SF_String another_cont_name;
1526 uiAPI.SFStringConstructor_char(&another_cont_name,"<Cont>IndDisp");
1527 uiAPI.CMnuBaseSetName((CMnuBase *)another_container, &another_cont_name);
1528 uiAPI.SFStringDestructor(&another_cont_name);
1529
1530 uint32_t campaign_type = _this->CAppMenu_data.campaign_type;
1531
1532 char *loading_name = uiAPI.SFStringCMbStr(map_name);
1533 const char *matched_msb = find_screen_for_map(loading_name);
1534
1535 uiAPI.SFStringConstructor_char(&c_brdr, "");
1536 if (matched_msb != NULL)
1537 {
1538 uiAPI.SFStringConstructor_char(&c_bgr, matched_msb);
1539 }
1540 else
1541 {
1542 switch (campaign_type)
1543 {
1544 case 0: uiAPI.SFStringConstructor_char(&c_bgr, "ui_mainmenu_bg_loading_sf1.msb"); break;
1545 case 1: uiAPI.SFStringConstructor_char(&c_bgr, "ui_mainmenu_bg_loading_sf1addon01.msb"); break;
1546 case 2: uiAPI.SFStringConstructor_char(&c_bgr, "ui_mainmenu_bg_loading_sf1addon02.msb"); break;
1547 default: uiAPI.SFStringConstructor_char(&c_bgr, "ui_mainmenu_bg_loading_sf1.msb"); break;
1548 }
1549 }
1550 uiAPI.setupMenuContainerData(another_container, 0.0, 0.0, 0.0, 0.0, &c_bgr, &c_brdr);
1551 uiAPI.SFStringDestructor(&c_brdr);
1552 uiAPI.SFStringDestructor(&c_bgr);
1553
1554 uiAPI.setCanFocus((CMnuBase *)another_container, 0);
1555 //black magic, vfunction 182 equivalent 0x512ef0
1556 *(uint32_t *)(&another_container->CMnuContainer_data[0x78]) = 1;
1557 uiAPI.containerAddControl(some_container, (CMnuBase *)another_container, 0, 1, 0);
1558
1559 CMnuLabel *progress_label = (CMnuLabel *)uiAPI.newOperator(0x368);
1560 if (progress_label != NULL)
1561 {
1562 uiAPI.menuLabelConstructor(progress_label);
1563 }
1564 _this->CAppMenu_data.progress_label = progress_label;
1565 SF_String label_name;
1566 uiAPI.SFStringConstructor_char(&label_name, "<Ctrl>lbSplash");
1567 uiAPI.CMnuBaseSetName((CMnuBase *)_this->CAppMenu_data.progress_label, &label_name);
1568 uiAPI.SFStringDestructor(&label_name);
1569
1570 SF_String label_data;
1571 uiAPI.SFStringConstructor_char(&label_data, "");
1572 uiAPI.initMenuElement(_this->CAppMenu_data.progress_label, 308.0, 0.0, 0.0, 0.0, &label_data);
1573 uiAPI.SFStringDestructor(&label_data);
1574
1575 SF_FontStruct *fonts = uiAPI.getFonts();
1576 SF_Font *font = uiAPI.getFont(fonts, 7);
1577 uiAPI.menuLabelSetFont(_this->CAppMenu_data.progress_label, font);
1578 uiAPI.vfunction175(_this->CAppMenu_data.progress_label,1);
1579
1580 uiAPI.containerAddControl(another_container, (CMnuBase *)_this->CAppMenu_data.progress_label, 0, 1, 0);
1581 uiAPI.vfunction12((CMnuBase *)_this->CAppMenu_data.progress_label, 761.0, 1);
1582
1583 uiAPI.bringToFront(some_container, 0);
1584 uiAPI.vfunction163(some_container, 0);
1585 //some container vfun163
1586
1587 //offset 0x148 =1
1588 _this->CAppMenu_data.more_data2[0x70] = 1;
1589
1590}
1591
1592
1593SF_String * getMapFromSave(CAppSession *_this, char *param_1, int campaign_type)
1594{
1595 FileWrapper Wrapper;
1596 D_String filename;
1597 SF_String base_name;
1598
1599 uiAPI.SFStringConstructor_char(&base_name, param_1);
1600 //getSavePath(_this,&save_path,campaign_type);
1601 //uiAPI.SFStringConcat(&save_path, &base_name);
1602 //uiAPI.SFStringDestructor(&base_name);
1603 char *path = uiAPI.SFStringCMbStr(&base_name);
1604
1605 DStringConstructor_char (&filename, path);
1606
1607 uiAPI.SFStringDestructor(&base_name);
1608 FileWrapperInit(&Wrapper);
1609
1610 if (FileWrapperOpen(&Wrapper, &filename, 0) != 0)
1611 {
1612 uint8_t AC57[0x2803c];
1613 AC57_Init(AC57, &Wrapper);
1614 SF_CGdWorld *temp_world = (SF_CGdWorld *)calloc(0x832341, 1);
1615 SF_String *output = (SF_String *)calloc(0x10, 1);
1616 uiAPI.SFStringConstructor(output);
1617 readMapNameFromSave(temp_world, AC57);
1618 uiAPI.SFStringCopy(output, &temp_world->map_name);
1619 free(temp_world);
1620 FileWrapperClose(&Wrapper);
1621 AC57_Dispose(AC57);
1622 return output;
1623 }
1624
1625 return NULL;
1626}
1627
1628
1629void __thiscall CreateSplashScreen(CAppMenu *_this, CMnuContainer **param_1, SF_String *param_2)
1630{
1631 CAppSession *session = _this->CAppMenu_data.CAppSession;
1632 char *save_path = uiAPI.SFStringCMbStr(&_this->CAppMenu_data.game_info.filename);
1633 int campaign_type = _this->CAppMenu_data.campaign_type;
1634 wchar_t *test_var = (wchar_t *)(*(uint32_t *)(&session->data.unknwn_data[0xa0]));
1635 if (test_var != NULL)
1636 {
1637 SF_String map_name;
1638 uiAPI.SFStringConstructor_wchar(&map_name, test_var);
1639 log_info ("1 Map name from portal change %ls", map_name.raw_data);
1640 CreateSplashScreenHelper(_this, param_1, param_2, &map_name);
1641 log_info ("2 Map name from portal change %ls", map_name.raw_data);
1642 uiAPI.SFStringDestructor(&map_name);
1643 }
1644 else
1645 {
1646 SF_String *map_name = getMapFromSave(session, save_path, campaign_type);
1647 if (map_name != NULL)
1648 {
1649 CreateSplashScreenHelper(_this, param_1, param_2, map_name);
1650 log_info ("Map name from save: %ls", map_name->raw_data);
1651 uiAPI.SFStringDestructor(map_name);
1652 free(map_name);
1653 }
1654 }
1655
1656 //createSplashScreen(_this, param_1, param_2);
1657
1658}
1659
1660static void splash_screen_hook()
1661{
1662 ASI::MemoryRegion mreg(ASI::AddrOf(0x18359f), 5);
1663 ASI::BeginRewrite(mreg);
1664 *(unsigned char *)(ASI::AddrOf(0x18359f)) = 0xE8;
1665 *(int *)(ASI::AddrOf(0x1835a0)) = (int)(&CreateSplashScreen)- ASI::AddrOf((0x1835a4));
1666 ASI::EndRewrite(mreg);
1667
1668 ASI::MemoryRegion mreg2(ASI::AddrOf(0x1856fe), 5);
1669 ASI::BeginRewrite(mreg2);
1670 *(unsigned char *)(ASI::AddrOf(0x1856fe)) = 0xE8;
1671 *(int *)(ASI::AddrOf(0x1856ff)) = (int)(&CreateSplashScreen)- ASI::AddrOf((0x185703));
1672 ASI::EndRewrite(mreg2);
1673
1674}
1675
1677{
1678 add_item = (add_item_ptr)(ASI::AddrOf(0x260d70));
1679
1685
1697
1699
1705 AC57_Init = (AC57_Init_ptr)(ASI::AddrOf(0x386460));
1707
1709
1710 log_info("| - Vanilla Fix Hooks");
1711 figure_statistic_hook_current_ac();
1712 figure_statistic_hook_current_agi();
1713 figure_statistic_hook_current_cha();
1714 figure_statistic_hook_current_dex();
1715 figure_statistic_hook_current_int();
1716 figure_statistic_hook_current_hp();
1717 figure_statistic_hook_current_mp();
1718 figure_statistic_hook_current_sta();
1719 figure_statistic_hook_current_str();
1720 figure_statistic_hook_current_wis();
1721 figure_statistic_hook_current_fire_res();
1722 figure_statistic_hook_current_ice_res();
1723 figure_statistic_hook_current_mental_res();
1724 figure_statistic_hook_current_black_res();
1725 figure_statistic_hook_current_walk_spd();
1726 figure_statistic_hook_current_fight_spd();
1727 figure_statistic_hook_current_cast_spd();
1728 salvo_fix_hook();
1729 get_race_fix_hook();
1730 army_size_fix_hook();
1731 figure_turn_off_battle_mode_hook();
1732 splash_screen_hook();
1733
1734}
RegistrationFunctions * registrationAPI
Definition TestMod.cpp:14
SpellFunctions * spellAPI
Definition TestMod.cpp:11
FigureFunctions * figureAPI
Definition TestMod.cpp:13
ToolboxFunctions * toolboxAPI
Definition TestMod.cpp:12
SF_String *(__thiscall * AC95_get_figure_name_ptr)(void *AC95, SF_String *name_buffer, uint32_t figure_id)
AC95_get_figure_name_ptr AC95_get_figure_name
void __thiscall sf_endspell_hook(SF_CGdSpell *_this, uint16_t spell_index)
EffectFunctions effectAPI
Definition sf_hooks.c:45
UiFunctions uiAPI
Definition sf_hooks.c:50
IteratorFunctions iteratorAPI
Definition sf_hooks.c:49
BuildingFunctions buildingAPI
Definition sf_hooks.c:47
AiFunctions aiAPI
Definition sf_hooks.c:51
const char * find_screen_for_map(const char *map_name)
Finds the loading screen mesh for a map, or NULL for the default.
void log_info(const char *format,...)
int AddrOf(int offset)
returns "real" virtual address of given memory offset
Definition sf_asi.h:135
bool BeginRewrite(MemoryRegion &mem_region)
allows rewriting code in a given memory region by overwriting permissions for that memory region
Definition sf_asi.cpp:6
bool EndRewrite(MemoryRegion &mem_region)
ends rewriting by restoring old permissions in a given memory region
Definition sf_asi.cpp:14
enchant_handler_ptr get_enchant_handler(uint16_t spell_line)
@ SIEGE_AURA_SPELL
uint16_t(__thiscall * enchant_handler_ptr)(SF_CGdFigure *_this, uint16_t figure_id)
createSplashScreen_ptr createSplashScreen
SF_String * getMapFromSave(CAppSession *_this, char *param_1, int campaign_type)
uint32_t(__thiscall * GetResourceSpellLine_ptr)(SF_CGdResource *_this, uint16_t spell_line_id, SF_CGdResourceSpellLine *value)
onFigureBattleEnd_ptr onFigureBattleEnd
bool(__thiscall * getTextString_ptr)(SF_CGdResource *_this, uint16_t text_id, char *out_string)
uint16_t __thiscall get_figure_statistic_current_black_res(SF_CGdFigure *_this, uint16_t figure_id)
void __thiscall decreaseUsedArmyUnitCount(SF_CGdPlayer *_this, uint16_t owner, uint8_t side)
uint16_t __thiscall get_figure_statistic_max_mp(SF_CGdFigure *_this, uint16_t figure_id)
uint16_t __thiscall get_figure_statistic_current_fire_res(SF_CGdFigure *_this, uint16_t figure_id)
uint16_t(__thiscall * getUnitStringID_ptr)(SF_CGdResource *_this, uint16_t unit_id)
SF_String *(__cdecl * getSpecialDesc_ptr)(SF_String *param_1, uint32_t param_2)
SF_String *(__thiscall * GetItemInfo_ptr)(SF_CGdResource *_this, CGdResourceWeaponData *stats, uint16_t item_id)
uint16_t __thiscall get_figure_statistic_current_wis(SF_CGdFigure *_this, uint16_t figure_id)
void(__stdcall * getWeaponRangeDescription_ptr)(SF_String *param_1, uint16_t param_2, uint16_t param_3, SF_String *param_4, uint8_t param_5)
uint16_t __thiscall get_figure_statistic_current_agi(SF_CGdFigure *_this, uint16_t figure_id)
SF_String *(__thiscall * ExpandSpellDescription_ptr)(AutoClass101 *_this, SF_String *out_string, SF_String *in_string, SF_CGdResourceSpell *param_3)
void(__thiscall * createSplashScreen_ptr)(CAppMenu *_this, CMnuContainer **param_1, SF_String *param_2)
void(__thiscall * readMapNameFromSave_ptr)(SF_CGdWorld *_this, void *AC57)
GetResourceSpellLine_ptr GetResourceSpellLine
GetWeaponEffects_ptr GetWeaponEffects
AC34calculateWeaponSpeed_ptr AC34calculateWeaponSpeed
FileWrapperOpen_ptr FileWrapperOpen
uint16_t __thiscall get_figure_statistic_current_dex(SF_CGdFigure *_this, uint16_t figure_id)
uint16_t __thiscall get_figure_statistic_current_int(SF_CGdFigure *_this, uint16_t figure_id)
uint16_t __thiscall get_figure_statistic_current_hp(SF_CGdFigure *_this, uint16_t figure_id)
GetWeaponType_ptr GetWeaponType
getWeaponRangeDescription_ptr getWeaponRangeDescription
void prepareHPString(AutoClass101 *_this, SF_CGdFigure *figures, uint16_t figure_id, SF_String *out_string)
void CreateSplashScreenHelper(CAppMenu *_this, CMnuContainer **param_1, SF_String *param_2, SF_String *map_name)
AC57_Init_ptr AC57_Init
D_String *(__thiscall * DStringConstructor_char_ptr)(D_String *_this, char *source)
uint32_t(__thiscall * GetDamageMultiplierPerLevel_ptr)(SF_CGdResource *_this, uint8_t level)
DStringConstructor_char_ptr DStringConstructor_char
GetDamageMultiplierPerLevel_ptr GetDamageMultiplierPerLevel
readMapNameFromSave_ptr readMapNameFromSave
uint32_t(__thiscall * AC34calculateWeaponSpeed_ptr)(void *_this, uint32_t base_fight_speed, uint8_t race, uint16_t item_id, uint32_t dual_wield, uint32_t is_ranged)
void dump_offsets(CAppSession *_this)
void *(__thiscall * CGdMainGetAC34_ptr)(void *_this)
uint16_t __thiscall get_figure_statistic_current_fight_spd(SF_CGdFigure *_this, uint16_t figure_id)
void(__thiscall * FileWrapperClose_ptr)(FileWrapper *_this)
void(__thiscall * GetDescriptionText_ptr)(void *_this, uint32_t param_1, SF_String *name_buffer)
SF_String *__thiscall getSpecialFigureName(SF_CGdFigureToolbox *_this, SF_String *in_string, uint16_t figure_id)
uint16_t __thiscall get_figure_statistic_max_sta(SF_CGdFigure *_this, uint16_t figure_id)
void __thiscall figureTurnOffBattleMode(SF_CGdBattleDevelopment *_this)
void(__cdecl * GetColoredText_ptr)(SF_String *param_1, uint32_t param_2)
void initialize_vanilla_fix_hooks()
uint16_t __thiscall get_figure_statistic_current_mp(SF_CGdFigure *_this, uint16_t figure_id)
void prepareDamageString(AutoClass101 *_this, SF_CGdFigure *figures, uint16_t figure_id, CGdResourceWeaponData *weapon_data, SF_String *out_string)
void prepareSpellsHeaderString(AutoClass101 *_this, SF_String *out_string)
SF_String *__thiscall portrait_overlay_hook(AutoClass101 *_this, SF_String *param_1, uint16_t figure_id, uint32_t param3, uint32_t param4, uint32_t param5)
void prepareSpellString(AutoClass101 *_this, SF_String *out_string, uint16_t spell_id)
uint16_t __thiscall get_figure_statistic_current_mental_res(SF_CGdFigure *_this, uint16_t figure_id)
FileWrapperClose_ptr FileWrapperClose
uint32_t __thiscall decreaseUnitCount(AutoClass46 *_this, uint16_t figure_id)
getSpecialDesc_ptr getSpecialDesc
bool __thiscall isSwarm(SF_CGdFigure *_this, uint16_t figure_id)
GetTextById_ptr GetTextById
CGdMainGetAC34_ptr CGdMainGetAC34
void(__thiscall * GetTextById_ptr)(void *_this, uint16_t text_id, SF_String *out_string)
add_item_ptr add_item
uint16_t __thiscall get_figure_statistic_current_cha(SF_CGdFigure *_this, uint16_t figure_id)
bool __thiscall isTitan(SF_CGdFigure *_this, uint16_t figure_id)
uint16_t __thiscall get_figure_statistic_current_walk_spd(SF_CGdFigure *_this, uint16_t figure_id)
uint16_t __thiscall get_figure_statistic_current_cast_spd(SF_CGdFigure *_this, uint16_t figure_id)
GetColoredText_ptr GetColoredText
void *(__thiscall * AC57_Init_ptr)(void *_this, FileWrapper *fileWrapper)
void prepareMPString(AutoClass101 *_this, SF_CGdFigure *figures, uint16_t figure_id, SF_String *out_string)
uint8_t __thiscall getEffectiveRace(SF_CGdFigure *_this, uint16_t figure_id)
ExpandSpellDescription_ptr ExpandSpellDescription
uint16_t __thiscall get_figure_statistic_current_str(SF_CGdFigure *_this, uint16_t figure_id)
GetItemInfo_ptr GetItemInfo
bool __thiscall get_salvo_target_list(SF_CGdFigureJobs *_this, SF_CGdTargetData *source, SF_CGdTargetData *target, uint32_t angle, uint16_t *ranges, uint32_t target_count, ushort_list_node *output)
getUnitStringID_ptr getUnitStringID
uint16_t __thiscall get_figure_statistic_max_hp(SF_CGdFigure *_this, uint16_t figure_id)
uint16_t *(__thiscall * GetWeaponEffects_ptr)(SF_CGdResource *_this, uint16_t *param_1, uint16_t item_id)
uint16_t __thiscall get_figure_statistic_current_ac(SF_CGdFigure *_this, uint16_t figure_id)
uint16_t __thiscall get_figure_statistic_current_sta(SF_CGdFigure *_this, uint16_t figure_id)
void(__thiscall * onFigureBattleEnd_ptr)(SF_CGdFigureToolbox *_this, uint16_t figure_id)
void prepareEffectString(AutoClass101 *_this, SF_CGdFigure *figures, uint16_t figure_id, uint16_t effect_id, SF_String *out_string)
GetDescriptionText_ptr GetDescriptionText
FileWrapperClose_ptr FileWrapperInit
AC57_Dispose_ptr AC57_Dispose
getTextString_ptr getTextString
uint16_t __thiscall get_figure_statistic_current_ice_res(SF_CGdFigure *_this, uint16_t figure_id)
uint8_t(__thiscall * GetWeaponType_ptr)(SF_CGdResource *_this, uint16_t item_id)
void __thiscall CreateSplashScreen(CAppMenu *_this, CMnuContainer **param_1, SF_String *param_2)
int(__thiscall * FileWrapperOpen_ptr)(FileWrapper *_this, D_String *path, int param_2)
void(__thiscall * AC57_Dispose_ptr)(void *_this)
void(__thiscall * add_item_ptr)(ushort_list_node *_this, uint16_t *item)
MemoryRegion is used for rewriting code in a given memory block.
Definition sf_asi.h:17
Group of functions related to AI manipulation.
SF_CGdResource * SF_CGdResource
SF_CGdPlayer * CGdPlayer
SF_CGdFigure * CGdFigure
CAppSession * CAppSession
CAppMenu_data CAppMenu_data
CAppSession_data data
uint32_t current_figure_is_hero
uint32_t current_figure_is_mainchar
EntityPriorityList enemy_figures
SF_CGdFigureToolbox * CGdFigureToolBox
SF_CGdFigure * CGdFigure
SF_CGdSpell * CGdSpell
uint8_t CMnuContainer_data[0x98]
Group of functions related to Effect manipulation.
Group of functions to manipulate the behavior and statistics of the game figures (units).
FigureStatisticExt stamina
uint16_t equipment[16]
FigureStatistic strength
uint16_t master_figure
FigureStatistic dexterity
FigureStatistic resistance_mental
FigureStatistic charisma
FigureStatistic resistance_fire
FigureStatistic cast_speed
FigureJobData current_job
FigureStatisticExt health
FigureStatistic wisdom
uint16_t unit_data_id
FigureStatisticExt mana
FigureStatistic fight_speed
FigureStatistic resistance_ice
FigureStatistic agility
FigureStatistic resistance_black
FigureStatistic walk_speed
FigureStatistic armor
FigureStatistic intelligence
uint16_t avatar_figure_index
SF_String hero_names[5]
uint16_t hero_figure_index[5]
uint16_t civilian_count[6]
uint16_t warrior_count[2]
Group of functions related to Iteration, Often used for AOE or Chain Like Spells.
A structure dedicated to the registration of spells This structure holds functions that are used to c...
High-level structure managing AI battle development.
A structure for the global list of figures and related statistics for them.
GdFigure figures[2000]
SF_CGdFigureToolbox * CGdFigureToolBox
SF_CGdResource * CGdResource
Represents a collection of function pointers for managing spell-related operations.
Holds most of the Toolbox Functions relevent for custom spells. Includes functions for the manipulati...
Group of functions related to UI manipulation.
Represents a node in a list of unsigned short values.