Top.Mail.Ru

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

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

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

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

x
Хроники        Interlude) _- X: l- F2 n" B) }  S
Сборка        L2j
$ X0 c$ J0 Y7 [Обратите внимание: в файле htm стартового NCP обязательно должна быть ссылка на квест:
$ q; P/ G& d2 Q$ ~5 L+ V
  1. STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код
Для этого квеста больше ничего не надо. Все необходимое для корректной работы квеста уже добавили. Вот полный текст квеста:
; Z# W4 k2 b$ J2 \, a. G+ P; i7 v
" o% @" `  T8 C' U4 O
  1. if getCount(st) >= 4 :$ y  T, |& q6 ~
  2. completed(st)
    # d% @; Q3 E! J5 |/ R
  3.   return
    6 H) a; b; {) S* I* K: ~6 B2 ^

  4. + {: Z  t0 @) u: N: o6 B4 d
  5. class Quest (JQuest):/ j; `5 O$ J: e7 S
  6.   def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)$ z  ~% f, @0 b) z
  7.   def onEvent (self,event,st):
    : P& `0 P: |2 [9 ]
  8. id = st.getState()
    8 N/ Q4 j- p9 E
  9. if   id == CREATED  : st.setState(STARTED), F( p* i# L8 F* q0 L8 Q& |" X: U
  10. elif id == COMPLETED: pass
    0 Y% ]4 \% O+ D1 y4 q$ X
  11. elif id == STARTED  : check(st)
    3 D! `( C# U  F
  12. return
    ' v* B5 [1 W! c; ~/ H
  13. # W1 Q% O" E1 Q* X8 o" v
  14. QUEST     = Quest(201,"Tutorial", "Tutorial quest")' ]/ W- F4 s5 ?( G
  15. CREATED   = State('Start',     QUEST)
    6 O# M8 c$ l2 E. i( N/ v1 O3 K
  16. STARTED   = State('Started',   QUEST)/ f* n5 M% D$ [8 Z
  17. COMPLETED = State('Completed', QUEST)4 |; v$ X) n4 s9 r
  18. 3 d3 p% I6 v$ o2 X5 K" P2 p* _
  19. QUEST.setInitialState(CREATED)$ Y  e8 C7 j6 \
  20. QUEST.addStartNpc(7056)
    2 e  }/ `( _# U7 L! z
  21. STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код
Теперь рассмотрим, как это работает.
9 M6 N1 J, F2 k5 F8 ^Игрок подходит к начальному NCP (в данном случае 7056), нажимает на «Quest». Квест будет создан и состояние квеста перейдет к CREATED и игроку будет показана страничка Start.htm с описанием квеста. Тогда метод onEvent, поле открытия странички Start.htm переведет состояние квеста в STARTED и игроку будет показана страничка Started.htm, где будет опсание того, как найти keltirs и .т.д.
5 t% K5 c4 q5 A  M- @# F- f# P7 O3 R/ W" k% u+ Q

! Z: T+ H. _- X- S$ k, _При состоянии STARTED будет зарегистрирован дроп «fangs» при убийстве keltirs. Игрок может вернуться к стартовому NCP и спросить о квесте – метод onEvent будет вызван снова. Если у игрока не хватает необходимого количества предметов, то метод check() не переведет квест в следующее состояние и Started.htm будет показана снова. Но если игрок собрал необходимее количество предметов (в данном случае 4 клыка), то метод check() вызовет метод completed() который переведет квест в новое состояние COMPLETED, заберет все клыки, даст карту мира, т.к. это награда за квест, покажет Completed.htm и завершит квест." b5 M! W5 _5 G* U) B
& ^7 [' x* b. H) ]

' r$ a, i4 ^1 d+ y2 P+ ^Теперь давайте сделаем наш квест более похожим на то, что он должен из себя представлять.
& s( k) E- R& D  I& ]/ q: ^$ d* rПрежде всего у нас есть 3 метода для объявления их в Яве – onTalk, onKill и onEvent. Если методы onTalk и onKill не объявлены, то за них все будет делать метод onEvent, т.е. определять квестовых монстров и вызывать диалоги NCP. Есть примечание, методы onTalk и onKill будут вызывать только диалоги с NCP в зависимости от текущего состояния квеста. Метод onKill будет вызываться только тогда, когда мы убиваем квестового монстра.
0 Q. b% S& [& c
; B' f6 o6 U+ N, ?* h5 l
! n9 l: R- k9 K* `) g6 h
Давайте рассмотрим как вызывается метод onKill при убийстве keltir в состоянии квеста STARTED:- F6 d9 E) c& v' V3 L- N* i6 S* ]
  1. STARTED.addKillId(KELTIR_NPC_ID)
