Top.Mail.Ru

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

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

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

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

x
Хроники        Interlude
) R) @: I, {; c) @4 k$ I# cСборка        L2j9 ^5 j/ h$ S* C
Обратите внимание: в файле htm стартового NCP обязательно должна быть ссылка на квест:. A2 b6 ~& l' b% Y
  1. STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код
Для этого квеста больше ничего не надо. Все необходимое для корректной работы квеста уже добавили. Вот полный текст квеста:
; O7 l. l3 |% e, B: w
/ w/ N5 o1 ?# v) b' [/ D1 ?! o7 ]% Q
  1. if getCount(st) >= 4 :) R' V/ A2 l5 Q, c5 ^: L& l
  2. completed(st)
    5 b9 h! F( \, s) C$ G2 t, z6 K
  3.   return
    ) E  p9 H7 U5 F  O8 }, v- j

  4. $ d* h. X9 f7 C& d* G6 ?
  5. class Quest (JQuest):& g7 @, p/ }+ O& C1 o' S
  6.   def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)) u* M( g2 p; g* j( }: s
  7.   def onEvent (self,event,st):
    3 s$ }2 s. w  z+ O" ^( P
  8. id = st.getState()
    . @' C' X. d9 M: J0 ^; m
  9. if   id == CREATED  : st.setState(STARTED): |9 |+ ?+ h& j2 w+ u
  10. elif id == COMPLETED: pass
      i; }" x! [; ]1 I
  11. elif id == STARTED  : check(st)$ S% s1 s% s# X: C6 J7 H/ V
  12. return0 E3 _; O  x, E$ W- Z
  13. + H# s6 K  `' B( ]- A& j7 A
  14. QUEST     = Quest(201,"Tutorial", "Tutorial quest")! S: N2 o; v0 [2 U0 o
  15. CREATED   = State('Start',     QUEST)7 @+ ]  y  H1 u$ R: \" v5 X$ Z! \
  16. STARTED   = State('Started',   QUEST)
    * g9 E: G+ ~) t6 P
  17. COMPLETED = State('Completed', QUEST)3 s4 ]5 H) }& S' j( }8 i

  18. % s* h7 S7 [7 o- }8 ]# ^* P7 H! J
  19. QUEST.setInitialState(CREATED)' n8 ^$ V1 k- s7 P# M3 Q, u3 |; A
  20. QUEST.addStartNpc(7056)
    & p& A* R+ F2 U' a- Y! H
  21. STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код
Теперь рассмотрим, как это работает.
7 T5 ?( l/ U7 L2 a2 hИгрок подходит к начальному NCP (в данном случае 7056), нажимает на «Quest». Квест будет создан и состояние квеста перейдет к CREATED и игроку будет показана страничка Start.htm с описанием квеста. Тогда метод onEvent, поле открытия странички Start.htm переведет состояние квеста в STARTED и игроку будет показана страничка Started.htm, где будет опсание того, как найти keltirs и .т.д.
/ s& S" Z7 @% O/ ?
9 i: T3 F8 `5 x5 d
3 Q0 D! w' W" L3 C  A
При состоянии STARTED будет зарегистрирован дроп «fangs» при убийстве keltirs. Игрок может вернуться к стартовому NCP и спросить о квесте – метод onEvent будет вызван снова. Если у игрока не хватает необходимого количества предметов, то метод check() не переведет квест в следующее состояние и Started.htm будет показана снова. Но если игрок собрал необходимее количество предметов (в данном случае 4 клыка), то метод check() вызовет метод completed() который переведет квест в новое состояние COMPLETED, заберет все клыки, даст карту мира, т.к. это награда за квест, покажет Completed.htm и завершит квест.
" O6 z8 D7 I! b& M1 H' m1 e7 a0 T6 b+ B4 M  M4 n6 }0 b

4 C' [; r; N7 [Теперь давайте сделаем наш квест более похожим на то, что он должен из себя представлять.. {# M  p1 o; Z7 h
Прежде всего у нас есть 3 метода для объявления их в Яве – onTalk, onKill и onEvent. Если методы onTalk и onKill не объявлены, то за них все будет делать метод onEvent, т.е. определять квестовых монстров и вызывать диалоги NCP. Есть примечание, методы onTalk и onKill будут вызывать только диалоги с NCP в зависимости от текущего состояния квеста. Метод onKill будет вызываться только тогда, когда мы убиваем квестового монстра.6 \+ V1 N! T9 v& z! m7 N7 x9 j% b) k0 G8 f

( r' W# q, W% E
( ?0 ]/ w2 d: s. m$ A
Давайте рассмотрим как вызывается метод onKill при убийстве keltir в состоянии квеста STARTED:
' k/ i6 F, Y' Z1 d
  1. STARTED.addKillId(KELTIR_NPC_ID)
Скопировать код
и метод onKill в классе Quest:
# `# ~! e' \: i' Q. `. M; V+ {) @- a" D0 p
  1. class Quest (JQuest):" U5 @: ?  B) k8 l, @) I
  2.   ...
    + D, {: d. Z! d3 D& w$ B1 `
  3.   def onKill (self,npcId,st):  m8 p6 ^$ x8 [5 `2 y4 I
  4. if npcId == KELTIR_NPC_ID:( t, Z/ w4 m* e2 i; g) h: P' W, V  d
  5.    n = getCount(st)
    ! I% E: l. a/ }2 ?! i( H6 @
  6.    if   n == 0:6 t" v# f' r' O  D$ H/ K
  7.        return "Chat0.htm"9 G4 n3 O2 H7 j! v2 C
  8.    elif n == 1:
    * G, \8 M. u/ u8 q1 q$ g% l
  9.        return "Chat1.htm"
    + g/ r# k, Q1 J8 u
  10.    elif n >= 4:% `1 {( R  Z# O; A, U& k* L
  11.        return "Chat4.htm"# U8 d5 m5 g* `. }; ]$ g
  12.    return "Collected "+str(n)+" of 4 fangs"+ F- v4 l. C8 n6 U" c4 d
  13. return
