Top.Mail.Ru

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

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

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

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

x
Хроники        Interlude
) Z6 a' _7 u- k) |# B( GСборка        L2j1 z3 i) A) ]0 t. c0 d+ _
Обратите внимание: в файле htm стартового NCP обязательно должна быть ссылка на квест:  _& j' d5 g  O8 M
  1. STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код
Для этого квеста больше ничего не надо. Все необходимое для корректной работы квеста уже добавили. Вот полный текст квеста:* B! u. k$ |/ }" u9 l4 ^

6 K, S1 F- }; y2 c9 s. a
  1. if getCount(st) >= 4 :9 F9 ~1 E  M# p
  2. completed(st)
    , R+ V( O) C7 G7 V
  3.   return
    5 E. e& B& t& x3 k. I
  4. $ c1 V1 O/ ~9 u# J
  5. class Quest (JQuest):
    3 |8 E+ F3 @: z/ p% `; X5 _
  6.   def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)
    0 @( n7 |* a( M* D
  7.   def onEvent (self,event,st):
    # v! k# s2 @$ g) i
  8. id = st.getState()) Z; W% W. F( U2 [! O
  9. if   id == CREATED  : st.setState(STARTED)
    9 \2 Z" [/ K# m. O! v& n) f# W' T
  10. elif id == COMPLETED: pass! R& t) A5 H+ [3 ]
  11. elif id == STARTED  : check(st)* |5 H0 \8 {' X& F* }& w
  12. return" y4 K  z( i. }

  13. - T% i/ R( e7 r
  14. QUEST     = Quest(201,"Tutorial", "Tutorial quest")0 s- A8 X1 t- A8 Z
  15. CREATED   = State('Start',     QUEST)
    3 @" `9 B6 s2 h* Z; ]$ B/ n0 O
  16. STARTED   = State('Started',   QUEST)
    $ S+ L7 w) f: s
  17. COMPLETED = State('Completed', QUEST)
    2 ~. c; u/ V! }5 m
  18. ' g. B5 e  X9 X! _2 e6 @
  19. QUEST.setInitialState(CREATED)! |" o; y9 O( ~7 @( }7 \& m
  20. QUEST.addStartNpc(7056)6 f* ?" G7 M: Q& |8 W7 q
  21. STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код
