Top.Mail.Ru

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

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

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

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

x
Хроники        Interlude
, o( x# _( a( i3 ?$ \Сборка        L2j4 _8 W$ B! Z; p6 P
Обратите внимание: в файле htm стартового NCP обязательно должна быть ссылка на квест:- `  y) _, |9 a, F( `8 E3 @: A
  1. STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код
Для этого квеста больше ничего не надо. Все необходимое для корректной работы квеста уже добавили. Вот полный текст квеста:
) Q4 L' T$ `2 m" h  C* _* |* G3 f5 a* i: x4 q. t
  1. if getCount(st) >= 4 :7 c& D5 Y* t+ r' b
  2. completed(st)
    . `' m# A( b9 U" F4 |% W
  3.   return
    2 g- Y9 x2 Q1 y0 ~; W

  4. ! s$ w% |% `  H5 A5 f/ w1 q" V
  5. class Quest (JQuest):
    2 F2 f0 f; \; x$ K0 `
  6.   def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)
    " ]2 c( G7 i  |6 W  S
  7.   def onEvent (self,event,st):( F; o+ [: k% {4 A/ R. b, _- K; t: n& O
  8. id = st.getState()& S% d; A' \) L# J+ {6 L
  9. if   id == CREATED  : st.setState(STARTED)5 P: t7 p9 Q  W/ q, o
  10. elif id == COMPLETED: pass
    * Z0 b/ f6 S3 J# X/ \
  11. elif id == STARTED  : check(st)
    : ^. c. k; ?( q) [, c3 k  ~# b1 b8 `
  12. return
    ; n! i  ^: i( l1 q: F. J
  13.   s) u  T9 Q  R* }2 o4 w
  14. QUEST     = Quest(201,"Tutorial", "Tutorial quest")
    ) k& B6 [" J* o9 r- Q9 b
  15. CREATED   = State('Start',     QUEST)
    $ c8 q5 O! R6 n
  16. STARTED   = State('Started',   QUEST)5 K2 r$ [2 p. G4 h
  17. COMPLETED = State('Completed', QUEST)
    * t# x- K* B- L$ d4 S$ M6 ^
  18. ; v! J$ B+ B' g. J- b, h& J; e
  19. QUEST.setInitialState(CREATED)
    ! w0 u6 J" _4 D& L
  20. QUEST.addStartNpc(7056)
    8 J( X: X/ c3 _8 U+ Q/ ~
  21. STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код
Теперь рассмотрим, как это работает.
) s- x  o" S7 X( W1 jИгрок подходит к начальному NCP (в данном случае 7056), нажимает на «Quest». Квест будет создан и состояние квеста перейдет к CREATED и игроку будет показана страничка Start.htm с описанием квеста. Тогда метод onEvent, поле открытия странички Start.htm переведет состояние квеста в STARTED и игроку будет показана страничка Started.htm, где будет опсание того, как найти keltirs и .т.д.% i; J' }! a/ n; y0 ~
, b, ~3 ?6 ~' o" D0 K, T
. j, I, a* S9 g5 ?9 W/ G
При состоянии STARTED будет зарегистрирован дроп «fangs» при убийстве keltirs. Игрок может вернуться к стартовому NCP и спросить о квесте – метод onEvent будет вызван снова. Если у игрока не хватает необходимого количества предметов, то метод check() не переведет квест в следующее состояние и Started.htm будет показана снова. Но если игрок собрал необходимее количество предметов (в данном случае 4 клыка), то метод check() вызовет метод completed() который переведет квест в новое состояние COMPLETED, заберет все клыки, даст карту мира, т.к. это награда за квест, покажет Completed.htm и завершит квест.
& G- y1 F- E) n- R
" R3 _4 ]2 m/ y. O" ~# v

7 L$ u$ }' B  p" y9 hТеперь давайте сделаем наш квест более похожим на то, что он должен из себя представлять.
. k* q! U+ `3 M% Y: l( {9 g) w9 ^Прежде всего у нас есть 3 метода для объявления их в Яве – onTalk, onKill и onEvent. Если методы onTalk и onKill не объявлены, то за них все будет делать метод onEvent, т.е. определять квестовых монстров и вызывать диалоги NCP. Есть примечание, методы onTalk и onKill будут вызывать только диалоги с NCP в зависимости от текущего состояния квеста. Метод onKill будет вызываться только тогда, когда мы убиваем квестового монстра.
  l3 a3 l4 {& D9 [5 y; _5 s) X/ O  m% X! @% ~- A

9 g. w8 V1 F) t% a, c% R1 \Давайте рассмотрим как вызывается метод onKill при убийстве keltir в состоянии квеста STARTED:
6 K* T3 k$ s$ ^: l' S0 t$ {
  1. STARTED.addKillId(KELTIR_NPC_ID)
Скопировать код
и метод onKill в классе Quest:
7 W- i( w  f- @8 U% y" N2 W0 X
/ A2 d! i) Z5 C( }. e4 S- A  m5 _
  1. class Quest (JQuest):  y& ]3 \& Z- C1 u3 |; j, ]; L2 J
  2.   ...: G3 \4 l4 D& c4 q, ^+ T
  3.   def onKill (self,npcId,st):7 d8 w- I" k$ G8 ~- O' n7 v
  4. if npcId == KELTIR_NPC_ID:
    4 y, p- S2 A. N3 c9 a9 V1 y( R) |- [
  5.    n = getCount(st); l' Z. ^9 }$ z+ y5 N9 b0 ^
  6.    if   n == 0:
    : I# R  J+ j) h  Y$ `
  7.        return "Chat0.htm"( W& j3 @1 S2 K; ^/ v* |+ I
  8.    elif n == 1:
    $ w: P, O4 A9 a3 G
  9.        return "Chat1.htm"7 O0 ~$ Y& z. q' q8 T. x
  10.    elif n >= 4:
    2 b. l. i$ K2 v4 ?) V) H7 @$ |# R" ~0 Y
  11.        return "Chat4.htm"
    6 W& V; Y, Y( G7 F
  12.    return "Collected "+str(n)+" of 4 fangs"
    0 S3 o) r! Z# f6 C' w( G
  13. return
