Top.Mail.Ru

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

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

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

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

x
Хроники        Interlude
8 X7 b# U0 j6 NСборка        L2j
) K' |8 e* |' P5 Y( Y$ I( ]Обратите внимание: в файле htm стартового NCP обязательно должна быть ссылка на квест:
* x: ]( `9 c8 J% t' P5 z( }
  1. STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код
Для этого квеста больше ничего не надо. Все необходимое для корректной работы квеста уже добавили. Вот полный текст квеста:, `7 t7 s: u$ z- D6 Q) w" W

1 \$ u  r2 Q* k$ g% u; v7 P1 m9 K
  1. if getCount(st) >= 4 :4 D: N3 e3 H; ^$ O" g. l# T
  2. completed(st), }6 P) V; V; T. E
  3.   return
    $ B* w% N) Y2 O# k

  4. 8 K- y- `9 e" H- p- Z; @: Z# Z
  5. class Quest (JQuest):
    $ N0 x9 \* U9 y
  6.   def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)( s' D7 @  _. O+ J/ g' O; u
  7.   def onEvent (self,event,st):
    2 c8 m, m, T, M
  8. id = st.getState()- D  [, ?+ d/ R% b3 ^
  9. if   id == CREATED  : st.setState(STARTED)
    : g  Y0 F0 ?/ E2 y1 r, u, h3 i
  10. elif id == COMPLETED: pass
    ! E4 p8 _* T  _
  11. elif id == STARTED  : check(st)
    ( u4 c& ], Z; p
  12. return
    ( R5 u, R+ C. v& k. Z2 a$ d
  13. 6 s* C4 C2 |. u7 M0 n1 O  Z
  14. QUEST     = Quest(201,"Tutorial", "Tutorial quest")$ {6 p' x- v8 m' d$ c1 Q
  15. CREATED   = State('Start',     QUEST)
    - Q! u5 b& F2 ?0 R) @" W& h
  16. STARTED   = State('Started',   QUEST)
    * o1 F: H1 Y3 P# q9 {& T9 ?
  17. COMPLETED = State('Completed', QUEST); \' Q$ e0 f6 ^9 o% u

  18. - f* D# G# q! E$ F
  19. QUEST.setInitialState(CREATED)$ {3 l* \9 J( f/ d+ `
  20. QUEST.addStartNpc(7056)
    , h5 a7 C4 N. k( M8 R
  21. STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код
Теперь рассмотрим, как это работает.
8 ?+ B) R3 ^, H$ U+ x% aИгрок подходит к начальному NCP (в данном случае 7056), нажимает на «Quest». Квест будет создан и состояние квеста перейдет к CREATED и игроку будет показана страничка Start.htm с описанием квеста. Тогда метод onEvent, поле открытия странички Start.htm переведет состояние квеста в STARTED и игроку будет показана страничка Started.htm, где будет опсание того, как найти keltirs и .т.д., E' p7 {' y( Z
. B1 S. I) K: d! V# g8 h2 D0 @
" z$ K- s! o2 B5 H* B3 V3 U2 p- A" F
При состоянии STARTED будет зарегистрирован дроп «fangs» при убийстве keltirs. Игрок может вернуться к стартовому NCP и спросить о квесте – метод onEvent будет вызван снова. Если у игрока не хватает необходимого количества предметов, то метод check() не переведет квест в следующее состояние и Started.htm будет показана снова. Но если игрок собрал необходимее количество предметов (в данном случае 4 клыка), то метод check() вызовет метод completed() который переведет квест в новое состояние COMPLETED, заберет все клыки, даст карту мира, т.к. это награда за квест, покажет Completed.htm и завершит квест.
0 `6 B  R3 x7 g7 B4 u3 t5 d4 a5 }; ?) P- J

7 _1 N& ]3 L8 C3 E) Y$ @; }! F8 |Теперь давайте сделаем наш квест более похожим на то, что он должен из себя представлять.3 A2 z* w, e+ Z3 s' u2 H+ \
Прежде всего у нас есть 3 метода для объявления их в Яве – onTalk, onKill и onEvent. Если методы onTalk и onKill не объявлены, то за них все будет делать метод onEvent, т.е. определять квестовых монстров и вызывать диалоги NCP. Есть примечание, методы onTalk и onKill будут вызывать только диалоги с NCP в зависимости от текущего состояния квеста. Метод onKill будет вызываться только тогда, когда мы убиваем квестового монстра.2 S' w0 t  K1 ]! j: E
  g7 y; E: }+ r$ }( ?
, `' H0 ]& B# o2 N' L. \+ O: ]
Давайте рассмотрим как вызывается метод onKill при убийстве keltir в состоянии квеста STARTED:3 L( }% N/ l3 I% `* C" P
  1. STARTED.addKillId(KELTIR_NPC_ID)
Скопировать код
и метод onKill в классе Quest:9 H$ r( P) `- y8 o( ]
2 x! b1 q6 T9 P0 k* W
  1. class Quest (JQuest):/ P/ q6 U. C2 I
  2.   ...
    ; a/ Y. \/ s$ H
  3.   def onKill (self,npcId,st):
    - P- c  o1 V. \' b
  4. if npcId == KELTIR_NPC_ID:
    9 S  ?! J' J/ i& ?. m
  5.    n = getCount(st)' o; u7 v' l+ W
  6.    if   n == 0:7 L3 w# ]4 K! H: Q$ y8 p+ R! [
  7.        return "Chat0.htm". y+ M1 m$ R6 {; [: {. m  ^6 |+ m
  8.    elif n == 1:6 n8 R: t7 ~1 I% V8 Y* m3 L
  9.        return "Chat1.htm"+ n$ K* k% V' E4 ?, K
  10.    elif n >= 4:: Q! q; Y: p1 j4 X
  11.        return "Chat4.htm"
    : a( l2 X! U: o: Q+ u$ |" ?) j
  12.    return "Collected "+str(n)+" of 4 fangs"- W+ w- E8 c5 z- B
  13. return
Скопировать код
Метод onKill (а так же метод onTalk) имеет следующие параметры:
, e+ J3 z  P4 D" ?; H- u, c: d8 ]
( S' k/ r( Q7 h+ r7 d8 K
• self – квест
2 f" n. i# k% ?  U$ t0 D9 v. r' g5 i• npcId – ID NCP, которого мы должны убивать (если это метод onTalk, то ID того NCP, с которым мы должны поговорить).
5 f; i, m' W; o  P  ]* e• st – текущее состояние игрока.
( W+ C6 V# }0 g- c
+ O0 {4 g. g5 m, ?
& V2 N) m+ S. k$ C% R' F
В этом методе мы проверяем и отмечаем, является ли убитый NCP keltir’ом. В основном эта проверка не нужна, т.к. у нас только KELTIR_NPC_ID.4 Z2 f3 ]1 w3 a9 ]

2 e: L2 ^3 D9 b$ |% q0 B# T1 ?* g3 h

& u+ F. b# K9 QЗатем проверяем количество предметов (в данном случае количество клыков), и если их вообще нет, то возвращаем строку "Chat0.htm", если только один предмет, то возвращаем строку "Chat1.htm", если же предметов 4 или больше, то "Chat4.htm". Если строка возвращена из методов onEvent, onKill или onTalk, то сервер покажет соответствующие htm. В Chat0.htm может иметь следующий текст: «Вы не имеете ни одного клыка, возвращайтесь позже, когда соберете 4 штуки и бла, бла, бла…», в Chat1.htm может быть следующий текст: «У Вас всего 1 клык, по этому соберите еще…». В Chat4.htm – «Вы собрали необходимое количество предметов, возвращайтесь к вашему тренеру, что бы завершить квест…»
( X& l) \: p* l' n5 J, E2 ~# b
: i: e  L+ _9 S$ c# [9 w
, N: G" J( a* X: v* u
Примечание: если в строка return начинается с "<html>", то будет показана страничка html с текстом, который стоит далее. Так вместо:% e, t2 z/ u  z
return "Chat4.htm"6 M$ z, d4 z+ N" y$ |

& e1 h) f; `3 R: Q# `5 r

& R6 \: ]# x: v8 M6 Z( V  tможно поставить:' S. F! O$ \0 k2 m$ o! U5 M  i
  1. return "<html><body>Return to your trainer to complete the quest</body></html>"
Скопировать код
Так же если строка заканчивается без .htm или в начале нет <html>, то текст будет выведен, как системное сообщение в окне чата. В нашем случае мы сделаем так, что бы при каждом убийстве keltik выводилось системное сообщение: «Собрано N из 4-х клыков».7 \- ~  J7 I, c
! @" @6 t2 i5 c4 O. g( c3 f

/ j) }1 m8 u/ N; mНаш код для onKill имеет один недостаток. Он будет постоянно показывать Chat0.htm, Chat1.htm и Chat4.htm, нам же необходимо, что бы Chat0.htm и Chat1.htm показывались только один раз. Как нам это сделать? С помощью переменных." _0 z: T7 {) g: h1 @
6 F1 A8 z" w- L: X  o3 H1 R

