Top.Mail.Ru

[Квесты] Создаём собственные квесты (часть 2)

[Скопировать ссылку]
admin Опубликовано 2024-9-17 19:36:47 | Показать все сообщения |Режим чтения Распечатать Назад Вперед

Зарегистрируйтесь сейчас чтобы найти еще больше друзей, и получить полноценный доступ ко всем функциям сайта!

Для просмотра Вам необходимо авторизоваться Если Вы еще не зарегистрированы, перейдите по ссылке:Зарегистрироваться

x
Хроники        Interlude
0 e; `# M8 [) F% S$ {Сборка        L2j0 a& m) m0 C' p) w! R; M
Обратите внимание: в файле htm стартового NCP обязательно должна быть ссылка на квест:) P' V2 R2 W& }1 e! }: M2 b
  1. STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код
Для этого квеста больше ничего не надо. Все необходимое для корректной работы квеста уже добавили. Вот полный текст квеста:
4 N3 Z$ m' T: z3 N
8 \5 V1 I, T; {9 D0 f; {; E
  1. if getCount(st) >= 4 :
    , E( S1 s5 p0 h" o$ w1 y! _
  2. completed(st)+ S7 g, ?* `) c. z
  3.   return
    8 k7 X' R2 c5 I0 k2 y' t; U0 e( j

  4. + f4 i. J$ q3 ]* t- I+ A
  5. class Quest (JQuest):
    : ?" H) U4 q& z0 I' Z; A0 F
  6.   def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)& o! @* m7 E2 I/ g% b
  7.   def onEvent (self,event,st):
    1 i% x- W; J) w4 U: ?
  8. id = st.getState()
    6 a/ m# V! ?4 }1 F
  9. if   id == CREATED  : st.setState(STARTED)
    ) q  d* }( Z: K' n- c9 }- F
  10. elif id == COMPLETED: pass- v% }; f1 T9 P8 |% C) p
  11. elif id == STARTED  : check(st)0 c& t0 Y/ q0 {$ y) u7 S
  12. return
    2 Y4 d3 `3 H, U# q) O) @
  13. 2 _$ @, C6 z: I" m& C' k# ~; S
  14. QUEST     = Quest(201,"Tutorial", "Tutorial quest")1 t; e# e, Z8 v. F
  15. CREATED   = State('Start',     QUEST)4 H, y5 J6 |' u) ?9 a
  16. STARTED   = State('Started',   QUEST)
    6 ^% `% v2 @2 L/ q! f) w
  17. COMPLETED = State('Completed', QUEST)1 x! C" x) n0 E: b+ x) z

  18. ) z. Z* U) q  t  \5 j) ]1 o1 l6 i
  19. QUEST.setInitialState(CREATED)* F" v" E& O. Y2 Z8 r  {- l
  20. QUEST.addStartNpc(7056); n0 m4 A* g- g
  21. STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код
Теперь рассмотрим, как это работает.
- Q+ n( Y* I1 U! k0 D. CИгрок подходит к начальному NCP (в данном случае 7056), нажимает на «Quest». Квест будет создан и состояние квеста перейдет к CREATED и игроку будет показана страничка Start.htm с описанием квеста. Тогда метод onEvent, поле открытия странички Start.htm переведет состояние квеста в STARTED и игроку будет показана страничка Started.htm, где будет опсание того, как найти keltirs и .т.д.- d. a# L" F! W6 J. {" p9 s

  p' B6 B8 I3 P$ c; H$ B7 y

9 ^. T6 X. D# e0 v7 zПри состоянии STARTED будет зарегистрирован дроп «fangs» при убийстве keltirs. Игрок может вернуться к стартовому NCP и спросить о квесте – метод onEvent будет вызван снова. Если у игрока не хватает необходимого количества предметов, то метод check() не переведет квест в следующее состояние и Started.htm будет показана снова. Но если игрок собрал необходимее количество предметов (в данном случае 4 клыка), то метод check() вызовет метод completed() который переведет квест в новое состояние COMPLETED, заберет все клыки, даст карту мира, т.к. это награда за квест, покажет Completed.htm и завершит квест.
0 u( Q0 Z8 \8 p" N9 V5 |1 o& X  i: e
8 A/ h' j  `1 s: J9 a
Теперь давайте сделаем наш квест более похожим на то, что он должен из себя представлять.1 G" t  v- L" r1 s1 ^: m7 N; J4 f
Прежде всего у нас есть 3 метода для объявления их в Яве – onTalk, onKill и onEvent. Если методы onTalk и onKill не объявлены, то за них все будет делать метод onEvent, т.е. определять квестовых монстров и вызывать диалоги NCP. Есть примечание, методы onTalk и onKill будут вызывать только диалоги с NCP в зависимости от текущего состояния квеста. Метод onKill будет вызываться только тогда, когда мы убиваем квестового монстра.) M( N1 `& ]: A/ ?( ^, Z% Z

3 q/ S! y1 T9 m. V3 |& J( Q+ V

3 ]4 z2 K. j* Y) I5 fДавайте рассмотрим как вызывается метод onKill при убийстве keltir в состоянии квеста STARTED:
& |5 z7 S, U3 p1 w$ |4 q* O4 o$ M$ b( x
  1. STARTED.addKillId(KELTIR_NPC_ID)
Скопировать код
и метод onKill в классе Quest:) c+ j7 i+ c  F, o

9 o! d0 w2 [; _1 ]7 x
  1. class Quest (JQuest):
    ( }1 y& ~  [# a8 S
  2.   ...
    0 m) B, Z8 _7 G4 |/ E" y
  3.   def onKill (self,npcId,st):
    6 K2 Y3 O" X/ {
  4. if npcId == KELTIR_NPC_ID:
      K+ ]# t0 d4 g
  5.    n = getCount(st)
    ( g0 ~' G$ r( H9 z* l
  6.    if   n == 0:
    7 y0 `+ x; C' v# x" ^* m7 ^6 n/ v
  7.        return "Chat0.htm"
    5 H& |3 q# a! {- R, ]
  8.    elif n == 1:0 j( r3 b# Z0 E# h7 C& |
  9.        return "Chat1.htm"2 E+ U- p  Q8 G/ R2 G& |) U
  10.    elif n >= 4:3 L$ B7 g2 i  o* F
  11.        return "Chat4.htm"
    ! H9 o9 Y  p& A/ H
  12.    return "Collected "+str(n)+" of 4 fangs"
    % k( `7 `' X, @# T/ m8 }* v9 [
  13. return
Скопировать код
Метод onKill (а так же метод onTalk) имеет следующие параметры:
! x- o: X! L+ u8 v6 Z
8 F  A- A4 z$ s& r3 a  {
5 ^  i. P& B0 R) g/ r( S( w
• self – квест- w2 }* P$ }) x+ w4 d6 E" W
• npcId – ID NCP, которого мы должны убивать (если это метод onTalk, то ID того NCP, с которым мы должны поговорить).7 f, |  d. m9 E
• st – текущее состояние игрока.1 H) C6 Z  p* t6 C5 y) S

5 d4 ?  X# X2 j+ o
6 v# A2 U, B) O8 z7 Q0 c# P
В этом методе мы проверяем и отмечаем, является ли убитый NCP keltir’ом. В основном эта проверка не нужна, т.к. у нас только KELTIR_NPC_ID.
& t+ o5 ?8 j% k9 Y( m' n
( O# ]( _0 ~- C5 E) k

# o' o* [6 c9 {) ]3 l* qЗатем проверяем количество предметов (в данном случае количество клыков), и если их вообще нет, то возвращаем строку "Chat0.htm", если только один предмет, то возвращаем строку "Chat1.htm", если же предметов 4 или больше, то "Chat4.htm". Если строка возвращена из методов onEvent, onKill или onTalk, то сервер покажет соответствующие htm. В Chat0.htm может иметь следующий текст: «Вы не имеете ни одного клыка, возвращайтесь позже, когда соберете 4 штуки и бла, бла, бла…», в Chat1.htm может быть следующий текст: «У Вас всего 1 клык, по этому соберите еще…». В Chat4.htm – «Вы собрали необходимое количество предметов, возвращайтесь к вашему тренеру, что бы завершить квест…»
; n$ Q8 E6 l' L6 g' o, `5 Z8 X0 \( Z# O# V  ]4 [: i+ i

5 C8 Y- V' R# L2 E& CПримечание: если в строка return начинается с "<html>", то будет показана страничка html с текстом, который стоит далее. Так вместо:5 x. R9 o$ H1 c/ ?7 B1 a
return "Chat4.htm"
+ h3 C+ B/ t  K0 Y: ]
# b; K5 G2 e, M2 @* Z! t# Z6 c

# V* n' \  n4 |) ^9 E% e9 Wможно поставить:6 H9 i2 H" q5 e- M) i
  1. return "<html><body>Return to your trainer to complete the quest</body></html>"
Скопировать код
Так же если строка заканчивается без .htm или в начале нет <html>, то текст будет выведен, как системное сообщение в окне чата. В нашем случае мы сделаем так, что бы при каждом убийстве keltik выводилось системное сообщение: «Собрано N из 4-х клыков».
; ?( S8 m" ?! y3 |4 q
0 \( w$ T' t6 g) a+ u
" l# n: v' N- C" \1 R  O
Наш код для onKill имеет один недостаток. Он будет постоянно показывать Chat0.htm, Chat1.htm и Chat4.htm, нам же необходимо, что бы Chat0.htm и Chat1.htm показывались только один раз. Как нам это сделать? С помощью переменных.
- q2 V3 W2 B9 E  g" @' M+ l  u* ^  B* }1 r9 c  c6 y" E4 {2 u9 ]7 L

) d, h/ F& W' K0 t$ x$ XВ каждом квесте строки могут храниться с помощью переменных. Эти переменные сохраняются в Вашей БД. В каждом методе мы можем назначить, прочитать и удалить переменные. Давайте изменим метод onKill, так что бы каждый диалог вызывался только один раз.$ G6 k6 x0 O8 {6 \0 m( @
  1. def onKill (self,npcId,st):% l/ E9 m' X" `) Y
  2. if npcId == KELTIR_NPC_ID:+ g' o- X5 J$ w# f: z
  3. n = getCount(st)
      D) H5 l  I0 [
  4. if n == 0:1 g9 X3 J  ]; X: |  e8 v: w4 X
  5. if st.get('chat0') == None :0 o$ @- n  z8 K* Y
  6. st.set("chat0", "true")
    8 d/ g+ O) D, q* c9 a. k7 n
  7. return "Chat0.htm"3 a5 \$ |. X1 O( h1 \
  8. elif n == 1:7 @0 [) i- }" x: w8 g/ l. o
  9. if st.get('chat1') == None :
    ! D, G& s& H! L& k3 x
  10. st.set("chat1", "true")
    4 W; C# W0 R/ m, v& m9 e- P2 a- D
  11. return "Chat1.htm", @; E, m7 p- t/ ~
  12. elif n >= 4:  w2 e7 [: h' p) D
  13. return "Chat4.htm"
    , p  E% T3 n5 \7 V2 A
  14. return "Collected "+str(n)+" of 4 fangs"
    ! y2 y$ u" [. ]- B& ?' g9 o" ^# V
  15. return
Скопировать код
Если у игрока нет клыков (n=0), то мы получаем занчение переменной 'chat0'. Когда метод onKill вызван в первый раз, то пока ни каких переменных не имеется и python возвращает значение None. В этом случае объявляется переменная и показывается диалог Chat0.htm. Когда мы убиваем keltir, но не получаем с него клык, функция st.get('chat0') возвращает строку true, а не None. И во второй раз окно с Chat0.htm не появится, но в окне чата появится строчка «Collected 0 of 4 fangs». По тому же принципу сделано и с Chat1.htm." H7 O3 @$ F; F6 Z! S
9 N& f/ |6 T/ m  W5 c9 N  }

