Top.Mail.Ru

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

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

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

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

x
Хроники        Interlude/ W* B5 i5 D6 j
Сборка        L2j" J0 p: F7 p) I' h8 |# p
Обратите внимание: в файле htm стартового NCP обязательно должна быть ссылка на квест:) g4 C  ?) k& c+ q7 e& {9 h
  1. STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код
Для этого квеста больше ничего не надо. Все необходимое для корректной работы квеста уже добавили. Вот полный текст квеста:
/ t' i6 B" ~" B( L3 N0 B! ]6 @2 N$ [' d- G7 m) h) o
  1. if getCount(st) >= 4 :
    , e+ X# [+ P9 U
  2. completed(st)3 b! ]4 B2 e" _9 d4 R# a8 \! k
  3.   return) @0 w6 J4 B* `, U2 i/ P/ U
  4. 9 O. c5 m2 u* ~+ e) ^
  5. class Quest (JQuest):& E! h9 d, t* g) f3 M6 p
  6.   def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)
    ; |4 R# R( t: n7 M$ D! \8 T
  7.   def onEvent (self,event,st):
    $ T# q9 `% X/ q1 }+ r
  8. id = st.getState()& x7 e5 @7 ^  {8 A+ u: S
  9. if   id == CREATED  : st.setState(STARTED)
    ) |# V4 z$ H1 H+ n) L5 M; w
  10. elif id == COMPLETED: pass. G; h; _$ ^" U( _) q
  11. elif id == STARTED  : check(st)1 J1 J6 f  h$ Z
  12. return' q6 A9 d+ T$ m% M; J  ~! O- U
  13. * R2 u( v  E1 s& s% |1 k5 z4 T. r
  14. QUEST     = Quest(201,"Tutorial", "Tutorial quest")4 z1 z3 N  j  U; ]
  15. CREATED   = State('Start',     QUEST): F/ {1 p2 X/ Q1 _  _
  16. STARTED   = State('Started',   QUEST)* F# G9 p% m& O
  17. COMPLETED = State('Completed', QUEST)5 w) d1 ^7 ]& T! m: d6 i

  18. ! F+ |# `5 C  J0 e' x
  19. QUEST.setInitialState(CREATED), _, @" n6 i/ b; g4 n) A
  20. QUEST.addStartNpc(7056), ^. E4 J! }2 \: A3 z1 [* d1 A
  21. STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код
Теперь рассмотрим, как это работает.
# f. c% b- ~- o$ O% q) qИгрок подходит к начальному NCP (в данном случае 7056), нажимает на «Quest». Квест будет создан и состояние квеста перейдет к CREATED и игроку будет показана страничка Start.htm с описанием квеста. Тогда метод onEvent, поле открытия странички Start.htm переведет состояние квеста в STARTED и игроку будет показана страничка Started.htm, где будет опсание того, как найти keltirs и .т.д.3 F1 s5 [( P$ V9 I0 A. n

/ U0 e9 |  I8 u# o$ r  r4 P% @

. M! Q7 T' e6 {" \При состоянии STARTED будет зарегистрирован дроп «fangs» при убийстве keltirs. Игрок может вернуться к стартовому NCP и спросить о квесте – метод onEvent будет вызван снова. Если у игрока не хватает необходимого количества предметов, то метод check() не переведет квест в следующее состояние и Started.htm будет показана снова. Но если игрок собрал необходимее количество предметов (в данном случае 4 клыка), то метод check() вызовет метод completed() который переведет квест в новое состояние COMPLETED, заберет все клыки, даст карту мира, т.к. это награда за квест, покажет Completed.htm и завершит квест.. n3 v9 G- a. q; c7 X
5 E  P3 q7 n/ L, G6 C$ [; w

! b. f$ A2 l! DТеперь давайте сделаем наш квест более похожим на то, что он должен из себя представлять.& Z/ [0 A& p/ s, d
Прежде всего у нас есть 3 метода для объявления их в Яве – onTalk, onKill и onEvent. Если методы onTalk и onKill не объявлены, то за них все будет делать метод onEvent, т.е. определять квестовых монстров и вызывать диалоги NCP. Есть примечание, методы onTalk и onKill будут вызывать только диалоги с NCP в зависимости от текущего состояния квеста. Метод onKill будет вызываться только тогда, когда мы убиваем квестового монстра.+ k8 V. p6 U* G- }1 O

) @# i5 v: _* F3 x
1 g7 F9 g) q/ S$ b( u5 T) h0 ?
Давайте рассмотрим как вызывается метод onKill при убийстве keltir в состоянии квеста STARTED:  I# [4 T* f+ M( `$ ]6 g
  1. STARTED.addKillId(KELTIR_NPC_ID)
