Top.Mail.Ru

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

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

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

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

x
Хроники        Interlude" e: C* i6 j1 X, A; f, I: E3 f( s
Сборка        L2j
3 s, h1 ^& K9 E4 C/ J/ ^7 K+ aОбратите внимание: в файле htm стартового NCP обязательно должна быть ссылка на квест:5 `2 {. O" e" z- V5 X+ l
  1. STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код
Для этого квеста больше ничего не надо. Все необходимое для корректной работы квеста уже добавили. Вот полный текст квеста:
3 n! W2 Z; b- X: a; {9 \" X* S7 @$ F& w3 `, u2 \# [- E+ [
  1. if getCount(st) >= 4 :+ a2 \. G; v- _8 R- s3 i4 ]
  2. completed(st): f2 g; j4 a; ]3 z6 r* @
  3.   return
    3 _6 }: Q$ l4 p! f6 \+ b
  4. + L9 T) s" k5 j9 ]/ ]: N
  5. class Quest (JQuest):% o1 @# J0 l: q* r: q' J! v
  6.   def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)
    ) m+ ^: C1 v7 W$ t; W9 a; D) w* |* T, y
  7.   def onEvent (self,event,st):& `8 X0 y( i+ a% f
  8. id = st.getState()& h1 n2 P2 {& E: ^& N+ z/ l5 ~( k
  9. if   id == CREATED  : st.setState(STARTED)
    , U& o) G+ d- j
  10. elif id == COMPLETED: pass
    ( {' |' I+ z) ]% h
  11. elif id == STARTED  : check(st)
    ; E' Z1 {7 X0 H; |+ d
  12. return
    4 D9 Y$ x* o8 [% n: k: l4 w9 ~
  13. . W9 S% @4 }# z5 o2 O3 b
  14. QUEST     = Quest(201,"Tutorial", "Tutorial quest")3 M! D! D0 h. P: ^
  15. CREATED   = State('Start',     QUEST)
    ' X2 @5 f$ M( U3 W0 L/ U" N* i
  16. STARTED   = State('Started',   QUEST)0 {6 T$ ^! R  T8 A9 m; \
  17. COMPLETED = State('Completed', QUEST)
    1 Q3 U# c0 Q4 K$ [- v) A
  18.   q9 u  C6 M% |0 d! z
  19. QUEST.setInitialState(CREATED)
    3 l% |! s' ~7 F* U/ Q5 Q& J( {+ k3 B* u
  20. QUEST.addStartNpc(7056)# O) I& X& W/ n8 n
  21. STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код
Теперь рассмотрим, как это работает.0 f. y4 a$ n. w; A! A
Игрок подходит к начальному NCP (в данном случае 7056), нажимает на «Quest». Квест будет создан и состояние квеста перейдет к CREATED и игроку будет показана страничка Start.htm с описанием квеста. Тогда метод onEvent, поле открытия странички Start.htm переведет состояние квеста в STARTED и игроку будет показана страничка Started.htm, где будет опсание того, как найти keltirs и .т.д.
9 U0 y( b$ S; l' t+ F, M; h; z9 K$ A. v; G- L- U2 l

( |8 V5 Z' o  o, L: w# s9 z, BПри состоянии STARTED будет зарегистрирован дроп «fangs» при убийстве keltirs. Игрок может вернуться к стартовому NCP и спросить о квесте – метод onEvent будет вызван снова. Если у игрока не хватает необходимого количества предметов, то метод check() не переведет квест в следующее состояние и Started.htm будет показана снова. Но если игрок собрал необходимее количество предметов (в данном случае 4 клыка), то метод check() вызовет метод completed() который переведет квест в новое состояние COMPLETED, заберет все клыки, даст карту мира, т.к. это награда за квест, покажет Completed.htm и завершит квест.
! E9 S. C8 c3 m; q. }' s5 Z
0 r  m; \# o4 k) a( n: @
1 ~; [. o3 b; b1 y* B6 i( p
Теперь давайте сделаем наш квест более похожим на то, что он должен из себя представлять.
- s; u3 p- ?: h1 v$ [* V+ _Прежде всего у нас есть 3 метода для объявления их в Яве – onTalk, onKill и onEvent. Если методы onTalk и onKill не объявлены, то за них все будет делать метод onEvent, т.е. определять квестовых монстров и вызывать диалоги NCP. Есть примечание, методы onTalk и onKill будут вызывать только диалоги с NCP в зависимости от текущего состояния квеста. Метод onKill будет вызываться только тогда, когда мы убиваем квестового монстра.
9 Z- ]" r; l% ]5 |/ U+ X! Z7 o) p
& {; M$ h/ H5 T) X  W
7 e% E1 s' v1 s7 @
Давайте рассмотрим как вызывается метод onKill при убийстве keltir в состоянии квеста STARTED:0 s  E1 D( r) z* |9 {
  1. STARTED.addKillId(KELTIR_NPC_ID)
Скопировать код
и метод onKill в классе Quest:
% \- @7 q) C: L& ?& Q! |5 P0 f* G$ F# ~$ v; w
  1. class Quest (JQuest):+ G3 c' e( F; y; y: U* T( O/ Y  K
  2.   .../ z; {% S3 E3 k( z! E0 M
  3.   def onKill (self,npcId,st):& b* ~! G- L0 g: g0 G  j/ `
  4. if npcId == KELTIR_NPC_ID:: V/ r; M. p+ F/ [# Q& g# I
  5.    n = getCount(st)
    / v) I$ V; \# A. l8 F+ r
  6.    if   n == 0:) n8 }; @1 `% j; B/ F) b
  7.        return "Chat0.htm"
    2 N! R  y  `; I8 h/ e% M+ J
  8.    elif n == 1:9 |3 W* E! k, H0 ~# u0 I  i' S
  9.        return "Chat1.htm"
    ' P6 G% Y0 c5 Q$ _
  10.    elif n >= 4:
    5 c' R" G5 r4 ~# M- ]
  11.        return "Chat4.htm"
      |* A$ J: ?. K) S* b
  12.    return "Collected "+str(n)+" of 4 fangs"
    " G% S: ~7 v  {/ ?: b7 t1 z& D
  13. return
