Top.Mail.Ru

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

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

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

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

x
Хроники        Interlude$ O; f* G; t: U* o
Сборка        L2j
; t9 i# p: A* w0 Y5 jОбратите внимание: в файле htm стартового NCP обязательно должна быть ссылка на квест:2 y. ?3 ?; H+ H) P; q6 P0 |
  1. STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код
Для этого квеста больше ничего не надо. Все необходимое для корректной работы квеста уже добавили. Вот полный текст квеста:
+ o9 k$ R3 ]% l* }/ W. X+ n
% C: C7 z- q( b( _$ {$ t+ E" L
  1. if getCount(st) >= 4 :
    3 R  F. K3 u2 L9 J. i
  2. completed(st)4 h' Q6 m4 Q, k
  3.   return
    5 |5 ]2 c$ l" O+ ^# o! U

  4. 9 D% j. m; K+ G! N  z
  5. class Quest (JQuest):
    4 T6 G1 [  g/ e$ v' J" g6 C1 O
  6.   def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)% w6 T4 D" s! N! I
  7.   def onEvent (self,event,st):! v/ m) V/ v% M9 K! D$ D7 {
  8. id = st.getState()
    / ^2 x* _- O  K: ?# D2 q
  9. if   id == CREATED  : st.setState(STARTED)
    ' h* s0 a, u" W
  10. elif id == COMPLETED: pass
    5 J5 c- @3 _& P& G3 J* L. {
  11. elif id == STARTED  : check(st)
    9 [) L  W0 Z" t, p4 P! @# ]6 G6 F
  12. return$ j4 d0 h/ K, z8 M8 b- D3 R
  13. 7 O1 ?) u* x& V. {% ^- c# F5 W( i
  14. QUEST     = Quest(201,"Tutorial", "Tutorial quest")
    4 A0 R- C* u' q2 x% ~: J
  15. CREATED   = State('Start',     QUEST)
    , |" I, e: K5 R* e3 `9 ?3 m
  16. STARTED   = State('Started',   QUEST)) h) g" z3 y" C: G) W; l+ y
  17. COMPLETED = State('Completed', QUEST)
      m! A0 p5 V! l, c, c! A& `
  18. ' A( g. _; i2 b  c; k8 ^, Y
  19. QUEST.setInitialState(CREATED)
    1 E' q0 ]7 r, a! ]2 q
  20. QUEST.addStartNpc(7056)% H6 ^) T& ]) k5 `
  21. STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код
Теперь рассмотрим, как это работает.; v9 R: h) H' _& V5 l; U
Игрок подходит к начальному NCP (в данном случае 7056), нажимает на «Quest». Квест будет создан и состояние квеста перейдет к CREATED и игроку будет показана страничка Start.htm с описанием квеста. Тогда метод onEvent, поле открытия странички Start.htm переведет состояние квеста в STARTED и игроку будет показана страничка Started.htm, где будет опсание того, как найти keltirs и .т.д.
/ J7 H5 b! V7 R( l8 m' b2 o/ K( ]3 N8 z
: U1 d+ ?: U* {9 h6 F7 ]: f
При состоянии STARTED будет зарегистрирован дроп «fangs» при убийстве keltirs. Игрок может вернуться к стартовому NCP и спросить о квесте – метод onEvent будет вызван снова. Если у игрока не хватает необходимого количества предметов, то метод check() не переведет квест в следующее состояние и Started.htm будет показана снова. Но если игрок собрал необходимее количество предметов (в данном случае 4 клыка), то метод check() вызовет метод completed() который переведет квест в новое состояние COMPLETED, заберет все клыки, даст карту мира, т.к. это награда за квест, покажет Completed.htm и завершит квест.7 I8 |0 |! ]' O8 w$ C& ~) O) s7 a" a

! J* K1 m0 a1 r( L; I. J# d. x0 c
" s% F6 g  _8 L) S7 o# m1 H  A
Теперь давайте сделаем наш квест более похожим на то, что он должен из себя представлять.% D* q. {$ J, N* d2 s6 v. i2 W
Прежде всего у нас есть 3 метода для объявления их в Яве – onTalk, onKill и onEvent. Если методы onTalk и onKill не объявлены, то за них все будет делать метод onEvent, т.е. определять квестовых монстров и вызывать диалоги NCP. Есть примечание, методы onTalk и onKill будут вызывать только диалоги с NCP в зависимости от текущего состояния квеста. Метод onKill будет вызываться только тогда, когда мы убиваем квестового монстра.% ]- ]. N) X; H, D6 F8 o. Q

