Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Secondary skills manager for TE
DF2 :: ФОРУМЫ > Игровые форумы > Heroes of Might & Magic III > Моды > Скрипты
Demiurg
качать отсюда

Здесь представлена функция дли установки и получения силы 16 вторичных навыков на уровнях none, basic, advanced, expert.
Синтаксис:
Код
!!FU27512:P<skill_number>/<mastery>/<integer value>/<mode>/<index of float variable>;
skill_number: must be from {1, 2, 3, 4, 6, 8, 9, 11, 12, 13, 21, 22, 23, 24, 25 ,26}
mastery: none - 0, basic - 1, advanced - 2, expert - 3
integer value: optional parameter, variable or value(if write)
mode: 0 - read, 1 - write(0 by default)
index of float variable: optional parametr, index of (e-)-variable if need convert (in this case must be less than 0)

Сначала проверяется 5ый параметр. Если он меньше нуля, то идет чтение(запись) переменной с плавающей запятой. Иначе идет чтение(запись) 3его параметра.
Вот тестовый пример работы функции:
Код
;После выполнения этого кода базовая логистика будет увеличивать ходы героя на две трети.
!?PI;
!!VRe-7:S2:3;//устанавливаем число с плавающей точкой
!!FU27512:P2/1//1/-7;//устанавливаем силой базовой логистики значение переменной e-7
!!FU27512:P2/1///-1;//получаем в переменную e-1 силу базовой логистики
!!VRy-1:S100*e-1;//домножаем на 100, чтобы получить проценты
!!IF:M^basic logistics increase movementpoints by %Y-1%%^;//выводим на экран


Еще примеры:
Код
;при отсутствии интеллекта герои получают 5 маны за знание
!?PI;
!!VRe-3:S-1:2;
!!FU27512:P24/0//1/-3;

Код
;герой с экспертным имуществом приносит в казну 830 золота в день
!?PI;
!!FU27512:P13/3/830/1;

Код
;получаем процент, на который продвинутая стрельба увеличивает урон стрелков
!?PI;
!!FU27512:P1/2///-3;
!!VRy6:S100*e-3;
!!IF:M^advanced archery skill increase distant damage by %Y6%%^;

Код
;Реализация класса Снайпер(герой с баллистикой и стрельбой получает дополнительные бонусы к стрельбе: +10/+20/+30%) из ТЕ с помощью функции.
;new style of Sniper class
!#VRv2085:S1;
!?BA52&v2085=1;
!!VRv2084:S-1;
!!BA:H0/?y-1 H1/?y-2;
!!HEy-1:S10/?y-3 S1/?y-4;
!!VRv2080&y-3<y-4:Sy-3;
!!VRv2080&y-3>=y-4:Sy-4;
!!VRv2082:Sy-4;
!!FU&y-2<0:E;
!!HEy-2:S10/?y-3 S1/?y-4;
!!VRv2081&y-3<y-4:Sy-3;
!!VRv2081&y-3>=y-4:Sy-4;
!!VRv2083:Sy-4;



!?MM&v2085=1;
!!BG:Q?y-1;
!!FU&y-1=v2084:E;
!!VRv2084:Sy-1;
!!VRy1:S2080+y-1;
!!VRy2:S2082+y-1;
!!VRy3:Svy2*2-1+vy1;
!!VRy3&vy2=0:S0;
!!VRe-1:S1:10*y3;
!!FU27512:P1/vy2//1/-1;

!?BG0&v2085=1;//just in case and AI
!!BG:Q?y-1;
!!FU&y-1=v2084:E;
!!VRv2084:Sy-1;
!!VRy1:S2080+y-1;
!!VRy2:S2082+y-1;
!!VRy3:Svy2*2-1+vy1;
!!VRy3&vy2=0:S0;
!!VRe-1:S1:10*y3;
!!FU27512:P1/vy2//1/-1;


