Top.Mail.Ru

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

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

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

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

x
Хроники        Interlude# i- I  w0 o2 ~! A- K. x/ G1 S
Сборка        L2j
) Y& s. }9 A, c1 Z8 X+ l) QОбратите внимание: в файле htm стартового NCP обязательно должна быть ссылка на квест:
5 c9 Q2 Z' @; J/ {* R
  1. STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код
Для этого квеста больше ничего не надо. Все необходимое для корректной работы квеста уже добавили. Вот полный текст квеста:4 j" R% z7 E& l, k3 |
5 F( z8 X1 T4 p1 c3 \
  1. if getCount(st) >= 4 :7 Z# _/ }  K5 N
  2. completed(st)
    $ K5 u, d. b: O: S
  3.   return) J; B* c. H4 T  V+ L6 o! Y

  4. 7 ?- y8 Q0 U3 v0 `  Y, P9 d
  5. class Quest (JQuest):% c/ m1 K% Q$ K. Z( O4 l
  6.   def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)
    ' D- M$ c# m! g- `- O
  7.   def onEvent (self,event,st):
    ' ^7 u* F7 I4 T9 U: G
  8. id = st.getState()
    ( p( n9 D3 r7 L) v
  9. if   id == CREATED  : st.setState(STARTED)$ o$ J8 h  @) S5 F  t
  10. elif id == COMPLETED: pass
    " r' d4 ]% D6 T
  11. elif id == STARTED  : check(st)+ Y3 m: v$ `2 W8 k' l6 [+ D' ]
  12. return
    - t9 V" z0 D: z! }4 P! j6 x
  13. + M. o1 G/ {9 l7 n8 E6 k
  14. QUEST     = Quest(201,"Tutorial", "Tutorial quest")
    ; Y+ Q) P) Y+ m/ [6 @
  15. CREATED   = State('Start',     QUEST)
    0 [' Y* \3 Z: r, K* D
  16. STARTED   = State('Started',   QUEST)
    & l. u# k, G& [( o' }* l
  17. COMPLETED = State('Completed', QUEST)* s+ Q( v2 U" E& }$ q0 J

  18. ) K! b1 q& x$ x2 n* l) j7 M, d
  19. QUEST.setInitialState(CREATED)) r( X9 P. F2 n+ f. l: T
  20. QUEST.addStartNpc(7056)
    " }# |- J' J% d& J0 ^$ C2 I) F/ b
  21. STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код
Теперь рассмотрим, как это работает.( g5 A' |5 O% S
Игрок подходит к начальному NCP (в данном случае 7056), нажимает на «Quest». Квест будет создан и состояние квеста перейдет к CREATED и игроку будет показана страничка Start.htm с описанием квеста. Тогда метод onEvent, поле открытия странички Start.htm переведет состояние квеста в STARTED и игроку будет показана страничка Started.htm, где будет опсание того, как найти keltirs и .т.д.
& s* F. x) w5 {; f; y1 P4 D" M
9 D) o* b# T* J' s) ?- z
: j, W; G4 D9 u
При состоянии STARTED будет зарегистрирован дроп «fangs» при убийстве keltirs. Игрок может вернуться к стартовому NCP и спросить о квесте – метод onEvent будет вызван снова. Если у игрока не хватает необходимого количества предметов, то метод check() не переведет квест в следующее состояние и Started.htm будет показана снова. Но если игрок собрал необходимее количество предметов (в данном случае 4 клыка), то метод check() вызовет метод completed() который переведет квест в новое состояние COMPLETED, заберет все клыки, даст карту мира, т.к. это награда за квест, покажет Completed.htm и завершит квест.* P$ l- q4 V9 Q' p: m
$ U( _6 I1 U6 c) \

/ r7 L1 V2 y: l) c! BТеперь давайте сделаем наш квест более похожим на то, что он должен из себя представлять.( u* D& K* v9 F# r3 u5 [
Прежде всего у нас есть 3 метода для объявления их в Яве – onTalk, onKill и onEvent. Если методы onTalk и onKill не объявлены, то за них все будет делать метод onEvent, т.е. определять квестовых монстров и вызывать диалоги NCP. Есть примечание, методы onTalk и onKill будут вызывать только диалоги с NCP в зависимости от текущего состояния квеста. Метод onKill будет вызываться только тогда, когда мы убиваем квестового монстра.
& h- I) ]  a6 b" ]) r/ s
- F" M# H9 Y: B7 W

# l% S: P  ~% s/ a% MДавайте рассмотрим как вызывается метод onKill при убийстве keltir в состоянии квеста STARTED:
4 W2 f( j8 q6 O- q: U+ o2 N) F/ E$ F
  1. STARTED.addKillId(KELTIR_NPC_ID)
Скопировать код
и метод onKill в классе Quest:+ P. G, P+ O$ }, l& w* @9 K$ [, D' R

4 S+ ~7 \+ ]$ Y# V6 ~. |1 w7 [- p
  1. class Quest (JQuest):+ s5 O, A$ u2 g0 S2 Q
  2.   ...: D' M; B4 _) d( w
  3.   def onKill (self,npcId,st):: V+ r# S( p# ~- i0 Y" r
  4. if npcId == KELTIR_NPC_ID:
    * e5 X" }! w: M9 e. t$ I
  5.    n = getCount(st)
    / Q! X' }! G* S+ h( R$ n
  6.    if   n == 0:
    ' y# u" o* W6 Z- a2 M
  7.        return "Chat0.htm"& r! }1 p1 l4 S% E5 ?/ U
  8.    elif n == 1:
    # f7 k; W$ X* D
  9.        return "Chat1.htm"% ~5 }( G6 p2 Y6 |1 {% ]5 [* q+ v, m
  10.    elif n >= 4:- N+ S' l# f2 V! e& A6 Y
  11.        return "Chat4.htm"
    # ?0 O' L4 H/ {; e8 p
  12.    return "Collected "+str(n)+" of 4 fangs"
    1 M. U1 n* g1 `5 S$ I; _
  13. return
