Top.Mail.Ru

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

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

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

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

x
Хроники        Interlude
7 h9 m/ q9 y. q; ~- K& P) {9 {Сборка        L2j
% x9 p$ [. A2 S* r6 m1 c5 VОбратите внимание: в файле htm стартового NCP обязательно должна быть ссылка на квест:" C+ V0 P  g# R& {7 g3 i0 H- d
  1. STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код
Для этого квеста больше ничего не надо. Все необходимое для корректной работы квеста уже добавили. Вот полный текст квеста:5 H1 P# {7 Y0 c' ]0 |
$ A+ e1 K; L7 y' ^0 l& c
  1. if getCount(st) >= 4 :. v. i: \, q" X+ d
  2. completed(st): A( V# S  e" D; _6 r9 @; u
  3.   return
    ( }9 h0 J" |1 e: t7 u  y1 h

  4. 1 h* I& z& t4 K$ r9 g7 w; S
  5. class Quest (JQuest):
    $ P5 b; m* c8 K- Y, l/ A1 B
  6.   def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)
    4 e" ~1 M4 f: [
  7.   def onEvent (self,event,st):! t5 Z& b  T( L) v
  8. id = st.getState()
    9 p. {5 ]  u" \: ^( e7 _5 N
  9. if   id == CREATED  : st.setState(STARTED)
    ' v9 K3 K! f. j& f
  10. elif id == COMPLETED: pass
    5 p2 c. `. W% k" H2 b0 }5 a
  11. elif id == STARTED  : check(st)
    " l: K3 b1 P. l! V% l8 Q: b/ z
  12. return9 u- i. l0 t5 u3 }/ r4 U0 u

  13. 4 P% a" E4 O# x1 }) _
  14. QUEST     = Quest(201,"Tutorial", "Tutorial quest")
    : @" C' |0 ]3 s; y
  15. CREATED   = State('Start',     QUEST)
    $ g1 U& x, f+ }0 x' O% l/ T* S
  16. STARTED   = State('Started',   QUEST)
      ~. W: }6 y+ [
  17. COMPLETED = State('Completed', QUEST)
    : \1 H" o) C6 v

  18. % W0 m; A* j" T5 q% {, M
  19. QUEST.setInitialState(CREATED). b5 o9 ^* I( z& |) J8 W1 r2 g
  20. QUEST.addStartNpc(7056)
    3 j% z1 r; T& c8 @" c! q# c1 L, ~
  21. STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код
Теперь рассмотрим, как это работает.; S! @% Q  _) c+ `; g5 n
Игрок подходит к начальному NCP (в данном случае 7056), нажимает на «Quest». Квест будет создан и состояние квеста перейдет к CREATED и игроку будет показана страничка Start.htm с описанием квеста. Тогда метод onEvent, поле открытия странички Start.htm переведет состояние квеста в STARTED и игроку будет показана страничка Started.htm, где будет опсание того, как найти keltirs и .т.д.
/ q+ [0 B" r( Z  [/ y
) n* K" F& u# l6 e
! \- b, k' p$ C1 [
При состоянии STARTED будет зарегистрирован дроп «fangs» при убийстве keltirs. Игрок может вернуться к стартовому NCP и спросить о квесте – метод onEvent будет вызван снова. Если у игрока не хватает необходимого количества предметов, то метод check() не переведет квест в следующее состояние и Started.htm будет показана снова. Но если игрок собрал необходимее количество предметов (в данном случае 4 клыка), то метод check() вызовет метод completed() который переведет квест в новое состояние COMPLETED, заберет все клыки, даст карту мира, т.к. это награда за квест, покажет Completed.htm и завершит квест.
5 N3 r$ T, }5 ~; M
4 ]! n& d8 u; ~5 G) f: o

