Top.Mail.Ru

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

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

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

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

x
Хроники        Interlude2 Q+ E$ H# y0 J/ W+ ^) D
Сборка        L2j
6 _) ~0 H7 X% @' `Обратите внимание: в файле htm стартового NCP обязательно должна быть ссылка на квест:
+ u# U" [: s, c' T
  1. STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код
Для этого квеста больше ничего не надо. Все необходимое для корректной работы квеста уже добавили. Вот полный текст квеста:8 h6 q: h5 f! H

" P# a* W( b' B! _
  1. if getCount(st) >= 4 :
    / D% c. W+ B# t7 U3 Z7 T
  2. completed(st)
    ! o9 c5 Z) m; Y  M- a0 w( p
  3.   return$ T, r% W0 y: Q2 a0 x0 ?8 y

  4. * B7 \* z- e1 o8 |( ^3 a) F
  5. class Quest (JQuest):
    " E' V4 @; ~. s3 \
  6.   def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)4 |  b. z/ A6 Z" @7 B
  7.   def onEvent (self,event,st):* G6 J5 n: p' \
  8. id = st.getState()
    0 W" j  m; z$ q" P' B/ w$ j
  9. if   id == CREATED  : st.setState(STARTED)
    ( ^$ W) D5 K8 E( Z- L7 L3 |: y
  10. elif id == COMPLETED: pass
    + Q0 P9 C7 B8 V5 u
  11. elif id == STARTED  : check(st)
    ) H/ L: D2 p( u  E; k  `) Y; Q# j
  12. return
    - j8 E6 [8 h1 L5 c& r$ e5 p9 H

  13. 5 L" B1 }) k- K  F3 B* J
  14. QUEST     = Quest(201,"Tutorial", "Tutorial quest")
    ! _% [% |, K. i# w9 z$ _
  15. CREATED   = State('Start',     QUEST)
    & d4 ]8 }& a2 S8 _
  16. STARTED   = State('Started',   QUEST)
    ! u. `0 n2 d& _$ q5 W
  17. COMPLETED = State('Completed', QUEST)$ x; L- c! r, k: O. r' P3 |$ T# \
  18. 8 R& x# c: L6 V8 x6 \% R( r4 }! ?6 g
  19. QUEST.setInitialState(CREATED)2 T5 c' m, m0 i' R! i0 H5 d% d1 ~
  20. QUEST.addStartNpc(7056)+ h" |& K; _& S  Y" i$ }' y
  21. STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код
Теперь рассмотрим, как это работает.) n2 j8 l( n" U( z1 {- I
Игрок подходит к начальному NCP (в данном случае 7056), нажимает на «Quest». Квест будет создан и состояние квеста перейдет к CREATED и игроку будет показана страничка Start.htm с описанием квеста. Тогда метод onEvent, поле открытия странички Start.htm переведет состояние квеста в STARTED и игроку будет показана страничка Started.htm, где будет опсание того, как найти keltirs и .т.д.5 K# B. V$ R' P6 z
8 L0 o0 Q& o& q7 M8 H
6 Y: u- m6 }7 T8 O) l
При состоянии STARTED будет зарегистрирован дроп «fangs» при убийстве keltirs. Игрок может вернуться к стартовому NCP и спросить о квесте – метод onEvent будет вызван снова. Если у игрока не хватает необходимого количества предметов, то метод check() не переведет квест в следующее состояние и Started.htm будет показана снова. Но если игрок собрал необходимее количество предметов (в данном случае 4 клыка), то метод check() вызовет метод completed() который переведет квест в новое состояние COMPLETED, заберет все клыки, даст карту мира, т.к. это награда за квест, покажет Completed.htm и завершит квест.
8 Y/ C! ]& V6 B) O5 b: h2 \9 F$ J& J) n( F
& }6 a5 c% B; w$ h: l5 D
Теперь давайте сделаем наш квест более похожим на то, что он должен из себя представлять.+ I1 H- w1 R/ t. d7 j) I
Прежде всего у нас есть 3 метода для объявления их в Яве – onTalk, onKill и onEvent. Если методы onTalk и onKill не объявлены, то за них все будет делать метод onEvent, т.е. определять квестовых монстров и вызывать диалоги NCP. Есть примечание, методы onTalk и onKill будут вызывать только диалоги с NCP в зависимости от текущего состояния квеста. Метод onKill будет вызываться только тогда, когда мы убиваем квестового монстра.# o' L0 k+ I. o% [
9 F+ \7 |, s# i/ X  Y4 d
6 [0 E8 |# `& O! t- d. }( h$ A* d
Давайте рассмотрим как вызывается метод onKill при убийстве keltir в состоянии квеста STARTED:) _8 T" L" I; d& h% `& V3 l
  1. STARTED.addKillId(KELTIR_NPC_ID)
Скопировать код
и метод onKill в классе Quest:
3 L$ a) v' }! A& K3 F( I8 T9 t6 v4 R/ E2 n% \" s% F4 l; b* Y
  1. class Quest (JQuest):2 K2 {/ L" c# S/ N
  2.   ..., Z0 m7 K- y. y* e* f# `1 Q3 o
  3.   def onKill (self,npcId,st):( @, v4 ~9 r' X
  4. if npcId == KELTIR_NPC_ID:" X. x$ E( N0 b9 _- ^" N3 T9 }2 z
  5.    n = getCount(st)( e7 z6 g$ Q$ R7 q3 s  b
  6.    if   n == 0:+ v0 [$ q1 C0 c
  7.        return "Chat0.htm"
    * v& I6 e6 s9 [% _  A& J* \: E% ~
  8.    elif n == 1:, E2 g0 k0 w' t" a; n0 C
  9.        return "Chat1.htm"
    + X# x2 ]! Z* p1 h% e( z* _8 p6 K0 e
  10.    elif n >= 4:& k) B* E, h1 {1 z
  11.        return "Chat4.htm"
    & f1 F7 g# |6 E
  12.    return "Collected "+str(n)+" of 4 fangs"
    0 Y. \' X" ~* [- ?+ }0 A
  13. return
Скопировать код
Метод onKill (а так же метод onTalk) имеет следующие параметры:5 ~+ N& K. G! M) u
" Z$ e/ \$ D6 p
1 x$ E* T+ z+ y' g* F0 n9 ~- m6 G
• self – квест
8 h0 |6 q& Q' z5 B: u' F* Z• npcId – ID NCP, которого мы должны убивать (если это метод onTalk, то ID того NCP, с которым мы должны поговорить).
0 M  B6 O9 n/ ?; N8 L3 \• st – текущее состояние игрока.
+ V  B9 [. Y, A. g9 Z8 u) g) z; k! C+ E
8 C* _4 ~4 a6 R( Z" w9 [
В этом методе мы проверяем и отмечаем, является ли убитый NCP keltir’ом. В основном эта проверка не нужна, т.к. у нас только KELTIR_NPC_ID.: s: N- G: r- M
- y1 ~, j. w* q- g2 |( C; t
: m- F. B  I; y' a" f4 P
Затем проверяем количество предметов (в данном случае количество клыков), и если их вообще нет, то возвращаем строку "Chat0.htm", если только один предмет, то возвращаем строку "Chat1.htm", если же предметов 4 или больше, то "Chat4.htm". Если строка возвращена из методов onEvent, onKill или onTalk, то сервер покажет соответствующие htm. В Chat0.htm может иметь следующий текст: «Вы не имеете ни одного клыка, возвращайтесь позже, когда соберете 4 штуки и бла, бла, бла…», в Chat1.htm может быть следующий текст: «У Вас всего 1 клык, по этому соберите еще…». В Chat4.htm – «Вы собрали необходимое количество предметов, возвращайтесь к вашему тренеру, что бы завершить квест…»3 V2 Q5 K1 H/ t) ~/ y
$ N" j" G5 j. d" W* `+ e& Z
! Y3 E+ Q) P& b! |
Примечание: если в строка return начинается с "<html>", то будет показана страничка html с текстом, который стоит далее. Так вместо:
( S6 p, k8 a9 y# rreturn "Chat4.htm". l% V( R1 o" J3 u" p: Y
! p5 h3 w& x8 j% O

0 `/ |* `6 ?% f4 U! Q) S- d; }можно поставить:& U  k5 {% I( t1 w
  1. return "<html><body>Return to your trainer to complete the quest</body></html>"
Скопировать код
Так же если строка заканчивается без .htm или в начале нет <html>, то текст будет выведен, как системное сообщение в окне чата. В нашем случае мы сделаем так, что бы при каждом убийстве keltik выводилось системное сообщение: «Собрано N из 4-х клыков».1 r2 A/ m9 }- p& b) d
: x9 ~) m  y5 n8 h0 A0 I* a
1 k/ F6 m5 l+ U% Q, h
Наш код для onKill имеет один недостаток. Он будет постоянно показывать Chat0.htm, Chat1.htm и Chat4.htm, нам же необходимо, что бы Chat0.htm и Chat1.htm показывались только один раз. Как нам это сделать? С помощью переменных.
6 Z* \' J( b, y) g0 Q; A
1 [$ h8 m$ z4 h8 R7 d. B) ?

