IPB

Здравствуйте, гость ( Вход | Регистрация )

29 страниц V  « < 10 11 12 13 14 > »   
Reply to this topicStart new topic
> Мод на ХотА
DedMorozzz
сообщение 24 Dec 2016, 15:07 (Сообщение отредактировал DedMorozzz - 24 Dec 2016, 15:23)
Сообщение #221

God
Сообщений: 267
Спасибо сказали: 25 раз




С замедлением засада вышла...
Была переделана логика замедления. Что бы округлялось в большую сторону. Т.е. 11->6 / 10->5 / 9->5 ... вместо 11->5 / 10->5 / 9->4 ...
Проблема следующая, замедление корректно работает только на летающих юнитах. Виверну замедляет с 11 до 6 и пролетает 6 клеток
А вот с пешими юнитами пишется скорость (у единорога примеру) 7. После замедления пишется 4. И область хода показывается в 4 клетки. Но по факту проходит 3!
Т.е. нажимаю на 4ю клетку, юнит начинает ходить и пройдя 3 клетки останавливается. Или даже лучше. на 4х клетках от врага, пишется что я могу атаковать юнита (появляется меч и пишется (снизу) сколько урона нанесу), нажмая атаковать, юнит проходит 3 клетки и останавливается smile.gif
Повторюсь, с летающими всё ок

Код
.text:004489F0; int __thiscall combatMonster_GetSpeed(_CombatMonster_ *this)
.text:004489F0 combatMonster_GetSpeed proc near                          ; CODE XREF: CombatMan_0041E310+F5p
.text:004489F0                                                        ; CombatMan_0041E310+109p ...
.text:004489F0
.text:004489F0 var_4               = dword ptr -4
.text:004489F0
.text:004489F0                     push    ebp
.text:004489F1                     mov     ebp, esp
.text:004489F3                     push    ecx
.text:004489F4                     mov     edx, [ecx+270h]
.text:004489FA                     mov     eax, [ecx+0C4h]
.text:00448A00                     test    edx, edx                      ; Logical Compare
.text:00448A02                     mov     [ebp+var_4], eax
.text:00448A05                     jz      short loc_00448A37            ; Jump if Zero (ZF=1)
.text:00448A07                     mov     eax, [ecx+84h]
.text:00448A0D                     shr     eax, 6                        ; Shift Logical Right
.text:00448A10                     test    al, 1                         ; Logical Compare
.text:00448A12                     jz      short loc_00448A1A            ; Jump if Zero (ZF=1)
.text:00448A14                     xor     eax, eax                      ; Logical Exclusive OR
.text:00448A16                     mov     esp, ebp
.text:00448A18                     pop     ebp
.text:00448A19                     retn                                  ; Return Near from Procedure
.text:00448A1A; ---------------------------------------------------------------------------
.text:00448A1A
.text:00448A1A loc_00448A1A:                                             ; CODE XREF: combatMonster_GetSpeed+22j
.text:00448A1A                     fild    [ebp+var_4]                ; Load Integer
.text:00448A1D                     fstp    [ebp+var_4]                ; Store Real and Pop
.text:00448A20                     fld     [ebp+var_4]                ; Load Real
.text:00448A23                     fmul    dword ptr [ecx+4C8h]          ; Multiply Real
.text:00448A29                     call    __ftol                        ; Call Procedure
.text:00448A2E                     test    eax, eax                      ; Logical Compare
.text:00448A30                     jg      short loc_00448A37            ; Jump if Greater (ZF=0 & SF=OF)
.text:00448A32                     mov     eax, 1
.text:00448A37
.text:00448A37 loc_00448A37:                                             ; CODE XREF: combatMonster_GetSpeed+15j
.text:00448A37                                                        ; combatMonster_GetSpeed+40j
.text:00448A37                     mov     esp, ebp
.text:00448A39                     pop     ebp
.text:00448A3A                     retn                                  ; Return Near from Procedure
.text:00448A3A combatMonster_GetSpeed endp


