Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Мод на ХотА
DF2 :: ФОРУМЫ > Игровые форумы > Heroes of Might & Magic III > Моды
Страницы: 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12
AlexSpl
Как раз те условия, что мы пропустили, должны были позаботиться об этом. Т.е. мой первоначальный вариант работает на SoD корректно. Позже посмотрю, почему не хочет работать на Хота.
DedMorozzz
Так а что мешает привязаться к логике побега? Т.е. это по сути и есть разновидность побега
Ток не знаю как проверить возможность сбежать..
AlexSpl
Нужно добавить пару условий в функцию setSurrenderButton(). Видимо, если героя у противника нет, то edi в Хота возвращает не ноль. Это, наверное, ещё и причина того, что диалог так просто завёлся.
AlexSpl
Просто интересно, а если поставить LoHook на 0x477EA9, первоначальный код будет работать?

Код
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;
}


Код
_PI->WriteLoHook(0x477EA9, setSurrenderButton);
DedMorozzz
Да, всё работает так же
Какой из них более корректный? или всё равно?
AlexSpl
Странно. Проверь работу тактической фазы и осады. Герой с Дипломатией и без неё против героя/нейтралов.

Должно быть так:
1. В тактической фазе кнопка "Сдаться" всегда неактивна";
2. В битве против героя кнопка "Сдаться" активна;
3. В битве против нейтралов кнопка "Сдаться" активна, только если у героя есть Дипломатия;
4. При осаде, если герой защищает город, кнопка "Сдаться" неактивна (активна только при наличии соотв. строения).
DedMorozzz
ух ты. Не могу сбежать, во время осады города. Если защищаюсь. Нападающий - может

1. Не проверял, это не особо актуально. Ибо сбежать то можно, по логике и сдаться тоже.. т.е. любой вариант нормальный
2. так и есть
3. так и есть
4. так и есть (не проверял в варварском замке)

1, 4 сейчас проверю...
AlexSpl
См. пост выше. Интересно, почему старый хук не работал так же...
DedMorozzz
Проверяю последнии моменты (работа с оковами и дипломатия + тактика)
Но в целом НЕ дипломат во время тактики может сдаться. Дипломаю думаю тоже сможет
По поводу замка с "ходом". Убежать можно, сдаться - нет (ну это может и правильно, ибо не дипломат так же)

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

Допроверил всё... всё работает как надо. Оковы не отпускают никогда. Ни сбежать, ни постройка в замке, ни навык дипломатии, ни сдаться - никак нельзя
Тактика никак на дипломата не влияет. Сдаться/убежать могут любые герои
С мобами только дипломат может убежать/сдаться
Фикс в ХотА, что оковы не дествуют в бою с мобами, так же действует и на откуп. Можно откупиться при одетых оковах от мобов
AlexSpl
Получается, что только в тактической фазе отличия. С замком всё в порядке. Можно сбежать только через "Подземный ход", но не сдаться.

UPD Это я опять туплю. Действительно, всё в порядке. Сдаться можно и в тактической фазе. Просто в оригинале нейтралам сдаться вообще нельзя, в т.ч. и во время тактической фазы.

Проверьте тогда следующее в тактической фазе:

1. Герой без Дипломатии против нейтралов (кнопка "Сдаться" должна быть неактивна);
2. Герой с Дипломатией против нейтралов (кнопка "Сдаться" должна быть активна);
DedMorozzz
По поводу стоимости откуда от монстров. Функа по адресу - 474942
Оттуда переходим сюда loc_00474980. В ней имеется функция GetDiplomacyPower. Я так понимаю она нам и нужна...
И в новом хуке (setSurrenderButton) заодно и переписать уменьшение выкупа? Что бы только для монстров другие процены были...
AlexSpl
Дипломатия влияет на стоимость сдачи и так. Какие отличия должны быть при сдаче нейтралам?

Цитата
Base price when surrendering is half the army's cost in gold. This can be further reduced via
Diplomacy and Artifacts to a total of 5% of normal price.


Куда уж меньше? smile.gif И так уже сильный навык получился. Одна возможность откупаться от нейтралов чего стоит.
DedMorozzz
Цитата(AlexSpl @ 25 Dec 2016, 17:37) *
Дипломатия влияет на стоимость сдачи и так. Какие отличия должны быть при сдаче нейтралам?

Цитата
Base price when surrendering is half the army's cost in gold. This can be further reduced via
Diplomacy and Artifacts to a total of 5% of normal price.


