Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Мод на ХотА
DF2 :: ФОРУМЫ > Игровые форумы > Heroes of Might & Magic III > Моды
Страницы: 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12
AlexSpl
Если бы контекст возвращался неверный, то и вот это:

Код
c->ebx == cmAddr + 0x132A0;

тоже бы не работало. Так что реально вопрос.

Код
.text:00475A28                 mov     eax, [ebx]
.text:00475A2A                 inc     eax; инкрементируем счётчик
.text:00475A2B                 mov     [ebp+var_4], ecx
.text:00475A2E                 mov     [ebx], eax; пишем значение счётчика по адресу ebx
.text:00475A30                 mov     [ebp+var_8], 20
.text:00475A37
.text:00475A37 loc_475A37:
.text:00475A37                 cmp     dword ptr [ecx+34h], -1
.text:00475A3B                 jz      short loc_475A45
.text:00475A3D                 call    sub_446E40; до выполнения этой инструкции - хук, соответсвенно, в c->eax - счётчик
DedMorozzz
Цитата(AlexSpl @ 29 Dec 2016, 19:08) *
Цитата
Вот это не работает, если c->eax - 30000 использовать. Не отнимается скорость

Это я уже не знаю, почему. В контексте хука (c->eax - 30000) - это номер раунда. Нужно у baratorch'а спрашивать, почему не работает. У меня в ассемблере - работает.


на 16й странице похожая проблема была smile.gif
AlexSpl
Тут нужно смотреть на контекст. Попробуйте в хуке написать не просто

Код
int roundNumber = *(int*)(cmAddr + 0x132A0) - 30000;
,

а
Код
int roundNumber = *(int*)(cmAddr + 0x132A0) - 30000;
int roundNumberAlt = c->eax - 30000;

if ( roundNumber != roundNumberAlt ) return EXEC_DEFAULT;


Если эти значения действительно не равны скорость уменьшена не будет. Хотя они должны *быть* равны для левой стороны.
DedMorozzz
Цитата(AlexSpl @ 29 Dec 2016, 19:48) *
Тут нужно смотреть на контекст. Попробуйте в хуке написать не просто

Код
int roundNumber = *(int*)(cmAddr + 0x132A0) - 30000;
,

а
Код
int roundNumber = *(int*)(cmAddr + 0x132A0) - 30000;
int roundNumberAlt = c->eax - 30000;

if ( roundNumber != roundNumberAlt ) return EXEC_DEFAULT;


Если эти значения действительно не равны скорость уменьшена не будет. Хотя они должны *быть* равны для левой стороны.

Не уменьшается. Бонус в начале даётся. Во 2м раунде - бонус остаётся
AlexSpl
Это может означать только то, что контекст возвращается неправильный, т.к. c->eax это и есть *(int*)c->ebx.

Посмотрим ещё раз на код:
Код
.text:00475A2E                 mov     [ebx], eax; [ebx] = eax !!
.text:00475A30                 mov     [ebp+var_8], 20
.text:00475A37
.text:00475A37 loc_475A37:
.text:00475A37                 cmp     dword ptr [ecx+34h], 0FFFFFFFFh
.text:00475A3B                 jz      short loc_475A45
.text:00475A3D                 call    sub_446E40; хук выполняется до этой инструкции


Какая у Вас версия патчера, кстати?

Так! Стоп ) Я разобрался, похоже )

Мы ставим хук *внутри* цикла. И действительно c->eax в нём меняется. Так что вопрос снят.
DedMorozzz
Цитата(AlexSpl @ 29 Dec 2016, 20:05) *
Какая у Вас версия патчера, кстати?

Версия 4.2

И сейчас столкнулся с проблемой:
Код
if(*(int*)(c->ecx + 201 + 27) > 0) { //проверка на палатку
            if ( *(int*)(c->ecx + 301 + (15 << 3)) == 6 ) { //15 - слот на кукле для палатки. 6 - айди палатки
                *(int*)(c->esi + 88) += *(int*)(c->ecx + 201 + 27);
            }
        }

При нападении с палаткой и навыком - вылетает игра...
Пробую разрулить

