Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Инженерный анализ
DF2 :: ФОРУМЫ > Игровые форумы > Heroes of Might & Magic III > Моды
Страницы: 1, 2, 3, 4
MasterOfPuppets
Чуть-чуть.

Контрудары

В начале битвы:

43D6A0 cmp eax,00000004h - Грифон
43D6A3 mov [esi+5Ch],ecx
43D6A6 mov dword ptr [esi+00000454h],00000001h - кол-во ответок для обычного существа
43D6B0 jnz L0043D6BC
43D6B2 mov dword ptr [esi+00000454h],00000002h - кол-во ответок для Грифона
43D6BC cmp eax,00000005h - Кор. Грифон
43D6BF jnz L0043D6CB
43D6C1 mov dword ptr [esi+00000454h],00001388h - кол-во ответок для Кор. Грифона

446E65 - аналогичный код для ответок в каждом раунде.

Шпионаж

4E605C push 0000008Fh; - Вор

Передвижение по песку

4B177B push 0000008Eh; - Кочевник
feanor
5BDCE0 - Начисление плюшек спецстроениями типа водоворота маны, академии, Вальгаллы и т.п.
Соответственно, здесь же можно их и отрубить (для"болванок" городов), к примеру:

Убить Mana Vortex - 5BDD50: EB
Убить Academy: 5BDFF5: EB

Типы призываемых заклятьями существ
mem:5A2042,5A2057,5A206C,5A2081 - номера для огненного, земляного, водного и воздушного элементалей.

Оно конечно легко ищется из ранее упомянутого свитча - но свитч еще расковырять надо. Пусть будет.
feanor
Цитата(Чёртос-2 (Chortos-2) @ 20 Jun 2007, 15:29)
Вот они, цвета наши. smile.gif В WoG они хранятся по адресу 0043F5C4, но только для существ с номерами от 35 (архимаг) до 121 (магический элементаль) включительно — при этом психическому и магическому элементалю зачем‑то выставлен белый цвет, правда, я так и не понял, зачем. (Архимагу выставлен зеленый, созерцателю и злому глазу — белый, всем остальным в таблице — черный; если существа нет в таблице, подразумевается черный.) Ноль соответствует зеленому лучу, один — белому, и два — черному. Ловим функцию… (Ловим в первом сообщении темы.)

реально цвет луча определяется значение регистра ecx после свитча в районе 43F296h

0 - черный, 12Е - зеленый, 130 - белый.
Если расширить свитч и поиграться с этим значением, то дополнительно получим:
12F - тонкий фиолетово-черный
12D - синий
FF - ярко-синий
37B0 - светло-зеленый
F800 - красный.

Похоже, что в ecx хранится цвет в RGB565.
_____________________
Смотрим на радужных бехолдеров!
Они стреляют новыми радужными лучами!!11
MasterOfPuppets
SUB_L0044AA90 - функция проверки наличия существ у героя.
Принимает два параметра - номер существа и адрес структуры героя (со смещением до первого слота существ). Возвращает в eax суммарное кол-во заданных существ у героя. Если их нет, то и eax = 0.

Банка с джемом smile.gif

4B8ACF push 00000085h - Кристальный Дракон.
4B8B28 lea ecx,[ebx+00020BE8h] - загрузка исполнительного адреса (смещение в структуре игрока). Изменив, допустим, на +4, можно заставить существо производить Драг. Камни вместо Кристаллов и т.д.
4B8B40 add dword ptr [ecx],00000003h - собственно, кол-во добавляемого ресурса в неделю.
Vade Parvis
Цитата
F800 - красный.
Гоблины с бластерами? rolleyes.gif
MasterOfPuppets
Цитата
Маленькое наблюдение.
Описанные тобой, МОР, свойства монстров,а именно: снижение стоимости заклинания, кавалерийский бонус, пенальти за расстояние и шарпшутерство - находятся почему-то в секции кода ЗВС? Тем не менее эти свойства есть и в оригинальном СОДе, может это промежуточный код?

Абилки вынесены из-за опыта существ. А код - действительно промежуточный, что, тем не менее, не убирает его с повестки дня, так как WoG обращается к нему и при выключенном опыте. В большинстве случаев делается так: при запуске exe перед проверкой на существо ставится хук на вог-функцию. Если проверок несколько - хук также затирает и их, оставляя лишь последнюю. В вог-функции сначала идут проверки на существа, имеющие этот бонус в СОД, затем - на существа, имеющие бонус в качестве абилки опыта. В обоих случаях при наличии свойства в изначальный регистр или ячейку памяти заносится номер монстра, имеющего данный бонус в СОД, с которым СОД его далее и сравнивает в оставшейся проверке.
Способ несколько странный и смахивает на жульничество - подтасовка номера монстра под нужный СОДу. Хотя, может, так и безопаснее...

Как уже говорил, ключ ко всем таким вещам - воговское копирование массивов. По-моему, оно делится на три вида:
1. Откуда/Куда/Сколько байт
2. Куда/Что/Сколько байт
3. Адрес для помещения хука/0/Адрес вог-функции

Посмотрев, что и куда копируется, можно найти много интересных штук и облегчить себе жизнь. Простой пример: отрезок exe3253D0-325C1B - снятие всех ограничений на хинт по существу (adress/197/4).
Слава фактически предоставил нам свой огромный труд на блюдечке, безо всяких исходников.

Повышение цен заклинаний

4E554C push 00000014h - Пегас
4E554E mov ecx,edi
4E5550 call SUB_L0044A850
4E5555 test al,al
4E5557 jnz L004E5566
4E5559 push 00000015h - Серебряный Пегас
4E555B mov ecx,edi
4E555D call SUB_L0044A850
4E5562 test al,al
4E5564 jz L004E5569
4E5566 add esi,00000002h - кол-во очков на подорожание

Код стоит прямо перед снижением цен на заклинания Магами и Архимагами. Странно, что ВОГ вклинился только в нижний участок.

Уменьшение вражеской защиты

75D4A0 cmp dword ptr [ebp-04h],00000060h - Чудище
75D4A4 jz L0075D4AE
75D4A6 cmp dword ptr [ebp-04h],00000061h - Древнее Чудище
75D4AA jz L0075D4E0

75D551 cmp dword ptr [edx+34h],0000009Ch - Чудище-Привидение
75D558 jnz L0075D564

Блок удара

766A8D cmp dword ptr [ecx+34h],000000C4h - Драколич
766A94 setnz dl
766A97 dec edx
766A98 and edx,00000014h - %-ый шанс срабатывания

Его же сопротивление магии:

75D9FC cmp dword ptr [ecx+34h],000000C4h
75DA03 jnz L0075DA14
75DA05 mov edx,[L0283282C]
75DA0B sub edx,00000014h

Всегда положительная мораль

На поле боя:

767133 cmp dword ptr [ebp-04h],0000004Eh - Минотавр
767137 jz L0076713F
767139 cmp dword ptr [ebp-04h],0000004Fh - Король-Минотавр
76713D jnz L0076714B

В слоте:

44AEF7 cmp edi,0000004Eh
44AEFA jz L0044AF01
44AEFC cmp edi,0000004Fh
44AEFF jnz L0044AF0B

Магическая Аура

767244 cmp dword ptr [eax+34h],00000018h - Единорог
767248 jnz L00767256
76724A mov dword ptr [L028601E8],00000019h - Боевой Единорог

и

76729F cmp dword ptr [eax+34h],00000018h
7672A3 jnz L007672B1
7672A5 mov dword ptr [L028601E8],00000019h

Бряк, поставленный на эти адреса, даёт о себе знать, когда существо встаёт рядом с другим существом.

+1 к морали союзников

44BA46 cmp dword ptr [eax],0000000Ch - Ангел
............
760A15 cmp dword ptr [ecx],0000000Dh - Архангел
760A18 jz L00760A32
760A1A cmp dword ptr [ecx],00000096h - Верховный Архангел
760A20 jz L00760A32

А это для текста "Архангелы в группе" в окне существа (иначе будет "Алебардщики в группе"):

760A39 cmp dword ptr [edx],0000000Dh
760A3C jz L00760A56
760A3E cmp dword ptr [edx],00000096h
760A44 jz L00760A56


-1 к удаче врага

7609BC cmp dword ptr [edx],00000037h - Архидьявол
7609BF jz L007609D9
7609C1 cmp dword ptr [edx],00000099h - Антихрист
7609C7 jz L007609D9

Для текста:

7609F6 cmp dword ptr [ecx],00000037h
7609F9 jz L00760A0E
7609FB cmp dword ptr [ecx],00000099h

Между этими проверками есть ещё проверки неясного содержания. В общем, надо ещё разобраться, что за что отвечает.
feanor
Навыки, дающиеся в Университете Сопряжения:
Код
005D330A   C745 D0 0A000000 MOV DWORD PTR SS:[EBP-30],0E
005D3311   C745 D4 0F000000 MOV DWORD PTR SS:[LOCAL.11],0F
005D3318   C745 D8 10000000 MOV DWORD PTR SS:[LOCAL.10],10
005D331F   C745 DC 11000000 MOV DWORD PTR SS:[LOCAL.9],11
feanor
Объекты на карте
4A8160 - функция (один большой свитч), обрабатывающая вход в объекты на карте.