Куда уж меньше? smile.gif И так уже сильный навык получился. Одна возможность откупаться от нейтралов чего стоит.


На самом деле баланс штука тонкая это факт)
Но по сути, что такое откупиться от нейтралов - это тот же самый таун портал, только с ценой в 2.5к голды(стоимость героя) + цена войска (процент от неё). И при этом не с любого места
На выходе не выходит чего-то сверх сильного, вот в начале игры будет пользоваться спросом, когда надо будет вернуться в город.
Обычно цепочки строятся, которые вернут войска, а с дипломатией та же цепочка будет, но вот в замке можно быть сразу ускореным, если убежать с каким нибуть условным ангелом

Потому планирую сделать откуп от монстров 30-20-10%. А арты снижать на 5% будут. Т.е. 2 арта дипломата = портал города за 2500 голды smile.gif

Но вот что планирую изменить, это либу. Что бы +3 давала на всех левелах. Сейчас +4 на эксперте (но на практике не проверялось насколько это эффективно)

Итого в планах навык дипломатии должен давать:
1. усиливать войска при учёте побега/разбивки на пачки на 10-20-30%
2. снижать цену капитуляции на 20-40-60% (родное поведение)
3. уменьшать левел для посещения либы на 2-4-6 (родное поведение)
4. либа давать будет на +1 к статам выше, т.е. по +3
5. сдаваться можно монстрам по цене 30-20-10% от стоимости

Арты:
1. увеличивают силу армии на 10%
2. Умеьшает цену капитуляции на 10% для героя (5% для монстров)
3. Уменьшает левел для посещения либы на 1

При этом монстры не могут присоединяться. Эта способность убирается у дипломатии

На выходе достаточно много разных моментов, но все они не существенные smile.gif
Только библиотека влияет. Но по статистике за игру посещается примерно 1 библиотека. Так что не настолько и сильный навык, но уже полезный

И даже так, если выбрать логистику/землю/нападение или дипломатию, я выберу 1е)
AlexSpl
Понятно. Нейтралам хотите платить больше. Я бы особо не заморачивался, а просто б умножил стоимость капитуляции на 2 для нейтралов.

Ага. Наоборот.

Цитата
2. снижать цену капитуляции на 20-40-60%

Цитата
5. сдаваться можно монстрам по цене 30-20-10% от стоимости

Т.е. снижение стоимости получается 90-80-70% (при сдаче нейтралам) против 60-40-20% (при сдаче героям)?
DedMorozzz
Цитата(AlexSpl @ 25 Dec 2016, 18:45) *
Понятно. Нейтралам хотите платить больше. Я бы особо не заморачивался, а просто б умножил стоимость капитуляции на 2 для нейтралов.

Наоборот, меньше
AlexSpl
Тогда смотрите на инструкцию по адресу 4E4804h. Она как раз в регистр edx коэффициенты (0.2, 0.4, 0.6) загружает.

Т.е. примерная функция хука:

Код
if ( opponent == neutrals ) {
    switch ( diplomacyLevel ) {
        case 1: (float)c->edx = 0.7f;
        case 2: (float)c->edx = 0.8f;
        case 3: (float)c->edx = 0.9f;
    }
    c->return_address = 0x4E480B;
    return NO_EXEC_DEFAULT;
}; else return EXEC_DEFAULT;


diplomacyLevel в данном контексте элементарно получается:
Код
char diplomacyLevel = (char)c->ecx;


* * *
Т.е. код такой должен быть:

Код
if ( *(int*)(*(int*)0x699420 + 0x132C0) == 0 ) {
    switch ( (char)c->ecx ) {
        case 1: (float)c->edx = 0.7f;
        case 2: (float)c->edx = 0.8f;
        case 3: (float)c->edx = 0.9f;
    }
    c->return_address = 0x4E480B;
    return NO_EXEC_DEFAULT;
}; else return EXEC_DEFAULT;
DedMorozzz
Код
int __stdcall setSurrenderPrice(LoHook* h, HookContext* c)
{
    float surrenderPrice[4] = {0.00, 0.70, 0.8, 0.9};
    
    if ( *(int*)(*(int*)0x699420 + 0x132C0) == 0 ) {
        float currentModifier = ( ((char)c->ecx >= 0) && ((char)c->ecx <= 3) ? surrenderPrice[(char)c->ecx] : 1 );
        c->edx = currentModifier;
        //c->edx = 0.2;
        //c->ecx = 0.2;
        
        c->return_address = 0x4E480B;

        return NO_EXEC_DEFAULT;
    }
    
    return EXEC_DEFAULT;
}