Цитата(AlexSpl @ 29 Dec 2016, 20:11) *
Мы ставим хук *внутри* цикла. И действительно c->eax в нём меняется. Так что вопрос снят.

на 16й странице тоже самое? smile.gif
AlexSpl
Всё, я разобрался. Читай предыдущий пост.

Ну, как бы весь код я набираю здесь )) Я не проверяю его работоспособность, так что извиняйте )
DedMorozzz
Не, вылетает не из-за моего кода) Ща ковыряю в общем
AlexSpl
Цитата
При нападении с палаткой и навыком - вылетает игра...

Код
*(int*)(c->esi + 88) += *(int*)(c->ecx + 201 + 27);

Это дефенс так повышаете? Там контекст другой. Пример со скоростью: +80 и +196. М.б. в этом проблема?

Ладно, немного посмотрел. Я давал код на инициализацию. Туда нужно было хук ставить. Попробуйте несколько раз кликнуть правой кнопкой мыши на отряде на экране окна героя. Каждый раз сработает хук, что не есть правильно.

Т.е. уже скорость отрядов отображается завышенной.

Попробуйте раздавать "плюшки" здесь: 43D492h (LoHook).

Т.е. после выполнения инструкции rep movsd отряд инициализирован. Самое время добавить бонусы к параметрам.
AlexSpl
Код
.text:0043D47F lea     edi, [ebx+74h]
.text:0043D482 lea     edx, [eax+edx*4]
.text:0043D485 shl     edx, 2
.text:0043D488 lea     esi, [edx+ecx]
.text:0043D48B mov     ecx, 29
.text:0043D490 rep movsd
.text:0043D492 mov     ecx, dword_699538

LoHook на 43D492h. Все бонусы раздавать только здесь.
igrik
Цитата(DedMorozzz @ 29 Dec 2016, 21:12) *
При нападении с палаткой и навыком - вылетает игра...

Известная проблема, особенно по WOGy. У палатки скорость всегда должна быть =0. Иначе - вылет при получении хода (как, впрочем, и у всех боевых машин). Проверку делайте на флаг "боевой машины" (64), либо на тип монстров (146 ... 150).
Код
!(o_BattleMgr->stack[0][номер стека текущей стороны].creature.flags & 64)


И смещение 0x132A0 - это что-то связанное с автокастом Чародеев (там идет проверка на каждый третий раунд). Очень сомнительно использовать в качестве номера раунда битвы.