из которой можно вызнать, к примеру
Откуда берет артефакты Чёрный Рынок:
По адресу 699538h лежит некий указатель
Прибавляем к нему 1F684h, получаем второй указатель
Этот указатель показывает на таблицу артефактов (7 DWORDов на каждый черный рынок).

Пример:
Код
//устанавливаем в первый слот первого рынка магическую книжку.
!!UN:C6919480/4/?y1;
!!VRy1:+128644;
!!UN:Cy1/4/?y2;
!!UN:Cy2/4/0;


Номер рынка можно узнать через OB:C - он совпадает с контрольным числом.
MasterOfPuppets
Боян, но пусть будет:

679DD0h - массив стартовых параметров героев. 5Ch байт на структуру героя. Данные:
1. Пол
2. ?
3. Класс
4. Первый стартовый навык
5. Уровень первого стартового навыка
6. Второй стартовый навык
7. Уровень второго стартового навыка
8. Наличие Книги Заклинаний: да/нет
9. Стартовое заклинание
10. Стартовая армия, тип существа, слот №1
11. Стартовая армия, тип существа, слот №2
12. Стартовая армия, тип существа, слот №3
13. Ссылка на название малого портрета
14. Ссылка на название большого портрета
15. ? (напоминает запрет/доступность для найма, но при изменении эффекта не замечено)
Остальные данные (16-23) всегда нулевые, для чего нужны - неизвестно.

