Top.Mail.Ru

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

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

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

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

x
Хроники        Interlude  N) e5 J$ }" h  A7 Z+ [( w
Сборка        L2j
$ Q; B, _$ T' p4 l. ]& D6 sОбратите внимание: в файле htm стартового NCP обязательно должна быть ссылка на квест:) o" T- g$ {# Q* z
  1. STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код
Для этого квеста больше ничего не надо. Все необходимое для корректной работы квеста уже добавили. Вот полный текст квеста:
" g; R# k$ h. v8 c( X& x: y0 Z* P$ I: C' ~  }
  1. if getCount(st) >= 4 :$ g( j- v! G$ w, y4 D/ ?
  2. completed(st)
    & l: o1 ]# A! g( G6 {
  3.   return2 p* ?' }; s+ j/ C& i
  4. 5 M( v( k! m1 v1 |% q
  5. class Quest (JQuest):
    7 y: s( U! B0 x( @7 p. Z
  6.   def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)
    2 m9 O3 J) O1 F! y
  7.   def onEvent (self,event,st):# [- J0 g- O( y# X
  8. id = st.getState()
    : V  }6 O5 |2 W* B, i3 q$ R
  9. if   id == CREATED  : st.setState(STARTED)
    # S' c8 R' V! N! F
  10. elif id == COMPLETED: pass' }# u; E7 g5 j9 K& T: S' L( b
  11. elif id == STARTED  : check(st)
    ( w1 F" X8 R: _( k8 F# ~$ f) H) ]
  12. return
    0 h6 G/ @- H' _4 ^& p% ]

  13. - M/ N7 n# `: ^9 E
  14. QUEST     = Quest(201,"Tutorial", "Tutorial quest")$ T1 g; J$ K' ]& v8 N$ I- ~
  15. CREATED   = State('Start',     QUEST)
    : U( m2 e4 z8 [- o' E" p
  16. STARTED   = State('Started',   QUEST)8 [+ @& k7 c* v$ R) q7 F
  17. COMPLETED = State('Completed', QUEST)
    # g% x" [# z4 H
  18. " ^* o6 n: S7 W3 c
  19. QUEST.setInitialState(CREATED)& H* G) t, \# j9 n
  20. QUEST.addStartNpc(7056)
    + x" y7 X& U7 @, B
  21. STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код
Теперь рассмотрим, как это работает.* Z6 i" H5 _3 @( \  O
Игрок подходит к начальному NCP (в данном случае 7056), нажимает на «Quest». Квест будет создан и состояние квеста перейдет к CREATED и игроку будет показана страничка Start.htm с описанием квеста. Тогда метод onEvent, поле открытия странички Start.htm переведет состояние квеста в STARTED и игроку будет показана страничка Started.htm, где будет опсание того, как найти keltirs и .т.д.1 s/ v# |; i! b* D- E8 s& j9 E

: x7 Y" J1 A; `" P

- D; C7 d7 u; J4 \6 lПри состоянии STARTED будет зарегистрирован дроп «fangs» при убийстве keltirs. Игрок может вернуться к стартовому NCP и спросить о квесте – метод onEvent будет вызван снова. Если у игрока не хватает необходимого количества предметов, то метод check() не переведет квест в следующее состояние и Started.htm будет показана снова. Но если игрок собрал необходимее количество предметов (в данном случае 4 клыка), то метод check() вызовет метод completed() который переведет квест в новое состояние COMPLETED, заберет все клыки, даст карту мира, т.к. это награда за квест, покажет Completed.htm и завершит квест.
( u- M& z; j0 H2 x: H6 D, P/ S
" T( u/ S3 o2 }! S- m5 s
# _" V% F1 |5 }* B' L) g
Теперь давайте сделаем наш квест более похожим на то, что он должен из себя представлять.
! q5 P" H8 {0 S9 }$ V( h4 @% p$ E! HПрежде всего у нас есть 3 метода для объявления их в Яве – onTalk, onKill и onEvent. Если методы onTalk и onKill не объявлены, то за них все будет делать метод onEvent, т.е. определять квестовых монстров и вызывать диалоги NCP. Есть примечание, методы onTalk и onKill будут вызывать только диалоги с NCP в зависимости от текущего состояния квеста. Метод onKill будет вызываться только тогда, когда мы убиваем квестового монстра.
! o9 m3 `5 x2 ~3 x! a7 N1 b. e+ g' \3 `7 O% a. G! h! S

8 _0 X, @5 T% E: UДавайте рассмотрим как вызывается метод onKill при убийстве keltir в состоянии квеста STARTED:, V1 T1 q% D- r& O; V
  1. STARTED.addKillId(KELTIR_NPC_ID)
Скопировать код
и метод onKill в классе Quest:
; _2 g, W* Y& K# y
, f& I. _6 t- @1 @/ [( n! o: l
  1. class Quest (JQuest):
    5 ^8 s# V/ _  G( `1 x) `
  2.   ...
    ; D9 x( a; A, V. T# I# b7 L
  3.   def onKill (self,npcId,st):) H! l& }- ~8 i" [
  4. if npcId == KELTIR_NPC_ID:6 b4 U- G4 Q1 L  `# f
  5.    n = getCount(st)
    $ t! h$ L; a6 O& c5 ~4 w! \
  6.    if   n == 0:
    ! ^) V5 s& L5 `: ~3 d5 Z
  7.        return "Chat0.htm"4 ^% i3 J$ f! `! d) k
  8.    elif n == 1:
    2 Z! ^! _" ~6 \1 j4 O
  9.        return "Chat1.htm") V$ T* N" n. N" K, m: |# C
  10.    elif n >= 4:/ T) I' X! f# F5 A
  11.        return "Chat4.htm", i3 V9 j% q  b8 u2 f
  12.    return "Collected "+str(n)+" of 4 fangs"
    6 u5 I6 d3 H4 i3 z$ Q9 j
  13. return
Скопировать код
Метод onKill (а так же метод onTalk) имеет следующие параметры:: E1 e: i' U6 H0 ]* M# U
) K& v2 z) v. f2 M, K# U
: Q+ q( h% c" e5 s' ?' U- K3 s
• self – квест
& X; J6 R3 Z; f, L* `& g, x• npcId – ID NCP, которого мы должны убивать (если это метод onTalk, то ID того NCP, с которым мы должны поговорить).
5 u$ [# {" T( [. T7 @/ |0 t+ ?$ [• st – текущее состояние игрока.
; K. u! ?; X$ Q% F) q# _* e0 Q- _6 f0 m. n  |2 e! b& {
" Z# v) U+ m- R
В этом методе мы проверяем и отмечаем, является ли убитый NCP keltir’ом. В основном эта проверка не нужна, т.к. у нас только KELTIR_NPC_ID.& e2 n9 T( R' j. l$ y! ~
' C9 `  O7 h/ X1 X9 d3 ~
+ {: w5 g3 e( Q  r5 g
Затем проверяем количество предметов (в данном случае количество клыков), и если их вообще нет, то возвращаем строку "Chat0.htm", если только один предмет, то возвращаем строку "Chat1.htm", если же предметов 4 или больше, то "Chat4.htm". Если строка возвращена из методов onEvent, onKill или onTalk, то сервер покажет соответствующие htm. В Chat0.htm может иметь следующий текст: «Вы не имеете ни одного клыка, возвращайтесь позже, когда соберете 4 штуки и бла, бла, бла…», в Chat1.htm может быть следующий текст: «У Вас всего 1 клык, по этому соберите еще…». В Chat4.htm – «Вы собрали необходимое количество предметов, возвращайтесь к вашему тренеру, что бы завершить квест…»
2 Y3 @: Z9 f/ R$ ^% |
. Y2 B4 K! m$ y* P; [

! x- D$ I, Z$ D. Y* ]Примечание: если в строка return начинается с "<html>", то будет показана страничка html с текстом, который стоит далее. Так вместо:
% O6 s0 O. a+ `return "Chat4.htm"
1 h4 M: Q! G: o& ^. g: y) r7 H
. s) U' g& c" y9 u1 h
. g( o- W) ]! T' h9 }- Q; a/ L$ l
можно поставить:
; v$ Y' n5 J+ m% J$ @
  1. return "<html><body>Return to your trainer to complete the quest</body></html>"
Скопировать код
Так же если строка заканчивается без .htm или в начале нет <html>, то текст будет выведен, как системное сообщение в окне чата. В нашем случае мы сделаем так, что бы при каждом убийстве keltik выводилось системное сообщение: «Собрано N из 4-х клыков».6 K8 L" T6 h$ P
1 w& |- W  R. n1 t  L! V  l' T
" F6 C) Q/ r1 P6 J
Наш код для onKill имеет один недостаток. Он будет постоянно показывать Chat0.htm, Chat1.htm и Chat4.htm, нам же необходимо, что бы Chat0.htm и Chat1.htm показывались только один раз. Как нам это сделать? С помощью переменных.
+ o, y0 ?7 K) B1 `, E! e1 y+ |4 \& s- ^7 W7 q
; c% T) O! I9 M/ E6 z
В каждом квесте строки могут храниться с помощью переменных. Эти переменные сохраняются в Вашей БД. В каждом методе мы можем назначить, прочитать и удалить переменные. Давайте изменим метод onKill, так что бы каждый диалог вызывался только один раз.4 U/ l2 D" g( |9 \; S" a
  1. def onKill (self,npcId,st):
    ( x8 }2 E8 h4 K, y
  2. if npcId == KELTIR_NPC_ID:
    " O* z8 R# y6 s8 c) B
  3. n = getCount(st)) p, J/ _6 V6 w: o! H* }0 s; M' T
  4. if n == 0:
    ' Y7 e) ~# U% l7 j' v& U6 ?7 i
  5. if st.get('chat0') == None :2 T, \+ v% A1 O6 ]# h/ f" ?
  6. st.set("chat0", "true")* T0 _8 y# [9 |8 O8 @0 p
  7. return "Chat0.htm"
    . c; ]" S, W1 _  [$ ]* E$ G
  8. elif n == 1:, C. W( W  V* N: n) u# b8 i
  9. if st.get('chat1') == None :. _' A- `1 u6 l8 x
  10. st.set("chat1", "true")9 l! O- S5 _: E5 t1 z
  11. return "Chat1.htm") h$ q8 W0 j: g5 J5 |
  12. elif n >= 4:( C6 A5 z" }! K( o9 H& }
  13. return "Chat4.htm"( V+ l" M9 s7 @; b1 w
  14. return "Collected "+str(n)+" of 4 fangs"
    2 \# l4 u9 L1 |* M. g9 m) |
  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.
" U0 n4 F+ Y1 a0 d+ l9 N; j0 J2 V$ j( \% a
; j4 y9 k! x6 H/ u9 l3 s
Вот конечный рабочий вариант квеста:
$ T# R- t4 f8 r3 J2 e/ H
  1. import sys
    4 S- a  N  D* j7 ]; q
  2. from net.sf.l2j.gameserver.model.quest import State
    1 k8 U; Z; o; o
  3. from net.sf.l2j.gameserver.model.quest import QuestState9 j# k5 K. U5 b: ~4 [
  4. from net.sf.l2j.gameserver.model.quest.jython import QuestJython as JQuest
    ; T5 w3 Z. F9 ^; q. C4 y7 `

  5. " ~0 X! R) n7 F+ z- K1 ~# A7 u
  6. KELTIR_NPC_ID = 12082
    ; f& S8 h4 `5 z' w0 U4 D) w
  7. FANGS_ITEM_ID = 1859( R1 z, m7 p3 F1 C/ m7 v' C. l! d
  8. DROP_RATE    = 500000
    + p8 h8 r% g  {

  9. 6 H& A2 W) r5 O  Y, ^- I1 L
  10. WORLD_MAP_ITEM_ID = 16657 P/ L2 {( K6 ]5 A+ l/ z
  11. * B1 ^: |$ u/ _( d& n
  12. def getCount(st) :
    * H/ `! D9 N; s9 O% M5 X8 W9 p' q
  13. return st.getQuestItemsCount(FANGS_ITEM_ID)
    , {  X7 P! n( p/ N0 B4 |$ q0 \
  14. 5 m& l& z& ]$ u
  15. def completed(st) :
    , {9 t% H. x: i4 `
  16. st.setState(COMPLETED)
    , K4 |& ^5 o6 x0 H6 t
  17. st.clearQuestDrops()
    0 z1 [  W. F& i( e  j8 r
  18. st.takeItems(FANGS_ITEM_ID,-1)
    : U: U' H4 r1 K  z+ i, {
  19. st.giveItems(WORLD_MAP_ITEM_ID,1)
    2 s( z) d4 L, p. J
  20. st.exitQuest(False)0 r; W# f! ^3 C+ c
  21. return$ I; Q0 a. z; Y3 ~* q2 d2 z* Y8 x

  22. / ]4 g0 |" A8 n0 x0 G
  23. def check(st) :2 [% a, b1 E$ D% `
  24. if getCount(st) >= 4 :, T4 [) U; R! T, d: ]5 u
  25. completed(st)
    9 Z- s" }& b% Y2 C$ [' k7 |% y" V
  26. return
    ' D- F/ o. A. d0 P0 D* Y: o
  27. ' @3 _  \7 U3 S; E$ S) v/ {
  28. class Quest (JQuest):2 \$ B- B, F, w( p0 M

  29. 8 |' V+ {* r+ F( H& ~- c) O! |( V. m
  30. def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)! I1 j" a9 F. G+ v
  31. 4 o! r6 Z+ r. u6 c* B: I
  32. def onEvent (self,event,st):
    3 H! i$ b5 Y; v" D4 Y3 \4 x& W
  33. id = st.getState()
    3 R9 i' b3 ?. K2 z5 n6 {) g+ e
  34. if id == CREATED : st.setState(STARTED)
    / j( J3 U, D. |1 N, Z8 j; D
  35. elif id == COMPLETED: pass
    6 m4 e( t  s; @, v( e% x" h6 V
  36. elif id == STARTED : check(st)  L" q4 U9 x9 w# r
  37. return
    ; J0 j) {! D' v

  38. 5 v. K. c# \/ _* Q
  39. def onKill (self,npcId,st):
    ) A3 D! E% q2 v8 i+ @9 ?4 A
  40. if npcId == KELTIR_NPC_ID:6 r, K# j, b/ C; Z% ?. j5 |/ D3 h- J
  41. n = getCount(st)
    , v) r1 N& F+ o# m
  42. if n == 0:9 w9 y$ y* j1 f3 [3 e" s
  43. if st.get('chat0') == None :
      K- d3 }# I  _' T. U
  44. st.set("chat0", "true")" S) {' |' K3 X7 O) p2 ]) H
  45. return "Chat0.htm"
    " }, H% _0 v$ N0 o  W" z
  46. elif n == 1:, X+ `; c- {; r$ _5 h0 g
  47. if st.get('chat1') == None :" i$ e" v0 _  \6 z9 |0 Z
  48. st.set("chat1", "true")
    8 D/ `8 |9 Z! z
  49. return "Chat1.htm"6 n5 y& g: k0 r& w
  50. elif n >= 4:( t& Y9 T" Z- _& P: i/ D
  51. return "Chat4.htm"( c2 Y' P& ]7 P  d
  52. return "Collect "+str(n)+" of 4 fangs"5 e- l5 n  i& t( t7 u6 S
  53. return
    9 P/ V0 B9 Y; a( F# G+ A4 {
  54. 0 t' W- ^9 X) s' M  ^
  55. QUEST    = Quest(201, "Tutorial", "Tutorial quest")
    7 e- l. x/ q! E
  56. CREATED = State('Start',    QUEST)0 f# [8 B0 Q  }" ?4 ?
  57. STARTED = State('Started', QUEST)  J+ L. c/ U$ Q! f4 O4 a) ?
  58. COMPLETED = State('Completed', QUEST)2 M# a8 a4 ~1 P3 K' {: Y) u; C

  59. . Q: N$ i, O4 o; w
  60. QUEST.setInitialState(CREATED)
    $ y2 y6 |+ X3 n  Z" M- q
  61. QUEST.addStartNpc(7056)
    1 N. ^1 w+ d/ D4 `# a
  62. QUEST.addStartNpc(7012)
    8 g. b3 L% i% E: f$ u. d$ D
  63. QUEST.addStartNpc(7009)
      w1 |8 t1 Z! c# `* K6 h' W
  64. QUEST.addStartNpc(7011)
    - R# X# k% x5 t) ]

  65. 3 ]. S, _( z: b' P8 q( A( O. S
  66. STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)3 F- f' v' ]% _" R$ x' S% [- S
  67. STARTED.addKillId(KELTIR_NPC_ID)- b4 ~! C1 b- F. d- ^7 n+ K
  68. STARTED.addTalkId(7056)
    5 u1 p5 ]3 i0 [3 D' s
  69. STARTED.addTalkI d(7012)
    . l/ J( |# k5 o8 p; q# Q/ O
  70. STARTED.addTalkId(7009)1 F* }+ N: g, F0 V
  71. STARTED.addTalkId(7011)
Скопировать код

0 o1 `5 v2 D6 [/ Y& t7 g# L6 @' k( ~
Чтобы ответить, вам надо авторизироваться в системе Вход | Зарегистрироваться

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

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

638638758

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

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

admin@artace.ru Онлайн

QR-код

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