Решение багов ERA/WOG - igrik - 21.09.2011 22:09
Данная тема предназначена только для выкладывания кода лечения багов (непосредственно касающихся Вога или Эры) на программном уровне, для того чтобы Berserker мог их включать в состав era.dll
Любые сообщения, не содержащие указание бага совместно с его решением на Ассамблере, Delphi или С++ будут безжалостно уничтожаться.
Я буду данные фиксы включать в плагин game bug fixes extended.dll
Исходник можно увидеть тут: github.com
[+] работающая кнопка Отмена в Арене
[+] кнопка Отмена у Хижины ведьм
[+] кнопка отмены у ученого, предлагающего втор.навык
[+] фикс некоторых операций со стеками
[+] исправление бага посещения банков в которых дают существ (вылет в диалоге присоедиенния монстров)
[+] исправление некоторых багов ИИ: хождение по воде (без заклинания) и возможность колдовать заклы выше 1-го уровня на проклятой земле
[+] фикс урона стрелковых башен при Доспехах и заклинании "Воздушный щит"
[+] исправление перепутаных бонусов атаки и защиты в спецстроениях Крепости
[+] исправление бага заклинания Землетрясение, когда оно могло убить верхний стек защитника
[+] центрирование изображения по ПКМ в городе на иконке найма войск (ранее уходило сильно влево)
[+] исправление координат кнопки Сказочных Драконов
[+] исправление ошибки ERM в командре IF:N1, теперь командра работает со всеми локальными, глобальными и отрицательными переменными z, а не только с z1
[+] исправление неправильных иконок специализаций героев Инферно (Ксерафакс и Ксерон)
[+] исправление некоторых кнопок в таверне, в окне разделения отряда, в диалоге преобразователя скелетов
[+] правильное смещение портрета героя в диалоге повышения уровня героя
[+] исправление отключения тени курсора при автобитве
[+] фикс вылета в быстрой битве: проверка скорости монстра на 0
[+] фикс вылета в быстрой битве: при касте заклинания Воскрешение и Поднятие Мертвецов
[+] фикс вылета при удалении препятствия в битве
[+] отключение показа входа Двеллинга 8-го уровня существ, при его захвате ИИ
[+] ненависть существ теперь считается и на существ 8-го уровня
[+] бонусы специалистов героев теперь действуюи и существ 8-го уровня
[+] отключение псевдорасчета урона на существ с полётом и кавалерийским бонусом одновременно
[+] добавление динамического Fight_Value командира
[+] исправление бага блока командира, когда защита падала из-за флага "в защите"
[+] исправление бага блока существ (опыт монстров), когда игра падала в бесконечный цикл
[+] исправление критического бага Астрального духа
[+] полноценный хинт колдовства для описаний командиров и монстров с номером больше 134
[+] исправление бага палатки, когда на её ходу невозможно убежать или сделать другие действия
[+] критический вылет на ходу палатки
[+] возможность заходить в гильдию магов без наличия книги и денег у героя-гостя
[+] исправление бага с исчезновением стартового героя при переигрывании новой карты
[+] запрет стрельбы при отрицат.боезапасе
[+] решение бага (еще с SoD) исчезновения улучшенного стека при битве с даунгрейдом нейтралов
[+] фикс отлета гарпий, когда после удара они связаны корнями дендроидов
[+] не считать предварительный бонус урона от кавалерии при полете (он всё равно не работает)
[+] решение бага Вога, когда в бою накладывается опыт через EA:E и атака, защита, уроны, скорость, боезапасы и т.п. заново пересчитываются. Из-за этого терялись бонусы наложенных заклинаний (например бонус скорости от ускорения)
[+] фикс когда бонусы специалистов не считались существам 8-го уровня
[+] исправление созданий WoG'ом корявых пакованых координат
[+] корректировка WoG ненависти существ (добавление и существ 8-го уровня)
[+] вызовы драконов от артефакта сердце дракона, чтобы в банках существ не перекрывался стек №3
[+] фикс выбора типа атаки при битве ИИ vs человек (человек не мог выбрать тип атаки)
[+] решение проблемы отображения некоторых строк (в русской локализации) в диалоге опыта монстров.
[+] корректировка описаний заклинаний в книге (не учитывались бонусы специалистов по заклинаниям)
[+] фикс неотображения Монолитов и Подземных врат в диалоге заклинания Просмотр Земли и Воздуха
[+] фикс неправильного отображения величины урона в окне статуса битвы при касте заклинания Армагеддон
[+] решение бага ERM: триггер MA:U#/-2 приводил к тому, что любое существо при установке такой команды улучшалось в копейщика
[+] фикс расстановки клонов от заклинания Клон
[+] фикс расстановки клонов от опыта монстров
[+] отображение тени установки заклинания Силовое Поле
[+] рабочий запрет выдачи заклинаний у артефактов, если они запрещены через UN:J0/spell_id/1
Решение багов ERA/WOG - Sav - 06.07.2012 18:55
Я всё-таки разобрался со шрифтами.
Вот патч:
PHP Code:
// Исправляем обработку отрицательного отступа шрифта (ошибку приведения типов). _PI->WriteByte(0x4B5349 + 1, 0xB6); // (mov)zx _PI->WriteByte(0x4B53E5 + 1, 0xB6); // (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(0x4CCC43, IntAt(0x4CCC43) - 4);
Этот вылет связан с содовским багом (возможно, только 3.2) генерации слуха в таверне. Там берётся случайное число от 1 до 256 и по нему как по индексу берётся значение (адрес строки слуха) из 256-элементного массива. Соответственно, первый слух никогда не берётся, зато иногда берётся элемент "за последним", он равен 0, и происходит вылет.
Раньше мне казалось, что в Воге что-то намутили с таблицей слухов и там этого вылета нет, но теперь я поймал его в Эре.
Этот баг фактически обеспечивал 0.4% шанса вылететь каждую неделю.
RE: ERA II - MOP - 20.09.2012 21:27
Исправление бага отображения русских букв в диалоге опыта существ (некоторые способности - чёрточки вместо слов):
RE: ERA II - MOP - 28.09.2012 07:27
деактивация вог-проверок, вызывающих потерю опыта последнего отряда (exe-адреса):
Code:
2F3C55 EB0C
2F3BEC EB0C
2F42E6 EB0C
2F4356 EB0C
Исходники WoG, Monsters.cpp - поиск по фразе "хочет перенести последний стэк - не получится".
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 (патч для памяти):
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, адрес хука?
Поправил пост.
|