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

А так-то можно моповские файлы взять, WERD, там очень много чего уже есть готового.
XEPOMAHT
Цитата(hippocamus @ 04 Mar 2021, 00:34) *
Да пусть человек исследует. Одна голова хорошо, а две - лучше.
Что-то он сделает оптимальнее, чем было до него.


Считаю, что лучше не исследовать с 0 то, что уже было не плохо кем-то исследовано, а выбирать то, что ещё почти не исследовалось, чтобы не идти по спирали и не повторять то, что уже было лет 5-10-15 назад.

Цитата(hippocamus @ 04 Mar 2021, 00:34) *
А так-то можно моповские файлы взять, WERD, там очень много чего уже есть готового.


Да, только код из WERD написан под MoP, поэтому под ERA его приходится почти всегда переписывать. Почти всё встраивается или когда-нибудь будет встроено непосредственно в exe-файл, поэтому моповский код с каждым годом всё дальше и дальше уходит от SoD/WoG TE, лет через 5 возможно получится уже ассемблерный аналог VCMI, т.к. может выйти так, что будет сменён весь игровой код от SoD. Поэтому лучше всё же публиковать что-то из IDA-базы от Третьих Героев, нежели из самих модов.
Raistlin
XEPOMAHT, я искренне не знал, что такая функция уже есть, а потому решил написать собственную. Для этого мне пришлось найти пример вызова книги, который я тут и выложил.
Raistlin
Лютый разврат, господа biggrin.gif

Код
int __stdcall GM345_off(LoHook* h, HookContext* c)
{
    if (*(char*)(c->esi + 4) == KremlinTown)
    {
        c->return_address = 0x460F56;
        return NO_EXEC_DEFAULT;
    }
    return EXEC_DEFAULT;
}
...
// Ограничить гильдию магов вторым уровнем
Magic->WriteLoHook(0x460F80, GM345_off);


Для самых немагических замков на свете biggrin.gif
У Кремля, к слову, задумывалось всего два уровня, так что пусть будет - мало ли...

Ну а для трехэтажки хук нужно ставить в 0x460FA6 с возвратом в 0x460F80. Для четырех - 0x460FE0 и 0x460FB1.
Raistlin
Всякая всячина из WoG:

sub_760652(), sub_75E762() - тут производится накладывание заклинаний на воговских существ (например, 1000 раундов огненного щита у пожаров)

75C96C — накладывание заклинаний волшебницами (при выстреле)

76E71F — функция блока командиров

71C710 — воговское уклонение, блок с аниманцией 86 (см. BM:V)

70AF16 — существо, нанимаемое в разрушенном замке (привидение). 4 Байта
Raistlin
69955C - Игрок, нашедший Грааль

Код
//Отрубить бонус командира Крепости (атака и защита)
Magic->WriteDword(0x76C4AE, 0x76C46A); //В бою
Magic->WriteByte(0x76A685, 0xEB); //В окне командира


Две функции, в которых идет проверка армии героя на наличие Темных Драконов, а также специализации "Вуаль Тьмы", для последующего затемнения карты
754584 WoG_SearchFor_HidingAreaSpecialization_AndDarknessDragons_ByHero_1
7546BC WoG_SearchFor_HidingAreaSpecialization_AndDarknessDragons_ByHero_2

Само затемнение: 712589

Проверка на возможность оставить существ на КП. См. "Привидения не хотят оставаться одни"
757045 ; signed int __cdecl CheckCreatureToLeave_WoG(signed int CreatureID)

Само оставление существ вместе с помещением объекта: 7570D9

Проверка на "дружественность"
7575D5 MayHeroFightWithThisMonster

И еще пара полезных функций:
714913 ; signed int __cdecl DoesHeroHaveCreatures_WoG(int HeroStruct, int CreatureID)
71168D ; int __cdecl GetHeroPtr_WoG(signed int HeroID)

Вдогонку:

711209 ; int __cdecl GetMapItem_WoG(int x, int y, signed int l)
7548BC ChooseArtToLeave_WoG

Получение строки из главного текстовика WoG
77710B ; char *__cdecl ReadStringFromTxt(int StringID, int a2, _DWORD *a3)
Благодаря этой функции и исходникам можно выйти практически на все.
Raistlin
Еще вдогонку:

7125DB OpenArea_WoG(int x, int y, int l, int Player, int Radius) //Открытие карты

Работа с текстом:
714973 ; int __cdecl GetArtName_WoG(int ArtID)
7149AF ; int __cdecl GetSpellName_WoG(int SpellID)
7149F0 ; int __cdecl GetBuildingName_WoG(signed int TownType, int BuildingID)
714A38 ; int __cdecl GetMonName_WoG(int CreatureID, int SingleOrMany)
714B05 ; int __cdecl GetSecSkillName_WoG(int SkillID)

712171 H3Str_SetNewText_WoG //Запись текста в геройскую строку
Raistlin
Выяснил еще кое-что интересное, а именно:

В функции 440030 BattleStack_StrikeAllAround не был указан второй параметр (я рассматриваю публичную базу для IDA), но теперь он известен - это флаг атаки тремя головами. Мне нужно было вызывать эту функцию, и я, не подумав, записал во второй параметр 1, а потом ломал голову, почему урон наносится не всем врагам. Сегодня я разрешил этот вопрос, прототип функции выглядит теперь так:

void __thiscall BattleStack_StrikeAllAround(_BattleStack_ *this, int ThreeHeadedAttack, int *totalDamage, int *killedCount, int fireShieldDmg);


Получение структуры гекса:
715872 ; int __cdecl GetHexStruct_WoG(signed int HexID)

Выбор типа атаки при клике ПКМ по защите:
7625E5 ChooseMonAttackType

Артефакт Сила монстра:
760A5A DailyMonster_Art143

Артефакт Золотая стрела:
7602D3 sub_7602D3

Проверка на артефакт Сердце Дракона:
767065 HasDragoHeartArt


762BBF SendMonOfWeek - отсюда и далее идут функции отправки и получения данных для игры по сети.
Сама отправка:
763166 Add2Send
Получение:
763802 Get4Receive

Вызов охраны Санта-гремлинов:
75CDA2 ; int __cdecl SummonSantaGuards(int BM, _DWORD *StackStruct, int StackID)

Абилки Оборотня:
7673AD ; int __cdecl WereWolf(_DWORD *BattleStack_A, int BattleStack_D)



Друзья, я подготовил весьма подробную базу для IDA с разобранной WoG-секцией. Когда я ее еще немного доработаю, она будет опубликована здесь.
Raistlin
Ну вот, это все-таки случилось, и я закончил работать над основой для базы h3era.exe.

Разобран там в основном код, связанный с битвой, но есть и другие функции. К сожалению, часть данных, связанных с картой приключений, была потеряна, но в будущем я снова разберу этот код. Сейчас на ближайшее время я остановлюсь, так что, если хотите, можете продолжить мое дело или просто помочь мне с этим, а недели через две-три, возможно снова вернусь к этому занятию. Советы и пожелания с удовольствием выслушаю.

Скачать базу

Кстати:

Позиции командиров на поле боя:
0076B820 |. C745 E4 58000 MOV DWORD PTR SS:[LOCAL.7],58 ; 88
0076B827 |. EB 07 JMP SHORT 0076B830
0076B829 |> C745 E4 62000 MOV DWORD PTR SS:[LOCAL.7],62 ; 98

Позиции палатки от командира на поле боя:
0076B906 C745 E4 99000 MOV DWORD PTR SS:[LOCAL.7],99 ; 153
0076B90D EB 07 JMP SHORT 0076B916
0076B90F C745 E4 A9000 MOV DWORD PTR SS:[LOCAL.7],0A9 ; 169

Позиции баллисты от командира на поле боя:
0076B9F8 C745 E4 33000 MOV DWORD PTR SS:[LOCAL.7],33 ; 51
0076B9FF EB 07 JMP SHORT 0076BA08
0076BA01 C745 E4 43000 MOV DWORD PTR SS:[LOCAL.7],43 ; 67

Убрать труп с позиции:
5A7630 ; int __stdcall BattleMgr_RemoveDeadStack(_BattleGEX_ *a1, int side, int IndexOnSide) // В ИДЕ этого нет.

Убрать последний труп:
CALL_3(void, __stdcall, 0x5A7630, &o_BattleMgr->hex[ваш индекс], 0, 0);
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Форум IP.Board © 2001-2025 IPS, Inc.