Top.Mail.Ru

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

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

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

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

x
Хроники        Interlude: K; ?+ Q6 p  m: w' U8 }; h! n
Сборка        L2j
/ Z& R9 ]; M/ p! XОбратите внимание: в файле htm стартового NCP обязательно должна быть ссылка на квест:" X5 p' X6 T$ D7 z$ l$ P
  1. STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код
Для этого квеста больше ничего не надо. Все необходимое для корректной работы квеста уже добавили. Вот полный текст квеста:2 f3 ?; `) j" X% z
7 S! R+ N! h9 a" Z& |8 g2 G/ S
  1. if getCount(st) >= 4 :
    ! Y1 a+ n: G& H+ y1 E+ B+ Y  U# V
  2. completed(st)
    $ {5 k2 y# m5 N5 \9 I
  3.   return- N' l+ g# ~  u( ?
  4. - s7 d( @. g3 n! ?/ M0 a
  5. class Quest (JQuest):5 A* V. D* R0 @
  6.   def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)
    * j& t: t' e" k# r/ Z
  7.   def onEvent (self,event,st):
    + g; S8 r0 u1 j0 }. t1 m+ ]
  8. id = st.getState(); }0 ^& d9 r9 U3 w4 s& r
  9. if   id == CREATED  : st.setState(STARTED)" P3 n  j- O7 \% ]- u- j
  10. elif id == COMPLETED: pass
    % z. o+ E% g4 H) I
  11. elif id == STARTED  : check(st)( ~4 g4 _& G9 B6 K% ?/ {
  12. return2 n: k/ w/ e+ P: a

  13. - C9 r  U" H. f# a% K) E  u
  14. QUEST     = Quest(201,"Tutorial", "Tutorial quest")
    " z2 a; J3 Q  x) ?3 \5 \; |
  15. CREATED   = State('Start',     QUEST)# _$ ~2 a$ C( r6 Z0 ?; Q: u
  16. STARTED   = State('Started',   QUEST)$ r0 S# }( k; c6 @* U. c) T
  17. COMPLETED = State('Completed', QUEST)1 w" r2 o* g0 p6 K/ F% g0 z  ]2 [
  18. ) R+ v/ L# H6 ]% u5 H/ z
  19. QUEST.setInitialState(CREATED)6 Z; \7 b: A7 b! o
  20. QUEST.addStartNpc(7056)
    5 n5 L1 O0 u% C( }# U; N
  21. STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код
Теперь рассмотрим, как это работает.
# T( R4 ~' s! C0 y4 W/ h! ]7 kИгрок подходит к начальному NCP (в данном случае 7056), нажимает на «Quest». Квест будет создан и состояние квеста перейдет к CREATED и игроку будет показана страничка Start.htm с описанием квеста. Тогда метод onEvent, поле открытия странички Start.htm переведет состояние квеста в STARTED и игроку будет показана страничка Started.htm, где будет опсание того, как найти keltirs и .т.д.1 g  h( D$ q2 D% g$ p+ Y! T

( `9 o9 k, n. }( b

0 j0 L9 `. ^: k; O- xПри состоянии STARTED будет зарегистрирован дроп «fangs» при убийстве keltirs. Игрок может вернуться к стартовому NCP и спросить о квесте – метод onEvent будет вызван снова. Если у игрока не хватает необходимого количества предметов, то метод check() не переведет квест в следующее состояние и Started.htm будет показана снова. Но если игрок собрал необходимее количество предметов (в данном случае 4 клыка), то метод check() вызовет метод completed() который переведет квест в новое состояние COMPLETED, заберет все клыки, даст карту мира, т.к. это награда за квест, покажет Completed.htm и завершит квест.$ o9 k5 x1 [4 t3 e. Z, O% A0 O$ a: F5 a

6 g+ e6 h0 K0 D( O* O( K' A

* g1 I4 e) Q0 V, z5 e2 VТеперь давайте сделаем наш квест более похожим на то, что он должен из себя представлять.
# _% U+ U- _8 b7 w; M1 j# vПрежде всего у нас есть 3 метода для объявления их в Яве – onTalk, onKill и onEvent. Если методы onTalk и onKill не объявлены, то за них все будет делать метод onEvent, т.е. определять квестовых монстров и вызывать диалоги NCP. Есть примечание, методы onTalk и onKill будут вызывать только диалоги с NCP в зависимости от текущего состояния квеста. Метод onKill будет вызываться только тогда, когда мы убиваем квестового монстра., n$ O8 N4 W* ]& B

" Z$ {7 d2 _4 @9 L

+ b6 X- x0 w3 f) T  IДавайте рассмотрим как вызывается метод onKill при убийстве keltir в состоянии квеста STARTED:/ V$ X4 r. u( `- p6 R. G
  1. STARTED.addKillId(KELTIR_NPC_ID)
Скопировать код
и метод onKill в классе Quest:6 U4 r: l( s, v
" o+ _8 q  `$ {5 K& L
  1. class Quest (JQuest):& }! b6 M- O" o- q) |/ ^7 n
  2.   ...& \! u, }0 J. |8 E6 W+ h0 r' I
  3.   def onKill (self,npcId,st):7 i* C% J9 T  E6 h: s
  4. if npcId == KELTIR_NPC_ID:! ?. q5 Z! C) M8 e/ `* S2 n
  5.    n = getCount(st)% d, J* A8 v7 Q% C' V$ O
  6.    if   n == 0:. a) q+ Y- k; _' Y6 M! R4 ~9 U
  7.        return "Chat0.htm") [+ t9 [9 H9 Z3 R$ X7 o" i
  8.    elif n == 1:- E/ p' [) b: E7 u5 X2 n! w
  9.        return "Chat1.htm"" q) t$ N9 u  U' N+ X+ I
  10.    elif n >= 4:
    : w8 F( W3 j+ e2 v" h7 b; p
  11.        return "Chat4.htm"
    , y6 h' u5 u+ G
  12.    return "Collected "+str(n)+" of 4 fangs"
    $ a1 A  A5 p, X) Q
  13. return
Скопировать код
Метод onKill (а так же метод onTalk) имеет следующие параметры:$ P* I7 Z- ?! O% w& S
, ~; q$ }! U) Z! Z

5 B: `) n* |& x/ P# {- ]• self – квест
' k" b# T( F0 A  T" Y7 m. ]2 E2 b3 T• npcId – ID NCP, которого мы должны убивать (если это метод onTalk, то ID того NCP, с которым мы должны поговорить).
" {( A% l# o8 N• st – текущее состояние игрока.
) t( [# x4 a- w( t9 e! G1 t' p# |1 p  C, g
8 U" O$ B0 |$ k
В этом методе мы проверяем и отмечаем, является ли убитый NCP keltir’ом. В основном эта проверка не нужна, т.к. у нас только KELTIR_NPC_ID.$ ~; x( U0 H: ~' G) ~
* s: O% [% s! K- h7 @

* D4 {3 P. _( Y) [: D# g3 @Затем проверяем количество предметов (в данном случае количество клыков), и если их вообще нет, то возвращаем строку "Chat0.htm", если только один предмет, то возвращаем строку "Chat1.htm", если же предметов 4 или больше, то "Chat4.htm". Если строка возвращена из методов onEvent, onKill или onTalk, то сервер покажет соответствующие htm. В Chat0.htm может иметь следующий текст: «Вы не имеете ни одного клыка, возвращайтесь позже, когда соберете 4 штуки и бла, бла, бла…», в Chat1.htm может быть следующий текст: «У Вас всего 1 клык, по этому соберите еще…». В Chat4.htm – «Вы собрали необходимое количество предметов, возвращайтесь к вашему тренеру, что бы завершить квест…»
# L' K# _; ^# u
7 H: f; G* Y! O) N" F/ |! B7 h* @

3 a5 w3 N7 A9 @Примечание: если в строка return начинается с "<html>", то будет показана страничка html с текстом, который стоит далее. Так вместо:
0 K( o4 w- Q1 h- Oreturn "Chat4.htm"
& q6 H9 ]+ R. w' E0 k8 ~6 j: ]9 ^* |  p: D, i2 E8 T, X6 j# X; K+ M# N* P$ z

* c, j  _7 f$ ]8 G" y1 U* f" H7 Yможно поставить:
( W3 S# J3 y: I5 Z6 a: P) ?
  1. return "<html><body>Return to your trainer to complete the quest</body></html>"
Скопировать код
Так же если строка заканчивается без .htm или в начале нет <html>, то текст будет выведен, как системное сообщение в окне чата. В нашем случае мы сделаем так, что бы при каждом убийстве keltik выводилось системное сообщение: «Собрано N из 4-х клыков».. t. x) J9 ?  C+ d
; |: J1 F- B/ M9 U4 K3 v. t
4 o  ~, k* C+ E
Наш код для onKill имеет один недостаток. Он будет постоянно показывать Chat0.htm, Chat1.htm и Chat4.htm, нам же необходимо, что бы Chat0.htm и Chat1.htm показывались только один раз. Как нам это сделать? С помощью переменных.+ N' a/ C) G* Z( M  v. ?8 k3 D$ `8 \7 l
2 A8 N9 X. |2 u5 }: D, h0 t- R
) o- D. T+ ~; w( P$ G' B. Z
В каждом квесте строки могут храниться с помощью переменных. Эти переменные сохраняются в Вашей БД. В каждом методе мы можем назначить, прочитать и удалить переменные. Давайте изменим метод onKill, так что бы каждый диалог вызывался только один раз.9 b8 ]  T+ x/ V* b2 M, \
  1. def onKill (self,npcId,st):% b  C( i$ I- p6 p
  2. if npcId == KELTIR_NPC_ID:9 h4 q, W9 l1 Y* x
  3. n = getCount(st)
    - t$ g" u6 d8 M
  4. if n == 0:! \8 X5 d- s! q% q! ~/ n
  5. if st.get('chat0') == None :
    ) c$ ?+ {  G& L" z8 e! l/ G
  6. st.set("chat0", "true")
    4 M9 a  J) X) D7 h- q6 z
  7. return "Chat0.htm"9 X' R6 k; \, T. W/ ~6 O
  8. elif n == 1:/ i4 \# W. {/ E+ V5 `: K/ y
  9. if st.get('chat1') == None :
    ' |5 y- E1 `; ~4 i
  10. st.set("chat1", "true")
    ) M4 l/ a# P8 O$ `* e
  11. return "Chat1.htm"
    0 s0 l. }# b1 k! n. V
  12. elif n >= 4:( W9 S7 d: ~3 \% w+ H2 W  @
  13. return "Chat4.htm". W7 C# u+ X+ z# T
  14. return "Collected "+str(n)+" of 4 fangs") f& ~8 I9 d8 Z# p
  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." L5 B' |& H, {1 b, I0 }