1 [$ V& M8 d% J( N8 `3 f
* u: H1 W3 L: R# r
Давайте рассмотрим как вызывается метод onKill при убийстве keltir в состоянии квеста STARTED:
/ m- q  B* S. E& R
  1. STARTED.addKillId(KELTIR_NPC_ID)
Скопировать код
и метод onKill в классе Quest:
, C: o8 @1 B9 g) H: g6 h! V' M9 s$ D, ^% O* a7 A& C# E9 O
  1. class Quest (JQuest):* ]! p' T$ W  r3 d6 u
  2.   ...
    : e; j& ?6 D0 K2 ]1 ]/ W3 z4 e
  3.   def onKill (self,npcId,st):- ]7 ?0 \3 |- C- V3 ^
  4. if npcId == KELTIR_NPC_ID:6 {. z1 }  _5 R: k  @" j- |" I
  5.    n = getCount(st)$ j' r$ f) x1 }& B8 Q) s/ Z
  6.    if   n == 0:5 A0 x* ^6 L" }, U; o$ |6 b
  7.        return "Chat0.htm"' K$ P6 v9 j' z  ~
  8.    elif n == 1:
    ) ?9 i0 l' Z2 f3 V5 \' E
  9.        return "Chat1.htm"9 c5 X7 h, D6 Y$ _1 {" s
  10.    elif n >= 4:
    0 C) [% i4 Q+ \) ~; c
  11.        return "Chat4.htm"
    + g! R: d1 c, [1 q; v- Z' y9 E' L3 v
  12.    return "Collected "+str(n)+" of 4 fangs"$ t: Z& S8 Z! u9 H7 H& w1 l+ w
  13. return
Скопировать код
Метод onKill (а так же метод onTalk) имеет следующие параметры:( @$ C" O9 z% E% V3 ?6 Z# ~

0 j+ x. O. l, r4 R( \: |# K
' B, E9 d, U! ~% x$ I4 E4 k3 v
• self – квест7 R+ V2 Z. R& Q* |7 H. c
• npcId – ID NCP, которого мы должны убивать (если это метод onTalk, то ID того NCP, с которым мы должны поговорить).  J( Y+ a1 z" f3 f- ]  S
• st – текущее состояние игрока.
2 t' P& _) `8 [: O# ^; ~6 u) Y1 z5 ], f! W! ~
+ J+ E, a% d4 _" y* K
В этом методе мы проверяем и отмечаем, является ли убитый NCP keltir’ом. В основном эта проверка не нужна, т.к. у нас только KELTIR_NPC_ID.6 i( X# ?, H$ S$ D% z3 F1 U

7 V4 j: z  J, A

$ C6 R! d! e1 ~' {5 VЗатем проверяем количество предметов (в данном случае количество клыков), и если их вообще нет, то возвращаем строку "Chat0.htm", если только один предмет, то возвращаем строку "Chat1.htm", если же предметов 4 или больше, то "Chat4.htm". Если строка возвращена из методов onEvent, onKill или onTalk, то сервер покажет соответствующие htm. В Chat0.htm может иметь следующий текст: «Вы не имеете ни одного клыка, возвращайтесь позже, когда соберете 4 штуки и бла, бла, бла…», в Chat1.htm может быть следующий текст: «У Вас всего 1 клык, по этому соберите еще…». В Chat4.htm – «Вы собрали необходимое количество предметов, возвращайтесь к вашему тренеру, что бы завершить квест…»
( W/ Y4 U+ ?1 j& u+ P: x: u4 ?" l: o, ^1 V: b  w
  |# n! g- M- A  ?8 {
Примечание: если в строка return начинается с "<html>", то будет показана страничка html с текстом, который стоит далее. Так вместо:
6 E# T9 T  N  `4 Sreturn "Chat4.htm"
2 i2 P, m. }4 d  K/ S: ^0 @) E% y$ s
  W; o* ^' `' J$ N
можно поставить:+ Z+ q8 _$ s7 t
  1. return "<html><body>Return to your trainer to complete the quest</body></html>"
Скопировать код
Так же если строка заканчивается без .htm или в начале нет <html>, то текст будет выведен, как системное сообщение в окне чата. В нашем случае мы сделаем так, что бы при каждом убийстве keltik выводилось системное сообщение: «Собрано N из 4-х клыков».
* J2 U  B6 e8 P( k: S9 n5 e; J8 b4 c5 D* u- V
3 C" B) }" z8 N& s" O
Наш код для onKill имеет один недостаток. Он будет постоянно показывать Chat0.htm, Chat1.htm и Chat4.htm, нам же необходимо, что бы Chat0.htm и Chat1.htm показывались только один раз. Как нам это сделать? С помощью переменных.
  Z& i+ v2 B) C' j2 u# F
; E. X/ D7 \1 q

6 b7 D& y( f+ z( EВ каждом квесте строки могут храниться с помощью переменных. Эти переменные сохраняются в Вашей БД. В каждом методе мы можем назначить, прочитать и удалить переменные. Давайте изменим метод onKill, так что бы каждый диалог вызывался только один раз.& e  |, N: ]: D9 Z
  1. def onKill (self,npcId,st):
    5 _/ ]' D) ?/ s9 V' }9 J# g( R
  2. if npcId == KELTIR_NPC_ID:
    : R8 `. a; X# p7 ^1 D/ `
  3. n = getCount(st)7 v( q  b6 i3 W/ w  P* @  l$ e
  4. if n == 0:  k' t" {0 B; p5 A! }$ `
  5. if st.get('chat0') == None :
    * ^* y, m- h. B/ p7 o) w
  6. st.set("chat0", "true")  i. ^  b! ~' R, G6 p
  7. return "Chat0.htm"& c& [/ g/ q! m% S
  8. elif n == 1:8 t& n/ n' p) y6 U6 T3 H5 t$ B) U
  9. if st.get('chat1') == None :8 P5 p  _: l7 z# a2 n8 q4 ]3 I
  10. st.set("chat1", "true")3 b' C, U( }4 L* U* a
  11. return "Chat1.htm"
    + i2 |  e) Z! {  I+ Q
  12. elif n >= 4:, }. V2 C- ?( [8 t7 }9 J
  13. return "Chat4.htm"
    6 L+ L5 e" J7 J- q# \# n# B5 }5 D* A* m6 \( l
  14. return "Collected "+str(n)+" of 4 fangs": ?& Z9 B( [0 v" b3 j% B, a  R
  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.
& t1 N. U6 c9 u" o7 r7 _! |% q+ {& M" k+ m1 U/ Y

" h, o: X6 Y" PВот конечный рабочий вариант квеста:7 F: {0 P' |* n4 I$ Z& d$ i
  1. import sys# |* r# n2 m! S8 M2 H  N* v
  2. from net.sf.l2j.gameserver.model.quest import State
    3 Q; Q- B$ _- c; r1 @7 P( N
  3. from net.sf.l2j.gameserver.model.quest import QuestState
    * Q% k" l" a/ S6 W$ C
  4. from net.sf.l2j.gameserver.model.quest.jython import QuestJython as JQuest
    2 q# V5 m: r9 e9 m4 |# o: ]

  5. 2 Q# w) e2 C( t4 b3 m- `
  6. KELTIR_NPC_ID = 12082
    6 F8 u$ [  J, i. k  @( y
  7. FANGS_ITEM_ID = 1859' U+ D. `) O" Z$ I, |+ I# C
  8. DROP_RATE    = 5000009 @, B+ X- i- F: y6 [  t% D

  9. 4 o" d7 x$ G- m# W& k0 ^) A4 @; \, h4 G
  10. WORLD_MAP_ITEM_ID = 1665- u( _7 Y' Q5 `+ b. u

  11. , b0 l8 H5 w+ @. V+ e  ~
  12. def getCount(st) :3 c/ n9 D6 L* O: u6 _
  13. return st.getQuestItemsCount(FANGS_ITEM_ID)7 Z, D5 r: k2 o. i3 N! P

  14. ; I4 R/ `) m  s) C& R
  15. def completed(st) :5 M: m" Z/ k4 u7 ]# r  f
  16. st.setState(COMPLETED)
    ' u. G2 o3 x3 O# o" r
  17. st.clearQuestDrops()/ s- |& s' a2 ^. O
  18. st.takeItems(FANGS_ITEM_ID,-1)
    ) J" r5 [( t- X% u# C
  19. st.giveItems(WORLD_MAP_ITEM_ID,1)
    % Y: X; N* {3 w& n3 o
  20. st.exitQuest(False), h) ^. C- _4 o! \8 p& ]
  21. return1 m3 y6 X9 o. @' a; J

  22. . ~7 `6 h  y7 v0 H* V$ o! q+ G
  23. def check(st) :, P1 b7 T6 r. l5 R: y
  24. if getCount(st) >= 4 :9 E8 p: l# t& {- L: ~+ r& y
  25. completed(st)- N8 \  Z) R6 N$ F$ z9 e: ~
  26. return
    , ^0 k* N; n8 V' H- i

  27. 3 J4 t* k' A$ Y
  28. class Quest (JQuest):
    . K( z2 q! E6 V, X6 t0 R6 V8 u( ?: E
  29. 3 s2 K7 J' _3 v+ [4 V. Q
  30. def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)
    # l6 p& e8 [! n# |4 }
  31. ' e9 X& Y2 ]2 m+ K* i1 Q
  32. def onEvent (self,event,st):2 ~, S/ l/ D* p; Y: F" }
  33. id = st.getState()0 b2 x* c" G0 D! b3 l
  34. if id == CREATED : st.setState(STARTED)
    $ ^" P4 k0 F0 A1 {  p4 r) Y& ]
  35. elif id == COMPLETED: pass
    4 z, f# L) A; r/ S9 z$ w% F
  36. elif id == STARTED : check(st)9 E; J, j6 p6 P0 g& [
  37. return
    ; s6 @6 F! A% e+ U
  38. 7 y+ Y, S1 r" M! h
  39. def onKill (self,npcId,st):. i' J( [; d6 N5 P5 y
  40. if npcId == KELTIR_NPC_ID:
    ' ~8 d$ Z# O4 T+ f& {7 \* ^: q
  41. n = getCount(st)  h3 @- P4 [, u% H, S- F- H
  42. if n == 0:) O1 f9 R2 _+ a! D# R- R' R) |
  43. if st.get('chat0') == None :
    3 p9 H" }5 O4 Y8 O
  44. st.set("chat0", "true")
    $ F; H3 Y$ J/ ?4 G, ~, X/ k) g. C
  45. return "Chat0.htm"; [- q( i: I: P8 P; ~
  46. elif n == 1:
    ) I/ G9 M" I) P6 x8 B% d* R
  47. if st.get('chat1') == None :. d; n! O+ a% d( E" A/ G% K
  48. st.set("chat1", "true")5 |# G" J; J( c- e
  49. return "Chat1.htm"
    * I! w! n. \5 k/ D1 c, h
  50. elif n >= 4:
    % }1 T8 r7 V" \, U  O# R
  51. return "Chat4.htm"6 e! [3 @( b+ ?) U( u
  52. return "Collect "+str(n)+" of 4 fangs"
    / t+ T+ E) }* r7 q5 M/ S  ]$ C1 b
  53. return
      ~6 R3 z3 O3 c! [3 w% d

  54. 8 N0 l, v/ `' L0 o% n
  55. QUEST    = Quest(201, "Tutorial", "Tutorial quest")* H9 z, F, j4 ~( ^. M$ _4 s
  56. CREATED = State('Start',    QUEST)% b$ x4 V8 n! F3 y, ]
  57. STARTED = State('Started', QUEST)( d' _' c% P) y. F
  58. COMPLETED = State('Completed', QUEST)' D/ i' ~6 F! C8 x9 _" S. j5 y
  59. 3 T! k& D  O( u! {2 i# M
  60. QUEST.setInitialState(CREATED)& y9 l% k. Y) e9 M
  61. QUEST.addStartNpc(7056)  b: \% l$ b: V) P, ?
  62. QUEST.addStartNpc(7012)8 V4 P# Q3 X# y7 n$ t; j0 }
  63. QUEST.addStartNpc(7009)& V5 ?$ F( r/ l
  64. QUEST.addStartNpc(7011)2 I' Q& l9 s( m5 ~
  65. 3 @7 c$ J  y- i7 ]4 `3 w8 C, r
  66. STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
    - f1 b+ ^. L  c# ~
  67. STARTED.addKillId(KELTIR_NPC_ID)$ i9 P$ H9 e" L" C/ A7 A. f7 ?
  68. STARTED.addTalkId(7056)& _$ a2 @# K: i0 \6 c2 J) Z$ x. M
  69. STARTED.addTalkI d(7012)
    3 x$ z% b& U9 K; X. e. Q: l( h
  70. STARTED.addTalkId(7009)
    ( B  |  {$ }" m. X( e
  71. STARTED.addTalkId(7011)
Скопировать код
* n0 A& g* Y4 |  U& r$ ?

6 R1 ?) r) f; m, n
Чтобы ответить, вам надо авторизироваться в системе Вход | Зарегистрироваться

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

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

638638758

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

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

admin@artace.ru Онлайн

QR-код

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