Top.Mail.Ru

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

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

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

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

x
Хроники        Interlude
. O  l7 |  k) }8 X; ~: f3 n  [Сборка        L2j
. ]* p8 M. f$ d& p* q. WОбратите внимание: в файле htm стартового NCP обязательно должна быть ссылка на квест:( T  s4 j) ?$ d" A6 @
  1. STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код
Для этого квеста больше ничего не надо. Все необходимое для корректной работы квеста уже добавили. Вот полный текст квеста:
. J$ B& d5 p2 R8 d8 v
3 d' l8 A0 E& p4 u
  1. if getCount(st) >= 4 :# L( _8 i: H" u
  2. completed(st)
    ) B0 k; f. h0 o2 @8 j; f
  3.   return! v$ Q/ G  K. G& V. R7 {

  4. " g5 ~: b" t1 Z" z0 ^
  5. class Quest (JQuest):# C8 c& F$ W3 B
  6.   def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)1 I5 k* |# X, t- Y& q2 E
  7.   def onEvent (self,event,st):
    # Z4 h* z) c* v# h
  8. id = st.getState()8 `2 D0 z4 K1 [; |2 B
  9. if   id == CREATED  : st.setState(STARTED)2 L9 p! A/ F( O
  10. elif id == COMPLETED: pass1 {5 Y; o' V' A  `' I: C* Q$ s
  11. elif id == STARTED  : check(st)4 b+ h4 K( ?% S
  12. return
    # s. q. Z9 p% ?) y2 h. Q2 o! T) O

  13. / V4 `' g) a/ E- s
  14. QUEST     = Quest(201,"Tutorial", "Tutorial quest")
    7 D+ ^3 @+ ?1 b0 F# L$ h: }* P% Q
  15. CREATED   = State('Start',     QUEST)* D/ @& B: v) d* i! M
  16. STARTED   = State('Started',   QUEST)9 O- c( C2 l1 D5 J0 |: [* j' l
  17. COMPLETED = State('Completed', QUEST)
    " A1 U5 z: A( w) J0 p( k
  18.   l3 @4 E$ c0 d: B2 H5 q4 j9 c
  19. QUEST.setInitialState(CREATED)+ E+ E( }+ C& g8 s3 l
  20. QUEST.addStartNpc(7056)
    ) [+ l1 Q2 E9 O' T1 n8 B" N6 l
  21. STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код
Теперь рассмотрим, как это работает., ]' Z3 m4 t2 l1 O5 C0 u
Игрок подходит к начальному NCP (в данном случае 7056), нажимает на «Quest». Квест будет создан и состояние квеста перейдет к CREATED и игроку будет показана страничка Start.htm с описанием квеста. Тогда метод onEvent, поле открытия странички Start.htm переведет состояние квеста в STARTED и игроку будет показана страничка Started.htm, где будет опсание того, как найти keltirs и .т.д.  J- ~, d' \9 Z7 X4 I
' |$ u, X; L( ~/ I
. x) p) N0 N6 F) ~
При состоянии STARTED будет зарегистрирован дроп «fangs» при убийстве keltirs. Игрок может вернуться к стартовому NCP и спросить о квесте – метод onEvent будет вызван снова. Если у игрока не хватает необходимого количества предметов, то метод check() не переведет квест в следующее состояние и Started.htm будет показана снова. Но если игрок собрал необходимее количество предметов (в данном случае 4 клыка), то метод check() вызовет метод completed() который переведет квест в новое состояние COMPLETED, заберет все клыки, даст карту мира, т.к. это награда за квест, покажет Completed.htm и завершит квест.
- {3 ]1 M% }+ ~+ }1 |7 F7 i5 W. u& e7 }- [2 t

4 i+ @7 w2 Z+ s8 v2 X. b3 vТеперь давайте сделаем наш квест более похожим на то, что он должен из себя представлять.6 p1 ]5 E6 ^4 D( V) N
Прежде всего у нас есть 3 метода для объявления их в Яве – onTalk, onKill и onEvent. Если методы onTalk и onKill не объявлены, то за них все будет делать метод onEvent, т.е. определять квестовых монстров и вызывать диалоги NCP. Есть примечание, методы onTalk и onKill будут вызывать только диалоги с NCP в зависимости от текущего состояния квеста. Метод onKill будет вызываться только тогда, когда мы убиваем квестового монстра.
) H/ s8 Q5 V) u4 p- j8 i5 r2 z  X  ^/ J( T. z

- C$ w" |) M! k* d5 p8 YДавайте рассмотрим как вызывается метод onKill при убийстве keltir в состоянии квеста STARTED:
8 L: ~! |) d. w+ _& L3 a5 v& I
  1. STARTED.addKillId(KELTIR_NPC_ID)
Скопировать код
и метод onKill в классе Quest:, W0 ~6 U; ~# ?1 u( p
  x2 @% N# O5 _7 ^0 y
  1. class Quest (JQuest):
    + ?/ P( [  s. p1 N4 }+ B
  2.   ..." f, A, R$ ?' M+ o
  3.   def onKill (self,npcId,st):4 Y$ i1 K7 d/ k% X" L+ X; ^' q
  4. if npcId == KELTIR_NPC_ID:
    . C' g# O, U8 j0 ]+ V
  5.    n = getCount(st)
    & J/ [& d$ d& C9 a# h
  6.    if   n == 0:  t) v6 B5 f* f) r' \
  7.        return "Chat0.htm"7 Y/ m3 e0 {4 ~
  8.    elif n == 1:* V2 {4 ]$ @/ Y8 I2 T
  9.        return "Chat1.htm"
    $ y( W3 m1 w& C$ m! E. Y9 D! j; o' B
  10.    elif n >= 4:
    ; S/ v6 d- R8 }' |
  11.        return "Chat4.htm". H  W0 u  p3 p0 |5 s
  12.    return "Collected "+str(n)+" of 4 fangs"
    1 [' Z0 l6 Q' C$ x0 l! Q
  13. return
Скопировать код
Метод onKill (а так же метод onTalk) имеет следующие параметры:
# q4 [6 k' U6 |  [. M- r6 K' ?4 e2 ]7 v( H* Z4 l: M. [

8 h9 V7 O0 @+ R# p• self – квест, c- U/ R" O7 T# L
• npcId – ID NCP, которого мы должны убивать (если это метод onTalk, то ID того NCP, с которым мы должны поговорить).
& t: i! ^5 f9 e% P! E+ H' j• st – текущее состояние игрока.
% U! w% f: H/ f# d6 q
, _+ Z0 B" P- w- o. M/ S4 Z
$ K9 @" I* t- b8 h, }. ?
В этом методе мы проверяем и отмечаем, является ли убитый NCP keltir’ом. В основном эта проверка не нужна, т.к. у нас только KELTIR_NPC_ID.
, k9 e9 p$ C, h) f: m9 d4 c: z
$ r- ?  _! a; ]/ _: V1 o; u
1 D. u4 f, l1 E" K  D  U) w: L6 R$ q
Затем проверяем количество предметов (в данном случае количество клыков), и если их вообще нет, то возвращаем строку "Chat0.htm", если только один предмет, то возвращаем строку "Chat1.htm", если же предметов 4 или больше, то "Chat4.htm". Если строка возвращена из методов onEvent, onKill или onTalk, то сервер покажет соответствующие htm. В Chat0.htm может иметь следующий текст: «Вы не имеете ни одного клыка, возвращайтесь позже, когда соберете 4 штуки и бла, бла, бла…», в Chat1.htm может быть следующий текст: «У Вас всего 1 клык, по этому соберите еще…». В Chat4.htm – «Вы собрали необходимое количество предметов, возвращайтесь к вашему тренеру, что бы завершить квест…»
) [- S, w+ F, ?2 J
& d% \6 X; E1 T6 G

$ ?& E1 Y) k9 _3 `$ k) ~% W7 VПримечание: если в строка return начинается с "<html>", то будет показана страничка html с текстом, который стоит далее. Так вместо:/ S' z1 R) r% q) p6 Y+ c4 s
return "Chat4.htm"* e: N3 q$ t3 r8 t/ v8 \" A' Y

) @' g. E* l9 n. `* h' `
6 k& P; O5 c1 z- h( P8 k
можно поставить:0 N7 g% C, f% u3 F
  1. return "<html><body>Return to your trainer to complete the quest</body></html>"
Скопировать код
Так же если строка заканчивается без .htm или в начале нет <html>, то текст будет выведен, как системное сообщение в окне чата. В нашем случае мы сделаем так, что бы при каждом убийстве keltik выводилось системное сообщение: «Собрано N из 4-х клыков».
3 y* H, K7 b1 E9 k; v% y& P% i
( S8 x0 u, D8 `  J

