Top.Mail.Ru

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

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

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

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

x
Хроники        Interlude, t9 ]. f: K" Y' p( C' D/ ]; c% H$ G
Сборка        L2j
0 g; Q# d4 `. LОбратите внимание: в файле htm стартового NCP обязательно должна быть ссылка на квест:
2 `0 U4 ~/ ~8 p& F7 F! F" q0 ~; z# g
  1. STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код
Для этого квеста больше ничего не надо. Все необходимое для корректной работы квеста уже добавили. Вот полный текст квеста:
6 N7 W8 n* m+ u" h! {
: k# j, t0 Q' e5 w; N2 Y. ~0 O
  1. if getCount(st) >= 4 :8 @, \; I/ Z4 C' r  e# H9 E6 m
  2. completed(st)
    0 x. G* T1 O6 Z) \( I/ c+ e
  3.   return
    8 Q5 C1 J1 Z+ ~  O

  4. $ E% A. G1 Y! z( w. k+ }
  5. class Quest (JQuest):* B* f) g' O7 I, |2 M2 ~
  6.   def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)$ q/ a( h9 y2 V( M9 c
  7.   def onEvent (self,event,st):! Y0 J- b& X# R$ x* {
  8. id = st.getState()1 `$ \5 A; l4 ~7 _# y( R. M. n
  9. if   id == CREATED  : st.setState(STARTED)
    & P* v3 a  F" S6 u) |4 o: C- p6 l, b
  10. elif id == COMPLETED: pass5 C* u% I. w: v% X% e$ Y
  11. elif id == STARTED  : check(st)
    & Z# J  ~; C7 J, |! M* R
  12. return9 k. K# J+ e1 P
  13. 4 f2 ^3 R+ @6 I0 G
  14. QUEST     = Quest(201,"Tutorial", "Tutorial quest")
    ' {- |! g$ Q& @# p0 o% O
  15. CREATED   = State('Start',     QUEST)
    $ F: o7 `" U8 @* r9 s* M% c, q& f0 S
  16. STARTED   = State('Started',   QUEST)$ w+ U2 Y4 @; R& N: K
  17. COMPLETED = State('Completed', QUEST): i! S7 \8 D, ?' U

  18. 1 `& |+ x, S& s- R
  19. QUEST.setInitialState(CREATED)
    8 t" F& B$ j4 ?: T
  20. QUEST.addStartNpc(7056)  @/ \8 `3 W& X: \$ b9 U! A
  21. STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код
Теперь рассмотрим, как это работает.
4 \6 q3 Y) e/ N* [Игрок подходит к начальному NCP (в данном случае 7056), нажимает на «Quest». Квест будет создан и состояние квеста перейдет к CREATED и игроку будет показана страничка Start.htm с описанием квеста. Тогда метод onEvent, поле открытия странички Start.htm переведет состояние квеста в STARTED и игроку будет показана страничка Started.htm, где будет опсание того, как найти keltirs и .т.д.8 E8 b- y  M+ c5 I( @

+ V9 D4 R# o( m5 B' e! j

0 a! c2 c. G# k+ @При состоянии STARTED будет зарегистрирован дроп «fangs» при убийстве keltirs. Игрок может вернуться к стартовому NCP и спросить о квесте – метод onEvent будет вызван снова. Если у игрока не хватает необходимого количества предметов, то метод check() не переведет квест в следующее состояние и Started.htm будет показана снова. Но если игрок собрал необходимее количество предметов (в данном случае 4 клыка), то метод check() вызовет метод completed() который переведет квест в новое состояние COMPLETED, заберет все клыки, даст карту мира, т.к. это награда за квест, покажет Completed.htm и завершит квест.
6 N. Q0 o6 p, `) i. Q  H4 a, B" t" O: Q; a
  N3 A$ Q8 q, R% [
Теперь давайте сделаем наш квест более похожим на то, что он должен из себя представлять.  w* H% M. F* E5 @8 q* D* M, c3 ~- f
Прежде всего у нас есть 3 метода для объявления их в Яве – onTalk, onKill и onEvent. Если методы onTalk и onKill не объявлены, то за них все будет делать метод onEvent, т.е. определять квестовых монстров и вызывать диалоги NCP. Есть примечание, методы onTalk и onKill будут вызывать только диалоги с NCP в зависимости от текущего состояния квеста. Метод onKill будет вызываться только тогда, когда мы убиваем квестового монстра.
. X; n# W. C! X. S+ Z! z3 B
) x- t" C( Q, U1 E% d

