Top.Mail.Ru

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

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

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

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

x
Хроники        Interlude+ l; B3 W% R4 I$ ^0 l
Сборка        L2j
5 A4 L+ A6 ]  E7 cОбратите внимание: в файле htm стартового NCP обязательно должна быть ссылка на квест:
& _6 C/ ?& O& R3 d9 M
  1. STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код
Для этого квеста больше ничего не надо. Все необходимое для корректной работы квеста уже добавили. Вот полный текст квеста:
6 `2 g: ?8 f$ T! S: g' c' W2 [; M: x
  1. if getCount(st) >= 4 :
    / j; B6 O4 @+ B, V2 a
  2. completed(st)
    ) N% D3 L# _# t9 y' C7 ]9 b- P
  3.   return1 k7 D3 x8 \9 R; \+ P4 D6 C

  4. ( {# [  Z+ F+ `
  5. class Quest (JQuest):% a* y) ]6 R$ L* g( |* `
  6.   def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)+ R  q& Z, h/ R! `* E8 W
  7.   def onEvent (self,event,st):- \' F$ N" H. r6 @3 f0 e
  8. id = st.getState()3 Y2 d# @" p, l7 g% t
  9. if   id == CREATED  : st.setState(STARTED)3 `" N! v% V( R. t
  10. elif id == COMPLETED: pass
    : n1 [* f0 N! _& o$ q7 v
  11. elif id == STARTED  : check(st)0 l( ?& f( p+ k; H  V& E3 n  ^9 ]% g
  12. return% U/ e" g5 a2 P9 {) Y4 v; e

  13. ' l+ p% Y" u9 n( g: u. k+ t
  14. QUEST     = Quest(201,"Tutorial", "Tutorial quest")
    2 b. n& e+ m8 n- R
  15. CREATED   = State('Start',     QUEST)
    4 n' f' @$ l  S3 S- I3 @
  16. STARTED   = State('Started',   QUEST)$ ^- Y  R1 [6 c; h! D( t+ R
  17. COMPLETED = State('Completed', QUEST)
    $ g5 h- [0 ]) i: x! B' E! w+ d

  18. $ j) `6 u' \( c9 G6 U* T, c* c
  19. QUEST.setInitialState(CREATED)
    4 s' j2 K* R9 H1 H8 H
  20. QUEST.addStartNpc(7056)
    . f9 R! }; ]7 H& J8 x+ R
  21. STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код
Теперь рассмотрим, как это работает.* Z1 C' y/ ~; q" X9 ?0 t8 N
Игрок подходит к начальному NCP (в данном случае 7056), нажимает на «Quest». Квест будет создан и состояние квеста перейдет к CREATED и игроку будет показана страничка Start.htm с описанием квеста. Тогда метод onEvent, поле открытия странички Start.htm переведет состояние квеста в STARTED и игроку будет показана страничка Started.htm, где будет опсание того, как найти keltirs и .т.д.
+ O+ s, B( Z, s9 S, S5 `+ u
6 s# N! j8 A  i* j  v& ~5 Y% j1 }

- ~9 X8 O- ]  n, M) S  A8 A: zПри состоянии STARTED будет зарегистрирован дроп «fangs» при убийстве keltirs. Игрок может вернуться к стартовому NCP и спросить о квесте – метод onEvent будет вызван снова. Если у игрока не хватает необходимого количества предметов, то метод check() не переведет квест в следующее состояние и Started.htm будет показана снова. Но если игрок собрал необходимее количество предметов (в данном случае 4 клыка), то метод check() вызовет метод completed() который переведет квест в новое состояние COMPLETED, заберет все клыки, даст карту мира, т.к. это награда за квест, покажет Completed.htm и завершит квест.
+ |/ ^' ?9 h5 S5 X! b1 h$ z: y5 P  w

& |$ c" g4 Y, i$ U/ I) IТеперь давайте сделаем наш квест более похожим на то, что он должен из себя представлять.
4 Z) @- R. @$ n9 {Прежде всего у нас есть 3 метода для объявления их в Яве – onTalk, onKill и onEvent. Если методы onTalk и onKill не объявлены, то за них все будет делать метод onEvent, т.е. определять квестовых монстров и вызывать диалоги NCP. Есть примечание, методы onTalk и onKill будут вызывать только диалоги с NCP в зависимости от текущего состояния квеста. Метод onKill будет вызываться только тогда, когда мы убиваем квестового монстра.
/ P& t: P  i/ @% d, R$ T9 E; c: V" K

  U2 ^8 A) k  J3 u4 {- P2 TДавайте рассмотрим как вызывается метод onKill при убийстве keltir в состоянии квеста STARTED:
; W0 e. [5 G# h
  1. STARTED.addKillId(KELTIR_NPC_ID)
Скопировать код
и метод onKill в классе Quest:
! q* y5 [4 H) n9 t* R$ b
1 L2 ~6 J) q3 g, W
  1. class Quest (JQuest):. K0 c0 x! {( s7 ~6 K0 F5 P
  2.   ...
    . \+ N# T/ N/ s) J7 }/ }+ @+ E# D9 m5 X
  3.   def onKill (self,npcId,st):3 e' o& }3 T/ B/ R0 I
  4. if npcId == KELTIR_NPC_ID:5 u: Z  k% D7 W. Y/ i) z/ O; q8 k
  5.    n = getCount(st)- _4 K5 j# ~: O: v3 _
  6.    if   n == 0:
    % j  ?/ V: k3 L
  7.        return "Chat0.htm"
    1 `: n5 L$ G, u* q* a$ \3 `
  8.    elif n == 1:
    " E" q4 a5 I& b2 M
  9.        return "Chat1.htm"9 b9 n: i! `: @2 f- g& x" k4 [
  10.    elif n >= 4:
    : a) O- b( \+ E5 b7 [& a1 j
  11.        return "Chat4.htm"
    ' ]/ r7 c8 K* U. B/ j0 W
  12.    return "Collected "+str(n)+" of 4 fangs"" q: `1 ?; _4 x& z+ _% S* f2 J
  13. return
Скопировать код
Метод onKill (а так же метод onTalk) имеет следующие параметры:. E" C5 T8 _/ e
6 ?4 ]: Z4 }2 C& g: M; S  K' S

