Top.Mail.Ru

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

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

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

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

x
Хроники        Interlude) a& ^4 {$ }* P' c2 H& a
Сборка        L2j
, t3 d9 {: C, H5 ?+ S2 }, J2 sОбратите внимание: в файле htm стартового NCP обязательно должна быть ссылка на квест:
0 f, ], a7 a, L2 g: v0 W
  1. STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код
Для этого квеста больше ничего не надо. Все необходимое для корректной работы квеста уже добавили. Вот полный текст квеста:
/ p- U1 m7 y8 d  w/ [6 u! \) X. t% ~6 [. V
  1. if getCount(st) >= 4 :1 K9 _$ v: c& B- G
  2. completed(st)
    9 t; S' N  F" o) h- D" {$ T
  3.   return
    9 K+ H1 c$ E6 o
  4. * j7 }3 v8 _2 N6 V6 ?
  5. class Quest (JQuest):' i$ `; Q4 j6 u9 x" Y
  6.   def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)
    ) V+ a2 \' s% l) u0 z
  7.   def onEvent (self,event,st):
    4 t) t9 W6 L2 t5 c' P
  8. id = st.getState()
    $ ~" |# e; Q; @* s7 q, g4 y
  9. if   id == CREATED  : st.setState(STARTED); k* j: J7 X% S* a3 C/ ^' z1 s4 A
  10. elif id == COMPLETED: pass
    : h6 z4 d8 n3 G  a( O' H+ |
  11. elif id == STARTED  : check(st)
    ) p5 Q; [3 x0 ]0 l+ x1 [8 L
  12. return
    - R/ _' m4 Q" W, `

  13. * U8 p: r: H5 J+ m$ B4 v' X
  14. QUEST     = Quest(201,"Tutorial", "Tutorial quest")7 e, w, d2 ^* i3 H: k
  15. CREATED   = State('Start',     QUEST); V+ \. L5 V: V3 L6 g3 U
  16. STARTED   = State('Started',   QUEST)8 D1 X: T4 z* y6 a0 K" e3 H# \
  17. COMPLETED = State('Completed', QUEST), h1 L5 C: G, U9 M

  18. # i# \( L* m- }$ e8 B
  19. QUEST.setInitialState(CREATED)
    ( H! T5 }1 m9 q- G9 I0 ?1 X
  20. QUEST.addStartNpc(7056)5 B; A( K. o  h# p% h! C8 J  s
  21. STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код
Теперь рассмотрим, как это работает.
; T' P0 H, R2 i: p6 E; k/ ZИгрок подходит к начальному NCP (в данном случае 7056), нажимает на «Quest». Квест будет создан и состояние квеста перейдет к CREATED и игроку будет показана страничка Start.htm с описанием квеста. Тогда метод onEvent, поле открытия странички Start.htm переведет состояние квеста в STARTED и игроку будет показана страничка Started.htm, где будет опсание того, как найти keltirs и .т.д.
# W3 R" L" ^" g7 e, }. E/ X# p# B! o1 G/ z  {* |" q! M
! ^( x3 p1 d( _/ D
При состоянии STARTED будет зарегистрирован дроп «fangs» при убийстве keltirs. Игрок может вернуться к стартовому NCP и спросить о квесте – метод onEvent будет вызван снова. Если у игрока не хватает необходимого количества предметов, то метод check() не переведет квест в следующее состояние и Started.htm будет показана снова. Но если игрок собрал необходимее количество предметов (в данном случае 4 клыка), то метод check() вызовет метод completed() который переведет квест в новое состояние COMPLETED, заберет все клыки, даст карту мира, т.к. это награда за квест, покажет Completed.htm и завершит квест.
4 W" ]& f$ G/ |9 H+ j& k  M% y6 Q1 o

$ F) N$ A" r1 _, Z3 I. [/ ^3 {, ~* HТеперь давайте сделаем наш квест более похожим на то, что он должен из себя представлять.7 c0 J4 P) j4 ^" i
Прежде всего у нас есть 3 метода для объявления их в Яве – onTalk, onKill и onEvent. Если методы onTalk и onKill не объявлены, то за них все будет делать метод onEvent, т.е. определять квестовых монстров и вызывать диалоги NCP. Есть примечание, методы onTalk и onKill будут вызывать только диалоги с NCP в зависимости от текущего состояния квеста. Метод onKill будет вызываться только тогда, когда мы убиваем квестового монстра.  I7 Y/ p$ i3 }& O2 L( X

( d- [+ N0 X. o; K

# C; {& R2 a8 L$ k/ zДавайте рассмотрим как вызывается метод onKill при убийстве keltir в состоянии квеста STARTED:' R6 e& m; _# X0 M) d: x5 \' G
  1. STARTED.addKillId(KELTIR_NPC_ID)
Скопировать код
и метод onKill в классе Quest:
, P7 W" v# O" r3 E* T% R' }) H- V8 {( j+ J
  1. class Quest (JQuest):
    1 s% g% R- ]0 t8 P6 {! B' {. ~
  2.   ...
    ( c! y: v9 m9 B5 [- w
  3.   def onKill (self,npcId,st):0 t: }9 }2 {% J$ a/ l1 E
  4. if npcId == KELTIR_NPC_ID:
    0 R0 y# m& s( C3 e3 I
  5.    n = getCount(st)
    / N% X, G* d( B. c# w9 m
  6.    if   n == 0:$ }" B3 T- H6 ~5 a: O2 s/ H
  7.        return "Chat0.htm", i$ ~, d) Q! W! ]( u& R4 G, M; ^) i2 ?
  8.    elif n == 1:3 g( H9 y4 I* T0 }! B- [: R. d& A) ^9 D
  9.        return "Chat1.htm"
    " e" ~  w! S9 U5 ^8 k
  10.    elif n >= 4:
    ( o: j2 E& u( x# T
  11.        return "Chat4.htm"
    : ~% D$ B  D" }4 e( W7 W
  12.    return "Collected "+str(n)+" of 4 fangs"
    / g$ G# B7 i1 T8 r
  13. return
Скопировать код
Метод onKill (а так же метод onTalk) имеет следующие параметры:# m9 v* W0 l. d

& u1 ]; R; ]2 T4 ^. n

& {& f& a' E' x3 D1 ?1 |( N• self – квест* j, v9 L& v9 o3 ^* k1 k4 _+ M
• npcId – ID NCP, которого мы должны убивать (если это метод onTalk, то ID того NCP, с которым мы должны поговорить).
) P) `4 A0 L) `; ^! }% j6 J1 B4 u• st – текущее состояние игрока.
& p2 b" m( ^2 @7 d9 |; X$ u1 s$ x
' z- x8 Y6 s+ @4 \( n' k

1 ^* x% A4 t6 P* s) C$ v9 ~В этом методе мы проверяем и отмечаем, является ли убитый NCP keltir’ом. В основном эта проверка не нужна, т.к. у нас только KELTIR_NPC_ID.0 n$ [2 T- f( F. O
7 r4 E1 n% c4 n$ J" Z/ R) L
# |6 S% E' s2 e' C1 H
Затем проверяем количество предметов (в данном случае количество клыков), и если их вообще нет, то возвращаем строку "Chat0.htm", если только один предмет, то возвращаем строку "Chat1.htm", если же предметов 4 или больше, то "Chat4.htm". Если строка возвращена из методов onEvent, onKill или onTalk, то сервер покажет соответствующие htm. В Chat0.htm может иметь следующий текст: «Вы не имеете ни одного клыка, возвращайтесь позже, когда соберете 4 штуки и бла, бла, бла…», в Chat1.htm может быть следующий текст: «У Вас всего 1 клык, по этому соберите еще…». В Chat4.htm – «Вы собрали необходимое количество предметов, возвращайтесь к вашему тренеру, что бы завершить квест…»
( a4 A4 M, T0 Q6 A& m( O% K& R/ {
, ?% p( u, t4 P' ~* u

4 C$ k& U) D  P+ d( IПримечание: если в строка return начинается с "<html>", то будет показана страничка html с текстом, который стоит далее. Так вместо:
6 ?- W9 K# \; ]4 |) ]3 _& y& Mreturn "Chat4.htm"
  i( l) ~5 U9 k1 {9 D! ?9 A
4 Q0 c6 E7 _7 `1 ^- o0 w' N; d

6 O2 O+ _9 v5 J; u6 l6 tможно поставить:
1 `/ ^/ a# T7 c/ _; Q
  1. return "<html><body>Return to your trainer to complete the quest</body></html>"
Скопировать код
Так же если строка заканчивается без .htm или в начале нет <html>, то текст будет выведен, как системное сообщение в окне чата. В нашем случае мы сделаем так, что бы при каждом убийстве keltik выводилось системное сообщение: «Собрано N из 4-х клыков».( i6 Q+ w; D1 D& d+ z& s
0 R. i0 B+ {5 l4 e+ J9 p% q
% E2 l8 u7 J0 X1 ?5 V# G1 \
Наш код для onKill имеет один недостаток. Он будет постоянно показывать Chat0.htm, Chat1.htm и Chat4.htm, нам же необходимо, что бы Chat0.htm и Chat1.htm показывались только один раз. Как нам это сделать? С помощью переменных.
1 Z0 R" I5 V- o
* `/ c9 @, h6 W* v8 B" h5 X
0 ?4 h6 u4 a3 _; j- O+ k, z
В каждом квесте строки могут храниться с помощью переменных. Эти переменные сохраняются в Вашей БД. В каждом методе мы можем назначить, прочитать и удалить переменные. Давайте изменим метод onKill, так что бы каждый диалог вызывался только один раз.
& C% J3 X* t. h  X3 j
  1. def onKill (self,npcId,st):" \6 z7 X; q3 i2 E1 M. `" T0 _
  2. if npcId == KELTIR_NPC_ID:0 C0 B  S' L' W
  3. n = getCount(st)3 N  k4 F" {9 n# Q
  4. if n == 0:
    2 K# c/ X0 t' U& E! X& ?# }9 W
  5. if st.get('chat0') == None :
    2 P( Y4 m7 }4 \% B5 G
  6. st.set("chat0", "true")
    + H- W+ R; @5 ]. \: t
  7. return "Chat0.htm"
    ' l8 q9 @- E4 t1 g, f4 D+ r
  8. elif n == 1:
    ( F" m6 r- ^( s, r% i
  9. if st.get('chat1') == None :
    4 d* g9 w5 `6 F8 C8 A- p
  10. st.set("chat1", "true")
    ' y2 l( b% B5 ?9 Z2 ]. A
  11. return "Chat1.htm"8 I( j3 i& J; P( N+ T
  12. elif n >= 4:
    9 f+ q5 x. S" C5 J# ]
  13. return "Chat4.htm"6 @0 v6 p8 b& v/ q+ W
  14. return "Collected "+str(n)+" of 4 fangs"5 f1 @( Z9 @( f( j+ O; t& h5 a
  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.
# r3 G; {9 X; U7 m* N
. Y& x6 ^3 a8 M: C% Y
6 i; s" p3 w  i' u, u+ i9 v: }; V
Вот конечный рабочий вариант квеста:: Z: K4 W! k( j
  1. import sys# ?% a# O% o3 P9 ?& U/ G/ m
  2. from net.sf.l2j.gameserver.model.quest import State
    . H- d2 c0 I& x; h# L' W. K
  3. from net.sf.l2j.gameserver.model.quest import QuestState
    / Z0 s1 B3 t6 X2 @6 j
  4. from net.sf.l2j.gameserver.model.quest.jython import QuestJython as JQuest8 C( |7 O4 M& Z) C

  5. 5 u* R* ?* L. v* t# k( X7 t' e
  6. KELTIR_NPC_ID = 12082
    " i, Y. E! [- ^( [0 e
  7. FANGS_ITEM_ID = 1859
    % X/ ?5 U0 F. E/ N, a( Q
  8. DROP_RATE    = 500000
    8 |. p" j/ E8 X! z0 V5 c, y
  9. % Z3 F! z( a, A4 K% f* u
  10. WORLD_MAP_ITEM_ID = 1665
    # |( ?" a. r: ~! I* t; V

  11. ! s$ P* b4 W6 b0 l5 u; _
  12. def getCount(st) :
    + z0 F( ]0 u+ ~/ M4 j& i) h
  13. return st.getQuestItemsCount(FANGS_ITEM_ID)1 t8 L  ?! r' b# d+ Z. }% U  w

  14. / O- b$ e* f7 u" H
  15. def completed(st) :7 D# q1 G% y& v' k
  16. st.setState(COMPLETED)# V: A4 X0 ]: j: p
  17. st.clearQuestDrops()9 T% k) p) [+ I1 }" s9 {
  18. st.takeItems(FANGS_ITEM_ID,-1)$ i1 \" J* x' g0 P0 s3 e; ^5 L
  19. st.giveItems(WORLD_MAP_ITEM_ID,1): O) V' |# X& s9 @  J
  20. st.exitQuest(False)
    ) m; ?" l" [4 ~3 X4 C( j
  21. return' w- U& q4 w# i) u

  22. & |# c( ~0 Y, Z+ S. v: `+ |
  23. def check(st) :9 N$ \5 q; M  {6 L8 r9 }
  24. if getCount(st) >= 4 :1 D7 q7 [2 C+ h' w0 h1 H; x: X5 X
  25. completed(st)
    & c1 Y* Q* Q9 c  S3 d4 p
  26. return
    * ]8 N7 e9 e/ A+ k1 ~
  27. + r, Z+ P, l& W
  28. class Quest (JQuest):: c4 h: c# X+ D7 i2 Y
  29. 1 M4 H0 @* ?1 {- V1 R3 R
  30. def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)
    # C& U1 w, J4 Y% k3 e6 N
  31. ' W7 Z7 P' Z" X. C: l7 Q
  32. def onEvent (self,event,st):
    ! f9 D7 V' a" @) Y- U# ~  }+ Z
  33. id = st.getState()
    ' ]/ w, F! u- Y% x5 d' j* \* m
  34. if id == CREATED : st.setState(STARTED)
    % m1 F3 k1 ]8 ]: W: F
  35. elif id == COMPLETED: pass
    5 U* k8 l8 ]' o5 T) ~4 M1 l
  36. elif id == STARTED : check(st)+ U% T* T8 F) h6 b
  37. return: |( R9 S! L8 G$ |

  38. 2 ~# \; q$ C$ f, S2 J
  39. def onKill (self,npcId,st):
    ! j6 _1 K" n# A! x  H) G
  40. if npcId == KELTIR_NPC_ID:- ]* X4 V8 |8 e0 E5 f
  41. n = getCount(st)8 {' f9 X/ Y( C
  42. if n == 0:
    ) n: q, o, D; m
  43. if st.get('chat0') == None :
    7 U* n& f, D6 N/ [9 u+ \
  44. st.set("chat0", "true")
    8 j2 Z4 _' z4 _) R8 C, q5 D
  45. return "Chat0.htm"  d* _; P# Z( O1 J; D; e
  46. elif n == 1:
    . c1 h- V+ f& T. u& z3 e
  47. if st.get('chat1') == None :  L/ z+ M) s6 g# ^, R
  48. st.set("chat1", "true")3 O! T4 ]" k3 ?: @+ ]+ Y4 F9 f
  49. return "Chat1.htm"
    + g1 }' L/ Q: i5 Y9 a! j
  50. elif n >= 4:) w# v# Z8 N# B+ S6 b# X8 h, x3 S
  51. return "Chat4.htm"! y, H, P' [* x' i, P: w0 U
  52. return "Collect "+str(n)+" of 4 fangs"
    $ L1 q/ E0 i" z
  53. return
    2 x$ p& G9 ~" F- S! _, K. M; @* }1 b

  54. 3 ~( |: @1 g: ]6 `9 y- `0 m+ K
  55. QUEST    = Quest(201, "Tutorial", "Tutorial quest"); |3 e0 Y' Z6 }' p
  56. CREATED = State('Start',    QUEST)
    - v/ |! r) V) i
  57. STARTED = State('Started', QUEST)' [( l0 N; }$ S$ k/ }
  58. COMPLETED = State('Completed', QUEST)( T; _2 w* g$ I/ }  N' Q
  59. - X$ j3 A/ F% Q3 w3 X
  60. QUEST.setInitialState(CREATED): `2 F2 i% J* w, @
  61. QUEST.addStartNpc(7056)$ L* Q0 \+ t4 s7 x3 q
  62. QUEST.addStartNpc(7012)1 Y$ n" d7 A. B$ z, W0 `& b5 f
  63. QUEST.addStartNpc(7009)  o( w6 r# B" c3 r: |
  64. QUEST.addStartNpc(7011)5 y; ^! p3 r* ~5 [/ I0 R

  65. 8 D2 g7 C( X4 ?
  66. STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
    3 ]# _4 ^1 ]  U8 X4 |0 e7 _- i
  67. STARTED.addKillId(KELTIR_NPC_ID)( F2 C0 j7 _  d3 L3 p' K! x0 J3 W
  68. STARTED.addTalkId(7056). S. c3 A) A, V- y
  69. STARTED.addTalkI d(7012)$ q% h' [7 c. P
  70. STARTED.addTalkId(7009); h' P7 w5 N; `0 ~1 O9 o
  71. STARTED.addTalkId(7011)
Скопировать код
# Q! K. W9 r8 q" f5 o  g

+ Q0 i" n; r3 ^" ?: B- m
Чтобы ответить, вам надо авторизироваться в системе Вход | Зарегистрироваться

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

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

638638758

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

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

admin@artace.ru Онлайн

QR-код

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