Код
_PI->WriteLoHook(0x4E4804, setSurrenderPrice);


закоментил 2 строки которые пробовал и не вылетает при которых. В общем 60% скидка. Арх убегает за 1999 голды
Любой вариант, цена та же. Только дипломатия учитывается

PS: проверил адресса, вроде всё верно. Странно
AlexSpl
Сам свитч работает?
Код
switch ( (char)c->ecx ) {
    case 1: (float)c->edx = 0.7f;
    case 2: (float)c->edx = 0.8f;
    case 3: (float)c->edx = 0.9f;
}
c->return_address = 0x4E480B;
return NO_EXEC_DEFAULT;


Полагаю, вот это условие *(int*)(*(int*)0x699420 + 0x132C0) == 0 не выполняется.

* * *
Проверил, должно работать и на Хота.
DedMorozzz
так ошибка:
1>.\dllmain.cpp(329) : error C2106: '=' : left operand must be l-value
1>.\dllmain.cpp(330) : error C2106: '=' : left operand must be l-value
1>.\dllmain.cpp(331) : error C2106: '=' : left operand must be l-value


и в 1м вариенте она и была. Если убираю флоат - тогда ошибки нету. Но цена откупа = 40%
1 Арх = 1999

Полный код:
Код
int __stdcall setSurrenderPrice(LoHook* h, HookContext* c)
{
    if ( *(int*)(*(int*)0x699420 + 0x132C0) == 0 ) {
        switch ( (char)c->ecx ) {
            case 1: c->edx = 0.7f;
            case 2: c->edx = 0.8f;
            case 3: c->edx = 0.9f;
        }
        c->return_address = 0x4E480B;

        return NO_EXEC_DEFAULT;
    }
    
    return EXEC_DEFAULT;
}

Код
_PI->WriteLoHook(0x4E4804, setSurrenderPrice);
AlexSpl
Убрал пост. Оказывается на C++ ещё та проблема float в int запихнуть. Сейчас подумаю.
AlexSpl
Попробуйте вот так:
Код
int __stdcall setSurrenderPrice(LoHook* h, HookContext* c)
{
    if ( *(int*)(*(int*)0x699420 + 0x132C0) == 0 ) {
        switch ( (char)c->ecx ) {
            case 1:  *(float*)&c->edx = 0.7f;  break;
            case 2:  *(float*)&c->edx = 0.8f;  break;
            case 3:  *(float*)&c->edx = 0.9f;  break;
            default:  c->edx = 0;
        }
        c->return_address = 0x4E480B;

        return NO_EXEC_DEFAULT;
    }
    
    return EXEC_DEFAULT;
}


И без условия:
Код
int __stdcall setSurrenderPrice(LoHook* h, HookContext* c)
{
    switch ( (char)c->ecx ) {
        case 1:  *(float*)&c->edx = 0.7f;  break;
        case 2:  *(float*)&c->edx = 0.8f;  break;
        case 3:  *(float*)&c->edx = 0.9f;  break;
        default:  c->edx = 0;
    }
    c->return_address = 0x4E480B;

    return NO_EXEC_DEFAULT;
}


* * *
Посмотрел код. Там есть ограничение: уменьшение стоимости не может быть более 90%. Так что его тоже нужно убирать.
А случайно Хота эту функцию (GetDiplomacyPower) не патчит?
DedMorozzz
С дипломатией арх от монстров убегает за 250 золотых (при 2х артах дипломатии и без них)
От героя тоже за 250 золотых
Арх стоит 5000

Герой без дипломатии не может убежать от монстров, а от героя убегает за 2500 золотых

Код
int __stdcall setSurrenderPrice(LoHook* h, HookContext* c)
{
    if ( *(int*)(*(int*)0x699420 + 0x132C0) == 0 ) {
        switch ( (char)c->ecx ) {
            case 1:  *(float*)&c->edx = 0.7f;  break;
            case 2:  *(float*)&c->edx = 0.8f;  break;
            case 3:  *(float*)&c->edx = 0.9f;  break;
            default:  c->edx = 0;
        }
        c->return_address = 0x4E480B;

        return NO_EXEC_DEFAULT;
    }
    
    return EXEC_DEFAULT;
}


