Top.Mail.Ru

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

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

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

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

x
Хроники        Interlude! n0 Y9 {6 }1 O9 e4 a" [  I+ p, \
Сборка        L2j. V( F! u2 s$ n- O
Обратите внимание: в файле htm стартового NCP обязательно должна быть ссылка на квест:) q3 A  I. B5 @; Z+ i0 p$ i
  1. STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код
Для этого квеста больше ничего не надо. Все необходимое для корректной работы квеста уже добавили. Вот полный текст квеста:8 ]; f) p8 \- \; r. Y0 N' ~! I

0 }$ q) N% H# W# Q7 l
  1. if getCount(st) >= 4 :
    5 q( ~: D  B6 C" Q- {' h# w
  2. completed(st), H) ?9 H0 h& Q  t& Z! l
  3.   return& j9 q% H$ l% p# }$ C
  4. 1 l' C3 n9 B' t- ]! M
  5. class Quest (JQuest):
    , Q' |& w$ {/ B" R; a0 c
  6.   def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)
    9 c+ u+ M- n: G. |6 ^; b3 H6 c
  7.   def onEvent (self,event,st):1 U/ C0 M) N2 M7 N* _  }. E
  8. id = st.getState()9 P" l; Y1 ]- r/ |
  9. if   id == CREATED  : st.setState(STARTED)& L8 }7 K* M' u$ r- t2 c
  10. elif id == COMPLETED: pass
    2 Y+ F1 S6 g: q. v) R2 v4 {
  11. elif id == STARTED  : check(st)
    0 w0 _. S  y3 g( z, k  k1 d
  12. return
    0 [! ?( c7 s: P* R
  13. ) m* V2 j- {% Q6 l- m! E) G
  14. QUEST     = Quest(201,"Tutorial", "Tutorial quest"); T) \; D) X: a( m
  15. CREATED   = State('Start',     QUEST)
    & {: A2 L. s, N1 d' S
  16. STARTED   = State('Started',   QUEST)
    ) o2 s5 X% t8 R8 h9 R) Y+ b' ~
  17. COMPLETED = State('Completed', QUEST)) U8 ~( ^+ M' h

  18. 8 U' [# t; y. E8 o
  19. QUEST.setInitialState(CREATED)9 t* K& h! e% m
  20. QUEST.addStartNpc(7056)
    7 B4 }$ W2 Z1 [" r% ^; I6 m) [
  21. STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код
Теперь рассмотрим, как это работает.
- b: c$ j# z: \6 Q  V3 tИгрок подходит к начальному NCP (в данном случае 7056), нажимает на «Quest». Квест будет создан и состояние квеста перейдет к CREATED и игроку будет показана страничка Start.htm с описанием квеста. Тогда метод onEvent, поле открытия странички Start.htm переведет состояние квеста в STARTED и игроку будет показана страничка Started.htm, где будет опсание того, как найти keltirs и .т.д.* k% D4 E0 Y8 ^" q
1 N( T! U$ H  R9 H0 y
! e6 {* G) B5 |  w) ^3 q7 z
При состоянии STARTED будет зарегистрирован дроп «fangs» при убийстве keltirs. Игрок может вернуться к стартовому NCP и спросить о квесте – метод onEvent будет вызван снова. Если у игрока не хватает необходимого количества предметов, то метод check() не переведет квест в следующее состояние и Started.htm будет показана снова. Но если игрок собрал необходимее количество предметов (в данном случае 4 клыка), то метод check() вызовет метод completed() который переведет квест в новое состояние COMPLETED, заберет все клыки, даст карту мира, т.к. это награда за квест, покажет Completed.htm и завершит квест.6 `1 o  l# G9 S7 B$ Q

, h7 v: K$ u4 Z  e$ y. x5 B

7 I6 K5 T+ g, n: P/ @) b. W2 SТеперь давайте сделаем наш квест более похожим на то, что он должен из себя представлять.. S7 f4 V5 @6 k* X& X
Прежде всего у нас есть 3 метода для объявления их в Яве – onTalk, onKill и onEvent. Если методы onTalk и onKill не объявлены, то за них все будет делать метод onEvent, т.е. определять квестовых монстров и вызывать диалоги NCP. Есть примечание, методы onTalk и onKill будут вызывать только диалоги с NCP в зависимости от текущего состояния квеста. Метод onKill будет вызываться только тогда, когда мы убиваем квестового монстра.
+ p( ?! ^+ ~- j/ e& R1 p$ s6 `: ^# P" j8 u" H: |! x
5 o) Y* T. f. z# w
Давайте рассмотрим как вызывается метод onKill при убийстве keltir в состоянии квеста STARTED:' [; |+ Z- R9 v
  1. STARTED.addKillId(KELTIR_NPC_ID)