используемый код:
Код
int __stdcall spellSlow(LoHook* h, HookContext* c)
{
    // тут структура монстра лежит в ecx.
    // откуда мы и можем получить все интересующие нас параметры
    float speed = (float)(*(int*)(c->ecx +196));                   // получаем скорость монстра (структура +196)
    c->eax = floor( (speed * (*(float*)(c->ecx + 1224))) + 0.5 );  // функция правильного округления (скорость * коэфф.замедления)
    
    // а также приходится "обойти" часть оригинального кода
    c->return_address = 0x448A37;                                  // указываем новый адрес возврата
    return NO_EXEC_DEFAULT;                                        // после завершения хука не выполняется затертый хуком код
}


Судя по этому комменту:
Цитата
в структуре стека в битве есть поле множителя (SlowMul в вогобазе), которое устанавливается при касте скорости и потом используется как коэффициент для актуальной скорости в combatMonster_00448560 (что-то с определением достижимости цели, что ли) и combatMonster_GetSpeed (004489F0, собственно расчет скорости)

изменён только метод combatMonster_GetSpeed (хоть и с достижимостью цели проблем не возникло, работает корректно)
Попробовал изменить combatMonster_00448560
Код
int __stdcall spellSlow2(LoHook* h, HookContext* c)
{
    float speed = (float)(*(int*)(c->ecx +196));
    c->eax = floor( (speed * (*(float*)(c->ecx + 1224))) + 0.5 );
    
    c->return_address = 0x4485B5;
    return NO_EXEC_DEFAULT;
}

Не помогло...

Как сделать корректное замедление для пеших юнитов?

PS:
Код
_PI->WriteLoHook(0x448A1A, spellSlow);
_PI->WriteLoHook(0x4485A5, spellSlow2);
Go to the top of the pageAdd Nick
 
+Quote Post
Sav
сообщение 24 Dec 2016, 15:33
Сообщение #222

Immortal
Сообщений: 9 444
Спасибо сказали: 3978 раз




Функция получения скорости много где подставлена inline. То есть при компиляции кода Героев вместо того, чтобы добавить в некоторые места вызов этой функции, туда была добавлена прямо копия кода этой функции (несколько видоизменённая: с использованием других регистров и т. п.). Для геройского кода это обычное дело, поэтому при модификации не очень больших функций всегда следует исследовать те места, откуда они вызываются, и подумать над тем, не может ли она теоретически использоваться где-то ещё (не забывая, например, про код ИИ).

Часто, впрочем, есть возможность зацеписться за техническую особенность функции и найти её inline-вызовы без понимания, где и зачем они происходят. Здесь тоже повезло: используется редкое смещение +4C8h. Можно просто поиском по ассемблерному тексту найти все использования этого смещения и на взгляд определить, какие именно относятся к получению скорости; соответственно, все их модифицировать.

Это не гарантирует того, что будут найдены действительно все inline-вызовы: иногда используется смещённый указатель на структуру, и тогда 4C8h превращается в другое число. Здесь уже помогает только опыт исследования кода и проверка всех мест, откуда потенциально могла бы вызываться эта функций. Но такие случае не так часты.


Спасибо сказали:
Go to the top of the pageAdd Nick
 
+Quote Post
AlexSpl
сообщение 24 Dec 2016, 15:40
Сообщение #223

Immortal
Сообщений: 798
Спасибо сказали: 555 раз




А по каким адресам хуки?

Например, в sub_448560:

int speed = *(int*)(c->esi + 196); // скорость
float speedMod = *(float*)(c->esi + 1224); // модификатор скорости
Go to the top of the pageAdd Nick
 
+Quote Post
DedMorozzz
сообщение 24 Dec 2016, 15:52 (Сообщение отредактировал DedMorozzz - 24 Dec 2016, 16:04)
Сообщение #224