Код
_PI->WriteLoHook(0x4E4804, setSurrenderPrice);



case 3: *(float*)&c->edx = 0.3f; break; -- тут ставлю 0.3 и получается откуп за 35% цены
Судя по всему цена режется на 2. Но не менее 5%

Цитата
А случайно Хота эту функцию (GetDiplomacyPower) не патчит?

Прочитал изменения хоты. Про дипломатию ни слова (только новый сборный арт добавили). Так что скорее всего нет
AlexSpl
Да, после вызова функции идёт деление на 2.
DedMorozzz
Цитата(AlexSpl @ 26 Dec 2016, 22:11) *
Да, после вызова функции идёт деление на 2.

Это так и надо? И где ограничение в 10% стоит, что меньше нельзя?
AlexSpl
см. код по адресу 4E4927h

Декомпилированный вариант:
Код
if ( DiploMod > 0.89999998 ) DiploMod = 0.89999998;
DedMorozzz
Цитата(AlexSpl @ 26 Dec 2016, 22:26) *
см. код по адресу 4E4927h

Декомпилированный вариант:
Код
if ( DiploMod > 0.89999998 ) DiploMod = 0.89999998;


Не пойму какое значение верное для этой проверки

Код
int __stdcall setSurrenderMinPrice(LoHook* h, HookContext* c)
{
    //ebp+var_4 -- такое в ИДА есть, но явно не то что надо
    
    /*
        if ( (char) c->edi > 1) {
          *(float*)&c->edi = 1.0f;
        }
        */
    
    //ecx+eax*8 ---- и такое есть
    /*
    if ( (char) (c->ecx + c->eax*8) > 1 ) {
           *(float*)& (c->ecx + c->eax*8) = 1.0f;
        }
    */
    
    return NO_EXEC_DEFAULT;
}

Код
_PI->WriteLoHook(0x4E492A, setSurrenderMinPrice);


Вот этот код (т.е. просто return NO_EXEC_DEFAULT;), при 2х артах дипломата далает цену откупа (при базовом значении 0.9) в -5% (-10% / 2)
С 1м артом цена = 0. С 2мя - монстры доплачивают, что бы уже сбежал smile.gif я не шучу, -250 голды с архом стоит откуп)
Т.е. место верное. Убираю проверку на граничение цены. А вот как изменить её - не пойму какой esi/edi/ecx юзать
DedMorozzz
Цитата(igrik @ 05 Dec 2016, 13:06) *
Цитата
Как молитве сделать не +4, а +6 ко всем статам (имеется ввиду атака+защита)?

Бонусы молитвы прописаны в "SPTRAITS.TXT".


Проверил, по факту только описание меняется. А даёт столько же, сколько и ранее. При этом манакост/школа к которой относится меняется, а логика нет.
Что собсно и ожидаемо. Было бы крайне странно, если бы логика поведения была бы описана обычным текстом
AlexSpl
Здесь лучше хук на 4E4931h поставить, чтобы не пропустить инструкцию pop edi.

Код такой:

Код
{
    float diploCap = 0.99f; // ограничение  

    if ( *(float*)(c->ebp - 4) > diploCap ) {
        *(float*)(c->ebp - 4) = diploCap;
    }

    c->return_address = 0x4E493F;
    return NO_EXEC_DEFAULT;
}
DedMorozzz
Цитата(AlexSpl @ 27 Dec 2016, 16:40) *
Здесь лучше хук на 4E4931h поставить, чтобы не пропустить инструкцию pop edi.

Код такой:

