Top.Mail.Ru

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

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

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

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

x
Хроники        Interlude
8 d3 }8 ]1 `! K. [; uСборка        L2j6 s  n/ s9 y: r# [! |2 w) A
Обратите внимание: в файле htm стартового NCP обязательно должна быть ссылка на квест:
# h; {% }5 V5 z
  1. STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код
Для этого квеста больше ничего не надо. Все необходимое для корректной работы квеста уже добавили. Вот полный текст квеста:# I& E  l1 ]3 {8 b2 @( J

+ m+ n( ]; j3 x! u: S
  1. if getCount(st) >= 4 :
    . a3 U2 Z0 J) p: p9 v/ f
  2. completed(st)3 s# N$ c1 n3 M. u
  3.   return
    & Y: r# }1 d5 L/ j
  4. $ E& g  A2 E1 Y; S
  5. class Quest (JQuest):
      o) Z6 g. D! Q% [8 G7 R
  6.   def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)
    ( K, K, f# q+ n$ Y! @  C
  7.   def onEvent (self,event,st):
    ! q) G5 x0 s% N. E1 ]# B
  8. id = st.getState()
    # d2 W$ T9 d8 Z2 p, G0 a+ v/ x
  9. if   id == CREATED  : st.setState(STARTED)
    ' n" x, ?# m  O& ]
  10. elif id == COMPLETED: pass
    7 A( h5 [5 p- s7 R  F3 |
  11. elif id == STARTED  : check(st)% ~5 ]* h" n, B+ S% r
  12. return- u0 c) _- x9 M/ m

  13. ) D" |3 K" ]- j6 P! ?) o( r$ B0 O
  14. QUEST     = Quest(201,"Tutorial", "Tutorial quest")% _( U* s! q+ R: D+ z
  15. CREATED   = State('Start',     QUEST)
    ' i, H# `& m7 n/ u6 Q
  16. STARTED   = State('Started',   QUEST)
    6 i( \! K& v9 v5 h
  17. COMPLETED = State('Completed', QUEST)
    ' _, w8 _! D) C' z$ A6 j
  18. 8 ~; M, i3 t9 s* @
  19. QUEST.setInitialState(CREATED)
    8 W% u& i+ v) z, ^7 a
  20. QUEST.addStartNpc(7056)& o. L7 r: |% n% r
  21. STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код
Теперь рассмотрим, как это работает.
; i" x( z" r/ v5 o0 P' b( K" _Игрок подходит к начальному NCP (в данном случае 7056), нажимает на «Quest». Квест будет создан и состояние квеста перейдет к CREATED и игроку будет показана страничка Start.htm с описанием квеста. Тогда метод onEvent, поле открытия странички Start.htm переведет состояние квеста в STARTED и игроку будет показана страничка Started.htm, где будет опсание того, как найти keltirs и .т.д.
$ S* j1 F3 G9 v2 ?
2 l6 @9 k# z. D9 h/ k  B& h+ V