8 B. w! C& ~2 i2 f+ q8 @$ [; HДавайте рассмотрим как вызывается метод onKill при убийстве keltir в состоянии квеста STARTED:
  T% w& e# ?; R0 g7 y
  1. STARTED.addKillId(KELTIR_NPC_ID)
Скопировать код
и метод onKill в классе Quest:
. I$ J6 w9 Y5 R% B. M6 O, ?6 @5 Y! y0 ^
  1. class Quest (JQuest):2 g$ b$ F9 A. Y
  2.   ...
    ! _3 T: \9 y4 U0 q
  3.   def onKill (self,npcId,st):3 Q9 s* U1 D. V
  4. if npcId == KELTIR_NPC_ID:
    * H. J0 X; f$ r0 ^
  5.    n = getCount(st)) S0 x. R, i  z. n/ c! p& m
  6.    if   n == 0:
    0 x- ]( ]7 I/ H+ Y1 _6 u9 _0 b8 O
  7.        return "Chat0.htm"
    . a' d  P. q: B
  8.    elif n == 1:, l- x3 B4 S2 l/ k" Q9 T: d
  9.        return "Chat1.htm"
    " z9 _' e* a4 F" {9 Y$ a) ]2 R! D
  10.    elif n >= 4:$ f5 N2 m5 s( q; ]8 [
  11.        return "Chat4.htm"0 M# \- j5 k/ t
  12.    return "Collected "+str(n)+" of 4 fangs"
    5 x  Y- X8 e  y0 k5 k, E8 g) q
  13. return
Скопировать код
Метод onKill (а так же метод onTalk) имеет следующие параметры:
  w- Q: u8 h. |" ^& N1 C, f: L6 L  i: ?% X5 _! D. Q
