Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Инженерный анализ
DF2 :: ФОРУМЫ > Игровые форумы > Heroes of Might & Magic III > Моды
Страницы: 1, 2, 3, 4
tolich
Может, я чего-то не понимаю, но разве проблема вообще стоит?
AlexSpl
В Двойке есть флаги: int gbGameOver (если мы на экране победы или поражения), int gbInCombat (если в бою), int bEnteringTown (если открыто окно города) и т.п. Нужно найти в Тройке аналогичные (или лучше один: "мы на карте приключений") или другим образом определить идёт ли игра на карте (началась, но ещё не завершена) в произвольном месте кода.
AlexSpl
Пока тупо сделал проверку MaxMP на ноль для Героев 3 (номера дерева прокачки в Героях 1, 2). Всё равно это полумера. Если начинаешь новую игру, то структуры остаются инициализированными, пока не перейдёшь к выбору карты. Следовательно, на них нельзя опираться. Нужно точно знать, в меню я или нет. Неужели никто не знает? Если не желаете делиться информацией, пойму. Хотя с чего бы это?
feanor
Нет, ну не **. Есть обсуждения же тред, есть еще куча прочих тредов, нет, надо писать в справочные.

Цитата(хэлп эры)
PROCEDURE GetGameState (VAR GameState: TGameState); STDCALL;
Gets the current state of the game as a pair of dialog identifiers—the main parent and current dialogs. 0 - no dialogs have been created yet. This function is useful for determining in which window a key was pressed.


Цитата(код эры)
Код
  PPAdvManager  = ^PAdvManager;
  PAdvManager   = ^TAdvManager;
  TAdvManager   = PACKED RECORD
    Dummy:            ARRAY [0..79] OF BYTE;
    RootDlgIdPtr:     PPINTEGER;
    CurrentDlgIdPtr:  PPINTEGER;
    (* Dummy *)
  END; // .RECORD TAdvManager


  AdvManagerPtr:  PPAdvManager  = Ptr($6992D0);


PROCEDURE GetGameState (OUT GameState: TGameState);
BEGIN
  IF AdvManagerPtr^.RootDlgIdPtr <> NIL THEN BEGIN
    GameState.RootDlgId :=  AdvManagerPtr^.RootDlgIdPtr^^;
  END // .IF
  ELSE BEGIN
    GameState.RootDlgId :=  0;
  END; // .ELSE
  IF AdvManagerPtr^.CurrentDlgIdPtr <> NIL THEN BEGIN
    GameState.CurrentDlgId  :=  AdvManagerPtr^.CurrentDlgIdPtr^^;
  END // .IF
  ELSE BEGIN
    GameState.CurrentDlgId  :=  0;
  END; // .ELSE
END; // .PROCEDURE GetDialogsIds

или же сразу
AlexSpl
У меня была такая идея. Но в Героях 2 недостаточно, чтобы int iDialogNestCount был равен 0. В игре мы же можем начинать различные диалоги, но игра же не прерывается.

Допустим, в Тройке этой информации достаточно. Как получить AdvManagerPtr^.RootDlgIdPtr^^ и AdvManagerPtr^.CurrentDlgIdPtr^^? И какие значения будут соответствовать тому факту, что игра не началась или уже закончилась?
AlexSpl
Может, я недостаточно чётко сформулировал проблему. После выбора карты, мы начинаем игру. После "Начать новую игру"/"Загрузить сейв"/победы/проигрыша игра заканчивается. Как определить, что мы [по-прежнему] здесь, а не [* карты больше нет и продолжить игру невозможно*] там?

Не знаю, как в Тройке, но в Двойке это большая проблема, т.к. все игровые структуры не реинициализируются, т.е. хранят данные последней игры, хотя карты уже нет и мы в меню.
feanor
Шестая ида умеет в экспорт структур в сишные хедеры, так что вот вам из вогобазы.
https://dl.dropboxusercontent.com/u/61759222/HoMM/Heroes3.h

Надо бы, конечно, стандартизировать структуры, хоть тему открывай..
Richter
У кого нибудь есть решение ввиде bin файла, либо dll файла или через ERM для отключения экрана Wog'ификации?

MasterOfPuppets
Сейчас нет игры под рукой, но можешь посмотреть патч в исходниках MoP: BIN-files, файл WoG-options.txt.
igrik
*.bin класть в "AfterWoG"
0071010F EB20
Barin
Поменять координаты здания в экране города сложно? Может уже есть алгоритм. Если не сложно, подскажите как это сделать.
igrik
Ты вообще темы по UN:C читаешь?
вот © feanor
Barin
Цитата(igrik @ 01 May 2017, 12:30) *
Ты вообще темы по UN:C читаешь?
вот © feanor


Хорошо, работает для объектов которые можно построить. А как определить подобные декоративные объекты непонятно:

Это деф анимированного водопада из Сопряжения. Его конечно же можно сделать прозрачным фоном, чтобы не отображался, но всё-таки, есть идея как его сместить?
igrik
Цитата(Barin @ 01 May 2017, 14:41) *
Хорошо, работает для объектов которые можно построить. А как определить подобные декоративные объекты непонятно:

Сначала проверь указанное, а потом говори что "непонятно". Откуда эта инфа, что можно менять только строящиеся объекты? Ты проверял? Конечно нет. Поэтому и не знаешь, что можно.
И в сотый раз тебе повторять уже надоело - есть специальные темы для обсуждений. А эти темы для чистой информации. Смекаешь?
feanor
Деревья строительства и маски заменяющих друг друга объектов, дамп


CODE
#define BLD_ID_MAGE1 0
#define BLD_ID_MAGE2 1
#define BLD_ID_MAGE3 2
#define BLD_ID_MAGE4 3
#define BLD_ID_MAGE5 4
#define BLD_ID_TAVERN 5
#define BLD_ID_WHARF 6
#define BLD_ID_FORT1 7
#define BLD_ID_FORT2 8
#define BLD_ID_FORT3 9
#define BLD_ID_HALL1 10
#define BLD_ID_HALL2 11
#define BLD_ID_HALL3 12
#define BLD_ID_HALL4 13
#define BLD_ID_MARKET 14
#define BLD_ID_SILO 15
#define BLD_ID_SMITH 16
#define BLD_ID_SPEC17 17
#define BLD_ID_HORDE1 18
#define BLD_ID_HORDE1U 19
#define BLD_ID_WHARF2 20
#define BLD_ID_SPEC21 21
#define BLD_ID_SPEC22 22
#define BLD_ID_SPEC23 23
#define BLD_ID_HORDE2 24
#define BLD_ID_HORDE2U 25
#define BLD_ID_GRAIL 26
#define BLD_ID_DECOR27 27
#define BLD_ID_DECOR28 28
#define BLD_ID_DECOR29 29
#define BLD_ID_DWELL1 30
#define BLD_ID_DWELL2 31
#define BLD_ID_DWELL3 32
#define BLD_ID_DWELL4 33
#define BLD_ID_DWELL5 34
#define BLD_ID_DWELL6 35
#define BLD_ID_DWELL7 36
#define BLD_ID_DWELL1U 37
#define BLD_ID_DWELL2U 38
#define BLD_ID_DWELL3U 39
#define BLD_ID_DWELL4U 40
#define BLD_ID_DWELL5U 41
#define BLD_ID_DWELL6U 42
#define BLD_ID_DWELL7U 43

int Dependencies0[] = {
BLD_ID_MAGE1, -1,
BLD_ID_MAGE2, BLD_ID_MAGE1, -1,
BLD_ID_MAGE3, BLD_ID_MAGE2, -1,
BLD_ID_MAGE4, BLD_ID_MAGE3, -1,
BLD_ID_WHARF, -1,
BLD_ID_TAVERN, -1,
BLD_ID_SPEC22, BLD_ID_TAVERN, -1,
BLD_ID_MARKET, -1,
BLD_ID_SILO, BLD_ID_MARKET, -1,
BLD_ID_SMITH, -1,
BLD_ID_SPEC17, BLD_ID_WHARF, -1,
BLD_ID_FORT1, -1,
BLD_ID_FORT2, BLD_ID_FORT1, -1,
BLD_ID_FORT3, BLD_ID_FORT2, -1,
BLD_ID_HALL2, BLD_ID_TAVERN, -1,
BLD_ID_HALL3, BLD_ID_HALL2, BLD_ID_SMITH, BLD_ID_MAGE1, BLD_ID_MARKET, -1,
BLD_ID_HALL4, BLD_ID_HALL3, BLD_ID_FORT3, -1,
BLD_ID_DWELL1, BLD_ID_FORT1, -1,
BLD_ID_DWELL1U, BLD_ID_DWELL1, -1,
BLD_ID_DWELL2, BLD_ID_DWELL1, -1,
BLD_ID_DWELL2U, BLD_ID_DWELL2, -1,
BLD_ID_DWELL4, BLD_ID_DWELL1, BLD_ID_SMITH, -1,
BLD_ID_DWELL4U, BLD_ID_DWELL4, -1,
BLD_ID_DWELL3, BLD_ID_DWELL4, -1,
BLD_ID_HORDE1, BLD_ID_DWELL3, -1,
BLD_ID_DWELL3U, BLD_ID_DWELL3, -1,
BLD_ID_HORDE1U, BLD_ID_DWELL3U, -1,
BLD_ID_SPEC21, BLD_ID_DWELL4, -1,
BLD_ID_DWELL6, BLD_ID_SPEC21, -1,
BLD_ID_DWELL6U, BLD_ID_DWELL6, -1,
BLD_ID_DWELL5, BLD_ID_DWELL4, BLD_ID_MAGE1, -1,
BLD_ID_DWELL5U, BLD_ID_DWELL5, -1,
BLD_ID_DWELL7, BLD_ID_DWELL5, -1,
BLD_ID_DWELL7U, BLD_ID_DWELL7, -1,
BLD_ID_GRAIL, -1,
-100
};


int Dependencies1[] = {
BLD_ID_FORT1, -1,
BLD_ID_FORT2, BLD_ID_FORT1, -1,
BLD_ID_FORT3, BLD_ID_FORT2, -1,
BLD_ID_TAVERN, -1,
BLD_ID_SMITH, -1,
BLD_ID_MARKET, -1,
BLD_ID_SILO, BLD_ID_MARKET, -1,
BLD_ID_MAGE1, -1,
BLD_ID_MAGE2, BLD_ID_MAGE1, -1,
BLD_ID_MAGE3, BLD_ID_MAGE2, -1,
BLD_ID_MAGE4, BLD_ID_MAGE3, -1,
BLD_ID_MAGE5, BLD_ID_MAGE4, -1,
BLD_ID_SPEC17, -1,
BLD_ID_SPEC21, BLD_ID_SPEC17, -1,
BLD_ID_HALL2, BLD_ID_TAVERN, -1,
BLD_ID_HALL3, BLD_ID_HALL2, BLD_ID_MAGE1, BLD_ID_SMITH, BLD_ID_MARKET, -1,
BLD_ID_HALL4, BLD_ID_HALL3, BLD_ID_FORT3, -1,
BLD_ID_DWELL1, BLD_ID_FORT1, -1,
BLD_ID_DWELL1U, BLD_ID_DWELL1, -1,
BLD_ID_DWELL2, BLD_ID_DWELL1, -1,
BLD_ID_HORDE1, BLD_ID_DWELL2, -1,
BLD_ID_SPEC22, BLD_ID_HORDE1, -1,
BLD_ID_DWELL2U, BLD_ID_DWELL2, -1,
BLD_ID_HORDE1U, BLD_ID_DWELL2U, -1,
BLD_ID_DWELL3, BLD_ID_DWELL1, -1,
BLD_ID_DWELL3U, BLD_ID_DWELL3, -1,
BLD_ID_DWELL5, BLD_ID_DWELL3, -1,
BLD_ID_HORDE2, BLD_ID_DWELL5, -1,
BLD_ID_DWELL5U, BLD_ID_DWELL5, -1,
BLD_ID_HORDE2U, BLD_ID_DWELL5U, -1,
BLD_ID_DWELL4, BLD_ID_DWELL3, -1,
BLD_ID_DWELL4U, BLD_ID_DWELL4, -1,
BLD_ID_DWELL6, BLD_ID_DWELL4, BLD_ID_DWELL5, -1,
BLD_ID_DWELL6U, BLD_ID_DWELL6, -1,
BLD_ID_DWELL7, BLD_ID_DWELL6, BLD_ID_MAGE2, -1,
BLD_ID_DWELL7U, BLD_ID_DWELL7, BLD_ID_MAGE3, -1,
BLD_ID_GRAIL, -1,
-100
};


