Показать: 45|Ответить: 0

[Квестовые файлы] Гайд: как зарегистрировать новый квест

[Скопировать ссылку]
Опубликовано 2025-8-30 13:31:31 | Показать все этажи |Режим чтения


Гайд: как зарегистрировать новый квест



1) Подготовь класс квеста

Принято класть в пакет quests.Q70001_ElmorionCh1 и файл Q70001_ElmorionCh1.java.

[code=java]
// Пример минимального скелета под  сборку (Elmorion)
package quests.Q70001_ElmorionCh1;

import org.l2jmobius.gameserver.model.quest.Quest;
import org.l2jmobius.gameserver.model.quest.QuestState;
import org.l2jmobius.gameserver.model.actor.Npc;
import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;

public class Q70001_ElmorionCh1 extends Quest
{
// Привяжи к нужным NPC/мобам/предметам
private static final int START_NPC = 30151; // пример: Чад (склад)
private static final int END_NPC = 30152; // пример: Джулия
// private static final int MOB = 20003; // если нужно


  1. public Q70001_ElmorionCh1()
  2. {
  3.     super(70001);                 // ID квеста
  4.     addStartNpc(START_NPC);       // кто начинает
  5.     addTalkId(START_NPC, END_NPC);// с кем говорим
  6.     // addKillId(MOB);            // если нужно
  7.     // registerQuestItems(...);   // если есть предметы квеста
  8.     // addCondMinLevel(1, "70001-lvl.htm"); // пример условия
  9. }

  10. @Override
  11. public String onTalk(Npc npc, PlayerInstance player)
  12. {
  13.     final QuestState qs = getQuestState(player, true);
  14.     final int npcId = npc.getId();

  15.     if (npcId == START_NPC)
  16.     {
  17.         if (qs.isCreated())
  18.         {
  19.             // Старт
  20.             return "70001-01.htm";
  21.         }
  22.         else if (qs.isStarted())
  23.         {
  24.             // В процессе
  25.             return "70001-02.htm";
  26.         }
  27.         else if (qs.isCompleted())
  28.         {
  29.             // Повторно
  30.             return "70001-complete.htm";
  31.         }
  32.     }
  33.     else if (npcId == END_NPC)
  34.     {
  35.         // Завершение
  36.         // giveItems(player, 57, 1000); addExpAndSp(player, ...);
  37.         // qs.exitQuest(false, true);
  38.         return "70001-end.htm";
  39.     }
  40.     return null;
  41. }
Скопировать код


b]HTML для квеста кладём обычно в data/html/... (или в твои папки elmlight/elmdark/elmchaos, как вы решили).
Кнопка запуска в диалоге:
[code=html]
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest Q70001_ElmorionCh1">Начать квест</Button>
[/code]
Если используешь «события» (event), верни из onAdvEvent(...) имена html ("70001-01.htm" и т. п.) и в кнопке передавай это событие:
[code=html]
action="bypass -h Quest Q70001_ElmorionCh1 start"
[/code]

2) Зарегистрируй класс в QuestMasterHandler.java

В твоём файле нет метода register() — здесь используется статический массив QUESTS и простое создание экземпляров. Делается так:

а) Добавь import (вверху, среди уже существующих):
[code=java]
import quests.Q70001_ElmorionCh1.Q70001_ElmorionCh1;
[/code]

б) Добавь класс в массив QUESTS (найди массив private static final Class<?>[] QUESTS = { ... } и допиши новую строку):
[code=java]
Q70001_ElmorionCh1.class,
[/code]

И всё — лоадер пройдётся по массиву и вызовет пустой конструктор твоего квеста:
[code=java]
for (Class<?> quest : QUESTS)
{
quest.getDeclaredConstructor().newInstance();
}
[/code]

Чек-лист по регистрации:


    [] Есть правильный пакет package quests.Q70001_ElmorionCh1;
    [] Импорт добавлен в QuestMasterHandler.java
    [] Класс добавлен в массив QUESTS
    [] В конструкторе квеста вызывается super(70001)
    [] Повешены нужные addStartNpc(...), addTalkId(...), addKillId(...)
    [] HTML лежит по путям, куда ссылается код ("70001-01.htm" и т. п.)

3) Пропиши данные для клиента: data/NewQuestData.xml

Этот файл у тебя есть в архиве, его читает сервер и отправляет клиенту корректные сведения о квесте (название, тип, кто старт/финиш, цели, награды для UI).

Структура (реальные поля из твоего файла):
[code=xml]
<quest id="10001" type="1" name="Sedrick's Best Pupil" startNpcId="30008" endNpcId="30008">
<locations>
<param name="startLocationId">485</param>
<param name="endLocationId">485</param>
<param name="questLocationId">485</param>
</locations>
<conditions>
<param name="minLevel">1</param>
<param name="maxLevel">5</param>
<param name="classIds">0;1;4;7;2;3;5;6;8;9</param>
<param name="preQuestId">10000</param>
<param name="oneOfPreQuests">10002;10003</param>
</conditions>
<rewards>
<items>
<item id="91912" count="100"/>
</items>
<param name="rewardExp">12345</param>
<param name="rewardSp">2</param>
<param name="rewardLevel">5</param>
</rewards>
<goals>
<param name="goalItemId">98464</param>
<param name="goalCount">3</param>
<param name="goalString">Herb Roots</param>
</goals>
</quest>
[/code]