Код
{
    float diploCap = 0.99f; // ограничение  

    if ( *(float*)(c->ebp - 4) > diploCap ) {
        *(float*)(c->ebp - 4) = diploCap;
    }

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

Работает! Спасибо. А откуда ты взять ebp - 4
Я код почитал, попробовал разные варианты - ничего не подошло

PS: только вот эта проверка не работает. if ( *(int*)(*(int*)0x699420 + 0x132C0) == 0 ) {
От героя по той же цене убегает
AlexSpl
Цитата
А откуда ты взять ebp - 4
Я код почитал, попробовал разные варианты - ничего не подошло

Модификатор стоимости капитуляции хранится в локальной переменной (var_4, [ebp-4]).

Цитата
*(int*)(*(int*)0x699420 + 0x132C0)

Было бы неплохо увидеть значение. Но наверняка в combatManager'е есть и другие полезные поля, по которым можно определить, с кем велась битва.

* * *
Проверил, оказывается, что *(int*)(*(int*)0x699420 + 0x132C0) - это не адрес героя.
AlexSpl
Попробуйте заменить условие на следующее:

Код
int cmAddr = *(int*)0x699420; // адрес combatManager
int side = *(int*)(cmAddr + 0x132C0); // сторона в битве (0 - правая, 1 - левая)
if ( *(int*)(cmAddr + (0x14F4 - side) * 4) == 0 ) {
...
}


Например, для setSurrenderPrice:

Код
int __stdcall setSurrenderPrice(LoHook* h, HookContext* c)
{
    int cmAddr = *(int*)0x699420; // адрес combatManager
    int side = *(int*)(cmAddr + 0x132C0); // сторона в битве (0 - правая, 1 - левая)
    if ( *(int*)(cmAddr + (0x14F4 - side) * 4) == 0 ) {
        // если нейтралы, меняем модификаторы (0.7, 0.8, 0.9)
        switch ( (char)c->ecx ) {
            case 1:  *(float*)&c->edx = 0.7f;  break;
            case 2:  *(float*)&c->edx = 0.8f;  break;
            case 3:  *(float*)&c->edx = 0.9f;  break;
            default:  c->edx = 0;
        }
        c->return_address = 0x4E480B;
        return NO_EXEC_DEFAULT;
    }
    
   // если герой, оставляем стандарные модификаторы (0.2, 0.4, 0.6)    
   return EXEC_DEFAULT;
}
DedMorozzz
Цитата(AlexSpl @ 27 Dec 2016, 17:30) *
Было бы неплохо увидеть значение. Но наверняка в combatManager'е есть и другие полезные поля, по которым можно определить, с кем велась битва.

а как это посмотреть?

Цитата(AlexSpl @ 27 Dec 2016, 18:21) *
Попробуйте заменить условие на следующее:

Да, работает. От нейтралов с артами бесполатно. От героя платно
AlexSpl
Аналогично меняем ограничение:

Код
{
    int cmAddr = *(int*)0x699420; // адрес combatManager
    int side = *(int*)(cmAddr + 0x132C0); // сторона в битве (0 - правая, 1 - левая)
    
    float diploCap;
    if ( *(int*)(cmAddr + (0x14F4 - side) * 4) == 0 ) diploCap = 0.99f; else diploCap = 0.9f;

    if ( *(float*)(c->ebp - 4) > diploCap ) {
        *(float*)(c->ebp - 4) = diploCap;
    }

    c->return_address = 0x4E493F;
    return NO_EXEC_DEFAULT;
}
DedMorozzz
хоть и текущего смысла в этом ограничении нету, но на "всякий" можно сделать
Ибо 60+10+10+10 (3 арта) это и есть 90%
AlexSpl
А как же спецы Дипломаты?
DedMorozzz
Цитата(AlexSpl @ 27 Dec 2016, 18:49) *
А как же спецы Дипломаты?

я или не правильно помню. Или таких нету

Ну и ещё момент с дипломатией. Хочу что бы арты дипломата снижали требования уровня для либы. Т.е. дефолтные 10. Каждый уровень дипломатии отнимает 2. А каждый арт по -1
Какой адресс отвечает за требования уровня?
AlexSpl
Ага, точно нету. Но код учитывает и спецов )

Цитата
Какой адресс отвечает за требования уровня?


4A2F47h

Код
.text:004A2F47 loc_4A2F47:
.text:004A2F47 movsx   ecx, byte ptr [esi+0CDh]
.text:004A2F4E movsx   edx, word ptr [esi+55h]
.text:004A2F52 lea     eax, [edx+ecx*2]
.text:004A2F55 cmp     eax, 0Ah
DedMorozzz
Цитата(AlexSpl @ 27 Dec 2016, 19:12) *
Ага, точно нету. Но код учитывает и спецов )

Цитата
Какой адресс отвечает за требования уровня?


4A2F47h

Код
.text:004A2F47 loc_4A2F47:
.text:004A2F47 movsx   ecx, byte ptr [esi+0CDh]
.text:004A2F4E movsx   edx, word ptr [esi+55h]
.text:004A2F52 lea     eax, [edx+ecx*2]
.text:004A2F55 cmp     eax, 0Ah