Скопировать код
и метод onKill в классе Quest:
" `$ f! Z+ \' \) N5 ?0 L
8 D$ t9 f0 t" g' `+ T
  1. class Quest (JQuest):% p6 @$ S( b/ P
  2.   ...$ d5 B- U; R9 F( f+ B; G. T. ~) l
  3.   def onKill (self,npcId,st):# G+ o& Q9 U" y! H7 k$ `
  4. if npcId == KELTIR_NPC_ID:4 r) L0 w7 X" Z: u4 s
  5.    n = getCount(st)
    , Y1 l* F0 H% D4 |; \
  6.    if   n == 0:
    ( n2 W' Y$ V* Z9 n
  7.        return "Chat0.htm"; @6 w1 q% K' _% K! c
  8.    elif n == 1:' U$ L4 C# V1 u% j( l! f
  9.        return "Chat1.htm"4 R5 }7 J5 n/ _/ |7 S5 P8 R
  10.    elif n >= 4:
      Z! @1 g6 ?; e) I2 G4 m, N! ]" Y
  11.        return "Chat4.htm"
    % _2 C9 B% e( |/ I: Q" g
  12.    return "Collected "+str(n)+" of 4 fangs") G7 U% R1 F; v3 D% \3 \# c6 g
  13. return
Скопировать код
Метод onKill (а так же метод onTalk) имеет следующие параметры:
+ v2 z- }" I8 M1 Q$ ?7 X% L4 M. x# K% L) i

' S3 R$ k* T% f$ `) c4 b% C• self – квест
; k. x4 {0 J: p, j. p• npcId – ID NCP, которого мы должны убивать (если это метод onTalk, то ID того NCP, с которым мы должны поговорить)., ~, ^+ N! M  e5 U1 M
• st – текущее состояние игрока.  t8 y" Z$ X# B7 T" H
5 m3 _3 p5 @' [2 k7 e

* E- T" \4 J& G; {7 cВ этом методе мы проверяем и отмечаем, является ли убитый NCP keltir’ом. В основном эта проверка не нужна, т.к. у нас только KELTIR_NPC_ID.
) ^; H9 e4 l# }  C
2 y# I% l8 s5 n% R$ p. n# u
4 a9 ]7 |# U6 I: B
Затем проверяем количество предметов (в данном случае количество клыков), и если их вообще нет, то возвращаем строку "Chat0.htm", если только один предмет, то возвращаем строку "Chat1.htm", если же предметов 4 или больше, то "Chat4.htm". Если строка возвращена из методов onEvent, onKill или onTalk, то сервер покажет соответствующие htm. В Chat0.htm может иметь следующий текст: «Вы не имеете ни одного клыка, возвращайтесь позже, когда соберете 4 штуки и бла, бла, бла…», в Chat1.htm может быть следующий текст: «У Вас всего 1 клык, по этому соберите еще…». В Chat4.htm – «Вы собрали необходимое количество предметов, возвращайтесь к вашему тренеру, что бы завершить квест…»; a. N& e; i7 J/ V2 E! g

  d' i8 t, n7 `6 P- I& I& g% J3 ]
' }% r9 p+ V" `  F: p* O/ i* w  f& L
Примечание: если в строка return начинается с "<html>", то будет показана страничка html с текстом, который стоит далее. Так вместо:
1 j) V/ y9 r+ P7 a0 I- \" V: y, wreturn "Chat4.htm") B1 }9 M& l' g+ X* \

- w; e; x. |# i0 e" t5 X

) Y- V, j% F* w' P/ `9 Cможно поставить:+ t4 C) R  ]7 ^* ^$ @, l. C
  1. return "<html><body>Return to your trainer to complete the quest</body></html>"
