Top.Mail.Ru

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

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

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

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

x
Хроники        Interlude8 b/ Z7 _3 V0 t
Сборка        L2j4 H6 c2 b& X1 {& p$ N7 \
Обратите внимание: в файле htm стартового NCP обязательно должна быть ссылка на квест:* w9 a  o# A3 ^  E6 f) d3 l  N
  1. STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код
Для этого квеста больше ничего не надо. Все необходимое для корректной работы квеста уже добавили. Вот полный текст квеста:# P0 Y0 n" _0 Q2 Z4 E9 }$ G

1 l) B* D8 B$ L3 V
  1. if getCount(st) >= 4 :
      f8 j0 f$ ^, K$ p2 a" i& w
  2. completed(st)
    ; ^. B$ l# @! @0 K0 J1 b
  3.   return; e. s/ n4 F, N4 P5 x- @8 x1 z
  4. 6 ^3 s: W: Z* w: M$ S- Q4 r
  5. class Quest (JQuest):
      o  V3 z; f& r$ m/ L9 _
  6.   def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)
    - x: N5 J0 ?, W
  7.   def onEvent (self,event,st):
    2 f, I8 w% f9 x- y) u7 O5 C3 y
  8. id = st.getState()
    4 |+ |# \) s9 q, X$ h
  9. if   id == CREATED  : st.setState(STARTED)
    " d+ i3 @# _# X
  10. elif id == COMPLETED: pass
    4 m. D( U" i: @8 v: ~8 C6 w  U/ D/ E
  11. elif id == STARTED  : check(st)
    7 f! t% z8 a; ]9 c
  12. return
    - j: [  W; k4 n" C& x. e

  13. + _0 |& D" C/ w! ^6 s# _" S
  14. QUEST     = Quest(201,"Tutorial", "Tutorial quest"). f4 G1 J& w" V
  15. CREATED   = State('Start',     QUEST)
    8 n& V9 i& ]& m1 k
  16. STARTED   = State('Started',   QUEST)
    ' g$ M, W3 i! h8 k( Q
  17. COMPLETED = State('Completed', QUEST)
    ) H9 @" D, r/ w$ K

  18. : b8 b% K5 Q9 x  {# T
  19. QUEST.setInitialState(CREATED)$ s; [1 ]' @0 H) M) T. {) ~. \
  20. QUEST.addStartNpc(7056)
    1 g* o" N" Z) |  }' w) |* a
  21. STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код
Теперь рассмотрим, как это работает.
6 K, k2 ?  E$ D; rИгрок подходит к начальному NCP (в данном случае 7056), нажимает на «Quest». Квест будет создан и состояние квеста перейдет к CREATED и игроку будет показана страничка Start.htm с описанием квеста. Тогда метод onEvent, поле открытия странички Start.htm переведет состояние квеста в STARTED и игроку будет показана страничка Started.htm, где будет опсание того, как найти keltirs и .т.д.
! S8 Q4 [0 I( q, p
* @$ E3 a$ t7 L: q5 Y1 ]
2 F( d  \# K. n1 W
При состоянии STARTED будет зарегистрирован дроп «fangs» при убийстве keltirs. Игрок может вернуться к стартовому NCP и спросить о квесте – метод onEvent будет вызван снова. Если у игрока не хватает необходимого количества предметов, то метод check() не переведет квест в следующее состояние и Started.htm будет показана снова. Но если игрок собрал необходимее количество предметов (в данном случае 4 клыка), то метод check() вызовет метод completed() который переведет квест в новое состояние COMPLETED, заберет все клыки, даст карту мира, т.к. это награда за квест, покажет Completed.htm и завершит квест.% w/ h7 C$ ~1 N0 p

/ h  Y9 D! _  W4 V/ G

3 _! w# u, T6 R$ X( ]4 _9 x6 h8 r0 oТеперь давайте сделаем наш квест более похожим на то, что он должен из себя представлять.4 j* R" L! H+ j1 ~0 ~% c* k
Прежде всего у нас есть 3 метода для объявления их в Яве – onTalk, onKill и onEvent. Если методы onTalk и onKill не объявлены, то за них все будет делать метод onEvent, т.е. определять квестовых монстров и вызывать диалоги NCP. Есть примечание, методы onTalk и onKill будут вызывать только диалоги с NCP в зависимости от текущего состояния квеста. Метод onKill будет вызываться только тогда, когда мы убиваем квестового монстра.- F. M) U# A$ l% Z7 p
$ E4 Q/ R5 n& }* P" E5 I