Скопировать код
Метод onKill (а так же метод onTalk) имеет следующие параметры:- j8 h- D8 O, g# e* A  A
' e* {' G! e8 B' [/ _. L
1 j. a& F5 K. t
• self – квест
" |, Y! i) a, e• npcId – ID NCP, которого мы должны убивать (если это метод onTalk, то ID того NCP, с которым мы должны поговорить).9 I9 l; f6 @/ Z' d
• st – текущее состояние игрока.
/ A+ f" y$ P  Y7 \. _6 v2 \
8 F4 f! E: N6 n/ i

9 I4 L* O0 W4 ?& U/ K1 B; w& ?В этом методе мы проверяем и отмечаем, является ли убитый NCP keltir’ом. В основном эта проверка не нужна, т.к. у нас только KELTIR_NPC_ID.7 S/ e% O1 Q" R

4 O, x: q2 F9 X

  h, G: t) u) G! N9 zЗатем проверяем количество предметов (в данном случае количество клыков), и если их вообще нет, то возвращаем строку "Chat0.htm", если только один предмет, то возвращаем строку "Chat1.htm", если же предметов 4 или больше, то "Chat4.htm". Если строка возвращена из методов onEvent, onKill или onTalk, то сервер покажет соответствующие htm. В Chat0.htm может иметь следующий текст: «Вы не имеете ни одного клыка, возвращайтесь позже, когда соберете 4 штуки и бла, бла, бла…», в Chat1.htm может быть следующий текст: «У Вас всего 1 клык, по этому соберите еще…». В Chat4.htm – «Вы собрали необходимое количество предметов, возвращайтесь к вашему тренеру, что бы завершить квест…»& w" I) _% M5 x" h, f' ~