int Dependencies2[] = {
BLD_ID_FORT1, -1,
BLD_ID_SPEC21, BLD_ID_FORT1, -1,
BLD_ID_FORT2, BLD_ID_FORT1, -1,
BLD_ID_FORT3, BLD_ID_FORT2, -1,
BLD_ID_MAGE1, -1,
BLD_ID_SPEC22, BLD_ID_MAGE1, -1,
BLD_ID_SPEC23, BLD_ID_MAGE1, -1,
BLD_ID_MAGE2, BLD_ID_MAGE1, -1,
BLD_ID_MAGE3, BLD_ID_MAGE2, -1,
BLD_ID_MAGE4, BLD_ID_MAGE3, -1,
BLD_ID_MAGE5, BLD_ID_MAGE4, -1,
BLD_ID_TAVERN, -1,
BLD_ID_SMITH, -1,
BLD_ID_MARKET, -1,
BLD_ID_SILO, BLD_ID_MARKET, -1,
BLD_ID_SPEC17, BLD_ID_MARKET, -1,
BLD_ID_HALL2, BLD_ID_TAVERN, -1,
BLD_ID_HALL3, BLD_ID_HALL2, BLD_ID_MARKET, BLD_ID_SMITH, BLD_ID_MAGE1, -1,
BLD_ID_HALL4, BLD_ID_HALL3, BLD_ID_FORT3, -1,
BLD_ID_DWELL1, BLD_ID_FORT1, -1,
BLD_ID_DWELL1U, BLD_ID_DWELL1, -1,
BLD_ID_DWELL2, BLD_ID_DWELL1, -1,
BLD_ID_HORDE1, BLD_ID_DWELL2, -1,
BLD_ID_DWELL2U, BLD_ID_DWELL2, -1,
BLD_ID_HORDE1U, BLD_ID_DWELL2U, -1,
BLD_ID_DWELL3, BLD_ID_DWELL1, -1,
BLD_ID_DWELL3U, BLD_ID_DWELL3, -1,
BLD_ID_DWELL4, BLD_ID_DWELL2, BLD_ID_DWELL3, BLD_ID_MAGE1, -1,
BLD_ID_DWELL4U, BLD_ID_DWELL4, BLD_ID_SPEC22, -1,
BLD_ID_DWELL5, BLD_ID_DWELL4, -1,
BLD_ID_DWELL5U, BLD_ID_DWELL5, -1,
BLD_ID_DWELL6, BLD_ID_DWELL4, -1,
BLD_ID_DWELL6U, BLD_ID_DWELL6, -1,
BLD_ID_DWELL7, BLD_ID_DWELL5, BLD_ID_DWELL6, -1,
BLD_ID_DWELL7U, BLD_ID_DWELL7, -1,
BLD_ID_GRAIL, -1,
-100
};


int Dependencies3[] = {
BLD_ID_FORT1, -1,
BLD_ID_SPEC21, BLD_ID_FORT1, -1,
BLD_ID_FORT2, BLD_ID_FORT1, -1,
BLD_ID_SPEC22, BLD_ID_FORT2, -1,
BLD_ID_FORT3, BLD_ID_FORT2, -1,
BLD_ID_TAVERN, -1,
BLD_ID_SMITH, -1,
BLD_ID_MARKET, -1,
BLD_ID_SILO, BLD_ID_MARKET, -1,
BLD_ID_MAGE1, -1,
BLD_ID_SPEC23, BLD_ID_MAGE1, -1,
BLD_ID_MAGE2, BLD_ID_MAGE1, -1,
BLD_ID_MAGE3, BLD_ID_MAGE2, -1,
BLD_ID_MAGE4, BLD_ID_MAGE3, -1,
BLD_ID_MAGE5, BLD_ID_MAGE4, -1,
BLD_ID_HALL2, BLD_ID_TAVERN, -1,
BLD_ID_HALL3, BLD_ID_HALL2, BLD_ID_SMITH, BLD_ID_MARKET, BLD_ID_MAGE1, -1,
BLD_ID_HALL4, BLD_ID_HALL3, BLD_ID_FORT3, -1,
BLD_ID_DWELL1, BLD_ID_FORT1, -1,
BLD_ID_HORDE1, BLD_ID_DWELL1, -1,
BLD_ID_DWELL1U, BLD_ID_DWELL1, -1,
BLD_ID_HORDE1U, BLD_ID_DWELL1U, -1,
BLD_ID_DWELL3, BLD_ID_DWELL1, -1,
BLD_ID_HORDE2, BLD_ID_DWELL3, -1,
BLD_ID_DWELL3U, BLD_ID_DWELL3, -1,
BLD_ID_HORDE2U, BLD_ID_DWELL3U, -1,
BLD_ID_DWELL2, BLD_ID_DWELL1, -1,
BLD_ID_DWELL2U, BLD_ID_DWELL2, -1,
BLD_ID_DWELL4, BLD_ID_DWELL2, -1,
BLD_ID_DWELL4U, BLD_ID_DWELL4, -1,
BLD_ID_DWELL6, BLD_ID_DWELL4, BLD_ID_MAGE1, -1,
BLD_ID_DWELL6U, BLD_ID_DWELL6, -1,
BLD_ID_DWELL5, BLD_ID_DWELL4, -1,
BLD_ID_DWELL5U, BLD_ID_DWELL5, BLD_ID_MAGE2, -1,
BLD_ID_DWELL7, BLD_ID_DWELL5, BLD_ID_DWELL6, -1,
BLD_ID_DWELL7U, BLD_ID_DWELL7, -1,
BLD_ID_GRAIL, -1,
-100
};


int Dependencies4[] = {
BLD_ID_FORT1, -1,
BLD_ID_SPEC17, BLD_ID_FORT1, -1,
BLD_ID_FORT2, BLD_ID_FORT1, -1,
BLD_ID_FORT3, BLD_ID_FORT2, -1,
BLD_ID_TAVERN, -1,
BLD_ID_SMITH, -1,
BLD_ID_MARKET, -1,
BLD_ID_SILO, BLD_ID_MARKET, -1,
BLD_ID_WHARF, -1,
BLD_ID_MAGE1, -1,
BLD_ID_SPEC21, BLD_ID_MAGE1, -1,
BLD_ID_MAGE2, BLD_ID_MAGE1, -1,
BLD_ID_MAGE3, BLD_ID_MAGE2, -1,
BLD_ID_MAGE4, BLD_ID_MAGE3, -1,
BLD_ID_MAGE5, BLD_ID_MAGE4, -1,
BLD_ID_HALL2, BLD_ID_TAVERN, -1,
BLD_ID_HALL3, BLD_ID_HALL2, BLD_ID_MARKET, BLD_ID_SMITH, BLD_ID_MAGE1, -1,
BLD_ID_HALL4, BLD_ID_HALL3, BLD_ID_FORT3, -1,
BLD_ID_DWELL1, BLD_ID_FORT1, -1,
BLD_ID_SPEC22, BLD_ID_DWELL1, -1,
BLD_ID_HORDE1, BLD_ID_SPEC22, -1,
BLD_ID_DWELL1U, BLD_ID_DWELL1, -1,
BLD_ID_HORDE1U, BLD_ID_DWELL1U, BLD_ID_SPEC22, -1,
BLD_ID_DWELL3, BLD_ID_DWELL1, -1,
BLD_ID_DWELL3U, BLD_ID_DWELL3, -1,
BLD_ID_DWELL2, BLD_ID_DWELL1, -1,
BLD_ID_DWELL2U, BLD_ID_DWELL2, -1,
BLD_ID_DWELL4, BLD_ID_DWELL2, -1,
BLD_ID_DWELL4U, BLD_ID_DWELL4, BLD_ID_SPEC21, -1,
BLD_ID_DWELL5, BLD_ID_DWELL2, BLD_ID_MAGE1, -1,
BLD_ID_DWELL5U, BLD_ID_DWELL5, -1,
BLD_ID_DWELL6, BLD_ID_DWELL4, BLD_ID_DWELL5, -1,
BLD_ID_DWELL6U, BLD_ID_DWELL6, -1,
BLD_ID_DWELL7, BLD_ID_DWELL6, -1,
BLD_ID_DWELL7U, BLD_ID_DWELL7, -1,
BLD_ID_GRAIL, -1,
-100
};


int Dependencies5[] = {
BLD_ID_FORT1, -1,
BLD_ID_FORT2, BLD_ID_FORT1, -1,
BLD_ID_FORT3, BLD_ID_FORT2, -1,
BLD_ID_SPEC22, -1,
BLD_ID_SPEC23, -1,
BLD_ID_TAVERN, -1,
BLD_ID_SMITH, -1,
BLD_ID_MARKET, -1,
BLD_ID_SILO, BLD_ID_MARKET, -1,
BLD_ID_SPEC17, BLD_ID_MARKET, -1,
BLD_ID_MAGE1, -1,
BLD_ID_SPEC21, BLD_ID_MAGE1, -1,
BLD_ID_MAGE2, BLD_ID_MAGE1, -1,
BLD_ID_MAGE3, BLD_ID_MAGE2, -1,
BLD_ID_MAGE4, BLD_ID_MAGE3, -1,
BLD_ID_MAGE5, BLD_ID_MAGE4, -1,
BLD_ID_HALL2, BLD_ID_TAVERN, -1,
BLD_ID_HALL3, BLD_ID_HALL2, BLD_ID_SMITH, BLD_ID_MARKET, BLD_ID_MAGE1, -1,
BLD_ID_HALL4, BLD_ID_HALL3, BLD_ID_FORT3, -1,
BLD_ID_DWELL1, BLD_ID_FORT1, -1,
BLD_ID_HORDE1, BLD_ID_DWELL1, -1,
BLD_ID_DWELL1U, BLD_ID_DWELL1, -1,
BLD_ID_HORDE1U, BLD_ID_DWELL1U, -1,
BLD_ID_DWELL3, BLD_ID_DWELL1, -1,
BLD_ID_DWELL3U, BLD_ID_DWELL3, -1,
BLD_ID_DWELL2, BLD_ID_DWELL1, -1,
BLD_ID_DWELL2U, BLD_ID_DWELL2, -1,
BLD_ID_DWELL4, BLD_ID_DWELL3, BLD_ID_DWELL2, -1,
BLD_ID_DWELL4U, BLD_ID_DWELL4, -1,
BLD_ID_DWELL5, BLD_ID_DWELL4, -1,
BLD_ID_DWELL5U, BLD_ID_DWELL5, -1,
BLD_ID_DWELL6, BLD_ID_DWELL4, -1,
BLD_ID_DWELL6U, BLD_ID_DWELL6, -1,
BLD_ID_DWELL7, BLD_ID_DWELL5, BLD_ID_DWELL6, BLD_ID_MAGE2, -1,
BLD_ID_DWELL7U, BLD_ID_DWELL7, BLD_ID_MAGE3, -1,
BLD_ID_GRAIL, -1,
-100
};


