Wake of Gods Forum | Форум Во Имя Богов
Решение багов ERA/WOG - Printable Version

+- Wake of Gods Forum | Форум Во Имя Богов (http://wforum.heroes35.net)
+-- Forum: Герои Меча и Магии 3.5 WoG/ERA (/forumdisplay.php?fid=99)
+--- Forum: Библиотека по моддингу (/forumdisplay.php?fid=186)
+--- Thread: Решение багов ERA/WOG (/showthread.php?tid=5244)


Решение багов ERA/WOG - igrik - 21.09.2011 22:09

Данная тема предназначена только для выкладывания кода лечения багов (непосредственно касающихся Вога или Эры) на программном уровне, для того чтобы Berserker мог их включать в состав era.dll
Любые сообщения, не содержащие указание бага совместно с его решением на Ассамблере, Delphi или С++ будут безжалостно уничтожаться.


Я буду данные фиксы включать в плагин game bug fixes extended.dll
Исходник можно увидеть тут: github.com
Список фиксов (Click to View)



Решение багов ERA/WOG - Sav - 06.07.2012 18:55

Я всё-таки разобрался со шрифтами.
Вот патч:
PHP Code:
// Исправляем обработку отрицательного отступа шрифта (ошибку приведения типов).
_PI->WriteByte(0x4B5349 10xB6); // (mov)zx
_PI->WriteByte(0x4B53E5 10xB6); // (mov)zx 

Ошибка эта была не в алгоритме, а в приведении типов, поэтому её не видно в выложенном мной декомпилированном коде.

Вот код, содержащий ошибку:
Code:
.text:004B5335 ; 109:             if ( *((_DWORD *)&this_v11->v_table + 3 * (symbol_v21 + 5)) < 0 )// fnt->char_sizes[symbol].width
.text:004B5335                 mov     edx, eax
.text:004B5337                 and     edx, 0FFh
.text:004B533D                 add     edx, 5
.text:004B5340                 lea     edx, [edx+edx*2]
.text:004B5343                 cmp     dword ptr [ebx+edx*4], 0
.text:004B5347
.text:004B5347 loc_4B5347:                             ; DATA XREF: 0138630Ao
.text:004B5347                 jge     short loc_4B5357
.text:004B5349 ; 110:               symbols_width_v19 = -*((_DWORD *)&this_v11->v_table + 3 * ((char)symbol_v21 + 5));// fnt->char_sizes[symbol].width
.text:004B5349                 movsx   ecx, al
.text:004B534C
.text:004B534C loc_4B534C:                             ; DATA XREF: 018ECE8Co
.text:004B534C                 add     ecx, 5
.text:004B534F                 lea     ecx, [ecx+ecx*2]
.text:004B5352                 mov     ecx, [ebx+ecx*4]
.text:004B5355                 neg     ecx
Тут левый отступ первого символа строки сравнивается с 0, а потом, если он отрицательный, ecx устанавливается в -него (чтобы потом, когда он в цикле прибавится, скомпенсировать его, чтобы таким образом игнорировать отрицательный отступ первого символа строки).
Проблема в строке ".text:004B5349 movsx ecx, al". Ведь если символ русский, al будет отрицательной и в ecx запишется отрицательное число, которое потом будет использоваться как индекс. В результате, вместо отступа будет взят мусор (например, 0xBAADF00D), из-за которого строка уползёт чёрт знает куда. Ну или там может лежать 0 и недочёт не будет заметен.
Такая же вещь с правым отступом последнего символа строки.

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


RE: ERA II - Sav - 11.07.2012 20:36

Исправление одного из вылетов при загрузке карты / наступлении новой недели.
PHP Code:
_PI->WriteDword(0x4CCC43IntAt(0x4CCC43) - 4); 

Этот вылет связан с содовским багом (возможно, только 3.2) генерации слуха в таверне. Там берётся случайное число от 1 до 256 и по нему как по индексу берётся значение (адрес строки слуха) из 256-элементного массива. Соответственно, первый слух никогда не берётся, зато иногда берётся элемент "за последним", он равен 0, и происходит вылет.
Раньше мне казалось, что в Воге что-то намутили с таблицей слухов и там этого вылета нет, но теперь я поймал его в Эре.

Этот баг фактически обеспечивал 0.4% шанса вылететь каждую неделю. Sm


RE: ERA II - MOP - 20.09.2012 21:27

Исправление бага отображения русских букв в диалоге опыта существ (некоторые способности - чёрточки вместо слов):

Code:
722792 B6



RE: ERA II - MOP - 28.09.2012 07:27

деактивация вог-проверок, вызывающих потерю опыта последнего отряда (exe-адреса):

Code:
2F3C55 EB0C
2F3BEC EB0C
2F42E6 EB0C
2F4356 EB0C

Исходники WoG, Monsters.cpp - поиск по фразе "хочет перенести последний стэк - не получится". Sm


RE: ERA II - Sav - 14.04.2013 20:33

Некоторое время назад я исправлял вылеты, связанные со слухами в таверне. Сейчас я подробно исследовал тот код и понял, что прошлый мой фикс был не совсем правильным: вылет-то он исправлял, но не исправлял нарушенный механизм генерации слухов, делающий некоторые из них недоступными, а некоторые генерирующимися слишком часто, особенно через большое количество недель после начала игры.
Вместо
Code:
_PI->WriteDword(0x4CCC43, 0x696DE8);
Следует вставить
PHP Code:
_PI->WriteHexPatch(0x4CCC40 2"8D"); // mov ..., ...[ecx*4] 



RE: ERA Scripts 1.15 Rus - gamecreator - 07.04.2015 02:19

(07.04.2015 00:51)Elzivir Wrote:  при нападении героя AI на человека в режиме одиночной игры и при попытке последнего путем нажатия ПКМ на кнопку Defend (оборона) поменять тип атаки лучников/командира со стрельбы на рукопашную, выдается сообщение: "This feature does not work in Human vs Human network baced battle", т.е. если стрелки никем не заблокированы им остается лишь дистанционная атака, а переход в режим рукопашного боя невозможен, даже если вражеский юнит находится в пределах досягаемости. Причем, если на стороне атакующего героя будет человек, то данной проблемы не возникает

(07.04.2015 01:16)Berserker Wrote:  Может быть кто-нибудь напишет патч, отключающий проверку.

Лучше. Меняем проверку флага 997 на 998 (патч для памяти):
Code:
762604 С5



RE: Тема модераторов - gamecreator - 31.05.2016 02:48

Ok, I found the problem. There is a fatal flaw in the hint system, making so that no hint can be set twice. I can imagine how ZVS / sergroj / whoever else made WoG T1 managed to compile this incorrect code. A good example of why one shouldn't use outdated compilers they don't understand.
Anyhow, here is the fix (hopefully without errors, because I didn't test it):
Code:
72982C FC
729835 FC
72983B FC
729843 FC
729859 FC
72987B FC
72988F FC



Решение багов ERA/WOG - igrik - 01.02.2019 15:40

Решение бага Вога, когда в бою накладывается опыт через EA:E и атака, защита, уроны, скорость, боезапасы и т.п. заново пересчитываются.
Из-за этого теряются бонусы наложенных заклинаний (например бонус скорости от ускорения)

Сама функция пересчета параметров стека из исходников WoG:
0x726DE4 тут вызывается функция установки опыта в бою (и этот баг) через EA:E = CrExpBon::Apply(MonPos(Type)); (стр.4886)
int CrExpBon::Apply(Byte *Mon){ // настройка бонусов на поле боя один раз (стр 1495 crexpo.cpp)

Code:
int __stdcall ERM_Fix_EA_E(HiHook* hook, _BattleStack_* stack )
{
    int ret = 0;
    _int32_ spell_duration[81]; // для сохранения длительности заклинаний
    _int32_ spells_power[81];   // для сохранения силы действия заклинания

    if (stack) {
        for (int i=0; i<80; i++) {
            spell_duration[i] = stack->active_spell_duration[i];
            spells_power[i] = stack->active_spells_power[i];

            if (spell_duration[i] > 0 ) // если заклинание наложено на стек, то сбрасываем его эффект
                CALL_2(int, __thiscall, 0x444230, stack, i); // ResetSpellFromStack 0x444230
        }
    }

    ret = CALL_1(int, __cdecl, hook->GetDefaultFunc(), stack);

    for (int i=0; i<80; i++) {
        if (spell_duration[i] > 0) { // если заклинание ранее было наложено, то восстанавливаем его
            CALL_5(int, __thiscall, 0x444610, stack, i, spell_duration[i], spells_power[i], 0); // ApplySpell 0x444610
        }
    }

    return ret;
}
/////////////////////////////////////////////////////////////
_PI->WriteHiHook(0x726DE4, CALL_, EXTENDED_, CDECL_, ERM_Fix_EA_E);



RE: Решение багов ERA/WOG - igrik - 01.02.2019 17:21

Решение багов ИИ, когда тот может (© RoseKavalier):
1. Использовать заклинание полёт когда у него нет Крыльев Ангела или Полёта
2. Использовать заклинания на Проклятой Земле, которые на ней запрещены
Code:
int __stdcall AI_waterwalk_fly(LoHook *h, HookContext *c)
{
    if (c->eax == 0) // no angel wings
    {
        _Hero_ *hero = (_Hero_ *)(c->esi);
        if (hero->spell[6] == 0 && hero->spell_level[6] == 0) // this AI hero does not have the means to cast fly (id = 6)
        {
            if (hero->spell[7] != 0 || hero->spell_level[7] != 0) // this AI hero has access to waterwalk (id = 7)
            {
                if (hero->waterwalk_cast == -1) // waterwalk is not cast ~ waterwalk field is *(&hero + 0x116) (see 0x4E6040 Cast_waterwalk function)
                    c->return_address = 0x430231; // try to cast waterwalk instead (code checks for Boots of Levitation first...)
                else
                    c->return_address = 0x430540; // skip procedure
                return NO_EXEC_DEFAULT;
            }
        }
    }
    return EXEC_DEFAULT;
}

int __stdcall AI_TP_cursed_check(LoHook *h, HookContext *c)
{
    _Hero_ *hero = (_Hero_*)c->esi;
    if (hero->GetSpecialTerrain() == 0x15) // 0x15 = cursed ground, 0x4E5130: __thiscall GetSpecialTerrain()
    {
        c->return_address = 0x56B6F4;
        return NO_EXEC_DEFAULT;
    }
    return EXEC_DEFAULT;
}

_PI->WriteLoHook(0x56B344, AI_TP_cursed_check);
_PI->WriteLoHook(0x43020E, AI_waterwalk_fly);


Решение бага (еще с SoD) исчезновения улучшенного стека при битве с даунгрейдом нейтралов
Code:
_int_ __stdcall Y_FixBagCreatureGredeOfNeutrals(HiHook* hook, _Army_* army, _int_ creature_id)
{
    _int_ count = 0;
    _int_ i = 0;
    _int_ crGrade_id = GetCreatureGrade(creature_id);
    do {
        if (army->type[i] == creature_id || army->type[i] == crGrade_id) {
            count += army->count[i];
        }
        i++;
    } while ( i<7 );

    return count;
}

//////////////////////////////////////////////////////////////

_PI->WriteHiHook(0x4AC5F5, CALL_, EXTENDED_, THISCALL_, Y_FixBagCreatureGredeOfNeutrals);



RE: Решение багов ERA/WOG - igrik - 01.02.2019 17:27

Исправление бага с исчезновением стартового героя при переигрывании
Code:
_PI->WriteByte(0x5029C0, 0xEB);

Исправление бага палатки, когда на её ходу невозможно убежать или сделать другие действия
Code:
_PI->WriteByte(0x75C82C, 0xEB);

Исправление недочета WoGа на расширение свитча хинтов колдовства для описаний командиров и монстров с номером больше 134
Code:
_PI->WriteHexPatch(0x492A56, "81FF B7000000 90 7747");
_PI->WriteDword(0x492A63, *(_int_*)0x44825F);

Исправление одного из багов Астрального духа
Т.е. убираем WoG сообщение, которое вызывает неизвестную ошибку в малочисленном ряде случаев
Code:
_PI->WriteHexPatch(0x76D4B3, "EB17");

Исправление бага блока командира, когда защита падала из-за флага "в защите"
Code:
_PI->WriteCodePatch(0x76E7D7, "%n", 24); // 15 nop
_PI->WriteCodePatch(0x76E80B, "%n", 13); // 13 nop
_PI->WriteHexPatch(0x76E7D7, "8B4D 08 C601 01 C641 02 04");

Исправление ошибки ERM (видимо опечатки Славы ZVS) в командре IF:N1.
Теперь команда работает со всеми локальными, глобальными и отрицательными переменными z, а не только с z1
Code:
_PI->WriteByte(0x749093, 0xB0);
_PI->WriteByte(0x74909C, 0xB0);
_PI->WriteByte(0x7490B0, 0xB0);
_PI->WriteByte(0x7490B6, 0xB0);
_PI->WriteByte(0x7490CD, 0xB0);

Меняем месторасположение кнопки Сказочного Дракона
Code:
// исправить координаты кнопки
_PI->WriteDword(0x5F3D9F, 235); // подложка поз.Y
_PI->WriteByte(0x5F3DA4, 21);    // подложка поз.X
_PI->WriteDword(0x5F3DF5, 235); // кнопка   поз.Y
_PI->WriteByte(0x5F3DFA, 21);    // кнопка   поз.X



RE: Решение багов ERA/WOG - igrik - 01.02.2019 17:40

Убираем показ (предварительного расчета в строке состояния битвы) увеличенного урона от кавалерийского бонуса, если существо летает.
Потому что в оригинале бонус кавалерии не действует (при нанесении фактического урона) у летающих существ.
Code:
// не считать кавалерийский бонус при полете
_int_ __stdcall Y_AntiKavalierAndFly(LoHook* h, HookContext* c)
{
    if ( *(_dword_*)(c->ebx +132) >> 1 & 1 ) { // проверить флаг атакующего на полет
        c->return_address = 0x4430A3; // обходим расчет кавалерийского бонуса (он всё равно не работает)
        return NO_EXEC_DEFAULT;
    }
    return EXEC_DEFAULT;
}
///////////////////////////////////////////////

_PI->WriteLoHook(0x44307A, Y_AntiKavalierAndFly); // не считать кавалерийский бонус при полете



RE: Решение багов ERA/WOG - igrik - 03.09.2019 11:56

Решение бага ERM: триггер MA:U#/-2 приводил к тому, что любое существо при установке такой команды улучшалось в копейщика. Подробнее тут
Плагин: скачать

Code:
int __stdcall Fix_WoG_GetCreatureGrade_Expo(LoHook* h, HookContext* c)
{
    if ( *(int*)(c->ebp -4) < -1) {
        *(int*)(c->ebp -4) = -1;
    }
    return EXEC_DEFAULT;
}

int __stdcall Fix_WoG_GetCreatureGrade_Town(LoHook* h, HookContext* c)
{
    if (*(int*)0x27F93B0 < -1) { // FOH_ret < -1
        *(int*)0x27F93B0 = -1;
    }
    return EXEC_DEFAULT;
}
///////////////////////////////////////////////
_PI->WriteDword(0x724A9F, -2);    
_PI->WriteLoHook(0x724AC5, Fix_WoG_GetCreatureGrade_Expo);

_PI->WriteDword(0x74ED27, -2);  
_PI->WriteLoHook(0x74ED5C, Fix_WoG_GetCreatureGrade_Town);



RE: Решение багов ERA/WOG - igrik - 11.10.2020 19:37

Решение нескольких крит.вылетов в игре в режиме битвы
Code:
// фикс вылета: АИ битва (просчёт)
// проверка на скорость монстра и когда он дойдет до защиты стрелка.
// Убираем из проверки существ с нулевой скоростью и боевые машины
_int_ __stdcall Y_AIMgr_Stack_MinRoundToReachHex(HiHook* hook, _dword_ this_, _BattleStack_* stack, _int_ a3)
{
    if (stack->creature.flags == BCF_CANT_MOVE || stack->creature.speed < 1)
        return 99; // 99 раундов необходимо, чтобы добраться до стрелка

    return CALL_3(_int_, __thiscall, hook->GetDefaultFunc(), this_, stack, a3);
}

_PI->WriteHiHook(0x4B3C80, SPLICE_, EXTENDED_, THISCALL_, Y_AIMgr_Stack_MinRoundToReachHex);

Code:
// фикс вылета: нет проверки на наличие стуктуры целевого стека при воскрешении
// тут не хватает проверки на c->edi
int __stdcall Y_FixCrash_CastSpell_38(LoHook* h, HookContext* c)
{
    if ( c->edi )
    {
       c->eax = *(int*)(c->edi + 0x38);
       c->ecx = *(int*)(c->ebx + 0x132C0);
       c->return_address = 0x5A1C20;
      
    }  else c->return_address = 0x5A2368;

    return NO_EXEC_DEFAULT;
}

_PI->WriteLoHook(0x5A1C17, Y_FixCrash_CastSpell_38);

Code:
// фикс вылета: при удалении препятствия в битве нет проверки на наличие стуктуры его дефа
// (привет WoG и его стена огня у Огненных Лошадей)
int __stdcall Y_FixCrash_RemoveObstackle(LoHook* h, HookContext* c)
{
    // проверяем на пустую структуру боевого пропятствия
    // чтобы пропустить код обращения к ней и как следствие крит.краш.игры
    if ( !c->ecx || !c->edi )
    {
       c->return_address = 0x466826;
       return NO_EXEC_DEFAULT;  
    }

    return EXEC_DEFAULT;
}

_PI->WriteLoHook(0x46681B, Y_FixCrash_RemoveObstackle);



RE: Решение багов ERA/WOG - slater777 - 08.01.2023 06:37

Фикс бага WOG'a

Code:
_LHF_(HooksInit)
{
    // Фикс Димера - герой имеет продвинутую разведку на старте
    h3::H3HeroInfo* hero_info_table = P_HeroInfo->Get();
    hero_info_table[eHero::DEEMER].sskills[1].level = eSecSkillLevel::BASIC;
}

_PI->WriteLoHook(0x4EEAF2, HooksInit);



RE: Решение багов ERA/WOG - daemon_n - 08.01.2023 08:22

slater777, адрес хука?


RE: Решение багов ERA/WOG - slater777 - 08.01.2023 09:57

(08.01.2023 08:22)daemon_n Wrote:  slater777, адрес хука?

Поправил пост.