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

Замени edi на esi.

Код
char DiploLevel = *(char*)(c->esi + 205);


Хук на 4171E0h или 4171E6h - не важно.
DedMorozzz
Цитата(AlexSpl @ 18 Dec 2016, 21:00) *
Предпросмотр который? Visions?

Замени edi на esi.

Да! Так работает. Вообще не ясна логика когда что юзать... кроме как наугад менять

И как вот эту штуку сделать рабочей
Цитата
Код
_PI->WriteDword((0x417236 + 1), 3);    // при ПКМ


Ибо показывает что присоеденятся при предпросмотре (да-да, Vision), а по факту убегают/нападают
AlexSpl
Цитата
Да! Так работает. Вообще не ясна логика когда что юзать... кроме как наугад менять

Ставь брейкпоинт на 4171E6h и смотри в каком регистре хранится указатель на героя. Т.е. G[o] -> 4171E6, F2, кастуем Visions, ПКМ, срабатывает брейкпоит, анализируем код.

Цитата
И как вот эту штуку сделать рабочей

Просто убери.

Там другой патч нужен.

Попробуй так:

Код
_PI->WriteHexPatch(0x417234, "EB");  // проходим мимо бесплатного присоединения
_PI->WriteHexPatch(0x417246, "EB");  // проходим мимо платного присоединения


HiHook на sub_4170B0.
DedMorozzz
Цитата(AlexSpl @ 18 Dec 2016, 21:26) *
Цитата
Да! Так работает. Вообще не ясна логика когда что юзать... кроме как наугад менять

Ставь брейкпоинт на 4171E6h и смотри в каком регистре хранится указатель на героя. Т.е. G[o] -> 4171E6, F2, кастуем Visions, ПКМ, срабатывает брейкпоит, анализируем код.

https://sc-cdn.scaleengine.net/i/fbe739dbe6...02d39ddd287.png
Прошелся по коду. Там этих edi/esi уйма. И все подряд идут)

Цитата(AlexSpl @ 18 Dec 2016, 21:26) *
Попробуй так:

Код
_PI->WriteHexPatch(0x417234, "EB");  // проходим мимо бесплатного присоединения
_PI->WriteHexPatch(0x417246, "EB");  // проходим мимо платного присоединения

Работает smile.gif Круто

Кстати новый код что бы не дублировать логику для дипломатии, для нападения и для Вижина (20 для теста юзаю):


Код
float __stdcall getArmyValueModificator(int diplomatyLevel)
{

    float armyModificator = 1;

    if (diplomatyLevel > 0) {
        switch (diplomatyLevel) {
            case 1: {
                armyModificator = 1.1;
                break;
            }
            
            case 2: {
                armyModificator = 1.15;
                break;
            }
            
            case 3: {
                armyModificator = 20;
                break;
            }
        }
    }

    return armyModificator;

}

int __stdcall setArmyValue(LoHook* h, HookContext* c)
{
    int diplomatyLevel = (int)(*(char*)(c->edi + 201 + 4));
    float armyModificator = getArmyValueModificator(diplomatyLevel);
    (int)c->eax *= armyModificator;

    return EXEC_DEFAULT;
}


int __stdcall setArmyValuePreview(LoHook* h, HookContext* c)
{
    int diplomatyLevel = (int)(*(char*)(c->esi + 201 + 4));
    float armyModificator = getArmyValueModificator(diplomatyLevel);
    (int)c->eax *= armyModificator;

    return EXEC_DEFAULT;
}
AlexSpl
Только в этом:

Код
if (diplomatyLevel > 0)


нет смысла, т.к. дефолтный float armyModificator = 1; уже прописан. Я рекомендую всё-таки прописать его в default.

P.S. Разве не стоит цель оптимизировать. Но в этом случае вообще от свитча уходить нужно smile.gif Обычный array c проверкой границ был бы быстрее и компактнее (в коде).

Код
float armyModificator[4] = {1.00, 1.10, 1.15, 20.00};
return ( (diplomacyLevel >= 0) && (diplomacyLevel <= 3) ? armyModificator[diplomacyLevel] : ERROR_CODE );
DedMorozzz
Цитата(AlexSpl @ 18 Dec 2016, 21:43) *
Только в этом:

Код
if (diplomatyLevel > 0)


нет смысла, т.к. дефолтный float armyModificator = 1; уже прописан. Я рекомендую всё-таки прописать его в default.

