Top.Mail.Ru

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

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

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

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

x
Хроники        Interlude3 o% y& s- y- E' |- T4 L
Сборка        L2j' r" j+ A- t  T; r% m4 W
Обратите внимание: в файле htm стартового NCP обязательно должна быть ссылка на квест:
* t0 Z" Z1 r! ?& D! A' d, W- M* v
  1. STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код
Для этого квеста больше ничего не надо. Все необходимое для корректной работы квеста уже добавили. Вот полный текст квеста:
. J2 j  q2 |0 G( d3 H/ T2 g% F  S5 Q3 t' m# J
  1. if getCount(st) >= 4 :1 t. u$ q; G; O; H' u
  2. completed(st)
    & Z; f: [6 q% M; z& G$ z, P
  3.   return
    / o0 }. B1 G+ s; `5 z" f# c

  4. 8 P' U: T% O# C- ]
  5. class Quest (JQuest):
    5 j. N5 Z8 @5 E, {
  6.   def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)% S. J4 |4 S6 Z7 G
  7.   def onEvent (self,event,st):
    9 s) |0 @* G4 H1 d
  8. id = st.getState()6 s- b: O- _1 n. `% f
  9. if   id == CREATED  : st.setState(STARTED)
    / l5 D! Q5 t# }: B( ]8 L+ e9 y
  10. elif id == COMPLETED: pass
    " U% U' M, ?. z# r1 E1 W; h
  11. elif id == STARTED  : check(st)  ^! r. a  E: ?. _9 u" Z
  12. return
    4 @4 ~* K: p. ]& Y% q
  13. - V) Z. V- S' D0 K$ k
  14. QUEST     = Quest(201,"Tutorial", "Tutorial quest")
      B9 O) S+ B3 A( ?+ W9 [
  15. CREATED   = State('Start',     QUEST)9 u7 i; s' ^% C# O* C
  16. STARTED   = State('Started',   QUEST)
    1 ]1 |3 s' r  u
  17. COMPLETED = State('Completed', QUEST)
    . F# T  Z+ S  G* Z% G
  18. 0 r) ?7 V2 @) x0 A. K; X* G
  19. QUEST.setInitialState(CREATED); C9 @9 x; |" y" c  `. d1 r
  20. QUEST.addStartNpc(7056)% c. v; X! E/ K
  21. STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код
Теперь рассмотрим, как это работает.# L+ _4 \4 l% J- n
Игрок подходит к начальному NCP (в данном случае 7056), нажимает на «Quest». Квест будет создан и состояние квеста перейдет к CREATED и игроку будет показана страничка Start.htm с описанием квеста. Тогда метод onEvent, поле открытия странички Start.htm переведет состояние квеста в STARTED и игроку будет показана страничка Started.htm, где будет опсание того, как найти keltirs и .т.д.5 b; d' R( T8 Z/ @2 _$ N" s" K. Q

( z* c7 y& ~, T1 w: _& P
& c! c& I) Y9 d/ f4 ?* C
При состоянии STARTED будет зарегистрирован дроп «fangs» при убийстве keltirs. Игрок может вернуться к стартовому NCP и спросить о квесте – метод onEvent будет вызван снова. Если у игрока не хватает необходимого количества предметов, то метод check() не переведет квест в следующее состояние и Started.htm будет показана снова. Но если игрок собрал необходимее количество предметов (в данном случае 4 клыка), то метод check() вызовет метод completed() который переведет квест в новое состояние COMPLETED, заберет все клыки, даст карту мира, т.к. это награда за квест, покажет Completed.htm и завершит квест./ o, v7 u8 x6 o/ E- }4 J

8 n2 N+ Y. x5 Z2 V* O! m

4 l6 l4 O; s% e& aТеперь давайте сделаем наш квест более похожим на то, что он должен из себя представлять.
" ?3 \2 `5 u' M; j: Y! eПрежде всего у нас есть 3 метода для объявления их в Яве – onTalk, onKill и onEvent. Если методы onTalk и onKill не объявлены, то за них все будет делать метод onEvent, т.е. определять квестовых монстров и вызывать диалоги NCP. Есть примечание, методы onTalk и onKill будут вызывать только диалоги с NCP в зависимости от текущего состояния квеста. Метод onKill будет вызываться только тогда, когда мы убиваем квестового монстра.  C  ~) n; t6 G9 n0 H

4 m9 L  z# |( T: [' M- [