. M7 ^2 E7 \- H- h4 J

/ |. W+ {2 E8 l6 qВот конечный рабочий вариант квеста:) B" i& S5 l1 P( j0 k4 {
  1. import sys3 a7 I) O0 z) C! ?% r( X
  2. from net.sf.l2j.gameserver.model.quest import State$ w  x  S3 w: _
  3. from net.sf.l2j.gameserver.model.quest import QuestState1 v& k4 _0 l2 d' a
  4. from net.sf.l2j.gameserver.model.quest.jython import QuestJython as JQuest' s, X* b' s0 m% ^, L! g& E8 \
  5. 9 M: s, C2 {, v& u% |
  6. KELTIR_NPC_ID = 12082
    ' H' |9 Z" h' R* ^
  7. FANGS_ITEM_ID = 1859& p# H; a% d1 o7 Y
  8. DROP_RATE    = 5000005 P* l5 J: M. k6 U

  9. 5 T% m. S8 \5 E- W
  10. WORLD_MAP_ITEM_ID = 1665/ l# y' y, ]# W4 O/ s; w3 R

  11. 6 L4 d+ `) u. N2 g
  12. def getCount(st) :, j* w# T4 A: I9 h! T! K
  13. return st.getQuestItemsCount(FANGS_ITEM_ID)
    % M. e/ w' E+ q- M& Q( t5 j" C

  14. 9 b% ?% e/ H5 A+ W7 k
  15. def completed(st) :
    2 R+ f% x4 f, L% v
  16. st.setState(COMPLETED)( \- E( A& C2 h
  17. st.clearQuestDrops()7 s  a1 d9 V; K6 h' n1 D) D, N
  18. st.takeItems(FANGS_ITEM_ID,-1)
    4 o7 I0 e! g6 w+ @4 D1 a3 s
  19. st.giveItems(WORLD_MAP_ITEM_ID,1)9 z* n' v( V! A. M9 m
  20. st.exitQuest(False)1 J2 W' {% c6 l
  21. return. u6 a! I; S2 w

  22. 4 ~2 W, O! f+ u' }# a! j$ m" G
  23. def check(st) :; W7 |2 O$ D0 Z6 L" c: n, Y
  24. if getCount(st) >= 4 :
    2 q8 G  ?, S4 m, p6 r% Q  m1 ]
  25. completed(st)0 M" T, b: Z& }7 W
  26. return) o! }( ]  C* F+ T
  27. 0 Q& s# l. ^( |7 _8 a' Z( k
  28. class Quest (JQuest):
    4 {6 l; t8 G  ~; P; w2 I
  29. , w9 n# L% O% O7 C
  30. def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)
    . X: Z4 l6 n, t5 {
  31. 4 w' u' l' C: r, z0 E$ }4 r
  32. def onEvent (self,event,st):! [+ W/ [4 O7 r& j
  33. id = st.getState()% D0 ?8 d5 x  Y
  34. if id == CREATED : st.setState(STARTED)7 {' R0 u2 |) F4 v+ e) s
  35. elif id == COMPLETED: pass
    , V  H% }$ [* t) H9 C
  36. elif id == STARTED : check(st)9 c- t+ V9 x0 O. A0 T8 n  z. d
  37. return
    . I! A, l& M* {

  38. % ^* L" C% L+ J; N( ~+ M
  39. def onKill (self,npcId,st):7 R( S3 U8 S+ |0 `: x, G
  40. if npcId == KELTIR_NPC_ID:
    8 D0 y4 w( r) k( G8 V% k! T
  41. n = getCount(st)
    ; ^6 C0 o1 i3 w- @& u) F7 C
  42. if n == 0:( j# R1 ^( U+ N! a% ]$ \) j
  43. if st.get('chat0') == None :2 o( G; B, I" a$ h/ X
  44. st.set("chat0", "true")
    ! F+ p5 c9 m& C1 U! o1 X' C
  45. return "Chat0.htm"1 Q2 S: w1 ~% e9 r2 [1 a) B: m
  46. elif n == 1:
    ; ?, V) K- v7 X! s5 S" z
  47. if st.get('chat1') == None :. }  t9 c/ P/ q( B
  48. st.set("chat1", "true")
    * E- j) I6 c* w* y+ a9 ^+ P2 ~  X
  49. return "Chat1.htm"
    , U& r% Z) Q+ G2 A, t
  50. elif n >= 4:
    # ?! W: R! x5 V2 F
  51. return "Chat4.htm"8 l* b4 w5 g+ [0 C6 M& s9 ^- B* o
  52. return "Collect "+str(n)+" of 4 fangs"
    $ D  [) Z  g) w  a3 B1 A; h
  53. return& p9 a: k/ r8 m3 ?3 m8 ^7 p
  54. $ |+ W, H! w7 ?
  55. QUEST    = Quest(201, "Tutorial", "Tutorial quest")
    6 l$ I2 ]6 L0 A# o: c( R$ \. F
  56. CREATED = State('Start',    QUEST)) T% G1 a. }- p& D3 g% E' _
  57. STARTED = State('Started', QUEST)# z, Q, `0 P; K, y. E8 I4 t2 C* r
  58. COMPLETED = State('Completed', QUEST)
    $ N5 y# P! T' l+ E6 l5 V9 ?% z
  59. 8 E4 n2 J. Z1 R+ q' Z0 k
  60. QUEST.setInitialState(CREATED)1 s) e- s7 |& F5 o
  61. QUEST.addStartNpc(7056), \$ z% R. o' r1 U. C- r
  62. QUEST.addStartNpc(7012)4 {7 h. L0 L/ K6 E  b, x2 B. q
  63. QUEST.addStartNpc(7009)
    * ?0 V8 L2 i: u3 P3 B, |
  64. QUEST.addStartNpc(7011)3 Z. C' G( o8 J/ n4 U
  65.   j6 T* f2 o/ f$ H$ E* o
  66. STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
    ' o6 g7 q; n  C. j  Y. q8 l
  67. STARTED.addKillId(KELTIR_NPC_ID): D- S! ^! K/ k  z/ I& A) e
  68. STARTED.addTalkId(7056)
    0 }. \: k" F7 h8 y2 i
  69. STARTED.addTalkI d(7012)
    1 {5 {! w( S: e
  70. STARTED.addTalkId(7009)
    , q, m7 f" ^  L/ @
  71. STARTED.addTalkId(7011)
Скопировать код

( C! u, \: k7 k8 f. q; P, I+ b8 t
Чтобы ответить, вам надо авторизироваться в системе Вход | Зарегистрироваться

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

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

638638758

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

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

admin@artace.ru Онлайн

QR-код

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