Top.Mail.Ru

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

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

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

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

x
Хроники        Interlude
' o3 W( P4 q; EСборка        L2j' \" d) X% Q; h, L
Обратите внимание: в файле htm стартового NCP обязательно должна быть ссылка на квест:
7 d- Y  e* ?) ]1 K( i  }
  1. STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код
Для этого квеста больше ничего не надо. Все необходимое для корректной работы квеста уже добавили. Вот полный текст квеста:
* U2 ]+ w8 x0 R% C, T' _/ z( G5 I9 m
% o6 V! N4 H  c. ]3 _; g
  1. if getCount(st) >= 4 :- e  d- Y9 A6 q( ]3 Z
  2. completed(st)
    - U# L( Z5 Q8 `: H! s. }
  3.   return6 i/ K6 K" m3 E9 ~5 q5 h# @' F( B, n
  4. & E+ F, x2 y( ?
  5. class Quest (JQuest):
    , Q% |5 T* a6 [3 U; n+ L
  6.   def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)0 [/ K4 N1 j+ X
  7.   def onEvent (self,event,st):
    + [: W! V& Q% z/ E: v3 R: C! S
  8. id = st.getState()
    , z; D# a- j) [2 H
  9. if   id == CREATED  : st.setState(STARTED)
    $ I6 }# l' b( j; _/ V
  10. elif id == COMPLETED: pass5 R% b/ T" `. g  _0 V
  11. elif id == STARTED  : check(st), B: o- Z0 I, c* ?( r$ V& i1 n
  12. return- H2 M) O; u2 t2 |% @& `

  13. 2 ^4 E: C+ s, |0 [7 n0 Z
  14. QUEST     = Quest(201,"Tutorial", "Tutorial quest")
    1 ^4 i, h+ h$ d
  15. CREATED   = State('Start',     QUEST)& z7 y- X- o2 x9 Z! D7 `
  16. STARTED   = State('Started',   QUEST)& E; {: @* V7 O- ]- B3 U+ F' r: ^( V
  17. COMPLETED = State('Completed', QUEST)
    / O+ N4 _: W  v. [

  18. & A* j9 M% I: d( u; g  B. R" D* K
  19. QUEST.setInitialState(CREATED): H* m5 X; {; \7 m) ^
  20. QUEST.addStartNpc(7056)- [/ ]/ j& P$ X9 v
  21. STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код
Теперь рассмотрим, как это работает.# @0 s2 I  }, ?( h5 |) b
Игрок подходит к начальному NCP (в данном случае 7056), нажимает на «Quest». Квест будет создан и состояние квеста перейдет к CREATED и игроку будет показана страничка Start.htm с описанием квеста. Тогда метод onEvent, поле открытия странички Start.htm переведет состояние квеста в STARTED и игроку будет показана страничка Started.htm, где будет опсание того, как найти keltirs и .т.д.
4 c2 y2 M2 B) O  e% N9 M
( E7 m' k  M* g3 }
# ?% j# e, l# ?8 F6 d( ^
При состоянии STARTED будет зарегистрирован дроп «fangs» при убийстве keltirs. Игрок может вернуться к стартовому NCP и спросить о квесте – метод onEvent будет вызван снова. Если у игрока не хватает необходимого количества предметов, то метод check() не переведет квест в следующее состояние и Started.htm будет показана снова. Но если игрок собрал необходимее количество предметов (в данном случае 4 клыка), то метод check() вызовет метод completed() который переведет квест в новое состояние COMPLETED, заберет все клыки, даст карту мира, т.к. это награда за квест, покажет Completed.htm и завершит квест.
+ L$ @' ]- v+ `& P! K
5 ~3 d. D& {% O8 X

4 Q, T3 S# M# c0 _) L7 |Теперь давайте сделаем наш квест более похожим на то, что он должен из себя представлять.& A/ b7 v. [" p' r+ j6 h
Прежде всего у нас есть 3 метода для объявления их в Яве – onTalk, onKill и onEvent. Если методы onTalk и onKill не объявлены, то за них все будет делать метод onEvent, т.е. определять квестовых монстров и вызывать диалоги NCP. Есть примечание, методы onTalk и onKill будут вызывать только диалоги с NCP в зависимости от текущего состояния квеста. Метод onKill будет вызываться только тогда, когда мы убиваем квестового монстра.
+ Z$ I" V$ g# e% Q! m6 `7 g" H. D2 K" [& h: e
2 k. e* w% A1 g8 d
Давайте рассмотрим как вызывается метод onKill при убийстве keltir в состоянии квеста STARTED:7 ?4 [# u# h/ q, ^% g- F9 G: ]
  1. STARTED.addKillId(KELTIR_NPC_ID)
Скопировать код
и метод onKill в классе Quest:
9 {& B4 p$ d, s! h6 g; j. s; V% i/ U; M
  1. class Quest (JQuest):8 t7 ~8 d. h9 {/ [) v
  2.   ...0 ?1 Z  R; c" O: \
  3.   def onKill (self,npcId,st):
    ) [; N" N0 B3 l% K' t- J
  4. if npcId == KELTIR_NPC_ID:  |; V! b1 `/ J8 c6 m& \8 ]
  5.    n = getCount(st)) A4 i# ~$ M5 d$ e* H
  6.    if   n == 0:4 E/ ^" U1 d4 q) l2 e
  7.        return "Chat0.htm"
    0 s9 k+ O# a2 q: ?
  8.    elif n == 1:
    " C' D, t( x- a
  9.        return "Chat1.htm"
    & w) d$ V+ K# B* K+ P
  10.    elif n >= 4:0 t3 N/ A: v$ Y& t2 E% ^
  11.        return "Chat4.htm"
      n3 I2 C$ w) f* n( f, w
  12.    return "Collected "+str(n)+" of 4 fangs"0 l. [+ o" _" Z
  13. return
Скопировать код
Метод onKill (а так же метод onTalk) имеет следующие параметры:
+ q" f# ]0 k: f* {- m: J' n$ i
3 T* |9 @, ~3 e' P! l9 e3 A

4 w1 x7 J+ x0 R- X• self – квест
" Q& P& _' W1 x6 K4 Z+ G$ N• npcId – ID NCP, которого мы должны убивать (если это метод onTalk, то ID того NCP, с которым мы должны поговорить).0 W; m* h2 |7 G) t' P) J+ z
• st – текущее состояние игрока.1 }. Y) x5 Q! [
* S+ p7 u- L# o( d# e4 Y
' A$ y/ z3 Q# g2 f; g" h
В этом методе мы проверяем и отмечаем, является ли убитый NCP keltir’ом. В основном эта проверка не нужна, т.к. у нас только KELTIR_NPC_ID.
. }; Q  W8 ?2 r# `; H4 q4 f/ @6 W- [' a1 L. D- h/ l: N0 D0 V+ @

$ t9 J; U8 Q# ZЗатем проверяем количество предметов (в данном случае количество клыков), и если их вообще нет, то возвращаем строку "Chat0.htm", если только один предмет, то возвращаем строку "Chat1.htm", если же предметов 4 или больше, то "Chat4.htm". Если строка возвращена из методов onEvent, onKill или onTalk, то сервер покажет соответствующие htm. В Chat0.htm может иметь следующий текст: «Вы не имеете ни одного клыка, возвращайтесь позже, когда соберете 4 штуки и бла, бла, бла…», в Chat1.htm может быть следующий текст: «У Вас всего 1 клык, по этому соберите еще…». В Chat4.htm – «Вы собрали необходимое количество предметов, возвращайтесь к вашему тренеру, что бы завершить квест…»
% s5 k8 B) s! J6 }0 |' j! S
  J, _5 `' B' y0 p3 \/ n% d" f

  E2 k: n2 q5 [. ~Примечание: если в строка return начинается с "<html>", то будет показана страничка html с текстом, который стоит далее. Так вместо:* R/ o  t- [% ]
return "Chat4.htm"
: l) O. a6 p2 d, G* ^1 O4 E/ a0 {% i+ \; C1 [9 r0 v

3 \+ y% q! A( V# ^9 {можно поставить:
; l' R$ ?' `. A5 z0 R/ E9 E
  1. return "<html><body>Return to your trainer to complete the quest</body></html>"
Скопировать код
Так же если строка заканчивается без .htm или в начале нет <html>, то текст будет выведен, как системное сообщение в окне чата. В нашем случае мы сделаем так, что бы при каждом убийстве keltik выводилось системное сообщение: «Собрано N из 4-х клыков»., u- i; j: |# g8 I; i/ i" A$ W
. j6 U, \1 A1 b) ~: a$ Z. o- e

& T: g! H2 k& m# J$ A' ~% Q; @9 cНаш код для onKill имеет один недостаток. Он будет постоянно показывать Chat0.htm, Chat1.htm и Chat4.htm, нам же необходимо, что бы Chat0.htm и Chat1.htm показывались только один раз. Как нам это сделать? С помощью переменных." A* P2 C5 d) b1 O, N) y6 G
6 W- x1 \+ v# @6 K" a6 G

2 {$ M) U8 K- {: f4 ~В каждом квесте строки могут храниться с помощью переменных. Эти переменные сохраняются в Вашей БД. В каждом методе мы можем назначить, прочитать и удалить переменные. Давайте изменим метод onKill, так что бы каждый диалог вызывался только один раз., `9 p9 V+ s7 l* \6 D) v: V: p2 S6 e6 [
  1. def onKill (self,npcId,st):8 e1 \* {% |) \" d7 i: }2 h- `4 J
  2. if npcId == KELTIR_NPC_ID:
    ! E7 ~2 \; P& w
  3. n = getCount(st)9 O8 ^7 q: S# g- u, v; Z$ f  `
  4. if n == 0:
    ; g5 C3 a3 [) s; ]3 o& v
  5. if st.get('chat0') == None :
    " i8 o* u0 Y( f* C
  6. st.set("chat0", "true")
    $ r" ^) T$ l: L. P" H
  7. return "Chat0.htm"/ U+ q6 y7 y: t, A
  8. elif n == 1:# S) M! C, S% O) H
  9. if st.get('chat1') == None :, i: _: Y6 \$ o8 r* A
  10. st.set("chat1", "true")
      \4 N) J: g0 b7 e# i1 i# Q' i  b
  11. return "Chat1.htm"
    ) b% r1 L# B2 y- C; \( M
  12. elif n >= 4:) ^! I# [# P' Q5 D0 n% `7 [' H
  13. return "Chat4.htm"
    9 f' b: ^: F! q1 E* @3 Z: n
  14. return "Collected "+str(n)+" of 4 fangs"
    & P- X4 E# a& z% }) x8 u# X2 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.
/ f% E3 _# T# n/ D8 V3 B+ @6 n0 I4 t( g- N/ V5 I% }

0 h8 F; b7 E% u- q+ NВот конечный рабочий вариант квеста:* g8 R. |* v( B7 t' w" X" k! T
  1. import sys1 b7 A/ q: x- T: X$ q# A
  2. from net.sf.l2j.gameserver.model.quest import State: r6 U6 L3 T  W! h' q
  3. from net.sf.l2j.gameserver.model.quest import QuestState
    ' d, F$ {3 T$ R. V  O
  4. from net.sf.l2j.gameserver.model.quest.jython import QuestJython as JQuest
    ( `+ b4 B6 [+ j. A
  5. 4 c1 A+ l$ V* ~9 z* ~$ U) h
  6. KELTIR_NPC_ID = 12082
    ) N, j' _& m4 e* M3 P
  7. FANGS_ITEM_ID = 1859
    " w; {  W$ M* T& G: C4 H( w
  8. DROP_RATE    = 500000& l, C6 s6 X8 w
  9. . G" _! A/ ~9 l. }# ~' s
  10. WORLD_MAP_ITEM_ID = 1665) d& Y6 s2 Q. u1 D  t
  11. 8 t- b  m' W7 y) y, U
  12. def getCount(st) :
    - H* m1 s& I8 V+ D- t- B
  13. return st.getQuestItemsCount(FANGS_ITEM_ID)4 D5 n  _: S7 d; n2 Y# ], H$ L8 E0 z

  14. & T& B+ |1 x: D9 H: |+ c
  15. def completed(st) :
    7 W4 K, S% W2 z( M* O
  16. st.setState(COMPLETED)  Q) y# x( y0 v8 r1 R0 O
  17. st.clearQuestDrops()2 }$ O& X. N! [6 g4 `
  18. st.takeItems(FANGS_ITEM_ID,-1)5 ~$ x! O: h: U& ^  k1 Y
  19. st.giveItems(WORLD_MAP_ITEM_ID,1)
    3 ~6 O, K9 Q/ r0 o) E, c+ H
  20. st.exitQuest(False)( ^% M; g1 J2 E/ P* }
  21. return! S% i, |6 C2 b, ^$ i7 o0 I

  22. 6 {2 a( ]( w* v; F+ o, w, ~
  23. def check(st) :2 w' @( ~; @4 Y3 c, i. L  L" p
  24. if getCount(st) >= 4 :
    2 a% t9 [. u# p! d) S2 W, R
  25. completed(st)1 s8 [( i' i: T- a2 O  M
  26. return
    , o$ b" \1 h" ]
  27. 0 N8 F. S8 V4 M. F
  28. class Quest (JQuest):
    " H/ ^" ?+ w7 K1 g: t

  29. 7 U' S" H& ?+ U2 ^
  30. def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr); \: M; o; M1 z* N& a* N  R  T
  31. 1 T1 W: N# x/ y# E( ]% u2 g* U" K
  32. def onEvent (self,event,st):
    2 k/ ~$ D, [$ U) ~& m' E
  33. id = st.getState()9 Q9 k2 t- n0 O& x: N- C
  34. if id == CREATED : st.setState(STARTED)' N' X. [* d7 @
  35. elif id == COMPLETED: pass
    % S9 O4 P- T  |4 V6 y* \* A
  36. elif id == STARTED : check(st): i/ B% \5 m5 o
  37. return0 S; {  ~8 n# O$ W

  38. 1 F6 @( k. F+ v$ Y, Q9 X
  39. def onKill (self,npcId,st):
    " w8 T' Y* B: I8 e  Z& T
  40. if npcId == KELTIR_NPC_ID:
    + E- V# f' v  J8 M# v4 {0 E5 Y
  41. n = getCount(st)2 O8 _+ |( S) H" P$ ^
  42. if n == 0:
    . W( a1 g9 w) }9 |( v
  43. if st.get('chat0') == None :0 s8 G7 k& b; A' y3 A  @) I1 x3 b
  44. st.set("chat0", "true")
    - q0 o& L0 ?' F) F0 l# ]
  45. return "Chat0.htm"
    1 c& I: p5 E' j4 J1 `& Y5 ^
  46. elif n == 1:
    , u/ |- I4 L- @' M& A. z7 Q
  47. if st.get('chat1') == None :
    $ K9 P) K. d# Z' _" j) Z
  48. st.set("chat1", "true")
    4 p; Y( @9 I" H( I. O7 B1 p/ I& Q
  49. return "Chat1.htm"; S/ h3 U+ ~) l% s$ C
  50. elif n >= 4:
    * D( I& s: E6 j4 K6 P' `3 N& A
  51. return "Chat4.htm"
    # }/ o, @/ D, K$ k' ~4 a5 e
  52. return "Collect "+str(n)+" of 4 fangs"' L" ]1 }& h* i% P( X
  53. return
    $ f4 q2 A& j3 g
  54. 3 N, i8 ~& A. x  h2 U. S0 S' Z
  55. QUEST    = Quest(201, "Tutorial", "Tutorial quest")
    8 `5 G" u* A: o0 f  l
  56. CREATED = State('Start',    QUEST)' d* v. g1 [  O6 ~
  57. STARTED = State('Started', QUEST)
    $ [. \, ]1 W6 ^. c
  58. COMPLETED = State('Completed', QUEST)
    " P5 |8 p. N8 ~7 h! |
  59. , t( T# q' U' V0 h! t
  60. QUEST.setInitialState(CREATED)$ m7 l$ _8 k, ]7 \+ J
  61. QUEST.addStartNpc(7056)2 L6 }$ F9 h# g; E; N: P* c
  62. QUEST.addStartNpc(7012)
    ! Y5 ^- ^7 {1 j% y2 v
  63. QUEST.addStartNpc(7009)$ y8 Q7 p/ D# z5 G1 F1 L+ _, \
  64. QUEST.addStartNpc(7011)
    2 z' `3 c& P, x" K

  65. 1 P% G4 p# X7 D* z. m9 G
  66. STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
    2 M8 i- b0 S+ d/ K
  67. STARTED.addKillId(KELTIR_NPC_ID)/ [  R4 {; N( K% o" y% q& @& N
  68. STARTED.addTalkId(7056)
    5 g# N: P# Y- {1 J3 U
  69. STARTED.addTalkI d(7012)
    & ?8 S, P; w9 b. J; t
  70. STARTED.addTalkId(7009)! |8 ^$ t0 ^  g' X' f# c! i
  71. STARTED.addTalkId(7011)
Скопировать код

, \- Q2 G0 `+ ]2 G! W9 r" T% g* b% w  i5 P4 ^# V% b
Чтобы ответить, вам надо авторизироваться в системе Вход | Зарегистрироваться

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

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

638638758

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

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

admin@artace.ru Онлайн

QR-код

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