Top.Mail.Ru

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

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

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

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

x
Хроники        Interlude
7 s7 j1 C6 ]+ v6 A$ tСборка        L2j  a0 A) n" t' f
Обратите внимание: в файле htm стартового NCP обязательно должна быть ссылка на квест:
8 B1 F$ ?7 I) t, Y" A5 F
  1. STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код
Для этого квеста больше ничего не надо. Все необходимое для корректной работы квеста уже добавили. Вот полный текст квеста:
  \6 Q3 a( k7 M# h+ D+ B
+ {4 Z. \6 v! f: [, k) x
  1. if getCount(st) >= 4 :
    $ B' `+ \& K& |5 M
  2. completed(st)
    7 `! R' M* T0 C! B$ n
  3.   return. C- M, v9 ^4 i

  4. 3 B, l9 E  u% T* f5 g/ [6 n7 Z
  5. class Quest (JQuest):
    % L+ i8 a$ ?# {
  6.   def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)
    # |8 [" Z( a8 L
  7.   def onEvent (self,event,st):
    7 }# }! K* D2 S
  8. id = st.getState()
    # y- G- k: z3 w4 x) }8 c" }
  9. if   id == CREATED  : st.setState(STARTED)6 }! w9 m- i7 {; M3 p
  10. elif id == COMPLETED: pass+ v+ @9 M1 E2 t( A# s' w7 N
  11. elif id == STARTED  : check(st)$ V0 i5 d) J0 p4 Z
  12. return
    - c1 [9 w4 V4 Y7 k, L6 w) }
  13. 3 J& p6 Z+ z2 h; D5 A# p& U0 j1 t- O
  14. QUEST     = Quest(201,"Tutorial", "Tutorial quest")4 e/ a: o; j5 l% c1 [9 S4 s# T
  15. CREATED   = State('Start',     QUEST)8 N5 M, R" ]/ r
  16. STARTED   = State('Started',   QUEST)
    ; G, C3 Y$ `' V8 X7 \: R3 u" M' g$ Q
  17. COMPLETED = State('Completed', QUEST)9 r( z# n( f' E6 H8 A3 `
  18. ) h. v1 M7 e& Z" C, O
  19. QUEST.setInitialState(CREATED)
    , l* {) i  e0 {8 q% s
  20. QUEST.addStartNpc(7056)4 S) ~. q5 D  H: @& P* _
  21. STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код
Теперь рассмотрим, как это работает.4 h7 m9 E& m- z4 t* @5 W
Игрок подходит к начальному NCP (в данном случае 7056), нажимает на «Quest». Квест будет создан и состояние квеста перейдет к CREATED и игроку будет показана страничка Start.htm с описанием квеста. Тогда метод onEvent, поле открытия странички Start.htm переведет состояние квеста в STARTED и игроку будет показана страничка Started.htm, где будет опсание того, как найти keltirs и .т.д.
7 Z* I/ b" b0 l+ H6 n0 s" X* I( _
& J6 \2 D: o. N

' G, l, w3 ^- {7 O4 S; bПри состоянии STARTED будет зарегистрирован дроп «fangs» при убийстве keltirs. Игрок может вернуться к стартовому NCP и спросить о квесте – метод onEvent будет вызван снова. Если у игрока не хватает необходимого количества предметов, то метод check() не переведет квест в следующее состояние и Started.htm будет показана снова. Но если игрок собрал необходимее количество предметов (в данном случае 4 клыка), то метод check() вызовет метод completed() который переведет квест в новое состояние COMPLETED, заберет все клыки, даст карту мира, т.к. это награда за квест, покажет Completed.htm и завершит квест.
" q' {- F2 c! h! Y2 I
) I$ b. r4 G4 E' a5 e
1 m, E; _  X, u8 Y  W' `3 U
Теперь давайте сделаем наш квест более похожим на то, что он должен из себя представлять.
/ f: O# `" I7 v9 I5 cПрежде всего у нас есть 3 метода для объявления их в Яве – onTalk, onKill и onEvent. Если методы onTalk и onKill не объявлены, то за них все будет делать метод onEvent, т.е. определять квестовых монстров и вызывать диалоги NCP. Есть примечание, методы onTalk и onKill будут вызывать только диалоги с NCP в зависимости от текущего состояния квеста. Метод onKill будет вызываться только тогда, когда мы убиваем квестового монстра., y; v6 X- x/ k" P) H
( ], y! l8 L' z# h9 D7 G4 o

' x! Y, K, ]* y: T1 zДавайте рассмотрим как вызывается метод onKill при убийстве keltir в состоянии квеста STARTED:
' I6 V3 ?3 v. W% ~( |0 y
  1. STARTED.addKillId(KELTIR_NPC_ID)
Скопировать код
и метод onKill в классе Quest:
4 ]3 W- P! h) I5 {+ F. S1 x$ H
0 _2 n* u& Y7 a* t7 l% z  ]
  1. class Quest (JQuest):
      Y. t) w5 @6 z
  2.   ...2 k2 M5 n6 W5 n' L2 W- B, z( t' E
  3.   def onKill (self,npcId,st):6 K$ t1 {+ g# g
  4. if npcId == KELTIR_NPC_ID:3 W' }# e6 o! A4 G4 p
  5.    n = getCount(st)& N# f+ k6 z' B
  6.    if   n == 0:
    " f$ X' b5 c2 \1 Z3 J. O4 w; ?) |" Z8 b
  7.        return "Chat0.htm"  M$ `9 c# O0 `1 z& |6 Y
  8.    elif n == 1:
    9 ~' {, d+ N. f! O4 H
  9.        return "Chat1.htm"- d7 t( L' J! v3 @" A( c
  10.    elif n >= 4:( I  \  X4 i' Q3 C3 M/ v* C& k
  11.        return "Chat4.htm"# b; K, l; O( Y% q. [
  12.    return "Collected "+str(n)+" of 4 fangs"
    / z+ ?& S8 N* \) o( `1 t0 s. E
  13. return
Скопировать код
Метод onKill (а так же метод onTalk) имеет следующие параметры:
2 c' S/ G2 C. ~' N8 x$ g. F
, ~% [  g2 a# E1 r% W5 Y
' o# E+ U3 Z( N/ U1 E% k8 q! I+ S
• self – квест0 J0 ~7 d/ [. U! f: h
• npcId – ID NCP, которого мы должны убивать (если это метод onTalk, то ID того NCP, с которым мы должны поговорить).
' J1 x0 x2 }5 P+ l• st – текущее состояние игрока.
& B4 L3 G( Y) F/ a- @9 g8 ?; D7 v) Z
& v8 s& S, z5 V0 c

& `2 q) [1 z& {$ j* zВ этом методе мы проверяем и отмечаем, является ли убитый NCP keltir’ом. В основном эта проверка не нужна, т.к. у нас только KELTIR_NPC_ID.
& L6 P7 f! \  F8 b
0 e$ B( C1 p; d

; u' e: A: g1 i& @& k! C! kЗатем проверяем количество предметов (в данном случае количество клыков), и если их вообще нет, то возвращаем строку "Chat0.htm", если только один предмет, то возвращаем строку "Chat1.htm", если же предметов 4 или больше, то "Chat4.htm". Если строка возвращена из методов onEvent, onKill или onTalk, то сервер покажет соответствующие htm. В Chat0.htm может иметь следующий текст: «Вы не имеете ни одного клыка, возвращайтесь позже, когда соберете 4 штуки и бла, бла, бла…», в Chat1.htm может быть следующий текст: «У Вас всего 1 клык, по этому соберите еще…». В Chat4.htm – «Вы собрали необходимое количество предметов, возвращайтесь к вашему тренеру, что бы завершить квест…», G1 N! T( V! H, D! ^! y- d

1 F" O) i+ W! O2 h- [. @

# f2 i* o3 _4 @$ p6 u% j: c  WПримечание: если в строка return начинается с "<html>", то будет показана страничка html с текстом, который стоит далее. Так вместо:4 {$ K. u8 E+ _- V0 C- v+ ]
return "Chat4.htm"0 _. m7 g6 l+ k% D0 D/ z7 h
# K; Z2 _( [1 k$ W
6 G0 l1 s0 E/ C! \5 k9 v, v
можно поставить:
! P  Q$ N( c! q
  1. return "<html><body>Return to your trainer to complete the quest</body></html>"
Скопировать код
Так же если строка заканчивается без .htm или в начале нет <html>, то текст будет выведен, как системное сообщение в окне чата. В нашем случае мы сделаем так, что бы при каждом убийстве keltik выводилось системное сообщение: «Собрано N из 4-х клыков».2 A/ D7 P$ k7 M! b) M- t* v

0 s: T3 P4 S0 @: U& E# v  W  @

5 T  Y/ `7 \+ r4 SНаш код для onKill имеет один недостаток. Он будет постоянно показывать Chat0.htm, Chat1.htm и Chat4.htm, нам же необходимо, что бы Chat0.htm и Chat1.htm показывались только один раз. Как нам это сделать? С помощью переменных.
# c+ J2 X0 _' J  ?" Y4 @3 l9 R/ k
* Q# b( }  ?  T7 F" u6 T( x

# q7 Z) u& J# I( ^6 T) W4 H) JВ каждом квесте строки могут храниться с помощью переменных. Эти переменные сохраняются в Вашей БД. В каждом методе мы можем назначить, прочитать и удалить переменные. Давайте изменим метод onKill, так что бы каждый диалог вызывался только один раз.. ]! C' @/ k$ s; B: A+ l
  1. def onKill (self,npcId,st):
    4 M9 A& ]& a1 z5 E% \
  2. if npcId == KELTIR_NPC_ID:
    * }# M$ Y' e& z: M/ A: u) b* s
  3. n = getCount(st)
    . c# P4 A, Z4 T; ?6 n1 o
  4. if n == 0:+ q$ T& M# P& E0 A
  5. if st.get('chat0') == None :" ^. T$ v& \( ?- {) D/ s0 m3 f7 n
  6. st.set("chat0", "true")
    # |+ `6 f' T- x  N0 Z, t2 @
  7. return "Chat0.htm"- Z; A" W6 G( u" {5 D
  8. elif n == 1:
    " w0 ?$ z& X! v8 X
  9. if st.get('chat1') == None :2 c* E  @$ o# k
  10. st.set("chat1", "true")7 [3 a% Y5 M& N) ]4 k/ \, g
  11. return "Chat1.htm"1 B' v1 O2 I6 l7 {7 c( s
  12. elif n >= 4:) r5 A) C; P- [6 ~; M2 d$ i8 A
  13. return "Chat4.htm"7 z) X1 M- |/ a5 _  E6 J
  14. return "Collected "+str(n)+" of 4 fangs"
    3 X- X+ L  {2 A9 h  c: J) ~% L# z
  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.
& b# p) s1 z  L: X$ `8 ^! H& K1 K4 n  m+ [) \
- U6 E- L- X$ j( @7 e0 l0 I
Вот конечный рабочий вариант квеста:' V5 m* s* }" g+ C9 }' i) Z
  1. import sys  m% ?$ W* D; s( b
  2. from net.sf.l2j.gameserver.model.quest import State
    ! U# N2 s  C* x$ B
  3. from net.sf.l2j.gameserver.model.quest import QuestState
    8 K- M3 L* X( s5 g: I3 O
  4. from net.sf.l2j.gameserver.model.quest.jython import QuestJython as JQuest
    7 h5 R2 m7 F+ p1 v5 g

  5. ) V  h; ?- P* Z; G+ `+ w* l5 _
  6. KELTIR_NPC_ID = 12082' |- i0 ?, E9 i. E$ j- k1 [, I
  7. FANGS_ITEM_ID = 1859* U7 f" d+ l3 ~! Z; p# ]5 k8 L1 w* b
  8. DROP_RATE    = 500000& f5 K' W" E8 d1 i
  9. 0 c& i5 l6 t. |5 c! ^5 e
  10. WORLD_MAP_ITEM_ID = 1665
    ! X# j- t. F0 k0 O+ H4 ]" ^
  11. 4 z. p, z3 ~) o: h, z8 q
  12. def getCount(st) :
    4 F; M' R( r  ]
  13. return st.getQuestItemsCount(FANGS_ITEM_ID)0 ~; T8 N! F- @) V, R- o

  14. , |2 P! u. _' I
  15. def completed(st) :
    . \7 t  x+ K4 d) S6 K! y4 y0 b2 ^1 d2 ~
  16. st.setState(COMPLETED)
    . C, B: x5 R! g( z
  17. st.clearQuestDrops(), |' G- t1 r! \& ^* _- b
  18. st.takeItems(FANGS_ITEM_ID,-1)1 V) T% ?1 j' o( [# M; Q
  19. st.giveItems(WORLD_MAP_ITEM_ID,1)0 j/ e% F; m+ f) a9 V
  20. st.exitQuest(False): }, z" \" F$ Z3 X
  21. return
    ; k- s8 W$ i% X: U* _

  22. 2 J9 y# t+ ?, l
  23. def check(st) :+ L3 R( t4 u9 f% V/ s
  24. if getCount(st) >= 4 :
    9 O9 q/ J' h# L! W' T
  25. completed(st)
    " v9 ]; w  _$ l" |% ]& q* R
  26. return
    2 w6 |. D  _5 d2 u9 b0 R# x
  27. ' B4 F8 p8 i" c! u1 r6 L" N- }$ `
  28. class Quest (JQuest):9 P* c% v- d. n  y
  29. " p9 n0 P2 T4 B$ S+ L" r% g
  30. def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)
      P& E& Q  a  B7 Z

  31. 3 j: N, n+ q# H$ a) B9 G
  32. def onEvent (self,event,st):6 U% y$ c/ P/ T8 f) ]- n8 o9 Z
  33. id = st.getState()
    2 ]( w: }( |' y, v9 M. Z2 T
  34. if id == CREATED : st.setState(STARTED)7 e- X' q  |, X: j
  35. elif id == COMPLETED: pass
    " D9 _' R9 L; s; K  n& {
  36. elif id == STARTED : check(st)
    $ n# G8 w, H& P, R8 j8 `9 @
  37. return
    4 ~- ]! p, h+ t

  38. # Q* {8 a- v) L+ r
  39. def onKill (self,npcId,st):* m1 J$ R8 w5 i5 n: S3 A2 l8 B
  40. if npcId == KELTIR_NPC_ID:
    / k( `9 ~9 N# |* C+ c# k
  41. n = getCount(st)
    " [( R) Z9 A! F! v8 N
  42. if n == 0:4 T0 T8 X) a1 ^
  43. if st.get('chat0') == None :
    , a* x7 g7 w/ b; x5 }
  44. st.set("chat0", "true")
      d" L) c  ~: S' j
  45. return "Chat0.htm"
    , E# N# Y2 \: [$ H4 ?
  46. elif n == 1:2 Z4 s: n3 v6 H: x# e5 E
  47. if st.get('chat1') == None :
    ) c* \3 W; q' _4 {
  48. st.set("chat1", "true")
    / X+ `, ?  T$ l# E2 M0 B7 b
  49. return "Chat1.htm"
    ( ?6 S+ T6 p9 q( n  U3 S
  50. elif n >= 4:
    2 `3 a3 `! S& |8 A& K& ]( W" g6 o
  51. return "Chat4.htm"* Z; \: z- p# G/ t: y
  52. return "Collect "+str(n)+" of 4 fangs"8 o7 Q" N& L0 q3 H8 B6 g
  53. return
    ; l- R' r: H2 q( s$ r

  54. " ~/ \$ z  |  {! |
  55. QUEST    = Quest(201, "Tutorial", "Tutorial quest")
    , W3 }/ s! S' o# D
  56. CREATED = State('Start',    QUEST). Y7 m) N! }0 f
  57. STARTED = State('Started', QUEST)1 B- ?: k# t1 L! {
  58. COMPLETED = State('Completed', QUEST); H7 _( B, h& s& I3 @6 p0 y
  59. 3 v; e5 Q; k. S9 L7 E; V" D
  60. QUEST.setInitialState(CREATED)
    ( Q) m- _* f8 s5 B6 U! T6 `! z  X
  61. QUEST.addStartNpc(7056)* W+ r- H' a* a( `$ I  [3 F" u
  62. QUEST.addStartNpc(7012)
    : f' b9 c  I6 F# R
  63. QUEST.addStartNpc(7009)1 C* y# }/ `- Y# l
  64. QUEST.addStartNpc(7011)3 ^0 u3 J, Y# }+ ?1 R5 r/ U. j

  65. " P. u' w5 X9 z$ Y
  66. STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
    1 w# V$ L: V* a1 o
  67. STARTED.addKillId(KELTIR_NPC_ID)
    ) I2 c$ _  i9 H7 l4 i
  68. STARTED.addTalkId(7056)/ i* x! t+ f; b! b( l
  69. STARTED.addTalkI d(7012); X: v1 T. U# e: T+ b
  70. STARTED.addTalkId(7009)
      N% z* `' R( f) Q2 P6 K2 \% i
  71. STARTED.addTalkId(7011)
Скопировать код

3 l( F. ]& `+ i) @' D7 |& }$ r: h  }+ e0 y# H; z; v5 j; l5 z. v
Чтобы ответить, вам надо авторизироваться в системе Вход | Зарегистрироваться

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

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

638638758

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

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

admin@artace.ru Онлайн

QR-код

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