Top.Mail.Ru

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

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

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

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

x
Хроники        Interlude) l; S3 z6 Y; k8 |
Сборка        L2j  R0 d+ x# y9 }, \  x. Y0 [+ Z
Обратите внимание: в файле htm стартового NCP обязательно должна быть ссылка на квест:3 w5 i1 Z' ]; q! s( O
  1. STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код
Для этого квеста больше ничего не надо. Все необходимое для корректной работы квеста уже добавили. Вот полный текст квеста:
( p! f/ a4 t8 }8 e2 O/ M' R: f* Y5 ?( i9 I. J
  1. if getCount(st) >= 4 :3 M; L/ Y; h, z3 X" d7 ~4 U
  2. completed(st)
    $ R' E7 b) Y' n* r) g: f4 A
  3.   return' |. h+ v8 }2 C8 @  _" c9 E

  4. ; Z; A( {& v8 K( z; ?
  5. class Quest (JQuest):
    - p2 C6 ^$ c  L( B: {+ h' F
  6.   def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)* q- z9 X5 i) U+ o! n$ [+ n
  7.   def onEvent (self,event,st):
    : m9 h9 h7 I: b* S7 T+ y7 O
  8. id = st.getState()
    # h7 I' z% G" T. P0 ?/ b' X! M
  9. if   id == CREATED  : st.setState(STARTED)
    + h. ]0 o+ ]7 a2 _3 d
  10. elif id == COMPLETED: pass
    * E, U" u6 E/ o% O
  11. elif id == STARTED  : check(st)7 S4 W$ S" r! D& k+ `$ s" N" s# y
  12. return
    4 H' }" _, J/ m/ K+ d# k2 p
  13. ' w( R0 r3 X$ ?) V
  14. QUEST     = Quest(201,"Tutorial", "Tutorial quest")& a) `% A* e' N0 z
  15. CREATED   = State('Start',     QUEST)
    , j$ D- y" o2 D6 e
  16. STARTED   = State('Started',   QUEST)# {* S# X- }' F, H$ b$ m
  17. COMPLETED = State('Completed', QUEST)
    $ f  [$ a( I2 q) p2 g0 _
  18. 8 f; e  r; L. Y7 l; P
  19. QUEST.setInitialState(CREATED)& _. q" T) c+ N. ]2 G& x
  20. QUEST.addStartNpc(7056)' N; b2 |3 Y  {, b6 U' o
  21. STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код
Теперь рассмотрим, как это работает.+ L, F" K' B5 F5 [; {
Игрок подходит к начальному NCP (в данном случае 7056), нажимает на «Quest». Квест будет создан и состояние квеста перейдет к CREATED и игроку будет показана страничка Start.htm с описанием квеста. Тогда метод onEvent, поле открытия странички Start.htm переведет состояние квеста в STARTED и игроку будет показана страничка Started.htm, где будет опсание того, как найти keltirs и .т.д.4 ]& z7 H2 ]5 M' H% F( m, |

; W6 J* {7 W# X/ N# n
- i2 e* R3 I' x
При состоянии STARTED будет зарегистрирован дроп «fangs» при убийстве keltirs. Игрок может вернуться к стартовому NCP и спросить о квесте – метод onEvent будет вызван снова. Если у игрока не хватает необходимого количества предметов, то метод check() не переведет квест в следующее состояние и Started.htm будет показана снова. Но если игрок собрал необходимее количество предметов (в данном случае 4 клыка), то метод check() вызовет метод completed() который переведет квест в новое состояние COMPLETED, заберет все клыки, даст карту мира, т.к. это награда за квест, покажет Completed.htm и завершит квест.1 N4 K( B* h9 Q: X- L; f
5 w1 V- z# P% n
; i1 E% ^9 e3 V0 W3 s
Теперь давайте сделаем наш квест более похожим на то, что он должен из себя представлять.
/ h" v3 y  x4 Z. u1 o  j. JПрежде всего у нас есть 3 метода для объявления их в Яве – onTalk, onKill и onEvent. Если методы onTalk и onKill не объявлены, то за них все будет делать метод onEvent, т.е. определять квестовых монстров и вызывать диалоги NCP. Есть примечание, методы onTalk и onKill будут вызывать только диалоги с NCP в зависимости от текущего состояния квеста. Метод onKill будет вызываться только тогда, когда мы убиваем квестового монстра.. I6 X- B" Z3 r& j- X' A
  P8 R+ W) y0 z2 G/ E# j

+ K5 [4 ~- }  D! T: F4 O9 n& w$ `  ]Давайте рассмотрим как вызывается метод onKill при убийстве keltir в состоянии квеста STARTED:
: U& \0 ^$ d$ L4 L8 H# f
  1. STARTED.addKillId(KELTIR_NPC_ID)
Скопировать код
и метод onKill в классе Quest:
7 n/ p, A: j0 c0 P- q7 B4 E( i& j6 T1 @1 t
  1. class Quest (JQuest):+ ~; R& s, R7 h2 p1 D7 D
  2.   ...& N6 x) ~4 Z( q9 P9 ]
  3.   def onKill (self,npcId,st):1 s' h: d* C. I" P; h
  4. if npcId == KELTIR_NPC_ID:# `) M1 E2 ~# l" ]8 ~3 g( Y: J
  5.    n = getCount(st)' w: S, m7 K& S% u6 M
  6.    if   n == 0:" M$ I& v! t6 L& N
  7.        return "Chat0.htm"4 X; T7 x: E4 O8 O7 `
  8.    elif n == 1:+ M0 ?/ v" }/ M3 f  }5 i+ ^
  9.        return "Chat1.htm"
    9 f) ^6 G' c# Q; j2 U9 h8 o
  10.    elif n >= 4:' q, `3 Q# i& K: E0 v
  11.        return "Chat4.htm"% t' Y8 f& {% g* W0 }- z
  12.    return "Collected "+str(n)+" of 4 fangs"8 b* I& j& e8 ]3 Y
  13. return
Скопировать код
Метод onKill (а так же метод onTalk) имеет следующие параметры:" S! X- G# x3 N+ J9 K& f

3 T7 F  Y$ S5 v" f

' |" T0 f- Q" Q: E5 D/ G• self – квест0 ^6 R- Z1 Y9 Q* H
• npcId – ID NCP, которого мы должны убивать (если это метод onTalk, то ID того NCP, с которым мы должны поговорить).
2 G* [% v' @0 b5 I! F• st – текущее состояние игрока.
) _: g4 q2 }4 l* o
* v3 `- N3 E4 `& ?, ^6 z, _* |