int Dependencies6[] = {
BLD_ID_FORT1, -1,
BLD_ID_SPEC17, BLD_ID_FORT1, -1,
BLD_ID_SPEC23, BLD_ID_FORT1, -1,
BLD_ID_FORT2, BLD_ID_FORT1, -1,
BLD_ID_FORT3, BLD_ID_FORT2, -1,
BLD_ID_TAVERN, -1,
BLD_ID_SMITH, -1,
BLD_ID_SPEC22, BLD_ID_SMITH, -1,
BLD_ID_MARKET, -1,
BLD_ID_SILO, BLD_ID_MARKET, -1,
BLD_ID_SPEC21, BLD_ID_MARKET, -1,
BLD_ID_MAGE1, -1,
BLD_ID_MAGE2, BLD_ID_MAGE1, -1,
BLD_ID_MAGE3, BLD_ID_MAGE2, -1,
BLD_ID_HALL2, BLD_ID_TAVERN, -1,
BLD_ID_HALL3, BLD_ID_HALL2, BLD_ID_MAGE1, BLD_ID_MARKET, BLD_ID_SMITH, -1,
BLD_ID_HALL4, BLD_ID_HALL3, BLD_ID_FORT3, -1,
BLD_ID_DWELL1, BLD_ID_FORT1, -1,
BLD_ID_HORDE1, BLD_ID_DWELL1, -1,
BLD_ID_DWELL1U, BLD_ID_DWELL1, -1,
BLD_ID_HORDE1U, BLD_ID_DWELL1U, -1,
BLD_ID_DWELL2, BLD_ID_DWELL1, -1,
BLD_ID_DWELL2U, BLD_ID_DWELL2, BLD_ID_DWELL1U, -1,
BLD_ID_DWELL5, BLD_ID_DWELL2, -1,
BLD_ID_DWELL5U, BLD_ID_DWELL5, -1,
BLD_ID_DWELL7, BLD_ID_DWELL5, -1,
BLD_ID_DWELL7U, BLD_ID_DWELL7, -1,
BLD_ID_DWELL3, BLD_ID_DWELL1, -1,
BLD_ID_DWELL3U, BLD_ID_DWELL3, BLD_ID_SMITH, -1,
BLD_ID_DWELL4, BLD_ID_DWELL3, -1,
BLD_ID_DWELL4U, BLD_ID_DWELL4, BLD_ID_MAGE1, -1,
BLD_ID_DWELL6, BLD_ID_DWELL4, -1,
BLD_ID_DWELL6U, BLD_ID_DWELL6, -1,
BLD_ID_GRAIL, -1,
-100
};


int Dependencies7[] = {
BLD_ID_FORT1, -1,
BLD_ID_SPEC21, BLD_ID_FORT1, -1,
BLD_ID_SPEC22, BLD_ID_SPEC21, -1,
BLD_ID_FORT2, BLD_ID_FORT1, -1,
BLD_ID_FORT3, BLD_ID_FORT2, -1,
BLD_ID_TAVERN, -1,
BLD_ID_SMITH, -1,
BLD_ID_MARKET, -1,
BLD_ID_SILO, BLD_ID_MARKET, -1,
BLD_ID_MAGE1, -1,
BLD_ID_MAGE2, BLD_ID_MAGE1, -1,
BLD_ID_MAGE3, BLD_ID_MAGE2, -1,
BLD_ID_HALL2, BLD_ID_TAVERN, -1,
BLD_ID_SPEC17, BLD_ID_HALL2, BLD_ID_SPEC21, -1,
BLD_ID_HALL3, BLD_ID_HALL2, BLD_ID_MARKET, BLD_ID_SMITH, BLD_ID_MAGE1, -1,
BLD_ID_WHARF, -1,
BLD_ID_HALL4, BLD_ID_HALL3, BLD_ID_FORT3, -1,
BLD_ID_DWELL1, BLD_ID_FORT1, -1,
BLD_ID_HORDE1, BLD_ID_DWELL1, -1,
BLD_ID_DWELL1U, BLD_ID_DWELL1, BLD_ID_TAVERN, -1,
BLD_ID_HORDE1U, BLD_ID_DWELL1U, -1,
BLD_ID_DWELL2, BLD_ID_DWELL1, -1,
BLD_ID_DWELL2U, BLD_ID_DWELL2, -1,
BLD_ID_DWELL6, BLD_ID_DWELL2, -1,
BLD_ID_DWELL6U, BLD_ID_DWELL6, -1,
BLD_ID_DWELL3, BLD_ID_DWELL1, -1,
BLD_ID_DWELL3U, BLD_ID_DWELL3, -1,
BLD_ID_DWELL4, BLD_ID_DWELL3, -1,
BLD_ID_DWELL4U, BLD_ID_DWELL4, -1,
BLD_ID_DWELL5, BLD_ID_DWELL3, BLD_ID_DWELL2, -1,
BLD_ID_DWELL5U, BLD_ID_DWELL5, BLD_ID_SILO, -1,
BLD_ID_DWELL7, BLD_ID_DWELL6, BLD_ID_DWELL4, -1,
BLD_ID_DWELL7U, BLD_ID_DWELL7, -1,
BLD_ID_GRAIL, -1,
-100
};


int Dependencies8[] = {
BLD_ID_FORT1, -1,
BLD_ID_FORT2, BLD_ID_FORT1, -1,
BLD_ID_FORT3, BLD_ID_FORT2, -1,
BLD_ID_WHARF, -1,
BLD_ID_TAVERN, -1,
BLD_ID_SMITH, -1,
BLD_ID_MARKET, -1,
BLD_ID_SILO, BLD_ID_MARKET, -1,
BLD_ID_SPEC17, BLD_ID_MARKET, -1,
BLD_ID_MAGE1, -1,
BLD_ID_MAGE2, BLD_ID_MAGE1, -1,
BLD_ID_MAGE3, BLD_ID_MAGE2, -1,
BLD_ID_MAGE4, BLD_ID_MAGE3, -1,
BLD_ID_MAGE5, BLD_ID_MAGE4, -1,
BLD_ID_SPEC21, BLD_ID_MAGE1, -1,
BLD_ID_HALL2, BLD_ID_TAVERN, -1,
BLD_ID_HALL3, BLD_ID_HALL2, BLD_ID_MARKET, BLD_ID_SMITH, BLD_ID_MAGE1, -1,
BLD_ID_HALL4, BLD_ID_HALL3, BLD_ID_FORT3, -1,
BLD_ID_DWELL1, BLD_ID_FORT1, -1,
BLD_ID_HORDE1, BLD_ID_DWELL1, -1,
BLD_ID_DWELL1U, BLD_ID_DWELL1, -1,
BLD_ID_HORDE1U, BLD_ID_DWELL1U, -1,
BLD_ID_DWELL2, BLD_ID_DWELL1, BLD_ID_MAGE1, -1,
BLD_ID_DWELL2U, BLD_ID_DWELL2, -1,
BLD_ID_DWELL3, BLD_ID_DWELL1, BLD_ID_MAGE1, -1,
BLD_ID_DWELL3U, BLD_ID_DWELL3, -1,
BLD_ID_DWELL4, BLD_ID_DWELL2, -1,
BLD_ID_DWELL4U, BLD_ID_DWELL4, BLD_ID_DWELL2U, -1,
BLD_ID_DWELL5, BLD_ID_DWELL3, -1,
BLD_ID_DWELL5U, BLD_ID_DWELL5, -1,
BLD_ID_DWELL6, BLD_ID_DWELL4, BLD_ID_DWELL5, -1,
BLD_ID_DWELL6U, BLD_ID_DWELL6, BLD_ID_MAGE2, -1,
BLD_ID_DWELL7, BLD_ID_DWELL6, -1,
BLD_ID_DWELL7U, BLD_ID_DWELL7, -1,
BLD_ID_GRAIL, -1,
-100
};


int ObsolutionsAll[] = {
BLD_ID_MAGE2, BLD_ID_MAGE1, -1,
BLD_ID_MAGE3, BLD_ID_MAGE2, -1,
BLD_ID_MAGE4, BLD_ID_MAGE3, -1,
BLD_ID_MAGE5, BLD_ID_MAGE4, -1,
BLD_ID_FORT2, BLD_ID_FORT1, -1,
BLD_ID_FORT3, BLD_ID_FORT2, -1,
BLD_ID_HALL2, BLD_ID_HALL1, -1,
BLD_ID_HALL3, BLD_ID_HALL2, -1,
BLD_ID_HALL4, BLD_ID_HALL3, -1,
BLD_ID_HORDE1U, BLD_ID_HORDE1, -1,
BLD_ID_HORDE2U, BLD_ID_HORDE2, -1,
BLD_ID_DWELL1U, BLD_ID_DWELL1, -1,
BLD_ID_DWELL2U, BLD_ID_DWELL2, -1,
BLD_ID_DWELL3U, BLD_ID_DWELL3, -1,
BLD_ID_DWELL4U, BLD_ID_DWELL4, -1,
BLD_ID_DWELL5U, BLD_ID_DWELL5, -1,
BLD_ID_DWELL6U, BLD_ID_DWELL6, -1,
BLD_ID_DWELL7U, BLD_ID_DWELL7, -1,
-100
};


int Obsolutions0[] = {
BLD_ID_SPEC22, BLD_ID_TAVERN, -1,
BLD_ID_HORDE1, BLD_ID_DWELL3, -1,
BLD_ID_HORDE1U, BLD_ID_DWELL3U, BLD_ID_HORDE1, -1,
-100
};


int Obsolutions1[] = {
BLD_ID_HORDE1, BLD_ID_DWELL2, -1,
BLD_ID_HORDE1U, BLD_ID_DWELL2U, BLD_ID_HORDE1, -1,
BLD_ID_HORDE2, BLD_ID_DWELL5, -1,
BLD_ID_HORDE2U, BLD_ID_DWELL5U, BLD_ID_HORDE2, -1,
BLD_ID_SPEC21, BLD_ID_SPEC17, -1,
-100
};


int Obsolutions2[] = {
BLD_ID_HORDE1, BLD_ID_DWELL2, -1,
BLD_ID_HORDE1U, BLD_ID_DWELL2U, BLD_ID_HORDE1, -1,
-100
};


