Top.Mail.Ru

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

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

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

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

x
Хроники        Interlude( I% @$ f4 X8 Z& L
Сборка        L2j* @# D/ m# l1 L# N3 @' D; D7 q1 h% f
Обратите внимание: в файле htm стартового NCP обязательно должна быть ссылка на квест:" L. l+ S# ?* c: t
  1. STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код
Для этого квеста больше ничего не надо. Все необходимое для корректной работы квеста уже добавили. Вот полный текст квеста:* ~9 D. N4 ~3 Y8 `$ U
7 p9 X5 _( W4 t4 c- U; e6 ~) Y- y8 U: D
  1. if getCount(st) >= 4 :9 n+ E# o! Q8 t+ l* W
  2. completed(st)) A* R! h0 }$ ^( V% p5 Y- h% o
  3.   return
    4 g  R3 C! C: |$ |$ t+ q% A
  4. / p! Q; I# O3 f8 M2 V
  5. class Quest (JQuest):9 [+ y- E, `" B" T* c# S
  6.   def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)
    % F4 U$ H  E, s
  7.   def onEvent (self,event,st):7 U" E5 Q, B- Y2 s- Z7 {
  8. id = st.getState()
    - r: w/ z7 V' @/ `% u
  9. if   id == CREATED  : st.setState(STARTED)% }' v- ?! Q' M1 a" `- w" J
  10. elif id == COMPLETED: pass
    3 y: e+ I6 d0 f3 E, t/ f/ w
  11. elif id == STARTED  : check(st), x1 `+ p1 f8 |
  12. return
    8 g1 B3 o. w" A

  13. 8 p$ X' i  O) B2 G
  14. QUEST     = Quest(201,"Tutorial", "Tutorial quest")
    # ?0 q3 f  n, Z3 T8 [
  15. CREATED   = State('Start',     QUEST)
    / w, ^4 _/ M* C& _$ m( C
  16. STARTED   = State('Started',   QUEST)
    " X" V! ]& s2 r/ w7 s6 q1 P
  17. COMPLETED = State('Completed', QUEST)1 N  n3 x# B4 v' O- I% t6 Q0 }
  18. - f9 \: z4 o, F- l) @" ?
  19. QUEST.setInitialState(CREATED)' P. R8 |- i, ?3 V
  20. QUEST.addStartNpc(7056)
    & t) x+ A5 [7 p: V( W( s
  21. STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код
Теперь рассмотрим, как это работает.% n7 R0 @& |( Y1 s* b, M
Игрок подходит к начальному NCP (в данном случае 7056), нажимает на «Quest». Квест будет создан и состояние квеста перейдет к CREATED и игроку будет показана страничка Start.htm с описанием квеста. Тогда метод onEvent, поле открытия странички Start.htm переведет состояние квеста в STARTED и игроку будет показана страничка Started.htm, где будет опсание того, как найти keltirs и .т.д.) y, o( P6 [8 D: }; H  T
& A4 k6 T; o- Q! `; }: d& B

