Drac: Блог

 

Drac

разработчик l2j-сервера

Случайно наткнулся на написанный месяц назад мануал и решил его выложить. Он представляет собой упрощение написания квестов на языке Jython для сервера (особенно, если понять изложенные тут мысли).
Раньше, когда у СФ в Датапаке творилась неразбериха, материал был очень актуален, т.к. квесты писали очень коряво, даже не учитывая клиентсих данных, поэтому даже сейчас многие квесты не показывают правильно шаги в клиенте, т.к. являют собой зачаток нормального квеста (в них логика правильная, а вот посылка клиенту данных хромает сильно). Сейчас ситуация несколько изменилась, в Датапаке СФ появились более грамотные люди, и квесты пишутся почти так, как я задумывал (правда их стиль ох как похож на мой :), наводит на мысли).

В этом мануале я разбирал квест 297_GatekeepersFavor, переделывая его с написания. Не буду вдаваться в подробности, напишу как есть. Если возникнут вопросы - постараюсь ответить.

ПОЕХАЛИ:
Прямо с самого верха пойдем.

Зачем нужны окончания _ID при обозначении переменных в самом начале квеста (это особенно относится к предметам)? Перестал это понимать уже давно. Они только место занимают, и строку удлиняют.

def onEvent:
1. Описывается всегда жутко страшно в СФ, особенно в старых квестах. Эта строчка отвечает за ссылку в диалоге, т.е. пример [Quest 297_GatekeepersFavor 1|Say you will help], тут 1 - это ссылка. Уже вполне давно реализовано, что если вызывать ссылку на конце которой написано .htm , то ява будет искать файл диалога с таким именем. Притом мало того, что она будет искать диалог - так она ещё и запустит обработчик onEvent, что позволит убить сразу 2-х зайцев: вызвать нужный диалог, и запустить обработчик (в обычном случае нам бы пришлось сначала запускать обработчик потом показывать диалог).

2. st.set("id","0") - сакральный смысл этого мне до сих пор непонятен. Вероятно они думали про защиту от мошенничества. Но я боюсь, что она итак не пройдет.

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

def onTalk:
1.
if id == CREATED :
st.setState(STARTING)
st.set("cond","0")
st.set("onlyone","0")
st.set("id","0")
Вот эти 5 строчек - глупость полная. Можно обойтись и без них. Они при нажатии на диалог проверяют стадию (<state>) квеста, и если она в базе описана как Start, то будет запущена установка стадии в STARTING и добавление в таблицу character_quests в БД значений cond, onlyone, id и все в 0. Но зачем нам дергать итак нагруженную базу?! Это совершенно не нужно.
Расписываю почему:
а) cond - если делать st.getInt("cond") - то из базы будет возвращаться значение cond, а если cond нет в базе - то вернется 0. Значит нам вообще не надо его определять тут;
б) STARTING - некая промежуточная стадия, которая не нужна, потому как, обычно человек сразу кликает на ссылку и ему сразу же выдается стадия STARTED, т.к. смысла вообще не имеет;
в) onlyone - это, якобы, используется для того, чтобы определить многоразовость квеста. Если стоит 1 - значит квест уже был один раз пройден и при наличии проверки - не получится пройти его ещё раз. Но это же можно сделать если правильно поставить проверку на стадию st.getState() (<state> в БД) квеста. Что-то типа if id == COMPLETED : ...;
г) id - как и говорил, зачем используется я не понимаю, возможно пытались не дать поюзать баги.
Так что оно не нужно совершенно.

2. Дальше я поубивал все проверки на номер НПЦ. Вопрос: а зачем они, если в квесте всего 1 НПЦ, с которым надо разговаривать?!Командами в конце:
QUEST.addStartNpc(30540)
STARTING.addTalkId(30540)
STARTED.addTalkId(30540)
этот НПЦ будет занесен в ХешМапы, и кроме него там никого больше не будет. Поэтому при выборе квеста ява сама будет понимать, что только у одного НПЦ можно по этому квесту разговаривать.
Соответственно, этот метод не подойдет, если в квесте разговор идет более, чем с одним НПЦ.

3. Вот кстати, чуток повыше надо было поставить: я int(st.get("cond")) переименовал в st.getInt("cond") (выше описано почему) и поставил прямо на входе в метод onTalk строку cond = st.getInt("cond"), чтобы можно было сокращенно использовать его. Очень полезно, когда квест длинный.

