Current time: 14.12.2018, 22:19 Hello There, Guest! (LoginRegister)
Language: english | russian  

Post Reply 
Threaded Mode | Linear Mode
Исследование героев
» туториал(ы)
Author Message
feanor Offline

Posts: 497
Post: #676

У меня сделано как-то так

Code:
#include "targetver.h"

#include <windows.h>
#include <stdlib.h>
#include <stdio.h>

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

Patcher * globalPatcher;
PatcherInstance *patcher;

int __stdcall StrikeAndReturn (LoHook* h, HookContext* c)
{
    int unit = c->eax;


    if (advanced_properties[unit].strike_n_ret)
    {
        if(o_CreatureInfo[unit].flags &1)
            c->return_address = 0x75E08B;
        else
            c->return_address = 0x75E0BB;
    }
    else
    {
        c->return_address = 0x75E06A;
    }
    return NO_EXEC_DEFAULT;
}


int __stdcall StrikeAndReturnButton (LoHook* h, HookContext* c)
{
    int unit = *(int*)(c->ebp-4);
    if(advanced_properties[unit].strike_n_ret)
    {
        c->return_address = 0x762969;
    }
    else
    {
        c->return_address = 0x762955;
    }
    return NO_EXEC_DEFAULT;
}


void __stdcall PatchIt (PEvent e)
{
        patcher->WriteLoHook(0x75E059,(void*)StrikeAndReturn);
        patcher->WriteLoHook(0x762940,(void*)StrikeAndReturnButton);
}

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("h2sw_creatures");
        ConnectEra();
        RegisterHandler(PatchIt,"OnAfterCreateWindow");
    }
    return TRUE;
}

правда, я еще не проверял))
(This post was last modified: 09.03.2015 18:28 by feanor.)
09.03.2015 18:27
Find all posts by this user Quote this message in a reply
major Offline

Posts: 94
Post: #677

Для таблицы же тоже место выделить надо в экзешнике? Что значит DLL_PROCESS_ATTACH, т.е. каким образом это сделать?
09.03.2015 19:04
Find all posts by this user Quote this message in a reply
gamecreator Offline
Administrators

Posts: 7146
Post: #678

Не обязательно в экзешнике, в твоей длл тоже можно. Что такое DLL_PROCESS_ATTACH у feanorа в примере очень понятно написано.


When all gods have burnt to ashes in eternity of sorrow,
Demons gonna tear your soul because there is no tomorrow.
09.03.2015 19:10
Find all posts by this user Quote this message in a reply
Дьякон Offline

Posts: 378
Post: #679

Процедура расчета для дипломатии:
0x4A73B0

Коэффициенты для расчета Power_Factor из ФизМига (см. со стр. 303)
63E500 - 7
63AC50 - 1
63B9E0 - 2
63AC70 - 0,5
63E4F8 - 0,333


Страус труп (с) Бьерн
10.03.2015 18:51
Find all posts by this user Quote this message in a reply
major Offline

Posts: 94
Post: #680

В коде феанора все более-менее понятно, но есть пара вопросов.
1. advanced_properties[unit].strike_n_ret - это свойство юнита определено где-то ранее?
2.
Code:
#include "targetver.h"

#include <windows.h>
#include <stdlib.h>
#include <stdio.h>

#include "..\..\include\patcher_x86_commented.hpp"
#include "..\..\include\HotA\HoMM3.h"
#include "..\..\include\era.h"
Чтобы скомпилировать, нужны все эти файлы?
11.03.2015 13:51
Find all posts by this user Quote this message in a reply
gamecreator Offline
Administrators

Posts: 7146
Post: #681

Судя по всему, advanced_properties - просто новый массив из Хоты. Если тебе не хочется ничего расширять, то напиши свою проверку в условии, без массивов.


When all gods have burnt to ashes in eternity of sorrow,
Demons gonna tear your soul because there is no tomorrow.
11.03.2015 14:08
Find all posts by this user Quote this message in a reply
feanor Offline

Posts: 497
Post: #682

Quote:1. advanced_properties[unit].strike_n_ret - это свойство юнита определено где-то ранее?
да

Quote:Чтобы скомпилировать, нужны все эти файлы?
где-то я уже выкладывал свою папку с инклудами
https://dl.dropboxusercontent.com/u/6175...nclude.zip

а, и заодно сам пример (MSVS 2008)
https://dl.dropboxusercontent.com/u/6175...sample.zip

единственно что, я его написал, но еще не проверял в работе))
(This post was last modified: 11.03.2015 15:12 by feanor.)
11.03.2015 15:12
Find all posts by this user Quote this message in a reply
gamecreator Offline
Administrators

Posts: 7146
Post: #683

Вообще польза от использования патчера в этом конкретном случае достаточно сомнительна. Если два мода независимо добавляют атаку с возвратом, то никакой патчер их совместимыми не сделает.


When all gods have burnt to ashes in eternity of sorrow,
Demons gonna tear your soul because there is no tomorrow.
11.03.2015 15:56
Find all posts by this user Quote this message in a reply
feanor Offline

Posts: 497
Post: #684

Quote:Вообще польза от использования патчера в этом конкретном случае достаточно сомнительна.

Чтоб не на ассемблере писать, тащемта
11.03.2015 16:00
Find all posts by this user Quote this message in a reply
gamecreator Offline
Administrators

Posts: 7146
Post: #685

Ну это уже личный выбор каждого.


When all gods have burnt to ashes in eternity of sorrow,
Demons gonna tear your soul because there is no tomorrow.
11.03.2015 17:37
Find all posts by this user Quote this message in a reply
major Offline

Posts: 94
Post: #686

Вроде бы немного разобрался, спасибо.
(This post was last modified: 15.03.2015 19:12 by major.)
13.03.2015 21:30
Find all posts by this user Quote this message in a reply
major Offline

Posts: 94
Post: #687

Немного переделал регенерацию.
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. Регенерация от опыта существ работает как-то по-другому? Этот хук не срабатывает, реген проходит без воскрешения. Как это можно исправить?
15.03.2015 19:16
Find all posts by this user Quote this message in a reply
feanor Offline

Posts: 497
Post: #688

Quote:1. Как добавить проверку на эликсир жизни, чтоб он добавлял еще 50 хп к регену.

o_BattleMgr->hero[((_BattleStack_*)c->esi)->side]->DoesWearArtifact(ID), как-то так
15.03.2015 19:30
Find all posts by this user Quote this message in a reply
gamecreator Offline
Administrators

Posts: 7146
Post: #689

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 - это стандартная регенерация от опыта.


When all gods have burnt to ashes in eternity of sorrow,
Demons gonna tear your soul because there is no tomorrow.
15.03.2015 20:15
Find all posts by this user Quote this message in a reply
feanor Offline

Posts: 497
Post: #690

Как можно перебрать все объекты определенного типа/подтипа кодом?
ну, то бишь, как это делает Вог в UN:U?)

..эм
пробегать всю карту каждый раз? серьезно?
(This post was last modified: 17.03.2015 03:45 by feanor.)
17.03.2015 03:41
Find all posts by this user Quote this message in a reply
« Next Oldest | Next Newest »
Post Reply 


Forum Jump:

Powered by MyBB Copyright © 2002-2018 MyBB Group