Top.Mail.Ru

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

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

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

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

x
Хроники        Interlude# t7 _8 o1 o$ D; L+ v1 L
Сборка        L2j
1 ^8 N! X) N6 ^5 o. f) x7 MОбратите внимание: в файле htm стартового NCP обязательно должна быть ссылка на квест:  X( Y: d' w1 g5 d( h+ B
  1. STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код
Для этого квеста больше ничего не надо. Все необходимое для корректной работы квеста уже добавили. Вот полный текст квеста:
( Z7 F4 w. e! I4 Z* w% d( b! l+ r1 `) ]) Z0 ~8 t8 Y% i
  1. if getCount(st) >= 4 :
    0 M3 C& r0 _5 a" ]" p
  2. completed(st)
    " B$ r, Q) j3 G' I
  3.   return
      t* P$ h9 e2 L8 B1 p& Q9 R1 b
  4. 1 z7 s  Q8 A/ \6 @5 R
  5. class Quest (JQuest):7 {- s. ^/ c) e1 }  ]" r& M
  6.   def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr); i  h+ p9 S8 A% l/ p' b& d, M
  7.   def onEvent (self,event,st):
    - E  s. G" Z" `) Q+ c  ]+ W: I9 U
  8. id = st.getState()$ z: _4 e8 `2 u9 S
  9. if   id == CREATED  : st.setState(STARTED)1 x7 j4 C6 {& _2 e0 J5 F1 b$ H
  10. elif id == COMPLETED: pass' g" {- s* S  O9 n# k6 k
  11. elif id == STARTED  : check(st)
    8 |! w5 x! W/ A9 o) `8 f+ |
  12. return
    4 x8 r! L) B- x$ \

  13. ' s: o0 N. o) J7 Y) l- V$ b- l
  14. QUEST     = Quest(201,"Tutorial", "Tutorial quest")
    : u- E* ?- q# q# W. N" w  B0 Y+ W! L2 `
  15. CREATED   = State('Start',     QUEST)
    9 {* c% f. T. S+ ~* k8 H
  16. STARTED   = State('Started',   QUEST)
    . u7 E! k2 n0 ~
  17. COMPLETED = State('Completed', QUEST)3 q( S  Z: J3 Z8 ?

  18. ' c9 A/ R: [. F' C1 D" Y6 B
  19. QUEST.setInitialState(CREATED)
    ; Z; J! X- v. O+ q/ e/ i: N, d
  20. QUEST.addStartNpc(7056)
    / H7 r0 {& v8 {4 G
  21. STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код
Теперь рассмотрим, как это работает.
- }6 ^' [7 r4 y& R2 bИгрок подходит к начальному NCP (в данном случае 7056), нажимает на «Quest». Квест будет создан и состояние квеста перейдет к CREATED и игроку будет показана страничка Start.htm с описанием квеста. Тогда метод onEvent, поле открытия странички Start.htm переведет состояние квеста в STARTED и игроку будет показана страничка Started.htm, где будет опсание того, как найти keltirs и .т.д.
7 d( O0 p+ _( a5 p+ x% V5 r4 b( d, E4 F! r! C
: Y  W/ U+ _5 p4 R" h3 X
При состоянии STARTED будет зарегистрирован дроп «fangs» при убийстве keltirs. Игрок может вернуться к стартовому NCP и спросить о квесте – метод onEvent будет вызван снова. Если у игрока не хватает необходимого количества предметов, то метод check() не переведет квест в следующее состояние и Started.htm будет показана снова. Но если игрок собрал необходимее количество предметов (в данном случае 4 клыка), то метод check() вызовет метод completed() который переведет квест в новое состояние COMPLETED, заберет все клыки, даст карту мира, т.к. это награда за квест, покажет Completed.htm и завершит квест.0 h- M8 g: F! Q( u9 T: f
- U, v; O& r' c2 z/ R

6 M) c" {$ @* X9 w  @Теперь давайте сделаем наш квест более похожим на то, что он должен из себя представлять.# X7 g, k9 Y: |1 |
Прежде всего у нас есть 3 метода для объявления их в Яве – onTalk, onKill и onEvent. Если методы onTalk и onKill не объявлены, то за них все будет делать метод onEvent, т.е. определять квестовых монстров и вызывать диалоги NCP. Есть примечание, методы onTalk и onKill будут вызывать только диалоги с NCP в зависимости от текущего состояния квеста. Метод onKill будет вызываться только тогда, когда мы убиваем квестового монстра.. I& m' p( r) X# k1 W: p+ S
/ \8 ~7 w0 q$ }+ u
9 ^1 A- p  y/ D8 P  J
Давайте рассмотрим как вызывается метод onKill при убийстве keltir в состоянии квеста STARTED:' d  N# D" O, k, O
  1. STARTED.addKillId(KELTIR_NPC_ID)
Скопировать код
и метод onKill в классе Quest:
) x* M/ ~- F, U1 q. p8 }& R- \( A  m( P+ M8 N
  1. class Quest (JQuest):0 M& f9 O( |' `3 Q6 m0 {0 l
  2.   ...( ^( ]; w" q3 t4 j. O6 u# m
  3.   def onKill (self,npcId,st):0 {' }% S8 @! M7 [3 H- e+ r
  4. if npcId == KELTIR_NPC_ID:
    . V9 b5 p/ Y, {
  5.    n = getCount(st)
    & t( o: c+ r# ~4 j9 U
  6.    if   n == 0:
    , Q" _  K9 `0 g
  7.        return "Chat0.htm"+ Q7 Y6 t' [( |$ u
  8.    elif n == 1:% j. @! h/ d: r  Y& q4 l
  9.        return "Chat1.htm"% {4 Q9 [' L4 F
  10.    elif n >= 4:) y5 n* w$ f+ l7 s
  11.        return "Chat4.htm"
    % n# ]; {' q2 L$ F. p
  12.    return "Collected "+str(n)+" of 4 fangs"6 r2 [2 R. t3 r
  13. return
Скопировать код
Метод onKill (а так же метод onTalk) имеет следующие параметры:, h0 U5 z4 {3 K- D6 j) B

* T- E# i7 A7 m" E7 b6 B% D

( T2 f5 M/ S# k: J7 A2 P• self – квест8 o# s0 t3 c% B; x% M9 ^
• npcId – ID NCP, которого мы должны убивать (если это метод onTalk, то ID того NCP, с которым мы должны поговорить).
5 K( s& B/ P. P  ]+ b0 F• st – текущее состояние игрока.0 W7 c& K) h. r" Q

/ f1 b' j) g1 D/ \7 q

$ E, Q9 Z, `. w4 K& MВ этом методе мы проверяем и отмечаем, является ли убитый NCP keltir’ом. В основном эта проверка не нужна, т.к. у нас только KELTIR_NPC_ID.; d3 L1 ?6 n6 y$ i6 o
9 j# Z4 ?8 P7 S% m" [

! y9 t, \! P/ BЗатем проверяем количество предметов (в данном случае количество клыков), и если их вообще нет, то возвращаем строку "Chat0.htm", если только один предмет, то возвращаем строку "Chat1.htm", если же предметов 4 или больше, то "Chat4.htm". Если строка возвращена из методов onEvent, onKill или onTalk, то сервер покажет соответствующие htm. В Chat0.htm может иметь следующий текст: «Вы не имеете ни одного клыка, возвращайтесь позже, когда соберете 4 штуки и бла, бла, бла…», в Chat1.htm может быть следующий текст: «У Вас всего 1 клык, по этому соберите еще…». В Chat4.htm – «Вы собрали необходимое количество предметов, возвращайтесь к вашему тренеру, что бы завершить квест…». g4 t) K. \5 B) O
0 i9 w' ^! I% p0 ]) I

  `  E; _8 ^( CПримечание: если в строка return начинается с "<html>", то будет показана страничка html с текстом, который стоит далее. Так вместо:
( K9 A; I& M8 w8 |$ B% }2 Dreturn "Chat4.htm"
* ~; \: H3 }4 b
5 Y- b  c% ]; M

9 G; g+ W& e: k) m4 t9 Eможно поставить:
2 v3 n, `2 o: U9 D' W- r: `. C
  1. return "<html><body>Return to your trainer to complete the quest</body></html>"
Скопировать код
Так же если строка заканчивается без .htm или в начале нет <html>, то текст будет выведен, как системное сообщение в окне чата. В нашем случае мы сделаем так, что бы при каждом убийстве keltik выводилось системное сообщение: «Собрано N из 4-х клыков».
0 X; Y3 U! g1 p* t0 k. Y2 Y/ B( S5 m: Q$ a
1 w3 Q! v% v% }  ^
Наш код для onKill имеет один недостаток. Он будет постоянно показывать Chat0.htm, Chat1.htm и Chat4.htm, нам же необходимо, что бы Chat0.htm и Chat1.htm показывались только один раз. Как нам это сделать? С помощью переменных.
7 y4 t/ N- Q& y( P8 F, j
2 u, V- f( @  h" U
1 s. J) h9 p0 s
В каждом квесте строки могут храниться с помощью переменных. Эти переменные сохраняются в Вашей БД. В каждом методе мы можем назначить, прочитать и удалить переменные. Давайте изменим метод onKill, так что бы каждый диалог вызывался только один раз.
0 T) {+ U7 o( d, d5 D( z
  1. def onKill (self,npcId,st):' L& m' E" i: p$ w) G
  2. if npcId == KELTIR_NPC_ID:
      P' _, D3 W0 b% Z' |- z; f
  3. n = getCount(st)1 R0 Z  J4 b& g
  4. if n == 0:, k: j" g( L. q
  5. if st.get('chat0') == None :
    6 y& r' f7 h3 u3 X
  6. st.set("chat0", "true")/ `- s& M' a' I& Q
  7. return "Chat0.htm"
    # }0 m" B' G* b/ a9 v0 {
  8. elif n == 1:3 A( j7 R% E; [1 U
  9. if st.get('chat1') == None :7 J0 g+ `3 a& F' h, |5 ^' S
  10. st.set("chat1", "true")
    + m" n2 B; l. h9 r9 }: \% J
  11. return "Chat1.htm"
    , b, I, E6 `7 V. N4 W7 g4 Z- q! X
  12. elif n >= 4:0 c! |! K" c% |3 |; T9 C
  13. return "Chat4.htm"
    8 U& x5 b9 V6 g3 S1 U0 X$ w5 `
  14. return "Collected "+str(n)+" of 4 fangs". N' p# j+ }" Q* Q
  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.- K4 @1 ?$ ]4 G

$ Z2 o; i+ c1 Q/ z
6 \5 [1 S% m8 P9 F4 E" e
Вот конечный рабочий вариант квеста:
( l! t) o9 a4 b, T
  1. import sys0 `, G7 }" B& k' p' D/ G" G' F- ?
  2. from net.sf.l2j.gameserver.model.quest import State
    8 H( c. E$ r  p7 h! ^
  3. from net.sf.l2j.gameserver.model.quest import QuestState  F4 o% Z+ s1 o; f# p
  4. from net.sf.l2j.gameserver.model.quest.jython import QuestJython as JQuest
      j, K9 F$ B( K) w2 N+ t- \- p

  5. / l) U/ O  ~& L& L% U' B) @& Y
  6. KELTIR_NPC_ID = 12082  a  I9 X9 }# X% ^% o' R
  7. FANGS_ITEM_ID = 1859
      o) o3 h. D0 N
  8. DROP_RATE    = 500000
    " `) H: @( s3 d$ G1 [; e

  9. 8 t! t* o9 E3 z* k! I
  10. WORLD_MAP_ITEM_ID = 1665
    & [' Q) v( [/ d$ z4 n) C; N* z
  11. 3 Q; D( m' G! N1 x  b' U4 Q
  12. def getCount(st) :2 S2 Z) T5 e4 H+ O
  13. return st.getQuestItemsCount(FANGS_ITEM_ID)
    , K& ]9 f7 ^2 N8 G' t

  14. 6 {1 v5 j% S( d! e
  15. def completed(st) :9 ?+ L* ~4 z0 S9 }( w1 b: ?: A
  16. st.setState(COMPLETED)% X( _; I& U+ d" n! ~
  17. st.clearQuestDrops()- v' c5 }1 g  c( m5 W1 A
  18. st.takeItems(FANGS_ITEM_ID,-1)
    + t$ x; F8 d) h$ Q- G* `5 |3 W
  19. st.giveItems(WORLD_MAP_ITEM_ID,1)7 n5 V0 ], P- H" k7 Q5 S( T
  20. st.exitQuest(False)
    2 ]* Y1 `2 m; \2 j2 _* E" G, Y
  21. return
    - @8 z* U! D( I
  22.   w+ S9 D* q: @3 Z, M  v: g' E
  23. def check(st) :0 _0 R% x' u" C8 b8 Q3 V/ n9 V
  24. if getCount(st) >= 4 :
    - _5 S! C  f* j, o" s1 Z0 E9 d" u
  25. completed(st)2 O. C# `8 q9 _
  26. return
    1 r9 \+ B* D7 x; C) P

  27. 5 |" v! K" P9 l  }; Z, a0 ]6 w
  28. class Quest (JQuest):
    ; V; ?5 |* k0 a) r

  29. ; t) Z8 l; g- \" j, x
  30. def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)
    9 Q" f0 j! j7 u- X# L' Q9 [
  31. ) U( \4 ?! h3 w, R4 b* N$ [
  32. def onEvent (self,event,st):& @& Y4 ]3 E0 P0 K7 q0 k! A
  33. id = st.getState()
    ; t0 n6 G3 i, J( Q- z  g; B% C) x
  34. if id == CREATED : st.setState(STARTED)- }) {2 E1 k8 q1 m$ f" S& ]6 Z
  35. elif id == COMPLETED: pass
    , z" F( ?0 @9 k: X* e
  36. elif id == STARTED : check(st): Q' {2 T+ ?1 x/ V0 O  R
  37. return8 H' d/ m. W6 _' M7 w+ ]

  38. 6 S( _- h; R0 @9 {, g! Q& B
  39. def onKill (self,npcId,st):
    + o; O3 k& h  b1 v. \
  40. if npcId == KELTIR_NPC_ID:- _: N& ~6 P; y5 N, N/ a
  41. n = getCount(st)* ?+ ?1 S  }6 \  ]" b3 D- L
  42. if n == 0:
    4 c/ G4 q$ @2 V1 H; S- c
  43. if st.get('chat0') == None :
    6 t7 ?0 L) f) v/ k* B) [. o0 i+ E5 j
  44. st.set("chat0", "true")8 w- a; C0 \* ?/ a% v
  45. return "Chat0.htm"
    ' Y3 @) p: K  Q
  46. elif n == 1:
    4 f7 v- `: L* h) v% J4 X
  47. if st.get('chat1') == None :$ e5 [4 S1 }: t$ D7 u+ U7 l" c
  48. st.set("chat1", "true")
    + f( @1 E+ C( ?' D
  49. return "Chat1.htm"$ D) h  M! K  D2 J4 S5 [9 k
  50. elif n >= 4:
    8 [! [- l$ l# Q( x9 |# ~. ^# U
  51. return "Chat4.htm"
    5 @6 R6 K( s; H7 Q/ }% G5 @5 l
  52. return "Collect "+str(n)+" of 4 fangs"
    6 n6 \, {6 [' k& L; e+ u/ d: Y
  53. return% M2 C) P% T4 H$ z

  54. - u5 J4 W( e. t0 B. a! F
  55. QUEST    = Quest(201, "Tutorial", "Tutorial quest")0 t, j5 D7 t' a$ N! q  \+ @
  56. CREATED = State('Start',    QUEST)
    ) j0 K0 f' C4 N( o
  57. STARTED = State('Started', QUEST)
    $ ~2 _. I( i5 }
  58. COMPLETED = State('Completed', QUEST)
    / K  y& X5 K/ T: I% ?0 Q: ]

  59. 9 z- u# n5 C1 ^4 |  [( L  W0 I
  60. QUEST.setInitialState(CREATED)
    0 y' T  D, O9 @
  61. QUEST.addStartNpc(7056)
    5 L8 ?" p$ X( D: x
  62. QUEST.addStartNpc(7012)
    - E( ?/ W. U' w  e: X% f2 u& p1 B% o
  63. QUEST.addStartNpc(7009)
    9 d" i$ [1 G  _- n( F  ]- y7 Q/ E& s
  64. QUEST.addStartNpc(7011)
    - N9 e. j; s2 y- r. b2 z7 ]

  65. 3 R( o8 F% P: M* Q
  66. STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
    % J! @. x5 Y9 o; G6 p7 t
  67. STARTED.addKillId(KELTIR_NPC_ID)
    * e- y0 G4 J6 H* R
  68. STARTED.addTalkId(7056)1 y- I/ S1 s/ |0 X
  69. STARTED.addTalkI d(7012)+ S, f0 t+ r: @4 H' u) u; Q
  70. STARTED.addTalkId(7009)! F) V/ W, P5 Q$ I* D) w
  71. STARTED.addTalkId(7011)
Скопировать код
# _9 }: p( l- x. G" x" F

. ]; g) w- b/ f! v
Чтобы ответить, вам надо авторизироваться в системе Вход | Зарегистрироваться

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

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

638638758

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

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

admin@artace.ru Онлайн

QR-код

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