Top.Mail.Ru

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

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

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

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

x
Хроники        Interlude; l! x: y4 b; `  B& o) Z9 C
Сборка        L2j; ~( E8 u+ Z. Z& s; E  w% ^
Обратите внимание: в файле htm стартового NCP обязательно должна быть ссылка на квест:
5 m3 u& F  i3 k5 Z  k0 a! _0 n( n2 v
  1. STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код
Для этого квеста больше ничего не надо. Все необходимое для корректной работы квеста уже добавили. Вот полный текст квеста:5 ?2 p% H4 k) X: ^4 r
9 m) [7 t5 y8 w$ s5 s
  1. if getCount(st) >= 4 :1 ]! z5 Z' r( N" [. e% ?
  2. completed(st)* b1 ?; T! X. C2 r
  3.   return% E& o4 N. A4 p8 X1 `

  4. * e* F, H: t  k4 O; K" n$ u! {6 I
  5. class Quest (JQuest):/ T% w6 F% _7 E3 e( E5 ?
  6.   def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)0 q( Z8 L1 _1 b
  7.   def onEvent (self,event,st):
    , H2 K' {$ _) G7 Y
  8. id = st.getState()
    6 |+ j* a* m) R+ G  |& {; p- V
  9. if   id == CREATED  : st.setState(STARTED)2 [9 b! T( @( O% \5 W8 o1 ~
  10. elif id == COMPLETED: pass
    4 C9 B8 g, ^2 U1 @- U
  11. elif id == STARTED  : check(st). y8 G/ W" w, {; |
  12. return
    4 H9 r% W! v2 V8 B

  13. / F$ r, s. A; G6 l
  14. QUEST     = Quest(201,"Tutorial", "Tutorial quest")
      Q+ G# Y: k( A0 P4 _9 b; s8 g0 j
  15. CREATED   = State('Start',     QUEST)1 K: J7 \) |. G; R
  16. STARTED   = State('Started',   QUEST)
    4 M" G4 w9 }# _+ T+ U! t2 F7 q1 {
  17. COMPLETED = State('Completed', QUEST)
    7 r6 C1 T! L! \3 r
  18. 0 U  y$ a7 Y& t  Y
  19. QUEST.setInitialState(CREATED)
    3 E! W& }" t9 d1 e: j0 d  u
  20. QUEST.addStartNpc(7056)/ o; T& A# E6 F
  21. STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код
Теперь рассмотрим, как это работает.# B  d/ X! o9 L! W7 @4 ]! q2 Z6 r+ b
Игрок подходит к начальному NCP (в данном случае 7056), нажимает на «Quest». Квест будет создан и состояние квеста перейдет к CREATED и игроку будет показана страничка Start.htm с описанием квеста. Тогда метод onEvent, поле открытия странички Start.htm переведет состояние квеста в STARTED и игроку будет показана страничка Started.htm, где будет опсание того, как найти keltirs и .т.д.
% @; G. m4 w2 h; ^# K4 x( y: x4 P6 D, I3 ~1 N) M
8 a4 a8 U0 R5 p# G1 O2 _
При состоянии STARTED будет зарегистрирован дроп «fangs» при убийстве keltirs. Игрок может вернуться к стартовому NCP и спросить о квесте – метод onEvent будет вызван снова. Если у игрока не хватает необходимого количества предметов, то метод check() не переведет квест в следующее состояние и Started.htm будет показана снова. Но если игрок собрал необходимее количество предметов (в данном случае 4 клыка), то метод check() вызовет метод completed() который переведет квест в новое состояние COMPLETED, заберет все клыки, даст карту мира, т.к. это награда за квест, покажет Completed.htm и завершит квест.
* Q2 g; u- G1 H) c8 p; ?+ ^
# o, _  p- m0 n% j& ?

( k$ ^7 u+ e& O* VТеперь давайте сделаем наш квест более похожим на то, что он должен из себя представлять.0 t( y0 C5 i6 k& l1 b6 k$ x' c; C( T, ?$ O
Прежде всего у нас есть 3 метода для объявления их в Яве – onTalk, onKill и onEvent. Если методы onTalk и onKill не объявлены, то за них все будет делать метод onEvent, т.е. определять квестовых монстров и вызывать диалоги NCP. Есть примечание, методы onTalk и onKill будут вызывать только диалоги с NCP в зависимости от текущего состояния квеста. Метод onKill будет вызываться только тогда, когда мы убиваем квестового монстра.
% J; ~2 e) {+ Q3 |
1 ?* X2 Y0 V2 Q2 b: N, D6 a3 J/ c$ o; U

: a* z6 S" _7 C$ BДавайте рассмотрим как вызывается метод onKill при убийстве keltir в состоянии квеста STARTED:. j4 x/ H- J0 G% g( i1 ?
  1. STARTED.addKillId(KELTIR_NPC_ID)
Скопировать код
и метод onKill в классе Quest:7 _9 c+ C5 l0 `: h( B4 G
0 e2 r8 s5 U1 j+ x, r' ~
  1. class Quest (JQuest):/ `! J4 c. A* z# g2 X: c6 e0 s
  2.   ...
    . @' P% B" H' _' q
  3.   def onKill (self,npcId,st):; Z% p, x, V8 c$ n2 _4 p! B
  4. if npcId == KELTIR_NPC_ID:
    % y+ _/ K4 o! |
  5.    n = getCount(st)! p, R  S, k+ w6 Q  Y8 C
  6.    if   n == 0:' g8 b# o+ y8 e4 g7 N
  7.        return "Chat0.htm"
    ) `1 I) G$ e) s6 I+ Y$ z9 ^
  8.    elif n == 1:
    2 I7 a1 t" N! ~. z3 M+ N' x
  9.        return "Chat1.htm"
    & o! A& T7 h! q$ c6 {% f
  10.    elif n >= 4:
    ! n9 v. \) z. B+ y/ |
  11.        return "Chat4.htm": b& M0 F# }" V& {! H6 A8 i; M
  12.    return "Collected "+str(n)+" of 4 fangs"/ n$ ?4 _" B( Q% h/ x. O
  13. return
Скопировать код
Метод onKill (а так же метод onTalk) имеет следующие параметры:
5 \2 F5 i2 O+ o; F1 K% ]* Q6 p% J
' Z, K# t: C: J1 z3 M1 y
8 t. K3 U( i! L; k
• self – квест
& W6 \+ v9 ^1 _- E• npcId – ID NCP, которого мы должны убивать (если это метод onTalk, то ID того NCP, с которым мы должны поговорить).% y. Y* }. P4 Q: k3 z6 b
• st – текущее состояние игрока.
: t) N: ]  u" H
9 u  m4 B2 Q5 \) Z' P/ m+ U2 r
2 _5 t$ _' K) u. w
В этом методе мы проверяем и отмечаем, является ли убитый NCP keltir’ом. В основном эта проверка не нужна, т.к. у нас только KELTIR_NPC_ID.
1 D0 e" e' k' @) }; z' z& q
) O, d8 u! b; ^! ^
5 S( H/ V6 I. n. `) n" O
Затем проверяем количество предметов (в данном случае количество клыков), и если их вообще нет, то возвращаем строку "Chat0.htm", если только один предмет, то возвращаем строку "Chat1.htm", если же предметов 4 или больше, то "Chat4.htm". Если строка возвращена из методов onEvent, onKill или onTalk, то сервер покажет соответствующие htm. В Chat0.htm может иметь следующий текст: «Вы не имеете ни одного клыка, возвращайтесь позже, когда соберете 4 штуки и бла, бла, бла…», в Chat1.htm может быть следующий текст: «У Вас всего 1 клык, по этому соберите еще…». В Chat4.htm – «Вы собрали необходимое количество предметов, возвращайтесь к вашему тренеру, что бы завершить квест…»
7 q8 c5 ]$ C/ W& u. L
5 T$ b  d6 G1 {5 }2 ~( \
* S) t  j! R1 v" `
Примечание: если в строка return начинается с "<html>", то будет показана страничка html с текстом, который стоит далее. Так вместо:# l' r% U$ J: [  X  O# W" y4 \
return "Chat4.htm"
( V( j  X, i/ _6 ^" w) |. S) T. K! y
. w5 v7 }% A3 N
можно поставить:; K" c: m. ^  P7 \& ^
  1. return "<html><body>Return to your trainer to complete the quest</body></html>"
Скопировать код
Так же если строка заканчивается без .htm или в начале нет <html>, то текст будет выведен, как системное сообщение в окне чата. В нашем случае мы сделаем так, что бы при каждом убийстве keltik выводилось системное сообщение: «Собрано N из 4-х клыков».
$ ?. M: n) u' j% K9 G( V4 Z: Z' s, m6 }$ D; N. p* n