/ S' n/ w) w) ~4 S/ BВот конечный рабочий вариант квеста:8 J  X4 z) y2 h' F& f; O0 T
  1. import sys+ j# n' p. M2 \
  2. from net.sf.l2j.gameserver.model.quest import State" |. m7 V5 V' e9 L
  3. from net.sf.l2j.gameserver.model.quest import QuestState
    4 h. F0 E* R5 Q# K
  4. from net.sf.l2j.gameserver.model.quest.jython import QuestJython as JQuest' ?. m. Z6 d) ?0 R6 L- i9 g2 y; h- ^

  5. 2 t, T- Q. u1 R$ _. W$ m' f7 _7 |& A
  6. KELTIR_NPC_ID = 12082
    & E) m% [" m, v
  7. FANGS_ITEM_ID = 1859: _0 f( U9 O% H/ L
  8. DROP_RATE    = 500000
    - F9 H. D( e# `3 y' O/ t  u3 |

  9. 7 x. d2 n( n/ Y$ d) V. d7 V
  10. WORLD_MAP_ITEM_ID = 1665; ?1 @( J6 v& o% z) g& ?

  11. - n. k" d9 B; V( G1 k$ e7 n
  12. def getCount(st) :
    2 d. t4 {5 L& ?$ u
  13. return st.getQuestItemsCount(FANGS_ITEM_ID)
    * p+ n% b; g7 `+ G/ n4 ]

  14. + `- q- I  e6 M6 s( k2 V
  15. def completed(st) :+ v4 X5 L1 U/ C6 u1 ~+ J. K
  16. st.setState(COMPLETED)
    $ J2 `; E6 @% n( J- s, |) M
  17. st.clearQuestDrops()
    - I! a: {0 P" g. ]5 o, L8 V
  18. st.takeItems(FANGS_ITEM_ID,-1)9 O  e) M- i8 d
  19. st.giveItems(WORLD_MAP_ITEM_ID,1)+ ?5 d' a3 d$ t
  20. st.exitQuest(False)
    ) S* T2 v7 w# d( p5 f2 _
  21. return( E; R4 `; ^/ K; k! m
  22. : {$ _8 ?; I! y4 I, P
  23. def check(st) :
    ' N; X. o7 N7 l7 P# }
  24. if getCount(st) >= 4 :
    $ Z3 |* y" r" r2 k- M7 i
  25. completed(st)
    9 E4 q* E% p, W8 Y+ Z* @, W
  26. return
    $ N$ S2 F# U& A, j& a

  27. : m$ m0 Y& D+ e; G9 c! O
  28. class Quest (JQuest):
    2 w7 m: e6 k" Z1 N$ A* ?0 |

  29. 8 u, a+ o; X' e: U
  30. def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)" W& A: ]+ N+ R3 V. p

  31. 5 m  i, r6 \' ~0 z! K7 Y2 M/ u
  32. def onEvent (self,event,st):
    5 c: u2 D/ j; ]. |
  33. id = st.getState()
    % G, p; b" F, T3 ~5 |$ f
  34. if id == CREATED : st.setState(STARTED)
    7 r+ `9 O* h9 ~( \/ [8 }& [1 _) [$ A
  35. elif id == COMPLETED: pass
    7 n) [. B( U3 U4 L; ~
  36. elif id == STARTED : check(st)
    7 x9 Q' E8 U) u2 j! o8 R; j
  37. return4 P8 P9 X7 J; J& e

  38. ; w, q4 H; e. h" n5 y. h- b: j0 D
  39. def onKill (self,npcId,st):
      L! V( B- D4 S5 s) o# @
  40. if npcId == KELTIR_NPC_ID:
    0 W2 u* z9 Y9 U2 t( P. |
  41. n = getCount(st)
    0 l5 G" ^3 K& [2 n
  42. if n == 0:! A6 o6 y3 {3 {" p) P
  43. if st.get('chat0') == None :
    & ]3 D9 R% R$ }: p0 b
  44. st.set("chat0", "true")
    0 S9 E4 \' T- F0 U( @& O3 q% [
  45. return "Chat0.htm"' V# ~, P( {7 O9 H- V* c
  46. elif n == 1:4 i# W6 \! u' }
  47. if st.get('chat1') == None :" Z( J! l. Y5 u
  48. st.set("chat1", "true")
    * o! |; d1 Y2 _6 o; |
  49. return "Chat1.htm"! R7 j4 Z2 y: @/ i" g+ I
  50. elif n >= 4:
    + a3 S/ \7 [( T2 N/ \. v% A* J& w
  51. return "Chat4.htm"$ Q0 c3 |. [: R8 ?$ X- L0 f
  52. return "Collect "+str(n)+" of 4 fangs"
    3 V; d3 K* R4 A/ ?7 I
  53. return
    + r: t8 x' ?6 I

  54. ; m/ F/ A; }$ b5 b4 |. ^* d& B
  55. QUEST    = Quest(201, "Tutorial", "Tutorial quest")
    6 k' O7 C  Z$ ~% ]
  56. CREATED = State('Start',    QUEST)
    9 M5 _1 {8 ]. y) ?- @
  57. STARTED = State('Started', QUEST)
    " s9 d% |9 H4 W& j3 ?% `
  58. COMPLETED = State('Completed', QUEST)
    4 X% a, N$ k/ ]7 I" S

  59. & o  _) z3 d& T# p- d
  60. QUEST.setInitialState(CREATED)9 Z1 X1 }5 Q5 a7 g3 ^; H' v
  61. QUEST.addStartNpc(7056)
    ) h, |# y" }! h0 B8 B
  62. QUEST.addStartNpc(7012)
    4 R7 g; H3 @0 R( b: A
  63. QUEST.addStartNpc(7009)9 u  Y( ~" h  Z
  64. QUEST.addStartNpc(7011)9 ?, `2 h. Z8 F

  65. * q  p. F0 X) x! [3 s* L
  66. STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
    7 H0 O' w/ |8 n4 L* t! [" c% U% r
  67. STARTED.addKillId(KELTIR_NPC_ID)
    % T3 [" @! o2 q2 p. X2 S$ E
  68. STARTED.addTalkId(7056)
    1 C5 \* L- {/ i! S6 n$ [
  69. STARTED.addTalkI d(7012)
    ; H0 K) i' G( B
  70. STARTED.addTalkId(7009)
    # R! {$ N5 x- Y* |) {6 W
  71. STARTED.addTalkId(7011)
Скопировать код

  W6 R% o* X5 d# X' E+ q* D# W& G* G" X6 M
Чтобы ответить, вам надо авторизироваться в системе Вход | Зарегистрироваться

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

Опубликовать
Сектор творческих людей
Горячая линия

638638758

С понедельника по воскресенье с 9:00 до 23:00

Обратной связь

admin@artace.ru Онлайн

QR-код

Powered by Discuz! X3.5© 2001-2021 Comsenz Inc.