Top.Mail.Ru

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

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

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

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

x
Хроники        Interlude
. ~1 @2 E3 ^4 mСборка        L2j
9 d; Z! G: v$ IОбратите внимание: в файле htm стартового NCP обязательно должна быть ссылка на квест:- e( ?$ ]7 o% K- G
  1. STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код
Для этого квеста больше ничего не надо. Все необходимое для корректной работы квеста уже добавили. Вот полный текст квеста:
8 T! w3 U" Z/ I4 E0 @: l( x
9 i/ x" h/ \+ Z8 _4 `
  1. if getCount(st) >= 4 :
    : l* p& e7 x4 z5 W& u8 F
  2. completed(st)' k2 j4 v0 M' l8 j8 b; b* s1 e- J5 E
  3.   return1 T8 L- W0 ~3 @! t% W0 z
  4. 6 e6 m0 ?7 J$ O2 m: ^0 J
  5. class Quest (JQuest):
    1 E2 T) h7 G+ \
  6.   def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)- b. m( u3 }4 y' f' C: h" e
  7.   def onEvent (self,event,st):
    6 [+ C1 @. _: Y1 F, y, T: W
  8. id = st.getState()$ s7 U' Z8 n) k! f/ h$ r
  9. if   id == CREATED  : st.setState(STARTED)$ n- a2 c4 ]2 F; w2 d) Q
  10. elif id == COMPLETED: pass
    7 t! f6 r! B6 Y
  11. elif id == STARTED  : check(st)! P. q! j; D4 G, l/ c; V2 G' q# W( d
  12. return
    7 S' |! j2 C$ `7 T/ n+ t  r
  13. . F4 h) o6 e% l  ~" a
  14. QUEST     = Quest(201,"Tutorial", "Tutorial quest")
    # h6 U2 x/ l) f6 k! C3 g0 x
  15. CREATED   = State('Start',     QUEST)
    & [) e1 e' f0 U9 ^; M2 h
  16. STARTED   = State('Started',   QUEST)) a/ `. S$ J8 {! Z8 g, I7 l
  17. COMPLETED = State('Completed', QUEST)
    0 v) J+ Y1 I, [& H, [8 Z# @
  18. 9 L4 W5 I; B4 z7 v
  19. QUEST.setInitialState(CREATED)0 X" U: X3 ^: ]; \
  20. QUEST.addStartNpc(7056). h4 t8 r9 t. Q% I
  21. STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код
Теперь рассмотрим, как это работает.
/ L6 }4 [$ G) `( }Игрок подходит к начальному NCP (в данном случае 7056), нажимает на «Quest». Квест будет создан и состояние квеста перейдет к CREATED и игроку будет показана страничка Start.htm с описанием квеста. Тогда метод onEvent, поле открытия странички Start.htm переведет состояние квеста в STARTED и игроку будет показана страничка Started.htm, где будет опсание того, как найти keltirs и .т.д.0 I* F5 @9 h/ ~( Z

# M) q& `: p* a3 I1 _  e8 N1 s9 C5 X
) \. E: u: f9 A
При состоянии STARTED будет зарегистрирован дроп «fangs» при убийстве keltirs. Игрок может вернуться к стартовому NCP и спросить о квесте – метод onEvent будет вызван снова. Если у игрока не хватает необходимого количества предметов, то метод check() не переведет квест в следующее состояние и Started.htm будет показана снова. Но если игрок собрал необходимее количество предметов (в данном случае 4 клыка), то метод check() вызовет метод completed() который переведет квест в новое состояние COMPLETED, заберет все клыки, даст карту мира, т.к. это награда за квест, покажет Completed.htm и завершит квест.
( w2 R3 [# W& X2 w% S6 |# q: @& e1 M; h& f1 n  H
! O- G/ t" e, F
Теперь давайте сделаем наш квест более похожим на то, что он должен из себя представлять.
7 A' ?  o% z1 b; F2 l) V( R$ zПрежде всего у нас есть 3 метода для объявления их в Яве – onTalk, onKill и onEvent. Если методы onTalk и onKill не объявлены, то за них все будет делать метод onEvent, т.е. определять квестовых монстров и вызывать диалоги NCP. Есть примечание, методы onTalk и onKill будут вызывать только диалоги с NCP в зависимости от текущего состояния квеста. Метод onKill будет вызываться только тогда, когда мы убиваем квестового монстра.
" T: q0 r% o% b! W" e# j- C+ C& l; K/ T) E
  W. c* y- L! l6 z
Давайте рассмотрим как вызывается метод onKill при убийстве keltir в состоянии квеста STARTED:* ^+ j9 O: p: P$ I* _) V% N: u
  1. STARTED.addKillId(KELTIR_NPC_ID)
Скопировать код
и метод onKill в классе Quest:4 W1 n7 O  h7 H! W

! T8 b, J1 ?" G: Q7 D3 B8 o
  1. class Quest (JQuest):
    # L% p: l' o8 f8 d/ ?
  2.   ...
    " l3 b' |) k( ^  B: \$ B: |5 G
  3.   def onKill (self,npcId,st):8 ?4 A! m( }# w4 [, _
  4. if npcId == KELTIR_NPC_ID:# Z6 Z  e+ u( y# h
  5.    n = getCount(st)
    2 o$ R  l1 z$ e( e9 @( m' o
  6.    if   n == 0:3 U6 d/ U/ }5 W; u
  7.        return "Chat0.htm"
    # H6 W& ]/ L, N: h: G3 i. Y
  8.    elif n == 1:3 D0 k7 }7 v- x6 T8 k" v
  9.        return "Chat1.htm"
    & ^4 v3 V4 J: _% R9 ^; `/ d7 M0 [$ w
  10.    elif n >= 4:. D9 E& [& E: `2 t; o9 h4 Z
  11.        return "Chat4.htm"* @, y( K2 @8 R% p5 ~
  12.    return "Collected "+str(n)+" of 4 fangs"
    8 Y' n  k) I& ]2 ?: A* M
  13. return
Скопировать код
Метод onKill (а так же метод onTalk) имеет следующие параметры:& z/ b: c6 y9 Q& v/ i# d3 L# o

2 d/ \! A* o8 M# W4 w8 `

' ^; V; p3 r3 n0 S, T3 b• self – квест4 h7 B% H: K. b8 ]4 O1 z
• npcId – ID NCP, которого мы должны убивать (если это метод onTalk, то ID того NCP, с которым мы должны поговорить).7 f0 |8 `1 p- A) T1 I
• st – текущее состояние игрока.
$ O- r6 a, j$ ~& q$ Q' Q- ?2 q: \; `, E5 v: I* [

2 O* W: i3 Z  F0 tВ этом методе мы проверяем и отмечаем, является ли убитый NCP keltir’ом. В основном эта проверка не нужна, т.к. у нас только KELTIR_NPC_ID.
8 H  a0 Q6 B7 K# E4 e
% j% [" O, l4 T9 [& V; C
2 l+ ]; }/ E  D7 s9 |
Затем проверяем количество предметов (в данном случае количество клыков), и если их вообще нет, то возвращаем строку "Chat0.htm", если только один предмет, то возвращаем строку "Chat1.htm", если же предметов 4 или больше, то "Chat4.htm". Если строка возвращена из методов onEvent, onKill или onTalk, то сервер покажет соответствующие htm. В Chat0.htm может иметь следующий текст: «Вы не имеете ни одного клыка, возвращайтесь позже, когда соберете 4 штуки и бла, бла, бла…», в Chat1.htm может быть следующий текст: «У Вас всего 1 клык, по этому соберите еще…». В Chat4.htm – «Вы собрали необходимое количество предметов, возвращайтесь к вашему тренеру, что бы завершить квест…»# X2 O: A- }2 W9 v7 [

6 m5 C$ w2 u. H

( v  p# l$ g& l7 ?Примечание: если в строка return начинается с "<html>", то будет показана страничка html с текстом, который стоит далее. Так вместо:1 q0 A7 F( ~3 E( M$ p3 N
return "Chat4.htm"
) _, B" t& }9 I7 M7 Z$ i6 C9 i5 v" p( z$ L  N
0 M: I+ o# p) u2 d5 Q- L* ?
можно поставить:' w, i' v7 J/ k- x0 M$ {
  1. return "<html><body>Return to your trainer to complete the quest</body></html>"
Скопировать код
Так же если строка заканчивается без .htm или в начале нет <html>, то текст будет выведен, как системное сообщение в окне чата. В нашем случае мы сделаем так, что бы при каждом убийстве keltik выводилось системное сообщение: «Собрано N из 4-х клыков».; z  j+ Z& v1 }8 R  ]/ [: f
6 |- y  y% E% ]1 u1 O  q
4 m1 I" q0 s9 |' D" \. U
Наш код для onKill имеет один недостаток. Он будет постоянно показывать Chat0.htm, Chat1.htm и Chat4.htm, нам же необходимо, что бы Chat0.htm и Chat1.htm показывались только один раз. Как нам это сделать? С помощью переменных.
/ m- z6 L- Y3 V3 u  _9 \( V% S8 |2 {' o7 Q  n- r* H; [

6 ~9 P/ s% J1 t, L0 h) AВ каждом квесте строки могут храниться с помощью переменных. Эти переменные сохраняются в Вашей БД. В каждом методе мы можем назначить, прочитать и удалить переменные. Давайте изменим метод onKill, так что бы каждый диалог вызывался только один раз.
+ {  ^/ b- B8 P6 y0 h
  1. def onKill (self,npcId,st):
    $ ~. b. v& o. g/ j
  2. if npcId == KELTIR_NPC_ID:
    ( N' e; A0 K: J  o
  3. n = getCount(st)
    - ]1 [. d5 X4 @, O+ a+ R
  4. if n == 0:
    + R5 f8 m/ P, P  C
  5. if st.get('chat0') == None :
    ) [! ]0 ]. q( T1 @* D) M
  6. st.set("chat0", "true")& _9 Z8 W- n9 a) P) c6 c
  7. return "Chat0.htm"
    + e/ k7 C4 ^8 k
  8. elif n == 1:
    9 y' \$ B9 `5 ]& M) c/ b! |& }
  9. if st.get('chat1') == None :4 l4 v% m1 A  X8 B) ~2 L" v
  10. st.set("chat1", "true")
    & `. B) d  p, C- U/ S! l
  11. return "Chat1.htm"
    ( s- i( _) f; _2 T
  12. elif n >= 4:5 ^" Z. E' I+ X3 E
  13. return "Chat4.htm", @- M5 V9 r. G, l; d" Y. ?
  14. return "Collected "+str(n)+" of 4 fangs"
    ) Y( N! `! B8 Z/ I+ Z0 v- }( t
  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.) v5 F+ O7 r1 [0 D# P
0 f) V1 c+ V" f8 P+ O

