Top.Mail.Ru

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

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

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

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

x
Хроники        Interlude
$ L2 |* J# J7 ^% N. a% u! yСборка        L2j
! j2 Q3 I$ S4 j5 f. L6 rОбратите внимание: в файле htm стартового NCP обязательно должна быть ссылка на квест:& q$ O2 d. E8 ~0 O2 u' o" y/ L: H
  1. STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код
Для этого квеста больше ничего не надо. Все необходимое для корректной работы квеста уже добавили. Вот полный текст квеста:
1 e& Q4 L; `2 i3 [. O. J+ r( |) o, k' P9 Q
  1. if getCount(st) >= 4 :# i$ X# I: }. h' u
  2. completed(st)
    & j: P1 _) Y" Q* Y/ W, r2 l/ M
  3.   return
    5 J8 h( Y  O' A( h. t

  4. 7 ?( i# ?9 L" c  l4 a' X1 V- l6 w% [
  5. class Quest (JQuest):
    1 x" u; I2 S: P$ B+ M! n* F6 Q
  6.   def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)* N4 }0 s) J" h0 {
  7.   def onEvent (self,event,st):3 c* \; [! w/ J) a$ `# z! B
  8. id = st.getState()
    6 d$ u1 `# I0 x6 Y* b; b& k
  9. if   id == CREATED  : st.setState(STARTED)- ]! U2 U$ I, c+ k+ O9 a2 B8 R$ a& ~* P
  10. elif id == COMPLETED: pass, G1 h( d: s: |: W6 e0 {
  11. elif id == STARTED  : check(st)7 j) p6 j- |+ d. D/ M' o/ y6 T  t
  12. return
    1 G8 S; w9 y' q, Y2 d; N# M0 q
  13. 3 q" Y! S5 D/ Q& k0 V
  14. QUEST     = Quest(201,"Tutorial", "Tutorial quest")+ ?* f# R% {9 I* c0 _+ S
  15. CREATED   = State('Start',     QUEST)9 ^1 @1 B' [' ~; |" `
  16. STARTED   = State('Started',   QUEST)' h6 k  h; h3 F+ ?& B
  17. COMPLETED = State('Completed', QUEST)
    , `% T' \( E8 L4 A6 g

  18. # L: e9 U1 d# c1 d
  19. QUEST.setInitialState(CREATED)2 P) H' P( M5 x4 `/ ]
  20. QUEST.addStartNpc(7056)
    * `* t; ^+ N. q' p7 x3 `4 {0 M4 |
  21. STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код
Теперь рассмотрим, как это работает.
* M9 y7 a8 }( B% ?2 l9 rИгрок подходит к начальному NCP (в данном случае 7056), нажимает на «Quest». Квест будет создан и состояние квеста перейдет к CREATED и игроку будет показана страничка Start.htm с описанием квеста. Тогда метод onEvent, поле открытия странички Start.htm переведет состояние квеста в STARTED и игроку будет показана страничка Started.htm, где будет опсание того, как найти keltirs и .т.д.( \% h: Y7 r. E$ x& ?" D1 M
' k7 [; b3 y0 j# k3 X5 W" J; p
) t8 ?! v) b: X8 O5 t
При состоянии STARTED будет зарегистрирован дроп «fangs» при убийстве keltirs. Игрок может вернуться к стартовому NCP и спросить о квесте – метод onEvent будет вызван снова. Если у игрока не хватает необходимого количества предметов, то метод check() не переведет квест в следующее состояние и Started.htm будет показана снова. Но если игрок собрал необходимее количество предметов (в данном случае 4 клыка), то метод check() вызовет метод completed() который переведет квест в новое состояние COMPLETED, заберет все клыки, даст карту мира, т.к. это награда за квест, покажет Completed.htm и завершит квест., P* g2 j% P6 z" ~, B; W' F$ E; |7 u
* L& _9 [$ q' Z% i

9 e$ }+ s8 d! f2 A* cТеперь давайте сделаем наш квест более похожим на то, что он должен из себя представлять.$ ]+ P- p- ]( y' |; K  s
Прежде всего у нас есть 3 метода для объявления их в Яве – onTalk, onKill и onEvent. Если методы onTalk и onKill не объявлены, то за них все будет делать метод onEvent, т.е. определять квестовых монстров и вызывать диалоги NCP. Есть примечание, методы onTalk и onKill будут вызывать только диалоги с NCP в зависимости от текущего состояния квеста. Метод onKill будет вызываться только тогда, когда мы убиваем квестового монстра.
' g0 g/ C( T! Q
+ M1 d% B$ ]; Z! Y  Y1 s8 i2 |
5 V4 o/ W& y% ]. k+ W$ ^5 g
Давайте рассмотрим как вызывается метод onKill при убийстве keltir в состоянии квеста STARTED:
( k6 P# Z$ \3 U! ]
  1. STARTED.addKillId(KELTIR_NPC_ID)
Скопировать код
и метод onKill в классе Quest:
/ d' s! N& e* ~: c/ v9 ~# u' L% d: S7 U1 x+ c
  1. class Quest (JQuest):
    # ~3 m; Z9 T9 w
  2.   ..., w- o: O. F$ y) C% K* p$ m5 B
  3.   def onKill (self,npcId,st):
    - }0 M* [+ ?/ i2 Q5 t! M: I
  4. if npcId == KELTIR_NPC_ID:$ m$ k$ o. O% {' R
  5.    n = getCount(st)
    ! y6 j- V/ ~* E8 Z
  6.    if   n == 0:
    . S/ F* s1 ]# z7 E6 w5 a2 W
  7.        return "Chat0.htm"
    / {+ O0 ?9 J0 S& u% N
  8.    elif n == 1:
    , o9 X) x: j7 Y6 n% }2 {8 q& ?
  9.        return "Chat1.htm"
    $ |; Z4 ^) ^7 c+ R- J  G
  10.    elif n >= 4:6 m2 d/ G, W6 T  `0 t5 ]
  11.        return "Chat4.htm"
    / O6 h( c+ [1 n* R; ^# X' P4 ~
  12.    return "Collected "+str(n)+" of 4 fangs": L( q4 d* g2 I2 L4 k$ ]& M
  13. return
Скопировать код
Метод onKill (а так же метод onTalk) имеет следующие параметры:0 w$ j& w9 J7 e0 v7 T3 a

, s( U: u! L/ }0 W8 n# H2 T8 t6 q! Q6 F

1 F1 j; }7 d9 j% l1 m8 d( K: R• self – квест
) x4 L8 e" \* q• npcId – ID NCP, которого мы должны убивать (если это метод onTalk, то ID того NCP, с которым мы должны поговорить).6 A9 ^2 K1 P; `) g. }7 e$ {
• st – текущее состояние игрока.& y+ d- r# Q. p, m
  D  h$ H" O* B5 m4 {' k
$ R% H( N2 F8 I1 {+ B
В этом методе мы проверяем и отмечаем, является ли убитый NCP keltir’ом. В основном эта проверка не нужна, т.к. у нас только KELTIR_NPC_ID.
& B/ j4 `. Q: U2 p4 \3 ~6 b8 n. |( ]/ n% g5 [' f5 l

' l, ~$ j1 @7 h. H4 c4 b3 yЗатем проверяем количество предметов (в данном случае количество клыков), и если их вообще нет, то возвращаем строку "Chat0.htm", если только один предмет, то возвращаем строку "Chat1.htm", если же предметов 4 или больше, то "Chat4.htm". Если строка возвращена из методов onEvent, onKill или onTalk, то сервер покажет соответствующие htm. В Chat0.htm может иметь следующий текст: «Вы не имеете ни одного клыка, возвращайтесь позже, когда соберете 4 штуки и бла, бла, бла…», в Chat1.htm может быть следующий текст: «У Вас всего 1 клык, по этому соберите еще…». В Chat4.htm – «Вы собрали необходимое количество предметов, возвращайтесь к вашему тренеру, что бы завершить квест…»
- u9 _' `; R5 U0 y3 p0 |* P  a# I$ k9 B3 m  T
+ j/ Q6 g; }, ^5 m  n; H
Примечание: если в строка return начинается с "<html>", то будет показана страничка html с текстом, который стоит далее. Так вместо:
0 V+ G. z- t3 \; ?; g1 x( [7 h5 X, S: |return "Chat4.htm"0 Q4 B: k" f, [9 W
2 C: {6 \6 k% m9 f) D  g! K5 `

- b2 c8 t) B( g% I+ ?: W' Cможно поставить:
5 b0 q' T, B1 ~5 S
  1. return "<html><body>Return to your trainer to complete the quest</body></html>"
Скопировать код
Так же если строка заканчивается без .htm или в начале нет <html>, то текст будет выведен, как системное сообщение в окне чата. В нашем случае мы сделаем так, что бы при каждом убийстве keltik выводилось системное сообщение: «Собрано N из 4-х клыков».
# B6 D2 r/ v( K( C
+ W0 U. _; `0 }5 y. M5 q. v

$ ]/ @3 g$ V- h7 ~) t" I' z# VНаш код для onKill имеет один недостаток. Он будет постоянно показывать Chat0.htm, Chat1.htm и Chat4.htm, нам же необходимо, что бы Chat0.htm и Chat1.htm показывались только один раз. Как нам это сделать? С помощью переменных.# i/ z, \, E& s4 `) C! z

$ Q5 e2 }8 O/ {- t6 {0 E3 ?
/ T0 s, X. k) q4 M; g# L* e
В каждом квесте строки могут храниться с помощью переменных. Эти переменные сохраняются в Вашей БД. В каждом методе мы можем назначить, прочитать и удалить переменные. Давайте изменим метод onKill, так что бы каждый диалог вызывался только один раз.7 [( j7 ~8 Y8 y
  1. def onKill (self,npcId,st):# |: H# |$ Q- J5 s
  2. if npcId == KELTIR_NPC_ID:7 a  f  m! s1 V; ]; a, F& G' v% \
  3. n = getCount(st)6 y1 Y9 |: _. X& |
  4. if n == 0:
    2 v: {/ K. D( Z. t+ a6 l* m. T! t
  5. if st.get('chat0') == None :" K4 J" G. f/ ^  d& L) [/ B
  6. st.set("chat0", "true")
    * C- C! d8 c- Z3 ?! x+ T
  7. return "Chat0.htm"
    8 N+ s4 ?7 v* a
  8. elif n == 1:
      t+ u1 {) v, ~( K  A
  9. if st.get('chat1') == None :
    ) G8 M; A+ V; g
  10. st.set("chat1", "true"); V& ?0 ?7 Q2 Q
  11. return "Chat1.htm"
    3 b; b; i) F; J
  12. elif n >= 4:8 u6 m) ~9 q6 P8 [
  13. return "Chat4.htm". d* |% n, u5 O( e- a
  14. return "Collected "+str(n)+" of 4 fangs"$ T; C) }5 v8 y
  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.  ?, A' o( P/ G
' Y) n* F3 |7 F4 ?- U, ], F; O7 x

- n) W! W0 }8 B. oВот конечный рабочий вариант квеста:
. o1 w' y- l+ N% l) r' S
  1. import sys
    8 _" Z4 b- F8 y
  2. from net.sf.l2j.gameserver.model.quest import State
    % s8 ?, g3 x' A. I# m
  3. from net.sf.l2j.gameserver.model.quest import QuestState
      }+ O1 c% P( x$ S
  4. from net.sf.l2j.gameserver.model.quest.jython import QuestJython as JQuest
    : p5 d* I! I% k' z
  5. . U& T" S% j, |5 N( e$ N) T
  6. KELTIR_NPC_ID = 12082$ l& i( J+ e/ Y( L
  7. FANGS_ITEM_ID = 18597 |  R* `: q% F
  8. DROP_RATE    = 5000005 O' ?2 ^& @2 F% v6 z4 P( {

  9. . Q6 j; C4 H- Z# `  j, l
  10. WORLD_MAP_ITEM_ID = 1665
    7 o# E5 D% S! \' [
  11. 6 D/ `0 l4 H" c# i6 {0 ^% O5 u
  12. def getCount(st) :
    . Y% I- u# M' |4 C
  13. return st.getQuestItemsCount(FANGS_ITEM_ID)
    , D7 {, [3 A( Z0 y3 q
  14. 8 o1 R7 J5 S) Q
  15. def completed(st) :* q+ ?( O' f5 j0 Z
  16. st.setState(COMPLETED)
    # P6 B6 A' s) D. N7 }8 o6 F
  17. st.clearQuestDrops()) a7 s( P3 Z% C- E
  18. st.takeItems(FANGS_ITEM_ID,-1), m+ z! t) w3 d+ z- p
  19. st.giveItems(WORLD_MAP_ITEM_ID,1)
    " Q% W3 `0 z3 k
  20. st.exitQuest(False)
    6 ^( q: ~; b5 H" b( P
  21. return
    : g9 Y& Q; H8 b: a& Y' x
  22. 6 p7 k  v0 V8 u; y7 ^& |
  23. def check(st) :
    # c7 a" t, L6 c
  24. if getCount(st) >= 4 :2 n8 M9 H% N1 [# `
  25. completed(st)1 v8 c: k: l. A3 h1 U( q
  26. return4 S( k; K8 |) H7 V2 N
  27. 9 o  j% t$ y* E4 N5 z9 {' w
  28. class Quest (JQuest):
    3 v" Z) n# M7 ~- ?7 g3 {

  29. - W5 J( @1 f3 f0 z
  30. def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)
    , E* H- L$ _4 @' V; q  s* J

  31. ! j+ j# R/ u* J9 Q6 B1 n5 s3 C- r) A3 ^
  32. def onEvent (self,event,st):
    : ^9 t8 [' |3 k' r
  33. id = st.getState()
    4 g! `- {/ D& S- \. B  L
  34. if id == CREATED : st.setState(STARTED)0 G% i# G8 @+ t  l
  35. elif id == COMPLETED: pass, ]7 |% q7 o2 G; N" q4 a
  36. elif id == STARTED : check(st)
    , g7 j/ U2 p  \2 a, D0 L
  37. return
    6 j$ W8 ~, F& v5 c% j

  38. ( V; [" d$ L4 D- \9 e0 `# W" z' i1 z
  39. def onKill (self,npcId,st):
    ! L; ?  S& U/ Y/ d( N
  40. if npcId == KELTIR_NPC_ID:
    % d' l( [/ W6 S* K3 U* H! m
  41. n = getCount(st)
    # U7 B; i- Q  O6 u: c- L0 v2 ]
  42. if n == 0:0 A: l! L4 T" v: i3 p, ~! X
  43. if st.get('chat0') == None :; t: L; q; C! I/ H# S9 F
  44. st.set("chat0", "true")! h3 ]& P9 a3 a# l  G
  45. return "Chat0.htm"6 d; a5 Y9 s+ V8 e* n% X
  46. elif n == 1:
    9 e' L7 S. S+ ?7 z4 {
  47. if st.get('chat1') == None :
    * `# c* ]! {0 e+ T) \
  48. st.set("chat1", "true")3 k7 F5 Q2 }' Q6 V6 x( d& `
  49. return "Chat1.htm"
    ! |# n5 F' z0 A
  50. elif n >= 4:% z1 n; A" @8 N
  51. return "Chat4.htm"
    $ d) F7 W! T! ]+ ]6 w
  52. return "Collect "+str(n)+" of 4 fangs"! S$ I8 W# f# p( l) d- c" o& J; c7 J
  53. return
    8 w% ^6 z; ^0 d5 X4 h% {
  54. 9 P( l- g9 J' E  E, K- P2 I/ C
  55. QUEST    = Quest(201, "Tutorial", "Tutorial quest")
    & s: j& S4 o; e. }# H+ e' V
  56. CREATED = State('Start',    QUEST)! y( I! _! F, d2 `' H
  57. STARTED = State('Started', QUEST)7 [' @+ G7 K5 s8 U. G) [
  58. COMPLETED = State('Completed', QUEST)' U3 [; u7 O, i8 `- p; J' v

  59. : _- B7 J- P4 `! N8 C6 @( R
  60. QUEST.setInitialState(CREATED)6 `# E/ m+ y  E0 {) ~) n$ O
  61. QUEST.addStartNpc(7056)
    3 ~$ C5 J5 G4 z' Y: s' h* m5 t- E
  62. QUEST.addStartNpc(7012)4 w: X2 K( w0 |  G0 X) a
  63. QUEST.addStartNpc(7009)- W6 W8 ]) S: b3 B% c* s
  64. QUEST.addStartNpc(7011)
    9 d* U3 B. G8 g
  65. ' R& x2 E! W; b- r- U( U
  66. STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)4 p, ^! l3 V7 O' l0 y' z
  67. STARTED.addKillId(KELTIR_NPC_ID)) q! D1 Q8 t0 T. `* b
  68. STARTED.addTalkId(7056)
    2 ]- w, P( F) M) p$ v
  69. STARTED.addTalkI d(7012)
    3 H; O: V6 a2 h( B" D
  70. STARTED.addTalkId(7009)6 w9 }; X4 X5 D& }
  71. STARTED.addTalkId(7011)
Скопировать код

2 u: T4 Z3 U1 x6 b, y) \/ i
2 P; N8 P* o' x1 _0 N3 h
Чтобы ответить, вам надо авторизироваться в системе Вход | Зарегистрироваться

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

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

638638758

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

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

admin@artace.ru Онлайн

QR-код

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