Wake of Gods Forum | Форум Во Имя Богов

Full Version: Исследование героев
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
Quote:Вообще польза от использования патчера в этом конкретном случае достаточно сомнительна.

Чтоб не на ассемблере писать, тащемта
Ну это уже личный выбор каждого.
Вроде бы немного разобрался, спасибо.
Немного переделал регенерацию.
Code:
// dllmain.cpp: определяет точку входа для приложения DLL.
#include "stdafx.h"

#include "..\..\include\patcher_x86_commented.hpp"
#include "..\..\include\HotA\HoMM3.h"
#include "..\..\include\era.h"

Patcher * globalPatcher;
PatcherInstance *patcher;

int __stdcall RegenerationCheck (LoHook* h, HookContext* c)
{
    if (((_BattleStack_*)c->esi)->count_current < ((_BattleStack_*)c->esi)->count_at_start)
    {
    c->return_address = 0x446BD3;
    }
    else
    {
        if (((_BattleStack_*)c->esi)->lost_hp > 0)
        {
        c->return_address = 0x446BD3;
        }
        else
        {
        c->return_address = 0x446DF1;
        }
    }
    return NO_EXEC_DEFAULT;
}

int __stdcall RegenerationFull (LoHook* h, HookContext* c)
{
    int regen = *(int*)0x2846BC8;
    int number = ((_BattleStack_*)c->esi)->count_current;
    int bnumber = ((_BattleStack_*)c->esi)->count_at_start;
    int lowhp = ((_BattleStack_*)c->esi)->lost_hp;
    int hp = ((_BattleStack_*)c->esi)->full_hp;
    if (regen <= lowhp)
    {
        lowhp -= regen;
        ((_BattleStack_*)c->esi)->lost_hp = lowhp;
    }
    else
    {
        regen -= lowhp;
        int count = 1;
        while (regen > hp)
        {
            regen -= hp;
            count += 1;
        }
        number += count;
        if (number > bnumber)
        {
            number = bnumber;
            lowhp = 0;
        }
        else
        {
            lowhp = hp - regen;
        }
        ((_BattleStack_*)c->esi)->lost_hp = lowhp;
        ((_BattleStack_*)c->esi)->count_current = number;
    }

    c->return_address = 0x446C3F;
    return NO_EXEC_DEFAULT;
}

int __stdcall Regeneration (LoHook* h, HookContext* c)
{
    int unit = c->eax;
    int regenhp = 0;
    if (unit == 4 || unit == 46 || unit == 47 || unit == 61)
    {
        regenhp += 40;
    }
    if (unit == 5)
    {
        regenhp += 50;
    }
    if (unit == 60)
    {
        regenhp += 30;
    }
    if (unit == 80 || unit == 81 || unit == 144)
    {
        regenhp += 80;
    }
    if (unit == 110 || unit == 193)
    {
        regenhp += 100;
    }
    if (unit == 111 || unit == 168)
    {
        regenhp += 150;
    }
    if (unit == 157)
    {
        regenhp += 200;
    }
//    if (unit == 159)
//    {
//        regenhp += 40;
//    }
    if (regenhp > 0)
    {
        *(int*)0x2846BC8 = regenhp;
        c->return_address = 0x75DF2A;
    }
    else
    {
        c->return_address = 0x75DE8E;
    }
    return NO_EXEC_DEFAULT;
}

void __stdcall PatchIt (PEvent e)
{
        patcher->WriteLoHook(0x75DE66,(void*)Regeneration);
        patcher->WriteLoHook(0x446BCD,(void*)RegenerationCheck);
        patcher->WriteLoHook(0x446C2B,(void*)RegenerationFull);
}

BOOL APIENTRY DllMain( HMODULE hModule, DWORD  ul_reason_for_call, LPVOID lpReserved)
{
    if (ul_reason_for_call == DLL_PROCESS_ATTACH)
    {
        globalPatcher = GetPatcher();
        patcher =  globalPatcher->CreateInstance("abilities");
        ConnectEra();
        RegisterHandler(PatchIt,"OnAfterCreateWindow");
    }
    return TRUE;
}
Подскажите по двум вопросам.
1. Как добавить проверку на эликсир жизни, чтоб он добавлял еще 50 хп к регену.
2. Регенерация от опыта существ работает как-то по-другому? Этот хук не срабатывает, реген проходит без воскрешения. Как это можно исправить?
Quote:1. Как добавить проверку на эликсир жизни, чтоб он добавлял еще 50 хп к регену.