хм. Не соглашусь.. Без этой проверки свич/кейс будет выполняться всегда. Даже когда дипломатия отсутствует

Цитата(AlexSpl @ 18 Dec 2016, 21:43) *
P.S. Разве не стоит цель оптимизировать. Но в этом случае вообще от свитча уходить нужно smile.gif Обычный array c проверкой границ был бы быстрее и компактнее (в коде).

Код
float armyModificator[4] = {1.00, 1.10, 1.15, 20.00};
return armyModificator[diplomacyLevel];

Тоже верно. Но если потребуется чуть расширить, кроме как модификатор изменить, тогда массив не пойдёт уже)
Но на кейсы можно будет переделать, когда потребуется. Сейчас действительно через массив сделаю

И ещё вопрос по теме дипломатии:
Где проверка можно ли сдаться стоит? Хочу сделать при наличии навыка дипломатии - возможность сдаваться мобам. С ценой 30-20-10%. В зависимости от левела навыка...
AlexSpl
Можно так:

Код
float armyModificator[4] = {1.00, 1.10, 1.15, 20.00};
return ( (diplomacyLevel >= 0) && (diplomacyLevel <= 3) ? armyModificator[diplomacyLevel] : ERROR_CODE );


Хотя у нас char, тогда ещё проще:

Код
float armyModificator[4] = {1.00, 1.10, 1.15, 20.00};
return ( diplomacyLevel < 4 ? armyModificator[diplomacyLevel] : ERROR_CODE );
DedMorozzz
Цитата(AlexSpl @ 18 Dec 2016, 22:24) *
Можно так:

Код
float armyModificator[4] = {1.00, 1.10, 1.15, 20.00};
return ( (diplomacyLevel >= 0) && (diplomacyLevel <= 3) ? armyModificator[diplomacyLevel] : ERROR_CODE );


Хотя у нас char, тогда ещё проще:

Код
float armyModificator[4] = {1.00, 1.10, 1.15, 20.00};
return ( diplomacyLevel < 4 ? armyModificator[diplomacyLevel] : ERROR_CODE );


Да, так вообще кратко вышло) хз есть ли эксепшины тут, но на эррор код - ругается. Вставил еденицу
И кстати да, Diplomacy верно, а не Diplomaty, спасибо, позаменял в коде)

И я ещё забыл разбивку по пакам сделать. Пока что при "равной" силе, с модификатором х20, когда нападаешь делит на 7 пачек.
Думаю дето в этой функе это логика sub_004A68D0. Поковыряю, отпишусь, если найду
AlexSpl
Цитата
И кстати да, Diplomacy верно, а не Diplomaty, спасибо, позаменял в коде)

Это я инстинктивно исправил. Но если идти дальше, то правильно armyModifier smile.gif

Цитата
И я ещё забыл разбивку по пакам сделать. Пока что при "равной" силе, с модификатором х20, когда нападаешь делит на 7 пачек.

Тот же LoHook, но на "альфу". Когда игра разбивает нейтралов на стеки, роляет только "альфа".
DedMorozzz
Цитата(AlexSpl @ 18 Dec 2016, 22:38) *
Цитата
И я ещё забыл разбивку по пакам сделать. Пока что при "равной" силе, с модификатором х20, когда нападаешь делит на 7 пачек.

Тот же LoHook, но на "альфу". Когда игра разбивает нейтралов на стеки, роляет только "альфа".


0x4AC35E
0x4AC361
0x427662
0x427664
0x4A6B00
0x4AC34F

Для каждого из этих адрессов, пробовал вызывать LoHook. Как для "setArmyValue" так и для "setArmyValuePreview"
Т.е.
_PI->WriteLoHook(0x4AC35E, setArmyValue);
не работает, пробую это:
_PI->WriteLoHook(0x4AC35E, setArmyValuePreview);

В общем не завелось не для какого адресса. Всегда 7 пачек.
Какой адрес правильный?
AlexSpl
Попробуйте так:

Код
int __stdcall setArmyValueSplit(LoHook* h, HookContext* c)
{
    char diplomacyLevel = *(char*)(c->ebx + 56 + 4);
    ...
    return EXEC_DEFAULT;
}
...
_PI->WriteLoHook(0x4AC35E, (void*)setArmyValueSplit);


c->ebx в данном контексте указатель на армию героя (+145). Навыки начинаются с +201. Поэтому уровень Дипломатии - это c->ebx + (201 - 145) + 4.

