Перейти к содержанию
Авторизация  
««†KENVOOD†»»

Учимся Писать Квесты На Python (часть 2)

Рекомендуемые сообщения

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

 

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>", то будет показана страничка 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.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

  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)

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
Авторизация  

  • Последние посетители   0 пользователей онлайн

    Ни одного зарегистрированного пользователя не просматривает данную страницу

×
×
  • Создать...