' r2 {' E! a8 J9 eПри состоянии STARTED будет зарегистрирован дроп «fangs» при убийстве keltirs. Игрок может вернуться к стартовому NCP и спросить о квесте – метод onEvent будет вызван снова. Если у игрока не хватает необходимого количества предметов, то метод check() не переведет квест в следующее состояние и Started.htm будет показана снова. Но если игрок собрал необходимее количество предметов (в данном случае 4 клыка), то метод check() вызовет метод completed() который переведет квест в новое состояние COMPLETED, заберет все клыки, даст карту мира, т.к. это награда за квест, покажет Completed.htm и завершит квест.+ e$ @$ N( `. Q& h7 H4 X2 c
3 J% a- Q% m1 V! H. z
! ^8 M% P0 y/ l( E! W4 _: h
Теперь давайте сделаем наш квест более похожим на то, что он должен из себя представлять.* d  g3 e& A6 \% r- {7 p
Прежде всего у нас есть 3 метода для объявления их в Яве – onTalk, onKill и onEvent. Если методы onTalk и onKill не объявлены, то за них все будет делать метод onEvent, т.е. определять квестовых монстров и вызывать диалоги NCP. Есть примечание, методы onTalk и onKill будут вызывать только диалоги с NCP в зависимости от текущего состояния квеста. Метод onKill будет вызываться только тогда, когда мы убиваем квестового монстра.
* B0 `& S( ?2 {9 X. v5 v" D9 W. i9 T5 n+ P( S2 T+ [1 z
! @/ i7 k& R+ ?, c  y
Давайте рассмотрим как вызывается метод onKill при убийстве keltir в состоянии квеста STARTED:$ X3 p" B# J. t! m& g5 J8 p
  1. STARTED.addKillId(KELTIR_NPC_ID)
Скопировать код
и метод onKill в классе Quest:
# {9 {! ?9 ~4 x( s
+ D$ e/ P4 [2 O+ Y+ f
  1. class Quest (JQuest):
    $ C) I4 B1 h3 F
  2.   ...
    6 C5 [% M6 K9 i' k: F7 B- ~
  3.   def onKill (self,npcId,st):
    , h( T! R7 o7 Y& o' _. f. R& c
  4. if npcId == KELTIR_NPC_ID:
    9 g: E6 n/ ]! e8 ?$ e9 Q& M$ e0 L$ h
  5.    n = getCount(st)5 S8 \; ~* Z( n( D8 J
  6.    if   n == 0:4 C( f4 U8 X1 K) g/ X
  7.        return "Chat0.htm"0 `" V; @6 t( b
  8.    elif n == 1:
    9 L( Q* m% ?. E) a5 n2 c
  9.        return "Chat1.htm"
    ) H, b+ [' P& M" u! R, s/ J' B3 x( @
  10.    elif n >= 4:/ f% l5 t* |/ j* K! a/ f) f$ F
  11.        return "Chat4.htm"
    # S: V6 Z6 I5 f7 ~- n
  12.    return "Collected "+str(n)+" of 4 fangs"' I' Q. Q5 G' ?
  13. return
Скопировать код
Метод onKill (а так же метод onTalk) имеет следующие параметры:2 d) o: Y0 |5 b9 N

( @  s  _5 ]8 B$ f% m
/ Z# b0 a( P; D) K. z# n
• self – квест
0 o) y+ V& C7 K8 K$ u; P5 @% Y• npcId – ID NCP, которого мы должны убивать (если это метод onTalk, то ID того NCP, с которым мы должны поговорить).
9 d9 @8 J/ W1 h" J• st – текущее состояние игрока.' g: X1 x% r+ V

; o; s; }7 W+ Q- S, K1 o

4 \7 K" q6 i7 R) R2 P8 o  S+ ?В этом методе мы проверяем и отмечаем, является ли убитый NCP keltir’ом. В основном эта проверка не нужна, т.к. у нас только KELTIR_NPC_ID.+ }5 \# `* X# a5 i" D* }! `9 ]/ _

5 j* {9 n+ t/ X- E4 }
- w7 x# j: h3 Y3 h
Затем проверяем количество предметов (в данном случае количество клыков), и если их вообще нет, то возвращаем строку "Chat0.htm", если только один предмет, то возвращаем строку "Chat1.htm", если же предметов 4 или больше, то "Chat4.htm". Если строка возвращена из методов onEvent, onKill или onTalk, то сервер покажет соответствующие htm. В Chat0.htm может иметь следующий текст: «Вы не имеете ни одного клыка, возвращайтесь позже, когда соберете 4 штуки и бла, бла, бла…», в Chat1.htm может быть следующий текст: «У Вас всего 1 клык, по этому соберите еще…». В Chat4.htm – «Вы собрали необходимое количество предметов, возвращайтесь к вашему тренеру, что бы завершить квест…»! W- B' x) i3 E1 \& S
9 P* Q! y+ t0 U6 l4 d* Y

1 c3 e0 W" V" _3 b. ~! m. YПримечание: если в строка return начинается с "<html>", то будет показана страничка html с текстом, который стоит далее. Так вместо:
3 q" s, N$ c8 Ureturn "Chat4.htm"9 v3 Z7 X& B+ v9 |- d9 u
2 M/ k2 }1 E" N% D
& W; [6 c# m) F" t1 R1 O* I: h
можно поставить:; C$ P! b  {# D1 [
  1. return "<html><body>Return to your trainer to complete the quest</body></html>"
Скопировать код
Так же если строка заканчивается без .htm или в начале нет <html>, то текст будет выведен, как системное сообщение в окне чата. В нашем случае мы сделаем так, что бы при каждом убийстве keltik выводилось системное сообщение: «Собрано N из 4-х клыков».5 Y. t7 V8 m% v. i$ d, M+ r  Y
1 E+ F# L* G& n7 ~8 d2 `
, C7 E+ S' ~9 X- V( c1 m+ V: ~
Наш код для onKill имеет один недостаток. Он будет постоянно показывать Chat0.htm, Chat1.htm и Chat4.htm, нам же необходимо, что бы Chat0.htm и Chat1.htm показывались только один раз. Как нам это сделать? С помощью переменных.' \0 h' C  P. k+ I$ D
- \3 m; A4 l: U/ m( a  B

+ Q) Y# q) j/ iВ каждом квесте строки могут храниться с помощью переменных. Эти переменные сохраняются в Вашей БД. В каждом методе мы можем назначить, прочитать и удалить переменные. Давайте изменим метод onKill, так что бы каждый диалог вызывался только один раз.
- t. x9 |7 x" F/ N) I  F2 e
  1. def onKill (self,npcId,st):
    * J6 k) ~9 U: m: i
  2. if npcId == KELTIR_NPC_ID:
    4 q8 ~. l+ s7 l8 d  N% x5 J# n" S
  3. n = getCount(st)
    - f; E5 Q+ v) v+ `
  4. if n == 0:
    8 y9 _: V/ G8 [
  5. if st.get('chat0') == None :
    8 l9 c8 H! Q8 m( o0 J; o" h
  6. st.set("chat0", "true"). s$ A/ T% o- x( l8 D: a2 ~$ G
  7. return "Chat0.htm"5 O2 Z* E4 E9 |3 Z5 M
  8. elif n == 1:
    7 q1 T7 |& M, t: X0 M
  9. if st.get('chat1') == None :
    . e3 o. ^& S4 r) I! k
  10. st.set("chat1", "true")
    * [4 |6 E  V8 p% i) k
  11. return "Chat1.htm"7 b/ I% Y  @' B. v  F6 v
  12. elif n >= 4:
    ( d- w. u( K' |, H
  13. return "Chat4.htm"
    ' Z7 L! m1 w4 l, b
  14. return "Collected "+str(n)+" of 4 fangs"
    7 R: H7 M1 g3 d5 N) Q( r4 o
  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.
) g# t5 H- }* z- }- z: y
9 {) L7 _' b! O, g" g  |% s; ^. i

4 H6 {# S) q+ ~: QВот конечный рабочий вариант квеста:
5 I( J6 y+ j7 R2 B: x
  1. import sys! w6 J$ n, u" ]( i- F
  2. from net.sf.l2j.gameserver.model.quest import State# n  F5 E$ a3 u! c
  3. from net.sf.l2j.gameserver.model.quest import QuestState2 k: L. |5 |9 y& G8 p$ p1 [2 B2 x
  4. from net.sf.l2j.gameserver.model.quest.jython import QuestJython as JQuest2 f+ B2 o9 I1 T1 K
  5. ( z0 X" H9 n- L& F4 v3 s- a; e
  6. KELTIR_NPC_ID = 120820 W) o; X$ R% G9 h$ g, c+ ?1 ^" z
  7. FANGS_ITEM_ID = 1859' p4 c% Z4 [% a7 F
  8. DROP_RATE    = 500000- ?# a- o1 G* l. g  D
  9. / ]0 V0 v! E9 O0 x0 H( r# M; _
  10. WORLD_MAP_ITEM_ID = 1665
    2 F, ^" W7 u. l% J
  11. 6 [  F& S$ O- \, K' ^( T: {
  12. def getCount(st) :
    " Q- u+ x- i9 w- ^2 L! B" U: i
  13. return st.getQuestItemsCount(FANGS_ITEM_ID)
    2 c5 T2 ]* \, e

  14. , ^" l. f8 c8 l+ C4 `
  15. def completed(st) :& Y! G3 V9 ^7 S/ v1 t
  16. st.setState(COMPLETED)
    ) b; n: `. N7 h7 A/ a) u
  17. st.clearQuestDrops()  }: |9 K: U" b) p4 U' w! ~
  18. st.takeItems(FANGS_ITEM_ID,-1)1 b/ r) V  W2 {" G9 |8 e
  19. st.giveItems(WORLD_MAP_ITEM_ID,1)
    - E. c& o1 N( ]5 U- b
  20. st.exitQuest(False)5 b/ |4 q0 T3 B
  21. return
    - O( s5 ]+ h1 m. n' x

  22. & G7 {9 W8 }: S9 I( u# S
  23. def check(st) :
      I$ X( A! h+ J
  24. if getCount(st) >= 4 :
    : Z$ Z: P5 l* a
  25. completed(st)* v# O/ s9 c$ ?* W% n
  26. return' ^/ p, ]" A4 `! N% Z  n7 m+ y
  27. & r9 V' m! W2 F3 E
  28. class Quest (JQuest):
    & e6 T# M3 W# m/ D( e) E# K
  29. $ v+ c$ |( A0 c  V1 R* }7 a
  30. def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)
    ' d- v" |: F, m) @$ v' a  X

  31. ! e5 e# w9 q8 f4 f8 `- ?% S2 ^
  32. def onEvent (self,event,st):' |' {) x5 _# Y+ n) {
  33. id = st.getState(). }  H/ R$ s1 E; x! S0 I
  34. if id == CREATED : st.setState(STARTED), b! [! G* b( W5 _4 q
  35. elif id == COMPLETED: pass0 i+ u8 ]6 R2 ^7 z2 t
  36. elif id == STARTED : check(st)
    9 p+ B) Q: P- g" F
  37. return: V  b" j$ S" f' D$ q( d

  38.   g- s; x9 x8 z8 U0 @. z
  39. def onKill (self,npcId,st):
    * @1 Q! ]; @$ J& v
  40. if npcId == KELTIR_NPC_ID:
    # V7 F2 m# X' j% F) @3 r! R
  41. n = getCount(st)
    9 B. B6 y5 ?( [; L3 H- J1 f
  42. if n == 0:0 d* @# S6 L& x* M  D
  43. if st.get('chat0') == None :
    ) k  m" j% l- i6 a$ j3 K
  44. st.set("chat0", "true")7 V% r# _  l- U- ?( a3 i
  45. return "Chat0.htm"; h* f4 c3 |8 D+ Y" l0 ]
  46. elif n == 1:8 _: _) t* j) `2 r* ]: x# r
  47. if st.get('chat1') == None :  g7 s% S  G- e
  48. st.set("chat1", "true")
    ( x) S4 {4 Y& u8 ^7 c4 W9 ?
  49. return "Chat1.htm"
    2 a7 Z& S, G9 b5 ^8 K  l5 O2 Q% w
  50. elif n >= 4:
    - N$ q+ _2 X. z/ X: R* F1 b9 ?( k
  51. return "Chat4.htm"
    6 l# ]& A" ], _
  52. return "Collect "+str(n)+" of 4 fangs"
    7 R9 _9 o/ n4 r; R$ w1 Y( Z; W1 ?
  53. return
    + A  @+ G& Q& T2 _

  54. ' x% v; t* m  D% `/ Q7 `' c" F
  55. QUEST    = Quest(201, "Tutorial", "Tutorial quest"), f# `- d7 {& _' a) n
  56. CREATED = State('Start',    QUEST)
    ( s& C% P) u! p1 g( M9 V
  57. STARTED = State('Started', QUEST); _/ A6 f/ B2 r1 ?( j" M7 ^( U
  58. COMPLETED = State('Completed', QUEST)4 Z0 \* T0 F& s7 ~  E

  59. 7 ]/ |! z8 m. n  c" s
  60. QUEST.setInitialState(CREATED)+ {9 X$ _" N4 u, D0 L
  61. QUEST.addStartNpc(7056)! ?4 Z# x2 ]7 W
  62. QUEST.addStartNpc(7012)
    5 l- X& R& ]+ Y) l! j
  63. QUEST.addStartNpc(7009)
    ( f* Q9 ], S, e9 _. Z% I9 R
  64. QUEST.addStartNpc(7011)( J  e" t  [8 j6 n0 f

  65. + u# J- @0 s* h/ ?( N- t
  66. STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
    1 k% V0 d! A9 K% @2 b2 a4 S3 h& a
  67. STARTED.addKillId(KELTIR_NPC_ID)0 X- n( S" C  {. m0 A8 L
  68. STARTED.addTalkId(7056)
    2 t9 I, j! W* U: [
  69. STARTED.addTalkI d(7012)
    * |. o4 }$ C4 t/ H9 [$ }$ g
  70. STARTED.addTalkId(7009)0 Y  P1 v8 e/ l+ G6 e
  71. STARTED.addTalkId(7011)
Скопировать код
0 i9 y6 f9 }+ _

5 T& ~  C) [8 {+ G
Чтобы ответить, вам надо авторизироваться в системе Вход | Зарегистрироваться

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

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

638638758

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

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

admin@artace.ru Онлайн

QR-код

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