int Obsolutions3[] = {
BLD_ID_HORDE1, BLD_ID_DWELL1, -1,
BLD_ID_HORDE1U, BLD_ID_DWELL1U, BLD_ID_HORDE1, -1,
BLD_ID_HORDE2, BLD_ID_DWELL3, -1,
BLD_ID_HORDE2U, BLD_ID_DWELL3U, BLD_ID_HORDE2, -1,
-100
};


int Obsolutions4[] = {
BLD_ID_HORDE1, BLD_ID_DWELL1, -1,
BLD_ID_HORDE1U, BLD_ID_DWELL1U, BLD_ID_HORDE1, -1,
-100
};


int Obsolutions5[] = {
BLD_ID_HORDE1, BLD_ID_DWELL1, -1,
BLD_ID_HORDE1U, BLD_ID_DWELL1U, BLD_ID_HORDE1, -1,
-100
};


int Obsolutions6[] = {
BLD_ID_HORDE1, BLD_ID_DWELL1, -1,
BLD_ID_HORDE1U, BLD_ID_DWELL1U, BLD_ID_HORDE1, -1,
-100
};


int Obsolutions7[] = {
BLD_ID_HORDE1, BLD_ID_DWELL1, -1,
BLD_ID_HORDE1U, BLD_ID_DWELL1U, BLD_ID_HORDE1, -1,
-100
};


int Obsolutions8[] = {
BLD_ID_HORDE1, BLD_ID_DWELL1, -1,
BLD_ID_HORDE1U, BLD_ID_DWELL1U, BLD_ID_HORDE1, -1,
-100
};

//патчим буквально сразу в DllMain, иначе данные уйдут в битовое поле
*(int*)0x004EB816 = (int)Dependencies0;

*(int*)0x004EB8B3 = (int)Dependencies1;

*(int*)0x004EB971 = (int)Dependencies2;

*(int*)0x004EBA39 = (int)Dependencies3;

*(int*)0x004EBA48 = (int)Dependencies4;

*(int*)0x004EBA5C = (int)Dependencies5;

*(int*)0x004EBA70 = (int)Dependencies6;

*(int*)0x004EBA84 = (int)Dependencies7;

*(int*)0x004EBA98 = (int)Dependencies8;

*(int*)0x004EBAC9 = (int)ObsolutionsAll;
*(int*)0x004EBB04 = (int)ObsolutionsAll;
*(int*)0x004EBB3F = (int)ObsolutionsAll;
*(int*)0x004EBB7A = (int)ObsolutionsAll;
*(int*)0x004EBC74 = (int)ObsolutionsAll;

*(int*)0x004EBAD8 = (int)Obsolutions0;

*(int*)0x004EBB13 = (int)Obsolutions1;

*(int*)0x004EBB89 = (int)Obsolutions2;

*(int*)0x004EBB4E = (int)Obsolutions3;

*(int*)0x004EBB98 = (int)Obsolutions4;

*(int*)0x004EBBA7 = (int)Obsolutions5;

*(int*)0x004EBBB6 = (int)Obsolutions6;

*(int*)0x004EBBC5 = (int)Obsolutions7;

*(int*)0x004EBBD4 = (int)Obsolutions8;

Экраны холла будут когда-нибудь позже

Ну и порождающий это говнокод, потому что писать программы, чтобы они писали программы - это весело, а еще так можно убить свою профессию с её рабочим местом

CODE

string GetDescByID(int id)
{
if(id ==-1) return "-1";
if(id ==-100) return "-100";

string[] arr =
{
"MAGE1",
"MAGE2",
"MAGE3",
"MAGE4",
"MAGE5",

"TAVERN", //5

"WHARF", //6

"FORT1", //7
"FORT2",
"FORT3",

"HALL1", //10
"HALL2",
"HALL3",
"HALL4",

"MARKET", //14
"SILO",

"SMITH", //16

"SPEC17",

"HORDE1", //18
"HORDE1U",

"WHARF2", //20
"SPEC21",
"SPEC22",
"SPEC23",

"HORDE2",
"HORDE2U",

"GRAIL",

"DECOR27",
"DECOR28",
"DECOR29",

"DWELL1",
"DWELL2",
"DWELL3",
"DWELL4",
"DWELL5",
"DWELL6",
"DWELL7",

"DWELL1U",
"DWELL2U",
"DWELL3U",
"DWELL4U",
"DWELL5U",
"DWELL6U",
"DWELL7U"
};

return "BLD_ID_"+arr[id];
}


int ReadInt(byte[] arr, ref int offset)
{
int ret = arr[offset] | arr[offset+1] << 8 | arr[offset+2] << 16 | arr[offset+3]<<24;
offset+=4;
return ret;
}

List<int> FindRefs(byte[] arr, int addr)
{
List<int> ret = new List<int>();
for(int i =0; i!=arr.Length-3; i++)
{
if((arr[i] == (addr & 0xFF)) &&
(arr[i+1] == ((addr>>8) & 0xFF)) &&
(arr[i+2] == ((addr>>16) & 0xFF)) &&
(arr[i+3] == ((addr>>24) & 0xFF)))
{
ret.Add(i+0x400000);
}

}
return ret;
}


string ProduceTable(byte[] file, int tree_offset, string name)
{
int v_tree_offset = tree_offset- 0x400000;


string s = "";
s += "\r\n";
s += "int "+name+"[] = {\r\n";

int i = 0;
do
{
i = ReadInt(file,ref v_tree_offset);
s += '\t';
s += GetDescByID(i);


if(i!=-100) s += ",";
if(i<0) s += Environment.NewLine;


}while( i != -100);
s += "};";
s += "\r\n";
return s;
}


string ProduceHooks(byte[] file, int tree_offset, string name)
{
string t = "\r\n";
foreach(int refaddr in FindRefs(file,tree_offset))
{

t+= string.Format("*(int*)0x{0:X8} = (int){1};\r\n", refaddr, name);
}
return t;
}

void MainFormLoad(object sender, EventArgs e)
{
var file = File.ReadAllBytes(@"d:\\h3era24\\h3era.exe");


string[] names = {
"Dependencies0",
"Dependencies1",
"Dependencies2",
"Dependencies3",
"Dependencies4",
"Dependencies5",
"Dependencies6",
"Dependencies7",
"Dependencies8",
"ObsolutionsAll",
"Obsolutions0",
"Obsolutions1",
"Obsolutions2",
"Obsolutions3",
"Obsolutions4",
"Obsolutions5",
"Obsolutions6",
"Obsolutions7",
"Obsolutions8"
};


int[] addrs =
{
0x63EC80,
0x63EE24,
0x63EFE4,
0x63F1A0,
0x63F364,
0x63F51C,
0x63F6D0,
0x63F870,
0x63FA14,
0x63FBC4,
0x63FCA0,
0x63FCCC,
0x63FD14,
0x63FD34,
0x63FD70,
0x63FD90,
0x63FDB0,
0x63FDD0,
0x63FDF0
};

for(int j=0; j!=44; j++)
{
textBox1.Text += string.Format("#define\t{0}\t{1}\r\n",GetDescByID(j),j);
}

for(int j = 0; j!=19; j++)
{
textBox1.Text += ProduceTable(file,addrs[j], names[j]);
textBox1.Text +=Environment.NewLine;
}
for(int j = 0; j!=19; j++)
{
textBox1.Text += ProduceHooks(file,addrs[j], names[j]);
}


}
Ben
Поисследовал, как изменить коэффициент первичного навыка защиты.
По ряду соображений хочется сделать его не 2,5%, а 3,5% - снижение ущерба от атаки.

В воговской базе соответствующих комментариев нет.

Обнаружилось, что коэффициент 0.025 нужно менять по адресу 0x0063B8C0

Ограничение на общее снижение ущерба (сейчас 70%) правится по адресу 0x0063B8B8.
Величину 0.3 меняю на 0.2

Дополнительно это дело захардкожено в одной процедуре (2 ассемблерных мува со значениями).
Нужно поправить значения в 0x00443913 и 0x00443918
Richter
Образовался вопрос, где хранится статус "выбрано существо или нет" и как его убрать (жёлтая рамка) в окне героя? Надеюсь с темой для поста не ошибся)
igrik
Цитата(Richter @ 18 Jan 2019, 10:18) *
Образовался вопрос, где хранится статус "выбрано существо или нет" и как его убрать (жёлтая рамка) в окне героя? Надеюсь с темой для поста не ошибся)

!!UN:C6911880/4/?y1;
Richter
Понимаю тема не для вопросов, однако такой вопрос не нашёл более где задать. Появилась необходимость в использовании свободных адресов в exe. Какие диапазоны могу использовать, чтобы не нарушить код после запуска и во время игры?
Необходимо 3800 адресов.
Вот пример:
Код
008CA2E0    0000            ADD BYTE PTR DS:[EAX],AL
008CA2E2    0000            ADD BYTE PTR DS:[EAX],AL
008CA2E4    0000            ADD BYTE PTR DS:[EAX],AL
008CA2E6    0000            ADD BYTE PTR DS:[EAX],AL
..................
00639D55      00            DB 00
00639D56      00            DB 00
00639D57      00            DB 00
00639D58      00            DB 00
MasterOfPuppets
Зачем?
XEPOMAHT
Цитата(Richter @ 27 Jan 2019, 09:46) *
Какие диапазоны могу использовать, чтобы не нарушить код после запуска и во время игры?


Все секции памяти используются геройским кодом. В конце воговской секции вроде бы был неиспользованный копеечный участок, но и туда бездумно лезть - тоже извращенство.

Цитата(Richter @ 27 Jan 2019, 09:46) *
Необходимо 3800 адресов.


Разве проблема создать *.dll под ЭРА и выделить нужное количество памяти под собственные нужды? Либо в самой ЭРЕ слишком сложно использовать SN:M? Опять придумываете велосипед вместе того, чтобы использовать проверенное временем.
Richter
Цитата(XEPOMAHT @ 27 Jan 2019, 13:05) *
Все секции памяти используются геройским кодом. В конце воговской секции вроде бы был неиспользованный копеечный участок, но и туда бездумно лезть - тоже извращенство.
То, есть такие нельзя использовать:
00639D55 00 DB 00
00639D58 00 DB 00 ...?
Цитата(XEPOMAHT @ 27 Jan 2019, 13:05) *
Разве проблема создать *.dll под ЭРА и выделить нужное количество памяти под собственные нужды? Либо в самой ЭРЕ слишком сложно использовать SN:M? Опять придумываете велосипед вместе того, чтобы использовать проверенное временем.

Повторюсь, не являюсь программистом, поэтому dll = проблема. Если не трудно создайте адресов на 80 тыс. Мне это поможет. Может ещё кому пригодится.
На счет SN:M не понятно как она поможет в добавлении кода.
Код
Работа с дополнительной памятью ↑
Описание ^
!!SN:M[...];

ЕРМ переменные статичны и ограничены в количестве. Статичность приводит к невозможности организовывать динамические структуры данных (например, списки), для которых нужны функции выделения и освобождения памяти, а ограниченное количество ведёт к необходимости строгого учёта индексов без возможности выйти за их пределы. Более того, ЕРМ строки в виде z-переменных занимают ровно 512 байт каждая в независимости от размера их содержимого. Эра предоставляет программисту до 2 млрд. слотов под массивы новых переменных (числовых или строковых). Размер массивов может изменяться средствами ЕРМ. Поскольку работа с динамическими структурами предполагает автоматическое выделение номеров слотов, то такая возможность присутствует. Слоты с положительными индексами принадлежат пользователю, а с отрицательными используются при автовыделении памяти.