9 k* A4 |; b9 j' zТеперь давайте сделаем наш квест более похожим на то, что он должен из себя представлять.
- t- f. C. q2 t  w5 vПрежде всего у нас есть 3 метода для объявления их в Яве – onTalk, onKill и onEvent. Если методы onTalk и onKill не объявлены, то за них все будет делать метод onEvent, т.е. определять квестовых монстров и вызывать диалоги NCP. Есть примечание, методы onTalk и onKill будут вызывать только диалоги с NCP в зависимости от текущего состояния квеста. Метод onKill будет вызываться только тогда, когда мы убиваем квестового монстра.. k9 ]( M% ~: t- Q& ]& S1 O
3 |. f3 z% e* t( q( G
3 i, v: D8 `4 l, l! H8 H+ ^2 h" d
Давайте рассмотрим как вызывается метод onKill при убийстве keltir в состоянии квеста STARTED:
+ T# P+ J* i  j1 ~+ p
  1. STARTED.addKillId(KELTIR_NPC_ID)
Скопировать код
и метод onKill в классе Quest:; d' @0 @+ u$ q$ z4 l
* u+ Z  H4 ?% Z! `& u% ~* h' f0 R" M
  1. class Quest (JQuest):+ z+ I: z2 D9 P( Q+ {/ G- c7 q" n
  2.   ...
    5 Z- Q6 n7 ~  B  ^3 M
  3.   def onKill (self,npcId,st):: l6 w! d( ^; Q" [, G3 n2 |4 Z
  4. if npcId == KELTIR_NPC_ID:! t: K/ ~* S" w% v6 \& V
  5.    n = getCount(st)
    " ^2 i5 Z* y9 R1 e7 I8 Q" f
  6.    if   n == 0:
    ) q( g/ A8 m7 w& \8 _
  7.        return "Chat0.htm"$ O4 G: |$ p) ?
  8.    elif n == 1:
    6 v  O; I1 P* C; y& }+ ~
  9.        return "Chat1.htm"
    1 O6 ~) h' Z) j- `; U; J
  10.    elif n >= 4:2 N/ k. f) _6 b# a5 @# b
  11.        return "Chat4.htm"
    $ m. y: c; A( ]7 H" @! g& r
  12.    return "Collected "+str(n)+" of 4 fangs"( y& Y# p9 U/ a
  13. return
Скопировать код
Метод onKill (а так же метод onTalk) имеет следующие параметры:. ]* m. M1 I8 f" q* F: b. k

" g0 t* b  L! c' g: _

( P' T3 D  d8 n$ J3 r• self – квест
, M& I3 g# r& `+ V• npcId – ID NCP, которого мы должны убивать (если это метод onTalk, то ID того NCP, с которым мы должны поговорить).
7 V" @- P0 K3 K2 R5 i8 }" @! C3 V• st – текущее состояние игрока.
1 Q; Y: X& B) }6 w$ S" s1 a7 S. s
) E  ~3 i; u$ ?) n6 P4 O! [

+ n: g  L* u& e* N. E& f; J: t. MВ этом методе мы проверяем и отмечаем, является ли убитый NCP keltir’ом. В основном эта проверка не нужна, т.к. у нас только KELTIR_NPC_ID.& e1 L, M+ Z# J; w% E
0 V2 M; M2 I* @, k2 p3 a

& f6 v* ]3 s$ YЗатем проверяем количество предметов (в данном случае количество клыков), и если их вообще нет, то возвращаем строку "Chat0.htm", если только один предмет, то возвращаем строку "Chat1.htm", если же предметов 4 или больше, то "Chat4.htm". Если строка возвращена из методов onEvent, onKill или onTalk, то сервер покажет соответствующие htm. В Chat0.htm может иметь следующий текст: «Вы не имеете ни одного клыка, возвращайтесь позже, когда соберете 4 штуки и бла, бла, бла…», в Chat1.htm может быть следующий текст: «У Вас всего 1 клык, по этому соберите еще…». В Chat4.htm – «Вы собрали необходимое количество предметов, возвращайтесь к вашему тренеру, что бы завершить квест…»
% Z$ Y9 n% A3 C0 r0 d& x6 G* E3 y* m2 b4 T& Q7 e) P