o_BattleMgr->hero[((_BattleStack_*)c->esi)->side]->DoesWearArtifact(ID), как-то так
1. Что-то типа (с указанием героя, конечно)
Code:
Era::ExecErmCmd("HE:A2/131/?v1/?v1;");
if (Era::v[1]>0) ...
2. Выдержка из исходников Вога:
Code:
void IsTroll(void)
{
  __asm{
    mov    IT_Mon,esi
    mov    edx,50 // умолчательное восстановление здоровья
    mov    IT_Edx,edx
    cmp    eax,0x3C
    je     l_Ok
    cmp    eax,0x3D
    je     l_Ok
    cmp    eax,0x90
    je     l_Ok
    cmp    eax,157 // гидра
    je     l_Ok_check
//    jmp   l_Exit
    pusha
  }
  __asm mov IDummy,eax
  #include "templ.h"
  IT_Ret=CanNPCRegenerate(IDummy,IT_Mon);
  if(IT_Ret!=-1){
    IT_Ret=CrExpBon::Regenerate(IT_Mon,*(int *)&IT_Mon[0x58]);
    if(IT_Ret==0){ // no reg
      IT_Ret=0;
    }else{ // yes
      IT_Edx=IT_Ret;
      IT_Ret=-1;
    }
  }
  STOP
  __asm{
     popa
     mov    eax,IT_Ret
//    je    _Ok_check
     jmp    l_Exit
  }
l_Ok_check:
  CalcRand100();
  __asm{
    cmp    eax,40  // 40%
    ja     l_Exit
  }
l_Ok:
  __asm mov    eax,-1
l_Exit:
  __asm mov    edx,IT_Edx
}
Это та функция, что перезаписывается по 0x446BD6.
CrExpBon::Regenerate - это стандартная регенерация от опыта.
Как можно перебрать все объекты определенного типа/подтипа кодом?
ну, то бишь, как это делает Вог в UN:U?)

..эм
пробегать всю карту каждый раз? серьезно?
feanor, думаю серьезно.
------------------------------------------------------------------
63E9B8 - % для навыков некромантии/чародейства (массив из 4 dword)
476DA0 - воскрешение нечести после боя
4E3F40 - расчет % чародейства(некромантии) с учетом артефактов и специальностей
Конечно же, если нужны не сами объекты, а только их структуры (если есть), то тут уже можно найти их список.
(17.03.2015 12:56)Дьякон Wrote: [ -> ]63E9B8 - % для навыков некромантии/чародейства (массив из 4 dword)
476DA0 - воскрешение нечести после боя
4E3F40 - расчет % чародейства(некромантии) с учетом артефактов и специальностей
А как при помощи ERM отключить навык Некромантии (со всеми артефактами, ПКН'ами и пр. усилителями некромантии)?
Через UN:C забиваешь для всех уровней некромантии 0, соответственно воскрешаться никто не будет.


Хотя не, нужно еще артефакты все отключать, т.к. там абсолютное приращение идет к %. Если нужно, то найду и выложу все адреса по некромантии.
Code:
0x63EAE4 - амулет гробовщика 5%
0x63B8D0 - мантия и усилители 10%
0x63EB28 - сапоги 15%
0x63B8B4 - грааль 20%
0x63EB24 - плащ 30%
Все обнулить и по идее будет счастье

Хотя можно сделать еще проще. Задать максимальный % воскресших 0%, который сейчас 100%. Но возможно с ним могут быть проблемы, т.к. данная константа может использоваться и в других расчетах, например как 0x63B8D0 одновременно отвечает и за мантию и за усилители.
Вот так будет (должно) работать и не нужно трогать константы:


И да константы универсальные и их правка не рекомендуется.
Спасибо, проверю на днях.
4A7530 - jmp определяющий вступят в бой или другие условия присоединиться. Отключение jmp - отключает дипломатию,т.е.
Reference URL's