Top.Mail.Ru

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

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

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

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

x
Хроники        Interlude- p2 i! r5 Z0 J" w  u/ `
Сборка        L2j
2 X3 u4 o' `& h+ a0 S* AОбратите внимание: в файле htm стартового NCP обязательно должна быть ссылка на квест:
9 W$ O  t( c( N
  1. STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код
Для этого квеста больше ничего не надо. Все необходимое для корректной работы квеста уже добавили. Вот полный текст квеста:+ R/ ~2 h5 |9 J. j
3 k/ V8 S* V: z; i0 f) k* O2 {0 O
  1. if getCount(st) >= 4 :
    2 g$ w# ?: ~2 |* G' {3 z
  2. completed(st)
    2 Z4 t$ |* X9 o
  3.   return
    4 f, e# L5 N: B+ O* _2 }% _5 N

  4. . [) o$ S1 K( _8 I: `
  5. class Quest (JQuest):
    : o+ N' m9 v* R+ ~( y
  6.   def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)3 d7 i) K0 m: R
  7.   def onEvent (self,event,st):& O7 Z3 H' X3 F* S
  8. id = st.getState()/ I7 i; R( g6 a2 d; P3 T
  9. if   id == CREATED  : st.setState(STARTED)
    0 n6 X$ p1 ^. t, ^) I
  10. elif id == COMPLETED: pass
    ' n+ U# h- w8 J2 p) J
  11. elif id == STARTED  : check(st)
    2 P/ j, i1 L( U: S  s
  12. return2 G* l$ i: N& H2 R. j' @$ Y

  13. ) c1 v$ M+ B# S0 I
  14. QUEST     = Quest(201,"Tutorial", "Tutorial quest")
    " T% @; D0 c( @7 D* ^- i
  15. CREATED   = State('Start',     QUEST)
    0 F- J% M2 ~8 X6 O+ \5 i
  16. STARTED   = State('Started',   QUEST)6 I7 I8 u: E- L7 Y9 r# g9 e
  17. COMPLETED = State('Completed', QUEST)
    7 Q/ @, {9 b4 R7 B8 ]( Z
  18. , H1 }) ~8 g4 b
  19. QUEST.setInitialState(CREATED)6 D& k+ x( m7 j1 v% [
  20. QUEST.addStartNpc(7056)
    + o4 ~# {: E) Y4 `8 W: ]
  21. STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код
Теперь рассмотрим, как это работает.
; e. J) `; j2 D' g4 xИгрок подходит к начальному NCP (в данном случае 7056), нажимает на «Quest». Квест будет создан и состояние квеста перейдет к CREATED и игроку будет показана страничка Start.htm с описанием квеста. Тогда метод onEvent, поле открытия странички Start.htm переведет состояние квеста в STARTED и игроку будет показана страничка Started.htm, где будет опсание того, как найти keltirs и .т.д.
5 I/ Y' g! y/ G( J' R/ ]) J, U1 C8 f6 `

/ f0 i% {5 M5 ?5 V; I+ r7 ~При состоянии STARTED будет зарегистрирован дроп «fangs» при убийстве keltirs. Игрок может вернуться к стартовому NCP и спросить о квесте – метод onEvent будет вызван снова. Если у игрока не хватает необходимого количества предметов, то метод check() не переведет квест в следующее состояние и Started.htm будет показана снова. Но если игрок собрал необходимее количество предметов (в данном случае 4 клыка), то метод check() вызовет метод completed() который переведет квест в новое состояние COMPLETED, заберет все клыки, даст карту мира, т.к. это награда за квест, покажет Completed.htm и завершит квест.* y6 G7 V" B! h( {( ~

& k, R* g  |) T3 ?; V

0 J) `! v# m; M* r* y7 m  X  dТеперь давайте сделаем наш квест более похожим на то, что он должен из себя представлять.
. P/ u; F" ^4 x, ]Прежде всего у нас есть 3 метода для объявления их в Яве – onTalk, onKill и onEvent. Если методы onTalk и onKill не объявлены, то за них все будет делать метод onEvent, т.е. определять квестовых монстров и вызывать диалоги NCP. Есть примечание, методы onTalk и onKill будут вызывать только диалоги с NCP в зависимости от текущего состояния квеста. Метод onKill будет вызываться только тогда, когда мы убиваем квестового монстра.& e8 v5 k0 L4 C2 H
- L- j4 E# _% P; A4 Y# D2 D4 E
; s( U* }1 m; G: }
Давайте рассмотрим как вызывается метод onKill при убийстве keltir в состоянии квеста STARTED:2 C. r2 ]: U9 t+ h# F- E
  1. STARTED.addKillId(KELTIR_NPC_ID)
Скопировать код
и метод onKill в классе Quest:
0 U! g8 O4 D* f4 G: u, N! C% w9 K$ R9 b( Y
  1. class Quest (JQuest):/ n: [' u4 v7 d8 J# V2 ?3 C
  2.   ...
    1 |+ r3 V" ~( f0 a/ Z7 L% L
  3.   def onKill (self,npcId,st):4 T* H% i* f" B( A, F- X1 N$ d
  4. if npcId == KELTIR_NPC_ID:
    2 Z+ y, e; q: ^+ n
  5.    n = getCount(st)+ N; ?' ?& Y1 |0 b
  6.    if   n == 0:' v1 D0 h( _1 x; T; g1 |; y" ^
  7.        return "Chat0.htm"
    0 [$ V% G" q1 P3 X- h- h
  8.    elif n == 1:( y, [5 a; \4 w! Q: O0 X, o
  9.        return "Chat1.htm"
    % t6 y& F7 x" }3 L
  10.    elif n >= 4:
    ) T2 `% `' @* j1 m
  11.        return "Chat4.htm"
    1 k* \1 I  H) @" J  m, q
  12.    return "Collected "+str(n)+" of 4 fangs"1 c- u; s* b3 P/ T: m  R9 v
  13. return
Скопировать код
Метод onKill (а так же метод onTalk) имеет следующие параметры:+ v  b& }& Y# H5 K5 o, Y( L/ h  {

3 A' I  M2 c3 }- c+ d3 {/ F# n' p

5 X" k9 \8 f! Q• self – квест# ~1 H. T( ]) T( F% G
• npcId – ID NCP, которого мы должны убивать (если это метод onTalk, то ID того NCP, с которым мы должны поговорить).
& O. T2 ?$ K: `# o• st – текущее состояние игрока.$ G* x4 c' K  q