Скопировать код
Метод onKill (а так же метод onTalk) имеет следующие параметры:0 b/ j3 R: Z! F9 e0 }! X
4 l2 K% y" z* @8 n" D% [

* K) U) |( f/ p- ~  Y5 y$ I) v• self – квест: _2 X9 ^0 b: F( c* V) B' N0 v5 L
• npcId – ID NCP, которого мы должны убивать (если это метод onTalk, то ID того NCP, с которым мы должны поговорить).8 O- Y8 l( a$ X$ }
• st – текущее состояние игрока.( q* ]% R% C/ D, t& l

) L- n5 s: R: G9 l4 Q
2 {; C4 ]5 }2 D2 D3 a
В этом методе мы проверяем и отмечаем, является ли убитый NCP keltir’ом. В основном эта проверка не нужна, т.к. у нас только KELTIR_NPC_ID.
5 X, _/ |  T% e  U3 _' H5 q1 c* K, |( i  z$ f3 b( U9 }% L# M

) \( [  d, |" p9 g  F0 TЗатем проверяем количество предметов (в данном случае количество клыков), и если их вообще нет, то возвращаем строку "Chat0.htm", если только один предмет, то возвращаем строку "Chat1.htm", если же предметов 4 или больше, то "Chat4.htm". Если строка возвращена из методов onEvent, onKill или onTalk, то сервер покажет соответствующие htm. В Chat0.htm может иметь следующий текст: «Вы не имеете ни одного клыка, возвращайтесь позже, когда соберете 4 штуки и бла, бла, бла…», в Chat1.htm может быть следующий текст: «У Вас всего 1 клык, по этому соберите еще…». В Chat4.htm – «Вы собрали необходимое количество предметов, возвращайтесь к вашему тренеру, что бы завершить квест…»
! C5 d" l! k* e& K) g+ r# Z" R5 I: G1 w6 z* @: `
( H$ e8 `$ W+ j$ `0 Y) s7 k* o
Примечание: если в строка return начинается с "<html>", то будет показана страничка html с текстом, который стоит далее. Так вместо:
1 `8 i( O3 ?6 nreturn "Chat4.htm"
$ E9 ~+ ]0 m& y4 m3 [
) i8 l% C. R; g" c

3 ~! a5 ^, S/ O7 hможно поставить:( \1 W9 t) f0 }1 V9 ~% X: t
  1. return "<html><body>Return to your trainer to complete the quest</body></html>"
Скопировать код
Так же если строка заканчивается без .htm или в начале нет <html>, то текст будет выведен, как системное сообщение в окне чата. В нашем случае мы сделаем так, что бы при каждом убийстве keltik выводилось системное сообщение: «Собрано N из 4-х клыков».
2 Q$ ?. x. {' Q8 n+ W8 x% t% e2 \: T5 Q/ S! I

  P, a/ D* v# SНаш код для onKill имеет один недостаток. Он будет постоянно показывать Chat0.htm, Chat1.htm и Chat4.htm, нам же необходимо, что бы Chat0.htm и Chat1.htm показывались только один раз. Как нам это сделать? С помощью переменных.
6 N. L4 Y' Y+ s3 m% O
6 b: W; {" m- y, ^7 I
4 z3 u" `- s7 x6 J
В каждом квесте строки могут храниться с помощью переменных. Эти переменные сохраняются в Вашей БД. В каждом методе мы можем назначить, прочитать и удалить переменные. Давайте изменим метод onKill, так что бы каждый диалог вызывался только один раз.1 t6 ?, ~7 d! |, G
  1. def onKill (self,npcId,st):
    - r: O2 p3 A! |7 r! w3 b0 C( p
  2. if npcId == KELTIR_NPC_ID:
    2 E$ e2 [4 q% D* t
  3. n = getCount(st)
      `! V) O' I5 N& `" p! {4 c- z
  4. if n == 0:
    ; h& `* E) w. t# }& w& f% l
  5. if st.get('chat0') == None :
    / I! Z, Y: K* R; |
  6. st.set("chat0", "true")! w; @7 a% V( f* V. Q. F6 _
  7. return "Chat0.htm"
    3 n6 y+ u# e+ B. u$ s
  8. elif n == 1:( V$ K( i* W) d" `
  9. if st.get('chat1') == None :
    % _/ S2 A" A9 w( ^+ v
  10. st.set("chat1", "true")# W. R' S+ \: I5 g* r. ~
  11. return "Chat1.htm"; o7 B1 a2 }2 ]- F! }' ]
  12. elif n >= 4:4 Q- L3 f0 u/ x, l0 @# V9 ~
  13. return "Chat4.htm"/ c1 }  ]% M* \& }
  14. return "Collected "+str(n)+" of 4 fangs"% q& \3 }7 W; N, W! a' ~
  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.