Скопировать код
и метод onKill в классе Quest:( @4 c" S9 @; r, J0 V" d2 `9 M8 Z
4 K8 S6 V/ L- h& P
  1. class Quest (JQuest):, [& z' z0 |: w. K4 }
  2.   ...6 \/ C  y7 e8 ?( t
  3.   def onKill (self,npcId,st):
    # N; K* A" }0 e+ z% ]) _
  4. if npcId == KELTIR_NPC_ID:
    % c4 I' J1 e* \9 F
  5.    n = getCount(st)
    2 L9 C, W, e5 N5 L) g- ]. |
  6.    if   n == 0:  Y7 h, S  ]6 `  V
  7.        return "Chat0.htm"1 J9 X  z! H) U1 d- \
  8.    elif n == 1:* g4 _0 ^8 i9 h
  9.        return "Chat1.htm"
    ; H/ u- b0 p" d" @
  10.    elif n >= 4:0 Y8 J4 b: \# H2 |$ k! J2 ?
  11.        return "Chat4.htm"
    1 A/ O, ~. x3 F3 t3 C7 R0 P
  12.    return "Collected "+str(n)+" of 4 fangs", a5 P9 V; R, l" r& X
  13. return
Скопировать код
Метод onKill (а так же метод onTalk) имеет следующие параметры:- W' X; g3 y% m* g3 h

5 F2 N  Y  Q  H$ M, N

