Top.Mail.Ru

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

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

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

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

x
Хроники        Interlude) u# V  @) F2 U
Сборка        L2j. F0 _  [" k0 A
Обратите внимание: в файле htm стартового NCP обязательно должна быть ссылка на квест:. j' h" S- f) L: H" P* b
  1. STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код
Для этого квеста больше ничего не надо. Все необходимое для корректной работы квеста уже добавили. Вот полный текст квеста:
/ s  P  _: V( `( e* Q: m
% M5 ^0 Z' w2 s! T0 R6 ?$ y: N
  1. if getCount(st) >= 4 :+ y, c) t. e+ P8 A
  2. completed(st)) H; _4 d/ X7 [8 S6 P
  3.   return
    0 @! S) |5 E6 ^; @. u$ b' _) e

  4. ! q) ^3 S! U- t% A/ Y
  5. class Quest (JQuest):
    6 S6 f0 n! s' N# {9 {  _
  6.   def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)* e7 r" t/ r7 z, g( ]7 d
  7.   def onEvent (self,event,st):3 T. X( T  Q" m0 h$ B4 s, s7 o
  8. id = st.getState()
    1 z- c; _6 z  V" k, N! Q
  9. if   id == CREATED  : st.setState(STARTED)
    3 ^4 o4 \/ E; R+ A
  10. elif id == COMPLETED: pass
    & Q! z' l% R  }+ j
  11. elif id == STARTED  : check(st)
    # x5 v% r0 r( S, [
  12. return5 \' j% o; d% k

  13. . n% n( c" D" K! V' q+ m* k& T5 e
  14. QUEST     = Quest(201,"Tutorial", "Tutorial quest")) n7 ~# t& P# l. T+ R
  15. CREATED   = State('Start',     QUEST)& S7 O% W- c; L/ k1 n: Q4 y
  16. STARTED   = State('Started',   QUEST)% I$ x5 e0 X" H5 p2 @$ c2 w: x
  17. COMPLETED = State('Completed', QUEST)
    $ }5 y6 @8 Z! E+ Y6 y6 a; S, U; T" G
  18. 2 j* z* Q6 n# _& w: b# K9 a2 r
  19. QUEST.setInitialState(CREATED)& o7 ~0 x4 c* S. E/ i
  20. QUEST.addStartNpc(7056)
    1 q1 ?' g: \# x( \" \& }. B+ Z, s& w
  21. STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код
Теперь рассмотрим, как это работает.3 ~, g7 E) M! f
Игрок подходит к начальному NCP (в данном случае 7056), нажимает на «Quest». Квест будет создан и состояние квеста перейдет к CREATED и игроку будет показана страничка Start.htm с описанием квеста. Тогда метод onEvent, поле открытия странички Start.htm переведет состояние квеста в STARTED и игроку будет показана страничка Started.htm, где будет опсание того, как найти keltirs и .т.д.3 p: v% R) b5 W) D* W

: l- Y  d- Q8 z. A

, J- u8 a! i0 TПри состоянии STARTED будет зарегистрирован дроп «fangs» при убийстве keltirs. Игрок может вернуться к стартовому NCP и спросить о квесте – метод onEvent будет вызван снова. Если у игрока не хватает необходимого количества предметов, то метод check() не переведет квест в следующее состояние и Started.htm будет показана снова. Но если игрок собрал необходимее количество предметов (в данном случае 4 клыка), то метод check() вызовет метод completed() который переведет квест в новое состояние COMPLETED, заберет все клыки, даст карту мира, т.к. это награда за квест, покажет Completed.htm и завершит квест.0 H* L8 j* w1 s0 i5 R

, M- H- |8 ^8 y7 \+ W( c# d& a
6 |* ?) D, d* \' b2 `+ S
Теперь давайте сделаем наш квест более похожим на то, что он должен из себя представлять.
  \3 z* D% m# r9 \, c& [$ fПрежде всего у нас есть 3 метода для объявления их в Яве – onTalk, onKill и onEvent. Если методы onTalk и onKill не объявлены, то за них все будет делать метод onEvent, т.е. определять квестовых монстров и вызывать диалоги NCP. Есть примечание, методы onTalk и onKill будут вызывать только диалоги с NCP в зависимости от текущего состояния квеста. Метод onKill будет вызываться только тогда, когда мы убиваем квестового монстра.
* U; T" L- \# F" ~7 k& p$ q% w0 Q. T. y# c

. o8 S' K5 }  z% P- u+ H- `. x9 t) GДавайте рассмотрим как вызывается метод onKill при убийстве keltir в состоянии квеста STARTED:! g/ G. M) U% B( g, R* e
  1. STARTED.addKillId(KELTIR_NPC_ID)
Скопировать код
и метод onKill в классе Quest:
% [2 ~9 O% g+ Z  x; J
$ n: }" j! j. I( }" B
  1. class Quest (JQuest):- [! _0 ~9 p  p% z
  2.   ...
    ( m: f* C8 J' I5 \, E2 A) R7 Q
  3.   def onKill (self,npcId,st):) o0 E; ~2 L6 r( z, x2 d  m0 h. G+ F8 H+ l
  4. if npcId == KELTIR_NPC_ID:( W  h6 H/ f7 }9 M; e. A: F
  5.    n = getCount(st)
    / l/ S9 y2 {! o; ~; Y# B8 p
  6.    if   n == 0:) k& [: ^: i5 z2 }/ D! A9 R
  7.        return "Chat0.htm") @: T; @; G1 h- W
  8.    elif n == 1:* s  Q0 b# F$ V; P
  9.        return "Chat1.htm"
    0 t( W! u$ I9 U8 `
  10.    elif n >= 4:: ?& h) {( Q. E" r6 L
  11.        return "Chat4.htm"
    $ \' N: @% x/ h
  12.    return "Collected "+str(n)+" of 4 fangs"
    ' @/ Z5 x. y  y9 W2 f1 \
  13. return
Скопировать код
Метод onKill (а так же метод onTalk) имеет следующие параметры:0 o0 Q/ C6 D7 p

& O) Y* O1 g/ n. [

  {; s* J1 |* l$ p* A% t0 q• self – квест) `- `9 N3 X' j1 i9 b
• npcId – ID NCP, которого мы должны убивать (если это метод onTalk, то ID того NCP, с которым мы должны поговорить).
* ?9 g8 P8 t4 G  Q4 u% z9 E• st – текущее состояние игрока.
( |2 W/ L5 @; H4 s; R& n6 j/ j: z6 m+ b' c
$ q7 A6 X$ \- R' B( B* `' R
В этом методе мы проверяем и отмечаем, является ли убитый NCP keltir’ом. В основном эта проверка не нужна, т.к. у нас только KELTIR_NPC_ID.
& z# T) i% E# A. P; w. L7 b
- ]/ d( U4 d7 L$ G; D

7 P; s0 @" S/ F* }2 E6 yЗатем проверяем количество предметов (в данном случае количество клыков), и если их вообще нет, то возвращаем строку "Chat0.htm", если только один предмет, то возвращаем строку "Chat1.htm", если же предметов 4 или больше, то "Chat4.htm". Если строка возвращена из методов onEvent, onKill или onTalk, то сервер покажет соответствующие htm. В Chat0.htm может иметь следующий текст: «Вы не имеете ни одного клыка, возвращайтесь позже, когда соберете 4 штуки и бла, бла, бла…», в Chat1.htm может быть следующий текст: «У Вас всего 1 клык, по этому соберите еще…». В Chat4.htm – «Вы собрали необходимое количество предметов, возвращайтесь к вашему тренеру, что бы завершить квест…»
7 ?, E* Q) l7 @+ i/ t0 q
- o* J( I$ _" R; u! O0 ~8 ~* G6 g

2 t; N3 R* L* M' ]8 S' wПримечание: если в строка return начинается с "<html>", то будет показана страничка html с текстом, который стоит далее. Так вместо:
  A6 f- t$ ]) ^) `return "Chat4.htm"5 R8 ]- G3 r$ b" g; W

4 W1 S! K* Z/ g& F' ?- G! t2 k# \
0 ]8 p9 Y1 ~+ f, w9 [1 d
можно поставить:
* k3 D" M% q! u- o; ?4 R
  1. return "<html><body>Return to your trainer to complete the quest</body></html>"
Скопировать код
Так же если строка заканчивается без .htm или в начале нет <html>, то текст будет выведен, как системное сообщение в окне чата. В нашем случае мы сделаем так, что бы при каждом убийстве keltik выводилось системное сообщение: «Собрано N из 4-х клыков».2 v+ s) Z1 v3 C4 T8 Y' q
1 x* q# |' ?% }, E$ U- u& d
# M# A' O9 w6 K2 w5 F
Наш код для onKill имеет один недостаток. Он будет постоянно показывать Chat0.htm, Chat1.htm и Chat4.htm, нам же необходимо, что бы Chat0.htm и Chat1.htm показывались только один раз. Как нам это сделать? С помощью переменных.
+ E: d& n4 P2 X6 e* _' z4 o. d/ q+ `( x
, k; Q4 y, v% ?8 M' v# T$ }

" ~) j/ O& ]% G( f# jВ каждом квесте строки могут храниться с помощью переменных. Эти переменные сохраняются в Вашей БД. В каждом методе мы можем назначить, прочитать и удалить переменные. Давайте изменим метод onKill, так что бы каждый диалог вызывался только один раз.
6 [# P4 l: D1 O/ ^0 z
  1. def onKill (self,npcId,st):2 g) j# i- C$ c& a6 S% d
  2. if npcId == KELTIR_NPC_ID:
    + `' B. S) P' s
  3. n = getCount(st)7 Q2 f* @7 Q# I: H* w7 X6 a6 F
  4. if n == 0:
    ' v5 f: D% }' J; M
  5. if st.get('chat0') == None :. m3 k4 p$ @* |+ M) S6 y. e) |
  6. st.set("chat0", "true")1 l' {# ~$ u. W( V" J
  7. return "Chat0.htm"( q) ?, Z( \9 ^7 j1 Q1 @
  8. elif n == 1:
    7 K, @* A4 [/ ?- O
  9. if st.get('chat1') == None :
    ; ?' n- c5 c9 l* M. T: l3 q5 g; v# l
  10. st.set("chat1", "true")9 k$ C2 k  p, V2 U/ h9 M0 ?
  11. return "Chat1.htm"
    * j* F6 P+ o" }
  12. elif n >= 4:
    ) ]* j/ ?# y' t$ h5 D
  13. return "Chat4.htm") P5 n% {- D4 S8 m# t7 y- F& j
  14. return "Collected "+str(n)+" of 4 fangs"5 t0 R# s/ }& k  [4 ~9 E! s
  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.
! S, }1 @7 V% L7 |( J0 ~) X! T) W' Z
/ d, c, |3 }# A, H) @
Вот конечный рабочий вариант квеста:6 S  ]: P! i5 m  W
  1. import sys
    0 B' F& \: L# a# v
  2. from net.sf.l2j.gameserver.model.quest import State
    9 |% U8 m+ N0 b* U, d
  3. from net.sf.l2j.gameserver.model.quest import QuestState1 {% z. W1 u* ~3 Z! Q- t  T
  4. from net.sf.l2j.gameserver.model.quest.jython import QuestJython as JQuest
    6 K8 K# g  C% X: p
  5. 2 p" K% m* c9 n' Q0 {' R
  6. KELTIR_NPC_ID = 12082
    # S$ B2 g* e" Z7 E1 \; O
  7. FANGS_ITEM_ID = 18598 y# ~4 p6 t& K% }% i) {
  8. DROP_RATE    = 500000
    ) y; C& G; L& s. v& F; W

  9. 6 j" G: f& R' `! u3 z3 M0 B
  10. WORLD_MAP_ITEM_ID = 1665
    ; E$ f0 {+ e# i: h+ ?6 ~9 ^

  11. / B2 N/ K$ i0 S! Q! O9 p8 `
  12. def getCount(st) :
    0 `" j# m3 X) o6 L4 t0 d
  13. return st.getQuestItemsCount(FANGS_ITEM_ID)
    ' N! O& m2 i8 u
  14. & V0 g. Z- `; h. `9 {( i
  15. def completed(st) :% M' P1 w+ |  x' ?# t7 u: d
  16. st.setState(COMPLETED)
      Q7 w' \0 ?6 a1 f+ m6 H
  17. st.clearQuestDrops()
    7 A# ]1 R* L- ^4 ^, j% J
  18. st.takeItems(FANGS_ITEM_ID,-1)6 ?/ F) y2 Q9 j" w) Q9 |
  19. st.giveItems(WORLD_MAP_ITEM_ID,1)2 Z8 A% V) X0 O* v# G2 e5 _
  20. st.exitQuest(False)
    + p$ r: D6 h* E: X
  21. return
    / y& j$ }! j8 `. [
  22. , B2 m& x# |4 U3 x0 _
  23. def check(st) :
    ( o% Y; G" y0 F
  24. if getCount(st) >= 4 :
    ' o) z$ \1 Q! K& }1 e; w% a, J
  25. completed(st)% a) y9 p* w7 B
  26. return4 X9 T; I. h5 d  u$ y- h) \
  27. 9 H+ ?8 e. i& H
  28. class Quest (JQuest):' ^% u" ^. m9 G  \0 ~
  29. 0 i1 @( O, \4 N& i6 ~$ o
  30. def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)
    $ U8 |" E2 {& a

  31. & s3 _; R  v4 i. W( Y# i5 q
  32. def onEvent (self,event,st):
    % b8 [1 [% b& E6 V$ I
  33. id = st.getState()5 q; y# a; Y4 S: w0 r! U' ^) c
  34. if id == CREATED : st.setState(STARTED)9 V# P' Y2 m8 f6 j7 k
  35. elif id == COMPLETED: pass. J! a. `- U4 [' p4 W2 ~
  36. elif id == STARTED : check(st)& ~& X0 J! ]* f8 B: G
  37. return) @& V1 Z, N( F- R

  38. $ T5 ~7 i- v( k5 I7 D8 j% ^# w
  39. def onKill (self,npcId,st):
    / s# y- |9 X, q8 b
  40. if npcId == KELTIR_NPC_ID:3 L: r9 p+ r6 z1 G$ _
  41. n = getCount(st): A- v- h% q1 n' Z5 S" i2 k
  42. if n == 0:
    9 _- f  N& P: j# }* C8 B
  43. if st.get('chat0') == None :
    " M) F! ~/ @7 {; r5 }
  44. st.set("chat0", "true")
    , ^7 d" W2 q* C$ X; W4 m2 e: G
  45. return "Chat0.htm"; g# \1 u- `1 L) D  w: W) P
  46. elif n == 1:
    9 l1 L/ R- x6 k1 {! H6 F3 j' z
  47. if st.get('chat1') == None :
    & j  n; S" e1 W( v2 ?" ]
  48. st.set("chat1", "true")
    4 h! q3 k0 P- }- G. m$ q
  49. return "Chat1.htm"
    ' M8 `. z0 J8 Q( e* l3 \. C
  50. elif n >= 4:& N7 j" \& i4 X
  51. return "Chat4.htm"5 q* t+ L% N0 u0 z- a# \. f
  52. return "Collect "+str(n)+" of 4 fangs"
      W7 R7 S: F7 P; c
  53. return2 i3 N; [+ @8 q' O) e- y7 v% I

  54. , N$ C7 Q$ `" B4 Q
  55. QUEST    = Quest(201, "Tutorial", "Tutorial quest"). }1 D! F+ w) s/ \+ R. `6 @) Q
  56. CREATED = State('Start',    QUEST)
    . n8 J+ z% |$ u$ k0 @* T+ n
  57. STARTED = State('Started', QUEST)0 W9 j4 A; \9 U7 Y* ^  @
  58. COMPLETED = State('Completed', QUEST)
    8 K" t3 g6 j1 ]$ b
  59. # b  y* m' I7 `# K& U. S
  60. QUEST.setInitialState(CREATED)# U1 }- o: d' d0 A5 }; _
  61. QUEST.addStartNpc(7056)8 B, I( k; Q8 |, ]' j: j  Z' T. B
  62. QUEST.addStartNpc(7012)
    4 i, Q& x: o3 y5 N4 a0 _
  63. QUEST.addStartNpc(7009)
    2 i, m  c; W  R( s$ H
  64. QUEST.addStartNpc(7011)
    ) o- v: f' k+ q( _7 O# J9 N; S

  65. " Z$ H" I# d0 f* w2 a
  66. STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)2 Y: R8 o: N- c- b/ T- Z0 W6 u
  67. STARTED.addKillId(KELTIR_NPC_ID)( H# y4 ~8 D1 O2 {, a- N
  68. STARTED.addTalkId(7056)9 n# T4 h/ W$ h1 u% S1 ?  q, X# E  v
  69. STARTED.addTalkI d(7012)- Z- \7 T% j& ~; |* G1 Q6 L
  70. STARTED.addTalkId(7009)5 R/ y% I' u7 y8 p: K; m
  71. STARTED.addTalkId(7011)
Скопировать код
6 u- Y# w( M) C7 u0 J

5 L* x  y: `, {$ @
Чтобы ответить, вам надо авторизироваться в системе Вход | Зарегистрироваться

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

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

638638758

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

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

admin@artace.ru Онлайн

QR-код

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