Top.Mail.Ru

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

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

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

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

x
Хроники        Interlude
% A- R- s6 R" j4 p8 o! q; QСборка        L2j( P8 n3 m. L) X4 S2 O
Обратите внимание: в файле htm стартового NCP обязательно должна быть ссылка на квест:( d2 |* O5 s+ B( |8 [( N6 e
  1. STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код
Для этого квеста больше ничего не надо. Все необходимое для корректной работы квеста уже добавили. Вот полный текст квеста:
) `" ?, V% j1 X& B4 f( {2 h' w7 u$ y; b
  1. if getCount(st) >= 4 :; f' f$ Q3 N9 l
  2. completed(st)  e* f3 ~+ I  X- ?! a! F( N
  3.   return
    1 c9 q7 I% A& z
  4.   E; r/ r5 T4 T8 @; Z. t/ _
  5. class Quest (JQuest):; [6 S' J3 }2 }& O
  6.   def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)
    ! Z% ?5 D1 x8 t
  7.   def onEvent (self,event,st):& F& u, c' j% g/ q3 c) [
  8. id = st.getState()
    2 X# @; a% F. m1 M9 H  k
  9. if   id == CREATED  : st.setState(STARTED)
    # r9 N5 e- y+ F0 j& ~# J- g
  10. elif id == COMPLETED: pass
    2 N! o3 B: C) p, I, B4 x
  11. elif id == STARTED  : check(st)
    / E! B- O2 Y9 `7 ]0 Q
  12. return
    / ~: n3 G8 G# u

  13. 3 O4 G- v& C0 O$ n8 O$ L3 g& I
  14. QUEST     = Quest(201,"Tutorial", "Tutorial quest"): S1 e7 d( V7 G3 `. H1 }; p
  15. CREATED   = State('Start',     QUEST)" C7 u$ E2 X" h
  16. STARTED   = State('Started',   QUEST)
    * I- I6 A( E  o
  17. COMPLETED = State('Completed', QUEST)7 R+ d) \* A7 n6 M4 F0 P

  18. ( F' y6 l, @3 K' F) h# z
  19. QUEST.setInitialState(CREATED)
    8 `: i- J  n% F( P& t
  20. QUEST.addStartNpc(7056)
    8 M9 Y7 R; a9 a+ ]' R9 o/ @
  21. STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код
Теперь рассмотрим, как это работает.
6 _, L, e- i" X2 K  eИгрок подходит к начальному NCP (в данном случае 7056), нажимает на «Quest». Квест будет создан и состояние квеста перейдет к CREATED и игроку будет показана страничка Start.htm с описанием квеста. Тогда метод onEvent, поле открытия странички Start.htm переведет состояние квеста в STARTED и игроку будет показана страничка Started.htm, где будет опсание того, как найти keltirs и .т.д.
. t" i( r- Y  W! ^" t2 e! [5 {
+ D- X/ [) y% ~0 G' N2 J
1 Z5 k7 [, o, N2 Z  v% b
При состоянии STARTED будет зарегистрирован дроп «fangs» при убийстве keltirs. Игрок может вернуться к стартовому NCP и спросить о квесте – метод onEvent будет вызван снова. Если у игрока не хватает необходимого количества предметов, то метод check() не переведет квест в следующее состояние и Started.htm будет показана снова. Но если игрок собрал необходимее количество предметов (в данном случае 4 клыка), то метод check() вызовет метод completed() который переведет квест в новое состояние COMPLETED, заберет все клыки, даст карту мира, т.к. это награда за квест, покажет Completed.htm и завершит квест.- h- N' o* s# Y" |

+ {* l1 [5 F6 Y: s' C
# \: A, M  b7 {' p$ q
Теперь давайте сделаем наш квест более похожим на то, что он должен из себя представлять.5 x) k9 P9 a' y( l. Y" {, S$ |
Прежде всего у нас есть 3 метода для объявления их в Яве – onTalk, onKill и onEvent. Если методы onTalk и onKill не объявлены, то за них все будет делать метод onEvent, т.е. определять квестовых монстров и вызывать диалоги NCP. Есть примечание, методы onTalk и onKill будут вызывать только диалоги с NCP в зависимости от текущего состояния квеста. Метод onKill будет вызываться только тогда, когда мы убиваем квестового монстра.+ w) D9 v4 D$ G/ r/ U
( I( ]) q/ a3 D6 e4 |$ o2 Y
: x% O# t, w% w9 l% N1 b
Давайте рассмотрим как вызывается метод onKill при убийстве keltir в состоянии квеста STARTED:
) p0 ^' T  T' _/ d
  1. STARTED.addKillId(KELTIR_NPC_ID)
Скопировать код
и метод onKill в классе Quest:
+ I; q- q+ Q3 |& q# Y# B
7 [* ~" m4 l* m; _" Z9 w7 |( K
  1. class Quest (JQuest):
    / i8 S* g4 T) G+ S# r/ i9 i
  2.   ...6 k; x* d$ y1 c( r
  3.   def onKill (self,npcId,st):
    ) v0 O. V3 d1 Q( a, {
  4. if npcId == KELTIR_NPC_ID:" m# n  ?" e' E) z: {: v
  5.    n = getCount(st)
    5 Y$ k( O2 r# P" s6 R- o5 A
  6.    if   n == 0:" _( o& `  G# C  N/ q# y$ T% G7 j
  7.        return "Chat0.htm"
    9 z5 {, x2 _, Y( h
  8.    elif n == 1:2 w8 j& R& z8 ~8 e: _
  9.        return "Chat1.htm"' S6 r/ d) D% E8 q1 J
  10.    elif n >= 4:% K: J) ?. m1 p, N. p/ O$ V/ s
  11.        return "Chat4.htm"; Z; U" j, n5 z
  12.    return "Collected "+str(n)+" of 4 fangs"
    8 v- y; i+ J3 a. y! [3 _
  13. return
Скопировать код
Метод onKill (а так же метод onTalk) имеет следующие параметры:
9 [0 M* D! _5 `+ i" J3 v
7 h, O- B( P: b
7 ?! L' T& ^7 ^5 s" L
• self – квест. I* i' ~3 i# d: k
• npcId – ID NCP, которого мы должны убивать (если это метод onTalk, то ID того NCP, с которым мы должны поговорить).
+ B: l4 ~! U3 `5 I• st – текущее состояние игрока.- E3 x) g! Q$ J+ I3 p; _- V9 m

: n' F+ z% |8 U' z+ ], L
  ^5 o) D/ I- t9 Y9 n( P- j7 b9 n
В этом методе мы проверяем и отмечаем, является ли убитый NCP keltir’ом. В основном эта проверка не нужна, т.к. у нас только KELTIR_NPC_ID.
) a* i% }* B; b; k3 i/ J- B# l0 x* x7 |+ [- B2 _

* o1 V" u! u" J# }8 {. q( i' rЗатем проверяем количество предметов (в данном случае количество клыков), и если их вообще нет, то возвращаем строку "Chat0.htm", если только один предмет, то возвращаем строку "Chat1.htm", если же предметов 4 или больше, то "Chat4.htm". Если строка возвращена из методов onEvent, onKill или onTalk, то сервер покажет соответствующие htm. В Chat0.htm может иметь следующий текст: «Вы не имеете ни одного клыка, возвращайтесь позже, когда соберете 4 штуки и бла, бла, бла…», в Chat1.htm может быть следующий текст: «У Вас всего 1 клык, по этому соберите еще…». В Chat4.htm – «Вы собрали необходимое количество предметов, возвращайтесь к вашему тренеру, что бы завершить квест…»$ H4 F/ N6 Q0 X# S# ~$ y

& l. C2 P: X4 T- d7 u) a  S
0 f, u2 `! x- e8 F0 R
Примечание: если в строка return начинается с "<html>", то будет показана страничка html с текстом, который стоит далее. Так вместо:
5 N8 S: E$ e/ v3 r; Freturn "Chat4.htm"
& g. |; H8 o1 G3 d( n; [0 C2 e
* L# q1 Y4 o# B% b. J3 X

: `1 l  P% m7 uможно поставить:
4 [8 D9 o1 e! D. E3 L: f
  1. return "<html><body>Return to your trainer to complete the quest</body></html>"
Скопировать код
Так же если строка заканчивается без .htm или в начале нет <html>, то текст будет выведен, как системное сообщение в окне чата. В нашем случае мы сделаем так, что бы при каждом убийстве keltik выводилось системное сообщение: «Собрано N из 4-х клыков».( G* l* H/ E. {' v) A2 L
4 q: m/ H; M6 r$ d+ Q
) ^- P1 f% G8 D; h9 e( M; }* m
Наш код для onKill имеет один недостаток. Он будет постоянно показывать Chat0.htm, Chat1.htm и Chat4.htm, нам же необходимо, что бы Chat0.htm и Chat1.htm показывались только один раз. Как нам это сделать? С помощью переменных.9 o8 a  u, S% a! W3 }4 q3 l

) a, v1 p& ~+ X6 \* }" }
8 |3 L" |& R$ l6 ~( X/ Z& L- W
В каждом квесте строки могут храниться с помощью переменных. Эти переменные сохраняются в Вашей БД. В каждом методе мы можем назначить, прочитать и удалить переменные. Давайте изменим метод onKill, так что бы каждый диалог вызывался только один раз.$ G5 j: r4 q( S  O, g7 f
  1. def onKill (self,npcId,st):7 C6 y( |. l: O: v! ?0 {4 y$ x
  2. if npcId == KELTIR_NPC_ID:
    0 ?$ G+ D5 I0 h1 t/ a
  3. n = getCount(st)7 L$ A5 G) f) R% M$ W# v
  4. if n == 0:
    1 Z8 ]# F! c% M
  5. if st.get('chat0') == None :  e' Q  C6 a6 Y% i. `! Z% W" D8 |
  6. st.set("chat0", "true")
    ! ?: \2 R: y# ~& L3 i9 W% P/ L
  7. return "Chat0.htm"& n. g; V9 G- d! x, g! v
  8. elif n == 1:
    ' j- K% L; p$ i
  9. if st.get('chat1') == None :
    : f( o4 ~: M' i3 P( j
  10. st.set("chat1", "true")
    $ k; o' ^5 ?! v- X
  11. return "Chat1.htm"
    % k- s$ C* b& M( N( a4 ]4 g( h
  12. elif n >= 4:
    8 m$ l/ C6 Z) G+ q6 L$ @
  13. return "Chat4.htm"
    . v  ?& k! b) w3 y: i- V7 e
  14. return "Collected "+str(n)+" of 4 fangs"
    ( |/ D6 e5 Y7 @' Y, U3 m+ [2 X, f
  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.; r' k$ Z- I$ d5 Q

+ F4 i4 G: z- E

8 E4 X" w  d$ rВот конечный рабочий вариант квеста:% Q& R/ |' y* I7 o1 H
  1. import sys
    4 i& P, [0 o5 d, p5 Q
  2. from net.sf.l2j.gameserver.model.quest import State6 V: s# [+ C2 M5 {6 [
  3. from net.sf.l2j.gameserver.model.quest import QuestState
    # j" Z0 i: W0 o7 k% A% ^! q
  4. from net.sf.l2j.gameserver.model.quest.jython import QuestJython as JQuest
    # K  g. J& Q) ]5 Y* u6 z0 o3 }
  5. * o( Z9 R) W8 i5 g) s4 C
  6. KELTIR_NPC_ID = 120822 J: j8 b  z" a# b7 @- Y
  7. FANGS_ITEM_ID = 18595 H. s- r4 M- _/ }+ C  h
  8. DROP_RATE    = 500000/ I) A0 }" h- p1 b' U! x

  9. 8 m7 U( N' F9 V8 F! G5 T
  10. WORLD_MAP_ITEM_ID = 1665  x9 h- b2 K  T

  11. # e" G! |! P6 Y
  12. def getCount(st) :
    6 z$ v+ {7 f9 ^6 q  z' s
  13. return st.getQuestItemsCount(FANGS_ITEM_ID)6 y, P9 ~" t- Z
  14. / ]6 e+ ~% _, w! l1 m4 \3 T
  15. def completed(st) :
    8 R( l1 o0 F" ]5 c$ |& o
  16. st.setState(COMPLETED)
    % i2 r6 I2 c) H! q' E/ Y
  17. st.clearQuestDrops()# H. P1 @0 H) U
  18. st.takeItems(FANGS_ITEM_ID,-1)0 y! [4 J) a9 k* @1 j( B
  19. st.giveItems(WORLD_MAP_ITEM_ID,1)  f3 @! P% N, X! y5 m
  20. st.exitQuest(False)# z- @! B" J1 F1 q" W: d. q5 I8 x
  21. return/ \3 T( L9 K; l1 L& k- N( C
  22. & j$ W& S0 |- u( g  d
  23. def check(st) :3 i' B  |4 x/ Z% ^1 T, X
  24. if getCount(st) >= 4 :
    * ]- g) [1 |. g0 u0 Q. s6 r
  25. completed(st)
    ; k$ F' N1 L+ U& G; p& K' K' M2 R
  26. return
    $ p- T0 p  G) W

  27. 1 a2 r$ T6 l$ S/ i# d
  28. class Quest (JQuest):6 S$ O: H: a" a9 J9 U6 x

  29. 8 x' L* v$ ~1 `! K  j0 ]" j
  30. def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)# ^) L( X( z/ I& q& T1 Q

  31. 2 ]0 Z: `- i  f6 d% _3 K; [. F) x
  32. def onEvent (self,event,st):
    6 ?' |# T3 n! e, P" n" S" u) `
  33. id = st.getState()& A+ K6 q  w0 ]8 P/ x
  34. if id == CREATED : st.setState(STARTED)4 c6 F* d; c6 N! F4 ~) S
  35. elif id == COMPLETED: pass) C7 C8 @' ?% n/ i8 u
  36. elif id == STARTED : check(st)
    " Q+ G2 v" r- m- ~% _
  37. return% k# b& s& c1 J6 [8 T

  38. ; k1 a: Q: S2 ]9 \; Q& D% w
  39. def onKill (self,npcId,st):
    # x2 v( _( {% [% r. K% j7 {( W6 q+ r# S
  40. if npcId == KELTIR_NPC_ID:& y6 [' r" A) i) I9 I' b2 ~" M$ n
  41. n = getCount(st)
    + j& N0 U* ]: {" j0 X: H) p; g3 F
  42. if n == 0:7 q: n$ R& @3 z4 a5 U
  43. if st.get('chat0') == None :
    0 X/ O; W( @) |- y0 R% T' f5 q3 }* K
  44. st.set("chat0", "true")
    : r2 w3 f! f& E
  45. return "Chat0.htm"3 [, C5 w9 Z1 ^/ r  B: t
  46. elif n == 1:/ R0 c  h  x8 Q3 O  @/ h
  47. if st.get('chat1') == None :
    ( ~( c2 Z/ M) C! ]% i
  48. st.set("chat1", "true"), d' r7 t/ T" a2 \. i# n. M1 |
  49. return "Chat1.htm"
    ! M3 g# V# C8 z
  50. elif n >= 4:
    & y7 n1 H, ?" w* H5 I
  51. return "Chat4.htm"
    % F- a6 d. C1 N# G, n
  52. return "Collect "+str(n)+" of 4 fangs"3 @+ [& u9 U- V4 P
  53. return. W& p) S0 r6 Y4 f

  54.   q, p1 U; ]3 u$ D  f. Y
  55. QUEST    = Quest(201, "Tutorial", "Tutorial quest")
    ) z+ S% ^, Z8 D9 P' B
  56. CREATED = State('Start',    QUEST)
    " y1 E5 p1 T& \" @6 |8 [
  57. STARTED = State('Started', QUEST)
    * n* k+ f/ Q( L# A$ ^
  58. COMPLETED = State('Completed', QUEST)
    3 ^! S- t# M5 K3 R4 p- u

  59. ; g7 {. J, |0 j" ^/ K9 s
  60. QUEST.setInitialState(CREATED)- x8 x6 v/ c. n: i* d% z
  61. QUEST.addStartNpc(7056)
    5 p& W$ [  I( P1 r% d( t. X. L
  62. QUEST.addStartNpc(7012)
      Q; x8 F: A5 V5 e) f( [
  63. QUEST.addStartNpc(7009)8 \0 f$ c: Q3 o% }
  64. QUEST.addStartNpc(7011), O2 Y2 C  s0 Z/ x

  65. ' G" a; R# Y  O7 a# P- V4 x
  66. STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)6 z6 f: U+ c" ^
  67. STARTED.addKillId(KELTIR_NPC_ID)7 o) Z, y- |# ?/ c+ Q
  68. STARTED.addTalkId(7056)
    ! M4 [" w) A3 L# z5 }  l
  69. STARTED.addTalkI d(7012)9 d$ }, f) Z  M8 `! r0 K# p" `' p1 i
  70. STARTED.addTalkId(7009)
    6 V( x6 V* q5 T+ _" A7 I
  71. STARTED.addTalkId(7011)
Скопировать код
: l) Z, L2 a% v+ [& v$ V9 g
3 l: j3 [  m8 G1 Q$ H
Чтобы ответить, вам надо авторизироваться в системе Вход | Зарегистрироваться

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

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

638638758

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

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

admin@artace.ru Онлайн

QR-код

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