Top.Mail.Ru

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

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

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

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

x
Хроники        Interlude
; f) |3 i  i* x! F0 y! o& i1 eСборка        L2j6 N% x8 M: b, Q6 n7 K
Обратите внимание: в файле htm стартового NCP обязательно должна быть ссылка на квест:
9 r) Y+ u: m$ J, b& C  G: l" A
  1. STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код
Для этого квеста больше ничего не надо. Все необходимое для корректной работы квеста уже добавили. Вот полный текст квеста:- @9 p$ f; y- b& p; W7 E* x
7 e+ q4 h1 B, W3 c7 i* F% ~- s
  1. if getCount(st) >= 4 :' S9 M& N# M, A4 u, C
  2. completed(st)
    6 J3 W- [. B+ S
  3.   return
    ! R. |/ z- u6 N

  4. , B0 T: u# M) X5 t! p- \
  5. class Quest (JQuest):
    # ?4 G+ p( }0 I  A' Z( i  b5 M  J
  6.   def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)
    - g* x- Q2 \' h
  7.   def onEvent (self,event,st):
    9 ^( Y- Q7 I* G- c! V8 T
  8. id = st.getState()! K% r6 o7 g' A
  9. if   id == CREATED  : st.setState(STARTED)2 @. ~$ p* b; F& @  P5 f
  10. elif id == COMPLETED: pass
    4 G( h6 O  Q4 T& U9 i; f
  11. elif id == STARTED  : check(st)+ p) C, H& J7 m
  12. return
    ; ~" G! P7 |: W, I* O; D
  13. : S% ^1 M% l5 h; p
  14. QUEST     = Quest(201,"Tutorial", "Tutorial quest")
    ; i, C: S' l, X
  15. CREATED   = State('Start',     QUEST)
    # u% S8 g/ v8 @, |3 [$ v3 A
  16. STARTED   = State('Started',   QUEST)
    / c. ~. M8 d- o5 Q! E; m3 S2 P) L
  17. COMPLETED = State('Completed', QUEST)
    9 E& [$ }" C# g& g" L

  18. ! i/ c/ E+ B/ u
  19. QUEST.setInitialState(CREATED). F) P4 v+ o. M) @! ]" m& O
  20. QUEST.addStartNpc(7056)/ e; [* [4 N* p. M9 {/ C
  21. STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код
Теперь рассмотрим, как это работает.
& x' ]4 A: M' k1 HИгрок подходит к начальному NCP (в данном случае 7056), нажимает на «Quest». Квест будет создан и состояние квеста перейдет к CREATED и игроку будет показана страничка Start.htm с описанием квеста. Тогда метод onEvent, поле открытия странички Start.htm переведет состояние квеста в STARTED и игроку будет показана страничка Started.htm, где будет опсание того, как найти keltirs и .т.д.2 M" _4 q2 E; X) u* m* X& R3 ?/ R

6 j! m: n( _# J

* z' _, g0 K5 p& |7 x; Q; ^) MПри состоянии STARTED будет зарегистрирован дроп «fangs» при убийстве keltirs. Игрок может вернуться к стартовому NCP и спросить о квесте – метод onEvent будет вызван снова. Если у игрока не хватает необходимого количества предметов, то метод check() не переведет квест в следующее состояние и Started.htm будет показана снова. Но если игрок собрал необходимее количество предметов (в данном случае 4 клыка), то метод check() вызовет метод completed() который переведет квест в новое состояние COMPLETED, заберет все клыки, даст карту мира, т.к. это награда за квест, покажет Completed.htm и завершит квест.( P6 f- j. A7 v
, M* X) E4 Y2 r6 p9 ~4 x6 e" K
. u4 k& C4 P7 q3 i3 h4 B
Теперь давайте сделаем наш квест более похожим на то, что он должен из себя представлять.: X0 k" s% S2 O1 Z5 N, X
Прежде всего у нас есть 3 метода для объявления их в Яве – onTalk, onKill и onEvent. Если методы onTalk и onKill не объявлены, то за них все будет делать метод onEvent, т.е. определять квестовых монстров и вызывать диалоги NCP. Есть примечание, методы onTalk и onKill будут вызывать только диалоги с NCP в зависимости от текущего состояния квеста. Метод onKill будет вызываться только тогда, когда мы убиваем квестового монстра.
/ _  L* ?$ [- N$ `* N8 k
7 |' {( F, [$ R9 l* ]- J
+ z% [$ [7 V6 p$ s
Давайте рассмотрим как вызывается метод onKill при убийстве keltir в состоянии квеста STARTED:
; K3 B7 b9 Q. F3 _
  1. STARTED.addKillId(KELTIR_NPC_ID)
Скопировать код
и метод onKill в классе Quest:, N& c- P- ]. q; a

1 x- h- X1 x! I3 _
  1. class Quest (JQuest):& ^% D1 w5 ?, L
  2.   ...
    % t8 `" U) S; v" w4 l
  3.   def onKill (self,npcId,st):
    . O& o2 L7 c6 X, d6 v5 \* ^
  4. if npcId == KELTIR_NPC_ID:
    * ~, x0 X+ X; t; H
  5.    n = getCount(st)' Q- k2 O3 Y) r- o  A% m0 R
  6.    if   n == 0:
    * _* p% w: W/ Q7 N
  7.        return "Chat0.htm"8 t: ^# ^/ l! p1 A3 C. J" q
  8.    elif n == 1:
    # ~* [' H- j% L- U$ H, ^/ G5 f. `
  9.        return "Chat1.htm"% u8 |2 d- {9 t- q; }
  10.    elif n >= 4:
    / n4 M8 w6 _  f& D# m0 P5 K
  11.        return "Chat4.htm"6 S  M# H# l! `/ q: P
  12.    return "Collected "+str(n)+" of 4 fangs"
    ' n* n  t6 C  R5 I) f
  13. return
Скопировать код
Метод onKill (а так же метод onTalk) имеет следующие параметры:
5 P8 I& H% g) Z& z3 p9 w$ Y
  m% @, ~: ^" I/ V+ l

! X  r! r; Q$ l! y  @  d, }/ s• self – квест$ Q7 X% G4 C7 n
• npcId – ID NCP, которого мы должны убивать (если это метод onTalk, то ID того NCP, с которым мы должны поговорить).. g1 T8 V+ t3 V1 ?+ S+ {
• st – текущее состояние игрока.
8 s' E$ D; S/ Q# k
) W" x- P" l+ r7 B9 x/ r# ^
7 d- f# _% V$ O8 n% q
В этом методе мы проверяем и отмечаем, является ли убитый NCP keltir’ом. В основном эта проверка не нужна, т.к. у нас только KELTIR_NPC_ID.
" J- D+ L9 m* _, v. C+ Q
& ^0 P+ _  u' u6 a
' {' D1 i, j8 _  F$ `
Затем проверяем количество предметов (в данном случае количество клыков), и если их вообще нет, то возвращаем строку "Chat0.htm", если только один предмет, то возвращаем строку "Chat1.htm", если же предметов 4 или больше, то "Chat4.htm". Если строка возвращена из методов onEvent, onKill или onTalk, то сервер покажет соответствующие htm. В Chat0.htm может иметь следующий текст: «Вы не имеете ни одного клыка, возвращайтесь позже, когда соберете 4 штуки и бла, бла, бла…», в Chat1.htm может быть следующий текст: «У Вас всего 1 клык, по этому соберите еще…». В Chat4.htm – «Вы собрали необходимое количество предметов, возвращайтесь к вашему тренеру, что бы завершить квест…»! u' u# m  w9 w* j

8 X0 ]+ X6 Q0 L$ f! a1 f% D
* A% N8 \4 `" {! |0 l9 X
Примечание: если в строка return начинается с "<html>", то будет показана страничка html с текстом, который стоит далее. Так вместо:
$ ~0 Q0 T! s/ a  k4 T6 S5 x, ?3 Treturn "Chat4.htm"
  Y- A  W( K1 s6 l* W! J3 g" P7 ^% }8 j
* r. ]2 V7 J) A6 P% h/ {: D
можно поставить:4 Q% Z; Q' V+ q$ c8 i+ j
  1. return "<html><body>Return to your trainer to complete the quest</body></html>"
Скопировать код
Так же если строка заканчивается без .htm или в начале нет <html>, то текст будет выведен, как системное сообщение в окне чата. В нашем случае мы сделаем так, что бы при каждом убийстве keltik выводилось системное сообщение: «Собрано N из 4-х клыков».
+ S5 _! R  {+ `3 M/ i
( F" n9 `) c1 S6 ^- \$ h" A1 W

9 A+ L' ~8 }  m# d' k4 G: `Наш код для onKill имеет один недостаток. Он будет постоянно показывать Chat0.htm, Chat1.htm и Chat4.htm, нам же необходимо, что бы Chat0.htm и Chat1.htm показывались только один раз. Как нам это сделать? С помощью переменных.0 p$ b; E  D" a2 j; e' N

% u9 e+ x' c; U, r
9 R6 ^1 v# j' w, }0 I/ b
В каждом квесте строки могут храниться с помощью переменных. Эти переменные сохраняются в Вашей БД. В каждом методе мы можем назначить, прочитать и удалить переменные. Давайте изменим метод onKill, так что бы каждый диалог вызывался только один раз.
1 g4 z: s9 ]$ @+ R6 y. W' j" y
  1. def onKill (self,npcId,st):
    9 R# R; t. O4 A+ u# n* \* f
  2. if npcId == KELTIR_NPC_ID:
    4 s7 r' \  o& J, x' R% O% m
  3. n = getCount(st)
    6 L! T" \0 _5 C, i, m* |! e4 t) Z
  4. if n == 0:4 g% J: x+ O4 v2 S" _& @
  5. if st.get('chat0') == None :
      l& x) H  K' ?. z# G& Z
  6. st.set("chat0", "true"): j8 g, o- _8 v0 r) o0 e
  7. return "Chat0.htm"+ m, P: T6 F/ j( W5 z
  8. elif n == 1:; ?3 A$ @" o* a9 I4 T
  9. if st.get('chat1') == None :
    9 A, G- p/ w8 `9 ?+ Y: [9 I* r
  10. st.set("chat1", "true")8 s% h# {, m; H! Y8 d
  11. return "Chat1.htm"- G0 C) f  |- h5 T1 v
  12. elif n >= 4:" c4 t4 d1 \, B% Y( {5 w, L& @
  13. return "Chat4.htm"
    8 }! W1 D$ U& p5 V% D# L
  14. return "Collected "+str(n)+" of 4 fangs"
    : G8 d( O" O) ^0 g6 V
  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.
# i& w( a' L, q. [  P' k3 ]3 d2 G
8 S8 N- {% T+ K3 d

& p) `) t. @7 c* X- hВот конечный рабочий вариант квеста:/ \) C+ j% J* m, e( ~
  1. import sys6 n# V% a. f! o& A
  2. from net.sf.l2j.gameserver.model.quest import State8 m1 |+ k, }) X+ }# p2 ^
  3. from net.sf.l2j.gameserver.model.quest import QuestState" u; m9 W+ g% p# l# N/ @( |
  4. from net.sf.l2j.gameserver.model.quest.jython import QuestJython as JQuest
    / R2 w# G* V' U

  5. 5 B) Y9 _' H) X9 a% i
  6. KELTIR_NPC_ID = 12082& ~+ d4 E  F8 L4 _7 S
  7. FANGS_ITEM_ID = 1859
    * W: o" J) A- C+ `+ S* V
  8. DROP_RATE    = 500000" G( k( s1 _% l. C6 U% @! d2 u0 n1 y( M

  9. / s) s7 v$ @9 k+ |
  10. WORLD_MAP_ITEM_ID = 1665
    & `$ Z& \7 O( D. v" J* y2 o

  11. + C! C: B1 f5 A4 _2 b0 O. G
  12. def getCount(st) :
    7 t$ q+ N! @& n+ P, e% W: N5 g$ O2 G/ l
  13. return st.getQuestItemsCount(FANGS_ITEM_ID)
    . d& `" {$ o9 j: k
  14. ; o8 U; ?0 V( U+ k2 T7 M& _5 x
  15. def completed(st) :- P- f; `. Y$ V2 u% Y. ?  \
  16. st.setState(COMPLETED)# A4 ?: R6 ?! i) z3 t  ]( Y* r
  17. st.clearQuestDrops(). t) O9 }7 T9 J$ a3 ^6 S
  18. st.takeItems(FANGS_ITEM_ID,-1)
      W& U$ c5 E  I, q
  19. st.giveItems(WORLD_MAP_ITEM_ID,1)
    / _: X. z, i+ y/ f) |' v/ V- f
  20. st.exitQuest(False)
    + n+ R$ E5 C  L) U7 z1 G
  21. return
    . x4 j! F0 v4 v' Y; e
  22. ) F: u6 ^2 c9 J4 t9 E
  23. def check(st) :1 l. W/ y- t9 i7 \3 l' d( |9 w
  24. if getCount(st) >= 4 :  B! ^- Q9 ?) v4 n+ r% j- l+ A- {( U
  25. completed(st)
    , Q- C6 Y& E: B5 H9 q6 t
  26. return
    ' f: y/ d2 h' q) q9 |

  27. 9 t8 d7 n2 P0 ?5 Y+ }& v& C
  28. class Quest (JQuest):
    " f6 N2 i5 c! p# G

  29. * L* S+ X/ m& O0 p
  30. def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)+ @( V" [1 M+ p/ f9 P3 J  S2 Q
  31. * @/ v7 G7 s; m8 X
  32. def onEvent (self,event,st):0 X9 j7 M9 ~) x5 G
  33. id = st.getState()$ \$ W8 x1 ^7 b# k1 g
  34. if id == CREATED : st.setState(STARTED)
    , e2 R! \% S" L9 |
  35. elif id == COMPLETED: pass
    7 c7 K! o9 ?4 S7 L  l
  36. elif id == STARTED : check(st)* Z0 c+ M/ k0 W# ^0 f
  37. return" K1 T, S( @4 Y4 e& u2 s8 ]' z% B% V0 E
  38. / I6 O/ L( b% X3 ~" }7 ^9 M; `8 G
  39. def onKill (self,npcId,st):0 ^3 K  P4 J# }/ r
  40. if npcId == KELTIR_NPC_ID:
    . l  ]1 h9 i8 L- }9 Q, x
  41. n = getCount(st)
    ' W9 K8 A0 y, ?: q6 E5 P. U4 {
  42. if n == 0:( ~' B8 E7 R+ f& \4 S0 N
  43. if st.get('chat0') == None :
    - |6 h% [& J& f
  44. st.set("chat0", "true")
    2 y! G, _. i1 [0 b" v
  45. return "Chat0.htm"
    : A% R6 {. I$ D4 ^) k
  46. elif n == 1:- W5 w8 J8 M+ S* w: F
  47. if st.get('chat1') == None :
    : G( V  P& [  H  W5 Q
  48. st.set("chat1", "true")
    + F! Y  L8 q' R$ i- K& @! b# E6 z
  49. return "Chat1.htm"
    # q4 X& |8 g5 R
  50. elif n >= 4:
    0 m: b& K- X: F4 j  ?3 l' v, U
  51. return "Chat4.htm") [4 u5 }$ `1 d" p$ A! _& K
  52. return "Collect "+str(n)+" of 4 fangs"
    ) A. K3 K' z( J- ~8 O! ?
  53. return. M; y! B) \/ m/ c7 i
  54. 3 ?* R1 O. R% \% j& {. q" G7 x& C$ J
  55. QUEST    = Quest(201, "Tutorial", "Tutorial quest")
    / E6 p3 _6 U, j! {2 c% @
  56. CREATED = State('Start',    QUEST)
    8 ?& c3 F. ~# n9 S' r8 H+ j; S
  57. STARTED = State('Started', QUEST)
    ( Z7 c! L  U0 N- ]+ R3 x1 a& ~
  58. COMPLETED = State('Completed', QUEST)
    7 _- |8 D1 @/ q% Q7 `  w

  59. % ]: m; d- h$ z; N$ u, F8 s
  60. QUEST.setInitialState(CREATED)
    & [+ h8 h$ o+ ~4 |6 P& u' B
  61. QUEST.addStartNpc(7056), N% L6 l" {* h3 I- ?
  62. QUEST.addStartNpc(7012)
    ( ^2 J" I) n2 D9 t
  63. QUEST.addStartNpc(7009)
    : l! Z  Q5 U- D/ P
  64. QUEST.addStartNpc(7011)
    . f$ ~8 a8 Q2 Y  z& p

  65. 6 i$ J- ~( q: M5 {% s- y! ~# I7 {
  66. STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)0 d3 c4 h* h* z4 c# h( Z. a- H
  67. STARTED.addKillId(KELTIR_NPC_ID)
    9 X( |3 r' j( j$ _0 F) B: P
  68. STARTED.addTalkId(7056)' h" q( P5 B) X7 ?7 v
  69. STARTED.addTalkI d(7012)
    : k3 G: l) V! @- M+ x/ ^) M
  70. STARTED.addTalkId(7009)
    1 j  P0 j; Y/ k7 A
  71. STARTED.addTalkId(7011)
Скопировать код

+ G& G% u2 `. i
  v5 b# _7 M# I" u+ K5 N5 s
Чтобы ответить, вам надо авторизироваться в системе Вход | Зарегистрироваться

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

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

638638758

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

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

admin@artace.ru Онлайн

QR-код

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