Top.Mail.Ru

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

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

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

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

x
Хроники        Interlude  R9 G* U% G5 F/ u  y7 }3 u2 b
Сборка        L2j
( ]/ x7 I/ |4 r" A% VОбратите внимание: в файле htm стартового NCP обязательно должна быть ссылка на квест:
+ D' i- V% S; [' w
  1. STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код
Для этого квеста больше ничего не надо. Все необходимое для корректной работы квеста уже добавили. Вот полный текст квеста:
/ _6 K9 y9 s% I' X; c) G
! c" b6 o# K  J" L3 Z; @8 {7 h
  1. if getCount(st) >= 4 :. H! I% Z( C$ D7 j$ I
  2. completed(st)
    - _* @: p4 @& w5 j
  3.   return
    1 Q) k! A" g3 G3 t/ ~
  4. 2 e8 l1 A% x5 V1 w
  5. class Quest (JQuest):
    3 B5 U+ z( }0 u& \8 R( E6 T
  6.   def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)
    5 W: y! L& {" y* x: T) T
  7.   def onEvent (self,event,st):
    ! e, _. Z0 o9 ?9 x
  8. id = st.getState()# g. X$ T! k! V6 P" m
  9. if   id == CREATED  : st.setState(STARTED)1 F/ D5 m; T0 X$ @5 m; F( }2 `6 Z
  10. elif id == COMPLETED: pass1 p5 ?$ N' [$ P9 Y7 Z% G4 K
  11. elif id == STARTED  : check(st)
    9 \9 c! F$ c* Z( m
  12. return
    ) K  L1 s: @. U: Z; w
  13. 6 c) w7 A$ s$ L( n1 V+ ]/ r
  14. QUEST     = Quest(201,"Tutorial", "Tutorial quest")
    5 R3 U8 n! U8 K' f
  15. CREATED   = State('Start',     QUEST)
    3 P! a! R5 {/ ?9 |  ]
  16. STARTED   = State('Started',   QUEST)' y0 V6 A) F5 B5 D' Z$ w0 X
  17. COMPLETED = State('Completed', QUEST)
    ; ^' q. N% t0 I& O

  18. 0 g; ^* O: q: `
  19. QUEST.setInitialState(CREATED)
    . U- o9 }" m  [0 r% R
  20. QUEST.addStartNpc(7056)
    6 u, P5 M, r3 f1 Q& n
  21. STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код
Теперь рассмотрим, как это работает.
: \5 L# T# q" q! EИгрок подходит к начальному NCP (в данном случае 7056), нажимает на «Quest». Квест будет создан и состояние квеста перейдет к CREATED и игроку будет показана страничка Start.htm с описанием квеста. Тогда метод onEvent, поле открытия странички Start.htm переведет состояние квеста в STARTED и игроку будет показана страничка Started.htm, где будет опсание того, как найти keltirs и .т.д.( u5 E1 F0 j7 R# ]4 G! p
' f9 L+ X- I; G+ y# s
1 k# w$ l" I& ~. N, x- b4 |
При состоянии STARTED будет зарегистрирован дроп «fangs» при убийстве keltirs. Игрок может вернуться к стартовому NCP и спросить о квесте – метод onEvent будет вызван снова. Если у игрока не хватает необходимого количества предметов, то метод check() не переведет квест в следующее состояние и Started.htm будет показана снова. Но если игрок собрал необходимее количество предметов (в данном случае 4 клыка), то метод check() вызовет метод completed() который переведет квест в новое состояние COMPLETED, заберет все клыки, даст карту мира, т.к. это награда за квест, покажет Completed.htm и завершит квест.& P! Z3 O0 H- l

" W; r/ d+ l- u% x( s

2 W& p* c5 r& n; n! hТеперь давайте сделаем наш квест более похожим на то, что он должен из себя представлять.; A& s6 E) g- p3 c' w! k
Прежде всего у нас есть 3 метода для объявления их в Яве – onTalk, onKill и onEvent. Если методы onTalk и onKill не объявлены, то за них все будет делать метод onEvent, т.е. определять квестовых монстров и вызывать диалоги NCP. Есть примечание, методы onTalk и onKill будут вызывать только диалоги с NCP в зависимости от текущего состояния квеста. Метод onKill будет вызываться только тогда, когда мы убиваем квестового монстра./ B6 h7 U% c- e- e/ Q
6 C  ^- E" d9 I% M/ m. i1 z
1 r  R2 H, E* S
Давайте рассмотрим как вызывается метод onKill при убийстве keltir в состоянии квеста STARTED:- t1 U4 L3 i  d6 g& s% \' [- v
  1. STARTED.addKillId(KELTIR_NPC_ID)