Удаление слота памяти ^
!!SN:M[номер слота, начиная с 0];

Пример:

!!SN:M5; удалить слот 5

Получение/установка размера слота ^
!!SN:M[номер слота]/[?][количество элементов];

Размер слота — это количество элементов в массиве. Команда возвращает -1, если слот не существует.

Пример:

!!SN:M2/5; установить количество элементов в слоте 2 равное 5. !!SN:My1/?y2; получить размер слота y1 в переменную y2.

Работа со значениями элементов слотов ^
!!SN:M[номер слота]/[номер элемента, начиная с 0]/[?][значение];

Пример:

!!SN:M1/3; размер слота 1—3 элемента !!SN:M1/0/111 M1/1/222 M1/2/333; содержимое слота 1: 111, 222, 333 !!SN:M1/1/?y5; y5 — содержимое 1-го элемента слота 1 !!IF:M^%Y5^; выведет: "222"

Получение адреса элемента слота ^
!!SN:M[номер слота]/?[адрес элемента]/[номер элемента];

При удалении слота или изменении его размера, — адрес станет недействительным!

Пример:

!!SN:M1/?y1/2; y1 содержит адрес 2-го элемента слота 1

Создание нового слота ^
!!SN:M[номер слота]/[количество элементов]/[тип элементов]/[запоминать ли значения в сохранёнках];

Старое содержимое слота (если оно было), уничтожается.

*номер слота* — "-1" для автовыделения свободного номера и помещения его в v1.

*тип элементов*:
- 0 (число)
- 1 (строка)

*запоминать ли значения в сохранёнках*
- 0 (нет, при загрузке игры содержимое элементов будет представлять собой случайный мусор)
- 1 (да, содержимое нужно сохранять как есть)

При 0 экономится место в файле и возрастает скорость сохранения.

Пример:

!!SN:M0/4/1/1; выделить массив из 4-х строк в слоте 0. Сохранять их содержимое при загрузке !!SN:M0/2/^привет^; установить значение 2-й строки слота 0 !!SN:M0/3/^мир^; установить значение 3-й строки слота 0 !!SN:M0/2/?z1 M0/3/?z2; получить значения 2-й и третьей строк в z1, z2 !!IF:M^%Z1 %Z2^; выведет "привет мир" !!SN:M0; удалить слот 0 !!SN:M-1/0/0/0; выделить пустой слот под временный массив чисел !!VRy1:S1 R6; сгенерировали случайное число 1..6 !!SN:Mv1/y1; установили размер нового слота в это число !!VRy1:-1; y1 — индекс последнего элемента в слоте !!SN:Mv1/y1/777; значение последнего элемента слота — 777
XEPOMAHT
Цитата(Richter @ 27 Jan 2019, 11:28) *
Повторюсь, не являюсь программистом, поэтому dll = проблема. Если не трудно создайте адресов на 80 тыс.


Возьми, например, исходник Тифона, открой в нём текстовик Virtual.asm и допиши в конце строчку

Код
Выделенная_память rb 80000


после собери dll. Там же где-нибудь в хуке AfterWoG можешь записать адрес выделенной памяти в какую-нибудь, к примеру, v-переменную, если хочешь ею пользоваться из ERM.

Через SN:M ещё проще - !!SN:M0/80000/0/0;
feanor
Стоп, а что надо-то конкретно? Ну то есть куда эти адреса?
Richter
Цитата(feanor @ 27 Jan 2019, 17:46) *
Стоп, а что надо-то конкретно? Ну то есть куда эти адреса?

Это обычные команды из Olly беру "кусками" и переношу. Пока не спрашивайте зачем и откудаsmile.gif (статика). Главное, что работает (проверял). Но мало памяти. Такие дела.
MasterOfPuppets
Тогда надо говорить не "адреса", а "память", "блок памяти", "свободные байты", "неиспользованное адресное пространство". При чем тут "адреса" и "команды"?
И да: делай так, как я говорю, и не делай так, как я делаю. Патчинг экзешника - путь к стагнации и всё большему запутыванию кодера в собственном проекте. Именно поэтому каждая следующая версия MoP дается мне всё труднее, всё чаще хочется плюнуть и бросить.
Используй DLL.
Richter
Цитата(XEPOMAHT @ 27 Jan 2019, 17:25) *
Через SN:M ещё проще - !!SN:M0/80000/0/0;

А как этим одновременно с Olly пользоваться?
!#SN:M1300/80000/0/0;
!?PI;
!!SN:M1300/?y84/0;
!!IF:M^%Y84^; далее открываем Olly и прыгаем на адрес и работаем. Так правильно?

Цитата(MasterOfPuppets @ 27 Jan 2019, 18:03) *
Патчинг экзешника - путь к стагнации и всё большему запутыванию кодера в собственном проекте...
Используй DLL.

Факт, уже столкнулся с этим. Однако у меня пока есть сумасшедший интерес закончить проект, главное чтоб работало как говорится. DLL наверно не сложно написать, однако не умею.
planetavril
how to change the projectiles of the creatures,I replaced the elves of the rampart but how to change the bullets / arrows and to set the shots?
feanor
Опять обсуждаете в справочном треде. Не надо так.

Так, продолжаем вопрос по деревьям отстройки, на сей раз про редактор.

Десять блоков двенадцатибайтовых структурок, в каждой пререквизит постройки (или -1 для от корня), указатель на название, указатель на описание. Для отключения достаточно нуля в указатель на название.

Как-то так:

Код
struct _TownBuildingInfo_
{
    char* short_name;
    char* long_name;
    int prerequisit;
};


#define o_KnightBuildings        ((_TownBuildingInfo_*)0x005A6458)
#define o_SorcBuildings            ((_TownBuildingInfo_*)0x005A7830)
#define o_WizardBuildings        ((_TownBuildingInfo_*)0x005A6860)
#define o_HereticBuildings        ((_TownBuildingInfo_*)0x005A6240)
#define o_WarlockBuildings        ((_TownBuildingInfo_*)0x005A71D0)
#define o_NecromancyBuildings    ((_TownBuildingInfo_*)0x005A75F0)
#define o_BarbarianBuildings    ((_TownBuildingInfo_*)0x005A6AE0)
#define o_WitchBuildings        ((_TownBuildingInfo_*)0x005A6F30)
#define o_DervishBuildings        ((_TownBuildingInfo_*)0x005A6D10)
#define o_RandomBuildings        ((_TownBuildingInfo_*)0x005A6660)


#define    ME_TOWN_HALL        0
#define    ME_CITY_HALL        1
#define    ME_CAPITOL            2
#define    ME_FORT                3
#define    ME_CITADEL            4
#define    ME_CASTLE            5
#define    ME_TAVERN            6
#define    ME_BLACKMITH        7
#define    ME_MARKETPLACE        8
#define    ME_SILO                9
#define    ME_ART_MERCHANT        10
#define    ME_MAGE_GUILD_1        11
#define    ME_MAGE_GUILD_2        12
#define    ME_MAGE_GUILD_3        13
#define    ME_MAGE_GUILD_4        14
#define    ME_MAGE_GUILD_5        15
#define    ME_SHIPYARD            16
#define    ME_GRAIL            17
#define    ME_SPEC1            18    //
#define    ME_SPEC2            19
#define    ME_SPEC3            20
#define    ME_SPEC4            21
#define    ME_DWELL1            22
#define    ME_DWELL1_UP        23
#define    ME_DWELL1_HORDE        24
#define    ME_DWELL2            25
#define    ME_DWELL2_UP        26
#define    ME_DWELL2_HORDE        27
#define    ME_DWELL3            28
#define    ME_DWELL3_UP        29
#define    ME_DWELL3_HORDE        30
#define    ME_DWELL4            31
#define    ME_DWELL4_UP        32
#define    ME_DWELL4_HORDE        33
#define    ME_DWELL5            34
#define    ME_DWELL5_UP        35
#define    ME_DWELL5_HORDE        36
#define    ME_DWELL6            37
#define    ME_DWELL6_UP        38
#define    ME_DWELL7            39
#define    ME_DWELL7_UP        40

void CopyBuildingInformation(_TownBuildingInfo_* source, _TownBuildingInfo_* destination)
{
    source->short_name  = destination->short_name;
    source->long_name   = destination->long_name;
    source->prerequisit = destination->prerequisit;
}

void DisableBuilding(_TownBuildingInfo_* source)
{
    source->short_name  = 0;
    source->long_name   = 0;
    source->prerequisit = -1;
}

void FlattenBuildingsPrereqs(_TownBuildingInfo_* source)
{
    source->prerequisit = -1;
}



Пример использования: врезаемся после загрузки текстовиков, когда эти структурки и заполняются, и, например


Код
    
//Разрешить верфи и ГМ всем городам
    CopyBuildingInformation(o_KnightBuildings + ME_MAGE_GUILD_5,        o_WarlockBuildings + ME_MAGE_GUILD_5);
    CopyBuildingInformation(o_WitchBuildings + ME_MAGE_GUILD_4,            o_WarlockBuildings + ME_MAGE_GUILD_4);
    CopyBuildingInformation(o_WitchBuildings + ME_MAGE_GUILD_5,            o_WarlockBuildings + ME_MAGE_GUILD_5);
    CopyBuildingInformation(o_BarbarianBuildings + ME_MAGE_GUILD_4,        o_WarlockBuildings + ME_MAGE_GUILD_4);
    CopyBuildingInformation(o_BarbarianBuildings + ME_MAGE_GUILD_5,        o_WarlockBuildings + ME_MAGE_GUILD_5);

    CopyBuildingInformation(o_SorcBuildings + ME_SHIPYARD,        o_KnightBuildings + ME_SHIPYARD);
    CopyBuildingInformation(o_WizardBuildings + ME_SHIPYARD,    o_KnightBuildings + ME_SHIPYARD);
    CopyBuildingInformation(o_BarbarianBuildings + ME_SHIPYARD,    o_KnightBuildings + ME_SHIPYARD);
    CopyBuildingInformation(o_WarlockBuildings + ME_SHIPYARD,    o_KnightBuildings + ME_SHIPYARD);
    CopyBuildingInformation(o_HereticBuildings + ME_SHIPYARD,    o_KnightBuildings + ME_SHIPYARD);


Код
//запретить граали и разрешить строить все строения независимо друг от друга
    _TownBuildingInfo_* allfractions[] = {o_KnightBuildings, o_SorcBuildings, o_WizardBuildings,
                            o_HereticBuildings, o_NecromancyBuildings, o_WarlockBuildings,
                            o_BarbarianBuildings, o_WitchBuildings, o_DervishBuildings,
                            o_RandomBuildings};
    int dwells[] = {ME_DWELL1, ME_DWELL2, ME_DWELL3, ME_DWELL4, ME_DWELL5, ME_DWELL6, ME_DWELL7};

    for(int i = 0; i!=10; i++)
    {
        DisableBuilding(allfractions[i]+ME_GRAIL);
        for(int j = 0; j!=7; j++)
        {
            FlattenBuildingsPrereqs(allfractions[i]+dwells[j]);
        }    
    }