4. Собственно, перенес проверку на левел. Т.е. когда игрок нажмет у НПЦ на Quest в главном диалоге, то получит описание квеста и диалог в котором будет сказано, что ему ещё мало годиков для того, чтобы взять квест :)

5. На самом деле в квесте содержалась ошибка. Значение cond - при его изменении передается в обработчик явы, который посылает клиенту обновленные сведения о квесте. В конкретно этом квесте 2 шага (1 - получение задания и 2 - возвращение с нужными вещами). Они были заранее неправильно выставлены. И использовался всегда только шаг 1. Т.е. в окне квестов клиент всегда бы видел, что получил задание, даже тогда, когда все необходимые вещи были собраны.
Поэтому при возвращении с 20-ью Старстоунами я переписал, чтобы был шаг 2 (он дается в обработчике onKill, когда собраны 20 этих камней).

6. st.takeItems(STARSTONE2_ID,st.getQuestItemsCount(STARSTONE2_ID))
Очень противная строка. st.getQuestItemsCount(STARSTONE2_ID) - определяет количество заданных вещей в инвентаре персонажа. Это лишние вычисления, после которых количество все количество этих вещей изымается у персонажа. Можно поставить вместо st.getQuestItemsCount(STARSTONE2_ID) значение -1 (минус один) и тогда точно также будут забираться все вещи, только не нужны будут средние вычисления.

7. На оффе дается 2 Токена. Сам проверял. Поэтому st.giveItems(GATEKEEPER_TOKEN_ID,1) заменил 1 на 2.


def onKill:
1. Опять же используется всего лишь 1 моб, поэтому совершенно не нужна проверка на его номер. Если мобов больше и награды разные - надо будет уже отдельно описывать.

2. Система выдачи вещей выпавших такова, что определяется, можно ли ещё дать предмет. Если можно - дается и проверяется, что если этот предмет последний - ставится шаг 2 и играется соответствующая музыка. Если не все собрали ещё - играется другая музыка. Такая система эффективнее. Насчет шага 2 я писал в п.5 предыдущего раздела.


Все, что далее:
1. Все упоминания о STARTING удалил за ненадобностью.
2. Чтобы квест многоразовый был надо как раз было подставить COMPLETED.addTalkId(...) . Если мы после выполнения квеста поставим cond в 0 и стадию в COMPLETED , то можно будет на самом входе в def onTalk у первого НПЦ проверять на возможность повтора квеста. Если проверки на COMPLETED не добавлять, то квест будет многоразовым.

P.S. Лучше всего использовать для отступов ПРОБЕЛЫ, а не табуляцию, как сделано во многих квестах. Разные редакторы по разному отображают количество пробелов в табуляции, и поэтому у разных пользователей может по разному это отображаться (если они, конечно, не пользуются Блокнотом :) )

Вот и все. Надеюсь, что доступно и понятно.

P.S.S. Кстати, к рассмотрению принимаются diff для любых квестов (желательно с комментариями, что вы поправили). Можете присылать свои квесты, будем только рады. Помогу оформить квест в самом лучшем виде (естественно, я пришлю обратно то, что правил), размещу у нас в Датапаке, и конечно можно подумать о взятии в команду.
 

Drac

разработчик l2j-сервера

В данной статье описывается как правильно установить программные продукты Java Development Kit (впоследствие просто JDK), Eclipse и Subeclipse для работы с открытыми исходными кодами java-серверов Lineage 2. Также будет описано как импортировать готовый проект L2j-сервера в Eclipse.

Первым делом надо скачать JDK - средство разработки java-приложений. Последняя версия JDK доступна по ссылке СКАЧИВАТЬ ТУТ или на сайте http://java.sun.com (впринципе это один ресурс, просто первое - прямая ссылка для скачивания, второе - главный сайт).
Далее скачиваем Eclipse с сайта http://www.eclipse.org/downloads/ (доступна всегда последняя версия).

Вторым шагом начинаем потихоньку устанавливать все это таким образом:
- jdk-6u2-windows-i586-p.exe просто запускаем и инсталлируем (я надеюсь, как это делать не надо разжевывать);
- eclipse-SDK-3.2.1-win32.zip (или какая у вас там версия его будет) распаковываем в любую папку.

