Top.Mail.Ru

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

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

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

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

x
Хроники        Interlude. p* u4 E8 g1 {: J0 g# X
Сборка        L2j
1 S2 u- A7 H0 q6 w  Z) XОбратите внимание: в файле htm стартового NCP обязательно должна быть ссылка на квест:* _& F! C( _# D4 [/ ?
  1. STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код
Для этого квеста больше ничего не надо. Все необходимое для корректной работы квеста уже добавили. Вот полный текст квеста:" n& d% n  ^8 W, w

' H1 x  A+ V$ k  D
  1. if getCount(st) >= 4 :
    , R+ E: C! P& t, Q! D7 w( M- h
  2. completed(st)  F& X, B2 f1 `
  3.   return
    ; `( \1 `/ V6 I+ A

  4. 2 b2 \; O  I( E, E
  5. class Quest (JQuest):# A& Y2 Z+ }: L5 r
  6.   def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)
    # |* Z. ]" j4 o/ o. b' C) d
  7.   def onEvent (self,event,st):" r$ G' m9 w+ t% _: X
  8. id = st.getState()0 S3 Q: V- [6 M: c- j7 ]
  9. if   id == CREATED  : st.setState(STARTED): S! w0 P, s% z5 s' f* V
  10. elif id == COMPLETED: pass) Y2 t7 O( g5 O: Y' N
  11. elif id == STARTED  : check(st)  i1 [: M' ?/ L, E( ?5 X1 {: b
  12. return( r0 d1 S! |! e: G! s% k

  13. 4 `$ E0 S' y+ S- Y! n% @! x
  14. QUEST     = Quest(201,"Tutorial", "Tutorial quest")& U2 ]4 Z5 D3 h' K9 {
  15. CREATED   = State('Start',     QUEST)( u0 L- p! K3 e
  16. STARTED   = State('Started',   QUEST); p. j4 f/ S4 I1 |) g
  17. COMPLETED = State('Completed', QUEST)
    7 \( A. A' o0 `* U( M

  18. 1 H; r) ^) b* g* w3 n3 H2 q
  19. QUEST.setInitialState(CREATED)
    0 Y* i# I; b* V$ G$ _* z) T, V8 X
  20. QUEST.addStartNpc(7056)
    - W# Y2 @% L! g/ V5 [. K! t
  21. STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код
Теперь рассмотрим, как это работает.
  B$ C7 J% i3 G- {Игрок подходит к начальному NCP (в данном случае 7056), нажимает на «Quest». Квест будет создан и состояние квеста перейдет к CREATED и игроку будет показана страничка Start.htm с описанием квеста. Тогда метод onEvent, поле открытия странички Start.htm переведет состояние квеста в STARTED и игроку будет показана страничка Started.htm, где будет опсание того, как найти keltirs и .т.д.7 V) @! R, A8 u; X
5 d, E: F; F$ e: [: `0 ~
; V: l$ j3 d, h, {" I
При состоянии STARTED будет зарегистрирован дроп «fangs» при убийстве keltirs. Игрок может вернуться к стартовому NCP и спросить о квесте – метод onEvent будет вызван снова. Если у игрока не хватает необходимого количества предметов, то метод check() не переведет квест в следующее состояние и Started.htm будет показана снова. Но если игрок собрал необходимее количество предметов (в данном случае 4 клыка), то метод check() вызовет метод completed() который переведет квест в новое состояние COMPLETED, заберет все клыки, даст карту мира, т.к. это награда за квест, покажет Completed.htm и завершит квест./ c) h- _1 b& t4 O! d, i

; X2 _5 c9 Y1 o& }  p6 ?0 e6 _
# @0 G- m: \& |) E
Теперь давайте сделаем наш квест более похожим на то, что он должен из себя представлять.7 k- M  A4 K. X, e9 `- i
Прежде всего у нас есть 3 метода для объявления их в Яве – onTalk, onKill и onEvent. Если методы onTalk и onKill не объявлены, то за них все будет делать метод onEvent, т.е. определять квестовых монстров и вызывать диалоги NCP. Есть примечание, методы onTalk и onKill будут вызывать только диалоги с NCP в зависимости от текущего состояния квеста. Метод onKill будет вызываться только тогда, когда мы убиваем квестового монстра.
# n  h. [# ^9 f& f; [/ F* h/ g* R) P0 G$ F# M! ^4 I$ C; k: R
7 y/ B1 h+ a) Y" Z- A
Давайте рассмотрим как вызывается метод onKill при убийстве keltir в состоянии квеста STARTED:
7 `, I5 X3 \9 |  B8 \* ~/ b3 g
  1. STARTED.addKillId(KELTIR_NPC_ID)
Скопировать код
и метод onKill в классе Quest:7 S1 ^5 w2 O* x2 @" f
( q  r" m! D+ d) X3 E5 B" n
  1. class Quest (JQuest):/ V9 G) M1 I7 u: W! a; r- w+ h% Q/ x
  2.   ...  B0 L1 ^* L- Y
  3.   def onKill (self,npcId,st):
    ' C5 S! G* g& d; n- X6 c+ q* x
  4. if npcId == KELTIR_NPC_ID:+ X0 b9 o. v# y# a
  5.    n = getCount(st)
    ( p$ ~3 A3 a4 u0 r0 N/ }9 v
  6.    if   n == 0:$ l& X! R- R2 k, g
  7.        return "Chat0.htm"
    , q+ E4 h+ u6 O' T8 t6 F
  8.    elif n == 1:1 P; p6 @: A; x+ n3 U4 L
  9.        return "Chat1.htm"
    1 K  F' {7 ?( `- z5 o5 N" ?6 a5 p
  10.    elif n >= 4:
    ! h# C# F; S- @
  11.        return "Chat4.htm"0 `: n$ o7 H: g! U! J4 n* y' t
  12.    return "Collected "+str(n)+" of 4 fangs"
    $ T  f% k  B1 v1 b0 [* a
  13. return
Скопировать код
Метод onKill (а так же метод onTalk) имеет следующие параметры:
1 D' P. v! t% F& v* B- ~) W/ a0 E9 b
1 I& j, D/ W( A4 b2 p. L9 M) y
• self – квест+ X! b8 T1 r* E* j; d
• npcId – ID NCP, которого мы должны убивать (если это метод onTalk, то ID того NCP, с которым мы должны поговорить).& b/ |1 o4 d  R, H! X
• st – текущее состояние игрока.
9 k  {. a5 j1 H* |2 n( I# E. Q$ q  I/ t7 o& l; ^

, |3 m4 q( h+ C- i% sВ этом методе мы проверяем и отмечаем, является ли убитый NCP keltir’ом. В основном эта проверка не нужна, т.к. у нас только KELTIR_NPC_ID.8 l1 T; s0 C- _( i- l

0 K$ r9 B3 D- d: ^2 {. O1 u
* m( ?, k: @( R
Затем проверяем количество предметов (в данном случае количество клыков), и если их вообще нет, то возвращаем строку "Chat0.htm", если только один предмет, то возвращаем строку "Chat1.htm", если же предметов 4 или больше, то "Chat4.htm". Если строка возвращена из методов onEvent, onKill или onTalk, то сервер покажет соответствующие htm. В Chat0.htm может иметь следующий текст: «Вы не имеете ни одного клыка, возвращайтесь позже, когда соберете 4 штуки и бла, бла, бла…», в Chat1.htm может быть следующий текст: «У Вас всего 1 клык, по этому соберите еще…». В Chat4.htm – «Вы собрали необходимое количество предметов, возвращайтесь к вашему тренеру, что бы завершить квест…»
6 D3 y. `' n9 H+ d2 u* r' f. F  _3 s/ u" P# A" I& Z+ n5 b$ y

  L* n8 s' m, W4 @Примечание: если в строка return начинается с "<html>", то будет показана страничка html с текстом, который стоит далее. Так вместо:' e% M* \3 e! Z  `
return "Chat4.htm"
& W  u. f; \9 Y7 J- e
; o* D+ x5 m# @5 x

# U# a& f- j  R  Z. p) Dможно поставить:- A% `4 w/ I( ?/ u: C: r( ^
  1. return "<html><body>Return to your trainer to complete the quest</body></html>"
Скопировать код
Так же если строка заканчивается без .htm или в начале нет <html>, то текст будет выведен, как системное сообщение в окне чата. В нашем случае мы сделаем так, что бы при каждом убийстве keltik выводилось системное сообщение: «Собрано N из 4-х клыков».
3 V, i8 g# _8 U! a7 H2 H3 e  o  u; I6 n0 ]
) R3 H6 w" b# ^7 c9 e( |% w$ }
Наш код для onKill имеет один недостаток. Он будет постоянно показывать Chat0.htm, Chat1.htm и Chat4.htm, нам же необходимо, что бы Chat0.htm и Chat1.htm показывались только один раз. Как нам это сделать? С помощью переменных.4 m- {2 a; h) a4 C  l! c7 E. t. ^
" b; y& p; y* u9 U, W/ T7 N* s

2 x, _3 H9 ?$ y9 }$ [В каждом квесте строки могут храниться с помощью переменных. Эти переменные сохраняются в Вашей БД. В каждом методе мы можем назначить, прочитать и удалить переменные. Давайте изменим метод onKill, так что бы каждый диалог вызывался только один раз.7 B1 g- \( ~' V$ b- p2 N
  1. def onKill (self,npcId,st):
    9 s' d5 I) m: T1 E0 a( S$ K; B# Z
  2. if npcId == KELTIR_NPC_ID:
    7 ^$ X8 @2 x3 O& q8 t
  3. n = getCount(st)8 d+ C" _, p6 ^
  4. if n == 0:* t+ n% Q5 z1 D4 Y: f
  5. if st.get('chat0') == None :
    ' @( I. @4 l/ S3 \
  6. st.set("chat0", "true")
    4 R( M# a7 S# a0 f1 l: \- b
  7. return "Chat0.htm"
    8 g+ d; m$ C+ N! v) i5 T3 I& b. P
  8. elif n == 1:
    ( ^0 S) W* Z$ y
  9. if st.get('chat1') == None :7 ~' g5 t) E) e2 I8 d3 }, H# q7 B
  10. st.set("chat1", "true")
    + u' q/ T% Y, V! a' ~
  11. return "Chat1.htm"
    . L, J1 z" b7 }; U- A5 `
  12. elif n >= 4:
      u1 k: D3 p+ A1 h$ C! _  C
  13. return "Chat4.htm"7 v! {* U; p1 @  |
  14. return "Collected "+str(n)+" of 4 fangs") R% W; h1 A+ B
  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.
. F4 h0 B! p. h8 k( C$ j' {# h( d
/ O' A& z- }" J' N( {  i# m
Вот конечный рабочий вариант квеста:2 F" |9 f- F% H  M
  1. import sys9 z% U! n* w. ~( D1 K7 X
  2. from net.sf.l2j.gameserver.model.quest import State; @/ j$ l6 j* n" u  S& l
  3. from net.sf.l2j.gameserver.model.quest import QuestState* N  }3 L+ H+ m& K" k6 g6 E/ T1 Q
  4. from net.sf.l2j.gameserver.model.quest.jython import QuestJython as JQuest) z2 G' E, ~( O( p

  5. " r: T. K) v. J/ q
  6. KELTIR_NPC_ID = 12082$ L4 Y, w3 S, j1 m# x" T7 O
  7. FANGS_ITEM_ID = 1859; E2 I, U' o5 e7 X- i) d) f
  8. DROP_RATE    = 500000* \& ]; S& O8 {) Z: C
  9. # L8 y' I+ W3 s7 p7 M) H8 T# }
  10. WORLD_MAP_ITEM_ID = 1665( v$ B! r+ d* Z! o9 h* d1 |
  11. 9 K1 h1 V4 b& G! a7 y
  12. def getCount(st) :
    * Y. a" {9 d$ g4 h, x
  13. return st.getQuestItemsCount(FANGS_ITEM_ID)& Y/ N4 R) F$ C

  14. : W0 @9 |3 F& r/ s* J# K! c+ @
  15. def completed(st) :6 s' S7 d/ B9 q+ [  K2 V+ J
  16. st.setState(COMPLETED)
    9 ^! W! i! N6 V: P( U3 u
  17. st.clearQuestDrops()
    / D. z' w% l! T9 H4 o4 E; ?; Q
  18. st.takeItems(FANGS_ITEM_ID,-1)1 G& M' x! o1 J
  19. st.giveItems(WORLD_MAP_ITEM_ID,1)
    + t/ _5 h/ U1 m1 Y/ _0 e
  20. st.exitQuest(False)
      ?; M, k0 j! m. c, t/ P
  21. return
    . j5 @0 S+ Q0 S% \4 e6 e
  22. 2 H  S1 q. a4 |- I& H2 @
  23. def check(st) :
    ; p7 D5 M% a: w" m: I# }& x0 w5 f
  24. if getCount(st) >= 4 :8 N2 X2 p4 @; n9 M4 L
  25. completed(st)
    $ w( ]$ {9 d7 J0 d/ z6 Y
  26. return% D5 Z  h, j# l0 ^. D9 z* a

  27. / K, K* {9 m& ?  p  b) e+ G9 ~
  28. class Quest (JQuest):
    : x9 u$ c* ~$ s& A. ]( C: D) |3 w; ]0 |

  29. & p: {" i! g) h2 ]
  30. def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)
    6 _7 L+ ]& G5 D' h% C

  31. 3 ~% |6 {% r* [5 f  J4 c
  32. def onEvent (self,event,st):9 Y- v7 v; `) ^+ @" {
  33. id = st.getState()
    : l9 a2 e# \" v, ]$ |, Z
  34. if id == CREATED : st.setState(STARTED)) T+ K/ g6 \( |2 U
  35. elif id == COMPLETED: pass9 K7 T0 Q3 S; c( o. B, ~. _
  36. elif id == STARTED : check(st)
    9 g* c) k$ O. \; Y7 ?7 }1 B
  37. return- c0 X3 r! g7 B  i& @$ G& |/ y. }# w

  38. # `0 F$ Y7 y) {2 F9 |
  39. def onKill (self,npcId,st):1 u. \& t9 ~1 w( J
  40. if npcId == KELTIR_NPC_ID:
    ! o2 {( h9 w: O2 f+ n
  41. n = getCount(st)2 y( y" i# z, V" a- y) }
  42. if n == 0:4 @6 B; j& E% T, c
  43. if st.get('chat0') == None :
    - z/ A2 ?7 \: q
  44. st.set("chat0", "true")
    ( O4 x& t1 @) m  }
  45. return "Chat0.htm"
    4 D0 L; i8 Y& m
  46. elif n == 1:
    & }" F8 [5 L( Y2 `6 A  n! O* X
  47. if st.get('chat1') == None :
      X0 U8 `8 _; z8 }7 I" L9 ^* v
  48. st.set("chat1", "true")) ^6 y9 t% j% o$ {) L+ m2 p
  49. return "Chat1.htm"/ R$ o9 v3 Z& U) ~* Z! {
  50. elif n >= 4:: [: _8 T& X, D7 ?) `# ]
  51. return "Chat4.htm"
    & j0 b7 w* J! {5 D: f& b$ i, R
  52. return "Collect "+str(n)+" of 4 fangs"! \4 @! @- F: ^  L6 F
  53. return5 l# T9 _$ e4 T' _

  54. ' H1 R6 J. n9 q( N
  55. QUEST    = Quest(201, "Tutorial", "Tutorial quest")
    / w1 j; i- H, b, N8 L. f
  56. CREATED = State('Start',    QUEST)
    % Z- q9 T/ H* h1 K- }
  57. STARTED = State('Started', QUEST)
    8 ]2 a9 a) _) e2 w% l: |$ A; v7 ^
  58. COMPLETED = State('Completed', QUEST)
      ]1 a0 c$ Q1 j7 R5 l- o; W7 f
  59. ' j5 X4 N2 `  ^
  60. QUEST.setInitialState(CREATED)
    " S) k7 d" s) \1 Z$ p
  61. QUEST.addStartNpc(7056)
    6 t/ A% c! j) T3 o6 J# N
  62. QUEST.addStartNpc(7012)
    3 D9 r: F* b, |
  63. QUEST.addStartNpc(7009)
    2 O/ I4 l, |. n4 f% Z% C
  64. QUEST.addStartNpc(7011)* M. ~7 s$ |, q) ~: Q1 k
  65. . D+ i5 Z) e# C4 O7 |# m
  66. STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
    + j2 a$ Y( W; v- C) r
  67. STARTED.addKillId(KELTIR_NPC_ID)5 w4 [  }$ b; w8 t+ y! W
  68. STARTED.addTalkId(7056)3 `! r0 o( X8 A5 |7 Z
  69. STARTED.addTalkI d(7012)3 s% L- m: H) ^9 }9 @9 D
  70. STARTED.addTalkId(7009)
    ) S1 q' B% T' P) u( y0 K. z
  71. STARTED.addTalkId(7011)
Скопировать код
( w9 V# V7 F7 K( B  z

  W' ^  m0 c6 X& z! s: l
Чтобы ответить, вам надо авторизироваться в системе Вход | Зарегистрироваться

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

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

638638758

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

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

admin@artace.ru Онлайн

QR-код

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