Код
    //переместить фонтан удачи в корень дерева отстройки
    o_SorcBuildings[ME_SPEC2].prerequisit = -1;
    //переместить сокровищницу в дерево отстройки замка после цитадели
    o_SorcBuildings[ME_SPEC3].prerequisit = ME_CITADEL;
    //переместить орду дендроидов в дерево отстройки 1 уровня
    o_SorcBuildings[ME_DWELL5_HORDE].prerequisit = ME_DWELL1;
feanor
It's not a thread for questions, stop spamming.
Also, answer is somwhere ITT on first pages, read carefully.
Richter
Здравствуйте. Вновь приходится задать вопрос в этой теме. Другой подходящей не попалось на глаза.
Где хранится способность героя ходить по воде (арт. сапоги левитации, закл. хождение по воде), можно ли её включить без артефакта и заклинания?
MasterOfPuppets
Исходники MoP (ArtReNumbering.txt - перенумерация артефактов)
Код
;*******************************************************************
; Сапоги Левитации (90 -> 202)
; функция проверки:
2C123 68CA000000;                        PUSH 0CA
2C128 E833D30A00;                        CALL mop.004D9460
2C12D C20400;                            RETN 4

; Замена вызовов:
7CEE E830440200;                        CALL mop.0042C123
7ECC E852420200;                        CALL mop.0042C123
1C8EB E833F80000;                       CALL mop.0042C123
3026B E8B3BEFFFF;                       CALL mop.0042C123
8161D E801ABFAFF;                       CALL mop.0042C123
8168C E892AAFAFF;                       CALL mop.0042C123
B1749 E8D5A9F7FF;                       CALL mop.0042C123
B299F E87F97F7FF;                       CALL mop.0042C123
16B796 E88809ECFF;                      CALL mop.0042C123
16B989 E89507ECFF;                      CALL mop.0042C123
16BB7A E8A405ECFF;                      CALL mop.0042C123
;*******************************************************************

То есть, на этот артефакт 11 проверок. Тут все они заменены на вызов одной функции, куда, в принципе, можно добавить проверки на что угодно.
Цитата(Richter @ 09 Feb 2019, 16:07) *
Здравствуйте. Вновь приходится задать вопрос в этой теме. Другой подходящей не попалось на глаза.

Вот же эта тема!
Richter
Цитата(MasterOfPuppets @ 10 Feb 2019, 07:40) *
То есть, на этот артефакт 11 проверок. Тут все они заменены на вызов одной функции, куда, в принципе, можно добавить проверки на что угодно.

Master of puppets, спасибо за указанное направление. Попробую разобраться.
Цитата(Richter @ 09 Feb 2019, 16:07) *
Здравствуйте. Вновь приходится задать вопрос в этой теме. Другой подходящей не попалось на глаза.

Вот же эта тема!
Думал это просто обсуждение уже имеющегося в "Инженерном анализе". Теперь буду знать.
hippocamus
Провёл мониторинг процессов по snd файлам.
ХотА, например, грузит:
- Data\heroes3.snd
- Data\hota.snd
и пытается:
- Heroes3\Data\heroes3.snd

Взял и поменял в экзешнике строку "heroes3" на "heroes4" ВО ВСЕХ случаях, не только для heroes3.snd
В результате, получается следующее:
- Data\heroes4.snd
- Data\hota.snd
и пытается:
- Data\heroes3.snd (капслоком)
- Heroes3\Data\heroes3.snd

Откуда вообще берутся эти пути и имена файлов? Я уже все dll проверил, реестр проверил!
XEPOMAHT
Цитата(hippocamus @ 22 Feb 2019, 16:57) *
Взял и поменял в экзешнике строку "heroes3" на "heroes4" ВО ВСЕХ случаях, не только для heroes3.snd


Значит не во всех. Пробуй менять в самой памяти (например HD-мод всегда подгружает Heroes3.exe четвёртой версии из папки _HD3_Data, игнорируя штатный геройский exe, за исключением ВоГа).
hippocamus
Цитата(XEPOMAHT @ 22 Feb 2019, 21:04) *
Значит не во всех. Пробуй менять в самой памяти (например HD-мод всегда подгружает Heroes3.exe четвёртой версии из папки _HD3_Data, игнорируя штатный геройский exe, за исключением ВоГа).

Да мне это не нужно в принципе. Если мне нужно подгрузить свой snd я его могу положить и как Data\heroes3.snd (переименовав штатный в heroes4.snd) и как Heroes3\Data\heroes3.snd.
Но такое впечатление, что строка "heroes3" собирается по кусочкам или лежит заксоренная.
XEPOMAHT
Цитата(hippocamus @ 22 Feb 2019, 21:35) *
и как Data\heroes3.snd (переименовав штатный в heroes4.snd) и как Heroes3\Data\heroes3.snd.
Но такое впечатление, что строка "heroes3" собирается по кусочкам или лежит заксоренная.


Heroes3 просто плюсуется к началу строки при чтении с CD (т.е. первый путь - <папка_с_игрой>\Data\heroes3.snd, а второй - диск:\Heroes3\Data\heroes3.snd) средствами какой-то сторонней dll, к сожалению, отладчик не пишет какой.

Проверил на MoP - первый путь к heroes3.snd без проблем переименовывается и в exe и в памяти. Второй - а нахрена, если CD - пережиток прошлого.
hippocamus
Цитата(XEPOMAHT @ 22 Feb 2019, 22:27) *
Проверил на MoP - первый путь к heroes3.snd без проблем переименовывается и в exe и в памяти. Второй - а нахрена, если CD - пережиток прошлого.
А МоП его и не грузит. МоП это по сути ТЕ, только переименованы лоды.
Хотя - нет, вот сравнение TE и MoP:
Data\h3wog.lod
Data\h3sprite.lod
Data\h3ab_spr.lod
Data\h3wog.lod
Data\h3bitmap.lod
Data\h3ab_bmp.lod
Data\h3bitmap.lod
Data\h3ab_ahd.vid
Data\video.vid
Data\heroes3.snd
Data\h3ab_ahd.snd
Data\h3mopRUS.lod
Data\h3mop.lod
Data\h3sprite.lod
Data\h3mopRUS.lod
Data\h3mopRUS.lod
Data\h3mop.lod
Data\h3bitmap.lod
Data\h3mopRUS.lod
heroes3\data\heroes3.vid
Data\video.vid
Data\heroes3.snd
Data\h3mop.snd
heroes3\data\heroes3.snd

MoP основан на h3wog358.exe? Не на h3te.exe?
MasterOfPuppets
На h3te.exe. Правда, после многолетней бомбардировки альфа-частицами и прочего чада кутежа это уже мало похоже на исходный материал.
Berserker
Формат файлов кампаний:

Код
Heroes 3 Campaign (h3c) format after unpacking (gz).
=================================
byte    = 1 byte (0..255)
word    = 2 bytes (0..65535)
integer = 4 bytes (-2147483648..2147483647)
boolean = 1 byte (0 = false, 1 = true)
---------------------------------
const
  (* Hardcoded in camptext.txt, differs for each campaign index. Number of zones in current campaign *)
  NUM_ZONES = ?;

var
  Header: THeader;
  Zones:  array NUM_ZONES of TZone;
  Maps:   array NUM_ZONES of TMap | None;

type
  TString = record
    Length: integer;
    Value:  array Length of char;
  end;

  THeader = record
    GameVersion:             integer = 5 (Armageddon Blade) | 6 (WoG);
    CampaignInd:             byte; // Index of campaign (from 0), see camptext.txt
    CampaignName:            TString;
    CampaignDesc:            TString; // Description
    UserCanSelectDifficulty: boolean;
    MusicTheme:              byte;
  end; // THeader

  TZonePrologue = record
    HasPrologue: boolean;

    if HasPrologue then
      VideoId: byte;
      MusicId: byte;
      Text:    TString;
    end;
  end;

  TZoneEpilogue = record
    HasEpilogue: boolean;

    if HasEpilogue then
      VideoId: byte;
      MusicId: byte;
      Text:    TString;
    end;
  end;

  TStartingOpts = record
    OptsType: byte; // StartingBonus = 1, CrossoverHero = 2, InitialHero = 3

    if OptsType = 1 then
      PlayerColor: byte;
      NumBonuses:  byte;
      Bonuses:     array NumBonuses of record
        BonusType: byte;

        if Bonuses = 0 (spell) then
          Hero:  word; 65023 for most powerful hero
          Spell: byte;
        end;

        if Bonuses = 1 (creature) then
          Creature: word;
          Number:   word;
        end;

        if Bonuses = 3 (artifact) then
          Hero: word;
          Art:  word;
        end;

        if Bonuses = 4 (spell scroll) then
          Hero:  word;
          Spell: byte;
        end

        if Bonuses = 5 (primary skills) then
          Hero:       word;
          PrimSkills: array 4] of byte;
        end;

        if Bonuses = 6 (secondary skill) then
          Hero:     word;
          SecSkill: byte;
          Level:    byte;
        end;

        if Bonuses = 7 (resource) then
          Resource: byte;
          Quantity: integer;
        end;
      end; // Bonuses
    end; // if

    if OptsType = 2 then
      PlayerColor: byte;
      ZoneIndex:   byte;
    end;
  end; // .TStartingOpts

  TZone = record
    FileName:           TString;
    FileSize:           integer;
    RequiredZones:      byte; // Zone prerequisites; bitmask: 1 bit for each zone
    ZoneColor:          byte;
    DifficultyLevel:    byte;
    RegionRmbText:      TString; // Right mouse button hint
    Prologue:           TZonePrologue;
    Epilogue:           TZoneEpilogue;
    HeroesRetain:       byte; // Bitmask of Experience (bit 0), Primary Skills (bit 1), Secondary Skills (bit 2), Spells (bit 3), Artifacts (bit 4)
    CrossoverCreatures: array of 19 bytes; // 1 bit for every creature. Creature ID: 0..159
    CrossoverArts:      array of 18 bytes; // 1 bit for every artifact. Artifact ID: 0..143
    StartingOpts:       TStartingOpts;
  end;

  TMap = unpacked h3m (gz) map
Sadness
Всем привет.

Мне казалось, я где-то видел аналогичную тему с адресами в SoD.
Могу ошибаться, конечно, но если такая тема есть - ткните, пожалуйста. smile2.gif
Richter
Всем привет) Выкладываю полезную Heroes3f.idb штуку для мододелов. Раньше была на сайте, сейчас не смог найти. Случайно наткнулся при чистке диска. Думаю будет полезна.
Raistlin
Привет, друзья, я тут раскопал некоторые неопубликованные виртуальные адреса и хочу оставить их здесь. Быть может, кому-то еще пригодится.

Регенерация существ

Цитата(major @ 15 Nov 2007, 20:27) *
002F55C7 83F8 3C CMP EAX,3C //стражи
002F55CA 0F84 BB000000 JE 002F568B
002F55D0 83F8 3D CMP EAX,3D //привидения
002F55D3 0F84 B2000000 JE 002F568B
002F55D9 3D 90000000 CMP EAX,90 //тролли
002F55DE 0F84 A7000000 JE 002F568B
002F55E4 3D 9D000000 CMP EAX,9D //кошмарные гидры
002F55E9 0F84 92000000 JE 002F5681
где 3C, 3D, 90, 9D - номер существа в шестнадцатеричной системе