Цитата
if(*(int*)(c->ecx + 201 + 27) > 0) { //проверка на палатку

Это проверка не на палатку, а на навык "Первая Помощь". И там вроде байт, а не четыре байта. Вылезаете за границы, что тоже может приводить в лучшем случае к вылету, в худшем - к трудноуловимым багам.

Цитата
И отнимает скорость всё равно у всех
Потому что нет правильной проверки на сторону стека. Как-то вообще у вас все слишком замудрёно получилось.
Кстате в ИДЕ есть отличная кнопка "tab", которая показывает псевдо сишный код.
AlexSpl
О, об этом не знал, но всё равно хук на 43D492h.
DedMorozzz
Цитата
И смещение 0x132A0 - это что-то связанное с автокастом Чародеев (там идет проверка на каждый третий раунд). Очень сомнительно использовать в качестве номера раунда битвы.

А как проверить номер раунда?

Всё равно вылетает...
Странно очень, я когда это писал - проверял. Работало. И с баллистой проверял и без. И цифры менял, что бы +10 давало
То же самое с палаткой и тактикой...
Пока что не понимаю что добавилось, почему вылетает игра. Причём на сейвах, на которых всё тестил

Цитата
Это дефенс так повышаете? Там контекст другой. Пример со скоростью: +80 и +196. М.б. в этом проблема?

Да, оно так работало. Почему атака/защита = 84/88. Потому что мы знаем смещение скорости, это +80 в данном контексте
А "базовое" смещение для скорости/атаки/защиты такое - 196/200/204
Код
//_int_ speed;  //+196 0xC4  
//_int_ attack;  //+200 0xC8
//_int_ defence;  //+204 0xCC


Учитывая что 80 это скорость, а атака на 4 (байта?) дальше. Защита на 4 дальше от атаки. Получается так:
80/84/88

Текущий код, с которым не всё ладно (может проблема и в другом, а не в этом коде) такой:

Код
int __stdcall setBankUnitBonus(LoHook* h, HookContext* c)
{
    if ( *(char*)(*(int*)0x699420 + 0x53C5) == 1) { // проверка что бой в банке существ
        
        if(*(char*)(c->ecx + 201 + 19) > 0) { // проверка на тактику
            *(int*)(c->esi+80) += *(int*)(c->ecx + 201 + 19);
            //*(int*)(c->esi+80) += 2;
        }

        if(*(char*)(c->ecx + 201 + 20) > 0) { //проверка на артиллерию
            if ( *(char*)(c->ecx + 301 + (13 << 3)) == 4 ) { //13 - слот на кукле для баллисты. 4 - айди баллисты
                *(int*)(c->esi + 84) += *(int*)(c->ecx + 201 + 20);
                //*(int*)(c->esi + 84) += 10;
            }
        }

        if(*(char*)(c->ecx + 201 + 27) > 0) { //проверка на первую помощь
            if ( *(char*)(c->ecx + 301 + (15 << 3)) == 6 ) { //15 - слот на кукле для палатки. 6 - айди палатки
                *(int*)(c->esi + 88) += *(int*)(c->ecx + 201 + 27) * 2;
                //*(int*)(c->esi + 88) += 10;
            }
        }
        
    }

    return EXEC_DEFAULT;
}

Код
_PI->WriteLoHook(0x43D492, setBankUnitBonus);


закоменченые варианты тоже пробовал. Всё равно вылетает

PS: если вешать хук на "0x43D492", то скорость уже не c->esi+80
PPS: походу скорость по этому адресу получается так: *(int*)(c->ebx + 196)
DedMorozzz
Пока что получилось такое:
Код
int __stdcall setBankUnitBonus(LoHook* h, HookContext* c)
{
    int cmAddr =  *(int*)0x699420;
    int heroOffset = *(int*)(cmAddr + 0x53CC);

    if ( *(char*)(*(int*)0x699420 + 0x53C5) == 1) { // проверка что бой в банке существ
        if(*(char*)(heroOffset + 201 + 19) > 0) { // проверка на тактику
            *(int*)(c->ebx + 196) += *(char*)(heroOffset + 201 + 19);
        }

        if(*(char*)(heroOffset + 201 + 20) > 0) { //проверка на артиллерию
            if ( *(char*)(heroOffset + 301 + (13 << 3)) == 4 ) { //13 - слот на кукле для баллисты. 4 - айди баллисты
                *(int*)(c->ebx + 200) += *(char*)(heroOffset + 201 + 20);
            }
        }

        if(*(char*)(heroOffset + 201 + 27) > 0) { //проверка на первую помощь
            if ( *(char*)(heroOffset + 301 + (15 << 3)) == 6 ) { //15 - слот на кукле для палатки. 6 - айди палатки
                *(int*)(c->ebx + 204) += *(char*)(heroOffset + 201 + 27) * 2;
            }
        }
        
    }

    return EXEC_DEFAULT;
}


Код
_PI->WriteLoHook(0x43D492, setBankUnitBonus);


Работает, но снова таки - на всех... пока что сторону ещё не понять как определить и не работает бонус в банке при наличии пушки (а не баллисты), что ожидаемо. Какой айди у пушки?
AlexSpl
Цитата
Работает, но снова таки - на всех... пока что сторону ещё не понять как определить

arg_8 есть как раз указатель на героя.

Цитата
на 16й странице тоже самое?

DedMorozzz
Цитата(AlexSpl @ 30 Dec 2016, 15:41) *
Цитата
Работает, но снова таки - на всех... пока что сторону ещё не понять как определить

arg_8 есть как раз указатель на героя.


Я ж уже знаю указатель на героя. Вот:
Код
    int heroOffset = *(int*)(cmAddr + 0x53CC);

А как понять, юнитам каким давать/отнимать бонус, а каким нет?
AlexSpl
Цитата
Я ж уже знаю указатель на героя. Вот:
Код
int heroOffset = *(int*)(cmAddr + 0x53CC);


А как понять, юнитам каким давать/отнимать бонус, а каким нет?

Просто сравнить *(int*)(c->ebp + 16) == heroOffset. Условие выполняется, только если проходим по нашим отрядам.
DedMorozzz
Код
int __stdcall setBankUnitBonus(LoHook* h, HookContext* c)
{
    int cmAddr =  *(int*)0x699420;
    int heroOffset = *(int*)(cmAddr + 0x53CC);

    if (*(int*)(c->ebp + 16) != heroOffset) {
        return EXEC_DEFAULT;
    }

    if ( *(char*)(*(int*)0x699420 + 0x53C5) == 1) { // проверка что бой в банке существ

        if(*(char*)(heroOffset + 201 + 19) > 0) { // проверка на тактику
            *(int*)(c->ebx + 196) += *(char*)(heroOffset + 201 + 19);
        }

        if(*(char*)(heroOffset + 201 + 20) > 0) { //проверка на артиллерию
            if ( *(char*)(heroOffset + 301 + (13 << 3)) == 4 ) { //13 - слот на кукле для баллисты. 4 - айди баллисты
                *(int*)(c->ebx + 200) += *(char*)(heroOffset + 201 + 20);
            }
        }

        if(*(char*)(heroOffset + 201 + 27) > 0) { //проверка на первую помощь
            if ( *(char*)(heroOffset + 301 + (15 << 3)) == 6 ) { //15 - слот на кукле для палатки. 6 - айди палатки
                *(int*)(c->ebx + 204) += *(char*)(heroOffset + 201 + 27) * 2;
            }
        }
    }

    return EXEC_DEFAULT;
}

int __stdcall resetTacticsUnitSpeedBonus(LoHook* h, HookContext* c)
{
    int cmAddr =  *(int*)0x699420;
    if ( *(char*)(cmAddr + 0x53C5) == 1) { // проверка что бой в банке существ
        char tacticLevel = *(char*)(*(int*)(cmAddr + 0x53CC) + 201 + 19);
        int roundNumber = *(int*)(cmAddr + 0x132A0) - 30000;

        if ((tacticLevel > 0) && (roundNumber == 1)) {
            if ( c->ebx == cmAddr + 0x132A0 ) {
                *(int*)(c->ecx + 196) -= tacticLevel;
            }
        }
    }

    return EXEC_DEFAULT;
}


Код
_PI->WriteLoHook(0x43D492, setBankUnitBonus);
_PI->WriteLoHook(0x475A3D, resetTacticsUnitSpeedBonus);


Вот так получилось. Но 2 проблемы имеется:
1.
менял
if ( *(char*)(heroOffset + 301 + (13 << 3)) == 4 ) {
на
if ( *(char*)(heroOffset + 301 + (13 << 3)) > 0 ) {

что бы просто проверить что слот под баллисту занят - не завелось. Пушка бонуса не даёт. Какое значение при пустом слоте?

2. При режиме "ПВП битве а нейтралами" - вылетает на ходу нейтралов (какой код разбираю, но точно не бонус при бое в банке)

PS: пункт 2 определил. Логика сбегания от нейтралов. Надо поставить проверку, что ходит герой, тогда кнопку разблокировтаь
AlexSpl
Цитата
Какое значение при пустом слоте?

-1

Да, ещё
Код
*(int*)(heroOffset + 301 + (slot << 3))

или
Код
*(int*)(heroOffset + 301 + slot * 8)

Как удобнее.
DedMorozzz
Цитата(AlexSpl @ 30 Dec 2016, 16:12) *
Цитата
Какое значение при пустом слоте?

-1

я тоже так думал... потому и поставил проверку > 0. Но не завелось. Перепроверю.

По поводу пункта 2, исправил. Получилось так:



Новый блок добавил такой, в начало:



----------------------------
Цитата
slot * 8

Во! Ибо я погуглил в С++ что значит <<, нашел инфу, но не сильно понял. Прочитал что менят сдвиг..
а *8 что даёт?
AlexSpl
Цитата
Код
if (*(int*)(c->ebp + 16) != heroOffset) {
        return EXEC_DEFAULT;
    }

Так вряд ли прокатит. Там аргументы другие.

Лучше так:
Код
if ( heroOffset == 0 ) {
        return EXEC_DEFAULT;
    }
DedMorozzz
Переделаю ща..

А по артиллерии в банке, вот так получилось:
Код
if(*(char*)(heroOffset + 201 + 20) > 0) { //проверка на артиллерию
            if ( *(char*)(heroOffset + 301 + (13 << 3)) != -1 ) { //13 - слот на кукле для баллисты. -1 - пустой слот
                *(int*)(c->ebx + 200) += *(char*)(heroOffset + 201 + 20);
            }
        }

Это завелось. И баллиста и пушка дают бонусы (при наличии навыка). При пустом слоте - бонуса нет
AlexSpl
8 - это размер структуры _Artifact_. Соответственно, 301 + slot * 8 - это оффсет арта в слоте.
DedMorozzz
Цитата(AlexSpl @ 30 Dec 2016, 16:18) *
Лучше так:
Код
if ( heroOffset == 0 ) {
        return EXEC_DEFAULT;
    }


Так вылетает. А мой код не вылетал, но не давал сбегать даже при наличии навыка. Т.е. всегда дефолтное поведение у ф-ии было
AlexSpl
Цитата
2. При режиме "ПВП битве а нейтралами" - вылетает на ходу нейтралов (какой код разбираю, но точно не бонус при бое в банке)

Понятно. В этом режиме нет героев?
DedMorozzz
Цитата(AlexSpl @ 30 Dec 2016, 16:28) *
Цитата
2. При режиме "ПВП битве а нейтралами" - вылетает на ходу нейтралов (какой код разбираю, но точно не бонус при бое в банке)

Понятно. В этом режиме нет героев?

нет, просто можно управлять нейтралами
Мы обычно с этим режимом на хотсите и играем.
Логика такая: ходит игрок, нападает на консерву с грифонами, а 2й игрок управляет грифонами

И вот сейчас получается игра вылетает на проверке активации кнопки побега, когда ход передаётся монстрам
AlexSpl
Попробуйте тогда так:

Код
int __stdcall setSurrenderButton(LoHook* h, HookContext* c)
{
    int heroOffset = *(int*)(c->esi + c->eax * 4 + 0x53CC);

    if ( heroOffset == 0 ) {
        return EXEC_DEFAULT;
    }

    char diplomacyLevel = *(char*)(heroOffset + 201 + 4);

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

    return EXEC_DEFAULT;
}
DedMorozzz
Да, так завелось, спасибо!
DedMorozzz
Хочу немного с магией поколдовать...
Каким образом можно отредачить параметры даваемые магией? В частности молитва.
Сейчас она даёт +4 к атаке/защите/скорости
Хочу сделать так: +6 атака/защита, +4 скорости. И что бы вешалось благо

С чего начать? Как это сделать?
AlexSpl
Адрес отряда легко посчитать. Да хотя бы на том же калькуляторе, если известен адрес combatManager. Известен адрес отряда, значит, и известны все его параметры. Например, скорость +196. Остаётся приаттачиться к процессу, поставить брейкпоинт на память по вычисленному адресу (в данном случае на запись, hardware), продолжить игру и повесить на этот отряд Молитву. Срабатывает брейкпоинт, и вот мы уже видим в IDA инструкцию, которая только что изменила память.
DedMorozzz
Цитата(AlexSpl @ 30 Dec 2016, 18:08) *
Адрес отряда легко посчитать. Да хотя бы на том же калькуляторе, если известен адрес combatManager. Известен адрес отряда, значит, и известны все его параметры. Например, скорость +196. Остаётся приаттачиться к процессу, поставить брейкпоинт на память по вычисленному адресу (в данном случае на запись, hardware), продолжить игру и повесить на этот отряд Молитву. Срабатывает брейкпоинт, и вот мы уже видим в IDA инструкцию, которая только что изменила память.

Я наверное что-то упускаю...
но какой "калькулятор"? Комбат менеджер да, есть. Но как получить отряд, если допустим не эксперт молитва?
А по поводу дебага вроде понятно. Но вот "вычисленный адрес", на который поставить брейк поинт - не ясен тоже smile.gif
AlexSpl
По шагам.

1. Начинаем бой. Загружаем базу игры в IDA и выбираем Debugger -> Attach to process...
2. Вычисляем адрес отряда. Пусть это будет самый верхний стек нашей армии в начале первого раунда.
2.1. Для начала смотрим адрес combatManager: клавиша G, вводим 699420 и записываем адрес (4 байта).
2.2. Вычисляем адрес отряда unitAddress = combatManager + 1352 * (unitNumber + 21 * unitSide) + 12708. В нашем случае unitAddress = combatManager + 1352 * (0 + 21 * 0) + 12708 = combatManager + 12708.
2.3. Вычисляем адрес параметра: прибавляем оффсет (например, +196 для скорости).
3. Снова жмём G, вводим этот адрес (понятно, что шестнадцатеричное значение). Ставим брейкпоинт: F2, снимаем флаг Read, ставим флаг Hardware.
4. Продолжаем игру: F9, кастуем Молитву. Инструкция выше выделенной и есть нужная.

Кстати, адреса и оффсеты лучше писать в шестнадцатеричной системе счисления, чтобы легко можно было потом считать.
DedMorozzz
https://sc-cdn.scaleengine.net/i/98a3f4c01a...24af4cb70c1.png - такой брейк поинт для комбат менеджера? (самый первый пункт)
Ранее диалога такого не показывалось

В общем если я правильно понимаю. Адрес такой - 07F32EF8. Я на верном пути?)
AlexSpl
Не, туда ставить не нужно. Делайте всё по инструкции ) Калькулятор можно использовать стандартный. Выберите режим "Программист" и переключитесь на HEX.

Цитата
2.1. Для начала смотрим адрес combatManager: клавиша G, вводим 699420 и записываем адрес (4 байта).
2.2. Вычисляем адрес отряда unitAddress = combatManager + 1352 * (unitNumber + 21 * unitSide) + 21708. В нашем случае unitAddress = combatManager + 1352 * (0 + 21 * 0) + 12708 = combatManager + 21708.


Поправил 12708 на 21708.

Цитата
В общем если я правильно понимаю. Адрес такой - 07F32EF8. Я на верном пути?)

