Top.Mail.Ru

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

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

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

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

x
Хроники        Interlude
* \* `; {% t! R0 T- XСборка        L2j8 o' S7 }  l2 z$ @6 ~. D
Обратите внимание: в файле htm стартового NCP обязательно должна быть ссылка на квест:( @+ A* u, i& H$ f" l4 H
  1. STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код
Для этого квеста больше ничего не надо. Все необходимое для корректной работы квеста уже добавили. Вот полный текст квеста:* X/ q7 x$ }. D) D# ]* x

  C! Z4 J+ W; T) r- [
  1. if getCount(st) >= 4 :) i2 M% |! h6 q4 v/ Q
  2. completed(st)& U8 I' D4 M  I7 z
  3.   return
    3 Z# Z  E. G, K% s' @; e

  4. 0 n( k8 O7 N( j9 i; e+ B) F
  5. class Quest (JQuest):
    8 E& @- c" z) Q  g% D1 ?8 ~
  6.   def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)
    9 @( a2 `* J5 m! F3 X
  7.   def onEvent (self,event,st):' p, l/ s8 U4 j
  8. id = st.getState()
      _! [7 @6 F- d$ [
  9. if   id == CREATED  : st.setState(STARTED)3 g, Q) G# w0 o
  10. elif id == COMPLETED: pass
    : a! b5 n1 @0 O( Q
  11. elif id == STARTED  : check(st)1 {1 L5 @' b) v. e7 J9 m
  12. return9 @  |* N" E( j9 a$ ~# U" S

  13. 1 f( e6 s1 `3 `9 k
  14. QUEST     = Quest(201,"Tutorial", "Tutorial quest")$ ?, a1 |5 s9 s6 v1 l
  15. CREATED   = State('Start',     QUEST)9 h7 ?2 H* x! f+ L( H
  16. STARTED   = State('Started',   QUEST)( @" U; R3 h3 ]3 l6 Z- I
  17. COMPLETED = State('Completed', QUEST)( t  J- J( ?1 f6 t+ e0 l1 D

  18. 0 [7 I2 O7 b% |- O
  19. QUEST.setInitialState(CREATED)
    - n6 z: R6 o8 m; x
  20. QUEST.addStartNpc(7056)
    7 z5 w, p, [  p
  21. STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код
Теперь рассмотрим, как это работает.
; W) {5 J: y$ {! c8 KИгрок подходит к начальному NCP (в данном случае 7056), нажимает на «Quest». Квест будет создан и состояние квеста перейдет к CREATED и игроку будет показана страничка Start.htm с описанием квеста. Тогда метод onEvent, поле открытия странички Start.htm переведет состояние квеста в STARTED и игроку будет показана страничка Started.htm, где будет опсание того, как найти keltirs и .т.д.: x9 L- K" Q+ U$ D5 Y; I

& v3 s( {6 M) F  k
# A4 F! m4 n5 r+ \, l* [
При состоянии STARTED будет зарегистрирован дроп «fangs» при убийстве keltirs. Игрок может вернуться к стартовому NCP и спросить о квесте – метод onEvent будет вызван снова. Если у игрока не хватает необходимого количества предметов, то метод check() не переведет квест в следующее состояние и Started.htm будет показана снова. Но если игрок собрал необходимее количество предметов (в данном случае 4 клыка), то метод check() вызовет метод completed() который переведет квест в новое состояние COMPLETED, заберет все клыки, даст карту мира, т.к. это награда за квест, покажет Completed.htm и завершит квест.
) S& v9 k  M' u0 \# G" u- v7 v& Y9 o& r* n! Q0 e

+ p9 v4 h' D3 K1 VТеперь давайте сделаем наш квест более похожим на то, что он должен из себя представлять.9 M9 b7 c/ O' e
Прежде всего у нас есть 3 метода для объявления их в Яве – onTalk, onKill и onEvent. Если методы onTalk и onKill не объявлены, то за них все будет делать метод onEvent, т.е. определять квестовых монстров и вызывать диалоги NCP. Есть примечание, методы onTalk и onKill будут вызывать только диалоги с NCP в зависимости от текущего состояния квеста. Метод onKill будет вызываться только тогда, когда мы убиваем квестового монстра.
4 p, ~6 u0 K6 q$ D6 {0 |+ f
9 w. ], J, g/ I$ V2 Z  l
  Q3 j! _; ^' A; S! \4 y0 E- P9 P
Давайте рассмотрим как вызывается метод onKill при убийстве keltir в состоянии квеста STARTED:! y: ]4 o1 i) v$ D" o* y
  1. STARTED.addKillId(KELTIR_NPC_ID)
Скопировать код
и метод onKill в классе Quest:
6 k2 T9 `; U8 K6 P
$ K3 l  n- h# a- W  a0 Z
  1. class Quest (JQuest):
    / b# N" k. a' m0 h% i9 q! H7 x
  2.   ...
    8 G* V) V! u5 M. }1 V
  3.   def onKill (self,npcId,st):2 C$ }  a$ k7 m1 j
  4. if npcId == KELTIR_NPC_ID:
    2 a. d3 I0 }+ ~
  5.    n = getCount(st)8 h( U4 v1 C3 ?' R! m1 {' Z
  6.    if   n == 0:
    / P8 V6 h) w0 B- Z* f/ ]
  7.        return "Chat0.htm"
    ; g0 M6 T" }) s: s
  8.    elif n == 1:
    # s/ p: w' A: H; {
  9.        return "Chat1.htm"
    / @; n- o$ f3 C# ]$ A* U& D9 Z! i
  10.    elif n >= 4:
    " t/ Z  X% g7 A+ V2 L; ^6 r# o) W
  11.        return "Chat4.htm"
    : h( X% O# T  d
  12.    return "Collected "+str(n)+" of 4 fangs"
    * ~0 ?: g' I: O2 _
  13. return
Скопировать код
Метод onKill (а так же метод onTalk) имеет следующие параметры:
& \; p9 l) w9 C
2 J8 u, F$ e+ t$ M1 r
2 d9 o, h. J$ c5 l
• self – квест
1 C( ~- h9 N7 F- H• npcId – ID NCP, которого мы должны убивать (если это метод onTalk, то ID того NCP, с которым мы должны поговорить).
! h/ v! e9 ?5 d( B• st – текущее состояние игрока.
8 R/ l0 p" S1 A  Q- P1 Z
6 G: E' |9 t; j* s5 b" E; ~/ t1 r/ D
7 B7 j* w2 s0 C* A0 d2 B! C
В этом методе мы проверяем и отмечаем, является ли убитый NCP keltir’ом. В основном эта проверка не нужна, т.к. у нас только KELTIR_NPC_ID.! u8 w( q4 ?! W6 e2 }" D4 v: d8 h# o

& f! \3 v; P- g2 M9 x! R

$ g2 j! t1 j0 k9 M" s5 E0 v3 ]Затем проверяем количество предметов (в данном случае количество клыков), и если их вообще нет, то возвращаем строку "Chat0.htm", если только один предмет, то возвращаем строку "Chat1.htm", если же предметов 4 или больше, то "Chat4.htm". Если строка возвращена из методов onEvent, onKill или onTalk, то сервер покажет соответствующие htm. В Chat0.htm может иметь следующий текст: «Вы не имеете ни одного клыка, возвращайтесь позже, когда соберете 4 штуки и бла, бла, бла…», в Chat1.htm может быть следующий текст: «У Вас всего 1 клык, по этому соберите еще…». В Chat4.htm – «Вы собрали необходимое количество предметов, возвращайтесь к вашему тренеру, что бы завершить квест…»; O1 b9 F, m6 j  O9 x

3 a5 f: q- M6 Y5 ~" d: A( ]

7 m' K$ m/ J9 y/ b  p8 dПримечание: если в строка return начинается с "<html>", то будет показана страничка html с текстом, который стоит далее. Так вместо:7 ^4 J  x9 W7 A- d
return "Chat4.htm"
$ z; T0 F: K" K- V% U# w3 W0 ^" L

* V# s: X  `# M1 O" @можно поставить:: U! w& g9 R  }; r8 S$ A' g
  1. return "<html><body>Return to your trainer to complete the quest</body></html>"
Скопировать код
Так же если строка заканчивается без .htm или в начале нет <html>, то текст будет выведен, как системное сообщение в окне чата. В нашем случае мы сделаем так, что бы при каждом убийстве keltik выводилось системное сообщение: «Собрано N из 4-х клыков».: B$ W, d+ Q1 ^6 g; w
' n" @. g* N  s2 W: F4 c5 ?

6 P* y/ l8 S1 j" _6 A7 e, {Наш код для onKill имеет один недостаток. Он будет постоянно показывать Chat0.htm, Chat1.htm и Chat4.htm, нам же необходимо, что бы Chat0.htm и Chat1.htm показывались только один раз. Как нам это сделать? С помощью переменных.! V( O# G% h) H+ X1 _

: `) s- Y; E1 k& P8 O

$ O" b9 {9 l7 oВ каждом квесте строки могут храниться с помощью переменных. Эти переменные сохраняются в Вашей БД. В каждом методе мы можем назначить, прочитать и удалить переменные. Давайте изменим метод onKill, так что бы каждый диалог вызывался только один раз.- G) b4 U6 A, \. \& m
  1. def onKill (self,npcId,st):
    ! a0 w, _5 F; h7 B
  2. if npcId == KELTIR_NPC_ID:4 u$ k0 p2 W8 {' l* |# R, v
  3. n = getCount(st)( I- q# {, a( h8 q
  4. if n == 0:
    $ d  s) T, j9 K1 s; J) w2 j
  5. if st.get('chat0') == None :
      d( S! Q: `) _* ]3 {
  6. st.set("chat0", "true")
    ) x/ Z; B6 N8 r6 Z3 I
  7. return "Chat0.htm"1 b1 y3 v! c; V% o" N, t. j
  8. elif n == 1:
    1 y+ V2 P( e) g3 }
  9. if st.get('chat1') == None :2 i+ A, `% z2 \. U8 i/ c, m% z$ \
  10. st.set("chat1", "true")* i, m; J" u: ]8 n+ K
  11. return "Chat1.htm"( m6 `; z  x+ |& t
  12. elif n >= 4:) ]. q% E+ M& K( n3 {6 \0 u
  13. return "Chat4.htm"
    ( C; }' c' [2 _) N: c" y
  14. return "Collected "+str(n)+" of 4 fangs"5 e3 u$ ]! L( m1 x+ R( o$ T
  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.
. ]0 N/ z" W% v) Y
9 V, q* C- T' ^% m+ z6 e- r

; P, x7 @8 A0 ]Вот конечный рабочий вариант квеста:
; g$ @3 x0 o0 m8 b
  1. import sys
    3 a- b. R6 h3 B9 ~
  2. from net.sf.l2j.gameserver.model.quest import State0 x' c' \" x. c) Z
  3. from net.sf.l2j.gameserver.model.quest import QuestState$ r* b4 ?' U2 b7 v& ?! T
  4. from net.sf.l2j.gameserver.model.quest.jython import QuestJython as JQuest1 Q# B% A  v7 h0 O

  5. ) [9 z0 n5 I2 l" ~- O
  6. KELTIR_NPC_ID = 12082* n% E0 ~0 D- ]: T- z5 X
  7. FANGS_ITEM_ID = 1859+ N9 g7 w$ M( x) A0 ~
  8. DROP_RATE    = 5000009 m9 Z1 c# X4 Q* E" t

  9. ) i/ E9 l- U6 `( Z" v# o6 o1 \
  10. WORLD_MAP_ITEM_ID = 1665! R; ?/ o- f4 c! o$ A9 Q

  11. - }8 s7 a& o/ {
  12. def getCount(st) :
      U% V8 z7 d1 w& _2 q' X
  13. return st.getQuestItemsCount(FANGS_ITEM_ID)
    0 K  k: `9 y5 f% K
  14. 8 u, {+ R' _& b9 n
  15. def completed(st) :
    ) D$ T! O* x) D+ V; U9 K
  16. st.setState(COMPLETED)
    0 J, c4 D1 }' x* H# F! X) W
  17. st.clearQuestDrops()
    2 Z7 k; C  c) _, j
  18. st.takeItems(FANGS_ITEM_ID,-1)- @5 I7 H( W8 d3 o$ C
  19. st.giveItems(WORLD_MAP_ITEM_ID,1)
    ( s6 v0 v2 m" P1 [
  20. st.exitQuest(False)
    3 P% `# G7 l3 y
  21. return
    3 t6 T% I: Q6 C& n
  22. 0 I8 F5 _' x5 k( P* |2 x  i6 ?
  23. def check(st) :
    : P% d8 b& D: o9 T% H0 u  t
  24. if getCount(st) >= 4 :5 {. [* T& C. G9 n; e' }1 Y
  25. completed(st)& B7 t3 Y- G% \0 N& R
  26. return
    6 o2 d. u6 w8 Y: M

  27. * o$ ]  V  h- C4 @
  28. class Quest (JQuest):9 q: j5 n  K! W9 g4 m$ {' c
  29. 6 j3 j6 r0 k4 _
  30. def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)4 I3 d5 V: W( s! Y0 D9 o
  31. $ x5 o: K- a* H; k0 A5 {0 {
  32. def onEvent (self,event,st):
    * ]4 o, [, j" K  T! R3 F% U
  33. id = st.getState()
    * G8 u* }1 Z% k% C5 Z
  34. if id == CREATED : st.setState(STARTED)% A% p9 h) D( T( F- K8 v8 M9 h
  35. elif id == COMPLETED: pass, S- N& T5 q6 G0 T* d
  36. elif id == STARTED : check(st)" b0 T+ U" V( e/ w) U
  37. return
    2 _: L$ {/ _% l
  38. 0 e( l+ {7 ^- ~! H; K) K. R; V
  39. def onKill (self,npcId,st):& f; r1 ^1 [2 \3 i1 v2 F7 P0 i
  40. if npcId == KELTIR_NPC_ID:
    * n8 u7 Z$ S! _/ _, C, l5 G/ A' A( N
  41. n = getCount(st)
    % W4 c# l2 p. O& o9 \- c. ~$ G
  42. if n == 0:
    / o9 J8 ~+ P3 ~0 ~: e1 _( W" L
  43. if st.get('chat0') == None :) m  h+ J) x& A6 i
  44. st.set("chat0", "true")- c/ `/ O+ S6 L
  45. return "Chat0.htm"" D! Y& ]* v9 B1 L1 |
  46. elif n == 1:
    6 \4 f" T: E" `7 [7 p9 F+ [
  47. if st.get('chat1') == None :3 R" O# a" U' @, D5 r2 B
  48. st.set("chat1", "true")
    0 G# h! R7 \5 A( z/ T  P
  49. return "Chat1.htm"6 {* ?& M, s3 n5 D
  50. elif n >= 4:9 i5 k8 }9 [* b+ ?3 o
  51. return "Chat4.htm"# c. M  {1 l0 b# X" U1 d
  52. return "Collect "+str(n)+" of 4 fangs"  R. E0 T8 ]7 j0 r4 B2 p; T4 L
  53. return
    ! X; M3 q, ?6 F6 t7 E+ S$ O

  54. 1 b, D1 g- m* j; a/ `
  55. QUEST    = Quest(201, "Tutorial", "Tutorial quest")
    * J5 L3 E. p& o5 }
  56. CREATED = State('Start',    QUEST)
    + V8 o) x: Z5 g2 j9 r
  57. STARTED = State('Started', QUEST)! G# m! h# J6 c' N
  58. COMPLETED = State('Completed', QUEST)
    + ]8 F0 t, l1 A8 N
  59. ; l7 \4 L; H, s' _# A
  60. QUEST.setInitialState(CREATED)
    0 x3 C# t1 Z- e
  61. QUEST.addStartNpc(7056)6 `1 C8 Q: a% X" v8 |( n
  62. QUEST.addStartNpc(7012)1 g$ ~- q2 Y' L0 `5 U
  63. QUEST.addStartNpc(7009)  ^# U1 W4 J+ K: {5 L  Q
  64. QUEST.addStartNpc(7011)2 G# }/ @+ {) w" a) A7 R# a  v0 c0 E1 w
  65. , V; Z& M6 v# P
  66. STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
      q8 m5 [% d0 N
  67. STARTED.addKillId(KELTIR_NPC_ID)
    8 }# ^  b6 f: f; O/ u" R" |) r
  68. STARTED.addTalkId(7056)
    / V0 @$ }5 r  T1 S: K5 N- ~0 B+ x
  69. STARTED.addTalkI d(7012). `% c1 q& R7 c4 p; k  ~; R& c2 G$ J
  70. STARTED.addTalkId(7009)
    8 v' F2 Z4 Z' ^" ]- d- z2 @
  71. STARTED.addTalkId(7011)
Скопировать код

9 D, P& r+ y# N2 u: {# r4 ^$ q+ ~% E4 x, V2 w( A5 J
Чтобы ответить, вам надо авторизироваться в системе Вход | Зарегистрироваться

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

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

638638758

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

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

admin@artace.ru Онлайн

QR-код

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