Top.Mail.Ru

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

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

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

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

x
Хроники        Interlude/ I( o* [2 e# G1 K) o" U
Сборка        L2j
- y& w8 r: z2 MОбратите внимание: в файле htm стартового NCP обязательно должна быть ссылка на квест:7 b! w2 B! ^" ]) Y+ P. h; u# p3 C
  1. STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код
Для этого квеста больше ничего не надо. Все необходимое для корректной работы квеста уже добавили. Вот полный текст квеста:
5 @& j( m! S! [1 y# {) E2 y" {/ t4 X8 W% Z
  1. if getCount(st) >= 4 :
    ; n( I) q- s" I- k, T/ z! k$ i
  2. completed(st)
    % L7 Y. u% m2 J5 c$ j9 K3 c# D
  3.   return
    / I4 }+ x1 t, w  y( G
  4. 8 a& F$ m4 S& S" J! W. m# S/ I
  5. class Quest (JQuest):  Y4 b- j- c4 a6 p
  6.   def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr): O) s2 A/ C1 h  s/ C
  7.   def onEvent (self,event,st):* ^) }8 C4 X" H
  8. id = st.getState()* L" R8 g9 R# {
  9. if   id == CREATED  : st.setState(STARTED)
    " _6 }, N  ?' ~3 d
  10. elif id == COMPLETED: pass
    - ~2 Z0 C0 ~9 k6 P  R" j  N
  11. elif id == STARTED  : check(st)
    9 e2 I+ Q( m) Z8 G
  12. return
    - x, N# H/ C: {* ^5 |

  13. - l7 p' i; a2 V' B% J) T& O0 k
  14. QUEST     = Quest(201,"Tutorial", "Tutorial quest")6 H' L8 T, L4 H0 S6 A, x
  15. CREATED   = State('Start',     QUEST)( U# R$ d: d4 h
  16. STARTED   = State('Started',   QUEST)4 V* ~0 B) _0 g7 T
  17. COMPLETED = State('Completed', QUEST). F# N; H% X# \& z- ]& U) `

  18. 7 O# g% ?) ~+ H' m2 s
  19. QUEST.setInitialState(CREATED)
    9 {( a' S) d( d* Y$ ], e
  20. QUEST.addStartNpc(7056)
    / }4 K( G' ?  F/ e; f( O
  21. STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код
Теперь рассмотрим, как это работает., j0 y+ j, V" I  y6 N; r
Игрок подходит к начальному NCP (в данном случае 7056), нажимает на «Quest». Квест будет создан и состояние квеста перейдет к CREATED и игроку будет показана страничка Start.htm с описанием квеста. Тогда метод onEvent, поле открытия странички Start.htm переведет состояние квеста в STARTED и игроку будет показана страничка Started.htm, где будет опсание того, как найти keltirs и .т.д.
  O$ i+ L7 e/ }2 M, H3 x8 R0 r" \3 g* L
# }. K& I, G9 _; ~! V5 h
При состоянии STARTED будет зарегистрирован дроп «fangs» при убийстве keltirs. Игрок может вернуться к стартовому NCP и спросить о квесте – метод onEvent будет вызван снова. Если у игрока не хватает необходимого количества предметов, то метод check() не переведет квест в следующее состояние и Started.htm будет показана снова. Но если игрок собрал необходимее количество предметов (в данном случае 4 клыка), то метод check() вызовет метод completed() который переведет квест в новое состояние COMPLETED, заберет все клыки, даст карту мира, т.к. это награда за квест, покажет Completed.htm и завершит квест.
& ~3 z$ `2 c0 R. A
5 ~! U, t. b4 g. k2 \

' u4 k7 w: f7 D/ k' [Теперь давайте сделаем наш квест более похожим на то, что он должен из себя представлять.: ]% x# V9 b/ x
Прежде всего у нас есть 3 метода для объявления их в Яве – onTalk, onKill и onEvent. Если методы onTalk и onKill не объявлены, то за них все будет делать метод onEvent, т.е. определять квестовых монстров и вызывать диалоги NCP. Есть примечание, методы onTalk и onKill будут вызывать только диалоги с NCP в зависимости от текущего состояния квеста. Метод onKill будет вызываться только тогда, когда мы убиваем квестового монстра.& [8 x8 A2 l6 D1 S% T
* ]1 K+ `& w2 Y! ~

& y, X1 |& ]+ A2 s" }: y; aДавайте рассмотрим как вызывается метод onKill при убийстве keltir в состоянии квеста STARTED:
! u2 _9 b* M5 F: L, s
  1. STARTED.addKillId(KELTIR_NPC_ID)