; Q, M$ g3 C: |' \# c* ~  [• self – квест
( O# Z6 J% u( X1 e4 g0 Y• npcId – ID NCP, которого мы должны убивать (если это метод onTalk, то ID того NCP, с которым мы должны поговорить).
# ~% \, m4 g# {2 _9 z5 t• st – текущее состояние игрока.
& n! k! A4 k. [+ _5 D1 T7 k( j% U' A0 @3 }0 U% `/ c2 o2 r! }
# K+ g" E; `. b3 ]* t, b. I
В этом методе мы проверяем и отмечаем, является ли убитый NCP keltir’ом. В основном эта проверка не нужна, т.к. у нас только KELTIR_NPC_ID.0 Z# n, j! l/ }0 a) y3 ~' |: I
7 ]. \3 @- g- c' S% _# T% [7 C

: d% t, o3 K! A) f4 @# j0 |, _Затем проверяем количество предметов (в данном случае количество клыков), и если их вообще нет, то возвращаем строку "Chat0.htm", если только один предмет, то возвращаем строку "Chat1.htm", если же предметов 4 или больше, то "Chat4.htm". Если строка возвращена из методов onEvent, onKill или onTalk, то сервер покажет соответствующие htm. В Chat0.htm может иметь следующий текст: «Вы не имеете ни одного клыка, возвращайтесь позже, когда соберете 4 штуки и бла, бла, бла…», в Chat1.htm может быть следующий текст: «У Вас всего 1 клык, по этому соберите еще…». В Chat4.htm – «Вы собрали необходимое количество предметов, возвращайтесь к вашему тренеру, что бы завершить квест…»
' n; Z; r, r% K  L
* z% _5 `9 c0 d8 g* Z
: _( T$ R8 q' L. A9 c* r( ]* K
Примечание: если в строка return начинается с "<html>", то будет показана страничка html с текстом, который стоит далее. Так вместо:
5 d& l( g' S( T1 j" C# z3 areturn "Chat4.htm"" f' O5 B0 }7 O& L* T
5 e8 T: ?  x. q/ D, C% L

6 S8 Y" ]0 D$ k2 B( Jможно поставить:
: z- w; A' p# G9 @5 q7 T/ R) S
  1. return "<html><body>Return to your trainer to complete the quest</body></html>"
Скопировать код
Так же если строка заканчивается без .htm или в начале нет <html>, то текст будет выведен, как системное сообщение в окне чата. В нашем случае мы сделаем так, что бы при каждом убийстве keltik выводилось системное сообщение: «Собрано N из 4-х клыков».3 x* S% a$ J( \

6 \  l; W/ y; y) {1 O7 s5 B* B
1 h( X; @9 h1 ~! q- @1 i% w
Наш код для onKill имеет один недостаток. Он будет постоянно показывать Chat0.htm, Chat1.htm и Chat4.htm, нам же необходимо, что бы Chat0.htm и Chat1.htm показывались только один раз. Как нам это сделать? С помощью переменных.$ `4 k" _+ ]. q" U' {. `0 T- L

3 I) o3 d/ ?% K. @9 J% ?9 Y
6 B4 v2 h/ I+ z% N
В каждом квесте строки могут храниться с помощью переменных. Эти переменные сохраняются в Вашей БД. В каждом методе мы можем назначить, прочитать и удалить переменные. Давайте изменим метод onKill, так что бы каждый диалог вызывался только один раз.
# ^: w: J# W" U3 `
  1. def onKill (self,npcId,st):
    2 K6 E( c; E% M5 Z7 Y1 P% u0 X
  2. if npcId == KELTIR_NPC_ID:6 V; g* v7 _+ {. p
  3. n = getCount(st)8 r: k! [" v: \- ]. P. Z8 \
  4. if n == 0:
    9 L3 O4 k6 e, {3 P) Q
  5. if st.get('chat0') == None :6 O# n3 E; j2 }1 `& \" t
  6. st.set("chat0", "true")! a2 z4 V  W5 O4 l1 x
  7. return "Chat0.htm"
    5 r0 v# ?4 {* h1 f4 P: j
  8. elif n == 1:
    6 Z% f- a& q8 f( g/ a
  9. if st.get('chat1') == None :
      g" _" ]) U: E& E
  10. st.set("chat1", "true")
    1 i3 y: L1 W  t2 O6 P, F
  11. return "Chat1.htm"/ u. [3 `3 }5 I3 O& s3 S# t  A
  12. elif n >= 4:
    7 z, Q/ g% v& g/ L& q
  13. return "Chat4.htm"4 H% R2 {( @3 I0 u. ~' _  H
  14. return "Collected "+str(n)+" of 4 fangs"  p& p) e! w8 h8 I
  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.9 B4 ]' c2 u" s: X

3 y, N1 G" X6 `- `5 G; f' T
% d+ e5 P0 ]( t
Вот конечный рабочий вариант квеста:/ ?, Y" j6 ?1 @  n
  1. import sys
    % U! c) G9 ?1 V6 t0 @# o8 e
  2. from net.sf.l2j.gameserver.model.quest import State
    * c7 t' S4 I6 E5 ]4 s) A
  3. from net.sf.l2j.gameserver.model.quest import QuestState
    ( n( U  D: n4 S1 d/ x
  4. from net.sf.l2j.gameserver.model.quest.jython import QuestJython as JQuest/ {1 H& t- O* X  s  k+ G! X2 a
  5. : H' y6 i! i  s! {' u8 r+ P
  6. KELTIR_NPC_ID = 12082
    4 X6 Z3 P8 _. j2 M5 d
  7. FANGS_ITEM_ID = 1859
    & h' R0 B( I" ~0 l" D+ S$ r
  8. DROP_RATE    = 500000
    , M3 J, `3 Q3 E$ ]

  9. , Z$ s; t1 Y! {3 K( @3 N& |5 C
  10. WORLD_MAP_ITEM_ID = 1665$ W+ M" _# S, U2 ~) l

  11. + @  \/ ?! Y2 @8 N# Q
  12. def getCount(st) :  M  H6 x+ N; ]$ n
  13. return st.getQuestItemsCount(FANGS_ITEM_ID)
    + N' p! k( w3 p# F
  14. / r- N1 P+ S/ V# i! q* Z
  15. def completed(st) :* z$ v3 ?3 h/ G$ E' `
  16. st.setState(COMPLETED)
    ! N0 A! i( I) i: [- z& I, v! z
  17. st.clearQuestDrops(): x/ \9 c4 [; N& \; `+ @
  18. st.takeItems(FANGS_ITEM_ID,-1): `; O9 o4 t9 L. z* Z& o
  19. st.giveItems(WORLD_MAP_ITEM_ID,1)9 j+ l: m, G+ {- H0 V4 Y
  20. st.exitQuest(False)6 ~( ?- e- j" A( z& e
  21. return" Y) X4 t0 [" ^" ?7 H
  22. " F: p% q, _- m1 x+ T7 _
  23. def check(st) :
    - d) n" {; S/ ]( y1 Q
  24. if getCount(st) >= 4 :+ w3 R5 Q- u& f4 e
  25. completed(st)
    ! O3 `2 A' I! ]# O& m
  26. return2 j! J& q7 {0 o  ?  k8 \

  27. 8 y: K4 h- y/ Z& v: Y
  28. class Quest (JQuest):4 b8 k6 B8 K- T

  29. 7 S8 {7 k/ Q2 f2 N2 r6 L
  30. def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)' B# `$ w# G# Q1 E3 @% b
  31. 4 _1 x- }3 i: J! r0 G! _
  32. def onEvent (self,event,st):
    , O' d% L4 C* r4 L
  33. id = st.getState()+ A! @9 O1 i- `8 T" z
  34. if id == CREATED : st.setState(STARTED), x- k* T1 X5 E  W3 Y
  35. elif id == COMPLETED: pass
    2 R. j1 q. V5 u$ ?+ k
  36. elif id == STARTED : check(st), A7 a7 |* @' P: x0 ~
  37. return) B' y+ B& k7 |  j5 z
  38. ; q# U/ t; ], j4 F2 e
  39. def onKill (self,npcId,st):
    # p* b1 ]# z' m2 i! P
  40. if npcId == KELTIR_NPC_ID:) c1 Y/ `0 ^6 k( L- t! p
  41. n = getCount(st)& `- e* [' A( j0 l9 y$ Y$ ^
  42. if n == 0:
    " @, b7 X6 A; G2 u% o
  43. if st.get('chat0') == None :! v+ _% `, U" `2 W1 d4 d( F
  44. st.set("chat0", "true")7 Y( Z; e; T; c5 q: v6 w
  45. return "Chat0.htm"
    ; d* E$ u- p2 u2 \* `
  46. elif n == 1:: Y/ V8 z% c9 Y. u  x
  47. if st.get('chat1') == None :9 q$ D  {* F3 [2 E1 p4 d9 d+ r  K. k
  48. st.set("chat1", "true")5 ^: ~) S9 _7 F) x+ X& p
  49. return "Chat1.htm"9 G6 w$ s( q. X- _7 t
  50. elif n >= 4:" D$ g& p5 B8 t9 L
  51. return "Chat4.htm"9 i$ ?' x+ x  V( a% B
  52. return "Collect "+str(n)+" of 4 fangs"
    5 s; W- _6 Z1 x
  53. return
    7 R- H% G4 c5 m& n* F
  54. + `/ |: r, d* A7 F0 B
  55. QUEST    = Quest(201, "Tutorial", "Tutorial quest")
    4 j/ t, k7 W, d* e
  56. CREATED = State('Start',    QUEST)4 V0 J8 i& V; J+ b( C* h& }
  57. STARTED = State('Started', QUEST). ~# u  E8 d6 M& g7 A! r
  58. COMPLETED = State('Completed', QUEST)
    + o0 C0 e6 |& g
  59. 1 c- s' u0 _+ Q2 j/ A$ g! ]
  60. QUEST.setInitialState(CREATED)
    - L2 }1 A7 R4 B* X; H$ H. P. G, R
  61. QUEST.addStartNpc(7056)" @( J  }# {" b
  62. QUEST.addStartNpc(7012)
    , L' i( [( g; E) r- B' H
  63. QUEST.addStartNpc(7009)2 J# ?: c6 y& X% n# o5 L. K/ Q
  64. QUEST.addStartNpc(7011)* ^- l7 d/ M8 a. n6 O

  65. ) E# v" ]: L4 Z
  66. STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
    ) i. L) U3 @/ @0 F: v
  67. STARTED.addKillId(KELTIR_NPC_ID)( R! p1 q" i7 a% G% k" R$ F, K
  68. STARTED.addTalkId(7056)$ a. L8 r% [; d; ~
  69. STARTED.addTalkI d(7012)
    . Q9 r* ~1 @6 G* W0 L3 O" S
  70. STARTED.addTalkId(7009)
    . \& m) X& o9 m' s
  71. STARTED.addTalkId(7011)
Скопировать код
4 T2 @3 J6 M# o% d& f5 r% y

. R& I' ^8 `, H" T
Чтобы ответить, вам надо авторизироваться в системе Вход | Зарегистрироваться

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

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

638638758

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

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

admin@artace.ru Онлайн

QR-код

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