Ещё вариант: char diplomacyLevel = *(char*)(*(int*)(с->ebp + 8) + 201 + 4), но он более громоздкий.

Теория по разбиению на стеки здесь: http://heroescommunity.com/viewthread.php3...D=1266094#focus
DedMorozzz
Цитата(AlexSpl @ 19 Dec 2016, 22:43) *
Попробуйте так:

Код
int __stdcall setArmyValueSplit(LoHook* h, HookContext* c)
{
    char diplomacyLevel = *(char*)(c->ebx + 56 + 4);
    ...
    return EXEC_DEFAULT;
}
...
_PI->WriteLoHook(0x4AC35E, (void*)setArmyValueSplit);


c->ebx в данном контексте указатель на армию героя (+145). Навыки начинаются с +201. Поэтому уровень Дипломатии - это c->ebx + (201 - 145) + 4.

Ещё вариант: char diplomacyLevel = *(char*)(*(int*)(с->ebp + 8) + 201 + 4), но он более громоздкий.

Теория по разбиению на стеки здесь: http://heroescommunity.com/viewthread.php3...D=1266094#focus

вылетает. прогнал по всем адресам(которые выше кидал) - или вылетает или не работает

PS: а вот это работает!
Код
int diplomacyLevel = (int)(*(char*)(c->ebx + 56 + 4));

Код
_PI->WriteLoHook(0x4AC35E, setArmyValueSplit);
AlexSpl
Оба варианта?
DedMorozzz
Цитата(AlexSpl @ 20 Dec 2016, 00:19) *
Оба варианта?

отредачил
AlexSpl
Цитата
int diplomacyLevel = (int)(*(char*)(c->ebx + 56 + 4));

Не нужет тут int. Просто char diplomacyLevel = *(char*)(c->ebx + 56 + 4);

Т.е. не работает вот это: char diplomacyLevel = *(char*)(*(int*)(с->ebp + 8) + 201 + 4)?

DedMorozzz
Цитата(AlexSpl @ 20 Dec 2016, 00:27) *
Т.е. не работает вот это: char diplomacyLevel = *(char*)(*(int*)(с->ebp + 8) + 201 + 4)?

тут такая ошибка:

1>.\dllmain.cpp(268) : error C2065: 'с' : undeclared identifier
1>.\dllmain.cpp(268) : error C2227: left of '->ebp' must point to class/struct/union/generic type
1> type is ''unknown-type''
1>.\dllmain.cpp(270) : warning C4244: '*=' : conversion from 'float' to 'int', possible loss of data


Цитата(AlexSpl @ 20 Dec 2016, 00:27) *
Цитата
int diplomacyLevel = (int)(*(char*)(c->ebx + 56 + 4));

Не нужет тут int. Просто char diplomacyLevel = *(char*)(c->ebx + 56 + 4);

Да, так тоже работает. А чего инт не нужен, я так понимаю что уровень навыка это не символ, а число, т.е. инт
AlexSpl
Потому что
Цитата
_byte_ second_skill[28]; // +201

char - это _byte_

char - это не символ. Просто символы ASCII умещаются в 1 байт. И решили так назвать.

В ассемблере всё проще, нет signed и unsigned, char и прочих "высокоуровневых" типов, есть
db - байт, dw - слово (два байта в архитектуре x86), dd - двойное слово (четыре байта) и т.д. Даже float - тот же dd. Типы придуманы для контроля типов smile.gif Чтобы уменьшить вероятность ошибки при написании кода человеком.

* * *

Цитата
1>.\dllmain.cpp(268) : error C2065: 'с' : undeclared identifier
1>.\dllmain.cpp(268) : error C2227: left of '->ebp' must point to class/struct/union/generic type
1> type is ''unknown-type''
1>.\dllmain.cpp(270) : warning C4244: '*=' : conversion from 'float' to 'int', possible loss of data

Warning понятно откуда. Можете использовать floor() здесь:
Код
(int)c->eax *= Mod;

Код
(int)c->eax = floor((int)c->eax * Mod);

Но не уверен, что floor() быстрее.

Но остальное интересно.
Цитата
1>.\dllmain.cpp(268) : error C2065: 'с' : undeclared identifier

c точно в английской раскладке набрали?

Если да, попробуйте просто присвоить:

Код
int Value = (int)c->ebp;

будет работать?