Если я правильно понимаю, то надо изменить сам ответ от функции, отняв оттуда по левелу за арт
Вижу такой код:
Код
.text:004A2EFD                     mov     ecx, [eax]
.text:004A2EFF                     mov     esi, [ebp+arg_0]
.text:004A2F02                     shl     ebx, cl                    ; Shift Logical Left
.text:004A2F04                     test    [esi+6Fh], ebx                ; Logical Compare
.text:004A2F07                     jz      short loc_004A2F47            ; Jump if Zero (ZF=1)
.text:004A2F09                     mov     al, [ebp+arg_8]
.text:004A2F0C                     test    al, al                        ; Logical Compare
.text:004A2F0E                     jz      loc_004A3046                  ; Jump if Zero (ZF=1)

И уровень героя, скорее всего тут - ebp+arg_8
Как понять что в arg_8 или в arg_0
Поставил точку остановки и вижу такое:
https://sc-cdn.scaleengine.net/i/71b863470d...3f9c79e68d1.png

Никакого значения переменной не отображается

PS: не, фигня. Сам ответ от фукнции "да" или "нет". Соотв кастыльное решение - увеличивать уровень героя на +1 для расчёта допуска к библиотеке
Нормальное - уменьшать требования. Пока что смотрел на не правльное

Но вопрос всё равно актуальный, как смотреть значения в arg_№?
AlexSpl
Нет, я же написал адрес. esi - адрес героя, соответственно, [esi+55h] = *(short*)(c->esi + 85) - уровень героя, [esi+CDh] = *(char*)(c->esi + 201 + 4) - уровень дипломатии. Легко и арты получить, если знаешь адрес героя.

Т.е. ставите LoHook на 4A2F52h и в цикле перебираете арты.

А как Вы, кстати, хотите, чтобы библиотека работала?
DedMorozzz
Цитата(AlexSpl @ 27 Dec 2016, 19:30) *
Нет, я же написал адрес. esi - адрес героя, соответственно, [esi+55h] = *(short*)(esi + 85) - уровень героя, [esi+CDh] = *(char)(c->esi + 201 + 4) - уровень дипломатии. Легко и арты получить, если знаешь адрес героя.

вроде понял, 10 мин. попробую прикрутить. Как арты смотреть вроде уже знаю

Цитата(AlexSpl @ 27 Dec 2016, 19:30) *
А как Вы, кстати, хотите, чтобы библиотека работала?

При наличии дипломатии что бы давала +3 к статам (это уже есть), код вот:

Код
int __stdcall libraryVisit(LoHook* h, HookContext* c)
{
    if (*(char*)(c->esi + 201 + 4) > 0) {
        char bonus = 1;

        *(char*)(c->esi + 1142) += bonus;                // атака
        *(char*)(c->esi + 1143) += bonus;                // защита
        *(char*)(c->esi + 1144) += bonus;                // колд. сила
        *(char*)(c->esi + 1145) += bonus;                // знания
    }

    if (*(char*)(c->esi + 201 + 4) > 0) {
        char moreleBonus = *(char*)(c->esi + 201 + 4);
        *(char*)(c->esi + 282) += moreleBonus;
    }

    return EXEC_DEFAULT;
}

Код
_PI->WriteLoHook(0x4A2F92, libraryVisit);

Ну и +1/2/3 морали до след. битвы


А при наличии артов, уменьшался требуемый левел на один
AlexSpl
Цитата
Но вопрос всё равно актуальный, как смотреть значения в arg_№?

К решению задачи не относится, но. Установите курсор на arg_N и нажмите клавишу k. Увидите что-то типа этого: [ebp + 8]. Аналогично с var_N: [ebp - 8].

Цитата
А при наличии артов, уменьшался требуемый левел на один

Код
lea     eax, [edx+ecx*2]


Игра берёт уровень героя (edx) и плюсует к нему уровень дипломатии (ecx), помноженный на 2, затем сравнивает получившееся значение с 10.

Решение простое:

c->eax = (c->edx + количество_артов) + c->ecx * 2;
DedMorozzz
Цитата(AlexSpl @ 27 Dec 2016, 19:45) *
Цитата
Но вопрос всё равно актуальный, как смотреть значения в arg_№?

К решению задачи не относится, но. Установите курсор на arg_N и нажмите клавишу k. Увидите что-то типа этого: [ebp + 8]. Аналогично с var_N: [ebp - 8].

Цитата
А при наличии артов, уменьшался требуемый левел на один

