Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Обсуждение развития ТЕ и новых команд ERM для него
DF2 :: ФОРУМЫ > Игровые форумы > Heroes of Might & Magic III > Моды > Скрипты
Страницы: 1, 2, 3, 4, 5
sergroj
На вскидку, вот это должно быть ответственно за обработку клика по карте, а именно, sub_0040F350:
.text:0040A1CE mov eax, [ebx+0E4h]
.text:0040A1D4 xor esi, esi ; Logical Exclusive OR
.text:0040A1D6 push esi
.text:0040A1D7 push esi
.text:0040A1D8 push esi
.text:0040A1D9 push 1
.text:0040A1DB push 1
.text:0040A1DD push eax
.text:0040A1DE mov ecx, ebx
.text:0040A1E0 call sub_00412BA0 ; Call Procedure
.text:0040A1E5 mov ax, [ebx+0E6h]
.text:0040A1EC push 1
.text:0040A1EE push esi
.text:0040A1EF lea ecx, ds:0[eax*4] ; Load Effective Address
.text:0040A1F6 movsx edx, cx ; Move with Sign-Extend
.text:0040A1F9 mov cx, [ebx+0E4h]
.text:0040A200 sar edx, 0Ch ; Shift Arithmetic Right
.text:0040A203 shl eax, 6 ; Shift Logical Left
.text:0040A206 shl cx, 6 ; Shift Logical Left
.text:0040A20A push edx
.text:0040A20B movsx eax, ax ; Move with Sign-Extend
.text:0040A20E movsx edx, cx ; Move with Sign-Extend
.text:0040A211 sar eax, 6 ; Shift Arithmetic Right
.text:0040A214 sar edx, 6 ; Shift Arithmetic Right
.text:0040A217 push eax
.text:0040A218 push edx
.text:0040A219 mov ecx, ebx
.text:0040A21B call sub_0040F350

Цитата(asm @ 01 Dec 2008, 12:49)
Вроде у меня были какие-то отладчики, вроде WinDASM или может кто-нть более удобную прогу посоветует для исследования кода?

Дизассемблер - Ida (могу дать). Более функциональный дебаггер - OllyDbg (мой уже, наверное, устарел).

Цитата(asm @ 01 Dec 2008, 12:49)
Жалко только что знаний асемблера у меня маловато.

А тут их много и не надо.
asm
sergroj, похоже с поиском это всё не так сложно как мне казалось сначала, более важный вопрос куда это потом всё применить.... как вызвать необходимую процедуру? как заполнить регистры необходимыми значениями?
sergroj
Я в 3.59 сделал возможность вызвать любую проедуру, у которой нет вещественных параметров. В Эре тоже можно сделать, только это лучше делать как полноценную команду, чтобы отличать числа от строк и чтобы кол-во параметров не прописывать. У меня это выглядит так:
mem.call(адрес, calling_conversion, параметры)
calling_conversion: 0 - stdcall, 1 - thiscall, 2 - fastcall
Wic
Всем привет.

Сейчас занимаюсь проблемой генерирования полностью симметричных рандомных карт.

Раздобыл описание формата карты h3m, написать конвертер из XL-U в симметричный XL+U теперь уже дело времени

Но есть проблема - как подцепить результат к Героям. То есть чтобы не ручками народ генерил - распаковывал - конвертил - загружал, а чтобы автоматически все шло.

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

Может кто-нибудь поспособствовать ?

Добавлено ([mergetime]1228417610[/mergetime]):
Это для TE 1.03R нужно (как и то, что выше спрашивают SAG и asm).
hippocamus
> Раздобыл описание формата карты h3m

Эх, намучишься ты с ним... Там кроме того ещё и ошибки есть.
asm
Цитата(Wic @ 05 Dec 2008, 01:06)
Видимо, надо потрогать код в том участке, когда генерация карты уже закончилась, но сама игра еще не началась. Или файловую операцию записи/считывания перехватить (если Герои карту сначала сейвят, а потом с диска стартуют).

Мне кажется сохранённная карта на диске это скорее побочка... так что думаю это будет сложновато....
У меня как раз обратная идея - не создавать карту на диске:
- карту не созадём
- У Берсерка почти готов автосейвкаунтер
- Т.е. можно будет попробовать писать запороленные сейвы с ключём от обоих игроков
- Так же можно будет делать сейвы текущего дня например каждые 30 секунд и перед битвами - это позволит избавится от проблем с вылетами героев и повтором хода, а так же с намеренными дисконектами.
- Если сейв был сделан во время текущего хода передбитвой, то после загрузки начинать битву автоматом.
+ Ещё сделать такую фичу: при чужом ходе игрока что бы можно было куда-нть кликнуть и увидеть процессы пользователя - позволит избежать АртМани, хотя тоже не панацея, можно АртМани переименовать в svchost.exe

Ну вот такие идеи.
Wic
Цитата(hippocamus @ 04 Dec 2008, 23:20)
> Раздобыл описание формата карты h3m

Эх, намучишься ты с ним... Там кроме того ещё и ошибки есть.
В природе существует версия без ошибок ?


Добавлено ([mergetime]1228421218[/mergetime]):
Артмани не критично имхо. Пользоваться умеют единицы, а умело пользоваться (читить и не палиться) может и вообще никто не умеет.

Плюс защита будет слишком сложна и скорее добавит гемора игрокам, чем реальную преграду поставит. Поэтому предлагаю забить. Есть более критичные вещи.