Вот и сама функция
Код
;real - necromancy, archery, attack, armorer, eagle eye, dimplomacy, resistance, learning, logistics, sorcery, intelligence
;for real needs convert
;integer - luck, leadership, mysticism, scouting, estate
;for integer does not need convert

!?FU27512;//set power of some SS
;x1 - secondary skill
;x2 - mastery
;x3 - value for write or read
;x4 - mode: 0 - read 1 - write
;x5 - index of (e-)-variable if need convert (in this case must be less than 0)
!!FU|x4<0/x4>1:E;//wrong mode (must be 0..1)
!!FU|x1<1/x1=5/x1=7/x1=10/x1>26:E;//skills aren't supported
!!FU&x1>13/x1<21:E;//skills aren't supported
!!FU|x2<0/x2>3:E;//wrong mastery (must be 0..3)
!!VRy1&x1=1:S6547944;//archery
!!VRy1&x1=2:S6548072;//logistics
!!VRy1&x1=3:S6547928;//scouting
!!VRy1&x1=4:S6548024;//dyplomacy
!!VRy1&x1=6:S6547880;//leadership
!!VRy1&x1=8:S6547912;//mysticism
!!VRy1&x1=9:S6547864;//luck
!!VRy1&x1=11:S6548008;//eagle eye
!!VRy1&x1=12:S6547896;//necromancy
!!VRy1&x1=13:S6547992;//estate
!!VRy1&x1=21:S6548056;//learning
!!VRy1&x1=22:S6547960;//attack
!!VRy1&x1=23:S6547976;//armorer
!!VRy1&x1=24:S6548104;//intelligence
!!VRy1&x1=25:S6548088;//sorcery
!!VRy1&x1=26:S6548040;//resistance
!!VRx2:*4;
!!VRy1:+x2;
!!if&x4=0:;
 !!UN:Cy1/4/?x3;
 !!UN:C10784536/4/x3;//10784536 - address of e1
 !!VRex5&x5<0:Se1;
!!el:;
 !!VRe1&x5<0:Sex5;
 !!UN&x5<0:C10784536/4/?x3;//10784536 - address of e1
 !!UN:Cy1/4/x3;
!!en:;


Замечания:
1) Нужно учитывать, что часть навыков хранится в типе integer, а часть в float. В integer хранятся следующие навыки: leadership, luck, mysticism, scouting, estates.
2) Для некоторых навыков позволены отрицательные значения. Например для интеллекта в одном из примеров устанавливается -0,5.
3) Не забывайте, что функция работает только под ТЕ по следующей причине: "В WOG 3.58f запрещена запись с помощью !!UN:C в область памяти, отвечающей за вторичные скиллы".
4) Описание работы конвертеров: Конвертер из действительного числа в его машинное целочисленное представление записывает по адресу переменной e1 значение и считывает оттуда с помощью !!UN:C его машинное представление. Конвертер из машинного целочисленного представления в действительное число записывает с помощью !!UN:C по адресу переменной e1 машинное представление и копирует переменную e1 в переменную ex2, где x2(<0) - выделенный пользователем индекс для получения значения.
Berserker
Если будет работать, будет здорово. Не помешала бы.
Demiurg
Обновление.
Теперь можно не только устанавливать значения навыков, но и получать их. Смотрите первый пост.
Чёртос-2 (Chortos-2)
Почему ты думаешь, что запрещена запись через !!UN:C в область вторичных навыков?
Demiurg
У меня не получилось
Я пробовал
Код
!?TM2;
!!UN:C6548108/4/1061158912;
Demiurg
Обновил ссылку.
Сделал возможность устанавливать и получать значения для уровня развития навыков None.
Добавил примеров в первый пост.
Demiurg
Обновление. Упростил конвертер из машинного представления в действительное число.
gamecreator
там, где по 4 строчки для каждого навыка расписано по-моему пожно упростить в одну
Druin
там условия разные...
gamecreator
нет, напр. первую четверку как:
!!UN&x1=9:C6547864+x2*4/4/x3;