$ |* F4 ~9 B* |% A$ o2 Q, zПри состоянии STARTED будет зарегистрирован дроп «fangs» при убийстве keltirs. Игрок может вернуться к стартовому NCP и спросить о квесте – метод onEvent будет вызван снова. Если у игрока не хватает необходимого количества предметов, то метод check() не переведет квест в следующее состояние и Started.htm будет показана снова. Но если игрок собрал необходимее количество предметов (в данном случае 4 клыка), то метод check() вызовет метод completed() который переведет квест в новое состояние COMPLETED, заберет все клыки, даст карту мира, т.к. это награда за квест, покажет Completed.htm и завершит квест.+ D6 s& d  Z; G2 K( {
; e& B, K# Q( X2 L
/ C1 q/ X( y8 ?1 V9 m5 K
Теперь давайте сделаем наш квест более похожим на то, что он должен из себя представлять.
3 a, ]  \. M& vПрежде всего у нас есть 3 метода для объявления их в Яве – onTalk, onKill и onEvent. Если методы onTalk и onKill не объявлены, то за них все будет делать метод onEvent, т.е. определять квестовых монстров и вызывать диалоги NCP. Есть примечание, методы onTalk и onKill будут вызывать только диалоги с NCP в зависимости от текущего состояния квеста. Метод onKill будет вызываться только тогда, когда мы убиваем квестового монстра.# R* Y: G# F7 m& D6 O
0 u% H4 {3 w1 @4 c% l) v! V. d

, c4 q& o' n4 v* }Давайте рассмотрим как вызывается метод onKill при убийстве keltir в состоянии квеста STARTED:: T% T! C; D; b/ [6 m3 ]& A  }. j
  1. STARTED.addKillId(KELTIR_NPC_ID)
Скопировать код
и метод onKill в классе Quest:, T7 M# [1 Z- k& a7 J. g

% {& o7 P9 ?1 Y1 w! v/ B# {/ a5 I
  1. class Quest (JQuest):) N+ L6 b& `2 q- Y
  2.   ...
    ( `, d# Q+ m$ x5 P- u" I0 s  p0 ]
  3.   def onKill (self,npcId,st):/ {2 H' b) X# T1 X" T0 v# T1 j: X
  4. if npcId == KELTIR_NPC_ID:
    $ m  |) H# Q9 ~" f7 F
  5.    n = getCount(st)1 D/ |. u$ j) B) E
  6.    if   n == 0:
    ( ?8 g8 [" Z0 N( Q* p
  7.        return "Chat0.htm"/ S! p$ P+ r7 N% S8 P8 H
  8.    elif n == 1:, \* ]" }! w: S" f( @
  9.        return "Chat1.htm"- J; l# i% j# C
  10.    elif n >= 4:9 k: W1 v  U7 E& S
  11.        return "Chat4.htm"/ t7 q6 ^% i# O; X% k
  12.    return "Collected "+str(n)+" of 4 fangs"6 h, u  X0 T6 \# [& V
  13. return
Скопировать код
Метод onKill (а так же метод onTalk) имеет следующие параметры:
: a! l; B4 p7 q& @0 Y# N
. i$ ]0 K, e) ]: @* \2 M: q
# D6 g4 E- ~4 Z) K) H
• self – квест
3 g. w' P) `+ b% V5 P7 y• npcId – ID NCP, которого мы должны убивать (если это метод onTalk, то ID того NCP, с которым мы должны поговорить).
% X2 {, j% Z( S0 D: ~• st – текущее состояние игрока.; N! t0 ?$ {; t; S  k
/ Q+ F+ M& _1 O6 N: s1 u% |4 _

9 ^1 P; m5 }6 x  xВ этом методе мы проверяем и отмечаем, является ли убитый NCP keltir’ом. В основном эта проверка не нужна, т.к. у нас только KELTIR_NPC_ID.
  m% o! K7 @9 R- b+ r6 K- W. O6 _- w  {1 T* U' S" g
( h) P$ x  \" V, t
Затем проверяем количество предметов (в данном случае количество клыков), и если их вообще нет, то возвращаем строку "Chat0.htm", если только один предмет, то возвращаем строку "Chat1.htm", если же предметов 4 или больше, то "Chat4.htm". Если строка возвращена из методов onEvent, onKill или onTalk, то сервер покажет соответствующие htm. В Chat0.htm может иметь следующий текст: «Вы не имеете ни одного клыка, возвращайтесь позже, когда соберете 4 штуки и бла, бла, бла…», в Chat1.htm может быть следующий текст: «У Вас всего 1 клык, по этому соберите еще…». В Chat4.htm – «Вы собрали необходимое количество предметов, возвращайтесь к вашему тренеру, что бы завершить квест…»
( ?/ x- ^: e8 X7 V0 U  Q2 V% @
: Y9 d7 g/ T6 k. {, z! r' u

' i" H  @8 o" H+ \7 C) AПримечание: если в строка return начинается с "<html>", то будет показана страничка html с текстом, который стоит далее. Так вместо:! J& _1 T; l$ t  N  |
return "Chat4.htm") e2 @1 K5 P3 p7 @2 W- Z
! _% ~& H2 Z$ R+ m

% H, v) R9 g, @можно поставить:
. z" H$ ^- G* x
  1. return "<html><body>Return to your trainer to complete the quest</body></html>"
Скопировать код
Так же если строка заканчивается без .htm или в начале нет <html>, то текст будет выведен, как системное сообщение в окне чата. В нашем случае мы сделаем так, что бы при каждом убийстве keltik выводилось системное сообщение: «Собрано N из 4-х клыков».
: r8 x0 H. Q5 a  \2 Q9 }
/ Z  \% x2 ^7 d( h. X, f3 ]
4 z2 o* f& C3 m4 x/ z
Наш код для onKill имеет один недостаток. Он будет постоянно показывать Chat0.htm, Chat1.htm и Chat4.htm, нам же необходимо, что бы Chat0.htm и Chat1.htm показывались только один раз. Как нам это сделать? С помощью переменных.' ~, D+ F* ]+ D/ M9 l/ M) z
) g( G  N. \0 p5 D0 |) L$ [0 W1 Y

- G( a: F3 r0 p) g* gВ каждом квесте строки могут храниться с помощью переменных. Эти переменные сохраняются в Вашей БД. В каждом методе мы можем назначить, прочитать и удалить переменные. Давайте изменим метод onKill, так что бы каждый диалог вызывался только один раз.: i) J+ \; l4 Y+ K5 K
  1. def onKill (self,npcId,st):) j& n% j' c4 I- ?% w6 |. ?; x
  2. if npcId == KELTIR_NPC_ID:
    " r- ^# A- f1 v9 E0 T0 z" B: O
  3. n = getCount(st)
    ; _% j: H) h; d+ q
  4. if n == 0:
    " V$ `+ N: a* D" Q
  5. if st.get('chat0') == None :
    ; Y) Q1 B2 g: w5 x: i
  6. st.set("chat0", "true"), F& n/ ]& H& {5 ~% J# p% z8 I
  7. return "Chat0.htm"- [9 z- `; c0 @
  8. elif n == 1:
    9 y6 Y. i# p) Z$ ]+ a
  9. if st.get('chat1') == None :
    3 z( l+ ~; m* S' I
  10. st.set("chat1", "true")
    2 K, ]/ [5 f5 }) q' w
  11. return "Chat1.htm"5 y, R5 j  v# Q
  12. elif n >= 4:1 u( ~: e2 m: ~  U1 {
  13. return "Chat4.htm"" Y6 }8 S+ T4 f, i4 `1 K
  14. return "Collected "+str(n)+" of 4 fangs"
    5 u2 @4 U& Z% x# g; |/ {  e2 G8 e
  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.
( f% |, M8 q5 F3 K" u. [8 Y" j% r' r* U* o* S( O
/ ~& Y" M: E6 V1 D" ?0 Q0 w* q
Вот конечный рабочий вариант квеста:
2 d6 `* k; Y$ o6 p% J1 i: C
  1. import sys- C2 `+ H* o  A  D- L7 E& K7 ~9 R
  2. from net.sf.l2j.gameserver.model.quest import State7 |1 k' I: j% O& I$ n
  3. from net.sf.l2j.gameserver.model.quest import QuestState
    ; V' t6 D& @- W& S; Q
  4. from net.sf.l2j.gameserver.model.quest.jython import QuestJython as JQuest  _7 D# I& F/ j  ^2 \% R  @9 F
  5. . k, j; ]& j# P4 W* B! M7 r
  6. KELTIR_NPC_ID = 12082, a# u" D: K; u$ C9 R5 a3 a& c& \
  7. FANGS_ITEM_ID = 1859
    5 A! c  }( M7 c4 _
  8. DROP_RATE    = 500000
    " g' D% R' i2 U+ V
  9. ; Z7 _8 x! D& ~1 t% M7 x' ~+ c3 w
  10. WORLD_MAP_ITEM_ID = 1665
    0 W% [$ N6 w: V" u+ m' W& j

  11. 0 L. V1 J+ |! C* ^, n% F& j/ w
  12. def getCount(st) :* F! q7 J1 q* J/ b1 E
  13. return st.getQuestItemsCount(FANGS_ITEM_ID)
    ) V! P" e7 |0 p

  14. 7 Q3 H6 H3 ~8 s$ B0 |
  15. def completed(st) :$ O& d: m$ v9 v" y* @6 Y. G" l& f! A. M
  16. st.setState(COMPLETED)9 s5 N: z4 K& f$ Z6 L7 J9 o
  17. st.clearQuestDrops()* v$ i3 f' d+ `& b. O8 V
  18. st.takeItems(FANGS_ITEM_ID,-1)
    5 h& r# q# G% U% m1 o  ~* ~
  19. st.giveItems(WORLD_MAP_ITEM_ID,1)& \5 _3 a& k1 b* q
  20. st.exitQuest(False)# q! _% g$ \4 s" v% N9 k
  21. return3 Z6 l, U  \6 k$ M, g1 r
  22. " Z: {: M' u2 e8 I6 N
  23. def check(st) :
    + A2 c9 r" v+ Z
  24. if getCount(st) >= 4 :
      }7 K- p  c2 y0 d% g
  25. completed(st)
    & d: x: S* {: D& F
  26. return: X1 o- M7 o8 H5 y9 v0 E

  27. ' B8 l, d, M$ R# \
  28. class Quest (JQuest):. W# R9 @. y; s% }: R4 f- F# X  u  [
  29. 5 w5 S2 m& W* L7 k) Q, Q
  30. def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)! p, m0 L0 s1 O1 m' O

  31. * e& G* }4 I1 Z9 M
  32. def onEvent (self,event,st):
    , [& A+ ]8 s3 X6 ]; X. j! Y
  33. id = st.getState()  }2 C2 N: H# R2 @
  34. if id == CREATED : st.setState(STARTED)
    2 g3 x: S7 D$ L
  35. elif id == COMPLETED: pass
    / p$ X. {6 ]* q
  36. elif id == STARTED : check(st)1 s5 h9 [! a: X. P
  37. return
    ! |9 [6 ?) I1 c/ J% S
  38. - r% a" G- l' d# J
  39. def onKill (self,npcId,st):  z1 ]6 K3 c; |7 m9 F
  40. if npcId == KELTIR_NPC_ID:4 a; j& Q0 D# d  @: n
  41. n = getCount(st), ?( t% e# C, q6 F, u
  42. if n == 0:5 T5 s# D& c0 G1 G' G/ {3 S! |
  43. if st.get('chat0') == None :8 U4 w/ h2 j5 y' y: u
  44. st.set("chat0", "true")
    . F5 G/ U; h3 Y8 q# R0 w
  45. return "Chat0.htm"+ u! ?. r$ R4 F1 M% S8 ~1 B
  46. elif n == 1:# O% I0 h0 h4 p4 S
  47. if st.get('chat1') == None :
    , M! _" d" e0 q" K6 R# w
  48. st.set("chat1", "true")
    ( R3 T# k1 o: C* Z: o1 s$ s4 w: C6 X, b
  49. return "Chat1.htm"
    6 V7 H/ Q# s8 F% A0 M/ S
  50. elif n >= 4:- J7 U3 {" p  Q! n) m2 I
  51. return "Chat4.htm"# {6 H2 U1 _, r% {2 s  b" \
  52. return "Collect "+str(n)+" of 4 fangs"
    + \& S2 `6 Q% E
  53. return
    ( X2 a, v3 e: S* y+ d6 O: c0 [
  54. # s/ n4 R8 }+ C2 u& b9 C) ~/ o) f1 C. r
  55. QUEST    = Quest(201, "Tutorial", "Tutorial quest")5 j4 x( [% p1 ]! _# I
  56. CREATED = State('Start',    QUEST)- i, n* {8 h! ?* _' F# k; M& W
  57. STARTED = State('Started', QUEST)
    ) o( Y  R3 i/ w
  58. COMPLETED = State('Completed', QUEST)8 ?! `. }3 E9 b) M
  59. * G+ H6 g+ N1 X. i5 t
  60. QUEST.setInitialState(CREATED)
    4 q! X5 `4 j1 N3 R
  61. QUEST.addStartNpc(7056)3 t* Y5 a9 r! f' i: e/ J) F
  62. QUEST.addStartNpc(7012)7 s: V9 ]4 D$ ?+ P5 B: D5 G2 R5 d6 |
  63. QUEST.addStartNpc(7009)4 y( Y' c8 w& h+ k$ v, b
  64. QUEST.addStartNpc(7011)% e8 D, s/ H) e1 \

  65. 3 h: i& E' O4 L5 |8 O
  66. STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)9 b7 q- a. `) t6 N" F
  67. STARTED.addKillId(KELTIR_NPC_ID)& ?4 W& Q: [9 ^; Q. P5 t/ y2 `2 b4 n
  68. STARTED.addTalkId(7056), u5 P* q! d4 s* ~) _
  69. STARTED.addTalkI d(7012)8 @0 b* q) z; m3 V/ [, y
  70. STARTED.addTalkId(7009)% g9 y1 @; ~: T: c1 T+ E
  71. STARTED.addTalkId(7011)
Скопировать код

1 G5 I2 c7 j& H" {( u0 {5 c& N& F4 f2 q6 E3 [' m" X% M
Чтобы ответить, вам надо авторизироваться в системе Вход | Зарегистрироваться

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

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

638638758

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

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

admin@artace.ru Онлайн

QR-код

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