% ?, y0 G$ c" J0 g% o• self – квест
$ n8 w, j+ f0 Q& U( T7 i• npcId – ID NCP, которого мы должны убивать (если это метод onTalk, то ID того NCP, с которым мы должны поговорить).. K  g. h$ y$ V, c0 T, J
• st – текущее состояние игрока.4 O4 n7 R7 A: V$ T9 t
/ ~* w5 P4 T/ g3 v* ~
- d2 _3 l' q9 j3 R
В этом методе мы проверяем и отмечаем, является ли убитый NCP keltir’ом. В основном эта проверка не нужна, т.к. у нас только KELTIR_NPC_ID.
- K9 f& `* }. `3 u# ~' r* D# _% ?) ~  o* I4 E" n

0 W3 H/ d8 X0 T: VЗатем проверяем количество предметов (в данном случае количество клыков), и если их вообще нет, то возвращаем строку "Chat0.htm", если только один предмет, то возвращаем строку "Chat1.htm", если же предметов 4 или больше, то "Chat4.htm". Если строка возвращена из методов onEvent, onKill или onTalk, то сервер покажет соответствующие htm. В Chat0.htm может иметь следующий текст: «Вы не имеете ни одного клыка, возвращайтесь позже, когда соберете 4 штуки и бла, бла, бла…», в Chat1.htm может быть следующий текст: «У Вас всего 1 клык, по этому соберите еще…». В Chat4.htm – «Вы собрали необходимое количество предметов, возвращайтесь к вашему тренеру, что бы завершить квест…»/ X, {  _" `7 W) D

- r# L6 u' v/ f5 _
0 ~6 b  s4 l2 ]1 K5 o
Примечание: если в строка return начинается с "<html>", то будет показана страничка html с текстом, который стоит далее. Так вместо:
2 t1 e8 \) I; A; [. J) l8 `4 Dreturn "Chat4.htm"
8 Z: |, n+ ]5 k( B0 r
$ }; u" o4 S5 W2 P
! g7 ^, l9 G" v2 ?# r
можно поставить:& E. v  K" O/ i* ]- X) O
  1. return "<html><body>Return to your trainer to complete the quest</body></html>"
Скопировать код
Так же если строка заканчивается без .htm или в начале нет <html>, то текст будет выведен, как системное сообщение в окне чата. В нашем случае мы сделаем так, что бы при каждом убийстве keltik выводилось системное сообщение: «Собрано N из 4-х клыков».3 o' Y, i8 Q1 \8 b7 `% V
8 g/ k8 a( V6 i

  T# X$ ?+ S3 u1 }Наш код для onKill имеет один недостаток. Он будет постоянно показывать Chat0.htm, Chat1.htm и Chat4.htm, нам же необходимо, что бы Chat0.htm и Chat1.htm показывались только один раз. Как нам это сделать? С помощью переменных.
& G" i8 F& P) q7 h% g
1 [! g- l* M8 u& c) f( X$ B% y* c3 {
: Z9 t, ]3 N; ?; f
В каждом квесте строки могут храниться с помощью переменных. Эти переменные сохраняются в Вашей БД. В каждом методе мы можем назначить, прочитать и удалить переменные. Давайте изменим метод onKill, так что бы каждый диалог вызывался только один раз.0 h' y2 R9 l8 |: @- P4 h: r
  1. def onKill (self,npcId,st):2 q1 _& z# b! Q& O: ]# l
  2. if npcId == KELTIR_NPC_ID:
    + Y& t" w2 S  U2 o
  3. n = getCount(st)$ q; u3 s. g' o1 W2 y9 E" F. p
  4. if n == 0:- K3 r) v. X  a$ \2 P- ]
  5. if st.get('chat0') == None :
      N2 `* k4 [, d% o: w. ^7 {$ H
  6. st.set("chat0", "true"), |7 \$ o( m1 h! u. c
  7. return "Chat0.htm"
    6 f* g" C0 S0 P( t# z
  8. elif n == 1:
    " }+ Z! k. S/ R, r
  9. if st.get('chat1') == None :
      g* c$ J5 }* U6 a. g* |; B) U* g
  10. st.set("chat1", "true")# P* ?) T; N& {5 q2 p$ R9 t  F
  11. return "Chat1.htm"( ~9 K* i* M% H) W. ~
  12. elif n >= 4:
    " _, {9 S! i! g0 N( H  j
  13. return "Chat4.htm"
    - u3 j- U" T; h
  14. return "Collected "+str(n)+" of 4 fangs"8 ^# [2 r  ?* I  n
  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.2 c' ^) J; Q5 w' D; h# F

( q/ W1 Z; Z- Q; n
' N! p7 O5 }! c7 _3 P
Вот конечный рабочий вариант квеста:7 p% ~8 |- O5 S  x
  1. import sys
    6 ]4 Q- M4 x/ ^% U7 r
  2. from net.sf.l2j.gameserver.model.quest import State
    3 @% u' ^6 v( ~
  3. from net.sf.l2j.gameserver.model.quest import QuestState; _4 c( N8 M! e) d8 Q$ C
  4. from net.sf.l2j.gameserver.model.quest.jython import QuestJython as JQuest- P  D  t' C3 ^  H3 o

  5. 9 l! v3 E# \+ Z
  6. KELTIR_NPC_ID = 12082
    ! t1 L6 I9 e9 ]& c# y
  7. FANGS_ITEM_ID = 1859
    % @2 a' W5 I& L# a3 L' X
  8. DROP_RATE    = 5000000 t6 y/ I5 ~$ \
  9.   \6 I  I% P, l
  10. WORLD_MAP_ITEM_ID = 1665
    " g! F& P( l9 a' W0 [- W

  11. - T# ]8 y0 c! B2 Q
  12. def getCount(st) :
    ! |7 A+ F- P) q% r2 C1 t% i9 o! x
  13. return st.getQuestItemsCount(FANGS_ITEM_ID)1 p& M' V. C" ~0 x
  14. ; O/ Z7 `9 |+ n1 ^
  15. def completed(st) :
    5 v/ p8 w5 j. _
  16. st.setState(COMPLETED)
    4 K! O. \% ~( s! D: m
  17. st.clearQuestDrops()( L4 ?8 X0 ~$ [
  18. st.takeItems(FANGS_ITEM_ID,-1)% Y* Q) N) G5 ]9 U' Y5 r
  19. st.giveItems(WORLD_MAP_ITEM_ID,1)
    ) M5 H6 {. Z, q% [
  20. st.exitQuest(False)2 H! P# |; Q5 q' T; C1 y; J1 u
  21. return
    & Z2 d4 G; N1 {6 U8 T- W) f9 ^
  22. ; l/ ^6 l$ E' p* i3 i" J6 o* K
  23. def check(st) :
    6 \3 q9 K  N( J
  24. if getCount(st) >= 4 :( ~0 e$ H% K7 ~; J- B: s" T
  25. completed(st)
    - f# H# Y! G9 K+ m
  26. return1 Y4 f% x! b' j  W( V

  27. + ?5 L+ P! S' H% K: K
  28. class Quest (JQuest):. W" Y& y/ X, d2 P% p; B' l) r
  29. 2 a' x8 _- ^. }' k$ ]
  30. def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)
    ' B* g. O6 M- C2 A: {1 `
  31. 2 e  N, l# V' ~; v, h3 c$ P0 R+ q+ ]' ^
  32. def onEvent (self,event,st):, O( X# s+ z! J( E' |, d
  33. id = st.getState()
    9 i  u% q, h3 O- r3 E* D
  34. if id == CREATED : st.setState(STARTED)
    * I2 C2 l4 Q  l0 }  |8 i
  35. elif id == COMPLETED: pass
    1 G. ^$ t& u" b, x2 `' T
  36. elif id == STARTED : check(st), v" h" r3 j( w. Y" i
  37. return% [' m4 v: Y# h1 w
  38. 5 Y! ?( X& i5 s  n8 T
  39. def onKill (self,npcId,st):
    $ H4 ]# w) C5 T: y* V2 l! ~
  40. if npcId == KELTIR_NPC_ID:& G7 w" [# ~4 p5 N, f# M
  41. n = getCount(st)
    " H0 v+ X7 Z) a/ C. i1 T; X
  42. if n == 0:
    ' ^2 J; X1 ?& H% ^: N+ W
  43. if st.get('chat0') == None :
    " B7 K4 L, u, K* B7 @6 R
  44. st.set("chat0", "true")# g, Z- l; W1 d6 N# X' k! e' ~
  45. return "Chat0.htm"! Q7 H- z& `" k8 c
  46. elif n == 1:; z2 D7 `) a( n) X5 X
  47. if st.get('chat1') == None :
    - s, x- P* ~( I5 c7 V+ ?6 o
  48. st.set("chat1", "true")
    ' n( y; A/ Y* O* Q9 ]6 d4 e
  49. return "Chat1.htm"
    . O5 m* R9 r- X* x
  50. elif n >= 4:* w: K( W5 l6 a+ f# c9 h" ?
  51. return "Chat4.htm"0 ~6 k9 l: L  `- ~
  52. return "Collect "+str(n)+" of 4 fangs"* |! m& w; ?+ m/ f* o( N
  53. return
    ' G7 w# m7 o2 Q3 d
  54. % T0 \3 q. X4 E3 I8 M6 R7 C
  55. QUEST    = Quest(201, "Tutorial", "Tutorial quest")7 S/ ^. {4 h2 v! q; A, I
  56. CREATED = State('Start',    QUEST)1 h+ m2 o5 b. `1 p5 n
  57. STARTED = State('Started', QUEST), s& o$ L. [2 p$ w8 g  Z8 F  s
  58. COMPLETED = State('Completed', QUEST)/ R/ I& N7 g" @# u2 K
  59. % ?+ p2 N- t5 f9 ^% F0 K5 w) v& _' f
  60. QUEST.setInitialState(CREATED)
    ) E3 L2 R4 V' G3 I# M1 w
  61. QUEST.addStartNpc(7056)
    2 o; G8 a' f3 h/ W5 W( D/ }
  62. QUEST.addStartNpc(7012)
    % y# N& w/ N  a; r5 u
  63. QUEST.addStartNpc(7009)+ a8 v9 `4 v; T% q, ^# V. `+ c
  64. QUEST.addStartNpc(7011)
    . ^& p  v- b  X  m% P

  65. 9 u$ z, ]  ?/ v, ?
  66. STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE): [! Q6 N( Q* `5 [, \7 G& q* x
  67. STARTED.addKillId(KELTIR_NPC_ID)" {$ m! M5 f: j9 u* T
  68. STARTED.addTalkId(7056)
    4 Z: v7 g; h% D2 G) V( K
  69. STARTED.addTalkI d(7012): z5 ~( G8 N* J1 k; W/ l
  70. STARTED.addTalkId(7009)* D5 G4 {6 c2 E# v1 Q8 U
  71. STARTED.addTalkId(7011)
Скопировать код

1 k2 g3 J# D) K! a: q: o6 E, |+ c, e( o* x( I5 [! G8 ]) `. t4 |" p
Чтобы ответить, вам надо авторизироваться в системе Вход | Зарегистрироваться

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

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

638638758

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

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

admin@artace.ru Онлайн

QR-код

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