+- Wake of Gods Forum | Форум Во Имя Богов (http://wforum.heroes35.net)
+-- Forum: Герои Меча и Магии 3.5 WoG/ERA (/forumdisplay.php?fid=99)
+--- Forum: Библиотека по моддингу (/forumdisplay.php?fid=186)
+--- Thread: Исследование героев (/showthread.php?tid=862)
очень полезно! ждем примеров динамического патчинга, желательно под Era. В примерах под Era кажется было что то похожее, однако, чем больше примеров тем понятнее!
RE: Исследование героев - NIKr0m@nceR - 12.12.200917:13
ссылка на летитбит не канает
RE: Исследование героев - Дьякон - 26.12.200916:39
По просьбе трудящихся, небольшой туториал по подгрузке длл в процесс:
Спасибо за помощь!
Только ИДА огромна... не ожидал. Траффик (тем более не мой) скачать пока не позволяет.
RE: Исследование героев - etoprostoya - 07.02.201013:14
В ИДА включена поддержка множества различных редких платформ, потому и огромна.
RE: Исследование героев - Дьякон - 07.02.201020:37
MOP для начала вполне хватит Оли. Там в принципе все что нужно. Иду конечно тоже не плохо иметь. Но думаю тебе и Оли хватит пока. Тем более если ты все через артмани находишь )))))
RE: Исследование героев - feanor - 08.02.201001:14
создал dll позволяющую расширить список стартовых героев за счет добавления героев из кампаний. Пока добавляются Мюллих и Катерина и банятся Сильвия и Саня. Потом доделаю, чтобы список динамически расширялся.
Большое спасибо Сергею Роженко, ASM, Дьякон, Берсеркер за большую помощь в создании этой dll.
Скачать можно здесь: http://www.heroes-iii.com/files/sag_dll_v1.zip
RE: Исследование героев - Berserker - 21.02.201000:33
SAG, для паблика более интересен адрес массива с героями и принцип.
RE: Исследование героев - feanor - 23.02.201021:26
Благодарю!
RE: Исследование героев - GhostManSD - 01.09.201011:57
После того, как увидел то, что можно творить через !!UN:C, очень хочется научиться творить такое самому. В наличии имеются Ida Pro, MASM, Asm_Ed, CodeView, Hiew, OllyDbg, Peid, QuickUnpack. Есть, как видите, многое, но навыка - ноль. Подскажите, пожалуйста, полезную литературу по данному вопросу, поскольку здесь я - даже больший нуб, чем в ERM.
Через АртМани, а потом !!UN:C уже умею менять кое-какие тексты и данные (спасибо огромное MOP'у и gamecreator'у за ценные советы). Однако этого явно недостаточно. Хочется иметь куда большие возможности. В частности, интересует методика создания новых триггеров.
Quote:В частности, интересует методика создания новых
триггеров.
Мне тоже это очень хотелось бы знать. Там вроде надо что-то менять в коде, но как найти, где и понять на что?
RE: Исследование героев - GhostManSD - 01.09.201012:53
Насколько я понял из исходника dll для Эры, который мне предоставил MOP, отлавливается адрес и при обращении к этому адресу выполняются нужные действия.
RE: Исследование героев - Berserker - 01.09.201015:04
Так и есть. Достаточно выучить азы ассемблера. Руководства можно найти на wasm.ru, как и весь нужный интрументарий.
Суть создания "нового триггера" в Эре - это в нужном месте кода героев/вога:
Прописать прыжок на свою функцию
Сохранить контекст исполнения
Сохранить параметры нового события, чтобы их можно было достать через SN:X
Вызвать функцию вога: CallFunc с номером функции
Вызов приведёт к вызову функции ЕРМ и т.д.
Восстановить контекст исполнения (регистры, флаги, чаще всего только регистры через POPAD)
Выполнить код героев/вог, затёртый нашим перехватчиком
Вот длл с более подробным (откомментированным) исходником. Создаёт триггер на лечение Палаткой.
Константы взяты из исходников ЭРЫ, ибо так удобнее. Авторская процедура - HOOK_tent.
Как пользоваться триггером - написано здесь.
RE: Исследование героев - GhostManSD - 01.09.201015:38
Bers, огромное спасибо! А как это же через !!UN:C?
Научил плохому...
Через UN:C это фактически и не делается. Просто я для тех, у кого даже ЭРА не стоит, делаю новые события с помощью записи командой UN:C в неиспользуемые игрой участки памяти того же самого ассемблерного кода. Вот те два события (пост-HL и вход в экран города) я записал, кажется, в неиспользуемую после загрузки exe сод-таблицу Трансформатора Скелетов.
Ответ: учить асм, больше никак.
RE: Исследование героев - Berserker - 01.09.201016:38
MOP, спасибо за пример. Довольно чётко. Разве что "PTR DS:" лишние...
RE: Исследование героев - GhostManSD - 01.09.201017:06
Через dll даже лучше. Но здесь нужны доп. программы. Я пытался скомпилировать исходник MOP'а, заменив номера функций, но мои Турбо и Визуал Паскали выдали ошибку: ТП - что пропущен бегин, ВП -что нет файла win.vpi (ошибка 15). Может, надо через что-то еще? Хотя для файла с расширением pas что еще может быть...
RE: Исследование героев - Berserker - 01.09.201017:22
GhostManSD, Virtual Pascal из папки Эры запускал?
/попробуй команду Make вместо Compile.
(01.09.2010 16:38)Berserker Wrote: MOP, спасибо за пример. Довольно чётко. Разве что "PTR DS:" лишние...
Учту. Я просто скопировал комментарий из исходника к бинарнику. Себе-то длл-ок пока не делаю - для этого мне нужна какая-то... глобальная задумка, что ли (как для тебя - ЭРА). А пока всё в exe...
А вот это самое сложное и трудозатратное...
Пример есть в туториале Дьякона. Игра по ходу выполнения кода обращается к ресурсам - картинкам, дефам, звукам, текстам. Поставив брейкпойнт на указатель к этому ресурсу, находим примерный интересующий нас участок кода и рассматриваем его. Я, например, вышел к лечению Палаткой через указатель на звук regener.wav.
Но далеко не всегда так просто. Порой надо обладать чутьём, представлять, в каком виде могут храниться данные. Почти интуиция.
Это который должен быть по ссылке в первом посте темы? Ссылка не работает.
RE: Исследование героев - feanor - 01.09.201018:38
Не портите нервы связкой паскаля и асма, припудренной милыми досовскими средами.
Портите нервы связкой С и асма.
Quote:Как можно найти это нужное место?
Тут надо предметно смотреть - в каждом конкретном случае вопрос особый.
На палатку я бы выходил через давно записанный на бумажке адрес свитча на действия юнитов в бою. Этот свитч я нашел через функцию каста заклинаний. А её я нашел, кажется, через функцию проигрывания звука.
RE: Исследование героев - gamecreator - 01.09.201019:23
MOP, а если в том неиспользуемом участке патч какой-то записался? получится каша.
+ ещё одна причина делать это по-человечески, а не UN:C.
Но не буду же я объяснять простому человеку, как поставить ЭРУ или прилепить длл к экзешнику.
RE: Исследование героев - Berserker - 01.09.201019:30
Quote:Портите нервы связкой С и асма.
Ничем не лучше, если не считать, что из-за крайней низкоуровневости, что-то большое писать без ошибок нереально. По поводу среды - использую Delphi, но не его IDE, а notepad++. Писать можно в чём нравится и как нравится, а компилировать хоть через командную строку. И как сказал ZVS на ag.ru, это не досовское окно, а полноценное win-32 приложение.
Quote:брейкпойнт
Перевожу: точка останова.
Quote:свитча
Перевожу: разветвление/переключатель (серия подряд идущих если..то).
RE: Исследование героев - feanor - 01.09.201019:58
Quote:Перевожу: точка останова.
Кстати, о бряках.
В той же оле есть три вида бряков: Int3, Memory и Hardware.
Первый ставится на код и срабатывает, что характерно, при проходе про коду.
Второй ставится на память и срабатывает при чтении\записи в память.
Третий может ставиться и на код, и на память, но имеет ряд ограничений - типа, только четыре бряка такого типа, брячится только до четырех байт (и то, зависит от фактического адреса).
Дык вот..для бряков на код лучше использовать первые.
А вот для бряков на память - третьи, несмотря на все их ограничения.
RE: Исследование героев - Berserker - 01.09.201020:11
Аппаратные точки останова обрабатывает процессор (регистры Dr0-Dr3). А Olly реализует это дело через VirtualProtect с нулевыми правами на всю страницу памяти и перехват-обработку исключений. Если доступ к странице нужен редко, то в принципе, терпимо, если постоянно, то тормоза будут существенные.
RE: Исследование героев - GhostManSD - 01.09.201020:27
О Боже... Х_Х
RE: Исследование героев - feanor - 01.09.201020:32
Quote:если постоянно, то тормоза будут существенные.
если обращения чаще, чем примерно раз в секунду - герои нафиг повисают. Приходится ставить-снимать паузу.
Так что, скажем, изменялку параметров героя с меморибряками выявить удастся только при достаточном терпении.
Quote:О Боже... Х_Х
ась? Все оказалось несколько сложнее, чем представлялось?)
Дык на самом деле все сложнее, чем на самом деле.
RE: Исследование героев - Berserker - 01.09.201021:22
Quote:О Боже... Х_Х
Я бы начал с обычного: wasm.ru Введение в крекинг с нуля. Хотя может МОР что посоветует, он вроде как обходился без азов программирования.
RE: Исследование героев - Berserker - 01.09.201021:45
Quote:или чистотой языка
В отличие от жаргона корректный литературный перевод уже несёт 90% смысла даже для человека непосвящённого. В СССР было понятие АВОСТ - аварийного останова. Это самый нормальный перевод для halt, например. Тоже самое и с breakpoint. Это и есть точка останова программы. И человек сразу вникает в суть дела. А жаргон используют все, но не везде же и среди тех, кто понимает.
feanor, по твоему уже удалённому посту. 6[a] в си тоже массив, как и 256[a]{b} и т.д. Но это не полноценный массив с двумя/более измерениями, а просто синтаксический сахар для вычисления адреса (собственно, нельзя создать тип-многомерный массив, массив можно использовать как переменную или одномерный и никакого контроля над границами тоже нет). Касаемо передачи параметра для изменения, это был не юмор. Введённая в Алголе60 конструкция VAR означает, что внутри функции работа с переменной/массивом/структурой вполне прозрачна, но реально компилятор имеет дело со ссылкой. Тем не менее проверка типов остаётся жёсткой. В СИ нет возможности передать аргумент для изменения иначе как использованием низкоуровневого средства ссылки. Именно поэтому, несмотря на тотальную популярность СИ-семейства, я бы не советовал людям формировать своё мировоззрение в сфере программирования, начиная с языка, чей основой является близость к ассемблеру и минимальная типизация. И тем более, если нужно что-то реализовать, а навыков нет. И конечно же, не посоветовал начинать с монстров класса СИ++, Ада, на прочтение одной лишь спецификации по которым уйдёт пол жизни, а остальная половина на знакомство с особенностями компиляторов.
P.S В посте была ошибка. Передача аргумента в качестве изменяемой переменной, а не по значению.
(01.09.2010 21:22)Berserker Wrote: Хотя может МОР что посоветует, он вроде как обходился без азов программирования.
Ну... что я делал без азов программирования? Баловался с Артмани и только. Правда, мне удалось увеличить кол-во монстров и артефактов, но ведь это и не требовало знаний асма. Просто перенаправление указателей, перенесение таблиц и увеличение максимального кол-ва по некоторым адресам. Что к чему лежит и что представляют собой циферки в окошке АртМани - оставалось тёмным лесом.
А первое, что я сделал в Olly - отключил Маскировку и передал контроль её колдовства ERM-функции. Просто подсмотрел, как такое проделал Феанор с книжкой колдовства Сказочного Дракона. На тот момент единственной мне понятной командой асма была jmp.
RE: Исследование героев - gamecreator - 01.09.201022:00
(01.09.2010 21:45)Berserker Wrote: на прочтение одной лишь спецификации по которым уйдёт пол жизни
а можно мне эту спецификацию? хоть раз в жизни почитаю.
RE: Исследование героев - Berserker - 01.09.201022:06
Страуструп "Язык программирования C++"
Стандарты СИ 89, 99
RE: Исследование героев - GhostManSD - 01.09.201022:13
(01.09.2010 21:22)Berserker Wrote:
Quote:О Боже... Х_Х
Я бы начал с обычного: wasm.ru Введение в крекинг с нуля. Хотя может МОР что посоветует, он вроде как обходился без азов программирования.
Bers, самое интересное, что я с этого и начал. Нравится, хорошее руководство, и впрямь для чайников. А то с Калашниковым как-то не пошло...
RE: Исследование героев - Berserker - 01.09.201022:18
Я в своё время Калашникова прочитал, только тольку-то? ДОС уже мёртв, как и 16-битный режим. Фактически, под винду совсем другой ассемблер. Ещё можно глянуть туториалы Изелона. Там, правда, основной упор на WinApi, это чуть позже.
У меня тоже Калашников есть. Тоже читал... засыпая над одной и той же главой. То есть, обучение получилось чисто практическое - OllyDbg + справка по командам ассемблера.
RE: Исследование героев - feanor - 01.09.201022:37
Собственно, для реверсинженеринга нужен именно язык с близостью к ассемблеру и минимальной типизацией. Паскалевские указатели наводят на меня тоску, необходимость явного приведения типов чуть ли не при перегоне из символа в число - напрягает.
___________________
Я реверсинженерингом Героев занялся после успешной сдачи экзамена по АЭВМ (ну то бишь по основам ассемблера).
До этого правда был небольшой опыт ковыряния дампов мобильников
(брр..отсутствие толковых отладчиков, любая ошибка в коде роняет все к чертям собачьим, никакая плавающая арифметика - короче, адЪ кромешный)
, но ARM таки несколько отличается от x86 :D
RE: Исследование героев - gamecreator - 01.09.201022:43
RE: Исследование героев - Berserker - 01.09.201022:51
Quote:Собственно, для реверсинженеринга нужен
Для обратного инжиниринга нужен отладчкик и/или дизассемблер. А вот писать плагины и серьёзные вещи нужно как раз-таки на безопасных языках. Ассемблер в паскале толковый, приведение типов нужно редко (и уж точно не для перевода символ-код для которых везде есть функции ord/chr), а когда нужно - делается осознанно и остаётся при этом низкоуровневым. Символ ^ - дело привычки. Выглядит не элегантно, но не так ужасно, как, простите, уродливая перегрузка математического оператора "*" или СИ++ вариант перегрузки СИ++ операции И "&". Впрочем, ко всему привыкаешь, я синтаксиса специально не касался. Тот, кто пишет часто на динамических языках, понимает, насколько сильно важна строгая типизация для создания хоть сколько-нибудь надёжных систем. Мой опыт программирования на PHP и JavaScript твердит, что даже эмуляция типизации позволяет словить орду ошибок ещё на ранних стадиях выполнения. Иначе мы имеем дело с уже известным законом, что написание кода отнимает 10% времени, отладка 90% + никакой гарантии, что код корректен или в будущем не обвалится. В общем всё это субъективный опыт, так что лучше вернёмся к предмету темы. Добавлено:
Quote:и что там такого страшного?
Ничего, кроме over 1100 страниц текста + бесконечного упоминания, что реализация той или иной фичи зависит от компилятора.
RE: Исследование героев - GhostManSD - 01.09.201022:54
Как-то содержание темы немного стало выходить за пределы "Героев".
RE: Исследование героев - GhostManSD - 02.09.201001:19
Пфф, прочитал и почти полностью осилил первые 4 статьи из "Введения в крэкинг с нуля". На сегодня хорош, а завтра повторим.
RE: Исследование героев - GhostManSD - 02.09.201011:44
Сразу большая просьба к тем, кто давно этим занимается: было бы, наверное, неплохо составить список адресов - какой адрес за что отвечает. И отправить этот список, например, в первый пост. Первое, что привожу на данную тему, - адрес, найденный Сергроем:
0x4DAF06 - после повышения уровня любого героя
RE: Исследование героев - feanor - 02.09.201012:30
RE: Исследование героев - GhostManSD - 04.09.201010:53
Камрады, пожалуйста, подскажите, какой адресок отвечает за активацию/деактивацию кнопки "Журнал" на карте приключений. Или, что тоже неплохо, подскажите способ поиска этого адреса. Искать пробовал так: ставил герою 999 копейщиков, ставил штук 20 стражей прохода с требованием принести 1 копейщика и, подходя к очередному стражу, отдавал или не отдавал копейщика. В артмани искал неизвестное значение, и, в зависимости от отдачи или невыдачи копейщика и изменения кнопки "Журнал" (всегда старался, чтобы в журнале было максимум одно задание), нажимал "Отсеять -> значение изменилось/не изменилось". Не нашел. Впрочем, тут и способ дурной.
Простейший способ - сменить id кнопки на какой-нибудь незаюзанный:
Кнопка теперь будет иметь CM:I = 50, станет нажимаемой всегда, но утратит свою функцию и подсказки по ПКМ и наведении мыши. Но это, думаю, то, что тебе и надо.
RE: Исследование героев - GhostManSD - 04.09.201011:05
MOP, подскажи, пожалуйста, как ты узнал, что для этого нужен адрес 4200424(dec).
Попросту вбил "iam004" (деф кнопки) в поиск по дизассемблеру. Сразу пришёл к указателю. А параметры отрисовки элементов диалогов мне как бы уже знакомы - следующим параметром за дефом в функцию идёт id.
Дополнил код выше. Второй адрес - для раскраски кнопки в цвета игрока. Его я не находил - мне Бараторч подсказал.
RE: Исследование героев - GhostManSD - 04.09.201013:26
RE: Исследование героев - Berserker - 05.09.201023:54
Quote:Берс, можешь объяснить суть триггеров входа в окно героя и выхода из оного?
Тебя интересует, как это юзать в Эре или почему именно так реализовано?
RE: Исследование героев - GhostManSD - 05.09.201023:55
Ну, меня интересует, можно ли таким же образом состряпать функцию для кода из второго спойлера. Добавлено:
Для функции 90002.
RE: Исследование героев - Berserker - 06.09.201000:52
C_FUNC_ZVS_CALLFU = $74CE30; // void FUCall(int n)
Я использовал константу для адреса функции обработки события вызова ЕРМ-функции. А феанор тебе просто дал числовое значение адреса, что одно и то же.
У тебя следующие ошибки:
1) Имена экспортируемых в кавычках должны быть.
2) Функции не нужно вызывать, просто пиши ЕРМ обработчики !?FU90001; ...
3) Секция exports должна быть одна и находиться до BEGIN Hook... END.
4) В секции записи друг от друга отделяются ",", а лишь в конце ";"
Code:
EXPORTS
HOOK_Trigger_TownEnter NAME 'Trigger_TownEnter',
HOOK_PostTrigger_HeroLevel NAME 'PostTrigger_HeroLevel',
HOOK_Trigger_RecruitingTroops NAME 'Trigger_RecruitingTroops';
RE: Исследование героев - GhostManSD - 06.09.201002:11
Bers, спасибо огромное! Всё работает!
RE: Исследование героев - GhostManSD - 06.09.201002:51
Подскажите, пожалуйста, вот какую штуку. Есть желание сделать триггер при найме существ. Нашел деф кнопки "нанять максимум существ", ввел в поиск по ссылкам, попал в ту часть кода, где эта кнопка создается и помещается. Теперь - главное: как выйти от момента создания кнопки в диалоговом окне к тому самому моменту, когда происходит первый запрос на создание диалогового окна?
Иными словами - как выйти на тот адрес, на который и нужно ставить ловушку? Добавлено:
Кстати, значение адреса 0x74CE30 дал мне не feanor, а MOP, за что ему тысячу раз спасибо!
RE: Исследование героев - Berserker - 06.09.201011:29
Там где создаётся, открой стёк вызовов. Либо в этой же функции, либо в одной из родительских генерируется действие.
RE: Исследование героев - GhostManSD - 06.09.201011:44
Теперь практически обратный вопрос: адрес выхода из окна искать так же? Иными словами, искать адрес, к которому обращается игра при закрытии окна, нужно так же?
Вот есть, например, окошко найма существ. Нужно найти три адреса: один - если игрок нажал кнопку покупки и успешно купил существ, другой - если игрок нажал кнопку покупки, а купить не смог (а-ля не хватает провизии), третий - если игрок нажал кнопку отмены. Порядок действий таков (например, хотя можно наверняка и иначе):
1. Найти в ссылках деф кнопки "нанять всех".
2. Открыть стек вызовов.
3. Поставить точку останова на все вызовы и по одному отсеивать их, снимая эти точки останова, пока не найду нужные.
Я правильно понял?
RE: Исследование героев - Berserker - 06.09.201014:59
Не правильно. Узнать купил или не купил можно в пост триггере, сравнив армию до и после. Так что нужно делать один перехватчик вызова функции диалога найма героя. Сперва генерируешь событие открытия, затем выполняешь геройскую функцию, затем событие закрытия. После этого возвращаешь управление игре.
RE: Исследование героев - GhostManSD - 06.09.201015:15
А события открытия/закрытия искать в Олли в стеке вызовов? Ставя точки останова на каждом из этих адресов? Добавлено:
И что имеется в виду под пост-триггером? !$FU%номер функции для открытия окна диалога%?
RE: Исследование героев - Berserker - 06.09.201015:18
GhostManSD, не могу помочь, не так много времени. Читай литературу, разбирайся сам по-тихоньку, всё ведь не всегда однозначно, чтобы 100%-ый рецепт выписать. Научившись трассировать программы по шагам, смотреть дамп и состояние переменных, легко сможешь определять то, что тебе нужно. А иначе вопросы будут постоянно.
RE: Исследование героев - feanor - 06.09.201018:22
Quote:третий - если игрок нажал кнопку отмены.
ищешь обработчик нажатий кнопок в диалоге. В конкретно данном случае искать легко - через бряк на 4F6C00 (показ сообщения). Кнопка с номером 30721 (дес.) - кнопка закрытия диалога.
RE: Исследование героев - GhostManSD - 06.09.201019:39
Номер получен путем опытов или интуитивно (кнопка ОК в CM:I - 30720)?
RE: Исследование героев - GhostManSD - 07.09.201003:10
Правильно ли я понял по поводу дефа той или иной кнопки, что данные располагаются в общем и целом примерно так (жирным выделена строка, к которой прихожу по поиску дефа):
Quote:???
???
кнопку можно нажать? -- 0 (да) / 1 (нет)
вид нажатой кнопки -- кадр дефа
вид обычной кнопки -- кадр дефа деф -- указатель с именем дефа
номер кнопки -- 512 (нанять всех) / 30720 (OK) / 30721 (отмена)
???
???
положение x -- вероятно, в пикселях
положение y -- вероятно, в пикселях
Не мог бы кто-нибудь объяснить суть команд, стыдливо прикрытых знаками "???"? Я пробовал поиграться со значением, но вроде ничего не изменилось.
Осталось теперь понять, как от всего этого великолепия выйти к моменту создания самого диалога.
RE: Исследование героев - gamecreator - 07.09.201009:26
(07.09.2010 03:10)GhostManSD Wrote: Не мог бы кто-нибудь объяснить суть команд, стыдливо прикрытых знаками "???"?
там может быть адрес обработчика нажатия (4 байта)
RE: Исследование героев - GhostManSD - 07.09.201010:49
Там вроде какие-то маленькие значения в духе 20, 40, 1, 2, etc. Некоторые интересные для меня адреса я нашел в call functions, ставя по очереди на них бряки:
1. Нажатие в окне найма "нанять" или "отмена". Действует почему-то лишь на экране города, в жилище действует лишь "отмена". Не там ищу?
2. Нажатие при заходе в жилище кнопки "ОК" при вопросе "хотите ли вы нанять...?".
3. Адрес перед высвечиванием диалога.
Нужен хук именно на кнопку "нанять".
RE: Исследование героев - GhostManSD - 07.09.201010:56
Причем хук на ее нажатие именно в окне жилища. В замке все равно все в гарнизон нанимается. А герою все равно уже туда не попасть.
RE: Исследование героев - feanor - 07.09.201021:57
Quote:???
???
положение x -- вероятно, в пикселях
положение y -- вероятно, в пикселях
3 и 4 параметры - ширина и высота нажимаемой области.
RE: Исследование героев - GhostManSD - 07.09.201022:55
feanor, спасибо!
RE: Исследование героев - baratorch - 08.09.201001:36
Я обычно делаю так:
1. по названию дефа нахожу функцию создающую диалог с этой кнопкой.
2. запоминаю ID кнопки, он PUSHится прямо рядом с PUSHом имени дефа.
3. Ищу функцию обработки сообщений этого диалогового окна, ставя бряк на известную мне функцию, которая точно вызывается и з этого обработчика (например функция показа сообщения)
4. в функции обработки сообщений окна нахожу место где идет проверка на равенство ID нажатой кнопки тому который запомнил и вуаля.
Но не представляю сколько времени потребуется чтобы все это осуществить только с помощью Олли.
HexRays в ИДЕ - это моё всё.
RE: Исследование героев - gamecreator - 08.09.201001:57
(08.09.2010 01:36)baratorch Wrote: Но не представляю сколько времени потребуется чтобы все это осуществить только с помощью Олли.
дилетантам типа меня или GhostManSD - около 15 минут. Добавлено:
это, конечно, если использовать артмани для поиска текста
RE: Исследование героев - GhostManSD - 08.09.201002:29
gamecreator, тогда предлагаю исключить тебя из списка дилетантов: мне явно потребуется больше. Поясняю: я - нуб. Впрочем, я делаю все, что от меня зависит, чтобы изменить ситуацию. Кроме того, я элементарно не представляю, что, где и как искать.
Например, до пояснения, что имеет смысл искать по дефу, я вообще не мог ничего. Еще чуть большему научился, когда Берс объяснил, что есть еще штука под названием "стек вызовов".
Но и сейчас мой метод туп и безобразен: открыв стек вызовов, я тупо ставлю точку останова на первый из адресов. Продолжаю выполнение и смотрю, когда произойдет останов. Если точка останова не подходит, возвращаюсь к адресу дефа и снова открываю стек вызовов. Ставлю точку останова на следующий адрес. Снова смотрю на то, когда происходит останов, и то ли это, что нужно. И вот так вот перебираю все адреса в стеке вызовов. Пока что их мало, благо я пока изучаю лишь небольшие окошки (например, окно найма). Но что я буду делать, когда адресов в стеке вызовов будет больше, я даже не представляю.
baratorch, как вот ты, например, искал адрес, отвечающий за цвет кнопки журнала? Я так понимаю, что идут вычисления в духе "а каков же цвет у этого игрока??", итог сохраняется в регистр, а потом уже из регистра присваивается значение. Но мне от этого ни горячо, ни жарко, поскольку я не знаю:
1. Как найти этот адрес.
2. Какой именно из них менять.
Ad exemplum. Вот ищу я славный момент, когда же у нас запускается окошко найма существ во внешнем жилище. Иду этим путем. И что же? Результат для точек останова сразу на три или четыре адреса - один: при первом же запросе к окошку срабатывает точка останова. И бес его знает, какой из адресов мне нужен.
GhostManSD Wrote:Вот ищу я славный момент, когда же у нас
запускается окошко найма существ во внешнем жилище.
Иду этим путем. И что же? Результат для точек останова
сразу на три или четыре адреса - один: при первом же
запросе к окошку срабатывает точка останова. И бес его
знает, какой из адресов мне нужен.
Если тебе надо сделать что-то, не связанное непосредственно с диалогом, наверное, подойдёт любой.
Только лучше проверять на нескольких разных жилищах.
RE: Исследование героев - GhostManSD - 08.09.201019:33
Вопрос адресован в первую очередь baratorch. По поводу отлова адреса, где нажимается кнопка. Взять то же окошко найма, например. Ищем деф кнопки покупки. Нашли. Переходим на адрес (например, по адресу AAAAAA). Чуть ниже (по адресу AAAAAB) - то, что я называю BID (button id). BID=7802. Снова иду на строчку дефа, нажимаю стек вызова. Появляется окошко с вызовами, под каждым из вызовов идут строки в духе "[адрес]argument1=x", "[адрес]argument2=y", etc. Вместо x и y написаны адреса. Я так понимаю, мне нужно найти случай, где "argument#=[адрес, где расположен BID]", и поставить на него ловушку. Я верно понял твой способ? Поскольку нигде нет данных типа "если x=7802, прыгнем-ка мы туда...".
RE: Исследование героев - gamecreator - 08.09.201019:51
ну как же... сразу после того, как функция, которой передается ид кнопки, отработает, идет проверка возвращаемых значений что-нибудь типа cmp eax,1E7Ah
RE: Исследование героев - GhostManSD - 08.09.201020:07
Вот я именно это и имел в виду. Значит, угадал: сравнивается не BID, а его адрес. Спасибо.
RE: Исследование героев - gamecreator - 08.09.201022:19
какой еще адрес? сравнивается код кнопки!
RE: Исследование героев - GhostManSD - 08.09.201022:48
То есть для кнопки с кодом ID=7802 должно быть cmp eax, 7802?
RE: Исследование героев - GhostManSD - 08.09.201023:44
Подскажите, пожалуйста, за что отвечает этот адрес: 0x42437D.
Более подробная информация - здесь.
RE: Исследование героев - gamecreator - 08.09.201023:46
(08.09.2010 22:48)GhostManSD Wrote: То есть для кнопки с кодом ID=7802 должно быть cmp eax, 7802?
я так и написал. но в олли ты увидишь только шестнадцатеричные значения, поэтому для тебя я перевел 7802: будет 1E7A. а буква h в конце значит что число записано в шестнадцатеричной системе исчисления.
RE: Исследование героев - GhostManSD - 08.09.201023:51
Quote:для тебя я перевел 7802: будет 1E7A
Лол, мы просто друг друга не поняли. Я и написал в hex, так, как отображается в окне Olly.
RE: Исследование героев - gamecreator - 08.09.201023:55
а, так надо ж было или 7802h написать, или 0x7802
RE: Исследование героев - GhostManSD - 09.09.201000:56
Каков аналог NOP для команды UN:C?
RE: Исследование героев - Berserker - 09.09.201000:59
Опкод нопа - 90h = 144
RE: Исследование героев - baratorch - 09.09.201003:12
(08.09.2010 22:48)GhostManSD Wrote: То есть для кнопки с кодом ID=7802 должно быть cmp eax, 7802?
в большинстве случаев проверяемые ID элементов окна в функции-обработчике находятся внутри switch-ей, поэтому ситуация cmp <ID>, 0x7777 встречается редко.
RE: Исследование героев - gamecreator - 09.09.201009:39
так свич - это и есть последовательность сравнений и прыжки на соотв. позиции.
RE: Исследование героев - GhostManSD - 09.09.201010:14
Bers, спасибо! Т.е. если я хочу забить адрес NOP-ами, то я должен ввести !!UN:C[адрес] / [размер адреса] / 144;? А где размер адреса смотреть? Артмани подойдет?
RE: Исследование героев - Berserker - 09.09.201014:55
nop - однобайтовая команда, а смотреть в оле, там слева от команд пишутся байты опкодов: e7 12345678 - 5 байт, 5 nop-ов нужно по одному.
RE: Исследование героев - feanor - 09.09.201019:57
Quote:так свич - это и есть последовательность сравнений и прыжки на соотв. позиции.
не всегда. Скажем, для свитчей на свойства существ используются две таблицы - таблица существ и таблица адресов обработчиков того или иного свитча. А итоговый код выглядит так:
3F - номер первого существа (артефакта, заклинания) в таблице соответствий.
797A4C - адрес таблицы соответствий (хранит номера ветвей-кейсов)
4412C0 - адрес таблицы обработчиков (хранит адреса ветвей-кейсов)
RE: Исследование героев - gamecreator - 09.09.201020:33
хм, интересно
RE: Исследование героев - etoprostoya - 09.09.201021:01
Таблица NOP'ов с разным числом байт. (Макрос для MS VC)
RE: Исследование героев - gamecreator - 09.09.201023:24
db size dup(90h)
RE: Исследование героев - etoprostoya - 09.09.201023:41
(09.09.2010 23:24)gamecreator Wrote: db size dup(90h)
Так не интересно. Хотя, конечно, читается лучше.
RE: Исследование героев - gamecreator - 10.09.201001:10
зато сразу видно где забитые байты
RE: Исследование героев - GhostManSD - 10.09.201003:12
Подскажите, пожалуйста, как найти адрес стандартного триггера WoG. Например, !?HE.
Кажись, вник. В комментариях - ошибки на неправильный синтаксис. Будем копать оттуда.
RE: Исследование героев - GhostManSD - 10.09.201004:09
Нашел место, где сравниваются данные из EBP и номер героя (ввел специально неправильную команду !?HE-1). Вопрос: что теперь делать, чтобы присвоить -1 значение типа "если x=-1, то выполнять для каждого значения от 0 до 156"? Куды иттить, то бишь, где этот гребаный x искать?
RE: Исследование героев - feanor - 10.09.201010:47
Quote:+) Добавлено новое событие 77010: Any Hero Interruction (аналог !?HE для всех героев). Параметры события: Герой-Инициатор, Герой-Цель.
Событие, как и оригинальное !?HL, возникает дважды: до и после взаимодействия.
Пример:
!?FU77010;
!!SN:X?y1/?y2;
!!IF:M^Initiator: %Y1, Target: %Y2^;
Не то?
RE: Исследование героев - GhostManSD - 10.09.201013:39
Гм, откуда это? Из Era.chm? Мне сейчас интересна не сама функция, а принцип поиска нужных значений для самой функции и ее создание. Пытаюсь учиться.
RE: Исследование героев - Berserker - 10.09.201015:28
Из хэлпа по изменениям в Эре 1.8. А так верно идёшь, находишь триггер !?HE ZVS, там он генерит событие в зависимости от нового героя. Ищешь, в каких регистрах герой-источник, герой-приёмник и пишешь свою реализацию. Код из Эры:
Code:
PROCEDURE Hook_HeroesMeet_Call; ASSEMBLER; {$FRAME-}
ASM
// Если триггер - !?OB, то возвращаемся
CMP DWORD [EBP+$1C], 34
JNE @@Exit
// Получаем номер героя-инициатора
MOV EAX, [$69CCFC]
MOV EAX, [EAX+4]
MOV DWORD [General.EventParams], EAX
// Получаем номер цели
LEA ECX, [ECX-30100]
MOV DWORD [General.EventParams+4], ECX
// Генерируем ЕРМ-событие
PUSHAD
PUSH General.C_ERA_EVENT_HEROMEET
CALL General.GenerateCustomErmEvent
POPAD
// Возвращаем управление ZVS
@@Exit:
PUSH $74D760
PUSH $74C816
END; // .procedure Hook_HeroesMeet_Call
RE: Исследование героев - GhostManSD - 10.09.201019:20
Bers, я сейчас писал, что я нашел место, где сравнивается номер героя с 0 и со 155. Но это для того, чтобы игра знала, выдавать или не выдавать сообщение об ошибке в духе "баран, героя номер -1 в природе не существует!!111". А мне теперь нужно от этого перейти непосредственно к триггеру !?HE... Вот это-то и представляет сложность: я не знаю соли.
RE: Исследование героев - GhostManSD - 11.09.201000:12
Так, ошибку при чтении игрой команды "!?HE-1;" затёр. Если кому нужно, вот исходник. Код, на самом-то деле, ничтожен, но приятно, что хоть это сумел...
Подскажите, пожалуйста, как всё-таки искать оригинальный триггер !?HE. Часа четыре пытался что-нибудь сообразить, но никак.
RE: Исследование героев - Berserker - 11.09.201000:37
GhostManSD, такие вещи проще и универсальнее через бинарные патчи делать. Например, нужно занопить 5 байт: адрес 9090909090.
RE: Исследование героев - GhostManSD - 11.09.201000:52
Berserker, спасибо! Осталось теперь узнать, как это делать... Добавлено:
А с поиском триггера никто не подскажет?
RE: Исследование героев - Berserker - 11.09.201001:14
Quote:Осталось теперь узнать, как это делать...
Создаёшь txt файл, в котором пишешь: адрес байты в хекс-формате. Далее BinGen.exe file.txt => file.bin. Бинарный файл просто кидаешь в папку EraPlugins.
RE: Исследование героев - GhostManSD - 12.09.201020:56
Долго думал, куда кинуть. Сперва хотел в тему по ERM, но, думаю, лучше сюда.
Функция для изменения типа и количества существ в армии героя. Зачем это нужно? Ну, например, это позволяет без ритуальных плясок устанавливать отрицательное количество существ.
Code:
; Функция для изменения существ в армии героя
; x1 - номер героя
; x2 - номер слота
; x3 - тип существ
; x4 - кол-во существ
!?FU80001;
!!VRy1:S1170 *x1; Указать номер героя
!!VRy2:S4 *x2; Указать номер слота
!!VRy3:S71112441 +y1 +y2; Вычислить адрес типа существ
!!VRy4:S71112469 +y1 +y2; Вычислить адрес количества существ
!!UN:Cy3/4/x3; Установить новый тип
!!UN:Cy4/4/x4; Установить новое кол-во
Исходные адреса в hex:
[[43D16F9]+492*x1+4*x2] - тип существ
[[43D1715]+492*x1+4*x2] - количество существ
RE: Исследование героев - GhostManSD - 12.09.201022:35
Обновил функцию. Теперь в x3 устанавливается тип существ, в x4 - количество.
RE: Исследование героев - feanor - 13.09.201020:43
Quote:43D16F9
адрес динамический. У меня, к примеру, там FFFFFFFF.
Расово кошерный православного вида указатель на структуру героя:
[699538]+21620+492*<hero>
Прошу прощения за тупой вопрос: динамический адрес может меняться при нескольких запусках программы на одном компьютере или только на разных компьютерах? И вообще, может кто-нибудь дать мне точное определение этого понятия?
RE: Исследование героев - GhostManSD - 13.09.201021:00
feanor, а теперь, пожалуйста, расшифруй. Это такой же указатель, как те, в которых меняется текст?
Ну, например, раньше я в артмани искал, например, текст "Лорд", менял значения для всех по возрастанию, смотрел нужный адрес и искал по нему указатель. Находил нужный и уже адрес самого указателя использовал в функциях.
RE: Исследование героев - baratorch - 14.09.201015:57
Статическая память - это секция данных в экзешнике. Эта память выделяется сразу при запуске экзешника. Для самого экзешника адрес этой памяти (и следовательно всех данных в этой памяти) всегда один и тот же (от запуска к запуску и во время выполнения ехе) и всегда существует (пока экзешник работает).
(Например массивы свойств существ, видео, координат строений в городе хранятся в статической памяти, так как длина этих массивов и размер их элементов (да и содержание тоже кстати) не меняется в процессе выполнения программы.
Динамическая память выделяется/освобождается под те или иные нужды в процессе выполнения екзе в зависимости от тех или иных событий. То есть адрес такой памяти (выделенной под какие-то определенные данные) может менятся не только от запуска к запуску, но и от выделения к выделению в процессе выполнения программы.(Например для списков запущенных диалоговых окон и списков элементов этих диалоговых окон память выделяется динамически, так как длина этих списков и размер элементов этих списков меняется в процессе выполнения программы)
Поэтому запоминать такой адрес не имеет смысла, так как при следующем запуске или даже например при старте другого сценария по этому адресу могут находится совершенно другие данные или вообще память недоступная для чтения/записи для этого процесса и тогда при попытке обращения к памяти по этому адесу мы получим крах программы с сообщением о "насилии над доступом" и что "память не может быть Read(Write)".
RE: Исследование героев - GhostManSD - 16.09.201001:50
Появилось три вопроса.
1. Как можно узнать статический адрес? Например, для того же динамического 43D16F9 пробовал искать указатель в Артмани - не находит. И вообще у меня этот адрес не меняется никогда и всегда хранит одну и ту же информацию, а именно - тип существ в первом слоте Оррина. Может, он и не динамический вовсе?
2. Если я добавлю деф в h3sprite.lod, для него появится свой адрес? Иными словами, смогу ли я обращаться к дефу в дизассемблере? Например, менять деф кнопки на MYDEF.DEF?
3. Самое важное. Я поставил хук на какой-либо адрес. Добавил функцию 90004. Как мне сделать, чтобы, если x1=0, эта функция меняла содержимое адреса на одно значение, а если x1=1, то меняла ла бы содержимое того же адреса на другое значение?
RE: Исследование героев - Prayer - 16.09.201008:38
Quote:Я поставил хук на какой-либо адрес.
Добавил функцию 90004. Как мне сделать, чтобы, если
x1=0, эта функция меняла содержимое адреса на одно
значение, а если x1=1, то меняла ла бы содержимое того
же адреса на другое значение?
Это после вызова функции, но перед popad.
mov ax, [$91DA38]
cmp ax, 0
jne @@m1
mov bx, zn1;Если x1=0, помещаем 1 значение в регистр.
@@m1:
mov bx, zn2;Если x1<>0, помещаем 2 значение в регистр.
mov perem, bx;Записываем нужное значение в переменную.
RE: Исследование героев - Дьякон - 16.09.201011:55
(16.09.2010 01:50)GhostManSD Wrote: 1. Как можно узнать статический адрес? Например, для того же динамического 43D16F9 пробовал искать указатель в Артмани - не находит. И вообще у меня этот адрес не меняется никогда и всегда хранит одну и ту же информацию, а именно - тип существ в первом слоте Оррина. Может, он и не динамический вовсе?
На твоей машине просто совпадает. На многих других работать не будет. Если ищешь через артмани то попробуй искать указатели на начало блока. А если через отладчик или дизассемблер, то в коде часто видно как идет обращение к этому адресу. Либо перехватывай все memalloc и смотри куда записывается указатель на выделенный блок.
(16.09.2010 01:50)GhostManSD Wrote: 2. Если я добавлю деф в h3sprite.lod, для него появится свой адрес? Иными словами, смогу ли я обращаться к дефу в дизассемблере? Например, менять деф кнопки на MYDEF.DEF?
Вообще мутный какой-то вопрос. Более четкую задачу поставь. Менять деф кнопки можно не заморачиваясь с кодом, если эта кнопка уже существует. А вот если хочешь добавить новый деф и кнопку тогда...
(16.09.2010 01:50)GhostManSD Wrote: 3. Самое важное. Я поставил хук на какой-либо адрес. Добавил функцию 90004. Как мне сделать, чтобы, если x1=0, эта функция меняла содержимое адреса на одно значение, а если x1=1, то меняла ла бы содержимое того же адреса на другое значение?
Ммм... берем справочник по нужному тебе языку программирования и смотрим условные операторы.
RE: Исследование героев - feanor - 16.09.201012:49
Quote:Как можно узнать статический адрес?
Самый грубый способ - шестизначные - статические, семизначные - динамические.
Quote: А если через отладчик или дизассемблер, то в коде часто видно как идет обращение к этому адресу.
Хардвер брякпойнт на чтение интересующих байтов. Когда сработает - смотреть в брякнувшем участке кода, как происходит обращение.
RE: Исследование героев - Дьякон - 16.09.201013:34
(16.09.2010 12:49)feanor Wrote: Самый грубый способ - шестизначные - статические, семизначные - динамические.
Есть и 6-е не статические.
(16.09.2010 12:49)feanor Wrote: Хардвер брякпойнт на чтение интересующих байтов. Когда сработает - смотреть в брякнувшем участке кода, как происходит обращение.
Иногда указатель кочует из процедуры в процедуру в виде аргументов. Поэтому докопаться до истины не всегда так просто.
RE: Исследование героев - feanor - 16.09.201018:06
Quote:Иногда указатель кочует из процедуры в процедуру в виде аргументов. Поэтому докопаться до истины не всегда так просто.
Знаю. В таком случае идем по вызвавшим процедурам. Ну и параллельно смотрим код в HexRays'e
RE: Исследование героев - Дьякон - 16.09.201020:11
(16.09.2010 18:30)Sav Wrote:
Quote:Ну и параллельно смотрим код в HexRays'e
Что такое Hex Rays?
Это страшная вещь . Это Шестнадцатиричные Лучи ))) разрушающие оболочку головного мозга.
А вообще гугл в помощь. Это дополнение к ИДА с С-подобным синтаксисом.
RE: Исследование героев - gamecreator - 16.09.201020:28
легче всего можно узнать статичность адреса, если исследовать секцию памяти, куда указывает адрес. секции можно смотреть в артмани и олли.
RE: Исследование героев - feanor - 17.09.201012:08
Quote:Что такое Hex Rays?
Плагин к Иде, декомпилятор.
RE: Исследование героев - GhostManSD - 18.09.201022:56
Спасибо, с динамическими и статическими адресами вроде разобрался.
NB: по адресу 0x67D86C+40*hero_class находится название класса героя.
RE: Исследование героев - GhostManSD - 18.09.201023:23
Подскажите, пожалуйста, как выйти на адрес, отлавливающий движение мыши по карте... Не координаты x/y/l (их я уже вроде нашел), а при любом движении.
RE: Исследование героев - GhostManSD - 19.09.201003:09
Блин, так и не выходит. Вот есть у меня адрес "71112441(dec)", нахожу два указателя - 42149612(dec) и 42149612(dec). Ни один из них не работает, а вот при обращении по прямой все отлично.
RE: Исследование героев - Дьякон - 19.09.201011:05
GetCursorPos и ScreenToClient Добавлено:
Чтоб не было лишних вопросов - дополню. Вероятнее всего оконная процедура героев реагирует на событие WM_MOUSEMOVE (или чет типа того. Лень лезть в MSDN). Т.е. при изменении положения мыши хоть на пиксель вызывается участок кода ответственный за обработку данного события и вызываются вышеуказанные процедуры. Хочешь иметь координаты мыши перехватывай процедуры. Координаты хранятся в локальных переменных, поэтому не найдешь ты адреса никакого.
RE: Исследование героев - gamecreator - 20.09.201021:19
а еще лучше подключить длл и поставить винапишный хук на сообщения мыши. это если надо движения мыши перехватывать.
RE: Исследование героев - GhostManSD - 20.09.201021:32
Надо отображать в подсказке координаты (как по ПКМ, так и в строке).
RE: Исследование героев - gamecreator - 20.09.201021:37
а, ну тогда хз
RE: Исследование героев - feanor - 20.09.201023:08
Координаты мыши или координаты на карте?
И да, если надо найти функцию вывода хинтов - то ставь бряк на чтение указателя на какую-нить хинтовую строку и лови через него.
RE: Исследование героев - GhostManSD - 20.09.201023:10
Координаты на карте. Спасибо, завтра попробую.
RE: Исследование героев - feanor - 21.09.201000:08
Quote:Координаты на карте. Спасибо, завтра попробую.
Quote:!!UN:C6916632/4/9; (698A18: 09)
включает указание координат в подсказке для почвы/объектов.
я это..энтузиазм не убиваю?
RE: Исследование героев - GhostManSD - 21.09.201023:07
feanor, да нет, скорее, наоборот! Спасибо!
Подскажите, пожалуйста, каков код в Virtual Pascal для того, чтобы сохранить в функции 90005 (которая является ловушкой для одного адреса) x1=[значение адреса A], а x2=[значение адреса B]? Дабы можно было выполнять, например, вот такое:
!?FU90005;
!!IF:M^%X1 %X2^;
RE: Исследование героев - feanor - 21.09.201023:27
С помощью, скажем:
!?CM1;
!!CA-1:U?y-1;
!!IF:M^%Y-1^;
Определяешь номер текущего города и ищешь его в ArtMoney.
Затем заходишь в другой город и отсеиваешь по его номеру.
RE: Исследование героев - GhostManSD - 25.09.201015:58
Sav, да пробовал я. С типом города адрес нашел сразу же, а вот с номером как-то лаговато выходит.
Code:
!?CM1;
!!CM:S?y1 F?y2 I?y3 P?y4/?y5/?y6 H?y7/?y8; Запомнить подтип клика, флаг для клика, место клика, позицию в x/y/l и номера героев
!!CA-1:U?y9 T?y10;
!!IF&y1=12/y2=0/y3=123:M^Номер - %Y9, тип - %Y10^;
В смысле лаговато?
Может быть надо ещё поискать указатели на эти адреса - не думаю, что они статичные.
RE: Исследование героев - GhostManSD - 25.09.201016:22
Лаговато - значит, не находится.
В процессе изысканий обнаружил забавную вещь: у нас есть адрес 0x043D0B57. Он вроде как равен номеру города, который выбран активным в списке справа на экране приключений. Выберите город номер 0. Ставьте заморозку. Попробуйте зайти в город с другим номером. Итог: независимо от того, в какой город вы пытаетесь зайти, будет отображаться экран города 0.
RE: Исследование героев - GhostManSD - 25.09.201016:44
Понял частично, в чем дело: AM отыскивает не номер текущего города, а номер города, который был последним выбран нажатием мышки в окошке города.
Если перемещаться между экранами города по стрелкам "Вверх" и "Вниз", то AM упорно отказывается искать номер текущего города.
RE: Исследование героев - feanor - 25.09.201023:36
Указатель на структуру текущего города -
[69954C]+38.
Первый байт в ней похож на номер города.
RE: Исследование героев - GhostManSD - 26.09.201001:22
Как изменять количество существ в армии игрока, я вроде бы нашел. Возможно ли отключить отображение количества существ в нужном слоте вообще? Помогите, пожалуйста, с составлением функции в духе
!!FU90004:Px1/x2/x3, где
x1 - номер героя
x2 - номер слота
x3 - включить/выключить (1/0) отображение количества
RE: Исследование героев - feanor - 26.09.201001:27
Ищи отрисовку диалога, в ней отрисовку этого искомого числа, и правь, скажем, координаты.
RE: Исследование героев - GhostManSD - 26.09.201003:37
Момент открытия диалога найти нетрудно. А как найти момент его закрытия? Например, момент закрытия окна покупки существ в форте (где отображаются все юниты города).
RE: Исследование героев - GhostManSD - 26.09.201020:41
Разъясните, пожалуйста, как найти адрес закрытия диалога форта в городе. Адрес открытия окна форта - 5D8AF0h (на платформе ERA, по крайней мере). Нужно найти тот адрес, который задействуется при выходе из диалога. Или при нажатии "ОК".
RE: Исследование героев - GhostManSD - 27.09.201001:23
Сразу вопрос вдогонку: могу ли я как-то при посещении объекта показать диалог из числа стандартных? Например, тот же диалог захода в форт города номер 0.
Частенько в коде Героев встречаются команды типа:
lea eax, [eax + 8*eax]
.
Я правильно понимаю, что они нужны для упрощения написания вычислений (вместо:
push ebx
push edx
mov ebx, eax
mov edx, 0
mov eax, 8
mul ebx
add eax, ebx
pop edx
pop ebx
)?
При выполнении есть ли разница между этими командами?
И такой тупой вопрос: можно ли в Иде изменять команды не через Hex-view и как?
RE: Исследование героев - etoprostoya - 04.10.201001:39
Да, примерно так и есть. Разница очевидна - с командой LEA ты не изменяешь другие регистры и не работаешь со стеком.
А когда процессор одинаково быстро выполняет эту lea-команду и "нормальный" код?
RE: Исследование героев - etoprostoya - 04.10.201016:32
LEA-команды выполняются за один такт обычно или даже две-три такие команды за такт, а "нормальный код", который ты привёл, во много раз дольше, в лучшем случае в пять-десять раз.
Но процессору всё равно же надо вычислить, чему равно, eax+8*eax, он что, как-то по-особому вычисляет это в lea-команде?
RE: Исследование героев - etoprostoya - 04.10.201019:38
Именно по-особому.
К тому же в твоём "нормальном" примере изменяются три регистра, а значит их нельзя использовать в других командах, что замедляет выполнение программы (регистры-то часто используемые). Используется стек, то есть идёт обращение к кеш-памяти, на что отводятся дополнительные такты процессора, а в случае с полным кешем, этот кеш нужно выгружать в оперативную память (десятки тактов). Используются три подряд команды mov, что полностью блокирует на несколько тактов блок ввода-вывода, хотя это и не важно, так как дальше идёт длительная команда MUL. Эта команда MUL сама по себе плохая, особенно если в твоём случае блокирует использование сразу трёх регистров и все конвееры процессора или ядра останавливаются, ожидая завершения этой команды.
А команда LEA специально оптимизирована для вычисления формул вида
REG = REG+REG*2N+CONST.
Современные процессоры вычисляют за такт несколько таких команд.
Если память мне не изменяет, то множители (2^N) могут быть только 2, 4 и 8. Этот модификатор команды появился только с i386. Ну и понятно, что умножение на 2^N суть сдвиг на N битов влево. Т.е. *9 и *8 две большие разницы (должно быть). Хотя современные процессоры и умножают уже за 1-2 такта.
RE: Исследование героев - etoprostoya - 05.10.201014:03
(05.10.2010 00:51)ZVS Wrote: Если память мне не изменяет, то множители (2^N) могут быть только 2, 4 и 8.
Ну, может быть и 1. То есть РЕГ = РЕГ + РЕГ. Ноль не считается.
Не знаю как самые-самые последние процессоры, но пару лет назад умножение было не меньше 3-4 тактов. Правда могло проходить сразу два умножения параллельно. Это про 32-разрядное умножение.
РЕГ+РЕГ - это стандартный модификатор, который был еще в 80x86, а множители появились, начиная с i386 специально для быстрого обращения к элементам массивов.
по адресу [6919480]+1170n+137020, где n - номер героя,
находится байт, в котором хранится 1, если герой спит (кнопка "Усыпить/разбудить героя" на карте приключений), иначе - 0.
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
PROCEDURE HOOK_tent; ASSEMBLER; {$FRAME-}
ASM
MOV EAX, $50C7C0
CALL EAX //вызываем функцию вычисления HP-очков, которую мы затёрли своим хуком.
MOV DWORD PTR DS:[$91DA38],-1 //заносим в адрес переменной x1 значение -1 - на случай, если мы не хотим вообще ничего менять в принципе лечения
MOV [$91DA3C], EAX //заносим в адрес переменной x2 исходное значение кол-ва хит-пойнтов, для подробностей и возможных вычислений
PUSHAD //сохраняем регистры
PUSH 29500 //номер ERM-функции. Меняйте на любой доступный.
MOV EAX, $74CE30
CALL EAX //вызываем C_FUNC_ZVS_CALLFU
ADD ESP, 4
POPAD //выталкиваем регистры
CMP DWORD PTR DS:[$91DA38],-1 //проверяем, изменил ли скриптописец кол-во очков HP для лечения
JE @@Default //если не изменил - продолжить код без изменения
MOV EAX,DWORD PTR DS:[$91DA38] // заменить значение очков на значение из x1
@@Default:
PUSH $478538 //адрес возврата в процедуру
END;
BEGIN
HookCode(POINTER($478533), @HOOK_tent, C_HOOKTYPE_JUMP);
END.
Я уже отправил SAG-у файл на почту.
RE: Исследование героев - GhostManSD - 24.10.201021:48
Подскажите, пожалуйста, как затереть/вызвать определенное диалоговое окно (алгоритм). Например, дабы вместо окна таверны вызывалось окно рынка.
RE: Исследование героев - Дьякон - 24.10.201022:57
Элементарно. Менять таблицу jmp-ов для case - а идентификатора зданий.
RE: Исследование героев - GhostManSD - 24.10.201023:11
Вопрос не в здании... Эт я как пример. Хочется иметь возможность в любом триггере вызвать нужный диалог.
RE: Исследование героев - feanor - 25.10.201000:10
В любом не получится. Тот же диалог оставления войск (HE:C) не вызвать в окне города.
RE: Исследование героев - GhostManSD - 25.10.201002:10
Возможно ли узнать адрес стандартных триггеров? Например, !?TM1 и !?TM2. feanor, спасибо! Буду разбираться!
RE: Исследование героев - GhostManSD - 25.10.201002:19
С тем, как искать диалог по кнопке, разобрался. А как найти диалог по тексту?
P.S. Объясните, пожалуйста (если не сложно), как дауну, - пошагово. Потому что иначе не пойму. :-(
кто из гуру может подсказать: как создать статический текст на карте приключений (типа количества ресурсов внизу экрана).
по идее это не должно быть сложно
Кто-нибудь может сказать, с чем может быть связано то, что Герои (Era 1.8) сами по себе нормально работают с моей dll-кой, а при отладке (с такими же скриптами и т. п.) работают по-другому и неправильно?
RE: Исследование героев - Berserker - 14.11.201022:04
Как по-другому и как не правильно? С какой длл и в чём заключается отладка?
Я делаю dll для передачи erm управления ударами в бою. В ней я сделал, условно говоря, режим, в котором она восстанавливает изначальный код (т. е. фактически ничего не модифицирует), включённость этого режима зависит от бита v-переменной.
Если запустить игру со скриптом, устанавливающим этот бит на включение режима, действительно ничего не изменится и всё будет работать так же, как и без dll.
Если же запустить тот же экзешник (с теми же скриптами и т. п., той же dll, включённым режимом немодифицирования) через отладчик Иды (в моём случае Windbg debugger), то в определённом месте будет попытка считать что-то из недоступного участка памяти (чего нет при обычном запуске). Если удалить dll и запустить Герои через отладчик, всё будет нормально.
RE: Исследование героев - Дьякон - 14.11.201023:08
Тут без экспертого навыка экстросенсорики и пол литра не разобраться. С кодом длл и принтскрином ошибки как-то проще бы было.
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;
//Модификация удара с флагом бить всех вокруг.
//Вместо вычисления 8-ми атакованных позиций, проверяется каждый из 42 стеков на необходимость атаки по нему (записанную в v-переменных).
//$890AD8 - v9501 - номера целевых стеков атакующего (побитно), $890ADC - v9502 - номера целевых стеков защищающегося (побитно).
//Модификация условия выполнения прохода цикла (в функции $440030).
//Запись 0 (что значит - все позиции вокруг могут быть атакованы).
//Без модификации значение - начение - смежные позиций побитно от правой нижней против часовой стрелки (0 - доступна).
PROCEDURE Damage_ability; ASSEMBLER; {$FRAME-}
ASM //Если 32-й бит в v9501 = 1, модифицируем. PUSH EAX MOV EAX, DWORD PTR DS:[$890AD8] SHR EAX, 31 TEST EAX, EAX POP EAX JNZ @@Modify
//Восстановление изначального кода: получение всех позиций рядом, на которых кто-то стоит побитно (Запись в ECX). MOV ECX, [EBP+8] JMP @@Exit
//Модифицирование кода: запись 0 (будто на всех клетках рядом кто-то стоит) в возвращаемый результат. @@Modify: MOV ECX, 0
@@Exit: TEST ECX, EAX//Восстанавливаем испорченную команду. PUSH $440057
END;
//Модификация вызова функции, вычисляющей позицию текущего атакованного (в функции $440030).
//Автоматическое возвращение 1 (легальной позиции) (в EAX), т. к. позиция может быть вычислена неправильно, если будет больше 8 атакованных.
PROCEDURE Damage_position; ASSEMBLER; {$FRAME-}
ASM //Если 32-й бит в v9501 = 1, модифицируем. MOV EAX, DWORD PTR DS:[$890AD8] SHR EAX, 31 TEST EAX, EAX JNZ @@Modify
//Восстановление изначального кода: вызов функции, вычисляющей позицию текущего атакованного (Запись в EAX). MOV EAX, $5242E0 CALL EAX//Внутри функции используется ESP - нельзя использовать PUSH перед ней. JMP @@Exit
//Модифицирование кода: запись 1 (легальной позиции) в возвращаемый результат. @@Modify: MOV EAX, 1
@@Exit: PUSH $440069
END;
//Модификация вызова функции вычисления адреса конструкций для атакованного на определённой позиции (в функции $440030).
//Вместо вычисления стека по позиции, смотрим в бите v-переменной, надо ли атаковать текущий проверяемый стек.
//Если надо, возвращаем (в EAX) $699420 + 1352*номер стека + 21708, иначе 0.
PROCEDURE Damage_stack; ASSEMBLER; {$FRAME-}
ASM //Если 32-й бит в v9501 = 1, модифицируем. MOV EAX, DWORD PTR DS:[$890AD8] SHR EAX, 31 TEST EAX, EAX JNZ @@Modify
//Восстановление изначального кода: вызов функции, вычисляющей адрес конструкций для атакованного на определённой позиции (запись в EAX). MOV EAX, $4E7230 CALL EAX JMP @@Exit
//Модифицирование кода: проверка, надо ли атаковать текущий стек и запись адреса его конструкций или 0 в EAX. @@Modify: //Проверяем, какой стороне принадлежит проверяемый стек. CMP EBX, 21 JAE @@Def_st
//Если стек принадлежит атакующей стороне, помещаем в EAX соответствующий стеку бит из v9501. MOV EAX, DWORD PTR DS:[$890AD8] MOV CL, BL SHR EAX, CL JMP @@All_st
//Если стек принадлежит защищающейся стороне, помещаем в EAX соответствующий стеку бит из v9502. @@Def_st: MOV EAX, DWORD PTR DS:[$890ADC] SUB EBX, 21 MOV CL, BL SHR EAX, CL ADD EBX, 21
//Оставляем в EAX 0 или помещаем в него адрес конструкций стека (в зависимости от начального значкния EAX, т. е. бита v-переменной). @@All_st: AND EAX, 1 JZ @@Exit //EAX = $699420 + 1352*EBX + 21708. LEA ECX, DS:0[EBX*8] SUB ECX, EBX LEA EDX, [ECX+ECX*2] MOV ECX, DWORD PTR DS:[$699420] LEA EAX, [EBX+EDX*8] LEA EAX, [ECX+EAX*8+21708]
@@Exit: PUSH $44009A
END;
//Модификация условия выхода из цикла (в функции $440030).
//42 прохода (для каждого стека) вместо стандартных 8 (для каждой возможной позиции около атакующего).
PROCEDURE Damage_target; ASSEMBLER; {$FRAME-}
ASM PUSH EAX
Ошибка по адресу 0x004417A4 (MOV EAX, [ESI+34h]) - попытка прочесть память по адресу 34h.
Ещё - отклонение, вызвавшее, скорее всего, эту ошибку - неправильная работа функции sub_5242E0, вызванной по адресу 0x00440064. Там идёт работа со стеком напрямую и извлекается неверное значение (по адресу 0x0052430F (MOV EBX, [EBP+arg_0]; arg_0 = 8])).
Но фишка-то в том, что всё это только при отладке. Просто в игре ничего такого нет.
P.S. Без включенного режима немодифицируемости (отключить - 32-й бит переменной v9501 = 1) ошибка будет в любом случае (правда, разная в игре и отладчике), но с этим я как-нибудь сам разберусь.
RE: Исследование героев - Дьякон - 15.11.201000:08
@@Exit: TEST ECX, EAX//Восстанавливаем испорченную команду. PUSH $440057
//Восстановление изначального кода: получение всех позиций рядом, на которых кто-то стоит побитно (Запись в ECX). MOV ECX, [EBP+8] JMP @@Exit
//Модифицирование кода: запись 0 (будто на всех клетках рядом кто-то стоит) в возвращаемый результат. @@Modify: MOV ECX, 0
@@Exit:
...
Эта функция, для того и нужна, чтобы либо выполнить MOV ECX,DWORD PTR SS:[ARG.1], что, как я понял равно MOV ECX, [EBP+8], либо поместить в ECX 0.
В моём случае она всегда выполняет первое.
RE: Исследование героев - Дьякон - 15.11.201000:56
//Восстановление изначального кода: вызов функции, вычисляющей адрес конструкций для атакованного на определённой позиции (запись в EAX). MOV EAX, $4E7230 CALL EAX JMP @@Exit
//Модифицирование кода: проверка, надо ли атаковать текущий стек и запись адреса его конструкций или 0 в EAX. @@Modify: //Проверяем, какой стороне принадлежит проверяемый стек. CMP EBX, 21 JAE @@Def_st
//Если стек принадлежит атакующей стороне, помещаем в EAX соответствующий стеку бит из v9501. MOV EAX, DWORD PTR DS:[$890AD8] MOV CL, BL SHR EAX, CL JMP @@All_st
//Если стек принадлежит защищающейся стороне, помещаем в EAX соответствующий стеку бит из v9502. @@Def_st: MOV EAX, DWORD PTR DS:[$890ADC] SUB EBX, 21 MOV CL, BL SHR EAX, CL ADD EBX, 21
//Оставляем в EAX 0 или помещаем в него адрес конструкций стека (в зависимости от начального значкния EAX, т. е. бита v-переменной). @@All_st: AND EAX, 1 JZ @@Exit //EAX = $699420 + 1352*EBX + 21708. LEA ECX, DS:0[EBX*8] SUB ECX, EBX LEA EDX, [ECX+ECX*2] MOV ECX, DWORD PTR DS:[$699420] LEA EAX, [EBX+EDX*8] LEA EAX, [ECX+EAX*8+21708]
@@Exit: PUSH $44009A
END;
Затирается вызов процедуры. Если переходим по JNZ @@Modify то там черт ногу сломит. Однозначно могу сказать только одно: если что-то не работает после твоего вмешательства, значит сам виноват. Проверяй код отладчиком.
Всё, что в modify сейчас не важно (на самом деле там выполняестся часть затёртой функции, но номер стека берётся не от адреса инфы о гексе, а из EBX), там действительно, возможно, есть ошибки, но на данном этапе всегда выполняется то, что не modify.
Проблема в том, что если я запущу игру с этой dll-кой, то всё будет работать. А при отладке - выдавать ошибку.
Короче, попробую отлаживать в Olly.
RE: Исследование героев - Berserker - 15.11.201002:57
Без отладчика может работать, имея скрытые дефекты, нарушения целостности структур. А под отладчиком диапазон выделяемых адресов сдвигается и лажа даёт о себе знать.
RE: Исследование героев - Berserker - 16.11.201000:06
Quote:Это как?
Отладчик выделяет память в процессе для своих нужд. Динамическую. То есть если без отладчика Angel.dll грузилась по адресу $3000000, то с отладчикаом запросто может по $300F000.
//Восстановление изначального кода: вызов функции, вычисляющей адрес конструкций для атакованного на определённой позиции (запись в EAX). MOV EAX, $4E7230 CALL EAX JMP @@Exit
//Модифицирование кода: проверка, надо ли атаковать текущий стек и запись адреса его конструкций или 0 в EAX. @@Modify:
@@Exit: PUSH $44009A
END;
BEGIN HookCode(POINTER($440095), @Damage_stack, C_HOOKTYPE_JUMP);
END.
то ESP послее выполнения выходит уменьшенным на 4. Почему?
RE: Исследование героев - Berserker - 21.11.201002:20
На вид всё корректно. В упор не вижу ошибки. Попробуй трассировать по шагам.
RE: Исследование героев - etoprostoya - 21.11.201012:16
SHR EAX, 31 TEST EAX, EAX JNZ @@Modify
=> TEST EAX, EAX JS @@Modify
А вообще, мне не нравится, когда в одной процедуре стоят PUSH'и без POP'ов. Зачем так сделали?
RE: Исследование героев - Berserker - 21.11.201015:26
Quote:А вообще, мне не нравится, когда в одной процедуре стоят PUSH'и без POP'ов. Зачем так сделали?
RET всегда идёт в конце асмовской процедуры. PUSH + RET = JMP
RE: Исследование героев - Дьякон - 21.11.201016:17
PROCEDURE Damage_stack; ASSEMBLER; {$FRAME-}
Приведи вид данной процедуры в отладчике
RE: Исследование героев - Berserker - 21.11.201016:54
Code:
код процедуры на асме, указанный в сорцах
RET
RE: Исследование героев - GhostManSD - 21.11.201019:17
Подскажите, пожалуйста, такую вот вещь: в DL кнока с номером 30721 реагирует на нажатие Esc, закрывая окно. Возможно ли сделать так, чтобы кнопка с номером 30720 реагировала так же на Enter?
RE: Исследование героев - Дьякон - 21.11.201020:08
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;
//Модификация удара с флагом бить всех вокруг.
//Вместо вычисления 8-ми атакованных позиций, проверяется каждый из 42 стеков на необходимость атаки по нему (записанную в v-переменных).
//$890AD8 - v9501 - номера целевых стеков атакующего (побитно), $890ADC - v9502 - номера целевых стеков защищающегося (побитно).
//Модификация вызова функции вычисления адреса конструкций для атакованного на определённой позиции (в функции $440030).
//Вместо вычисления стека по позиции, смотрим в бите v-переменной, надо ли атаковать текущий проверяемый стек.
//Если надо, возвращаем (в EAX) $699420 + 1352*номер стека + 21708, иначе 0.
PROCEDURE Damage_stack; ASSEMBLER; {$FRAME-}
ASM //Если 32-й бит в v9501 = 1, модифицируем. MOV EAX, DWORD PTR DS:[$890AD8] SHR EAX, 31 TEST EAX, EAX JNZ @@Modify
//Восстановление изначального кода: вызов функции, вычисляющей адрес конструкций для атакованного на определённой позиции (запись в EAX). MOV EAX, $4E7230 CALL EAX JMP @@Exit
//Модифицирование кода: проверка, надо ли атаковать текущий стек и запись адреса его конструкций или 0 в EAX. @@Modify:
@@Exit: PUSH $44009A
END;
BEGIN HookCode(POINTER($440095), @Damage_stack, C_HOOKTYPE_JUMP);
END.
Скомпилированная: удалено за ненадобностью.
RE: Исследование героев - Дьякон - 21.11.201021:20
Должна вызываться при ударе существа с флагом "бить всех вокруг". У меня при ударе горыныча вызывалась.
RE: Исследование героев - Дьякон - 21.11.201021:46
Не пойму откуда call взялся. В исходниках вроде все правильно.
RE: Исследование героев - Berserker - 21.11.201021:47
Понял, в чём проблема события. У тебя и МОРа установка заплаток происходит по сто раз )))
Сейчас ищу ошибку стёка. Добавлено:
Ответ: под нормальным отладчиком всё чисто.
RE: Исследование героев - Berserker - 21.11.201021:53
Quote:почувствуй разницу. откуда в геройской секции такие адреса могут быть?
А у меня JMP в оле)
RE: Исследование героев - Дьякон - 21.11.201021:56
BEGIN Win.DisableThreadLibraryCalls(Win.GetModuleHandle('Damage_s.dll')); [hooks...]
END.
Код запретит вызывать основую процедуру DLL, которая иначе будет при создании и удалении потоков в программе заново устанавливать хуки, тем самым перезаписывая точки останова в отладчике. Добавлено:
И точку останова можно ставить только после выполнения кода инициализации Эры, иначе она будет переписана хуком. Зы, точка останова = запись 0xCC по адресу, если что.
Это, видимо, было сделано специально - иначе файл получается слишком маленький и на него ругается антивирус (Avira, по крайней мере).
RE: Исследование героев - Berserker - 21.11.201022:54
Quote:Теперь всё нормально.
Большое спасибо!
Не за что.
Quote:Это, видимо, было сделано специально - иначе файл получается слишком маленький и на него ругается антивирус (Avira, по крайней мере).
Нет. Просто эти модули у тебя и МОРа вообще не используются, а в Эре использовались.
А ругаться на маленький файл глупо. Меньше размер - лучше компилятор.
Berserker Wrote:А ругаться на маленький файл глупо. Меньше размер - лучше компилятор.
Авире скажи.
Мне проще включить туда эти модули, чем разбираться с антивирусом. Поставлю только туда комментарий-напоминание, чтобы не забыть, если что, что можно убрать это.
RE: Исследование героев - Berserker - 21.11.201023:54
Sav, скорее всего её эвристику смущает не размер, а твой код, не похожий на код обычного приложения. А если подключить модули, то появляется много чего на вид нормального.
Помогите заполнить пробел в знании ассемблера: как работать с командами fild, fstp, fld, fmul, fdivr, fstp и прочими «f…»? Я понимаю, что они предназначены для операций над float – числами с плавающей запятой (как переменные e и e- в ERM). Но что конкретно они делают, что в каких регистрах/ячейках памяти должно находиться и куда возвращается результат – не знаю.
RE: Исследование героев - etoprostoya - 27.12.201016:59
А так, если ввести ограничение на неиспользование процессоров ниже Пентиум 3 или Пентиум 4, то лучше использовать гораздо более удобные регистровые инструкции SSE и SSE2 и забить на стековые операции.
О, кстати. Я этот пост не видел, а как-то сам допёр, когда делал dwellings.dll. Просто меня озадачило, что длл-ки Феанора весят почти в два раза меньше, а делают больше. Подумал: язык тут вряд ли играет особую роль, значит, что-то явно лишнее. Поубирал последовательно используемые средства - длл отказалась компилироваться только без win, а с ней одной работает нормально.
Такой вот метод тыка.
etoprostoya, спасибо!
RE: Исследование героев - GhostManSD - 16.01.201102:21
Подскажите, как быть. Нашел временный адрес, где хранится нужное значение. В АМ на него более 200 указателей. И как узнать, какой из них нужен?
В Олли щелкал по тому же адресу references, нашел опять-таки за 200 адресов. Но как там искать нужное - тем более не знаю.
Найди участок кода, где используется адрес и посмотри там, с помощью какого указателя он получен.
RE: Исследование героев - GhostManSD - 28.01.201101:37
Как при обращении к адресу A (на который стоит хук) заменить процедуру в адресе B? Например, изначально в адресе B стоит "MOV ECX 4", а надо, чтобы было "MOV 8". Имеется в виду код в Паскале.
RE: Исследование героев - Berserker - 28.01.201101:45
Посмотри в Оле, сколько байтов занимает сама команда, а сколько константа. Например, если 2 байта команда, то прибавь к адресу 2, а затем напиши: PINTEGER(адрес)^:=8. Если константа однобайтовая, то PBYTE(адрес)^:=4;
RE: Исследование героев - etoprostoya - 28.01.201101:56
Ссылка в первом сообщении темы не работает.
RE: Исследование героев - GhostManSD - 28.01.201102:37
Berserker, можно подробнее для идиота?
1. Что подразумевается под константой? Адрес хука?
2. Где смотреть, что сколько байт занимает?
Простите, если мои вопросы кажутся непроходимо тупыми...
RE: Исследование героев - Berserker - 28.01.201103:43
Для идиота смысла нет, а умному человеку почему бы не объяснить?
Видишь, B9 - байт-команда = MOV ECX, SomeConst, а сама константа занимает 4 байта и находится, естественно, байтом правее от адреса команды. Соответственно, нужно записать по адресу 701001(в моём случае) 8.
PINTEGER($701001)^:=8.
Однако это только для кода вога, для которого разрешена запись. Для остального нужно использовать процедуру:
RE: Исследование героев - feanor - 28.01.201117:19
Quote:Однако это только для кода вога, для которого разрешена запись.
А разве то ли в ТЕ, то ли в Эре защита со всех секций не снята?
___________
Где хранятся записи о требованиях к отстройке? Раскуривание CD:B результатов не дало.
RE: Исследование героев - Berserker - 28.01.201119:17
Не снята. Просто воговская часть имеет флаг на запись и расценивается как данные. А вот содовская, как и ранее, сгенерит исключение.
RE: Исследование героев - feanor - 28.01.201119:45
Quote:А вот содовская, как и ранее, сгенерит исключение.
Хм..у меня не генерит, не смотря на то, что я делаю, скажем, так:
Code:
*(int*)(0x59F898+1) = CREATURE_ENERGY_ELEM;
RE: Исследование героев - Berserker - 28.01.201119:47
Перепроверил. Был не прав. Очень странно. Выходит теперь любая ошибка запросто портит код, а когда уже будет исключение, анализировать будет нечего.
RE: Исследование героев - GhostManSD - 03.02.201106:08
Подскажите, пожалуйста, каков адрес x-переменных функций? Возможно ли вывести какую-нибудь общую формулу в духе [адрес функции 1 * номер функции] + [адрес x1 * номер x]?
RE: Исследование героев - Prayer - 03.02.201110:25
Здравствуйте!
Никто случаем не занимался изменением главного меню игры? Меня интересует дизабил некоторых кнопок. Как, например, это реализовано, если ваш компьютер клиент в сетевой игре:
Позарез нужно отключить или убрать из меню вообще кнопку "Показать дополнительные опции", чтоб на серваке ее тоже нельзя было использовать. Нашел дефку кнопки - gspbutt.def, текста на ней в genrltxt.txt.
Почитал данную ветку, полез на wasm.ru начал читать "Крекинг с нуля" , скачал Olly. Даже бряк поставил на gspbutt.def
И только потом понял, что я вообще не соображаю, что дальше делать Видать в моем возрасте уже позновато с нуля начать програмировать, при том что общие навыки в этом деле + знание языков = 0,000
RE: Исследование героев - GhostManSD - 03.02.201113:46
На фига бряк-то? Смещай координаты просто за пределы экрана.
Или забей нопами отрисовку.
RE: Исследование героев - GhostManSD - 03.02.201115:12
Мастера, подскажите, пожалуйста, как по умному сделать. Нужно, чтобы при хуке на адресе A:
1) сравнивалось значение по адресу B с -1 (CMP DWORD [адресB], -1);
2) если по адресу B и вправду -1, то команда по адресу C будет MOV ECX, DWORD [EDX*4+$68A36C];
3) если по адресу B отличное от -1 значение, то команда по адресу C будет MOV ECX, DWORD [адресB*4+$68A36C].
Я пробовал менять опкод и аргумент через PINTEGER, но у меня выходит хрень какая-то. Помогите, пожалуйста!
По-моему, лучше в хуке по адресу A запомнить значение по-адресу B, а проверять в хуке по адресу C, если я правильно понял, что тебе надо.
RE: Исследование героев - Prayer - 03.02.201120:13
(03.02.2011 13:46)GhostManSD Wrote: На фига бряк-то? Смещай координаты просто за пределы экрана.
Или забей нопами отрисовку.
Хммм... А это как? Где искать координаты? Отрисовку?
Я же писал что делитант...
RE: Исследование героев - GhostManSD - 03.02.201120:31
Нашел свою кнопку? Перейди на адрес, где она прописывается (в Олли: search > text references > твоя кнопка.def. Нажимаешь на ней лкм. Ты попадешь в CPU. Там рядом с названием кнопки будут прочие аргументы. Координаты находятся на пару строчек ниже (2 адреса: отступ сверху и отступ слева). Они - в шестнадцатеричном формате. Для перевода используй калькулятор Windows в инженерном режиме. Поставь большие координаты, чтобы кнопка "уехала" за пределы экрана. Вроде все.
RE: Исследование героев - GhostManSD - 03.02.201120:37
Sav, попробую. Мне тоже приходила в голову такая мысль, но я думал, есть способ сделать без второго хука.
RE: Исследование героев - Дьякон - 03.02.201121:57
покажи код
RE: Исследование героев - GhostManSD - 04.02.201100:00
Адреса для хука (точнее, для хука - верхний, а остальные прописываю для восстановления оригинальных команд); при хуке происходит вызов функции 90003 (это я уже прописал в плагине).
В функции 90003 игрок может установить параметр SN:X1 от -1 до 8. Если X1=-1, то значение ECX из кода №2 остается неизменным и соответствует реальному типу города. Если 0<X1<8, то устанавливается подложка соответствующего типа города.
Было бы еще здорово узнать, как эти параметры выставлять. При попытке прописать в своей dll нечто в духе MOV DWORD General.EventParams, 1 Паскаль говорит, что никакого General в природе нет.
BEGIN
HookCode(POINTER($5CCD80), @HOOK_MageGuildEnter, C_HOOKTYPE_JUMP); // 90003
END.
До этого вместо MOV устанавливал через PINTEGER таким же образом значения по адресам.
RE: Исследование героев - etoprostoya - 04.02.201101:36
А что у тебя подряд два POPAD в MageGuildBackground? Причём один то выполняется, то нет.
RE: Исследование героев - GhostManSD - 04.02.201101:51
Ну так вроде же надо восстанавливать регистры независимо от итога. Хотя во втором случае никакие регистры вроде не меняются, так что там и правда нет нужды. Но проблема-то не в этом.
Гм. Сейчас вот на свежую голову все это посмотрел и увидел, что если вручную в Олли поменять процедуру в нужном мне адресе, получается вот что:
БЫЛО
RE: Исследование героев - etoprostoya - 04.02.201103:45
Ты вообще в курсе, что PUSH(AD) и POP(AD) изменяют значение ESP?
RE: Исследование героев - GhostManSD - 04.02.201104:00
В курсе. Но стандартный метод вроде такой:
1. При срабатывании хука - PUSHAD.
2. Далее прописать вызов функции.
3. POPAD.
4. Выполнить затертые команды.
Может, проблема в том, что у меня выполняется больше команд, чем я затираю?
Будут работать совершенно по-разному, в зависимости от первого CMP. В одном случае возьмётся одно значение из стека, а в другом - другое. И так для всего кода программы, то есть ты делаешь ВЕСЬ код неправильным.
Нужно сделать так, чтобы ESP на метке @@Change был одинаков, независимо от проверки.
RE: Исследование героев - GhostManSD - 04.02.201114:40
Как? MOV EBP, ESP; затем в нужном месте (после метки) - MOV ESP, EBP?
ESP - регистр, отвечающий за заполненность стека.
Чтобы он не сбивался, надо, чтобы push было столько же, сколько и pop вне зависимости от, того, как будет выполняться код.
Как-то так, хотя я не понимаю, что делает push 800 в таоём коде.
(13.09.2010 21:00)Sav Wrote: Прошу прощения за тупой вопрос: динамический адрес может меняться при нескольких запусках программы на одном компьютере или только на разных компьютерах? И вообще, может кто-нибудь дать мне точное определение этого понятия?
Что-то никто не дал нормальный ответ. Теперь попробую я.
Для этого маленького исследования потребуется (из прог, которые мне знакомы):
либо PE Explorer,
либо не так давно найденная мной замечательная и очень компактная программка LordPE,
либо супермаленькая прога Икзелиона, некогда выложенная Дьяконом в приложение к одному из туториалов,
да почти любой дизасм.
В любом случае, нужна программа, позволяющая посмотреть сегментацию экзешника, его деление на секции. В принципе, подходит та же IDA, только там почему-то не видна секция .rsrc (видимо, за ненадобностью).
Мне лично нравится отображение секций в PE Explorer. Поэтому приведу скрин с него:
Size of Raw Data – размер секции непосредственно в файле.
Virtual Size – размер секции во время работы приложения. Включает в себя Raw Size.
Virtual Adress – адрес начала секции в запущенном приложении.
Pointer of Raw Data – адрес начала секции в файле.
Нетрудно заметить, что для сод-секций Virtual Adress = Pointer of Raw Data + 400000h, а для вог-секций Virtual Adress = Pointer of Raw Data + 465000h.
Для записи/чтения требуется знать только статическое виртуальное пространство, подходящее для этих целей. Достаточно нескольких минут, чтобы понять, что есть три НЕподходящих области:
1. < 401000h. В этих адресах работает система, поддерживая работу запущенного приложения. Также там находится стек. Запись/чтение там просто бесполезны и могут убить приложение.
2. >=6AD000/<701000. Иначе говоря, вся секция .rsrc. Этой секции просто не выставлены флаги Readable/Writeable, поэтому никаких операций с ней не выйдет и всё закончится вылетом (хотя можно выставить флаги и юзать, но лучше уж добавить новую секцию). Львиную долю её занимают иконки экзешника, также там информация о файле, менюшка, доступная в оконном режиме, и прочее.
3. >=293512Ch (21AE12C + 787000). Основная динамическая память. Сюда подгружаются библиотеки, здесь создаёт свои аллоки экзешник.
Существует закономерность: чем больше размер буфера, выделяемого в динамической памяти, тем больше шансов, что его адрес будет более статичен. Отюда многие заблуждения и принятие динамических адресов за статические. Достаточно запустить игру под отладчиком, подгрузить дополнительную длл или ресурс, запустить exe на другой системе или машине – и адрес окажется вовсе не таким.
Вот и всё.
Дополнения и уточнения принимаются, так как этот пост написан на основе личного практического знания.
RE: Исследование героев - GhostManSD - 04.02.201116:09
(04.02.2011 15:08)Sav Wrote: Как-то так, хотя я не понимаю, что делает push 800 в таоём коде.
Эти строки - оригинальный код. В т.ч. PUSH 800.
Попробовал твой код, Sav. Тоже вылет, только ошибка другая. А причина одна - безблагодатность. Прикладываю crashlog.
Если у тебя хук на 5CCDD7, то эти строчки не затираются, а значит - убери их. Лишний mov может и не страшно, а вот лишний push - страшно почти всегда.
RE: Исследование героев - Дьякон - 05.02.201100:23
MOP, динамическая память - это память выделенная в процессе выполнения программы, такими функциями как GlobalAlloc, VirtualAlloc и др. Все секции exe являются статическими.
RE: Исследование героев - Дьякон - 05.02.201100:34
(05.02.2011 00:23)Дьякон Wrote: MOP, динамическая память - это память выделенная в процессе выполнения программы, такими функциями как GlobalAlloc, VirtualAlloc и др. Все секции exe являются статическими.
А я что-то другое написал?
RE: Исследование героев - GhostManSD - 05.02.201121:56
Берс, спасибо огромное! Тысячный раз уже выручаешь! Вот только есть одна такая вот нехорошая штука... Как быть, если мне нужно поместить значение в X1 в одном хуке, а считывать - с другого? Например, в одном из адресов вычисляется что-то и заносится в EAX.
Hook1 mov ecx, [EventParams] mov [ecx], eax
.Hook1
Hook2 [моя функция]
.Hook2
При попытке считать SN:X он выдает всякую хрень. Как быть? В хуке 1 сохранять в левый адрес (типа v1) значение параметра, а в хуке 2 - передавать из этого адреса?
RE: Исследование героев - Berserker - 05.02.201122:19
GhostManSD Wrote:Как быть, если мне нужно поместить значение в X1 в одном хуке, а считывать - с другого?
Лучше завести отдельную переменную: мало ли как может использоваться SN:X между хуками (даже если не используется - ради совместимости с потенциальными другими модами).
RE: Исследование героев - Berserker - 05.02.201122:47
Quote:Я смотрел в исходниках Эры, там только 16.
Извиняюсь, скопировал с черновика 2.0.
RE: Исследование героев - GhostManSD - 05.02.201122:53
//////////////////////////////////////////////////
// 90001: TownEnter
// X1 - town number
// X2 - town type
//////////////////////////////////////////////////
PROCEDURE HookData1_TownEnter; ASSEMBLER; {$FRAME-}
ASM
RE: Исследование героев - GhostManSD - 07.02.201102:35
Все это, конечно, здорово. Но указатель порой находится далеко от места, на которое срабатывает хард брейкпойнт. Допустим, я никак не могу найти адрес типа текущего города, хотя знаю, что в момент срабатывания бряка по адресу $741B7C тип города заносится в ECX. Можно ли мне быстро найти место, где значение заносится в ECX? Я листал долго, но ничего в духе MOV ECX, [Адрес] не обнаружил. Нашел MOV ECX, [EBP-8], но где ставится EBP, найти не могу. Quod autem facere, то бишь, делать-то что?
RE: Исследование героев - Дьякон - 07.02.201110:00
А чем тебя ecx не устраивает? Полистай код, найди процедуру, в которую передается тип города, в зависимости от твоих потребностей, и меняй себе на здоровье.
RE: Исследование героев - GhostManSD - 07.02.201120:55
Дьякон, я не совсем понял, что ты имеешь в виду. Можешь пояснить или привести примерный код?
RE: Исследование героев - Дьякон - 07.02.201123:48
приведи код и поставь задачу
RE: Исследование героев - GhostManSD - 08.02.201100:40
Опять нашел ответы на свои вопросы. Размещаю здесь, авось кому пригодится.
Code:
[$6AAAB8] - номер города
[[$69954C]+$110] - тип города
Дьякон, спасибо, уже не надо. Научился вроде искать указатели. АртМани тут и впрямь не помощник.
RE: Исследование героев - GhostManSD - 08.02.201102:58
Мне может кто-нибудь объяснить, что означает эта команда?
Code:
MOV DWORD PTR FS:[0], ECX
При попытке поставить хук в ту область, где она выполняется, происходит вылет при записи.
RE: Исследование героев - Berserker - 08.02.201103:03
Установка обработчика структурных исключений. Если очень хочется мозголома, то гугл: Structured Exceptions Handling.
Обычно тебе этот код не должен быть нужен.
RE: Исследование героев - GhostManSD - 08.02.201103:37
Берс, уже поставил хук на другое место. Но почитаю, спасибо. Хотя вряд ли пойму, если даже ты говоришь, что мозголом.
RE: Исследование героев - GhostManSD - 08.02.201116:52
Такой вот вопрос: когда заклинания Гильдии магов добавляются герою? Если нет книги, то, по идее, сразу после покупки оной. А если есть книга, то при заходе в город?
подозреваю, что если портануться в город, но зайти в город не двойным кликом а через Управление королевством, то могут не добавиться. не проверял
RE: Исследование героев - GhostManSD - 09.02.201122:36
SAG, проверю.
Товарищи, поставил хук на получение уровня и после получения уровня (огромное спасибо MOP). Есть один досадный минус: почему-то лишь раз показывается окошко получения нового уровня (независимо от опыта), а уровень героя приравнивается к 34. Помогите отыскать жука.
Так в HE:E при установке уровня окна и не должны вроде появляться.
Откуда появляются значения в переменных LevelUp_HeroNumber и LevelUp_HeroLevel?
RE: Исследование героев - Berserker - 10.02.201101:18
Quote:Так в HE:E при установке уровня окна и не должны вроде появляться.
Конечно не должны. А в x2 - мусор по ходу.
RE: Исследование героев - GhostManSD - 10.02.201103:35
Sav, ты не понял. Не о том речь. При срабатывании хука все переменные перемещаются нормально и выдают верные значения. Но отображается лишь одно окно (даже если герой получил 3 уровня) и герою накидываются уровни до 34.
(10.02.2011 01:16)Sav Wrote: Откуда появляются значения в переменных LevelUp_HeroNumber и LevelUp_HeroLevel?
Из указателей. Дело не в этом.
RE: Исследование героев - GhostManSD - 10.02.201104:05
(10.02.2011 01:18)Berserker Wrote:
Quote:Так в HE:E при установке уровня окна и не должны вроде появляться.
Конечно не должны. А в x2 - мусор по ходу.
Почему же мусор? Показывает, какого уровня достиг герой.
Уровни до 34 накидываются всегда или только при использовании HE:E?
RE: Исследование героев - GhostManSD - 10.02.201114:49
Всегда. А HE:E было призвано исправить ситуацию, сменив уровень героя на тот, которого он достигает. Но ситуация не меняется. Я бы пошел иным путем: устанавливал бы значение в ассемблере, но я никак не могу найти указатель на реальный уровень героя (а не получаемый).
При вводе чита woggandalfwhite все проходит нормально, кстати. Получаемый уровень соответствует реальному.
Можно было бы сделать адресом хука адрес call-а и не восстанавливать ничего, кроме него.
И push-ить адрес call-а + 5.
Как это точно сделать - не знаю (нет кода игры перед глазами).
Здесь не видно связи с твоей ошибкой, но иногда при исправлении понятных недочётов исправляются и непонятные ошибки
RE: Исследование героев - GhostManSD - 10.02.201118:07
Sav, спасибо, помогло. Теперь всегда буду ставить хук на CALL.
З.Ы. X2 - и впрямь мусор. Точнее, не совсем мусор, но не то, что нужно. Не совсем то я искал.
(10.02.2011 18:07)GhostManSD Wrote: З.Ы. X2 - и впрямь мусор. Точнее, не совсем мусор, но не то, что нужно. Не совсем то я искал.
Извиняюсь, таки соврал. Нужное. Это уровень, которого достигнет герой, когда закончит щелкать по окошкам, выбирая новые навыки.
RE: Исследование героев - GhostManSD - 10.02.201123:55
Допустим, в адресе A идет значение (по дампу) [01 00 00 04 00 08 1F 00]. Могу ли я загнать в EAX только начало этого значения, т.е. (в данном случае) 01?
Да. Кроме того можно использовать не весь eax (4 байта), а только его четвертинку al:
mov al, [A]
RE: Исследование героев - Berserker - 11.02.201101:08
A - константа?
RE: Исследование героев - GhostManSD - 11.02.201101:09
Sav, спасибо, работает!
RE: Исследование героев - etoprostoya - 11.02.201101:28
Лучше
MOVZX EAX, [A];
Потому что команда
MOV AL, [A];
не изменяет старшие 24 бита и если там что-то было, то так и останется.
EAX = 0x12345678; MOV AL, BYTE PTR [A]; => EAX = 0x12345601;
EAX = 0x12345678; MOVZX EAX, BYTE PTR [A]; => EAX = 0x00000001;
RE: Исследование героев - GhostManSD - 11.02.201101:37
RE: Исследование героев - etoprostoya - 11.02.201102:17
Quote:0F B6 / r MOVZX r16,r/m8 Move byte to word with zero-extension 0F B6 / r MOVZX r32,r/m8 Move byte to doubleword, zero-extension 0F B7 / r MOVZX r32,r/m16 Move word to doubleword, zero-extension
MOVZX EAX, BYTE PTR [MEM]
и
MOVZX EAX, WORD PTR [MEM]
имеют разный код в 32-битном моде.
Ещё раз - а я что-то другое написал?
21AE12C + 787000 = 293512C = конец секции .data ВОГа, последней секции экзешника. Здесь кончается определённость и начинается динамический хаос.
Ладно, проехали.
RE: Исследование героев - GrayFace - 13.02.201100:31
(03.02.2011 10:25)Prayer Wrote: Позарез нужно отключить или убрать из меню вообще кнопку "Показать дополнительные опции", чтоб на серваке ее тоже нельзя было использовать. Нашел дефку кнопки - gspbutt.def, текста на ней в genrltxt.txt.
Лучше для этого спользовать IDA (на IsoHunt можно взять). Там в Shift+F12 найти gspbutt.def, по xrefs перейти на место, где используется. Потом нажми Tab. Там же будут передаваться и координаты, и горячая клавиша, правда коды клавишь в Героях свои. Можно занулить её и сделть запредельными координаты, а лучше полностью перепрыгнуть код по созданию кнопки. Чтобы эти изменения внести, нужно сделать патч для Эры.
RE: Исследование героев - GrayFace - 14.02.201100:40
Это тоже не совсем правильно называть дин. памятью - это свободная память, в которой как выделяется динамическая память, так и грузятся всякие dll.
(13.09.2010 21:00)Sav Wrote: Прошу прощения за тупой вопрос: динамический адрес может меняться при нескольких запусках программы на одном компьютере или только на разных компьютерах?
Может. На одном компе он часто остается одинаковым от запуска к запуску, но если, например, установить другой антивирус и т.п., легко может поменяться.
(04.02.2011 15:29)MOP Wrote: 1. < 401000h. В этих адресах работает система, поддерживая работу запущенного приложения. Также там находится стек. Запись/чтение там просто бесполезны и могут убить приложение.
Система на низком уровне использует адреса >7fffffffh (хотя может использовать только половину, если выставить это в манифесте ехе), системные библиотеки грузятся по адресам ниже 7fffffffh, но близким к этой границе. Адреса от 10000h до 401000h могут использоваться, у меня патч к редактору какое-то время, пока не вырос в размере, грузился по адресу 320000h - в этот адрес его поставил сам загрузчик Винды, я так и выставил. Только что для интереса сделал базовый адрес проги 30000h, где обычно стек - стек получился по адресу A0000h.
Во избежание дальнейших недоразумений...
Если кодишь в Олли, да и не только в ней - не указывай лишних данных. В данном случае надо было убрать "DWORD PTR DS:", но ты указал Олли эту дополнительную ненужную инфу. В результате смысл команды не изменился, но машкод её вырос на 1 байт и затёр "PUSH ECX".
То есть, в затирании ты сам виноват. Внимательнее.
RE: Исследование героев - GhostManSD - 26.02.201107:09
Подскажите, пожалуйста, реально ли заставить WoG обращаться к текстовому файлу. Выглядит примерно так...
Каждый раздел начинается с символа #. Программа должна сама высчитать, каков номер значка # в тексте, и это число является номером раздела.
Например, чтобы при !!SN:X0/3/25/78 в переменную z78 подставлялось значение из строки №25 раздела №3 файла GMSDData...
...а при !!SN:X1/5/78/25 значение переменной z78 подставлялось в строку №25 раздела №5.
RE: Исследование героев - Berserker - 26.02.201119:13
Команда есть в UN для чтения и записи в/из ini.
RE: Исследование героев - etoprostoya - 26.02.201121:06
Quote:!!UN:N5/#1/#2/#3/#4
Записать z-переменную в общую секцию файла wog.ini
Quote:!!UN:N6/#1/#2//#3/#4
Прочитать z-переменную из общей секции файла wog.ini
Quote:Так, для записи переменной z-1, названной "Главная_переменная", в файл "Мой.var" в папку GAMES (секция "MyLocalSettings") с опцией 4, используйте:
!!VRy1:S4;
!!VRz-1:S^Главная_переменная^;
!!VRz-2:S^MyLocalSettings^;
!!VRz-3:S^GAMES\My.var^;
!!UN:N5/z-1/y1/-2/-3;
У меня из-за этого хука жёсткий баг прямо на старте игры, причём только тогда, если включены wav-звуки, а скрипт создаёт аллоки с помощью erautils.dll.
Если выпилить хук и восстановить ориг. код – всё абсолютно нормально.
RE: Исследование героев - baratorch - 02.07.201123:55
Хочу сделать для оффлайна заказ героя в таверне (герой который будет появляться в таверне после нанятого).
В связи с этим вопрос: как узнать какие герои доступны/недоступны для появления в таверне у игрока?
Может подскажет кто?
RE: Исследование героев - Berserker - 03.07.201101:11
Может.
RE: Исследование героев - gamecreator - 03.07.201101:26
Очевидно, проверить владельца и разрешение на карте.
RE: Исследование героев - baratorch - 03.07.201101:48
Berserker, спасибо.
RE: Исследование героев - Berserker - 03.07.201103:09
У меня из-за этого хука жёсткий баг прямо на старте игры, причём только тогда, если включены wav-звуки, а скрипт создаёт аллоки с помощью erautils.dll.
Если выпилить хук и восстановить ориг. код – всё абсолютно нормально.
Так что, никто не знает?
Это хотя бы нужная вещь?
RE: Исследование героев - Berserker - 06.08.201117:17
RE: Исследование героев - kostya_76 - 10.12.201113:18
Может кто-нибудь подсказать, как правильно скомпилировать эту длл MoP'а в Дельфи7?
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
PROCEDURE HOOK_tent; ASSEMBLER; {$FRAME-}
ASM
MOV EAX, $50C7C0
CALL EAX //вызываем функцию вычисления HP-очков, которую мы затёрли своим хуком.
MOV DWORD PTR DS:[$91DA38],-1 //заносим в адрес переменной x1 значение -1 - на случай, если мы не хотим вообще ничего менять в принципе лечения
MOV [$91DA3C], EAX //заносим в адрес переменной x2 исходное значение кол-ва хит-пойнтов, для подробностей и возможных вычислений
PUSHAD //сохраняем регистры
PUSH 29500 //номер ERM-функции. Меняйте на любой доступный.
MOV EAX, $74CE30
CALL EAX //вызываем C_FUNC_ZVS_CALLFU
ADD ESP, 4
POPAD //выталкиваем регистры
CMP DWORD PTR DS:[$91DA38],-1 //проверяем, изменил ли скриптописец кол-во очков HP для лечения
JE @@Default //если не изменил - продолжить код без изменения
MOV EAX,DWORD PTR DS:[$91DA38] // заменить значение очков на значение из x1
@@Default:
PUSH $478538 //адрес возврата в процедуру
END;
BEGIN
HookCode(POINTER($478533), @HOOK_tent, C_HOOKTYPE_JUMP);
END.
Изменяю название библиотеки Win на Windows, остальные вроде не нужны, но можно и оставить, кроме VPUtils.
Еще не понятно, что такое {$FRAME-} в строке: PROCEDURE HOOK_tent; ASSEMBLER; {$FRAME-}, чтобы компилятор не ругался, приходится убирать.
Пробовал в разных папках компилить, в том числе и в папке с Эрой.
Компилится нормально, но адрес в созданном хуке получается левый - соответственно вылет при обращении. Если в Olly адрес перехода на функцию HOOK_tent поменять на нормальный - все работает.
RE: Исследование героев - Berserker - 10.12.201113:50
FRAME соответствует опции W в Delphi. Utils не нужен.
RE: Исследование героев - kostya_76 - 10.12.201116:07
Berserker, спасибо, скачал, работает.
Только цель как-бы в другом: получить работоспособный пример-шаблон подключения длл к Эре. Причем на удобной для меня платформе. В этом смысле больше бы подошел билдер, но хотя-бы на дельфи для начала.
Пробовал скомпилировать эту длл в Virtual Pascal v2.1 - вообще ничего не получилось. Да и после попыток работы с ним вообще всякое желание пропадает этим заниматься.
Добавил эту самую директиву W- вместо FRAME- - не помогло.
Хотя бы знать в каком направлении копать .
Имеет ли смысл пытаться в отладчике докопаться до алгоритма получения этого адреса: @HOOK_tent? Думаю, это не самый верный путь.
RE: Исследование героев - Berserker - 10.12.201116:22
Quote:получить работоспособный пример-шаблон подключения длл к Эре
Есть пример для GNU C++ и для Delphi.
В Эре 1.9+ Tools\Era\SDK
RE: Исследование героев - kostya_76 - 10.12.201117:35
Berserker, Так в примере подключение через длл ЕРМ-инструкций, я естественно смотрел этот пример и пробовал подключать.
Но интересует именно встраивание хуков, в частности создание с их помощью триггеров, как в примере МоР'а. Поэтому и хочу разобраться, почему не получается.
Или вот прикладной пример: нужно встраивать программу создания зеркальной карты для подмены исходной карты, созданной генератором прямо в игре. Может когда-нибудь до этого доберусь.
RE: Исследование героев - Berserker - 10.12.201118:53
Попробуйте посмотреть в Era\Tools\Era\Sources\Era 1.9 Delphi:
triggers.pas
А вообще, создание нового события - вещь не тривиальная. Нужно сперва в дизассемблере определить параметры, место перехвата и после уже писать сам перехват. Если вы для примера укажите адрес в коде игры, в который хотите вставить перехватчик, я приведу код для перехвата. При этом важно знать, в каких регистрах и адресах памяти на момент перехвата лежат нужные вам данные.
RE: Исследование героев - Berserker - 18.12.201121:42
Обновим тень перемещения:
493350 - F (0, 1); THISCALL;
Теперь если поменять скриптом скорость монстра, можно и сеточку обновить...
RE: Исследование героев - Al_Mualim - 23.12.201102:04
; Обновить экран встречи героев
!!UN:C6962576/4/?y1; [6A3D90h] - swapManager
!!SN:E5957888/2/y1;
Не помню, но артефакты в слотах, вроде, обновляются отдельно.
RE: Исследование героев - kostya_76 - 12.02.201200:26
(10.12.2011 16:22)Berserker Wrote:
Quote:получить работоспособный пример-шаблон подключения длл к Эре
Есть пример для GNU C++ и для Delphi.
В Эре 1.9+ Tools\Era\SDK
Как создать хук с помощью этого инструмента я понял. Вот только в Делфи у меня не получается создать форму в длл. Вылетает игра. В книгах обычно примеры создания форм в длл с вызовом из приложения, также написанного на Делфи .
В билдере получается форму создавать, в Делфи - хуки)
А код для GNU С++ в билдере не компилится.
Есть длл с хуком для подмены файла карты. После генерации карты, до загрузки. Подменял под отладчиком - работает.
begin Hook (@Func, HOOKTYPE_CALL, 5, POINTER($58C080));
end.
Создаю форму. Вызываю Form1.Show(); хоть в обработчике хука, хоть при загрузке длл - вылет.
Так тоже не получается:
VAR AOwner: TComponent;
Form1 := TForm1.Create(AOwner);
Form1.Show();
Хотя в любом случае, программа для обработки карты написана на С++, и подключать ее в Делфи - это извращение.
RE: Исследование героев - kostya_76 - 12.02.201200:54
(12.02.2012 00:33)GreyGhost Wrote: делфи это всего навсего расширение паскаля
Я как-бы в курсе)
(12.02.2012 00:33)GreyGhost Wrote: а вот создание FORM(окна) для перехвата функции - это извращение.
Откуда такое смелое предположение о цели создания формы?
Кроме как для организации интерфейса, она мне не нужна)
В приведенном мною примере особой связи между хуком и созданием формы нет.
А вообще, спасибо за содержательный комментарий.
RE: Исследование героев - Berserker - 12.02.201213:16
GreyGhost, да брось. И чего ты пост потёр из Кино/Сериалы? )
kostya_76, а какие ошибки в билдере?
RE: Исследование героев - gamecreator - 12.02.201214:08
(12.02.2012 00:26)kostya_76 Wrote: В билдере получается форму создавать, в Делфи - хуки)
так сделай две библиотеки и вызывай одну из другой
RE: Исследование героев - kostya_76 - 12.02.201215:10
(12.02.2012 13:16)Berserker Wrote: kostya_76, а какие ошибки в билдере?
(12.02.2012 00:26)kostya_76 Wrote: Создаю форму. Вызываю Form1.Show(); хоть в обработчике хука, хоть при загрузке длл - вылет.
Так тоже не получается:
VAR AOwner: TComponent;
Form1 := TForm1.Create(AOwner);
Form1.Show();
И не получится. Убери формы вообще и все связи с VCL.
Хотя в теории подружить VCL с героями возможно (но формы будут открываться отдельно от окна героев), а вот встроить их внутрь интерфейса нереально (если бы у окон героев были оконные хендлы, а их там AFAIK нет, то можно было бы вообще вставлять праактически любой виджет из VCL прямо на любое окно в игре)
RE: Исследование героев - kostya_76 - 12.02.201220:40
(12.02.2012 20:15)AVS Wrote: И не получится. Убери формы вообще и все связи с VCL.
Хотя в теории подружить VCL с героями возможно (но формы будут открываться отдельно от окна героев), а вот встроить их внутрь интерфейса нереально (если бы у окон героев были оконные хендлы, а их там AFAIK нет, то можно было бы вообще вставлять праактически любой виджет из VCL прямо на любое окно в игре)
Само-собой это окно отдельно от окна героев должно открываться.
RE: Исследование героев - Berserker - 12.02.201221:02
Реквизит встроила VCL-ые формы в игру. zvslib1 использует формы билдера для новых воговских диалогов. Я, к сожалению, добился только глючного модального запуска и бросил. kostya_76, замените __stdcall на WINAPI.
RE: Исследование героев - kostya_76 - 12.02.201221:10
Berserker, Не помогает - такое сообщение об ошибке.
Собственно, мне пока нужен только хук, попробую сейчас функцию
typedef __stdcall void (*THook) (void* HandlerAddr, int HookType, int PatchSize, void* CodeAddr);
(12.02.2012 20:40)kostya_76 Wrote: Само-собой это окно отдельно от окна героев должно открываться.
Тогда при запуске в хуке Application.Initialize. Еще возможно необходимо установить Application.Handle на реальный хендл героев.
Формы создавать Tform1.Create(nil) и ставить FreeOnRelease. Уже это должно работать.
(12.02.2012 21:02)Berserker Wrote: Реквизит встроила VCL-ые формы в игру.
Ну если хукнуть главный цикл и "подсунуть под" окно героев VCL форму (чтобы окно героев было дочерним) потом наверное переписав обрабтку мыши и клавиатуры может и получится.
(12.02.2012 21:02)Berserker Wrote: zvslib1 использует формы билдера для новых воговских диалогов. Я, к сожалению, добился только глючного модального запуска и бросил.
Увы я только мельком поглядел на исходники самого вога - этой либы в них нет - а в самом воге диалоги реализованы через грязные хаки с VMT классов внурти движка героев.
RE: Исследование героев - baratorch - 12.02.201221:43
kostya_76
__stdcall void замени на void __stdcall
RE: Исследование героев - kostya_76 - 12.02.201222:01
(12.02.2012 21:43)baratorch Wrote: kostya_76
__stdcall void замени на void __stdcall
Да, теперь копмилится. правда кучу предупреждений выдает:
Мне для работы пришлось переименовать era.cpp в era.h.
RE: Исследование героев - kostya_76 - 13.02.201218:25
(13.02.2012 00:54)Sav Wrote: Мне для работы пришлось переименовать era.cpp в era.h.
От появления предупреждений при линковке это действительно избавило. Но не более того.
От ошибок линковщика, приведенных на последнем скрине удалось избавиться, убрав галочки "Use VCL" и "Multi Threaded" при создании шаблона библиотеки мастером.
Но хук не создается, и вообще секции этой длл в памяти не появляются.
В предыдущем примере с удалением объектов с помощью ЕРМ-инструкций также в памяти длл не видно, но тем не менее объекты удаляются.
RE: Исследование героев - Berserker - 13.02.201220:45
Я залью сегодня обновлённый вариант.
RE: Исследование героев - Berserker - 13.02.201222:50
RE: Исследование героев - kostya_76 - 14.02.201200:12
Berserker, Все равно не получается )
В смысле, компилится нормально, только это предупреждение также осталось:
[C++ Warning] Era.h(130): W8058 Cannot create pre-compiled header: initialized data in header
При запуске то же сообщение:
И в памяти, соответственно , длл не появляется.
Может я что-то не так делаю? Бросаю созданную длл в папку EraPlagins. Все остальные плагины работают.
RE: Исследование героев - Berserker - 14.02.201201:38
Плагин должен иметь расширение *.era. Ну а предупреждение компилятора нормальное.
RE: Исследование героев - kostya_76 - 14.02.201216:03
(14.02.2012 01:38)Berserker Wrote: Плагин должен иметь расширение *.era. Ну а предупреждение компилятора нормальное.
На работоспособные длл изменение расширения на .era никак не влияет: работают и так и так.
А вот в данном примере смена расширения приводит к вылету после сообщения об исключении.
Если в DllMain оставить только вызов ConnectEra() , тогда нормально загружается.
Berserker, а ты пробовал сам скомпилировать и запустить этот пример? Работает?
RE: Исследование героев - Berserker - 14.02.201217:02
kostya_76, да, причём как часы. 20 КБ размер выходит.
Quote:На работоспособные длл изменение расширения на .era никак не влияет: работают и так и так.
Не так. *.dll - это старые плагины, *.era - новые. Новые грузятся ДО вога и основаны на системе событий.
А вы вообще на какой версии эры экспериментируете? Я видел в пути WT.
RE: Исследование героев - kostya_76 - 14.02.201217:20
(14.02.2012 17:02)Berserker Wrote: kostya_76, да, причём как часы. 20 КБ размер выходит.
Это, я так понимаю, в GNU компилилось , а не в билдере? У меня весит 9 КБ.
(14.02.2012 17:02)Berserker Wrote: Не так. *.dll - это старые плагины, *.era - новые. Новые грузятся ДО вога и основаны на системе событий.
В данном примере это принципиально? Пример на Делфи прекрасно работает без переименований.
(14.02.2012 17:02)Berserker Wrote: А вы вообще на какой версии эры экспериментируете? Я видел в пути WT.
Era 1.9, экзешник насколько помню потом еще отдельно скачивал.
А установлено в папку с WT.
RE: Исследование героев - Berserker - 14.02.201217:52
Я не знаю, что там чудим билдер, но суть проста. Era.dll загружается, получаются адреса её функций и вызываются. Если мне предоставится возможность проверить на билдере, я попробую. Дома его нет.
RE: Исследование героев - kostya_76 - 14.02.201218:20
(14.02.2012 17:52)Berserker Wrote: Я не знаю, что там чудим билдер, но суть проста. Era.dll загружается, получаются адреса её функций и вызываются. Если мне предоставится возможность проверить на билдере, я попробую. Дома его нет.
Для меня это не так уж просто) Попробую еще поковыряться в опциях. Можно еще мап-файл поизучать)
RE: Исследование героев - kostya_76 - 16.02.201202:56
Berserker, Если поменять hEra = (HINSTANCE) v[1]; на hEra = LoadLibrary("era.dll");,
то все работает, кроме функции ApiHook - Вероятно ее нет в библиотеке)
А Функция Hook работает, ну и остальные вроде тоже.
Адрес hEra указывал куда-то в середину секции, и в результата все GetProcAddress возвращали нули.
RE: Исследование героев - Berserker - 16.02.201212:11
ApiHook в Эре 2)
RE: Исследование героев - totkotoriy - 19.02.201213:00
Может у кого есть рабочий код на с++ какого-либо хука, который затем передает управление ERM триггеру?
RE: Исследование героев - gamecreator - 19.02.201213:22
так в Эре вроде есть функция, выполняющая ерм. вот с помощью нее и вызвать триггер.
RE: Исследование героев - totkotoriy - 19.02.201213:24
(19.02.2012 13:22)gamecreator Wrote: так в Эре вроде есть функция, выполняющая ерм. вот с помощью нее и вызвать триггер.
totkotoriy, не пойму, что тебе нужно. Я создавал триггер на паскале, но основная часть там - ассемблер, поэтому я могу без особых затрат времени перевести его на c++ и показать тебе код. Нужно?
RE: Исследование героев - totkotoriy - 19.02.201215:51
(19.02.2012 14:59)Sav Wrote: totkotoriy, не пойму, что тебе нужно. Я создавал триггер на паскале, но основная часть там - ассемблер, поэтому я могу без особых затрат времени перевести его на c++ и показать тебе код. Нужно?
Да, я про это и говорю. Код хука на С++ я уже написал, мне нужен теперь рабочий код на ассемблере для вызова триггера в ERM.
RE: Исследование героев - gamecreator - 19.02.201216:21
RE: Исследование героев - kostya_76 - 19.02.201219:21
(19.02.2012 15:51)totkotoriy Wrote: Да, я про это и говорю. Код хука на С++ я уже написал, мне нужен теперь рабочий код на ассемблере для вызова триггера в ERM.
Я ж тебе показывал пример. Весь код создания триггера это 4 строчки:
PUSH 29500 //номер ERM-функции. Меняйте на любой доступный.
MOV EAX, 0x74CE30
CALL EAX //вызываем C_FUNC_ZVS_CALLFU
ADD ESP, 4
Просто в примере с палаткой добавлены дополнительные операции по вызову параметров для использования в создаваемом триггере.
Вот пример, работающий с адресом 4074AC, который ты давал:
Добавил в скрипт триггер - срабатывает где-то после генерации карты.
Только хук в этом примере создан с помощью Эры 1.9. То есть еще файл Era.h нужен. Немного выше есть ссылка на него от Берсеркера.
RE: Исследование героев - totkotoriy - 22.02.201217:38
(19.02.2012 19:21)kostya_76 Wrote: файл Era.h нужен. Немного выше есть ссылка на него от Берсеркера.
Спасибо, но я не могу нигде найти эту библиотеку.
И еще хотел спросить что за адрес 6992D0 в этой команде mov eax,DWORD PTR DS:[0X6992D0]? Он для другого хука будет такой же?
Костян, и можешь еще прислать скомпилиный этот код? я скомпилил его чуть по другому (без era.h) и у меня все равно в игре вылетает(
(22.02.2012 17:38)totkotoriy Wrote: И еще хотел спросить что за адрес 6992D0 в этой команде mov eax,DWORD PTR DS:[0X6992D0]? Он для другого хука будет такой же?
heroWindowManager.
Для каждого хука свой затираемый этим хуком код.
totkotoriy, если ты не осилил плагин, которыя я для тебя переписал, вот упрощённый и чуть более плотно прокомментированный вариант. Тут создаётся триггер, в него передаются и из него принимаются параметры !!SN:X. Разумеется, тут ничего особенного не происходит, но триггер вызывается.
Это код на MSVC++ 9.0, по идее должен компилироваться, если положить рядом era.h, расширение плагина для работоспособности нужно изменять на "era" после компиляции.
/* ...Тут идёт код, вычисляющий переменные-параметры... */
//Записываем цели в параметры !!SN:X. mov edi, EventParams // Это специальный масив Эры для передачи параметров. При помощи erm-команды !!SN:X можно будет их считать в скрипте. mov eax, LeftSideBits mov [edi], eax // EventParams[0] = LeftSideBits; mov eax, RightSideBits mov [edi + 4], eax // EventParams[1] = RightSideBits;
//Записываем номер основной цели в параметры !!SN:X. mov eax, MainTarget mov [edi + 8], eax // EventParams[2] = MainTarget;
//Записываем номер атакующего стека в параметры !!SN:X. mov eax, Atacker mov [edi + 12], eax // EventParams[3] = Atacker;
//Вызываем ERM-функцию 78001 (перед ударом), из неё получаем параметры для записи в переменные целей. push 78001 mov eax, 0x74CE30 call eax add esp, 4
//Считываем новые цели из параметров !!SN:X. mov edi, EventParams // В erm-коде с помощью команды !!SN:X в этот массив был записаны новые значения. Мы можем их считать и что-нибудь изменить в зависимости от них. mov eax, [edi] mov ebx, [edi + 4]
//Записываем новые цели в переменные целей. mov LeftSideBits, eax // LeftSideBits = EventParams[0]; mov RightSideBits, ebx // RightSideBits = EventParams[1];
/* ...Тут могли бы обрабатываться параметры и что-нибудь изменяться... */
// Восстанавливаем все регистры. popad
//Вызываем затёртую функцию (вместо вызова этой функции в игре теперь стоит вызов кода этого хука, поэтому вызываем её вручную). mov eax, 0x465BC0 call eax
// push + ret = jmp (то есть это просто прыжок на адрес 0x44134B, возвращение из хука в код игры). push 0x44134B ret }
}
//Начало.
extern "C" __declspec(dllexport) BOOL APIENTRY DllMain(HINSTANCE hInst, DWORD reason, LPVOID lpReserved)
{ if (reason == DLL_PROCESS_ATTACH) { DisableThreadLibraryCalls(hInst); // Инициализация, создание связи с Эрой. ConnectEra();
// Регистрируем обработчик, который запустится после выполнения кода WoG в начале запуска программы и вызовет указанную функцию. RegisterHandler(OnAfterWoG, "OnAfterWoG");
} return TRUE;
};
RE: Исследование героев - Berserker - 22.02.201222:22
//DisableThreadLibraryCalls(hInst);
Автоматом вызывается для *.era модулей.
Да, я отстал от жизни, и SDK у меня там для 1.9. Ну, впрочем это непринципиально, старое, по крайней мере, то, что я использовал, не менялось.
RE: Исследование героев - kostya_76 - 22.02.201223:14
(22.02.2012 17:38)totkotoriy Wrote: Костян, и можешь еще прислать скомпилиный этот код? я скомпилил его чуть по другому (без era.h) и у меня все равно в игре вылетает(
Вот
Только работать будет лишь под Эрой, коль скоро функция оттуда вызывается.
Кстати, имена людей коверкать нехорошо
RE: Исследование героев - totkotoriy - 23.02.201213:37
(22.02.2012 21:48)Sav Wrote: totkotoriy, если ты не осилил плагин, которыя я для тебя переписал, вот упрощённый...
Попробуй тут осилить когда кто на чем пишет, а ты ни того не другого не знаешь... Спасибо, будем разбираться...
(22.02.2012 23:14)kostya_76 Wrote:
(22.02.2012 17:38)totkotoriy Wrote: Костян, и можешь еще прислать скомпилиный этот код? я скомпилил его чуть по другому (без era.h) и у меня все равно в игре вылетает(
Вот
Только работать будет лишь под Эрой, коль скоро функция оттуда вызывается.
Кстати, имена людей коверкать нехорошо
По мне так Костян - это ещё уважительнее чем просто Костя...
Спасибо, всё работает, наверное я ещё и неправильно код на С++ в прошлый раз написал.
Может ещё обясните как вычесляется адрес (например 0X6992D0), который затирается хуком?
Кто-нибудь может дать описание всем полям из cranim.txt или хотя бы некоторым (кроме x-смещения прямоугольника с количеством существ, периода между проигрываниями анимации кривляния и периода анимации движения)? В принципе я и сам разберусь, но если кто это уже сделал, не хотелось бы зря тратить время.
RE: Исследование героев - totkotoriy - 06.03.201223:51
(10.02.2012 18:26)MOP Wrote: Уже несколько человек спрашивало…
Code:
; Обновить экран встречи героев
!!UN:C6962576/4/?y1; [6A3D90h] - swapManager
!!SN:E5957888/2/y1;
Не помню, но артефакты в слотах, вроде, обновляются отдельно.
А может подскажите тогда ещё как обновлять отряды у героев в экране встречи? А то почему-то они таки не обновляются ...
// Структура боевой анимации существа. Заполняется из cranim.txt.
struct struct_CreatureAnim
{ short X_UpRight_Bullet_Shift_word10; // Смещение снаряда по X при стрельбе вправо-вверх short Y_UpRight_Bullet_Shift_word12; // Смещение снаряда по Y при стрельбе вправо-вверх short X_Right_Bullet_Shift_word14; // Смещение снаряда по X при стрельбе вправо short Y_Right_Bullet_Shift_word16; // Смещение снаряда по Y при стрельбе вправо short X_DownRight_Bullet_Shift_word18; // Смещение снаряда по X при стрельбе вправо-вниз short Y_DownRight_Bullet_Shift_word1A; // Смещение снаряда по Y при стрельбе вправо-вниз float BulletDefFramesAngles_adword1C[12]; // Угол отклонения снаряда от горизонтали для каждого кадра def`а (от -90.0 до 90.0) int X_CountShowingRect_Shift_dword3C; // Смещение изображения прямоугольника с отображаемым количеством существ по горизонтали в пикселях int DistanceAttackAnim_ClimaxFrame_dword40; // Число кадров, исходя из которого рассчитывается период каждого кадра анимации дистанционного действия (если <= 0, то берётся реальное число кадров) int RandomAnim_WaitTime_dword44; // Время между проигрываниями случайной анимации int MovingAnim_Time_dword48; // Время проигрывания анимации движения _DWORD DistanceActionAnim_Time_dword4C; // Общее время анимации дистанционного действия (выстрела или колдовства) _DWORD FlightAnim_FrameDistance_dword50; // Расстояние, на которое перемещается существо за кадр при полёте
};
Такие структуры хранятся для каждого существа по адресу, записанному в 0x67FF74, а так же входят в структуру стеков в бою по смещению 110h.
RE: Исследование героев - Berserker - 09.03.201221:30
Ценное исследование, спасибо!
RE: Исследование героев - Berserker - 20.03.201215:13
В оконном режиме без ХД:
1) Нажать на усыпить героя.
2) Свернуть окно мышкой
3) Развернуть
4) Панель ресурсов и статистики героя пустая - неперерисованнная.
Правый щелчок на карте приключений красит кнопку усыпления в зелёный цвет и правильно обновляет экран.
RE: Исследование героев - Berserker - 20.03.201215:21
// Структура стрелковой башни в бою.
struct struct_BattleTower
{ int CreatureType_dword0; // Тип существа башни void *Def_dword4; // Загруженный def существа башни void *BulletDef_dword8; // Загруженный def снаряда башни int X_Pos_dwordC; // Позиция изображения существа башни по горизонтали в пикселях int Y_Pos_dword10; // Позиция изображения существа башни по вертикали в пикселях int Orientation_dword14; // Направление (0 - вправо, 1 - влево) int AnimSectionNum_dword18; // Номер секции кадров анимации башни int AnimFrameNum_dword1C; // Текущий кадр секции анимации башни int StackNum_dword20; // Номер стека башни (сторона-владелец - всегда 1)
};
Хранится в виде 3-элементного массива структур в структуре BattleMgr (*(0x699420)) по смещению 81272. Индекс башни в массиве определяется dword`ом по +38h в структуре её стека (для остальных стеков это поле - позиция на поле боя). 254 - индекс 0, 251 - индекс 1, 255 - индекс 2.
RE: Исследование героев - Berserker - 20.03.201216:30
Quote:254 - индекс 0, 251 - индекс 1, 255 - индекс 2.
Забавно, что получаемый бонус явно рассчитан на то, чтобы на него урон умножали, но урон на него во всех случаях использования этой функции делится. Отсюда и баг с воздушным щитом, окаменением и (не помню, известен ли он) вторичным навыком Защиты.
Так же несложно заметить, что в функции рассчитывается всего 3 вещи - воздушный щит (IsShot во всех стандартных вызовах = 1), окаменение и вторичный навык Защита (со специализацией) героя-хозяина цели. Ни атака (а ведь у башни заявлено 10 атаки) с защитой, ни вторичные навыки героя-хозяина башни не учитываются.
Для Хоты я заменил все 3 вызова этой функции на нормальную A0_Battle_Stack_CalcDamageModifs_sub_443C60 (пришлось искать недостающие параметры, но это несложно). Это и исправит баги, и несколько усилит башни (учитывающиеся 10 атаки - не так мало + учёт атаки обороняющегося героя).
RE: Исследование героев - Berserker - 20.03.201223:26
Хотелось бы в Эру по умолчанию встроить. Двоичной заплаткой не обойтись?
// При подсчёте бонуса к урону стрелковой башни...
int __stdcall HookOn_ArrowTowerCalcDamageBonuses(LoHook* h, HookContext* c)
{
// Вызываем общую функцию подсчёта урона.
c->eax = (*(_BattleStack_**)(c->ebp - 36))->Calc_Damage_Bonuses((_BattleStack_*)(c->ebx), *(_int32_*)(c->ebp + 8), TRUE, FALSE, 0, 0);
c->return_address = 0x46594B;
return NO_EXEC_DEFAULT;
}
// При подсчёте бонуса к урону стрелковой башни ИИ (1)...
int __stdcall HookOn_ArrowTowerCalcDamageBonusesAI1(LoHook* h, HookContext* c)
{
// Выполняем затёртую команду.
c->edi = c->esi - 688;
// При подсчёте бонуса к урону стрелковой башни ИИ (2)...
int __stdcall HookOn_ArrowTowerCalcDamageBonusesAI2(LoHook* h, HookContext* c)
{
// Выполняем затёртую команду.
c->edi = c->esi - 688;
// При подсчёте бонуса к урону стрелковой башни...
_PI->WriteLoHook(0x465934, HookOn_ArrowTowerCalcDamageBonuses);
// При подсчёте бонуса к урону стрелковой башни ИИ (1)...
_PI->WriteLoHook(0x41E38E, HookOn_ArrowTowerCalcDamageBonusesAI1);
// При подсчёте бонуса к урону стрелковой башни ИИ (2)...
_PI->WriteLoHook(0x41E4CA, HookOn_ArrowTowerCalcDamageBonusesAI2);
Не хочу менять сам код (наделаю синтаксических ошибок ещё), поэтому поясню отдельно: _int32_ = int; TRUE = 1; FALSE = 0.
Code:
struct _BattleStack_
{
...
// Подсчёт добавок к наносимому урону (возвращается новый урон).
// Enemy - указатель на атакуемый стек.
// BaseDamage - начальный урон.
// IsShot - является ли атака выстрелом (TRUE - является).
// Virtual - является ли подсчёт производимым ИИ (TRUE - является).
// WayLength - пройденный путь до цели (для расчёта кавалерийского бонуса).
// out_FireshieldDamage - указатель на переменную, в которую в результате работы функции запишется урон от огненного щита (0 - не подсчитывать).
inline _int32_ Calc_Damage_Bonuses(_BattleStack_* Enemy, _int32_ BaseDamage, _bool8_ IsShot, _bool8_ Virtual, _int32_ WayLength, _int32_* out_FireshieldDamage)
{
return CALL_7(_int32_, __thiscall, 0x443C60, this, Enemy, BaseDamage, IsShot, Virtual, WayLength, out_FireshieldDamage);
}
...
}
_BattleMgr_.stack = +21708, массив 2 на 21 стеков (каждый - по 1352 байта).
_BattleMgr_.curr_stack_ix = +78524
_BattleMgr_.current_side = +78528
Так же, как видно, для получения стека башни ИИ приходится брать текущий стек. Но если эта ИИ-функцкци вызывается только стандартно из геройского кода, то это заведомо правильный способ.
etoprostoya Wrote:А там точно double, а не float? Раньше думал, что в игре используется только float32.
64 тоже используется, в основном в промежуточных вычислениях. Хотя конкретно в этом случае не знаю, но, думаю, Ида правильно определила, тем более в такой маленькой функции.
RE: Исследование героев - etoprostoya - 21.03.201210:58
Понятно. Ида просто не может отличить код для double от кода для float, если это не SSEx. Код для 64- и 32- битных плавающих числе отличается только в инициализации.
RE: Исследование героев - kostya_76 - 21.03.201223:33
Подскажет кто-нибудь, почему триггер в данной функции срабатывает только со второй генерации случайной карты?
// ExecErmCmd("UN:P97/?v1;"); - так работает нормально
__asm { mov EAX, [0x887668] // получаем значение из v1 mov simmTemplOption, EAX }
if (simmTemplOption == 1) { //код }
__asm { POPAD }
}
Врезка идет сразу после нажатия кнопки "начать" перед генерацией карты по адресу 0x5863ba.
Если то же самое сделать с помощью функции Эры ExecErmCmd, то срабатывает нормально - при первой же генерации.
В данном случае нужно получить значение одной из ВОГ-опций.
Это можно попробовать сделать и без ЕРМ, но возни много.
И, самое главное, что дальше после генерации карты нужно будет организовать интерфейс с помощью ВОГ-диалога, там уже по любому ЕРМ нужен.
Зависимость от Эры не устраивает, т.к. скорее всего программа будет использоваться в ТЕ/WT.
RE: Исследование героев - gamecreator - 22.03.201201:12
кто-нибудь знает как получить указатель на массив героев?
В начале 2^32 - 1 раунда все непризванные стеки на поле боя погибнут (призванные сделают это в начале 2^32 - 1 раунда, считая с момента призыва). Это связано с полем, отвечающим за оставшиеся раунды жизни клонов, которое при инициализации -1, для клона отдельно устанавливается, и при уменьшении которого нет никаких проверок.
(28.03.2012 16:37)Sav Wrote: В начале 2^32 - 1 раунда все непризванные стеки на поле боя погибнут
От черт.... значит нельзя бесконечно смотреть на 2х дерущихся троллей
Я кстати на df2 упоминал о подобном "переполнении" при споре, можно ли гарпией ведьмой при определенном сочетании препятствий на поле боя завалить 100500 бегемотов. Хотя, за миллиард ходов конкретно 100500 бегемотов лягут...
Это корректно, но в этом случае не учитывается атака башен (заявленная как 10 и на самом деле такая) и защита цели.
RE: Исследование героев - kostya_76 - 01.04.201221:15
Есть у кого мысли по поводу этого вопроса?
Не стесняемся, если кто подскажет, тому за это ничего не будет )
А то подключение программы зеркалирования карт практически готово, только вышеозначенная проблема возникла.
Пробовал разобраться, как в Эре реализована функция ExecErmCmd, но слишком сложно для меня, да и нет необходимости ее повторять. Нужно как-то инициировать выполнение ЕРМ кода из скрипта.
RE: Исследование героев - Berserker - 01.04.201221:32
Quote:Это корректно, но в этом случае не учитывается атака башен (заявленная как 10 и на самом деле такая) и защита цели.
Так она и без нас, по ходу, не считается. Просто деление на умножение вернуть уже достаточно. А ещё микробонус от разницы между атакой и защитой считать....имхо не стоит.
kostya_76, вы закомментировали получение опции, поэтому в v1 у вас мусор. Найдите адрес массива опций и обращайтесь к нему напрямую.
RE: Исследование героев - kostya_76 - 01.04.201221:59
(01.04.2012 21:32)Berserker Wrote: kostya_76, вы закомментировали получение опции, поэтому в v1 у вас мусор. Найдите адрес массива опций и обращайтесь к нему напрямую.
Да нет, это я закомментировал строчку с функцией Эры, чтобы показать, что с ней работает с первого раза. А получение опции идет с помощью той же ЕРМ команды, расположенной в скрипте в функции 29501, вызов которой есть в коде.
Все работает, но только со второй генерации после загрузки героев.
А адрес опции найти-то нетрудно, но обращение к ней нужно делать так, чтобы это работало впоследствии при любом изменении количества ВОГ-опций. Что у меня с ходу не получилось. Не знаю, как по номеру опции найти адрес.
И дело не в ВОГ-опции, это как пример - дальше мне нужен ВОГ-диалог для бана героев, ввода еще некоторых параметров.
Может быть загрузка скриптов идет только после загрузки карты?
Тогда получается нужно все-таки делать аналог ExecErmCmd из Эры?
Или может быть как-то инициировать загрузку скриптов до загрузки карты?
RE: Исследование героев - Berserker - 01.04.201223:10
Quote:Может быть загрузка скриптов идет только после загрузки карты?
Да.
Quote:Тогда получается нужно все-таки делать аналог ExecErmCmd из Эры?
Да. При чём скорее всего ещё и вызывать процедуры очистки и инициализации ЕРМ. Только диалог - это ещё и события, а события - уже Эра или полноценно загруженный скрипт.
Quote:Или может быть как-то инициировать загрузку скриптов до загрузки карты?
Думал уже над этим не раз, но на деле воговская процедура FindErm очень уж привязана к карте/сохранёнке.
RE: Исследование героев - kostya_76 - 01.04.201223:59
(01.04.2012 23:10)Berserker Wrote: Да. При чём скорее всего ещё и вызывать процедуры очистки и инициализации ЕРМ. Только диалог - это ещё и события, а события - уже Эра или полноценно загруженный скрипт.
А события для чего? Вот пример скрипта выбора героев:
Berserker Wrote:Так она и без нас, по ходу, не считается. А ещё микробонус от разницы между атакой и защитой считать....имхо не стоит.
Да, не считается. Но это ошибка, иначе бы не писалось в описании по ПКМ, что у башен атака 10.
Бонус не такой уж и мелкий, по слабым существам на треть вполне урон может увеличить. А если есть опыт башен и т. п., то уж и тем более. Кроме того, в общей функции теоретически могут срабатывать какие-нибудь новые защитные способности существ, поэтому её следует использовать, чтобы башня их не ломала. Разницы в скорости я не заметил.
Ну, во всяком случае, в Хоте я реализовал так, как считаю нужным. А в Эре, учитывая, что перед ней изначально не ставились задачи модификации геймплея, и мини-исправления может быть вполне достаточно.
RE: Исследование героев - Berserker - 02.04.201220:39
Quote:А события для чего?
Trigger = событие. Список событий формируется при загрузки скриптов уже после загрузки карты.
Кто-нибудь знает, чем занимается IFC20.dll, функции CImmProject__CreateEffect, CImmCompoundEffect__Start (вызовы в функции 0x4B6750)? У меня они вроде бы вообще не выполняются из-за неуспешного вызова инциализации этого CImmProject, поэтому я не могу так определить, что они делают.
Похоже, IFC - это Immersion Foundation Classes, 20 - видимо, версия 2.0. Но что это всё же такое по сути, я так и не смог разобрать.
RE: Исследование героев - solitaire345 - 04.04.201223:30
IFC library is responsible for kinetic feedback on gamepads/wheels and other game controllers. Quite strange that it is used for turn-based game. I managed to trigger that function on spell casting and hovering mouse on town buildings.
The branch that calls IFC functions is never executed because dword at 0x00696DD4 is always null and the function returns immediately to not dereference that pointer. 0x00696DD4 is probably pointer to device that supports Immersion Foundation Classes.
Trying to jump to other branch results in access violation.
Кто-нибудь знает, зачем нужно поле setup (первые 4 байта) у структур, таких, как банк существ, и зачем в конструкторе этому полю присваивается значение неинициализированной стековой переменной?
RE: Исследование героев - Berserker - 06.05.201200:17
Не знаю, но твоё сообщение напомнило мне об одной мысли, что хотел сказать по поводу твоего последнего модуля. Универсальный интерфейс делается в Си-стиле. Пишется обёртка над объектом в следующем виде:
То есть все методы - это функции, принимающие сам объект (указатель) в качестве одного из параметров. Для внешнего кода ссылка на твой объект - это чёрный ящик.
Тогда надо писать методы для доступа к каждому полю. Мне не жалко того, что структура объекта открыта, я бы и код открыл, если бы он содержал только мои исследования (кстати, адреса устанавливающихся хуков можно считать открытыми - их элементарно посмотреть извне, используя patcher_x86). Пусть пользователь делает с объектом что хочет, а о том, что трогать не надо, я предупредил, и эти поля объявлены как private. Или закрытость структуры должна быть более удобной пользователю? В этом случае сделаю так.
RE: Исследование героев - Berserker - 06.05.201200:59
В текущем варианте ты ограничил применение языком Си++. К другим даже обёртки не сделать.
Т. е. чтобы не ограничивать надо обязательно создать такие функции? Хорошо, тогда я сделаю это.
RE: Исследование героев - Berserker - 06.05.201201:13
Да. Тогда я их прямо экспортирую в целевом языке программирования и используя, абсолютно не интересуясь двоичной структурой объекта (для меня это указатель).
RE: Исследование героев - Berserker - 18.05.201222:43
solitaire345 Wrote:I found a table which holds setup of arrow towers. It is located at 0x63CF88 and stores the following values:
Code:
00000000 CreatureID dd ? ; base 10
00000004 MainTowerX dd ? ; base 10
00000008 MainTowerY dd ? ; base 10
0000000C LowTowerX dd ? ; base 10
00000010 LowTowerY dd ? ; base 10
00000014 UpTowerX dd ? ; base 10
00000018 UpTowerY dd ? ; base 10
0000001C MissileName dd ? ; offset (00000000)
Here's a function to change graphics of any town. The paremeters are:
x1 - town type; x2 - shooter ID; x3-x8 - X; Y coordinates for turrets (middle, lower, upper); x9 - pointer to missile def.
Notes:
1. There is no backup, so once changed, the setup will remain until h3era.exe is restarted.
2. Changing creature does not affect the power of arrow towers.
3. Using this function after BA0 trigger will have no effect in battle, because that table is copied to temporary location for the duration of combat.
4. creature images are cropped, so some creatures will look wrong (like this).
RE: Исследование героев - Berserker - 11.06.201217:54
solitaire345 Wrote:0x642EA0 - Table of creatures displayed in blacksmith screen. Gold cost is also taken from that creature.
0x6AAA60 - Table of artifacts that are sold in blacksmith. Stangely this table has two ints per town (second is always -1 and changing it has no effect).
RE: Исследование героев - Berserker - 16.06.201214:11
63BD18 - таблица урона от рвов.
Code:
5a7bf0 - расчёт урона от заклинания
базовый урон: включает силу магии и уровень навыка,
номер заклинания,
структура колдующего героя,
структура героя монстра или 0,
структура целевого монстра,
одиночная выборочная цель? (0, 1)
ecx = combat manager
RE: Исследование героев - Berserker - 16.06.201221:47
Берс, а ты отписываешься здесь каждый раз, когда что-то находишь или отбираешь по каким-то приципам? Просто многие из этих, смежных, да и вообще различных функций мной исследованы, но я не знаю, есть ли какой-то толк их выкладывать.
RE: Исследование героев - Berserker - 17.06.201202:22
Да, если нахожу что-то по просьбе или для Эры.
Толк есть. В своё время я все сообщения обошёл, вычленяя то, что можно использовать или довести до ума.
Одна из самых мозговыносящих геройских функций, понять которые с первого взгляда абсолютно невозможно, а потому она у меня очень подробно разобрана. Это функция проигрывания анимации урона стеков (при этом одновременно проигрывается анимация атакующего и боевая анимация при необходимости). Единственный урон, проигрывающийся не этой функцией - армагеддон.
Так же в этой функции накладываются заклинания, которые существа накладывают после атаки.
Посмотрел, DrawAction_Play вызывается и для любого удара, и для стрельбы.
Удар (Enemy_Gex_Around_Stack - номер атакуемого гекса вокруг стека - т. е. 0-6 (0-8), с учётом того, что гексы, окружающие стек, пронумерованы по определённому принципу):
PHP Code:
char __thiscall A0_Battle_Stack_MakeHit_sub_441330(_BattleStack_ *this, _BattleStack_ *Enemy, int Enemy_Gex_Around_Stack) { int Enemy_Gex_Around_Stack_v3; // ebx@1 _BattleStack_ *this_v4; // esi@1 char v5; // al@6 char v6; // zf@6 int v7; // edx@7 int v8; // edi@9 int v9; // edx@10 signed int SomeGexNum_v10; // eax@14 signed int EnemyGex_Num_v11; // eax@14 _BattleStack_ *GexStack_v12; // eax@16 int v13; // ebx@20 int v14; // edi@20 _BattleMgr_ *BattleMgr_v15; // ebx@23 int v16; // eax@24 signed int *v17; // ebx@25 int v18; // eax@29 unsigned int v19; // edx@31 _BattleStack_ *v20; // ebx@32 _BattleStack_ *Enemy_v21; // edi@32 int v22; // ecx@33 int v23; // edi@33 int v24; // ebx@37 int v25; // edi@37 signed int v26; // eax@41 _BattleStack_ *Enemy_v27; // eax@44 int Damage_v28; // eax@45 int v29; // eax@49 int v30; // eax@50 void *v31; // eax@59 void *v32; // eax@66 void *v33; // eax@72 int v34; // eax@82 char *Attacker_Name_v35; // eax@85 int Attacker_type_v36; // eax@89 char result; // al@100 int Attacker_count_v38; // [sp-10h] [bp-40h]@88 int v39; // [sp-Ch] [bp-3Ch]@3 int Damage_v40; // [sp-Ch] [bp-3Ch]@88 int Type_v41; // [sp-8h] [bp-38h]@3 _BattleStack_ *Enemy_v42; // [sp-8h] [bp-38h]@88 int Dead_v43; // [sp-4h] [bp-34h]@88 signed int a5; // [sp+Ch] [bp-24h]@9 int v45; // [sp+10h] [bp-20h]@25 int v46; // [sp+14h] [bp-1Ch]@31 _BattleStack_ *Enemy_v47; // [sp+18h] [bp-18h]@31 int v48; // [sp+1Ch] [bp-14h]@5 signed int a3; // [sp+20h] [bp-10h]@31 int Num; // [sp+24h] [bp-Ch]@31 _BattleStack_ *DragonBreathAttackedStack_v51; // [sp+28h] [bp-8h]@1 char v52; // [sp+2Fh] [bp-1h]@6
void __thiscall A0_DrawTextToPcx16_sub_4B51F0(_Fnt_ *this, const char *text, _Pcx16_ *Pcx16, int x, int y, int width, int height, int color, int align, signed int a10) { const char *text_i; // edx@1 _Fnt_ *this_v11; // ebx@1 int string_symbol_off_v12; // esi@1 unsigned int Str_len_v13; // kr00_4@2 int color_v14; // eax@4 int text_height_v15; // ecx@9 int height_v16; // edi@9 int align_v18; // eax@16 int v18; // eax@16 int symbols_width_v19; // ecx@25 const char Curr_symbol_v20; // al@26 unsigned __int8 symbol_v21; // al@29 int i; // edi@39 const char curr_symbol_v23; // al@40 int char_right_v24; // eax@45 const char last_string_symbol_v25; // dl@48 const char curr_symbol_v26; // al@52 const char *text_v27; // edx@52 const char curr_symbol_v28; // al@59 int X_Add_v29; // eax@65 int symbols_width_v30; // [sp+Ch] [bp-18h]@48 int Last_symb_offset_v31; // [sp+10h] [bp-14h]@2 int last_good_symbol_v32; // [sp+14h] [bp-10h]@48 int string_height_v33; // [sp+18h] [bp-Ch]@9 int string_height_v34; // [sp+18h] [bp-Ch]@23 int Curr_string_first_symbol_off_v35; // [sp+1Ch] [bp-8h]@25 int Y_Addition_v36; // [sp+20h] [bp-4h]@2
text_i = text; string_symbol_off_v12 = 0; this_v11 = this; if ( text ) { Y_Addition_v36 = 0; Str_len_v13 = strlen(text); Last_symb_offset_v31 = Str_len_v13 - 1; if ( Str_len_v13 == 1 ) // 1 символ { if ( a10 != -1 ) { color_v14 = color; if ( BYTE1(color_v14) & 1 ) BYTE1(color_v14) &= 0xFEu; else color_v14 = color + 9; A0_Fnt_DrawSymbol_sub_4B4F00(this_v11, '_', (signed int)Pcx16, x, y, color_v14); } } else // Несколько символов { if ( align & 4 ) // Выравнивание по центру { align &= 0xFFFFFFFBu; string_height_v33 = this_v11->string_height; text_height_v15 = this_v11->string_height * A0_Fnt_GetTextStringsCount_sub_4B5580(this_v11, text, width); height_v16 = height; if ( text_height_v15 >= height ) // Если текст не влезает { if ( height < 2 * string_height_v33 ) // Если влезает не более одной строки, центруем её Y_Addition_v36 = (height - string_height_v33) / 2; text_i = text; } else { text_i = text; Y_Addition_v36 = (height - text_height_v15) / 2;// Центруем текст } } else { height_v16 = height; } if ( align & 8 ) // Выранивание по низу { v18 = align; LOBYTE(v18) = align & 0xF7; align = v18; align_v18 = this_v11->string_height * A0_Fnt_GetTextStringsCount_sub_4B5580(this_v11, text_i, width); if ( align_v18 < height_v16 ) // Если текст влезает Y_Addition_v36 = height_v16 - align_v18;// опускаем его вниз text_i = text; } if ( Last_symb_offset_v31 > 0 ) // Текст есть { while ( text_i[string_symbol_off_v12] ) // Идём до конца текста { string_height_v34 = this_v11->string_height; if ( Y_Addition_v36 + string_height_v34 > height_v16 )// Если строка не в начале и не влезет - прерываемся { if ( Y_Addition_v36 ) break; } symbols_width_v19 = 0; Curr_string_first_symbol_off_v35 = string_symbol_off_v12;// Смещение текущей строки while ( 1 ) // До первого неуправляющего символа { Curr_symbol_v20 = text_i[string_symbol_off_v12]; if ( Curr_symbol_v20 != '{' ) { if ( Curr_symbol_v20 != '}' ) break; } ++string_symbol_off_v12; } symbol_v21 = text_i[string_symbol_off_v12];// Текущий символ в строке if ( symbol_v21 ) { // Отрицательное смещение 1 символа игнорируется if ( *((_DWORD *)&this_v11->v_table + 3 * (symbol_v21 + 5)) < 0 )// fnt->char_sizes[symbol].width symbols_width_v19 = -*((_DWORD *)&this_v11->v_table + 3 * ((char)symbol_v21 + 5));// fnt->char_sizes[symbol].width for ( text_i = text; symbol_v21; symbol_v21 = text[string_symbol_off_v12++ + 1] )// Проход по строке { if ( symbol_v21 == '\n' ) // Следующая строка break; if ( symbols_width_v19 > width ) // Не влезло - переходим на следующую строку break; if ( symbol_v21 != '{' ) { if ( symbol_v21 != '}' ) // Добавляем к ширине строки данные символа symbols_width_v19 += *((_DWORD *)&this_v11->v_table + 3 * (symbol_v21 + 5))// fnt->char_sizes[symbol].width + *(_DWORD *)&this_v11->name[12 * (symbol_v21 + 5)]// fnt->char_sizes[symbol].left + *(_DWORD *)&this_v11->name[12 * (symbol_v21 + 5) + 4];// fnt->char_sizes[symbol].right } } } for ( i = string_symbol_off_v12 - 1; ; --i )// Проход назад по уже пройденным символам { curr_symbol_v23 = text_i[i]; if ( curr_symbol_v23 != '{' ) { if ( curr_symbol_v23 != '}' ) break; } if ( i <= Curr_string_first_symbol_off_v35 ) break; } // Нашли последний неуправляющий символ if ( string_symbol_off_v12 > 0 ) { char_right_v24 = this_v11->char_sizes[(unsigned __int8)text_i[i]].right; if ( char_right_v24 < 0 ) // Игнорируем отрицательный правый отступ в конце строки symbols_width_v19 -= char_right_v24; } if ( symbols_width_v19 > width ) // Если символы в результате вылезли за ширину... { last_string_symbol_v25 = text_i[i]; symbols_width_v30 = symbols_width_v19; last_good_symbol_v32 = 0; if ( this_v11->char_sizes[(unsigned __int8)last_string_symbol_v25].right < 0 )// Возвращаем правый отступ последнего символа symbols_width_v19 += this_v11->char_sizes[last_string_symbol_v25].right; string_symbol_off_v12 = i; // Последний символ if ( last_string_symbol_v25 != ' ' )// Последний символ - не пробел { while ( string_symbol_off_v12 >= Curr_string_first_symbol_off_v35 )// Если символ - не первый в строке { text_v27 = text; curr_symbol_v26 = text[string_symbol_off_v12]; if ( curr_symbol_v26 != '{' && curr_symbol_v26 != '}' )// Если текущий символ - не управляющий { symbols_width_v19 -= *((_DWORD *)&this_v11->v_table// Отнимаем текущий символ от строки + 3 * ((unsigned __int8)text[string_symbol_off_v12] + 5))// fnt->char_sizes[symbol].width + *(_DWORD *)&this_v11->name[12// fnt->char_sizes[symbol].left * ((unsigned __int8)text[string_symbol_off_v12] + 5)] + *(_DWORD *)&this_v11->name[12 * ((unsigned __int8)text[string_symbol_off_v12] + 5)// fnt->char_sizes[symbol].right + 4]; if ( Y_Addition_v36 + 2 * string_height_v34 > height && symbols_width_v19 < width )// Если строка влезает по-горизонтали, но следующая не влезет по-вертикали goto END_CANCEL_SYMBOLS_L61; if ( !last_good_symbol_v32 ) { if ( symbols_width_v19 < width ) last_good_symbol_v32 = string_symbol_off_v12; } } curr_symbol_v28 = text[string_symbol_off_v12-- - 1];// Берём текущий символ и переходим к следующему if ( curr_symbol_v28 == ' ' ) // Если перенесли целое слово, завершаем перенос break; } } text_v27 = text; END_CANCEL_SYMBOLS_L61: if ( string_symbol_off_v12 <= Curr_string_first_symbol_off_v35 )// Если перенесли всё до первого символа в строке... { string_symbol_off_v12 = last_good_symbol_v32;// Берём последний подходящий символ и всю ширину symbols_width_v19 = symbols_width_v30; } if ( text_v27[string_symbol_off_v12] == ' ' )// Последний символ - пробел - просто игнорируем его существование symbols_width_v19 -= this_v11->char_sizes[32].width + this_v11->char_sizes[32].left + this_v11->char_sizes[32].right; } X_Add_v29 = 0; if ( align ) { if ( align == 1 ) // Выравнивание по центру - центрируем { X_Add_v29 = (width - symbols_width_v19) / 2; } else { if ( align == 2 ) // Выравнивание по правому краю - выравниваем X_Add_v29 = width - symbols_width_v19; } } else { // Выравнивание по левому краю X_Add_v29 = 0; } A0_Fnt_DrawString_To_Pcx16_sub_4B4FC0( this_v11, (int)&text[Curr_string_first_symbol_off_v35],// Первый символ string_symbol_off_v12++ - Curr_string_first_symbol_off_v35,// Кол-во символов (+ переходим к первому символу следующей строки) Pcx16, x + X_Add_v29, Y_Addition_v36 + y, color, x, y, width, height, a10); Y_Addition_v36 += this_v11->string_height;// Вертикаль следующей строки if ( string_symbol_off_v12 >= Last_symb_offset_v31 )// Если вывели все символу - завершаем break; height_v16 = height; text_i = text; } } } } }
RE: Исследование героев - Berserker - 21.08.201215:42
Sav Wrote:
Berserker Wrote:Sav, а вот это уже интересно. Как сделать деф, чтобы при замене дефа страха он проигрывался полупрозрачным?
Специального дефа не нужно, полупрозрачность работает с любым. Это параметр у функции, которая отрисовывает анимации, (0x47BA90) любую анимацию можно отрисовывать полупрозрачно. Ну, разумеется, полупрозрачность не регулируемая, одинакова для каждого пикселя.
Вот, как устроена таблица боевых анимаций.
PHP Code:
// Структура боевой анимации. NOALIGN struct _BattleAnim_ { _cstr_ DefName; // Имя def`а анимации _cstr_ TouchEffect_Name; // Имя тактильного эффекта анимации (для его воспроизведения на нестандартных элементах управления с помощью IFC20.dll) _dword_ Properties; // Свойства боевой анимации (по несколько битов) // *** // Начало описания свойств анимации // *** // (сдвиг - размер в битах - значение) // 0 - 4 - Позиция отображения (0 - от земли на стеке или гексе, 1 - посередине гекса или стека, 2 - выше стека, 3 - перед стеком, 4 - с нижней и левой границы гекса, -1 - нет позиции) // 4 - 4 - Не используется // 8 - 1 - Прозрачность (0 - нет, 1 - есть) // 9 - 23 - Не используется // *** // Конец описания свойств анимации // *** };
В Воге таблица, перенесена на адрес 0x7B6980. Номера анимаций соответствую номерам в таблице BM:V в ERM-help. С помощью UN:C можно легко на время изменить параметры любой анимации.
Родной земле замка, к которому принадлежит существо. Это явно не баг, т. к. там вполне конкретно проверяется наличие у стороны стека с соотв. родной землёй.
(21.09.2012 20:42)Berserker Wrote: И это точно баг?
(21.09.2012 22:59)Sav Wrote: Это явно не баг
Я и не говорил ни разу, что это баг. Однако данная содовская "фишка" делает Мины и Зыбучий Песок ещё более УГ-заклинаниями, чем они могли бы быть. И я не разу не слышал, чтобы кто-то был против её устранения. Наоборот, всё орали: "Уберите!".
RE: Исследование героев - Berserker - 11.12.201221:17
feanor Wrote:
Quote:10. Нейтральные герои, с магией
А в чем тут проблема? Нейтральных (минус первого игрока) героев как неподвижных стражей вытащить можно без особого изврата. Я где-то писал команду, чтоб они отображались на карте..
Раз там есть поле compression_type, значит кадр хранится сжатым, тогда Sav прав.
RE: Исследование героев - Berserker - 01.03.201323:22
Что-то похожее видел в коде. Участвует в расчёте итогового смещения для отрисовки (ака dx, dy).
RE: Исследование героев - etoprostoya - 02.03.201311:38
Правильно Сав сказал. Я специально вёл логи отрисовки монстров и ни разу не было случая, что бы рисовался полный кадр, который, как известно имеет размер 450*400 пикселей.
По крайней мере в триггере 66666 не работает. А так же в этом триггере нельзя узнать номера встретившихся героев. Приходиться узнавать их в CM3 (то есть можно узнать номера только при нажатии какой-либо кнопки в окне встречи, но не новой) и передавать в 66666. Обновляется только когда нажимаешь куда нибудь еще, но не на новую кнопку (так кстати и было раньше). Даже не знаю что и делать...
ID кнопки в этом триггере находится в значении x1 - на всякий случай.
И еще заметил: после того как сработал триггер CM3 в триггере 66666 можно узнать номера героев.
Может симитировать командой нажатие кнопки по пустому месту в начале и в конце триггера 66666?
RE: Исследование героев - Berserker - 26.05.201317:32
RE: Исследование героев - totkotoriy - 26.05.201318:22
Перехватывает, но экран всё также не обновляется :_(
Может что-то не так делаю?
RE: Исследование героев - Berserker - 26.05.201319:05
Обновляется (проверял на отрядах, не артах).
Что именно ты делаешь?
RE: Исследование героев - totkotoriy - 26.05.201321:01
Так например делаю...
RE: Исследование героев - Berserker - 26.05.201321:25
Подтверждаю отложенное обновление при щелчке на кнопке именно. Исследую дальше.
IF:L в том же месте обновляет экран, нужно глянуть как.
RE: Исследование героев - Berserker - 26.05.201321:54
RE: Исследование героев - totkotoriy - 27.05.201310:07
Ура! Спасибо! Наконец-то работает!
Надо сказать еще Bes"у и Valery, тоже давно хотели такие кнопки...
RE: Исследование героев - Berserker - 27.05.201317:22
Спасибо за тестирование.
RE: Исследование героев - Berserker - 31.05.201300:59
RE: Исследование героев - Berserker - 12.07.201314:42
solitaire345 Wrote:The town creature list is at memory 0x6747B4. The formula to calculate the address for particular dwelling is ((int *)0x6747B4+7*2*TownType+7*IsUpgraded+DwellingLevel)
The town incomes are integers stored at these addresses: 0x5BFA1A+1 - basic (500) 0x5BFA2D+1 - town hall (1000) 0x5BFA48+1 - city hall (2000) 0x5BFA63+1 - capitol (4000) 0x5BFABD+1 - grail bonus (5000)
Also you can add bonus to gold income given by resource silo: The table of integers is at 0x688F04. There are 7 ints per town, corresponing to different resources. The last one is the value for gold.
RE: Исследование героев - hippocamus - 12.08.201300:19
Кто знает:
- что за лоды прописаны в экзешнике героев h3psprit и h3pbitma?
- они реально подгружаются или нет?
RE: Исследование героев - AKuHAK - 16.08.201301:39
Это лоды из патча 1.3 возрождения эрафии. Да они в те далёкие времена так назывались. И да все лоды грузятся до сих пор (порядок точный уже не помню). Если возникают ещё вопросы по поводу древних лодов милости просим под спойлеры в этой теме.
p - значит патч ))
Например в патче 2.1 добавились h3abp_sp.lod и h3abp_bm.lod
RE: Исследование героев - Berserker - 27.12.201323:09
4E2C70 - thiscall (*hero) (*art => 8 bytes, slot or -1) - equip art
4E2E40 - thiscall (*hero) (slot) - unequip art
4E2AB0 - thiscall (*hero) (art, slot) - check if artifact can be put in the slot
RE: Исследование героев - Berserker - 27.12.201323:39
Валерий напомнил мою старую функцию. Не помню, как работает.
RE: Исследование героев - Valery - 28.12.201308:55
(27.12.2013 23:09)Berserker Wrote: ; x2 - art type
; x3 - art subtype or -1 (usually for non-scrolls)
Meh, this made me lose 1 hour and doubt about the state of my brain
Artifact type should be read artifact number or ID, as type is always 5, is the subtype/number which changes. So I couldn't make the artifacts be equipped again until I found the trick.
; x2 - art ID
; x3 - art subtype or -1 (usually for non-scrolls) -this is not clear for me what it means, for now I leave it -1, works like that.
Combos switch work perfectly. Everything is perfect, joy.
RE: Исследование героев - Berserker - 28.12.201316:18
You always missunderstand the meaning of word "type". Not "object type" (where 5 for artifacts would be ok) but artifact type. Type is a matter of classification )
RE: Исследование героев - Valery - 28.12.201316:20
Well usually I know where to put type and subtype, but those SN:E I have no clue how they work, so I took your words as God's bible. Still not sure what the second is about, the -1. It works with so I don't worry for now.
RE: Исследование героев - Berserker - 03.01.201422:21
; НАЗВАНИЕ: Removes commanders disbalance abilities
; ВЕРСИЯ: 1.0
; АВТОР: Berserker
; ОПИСАНИЕ: Убирает у Суккубов присоединение монстров, а у Зверей - золото после боя
; EXE: TE
; 76CC35:
; JNZ SHORT 0076CC3C => NOP(2)
307C35 9090
; 769A28:
; JNZ SHORT 00769A2C => NOP(2)
304A28 9090
как правильно прочитать адрес? 6918864 это 6918864 в десятичной, а что с 0x54?
В итоге считать UN:C[0x6992D0]/4/?y1; или UN:C([0x6992D0] + 0x54])/4/?y1
RE: Исследование героев - Berserker - 26.06.201400:22
0x54 = 84.
RE: Исследование героев - gamecreator - 26.06.201401:10
0x - традиционно обозначение 16-й системы.
RE: Исследование героев - Berserker - 27.06.201401:36
; НАЗВАНИЕ: Alterbranchs
; ВЕРСИЯ: 1.0
; АВТОР: The Master
; ОПИСАНИЕ: Реализация альтерветок (отдельная структура обитателей для каждого города на карте)
; EXE: MoP
;*******************************************************************
; Разрешить строительство зданий в городах союзника (кроме альтерветок):
;1D5EF7 EB; jz L005D5F0E -> jmp L005D5F0E - старый вариант, просто разрешение строительства любых зданий
;*******************************************************************
; 34. Установка прироста монстров в города в первый день игры:
1BEF9E E9260AFEFF; JMP mop.0059F9C9
1BEFA3 9090; NOP (2)
;*******************************************************************
; 35. Подсказка к орде первого уровня в городе при наведении мыши:
1C7CE5 8B4338; MOV EAX,DWORD PTR DS:[EBX+38]
1C7CE8 0FBE00; MOVSX EAX,BYTE PTR DS:[EAX]
1C7CEB E9981B070090; JMP mop.00639888; NOP
;007104E5 8A11 MOV DL,BYTE PTR DS:[ECX]
; SUB_L0047AB50 - ИИ-функция, не привязанная ни к какому городу, только к структуре. Оставляем там прежние адреса.
RE: Исследование героев - baratorch - 09.12.201412:29
inline void CrExpoSet_Remove(_Army_* army, int i)
{
int type_s;
_ptr_ crloc_s;
o_CrExpoSet_FindType(army, i, &type_s, &crloc_s);
o_CrExpoSet_Del(type_s, crloc_s);
}
inline int CrExpoSet_GetExp(_Army_* army, int i)
{
int type_s;
_ptr_ crloc_s;
o_CrExpoSet_FindType(army, i, &type_s, &crloc_s);
return army->type[i] < 0 ? 0 : o_CrExpoSet_GetExp(type_s, crloc_s);
}
inline void CrExpoSet_SetExp(_Army_* army, int i, int exp)
{
int type_s;
_ptr_ crloc_s;
o_CrExpoSet_FindType(army, i, &type_s, &crloc_s);
n_CrExpoSet_Set(type_s, crloc_s, army->type[i], army->count[i], exp);
}
RE: Исследование героев - Berserker - 09.12.201421:23
Подскажите, где найти функцию регенерации эликсира жизни. В воге/эре она подменяет стандартную, и вместо 50 хп регенит какой-то мусор, как мне кажется.
major Wrote:и вместо 50 хп регенит какой-то мусор, как мне кажется.
А разве должно 50 хп восстанавливаться?
FizMiG Wrote:Все войска героя (кроме undead, горгулий, големов и элементалей) получают 25% прибавку в HP и регенерируют до полного HP перед каждым ходом.
(03.03.2015 15:08)Berserker Wrote: Полный реген делает бессмертными командиров и оруженосцев.
Поэтому я предпочитал в качестве оруженосца брать привидение ))
RE: Баланс Heroes 3 HD Edition - Дьякон - 04.03.201515:41
Вот кстати адреса для СоДа, хотя может уже кто-то и выкладывал:
63AC58 - 5% урон за каждую единицу атаки
63AC28 - 300% - максимальный урон от базового
63B8C0 - 2.5% снижение урона за каждую единицу защиты
63AC50 - 100% база для вычитания урона
63B8B8 - 30% минимальный урон
все данные типа dq
RE: Исследование героев - Berserker - 04.03.201521:27
У приведения не полный реген, а очков 35, кажется.
Дьякон Wrote:Вот кстати адреса для СоДа, хотя может уже кто-то и выкладывал:
63AC58 - 5% урон за каждую единицу атаки
63AC28 - 300% - максимальный урон от базового
63B8C0 - 2.5% снижение урона за каждую единицу защиты
63AC50 - 100% база для вычитания урона
63B8B8 - 30% минимальный урон
RE: Исследование героев - gamecreator - 04.03.201523:57
(03.03.2015 12:10)major Wrote: Подскажите, где найти функцию регенерации эликсира жизни. В воге/эре она подменяет стандартную, и вместо 50 хп регенит какой-то мусор, как мне кажется.
Посмотри, по адресу 0x446BD6 вызывается какая-то. Это подменяет Вог. После подмены там натуральный реген + опыт отрядов.
(03.03.2015 12:10)major Wrote: Подскажите, где найти функцию регенерации эликсира жизни. В воге/эре она подменяет стандартную, и вместо 50 хп регенит какой-то мусор, как мне кажется.
Посмотри, по адресу 0x446BD6 вызывается какая-то. Это подменяет Вог. После подмены там натуральный реген + опыт отрядов.
Да, это я и нашел, а вот чем это подменяет вог, не могу найти.
RE: Исследование героев - gamecreator - 05.03.201519:49
Так запусти Вог, он и подменит этот вызов на свой. Ничего искать тут не надо.
Если надо, то можно бинарный патч сделать, который бы это отключал.
Спасибо, более-менее разобрался.
Такой вопрос. Никогда не писал dll. Может кто-нибудь показать на простом примере, как это делается? Допустим, расширить список существ с атакой-возвратом. Т.е. не расширить на всех существ, а просто добавить доп. проверки.
Code:
2F9059 CMP EAX,48
2F905C JE SHORT 2F90BB
2F905E CMP EAX,49
2F9061 JE SHORT 2F90BB
2F9063 CMP EAX,9B
2F9068 JE SHORT 2F908B
Добавить сюда проверку на 44h и 45h.
Или, через ерм_хукер.
RE: Исследование героев - gamecreator - 09.03.201515:43
Проще расширить на всех существ. Думаю, даже поместится вместо оригинального кода. Что-то типа
Code:
cmp [таблица+eax], 0
je short 2f908b
Перезаписываешь это в DLL_PROCESS_ATTACH или OnAfterWog.
RE: Исследование героев - feanor - 09.03.201518:27
В коде феанора все более-менее понятно, но есть пара вопросов.
1. advanced_properties[unit].strike_n_ret - это свойство юнита определено где-то ранее?
2.
RE: Исследование героев - gamecreator - 11.03.201514:08
Судя по всему, advanced_properties - просто новый массив из Хоты. Если тебе не хочется ничего расширять, то напиши свою проверку в условии, без массивов.
RE: Исследование героев - feanor - 11.03.201515:12
Quote:1. advanced_properties[unit].strike_n_ret - это свойство юнита определено где-то ранее?
единственно что, я его написал, но еще не проверял в работе))
RE: Исследование героев - gamecreator - 11.03.201515:56
Вообще польза от использования патчера в этом конкретном случае достаточно сомнительна. Если два мода независимо добавляют атаку с возвратом, то никакой патчер их совместимыми не сделает.
RE: Исследование героев - feanor - 11.03.201516:00
Quote:Вообще польза от использования патчера в этом конкретном случае достаточно сомнительна.
Чтоб не на ассемблере писать, тащемта
RE: Исследование героев - gamecreator - 11.03.201517:37
Подскажите по двум вопросам.
1. Как добавить проверку на эликсир жизни, чтоб он добавлял еще 50 хп к регену.
2. Регенерация от опыта существ работает как-то по-другому? Этот хук не срабатывает, реген проходит без воскрешения. Как это можно исправить?
RE: Исследование героев - feanor - 15.03.201519:30
Quote:1. Как добавить проверку на эликсир жизни, чтоб он добавлял еще 50 хп к регену.
o_BattleMgr->hero[((_BattleStack_*)c->esi)->side]->DoesWearArtifact(ID), как-то так
RE: Исследование героев - gamecreator - 15.03.201520:15
1. Что-то типа (с указанием героя, конечно)
Code:
Era::ExecErmCmd("HE:A2/131/?v1/?v1;");
if (Era::v[1]>0) ...
2. Выдержка из исходников Вога:
Code:
void IsTroll(void)
{
__asm{
mov IT_Mon,esi
mov edx,50 // умолчательное восстановление здоровья
mov IT_Edx,edx
cmp eax,0x3C
je l_Ok
cmp eax,0x3D
je l_Ok
cmp eax,0x90
je l_Ok
cmp eax,157 // гидра
je l_Ok_check
// jmp l_Exit
pusha
}
__asm mov IDummy,eax
#include "templ.h"
IT_Ret=CanNPCRegenerate(IDummy,IT_Mon);
if(IT_Ret!=-1){
IT_Ret=CrExpBon::Regenerate(IT_Mon,*(int *)&IT_Mon[0x58]);
if(IT_Ret==0){ // no reg
IT_Ret=0;
}else{ // yes
IT_Edx=IT_Ret;
IT_Ret=-1;
}
}
STOP
__asm{
popa
mov eax,IT_Ret
// je _Ok_check
jmp l_Exit
}
l_Ok_check:
CalcRand100();
__asm{
cmp eax,40 // 40%
ja l_Exit
}
l_Ok:
__asm mov eax,-1
l_Exit:
__asm mov edx,IT_Edx
}
Это та функция, что перезаписывается по 0x446BD6.
CrExpBon::Regenerate - это стандартная регенерация от опыта.
RE: Исследование героев - feanor - 17.03.201503:41
Как можно перебрать все объекты определенного типа/подтипа кодом?
ну, то бишь, как это делает Вог в UN:U?)
..эм
пробегать всю карту каждый раз? серьезно?
RE: Исследование героев - Дьякон - 17.03.201512:56
feanor, думаю серьезно.
------------------------------------------------------------------
63E9B8 - % для навыков некромантии/чародейства (массив из 4 dword)
476DA0 - воскрешение нечести после боя
4E3F40 - расчет % чародейства(некромантии) с учетом артефактов и специальностей
RE: Исследование героев - gamecreator - 17.03.201513:36
Конечно же, если нужны не сами объекты, а только их структуры (если есть), то тут уже можно найти их список.
(17.03.2015 12:56)Дьякон Wrote: 63E9B8 - % для навыков некромантии/чародейства (массив из 4 dword)
476DA0 - воскрешение нечести после боя
4E3F40 - расчет % чародейства(некромантии) с учетом артефактов и специальностей
А как при помощи ERM отключить навык Некромантии (со всеми артефактами, ПКН'ами и пр. усилителями некромантии)?
RE: Исследование героев - Дьякон - 17.03.201517:06
Через UN:C забиваешь для всех уровней некромантии 0, соответственно воскрешаться никто не будет.
Хотя не, нужно еще артефакты все отключать, т.к. там абсолютное приращение идет к %. Если нужно, то найду и выложу все адреса по некромантии.
RE: Исследование героев - Дьякон - 17.03.201517:20
Хотя можно сделать еще проще. Задать максимальный % воскресших 0%, который сейчас 100%. Но возможно с ним могут быть проблемы, т.к. данная константа может использоваться и в других расчетах, например как 0x63B8D0 одновременно отвечает и за мантию и за усилители.
RE: Исследование героев - Дьякон - 17.03.201517:40
Вот так будет (должно) работать и не нужно трогать константы:
И да константы универсальные и их правка не рекомендуется.
может что то типо этого или где-то тут, а может и нет....
RE: Исследование героев - feanor - 24.03.201518:09
Quote:Подскажите адрес указателя на распакованную текущую карту, если таковой имеется?
что конкретно интересует?
Code:
#define o_GameMgr (*(_GameMgr_**)0x699538)
в нем поля
// Заголовочная информация карты игры.
_MapHeader_ map_header; // +1F86Ch
// Карта игры.
_GameMap_ Map; // +1FB70h
RE: Исследование героев - Дьякон - 25.03.201518:08
Вот, что я искал - функции генератора карт:
54AE02 - вызов функции, которая устанавливает доступные артефакты. arg1 - колво байт, arg2 - буфер
54AF1B - вызов функции, которая устанавливает доступные заклинания. arg1 - колво байт, arg2 - буфер
54AF6E - вызов функции, которая устанавливает доступные вторичные навыки. arg1 - колво байт, arg2 - буфер
arg1 - указывает сколько байт будет считано из буфера (указатель arg2). В буфере хранится побитовая маска доступных артефактов/заклинаний/навыков.
Т.е. подменяя буфер, можно заставить рандомный генератор карт создавать карты с необходимой спецификацией. (например выкинуть имбалансные арты, или ненужные/редко используемые навыки)
Дьякон Wrote:например выкинуть имбалансные арты, или ненужные/редко используемые навыки
Водные артефакты/Навигацию на безводных картах. В ХотА вроде есть такое, у меня в ES скриптом сделано. Но отдельный бинарный фикс будет лучше, имхо.
Что касается остальных артов/навыков, то их надо править и балансировать вместо того, чтобы вырезать.
RE: Исследование героев - Дьякон - 25.03.201520:11
(25.03.2015 19:48)Algor Wrote: Водные артефакты/Навигацию на безводных картах. В ХотА вроде есть такое, у меня в ES скриптом сделано. Но отдельный бинарный фикс будет лучше, имхо.
Что касается остальных артов/навыков, то их надо править и балансировать вместо того, чтобы вырезать.
В СоДе скриптов нет, а балансить можно и со временем. Сначала выкинуть все, что мешает, а там видно будет. Вообще конечно можно вставить код и менять спецификацию перед началом карты как в скриптах, например. Но все же мне кажется настроить генератор как-то более правильным что ли. Хотя разницы практически никакой.
Подскажите, плиз, какой формат имеет файл с настройками (.dat)? Каким образом его лучше всего сжать?
RE: Исследование героев - Berserker - 26.03.201500:37
Эм, 1000 настроек по 4 байта каждая со значением 0 или 1? ))) Сжать можно чем угодно: Проще всего преобразовать в массив битов, тогда это будет 125 байт. Если много, тогда кодирование бегущих длин или как там RLE )
RE: Исследование героев - Valery - 30.03.201523:47
I think I will remove from HMS mod the total swap of backpacks (19-82 slots at once), it creates some bugs: all okay, I switch a lot between heroes, then later in game, sometimes it says backpack full, but is not; then when searching with erm, there are empty slots, probably conflict, no clue why. I will add instead this swap, alt+click, like in HD mod.
RE: Исследование героев - Valery - 31.03.201500:41
But for faster switch of backpacks, maybe a better idea would be shift+right/left-click directly from backpack when backpack open, what you think? You did the backpack script, do you think such thing could be possible?
RE: Исследование героев - Berserker - 31.03.201500:42
gamecreator, так вроде бы и раньше работала IF:M. Какой конкретно код? Valery, I thought I fixed artifact deletion function. It had bugs in 3.58, not decrementing artifacts counter, thus one day you see "no space" message. But after fixing in Phoenix there is not more any problem for years. Which code did you use to delete artifact?
RE: Исследование героев - Valery - 31.03.201500:51
We used your code to delete artifacts from equipped slots. I used my script for deleting all artifacts from hero x backpack and transfer them all to hero y. As it worked okay, we didn't check if your function is necessary also for backpack, but after testing several games, I get sometimes message "backpack full" (only when trying to discard an equipped artifact) while is not. But I don't know what causes it and can't reproduce the error.
Last part of the script (deleting adding artis):
RE: Исследование героев - Berserker - 31.03.201501:39
RightHeroGlobalStorage, em, how do you control this counter when player simple drops/equips/unequips artifact? Maybe just count real artifacts by looping all 64 slots?
RE: Исследование героев - feanor - 31.03.201501:42
All works well, but if I have two of same artifacts consecutive in backpack, it deletes the previous one when clicking on second (if left to right). This is because the erm code is searching for first artifact of that kind in backpack. Result is correct but visually is weird. Don't know a solution.
RE: Исследование героев - Valery - 31.03.201516:07
No, I don't think so, I had a double click (can be heard) and left hero had more than 5 gloves. Result is correct, but it looks weird. erm code is searching from left to right.
RE: Исследование героев - Berserker - 31.03.201523:55
RE: Исследование героев - Дьякон - 03.04.201510:41
(03.04.2015 01:13)Algor Wrote: Не те адреса, похоже. Есть верные для установки своих значений (не обнуления)?
Адреса те. Почитай несколько постов ниже после этого сообщения. Я писал, что кроме навыка некромантии на воскрешение влияет и прочие артефакты и строения.. Вот еще раз код
RE: Исследование героев - Дьякон - 03.04.201510:46
(03.04.2015 02:34)feanor Wrote: Все украдено до нас же.
Причем настолько давно, что никто уже и не помнит.
(03.04.2015 10:41)Дьякон Wrote: Адреса те. Почитай несколько постов ниже после этого сообщения. Я писал, что кроме навыка некромантии на воскрешение влияет и прочие артефакты и строения.. Вот еще раз код
Algor Wrote:Есть верные для установки своих значений (не обнуления)?
Очевидно, я где-то торможу... но это
и это
даже при отсутствии прочих артефактов и строений дают одинаковый результат, подозрительно похожий на штатную работу Некромантии...
PS: да, и попытка прочитать по этим адресам также возвращает что-то неожиданное (точных цифр не помню, дома вчера было). Собсно, поэтому и усомнился в их правильности.
RE: Исследование героев - Дьякон - 03.04.201514:17
Там данные в формате float и там не прокатит такое
15, 30,50 в формате флоат - стремится к нулю.
Мое упущение что не написал. Будет так
Не знаю может конечно в ерм есть перевод в флоат, если нет то нужно либо конвертор писать либо на калькуляторе переводить.
RE: Исследование героев - Berserker - 03.04.201515:30
RE: Исследование героев - Дьякон - 03.04.201517:10
Algor, и еще да ты прав на счет адресов, они явно идут не по порядку. Не знаю как я считал. Только первый адрес правильный.
(03.04.2015 17:10)Дьякон Wrote: Algor, и еще да ты прав на счет адресов, они явно идут не по порядку. Не знаю как я считал. Только первый адрес правильный.
Чёт ты опять как-то не так посчитал: 15 -> 1097859072
!!SN:Xe1 X?y1; работает отлично.
Дьякон, Берс, спасибо
RE: Исследование героев - Berserker - 03.04.201523:09
На здоровье
RE: Исследование героев - gamecreator - 03.04.201523:13
(03.04.2015 22:40)Algor Wrote: Чёт ты опять как-то не так посчитал: 15 -> 1097859072
(03.04.2015 17:10)Дьякон Wrote: Algor, и еще да ты прав на счет адресов, они явно идут не по порядку. Не знаю как я считал. Только первый адрес правильный.
Вы будете смеяться... но практика показывает что верные адреса эти:
Это действительно так, или это мои глюки при попытке писать "на сухую"? Экспериментировал без артов/строений/специализаций, если что.
*Пошел в холодильник за пивом*
RE: Исследование героев - Berserker - 04.04.201502:19
По-моему все эти адреса уже сто лет как были найдены Демиургом и оформлены в функцию. И да, там по три числа с плавающей запятой подряд идут.
RE: Исследование героев - gamecreator - 04.04.201503:11
В теме Демиург говорил о возможности менять силу навыка на нулевом уровне. Так что вполне возможно, что там по четыре числа подряд.
RE: Исследование героев - Дьякон - 04.04.201510:52
(04.04.2015 01:52)Algor Wrote: Это действительно так, или это мои глюки при попытке писать "на сухую"? Экспериментировал без артов/строений/специализаций, если что.
Да это так. Там 4 значения. Первое нулевое. Да и пользуйся функцией Демиурга, т.к. проверять данные не входит в мои привычки ))))
RE: Исследование героев - Berserker - 04.04.201515:18
Более того, я эту функцию перевёл под Эру и опубликовал здесь и на HC. Эх, всё хочу сделать ресурс, где такая информация хранилась бы отдельными записями. Неужели плодить подфорум и темы?
_int32_ creature_id; // +52 0x34 // тип монстра
_int32_ hex_ix; // +56 0x38 //позиция на поле боя
_int32_ def_group_ix; // +60 0x3C
_int32_ def_frame_ix; // +64 0x40
_dword_ second_hex_is_right; // +68 0x44 //(=1) сдвиг в сторону второй занятой клетки для монстра с двумя клетками
_dword_ field_48; // +72 0x48 ?
_int32_ count_current; // +76 0x4C // число монстров
_int32_ count_before_attack; // +80 +0x50 // число монстров до удара по ним в тек. атаку
_dword_ field_54; // +84 0x54 ?
_int32_ lost_hp; // +88 0x58 потери здоровья последнего монстра
_int32_ army_slot_ix; // +92 0x5C номер слота of _Army_ (0...6), -1 - будет удален после битвы
_int32_ count_at_start; // +96 0x60 число монстров в начале битвы
_dword_ field_64; // +100 0x64 ?
_dword_ anim_value; // +104 0x68 = cranim.f[15] при инициализации
_int32_ full_hp; // +108 0x6C полное здоровье (исп. как база для лечения)
_int32_ active_spells_count; // +404 0x194 dd = количество уже наложенных заклинаний
_int32_ active_spell_duration[81]; // +408 0x198 есть заклинание (длительность) или нет
_int32_ active_spells_power[81]; // +732 0x2DC (сила действия заклинания)
_byte_ field_420[52]; // +1056 0x420 ?
_int32_ retaliations; // +1108 0x454 // 441B17 (кол-во ответов на атаку 0= не отв. на атаку)// настройка для грифонов 46D6A0
_int32_ bless_value; // +1112 0x458 Bless добавка к Max. Damage
_int32_ curse_value; // +1116 0x45C Curse убавка к Min. Damage
_int32_ field_460; // +1120 0x460 ?
_int32_ bloodlast_value;// +1124 0x464 Bloodlast добавка к Атаке с бонусами
_int32_ precision_value;// +1128 0x468 Precision добавка к Атаке с бонусами
_byte_ field_46C[32]; // +1132 0x46C ?
_int32_ king_type; // +1164 0x48C dd KING_123 тип (1=KING_1,2=KING_2,3=KING_3) // исп для расчета Slayer. Бонус 8 к Атаке: 0x4421D2
_int32_ field_490; // +1168 0x490 dd номер атакера по порядку??? уже атаковал??? (сбрасывается после первого удара)
_int32_ counerstrike_retaliations; // +1172 0x494 dd кол. доп. ответов на атаку, добавленных Counerstrike заклом
_byte_ field_498[40]; // +1176 0x498 ?
_bool8_ blinded; // +1216 0x4C0 db Blinded - снизить защиту (сбросить после?) при атаке на него (уст. перед ударом)
_bool8_ paralized; // +1217 0x4C1 db Paralized - снизить защиту (сбросить после?) при атаке на него (уст. перед ударом)
_bool8_ forgetfulness; // +1218 0x4C2 dd Forgetfulness - уровень (>2 - не может стрелять)
_byte_ field_4C3[25]; // +1219 0x4C3 ?
_int32_ defend_bonus; // +1244 0x4DC dd = величина бонуса при выборе защиты
_int32_ faerie_dragon_spell;// +1248 0x4E0 dd заклинание для сказ дракона
_byte_ field_4E4[100];
// +4EC dd 44152A
// +4F1 db 43DF88
// +514 dd
// +518 dd -> dd first \ adjusted stacks pointers
// +51C dd -> dd last /
// +524 dd
// +528 dd -> dd first \ adjusted to wich stacks pointers
// +52C dd -> dd last /
};
RE: Исследование героев - gamecreator - 26.08.201510:16
igrik, т.е. можно показывать диалог не по центру?
Если да, то очень большое спасибо. Я хотел такое в BH сделать, но прямо и без артефактов не получалось.
да, ты сам можешь динамически изменять координаты, НО перед вызовом диалога. Как обновлять/перерисовывать диалог на лету я так и не разобрался
(17.07.2015 16:11)gamecreator Wrote: Ну и не забыть перерисовать диалог:
hdlg->0x7299FD(-1
!!SN:E7510525/1/-1; вызывает у меня вылет, тут видимо я не так что-то понял
upd: Algor, если будут вопросы или нужна помощь по этой функции, обращайся. Например можно ее дописать, чтобы прилеплять диалог к правому/ левому/нижнему/верхнему бокам экрана
Запаковано в виде мода. Скачать
Это диалоговое окно выбора режима битвы. Нападешь на монстра - появится это окно. На нажатие клавиши "7" происходит отрисовка диалога в других координатах. Клавиша "5" просто информация.
RE: Исследование героев - gamecreator - 11.09.201515:11
так !!SN:E7510525/0/-1;
и так!!SN:E7510525/1/68;, где 68-номер WoG диалога
и так!!SN:E7510525/2/68;, где 68-номер WoG диалога
и еще много чего, но всё с этим адресом
RE: Исследование героев - gamecreator - 11.09.201515:24
Ну это я увидел. А где вариант с thiscall? Напоминаю:
Quote: E #1 / #2 / ... up to 62 parameters; Execute external function
#1 = function address
#2 = calling conversion
0 - Pascal (use for all Angel.dll functions)
1 - Cdecl or Stdcall (use for WinAPI and the majority of other functions) 2 - ThisCall (use it only if you know, what you are doing)
3 - FastCall (the same as above, try to avoid)
Первый аргумент - this (третий аргумент команды соответственно).
Что конкретно неясно?
К слову, исправил на thiscall и всё заработало. Только старое изображение диалога осталось, наверное надо экран перерисовать сперва.
я исправил на thiscall, и у меня не работало, ни тогда, ни сейчас.
Почему я и обратился к тебе за помощью. У меня вылетает, и перепробовал я все что только мог, в том числе и thiscall
RE: Исследование героев - gamecreator - 11.09.201515:36
(11.09.2015 15:17)igrik Wrote: upd, и да, я пробовал и так !!SN:E7510525/2/-1; результат тот же = вылет
а еще:
так !!SN:E7510525/0/-1;
и так!!SN:E7510525/1/68;, где 68-номер WoG диалога
и так!!SN:E7510525/2/68;, где 68-номер WoG диалога
и еще много чего, но всё с этим адресом
Теперь понятно. Поясняю: thiscall - это вызов метода объекта (если ты знаком с ООП). Функции такого типа принимают дополнительный параметр this, указатель на сам объект. Синтаксис вызова thiscall:
Смотрим в описание функции:
Функция имеет один параметр, но в дополнение является методом объекта диалога. Значит нужно передать ей адрес этого объекта. Смотрим снова в описание, как же получить сам диалог, тоесть объект:
(17.07.2015 16:11)gamecreator Wrote: Получить адрес диалога можно по номеру диалога:
hdlg = cdecl 0х729AD3(int32 id)
Или получить последний (текущий?) отображаемый диалог:
hdlg = [0x887650]
Quote:Теперь понятно. Поясняю: thiscall - это вызов метода объекта (если ты знаком с ООП). Функции такого типа принимают дополнительный параметр this, указатель на сам объект. Синтаксис вызова thiscall:
!!SN:Eфункция/2/this/параметры;
не знал. Получилось. Естественно осталось старое изображение диалога. Буду искать способы решения.
это побитовый сдвиг с присваиванием? блин, для меня это темный лес, а можно разжевать для чайника
RE: Исследование героев - gamecreator - 24.10.201500:32
Разве ты с флагами существ не работал?
Вообще у Миханика хорошо рассказано, в предисловии к справке по значениям OB:C. Недавно мелькала тут ссылка на дф2.
работал, но я всё равно не вижу связи. Ты хочешь сказать, что это вроде проверки &16 или |16?
RE: Исследование героев - gamecreator - 24.10.201501:55
Да. Вот смотри, есть у тебя int:
Code:
□□□□ □□□□ □□□□ □□□□ □□□□ □□□□ □□□□ □□□□
Всего 32 двоичных цифры (то есть 32 бита).
Число твоё - это сумма: (x & 0x3FF) + ((y & 0x3FF) << 16) + ((l & 0xF) << 26).
0x3FF = 11 1111 1111 (10 бит)
0xF = 1111 (4 бита)
Это обычная маска, как в твоём &16.
Теперь смотришь на сдвиг. Значение сдвинуто влево на несколько бит, то есть все его цифры переместились на более старшие позиции. Если сдвинуто влево на 1 бит, то 0-й бит будет пустым, а значение будет начинаться с 1-го бита. Если сдвинуто на 2, то 0-й и 1-й биты пустые, значение начинается со 2-го и т.д.
Значит x начинается с 0-го бита, y - с 16-го, l - с 26-го:
Code:
- □□□□ □□□□ □□□□ □□□□ □□□□ □□□□ □□□□ □□□□
x 11 1111 1111
y 11 1111 1111
l 11 11
Как видишь, они не пересекаются. Каждое значение на своём месте:
!?CM0 - вызывается при клике ПКМ на карте приключений
!?CM1 - вызывается при клике в окне замка
!?CM2 - вызывается при клике в окне героя
!?CM3 - вызывается при клике в окне обмена между героями
!?CM4 - вызывается при клике на поле боя
!?CM5 !?CM9 - вызываются при клике ЛКМ на карте приключений
!?CM6 - вызывается при одевании артефакта
!?CM7 - при движение мышью в бою
!?CM8 - при движении мышью в городе
!?CM11 - после покупки здания (видимо при обновлении/прорисовке окна города и карты приключений, окна боя), посещение любого объекта на карте,
!?CM12 - при открытии книги заклинаний на карте приключений через кнопку
!?CM13 - при закрытии книги заклинаний на карте приключений через кнопку
!?CM14 - вход в окно покупки зданий в городе
!?CM15 - выход из окна покупки в городе
!?CM30 - открытие окна командира
!?CM31 - закрытие окна командира
триггеры CM10, 16...21 пока не нашёл
RE: Исследование героев - feanor - 12.11.201504:29
о_О
шо, правда?
RE: Исследование героев - feanor - 12.11.201504:36
А, отставить офигевать.
Сравни с списком (erm.cpp)
Quote:// 30310 mouse click на карте (правый) !?CM0
// 30311 mouse click в Городе !?CM1
// 30312 mouse click in hero screen !?CM2
// 30313 mouse click it two heroes screen !?CM3
// 30314 mouse click in battlefield !?CM4
// 30315 игрок снял артифакт
// 30316 игрок одел артифакт
// 30317 mouse move over battlefield
// 30318 mouse move over townscreen
// 30319 mouse click на карте (левый) !?CM5
// 30320 MP3 music
// 30321 WAV and M82 Sound 3.58
// 30322 Magic cast (adv. map) (pre-trigger)
// 30323 Magic cast (adv. map) (post-trigger)
// 30324 Go to Town Hall Screen 3.58 !?TH0
// 30325 Leave Town Hall Screen 3.58 !?TH1
// 30330 MP before sending data before battle
// 30331 MP after receiving data before battle
// 30332 MP before sending data after battle
// 30333 MP after receiving data after battle
// 30334 MP received data during a battle
// 30340 CO Перед открытием диалога Командира
// 30341 CO После закрытия диалога Командира
// 30342 CO После покупки Командира в городе
// 30343 CO После воскрешения Командира в городе
Что то не могу найти в exe: по какому адресу лежит "avwphx.def".
Да и вообще с подменой дефа феникса жуткие траблы. Не меняются дефы, хоть убей. Приходится изменять название через патч экзешника. С основным дефом и озвучкой разобрался. Но вот деф на карте не могу найти
или что такое?
_int_ advmap_low;
_int_ advmap_high;
RE: Исследование героев - feanor - 05.12.201500:18
Дефы на карте в объектных текстовиках.
RE: Ваши вопросы по ERM-скриптам - feanor - 25.12.201514:06
Генерация рандомных артов - это 004C9190
(25.12.2015 02:34)Algor Wrote: Кто в курсе, как разрешить генерацию WoG-артефактов, например, артефактов командира, на карте (на месте случайных артефактов...)?
(25.12.2015 12:18)igrik Wrote: Может можно через UN:C расширить кол-во артов. Мож там функция типа "_random[7,125]" и можно ее сделать "_random[7,255]"?
да, там надо в двух местах поправить константу (=144) на сколько надо.
Там есть нюанс - оно заодно обращается к двум таблицам (запрета артов и уже наличествующих артов), которые имеют фиксированный размер и, что хуже, лежат в очень динамической памяти
На DF2 зашел разговор о телекинезе, делать было нечего, поэтому начал накидывать, но потом что-то стало влом.
Короче, функция посещения героем любого объекта удалённо (даже самого себя):
Накопал я довольно таки интересную вещь в сетевом режиме (LAN). Итак, при генерации карты в триггере !?PI, пользуясь функцией удаления объекта (при замене оных) мы получаем гарантированный вылет. Это происходит вследствие того, что в геройской функции удаления объектов есть функция "звукового сопровождения". Если ее занопить на момент генерации карты, то вылета игры не будет. А т.к. на этот момент передача сетевых данных еще не происходит, то мы получаем рабочий код замены объектов, не требующий использования таймеров и других плюх. Плюс при показе карты приключений как на стороне сервера, так и на стороне клиента мы уже имеем замененные объекты. Т.е. 1 часть рассинхрона мы вылечили (остается еще решить рассинхрон в битве. Тут у меня уже тоже есть кое-какие наблюдения и как это лечить).
Код выглядит так (на примере замены двусторонних монолитов на мельницы) (Click to View)
И ещё, я не использовал функцию UN:U [сосчитать все объекты на карте], потому что при передаче хода от клиента серверу происходит непонятный вылет, связанный с библиотекой "kernel32.dll" и не связанный с этим патчем.
хм, очень интересно.
Т.е. по сути можно уже щас взять оф.скрипты из WoG и "вылечить" их, обозвав это тестингом на стабильность и выложить для массового тестинга людям?
P.S.
(21.03.2017 17:45)igrik Wrote: И ещё, я не использовал функцию UN:U [сосчитать все объекты на карте], потому что при передаче хода от клиента серверу происходит непонятный вылет, связанный с библиотекой "kernel32.dll" и не связанный с этим патчем.
а ты не проверял этот момент на разных ОС (Xp, win7+)
вдруг там будут разные "грабли"?
(25.03.2017 17:25)Bes Wrote: хм, очень интересно.
Т.е. по сути можно уже щас взять оф.скрипты из WoG и "вылечить" их, обозвав это тестингом на стабильность и выложить для массового тестинга людям?
а ты не проверял этот момент на разных ОС (Xp, win7+)
вдруг там будут разные "грабли"?
Проверял на XP и на Win7_x64.
Да, можно. И я бы даже сказал - что нужно. Но у меня совершенно нет желания перелопачивать тонну оф.скриптов. Вообще.
igrik, могу потихоньку начать... по порядку.
я правильно понял, что эту махинацию надо делать каждый раз при замене объкта на карте в скрипте (или удалении)?
буду не спеша, чтобы лишних багов не натворить по невнимательности.
в отдельной теме выкладывать До и ПОСЛЕ файл с описанием что заменял.
дабы была и сторонняя модерация подмены кода.
(26.03.2017 16:51)Bes Wrote: igrik, могу потихоньку начать... по порядку.
я правильно понял, что эту махинацию надо делать каждый раз при замене объкта на карте в скрипте (или удалении)?
Не совсем. Этот код расчитан только на момент действия триггера !?PI. Вся суть заключается в том, что (для LAN):
1. Хост нажимает кнопку "Начать"
2. Происходит генерация (для случайных) а потом загрузка карты.
2а. Тут вызывается триггер !?PI и в данном случае наша подмена объектов
3. Происходит передача сетевых данных клиенту, в том числе и карты (в нашем случае уже с измененными объектами).
В итоге: у обоих игроков при первом показе карты приключений все объекты идентичны.
Данный скрипт актуален для всех скриптов, которые заменяют объекты только в первый день. Например: замены картографов, улиев, и весь комплекс опций от "Замена объектов во время WoG'ификации.
На счет замены в другие игровые дни не скажу. Да и сейчас для этого нет достаточного запаса времени.
(26.03.2017 16:51)Bes Wrote: буду не спеша, чтобы лишних багов не натворить по невнимательности.
в отдельной теме выкладывать До и ПОСЛЕ файл с описанием что заменял.
дабы была и сторонняя модерация подмены кода.
Было бы конечно отлично, но спрошу ещё раз: стоит ли игра свечь?
igrik, я на больничный пошёл... могу сидеть смотреть сериалы, порно кино, или же таки открыть скрипты и прогнать всю эту тему по мере возможного.
вроде бы замена wog'ификацией идёт в теле таймера... не?
RE: Исследование героев - gamecreator - 27.03.201714:57
(27.03.2017 13:16)Bes Wrote: вроде бы замена wog'ификацией идёт в теле таймера... не?
Так о том и речь. Если замена в начале игры, то перенести её в !?PI.
(27.03.2017 13:16)Bes Wrote: вроде бы замена wog'ификацией идёт в теле таймера... не?
В том и дело, что все те замены которые идут в теле таймера (только для первого дня) следует перенести в тело !?PI;
И раньше мы получали гарантированный вылет, сейчас - нет.
RE: Исследование героев - hippocamus - 03.04.201705:46
Вот всегда инстересовал вопрос - почему многие ресиверы нормально обрабатываются в ?!PI, но не работают в качестве инструкций #! ?
Что вообще допустимо в инструкциях?
(да, у вас переставлены местами символы ? и !. старого ермиста не проведёшь!)
(03.04.2017 05:46)hippocamus Wrote: Вот всегда инстересовал вопрос - почему многие ресиверы нормально обрабатываются в ?!PI, но не работают в качестве инструкций #! ?
Что вообще допустимо в инструкциях?
Немного странный вопрос если честно. Это же разные участки кода, куда поставлены хуки триггеров и инструкции.
(03.04.2017 05:46)hippocamus Wrote: (да, у вас переставлены местами символы ? и !. старого ермиста не проведёшь!)
Зачем его пытаться провести, когда он сам это делает с успехом. Либо кто-то уже совсем старый в этом деле, и кое-что успел подзабыть.
RE: Исследование героев - RoseKavalier - 12.08.201705:18
Hello
Привет!
Sorry for English! I will try to translate with Yandex...
Извините за английский! Я попытаюсь перевести с Яндекс...
Is it possible to link these includes that were previously available here ?
Можно ли связать эти включает в себя, которые ранее были доступны здесь ?
Would be very nice for making plugins)
Было бы очень хорошо для создание плагинов)
RE: Исследование героев - RoseKavalier - 18.08.201700:20
Thank you)
Спасибо)
By any chance, you wouldn't happen to have an example of creating a custom dialog? I understand how to use 0x4F6C00 but I can't figure how to make one from scratch ..
Вы случайно не пример создания пользовательского диалогового окна? Я понимаю, как использовать 0x4F6C00, но я не могу понять, как сделать один с нуля
RE: Исследование героев - feanor - 18.08.201701:57
No, I haven't.
If I'll need it someday, probably I will use !!DL and ExecErm.
(18.08.2017 00:20)RoseKavalier Wrote: By any chance, you wouldn't happen to have an example of creating a custom dialog? I understand how to use 0x4F6C00 but I can't figure how to make one from scratch ..
Уфф!!! И у меня наконец-то что-то начало получаться:
Code:
void AdvMgr_ShowTestDlg(int x, int y)
{
int cx = 256; // ширина (width)
int cy = 106; // высота (height)
int zx = 22; // отступ по x
int zy = 55; // отступ по y
_Dlg_* dlg = _CustomDlg_::Create(-1, -1, cx, cy, DF_SCREENSHOT | DF_SHADOW, NULL); // создали диалог
dlg->AddItemByZOrder(_DlgStdBackground_::Create(0,0,dlg->width,dlg->height, 0, 0, o_GameMgr->GetMeID()), 0); // рамка в цвете игрока
// dlg->AddItem(_DlgBlueBackground_::Create(0,0, dlg->width, dlg->height, o_GameMgr->GetMeID())); // синяя рамка как в HD
dlg->AddItem(_DlgStaticText_::Create(0, 20, dlg->width, 42, "Вы действительно хотите выйти?", "medfont.fnt", 1, 0, ALIGN_H_CENTER | ALIGN_V_TOP, 0)); // заголовок
RE: Исследование героев - RoseKavalier - 18.08.201717:24
@feanor
Sadly, cannot use ERM for what I want (SoD).
@igrik
Very nice!
I will try it and see if I can get some more things figured out and share back results)
RE: Исследование героев - RoseKavalier - 02.09.201708:13
I've not managed to discover much except about this:
Right-click window message on item
Code:
_DlgItem_* it;
it = dlg->GetItem(7);
it->full_tip_text = "This is right-click popup message.";
Dialog only open during right-click
Code:
//dlg->Run(); // don't use this
//dlg->Destroy(TRUE); // don't use this
dlg->RMC_Show();
Some work done... not sure if I should make it available to public even with multiplayer checks. I don't mind sharing code, just don't want it to fall in wrong hands, opinions?
Some things I'm interested in (if anyone knows) :
assign a variable/function to a clicked item (not only button, also defs - see 4/5)
read text in the edit dialog
make edit dialog numbers/text only
make the highlighted cadre when clicking an item (like level-up skills)
changing defs (like HWrulez button)
I think some of these may be connected to each other but I could not figure it out so far.
4:
5:
Any help greatly appreciated)
RE: Исследование героев - Valery - 02.09.201714:18
Can't add a check if game is MP or single, as cheat codes? Then I see no problem with releasing the code, btw great job
RE: Исследование героев - RoseKavalier - 02.09.201719:17
(02.09.2017 14:18)Valery Wrote: Can't add a check if game is MP or single, as cheat codes? Then I see no problem with releasing the code, btw great job
Merci, I think the inspiration should look familiar to you!
Of course, almost all my code has no-multiplayer check, but anyone with a little knowledge and bad intentions could circumvent it - hence my hesitation.
Fantastic, it seems you've figured most of it already) :D
Another question: how about "mouse-over text"?
Code:
dlg->AddItemByZOrder(_DlgStdBackground_::Create(x, y, w, h, id, bottom_bar=TRUE, player_id), 0);
[...]
dlg->GetItem(some_id)->short_tip_text = "Text to show in bottom bar."
//guess you need text in bottom bar
dlg->AddItem(_DlgStaticText_::Create(x, y, w, h, ?messageText?, font, color, id, ALIGN_H_CENTER | ALIGN_V_TOP, bkcolor));
RE: Исследование героев - Valery - 02.09.201720:20
(02.09.2017 19:17)RoseKavalier Wrote: but anyone with a little knowledge and bad intentions could circumvent it - hence my hesitation.
If a player is motivated enough to change your code in order to cheat, it already means he can already cheat by using other obvious tools, as playing the autosaves on another device and find how split works anyway.
// показ сообщения по ПКМ на первичных навыках командира
void Y_New_CommanderDlg_ShowPreSkill_RMC(int npc_id, int skill)
{
int skill_power = *(int*)(0x28620C0 + 296 * npc_id + 56 + skill*4); // получить силу скила
char* text = "";
int sizeX, sizeY;
bool art_npc_155 = false;
for (char i = 0; i < 6; ++i ){
if (o_Npc[npc_id].arts[i][0] == 155 )
art_npc_155 = true;
}
if ( !art_npc_155 || skill_power > 1 )
{
text = Get_ITxt(skill_power + 136 + skill *6, 1); // получить строку в текстовике в зависимости от силы скила
sizeX = 560; sizeY = 440;
}
else
{
text = Get_ITxt(skill + 236, 1);
sizeX = 340; sizeY = 220;
}
int __stdcall Y_New_CommanderDlg_Proc(_Dlg_* dlg_Npc, _EventMsg_* msg)
{
int r = dlg_Npc->DefProc(msg);
int npc_id = dlg_Npc->field_64; // получаем номер командира/героя
_Npc_* npc = GetNpc(npc_id); // получаем структуру командира
_Hero_* hero = o_GameMgr->GetHero(npc_id); // структура героя
int temp_1, temp_2; // временная переменная
// обновление подсказки при движении мыши (id = 10)
if (msg->type == MT_MOUSEOVER)
{
_DlgItem_* it = dlg_Npc->FindItem(msg->x_abs, msg->y_abs);
char* text = "";
if (it)
{
switch (it->id)
{
case 3: text = Get_ITxt(263, 1); break; // подсказка Уволить командира
case 4: text = Get_ITxt(273, 1); break; // подсказка для просмотра биографии
case 6: text = Get_ITxt(npc->type + 10, 1); break; // подсказка первого спец_умения
case 7: text = Get_ITxt(npc->type + 10, 2); break; // подсказка второго спец_умения
case 11: text = Get_ITxt(259, 1); break; // подсказка Имя командира
case 12: text = Get_ITxt(npc->lvl_attack + 100, 1); break; // подсказка дефа навыка атаки
case 13: text = Get_ITxt(npc->lvl_defence + 106, 1); break; // подсказка дефа навыка защиты
case 14: text = Get_ITxt(npc->lvl_hit_points + 112, 1); break; // подсказка дефа навыка здоровья
case 15: text = Get_ITxt(npc->lvl_damage + 118, 1); break; // подсказка дефа навыка урона
case 16: text = Get_ITxt(npc->lvl_spell_power + 124, 1); break; // подсказка дефа навыка силы магии
case 17: text = Get_ITxt(npc->lvl_speed + 130, 1); break; // подсказка дефа навыка скорости
case 31: case 61: sprintf(o_TextBuffer, "%s%d", Get_ITxt(264, 1), npc->now_level +1); text = o_TextBuffer; break;// подсказка уровня командира
case 32: case 33: text = Get_ITxt(242, 1); break; // подсказка класса командира
case 34: case 35: sprintf(o_TextBuffer, "%s%s", Get_ITxt(266, 1), hero->name); text = o_TextBuffer; break;// подсказка хозяина героя
case 36: case 37: sprintf(o_TextBuffer, "%s%d", Get_ITxt(267, 1), npc->now_expa); text = o_TextBuffer; break;// подсказка текущего опыта
case 38: case 39: sprintf(o_TextBuffer, "%s%d", Get_ITxt(268, 1), CALL_1(int, __thiscall, 0x769260, npc)); text = o_TextBuffer; break;// подсказка следующего опыта
case 40: text = Get_ITxt(269, 1); break; // подсказка навыки класса
case 41: text = Get_ITxt(270, 1); break; // подсказка артефакты
case 42: text = Get_ITxt(271, 1); break; // подсказка основные навыки
case 43: text = Get_ITxt(272, 1); break; // подсказка вторичные навыки
case 45: temp_1 = Get_NpcSkillPower(npc, 0); temp_2 = hero->attack;
if ( npc->type == 7 ) temp_2 += (temp_2/2);
sprintf(o_TextBuffer, Get_ITxt(275, 2), temp_1 + temp_2); text = o_TextBuffer; break; // подсказка атака
case 46: temp_1 = Get_NpcSkillPower(npc, 1); temp_2 = hero->defence;
if ( npc->type == 7 ) temp_2 += (temp_2/2);
sprintf(o_TextBuffer, Get_ITxt(276, 2), temp_1 + temp_2); text = o_TextBuffer; break; // подсказка защита
case 47: sprintf(o_TextBuffer, Get_ITxt(277, 2), Get_NpcSkillPower(npc, 2)); text = o_TextBuffer; break; // подсказка здоровье
case 48: sprintf(o_TextBuffer, Get_ITxt(278, 2), Get_NpcSkillPower(npc, 3)/2, Get_NpcSkillPower(npc, 3)); text = o_TextBuffer; break; // подсказка сила урон
case 49: sprintf(o_TextBuffer, Get_ITxt(279, 2), Get_NpcSkillPower(npc, 4)); text = o_TextBuffer; break; // подсказка сила магии
case 50: sprintf(o_TextBuffer, Get_ITxt(280, 2), Get_NpcSkillPower(npc, 6)); text = o_TextBuffer; break; // подсказка сопротивление
case 51: sprintf(o_TextBuffer, Get_ITxt(281, 2), ((npc->specBon[0] & 0x10) ? 24 : 0)); text = o_TextBuffer; break; // подсказка боезапас
case 52: sprintf(o_TextBuffer, Get_ITxt(282, 2), Get_NpcSkillPower(npc, 5)); text = o_TextBuffer; break; // подсказка скорость
case 30722: text = Get_ITxt(261, 1); break; // Ok Выход
default: text = ""; break;
}
statbar->SetText(text);
statbar->Draw();
statbar->RedrawScreen();
}
}
if (msg->type == MT_MOUSEBUTTON)
{
if (msg->subtype == MST_RBUTTONDOWN) // клик ПКМ
{
switch (msg->item_id)
{
case 3: b_MsgBox(Get_ITxt(201, 1), MBX_RMC); break; // Уволить командира
case 4: case 11: b_MsgBox(Get_ITxtBio(npc_id, 1), MBX_RMC); break; // ПКМ для просмотра биографи
case 6: b_MsgBox(Get_ITxt(npc->type + 19, 1), MBX_RMC); break; // ПКМ первого спец_умения
case 7: b_MsgBox(Get_ITxt(npc->type + 19, 2), MBX_RMC); break; // ПКМ второго спец_умения
case 12: Y_New_CommanderDlg_ShowPreSkill_RMC(npc_id, 0); break; // ПКМ дефа навыка атаки
case 13: Y_New_CommanderDlg_ShowPreSkill_RMC(npc_id, 1); break; // ПКМ дефа навыка защиты
case 14: Y_New_CommanderDlg_ShowPreSkill_RMC(npc_id, 2); break; // ПКМ дефа навыка здоровья
case 15: Y_New_CommanderDlg_ShowPreSkill_RMC(npc_id, 3); break; // ПКМ дефа навыка урона
case 16: Y_New_CommanderDlg_ShowPreSkill_RMC(npc_id, 4); break; // ПКМ дефа навыка силы магии
case 17: Y_New_CommanderDlg_ShowPreSkill_RMC(npc_id, 5); break; // ПКМ дефа навыка скорости
case 32: case 33: b_MsgBox(Get_ITxt(npc->type + 186, 1), MBX_RMC); break; // ПКМ на описании класса
case 30722: b_MsgBox(Get_ITxt(261, 2), MBX_RMC); break; // ПКМ Ok Выход
}
}
}
return r;
}
// новое диалоговое окно командира для ERA (0x0076A46E)
int Y_New_CommanderDlg_Show(int NHero_id, bool lvl_up)
{
_Npc_* npc = GetNpc(NHero_id); // получаем структуру командира
_Hero_* hero = o_GameMgr->GetHero(NHero_id); // структура героя
int sizeX, sizeY;
char* name_pcx;
// деф командира
dlg->field_64 = NHero_id; // сохраняем номер командира в структуре диалога для Dlg_Proc
dlg->AddItem(_DlgStaticPcx8_::Create(20, 70, 100, 130, 4, "CRBKGNEU.pcx")); // фон замка под дефом командира нейтральный (id = 4)
dlg->AddItem(CommDef = _DlgStaticDef_::Create(-130, -80, 100, 130, 5, o_CreatureInfo[npc->type + 174].def_name, 0, 0, 0x12)); // шагающий деф командира (id = 5)
// задник диалога под цвет игрока (id = 1)
_DlgStaticPcx8_* fonPcx;
dlg->AddItem(fonPcx = b_DlgStaticPcx8_Create(0, 0, dlg->width, dlg->height, 1, name_pcx, 2048));
fonPcx->Colorize(o_GameMgr->GetMeID());
// кнопки ок и уволить
dlg->AddItem(_DlgButton_::Create(285, dlg->height -76, 64, 30, 30722, "iOkay.def", 0, 1, 1, 28, 2)); // кнопка ok (id = 30722)
dlg->AddItem(_DlgButton_::Create(564, dlg->height -76, 51, 35, 3, "hsbtns2.def", 0, 1, 1, 28, 2)); // кнопка удалить командира (id = 3)
CALL_3 (void, __thiscall, 0x50CEA0, o_MouseMgr, 0, 0); // установить курсор(0,0)
dlg->AddItem(_DlgStaticText_::Create(20, 70, 100, 130, "", "medfont.fnt", 1, 4, ALIGN_H_CENTER | ALIGN_V_CENTER, 0)); // подсказка на дефе (пустышка, но по ней ПКМ определяет id и выдает окно биографии)
// дефы спец_умений командира
dlg->AddItem(_DlgStaticDef_::Create(395, 113, 43, 43, 6, "ComSkls.def", npc->type *2, 0, 0x12)); // первый деф спец_умений (id = 6)
dlg->AddItem(_DlgStaticDef_::Create(504, 113, 43, 43, 7, "ComSkls.def", npc->type *2 +1, 0, 0x12)); // первый деф спец_умений (id = 7)
#define o_Npc ((_Npc_*)0x28620C0) // получение структуры командира
struct _Npc_;
// Структура командира 0x128h (296)
NOALIGN struct _Npc_
{
_dword_ on; // 0x00 +0 Доступность
_dword_ alive; // 0x04 +4 Жив_или_мёртв
_dword_ id; // 0x08 +8 Номер_героя_хозяина (ну и номер командира)
_dword_ type; // 0x0C +12 Тип_командира
_dword_ type_Hero; // 0x10 +16 Тип_героя
_dword_ LastExpaInBattle; // 0x14 +20 Опыт в прошлых битвах
_dword_ CustomPrimary; // 0x18 +24 Если вы установить 1 (вкл), первичные навыки не будут изменяться с продвижением командира по уровням
// Если установить 0, то здоровье и урон будут автоматически прибавляться вместе с уровнем командира (из ERM Help = CO:P)
_dword_ attack; // 0x1C +28 Атака
_dword_ defence; // 0x20 +32 Защита
_dword_ hit_points; // 0x24 +36 Здоровье
_dword_ damage; // 0x28 +40 Урон
_dword_ spell_power; // 0x2C +44 Сила_магии
_dword_ speed; // 0x30 +48 Скорость
_dword_ resistance; // 0x34 +52 Сопротивление
// функция получения адреса структуры командира
inline _Npc_* GetNpc(_int_ hero_id) {return ((_Npc_ *)(0x28620C0 + 296 * hero_id));}
// функция получения строк из командирского текстовика "znpc00.txt"
inline char* Get_ITxt(int StrNum, int ItemNum) {return CALL_3 (char*, __cdecl, 0x77710B, StrNum, ItemNum, 0x2860724);}
// функция получения строк из командирского текстовика "znpc01.txt" Имена и биографии
inline char* Get_ITxtBio(int StrNum, int ItemNum) {return CALL_3 (char*, __cdecl, 0x77710B, StrNum, ItemNum, 0x286072C);}
// функция получения силы первичного командирского навыка
inline int Get_NpcSkillPower(_Npc_* npc, int skill_id) {return CALL_2 (int, __thiscall, 0x769460, npc, skill_id);}
RE: Исследование героев - RoseKavalier - 03.09.201718:39
Очень приятно, спасибо еще раз за помощь)
EDIT:
Modified to use with short_tip_text. Works great, thanks x2
Code:
int __stdcall show_text_hint(_Dlg_* this_, _EventMsg_* msg)
{
int r = this_->DefProc(msg);
char* text;
text = "";
if (msg->type == MT_MOUSEOVER) {
_DlgItem_* it = this_->FindItem(msg->x_abs, msg->y_abs);
if (it) {
if (it->short_tip_text != NULL)
text = it->short_tip_text;
}
statbar->SetText(text);
statbar->Draw();
statbar->RedrawScreen();
}
return r;
}
RE: Исследование героев - RoseKavalier - 07.09.201704:06
I read conversation at DF2 (don't have account there...) and your solution below.
Я читал разговор на DF2 (нет аккаунта там...) и ваше решение ниже. Graphic mode
It seems bug is related to different graphic mode,
32-bit GDI ok
True not ok
By any chance, could there be updated versions of dialog files?
Случайно, может быть обновленных версий диалоговые файлы?
If not, is there a way to make Set_DlgStdBackground() more... dynamic and less "one-size fits all". Seems to increment in +64
Если нет, есть ли способ, чтобы сделать Set_DlgStdBackground() в более... динамичным и менее "одну гребенку". Кажется, прирост в +64
(07.09.2017 04:06)RoseKavalier Wrote: By any chance, could there be updated versions of dialog files?
Случайно, может быть обновленных версий диалоговые файлы?
If not, is there a way to make Set_DlgStdBackground() more... dynamic and less "one-size fits all". Seems to increment in +64
Если нет, есть ли способ, чтобы сделать Set_DlgStdBackground() в более... динамичным и менее "одну гребенку". Кажется, прирост в +64
Обновленных версий нет.
Да, там проиходит увеличение дилогового окна на +64.
Если хотите сделать более динамичным, то вам необходимо исследовать функцию 0x48FA80 и перед показом диалога изменять все "64" на нужное увеличение размера, а потом возвращать этот параметр (=64).
Я бы сделал так.
RE: Исследование героев - RoseKavalier - 08.09.201704:00
Отличный ответ, спасибо!
EDIT: good news ---
you can place any custom *.pcx, *.def, *.bmp inside your plugin folder and it can be used directly.
вы можете разместить любой заказ, *.pcx, *.def, *.bmp ..., внутри папки плагинов и его можно использовать напрямую.
EDIT2: after some thinking... started making a function for dynamic background.
Lacks color but maybe that can be fixed...
после некоторых размышлений, я начал делать функцию для динамического фона.
It works will all graphic modes as far as I could tell.
Code:
int create_standard_background(_Dlg_* dlg, int status_bar)
{
//dlg->AddItem(_DlgStaticPcx8_::Create(0, 0, min(dlg->width,256), min(dlg->height,256), 0, "DiBoxBck.pcx"));
int current_x, remaining_x, current_y, remaining_y, horizontal_row;
if (remaining_x < 64 || remaining_y < 64)
return 0;
while (TRUE) {
while (TRUE) { // do horizontal pass first
if (remaining_x > 0) {
dlg->AddItem(_DlgStaticPcx8_::Create(current_x, horizontal_row * 256, min(remaining_x, 256), min(remaining_y, 256), 0, "DiBoxBck.pcx"));
current_x = current_x + 256;
remaining_x = remaining_x - 256;
}
else break;
}
current_x = 0; // reset x position to 0
remaining_x = dlg->width; // reset length of horizontal line
remaining_y = remaining_y - 256; // update remaining y since we're done with horizontal pass
horizontal_row = horizontal_row + 1; // we might be working on a new row soon if condition below is met
if (remaining_y <= 0)
break; // no more rows to add
}
int top_left = 0;
int top_right = 1;
int bottom_left = 2;
int bottom_right = 3;
int left_middle = 4;
int right_middle = 5;
int top_middle = 6;
int bottom_middle = 7;
(08.09.2017 04:00)RoseKavalier Wrote: EDIT2: after some thinking... started making a function for dynamic background.
Lacks color but maybe that can be fixed...
после некоторых размышлений, я начал делать функцию для динамического фона.
It works will all graphic modes as far as I could tell.
Wow nice!!
Add a repainted dialogue to the player's color. Like this
Code:
// add color this player
CALL_5 (int, __thiscall, 0x5FF400, dlg, 512, 13, 0, o_GameMgr->GetMeID());
if (remaining_x < 42 || remaining_y < 42)
return 0;
while (TRUE) {
while (TRUE) { // do horizontal pass first
if (remaining_x > 0) {
dlg->AddItem(_DlgStaticPcx8_::Create(current_x, horizontal_row * 256, min(remaining_x, 256), min(remaining_y, 256), 0, "DlgBluBk.bmp"));
current_x += 256;
remaining_x -= 256;
}
else break;
}
current_x = 0; // reset x position to 0
remaining_x = dlg->width; // reset length of horizontal line
remaining_y = remaining_y - 256; // update remaining y since we're done with horizontal pass
horizontal_row = horizontal_row + 1; // we might be working on a new row soon if condition below is met
if (remaining_y <= 0)
break; // no more rows to add
}
int top_left = 0;
int top_right = 1;
int bottom_left = 2;
int bottom_right = 3;
int left_middle = 4;
int right_middle = 5;
int top_middle = 6;
int bottom_middle = 7;
RE: Исследование героев - RoseKavalier - 18.09.201705:05
Small modification for create_standard_background(...) to prevent border appearance in status bar... actually would be slightly more efficient starting from (dlg->height - 64) and working back but this works fine)
Небольшая модификация для create_standard_background(...) для предотвращения появления границы в строке состояния...
Code:
// add vertical borders
current_y = 0;
remaining_y = dlg->height;
while (remaining_y >= 64) {
if (remaining_y - 64 <= 37)
current_y = dlg->height - 64 - 37; // hide a bit for status bar
dlg->AddItem(_DlgStaticDef_::Create(0, current_y, 0, "dialgbox.def", left_middle, 0, 0));
dlg->AddItem(_DlgStaticDef_::Create(dlg->width - 64, current_y, 0, "dialgbox.def", right_middle, 0, 0));
current_y += 64;
remaining_y -= 64;
}
~~~~~
Are there structures available for Quest Guards / Seer Huts? Only thing I could find is QU receiver from ERA but no structure... I could probably map these myself but if someone has and is willing to share, would be quite helpful!
Имеющиеся конструкции для охранников квеста / хижины Провидца? Единственное, что я мог найти, это QU приемник от эпохи, но не структура... Я мог бы сопоставить его сам, но если кто-то имеет и готов поделиться, это было бы очень полезно!
e.g.
struct + 0x3C = deadline / крайний срок
RE: Исследование героев - gamecreator - 18.09.201720:55
(18.09.2017 05:05)RoseKavalier Wrote: Are there structures available for Quest Guards / Seer Huts? Only thing I could find is QU receiver from ERA but no structure... I could probably map these myself but if someone has and is willing to share, would be quite helpful!
Link updated. It has the sources you need.
RE: Исследование героев - RoseKavalier - 19.09.201705:14
Wonderful, much appreciated. What a great community!
RE: Исследование героев - RoseKavalier - 26.09.201709:02
Hello... another question I can't seem to solve.
Привет ... другой вопрос, который я не могу решить.
// _DlgTextEdit_* Create(int x, int y, int width, int height, int max_len, char* text, char* font_name, _dword_ text_color, _dword_ text_align, char* bkground_pcx8_name, int id, _bool_ has_border, int border_width, int border_height)
Is there an easy way to restrict which characters can be input in _DlgTextEdit_?
e.g. digits only
Есть ли простой способ ограничить, какие символы могут быть введены в _DlgTextEdit_?
например только цифры
RE: Исследование героев - Valery - 26.09.201711:08
Is there some restriction from HD for that? Because I can't anymore input any digits in that box and I can't find any tweak about in HD.
@Edit: I found, HD requires ctrl hold to change digits.
(26.09.2017 09:02)RoseKavalier Wrote: Hello... another question I can't seem to solve.
Is there an easy way to restrict which characters can be input in _DlgTextEdit_?
I do not know how to do it yet. But I'll figure it out.
RE: Исследование героев - RoseKavalier - 27.09.201708:35
@Valery
You don't need to press Control, just click in the area and you can type numbers. This is not a HD feature, it is available with regular HoMM3 - or at the very least it worked on my 4.0 copy without HDmod.
@igrik
Thanks)
I looked at function that does for creatures but I got lost.
0x5BB000 (process command)
0x5FF3A0 (load correct text to 0x697428)
Alternatively, I thought of reading text from edit and removing unwanted characters - then load back text without unwanted characters to edit.
Спасибо)
Я смотрел на функцию, которая делает для существ, но я потерялся.
0x5BB000 (команда процесса)
0x5FF3A0 (загрузить правильный текст в 0x697428)
В качестве альтернативы, я думал о чтении текста из редактирования и удалении нежелательных символов, а затем загружать текст без ненужных символов для редактирования.
Code:
proc:
(print to buffer) ((_DlgTextEdit_*)dlg->GetItem(edit_id))->text;
(remove non-digits from buffer);
((_DlgTextEdit_*)dlg->GetItem(edit_id))->text = buffer;
I have not had time to try and code it and test so no idea if it could/would work.
RE: Исследование героев - Valery - 27.09.201715:50
Nope, typing directly digits has no effect, need to hold control key in HD mod. Without HD is ok.
RE: Исследование героев - RoseKavalier - 29.09.201722:28
(27.09.2017 15:50)Valery Wrote: Nope, typing directly digits has no effect, need to hold control key in HD mod. Without HD is ok.
I tried on 4.208, few 5.0s and control key is not needed?
Anyhow, not really important.
@igrik
I tried my idea from previous post... it kind of works. It's not perfect but in the end only digits remain.
Я попробовал то, что написал в предыдущем посте... Это работает. Это не идеально, но в конце концов только цифры.
Code:
int __stdcall edit_text_proc(_Dlg_* dlg, _EventMsg_* msg)
{
int r = dlg->DefProc(msg);
if (msg->type == MT_KEYDOWN || msg->type == MT_KEYUP || msg->type == MT_MOUSEBUTTON) { // not absolutely necessary, less cpu intensive
_DlgTextEdit_ *edit = (_DlgTextEdit_*)(dlg->GetItem(55)); // id of _DlgTextEdit_
char edit_text[25]; // _DlgTextEdit_ max_len
sprintf(edit_text, edit->text); // copy _DlgTextEdit_ text
keep_digits(edit_text); // keep only '0123456789' in string (with !is_digit())
if (edit_text[0] == 0) { // strlen == 0
edit_text[0] = '0'; // put '0' as default
edit_text[1] = 0; // terminate string
}
sprintf(edit->text, edit_text); // replace _DlgTextEdit_ text
dlg->Redraw(); // redraw
}
return r;
}
EDIT:
Got it working nice and fine
Add this also when creating. Noticed it was happening with creature dialog.
насчет загрузки и отрисовки полноцветных изображений.
и проблемы c этим в 32-bit True режимах ХД.
Почему не использовать оригинальный геройский _Pcx24_ ???
А если уж так надо получить именно _Pcx16_ (_Pcx32_), то можно воспользоваться оригинальной геройской функцией
рисующей _Pcx24_ на _Pcx16_ (_Pcx32_)
при этом не надо запариваться какая там битность и что там внутри _Pcx16_ (_Pcx32_) при каком режиме.
Конструктор новой _Pcx24_: 44EA20
- этот конструктор заполняет буфер из указанного источника, поэтому лучше написать свой конструктор пустой _Pcx24_
(сканлайн = ширина * 3, размер буфера = сканлайн * высота. пиксель в формате RGB888)
Конструктор новой _Pcx16_: 0x44DD20
Функция рисующая _Pcx24_ на _Pcx16_: 0x44ECA0
Именно так, через загрузку _Pcx24_ и его отрисовку на _Pcx16_
загружаются в менеджере ресурсов полноцветные pcx в оригинале.
Все мы прекрасно знаем, что описания Джедита и Нагаша в Воге всегда были на английском языке.
На самом деле, русский язык для описания специальностей тоже предусмотрен. В коде WOG'a даже есть переменная, отвечающая за русскую или английскую локализацию.
Code:
// тип игры 0-английская, 1-русская
int WoGType=0; // для ERA 0x80321C
0x703F28 void FileLoader(void) - это функция, которая инициализирует некоторые воговские параметры и заодно устанавливает английский или русский язык в переменную WoGType.
Вот выдержка кода, отвечающая за установку типа локализации:
Code:
if(LoadTXT("ZMESS00.TXT",&Strings)) Exit(); // не может загрузить TXT
// выносим внутренние сообщения в файл наружу
TxtOutOfExe();
// тип локализации
switch(ITxt(0,0,&Strings)[0]){ // считываем первый символ ZMESS00.TXT
case 'R': WoGType=1; break; // русский язык
default : WoGType=0; // иначе английский язык
}
Суммарно русских строк в коде немного: менее десяти наберется. В том числе и описания специализаций героев Джедита и Нагаша
Так вот, видимо при переводе на русский язык о данной особенности не знали. А всё что нужно было сделать для инициализации русских строк и описания специальностей, это в файле "ZMESS00.TXT" первый символ в моде "WoG Rus" изменить с E на R
ENG Wrote:E All New Messages are to be placed below.
RUS Wrote:R All New Messages are to be placed below.
Berserker'у в ЛС продублируй, чтоб не забылось до подготовки следующего русификатора.
RE: База для IDA и исходники последней Славиной версии ВоГа - feanor - 23.11.201820:07
Как вытащить гильдии 4- и 5-ого уровней для городов, где они заблокированы изначально:
Для вытаскивания ГМ4-5 вообще никаких особенных хитростей не надо, но делать это реально удобнее плагинами: слишком много всего происходит до старта ERM.
1. Нам надо сделать ГМ4-5 как строение на экране.
Для этого надо добавить его в таблицу приоритетов зданий; задать ему координаты, имя дефа, имя маски. Это делается в плагине, который towns. У нас - в конфиге, который я когда-нибудь обязательно преобразую в геройскую текстовую таблицу, конфиг в моде, прикладывать поленился, впрочем, там и так понятно.
2. Надо сделать ГМ4-5 как отстраиваемое строение.
Для этого нужно тем или иным способом задать ему требования отстройки. Я делал это вот в этой замечательной таблице, которая Dependencies. Её правка работает _только_ до реального старта игры, ерм - поздно, по-моему, даже OnAfterWoG поздно. Если надо править после старта, то либо ERM (какой-то из ресиверов в СА, уже не помню, CA:B вроде), либо надо найти структуру, в которую эти списки преобразуются. Там битовое поле, ищется несложно, но зачем, если есть такой замечательный гибрид между человеко- и машино- читаемым видом. Сразу говорю, копировать из приведенного кода не надо, там все деревья тсвшные. Лучше из экзешника.
Не помню, надо ли править текстовики для цен и описаний. Наверное, надо.
2.5. Надо сделать ГМ отстраиваемым в таунхолле.
Это, соответственно, одна из трех строк.
Code:
*(unsigned short*)4591590 = 37008; //cstl skip
*(char*)0x460FAA = 0x40; //barb id
*(char*)0x460FAE = 0x40; //wtch id
замок, барб, фортресс, соответственно.
Да, это разные методы, в одном патчится условный переход, в другом правится индекс. Не помню.
3. Надо додать заклинаний в ГМ.
А вот это делается чисто текстовиками. В sptraits или как там его прописана нулевая вероятность выпадения спеллов соответствующего уровня у недомагических замков: если додать какую надо - будут прекрасно генерироваться.
4. ИИ править не надо, он ГМ строить будет и так.
5. Редактор карт - надо, забыл приложить быстрофикс. https://pastebin.com/ctahgjTh
RE: Карта-мод STALKER для ERA 2.7.7 - feanor - 26.03.201916:41
Указатель на таблицу заклинаний лежит по 0х687FA8, формат записи -
Code:
struct _Spell_{ // size:88h
int FRposNOzerENneg; // +0 -1=enemy, 0=square/global/area, 1=friend
char *SoundFileName; // +4
int DefIndex; // +8 used to get DefName
int Flags; // +C
//0x00000001 - BF spell
//0x00000002 - MAP spell
//0x00000004 - Has a time scale (3 rounds or so)
//0x00000008 - Creature Spell
//0x00000010 - target - single stack
//0x00000020 - target - single shooting stack (???)
//0x00000040 - has a mass version at expert level
//0x00000080 - target - any location
//0x00000100 -
//0x00000200 -
//0x00000400 - Mind spell
//0x00000800 - friendly and has mass version
//0x00001000 - cannot be cast on SIEGE_WEAPON
//0x00002000 - Spell from Artifact
//0x00004000 -
//0x00008000 - AI
//0x00010000 - AI area effect
//0x00020000 - AI
//0x00040000 - AI
//0x00080000 - AI number/ownership of stacks may be changed
//0x00100000 - AI
char *Name; // +10h
char *AbbrName; // +14h
int Level; // +18h
int SchoolBits; // +1Ch Air=1,Fire=2,Water=4,Earth=8
int Cost[4]; // +20h cost mana per skill level
int Eff_Power; // +30h
int Effect[4]; // +34h effect per skill level
int Chance2GetVar[9];// +44h chance per class
int AIValue[4]; // +68h
char *Descript[4]; // +78h
};
RE: Ваши вопросы по ERM-скриптам - XEPOMAHT - 13.05.201900:58
Quote:можно ли выдернуть готовый скрипт с игры на артефакт "топор свирепости лорда варваров". Если можно, то как это сделать?
1. В функции BuildUpNewComboArts:
Code:
int Arts[10]={10,16,22,28};
BuildUpCombo(158,12,4,Arts);
Так. Как я понимаю - для некоторых - о давно наболевшем.
Отключение ТЮРЕМ (скачать)
Файл класть в папку "EraPlugins\AfterWoG" любого активного мода.
Вообще, наверное, нужно включить в официальную эру эту заплатку в отключенном состоянии. ИМХО
Это bin файл, позволяющий отключать генерацию тюрем на случайных картах. Одно уточнение: я оставил генерацию тюрем только с героями 1 уровня. Тюрьмы с героями 5, 15, 30 уровней вырезаны.
Еще раз: данная фича работает только для случайных карт, поэтому за авторские карты можно не беспокоиться.
Code:
// вырезаем генерацию тюрем
JMP отсюда 0x53A317 (5481239) тюрьмы все
... или ...
JMP отсюда 0x53A363 (5481315) тюрьмы с опытом >= 5000
... и ...
JMP сюда 0x53A48E (5481614) создание объекта с №63
ИТОГО КОД ЗАПЛАТКИ: 0053A363 E926010000 (0x53A363 JMP 0053A48E)
Решение проблемы отображения некоторых строк (в русской локализации) в диалоге экспы монстров.
Суть в подмене типа копирования символов со знакового на беззнаковое ( MOVSX -> MOVZX )
На сколько я знаю, MoP уже давно решил эту проблему, но как он это сделал я нигде не встречал.
RE: Исследование героев - Berserker - 02.07.201912:36
igrik, отличная заплатка, спасибо!
RE: Исследование героев - XEPOMAHT - 02.07.201913:34
(02.07.2019 11:51)igrik Wrote: MoP уже давно решил эту проблему, но как он это сделал я нигде не встречал.
Если интересно, то вот код из исходников:
Code:
; настраиваем тексты и подсказки способностей:
xor ebx, ebx
.repeat
mov eax, [ebx*4+840E40h]
.if eax
ChangeDlgItem esi, addr ebx + 1100, 3, eax
fn Настройка_подсказки_к_элементу_игрового_диалога, esi, addr ebx + 1100, dword [ebx*4+85D308h]
mov edi, ebx
imul edi, 100h
fn Настройка_подсказки_к_элементу_игрового_диалога, esi, addr ebx + 1300, addr edi + 845B00h
add edi, 85DB48h
mov dword [ebp-8], 0
.repeat
imul eax, ebx, 11
add eax, [ebp-8]
add eax, 1116
xchg byte [edi+8], bh; обнуляем конец строки
ChangeDlgItem esi, eax, 3, edi
xchg byte [edi+8], bh; возвращаем исходный символ
add edi, 8
inc dword [ebp-8]
.until signed dword [ebp-8] > 10
.endif
inc ebx
.until signed ebx > 15
Соответственно, сам воговский код этого дела в MoP заглушен и, скорее всего, затёрт.
RE: Исследование героев - daemon_n - 18.07.201904:59
Не знаю, как часто поднималась данная тема, потому спрошу с опаской:
были ли попытки научить ИИ пользоваться рюкзаком? А то все эти попытки его усилить скриптами упростились, научись он просто грамотно подбирать арты к бою и на ночь.
RE: Исследование героев - XEPOMAHT - 18.07.201911:20
(18.07.2019 04:59)daemon_n Wrote: научись он просто грамотно подбирать арты к бою и на ночь.
Возьми да сделай скрипт, переодевающий куклу героев ИИ перед боем и на ночь. Самое сложное там - решить какие артефакты должен одевать ИИ, а какие снимать (т.е. для каждого артефакта нужно будет как-то высчитывать AI value, по которому они все будут приоритетны для ИИ в той или иной степени, но такой готовой таблицы для Третьих Героев никто никогда не делал, хотя сделать её может любой опытный игрок - желания нет ни у кого, увы ).
RE: Исследование героев - daemon_n - 18.07.201912:57
XEPOMAHT, таблицу, мб, подумаю на досуге, если опыт позволит)
Однако вопрос именно в моментальном переодевании, чтобы ии, получив книгу земли, смог сразу использовать и спастись либо напасть.
RE: Исследование героев - XEPOMAHT - 18.07.201915:04
(18.07.2019 12:57)daemon_n Wrote: Однако вопрос именно в моментальном переодевании, чтобы ии, получив книгу земли, смог сразу использовать и спастись либо напасть.
В триггере пост-посещения артефакта проверяешь ИИ-чность, если ИИ, то ищешь артефакт в сумке, если артефакт найден в сумке, то читаешь номер слота из структуры артефакта и AI value артефакта и проверяешь в слотах куклы героя те же AI value, а затем сравниваешь их. Если AI value подобранного на карте артефакта больше уже одетого, то меняешь их местами.
Перед битвой так же можно сравнивать всю куклу героя с рюкзаком на AI value, т.к. артефакты у героев могут появляться в любой момент времени и это затратно отслеживать (т.к. особые функции при этом не нужны, достаточно просто изменить байт в структуре героя).
Слишком много факторов учитывать надо. К примеру, Сферу Земли когда ИИ надевать? Когда у него есть полезные заклинания этой школы. Когда они полезнее заклинаний других школ. Когда колдовство не запрещено полностью (Сфера Запрещения) или частично (Проклятая Земля), но не запрещается колдовство наиболее полезных заклов. Когда нужные заклинания изучены. Когда есть книга заклинаний. Как прокачана мудрость и сила магии. Есть ли свободный слот. Каковы свойства заклинаний. Нет ли надетого артефакта, который нивелирует свойства Сферы. Иммунитеты существ - своих и чужих. Наконец, не надет ли более полезный артефакт или дублирующий свойства Сферы. И еще невесть какие факторы, о которых вспомнишь только в игре.
И это условия полезности лишь для одного артефакта. Какая ещё таблица AI value, когда всё так ситуативно?
RE: Исследование героев - daemon_n - 19.07.201915:40
MOP, вот поэтому он будет среди последних)
RE: Исследование героев - XEPOMAHT - 19.07.201916:16
(19.07.2019 15:25)MOP Wrote: Какая ещё таблица AI value, когда всё так ситуативно?
С точки зрения заядлого игрока, знающего все вышеперечисленные особенности - да, использование AI value не приведёт ИИ до уровня эксперта по игре. Тогда для и монстров давайте тоже перестанем использовать AI value по той же причине ситуативности (вроде в игре работает норм, даже в MoP с почти удвоенным их количеством).
Например как играю я: поднимаю с карты ту же Сферу Земли, помещаю на куклу героя взамен какого-нибудь барахла и играю дальше, не думая ни о каких-то факторах (на Героях мозг обычно должен отдохнуть, это развлечение). Конечно, можно сказать, что хардкорщиков-задротов сейчас наверное большинство (от того и рулят моды, не содержащие коренных изменений игрового процесса), но я бы всё всё равно предложил для ИИ схему по-проще (например, в MoP уже больше 400 артефактов, сложную схему для ИИ сделать жизни не хватит).
Ну если упрощённо, то такая система AI value уже есть в игре - градация по классам артефактов. И она худо-бедно работает - потому что и создана для ИИ. Вот только лучше бы вместо классов в качестве value была выбрана стоимость в золоте - иными словами, не четыре ступени ценности, а неограниченный ценностный диапазон.
RE: Исследование героев - daemon_n - 22.07.201914:58
(19.07.2019 19:30)MOP Wrote: Ну если упрощённо, то такая система AI value уже есть в игре - градация по классам артефактов. И она худо-бедно работает - потому что и создана для ИИ. Вот только лучше бы вместо классов в качестве value была выбрана стоимость в золоте - иными словами, не четыре ступени ценности, а неограниченный ценностный диапазон.
Но это только если Артефакт подбирается с земли.
RE: Ваши вопросы по ERM-скриптам - igrik - 17.12.201914:44
(17.12.2019 12:42)Algor Wrote: Как вариант, конечно, раскопать какую-нить функцию типа "мощь армии королевства" из обзора королевства, но не уверен, что там будет именно то, что нужно.
Отдельно взятой такой функции нет. Есть только участок кода внутри функции, но его никак нельзя использовать через ERM
вопрос только один - что за адрес используется нестандартный 6933756 ?
я почему-то ожидал здесь адрес основного игрового менеджера (6919480)... есть у кого объяснение?
RE: Вопросы по моддингу - Berserker - 21.07.202000:38
418B70 void __thiscall MapItem_Start_Loop_Sound(AdvMgr *advMgr, int x, int y, int z, int distance, int allowCaching) { AdvMgr *self; // esi signed int determinedLoopSoundId; // edi AdvMgrConsts cachedLoopSoundIndex; // eax HeroClosestLoopSound *cachedLoopSound; // ecx int farthestDistance; // edx signed int newLoopSoundIndex; // ebx AdvMgrConsts i; // eax int prevLoopSoundId; // eax int *soundDistanceToCheck; // [esp+14h] [ebp+8h]
self = advMgr; if ( x >= 0 && y >= 0 && z >= 0 && x < MapSizeX && y < MapSizeY ) { determinedLoopSoundId = AdvMgr_MapItem_Determine_Sound(x, y, z); if ( determinedLoopSoundId != -1 ) { cachedLoopSoundIndex = 0; cachedLoopSound = self->cachedLoopSounds; while ( cachedLoopSound->loopSoundId != determinedLoopSoundId ) { ++cachedLoopSoundIndex; ++cachedLoopSound; if ( cachedLoopSoundIndex >= MAX_CACHED_LOOP_SOUNDS )// Such looped sound not found in cache { if ( allowCaching != 1 ) { farthestDistance = distance; newLoopSoundIndex = -1; i = 0; soundDistanceToCheck = &self->cachedLoopSounds[0].distance; do { if ( *soundDistanceToCheck > farthestDistance ) { farthestDistance = *soundDistanceToCheck; newLoopSoundIndex = i; } ++i; soundDistanceToCheck += 2; } while ( i < MAX_CACHED_LOOP_SOUNDS ); if ( newLoopSoundIndex != -1 ) { prevLoopSoundId = self->cachedLoopSounds[newLoopSoundIndex].loopSoundId; if ( prevLoopSoundId != -1 ) StopBINKVideo_AIL(o_SoundMgr, *(self->cachedLoopSoundWavs[prevLoopSoundId] + 7)); self->cachedLoopSounds[newLoopSoundIndex].loopSoundId = determinedLoopSoundId; self->cachedLoopSounds[newLoopSoundIndex].distance = distance; if ( determinedLoopSoundId > -1 && determinedLoopSoundId < 70 && !self->cachedLoopSoundWavs[determinedLoopSoundId] ) { Dlg_KingdomOverviewPrepare(self, 4); self->cachedLoopSoundWavs[determinedLoopSoundId] = LoadWAV2((&off_0065F794)[determinedLoopSoundId]); } *(self->cachedLoopSoundWavs[determinedLoopSoundId] + 11) = dword_0063A64C[distance]; *(self->cachedLoopSoundWavs[determinedLoopSoundId] + 12) = 0; *(self->cachedLoopSoundWavs[determinedLoopSoundId] + 10) = 3; NotifyPlayerWithBINKandSound(o_SoundMgr, self->cachedLoopSoundWavs[determinedLoopSoundId]); self->cachedLoopsSoundsMask ^= 1 << self->cachedLoopSounds[newLoopSoundIndex].loopSoundId; } } return; } } if ( self->cachedLoopSounds[cachedLoopSoundIndex].distance > distance ) { self->cachedLoopSounds[cachedLoopSoundIndex].distance = distance; self->cachedLoopsSoundsMask |= 1 << self->cachedLoopSounds[cachedLoopSoundIndex].loopSoundId; } } } }
Список идентификаторов игровых диалогов (получены в ERA2)
Code:
4205280 - карта приключений (КП)
5755920 - окно сохранения
5884864 - книга заклинаний
4789216 - режим "дверь измерений"
4790240 - режим "затопить корабль"
6039360 - окно выбор города (без HD; для закла ГП или через врата Инферно)
5217680 - окно повышения уровня героя
5378592 - окно обзора королевства
5976864 - окно настроек КП
4216352 - окно действий на КП
6275296 - обзор мира (включая заклы Просмотр земли/воздуха)
5425744 - карта-загадка
6068832 - гильдия воров
5675664 - инфо по сценарию
6100112 - окно гарнизона
6099296 - окно оставления существ (включая шахты)
5570288 - жилища существ/фабрика машин
5637600 - жертвенный алтарь
6228784 - университет
6105344 - верфь
6183568 - чёрный рынок/торговец артефактами (покупка)
6167072 - рынок (обмен ресурсами)
6175376 - рынок (передача ресурсов игроку)
6241984 - окно статистики монстра/отряда
5144224 - форт на холме
6201472 - гильдия наёмников
6126720 - таверна
** (одноимённые диалоги вне КП имеют те же ID и ниже не упоминаются)
4662240 - окно битвы
4649504 - окно настроек в битве
4658576 - статистика боя
5117840 - окно героя
4304960 - окно командира (с WND)
5432976 - окно журнала (без плагина на новый диалог)
4304960 - окно журнала (с плагином на новый диалог)
6053040 - окно города
6087968 - гильдия магов
6081760 - зал совета
6119232 - инфо о постройке
6147920 - форт/замок
6102528 - кузница
5661104 - преобразователь скелетов
6193120 - торговец артефактами (продажа)
5957344 - окно встечи героев
4782512 - прочие диалоги (включая IF:M/IF:Q; и все новые от HD)
4304960 - WoG-диалоги (с WND: опыт существ, сфинкс, проклятья, IF:G/IF:B и пр.)
- - - WoG-диалоги без WND не пропускают (OnKeyPressed), потому хз как их пощупать
RE: Исследование героев - daemon_n - 22.01.202103:25
Итак. Снова сутки за героями, но исследовал вот что:
Вопросы, что я себе задал, мол, как поймать "фазу ожидания" существа(Click to View)
После
Это не баг? Так и должно быть?
А вот и ответ, который пришёл мне в голову - прошу подтвердить:
Есть флаг ожидания у существа
!!BM0:F?i; записать значения флагов первого стека в переменную i
!!VRi:&33554432; проверить на ожидание
!!IF&i>0:M^Стек ждет лучшего момента для действия^;
Но он возвращает "истину", пока нет всеобщей фазы ожидания, которая определяется через:
!!UN:C6919200/4/?y10;
!!VRy11:Sy10 +81380;
!!UN:Cy11/1/?y8;
То есть, чтобы узнать, в ожидании отряд или нет, когда настала всеобщая фаза ожидания, надо сделать проверку на саму фазу, сделать проверку на флаг "завершённое действие" и на флаг "защиты". То есть флаг &33554432 проверять надо всегда с нюансами
RE: Исследование героев - Berserker - 22.01.202115:23
Quote:!!UN:C6919200/4/?y10;
!!VRy11:Sy10 +81380;
!!UN:Cy11/1/?y8; проверка на фазу ожидание
Спасибо за исследование! В Эре 3.3 можно будет написать так:
!!UN:C(COMBAT_MANAGER)/(UNC_INT)/?(combatMan:y) C(combatMan)/(STRUCT_COMBATMAN_IS_WAITING_PHASE)/(UNC_UINT8)/?(isWaitingPhase:y);
RE: Ваши вопросы по ERM-скриптам - RoseKavalier - 12.02.202122:39
(10.02.2021 19:34)XEPOMAHT Wrote: Теперь знаю что такое SPLICE_, спасибо что объяснили.
Show, don't tell)
LoHook - register access (HookContext)
Hihook - arguments access, no register access
RE: Вопросы по моддингу - Raistlin - 13.02.202118:40
Друзья, подскажите пожалуйста, где можно узнать в каком "статусе" находятся стены? Изначально у них статус 2 (возможно, кстати, не у всех), если наполовину поломаны - 1, если можно пройти - 0.
Неактуально, я все нашел сам. Оставлю информацию здесь, чтобы другие могли найти тоже.
Смещения в менеджере битвы:
Code:
INT32 fortWallsHp[18]; // +13F60 (hit points of town walls)
INT32 fortWallsAlive[18];// +13FA8
RE: Вопросы по моддингу - Raistlin - 21.02.202101:32
Нашел я в исходниках вога вот такой вот интересный список патчей, как думаете, имеет смысл попытаться на его основе добавить героев?
RE: Вопросы по моддингу - XEPOMAHT - 21.02.202119:00
(21.02.2021 01:32)Raistlin Wrote: Нашел я в исходниках вога вот такой вот интересный список патчей, как думаете, имеет смысл попытаться на его основе добавить героев?
Попытайся. Он под чистый SoD без модов, если что.
RE: Вопросы по моддингу - Raistlin - 21.02.202120:24
XEPOMAHT, хорошо )
RE: Вопросы по моддингу - feanor - 21.02.202122:36
Насчет героев вообще была умеренно всратая идея: у нас же в игре все равно не может быть больше 8*8 + 2*8 + 48 героев (8 в поле каждой фракции, 48 в гарнизонах замков, 2*8 в тавернах)
Так вот, зачем нам их добавлять актуально, убиваясь о все возможные битмапы (в хоте перенос между кампаниями фиксили чуть ли не до 1.4), допструктуры вога и все такое, если можно сделать пул и менять их динамически?
RE: Вопросы по моддингу - XEPOMAHT - 22.02.202100:15
(21.02.2021 22:36)feanor Wrote: Так вот, зачем нам их добавлять актуально, убиваясь о все возможные битмапы (в хоте перенос между кампаниями фиксили чуть ли не до 1.4), допструктуры вога и все такое, если можно сделать пул и менять их динамически?
Это уже кастыли, затруднительно сказать, какие при этом повылазят глюки. Проще расширением существующих структур (что уже было сделано ещё в WoG 3.59 и портировано на все текущие троешные геройские платформы) и полной адаптацией кривостей воговского кода с воговскими скриптами (что давно пора сделать, а не заниматься тем, что уже кем-то сделано).
RE: Вопросы по моддингу - Дьякон - 26.06.202114:29
Сюда продублирую. Структуры сноса строений при постройках: 0x839AA8 - имеет два dworda на каждое строение. Адрес для ЭРЫ.
RE: Ваши вопросы по ERM-скриптам - Berserker - 09.07.202101:11
Щиты снайперов и иже с ним прочие wog-способности
Code:
static void _SetUpBeforeBattle2(void)
{
#include "templ.h"
int i,j,tp;
Byte *bm=(Byte *)SUBB_BatMan;
Byte *mon;
// _Hero_ *hp1=(_Hero_ *)*(Dword *)&bm[0x53CC];
// _Hero_ *hp2=(_Hero_ *)*(Dword *)&bm[0x53D0];
NMT_First=0; // Сброс для Санта Гремлина и других, кто иниц. после тактики
/////////// PlaceNPCAtBattleStart(bm);
// CrExpBon::PrepareBFExpStructure(bm);
// if(bm[0x13D68]==0){ // NO tactic phase
*(int *)&((Byte *)bm)[0x13D6C]=0; // clear the turn index
// }
for(i=0;i<(21*2);i++){
mon=&bm[0x54CC+0x548*i];
*(int *)&mon[0x288]=0; // not being hypnotized
*(int *)&mon[0xF4] =i/21; // initial side
// 3.58 Tower skip
if(i==20) continue; // 3.58
if(i==41) continue; // 3.58
mon=&bm[0x54CC+0x548*i];
// AdjustStackParams(/*bm,*/mon,0); // 3.58 Creature experience
CrExpBon::Apply(mon);
tp=*(int *)&mon[0x34];
if((tp>=174)&&(tp<=191)){
AddMagic2NPC(mon,bm);
}
if(tp==152){ // титан
SetMonMagic(mon,28,1000,3,0); // воздушный щит
}
if(tp==156){ // чудище
*(int *)&mon[0x454]=2;
}
if(tp==158){ // феникс
SetMonMagic(mon,0x1D,1000,1,0); // огненный щит
SetMonMagic(mon,55,1000,3,0); // палач
}
if(tp==195){ // Hell Steed (fire horse)
SetMonMagic(mon,0x1D,1000,1,0); // огненный щит
}
if((tp>=GODMONTSTRT)&&(tp<(GODMONTSTRT+GODMONTNUM))){ // бог
*(int *)&mon[0x454]=0; // не отвечает на атаку
}
if(tp==164){ // огненный голем
SetMonMagic(mon,31,1000,3,0); // защита от огня
}
if(tp==165){ // огненный голем
SetMonMagic(mon,33,1000,3,0); // защита от земли
}
if(tp==166){ // огненный голем
SetMonMagic(mon,30,1000,3,0); // защита от воздуха
}
if(tp==167){ // огненный голем
SetMonMagic(mon,32,1000,3,0); // защита от воды
}
if(tp==169){ // белый монах
SetMonMagic(mon,36,1000,3,0); // волшебное зеркало
}
if(tp==170){ // белый шутер
SetMonMagic(mon,28,1000,3,0); // воздушный щит
}
if(tp==171){ // красный шутер
SetMonMagic(mon,0x1D,1000,1,0); // огненный щит
}
if(tp==192){ // Centaur-Elf
SetMonMagic(mon,49,1000,3,0); // Mirth
}
for(j=0;j<100;j++){
if(MonsterOfWeek[j]==-1) break;
if(tp==MonsterOfWeek[j]){ // монстр недели
SetMonMagic(mon,48,1000,3,0); // воздушный щит
}
}
CrExpBon::ApplySpell(mon,bm);
// CrExpBon::ApplyMassSpell(mon);
if(tp==0x95){ // башня
_CastleSetup_ *cp;
cp=(_CastleSetup_ *)*(Dword *)&bm[0x53C8];
if(IsCastleSetup(cp)==1){ // замок
SetTowerBunus(cp,mon);
/*
int side=*(int *)&mon[0xF4]; // сторона
_Hero_ *htmp;
_Hero_ *hpo=(_Hero_ *)*(Dword *)&bm[0x53CC];
_Hero_ *hpe=(_Hero_ *)*(Dword *)&bm[0x53D0];
if(side!=0){ htmp=hpo; hpo=hpe; hpe=htmp; }
if((hpo!=0)&&(HeroHasArt(hpo,0x8E))){ // свой
// *(int *)&mon[0x4C]=99;
}
*/
}
}
Code:
static void _SetUpNewRound(void)
{
#include "templ.h"
int j;
Byte *sgp,*bmp=(Byte *)SUNR_BatMan;
Byte *mon=(Byte *)SUNR_Mon;
int tp=*(int *)&mon[0x34];
// Byte *bm=(Byte *)SUNR_BatMan;
// _Hero_ *hp1=(_Hero_ *)*(Dword *)&bm[0x53CC];
// _Hero_ *hp2=(_Hero_ *)*(Dword *)&bm[0x53D0];
if((tp>=174)&&(tp<=191)){
AddMagic2NPC(mon,bmp);
}
CrExpBon::Apply2(mon);
if(tp==152){ // титан
SetMonMagic(mon,28,1000,3,0); // воздушный щит
}
if(tp==156){ // чудище
*(int *)&mon[0x454]=2; // отвечает дважды
}
if(tp==158){ // феникс
SetMonMagic(mon,0x1D,1000,1,0); // огненный щит
SetMonMagic(mon,55,1000,3,0); // палач
}
if(tp==195){ // Hell Steed (fire horse)
SetMonMagic(mon,0x1D,1000,1,0); // огненный щит
}
for(j=0;j<100;j++){
if(MonsterOfWeek[j]==-1) break;
if(tp==MonsterOfWeek[j]){ // монстр недели
SetMonMagic(mon,48,1000,3,0); // воздушный щит
}
}
if((tp>=GODMONTSTRT)&&(tp<(GODMONTSTRT+GODMONTNUM))){ // бог
*(int *)&mon[0x454]=0; // не отвечает на атаку
}
if(tp==164){ // огненный голем
SetMonMagic(mon,31,1000,3,0); // защита от огня
}
if(tp==165){ // огненный голем
SetMonMagic(mon,33,1000,3,0); // защита от земли
}
if(tp==166){ // огненный голем
SetMonMagic(mon,30,1000,3,0); // защита от воздуха
}
if(tp==167){ // огненный голем
SetMonMagic(mon,32,1000,3,0); // защита от воды
}
if(tp==169){ // белый монах
SetMonMagic(mon,36,1000,3,0); // волшебное зеркало
}
if(tp==170){ // белый шутер
SetMonMagic(mon,28,1000,3,0); // воздушный щит
}
if(tp==171){ // красный шутер
SetMonMagic(mon,0x1D,1000,1,0); // огненный щит
}
if(tp==192){ // Centaur-Elf
SetMonMagic(mon,49,1000,3,0); // Mirth
}
CrExpBon::ApplySpell(mon,bmp);
for(j=0;j<SG_GuardsSet;j++){
if(SG_GuardsSetUp[j].own_stack!=-1){
sgp=&bmp[0x54CC+0x548*SG_GuardsSetUp[j].sg_stack];
if((*(int *)&sgp[0x4C])<=0){
sgp=&bmp[0x54CC+0x548*SG_GuardsSetUp[j].own_stack];
*(int *)&sgp[0xC4]=SG_GuardsSetUp[j].own_speed;
}
}
}
Двоичные патчи для BinMagic:
Отключить щиты у арктического и лавового снайперов в начале боя
75E99C 0000007F
75E9BC 0000007F
Отключить щиты у арктического и лавового снайперов в начале каждого раунда
760854 0000007F
760874 0000007F
Флаг 29 у отряда на поле боя говорит, что на отряде анимация жажды крови, а потому деф нужно отрисовывать с палитрой, смещённой к красному.
По смещению 1104 в структуре отряда лежит float (вещественное число) от 0 до 1.0, которое говорит, насколько нужно сдвинуть цвет каждого пикселя в цветовой модели HSV ближе к красному. 0 — ни на сколько, 0.8 — на 80%, 1.0 — полностью красный. Яркость и насыщенность тоже увеличиваются с увеличением значения поля. Если флаг установлен, то при отрисовке уже не проверяется флаг окаменения или клона. Потому при колдовстве жажды крови на клоне, клон временно рисуется без синих тонов.
Upd. Флаг 30 означает коррекцию насыщенности в модели HSV. Если поле в структуре отряда 0x450 (float, 4 байта) < 1.0 значит умножение (*0 - полностью в серый тонах, на 0.5 — потерять половину насыщенности). Если > 1.0, то новая насыщенность = 1 - ((1 - старая насыщенность) / значение_поля)).
Если стоит флаг 29, то флаг 30 не обрабатывается.
В оригинале во время анимации окаменения значения изменяются от 1.0 до 0.0 с шагом 0.1 (шаг 0.1 и в жажде крови)
Quote:Так, если в теле триггера !?MF1 считывать из памяти по адресу 42149568 значения (число, 4 байта), то мы сможем узнать какой именно тип физического повреждения наносится стеку.
Перечень данных для различных типов физ.повреждения:
Code:
4454752 Урон огненным шаром
4455011 Урон от стрельбы
4455746 Урон от смертельного облака
4456676 Урон от круговой атаки (включая атаку Церберами)
4458589 Урон от огненного щита
4460149 Урон от смертельного взгляда
4460621 Удар молнии
4461137 Урон от кислотной атаки
4462398 Урон от рукопашной
4462479 Урон дракона
4610404 Урон от стрелковых башен
4627096 Урон от рва
5902442 Урон от волны смерти
Странно, что здесь есть помимо всего прочего и урон от Волны смерти... исходя из этого есть предположение, что кто-то изначально в игре должен был ей атаковать, как монстро-абилкой.
RE: Era AI Edition 32bit - void_17 - 16.12.202118:31
Ребят, я тут выложил в своем треде базу HD Edition: http://wforum.heroes35.net/showthread.php?tid=6419
Там халявная дебажная инфа есть и можно восстановить код в тех местах, где загружается и обрабатывается новая графика HD Edition. Я скоро восстановлю RoE-вские типы и, впринципе, перед нами уже будет готовый код HD Edition. Можно написать плагин по этому коду, добавить перерисованных нейросетью файлов SoD или даже WoG и кинуть куда надо, чтобы плагин грузил. Как вам идея?
"Перенесено в корректную тему" @Администратор
RE: Стандартизированная база героев 3 - void_17 - 16.12.202118:40
Отличия оригинальных типов между RoE и HD Edition есть. Пока не могу сказать какие, но точно это связано с интерфейсом.
RE: Исследование героев - XEPOMAHT - 16.12.202121:05
(16.12.2021 17:40)void_17 Wrote: Например, army::TSampleID.
здесь видно константы прямо над названием перечисления. Значение константы лежит по 2 байта слева от нее.
Таким образом, получаем:
Пока как-то больше похоже на гадание на кофейной гуще. Например, army::TSampleID - функция-конструктор, инициализирующая структуру звуков отрядов на поле боя, имена - названия переменных (стековая память), которая потом копируется в структуру _ARMY_ (воговский стиль именования структур, т.к. к нему привыкли за 20 лет), открываем в исходниках WERD, и сразу находим:
Можно компилировать в ассемблере и применять в модах.
RE: Исследование героев - void_17 - 16.12.202121:24
Все развивается так быстро, что даже этот гайд устарел. RoseKavalier написал скрипты и сейчас пытается дампать всю эту информацию. AlexSpl обнаружил еще оригинальные названия параметров функций.
Как только RoseKavalier отправит мне дампы, я вручную все обработаю(по-другому к сожалению никае) по сути у нас будут готовы все игровые типы и enum-ы.
И да, я не совсем понял о каком конструкторе идет речь. Может дадите адрес? Дримкаст база и моя база больше соответствуют реальности и могут дать более точный ответ. А вообще, army::TSampleID это именно перечисление(enum). Не путайте с массивом из 8 char*-указателей, enum army::TSampleID это просто перечисление для удобства, не структура. По крайней мере так у NWC.
RE: Стандартизированная база героев 3 - XEPOMAHT - 16.12.202121:30
(16.12.2021 18:40)void_17 Wrote: Отличия оригинальных типов между RoE и HD Edition есть. Пока не могу сказать какие, но точно это связано с интерфейсом.
У дримкаста интерфейс тоже значительно перелопачен по сравнению с ПК. Куча новых юбисофтских функций, некоторые кстати перекочевали с дримкаста в порт 2015 года (что подтверждает гипотизу о том, что разорившийся 3DO не передал исходные коды после покупки, поэтому для HD-переиздания использовали то, что откопали в закромах самого Юбисофта, а именно, исходники RoE 0.99). Более-менее достоверно можно восстановить оригинальные имена игрового кода.
RE: Стандартизированная база героев 3 - void_17 - 16.12.202121:39
Я знаю об этом. Постоянно сижу в этой самой дримкаст базе, собственно мы этим и занимаемся, что переносим дебажную информацию из дримкаст в "дикий" SoD, некогда воговскую базу. Могу сказать лишь то, что в интерфейсе дримкаста из самих типов не особо поменялось по сравнению с ПК билдом RoE. Говорю просто из опыта работы с базой. Типы не меняются, меняются там лишь аргументы функций да всякие таблицы и прочее.
Кстати есть в дримкасте функции, которых нет в RoE ПК просто из ненадобности. Ну например для переноса камеры на поле боя, так как она не вмещается полностью.
RE: Era AI Edition 32bit - XEPOMAHT - 16.12.202121:50
(16.12.2021 18:31)void_17 Wrote: Я скоро восстановлю RoE-вские типы и, впринципе, перед нами уже будет готовый код HD Edition. Можно написать плагин по этому коду, добавить перерисованных нейросетью файлов SoD или даже WoG и кинуть куда надо, чтобы плагин грузил. Как вам идея?
Не имеет смысла. Дополнение Клинок Армагеддона всё равно сложно будет реализовать в HD-переиздании, т.к. там изменений вагон. SoD больше тянет на DLC, изменений там совсем немного (т.к. SoD запланирован не был, тут в дело вмешался издатель с первым намереньем заработать на игроках с минимальными затратами программисто-часов).
RE: Might and Magic. Heroes III — HD Edition - void_17 - 16.12.202121:55
Вы не поняли меня. Применяя код HD Edition, сделать плагин для SoD или даже WoG, чтобы работала графика как в HD Edition.
RE: Исследование героев - XEPOMAHT - 16.12.202122:15
(16.12.2021 21:24)void_17 Wrote: Все развивается так быстро, что даже этот гайд устарел. RoseKavalier написал скрипты и сейчас пытается дампать всю эту информацию. AlexSpl обнаружил еще оригинальные названия параметров функций.
Как только RoseKavalier отправит мне дампы, я вручную все обработаю(по-другому к сожалению никае) по сути у нас будут готовы все игровые типы и enum-ы.
Если это как-то поможет моддерам, то будет замечательно, а если так и останется "на бумаге", тогда смысл? Основная проблема - доступность простым смертным, если они ничего не поймут, тогда что есть, что нет - больше модов от этого не станет. Лично я от RoseKavalier ничего не использую, т.к. он делает слишком много вложений в структурах, что совершенно неудобно при их чтении и анализе, редко его комментарии в самих структурах полезны, т.к. программисткий жаргон мне понимать тяжело, ну а самое главное - я работаю с русифицированными структурами, т.к. английский совершенно не знаю.
До сих пор использую структуры Мастера, замиксованные с разными структурами из параллельных проектов. Самые понятные для меня - наработки по структурам из WoG 3.59, т.к. сделаны явно непрограммистами для непрограммистов.
(16.12.2021 21:24)void_17 Wrote: Может дадите адрес? Дримкаст база и моя база больше соответствуют реальности и могут дать более точный ответ. А вообще, army::TSampleID это именно перечисление(enum). Не путайте с массивом из 8 char*-указателей, enum army::TSampleID это просто перечисление для удобства, не структура. По крайней мере так у NWC.
У меня ваша база не открывается, ничего по ней сказать не могу, у меня дримкастный исполняемый файл был диассемблирован IDA 6, с чем потом я пытался работать, потом забросил. Что такое указатели и перечисления - не знаю. Программисткий жаргон не понимаю.
В самой игре это просто кусок памяти на 24h байта, адресующийся в виде dword-значений. Просто и понятно, без изысков.
RE: Might and Magic. Heroes III — HD Edition - XEPOMAHT - 16.12.202122:33
(16.12.2021 21:55)void_17 Wrote: Применяя код HD Edition, сделать плагин для SoD или даже WoG, чтобы работала графика как в HD Edition.
Это ещё дольше и сложнее, чем портирование всех дополнений на HD Edition, т.к. потребуется полностью заменить весь графический движок игры. Да и смысла так же в этом нет, т.к. затраты несоизмеримы с тем, что получится в итоге.
RE: Might and Magic. Heroes III — HD Edition - void_17 - 17.12.202107:38
(16.12.2021 22:33)XEPOMAHT Wrote:
(16.12.2021 21:55)void_17 Wrote: Применяя код HD Edition, сделать плагин для SoD или даже WoG, чтобы работала графика как в HD Edition.
Это ещё дольше и сложнее, чем портирование всех дополнений на HD Edition, т.к. потребуется полностью заменить весь графический движок игры. Да и смысла так же в этом нет, т.к. затраты несоизмеримы с тем, что получится в итоге.
Я изначально запостил это в теме, в которой ребята этим по-сути и занимались. Я таким образом хотел им подсказать, мне лично это не надо и неинтересно. Админ перенес пост зачем-то. И да, в HD Edition графика работает по принципу надстройки, т.е. там не очень-то и сложно. Главное алгоритмы понять.
Администратор (igrik): вернул сообщения в надлежащую тему
Я тоже не понимаю, зачем сообщения нужно было отсюда переносить.
RE: Исследование героев - void_17 - 17.12.202107:48
Quote:Если это как-то поможет моддерам, то будет замечательно
Понятное дело, что поможет. Разработчики игры оставили информацию о всех типах enum, битовым полям и даже параметрам функций де-факто в открытом доступе. Остается лишь это систематизировать и перед нами.. Рай для моддеров!
Quote:а если так и останется "на бумаге", тогда смысл?
Quote:Основная проблема - доступность простым смертным, если они ничего не поймут, тогда что есть, что нет - больше модов от этого не станет.
Этим самым "смертным" порой достаточно пару чисел поменять, они уже в шоке от того, что можно менять стартовые ресурсы сложности, им хватает этого вполне. Можно сделать гайд, как это делать. Вот я в вк пытаюсь. Для моддеров тем не менее это невероятно полезная информация, мы сейчас всю работу сделаем и пользуйтесь наздоровье. Моддинг удобнее гораздо станет, ведь вместо безликих sub_XXXXXX и прочего у нас 100% точная информация обо всем прямо от разработчиков игры.
Quote:Лично я от RoseKavalier ничего не использую, т.к. он делает слишком много вложений в структурах, что совершенно неудобно при их чтении и анализе, редко его комментарии в самих структурах полезны
А это здесь причем вообще? Ну я тоже не пользуюсь H3API, тоже она мне не нравится, ну не значит это, что нужно вообще человека бойкотировать. Он с нами в команде работает и приносит только пользу, дампая информацию. Мне остается ее лишь вручную обработать, т.к. скриптов для этого нет.
Quote:т.к. программисткий жаргон мне понимать тяжело, ну а самое главное - я работаю с русифицированными структурами, т.к. английский совершенно не знаю.
До сих пор использую структуры Мастера, замиксованные с разными структурами из параллельных проектов. Самые понятные для меня - наработки по структурам из WoG 3.59, т.к. сделаны явно непрограммистами для непрограммистов.
Я тоже ни разу не программист. Я буквально этой весной не знал как поставить хук и что такое структура и классы. Я вообще на инженера учусь. Мне ничего не мешало изучить по-тихоньку это дело, тем более для моих институтских проектов это мне помогает хорошо, поэтому лично для меня все героями не ограничивается.
Quote:У меня ваша база не открывается, ничего по ней сказать не могу, у меня дримкастный исполняемый файл был диассемблирован IDA 6, с чем потом я пытался работать, потом забросил. Что такое указатели и перечисления - не знаю. Программисткий жаргон не понимаю.
А IDA 7.6 у вас не работает? Тогда ничем не могу помочь, кроме как порекоммендовать виндовс обновить хотя бы до 7-ки.
RE: Исследование героев - XEPOMAHT - 17.12.202110:41
(17.12.2021 07:48)void_17 Wrote: Понятное дело, что поможет. Разработчики игры оставили информацию о всех типах enum, битовым полям и даже параметрам функций де-факто в открытом доступе. Остается лишь это систематизировать и перед нами.. Рай для моддеров!
Смотрел, там каша отладочной информации, у меня просто духу не хватило глубоко разбираться в ней. Моддинг считаю превыше.
(17.12.2021 07:48)void_17 Wrote: Этим самым "смертным" порой достаточно пару чисел поменять, они уже в шоке от того, что можно менять стартовые ресурсы сложности, им хватает этого вполне. Можно сделать гайд, как это делать. Вот я в вк пытаюсь. Для моддеров тем не менее это невероятно полезная информация, мы сейчас всю работу сделаем и пользуйтесь наздоровье. Моддинг удобнее гораздо станет, ведь вместо безликих sub_XXXXXX и прочего у нас 100% точная информация обо всем прямо от разработчиков игры.
Появится у тех, кто сможет открыть базу. Далеко не у всех есть IDA, для многих изменение данных в структурах с помощью UN:C - потолок, поэтому списки имён к функциям с адресами и сами структуры рекомендую всё же публиковать отдельно в текстовом виде, чтобы этими данными мог воспользоваться любой у кого установлен Блокнот на ПК.
(17.12.2021 07:48)void_17 Wrote: А это здесь причем вообще? Ну я тоже не пользуюсь H3API, тоже она мне не нравится, ну не значит это, что нужно вообще человека бойкотировать. Он с нами в команде работает и приносит только пользу, дампая информацию. Мне остается ее лишь вручную обработать, т.к. скриптов для этого нет.
Не бойкотирую, а только намекаю, что у Кавалериста слишком сложно описаны данные, нужно быть проще.
(17.12.2021 07:48)void_17 Wrote: А IDA 7.6 у вас не работает? Тогда ничем не могу помочь, кроме как порекоммендовать виндовс обновить хотя бы до 7-ки.
IDA 6.5 - максимальная версия для Windows 2003. У Windows 7 слишком высокие системные требования.
RE: Исследование героев - void_17 - 17.12.202112:29
Здесть есть:
! Оригинальные названия функций и методов !
! Оригинальные названия параметров функций !
! Оригинальные названия всех типов !
! Оригинальные названия всех констант перечислений !
и многое другое.
Огромное количество полезной информации, актуальной в т.ч. и для SoD/WoG. Некоторые типы вообще не менялись из версий в версию, некоторые слегка видоизменялись в соответствии с нововведениями.
RE: Исследование героев - Berserker - 17.12.202121:20
void_17, Проблема в том что нужно чем то обработать всю недостающую графику для Wog и Сопряжения - что толку от половины работы?, там нужно еще менять настройки сжатия всех кадров ибо они хранятся в х3 размере, так как нам нужно чтобы отображалось как в оригинальной игре а не как в переиздании в увеличенном размере
RE: Исследование героев - void_17 - 23.01.202212:45
(22.01.2022 10:16)suftfree Wrote: void_17, Проблема в том что нужно чем то обработать всю недостающую графику для Wog и Сопряжения - что толку от половины работы?, там нужно еще менять настройки сжатия всех кадров ибо они хранятся в х3 размере, так как нам нужно чтобы отображалось как в оригинальной игре а не как в переиздании в увеличенном размере
Ну у вас же получается Topaz-ом обрабатывать. Я уверен, убейсофт так и делали, чутка подкорректировал в фотошопе.
Осталось изучить код HD Edition, благо там есть сигнатуры и иногда assert-ы с полезной информацией.
void_17, Поля битвы при обработке топазом очень похожи на HD Edition - даже местами лучше
Они какой-то другой (похожей) программой обрабатывали
Кстати вот наводка - HD Edition хранят весь интерфейс с не перекраской цветов (синего как в оригинале) а отдельно изображения с другим цветом
RE: Исследование героев - void_17 - 24.01.202215:02
Практически полностью разобрал combatManager, кроме полей, которые находятся по смещению от 0x13304 до 0x133CC.
upd.: Не обращайте внимания, я опять невнимательно посмотрел...
Завтра посмотрю, для чего поле unknown1.
Структура :
Code:
class combatManager : baseManager
{
CNetMsgHandlerPause *netMsgHandlerPause;
int iNextAction;
int iNextActionExtra;
int iNextActionGridIndex;
int iNextActionGridIndex2;
uchar iLastDrawGridShade[187];
uchar iCurDrawGridShade[187];
struct hexcell cell[187];
int combatTerrain;
int combatFringe;
int iCombatCycleType;
int iElevationOverlay;
int iDoorStatus;
uchar bMoatOn;
uchar moatIsWide;
Bitmap16Bit *SaveScreenPreGrid;
Bitmap16Bit *SaveScreenPostGrid;
Bitmap16Bit *combatMouseBackground;
int bBackgroundDrawn;
NewmapCell *EventCell;
uchar OnMagicPlains;
uchar OnCursedGround;
uchar OnAntiMagicGarrison;
uchar IsSurrounded;
uchar OnBoats;
uchar OnBeach;
struct town *combatTown;
struct hero *Heroes[2];
int iSideSpellPower[2];
uchar PlayDoh[2];
uchar PlayYeah[2];
uchar DohPlayedThisRound[2];
uchar YeahPlayedThisRound[2];
int cmbtHeroFrameType[2];
int cmbtHeroFrameIndex[2];
int cmbtHeroDataSet[2];
ulong cmbtHeroLastFidgetTime[2];
CSprite *cmbtHero[2];
CSprite *cmbtHeroFlag[2];
int cmbtHeroFlagFrame[2];
SLimitData sCmbtHeroLimitData[2];
SLimitData sCmbtHeroFlagLimitData[2];
std::vector< SpellID > EagleEyeSpellLearned[2];
uchar ArmyEffected[2][20];
bool IsHuman[2];
bool IsLocalHuman[2];
int iPlayer[2];
bool bArtifactCast[2];
int bSpellsCast[2];
int numArmies[2];
armyGroup *ArmyGroups[2];
army Armies[2][21];
///////////////////////
int unknown1;
//////////////////////
int turnSinceLastEnchanter[2];
bool OnNativeTerrain[2];
enum TCreatureType SummonedElemental[2];
int SideRetreated;
int currArmyGroup;
int currArmyIndex;
int currControl;
int autoCombatOn;
army *currTroop;
uchar selectorOn;
int selectorIndex;
int highlighterOn;
int highlighterIndex;
int lastMoveToIndex;
int lastCommand;
int combatCommand;
CSprite *CurLoadedSpellIcon;
int CurLoadedSpellEffect;
int CurSpellEffectFrame;
TFortificationLevel fortificationLevel;
int bBattleOver;
TCombatWindow *mainWindow;
int bCombatShowIt;
iconWidget * iconWidgetWL[ 25 ];
textWidget * textWidgetWL[ 25 ];
enum type_combat_cursor attack_cursor[ 12 ];
int attack_hex[ 12 ];
enum type_combat_cursor last_attack_cursor;
int iTtlCombatDirections;
int iBackgroundFrame;
bool bCreatureIsDead[2][20];
bool bSomeCreaturesVanish;
const char *cBkgName;
combatManager::adjacency_array AdjacentIndex[187];
uchar SaveBiggestExtent;
int LimitToExtent;
int ComputeExtentOnly;
SLimitData Extent;
int winner;
int SkeletonsCreated;
enum TCreatureType skeleton_type;
Bitmap816 *NumberWindow;
std::vector< combatManager::TObstacle > Obstacles;
bool InPlacementPhase;
int turn_number;
int BattleTacticsAdvantage;
bool DebugNoSpellLimit;
bool DebugShowHiddenObjects;
bool DebugShowBlockedHexes;
combatManager::TArcher Archers[3];
bool in_second_phase;
int OriginalAttackSkill;
int OriginalDefenseSkill;
int OriginalPowerSkill;
int original_mana;
Bitmap816 *wallImages[18][5];
int wallLevel[18];
int wall_frame[18];
type_point map_point;
Bitmap816 *CombatCellGrid;
Bitmap816 *CombatCellShaded;
int ObstacleAnimationFrame;
bool bCreatureEffect[2][20];
bool bHeroEffect[2];
bool bFlagEffect[2];
bool bArcherEffect[3];
bool any_action_taken;
uchar creaturePath[187];
};
RE: Исследование героев - RoseKavalier - 24.01.202215:18
Вопрос не про то, кто какие раздачи видел. Поэтому если есть такая версия - то хорошо (и тогда можно и поговорить, зачем это нужно), остальные же разговоры - бессмыслица.