DedMorozzz
Цитата(AlexSpl @ 20 Dec 2016, 00:54) *
Потому что
Цитата
_byte_ second_skill[28]; // +201

char - это _byte_

char - это не символ. Просто символы ASCII умещаются в 1 байт. И решили так назвать.

В ассемблере всё проще, нет signed и unsigned, char и прочих "высокоуровневых" типов, есть
db - байт, dw - слово (два байта в архитектуре x86), dd - двойное слово (четыре байта) и т.д. Даже float - тот же dd. Типы придуманы для контроля типов smile.gif Чтобы уменьшить вероятность ошибки при написании кода человеком.

хм... я ж С++ использую, он то высокоуровневый

Цитата(AlexSpl @ 20 Dec 2016, 00:54) *
Но остальное интересно.
Цитата
1>.\dllmain.cpp(268) : error C2065: 'с' : undeclared identifier

c точно в английской раскладке набрали?


Вот из этого поста http://forum.df2.ru/index.php?s=&showt...st&p=734319
взял код:

И там действительно кириллица затесалась. Заменив - завелось

Цитата(AlexSpl @ 20 Dec 2016, 00:54) *

Инт8 это кол-во байт, я правильно понимаю?
AlexSpl
Цитата
И там действительно кириллица затесалась. Заменив - завелось

Тогда я виноват smile.gif

Цитата
Инт8 это кол-во байт, я правильно понимаю?

Кол-во бит: 8, 16, 32 или 64. Это просто синонимы стандартных типов.

Цитата
The types __int8, __int16, and __int32 are synonyms for the ANSI types that have the same size, and are useful for writing portable code that behaves identically across multiple platforms.
DedMorozzz
Такой вопрос:
я хочу задейстовать арты дипломатии. Что бы не были бесполезным мусором. Что бы арты так же давали бонус к силе армии. Нашел такой код (в подсчёте навыка дипломатии)
Код
.text:004E4857 loc_004E4857:                                              ; CODE XREF: GetDiplomacyPower+73j
.text:004E4857                     cmp     dword ptr [eax], 66            ; Statesman's Medal
.text:004E485A                     jz      short loc_004E488D             ; Jump if Zero (ZF=1)
.text:004E485C                     inc     ecx                            ; Increment by 1
.text:004E485D                     add     eax, 8                         ; Add
.text:004E4860                     cmp     ecx, 13h                       ; Compare Two Operands
.text:004E4863                     jl      short loc_004E4857             ; Jump if Less (SF!=OF)
.text:004E4865                     mov     eax, ArtSettingsPo
.text:004E486A                     mov     eax, [eax+858h]
.text:004E4870                     cmp     eax, 0FFFFFFFFh                ; Compare Two Operands
.text:004E4873                     jz      short loc_004E4899             ; Jump if Zero (ZF=1)
.text:004E4875                     mov     edx, ComboArtSetUpPo
.text:004E487B                     lea     ecx, [eax+eax*2]               ; Load Effective Address
.text:004E487E                     mov     eax, [edx+ecx*8]
.text:004E4881                     mov     ecx, edi
.text:004E4883                     push    eax
.text:004E4884                     call    HeroHasArt                     ; Call Procedure
.text:004E4889                     test    al, al                         ; Logical Compare
.text:004E488B                     jz      short loc_004E4899             ; Jump if Zero (ZF=1)


Как я понимаю это медаль дипломата. Как его задейстовать в логике? Что бы давал +5% к силе армии
AlexSpl
Итак, у нас есть функция подсчёта "альфы", которая в цикле проходит по всем слотам армии героя. Единственное правильное решение - добавить в эту функцию код, который бы проходил также и по всем артам, висящим на "кукле" героя, и модифицировал бы "альфу" при наличии того или иного арта.

Так как адрес героя внутри функции известен, то и адрес массива артов - тоже. Так что не должно быть сложно реализовать. Можно обойтись LoHook'ом.
DedMorozzz
Алгорит сам ясен, в нём сложностей нету. Как я себе это вижу:
У нас есть метод (HeroHasArt), судя по всему котороый проверяет наличие арта у героя и возвращает 0/1 скорее всего, сомневаюсь что булеан
Соотв в своей ф-и возврата модификатора, необходимо добавить условие арта. Который ещё дополнительно будет усиливаться надетыми предметами (естественно только указаными)