2 q3 \% W. P+ r  E; V2 y* yВ каждом квесте строки могут храниться с помощью переменных. Эти переменные сохраняются в Вашей БД. В каждом методе мы можем назначить, прочитать и удалить переменные. Давайте изменим метод onKill, так что бы каждый диалог вызывался только один раз." S4 D, J. ?/ u. T/ W$ Q
  1. def onKill (self,npcId,st):, ?+ H) w- {: P9 @/ D( ~
  2. if npcId == KELTIR_NPC_ID:
    8 c  f+ k3 m" u2 |* \  q
  3. n = getCount(st)( p1 X. c9 s" E9 b  V) U8 P3 k
  4. if n == 0:
      ?, H8 {* J- G" c5 W
  5. if st.get('chat0') == None :8 Z+ f5 Q' \5 }/ g
  6. st.set("chat0", "true"). {5 s5 V8 K% Z7 j% A8 g
  7. return "Chat0.htm"1 O4 }0 n( S4 q7 d: f5 j/ u
  8. elif n == 1:
    ! z# Z9 Q4 ]9 m# }0 S3 S3 C& U& O9 v9 |
  9. if st.get('chat1') == None :
    . ]$ x5 p6 B9 i% `+ `3 Y+ y
  10. st.set("chat1", "true")( g* A" {3 u" Z2 q5 Q
  11. return "Chat1.htm"9 d0 a+ p% l# R6 T6 S
  12. elif n >= 4:3 S( S" E9 f; `; p6 j" V) ?
  13. return "Chat4.htm"4 j5 p: m3 E" [5 u- z. O* O8 j- g
  14. return "Collected "+str(n)+" of 4 fangs"
    + Y9 l! U. ^$ A9 p4 F% y/ B" {1 G
  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.' y( n! M( g* @+ F$ S' l
3 s! O- a( m$ s5 y/ W: C
" V) }& Q- m: U0 ^; b! P" s% x
Вот конечный рабочий вариант квеста:% r* R% q, M! Y; ?. D" E& ]
  1. import sys9 a% u, H+ \4 J$ j( X5 m
  2. from net.sf.l2j.gameserver.model.quest import State
      l2 p0 K: c5 s4 S
  3. from net.sf.l2j.gameserver.model.quest import QuestState4 g) d7 P2 u7 n& I
  4. from net.sf.l2j.gameserver.model.quest.jython import QuestJython as JQuest
    ' b4 K" o& g8 W+ j& H5 S9 B/ S2 k
  5. 3 a  Q+ R+ `! m( E* U, Z
  6. KELTIR_NPC_ID = 12082
    7 {$ C# e! t, Q8 u: R! C$ I
  7. FANGS_ITEM_ID = 1859
    0 ]! T! w# f* m- W) q+ [, Z
  8. DROP_RATE    = 500000
    2 G4 E$ q# s& L+ B
  9. & `. o+ |' B' `. x5 ~- f
  10. WORLD_MAP_ITEM_ID = 1665
    + S( x) `% A1 w1 e! b; v6 `: F

  11. * f& n$ r2 S/ h
  12. def getCount(st) :
    . u6 @& t, P) u0 P
  13. return st.getQuestItemsCount(FANGS_ITEM_ID)" J' R+ w8 u2 C$ V/ I+ J; S: y, [
  14. ' x1 f0 q. A) W) W! x) D' D8 o) p
  15. def completed(st) :( @: k4 r% N; Q0 t0 W
  16. st.setState(COMPLETED)% }' d+ t/ F% G3 ^0 @" P% Z
  17. st.clearQuestDrops()
    # `! K  C- J- X/ M- c# }' r
  18. st.takeItems(FANGS_ITEM_ID,-1)% q9 R2 F7 g# ^: e8 f( `0 d$ t
  19. st.giveItems(WORLD_MAP_ITEM_ID,1)
    % a+ e1 K3 W5 N! v% i
  20. st.exitQuest(False), j, P9 u- X0 H$ t: E2 Y. H
  21. return. {  o8 I& _' s1 E) x

  22. / v# o+ J1 V8 w$ ~
  23. def check(st) :( B; D- I$ Y8 ~0 o
  24. if getCount(st) >= 4 :1 W# J" t0 ?9 V; ?- p( ^/ s
  25. completed(st)' Z5 {9 t  J: ]1 `5 s. x2 k" P
  26. return/ {# y+ d( ~$ d; L
  27. + B8 u5 {& K  T1 P( x1 Q9 H1 J
  28. class Quest (JQuest):2 W. U8 c' _# t  e/ C
  29. 4 y5 ]& ]0 |" s9 w6 [& b* {
  30. def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr); P1 L1 I; A7 T

  31. $ V% m8 M0 l9 l& n/ I, q# f7 F
  32. def onEvent (self,event,st):6 V! \( r+ H" i& X! i
  33. id = st.getState(), g0 F, L7 n. w6 A1 A* f4 ?
  34. if id == CREATED : st.setState(STARTED)4 N) I& x# {) y" d- \9 {. {: g
  35. elif id == COMPLETED: pass
    ! k9 b1 H5 W: a% A& Y: |% D& o7 X) J
  36. elif id == STARTED : check(st)2 ~, F! _8 \3 i# o
  37. return
    3 j2 M! r6 e- ^: A2 s9 d

  38. % o4 P  ]& K' M; s7 e' @5 A) U
  39. def onKill (self,npcId,st):& R2 n4 A0 i( H5 |
  40. if npcId == KELTIR_NPC_ID:
    . y+ k# ~7 S" V1 z, V$ R
  41. n = getCount(st)
    , ]. A" i( m' u8 S) K0 i5 k1 C- Q
  42. if n == 0:9 P8 i: [+ w$ b- t
  43. if st.get('chat0') == None :
    " x& [( d4 e# g$ p  o5 `) b% Q  C8 e
  44. st.set("chat0", "true")( k' I9 m: I2 j; N
  45. return "Chat0.htm"
    # I# r- S: ?  I+ t7 F$ L
  46. elif n == 1:6 `+ z6 e1 x/ d7 P; H! z
  47. if st.get('chat1') == None :
    $ n/ }% O& l* t4 `, o; {0 B
  48. st.set("chat1", "true")! V, f, d  _- d4 a" S" _/ m
  49. return "Chat1.htm": g3 J3 [6 K. n; r+ _" Y5 D
  50. elif n >= 4:
    % I( R0 \4 E8 \! v; d6 W$ e
  51. return "Chat4.htm"
    : D" Y5 r( Z+ L! m7 d0 Z
  52. return "Collect "+str(n)+" of 4 fangs"8 h* ?0 K# e& |2 S
  53. return
    , v4 f  Z( K% z; q

  54. 2 K% n4 l  r) Z3 G& V$ I/ L1 \: b
  55. QUEST    = Quest(201, "Tutorial", "Tutorial quest")" L& c6 J* e$ D2 ?% H+ I
  56. CREATED = State('Start',    QUEST)
    : _7 `1 V) W  z" H$ Z
  57. STARTED = State('Started', QUEST)
    / e; G6 l: j- ^
  58. COMPLETED = State('Completed', QUEST)4 P: V. H5 T6 d8 h: r
  59. * W+ H, @2 q6 ~% I7 p+ T
  60. QUEST.setInitialState(CREATED)7 `# Y6 z8 p+ Z5 D8 E& ?
  61. QUEST.addStartNpc(7056)6 j% H2 \% I0 O4 S0 T8 _
  62. QUEST.addStartNpc(7012)
    : T: O% A* L' o8 S- v- ]. g& l
  63. QUEST.addStartNpc(7009)  M5 E- C) e9 \+ k) u, X
  64. QUEST.addStartNpc(7011)1 k' E! P& j; u' c

  65. 3 _* g% Q9 v. u
  66. STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
    - L- S' F; o# q8 m. N
  67. STARTED.addKillId(KELTIR_NPC_ID)
    & t! n( K, m% B
  68. STARTED.addTalkId(7056)
    % w. D# W  w, w) T* Q* V3 f
  69. STARTED.addTalkI d(7012)) J7 r! y3 u2 X- ^- O" S. s
  70. STARTED.addTalkId(7009)! S$ O  }$ @1 s$ v* ?
  71. STARTED.addTalkId(7011)
Скопировать код

( T- g. v; Y  [* A' P5 T* p  P  X
Чтобы ответить, вам надо авторизироваться в системе Вход | Зарегистрироваться

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

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

638638758

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

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

admin@artace.ru Онлайн

QR-код

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