4 C5 s0 o5 \+ x) j0 GВот конечный рабочий вариант квеста:
1 J* ^5 t& B8 H: _# ~# D1 V
  1. import sys
      s9 h2 r- d& N. h( m4 g% {# f
  2. from net.sf.l2j.gameserver.model.quest import State
    # k1 e7 \2 Z# w) M. b9 t% v, P
  3. from net.sf.l2j.gameserver.model.quest import QuestState& O  i4 Y2 R: i3 F
  4. from net.sf.l2j.gameserver.model.quest.jython import QuestJython as JQuest" x) [% _  o8 A2 D' n
  5. ; V' J- s7 L( z! B$ L6 l
  6. KELTIR_NPC_ID = 12082
    5 K7 H0 r/ ~% [3 ]% t7 a9 g
  7. FANGS_ITEM_ID = 1859
      `) g2 U7 k  Y% l; `
  8. DROP_RATE    = 5000009 q+ P1 ?  Q0 A1 X9 M
  9. 0 s" Q9 ]& t" ~7 x* x' D
  10. WORLD_MAP_ITEM_ID = 1665
    0 o3 B! K5 s7 P$ [
  11. , y5 t' R/ P. a( m# d6 D, n
  12. def getCount(st) :
    % N) _, o' H) E+ U% T, i
  13. return st.getQuestItemsCount(FANGS_ITEM_ID)6 i4 ^2 F, v- `( f9 p, R% Y0 l
  14. ) Q* Y1 M- D) m8 D5 Q4 F' C- U
  15. def completed(st) :. _6 b; y+ k. d( p$ o1 ~
  16. st.setState(COMPLETED)( w" m  a6 D) p: r$ `0 t
  17. st.clearQuestDrops()
    * H7 f$ L2 C0 |/ K# u0 l5 ~6 ]8 u$ @
  18. st.takeItems(FANGS_ITEM_ID,-1)
    ! j' P% G- y6 S0 F* f3 ?- J. s2 e
  19. st.giveItems(WORLD_MAP_ITEM_ID,1)
    1 T% W/ @9 p* p9 }1 W* z3 G
  20. st.exitQuest(False): ~8 y( b+ @( O1 ~" a: _+ B
  21. return( `  I2 \2 D4 ]- I: B% z7 _* I
  22. ! L; O; s7 W9 V* l; E2 h" H4 [
  23. def check(st) :" v2 }, E, g, ^( v: p7 G/ L% W
  24. if getCount(st) >= 4 :7 C$ k9 h; q5 ~3 c" ]: m" K
  25. completed(st)- e: T6 z7 A& H& L& d
  26. return
    0 y3 I. B% Z9 E$ p, x6 D
  27.   o6 O. N. E' ?- ~* w! i% ?* w
  28. class Quest (JQuest):
    / |8 k+ }+ e. ~3 M: {* j0 u0 `
  29. # T- L' f3 M1 i& W+ d
  30. def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)# x9 {; k; s0 M' q9 |
  31. & c# S! ]' {% F( _$ X
  32. def onEvent (self,event,st):
    4 D+ Q# w% d! K$ Z- x9 ^% Z9 A
  33. id = st.getState()
    - G, T1 J2 f! W6 b! n
  34. if id == CREATED : st.setState(STARTED)
    1 s# {2 t5 e" Z" c+ n" P1 H
  35. elif id == COMPLETED: pass
    6 M) Y1 N% j1 Q
  36. elif id == STARTED : check(st)7 K& P: _0 g7 D" I( [# Y( w
  37. return
    - r1 ~; `+ P0 n: X: X. B8 R
  38. ! M4 F! ^0 q+ Z, W! M) I0 ~1 {
  39. def onKill (self,npcId,st):
    $ p) }) {* T4 u' `; S
  40. if npcId == KELTIR_NPC_ID:
    " C5 W# U/ h$ T: s
  41. n = getCount(st)
    & Y9 _3 C$ W3 w+ {& k& g
  42. if n == 0:
    ; R1 d% X. G: U. X- ]5 t8 L5 J
  43. if st.get('chat0') == None :5 ?# F. p/ \5 y5 r( {; F
  44. st.set("chat0", "true")
    7 o- q0 Y3 T1 l. O
  45. return "Chat0.htm"
    + o! A7 y/ Z  b+ e: D
  46. elif n == 1:  k9 e; [+ X1 _5 E4 N2 I% W
  47. if st.get('chat1') == None :
    9 }+ ~/ a0 k  b  q* H- j
  48. st.set("chat1", "true")) f1 S, r; G2 R
  49. return "Chat1.htm"8 O/ ~6 M: u* U% G2 k1 `7 C6 f- F
  50. elif n >= 4:4 Z( @2 x- y5 r, c9 K% B
  51. return "Chat4.htm"  q' N+ Q, h9 v5 A% {& c
  52. return "Collect "+str(n)+" of 4 fangs"( g# w: q3 Q% t& I
  53. return
    : n. ^* E# O$ _9 Q% n

  54. . a, S; Y3 [7 N2 j! g7 v" Q
  55. QUEST    = Quest(201, "Tutorial", "Tutorial quest")) Q$ m, w4 ~* f' B3 x- v
  56. CREATED = State('Start',    QUEST)
    4 c& E1 c* T) ?& \3 o
  57. STARTED = State('Started', QUEST)
    6 d4 g- J  g( n9 i8 T1 ^+ `
  58. COMPLETED = State('Completed', QUEST)
    ; W5 X$ K% f& J& w& z' \
  59. ' d0 B5 g9 w3 X* H
  60. QUEST.setInitialState(CREATED)
    5 i0 Z) @* a% ~
  61. QUEST.addStartNpc(7056)) `1 z0 C% B: y; M" u
  62. QUEST.addStartNpc(7012)$ u' M$ Q; H- Z9 P7 ^+ e. R' I, Z
  63. QUEST.addStartNpc(7009)
    ! T# q% l' v/ o& J7 g8 ?* v, ]
  64. QUEST.addStartNpc(7011)
    1 F2 j+ \; P/ d, l# d
  65. 4 B9 I; \4 o+ T& _
  66. STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
    4 o8 H1 P2 o' z, l/ I% b' l
  67. STARTED.addKillId(KELTIR_NPC_ID)
    ; ?6 r8 P" a+ }" _1 q+ h% e% I
  68. STARTED.addTalkId(7056)
    ' N: l3 p# t  U/ K9 s
  69. STARTED.addTalkI d(7012)
    ) I* w+ [: w+ Q/ Q
  70. STARTED.addTalkId(7009)# J  Z$ v# h' u" I- F3 v
  71. STARTED.addTalkId(7011)
Скопировать код

: |: |% i1 A# g" t- x1 y/ }# P6 \% s% _7 X
Чтобы ответить, вам надо авторизироваться в системе Вход | Зарегистрироваться

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

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

638638758

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

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

admin@artace.ru Онлайн

QR-код

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