Top.Mail.Ru

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

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

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

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

x
Хроники        Interlude( r! C9 f( u8 Y: D( C
Сборка        L2j
0 w, [9 ^; q0 w: i( yОбратите внимание: в файле htm стартового NCP обязательно должна быть ссылка на квест:
0 D! H4 a& G( P& T4 j( S
  1. STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код
Для этого квеста больше ничего не надо. Все необходимое для корректной работы квеста уже добавили. Вот полный текст квеста:
( m/ e4 ?. v7 J! B# ~1 B2 F# S8 _7 d. l8 B& v- |
  1. if getCount(st) >= 4 :. C  h  r9 F- P  f
  2. completed(st); [) z3 K2 t( i8 A! a' j
  3.   return0 x$ ?, g5 `- y8 g4 M

  4. ! y9 s& c6 P/ @" D) r
  5. class Quest (JQuest):- c# N/ `3 s. ~( ?& j
  6.   def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)
    + X/ |) @* q  @; M
  7.   def onEvent (self,event,st):
    & V4 i7 L1 n, f6 d8 W$ f- q
  8. id = st.getState()
    ' ?  Z  a9 X& k9 Y& @
  9. if   id == CREATED  : st.setState(STARTED)
    6 G, X- t" X( P5 O. H
  10. elif id == COMPLETED: pass+ _2 F3 a4 Y1 w5 I. e# L
  11. elif id == STARTED  : check(st)
    6 u4 e, _$ ^& H4 O2 J; }+ F. Z: O
  12. return
    8 S4 i" @7 w" [! C: T
  13. . C5 P) d7 F$ P5 j" L
  14. QUEST     = Quest(201,"Tutorial", "Tutorial quest")
    , ~" v/ V% V/ K
  15. CREATED   = State('Start',     QUEST)& C8 W( T# F% K. C3 |" }
  16. STARTED   = State('Started',   QUEST)
      Y! g( d1 O, [- F; Z3 M( j: U7 x
  17. COMPLETED = State('Completed', QUEST)
    0 @  e9 e; t5 y$ A+ v$ I( `$ K
  18. 4 [* R# r; ]1 ~0 t' `9 ^' d/ R
  19. QUEST.setInitialState(CREATED)' ~, u% f/ _+ B
  20. QUEST.addStartNpc(7056)5 g: K4 k# c2 a+ f- e
  21. STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код
Теперь рассмотрим, как это работает.
3 J$ T& W0 j) U1 {( VИгрок подходит к начальному NCP (в данном случае 7056), нажимает на «Quest». Квест будет создан и состояние квеста перейдет к CREATED и игроку будет показана страничка Start.htm с описанием квеста. Тогда метод onEvent, поле открытия странички Start.htm переведет состояние квеста в STARTED и игроку будет показана страничка Started.htm, где будет опсание того, как найти keltirs и .т.д.' [, L; S' {$ k) P! v  _1 @

3 k" V5 t( o# ^0 y  G7 Y, g/ V! B8 L

6 S% [- R' V1 O0 D3 l% AПри состоянии STARTED будет зарегистрирован дроп «fangs» при убийстве keltirs. Игрок может вернуться к стартовому NCP и спросить о квесте – метод onEvent будет вызван снова. Если у игрока не хватает необходимого количества предметов, то метод check() не переведет квест в следующее состояние и Started.htm будет показана снова. Но если игрок собрал необходимее количество предметов (в данном случае 4 клыка), то метод check() вызовет метод completed() который переведет квест в новое состояние COMPLETED, заберет все клыки, даст карту мира, т.к. это награда за квест, покажет Completed.htm и завершит квест.3 m4 Q- s4 J, @9 f" e+ R4 e- m
5 r9 g' ~+ l; ^9 p

; _! p' h- R6 k. P- R; VТеперь давайте сделаем наш квест более похожим на то, что он должен из себя представлять.; f# X: p" J) A+ n5 S$ N; I
Прежде всего у нас есть 3 метода для объявления их в Яве – onTalk, onKill и onEvent. Если методы onTalk и onKill не объявлены, то за них все будет делать метод onEvent, т.е. определять квестовых монстров и вызывать диалоги NCP. Есть примечание, методы onTalk и onKill будут вызывать только диалоги с NCP в зависимости от текущего состояния квеста. Метод onKill будет вызываться только тогда, когда мы убиваем квестового монстра.. S( _7 n! G  t2 f

: c. M+ w/ }  ^
0 d3 v- ^- |1 E! B. K3 t8 i* G
Давайте рассмотрим как вызывается метод onKill при убийстве keltir в состоянии квеста STARTED:
1 ^5 M  C# Z6 s3 R; f
  1. STARTED.addKillId(KELTIR_NPC_ID)
Скопировать код
и метод onKill в классе Quest:; y/ _' w( n$ X) W& l

1 I- y8 n! p: x5 Z
  1. class Quest (JQuest):6 z( [# K- u7 |  ]- R4 W+ o
  2.   ...( D8 ?2 {' ^& |0 l
  3.   def onKill (self,npcId,st):& `9 e7 s: L* U3 o; B
  4. if npcId == KELTIR_NPC_ID:
    9 b7 J+ @" I. T
  5.    n = getCount(st)- f3 v) c" ]2 y
  6.    if   n == 0:+ [/ ^5 N9 L5 N+ D+ `- X& Z
  7.        return "Chat0.htm"
    2 A" V) J2 D. z+ D8 h) S6 g
  8.    elif n == 1:6 J4 p4 ~  i. d( x. A
  9.        return "Chat1.htm"3 }. d3 W) ^0 c6 {
  10.    elif n >= 4:( H/ j! s- y5 q6 T/ e$ l# O; A
  11.        return "Chat4.htm"
    , q" G5 p! j6 I" A: P' o, F
  12.    return "Collected "+str(n)+" of 4 fangs"
    / n1 v6 O4 l0 D& C$ x* r4 E
  13. return
Скопировать код
Метод onKill (а так же метод onTalk) имеет следующие параметры:3 m  Z* t% l! t/ @4 x* K
5 ^& ^* S/ E6 Y( S5 Q- E

; a. y% I; ~! R6 b- ?, q• self – квест4 b4 w$ E( s! T
• npcId – ID NCP, которого мы должны убивать (если это метод onTalk, то ID того NCP, с которым мы должны поговорить).8 U' r/ r4 ?  H& w  |; d' J0 E% \
• st – текущее состояние игрока.+ v6 w) S/ s  i$ [& v7 x
, `( V" g' J# M# m$ `- x

/ N/ z, O5 ^) L4 F- g3 ?1 j" aВ этом методе мы проверяем и отмечаем, является ли убитый NCP keltir’ом. В основном эта проверка не нужна, т.к. у нас только KELTIR_NPC_ID.0 q% r/ y8 e5 q& M
+ G' F! Z$ C! t: E8 t, N. ]0 ?

! M5 D8 W) l' B# \3 F/ n3 E8 j' dЗатем проверяем количество предметов (в данном случае количество клыков), и если их вообще нет, то возвращаем строку "Chat0.htm", если только один предмет, то возвращаем строку "Chat1.htm", если же предметов 4 или больше, то "Chat4.htm". Если строка возвращена из методов onEvent, onKill или onTalk, то сервер покажет соответствующие htm. В Chat0.htm может иметь следующий текст: «Вы не имеете ни одного клыка, возвращайтесь позже, когда соберете 4 штуки и бла, бла, бла…», в Chat1.htm может быть следующий текст: «У Вас всего 1 клык, по этому соберите еще…». В Chat4.htm – «Вы собрали необходимое количество предметов, возвращайтесь к вашему тренеру, что бы завершить квест…»! C- T: z' C) c% t# ?  p
  f. m; W) t! J$ z

  C2 b1 F* p4 S! lПримечание: если в строка return начинается с "<html>", то будет показана страничка html с текстом, который стоит далее. Так вместо:( R2 g# E. A: u9 @" {4 V
return "Chat4.htm"9 a* U% R5 u9 f/ |9 S4 e9 C

, M5 M  \( ^/ S; d( @5 `4 S
% C) N+ _5 X4 Q& f3 ?
можно поставить:
" O7 k5 K# H8 ]+ e, O
  1. return "<html><body>Return to your trainer to complete the quest</body></html>"
Скопировать код
Так же если строка заканчивается без .htm или в начале нет <html>, то текст будет выведен, как системное сообщение в окне чата. В нашем случае мы сделаем так, что бы при каждом убийстве keltik выводилось системное сообщение: «Собрано N из 4-х клыков».
7 {3 B% u8 \0 W$ r/ t' x0 Q4 ~
) c( _3 K$ O2 v  J- N1 r

- |0 K( {( K& R. \( V3 Y( iНаш код для onKill имеет один недостаток. Он будет постоянно показывать Chat0.htm, Chat1.htm и Chat4.htm, нам же необходимо, что бы Chat0.htm и Chat1.htm показывались только один раз. Как нам это сделать? С помощью переменных.- d( H8 {; u; @7 y8 X' h3 E* e
+ j) j6 s3 x; T
' ^- R8 X- T, P# Q3 q  B1 A
В каждом квесте строки могут храниться с помощью переменных. Эти переменные сохраняются в Вашей БД. В каждом методе мы можем назначить, прочитать и удалить переменные. Давайте изменим метод onKill, так что бы каждый диалог вызывался только один раз.
% K# k: N& d8 _" z  v
  1. def onKill (self,npcId,st):% Y1 |1 T5 s  ^& w
  2. if npcId == KELTIR_NPC_ID:- l0 ~7 C4 @  s+ S1 A
  3. n = getCount(st)& J8 V7 L7 c7 u; I! k! K3 I" J+ J
  4. if n == 0:
    ; y- O8 S4 e( s5 L9 M: p
  5. if st.get('chat0') == None :* k: W7 v, C) W) i$ Q* |
  6. st.set("chat0", "true")& f2 h8 T% ]& y- s# x2 s' p  q& c
  7. return "Chat0.htm"7 ~: P  g; n' U( s! \$ I! d/ H
  8. elif n == 1:9 O; K9 B: T1 B
  9. if st.get('chat1') == None :9 L4 L4 t6 b3 a( H) k) M! J
  10. st.set("chat1", "true")
      ^6 u% v0 w/ S! j) _
  11. return "Chat1.htm"# U; j6 q# C  z' X
  12. elif n >= 4:
    & F$ n6 }$ p3 m( N
  13. return "Chat4.htm") R9 w! I  k/ R" ]1 e. e- ?8 F
  14. return "Collected "+str(n)+" of 4 fangs"
    - E/ D! r# T7 X3 Z8 ?! e8 p8 u4 k
  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.
% d1 M; y% J( r
+ k6 u1 C7 Q! f( ~# R" G

$ w/ Z/ T1 v8 M3 @7 g) Z0 F# rВот конечный рабочий вариант квеста:) S9 ~8 @+ `& x
  1. import sys
    " A: ^: m# F4 j( T
  2. from net.sf.l2j.gameserver.model.quest import State: O/ o( G& W" L6 W* s5 y
  3. from net.sf.l2j.gameserver.model.quest import QuestState- `! q' D; V: F
  4. from net.sf.l2j.gameserver.model.quest.jython import QuestJython as JQuest2 Q! x! j4 I4 e" r7 F9 Q4 G0 a

  5. ' T: P0 |$ K0 \8 ^+ s% q0 m
  6. KELTIR_NPC_ID = 12082. [) T& f" V) O7 G
  7. FANGS_ITEM_ID = 1859
    $ p. c% l0 I; G% b
  8. DROP_RATE    = 500000
    , I- ?/ c; A3 h5 z! x, k7 T* z
  9. 2 E3 |0 I4 i- m( i' W
  10. WORLD_MAP_ITEM_ID = 1665
    7 Z( m  Z& o0 w& x5 `* v$ i/ e6 Z

  11. * Q4 ~! m4 {- R/ @
  12. def getCount(st) :
    , G# i3 J7 v- s. X1 R
  13. return st.getQuestItemsCount(FANGS_ITEM_ID)$ S0 j$ N& k7 J& P5 ~1 w

  14. - y' C% h5 i+ t4 c. Z% P
  15. def completed(st) :6 h. i, i# F: j
  16. st.setState(COMPLETED)
    : a. B5 J# @: |  ^- o0 I" b/ e
  17. st.clearQuestDrops()
    6 ]; _7 ]3 }( a8 n& O; V# }- v
  18. st.takeItems(FANGS_ITEM_ID,-1)' I* x: ]* b) n6 a4 G8 y9 f! X
  19. st.giveItems(WORLD_MAP_ITEM_ID,1)8 W( g& \9 F% ]4 O1 Y0 `1 }4 R: L
  20. st.exitQuest(False)8 \, s9 u$ t* P, T. i4 a- a
  21. return
    7 t) j9 {/ ]# V) b% L
  22. 6 g3 K) g( T+ f
  23. def check(st) :% ?  d1 w$ d2 h: s8 k! y# |( B
  24. if getCount(st) >= 4 :
    ) {* ?8 @6 @" f! O* Y& {
  25. completed(st)" ~$ f) S9 Z: o* u8 e
  26. return5 P9 [2 n( u' K' j) o$ W
  27. & ]3 F$ u4 j8 v- J3 w
  28. class Quest (JQuest):( {  A* k6 e7 t! k. N

  29. & ]) h# O" b* A# l
  30. def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)
    " A3 J% m# T6 c; N

  31. 6 [; R$ a) t# U6 Q% N
  32. def onEvent (self,event,st):5 h  \. G6 u$ F. ~, V
  33. id = st.getState()
    ) W* J. P/ @! J' Q/ ^$ X$ L
  34. if id == CREATED : st.setState(STARTED)
      n9 ?8 X! b& b2 a/ E, N4 X/ @
  35. elif id == COMPLETED: pass
    8 x0 s& L$ v. ?7 V
  36. elif id == STARTED : check(st)
    - c+ I, y6 w0 E; L1 e
  37. return( l. X0 v7 G% k3 t) t+ s6 v# M

  38. 3 E8 `* W- H( ^7 p- s
  39. def onKill (self,npcId,st):0 [" C$ o! ?4 g7 f4 O8 e
  40. if npcId == KELTIR_NPC_ID:* [6 R" R; P& Z
  41. n = getCount(st)
    + `6 |& @% _# \6 V! r& T9 i0 G
  42. if n == 0:
    ( u! m. y; c* B; E% z$ l
  43. if st.get('chat0') == None :* @2 @8 e+ A, ~# v
  44. st.set("chat0", "true")
    9 l% A( R# L( d/ R8 T
  45. return "Chat0.htm"/ F( V6 O2 {0 C& h8 ]
  46. elif n == 1:5 R' s6 V7 t2 I
  47. if st.get('chat1') == None :
    ) |& f7 ?& U7 B4 }$ o  I6 M! T3 a
  48. st.set("chat1", "true")) V# K1 [  D2 y1 P/ M0 @
  49. return "Chat1.htm": l# ~1 f3 A1 B1 A8 O$ [4 w
  50. elif n >= 4:3 B! S. ~4 E3 |  |2 `# ]& {
  51. return "Chat4.htm"1 f: Q: B( L5 i; c
  52. return "Collect "+str(n)+" of 4 fangs"+ g$ r; T- m: J
  53. return, a5 r0 A4 w, j( }- U' u# h6 D

  54. . c" L( j: G/ Z' _, Q4 P( Q
  55. QUEST    = Quest(201, "Tutorial", "Tutorial quest")
    ' O. s( A; {" ^; @6 W  w' ^+ |
  56. CREATED = State('Start',    QUEST)! J5 s! }( w* H- b- ^
  57. STARTED = State('Started', QUEST)6 `" Z+ Z" U1 [; r% C4 S" Y% a
  58. COMPLETED = State('Completed', QUEST)$ [7 Q$ A. B% b
  59. " A* L, ~7 w- p" G9 [1 w6 j
  60. QUEST.setInitialState(CREATED)3 X; F4 L# n; O
  61. QUEST.addStartNpc(7056)
    - M( r& ^3 W, k* z4 O" w! m& a
  62. QUEST.addStartNpc(7012)8 d5 A$ S3 R2 Q& ^6 ]. ]9 i. L
  63. QUEST.addStartNpc(7009)
    ' U" C* \  M# \
  64. QUEST.addStartNpc(7011)% o7 A0 J0 `- o8 ?2 o

  65. & W1 N: d9 Z0 R" q- B; j
  66. STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)( S& a$ S8 {5 L$ _: p7 f, S
  67. STARTED.addKillId(KELTIR_NPC_ID)+ P3 `) ^% y( `: `0 L2 b# m
  68. STARTED.addTalkId(7056)+ {( ^$ b5 P/ g( s. v! Z* G
  69. STARTED.addTalkI d(7012)
    , O" w, e( @  R6 y0 p: G0 D
  70. STARTED.addTalkId(7009)
    / @2 v+ r- [* X# }
  71. STARTED.addTalkId(7011)
Скопировать код
8 b$ R' ~# ~) S+ ]

0 K! A- ]: o' h8 t/ E6 G! m
Чтобы ответить, вам надо авторизироваться в системе Вход | Зарегистрироваться

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

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

638638758

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

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

admin@artace.ru Онлайн

QR-код

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