Атрибуты у <quest ...>:


    [] id — ID квеста (у тебя внутрянка — 70001 и т. д.)
    [] type — тип. В твоём файле встречаются 1 и 4:


      [] 1 — стандартный (старт от NPC/ленточные обучающие и пр.)
      [] 4 — «Request»/охотничье поручение (встречается с startItemId)

    [] name — отображаемое имя квеста (английский/локаль клиента)
    [] startNpcId / endNpcId — кто стартует/завершает
  • startItemId — если квест стартует предметом, а не NPC


Внутренние блоки:


    [] <locations>: startLocationId, endLocationId, questLocationId — ID локаций для UI-подсказок
    [] <conditions>: minLevel, maxLevel, classIds (через ;), preQuestId, oneOfPreQuests
    [] <rewards>: блок items (список <item id="" count=""/>) + параметры rewardExp, rewardSp, rewardLevel
    [] <goals>: goalItemId, goalCount, goalString (подпись в UI «что делать»)


Пример для твоего квеста 70001:
[code=xml]
<quest id="70001" type="1" name="Elmorion: Chapter I" startNpcId="30151" endNpcId="30152">
<locations>
<param name="startLocationId">561</param>
<param name="endLocationId">562</param>
<param name="questLocationId">562</param>
</locations>
<conditions>
<param name="minLevel">1</param>
<param name="classIds">0;1;2;3;4;5;6;7;8;9</param>
</conditions>
<rewards>
<items>
<item id="57" count="1000"/>
</items>
<param name="rewardExp">500</param>
<param name="rewardSp">1</param>
</rewards>
<goals>
<param name="goalCount">1</param>
<param name="goalString">Talk to Julia</param>
</goals>
</quest>
[/code]

Где вставлять? Внутрь корневого:
[code=xml]

<?xml version="1.0" encoding="UTF-8"?>

<list xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="xsd/NewQuestData.xsd">
... тут идут <quest ...> ... </quest> ...
</list>
[/code]

4) «Жёлтый вопросик», портреты и тексты клиента

Вашей сборке они используются на стороне клиента, ориентируйся на такие схемы (типовые структуры из Essence-веток; имена/поля в конкретной ревизии могут отличаться):

4.1 QuestMarkConditionData.xml — правила появления «?» над NPC.
[code=xml]

<?xml version="1.0" encoding="UTF-8"?> <list> <mark questId="70001" npcId="30151"> <conditions> <param name="minLevel">1</param> <param name="maxLevel">40</param> <!-- classIds / preQuestId / oneOfPreQuests и т. п. --> </conditions> </mark> </list> [/code]

4.2 NewQuestDialog.xml — тексты для клиентских окон квеста (заголовки/описания шагов).
[code=xml]

<?xml version="1.0" encoding="UTF-8"?> <list> <dialog questId="70001"> <title>Elmorion: Chapter I</title> <step id="1"> <text>Поговорите с Джулией в эльфийской деревне.</text> </step> <step id="2"> <text>Вернитесь к Чаду, чтобы завершить задание.</text> </step> </dialog> </list> [/code]

4.3 NewQuestNpcPortrait.dat— портреты NPC, показываемые в UI квеста. (клиент)
[code=xml]

<?xml version="1.0" encoding="UTF-8"?> <list> <portrait npcId="30151" icon="Icon.npc_chad" /> <portrait npcId="30152" icon="Icon.npc_julia" /> </list> [/code]

Важно: В ряде ревизий клиент читает эти данные не из *.xml, а из *.dat (NewQuestData-eu.dat, QuestMarkConditionData.dat, NewQuestDialog-eu.dat, NewQuestNpcPortrait.dat). Тогда правка делается в клиенте (и/или через ваши редакторы), а серверный NewQuestData.xml остаётся как источник данных, которые он шлёт клиенту для согласованности UI.

5) Тестирование и типичные ошибки



    [] Квест «не виден» вообще: проверь import и наличие Q70001_ElmorionCh1.class в массиве QUESTS.
    [] Кнопки «молчат»: проверь bypass -h Quest Q70001_ElmorionCh1 ... и соответствие имён html, которые возвращаешь из onTalk/onAdvEvent.
    [] UI пишет Unknown quest: допиши блок в NewQuestData.xml с корректным id, type, name, startNpcId/endNpcId.
    [] «Жёлтый ?» не появляется: это клиентская логика — правится QuestMarkConditionData.(xml/dat) (в твоём серверном архиве файла нет).
    [] Портрет/текст не показываются: проверь клиентские NewQuestNpcPortrait / NewQuestDialog (в твоём серверном архиве их тоже нет).
    [] Исключение при загрузке: смотри лог — обычно ругается на отсутствие пустого конструктора или NPE в конструкторе квеста.
Хроники Элмориона пишутся каждым шагом путника.

Правила начисления баллов

Быстрый ответ Наверх Вернуться к списку