Top.Mail.Ru

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

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

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

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

x
Хроники        Interlude. Y( N& K6 J* `8 \
Сборка        L2j- \- L$ a: ~: n7 w0 @& [
Обратите внимание: в файле htm стартового NCP обязательно должна быть ссылка на квест:+ S5 Z& |' \$ v! k% E
  1. STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код
Для этого квеста больше ничего не надо. Все необходимое для корректной работы квеста уже добавили. Вот полный текст квеста:
% J% Q. u$ ]8 K5 k: w; ^/ n) b; Y" O, W$ I! {
  1. if getCount(st) >= 4 :$ |1 I$ \& \" c- _; H" z1 O5 y  F, r
  2. completed(st)
    ' I9 W7 }5 }% _' q+ L: K+ _
  3.   return
    ; X, L. y& U: D" ?) R; v+ y8 |; o

  4. 6 h; d# [8 G5 q- W
  5. class Quest (JQuest):
    % v- ]+ C& k$ X
  6.   def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr). x8 P) |9 i7 S4 V& V
  7.   def onEvent (self,event,st):
    " D* w' A4 k" y/ @
  8. id = st.getState()
    & j% P5 g* y' f/ v* ]6 c
  9. if   id == CREATED  : st.setState(STARTED)3 |3 G4 z3 o, T
  10. elif id == COMPLETED: pass
    8 z! @2 u- O) m, e- ]$ b. U
  11. elif id == STARTED  : check(st)  A0 S5 T0 I! ?% t! q
  12. return
    5 c$ L. ?2 M5 Q) k7 S, S! u

  13. 7 P2 i2 t& U8 [! J2 f' @
  14. QUEST     = Quest(201,"Tutorial", "Tutorial quest")2 r/ V! ?/ X5 |& q' G9 C
  15. CREATED   = State('Start',     QUEST)
    + h7 R: ~  q2 }' T/ m( z3 ^5 G' L
  16. STARTED   = State('Started',   QUEST)6 L; M' T2 p$ W% ?# O; ?
  17. COMPLETED = State('Completed', QUEST)( _+ u: K' k2 h

  18. % A: _; d; O' _/ u
  19. QUEST.setInitialState(CREATED)
    ' [. r& }/ _+ ^5 d
  20. QUEST.addStartNpc(7056)
    5 ]. Y! r3 }, L2 H
  21. STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код
Теперь рассмотрим, как это работает.) X, p! o) `+ r
Игрок подходит к начальному NCP (в данном случае 7056), нажимает на «Quest». Квест будет создан и состояние квеста перейдет к CREATED и игроку будет показана страничка Start.htm с описанием квеста. Тогда метод onEvent, поле открытия странички Start.htm переведет состояние квеста в STARTED и игроку будет показана страничка Started.htm, где будет опсание того, как найти keltirs и .т.д.
+ p. M; N2 E% a, b3 c/ c) @* f" [* M' @2 }