Собстна пароль на сейвы + несохранение карты на диск этого более чем достаточно на текущем этапе.
hippocamus
Цитата(Wic @ 04 Dec 2008, 23:06)
Цитата(hippocamus @ 04 Dec 2008, 23:20)
> Раздобыл описание формата карты h3m

Эх, намучишься ты с ним... Там кроме того ещё и ошибки есть.
В природе существует версия без ошибок ?

Напиши мне, я тебе дам модуль на Делфи для чтения карты.
Только напиши, что вообще конкретно ты хочешь, что такое симметричные карты.

Добавлено ([mergetime]1228430120[/mergetime]):
- Если сейв был сделан во время текущего хода передбитвой, то после загрузки начинать битву автоматом.

Это невозможно нормальными средствами...
Wic
Цитата(hippocamus @ 05 Dec 2008, 02:35)
Цитата(Wic @ 04 Dec 2008, 23:06)
Цитата(hippocamus @ 04 Dec 2008, 23:20)
> Раздобыл описание формата карты h3m

Эх, намучишься ты с ним... Там кроме того ещё и ошибки есть.
В природе существует версия без ошибок ?

Напиши мне, я тебе дам модуль на Делфи для чтения карты.
Только напиши, что вообще конкретно ты хочешь, что такое симметричные карты.
Алгоритм там такой:

1) Генерится карта XL-U на 4-х игроков по определенному шаблону (уже сделал его).
2) Внешней программой добавляется подземка, куда копируется содержимое поверхности.
3) Цвета стартовых замков меняются так, чтобы игроков стало 8, а синий находился строго под красным. Тип замков не меняется, то есть красный и синий играют одной и той же расой.
4) Делаются связи между плоскостями. Тут в зависимости от шаблона варианты. Все они так или иначе сводятся к заменам нейтральных городов/деревень определенного типа на лифты или телепорты. В том шаблоне, что сделал, планируется 3 лифта и 6 систем односторонников, ко всем идут дороги (ибо бывшие города).
5) При старте игры скриптами выравнивается начинка объектов, то есть одинаковое содержимое банков, кучек, хаток, универов, одинаковые арты и т.д.

Собственно всё.

Скинь на мыло библиотеку плз - wicforever@mail.ru

Добавлено ([mergetime]1228465025[/mergetime]):
Еще вопрос - можно ли сделать 9-й односторонник ? Не хватает smile.gif
hippocamus
Отправил. Если каких библиотек не хватает - они и не нужны.
Они нужны для работоспособности программы, для чтения лодов и проч., просто отключи.
Wic
По поводу формата карты - в описании пропущена последняя секция - список объектов с координатами.

