Top.Mail.Ru

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

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

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

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

x
Хроники        Interlude
* f& B5 \" t0 \8 H" }8 l. eСборка        L2j
! i/ [) V; G7 k8 p+ ?: A' rОбратите внимание: в файле htm стартового NCP обязательно должна быть ссылка на квест:
3 e# i) L+ |* C) w; ]8 W
  1. STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код
Для этого квеста больше ничего не надо. Все необходимое для корректной работы квеста уже добавили. Вот полный текст квеста:3 J/ K& k( M# B$ L* B& S, ~

' J0 o! M4 A! K4 s& c; e6 g- ~
  1. if getCount(st) >= 4 :4 j& `9 V5 {+ n
  2. completed(st)
    ! F% z! v/ g2 Q. @  [1 P
  3.   return! D% }% Q4 @# M

  4. 3 I. F1 e) x) [8 _6 L$ H6 Z
  5. class Quest (JQuest):
    " M6 G0 D, n4 ^' H1 S6 H- W$ N
  6.   def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)
    4 B" L6 ^0 \  }
  7.   def onEvent (self,event,st):
    6 A3 r/ e, p0 C# _3 h
  8. id = st.getState()
    7 D$ [9 D! l1 V- @
  9. if   id == CREATED  : st.setState(STARTED)
    , y3 B3 q) u) q7 D4 _
  10. elif id == COMPLETED: pass
    4 C# [% U: h- W! u3 V
  11. elif id == STARTED  : check(st)/ [. j3 w8 U& t% o$ d
  12. return  X6 z( r7 f5 ~  L7 I4 h
  13. 7 N2 U' |/ \; g4 ~5 f0 T5 n
  14. QUEST     = Quest(201,"Tutorial", "Tutorial quest")' L! d3 C* w( U* J  q
  15. CREATED   = State('Start',     QUEST)
    : V/ `. n" X! ?# r9 @
  16. STARTED   = State('Started',   QUEST)# K; n$ m. K+ L
  17. COMPLETED = State('Completed', QUEST)
    : O/ l$ f  ?$ {' F

  18. * Q! W. B# @1 U; G8 e
  19. QUEST.setInitialState(CREATED)
    ! ?; u$ @+ W! x9 j6 R& n6 H( G
  20. QUEST.addStartNpc(7056)
    5 s  K1 s2 U  t) T
  21. STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код
Теперь рассмотрим, как это работает.
; ?3 @. v  e$ IИгрок подходит к начальному NCP (в данном случае 7056), нажимает на «Quest». Квест будет создан и состояние квеста перейдет к CREATED и игроку будет показана страничка Start.htm с описанием квеста. Тогда метод onEvent, поле открытия странички Start.htm переведет состояние квеста в STARTED и игроку будет показана страничка Started.htm, где будет опсание того, как найти keltirs и .т.д.5 V# q1 P' u2 g4 R1 |) p

0 M2 _6 d! [% Z9 U0 s3 c

7 h4 o, M: Y4 L+ FПри состоянии STARTED будет зарегистрирован дроп «fangs» при убийстве keltirs. Игрок может вернуться к стартовому NCP и спросить о квесте – метод onEvent будет вызван снова. Если у игрока не хватает необходимого количества предметов, то метод check() не переведет квест в следующее состояние и Started.htm будет показана снова. Но если игрок собрал необходимее количество предметов (в данном случае 4 клыка), то метод check() вызовет метод completed() который переведет квест в новое состояние COMPLETED, заберет все клыки, даст карту мира, т.к. это награда за квест, покажет Completed.htm и завершит квест.; [3 M# C) \  `

9 r* |# W. V( U' n0 |$ f
6 @6 X$ f: q- ^. Z6 s. U" I
Теперь давайте сделаем наш квест более похожим на то, что он должен из себя представлять.8 w, k; S; r4 ~) ~, i: Q8 ?
Прежде всего у нас есть 3 метода для объявления их в Яве – onTalk, onKill и onEvent. Если методы onTalk и onKill не объявлены, то за них все будет делать метод onEvent, т.е. определять квестовых монстров и вызывать диалоги NCP. Есть примечание, методы onTalk и onKill будут вызывать только диалоги с NCP в зависимости от текущего состояния квеста. Метод onKill будет вызываться только тогда, когда мы убиваем квестового монстра.
$ G4 x# a8 b! \6 P
! c( A* e9 ], d; z! K) w

* F: u( E& c% K3 Q+ p7 fДавайте рассмотрим как вызывается метод onKill при убийстве keltir в состоянии квеста STARTED:3 W/ _. f; K5 R1 I4 g! j4 D/ z  W- M
  1. STARTED.addKillId(KELTIR_NPC_ID)
Скопировать код
и метод onKill в классе Quest:+ v- Q3 }* |; D: h

$ d: w2 A3 H0 C( b3 L4 I- O
  1. class Quest (JQuest):
    * a. G$ t# [/ v4 q
  2.   ..." u+ H3 K6 m% N/ k3 f% D  V. ?$ [
  3.   def onKill (self,npcId,st):
    " ^% `) ?- n, r3 K# w$ W
  4. if npcId == KELTIR_NPC_ID:
    $ a0 ?2 V" {8 V7 D! ?) X
  5.    n = getCount(st)
    % }. T9 O; v& P0 i" a
  6.    if   n == 0:
    4 \2 T; Q3 i# _0 P* M. ]
  7.        return "Chat0.htm"
    + ^% M* R8 l* X9 x
  8.    elif n == 1:
    % F: E$ K0 J6 K( O  s* N3 N" w
  9.        return "Chat1.htm"$ D. n/ U; E6 v
  10.    elif n >= 4:3 C, o; `6 T" a+ S& Y
  11.        return "Chat4.htm"3 |  X& K( |2 L) j+ T% A: [' j
  12.    return "Collected "+str(n)+" of 4 fangs"
    " Y* O: S2 r* v
  13. return
Скопировать код
Метод onKill (а так же метод onTalk) имеет следующие параметры:
  X! `+ E# c" x. J! N! P  G  x5 v8 K& P5 A/ @( ~$ e5 f* q
) ?4 v# x3 S' |% U' N
• self – квест
# }6 D: h. ~3 r1 {• npcId – ID NCP, которого мы должны убивать (если это метод onTalk, то ID того NCP, с которым мы должны поговорить).
, |, c( L. m+ W. j0 h2 ?• st – текущее состояние игрока.! Y+ i7 G/ R2 W# b* [! a

/ T# Z! Z' G! d4 R

( d+ }* s) \& k) Z% n! }В этом методе мы проверяем и отмечаем, является ли убитый NCP keltir’ом. В основном эта проверка не нужна, т.к. у нас только KELTIR_NPC_ID.6 Y6 r3 u$ B8 \- f

) ?% A% f+ O4 _" _$ g' L
) l% r4 Q4 X4 ?# F# n7 I
Затем проверяем количество предметов (в данном случае количество клыков), и если их вообще нет, то возвращаем строку "Chat0.htm", если только один предмет, то возвращаем строку "Chat1.htm", если же предметов 4 или больше, то "Chat4.htm". Если строка возвращена из методов onEvent, onKill или onTalk, то сервер покажет соответствующие htm. В Chat0.htm может иметь следующий текст: «Вы не имеете ни одного клыка, возвращайтесь позже, когда соберете 4 штуки и бла, бла, бла…», в Chat1.htm может быть следующий текст: «У Вас всего 1 клык, по этому соберите еще…». В Chat4.htm – «Вы собрали необходимое количество предметов, возвращайтесь к вашему тренеру, что бы завершить квест…»
/ M* p  D+ q$ T- C
1 ?! v+ M. C6 ?( \( m! d$ d
) R. K( J" H' ?5 u5 s& A8 i! O# Q
Примечание: если в строка return начинается с "<html>", то будет показана страничка html с текстом, который стоит далее. Так вместо:
2 J# r7 |8 Y8 e% ]) rreturn "Chat4.htm"# C0 K; P$ W; Q0 e1 ~5 C+ h
: m! P5 Q8 w5 \5 |

" ]$ @5 I9 w$ j  w7 }. _* G9 ^можно поставить:3 ~9 a( {- q+ w, V- O4 j
  1. return "<html><body>Return to your trainer to complete the quest</body></html>"
Скопировать код
Так же если строка заканчивается без .htm или в начале нет <html>, то текст будет выведен, как системное сообщение в окне чата. В нашем случае мы сделаем так, что бы при каждом убийстве keltik выводилось системное сообщение: «Собрано N из 4-х клыков».
9 V% I. i7 c" @% `
  y- ~: p! X6 J9 Y6 `, S" e3 f. b4 Y

/ E7 B. p5 l, C+ TНаш код для onKill имеет один недостаток. Он будет постоянно показывать Chat0.htm, Chat1.htm и Chat4.htm, нам же необходимо, что бы Chat0.htm и Chat1.htm показывались только один раз. Как нам это сделать? С помощью переменных.
; m' c4 m  ]3 U6 z/ Q# ~
2 |& B" `% x4 I+ N, |: f. h* r

6 n6 ~2 n& f3 q" q( ?, O3 [В каждом квесте строки могут храниться с помощью переменных. Эти переменные сохраняются в Вашей БД. В каждом методе мы можем назначить, прочитать и удалить переменные. Давайте изменим метод onKill, так что бы каждый диалог вызывался только один раз.; I: q; Y9 F& J0 j* E% u
  1. def onKill (self,npcId,st):) o: N8 a/ o- P8 u- ^
  2. if npcId == KELTIR_NPC_ID:
    1 q2 e% ~- f  v: m" \" w' |, x, w
  3. n = getCount(st)
    4 J/ ^- L6 B% V+ x$ ^
  4. if n == 0:7 D8 C! i; [' R
  5. if st.get('chat0') == None :
    / j8 w2 C4 M& H4 l. Y
  6. st.set("chat0", "true")
    9 P; K' g: c% v. ^; A, n' r
  7. return "Chat0.htm"% u4 P" j' |# |& U. r
  8. elif n == 1:
    4 _1 n/ S5 P+ J8 a. d( h
  9. if st.get('chat1') == None :( t6 l+ ]4 L6 v. A( d, H
  10. st.set("chat1", "true")
    4 e9 X) Q1 h1 I5 @
  11. return "Chat1.htm"
    : b! y6 c; y9 X7 \! ?
  12. elif n >= 4:' E& h1 w5 [) e1 \' g. L# V
  13. return "Chat4.htm"
    2 F8 N  f/ S" _2 @" T! u( E* }
  14. return "Collected "+str(n)+" of 4 fangs"
    ; ]; A; ?# D6 K
  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." X+ d1 b% n) B6 C8 D

) K' `6 V: k( a- R. d! ?
0 P; B+ a# o# T! D! K* G& S& t$ w  P& d
Вот конечный рабочий вариант квеста:- k+ c9 Z" r$ p+ h8 C
  1. import sys
    4 c4 b3 n$ M, G( l
  2. from net.sf.l2j.gameserver.model.quest import State
      _: h- Q+ x4 V) j
  3. from net.sf.l2j.gameserver.model.quest import QuestState" {* Q9 O. n( e! q( g8 {; ~$ y% P
  4. from net.sf.l2j.gameserver.model.quest.jython import QuestJython as JQuest/ L0 u4 s4 v+ z) S+ y6 D
  5. . k+ k9 q0 s# O4 c! a
  6. KELTIR_NPC_ID = 120828 D! r4 S6 @& Z, L# D, P  C0 y
  7. FANGS_ITEM_ID = 1859- V3 g4 V  i. K4 ~, Y2 e+ g& x
  8. DROP_RATE    = 500000
    : {  A: l, w. r2 l

  9. + r* |% B  F1 S. q3 n2 q
  10. WORLD_MAP_ITEM_ID = 16650 q( H/ k; @  p& C- `% x, ]& Q) w/ Y  H
  11. ! d( d7 ?0 }7 m$ A
  12. def getCount(st) :
      z. ?2 X  k/ \/ a/ V7 h
  13. return st.getQuestItemsCount(FANGS_ITEM_ID)' _  h9 e& }1 |1 s& L' |" C
  14. * f& |, O8 J* `( U& M: n) }
  15. def completed(st) :
    " O" A# k  e9 |, M( r5 @; v
  16. st.setState(COMPLETED)7 {0 k, Q8 A& s0 S
  17. st.clearQuestDrops()$ f1 H( f: L3 T4 s
  18. st.takeItems(FANGS_ITEM_ID,-1)
    3 m/ J+ m! e8 Y/ k0 w
  19. st.giveItems(WORLD_MAP_ITEM_ID,1)$ M4 @. I! j6 X5 v4 ^3 L4 M* V
  20. st.exitQuest(False)
    7 y. t8 v% R4 W+ c3 h* g
  21. return4 I# J5 ?' }' A% f" e. n

  22. % C4 U3 b3 U! @% X" E9 E3 u' B
  23. def check(st) :
    # f/ L  Q  P$ B) x' v3 L! t
  24. if getCount(st) >= 4 :
    $ P; v; o, M. \! y+ O
  25. completed(st)6 ]( B' S- o, _! D
  26. return; D9 A2 t" f9 Y7 \& l& P! k) ~5 Z$ G, R

  27. " p0 z7 A3 O9 W' p* [
  28. class Quest (JQuest):" a- I& y( r5 j6 D( E, r
  29. ( i7 S& L: X2 m( Z) E
  30. def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)3 W" a* G! o* T( A8 M
  31. % T. y- a7 l8 ]3 N" B5 |; ]
  32. def onEvent (self,event,st):3 N- P! v- `$ E0 ~/ Y' `
  33. id = st.getState()
    3 c& B& U8 n+ g# O1 b5 |1 O( R* a
  34. if id == CREATED : st.setState(STARTED)
    . g' `7 q2 U' q; D$ \9 R  W
  35. elif id == COMPLETED: pass
    : J+ ?/ N; }8 j$ t+ ]* L
  36. elif id == STARTED : check(st)( D/ U& ]. T" p
  37. return+ w- H* q, C! N2 x! M% |

  38. : _' `( Z( U2 \4 [% J* ^" k
  39. def onKill (self,npcId,st):
    0 Q' J) f% y: X" I
  40. if npcId == KELTIR_NPC_ID:9 n1 S1 j; ]3 T/ C; n  {' w2 n8 O
  41. n = getCount(st). [2 |8 m8 X5 [/ b; K6 e+ F3 u
  42. if n == 0:
    - h1 f( W# c& w# D- t* V
  43. if st.get('chat0') == None :8 {. d9 f+ d  a5 {6 R4 B
  44. st.set("chat0", "true")
    3 T; c0 c2 |% H7 A7 Z
  45. return "Chat0.htm"
    4 |, D9 }# ?/ F7 `' F& G- ~/ {) m
  46. elif n == 1:% [3 E0 j) _8 z' K* ?! y; q, M: Y: N
  47. if st.get('chat1') == None :
    * V; X8 D. e( n: m/ Z+ h8 W# [# V
  48. st.set("chat1", "true")
    ; F3 {: r  N4 _! z& x  R# E
  49. return "Chat1.htm"9 j( f9 Y* \4 @- _
  50. elif n >= 4:
    # ?. [2 T( p  i, b3 f
  51. return "Chat4.htm"
    . a' n. R' u# P, W# m
  52. return "Collect "+str(n)+" of 4 fangs"* g  W  Y5 O9 s; G( G. z- h" {
  53. return
    & R$ S2 @3 p, I7 A3 m2 Z5 F

  54. , k% `0 I3 {+ F/ u" r/ R# ?
  55. QUEST    = Quest(201, "Tutorial", "Tutorial quest"): D: e( e2 f1 P# J4 {- R- y8 m  Y
  56. CREATED = State('Start',    QUEST)& {' T: s7 t; s5 w8 j$ S( @- ^
  57. STARTED = State('Started', QUEST)
    5 \# I5 V: N3 m' w6 v# p
  58. COMPLETED = State('Completed', QUEST)3 x, [( `6 U. s, P5 p

  59. ) N! i) {4 b* f( c) K
  60. QUEST.setInitialState(CREATED)
    # X- R9 e1 y6 |' E8 k' J! l9 ?
  61. QUEST.addStartNpc(7056)
    1 f4 g/ U' ^# e" g2 S6 A& x  @
  62. QUEST.addStartNpc(7012)
    ' @6 L2 O, Y% i, F' r
  63. QUEST.addStartNpc(7009), w" b8 r4 D: R/ U  N
  64. QUEST.addStartNpc(7011)3 \5 ]# C# ?) n7 K
  65. * `. H% p. ^* k4 V3 \
  66. STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)/ J5 \2 h% z. D, q
  67. STARTED.addKillId(KELTIR_NPC_ID)
    % J- I4 @0 n, F- g
  68. STARTED.addTalkId(7056)) r- {6 X# b3 _! m0 C1 [4 B6 P
  69. STARTED.addTalkI d(7012)
    ! F* K* ]9 Q8 h& ?& u3 c
  70. STARTED.addTalkId(7009)! L: A( H+ }( U, H! g
  71. STARTED.addTalkId(7011)
Скопировать код
7 o" z' K# t/ ]/ N9 z9 L8 y
1 J1 K9 j3 H& {3 p
Чтобы ответить, вам надо авторизироваться в системе Вход | Зарегистрироваться

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

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

638638758

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

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

admin@artace.ru Онлайн

QR-код

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