Похож.

Теперь прибавьте к этому значению 21708 или 54ССh. Получите адрес первого отряда. Прибавьте смещение параметра - получите адрес параметра. Туда и нужно ставить брейкпоинт.
DedMorozzz
Цитата(AlexSpl @ 30 Dec 2016, 18:36) *
Не, туда ставить не нужно. Делайте всё по инструкции ) Калькулятор можно использовать стандартный. Выберите режим "Программист" и переключитесь на HEX.

Ага, дефолтный калькулятор и юзаю...
В общем, что получилось:
2.1. 07F32EF8
2.2. unitAddress = combatManager + 12708
07F32EF8 = ‭133377784‬
133377784‬ + 12708 == 133390492

Теперь перевожу 133390492 в хекс - ‭7F3609C‬

Пробую найти "‭7F3609C‬" в ИДА - пишет не верный адрес

PS: ага, с 21704 завелось. получилось 7F383C4. А со смещением (+196) вышло 7F38488
AlexSpl
Цитата
2.2. Вычисляем адрес отряда unitAddress = combatManager + 1352 * (unitNumber + 21 * unitSide) + 21708. В нашем случае unitAddress = combatManager + 1352 * (0 + 21 * 0) + 12708 = combatManager + 21708.


Перевожу в хекс:
Цитата
2.2. Вычисляем адрес отряда unitAddress = combatManager + 0x548 * (unitNumber + 0x15 * unitSide) + 0x54CC. В нашем случае unitAddress = combatManager + 0x548 * (0 + 0x15 * 0) + 0x54CC = combatManager + 0x54CC.