Третий шаг - настройка Eclipse.
Идем в папку, куда распаковывали Eclipse и запускаем eclipse.exe. Возможно на этом этапе вам предложат выбрать Рабочее пространство (Workspace), в котором вы будете впоследствие храните свои исходные коды. Далее выбираем меню Help -> Software Updates -> Find and Install , как показано на рисунке НОМЕР 1 . Далее выбираем "Search for new features for install". Жмем "Next" . Кликаем кнопку "New Remote Site".
В поле "Name" вводим subeclipse , а в поле "URL" вводим subclipse: Subclipse Update Site . Должно получиться что-то вроде этого НОМЕР 2 . Затем жмем "Ок", потом "Finish", выбираем subeclipse для установки и нажимаем "Next", соглашаемся с правилами (Accept terms), и жмем Finish.
Теперь наберитесь терпения во время того, как программа будет закачивать обновления для себя. Процесс это недолгий. После того, как выкачивание завершится, нажмите кнопку "Install all". И после завершения установки Eclipse попросится на перезагрузку - отправляйте.
Модуль subeclipse установлен. Поздравляем! Если же не получилось - вчитывайтесь лучше :)

Собственно на этом заканчивается установка необходимых продуктов, теперь надо только найти место, откуда можно скачать исходные коды (если они конечно вам очень нужны). Я не буду приводить адреса сайтов с исходными кодами, рассмотрю на примере несуществующего сайта :)

Для скачивания проекта из SVN репозитория выбираете в главном окне Eclipse кнопку "Window", далее "Show View" , далее "SVN Repository", как показано на рисунках НОМЕР 3 , НОМЕР 4 . На пустом поле открывшегося окошка щелкаете правой кнопкой мыши и выбираете меню "New" -> "Repository Location". В поле URL вставляете адрес репозитория, откуда будете выкачивать исходные коды. А в поле User и Password , соответственно свои логин и пароль для доступа к исходникам.
После небольшого обдумывания проект появится в том окне, что мы открывали раньше. Кликните на него правой кнопкой мышки и выберите "Checkout..."
Скачивание проекта займет некоторое время, которое будет зависеть от размера самого проекта. После скачивания этот проект предстанет перед вами в новом окне. Вам только останется выбрать нужный файл для редактирования (отдельно работу с программой я описывать не буду).

Для компиляции проекта вам понадобится встроенный по умолчанию в Eclipse инструмент Ant. Выбираем в главном окне Window -> Show View -> Other -> Ant (показано на рисунках НОМЕР 5 , НОМЕР 6 ) . В новом открытом пространстве щелкаем правой клавишей и выбираем "Add Buildfiles..." Программа покажет список доступных проектов. В проекте выбираете файл build.xml (рисунок НОМЕР 7 ).
В окне Ant появится проект с несколькими доступными на развороте свойствами. Краткая характеристика основных:
clean - удаление предыдущих скомпиленных сборок. Лучше проводить перед каждой компиляцией новой версии, иначе могут вылезти ошибки;
dist [default] - непосредственно компиляция. После её выбора начнется компиляция проекта в папку (обычно называется build у всех l2j проектов);
jar - компилирование только jar файлов (содержащих классы проектов), без датапака и прочих прибамбасов.

Для компиляции проекта также понадобится выставленный в "Переменных средах" путь к JAVA_HOME. Как добраться? Просто : Правый клик мышкой по "Мой компьютер" дальше закладка "Дополнительно" и кнопка "Переменные среды".
Жмете кнопку "Создать" и вбиваете:
Имя переменной - JAVA_HOME
Значение переменной - C:\Program Files\Java\jdk1.5.0_04\ (или другой путь, который у вас :))

По-умолчанию можно выбирать dist [default] как показано на НОМЕР 8 .
После выбора этого пункта начнется компиляция проекта. Время зависит от мощности компьютера и его загруженности сторонними программами в момент компиляции. Время полной компиляции 1-5 минут. Только исходных файлов (без датапака) - от 10 секунд до 1 минуты.

В данном случае вы получили проект в Eclipse, который можете редактировать, компилировать и что угодно с ним делать.

На этом я закончу описание выкачивания проекта, и углубляться в установку сервера и его настройку не буду в этом топике (об этом будет отдельный топик).

