Top.Mail.Ru

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

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

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

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

x
Хроники        Interlude& N/ E0 x9 h4 W7 j& g* `
Сборка        L2j
* X# S! Q$ t- M  l# @Обратите внимание: в файле htm стартового NCP обязательно должна быть ссылка на квест:0 M& S4 a- g% a' q0 V' |  ^7 H2 L# Y
  1. STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код
Для этого квеста больше ничего не надо. Все необходимое для корректной работы квеста уже добавили. Вот полный текст квеста:: f( o* t; w" g  y8 Z
7 M% C8 Y* _: @5 }7 y6 Y* m3 H/ Y. n
  1. if getCount(st) >= 4 :" r. W* E5 P  J" y$ X7 e/ y
  2. completed(st)
    : O5 f8 M: v5 N  V, f6 Q5 u& U1 Z! R% ~. z
  3.   return
    8 J$ h2 I9 P3 Z7 A
  4. - C) [* m! x+ W/ Z: u% A: |
  5. class Quest (JQuest):1 h3 k3 o/ V' Y% a$ }  u
  6.   def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)! A: @: l2 j( [0 c( C5 e
  7.   def onEvent (self,event,st):; _+ r. p/ Z- u" G% I6 O/ P& f2 a4 B
  8. id = st.getState()8 O. t0 R* H- x
  9. if   id == CREATED  : st.setState(STARTED)
    $ ~1 N2 E1 F5 H* s" J, K6 E2 L! _1 n' n
  10. elif id == COMPLETED: pass. O3 T+ A4 V# n+ J% S. t
  11. elif id == STARTED  : check(st)1 _1 v6 m$ l. q
  12. return4 N, i+ [0 U( u8 ^6 R8 i6 {
  13. % s, m3 g# {# N; q" `# X
  14. QUEST     = Quest(201,"Tutorial", "Tutorial quest")
    ! d5 y) F( }# z- N5 i8 a
  15. CREATED   = State('Start',     QUEST)
    " y; h9 @0 J1 }2 X6 _5 t
  16. STARTED   = State('Started',   QUEST)- A( A' Q( D: r- @
  17. COMPLETED = State('Completed', QUEST)8 A) M, z2 V& R$ R- J: _
  18. 9 E9 X1 z' u* `: k( K' M: ?" F
  19. QUEST.setInitialState(CREATED)
    - Z9 Y$ G& B% a+ O2 v
  20. QUEST.addStartNpc(7056)
    / y2 [& J5 R! r$ N. k
  21. STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код
Теперь рассмотрим, как это работает.# ~3 A/ j3 c. R' M
Игрок подходит к начальному NCP (в данном случае 7056), нажимает на «Quest». Квест будет создан и состояние квеста перейдет к CREATED и игроку будет показана страничка Start.htm с описанием квеста. Тогда метод onEvent, поле открытия странички Start.htm переведет состояние квеста в STARTED и игроку будет показана страничка Started.htm, где будет опсание того, как найти keltirs и .т.д.% M, C- ?9 V, a  W
) S+ g% x* R; N/ B, [  K
3 ^/ X) V/ v- \: s7 x' m! z
При состоянии STARTED будет зарегистрирован дроп «fangs» при убийстве keltirs. Игрок может вернуться к стартовому NCP и спросить о квесте – метод onEvent будет вызван снова. Если у игрока не хватает необходимого количества предметов, то метод check() не переведет квест в следующее состояние и Started.htm будет показана снова. Но если игрок собрал необходимее количество предметов (в данном случае 4 клыка), то метод check() вызовет метод completed() который переведет квест в новое состояние COMPLETED, заберет все клыки, даст карту мира, т.к. это награда за квест, покажет Completed.htm и завершит квест.+ p( n, [  e7 x1 N! w7 K
5 F) L5 w3 E4 _1 `7 y

5 I0 e" H4 P3 I  u. Q% d7 U' WТеперь давайте сделаем наш квест более похожим на то, что он должен из себя представлять.
' C. L: x% r5 B+ V' ^4 XПрежде всего у нас есть 3 метода для объявления их в Яве – onTalk, onKill и onEvent. Если методы onTalk и onKill не объявлены, то за них все будет делать метод onEvent, т.е. определять квестовых монстров и вызывать диалоги NCP. Есть примечание, методы onTalk и onKill будут вызывать только диалоги с NCP в зависимости от текущего состояния квеста. Метод onKill будет вызываться только тогда, когда мы убиваем квестового монстра.
2 n( P) q% u; I# R4 o0 u
& `3 z; |0 N$ j! {$ e+ M2 ]

: W" P3 S: r0 \5 FДавайте рассмотрим как вызывается метод onKill при убийстве keltir в состоянии квеста STARTED:
8 h1 R. _$ ], D+ I  q
  1. STARTED.addKillId(KELTIR_NPC_ID)