Добавлено ([mergetime]1182948642[/mergetime]):
там закономерность есть
Чёртос-2 (Chortos-2)
ERM‐интерпретатор не поймет.

Я бы сделал так (хотя, если бы я это писал, я бы, во‑первых, сделал одну и ту же функцию и для чтения, и для записи, во‑вторых, возвращал бы значение в x3, а не vx3):
Код
!?FU27512;
;x1 - secondary skill
;x2 - mastery
;x3 - value for write
!!FU|x1<1/x1=5/x1=7/x1=10/x1>26:E;
!!FU&x1>13/x1<21:E;
!!VRy1&x1=1:S6547944;//archery
!!VRy1&x1=2:S6548072;//logistics
!!VRy1&x1=3:S6547928;//scouting
!!VRy1&x1=4:S6548024;//dyplomacy
!!VRy1&x1=6:S6547880;//leadership
!!VRy1&x1=8:S6547912;//mysticism
!!VRy1&x1=9:S6547864;//luck
!!VRy1&x1=11:S6548008;//eagle eye
!!VRy1&x1=12:S6547896;//necromancy
!!VRy1&x1=13:S6547992;//estate
!!VRy1&x1=21:S6548056;//learning
!!VRy1&x1=22:S6547960;//attack
!!VRy1&x1=23:S6547976;//armorer
!!VRy1&x1=24:S6548104;//intelligence
!!VRy1&x1=25:S6548088;//sorcery
!!VRy1&x1=26:S6548040;//resistance
!!VRx2:*4;
!!VRy1:+x2;
!!UN:Cy1/4/x3;

!?FU27513;
;x1 - secondary skill
;x2 - mastery
;x3 - index of v-variable
!!FU|x1<1/x1=5/x1=7/x1=10/x1>26:E;
!!FU&x1>13/x1<21:E;
!!VRy1&x1=1:S6547944;//archery
!!VRy1&x1=2:S6548072;//logistics
!!VRy1&x1=3:S6547928;//scouting
!!VRy1&x1=4:S6548024;//dyplomacy
!!VRy1&x1=6:S6547880;//leadership
!!VRy1&x1=8:S6547912;//mysticism
!!VRy1&x1=9:S6547864;//luck
!!VRy1&x1=11:S6548008;//eagle eye
!!VRy1&x1=12:S6547896;//necromancy
!!VRy1&x1=13:S6547992;//estate
!!VRy1&x1=21:S6548056;//learning
!!VRy1&x1=22:S6547960;//attack
!!VRy1&x1=23:S6547976;//armorer
!!VRy1&x1=24:S6548104;//intelligence
!!VRy1&x1=25:S6548088;//sorcery
!!VRy1&x1=26:S6548040;//resistance
!!VRx2:*4;
!!VRy1:+x2;
!!UN:Cy1/4/?vx3;

Функция умеет работать только с 16‑ю навыками, но это нигде не сказано. Непорядок.
Demiurg
Цитата(Чёртос-2 (Chortos-2) @ 27 Jun 2007, 17:31)
ERM‐интерпретатор не поймет.

Я бы сделал так (хотя, если бы я это писал, я бы, во‑первых, сделал одну и ту же функцию и для чтения, и для записи, во‑вторых, возвращал бы значение в x3, а не vx3):

1) Насколько я знаю, считается дурным тоном объединять методы Set и Get в один.
2) Согласен с тем, что нужно возвращать в x3. Исправлю.
3) Посмотрю, насколько большой выигрыш по скорости получается при использовании сокращения.
Цитата
Функция умеет работать только с 16‑ю навыками, но это нигде не сказано. Непорядок.

