Top.Mail.Ru

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

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

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

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

x
Хроники        Interlude9 K% ?7 H" s, \  R" ~4 g" Q4 N) [
Сборка        L2j, u& V$ h5 A0 K9 X* s  \6 l) c: }
Обратите внимание: в файле htm стартового NCP обязательно должна быть ссылка на квест:
# d& E. M$ J$ s; Z$ V2 d) |8 p3 o
  1. STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код
Для этого квеста больше ничего не надо. Все необходимое для корректной работы квеста уже добавили. Вот полный текст квеста:
; a' a# ?% \$ |* o0 m$ e) n6 R. y6 `) {1 ~6 u4 r
  1. if getCount(st) >= 4 :( V% H( D) Y% N* H
  2. completed(st). R2 Y8 y) ?$ f2 a
  3.   return0 \: Z$ d2 A5 q: u
  4. - Y- c3 p0 W4 L; X5 i8 b
  5. class Quest (JQuest):* a$ F1 A1 x* G
  6.   def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)0 D' d$ t! L$ J% C' D
  7.   def onEvent (self,event,st):( w  q# V2 D2 Y4 K6 {2 q
  8. id = st.getState()' Z7 M% A6 Q. O% N
  9. if   id == CREATED  : st.setState(STARTED)4 V) o8 o3 }1 z! r/ D
  10. elif id == COMPLETED: pass
    ( C$ a9 x' N3 h
  11. elif id == STARTED  : check(st)4 k- u4 t4 z: ?* o- G3 ?0 y- l
  12. return* {: }) W% p) ~* A) }: a

  13.   j; a( j) P, \' Y6 b: g/ w1 t
  14. QUEST     = Quest(201,"Tutorial", "Tutorial quest")% ]& e, y0 W6 H: y$ @
  15. CREATED   = State('Start',     QUEST)+ ]9 [; m. q  V$ W
  16. STARTED   = State('Started',   QUEST)
    7 G. X% w' T! d. `( W3 y
  17. COMPLETED = State('Completed', QUEST)
    ! B8 O1 s2 W4 q# o! p8 ~7 |9 R
  18. , H5 A8 i, o: G6 o& Q5 g
  19. QUEST.setInitialState(CREATED)
    * R0 r+ a& O3 j8 h) b& w
  20. QUEST.addStartNpc(7056)
    3 u5 k* Z1 d; R1 I1 O/ j, T2 L
  21. STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код
Теперь рассмотрим, как это работает.$ a! r9 N" ^: m0 t* D$ L8 W
Игрок подходит к начальному NCP (в данном случае 7056), нажимает на «Quest». Квест будет создан и состояние квеста перейдет к CREATED и игроку будет показана страничка Start.htm с описанием квеста. Тогда метод onEvent, поле открытия странички Start.htm переведет состояние квеста в STARTED и игроку будет показана страничка Started.htm, где будет опсание того, как найти keltirs и .т.д.# E, j# Z5 F4 `+ v% W' v
- S6 Z& G6 j* S. Y( G+ u5 |

% P9 I! `+ ^8 WПри состоянии STARTED будет зарегистрирован дроп «fangs» при убийстве keltirs. Игрок может вернуться к стартовому NCP и спросить о квесте – метод onEvent будет вызван снова. Если у игрока не хватает необходимого количества предметов, то метод check() не переведет квест в следующее состояние и Started.htm будет показана снова. Но если игрок собрал необходимее количество предметов (в данном случае 4 клыка), то метод check() вызовет метод completed() который переведет квест в новое состояние COMPLETED, заберет все клыки, даст карту мира, т.к. это награда за квест, покажет Completed.htm и завершит квест.* g$ j; u" h0 }! n

4 B  r$ ^2 z; |# e1 ]
, {% _# Z: ]" Q# u$ b3 Q
Теперь давайте сделаем наш квест более похожим на то, что он должен из себя представлять.
$ y$ ?+ Y: ~5 @) ]Прежде всего у нас есть 3 метода для объявления их в Яве – onTalk, onKill и onEvent. Если методы onTalk и onKill не объявлены, то за них все будет делать метод onEvent, т.е. определять квестовых монстров и вызывать диалоги NCP. Есть примечание, методы onTalk и onKill будут вызывать только диалоги с NCP в зависимости от текущего состояния квеста. Метод onKill будет вызываться только тогда, когда мы убиваем квестового монстра.5 `" F! m8 W0 W

' a7 U' f5 h. \) i! `' j( k0 s' z

; z. V' g, r3 z4 ]; _* ?7 gДавайте рассмотрим как вызывается метод onKill при убийстве keltir в состоянии квеста STARTED:
" H5 F7 F" s  R) F" u8 E3 ^
  1. STARTED.addKillId(KELTIR_NPC_ID)
Скопировать код
и метод onKill в классе Quest:/ g# F: u: L3 }

1 T: C+ I4 {1 N3 C& L( w
  1. class Quest (JQuest):7 L# S1 l7 F  W& F$ l1 Y
  2.   ...1 \9 P. G/ z5 D2 [5 U7 c
  3.   def onKill (self,npcId,st):* N3 @* J$ b, O5 F$ H! z8 B
  4. if npcId == KELTIR_NPC_ID:! ?/ x3 r* t1 a5 y; ~* x) \7 F
  5.    n = getCount(st)/ O0 E6 s- t; U( ?6 {& q, D
  6.    if   n == 0:
    " u( b. x  W# c: J$ j5 {7 d7 K! m
  7.        return "Chat0.htm"
    ( |# q% E7 z9 j
  8.    elif n == 1:4 @( m5 X7 e6 G. m! v) Z
  9.        return "Chat1.htm"
    : V: a: B, n$ n# n4 l4 m( L$ o
  10.    elif n >= 4:8 U2 y( X1 n0 W4 p( ]
  11.        return "Chat4.htm"
    4 W7 z; V- j( b
  12.    return "Collected "+str(n)+" of 4 fangs") n  K$ m) ^& o/ h, x/ A
  13. return
Скопировать код
Метод onKill (а так же метод onTalk) имеет следующие параметры:2 g# r8 V2 q3 B. \7 e

9 `' [6 p! c) K' E8 M