( G: N5 S; n: }) H
# p1 j, Z- ?) p3 x2 u; b' {$ m+ S+ E
5 H) |2 j1 |: g' ]: P# C  b
Вот конечный рабочий вариант квеста:
: J' ?7 C% V" e* n
  1. import sys
    5 @+ C9 c* F4 ~5 f, Z/ i+ e$ x
  2. from net.sf.l2j.gameserver.model.quest import State4 ]0 z! P8 r: J2 o
  3. from net.sf.l2j.gameserver.model.quest import QuestState
    ; U/ k8 U: ^3 l* w! L
  4. from net.sf.l2j.gameserver.model.quest.jython import QuestJython as JQuest- {" B+ ~( e- [  u4 a
  5. - g% v# x0 ]( @3 A% J* d
  6. KELTIR_NPC_ID = 12082
    8 b) E8 R# z4 q! ~/ J
  7. FANGS_ITEM_ID = 1859
    ! _' K% e+ M4 `3 U' @1 S1 \8 {
  8. DROP_RATE    = 500000* h0 Y+ @( o4 q* j" E

  9. , x- [3 [. S9 R5 H- a+ [1 L# R* ~
  10. WORLD_MAP_ITEM_ID = 1665
    6 ^) D. |0 }9 d3 p

  11. 9 c1 \; ]3 T+ }8 I2 A$ {2 r" X
  12. def getCount(st) :
      k* C0 v, o# E1 r$ j
  13. return st.getQuestItemsCount(FANGS_ITEM_ID); C7 Y9 e2 t. ^' t0 v
  14. 4 t+ l8 g( \- t* R# l. D" I# o
  15. def completed(st) :# Y+ V) c% c3 ^8 U& p9 {! U
  16. st.setState(COMPLETED)
    1 y4 V/ M5 k; m+ _
  17. st.clearQuestDrops()
    3 Z+ y+ u; \' z* n
  18. st.takeItems(FANGS_ITEM_ID,-1)2 X. g2 c2 }9 E" I/ _
  19. st.giveItems(WORLD_MAP_ITEM_ID,1)
    8 Y) W6 j' U7 z9 I+ Q) u. r! o* [
  20. st.exitQuest(False)2 ?8 s, E2 T4 w' i0 d+ v
  21. return
    ) j( B0 g8 @- l" ~8 x
  22. + d# @3 t* U4 R7 |+ x9 F, \, J
  23. def check(st) :9 }6 f  x  W; {  f
  24. if getCount(st) >= 4 :. q! `% [" C& y5 P6 z% E
  25. completed(st)
    4 ~0 w2 l9 L+ E- Y7 |0 Z( Y0 r
  26. return
    . t8 j3 E( |. O! {9 S0 W. H

  27. , O6 g+ i4 s3 R& S: U. n: Y
  28. class Quest (JQuest):3 Q: T" k" h  g% P

  29. & }8 L0 y+ X: J! [, ]' g* L
  30. def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)
    & Q* M- M' U+ r& A/ W; x4 j/ W

  31. + Q& A- a  z6 |/ ^0 Y, _2 o' {
  32. def onEvent (self,event,st):- i4 A( b. s" ]7 D9 @9 L( U  O, _
  33. id = st.getState()
    : s) b+ D+ u% f. |
  34. if id == CREATED : st.setState(STARTED). R" w- R1 B$ Y% K9 P
  35. elif id == COMPLETED: pass
    / Q- l; m( _/ J' f3 y' d; _
  36. elif id == STARTED : check(st)/ G7 e- o# b# ^1 f
  37. return
    7 j! \( S* P$ x+ l' u/ l
  38. 2 e8 S  w4 _8 M! |! ^8 G9 g1 K
  39. def onKill (self,npcId,st):
    8 R7 ?( f: |: g: Q4 @, ^/ \8 P( P- H
  40. if npcId == KELTIR_NPC_ID:
    0 t- m. `7 {( V4 \2 v( E8 c* i
  41. n = getCount(st)
    : Y2 z% p& `$ s, a* N1 W. w8 r
  42. if n == 0:! f% h! s8 a* F. u3 R
  43. if st.get('chat0') == None :
    ( h! N4 L/ d. m0 j8 \6 ?: h3 G4 D- M
  44. st.set("chat0", "true")' U, B2 z% f. _4 v3 {
  45. return "Chat0.htm"
    : R. K% S: i0 G$ J
  46. elif n == 1:
    : S/ w' X/ [- a/ m/ ?' ~
  47. if st.get('chat1') == None :
    ! _/ }; ]0 p! f3 \* M8 j
  48. st.set("chat1", "true")( E9 d2 ?# J( O" J; M' u
  49. return "Chat1.htm"
    & l; m& T* a, W! T$ f
  50. elif n >= 4:
    - H' X' b5 @! `; _  o. m
  51. return "Chat4.htm"6 @' I$ T! G6 g$ E# ?3 E7 e
  52. return "Collect "+str(n)+" of 4 fangs"
    ) Z" D* X: b- Q1 Z. _% Z) s  H! ?
  53. return
    9 e6 t2 d1 J. h( F5 b! C

  54. 4 \. J! C  D6 r: A6 p
  55. QUEST    = Quest(201, "Tutorial", "Tutorial quest")  ]6 Z1 F, q0 x% p6 s) N  f
  56. CREATED = State('Start',    QUEST); t0 E2 F1 H% r7 W+ o  L/ i
  57. STARTED = State('Started', QUEST), q& Z. g! `/ m& l
  58. COMPLETED = State('Completed', QUEST)
    2 a' D: W# \, K0 r1 @& y

  59. 5 h0 a' p5 ~3 x6 S3 A2 n1 \
  60. QUEST.setInitialState(CREATED)' w& ~% ]& k" }
  61. QUEST.addStartNpc(7056)3 A3 T8 o" W- U# a# F
  62. QUEST.addStartNpc(7012)
    : B! }& @( B3 O3 \# e
  63. QUEST.addStartNpc(7009)
    6 `9 s( S) n  O
  64. QUEST.addStartNpc(7011)' p0 K: O  c$ l# ^" H

  65. ( I& v3 A+ Y2 g
  66. STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
    % m- i: m: r* r
  67. STARTED.addKillId(KELTIR_NPC_ID)
    9 j2 ]5 P! _9 R- p/ ]
  68. STARTED.addTalkId(7056)
    : c) v0 M0 j' [  s& c; H
  69. STARTED.addTalkI d(7012)
    + U3 ^' c/ L2 D" N+ J
  70. STARTED.addTalkId(7009)
    6 @6 _4 |$ o0 b1 f* b) w/ W
  71. STARTED.addTalkId(7011)
Скопировать код

& X9 b  N: ?4 `7 s! ?7 M+ {5 \; V5 K+ Y
Чтобы ответить, вам надо авторизироваться в системе Вход | Зарегистрироваться

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

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

638638758

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

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

admin@artace.ru Онлайн

QR-код

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