Методом тыка было выяснено, что сначала идет 4 байта - количество объектов, а дальше на каждый участок или 12 или 24 байта в формате
1 байт - x координата
1 байт - y координата
1 байт - z координата
видимо 4 байта - какой-то код объекта (у рандомных карт они упорядочены по номерам
дальше служебные поля (видимо, доп свойства объектов)

Собственно вопрос - как определить, 12 там байт будет выделено или 24 ? Бывает ли больше байтов на объект (замки/деревни мб ?)
hippocamus
Это ты у меня спрашиваешь? Ты не по структуре класса смотри, а по процедуре чтения из файла. Класс сделан немного по другому, число объектов хранить не нужно, т.к. это число равно размерности открытого массива.
Wic
Цитата(hippocamus @ 05 Dec 2008, 18:26)
Это ты у меня спрашиваешь? Ты не по структуре класса смотри, а по процедуре чтения из файла. Класс сделан немного по другому, число объектов хранить не нужно, т.к. это число равно размерности открытого массива.
Не, я пока библиотечку не смотрел. Ибо на работе сейчас mail.ru недоступен, да и Дельфи нету. Поэтому с Турбо-Паскалем ковыряюсь smile.gif. Заголовок разобрал, территорию скопировал, а со списком объектов вышеописанный трабл вышел.
hippocamus
Там гораздо сложнее чем ты думаешь.
Wic
Цитата(hippocamus @ 05 Dec 2008, 18:41)
Там гораздо сложнее чем ты думаешь.
Это компенсируется простотой задачи smile.gif.

Нужно сдублировать 2 массива: территория (сделал) и объекты, во втором поменять везде z координату с 0 на 1. И заголовок слегка пофиксить (есть описание, да и научный тык работает).

Собствено copymap.exe это и делает, поэтому надо сдублировать ее функциональность и чутка расширить.
SAG19330184
формат объектов карты очень непростой, я делал загрузку карт (когда делал героев с нуля) и намучался с картами, постараюсь найти формат на днях
hippocamus
Я уже прислал Wic библиотеку на делфи.
Aнгeл
Цитата
Берсерк, а где можно поподробнее про твою работу, а то видел ты в разных ветках форума выкладываешь по чуть-чуть информации.
Желательно бы с примерами.

Прежде всего, если можно, то Ангел. В крайнем случае Берсеркер/Берс, от Берсерка коробит fie.gif

Что касается информации, то опишу очень кратко и применимо к последней версии.

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

II. Angel.dll инициализирует модули, каждый из которых патчит нужные для работы места в ехе. Затем управление возвращается игре.

III. Взаимодействие Эры с ЕРМ довольно прозрачно, хотя кодить будет удобнее с новым компилятором, поддерживающим полноценные макросы. Для реализации взаимодействия ЕРМ и кода использован триггер и ресивер SN. Они самые редко используемые и не загруженные бесконечными case-ами.

Переменные v50-v99 зарезервированны под нужды Эры (хотя в исходниках и можно произвольно изменить стартовый индекс).

v50 используется как команда ядру Эры. ЕРМ вызывает триггер SN через ресивер проигрывания звука SN:Pz1. Процедура PlaySound перехвачена и управление получает Эра. Далее анализируется содержимое v50. Если это 0 (стандартное значение), значит проигрывается звук, вызывается ЕРМ триггер. В общем всё так, как будто никто ничего не менял.

Возможные значения v50 (и параметров: соответственно v51, v52...)

Код
[1 - LoadLibrary (команда обнуляется)]
Name: ZIndex; VAR Result: VIndex;

[2 - GetProcAddress (команда обнуляется)]
hModule: INTEGER; ProcName: ZIndex; Result: VIndex;

[3 - Call Proc (команда обнуляется)]
Proc: POINTER; CallConversion: TCallConvType; Params: TParams;

[4 - вызов PlaySound без ЕРМ-триггера. (команда обнуляется)]

Другое: - вызвать !?SN-триггер без вызова функции PlaySound (команда не обнуляется). Используется для реализации пользовательских событий, но в основном - для реализации произвольного кол-ва новых триггеров.


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

В частности, вы вызываете !!VR:C и инициализируете сразу все параметры. Быстрее через ЕРМ это можно сделать лишь отдельной командой, что, правда, лишь ещё больше раздует ЕРМ case-ми, и приведёт лишь к мизерному приросту производительности.
Далее вы вызываете !!SN:Pz1, что очень быстро приводит нас к PlaySound, а там анализ умещается в пару десятков строк, причём сверху asm-овских case-ов идут самые частоиспользуемые команды.

Пояснения:

Код
TCallConvType = (CDECL = 0, PASCAL = 1, STDCALL = 2);
В новой версии добавятся ещё FastCall и, возможно, ThisCall (хотя врядли последнее будет использоваться).

TParams = RECORD
Count: INTEGER; // Кол-во параметров
Params: ARRAY Count OF INTEGER; // Сами параметры
END;


Последний список изменений уже намусолил всем глаза:

Цитата
1) Деактивированы проверки CRC
2) ЕРМ больше не отключает скрипты при ошибке
3) Исправлен баг с установкой дорог через ЕРМ
4) Возможность сохранять игру через ЕРМ
5) Событие: Игра Сохранена (если сохраняли через ЕРМ); #100
6) Событие: Запись данных в сейв; #101
7) PROCEDURE GZipWrite(Address: POINTER; Count: INTEGER); CDECL; AT $704062;
8) PROCEDURE GZipRead(Address: POINTER; Count: INTEGER); CDECL; AT $7040A7;
9) Событие: Загрузка данных из сейва; #102
10) Опция: Отключить вопрос "Вы действительно хотите загрузить игру?"; #0
11) Событие: Нажатие Клавиши - полный контроль реакции через ЕРМ; #103
12) Событие: Вход в Окно Героя; #104
13) Событие: Выход из Окна Героя; #105
14) Исправление триггера ЕРМ !?HE на универсальный, где v51 и v52 - инициатор и цель соответственно, а сам триггер = !?HE199
15) Событие: Контроль над очерёдностью хода в битве; #106
16) Опция: Отключение ERM таймера (ускоряет игру); #1
17) Опция: Грааль не даёт все спелы; #2
18) Событие: До действия (пример: регенерация троллей) - полный контроль через ЕРМ; #107


Для поддержки плагинов Эра после своей инициализации до передачи управления игре загружает библиотеки, имена которых прописаны в файле EraPlugins.dat в формате 1 имя на 1 строку. В конце обязательно наличие символов #13#10. В пользовательских dll можно произвести нужный динамический патчинг.

Функции для Паскаля/Делфи:

Код
// Assume Win=Windows

CONST
    (* HookCode constants *)
    C_HOOKTYPE_JUMP = FALSE;
    C_HOOKTYPE_CALL = TRUE;
    C_OPCODE_JUMP = $E9;
    C_OPCODE_CALL = $E8;
    C_UNIHOOK_SIZE = 5;

TYPE
(* Запись, необходимая для работы с функциями патчинга *)
    THookRec = RECORD
 Opcode: BYTE;
 Ofs: INTEGER;
    END; // .record THookRec

VAR
Temp: INTEGER; // Универсальная временная переменная

(*  *)
PROCEDURE WriteAtCode(P: POINTER; Buf: POINTER; Count: INTEGER);
BEGIN
    Win.VirtualProtect(P, Count, PAGE_READWRITE, @Temp);
    Win.CopyMemory(P, Buf, Count);
    Win.VirtualProtect(P, Count, Temp, NIL);
END; // .procedure WriteAtCode

PROCEDURE HookCode(P: POINTER; NewAddr: POINTER; UseCall: BOOLEAN);
VAR
    HookRec: THookRec;

BEGIN
    IF UseCall THEN BEGIN
 HookRec.Opcode:=C_OPCODE_CALL;
    END // .if
    ELSE BEGIN
 HookRec.Opcode:=C_OPCODE_JUMP;
    END; // .else
    HookRec.Ofs:=INTEGER(NewAddr)-INTEGER(P)-C_UNIHOOK_SIZE;
    WriteAtCode(P, @HookRec, 5);
