Top.Mail.Ru

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

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

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

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

x
Хроники        Interlude
6 K( D9 q0 v( L0 J' N% C- L- ~1 jСборка        L2j
9 y, S/ D, i6 e; U' xОбратите внимание: в файле htm стартового NCP обязательно должна быть ссылка на квест:" G, q8 }8 _  T* ^( X5 d
  1. STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код
Для этого квеста больше ничего не надо. Все необходимое для корректной работы квеста уже добавили. Вот полный текст квеста:. l% m. f* m. `4 F1 R/ A" y" M+ L
/ D; W0 D& R# z, w
  1. if getCount(st) >= 4 :
    " _, U( l( q! Y( T
  2. completed(st)3 [. ?( l$ T8 L
  3.   return
    ; k- n7 c- u, X5 t3 m
  4. + y, B$ B7 X- k) \. B( L5 e8 R
  5. class Quest (JQuest):! V+ m9 W& w4 }: ^
  6.   def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)
    ; f$ m# d- F; c/ p6 L
  7.   def onEvent (self,event,st):
      Y, ?' o% \! N& [9 ~
  8. id = st.getState(): y! N6 b, |. n: v( S' a2 O
  9. if   id == CREATED  : st.setState(STARTED)
    + P; c- e. p; ]9 Z4 f& W
  10. elif id == COMPLETED: pass
    2 I1 d: n7 @3 c
  11. elif id == STARTED  : check(st)
    . J; }! i7 _* y" ]& z
  12. return$ F+ |4 \" a. r6 T" p

  13. ! b8 T( B- N& \: ~1 {# b
  14. QUEST     = Quest(201,"Tutorial", "Tutorial quest"), V. D$ u/ x+ w* `9 Q4 {
  15. CREATED   = State('Start',     QUEST)
    : f0 E- w. y; I7 A6 y: W$ e
  16. STARTED   = State('Started',   QUEST)  ]: B  \, A- o1 P' _0 b
  17. COMPLETED = State('Completed', QUEST)+ F+ I/ R1 w: G# m9 u# ~

  18. 0 z- s. Z  ?- ~- }. m; ?
  19. QUEST.setInitialState(CREATED)3 O. m1 m: L$ b3 A& h9 [( r
  20. QUEST.addStartNpc(7056)
    # a5 x, g2 j  t2 }0 A
  21. STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код
Теперь рассмотрим, как это работает.0 j, c8 a' `% q7 K" L
Игрок подходит к начальному NCP (в данном случае 7056), нажимает на «Quest». Квест будет создан и состояние квеста перейдет к CREATED и игроку будет показана страничка Start.htm с описанием квеста. Тогда метод onEvent, поле открытия странички Start.htm переведет состояние квеста в STARTED и игроку будет показана страничка Started.htm, где будет опсание того, как найти keltirs и .т.д.
* ~! Z& u" ?# l) F4 m1 J/ z# O
8 O$ W' z; m7 q
. ?/ J! h6 X" B" g  U/ z1 M
При состоянии STARTED будет зарегистрирован дроп «fangs» при убийстве keltirs. Игрок может вернуться к стартовому NCP и спросить о квесте – метод onEvent будет вызван снова. Если у игрока не хватает необходимого количества предметов, то метод check() не переведет квест в следующее состояние и Started.htm будет показана снова. Но если игрок собрал необходимее количество предметов (в данном случае 4 клыка), то метод check() вызовет метод completed() который переведет квест в новое состояние COMPLETED, заберет все клыки, даст карту мира, т.к. это награда за квест, покажет Completed.htm и завершит квест.
3 w4 q% ]  W6 l
# X& |9 ?8 k- l  K6 ?3 f4 H* H

( W3 F. |3 T2 f) @Теперь давайте сделаем наш квест более похожим на то, что он должен из себя представлять.
0 G' D# r& S8 V2 O2 r8 mПрежде всего у нас есть 3 метода для объявления их в Яве – onTalk, onKill и onEvent. Если методы onTalk и onKill не объявлены, то за них все будет делать метод onEvent, т.е. определять квестовых монстров и вызывать диалоги NCP. Есть примечание, методы onTalk и onKill будут вызывать только диалоги с NCP в зависимости от текущего состояния квеста. Метод onKill будет вызываться только тогда, когда мы убиваем квестового монстра.# ?( `+ A4 t( M9 z( @# q

. g) p3 g! \  ~$ l

0 F& ^7 l; Z% uДавайте рассмотрим как вызывается метод onKill при убийстве keltir в состоянии квеста STARTED:
5 f0 }2 P0 U; C/ }
  1. STARTED.addKillId(KELTIR_NPC_ID)
