Top.Mail.Ru

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

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

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

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

x
Хроники        Interlude
5 D2 u  U3 n2 V  n+ s$ aСборка        L2j6 M6 s( [9 {  s
Обратите внимание: в файле htm стартового NCP обязательно должна быть ссылка на квест:% I+ [; q% o1 w9 i
  1. STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код
Для этого квеста больше ничего не надо. Все необходимое для корректной работы квеста уже добавили. Вот полный текст квеста:
& _2 B% \1 U+ Y- E  D! Q$ r5 _6 v  k
  1. if getCount(st) >= 4 :
    - U* _0 x8 ^% Q1 l( a
  2. completed(st)# g$ s2 l3 G% _7 Q
  3.   return
    1 c) ^6 t. @  `+ }% N
  4. / O. v% x: X( J5 c
  5. class Quest (JQuest):
    , O1 ^# G% Z+ ?7 z
  6.   def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr); ]7 F# z, ]5 h$ q: l% ^+ o9 V+ z+ o
  7.   def onEvent (self,event,st):" `0 E% i% g" |* ]: \# u+ x/ V
  8. id = st.getState()6 G7 W8 ?, F( T7 u
  9. if   id == CREATED  : st.setState(STARTED)
    5 G" b* Z, y7 [. x+ o' D1 n/ v
  10. elif id == COMPLETED: pass
    + B: R! x& q2 `# I& b% T" w" x2 ]- H
  11. elif id == STARTED  : check(st)
    3 H8 M1 R6 @# r( ?2 J0 R
  12. return
    $ _" S; q2 X) t, N' @
  13. 3 \% v  V. Y( ?7 A# }
  14. QUEST     = Quest(201,"Tutorial", "Tutorial quest")
    4 Z( _- s! @, T  K3 Y- B( R
  15. CREATED   = State('Start',     QUEST)
    8 o( ~- k* v) `# D* L
  16. STARTED   = State('Started',   QUEST)7 m$ i: e% z# I' C* I
  17. COMPLETED = State('Completed', QUEST)% y5 B' N# R: M- k4 q3 z

  18. 2 q% \* ^# w! [2 r/ `
  19. QUEST.setInitialState(CREATED)
    7 w/ _/ c8 x1 J1 U4 D
  20. QUEST.addStartNpc(7056)+ Y; q! G! i% v6 T
  21. STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код
Теперь рассмотрим, как это работает.( T7 X) R" d8 h' ]' Y" m# m
Игрок подходит к начальному NCP (в данном случае 7056), нажимает на «Quest». Квест будет создан и состояние квеста перейдет к CREATED и игроку будет показана страничка Start.htm с описанием квеста. Тогда метод onEvent, поле открытия странички Start.htm переведет состояние квеста в STARTED и игроку будет показана страничка Started.htm, где будет опсание того, как найти keltirs и .т.д.
3 k" y/ Q+ s  d: h7 k4 J. Z4 b. d1 l7 @$ r( H9 p$ s; L8 g( T

1 K2 R; q/ m1 `& l/ GПри состоянии STARTED будет зарегистрирован дроп «fangs» при убийстве keltirs. Игрок может вернуться к стартовому NCP и спросить о квесте – метод onEvent будет вызван снова. Если у игрока не хватает необходимого количества предметов, то метод check() не переведет квест в следующее состояние и Started.htm будет показана снова. Но если игрок собрал необходимее количество предметов (в данном случае 4 клыка), то метод check() вызовет метод completed() который переведет квест в новое состояние COMPLETED, заберет все клыки, даст карту мира, т.к. это награда за квест, покажет Completed.htm и завершит квест.. O( t+ O; _6 c  h! C- s& G

/ Z$ J6 y1 H4 P

9 [" t4 b. F: @8 E% h' A0 UТеперь давайте сделаем наш квест более похожим на то, что он должен из себя представлять.
+ b/ k- W! O) x1 {. i+ d1 w- U! c, |Прежде всего у нас есть 3 метода для объявления их в Яве – onTalk, onKill и onEvent. Если методы onTalk и onKill не объявлены, то за них все будет делать метод onEvent, т.е. определять квестовых монстров и вызывать диалоги NCP. Есть примечание, методы onTalk и onKill будут вызывать только диалоги с NCP в зависимости от текущего состояния квеста. Метод onKill будет вызываться только тогда, когда мы убиваем квестового монстра.
) y; V4 f4 `2 O+ X, n1 z4 Y; W. _+ @
8 ^2 z. ^+ x" v

7 @8 D' a" }( G9 aДавайте рассмотрим как вызывается метод onKill при убийстве keltir в состоянии квеста STARTED:$ s3 |2 S1 W; u/ m* X
  1. STARTED.addKillId(KELTIR_NPC_ID)
Скопировать код
и метод onKill в классе Quest:
: }# U, p; j$ P0 R
$ }1 {# e9 u  H
  1. class Quest (JQuest):
    1 E  b/ ^$ ], H% P! t$ m
  2.   ...# m. C1 `# [2 b! r* D, }
  3.   def onKill (self,npcId,st):* ~7 H9 Z: a1 j4 I5 V6 \
  4. if npcId == KELTIR_NPC_ID:
    5 a# ?$ K4 m% j7 k1 [" }
  5.    n = getCount(st)/ z, ?  v* M( L# _' H, D) F( w
  6.    if   n == 0:
    / s6 q- @% E: X: Y% L7 |' P: `
  7.        return "Chat0.htm"* R$ A/ r. P7 d& D0 p) B7 ^
  8.    elif n == 1:
    8 J) {& Y0 p+ r  O# m
  9.        return "Chat1.htm"
    " H6 I- ^  h; p! p2 G) n0 C
  10.    elif n >= 4:% w: t& T: a( l1 R
  11.        return "Chat4.htm"8 u0 }: r, P3 B# L- p* `
  12.    return "Collected "+str(n)+" of 4 fangs"/ D/ B3 f- T+ V+ x
  13. return
Скопировать код
Метод onKill (а так же метод onTalk) имеет следующие параметры:( v$ O) K- }6 y; j& x5 Q5 a% W

8 f$ s" x& {& T: _* x+ W" u

+ Y0 D8 X) o. V. [4 ?: ^• self – квест9 f8 p, N9 n8 N! Q# A5 S) ~
• npcId – ID NCP, которого мы должны убивать (если это метод onTalk, то ID того NCP, с которым мы должны поговорить)./ Q; T$ p' r  a1 B0 ?' r, K2 `
• st – текущее состояние игрока.
0 U4 f- j" p$ B1 G! M' I. g
7 n# i% _* _- D

/ @3 ^) Z0 \3 q6 a/ b- pВ этом методе мы проверяем и отмечаем, является ли убитый NCP keltir’ом. В основном эта проверка не нужна, т.к. у нас только KELTIR_NPC_ID.
& `4 V# {/ E0 w; P4 h& @! I! W. j4 b: X; J; u9 p, z, Y, i* M
( X  r- z; o. I2 V, i  W
Затем проверяем количество предметов (в данном случае количество клыков), и если их вообще нет, то возвращаем строку "Chat0.htm", если только один предмет, то возвращаем строку "Chat1.htm", если же предметов 4 или больше, то "Chat4.htm". Если строка возвращена из методов onEvent, onKill или onTalk, то сервер покажет соответствующие htm. В Chat0.htm может иметь следующий текст: «Вы не имеете ни одного клыка, возвращайтесь позже, когда соберете 4 штуки и бла, бла, бла…», в Chat1.htm может быть следующий текст: «У Вас всего 1 клык, по этому соберите еще…». В Chat4.htm – «Вы собрали необходимое количество предметов, возвращайтесь к вашему тренеру, что бы завершить квест…»
2 c: t; L5 J( m- F; N, P7 E
/ f* F* Z2 S4 v7 J+ ~4 U  Z

  [2 q- a9 T/ p- U. o7 vПримечание: если в строка return начинается с "<html>", то будет показана страничка html с текстом, который стоит далее. Так вместо:
- ?' Q6 ]+ z- xreturn "Chat4.htm"
8 R2 y; ^7 T1 T7 I+ d+ J6 W
6 ^1 \! \! K( L5 [2 b) k8 s. s

% X) {& ?2 w$ |можно поставить:
$ c0 e! ^( h, M; w
  1. return "<html><body>Return to your trainer to complete the quest</body></html>"
Скопировать код
Так же если строка заканчивается без .htm или в начале нет <html>, то текст будет выведен, как системное сообщение в окне чата. В нашем случае мы сделаем так, что бы при каждом убийстве keltik выводилось системное сообщение: «Собрано N из 4-х клыков».
9 ?4 z8 K  Z/ v: X
  {* E* K9 X2 @9 v; O- P2 O9 U! e+ a

# Q+ r0 A# D0 PНаш код для onKill имеет один недостаток. Он будет постоянно показывать Chat0.htm, Chat1.htm и Chat4.htm, нам же необходимо, что бы Chat0.htm и Chat1.htm показывались только один раз. Как нам это сделать? С помощью переменных.
( U6 c' E% f+ q% D- z% l
8 X9 v+ b) G% I/ {% ]( y

. N( m% W# S0 u7 T9 H6 s% K4 kВ каждом квесте строки могут храниться с помощью переменных. Эти переменные сохраняются в Вашей БД. В каждом методе мы можем назначить, прочитать и удалить переменные. Давайте изменим метод onKill, так что бы каждый диалог вызывался только один раз.0 C. |( U* g8 L  y6 D3 Z  F; E& }
  1. def onKill (self,npcId,st):/ o4 n( r. _' [- V9 V
  2. if npcId == KELTIR_NPC_ID:# @& x  O5 l7 z& R
  3. n = getCount(st)
    " \) s+ ]# t( x* Y/ E) n
  4. if n == 0:
    ; e6 r2 Z; ~% \- D6 v
  5. if st.get('chat0') == None :% q* N/ y9 G5 s' g6 K
  6. st.set("chat0", "true")" M# p2 m$ g5 ]6 T1 q% F4 P
  7. return "Chat0.htm"
    6 ^5 N, F3 J9 b# O1 X9 k
  8. elif n == 1:# i$ B. W- A# n. d
  9. if st.get('chat1') == None :9 Y+ n5 ]% \2 Q* Z! j' n
  10. st.set("chat1", "true")
    5 k8 E, x3 W1 |
  11. return "Chat1.htm"0 Z0 n$ P% k1 y2 c+ N
  12. elif n >= 4:7 _4 ~2 F7 M6 L
  13. return "Chat4.htm"
    - g  k6 l' z5 T0 o
  14. return "Collected "+str(n)+" of 4 fangs"" V9 y# T% k5 q' f, v/ q
  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.- q0 \6 S6 r- }$ _  l& ]: g2 S+ K- h

! N( o3 m! d: z1 w" G; N
- ^" h4 U' K" G# I
Вот конечный рабочий вариант квеста:
1 F  D/ g7 M8 E
  1. import sys
    " p. S6 j4 r/ U( C
  2. from net.sf.l2j.gameserver.model.quest import State! R; m2 |$ Y5 C+ O9 z- h5 U# u
  3. from net.sf.l2j.gameserver.model.quest import QuestState8 X  N, ~2 z$ I
  4. from net.sf.l2j.gameserver.model.quest.jython import QuestJython as JQuest
    " D/ W1 @3 _4 Z  n: M, A2 M9 @

  5. 0 r) D. ]8 A9 t& k2 K) _5 g
  6. KELTIR_NPC_ID = 12082
    $ z& G2 ^& c0 F, j1 {
  7. FANGS_ITEM_ID = 18592 d; D$ P- B0 {; V- ]
  8. DROP_RATE    = 5000009 F  b. {* Z" H, ]5 o: S
  9. % ~( o6 p) O' I- F& n& W  R, S
  10. WORLD_MAP_ITEM_ID = 1665+ I) t) ?; P1 u" a
  11. / t+ w% T, G' G( c" Z
  12. def getCount(st) :2 ]  q: W% j4 S; {5 t; V0 h
  13. return st.getQuestItemsCount(FANGS_ITEM_ID)4 W6 C# J" B2 f& q$ g
  14. ( J% P" C6 j( h, B$ H. M, P: T  x
  15. def completed(st) :
    0 l6 ]7 D% r# {
  16. st.setState(COMPLETED)+ e$ |# n: }8 K; j  p
  17. st.clearQuestDrops()% c# w& a' }. w6 S0 R
  18. st.takeItems(FANGS_ITEM_ID,-1)) \- B1 G0 p3 l$ L0 z/ R$ e
  19. st.giveItems(WORLD_MAP_ITEM_ID,1)1 _* u& G7 \- `% U/ z0 z
  20. st.exitQuest(False)
    ' `" B* g9 @9 J
  21. return+ V! ^. h1 T5 F; [; r. o$ y

  22. . C) G# g" H3 W* V
  23. def check(st) :- I( ^% A+ |# G$ I* c$ C
  24. if getCount(st) >= 4 :
    ; w7 a! I8 {0 @5 o6 Y; b9 P* S
  25. completed(st)8 k/ [3 h( r7 K3 R9 O* D  [
  26. return
    % c0 k) `* `% H% S/ T9 q: o7 \
  27. / l% s" O: B% h+ t/ q
  28. class Quest (JQuest):
    # X# [5 \3 n) E+ n4 x, e

  29.   \  |6 U7 D# n1 E
  30. def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)' h7 N) O, V0 {

  31. - G$ z1 C/ I4 a$ g
  32. def onEvent (self,event,st):. }1 N& \/ w8 p9 i$ h
  33. id = st.getState()1 q, r( e  D" i2 \/ b5 q, B
  34. if id == CREATED : st.setState(STARTED)  c" R, e3 m6 _
  35. elif id == COMPLETED: pass
    1 c& r" v3 D+ D" C
  36. elif id == STARTED : check(st)
    7 K" R5 K( q: n' c' x
  37. return
    9 T$ n# a5 `: x9 {9 N) w( B1 v
  38. ' W( |& v, ?: ~% C
  39. def onKill (self,npcId,st):- k7 [! O/ o4 k/ @* k7 m
  40. if npcId == KELTIR_NPC_ID:' U- L% x* r& P9 h1 t8 k
  41. n = getCount(st)
    4 O* R3 |' e6 W
  42. if n == 0:! n+ t: d3 X4 l* c
  43. if st.get('chat0') == None :
    / [- h- }3 P7 b8 Y
  44. st.set("chat0", "true")
      ^7 J/ y/ l6 R. _; S
  45. return "Chat0.htm"
    7 u/ z3 n1 K9 n! S( ~
  46. elif n == 1:, j" ]$ A% t  B; Z
  47. if st.get('chat1') == None :
    1 b' u6 \; h. ]* z
  48. st.set("chat1", "true")
    4 R/ t7 M7 E# b5 F/ C
  49. return "Chat1.htm"" D% ~! |. C$ R6 _" L) ?6 ?3 a
  50. elif n >= 4:
    . w* ~) k* R0 m: V
  51. return "Chat4.htm"
    " V2 L  V8 Q! C1 O; I2 ]
  52. return "Collect "+str(n)+" of 4 fangs"
    + C. q; _2 M; D) G, R
  53. return# m' X! Z% A# t( {9 m9 E
  54. , T' q# D' C* G: M$ h5 t
  55. QUEST    = Quest(201, "Tutorial", "Tutorial quest")2 b) }' h5 C# z/ W
  56. CREATED = State('Start',    QUEST)
    , E% w9 B* A) P6 o9 Y" Z
  57. STARTED = State('Started', QUEST)' N. X  \  c3 ^: m3 G
  58. COMPLETED = State('Completed', QUEST)+ Z8 N  |* D' _

  59. ) o8 |( B+ z9 e  M/ F4 p" r0 D
  60. QUEST.setInitialState(CREATED)0 u! W" ~  j/ I4 t& P! x1 j
  61. QUEST.addStartNpc(7056)9 o% n2 @, N9 c2 v' m, s6 C
  62. QUEST.addStartNpc(7012)+ p3 w' T3 D1 Q, M: C
  63. QUEST.addStartNpc(7009)
    3 U! \8 s3 _: H, \6 U5 w) C3 `
  64. QUEST.addStartNpc(7011). m" j/ ~+ b8 X" g, Y/ i4 S3 r

  65. 0 o" Z9 H1 D& v, E# @9 [# E! H
  66. STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)! j' m* [% {# u. ^" D& V
  67. STARTED.addKillId(KELTIR_NPC_ID)
    - e5 A0 \  }4 z" a
  68. STARTED.addTalkId(7056)& w" B" E2 y. H( S: b% d
  69. STARTED.addTalkI d(7012)
    + L, {# k$ [; I
  70. STARTED.addTalkId(7009)/ Z) g! W, n& B2 O  U
  71. STARTED.addTalkId(7011)
Скопировать код
- n% T$ _  B2 x8 V2 w- E! K3 c: w& u
! Y6 V, X/ p* h' l) C5 m
Чтобы ответить, вам надо авторизироваться в системе Вход | Зарегистрироваться

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

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

638638758

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

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

admin@artace.ru Онлайн

QR-код

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