- b/ |5 l1 H6 K) E8 g
• self – квест' d, I& _6 @% I* t, y2 w
• npcId – ID NCP, которого мы должны убивать (если это метод onTalk, то ID того NCP, с которым мы должны поговорить).  S! a+ Y. @2 \) X4 X) F
• st – текущее состояние игрока.$ M- @1 x$ c+ K5 A& Q( K! l( @& }
# y1 H$ f0 Z# U% H% a6 u

+ B( _( l3 _% u. p* T8 IВ этом методе мы проверяем и отмечаем, является ли убитый NCP keltir’ом. В основном эта проверка не нужна, т.к. у нас только KELTIR_NPC_ID.: O+ x6 E; h# z. W6 f# [* z; N$ [

" F* d* L& L$ A5 T% b, n$ p

6 t  S. ]. C; }; ]/ g- BЗатем проверяем количество предметов (в данном случае количество клыков), и если их вообще нет, то возвращаем строку "Chat0.htm", если только один предмет, то возвращаем строку "Chat1.htm", если же предметов 4 или больше, то "Chat4.htm". Если строка возвращена из методов onEvent, onKill или onTalk, то сервер покажет соответствующие htm. В Chat0.htm может иметь следующий текст: «Вы не имеете ни одного клыка, возвращайтесь позже, когда соберете 4 штуки и бла, бла, бла…», в Chat1.htm может быть следующий текст: «У Вас всего 1 клык, по этому соберите еще…». В Chat4.htm – «Вы собрали необходимое количество предметов, возвращайтесь к вашему тренеру, что бы завершить квест…»9 K+ `% n# b7 L, z; [

' L5 z' `4 B* x( @+ R1 R3 j
2 F- E2 F5 B; @# q# u$ }1 N/ p* X
Примечание: если в строка return начинается с "<html>", то будет показана страничка html с текстом, который стоит далее. Так вместо:
" t6 B$ I# z. b! Yreturn "Chat4.htm"7 x+ a# B) d3 U; b$ i& D
1 I. C" j- Q$ C* J  \7 t' {: n
1 A% T  B' C8 f0 E; y# H
можно поставить:) O, {; K$ z! `5 V' _% X  h
  1. return "<html><body>Return to your trainer to complete the quest</body></html>"
Скопировать код
Так же если строка заканчивается без .htm или в начале нет <html>, то текст будет выведен, как системное сообщение в окне чата. В нашем случае мы сделаем так, что бы при каждом убийстве keltik выводилось системное сообщение: «Собрано N из 4-х клыков»./ J' I$ @& m2 y5 J
9 G/ L. T( Q5 C% U, s
9 |2 ?& l& X# S& z+ D8 b2 P4 S1 K. \
Наш код для onKill имеет один недостаток. Он будет постоянно показывать Chat0.htm, Chat1.htm и Chat4.htm, нам же необходимо, что бы Chat0.htm и Chat1.htm показывались только один раз. Как нам это сделать? С помощью переменных., Z: C, P' A  }0 n8 U0 o* b! h

# L5 e" ~! \5 H8 g
: V) R  @' M( y' |: F, r
В каждом квесте строки могут храниться с помощью переменных. Эти переменные сохраняются в Вашей БД. В каждом методе мы можем назначить, прочитать и удалить переменные. Давайте изменим метод onKill, так что бы каждый диалог вызывался только один раз., @0 b/ Q& z: ^1 ~) F( o
  1. def onKill (self,npcId,st):
    3 y( R7 G* c6 y6 j; x& E
  2. if npcId == KELTIR_NPC_ID:
    ) @1 N8 _4 p, E. F, Y0 w! z& x
  3. n = getCount(st)
    + P5 ^5 S5 w% w
  4. if n == 0:7 A+ I, \# x" {9 r$ e
  5. if st.get('chat0') == None :
    " O/ K2 {( \' i
  6. st.set("chat0", "true")
    , {  q8 _2 l: A8 P) h
  7. return "Chat0.htm"1 ]. r+ z" i3 b# S8 \1 R  A& |
  8. elif n == 1:
    % o8 L) f3 n6 y# s( j
  9. if st.get('chat1') == None :$ Z" D/ u2 T7 X9 o0 b
  10. st.set("chat1", "true")7 K: z$ _; d/ a  S) g/ H! b
  11. return "Chat1.htm"
    - x0 S: s8 P: p0 `; m2 c9 v3 v/ }+ a
  12. elif n >= 4:
    1 x- f# G; r8 v8 ]* Z, R& f
  13. return "Chat4.htm"
    6 [8 ~' ]( y1 |9 R" e
  14. return "Collected "+str(n)+" of 4 fangs"  M+ q6 H- _0 N5 n! D$ f
  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.7 Z! H" W; E: P( U3 {% i. v

+ _" N$ [. X, p

+ p6 e# W1 r9 V  c& @. j/ yВот конечный рабочий вариант квеста:
0 e& T7 r' D1 A+ T5 P- }" F, m
  1. import sys
      w' X) Y/ q* S& j1 G8 Q2 {
  2. from net.sf.l2j.gameserver.model.quest import State
    2 R) K& g. {6 Z" X# l5 a4 Q4 d
  3. from net.sf.l2j.gameserver.model.quest import QuestState
    " n& z3 Y. F. F7 e& `, }; T
  4. from net.sf.l2j.gameserver.model.quest.jython import QuestJython as JQuest
    5 D5 k6 K! g. v* ?9 h# S/ H! E
  5. - P3 Z6 p8 g% v# i
  6. KELTIR_NPC_ID = 12082' q. Y. K7 P. j4 H6 ]7 K9 j
  7. FANGS_ITEM_ID = 18599 G) ], m# {  [4 T
  8. DROP_RATE    = 500000
    $ W8 ^: N) t$ z4 F# @

  9. " l. x$ R' Z5 y6 Y
  10. WORLD_MAP_ITEM_ID = 1665
    1 h  p2 w( U) `" Z8 Z

  11. & w5 b" U6 j: A, `% R- v
  12. def getCount(st) :3 |5 E# {4 H& [. V- b5 i
  13. return st.getQuestItemsCount(FANGS_ITEM_ID)
    5 P. Q/ x/ F- g: M2 a

  14. . Y9 Y2 `) b* I
  15. def completed(st) :
    / {2 ^  V  {' |; K. u
  16. st.setState(COMPLETED)
    3 _' |: J* r& n4 h/ o' o
  17. st.clearQuestDrops()
    7 \, m- {; n- x0 p9 C
  18. st.takeItems(FANGS_ITEM_ID,-1)7 I% X; D/ B$ x' e& P
  19. st.giveItems(WORLD_MAP_ITEM_ID,1)- M0 j+ q( Z. X
  20. st.exitQuest(False)
    ! B& d' c- r: }+ c5 @0 w
  21. return
    8 C- P2 k" G7 {- }

  22. - ]! S* \  d2 e3 G% j
  23. def check(st) :
    1 @3 C+ A5 h6 ~! w0 x/ X4 q3 d& V
  24. if getCount(st) >= 4 :* Q0 _, @( [" B/ f' C& k8 Z( K
  25. completed(st)
    8 R1 D% E6 z8 O- B
  26. return
    1 Y+ ?! U" y/ y8 f( N* |" k1 V
  27. 5 R* P  O( S: R- f; A9 e$ N5 c
  28. class Quest (JQuest):- `+ e# g3 M  e3 {; f$ ?+ K
  29. 1 p2 ~& Z7 f9 e! E5 o5 c1 E% V
  30. def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)+ O( k) B2 i7 X" p) `

  31. ; [; k% ?! p3 [
  32. def onEvent (self,event,st):) S  l8 d3 ^  @( h5 v6 Z- g
  33. id = st.getState()
    ; L6 ^" V0 `0 G$ R
  34. if id == CREATED : st.setState(STARTED)& T3 N! |% D) p) r; X( }
  35. elif id == COMPLETED: pass5 u2 x7 e3 I# S& F5 p  F. p# k
  36. elif id == STARTED : check(st), t7 r) k  ]5 z0 y5 n8 n0 Q
  37. return  V$ X; e' J: `1 e& T3 z+ d

  38. $ m+ {% i$ U9 \2 u5 A: J
  39. def onKill (self,npcId,st):# l1 u# V7 r& v( g7 ^# B4 V
  40. if npcId == KELTIR_NPC_ID:) e2 f  p, W  E& x* Q# s/ F
  41. n = getCount(st)
    ; F0 m, w5 `. W) X! i! A/ \( G( v
  42. if n == 0:) @+ F# D( z, i1 i
  43. if st.get('chat0') == None :
    ) ?" s" ~: F- Z$ C7 D
  44. st.set("chat0", "true")
    8 W$ V6 |% _, X" J* c
  45. return "Chat0.htm"
    , l% C% Y/ L2 c5 e- L* L4 G
  46. elif n == 1:
    . \( Z+ M7 R8 y" R6 |5 @; w
  47. if st.get('chat1') == None :% ~4 j& F5 N# Z6 Z2 b: W
  48. st.set("chat1", "true")
    / y; M7 F: P+ A! ^# o9 W3 f
  49. return "Chat1.htm"
    8 Z4 U- P1 [& k4 c5 r
  50. elif n >= 4:3 v. G. h0 W4 F9 P
  51. return "Chat4.htm"6 `4 ]( A, y+ F4 I7 M$ A- R8 ~
  52. return "Collect "+str(n)+" of 4 fangs"
    + B; h7 F+ I6 j$ s- @8 P) m: }3 I! Y
  53. return0 U' L7 @9 o, R8 n- c' B6 A3 `. P
  54. ( a  E) k% ~1 i
  55. QUEST    = Quest(201, "Tutorial", "Tutorial quest")
    $ g6 w, H2 F/ b( [6 ?1 f& P
  56. CREATED = State('Start',    QUEST)
    ( }2 Z  u2 N: N1 ^
  57. STARTED = State('Started', QUEST)% D- ^; P  T  e% \0 z0 o
  58. COMPLETED = State('Completed', QUEST)* n, f& b9 D: M
  59. ) G" U7 K! b- @( q# N
  60. QUEST.setInitialState(CREATED)) k; M1 m, }* @" I  `; A
  61. QUEST.addStartNpc(7056)/ j' h9 j5 Y0 h% E" [
  62. QUEST.addStartNpc(7012), D: Y( `7 W! h% E! T7 ~- X
  63. QUEST.addStartNpc(7009)2 G8 \% m+ ]! w6 \
  64. QUEST.addStartNpc(7011)0 t+ |- |+ b+ G0 E3 B, d# \

  65. 8 W4 Z* t8 W+ d5 L) p! I# b5 o
  66. STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
    7 t* u. n/ o. b# ]; C
  67. STARTED.addKillId(KELTIR_NPC_ID)5 L  R3 x/ H* h- C7 ~
  68. STARTED.addTalkId(7056)+ H$ {9 e5 [# B! q' d
  69. STARTED.addTalkI d(7012)/ ]4 z' p) O( }, P- M# K: {
  70. STARTED.addTalkId(7009)
    ' m4 z% l7 a% [2 B( o
  71. STARTED.addTalkId(7011)
Скопировать код
% @0 C, B% h* n
& p/ a6 k  L! v8 n# K
Чтобы ответить, вам надо авторизироваться в системе Вход | Зарегистрироваться

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

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

638638758

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

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

admin@artace.ru Онлайн

QR-код

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