Top.Mail.Ru

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

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

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

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

x
Хроники        Interlude
" V$ o! c5 o# Q8 q; yСборка        L2j- m/ p3 e, I* P. A
Обратите внимание: в файле htm стартового NCP обязательно должна быть ссылка на квест:& S0 ^% r' B% i6 Q0 X' [
  1. STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код
Для этого квеста больше ничего не надо. Все необходимое для корректной работы квеста уже добавили. Вот полный текст квеста:
. K, l( V& f( n! Q! e7 I& T! ]8 G  }4 ?* g# Y$ j
  1. if getCount(st) >= 4 :
    2 }6 `# b. a4 m3 J% T
  2. completed(st)
    ' z: J& e8 Y* X* {
  3.   return
    " p' h, Z* r# C& n1 G) i
  4. ) k) j2 Z* A- ~
  5. class Quest (JQuest):
    6 |" s0 Q) Y- W7 w, O6 U# `( [
  6.   def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)
    3 j- J  s0 z. ^+ w& E
  7.   def onEvent (self,event,st):
    3 N! v* u$ k# F/ R5 e7 a8 E
  8. id = st.getState()) i- z2 E+ ]' R+ }- m0 e
  9. if   id == CREATED  : st.setState(STARTED)
    % M$ I7 v  d3 {9 g+ G* s% m: ]( }' s
  10. elif id == COMPLETED: pass' M/ s" @) L' c7 ~& u$ d7 p! o: k  N
  11. elif id == STARTED  : check(st)5 u; h, c/ y( I. h
  12. return
    ; @. S( D' f- @% Q3 H) l+ m) a$ S

  13. 5 {# f! s8 g* ~0 S( w
  14. QUEST     = Quest(201,"Tutorial", "Tutorial quest")/ ]' z; y  x2 Q" x+ s
  15. CREATED   = State('Start',     QUEST)" L' ?- w* O4 W0 d- o
  16. STARTED   = State('Started',   QUEST)
    0 s, e( B2 D1 J1 Z+ g3 F' `
  17. COMPLETED = State('Completed', QUEST)7 U8 s2 k% O3 _2 m7 t: V% L0 U

  18. 9 D% }" G( ~* M% h, H( G
  19. QUEST.setInitialState(CREATED)
    5 O1 Z+ N) Q2 L0 W$ A
  20. QUEST.addStartNpc(7056)3 N9 F* P3 T) G( B8 j8 t1 T
  21. STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код
Теперь рассмотрим, как это работает.
) c. q: O- u8 }* ^Игрок подходит к начальному NCP (в данном случае 7056), нажимает на «Quest». Квест будет создан и состояние квеста перейдет к CREATED и игроку будет показана страничка Start.htm с описанием квеста. Тогда метод onEvent, поле открытия странички Start.htm переведет состояние квеста в STARTED и игроку будет показана страничка Started.htm, где будет опсание того, как найти keltirs и .т.д.0 g6 x: {% I0 P& B% V- e7 k$ S
  a& _. K1 R3 w8 {$ m; P, P
( n/ q( e. i0 c
При состоянии STARTED будет зарегистрирован дроп «fangs» при убийстве keltirs. Игрок может вернуться к стартовому NCP и спросить о квесте – метод onEvent будет вызван снова. Если у игрока не хватает необходимого количества предметов, то метод check() не переведет квест в следующее состояние и Started.htm будет показана снова. Но если игрок собрал необходимее количество предметов (в данном случае 4 клыка), то метод check() вызовет метод completed() который переведет квест в новое состояние COMPLETED, заберет все клыки, даст карту мира, т.к. это награда за квест, покажет Completed.htm и завершит квест.2 Z* [+ a+ w2 j- q, V- \) J0 t7 v
* `' Y4 w6 C  \6 l% {2 S3 _

: O0 ^! G9 H/ gТеперь давайте сделаем наш квест более похожим на то, что он должен из себя представлять." x. u' c3 H. r' L  {) ^
Прежде всего у нас есть 3 метода для объявления их в Яве – onTalk, onKill и onEvent. Если методы onTalk и onKill не объявлены, то за них все будет делать метод onEvent, т.е. определять квестовых монстров и вызывать диалоги NCP. Есть примечание, методы onTalk и onKill будут вызывать только диалоги с NCP в зависимости от текущего состояния квеста. Метод onKill будет вызываться только тогда, когда мы убиваем квестового монстра./ M; A6 q" I+ a. T  D8 O

4 b  E4 E- j+ U6 J( b' `4 t

' D# o) c1 C4 E+ K$ nДавайте рассмотрим как вызывается метод onKill при убийстве keltir в состоянии квеста STARTED:& T) x8 E$ U5 U8 h. B- u
  1. STARTED.addKillId(KELTIR_NPC_ID)
Скопировать код
и метод onKill в классе Quest:* W0 }/ I: F7 J' U" j2 e$ M: W3 t

, D- T& t2 z& L% @/ g- W
  1. class Quest (JQuest):6 i* d' j) |, y: {( _, x
  2.   ...9 y" o8 P! C4 K7 }6 e9 K# A
  3.   def onKill (self,npcId,st):
    # J$ ^0 K) k3 Q  L
  4. if npcId == KELTIR_NPC_ID:/ ~0 Z+ Y! G5 G' y: |4 a
  5.    n = getCount(st)
    & H% Q6 C8 [# M1 L% t
  6.    if   n == 0:& u, d" {# X' ], o8 z/ c" b
  7.        return "Chat0.htm"
    - h: Y/ p( O) A$ X! t" T
  8.    elif n == 1:+ T2 K3 m( ?4 Z- X. C- g' U
  9.        return "Chat1.htm"! b1 n% l7 G1 \7 i* S/ g2 K5 F
  10.    elif n >= 4:$ e6 q/ d: q; Z: p; J* a- `
  11.        return "Chat4.htm"6 n# ?" D1 x/ z- e- }
  12.    return "Collected "+str(n)+" of 4 fangs"
    * S1 F$ B# l) i2 c- {% j$ v$ q
  13. return
Скопировать код
Метод onKill (а так же метод onTalk) имеет следующие параметры:
+ K- a0 O& d5 M  V; a% j" n# Z( J5 W* J' }
+ s! }2 a/ V3 i+ S7 M+ }9 B5 j
• self – квест, X) r6 k) B# F  q$ T$ n
• npcId – ID NCP, которого мы должны убивать (если это метод onTalk, то ID того NCP, с которым мы должны поговорить).5 G% o# T4 f% \  s
• st – текущее состояние игрока.
* w% E1 y: D) b5 V
- d. q' v3 c$ i$ n  y5 A
" g9 h, A7 O0 [* x7 m
В этом методе мы проверяем и отмечаем, является ли убитый NCP keltir’ом. В основном эта проверка не нужна, т.к. у нас только KELTIR_NPC_ID.
3 \/ A4 }( ~" o0 V8 i/ u
; B4 A$ y; c/ \3 Y1 C: _6 Y

9 r! }. a) _1 g4 i# qЗатем проверяем количество предметов (в данном случае количество клыков), и если их вообще нет, то возвращаем строку "Chat0.htm", если только один предмет, то возвращаем строку "Chat1.htm", если же предметов 4 или больше, то "Chat4.htm". Если строка возвращена из методов onEvent, onKill или onTalk, то сервер покажет соответствующие htm. В Chat0.htm может иметь следующий текст: «Вы не имеете ни одного клыка, возвращайтесь позже, когда соберете 4 штуки и бла, бла, бла…», в Chat1.htm может быть следующий текст: «У Вас всего 1 клык, по этому соберите еще…». В Chat4.htm – «Вы собрали необходимое количество предметов, возвращайтесь к вашему тренеру, что бы завершить квест…»9 V5 z7 h% Q5 u! i
6 |0 @! M, H# n. ]3 ?
, F6 |, r' D- w. G' S) z
Примечание: если в строка return начинается с "<html>", то будет показана страничка html с текстом, который стоит далее. Так вместо:5 @3 o- k& q7 X: f) W. _: _
return "Chat4.htm"+ i! `& ~  d  u5 R

$ R; l6 ]0 v2 `" x, J6 S% a
- J3 H- A8 v8 H# G; `( A8 s
можно поставить:! A& l) J( @" ~/ E1 [3 }
  1. return "<html><body>Return to your trainer to complete the quest</body></html>"
Скопировать код
Так же если строка заканчивается без .htm или в начале нет <html>, то текст будет выведен, как системное сообщение в окне чата. В нашем случае мы сделаем так, что бы при каждом убийстве keltik выводилось системное сообщение: «Собрано N из 4-х клыков».
% h( `0 B/ o6 Q- [+ T
: ^) o1 ]& ]: r3 i7 _5 V
' k1 G# p$ `( F
Наш код для onKill имеет один недостаток. Он будет постоянно показывать Chat0.htm, Chat1.htm и Chat4.htm, нам же необходимо, что бы Chat0.htm и Chat1.htm показывались только один раз. Как нам это сделать? С помощью переменных." s% C& W: @8 t+ t4 o0 H# W, a  R
- f+ M" p  _6 z* o9 i

" Y  ~  }. s& _0 g* I8 TВ каждом квесте строки могут храниться с помощью переменных. Эти переменные сохраняются в Вашей БД. В каждом методе мы можем назначить, прочитать и удалить переменные. Давайте изменим метод onKill, так что бы каждый диалог вызывался только один раз.( T9 c# p% T* k) C2 ^8 q% T
  1. def onKill (self,npcId,st):8 `0 L: W2 {# h3 F2 j! M  o
  2. if npcId == KELTIR_NPC_ID:1 c+ ]3 z3 X. T3 ~" y% z9 u2 @
  3. n = getCount(st)
    6 `( n1 p1 I* Y* Y: B: e8 F
  4. if n == 0:3 X. ~4 A& w- J0 o: d
  5. if st.get('chat0') == None :
    $ \7 \: }' x; F2 d# s. Q; e0 `
  6. st.set("chat0", "true")" g2 F- f4 S$ r1 ]4 y$ Q. S" p2 v& z
  7. return "Chat0.htm"
    # A2 y  C6 r7 Q) S4 W( d9 W1 z1 U/ m
  8. elif n == 1:
    1 _7 ?2 u' Q! y
  9. if st.get('chat1') == None :2 _* V! R- z( y
  10. st.set("chat1", "true"). \) m* b% }5 p6 @' o6 F6 a4 g
  11. return "Chat1.htm"
    % v4 Y" ~* c& d2 i. n8 M0 I
  12. elif n >= 4:% [/ ^& a/ i. `
  13. return "Chat4.htm"
    # w- q$ R0 m! l. L
  14. return "Collected "+str(n)+" of 4 fangs"! X% K  Z5 }4 v2 n% ~( G, U% |& n% C
  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.
2 W0 }9 o6 {; a" s. a
# T8 D3 E9 a1 e
& F: D  l7 _9 l5 p$ R8 c$ B, E
Вот конечный рабочий вариант квеста:
  ^! E% t  C$ I7 }: v. s5 R: M
  1. import sys
    2 q2 T' h: Q& k! s
  2. from net.sf.l2j.gameserver.model.quest import State
    - l$ b* ~; L+ _9 X
  3. from net.sf.l2j.gameserver.model.quest import QuestState1 k# y  g! J( _
  4. from net.sf.l2j.gameserver.model.quest.jython import QuestJython as JQuest
    ; I' ]* l1 y- X

  5. # ^1 K+ @0 N* |) B/ M
  6. KELTIR_NPC_ID = 12082
    , v1 a/ I4 l# [& B) e
  7. FANGS_ITEM_ID = 1859
    ) y  C& v# j( _5 ?7 K1 E# n
  8. DROP_RATE    = 500000
    ( d1 S0 o. k: V1 k8 B, }* d  l6 z

  9. 3 n9 L; j6 F$ X' s" b3 ]; v( \0 h( M
  10. WORLD_MAP_ITEM_ID = 16653 o( v$ A8 T( v+ }. v( F

  11. 5 H  Z7 A% r6 i/ [6 E
  12. def getCount(st) :" N4 s; ~$ R0 s  t
  13. return st.getQuestItemsCount(FANGS_ITEM_ID)8 G7 o) Z* T5 x* R3 H; T

  14. 9 S; e& p7 E$ ?" Q# A
  15. def completed(st) :
    % R# h, |+ M. J; O
  16. st.setState(COMPLETED)
    - V0 O6 D5 ^/ _# m; u" d: }
  17. st.clearQuestDrops()- o5 i, L3 u8 }6 ~+ }0 s8 w
  18. st.takeItems(FANGS_ITEM_ID,-1)' T: t2 A9 [7 K) A4 }% a( {+ @) {6 ^8 a
  19. st.giveItems(WORLD_MAP_ITEM_ID,1)) B  f& G" U$ _3 {3 X- a# E0 v
  20. st.exitQuest(False)
    / g4 R& j  q3 }7 w
  21. return3 J3 I! E4 G" Q. g8 ~3 i7 |: d
  22. ' q9 U- z- w- P0 z6 H: a% p
  23. def check(st) :2 f, T9 F. B7 \$ z
  24. if getCount(st) >= 4 :* `( B8 F, l( d  o8 T4 y
  25. completed(st)
    ) G( M8 a$ A! L1 O) G& w1 w9 @& s
  26. return9 r) v9 N% n& v

  27. ' N- c* {9 `# Z# F
  28. class Quest (JQuest):# g& j0 ~6 C3 Y& v

  29. & B7 y( V4 s4 |
  30. def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)
    - F% \: n' ]+ `1 _$ T
  31. + X9 m: ]( h  U3 x) ]( M
  32. def onEvent (self,event,st):
    $ s8 l0 W, t, M/ q! q$ {+ Q5 q
  33. id = st.getState()
      Q/ C1 N! w# L9 ?* v
  34. if id == CREATED : st.setState(STARTED)  o/ P* x; O8 h, L" l. S
  35. elif id == COMPLETED: pass
    , e  O- F" }: D0 p1 k8 ~
  36. elif id == STARTED : check(st)
      c" H# s$ D& x+ i/ H2 S
  37. return
    & a$ T$ i* G% |

  38. ( \4 ]8 B6 [  P0 I" h% S
  39. def onKill (self,npcId,st):
      m# ^8 j( m, k/ _" c9 Y9 R, l) Z) o
  40. if npcId == KELTIR_NPC_ID:
      J& O( b7 q+ H1 G5 O
  41. n = getCount(st)( u8 l3 i9 h; Y! M
  42. if n == 0:" p" Y- X8 J2 y, O7 E
  43. if st.get('chat0') == None :
    . {8 b& {" }; n. N7 T6 w/ s
  44. st.set("chat0", "true")
      y& [) k$ K1 k# q$ i5 o
  45. return "Chat0.htm"% f0 @) h" H* c, t
  46. elif n == 1:
    5 U) _9 u0 W2 T, y! P
  47. if st.get('chat1') == None :
    & c; v5 p- M/ Q
  48. st.set("chat1", "true")) k% m! G2 c& H3 v/ {
  49. return "Chat1.htm"
    9 W% x5 Q" F0 c. _
  50. elif n >= 4:
    8 Q/ ]9 `, K; d0 Q6 O
  51. return "Chat4.htm"
    ( ?7 V3 L) B1 }7 l# i
  52. return "Collect "+str(n)+" of 4 fangs"7 c( c; J: P" G% O
  53. return
    & d! T+ n7 }5 V! K4 v9 `
  54.   [! X; `( M: U; b4 `
  55. QUEST    = Quest(201, "Tutorial", "Tutorial quest")
    3 q) G6 V$ F& v: g) e! m
  56. CREATED = State('Start',    QUEST)
    1 s, \; b5 s. p1 z
  57. STARTED = State('Started', QUEST)
    - e: f. ^' Y# q4 \$ j7 Z! N4 E) C7 T
  58. COMPLETED = State('Completed', QUEST)/ W: K4 A$ f% j

  59. ! K- Y) F; W: z' H
  60. QUEST.setInitialState(CREATED), t. s; M* M4 n9 c6 @. z6 \
  61. QUEST.addStartNpc(7056). n5 {0 T: m" l$ P0 J
  62. QUEST.addStartNpc(7012)
    9 A" K9 R! V/ q
  63. QUEST.addStartNpc(7009)
    * @) u5 d, V9 b4 y9 {3 r
  64. QUEST.addStartNpc(7011)
    " Z# n$ U! P9 T# `0 u" d* h

  65. - _$ @( o- ]8 n7 u: C! Z' q: u
  66. STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
    4 S8 `' V3 h/ |
  67. STARTED.addKillId(KELTIR_NPC_ID)  @3 S  k. R: u! ^! M: D
  68. STARTED.addTalkId(7056)4 g  |$ n% b5 ^, y% q9 u9 Y
  69. STARTED.addTalkI d(7012). p+ c# b; g, Y
  70. STARTED.addTalkId(7009)
    . @  F# K5 y2 [0 n1 J( y
  71. STARTED.addTalkId(7011)
Скопировать код
% w- R2 l+ _3 ]; V* W

, @4 ~4 s* k9 x+ e" b
Чтобы ответить, вам надо авторизироваться в системе Вход | Зарегистрироваться

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

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

638638758

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

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

admin@artace.ru Онлайн

QR-код

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