END; // .procedure HookCode


Интерфейс:

Код
(* WriteAtCode *) {Записывает данные из буфера в указанное место}
PROCEDURE WriteAtCode(P: POINTER; Buf: POINTER; Count: INTEGER);
(* HookCode *) {Патчит указанное место 5-байтовым хуком на новое, адрес которого указывается в параметре. Хук может быть вызовом или прыжком}
PROCEDURE HookCode(P: POINTER; NewAddr: POINTER; UseCall: BOOLEAN);


IV. Применение на практике.

1. Использование новых событий. В текущей версии обязательно, иначе будут происходить очень странные вещи. В новых версиях всё будет несколько дружелюбнее. Поехали.

[События нажатии клавиши]
Код
Параметры: 103 (код события)/Код клавиши
Нужно вернуть: v52: Block? (Boolean); Блокировать игре доступ к событию или нет.


События нажатия клавиши очень тонкое и требует бережного обращения. Представьте себе, что вы желаете изменить стандартную реакцию нажатия на 'L' (Load, загрузка сейва). Тут же нарисовываются несколько проблем. Первая - нет возможности определить, в каком диалоге мы находимся. Это карта приключений, битва, опции...А может сейчас отображается обычное сообщение через !!IF:M? Второе, в ЕРМ нет понятия стёка. Так, событие привело нас на код ЕРМ, что вызывает диалог, который тоже порождает событие, которое вызывает ещё один ЕРМ диалог...В это время куча переменных по сто раз меняют своё значение!

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

Код
v20 - сохранённый код команды
v21..v39 - сохранённые параметры события
v40 - флаг ЕРМ-диалога

!#VRv40:S0;

!?SN; Универсальный триггер
 !!VRv20:Sv50; Сохранили код команды в v20

!?SN&v20=103; Событие нажатия любой клавиши
 !!VRv52:S0; Игра по умолчанию получит событие
 !!if&v40=1:; Если в данный момент отображается ЕРМ-диалог, то событие не должно идти дальше по триггерам
   !!VRv20:S1; Номера событий начинаются со 100, так что 1 значит - нет события
   !!FU:E;
 !!en:;
 !!VRv21:Sv51; Сохранили код клавиши в v21


Знаете, играл в Mount & Blade. Игровой движок там на Питоне. Тормозит каждое простейшее меню, а у скриптописцев возможности практически на нуле. Эру это не касается, даже перехваты клавиш происходят очень быстро и пользователь мгновенно увидит работу скрипта, как будто это игровой код, а не ЕРМ+DLL.

А теперь код простейшего скрипта в стиле Реквизита. Нажатие на клавишу 'L' не вызывает вопрос "Вы действительно хотите загрузить игру?" и т.д, а выводит сообщение с просьбой перечислить 5 у.е на их счёт. Поехали:

Код
!?SN&v20=103/v21=76; Событие нажатия клавиши 'L', #76
 !!VRv40:S1; Сейчас мы будем отображать диалог ЕРМ и не хотим в это время перехватывать нажатия клавиш
 !!IF:M^Хотите загрузить игру?
Данные потеряются и т.д.?
Перечислите 5 у.е на счёт {Реквизита}.
Не хотите? Тогда грузитесь через {Опции}, блин.^;
 !!VRv40:S0; Диалог уже закрыт
 !!VRv52:S1; А вот событие доставлять игре не нужно
 !!VRv20:S1; Равно как и давать управление другим перехватчикам события


На тестовой карте (ссылки в конце поста) нажмите L и увидите реакцию.

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

Код
!?SN&v20=103; Событие нажатия любой клавиши
 !!VRv40:S1; Сейчас мы будем отображать диалог ЕРМ и не хотим в это время перехватывать нажатия клавиш
 !!IF:Q2^Хотите, чтобы игра обработала нажатие на клавишу?
Перечислите 5 у.е на счёт {Реквизита}.
Заранее благодарим.^;
 !!VRv40:S0; Диалог уже закрыт
 !!VRv52:S1; А вот событие доставлять не нужно
 !!VRv52&2:S0; Или нужно? :-)
 !!VRv20:S1; Не нужно давать управление другим перехватчикам события


[События нажатии клавиши]
Код
Параметры: 103 (код события)/Код клавиши
Нужно вернуть: v52: Block? (Boolean); Блокировать игре доступ к событию или нет.


Пожалуй, для полноты рассмотрим ещё одно событие с примером. Для остальных будет просто описание.

[Событие: Контроль над очерёдностью хода в битве]
Код
Параметры: 106 (код события)/Сторона/Номер стёка 0..20
Нужно вернуть: v51 = Сторона/v52 = Номер стёка


Тестовый скрипт позволит нам на тестовой карте выигрывать любые сражения за...1 ход. Почти любые. У героя имеется один стёк - 50 арбалетчиков. Пусть они всегда ходят (считается, что МЫ всегда нападает на противника). Таким образом мы попросту растреляем армию противника, не дав кому-то походить.

; Все клавишные события направляются игре
Код
!?SN&v50=103;
!!VRv51:S0;

!?SN&v50=106; Событие: кто ходит?
!!VRv51:S0; Сторона - левая (0 - левая, 1 - правая)
!!VRv52:S0; Номер стёка - 0 (у нас это арбалетчики и 1 - командир, если есть)


Как видите, всё довольно просто и внутренняя рутина скрыта от глаз скриптописцев.

