Top.Mail.Ru

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

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

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

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

x
Хроники        Interlude
/ J/ M+ M/ h# U$ c/ MСборка        L2j) W0 v2 A: N/ \) a7 F
Обратите внимание: в файле htm стартового NCP обязательно должна быть ссылка на квест:
; {! r7 Q2 N6 L! i) p% e& ]$ V6 T
  1. STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код
Для этого квеста больше ничего не надо. Все необходимое для корректной работы квеста уже добавили. Вот полный текст квеста:% Z$ h/ B; L% I; P! s. X

& B8 t! o3 Y) m" R
  1. if getCount(st) >= 4 :+ X# M/ O% W" T0 K8 C
  2. completed(st)
    4 e* `3 A0 Q) l7 d* n8 u! r1 A
  3.   return3 @% [9 Z% _- A
  4. ' u) p' z) P5 J7 L6 K; C) O1 d  v
  5. class Quest (JQuest):5 V  ~8 y5 \$ J3 C+ q6 n
  6.   def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)) r  }! e5 y% S
  7.   def onEvent (self,event,st):5 y/ t2 [2 }: S
  8. id = st.getState(). D/ ]! O; R. n  l8 c/ F% Z4 W  ]7 m
  9. if   id == CREATED  : st.setState(STARTED)5 u8 `3 ?- Z6 ]; D0 T- |% }% v, }9 ]
  10. elif id == COMPLETED: pass3 S6 L5 D9 r0 U' R; W
  11. elif id == STARTED  : check(st)9 Y% s* q, d  V* q
  12. return. o" y1 u! S, |4 S0 b5 m

  13. $ h6 f2 ?; \# p0 I7 ?& _
  14. QUEST     = Quest(201,"Tutorial", "Tutorial quest")# r, `% I- v) g
  15. CREATED   = State('Start',     QUEST)
    7 g3 i! V, U9 M7 s
  16. STARTED   = State('Started',   QUEST)
    # G5 }) N/ l0 i' D& W1 k6 w. @
  17. COMPLETED = State('Completed', QUEST)
    9 u. b4 Q4 ?# c) `4 J$ z- F6 {
  18. * q, P/ u2 P0 y% H% W1 @6 T
  19. QUEST.setInitialState(CREATED)
    $ W) p$ N6 x: W! Q- i" i8 b
  20. QUEST.addStartNpc(7056)
    : q& s* ~5 s: p6 w! N2 w+ k8 w+ `& Y
  21. STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код
Теперь рассмотрим, как это работает.
& y3 N) U+ s) l7 t2 a3 T# B: ~Игрок подходит к начальному NCP (в данном случае 7056), нажимает на «Quest». Квест будет создан и состояние квеста перейдет к CREATED и игроку будет показана страничка Start.htm с описанием квеста. Тогда метод onEvent, поле открытия странички Start.htm переведет состояние квеста в STARTED и игроку будет показана страничка Started.htm, где будет опсание того, как найти keltirs и .т.д.7 Q. U/ d1 [$ j

2 N7 l0 m  ?4 p8 G/ c$ F

0 w! I/ Y/ ~, n) m- g. SПри состоянии STARTED будет зарегистрирован дроп «fangs» при убийстве keltirs. Игрок может вернуться к стартовому NCP и спросить о квесте – метод onEvent будет вызван снова. Если у игрока не хватает необходимого количества предметов, то метод check() не переведет квест в следующее состояние и Started.htm будет показана снова. Но если игрок собрал необходимее количество предметов (в данном случае 4 клыка), то метод check() вызовет метод completed() который переведет квест в новое состояние COMPLETED, заберет все клыки, даст карту мира, т.к. это награда за квест, покажет Completed.htm и завершит квест.& N, V, j+ P) }  a5 Q$ y. t; g* l! v- P/ [

' d) a0 {  f9 v/ |$ |( ~: S4 m
  D' Y& v5 ?  f4 i8 G, G8 n4 J
Теперь давайте сделаем наш квест более похожим на то, что он должен из себя представлять., H4 M4 j/ M4 r  B, J4 I3 b/ _5 B6 t
Прежде всего у нас есть 3 метода для объявления их в Яве – onTalk, onKill и onEvent. Если методы onTalk и onKill не объявлены, то за них все будет делать метод onEvent, т.е. определять квестовых монстров и вызывать диалоги NCP. Есть примечание, методы onTalk и onKill будут вызывать только диалоги с NCP в зависимости от текущего состояния квеста. Метод onKill будет вызываться только тогда, когда мы убиваем квестового монстра., @( s0 ?3 j3 P# \, X# k( I5 j8 q

2 A1 y! T5 i" e/ Z

; R% v& \; N' S" H; SДавайте рассмотрим как вызывается метод onKill при убийстве keltir в состоянии квеста STARTED:
2 l- D7 x8 Q6 M9 f4 K
  1. STARTED.addKillId(KELTIR_NPC_ID)
Скопировать код
и метод onKill в классе Quest:
' N2 ]5 p& G) D! `& y7 b
' D; }% S: s% g
  1. class Quest (JQuest):( w+ R( J7 t9 ~  p$ J
  2.   ...
    ! a1 _; W; |3 A; q/ t
  3.   def onKill (self,npcId,st):. E+ g: e, _% c$ `" t
  4. if npcId == KELTIR_NPC_ID:% X2 A7 Y, T1 d( x
  5.    n = getCount(st)
    9 T6 B. _4 G) N5 h! t2 R
  6.    if   n == 0:
    0 Z( V/ n. |5 X& ?  H. |& {8 Z
  7.        return "Chat0.htm"
    & k2 H( k" o0 X* j/ I1 }9 ?) [
  8.    elif n == 1:
    3 {3 ?8 c8 @. ?' J# C
  9.        return "Chat1.htm"1 Z  s+ Z, {3 M  c! y
  10.    elif n >= 4:
    ! M1 M$ O* R4 ~
  11.        return "Chat4.htm"
    6 Q2 W3 _$ n/ P* u) D% N2 z" _
  12.    return "Collected "+str(n)+" of 4 fangs"9 v1 \* m9 |! W' `, y9 k. B
  13. return
Скопировать код
Метод onKill (а так же метод onTalk) имеет следующие параметры:  O& h- X6 D7 M. h- y
* q3 ?9 w- y- N  l4 [- T* v' P

  Y0 n7 A' q6 o( ]• self – квест
6 q; g6 Q' u, Q7 D- d• npcId – ID NCP, которого мы должны убивать (если это метод onTalk, то ID того NCP, с которым мы должны поговорить).0 E, ?) W1 ~6 x
• st – текущее состояние игрока.
* ^( F, B0 j: ]% z2 G2 k& K3 y- S- i; Y0 ]& ?$ h4 g/ t  T
1 O1 q! S% ^+ O! q6 i# ~3 ?# P
В этом методе мы проверяем и отмечаем, является ли убитый NCP keltir’ом. В основном эта проверка не нужна, т.к. у нас только KELTIR_NPC_ID.
! v2 x8 L; Z% p' Z% k
" p6 o) o( B3 B

+ R& @) a9 R+ n( P' R* B, gЗатем проверяем количество предметов (в данном случае количество клыков), и если их вообще нет, то возвращаем строку "Chat0.htm", если только один предмет, то возвращаем строку "Chat1.htm", если же предметов 4 или больше, то "Chat4.htm". Если строка возвращена из методов onEvent, onKill или onTalk, то сервер покажет соответствующие htm. В Chat0.htm может иметь следующий текст: «Вы не имеете ни одного клыка, возвращайтесь позже, когда соберете 4 штуки и бла, бла, бла…», в Chat1.htm может быть следующий текст: «У Вас всего 1 клык, по этому соберите еще…». В Chat4.htm – «Вы собрали необходимое количество предметов, возвращайтесь к вашему тренеру, что бы завершить квест…»0 G" ~, s2 k8 D) R* H

2 n! C3 T( C* u) e0 a5 W

( ?7 B" A. O% `  c; \Примечание: если в строка return начинается с "<html>", то будет показана страничка html с текстом, который стоит далее. Так вместо:3 I  o) U) j  x! [( A5 |
return "Chat4.htm", B1 Z  E  @/ e" z' }; s
! |- V3 g+ n! T; Y. i

- F$ P4 A4 P" d0 Iможно поставить:8 c2 G9 t9 ?) Y2 k( j8 y# |3 U
  1. return "<html><body>Return to your trainer to complete the quest</body></html>"
Скопировать код
Так же если строка заканчивается без .htm или в начале нет <html>, то текст будет выведен, как системное сообщение в окне чата. В нашем случае мы сделаем так, что бы при каждом убийстве keltik выводилось системное сообщение: «Собрано N из 4-х клыков».
6 R% F: l) A# F' Q' Y0 [, Q  D( T: j* j( e! A
8 ?  S* o' ]% c4 d; g5 t
Наш код для onKill имеет один недостаток. Он будет постоянно показывать Chat0.htm, Chat1.htm и Chat4.htm, нам же необходимо, что бы Chat0.htm и Chat1.htm показывались только один раз. Как нам это сделать? С помощью переменных.
" M3 u9 _) [9 A* v
( p: W" j8 Q. r1 O

3 W1 V% x; R3 w& bВ каждом квесте строки могут храниться с помощью переменных. Эти переменные сохраняются в Вашей БД. В каждом методе мы можем назначить, прочитать и удалить переменные. Давайте изменим метод onKill, так что бы каждый диалог вызывался только один раз.- h9 i! h5 g4 g2 g; K5 F
  1. def onKill (self,npcId,st):5 F% J; C8 p/ ?: f/ i# M0 C6 x
  2. if npcId == KELTIR_NPC_ID:$ M4 Z! o+ A" {& P
  3. n = getCount(st)& d/ Z; f2 Z/ [/ ?" C- {' J' X
  4. if n == 0:
    5 U0 P& C! ?) I9 s9 \
  5. if st.get('chat0') == None :
    8 g# g. X( t! K, Z  E( _1 }4 f
  6. st.set("chat0", "true")2 ~3 T# n; m9 H$ R- Q$ D6 B
  7. return "Chat0.htm"5 q2 H2 w! L3 y
  8. elif n == 1:; F3 @+ I2 K* w$ ]0 v* F4 `% D1 c
  9. if st.get('chat1') == None :
    . q# @' m. D4 r
  10. st.set("chat1", "true")
    % U( [; p4 Y+ B+ E! m
  11. return "Chat1.htm"
    * W" q" K/ i0 k7 y$ ]$ m+ R
  12. elif n >= 4:  L8 G1 n$ F# {5 w  g. q
  13. return "Chat4.htm"0 [+ i  g8 ?, e7 l- @# }& u2 K
  14. return "Collected "+str(n)+" of 4 fangs"
    ! n0 |. G# C; b3 Z3 `/ p. F
  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.% ~2 e! I) B# f' U9 W" B
* r; ^/ ]$ a+ k; A, x  K+ \) e