Что тут для меня не ясно:
1. как передать идентификатор на арт который надо проверить в ф-ю
2. как получить ответ от ф-ии

Остальное - просто smile.gif
AlexSpl
Тут нет смысла вызывать эту функцию. Просто пройтись по _Artifact_ doll_art[19]; // +301

LoHook на 44A985h. Дальше простой цикл for (;;). Тут необходимо учесть структуру _Artifact_. Если я правильно помню - это пары dd, второе число (int) в паре - ID арта. Первое - без понятия, возможно, для "замков". c->eax - сила армии.

if ( *(int*)(c->reg + 301 + i) == DIPLOMACY_ART_ID ) c->eax *= diplomacyArtPowerMod[DIPLOMACY_ART_ID];

где i проходит по всем артам на "кукле".
AlexSpl
c->edx в данном контексте - указатель на кол-во существ в первом слоте, т.е. адрес "куклы" будет такой: с->edx + 301 - 145 - 7*4 = с->edx + 128.

Поэтому для медали (ID = 66) следующий код должен работать (Mod - модификатор):

Код
for (int i = 0; i < 19; ++i) {
    if ( *(int*)(c->edx + 128 + (i << 3) + 4) == 66 ) c->eax *= Mod;
}

(i << 3) + 4 = i * 8 + 4 - оффсет ID арта.

UPD: Поправил адрес "куклы" и приоритет операций.
feanor
Цитата
Первое - без понятия, возможно, для "замков".
Параметр конкретного арта, используется для свитков.

Зачем вы используете эти страшные конструкции со смещениями, если у вас есть описание структуры данных?
((_Hero_*)c->edx)->arts[i].id или как-то так примерно.
AlexSpl
Цитата
((_Hero_*)c->edx)->arts[i].id или как-то так примерно.

У меня есть только структура. Без описания типов конкретных полей (_Army_, _Artifact_, _HStringF_ и т.п.).
DedMorozzz
Цитата(AlexSpl @ 20 Dec 2016, 21:34) *
c->edx в данном контексте - указатель на кол-во существ в первом слоте, т.е. адрес "куклы" будет такой: с->edx + 301 - 145 - 7*4 = с->edx + 128.

Поэтому для медали (ID = 66) следующий код должен работать (Mod - модификатор):

Код
for (int i = 0; i < 19; ++i) {
    if ( *(int*)(c->edx + 128 + (i << 3) + 4) == 66 ) c->eax *= Mod;
}

(i << 3) + 4 = i * 8 + 4 - оффсет ID арта.

UPD: Поправил адрес "куклы" и приоритет операций.

Как из адресса указателя на кол-во существ в 1м слоте получилась конструкция "301-145-7*4"? Вообще не понятно ):
И где глянуть айдишники артов?

Ну и не работает этот код:
Код
if ( *(int*)(c->edx + 128 + (i << 3) + 4) == 66 )

и этот тоже, соответственно:
Код
if ( *(int*)(c->edx + 128 + i * 8 + 4) == 66 )

Вылетает при нападении. И не важно есть арты или нету
AlexSpl
А так?
Код
if ( *(int*)(c->edx + 128 + (i << 3) + 4) == 66 ) (int)c->eax *= Mod;
DedMorozzz
Цитата(AlexSpl @ 21 Dec 2016, 22:10) *
А так?
Код
if ( *(int*)(c->edx + 128 + (i << 3) + 4) == 66 ) (int)c->eax *= Mod;

Так это то же самое.
Вот полный код:
Код
float __stdcall getArmyValueModificator(int diplomacyLevel, HookContext* c)
{
    float armyModificator[4] = {1.00, 1.10, 1.15, 20.00};
    float currentModifier = ( (diplomacyLevel >= 0) && (diplomacyLevel <= 3) ? armyModificator[diplomacyLevel] : 1 );

    for (int i = 0; i < 19; ++i) {
        if ( *(int*)(c->edx + 128 + (i << 3) + 4) == 66 ) {
            //currentModifier = currentModifier + 20;
            currentModifier = 30;
        }
    }
    
    return currentModifier;
}

т.е. при наличии арта делает модификатор = 30
AlexSpl
Закомментируйте вот это:

Код
/* for (int i = 0; i < 19; ++i) {
        if ( *(int*)(c->edx + 128 + (i << 3) + 4) == 66 ) {
            //currentModifier = currentModifier + 20;
            currentModifier = 30;
        }
    } */