Теперь рассмотрим, как это работает./ M; I/ x) `2 [
Игрок подходит к начальному NCP (в данном случае 7056), нажимает на «Quest». Квест будет создан и состояние квеста перейдет к CREATED и игроку будет показана страничка Start.htm с описанием квеста. Тогда метод onEvent, поле открытия странички Start.htm переведет состояние квеста в STARTED и игроку будет показана страничка Started.htm, где будет опсание того, как найти keltirs и .т.д.' j8 A. j+ `3 Z2 h9 \: d) p
0 @* D* i9 r' t. ~. r
' q# J3 H% P/ H# H8 A/ Z
При состоянии STARTED будет зарегистрирован дроп «fangs» при убийстве keltirs. Игрок может вернуться к стартовому NCP и спросить о квесте – метод onEvent будет вызван снова. Если у игрока не хватает необходимого количества предметов, то метод check() не переведет квест в следующее состояние и Started.htm будет показана снова. Но если игрок собрал необходимее количество предметов (в данном случае 4 клыка), то метод check() вызовет метод completed() который переведет квест в новое состояние COMPLETED, заберет все клыки, даст карту мира, т.к. это награда за квест, покажет Completed.htm и завершит квест." a  P5 n/ p+ y
/ [6 G- |( p) O, q2 y$ d+ g
! w1 n" i  {! u0 m
Теперь давайте сделаем наш квест более похожим на то, что он должен из себя представлять.
/ j9 S& @1 N; _5 s, N# b) P  e8 c$ s, lПрежде всего у нас есть 3 метода для объявления их в Яве – onTalk, onKill и onEvent. Если методы onTalk и onKill не объявлены, то за них все будет делать метод onEvent, т.е. определять квестовых монстров и вызывать диалоги NCP. Есть примечание, методы onTalk и onKill будут вызывать только диалоги с NCP в зависимости от текущего состояния квеста. Метод onKill будет вызываться только тогда, когда мы убиваем квестового монстра.
# _: ]1 g0 ?  C  |: T: Q: O6 \" K4 [0 d1 X- ~/ w& ]

, s3 [/ W9 O3 _3 ^; L) e. f! {Давайте рассмотрим как вызывается метод onKill при убийстве keltir в состоянии квеста STARTED:  I* Q5 j. C4 w5 H/ n2 }; V
  1. STARTED.addKillId(KELTIR_NPC_ID)
Скопировать код
и метод onKill в классе Quest:' A# X+ L8 J0 x8 U- h
+ T8 n: e/ F' Y
  1. class Quest (JQuest):0 N" d3 \5 m  {7 o. `& `% q
  2.   ...) Z/ m' v9 l2 g
  3.   def onKill (self,npcId,st):
    / l1 }8 q" h/ c: o- g2 F0 w3 g0 e8 |
  4. if npcId == KELTIR_NPC_ID:6 i, g; n1 n' j2 ~( Z. M" D- T
  5.    n = getCount(st)) e0 s8 R( l: _' U9 Q0 Z* A) R' l3 ^
  6.    if   n == 0:  r2 K( I( C6 f4 e; G. B
  7.        return "Chat0.htm", J% ]! Q. C+ z! j5 A
  8.    elif n == 1:
    4 q  _9 l0 C% `+ T% U
  9.        return "Chat1.htm", E2 d8 U' g2 f6 e3 s# c& Z
  10.    elif n >= 4:, G5 r7 {2 Z1 c. d
  11.        return "Chat4.htm"* s& v' F6 W  P. p4 ]
  12.    return "Collected "+str(n)+" of 4 fangs"* ^% B( m1 U- K5 |
  13. return
Скопировать код
Метод onKill (а так же метод onTalk) имеет следующие параметры:
* ^9 B% w* f* W6 w
( O1 }: e! {( Y  L

# }# L/ _6 u% d• self – квест
/ t# E5 S  B! V, Q7 K7 f• npcId – ID NCP, которого мы должны убивать (если это метод onTalk, то ID того NCP, с которым мы должны поговорить).
: X& f0 ?4 W: c. i% k3 j• st – текущее состояние игрока.2 ^2 \6 ]% j4 l, q( g# H# h
; H( r! x# C' I5 w+ ?2 @) J
& ]/ a+ ?* D0 n: K4 w0 T4 t  [9 X
В этом методе мы проверяем и отмечаем, является ли убитый NCP keltir’ом. В основном эта проверка не нужна, т.к. у нас только KELTIR_NPC_ID.# q& ]4 f' F! S
0 |# `4 V- ?3 Y4 z' w, P% L

+ @& h" V* Z# g9 g/ x7 cЗатем проверяем количество предметов (в данном случае количество клыков), и если их вообще нет, то возвращаем строку "Chat0.htm", если только один предмет, то возвращаем строку "Chat1.htm", если же предметов 4 или больше, то "Chat4.htm". Если строка возвращена из методов onEvent, onKill или onTalk, то сервер покажет соответствующие htm. В Chat0.htm может иметь следующий текст: «Вы не имеете ни одного клыка, возвращайтесь позже, когда соберете 4 штуки и бла, бла, бла…», в Chat1.htm может быть следующий текст: «У Вас всего 1 клык, по этому соберите еще…». В Chat4.htm – «Вы собрали необходимое количество предметов, возвращайтесь к вашему тренеру, что бы завершить квест…»  v$ M1 d( W, P& A9 s

/ Y+ D7 U9 p5 x  w5 J. n, I

7 o$ }1 i5 L! e* IПримечание: если в строка return начинается с "<html>", то будет показана страничка html с текстом, который стоит далее. Так вместо:9 i$ r0 }  X7 O0 H) C
return "Chat4.htm") J1 W2 a8 T6 `, ]5 U
  b8 ?% w$ W1 l7 U
( u4 z3 ]* ?8 |, w8 u4 N0 W- u7 L) ^
можно поставить:
! ]5 p4 u) ^) i) A) e
  1. return "<html><body>Return to your trainer to complete the quest</body></html>"
Скопировать код
Так же если строка заканчивается без .htm или в начале нет <html>, то текст будет выведен, как системное сообщение в окне чата. В нашем случае мы сделаем так, что бы при каждом убийстве keltik выводилось системное сообщение: «Собрано N из 4-х клыков».5 T& Z. L+ u; C/ K7 S
% N" j0 }% E4 h. j- p! i8 [, ]

4 y; N6 V. f3 l" [% K7 fНаш код для onKill имеет один недостаток. Он будет постоянно показывать Chat0.htm, Chat1.htm и Chat4.htm, нам же необходимо, что бы Chat0.htm и Chat1.htm показывались только один раз. Как нам это сделать? С помощью переменных.0 i. a' S8 x; p5 N' O

% Q3 Z8 H3 X( K+ Y
7 n% }9 o9 i. a, T$ H' M& h
В каждом квесте строки могут храниться с помощью переменных. Эти переменные сохраняются в Вашей БД. В каждом методе мы можем назначить, прочитать и удалить переменные. Давайте изменим метод onKill, так что бы каждый диалог вызывался только один раз.
% R) U/ T6 n! U; ~
  1. def onKill (self,npcId,st):
    3 m& A' Y9 N" F& i, h0 X
  2. if npcId == KELTIR_NPC_ID:
    ! s. ^" A- w$ a. e/ d
  3. n = getCount(st)( T  z8 g. @% l& W
  4. if n == 0:6 c0 {$ i1 \) v2 Q
  5. if st.get('chat0') == None :% J% F& S1 f1 J4 |/ A' m4 R) K
  6. st.set("chat0", "true")& j) ]( l$ [1 u5 k. r/ D3 A
  7. return "Chat0.htm"1 O  a5 u8 ]5 H8 o
  8. elif n == 1:, s8 ~3 [# f4 j+ L7 H' F4 B1 G+ o
  9. if st.get('chat1') == None :4 p) ^+ }, o. E. D
  10. st.set("chat1", "true")
    0 V! v, `6 I# g3 U% u' q3 T5 ]
  11. return "Chat1.htm"
    % t, \- K- f$ }! R$ J0 E# v
  12. elif n >= 4:. x4 j6 R7 X% G2 }3 T/ H/ [: r: l
  13. return "Chat4.htm"* I8 X+ h! W3 t6 k
  14. return "Collected "+str(n)+" of 4 fangs"
    , \1 ?8 N) j+ G6 B" R; A
  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.
