Top.Mail.Ru

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

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

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

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

x
Хроники        Interlude
9 S- N  S( c5 L& aСборка        L2j
  Y* o* ^$ Y2 F+ n' }7 PОбратите внимание: в файле htm стартового NCP обязательно должна быть ссылка на квест:
$ `4 E+ n% H  C4 ^  \- B; U
  1. STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код
Для этого квеста больше ничего не надо. Все необходимое для корректной работы квеста уже добавили. Вот полный текст квеста:2 ~7 V: k. X4 W2 a8 }# l

' H. l+ \% X5 U: B9 t1 g8 S7 c
  1. if getCount(st) >= 4 :
    1 e) J$ C/ v) e' A, R7 g
  2. completed(st)
    ) Q, U9 l. Q6 l/ @5 s+ i1 I/ z. ]
  3.   return0 r) W% Z+ q) }$ m; n

  4. * v1 w( V+ O% }  X1 p6 X$ R/ A* L
  5. class Quest (JQuest):
    " A& ^3 ~2 v$ s- I0 q1 e  B
  6.   def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)5 _: h$ _& u- F# G2 T
  7.   def onEvent (self,event,st):
    5 P$ H1 U  H) X; ]  E/ y/ @
  8. id = st.getState()
    1 X- l9 W7 g# t* u( |2 m
  9. if   id == CREATED  : st.setState(STARTED)8 z& n2 d" p: z8 a" o
  10. elif id == COMPLETED: pass6 |9 E2 j1 J4 m1 Z1 W" f! S
  11. elif id == STARTED  : check(st)5 h+ d% @/ ~! l9 E' v7 D
  12. return
    4 }. D4 m# u5 r& j
  13. # I( _( I1 z5 Q) }
  14. QUEST     = Quest(201,"Tutorial", "Tutorial quest")% t6 Q. K; z, T! }$ D: _+ k
  15. CREATED   = State('Start',     QUEST); m, {* ?* O2 @3 d2 M' l) _
  16. STARTED   = State('Started',   QUEST)# I1 x8 D0 j, |9 a, x5 B2 p# O
  17. COMPLETED = State('Completed', QUEST)/ U( d% F+ d/ y

  18. ; ^  H5 p' l: A9 D  z% A5 u
  19. QUEST.setInitialState(CREATED)
    * _* Y2 b3 `; ^9 O! ?1 H
  20. QUEST.addStartNpc(7056)0 F! v" w7 j# I
  21. STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код
Теперь рассмотрим, как это работает.
+ @, y8 Y4 Z# @Игрок подходит к начальному NCP (в данном случае 7056), нажимает на «Quest». Квест будет создан и состояние квеста перейдет к CREATED и игроку будет показана страничка Start.htm с описанием квеста. Тогда метод onEvent, поле открытия странички Start.htm переведет состояние квеста в STARTED и игроку будет показана страничка Started.htm, где будет опсание того, как найти keltirs и .т.д.
/ e- |; ?0 t# Y* [7 V: r$ f
5 a- ?: t+ [% [4 q
. O- C9 y  j# j7 o. }; j8 j
При состоянии STARTED будет зарегистрирован дроп «fangs» при убийстве keltirs. Игрок может вернуться к стартовому NCP и спросить о квесте – метод onEvent будет вызван снова. Если у игрока не хватает необходимого количества предметов, то метод check() не переведет квест в следующее состояние и Started.htm будет показана снова. Но если игрок собрал необходимее количество предметов (в данном случае 4 клыка), то метод check() вызовет метод completed() который переведет квест в новое состояние COMPLETED, заберет все клыки, даст карту мира, т.к. это награда за квест, покажет Completed.htm и завершит квест.3 p3 V4 F: K$ A% W

2 y$ ^3 c8 K) s: x) C5 Q
& E3 j; N: `) j+ {
Теперь давайте сделаем наш квест более похожим на то, что он должен из себя представлять.! c8 N# q$ [3 ^2 u4 l8 w( c
Прежде всего у нас есть 3 метода для объявления их в Яве – onTalk, onKill и onEvent. Если методы onTalk и onKill не объявлены, то за них все будет делать метод onEvent, т.е. определять квестовых монстров и вызывать диалоги NCP. Есть примечание, методы onTalk и onKill будут вызывать только диалоги с NCP в зависимости от текущего состояния квеста. Метод onKill будет вызываться только тогда, когда мы убиваем квестового монстра.1 D0 G& \& X+ |" [, R

7 g- f* }* q; x

2 h' f. l8 O7 @7 l, B" v) ~. LДавайте рассмотрим как вызывается метод onKill при убийстве keltir в состоянии квеста STARTED:
: o) N2 m, j5 D! ?
  1. STARTED.addKillId(KELTIR_NPC_ID)
Скопировать код
и метод onKill в классе Quest:' w& R; G7 j" Z

$ z% z, F( r  m1 P  q1 _1 a. M( G. \
  1. class Quest (JQuest):
    4 n9 N1 p; h5 C/ I4 [; a0 W) x
  2.   ...5 W. _5 D  j7 r9 p, V
  3.   def onKill (self,npcId,st):& C1 Z, C. d1 Q
  4. if npcId == KELTIR_NPC_ID:
    $ v1 n9 O: Q$ H
  5.    n = getCount(st)$ q, C) ?. Z: ?, L
  6.    if   n == 0:4 n" E/ @' v& M  [0 z0 F1 N
  7.        return "Chat0.htm"2 x. X( X: @6 f; n4 I- c
  8.    elif n == 1:' Y9 ~3 I/ @5 n/ ]% s1 {
  9.        return "Chat1.htm"
    ( f8 ~8 R5 a2 [4 s2 I
  10.    elif n >= 4:) E. u" V( G; n. Z9 @) B
  11.        return "Chat4.htm"
    # X6 F8 ]  F, Y  a' e
  12.    return "Collected "+str(n)+" of 4 fangs"
    3 K, F+ W+ B9 y, P7 z6 ^
  13. return
Скопировать код
Метод onKill (а так же метод onTalk) имеет следующие параметры:& o. L9 X9 r9 O# L$ T9 D* x
+ O3 H, n. q, s4 z5 t/ r
% ]2 R  L( {  d
• self – квест* N4 ?7 I7 q! l" C
• npcId – ID NCP, которого мы должны убивать (если это метод onTalk, то ID того NCP, с которым мы должны поговорить).& f' h) F3 W* ?, G7 ?
• st – текущее состояние игрока.
% d% ~- ]" X- a3 t' z( i! ?4 K/ k- j2 N

/ F* M1 @7 b! A. @& d6 f( D! i8 p( R3 gВ этом методе мы проверяем и отмечаем, является ли убитый NCP keltir’ом. В основном эта проверка не нужна, т.к. у нас только KELTIR_NPC_ID.- L) [! j$ R2 f8 d# V/ A

- C! ~9 Y& l6 }7 I( \
! E7 i7 g& P, ?. y6 E' F0 R9 `
Затем проверяем количество предметов (в данном случае количество клыков), и если их вообще нет, то возвращаем строку "Chat0.htm", если только один предмет, то возвращаем строку "Chat1.htm", если же предметов 4 или больше, то "Chat4.htm". Если строка возвращена из методов onEvent, onKill или onTalk, то сервер покажет соответствующие htm. В Chat0.htm может иметь следующий текст: «Вы не имеете ни одного клыка, возвращайтесь позже, когда соберете 4 штуки и бла, бла, бла…», в Chat1.htm может быть следующий текст: «У Вас всего 1 клык, по этому соберите еще…». В Chat4.htm – «Вы собрали необходимое количество предметов, возвращайтесь к вашему тренеру, что бы завершить квест…», T( f# q' [) x4 I7 W" Y+ @

+ z' A9 V$ r5 U4 M
. d. Y' O2 u) M0 n3 u
Примечание: если в строка return начинается с "<html>", то будет показана страничка html с текстом, который стоит далее. Так вместо:! p' d9 {) D* w7 U1 L
return "Chat4.htm"6 D& u2 x6 ~( [' @! A% J- S

4 n/ |3 b: c% P7 F5 K4 ?" \/ q

8 |, n# B& r. c* i) uможно поставить:. _; S3 s  e4 u9 f: A3 _
  1. return "<html><body>Return to your trainer to complete the quest</body></html>"
Скопировать код
Так же если строка заканчивается без .htm или в начале нет <html>, то текст будет выведен, как системное сообщение в окне чата. В нашем случае мы сделаем так, что бы при каждом убийстве keltik выводилось системное сообщение: «Собрано N из 4-х клыков».' k5 P8 t& U5 e9 e4 z7 K$ ~3 O
7 v" I1 y8 ^  J$ b% \$ F

  ], |8 U5 X% z4 B+ Y! fНаш код для onKill имеет один недостаток. Он будет постоянно показывать Chat0.htm, Chat1.htm и Chat4.htm, нам же необходимо, что бы Chat0.htm и Chat1.htm показывались только один раз. Как нам это сделать? С помощью переменных.
( X( U& s. V# M9 l
: U: ?( I# ~& O) v6 Q7 g2 r' @. d

* ~: }, l& {! o  lВ каждом квесте строки могут храниться с помощью переменных. Эти переменные сохраняются в Вашей БД. В каждом методе мы можем назначить, прочитать и удалить переменные. Давайте изменим метод onKill, так что бы каждый диалог вызывался только один раз.
, p9 o, B5 O6 D! c9 Q* g
  1. def onKill (self,npcId,st):4 N: O+ q; x  S8 S/ Q
  2. if npcId == KELTIR_NPC_ID:- G4 m- \$ _% ~: e6 y
  3. n = getCount(st)
    + Q/ W3 C7 S) l6 E9 X: s% L
  4. if n == 0:1 W4 L; y- i3 u; [+ X
  5. if st.get('chat0') == None :
    . j  E- K0 S9 M2 }5 x
  6. st.set("chat0", "true")) p! y: f# s- C' e# a) c% N
  7. return "Chat0.htm"" f8 c/ g; M. X1 J5 o9 n( f! t
  8. elif n == 1:" r* B( p& n; K0 V
  9. if st.get('chat1') == None :
    6 i1 f% m# h% p
  10. st.set("chat1", "true")3 \6 }5 T$ [0 e; r" Q' v9 O! r: a: \
  11. return "Chat1.htm"
    / ~% a) G0 k, n( I
  12. elif n >= 4:9 m5 b4 L: i' }8 D$ Z
  13. return "Chat4.htm"
    , R0 ?/ m. K- p) x4 k( C# x. W* H
  14. return "Collected "+str(n)+" of 4 fangs"( u. O$ c  j5 A
  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.
  v" Q+ j% i! E  @8 n( O
1 W. b7 b2 X- u4 Y
, `+ Q" `4 n! G; g
Вот конечный рабочий вариант квеста:! [2 E1 L) w8 u0 J* C
  1. import sys) K# N4 [, ]5 r: G; l* [
  2. from net.sf.l2j.gameserver.model.quest import State; c& P% l. q9 ]0 l5 y
  3. from net.sf.l2j.gameserver.model.quest import QuestState0 [2 q- Z; H5 `" S7 M
  4. from net.sf.l2j.gameserver.model.quest.jython import QuestJython as JQuest; [, [+ _+ X, v6 G) \

  5. 3 o" Y% x2 w5 L/ A; g- l
  6. KELTIR_NPC_ID = 12082
    ' b, ~0 [7 \- |- m7 Y
  7. FANGS_ITEM_ID = 1859, o" \& m9 A5 f! X, B
  8. DROP_RATE    = 500000- a: Q0 e: Y) W' c; z) k" L
  9. ) A7 F2 L7 Z% q: h
  10. WORLD_MAP_ITEM_ID = 16657 m! i! c9 R- G9 w
  11. 3 a6 v% f# `* N0 ^# M
  12. def getCount(st) :
    7 s& p! s* v( e/ q$ f
  13. return st.getQuestItemsCount(FANGS_ITEM_ID)
      R: e, w4 {/ ]$ @8 Q" b( W

  14. ! o- |: P8 j! M, g" t/ Z2 K+ c- H+ L
  15. def completed(st) :
    - S* m5 u0 j6 e9 R/ t
  16. st.setState(COMPLETED)
    - r9 j0 M0 U. l
  17. st.clearQuestDrops()
    ! E; C, U! n2 J, B
  18. st.takeItems(FANGS_ITEM_ID,-1)  _) T$ H! F3 B7 ^5 E& D. e" ]" T
  19. st.giveItems(WORLD_MAP_ITEM_ID,1)# R" A2 x& N' v6 i4 h* E
  20. st.exitQuest(False)" C1 Q% y: M: X1 ^' K
  21. return
    4 L2 A' p, w; i  U, P# X

  22. + l6 e# e! e$ H2 |
  23. def check(st) :
    0 j  d8 l2 r, J1 O9 k
  24. if getCount(st) >= 4 :
    , z& s3 X2 [+ l$ P3 l  {
  25. completed(st)
    + X( |8 D2 e' B, R9 e9 ?
  26. return
    " }/ N/ T& K# E  y1 _, Q
  27. 6 S/ P9 y+ W! b! g# e
  28. class Quest (JQuest):
    , l$ d* n; M2 D( W7 h( j, [

  29. 4 i: U4 t6 l) U- s
  30. def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)
    0 ~. v8 i; F5 H: a6 C+ W8 G
  31. 4 w% k2 X# l& a# X4 A
  32. def onEvent (self,event,st):" t" J* d8 w7 Z  h/ R' U
  33. id = st.getState()
    9 R6 x4 n4 R$ t- Z/ e$ a
  34. if id == CREATED : st.setState(STARTED)
    6 v" x. \. U/ s
  35. elif id == COMPLETED: pass
    1 a9 D* [* }+ f: B' X( b, o! p! J- X- {
  36. elif id == STARTED : check(st)/ P+ D" u; Q6 [  T# q6 k* u
  37. return: ~/ i5 |' A0 u! Q
  38. . l3 U# v% C5 ]$ G8 R+ `
  39. def onKill (self,npcId,st):" E2 ]( K: }, Y5 I0 ^  `$ E
  40. if npcId == KELTIR_NPC_ID:
    8 w  K, n& D! r5 d0 e" Y
  41. n = getCount(st)
    / v& E2 A% y4 t! ]. Q
  42. if n == 0:
    $ x4 F' B# Q/ U$ E. v
  43. if st.get('chat0') == None :
    $ r2 }) X' b; Y, W5 ]* L. f
  44. st.set("chat0", "true")
    4 s, v. v* S8 c7 A* h4 X8 U
  45. return "Chat0.htm"* a2 \  H" T; L# \- T% h) S1 v2 d
  46. elif n == 1:
    4 F6 L2 v) v; \
  47. if st.get('chat1') == None :+ }7 H' w1 V5 ?0 `0 ]: \! t
  48. st.set("chat1", "true")
    + C) }, L4 U+ o" P5 {
  49. return "Chat1.htm"+ a+ l5 D* ^  V0 X# u6 |0 m
  50. elif n >= 4:! I) j! [, G1 G( u, R! z
  51. return "Chat4.htm"
      G8 H( T& W% S: Y
  52. return "Collect "+str(n)+" of 4 fangs"
    ( V, O7 I6 W4 w- u
  53. return
    3 V  r  T' i- j3 J, j) |# T4 K
  54.   B1 E. L1 l; K
  55. QUEST    = Quest(201, "Tutorial", "Tutorial quest"). E$ i  }: j9 Q+ \5 z0 g+ I
  56. CREATED = State('Start',    QUEST)
    6 h+ T/ s$ z9 J% t% T# B
  57. STARTED = State('Started', QUEST)( K9 c. Z8 y3 s
  58. COMPLETED = State('Completed', QUEST)2 p& B) Q$ s/ ~7 x

  59. " @" q9 G7 {6 d9 e1 X7 u
  60. QUEST.setInitialState(CREATED)2 v9 h" `9 l) M  [$ h& v. \. D. s
  61. QUEST.addStartNpc(7056)4 T; H% W: d2 m
  62. QUEST.addStartNpc(7012)
    : \5 p% i/ y0 @2 J
  63. QUEST.addStartNpc(7009)
    0 `& R9 g" k0 h  C
  64. QUEST.addStartNpc(7011), a, _, z) }3 K$ x/ Z

  65. ) J' w: I$ N; B# d, l
  66. STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)+ g: s& [6 }9 w( x! x8 o% _
  67. STARTED.addKillId(KELTIR_NPC_ID)& F' X" ?. |5 S9 Z3 C
  68. STARTED.addTalkId(7056)# {8 A: C* ^! s# g- Q6 F  h7 i4 }
  69. STARTED.addTalkI d(7012). Q- a4 I3 L0 _( a
  70. STARTED.addTalkId(7009)
    & i6 A  W/ j9 E7 c6 {% k
  71. STARTED.addTalkId(7011)
Скопировать код

; D; y* u3 ~2 |* n4 N; Q/ y3 d! @+ g3 a/ V
Чтобы ответить, вам надо авторизироваться в системе Вход | Зарегистрироваться

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

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

638638758

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

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

admin@artace.ru Онлайн

QR-код

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