Top.Mail.Ru

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

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

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

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

x
Хроники        Interlude
9 d+ X4 ]6 Q% @: `$ mСборка        L2j4 ]$ W6 o. _, m+ @
Обратите внимание: в файле htm стартового NCP обязательно должна быть ссылка на квест:
( ]7 o; A! I  U" \
  1. STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код
Для этого квеста больше ничего не надо. Все необходимое для корректной работы квеста уже добавили. Вот полный текст квеста:1 v" {  k* O" I6 ]5 T+ X, ~

6 U7 s3 `) f) @# n; R
  1. if getCount(st) >= 4 :, d* }# _. d- }$ Z; ], F; P( [. a
  2. completed(st)
    ' E/ B' |. @* _' V/ \( y
  3.   return
      h/ j8 ^3 `* @* x2 }# P
  4. 7 ?+ y; {$ S) v6 X1 I! g8 b2 a: A
  5. class Quest (JQuest):
    ! q" A# W& \1 E) p$ Y
  6.   def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)5 q% R) R: V! j( q! F# U+ K0 b
  7.   def onEvent (self,event,st):, f2 U4 f4 O% W0 h4 ]% @- V: J8 K
  8. id = st.getState()" _7 H# O% J' L1 m& D% q
  9. if   id == CREATED  : st.setState(STARTED)7 z) x! v6 N; ]+ m
  10. elif id == COMPLETED: pass
    ' H# C* _* k! w2 m  Y8 Q
  11. elif id == STARTED  : check(st)
    0 l5 k+ t  A) g8 y
  12. return
    ! J, ~. E$ F) a6 n8 ?
  13. 8 }& W, ~' C- c# a6 U! g
  14. QUEST     = Quest(201,"Tutorial", "Tutorial quest")
    , |* v/ U6 X2 x5 G
  15. CREATED   = State('Start',     QUEST)
    $ F  D: ]2 S+ u8 Y0 S1 @) f
  16. STARTED   = State('Started',   QUEST)+ q; ~1 G& q1 R
  17. COMPLETED = State('Completed', QUEST)$ Y1 j/ z. o9 ~9 X! e0 S4 _; p
  18. 7 L8 b4 @0 @9 m3 V0 D; A
  19. QUEST.setInitialState(CREATED)
    ; D5 N  w0 q. H5 m
  20. QUEST.addStartNpc(7056)
    + g( I( B: f" i1 {& g
  21. STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код
Теперь рассмотрим, как это работает.
0 Q0 O( {4 h) [3 F* P- R" B- L8 J8 wИгрок подходит к начальному NCP (в данном случае 7056), нажимает на «Quest». Квест будет создан и состояние квеста перейдет к CREATED и игроку будет показана страничка Start.htm с описанием квеста. Тогда метод onEvent, поле открытия странички Start.htm переведет состояние квеста в STARTED и игроку будет показана страничка Started.htm, где будет опсание того, как найти keltirs и .т.д.
5 o: m1 \2 d: B# S3 t
; [* V0 k9 o4 q8 s1 v6 h
% l) y2 R  b8 D. j. q) a; G
При состоянии STARTED будет зарегистрирован дроп «fangs» при убийстве keltirs. Игрок может вернуться к стартовому NCP и спросить о квесте – метод onEvent будет вызван снова. Если у игрока не хватает необходимого количества предметов, то метод check() не переведет квест в следующее состояние и Started.htm будет показана снова. Но если игрок собрал необходимее количество предметов (в данном случае 4 клыка), то метод check() вызовет метод completed() который переведет квест в новое состояние COMPLETED, заберет все клыки, даст карту мира, т.к. это награда за квест, покажет Completed.htm и завершит квест.
0 b: B5 Y9 {, Z) w- S- u5 D' K: w0 J8 D( ?& }
' b- V! \. J1 K3 \' i% @7 T
Теперь давайте сделаем наш квест более похожим на то, что он должен из себя представлять.
' C6 H, v% p  l; ^3 ~Прежде всего у нас есть 3 метода для объявления их в Яве – onTalk, onKill и onEvent. Если методы onTalk и onKill не объявлены, то за них все будет делать метод onEvent, т.е. определять квестовых монстров и вызывать диалоги NCP. Есть примечание, методы onTalk и onKill будут вызывать только диалоги с NCP в зависимости от текущего состояния квеста. Метод onKill будет вызываться только тогда, когда мы убиваем квестового монстра.
8 R! U# B, D* p; P8 r8 n) A
1 Z( q5 t" L9 o3 P

# w6 R- |9 s# d: z8 RДавайте рассмотрим как вызывается метод onKill при убийстве keltir в состоянии квеста STARTED:
, I4 B+ r- H0 T  o
  1. STARTED.addKillId(KELTIR_NPC_ID)
Скопировать код
и метод onKill в классе Quest:. S. o4 M5 l2 @- N
8 Z% p6 N  ?4 r4 x
  1. class Quest (JQuest):
      H1 e* X& w7 K
  2.   ...
    1 z) N# c% H% T2 K( t3 l5 ]# i
  3.   def onKill (self,npcId,st):- X% f8 t. t/ [
  4. if npcId == KELTIR_NPC_ID:1 U8 o4 k# B1 w% E4 T3 x0 }5 {
  5.    n = getCount(st)+ L% L7 I5 t! Z& b
  6.    if   n == 0:
    , h3 ]. P; I; X' u0 F1 i
  7.        return "Chat0.htm") w: ^4 L5 E4 i' {$ ~
  8.    elif n == 1:
    ' j3 [- a; L, D  Q6 c' ^
  9.        return "Chat1.htm"
    : K+ U/ I+ A: g/ ], t
  10.    elif n >= 4:! ]( @" H# J( h5 k! n9 n, `# U
  11.        return "Chat4.htm"
    6 m3 t6 ~. c7 I% \3 o3 e
  12.    return "Collected "+str(n)+" of 4 fangs"; }2 Y! C8 H3 e! I! |
  13. return