Сказано в названии темы (change some SS values). Но, согласен, в посте нужно продублировать.
Чёртос-2 (Chortos-2)
Цитата(Demiurg @ 27 Jun 2007, 18:48)
Насколько я знаю, считается дурным тоном объединять методы Set и Get в один.
Возможно, но, во‑первых, я не согласен crazy.gif — почему нет? Во‑вторых, можно сделать разный синтаксис, как у меня:
Код
!!FU#:P0/#/#/#;
!!FU#:P1/#/#/?$;
В‑третьих, это разумно, так как сэкономит целую функцию, а сейчас в ERM номера — какие бы то ни было — нарасхват.
Berserker
Согласен с Чёртосом. Комментарий (ложка дегтя в бочке мёда):

3) Посмотрю, насколько большой выигрыш по скорости получается при использовании сокращения.

Не посмотришь smile.gif Никак.
Demiurg
Цитата(Berserker @ 27 Jun 2007, 22:16)
3) Посмотрю, насколько большой выигрыш по скорости получается при использовании сокращения.

Не посмотришь smile.gif Никак.

Почему?
Запускаешь цикл до 1000000 (10000000 или сколько нужно) и засекаешь время на одной функции, потом на другой. По отношению времени смотришь, какой алгоритм работает быстрее. Я таким методом сравнивал несколько алгоритмов сортировки, которые за Nlog2N. Запускал их на 10000000 чисел. Один работал 70 секунд, другой 140 секунд, третий тоже 140 секунд. (Это было еще на старом компе, поэтому так долго.) Как говорится время хороший свидетель скорости.
Berserker
Ну в лоб всё можно. Только комп работает с разной нагрузкой (смотря какие приложения запущены) + если ты запустишь такой цикл, то ЕРМ надолго заснёт. читать (НАДОЛГО). Ну и время ты как, вручную замерять будешь? smile.gif

З.Ы Жаль, что воговцы свои алгоритмы не оптимизировали и время не проверяли.

Заметка по ЕРМ: выгоднее писать макросы (то есть которые будут текстом вставляться в код), чем вызывать функцию. Значительный выигрышь времени. Не надо анализировать, обнулять переменные, резервировать место + (ещё внутренняя кухня) ЕРМ.
Demiurg
Время как-нибудь уж померюsmile.gif Была бы проблема.
Насчет макросов. Они страшно глючат. Медленный и безглючный код лучше быстрого и нерабочего. Благо для большинства скриптов есть большой запас по скорости.
Berserker
Я про другие макросы, скоро узнаешь smile.gif
Demiurg
Цитата(Berserker @ 28 Jun 2007, 23:29)
Я про другие макросы, скоро узнаешь smile.gif

Ждемс.
Только мне кажется, что не все так просто. Я думаю, что время работы скрипта зависит еще и от его длины. А использование макросов вместо функций ведет к удлинению скрипта
Berserker
Нет, нет, и ещё раз нет smile.gif Причина: ЕРМ-парсер не преобразует исходник в байт кода каждый раз заного интерпритирует команду. То есть если в функции даже одна команда, а выполняется функция 200 раз, то всё равно выгодне написать эти 200 раз текстом.
Demiurg
Berserker очень прав.
Время вызова функции ~ 0,5ms
Время выполнения одного сравнения < 0,001ms
Однако, время загрузки в память на старте карты 1ой строчки скрипта ~ 0,2ms
Вывод1:
У Чертоса функция работает быстрее. В ней меньше сравнений и она занимает меньше места, т. е. быстрее грузится на старте.
Вывод2:
Лучше использовать функции по минимуму.
Вывод3:
Можно предположить ситуацию, когда стоит использовать функции, чтобы сократить время загрузки карты на старте.