% ~/ U( }6 ^& L4 o5 pДавайте рассмотрим как вызывается метод onKill при убийстве keltir в состоянии квеста STARTED:
7 M! z% J4 }( J6 ?  y; J* f
  1. STARTED.addKillId(KELTIR_NPC_ID)
Скопировать код
и метод onKill в классе Quest:7 n: e0 L' Y1 |1 d6 s' O1 t7 t

6 \% D/ W9 Z1 v) p0 o
  1. class Quest (JQuest):5 ^$ C8 F# p; \9 G0 r3 {) z& D( H
  2.   ...
    2 K* q) R' P$ i6 j
  3.   def onKill (self,npcId,st):
    1 k; D1 `4 b# X
  4. if npcId == KELTIR_NPC_ID:4 j0 L0 c: w. V; G0 i, A1 p
  5.    n = getCount(st)
    ; M+ m  h& o3 S, B4 N
  6.    if   n == 0:
    ( [9 d; L; P& Z" C7 M* @2 [4 ^
  7.        return "Chat0.htm"* `& }+ T7 c- T3 k( ]
  8.    elif n == 1:
    ; n8 G3 Q5 R- ~6 V) c! h: L
  9.        return "Chat1.htm": s% A9 P. L1 p( T) @. N) r$ m
  10.    elif n >= 4:
    ' b5 S. j( M$ {% ]$ p
  11.        return "Chat4.htm"
    : d, K0 o# h3 W" l$ ]& [) |
  12.    return "Collected "+str(n)+" of 4 fangs"
    ) C7 e1 q% l+ S: v' t
  13. return
Скопировать код
Метод onKill (а так же метод onTalk) имеет следующие параметры:
* N; X$ q: ~  B: v* b) `/ ^+ @3 P3 _& d& B, @# Q/ s
2 w9 [+ s6 m6 c  M* r* H
• self – квест
& N# F( l: h/ S4 J7 W• npcId – ID NCP, которого мы должны убивать (если это метод onTalk, то ID того NCP, с которым мы должны поговорить).& a6 G3 h$ T2 g
• st – текущее состояние игрока./ L% }8 K# B1 l2 G8 L6 u: }  e
5 @8 @, M1 Z3 @- Q
1 O7 ~6 b0 A2 m! i8 \8 L" r! s
В этом методе мы проверяем и отмечаем, является ли убитый NCP keltir’ом. В основном эта проверка не нужна, т.к. у нас только KELTIR_NPC_ID.
6 Z3 X3 Z- e' w* w9 S" ^- Y7 k$ F! G6 e

3 c& Q0 ]% ^2 v6 g. _; `Затем проверяем количество предметов (в данном случае количество клыков), и если их вообще нет, то возвращаем строку "Chat0.htm", если только один предмет, то возвращаем строку "Chat1.htm", если же предметов 4 или больше, то "Chat4.htm". Если строка возвращена из методов onEvent, onKill или onTalk, то сервер покажет соответствующие htm. В Chat0.htm может иметь следующий текст: «Вы не имеете ни одного клыка, возвращайтесь позже, когда соберете 4 штуки и бла, бла, бла…», в Chat1.htm может быть следующий текст: «У Вас всего 1 клык, по этому соберите еще…». В Chat4.htm – «Вы собрали необходимое количество предметов, возвращайтесь к вашему тренеру, что бы завершить квест…»( d9 D. g1 S% H2 Q
- p* y; [; B0 D+ R. n  t  \% B
$ J' V" i4 l/ ?" I
Примечание: если в строка return начинается с "<html>", то будет показана страничка html с текстом, который стоит далее. Так вместо:- p/ }4 H: ~, C( u
return "Chat4.htm"
" a) ~" x* p/ v
8 e+ ^, j7 u7 F8 s" y# [4 Q. X

& {. J% h- i3 z: e/ s! U3 J8 Uможно поставить:& z8 B4 p" U0 t; r
  1. return "<html><body>Return to your trainer to complete the quest</body></html>"
Скопировать код
Так же если строка заканчивается без .htm или в начале нет <html>, то текст будет выведен, как системное сообщение в окне чата. В нашем случае мы сделаем так, что бы при каждом убийстве keltik выводилось системное сообщение: «Собрано N из 4-х клыков».4 a+ f. n' U  T) h7 p. t  N

5 N) A  ]4 r' m+ i  E- R

& O, `1 m5 ]3 l4 {! TНаш код для onKill имеет один недостаток. Он будет постоянно показывать Chat0.htm, Chat1.htm и Chat4.htm, нам же необходимо, что бы Chat0.htm и Chat1.htm показывались только один раз. Как нам это сделать? С помощью переменных.
* z9 [) _( `2 k9 c
, f0 E2 }; d+ @1 G. U

