Top.Mail.Ru

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

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

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

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

x
Хроники        Interlude
' I3 L8 u) X# u8 D% t. hСборка        L2j
; Z# p8 q! P. t0 E; [, Q+ dОбратите внимание: в файле htm стартового NCP обязательно должна быть ссылка на квест:
. ~/ |- a7 [+ }& y# J
  1. STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код
Для этого квеста больше ничего не надо. Все необходимое для корректной работы квеста уже добавили. Вот полный текст квеста:0 O& b1 r0 Z) ^% M# j
3 p: p5 ?7 b8 C
  1. if getCount(st) >= 4 :
    $ U5 }# |. v2 m1 p! L; O
  2. completed(st); |+ g3 s* A; _5 d
  3.   return
    6 I& ?7 r# X. H% k0 w, U0 g7 G
  4. 5 ]9 J% V* @# q
  5. class Quest (JQuest):; l3 U% e1 ~' \! D. E. u3 z' o
  6.   def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)
    ( g" d1 _9 ~8 @6 B0 U; X
  7.   def onEvent (self,event,st):
    $ l6 Q7 @1 [' D
  8. id = st.getState()
    / i+ J) C0 ^' w( e
  9. if   id == CREATED  : st.setState(STARTED)
    " _) ]9 N5 k5 o5 g$ ?% {; U. ?0 @
  10. elif id == COMPLETED: pass" d8 [# [% w4 _5 u
  11. elif id == STARTED  : check(st)  D1 \+ g- `. u
  12. return
    9 B0 k6 z" G% M
  13. & p& [/ t1 _0 V: u( ~% N& {; r) T
  14. QUEST     = Quest(201,"Tutorial", "Tutorial quest")
    - i* E! P4 @/ @5 ?( `3 G: [
  15. CREATED   = State('Start',     QUEST)2 [4 l- s% j; ]+ Q$ `5 [6 o% q1 T
  16. STARTED   = State('Started',   QUEST)
    5 B9 d8 e$ l% F
  17. COMPLETED = State('Completed', QUEST)
    # s) e7 s$ y5 D/ t

  18. 8 w0 D* \4 s& k  M# B5 [" D5 i+ B# }
  19. QUEST.setInitialState(CREATED)7 V& M( @, Z" E, g5 z* w
  20. QUEST.addStartNpc(7056)
    : h; Y8 D1 d! q# T/ V8 d3 X
  21. STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код
Теперь рассмотрим, как это работает.& o: a0 Q1 x) K
Игрок подходит к начальному NCP (в данном случае 7056), нажимает на «Quest». Квест будет создан и состояние квеста перейдет к CREATED и игроку будет показана страничка Start.htm с описанием квеста. Тогда метод onEvent, поле открытия странички Start.htm переведет состояние квеста в STARTED и игроку будет показана страничка Started.htm, где будет опсание того, как найти keltirs и .т.д.4 L2 H# m- Q) f: m# s

" }3 A& W8 I5 m' |8 J7 O  D& }

4 o. J! |4 ]# lПри состоянии STARTED будет зарегистрирован дроп «fangs» при убийстве keltirs. Игрок может вернуться к стартовому NCP и спросить о квесте – метод onEvent будет вызван снова. Если у игрока не хватает необходимого количества предметов, то метод check() не переведет квест в следующее состояние и Started.htm будет показана снова. Но если игрок собрал необходимее количество предметов (в данном случае 4 клыка), то метод check() вызовет метод completed() который переведет квест в новое состояние COMPLETED, заберет все клыки, даст карту мира, т.к. это награда за квест, покажет Completed.htm и завершит квест.8 G+ t- h  c+ S" n% c# ^

) [8 X; e2 Z8 ]  v6 [
' |7 D: O5 ?# j7 U; C4 y
Теперь давайте сделаем наш квест более похожим на то, что он должен из себя представлять.- a7 x5 T  w3 b1 O+ C& P
Прежде всего у нас есть 3 метода для объявления их в Яве – onTalk, onKill и onEvent. Если методы onTalk и onKill не объявлены, то за них все будет делать метод onEvent, т.е. определять квестовых монстров и вызывать диалоги NCP. Есть примечание, методы onTalk и onKill будут вызывать только диалоги с NCP в зависимости от текущего состояния квеста. Метод onKill будет вызываться только тогда, когда мы убиваем квестового монстра.
9 F& w% G1 [" A& U% n0 C0 p; {/ ~2 H/ B; y* @# s
+ Z0 r  I, v8 `* f
Давайте рассмотрим как вызывается метод onKill при убийстве keltir в состоянии квеста STARTED:
+ o) s! _- F' m
  1. STARTED.addKillId(KELTIR_NPC_ID)
Скопировать код
и метод onKill в классе Quest:
* v; X% e8 q& ~/ m9 d' ^) s, V$ U# v( e! M# ?* r- O
  1. class Quest (JQuest):
    + \& Y2 F- f# {2 v# {& k$ m- F
  2.   ...
    : W7 A7 C7 U3 E9 q
  3.   def onKill (self,npcId,st):8 W5 z1 q4 Z  p
  4. if npcId == KELTIR_NPC_ID:
    ( e1 y. L0 t1 H
  5.    n = getCount(st)* z0 `' ^9 f; ]2 Q  \" p
  6.    if   n == 0:
    * L1 }# Y) |9 a; f3 O, F4 a: G9 a
  7.        return "Chat0.htm": B" b3 T/ l  F% F  k8 b& |
  8.    elif n == 1:
    ( j2 |/ X3 j0 s
  9.        return "Chat1.htm"5 @+ e8 z" s8 x7 N
  10.    elif n >= 4:1 ]. |: u# Q, j3 a/ ~* I. |- E1 q. g
  11.        return "Chat4.htm"7 f$ M) ^2 B8 v# N% Y7 X' t3 Y9 ~
  12.    return "Collected "+str(n)+" of 4 fangs"& J2 \& W7 Y) D3 S" O9 q' t
  13. return
Скопировать код
Метод onKill (а так же метод onTalk) имеет следующие параметры:, F# V; W8 M" h% G: x
* q# _( }' B. U
0 q1 G1 O/ R% q$ d/ c
• self – квест
2 _: D: A) V* a2 M) y1 T• npcId – ID NCP, которого мы должны убивать (если это метод onTalk, то ID того NCP, с которым мы должны поговорить).+ f; N8 F1 k0 D/ a: i/ U( w
• st – текущее состояние игрока.
- ~0 W: i1 g4 S9 V& N8 A. ]+ C% T, R3 K6 ~

7 J2 C8 p% R- N# y3 n2 E+ rВ этом методе мы проверяем и отмечаем, является ли убитый NCP keltir’ом. В основном эта проверка не нужна, т.к. у нас только KELTIR_NPC_ID.2 r! K% l  C% h! z% S* c; w6 z

" ~1 Z- o8 }- \- G6 G1 d; f( c2 b
0 K% Z) t1 \7 Q
Затем проверяем количество предметов (в данном случае количество клыков), и если их вообще нет, то возвращаем строку "Chat0.htm", если только один предмет, то возвращаем строку "Chat1.htm", если же предметов 4 или больше, то "Chat4.htm". Если строка возвращена из методов onEvent, onKill или onTalk, то сервер покажет соответствующие htm. В Chat0.htm может иметь следующий текст: «Вы не имеете ни одного клыка, возвращайтесь позже, когда соберете 4 штуки и бла, бла, бла…», в Chat1.htm может быть следующий текст: «У Вас всего 1 клык, по этому соберите еще…». В Chat4.htm – «Вы собрали необходимое количество предметов, возвращайтесь к вашему тренеру, что бы завершить квест…»
5 _5 O* M: ~& d+ A. s* Y( B( U5 K/ `- d+ v/ v5 @

1 h( q& \8 d% Q+ s+ _Примечание: если в строка return начинается с "<html>", то будет показана страничка html с текстом, который стоит далее. Так вместо:( d+ H8 l; k! z1 h" k7 J% q: B
return "Chat4.htm"$ Y- W# N; n- {, v

6 a& ]3 ?2 a$ E. H5 f3 i
- {9 j+ P5 V- ^5 U  Q  t
можно поставить:
6 j0 \* D7 \4 J
  1. return "<html><body>Return to your trainer to complete the quest</body></html>"
Скопировать код
Так же если строка заканчивается без .htm или в начале нет <html>, то текст будет выведен, как системное сообщение в окне чата. В нашем случае мы сделаем так, что бы при каждом убийстве keltik выводилось системное сообщение: «Собрано N из 4-х клыков».( N$ X# E# w; c
/ Y6 m: Z& N: X' y1 r# V

( b& }$ R1 F- A  I* [& M7 uНаш код для onKill имеет один недостаток. Он будет постоянно показывать Chat0.htm, Chat1.htm и Chat4.htm, нам же необходимо, что бы Chat0.htm и Chat1.htm показывались только один раз. Как нам это сделать? С помощью переменных.
. O0 e3 f; F# |6 j8 {% d# j
8 m9 Q8 u4 B* e6 E7 t9 ?

" ^; L; C; v  e* w4 O( Z$ fВ каждом квесте строки могут храниться с помощью переменных. Эти переменные сохраняются в Вашей БД. В каждом методе мы можем назначить, прочитать и удалить переменные. Давайте изменим метод onKill, так что бы каждый диалог вызывался только один раз./ ?  q0 n/ R! a: q: }! L0 {
  1. def onKill (self,npcId,st):  r5 o9 G0 H- I: o0 R
  2. if npcId == KELTIR_NPC_ID:0 @& ^! s: B4 \" l
  3. n = getCount(st)& r3 ?+ m8 i  i! w" N; U
  4. if n == 0:: R! e. }) R% \3 q( ^( L
  5. if st.get('chat0') == None :7 H; f% P9 M4 t, ~& F0 I( E
  6. st.set("chat0", "true")
    " Q% S* a: p' p- s0 O7 S; r7 b
  7. return "Chat0.htm"
    1 [8 ~, j  S+ D; i: g1 }' f- g
  8. elif n == 1:. _* W9 x" D0 _# G# k4 \' t. [6 _
  9. if st.get('chat1') == None :
    1 R, w% d4 h% X' t* b' [8 N
  10. st.set("chat1", "true")% X( L4 v8 x/ ~! D, x$ L
  11. return "Chat1.htm"& d: w6 U- z, A& e& p8 P
  12. elif n >= 4:4 G' K7 i: w/ {0 O. d6 N9 `
  13. return "Chat4.htm"
    7 X3 |! [1 H- K/ d# ]1 b6 P
  14. return "Collected "+str(n)+" of 4 fangs"
    ) s* U+ G/ b$ U2 A' K5 S
  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.& F4 T+ N3 C/ S% E
* b# j% F2 i- R" y! S- T( H
( f& j% u6 }& ^" P/ A
Вот конечный рабочий вариант квеста:7 r7 {+ H9 I5 }5 f6 \( d& E: _
  1. import sys
    ( S' c% m1 x" w0 [* e- T6 J
  2. from net.sf.l2j.gameserver.model.quest import State
    ; M' G) n$ ]' j/ n: Z  Y
  3. from net.sf.l2j.gameserver.model.quest import QuestState
    6 _. }/ \! O: z, W
  4. from net.sf.l2j.gameserver.model.quest.jython import QuestJython as JQuest- b. ?+ Z% V6 n& |

  5.   }: ]& @8 T2 L$ g! a; ~! X* z
  6. KELTIR_NPC_ID = 12082
    . Y" J  J% S# a: W7 K; {: l! K) ]
  7. FANGS_ITEM_ID = 1859  ~8 l# @' x, S" w# e- d4 ]
  8. DROP_RATE    = 5000001 P- I, L! ~' ^
  9. 9 j/ a" A' i5 f
  10. WORLD_MAP_ITEM_ID = 1665/ P+ ^, v: V8 o% j

  11. ! s+ U  \! a+ J' U* _
  12. def getCount(st) :6 d$ S2 m- o. s8 |7 A- w) Y/ R
  13. return st.getQuestItemsCount(FANGS_ITEM_ID)- D4 g* n% v* r6 e+ @9 @

  14. $ [& t# R4 H8 D5 i
  15. def completed(st) :
    & y. b0 Y& r5 Q; F7 }
  16. st.setState(COMPLETED)
    * O! W+ [+ i" v+ C& \( }1 s0 A
  17. st.clearQuestDrops()" J/ t9 B4 I: N- `; g
  18. st.takeItems(FANGS_ITEM_ID,-1)
    ! m- p6 ]4 `0 C" v2 B; S
  19. st.giveItems(WORLD_MAP_ITEM_ID,1)
    " c" @( \9 w" F
  20. st.exitQuest(False)
    $ K5 T& Q8 ]  h$ K8 R9 v
  21. return
      I* O2 O6 o- C
  22. 1 u% b' F, `" k  a) {1 \) |7 r
  23. def check(st) :! p. V5 Z- M' I# m
  24. if getCount(st) >= 4 :
    1 w! T& `  Y5 b2 H! m
  25. completed(st)
    5 y1 ~) I2 k. s, X9 c- J- h
  26. return
    3 p- r: G+ \6 I$ C7 E( ~0 Y" z: k( y

  27. 0 R& a, K8 R) z' O* ~9 G" ]( T
  28. class Quest (JQuest):! x- ]& J! ]  Z" e- _7 z* f

  29. ! X: q5 M' a1 U# l* o/ C+ P4 `
  30. def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)
    6 L3 ~  L: |" J9 H* U

  31. ) u3 J$ c  C, t4 U/ Y0 _0 {
  32. def onEvent (self,event,st):9 R6 n' v4 u4 P: L1 O# g7 a1 ]. L/ a( f
  33. id = st.getState()8 J0 `  M; F' h2 B( z% B9 h
  34. if id == CREATED : st.setState(STARTED)
    " d0 l0 r  y% y
  35. elif id == COMPLETED: pass7 R2 Q9 g' g) A' R
  36. elif id == STARTED : check(st)
    , V" w! e* I) ~# f) h, a
  37. return
    3 c+ w8 m' f: L7 z' f8 }
  38. ! h* C/ h0 N) z% g$ w( h
  39. def onKill (self,npcId,st):! p& ]" R( \9 ]9 b
  40. if npcId == KELTIR_NPC_ID:3 G5 q. p) }8 E$ Z
  41. n = getCount(st); c9 F+ x0 K) Z8 x# ]/ m$ \
  42. if n == 0:7 @. _; \' v, T; Z0 ^
  43. if st.get('chat0') == None :' ~1 q+ t# L' ?6 K/ R$ ]: v
  44. st.set("chat0", "true")
    ( R9 o3 S8 t- @; ^! v
  45. return "Chat0.htm"
    ! A' ^! J, b4 b; f
  46. elif n == 1:5 [* P5 h. c! a! K- [( r/ M& G
  47. if st.get('chat1') == None :, R$ p0 t3 h3 M5 V
  48. st.set("chat1", "true")
    : k$ V/ y/ F9 Q0 D9 l, E& o! f
  49. return "Chat1.htm"  x3 j; x' d8 }% {$ J' C( K8 D
  50. elif n >= 4:
    # c, o  J2 D: H
  51. return "Chat4.htm"7 J# ^: `; H, l
  52. return "Collect "+str(n)+" of 4 fangs"& n" N+ X) {4 f5 B, u. o% B
  53. return
    , t- Q/ B$ J4 B6 A+ k) ]
  54. + Z$ h+ m8 I' c0 B
  55. QUEST    = Quest(201, "Tutorial", "Tutorial quest"): ~7 }! ]  U# U* D& k% g9 G
  56. CREATED = State('Start',    QUEST)
    9 p7 S* V! A* w5 ^
  57. STARTED = State('Started', QUEST)
    7 J8 m& t$ U/ k5 h6 u0 }5 T
  58. COMPLETED = State('Completed', QUEST)7 A* z  D- D2 N1 ]+ f- J, \8 M
  59. " I$ u. m# y  O, I4 [
  60. QUEST.setInitialState(CREATED)
      a7 y0 b- \2 I
  61. QUEST.addStartNpc(7056). U+ _" p6 q: P7 ^) r- O4 a, A
  62. QUEST.addStartNpc(7012)/ r5 @  U* a& _8 t" n! A
  63. QUEST.addStartNpc(7009)  H5 v$ h9 P" j- @2 Y- G! q
  64. QUEST.addStartNpc(7011)9 S3 u- O" g, K7 [

  65. ' L6 _- f2 |& O: B* k- t6 p2 }) `
  66. STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
    8 s7 i* t! O/ l5 z) m$ ]6 B- g( o
  67. STARTED.addKillId(KELTIR_NPC_ID)/ G/ F: o) T' Q" i% d* ]2 L) f
  68. STARTED.addTalkId(7056)* x" V% o& x. C  t
  69. STARTED.addTalkI d(7012)( F" g; H* O4 e( B: K% b9 ~
  70. STARTED.addTalkId(7009)& k: T) w2 `6 T% q& a- T
  71. STARTED.addTalkId(7011)
Скопировать код
. R7 Z, {+ z9 ?& u" T8 J
/ H; p/ N/ F* Q2 X1 u# X! M2 ^" E4 f
Чтобы ответить, вам надо авторизироваться в системе Вход | Зарегистрироваться

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

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

638638758

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

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

admin@artace.ru Онлайн

QR-код

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