Код
lea     eax, [edx+ecx*2]


Игра берёт уровень героя (edx) и плюсует к нему уровень дипломатии (ecx), помноженный на 2, затем сравнивает получившееся значение с 10.

Решение простое:

c->eax = (c->edx + количество_артов) + c->ecx * 2;


А я так написал, получилось:
Код
int __stdcall setLibraryVisitLevel(LoHook* h, HookContext* c)
{
    if (*(short*)(c->esi + 85) < 10) {
        //*(short*)(c->esi + 85) = 10;
        int tmpLevelBonus = 0;
        for (int i = 0; i < 19; ++i) {
            if ( *(int*)(c->esi + 301 + (i << 3)) == 66 ) {
                tmpLevelBonus += 1;
            }

            if ( *(int*)(c->esi + 301 + (i << 3)) == 67 ) {
                tmpLevelBonus += 1;
            }

            if ( *(int*)(c->esi + 301 + (i << 3)) == 68 ) {
                tmpLevelBonus += 1;
            }
        }

        *(short*)(c->esi + 85) += tmpLevelBonus;
    }
    
    return EXEC_DEFAULT;
}


С небольшим но, левел реально вырос) Навыки не дали, просто открыв героя левел пишется выше
AlexSpl
Код
int __stdcall setLibraryVisitLevel(LoHook* h, HookContext* c)
{
    for (int i = 0; i < 19; ++i) {
        switch ( *(int*)(c->esi + 301 + (i << 3)) ) {
            case 66:  c->edx += 1; break;
            case 67:  c->edx += 1; break;
            case 68:  c->edx += 1; break;
        }
    }

    c->eax = c->edx + c->ecx * 2;
    c->return_address = 0x4A2F55;
    return NO_EXEC_DEFAULT;
}


LoHook на 4A2F52h.

Этот код для случая, если бонусы для артов решите поменять. Если для всех +1, то можно проще написать.

Закончил редактировать. Реально есть проблема с табуляцией )
DedMorozzz
Цитата(AlexSpl @ 27 Dec 2016, 20:01) *
Код
int __stdcall setLibraryVisitLevel(LoHook* h, HookContext* c)
{
    for (int i = 0; i < 19; ++i) {
        switch ( *(int*)(c->esi + 301 + (i << 3)) ) {
            case 66:  {
                c->edx += 1;
                break;
            }

            case 67:  {
               c->edx += 1;
               break;
            }
                
            case 68:  {
                c->edx += 1;
                break;
            }
    }

        c->eax = c->edx + c->ecx * 2;
    c->return_address = 0x4A2F55;
    return NO_EXEC_DEFAULT;
}


LoHook на 4A2F52h.

Этот код для случая, если бонусы для артов решите поменять, есть для всех +1, то можно проще написать.


Так мне же надо дипломатию тоже учесть если нету её

У меня получилось пока что так, только вот и для 7го уровня (без дипломатии) условие проходит, статы повышаются:
Код
int __stdcall setLibraryVisitLevel(LoHook* h, HookContext* c)
{
    if (*(short*)(c->esi + 85) < 10) {
        int tmpLevelBonus = 0;
        for (int i = 0; i < 19; ++i) {
            if ( *(int*)(c->esi + 301 + (i << 3)) == 66 ) {
                tmpLevelBonus += 1;
            }

            if ( *(int*)(c->esi + 301 + (i << 3)) == 67 ) {
                tmpLevelBonus += 1;
            }

            if ( *(int*)(c->esi + 301 + (i << 3)) == 68 ) {
                tmpLevelBonus += 1;
            }
        }

        c->eax = ((c->esi + 85) + tmpLevelBonus) + (c->esi + 201 + 4) * 2;
    }
    
    c->return_address = 0x4A2F55;
    return NO_EXEC_DEFAULT;
}


PS: о, вижу новый код)) С дипломатией

PPS: реально не пойму почему мой вариант не работает. По идеи (при 2х артах) должно быть так:
7 + 2 + 0*2 //9
А условие проходит
AlexSpl
Я только что исправил. Реально неудобно код писать в браузере.

Цитата
Так мне же надо дипломатию тоже учесть если нету её

Она учтена тут:

Код
c->eax = c->edx + c->ecx * 2;


На всякий случай, продублирую код:

