Регистрация Главная Сообщество
Сообщения за день Справка Регистрация
Навигация
Zhyk.org LIVE! Реклама на Zhyk.org Правила Форума Награды и достижения Доска "почета"

Ответ
 
Опции темы
Старый 28.06.2012, 15:55   #1
 Сержант
Аватар для КириллZ
 
КириллZ гордость нацииКириллZ гордость нацииКириллZ гордость нацииКириллZ гордость нацииКириллZ гордость нацииКириллZ гордость нацииКириллZ гордость нацииКириллZ гордость нацииКириллZ гордость нацииКириллZ гордость нацииКириллZ гордость нации
Регистрация: 29.03.2011
Сообщений: 155
Популярность: 3277
Сказал(а) спасибо: 325
Поблагодарили 145 раз(а) в 101 сообщениях
 
По умолчанию Мануал по написанию квестов на python

Первое что нужно сделать, это добавить необходимые Java классы в квест.(пример) - (net.sf.l2j.gameserver.model.quest)

Код:
import sys
from net.sf.l2dc.gameserver.model.quest import State
from net.sf.l2dc.gameserver.model.quest import QuestState
from net.sf.l2dcgameserver.model.quest.jython import QuestJython as JQuest
Класс QuestJython (импортирован под названием JQuest) содержит информацию о квестах.
Класс State используется для того, что бы описать информацию о состоянии квеста.
Класс QuestState применяется непосредственно для отслеживания состояния игрока,
о ходе выполнения квеста или части квеста.
Затем необходимо добавить несколько констант, что сделает квест удобочитаемым.
Если этого не сделать, то могут возникнуть сложности с редактированием квеста в будущем.
Константы нашего квеста – это ID NPС и итемов.

Код:
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 – имя описания квеста, показываемое игроку, когда берет квест у NPC, у которого можно взять, кроме этого квеста, еще и другой.

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

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

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

Код:
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'. Имена состояний используются так же для хранения состояния выполнения
квеста в БД, когда игрок выходит из игры, так что имена не должны повторятся в пределах одного квеста.

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

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

Обратите внимание: в файле htm стартового NPC обязательно должна быть ссылка на квест:

Код:
<a action="bypass -h npc_%objectId%_QuestEvent">
Теперь необходимо добавить дроп для этого квеста при состоянии STARTED, для того, что бы получить необходимые вещи.

Код:
STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Для этого квеста больше ничего не надо. Все необходимое для корректной работы квеста уже добавили. Вот полный текст квеста:

Код:
import sys
from net.sf.l2dc.gameserver.model.quest import State
from net.sf.l2dc.gameserver.model.quest import QuestState
from net.sf.l2dc.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)
Теперь рассмотрим, как это работает.
Игрок подходит к начальному NPC (в данном случае 7056), нажимает на «Quest».
Квест будет создан и состояние квеста перейдет к CREATED и игроку будет показана страничка Start.htm с описанием квеста.
Тогда метод onEvent, поле открытия странички Start.htm переведет состояние квеста в STARTED и игроку будет показана
страничка Started.htm, где будет опсание того, как найти keltirs и .т.д.

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

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

Прежде всего у нас есть 3 метода для объявления их в Яве – onTalk, onKill и onEvent.
Если методы onTalk и onKill не объявлены, то за них все будет делать метод onEvent, т.е. определять квестовых монстров
и вызывать диалоги NPC. Есть примечание, методы onTalk и onKill будут вызывать только диалоги с NPC в зависимости от
текущего состояния квеста. Метод 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 NPC, которого мы должны убивать
(если это метод onTalk, то ID того NPC, с которым мы должны поговорить).
• st – текущее состояние игрока.

В этом методе мы проверяем и отмечаем, является ли убитый NPC 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", то будет показана страничка html с текстом, который стоит далее.
Так вместо:

Код:
return "Chat4.htm"
можно поставить:

Код:
return "<html><body>Return to your trainer to complete the quest</body></html>"
Так же если строка заканчивается без .htm или в начале нет открывающего тега html,
то текст будет выведен, как системное сообщение в окне чата.
В нашем случае мы сделаем так, что бы при каждом убийстве 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.l2dc.gameserver.model.quest import State
from net.sf.l2dc.gameserver.model.quest import QuestState
from net.sf.l2dc.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

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 "Collect "+str(n)+" of 4 fangs"
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)
QUEST.addStartNpc(7012)
QUEST.addStartNpc(7009)
QUEST.addStartNpc(7011)

STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
STARTED.addKillId(KELTIR_NPC_ID)
STARTED.addTalkId(7056)
STARTED.addTalkI d(7012)
STARTED.addTalkId(7009)
STARTED.addTalkId(7011)
  Ответить с цитированием
Ответ


Ваши права в разделе
Вы не можете создавать новые темы
Вы не можете отвечать в темах
Вы не можете прикреплять вложения
Вы не можете редактировать свои сообщения

BB коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.

Быстрый переход

Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
[Руководство] Мануал по написанию бота на delphi7 OneShot Свободное обсуждение 4 11.02.2011 16:46
мануал по написанию эвента !!! jekajkee Lineage 2 1 20.03.2010 14:00
[Файл] Python v.2.0.0 AsPin Программы и приложения для смартфонов 0 15.03.2010 18:20

Заявление об ответственности / Список мошенников

Часовой пояс GMT +4, время: 09:02.

Пишите нам: [email protected]
Copyright © 2024 vBulletin Solutions, Inc.
Translate: zCarot. Webdesign by DevArt (Fox)
G-gaMe! Team production | Since 2008
Hosted by GShost.net