God
Сообщений: 267
Спасибо сказали: 25 раз




Цитата(AlexSpl @ 24 Dec 2016, 14:40) *
А по каким адресам хуки?

Например, в sub_448560:

int speed = *(int*)(c->esi + 196); // скорость
float speedMod = *(float*)(c->esi + 1224); // модификатор скорости

Я пост выше обновил. Добавил 2 адреса

------------------

По смещению(+4C8h) нашел такую функу. Имеется подозрение что её и надо отредачить:
00441CC0 ; char __thiscall combatMonster_WalkToPos(_CombatMonster_ *a1, signed int a2, char a3)
Go to the top of the pageAdd Nick
 
+Quote Post
AlexSpl
сообщение 24 Dec 2016, 15:53 (Сообщение отредактировал AlexSpl - 24 Dec 2016, 16:14)
Сообщение #225

Immortal
Сообщений: 798
Спасибо сказали: 555 раз




Здесь нужно отследить сам каст "Замедления" и посмотреть, что он делает с модификатором скорости. А иначе придётся перехватывать в коде все умножения скорости на модификатор, и последующее округление (call __ftol).


Спасибо сказали:
Go to the top of the pageAdd Nick
 
+Quote Post
DedMorozzz
сообщение 24 Dec 2016, 16:24
Сообщение #226

God
Сообщений: 267
Спасибо сказали: 25 раз




Вроде сделал!
Код
int __stdcall spellSlow3(LoHook* h, HookContext* c)
{
    float speed = (float)(*(int*)(c->esi +196));
    c->eax = floor( (speed * (*(float*)(c->esi + 1224))) + 0.5 );
    
    c->return_address = 0x441E36;
    return NO_EXEC_DEFAULT;
}


Код
_PI->WriteLoHook(0x441E19, spellSlow3);
Go to the top of the pageAdd Nick
 
+Quote Post
AlexSpl
сообщение 24 Dec 2016, 16:49 (Сообщение отредактировал AlexSpl - 24 Dec 2016, 16:51)
Сообщение #227

Immortal
Сообщений: 798
Спасибо сказали: 555 раз




Лучше управление возвратить по адресу 441E2Dh, а не 441E36h, чтобы выполнилась проверка на 0.

И потом нет гарантии, что учтены все случаи округления.

В этом блоке инструкций меняется модификатор при касте Slow:

Код
.text:00444A33 push    35h
.text:00444A35 mov     ecx, esi
.text:00444A37 call    sub_444230
.text:00444A3C fild    [ebp+arg_8]
.text:00444A3F fstp    [ebp+var_18]
.text:00444A42 fld     [ebp+var_18]
.text:00444A45 fdiv    ds:dbl_63A698
.text:00444A4B fstp    dword ptr [esi+4C8h]
.text:00444A51 fild    dword ptr [esi+68h]
.text:00444A54 fstp    [ebp+var_18]
.text:00444A57 fld     [ebp+var_18]
.text:00444A5A fmul    ds:dbl_63B8D8
.text:00444A60 call    __ftol
.text:00444A65 mov     [esi+158h], eax


Спасибо сказали:
Go to the top of the pageAdd Nick
 
+Quote Post
DedMorozzz
сообщение 24 Dec 2016, 16:50 (Сообщение отредактировал DedMorozzz - 24 Dec 2016, 16:51)
Сообщение #228

God
Сообщений: 267
Спасибо сказали: 25 раз




Цитата(AlexSpl @ 24 Dec 2016, 15:36) *
Лучше управление возвратить по адресу 441E2Dh, а не 441E36h, чтобы выполнилась проверка на 0.

И потом нет гарантии, что учтены все случаи округления.


Переделал, код чуть ниже

Насчёт гарантий.. да нету. Но я проверил что смог, как на АИ, так и на ручном управлении юнитами. Как на пеших, так и на летающих. В том числе бонус от родной земли