9 V4 u, v& S( P: q; P: OПри состоянии STARTED будет зарегистрирован дроп «fangs» при убийстве keltirs. Игрок может вернуться к стартовому NCP и спросить о квесте – метод onEvent будет вызван снова. Если у игрока не хватает необходимого количества предметов, то метод check() не переведет квест в следующее состояние и Started.htm будет показана снова. Но если игрок собрал необходимее количество предметов (в данном случае 4 клыка), то метод check() вызовет метод completed() который переведет квест в новое состояние COMPLETED, заберет все клыки, даст карту мира, т.к. это награда за квест, покажет Completed.htm и завершит квест.
/ W9 \, V9 T7 N4 G' ~1 k6 E0 l: |. V# A$ R( l/ g+ M  X- d0 C4 m7 |$ g
6 y# d" z2 ^- i6 y( O
Теперь давайте сделаем наш квест более похожим на то, что он должен из себя представлять.. \6 N: |0 i' M9 W% R4 W0 [
Прежде всего у нас есть 3 метода для объявления их в Яве – onTalk, onKill и onEvent. Если методы onTalk и onKill не объявлены, то за них все будет делать метод onEvent, т.е. определять квестовых монстров и вызывать диалоги NCP. Есть примечание, методы onTalk и onKill будут вызывать только диалоги с NCP в зависимости от текущего состояния квеста. Метод onKill будет вызываться только тогда, когда мы убиваем квестового монстра.9 Y( X) i9 S3 V7 p1 f

/ I- `& F1 X2 G9 I: z7 X  V
, B. ?7 e( S3 o
Давайте рассмотрим как вызывается метод onKill при убийстве keltir в состоянии квеста STARTED:
0 a1 T$ {0 u2 D) t7 u
  1. STARTED.addKillId(KELTIR_NPC_ID)
Скопировать код
и метод onKill в классе Quest:$ ]& k0 T) t4 W% t/ t8 d

& v4 E4 `( R1 r& B+ P
  1. class Quest (JQuest):
    * H$ B; K: _3 t3 l3 L1 Y- G* g
  2.   ...8 M- _8 j7 L) o2 i
  3.   def onKill (self,npcId,st):
    ! t1 }: g% t& K
  4. if npcId == KELTIR_NPC_ID:
    0 W/ P* M' O- K4 r6 D0 G' n
  5.    n = getCount(st)+ Z: o$ E, R" ^' H, v
  6.    if   n == 0:6 a  l1 W7 [1 x9 G/ v/ ~. c; r
  7.        return "Chat0.htm"
    ) E. }% L6 n, z/ h4 q: T
  8.    elif n == 1:
    # s. [' J  e2 k2 x2 a
  9.        return "Chat1.htm"
    / Y4 \2 o$ A1 g& K. A7 r* W) {1 c
  10.    elif n >= 4:1 r7 f  `, c/ X& U6 Y
  11.        return "Chat4.htm"
    . a( k: v& W. ]7 g6 M6 _
  12.    return "Collected "+str(n)+" of 4 fangs"+ l' ^; I+ I$ T4 ]" S
  13. return
Скопировать код
Метод onKill (а так же метод onTalk) имеет следующие параметры:6 C- q& e$ s( e5 P0 d

4 g) A: L/ I) X3 v

7 D$ q2 X5 X) V2 j• self – квест
- D0 |8 w* G( ]• npcId – ID NCP, которого мы должны убивать (если это метод onTalk, то ID того NCP, с которым мы должны поговорить).5 e2 l2 i8 V4 K7 S; U! \( o) l
• st – текущее состояние игрока.3 O7 L+ M' Y/ L; k
: h' y* @3 t4 f/ A/ ]. P) ]# h5 j

. d8 D5 |2 F3 H: \/ w- jВ этом методе мы проверяем и отмечаем, является ли убитый NCP keltir’ом. В основном эта проверка не нужна, т.к. у нас только KELTIR_NPC_ID.3 Q8 _+ W+ Q6 B7 ?0 Z

3 E) m  [6 y- h# o1 `0 E

5 G. E3 ]6 l* A3 Y  ~- g, RЗатем проверяем количество предметов (в данном случае количество клыков), и если их вообще нет, то возвращаем строку "Chat0.htm", если только один предмет, то возвращаем строку "Chat1.htm", если же предметов 4 или больше, то "Chat4.htm". Если строка возвращена из методов onEvent, onKill или onTalk, то сервер покажет соответствующие htm. В Chat0.htm может иметь следующий текст: «Вы не имеете ни одного клыка, возвращайтесь позже, когда соберете 4 штуки и бла, бла, бла…», в Chat1.htm может быть следующий текст: «У Вас всего 1 клык, по этому соберите еще…». В Chat4.htm – «Вы собрали необходимое количество предметов, возвращайтесь к вашему тренеру, что бы завершить квест…»+ x9 n3 C) t# a9 Y! O
% k9 f; w% a/ T: @% a

