Top.Mail.Ru

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

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

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

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

x
Хроники        Interlude
5 s' p6 n! K8 j+ b  x& d( tСборка        L2j% ^2 Z9 C7 Q4 C* \
Обратите внимание: в файле htm стартового NCP обязательно должна быть ссылка на квест:$ x. ]0 O1 \' g( w- t1 r
  1. STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код
Для этого квеста больше ничего не надо. Все необходимое для корректной работы квеста уже добавили. Вот полный текст квеста:/ u, ~" u5 q! c. o2 F5 {
' c$ D$ ^$ B+ v+ K: M
  1. if getCount(st) >= 4 :
    1 g) ^2 |4 f7 z0 M. b; p
  2. completed(st)
    1 c* w* R* A9 y& {$ u
  3.   return0 |0 c6 V5 g8 W- F! A. ~; S
  4. ( t8 ?6 Y- c; j
  5. class Quest (JQuest):
    0 w+ t+ V4 N/ W1 O
  6.   def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)
    : e1 n6 O6 L4 M  R
  7.   def onEvent (self,event,st):) S2 C# q: {/ g& I3 _  n) J
  8. id = st.getState()& X+ [' \0 K" z& v
  9. if   id == CREATED  : st.setState(STARTED)
    : M6 n& v6 R3 r
  10. elif id == COMPLETED: pass5 s4 w7 }) I3 M! N* W' K6 A
  11. elif id == STARTED  : check(st)
    6 O0 n! D- r/ U. Q# H% ]
  12. return8 N* a0 L: l* E$ `
  13. : z1 x0 [0 C$ G; P
  14. QUEST     = Quest(201,"Tutorial", "Tutorial quest")
    ' Y2 ?7 J, O) s! a; v" x) r# J
  15. CREATED   = State('Start',     QUEST)
    / M' Q* {% m0 q5 {
  16. STARTED   = State('Started',   QUEST)
    + ]. l3 a2 M9 X( p% d
  17. COMPLETED = State('Completed', QUEST)( l% C5 u) v2 F  K

  18. - u% u5 N- u1 x) C# g
  19. QUEST.setInitialState(CREATED)8 [# Q! n7 q' Q% ?
  20. QUEST.addStartNpc(7056)$ h4 }  t& W/ s9 G& a
  21. STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код
Теперь рассмотрим, как это работает.
0 v4 \* u+ a  d0 g" OИгрок подходит к начальному NCP (в данном случае 7056), нажимает на «Quest». Квест будет создан и состояние квеста перейдет к CREATED и игроку будет показана страничка Start.htm с описанием квеста. Тогда метод onEvent, поле открытия странички Start.htm переведет состояние квеста в STARTED и игроку будет показана страничка Started.htm, где будет опсание того, как найти keltirs и .т.д.
, ~$ r" a* }8 r3 L, X3 [- i. d8 r/ E( x) e5 h5 r* H+ P

: V% K6 S+ E7 CПри состоянии STARTED будет зарегистрирован дроп «fangs» при убийстве keltirs. Игрок может вернуться к стартовому NCP и спросить о квесте – метод onEvent будет вызван снова. Если у игрока не хватает необходимого количества предметов, то метод check() не переведет квест в следующее состояние и Started.htm будет показана снова. Но если игрок собрал необходимее количество предметов (в данном случае 4 клыка), то метод check() вызовет метод completed() который переведет квест в новое состояние COMPLETED, заберет все клыки, даст карту мира, т.к. это награда за квест, покажет Completed.htm и завершит квест.2 M0 q# y/ j5 _. M5 N7 }$ ]7 s6 S

7 T- }+ b1 G9 \3 n$ d! w. O, x

7 x- m2 g* b0 m3 y% wТеперь давайте сделаем наш квест более похожим на то, что он должен из себя представлять.
: c4 D3 S/ i+ eПрежде всего у нас есть 3 метода для объявления их в Яве – onTalk, onKill и onEvent. Если методы onTalk и onKill не объявлены, то за них все будет делать метод onEvent, т.е. определять квестовых монстров и вызывать диалоги NCP. Есть примечание, методы onTalk и onKill будут вызывать только диалоги с NCP в зависимости от текущего состояния квеста. Метод onKill будет вызываться только тогда, когда мы убиваем квестового монстра.
& N( b" y7 Z) b& C4 n. r5 Z$ u$ d: B5 I: F2 G3 P
6 h9 f4 U+ Q! @# r  T% a; d
Давайте рассмотрим как вызывается метод onKill при убийстве keltir в состоянии квеста STARTED:) j$ q  E3 }& g) H3 f# E" Y
  1. STARTED.addKillId(KELTIR_NPC_ID)
Скопировать код
и метод onKill в классе Quest:
9 J. s' B9 s8 s8 {; d5 [; Y) [2 O
  1. class Quest (JQuest):
      q. O% p3 e# U$ n3 x/ W
  2.   ...
    ( L! I# z% ?* J+ j
  3.   def onKill (self,npcId,st):
    & H! v# ]  X! F3 l( E  ~, w
  4. if npcId == KELTIR_NPC_ID:* o" Q1 l; g5 j) U" }. Q, ~
  5.    n = getCount(st)% ^/ A' m( x' t$ E7 Y- }" O
  6.    if   n == 0:5 K0 @, T4 E* Q3 C) i) f7 `( a
  7.        return "Chat0.htm"9 Y0 v! ^" m" X& q3 j
  8.    elif n == 1:
    ; B6 o" q2 {) Z6 H. A5 Y" e
  9.        return "Chat1.htm"- r( q2 p; w* w' V
  10.    elif n >= 4:
    / Z, C) p# n/ u/ M
  11.        return "Chat4.htm"
    , w( x! s) ^8 j5 [. o: h  J9 d
  12.    return "Collected "+str(n)+" of 4 fangs"
    ( L9 ?$ ]- Z- ~% M
  13. return
Скопировать код
Метод onKill (а так же метод onTalk) имеет следующие параметры:
$ X* a  s0 g* @! W4 f/ A: j1 M- t5 E. w, J! g5 R. U" l
. d, S1 {. p+ q. N' e$ A/ p, Q( ?. J
• self – квест
9 H1 i" b/ z3 J5 Y4 J% S• npcId – ID NCP, которого мы должны убивать (если это метод onTalk, то ID того NCP, с которым мы должны поговорить).
$ r9 l4 a9 _) I- x• st – текущее состояние игрока.( v0 j) ]" i7 j, q7 m2 O# s. s" H

7 m) D7 O4 Y( l7 c5 {6 F/ l

4 H. l2 }( t+ o4 z# M2 qВ этом методе мы проверяем и отмечаем, является ли убитый NCP keltir’ом. В основном эта проверка не нужна, т.к. у нас только KELTIR_NPC_ID.
& {5 [! o  t4 H& _
& Q# E2 a& X+ D% _$ X3 A$ M

' D  C$ ?7 w' f* n, x) P6 UЗатем проверяем количество предметов (в данном случае количество клыков), и если их вообще нет, то возвращаем строку "Chat0.htm", если только один предмет, то возвращаем строку "Chat1.htm", если же предметов 4 или больше, то "Chat4.htm". Если строка возвращена из методов onEvent, onKill или onTalk, то сервер покажет соответствующие htm. В Chat0.htm может иметь следующий текст: «Вы не имеете ни одного клыка, возвращайтесь позже, когда соберете 4 штуки и бла, бла, бла…», в Chat1.htm может быть следующий текст: «У Вас всего 1 клык, по этому соберите еще…». В Chat4.htm – «Вы собрали необходимое количество предметов, возвращайтесь к вашему тренеру, что бы завершить квест…»
; Y. {. [3 Q& B' g, O1 P) y1 N5 A  d! ]2 ?& N$ x
. {# x( r1 Y: {8 Y  I
Примечание: если в строка return начинается с "<html>", то будет показана страничка html с текстом, который стоит далее. Так вместо:
2 \" O4 Z0 c2 s; v6 j9 Treturn "Chat4.htm"' N! y: z$ v7 V% \* ^# I
& O6 d. |& i+ M7 g5 S8 V

! o+ e, G9 k- \8 z' S5 ]/ d/ R- {можно поставить:
( }5 O7 j3 c/ h! a7 ?& S
  1. return "<html><body>Return to your trainer to complete the quest</body></html>"
Скопировать код
Так же если строка заканчивается без .htm или в начале нет <html>, то текст будет выведен, как системное сообщение в окне чата. В нашем случае мы сделаем так, что бы при каждом убийстве keltik выводилось системное сообщение: «Собрано N из 4-х клыков».; |0 k9 E: {, l# H! d( \

- l4 I9 Q: s$ x

8 L, \+ k2 J" k$ f  y8 Q( @Наш код для onKill имеет один недостаток. Он будет постоянно показывать Chat0.htm, Chat1.htm и Chat4.htm, нам же необходимо, что бы Chat0.htm и Chat1.htm показывались только один раз. Как нам это сделать? С помощью переменных.  @1 H/ o# w/ `) x+ ~
3 a1 e0 o( a3 t$ y3 [$ }

2 v4 M, l: o: b: pВ каждом квесте строки могут храниться с помощью переменных. Эти переменные сохраняются в Вашей БД. В каждом методе мы можем назначить, прочитать и удалить переменные. Давайте изменим метод onKill, так что бы каждый диалог вызывался только один раз.
) s! @2 ], q  T
  1. def onKill (self,npcId,st):1 S9 l  n+ X3 {) M
  2. if npcId == KELTIR_NPC_ID:
    6 O6 D# Y# O# }9 J. O7 w- {
  3. n = getCount(st)
    & {  u5 R2 x2 i
  4. if n == 0:
    ( E4 E. [, F3 e7 `5 w8 c( Y
  5. if st.get('chat0') == None :
    + M- ^1 ]4 h+ {
  6. st.set("chat0", "true")
    9 N: b; V0 L; z
  7. return "Chat0.htm"
    8 e4 z5 x" ^1 R6 g; m" v) d7 f
  8. elif n == 1:
    , ^+ R) O& W% _2 g# L6 M6 V1 p: H% B
  9. if st.get('chat1') == None :
    # K- r5 N! c! B. C$ d! @
  10. st.set("chat1", "true"): P* z2 Z: U$ r0 A" e% G9 F
  11. return "Chat1.htm"5 Z1 d$ c3 w' X, G4 z" g# `
  12. elif n >= 4:
    1 a1 h3 @+ X. T) |6 `
  13. return "Chat4.htm"3 f, u, P: ]. Q5 G+ \
  14. return "Collected "+str(n)+" of 4 fangs"9 ?; m0 ]+ u, M. m) O7 z
  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.
' ]$ G$ I1 s  t. F6 {
! ?9 v) c& G, `! N, ?$ e
1 O% B! U  y- M
Вот конечный рабочий вариант квеста:- L* j" j  k3 Z4 N
  1. import sys1 d- E# g) ~$ [' l8 [: a4 p" K
  2. from net.sf.l2j.gameserver.model.quest import State( V4 \- S1 @; ^6 y# h' l! S' C6 I6 ~% N) O
  3. from net.sf.l2j.gameserver.model.quest import QuestState
    ' N) G/ U/ u+ m* V4 `3 C7 }% r
  4. from net.sf.l2j.gameserver.model.quest.jython import QuestJython as JQuest5 i& P6 G/ z# Z6 D2 |# i2 h. C0 w

  5. ) X, g! y2 _$ E9 V
  6. KELTIR_NPC_ID = 12082
    9 P8 @$ \% }5 F+ ?  n
  7. FANGS_ITEM_ID = 18598 {: z  q, C. E" v
  8. DROP_RATE    = 500000
    " e( G) \# J3 r5 D) d

  9. 5 j/ H& u, q5 x9 U
  10. WORLD_MAP_ITEM_ID = 1665  K' h+ X  p0 ^* N
  11. % A2 g) `- \1 K" L: q/ ?
  12. def getCount(st) :
    3 I: P3 e9 P. O5 w8 M- `
  13. return st.getQuestItemsCount(FANGS_ITEM_ID)
    + I0 l6 z' f) v6 l% K$ U
  14. 4 m6 g( C& S% V+ L
  15. def completed(st) :
    + q3 O9 \. Q7 K5 }! d" Y7 p/ M: s
  16. st.setState(COMPLETED)
    ; J1 Q- B6 T' X# o; ^- U8 z
  17. st.clearQuestDrops()
    ) c  P0 P" z; F% t8 j
  18. st.takeItems(FANGS_ITEM_ID,-1)
    1 ?' J& v# V, ~, k; v
  19. st.giveItems(WORLD_MAP_ITEM_ID,1)9 N+ o" g2 J) K" n8 ?
  20. st.exitQuest(False)
      d) [/ E$ g7 ~
  21. return
    , B  ]) `3 X0 J5 v, X
  22. 5 _8 P5 n( ~5 W+ _7 W0 z: ~2 Y5 i6 o
  23. def check(st) :
    : }7 P, F/ _8 J" u$ u0 E
  24. if getCount(st) >= 4 :
    $ d5 t$ Q7 g1 ?
  25. completed(st)
    9 u  c! v  A9 q: e1 ~
  26. return- X, j" ~9 N6 i0 e/ o
  27. # [4 }8 l3 w9 U$ y& s% k
  28. class Quest (JQuest):4 J' u. p3 `* |4 v- I

  29. . G5 ], P) o4 e
  30. def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)
    # T3 A9 i6 y2 b3 M0 Y
  31. 5 f' d" a/ K; M4 N, v
  32. def onEvent (self,event,st):
    ; i% b$ [% C9 R  N2 _
  33. id = st.getState()
    * L2 Z, _9 f8 q# w' a4 V, l
  34. if id == CREATED : st.setState(STARTED)8 K4 H" n8 ?' U: f2 H9 Y
  35. elif id == COMPLETED: pass
    8 \  o9 T) ~4 H3 E' o) G
  36. elif id == STARTED : check(st)& E' Y/ b8 g4 T% w+ ^
  37. return" l' P/ k, t( u2 I7 K+ c
  38. 8 }+ }  S) j5 s, _; u0 h
  39. def onKill (self,npcId,st):  b$ H( E& y/ a, A* j2 `2 C  T
  40. if npcId == KELTIR_NPC_ID:2 T# [0 ?; v& Q! v/ `
  41. n = getCount(st)  x0 b1 e5 U& ^# V, W
  42. if n == 0:( V9 H4 a8 M$ c( S) u; {
  43. if st.get('chat0') == None :4 }) c" Z5 n! ?: u+ o
  44. st.set("chat0", "true"); y- T) J( E8 f+ d; q9 {- Z
  45. return "Chat0.htm"' S5 \, e- i' v3 D6 t3 }( ^! Q
  46. elif n == 1:4 U+ ]2 U+ ?- x* ]
  47. if st.get('chat1') == None :
    ) C  q) z/ s2 t5 J/ P+ z- @
  48. st.set("chat1", "true")
    & j* h3 C) {! ^" C
  49. return "Chat1.htm") b" T# `  q1 u2 m* v
  50. elif n >= 4:
    " P" e& j+ N1 W, ~4 O8 T
  51. return "Chat4.htm"( D' |! @5 A% q) d' i# s- A1 t, x
  52. return "Collect "+str(n)+" of 4 fangs"; s+ g1 p" k$ W" @1 p
  53. return/ G# [# g4 ^% p2 t! \

  54. " |- R- W) n7 p
  55. QUEST    = Quest(201, "Tutorial", "Tutorial quest")1 Z' {. \+ U8 U
  56. CREATED = State('Start',    QUEST). ]6 _( J- D( G& `; }4 Y1 o
  57. STARTED = State('Started', QUEST)' p0 {% M( r& {) \/ h8 D
  58. COMPLETED = State('Completed', QUEST)
      k1 h9 j9 R5 }; a7 j4 W

  59. ! x. D) B# R2 o4 }: k9 f& e6 s
  60. QUEST.setInitialState(CREATED)# Q0 ~: W% Z! x! p; {* _
  61. QUEST.addStartNpc(7056)
    : u) `9 l0 Z9 i; v
  62. QUEST.addStartNpc(7012)
    % e7 ^! t. s% e! M  y
  63. QUEST.addStartNpc(7009)8 q2 I; }; P+ X: K' s% ^# z6 a
  64. QUEST.addStartNpc(7011)
    + S9 V% x+ W6 e5 ~# [- O" D
  65. $ g, u, L' n! ~) A! I
  66. STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)) \! p. a( d7 O2 T5 X
  67. STARTED.addKillId(KELTIR_NPC_ID)  Y0 w# H. b8 x) B+ F% f6 f( n( n# w
  68. STARTED.addTalkId(7056)
    " V3 }) m! n- m' d  ]
  69. STARTED.addTalkI d(7012)! |0 t7 V1 W! b0 d( Q: c% O/ U) c( {# q
  70. STARTED.addTalkId(7009)5 f5 [% q$ _. m, o
  71. STARTED.addTalkId(7011)
Скопировать код

1 C$ x. j! p7 d6 L: Y$ ]
& s* y; Z% N; |+ v0 M" ^$ d  p$ p  n
Чтобы ответить, вам надо авторизироваться в системе Вход | Зарегистрироваться

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

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

638638758

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

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

admin@artace.ru Онлайн

QR-код

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