2 u  @: [9 J- S) b, G/ u1 o; G

8 g- Q' L/ G( ]9 C. LВ этом методе мы проверяем и отмечаем, является ли убитый NCP keltir’ом. В основном эта проверка не нужна, т.к. у нас только KELTIR_NPC_ID.
5 y7 d+ J& Y+ w" U% s" N" x5 |
4 V# X7 ]/ d( ?4 c( V: |
4 @( ]  M; t+ H& }9 e! }/ c
Затем проверяем количество предметов (в данном случае количество клыков), и если их вообще нет, то возвращаем строку "Chat0.htm", если только один предмет, то возвращаем строку "Chat1.htm", если же предметов 4 или больше, то "Chat4.htm". Если строка возвращена из методов onEvent, onKill или onTalk, то сервер покажет соответствующие htm. В Chat0.htm может иметь следующий текст: «Вы не имеете ни одного клыка, возвращайтесь позже, когда соберете 4 штуки и бла, бла, бла…», в Chat1.htm может быть следующий текст: «У Вас всего 1 клык, по этому соберите еще…». В Chat4.htm – «Вы собрали необходимое количество предметов, возвращайтесь к вашему тренеру, что бы завершить квест…»
. f7 B4 |8 U! L/ ]! x( D0 c: W+ q$ {
* [( g# _  k  l: P* K
Примечание: если в строка return начинается с "<html>", то будет показана страничка html с текстом, который стоит далее. Так вместо:/ W1 m$ q& u& x6 ]/ k' R
return "Chat4.htm"8 o& a1 W* v" q" c4 B! {1 U9 n
! `6 g) n6 @5 S1 q3 {: }& q

( \( ^! h6 A/ k  r: M' wможно поставить:, G  c/ P1 x: U* a6 ^# X
  1. return "<html><body>Return to your trainer to complete the quest</body></html>"
Скопировать код
Так же если строка заканчивается без .htm или в начале нет <html>, то текст будет выведен, как системное сообщение в окне чата. В нашем случае мы сделаем так, что бы при каждом убийстве keltik выводилось системное сообщение: «Собрано N из 4-х клыков».
5 v' k  P3 I. M" f2 S7 }! k
/ A) p7 o2 n! h. x% G

4 n3 k/ K9 c  T. P. rНаш код для onKill имеет один недостаток. Он будет постоянно показывать Chat0.htm, Chat1.htm и Chat4.htm, нам же необходимо, что бы Chat0.htm и Chat1.htm показывались только один раз. Как нам это сделать? С помощью переменных.% ]+ K) u" D0 N' J

/ D/ w+ r5 g5 W1 M! W4 b

9 @$ ?: E( G4 [/ uВ каждом квесте строки могут храниться с помощью переменных. Эти переменные сохраняются в Вашей БД. В каждом методе мы можем назначить, прочитать и удалить переменные. Давайте изменим метод onKill, так что бы каждый диалог вызывался только один раз.
- q( D' N2 v) C; o# H
  1. def onKill (self,npcId,st):
    7 v& ^  a6 a- |
  2. if npcId == KELTIR_NPC_ID:
      ?4 _  I3 V6 k) r' o
  3. n = getCount(st)
    - D, a$ R$ t4 l9 S
  4. if n == 0:: r: X( k0 X6 J5 q, F  U7 V& ]
  5. if st.get('chat0') == None :
    ) M) T  J9 ]4 M8 i/ D
  6. st.set("chat0", "true")
    ( Y  Y, m2 L$ c% A7 |
  7. return "Chat0.htm"
    * J$ [, g0 \3 u6 z4 O+ A
  8. elif n == 1:' x0 p+ A$ |# s, @
  9. if st.get('chat1') == None :1 O: H; A8 H: E
  10. st.set("chat1", "true")1 X; u" n; |( ?  \+ ^7 T* H7 P
  11. return "Chat1.htm"
    ( w( C4 z! X. n1 O, c
  12. elif n >= 4:7 q6 I" s! J) H
  13. return "Chat4.htm"
    : E0 @. F# \+ W' Q9 G
  14. return "Collected "+str(n)+" of 4 fangs"
    " n2 |2 u6 C- a3 W5 F% N
  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.
# B/ A5 [& e; S, `' Q' `$ t& f" u" T2 p% Z
, A2 u; N+ h% P& m$ n
Вот конечный рабочий вариант квеста:
+ n# w6 U' K6 G5 a* v  c" j; b- F4 T; U
  1. import sys9 ]. y; n1 j8 F" K( e5 w
  2. from net.sf.l2j.gameserver.model.quest import State
    5 _! P* `. ]/ Q! C/ ]
  3. from net.sf.l2j.gameserver.model.quest import QuestState
    ( K8 k; V6 f/ ?! j  L
  4. from net.sf.l2j.gameserver.model.quest.jython import QuestJython as JQuest
    4 ]0 c+ a: R# o3 {
  5. " @6 R8 B  ~4 f& x* U5 c. @
  6. KELTIR_NPC_ID = 12082& H- K2 `7 i0 ]# Y% T0 v
  7. FANGS_ITEM_ID = 1859
    ( h3 E; l) l& t. Y/ W2 {; K8 ~
  8. DROP_RATE    = 500000& v' y$ L7 K; y7 i% j

  9. 6 {  p! C4 Q( C- ?4 m$ u0 w, @0 ]: C9 L
  10. WORLD_MAP_ITEM_ID = 16651 i. I6 f9 B% J* l6 k

  11. ' F# r* m3 L. ]. M1 H" @
  12. def getCount(st) :
    ' K+ @3 `% a( u) K; r/ g& J
  13. return st.getQuestItemsCount(FANGS_ITEM_ID)
    $ g5 h# Q$ h1 R. K+ g  h. ~3 j

  14. 6 D9 \# G) D% p9 u8 S! r
  15. def completed(st) :$ s) S' X3 \1 u$ H
  16. st.setState(COMPLETED)
    7 K: T7 N: H0 n+ ^( V) r( a
  17. st.clearQuestDrops()
    9 G6 o% [  O3 s+ X
  18. st.takeItems(FANGS_ITEM_ID,-1)
      |0 s  J0 E6 u" k1 B
  19. st.giveItems(WORLD_MAP_ITEM_ID,1)/ L- _+ A9 J- F# d) P* c/ g( j6 }
  20. st.exitQuest(False)' L" n" ]2 X) y- ?' O" W
  21. return2 x6 c0 ~* F- l) G. L
  22. 0 Y& T' D, ]. f/ q( }  j0 ]
  23. def check(st) :* {1 M0 q7 ?  n: ]  n& \' @
  24. if getCount(st) >= 4 :
    $ J* B! z+ l4 n2 Q+ i8 B% z( L
  25. completed(st)
    2 K" }7 b5 p" H4 g  U( R
  26. return6 E0 T; e, K, z, ?3 ?/ E
  27. $ x3 ]1 L3 a0 ^* a3 o
  28. class Quest (JQuest):
    ' t% e/ D5 |% r9 A. M1 r) b; |
  29. % _5 A1 J9 D  b6 G; W
  30. def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)
    $ a2 T# |+ l( c8 Y9 G- X

  31. 4 i( [3 D: E( D$ Q
  32. def onEvent (self,event,st):
    0 c$ p/ m( Q+ [! ~3 S5 M
  33. id = st.getState()
    ) H1 [) U+ ]/ X, x
  34. if id == CREATED : st.setState(STARTED)5 K% `4 A$ P( O& T. I0 m
  35. elif id == COMPLETED: pass
      e4 q; N3 G  L' s( S; i
  36. elif id == STARTED : check(st)4 A7 ]' C3 `6 ^7 U& x
  37. return( l6 t5 k  ^* t# g  J% h0 r% x

  38. ' [. }) j% }# R$ t& Z
  39. def onKill (self,npcId,st):
    / [8 ^. V& x, Y" N- H
  40. if npcId == KELTIR_NPC_ID:
    6 n% j) ]5 z. b& E* d
  41. n = getCount(st)
    % x: ^* i8 J& ]1 }' m* B& [/ {
  42. if n == 0:
    & S1 G- o9 I2 m9 K) \
  43. if st.get('chat0') == None :7 c3 ?1 j# \) }6 p5 G- B) O
  44. st.set("chat0", "true")
    " e3 J- I1 S  B4 b/ J0 a
  45. return "Chat0.htm"; ]4 T; V) T, n: I
  46. elif n == 1:* b7 w- I1 x' S2 T
  47. if st.get('chat1') == None :
    . n# L3 p) ^/ T, w
  48. st.set("chat1", "true")
    6 O% r, c7 ^. d5 u5 k
  49. return "Chat1.htm"
    , V: O* d  O* S' j, [" l4 I
  50. elif n >= 4:
    " d1 x' `6 x$ ?% h
  51. return "Chat4.htm"
    ! w# g& K3 w0 T- U* P6 {; C
  52. return "Collect "+str(n)+" of 4 fangs", [; Q. d2 K% a  N) p2 F3 `2 r, c
  53. return9 ~' e$ k* Z& [; U/ Y8 h
  54.   N/ ^3 C; b8 q" g5 Q
  55. QUEST    = Quest(201, "Tutorial", "Tutorial quest")
    . f  h/ n( [' P
  56. CREATED = State('Start',    QUEST)% i4 o' x: }3 v, [
  57. STARTED = State('Started', QUEST)" j0 g4 N: X( H
  58. COMPLETED = State('Completed', QUEST)3 w) c, J$ L% y3 Q, B, J6 Y9 w
  59. 7 G% t! H+ f! u# b% U, `! ]' [
  60. QUEST.setInitialState(CREATED); i2 ]$ M" c- Z5 _/ ], x
  61. QUEST.addStartNpc(7056)3 ?+ P/ J; G; R1 T" h( K! u; E3 @
  62. QUEST.addStartNpc(7012)& i6 t3 b. J% g1 m# J  X
  63. QUEST.addStartNpc(7009)
    2 M- w; {7 A' P" T# N
  64. QUEST.addStartNpc(7011)" C; N" F. @9 w' _7 |( \

  65. - t! v& r( W: I5 I7 J
  66. STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)* A2 _3 R3 w8 q5 F+ U, X
  67. STARTED.addKillId(KELTIR_NPC_ID)
    ; d7 H) d7 ~. x; R
  68. STARTED.addTalkId(7056)
    5 L8 i9 ?) W+ Y: s  z* M# |
  69. STARTED.addTalkI d(7012)! b7 e$ f+ q: O' j% w
  70. STARTED.addTalkId(7009)! J. N3 B2 `4 E. H( l5 J( _
  71. STARTED.addTalkId(7011)
Скопировать код
- v' T! E$ V& r9 n; Y; x) o9 r) Q

3 C, c, S( u' F# K: s) t. H% |
Чтобы ответить, вам надо авторизироваться в системе Вход | Зарегистрироваться

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

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

638638758

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

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

admin@artace.ru Онлайн

QR-код

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