; w5 I+ `$ j8 J! vПримечание: если в строка return начинается с "<html>", то будет показана страничка html с текстом, который стоит далее. Так вместо:; e3 x! u3 y* S5 [4 c  B
return "Chat4.htm"0 n$ y% N  j/ a5 B7 E% |

# F% V; `( E2 w. G

) M- k/ j- i$ w' R6 [" S5 pможно поставить:
2 C* F- {% ^/ x  W: [8 ^# ?# F
  1. return "<html><body>Return to your trainer to complete the quest</body></html>"
Скопировать код
Так же если строка заканчивается без .htm или в начале нет <html>, то текст будет выведен, как системное сообщение в окне чата. В нашем случае мы сделаем так, что бы при каждом убийстве keltik выводилось системное сообщение: «Собрано N из 4-х клыков».$ f6 a9 K. m- o  l
* n$ B/ Y; y$ j

( ]' ^  |: e( {/ M, O! N! c1 q  \Наш код для onKill имеет один недостаток. Он будет постоянно показывать Chat0.htm, Chat1.htm и Chat4.htm, нам же необходимо, что бы Chat0.htm и Chat1.htm показывались только один раз. Как нам это сделать? С помощью переменных.5 B2 V9 i9 X' f# Y6 |0 V

& ?5 X7 j. H2 F! ~6 z4 R9 x

+ N' @- B1 `; nВ каждом квесте строки могут храниться с помощью переменных. Эти переменные сохраняются в Вашей БД. В каждом методе мы можем назначить, прочитать и удалить переменные. Давайте изменим метод onKill, так что бы каждый диалог вызывался только один раз.$ O% k% x6 T5 f) ~% r
  1. def onKill (self,npcId,st):
      f0 m0 U9 J5 l7 H1 ~# f$ ~
  2. if npcId == KELTIR_NPC_ID:7 }+ E# T9 m4 U6 [: I; B
  3. n = getCount(st)# v8 K! J2 j. T
  4. if n == 0:+ A2 j3 |3 Z5 W9 S" D
  5. if st.get('chat0') == None :
    - H$ K. j6 T) Z( T5 b8 m/ r4 z
  6. st.set("chat0", "true")
    ; b3 _+ |6 E$ I
  7. return "Chat0.htm"
    0 n" C; ^- A/ o6 Q; W
  8. elif n == 1:# W4 v, v  J" R5 ^3 @8 |9 V, m* R9 a
  9. if st.get('chat1') == None :
    * z, W* S" ?, R. p) U5 A2 b
  10. st.set("chat1", "true")0 v# q! `; X; |5 D9 [7 k. f
  11. return "Chat1.htm"
    % G# m, v, R4 k+ p& z' [
  12. elif n >= 4:
    + b8 ]& M1 T( J% x
  13. return "Chat4.htm"
    $ h4 v  q! @3 K( c, }
  14. return "Collected "+str(n)+" of 4 fangs"/ s, H& ]9 w, T
  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.+ X4 ]4 Q9 y) S/ k+ ~6 f

' v6 x& }& f# @- v