Скопировать код
Метод onKill (а так же метод onTalk) имеет следующие параметры:+ U1 M2 M/ Y  z- X) o% \% @$ e

! p, j! V" P' x: T6 Y5 w
' R+ C' }0 k3 N1 m1 T1 Z$ U
• self – квест
5 ^0 y' x) N2 o• npcId – ID NCP, которого мы должны убивать (если это метод onTalk, то ID того NCP, с которым мы должны поговорить).5 q% f; I- @  k* W9 T0 `
• st – текущее состояние игрока.
' {: S  Y0 A: x- ]- u
; z; I' l1 O. J* n+ a
+ D" U' ^- l% W( N% u
В этом методе мы проверяем и отмечаем, является ли убитый NCP keltir’ом. В основном эта проверка не нужна, т.к. у нас только KELTIR_NPC_ID.
( b0 P9 Q) l; {4 C' i4 n6 T% q$ K; p8 X% f" \  U; I( v

* O0 @+ \" q# q4 z/ PЗатем проверяем количество предметов (в данном случае количество клыков), и если их вообще нет, то возвращаем строку "Chat0.htm", если только один предмет, то возвращаем строку "Chat1.htm", если же предметов 4 или больше, то "Chat4.htm". Если строка возвращена из методов onEvent, onKill или onTalk, то сервер покажет соответствующие htm. В Chat0.htm может иметь следующий текст: «Вы не имеете ни одного клыка, возвращайтесь позже, когда соберете 4 штуки и бла, бла, бла…», в Chat1.htm может быть следующий текст: «У Вас всего 1 клык, по этому соберите еще…». В Chat4.htm – «Вы собрали необходимое количество предметов, возвращайтесь к вашему тренеру, что бы завершить квест…»% V/ [6 a/ i% w: w0 Y/ V
5 p$ k" N4 u# q+ S% T2 a( O
- X+ Z; F: E- z+ I  G
Примечание: если в строка return начинается с "<html>", то будет показана страничка html с текстом, который стоит далее. Так вместо:- h  T- t; N7 J/ O' w8 z# U6 ^
return "Chat4.htm"7 G3 }, Y8 j/ q: H