И возвратите 30: return 30; Работает?
DedMorozzz
Цитата(AlexSpl @ 21 Dec 2016, 22:19) *
Закомментируйте вот это:

Код
/* for (int i = 0; i < 19; ++i) {
        if ( *(int*)(c->edx + 128 + (i << 3) + 4) == 66 ) {
            //currentModifier = currentModifier + 20;
            currentModifier = 30;
        }
    } */


И возвратите 30: return 30; Работает?

Даже если просто иф закоментить - 30ка возвращается (в смысле закоментить линию с ифом и линию с закрывающей скобкой)
А вариант феанора - хз как применить smile.gif
AlexSpl
Скорее всего, хук неправильный, см.:

Код
int __stdcall setArmyValue(LoHook* h, HookContext* c)


Не нужно ничего возвращать, просто return EXEC_DEFAULT; Код должен быть таким, как я написал.

Т.е.

Код
int __stdcall setArmyValueArt(LoHook* h, HookContext* c)
{
    for (int i = 0; i < 19; ++i) {
        if ( *(int*)(c->edx + 128 + (i << 3) + 4) == 66 ) c->eax *= Mod;
    }
    
    return EXEC_DEFAULT;
}

// Mod =, например, 30.
...
_PI->WriteLoHook(0x44A985, (void*)setArmyValueArt);


Возвращать не нужно, т.к. LoHook - это тот же inline-патч, считай. Бонусы от предыдущих хуков будут работать нормально.

Неправильно делать хук вспомогательной функцией. Хук - это патч.

UPD Сорри, адрес по инерции скопировал. Исправил на правильный.

* * *
Короче, программа выполняется последовательно. Вы поставили несколько хуков. Сначала работает первый, потом второй и т.д. Они независимы, это разные функции и у них разный контекст.
DedMorozzz
не, не работает. Эффекта никакого (на герое одет амулет на шее, и флаг на плечах). А по идеи должно на меньше пачек при нападении делить, если я верно понимаю
а для этого адреса _PI->WriteLoHook(0x4A7441, setArmyValueArt); -- вылетает

Для 0x44A985 то же самое. Эффекта нет. Сделал усиление в 2 раза и в 30 раз, не меняется ничего

Но главная идея у меня была главную ф-ю расчёта изменить, а не новый хук делать. Так было бы правильнее наверное
AlexSpl
Попробуйте отдельный хук в посте выше. А лучше скиньте Ваш код под спойлер.
DedMorozzz
Цитата(AlexSpl @ 21 Dec 2016, 23:06) *
Попробуйте отдельный хук в посте выше. А лучше скиньте Ваш код под спойлер.

Код
int __stdcall setArmyValueArt(LoHook* h, HookContext* c)
{
    for (int i = 0; i < 19; ++i) {
        if ( *(int*)(c->edx + 128 + (i << 3) + 4) == 66 ) {
            c->eax *= 30;
        }
    }
    
    return EXEC_DEFAULT;
}

...
_PI->WriteLoHook(0x44A985, setArmyValueArt);

AlexSpl
Цитата
Эффекта никакого (на герое одет амулет на шее, и флаг на плечах). А по идеи должно на меньше пачек при нападении делить, если я верно понимаю

Так код выше (Ваш пост) приводит к вылету или не даёт эффекта?

Цитата
А по идеи должно на меньше пачек при нападении делить, если я верно понимаю

Для некоторых клеток 3 стека - минимум. Меньше не получишь.
DedMorozzz
Цитата(AlexSpl @ 21 Dec 2016, 23:25) *
Цитата
Эффекта никакого (на герое одет амулет на шее, и флаг на плечах). А по идеи должно на меньше пачек при нападении делить, если я верно понимаю

Так код выше (Ваш пост) приводит к вылету или не даёт эффекта?

Не вылетает, просто не влияет не на что
AlexSpl
Попробуйте напасть на сильный отряд стандартной армией и выставить модификатор в 100000.

Не этот ли у Вас случай:
Цитата
3 и более - 1 отряд. На самом деле, 1 отряд может получиться только из 2 отрядов с вероятностью 20%. Т.е. какой бы сильной ни была Ваша армия, всегда найдутся нейтралы, которые разделятся на 2 и даже 3 стека. Пример клетки, на которой нейтралы делятся на 3 отряда, даже если у Вашей армии 100-кратное превосходство, - 31:28:1. Подробнее здесь. В этой же теме можно найти и условия появления грейженого стека.
DedMorozzz
Цитата(AlexSpl @ 21 Dec 2016, 23:31) *
Попробуйте напасть на сильный отряд стандартной армией и выставить модификатор в 100000.