Скопировать код
Метод onKill (а так же метод onTalk) имеет следующие параметры:
  q  {. h( A& f8 O, i' F+ O' U9 p8 S" z9 d; o, r! W

5 ^; b! @) W) ]7 ]/ g• self – квест# U$ L' S) _1 j+ T$ u' m8 E7 E
• npcId – ID NCP, которого мы должны убивать (если это метод onTalk, то ID того NCP, с которым мы должны поговорить).
. _% q5 Z5 [4 X1 |' `/ m& b• st – текущее состояние игрока.' {& |" W' V; C9 ]! W% p
1 F0 ~; H4 W  d; n
) ?4 @& A+ j, c- q: W9 C% N
В этом методе мы проверяем и отмечаем, является ли убитый NCP keltir’ом. В основном эта проверка не нужна, т.к. у нас только KELTIR_NPC_ID.) N6 l, _! F) ^7 ~
; y- Y2 t6 e* @% N3 t; z& d
# I* O  n0 h: J" B. F
Затем проверяем количество предметов (в данном случае количество клыков), и если их вообще нет, то возвращаем строку "Chat0.htm", если только один предмет, то возвращаем строку "Chat1.htm", если же предметов 4 или больше, то "Chat4.htm". Если строка возвращена из методов onEvent, onKill или onTalk, то сервер покажет соответствующие htm. В Chat0.htm может иметь следующий текст: «Вы не имеете ни одного клыка, возвращайтесь позже, когда соберете 4 штуки и бла, бла, бла…», в Chat1.htm может быть следующий текст: «У Вас всего 1 клык, по этому соберите еще…». В Chat4.htm – «Вы собрали необходимое количество предметов, возвращайтесь к вашему тренеру, что бы завершить квест…», X# P  E) n: R4 q6 F
& ?. |! C7 @6 y8 B

( u  e: g/ B' w& p8 Q( vПримечание: если в строка return начинается с "<html>", то будет показана страничка html с текстом, который стоит далее. Так вместо:) u9 D* q+ K; }) [" ^' z) ^
return "Chat4.htm"
- o) r8 G3 _7 P! x5 E  G; Y4 y! K& a* H

