Top.Mail.Ru

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

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

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

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

x
Хроники        Interlude* c- G0 m) F5 k6 C; |' m
Сборка        L2j
4 ?' a3 M6 ?1 F+ v; n" EОбратите внимание: в файле htm стартового NCP обязательно должна быть ссылка на квест:
6 o) p0 ^, S+ j; y- y1 Y
  1. STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код
Для этого квеста больше ничего не надо. Все необходимое для корректной работы квеста уже добавили. Вот полный текст квеста:% Y9 n4 N$ k9 n: I. L% L. L

" [8 z1 _  ^6 C7 v0 M9 ~7 h
  1. if getCount(st) >= 4 :! w1 {9 e7 }" c2 ~
  2. completed(st)  s  P( i! y! E8 _, m2 B# `; Q3 p  a0 O
  3.   return( u2 z( i( w% t3 d7 I
  4. 7 Z' d: J3 b5 P* @/ @
  5. class Quest (JQuest):% X2 G5 J5 g' S
  6.   def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)# }9 S9 O/ E! ~  _- S# v4 M( D( U8 z7 G/ k
  7.   def onEvent (self,event,st):: _$ @" Y# H+ G% c( R
  8. id = st.getState()! _# S% \$ D; ]# Z* l
  9. if   id == CREATED  : st.setState(STARTED)
    4 t# ]2 T* y$ |8 i: Q: c/ f4 q
  10. elif id == COMPLETED: pass
    , M7 S2 Z+ `/ q" R/ Q
  11. elif id == STARTED  : check(st)4 ~! D$ R! a- R. `' w/ w2 c: g6 R5 F
  12. return) V( I( B9 Z( e4 o  m% w( r+ ~' r
  13. 8 H) w4 B; C2 v- W
  14. QUEST     = Quest(201,"Tutorial", "Tutorial quest"). i  C0 n, o3 ]8 w* ]
  15. CREATED   = State('Start',     QUEST)
    # |' @  s, P" P7 G
  16. STARTED   = State('Started',   QUEST)1 H9 m2 X* J5 {( W" J+ X
  17. COMPLETED = State('Completed', QUEST)
    & c. g2 B$ q4 `

  18. & ]+ `; {- m5 I, `8 K0 _# r
  19. QUEST.setInitialState(CREATED)
    - @2 |2 L& F# J6 H+ q+ z8 }
  20. QUEST.addStartNpc(7056)
    - w" d) R0 y' w& ^! ]$ h, Q5 ?; P% q
  21. STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код
Теперь рассмотрим, как это работает.1 [. N3 F1 ~, l. i3 n- V
Игрок подходит к начальному NCP (в данном случае 7056), нажимает на «Quest». Квест будет создан и состояние квеста перейдет к CREATED и игроку будет показана страничка Start.htm с описанием квеста. Тогда метод onEvent, поле открытия странички Start.htm переведет состояние квеста в STARTED и игроку будет показана страничка Started.htm, где будет опсание того, как найти keltirs и .т.д.. H, S' w. s4 E1 p3 |! h
! o& y; k  h5 O3 D, P* k- A

  K# _) S% C- H4 n6 b. yПри состоянии STARTED будет зарегистрирован дроп «fangs» при убийстве keltirs. Игрок может вернуться к стартовому NCP и спросить о квесте – метод onEvent будет вызван снова. Если у игрока не хватает необходимого количества предметов, то метод check() не переведет квест в следующее состояние и Started.htm будет показана снова. Но если игрок собрал необходимее количество предметов (в данном случае 4 клыка), то метод check() вызовет метод completed() который переведет квест в новое состояние COMPLETED, заберет все клыки, даст карту мира, т.к. это награда за квест, покажет Completed.htm и завершит квест.
) v' _# X- b5 F2 R8 G( p3 X7 t6 z
3 q, f* P" P  N9 c; x
Теперь давайте сделаем наш квест более похожим на то, что он должен из себя представлять.
5 o6 @" ]7 s/ ]Прежде всего у нас есть 3 метода для объявления их в Яве – onTalk, onKill и onEvent. Если методы onTalk и onKill не объявлены, то за них все будет делать метод onEvent, т.е. определять квестовых монстров и вызывать диалоги NCP. Есть примечание, методы onTalk и onKill будут вызывать только диалоги с NCP в зависимости от текущего состояния квеста. Метод onKill будет вызываться только тогда, когда мы убиваем квестового монстра.
3 Y; [2 z! I, c1 H3 `" G7 e8 J! k0 L* W0 s
- p" F4 V& F' f% P
Давайте рассмотрим как вызывается метод onKill при убийстве keltir в состоянии квеста STARTED:" z  r6 C7 W2 m' m! G) d
  1. STARTED.addKillId(KELTIR_NPC_ID)
Скопировать код
и метод onKill в классе Quest:
5 P/ U8 i& Z. r3 C" |* @* g, z- h- e4 I1 S
  1. class Quest (JQuest):
    ) o% d4 F. d! S5 e
  2.   ...- o: b$ W) T! J& _6 ~+ p* Z6 o. z
  3.   def onKill (self,npcId,st):
    ( N: O' |. n: f# w; p4 x
  4. if npcId == KELTIR_NPC_ID:; o7 N9 m. h* ?$ w, F
  5.    n = getCount(st)
    / i2 x& l' w( n" o% C
  6.    if   n == 0:
    6 x4 r2 i5 N/ o" E8 b5 A' o
  7.        return "Chat0.htm"6 q7 G% w7 a) e6 R  K4 U- j
  8.    elif n == 1:) T* D5 W' O8 h7 U0 h' M+ N
  9.        return "Chat1.htm"6 m$ Z  j% B( ?% d
  10.    elif n >= 4:. l" c3 k) Y" ^, L0 k; ~+ |
  11.        return "Chat4.htm"5 a+ h! D  Q4 `% `
  12.    return "Collected "+str(n)+" of 4 fangs", r* I! T! ]  _4 A/ F
  13. return
Скопировать код
Метод onKill (а так же метод onTalk) имеет следующие параметры:
$ _& J1 n9 {. |8 F& D& U
$ Q/ ~6 R0 ]! ^5 K

6 V! J- L0 A, V! a- Y0 |• self – квест
( _5 t; w9 w5 }3 t1 i- ]; I• npcId – ID NCP, которого мы должны убивать (если это метод onTalk, то ID того NCP, с которым мы должны поговорить).7 k% A3 X. b: {6 X: V
• st – текущее состояние игрока.
+ J* p* p1 |; w* ~. `3 o5 H+ \. n) i; J7 i5 Z
- r/ x# t3 M1 w; x  u, ~
В этом методе мы проверяем и отмечаем, является ли убитый NCP keltir’ом. В основном эта проверка не нужна, т.к. у нас только KELTIR_NPC_ID.3 w) c' q% [2 v$ ^! X

1 f  C$ _; j- q1 H3 S
5 E7 T8 `( x, F6 s
Затем проверяем количество предметов (в данном случае количество клыков), и если их вообще нет, то возвращаем строку "Chat0.htm", если только один предмет, то возвращаем строку "Chat1.htm", если же предметов 4 или больше, то "Chat4.htm". Если строка возвращена из методов onEvent, onKill или onTalk, то сервер покажет соответствующие htm. В Chat0.htm может иметь следующий текст: «Вы не имеете ни одного клыка, возвращайтесь позже, когда соберете 4 штуки и бла, бла, бла…», в Chat1.htm может быть следующий текст: «У Вас всего 1 клык, по этому соберите еще…». В Chat4.htm – «Вы собрали необходимое количество предметов, возвращайтесь к вашему тренеру, что бы завершить квест…»
7 }3 P" o5 p0 z5 |9 @5 ^+ ]6 l5 X2 r+ [

2 Q- R/ j: Y5 d7 JПримечание: если в строка return начинается с "<html>", то будет показана страничка html с текстом, который стоит далее. Так вместо:
+ @/ d  e7 r& Greturn "Chat4.htm"
3 }8 Q3 q0 f2 o; P9 |/ R# _( O) U( r
% t9 D  v* S" p  v$ l+ W8 L
можно поставить:
  j* z2 z4 E9 l: `5 C6 O
  1. return "<html><body>Return to your trainer to complete the quest</body></html>"
Скопировать код
Так же если строка заканчивается без .htm или в начале нет <html>, то текст будет выведен, как системное сообщение в окне чата. В нашем случае мы сделаем так, что бы при каждом убийстве keltik выводилось системное сообщение: «Собрано N из 4-х клыков».0 O) N' P2 k2 L* y9 s" U3 U5 x

! Q9 G" I+ p: U1 r6 R: m3 O
" n9 F  I( h, C; |
Наш код для onKill имеет один недостаток. Он будет постоянно показывать Chat0.htm, Chat1.htm и Chat4.htm, нам же необходимо, что бы Chat0.htm и Chat1.htm показывались только один раз. Как нам это сделать? С помощью переменных.8 C1 g2 s( R, z

- M" Y- E  Y# H2 U5 F, W' g: h

2 _3 \! T9 D* lВ каждом квесте строки могут храниться с помощью переменных. Эти переменные сохраняются в Вашей БД. В каждом методе мы можем назначить, прочитать и удалить переменные. Давайте изменим метод onKill, так что бы каждый диалог вызывался только один раз.
4 |" E4 U! ^2 Z. t" S
  1. def onKill (self,npcId,st):
    5 U, K2 ~- y9 R* Y
  2. if npcId == KELTIR_NPC_ID:
    + W; v, S. i( ^. m' d+ _
  3. n = getCount(st)1 e4 c, [$ {. u# c, ~8 Y
  4. if n == 0:- x+ }; V0 X8 ?! j0 E# e
  5. if st.get('chat0') == None :6 S- i5 x# ^1 U, P  ~
  6. st.set("chat0", "true")
    $ B- P' D6 Y! C; S. ~3 H
  7. return "Chat0.htm"2 }+ e# w. D6 n. E$ Z( R
  8. elif n == 1:
    5 t8 B1 N2 g4 }9 F! `
  9. if st.get('chat1') == None :, J( N- c* C; |
  10. st.set("chat1", "true")
    7 _; r* o& }: O  L, ^
  11. return "Chat1.htm"+ C8 K) v4 r7 M- Q) B: B: w/ V2 `
  12. elif n >= 4:
    2 V8 l# E* S  N- F3 z1 p
  13. return "Chat4.htm". `9 h- m0 K- J: E5 M# d  h
  14. return "Collected "+str(n)+" of 4 fangs"* [' h) ^- Q0 o6 ^' P/ J& z
  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.2 i: l6 W6 e% ~; s3 V) B5 i, `! l
3 Y6 L# e( I! Y5 j. u# D7 e( a4 |

0 X% m0 h1 \$ Z) u) [! HВот конечный рабочий вариант квеста:0 N, ~9 r) H8 s9 ~  H/ o) A5 d# Y
  1. import sys) j7 h2 E. i! V& A
  2. from net.sf.l2j.gameserver.model.quest import State  _- ?8 U- R8 c+ C; w
  3. from net.sf.l2j.gameserver.model.quest import QuestState
    3 e# v2 S* L1 B1 ]  Q, u
  4. from net.sf.l2j.gameserver.model.quest.jython import QuestJython as JQuest
    ; h8 D1 c+ y) m, h0 [. u& N

  5. 2 B- J. S# K+ }' R; w
  6. KELTIR_NPC_ID = 12082
    9 L9 U* ~/ W1 f. t7 c3 g) H: @
  7. FANGS_ITEM_ID = 1859, j" I8 {9 D- f  ^' E& f
  8. DROP_RATE    = 5000004 ?3 N6 ?( W- W6 g
  9. + F& G& H' x. A6 E9 o3 {
  10. WORLD_MAP_ITEM_ID = 1665
    8 D2 s  v0 B  c$ s$ H5 @1 q

  11. % R9 e5 m& v& q( M
  12. def getCount(st) :( m4 q7 }' p4 ]" ]3 ?
  13. return st.getQuestItemsCount(FANGS_ITEM_ID), E" C  C! q* P& {1 x. H
  14. 0 n5 t& }. \4 P4 {
  15. def completed(st) :- M% I8 o' z; V$ f# _
  16. st.setState(COMPLETED)
    9 C3 J. A$ T+ K, [. J
  17. st.clearQuestDrops()
    - ~5 Q5 ?. Q4 e" ^: p9 U  {- [
  18. st.takeItems(FANGS_ITEM_ID,-1)7 [: J* u# S- }2 l% n) Z3 z  z
  19. st.giveItems(WORLD_MAP_ITEM_ID,1)
    + {& e9 d" i  @3 f, j
  20. st.exitQuest(False)
    . |2 N( Z, a! g4 [
  21. return. f7 g. b9 r: ]* w' @9 X  ]

  22. # U0 U) J, j. Z; o# U& E
  23. def check(st) :
    + g5 a) R, I0 f) |# D
  24. if getCount(st) >= 4 :; f7 Z5 ], {6 x8 K% q
  25. completed(st)
    5 P' N- f% k6 y( S& A6 r8 c
  26. return
    # ]& k# b- V$ G( m3 z: g0 T
  27. 1 W: R& Y; Q4 \8 r
  28. class Quest (JQuest):
    + K$ u. [. h7 H) t2 t# [

  29. 5 g! j! v8 o* ?" ]4 z: @. ^
  30. def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)( C7 b2 ~% ?; k! T4 A5 i" F! t5 k
  31. ) X+ n9 j1 _) Z' J' J
  32. def onEvent (self,event,st):
    8 I, c. N7 G  s- J( g4 [4 ]
  33. id = st.getState()) q9 e! c6 ^8 `
  34. if id == CREATED : st.setState(STARTED), p+ l) n/ u2 P% [
  35. elif id == COMPLETED: pass
      l' Y% {5 C- q5 m, V; \, V8 ?  L
  36. elif id == STARTED : check(st)- s7 t. b3 ~3 S2 `/ R! Q0 H
  37. return8 k& x5 ?, B  N/ b6 k/ a

  38. 9 `5 I% ^. l7 I" _  _
  39. def onKill (self,npcId,st):
    + ~+ Z2 B& C& `% k& z0 r' x
  40. if npcId == KELTIR_NPC_ID:
    . r$ u; x4 O  d. g7 y+ z9 ]. A7 K% f
  41. n = getCount(st)6 {* d- T7 Y$ c( ?1 _
  42. if n == 0:
    , i# P$ b! p% `5 [
  43. if st.get('chat0') == None :
    9 {) C+ o" K3 ]# P2 `4 p5 Y+ B
  44. st.set("chat0", "true")
    4 L) ^% s# D+ L7 h( _( }
  45. return "Chat0.htm"
    . `- V  Z( D3 f. j$ Q
  46. elif n == 1:" \% n6 K. o6 c+ L  w, ?7 d
  47. if st.get('chat1') == None :
    " C: a- D, Y6 F0 c- ?
  48. st.set("chat1", "true")( Y; K' X# c$ K9 E8 r# ?
  49. return "Chat1.htm"
    - }. t# u, L9 `1 C- s3 j5 y4 e
  50. elif n >= 4:
    9 l, d4 a( L( X# E9 l, V  O
  51. return "Chat4.htm"
    & j; ^, n5 _  ?$ m
  52. return "Collect "+str(n)+" of 4 fangs"
    : y8 b, c" U' v
  53. return8 a& U2 d; v" ]# C5 Z; @

  54. + R$ D- r3 |9 w
  55. QUEST    = Quest(201, "Tutorial", "Tutorial quest")
    7 f. F  |5 I" W0 [" m9 Z/ J# t) y
  56. CREATED = State('Start',    QUEST)
    + m. e( T/ B4 N- S$ Y/ V$ S
  57. STARTED = State('Started', QUEST)
    / [  W- J/ q7 |9 o+ ^- T
  58. COMPLETED = State('Completed', QUEST)- r  b9 u" O% u/ G/ J

  59. 9 g1 `! Q! \4 s( e7 b
  60. QUEST.setInitialState(CREATED)" B/ Y$ H! z1 O* [& J9 x, q
  61. QUEST.addStartNpc(7056)
    # |2 \6 ]' U8 V9 f
  62. QUEST.addStartNpc(7012)/ u- s1 z9 I  u- J( L
  63. QUEST.addStartNpc(7009)+ ^4 V9 g5 @2 C6 O( u8 R& q
  64. QUEST.addStartNpc(7011)
    1 h4 V6 O- m& V, p
  65. 1 t5 B3 D) x; Y$ L8 c8 s+ C
  66. STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)& h: }  `4 _- }- C1 A0 O) }
  67. STARTED.addKillId(KELTIR_NPC_ID)
    / k  k: `( W# J* n: S( u
  68. STARTED.addTalkId(7056)9 X) T+ A3 v+ M# A7 V$ U0 j) J
  69. STARTED.addTalkI d(7012)
    . u& }+ g+ X9 f9 }% Z$ ?
  70. STARTED.addTalkId(7009)
    1 {+ W& u: i) f* t
  71. STARTED.addTalkId(7011)
Скопировать код

; n" G0 G4 s" {' N+ X7 x. z/ g
4 ]- K* M5 p# c7 w6 s* v
Чтобы ответить, вам надо авторизироваться в системе Вход | Зарегистрироваться

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

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

638638758

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

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

admin@artace.ru Онлайн

QR-код

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