Top.Mail.Ru

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

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

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

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

x
Хроники        Interlude
! ~) v, \  ?: ?0 y8 f* J. cСборка        L2j% n" G; l0 ~7 a6 K% C, \3 ~
Обратите внимание: в файле htm стартового NCP обязательно должна быть ссылка на квест:
% ]" j5 c0 A1 E
  1. STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код
Для этого квеста больше ничего не надо. Все необходимое для корректной работы квеста уже добавили. Вот полный текст квеста:1 ^3 k& e$ @4 g* S! e! _# ~  J

9 d) p6 G% F& x" Q+ p
  1. if getCount(st) >= 4 :
    7 r- z3 U4 B! j1 }- ~: v' ?
  2. completed(st)
    + q" c+ ~. M' @
  3.   return2 [8 O8 s1 }* O% j4 G, L2 j

  4. . G( J( {+ h3 b0 e6 [6 [) ^
  5. class Quest (JQuest):! D) h9 w8 l- q. V$ W
  6.   def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)6 Z4 @$ `, Q  x7 F, O1 M0 S
  7.   def onEvent (self,event,st):9 M4 T, W3 m* f
  8. id = st.getState()) b: P  z/ e! N9 L  \2 g( Z- I: y
  9. if   id == CREATED  : st.setState(STARTED)
    # {8 b8 j2 K* d& _
  10. elif id == COMPLETED: pass0 f' n* ?: c$ U. D$ b- t2 s
  11. elif id == STARTED  : check(st)% ~3 t8 M1 |5 |
  12. return/ w$ ]7 @6 V* l4 `5 g, e( d# ~

  13. * I1 [4 A' d3 m+ N
  14. QUEST     = Quest(201,"Tutorial", "Tutorial quest"). F, F5 U% {' _/ i8 v
  15. CREATED   = State('Start',     QUEST)
    $ g, r. [" C* c% y" t' M; R
  16. STARTED   = State('Started',   QUEST)
    / O. p0 D5 m/ U) t
  17. COMPLETED = State('Completed', QUEST)- @3 G0 ?) O  z5 [; x0 L& B$ f
  18. 9 d/ J& L$ U  N( D1 o1 z- z7 }
  19. QUEST.setInitialState(CREATED)
    ; r  ]- p5 H3 p! u# w
  20. QUEST.addStartNpc(7056); H" y2 [. x8 u) K3 k* I5 v3 ~1 L
  21. STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код
Теперь рассмотрим, как это работает.
  J4 }; k8 h, @, j( P9 w3 |) [Игрок подходит к начальному NCP (в данном случае 7056), нажимает на «Quest». Квест будет создан и состояние квеста перейдет к CREATED и игроку будет показана страничка Start.htm с описанием квеста. Тогда метод onEvent, поле открытия странички Start.htm переведет состояние квеста в STARTED и игроку будет показана страничка Started.htm, где будет опсание того, как найти keltirs и .т.д.
: k' e* `' K. Y, T
% n1 c& D8 Q# Y  B7 X# v

. u8 G+ O) K- C  ]9 m. nПри состоянии STARTED будет зарегистрирован дроп «fangs» при убийстве keltirs. Игрок может вернуться к стартовому NCP и спросить о квесте – метод onEvent будет вызван снова. Если у игрока не хватает необходимого количества предметов, то метод check() не переведет квест в следующее состояние и Started.htm будет показана снова. Но если игрок собрал необходимее количество предметов (в данном случае 4 клыка), то метод check() вызовет метод completed() который переведет квест в новое состояние COMPLETED, заберет все клыки, даст карту мира, т.к. это награда за квест, покажет Completed.htm и завершит квест.: V- t, i) l* o' D
8 t1 ^( M, N+ B0 b. Q' k
* ^  b. p2 H! k# X$ N% j" ~2 }) @
Теперь давайте сделаем наш квест более похожим на то, что он должен из себя представлять.
6 `( K2 l1 ~8 K, c5 KПрежде всего у нас есть 3 метода для объявления их в Яве – onTalk, onKill и onEvent. Если методы onTalk и onKill не объявлены, то за них все будет делать метод onEvent, т.е. определять квестовых монстров и вызывать диалоги NCP. Есть примечание, методы onTalk и onKill будут вызывать только диалоги с NCP в зависимости от текущего состояния квеста. Метод onKill будет вызываться только тогда, когда мы убиваем квестового монстра.  |2 j! Y+ H* Q- n

. R3 E3 S* G' v% i

5 m1 @3 Z0 E2 W/ ~+ r* z7 YДавайте рассмотрим как вызывается метод onKill при убийстве keltir в состоянии квеста STARTED:
6 \  Z/ M7 e/ e! s- s  K
  1. STARTED.addKillId(KELTIR_NPC_ID)
Скопировать код
и метод onKill в классе Quest:+ p- S3 v! s# ~- q3 w: j: f1 V
  ], Y) m; L# [. F# N! J
  1. class Quest (JQuest):1 N' F+ z4 q  x( n3 T
  2.   ...
    9 |  ^! @" y# S% K+ Q' S& K( g
  3.   def onKill (self,npcId,st):' Z1 n8 L! b7 ]. X$ `' }, b
  4. if npcId == KELTIR_NPC_ID:
    7 D: r9 G! |" ?" N
  5.    n = getCount(st)
    1 Q0 N/ `. T" Z2 k
  6.    if   n == 0:6 S5 X2 o+ y# e+ Z8 |
  7.        return "Chat0.htm"( ~. S) f; C; U& f1 {
  8.    elif n == 1:
    + h. s. H/ _4 M0 E- H( u
  9.        return "Chat1.htm"6 K3 Q% o3 j0 E* g2 K' j$ ~
  10.    elif n >= 4:
    , l# X0 ^5 J5 }2 d/ z" s' l
  11.        return "Chat4.htm"
    $ H" a& I" ?0 }
  12.    return "Collected "+str(n)+" of 4 fangs"
    : |+ P( h! J" V' E7 F
  13. return
Скопировать код
Метод onKill (а так же метод onTalk) имеет следующие параметры:6 r3 |: ?, e$ Z& K# P5 I/ W+ j
! p0 v4 N; L2 X: b# ~  h

* R* P& y+ i& Z- i• self – квест7 t4 Y' b: q# M
• npcId – ID NCP, которого мы должны убивать (если это метод onTalk, то ID того NCP, с которым мы должны поговорить)., N& X3 A0 t. T1 [: b  A
• st – текущее состояние игрока.
5 f! P2 |3 L2 J8 ^  k+ h, K, Y5 I0 T0 M  |0 e2 O4 x/ O
7 m  A* y. e7 e) S# s
В этом методе мы проверяем и отмечаем, является ли убитый NCP keltir’ом. В основном эта проверка не нужна, т.к. у нас только KELTIR_NPC_ID.1 @$ N+ \: W7 @6 y5 x# b4 b! c& v3 n

; I* c: O" o$ j$ ?% T% z
3 U1 u- y2 ]4 `. v% g; y- r" ]
Затем проверяем количество предметов (в данном случае количество клыков), и если их вообще нет, то возвращаем строку "Chat0.htm", если только один предмет, то возвращаем строку "Chat1.htm", если же предметов 4 или больше, то "Chat4.htm". Если строка возвращена из методов onEvent, onKill или onTalk, то сервер покажет соответствующие htm. В Chat0.htm может иметь следующий текст: «Вы не имеете ни одного клыка, возвращайтесь позже, когда соберете 4 штуки и бла, бла, бла…», в Chat1.htm может быть следующий текст: «У Вас всего 1 клык, по этому соберите еще…». В Chat4.htm – «Вы собрали необходимое количество предметов, возвращайтесь к вашему тренеру, что бы завершить квест…»- t$ g0 H7 H" p, y2 W3 \) Q( ~# b
% y6 Y( A/ v7 a4 {3 h/ R

- O, E/ ]3 F9 w. [7 uПримечание: если в строка return начинается с "<html>", то будет показана страничка html с текстом, который стоит далее. Так вместо:8 W5 g: h4 w7 z! m- r- F
return "Chat4.htm"
7 O  {4 x- |( j* W, [7 b+ U) m: V# [: y

$ D# T0 W- Q& Z! Q9 ^+ Gможно поставить:1 q5 ^" E. m. ^6 r" E! J# i# }
  1. return "<html><body>Return to your trainer to complete the quest</body></html>"
Скопировать код
Так же если строка заканчивается без .htm или в начале нет <html>, то текст будет выведен, как системное сообщение в окне чата. В нашем случае мы сделаем так, что бы при каждом убийстве keltik выводилось системное сообщение: «Собрано N из 4-х клыков».
0 n$ j, V+ E$ \% c! J1 f# S4 E
4 S1 B+ X' j( ~, o9 v

( {5 e: q, P6 }) O. Y9 v) ^Наш код для onKill имеет один недостаток. Он будет постоянно показывать Chat0.htm, Chat1.htm и Chat4.htm, нам же необходимо, что бы Chat0.htm и Chat1.htm показывались только один раз. Как нам это сделать? С помощью переменных.& L1 _9 u+ Q; _# q5 W

' i; J/ I; i9 N+ K5 G5 w
  D/ F  q" G2 [
В каждом квесте строки могут храниться с помощью переменных. Эти переменные сохраняются в Вашей БД. В каждом методе мы можем назначить, прочитать и удалить переменные. Давайте изменим метод onKill, так что бы каждый диалог вызывался только один раз.
! }$ @! _5 c& {8 G  A0 J
  1. def onKill (self,npcId,st):* P( I) B7 Q# }! {! l2 J- e8 ^
  2. if npcId == KELTIR_NPC_ID:
    # B/ E4 d0 Y8 ]
  3. n = getCount(st)3 x4 B, r( A/ X' P1 U2 G& w
  4. if n == 0:2 {2 s) c' e; {! g% s& _
  5. if st.get('chat0') == None :. U% K$ P5 E" ~0 W: r
  6. st.set("chat0", "true")
    $ `* E# [- x- B7 w0 G3 c2 Y! m
  7. return "Chat0.htm"
    ( S' f$ A, x: t6 \% a6 j
  8. elif n == 1:
    0 ^/ g- J7 y/ D+ ~
  9. if st.get('chat1') == None :2 B/ I6 _1 b& K6 T$ L3 S7 l
  10. st.set("chat1", "true")6 b/ d0 _- W2 M3 p( N9 E
  11. return "Chat1.htm"
    6 ~5 y$ M( d- n" _
  12. elif n >= 4:) A, k% S& z. C% O  H
  13. return "Chat4.htm"
    2 o0 ?% i: S- D# W5 [
  14. return "Collected "+str(n)+" of 4 fangs"
      l& t6 c, T* E  g6 \1 r9 {
  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.
1 ~2 h; _1 ~2 G0 z6 N/ j  Y+ h5 n5 h3 v9 n. }2 d; W
0 M' ^: U) N7 g9 D) K" M0 V" O
Вот конечный рабочий вариант квеста:3 V! A: @1 v/ R5 |5 N9 L; z: \( E
  1. import sys, h- _: s1 w' e$ V' m) |' a- Y
  2. from net.sf.l2j.gameserver.model.quest import State+ `0 B+ b. J5 L8 |
  3. from net.sf.l2j.gameserver.model.quest import QuestState# w) D' K+ _8 |* ~: j) Y/ x: R
  4. from net.sf.l2j.gameserver.model.quest.jython import QuestJython as JQuest. N& R3 u( X% T+ B. E: |

  5. 6 S) H5 ?% V. ^0 b
  6. KELTIR_NPC_ID = 12082# Y$ _% i/ X. f  _
  7. FANGS_ITEM_ID = 1859
    1 p/ f0 u/ P. |, ~( A) n9 j) k. s' A
  8. DROP_RATE    = 500000  _% ~5 a4 O- b3 `

  9. 8 Y8 v; }( D' r# a# M8 n
  10. WORLD_MAP_ITEM_ID = 1665- ]5 [2 w# B5 |  A: E2 E
  11. 2 O% ]5 p! L% \7 l
  12. def getCount(st) :
    / q6 n$ u+ B* {3 j6 f
  13. return st.getQuestItemsCount(FANGS_ITEM_ID)7 h+ K2 l4 b/ H. j, M3 l1 H
  14. 6 G" {' |! p) H4 x5 K& T7 g
  15. def completed(st) :- y; z7 g3 G) `) ]8 _! d
  16. st.setState(COMPLETED)
    1 g+ j" i* H, ^# a( L
  17. st.clearQuestDrops()
    1 A) W: d7 Z4 L7 e( r% {
  18. st.takeItems(FANGS_ITEM_ID,-1)9 [" [- ~( Z+ @5 l% m
  19. st.giveItems(WORLD_MAP_ITEM_ID,1)6 M  k$ }9 U6 m
  20. st.exitQuest(False)9 {+ b. i4 V% |( C6 D% j% x" {
  21. return
    5 |1 N- N  T" @) W$ f
  22. 9 Z- a: _+ S0 @9 K9 c; B
  23. def check(st) :/ e9 J6 t! o1 _( X
  24. if getCount(st) >= 4 :
    + x3 @7 |8 ?1 c  @" m
  25. completed(st)& d( M: |7 d0 e2 d
  26. return) l. A$ X6 {) ^( U7 ^( q
  27. ) ^% h% e& K4 T1 |
  28. class Quest (JQuest):6 B' [5 Q) q( f. j3 V* Q) v7 M& l

  29. 6 W+ v1 B# ~  c" y3 l0 ~4 O7 I
  30. def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)+ V# x5 y+ @8 @% ?

  31. ' A  }$ ]& g" n. c) n- `
  32. def onEvent (self,event,st):
    5 r! s$ W+ o, `) \  n
  33. id = st.getState()
    , I9 ]9 U0 Q$ I. d1 X/ i# V+ R. o* n
  34. if id == CREATED : st.setState(STARTED)$ x9 l9 v2 y" N" Q# i
  35. elif id == COMPLETED: pass
    ! ~5 B  k3 C5 P+ A1 l8 I
  36. elif id == STARTED : check(st)
    0 V$ N8 B  B0 K3 U
  37. return
    - S7 I  ~  k- `7 m$ Y

  38. ) |: {, K* c% D9 [2 G% _
  39. def onKill (self,npcId,st):4 n8 s5 p7 r+ E6 @2 @, C4 ^  u2 V
  40. if npcId == KELTIR_NPC_ID:
    / c% n0 C( N: ?5 n
  41. n = getCount(st)1 K/ S% _6 p; `0 _
  42. if n == 0:3 m6 G. D6 x7 t9 m2 C: f- _
  43. if st.get('chat0') == None :
    - ^" t* y5 {; J
  44. st.set("chat0", "true")0 o3 X4 m6 A: y# D) ?1 K2 u
  45. return "Chat0.htm"  @  ~5 g$ m" U. D
  46. elif n == 1:9 I# ]' j0 L; A5 I9 ?; ~5 D; _. `, Y
  47. if st.get('chat1') == None :1 q& |- N/ p8 S2 t/ I  T7 ~
  48. st.set("chat1", "true")6 s. G/ c7 U- U' l( [/ w
  49. return "Chat1.htm"! a. `1 }- p6 U7 v# a  c
  50. elif n >= 4:
    ! K6 o0 X) K7 c/ Z9 X( S. o; U2 n
  51. return "Chat4.htm"
    , ]  u5 K5 w; r) Q6 K7 g
  52. return "Collect "+str(n)+" of 4 fangs"
    $ N5 a, W1 u, p  Z3 }: [. K- ]! f) \% l8 x
  53. return
    $ Q3 d+ M1 h0 }: K
  54. / O. I/ v( k! t5 A% @
  55. QUEST    = Quest(201, "Tutorial", "Tutorial quest")
    / o+ X8 \) c$ {  Z% p4 q
  56. CREATED = State('Start',    QUEST)
    9 s, F* L" u+ ^$ `" Q
  57. STARTED = State('Started', QUEST)
    0 F9 W8 L, I) N# J5 [
  58. COMPLETED = State('Completed', QUEST)
    7 w! d6 Z( _  G; ?" s( e$ @

  59. 1 o) u% W+ F5 F
  60. QUEST.setInitialState(CREATED)( r7 _; f! q2 |: X; q# T/ u
  61. QUEST.addStartNpc(7056)
    9 U8 w; y* @9 C0 V, j
  62. QUEST.addStartNpc(7012)
    % O9 @& F0 o4 e8 h, }
  63. QUEST.addStartNpc(7009)9 U; ~) O" [+ p
  64. QUEST.addStartNpc(7011)
    & d2 A0 {' x4 Q& |' W
  65. 5 P$ {, ^! ~  A1 G0 f
  66. STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
    $ \0 L$ \4 L$ e, N
  67. STARTED.addKillId(KELTIR_NPC_ID)
    ) e3 Z' u- a4 `: r  n/ H% Y
  68. STARTED.addTalkId(7056)
    " G. V( ]4 G" }" T+ Q4 c' T! I
  69. STARTED.addTalkI d(7012)& `! G' W; k: C% d$ ]5 T
  70. STARTED.addTalkId(7009)
    ; g( f' P& S+ j, E) @8 T
  71. STARTED.addTalkId(7011)
Скопировать код

% T' C( C' R6 x! j2 `/ F9 f4 c$ \, T2 Z! x
Чтобы ответить, вам надо авторизироваться в системе Вход | Зарегистрироваться

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

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

638638758

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

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

admin@artace.ru Онлайн

QR-код

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