Top.Mail.Ru

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

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

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

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

x
Хроники        Interlude
' ?3 t$ r" O6 _4 e7 C$ W1 M  lСборка        L2j
7 K) M, T$ c4 c9 RОбратите внимание: в файле htm стартового NCP обязательно должна быть ссылка на квест:* t# D$ p' L* E1 d7 |9 o
  1. STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код
Для этого квеста больше ничего не надо. Все необходимое для корректной работы квеста уже добавили. Вот полный текст квеста:
5 N9 }6 s2 E4 H( ]( j+ [# y) S# q1 Z: X  S. C
  1. if getCount(st) >= 4 :
    # e% ^8 T5 }# Q) F
  2. completed(st)/ _* b: V+ Y' Y& V2 B5 _
  3.   return# h$ R+ ]& }2 T- b: F8 S
  4. 8 W3 x2 v) j2 M* d- A  c6 [& s) }' s
  5. class Quest (JQuest):
    ! k. q& U8 Z& j4 a/ x" q
  6.   def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)1 ]% k3 Y6 h* H+ v0 ]$ m
  7.   def onEvent (self,event,st):% t& h1 B: a9 d9 v
  8. id = st.getState()
    + d2 `, ]5 ]& c6 K
  9. if   id == CREATED  : st.setState(STARTED)
    ( g5 |( g3 C  }% L. g+ v! G
  10. elif id == COMPLETED: pass3 _! _0 ?2 H# `9 t5 B0 G. T
  11. elif id == STARTED  : check(st)
    $ x5 [0 e9 u& W% `1 u% [3 U3 A4 i
  12. return
    2 G0 J. K6 N" ~# F0 h9 ]
  13. ) p5 @! p# [% e: m7 d
  14. QUEST     = Quest(201,"Tutorial", "Tutorial quest")
    ( i7 I- _0 ]! k. e3 O) ]! P$ t
  15. CREATED   = State('Start',     QUEST)! h' n4 V; j4 A# S  j' q& O& r
  16. STARTED   = State('Started',   QUEST)) k) u! s( ~6 b6 U3 V
  17. COMPLETED = State('Completed', QUEST)
    7 O( y- G' I* @* E, C
  18. ( J7 [" i' O% ]/ h
  19. QUEST.setInitialState(CREATED). @" G8 ~/ b; O; w1 I7 b. e
  20. QUEST.addStartNpc(7056)  y: Q0 E; Q) C, N" O2 _
  21. STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код
Теперь рассмотрим, как это работает.. g) ^* e4 C. Y! V/ I/ Z( v5 Y3 q
Игрок подходит к начальному NCP (в данном случае 7056), нажимает на «Quest». Квест будет создан и состояние квеста перейдет к CREATED и игроку будет показана страничка Start.htm с описанием квеста. Тогда метод onEvent, поле открытия странички Start.htm переведет состояние квеста в STARTED и игроку будет показана страничка Started.htm, где будет опсание того, как найти keltirs и .т.д.5 x" M) |! Y; j* m3 S6 k4 I

  O, B/ ^8 m; r# _, k0 p# T+ v! C9 z
1 m; r1 J# S' ~, |  u! M
При состоянии STARTED будет зарегистрирован дроп «fangs» при убийстве keltirs. Игрок может вернуться к стартовому NCP и спросить о квесте – метод onEvent будет вызван снова. Если у игрока не хватает необходимого количества предметов, то метод check() не переведет квест в следующее состояние и Started.htm будет показана снова. Но если игрок собрал необходимее количество предметов (в данном случае 4 клыка), то метод check() вызовет метод completed() который переведет квест в новое состояние COMPLETED, заберет все клыки, даст карту мира, т.к. это награда за квест, покажет Completed.htm и завершит квест.; U4 D! e$ H! D2 V. t! R  S

% m5 h5 y" |5 e. O/ R2 x, E' |

. M9 F8 b# g' {6 `& mТеперь давайте сделаем наш квест более похожим на то, что он должен из себя представлять.
  m" x+ Y: A0 `" l1 {Прежде всего у нас есть 3 метода для объявления их в Яве – onTalk, onKill и onEvent. Если методы onTalk и onKill не объявлены, то за них все будет делать метод onEvent, т.е. определять квестовых монстров и вызывать диалоги NCP. Есть примечание, методы onTalk и onKill будут вызывать только диалоги с NCP в зависимости от текущего состояния квеста. Метод onKill будет вызываться только тогда, когда мы убиваем квестового монстра.
' R3 l2 g$ i. O/ p9 \) j, @1 n, S0 q/ X7 T

+ i% n9 N; x& m. K1 n' C1 L, D' RДавайте рассмотрим как вызывается метод onKill при убийстве keltir в состоянии квеста STARTED:
0 ^" b7 l! }' M) \% }
  1. STARTED.addKillId(KELTIR_NPC_ID)
Скопировать код
и метод onKill в классе Quest:
0 `" i1 ?5 H# `1 a4 w& Y) Y/ v3 j* d% J7 x5 p
  1. class Quest (JQuest):
    2 m, O& ~2 g7 K1 `0 i
  2.   ...
    & T% ^, G1 h; R$ M" q
  3.   def onKill (self,npcId,st):
    6 R/ z6 Q* C% X$ u; u: I
  4. if npcId == KELTIR_NPC_ID:* V. L1 u' `" P
  5.    n = getCount(st)* q' t0 l: }* s
  6.    if   n == 0:
    5 f- H* W) h* u( x4 Z
  7.        return "Chat0.htm"; \( i. \5 f6 F+ [! G" w. F! ~7 z' H9 s
  8.    elif n == 1:
    & A3 b; r9 Q" v0 v# U. \# [6 D7 g
  9.        return "Chat1.htm"- ^3 f; |# d! J) G
  10.    elif n >= 4:
    # R( D& _2 E" A* ]% F
  11.        return "Chat4.htm"
    : a3 Y: L$ n( T1 r, ^" @# {, D
  12.    return "Collected "+str(n)+" of 4 fangs"
    * h7 }; D& ~0 [: B' S1 S* [
  13. return
Скопировать код
Метод onKill (а так же метод onTalk) имеет следующие параметры:
$ u. H$ e1 G) _
! P! Z& K2 }5 O: J/ e( |$ A1 p( L

: V8 m) G* V. f0 a& {• self – квест! f4 F, V) W. _; r
• npcId – ID NCP, которого мы должны убивать (если это метод onTalk, то ID того NCP, с которым мы должны поговорить).2 l, d1 }2 t0 D0 G, a) ^
• st – текущее состояние игрока.
# e) {% P! B% Q
  p/ @6 P1 I' |  m- p

: ]# I3 H* ^% x- FВ этом методе мы проверяем и отмечаем, является ли убитый NCP keltir’ом. В основном эта проверка не нужна, т.к. у нас только KELTIR_NPC_ID.
2 v/ y2 U$ \0 D5 Y  f9 a; N) s) b) F' W' k