[Событие: Игра сохранена]
Код
Параметры: 100 (код события)


[Событие: Запись данных в сейв]
Код
Параметры: 101 (код события)

Удобные функции:
Код
PROCEDURE GZipWrite(Address: POINTER; Count: INTEGER); CDECL; AT $704062;


[Событие: Загрузка данных из сейва]
Код
Параметры: 102 (код события)

Удобные функции:
Код
PROCEDURE GZipRead(Address: POINTER; Count: INTEGER); CDECL; AT $7040A7;


[Событие: Вход в Окно Героя]
Код
Параметры: 104 (код события)


[Событие: Выход из Окна Героя]
Код
Параметры: 105 (код события)


[Событие: До действия (пример: регенерация троллей)]
Код
Параметры: 107 (код события)/Номер стёка 0..41/Адрес структуры TBattleMonster

Описание TBattleMonster я позаимствовал из исходников ЕРМ и прилагаю к материалам данного кратчайшего руководства.

V. Опции Эры.
На данный момент их три:

Код
C_ERA_OPTION_LOADGAME_QUESTION = 0; // Опция отключения вопроса о загрузке игры
C_ERA_OPTION_ERMTIMER_ONOFF = 1; // Опция отключения ERM таймера для ускорения игры
C_ERA_OPTION_CONFLUXGRAILALLSPELLS_ONOFF = 2; // Опция отключения свойства грааля в Сопряжении по обучению всем спелам


Изменяются через экспортируемую Angel.dll функцию:
Код
SetOption(ID: INTEGER; Value: INTEGER);


Цитата
Я так вижу из твоих наработок можно ещё 1 оч неплохую идею ТЕшников реализовать - запароленые сейвы. Так же видимо можно будет написать встроенный автосейвкаунтер.

Запароленные сейва только через Эру+ЕРМ - невозможно. Хотя, если нужно всего лишь запретить загрузку сейва, то есть вариант. Правда, загрузив сейв через другой ехе, этот вариант обойдут.

Что касается столь сложного слова автосейвкаунтера, то гораздо проще просто автосейвы по дням + в начале хода, что элементарно, но тестировалось на сингле и для сингла.

Цитата
calling_conversion: 0 - stdcall, 1 - thiscall, 2 - fastcall

А где Pascal? Или его уже отожествляют с Делфи, а FreePascal, TMTPascal, Virtual Pascal и прочее забыты? smile.gif

Цитата
Кое-какие изменения уже внёс (спасибо Берсерку за разлоченный экзешник)

Взял термин на вооружение rolleyes.gif

Цитата
Поэтому с Турбо-Паскалем ковыряюсь

Старик ещё жив???

[ВЛОЖЕНИЯ]
Тестовая карта: Высокомерие = Скачать
Era_6_12_08.rar
Хмм..
я надеюсь будет хелп, желательно в chm )))
Aнгeл
Ну, Хмм.., тебе-то для Хоты нужно только уметь прописать имя своей DLL в файле EraPlugins. А в ней уже патчить ехе, при чём для удобства можно использовать функции WriteAtCode и HookCode, что я привёл выше как альтернативу WriteProcessMemory, что юзал ты.
Остальное - для скриптописцев.
hippocamus
Спасибо, Ангел! Родина не забудет.

ЗЫ. Бедные арбалетчики! Они ведь могут столкнуться с группой лазуриков, и у них тупо не хватит стрел... sad.gif
Лучше использовать Вампиров или Наг smile.gif

Добавлено ([mergetime]1228599168[/mergetime]):
В chm хелп напишет Драколич smile.gif
Хмм..
Цитата(Aнгeл @ 07 Dec 2008, 00:21)
Ну, Хмм.., тебе-то для Хоты нужно только уметь прописать имя своей DLL в файле EraPlugins.


Слишком сложно
Aнгeл
Цитата
ЗЫ. Бедные арбалетчики! Они ведь могут столкнуться с группой лазуриков, и у них тупо не хватит стрел...
Лучше использовать Вампиров или Наг

Уже думал об этом, но решил не усложнять smile.gif И это, подвоза в помощь smile.gif

Цитата
Слишком сложно

А я упрощу: помести имя длл в EraPlugins.dat. 5 слов, проще никак biggrin.gif
sergroj
Цитата(Aнгeл @ 07 Dec 2008, 03:48)
Цитата
calling_conversion: 0 - stdcall, 1 - thiscall, 2 - fastcall

А где Pascal? Или его уже отожествляют с Делфи, а FreePascal, TMTPascal, Virtual Pascal и прочее забыты? smile.gif

А зачем? В Героях и в нормальных dll используются только эти и cdecl.
Я забыл написать, что 0 - это и stdcall, и cdecl.
Wic
Цитата
Что касается информации, то опишу очень кратко и применимо к последней версии
ЕРМ-у явно не хватает своего Якова Перельмана smile.gif. Моск сломать можно обо всё это ...

Добавлено ([mergetime]1228670877[/mergetime]):
Кстати, не было мысли написать читабельный язык для ERM ?

Чтобы был на Си/Паскаль похож. Учитывая общую простоту языка это не сильно сложно, написать LL(1)-грамматику с парсером тут достаточно просто будет.
Монца
да хотя бы какую нить обертку-макрос, чтобы можно было константы хоть как то идентифицировать.
hippocamus
Ангел, такое предложение: пусть не в конфиг-файле прописывать имя плагина, а создать каталог Plugins и в него все плагины кидать. Тогда с помощью обычного инсталлятора можно будет интсаллировать аддоны нового поколения. А инсталлятору дать команду дописать в файл гораздо сложнее.