Скопировать код
и метод onKill в классе Quest:
- u1 n! z/ V% H1 L0 t9 c  j$ J8 B5 V& H  R
  1. class Quest (JQuest):
    ' b$ {! m% b% x; N  g7 z0 k
  2.   ...
    & i" o7 F' x0 i6 E3 b
  3.   def onKill (self,npcId,st):0 u* G7 w+ J, w& b# J+ P
  4. if npcId == KELTIR_NPC_ID:
    7 i9 ^9 k. H  l* D" n( p, d+ @
  5.    n = getCount(st)
    + A  d- a3 h% ]# t
  6.    if   n == 0:
    # ^% o" k# h# D6 W# y0 O
  7.        return "Chat0.htm"
    3 g! l  P1 |: a1 D1 @( ^: Y
  8.    elif n == 1:! D. n% s2 _5 g2 ?6 R- I
  9.        return "Chat1.htm"
    5 Y0 A! `. A+ J+ p  c* T* o/ r( ?, O
  10.    elif n >= 4:
    0 q/ W, @. w0 f& f: w8 }! L6 n
  11.        return "Chat4.htm"
    3 d8 F/ R) I: T$ w% V2 k3 g5 m0 ?
  12.    return "Collected "+str(n)+" of 4 fangs"% h) W8 F* a: @4 J5 x
  13. return
Скопировать код
Метод onKill (а так же метод onTalk) имеет следующие параметры:4 X5 F* s; m+ w+ L" a9 |

( }: x2 h- `0 @; A

" i% h( ?0 T: S: a• self – квест/ v/ C1 U; N5 h) g* V' K
• npcId – ID NCP, которого мы должны убивать (если это метод onTalk, то ID того NCP, с которым мы должны поговорить).
4 q8 E& ~$ h) U• st – текущее состояние игрока.
% n( k' @6 s. m: k3 [3 h4 j, {' Z" q; P* H
5 l% M' x4 x& r2 X
В этом методе мы проверяем и отмечаем, является ли убитый NCP keltir’ом. В основном эта проверка не нужна, т.к. у нас только KELTIR_NPC_ID.
$ c$ D, K  H; o) Z7 c* B, ~. I" U' ~4 h8 {

" N; n: x4 n1 L  y; B: H, B/ xЗатем проверяем количество предметов (в данном случае количество клыков), и если их вообще нет, то возвращаем строку "Chat0.htm", если только один предмет, то возвращаем строку "Chat1.htm", если же предметов 4 или больше, то "Chat4.htm". Если строка возвращена из методов onEvent, onKill или onTalk, то сервер покажет соответствующие htm. В Chat0.htm может иметь следующий текст: «Вы не имеете ни одного клыка, возвращайтесь позже, когда соберете 4 штуки и бла, бла, бла…», в Chat1.htm может быть следующий текст: «У Вас всего 1 клык, по этому соберите еще…». В Chat4.htm – «Вы собрали необходимое количество предметов, возвращайтесь к вашему тренеру, что бы завершить квест…»; j$ x" {! k4 R& H

8 E7 }1 a+ x8 K& c- H
, U2 I5 h/ k9 N: B) u9 c7 U
Примечание: если в строка return начинается с "<html>", то будет показана страничка html с текстом, который стоит далее. Так вместо:+ c; q/ s4 S+ K: Z; w
return "Chat4.htm"
0 m9 r* P8 P' w+ W! v8 I2 p3 A3 I2 ]" ^: ?/ r- D' C
3 F' V9 C( X! W0 e
можно поставить:
+ d* N, l- x1 T" Z
  1. return "<html><body>Return to your trainer to complete the quest</body></html>"