Ещё важный момент, надо было юзать esi, а не ecx во 2й функции
Мб кому понадобится:
Код
.text:00441E19 loc_00441E19:                                             ; CODE XREF: combatMonster_WalkToPos+153j
.text:00441E19                     fild    dword ptr [ebp+a5]            ; Load Integer
.text:00441E1C                     fstp    dword ptr [ebp+a5]            ; Store Real and Pop
.text:00441E1F                     fld     dword ptr [ebp+a5]            ; Load Real
.text:00441E22                     fmul    dword ptr [esi+4C8h]          ; Multiply Real
.text:00441E28                     call    __ftol                        ; Call Procedure
.text:00441E2D                     test    eax, eax                      ; Logical Compare
.text:00441E2F                     jg      short loc_00441E36            ; Jump if Greater (ZF=0 & SF=OF)
.text:00441E31                     mov     eax, 1


Т.е. тут нужное смещение применятся к esi ([esi+4C8h]), а в 1й функе:
Код
.text:00448A1A loc_00448A1A:                                             ; CODE XREF: combatMonster_GetSpeed+22j
.text:00448A1A                     fild    [ebp+var_4]                ; Load Integer
.text:00448A1D                     fstp    [ebp+var_4]                ; Store Real and Pop
.text:00448A20                     fld     dword ptr [ebp-4]             ; Load Real
.text:00448A23                     fmul    dword ptr [ecx+4C8h]          ; Multiply Real
.text:00448A29                     call    __ftol                        ; Call Procedure
.text:00448A2E                     test    eax, eax                      ; Logical Compare
.text:00448A30                     jg      short loc_00448A37            ; Jump if Greater (ZF=0 & SF=OF)
.text:00448A32                     mov     eax, 1

Т.е. тут ( [ecx+4C8h]). И юзать надо ecx. Может это и не верный алоритм определения esi/ecs/..., но другого не знаю)

Итого, финальный код:
Код
int __stdcall spellSlow(LoHook* h, HookContext* c)
{
    float speed = (float)(*(int*)(c->ecx +196));                   // получаем скорость монстра (структура +196)
    c->eax = floor( (speed * (*(float*)(c->ecx + 1224))) + 0.5 );  // функция правильного округления (скорость * коэфф.замедления)
    
    c->return_address = 0x448A37;                                  // указываем новый адрес возврата
    return NO_EXEC_DEFAULT;                                        // после завершения хука не выполняется затертый хуком код
}

int __stdcall spellSlowMelee(LoHook* h, HookContext* c)
{
    float speed = (float)(*(int*)(c->esi +196));
    c->eax = floor( (speed * (*(float*)(c->esi + 1224))) + 0.5 );
    
    c->return_address = 0x441E2D;
    return NO_EXEC_DEFAULT;
}

Код
_PI->WriteLoHook(0x448A1A, spellSlow);
_PI->WriteLoHook(0x441E19, spellSlowMelee);
Go to the top of the pageAdd Nick
 
+Quote Post
AlexSpl
сообщение 24 Dec 2016, 16:56
Сообщение #229

Immortal
Сообщений: 798
Спасибо сказали: 555 раз




Аналогично 0x448A37 на 0x448A2E, иначе пропускается проверка if (speed <= 0) speed = 1;


Спасибо сказали:
Go to the top of the pageAdd Nick
 
+Quote Post
DedMorozzz
сообщение 24 Dec 2016, 17:04
Сообщение #230

God
Сообщений: 267
Спасибо сказали: 25 раз




Цитата(AlexSpl @ 24 Dec 2016, 15:56) *
Аналогично 0x448A37 на 0x448A2E, иначе пропускается проверка if (speed <= 0) speed = 1;

заменил, всё работает

Терь хочу допилить 2 оставшихся момента с дипломатией...
как реализовать возможность сдаваться при бое с монстрами?
Т.е. хочу сделать активной кнопку "сдаться" за 30-20-10% от цены войска. Но только при бое с монстрами, против героя не меняя
Go to the top of the pageAdd Nick
 