Добавлено ([mergetime]1228671279[/mergetime]):
Отвечаю на предыдущие посты:
есть, и где-то здесь были выложены проги для этого. ищите внимательнее.
Монца
И вообще структуру папок вога надо привести в порядок, а то аж страшно становится.
Монца
Модеры, сделайте отдельный форум по эре.
Ангел, есть одна идейка: возможность патча на лету. Подробнее в личку кину.
Aнгeл
[quote]А зачем? В Героях и в нормальных dll используются только эти и cdecl.
Я забыл написать, что 0 - это и stdcall, и cdecl.[/quote]
Мда, значит я всегда юзаю ненормальные DLL, потому как применяю только соглашение PASCAL.

[quote]Ещё вопросик насчёт совместимости с ТЕ: получается только необходимо проверить что в ТЕ не используются переменные v50-v99 а так всё должно работать.[/quote]
Именно так. Хорн вроде использовал только большие индексы, но мало ли.

[quote]По поводу запароленых сейвов... не пойму почему невозможно.... у тя же я так понял есть возможность подключать dll-ки + уже есть GZipWrite и Рид[/quote]
Да, так и есть. Но фича в том, что управление ЕРМ получает, когда сейв уже записан, ZVS сохранил все нужные данные и скриптописец может сохранить свои, они будут в конце. Чтобы шифровать сейв, нужно перехватывать процедуру GZipWrite, шифровать данные указанным ключом и возвращать управление оригинальному коду. Если подобное дело нужно для турниров, и реально достают читеры, то почему бы и не ввести механизм smile.gif

[quote]Автосейв каунтер - это и есть прога которая просто переименовывает текущий автосейв в автосейв текущего дня[/quote]
Автосейвы можно отключить, а сохранять игру через ЕРМ.

[quote]понял что теоретически реально реализовать ОДНОВРЕМЕННЫЕ ХОДЫ!!!![/quote]
Теорию нужно доказать практикой.

[quote]3) Где-то недавно видел на форуме была ссылочка на дизасемблер, который генерит дополнительно псевдо код,[/quote]
Плагин к IDA, стоимость - 5000 у.е.

[quote]ЕРМ-у явно не хватает своего Якова Перельмана . Моск сломать можно обо всё это ...[/quote]
Если поверхностно пробежаться глазами, то и ЕРМ будет сущим адом для привыкших к строгим ЯП. А если разобраться, то окажется, что всё просто и универсально.

[quote]Кстати, не было мысли написать читабельный язык для ERM ?

Чтобы был на Си/Паскаль похож. Учитывая общую простоту языка это не сильно сложно, написать LL(1)-грамматику с парсером тут достаточно просто будет.[/quote]
В ЕРМ много ограничений, что делает написание подобного диалекта отнюдь не тривиальной задачей. Попробуйте, раз это просто. Все, кто начинал, бросили.

[quote]да хотя бы какую нить обертку-макрос, чтобы можно было константы хоть как то идентифицировать.[/quote]
Компилятору SCVS уже больше года. Входит в Феникс и долгое время лежал на Вог-архиве. Там есть переменные, массивы, константы.

Пример кода:

Код
; Стандартные предбитвенные триггеры
!?BA0&(HUMAN BATTLE);
~~
~Tactics[2] = y1; y1-y2: навык Тактика обоих героев
 !!BA:Q?$Battle.Quick$; получили режим быстрой битвы
; получаем цвета игроков и номера героев
 !!BA:O?$Battle.Owner[0]$/?$Battle.Owner[1]$ H(LEFT)/?$Battle.Hero[0]$ H(RIGHT)/?$Battle.Hero[1]$;
; получаем тип полководцев, ИИ или человек
 !!OW:I$Battle.Owner[0]$/?$Battle.Who[0]$;
 !!VR$Battle.Who[1]$:S(COMP);
 !!OW&$Battle.Owner[1]$<>(NO OWNER):I$Battle.Owner[1]$/?$Battle.Who[1]$;
; определяем тип битвы
 !!VR$Battle.Type$&$Battle.Owner[1]$=(NO OWNER):S(HUMAN HERO vs NEUTRALS);
 !!VR$Battle.Type$&$Battle.Hero[1]$=(NO HERO)/$Battle.Who[1]$=(COMP):S(HUMAN HERO vs COMP MONSTERS);
 !!VR$Battle.Type$&$Battle.Hero[1]$=(NO HERO)/$Battle.Who[1]$=(HUMAN)/$Battle.Who[0]$=(COMP):S(COMP HERO vs HUMAN MONSTERS);
 !!VR$Battle.Type$&$Battle.Hero[1]$=(NO HERO)/$Battle.Who[0]$=(HUMAN)/$Battle.Who[1]$=(HUMAN):S(HUMAN HERO vs HUMAN MONSTERS);
 !!VR$Battle.Type$&$Battle.Hero[1]$<>(NO HERO)/$Battle.Who[1]$=(COMP):S(HUMAN HERO vs COMP HERO);
 !!VR$Battle.Type$&$Battle.Hero[1]$<>(NO HERO)/$Battle.Who[0]$=(COMP):S(COMP HERO vs HUMAN HERO);
 !!VR$Battle.Type$&$Battle.Hero[1]$<>(NO HERO)/$Battle.Who[0]$=$Battle.Who[1]$:S(HUMAN HERO vs HUMAN HERO);