( ~  N3 `2 N2 Y! ?9 i- A$ s( `

% u. Y6 S, v/ P7 J7 ^$ R& BПримечание: если в строка return начинается с "<html>", то будет показана страничка html с текстом, который стоит далее. Так вместо:
, ^( j( I3 m0 s$ ^; `# @1 K1 n, ~: hreturn "Chat4.htm"8 e/ v6 T: h$ k1 {& `
! C6 S1 F# s* e+ N

/ v" _  @7 i' d0 o/ q- V2 mможно поставить:
* O) Z3 }1 o/ @2 e7 @8 k( r
  1. return "<html><body>Return to your trainer to complete the quest</body></html>"
Скопировать код
Так же если строка заканчивается без .htm или в начале нет <html>, то текст будет выведен, как системное сообщение в окне чата. В нашем случае мы сделаем так, что бы при каждом убийстве keltik выводилось системное сообщение: «Собрано N из 4-х клыков».
. [) M3 b* X# ?  G- X& o% {: @

$ {! e' p5 ]4 O: V' EНаш код для onKill имеет один недостаток. Он будет постоянно показывать Chat0.htm, Chat1.htm и Chat4.htm, нам же необходимо, что бы Chat0.htm и Chat1.htm показывались только один раз. Как нам это сделать? С помощью переменных.' O1 f5 p7 X/ U# p. i
. s  _/ U4 K) S% u/ x  U1 n# M

' D1 `" D$ P% ~В каждом квесте строки могут храниться с помощью переменных. Эти переменные сохраняются в Вашей БД. В каждом методе мы можем назначить, прочитать и удалить переменные. Давайте изменим метод onKill, так что бы каждый диалог вызывался только один раз.9 L; I% [6 S2 H  [8 v' H
  1. def onKill (self,npcId,st):! v9 ~. E" i9 W, k; \
  2. if npcId == KELTIR_NPC_ID:
    0 L% ~6 I) g, K# _- l3 q0 ?
  3. n = getCount(st)
    & g% w; W- [2 k0 x) l; q% m7 }
  4. if n == 0:
    1 Q& m( a4 y5 f. n3 q" e
  5. if st.get('chat0') == None :
    3 A8 y" b( w7 g# a/ `
  6. st.set("chat0", "true")
    : k+ C# I* V' u% Z! F, y2 q
  7. return "Chat0.htm"
    ' ?- e9 d* h' b& g8 f, O* b( A. |
  8. elif n == 1:
    % F. E8 u- |" a3 {0 g
  9. if st.get('chat1') == None :
    2 A% P2 h2 p# h: `) o
  10. st.set("chat1", "true")0 K, R# O1 y" O+ L
  11. return "Chat1.htm"9 [$ b# o, L, o
  12. elif n >= 4:4 B2 A9 r. P4 l' f1 W* C
  13. return "Chat4.htm"1 B0 R, I3 ]3 x) ?3 l
  14. return "Collected "+str(n)+" of 4 fangs"
    : A8 ^/ R8 {/ D# {3 b3 G$ s9 S. 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.
0 o& A  W. v( ]) T$ \; Z; \; _% l8 g( X% g/ V! @: w/ _
+ Z8 S$ U5 x+ I" o4 k
Вот конечный рабочий вариант квеста:
) Q, I, g0 d  n8 X( b1 B
  1. import sys
    4 P8 [' b& g+ ?/ j
  2. from net.sf.l2j.gameserver.model.quest import State/ i5 ~- n2 n0 ^9 Z4 i1 b) e  e) E
  3. from net.sf.l2j.gameserver.model.quest import QuestState$ X6 g  L. X8 ~
  4. from net.sf.l2j.gameserver.model.quest.jython import QuestJython as JQuest3 l2 \- z6 K0 O( K! R) o

  5. * |- s; B" |9 P  U
  6. KELTIR_NPC_ID = 12082
      N) \% s9 C" k; p
  7. FANGS_ITEM_ID = 18591 \- X1 H% r: m( ^
  8. DROP_RATE    = 500000: G1 R2 J$ P  t! S) c9 G$ o' K
  9. ; N5 M( I  J8 ]  W# q7 F
  10. WORLD_MAP_ITEM_ID = 1665
    0 j; c7 z9 v4 _: J1 e
  11. 3 b% I$ Z9 A' G) d( W' e! ^6 k
  12. def getCount(st) :, V- M* p0 C0 q. r& R
  13. return st.getQuestItemsCount(FANGS_ITEM_ID): W* l  z, ^. R/ A) l
  14. * J% m- q$ K4 a+ _' w# N
  15. def completed(st) :
    ) i0 T& R" ]! v# C6 P
  16. st.setState(COMPLETED)
    - `3 C' K& i, I
  17. st.clearQuestDrops()
    / A1 Q: p3 \  p/ d/ @1 D3 o
  18. st.takeItems(FANGS_ITEM_ID,-1)3 L( k, Q0 |+ r3 P9 D* @3 N3 L7 F; z
  19. st.giveItems(WORLD_MAP_ITEM_ID,1)
    8 \: c$ p8 Z  R  V" O  [3 J
  20. st.exitQuest(False)
    $ b$ H' h. N* C: M* V
  21. return
    ; Q0 G1 j/ A$ A1 U8 u

  22. ! L1 t  v% f# G+ `9 d1 Z- b2 }. b
  23. def check(st) :
    ( z& I5 ?/ @8 w& q, w/ l
  24. if getCount(st) >= 4 :
    , @9 @$ x" ?  j& H  b4 Y& ?
  25. completed(st)" s, E( @+ b/ b( o5 V' l& ~
  26. return  R6 U$ u# x. w) o4 n/ i
  27. , @# L  k4 _4 @: n0 B6 n- P
  28. class Quest (JQuest):; [7 ~7 s: l8 E+ Q- @

  29. & b- C( q* @0 j2 F  A4 K
  30. def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)
    5 {/ Z, E1 Q; q( ^" n1 ~
  31. 3 `$ M3 P# R7 @; F' ]! H
  32. def onEvent (self,event,st):5 H- m0 q  f& `( @
  33. id = st.getState()$ l, h9 v1 g6 }9 T
  34. if id == CREATED : st.setState(STARTED)
    * A( |/ `. V% j6 U' ?  L5 e$ E
  35. elif id == COMPLETED: pass6 s% W. Z( n5 b* S( t, ]% v
  36. elif id == STARTED : check(st)
    4 W. ~5 k$ V) H7 [. Y
  37. return* O6 X5 n7 X+ C9 s! [; t! q8 A

  38. 3 `2 B! T  h5 X
  39. def onKill (self,npcId,st):
    1 V9 \% i" G. J5 b9 b
  40. if npcId == KELTIR_NPC_ID:
    - h% C. v  E0 a/ C% {
  41. n = getCount(st)
    * m$ F; Z) F' \' w0 U! m% \$ i
  42. if n == 0:
    * `. J, ^- P8 B& W+ e' z/ I
  43. if st.get('chat0') == None :
    ' l' ^& a! n3 u
  44. st.set("chat0", "true")
    6 K- F) k) L% H: e/ `; t4 B2 E1 ~
  45. return "Chat0.htm"# R" N! ^% H. [! }5 y1 C" J/ i2 @
  46. elif n == 1:$ F6 ~0 \% v5 K  G* m0 x* R# T
  47. if st.get('chat1') == None :- f* ~1 ]: ]( n! r6 v; H
  48. st.set("chat1", "true")
    ' a( J# r1 L3 Z- P$ e& _
  49. return "Chat1.htm"/ t8 ], T; I' i# S) e. O
  50. elif n >= 4:3 C* |9 K7 w' L" \  k. j% x; W& P
  51. return "Chat4.htm"
      V3 M, o; [7 _7 X$ p3 T0 |
  52. return "Collect "+str(n)+" of 4 fangs"
    - X2 f/ |- W- H: l& v1 U# h& ^
  53. return
    3 A% J9 a' N( ~5 A; g- \

  54. . u7 k8 s, \/ O. _" g
  55. QUEST    = Quest(201, "Tutorial", "Tutorial quest")
    2 P; n6 J, R/ p4 T# {; Y7 M
  56. CREATED = State('Start',    QUEST)
    $ H3 F5 e$ o9 |) T5 W; R6 ?- l  F9 {
  57. STARTED = State('Started', QUEST)
    # J& O2 h& w' W- F' y7 y$ i
  58. COMPLETED = State('Completed', QUEST)+ n2 D& p2 i" Y5 g. Z
  59. 3 H( Y6 S% C9 E6 s. M
  60. QUEST.setInitialState(CREATED)
    . a# g1 O) Y: n; f5 }
  61. QUEST.addStartNpc(7056)
    * j7 z7 q$ m9 ]6 s  H
  62. QUEST.addStartNpc(7012)2 B1 L5 _9 c6 f" l8 Z# X
  63. QUEST.addStartNpc(7009)
    & z/ E9 q" h* ~# A
  64. QUEST.addStartNpc(7011)
    5 j7 r. G6 T( H" n; e' B  O

  65. ' Q4 F1 H6 p( l6 {8 {3 N- @! J
  66. STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
    : K9 q  ]& M& K7 ~
  67. STARTED.addKillId(KELTIR_NPC_ID). h+ D# d, x* W4 G+ ^7 V; [* i
  68. STARTED.addTalkId(7056)
    * c8 M4 Y, g7 z2 K$ h$ Q  Q" q
  69. STARTED.addTalkI d(7012)7 G1 [5 d/ K6 K# X0 t4 X: \3 C# H
  70. STARTED.addTalkId(7009)) m3 G( v7 x! k# L' d: V
  71. STARTED.addTalkId(7011)
Скопировать код

5 I5 A1 o4 X1 _! J) {" {0 l$ ]8 _/ v7 ^: t6 B) W
Чтобы ответить, вам надо авторизироваться в системе Вход | Зарегистрироваться

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

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

638638758

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

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

admin@artace.ru Онлайн

QR-код

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