9 y5 g9 V. m/ mДавайте рассмотрим как вызывается метод onKill при убийстве keltir в состоянии квеста STARTED:
! R  F; b, ~, {4 \
  1. STARTED.addKillId(KELTIR_NPC_ID)
Скопировать код
и метод onKill в классе Quest:, ^. |+ ?9 j8 G1 g+ Q7 y! U9 c# T
$ c* A8 \$ B) Z
  1. class Quest (JQuest):
    ; f; g$ {/ I3 w6 ^# `
  2.   ...
    " W0 o( M: W$ ]2 e  m
  3.   def onKill (self,npcId,st):1 Q( \& \1 B' V0 `4 ~
  4. if npcId == KELTIR_NPC_ID:
    ) T+ ^8 \0 e( j& |. N
  5.    n = getCount(st)) W9 j; `/ S7 m
  6.    if   n == 0:1 }- P1 a% l9 x9 Z) v5 R9 T
  7.        return "Chat0.htm"
    9 A: p# z5 S% E' i6 f& `9 Y4 {, x
  8.    elif n == 1:
    / `# ]9 P% T4 `( a! E5 B
  9.        return "Chat1.htm"
      w$ }1 N0 h% ]' H
  10.    elif n >= 4:
    . O0 o$ |; J( }) i5 |/ h4 J
  11.        return "Chat4.htm"
    / `0 y3 s' j! i6 S5 N1 T
  12.    return "Collected "+str(n)+" of 4 fangs"1 g1 ~: ~4 B+ ^, ]4 z% T- Z
  13. return
Скопировать код
Метод onKill (а так же метод onTalk) имеет следующие параметры:% u) v. a7 J# V
# f9 \) R8 t% a5 Y0 ?5 ~+ E' C

4 v+ @) ?9 z* ]" d% f' x/ B• self – квест
7 K2 F' w# N% K' U4 I  i• npcId – ID NCP, которого мы должны убивать (если это метод onTalk, то ID того NCP, с которым мы должны поговорить).
9 Q7 H- x' X5 f6 @) ~• st – текущее состояние игрока.8 Z( R! p$ I( m  [% _- B* y, A

9 n+ Y5 D& r# c1 B
* E9 B8 _6 _! }1 J+ h/ V
В этом методе мы проверяем и отмечаем, является ли убитый NCP keltir’ом. В основном эта проверка не нужна, т.к. у нас только KELTIR_NPC_ID.& S+ }, {* P, K  \2 m1 X
, k( o* o$ M* D
$ ]/ ]# \) w+ G% s
Затем проверяем количество предметов (в данном случае количество клыков), и если их вообще нет, то возвращаем строку "Chat0.htm", если только один предмет, то возвращаем строку "Chat1.htm", если же предметов 4 или больше, то "Chat4.htm". Если строка возвращена из методов onEvent, onKill или onTalk, то сервер покажет соответствующие htm. В Chat0.htm может иметь следующий текст: «Вы не имеете ни одного клыка, возвращайтесь позже, когда соберете 4 штуки и бла, бла, бла…», в Chat1.htm может быть следующий текст: «У Вас всего 1 клык, по этому соберите еще…». В Chat4.htm – «Вы собрали необходимое количество предметов, возвращайтесь к вашему тренеру, что бы завершить квест…»
% p3 u3 f! v$ e. G) Q$ n  F; D3 B9 e5 ?! `1 U4 y8 _9 t! ]
- J6 {0 Z! g) U
Примечание: если в строка return начинается с "<html>", то будет показана страничка html с текстом, который стоит далее. Так вместо:
# A: w$ z6 o* ~! Z% h: Preturn "Chat4.htm"
3 E& Q/ h! R& p2 w3 Z9 u6 M  g- u. q+ q7 }: O$ M9 K9 O# M, c

3 ~8 _9 t5 k$ d- ^можно поставить:9 J, P4 r* y: ^' s4 L/ Q! A& b
  1. return "<html><body>Return to your trainer to complete the quest</body></html>"
