Advertisement
Nihthelm

Untitled

Nov 7th, 2020
152
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 15.07 KB | None | 0 0
  1. // dllmain.cpp: определяет точку входа для приложения DLL.
  2.  
  3. #include "..\..\include\patcher_x86_commented.hpp"
  4. #include "..\..\include\HotA\HoMM3.h"
  5. #include "..\..\include\h3sw_ids.h"
  6. #include "..\..\include\era.h"
  7.  
  8. #include <math.h>
  9.  
  10. Patcher * globalPatcher;
  11. PatcherInstance *patcher;
  12.  
  13. bool HasAdditionalSpell(_Hero_* hero, int spell)
  14. {  
  15.     char erm_command[256];
  16.     sprintf(erm_command,"SN:W^new_spells_%i_%i^/?v1;",hero->id,spell);
  17.     ExecErmCmd(erm_command);
  18.  
  19.     return ErmV[1];
  20. }
  21.  
  22. bool HasSpell(_Hero_* hero, int spell)
  23. {
  24.     if(spell < 70)
  25.         return hero->spell[spell];
  26.     else
  27.         return HasAdditionalSpell(hero, spell);
  28. }
  29.  
  30. void GiveSpell(_Hero_* hero, int spell)
  31. {
  32.     if(spell < 70)
  33.     {
  34.         hero->spell[spell] = 1;
  35.         hero->spell_level[spell] = 1;
  36.     }
  37.     else
  38.     {
  39.         char erm_command[256];
  40.         sprintf(erm_command,"SN:W^new_spells_%i_%i^/1;",hero->id,spell);
  41.         ExecErmCmd(erm_command);
  42.     }
  43. }
  44.  
  45. int __stdcall GiveSpell_hook(HiHook* h, _Hero_* hero, int spell)
  46. {
  47.     GiveSpell(hero, spell);
  48.     return spell;
  49. }
  50.  
  51. int __stdcall HasSpellLoHook(LoHook* h, HookContext* c)
  52. {
  53.     _Hero_* hero = (_Hero_*)(c->ecx);
  54.     int spell = c->edi;
  55.  
  56.     if(spell < 70)
  57.     {
  58.         return EXEC_DEFAULT;
  59.     }
  60.     else
  61.     {
  62.         c->eax =  HasAdditionalSpell(hero,spell);
  63.         c->return_address = 0x59CD62;
  64.         return NO_EXEC_DEFAULT;
  65.     }
  66. }
  67.  
  68.  
  69. //
  70. int __stdcall SpellChosen(LoHook* h, HookContext* c)
  71. {
  72.     int spell = c->ebx;
  73.    
  74.     if(spell < 70)
  75.     {
  76.         return EXEC_DEFAULT;  
  77.     }
  78.     else
  79.     {
  80.         c->return_address = 0x59F06A;
  81.         return NO_EXEC_DEFAULT;
  82.     }
  83.     return NO_EXEC_DEFAULT;
  84. }
  85.  
  86.  
  87. //c
  88. int __stdcall SpellCast(LoHook* h, HookContext* c)
  89. {
  90.     int spell = c->edx;
  91.     _BattleStack_* target = (_BattleStack_*)(c->edi);
  92.     int spellpower = *(int*)(c->ebp+0x1C);
  93.     int DHp = *(int*)(c->ebp-0x3C);
  94.     _Hero_* hero = *(_Hero_**)(c->ebp-0x14);
  95.     //ebx - комбат менеджер 005A0E4B
  96.  
  97.     if(spell < 81)
  98.         return EXEC_DEFAULT;  
  99.    
  100.     if(spell == 82)
  101.     {  
  102.         _Pcx16_* p = _Pcx16_::CreateNew("testt",400,450);
  103.  
  104.         target->def->Draw_Transparent(0,0,
  105.             0,0,target->def->width,target->def->height,
  106.             p->buffer,0,0,p->width,p->height,p->scanline_size,0,0);
  107.  
  108.         p->DrawSurface16(0,0,p->width, p->height,
  109.             o_WndMgr->screen_pcx16->buffer,0,0,o_WndMgr->screen_pcx16->width,
  110.                 o_WndMgr->screen_pcx16->height,
  111.                 o_WndMgr->screen_pcx16->scanline_size,
  112.                 0);
  113.          
  114.         /*
  115.         //Calculate Damage CombatMan_ApplyMagicDamage
  116.         int dmg = CALL_7(int, __thiscall, 0x5A7BF0,o_BattleMgr,99,spell,hero,DHp,target,1);
  117.         //Make a damage combatMonster_DoPhysicalDamage
  118.         int dmg2 = CALL_2(int, __thiscall, 0x443DB0, target, dmg);
  119.         //Выставить необходимость проиграть анимацию урона
  120.         target->fireshield = 1;
  121.         //Проиграть анимацию спелла CombatMan_00468570_DoHitAnimation
  122.         CALL_3(void, __thiscall,0x468570,o_BattleMgr, 13, 1);
  123.         //Надпись в лог CombatMan_ReportDamageDoneCreaturesKilled   
  124.         CALL_6(void, __thiscall,0x469670,o_BattleMgr,o_Spell[spell].name,1,dmg,target,dmg2);
  125.         //Обновить экран?? CombatMan_00469020
  126.         CALL_1(void, __thiscall,0x469020,o_BattleMgr);*/
  127.  
  128.         //CALL_5(void,__thiscall, 0x4963C0,o_BattleMgr, 1, target, 10, 0);
  129.         c->return_address = 0x5A2368;
  130.         return NO_EXEC_DEFAULT;
  131.     }
  132.     if(spell == 83)
  133.     {
  134.         int casterKind = 0;
  135.         int anim_def = 31;
  136.         int spell_level = c->esi;
  137.         //Mass apply buff
  138.         CALL_7(int, __thiscall, 0x5A69E0,o_BattleMgr, hero, 53, spell_level, spellpower, o_BattleMgr->current_side, casterKind);
  139.         //
  140.         CALL_4(int, __thiscall, 0x5A8C60,o_BattleMgr, casterKind, 83, 0);
  141.         CALL_4(int, __thiscall, 0x5A6AD0,o_BattleMgr, c->ebx + 0x547C, anim_def, 0);
  142.         //c->return_address = 0x5A2368;
  143.         //return NO_EXEC_DEFAULT;
  144.     }
  145.     if(spell == 84)
  146.     {
  147.         int casterKind = 0;
  148.         int anim_def = 19;
  149.         int spell_level = c->esi;
  150.         //Mass apply buff
  151.         CALL_7(int, __thiscall, 0x5A69E0,o_BattleMgr, hero, 54, spell_level, spellpower, o_BattleMgr->current_side, casterKind);
  152.         //
  153.         CALL_4(int, __thiscall, 0x5A8C60,o_BattleMgr, casterKind, 84, 0);
  154.         CALL_4(int, __thiscall, 0x5A6AD0,o_BattleMgr, c->ebx + 0x547C, anim_def, 0);
  155.         //c->return_address = 0x5A2368;
  156.         //return NO_EXEC_DEFAULT;
  157.     }
  158.     return EXEC_DEFAULT;  
  159. }
  160.  
  161. _BattleAnim_ new_animation_table[999];
  162. char def_name[999][16];
  163. char eff_name[999][32];
  164.  
  165. void __stdcall LoadAnims (PEvent e)
  166. {
  167.       int new_p = (int)new_animation_table;
  168.  
  169.     patcher->WriteDword(0x43F77B + 3, new_p); // Шар магога
  170.     patcher->WriteDword(0x43FB67 + 3, new_p); // Облако смерти лича
  171.     patcher->WriteDword(0x4963F9 + 2, new_p); // Стандартная анимация на стеке
  172.     patcher->WriteDword(0x4965CD + 2, new_p); // Стандартная анимация на гексе
  173.     patcher->WriteDword(0x5A5033 + 3, new_p); // Армагеддон
  174.     patcher->WriteDword(0x5A6B11 + 3, new_p); // Массовое колдовство
  175.     patcher->WriteDword(0x5A7A71 + 3, new_p); // Воскрешение
  176.     patcher->WriteDword(0x5A9629 + 3, new_p); // Загрузка анимации
  177.  
  178.     patcher->WriteDword(0x4689C1 + 3, new_p + 4); // Проигрывание действия отрисовки
  179.     patcher->WriteDword(0x496518 + 2, new_p + 4); // Стандартная анимация на стеке
  180.     patcher->WriteDword(0x4966CB + 2, new_p + 4); // Стандартная анимация на гексе
  181.     patcher->WriteDword(0x5A6D2A + 3, new_p + 4); // Массовое колдовство
  182.     patcher->WriteDword(0x5A7B03 + 3, new_p + 4); // Загрузка анимации
  183.  
  184.     patcher->WriteDword(0x43E500 + 3, new_p + 8); // Отрисовка стека
  185.  
  186.     // Правки количества анимаций.
  187.     patcher->WriteByte(0x4963E7 + 2, 127); // Стандартная анимация на стеке
  188.     patcher->WriteByte(0x4965BB + 2, 127); // Стандартная анимация на гексе
  189.  
  190.     _Txt_* txt = o_LoadTxt("magicani.txt");
  191.     if(txt != 0)
  192.     {
  193.         for(int i = 0; i!=127; i++)
  194.         {
  195.             _TxtLine_* corresponding_line = txt->Lines[i+1];
  196.  
  197.             strcpy((char*)(def_name[i]),corresponding_line->items[1]);
  198.             o_BattleAnimation[i].DefName = def_name[i];
  199.            
  200.             strcpy((char*)(eff_name[i]),corresponding_line->items[2]);
  201.             o_BattleAnimation[i].TouchEffect_Name = eff_name[i];
  202.  
  203.             o_BattleAnimation[i].Properties =
  204.                 atoi(corresponding_line->items[3]) |
  205.                 atoi(corresponding_line->items[4]) << 8;
  206.  
  207.         }
  208.  
  209.         txt->DerefOrDestruct();
  210.     }
  211.  
  212. }
  213.  
  214.  
  215. int __stdcall ReadSptraitsLineHook(HiHook* h, _Txt_** file_ptr, int spell, int line_num)
  216. {  
  217.     _Txt_* file = *file_ptr;
  218.     char* anim_ix = file->Lines[line_num]->items[33];
  219. /*
  220. char mess[255];
  221.     sprintf(mess,"%s %i", anim_ix,  atoi(anim_ix) );
  222.     MessageBoxA(0,(LPCSTR)mess,"",0);*/
  223.  
  224.     if(*anim_ix)
  225.         o_Spell[spell].animation_ix = atoi(anim_ix);
  226.    
  227.     o_Spell[spell].flags = 0;
  228.     for(int i = 0; i!=32; i++)
  229.     {
  230.         char* flag = file->Lines[line_num]->items[35+i];
  231.  
  232.         if(*flag)
  233.             o_Spell[spell].flags |= 1 << i;
  234.     }
  235.  
  236.     return CALL_3(int,__cdecl,h->GetOriginalFunc(),file_ptr,spell,line_num);
  237. }
  238.  
  239. int Ray(_BattleMgr_ *cmgr,  int a1, //edx
  240.                             int a2, //1
  241.                             int a3, //start x
  242.                             int a4, //start y
  243.                             int a5, //target x
  244.                             int a6, //target y
  245.                             int a7, //150
  246.                             int a8, // 100
  247.                             int a9, //9 толщина по x
  248.                             int a10, //2 толщина по y
  249.                             int a11, //color
  250.                             int a12, //param
  251.                             int a13, //param2
  252.                             int a14, //размер секции (уменьшение луч затормаживает)
  253.                             int a15, // не используется!
  254.                             int a16,
  255.                             int a17, //интервал между кадрами
  256.                             int a18 //не используется!
  257.                             )
  258. {
  259.     return CALL_19(int,__fastcall,0x5A5F30,cmgr,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16,a17,a18);
  260. }
  261.  
  262. int savedspell = -1;
  263.  
  264. int __stdcall LightningStrikeAnim(HiHook* h, _BattleMgr_ *cmgr, int animId, _BattleStack_ *target, int timeStep, char showHitting)
  265. {  
  266.     /*char mess[255];
  267.     sprintf(mess,"%i %i", savedspell, cmgr->current_spell_id);
  268.     MessageBoxA(0,(LPCSTR)mess,"",0);*/
  269.  
  270.     _Hero_* hero = cmgr->hero[cmgr->current_side];
  271.     _HeroCombatDef_ hero_def = o_HeroCombatDefs[(hero->_class & 0xFE) + hero->sex];
  272.      
  273.     int hero_x = 0;
  274.     if (cmgr->current_side == 0)
  275.         hero_x = hero_def.CastX - 43;
  276.     else
  277.         hero_x = 693 - hero_def.CastX;
  278.  
  279.     int hero_y = hero_def.CastY - 19;
  280.  
  281.     if(savedspell != 57)
  282.     {
  283.         //CALL_1(void, __thiscall, 0x4F8A50, 100.0);
  284.         CALL_19(int,__fastcall,0x5A5F30,cmgr,500,0,hero_x,hero_y,target->GetX(),target->GetY(),150,100,9,2,65504,-40,40,15/*BattleAnimPeriodFactors[Settind_BattleFast]*/,1,0,3,1);
  285.         //cmgr->FlipBattlefield();
  286.         cmgr->RedrawBattlefield( 1, 0, 0, 0, 1, 0);
  287.         return 1;
  288.     }
  289.     else
  290.     {
  291.         /*_Def_* def = o_LoadDef("default.def");
  292.         for(int i = 100; i<= 300; i+=20)
  293.         {
  294.             def->Draw_Transparent(0,0,0,0,def->width,def->height,o_WndMgr->screen_pcx16->buffer,i,i,o_WndMgr->screen_pcx16->width, o_WndMgr->screen_pcx16->height, o_WndMgr->screen_pcx16->scanline_size,0,0);
  295.             CALL_1(void,__thiscall,0x493300,cmgr);
  296.             WaitTill(o_GetTime()+100);
  297.         }
  298.         def->DerefOrDestruct();*/
  299.  
  300.  
  301.         int colors[]=
  302.         {63488,65504,63488,63488,65504,63488,63488,65504,63488,63488,65504};
  303.         for(int i = 0; i!=10; i++)
  304.             CALL_19(int,__fastcall,0x5A5F30,cmgr,500,0,hero_x,hero_y,target->GetX(),target->GetY(),150,100,3,3,colors[i],0,0,1000/*BattleAnimPeriodFactors[Settind_BattleFast]*/,1,0,45,1);
  305.  
  306.         cmgr->RedrawBattlefield( 1, 0, 0, 0, 1, 0);
  307.        
  308.         return 1;
  309.     }
  310. }
  311.  
  312.  
  313. int __stdcall RainbowAnim(HiHook* h, _BattleMgr_ *cmgr, int animId, _BattleStack_ *target, int timeStep, char showHitting)
  314. {    
  315.     CALL_19(int,__fastcall,0x5A5F30,cmgr,500,0,cmgr->current_side*800,0,target->GetX(),target->GetY(),0,0,15,15,300,40,40,10,1,0,15,1);
  316.    
  317.     //CALL_19(int,__fastcall,0x5A5F30,cmgr,500,50,50,0,target->GetX(),target->GetY(),0,0,15,15,303,40,40,10,1,0,15,1);
  318.     cmgr->RedrawBattlefield( 1, 0, 0, 0, 1, 0);
  319.     return 1; //CALL_5(int,__thiscall,h->GetOriginalFunc(),cmgr,animId,target,timeStep,showHitting);
  320. }
  321.  
  322.  
  323. int __stdcall ColdRayAnim(HiHook* h, _BattleMgr_ *cmgr, int v264, signed int skillLevel, int target_x, int target_y, int five, int a7, int a8)
  324. {
  325.     int interval = 18;
  326.  
  327.     _Hero_* hero = cmgr->hero[cmgr->current_side];
  328.     _HeroCombatDef_ hero_def = o_HeroCombatDefs[(hero->_class & 0xFE) + hero->sex];
  329.      
  330.     int hero_x = 0;
  331.     if (cmgr->current_side == 0)
  332.         hero_x = hero_def.CastX - 43;
  333.     else
  334.         hero_x = 693 - hero_def.CastX;
  335.  
  336.     int hero_y = hero_def.CastY - 19;
  337.  
  338.     int width = target_x - hero_x ;
  339.     int height = target_y - hero_y;
  340.    
  341.  
  342.     double line = sqrt(0.0 + width * width + height*height);
  343.     int cadres = (int)(line / interval);
  344.  
  345.     _Def_* def = o_LoadDef("coldray.def");
  346.     for(int i = 0; i < cadres; i++)
  347.     {
  348.         int x = hero_x + (int)(width * i / cadres) - def->width / 2;
  349.         int y = hero_y + (int)(height * i / cadres)  - def->height / 2;
  350.  
  351.         int frame = i*10 / cadres;
  352.  
  353.         def->Draw_Transparent(0,frame,0,0,def->width,def->height,o_WndMgr->screen_pcx16->buffer,x,y,o_WndMgr->screen_pcx16->width, o_WndMgr->screen_pcx16->height, o_WndMgr->screen_pcx16->scanline_size,0,0);
  354.         CALL_1(void,__thiscall,0x493300,cmgr);
  355.         WaitTill(o_GetTime()+10*BattleAnimPeriodFactors[Settind_BattleFast]);
  356.     }
  357.     def->DerefOrDestruct();
  358.     cmgr->RedrawBattlefield( 1, 0, 0, 0, 1, 0);
  359.  
  360.     return 0;
  361. }
  362.  
  363.  
  364. int __stdcall SpellCastHook(HiHook* h, _BattleMgr_ *cmgr, int spell, signed int pos, int casterKind, int pos2, int skillLevel, int spellPower)
  365. {  
  366.     savedspell = spell;
  367.     return CALL_7(int,__thiscall,h->GetOriginalFunc(),cmgr,spell,pos,casterKind,pos2,skillLevel,spellPower);
  368. }
  369.  
  370.  
  371. int SelectByRoulette(int spells[])
  372. {
  373.     int sum = 0;
  374.     for(int i = 0; i!=200;i++)
  375.         sum = spells[i];
  376.    
  377.     if(sum == 0)
  378.         return -1;
  379.  
  380.     int r = Randint(0,sum);
  381.     for(int i =0; i!=200; i++)
  382.     {
  383.         r-=spells[i];
  384.         if (r<0)
  385.             return i;
  386.     }
  387.     return -1;
  388. }
  389.  
  390. int __stdcall TownSpellGenerate(HiHook* h, _Town_* town, int some_ptr)
  391. {  
  392.     int ret = CALL_2(int,__thiscall,h->GetOriginalFunc(),town,   some_ptr);
  393.  
  394.     ///char* prohibited = (char*)(some_ptr + 112);
  395.     //char* enforced   = (char*)(some_ptr + 124);
  396.  
  397.     int spell_prohibited [200];
  398.     int spell_enforced   [200];
  399.  
  400.     for(int i = 0; i!= 70; i++)
  401.     {
  402.         int off = i / 8;
  403.         int mask = 1 << (i % 8);
  404.  
  405.         //if((prohibited >> i) & 1)
  406.         if(*(char*)(some_ptr + 112 + off) & mask)
  407.         {
  408.             spell_prohibited[i] = 1;
  409.             MessageBoxA(0,(LPCSTR)o_Spell[i].name,"Prohibited",0);
  410.         }
  411.         else
  412.         {
  413.             spell_prohibited[i] = 0;
  414.         }
  415.     }
  416.  
  417.     for(int i = 0; i!= 70; i++)
  418.     {
  419.         int off = i / 8;
  420.         int mask = 1 << (i % 8);
  421.  
  422.         if(*(char*)(some_ptr + 124 + off) & mask)
  423.         {
  424.             spell_enforced[i] = 1;
  425.             MessageBoxA(0,(LPCSTR)o_Spell[i].name,"enforced",0);
  426.         }
  427.         else
  428.         {
  429.             spell_enforced[i] = 0;
  430.         }
  431.     }  
  432.  
  433.     //для каждого уровня
  434.     //подсчитать, сколько нам надо сгенерировать чар:
  435.     //количество чар на уровне ГМ минус принудительно выставляемые
  436.     //
  437.  
  438.     int level = 1;
  439.     int pool[200];
  440.     int spell_count = 5;
  441.  
  442.     for(int i = 0; i!=200; i++)
  443.     {
  444.         if(o_Spell[i].level == level && !spell_prohibited[i] && !spell_enforced[i])
  445.         {
  446.             pool[i] = o_Spell[i].chance2get_var[town->type];
  447.         }
  448.         else
  449.         {
  450.             pool[i]=0;
  451.         }
  452.     }
  453.  
  454.  
  455.  
  456.     return ret;
  457. }
  458.  
  459. BOOL APIENTRY DllMain( HMODULE hModule,
  460.                        DWORD  ul_reason_for_call,
  461.                        LPVOID lpReserved
  462.                      )
  463. {
  464.     if (ul_reason_for_call == DLL_PROCESS_ATTACH)
  465.     {  
  466.         globalPatcher = GetPatcher();
  467.         patcher =  globalPatcher->CreateInstance("h3sw_spells");
  468.         ConnectEra();
  469.  
  470.         patcher->WriteHiHook(0x4D95A0,SPLICE_,EXTENDED_, THISCALL_, (void*)GiveSpell_hook);
  471.  
  472.         //Spell book
  473.         patcher->WriteLoHook(0x59CD5B,(void*)HasSpellLoHook);
  474.         patcher->WriteDword(0x59CDBF,0x2530+0x88*40);
  475.  
  476.         //Spell chosen
  477.         patcher->WriteLoHook(0x59EFD4,(void*)SpellChosen);
  478.  
  479.         //Spell cast
  480.         patcher->WriteLoHook(0x5A0649,(void*)SpellCast);
  481.  
  482.         //patcher->WriteHiHook(0x5BEA00,SPLICE_,EXTENDED_,THISCALL_,(void*)TownSpellGenerate);
  483.  
  484.         //расширение текстовика для заклинаний
  485.         patcher->WriteHiHook(0x775990,SPLICE_,EXTENDED_, CDECL_, (void*)ReadSptraitsLineHook);
  486.         //создание текстовика для анимаций
  487.         RegisterHandler(LoadAnims,"OnAfterCreateWindow");
  488.  
  489.         patcher->WriteHiHook(0x5A0140,SPLICE_,EXTENDED_,THISCALL_,(void*)SpellCastHook);
  490.  
  491.         //Правки эффектов для существующих чар
  492.         patcher->WriteHiHook(0x5A0E25,CALL_,EXTENDED_, THISCALL_,(void*)LightningStrikeAnim); //молния и грохот титанов
  493.         patcher->WriteHiHook(0x5A6726,CALL_,EXTENDED_, THISCALL_,(void*)LightningStrikeAnim); //цепная молния
  494.         patcher->WriteDword(0x5A67EB,65504); //замена цвета сегментов цепной молнии
  495.  
  496.         patcher->WriteHiHook(0x5A0D71,CALL_,EXTENDED_, THISCALL_,(void*)ColdRayAnim); //снаряд ледяной молнии
  497.        
  498.         patcher->WriteHiHook(0x43F6F1,CALL_,EXTENDED_, THISCALL_,(void*)RainbowAnim); //молния и грохот титанов
  499.        
  500.     }
  501.     return TRUE;
  502. }
  503.  
  504.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement