Top.Mail.Ru

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

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

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

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

x
Хроники        Interlude
9 Q; p- r$ U: T7 _. uСборка        L2j; d% r( w$ b- U" P
Обратите внимание: в файле htm стартового NCP обязательно должна быть ссылка на квест:" a  N! d9 s  @" v  Y& `8 _4 g
  1. STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код
Для этого квеста больше ничего не надо. Все необходимое для корректной работы квеста уже добавили. Вот полный текст квеста:. a2 {. y2 c* q8 k2 q

# j4 x7 `% r$ I" q* x+ R
  1. if getCount(st) >= 4 :
    # S" P) x1 B4 N
  2. completed(st)
    " d: X: G- p' y) s
  3.   return% O. x) D' R5 F- ^2 a5 W
  4. / p0 _" ?& I6 Z- R/ t& \( W4 ^
  5. class Quest (JQuest):0 I  N: P, `; i% m
  6.   def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)
    : P" Y" R2 A) p. s. L- Q& S
  7.   def onEvent (self,event,st):
    8 s6 D3 Z# {) `2 V- X- ?+ V+ a9 {! p
  8. id = st.getState()  {$ ~6 G1 [: E' `( v
  9. if   id == CREATED  : st.setState(STARTED)" c  F7 ~0 P# t7 n8 s
  10. elif id == COMPLETED: pass. A" ?. F  R2 z; ]! D* n
  11. elif id == STARTED  : check(st)
      M% j/ K. |) R6 q. m3 P) \
  12. return/ b! @5 n8 d& s  X1 u; D) N# R) k

  13. % i% S" a/ s; n) i4 n
  14. QUEST     = Quest(201,"Tutorial", "Tutorial quest")7 J5 S" Q9 f+ i; r
  15. CREATED   = State('Start',     QUEST)
    ' w( E* W# ~8 f5 f
  16. STARTED   = State('Started',   QUEST)
    3 ~: W5 p6 i  R7 t7 K& u8 L
  17. COMPLETED = State('Completed', QUEST)0 T; |  M; h: f, k1 k& w, q

  18. 3 I" p/ i# ?9 @5 V* Q# |
  19. QUEST.setInitialState(CREATED)! S" M) E' r# V( T+ w: J8 h
  20. QUEST.addStartNpc(7056)
    2 o$ F2 [4 c" @3 w3 \
  21. STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код
Теперь рассмотрим, как это работает.2 l- ^  q  ]! _7 W4 d5 s
Игрок подходит к начальному NCP (в данном случае 7056), нажимает на «Quest». Квест будет создан и состояние квеста перейдет к CREATED и игроку будет показана страничка Start.htm с описанием квеста. Тогда метод onEvent, поле открытия странички Start.htm переведет состояние квеста в STARTED и игроку будет показана страничка Started.htm, где будет опсание того, как найти keltirs и .т.д.
0 E4 J7 O$ V6 E) ~4 m  P- O, m
9 {9 u5 l7 Y8 M' P
! \+ X& b/ r' N1 H
При состоянии STARTED будет зарегистрирован дроп «fangs» при убийстве keltirs. Игрок может вернуться к стартовому NCP и спросить о квесте – метод onEvent будет вызван снова. Если у игрока не хватает необходимого количества предметов, то метод check() не переведет квест в следующее состояние и Started.htm будет показана снова. Но если игрок собрал необходимее количество предметов (в данном случае 4 клыка), то метод check() вызовет метод completed() который переведет квест в новое состояние COMPLETED, заберет все клыки, даст карту мира, т.к. это награда за квест, покажет Completed.htm и завершит квест.4 u+ c8 {6 H# r6 a8 {' F2 A+ y5 S
7 ^* m# X6 u1 O  M6 {& d7 g% }

5 I4 t: A% K0 a* ?& sТеперь давайте сделаем наш квест более похожим на то, что он должен из себя представлять.
/ K0 v, R' c" [& y7 q- }  q) kПрежде всего у нас есть 3 метода для объявления их в Яве – onTalk, onKill и onEvent. Если методы onTalk и onKill не объявлены, то за них все будет делать метод onEvent, т.е. определять квестовых монстров и вызывать диалоги NCP. Есть примечание, методы onTalk и onKill будут вызывать только диалоги с NCP в зависимости от текущего состояния квеста. Метод onKill будет вызываться только тогда, когда мы убиваем квестового монстра.' G7 \! m' R* m$ h, D/ j' q/ T! Z

( N- G) a. L6 k" z2 B9 _8 O6 j0 c( i
# A, t8 o. P* D& ~
Давайте рассмотрим как вызывается метод onKill при убийстве keltir в состоянии квеста STARTED:0 I& B3 `7 `: g" Q9 v
  1. STARTED.addKillId(KELTIR_NPC_ID)
Скопировать код
и метод onKill в классе Quest:2 F6 O4 w' Y9 J
! `6 s4 F+ y, _6 ^7 H/ J8 ~
  1. class Quest (JQuest):
    % _$ o- V4 n3 u5 c! d
  2.   ...9 J7 C  t2 b4 w
  3.   def onKill (self,npcId,st):0 G% K9 |1 n) L$ o8 p( l
  4. if npcId == KELTIR_NPC_ID:1 b) k: p9 m0 J' ?+ M+ a
  5.    n = getCount(st)
    4 I( _' C- E0 c8 C
  6.    if   n == 0:
    - ?+ N6 Z" C; n8 j3 |3 k. m/ H
  7.        return "Chat0.htm"; e6 f) N- z7 K2 F7 n9 J! i: G& o) K
  8.    elif n == 1:$ N2 n4 V! P% [
  9.        return "Chat1.htm". y  d1 S1 q% }1 ^: A4 U
  10.    elif n >= 4:! s" K$ A. h+ X0 U8 ^( _
  11.        return "Chat4.htm"
    ( V/ S9 ~9 p1 S
  12.    return "Collected "+str(n)+" of 4 fangs"' q2 t( r8 d9 v3 ~" d, i
  13. return
Скопировать код
Метод onKill (а так же метод onTalk) имеет следующие параметры:
/ l6 z$ p8 r$ G+ p: P5 g
* `0 A9 A2 i3 w( a- z  g! U( m
; U: Q9 d; g& u: y! y
• self – квест. p' A% U% H& n4 R7 S  ?
• npcId – ID NCP, которого мы должны убивать (если это метод onTalk, то ID того NCP, с которым мы должны поговорить).9 c2 X0 M2 `7 k
• st – текущее состояние игрока.
! I$ G4 U0 L4 R& x4 D; C2 o
( X. _9 k0 y' |, t9 U; F
5 |* `+ C# I( }% |# I; L
В этом методе мы проверяем и отмечаем, является ли убитый NCP keltir’ом. В основном эта проверка не нужна, т.к. у нас только KELTIR_NPC_ID.
7 k, Q; M4 f' J& o  u6 b) |2 G1 J: a) e" t' M2 M$ ^' D
, {) ?  {  _; I  Q2 T& q# ~2 ^
Затем проверяем количество предметов (в данном случае количество клыков), и если их вообще нет, то возвращаем строку "Chat0.htm", если только один предмет, то возвращаем строку "Chat1.htm", если же предметов 4 или больше, то "Chat4.htm". Если строка возвращена из методов onEvent, onKill или onTalk, то сервер покажет соответствующие htm. В Chat0.htm может иметь следующий текст: «Вы не имеете ни одного клыка, возвращайтесь позже, когда соберете 4 штуки и бла, бла, бла…», в Chat1.htm может быть следующий текст: «У Вас всего 1 клык, по этому соберите еще…». В Chat4.htm – «Вы собрали необходимое количество предметов, возвращайтесь к вашему тренеру, что бы завершить квест…»+ Y! h# m" F: @6 `! P" U: w3 x
; f2 W& J9 C( }- W) U- i: |

( g% G  @4 S+ BПримечание: если в строка return начинается с "<html>", то будет показана страничка html с текстом, который стоит далее. Так вместо:, c3 G  t/ F- x& g% E& `* x. u6 ~
return "Chat4.htm"
! N* w. ~' p# C( v# o% \6 D" S  u* Z+ o7 i
. O) D, j+ E7 g( q! ]- r! {- Z6 U
можно поставить:# e8 C8 A' i9 u; p
  1. return "<html><body>Return to your trainer to complete the quest</body></html>"
Скопировать код
Так же если строка заканчивается без .htm или в начале нет <html>, то текст будет выведен, как системное сообщение в окне чата. В нашем случае мы сделаем так, что бы при каждом убийстве keltik выводилось системное сообщение: «Собрано N из 4-х клыков».
5 C( [  U1 J7 r+ L7 b+ @0 t
7 U+ S9 X: N% y/ R, s2 ?

% q: G' D0 |; M2 e8 |" _Наш код для onKill имеет один недостаток. Он будет постоянно показывать Chat0.htm, Chat1.htm и Chat4.htm, нам же необходимо, что бы Chat0.htm и Chat1.htm показывались только один раз. Как нам это сделать? С помощью переменных.
, ^' e; i$ F: W
  G% t! g$ ~# E5 H" t4 l
5 m9 w/ |5 K; U& q1 S7 z* V
В каждом квесте строки могут храниться с помощью переменных. Эти переменные сохраняются в Вашей БД. В каждом методе мы можем назначить, прочитать и удалить переменные. Давайте изменим метод onKill, так что бы каждый диалог вызывался только один раз.
" T  i  e2 M' z4 I' f& ?) N# U/ u
  1. def onKill (self,npcId,st):
    6 `* p5 A* o! J$ L- M0 M
  2. if npcId == KELTIR_NPC_ID:" z" e9 J+ J0 A
  3. n = getCount(st), o, G, E8 F% k6 ?( T5 u0 X
  4. if n == 0:
    : W  j1 Z7 U: {" y! F
  5. if st.get('chat0') == None :& O) u1 a1 I/ N2 |4 M% E
  6. st.set("chat0", "true")
    4 j4 e0 |2 \) @; U0 ^2 F
  7. return "Chat0.htm"
    & h3 f0 S% o8 c. \- Q
  8. elif n == 1:* W1 J; ?7 J& d" W1 k
  9. if st.get('chat1') == None :& U4 X" q( y" I2 u. N/ z5 v2 J; C
  10. st.set("chat1", "true")$ a- v6 ]; s& i5 D- N1 e# F; v
  11. return "Chat1.htm"
    3 K2 G- z  T" i' n5 _0 w
  12. elif n >= 4:; p  G$ I* M/ Q5 f, n+ v
  13. return "Chat4.htm"+ ]0 s6 r* Q9 V/ ^. d
  14. return "Collected "+str(n)+" of 4 fangs"8 F: w0 G$ r6 n( \* Z* D
  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.
" S  l, t, C1 G8 x3 R- J3 F& R! {+ m& ^& ^3 [4 a

1 X: z* K: q2 w# {4 C+ z8 oВот конечный рабочий вариант квеста:
* W' b/ ?: D5 }# {) c
  1. import sys# r0 V# n! K% N' `
  2. from net.sf.l2j.gameserver.model.quest import State
    ) h' |/ \+ Z6 S  b1 n
  3. from net.sf.l2j.gameserver.model.quest import QuestState/ M( `7 K9 I8 Q  Y
  4. from net.sf.l2j.gameserver.model.quest.jython import QuestJython as JQuest' R) @$ y( T% Z  P0 g7 a, M

  5. 2 z# c- n: r, t1 D$ I; M
  6. KELTIR_NPC_ID = 120824 f/ y' w3 b4 V
  7. FANGS_ITEM_ID = 1859# b3 C3 v6 z8 Q
  8. DROP_RATE    = 500000. E6 W5 L& |2 R; b! u! W, x

  9. $ L. {" _$ t  `; |. Z: K4 |
  10. WORLD_MAP_ITEM_ID = 16651 a7 e. {6 b% B& ~* c

  11. 8 i( ^! E& @4 Y- k: \4 u+ z
  12. def getCount(st) :
    0 g1 d- M  t8 |0 e3 U+ ^9 e- P+ \
  13. return st.getQuestItemsCount(FANGS_ITEM_ID)
    . ]# z7 s' p6 O2 L1 G7 x7 `

  14. . d) l" l# ?! Y( J+ n% H% K
  15. def completed(st) :
    + w2 {( @/ a/ u
  16. st.setState(COMPLETED)+ ?  d! _! X- W$ u) R# M: m$ s+ V
  17. st.clearQuestDrops()" o, O( G) d6 u4 s/ }: O& h
  18. st.takeItems(FANGS_ITEM_ID,-1)- d" k* c5 n: i9 L* N' }: k
  19. st.giveItems(WORLD_MAP_ITEM_ID,1)( e4 o; T' g! q' V/ u3 f) Z" u. L
  20. st.exitQuest(False)2 J: b! [. S. n9 O/ b- W
  21. return
    * s" I( A+ a! u2 ^/ }" o4 Z' s

  22. , b- D6 Z4 E" l2 F6 P# g: a
  23. def check(st) :4 F. }6 I' m9 e" ?4 o& c9 p
  24. if getCount(st) >= 4 :
    : Z( N% d- `5 j* i* A
  25. completed(st)
    * V2 O0 Q, g6 \! ^( f
  26. return
    3 q: k1 Z. K# z9 q& w: c  W: K/ v! ~" T: p

  27. . @% j+ Q& o- v  c2 e3 H
  28. class Quest (JQuest):& P' d1 f; H* @4 D! S! {  M

  29. 2 y5 C5 W# h( L% I# {$ o
  30. def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)$ v3 i4 x8 [7 q  Y. z

  31. , ]* O: P2 {2 R) Q5 z) w
  32. def onEvent (self,event,st):
    ) S) r- Z3 E+ R  x3 ]& s
  33. id = st.getState()
    6 a5 }% g/ k2 N/ f$ l5 x8 V, G
  34. if id == CREATED : st.setState(STARTED)
    % r; a0 `# H1 n8 R* o; `. c
  35. elif id == COMPLETED: pass+ H0 c# G  H+ u; x5 c6 C# v
  36. elif id == STARTED : check(st)
    . k( l% ^1 w: p5 v, X
  37. return0 P5 Y  i' J% n
  38. 8 U- f( F+ d1 w- `4 @) B
  39. def onKill (self,npcId,st):) v' E$ m; M( `1 }8 {
  40. if npcId == KELTIR_NPC_ID:) L7 i7 S1 n7 L' ~6 A( x: k
  41. n = getCount(st)
    * Y0 q" K. ?7 D7 ^0 e1 d7 u
  42. if n == 0:9 t+ J  T# [5 |& E( k" j7 e) w
  43. if st.get('chat0') == None :
    4 ]8 t8 G+ Q/ G
  44. st.set("chat0", "true")
    0 n5 i0 ^/ o7 F9 ]$ C
  45. return "Chat0.htm"
    - O/ t2 P* T' k
  46. elif n == 1:3 A, k6 X3 }2 X5 Z  {
  47. if st.get('chat1') == None :
    - e/ q0 s4 l- `* f: \4 U/ {
  48. st.set("chat1", "true")
    7 C2 N5 n# C: ?8 l& B2 `
  49. return "Chat1.htm"3 Y( Z5 ?2 q1 P
  50. elif n >= 4:
    0 l# _! j8 X- m' A% j
  51. return "Chat4.htm"
      Z, z1 e0 r" C9 N# J! J9 r, W1 S
  52. return "Collect "+str(n)+" of 4 fangs"* _  y5 s) }! D2 e
  53. return& z  }1 j4 W! f
  54. % U$ R6 p- H3 I2 H; z6 a' h! [# K
  55. QUEST    = Quest(201, "Tutorial", "Tutorial quest")
    8 b  M% @$ F4 }& N" Q
  56. CREATED = State('Start',    QUEST)) u7 o! r  f7 X( o. A
  57. STARTED = State('Started', QUEST)% c" d' Y7 A# B* ]; F8 D- H
  58. COMPLETED = State('Completed', QUEST)1 z# r( N% e! o4 p# j" r7 F  s2 L$ c
  59. 4 _: k' k8 {) {' z& R
  60. QUEST.setInitialState(CREATED)
    * P" x1 |+ v% j+ Q2 l
  61. QUEST.addStartNpc(7056)* L  X& `9 K& I/ _) d
  62. QUEST.addStartNpc(7012)
    & D! }/ F- ~/ g8 i8 t- X
  63. QUEST.addStartNpc(7009)
    , S7 U  M5 P7 N) L. b# @; _1 G0 F7 n
  64. QUEST.addStartNpc(7011)! u0 {" ]8 `! {+ f

  65. 8 M4 L- p$ g5 s) k* ~
  66. STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)3 A9 R* }, }9 N3 N2 x
  67. STARTED.addKillId(KELTIR_NPC_ID)" o' a0 O% [9 t# W# ~
  68. STARTED.addTalkId(7056); q4 i/ v( A$ A2 t6 E1 ?2 ]
  69. STARTED.addTalkI d(7012)
    : d% p# ?) g4 n/ y3 ]
  70. STARTED.addTalkId(7009)8 M2 d5 M5 B1 @3 j! q
  71. STARTED.addTalkId(7011)
Скопировать код

6 n: A4 U9 X. x( a# n8 H1 s
' B3 h8 D3 F% e* N( }2 F# d
Чтобы ответить, вам надо авторизироваться в системе Вход | Зарегистрироваться

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

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

638638758

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

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

admin@artace.ru Онлайн

QR-код

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