Теперь я хочу рассмотреть вариант для тех, кто скачивал проект не через Eclipse (например, через популярный Tortoise SVN : http://tortoisesvn.tigris.org/ ). Тут может случиться затык, т.к. просто так проект не развернешь в Эклипсе и править можно сначала только в блокноте. Дальше я расскажу как корректно импортировать скачанный из репозитория проект в проекты Eclipse.

В главном окне программы выбираем Window -> Show View -> Package Explorer . Откроется новая вкладка Package Explorer.
На пустом пространстве этого окна щелкаем правой кнопкой мыши и выбираем кнопку Import. Появляется список по категориям.
Разворачиваем" категорию General и выбираем пункт "Existing project into Workspace".
Убедитесь, что проект, который вы хотите импортировать находится в указанном Рабочем Пространстве (workspace), которое вы указывали при первом запуске программы.
Выберите в самом верху Select root directory и нажмите кнопочку Browse рядом со строкой для ввода.
Дальше ищите папку, в которой хранится проект, который вы хотите импортировать.
Выбрали папку и в поле "Projects" появился ваш проект (…

Дальше »»»
 

Drac

разработчик l2j-сервера

До сих пор достаточно остро стоит проблема с осадами. Вот недавно обнаружилость, что наемные гварды на осадах стоят как вкопанные, притом не предпринимая на каких действий по отношению к захватчикам. Вероятно не аттачится к ним АИ никакой.

Задача: исправить ошибку. Сделать так, чтобы наемные гварды получали свой АИ, присущий всем остальным гвардам.

Исполнитель: неизвестен. Место вакантно.
 

Drac

разработчик l2j-сервера

Сразу оговорюсь. Много написано, поэтому форум неадекватно это все воспринял. Если строчка обрывается, прокрутите вправо, чтобы дочитать её до конца.

Это явно наболевшая тема, ибо все, кто занимается диалогами и переводами делают их в своем неповторимом стиле.
/*Лирическое отсутпление: встречал даже "новорусские" переводы такого типа: "Ща по мобиле добазарю и тогда подойди ко мне", сие в литературном переводе с английского значило: "Ты ещё не выполнил (ля-ля-ля). Напомню, что тебе надо сделать (то-то-то)." */

Вот ещё пример : месяц назад человеком с ником Saboteur были в Фортрессе размещены выправленные диалоги. Вроде все получалось у него нормально: ненужные теги хтмл были убраны (а зачем они в фортрессе, если все равно все диалоги парсятся в хтмл); убраны кучи ненужных пробелов; подправлено форматирование, ну и все прилегающие вещи. Только меня эта работа немного смутила, ибо после этого коммита все фиксенные диалоги приобрели новые ошибки форматирования (между абзацами диалогов вставало по 2-3 пустые строки), что мне не очень понравилось. С этого момента я и по сей день, когда нахожу эти ошибки - исправляю их, и, чувствую, что такого ещё много. Но меня добило больше всего то, что после исправления перевода и расстановки строк, который я позавчера сделал, Saboteur вернул сегодня все обратно, даже ничего не спрашивая.

Так вот, я предлагаю наконец перейти к нормальному формату ВСЕХ диалогов, включая квестовые. Притом не ориентироваться ни на Датапак СФ, ни на остальные, так как у них своих ошибок хватает, а вид диалогов оставляет желать лучшего.

В связи с этим хочу повторить для всех, кто будет работать (или помогать) на поле формирования датапака Фортресс, а точнее с его диалоговой частью, разметку, которая поддерживается сервером и преобразовывается в ХТМЛ-код.

- заголовок файла, определяется при парсинге как <html><head><body>
Сразу скажу, что он этот тег не требует закрытия в конце файла, так как автоматически добавит в конец файла нужные </body></html>.

%% - перевод строки, в ХТМЛ-коде интерпретируется как <br1>.

text - текст между звездочками подсвечивается желтым цветом, в ХТМЛ-коде выглядит как text, т.е. text. Первая звездочка всегда будет открывать тег и искать закрывающую звездочку.

[b][ [/b] - начало байпасса, в ХТМЛ-коде выглядит как [u][html_a action="bypass -h [/u].

Притом! Это именно этот тег! Если вы хотите сделать, например, кнопку, то вы не сможете указать этот тег, а придется делать <button action="bypass -h ...



] - конец байпасса, в ХТМЛ-коде оно < /a]. (Перед /a стоит специальный символ, который делает пустоту, а то форум хочет урл интерпретировать. Не обращайте внимания.)

| - разделитель между коммандной частью и текстом в байпассе, в ХТМЛ-коде он ">. То что до него - это комманда, то, что после - это текст, который будет показан в диалоге.

Уточнение

- если используете массовое исправление в куче файлов, то учтите, что "> встречается не только в теге байпасса, а может и в картинках и шрифтах (и других тоже, если есть). Поэтому всегда следует убедиться, чтобы потом не искать ошибку.

По трем последним тегам пример:
[html_a action="bypass -h npc_%ObjectId%_Quest"]Quest< /a> как будет правильно выглядеть? Правильно, мальчик, именно как [npc_%ObjectId%_Quest|Quest].

Для таблиц нет отдельных тегов в Фортрессе, поэтому мы используем стандартные из ХТМЛ, но учитывая несколько правил, чтобы было удобнее читать. Все равно размер окошек диалогов маленький, поэтому на официальном сервере все настоящие диалоги подогнаны под них.
Seed: Dark Coda105
Seed: Red Coda135

-Это пример из Информации по семенам.
По-моему мнению получается довольно компактно, и в любом случае это будет читабельно, внутри тегов (по-крайней мере для меня) весь текст хорошо виден.

Центровка элементов диалога производится парой ХТМЛ-тегов
text
. Никаких особых тегов у нас на этот счет нет.

Для изображений тоже нет отдельного тега. Поэтому формируем его как есть в ХТМЛ, т.е., например, .

Это была лекция по разметке. Теперь по правилам оформления.

Как была достаточно давно сказано, дабы русифицировать диалоги и квесты, но притом не потерять ничего, если клиент не является русифицированным, мы используем при написании имен собственных сразу 2 варианта - русский и английский. Может повысим грамотность населения по части английского языка.
Поэтому, как и предлагал Балансер, и до сих пор бьюсь я, чтобы именно так писали, оформлять так:
1. Если надо писать имя НПЦ, то пишем сначала как оно звучит по-русски, потом в скобочках оригинальный вариант.
Например, Gatekeeper Mirabel в английском варинте, а в переводе напишем : Привратница Мирабель (Gatekeeper Mirabel).
2. Если имя монстра (моба) то есть 2 случая :
1) оно переводимо на русский без потери смысла - то пишем русский варианта и в скобочках английский.
Например, Stone Golem - переводим и получаем, что в диалог надо написать : Каменный Голем (Stone Golem).
2) оно содержит имя нарицательное - то пишем как бы предположительно оно могло выглядеть по-русски и добавляем в скобки английский вариант..
Например, Ol Mahum Raider - переводим, и видим, что Ol Mahun - это скорее всего название племени. Поэтому переводим вот так и дописываем : Налетчик Ол Махум (Ol Mahum Raider). В таком случае мы никогда не потеряем истинного названия моба и всегда можно будет его найти, если конечно никакой лентяй не будет юзать какую-нибудь русификацию клиента.