& w4 {* O; a( g7 y1 x2 F; lНаш код для onKill имеет один недостаток. Он будет постоянно показывать Chat0.htm, Chat1.htm и Chat4.htm, нам же необходимо, что бы Chat0.htm и Chat1.htm показывались только один раз. Как нам это сделать? С помощью переменных.: P) _5 P' [! A* {
' s# G3 S! L  {4 V* t! A

. v* H1 M2 }$ Z3 t* g, B5 B7 DВ каждом квесте строки могут храниться с помощью переменных. Эти переменные сохраняются в Вашей БД. В каждом методе мы можем назначить, прочитать и удалить переменные. Давайте изменим метод onKill, так что бы каждый диалог вызывался только один раз." g+ w" x% Y: D1 s
  1. def onKill (self,npcId,st):& G: ?# [; f. a9 |( x7 ]
  2. if npcId == KELTIR_NPC_ID:0 @! h" d/ q2 x. r- l5 I
  3. n = getCount(st)5 p! _4 h# M/ C2 W0 w
  4. if n == 0:2 @' |! n( n% e
  5. if st.get('chat0') == None :
    4 z. x+ F. J& Y3 g/ U8 Y
  6. st.set("chat0", "true")) M6 L& z5 e' |- D
  7. return "Chat0.htm"
    ( x! P) q' J$ Z
  8. elif n == 1:! I1 u9 M/ I5 d; a( @) [
  9. if st.get('chat1') == None :
    0 U/ f3 T3 U% F5 Y; R# s
  10. st.set("chat1", "true")  Z" {$ `9 G5 m8 q3 Y7 \+ j2 F* K0 w
  11. return "Chat1.htm"# o0 a4 {. F/ {$ y' Y5 q" ~$ i
  12. elif n >= 4:% i( }% ?6 Z, g& H
  13. return "Chat4.htm"
    1 P# t4 I9 n+ h) C
  14. return "Collected "+str(n)+" of 4 fangs"/ @0 |: A# p# w2 D8 Q
  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.' Z1 u+ X& j6 H7 V; h$ N
* b1 r8 c* p% {& m5 t' v: u
' m0 n8 L' X3 S0 n
Вот конечный рабочий вариант квеста:* C( ?% w$ R( a- ~
  1. import sys
    + s& H3 M) ?4 R# \/ g8 g6 A
  2. from net.sf.l2j.gameserver.model.quest import State- M+ f, l% {+ P  j4 t
  3. from net.sf.l2j.gameserver.model.quest import QuestState
    , C9 f& n. p2 @* u8 `
  4. from net.sf.l2j.gameserver.model.quest.jython import QuestJython as JQuest# m* y$ Y' G: c2 M  i7 K

  5. ! |8 Q; e$ q, V7 D, p
  6. KELTIR_NPC_ID = 12082
    5 [& Z& o, n5 ?
  7. FANGS_ITEM_ID = 18591 ?7 K9 {* B6 M7 w% {3 _# I
  8. DROP_RATE    = 500000
    ! v6 y1 I4 j9 t. x! I
  9. : G& Q; L6 N( f. O8 Z" Q% y: t
  10. WORLD_MAP_ITEM_ID = 1665
    - I4 q7 Y" u4 s" t# E4 z

  11. 3 H' D1 W3 P! q% D1 z8 ^2 b
  12. def getCount(st) :1 P9 `  W5 w: n2 X# P5 c
  13. return st.getQuestItemsCount(FANGS_ITEM_ID)
    8 c- r7 i3 ?/ K

  14. 7 d' h! M# E' C
  15. def completed(st) :; H) |' a* a/ Q# [& W+ a7 _
  16. st.setState(COMPLETED)
      @7 g* |' l. \+ @& l7 ?' @
  17. st.clearQuestDrops()
    ( c6 l0 P2 r1 ?0 |9 [
  18. st.takeItems(FANGS_ITEM_ID,-1)1 }$ {  v0 y: G' I) P
  19. st.giveItems(WORLD_MAP_ITEM_ID,1)
    7 e1 \* R1 G, F- }
  20. st.exitQuest(False)
    2 W# T/ ]3 K& b9 P+ O. m
  21. return
    $ N$ }! ]) [! }) j; R

  22. 1 e5 x. k) d/ ~9 A
  23. def check(st) :9 X0 H3 G# y& l9 i8 T% J4 ~
  24. if getCount(st) >= 4 :
    ) _7 A5 U& R. Z/ I+ t
  25. completed(st)* \* d( r) E/ {. @1 J' A7 c
  26. return' ~  j" K; ^6 q
  27. 4 B2 C! I& p3 \& Q7 M
  28. class Quest (JQuest):8 t0 ^# |! T6 w1 e$ o& l) a

  29. # Q( G6 }+ A* e+ y0 P
  30. def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)6 _1 c4 b( j2 t: o! x' l
  31. - \. _! T  l! u0 x% u
  32. def onEvent (self,event,st):$ y. w6 S( G9 S0 T
  33. id = st.getState()- @: p- ~" X9 I. F7 F
  34. if id == CREATED : st.setState(STARTED)
    : q6 Y0 V% E  {) ?
  35. elif id == COMPLETED: pass
    ; [4 P/ J* J2 F1 x
  36. elif id == STARTED : check(st)( ^+ o1 x7 @( h- M( ?) `
  37. return) i2 s8 ]" P, Y" x2 u/ r

  38. 9 f* r  L# @& F2 L, B- I+ s
  39. def onKill (self,npcId,st):6 `# c) x% t, E8 v9 w5 u- \
  40. if npcId == KELTIR_NPC_ID:( }% O" u, T# T7 S( N. a( q6 U
  41. n = getCount(st)( u; u- i6 b4 H3 h( w" J
  42. if n == 0:
    ! h+ c2 f  C( o' P8 ]7 p
  43. if st.get('chat0') == None :6 [; r5 D6 z) V6 U/ q0 K) l9 d
  44. st.set("chat0", "true")4 H6 N8 G7 x' Y/ }/ I) P* Y
  45. return "Chat0.htm", L. f) O) r9 n- H4 `4 t! K: M
  46. elif n == 1:
    5 s8 ~; j, }4 }$ g) d& S
  47. if st.get('chat1') == None :
    0 x! x5 s7 r: ]* I
  48. st.set("chat1", "true")0 ]* h' _' r9 X$ ~# a
  49. return "Chat1.htm"( B, {2 Y$ ]  P; v1 H
  50. elif n >= 4:
    / G/ d8 ]# R: k8 z+ `2 M& ^& z
  51. return "Chat4.htm"
    - e8 X7 C% M9 j3 V; X: ?% N& o
  52. return "Collect "+str(n)+" of 4 fangs"5 e: d+ F* K) \" g4 z
  53. return
    , b6 n7 F* R/ l: C

  54. " Y& b2 M# o, o: O, D# l
  55. QUEST    = Quest(201, "Tutorial", "Tutorial quest")" A" ^7 i  i1 A: b% h
  56. CREATED = State('Start',    QUEST): S* ?- N3 N+ V, [7 J
  57. STARTED = State('Started', QUEST)' C+ B4 i' p6 Q- H* ~+ U6 F
  58. COMPLETED = State('Completed', QUEST)
    & W- k& e, M* h  J" T# |, m

  59.   Q6 Q: z, q) s" v0 q+ H+ U( c
  60. QUEST.setInitialState(CREATED)
    % j# w3 G7 c1 M/ |1 D/ |
  61. QUEST.addStartNpc(7056)
    : v" L& H" q+ W5 K% V# [7 O5 h# p
  62. QUEST.addStartNpc(7012)# a" K5 U4 H& K, ~, ]% r( b  g, |4 h
  63. QUEST.addStartNpc(7009)# Y) i) ?) `& o, ~4 z3 @3 [
  64. QUEST.addStartNpc(7011)
    + I9 E3 Y- V, Z, K) v
  65. % I* u/ h  [  @& p
  66. STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)- g- {7 F$ E# ]
  67. STARTED.addKillId(KELTIR_NPC_ID)( B# ~# H! {5 J, K% U
  68. STARTED.addTalkId(7056)# k2 g$ P, Y) t3 Z
  69. STARTED.addTalkI d(7012)
    % j' O) s- J; y; \/ c4 V
  70. STARTED.addTalkId(7009)& }0 o7 d: ?# v# z
  71. STARTED.addTalkId(7011)
Скопировать код

6 n1 G# D; x7 y6 o$ `5 V+ ?: u+ X
* G! j* [3 b7 j4 K' ?9 h; a# g
Чтобы ответить, вам надо авторизироваться в системе Вход | Зарегистрироваться

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

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

638638758

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

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

admin@artace.ru Онлайн

QR-код

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