# S& ]0 F3 @, E7 K- @4 i' wНаш код для onKill имеет один недостаток. Он будет постоянно показывать Chat0.htm, Chat1.htm и Chat4.htm, нам же необходимо, что бы Chat0.htm и Chat1.htm показывались только один раз. Как нам это сделать? С помощью переменных.
/ b$ |% V0 |1 Z* N6 }  Q; {
4 f7 O: I* v+ k3 N0 m0 r
) ]- }. ?) Q# T' q$ E7 g3 ~
В каждом квесте строки могут храниться с помощью переменных. Эти переменные сохраняются в Вашей БД. В каждом методе мы можем назначить, прочитать и удалить переменные. Давайте изменим метод onKill, так что бы каждый диалог вызывался только один раз.
) Y; @7 ?7 {5 s) k" n% ^( b/ D
  1. def onKill (self,npcId,st):
    ; D5 ^2 ], d: z6 o* H' j: l
  2. if npcId == KELTIR_NPC_ID:& d$ N; X! K# e* C8 f: d# @
  3. n = getCount(st)
    * b& a' R7 o; N/ ^
  4. if n == 0:
    ! c  b) d1 h6 e, B( z
  5. if st.get('chat0') == None :+ W: D  h: u/ g# O8 j9 o8 t6 D1 V: v* a
  6. st.set("chat0", "true")
    2 w, x4 l! \0 w. m) K$ L3 l2 e# ^
  7. return "Chat0.htm"
    3 ?4 u* {# ^7 k' z$ M
  8. elif n == 1:
    ; g( f* R3 b5 T  d+ X. l  R
  9. if st.get('chat1') == None :$ \* H  X6 Q) `7 n8 o
  10. st.set("chat1", "true")
    ! e. ~/ k9 Q" O; k1 x4 k1 P+ [
  11. return "Chat1.htm"$ }% g" M" s- n. H- ]/ Y- u) k+ \7 m
  12. elif n >= 4:2 J! l0 K+ S* }8 F- ~' [) j
  13. return "Chat4.htm"
    6 s" C, V6 T3 B$ S' O
  14. return "Collected "+str(n)+" of 4 fangs"! d, u8 L; N1 p! ~, p9 V
  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.
- `8 t# P7 [# P3 m9 Z  _
: m# G; \' S  `

1 I: |( Z& i0 f, ^Вот конечный рабочий вариант квеста:
; \* E  D! c3 @/ [
  1. import sys
    & S9 W# m. o% I
  2. from net.sf.l2j.gameserver.model.quest import State
    & O5 S" i9 \( c/ ]& Q5 z' j
  3. from net.sf.l2j.gameserver.model.quest import QuestState
    / ?" L5 y/ ?/ I6 x. T/ X1 U
  4. from net.sf.l2j.gameserver.model.quest.jython import QuestJython as JQuest% l. ^+ h& R1 t
  5. ; j3 G3 ]9 m" ]8 f* v! S, {6 U
  6. KELTIR_NPC_ID = 12082) r+ p- R3 j; G: L* i6 p( u8 B' i" ]
  7. FANGS_ITEM_ID = 18594 ^. Y- C3 U  p' c! q) q
  8. DROP_RATE    = 500000
    7 t$ g9 w7 t# b3 Z  O" k" k* A+ z
  9. - n" k8 H/ b+ W+ }; O0 M* B
  10. WORLD_MAP_ITEM_ID = 1665
    * z! _1 v6 L' i3 [8 \8 C: M

  11. 6 R$ k& M! ^/ ~- K6 E9 ?$ y2 E
  12. def getCount(st) :
    5 g4 w7 [$ y* k
  13. return st.getQuestItemsCount(FANGS_ITEM_ID), S: I/ H0 F: y5 \0 s
  14. ) {0 H) w% I; L6 {$ j. R( k( b
  15. def completed(st) :3 l2 [% p& B2 E1 \
  16. st.setState(COMPLETED)
    4 [2 f! K7 y9 W9 {- m
  17. st.clearQuestDrops()% ]0 G: s7 \( v, U- S5 C6 ?
  18. st.takeItems(FANGS_ITEM_ID,-1): q% `3 e: J& r, `- D: c
  19. st.giveItems(WORLD_MAP_ITEM_ID,1)% h  V0 j$ @' M/ r; {
  20. st.exitQuest(False)
    ' B0 s! M, H/ g! l
  21. return2 @- e- U% ]# F1 y

  22. ) v) K/ k0 k) u' M9 C, ^, {2 N
  23. def check(st) :
    & k+ l+ v) g( p' w
  24. if getCount(st) >= 4 :
    % |1 O1 E* r" E8 i* r
  25. completed(st)
    ) O( _! e( X0 L7 X& P
  26. return+ y( G/ B: U- s: |( ^; _$ B

  27. " i. p- V+ }& ~. i: g- V
  28. class Quest (JQuest):8 x2 q2 \6 ?# t6 m4 \

  29. 4 Y- i- N4 p' _& o# x( K
  30. def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)
    5 ?$ Z0 u- o) a  r

  31. ! \" q1 X. _2 a" ^! _+ c- N: n; C
  32. def onEvent (self,event,st):
    % p& t. I. u( V/ K6 k" s
  33. id = st.getState()
    2 Y/ ^0 v6 p# U3 U# a1 c- j
  34. if id == CREATED : st.setState(STARTED)
    & ^+ |) O, g9 r2 s0 n+ l4 Y7 A. _
  35. elif id == COMPLETED: pass
    & N' h5 k! N' Q; @! x! v& n; f2 g
  36. elif id == STARTED : check(st)4 a1 M( d3 ]9 v6 N& K7 ^8 d/ v
  37. return
    * I! b( r$ |, T9 ~0 ^/ t
  38. ( Q. d# C9 ]( {6 C
  39. def onKill (self,npcId,st):
    ! O& ?- @( ?0 q
  40. if npcId == KELTIR_NPC_ID:
    9 `: B# G" X' r0 V: F7 e- }  }
  41. n = getCount(st)0 c# K5 f# r- q: ]. w: Q
  42. if n == 0:. O9 C- G2 F9 w& h% R
  43. if st.get('chat0') == None :
    ' s5 \( m5 M1 O+ y" l0 k  u
  44. st.set("chat0", "true")% L* C/ r( k7 X: ~/ y; k0 d
  45. return "Chat0.htm"7 X- l- W" o5 f
  46. elif n == 1:
    4 X0 V/ r4 [7 A
  47. if st.get('chat1') == None :, _; `/ P( y  @
  48. st.set("chat1", "true")
    5 Q3 l* U; v# c( e: C. W3 R- C
  49. return "Chat1.htm"
    ; X* F2 v6 }5 S( {6 H
  50. elif n >= 4:9 g% f- T" {* J' D
  51. return "Chat4.htm"
    $ ~2 B; a/ O. |: l
  52. return "Collect "+str(n)+" of 4 fangs"/ r  E5 V) _8 g" t' C
  53. return  H2 t  ?9 E$ q# z

  54. 4 [8 P0 N' @# q/ x
  55. QUEST    = Quest(201, "Tutorial", "Tutorial quest")! z9 W5 m: m1 L4 C* @# G6 D
  56. CREATED = State('Start',    QUEST)
    , W# e6 s" o* d9 t/ S9 Q
  57. STARTED = State('Started', QUEST)8 Y1 G+ S0 P1 _7 o# l! l
  58. COMPLETED = State('Completed', QUEST)4 }2 W7 s  d9 @7 p5 F- q
  59. # b" |8 q6 a8 w
  60. QUEST.setInitialState(CREATED), N% p' i5 O1 b( {: `) ]
  61. QUEST.addStartNpc(7056)+ j$ Y" O% b5 i0 y1 i* \
  62. QUEST.addStartNpc(7012)
    2 ?* J0 j- Z( }
  63. QUEST.addStartNpc(7009)
    # z$ }. ?  N; ^8 d+ h3 U$ v
  64. QUEST.addStartNpc(7011)3 r4 p, Y" y/ ~9 G4 T
  65. 2 M- f4 [6 l# `4 H
  66. STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
    0 y5 Z' h& t- j8 d- ?' `
  67. STARTED.addKillId(KELTIR_NPC_ID)! ~6 m. p8 _- W
  68. STARTED.addTalkId(7056)
    - Y& M; C+ w' s# l
  69. STARTED.addTalkI d(7012)
    ! N$ W+ C2 k9 x, c2 u2 Z) h9 ^# }
  70. STARTED.addTalkId(7009)
    5 j- i) a+ V1 J
  71. STARTED.addTalkId(7011)
Скопировать код
7 M5 W" d. i6 C5 S! _4 i

% n+ Q8 ^6 A! f& \4 `+ u" m
Чтобы ответить, вам надо авторизироваться в системе Вход | Зарегистрироваться

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

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

638638758

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

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

admin@artace.ru Онлайн

QR-код

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