Скопировать код
и метод onKill в классе Quest:$ m1 l3 ~* ]2 m: Q' q2 n

% e( W2 O$ E3 @9 d) K$ h! N
  1. class Quest (JQuest):
    # t; _" Z8 ~8 ?; q7 r# R7 r- u. q
  2.   ...
    ; Q( o; `4 W8 m* J* p
  3.   def onKill (self,npcId,st):0 T( V, K8 R" P4 u8 W0 f' y
  4. if npcId == KELTIR_NPC_ID:
    " [$ t1 C& E9 Y' I) C
  5.    n = getCount(st)4 Y3 v6 H$ \, G/ R  f
  6.    if   n == 0:
    7 C" H( G0 O2 X; P. Y: s
  7.        return "Chat0.htm"' }* O4 t% n6 v0 i: c1 y
  8.    elif n == 1:# J+ W: W2 t9 }2 ]" [. S; |
  9.        return "Chat1.htm"# q1 K7 g# I$ A6 p
  10.    elif n >= 4:! {2 }( |+ a/ k6 ?
  11.        return "Chat4.htm"
    " Y- U3 w" M: H' o8 x) q& z- X
  12.    return "Collected "+str(n)+" of 4 fangs"" y7 Q- w8 t2 f& S1 j5 t( _) @
  13. return
Скопировать код
Метод onKill (а так же метод onTalk) имеет следующие параметры:6 Y" ]' M6 }/ _% a* @3 I

# ~( V# S" b  x. i
, S( |8 t/ Q( Z- u
• self – квест- h+ V% {' W( N
• npcId – ID NCP, которого мы должны убивать (если это метод onTalk, то ID того NCP, с которым мы должны поговорить).
& V/ U" \, r( Y" h• st – текущее состояние игрока.
' y1 D4 o' s. _0 O- }7 u7 M0 {# g4 R% o0 z( ~  m/ I4 O. U" Y; J9 v* S
& T0 Z/ E5 z, ]4 M
В этом методе мы проверяем и отмечаем, является ли убитый NCP keltir’ом. В основном эта проверка не нужна, т.к. у нас только KELTIR_NPC_ID.
! t5 c- x. c9 d6 \7 i
) ]1 g; @# W/ `! i
9 h* c8 b/ d2 p9 i
Затем проверяем количество предметов (в данном случае количество клыков), и если их вообще нет, то возвращаем строку "Chat0.htm", если только один предмет, то возвращаем строку "Chat1.htm", если же предметов 4 или больше, то "Chat4.htm". Если строка возвращена из методов onEvent, onKill или onTalk, то сервер покажет соответствующие htm. В Chat0.htm может иметь следующий текст: «Вы не имеете ни одного клыка, возвращайтесь позже, когда соберете 4 штуки и бла, бла, бла…», в Chat1.htm может быть следующий текст: «У Вас всего 1 клык, по этому соберите еще…». В Chat4.htm – «Вы собрали необходимое количество предметов, возвращайтесь к вашему тренеру, что бы завершить квест…»$ K; W0 z* c6 l: j8 Y3 B

2 a- f1 i5 q7 Q# a* w% w3 q
1 \3 r; Y8 |5 N5 b7 |/ C; G0 g" E
Примечание: если в строка return начинается с "<html>", то будет показана страничка html с текстом, который стоит далее. Так вместо:7 o5 V0 c, o- k+ _/ f, M
return "Chat4.htm"
6 d3 j8 l, b/ n2 O! n: P: ~" j  P+ @4 B: F' l, R' ]* z; e

3 J$ x! G/ z1 ?5 G9 I3 J6 }0 W7 Vможно поставить:7 b- Z1 c( r* F- w
  1. return "<html><body>Return to your trainer to complete the quest</body></html>"
Скопировать код
Так же если строка заканчивается без .htm или в начале нет <html>, то текст будет выведен, как системное сообщение в окне чата. В нашем случае мы сделаем так, что бы при каждом убийстве keltik выводилось системное сообщение: «Собрано N из 4-х клыков».9 _9 f" M( \$ |4 K. Z' \) T
2 W* P& k. u. v5 A

+ E( J" a* K. |) JНаш код для onKill имеет один недостаток. Он будет постоянно показывать Chat0.htm, Chat1.htm и Chat4.htm, нам же необходимо, что бы Chat0.htm и Chat1.htm показывались только один раз. Как нам это сделать? С помощью переменных.
8 O% u! ^8 x# q* i2 i$ [
: s* n6 t3 g' d  b- U, y
, J6 h% g( v0 C: A  P6 P& k
В каждом квесте строки могут храниться с помощью переменных. Эти переменные сохраняются в Вашей БД. В каждом методе мы можем назначить, прочитать и удалить переменные. Давайте изменим метод onKill, так что бы каждый диалог вызывался только один раз.1 M, d* `& |5 n+ ~- w
  1. def onKill (self,npcId,st):/ a/ y( f! f/ ]1 f
  2. if npcId == KELTIR_NPC_ID:6 \6 l) j7 @# Q* q+ b
  3. n = getCount(st)
    9 s5 p4 `& o0 H- w) a- P
  4. if n == 0:
    + L* P! z$ ^! _9 C8 W
  5. if st.get('chat0') == None :& Z. H0 n$ j' i9 n; }) Y
  6. st.set("chat0", "true")
    2 ?! m4 b' E' S* T: o0 S
  7. return "Chat0.htm"6 g) \( r6 U' R, A  \
  8. elif n == 1:) ?6 ]' e  Q% b# ]: \
  9. if st.get('chat1') == None :' g9 V9 u( W3 K* O- F
  10. st.set("chat1", "true")4 v% d  E5 r/ S+ m/ I8 l6 ~' f
  11. return "Chat1.htm"3 E6 Q8 L& a+ t% H2 K1 ^5 T
  12. elif n >= 4:
    ! i' C/ B, |3 ~& p5 ~. G. z
  13. return "Chat4.htm"
    : F5 [! g8 R/ q
  14. return "Collected "+str(n)+" of 4 fangs"( c( J7 q7 v1 n( j: ?* m; s
  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.0 ]% V" u8 T( k( l5 k
# n7 B7 @3 p- n* {4 j" n6 L

; o. v+ O* W2 a( b+ p+ R- fВот конечный рабочий вариант квеста:* G0 D# y) G7 A8 s
  1. import sys
    ) T: F0 ^" Z# |# ~" y3 E9 y9 w. i
  2. from net.sf.l2j.gameserver.model.quest import State* @' c* V, B3 {8 A' p  |/ g
  3. from net.sf.l2j.gameserver.model.quest import QuestState
    # O0 E. g0 g! h% |
  4. from net.sf.l2j.gameserver.model.quest.jython import QuestJython as JQuest) m1 v& T8 G5 }

  5. : j, [& o5 J/ k: h% t4 Z
  6. KELTIR_NPC_ID = 12082( X- w# c+ m/ j0 t. N" l
  7. FANGS_ITEM_ID = 1859
    6 s% H+ s6 ?9 M! C6 N# w) ?( W
  8. DROP_RATE    = 5000006 a6 V9 J7 L! t4 W8 A

  9. # |5 j* P- D8 S  R
  10. WORLD_MAP_ITEM_ID = 16652 r$ \3 o' v: @. o; J2 G3 w5 M0 I

  11. ( V5 j5 x. P/ E$ R& E
  12. def getCount(st) :: Y1 V0 ]# a0 F; s" r+ g
  13. return st.getQuestItemsCount(FANGS_ITEM_ID)3 @; g  i3 a* i+ c: k; i
  14. - b/ H3 r; o# u& G: m& `! ]
  15. def completed(st) :/ U! g- b+ a7 g+ G1 N
  16. st.setState(COMPLETED)% y/ h/ E* t& n+ U' H
  17. st.clearQuestDrops()
    ! k9 i% s* h; [$ i4 I7 @9 ]
  18. st.takeItems(FANGS_ITEM_ID,-1)  i0 F7 ]$ _3 V$ L
  19. st.giveItems(WORLD_MAP_ITEM_ID,1)
    # h1 i" c- j6 @. f
  20. st.exitQuest(False)( n. S( P6 y" [6 `# U! o6 b( M
  21. return/ @7 M9 A3 X+ @# H& D3 F2 z

  22. 5 T% H. ?, v0 K# K0 c- a1 `
  23. def check(st) :0 x; y% g1 l: `. \
  24. if getCount(st) >= 4 :
    # L9 J7 w6 x' X
  25. completed(st): ?+ q6 J/ N2 x1 O5 ]& ~+ t
  26. return0 e4 B8 m; C# u* A5 D) u4 F; \
  27. : G8 z) ^+ }9 Z* Q( `& z
  28. class Quest (JQuest):" m. i  A. ^% s7 N
  29.   q, Z2 |0 w" q. k" |! M6 h
  30. def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)4 F, z9 b1 p/ n! B- ?0 d& k' v# R$ _3 j
  31. # I* j) |9 w7 h
  32. def onEvent (self,event,st):
    * s$ U, a( L* z  r" I/ W
  33. id = st.getState()5 b) X: c8 f/ f6 @. E
  34. if id == CREATED : st.setState(STARTED)9 Q7 ~! `* [9 P3 Z
  35. elif id == COMPLETED: pass; a, d3 R7 M( Z5 t4 B3 l4 |6 _
  36. elif id == STARTED : check(st)
    0 F  W( u! T- c  n9 b1 j) M; I
  37. return9 z' B" P' f7 R, b. c  l) ]( g8 e# l

  38. : A" K4 E% g$ y0 z9 f  [8 |
  39. def onKill (self,npcId,st):# \8 r  t+ e; ?$ v# M: x: }
  40. if npcId == KELTIR_NPC_ID:
    ! ^& u$ p8 T! J7 U
  41. n = getCount(st)
    & W6 N4 ^  I2 B! J- B7 v
  42. if n == 0:" B" m* M. @! N. M
  43. if st.get('chat0') == None :; Q- }1 A: y) L0 G7 t
  44. st.set("chat0", "true"), e7 ?( |1 m1 X. |7 r* a
  45. return "Chat0.htm"
    $ h, ~6 C/ z2 {0 B
  46. elif n == 1:4 R7 p; o. o/ O7 W
  47. if st.get('chat1') == None :( p, g" g0 f- g
  48. st.set("chat1", "true"); x: ]) N! Z8 g$ I( [4 x: r
  49. return "Chat1.htm"
    9 e( k7 m( g/ I6 b- n5 E
  50. elif n >= 4:8 W0 H; m) y. g+ ^( j3 h9 J5 P
  51. return "Chat4.htm"
    % W% t$ t# g! v
  52. return "Collect "+str(n)+" of 4 fangs"( e1 `4 W& r9 W" j5 K- u- H
  53. return
    9 }9 O- K  m  z, w7 x' D
  54. 7 H/ F: E* T0 T
  55. QUEST    = Quest(201, "Tutorial", "Tutorial quest")& m' e4 T' W( s% t
  56. CREATED = State('Start',    QUEST)/ D9 d+ k! j1 W) @: V# D
  57. STARTED = State('Started', QUEST)
    * W0 [% `9 E  Y; M' P
  58. COMPLETED = State('Completed', QUEST)
    # s7 @% K( z& W/ Q4 W4 F! U

  59. 0 r) a) w% ~/ R7 d8 Z/ U- B4 @6 S& C
  60. QUEST.setInitialState(CREATED)
    " [) l! Q' k% o# ~4 G
  61. QUEST.addStartNpc(7056)
    4 r0 l7 z5 `' o* m4 S: e2 ?7 W
  62. QUEST.addStartNpc(7012)
    ' Z2 s% H1 w" H/ p
  63. QUEST.addStartNpc(7009)
    * V+ O& y; l5 y' k: j
  64. QUEST.addStartNpc(7011)8 M4 }8 N% F& Z! N! n

  65. % o6 b' d; w9 }9 `4 [/ v. O  N
  66. STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)1 l, {$ r; [# t$ z
  67. STARTED.addKillId(KELTIR_NPC_ID)+ l5 ]( T& ~4 e% |2 G
  68. STARTED.addTalkId(7056)
    ) \1 V5 X6 f, t: Q5 B$ v4 `' R9 }7 Y
  69. STARTED.addTalkI d(7012)& k6 M; A  m3 O8 U  U
  70. STARTED.addTalkId(7009)
      u2 \% t' Z+ R  `
  71. STARTED.addTalkId(7011)
Скопировать код
5 G4 x; c& w( `, v8 w, ^: g
9 C0 }1 Q( [3 k/ q3 B
Чтобы ответить, вам надо авторизироваться в системе Вход | Зарегистрироваться

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

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

638638758

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

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

admin@artace.ru Онлайн

QR-код

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