3. Переводы имен нарицательных различных сооружений это вообще отдельный разговор. Над каждым именем нужно подумать, как его правильно перевести, так как может быть несколько трактовок. Единственный вариант понять как правильно перевести - изучить историю мира Аден. Притом это не шутка, из кучи информативных диалогов можно понять, как правильно перевести, так как в них как раз рассказывается история некоторых локаций.
Если вы полностью уверены, что знаете истинный смысл названия, то делаем как и в предыдущих случаях - пишем русский вариант и за ним в скобочках английский.
Пример (оно с моим мнением как переводить одну из локаций): было в английском варианте Immortal Plateau, стало в русском Бессмертное плато (Immortal Plateau).

4. Вещи: с ними тоже сложно, не менее, чем с локациями. Поэтому стараемся максимально точно (с минимальным отклонением) передать смысл вещи. Но принцип вссе тот же - сначала русское название, потом в скобочках английское. Именные вещи точно также, главное понять, что в названии есть именное слово.
Примеры :
1) Именная вещь :английский вариант Greenis's Letter; на русский переводим и пишем как Письмо Гриниса (Greenis's Letter);
2) Не именная вещь : английский вариант Piece Bone Breastplate; на русский переведем и напишем как Кусок Костяного Нагрудника (Piece Bone Breastplate).

Так как каждый сервер стремится быть чем-то похожим на официальный сервер (конечно это не относится к тем, кто делает ПвП сервер), поэтому абзацы, расположение ссылок, кнопок и т.п. нужно подгонять под Офф, наверное все таки они хорошо понимают логику и делают так как надо.
Поэтому если у них есть 3 абзаца - то не стоит каждое предложение из этих 3-х абзацев ставить на новую строчку. А если…

Дальше »»»
 

в начало страницы | новое
 
Поиск
Настройки
Твиттер сайта
Статистика
Рейтинг@Mail.ru