Скопировать код
и метод onKill в классе Quest:
" a" R; w5 [8 N0 @* ?+ ^2 L6 Y6 y. `+ u
  1. class Quest (JQuest):
    2 |% \. `7 L- g/ N2 F9 N2 y
  2.   ...
    ; b9 \. T; ~. f( I9 }0 h7 W
  3.   def onKill (self,npcId,st):
    * @6 X+ j8 a9 \7 N2 O% z
  4. if npcId == KELTIR_NPC_ID:
    ! M$ ^# o: Q* e3 g, H7 r
  5.    n = getCount(st)
    $ t  B$ i( U0 A$ o: u
  6.    if   n == 0:
    ( ]/ p" c0 |& M! W) O
  7.        return "Chat0.htm"0 b  i0 Q, B5 X5 {& w
  8.    elif n == 1:8 ]% m4 A8 Y, n( h5 ]: z4 H5 t
  9.        return "Chat1.htm"6 R" }# V) x( H0 y; K1 r( T
  10.    elif n >= 4:
    ; C% E( }. u1 l6 Y0 t7 V* \9 ]/ l7 T
  11.        return "Chat4.htm"
    - `$ V/ T* m" Z
  12.    return "Collected "+str(n)+" of 4 fangs"1 }, X8 `  b; t4 j. E/ f
  13. return
Скопировать код
Метод onKill (а так же метод onTalk) имеет следующие параметры:
" |( U" a* e/ _( d/ @
" f7 J, u& v5 N/ b

9 D; }! W& W' F2 m• self – квест2 G* i" j) ^2 C
• npcId – ID NCP, которого мы должны убивать (если это метод onTalk, то ID того NCP, с которым мы должны поговорить).; c6 l; E) @* |: u3 T4 J
• st – текущее состояние игрока.
% y& Q; f3 [, |
/ `. f  [* f7 {% U0 K
3 j% R8 k! s3 A
В этом методе мы проверяем и отмечаем, является ли убитый NCP keltir’ом. В основном эта проверка не нужна, т.к. у нас только KELTIR_NPC_ID.$ B7 T$ z. R+ t, M7 [. F3 t
  y4 U$ P3 e5 `# u

6 U7 F  T% Z" c: S7 q; wЗатем проверяем количество предметов (в данном случае количество клыков), и если их вообще нет, то возвращаем строку "Chat0.htm", если только один предмет, то возвращаем строку "Chat1.htm", если же предметов 4 или больше, то "Chat4.htm". Если строка возвращена из методов onEvent, onKill или onTalk, то сервер покажет соответствующие htm. В Chat0.htm может иметь следующий текст: «Вы не имеете ни одного клыка, возвращайтесь позже, когда соберете 4 штуки и бла, бла, бла…», в Chat1.htm может быть следующий текст: «У Вас всего 1 клык, по этому соберите еще…». В Chat4.htm – «Вы собрали необходимое количество предметов, возвращайтесь к вашему тренеру, что бы завершить квест…»
7 N; k* F+ K4 |
' a; T7 {1 ^7 K8 m
. p$ T7 \2 \& K$ l0 g1 N$ t
Примечание: если в строка return начинается с "<html>", то будет показана страничка html с текстом, который стоит далее. Так вместо:0 ^  B7 X% K( B3 t9 M% E
return "Chat4.htm"7 W. R( p. }- [& m4 ^2 R% q7 e0 E
) U0 J; u% ~3 S6 F7 e$ C5 F

8 t. ^- f2 ^0 C: I, p1 rможно поставить:# N9 C( G& T2 o
  1. return "<html><body>Return to your trainer to complete the quest</body></html>"
Скопировать код
Так же если строка заканчивается без .htm или в начале нет <html>, то текст будет выведен, как системное сообщение в окне чата. В нашем случае мы сделаем так, что бы при каждом убийстве keltik выводилось системное сообщение: «Собрано N из 4-х клыков».
, h1 T2 Y( s- ^: W6 O4 K, j* z& q( Z0 L8 Z3 y

! \' L6 q( m$ g+ L+ SНаш код для onKill имеет один недостаток. Он будет постоянно показывать Chat0.htm, Chat1.htm и Chat4.htm, нам же необходимо, что бы Chat0.htm и Chat1.htm показывались только один раз. Как нам это сделать? С помощью переменных.
& h$ Y. c# M% w+ v" Z$ E. R  t) ]7 I/ @" S" Z" o
( l+ L2 T( l0 w
В каждом квесте строки могут храниться с помощью переменных. Эти переменные сохраняются в Вашей БД. В каждом методе мы можем назначить, прочитать и удалить переменные. Давайте изменим метод onKill, так что бы каждый диалог вызывался только один раз.7 s2 d' {( [% V/ s
  1. def onKill (self,npcId,st):
    , ^% w, q6 a. }! q
  2. if npcId == KELTIR_NPC_ID:
    6 R9 j  D0 L# X' M- Z1 d
  3. n = getCount(st)$ z; F: U# s, f% o* N' c
  4. if n == 0:0 p% [: K5 y4 D( p
  5. if st.get('chat0') == None :& m1 `# \4 X+ ?; s) K/ {! ?/ K3 y: q
  6. st.set("chat0", "true")% T/ c1 T( B$ c( m/ D
  7. return "Chat0.htm"
    * I( l! I+ A$ ?, |8 y
  8. elif n == 1:
    . j; U8 {# j3 S" f0 @; l
  9. if st.get('chat1') == None :4 K% C% r) E( ^: {4 t
  10. st.set("chat1", "true")
    7 F& A, Q+ h" f8 s2 d- \
  11. return "Chat1.htm"
    5 b8 b# b+ J$ [1 T6 ^) e5 e
  12. elif n >= 4:
    % X2 X, u, ?* f9 I& t/ H* u$ J
  13. return "Chat4.htm"; z5 K2 Y% W! E
  14. return "Collected "+str(n)+" of 4 fangs"; N* m1 e2 N1 S
  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.
: N: }1 o# B. ?' E+ A: l  L8 X
" M7 {& D  A1 l9 M2 ^- J" K& H$ F
1 b% h9 S* ]  l5 N+ R
Вот конечный рабочий вариант квеста:" A( c  A8 I( I0 r/ w. s" A
  1. import sys
    6 @( {4 y7 q# {$ G
  2. from net.sf.l2j.gameserver.model.quest import State3 R4 M: _. @3 c# X! }9 K; j9 @
  3. from net.sf.l2j.gameserver.model.quest import QuestState" H$ |: |3 d# a5 \2 G* N9 a9 e
  4. from net.sf.l2j.gameserver.model.quest.jython import QuestJython as JQuest4 R# z0 k6 ~+ b
  5. ; P. I* E% X4 {, C
  6. KELTIR_NPC_ID = 12082
    + v- g1 M3 V& z% z4 s7 Y5 V
  7. FANGS_ITEM_ID = 18594 W# q: C4 X" t! T' X
  8. DROP_RATE    = 500000
    . ]$ @; {9 d% z

  9. 6 k; H7 {! m; }% i# o
  10. WORLD_MAP_ITEM_ID = 16653 ]) S1 N8 S! }: j8 R# N) }

  11. 0 l" A4 d; H4 j/ l
  12. def getCount(st) :( F& `) G" _  Z
  13. return st.getQuestItemsCount(FANGS_ITEM_ID)
    - r  {- N3 ]# J! j
  14. - w% {! C1 H* |! \2 H. I
  15. def completed(st) :3 I; R9 X! i, }4 q$ p" e6 v
  16. st.setState(COMPLETED)
    ( i0 w& ]8 A( ?' Q0 t3 q) L
  17. st.clearQuestDrops()- i" @' T# r( J, Q
  18. st.takeItems(FANGS_ITEM_ID,-1)
    - i3 C/ C% s; B- K5 f& N! A
  19. st.giveItems(WORLD_MAP_ITEM_ID,1), E5 z& m8 k: f- s
  20. st.exitQuest(False)
    - S" g) B1 ~7 S8 s1 ^* ~
  21. return
    & c& g+ z/ z; e) f1 d2 G& @5 u

  22. . _( T/ q% V4 k& L0 q) g) d3 p2 U
  23. def check(st) :
    0 `9 Z5 {2 p4 w* v7 G# p
  24. if getCount(st) >= 4 :
    5 w  z4 s1 T# g) W" i
  25. completed(st)6 G6 R6 v' v" t* j1 h- W/ Z* N
  26. return
    ! o1 Z6 z) }* m9 m) u3 ~
  27. . k6 @7 j. @( E* P
  28. class Quest (JQuest):
    ' D& ?! U7 P4 M
  29. . z- G) i% q) n; c. e1 n
  30. def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)) [0 _& T0 c8 t) ]+ H/ k

  31. $ \3 N* p% X# z7 a, e, o, r# P$ P' y
  32. def onEvent (self,event,st):6 B) J2 Q! r' Y! P
  33. id = st.getState()
    5 P6 d7 I3 T2 b( x; Q* m
  34. if id == CREATED : st.setState(STARTED)
    % W9 ]& b: n( }$ g% j4 g! }
  35. elif id == COMPLETED: pass
    ( g& ~( J+ Z; G1 a1 C
  36. elif id == STARTED : check(st)
    . w" e- g5 @0 t0 Y! {* T1 |
  37. return
    ) U6 ~, v6 O. o, |, \

  38. & F7 F, d7 W4 A9 M4 e5 h$ w
  39. def onKill (self,npcId,st):
    + N# i- @- g  J/ O5 c, k0 S! K
  40. if npcId == KELTIR_NPC_ID:
    , K! a- p0 C/ L* b- c# T% l# W
  41. n = getCount(st)
    9 ]. c* [! B$ x* V
  42. if n == 0:+ M' W' K8 q, G1 ?8 h
  43. if st.get('chat0') == None :
    ! W5 }3 |  ^3 |) A" h
  44. st.set("chat0", "true"). L, o2 S/ i- s- u# ]
  45. return "Chat0.htm"
    % k8 \9 ?" Q: ~
  46. elif n == 1:5 m4 M4 C8 Y7 `6 v
  47. if st.get('chat1') == None :
      o. y6 I- T/ z# E
  48. st.set("chat1", "true")
    5 L+ E- |, X" I8 ?
  49. return "Chat1.htm"
    & x; g1 g( o: p9 u- Q) |! Y. u
  50. elif n >= 4:
    " P; w9 H% X! {
  51. return "Chat4.htm"+ K% o# o! ?+ Z: z
  52. return "Collect "+str(n)+" of 4 fangs"
    # F6 _6 _2 e. I+ M
  53. return7 d2 P1 j: C# n. L8 N

  54. 8 H) y5 U7 q! M
  55. QUEST    = Quest(201, "Tutorial", "Tutorial quest")" a$ K, d+ n0 D& c$ ]! V' F1 r& Q& D
  56. CREATED = State('Start',    QUEST)
    9 q. H; V# h( k+ g5 J' f
  57. STARTED = State('Started', QUEST)
    4 F* T6 b- M; O  H! @6 F- j3 b: W
  58. COMPLETED = State('Completed', QUEST)
    ; e, g) h' k( H2 N6 Z; x3 E# k4 ?& K7 {

  59. & m5 p1 D; ~* ?8 e' E
  60. QUEST.setInitialState(CREATED)
    5 J9 b9 r' I; I, ^* a  I
  61. QUEST.addStartNpc(7056)
    # a: ?6 R1 O# X* \* k3 S% ?3 |8 d
  62. QUEST.addStartNpc(7012)# C8 ?! g) Y; R% b) @
  63. QUEST.addStartNpc(7009)
    - p: Y3 V; w/ V+ X4 x- u' f  {
  64. QUEST.addStartNpc(7011)2 l/ l1 P/ B; T5 r8 }5 u

  65.   O& L  p( f, y( P9 c1 v9 ]
  66. STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
    # Z8 ~% s. C0 w' i( I1 w# |) \
  67. STARTED.addKillId(KELTIR_NPC_ID)* Y6 n6 y3 }, }2 A
  68. STARTED.addTalkId(7056)! q8 v( o& J0 B/ y' Q. s9 r
  69. STARTED.addTalkI d(7012)7 L+ g/ A# P. g2 D; }* U# v
  70. STARTED.addTalkId(7009)
    4 {6 M; P3 j2 ^+ X- [
  71. STARTED.addTalkId(7011)
Скопировать код

9 I' \2 t/ S3 h
( A3 _( G  r- P5 f
Чтобы ответить, вам надо авторизироваться в системе Вход | Зарегистрироваться

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

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

638638758

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

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

admin@artace.ru Онлайн

QR-код

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