Соответственно, смещения тоже в хексе писать нужно: 196 = 0xC4.

Если не получается, заскриньте после 2.1. Я приведу пример расчёта с реальными цифрами.
DedMorozzz
Поставил точки остановки. Не отрабатывают.
2.1 - https://sc-cdn.scaleengine.net/i/2e9c35b615...2ba8952d7e5.png
адрес - 7F32EF8
2.2 - 133377784 + 21708 + 196 = 133399688
в хексовом виде - 7F38488
3. https://sc-cdn.scaleengine.net/i/0a85f3a7d4...157f85f9a82.png
4. молитва кастуется, ничего не происходит

PS: вот 2й заход. Всё с 0 сделал. Вот после каста молитвы https://sc-cdn.scaleengine.net/i/8772c1268f...18fac1ed0c3.png
Ничего не останавливалось. Бой как шел так и идёт
AlexSpl
Короче, надеюсь, что адрес вы считаете верно. Иначе работать не будет. Также учтите, что адрес combatManager - не есть постоянная. Если выходите из игры, нужно пересчитывать.

Далее, после того, как Вы нашли адрес параметра (скорости, например), переходите по этому адресу и просто жмите F2. Флаги Вы убрали, но почему Enabled не стоит? Кроме того, из скрина видно, что скорость отряда равна 7 (так ли это?). Если всё сделать правильно, то после каста Молитвы на первый отряд, сработает брейкпоинт.

