Top.Mail.Ru

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

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

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

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

x
Хроники        Interlude- f1 C# a7 E/ H! w8 l7 \. ]3 H1 D8 {
Сборка        L2j+ L) m8 ^. J* f, ?5 k+ v
Обратите внимание: в файле htm стартового NCP обязательно должна быть ссылка на квест:  J' a6 z/ B; \0 p1 K$ p& q4 ]' |% O
  1. STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код
Для этого квеста больше ничего не надо. Все необходимое для корректной работы квеста уже добавили. Вот полный текст квеста:  v4 I6 e* G4 n# V  P; f0 F
0 u- n. \- r: ^$ B, S  ^% [
  1. if getCount(st) >= 4 :: Z& W$ @) T( P3 v
  2. completed(st)
    ; S/ n) }' v* T' y% k9 @  ]! Y
  3.   return
    " U2 @! `/ `& ^

  4. - x' a: ?' ]+ Z" b. \
  5. class Quest (JQuest):1 K2 K% o2 p+ e+ v' \! |# K7 N
  6.   def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)
    % D* `4 E/ N& P  I2 [5 @1 k, x
  7.   def onEvent (self,event,st):
    1 L5 j+ H. `, h, }' G6 F, e
  8. id = st.getState()/ L, w, M( T. y7 R+ [1 \. D
  9. if   id == CREATED  : st.setState(STARTED)
    ' _% ~4 m  Z4 j- F' F
  10. elif id == COMPLETED: pass; s8 \! w. z3 R
  11. elif id == STARTED  : check(st)! q1 e5 y, H4 v, K) Q4 ]- n8 a  k
  12. return
    , H4 z9 B* x! S0 M6 T: ?& [

  13. # r9 s; q7 R8 o: D0 f* j6 O
  14. QUEST     = Quest(201,"Tutorial", "Tutorial quest")
    4 L' q; l1 Y; }6 J
  15. CREATED   = State('Start',     QUEST)( c" l1 S3 {$ _" M; V9 b4 e
  16. STARTED   = State('Started',   QUEST)
    1 S2 K7 E) C9 |6 N$ D7 H
  17. COMPLETED = State('Completed', QUEST)* Z9 X5 a- V% \* D. j% ?7 X
  18. : R* V. Q6 W  ?) x3 S5 U: ~
  19. QUEST.setInitialState(CREATED)
    , i! X; k. w3 w: a% V7 U8 _
  20. QUEST.addStartNpc(7056)
    : W8 R  x% i1 z: ?! m+ r
  21. STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код
