Top.Mail.Ru

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

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

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

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

x
Хроники        Interlude
2 i3 M- c0 M, R5 v! VСборка        L2j  w5 S9 _7 w" A: z& Y" n) g
Обратите внимание: в файле htm стартового NCP обязательно должна быть ссылка на квест:
1 n1 B! ?, e, i( ?0 J( h+ X# T
  1. STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код
Для этого квеста больше ничего не надо. Все необходимое для корректной работы квеста уже добавили. Вот полный текст квеста:
9 u1 v0 X% y; K# x7 o. ]
" J- E% g8 y+ i5 Q7 C
  1. if getCount(st) >= 4 :
    ' Z6 V' r- x4 W/ O
  2. completed(st)
    2 |/ @( K0 |4 r0 {) ~
  3.   return
    7 E( t3 Q' T. [( k% X7 L; `

  4. ' e" c; I% A* V. ^7 @8 o
  5. class Quest (JQuest):4 T# Z/ M$ i7 `2 Q- R# n
  6.   def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)
    ( i) o& Y+ w8 R3 m2 |
  7.   def onEvent (self,event,st):! e( T: ]  M& f7 }( K; Z
  8. id = st.getState()
    ! p* v3 r7 Q7 A4 s3 e+ K3 _
  9. if   id == CREATED  : st.setState(STARTED)4 V6 {' @* R6 r6 e
  10. elif id == COMPLETED: pass
    ! o2 o& o' v% ]. {! O4 Y
  11. elif id == STARTED  : check(st)
    % k1 B7 `1 Z3 a, ?' j' `
  12. return
    $ T% u) V) T" R7 j" B2 Q0 s( `
  13. 5 T8 N: r0 |$ F& }- a
  14. QUEST     = Quest(201,"Tutorial", "Tutorial quest")
    6 i4 F! p/ F' Q8 F4 ]7 b
  15. CREATED   = State('Start',     QUEST)
    7 |9 o- h6 E; I: o0 L+ ?
  16. STARTED   = State('Started',   QUEST)' {& J# \3 V; `/ X1 ]. j
  17. COMPLETED = State('Completed', QUEST)" U% [4 O! w6 B7 f: {0 W1 _0 l% L1 ~
  18. 1 R5 L* L* x$ _5 d% Q7 t. u6 h
  19. QUEST.setInitialState(CREATED)
    ) z5 s" s! _9 K$ j, n( j
  20. QUEST.addStartNpc(7056)
    4 O' \  ?3 y7 |1 J
  21. STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код
Теперь рассмотрим, как это работает.
% T  M! q4 }5 U5 r, k3 G% SИгрок подходит к начальному NCP (в данном случае 7056), нажимает на «Quest». Квест будет создан и состояние квеста перейдет к CREATED и игроку будет показана страничка Start.htm с описанием квеста. Тогда метод onEvent, поле открытия странички Start.htm переведет состояние квеста в STARTED и игроку будет показана страничка Started.htm, где будет опсание того, как найти keltirs и .т.д.$ q8 U4 n) o# j. n) }