5 k+ U3 u2 i4 Z, }% M  v/ y8 i• self – квест5 s) S# M1 U  t3 Q
• npcId – ID NCP, которого мы должны убивать (если это метод onTalk, то ID того NCP, с которым мы должны поговорить).! s( r4 X- \) @: f, [* E) v
• st – текущее состояние игрока.
  ]/ S. \* A/ _8 d# {1 I2 [
5 V( @% G: n% }/ Z' K7 ~4 _
! ^8 Q$ ~) Y; `! S9 M' g
В этом методе мы проверяем и отмечаем, является ли убитый NCP keltir’ом. В основном эта проверка не нужна, т.к. у нас только KELTIR_NPC_ID.
# L" y# V' Q3 x9 I$ Q" f! E+ S+ C# j5 {" c9 V6 R

" t" B+ G& h  u6 y' K1 KЗатем проверяем количество предметов (в данном случае количество клыков), и если их вообще нет, то возвращаем строку "Chat0.htm", если только один предмет, то возвращаем строку "Chat1.htm", если же предметов 4 или больше, то "Chat4.htm". Если строка возвращена из методов onEvent, onKill или onTalk, то сервер покажет соответствующие htm. В Chat0.htm может иметь следующий текст: «Вы не имеете ни одного клыка, возвращайтесь позже, когда соберете 4 штуки и бла, бла, бла…», в Chat1.htm может быть следующий текст: «У Вас всего 1 клык, по этому соберите еще…». В Chat4.htm – «Вы собрали необходимое количество предметов, возвращайтесь к вашему тренеру, что бы завершить квест…»7 m0 J0 Q! Q% H; L/ @& O2 Q7 U" J1 t

# e9 V( {. G8 r' N8 I+ X: {1 {
3 X+ C7 n! T3 d# O9 G! U
Примечание: если в строка return начинается с "<html>", то будет показана страничка html с текстом, который стоит далее. Так вместо:, {+ F+ P, z9 J) U( W% \$ r+ V- z. Y
return "Chat4.htm"
9 w4 P6 e, c. h. A+ K! ~/ [8 A
: w4 s- X. ?, Q) i2 s# j0 L/ s+ n* m

- e, t8 Q  @7 H7 _4 l' iможно поставить:
, d/ v1 Q  v  a  e" Q# S4 J
  1. return "<html><body>Return to your trainer to complete the quest</body></html>"
Скопировать код
Так же если строка заканчивается без .htm или в начале нет <html>, то текст будет выведен, как системное сообщение в окне чата. В нашем случае мы сделаем так, что бы при каждом убийстве keltik выводилось системное сообщение: «Собрано N из 4-х клыков».
/ L) d. F) @. A3 g
" X& p: H( l  Q( n0 D

1 X- v+ ]7 f) S) M5 X) OНаш код для onKill имеет один недостаток. Он будет постоянно показывать Chat0.htm, Chat1.htm и Chat4.htm, нам же необходимо, что бы Chat0.htm и Chat1.htm показывались только один раз. Как нам это сделать? С помощью переменных.
6 o1 ]1 v( ]5 L- a+ a. ~% z# z- w( o8 t+ y
# b% Y' W7 B" h5 _* {9 S+ y
В каждом квесте строки могут храниться с помощью переменных. Эти переменные сохраняются в Вашей БД. В каждом методе мы можем назначить, прочитать и удалить переменные. Давайте изменим метод onKill, так что бы каждый диалог вызывался только один раз.: Q( F0 E4 t. _9 I# w1 \
  1. def onKill (self,npcId,st):
    8 ?+ p- F  _6 v# C2 f0 {0 M
  2. if npcId == KELTIR_NPC_ID:
    - ~& Q# w; d7 t7 D: E3 e
  3. n = getCount(st), \7 z; Z0 A) l" w7 ~! ]" @
  4. if n == 0:
    4 q* D7 [5 a* X! k' w) r
  5. if st.get('chat0') == None :% f# [- O* e6 r" h
  6. st.set("chat0", "true")& Z5 d9 L+ Y2 m! |! v4 d) g
  7. return "Chat0.htm"
    3 i' r9 ^0 d' H8 \) ^  G& i( o
  8. elif n == 1:
    " j- x, M9 j* u/ Z
  9. if st.get('chat1') == None :
    & V$ \# e7 O# C1 y8 A' x
  10. st.set("chat1", "true")
    . i9 q  `1 C' ~* ~) n) g1 d
  11. return "Chat1.htm"6 u% X* Q: Y' \, ^
  12. elif n >= 4:
    ; O9 ~& [. B% u1 G3 a2 n' ~
  13. return "Chat4.htm"
    * a' u5 `' N7 \2 k8 h5 A1 ^
  14. return "Collected "+str(n)+" of 4 fangs"
    - {5 E& {7 c* k; n, ]) {8 N+ B
  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./ K$ @( ~. {) ^5 K

. p+ z( W  v8 N+ w

& o, i) g' ]$ _" {4 pВот конечный рабочий вариант квеста:
2 n0 _& b7 V( I9 ]! a8 {. |
  1. import sys4 T% v8 }( j# O
  2. from net.sf.l2j.gameserver.model.quest import State
    * n% e% G) c  ~. E5 Z* \
  3. from net.sf.l2j.gameserver.model.quest import QuestState
    ' D. f/ g; y; K: W7 X1 c
  4. from net.sf.l2j.gameserver.model.quest.jython import QuestJython as JQuest
    8 |/ S" W9 w! m" m2 M2 q
  5. ' k- d& K4 V# d. ]
  6. KELTIR_NPC_ID = 12082% g% G# T* t& p5 ?! B
  7. FANGS_ITEM_ID = 1859
    7 l: E! j8 w5 M6 x
  8. DROP_RATE    = 5000006 B! L! _, W1 o" P: {2 M
  9. ) h$ r) Z! o3 d4 R# z  N; q
  10. WORLD_MAP_ITEM_ID = 16652 I6 f" }" ~( ^; f/ ~' }% }% D
  11. % [# k# ~, A  m5 ]) _+ [$ H
  12. def getCount(st) :
    , Q2 P& ?. s4 v& O' \1 u) Y1 a2 d( J
  13. return st.getQuestItemsCount(FANGS_ITEM_ID)
    $ Y  E8 _. Z0 {4 |' A0 q/ d6 Z& R

  14. ; e. T. B5 J. o8 c- L' @
  15. def completed(st) :
    # S( I' @. X) |; X! |/ u; j. `3 d
  16. st.setState(COMPLETED)
    4 K7 d: h; T- M4 L% V% O% i, \4 y3 Q
  17. st.clearQuestDrops()
    ) g4 U! m& v9 p' b7 O! {: _  L9 _
  18. st.takeItems(FANGS_ITEM_ID,-1)+ I+ E% ~' {% t! p' i$ q4 O
  19. st.giveItems(WORLD_MAP_ITEM_ID,1)
    7 K% X; W5 s& u; K9 U  W
  20. st.exitQuest(False)
    % P* @* V$ {7 b0 Y
  21. return
    9 S9 R' j2 M! M; U! A/ d( O% X
  22. ; w8 d, P3 ]. V7 W# O0 D
  23. def check(st) :
    , o: O0 y/ l: p: R- W) f7 j( S; r
  24. if getCount(st) >= 4 :
    , T4 n$ v7 v0 m. ~' `
  25. completed(st)
      X8 r2 H( C# @! \( {7 v
  26. return' \1 A9 o8 _# |; ^
  27. * S- u" O: E2 G3 F+ |/ V
  28. class Quest (JQuest):
    2 M. p4 U: W9 \  ]
  29. - W) @! |5 }& @; C# X0 o
  30. def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)
    : s/ ^! {7 w: p# I1 k
  31. 7 ?& j) N( |$ A  r# a' a! R) {
  32. def onEvent (self,event,st):: k! n5 P; R! J8 f$ [8 d8 o
  33. id = st.getState()
    0 L+ z- }. P0 C8 t! B# k8 [& U
  34. if id == CREATED : st.setState(STARTED)
    ' p" t+ v, K/ a7 I+ N: k1 R5 L8 G
  35. elif id == COMPLETED: pass1 _# A1 \( D  S. ^" Y2 v( H
  36. elif id == STARTED : check(st)$ o: z& O* v! h2 x/ c' ^0 h6 o
  37. return  u9 K" D9 E" N8 O- i' K# A0 o, l  A

  38. 8 q, k9 X5 W; D- _
  39. def onKill (self,npcId,st):  G$ c+ j( L6 i  N2 U( }9 E$ i* X6 o, v
  40. if npcId == KELTIR_NPC_ID:2 \7 l- d7 A0 x+ X* M8 B7 Y
  41. n = getCount(st)
    ) y6 @) i8 k9 {& F' I
  42. if n == 0:
    9 R7 g- T; l1 K  I) O  o
  43. if st.get('chat0') == None :
    $ t" ~; i1 L& O2 s
  44. st.set("chat0", "true")  t, N, \2 d* O. `& Q2 @
  45. return "Chat0.htm"9 k( L1 G% A5 W7 y1 z
  46. elif n == 1:
    ) I9 z9 o; k* Q* C; v$ s1 n, G
  47. if st.get('chat1') == None :
    " |, }8 i5 O7 V# |1 f4 y- Y
  48. st.set("chat1", "true")
    # \& S' c+ l+ U* {3 T  o& j
  49. return "Chat1.htm"
    3 t. |( O) a" @) j
  50. elif n >= 4:
    ; T8 K, r" S2 q0 d7 R
  51. return "Chat4.htm": j' y9 [& l( E) l* B6 k
  52. return "Collect "+str(n)+" of 4 fangs"
    % g. X! Q: f$ j6 Y# ?
  53. return$ K# A' v$ E* R( U
  54. , N4 i% x* w- U8 p
  55. QUEST    = Quest(201, "Tutorial", "Tutorial quest")
    0 a9 c$ L, H, \0 @
  56. CREATED = State('Start',    QUEST)
    ' \& ]" H$ P8 f/ }4 u1 F
  57. STARTED = State('Started', QUEST)- e$ d5 m* D) s( N  b6 _3 O
  58. COMPLETED = State('Completed', QUEST)( s3 V, Q( x! b, S( O! U

  59. ! D( L, i$ j5 Q5 B6 e  W! Q+ U
  60. QUEST.setInitialState(CREATED)
    & Y* Q- \4 |& s
  61. QUEST.addStartNpc(7056)% l$ v. V6 D( w, K
  62. QUEST.addStartNpc(7012). U4 T2 L# l3 U& m6 I
  63. QUEST.addStartNpc(7009)5 T, X* {& v: O
  64. QUEST.addStartNpc(7011)
    % o0 o0 \+ ~6 w/ \+ w2 E# F8 q9 F

  65. * `/ ]: _/ t: Y9 @
  66. STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)' X, Z9 o6 f5 D$ w: i& T
  67. STARTED.addKillId(KELTIR_NPC_ID)
    * k8 J; Q4 r- w9 y, a  G- A
  68. STARTED.addTalkId(7056)
    1 M9 R' _; c- p9 A. j% k. ~9 Q
  69. STARTED.addTalkI d(7012)# r" f+ ]8 p# j) d5 h8 R. Z5 T
  70. STARTED.addTalkId(7009)
    $ g& E: x' {, Y& b+ v) u
  71. STARTED.addTalkId(7011)
Скопировать код

3 ]3 h$ N$ d+ S  F6 f
# o7 x2 E- o2 i8 h5 t+ H$ U
Чтобы ответить, вам надо авторизироваться в системе Вход | Зарегистрироваться

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

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

638638758

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

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

admin@artace.ru Онлайн

QR-код

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