Скопировать код
и метод onKill в классе Quest:
0 m' W% v, o9 Y5 a& r0 K/ T  j! A* r  d
  1. class Quest (JQuest):. W; e; I  Y- J) v" [) U, [" x) W
  2.   ...
    ( I- {" v' r3 c: w+ D5 w* G
  3.   def onKill (self,npcId,st):
    ( y# ^7 o6 ^8 K# Z5 _3 Z
  4. if npcId == KELTIR_NPC_ID:" T& l( p& S: J& q$ g6 P
  5.    n = getCount(st)
    ; D7 L4 m+ s0 L
  6.    if   n == 0:2 ~) t* G  Q& d$ q7 f; |, _+ \
  7.        return "Chat0.htm"
    " c% n' M6 n+ x2 H
  8.    elif n == 1:2 n* `. h' J( u
  9.        return "Chat1.htm"" [1 A7 D1 D5 k3 M
  10.    elif n >= 4:
    1 ?7 U* e' u& q9 S( @+ N
  11.        return "Chat4.htm"5 r2 E$ r9 P7 \; x
  12.    return "Collected "+str(n)+" of 4 fangs"( K1 W+ `( {, e) ^3 m6 S
  13. return
Скопировать код
Метод onKill (а так же метод onTalk) имеет следующие параметры:
: ~- t5 g& l; y- f
. X0 G) X4 u' ^9 A6 z% y) n
3 B% {4 B* m0 S0 i& l( k- `% j& Y
• self – квест
6 x* E4 u7 c; I7 Q• npcId – ID NCP, которого мы должны убивать (если это метод onTalk, то ID того NCP, с которым мы должны поговорить).
" c+ X- b/ `& x• st – текущее состояние игрока.
  @4 c( t$ K% o) ~( ?  f2 _
) B- r8 s5 X! ]

" J$ [8 u* G4 I; D# q5 b$ GВ этом методе мы проверяем и отмечаем, является ли убитый NCP keltir’ом. В основном эта проверка не нужна, т.к. у нас только KELTIR_NPC_ID.4 Z5 @& R& k7 n
2 C) s+ _5 @% z: o6 N1 D6 ?

7 r9 K) {9 U" aЗатем проверяем количество предметов (в данном случае количество клыков), и если их вообще нет, то возвращаем строку "Chat0.htm", если только один предмет, то возвращаем строку "Chat1.htm", если же предметов 4 или больше, то "Chat4.htm". Если строка возвращена из методов onEvent, onKill или onTalk, то сервер покажет соответствующие htm. В Chat0.htm может иметь следующий текст: «Вы не имеете ни одного клыка, возвращайтесь позже, когда соберете 4 штуки и бла, бла, бла…», в Chat1.htm может быть следующий текст: «У Вас всего 1 клык, по этому соберите еще…». В Chat4.htm – «Вы собрали необходимое количество предметов, возвращайтесь к вашему тренеру, что бы завершить квест…»# O, `, f/ M& J7 W1 P0 R( h/ Y% Z
6 H; s6 ?6 r" J# r* ]- `+ \
  o, a8 j' S* O8 ^; u6 L
Примечание: если в строка return начинается с "<html>", то будет показана страничка html с текстом, который стоит далее. Так вместо:8 c7 Q! J% p" w7 e8 l+ J7 A+ k
return "Chat4.htm"
. j0 X3 ]( f# @6 f3 Y: z+ t) u( v" o/ |9 {: [

: D/ E4 J) O! T' w( U* Pможно поставить:
7 o4 |+ L7 h' Q
  1. return "<html><body>Return to your trainer to complete the quest</body></html>"
Скопировать код
Так же если строка заканчивается без .htm или в начале нет <html>, то текст будет выведен, как системное сообщение в окне чата. В нашем случае мы сделаем так, что бы при каждом убийстве keltik выводилось системное сообщение: «Собрано N из 4-х клыков».
( n5 {- H1 f1 g; V5 \( G  p, h  t) V; R' v; d

0 w* G& }4 z1 t! R  g! r% ]/ |Наш код для onKill имеет один недостаток. Он будет постоянно показывать Chat0.htm, Chat1.htm и Chat4.htm, нам же необходимо, что бы Chat0.htm и Chat1.htm показывались только один раз. Как нам это сделать? С помощью переменных.
) c1 \, [( D& d& }( h! l
! c4 {: x1 p; N5 K9 H  P
$ z1 e6 R$ [/ g0 d7 |8 E8 N
В каждом квесте строки могут храниться с помощью переменных. Эти переменные сохраняются в Вашей БД. В каждом методе мы можем назначить, прочитать и удалить переменные. Давайте изменим метод onKill, так что бы каждый диалог вызывался только один раз.+ @& m( G& L" _. m: ^6 M+ O
  1. def onKill (self,npcId,st):9 s- z% L* S! Q8 z
  2. if npcId == KELTIR_NPC_ID:& J* E( k9 m- N3 ?
  3. n = getCount(st)
    5 E, E  q, m7 `6 r- d
  4. if n == 0:
    / d, n1 _# F5 f' [. x/ p: E
  5. if st.get('chat0') == None :' n8 V9 A! g- N
  6. st.set("chat0", "true")
    & n) R; J. q/ E* h
  7. return "Chat0.htm"- c. @/ v& k- ^4 C. |
  8. elif n == 1:0 w9 i# Q6 ^% N4 S; n" x2 a* @
  9. if st.get('chat1') == None :# h- W, t: p% U& A: z- E2 b
  10. st.set("chat1", "true")4 p9 c' q8 P# o6 N
  11. return "Chat1.htm": t. k' ^& t. l1 B; N
  12. elif n >= 4:
    # c0 {& ]/ y" I9 l! ^( L: y
  13. return "Chat4.htm"
      Y& I6 q7 f. e0 k8 {0 |( L
  14. return "Collected "+str(n)+" of 4 fangs"
    + I& P" ^6 R9 l1 K. 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.
2 U% o' a; K$ J3 v; w1 ~, i- }& l' t1 e. e# n
4 }* v# p5 l5 Y$ g% K' K) [
Вот конечный рабочий вариант квеста:
2 t- I5 P1 n! [' A+ {8 g5 p5 ^
  1. import sys
    9 C* X/ A- y8 B3 ?, p
  2. from net.sf.l2j.gameserver.model.quest import State3 J5 D0 ^) G5 ]5 s( ~. }. ^, l; G
  3. from net.sf.l2j.gameserver.model.quest import QuestState6 h& n7 s4 [. g' V7 H( l/ e& ^
  4. from net.sf.l2j.gameserver.model.quest.jython import QuestJython as JQuest
      n/ v# W# X: Q* }* \2 K

  5. * `- l0 Q  d1 Q" c) e! m6 j, \
  6. KELTIR_NPC_ID = 12082
    . s0 t$ S' ]8 s, L9 r
  7. FANGS_ITEM_ID = 18599 p7 C7 o( q6 {* S6 Y
  8. DROP_RATE    = 5000003 ~# A% S0 d$ x0 D" x/ q7 m
  9. , Q/ x2 r  [; G1 X3 z
  10. WORLD_MAP_ITEM_ID = 16655 ]7 h5 I. D4 n) h3 r; M7 G

  11. 3 [% b9 H) s( |: L1 |+ q
  12. def getCount(st) :' S( a, ?2 a3 I/ D
  13. return st.getQuestItemsCount(FANGS_ITEM_ID)
    3 w7 V, P* S% o
  14. : F3 ]2 l  w4 s5 Y" x
  15. def completed(st) :
    ! W/ X) a1 B4 ]
  16. st.setState(COMPLETED)0 A9 r* [1 k1 ~6 A
  17. st.clearQuestDrops(). p6 g+ @, y6 C) C5 c
  18. st.takeItems(FANGS_ITEM_ID,-1)$ l. Z9 k$ }7 O3 l! l( R- E
  19. st.giveItems(WORLD_MAP_ITEM_ID,1)
    ) E* f0 D1 k1 ~3 `
  20. st.exitQuest(False)
    , p7 {$ M3 T9 U2 h; V" c" M
  21. return
    3 p, R( h4 ^7 x' T

  22. ) _: d$ O! P" y) X+ k( @
  23. def check(st) :
    1 P; P' B7 {! G5 ~0 e8 l
  24. if getCount(st) >= 4 :* f. c8 b  O. \( p
  25. completed(st)
    + t% A# q6 M4 r9 w
  26. return
    $ N; C3 W( v0 t5 z( C6 g) t
  27. # a  p- K; e! f, T
  28. class Quest (JQuest):
    . ]  h# ~& V, N( S# z. ?+ I* R$ d
  29. - r. l0 i- }8 |' B2 P' ^% }" c
  30. def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)
    ; k2 P/ S, J& Q0 C! J) F0 z0 Y
  31. + B5 Q6 h6 _' [$ G) ?& M; d
  32. def onEvent (self,event,st):
      [' s0 v) ?5 u& ?1 G5 {
  33. id = st.getState()
    & T5 @! D5 b1 h. h5 r6 ]. m/ [
  34. if id == CREATED : st.setState(STARTED)
    ( C) U3 U+ z7 O1 T( ~
  35. elif id == COMPLETED: pass$ w+ {. @- ~* s$ T4 b! n
  36. elif id == STARTED : check(st)
    4 ~) N& \( b- K' g
  37. return8 t1 H* U1 ?6 W9 I* P/ A2 S
  38. 7 U; a# G2 D6 B: M
  39. def onKill (self,npcId,st):! |" x9 q6 j! @1 q
  40. if npcId == KELTIR_NPC_ID:; ]9 I  z* g9 @/ l6 J9 b
  41. n = getCount(st)
    * g9 {- s7 t4 L, t1 v
  42. if n == 0:
    3 E- V/ X9 Z$ I3 c! J- V$ ~1 W' I
  43. if st.get('chat0') == None :2 }4 ?% }- N1 B; E# M- d
  44. st.set("chat0", "true")
    7 s1 C4 f. K+ B) J( B' w
  45. return "Chat0.htm"  V! z7 i/ N9 q. i5 V# V' c8 ~
  46. elif n == 1:' H, O4 s& H% |$ ^1 \5 F% q
  47. if st.get('chat1') == None :
    2 c: Q8 E+ g% E4 @) {9 J$ M
  48. st.set("chat1", "true")9 P' q  s  o) B: H8 m
  49. return "Chat1.htm"
    ' ^8 g' a, f2 D2 l9 X
  50. elif n >= 4:, G* H  e/ y, Z3 n7 ?
  51. return "Chat4.htm"
    $ Z4 Y- M2 a: B
  52. return "Collect "+str(n)+" of 4 fangs"- w5 s9 A) \% @0 a# J' ~
  53. return
    ) f5 n, O5 ^4 M& L! W2 `5 g5 o
  54. 9 g* `; I( T$ k% N
  55. QUEST    = Quest(201, "Tutorial", "Tutorial quest")7 ^& A4 V2 P" L; F
  56. CREATED = State('Start',    QUEST)% t+ m; K/ [, c& _; z
  57. STARTED = State('Started', QUEST)& x; g9 W5 ~9 I5 [( r( z; t" G9 N
  58. COMPLETED = State('Completed', QUEST)
    " T8 \0 u( o6 ]2 Q2 C
  59. 3 e: X- q6 H9 i; i6 e
  60. QUEST.setInitialState(CREATED)# U& N, O7 q9 X4 u7 O* z
  61. QUEST.addStartNpc(7056)( h6 G9 u2 G3 F5 k
  62. QUEST.addStartNpc(7012)
    , I) s! {3 `" x! e: N" w
  63. QUEST.addStartNpc(7009)+ b* S4 b- T8 D% c% m9 h
  64. QUEST.addStartNpc(7011)6 }/ S8 T0 q$ G, r5 N5 @: v
  65. " y! V! E3 c) p9 X$ _
  66. STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)0 L; M# B. h' d, W7 I9 T, t7 v
  67. STARTED.addKillId(KELTIR_NPC_ID)
    , w# b5 g3 x8 b5 U: {# \* X
  68. STARTED.addTalkId(7056); e9 h; f" y) o1 @* y. d1 \
  69. STARTED.addTalkI d(7012)
    - O5 g7 l' b  }' B& W% U* _
  70. STARTED.addTalkId(7009)6 n+ @6 o" b6 f- x
  71. STARTED.addTalkId(7011)
Скопировать код

) I% T% C$ i" B( v2 ~9 I  {. H; p$ Y* x% R/ S4 f" c( p4 S' f
Чтобы ответить, вам надо авторизироваться в системе Вход | Зарегистрироваться

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

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

638638758

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

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

admin@artace.ru Онлайн

QR-код

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