Top.Mail.Ru

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

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

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

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

x
Хроники        Interlude' R% ~$ d! {7 j
Сборка        L2j4 o& u' }2 e9 R- h8 o6 @5 B: C
Обратите внимание: в файле htm стартового NCP обязательно должна быть ссылка на квест:7 {3 ~: w2 r4 r7 O8 _% S* F: X
  1. STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код
Для этого квеста больше ничего не надо. Все необходимое для корректной работы квеста уже добавили. Вот полный текст квеста:1 i4 E, }, C& `/ a
- H# `% A3 c. _+ s" ]
  1. if getCount(st) >= 4 :# x: ]7 u7 b! j  y1 W* m
  2. completed(st)2 l' \1 T& I+ ~9 y7 p6 ?9 s/ S8 d
  3.   return
    / ~2 o. K' j! z- L
  4. # `$ p1 [$ c8 Z* f" M  o/ p  K
  5. class Quest (JQuest):6 K* b- |7 r; U+ U; a
  6.   def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)9 ~) v1 U" G- R% [6 v+ H0 D4 s
  7.   def onEvent (self,event,st):
    $ ~! R8 ~0 p4 m
  8. id = st.getState()
    1 Q6 [: ?9 U# a' N. W: O: p1 W8 M
  9. if   id == CREATED  : st.setState(STARTED), L2 |0 G4 S+ O' a
  10. elif id == COMPLETED: pass
    0 w* S: i' ?$ x0 J% n0 \$ z& f0 J8 G
  11. elif id == STARTED  : check(st)/ ~, E) d! N- I6 t+ q2 j
  12. return6 w" l( n! x8 c- u
  13. & H  @0 N1 J3 i; A7 ?2 g
  14. QUEST     = Quest(201,"Tutorial", "Tutorial quest")) O1 O4 ?8 R: {; p, k6 i7 Z/ a" b5 m
  15. CREATED   = State('Start',     QUEST)
    # X  e5 w0 @8 s: J5 Z
  16. STARTED   = State('Started',   QUEST)) K" Z5 Z! J  ~( B
  17. COMPLETED = State('Completed', QUEST)7 m- `7 Z  f  V
  18. / T% G6 A! a8 i( C
  19. QUEST.setInitialState(CREATED)9 M: I" I# d5 ]2 p* F" k3 O
  20. QUEST.addStartNpc(7056)4 s5 j0 B) h* ^/ _! n6 X7 k1 H
  21. STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код
Теперь рассмотрим, как это работает.5 R/ F  s! G* ]$ v+ H
Игрок подходит к начальному NCP (в данном случае 7056), нажимает на «Quest». Квест будет создан и состояние квеста перейдет к CREATED и игроку будет показана страничка Start.htm с описанием квеста. Тогда метод onEvent, поле открытия странички Start.htm переведет состояние квеста в STARTED и игроку будет показана страничка Started.htm, где будет опсание того, как найти keltirs и .т.д.
3 g% H/ d- q( N6 ~% |* c! ?0 f+ F. M+ ^8 n% W# x& g

# G* u5 [' [4 ?6 @! D  VПри состоянии STARTED будет зарегистрирован дроп «fangs» при убийстве keltirs. Игрок может вернуться к стартовому NCP и спросить о квесте – метод onEvent будет вызван снова. Если у игрока не хватает необходимого количества предметов, то метод check() не переведет квест в следующее состояние и Started.htm будет показана снова. Но если игрок собрал необходимее количество предметов (в данном случае 4 клыка), то метод check() вызовет метод completed() который переведет квест в новое состояние COMPLETED, заберет все клыки, даст карту мира, т.к. это награда за квест, покажет Completed.htm и завершит квест.
+ `3 c- ?/ M' N" {/ z% _8 @! @
7 e( F/ [( C" r$ r7 d& j
, W$ n8 h4 q/ f! R
Теперь давайте сделаем наш квест более похожим на то, что он должен из себя представлять.0 F5 J+ X/ b$ p* I; k
Прежде всего у нас есть 3 метода для объявления их в Яве – onTalk, onKill и onEvent. Если методы onTalk и onKill не объявлены, то за них все будет делать метод onEvent, т.е. определять квестовых монстров и вызывать диалоги NCP. Есть примечание, методы onTalk и onKill будут вызывать только диалоги с NCP в зависимости от текущего состояния квеста. Метод onKill будет вызываться только тогда, когда мы убиваем квестового монстра.! a1 I5 b# V" S& y2 {5 i) ]
6 i: k% V. Q1 K' \. H

0 A3 m+ f4 M! [; K0 k& c3 IДавайте рассмотрим как вызывается метод onKill при убийстве keltir в состоянии квеста STARTED:1 ]1 d* O# F6 Q4 s* S
  1. STARTED.addKillId(KELTIR_NPC_ID)
Скопировать код
и метод onKill в классе Quest:
  P" N- i6 p' W. g( n) Q/ u1 h
3 s2 I; g9 i% S+ I
  1. class Quest (JQuest):
    1 A4 C. S5 ^$ `6 l$ w2 E8 y5 A
  2.   ...
    + J& k$ P; E' }, x
  3.   def onKill (self,npcId,st):9 R( }7 Y5 z5 q! g& b( O& w3 ]9 i
  4. if npcId == KELTIR_NPC_ID:  f% @3 i; ^# e" f0 w
  5.    n = getCount(st)
    + P! h* Q. Y9 ]3 s8 B# @& T& X
  6.    if   n == 0:
    6 v8 o  W+ |% Z' J+ L
  7.        return "Chat0.htm"
    6 l; q; R3 D# G, f! w
  8.    elif n == 1:
    : _9 Y; Z1 e) r2 Y: E& G& J6 E/ M' ?
  9.        return "Chat1.htm"
    . q- Q$ B" Q  f. D3 Z1 {
  10.    elif n >= 4:: n3 \6 o' D/ w. I8 Z( ^
  11.        return "Chat4.htm"4 i& M( t6 M/ V2 M
  12.    return "Collected "+str(n)+" of 4 fangs"
    % H0 [6 F/ G- G) l# x( j! O
  13. return
Скопировать код
Метод onKill (а так же метод onTalk) имеет следующие параметры:
3 f  J' W' E# r) S
/ R: v. ?% [' s/ k7 n4 F4 a' m

( A8 s! `/ p( l9 ~9 Y; r/ d+ x" D• self – квест: Z+ f" p- ?3 C5 m7 x& P
• npcId – ID NCP, которого мы должны убивать (если это метод onTalk, то ID того NCP, с которым мы должны поговорить).
& G- K* F: ^! v" H$ c; d• st – текущее состояние игрока.
6 t4 T; h- T9 C3 j
+ p/ L0 k4 I5 k+ @2 }: j( z
8 X' Y- t9 g5 Y, @6 q" b$ \
В этом методе мы проверяем и отмечаем, является ли убитый NCP keltir’ом. В основном эта проверка не нужна, т.к. у нас только KELTIR_NPC_ID.2 m7 Y, o1 s, v+ a% Y- x, _
$ f# [6 H6 d5 m6 i9 Y

# x+ V; K7 x( SЗатем проверяем количество предметов (в данном случае количество клыков), и если их вообще нет, то возвращаем строку "Chat0.htm", если только один предмет, то возвращаем строку "Chat1.htm", если же предметов 4 или больше, то "Chat4.htm". Если строка возвращена из методов onEvent, onKill или onTalk, то сервер покажет соответствующие htm. В Chat0.htm может иметь следующий текст: «Вы не имеете ни одного клыка, возвращайтесь позже, когда соберете 4 штуки и бла, бла, бла…», в Chat1.htm может быть следующий текст: «У Вас всего 1 клык, по этому соберите еще…». В Chat4.htm – «Вы собрали необходимое количество предметов, возвращайтесь к вашему тренеру, что бы завершить квест…»
  t. M' v" x6 J) d5 ]$ c* n
8 A5 a, J3 p+ J8 [5 N

# }  _! }3 Z2 X, VПримечание: если в строка return начинается с "<html>", то будет показана страничка html с текстом, который стоит далее. Так вместо:
2 }2 i; l3 k. M7 \) t# areturn "Chat4.htm"
6 ]5 Q7 j& e3 a7 V& N4 Q6 T3 G* b+ [* M0 H8 g- q

! Z; ]& h: c: u; ^( N+ d/ ^можно поставить:
* k3 i, q% _3 Q. r9 i" ~
  1. return "<html><body>Return to your trainer to complete the quest</body></html>"
Скопировать код
Так же если строка заканчивается без .htm или в начале нет <html>, то текст будет выведен, как системное сообщение в окне чата. В нашем случае мы сделаем так, что бы при каждом убийстве keltik выводилось системное сообщение: «Собрано N из 4-х клыков».3 `7 q0 ?6 v- t+ N( L7 y) `
7 X- g" O, z. ]* l

; l/ u& [3 D! i4 O8 ]Наш код для onKill имеет один недостаток. Он будет постоянно показывать Chat0.htm, Chat1.htm и Chat4.htm, нам же необходимо, что бы Chat0.htm и Chat1.htm показывались только один раз. Как нам это сделать? С помощью переменных.5 A+ h1 h6 e0 o) U9 L& T0 Q" A

7 T& T! n, O- |9 r# B

7 Z' X) e3 \6 w3 JВ каждом квесте строки могут храниться с помощью переменных. Эти переменные сохраняются в Вашей БД. В каждом методе мы можем назначить, прочитать и удалить переменные. Давайте изменим метод onKill, так что бы каждый диалог вызывался только один раз.
" Z; W1 K! ~# j
  1. def onKill (self,npcId,st):
    4 |* u2 c- ^4 j
  2. if npcId == KELTIR_NPC_ID:8 m7 g) K* _4 G0 l1 U9 K  z
  3. n = getCount(st)3 ], n: c; A) K- ]5 L; V
  4. if n == 0:
    , E. s, ]' C) L" C2 a
  5. if st.get('chat0') == None :
    " Q, h7 z6 R  i1 B# O/ c9 g+ r& I. G8 ^
  6. st.set("chat0", "true")7 Z! p! U( [6 a7 U) r
  7. return "Chat0.htm"" K6 E& |+ Z, [; O5 z# ~: M
  8. elif n == 1:9 n4 W3 z+ f" V9 \) L- k2 a" g
  9. if st.get('chat1') == None :
    8 p; V. j) j8 o% @% [4 v
  10. st.set("chat1", "true")
    + v5 [: @  a0 l& t% v; V6 ^
  11. return "Chat1.htm"9 n6 {- o! A& F& Q
  12. elif n >= 4:2 ^1 i9 H: x- X0 i5 p
  13. return "Chat4.htm"( x# r' w5 k- J" f
  14. return "Collected "+str(n)+" of 4 fangs"" l+ l1 q# ]: }: G8 c
  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.
% Y; R6 N, p5 f3 M2 U. l* z3 Y+ g: N+ q+ q( `6 n' j$ @

$ |1 i6 ^! R( N# l& G( W$ OВот конечный рабочий вариант квеста:) J# G; ?2 T8 ~7 R; }. w& {
  1. import sys
    0 c# b. {2 S8 o! w( J5 T2 O* }
  2. from net.sf.l2j.gameserver.model.quest import State# }$ g! H3 |/ S! ?' e* R* I! s- X
  3. from net.sf.l2j.gameserver.model.quest import QuestState
    & ~3 u8 B. v4 q! f6 X+ q5 T$ @7 Y+ }
  4. from net.sf.l2j.gameserver.model.quest.jython import QuestJython as JQuest& }$ Q/ S- c( ]# ], w' i

  5. ' X; p$ N# }# `0 P& q. n% e) Y! C
  6. KELTIR_NPC_ID = 120825 M& N$ S& E$ s4 ?8 A. Q. ^
  7. FANGS_ITEM_ID = 1859" Y# o. h* g+ J3 {4 e# {! i3 A6 z
  8. DROP_RATE    = 500000
    % |8 ~( C5 B; w# g! H9 o  u( i

  9. $ q5 j: ?. q/ P' w
  10. WORLD_MAP_ITEM_ID = 1665
    ; p" E# o- E. x1 [) c0 `1 ?& g

  11. 7 g; n" T. j6 R0 S
  12. def getCount(st) :
    $ v' }3 r! ~" q+ o! e
  13. return st.getQuestItemsCount(FANGS_ITEM_ID)4 u' L5 H; o: h! j6 G8 @8 v/ _
  14. 7 C5 j, E# v9 z4 h- g
  15. def completed(st) :' X6 z% m, E: t! J# Y) r5 ^0 ^
  16. st.setState(COMPLETED)
    " H( ]4 G4 q( m3 i0 u! d+ u3 c( M
  17. st.clearQuestDrops()
    8 `/ X: m, \  _+ H; @' A$ {) y
  18. st.takeItems(FANGS_ITEM_ID,-1)/ `* O# e- D5 J" r- g$ S2 B, q; S
  19. st.giveItems(WORLD_MAP_ITEM_ID,1)
    7 |( E  L/ B; ~1 T- t$ d! }' `9 i
  20. st.exitQuest(False)
    6 {0 U  ?% `" I. I% ^
  21. return
    $ M  B2 m1 w9 A" E
  22. $ G9 s% \  T- z/ o
  23. def check(st) :
    1 W. y  Z7 j; V% Y" ]. ]
  24. if getCount(st) >= 4 :) K9 B9 D" F' ]! ?$ A5 q0 C, K9 M
  25. completed(st)2 T; A' y" w0 i5 k# t
  26. return+ y+ ?& Z- d+ L& U* f& c3 S) M

  27. 1 S- Q2 r$ V7 I0 a
  28. class Quest (JQuest):
    2 V1 Y. T1 t5 d+ J- _3 {8 Q
  29. - ?3 `5 l. m7 d* E
  30. def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)
    2 x2 X; X: ^6 \# L6 P

  31. * E$ N$ d# x5 E, @
  32. def onEvent (self,event,st):
    / ~6 Y, d/ b3 _; V+ f2 G0 _
  33. id = st.getState()
    * A" C7 Y# H% M4 U, X  F, ]
  34. if id == CREATED : st.setState(STARTED)  Q  ~: K7 f9 M3 s
  35. elif id == COMPLETED: pass
    : c1 l: C& c; t/ Y: N& O- \
  36. elif id == STARTED : check(st)
    * f. O) _. g( X! S- B  T5 h9 n# I
  37. return
    3 T' i' @# _$ F/ g' H

  38. ' S; Q# i* M: g
  39. def onKill (self,npcId,st):- y2 E6 L0 s. W  ^; o
  40. if npcId == KELTIR_NPC_ID:. s6 ~* o6 ^6 e, K$ d
  41. n = getCount(st)
    $ _/ W" ^% q4 Q6 B9 s
  42. if n == 0:6 g- D3 _1 S- Q$ v3 B8 p
  43. if st.get('chat0') == None :9 c- J* P, z0 e8 x) u' s
  44. st.set("chat0", "true")8 t0 i' E9 s, k" j  t8 |  ?& T2 E
  45. return "Chat0.htm"
    ! d- o+ x3 c& @" x+ p, x
  46. elif n == 1:
    * B3 O+ {+ e6 {$ {
  47. if st.get('chat1') == None :
    8 M( p3 m% h& y3 R9 W1 T
  48. st.set("chat1", "true")
      \1 J0 N' r8 h4 R( a5 l* f
  49. return "Chat1.htm"
    6 H2 N2 n6 ~9 {. O/ v/ Q3 y
  50. elif n >= 4:8 k. l# I  l6 r; h. T: T
  51. return "Chat4.htm"6 o: u4 a: i* @, B9 x4 s+ }, H
  52. return "Collect "+str(n)+" of 4 fangs"" M- y: _: ?8 ]. z8 t: |
  53. return
    1 s7 z$ T2 D% ]6 m
  54. ; {/ D$ Q: ^7 e8 }: `" T
  55. QUEST    = Quest(201, "Tutorial", "Tutorial quest")* n8 R9 e5 S1 ^8 }' M3 q
  56. CREATED = State('Start',    QUEST)
    & G/ U# n% o) Q( u: B" l
  57. STARTED = State('Started', QUEST)9 A8 _' Y8 L) t, y8 }0 H: b
  58. COMPLETED = State('Completed', QUEST)
    : u7 _, t7 A- N, p0 h

  59. / _8 \- L7 T9 J0 X
  60. QUEST.setInitialState(CREATED)
    " i, x) {9 W! l9 u6 e
  61. QUEST.addStartNpc(7056)7 d3 ^$ @" d8 g# R6 m7 ^9 r6 [
  62. QUEST.addStartNpc(7012). l1 x% x5 j5 e  ^* ^( `
  63. QUEST.addStartNpc(7009)
    6 V7 K! ^# o4 o1 c% U, |
  64. QUEST.addStartNpc(7011)7 [4 B- y  D. G+ _/ J. l
  65. ; H  w# }# h& F
  66. STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
    4 S$ C+ e/ Q2 a5 i1 w& _2 r2 X
  67. STARTED.addKillId(KELTIR_NPC_ID)" }) G5 I) b& F+ @; Z0 m
  68. STARTED.addTalkId(7056)! [, N: v' I% L% Z! q" U
  69. STARTED.addTalkI d(7012)
    6 h+ B4 Q, A# Y( C! I2 P+ {
  70. STARTED.addTalkId(7009)
    ; |  c) d; C+ t6 A  b/ y. g0 @) u, a
  71. STARTED.addTalkId(7011)
Скопировать код

# Z% H, s5 ^6 N: \4 @9 {5 ]9 B, h+ D) E; y( `2 I% p7 m
Чтобы ответить, вам надо авторизироваться в системе Вход | Зарегистрироваться

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

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

638638758

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

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

admin@artace.ru Онлайн

QR-код

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