2 \% ^( s5 h1 `В каждом квесте строки могут храниться с помощью переменных. Эти переменные сохраняются в Вашей БД. В каждом методе мы можем назначить, прочитать и удалить переменные. Давайте изменим метод onKill, так что бы каждый диалог вызывался только один раз.# X7 k/ K5 Q' Z: O3 ]# {
  1. def onKill (self,npcId,st):1 K; w( `8 B8 u/ S% W& T& O9 ]
  2. if npcId == KELTIR_NPC_ID:+ r% i2 A! B; A0 p* R+ X* f
  3. n = getCount(st)" u1 @* ^, X6 y' Y* q
  4. if n == 0:
    # l1 A: \$ i& J/ r7 c
  5. if st.get('chat0') == None :7 o$ m5 {2 P8 b$ u  f: B: E& S; Y
  6. st.set("chat0", "true")
      s5 r6 X) y  P' D
  7. return "Chat0.htm"
    5 }. {- W# K1 r6 n  m  i
  8. elif n == 1:; x3 l. `4 ~! V2 W5 A( T
  9. if st.get('chat1') == None :( {, @. m& s3 O0 _6 K
  10. st.set("chat1", "true")
    9 }6 }2 L6 Z1 }  z
  11. return "Chat1.htm"
    * `8 [' x1 V1 ]4 y
  12. elif n >= 4:9 u% m* s) K' {
  13. return "Chat4.htm"
    / K# m/ Y/ k" Y) U# ^& @
  14. return "Collected "+str(n)+" of 4 fangs"
    4 _  \: y9 q, J% S! V! 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.) ^* ^: l" v! _) S$ X: X