; получаем предбитвенный опыт героев
 !!HE$Battle.Hero[0]$:E?$Battle.Exp[0]$;
 !!HE$Battle.Hero[1]$&$Battle.Hero[1]$<>(NO HERO):E?$Battle.Exp[1]$;
; определяем, будет ли в бою тактическая фаза
 !!HE$Battle.Hero[0]$:S(SKILL TACTICS)/?$Tactics[0]$;
 !!VR$Tactics[1]$:S(DONT KNOW);
 !!HE$Battle.Hero[1]$&$Battle.Hero[1]$<>(NO HERO):S(SKILL TACTICS)/?$Tactics[1]$;
 !!VR$Tactics[0]$:-$Tactics[1]$;
 !!IF:V@Battle.Tactics@/(TRUE);
 !!IF&$Tactics[0]$=0:V@Battle.Tactics@/(FALSE);
; инициализируем счётчик раунда
 !!VR$Battle.Round$:S(BAD ROUND);

; SCRIPT: GENERAL

; !?START SECTION %%% COMPILER %%%

({) = '('
(}) =')'
($) ='$'
(~) = '~'

; !?END SECTION %%% COMPILER %%%


; !?START SECTION %%% HLL (High Level Language) %%%

; Включение/выключение ЕРМ-ошибок (Используется y99 для храенния флага ошибки)
(errors off) = '!!UN:P904/1 P905/0;'; выключить показ ошибок
(errors on) = '!!UN:P904/0 P905/?y99 P905/0;'; включить показ ошибок
(error) = 'y99=1'; была ошибка
(no error) = 'y99=0'; не было ошибки

; Определения Человек/Компьютер
(HUMAN TURN) = '1000'; ход человека
(COMP TURN) = '-1000'; ход компьютера
(HUMAN BATTLE) = '1000'; битва с присутствием человека
(COMP BATTLE) = '-1000'; теоритическая ИИ битва
(HUMAN) = '0'; человек
(COMP) = '1'; комп

; Игроки (Хозяева)
(RED) = '0'; красный
(BLUE) = '1'; синий
(TAN) = '2'; коричневый
(GREEN) = '3'; зелёный
(ORANGE) = '4'; оранжевый
(PURPLE) = '5'; пурпурный
(TEAL) = '6'; берюзовый
(PINK) = '7'; розовый
(NO OWNER) = '-1'; нет хозяина или нейтральный

; Герои
(HERO ORRIN) = '0'; Оррин
(NO HERO) = '-2'; нет героя

; Объекты
(NO OBJECT) = '-1'; нет объекта

; Монстры
(MONSTER PIKEMAN) = '0'; копейщик
(NO MONSTER) = '-1'; нет типа


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

Код, правда, разрастётся немного. Дело в том, что в Винде поиск файлов сделан по кривому. Для корневого диска один синтаксис, для пути, где больше 256 символов другой, где меньше - третий. Впрочем, это не важно. Значится будут подгружаться все DLL из папки "Era Plugins".

[quote]И вообще структуру папок вога надо привести в порядок, а то аж страшно становится.[/quote]
Меня самого коробит. В Соде пара папок и файлов, всё чисто. В Воге - просто энциклопедия файлов и папок с различными названиями.

Добавлено ([mergetime]1228678861[/mergetime]):
[quote]Ангел, есть одна идейка: возможность патча на лету. Подробнее в личку кину.[/quote]
Дельное предложение. Остаётся только выбрать формат для патча. В Mount & Blade используется что-то вроде:

Код
49 1235468 73493 956734286 384634 28546


Для пары мест - это норма. А если много, то время будет зря потрачено на парсинг текстовика и преобразования чисел в integer.
Предлагаю такой вариант:

Код
Адрес[hex] Кол-во байт[hex] хекс-коды подряд#13#10


Пример:

Код
701000 5 9090909090


Для ускорения процесса патчинга и загрузки в целом такой текстовик сперва пропускается через прогу, та переводит всё в машинный формат и проверяет на ошибки. Эре же остаётся лишь только прочитать данные и пропатчить нужные места.
Wic
Цитата(Aнгeл @ 07 Dec 2008, 23:41)
Если поверхностно пробежаться глазами, то и ЕРМ будет сущим адом для привыкших к строгим ЯП. А если разобраться, то окажется, что всё просто и универсально.
Ну ЕРМ больше Ассемблер напоминает, чем языки высокого уровня.

Цитата
В ЕРМ много ограничений, что делает написание подобного диалекта отнюдь не тривиальной задачей. Попробуйте, раз это просто. Все, кто начинал, бросили.
Трудности в придумывании диалекта или в его реализации ? Если первое, то хз, сам ЕРМ пока плохо знаю. А если второе, то это решаемо, было дело писал компилятор Паскаля, и технологию всю эту освоил.
Монца
nop nop nop nop nop
да, очень даже ничего.
Цитата
Предлагаю такой вариант: 
Код
Адрес[hex] Кол-во байт[hex] хекс-коды подряд#13#10
 


а количество байт нужно ли?
Aнгeл
Цитата
а количество байт нужно ли?

Позже дошло, что нет smile.gif

