Top.Mail.Ru

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

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

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

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

x
Хроники        Interlude
" G* W3 r) ^8 _) U( B4 mСборка        L2j- a  \) D/ `! K$ _* B
Обратите внимание: в файле htm стартового NCP обязательно должна быть ссылка на квест:
4 @0 W  }7 |# p/ h3 w0 R/ v
  1. STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код
Для этого квеста больше ничего не надо. Все необходимое для корректной работы квеста уже добавили. Вот полный текст квеста:8 }2 q4 }% E. L) G0 `  c  r- n
1 X" G6 L& Y" ~: K- w6 q
  1. if getCount(st) >= 4 :
    / n' R5 O7 C1 `2 L
  2. completed(st)' d" y! V/ N( i, Q; T, e3 p- r, c9 k
  3.   return# r- H6 b3 s8 l& o  Q+ t$ u0 t

  4. / L2 L9 D7 A  }' w# W: m
  5. class Quest (JQuest):
    ( ]$ f9 b! ^! D1 m
  6.   def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)' d; n8 ^$ L9 G, v6 R& C* \
  7.   def onEvent (self,event,st):2 C! ~# U8 k3 ~. a& z6 [2 l  I
  8. id = st.getState()
    * r  n  D% y+ V( K
  9. if   id == CREATED  : st.setState(STARTED)2 T( t8 G! v' s/ \6 {
  10. elif id == COMPLETED: pass% |/ b: t6 {1 @. h
  11. elif id == STARTED  : check(st)
    ( ~3 z! I% N. K* u7 h0 T' R
  12. return/ I! E0 q9 Z9 L  h& i  ^; ?  j1 Z

  13. " H6 S! s4 {# G0 l( i/ a
  14. QUEST     = Quest(201,"Tutorial", "Tutorial quest")
    2 u, S/ ?1 T* D: x1 k, a2 p+ }" [
  15. CREATED   = State('Start',     QUEST)
    # M  E& v/ F' D0 |8 h8 p( S
  16. STARTED   = State('Started',   QUEST)
    & m: o, p2 v* W5 |9 d& W
  17. COMPLETED = State('Completed', QUEST)
    ; V! d0 I, _$ _& r' ~, Q0 C( O

  18. # Z) @  B# s) `, ~& ~7 [. s
  19. QUEST.setInitialState(CREATED)7 L; q9 h- d% i% j
  20. QUEST.addStartNpc(7056)2 N' q6 Q# [# c8 u  u: k% j
  21. STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код
Теперь рассмотрим, как это работает.  p7 K7 N8 x4 t) I
Игрок подходит к начальному NCP (в данном случае 7056), нажимает на «Quest». Квест будет создан и состояние квеста перейдет к CREATED и игроку будет показана страничка Start.htm с описанием квеста. Тогда метод onEvent, поле открытия странички Start.htm переведет состояние квеста в STARTED и игроку будет показана страничка Started.htm, где будет опсание того, как найти keltirs и .т.д.
- G+ G" m# a4 ^/ M$ {% I
; T  W; ^* g7 Z0 {" [# J

0 e$ Q! I' Y: y' [! WПри состоянии STARTED будет зарегистрирован дроп «fangs» при убийстве keltirs. Игрок может вернуться к стартовому NCP и спросить о квесте – метод onEvent будет вызван снова. Если у игрока не хватает необходимого количества предметов, то метод check() не переведет квест в следующее состояние и Started.htm будет показана снова. Но если игрок собрал необходимее количество предметов (в данном случае 4 клыка), то метод check() вызовет метод completed() который переведет квест в новое состояние COMPLETED, заберет все клыки, даст карту мира, т.к. это награда за квест, покажет Completed.htm и завершит квест.
2 O8 L& J* y' D! F! y& K; y; C
$ T. A# G) d9 I

# ?) A! d0 e' m  E7 w4 d. wТеперь давайте сделаем наш квест более похожим на то, что он должен из себя представлять.  p2 r( p7 D  ^- h  h6 h
Прежде всего у нас есть 3 метода для объявления их в Яве – onTalk, onKill и onEvent. Если методы onTalk и onKill не объявлены, то за них все будет делать метод onEvent, т.е. определять квестовых монстров и вызывать диалоги NCP. Есть примечание, методы onTalk и onKill будут вызывать только диалоги с NCP в зависимости от текущего состояния квеста. Метод onKill будет вызываться только тогда, когда мы убиваем квестового монстра.3 U$ P' l' B! V. j% T
5 Z7 O$ G* K; k% U4 e

: b" V9 U3 O4 m; ^) ]Давайте рассмотрим как вызывается метод onKill при убийстве keltir в состоянии квеста STARTED:
  L4 a* G; c  d# d5 ^
  1. STARTED.addKillId(KELTIR_NPC_ID)
Скопировать код
и метод onKill в классе Quest:0 f; \& r3 D( S5 o# B+ i

. T# ?( @. i* s2 k/ Q4 L
  1. class Quest (JQuest):" T- n' v. w: z* l
  2.   ...0 s  ^* J8 M( R4 z  R4 H* h
  3.   def onKill (self,npcId,st):- d8 R- C9 k' S3 R" V* |
  4. if npcId == KELTIR_NPC_ID:
    6 Y  y3 ?) B/ q7 A( x
  5.    n = getCount(st)/ @7 `$ v2 j) C; e/ m" u, {* s
  6.    if   n == 0:
    8 E5 w! B* t& {) t! ]. {5 m
  7.        return "Chat0.htm"
    , D, M1 w0 B7 r4 N0 e
  8.    elif n == 1:$ o. Y, {$ g$ Z6 ?! e7 B( h5 d
  9.        return "Chat1.htm"
    ! n* l! o6 i; z9 Y$ [7 F$ _4 w
  10.    elif n >= 4:. n$ F  S% `. k& I4 ~9 }
  11.        return "Chat4.htm"$ x1 k  i$ t9 m0 P7 y4 j4 E
  12.    return "Collected "+str(n)+" of 4 fangs"
    ) l! X9 C/ p# ?6 v1 {
  13. return
Скопировать код
Метод onKill (а так же метод onTalk) имеет следующие параметры:9 _  Y/ v! u0 g$ |* \  k; @

3 K8 k- ]. I5 ^! `  A8 G8 N

' s- u' S8 v9 Y4 t2 t* X7 H; a2 Y; r• self – квест
& n  A; d4 }. X% C& C. u• npcId – ID NCP, которого мы должны убивать (если это метод onTalk, то ID того NCP, с которым мы должны поговорить).
/ P% J; I0 c$ d+ l• st – текущее состояние игрока.0 @+ q/ C  w; l7 f  @3 G
! q4 s: n2 \6 [! }8 @4 `4 Z; y

2 U0 u; _# x5 UВ этом методе мы проверяем и отмечаем, является ли убитый NCP keltir’ом. В основном эта проверка не нужна, т.к. у нас только KELTIR_NPC_ID.
/ Q; a1 X& P  z/ ?( \) {
  K- y- q$ K, E% W& z+ {

1 V9 L0 n" ^* n1 G- j7 V& AЗатем проверяем количество предметов (в данном случае количество клыков), и если их вообще нет, то возвращаем строку "Chat0.htm", если только один предмет, то возвращаем строку "Chat1.htm", если же предметов 4 или больше, то "Chat4.htm". Если строка возвращена из методов onEvent, onKill или onTalk, то сервер покажет соответствующие htm. В Chat0.htm может иметь следующий текст: «Вы не имеете ни одного клыка, возвращайтесь позже, когда соберете 4 штуки и бла, бла, бла…», в Chat1.htm может быть следующий текст: «У Вас всего 1 клык, по этому соберите еще…». В Chat4.htm – «Вы собрали необходимое количество предметов, возвращайтесь к вашему тренеру, что бы завершить квест…»4 F6 U% d6 F  X$ [0 ?7 f

9 L& [) u& [  i  i: K( ?, F+ x

$ q, X0 I0 q4 |8 R+ kПримечание: если в строка return начинается с "<html>", то будет показана страничка html с текстом, который стоит далее. Так вместо:
. x- w8 U" N2 s  e7 |& Preturn "Chat4.htm"
; D- S* j  M3 u( m* M; k" A0 h+ N) e' _$ _0 P( Q  e4 g
  V) B. ?4 V  _! t2 s' Q6 j$ B
можно поставить:" k) m1 T3 O1 @
  1. return "<html><body>Return to your trainer to complete the quest</body></html>"
Скопировать код
Так же если строка заканчивается без .htm или в начале нет <html>, то текст будет выведен, как системное сообщение в окне чата. В нашем случае мы сделаем так, что бы при каждом убийстве keltik выводилось системное сообщение: «Собрано N из 4-х клыков».  o, c% ~2 I8 P! b) ~( d: }1 A

+ J0 v# W( h8 y% F4 J0 s# h: t

. Y& S4 [8 [; \Наш код для onKill имеет один недостаток. Он будет постоянно показывать Chat0.htm, Chat1.htm и Chat4.htm, нам же необходимо, что бы Chat0.htm и Chat1.htm показывались только один раз. Как нам это сделать? С помощью переменных.
% d1 P- b# ~/ F. `' z) ~( ^! x
$ r, U8 R: |0 `& P$ A/ v2 L$ h
: z- e2 r4 _1 _5 t* Y5 Y* R+ C
В каждом квесте строки могут храниться с помощью переменных. Эти переменные сохраняются в Вашей БД. В каждом методе мы можем назначить, прочитать и удалить переменные. Давайте изменим метод onKill, так что бы каждый диалог вызывался только один раз.5 C/ N4 Z: @/ Q  ]( |/ S/ W$ b
  1. def onKill (self,npcId,st):* C# T2 w0 Y- `8 H
  2. if npcId == KELTIR_NPC_ID:
    - Q+ o5 D3 V" X4 w
  3. n = getCount(st)0 {0 q' G9 S$ h* Z2 Y& T# N5 H
  4. if n == 0:
    ' j5 x' ~% }# ]2 ?- J
  5. if st.get('chat0') == None :
    . V, r/ M% d- ^2 I
  6. st.set("chat0", "true")
      b6 U( h" G8 d
  7. return "Chat0.htm"# H# w( R$ Q, H( C0 q% ?5 D3 \
  8. elif n == 1:
    4 N. e  N  F- ~4 R4 e; e- Q
  9. if st.get('chat1') == None :  j' o& O/ Q- {# r. {" A
  10. st.set("chat1", "true")
    2 b( j0 v. o/ m% F5 I" }
  11. return "Chat1.htm"; |9 q2 O5 k1 V/ t0 N( B* }' r
  12. elif n >= 4:# `0 p$ z- y# L4 ]6 O- u1 F4 [: z
  13. return "Chat4.htm"! H) M% y- T) X- ~
  14. return "Collected "+str(n)+" of 4 fangs"
    ' k& N2 a4 T7 z4 y4 x
  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.' [" c8 q" x# K/ |7 d2 K
- B+ I! u% z8 m. S$ O  |4 ~
3 I# j* x. y) G+ d+ M" ^
Вот конечный рабочий вариант квеста:
6 J  Y1 v9 Z2 I. k/ S
  1. import sys5 J  [4 Q2 _0 y) P' e
  2. from net.sf.l2j.gameserver.model.quest import State2 T* i6 f1 Q  U6 F: Y' H
  3. from net.sf.l2j.gameserver.model.quest import QuestState# m- ]9 ]* e# H5 c
  4. from net.sf.l2j.gameserver.model.quest.jython import QuestJython as JQuest
    9 [' i7 U7 c1 j$ y6 d- V5 `

  5. 7 |' z8 t! a0 D4 e
  6. KELTIR_NPC_ID = 120824 t: f' E. f5 k, `3 n
  7. FANGS_ITEM_ID = 1859! Z* O% f' S- I; @" S/ h$ Z+ C
  8. DROP_RATE    = 5000002 ?0 x: z8 C" s; `% Y. j
  9. 3 X* C; |0 F( w8 z. _
  10. WORLD_MAP_ITEM_ID = 1665' U! d4 b+ S1 Q1 {. s; \9 n7 ^: N
  11. $ d. Z  R0 p% w) l
  12. def getCount(st) :
    ' j, n$ Q* Y& o5 }7 f6 }$ T
  13. return st.getQuestItemsCount(FANGS_ITEM_ID)5 g/ x# Y$ W: U
  14.   L7 t( w0 D# P% j3 d
  15. def completed(st) :. _0 ^, t  q3 B8 l( \7 U3 |, F  r9 u
  16. st.setState(COMPLETED)
    ( J5 k! `: W) G% B4 x# ?7 g
  17. st.clearQuestDrops()* ?1 F9 D; Y* W+ K
  18. st.takeItems(FANGS_ITEM_ID,-1)+ t: U# |+ A4 t* J: T5 w
  19. st.giveItems(WORLD_MAP_ITEM_ID,1)
    , h+ n$ e, B& S  L0 `% q
  20. st.exitQuest(False)5 B/ ?0 S. C  X5 x- H( E+ f( j
  21. return6 U1 ]! C4 d5 [' H2 q9 q2 b8 w& v
  22. . _& N6 ^1 ?8 W$ _
  23. def check(st) :
      a6 f: O5 w/ r* j
  24. if getCount(st) >= 4 :0 R# O# r' _' `# R( t: e1 ~
  25. completed(st)
    " Q# \% h- A. U% Y
  26. return
      e( @( b3 u% N5 T& f

  27. & R, q8 K( _) s# X. ~1 w; h1 z& s& ]
  28. class Quest (JQuest):
    , t. l8 g; b9 M+ [) K& `

  29. ' H. [1 V$ F; Q& X0 V6 P' K
  30. def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)
    - Q$ s# Z. N1 ?+ T- s

  31. " t' L* ]  R' Z
  32. def onEvent (self,event,st):
    ( I* a, q2 H- l
  33. id = st.getState()
    ; w$ Z+ A+ i7 U7 N" [) y4 _4 x
  34. if id == CREATED : st.setState(STARTED)
    , [$ e1 G) W# e2 i) _
  35. elif id == COMPLETED: pass3 K2 R' u0 m0 M# z! I  ?3 ~0 G# ]
  36. elif id == STARTED : check(st)
    ; v" Y- y  V) Y
  37. return
    / K& @& |( O7 L0 L0 g; I0 i
  38. 4 z) B( r: J8 O) N& l5 _
  39. def onKill (self,npcId,st):
    & X. `3 x' e7 ?. V& }) A
  40. if npcId == KELTIR_NPC_ID:
    8 O1 G, N1 f5 i- R# B8 L: {
  41. n = getCount(st)
    $ u1 T8 V8 h1 ?  M2 K' w9 l6 m
  42. if n == 0:
    & g- u; u/ m) a7 U! Z
  43. if st.get('chat0') == None :  p$ z! F, E2 c* q( H) J
  44. st.set("chat0", "true")
    6 ^" Z1 v3 |0 x
  45. return "Chat0.htm"
    6 y* S* y0 Y+ v
  46. elif n == 1:2 _; G6 Q5 Q. L- L+ r) H
  47. if st.get('chat1') == None :
    : j3 C& i! R4 R0 N& t  Q
  48. st.set("chat1", "true")
    + A  V) `& i0 r8 w6 b3 ?9 U
  49. return "Chat1.htm"! S6 ~+ T4 `7 Y$ ], b  f0 X
  50. elif n >= 4:
    6 T4 o; d4 L. _: ~* b
  51. return "Chat4.htm"3 y8 j! n5 }' {+ H- i
  52. return "Collect "+str(n)+" of 4 fangs"" J; [* V, X" D' k# _. P( Y* ~
  53. return8 b- j% E3 `" ?0 R% E

  54. 1 t3 n  Z7 C' ]; i# B
  55. QUEST    = Quest(201, "Tutorial", "Tutorial quest")/ m1 z* A  A" M
  56. CREATED = State('Start',    QUEST)
    6 i& c$ v+ a: n0 ^/ _% S9 [
  57. STARTED = State('Started', QUEST)
    4 i) P; }( p6 b# |
  58. COMPLETED = State('Completed', QUEST)
      f9 W7 |/ F9 K

  59. 7 \/ i" J' K2 f
  60. QUEST.setInitialState(CREATED)2 p' N+ q! m& X7 \2 ]
  61. QUEST.addStartNpc(7056)
    " v9 L& U! F6 v* X0 J) b' R( M
  62. QUEST.addStartNpc(7012)! w6 @( l( d+ {1 s* @' g
  63. QUEST.addStartNpc(7009)+ Q7 ~2 [( R! m: l* I5 U  m
  64. QUEST.addStartNpc(7011)  K8 p; q7 [5 Q6 Q" P2 m$ I* v

  65. . Q! h8 M% C- P
  66. STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)9 M& V. _+ N5 o: s
  67. STARTED.addKillId(KELTIR_NPC_ID)
    ( q$ M7 U3 E* ~7 V3 q
  68. STARTED.addTalkId(7056)# W; e2 z, ~% o4 w- i) g
  69. STARTED.addTalkI d(7012)
    ' I0 m0 O) r# e  g6 i" y! r/ r
  70. STARTED.addTalkId(7009)
    1 N1 |: ]( u  d
  71. STARTED.addTalkId(7011)
Скопировать код

! Y7 h; F, r( i, D! Q0 @1 l( R4 Z; Z' T$ ^9 s
Чтобы ответить, вам надо авторизироваться в системе Вход | Зарегистрироваться

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

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

638638758

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

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

admin@artace.ru Онлайн

QR-код

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