, ?! \6 U, K. Z- O+ i8 w, ?! [Примечание: если в строка return начинается с "<html>", то будет показана страничка html с текстом, который стоит далее. Так вместо:' N6 z4 D# D- {/ }- u) E
return "Chat4.htm"
  @$ j5 Y" }/ l4 U/ f
8 s/ M! R: y- X$ r! x

# @9 u* {8 C5 `# nможно поставить:
! n  h2 Q0 r# f" a7 j# [7 q! f2 \( S
  1. return "<html><body>Return to your trainer to complete the quest</body></html>"
Скопировать код
Так же если строка заканчивается без .htm или в начале нет <html>, то текст будет выведен, как системное сообщение в окне чата. В нашем случае мы сделаем так, что бы при каждом убийстве keltik выводилось системное сообщение: «Собрано N из 4-х клыков».
- C$ R, j8 w2 X' G& Q7 ]# _
! O/ _5 t! O: {

0 S' V) t/ X  v, N8 SНаш код для onKill имеет один недостаток. Он будет постоянно показывать Chat0.htm, Chat1.htm и Chat4.htm, нам же необходимо, что бы Chat0.htm и Chat1.htm показывались только один раз. Как нам это сделать? С помощью переменных., i6 _4 ^! E$ }& `; f
+ [7 ^; ?/ r- @3 q

7 \1 ?$ @; V( r& ?8 n9 {В каждом квесте строки могут храниться с помощью переменных. Эти переменные сохраняются в Вашей БД. В каждом методе мы можем назначить, прочитать и удалить переменные. Давайте изменим метод onKill, так что бы каждый диалог вызывался только один раз.
6 o3 R* P# E# z/ R' _+ m
  1. def onKill (self,npcId,st):
    6 k4 q, f) r+ s9 P
  2. if npcId == KELTIR_NPC_ID:; W  i! g& A' R$ a; o( O1 z+ a9 w
  3. n = getCount(st)$ a* v+ X7 I: j( D% g
  4. if n == 0:
    ' A: G, b6 |8 V, O
  5. if st.get('chat0') == None :
    3 T+ D; q( h2 R
  6. st.set("chat0", "true")* w( o3 `* R4 F) t( c6 n1 U3 x. s
  7. return "Chat0.htm"
    0 ]$ m" G5 ?8 M( Z/ Z2 F5 ?
  8. elif n == 1:/ P1 J; Y$ E0 l0 ~2 R# k
  9. if st.get('chat1') == None :7 H+ w8 C/ A# s
  10. st.set("chat1", "true")
    ' q) D) q2 l5 u6 K& H4 _6 G; T0 E
  11. return "Chat1.htm". j* S8 _$ n. z0 D2 @7 `
  12. elif n >= 4:
    * _8 P3 `) t$ L* a9 u, o
  13. return "Chat4.htm"- _. k! j6 G5 K" }
  14. return "Collected "+str(n)+" of 4 fangs"
    ; G  R5 U- R$ t6 ^
  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.
% |. n; ?; b6 ^% b! a
: v, N& _8 I  U  d& v! X; Z& d
, a; v, X. d, Y" J# Z2 q- H+ q
Вот конечный рабочий вариант квеста:1 ~5 m+ t8 ~2 r7 q; N3 L
  1. import sys
    6 @" C4 |3 Y8 }& d% N) m9 g
  2. from net.sf.l2j.gameserver.model.quest import State' V, `1 E5 p: F' T! m; {$ c
  3. from net.sf.l2j.gameserver.model.quest import QuestState* Z7 S( e  E+ @# H8 s3 l; D
  4. from net.sf.l2j.gameserver.model.quest.jython import QuestJython as JQuest
    4 T8 k9 C9 |. o, n

  5. 0 G# ~7 \. l7 D/ m$ n
  6. KELTIR_NPC_ID = 120827 L0 k6 y2 k; @1 s8 N1 G
  7. FANGS_ITEM_ID = 1859
    , [) c3 V0 s0 ^& `2 n
  8. DROP_RATE    = 500000# B  ]0 V& T2 `* k" w; B  B

  9. $ s. ~* K$ F/ a7 L3 L
  10. WORLD_MAP_ITEM_ID = 1665
    ( A5 F8 i" m" M3 h* @( A
  11. / C! U* S0 }% b( t2 F  o
  12. def getCount(st) :
    / [* s* c$ }! ^2 v
  13. return st.getQuestItemsCount(FANGS_ITEM_ID)
    : p* N" G! J) x, n; p: J6 ?
  14. 1 U* m: s9 y7 Q; s2 N
  15. def completed(st) :
    7 s& @/ z7 N/ S& R; e+ t
  16. st.setState(COMPLETED)- B% `. d3 L+ y4 i% s9 V+ ]
  17. st.clearQuestDrops(). }( B  l7 v8 M8 k
  18. st.takeItems(FANGS_ITEM_ID,-1)
    / j4 L; M# W7 Z, N! ~% m
  19. st.giveItems(WORLD_MAP_ITEM_ID,1)8 H9 m9 t. k1 _
  20. st.exitQuest(False)
    ' C) [1 P5 F$ f1 K9 `6 q. R
  21. return
    : @- _+ d- q) K. k  S
  22. ' J  W& Q# k; C
  23. def check(st) :2 q: s5 p: P) x# H1 r
  24. if getCount(st) >= 4 :
    , x4 h# N1 P, U! h% [7 R. O
  25. completed(st)- m* E  M  V# V* {# ^) k% O
  26. return
    , [" `8 x4 J6 g7 M
  27. * Z, z$ U5 e! V4 B: L
  28. class Quest (JQuest):& M: z% R0 R7 J( v
  29. 3 z1 u2 v: J, k! ?2 t
  30. def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)
    " L: S) p; _- |6 [7 E0 ]9 p' v
  31. 9 W, G( R3 l* b4 T0 w
  32. def onEvent (self,event,st):  ^% E+ f; e: K0 L, S
  33. id = st.getState()' O! {- B- p* n! @, R9 z" c: O
  34. if id == CREATED : st.setState(STARTED)
    ! w) D- \5 ]: b! z$ _
  35. elif id == COMPLETED: pass5 f! r" y0 \/ V( J
  36. elif id == STARTED : check(st)- c4 s! R  _' r* k' x
  37. return
    / o6 m+ L- V* c2 P" T6 t  ?
  38. & n2 I3 k* _# ~3 ^8 ]0 q
  39. def onKill (self,npcId,st):
    4 |: ^2 Z* s/ I+ f
  40. if npcId == KELTIR_NPC_ID:
    5 k" D7 j0 X* W( @% i6 l0 }& i
  41. n = getCount(st)" q. a: @" t0 O$ o6 S) ]  c! D1 n. M
  42. if n == 0:' d: T3 y: k  ]+ O! `3 U) B: C3 K% e
  43. if st.get('chat0') == None :
    8 Y2 p8 H5 z3 }5 Z$ V
  44. st.set("chat0", "true")3 `7 y# }; e% m8 m; V; ^* v
  45. return "Chat0.htm"
      M" o1 M1 s7 \- U! b
  46. elif n == 1:
    ' `  R" P/ T4 Q$ |
  47. if st.get('chat1') == None :
    7 ?+ w2 \& o$ D3 F; w8 B1 A4 _2 M
  48. st.set("chat1", "true")
    4 A- X  e. `+ ^+ G2 W' X1 f9 j
  49. return "Chat1.htm"
    , D  _5 d/ _: L8 V) P  k
  50. elif n >= 4:
    & U6 |# a' @) D$ ^/ E6 h7 B) q
  51. return "Chat4.htm"4 r! h. _, ?( M& J  R0 P
  52. return "Collect "+str(n)+" of 4 fangs"
    * Q: y) Q+ w% J2 D
  53. return; A5 Q% e& V8 [" \$ j2 F! c3 X
  54. + O+ C* `; F6 a: u- e, t! C
  55. QUEST    = Quest(201, "Tutorial", "Tutorial quest")  w1 a# ]. b1 ]" y2 w) C' s
  56. CREATED = State('Start',    QUEST)
    ( U9 z* I) v' J4 |& i5 o: M! \" U
  57. STARTED = State('Started', QUEST)
    # E+ q3 G$ S" {; {5 s# @! ]3 o
  58. COMPLETED = State('Completed', QUEST); b+ R% B% _# N+ s9 Z* U

  59. 7 [3 x/ X* r2 u! D- K
  60. QUEST.setInitialState(CREATED)( k& a  c0 J  Y6 s! l# J* w
  61. QUEST.addStartNpc(7056)
    " p9 p7 R- _1 U" K# f
  62. QUEST.addStartNpc(7012)
    $ O. n% C% P. W: ]: W% D9 o
  63. QUEST.addStartNpc(7009)
    ! r1 W, m. h6 A7 r
  64. QUEST.addStartNpc(7011)$ S) V. A. W4 Q. v4 M' i& T" {9 Y
  65. 0 K7 B. U: B. ~6 f: ]1 j6 h
  66. STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
    + u8 G  z, t% t6 o+ c5 O4 @5 P9 J
  67. STARTED.addKillId(KELTIR_NPC_ID)
      `7 g! w$ ?& F7 v+ H% s
  68. STARTED.addTalkId(7056)" D- h5 u- e# h$ @! T" |, [, }3 G
  69. STARTED.addTalkI d(7012)
    1 D% |! B2 g8 ~$ t2 ^
  70. STARTED.addTalkId(7009), y3 @+ ^& g6 o* P3 G4 E
  71. STARTED.addTalkId(7011)
Скопировать код
: i4 y0 |! Y9 m" ^, E
8 O0 R& q" N5 G
Чтобы ответить, вам надо авторизироваться в системе Вход | Зарегистрироваться

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

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

638638758

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

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

admin@artace.ru Онлайн

QR-код

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