4 W4 V9 s. v4 e3 d2 x
) D4 @5 u/ R2 O/ W+ p
Вот конечный рабочий вариант квеста:' j' r+ a0 `8 }( \1 {: F. a! ]
  1. import sys
    5 Y. L9 z4 U6 i. B; j
  2. from net.sf.l2j.gameserver.model.quest import State0 _1 ?7 @3 x9 D+ l8 V; |* F* s" ?
  3. from net.sf.l2j.gameserver.model.quest import QuestState8 ?1 Z; A* }4 B6 b" i) _
  4. from net.sf.l2j.gameserver.model.quest.jython import QuestJython as JQuest
    ' ]7 J7 ], Q: z8 {+ F4 u! r* x9 N7 }
  5. ( j' b8 m: J* }* z: {6 ?, V2 D/ ^
  6. KELTIR_NPC_ID = 12082
    & t2 C2 O, G* \1 f/ o: V6 X+ v
  7. FANGS_ITEM_ID = 1859
    ' z, ~# U. {: [
  8. DROP_RATE    = 500000; N6 a; Y+ d: O& u  v3 L8 {4 u
  9. * t0 s4 B% _. a( u/ y; }$ Y" z
  10. WORLD_MAP_ITEM_ID = 1665
    : ]! p" p# e3 }+ e- V
  11. ; l* F5 _0 W' L2 D
  12. def getCount(st) :6 z) J! P5 w. k% Z3 q) [& ~
  13. return st.getQuestItemsCount(FANGS_ITEM_ID)- c, y; @! F7 i: p4 {
  14. / k$ e; O6 Y  p3 I: n/ u3 `$ A" n8 |
  15. def completed(st) :5 V# E6 F1 b6 o) ^5 W
  16. st.setState(COMPLETED)
    # ~$ C* o- ~+ ~. ^
  17. st.clearQuestDrops()
    / \* J+ {, e8 e) ]) P: k$ d
  18. st.takeItems(FANGS_ITEM_ID,-1)
    & o, ~+ C% e; F" r, {6 O: _
  19. st.giveItems(WORLD_MAP_ITEM_ID,1)
    + N9 _: T1 ~/ d! `- Q8 Z; R% `
  20. st.exitQuest(False)
    9 Q2 Y- l' S% D+ K
  21. return
    $ L( D) ]* G5 X6 }' _0 y+ b- ^& ]" y/ \( u

  22. 4 f% D5 H1 {1 J) l
  23. def check(st) :
    5 `; [( Z% @% L1 i, w
  24. if getCount(st) >= 4 :* B) H# S( P9 x  k0 u* h
  25. completed(st)
    ( q* o8 ]- Q2 `( ~% Y3 ^
  26. return
    ' d, i" ?( r0 a5 J! L

  27. " g! a1 e4 h8 K! b( G/ B
  28. class Quest (JQuest):
    ( T2 S, {4 b) b0 V3 i4 c4 t
  29. " ?6 M- ~; e. w5 O) D  K/ C
  30. def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)  m, C5 M* ]# |- o! `( g8 x
  31. 1 ?& j% |) h: ^. ]- r# y* q
  32. def onEvent (self,event,st):+ _. Z, C* U) o0 @
  33. id = st.getState(), I& q- T: P0 W6 |$ L6 a3 j
  34. if id == CREATED : st.setState(STARTED)
    2 Q% G& J. n) v8 c4 U( [
  35. elif id == COMPLETED: pass8 v% T6 `! Z) b8 |+ C
  36. elif id == STARTED : check(st)0 {) ^7 s7 w& f" C% Y, {
  37. return
    4 o* t/ B+ Q& F" H% R1 e/ P5 ^
  38. . ?1 H5 Q3 j$ @5 W0 F
  39. def onKill (self,npcId,st):
    * b/ |, c8 ?" V$ d5 t/ \2 @
  40. if npcId == KELTIR_NPC_ID:( I% B, v0 X, \+ ?3 o
  41. n = getCount(st)
    " P- c4 E) z8 y% c  R1 v
  42. if n == 0:+ _" b$ a: L! E( i( m5 q. h( m
  43. if st.get('chat0') == None :
    1 D  Z! }. A# G5 H3 \4 |
  44. st.set("chat0", "true")$ T3 A' J* P" D4 ?
  45. return "Chat0.htm"8 G$ }3 j& u( M
  46. elif n == 1:/ d" j  T9 t8 |! Y
  47. if st.get('chat1') == None :
    * x( T& [& }) C+ [% E5 L0 H
  48. st.set("chat1", "true")/ x; P& K, a2 _  p/ }* n
  49. return "Chat1.htm"  A0 Q& h  \6 B
  50. elif n >= 4:
    * u/ U# Z4 y# c7 S* R
  51. return "Chat4.htm"$ x9 k5 l/ v# f( [# L* z. g
  52. return "Collect "+str(n)+" of 4 fangs"4 q' ]) k: c$ f
  53. return
    + `9 S/ z" R& l" [8 q/ `0 F
  54. $ h9 C0 a' [& F7 |8 E0 _# ?; Q
  55. QUEST    = Quest(201, "Tutorial", "Tutorial quest")
    9 n8 E2 e3 n# I3 ?. ?
  56. CREATED = State('Start',    QUEST)% n: }2 M# ?) W7 b" T
  57. STARTED = State('Started', QUEST)
    : a7 I4 ^& X. c* D) f  Z) p6 u
  58. COMPLETED = State('Completed', QUEST)
    - z" j1 O8 d) j+ B7 D
  59. * b( w% s! ^7 E) [1 y: H
  60. QUEST.setInitialState(CREATED)
    # t& C3 {# @5 F4 j/ U) @
  61. QUEST.addStartNpc(7056)
    # m( w5 L# _1 ?# I; z( f, V3 u
  62. QUEST.addStartNpc(7012)
    4 {" h" F+ L' b4 z/ ?' G7 C
  63. QUEST.addStartNpc(7009)4 u$ v& v3 Z6 y, c* X! A* t9 C
  64. QUEST.addStartNpc(7011)
      @( }) `0 a0 X' D: T

  65. ! M- Y; \- W% F; ?
  66. STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
    ) y0 Y$ S* k0 }/ g% s
  67. STARTED.addKillId(KELTIR_NPC_ID)
    2 m8 Q0 x- ~9 n, N- |. g! @
  68. STARTED.addTalkId(7056)
    ' R* `5 D& H6 @8 G, \0 h
  69. STARTED.addTalkI d(7012); d5 k- c2 F7 k# o( K
  70. STARTED.addTalkId(7009)
    : `% G6 Y- Q9 N: }% ~/ d+ f9 f
  71. STARTED.addTalkId(7011)
Скопировать код

3 m2 `! L6 E# c+ Q9 W* W% Y$ }* D' I% ~# K& R& k4 t4 d# ]0 ^
Чтобы ответить, вам надо авторизироваться в системе Вход | Зарегистрироваться

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

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

638638758

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

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

admin@artace.ru Онлайн

QR-код

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