Скопировать код
Так же если строка заканчивается без .htm или в начале нет <html>, то текст будет выведен, как системное сообщение в окне чата. В нашем случае мы сделаем так, что бы при каждом убийстве keltik выводилось системное сообщение: «Собрано N из 4-х клыков».
+ ]' V. G0 F1 w5 F) O: `, E  z8 A# t. r2 A! `7 b8 z( }
% B6 a% L6 O/ L; e6 @/ ?: ?2 k
Наш код для onKill имеет один недостаток. Он будет постоянно показывать Chat0.htm, Chat1.htm и Chat4.htm, нам же необходимо, что бы Chat0.htm и Chat1.htm показывались только один раз. Как нам это сделать? С помощью переменных.; J' w, }# z9 D1 r( P" A3 _+ S

- U. G2 E" N5 H. f1 Z; G
( o. [, ^5 t3 m( l3 @
В каждом квесте строки могут храниться с помощью переменных. Эти переменные сохраняются в Вашей БД. В каждом методе мы можем назначить, прочитать и удалить переменные. Давайте изменим метод onKill, так что бы каждый диалог вызывался только один раз.9 f; j: @  W9 f# @3 x- C) {! n2 z
  1. def onKill (self,npcId,st):
    * ?: x$ _7 `" q4 Y* p4 l9 `8 Y0 c
  2. if npcId == KELTIR_NPC_ID:0 B8 w: l! Y1 I: u
  3. n = getCount(st)
    * F2 Z: G1 W: D% J6 p
  4. if n == 0:
    . f) Q' L4 i% g6 ~, r
  5. if st.get('chat0') == None :
    6 F' D/ s/ a8 i4 K9 J1 |! N
  6. st.set("chat0", "true")) T$ r/ h. u- y( j. q
  7. return "Chat0.htm"
    % {9 R1 F* O: ?; s
  8. elif n == 1:
    ' y$ C. U1 W  X# v. J
  9. if st.get('chat1') == None :, `5 y/ D2 P3 F, Q' Z
  10. st.set("chat1", "true")
    3 J' Z2 h. W# ?: A6 J6 g
  11. return "Chat1.htm"
    - l. ]2 M3 W) U5 b; D
  12. elif n >= 4:# S$ H2 D" n0 `) C: S$ a' ~  ~' \
  13. return "Chat4.htm"
    , J6 I9 ^! L0 {% l4 T: `, z
  14. return "Collected "+str(n)+" of 4 fangs"
    / `; u4 l! w0 R% F
  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.
. i6 V( z; L; [8 H5 v% L" h; b0 f% y: i- M% m

/ f. C  D: i) dВот конечный рабочий вариант квеста:& J. C- K% x' u6 A5 o4 p5 C
  1. import sys
    5 e6 F4 }; ?! P4 m6 w; V% A
  2. from net.sf.l2j.gameserver.model.quest import State, P, b9 I+ K* o& l. t# k
  3. from net.sf.l2j.gameserver.model.quest import QuestState
    / ]; j  I; X  N4 Y' ]# s1 B: t
  4. from net.sf.l2j.gameserver.model.quest.jython import QuestJython as JQuest9 V+ z/ v2 z% t* {

  5. 6 E) m3 k5 {, t9 b% T# Z9 T: L
  6. KELTIR_NPC_ID = 12082
      ~' a! u8 G, I" K8 r# M7 O
  7. FANGS_ITEM_ID = 1859
    3 A, [& \' P) c/ T: D5 S
  8. DROP_RATE    = 500000
    & d* a2 y! X2 y1 x; v8 y

  9. : @( r' z, k, R
  10. WORLD_MAP_ITEM_ID = 1665
    & Z  m* ~2 P- r- X4 S$ T; X
  11. ( z9 G. B; j) T/ ]
  12. def getCount(st) :2 A0 O/ V( w; i. E. c
  13. return st.getQuestItemsCount(FANGS_ITEM_ID)- \* L: n5 L; T2 K& U

  14. : B  n0 R& I" r5 ]% s, b
  15. def completed(st) :' o( T  T! p$ Z* X, w
  16. st.setState(COMPLETED)( C7 K( s0 H8 |) c' v
  17. st.clearQuestDrops()7 |' a: A0 {+ s+ X
  18. st.takeItems(FANGS_ITEM_ID,-1)
    " H2 O. N. K! S' E. w- A
  19. st.giveItems(WORLD_MAP_ITEM_ID,1)  T2 q, ^3 Z' V* X( c
  20. st.exitQuest(False)
    . t' `2 {7 W" L+ H; o' U
  21. return  L7 V8 A" |, M- g
  22. # r' I$ E6 o$ z! x0 P8 Y
  23. def check(st) :
    5 n4 f+ a6 I3 D
  24. if getCount(st) >= 4 :" X1 n; `( d3 [2 N
  25. completed(st): o9 k3 w( h) P$ V/ c8 W1 W
  26. return" |, q7 E* ^  r0 X7 P  e2 \3 g

  27. ) U8 M; R, u6 S
  28. class Quest (JQuest):6 Y" b9 ^" m4 G" \5 e6 `  g5 {, K
  29. 2 Y3 t7 B$ l2 ~
  30. def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)  Z  L9 B) I# w$ M& l& ]# _
  31. 2 D6 K6 f  y$ W) N* k5 b* d
  32. def onEvent (self,event,st):
    7 i! g3 T$ d& e# K
  33. id = st.getState(). R& \4 h3 f7 D$ c: E0 z! ?; E
  34. if id == CREATED : st.setState(STARTED)
    ' O# F. v2 |* `! p; h" \! Q% P, u; W
  35. elif id == COMPLETED: pass
    + P# J7 S8 L( @
  36. elif id == STARTED : check(st). t2 |! G6 G$ h8 g
  37. return
    8 t$ @- ]$ s& Z8 V

  38.   Z3 X( [+ S) K6 i- J
  39. def onKill (self,npcId,st):
    9 V: T" Y1 m2 t
  40. if npcId == KELTIR_NPC_ID:, ?) Z8 M" O8 g. Q( {" W# c9 S
  41. n = getCount(st)- f$ T% v& V( D# `5 T" M' s# K
  42. if n == 0:
    ) l# o+ r& Z3 [$ _( s+ D9 G
  43. if st.get('chat0') == None :; v5 g1 j$ e& j4 n
  44. st.set("chat0", "true")
      @$ M1 V% x( `+ ]1 J
  45. return "Chat0.htm"
    % U' O3 h1 }; i; p6 r
  46. elif n == 1:  |+ Y: p2 E* Y$ y
  47. if st.get('chat1') == None :; y) B9 E7 {5 a9 [. @5 B2 S
  48. st.set("chat1", "true")! m6 _; t  q4 B) e$ i" U
  49. return "Chat1.htm"
    . ?( m8 ~  M( @4 L+ D8 ]4 A2 g
  50. elif n >= 4:0 ]5 |8 n4 p& I& j" b
  51. return "Chat4.htm"
    9 _. g; v: h% m1 Y5 h5 B
  52. return "Collect "+str(n)+" of 4 fangs") ]: k* K1 q9 q/ k
  53. return
      z5 t# |1 d2 L3 y
  54. 2 I. U4 s$ t' r# j$ H
  55. QUEST    = Quest(201, "Tutorial", "Tutorial quest")
    3 U+ Z& d" M2 n" q! m1 s
  56. CREATED = State('Start',    QUEST)" G1 G. g3 E! r6 T$ E! Z
  57. STARTED = State('Started', QUEST)2 A0 z9 V( c" x7 `' [4 H# C- S
  58. COMPLETED = State('Completed', QUEST)
    6 P) U  Z: j7 t" X2 t$ D8 \
  59. - ~; k$ q& U3 ?0 ?) r) Z7 t
  60. QUEST.setInitialState(CREATED)! {" I0 c: ?/ k0 d
  61. QUEST.addStartNpc(7056)/ H, }# A4 L4 M: Z6 _9 D) L- x
  62. QUEST.addStartNpc(7012)' o, h* {1 q0 G. d
  63. QUEST.addStartNpc(7009)( U; ~2 r; D  W  {5 z9 g
  64. QUEST.addStartNpc(7011)/ u& T9 B' F$ }* R" s# C% H" m

  65. 9 L& B$ @% z; a9 |' S. O
  66. STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)3 j+ c" p' Z1 V; e$ F$ o' a
  67. STARTED.addKillId(KELTIR_NPC_ID)) C- R5 x! U# D( m1 s
  68. STARTED.addTalkId(7056)0 }2 e# E; P0 ?( e  H6 s
  69. STARTED.addTalkI d(7012)6 ^0 A# b" G$ `
  70. STARTED.addTalkId(7009); ~" \! ~2 D3 J! i+ o& }1 a
  71. STARTED.addTalkId(7011)
Скопировать код
: ]: r# T3 K3 }2 V. s& T3 O3 K

4 e; ~" c- X& p; g* B- |+ z
Чтобы ответить, вам надо авторизироваться в системе Вход | Зарегистрироваться

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

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

638638758

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

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

admin@artace.ru Онлайн

QR-код

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