6 M9 r& d/ V( j1 q4 }& c& u  JВ этом методе мы проверяем и отмечаем, является ли убитый NCP keltir’ом. В основном эта проверка не нужна, т.к. у нас только KELTIR_NPC_ID.
6 T3 {3 \% U5 W$ _5 [: U3 X1 \3 ~2 y
' J& ]: F3 I7 m* ^, D6 R$ U' w

" c( w# h( [% S6 tЗатем проверяем количество предметов (в данном случае количество клыков), и если их вообще нет, то возвращаем строку "Chat0.htm", если только один предмет, то возвращаем строку "Chat1.htm", если же предметов 4 или больше, то "Chat4.htm". Если строка возвращена из методов onEvent, onKill или onTalk, то сервер покажет соответствующие htm. В Chat0.htm может иметь следующий текст: «Вы не имеете ни одного клыка, возвращайтесь позже, когда соберете 4 штуки и бла, бла, бла…», в Chat1.htm может быть следующий текст: «У Вас всего 1 клык, по этому соберите еще…». В Chat4.htm – «Вы собрали необходимое количество предметов, возвращайтесь к вашему тренеру, что бы завершить квест…»
: m7 X. a7 H7 R! I3 r, W1 \- M6 ~8 h1 L

* V1 |1 y% L4 w% f" MПримечание: если в строка return начинается с "<html>", то будет показана страничка html с текстом, который стоит далее. Так вместо:5 n( w6 y5 U$ F3 }; M2 d- R. x% z
return "Chat4.htm", o. R! c# j: K6 u" G6 ]( H2 g! Q

4 x8 o: \! [0 k! H2 v
) R! T) W) ]8 ~
можно поставить:
* {* o! J  T- O9 V# y% l% }
  1. return "<html><body>Return to your trainer to complete the quest</body></html>"
Скопировать код
Так же если строка заканчивается без .htm или в начале нет <html>, то текст будет выведен, как системное сообщение в окне чата. В нашем случае мы сделаем так, что бы при каждом убийстве keltik выводилось системное сообщение: «Собрано N из 4-х клыков».3 M# T2 ]. v& R

* b. Q. ~& T& T! l$ k1 n0 V: l2 O

6 S9 \& n5 d5 E  i! nНаш код для onKill имеет один недостаток. Он будет постоянно показывать Chat0.htm, Chat1.htm и Chat4.htm, нам же необходимо, что бы Chat0.htm и Chat1.htm показывались только один раз. Как нам это сделать? С помощью переменных.
& J' o$ {6 A6 n# v2 f" X
, j: m, \0 c$ Y& z, n
& a8 t# I& L' p8 o; r3 q
В каждом квесте строки могут храниться с помощью переменных. Эти переменные сохраняются в Вашей БД. В каждом методе мы можем назначить, прочитать и удалить переменные. Давайте изменим метод onKill, так что бы каждый диалог вызывался только один раз.
+ p" y0 l9 X4 C! g& q
  1. def onKill (self,npcId,st):
    $ ^0 c0 b9 ^4 E
  2. if npcId == KELTIR_NPC_ID:/ x% M/ W! x! S
  3. n = getCount(st)1 S: t% U8 r2 v- e. n: @
  4. if n == 0:+ R4 B; e9 L( Q5 y5 ]; U5 E
  5. if st.get('chat0') == None :
    $ r1 y$ k# s6 B
  6. st.set("chat0", "true")
    6 e& g1 Q: I2 h
  7. return "Chat0.htm"  G  g2 \. g+ d7 k4 m1 w
  8. elif n == 1:
    ; s# C9 n# n7 s
  9. if st.get('chat1') == None :0 x$ b. ?* i2 j. A
  10. st.set("chat1", "true")6 ]8 E' n+ p0 t+ t
  11. return "Chat1.htm"2 S; B$ ^7 [! N% C0 L9 l
  12. elif n >= 4:: U1 ?$ r% ?" Y, O8 F+ J
  13. return "Chat4.htm", B1 {/ M. w- `; k" F! d/ x5 Z
  14. return "Collected "+str(n)+" of 4 fangs"( `- c" p6 u# l- `$ 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.4 d) N" H. F' [! e0 y. U1 u; N9 k5 E! E

+ h% F8 V2 ]' ?) `

3 d' r& M: F( R* {5 Z9 T" R- ^' rВот конечный рабочий вариант квеста:$ e, _6 ]8 s3 x
  1. import sys
    ( I3 o+ Q  P  _: p' F# G! a) U; e
  2. from net.sf.l2j.gameserver.model.quest import State% ?8 I' t( ^2 o8 d- ~+ N
  3. from net.sf.l2j.gameserver.model.quest import QuestState
    8 `+ A5 i4 d% E' Z+ D# y1 \
  4. from net.sf.l2j.gameserver.model.quest.jython import QuestJython as JQuest
    4 I" T& }8 ?5 r

  5. * D; U  G( ~/ F2 v( `+ r  E
  6. KELTIR_NPC_ID = 12082
    , j7 \7 h% H# o
  7. FANGS_ITEM_ID = 1859% m5 f! |1 C- d* N( m
  8. DROP_RATE    = 5000007 a; w5 F! @+ b9 a& }# c- K" k
  9. " W. o8 ^5 e6 f
  10. WORLD_MAP_ITEM_ID = 1665
    / o* ?5 \9 _2 Q' x( ]

  11. 9 {; Y) p  u' U9 ]/ N8 J$ Q# B- K
  12. def getCount(st) :
    # V0 t. K% u" a$ G. }
  13. return st.getQuestItemsCount(FANGS_ITEM_ID)
    , N  n/ l2 n8 m8 V9 O. y7 p

  14. + r, r+ E4 [  @7 @
  15. def completed(st) :
    6 W8 C8 p# S9 U( C0 a/ J  C6 O# o/ `
  16. st.setState(COMPLETED)
    % D, X3 Q/ p! w( d
  17. st.clearQuestDrops()
    0 I- |7 R" {* P" g- I7 Z# x& \
  18. st.takeItems(FANGS_ITEM_ID,-1)3 m7 u& b6 Q- k) L
  19. st.giveItems(WORLD_MAP_ITEM_ID,1)6 J6 N7 W: H: h3 Z! i% g# \( z
  20. st.exitQuest(False)
    - d1 V% f8 |! v( i9 j: ]* F
  21. return% A0 s4 S) ?2 @6 v+ W# j

  22. * Z+ D4 |! x) q, ]  Y
  23. def check(st) :
    " B: }' b$ l5 e2 C  \3 t
  24. if getCount(st) >= 4 :+ P" Y/ w5 d/ B9 t) b
  25. completed(st): J4 h4 U$ M: A( u! G" B) [
  26. return7 _1 t0 _6 Z' v; Q
  27. . z1 z2 C& l) u4 m! d
  28. class Quest (JQuest):% `9 _) z8 B$ b2 a
  29. / j. d' B8 @- K5 p4 |' \
  30. def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)
    + l: x2 r6 {; a$ k( q
  31. 4 T' G+ K# ^0 I# `* \8 ?0 i
  32. def onEvent (self,event,st):
    5 `8 F8 f4 f% n/ Y
  33. id = st.getState()
    % Y2 i0 X7 l# {1 P, T
  34. if id == CREATED : st.setState(STARTED): d  G( \5 P2 P. Z, F
  35. elif id == COMPLETED: pass
    9 F" t& m) K+ E* x' d
  36. elif id == STARTED : check(st)
    0 C* W" L# d1 }& `- A* u
  37. return
    5 i2 |: T/ B" o; u' x

  38. 9 Z1 S3 ?+ h  n5 ~: Q( m4 K
  39. def onKill (self,npcId,st):
    ' V$ x0 I/ _9 P' i
  40. if npcId == KELTIR_NPC_ID:
    , a) O3 X# N9 x* F7 U, N* s
  41. n = getCount(st)
    7 G- p7 j9 a" o$ m. k
  42. if n == 0:
    . V* C  ]. }  }/ }: V/ |1 t) y
  43. if st.get('chat0') == None :
    3 O$ L! G9 d* G
  44. st.set("chat0", "true")
    1 F- g  r% E7 h9 e/ ?
  45. return "Chat0.htm"5 S' u! B3 D  Z  q$ K0 z' R
  46. elif n == 1:
    : V- w% q) P- O# U- P
  47. if st.get('chat1') == None :7 R4 s3 C; p3 R) w/ |8 @
  48. st.set("chat1", "true")% x1 n( t) M0 C7 z' Z4 e# W' q
  49. return "Chat1.htm"% P! A% d' b. _0 W+ H# ~* N$ L9 w
  50. elif n >= 4:
    2 ?3 s+ Q+ e3 z8 a4 ?
  51. return "Chat4.htm"/ N( ]6 M) t- J  \! _3 ~
  52. return "Collect "+str(n)+" of 4 fangs"( z  v  _3 \6 [& S
  53. return
    9 }/ ]8 i$ z8 B# `- F

  54. * ~9 S# B; I' Y& p/ F7 T8 X
  55. QUEST    = Quest(201, "Tutorial", "Tutorial quest")9 }5 r# \( }% j% {
  56. CREATED = State('Start',    QUEST)
    ! O2 I7 K  o& Y1 u4 _' f5 `! u
  57. STARTED = State('Started', QUEST)9 M; G2 p( |5 H0 P! i
  58. COMPLETED = State('Completed', QUEST)
    & y4 U5 i) v- {+ M% o$ x- f

  59. ( I0 y  e8 t6 s. o6 t8 t
  60. QUEST.setInitialState(CREATED)
    3 i$ a# l2 n2 |
  61. QUEST.addStartNpc(7056)
    # v2 U1 o4 ]5 @7 ]
  62. QUEST.addStartNpc(7012)
    + j& \, `, a8 r1 U. A
  63. QUEST.addStartNpc(7009)' x: ~6 V' r/ f! I1 G3 T
  64. QUEST.addStartNpc(7011)
    % e" i% [4 G+ F0 a7 D& e, P" W
  65. ) D4 l* C! _0 n; v. n" U
  66. STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)7 ^! g2 F* w4 ^/ y
  67. STARTED.addKillId(KELTIR_NPC_ID)9 ]- w7 d, D* T1 O! p5 Z
  68. STARTED.addTalkId(7056)
    : `, \) I& w( H. H7 Z4 m
  69. STARTED.addTalkI d(7012), w0 K4 z, v' t+ |
  70. STARTED.addTalkId(7009)
    + C0 r1 s5 V, b. z$ U; S) Z$ y# Q: X
  71. STARTED.addTalkId(7011)
Скопировать код

- q, G2 F' Z, ~' K; u$ U$ U/ N- M
Чтобы ответить, вам надо авторизироваться в системе Вход | Зарегистрироваться

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

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

638638758

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

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

admin@artace.ru Онлайн

QR-код

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