Ждем макросов!!!
Demiurg
Обновил функцию. Встроил конвертеры. Добавил проверку входных параметров на валидность.
Спасибо Chortos-2 за замечания и предложенияgood.gif
Berserker
Макросы - первая задача после евмы. Завтра выложу прогу с хэлпом для откладки в Wog3.58 и для ехешника ТЕ (всё в одной, выбор будет //З.Ы Также и Реквизит, знать бы версию экзешника)

Я знаю, насколько глупы бывают ошибки ЕРМ и насколько рутинна откладка. Приходится пихать везде !!IF:M^%V600 %V601 %V602^;....
Расталвять их по всем местам, заного менять, проверять другие... и каждый раз с перезапуском карты. Труд программера не ценится. Это ещё что, хуже когда присылают сейв с багом, который повторить больше не может (происходит раз в пол года), или который только в данном сейве. Тут нет возможности перезагрузки. Я было начал писать функцию для получения и изменения переменных ЕРМ прямо через ЕРМ (н помню как называется, в скриптах выкладывал), но это не то. Что даёт ERM VARS MEMORY EDITOR (EVMA):

1) Удобный и красочный диалог с программой через консоль.
2) Максимально простой интерфейс, одна клавиша определяет команду, остаётся только ввести значения.
3) Встроенная сводка команд
4) Масимальная защита от "уничтожения" игры. Вы можете вводить кривые числа, не те индексы, выходить за рамки ЕРМ переменных, оставлять пустые места, пихать во флаги цифры, отличные от 0 и 1 (в особом режиме), в общем издеваться как хотите. Прога укажет на каждую ошибку и выполнит операцию ТОЛЬКО при идеальном синтаксисе.
5) Поддерживаемые переменные: V, F (флаги), Z (строки), W (переменные героев, герой выбирается особой командой). Разумеется только глобальные поддерживаются, можно было и локальные, но это более рутинно, а я не могу тратить на прогу больше 2-3 дней.

6) Консоль на 1000 строк. Поддерживаемые команды:
//Очистить консоль, показать список команд, выход.

P.S Всё на русском языке.

//Получить значение переменной ЕРМ или нескольких. Если кол-во не указано, то по умоччанию одной, в противном случае до максимума. То есть v1 1000 после команды выведет все v переменные.

//Выбор героя (это понятно, так как w-переменные привязаны к определённому герою)

//Установить значение переменной. Поддерживаются массовые установки:
v1 1 2 3 4 5 6 7 8 9 10
установит переменные v1..v10 данными значениями. Если одно из значений некорректно, установка прервётся и покажется ошибка (которая не мешает, вы такие будете видеть часто).

Строки устанавливаются по одной и автоматом ковертятся в ansi-кодировку (как оказалось, в консоле кодировка доса и ваш ввод был бы непонятен ЕРМ и ЕРМ-строки отображались бы криво).

//Заполнить серию переменных указанным значением.
Так, где так армия защитника, ага, к примеру в v9000..v9015

v9000 16 0
Всё, нет армии (заполнили нулями).

Строки тоже массово устанавливаются и вся рутина (строки в ерм 0-конечные, а в паскале юзаю string) пользователю не видна и не нужна. Если нужно забить что-то пустыми строка, то используется '#0'

//Чтение и запись данных по адресу.
Нашли адрес с переменными? 16-ричный редактор неудобен, не поимает формата переменных, тогда идём сюда указываем адрес, тип (типы сллегка другие) и кол-во просматриваемых. Ой-ля-ля. Всё в родном виде. Также можно и писать в память в родном иде, числа, байты, строки...Если вы укажите кривой адрес - ничего не прозойдёт, а прога известит о неверном адресе (или защищённой от чтения/записи) области.

//Установка одной ЕРМ переменной значения другой. Сюда же входит совместимость w и v переменных. Так что все присваивания (опять таки, можно массовые) вам доступны. Например скопировать w55.w64 в v1..v10 можно за две секунды. Хорошо, но вам нужно скопировать большой объём данных, а там почти везде воговские переменные, не хочется и портить! Тогда...