UPD На скорость не надо ставить - это для примера. Лучше на атаку поставьте. Молитва меняет модификатор скорости, а не скорость.
DedMorozzz
Цитата(AlexSpl @ 30 Dec 2016, 19:04) *
Короче, надеюсь, что адрес вы считаете верно. Иначе работать не будет. Также учтите, что адрес combatManager - не есть постоянная. Если выходите из игры, нужно пересчитывать.

Далее, после того, как Вы нашли адрес параметра (скорости, например), переходите по этому адресу и просто жмите F2. Флаги Вы убрали, но почему Enabled не стоит? Кроме того, из скрина видно, что скорость отряда равна 7 (так ли это?). Если всё сделать правильно, то после каста Молитвы на первый отряд, сработает брейкпоинт.


Да, скорость была 7, это был кентавр на траве. Сейчас с архом пробую.
Когда галочку "енейблед" поставил - завелось. Т.е. не активирован брейк поинт был..

Вот такой код, на котором остановилась игра - https://sc-cdn.scaleengine.net/i/4cfb6118f0...ed0b9f6a071.png

Код
.text:00444928 loc_00444928:                                             ; CODE XREF: combatMonster_ApplySpell+302j
.text:00444928 mov     eax, [esi+478h]
.text:0044492E mov     ecx, [esi+0C8h]
.text:00444934 mov     ebx, [esi+0CCh]
.text:0044493A add     ecx, eax                                          ; Add
.text:0044493C mov     [esi+0C8h], ecx
.text:00444942 mov     ecx, [esi+84h]
.text:00444948 shr     ecx, 6                                            ; Shift Logical Right
.text:0044494B add     ebx, eax                                          ; Add
.text:0044494D test    cl, 1                                             ; Logical Compare
.text:00444950 mov     [esi+0CCh], ebx
.text:00444956 jnz     loc_00444D5C                                      ; default
.text:00444956                                                        ; jumptable 00444701 cases 8,10-13,20,30,36-43,45,47
.text:0044495C add     [esi+0C4h], eax                                ; Add
.text:00444962 jmp     loc_00444D5C                                      ; default
.text:00444962                                                        ; jumptable 00444701 cases 8,10-13,20,30,36-43,45,47