Скопировать код
Так же если строка заканчивается без .htm или в начале нет <html>, то текст будет выведен, как системное сообщение в окне чата. В нашем случае мы сделаем так, что бы при каждом убийстве keltik выводилось системное сообщение: «Собрано N из 4-х клыков».4 O6 W. f0 J- p4 Z/ P( |3 F7 t

: n  \8 t9 Y, t% b1 Y$ l* S
! m5 q. I" M5 k+ m
Наш код для onKill имеет один недостаток. Он будет постоянно показывать Chat0.htm, Chat1.htm и Chat4.htm, нам же необходимо, что бы Chat0.htm и Chat1.htm показывались только один раз. Как нам это сделать? С помощью переменных.- @! F4 e1 W- p

1 N" o9 B3 k. L6 j" Y

5 ~& n, Z5 s4 FВ каждом квесте строки могут храниться с помощью переменных. Эти переменные сохраняются в Вашей БД. В каждом методе мы можем назначить, прочитать и удалить переменные. Давайте изменим метод onKill, так что бы каждый диалог вызывался только один раз.
  I" x4 j  z& x; q1 @
  1. def onKill (self,npcId,st):/ y5 p# w$ X8 y+ A* o
  2. if npcId == KELTIR_NPC_ID:
    9 m% {( x) Q2 q8 Q- U
  3. n = getCount(st)
    : |3 S% G9 {& \% i% O
  4. if n == 0:
    / M3 t/ N% f# g3 @7 a% z
  5. if st.get('chat0') == None :
    " }7 n. y4 l# W( G9 w2 c4 B% R
  6. st.set("chat0", "true")& S. E8 E( L- O# w
  7. return "Chat0.htm") t1 n" i3 a& X, M- E
  8. elif n == 1:
    . s. R6 e0 t& B; f
  9. if st.get('chat1') == None :' P, a+ V3 ~4 ~" H) x
  10. st.set("chat1", "true")* F- h$ I, O! Y2 Q" p
  11. return "Chat1.htm"
    0 L9 G$ Y3 z+ P8 |
  12. elif n >= 4:
    : c/ C7 ]# Q8 G: C, {
  13. return "Chat4.htm"
    ) h( M8 M( D7 P/ t3 o5 l
  14. return "Collected "+str(n)+" of 4 fangs"* I* n7 c/ q& D' I; B6 ~; B2 R
  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.
) ~, g0 E1 B& x5 q+ d  d" Y  V5 |3 r  V8 F1 q; L

% C1 @- |1 S! z- Q- y0 AВот конечный рабочий вариант квеста:, f. \4 G9 W# |2 E. l8 j
  1. import sys6 R; \6 j  B9 n/ {6 x7 W
  2. from net.sf.l2j.gameserver.model.quest import State
    + p; l" j& g2 C( W# u8 r3 S  [
  3. from net.sf.l2j.gameserver.model.quest import QuestState/ p  _6 s: P0 u6 I- J& P
  4. from net.sf.l2j.gameserver.model.quest.jython import QuestJython as JQuest
    ' X4 ^) J! E" Y% ?# S

  5. ( J$ Q& m- p4 ~8 R( @% M  X0 K
  6. KELTIR_NPC_ID = 12082" N, f5 U. U+ J+ j* b
  7. FANGS_ITEM_ID = 1859
    # r# S2 K5 W7 k# A( `; f
  8. DROP_RATE    = 500000
    $ s( ]8 y; U% B( a) i1 ~
  9. . U4 u) S- e: z! g. A! V! x
  10. WORLD_MAP_ITEM_ID = 1665
    & c. @, b) y" v! L' b; B% L2 a3 f
  11. ; c2 h( l  V6 V6 d3 J
  12. def getCount(st) :
    % E( ~6 U$ n, z9 x
  13. return st.getQuestItemsCount(FANGS_ITEM_ID)* x$ Y) m. e; B5 z

  14. : }& F; o, m* l& i! f; W6 ^$ g
  15. def completed(st) :7 f9 y  H5 C" C  A5 C  E
  16. st.setState(COMPLETED): A# X" B# j2 m
  17. st.clearQuestDrops()5 g" e& W, M$ m
  18. st.takeItems(FANGS_ITEM_ID,-1)
    # Y2 k, E+ e6 r2 @, d" Y& [
  19. st.giveItems(WORLD_MAP_ITEM_ID,1)
    ; `: g0 v5 M9 P' P( h2 x
  20. st.exitQuest(False)
    / u; `& C8 e  i% }$ q7 ~
  21. return
    . s6 Z3 x* R  A$ J. P! H/ @
  22. ( v7 P$ O( ?+ ^' }6 v; ~
  23. def check(st) :
      w6 q6 x- y! z% K' ^- ~/ d3 |. K  d
  24. if getCount(st) >= 4 :
    9 `5 v2 Y, @5 W
  25. completed(st)
    , f% L8 @3 S- Q" x: S- v3 M1 ~
  26. return  l. @3 C( r. w6 i

  27. 0 `* v3 k4 k0 \5 `6 Q+ t  J
  28. class Quest (JQuest):3 u+ H- w0 z; H
  29. 4 L3 k; f% E, t
  30. def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)
    4 |$ [6 R' A; t7 {+ v: |+ H& x
  31. 7 e) T6 _  [4 Y  p; k; ]
  32. def onEvent (self,event,st):
    - y; H! X, j1 z
  33. id = st.getState()1 T# |# y) C) W& _0 d+ }; A
  34. if id == CREATED : st.setState(STARTED)
    7 H: {/ E6 `5 P4 V5 u1 ?
  35. elif id == COMPLETED: pass, p7 O# z" c, |: z4 o7 K. d
  36. elif id == STARTED : check(st)! R7 L0 b# p* X: F4 C4 f) H9 s
  37. return1 W0 k: J8 `7 g, o

  38. , p8 q0 q- ~" ^' n6 S  e4 U
  39. def onKill (self,npcId,st):2 a4 T6 ~# @3 @$ e. M$ K
  40. if npcId == KELTIR_NPC_ID:
    - E3 v/ ^8 u- c) R
  41. n = getCount(st)
    . ^' D+ {6 w7 Y+ N1 q. p+ N7 x" u
  42. if n == 0:
    $ ~; T3 Z0 H( J
  43. if st.get('chat0') == None :
    % J& H; h' N, O+ ~; @
  44. st.set("chat0", "true")
    # R) P  j* v3 ^; @. ~
  45. return "Chat0.htm"& S: b  V0 J; z! _$ c' H
  46. elif n == 1:( u! Y% \* R/ I1 u' v- E3 ?
  47. if st.get('chat1') == None :9 h2 Q; s& @+ {: @; y7 w! g
  48. st.set("chat1", "true")- l7 \9 \& o2 U( b0 l1 b5 c7 o
  49. return "Chat1.htm"% A- F6 P! D- b1 U1 W$ G" U
  50. elif n >= 4:- s0 f9 h5 _( b: s0 z1 t3 X0 S/ v- F
  51. return "Chat4.htm"
    / U& D5 k% b5 l! Y4 n* M3 h1 J' t# h
  52. return "Collect "+str(n)+" of 4 fangs"
    & K$ G" ]5 t* j  U5 Q7 e$ U+ [" K. v
  53. return. n' t4 o3 M2 u& |8 h8 V: w
  54. * w8 K* ^9 H$ q; `0 c* M
  55. QUEST    = Quest(201, "Tutorial", "Tutorial quest")
    ; I) r; P: S1 k7 x( M# C
  56. CREATED = State('Start',    QUEST)
    * {* c' x) U- m  d5 S$ w2 u
  57. STARTED = State('Started', QUEST)' ^+ F" a$ E' {" M
  58. COMPLETED = State('Completed', QUEST)- O' y3 Z1 L* M/ g$ a
  59. 0 c: B9 z) ~1 @; N5 C4 N
  60. QUEST.setInitialState(CREATED), K# h: K9 a  N; P4 `( H# _7 s
  61. QUEST.addStartNpc(7056)
    % B2 @* q$ Y$ i7 C
  62. QUEST.addStartNpc(7012)
    8 P1 ~2 a* F+ G+ k6 d( ?
  63. QUEST.addStartNpc(7009)
    6 o9 X8 P9 x; q' {) Q& _- T
  64. QUEST.addStartNpc(7011)
    ( Z1 g( K; c- p& M
  65. 3 w( D% k4 u& b9 _5 U
  66. STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
    # w% v! K! }, }8 f8 d7 m
  67. STARTED.addKillId(KELTIR_NPC_ID)" l- w. P9 a, f- j6 p
  68. STARTED.addTalkId(7056)
    ; r7 m* A. E1 u7 H- x
  69. STARTED.addTalkI d(7012)
    ; i  V; z( W$ T; c- D
  70. STARTED.addTalkId(7009)& C( V4 o6 Y, s* R6 H9 u0 U, e4 r
  71. STARTED.addTalkId(7011)
Скопировать код
5 S( {6 j  f# O0 A5 s1 X4 }
2 ?% \% Y8 O# J; m
Чтобы ответить, вам надо авторизироваться в системе Вход | Зарегистрироваться

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

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

638638758

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

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

admin@artace.ru Онлайн

QR-код

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