Теперь рассмотрим, как это работает.1 ?! t( W& m, P1 e  R6 f4 o
Игрок подходит к начальному NCP (в данном случае 7056), нажимает на «Quest». Квест будет создан и состояние квеста перейдет к CREATED и игроку будет показана страничка Start.htm с описанием квеста. Тогда метод onEvent, поле открытия странички Start.htm переведет состояние квеста в STARTED и игроку будет показана страничка Started.htm, где будет опсание того, как найти keltirs и .т.д.; P* E; }0 w8 z. l4 V: C
+ _" C" K5 b0 n8 d2 [
; ~; e/ I' k9 j* T2 ^
При состоянии STARTED будет зарегистрирован дроп «fangs» при убийстве keltirs. Игрок может вернуться к стартовому NCP и спросить о квесте – метод onEvent будет вызван снова. Если у игрока не хватает необходимого количества предметов, то метод check() не переведет квест в следующее состояние и Started.htm будет показана снова. Но если игрок собрал необходимее количество предметов (в данном случае 4 клыка), то метод check() вызовет метод completed() который переведет квест в новое состояние COMPLETED, заберет все клыки, даст карту мира, т.к. это награда за квест, покажет Completed.htm и завершит квест.) c3 H( b' C1 e1 k# z. O
7 F" Z- {: k  k- |6 n# |
( `7 R. j* V  U# l2 s
Теперь давайте сделаем наш квест более похожим на то, что он должен из себя представлять.* x- J5 w$ u0 C  m& {# n* J
Прежде всего у нас есть 3 метода для объявления их в Яве – onTalk, onKill и onEvent. Если методы onTalk и onKill не объявлены, то за них все будет делать метод onEvent, т.е. определять квестовых монстров и вызывать диалоги NCP. Есть примечание, методы onTalk и onKill будут вызывать только диалоги с NCP в зависимости от текущего состояния квеста. Метод onKill будет вызываться только тогда, когда мы убиваем квестового монстра.
! L& H5 b# I- t  M' y7 ~2 s3 ]' V2 E$ ]0 [* J$ Z' l( D

' Z+ h8 m4 [1 lДавайте рассмотрим как вызывается метод onKill при убийстве keltir в состоянии квеста STARTED:/ l/ R6 E! `1 Q! C% y5 h- T
  1. STARTED.addKillId(KELTIR_NPC_ID)
Скопировать код
и метод onKill в классе Quest:: T9 E5 R, z& {9 W: `
. C7 Z& Z) P$ y
  1. class Quest (JQuest):/ R# ?$ \; h4 X8 F5 G
  2.   ...
    ( m* W1 @6 k- E* ~# |/ Y# V6 m2 D7 l
  3.   def onKill (self,npcId,st):
    $ G. K8 n/ V! {+ H+ N: O4 O( U
  4. if npcId == KELTIR_NPC_ID:6 |" L" ?  I0 [& D7 ~
  5.    n = getCount(st)! I$ J& i8 }# w+ _% B
  6.    if   n == 0:
    ; ^7 Y' x+ L7 h9 M
  7.        return "Chat0.htm"9 H) ]0 |( n5 l7 G; |" d
  8.    elif n == 1:) p6 R6 o: f* y, e+ E9 P  q
  9.        return "Chat1.htm"
    / M* a8 K5 J$ X
  10.    elif n >= 4:! Z6 Q3 K7 K: k6 K/ b2 e
  11.        return "Chat4.htm"1 g) t1 C' Q! b3 Z. I
  12.    return "Collected "+str(n)+" of 4 fangs"
    5 N+ n; L- w" H& V6 ~: `
  13. return
Скопировать код
Метод onKill (а так же метод onTalk) имеет следующие параметры:% N  b  H4 Z& X% N4 h
$ @2 l  j" Z9 W$ M) w+ g

8 Y$ L2 m5 _5 O! L8 N& ]8 x/ j9 [• self – квест
+ q. a8 l+ U" W" Z# q• npcId – ID NCP, которого мы должны убивать (если это метод onTalk, то ID того NCP, с которым мы должны поговорить).
! V8 l/ u% _& a) I! N9 c' O# K• st – текущее состояние игрока.4 I' R# O  L4 b! y

- u6 [0 z6 [* e: n- g) C- z" U
# o" _. K" T& V, I" }
В этом методе мы проверяем и отмечаем, является ли убитый NCP keltir’ом. В основном эта проверка не нужна, т.к. у нас только KELTIR_NPC_ID.
6 {- n4 k9 V- d8 a
/ A" j; e8 u* O# _/ Z7 O: u

( q8 m) r7 ?& T- ~) lЗатем проверяем количество предметов (в данном случае количество клыков), и если их вообще нет, то возвращаем строку "Chat0.htm", если только один предмет, то возвращаем строку "Chat1.htm", если же предметов 4 или больше, то "Chat4.htm". Если строка возвращена из методов onEvent, onKill или onTalk, то сервер покажет соответствующие htm. В Chat0.htm может иметь следующий текст: «Вы не имеете ни одного клыка, возвращайтесь позже, когда соберете 4 штуки и бла, бла, бла…», в Chat1.htm может быть следующий текст: «У Вас всего 1 клык, по этому соберите еще…». В Chat4.htm – «Вы собрали необходимое количество предметов, возвращайтесь к вашему тренеру, что бы завершить квест…»
8 t. t* G# F: L/ j4 M6 P( t
( `: U( Q: z; ?2 q" a

2 g- e' R) V! ?- f: s" v8 w: GПримечание: если в строка return начинается с "<html>", то будет показана страничка html с текстом, который стоит далее. Так вместо:
4 a1 t0 w9 f1 _return "Chat4.htm"
! Q- i6 |/ H( P8 |; K% O/ X/ E* L4 z) z; i

9 T1 `  L0 b# E& ]* E4 c* Y; sможно поставить:5 K9 g" `- [, F* {; E0 b' ?
  1. return "<html><body>Return to your trainer to complete the quest</body></html>"
Скопировать код
Так же если строка заканчивается без .htm или в начале нет <html>, то текст будет выведен, как системное сообщение в окне чата. В нашем случае мы сделаем так, что бы при каждом убийстве keltik выводилось системное сообщение: «Собрано N из 4-х клыков»., U. ?! ?* h: M  M' s

, k$ ~+ V6 n1 B7 D( m0 P4 ?

8 z5 A5 b, U2 \' G% zНаш код для onKill имеет один недостаток. Он будет постоянно показывать Chat0.htm, Chat1.htm и Chat4.htm, нам же необходимо, что бы Chat0.htm и Chat1.htm показывались только один раз. Как нам это сделать? С помощью переменных.
; g# Q  }  u' u$ |+ y  N$ F+ K5 X( U% |; d
4 \: |& ~; Z, M: Q7 s6 s& d' l( _' L
В каждом квесте строки могут храниться с помощью переменных. Эти переменные сохраняются в Вашей БД. В каждом методе мы можем назначить, прочитать и удалить переменные. Давайте изменим метод onKill, так что бы каждый диалог вызывался только один раз.: L% a. F! y0 u' ]
  1. def onKill (self,npcId,st):' a; {$ D- y( I; w/ j
  2. if npcId == KELTIR_NPC_ID:! [% l. |/ [7 H! F5 |: A& J
  3. n = getCount(st)
    " _0 B2 w/ @* e3 V& ?
  4. if n == 0:; U- E/ |  t) J
  5. if st.get('chat0') == None :
    ; a4 E3 @! P# i! G' ^, M
  6. st.set("chat0", "true")
    4 I3 K! h1 {8 R' g( v
  7. return "Chat0.htm"
      v& p, g! i1 \
  8. elif n == 1:
    + a/ w4 x% q6 f9 _
  9. if st.get('chat1') == None :
    . p. C6 _+ O4 I" o
  10. st.set("chat1", "true")
    , t- Q) x1 M: C% [1 [
  11. return "Chat1.htm"
    ( k. V3 C+ ^7 {. z/ v
  12. elif n >= 4:
    3 {0 ]% j8 V+ o& p6 N2 H5 k  C
  13. return "Chat4.htm"
    9 _* |' y7 V9 }4 h. ^7 N" D& p
  14. return "Collected "+str(n)+" of 4 fangs"- x; s3 N" r, I3 y! N
  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.7 l2 U+ p% W6 R- _$ p: R* y5 |

% a) D5 r/ n8 e, q3 i
4 `5 X1 P9 `  B, c: @% V( ]5 R
Вот конечный рабочий вариант квеста:
) ?" _$ t/ w6 c: d$ r2 [8 V8 b7 u
  1. import sys
    $ N+ ~! F) c' E6 T5 N; j; v& \9 `
  2. from net.sf.l2j.gameserver.model.quest import State
    % Y6 c7 V2 v# N8 Y* m/ o# ]
  3. from net.sf.l2j.gameserver.model.quest import QuestState
    + T& a. d6 p# F+ j7 I$ B! f+ r
  4. from net.sf.l2j.gameserver.model.quest.jython import QuestJython as JQuest/ X$ [6 e0 y* R

  5. # x# c& o: [# n  v1 Y' J- R9 Z
  6. KELTIR_NPC_ID = 12082
    " p8 A( p  e# M
  7. FANGS_ITEM_ID = 1859. C) W: V( f" C2 @
  8. DROP_RATE    = 5000007 d, t1 S/ n4 ]! w- Y3 t

  9. & I. W4 K4 @* |7 X. x
  10. WORLD_MAP_ITEM_ID = 1665* V4 ]0 ~" F1 ]& C3 v' R
  11. ( r) B6 X1 u) v' o
  12. def getCount(st) :
    7 M0 E0 t) u% q6 K: J
  13. return st.getQuestItemsCount(FANGS_ITEM_ID)  E) V, m4 m; w: e% c# H. n
  14. 8 K# }4 w. D# M0 S# A* y8 g
  15. def completed(st) :" }9 T, C4 f1 g
  16. st.setState(COMPLETED)
    ) r) Q" @: w9 O3 U: j
  17. st.clearQuestDrops()
    , L  H7 u" C: X4 S6 l$ p
  18. st.takeItems(FANGS_ITEM_ID,-1): t" k8 c4 h( x* _( m1 [
  19. st.giveItems(WORLD_MAP_ITEM_ID,1)1 Q- z* w$ e/ l! W$ N
  20. st.exitQuest(False)7 |; @9 X; ^7 x
  21. return8 G8 y( C9 o+ J2 o5 M

  22. 8 Q9 v6 y7 L5 j) @: ]. R
  23. def check(st) :, ~9 W+ \1 R) |. f$ [" i
  24. if getCount(st) >= 4 :3 I9 \# n$ L% f  m) j$ R
  25. completed(st)8 K- t) T  [& U! V6 s+ f
  26. return
    # b9 T7 F/ Q* x8 }: k, N' \0 ]# w

  27. 6 }. R0 \9 p0 h2 w2 c
  28. class Quest (JQuest):
    , H+ m* ]9 H1 N3 d! c

  29. + F! A1 N- W1 ^' {5 p, i
  30. def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)
    6 q. g& \# o1 h2 f& B
  31. 5 L# W! a; k. ?- x6 I, f
  32. def onEvent (self,event,st):; u- e1 I% j& G
  33. id = st.getState()( U0 k! ]+ E# [" V: p1 @+ S7 G
  34. if id == CREATED : st.setState(STARTED)( |- _2 U: q) ?. q
  35. elif id == COMPLETED: pass2 H! N( M9 T+ h5 v4 t4 V
  36. elif id == STARTED : check(st)5 m9 O* i; k" y& g( ^6 V% J
  37. return
    - g5 _( l+ N9 R- e( `
  38. 0 b# `4 k  O9 z& [: Q- k9 P* S
  39. def onKill (self,npcId,st):
    4 P8 `3 P8 r4 e7 Z1 X" D" E
  40. if npcId == KELTIR_NPC_ID:. n6 h$ \7 G8 S1 }' X) y
  41. n = getCount(st): ~; q& h. c: h
  42. if n == 0:) U' f9 n9 \9 d5 j
  43. if st.get('chat0') == None :
    , Z+ \3 U  t; D. P; O$ I/ J" T
  44. st.set("chat0", "true")
    9 E/ K9 V/ I, y* l  D% m
  45. return "Chat0.htm"6 s7 C* K" n) k" i! U* C1 E0 D
  46. elif n == 1:
    ( s. s# w9 H! l; k
  47. if st.get('chat1') == None :$ w; }5 b" u/ N
  48. st.set("chat1", "true")! ?3 e6 V' V( x9 B  }
  49. return "Chat1.htm"
    , q, \% ^2 x8 v0 q. l& K, b& k
  50. elif n >= 4:
    * j  m8 `* S: ]% q# L  M
  51. return "Chat4.htm"
    ; Y/ u6 i" R; c
  52. return "Collect "+str(n)+" of 4 fangs"" W4 D  C) i/ A) s
  53. return
    ( v, |" d) v( h2 [

  54. # w. c$ v# x- {( I! A3 u
  55. QUEST    = Quest(201, "Tutorial", "Tutorial quest")
    , D8 ~) h7 u6 c
  56. CREATED = State('Start',    QUEST)" j, R2 Q+ Y! K$ ?5 c; V, L
  57. STARTED = State('Started', QUEST)
    : ^" `& J" |! b# @) ]8 p  J1 I
  58. COMPLETED = State('Completed', QUEST)
    ' t7 [. r* {- E) l/ P- X

  59. ! n$ r! w( x/ ?! Z5 w4 u
  60. QUEST.setInitialState(CREATED)
    & o. W5 Y: H( X" @5 x. {5 |
  61. QUEST.addStartNpc(7056)0 U6 k" s5 f0 O" z+ I9 B
  62. QUEST.addStartNpc(7012); s  Z. g+ p9 V. O
  63. QUEST.addStartNpc(7009)0 b& W5 I2 H2 X/ T
  64. QUEST.addStartNpc(7011), F, C* m/ d- D
  65. 3 l6 |3 ]% m. o. z+ b4 c
  66. STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
    3 C: ?8 P) U4 R$ E
  67. STARTED.addKillId(KELTIR_NPC_ID)7 a4 `& `8 T2 y+ ?
  68. STARTED.addTalkId(7056)' u. J$ u# a5 m6 a7 z4 O% l
  69. STARTED.addTalkI d(7012)2 f4 b0 k+ W( ~! s
  70. STARTED.addTalkId(7009)
    " g* u0 n' g3 _. B* z2 R4 W
  71. STARTED.addTalkId(7011)
Скопировать код

% a" e$ V- _( H: o( {0 ~9 _) _1 s- p& A- L1 U4 Q
Чтобы ответить, вам надо авторизироваться в системе Вход | Зарегистрироваться

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

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

638638758

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

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

admin@artace.ru Онлайн

QR-код

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