.text:0044492E mov ecx, [esi+0C8h]
.text:00444934 mov ebx, [esi+0CCh]
Это походу атака/защита
AlexSpl
Я апдейт написал в предыдущий пост. Если сработал брейкпоинт, то действительно изменилась скорость. Но безопаснее на атаку или защиту ставить.

Цитата
Код
.text:0044493C mov     [esi+0C8h], ecx

Ага, похоже на правду. Запишите этот адрес. И с атакой/защитой попробуйте.

Стоп. 0xC8 - это ж и есть атака.
DedMorozzz
если я правильно понимаю, теперь надо на адрес 00444928 поставить лоу хук
в ф-ии сделать другие цифры. И вернуть дефолтное?
AlexSpl
Теперь LoHook на 44493Ch и пишете свой код.
DedMorozzz
c->esi это у нас монстр?
Ибо не работает так:
Код
int __stdcall spellPray(LoHook* h, HookContext* c)
{
    *(int*)(c->esi + 200) += 2;

    return EXEC_DEFAULT;
}

Код
_PI->WriteLoHook(0x44493C, spellPray);
AlexSpl
Например, безусловно увеличиваем атаку дополнительно на +2:

Код
{
    c->ecx +=2;
    return EXEC_DEFAULT;
}


Если нужно не дополнительно (т.е. без стандартного бонуса к атаке), а прописать значение, то LoHook ставить нужно выше: 44493A. И скиповать инструкцию add ecx, eax.