Не этот ли у Вас случай:
Цитата
3 и более - 1 отряд. На самом деле, 1 отряд может получиться только из 2 отрядов с вероятностью 20%. Т.е. какой бы сильной ни была Ваша армия, всегда найдутся нейтралы, которые разделятся на 2 и даже 3 стека. Пример клетки, на которой нейтралы делятся на 3 отряда, даже если у Вашей армии 100-кратное превосходство, - 31:28:1. Подробнее здесь. В этой же теме можно найти и условия появления грейженого стека.


на самом деле ставлю без цикла в этой же ф-ии - работает всё.
В цикле умножаю на 30 каждый раз, 20 раз в сумме, то нападают все и делит на 7 пачек. Превышаю лимит походу)
т.е. именно логика проверки арта не отрабатывает. Не попадаем в нужное условие
AlexSpl
Не должно так быть, условие срабатывает, если ID арта = 66. У Вас есть способ выводить результат каждой итерации куда-нибудь? Т.е.

Код
for (int i = 0; i < 19; ++i) {
    if ( *(int*)(c->edx + 128 + (i << 3) + 4) == 66 ) {
        std::cout << "Сработало. i = " << i;
        c->eax *= 30;
    }
}
DedMorozzz
а куда вывод должен произойти?
И ругается:
1>.\dllmain.cpp(277) : error C2039: 'cout' : is not a member of 'std'
1>.\dllmain.cpp(277) : error C2065: 'cout' : undeclared identifier

Попробовал такой код:
Код
int __stdcall setArmyValueArt(LoHook* h, HookContext* c)
{
    for (int i = 0; i < 19; ++i) {
        if ( *(int*)(c->edx + 128 + (i << 3) + 4) > 0 ) {
            c->eax *= 30;
            break;
        }
    }
    
    return EXEC_DEFAULT;
}


Всё равно. Не заходим
AlexSpl
Следующий код имеет эффект? Т.е. сначала хилой армией нападаем на отряд. Смотрим, на сколько стеков он разделился. Потом надеваем медаль дипломата и снова нападаем.

Код
if ( *(int*)(c->edx + 128 + 20) == 66 ) {
    c->eax *= 100;
}


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

Код
if ( *(int*)(c->edx + 128 + 20) == 66 ) {
    c->eax *= 100;
}

Да, есть спец сейв. В котором 1 арх, и джебус с подземкой. ГО на поверхности циклопы, в поздемке - новые ящеры причала, с щитами
Так вот с рейтом х20 мощи армии циклопы убегают (когда всё же нападаю 3 пака). Ящеры нападают всегда (3 пака тоже)

Вот если задать х30 в функе с артом без условия, тогда и ящеры убегают. А при нападении и цикломы и ящеры делятся на 2 пака

В условие не попадаем даже если делать просто > 0 , вместо == 66. Как в коде выше

PS: есть подозрение что этот код или 0 возвращает или пустоту --- *(int*)(c->edx + 128 + (i << 3) + 4)
AlexSpl
Цитата
Если Вы нападаете героем с Дипломатией, учтите, что бонус накапливается. Т.е. наличие медали умножило силу армии на модификатор, а потом ещё навык Дипломатии это значение увеличил.

Вот это проверяли?
DedMorozzz
Цитата(AlexSpl @ 22 Dec 2016, 00:39) *
Цитата
Если Вы нападаете героем с Дипломатией, учтите, что бонус накапливается. Т.е. наличие медали умножило силу армии на модификатор, а потом ещё навык Дипломатии это значение увеличил.

Вот это проверяли?

