Top.Mail.Ru

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

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

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

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

x
Хроники        Interlude/ S' v. `* Y+ g1 Q9 R) a
Сборка        L2j
* L9 B/ r9 k0 s/ }# z% ]7 q4 EОбратите внимание: в файле htm стартового NCP обязательно должна быть ссылка на квест:
! ~2 m. a, X+ A1 i
  1. STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код
Для этого квеста больше ничего не надо. Все необходимое для корректной работы квеста уже добавили. Вот полный текст квеста:& ?' H) Y) z+ s" y! M! g0 i8 D

- {  [4 P- u! r  L4 t. L" \
  1. if getCount(st) >= 4 :
    ! \* p1 A2 u& B, b
  2. completed(st)
    ) x5 T0 N! E% E4 z6 M/ K
  3.   return
    0 r  ]$ ?& e( ]4 |; l
  4. 7 S% H! }. L0 E* o! C% h
  5. class Quest (JQuest):
    2 k4 h) s  Z1 {3 }3 z" }% h5 R% M8 C
  6.   def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)0 R/ h1 D  m! N* B
  7.   def onEvent (self,event,st):( X) M1 X/ m/ v2 V. b
  8. id = st.getState()7 O7 ^+ B9 X( J$ Z, U
  9. if   id == CREATED  : st.setState(STARTED)
    ' w/ S( i9 e2 ]  k8 H' B
  10. elif id == COMPLETED: pass% j+ e+ S+ r8 R# Z1 T: y3 L2 I
  11. elif id == STARTED  : check(st)' G0 ?, {1 m  }; E8 i* O% R- \
  12. return9 M$ w1 [$ x! T5 w
  13. : m  T: |  V3 ^, @) z4 e
  14. QUEST     = Quest(201,"Tutorial", "Tutorial quest")
    % j/ T! z, Z* Q- l
  15. CREATED   = State('Start',     QUEST)
    " O' P2 ^7 C+ v( _  m' v
  16. STARTED   = State('Started',   QUEST)
    ! R+ G% G3 I) u1 o5 h0 d1 ^
  17. COMPLETED = State('Completed', QUEST)
    % |: O( V1 y: L

  18.   a1 g* b) ?5 W1 K  I6 Y2 c6 H
  19. QUEST.setInitialState(CREATED)
    3 a+ ~3 n! D0 f) J  M* A
  20. QUEST.addStartNpc(7056)
      b: C# @! X; [9 t6 W! V
  21. STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код
Теперь рассмотрим, как это работает.* }: t% j* P. u' e/ k  y* T* k
Игрок подходит к начальному NCP (в данном случае 7056), нажимает на «Quest». Квест будет создан и состояние квеста перейдет к CREATED и игроку будет показана страничка Start.htm с описанием квеста. Тогда метод onEvent, поле открытия странички Start.htm переведет состояние квеста в STARTED и игроку будет показана страничка Started.htm, где будет опсание того, как найти keltirs и .т.д.7 B$ y( w" |" b
( q' f$ ~* t( F
3 ]+ T; ~8 ~3 `( g
При состоянии STARTED будет зарегистрирован дроп «fangs» при убийстве keltirs. Игрок может вернуться к стартовому NCP и спросить о квесте – метод onEvent будет вызван снова. Если у игрока не хватает необходимого количества предметов, то метод check() не переведет квест в следующее состояние и Started.htm будет показана снова. Но если игрок собрал необходимее количество предметов (в данном случае 4 клыка), то метод check() вызовет метод completed() который переведет квест в новое состояние COMPLETED, заберет все клыки, даст карту мира, т.к. это награда за квест, покажет Completed.htm и завершит квест.' W! B; a1 m6 j

# x) L+ u# f' h) `

3 ^0 [$ P$ V9 C6 W% D) }7 ^Теперь давайте сделаем наш квест более похожим на то, что он должен из себя представлять.2 u6 _" w& M$ d1 O8 Q  q
Прежде всего у нас есть 3 метода для объявления их в Яве – onTalk, onKill и onEvent. Если методы onTalk и onKill не объявлены, то за них все будет делать метод onEvent, т.е. определять квестовых монстров и вызывать диалоги NCP. Есть примечание, методы onTalk и onKill будут вызывать только диалоги с NCP в зависимости от текущего состояния квеста. Метод onKill будет вызываться только тогда, когда мы убиваем квестового монстра.( B' o* Q7 I& E! Y% c' O
; _1 }  L0 T3 {5 g- N- E9 Y3 b

) n' H. h' N) V  q9 fДавайте рассмотрим как вызывается метод onKill при убийстве keltir в состоянии квеста STARTED:: F4 w% d4 }: j% B& T! Y' V. b
  1. STARTED.addKillId(KELTIR_NPC_ID)