3 \* q7 P0 r# l: E7 EВот конечный рабочий вариант квеста:2 ^7 Q8 O+ e. J1 `. H
  1. import sys
    0 t# y) f5 x# `4 A6 h
  2. from net.sf.l2j.gameserver.model.quest import State0 Z1 C" i. [  X
  3. from net.sf.l2j.gameserver.model.quest import QuestState
    5 f5 {8 [- k+ _' b1 _% e0 @; b8 N
  4. from net.sf.l2j.gameserver.model.quest.jython import QuestJython as JQuest
    ( m& a# K% |3 k1 f0 P3 a$ D
  5.   z8 f0 o; g5 Y  ]  h5 G& Y
  6. KELTIR_NPC_ID = 12082& P1 C/ O- U' z: E  o0 m0 M2 T
  7. FANGS_ITEM_ID = 1859; Y" G# S( ^) B: `& J
  8. DROP_RATE    = 500000# a8 ]$ ^6 U7 R# D: o, r

  9. # h, c5 n- y' L6 t
  10. WORLD_MAP_ITEM_ID = 1665
    % [+ E8 }: J# H; v& S6 h5 m

  11. 4 i  ]4 i; K# ~) a  y8 l3 o
  12. def getCount(st) :
    ; y/ H4 @8 ^0 Q+ ]) g8 r$ A; T
  13. return st.getQuestItemsCount(FANGS_ITEM_ID)5 v/ J  I" P5 E# M

  14. % O/ ^' G6 d' Y$ I
  15. def completed(st) :1 V5 D9 j. \; B4 A+ w' r
  16. st.setState(COMPLETED)5 i$ h& S+ j& L6 t! T' [
  17. st.clearQuestDrops()
    ( S4 U9 }% m/ ~( v
  18. st.takeItems(FANGS_ITEM_ID,-1)6 R7 ^, C0 C" h. Y+ A2 {
  19. st.giveItems(WORLD_MAP_ITEM_ID,1)/ y4 d6 H, i0 I9 b; {
  20. st.exitQuest(False)
    1 a! m2 g6 ?9 [- a- G
  21. return
    0 t& v3 N5 J+ O+ k! p
  22. - l3 E9 J, P& Z" B6 ?& `3 _
  23. def check(st) :# }( G0 Z, ?5 ?8 r) |
  24. if getCount(st) >= 4 :" t5 l( W$ J: s, I. ?( [5 r$ f
  25. completed(st)
    * ~1 q) F/ I6 ]5 a) m1 }1 T' ~0 ]
  26. return) g- x5 h9 J+ d! k9 o3 E/ p
  27. 6 N' a5 ~" y) S6 i" H, Q
  28. class Quest (JQuest):) w2 `. e! d5 e6 B

  29. " d4 w3 j/ ?0 ^/ D, D0 p( w
  30. def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)
    5 \0 C5 E, M3 z: R* v

  31. ( d' ~+ Q% Y2 s5 R3 ?
  32. def onEvent (self,event,st):
    * P" S$ O! P  E( W9 ~& V4 g
  33. id = st.getState()' s' }6 H: |9 e  U- W3 l
  34. if id == CREATED : st.setState(STARTED)
    7 A5 R7 D; J* ?- a9 {: M; w
  35. elif id == COMPLETED: pass* x6 R) T5 h% E- x! U# n7 m
  36. elif id == STARTED : check(st)& x+ c$ T* Q- _# S4 ^. Z
  37. return, H5 f# e! ^3 v* b  I) ^! N- I
  38. ; i  t+ Q' ?. `9 ^% ?3 T% l) j
  39. def onKill (self,npcId,st):
    8 U: w1 c. t( v
  40. if npcId == KELTIR_NPC_ID:
    % O& _8 Q: f4 j' t
  41. n = getCount(st)
    ' Q: k. I9 n9 @; f+ H$ i
  42. if n == 0:
    . @" ?! G" x% \; P6 \( v2 S
  43. if st.get('chat0') == None :4 X& W: \- M* a# U/ W% l
  44. st.set("chat0", "true")
    1 h, Y0 \- F6 l
  45. return "Chat0.htm"1 H- g/ `# w; k) v+ h& L- N
  46. elif n == 1:0 t; {. h/ q: z" u3 d; a+ N! g
  47. if st.get('chat1') == None :
    7 J8 L& ~+ K) Z% k9 f9 c" w- t
  48. st.set("chat1", "true")
    ! I. Y% P6 V, P- }/ t. k
  49. return "Chat1.htm"
    : Z+ m# X1 L  F; J0 e, W
  50. elif n >= 4:( X+ F9 P3 P8 ], {3 o
  51. return "Chat4.htm"! i7 m, F$ _9 d+ j  X
  52. return "Collect "+str(n)+" of 4 fangs"' d( I# E9 ^; M  T8 l7 U" N
  53. return( b  M( T/ I4 u4 z# J

  54. 6 Q0 i0 y# e2 a; M- p- B# O
  55. QUEST    = Quest(201, "Tutorial", "Tutorial quest")7 d$ V6 g9 N1 X' D" x
  56. CREATED = State('Start',    QUEST)
    " O. O! q7 M0 k7 ^8 a( u4 }
  57. STARTED = State('Started', QUEST)- h( ~9 r& W, G1 P( b6 D
  58. COMPLETED = State('Completed', QUEST)& W! ]& w' l/ }" N

  59. 0 Q" K, r, N' D8 I; X  {% Z
  60. QUEST.setInitialState(CREATED)
    7 _6 a: c& c4 h
  61. QUEST.addStartNpc(7056)
    ! ^* C) D; }  ]1 Q
  62. QUEST.addStartNpc(7012); T6 F8 q" Z; o! O
  63. QUEST.addStartNpc(7009)
    # v* Y, C' w. A7 w/ Z7 w
  64. QUEST.addStartNpc(7011)7 W3 F# N( X/ C) }9 P9 Y( y' V

  65. # I1 q1 \" h7 i6 \
  66. STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
    . `1 H& Z0 N0 H; u# z( Z4 M4 C
  67. STARTED.addKillId(KELTIR_NPC_ID)
    : Q/ ^& H  t9 ?# b! u  C# `8 G# L- S; a
  68. STARTED.addTalkId(7056)
    ) M  g) n5 o! [% u, D
  69. STARTED.addTalkI d(7012)8 c5 X$ z. F) T* R+ {4 i
  70. STARTED.addTalkId(7009)
    7 Y! F5 ~) D6 S
  71. STARTED.addTalkId(7011)
Скопировать код
7 ^$ B- w4 x+ D! o4 X) D

, F8 e. P( a# [3 m) f, r! H
Чтобы ответить, вам надо авторизироваться в системе Вход | Зарегистрироваться

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

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

638638758

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

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

admin@artace.ru Онлайн

QR-код

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