' M( L3 L( t; _. I  I' G6 y! {/ y9 ~
" L  N5 O' _3 B, g
При состоянии STARTED будет зарегистрирован дроп «fangs» при убийстве keltirs. Игрок может вернуться к стартовому NCP и спросить о квесте – метод onEvent будет вызван снова. Если у игрока не хватает необходимого количества предметов, то метод check() не переведет квест в следующее состояние и Started.htm будет показана снова. Но если игрок собрал необходимее количество предметов (в данном случае 4 клыка), то метод check() вызовет метод completed() который переведет квест в новое состояние COMPLETED, заберет все клыки, даст карту мира, т.к. это награда за квест, покажет Completed.htm и завершит квест.5 @1 \1 B1 n+ c4 Q# S4 Z
* g4 \$ E# Z5 O
* J6 E# c9 X+ n, G0 f4 B4 N0 Z
Теперь давайте сделаем наш квест более похожим на то, что он должен из себя представлять.1 x5 f+ q7 H. v% S- X% V
Прежде всего у нас есть 3 метода для объявления их в Яве – onTalk, onKill и onEvent. Если методы onTalk и onKill не объявлены, то за них все будет делать метод onEvent, т.е. определять квестовых монстров и вызывать диалоги NCP. Есть примечание, методы onTalk и onKill будут вызывать только диалоги с NCP в зависимости от текущего состояния квеста. Метод onKill будет вызываться только тогда, когда мы убиваем квестового монстра.: C$ `/ j& o8 r, y  q2 f
% `/ {! P2 y2 n- H$ ?8 G& f( k% [

/ C3 v& B$ l: ?& N# E( ]5 zДавайте рассмотрим как вызывается метод onKill при убийстве keltir в состоянии квеста STARTED:
" y, K9 X% F  }( R) n! M* Z3 L
  1. STARTED.addKillId(KELTIR_NPC_ID)
Скопировать код
и метод onKill в классе Quest:
4 ~$ l/ Y. Z1 R! P: h+ _0 b' X& a
* d1 D) d& O3 y
  1. class Quest (JQuest):3 n2 a9 t  x7 V$ s
  2.   ...
    7 B3 ~. U7 W, L1 W; @/ O( E
  3.   def onKill (self,npcId,st):
    , A5 b" X: E, y5 U  `# E
  4. if npcId == KELTIR_NPC_ID:$ T/ S  J6 `0 b8 ^) h; r
  5.    n = getCount(st)
    ) z" S1 z8 D" |" F5 _
  6.    if   n == 0:
    3 X/ i8 Q: r. H! |6 [8 S' p& Z! l
  7.        return "Chat0.htm"- l* q2 x4 R, V
  8.    elif n == 1:
    7 g2 }6 `) B  b! s% J/ ~
  9.        return "Chat1.htm"4 L7 z! B5 }  Z4 V/ X( m( a( R, r& d
  10.    elif n >= 4:
    ' s, x, a# s; ]- ?
  11.        return "Chat4.htm"
    , _& m) A9 [7 O6 m) E
  12.    return "Collected "+str(n)+" of 4 fangs"
    ' d- r" C9 m" \9 h7 f/ p
  13. return
Скопировать код
Метод onKill (а так же метод onTalk) имеет следующие параметры:3 U! P* Y7 r8 }4 |1 I8 F
- x. D; [7 u1 @3 U3 k6 w
  t9 w8 _3 X" F& Z5 h
• self – квест
: V8 k: `. G3 N3 V9 g• npcId – ID NCP, которого мы должны убивать (если это метод onTalk, то ID того NCP, с которым мы должны поговорить).
3 p3 U: i+ Q7 k" p& Z• st – текущее состояние игрока.
" r9 q! L# ~6 e& W5 ~* {
1 F4 E9 I# z+ C) p4 W3 g
! b) c* @% K. \2 w3 |! i. l0 @2 r
В этом методе мы проверяем и отмечаем, является ли убитый NCP keltir’ом. В основном эта проверка не нужна, т.к. у нас только KELTIR_NPC_ID.
* I0 o, ~' i2 {0 t9 T' h8 ]$ T5 w4 r. |6 G( F; Y4 f" U
  P, i! Y4 U. R( `
Затем проверяем количество предметов (в данном случае количество клыков), и если их вообще нет, то возвращаем строку "Chat0.htm", если только один предмет, то возвращаем строку "Chat1.htm", если же предметов 4 или больше, то "Chat4.htm". Если строка возвращена из методов onEvent, onKill или onTalk, то сервер покажет соответствующие htm. В Chat0.htm может иметь следующий текст: «Вы не имеете ни одного клыка, возвращайтесь позже, когда соберете 4 штуки и бла, бла, бла…», в Chat1.htm может быть следующий текст: «У Вас всего 1 клык, по этому соберите еще…». В Chat4.htm – «Вы собрали необходимое количество предметов, возвращайтесь к вашему тренеру, что бы завершить квест…»
# G; K9 e5 t, Y; E
4 D1 {; W: G! X7 ?7 ^) v

& R- c& R: [9 AПримечание: если в строка return начинается с "<html>", то будет показана страничка html с текстом, который стоит далее. Так вместо:
( q7 T3 l, _6 c3 h3 I' S0 Ureturn "Chat4.htm"
, H* p1 n; v1 O5 ]; \, m, J' c, L: y! Y+ J

7 G* X$ k8 E8 r! Dможно поставить:
" m( |3 x: W* X1 ~6 h$ s
  1. return "<html><body>Return to your trainer to complete the quest</body></html>"
Скопировать код
Так же если строка заканчивается без .htm или в начале нет <html>, то текст будет выведен, как системное сообщение в окне чата. В нашем случае мы сделаем так, что бы при каждом убийстве keltik выводилось системное сообщение: «Собрано N из 4-х клыков»." A# R: j+ d  C4 m' _
3 g2 W3 T# `6 D: l1 Z1 e
: [2 r" F2 \5 |: K1 F# ?+ i. P: ]
Наш код для onKill имеет один недостаток. Он будет постоянно показывать Chat0.htm, Chat1.htm и Chat4.htm, нам же необходимо, что бы Chat0.htm и Chat1.htm показывались только один раз. Как нам это сделать? С помощью переменных.
' K! C7 j! Q* \9 u1 }' ?. U
6 c3 a3 W, b8 y5 W/ F

# {0 P! d+ }) gВ каждом квесте строки могут храниться с помощью переменных. Эти переменные сохраняются в Вашей БД. В каждом методе мы можем назначить, прочитать и удалить переменные. Давайте изменим метод onKill, так что бы каждый диалог вызывался только один раз.0 J$ ]7 ~  D& ?- \% O7 }6 i( `
  1. def onKill (self,npcId,st):
    / ?" k" ^! p% p! @
  2. if npcId == KELTIR_NPC_ID:
    3 d, Y; E, `  Q7 U' M
  3. n = getCount(st)$ K: o4 V! |3 ?: {- a% c6 b
  4. if n == 0:" h# l/ N% q' t; u& T
  5. if st.get('chat0') == None :
    5 D! e8 p" J4 Z* S
  6. st.set("chat0", "true")- o/ I  ^: [! R% y, W
  7. return "Chat0.htm"# o; G) q7 `! [( J$ h+ v- e
  8. elif n == 1:
    # E" m/ ]6 e0 K, E' ?9 M
  9. if st.get('chat1') == None :
    ) S8 ?" J( t- q  o  l" F2 r
  10. st.set("chat1", "true")
    ' M. W( M1 H& s
  11. return "Chat1.htm"
    ; H6 X4 n6 p3 t8 D6 r" r  W) z
  12. elif n >= 4:
    & r" N  t: g. w. w. I" g
  13. return "Chat4.htm"
    ' K  h9 B3 M, A
  14. return "Collected "+str(n)+" of 4 fangs"; i8 k8 ?4 X( J) Q. Y: b- [& T$ 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.
, a. R2 N* X: P
* A5 q# ~3 z: }) Y+ g

2 Y0 G, b0 I7 yВот конечный рабочий вариант квеста:
$ j# s  y+ R: {2 G# g& U" L
  1. import sys
    ; K8 _, v7 z) y* V; N  |+ ]
  2. from net.sf.l2j.gameserver.model.quest import State# o  e2 o' Y2 \9 k
  3. from net.sf.l2j.gameserver.model.quest import QuestState8 j' U3 p8 r7 g
  4. from net.sf.l2j.gameserver.model.quest.jython import QuestJython as JQuest3 D) `+ t5 G" w" j8 q1 ^& t/ U, \' C" N
  5. 3 P4 {5 m! g/ N  T
  6. KELTIR_NPC_ID = 12082
    5 w6 x  ]$ K# A$ H- m$ [3 D+ @4 t
  7. FANGS_ITEM_ID = 1859
    # u* E6 w% V( j4 f7 b1 O
  8. DROP_RATE    = 500000
    1 o( T/ }/ G0 B% W& }7 r/ P" f

  9.   @- U8 {  V& D
  10. WORLD_MAP_ITEM_ID = 1665
    / k7 x* q/ {8 I
  11. 1 E; v- N7 F4 ^4 H" F
  12. def getCount(st) :
    8 O# b% c& P% q2 ?( P
  13. return st.getQuestItemsCount(FANGS_ITEM_ID)# O+ g. I3 k( z! P4 m& ?
  14.   J) T0 a. g4 h6 z3 B" @7 I5 ?
  15. def completed(st) :
    / G3 h  q7 P, M9 n
  16. st.setState(COMPLETED)+ j8 j' @: ^& y. u7 Y4 H
  17. st.clearQuestDrops()$ a0 J1 l2 B2 ~4 V$ g
  18. st.takeItems(FANGS_ITEM_ID,-1)4 A% g3 y) `. n' m
  19. st.giveItems(WORLD_MAP_ITEM_ID,1)
    . x# v: m3 T4 T2 h
  20. st.exitQuest(False)
    : }4 A  d, B1 J( o) `  {
  21. return
    6 V+ [1 }2 V4 j( R
  22. $ l- j$ f4 ^7 ~9 |& W
  23. def check(st) :6 i: l/ X( Z1 m% m+ V
  24. if getCount(st) >= 4 :! Q4 Z( e  L1 g! Q! {1 a
  25. completed(st)/ L, C) G5 c6 |  A9 `# G
  26. return  Z/ d) H: A0 w1 s; }. S4 b6 O

  27. ( I4 i% A9 T$ r1 m/ B! c
  28. class Quest (JQuest):
    % ~; o. w6 I8 d9 N* K. p5 a$ \

  29. ( x7 P6 d, V0 z1 s. V9 d
  30. def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)9 c  l% H$ x. A' x

  31. ! v. n& O9 n* n3 l0 i  J
  32. def onEvent (self,event,st):- f0 X# R7 u% d$ j4 E' ~; R
  33. id = st.getState()+ F8 F9 k0 u0 T3 N8 V$ E( _4 Z
  34. if id == CREATED : st.setState(STARTED)
    5 j9 l! s9 b8 H+ Z, R( [" s
  35. elif id == COMPLETED: pass2 s& U; J  y% x5 B7 ?
  36. elif id == STARTED : check(st)8 K0 j. B' X6 I; d* E: I0 b4 R
  37. return% G, c% h' s2 ^
  38. - W% `2 ?4 P4 ^5 \: J
  39. def onKill (self,npcId,st):1 n# k; E# v8 h* D, N
  40. if npcId == KELTIR_NPC_ID:
    4 U% e  B/ q0 t! l
  41. n = getCount(st), F- M4 u$ z' F2 q, w* L
  42. if n == 0:4 m& N/ n: l$ @! h  S' p7 n, t
  43. if st.get('chat0') == None :1 Y  M) Q2 _  x6 M9 I2 e% r
  44. st.set("chat0", "true")
    % j6 m+ Q% T, p7 [  y" i) i; G
  45. return "Chat0.htm"3 ]5 k# g0 k  ?9 f# S. [1 X& `  _- ^
  46. elif n == 1:
    ( G" z- G8 g; Z1 J( A# E
  47. if st.get('chat1') == None :
      M- x" }% ?: o' B0 A
  48. st.set("chat1", "true")' N3 X- K$ t; H& @6 D  |8 u
  49. return "Chat1.htm"
    - s3 l3 R) H: U4 t! ?
  50. elif n >= 4:) z: c4 {, }, F# e; P: @- L
  51. return "Chat4.htm"
    0 g" Z( c  O5 x: t* X. ?/ t, T
  52. return "Collect "+str(n)+" of 4 fangs"
    - Y  Q$ z$ i3 G
  53. return
    / g( x6 j. V9 d9 O! k2 H
  54. # E: \  V! x. b
  55. QUEST    = Quest(201, "Tutorial", "Tutorial quest")8 A9 F1 p+ z/ c: g* I
  56. CREATED = State('Start',    QUEST)
      N# b( O# E8 a* r- m+ |
  57. STARTED = State('Started', QUEST)
    " R( q& S- Q2 D8 T: W5 K9 L" m
  58. COMPLETED = State('Completed', QUEST)+ q0 ]& x* j! ]. B
  59. , y% m, {6 v: l& T8 F
  60. QUEST.setInitialState(CREATED)
    - K+ v: H) m0 G+ S$ L8 V
  61. QUEST.addStartNpc(7056)
    $ |3 i3 o1 U9 w7 ~; p1 G2 i0 I
  62. QUEST.addStartNpc(7012)$ K4 K; v7 R, f6 h) e; K7 b
  63. QUEST.addStartNpc(7009)1 K6 y; B/ T& n+ l% `2 M* B% C+ h* _
  64. QUEST.addStartNpc(7011)+ z$ D8 n) N/ a% M, \9 Q. Y
  65. " c& W5 \! P6 x1 g1 @0 F
  66. STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)6 s9 u2 B; N! i0 i% ~4 G
  67. STARTED.addKillId(KELTIR_NPC_ID)
    * Y  C: I8 q  i+ |  \
  68. STARTED.addTalkId(7056)( x: @) ]7 I, S' ]! K
  69. STARTED.addTalkI d(7012)7 V2 E, C+ b# p- [0 J
  70. STARTED.addTalkId(7009)2 n% X$ A: d- |/ g8 e; V7 z2 A7 u
  71. STARTED.addTalkId(7011)
Скопировать код
+ p0 @* x) J) h* P! A( y! Z7 f) B

2 ~1 R0 x" X; {; T0 @, J
Чтобы ответить, вам надо авторизироваться в системе Вход | Зарегистрироваться

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

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

638638758

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

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

admin@artace.ru Онлайн

QR-код

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