Top.Mail.Ru

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

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

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

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

x
Хроники        Interlude3 b: m+ @$ S9 l- J2 u
Сборка        L2j6 f) r3 J) X( \
Обратите внимание: в файле htm стартового NCP обязательно должна быть ссылка на квест:
( z  S, E$ O1 h4 D+ I7 @2 N* W% K. ~* S
  1. STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код
Для этого квеста больше ничего не надо. Все необходимое для корректной работы квеста уже добавили. Вот полный текст квеста:/ }. J, \1 }" N9 _8 D
1 }  ~% @, \6 E3 K! q) S& E/ h
  1. if getCount(st) >= 4 :. p/ {! d0 i' E4 A. K
  2. completed(st)% L! C) @0 g& h2 Z" P( _, D
  3.   return
    - Y8 p: X5 T1 s, }. s$ s

  4. , f9 f# t+ i7 j: |
  5. class Quest (JQuest):
    - v" h) \% l0 R
  6.   def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)3 u% N0 O1 t8 M' Q0 ?% h
  7.   def onEvent (self,event,st):
    # S! X4 ^* q; X& y2 m! u
  8. id = st.getState()
    2 H' Q. S! f" p& }  z+ C
  9. if   id == CREATED  : st.setState(STARTED)
    ; [; ^* \9 [: a$ D
  10. elif id == COMPLETED: pass- _1 `5 c: A/ D; r* \
  11. elif id == STARTED  : check(st)/ H: Y& [' O" C+ n8 _
  12. return
    % @% y3 h9 T  t: E9 M% U

  13. 5 h% S5 o- |, D1 g+ v
  14. QUEST     = Quest(201,"Tutorial", "Tutorial quest"), _2 o" u& ^3 a7 t7 ?# Q7 G
  15. CREATED   = State('Start',     QUEST)
    3 y" C. N/ N2 a* |
  16. STARTED   = State('Started',   QUEST)
    - G7 l5 b' b9 t
  17. COMPLETED = State('Completed', QUEST), s# p3 n& A2 k, i  F: S
  18. + X8 F5 ^% ~8 Z3 U9 I
  19. QUEST.setInitialState(CREATED)  D. _" m8 K" a: [( s# A7 |
  20. QUEST.addStartNpc(7056)
    2 V- }/ ?" i; z$ J- ^  E# l6 W* {
  21. STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код
Теперь рассмотрим, как это работает.5 L* p" |* q9 Y
Игрок подходит к начальному NCP (в данном случае 7056), нажимает на «Quest». Квест будет создан и состояние квеста перейдет к CREATED и игроку будет показана страничка Start.htm с описанием квеста. Тогда метод onEvent, поле открытия странички Start.htm переведет состояние квеста в STARTED и игроку будет показана страничка Started.htm, где будет опсание того, как найти keltirs и .т.д.  {, L0 j8 `4 {' E' D4 c

# @9 [/ Y* K7 |: P: I8 ^# J& U, B: m0 n
( I8 P" T8 S7 G1 [3 q
При состоянии STARTED будет зарегистрирован дроп «fangs» при убийстве keltirs. Игрок может вернуться к стартовому NCP и спросить о квесте – метод onEvent будет вызван снова. Если у игрока не хватает необходимого количества предметов, то метод check() не переведет квест в следующее состояние и Started.htm будет показана снова. Но если игрок собрал необходимее количество предметов (в данном случае 4 клыка), то метод check() вызовет метод completed() который переведет квест в новое состояние COMPLETED, заберет все клыки, даст карту мира, т.к. это награда за квест, покажет Completed.htm и завершит квест.
( F% L& Q: N- _& Z5 k
8 A1 _! j( A6 F1 m0 p
. g% v/ ~( o% _% D4 E
Теперь давайте сделаем наш квест более похожим на то, что он должен из себя представлять.
8 K: P" l# l( IПрежде всего у нас есть 3 метода для объявления их в Яве – onTalk, onKill и onEvent. Если методы onTalk и onKill не объявлены, то за них все будет делать метод onEvent, т.е. определять квестовых монстров и вызывать диалоги NCP. Есть примечание, методы onTalk и onKill будут вызывать только диалоги с NCP в зависимости от текущего состояния квеста. Метод onKill будет вызываться только тогда, когда мы убиваем квестового монстра.2 H& ~5 ~4 e% G$ O
% I) [) F$ A1 ^

3 p, q* ^& a* @% x" R7 m6 TДавайте рассмотрим как вызывается метод onKill при убийстве keltir в состоянии квеста STARTED:# ~: ]- J; c9 H- ~9 l# @" c
  1. STARTED.addKillId(KELTIR_NPC_ID)
Скопировать код
и метод onKill в классе Quest:
9 {1 }4 H& q4 o
5 T% V9 L3 Y. ^
  1. class Quest (JQuest):
    , T, b  u8 Y5 Y+ \0 |, @
  2.   .../ F- K% F, x: J3 @' g
  3.   def onKill (self,npcId,st):" T/ `( {/ z3 g& M3 \1 _' ~' f; l; n
  4. if npcId == KELTIR_NPC_ID:/ q  }0 A: U% N
  5.    n = getCount(st)
    7 R1 R2 Q: e6 S  A( S
  6.    if   n == 0:
    ! F8 u& r- i- G
  7.        return "Chat0.htm"
    - O, W% ]$ w3 n! T+ A
  8.    elif n == 1:
    9 ?0 e, H6 ]7 A; F
  9.        return "Chat1.htm": D4 c- u% [2 ~
  10.    elif n >= 4:" U! f0 N3 ]5 B) r' G. Z- X
  11.        return "Chat4.htm"
    $ G1 f3 }- ?2 ~2 }- U/ n
  12.    return "Collected "+str(n)+" of 4 fangs"6 P! F. G/ `1 T0 Y  Q
  13. return
Скопировать код
Метод onKill (а так же метод onTalk) имеет следующие параметры:
- y) ~) ]$ e# f! T. F! I$ j( X% n# [) s; N' u2 C7 L

7 u& j7 ^, w9 E6 g' N• self – квест: g+ t! }/ a; |0 |
• npcId – ID NCP, которого мы должны убивать (если это метод onTalk, то ID того NCP, с которым мы должны поговорить).5 e, s/ [$ D( m( t1 n  M
• st – текущее состояние игрока.
/ W0 U; z1 j; o8 Z$ Z
( l8 i, U4 W, Z' y( y$ v. x
' y  n6 |2 p% K& r- L- k
В этом методе мы проверяем и отмечаем, является ли убитый NCP keltir’ом. В основном эта проверка не нужна, т.к. у нас только KELTIR_NPC_ID.. d% K  I( m" t) w3 q
/ ^8 i) s: V! t& q  p" \

# s( {5 v# t' \9 I7 Y% HЗатем проверяем количество предметов (в данном случае количество клыков), и если их вообще нет, то возвращаем строку "Chat0.htm", если только один предмет, то возвращаем строку "Chat1.htm", если же предметов 4 или больше, то "Chat4.htm". Если строка возвращена из методов onEvent, onKill или onTalk, то сервер покажет соответствующие htm. В Chat0.htm может иметь следующий текст: «Вы не имеете ни одного клыка, возвращайтесь позже, когда соберете 4 штуки и бла, бла, бла…», в Chat1.htm может быть следующий текст: «У Вас всего 1 клык, по этому соберите еще…». В Chat4.htm – «Вы собрали необходимое количество предметов, возвращайтесь к вашему тренеру, что бы завершить квест…»9 L9 P# s" S8 J

- `. Z6 J( y# Z+ Y% o% f. q
& M* `5 W+ H. G6 j/ k; z
Примечание: если в строка return начинается с "<html>", то будет показана страничка html с текстом, который стоит далее. Так вместо:% s3 W# r. K5 m1 x
return "Chat4.htm". H" l- i  a- r9 Y3 u
0 h' ?0 N9 ^1 F! g  _

3 M0 f$ U- \# V3 w$ _5 Wможно поставить:4 Q: Z8 K' C0 W. c6 b: d
  1. return "<html><body>Return to your trainer to complete the quest</body></html>"
Скопировать код
Так же если строка заканчивается без .htm или в начале нет <html>, то текст будет выведен, как системное сообщение в окне чата. В нашем случае мы сделаем так, что бы при каждом убийстве keltik выводилось системное сообщение: «Собрано N из 4-х клыков».4 O  b: R/ c  y* c: C

( Z3 y+ L0 Z& Q4 ~

# O! X- N; k1 i% s7 iНаш код для onKill имеет один недостаток. Он будет постоянно показывать Chat0.htm, Chat1.htm и Chat4.htm, нам же необходимо, что бы Chat0.htm и Chat1.htm показывались только один раз. Как нам это сделать? С помощью переменных.2 ]% i3 d; H; C% m) l$ y0 X
& T7 T# ^- e" a9 K/ p) V
1 O: j9 `) x3 [4 U+ t6 D) @& |
В каждом квесте строки могут храниться с помощью переменных. Эти переменные сохраняются в Вашей БД. В каждом методе мы можем назначить, прочитать и удалить переменные. Давайте изменим метод onKill, так что бы каждый диалог вызывался только один раз.
/ j: D& G+ \  @/ K# e! [' }
  1. def onKill (self,npcId,st):
    7 g# g! P7 j2 G! l' d
  2. if npcId == KELTIR_NPC_ID:9 t, z/ d' @0 @: [% k
  3. n = getCount(st)
    7 o- ?+ e  }' V/ ^8 f
  4. if n == 0:
    - N) n% n9 @9 B
  5. if st.get('chat0') == None :
    9 S' H3 c" Y0 ~# k
  6. st.set("chat0", "true")
    ' T9 g, o' t' R4 H
  7. return "Chat0.htm"
    : u6 x2 t* I  g" i
  8. elif n == 1:
    4 K: J' t6 s( R  w( N
  9. if st.get('chat1') == None :* `: J9 \) F# y% F5 E" C
  10. st.set("chat1", "true")( U. O' K6 t3 g4 t  ?' z; l
  11. return "Chat1.htm"! S, `- y( s. ?! U3 P8 o
  12. elif n >= 4:
    / d, h  w2 M# Y, w1 [% y% M
  13. return "Chat4.htm", a9 W& q$ w6 N- V6 C, w
  14. return "Collected "+str(n)+" of 4 fangs"
    * a- W  k/ ]  S- c) @& I, ?
  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 N2 E5 ^9 z3 a/ J: z5 x5 g* b; D( M. f* v
' @! L4 M( \" T+ L0 k- ?( g. m
Вот конечный рабочий вариант квеста:
: V* J0 t1 i" k& }$ w/ [# w7 W! E
  1. import sys3 w  c3 t9 `9 }0 m! d2 t0 r  {
  2. from net.sf.l2j.gameserver.model.quest import State7 H. r& n, @+ r/ J
  3. from net.sf.l2j.gameserver.model.quest import QuestState
    ) P+ B1 _  l& Y
  4. from net.sf.l2j.gameserver.model.quest.jython import QuestJython as JQuest7 F4 j7 u/ r7 s- D" ]( V0 `, z

  5. 1 N) k9 X5 N# r2 Q1 v
  6. KELTIR_NPC_ID = 12082
    ! @- U" E3 v9 F: V' a) u1 B8 G! R
  7. FANGS_ITEM_ID = 1859
    5 |3 \/ |* a- Z' h
  8. DROP_RATE    = 500000
    $ y% A3 X" v" _
  9. 3 T# l  ]% t5 [# E4 ?
  10. WORLD_MAP_ITEM_ID = 1665. C/ B) V6 T+ O
  11. ; L% u% N4 h% Q9 N$ x/ q$ t/ O0 I
  12. def getCount(st) :# f3 U/ \& d8 h; l. @) ]% Y2 ]" c1 T
  13. return st.getQuestItemsCount(FANGS_ITEM_ID)
    4 C9 L" e+ K% Z" L  C) B

  14. ; x* `- q7 C7 q* x: |% s8 U
  15. def completed(st) :
    9 B0 S; |5 C. r( C* k! R
  16. st.setState(COMPLETED), v% D  |+ t( ~0 U, K" a4 R; g2 _
  17. st.clearQuestDrops()
    - p! G' I7 p; ?% O) I
  18. st.takeItems(FANGS_ITEM_ID,-1)4 ]7 H/ n, f; h; w; ]. w" b
  19. st.giveItems(WORLD_MAP_ITEM_ID,1)+ |) i' r* P' V$ ]0 C; I& ]3 [
  20. st.exitQuest(False)
    . `/ \8 i3 ~; |! l4 |
  21. return9 w- H. @0 s2 I6 J  r
  22. , x- L- c4 z4 U$ t( P' Y7 f- m
  23. def check(st) :
    7 l1 a. Z$ q0 H. @9 h4 b1 S
  24. if getCount(st) >= 4 :1 [% p- a& E$ x
  25. completed(st)8 _. q5 m4 G/ ?7 `8 k( z" Z7 A  l4 v
  26. return& w$ N( y$ D5 z

  27. $ g1 q4 m; R, {0 h5 t8 L2 d3 q
  28. class Quest (JQuest):
    , {0 H' W! g& T7 U

  29. " ?+ V; h' u9 |- V# O
  30. def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)
    5 D( x5 K# v$ }
  31. & h' N9 h1 @9 c0 O6 T4 B4 o
  32. def onEvent (self,event,st):
    / @& p3 R" P- d# \6 j# K# Y1 m
  33. id = st.getState()
    / Z  v# y' w+ k  G( s4 u
  34. if id == CREATED : st.setState(STARTED)  X( J% y. L% ?8 C3 G# z0 t0 N
  35. elif id == COMPLETED: pass! t' g8 S) c1 x: _- y
  36. elif id == STARTED : check(st)8 r1 P5 w( I" m8 q$ y& x
  37. return0 b+ T# H( I! A5 J% e( }8 a% H  H
  38. 8 g# M2 G: S/ A9 G9 f6 B& K/ K
  39. def onKill (self,npcId,st):
    6 a+ L! T  |# d$ H" A* V
  40. if npcId == KELTIR_NPC_ID:2 \0 {- i3 z, f7 K9 F2 {$ _
  41. n = getCount(st)
    / S% }$ P# j  M2 u* E
  42. if n == 0:6 w0 z% G" E! b7 q: P4 v
  43. if st.get('chat0') == None :5 |) _9 g% G8 i! Y# l
  44. st.set("chat0", "true")
    . ^3 H- `9 o. E" z" y  A
  45. return "Chat0.htm"
    # d& j1 V9 B- Z3 O  |' l5 {# \" Z. V
  46. elif n == 1:
    . k* Q3 m* N  a* B9 g& H( c
  47. if st.get('chat1') == None :
    4 H. C* n3 g' @; ~) _
  48. st.set("chat1", "true")
    & E7 G5 p1 ^. L7 E* U
  49. return "Chat1.htm"8 e: ?/ s/ |  k* }
  50. elif n >= 4:
    + |6 j5 S& g; A8 Y) U
  51. return "Chat4.htm"% V6 q" H4 \1 S5 Z5 }
  52. return "Collect "+str(n)+" of 4 fangs"& ?" C+ R- L! u
  53. return
    ; R9 `3 P& D& F. c# H

  54. % _( Q7 A$ ^! w3 B- J! i  Z# u
  55. QUEST    = Quest(201, "Tutorial", "Tutorial quest")
    - g* W6 x7 z9 Q7 Z" \& v# p2 O" u6 ]
  56. CREATED = State('Start',    QUEST)6 b( G3 A/ Q# L  S" d  Q
  57. STARTED = State('Started', QUEST)
    - {$ W" T7 B4 A: i+ U# e% N, Q- q
  58. COMPLETED = State('Completed', QUEST)
    1 @" Q4 S% c* c0 N

  59. 9 V! Z+ h- O- ^1 C& ]0 O/ S+ p
  60. QUEST.setInitialState(CREATED)6 j/ t  u  z( u" }5 D7 @
  61. QUEST.addStartNpc(7056)
    3 w) [% w4 b- K  p  r
  62. QUEST.addStartNpc(7012)2 ?& U$ u/ L& R/ k5 H
  63. QUEST.addStartNpc(7009)
    ) I- S% y8 p0 _& p; C; K! U
  64. QUEST.addStartNpc(7011)& D! B8 |/ Y3 }, h. O1 I" ~
  65. 6 y6 m. L% ?, o* a- z
  66. STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
    * _( N$ Z+ r  b- @' c9 M
  67. STARTED.addKillId(KELTIR_NPC_ID): ?# |6 `; Y) G6 m: s9 Y7 y) {
  68. STARTED.addTalkId(7056), {7 o3 b5 M' _* t
  69. STARTED.addTalkI d(7012)
    8 h% E5 i6 N' H3 s; R& O
  70. STARTED.addTalkId(7009)5 ^9 ?& K# b) R& I& I1 O6 p7 v. q
  71. STARTED.addTalkId(7011)
Скопировать код
0 B2 M& ?5 O2 N2 X( G
6 j3 @& R- ^1 U) {4 q
Чтобы ответить, вам надо авторизироваться в системе Вход | Зарегистрироваться

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

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

638638758

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

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

admin@artace.ru Онлайн

QR-код

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