Скопировать код
Так же если строка заканчивается без .htm или в начале нет <html>, то текст будет выведен, как системное сообщение в окне чата. В нашем случае мы сделаем так, что бы при каждом убийстве keltik выводилось системное сообщение: «Собрано N из 4-х клыков».
- [* ?7 I) y- U; p: `4 T2 }9 t; h7 i& u7 L7 c, }3 r! k7 Z3 P
2 J2 z7 h" u$ J) @9 P0 Q2 X, Z! ?3 X
Наш код для onKill имеет один недостаток. Он будет постоянно показывать Chat0.htm, Chat1.htm и Chat4.htm, нам же необходимо, что бы Chat0.htm и Chat1.htm показывались только один раз. Как нам это сделать? С помощью переменных.6 G, c- ^/ Q8 q) L7 |. Q" b( w- t+ |, V

; A2 }2 C9 c8 M. P+ B

4 T/ l  @8 f% X- OВ каждом квесте строки могут храниться с помощью переменных. Эти переменные сохраняются в Вашей БД. В каждом методе мы можем назначить, прочитать и удалить переменные. Давайте изменим метод onKill, так что бы каждый диалог вызывался только один раз., {3 R3 w" Y8 ]
  1. def onKill (self,npcId,st):
    , G, ~2 d9 b$ h3 q
  2. if npcId == KELTIR_NPC_ID:
    ' y7 T6 O5 M, d$ O  h* K( T
  3. n = getCount(st)
    1 S" Y& r. _! B
  4. if n == 0:+ ^- d; [* a) d$ B# e% h( D/ D9 h5 s
  5. if st.get('chat0') == None :
    2 P8 ?& F4 y. ~1 s
  6. st.set("chat0", "true")
    2 P  Q# T) E% o; f
  7. return "Chat0.htm"* ]& }# J+ y% g
  8. elif n == 1:
    . Z  t) ~& q! N6 }. m* o( u+ d4 H
  9. if st.get('chat1') == None :8 @3 j- {3 J/ p9 |5 S
  10. st.set("chat1", "true")
    ; j, n$ P) F  f7 W7 U. M
  11. return "Chat1.htm": J. Z: s9 _% [& d
  12. elif n >= 4:
    $ P7 g; j0 i; O/ E0 t2 D2 y
  13. return "Chat4.htm"8 J" {$ r5 z, R5 m% y& i
  14. return "Collected "+str(n)+" of 4 fangs"
    ' A  c( r+ S  {6 W$ P% B) m
  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 b' C7 l6 v4 t0 A( O
( M/ H* T3 S. A8 \( j

5 [# D+ ~/ _/ G- o& k( ^/ tВот конечный рабочий вариант квеста:% g1 I5 _9 p) N+ p3 I
  1. import sys
    # y/ F+ Z& c' ]" n8 X9 v; n6 t) m
  2. from net.sf.l2j.gameserver.model.quest import State9 a$ O; H" m4 H) ]0 t
  3. from net.sf.l2j.gameserver.model.quest import QuestState
    7 D  b1 V7 O* o% f+ _; T0 H
  4. from net.sf.l2j.gameserver.model.quest.jython import QuestJython as JQuest4 D! S, I9 k8 T) z

  5. # |5 y$ }$ o# ^! g$ p
  6. KELTIR_NPC_ID = 12082) f/ }; Z( U( R. K0 R( b8 ^
  7. FANGS_ITEM_ID = 1859
    3 A* h% T+ q# o
  8. DROP_RATE    = 500000
    . f- P5 Q/ _0 n

  9. - {. Q; h9 p* f% \
  10. WORLD_MAP_ITEM_ID = 1665! M  c, A  W8 l  i! r5 e% \! ?
  11. 7 n! n, X- M) p0 U  j7 \
  12. def getCount(st) :9 }( M5 I* l6 |& O# _- X) S
  13. return st.getQuestItemsCount(FANGS_ITEM_ID)
    2 o( @- u/ d9 z! s
  14. 8 Q* T# R+ a0 \& b0 I
  15. def completed(st) :
    & |& j4 x9 a- j
  16. st.setState(COMPLETED)2 Z- a2 f7 Q' J/ V8 {
  17. st.clearQuestDrops()
    ' C! ?4 D9 u( d+ p
  18. st.takeItems(FANGS_ITEM_ID,-1)$ ~! v1 g, d+ b  ^, {6 \
  19. st.giveItems(WORLD_MAP_ITEM_ID,1)
    ( m! T6 `2 l" {. I- J0 ^; G4 B
  20. st.exitQuest(False)  @% j% i" Z" ~6 q
  21. return
    ! Z0 J0 W% O" E# w# Y4 Y

  22. 3 C* W. d$ I9 D8 V% N
  23. def check(st) :- N" b6 f3 _9 u
  24. if getCount(st) >= 4 :
    & T. S; L& `. \0 P- V
  25. completed(st)) [% R4 _4 s/ w
  26. return9 `% c6 t. Q/ J; b+ x
  27. . t& `3 h  u' O- c# A
  28. class Quest (JQuest):
    4 b, M( g4 Q: a# r' {. [* F
  29. 1 t; d$ y; l- s: S* z# w& x
  30. def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)( {1 Q8 H  v0 V

  31. . M/ @  M7 k% |2 e3 X( O
  32. def onEvent (self,event,st):
    3 @' @3 z' R/ T0 d7 Y" d
  33. id = st.getState()
    3 J. P5 }9 {, y' }& H- c5 m. [
  34. if id == CREATED : st.setState(STARTED)
    ! u# v9 |' U! \3 q$ I: W
  35. elif id == COMPLETED: pass
    $ P! l$ K  K* B% _7 u2 a
  36. elif id == STARTED : check(st)
    % Z0 w! j: u, z
  37. return1 \( D6 |% M, g! s$ y
  38. ) Y) V( R! X* [! x/ m$ y
  39. def onKill (self,npcId,st):) p& r1 d1 O8 a! Q
  40. if npcId == KELTIR_NPC_ID:3 T4 U. k2 ]" _& P0 ~
  41. n = getCount(st)! w1 v8 `. v: Q: c2 K, Z9 A
  42. if n == 0:* O4 P) N$ D( f$ h! c4 ~" t
  43. if st.get('chat0') == None :, T' `$ J4 I, f2 L/ r7 |# A
  44. st.set("chat0", "true"). j% M" f4 n( L
  45. return "Chat0.htm", A& f0 u: Q0 x8 x- F3 r* ]
  46. elif n == 1:2 h0 T0 V1 z4 ~2 s" \
  47. if st.get('chat1') == None :
    1 z$ H& n/ c) T& J* l
  48. st.set("chat1", "true"). ]4 w8 V9 u; i% s- X0 a/ Q& ?$ e; ~
  49. return "Chat1.htm"
    9 {: S& q, c) G7 F! n
  50. elif n >= 4:+ ~" @3 G1 c6 f. e) l4 D# q5 `
  51. return "Chat4.htm"
    1 l" O  d; f8 I, i  s
  52. return "Collect "+str(n)+" of 4 fangs"
    3 l3 a3 J: ~+ Z4 u, H. Q  ?
  53. return
    1 R5 F7 `& k5 T; N
  54. * Y' C+ M+ \2 E4 t# s. @  C
  55. QUEST    = Quest(201, "Tutorial", "Tutorial quest")' V2 H# z4 `3 O+ |- M  F5 t
  56. CREATED = State('Start',    QUEST); Y' O' b2 Z+ s
  57. STARTED = State('Started', QUEST)
    " E: p8 {/ K5 _) c. T
  58. COMPLETED = State('Completed', QUEST). b8 ?: ], I0 L3 o  l

  59. ! j5 [. q9 H+ \& r. r5 [; i
  60. QUEST.setInitialState(CREATED)
    * q$ |2 r8 S3 V& a
  61. QUEST.addStartNpc(7056)/ P2 }7 n; l! U; B' L
  62. QUEST.addStartNpc(7012)2 Q# Q6 r* H5 H+ \
  63. QUEST.addStartNpc(7009)
    " K% q' C' X7 L  a" ]+ ]
  64. QUEST.addStartNpc(7011)
    # h8 B2 |5 U  l, f5 G# P5 C

  65. : Q2 n6 S3 j  U! E2 v# L
  66. STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)3 @# W/ R" m1 }9 H
  67. STARTED.addKillId(KELTIR_NPC_ID)
    % k8 B! T/ l, J  v: {
  68. STARTED.addTalkId(7056)
    ' O/ s0 p- d2 H. z
  69. STARTED.addTalkI d(7012)5 M" K2 p8 M3 }8 ~* ~1 m
  70. STARTED.addTalkId(7009)
    ! R' c8 g! T% \+ [
  71. STARTED.addTalkId(7011)
Скопировать код
0 I3 [2 ?, }: ~' |* q

/ g1 T- h  A/ R& @  k/ \2 z7 {5 _
Чтобы ответить, вам надо авторизироваться в системе Вход | Зарегистрироваться

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

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

638638758

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

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

admin@artace.ru Онлайн

QR-код

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