Код
int __stdcall setLibraryVisitLevel(LoHook* h, HookContext* c)
{
    for (int i = 0; i < 19; ++i) {
        switch ( *(int*)(c->esi + 301 + (i << 3)) ) {
            case 66:  c->edx += 1; break;
            case 67:  c->edx += 1; break;
            case 68:  c->edx += 1; break;
        }
    }

    c->eax = c->edx + c->ecx * 2;
    c->return_address = 0x4A2F55;
    return NO_EXEC_DEFAULT;
}
DedMorozzz
Код
for (int i = 0; i < 19; ++i) {
        switch ( *(int*)(c->esi + 301 + (i << 3)) ) {
            case 66:  c->edx += 1; break;
            case 67:  c->edx += 1; break;
            case 68:  c->edx += 1; break;
        }
    }

    c->eax = c->edx + c->ecx * 2;
    
    c->return_address = 0x4A2F55;
    return NO_EXEC_DEFAULT;

Этот код не работает тоже... Ну не то же.. у меня всегда почему-то работает, даже если левел мал)
AlexSpl
Ваш код не будет работать хотя бы из-за этого:
Код
c->eax = ((c->esi + 85) + tmpLevelBonus) + (c->esi + 201 + 4) * 2;


Вы работаете с адресами, а не со значениями.
DedMorozzz
Цитата(AlexSpl @ 27 Dec 2016, 20:28) *
Ваш код не будет работать хотя бы из-за этого:
Код
c->eax = ((c->esi + 85) + tmpLevelBonus) + (c->esi + 201 + 4) * 2;


Вы работаете с адресами, а не со значениями.


хм. Пока что не сходится:

Код
if (*(char*)(c->esi + 201 + 4) > 0) {
        char moreleBonus = *(char*)(c->esi + 201 + 4);
        *(char*)(c->esi + 282) += moreleBonus;
    }

Тут тот же принцип и работает

не могу уловить пока что разницу

Цитата(AlexSpl @ 27 Dec 2016, 20:12) *
На всякий случай, продублирую код:

Код
int __stdcall setLibraryVisitLevel(LoHook* h, HookContext* c)
{
    for (int i = 0; i < 19; ++i) {
        switch ( *(int*)(c->esi + 301 + (i << 3)) ) {
            case 66:  c->edx += 1; break;
            case 67:  c->edx += 1; break;
            case 68:  c->edx += 1; break;
        }
    }

    c->eax = c->edx + c->ecx * 2;
    c->return_address = 0x4A2F55;
    return NO_EXEC_DEFAULT;
}


Пробую разобрать что к чему. Почему не работает.. так вот, даже на 10м пишется что условия не выполнены
AlexSpl
Вот это работает?

Код
int __stdcall setLibraryVisitLevel(LoHook* h, HookContext* c)
{
    int artBonus = 0;
    for (int i = 0; i < 19; ++i) {
        switch ( *(int*)(c->esi + 301 + (i << 3)) ) {
            case 66:
            case 67:
            case 68:  ++artBonus;
        }
    }

    c->eax = (c->edx + artBonus) + c->ecx * 2;
    c->return_address = 0x4A2F55;
    return NO_EXEC_DEFAULT;
}


Хук на 4A2F52h.
DedMorozzz
Сделал... ошибка в приведении типа была. 1 мин, причешу код


Вот так завелось:

Код
int __stdcall setLibraryVisitLevel(LoHook* h, HookContext* c)
{
    int tmpLevelBonus = 0;
    if (*(short*)(c->esi + 85) < 10) {
        
        for (int i = 0; i < 19; ++i) {
            switch ( *(int*)(c->esi + 301 + (i << 3)) ) {
                case 66:  tmpLevelBonus += 1; break;
                case 67:  tmpLevelBonus += 1; break;
                case 68:  tmpLevelBonus += 1; break;
            }
        }
    }
    

    int currentLevel = *(int*)(c->esi + 85);
    int diplomacyLevelBonus = *(int*)(c->esi + 201 + 4) * 2;
    
    c->eax = currentLevel + tmpLevelBonus + diplomacyLevelBonus;
        
    c->return_address = 0x4A2F55;
    return NO_EXEC_DEFAULT;
}


Осталось проверить что наличие дипломатии корректно работает

PS:
да, это int diplomacyLevelBonus = *(int*)(c->esi + 201 + 4) * 2; не работает как надо. Без этого всё верно. Левел+арты считаются корректно
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Форум IP.Board © 2001-2025 IPS, Inc.