+ k. [6 K$ p$ v8 i% W& Yможно поставить:
" v" c$ i; X* @: m; J, b
  1. return "<html><body>Return to your trainer to complete the quest</body></html>"
Скопировать код
Так же если строка заканчивается без .htm или в начале нет <html>, то текст будет выведен, как системное сообщение в окне чата. В нашем случае мы сделаем так, что бы при каждом убийстве keltik выводилось системное сообщение: «Собрано N из 4-х клыков».
5 s  q0 e' W9 {1 F4 T$ ~( s) Q# k8 Z) ?4 B1 W# j; `

7 _% D- ^( O+ q$ \Наш код для onKill имеет один недостаток. Он будет постоянно показывать Chat0.htm, Chat1.htm и Chat4.htm, нам же необходимо, что бы Chat0.htm и Chat1.htm показывались только один раз. Как нам это сделать? С помощью переменных., y1 x1 ^7 q5 b' B  Q
5 s$ f3 b7 c( }: }3 `# v
/ C* {& W& C  m% i* v- @( t  }
В каждом квесте строки могут храниться с помощью переменных. Эти переменные сохраняются в Вашей БД. В каждом методе мы можем назначить, прочитать и удалить переменные. Давайте изменим метод onKill, так что бы каждый диалог вызывался только один раз.
& C/ d8 R) u3 b' X$ U2 w2 {
  1. def onKill (self,npcId,st):
    / l. a! u* I! S% }! Y
  2. if npcId == KELTIR_NPC_ID:8 [, `. u! C8 h+ y! j' ?
  3. n = getCount(st)
    ' q! f3 N: b& S! H! S
  4. if n == 0:4 b. j$ `$ E: _' J) A/ [
  5. if st.get('chat0') == None :; P0 a: Y; j8 p: O; e* c
  6. st.set("chat0", "true")
    " B1 x5 v5 Q8 a4 x& B1 i
  7. return "Chat0.htm"% G4 [6 O/ }/ v; @
  8. elif n == 1:/ q+ y! c7 B3 U  L1 T
  9. if st.get('chat1') == None :4 _5 j4 P" e( O- C" k
  10. st.set("chat1", "true")
    + |5 b7 B1 c0 x& ]6 I
  11. return "Chat1.htm"; \! n- J! c  t
  12. elif n >= 4:
    - e, Z2 w, ]9 ]; J3 n6 o* q
  13. return "Chat4.htm"
    % I3 r# J5 k$ G
  14. return "Collected "+str(n)+" of 4 fangs"; ?0 ~: _  X3 F/ b2 g
  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.
! f0 m+ e8 S8 @1 Q
& D7 X, p5 x  k4 T% p

; f$ m( {! [/ z/ u. RВот конечный рабочий вариант квеста:# Z) ^% z% e1 {) B# N2 p  {+ k2 {
  1. import sys
      h+ G7 q# }& ?) @& R! m
  2. from net.sf.l2j.gameserver.model.quest import State
    . k$ d6 w& S" {( h7 N! u; Y' B- y
  3. from net.sf.l2j.gameserver.model.quest import QuestState
    ; k6 _" w* Z% d. Z7 j. P7 P2 Z$ `
  4. from net.sf.l2j.gameserver.model.quest.jython import QuestJython as JQuest
    ! O. ]+ P1 h6 M( V2 z5 N2 C1 d  h( Q
  5. + z  @7 Z& `/ k, F! Q, @
  6. KELTIR_NPC_ID = 12082% O1 {" r) K& K, w8 V* {9 W; r
  7. FANGS_ITEM_ID = 18596 I) f2 Z" K7 ?0 w3 x
  8. DROP_RATE    = 500000
    7 v4 ^  p/ C( y0 G0 x# f
  9. / s9 q3 a3 n3 X/ |/ d9 x
  10. WORLD_MAP_ITEM_ID = 1665
    % a$ M; S8 O' `1 s; ?$ m7 [/ j/ x1 W

  11. ( I. J7 A; }% \* r
  12. def getCount(st) :0 E& ]2 v5 Q  x8 i) z6 n' d, l
  13. return st.getQuestItemsCount(FANGS_ITEM_ID)
    4 [7 |; m+ Q6 D0 U( X( N& z$ I
  14. 9 `6 w5 k8 N/ o( C
  15. def completed(st) :( E3 K3 e/ p8 X
  16. st.setState(COMPLETED)
    7 n$ i. J, b4 A. `+ y8 O- O* W
  17. st.clearQuestDrops()! m4 R$ Z9 @/ ?8 Z$ q( G3 F
  18. st.takeItems(FANGS_ITEM_ID,-1)" v% s0 _9 ^6 G8 ]9 @/ F
  19. st.giveItems(WORLD_MAP_ITEM_ID,1)
    6 `0 R/ N* t/ i( X7 u+ ]
  20. st.exitQuest(False)
    # Y0 w2 R9 i/ c! N. \1 M* T
  21. return; @7 ]  v0 |3 O& o/ p

  22. # h4 L& Y* y) P6 v" S7 u
  23. def check(st) :
    : v* s6 {1 D$ U; A/ s
  24. if getCount(st) >= 4 :
    ( e$ A3 [# H9 O+ c2 `
  25. completed(st)' T* O! n$ U6 |* G* \
  26. return6 Z" G" M5 ]& n% ]6 c$ d

  27. 3 Z9 x4 a) X: g5 e- N7 u
  28. class Quest (JQuest):7 v' O, b* ]2 N: e" u
  29. 3 P. v4 a, \$ E. `2 O& Y/ ]
  30. def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)
    * l/ ?, A' n. _1 h

  31. , a" @" P5 F1 E& n' i7 `
  32. def onEvent (self,event,st):
    ' f; A- |& [/ R7 g( D/ S4 b
  33. id = st.getState()" P' H0 N) L  `- V
  34. if id == CREATED : st.setState(STARTED)" R# I7 x/ ~/ Z: P: J
  35. elif id == COMPLETED: pass
    8 [3 j' @+ r0 i2 Q3 r7 U
  36. elif id == STARTED : check(st)/ y9 K: N& \7 L! r1 u9 T
  37. return: `8 R5 e) Z/ U
  38. 6 M/ r4 e% F+ x2 I
  39. def onKill (self,npcId,st):
    3 w: O4 {, I: u9 a: `# W
  40. if npcId == KELTIR_NPC_ID:+ {3 C! D5 Y4 @& \1 l6 Q: K
  41. n = getCount(st)9 D1 C0 r; L) l; ]  K; k; j
  42. if n == 0:
    ! C# P& S# Y* K: k
  43. if st.get('chat0') == None :2 S/ w6 G% K' E/ p6 a/ O  x
  44. st.set("chat0", "true")4 X: Z0 H# S# U- |% h
  45. return "Chat0.htm"! C! v7 X$ \' Y1 S& s7 y9 n
  46. elif n == 1:
    " u( d9 z2 p0 M# E; C- f  b
  47. if st.get('chat1') == None :
    ' I9 u! Z0 f7 Z$ O  U! H
  48. st.set("chat1", "true")
    # n- D  D. p  _" _5 p9 G8 w% Q
  49. return "Chat1.htm"& v# y( \3 K; f# y
  50. elif n >= 4:
    ! Q. u& F( N$ W) R5 E6 T
  51. return "Chat4.htm"
    & |7 r% {9 J" R
  52. return "Collect "+str(n)+" of 4 fangs"
    5 U: [+ ^+ F& b8 e7 e
  53. return5 _, W7 o$ J0 e$ q6 S1 d# W

  54. " h- h- Y9 \% u
  55. QUEST    = Quest(201, "Tutorial", "Tutorial quest")
    / ~% T4 n& w% K2 ]: k
  56. CREATED = State('Start',    QUEST)- \! h! i, l% b  ?) ~
  57. STARTED = State('Started', QUEST)3 z9 I8 P- I/ `6 c8 P' V/ i
  58. COMPLETED = State('Completed', QUEST)/ ~8 X' C2 f3 H4 {: U0 |4 F! v  F1 I
  59. 7 S: r% c4 a2 I7 u
  60. QUEST.setInitialState(CREATED)
    " M; N4 k5 e9 Z' r* }" p
  61. QUEST.addStartNpc(7056)
    * o6 V# ]; s6 {. @& G( G
  62. QUEST.addStartNpc(7012)
    5 L( ?# e* C3 I0 i  Q* `( ~  E: @
  63. QUEST.addStartNpc(7009)
    9 p, ^# _* f8 ~& v
  64. QUEST.addStartNpc(7011)2 V# e  d" h, F7 u4 T" J

  65. 3 k; u8 p5 P$ B; K6 k6 u
  66. STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)6 e' k6 y' z8 h+ _) Q( l* d% ?
  67. STARTED.addKillId(KELTIR_NPC_ID)
    & b# k* ]9 D  m/ ^; h! V
  68. STARTED.addTalkId(7056)8 `% K, A0 ]- _* }) ?( R" F4 W
  69. STARTED.addTalkI d(7012)0 ]! w- Y/ @: U& i6 b
  70. STARTED.addTalkId(7009)4 j$ k5 j6 V1 U$ r+ c3 H7 v  I
  71. STARTED.addTalkId(7011)
Скопировать код

$ u% b3 y+ T& d5 ^
) q$ k* V6 O- G. [; K+ v8 R0 u
Чтобы ответить, вам надо авторизироваться в системе Вход | Зарегистрироваться

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

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

638638758

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

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

admin@artace.ru Онлайн

QR-код

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