Скопировать код
Метод onKill (а так же метод onTalk) имеет следующие параметры:
+ N% l( L8 R6 R5 F) ~1 b& T3 B5 e' I1 s' m" e

2 v: U9 ?2 c: h% x• self – квест
- X3 o8 f9 @, x. f+ s• npcId – ID NCP, которого мы должны убивать (если это метод onTalk, то ID того NCP, с которым мы должны поговорить).
; r8 {# t( S/ a( `6 j4 `: x6 m% s• st – текущее состояние игрока.
, l4 x; Y/ \7 b% W6 d, F3 y
" v8 \2 s+ B& ~8 j6 i9 |: J
3 X% m6 l! P+ Q6 a6 b8 Y
В этом методе мы проверяем и отмечаем, является ли убитый NCP keltir’ом. В основном эта проверка не нужна, т.к. у нас только KELTIR_NPC_ID.& c" F8 w7 A+ o' R# [

/ Y2 l+ E. ?8 q. P. f/ r

& Y+ P) G# R9 [2 M; Y* fЗатем проверяем количество предметов (в данном случае количество клыков), и если их вообще нет, то возвращаем строку "Chat0.htm", если только один предмет, то возвращаем строку "Chat1.htm", если же предметов 4 или больше, то "Chat4.htm". Если строка возвращена из методов onEvent, onKill или onTalk, то сервер покажет соответствующие htm. В Chat0.htm может иметь следующий текст: «Вы не имеете ни одного клыка, возвращайтесь позже, когда соберете 4 штуки и бла, бла, бла…», в Chat1.htm может быть следующий текст: «У Вас всего 1 клык, по этому соберите еще…». В Chat4.htm – «Вы собрали необходимое количество предметов, возвращайтесь к вашему тренеру, что бы завершить квест…»* V6 E0 D5 u) c; M

% m8 L" Q) \- A4 D

' K' x  O5 k; mПримечание: если в строка return начинается с "<html>", то будет показана страничка html с текстом, который стоит далее. Так вместо:3 F# S  Z3 P- j6 l7 M
return "Chat4.htm", _+ ]# N, N" J9 u& v* c1 z
- c. g! K1 |& J% J

6 P- L9 [& @9 c3 uможно поставить:! r) O/ a! J- x2 s
  1. return "<html><body>Return to your trainer to complete the quest</body></html>"
