Суббота, 08.02.2025, 00:09Приветствую Вас Гость
Регистрация | Вход
RSS
L I N E A G E
Меню сайта
Категории раздела
Interlude [571]
Дополнения к хроникам Interlude.
Gracia Final [108]
Дополнения для хроник Gracia Final.
Сборка [110]
Здесь можно скачать сборки, готовые сервера.
Программы [69]
Здесь можно скачать программы.
Прочее [47]
Другие материалы для Lineage 2
Шаблоны [192]
Здесь можно скачать шаблоны для сайта
NPC for Interlude [516]
Здесь можно скачать различных NPC для хроник Interlude.
Баннеры [57]
Можно скачать Баннеры для Lineage 2
Статьи [240]
Различные Статьи о Lineage 2
High Five [1]
Дополнения для хроник High Five
Вход на сайт
Поиск
Друзья сайта
  • Официальный блог
  • Сообщество uCoz
  • FAQ по системе
  • Инструкции для uCoz
  • Статистика
    Главная » Файлы » Статьи

    Гайд по созданию квеста
    12.02.2015, 16:20

     

    Первое что нужно сделать, это добавить необходимые Java классы в квест. (net.sf.l2j.gameserver.model.quest).
    Код:
    import sys
    from net.sf.l2j.gameserver.model.quest import State
    from net.sf.l2j.gameserver.model.quest import QuestState
    from net.sf.l2j.gameserver.model.quest.jython import QuestJython as JQuest



    Класс QuestJython (импортирован под названием JQuest) содержит информацию о квестах.
    Класс State используется для того, что бы описать информацию о состоянии квеста.
    Класс QuestState применяется непосредственно для отслеживания состояния игрока, о ходе выполнения квеста или части квеста.

    Затем необходимо добавить несколько констант, что сделает квест удобочитаемым. Если этого не сделать, то могут возникнуть сложности с редактированием квеста в будущем.
    Константы нашего квеста – это ID NCP и итемов.
    Код:
    KELTIR_NPC_ID = 12082
    FANGS_ITEM_ID = 1859
    DROP_RATE     = 500000
    WORLD_MAP_ITEM_ID = 1665


    Затем объявите несколько вспомогательных функций.

    Функция для получения количества квестовых предметов (keltir fangs) у игрока. (st должна быть в QuestState):
    Код:
    def getCount(st) :
      return st.getQuestItemsCount(FANGS_ITEM_ID)


    Функция для завершения квеста (st должна быть в QuestState):
    Код:
    def completed(st) :
      st.setState(COMPLETED)
      st.clearQuestDrops()
      st.takeItems(FANGS_ITEM_ID,-1)
      st.giveItems(WORLD_MAP_ITEM_ID,1)
      st.exitQuest(False)
      return


    Тут объявляем квест выполненным, сбрасываем квестовый дроп, забираем все клыки у игрока и даем ему награду. Затем сообщаем серверу, что квест завершен и больше не повторяется. (st.exitQuest(False))

    И наконец вспомогательная функция для проверки необходимого количества клыков у игрока для завершения квеста. (st должна быть в QuestState):
    Код:
    def check(st) :
      if getCount(st) >= 4 :
        completed(st)
      return


    Затем мы объявляем непосредственно сам класс quest. Quest – класс python, который расширяет java класс net.sf.l2j.gameserver.model.quest.jython.QuestJyth on. Затем мы объявляем метод onEvent, который вызывается Явой, если квест кто то начал.
    Код:
    class Quest (JQuest):

      def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)

      def onEvent (self,event,st):
        id = st.getState()
        if   id == CREATED  : st.setState(STARTED)
        elif id == COMPLETED: pass
        elif id == STARTED  : check(st)
        return

    Метод init – это конструктор Jython класса, который вызывает конструктор Java класса. Конструктор имеет параметры:
    • self – ссылка на себя.
    • id – численный идентификатор квеста для клиента.
    • name – имя квеста, которое будет опубликовано непосредственно с самом сервере.
    • descr – имя описания квеста, показываемое игроку, когда берет квест у NCP, у которого можно взять, кроме этого квеста, еще и другой.

    Метод onEvent вызывается от Явы. Осуществляет начало квеста. Имеет параметры:
    • self – ссылка непосредственно на Tutorial Quest
    • event – строка для идентификации эвента для Явы.
    • st – ссылка на QuestState, для отслеживания текущего состояния игрока.

    В первой строке идет проверка на текущее состояние квеста непосредственно для игрока и состояние запивается в переменную ‘id’.
    Если квест только взят, то объявляем начало квеста (if id == CREATED : st.setState(STARTED)).
    Если квест уже выполнен, то ничего не делаем elif id == COMPLETED: pass)
    Если квест уже начат (STARTED), то вызывается функция проверки (check(), определенная выше) количества клыков у персонажа для завершения квеста. Мы не проверяем переменную ‘event’, т.к. в нашем примере (Tutorial quest) все события происходят от разговоров с NCP. Метод onEvent вызывается, если поговорить с NCP.

    И наконец, когда скелет квеста определен, мы создаем сам квест (и определяем его в самом сервере) и объявляем его.


    Код:
    QUEST     = Quest(201,"Tutorial", "Tutorial quest")
    CREATED   = State('Start',     QUEST)
    STARTED   = State('Started',   QUEST)
    COMPLETED = State('Completed', QUEST)

    Квест будет иметь id клиента – 201, идентификатор «Tutorial» и описание «Tutorial quest». Так же будет иметь 3 состояния: CREATED, STARTED, COMPLETED. Имена состояний могут использоваться для автоматического поиска необходимых .htm. Например для CREATED будет соответствовать 'Start.htm', для STARTED – ‘Started.htm’ и для COMPLETED будет показана 'Completed.htm'. Имена состояний используются так же для хранения состояния выполнения квеста в БД, когда игрок выходит из игры, так что имена не должны повторятся в пределах одного квеста.

    Так же мы должны определить начальное состояние квеста, когда игрок его только взял, и так же стартового NCP.


    Код:
    QUEST.setInitialState(CREATED)
    QUEST.addStartNpc(7056)


    Обратите внимание: в файле htm стартового NCP обязательно должна быть ссылка на квест:
    Код:
    <a action="bypass -h npc_%objectId%_Quest">


    Теперь необходимо добавить дроп для этого квеста при состоянии STARTED, для того, что бы получить необходимые вещи.

    Код:
    STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)


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

    Код:
    import sys
    from net.sf.l2j.gameserver.model.quest import State
    from net.sf.l2j.gameserver.model.quest import QuestState
    from net.sf.l2j.gameserver.model.quest.jython import QuestJython as JQuest

    KELTIR_NPC_ID = 12082
    FANGS_ITEM_ID = 1859
    DROP_RATE     = 500000
    WORLD_MAP_ITEM_ID = 1665


    def getCount(st) :
      return st.getQuestItemsCount(FANGS_ITEM_ID)

    def completed(st) :
      st.setState(COMPLETED)
      st.clearQuestDrops()
      st.takeItems(FANGS_ITEM_ID,-1)
      st.giveItems(WORLD_MAP_ITEM_ID,1)
      st.exitQuest(False)
      return

    def check(st) :
      if getCount(st) >= 4 :
        completed(st)
      return

    class Quest (JQuest):

      def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)

      def onEvent (self,event,st):
        id = st.getState()
        if   id == CREATED  : st.setState(STARTED)
        elif id == COMPLETED: pass
        elif id == STARTED  : check(st)
        return

    QUEST     = Quest(201,"Tutorial", "Tutorial quest")
    CREATED   = State('Start',     QUEST)
    STARTED   = State('Started',   QUEST)
    COMPLETED = State('Completed', QUEST)

    QUEST.setInitialState(CREATED)
    QUEST.addStartNpc(7056)

    STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)


    Теперь рассмотрим, как это работает.
    Игрок подходит к начальному NCP (в данном случае 7056), нажимает на «Quest». Квест будет создан и состояние квеста перейдет к CREATED и игроку будет показана страничка Start.htm с описанием квеста. Тогда метод onEvent, поле открытия странички Start.htm переведет состояние квеста в STARTED и игроку будет показана страничка Started.htm, где будет опсание того, как найти keltirs и .т.д.

    При состоянии STARTED будет зарегистрирован дроп «fangs» при убийстве keltirs. Игрок может вернуться к стартовому NCP и спросить о квесте – метод onEvent будет вызван снова. Если у игрока не хватает необходимого количества предметов, то метод check() не переведет квест в следующее состояние и Started.htm будет показана снова. Но если игрок собрал необходимее количество предметов (в данном случае 4 клыка), то метод check() вызовет метод completed() который переведет квест в новое состояние COMPLETED, заберет все клыки, даст карту мира, т.к. это награда за квест, покажет Completed.htm и завершит квест.

    Теперь давайте сделаем наш квест более похожим на то, что он должен из себя представлять.

    Прежде всего у нас есть 3 метода для объявления их в Яве – onTalk, onKill и onEvent. Если методы onTalk и onKill не объявлены, то за них все будет делать метод onEvent, т.е. определять квестовых монстров и вызывать диалоги NCP. Есть примечание, методы onTalk и onKill будут вызывать только диалоги с NCP в зависимости от текущего состояния квеста. Метод onKill будет вызываться только тогда, когда мы убиваем квестового монстра.

    Давайте рассмотрим как вызывается метод onKill при убийстве keltir в состоянии квеста STARTED:

    Код:
    STARTED.addKillId(KELTIR_NPC_ID)

    и метод onKill в классе Quest:

    Код:
    class Quest (JQuest):
      ...
      def onKill (self,npcId,st):
        if npcId == KELTIR_NPC_ID:
          n = getCount(st)
          if   n == 0:
              return "Chat0.htm"
          elif n == 1:
              return "Chat1.htm"
          elif n >= 4:
              return "Chat4.htm"
          return "Collected "+str(n)+" of 4 fangs"
        return


    Метод onKill (а так же метод onTalk) имеет следующие параметры:
    • self – квест
    • npcId – ID NCP, которого мы должны убивать (если это метод onTalk, то ID того NCP, с которым мы должны поговорить).
    • st – текущее состояние игрока.

    В этом методе мы проверяем и отмечаем, является ли убитый NCP keltir’ом. В основном эта проверка не нужна, т.к. у нас только KELTIR_NPC_ID.

    Затем проверяем количество предметов (в данном случае количество клыков), и если их вообще нет, то возвращаем строку "Chat0.htm", если только один предмет, то возвращаем строку "Chat1.htm", если же предметов 4 или больше, то "Chat4.htm". Если строка возвращена из методов onEvent, onKill или onTalk, то сервер покажет соответствующие htm. В Chat0.htm может иметь следующий текст: «Вы не имеете ни одного клыка, возвращайтесь позже, когда соберете 4 штуки и бла, бла, бла…», в Chat1.htm может быть следующий текст: «У Вас всего 1 клык, по этому соберите еще…». В Chat4.htm – «Вы собрали необходимое количество предметов, возвращайтесь к вашему тренеру, что бы завершить квест…»

    Примечание: если в строка return начинается с "", то будет показана страничка html с текстом, который стоит далее. Так вместо:


    Код:
    return "Chat4.htm"


    можно поставить:

    Код:
    return "<html><body>Return to your trainer to complete the quest</body></html>"


    Так же если строка заканчивается без .htm или в начале нет , то текст будет выведен, как системное сообщение в окне чата. В нашем случае мы сделаем так, что бы при каждом убийстве keltik выводилось системное сообщение: «Собрано N из 4-х клыков».

    Наш код для onKill имеет один недостаток. Он будет постоянно показывать Chat0.htm, Chat1.htm и Chat4.htm, нам же необходимо, что бы Chat0.htm и Chat1.htm показывались только один раз. Как нам это сделать? С помощью переменных.

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


    Код:
    def onKill (self,npcId,st):
    if npcId == KELTIR_NPC_ID:
    n = getCount(st)
    if n == 0:
    if st.get('chat0') == None :
    st.set("chat0", "true")
    return "Chat0.htm"
    elif n == 1:
    if st.get('chat1') == None :
    st.set("chat1", "true")
    return "Chat1.htm"
    elif n >= 4:
    return "Chat4.htm"
    return "Collected "+str(n)+" of 4 fangs"
    return


    Если у игрока нет клыков (n=0), то мы получаем занчение переменной 'chat0'. Когда метод onKill вызван в первый раз, то пока ни каких переменных не имеется и python возвращает значение None. В этом случае объявляется переменная и показывается диалог Chat0.htm. Когда мы убиваем keltir, но не получаем с него клык, функция st.get('chat0') возвращает строку true, а не None. И во второй раз окно с Chat0.htm не появится, но в окне чата появится строчка «Collected 0 of 4 fangs». По тому же принципу сделано и с Chat1.htm.

    Вот конечный рабочий вариант квеста:

    Код:
    import sys
    from net.sf.l2j.gameserver.model.quest import State
    from net.sf.l2j.gameserver.model.quest import QuestState
    from net.sf.l2j.gameserver.model.quest.jython import QuestJython as JQuest


    KELTIR_NPC_ID = 12082
    FANGS_ITEM_ID = 1859
    DROP_RATE = 500000

    WORLD_MAP_ITEM_ID = 1665


    def getCount(st) :
    return st.getQuestItemsCount(FANGS_ITEM_ID)

    def completed(st) :
    st.setState(COMPLETED)
    st.clearQuestDrops()
    st.takeItems(FANGS_ITEM_ID,-1)
    st.giveItems(WORLD_MAP_ITEM_ID,1)
    st.exitQuest(False)
    return

    def check(st) :
    if getCount(st) >= 4 :
    completed(st)
    return

    class Quest (JQuest):

    def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)


    Всем желаю удачи))


    Автор: Мо3олЬ

     

    Категория: Статьи | Добавил: TheVainglorious
    Просмотров: 606 | Загрузок: 0 | Рейтинг: 0.0/0
    Всего комментариев: 0
    Скачивать материалы, добавлять комментарии могут только зарегистрированные пользователи.
    [ Регистрация | Вход ]