Актуальные адреса (проверено на Эре):
0075DE66 83F8 3C CMP EAX,3C
0075DE69 0F84 BB000000 JE 0075DF2A
0075DE6F 83F8 3D CMP EAX,3D
0075DE72 0F84 B2000000 JE 0075DF2A
0075DE78 3D 90000000 CMP EAX,90
0075DE7D 0F84 A7000000 JE 0075DF2A
0075DE83 3D 9D000000 CMP EAX,9D
0075DE88 0F84 92000000 JE 0075DF20


Для кошмарных гидр выполняется проверка вероятности регенерации (где 28h = 40% вероятность)
Цитата(major @ 15 Nov 2007, 20:27) *
002F5681 E8 9A7EFFFF CALL 002ED520
002F5686 83F8 28 CMP EAX,28

Актуальные адреса (проверено на Эре):
0075DF20 E8 7B84FFFF CALL 007563A0
0075DF25 83F8 28 CMP EAX,28


А вот тут находится количество срегенерированных жизней (где 32h = 50 HP)
Цитата(major @ 15 Nov 2007, 20:27) *
002F55BC BA 32000000 MOV EDX,32

Актуальный адрес (проверено на Эре):
0075DE5B BA 32000000 MOV EDX,32


Атака с возвращением

Цитата(major @ 15 Nov 2007, 20:27) *
002F57C6 83F8 48 CMP EAX,48 //гарпия
002F57C9 74 5D JE SHORT 002F5828
002F57CB 83F8 49 CMP EAX,49 //гарпия-ведьма
002F57CE 74 58 JE SHORT 002F5828
002F57D0 3D 9B000000 CMP EAX,9B //темный дракон
002F57D5 74 21 JE SHORT 002F57F8 //доп проверка двуклеточности

Актуальные адреса (проверено на Эре):
0075E059 83F8 48 CMP EAX,48
0075E05C 74 5D JE SHORT 0075E0BB
0075E05E 83F8 49 CMP EAX,49
0075E061 74 58 JE SHORT 0075E0BB
0075E063 3D 9B000000 CMP EAX,9B
0075E068 74 21 JE SHORT 0075E08B

Соответствующее место в оригинальном коде:
0047832B cmp eax, 48h ; Compare Two Operands
0047832E jz short loc_00478335 ; Jump if Zero (ZF=1)
00478330 cmp eax, 49h ; Compare Two Operands
00478333 jnz short loc_00478365 ; Jump if Not Zero (ZF=0)


Для выбора режима нападения после нажатия правой кнопкой на защите (атаковать и вернуться или атаковать и остаться там)

Цитата(major @ 15 Nov 2007, 20:27) *
002FA2D7 837D F0 48 CMP DWORD PTR SS:[EBP-10],48 //гарпия
002FA2DB 74 23 JE SHORT 002FA300
002FA2DD 837D F0 49 CMP DWORD PTR SS:[EBP-10],49 //гарпия-ведьма
002FA2E1 74 1D JE SHORT 002FA300
002FA2E3 817D F0 9B000000 CMP DWORD PTR SS:[EBP-10],9B //темный дракон
002FA2EA 74 14 JE SHORT 002FA300

Актуальные адреса (проверено на Эре):
00762940 837D FC 48 CMP DWORD PTR SS:[LOCAL.1],48
00762944 74 23 JE SHORT 00762969
00762946 837D FC 49 CMP DWORD PTR SS:[LOCAL.1],49
0076294A 74 1D JE SHORT 00762969
0076294C 817D FC 9B000 CMP DWORD PTR SS:[LOCAL.1],9B
00762953 74 14 JE SHORT 00762969


Возрождение фениксов

Цитата(major @ 15 Nov 2007, 20:27) *
002F587C 817E 34 83000000 CMP DWORD PTR DS:[ESI+34],83 //феникс
002F5883 74 38 JE SHORT 002F58BD
002F5885 817E 34 9E000000 CMP DWORD PTR DS:[ESI+34],9E //священный феникс
002F588C 74 1C JE SHORT 002F58AA

Актуальные адреса (проверено на Эре):
0075E108 817E 34 83000 CMP DWORD PTR DS:[ESI+34],83
0075E10F 74 38 JE SHORT 0075E149
0075E111 817E 34 9E000 CMP DWORD PTR DS:[ESI+34],9E
0075E118 74 1C JE SHORT 0075E136



Также в какой-то момент мой взгляд упал вот на это место:

004331CB 85F6 TEST ESI,ESI
004331CD 75 14 JNZ SHORT 004331E3
004331CF 83F8 70 CMP EAX,70
004331D2 74 5D JE SHORT 00433231
004331D4 83F8 71 CMP EAX,71
004331D7 74 58 JE SHORT 00433231
004331D9 83F8 72 CMP EAX,72
004331DC 74 53 JE SHORT 00433231
004331DE 83F8 73 CMP EAX,73
004331E1 74 4E JE SHORT 00433231

Тут идет проверка на четырех неулучшенных элементалей, однако, что за ней следует, я не смотрел. Если вдруг кто-то знает, прошу поделиться, а то любопытно =).gif

Кстати, можете пожалуйста помочь отключить следующее оповещение?

Raistlin
Пока искал одну вещь, нашел целую кучу всего другого...

00683288 - название первой выбранной карты при старте новой игры. По умолчанию "Высокомерие" (Arrogance.h3m)

0065F8AC - таблица с именами аудио-лупов, начинается с "loopocea.wav"

00687FAC - таблица с именами звуков заклинаний, начинается с "Acid.wav"

00660060 - таблица с именами дефов с иконками, показываемыми в зале совета. Начинается с HALLFORT.def (Крепость). Там же рядом находятся дефы, подгружаемые лишь единожды (twcrport.def, spells.def, artifact.def и тд.)

0068864C - названия многих текстовиков

00689004 - building.txt

0068C888 - jktext.txt

006834FC - еще пара текстовиков (условия победы, поражения, а заодно информация о турнирных правилах)

0067F154 - и еще (герои, их классы и навыки)

0067604C - таблица с именами иконок городских строений, начинается с "BoEup_6.pcx" (погребальный костер)


Подгружаемые игрой файлы с ресурсами:
Raistlin
Ну что же, раз уж я начал тему абилок, то почему бы не продолжить. 0=).gif В принципе, мне даже понравилось искать адреса) За окном давно стемнело, а я тут сижу за компьютером и уписываю йогурт... В общем, самое время поковырять любимую игру lol.gif

Бесстрашие

Цитата(major @ 01 Jul 2008, 16:57) *
002F7C6C 817F 34 84000000 CMP DWORD PTR DS:[EDI+34],84 //лазурный дракон
002F7C73 74 46 JE SHORT 002F7CBB
002F7C75 817F 34 96000000 CMP DWORD PTR DS:[EDI+34],96 //верховный архангел
002F7C7C 7C 09 JL SHORT 002F7C87
002F7C7E 817F 34 C0000000 CMP DWORD PTR DS:[EDI+34],0C0 //сильванский кентавр
002F7C85 7C 34 JL SHORT 002F7CBB

Актуальные адреса (проверено на Эре):
00760481 817F 34 84000 CMP DWORD PTR DS:[EDI+34],84 //лазурный дракон
00760488 74 46 JE SHORT 007604D0
0076048A 817F 34 96000 CMP DWORD PTR DS:[EDI+34],96 //верховный архангел
00760491 7C 09 JL SHORT 0076049C
00760493 817F 34 C0000 CMP DWORD PTR DS:[EDI+34],0C0 //сильванский кентавр
0076049A 7C 34 JL SHORT 007604D0
Бесстрашием обладают Лазурный дракон и диапазон существ от Верховного архангела (150) до командира Сопряжения (191).


Страх

Цитата(major @ 01 Jul 2008, 16:57) *
002F7CEA 81FB 84000000 CMP EBX,84 //лазурный дракон
002F7CF0 74 75 JE SHORT 002F7D67
002F7CF2 81FB 99000000 CMP EBX,99 //антихрист
002F7CF8 74 6D JE SHORT 002F7D67
002F7CFA 81FB 9B000000 CMP EBX,9B //темный дракон
002F7D00 74 65 JE SHORT 002F7D67

Актуальные адреса (проверено на Эре):
007604F1 81FB 84000000 CMP EBX,84 //лазурный дракон
007604F7 74 75 JE SHORT 0076056E
007604F9 81FB 99000000 CMP EBX,99 //антихрист
007604FF 74 6D JE SHORT 0076056E
00760501 81FB 9B000000 CMP EBX,9B //темный дракон
00760507 74 65 JE SHORT 0076056E

командиры сопряжения (в качестве монстров видимо)
Вот тут мне что-то кажется, что major ошибся, и Страхом по факту обладают все командиры. Нужно это для того, чтобы они могли получить эту способность в будущем.


Цитата(major @ 01 Jul 2008, 16:57) *
002F7D16 813D 68218302 AE000000 CMP DWORD PTR DS:[2832168],0AE
002F7D20 7C 21 JL SHORT 002F7D43
002F7D22 813D 68218302 BF000000 CMP DWORD PTR DS:[2832168],0BF
002F7D2C 7F 15 JG SHORT 002F7D43

Актуальные адреса (проверено на Эре):
0076051D 813D 94258302 CMP DWORD PTR DS:[2832594],0AE
00760527 7C 21 JL SHORT 0076054A
00760529 813D 94258302 CMP DWORD PTR DS:[2832594],0BF
00760533 7F 15 JG SHORT 0076054A


Магическое зеркало

Цитата(major @ 01 Jul 2008, 17:30) *
00048528 8179 34 86000000 CMP DWORD PTR DS:[ECX+34],86
0004852F 75 1E JNZ SHORT 0004854F

Актуальные адреса (проверено на Эре):
00448528 8179 34 86000 CMP DWORD PTR DS:[ECX+34],86
0044852F 75 1E JNE SHORT 0044854F
86h = 134 - Сказочный дракон


Атака огненным шаром

Цитата(major @ 01 Jul 2008, 17:30) *
0003F72C 83F8 2D CMP EAX,2D
0003F72F 0F85 EA020000 JNZ 0003FA1F

Актуальные адреса (проверено на Эре):
0043F72C 83F8 2D CMP EAX,2D
0043F72F 0F85 EA020000 JNE 0043FA1F
2Dh = 45 - Магог


Атака облаком смерти

Цитата(major @ 01 Jul 2008, 17:30) *
002FF990 83F8 40 CMP EAX,40 //лич
002FF993 74 12 JE SHORT 002FF9A7
002FF995 83F8 41 CMP EAX,41 //могущественный лич
002FF998 74 0D JE SHORT 002FF9A7
002FF99A 3D C4000000 CMP EAX,0C4 //драколич
002FF99F 74 06 JE SHORT 002FF9A7

Актуальные адреса (проверено на Эре):
00767B9F 83F8 40 CMP EAX,40
00767BA2 74 12 JE SHORT 00767BB6
00767BA4 83F8 41 CMP EAX,41
00767BA7 74 0D JE SHORT 00767BB6
00767BA9 3D C4000000 CMP EAX,0C4
00767BAE 74 06 JE SHORT 00767BB6
00767BB0 B8 00000000 MOV EAX,0
00767BB5 C3 RETN
00767BB6 B8 41000000 MOV EAX,41 //во всех трех случаях просто подсовываем индекс могущественного лича и не паримся