. U8 ]! R4 d% l, GВ каждом квесте строки могут храниться с помощью переменных. Эти переменные сохраняются в Вашей БД. В каждом методе мы можем назначить, прочитать и удалить переменные. Давайте изменим метод onKill, так что бы каждый диалог вызывался только один раз.
3 h2 y0 d+ X9 i0 z$ j! J: V" T
  1. def onKill (self,npcId,st):
    4 i# d* E, o  p
  2. if npcId == KELTIR_NPC_ID:) F( h+ {, m* c- E5 \7 c
  3. n = getCount(st)
      f7 @8 Y' F( q5 K
  4. if n == 0:2 \" F3 ~* z& [* V" K
  5. if st.get('chat0') == None :  J- P& a! ]% z. M# L0 B! Q
  6. st.set("chat0", "true")9 Q" N. l0 q( m: m* n# m
  7. return "Chat0.htm"# p! \: ?: g$ T* T/ w4 |
  8. elif n == 1:$ }( N0 L5 T, h$ K& G" H$ y) x( n# ~
  9. if st.get('chat1') == None :
    : G' g$ i: J: x6 ]: Y# h. a" k
  10. st.set("chat1", "true")
    & N' T" z! ~1 c
  11. return "Chat1.htm"* Z* ?1 K% n# L* @
  12. elif n >= 4:
    % V4 @5 ]4 F2 e7 ]9 z1 q- s
  13. return "Chat4.htm", ]$ I2 Q" O1 [" |, z) z8 d! H1 s
  14. return "Collected "+str(n)+" of 4 fangs"
    3 `8 Q# V3 i! K' p) ~, Q
  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.9 a. s* T6 X6 ~' I" y9 V
7 }: U: L, V/ i& I: \& @5 B
1 K/ D8 ~: q7 d: e3 v7 {6 x
Вот конечный рабочий вариант квеста:
/ v3 v, c- o0 |% C8 O
  1. import sys
    " ]8 L' _( G0 F( S
  2. from net.sf.l2j.gameserver.model.quest import State& ?# M0 r) y3 }, [; w
  3. from net.sf.l2j.gameserver.model.quest import QuestState
    % h: b+ k1 g, U
  4. from net.sf.l2j.gameserver.model.quest.jython import QuestJython as JQuest
    8 k# y8 s% g7 U/ z" s
  5. 8 V8 d; b/ `- y2 W! E, V
  6. KELTIR_NPC_ID = 12082
      J7 O* z- ?) g7 D8 b0 D, X- e
  7. FANGS_ITEM_ID = 1859/ @. Q! M0 Z. s5 A% {
  8. DROP_RATE    = 500000
    # p' J8 N) y+ J

  9. - I  O- o1 N+ f
  10. WORLD_MAP_ITEM_ID = 16656 D" ?7 E2 ?" p; L
  11. 7 L3 L5 [6 }% H# e( |
  12. def getCount(st) :
    . \: Y' g- r) o
  13. return st.getQuestItemsCount(FANGS_ITEM_ID)
    5 R, L, T4 C1 T2 o% P8 o, r" A
  14. ( i+ ]" s  ?, O: C9 K. m1 b
  15. def completed(st) :% s2 H. s" R* D* J% {: F
  16. st.setState(COMPLETED)3 P$ e0 Q! L6 n3 D# o& T6 d7 A
  17. st.clearQuestDrops()
    # J) ^* ?, N1 C# |
  18. st.takeItems(FANGS_ITEM_ID,-1), O: _2 h$ T* I1 h2 A
  19. st.giveItems(WORLD_MAP_ITEM_ID,1)* s! ^/ \. I# f, B2 `
  20. st.exitQuest(False)
    ; x; k& I; E' Y7 b
  21. return9 M- O/ n% a- z' D
  22. 3 @6 @: U- V) }6 W9 H' c
  23. def check(st) :1 v0 Z# Q" J* K, B2 q, K# M
  24. if getCount(st) >= 4 :
      D- \/ g3 c" A6 U+ @0 ^
  25. completed(st)
      \* U# l2 x2 A# U$ a* U  R5 R/ A
  26. return6 i) R( Q! F, R9 ], t0 X8 a/ k

  27. * K# e8 b$ g6 i6 g* \
  28. class Quest (JQuest):
    2 ?8 |6 g+ b# R

  29. # z7 Z/ R& Z# a* I/ [
  30. def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)
    $ |/ H3 D  d0 S& F& G: v+ z
  31. , B  F* Q5 m, o4 }8 {
  32. def onEvent (self,event,st):5 [% S5 Q& ]+ P# a" M) y* P) j
  33. id = st.getState()3 p. i( U  m$ A' M2 N2 [! d
  34. if id == CREATED : st.setState(STARTED)
    ' g: q& Y% S) m
  35. elif id == COMPLETED: pass
    ' k; |" H- g5 f" A: w; D
  36. elif id == STARTED : check(st)( Q; P  h  S% l- z. |- P7 D4 S3 {0 Z, b5 d
  37. return
    ; i! U6 J% f6 {0 I6 y" I# I6 I
  38. 1 L' \0 V( A) v% {8 A; }2 h
  39. def onKill (self,npcId,st):7 I$ u  H& X1 x/ J
  40. if npcId == KELTIR_NPC_ID:2 Y! g" j. b+ G" K
  41. n = getCount(st)
    * G, x  w, }+ u6 Q$ i* ^
  42. if n == 0:9 y) J- ?9 w+ a3 ]: O% H  t
  43. if st.get('chat0') == None :
    # u0 n) ]+ p9 f' a4 T
  44. st.set("chat0", "true")# z2 X; ?5 |5 a& S) H
  45. return "Chat0.htm") X! G; g- O4 H
  46. elif n == 1:/ O1 w1 e3 W; q  d3 W! t$ t
  47. if st.get('chat1') == None :) r7 j/ {/ S' n+ l& j- g
  48. st.set("chat1", "true")
    ; S, Y) z: `# e: S7 E, p5 P
  49. return "Chat1.htm"
    5 X+ A4 [% r/ G% C: H! q
  50. elif n >= 4:& i4 n! @4 r: g' c' x
  51. return "Chat4.htm") b2 s: R0 H( J/ H7 l1 w4 r' K
  52. return "Collect "+str(n)+" of 4 fangs"
    2 Z1 ]7 E* a1 {3 i9 G
  53. return
    2 _) p7 v. g* q
  54. - Q4 w/ X7 F; |1 J0 E( N  ~! w+ Y
  55. QUEST    = Quest(201, "Tutorial", "Tutorial quest")
    ; p% Q# h5 E5 q3 b
  56. CREATED = State('Start',    QUEST)# f/ I% t  {4 @1 a# o$ R; Q
  57. STARTED = State('Started', QUEST)
    - s1 u/ {: f: s, j) s$ T
  58. COMPLETED = State('Completed', QUEST)
      |/ G9 D2 h, K/ U) q6 ?

  59. ; G% {8 e4 q5 B
  60. QUEST.setInitialState(CREATED)% X) t1 E% K) i/ F0 m' I& P' ?
  61. QUEST.addStartNpc(7056), L; b( h  f2 d7 P9 ^- H7 r( G& G
  62. QUEST.addStartNpc(7012)5 S: C, ^* z+ L0 }
  63. QUEST.addStartNpc(7009)
    & U' n* g8 E2 n3 r. ^1 n
  64. QUEST.addStartNpc(7011)
    ; e7 r6 ~$ C" g

  65. 2 U+ ]+ L2 C1 M% L' @
  66. STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)- v; @3 z7 ?( L6 ^
  67. STARTED.addKillId(KELTIR_NPC_ID)
    8 O5 g: k+ g+ b) G% ]4 E$ d
  68. STARTED.addTalkId(7056): b$ J0 H/ _! a* B/ G
  69. STARTED.addTalkI d(7012)& O7 f& l3 ~7 R! _5 O
  70. STARTED.addTalkId(7009)
    : U: g, B8 O* [' K- y- [
  71. STARTED.addTalkId(7011)
Скопировать код
3 `3 z8 b0 L+ |, q  h: e3 e3 A

1 \$ U- {/ y0 M' h& \) ^
Чтобы ответить, вам надо авторизироваться в системе Вход | Зарегистрироваться

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

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

638638758

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

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

admin@artace.ru Онлайн

QR-код

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