Скопировать код
и метод onKill в классе Quest:$ d6 J3 R& p$ u3 m0 N$ f

, p+ d; r  ?! r
  1. class Quest (JQuest):' e1 F9 \  Z  g4 u/ i# t2 d1 M5 u$ D
  2.   ...
    ! ~  X9 r. M& H' R2 s  k9 V- m
  3.   def onKill (self,npcId,st):
    " _# O  X+ q$ H. a' a5 }
  4. if npcId == KELTIR_NPC_ID:
    - r- }- f# a/ b4 m9 P+ ^
  5.    n = getCount(st)
    3 F" Y9 n8 H+ c  [
  6.    if   n == 0:
    " d" _2 s  R  Y0 G) M6 M  S) u/ _
  7.        return "Chat0.htm"* \* ^5 M5 v9 a+ j
  8.    elif n == 1:( P+ _5 F" ^* @( V. U  e" u9 m
  9.        return "Chat1.htm"- |$ m& U1 G, z
  10.    elif n >= 4:
    + G" h: I% y# W9 d1 P, N
  11.        return "Chat4.htm"
    ! n( K' k& o( y" Z# O' |
  12.    return "Collected "+str(n)+" of 4 fangs"
    : M; `1 X8 b. `. r3 l; [
  13. return
Скопировать код
Метод onKill (а так же метод onTalk) имеет следующие параметры:: ~' i$ c4 K& Q  |) i- U- K, [; Q
7 x3 y! f- \! G4 N3 a2 `$ t  {7 G

! p+ _+ B( Y% C! `$ u/ i, {, i& B• self – квест
  p/ w, x+ X! _) N  X* e: N• npcId – ID NCP, которого мы должны убивать (если это метод onTalk, то ID того NCP, с которым мы должны поговорить).1 j  X6 i" @- E
• st – текущее состояние игрока.4 L4 f( f  w& X. M/ K! T
4 v- ^& s5 z8 G

5 b& M$ x% ]9 N* N- I% dВ этом методе мы проверяем и отмечаем, является ли убитый NCP keltir’ом. В основном эта проверка не нужна, т.к. у нас только KELTIR_NPC_ID.* _2 L/ X4 Y: @& z

! Z* N. X( p, Z) t# y  Q* l

6 B0 }0 S* X! X8 i; x% ~& ZЗатем проверяем количество предметов (в данном случае количество клыков), и если их вообще нет, то возвращаем строку "Chat0.htm", если только один предмет, то возвращаем строку "Chat1.htm", если же предметов 4 или больше, то "Chat4.htm". Если строка возвращена из методов onEvent, onKill или onTalk, то сервер покажет соответствующие htm. В Chat0.htm может иметь следующий текст: «Вы не имеете ни одного клыка, возвращайтесь позже, когда соберете 4 штуки и бла, бла, бла…», в Chat1.htm может быть следующий текст: «У Вас всего 1 клык, по этому соберите еще…». В Chat4.htm – «Вы собрали необходимое количество предметов, возвращайтесь к вашему тренеру, что бы завершить квест…»
3 l# a" j- s1 s. x* k4 X: N; [1 L: V$ |

5 J+ [0 \0 @) i2 i/ pПримечание: если в строка return начинается с "<html>", то будет показана страничка html с текстом, который стоит далее. Так вместо:
$ ]! I1 K( }- Q& [7 _, b7 U* areturn "Chat4.htm"
( W" Z; a0 _" M* d8 K( E3 m7 E% Z) p' W2 m1 p; |* h2 g

6 H" q( J  A, b. Rможно поставить:
# \3 u8 O# G; ~; ^1 O
  1. return "<html><body>Return to your trainer to complete the quest</body></html>"
Скопировать код
Так же если строка заканчивается без .htm или в начале нет <html>, то текст будет выведен, как системное сообщение в окне чата. В нашем случае мы сделаем так, что бы при каждом убийстве keltik выводилось системное сообщение: «Собрано N из 4-х клыков».# A1 s, C, C- }9 A: F
- {% r+ _" S6 s* [8 b2 H# N; m% L" S

$ |( ]1 e  ]( n4 ^1 h1 kНаш код для onKill имеет один недостаток. Он будет постоянно показывать Chat0.htm, Chat1.htm и Chat4.htm, нам же необходимо, что бы Chat0.htm и Chat1.htm показывались только один раз. Как нам это сделать? С помощью переменных.* M" `- [+ R5 H6 ~' ^
: y! b+ D& i; M" Y1 c) T& n
9 ?) _: J) v9 c1 o: \/ J. |
В каждом квесте строки могут храниться с помощью переменных. Эти переменные сохраняются в Вашей БД. В каждом методе мы можем назначить, прочитать и удалить переменные. Давайте изменим метод onKill, так что бы каждый диалог вызывался только один раз.# f3 H, w* F( N1 u5 o5 {
  1. def onKill (self,npcId,st):2 w. n. T) Z* E" k* P, i" f
  2. if npcId == KELTIR_NPC_ID:+ s! X4 `; o# a
  3. n = getCount(st)  q- C, W/ c- H" P; n3 X: {
  4. if n == 0:
      Y* b/ N- q2 c' M  F% F: g+ j. r
  5. if st.get('chat0') == None :8 @0 X+ R* ?2 x: P9 S# |  _3 t9 A
  6. st.set("chat0", "true")  o% v* E5 O9 c  L
  7. return "Chat0.htm"
    8 U. I1 X" e# L3 u# @: t
  8. elif n == 1:
    0 F  I9 b3 A) D" d8 M
  9. if st.get('chat1') == None :0 |/ i+ N0 R3 g' B3 l* l: a
  10. st.set("chat1", "true")
    1 ]1 w; T$ Y6 F" X; I0 j! L, u
  11. return "Chat1.htm"0 z- P4 M) R+ \4 u, O9 Q; ~5 e
  12. elif n >= 4:
    # |' `) m* H2 B5 j
  13. return "Chat4.htm"
    1 O9 ^$ T* E$ ~' p8 Z  b4 E
  14. return "Collected "+str(n)+" of 4 fangs"+ A9 y; w5 v- t* M5 _2 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.0 n& R& o7 t0 G9 @0 s