При выборе снаряда для драколича проходит отдельная проверка:
00767BE2 3D C4000000 CMP EAX,0C4
00767BE7 74 07 JE SHORT 00767BF0 //если драколич, подменяем снаряд
00767BE9 B9 B0096600 MOV ECX,006609B0 ; ASCII "plcbowx.def"
00767BEE EB 05 JMP SHORT 00767BF5 //в противном случае выходим из функции
00767BF0 B9 141B7A00 MOV ECX,OFFSET 007A1B14 ; ASCII "ZShot195.def"
00767BF5 C3 RETN


Соответствующее место в оригинальном коде:
0043FA1F 83F8 40 CMP EAX,40 //лич
0043FA22 0F84 FF000000 JE 0043FB27
0043FA28 83F8 41 CMP EAX,41 //могущественный лич
0043FA2B 0F84 F6000000 JE 0043FB27
Raistlin
Вот они, иконки наши )

005849D0 83C0 02 ADD EAX,2 // кадр номер 2 в scselc.def (иконка SoD)
005849D3 8945 FC MOV DWORD PTR SS:[EBP-4],EAX
005849D6 EB 10 JMP SHORT 005849E8
005849D8 C745 FC 01000000 MOV DWORD PTR SS:[EBP-4],1 // кадр номер 1 в scselc.def (иконка AB)
005849DF EB 07 JMP SHORT 005849E8
005849E1 C745 FC 00000000 MOV DWORD PTR SS:[EBP-4],0 // кадр номер 0 в scselc.def (иконка RoE)

Код
if ( *v11 == 14 )
{
  cadre = 0;
}
else if ( v12 == 21 )
{
  cadre = 1;
}
else
{
  v13 = -(v12 != 28);
  LOBYTE(v13) = v13 & 0xFD;
  cadre = v13 + 2;
}

Происходит это все в sub_00584820

В общем, если закинуть кадров в def и в нужный момент использовать их вместо стандартных, можно создать свои форматы карты wink.gif
Raistlin
Двухклеточный ров в Крепости:

004699E0 8078 04 07 CMP BYTE PTR DS:[EAX+4],7
004699E4 75 21 JNE SHORT 00469A07

Как убрать урон от рва в принципе (с проверкой на город):
Код
int __stdcall NoMoatDamage(LoHook* h, HookContext* c)
{
    if (c->eax == 7) //В eax лежит индекс города
    {
        c->return_address = 0x469AE8;
        return NO_EXEC_DEFAULT;
    }

    return EXEC_DEFAULT;
}

Код
Magic->WriteLoHook(0x469A90, (void*)NoMoatDamage);

Если хотите реализовать проверку на какого-то определенного монстра, то, если я ничего не путаю, структура стека в этот момент лежит в edi

*Спустя 10 минут*
Да, я был прав:
Код
if (*(int*)(c->edi + 52) == 13) //Дать Архангелам иммунитет ко рву
{
    c->return_address = 0x469AE8;
    return NO_EXEC_DEFAULT;
}
Raistlin
63B850 - Массив заклинаний Сказочного дракона

6608B8 - Массив заклинаний Чародея

Аура сопротивления у Единорогов:
43E800 cmp eax, 18h ; Compare Two Operands
43E803 jz short loc_0043E80E ; Jump if Zero (ZF=1)
43E805 cmp eax, 19h ; Compare Two Operands
43E808 jnz loc_0043E8AB ; Jump if Not Zero (ZF=0)

43E8AE cmp eax, 18h ; Compare Two Operands
43E8B1 jz short loc_0043E8BC ; Jump if Zero (ZF=1)
43E8B3 cmp eax, 19h ; Compare Two Operands
43E8B6 jnz loc_0043E95B ; Jump if Not Zero (ZF=0)

; Снижение удачи Дьяволами
44AFFF cmp dword ptr [esi], 36h
44B00F cmp dword ptr [edx], 37h

; Телепортация Дьяволов
44571B cmp eax, 36h ; Compare Two Operands
44571E jz short loc_00445743 ; Jump if Zero (ZF=1)
445720 cmp eax, 37h ; Compare Two Operands
445723 jz short loc_00445743 ; Jump if Zero (ZF=1)

44B180 - В данной функции производятся модификации урона от заклинаний. Для големов урон снижается, для элементалей - повышается.

Код
int __fastcall Battle_Get_Spell_GetResistGolem(signed int a1, int spell, int MonKind)
{
  int result; // eax

  switch ( MonKind )
  {
    case 32:
      result = a1 / 2;
      break;
    case 33:
      result = a1 / 4;
      break;
    case 112:
    case 127:
      if ( spell != 26 && spell != 17 && spell != 19 && spell != 57 )
        goto LABEL_20;
      result = 2 * a1;
      break;
    case 113:
    case 125:
      if ( spell != 23 )
        goto LABEL_20;
      result = 2 * a1;
      break;
    case 114:
    case 129:
      if ( spell != 16 && spell != 20 )
        goto LABEL_20;
      result = 2 * a1;
      break;
    case 115:
    case 123:
      if ( spell != 21 && spell != 22 && spell != 26 )
        goto LABEL_20;
      result = 2 * a1;
      break;
    case 116:
      result = 15 * a1 / 100;
      break;
    case 117:
      a1 /= 20;
      goto LABEL_20;
    default:
LABEL_20:
      result = a1;
      break;
  }
  return result;
}

Код
int __stdcall ChangeSpellDamage(LoHook* h, HookContext* c)
{
    int CreatureIndexForMR = *(_ptr_*)(c->esp + 8);
    if (CreatureIndexForMR == 201|| CreatureIndexForMR == 202)
    {
        c->ecx = (c->ecx / 4) * 3; //Урон от заклинания удвоен. Чтобы сделать х1.5 делим на 4 и умножаем на 3
    }
    return EXEC_DEFAULT;
}

[...]
Magic->WriteLoHook(0x44B1D4, (void*)ChangeSpellDamage);

Обратите внимание, в таблице с типами модификаторов магического урона у существ должен стоять повышенный урон от заклинаний холода. Изначально он есть только у Огненных и Энергитических Элементалей, но может быть задан и самостоятельно с помощью патчей или плагинов вроде Тифона.


Артефакт, дающий бесконечный боезапас
43F718 push 5
43F71A call Hero_ArtIsHas_OnDoll
43F71F test al, al
43F721 jnz short loc_0043F729 ; Jump if Not Zero (ZF=0)
43F723 dec dword ptr [esi+0D8h] ; Decrement by 1 (уменьшение количества снарядов)

41FA10 - функция менеджера битвы, отвечающая за блокировку колдовства (там находятся проверки на проклятую землю, антимагический гарнизон и сферу запрещения)
Raistlin
Вызов книги магии героя
В качестве примера взято колдовство заклинаний на карте приключений, но принцип, по идее, везде один - нужно создать диалог, дать пользователю с ним поиграться, а затем уничтожить.

Код
0041C500    50            PUSH EAX; /Arg4 = 2B3FFCC
0041C501    6A 01         PUSH 1        ; |Arg3 = 1
0041C503    6A 00         PUSH 0        ; |Arg2 = 0
0041C505    56            PUSH ESI; |Arg1
0041C506    8D8D 28FFFFFF LEA ECX,[LOCAL.54];
0041C50C    E8 DFFB1700   CALL 0059C0F0    ; _Dlg_ *__thiscall Dlg_SpellBook_Create(_Dlg_ *this, _Hero_ *hero, int a3, int a4, int TypeOfLand)
0041C511    6A 00         PUSH 0        ; /Arg1 = 0
0041C513    8D8D 28FFFFFF LEA ECX,[LOCAL.54];
0041C519    C745 FC 00000 MOV DWORD PTR SS:[LOCAL.1],0;
0041C520    E8 FB341E00   CALL 005FFA20    ; int __thiscall Dlg_ShowAndRun(void *dlg, int fadeIn)
0041C525    8D8D 28FFFFFF LEA ECX,[LOCAL.54]
0041C52B    C745 FC FFFFF MOV DWORD PTR SS:[LOCAL.1],-1
0041C532    E8 B9061800   CALL 0059CBF0    ; int __thiscall DestroySpellBook_Dlg(_Dlg_ *dlg)

Четвертый параметр функции Dlg_SpellBook_Create (a4) - это происхождение клика (то есть, при каких обстоятельствах диалог был создан). 0 - во время битвы, 1 - на карте приключений, 2 - в окне героя, 3 - возможно, при встрече героев (не проверено)


В бою, кстати, все немного иначе:
Код
00474895    call    0059EC10; BattleMgr_ShowHeroSpellBook. Создание диалога происходит уже в этой функции
XEPOMAHT
Цитата(Raistlin @ 02 Mar 2021, 22:24) *
Код
0041C500    50            PUSH EAX; /Arg4 = 2B3FFCC
0041C501    6A 01         PUSH 1; |Arg3 = 1
0041C503    6A 00         PUSH 0; |Arg2 = 0
0041C505    56            PUSH ESI; |Arg1
0041C506    8D8D 28FFFFFF LEA ECX,[LOCAL.54];
0041C50C    E8 DFFB1700   CALL 0059C0F0; _Dlg_ *__thiscall Dlg_SpellBook_Create(_Dlg_ *this, _Hero_ *hero, int a3, int a4, int TypeOfLand)
0041C511    6A 00         PUSH 0; /Arg1 = 0
0041C513    8D8D 28FFFFFF LEA ECX,[LOCAL.54];
0041C519    C745 FC 00000 MOV DWORD PTR SS:[LOCAL.1],0;
0041C520    E8 FB341E00   CALL 005FFA20; int __thiscall Dlg_ShowAndRun(void *dlg, int fadeIn)
0041C525    8D8D 28FFFFFF LEA ECX,[LOCAL.54]
0041C52B    C745 FC FFFFF MOV DWORD PTR SS:[LOCAL.1],-1
0041C532    E8 B9061800   CALL 0059CBF0; int __thiscall DestroySpellBook_Dlg(_Dlg_ *dlg)


В IDA-базе от WoG откомментировано лучше, советую копировать код оттуда. И для открывания книги магии лучше брать более чистый ассемблерный код (представленный выше - огрызочный и сам по себе работать не будет). И сама функция открывания диалога книги магии давно есть в высокоуровневом виде:

Код
void ShowSpellBookDlg(int a1, int a2, int land_modifier)
{
  if (this->doll_art[17].id != -1)
  {
   _Dlg_* dlg = (_Dlg_*)o_New(0xD0);
   // create spellbook dlg
   CALL_5(void, __thiscall, 0x59C0F0, dlg, this, a1, a2, land_modifier);
   dlg->Run();
   // destroy spellbook dlg
   CALL_1(void, __thiscall, 0x59CBF0, dlg);
   o_Delete(dlg);
  }
}
void ShowSpellBookDlg(int a1, int a2)
  {ShowSpellBookDlg(a1, a2, this->GetLandModifierUnder());}
};
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Форум IP.Board © 2001-2025 IPS, Inc.