0 A. j6 k0 D+ y. U) m: H0 s
5 x, @( ]% D6 P6 v$ F( P3 ?
можно поставить:
) P! X3 j  X2 [1 a5 n1 l
  1. return "<html><body>Return to your trainer to complete the quest</body></html>"
Скопировать код
Так же если строка заканчивается без .htm или в начале нет <html>, то текст будет выведен, как системное сообщение в окне чата. В нашем случае мы сделаем так, что бы при каждом убийстве keltik выводилось системное сообщение: «Собрано N из 4-х клыков».2 w; q7 G/ B( z3 E* p
$ D0 m$ a% f9 n9 _% ]# t0 D

2 o: E! g: Z: I* b! lНаш код для onKill имеет один недостаток. Он будет постоянно показывать Chat0.htm, Chat1.htm и Chat4.htm, нам же необходимо, что бы Chat0.htm и Chat1.htm показывались только один раз. Как нам это сделать? С помощью переменных.
/ m) U% I" m; q( c+ j  @
3 k$ m( \. u9 D  C. C
8 l2 y& m0 t9 V$ v
В каждом квесте строки могут храниться с помощью переменных. Эти переменные сохраняются в Вашей БД. В каждом методе мы можем назначить, прочитать и удалить переменные. Давайте изменим метод onKill, так что бы каждый диалог вызывался только один раз.( _2 i9 b9 n; B/ J1 A
  1. def onKill (self,npcId,st):  `7 U/ s/ y9 x9 c0 r5 J
  2. if npcId == KELTIR_NPC_ID:+ j3 e# g: T& `0 [. h
  3. n = getCount(st)) b8 Q8 z6 L4 I2 _# T+ g
  4. if n == 0:
    ( u: y5 E+ f" b& T: q
  5. if st.get('chat0') == None :% W  i/ U% t, Z8 M- ]4 W$ G& Y2 U
  6. st.set("chat0", "true")3 b7 u* r5 C6 V6 G" _
  7. return "Chat0.htm"
    . T" H4 H0 w( }( _6 p5 P: l
  8. elif n == 1:
    . J: Q/ v* ]  ?2 W1 ~9 t% `, `
  9. if st.get('chat1') == None :
    ' g# q( M. C- v( X* q5 ?  F+ w+ N
  10. st.set("chat1", "true")
    % B. s8 ^3 y6 y) N5 h- V
  11. return "Chat1.htm"
    ( x! ^, F9 T7 B$ |" h- i. G) N
  12. elif n >= 4:, u  V! ?9 E9 b0 h7 n
  13. return "Chat4.htm"+ A# l. l, w, L( A
  14. return "Collected "+str(n)+" of 4 fangs"* {$ ~6 g: `$ m4 ?  o  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.+ U/ l; _$ l& T  ^8 i4 Q# c: T

9 t2 o/ Y4 g' K' f+ B' j
1 K2 |* u9 y5 r+ ~  V
Вот конечный рабочий вариант квеста:; [; b2 M5 e9 a# C3 B- B2 F
  1. import sys0 a) O+ d$ u* x+ U4 |- I% f
  2. from net.sf.l2j.gameserver.model.quest import State
    0 r9 _' {7 [0 ^7 F6 i! \- J
  3. from net.sf.l2j.gameserver.model.quest import QuestState3 n* Q7 L& Y+ H- A' y# E
  4. from net.sf.l2j.gameserver.model.quest.jython import QuestJython as JQuest; H/ x; k  r  z. h: |- H
  5. ; k( u( d5 d$ F  n, h8 F" Y
  6. KELTIR_NPC_ID = 12082
    9 a3 i, z- t+ u% V6 V- ^) R+ V" i
  7. FANGS_ITEM_ID = 1859( E8 A; _- N: v) v
  8. DROP_RATE    = 500000  l$ Y* S, b) T0 E2 `% G  m
  9. 6 q9 V0 V' B' b4 A" ~0 U! r6 N0 T
  10. WORLD_MAP_ITEM_ID = 1665
    1 U9 Y* I6 g, P0 I8 r
  11. * C0 S( O$ z4 m) b
  12. def getCount(st) :, b, r. J, g& X9 q& j+ y
  13. return st.getQuestItemsCount(FANGS_ITEM_ID)
    " v- y& {8 i0 E
  14. 3 g! y1 r! B1 Y5 x" S# s
  15. def completed(st) :
    + I3 k' g3 v, C/ j
  16. st.setState(COMPLETED)
    ; U) R! T& R  {$ [6 [
  17. st.clearQuestDrops()
    % n) V; M& Z' E) Y) J  e
  18. st.takeItems(FANGS_ITEM_ID,-1)
    8 A* Z& v  T* r3 d: O- @+ d
  19. st.giveItems(WORLD_MAP_ITEM_ID,1)
    % H6 e' H' v7 s/ D, @" f# ^
  20. st.exitQuest(False); f3 R" }3 V* N# O6 i) o
  21. return
    + P: Y4 d3 ~( K) O

  22. 0 e; T7 b5 g0 M( X& g: z6 i( T& b
  23. def check(st) :
    3 [2 X. |6 A$ ]7 x# X# ]
  24. if getCount(st) >= 4 :. \+ N% N! Q0 ^
  25. completed(st)
      o" g0 k9 c& R
  26. return
    3 H3 |5 o6 x/ F! i. E8 q1 [

  27. 3 O3 [% k+ U) W$ d
  28. class Quest (JQuest):
    & n! j  W( Z& r" u  e1 U( B

  29. 3 M3 l' p  {4 E- M1 B) y1 t, d6 S
  30. def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)
    7 l; v4 H" ~! T5 r/ a; p
  31. . c, b/ P4 W0 o% r( z! i! R
  32. def onEvent (self,event,st):" T1 I' [7 T5 J" u& J( x
  33. id = st.getState()/ t9 P9 x" J5 O
  34. if id == CREATED : st.setState(STARTED)) Q1 ?- T. M+ g) g3 w
  35. elif id == COMPLETED: pass' O8 b* Y6 q% A# H! X9 t" {9 o
  36. elif id == STARTED : check(st)1 p2 P' k0 o2 l3 Q  f, H  K* N9 I: u
  37. return
    ! ~! s# b( m$ ?3 G; Z' F& C: G
  38. + |5 h7 D2 @8 d5 ^3 p
  39. def onKill (self,npcId,st):% L8 X& w  Z+ E1 M8 G
  40. if npcId == KELTIR_NPC_ID:
    2 w, S" w/ E/ D1 z5 o, T
  41. n = getCount(st)+ N; W. w0 u) E6 G; |
  42. if n == 0:1 j. P% B) z* s$ o; a) g) S! B" @
  43. if st.get('chat0') == None :1 Y0 L0 J) |4 \% }9 c/ B6 ?' ]' a
  44. st.set("chat0", "true")
    # w4 y0 o* t1 u6 B- \$ d' O
  45. return "Chat0.htm"
    $ K& ~8 e4 H6 K* [
  46. elif n == 1:* h5 \$ R. F+ _$ w7 z2 c
  47. if st.get('chat1') == None :& C& ]. Q  W0 h, l1 Q
  48. st.set("chat1", "true"): t$ L" D  g* v+ y* Y: O: ?4 y
  49. return "Chat1.htm"
    % v$ c# \. m2 q: i5 O4 V9 Z2 ~5 w
  50. elif n >= 4:
    , S- _5 }# j) T. v6 e8 o
  51. return "Chat4.htm"
    # s( @/ U2 M$ ~: F, H3 h
  52. return "Collect "+str(n)+" of 4 fangs"
    " M( [2 P- i# ~) q  v; x" }
  53. return; q7 r4 P5 G% m

  54. ! h  v4 d- c& c  g7 q/ H' [
  55. QUEST    = Quest(201, "Tutorial", "Tutorial quest")
    * p3 e. N5 i5 {/ z$ m! p% ?
  56. CREATED = State('Start',    QUEST), r( ?( Y5 W1 d7 d
  57. STARTED = State('Started', QUEST)5 w/ g% y' H' {3 f& U
  58. COMPLETED = State('Completed', QUEST)
    . z0 `- X! l5 G( ?

  59. * t& D( B+ [+ E" ?+ S
  60. QUEST.setInitialState(CREATED)/ L1 o2 T! Z& w* i
  61. QUEST.addStartNpc(7056)
    0 @) n" C: Y# A$ n* E; j
  62. QUEST.addStartNpc(7012)& f; A$ p+ k0 ^( F. Y
  63. QUEST.addStartNpc(7009)/ u) c. i% W5 E: H  x8 J
  64. QUEST.addStartNpc(7011)" L9 R$ C& s3 v1 n' M+ n

  65. % l. }! M4 Z& N$ V: g5 V/ P
  66. STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)6 C- i, I' T, E# o( B
  67. STARTED.addKillId(KELTIR_NPC_ID)9 ]' K/ K1 B0 u8 V
  68. STARTED.addTalkId(7056)
    % o2 c' t8 ]: \
  69. STARTED.addTalkI d(7012)
      f* U+ {1 |  D% C
  70. STARTED.addTalkId(7009)
    ' k6 Y% N$ i/ T) \  v7 n
  71. STARTED.addTalkId(7011)
Скопировать код

. U$ F. [1 q, o7 F4 ]/ h* \1 V' G/ y. j2 F& z6 P# ^/ [
Чтобы ответить, вам надо авторизироваться в системе Вход | Зарегистрироваться

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

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

638638758

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

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

admin@artace.ru Онлайн

QR-код

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