+Quote Post
AlexSpl
сообщение 24 Dec 2016, 17:04 (Сообщение отредактировал AlexSpl - 24 Dec 2016, 17:11)
Сообщение #231

Immortal
Сообщений: 798
Спасибо сказали: 555 раз




А Haste и Prayer (Молитва) работают нормально?
Go to the top of the pageAdd Nick
 
+Quote Post
DedMorozzz
сообщение 24 Dec 2016, 17:20
Сообщение #232

God
Сообщений: 267
Спасибо сказали: 25 раз




Цитата(AlexSpl @ 24 Dec 2016, 16:04) *
А Haste и Prayer (Молитва) работают нормально?

Проверил. Да ок. Как и ПВП, так и против мобов. И корректно считается бафф после замедления (и скорость и молитва)
Go to the top of the pageAdd Nick
 
+Quote Post
DedMorozzz
сообщение 24 Dec 2016, 18:06 (Сообщение отредактировал DedMorozzz - 24 Dec 2016, 18:14)
Сообщение #233

God
Сообщений: 267
Спасибо сказали: 25 раз




А куда копать для того что бы реализовать "сдаться" при бое с монстрами?
Go to the top of the pageAdd Nick
 
+Quote Post
AlexSpl
сообщение 24 Dec 2016, 19:07
Сообщение #234

Immortal
Сообщений: 798
Спасибо сказали: 555 раз




Это сложная задача, так как алгоритмы написаны для сдачи конкретному герою (его имя в сообщении, и в казну игрока, которому принадлежит этот герой, переводится золото). Для начала я бы нашёл место в коде, где "гасится" кнопка "Surrender".
Go to the top of the pageAdd Nick
 
+Quote Post
AlexSpl
сообщение 24 Dec 2016, 21:09 (Сообщение отредактировал AlexSpl - 25 Dec 2016, 05:16)
Сообщение #235

Immortal
Сообщений: 798
Спасибо сказали: 555 раз




Посмотрел немного. Если нажать кнопку "Surrender" в бою с нейтралами, игра ведёт себя корректно. Сообщение: "{Hero} surrenders to the enemy, and departs in shame.", герой подает в таверну с войском на момент сдачи. Одно но: нейтралы не требуют денег. Похоже, стоимость сдачи вычитается автоматически.

Наверное, я пропускаю диалог. Так что нужно искать вызов диалога.

Диалог - sub_4F6C00.
Код по адресу 474919h обрабатывает нажатие кнопки "Surrender", свитч джамп здесь: 474783h (0 - сдаться, 1 - сбежать, 2 - опции и т.д.).
Код, который реализует сдачу: 478EBCh, остальные действия в бою: свитч джамп - 47895Fh (функция sub_4786B0).

Решение, активна кнопка "Surrender" или нет, принимается здесь: 477EB3h.

Примерный алгоритм:
1. Делаем кнопку "Surrender" активной в битве с нейтралами (477EB3h);

2. Реализуем корректный диалог при сдаче нейтралам (474919h);

3. Проверяем код по адресу 478EBCh.

Осталось удостовериться, что деньги за откуп уходят в пустоту, а не прописываются по левому адресу. Вылета нет, но проверить стоит.


Спасибо сказали:
Go to the top of the pageAdd Nick
 
+Quote Post
DedMorozzz
сообщение 25 Dec 2016, 13:42
Сообщение #236

God
Сообщений: 267
Спасибо сказали: 25 раз




Пробую разрулить с диалогом. Что бы показывался только для героя с дипломатией:
Код
int __stdcall setSurrenderButton(LoHook* h, HookContext* c)
{
    char diplomacyLevel = *(char*)(c->esi + 201 + 4);

    if (diplomacyLevel > 0) {
        _P = GetPatcher();
        _PI = _P->GetInstance("HD.Plugin.DedMorozzz");
        _PI->WriteHexPatch(0x477EB3, "9090");
        //*(int*)0x477EB3 = 9090;
    }

    return EXEC_DEFAULT;
}