Скопировать код
Так же если строка заканчивается без .htm или в начале нет <html>, то текст будет выведен, как системное сообщение в окне чата. В нашем случае мы сделаем так, что бы при каждом убийстве keltik выводилось системное сообщение: «Собрано N из 4-х клыков».
5 j' ~3 ^3 l  v4 L. o* m( {% D1 I
8 @0 l& V( B9 ~: Q% r. X

/ e+ C( V0 o& P7 L! S. {+ R* gНаш код для onKill имеет один недостаток. Он будет постоянно показывать Chat0.htm, Chat1.htm и Chat4.htm, нам же необходимо, что бы Chat0.htm и Chat1.htm показывались только один раз. Как нам это сделать? С помощью переменных.
2 `) N% F2 a; ~4 E* r9 t& F* S  A3 T* m
" @% Y& B# ?* H* t( R, Y" b# G9 f
В каждом квесте строки могут храниться с помощью переменных. Эти переменные сохраняются в Вашей БД. В каждом методе мы можем назначить, прочитать и удалить переменные. Давайте изменим метод onKill, так что бы каждый диалог вызывался только один раз.
: g$ w7 q9 m5 u2 o
  1. def onKill (self,npcId,st):
    8 i. [8 F$ O1 H6 z3 `& H# v6 u, Q
  2. if npcId == KELTIR_NPC_ID:3 s) Q0 q$ h# X) Q) J
  3. n = getCount(st)
    / `2 N; }7 [7 f% m
  4. if n == 0:4 B3 {, {5 \2 n+ h9 o
  5. if st.get('chat0') == None :
    1 k- @3 J/ _( V
  6. st.set("chat0", "true")
    4 L& C& \2 h3 }& h3 K0 m
  7. return "Chat0.htm"
    ) h! Y4 m+ _5 F% R( v3 L/ P
  8. elif n == 1:! U9 W" r* A0 A- V: ?' w8 d
  9. if st.get('chat1') == None :/ S# h( Q, {1 u: B8 ]& y
  10. st.set("chat1", "true")! R6 R! |7 K5 W4 o3 N- `7 I
  11. return "Chat1.htm"
    0 r8 b+ H. R& a0 s$ e
  12. elif n >= 4:
    * p. X- m6 n# L# I3 Z) ~% B
  13. return "Chat4.htm"
    1 ?+ ^. J. t, b
  14. return "Collected "+str(n)+" of 4 fangs"
    4 O2 s- I6 E: m* H2 M9 z5 @
  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.
% e6 X8 z7 j/ c, Y8 \+ I7 f/ x4 J* b

7 N6 s) m! O. A8 W# c% rВот конечный рабочий вариант квеста:
/ l) H* A! W. \1 z4 @* M7 d
  1. import sys
    & Z1 v  E- C7 |: k
  2. from net.sf.l2j.gameserver.model.quest import State
    : f# C8 i8 e( l
  3. from net.sf.l2j.gameserver.model.quest import QuestState
    " L# n3 ^/ ]) t$ k7 E) N
  4. from net.sf.l2j.gameserver.model.quest.jython import QuestJython as JQuest
    4 U5 X+ P3 B% e% F/ S' }
  5. ' W. V' I8 ^, C& {: s$ g
  6. KELTIR_NPC_ID = 12082
    9 f* M3 I- I* {; m1 b+ F
  7. FANGS_ITEM_ID = 1859/ _; h# @3 y# |$ s3 Z9 Z+ b
  8. DROP_RATE    = 5000001 M8 d$ s- k, a9 S
  9. 8 b+ e5 c( Y) \  s) B
  10. WORLD_MAP_ITEM_ID = 1665
    $ f4 R1 t0 B) X

  11. / o: ^: L4 X) H7 x5 o. r6 s
  12. def getCount(st) :
    " _( O4 i- {+ Z6 l) z* ?% T6 ^- `" K
  13. return st.getQuestItemsCount(FANGS_ITEM_ID), u/ S/ _; x- ~8 T
  14. 4 p6 C; R* B9 m3 V6 D- ?- u; f6 r
  15. def completed(st) :
    # d# |4 s0 v, O. n
  16. st.setState(COMPLETED)4 I. w: h" t$ L4 {& h
  17. st.clearQuestDrops()/ x/ m' L! ]: N* @- |
  18. st.takeItems(FANGS_ITEM_ID,-1)" d8 Y! l9 |2 \6 T1 a$ }& Q3 i
  19. st.giveItems(WORLD_MAP_ITEM_ID,1)9 g9 H' B/ y7 {$ X  Y# R
  20. st.exitQuest(False)7 ?+ k, \, f& D5 o1 r; x
  21. return
      S$ f( K" h) |9 D+ S) t
  22. 4 Q. G/ C$ K/ ^- ?6 {% R
  23. def check(st) :6 A' p' v" ]1 C# _
  24. if getCount(st) >= 4 :/ c# Y- M# s* X, M* B& u/ o
  25. completed(st)
    ! Q3 z3 P; ]6 l( t
  26. return
    - q$ _' l4 o. u! q4 O6 H
  27. % b6 ?; `4 ]  L3 k! H
  28. class Quest (JQuest):' m& [; n2 u4 [. W/ O$ B% A/ \
  29. * a. c# ]( v) q% C
  30. def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)
    ' }6 |0 J8 ]/ r" o
  31. 2 J" X: V, |" u
  32. def onEvent (self,event,st):
    1 K7 Y0 p# J' Y; i
  33. id = st.getState()
    3 o0 G% `8 u4 ?% o- y/ t" }
  34. if id == CREATED : st.setState(STARTED)
    ! l: r+ d0 M4 o) g3 ?
  35. elif id == COMPLETED: pass
    . u+ o$ H) P( g& u
  36. elif id == STARTED : check(st)
    6 J" V1 E# n: f
  37. return; ?- U( f( \3 Z3 `* X
  38. ! {# L1 Y  ~7 G
  39. def onKill (self,npcId,st):
    / h  C4 f7 j0 ?7 }- a, a7 Y9 f
  40. if npcId == KELTIR_NPC_ID:
    8 _! L$ T' s, }6 e4 I2 {; s3 i
  41. n = getCount(st)9 a% C3 X3 K! D" ]! v
  42. if n == 0:
    : r6 N: k. _) @% f1 m- k, m
  43. if st.get('chat0') == None :. W4 a2 \9 I. U8 j( ^+ a, s
  44. st.set("chat0", "true")+ ~; [: j! i9 D: S" @. y+ l
  45. return "Chat0.htm"/ o$ m, C0 O  l: e( R; y
  46. elif n == 1:( t8 k# Z( b$ k% [" ]/ W( e% M$ q
  47. if st.get('chat1') == None :
    + Q+ K+ S" J9 N, ?8 B6 J
  48. st.set("chat1", "true")
    9 d% M/ ?0 A, W3 K2 G- ]
  49. return "Chat1.htm"
    : `6 q0 M7 F1 _$ I; P
  50. elif n >= 4:7 n' E7 g; ~; a! N- E
  51. return "Chat4.htm"
    1 S7 V1 q, m  m! }$ a
  52. return "Collect "+str(n)+" of 4 fangs"! C; O" }1 K& ]8 G
  53. return$ Q$ L- J! P4 W. E# d! j& Z" q
  54. 2 k- Z0 L- U9 L8 R
  55. QUEST    = Quest(201, "Tutorial", "Tutorial quest")6 g: i6 |( E  ?$ y& n) z
  56. CREATED = State('Start',    QUEST)
    0 b! `- i! ?( T' J# c
  57. STARTED = State('Started', QUEST)5 g% z% I# ^0 F3 S4 @
  58. COMPLETED = State('Completed', QUEST)3 J6 t: c* G. L5 S' C

  59. ! q3 q1 `+ n$ t! n( j. I
  60. QUEST.setInitialState(CREATED)' {* {: w" L! y$ Y5 e% U
  61. QUEST.addStartNpc(7056)
    " w8 P' s5 \& J4 m
  62. QUEST.addStartNpc(7012)0 n5 e+ a* N' J3 X$ d
  63. QUEST.addStartNpc(7009)
    8 e# m' j& A4 F; N. S% o2 f% N
  64. QUEST.addStartNpc(7011)
    2 ]/ Q8 [  L  x: d7 g' J6 L
  65. * c2 O: w1 p' S
  66. STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)" q( ]3 H1 e5 e+ H3 E
  67. STARTED.addKillId(KELTIR_NPC_ID)% z8 _9 G/ b: ~/ u
  68. STARTED.addTalkId(7056)
      j" ~" T5 k! s. {, G
  69. STARTED.addTalkI d(7012)
    7 n" L  c  ^# a
  70. STARTED.addTalkId(7009)
      c! J/ `9 |! c8 k) g) J# p" O# B
  71. STARTED.addTalkId(7011)
Скопировать код

! v3 b# t7 z, h% w
/ {$ R% [) ]) a$ N: O
Чтобы ответить, вам надо авторизироваться в системе Вход | Зарегистрироваться

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

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

638638758

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

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

admin@artace.ru Онлайн

QR-код

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