, u; z! u& H: N. x  \2 M6 mВот конечный рабочий вариант квеста:, p- L$ R4 p( N1 Q0 M' A# G3 I
  1. import sys
    3 S( _% k1 a6 ^) t( j1 A
  2. from net.sf.l2j.gameserver.model.quest import State
    ) S. R8 Z9 ~. z
  3. from net.sf.l2j.gameserver.model.quest import QuestState
    ) ]8 h! \  i2 M# ?
  4. from net.sf.l2j.gameserver.model.quest.jython import QuestJython as JQuest0 M- x9 ^* Q! ]2 j8 P& O7 f! @
  5. 5 g' o* M5 Q- p) X9 v  o+ r
  6. KELTIR_NPC_ID = 12082# `" g1 w1 ^- i1 n3 }
  7. FANGS_ITEM_ID = 1859
    9 l7 W* k- o8 m) Q3 r4 v7 E
  8. DROP_RATE    = 500000$ ?$ ~' }- F" z( U, x# V) X) T; o

  9. 6 b3 ~. l7 K# K% L& w; B" Z
  10. WORLD_MAP_ITEM_ID = 1665
    , J8 z; M$ k3 a$ G' o

  11. , }7 b4 K: X5 k9 J& E
  12. def getCount(st) :
    ! B& Z3 z! h5 v# L  \1 a
  13. return st.getQuestItemsCount(FANGS_ITEM_ID)
    1 u1 x, T  H% ^) h% P
  14. 2 o( c# B" r: k, ?# H; W
  15. def completed(st) :7 K2 I+ R, @, E3 \6 b4 D1 X6 p
  16. st.setState(COMPLETED), x1 T2 u, a+ y; D
  17. st.clearQuestDrops()
    5 A, n7 b6 ~& e. u! m
  18. st.takeItems(FANGS_ITEM_ID,-1)
    9 ~7 S: ]# r# D% ^' Q
  19. st.giveItems(WORLD_MAP_ITEM_ID,1)
    ( t' q0 [- R0 r9 J; ~0 C
  20. st.exitQuest(False)* `" s0 l/ V! S9 I
  21. return( I0 V$ N0 k! ~% H- ]" M- c# B
  22. 4 |- H4 |" l  K6 z) o+ I
  23. def check(st) :
    7 s$ y# S4 e! y5 M. s( i
  24. if getCount(st) >= 4 :+ I0 M; J) M' l6 v
  25. completed(st)
    / S9 h5 ?% N% E* y
  26. return
    * @) w$ \0 n+ g) f! o

  27. 5 ^' Z: A* n) ^, E
  28. class Quest (JQuest):7 }9 L# I5 w! v+ e

  29. 0 D' g/ y  ^- ^3 G
  30. def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)* R6 I' x0 P( ~# q: K) l* l& z3 e
  31. + p8 w& {9 U' x) j! E4 Q
  32. def onEvent (self,event,st):. ^+ t5 U. ^9 J
  33. id = st.getState()5 F& w; l: m3 ]1 `
  34. if id == CREATED : st.setState(STARTED)5 X& k, X5 X3 D$ w$ H' @. i
  35. elif id == COMPLETED: pass% u# e& s# R, s% S2 U1 o
  36. elif id == STARTED : check(st)0 v8 f% e2 S% s0 \
  37. return
    1 J9 D' l' G* e+ W8 ?6 ~% p5 c' F

  38. 7 q6 l- P! C# O3 B: j! N/ c
  39. def onKill (self,npcId,st):$ o$ o' ~( p  }) G2 T- T
  40. if npcId == KELTIR_NPC_ID:
    + o! @/ \: ?$ g& l; H
  41. n = getCount(st)( f+ m8 K4 P3 y2 W7 i1 Q" j/ _* l
  42. if n == 0:; G: ^" g1 l: B8 a' a, d
  43. if st.get('chat0') == None :7 K! m: Y2 {5 b& Z: M, {( k* h
  44. st.set("chat0", "true")& u4 S7 {2 l$ b7 K7 P
  45. return "Chat0.htm": d) \5 w! z6 p; r5 U* ]
  46. elif n == 1:3 B. {" s6 N$ u' v9 |
  47. if st.get('chat1') == None :
    ) Z0 C4 s9 Q) \- w, B
  48. st.set("chat1", "true"). ^5 R8 q, S( D  _
  49. return "Chat1.htm"9 n3 z& _2 I/ z- o8 I
  50. elif n >= 4:& B% |$ \: g3 u0 L1 K3 e/ {
  51. return "Chat4.htm"
    ' J" ^( S6 ?0 n% [9 e
  52. return "Collect "+str(n)+" of 4 fangs"- [" B# l+ h* k6 s7 e5 \8 b
  53. return8 L. D' y2 k$ c3 m& T

  54. / ~7 X7 E1 r  J4 Y# R
  55. QUEST    = Quest(201, "Tutorial", "Tutorial quest")/ K! d" U  ^# z3 H
  56. CREATED = State('Start',    QUEST): j' P& V( t" X/ l
  57. STARTED = State('Started', QUEST)5 X9 T8 b" n3 s
  58. COMPLETED = State('Completed', QUEST)* J& g% B# _8 A
  59. 9 `' q/ _: e( ]9 ]8 j, @2 M' t6 t
  60. QUEST.setInitialState(CREATED)0 [. b6 ]  Q; L/ ~) U& N
  61. QUEST.addStartNpc(7056)
    ( P* s( ?& Z7 B, {: L. g7 a& O& {
  62. QUEST.addStartNpc(7012)9 ~2 X- i+ m) _$ }
  63. QUEST.addStartNpc(7009)
    0 V) x  s. t4 ^  _
  64. QUEST.addStartNpc(7011)
    9 r  f: n# N& t

  65. 5 T! s! q3 a6 t# b
  66. STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
    ( K9 c  l" ?. I9 W4 r7 v! F3 N' F
  67. STARTED.addKillId(KELTIR_NPC_ID)4 P$ ^8 O7 d! i1 |7 B; Z0 U
  68. STARTED.addTalkId(7056)
    $ z4 O, R8 ^  N1 ~
  69. STARTED.addTalkI d(7012): Z* w1 t, v/ U* g
  70. STARTED.addTalkId(7009)1 u9 R) S2 p9 m' u2 t! _
  71. STARTED.addTalkId(7011)
Скопировать код
9 k2 h& Z+ O6 r8 l( b' {
% ?4 J0 M% z4 g9 J5 o
Чтобы ответить, вам надо авторизироваться в системе Вход | Зарегистрироваться

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

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

638638758

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

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

admin@artace.ru Онлайн

QR-код

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