* X! q3 S' f, E7 V0 v/ fЗатем проверяем количество предметов (в данном случае количество клыков), и если их вообще нет, то возвращаем строку "Chat0.htm", если только один предмет, то возвращаем строку "Chat1.htm", если же предметов 4 или больше, то "Chat4.htm". Если строка возвращена из методов onEvent, onKill или onTalk, то сервер покажет соответствующие htm. В Chat0.htm может иметь следующий текст: «Вы не имеете ни одного клыка, возвращайтесь позже, когда соберете 4 штуки и бла, бла, бла…», в Chat1.htm может быть следующий текст: «У Вас всего 1 клык, по этому соберите еще…». В Chat4.htm – «Вы собрали необходимое количество предметов, возвращайтесь к вашему тренеру, что бы завершить квест…»
7 u( }& A9 J4 T4 ^1 s+ O/ p( @( P; h2 p

2 I5 ?6 y, `# U, a4 aПримечание: если в строка return начинается с "<html>", то будет показана страничка html с текстом, который стоит далее. Так вместо:
+ S: l1 V4 X4 E% m4 P3 S. Rreturn "Chat4.htm"4 H! T" ?1 `/ r1 a& _* A) j% |# f

3 C( T+ [7 b8 q$ w0 _. t7 O8 z% s8 n
1 c* b0 U3 K2 c8 r; M/ C
можно поставить:# o0 i$ i& X7 E' g8 @$ R% p7 x# k
  1. return "<html><body>Return to your trainer to complete the quest</body></html>"
Скопировать код
Так же если строка заканчивается без .htm или в начале нет <html>, то текст будет выведен, как системное сообщение в окне чата. В нашем случае мы сделаем так, что бы при каждом убийстве keltik выводилось системное сообщение: «Собрано N из 4-х клыков».) d5 A' {% E+ S5 B7 o- C
* E1 H6 J2 Z8 {" G1 g
: t* T5 T4 |% S" j
Наш код для onKill имеет один недостаток. Он будет постоянно показывать Chat0.htm, Chat1.htm и Chat4.htm, нам же необходимо, что бы Chat0.htm и Chat1.htm показывались только один раз. Как нам это сделать? С помощью переменных.2 @& C6 b* _7 _" b& O& J
6 ~  B: D" n0 O$ Y' C
; R2 V/ O4 i1 g5 _0 z) E
В каждом квесте строки могут храниться с помощью переменных. Эти переменные сохраняются в Вашей БД. В каждом методе мы можем назначить, прочитать и удалить переменные. Давайте изменим метод onKill, так что бы каждый диалог вызывался только один раз.5 l, N3 H2 w4 i
  1. def onKill (self,npcId,st):
    6 W( h* e6 [" m3 N' i
  2. if npcId == KELTIR_NPC_ID:
    , x) G9 F( {8 n, D9 G5 l
  3. n = getCount(st)
    * x! B3 l0 T  V6 k4 u
  4. if n == 0:
    7 A! b/ v0 }1 A8 S" Z: H
  5. if st.get('chat0') == None :
    ; p4 H8 W, T" u
  6. st.set("chat0", "true")
    ( A% z3 ^9 X% Z9 I5 y" w
  7. return "Chat0.htm"( R# _( {- ~8 T5 G3 w6 z. L2 e
  8. elif n == 1:' B/ [: O6 T+ c5 y* f0 t! U; P9 L
  9. if st.get('chat1') == None :
    ! W5 k9 b( P( [
  10. st.set("chat1", "true")' }. h) D  m& u; t3 F
  11. return "Chat1.htm"
    3 U% H0 Y; G) [( {/ B
  12. elif n >= 4:$ _! P. n- a( q$ k0 C) E, q
  13. return "Chat4.htm"
    5 h8 f9 Y3 i; H
  14. return "Collected "+str(n)+" of 4 fangs"
    * W+ B! _% q) K: k7 e
  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 W2 b- L- D$ A
$ ~# g5 v  G+ q. g+ I$ j
, T: r. A5 O8 X8 c
Вот конечный рабочий вариант квеста:9 d& K7 S/ d+ x6 Q
  1. import sys9 \  ~: z" d: l/ z' v1 W0 x" S3 @
  2. from net.sf.l2j.gameserver.model.quest import State; `; c) G; ], b% o( y
  3. from net.sf.l2j.gameserver.model.quest import QuestState8 Q; p/ y+ e" x
  4. from net.sf.l2j.gameserver.model.quest.jython import QuestJython as JQuest
    4 i1 X+ f5 A% n4 o* A- W
  5. & m& O5 R9 f. P) F( D
  6. KELTIR_NPC_ID = 12082
    9 j2 C4 J: P' q: N- a
  7. FANGS_ITEM_ID = 18595 d4 K/ R- z# C0 A
  8. DROP_RATE    = 500000. _3 {: V6 s2 j& _: n* i
  9. 7 K( H, F1 s6 y( f7 S
  10. WORLD_MAP_ITEM_ID = 1665) i" J. [9 E2 c& C4 n2 J( x; y7 U
  11. , M# ~( o; w( N8 n( Y
  12. def getCount(st) :) h, b% Z- Z; c$ C& ?
  13. return st.getQuestItemsCount(FANGS_ITEM_ID). J- J7 v7 Y# ]+ C
  14. 3 F+ F+ o: Q- M  D6 }' d
  15. def completed(st) :
    : W  ^; l) B6 P7 n) m
  16. st.setState(COMPLETED)0 I4 r4 ^; S# J; Y4 ^! I
  17. st.clearQuestDrops()' p4 N" {( {4 {4 y* \* @/ ^# o
  18. st.takeItems(FANGS_ITEM_ID,-1)
    0 o$ ^" Y* d  A  {9 r9 W1 S# W; _
  19. st.giveItems(WORLD_MAP_ITEM_ID,1)& A) u2 _' n4 W% ~# k
  20. st.exitQuest(False); j: @1 M8 K' @; I' v$ @
  21. return
    8 b8 z! J" z; R7 }3 X7 ^" ?
  22.   h8 z- _* n! @. M  k- x5 J
  23. def check(st) :; c/ [0 j( v2 `
  24. if getCount(st) >= 4 :
    , j% C( ]0 q% D( c0 Z/ V4 O/ a/ r
  25. completed(st)
    - t& t9 Z' R5 W
  26. return9 D8 p8 I% j+ f9 I
  27.   `9 {! x# y8 D. J9 I
  28. class Quest (JQuest):
    7 U3 T4 Q1 D6 Z* l: K% A/ Z% `
  29. 0 z& v" @; `# D! J
  30. def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)6 q/ b& c) g/ R* O* ?" F

  31. : ~5 x9 P; J& C7 X& K5 ]4 c
  32. def onEvent (self,event,st):7 P$ Y3 J1 R" B# Y1 ?
  33. id = st.getState()0 W7 R4 @# N9 y0 y+ S
  34. if id == CREATED : st.setState(STARTED)
    - x- x8 E7 J$ f6 h$ Y
  35. elif id == COMPLETED: pass; R* ?7 @! d2 n: _
  36. elif id == STARTED : check(st)) t2 ]/ f2 ?+ G5 {
  37. return( [8 G* }. a/ u; N, g( d* L! ~
  38. 8 l" Z0 E) \3 H, C
  39. def onKill (self,npcId,st):
    ( v4 O& U! p# [0 T8 g" J
  40. if npcId == KELTIR_NPC_ID:1 }/ j/ S' v0 f5 h  ~% U
  41. n = getCount(st)! X& K, K7 Y4 t( i4 _$ T. L8 g
  42. if n == 0:& L# I- |6 z1 A
  43. if st.get('chat0') == None :
    " F% B) ~  {2 b: S# A$ K
  44. st.set("chat0", "true")
    ! P. t' p& W3 {+ ?
  45. return "Chat0.htm", O3 A8 ?) b, v( D; K
  46. elif n == 1:
    & g+ {3 v1 _- Y/ U
  47. if st.get('chat1') == None :7 d" d. G! y& N% X# f
  48. st.set("chat1", "true")8 D3 F7 a1 D( j8 O
  49. return "Chat1.htm"* Q4 n' t6 l5 S, v6 K% h- j' K
  50. elif n >= 4:" I- }. e! i4 w+ W# \: O: ?
  51. return "Chat4.htm"8 v& ^( x' v/ G1 S+ k# `
  52. return "Collect "+str(n)+" of 4 fangs"8 H# m# n  `% G" \! F4 c9 S
  53. return9 b0 ~, F) V; a

  54. % a* o  Q  x! o) G: r, c, ~. }
  55. QUEST    = Quest(201, "Tutorial", "Tutorial quest")
    " o7 Z; B* l  D: i) G
  56. CREATED = State('Start',    QUEST)
      J1 b/ m# T! y. A  Y1 M
  57. STARTED = State('Started', QUEST)
    7 ~9 h  G+ U" N5 a' }, r: F) r
  58. COMPLETED = State('Completed', QUEST)
    " H7 r; }! j  w
  59. ) B- v/ j' m) t; m0 N
  60. QUEST.setInitialState(CREATED). J- l# a6 i/ B+ e- C5 l' K/ w2 z
  61. QUEST.addStartNpc(7056)
    5 G7 ^7 k& \1 M( b
  62. QUEST.addStartNpc(7012)
    7 M; Y9 C/ o8 y& ^8 D
  63. QUEST.addStartNpc(7009)
      E1 a) B" N8 ~+ P
  64. QUEST.addStartNpc(7011)2 g' V& D; e9 L; i* \1 c2 h
  65. 7 D9 i; @* A6 j" s/ C9 }9 o- R
  66. STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
      k  b! B3 Q4 p) _! a. S2 O
  67. STARTED.addKillId(KELTIR_NPC_ID)) i- L  }/ m- f# q
  68. STARTED.addTalkId(7056)
    8 _: h$ ?7 q% D4 `" t7 B
  69. STARTED.addTalkI d(7012)
    2 E7 }4 s* p  d" L: j: C
  70. STARTED.addTalkId(7009)
    9 a* ~) p3 X5 ?5 z7 ^# Q6 h2 H
  71. STARTED.addTalkId(7011)
Скопировать код
5 v7 `" S( J" K9 W/ r; m/ I
* a* @- W' Z; G
Чтобы ответить, вам надо авторизироваться в системе Вход | Зарегистрироваться

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

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

638638758

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

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

admin@artace.ru Онлайн

QR-код

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