//Сброс дампа и загрузка переменных из дампа!!!
Сброс дампа: Имя файла: мой_дамп.XXX
Параметры: v1 10000
Всё, все v-переменные благополучно перекочевали в файл, можете юзать память. Также просто и загрузить! Более того, можете снять дамп строк, а загрузить в v-переменные, не знаю, что это вам правда даст smile.gif

Вывод: таким образом, кинув нужное место банальное !!IF:M^^; вы сможите качественно проанализировать работу скрипта и в каких переменных неверные значения, сможете эксперементировать прямо на ходу, наблюдая реакцию игры и быть в курсе внутренной кухни ЕРМ...
Чёртос-2 (Chortos-2)
В первом примере используется переменная v1, значение которой нигде не задается.
ZVS
ERM интерпретатор "разбирает" все триггеры и каждую строку с приемниками. Текст самой строки приемника (не триггера) не разбирается, а интерпретируется каждый раз.
Отсюда следствия:
1. Можно по ходу выполнения править текст приемников (для этого и делалось).
2. Повторной интерпретации триггера не производится, но при вызове триггера (например функции), происходит поиск в списке. Больше триггеров - дольше поиск.
3. Приемники интерпретируются при каждом выполнении. Два приемника в одной строке - меньше памяти (внутренней) используется, скорость не должна зависить. Т.к. поиска приемников нет, то и количество их (вернее строк в скрипте ERM) не влияет на скорость выполнения скриптов.
И последнее 4. При разработке ERM не ставилась задача оптимизации скорости работы скриптов. Ориентация была на разово выполняющиеся скрипты, а не циклы. И количество скриптов, конечно, ушло ДАЛЕКО вперед по сравнению с тем, что предполагалось. :-) Да и сами попробуйте прикрутить скриптовую систему, да еще и оптимизированную к чужому готовому экзешнику...
Berserker
ZVS, всё это верно smile.gif Ваш труд поистенне велик, но ИМХО байт-код сразу был бы более оптимальным решением. А теперь о другом. ЕРМ-скрипты уже есть, может просто переписать движок? Хотя работы много, это понятно, но диалоги и так есть, адреса переменных и встроенных функций имеются. Правда это лиш мечты. Была и другая идея: вызывать из произвольного кода библиотек Ваши ресиверы. Это возмоно? Проблема в том, что невозможно совместить быстрый код и вызов какой-небудь внутриигровой функции, которая в ЕРМ занимает пару символов. Та же: !!IF:M^^;
ZVS
Это возможно. Опять - интерфейсные соглашения и внешняя DLL. Так работает, например генаратор случ. карт для Г4. Утилита грузит DLL Генератора, передает указатель на интерфейс, DLL "просит" разместить объекты и утилита размещает.
Berserker
Можно даже проще.
Допустим Вы напишите универсальную функцию ЕРМ, которая выполняет один ресивер и возвращает управление. Тогда внешней DLL понадобится только адрес данной функции ну и параметр типа pchar. Функция возвращает булевкий аргумент.

Добавлено ([mergetime]1184086885[/mergetime]):
И ещё, команда по вызову DLL ещё как нужна. Пока мне приходится вообще рутинным процессом всё это делать (только при загрузке, правда). Дело в том, что если я вызываю
VreateRemoteThread с адресом LoadLibrary (сперва зарезервировав место под имя библиотеки), то библиотека загружается и всё вроде ОК, только адреса сдвинуты, а эти адреса и так с боем у Detective Story ищутся. Хуже всего то, что раз на раз не приходится.
ZVS
Это хорошо. Но некоторые ресиверы подразумевают callback триггеры (тот же таймер, например). Думаю, что в минимальном варианте можно и такой функцией обойтись, но если уж делать, так делать. Предлагаю и это по почте обсудить.
Berserker
В таком случае завтра придёт письмо. Рад, что не погибло желание продолжить работу над Героями. Честно говоря, я считал уже, что ВоГ 3.59 мало что светит.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Форум IP.Board © 2001-2024 IPS, Inc.