Код
{
    c->ecx =10;
    c->return_address = 0x44493C;
    return NO_EXEC_DEFAULT;
}


Ещё нужно учесть, чтобы бонус корректно снимался. Просто кастуете молитву и ждёте, пока не сработает второй брейкпоинт: там бонус убирается. Соответственно, туда тоже LoHook. Например,

Код
{
    c->ecx -=2;
    return EXEC_DEFAULT;
}
DedMorozzz
А как проверить школу и уровень школы кастуемого заклинания?
Как я понимаю благо надо будет прописывать в ручную. И если герой кастует молитву базовую то и давать базовое благо
И ещё ... улучшеное благо это:
1. максимальная атака += 1;
2. минимальная атака = максимальная атака?

Или какая-то другая логика
AlexSpl
Если удобнее через указатель на отряд, то вот код, который добавляет +6 к атаке:

Код
{
    *(int*)(c->esi + 200) += 6;
        c->return_address = 0x444942;
    return NO_EXEC_DEFAULT;
}


LoHook на 44493Ch (!)

Поправил. Стандартный бонус нужно пропустить.
DedMorozzz
Цитата(AlexSpl @ 30 Dec 2016, 19:40) *
Если удобнее через указатель на отряд, то вот код, который добавляет +6 к атаке:

Код
{
    *(int*)(c->esi + 200) += 6;
        c->return_address = 0x444942;
    return NO_EXEC_DEFAULT;
}


LoHook на 44493Ch (!)

Поправил. Стандартный бонус нужно пропустить.

Вот если пропускаем стандартный бонус то возникает вопрос проверки школы..
Ибо базовый должен давать +4/4/2, улучшеный +6/6/4, эксперта то же самое что и улучшеный, но на всех
AlexSpl
А вот простейшее решение, если нужно поднять атаку и защиту одновременно, как это делает игра:

Код
{
    c->eax = bonus; // не += !
    return EXEC_DEFAULT;
}


LoHook на 44492Eh.

* * *
Цитата
Вот если пропускаем стандартный бонус то возникает вопрос проверки школы..
Ибо базовый должен давать +4/4/2, улучшеный +6/6/4, эксперта то же самое что и улучшеный, но на всех


Тогда так:

Код
{
    c->eax += relative bonus;
    return EXEC_DEFAULT;
}


LoHook на 44492Eh.
DedMorozzz
Так как школу(точнее уровень 0-1-2-3. Где 3 - эксперт, 0 - нет школы даже базовой) каста узнать то? smile.gif
AlexSpl
Цитата
Так как школу(точнее уровень 0-1-2-3. Где 3 - эксперт, 0 - нет школы даже базовой) каста узнать то?

Лучше всего поставить брейкпоинт на +478h и найти место, где этот бонус прописывается. Тогда, наверное, и массовая версия работать будет нормально. Вот там школу будет проще получить.

Т.е. тот же алгоритм, только смещение добавляйте +478h, а не +0С8h.

Кстати, перед тем как ставить новый брейкпоинт на память рекомендую удалить старые: Ctrl+Alt+B. Иначе при следующем запуске игры будем получать останов в рандомном месте кода.

Короче, тут и искать не надо )

Всё рядом.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Форум IP.Board © 2001-2025 IPS, Inc.