678420h - специализации героев. 28h байт на специализацию.
Всё как в HE:X.
feanor
Репортаж с чемоданов (:.

Структуры стэков на поле боя.
[0x699420]+0x54CC+stack_num*0x548.
Формат описан в справке Драколича ("о недокументированных возможностях BM:G")
Все поля - по 4 байта (точнее, выравнены по 4м байтам - там, где в сорцах были шорты и чары, в дампе остались 0xBAADF00D)
Первые четыре байта соответствуют BM:G-полю -102.

Слух дня в таверне

Адрес: [699538h]+4E419h

Вообще, [699538h] - это все сохраняемые в сейве данные. Структуры героев (в самом начале), городов, объектов etc, etc.
feanor
Данные, как обычно, почти непроверенные и вообще извлеченные под перегревом и агрофитнессом.

49D040 - функция затемнения участка поверхности.
int __thiscall sub_49D040(void *this, int x, int y, int level, int player, int radius);
//====================================================
Текущий герой:
[69CCFC]+4
a
[69CCFC]+8
[69CCFC]+12
[69CCFC]+16
..
список героев на панели. 7 DWORD'ов.

[69CCFC]+1 - количество героев в списке.
Если поставить больше, чем есть, а в список вытянуть левого героя, он появится, но кликать на него не стоит.
Если поставить меньше, чем есть - лишние будут некликабельны.

[69CCFC]+E2 - возможно, флаг на определение, ИИ или человек сейчас ходит.
//====================================================
sub_553C40(..)
печать в внутриигровой чат. Функция напоминает printf.

ввод в чат можно хукнуть на 402450 или 4022E0.
//====================================================
void *__thiscall sub_5C8590(void *this, char amount)

Показать гильдию воров. amount - количество информации
//====================================================
Смещения в структурах героев:

476h - атака-защита-спеллпавер-знание
12Dh - слоты артов. Первый - шлем и далее по 4байта
1С5h - записи о блокированных слотах? странный формат. 11 байт
после них - рюкзак героя
51h - опыт
55h - уровень

35h,39h - точки назначения для героя 4байта
00h 02h 04h - ворд координаты
4Dh - мувпойнты

430h - таблица заклинаний
//====================================================
51BD60 - заглушка, поставленная вместо функции мультиплеерного лога. Надо вернуть её на место и почитать - интересссно. По формату сходна с ?printf, но первым параметром идет имя файла.
//====================================================
0х69844C - ID недели. Если неделя существа - там лежит номер существа. Если неделя белки, ежа и прочего - там лежит номер названия.
Как отличить - пока хз.
//====================================================
Текущий день - [840CE0]. Два байта - день, два байта - месяц, два байта - год.
//====================================================
Переход хода - функция 4СС490.
//====================================================
5CEC30 - вызов окна гарнизона.
1 параметр - указатель на структуру героя,
2 параметр - цвет флага
3 параметр - указатель на структуру войск гарнизона (7 DWORDов для типов, 7 DWORDов для количества (или наоборот (= ) и 8 байт непонятного назначения)
feanor
Проверка на Доспехи Проклятого и Альянс Ангелов - в куске кода от 464F10.

Много вкусных и питательных плюшек можно найти, если проследить вызовы функции 4D9460 - проверка на наличие артефакта на герое.

В частности:
0044A26F - свитч на выдачу артам иммуна к заклинаниям.
005A86F3 - дополнительная проверка на Клинок Армагеддона
004E663A - плюшки к скорости на поле боя
004E66CC - плюшки к хитпойнтам
005BFE32 - проверки на части Статуи Легиона
sergroj
Вот покопал тип, подтип недели и месяца:

69844C WeekSubtype:
Номер монстра или зверька (кролик и т.п.)
6977A0 WeekType:
2 - inferno imps
1 - growth +5
0 - none (if it's the frst week of month, see MonthType, else it's neutral week)

Probability:
2 - 0
1 - 1/4
0 - 3/4

697798 MonthSubType.
Номер монстра или зверька (кролик и т.п.)
698884 MonthType:
2 - plague
1 - monster *2
0 - nothing

Probability:
2 - 1/10
1 - 4/10
0 - 5/10

63E678 - 12 monsters that can double their population
sergroj
AI
Вычисляет ценность объекта для AI:
.text:00528520 ; int __fastcall AICalculateMapPosWeight(_Hero_ *hp, signed int *moveDist, int packedmapitem)
moveDist - расстояние до объекта,
packedmapitem - координаты объекта,
hp - герой.

AI решает, применить ли заклинание монстра:
.text:00421400 ; char __thiscall CombatMan_00421400_MonsterAITrySpecial(_CombatMan_ *this, _CombatMonster_ *mon, int *weight, int a4)
weight - ценность наилучшего действия, выбранного до этого.

Возвращает функцию, вычисляющую ценность заклинания:
.text:0043B2E0 combatMan_GetSpellWeightAIProc

[edit]
Вычисляет ценность удара по монстру:
.text:004357E0 ; int __thiscall CombatUnk_004357E0_AI_GetRawWeightOfMonAttack(int this, _CombatMonster_ *MonStr, int monHealth, _CombatMonster_ *enemy, int enemyHealth, signed int canShoot, signed int NotRealDamage)

AI для стрелков, у которых есть выстрелы и они не заблокированы:
.text:0041F1E0 ; char __thiscall CombatMan_0041F1E0_ShootingCreatureAI(_CombatMan_ *this, _CombatMonster_ *mon, char a3, int side)

AI для стрелков, у которых есть выстрелы и они не заблокированы:
.text:0041F1E0 ; char __thiscall CombatMan_0041F1E0_ShootingCreatureAI(_CombatMan_ *this, _CombatMonster_ *mon, char a3, int side)

Рукопашный AI для остальных:
.text:00422100 ; int __thiscall CombatMan_00422100_MeleeCreatureAI(_CombatMan_ *this, _CombatMonster_ *a2, char a3, char a4, int side)
feanor
Структуры классов героя.
Адрес - 67В86С. Ссылки - в 4A6A23 (код), 67DCEC, 78BFC0.
Описание:
struct
{
char* name;
float agression;
char start_prim_param[4];
char prim_param_percentage[4];
char prim_param_percentage2[4]; //10+
char second_param_chances[28];
char town_tavern_chances[9];
char foo[7];
}

Названия, впрочем чаще берутся из массива указателей по [698B78].
sergroj
что-то у тебя непонятное. Адрес где-то в середине структуры, у ссылок тоже левые адреса.

.data:0067D868 ; _HeroType_ HeroTypesTable[18] (ссылка - 67DCEC)

00000000 _HeroType_ struc ; (sizeof=0x40)
00000000 Belong2Town dd ?
00000004 TypeName dd ? ; offset (00000000)
00000008 Agression dd ?
0000000C PSkillStart db 4 dup(?)
00000010 ProbPSkillToLvl9 db 4 dup(?)
00000014 ProbPSkillAfterLvl10 db 4 dup(?)
00000018 ProbSSkill db 28 dup(?)
00000034 ProbInTown db 9 dup(?)
0000003D field_3D db 3 dup(?)
00000040 _HeroType_ ends

.data:00679DD0 ; _HeroInfo_ HeroInfo[163] (ссылка - 67DCE8)

00000000 _HeroInfo_ struc ; (sizeof=0x5C)
00000000 Female dd ?
00000004 _u1 dd 8 dup(?)
00000024 ArmyType dd 3 dup(?)
00000030 HPSName dd ? ; offset (00000000)
00000034 HPLName dd ? ; offset (00000000)
00000038 _u2 db 8 dup(?)
00000040 Name dd ? ; offset (00000000)
00000044 ArmyNum dd 6 dup(?)
0000005C _HeroInfo_ ends

P.S. дополнил пост про AI
feanor
ага, напортачил при поиске ссылок. Никогда больше не буду постить полученную в три ночи инфу, не проверив её утром. biggrin.gif

За описание структуры - спасибо.

Вообще, надо бы мне все выложенное проверить, а то то там куча ошибок sad.gif
MasterOfPuppets
Тоже немного об ИИ.
Довольно часто (я насчитал 46 вызовов) в коде вызывается простенькая функция SUB_L0044A950. Вычисляет она не что иное, как общую FightValue войск героя. В ecx кладётся указатель на структуру героя (со смещением до первого слота существ), в eax возвращается результат.
Два вызова этой функции приходятся на SUB_L004AC270, которая срабатывает в момент нападения ИИ на бродячего монстра и, видимо, управляет логикой этой битвы.
feanor
006747B4 - таблица обитателей жилищ в городах. По DWORD'у на рыло, порядок - негрейды Замка, грейды Замка, негрейды Оплота etc
feanor
Еще об артефактах, точнее, о расчете их (и не только их) бонусов.

004E3ED0 - функция, возвращающая тип поднимаемого в результате некромантии существа.
004E3F40 - функция, определяющая процент поднятых существ
004E42E0 - функция, определяющая радиус обзора.
004E43D0 - функция, определяющая проценты бонуса Archery
004E4690 - ..Eagle Eye
004E4950 - ..Resistance
004E4C00 - расчет мувпойнтов.
004E5020 - бонус к длительности заклятий
004E59D0 - бонусы к школам магии.
004E5D10 - бонусы к скорости в бою
004E5DF0 - к хитпойнтам

Haart of the Abyss
Цитата
004E3ED0 - функция, возвращающая тип поднимаемого в результате некромантии существа.
Ня, жезл переработки трупов в огненных элементалей! И прочие милые артефакты на тему некромантии по-кригански и по-варлочьи.
feanor
sub_757045 - проверки на прямые атаки воговских существ: душепийство Привидений и миролюбивость Эмиссаров.
sub_75E762 - заклинания, лежащие на воговских существах.
sub_7673AD - в начале функции дни полнолуния для Оборотней
sub_75C695 - хук на опыт башен, на палатку помощи, на Эмиссаров, на Колдуний и Пожаров.

sub_5BFA00 - количество денег, зарабатываемое городом
feanor
688f04 - таблица ресурсов, приносимых хранилищем. 7*4 байт для каждого города.
MasterOfPuppets
63E510h – таблица процентных модификаторов затрат очков хода при передвижении по разным почвам. Массив integer-ов, по 4 значения в зависимости от уровня развития Поиска Пути. По порядку:
00 Dirt
01 Sand
02 Grass
03 Snow
04 Swamp
05 Rough
06 Underground
07 Lava
08 Water
09 Rock/No road
10 Dirt
11 Gravel
12 Cobblestone
Следующие за таблицей четыре значения используются для доступа к модификаторам дорог.
MasterOfPuppets
Настройки игры

Все адреса в порядке возрастания. Все значения байтовые, но растянуты до двордов. Если опция не комментируется, то статус для неё: 1 - да, 0 - нет

6987A8 - скорость врага (2-5)
6987AC - скорость героя (1-4)

6987B0h - громкость mp3 (0-9)
6987B4h, 6987BCh - громкость wav-звуков (0-9). Почему-то дублируется, хотя на громкость влияет только 6987B4h.

6987C4h - показ маршрута
6987C8h - запрос об окончании хода
6987CCh - быстрая битва
6987D0h - видеосубтитры
6987D4h - контуры гор. зданий
6987D8h - анимация Книги Заклинаний
6987DCh - скорость прокрутки карты (0-2)

<<< Настройки автобоя
6987E4h - существа
6987E8h - заклинания
6987ECh - катапульта
6987F0h - баллиста
6987F4h - сан. палатка
/ >>>

6987F8 - качество видео (0 - низкое, 1 - высокое)

<<< Опции битвы
69880Ch - показать сетку?
698810h - тень курсора
698814h - Тень перемещения
698818h - информация об отряде (0 - нет, 1 - вся статистика, 2 - только заклинания)
69883Ch - скорость боевой анимации (0-2)
/ >>>
feanor
Генератор случайного монстра
sub_4C8F80(void *this, int level_from, int level_start);

Используется для беженцев и для замены случайных монстров на карте.

this = [699538]
Дьяк
Правка генератора случайных монстров при старте карты. Позволяет генерировать новых и воговских монстров на карте без вогификации. Выдрал из наработок по WoG 359

// врезка Fix генератора
{0x54110F, 0x0, DP(Hook54110F)}, // Diakon

// настройка генератора карт (генерируем новых и ВоГовских монстров)
//MGENERATOR mGenerator [MONNUM];

int gmon;
int nMon;
int NotCheck = 0x541137;
int Check = 0x541116;

__declspec (naked) void Hook54110F(){
__asm pushad;
__asm mov gmon, ebx;
__asm mov eax, dword ptr [edi];
__asm mov nMon, eax;

if (nMon == -1){
__asm popad;
__asm jmp NotCheck;
}

__asm popad;
__asm lea eax, dword ptr [esi + esi*4];
__asm jmp Check;

}

// врезка FixGeneratora
{(Byte*)&JMP, (Byte*)0x54110F, 1}, //Diakon
{(Byte*)&PSUB, (Byte*)(0x541013+2), 4}, //Diakon
{(Byte*)&MSUB, (Byte*)(0x54106B+2), 4}, //Diakon
{(Byte*)&MSUB, (Byte*)(0x54109C+3), 4}, //Diakon
{(Byte*)&MSUB, (Byte*)(0x5410E1+3), 4}, //Diakon
{(Byte*)&MSUB, (Byte*)(0x541174+3), 4}, //Diakon
{(Byte*)&GENMONNUM, (Byte*)(0x541063+1), 4}, //Diakon
{(Byte*)&GENMONNUM, (Byte*)(0x5410B3+1), 4}, //Diakon
{(Byte*)&GENMON, (Byte*)(0x541159+1), 4}, //Diakon

int JMP = 0xE9; //Diakon
int PSUB = 0x324; //Diakon
int MSUB = -804; // Diakon
int GENMONNUM = 0xC5; - изменяется в зависимости от кол-ва монстров. негенерируемых монстров не прописываем в текстовике. Не помню текстовик для рандомной карты. Если кто не знает - напишу. Лень копаться.
int GENMON = GENMONNUM -1;
MasterOfPuppets
6436A8h - родные почвы городов.
63D0A8h - таблица позиций, по которым расставляются существа в обычном бою.
63D0E0h - таблица позиций, по которым расставляются существа при грабеже банка.
ERM:
!!UN:C4600476/2/37008; - любая битва будет происходить как в банке
!!UN:C4600637/4/95721; - дополнительно к этому, уберёт с поля боя машины
!!UN:C4600476/2/5236 C4600637/4/24413455; - восстановит стандартный код
Чёртос-2 (Chortos-2)
Цитата(feanor @ 15 Feb 2011, 06:35) *
Товарищи! Ниже есть тема по обсуждению инженерного анализа!
Блин, теперь стали сам инженерный анализ в ту тему писать. Я сначала хотел покопировать куски оттуда сюда, но, добравшись до последней страницы, понял, что лучше просто отослать читателя к той теме куда-то в районе 120-го поста и позже.
MasterOfPuppets
sub_617F94 - возможно, самая частовстречающаяся функция (451 вызов). Округляет float ST0 в меньшую сторону и возвращает результат в виде integer.
tolich
Цитата(MasterOfPuppets @ 07 May 2011, 13:34) *
sub_617F94 - возможно, самая частовстречающаяся функция (451 вызов). Округляет float ST0 в меньшую сторону и возвращает результат в виде integer.
Точно в меньшую? Или всё же банально в сторону нуля? Проверь на отрицательных числах, я более чем уверен, что это operator int(double).
Etoprostoya
Моя ИДА распознала эту функцию как __ftol (convert float to long). tolich прав.
MasterOfPuppets
[[0x699420]+0x132C4]
0 - человек сам управляет боем, 1 - человек нажал кнопку "Автобой" и вышел покурить.
Только чтение.
tolich
А разве автобой с человеком не по той же схеме считается, что и с компом? (Это я про курение, по времени он даже сигарету не достанет.)
MasterOfPuppets
Имеется в виду реальный бой, но в авторежиме. Когда видишь всё действия.
tolich
Цитата(MasterOfPuppets @ 10 Jun 2011, 15:07) *
Имеется в виду реальный бой, но в авторежиме. Когда видишь всё действия.
А, вкурил понял.
MasterOfPuppets
Кстати, ошибся. Установка тоже работает.
Berserker
Полезная штука.
Valery
Is there any way to remove the 48 towns limit in game/editor? Those new 252x252 maps need a lot more.
Sav
Цитата(Dead @ 05 Nov 2011, 02:55 (Сообщение отредактировал Dead - 05 Nov 2011, 03:02))
.data:00681FB2 конец тоблицы координатоф карты загадки , PuzTOWNxx.bmp, пишу адрес конца таблицы потому что неуверен нащёт начала, штота неочень там сходитса, лень проверять, порядок: например .data:00681EF4 здесь PuzEle00.bmp координаты х, 2 баита на координаты, перва идут координаты х всех рысунков , потом у ..



Цитата(Dead @ 07 Nov 2011, 02:58 (Сообщение отредактировал Dead - 07 Nov 2011, 03:02))



Цитата(feanor @ 24 Nov 2011, 19:03)
О выстрелах по стенам.


Код
CPU Disasm
Address   Hex dump          Command                                  Comments
00445AA6  |> \8B7F 34       MOV EDI,DWORD PTR DS:[EDI+34]  ;edi до этого момента - указатель на структуру стека, после - номер монстра
00445AA9  |.  8B0D 20946900 MOV ECX,DWORD PTR DS:[699420]
00445AAF  |.  83EF 5E       SUB EDI,5E                             ; Switch (cases 5E..91, 4 exits)
00445AB2  |.  74 1F         JE SHORT 00445AD3
00445AB4  |.  4F            DEC EDI
00445AB5  |.  74 15         JE SHORT 00445ACC
00445AB7  |.  83EF 32       SUB EDI,32
00445ABA  |.  75 1E         JNE SHORT 00445ADA
00445ABC  |.  8B9481 CC5300 MOV EDX,DWORD PTR DS:[EAX*4+ECX+53CC]  ; Case 91 of switch Era_1_6_exe_HD.445AAF - катапульта
00445AC3  |.  0FBE82 D30000 MOVSX EAX,BYTE PTR DS:[EDX+0D3];D3 - смещение баллистики в структуре героя
00445ACA  |.  EB 11         JMP SHORT 00445ADD
00445ACC  |>  B8 02000000   MOV EAX,2                              ; Case 5F of switch Era_1_6_exe_HD.445AAF - циклопы
00445AD1  |.  EB 0A         JMP SHORT 00445ADD
00445AD3  |>  B8 01000000   MOV EAX,1                              ; Case 5E of switch Era_1_6_exe_HD.445AAF
00445AD8  |.  EB 03         JMP SHORT 00445ADD
00445ADA  |>  8B45 08       MOV EAX,DWORD PTR SS:[ARG.1]           ; Default case of switch Era_1_6_exe_HD.445AAF


Тут добавлю немного. Если стреляющее по стене существо - не циклоп, король-циклоп, катапульта, т. е. попадает в Default case, то в качестве навыка "артиллерия" для него берётся номер атакуемого сооружения. По этому уровню навыка впоследствии, как по индексу, берётся структура параметров баллистического выстрела, которая содержит в себе количество выстрелов, шансы не промахнуться и шансы нанести урон. Если номер атакуемого сооружения > 3, то вместо всего этого будет взят мусор. Вылета это не вызовет, т. к., с одной стороны, номера атакуемых сооружений находятся в пределах двух десятков, а памяти после массива структур параметров баллистического выстрела выделено достаточно, а с другой стороны, структура параметров баллистического выстрела не содержит в себе указателей. Самое неприятное, что может случиться - большое количество выстрелов с нулевым шансом нанесения урона.



Цитата(Berserker @ 18 Dec 2011, 21:17 (Сообщение отредактировал Berserker - 18 Dec 2011, 21:04))
Обновим тень перемещения:
493350 - F (0, 1); THISCALL;

Код
!!UN:C6919200/4/?y2;
!!SN:E4797616/2/y2/0/1;
!!BU:R;


Теперь если поменять скриптом скорость монстра, можно и сеточку обновить...

Цитата
[edit]
Вычисляет ценность удара по монстру:
.text:004357E0 ; int __thiscall CombatUnk_004357E0_AI_GetRawWeightOfMonAttack(int this, _CombatMonster_ *MonStr, int monHealth, _CombatMonster_ *enemy, int enemyHealth, signed int canShoot, signed int NotRealDamage)

Последний параметр - расстояние, 0 - теоретически.



Цитата(Berserker @ 25 Dec 2011, 11:51)
IsTacticPhase: CombatManager($699420) -> $13D68
Battle stacks: CombatManager($699420) -> 21708 (1352 на отряд)
ZvsCursorLocked: $840E10
StackToStackDamageCalculation: $443C88
MM Damage trigger: $492409



Цитата(Berserker @ 07 Jan 2012, 18:26)
50b970 - чтение настроек из реестра
50b420 - настройки по умолчанию
50bfd0 - сохранить все настройки

Show Intro - 699410
Music Volume - 6987B0
Sound Volume - 6987B4
Last Music Volume - 6987B8
Last Sound Volume - 6987BC
Walk Speed - 6987AC
Computer Walk Speed - 6987A8
Show Route - 6987C4
Move Reminder - 6987C8
Quick Combat - 6987CC
Video Subtitles - 6987D0
Town Outlines - 6987D4
Animate SpellBook - 6987D8
Window Scroll Speed - 6987DC
Blackout Computer - 6987E0
First Time - 699574
Test Decomp - 699578
Test Read - 69957C
Test Blit - 699580
Bink Video - 6987F8
Unique System ID - 698838
Network Default Name - 698867
Autosave - 6987C0
Show Combat Grid - 69880C
Show Combat Mouse Hex - 698810
Combat Shade Level - 698814
Combat Army Info Level - 698818
Combat Auto Creatures - 6987E4
Combat Auto Spells - 6987E8
Combat Catapult - 6987EC
Combat Ballista - 6987F0
Combat First Aid Tent - 6987F4
Combat Speed - 69883C
Main Game Show Menu - 6987FC
Main Game X - 698800
Main Game Y - 698804
Main Game Full Screen - 698808
AppPath - 698614
CDDrive - 698888



Цитата(etoprostoya @ 07 Jan 2012, 19:10)
MoP вроде эти адреса уже указывал, по крайней мере, некоторые.



Цитата(Berserker @ 07 Jan 2012, 19:21 (Сообщение отредактировал Berserker - 07 Jan 2012, 19:39))
http://forum.df2.ru/index.php?showtopic=68...st&p=490895

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

Код
[Settings]
Show Intro=1
AppPath="C:\h\"
Music Volume=0
Sound Volume=0
Last Music Volume=0
Last Sound Volume=0
Walk Speed=2
Computer Walk Speed=3
Show Route=0
Move Reminder=0
Quick Combat=0
Video Subtitles=0
Town Outlines=0
Animate SpellBook=0
Window Scroll Speed=0
Bink Video=0
Blackout Computer=0
First Time=0
Test Decomp=0
Test Read=0
Test Blit=0
Unique System ID="LOVE"
Network Default Name="Player"
Autosave=0
Show Combat Grid=0
Show Combat Mouse Hex=0
Combat Shade Level=0
Combat Army Info Level=0
Combat Auto Creatures=0
Combat Auto Spells=0
Combat Catapult=0
Combat Ballista=0
Combat First Aid Tent=0
Combat Speed=0
Main Game Show Menu=0
Main Game X=0
Main Game Y=0
Main Game Full Screen=0
CDDrive="C:"
WoG_Version="3.58f, 01 November 2004"
Era Version = "2.0"



Цитата(Berserker @ 09 Jan 2012, 03:07)
int 6911880d - индекс текущего выделенного слота в окне героя или -1.
int 6916756d - 0-1 - включён ли режим разделения существ? (кнопка такая)



Цитата(Berserker @ 09 Jan 2012, 17:27)
$06775888 - Heroes Meeting, selected side (0..1) or -1
$06775890 - Heroes Meeting, selected slot or -1
$0675254C - Visiting Hero, selected slot or -2
$067525CC - Town Garrison, selected slot or -2



Цитата(Sav @ 24 Jan 2012, 20:37 (Сообщение отредактировал Sav - 24 Jan 2012, 20:42))
Код
signed int __thiscall A0_Battle_Stack_get_Speed_sub_4489F0(struct_BattleStack *this)
{
  signed int result; // eax@1
  float Speed_v2; // ST00_4@4

  result = this->Speed_dwordC4;
  if ( this->Spells_Lengths_a198[54] )          // Если наложена Медлительность...
                                                // (а иначе - просто возвращаем скорость)
  {
    if ( (this->Flags_dword84 >> 6) & 1 )       // Осадное орудие
    {
      result = 0;
    }
    else
    {
      Speed_v2 = (double)(signed int)this->Speed_dwordC4;
      result = A0_to_signed_int_sub_617F94(Speed_v2 * this->SlowSpell_Modif_dword4C8);
      if ( result <= 0 )
        result = 1;                             // Минимальная скорость при медлительности - 1
    }
  }
  return result;
}


Код
// Сравнение приоритета хода стеков (если у первого приоритетнее - возврат 1)
char __thiscall A0_Battle_CompareStacksTurnPriority_sub_464B30(int this, struct_BattleStack *Stack1, struct_BattleStack *Stack2)
{
  int MoraleFlag1_v3; // eax@1
  bool res; // eax@2
  int Type2_v5; // edx@3
  int Type1_v6; // ecx@3
  signed int Speed1_v7; // ebx@5
  signed int v8; // esi@7
  signed int v9; // esi@8
  int Owner1_v10; // eax@9
  int this_v12; // [sp+Ch] [bp-4h]@1

  this_v12 = this;
  MoraleFlag1_v3 = Stack1->Flags_dword84 >> 24;
  if ( ((_BYTE)MoraleFlag1_v3 ^ (unsigned __int8)(Stack2->Flags_dword84 >> 24)) & 1 )// В этом ходу одному и только одному из отрядов выпала мораль
  {
    LOBYTE(res) = MoraleFlag1_v3 & 1;           // Если мораль выпала первому, возвращаем 1, иначе 0
  }
  else
  {
    Type1_v6 = Stack1->CreatureType_dword34;
    Type2_v5 = Stack2->CreatureType_dword34;
    res = Type1_v6 == 149;                      // Если первый - стрелковая башня, а второй - нет, возвращаем 1, наоборот - 0
    if ( res == (Type2_v5 == 149) )             // Стрелковая башня
    {
      res = Type1_v6 == 145;                    // Аналогично с катапультой
      if ( res == (Type2_v5 == 145) )           // Катапульта
      {                                         // Одинаковы по выпавшей морали, явлении катапультой и стрелковой башней
        Speed1_v7 = A0_Battle_Stack_get_Speed_sub_4489F0(Stack1);
        if ( Speed1_v7 == A0_Battle_Stack_get_Speed_sub_4489F0(Stack2) )// Скорости равны
        {
          Owner1_v10 = Stack1->Owner_dwordF4;
          if ( Owner1_v10 == Stack2->Owner_dwordF4 )
            LOBYTE(res) = Stack1->StackNum_dwordF8 < Stack2->StackNum_dwordF8;// Если хозяева одинаковы, раньше ходит тот, у кого номер стека меньше
          else
            LOBYTE(res) = res != *(_DWORD *)(this_v12 + 78520);// res = Stack1->OwnerF4 != (this_v12 + 78520)
                                                // Последнее - сторона последнего ходившего монстра (в особых же случаях устанавливается в 1)
                                                // Т. е. больший приоритет имеет существо другого владельца, чем только что ходивший (в особых случаях - нападающего)
        }
        else
        {
          if ( *(_BYTE *)(this_v12 + 81380) )   // Фаза ожидания
          {
            v8 = A0_Battle_Stack_get_Speed_sub_4489F0(Stack1);
            LOBYTE(res) = v8 < A0_Battle_Stack_get_Speed_sub_4489F0(Stack2);// У кого меньше, тот имеет преимущество
          }
          else                                  // Не фаза ожидания
          {
            v9 = A0_Battle_Stack_get_Speed_sub_4489F0(Stack1);
            LOBYTE(res) = v9 > A0_Battle_Stack_get_Speed_sub_4489F0(Stack2);// У кого больше, тот имеет преимущество
          }
        }
      }
    }
  }
  return res;
}



Цитата(tolich @ 24 Jan 2012, 20:53)
Вот поэтому охранники снеговика, будучи замедленными, начинают двигаться.



Цитата(etoprostoya @ 24 Jan 2012, 21:03)
Цитата(Sav @ 24 Jan 2012, 20:37)
Код
signed int __thiscall A0_Battle_Stack_get_Speed_sub_4489F0(struct_BattleStack *this)
{
  this->Speed_dwordC4;
}

Для полноты кода нужно описать и структуру "this" (struct_BattleStack).

P.S. "this" кириллицей будет "ершы"! smile.gif



Цитата(Sav @ 24 Jan 2012, 21:08 (Сообщение отредактировал Sav - 24 Jan 2012, 21:09))
Всё из BM:G с минимумом правок (не уверен, что всё верно, но многое точно). Кстати, в информации по BM:G (из справки Драколича), похоже, ошибка: флаги существ - это не -71, а -69.
Если поле обозначено массивом байтов с названием f, то что там находится, мне неизвестно.

Код
struct struct_BattleStack
{
  _BYTE f0[8];
  _DWORD Visiblity_dword8;
  _BYTE fC[40];
  _DWORD CreatureType_dword34;
  _DWORD GexNum_dword38;
  _DWORD AnimNum_dword3C;
  _DWORD AnimFrameNum_dword40;
  _BYTE f44[8];
  _DWORD Count_dword4C;
  _DWORD VisibleCount_dword50;
  _DWORD LosesAfterBattle_dword54;
  _DWORD HealthLoses_dword58;
  _BYTE f5C[4];
  _DWORD Count_At_BattleStart_dword60;
  _BYTE f64[16];
  _DWORD CreatureTown_dword74;
  _BYTE f78[12];
  _DWORD Flags_dword84;
  _DWORD Creature_NameSingle_dword88;
  _DWORD Creature_NameMulti_dword8C;
  _DWORD Creature_Description_dword90;
  _BYTE f94[44];
  _DWORD Health_dwordC0;
  _DWORD Speed_dwordC4;
  _DWORD Attack_dwordC8;
  _DWORD Defense_dwordCC;
  _DWORD Damage_Min_dwordD0;
  _DWORD Damage_Max_dwordD4;
  _DWORD Ammo_dwordD8;
  _BYTE fDC[24];
  _DWORD Owner_dwordF4;
  _DWORD StackNum_dwordF8;
  _BYTE fFC[4];
  _DWORD X_Shift_dword100;
  _DWORD Y_Shift_dword104;
  _BYTE f108[68];
  _DWORD X_CountShowingRect_Shift_dword14C;
  _BYTE f150[4];
  _DWORD RandomAnim_Freq_dword154;
  _BYTE f158[12];
  _DWORD CreatureAnim_dword164;
  _DWORD CreatureBulletAnim_dword168;
  _BYTE f16C[4];
  _DWORD Move_Sound_dword170;
  _DWORD Attack_Sound_dword174;
  _DWORD Damage_Sound_dword178;
  _DWORD Shot_Sound_dword17C;
  _DWORD Death_Sound_dword180;
  _DWORD Defense_Sound_dword184;
  _BYTE f188[12];
  _DWORD ActiveSpells_CountForColor_dword194;
  _DWORD Spells_Lengths_a198[80];
  _BYTE f2D8[372];
  _DWORD ActiveSpells_dword44C;
  _BYTE f450[120];
  float SlowSpell_Modif_dword4C8;
  _BYTE f4CC[28];
  _DWORD Morale_dword4E8;
  _DWORD Luck_dword4EC;
  _BYTE f4F0[88];
};



Цитата(tolich @ 24 Jan 2012, 21:20)
Есть подозрение, что, большей частью, все неизвестные поля на самом деле те же дворды. Больно уж у них размеры кратные 4.



Цитата(feanor @ 24 Jan 2012, 22:15)
Неа, там просто компилятор сделал округление. Кое-где именно char и short, ибо в старших байтах остатки от BAADF00D видны.



Цитата(Berserker @ 24 Jan 2012, 22:29)
А чем описание от ZVS не нравится?

Код
struct _CombatMon_{  // размер 0x548
                     // +00 db (1) когда отаковал уже(?)
                     // +01 db
                     // +02 db (0C) 44188C
                     // +03 db
                     // +08 dd = полное число стеков у игрока
                     // +10 dd =-1 после атаки и/или ответа(????)
                     // +1С dd = позиция на поле боя (куда бежать/стрелять)
                     // +20 db = огненный щит
                     // +28 dd = -1 (номер стэка клона этого)  
                     // +30 db 43E33C
  int   Type;        // +34 dd = тип монстра
  int   Pos;         // +38 dd = позиция монстра на поле боя (куда атакует)
                     // +3C dd = заклинания
                     // +40 dd 43E236
                     // +44 dd (=1) сдвиг в сторону второй занятой клетки для монстра с двумя клетками
  int   MonNum;      // +4C - число монстров
                     // +50 - число монстров до удара по ним в тек. атаку
  int   LostLastHP;  // +58 - потери здоровья последнего монстра
                     // +5C - номер слота героя (0...6), -1 - будет удален после битвы
  int   MonNum0;     // +60 - число монстров в начале битвы
                     // +6C - полное здоровье (исп. как база для лечения)
                     // +70 dd 44150F 441744
                     // +74 dd -1 для продвинутых элементалей
                     // +78 dd = уровень существа (0...6)
  Dword Flags;       // +84
    // 00000001 - 0x00 DOUBLE_WIDE - занимает 2 клетки
    // 00000002 - 0x01 летает
    // 00000004 - 0x02 стреляет
    // 00000008 - 0x03 расширенный радиус атаки (на две клетки)
    // 00000010 - 0x04 живое существо (можно восстанавливаться вампиру)
    // 00000020 - 0x05 CATAPULT - может разрушать стены
    // 00000040 - 0x06 SIEGE_WEAPON - осадное оружие - не двигается (5508CB)
    // 00000080 - 0x07 KING_1
    // 00000100 - 0x08 KING_2
    // 00000200 - 0x09 KING_3
    // 00000400 - 0x0A ??? 00020000 + 40,41,83 - не чуствителен к псих атаке
    // 00000800 - 0x0B нет описания (35,74,75)
    // 00001000 - 0x0C в ближнем бою бьет как в дальнем
    // 00002000 - 0x0D ----
    // 00004000 - 0x0E ??? IMMUNE_TO_FIRE_SPELLS
    // 00008000 - 0x0F стреляет дважды
    // 00010000 - 0x10 атака без ответа
    // 00020000 - 0x11 ... не подвержен низкой морали (?)
    // 32,33,56-69,112-117,120,121,123,,125,127,129,141,145-149
    // 00040000 - 0x12 нечисть
    // 00080000 - 0x13 бьет всех врагов рядом
    // 00100000 - 0x14 расширенный радиус стреляющих юнитов
    // 00200000 - 0x15 стэк убит? 41E617 чародей,firebird - может еще кастовать?
    // 00400000 - 0x16 421BDC,421FC4 (что-то с вызовом)
    // 00800000 - 0x17 копия стэку - умирает сразу
    // 01000000 - 0x18 гарпии-ведьмы
    // 02000000 - 0x19 остался(уже) ждать СБРОСИТЬ - МОЖЕТ ЖДАТЬ СНОВА
    // 04000000 - 0x1A уст. после атаки СБРОСИТЬ - ВНОВЬ МОЖЕТ ОТАКОВАТЬ
    // 08000000 - 0x1B - выбрал защиту
    // 10000000 - 0x1C - не может быть ресуректен ???
    // 20000000 - 0x1D + 43DFAF
    // 40000000 - 0x1E + 43E06F
    // 80000000 - 0x1F дракон
//  int   FullHP;      // +B0 dd = ???
  int   HitPoints;   // +C0 dd = здоровье монстра
  int   Speed;       // +С4 dd = скорость монстра
  int   Attack;      // +C8 dd = атака с бонусами
  int   Defence;     // +CC dd = защита с бонусами
                     // +D0 dd = мин. дамэдж
                     // +D4 dd = макс. дамэдж
                     // +D8 dd = количество выстрелов
                     // +DC dd = количество заклинаний 0=нет ДЛЯ ВОСКРЕШЕНИЯ УВЕЛИЧИТЬ
                     // +E8 db =
                     // +E9 db = 1, если умирал хоть один
                     // +EA db = 1, если был убит весь стэк
                     // +EC dd = номер заклинания существа в тек раунде 0x50 Acid breath
                     // +F0 db=1 перед атакой на него 441434
                     // +F4 dd (0,1) индекс игрока 0 или 1 4414AF 443D69
                     // +F8 dd = номер стэка у стороны на поле боя
                     // +FC dd = ? что-то с магией
                     // +100 dd 43DEA4
                     // +104 dd 43DEAD
                     // +108 dd
                     // +158 dd =?
                     // +164 dd -> ctroll.def (троль)
  Byte *ShootDef;    // +168 - загруж.деф. для стреляющих (иниц в 43DA8E)
                     // +16C
                     // +194 dd = количество уже наложенных заклинаний
                     // +198 dd*? (есть заклинание (длительность) или нет по номерам)
                     //  +198 dd = Summon Boat
                     //  +19C dd = Scuttle Boat
                     //  +1A0 dd = Visions
                     //  +1A4 dd = View Earth
                     //  +1A8 dd = Disguise
                     //  +1AC dd = View Air
                     //  +1B0 dd = Fly
                     //  +1B4 dd = Water Walk
                     //  +1B8 dd = Dimension Door
                     //  +1BC dd = Town Portal

                     //  +1C0 dd = Quicksand
                     //  +1C4 dd = Land Mine
                     //  +1C8 dd = Force Field
                     //  +1CC dd = Fire Wall
                     //  +1D0 dd = Earthquake
                     //  +1D4 dd = Magic Arrow
                     //  +1D8 dd = Ice Bolt
                     //  +1DC dd = Lightning Bolt
                     //  +1E0 dd = Implosion
                     //  +1E4 dd = Chain Lightning
                     //  +1E8 dd = Frost Ring
                     //  +1EC dd = Fireball
                     //  +1F0 dd = Inferno
                     //  +1F4 dd = Meteor Shower
                     //  +1F8 dd = Death Ripple
                     //  +1FC dd = Destroy Undead
                     //  +200 dd = Armageddon
                     //  +204 dd = Shield
                     //  +208 dd = Air Shield
                     //  +20C dd = fire Shield
                     //  +210 dd = Protection from Air
                     //  +214 dd = Protection from Fire
                     //  +218 dd = Protection from Water
                     //  +21C dd = Protection from Earth
                     //  +220 dd = Anti-Magic
                     //  +224 dd = Dispel
                     //  +228 dd = Magic Mirror
                     //  +22C dd = Cure
                     //  +230 dd = Resurrection
                     //  +234 dd = Animate Dead
                     //  +238 dd = Sacrifice
                     //  +23C dd = Bless
                     //  +240 dd = Curse
                     //  +244 dd = Bloodlust
                     //  +248 dd = Precision
                     //  +24C dd = Weakness
                     //  +250 dd = Stone Skin
                     //  +254 dd = Disrupting Ray
                     //  +258 dd = Prayer
                     //  +25C dd = Mirth
                     //  +260 dd = Sorrow
                     //  +264 dd = Fortune
                     //  +268 dd = Misfortune
                     //  +26C dd = Haste
                     //  +270 dd = Slow
                     //  +274 dd = Slayer
                     //  +278 dd = Frenzy
                     //  +27C dd = Titan's Lightning Bolt
                     //  +280 dd = Counterstrike
                     //  +284 dd = Berserk
                     //  +288 dd = Hypnotize
                     //  +28C dd = Forgetfulness
                     //  +290 dd = Blind
                     //  +294 dd = Teleport
                     //  +298 dd = Remove Obstacle
                     //  +29C dd = Clone
                     //  +2A0 dd = Fire Elemental
                     //  +2A4 dd = Earth Elemental
                     //  +2A8 dd = Water Elemental
                     //  +2AC dd = Air Elemental

                     //  +2B0 dd = Stone   443D3A 43E0EB 441B0D (!= не отв. на атаку)
                     //  +2B4 dd = Poison
                     //  +2B8 dd = Bind
                     //  +2BC dd = Desease
                     //  +2C0 dd = Paralyze
                     //  +2C4 dd = Aging
                     //  +2C8 dd = Death Cloud
                     //  +2CC dd = Thunderbolt
                     //  +2D0 dd = Dispel
                     //  +2D4 dd = Death Stare
                     //  +2D8 dd = Acid Breath
                  // +2DC dd*? (сила действия заклинания)
                     //  +2DC dd = Summon Boat
                     //  +2E0 dd = Scuttle Boat
                     //  +2E4 dd = Visions
                     //  +2E8 dd = View Earth
                     //  +2EC dd = Disguise
                     //  +2F0 dd = View Air
                     //  +2F4 dd = Fly
                     //  +2F8 dd = Water Walk
                     //  +2FC dd = Dimension Door
                     //  +300 dd = Town Portal

                     //  +304 dd = Quicksand
                     //  +308 dd = Land Mine
                     //  +30C dd = Force Field
                     //  +310 dd = Fire Wall
                     //  +314 dd = Earthquake
                     //  +318 dd = Magic Arrow
                     //  +31C dd = Ice Bolt
                     //  +320 dd = Lightning Bolt
                     //  +324 dd = Implosion
                     //  +328 dd = Chain Lightning
                     //  +32C dd = Frost Ring
                     //  +330 dd = Fireball
                     //  +334 dd = Inferno
                     //  +338 dd = Meteor Shower
                     //  +33C dd = Death Ripple
                     //  +340 dd = Destroy Undead
                     //  +344 dd = Armageddon
                     //  +348 dd = Shield
                     //  +34C dd = Air Shield
                     //  +350 dd = fire Shield
                     //  +354 dd = Protection from Air
                     //  +358 dd = Protection from Fire
                     //  +35C dd = Protection from Water
                     //  +360 dd = Protection from Earth
                     //  +364 dd = Anti-Magic
                     //  +368 dd = Dispel
                     //  +36C dd = Magic Mirror
                     //  +370 dd = Cure
                     //  +374 dd = Resurrection
                     //  +378 dd = Animate Dead
                     //  +37C dd = Sacrifice
                     //  +380 dd = Bless
                     //  +384 dd = Curse
                     //  +388 dd = Bloodlust
                     //  +38C dd = Precision
                     //  +390 dd = Weakness
                     //  +394 dd = Stone Skin
                     //  +398 dd = Disrupting Ray
                     //  +39C dd = Prayer
                     //  +3A0 dd = Mirth
                     //  +3A4 dd = Sorrow
                     //  +3A8 dd = Fortune
                     //  +3AC dd = Misfortune
                     //  +3B0 dd = Haste
                     //  +3B4 dd = Slow
                     //  +3B8 dd = Slayer
                     //  +3BC dd = Frenzy
                     //  +3C0 dd = Titan's Lightning Bolt
                     //  +3C4 dd = Counterstrike
                     //  +3C8 dd = Berserk
                     //  +3CC dd = Hypnotize
                     //  +3D0 dd = Forgetfulness
                     //  +3D4 dd = Blind
                     //  +3D8 dd = Teleport
                     //  +3DC dd = Remove Obstacle
                     //  +3E0 dd = Clone
                     //  +3E4 dd = Fire Elemental
                     //  +3E8 dd = Earth Elemental
                     //  +3EC dd = Water Elemental
                     //  +3F0 dd = Air Elemental

                     //  +3F4 dd = Stone   443D3A 43E0EB 441B0D (!= не отв. на атаку)
                     //  +3F8 dd = Poison
                     //  +3FC dd = Bind
                     //  +400 dd = Desease
                     //  +404 dd = Paralyze
                     //  +408 dd = Aging
                     //  +40C dd = Death Cloud
                     //  +410 dd = Thunderbolt
                     //  +414 dd = Dispel
                     //  +418 dd = Death Stare
                     //  +41C dd = Acid Breath
                          
                     // +444 dd ->
                     // +448 dd (2)
                     // +44C dd
                     // +454 dd 441B17 (кол-во ответов на атаку 0= не отв. на атаку)
// настройка для грифонов 46D6A0
// КОЛИЧЕСТВО ОТВЕТОВ НВ АТАКУ
                     // +458 dd Bless добавка к Max. Damage
                     // +45C dd Curse убавка к Min. Damage
                     // +464 dd Bloodlast добавка к Атаке с бонусами
                     // +468 dd Precision добавка к Атаке с бонусами
                     // +48C dd KING_123 тип (1=KING_1,2=KING_2,3=KING_3)
                     //   исп для расчета Slayer. Бонус 8 к Атаке: 0x4421D2    
                     // +490 dd номер атакера по порядку??? уже атаковал??? (сбрасывается после первого удара)
                     // +494 dd кол. доп. ответов на атаку, добавленных Counerstrike заклом
                     // +4A4 dd
                     // +4C0 db Blinded - снизить защиту (сбросить после?) при атаке на него (уст. перед ударом)
                     // +4C1 db Paralized - снизить защиту (сбросить после?) при атаке на него (уст. перед ударом)
                     // +4C2 dd Forgetfulness - уровень (>2 - не может стрелять)
                     // +4DC dd = величина бонуса при выборе защиты
                     // +4E0 dd заклинание для сказ дракона
                     // +4EC dd 44152A
                     // +4F1 db 43DF88

                     // +514 dd
                     // +518 dd -> dd first \ adjusted stacks pointers
                     // +51C dd -> dd last  /

                     // +524 dd
                     // +528 dd -> dd first \ adjusted to wich stacks pointers
                     // +52C dd -> dd last  /
};



Цитата(tolich @ 24 Jan 2012, 22:34)
Это называется выравнивание данных, а не округление. Да, о нём не подумал, считал, что все нормальные программисты "#pragma pack(1)". gigi.gif



Цитата(Sav @ 24 Jan 2012, 22:36 (Сообщение отредактировал Sav - 24 Jan 2012, 22:37))
Цитата(Berserker)
А чем описание от ZVS не нравится?

Хм, я ведь даже смотрел его. smile.gif Но почему-то вовремя не вспомнилось. Ну, хотя бы что-то новое у меня есть: float SlowSpell_Modif_dword4C8. smile.gif

feanor
Работа с моралью и удачей.
Наконец-то добрался до хинтов, угу, не прошло и двух лет
Код
extern int GetLuckBonus(int art, int customdata);
extern int GetMoraleBonus(int art, int customdata);
extern int GetLuckBonusFromBP(int art, int customdata);
extern int GetMoraleBonusFromBP(int art, int customdata);


int __stdcall LuckTextHook(LoHook* h, HookContext* c)
{
    HERO *hero = (HERO*)(c->ebx);

    /*char *s = "\x0AВрожденное везение +1";
    
    CALL_3(void, __thiscall, 0x41B2A0, (int*)(c->ebp-0x28), s, strlen(s));
    *(int*)(c->ebp-0x10) += 1;*/

    char buf[256];


    for (int i=0; i!=19; i++)
    {
        int l = 0;
        if(hero->IArt[i][0]!=-1 && (l=GetLuckBonus(hero->IArt[i][0],hero->IArt[i][1])))
        {
            sprintf(buf,"\x0A%s %s%i",GetArtifactRecord(hero->IArt[i][0])->name, l>0?"+":"",l);
            CALL_3(void, __thiscall, 0x41B2A0, (int*)(c->ebp-0x28), buf, strlen(buf));
            *(int*)(c->ebp-0x10) += l;
        }
    }


    for (int i=0; i!=64; i++)
    {
        int l = 0;
        if(hero->OArt[i][0]!=-1 && (l=GetLuckBonusFromBP(hero->OArt[i][0],hero->OArt[i][1])))
        {
            sprintf(buf,"\x0A%s %s%i",GetArtifactRecord(hero->OArt[i][0])->name, l>0?"+":"",l);
            CALL_3(void, __thiscall, 0x41B2A0, (int*)(c->ebp-0x28), buf, strlen(buf));
            *(int*)(c->ebp-0x10) += l;
        }
    }

    return EXEC_DEFAULT;
}


int __stdcall LuckValueHook(LoHook* h, HookContext* c)
{
    HERO *hero = (HERO*)(c->esi);
    
    for (int i=0; i!=19; i++)
    {
        int l = 0;
        if(hero->IArt[i][0]!=-1 && (l=GetLuckBonus(hero->IArt[i][0],hero->IArt[i][1])))
        {
            *(int*)(c->ebp+0x0C) += l;
        }
    }


    
    for (int i=0; i!=64; i++)
    {
        int l = 0;
        if(hero->OArt[i][0]!=-1 && (l=GetLuckBonusFromBP(hero->OArt[i][0],hero->OArt[i][1])))
        {
            *(int*)(c->ebp+0x0C) += l;
        }
    }

    return EXEC_DEFAULT;
}



int __stdcall MoraleTextHook(LoHook* h, HookContext* c)
{
    HERO *hero = (HERO*)(c->ebx);

    /*char *s = "\x0AВрожденное везение +1";
    
    CALL_3(void, __thiscall, 0x41B2A0, (int*)(c->ebp-0x28), s, strlen(s));
    *(int*)(c->ebp-0x10) += 1;*/

    char buf[256];


    for (int i=0; i!=19; i++)
    {
        int l = 0;
        if(hero->IArt[i][0]!=-1 && (l=GetMoraleBonus(hero->IArt[i][0],hero->IArt[i][1])))
        {
            sprintf(buf,"\x0A%s %s%i",GetArtifactRecord(hero->IArt[i][0])->name, l>0?"+":"",l);
            CALL_3(void, __thiscall, 0x41B2A0, (int*)(c->ebp-0x28), buf, strlen(buf));
            *(int*)(c->ebp-0x10) += l;
        }
    }

    for (int i=0; i!=64; i++)
    {
        int l = 0;
        if(hero->OArt[i][0]!=-1 && (l=GetMoraleBonusFromBP(hero->OArt[i][0],hero->OArt[i][1])))
        {
            sprintf(buf,"\x0A%s %s%i",GetArtifactRecord(hero->OArt[i][0])->name, l>0?"+":"",l);
            CALL_3(void, __thiscall, 0x41B2A0, (int*)(c->ebp-0x28), buf, strlen(buf));
            *(int*)(c->ebp-0x10) += l;
        }
    }
    return EXEC_DEFAULT;
}


int __stdcall MoraleValueHook(LoHook* h, HookContext* c)
{
    HERO *hero = (HERO*)(c->edi);
    
    for (int i=0; i!=19; i++)
    {
        int l = 0;
        if(hero->IArt[i][0]!=-1 && (l=GetMoraleBonus(hero->IArt[i][0],hero->IArt[i][1])))
        {
            *(int*)(c->ebp+0x0C) += l;
        }
    }

    for (int i=0; i!=64; i++)
    {
        int l = 0;
        if(hero->OArt[i][0]!=-1 && (l=GetMoraleBonusFromBP(hero->OArt[i][0],hero->OArt[i][1])))
        {
            *(int*)(c->ebp+0x0C) += l;
        }
    }

    return EXEC_DEFAULT;
}

...


//удача
emerald->WriteLoHook(0x4DCDA6, (void*)LuckTextHook);
emerald->WriteLoHook(0x4E3A46, (void*)LuckValueHook);

//мораль
emerald->WriteLoHook(0x4DC606, (void*)MoraleTextHook);
emerald->WriteLoHook(0x4E3C9E, (void*)MoraleValueHook);
feanor
Всякие мелочи, которые я возможно допилю до инструментов в ближайшие дни.

Код на замену анимации нового дня/недели.



Для активации 8 слота, требует дополнительной обвязки для нормальной работы.


Для расширения таблицы препятствий


feanor
В рантайме же палитра {цвета игрока для интерфейса} лежит в [6AAD10]+1C, массив int16, кодирующих 32*8 цвета (rgb565, little endian)
Изменение действует сразу же.

Чо бы такого с этим сотворить..
feanor
О анимации почв и рек.

Как известно, вода, лава и реки в тройке анимируются древним и утраченным ныне искусством color-cycling'a, то бишь, циклической смены цветов в палитре.

Происходит оная смена в функции 0x4EDB20, char __cdecl Dlg_Redraw1(), в которой:
- для watrtl.def циклично двигаются цвета 229-240, 242-253
- для lavatl.def - 246-254
- для clrrvr.def - 183-194, 195-200
- для mudrvr.def - 183-188, 240-245
- для lavrvr.def - 240-248


Код
//----- (004EDB20) --------------------------------------------------------
char __cdecl Dlg_Redraw1()
{
  int v0; // eax@1
  int v1; // eax@5
  _Def_ *v2; // ecx@8
  _Def_ *v3; // ecx@10
  _Def_ *v4; // ecx@12
  _Def_ *v5; // ecx@14
  _Def_ *v6; // ecx@16

  LOBYTE(v0) = dword_006995C8;
  if ( !dword_006995C8 )
  {
    dword_006995C8 = 1;
    sub_0050D880((int)pMouseManager);
    if ( timeGetTime() - NextPaletteRotate >= 0 )
    {
      if ( dword_00698A68 == 1 || dword_00698A68 == 3 )
        v1 = timeGetTime() + 110;
      else
        v1 = timeGetTime() + 200;
      NextPaletteRotate = v1;
      if ( (_BYTE)TownsHallDefs_ST )
      {
        v2 = *(_Def_ **)(pAdvManager + 128);
        if ( v2 )                               // watrtl.def
        {
          Def_RotateColors(v2, 229, 240, -1);
          Def_RotateColors(*(_Def_ **)(pAdvManager + 128), 242, 253, -1);
        }
        v3 = *(_Def_ **)(pAdvManager + 124);
        if ( v3 )                               // lavatl.def
          Def_RotateColors(v3, 246, 254, -1);
        v4 = *(_Def_ **)(pAdvManager + 140);
        if ( v4 )
        {                                       // clrrvr.def
          Def_RotateColors(v4, 183, 194, -1);
          Def_RotateColors(*(_Def_ **)(pAdvManager + 140), 195, 200, -1);
        }
        v5 = *(_Def_ **)(pAdvManager + 148);
        if ( v5 )
        {                                       // mudrvr.def
          Def_RotateColors(v5, 228, 239, -1);
          Def_RotateColors(*(_Def_ **)(pAdvManager + 148), 183, 188, -1);
          Def_RotateColors(*(_Def_ **)(pAdvManager + 148), 240, 245, -1);
        }
        v6 = *(_Def_ **)(pAdvManager + 152);
        if ( v6 )                               // lavrvr.def
          Def_RotateColors(v6, 240, 248, -1);
      }
    }
    v0 = timeGetTime() - dword_006989FC[0];
    if ( v0 >= 0 )
    {
      dword_006989FC[0] = timeGetTime() + 60;
      sub_00554AA0();
      LOBYTE(v0) = MPProcessTimeAndRemind((int)&MPTimeStructure);
    }
    dword_006995C8 = 0;
  }
  return v0;
}
// 6989FC: using guessed type int dword_006989FC[2];
// 698A04: using guessed type int NextPaletteRotate;
// 698A68: using guessed type int dword_00698A68;
// 6995C8: using guessed type int dword_006995C8;

feanor
Все забываю.

https://dl.dropbox.com/u/61759222/HoMM/Heroes3f.c

Декомпилировано по воговской idb-базе.
feanor
Обновил файл на тот, что с новой базы

Чуть-чуть по отстройке.

66CF98 - SoD-таблица индексов строений в окне холла (девять массивов по восемнадцать байтовых индексов). Вог использует адрес 836A20, содержимое по которому восстанавливается после каждой загрузки игры.
Функция 460D70 берет эту таблицу за основу и делает из неё актуальную таблицу, которая потом будет в процессе работы окна холла доступна по адресу 694EC0. Если нужно её динамически менять (третий грейд двеллинга сделать, к примеру) - врезаться можно где-то после 0046102B.

Появление окна в холле не означает, что здание можно автоматически строить. Перестрах**щики из NWC запилили автоматическую выдачу масок доступности, которые исключают постройку ГМ 5 уровня в Замке, верфи в Оплоте etc. Можно убрать их через ERM CD:B0 (хотя Верфи полноценно разрешить не удастся), а можно подправить масочки по адресу 697740 (оригинал) 836AD8 (вог, опять же восстанавливается каждую загрузку).
Вообще, настройка зданий в городе (запреты, настройка точки спауна корабля, постройка зданий (в том числе и вероятностная (30% постройка второго уровня)) идет в функции 5C0CC0.
feanor
всяческие неупомянутые вещи из геймменеджера

Окно свойств карты:
[0x699538]+1F6D0 - 8 байт, описывающие наличие или отсутствие игрока при старте карты. -1 - нету.
[0x699538]+1F864 - 8 байт, тип бонуса (00 - золото, 01 - арт, 02 - ресурс).
[0x699538]+1F6B0 - 8 dword, описывающих типы фракций на карте. 00..08 - фракции
[0x699538]+1F844 - 8 dword, стартовые герои
+1F6A8 - гандикапы?

[0x699538]+1FB40 - указатель на имя карты
[0x699538]+1FB50 - указатель на описание карты

ну и разное прочее
+1F875 - 8 байт под команды игроков, например, 00 01 02 03 04 05 06 07 - для всех против всех.
+1F636 - 8 байт, потерпел ли игрок поражение
igrik
Многие зашитые абилки существ
by Hawaiing
; -----------------------------------------------------
some of creature magic immunitie in the following table

table address = 0079fed0 (begin with 16#)
NO.=immunitie(creatureID)
0=16#Dwarf/133#
1=17#Battle Dwarf
2=26#Green Dragon/82#Red Dragon/132#Azure Dragon
3=27#Gold Dragon
4=83#Black Dragon/121#
5=112#/127#
6=113#/125#
7=115#/123#
8=NONE

troglidite
(immune blind)
0044A28A - 83 f8 46 - cmp eax,46
0044A28D - 0f 84 0e 01 00 00 - je 0044a3a1
0044A293 - 83 f8 47 - cmp eax,47
0044A296 - 0f 84 05 01 00 00 - je 0044a3a1
(immune stone)
0044A3CA - 83 f8 46 - cmp eax,46
0044A3CD - 74 05 - je 0044a3d4
0044A3CF - 83 f8 47 - cmp eax,47
0044A3D2 - 75 42 - jne 0044a416

; -----------------------------------------------------
the "spell effect" ability depend on a table list.
00440228 - 8b 46 34 - mov eax,[esi+34]
0044022B - 83 c0 ea - add eax,ea #begin with 22
0044022E - 83 f8 af - cmp eax,af
00440231 - 77 7b - ja 004402ae
00440233 - 33 c9 - xor ecx,ecx
00440235 - 8a 88 e0 fc 79 00 - mov cl,[eax+0079fce0] #0079fce0->table list
0044023B - ff 24 8d 94 fd 79 00 - jmp dword ptr [ecx*4+0079fd94] #case_address

TABALE LIST:
79FCE0 00 00 01 01 09 09 09 09 09 09 09 09 09 09 09 09 [22-37]22=Dendroid Guard (<22# is not support)
79FCF0 09 09 09 09 09 09 09 09 09 09 09 09 09 09 09 09 [38-53]
79FD00 09 09 09 09 09 02 09 09 09 09 09 09 03 03 09 04 [54-69]
79FD10 09 09 09 09 09 09 05 05 09 09 09 06 09 09 09 09 [70-85]
79FD20 09 09 09 09 09 09 09 09 09 09 09 09 09 09 09 09 [86-101]
79FD30 09 09 09 09 05 05 09 07 09 09 09 09 09 09 09 09 [102-117]
79FD40 09 09 09 09 09 09 09 09 09 09 09 09 09 09 09 09 [118-133]
79FD50 09 08 09 09 09 09 09 03 09 09 09 09 09 09 09 09 [134-149]
79FD60 09 01 09 05 04 09 09 08 09 09 09 09 09 09 09 09 [150-165]
79FD70 09 09 09 09 09 09 09 09 06 06 06 06 06 06 06 06 [166-181]
79FD80 06 06 06 06 06 06 06 06 06 06 09 09 09 09 09 09 [182-197]

0=Bind
1=Blind
2=Disease
3=Curse
4=Age
5=Stone
6=Paralyze
7=Poison
8=Acid Breath
9=NONE

; -----------------------------------------------------
By the way, the "attack effect" also a tale list.
(address 79FC50 and begin with 63#Vampire Lord)

0=Vampire ability
1=Thunderbird ability
2=Death Stare
3=Dragon Fly ability
4=Rust Dragon ability
5=NONE
feanor



Код
int __stdcall ReadAdditionalFields(LoHook* h, HookContext* c)
{
    _CreatureInfo_* target = (_CreatureInfo_*)(c->esi);
    //char** fields = (char**)*(int*)(c->ebx+4);

     target->town = atoi(*(const char **)(*(int *)(c->ebx + 4) + 96));
    target->level = atoi(*(const char **)(*(int *)(c->ebx + 4) + 100));

    target->flags = 0;
    for(int i = 0; i!=32; i++)
        if ( (*(char **)(*(int *)(c->ebx + 4) + 104 + i * 4))[0] !=0  )
            target->flags |= 1 << i;

    return EXEC_DEFAULT;
}

*(int*) 0x47ABC6 = (int)"zcrtrait.txt";
patcher->WriteLoHook(0x47B035, (void*)ReadAdditionalFields);
AlexSpl
Кто-нибудь знает, как в Тройке определить, что игра идёт (загружена карта приключений, а не, скажем, мы ещё/уже в меню)?
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Форум IP.Board © 2001-2025 IPS, Inc.