Код
_PI->WriteLoHook(0x4AC35E, setSurrenderButton);


Не работает. Явно патчер вызывать не надо, но я не знаю как сделать..

В чём была логика - на нужный адрес сделать лоу хук, который проверит наличие вторичного навыка. И если он есть - разблокируем кнопку "сдаться"
Go to the top of the pageAdd Nick
 
+Quote Post
AlexSpl
сообщение 25 Dec 2016, 14:13
Сообщение #237

Immortal
Сообщений: 798
Спасибо сказали: 555 раз




Можно и через LoHook:
Код
int __stdcall setSurrenderButton(LoHook* h, HookContext* c)
{
    char diplomacyLevel = *(char*)(*(int*)(c->esi + c->eax * 4 + 0x53CC) + 201 + 4);

    if ( diplomacyLevel > 0 ) {
        c->return_address = 0x477EB5;
        return NO_EXEC_DEFAULT;
    }

    return EXEC_DEFAULT;
}


Спасибо сказали:
Go to the top of the pageAdd Nick
 
+Quote Post
DedMorozzz
сообщение 25 Dec 2016, 14:21 (Сообщение отредактировал DedMorozzz - 25 Dec 2016, 14:25)
Сообщение #238

God
Сообщений: 267
Спасибо сказали: 25 раз




Цитата(AlexSpl @ 25 Dec 2016, 13:13) *
Можно и через LoHook:
Код
int __stdcall setSurrenderButton(LoHook* h, HookContext* c)
{
    char diplomacyLevel = *(char*)(*(int*)(c->esi + c->eax * 4 + 0x53CC) + 201 + 4);

    if ( diplomacyLevel > 0 ) {
        c->return_address = 0x477EB5;
        return NO_EXEC_DEFAULT;
    }

    return EXEC_DEFAULT;
}

вылетает. Пробовал 0x477EB5 на 0x477EB3 заменить. То же самое

----------------------

я так понимаю это:
char diplomacyLevel = *(char*)(*(int*)(c->esi + c->eax * 4 + 0x53CC) + 201 + 4);

не работает. Ибо нападая героем без дипломатии - всё равно вылетает
Go to the top of the pageAdd Nick
 
+Quote Post
AlexSpl
сообщение 25 Dec 2016, 14:26
Сообщение #239

Immortal
Сообщений: 798
Спасибо сказали: 555 раз




Так LoHook на

Код
_PI->WriteLoHook(0x477EB3, setSurrenderButton);


Спасибо сказали:
Go to the top of the pageAdd Nick
 
+Quote Post
DedMorozzz
сообщение 25 Dec 2016, 14:33 (Сообщение отредактировал DedMorozzz - 25 Dec 2016, 14:39)
Сообщение #240

God
Сообщений: 267
Спасибо сказали: 25 раз




Цитата(AlexSpl @ 25 Dec 2016, 13:26) *
Так LoHook на

Код
_PI->WriteLoHook(0x477EB3, setSurrenderButton);

да, точно! У меня чего-то вообще на 0x4AC35E стоял. Терь всё ок, не вылетает. Но и кнопки нету)) В смысле не активна


PS: её нету даже без условия.. Даже если так написать в ф-ии:
Код
c->return_address = 0x477EB5;
return NO_EXEC_DEFAULT;
Go to the top of the pageAdd Nick
 
+Quote Post

29 страниц V  « < 10 11 12 13 14 > » 
Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 



Текстовая версия Сейчас: 3 October 2025 - 23:59
Copyright by Алексей Крючков
Strategy Gamez by GrayMage
Programming by Degtyarev Dmitry
  Яндекс.Метрика