Добавлено ([mergetime]1228679928[/mergetime]):
Цитата
Трудности в придумывании диалекта или в его реализации ? Если первое, то хз, сам ЕРМ пока плохо знаю. А если второе, то это решаемо, было дело писал компилятор Паскаля, и технологию всю эту освоил.

И в том и в другом. Со стороны кажется проще, сперва лучше полностью освоить ЕРМ, а потом делать выводы.
hippocamus
> Адрес[hex] Кол-во байт[hex] хекс-коды подряд#13#10

Можно в ini сделать:

[Patching]
701000=9090909090
702000=909090

Или если нельзя в качестве ключа давать цифры, то

[Patching]
I701000=9090909090
I702000=909090
Aнгeл
А зачем усложнять? Ведь это писать будет человек в блокноте, а ему лишние секции врядли нужны.
hippocamus
Чтобы использовать функцию WinAPI для чтения ключей. К тому же - лично у меня редактор ini-файлов встроен в Тотал коммандер.
sergroj
Цитата(asm @ 07 Dec 2008, 23:04)
3) Где-то недавно видел на форуме была ссылочка на дизасемблер, который генерит дополнительно псевдо код, даже посмотрел там на сайте видео курс - скиньте плиз если кто знает. Мб проще будет разобратся со всеми этими call'ами

http://www.zshare.net/download/5419935d3a79d1/ (спасибо Entuser'у)
[Edit] говорят, что оттуда не качается, так что вот: http://narod.ru/disk/4261296000/IDA%205.2%20Install.rar.html (ida.wll в корне скопируйте в папку Иды, чтоыб она дружила с базами от старых версий)
Сразу скажу, что нисмотря на неработающие стрелки навигации, там можно жать Esc, чтобы перейти к прошлой процедуре.

Цитата(Wic @ 08 Dec 2008, 00:27)
Кстати, не было мысли написать читабельный язык для ERM ?

В 3.59 будет(и уже есть) Луа. Весь ЕРМ можно из нее вызвать.

Цитата(Монца @ 08 Dec 2008, 02:16)
возможность патча на лету.

Да, мне она тоже приходила. Точнее, патчить можно и через UN:C и аналоги для Луа (и CopyMem). А вот хуки в код из Луа ставить... spiteful.gif Тогда бы все, что угодно, можно было сделать. Но думается мне, что это перебор.
Мурсинушка
Тут как я поняла речь идет о времени когда скриптовый язык ещё не загружен.
Монца
Даже когда еще и exe не загружен.
Монца
Цитата
Можно в ini сделать:

[Patching]
701000=9090909090
702000=909090

Или если нельзя в качестве ключа давать цифры, то

[Patching]
I701000=9090909090
I702000=909090

Мне кажется здесь это будет лишним, ини здесь ни к чему. Чем проще, тем лучше.
hippocamus
Почему я собственно предложил ini, потому что была такая мысль - вместо всех текстовиков, которые есть в вог-архивах (Action, h3sprite и проч.) использовать один - Install.ini, в котором всё это и прописать.
И тогда в нём же можно и добавлять адреса для ран-тайм патчинга.
asm
Цитата(sergroj @ 08 Dec 2008, 03:50)
http://www.zshare.net/download/5419935d3a79d1/ (спасибо Entuser'у)
Сразу скажу, что нисмотря на неработающие стрелки навигации, там можно жать Esc, чтобы перейти к прошлой процедуре.

Это ссылка на IDA ? И там в составе HEXRays ? Или HEXRays надо будет отдельно доставить ?
Монца
это неудобно, чтобы пропатчить пару мест придется изменять здоровенный файл с остальными настройками.
Лучше для патча использовать отдельный файл.
Aнгeл
Как реализовывать шифрование сейва? Пока что не совсем ясен алгоритм. Не ясно также, как определить кто сервер, а кто нет.
asm
Цитата(Aнгeл @ 10 Dec 2008, 22:07)
Как реализовывать шифрование сейва? Пока что не совсем ясен алгоритм. Не ясно также, как определить кто сервер, а кто нет.

Алгоритм следующий:
- Перед началом игры оба игрока вводят пароль, ну или сохраняют в ТЕ.ini
, ну в общем так что бы программа могла получить доступ до паролей обоих игроков
- При сохранении применяет пароль склееный из 2-х половинок
Правда есть некоторые скользкие моменты:
- Как загрузить сейв если игра вылетела
Aнгeл
Нужна помощь по тестированию Эры в сетевых играх. Потому как после финальной версии, над которой я работаю, изменения больше вноситься не будут.
Aнгeл
Насчёт шифрования сейвов. Если нужна защита от обычных людей, не сведующих в ЕРМ и файлокопательстве, то делается всё просто.
На старте каждый игрок вводит пароль, из них лепится один, который через ЕРМ отправляется каждому игроку и запоминается в глобальной переменной. В триггере загрузки карты выводим диалог с просьбой ввести пароль. Если пароль неверный, то вызываем исключение с вылетом:

!!UN:C0/4/7;
hippocamus
Подожди, не будут. А как насчёт надстроек Дьякона по новым городам, кричам и проч.?
Aнгeл
Это уже полностью Дьякова задача. Эра автономна. А в своих длл можно реализовывать что угодно - любые нужные процедуры на экспорт и любые новые события.
Монца
Останется только быстро поправить лог. Про пароли - не стоит это того, читеров это не остановит, есть куча других способов играть не честно.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Форум IP.Board © 2001-2025 IPS, Inc.