/ L8 v; h2 C' L) b+ v, Y! e  g! ^' }; m2 B  E; ]5 [( Y4 k
' l3 p; B. ]- w$ J# ]4 r- l, W2 C
Вот конечный рабочий вариант квеста:
# z8 u1 a) i2 r( ^& D6 H
  1. import sys
    # ?1 b. p8 i# Z* |3 M" I" Y
  2. from net.sf.l2j.gameserver.model.quest import State: J) ?& S( j2 h( g9 |
  3. from net.sf.l2j.gameserver.model.quest import QuestState' Z6 [4 s) ~4 d% `  j
  4. from net.sf.l2j.gameserver.model.quest.jython import QuestJython as JQuest
      P( Q5 J# _7 \, I% V/ ]

  5. ; \* D( o! |1 t- l) F7 g$ H/ B
  6. KELTIR_NPC_ID = 12082
    ; S+ y4 U( b/ O( C# B
  7. FANGS_ITEM_ID = 18591 c5 F4 y1 O" d: F1 ]
  8. DROP_RATE    = 500000
      [! t( g' ^0 F: O
  9. 4 h2 w5 k$ B+ T( v! h: R9 A0 _
  10. WORLD_MAP_ITEM_ID = 1665
    $ h' a1 y% z- p5 H0 j# c

  11. 2 Y; L9 L8 }$ `% ~  _
  12. def getCount(st) :
    3 p: z& N/ l, F" O
  13. return st.getQuestItemsCount(FANGS_ITEM_ID)
    # U" }6 J* \: t% ]
  14. % R6 c' H) t' c- t" l- u
  15. def completed(st) :, c! |; K7 X4 \: G8 C
  16. st.setState(COMPLETED)0 l0 E" q- K. f, N8 V1 d" C
  17. st.clearQuestDrops()
    2 K+ C* [8 X( V  X/ x( J
  18. st.takeItems(FANGS_ITEM_ID,-1)$ H- M# w0 ^8 D/ y
  19. st.giveItems(WORLD_MAP_ITEM_ID,1)
    & |2 p/ g! K) M9 C
  20. st.exitQuest(False)5 d  d8 w; l  \4 A
  21. return! P" r) V- X; \. c

  22. % L# T, y3 Y& e7 \
  23. def check(st) :* t4 W$ f7 x1 L( V7 _. I
  24. if getCount(st) >= 4 :6 q% {' v  f: P- }0 n. ~
  25. completed(st)
    ' s# s- L% h" Y) J- |" f, ^8 C
  26. return' U; [4 f$ G1 O# z* L3 c

  27. ) B5 g, b( {- T. ]) ?) o4 v% v
  28. class Quest (JQuest):
    * y) `& O3 q$ k% C) ?
  29. 1 B: q) L) J9 J8 N& ?
  30. def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr): o' f& J" L# ?
  31. 4 A' [' C) I8 ?* c- Y2 A
  32. def onEvent (self,event,st):
    : f0 V" S& \! ]  z* p. n; w8 \( g
  33. id = st.getState()
    # i: S8 b, h2 l6 s  R
  34. if id == CREATED : st.setState(STARTED)3 {" H) ^+ g$ ^
  35. elif id == COMPLETED: pass
    : _9 l, a" H  j6 t
  36. elif id == STARTED : check(st)+ e5 B0 z1 R* U4 ~& E8 n
  37. return$ W" [1 M  |( _
  38. " Q  q) g5 a% A
  39. def onKill (self,npcId,st):
    7 C8 a0 s; M2 i' C% `
  40. if npcId == KELTIR_NPC_ID:& N3 ?. u! Q9 `0 C4 s6 z
  41. n = getCount(st)
    " j, N/ A: Q  j/ F8 H
  42. if n == 0:7 u' ?" A# t7 X! T
  43. if st.get('chat0') == None :
    3 A% p) {' |$ S% b2 D
  44. st.set("chat0", "true")
    9 d5 T4 b# c! H; y" P& G- G
  45. return "Chat0.htm"/ B6 g! W8 x* {% x
  46. elif n == 1:4 c" P, r! A6 |0 Z2 c2 A
  47. if st.get('chat1') == None :
    # o$ B: h+ j2 M, t
  48. st.set("chat1", "true")
    - D. Z, D9 m) \2 v- m# @( q& D
  49. return "Chat1.htm"0 w% G2 _% R7 _- ?2 v* r5 }. A+ e% b7 k
  50. elif n >= 4:* P5 w# h" {! j
  51. return "Chat4.htm"7 z7 u. b* K7 z" B! d8 N
  52. return "Collect "+str(n)+" of 4 fangs"
    % G  G3 q! d: H" }% B% d, v8 s0 l
  53. return
    ; |3 {: _8 E* J, M- \* d4 u
  54. " K+ T$ a, R% n4 }  ]3 ^+ K, ~% A) [
  55. QUEST    = Quest(201, "Tutorial", "Tutorial quest")
    1 G+ {: N7 ?1 M$ t
  56. CREATED = State('Start',    QUEST)
    2 P# P/ h9 z! D0 h9 C8 f/ r
  57. STARTED = State('Started', QUEST)
    * ^+ y. X; q4 z" [; g1 x5 u
  58. COMPLETED = State('Completed', QUEST)
    , F! I2 J% L5 ~9 k3 I8 W" [

  59. % U: r; d* B' q8 F; \+ b
  60. QUEST.setInitialState(CREATED)/ _" m9 B: p) s: p
  61. QUEST.addStartNpc(7056)$ R: {- r" R; |# b: P6 t  K
  62. QUEST.addStartNpc(7012)
    , F; a! M) k" y7 r
  63. QUEST.addStartNpc(7009)
    : i6 o" L8 z5 a3 t" [1 R- t
  64. QUEST.addStartNpc(7011)4 q1 e  f7 [8 f+ t/ D( T4 _1 h, D8 K

  65. , D2 X3 d+ r+ |- O8 K
  66. STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)* G0 O  S2 k0 k6 w: s5 J  M. Z+ i+ p
  67. STARTED.addKillId(KELTIR_NPC_ID)
    # M7 z5 F4 b( L, x- A+ S  ?
  68. STARTED.addTalkId(7056)
    : I2 c. Z  _: F% w! k* B- o
  69. STARTED.addTalkI d(7012)
    / ^; B' ~0 {7 q
  70. STARTED.addTalkId(7009)
    7 P+ {+ ?) Y: D* e7 X
  71. STARTED.addTalkId(7011)
Скопировать код
7 X) x' H* n6 r5 g

- u) ^2 o7 l; h( O7 b
Чтобы ответить, вам надо авторизироваться в системе Вход | Зарегистрироваться

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

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

638638758

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

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

admin@artace.ru Онлайн

QR-код

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