да, так и есть. ну и по коду так и должно быть
В функе увеличения модификатора артами, сделал увеличение на 1.1 - ящеры убегают тоже. Т.е. всё работает корректно
Только что проверил if ( *(int*)(c->edx + 128 + (i << 3) + 4) == 0 ) { --- всё равно не заходит
AlexSpl
Похоже, реально адрес арта неправильно считает ( Разбираюсь.

А так попробуйте:

Код
int __stdcall setArmyValueArt(LoHook* h, HookContext* c)
{
    for (int i = 0; i < 19; ++i) {
        if ( *(int*)(c->edx + 128 + (i << 3)) == 66 ) c->eax *= 30;
    }
    
    return EXEC_DEFAULT;
}


* * *

Не могу понять, я туплю или оффсеты в комментах структуры неправильные.

UPD Всё-таки туплю (см. абзац в конце этого поста). Правильный код такой:

Код
for (int i = 0; i < 19; ++i) {
    if ( *(int*)(c->edx + 128 + (i << 3)) == 66 ) c->eax *= Mod;
}

301 же - это оффсет идентификатора первого артефакта (шлема).

Ещё вот тут оффсеты в комментах неправильные:
Код
_word_ aim_z; // +61
_int16_ last_magic_level; // +61. Последний из уровней, на переходе на который предложили магию стихии.
DedMorozzz
да, так работает! Спасибо smile.gif

Код
float __stdcall getArmyValueModificator(int diplomacyLevel, HookContext* c)
{
    float armyModificator[4] = {1.00, 1.10, 1.15, 20.00};
    float currentModifier = ( (diplomacyLevel >= 0) && (diplomacyLevel <= 3) ? armyModificator[diplomacyLevel] : 1 );

    for (int i = 0; i < 19; ++i) {
        if ( *(int*)(c->edx + 124 + (i << 3) + 4) == 66 ) {
            //(float)currentModifier += 0.3;
            float newVar = 12;
        }
    }

    return currentModifier;
}


Перенёс увеличение модификатора в одно место. И тут с Си++ затык. Не работает такой код. Если меняю модификатор - вылетает
Просто переменую левую описываю - всё ок. Т.е в условие попадаю, вроде всё ок. Как я вижу - проблема только со сложением
Как сложить тут? smile.gif
AlexSpl
Не нужно передавать весь контекст. Пусть функция, которая считает модификатор (getArmyValueModificator(), я переименовал её в getArtModifier()), получает в качестве аргументов только массив артефактов.

Код
float getArtModifier(int art[]) {
    ...
    for (int i = 0; i < 19; ++i) {
        if ( art[i] == 66 ) {
            artModifier = ...;
        }
    }

    return artModifier;
}


Т.е. есть функция int __stdcall setArmyValueArt(LoHook* h, HookContext* c). В ней читаем арты:

art[i] = *(int*)(c->edx + 124 + (i << 3) + 4);

и вызываем getArtModifier(art) для получения модификатора. Всё, что имеем от этого, - усложнение логики и два цикла вместо одного.

Ну вот, при редактировании пропал текст. Короче, смысл был такой: функция подсчёта альфы вызывается не единожды в коде и не только для нашего героя, но хук срабатывает каждый раз. Поэтому аккумулировать модификатор бессмысленно.
DedMorozzz
Код
float __stdcall getArtArmyValueModificator(int art[])
{
    for (int i = 0; i < 19; ++i) {
        if ( art[i] == 66 ) {
            return 30;
        }
    }

    return 0;
}

float __stdcall getArmyValueModificator(int diplomacyLevel, HookContext* c)
{
    float armyModificator[4] = {1.00, 1.10, 1.15, 20.00};
    float currentModifier = ( (diplomacyLevel >= 0) && (diplomacyLevel <= 3) ? armyModificator[diplomacyLevel] : 1 );
    
    int art[19];
    for (int i = 0; i < 19; ++i) {
        art[i] = *(int*)(c->edx + 124 + (i << 3) + 4);
    }
    float currentArtModifier = getArtArmyValueModificator(art);

    return currentArtModifier + currentModifier;
}

падает так..

Но всё равно кажется херню делаю) Дважды цикл, когда можно единожды в 1м месте
Чего не передать hookContent в ф-ю подсчёта модификатора для арта. ИМХО логичнее будет
AlexSpl
Не, так не нужно )

Попробую объяснить. Есть код:

0: a = a + 1;
1: b = a + 2;
2: c = b + 3;

Вы ставите хук на 1 (это адрес такой) и пишете свой код, например:

if ( a == 4) a = 100;

Нормальное выполнение программы при a = 3:

0: a = a + 1; // a = 4
1: b = a + 2; // b = 6
2: c = b + 3; // c = 9

С хуком:

0: a = a + 1; // a = 4

*хук*
if ( a == 4) a = 100; // a = 100
*хук*

1: b = a + 2; // b = 102
2: c = b + 3; // c = 105
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Форум IP.Board © 2001-2025 IPS, Inc.