/ z; J0 C5 U/ F5 X
7 ?- d4 |! f' c9 b5 x) X0 O: Y
Вот конечный рабочий вариант квеста:
' P$ d; o; t7 j& K; i) x
  1. import sys
    - z, N" |2 ~' m: Y; L' `
  2. from net.sf.l2j.gameserver.model.quest import State5 D" ?5 a- q" T/ g  }- S- f: H5 ~2 v* p
  3. from net.sf.l2j.gameserver.model.quest import QuestState
    3 |+ u: z5 @* m
  4. from net.sf.l2j.gameserver.model.quest.jython import QuestJython as JQuest
    + K1 f) E' ^; l; T! _5 Z% g

  5. : h( ]9 t% d5 Z  G
  6. KELTIR_NPC_ID = 12082/ L' I; c- u% f3 E' F$ l7 u
  7. FANGS_ITEM_ID = 1859
    8 T  [( ~$ h: L" a
  8. DROP_RATE    = 500000
    % }5 C* A( i, z7 C3 b9 q" v6 x& _1 M
  9. 7 b$ `, v2 K" \4 v
  10. WORLD_MAP_ITEM_ID = 1665
    * Q/ P9 I/ V" F4 t5 Q
  11. : u$ q  F" C& v  H
  12. def getCount(st) :
    3 \% G% u2 T4 G8 k9 i; R
  13. return st.getQuestItemsCount(FANGS_ITEM_ID)& {4 e- F) ?' K0 @: f& n

  14. / f5 S  B" H* {) g2 m5 Q
  15. def completed(st) :
    # o' Y% d5 J7 Y2 U
  16. st.setState(COMPLETED)3 v4 R- a$ F) S3 L4 i
  17. st.clearQuestDrops()  ]8 p2 C3 W- U9 Z$ r
  18. st.takeItems(FANGS_ITEM_ID,-1)' e# V% B, @3 T6 L; K! b
  19. st.giveItems(WORLD_MAP_ITEM_ID,1)
    ! U  I4 G6 C6 H2 p
  20. st.exitQuest(False)$ K5 S* m+ |. g
  21. return6 s3 s) B3 q" i* a; n& }0 Z; h+ q

  22. ' r- K! g! V0 p% L
  23. def check(st) :
    ( b6 P% K; F2 k1 o* W( \3 S5 X
  24. if getCount(st) >= 4 :
    - M1 j) M' E' I' h  E
  25. completed(st)% b& \1 ?4 p3 K" M. E. |
  26. return
    0 p/ ~, s, J+ B

  27. 3 c& E: {- J; |8 R& y" _( K3 N/ K
  28. class Quest (JQuest):
    * r% V9 _; O7 n/ t" ]0 y
  29. 6 q. z( o( [0 }) _9 j4 O/ J3 L
  30. def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)
    $ v3 v1 N4 ]1 y& `" x
  31. & ^3 j( f! P3 ], e/ o; W/ g
  32. def onEvent (self,event,st):- r+ m0 k" |! X- U8 [9 |, Q
  33. id = st.getState()
    ! k1 G9 j0 U2 A, Z5 R; J
  34. if id == CREATED : st.setState(STARTED)8 L/ x) [6 o/ M, U
  35. elif id == COMPLETED: pass
    6 c0 _. Z6 P: @
  36. elif id == STARTED : check(st)
    " D8 Y, o% d3 Z, i1 L6 {
  37. return8 s+ A/ g  |# t
  38. " z2 ]8 o, }8 H: i# Z# D
  39. def onKill (self,npcId,st):' d9 H! s  c/ }6 X" F7 E
  40. if npcId == KELTIR_NPC_ID:
    + R$ g( n: z3 g' b1 _: W: c2 l
  41. n = getCount(st)
    4 r# X, y4 L( r; ~
  42. if n == 0:
    2 I6 u$ n! ]. j5 m1 _4 G6 i
  43. if st.get('chat0') == None :6 v  o" t, {+ Z9 Q* U
  44. st.set("chat0", "true")/ Z- G% i" b3 ?4 y$ r6 s
  45. return "Chat0.htm"; j1 U9 K/ T/ ~
  46. elif n == 1:1 ]3 @1 r, w. n* R
  47. if st.get('chat1') == None :' N6 J9 s. r" W
  48. st.set("chat1", "true")0 k& ~4 Q$ G4 R  W8 \! n
  49. return "Chat1.htm"
    # p1 c8 v* z/ d3 Z* b5 w2 K' ]+ H
  50. elif n >= 4:
    3 E+ L, o4 d1 Y6 D" @
  51. return "Chat4.htm"7 `" Q. M$ _' F# u& W8 W
  52. return "Collect "+str(n)+" of 4 fangs"% E2 U, `5 t) g, ^- e! e# K
  53. return4 y) i7 e9 o! j+ ?  J6 f

  54. ( b! ?! [; P2 u) n
  55. QUEST    = Quest(201, "Tutorial", "Tutorial quest")
    ' r! o) y) @# C
  56. CREATED = State('Start',    QUEST); D0 G' M9 |# U8 C# ~
  57. STARTED = State('Started', QUEST)" W, `: o, p; d2 q7 G# O1 N5 o9 W
  58. COMPLETED = State('Completed', QUEST)
    - l' B1 |! v, o+ t

  59.   K/ `0 d2 r6 g" G/ `, o$ z
  60. QUEST.setInitialState(CREATED)
    3 b) c; T, ^! m$ [+ n
  61. QUEST.addStartNpc(7056)* f$ N5 `' B- _5 }7 x
  62. QUEST.addStartNpc(7012)
    , {" e1 k# e; U, R
  63. QUEST.addStartNpc(7009)
    * c. v3 h% R/ P. `5 E* s
  64. QUEST.addStartNpc(7011)
    6 E4 g( @" M0 `- e1 m
  65. 6 g% R3 l$ z9 W( u8 G# h8 [
  66. STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
    * |4 |; x* e$ f; Y% r
  67. STARTED.addKillId(KELTIR_NPC_ID)" x+ H2 S2 }0 k6 i' R
  68. STARTED.addTalkId(7056)
    5 V& o. R! _+ `: i9 ?- N0 o* X) f+ B" ~
  69. STARTED.addTalkI d(7012)
    # g5 ?4 {8 A  }4 d* m- N+ F
  70. STARTED.addTalkId(7009)* W5 |0 a, I( K6 z& a. E, i- Z
  71. STARTED.addTalkId(7011)
Скопировать код
% {. W: V. I) |4 ^1 ]% d

' Y3 b. w5 F; t
Чтобы ответить, вам надо авторизироваться в системе Вход | Зарегистрироваться

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

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

638638758

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

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

admin@artace.ru Онлайн

QR-код

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