prog
offline
Опыт:
32,865Активность: |
Кодинг Редактора Объектов - доступ из jass, код в полях РО и многое другое
ВступлениеПервоначальная идеяРеализовать небольшую утилиту, которая будет анализировать данные РО и соответствующим образом дополнять jass-код карты. В идеале Также модификация данных РО при определенных условиях.
Что получилось в итогеИнтегрированная с экспериментальной версией JNGP утилита, которая извлекает данные из РО, а затем анализирует код карты на наличие шаблонов, подставляя где нужно полученные значения.
СпецификацияИспользование шаблоновШаблоны поддерживаются для файлов war3map.wts и war3map.j и обрабатываются до передачи кода другим препроцессорам.
Разновидности шаблоновПоддерживается две разновидности шаблонов - это операции с данными и директивы.
Операции с данными выглядят так: ((код
${код}
)) В составе кода могут быть использованы любые арифметические операции, шаблонные переменные и обращения к данным по объектам. Директивы выглядят так:
((код
<имя директивы и параметры>
</имя директивы>
)) Обращение к данным объектовВ общем виде доступ к данным конкретного объекта осуществляется с помощью конструкции ${XXXX.YYYYzz}, где XXXX это равкод объекта, YYYY равкод поля, к которому идет обращение, а zz - уровень способности или вариация декорации и не указывается для других типов объектов.
К сожалению, на данный момент доступны только нестандартные значения полей, но это будет исправлено со временем. Использование директивДирективы обеспечивают дополнительный функционал, выходящий за рамки линейной подстановки значений и выполнения арифметических операций.
В общем случае директива состоит из двух тегов - открывающего и закрывающего. Допускается вложенность директив, при условии соблюдения порядка тегов. Наиболее часто используемыми директивами являются <list> и <if>. Директива if((код
<if условие>
</if>
)) Содержимое директивы "выполняется" только если выполняется условие директивы. Директива list((код
<list collection as variable>
</list> )) Содержимое директивы "выполняется" для каждого элемента коллекции.
В качестве collection на данный момент может быть использована одна из следующих коллекций объектов:
units - все юниты ability - все способности items - все предметы Позже будут добавлены коллекции для всех остальных типов объектов. Что касается variable, то это локальная шаблонная переменная, которую можно обозвать как угодно и которая доступна только в области видимости директивы list. Для объектных коллекций обращение к этой переменной аналогично обращению к объекту по его равкоду.
Также эта конструкция может быть применена для обхода всех уровней способности. Для этого вместо collection нужно использовать конструкцию вида A000.levels или, любой другой способ обратиться к полю levels какой-либо способности.
Равкоды полейJNGP отображает равкоды полей в скобках после названия, так что с их получением не должно быть проблем. Позже будет введено несколько синонимов для основных полей.
Примеры((код
<list units as u>
юнит: ${u} скорость: ${u.umvs} стоимость: {u.ugol} </list> ))
Выдаст после компиляции список всех юнитов, их скорость и стоимость в золоте
((код
<list units as u>
<if u.ugol \gt 100 > юнит: ${u} стоимость: {u.ugol} </if> </list> )) Выдаст после компиляции список равкодов и стоимостей всех юнитов, стоимость которых больше или равна 100 ((код
${hgyr.ubld}
)) Выдаст время строительства вертолета (стандартный юнит альянса), если это значение отличается от стандартного. ((код
${ 2 * 2 + 5 }
))
Думаю вы догадываетесь что получится в результате)
((код
<list A000.levels as L>
${L} ${L.Data} </> )) выведет номер каждого уровня способности A000 и значение поля Data на этом уровне
Бета версияВ ближайшее время здесь будет выложена бета-версия для тестирования. Желающим пораньше посмотреть что это за зверь просьба писать в личку - бета уже есть.
Установка бета-версии достаточно проста.
Для начала необходимо установить седьмую джаву, затем извлечь архив бета-версии в папку с экспериментальным JNGP, предварительно сделав бекап файла wehack.lua. тут будет ссылка на скачивание
Для любопытных((кат как это работает
Для начала из карты извлекаются файлы с данными по объектам (w3u,w3a,w3t и так далее), файлы строк и код карты.
Затем данные разбираются утилитой и формируется модель данных. После чего модель данных, файл строк и код карты передаются библиотеке FreeMarker в качестве шаблонов для компиляции. Для уменьшения веса утилиты используется версия FreeMarker 2.03. Также файл строк очищается от пустых строк, которые там возникают в процессе импорта/экспорта. )) В разработкеК сожалению, утилита пока далека от совершенства и многое только предстоит доделать.
Например, на данный момент, если сохранить и закрыть карту, использующую шаблоны, а затем открыть ее, то все шаблоны будут утеряны, кроме тех что находятся в триггерах.
Второй серьезной проблемой является способ хранения строк описаний объектов - они вынесены в файл war3map.wts и утилита на данный момент еще не ассоциирует их с конкретными объектами. Как результат, при попытке подставить значение одного текстового поля в другое, получим надпись TRIGSTR_ вместо фактического значения. Также параллельно с решением этой проблемы планируется добавить локальную переменную, видимую только в описаниях объектов, указывающую на объект, которому принадлежит данное описание. Это позволит использовать ${this.равкод поля} вместо ${равкод конкретного объекта.равкод поля} при обращении к полям данного объекта.
И таких примеров еще множество и они будут добавляться сюда по мере того как я буду о них вспоминать.
Дополнительные ссылкиОтредактировано prog, 28.02.2012 в 18:51. |
20.02.2012, 22:53 | #1
+6/−0
Профиль |
Приват |
Поиск |
Цитата |
IP: Записан
|
Hanabishi
COOL STATUS
offline
Опыт: отключен
|
|
21.02.2012, 11:55 | #2
+0/−0
Профиль |
Приват |
Поиск |
Цитата |
IP: Записан
|
prog
offline
Опыт:
32,865Активность: |
Hanabishi, спасибо, конечно, но по моей ссылке информации намного больше. В частности там приведен подробный формат большинства файлов из архива, а не только их описание. Этого достаточно для решения моей задачи, вопрос в том есть ли еще что-то, например готовые утилиты? Или, может, кому-то уже доводилось заниматься этим и он может поделиться опытом. |
21.02.2012, 13:16 | #3
+0/−0
Профиль |
Приват |
Поиск |
Цитата |
IP: Записан
|
ScorpioT1000
Работаем
offline
Опыт: отключен
|
продублирую рандом идея =)
ScorpioT1000:
Пример применения:
((код jass
string OE_ABILITY_A001_DESCRIPTION () {
return "уровень 1 - " + OE_ABILITY_A001_START_DAMAGE + " урона\n" + \ "уровень 5 - " + R2S( S2R(OE_ABILITY_A001_START_DAMAGE) * \ S2R(OE_ABILITY_A001_DAMAGE_MULTIPLIER) * 5.0 ) + " урона" } ))
((код jass
function OE_ABILITY_A001_DESCRIPTION takes nothing returns string
return "уровень 1 - " + "5" + " урона\n" + "уровень 5 - " + R2S( S2R(5.0) * S2R(1.144) * 5.0 ) + " урона" endfunction ))
((код jass
function OE_ABILITY_A001_DESCRIPTION takes nothing returns string
return "уровень 1 - 5 урона\nуровень 5 - " + R2S( S2R(5.0) * S2R(1.144) * 5.0 ) + " урона" endfunction ))
Отредактировано ScorpioT1000, 21.02.2012 в 13:51. |
21.02.2012, 13:35 | #4
+1/−0
Профиль |
Приват |
Поиск |
Цитата |
IP: Записан
|
Alex_Hell
Mapmaker 'N' Programmer
offline
Опыт:
6,885Активность: |
На счет извлечения данных - думаю справишся.
А вот способ использования: хотелось бы прямо в игре иметь возможность обратиться к любому юниту и получить из него все его параметры. Например:
Т.е. задача проги - сгенерировать классы UnitInfo, SkillInfo (впринципе написать их руками можно сейчас), и забить контектом базы данных, т.е. в реализации метода UnitInfo.create(unit) идет обращение к БД, заполненной прогой. Такие виды классов сделать для всех объектов: unit, item, destructable, skill, buff. В качестве БД - hashtable. Способ заполнения - обычный dictionary между путем в файле вара и ключем в БД (Description, Name). Реализация свойства Description, Name - обращение к БД с ключем Description, Name и типом юнита или типом скила. Отредактировано Alex_Hell, 21.02.2012 в 14:39. |
21.02.2012, 14:24 | #5
+0/−0
Профиль |
Приват |
Поиск |
Цитата |
IP: Записан
|
ScorpioT1000
Работаем
offline
Опыт: отключен
|
опятьже продублирую, тут проблема очевидная =)
|
21.02.2012, 14:27 | #6
+0/−0
Профиль |
Приват |
Поиск |
Цитата |
IP: Записан
|
prog
offline
Опыт:
32,865Активность: |
Alex_Hell, поскольку я не поклонник vjass - оставлю эту задачу кому-нибудь другому. Ну или если совсем уж нечего делать будет.
ScorpioT1000, меня куда больше волнуют перспективы потери данных и их неотображения в РО без перезапуска.
По поводу препроцессинга описаний - свой препроцессор написать не проблема. В крайнем случае припахать того-же адольфа, если у меня не получится. Положить эти описания обратно в w3u файл - не проблема. Положить файл обратно в карту - ты показал как.
Проблема может быть с потерей данных при неправильном обращении с утилитой, но это частично решается введением переключателя dev/релиз. В режиме dev описания только переносятся в код, без обратновго вкладывания в карту, в режиме релиз карта сохраняется в двух экземплярах (если это возможно) первый аналогичен dev, а ко второму применяется какая-нибудь оптимизация и препроцессинг описаний. |
21.02.2012, 14:42 | #7
+0/−0
Профиль |
Приват |
Поиск |
Цитата |
IP: Записан
|
ScorpioT1000
Работаем
offline
Опыт: отключен
|
что мешает перед какойто хитроумной обработкой сделать нескомпиленный бекап? |
21.02.2012, 14:58 | #8
+0/−0
Профиль |
Приват |
Поиск |
Цитата |
IP: Записан
|
prog
offline
Опыт:
32,865Активность: |
ScorpioT1000, вот потому и нужен переключатель, отключающий впихивание в карту скомпиленную версию описаний. А лучше еще и автобекап перед сохранением скомпиленной версии - на случай кривых рук или недосыпания. |
21.02.2012, 15:01 | #9
+0/−0
Профиль |
Приват |
Поиск |
Цитата |
IP: Записан
|
ScorpioT1000
Работаем
offline
Опыт: отключен
|
да зачем плодить карты ? давай разберемся, у нас есть 2 проблемы:
|
21.02.2012, 15:09 | #10
+0/−0
Профиль |
Приват |
Поиск |
Цитата |
IP: Записан
|
Alex_Hell
Mapmaker 'N' Programmer
offline
Опыт:
6,885Активность: |
Ребят, я не совсем понял о чем вы пишете, что касается изменения данных и возврата изменений в РО. Есть рутиная задача - карта по diablo. Так вот есть например 6 видов драгоценных камней, и у каждого предмета 1 сокет - куда вставить можно камень. Вручную сделать - скопировать каждый предмет 6 раз, в каждом подменить описание вида "сокет: аметист" , "сокет: череп". Эффекты от сокетов будут одинаковые так что можно тут же добавить способность предмету (1 из 6) или возложить на jass - запихать в БД, т.к. БД все равно нужна будет чтобы сопоставить скилл улучшения (вставки сокета, 6 скилов) и полученный предмет. Так вот с помощью этой проги можно будет легко такой механизм реализоать? Вы хотите решать задачи такого плана?
prog:
Ты же мне именно об этом писал в ЛС, когда писал о способе восстановления маны за скилл без ручного написания БД. Это во мних случаях может пригодиться. Как прога будет почти готова, могу добавить такой функционал - генерации vJass структур (там статичный код будет для всех карт) и заполнении БД (это будет зависеть от содержимого карты). |
21.02.2012, 16:17 | #11
+0/−0
Профиль |
Приват |
Поиск |
Цитата |
IP: Записан
|
prog
offline
Опыт:
32,865Активность: |
Alex_Hell, изначально эти данные будут складываться в виде cJass дефайнов, примерно так как предложил ScorpioT1000
Если дружишь с джавой - посмотрим. По поводу БД я сам пока думаю как реализовать. Скорее всего это будет внешний конфигурационный файл для каждой карты, определяющий что туда ложить, а что нет. |
21.02.2012, 16:32 | #12
+0/−0
Профиль |
Приват |
Поиск |
Цитата |
IP: Записан
|
ScorpioT1000
Работаем
offline
Опыт: отключен
|
Ну я кароче тогда так предлагаю: написать несложный анализатор, в котором можно будет объявить простенькие макросы доступа, математики и работы со строками, тот же луа бы мог сойти.
Базовый функционал:
Предложение Alex_Hell насчет структур было бы удобнее, НО ! cJass оптимизирует и удаляет ненужные дифайны, а представь будет 1000 полей у структур ?
также необязательно, но неплохо было бы сделать простые операции подстроки и сложения строк.
смотрите, мы используя пункт 1, можем объявить один главный предмет, а у остальных ссылаться на первый, кроме какихто определенных полей, тем самым, можно менять 1 предмет не опасаясь за остальные
используя пункт 2 можно задать какойто предмет например "полный сет", который требует итемы при этом не задавать явно в нём что он требует, а дописывать его требования в отдельных новых итемах ! можно даже статы одного итема дописывать или убирать в других итемах
так же с юнитами и декором, т.е. это откроет офигенные возможности =)
это будет новый, динамический подход к статическим объектам в варкрафте)
ScorpioT1000 добавил:
я бы предложил таки запихивать всё в карту, не думаю что 20 килобайт сильно мешать будут. Даже есть 200 килобайт кода, мпку отлично его сжимает Отредактировано ScorpioT1000, 21.02.2012 в 17:18. |
21.02.2012, 17:24 | #13
+0/−0
Профиль |
Приват |
Поиск |
Цитата |
IP: Записан
|
prog
offline
Опыт:
32,865Активность: |
ScorpioT1000:
Речь идет не о дефайнах - они будут все ложиться, а о БД на массивах или хештаблице. Там уже надо отслеживать что должно сохраняться, а что - нет. |
21.02.2012, 17:31 | #14
+0/−0
Профиль |
Приват |
Поиск |
Цитата |
IP: Записан
|
ScorpioT1000
Работаем
offline
Опыт: отключен
|
prog, ты имеешь ввиду парсинг варовского архива, типа чтобы потом оттуда цеплять те данные, которые запрошены в юзерских полях ? могу посоветовать Sqlite - база данных без демонов ! x) удобно и практично, всего одна библиотечка |
21.02.2012, 17:33 | #15
+0/−0
Профиль |
Приват |
Поиск |
Цитата |
IP: Записан
|
prog
offline
Опыт:
32,865Активность: |
ScorpioT1000, нет имеется ввиду БД на jass, чтобы можно было спросить, зная Id, например, что написано в поле стоимость заклинания. При этом Id становится известен только на этапе выполнения - дефайны не катят.
Решается эта задача примерно так:
обычно такие БД собирают вручную, что представляет собой страшный геморрой |
21.02.2012, 17:55 | #16
+0/−0
Профиль |
Приват |
Поиск |
Цитата |
IP: Записан
|
ScorpioT1000
Работаем
offline
Опыт: отключен
|
ты имеешь ввиду, чтобы можно было делать например обход или пикать юнита и по его типу что-то находить ? ну я тоже так думал, это вполне реализуемо, если касается нестандартных вещей, а вот если на основе стандарта - начинается веселье =) да наверно так и есть - придется отметить явно объекты, которые надо будет подгружать. но я бы предложил пока сделать хотябы по нестандартной части. Действительно, дифайны тут не катят.
Про описание карты - както не шарит, хм. А что если сделать так - проверить, есть ли изменения в указанном объекте (ну помните они другим цветом выделяются, и это еще лежит в файлах карты), и их заливать в бд ? а юзерам скажем, типа если хотите по ним делать выборку - измените в них чето-то, поставьте пробел )
ScorpioT1000 добавил:
вот это лишнее, имхо. можно же в вар3мап закинуть всё и да, базу тогда предлагаю делать типа XAT - большой одномерный массив, работающий как хештейбл. Можно найти оффсет и писать его в константу внутри, по нему + равкоду и находить ячейку. |
21.02.2012, 18:15 | #17
+0/−0
Профиль |
Приват |
Поиск |
Цитата |
IP: Записан
|
prog
offline
Опыт:
32,865Активность: |
ScorpioT1000, объясняю зачем инжектить через cjass - это проще чем выковыривать .j файл, и дописывать в него.
По поводу объектов, которые надо подгружать. У меня в картах бывает до нескольких сотен способностей. Все нестандартные, естественно. Из них данные мне нужны, скажем, по двум десяткам. Забивать в базу все способности не вариант - это лишняя нагрузка и затраты памяти.
Второе - поля. У объектов достаточно много полей, не все из которых могут быть нужны во время игры - лишние тоже было бы неплохо убрать из БД.
Решение первой проблемы - какой-нибудь индикатор для препроцессора, указывающий что данные по этому объекту должны быть сложены в БД. (в одном из существующих полей или путем добавления полей в РО для нужд препроцессора)
Решение второй проблемы чуть сложнее - на ум приходит только создание конфигурационного файла со списком полей, которые должны быть подгружены в БД для данной карты.
Теперь по стандартной части - эти данные не так уж и сложно выдрать. Для их хранения вполне подойдет файл того-же формата что и для нестандартных, надо только скомпоновать данные из slk-таблиц |
21.02.2012, 18:36 | #18
+0/−0
Профиль |
Приват |
Поиск |
Цитата |
IP: Записан
|
ScorpioT1000
Работаем
offline
Опыт: отключен
|
prog, тогда смысл программы отпадает автоматически =) т.к. вся фича в автоматике была.
Я бы тогда предложил парсить конечный .j файл на наличие обращений к полям (может задать команду cjass, которая заменяет вызовы какойнить штуки вроде OELOAD(RAW,TYPE) на хорошо узнаваемую последовательность символов) и задавать для всех требуемых объектов только те поля, к которым были обращения.
Вынуть war3map.j не так уж сложно, если хочешь, я тебе даже прогу напишу, которая из файла .j собирает все обращения по какомуто keyword(rawcode,arg1,arg2,...) и складывает их в файл типа
rawcode|arg1|arg2|...\n я бы даже сделал умнее, и это будет наверно еще круче, кароче:
|
21.02.2012, 18:54 | #19
+0/−0
Профиль |
Приват |
Поиск |
Цитата |
IP: Записан
|
prog
offline
Опыт:
32,865Активность: |
да ладно, необходимость прописать один include со стадартным именем файла убивает на корню всю автоматику)
Или ты про конфиг с полями? так он делается один раз для каждого вида ресурсов и дальше просто используется.
Да, конфиг вынести в .j файл идея хорошая. Но парсить код на предмет обращения к полям это уже слишком, как мне кажется. Тем более что моя утилита рассчитана на работу перед cJass. Для начала сделаю в виде специального комментария - он будет легко парситься и удалится на этапе оптимизации карты любым оптимизатором. А там видно будет - может и это доделаю. |
21.02.2012, 18:56 | #20
+0/−0
Профиль |
Приват |
Поиск |
Цитата |
IP: Записан
|