Скопировать код
и метод onKill в классе Quest:' c( Q3 v% Z2 b* l

. E0 e+ h6 _+ O. ], O
  1. class Quest (JQuest):
    / j  Y( i* |# c
  2.   ...
    . R7 m/ y8 B- X5 S% ~
  3.   def onKill (self,npcId,st):% g% Q! _  A4 [6 d" V; T1 b4 V, d
  4. if npcId == KELTIR_NPC_ID:
    ; C& y, i# {/ H4 a! Q5 t5 |
  5.    n = getCount(st)
    , f( f% r, i: }" l
  6.    if   n == 0:, V: ]; n; H  @7 f- `
  7.        return "Chat0.htm"' N; X" v6 T7 X7 h. ~) \
  8.    elif n == 1:
    5 a8 S4 \9 \! ~: F8 Q# U; T
  9.        return "Chat1.htm"! a# e! a( |# |' |0 w* H6 c& T
  10.    elif n >= 4:1 S2 _( P$ u& l% |. F6 L
  11.        return "Chat4.htm"
    % A* A- w, h$ U: X: }3 c# b$ }7 x
  12.    return "Collected "+str(n)+" of 4 fangs"$ i$ D: x( j: w2 @2 @/ T
  13. return
Скопировать код
Метод onKill (а так же метод onTalk) имеет следующие параметры:; R, j, O" X0 X" K7 N7 T

9 o: `) t/ {- b0 M/ ^4 U# n

% {, r) D, o& J( K2 e" x• self – квест
3 S4 d  f  w* o& ~$ x" a, D• npcId – ID NCP, которого мы должны убивать (если это метод onTalk, то ID того NCP, с которым мы должны поговорить).: H  C/ b; J. u& e
• st – текущее состояние игрока.# A% H. e9 T9 ?/ [$ ?
+ M3 s1 U' i  u) O9 R& z; o

. M3 q, K, s$ ?% ~, m4 c! nВ этом методе мы проверяем и отмечаем, является ли убитый NCP keltir’ом. В основном эта проверка не нужна, т.к. у нас только KELTIR_NPC_ID.( g1 t# S% v2 H! ?$ k+ W6 M
3 |% A3 `3 \7 ?- ]0 B

$ [5 R+ ]+ }4 v* D$ T6 SЗатем проверяем количество предметов (в данном случае количество клыков), и если их вообще нет, то возвращаем строку "Chat0.htm", если только один предмет, то возвращаем строку "Chat1.htm", если же предметов 4 или больше, то "Chat4.htm". Если строка возвращена из методов onEvent, onKill или onTalk, то сервер покажет соответствующие htm. В Chat0.htm может иметь следующий текст: «Вы не имеете ни одного клыка, возвращайтесь позже, когда соберете 4 штуки и бла, бла, бла…», в Chat1.htm может быть следующий текст: «У Вас всего 1 клык, по этому соберите еще…». В Chat4.htm – «Вы собрали необходимое количество предметов, возвращайтесь к вашему тренеру, что бы завершить квест…»9 o, y. v- X' F+ X0 _

: L, q/ u. c- T) B' q

9 b3 A2 Q. B) I  y' H7 q$ o  HПримечание: если в строка return начинается с "<html>", то будет показана страничка html с текстом, который стоит далее. Так вместо:
7 L; Z9 ?& ?) K# k$ a) ?return "Chat4.htm". C8 ?; r0 v4 ~- E( g) h+ M
) W: Z* H- u: ?8 l
- p) k2 ?8 P! a- B. c. u) O, w
можно поставить:! V2 D0 Y6 N5 k4 G: U
  1. return "<html><body>Return to your trainer to complete the quest</body></html>"
Скопировать код
Так же если строка заканчивается без .htm или в начале нет <html>, то текст будет выведен, как системное сообщение в окне чата. В нашем случае мы сделаем так, что бы при каждом убийстве keltik выводилось системное сообщение: «Собрано N из 4-х клыков»." g6 q, E' {' b* Y7 o

) ?% k/ V1 _1 H; T

5 e7 _2 @3 ]) U' ^/ W, _Наш код для onKill имеет один недостаток. Он будет постоянно показывать Chat0.htm, Chat1.htm и Chat4.htm, нам же необходимо, что бы Chat0.htm и Chat1.htm показывались только один раз. Как нам это сделать? С помощью переменных.+ s& l1 J$ @) R  k

3 h9 ?: X, q  v, L3 l) a
" H% g3 @- S6 U! s4 p3 T
В каждом квесте строки могут храниться с помощью переменных. Эти переменные сохраняются в Вашей БД. В каждом методе мы можем назначить, прочитать и удалить переменные. Давайте изменим метод onKill, так что бы каждый диалог вызывался только один раз.! ?& {: B9 i4 A) w& b$ f
  1. def onKill (self,npcId,st):
    ! g; y- n3 c4 k
  2. if npcId == KELTIR_NPC_ID:
    ' `) I: W& p' s" W8 c, U
  3. n = getCount(st)* i! @# B, L, S: _8 S6 J
  4. if n == 0:% F3 j  z+ g1 v( d/ t
  5. if st.get('chat0') == None :
    6 x4 `3 N' a2 H
  6. st.set("chat0", "true")
    1 H2 W+ C3 h+ F* C" O0 x
  7. return "Chat0.htm"' L) {8 P: D1 Z4 F
  8. elif n == 1:
    * j* W- J& r% Z! p" `1 J8 ~7 @4 {
  9. if st.get('chat1') == None :; {5 q& s3 Y, Y1 E  c+ g* t
  10. st.set("chat1", "true")
    ( |' T# f" M; t" ^$ m( o
  11. return "Chat1.htm"! N" O& C  H; e- o4 J0 R
  12. elif n >= 4:
    7 X/ p- L6 p* c# J$ b2 T. w
  13. return "Chat4.htm"
    2 L6 @4 N: t$ v! L& H
  14. return "Collected "+str(n)+" of 4 fangs"
    ( n, q+ |9 U) c
  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.# w0 b. Q' V% h8 w/ v$ r/ ~) G( h

% Y6 t1 Z8 Z7 k* B; K
9 Q  W  d: K/ p1 y# q
Вот конечный рабочий вариант квеста:% k, j8 O$ o/ g4 g" T0 p
  1. import sys8 {- a% Q! B( n) j4 O
  2. from net.sf.l2j.gameserver.model.quest import State
    & V' K3 Z! l% _
  3. from net.sf.l2j.gameserver.model.quest import QuestState( {7 ]2 @- U/ G1 W- d4 Y
  4. from net.sf.l2j.gameserver.model.quest.jython import QuestJython as JQuest% b5 J' t, i& f! G) D
  5. - o, k0 B: ], y" Y! V
  6. KELTIR_NPC_ID = 12082
    9 ~1 I8 _/ N% S  Q/ E
  7. FANGS_ITEM_ID = 1859
    , ]6 p* B, a$ n+ c2 O
  8. DROP_RATE    = 500000
    6 Q/ d9 n+ i$ y% \, O9 M
  9.   [) K' L% O+ F$ p6 B
  10. WORLD_MAP_ITEM_ID = 16653 m& q& @  D+ R& }& d. y
  11. ; g9 t1 }9 |$ i8 l7 V# t9 p2 e
  12. def getCount(st) :
    : H! y& P8 }/ M  L. w9 T9 |
  13. return st.getQuestItemsCount(FANGS_ITEM_ID)" [! L! h! k  Y6 q0 p0 z, j
  14. ; Z5 ^0 S, n$ {4 K
  15. def completed(st) :# T0 u7 |$ c& [  ^$ T: Q
  16. st.setState(COMPLETED)
    ) Y0 W/ q% [% X) f5 B, O: t& [/ `
  17. st.clearQuestDrops()
    $ t' m6 m5 Q0 {" U7 D/ ?
  18. st.takeItems(FANGS_ITEM_ID,-1)" S) z5 b2 S. ]8 ]$ c$ j6 K+ Y
  19. st.giveItems(WORLD_MAP_ITEM_ID,1)) Z& W( ~$ u' b: ^/ H) E$ M! B3 a8 {3 h
  20. st.exitQuest(False)
    $ v9 d# v. c. R9 k* {! C% f
  21. return" n1 U8 ~; H. c* A* K, Z9 t$ N  f2 o
  22. & H  I4 {( S8 q% W9 c+ |- t
  23. def check(st) :
    ( X6 S( z: D& U; D
  24. if getCount(st) >= 4 :; \3 P; Q9 s0 b" M$ q
  25. completed(st)- e% B# }6 q4 c$ v" h
  26. return% l: U; ]1 R( X( v$ d

  27. * W  k, h; z2 Q' G( z
  28. class Quest (JQuest):: n1 {3 ]% u% Q1 [9 O

  29. 8 z2 b% x: B& G8 ^% K1 P
  30. def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)* W5 Y- i% e; L4 B  {. p: S4 v

  31. , K  v1 ^3 E$ E; k
  32. def onEvent (self,event,st):! ]7 B0 e# g$ D) f. c
  33. id = st.getState(), u2 c) m; r1 y5 O  b# O
  34. if id == CREATED : st.setState(STARTED)
    + G- n  g- X3 [) [0 L- Y
  35. elif id == COMPLETED: pass: x& n. ~, x0 n- G
  36. elif id == STARTED : check(st)! b1 `9 p4 c; h$ S
  37. return- C  ~# g" L# Z" k( f
  38. . `( T' y# ~4 m( E1 K7 q
  39. def onKill (self,npcId,st):
    9 e6 X8 y' J" _0 b9 j
  40. if npcId == KELTIR_NPC_ID:3 p9 i# M, D  {; `
  41. n = getCount(st)
    + O5 ?* D6 g! v/ D( t
  42. if n == 0:& f. \* u& ^' j( h
  43. if st.get('chat0') == None :
    5 M9 N) b* L' U- _
  44. st.set("chat0", "true"). d1 I: B( \7 t* E% r7 e# J
  45. return "Chat0.htm", x  r. Z! Z$ b
  46. elif n == 1:4 w0 Z# v. [1 U( t2 Q
  47. if st.get('chat1') == None :- N( ]6 I/ B) H. v# {+ [! v! D
  48. st.set("chat1", "true"): N  a, g% ]! }
  49. return "Chat1.htm"
    1 v! u7 L6 y0 j
  50. elif n >= 4:
    & u9 ~4 Q& c$ f* P( D
  51. return "Chat4.htm"
    , Q" k4 C. X! F
  52. return "Collect "+str(n)+" of 4 fangs"; b0 @; O0 z$ @1 M/ c* [0 ^3 L/ ]5 n! k0 ^
  53. return
    / e- {/ E7 Z' f: ]
  54. - r$ {! O: T8 {2 j! ^
  55. QUEST    = Quest(201, "Tutorial", "Tutorial quest"). v2 h6 t' Y0 V: M- l6 k6 |
  56. CREATED = State('Start',    QUEST)* K2 \2 w9 u4 G5 j
  57. STARTED = State('Started', QUEST)/ F; X6 G. A$ J1 v3 R' R5 {
  58. COMPLETED = State('Completed', QUEST)
    3 b3 X# l  s5 @2 G
  59. ' v/ I1 J* [9 s2 W; B# I* U
  60. QUEST.setInitialState(CREATED)" H' M6 B! G: N8 P7 A" F
  61. QUEST.addStartNpc(7056)" g- Y( O/ ]* R; y6 \
  62. QUEST.addStartNpc(7012)
    ; X* [0 t" _0 `! Q' b; X6 N
  63. QUEST.addStartNpc(7009)
    , q7 c. F0 v: Y0 {
  64. QUEST.addStartNpc(7011)
    ! }8 x1 W( ~8 _- Z% l* b* y+ \

  65. 4 G+ w4 K3 {& ^; b! H
  66. STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)5 k- F% J/ c0 U2 {
  67. STARTED.addKillId(KELTIR_NPC_ID)) `( r% O! ]( e5 r; q1 x. |- {) F/ t
  68. STARTED.addTalkId(7056)
    + D) f, [& p/ h5 r0 Y+ _
  69. STARTED.addTalkI d(7012)
    % u! d4 L* w. V( H
  70. STARTED.addTalkId(7009)+ m4 Z/ b, U5 t' `  v& E0 m2 {
  71. STARTED.addTalkId(7011)
Скопировать код
6 U3 n1 z# w5 j0 D

2 P# u2 C2 a9 G% W( x
Чтобы ответить, вам надо авторизироваться в системе Вход | Зарегистрироваться

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

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

638638758

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

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

admin@artace.ru Онлайн

QR-код

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