Top.Mail.Ru

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

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

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

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

x
Хроники        Interlude" Y3 f( j) J; p  ?1 g7 r
Сборка        L2j& [9 @) |* U& ^
Обратите внимание: в файле htm стартового NCP обязательно должна быть ссылка на квест:
3 h; K3 u: F3 V* X0 {# _5 ~
  1. STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код
Для этого квеста больше ничего не надо. Все необходимое для корректной работы квеста уже добавили. Вот полный текст квеста:* _' F/ {) M1 |) `& i, w, S

  y+ |/ L& K+ P- u. W" H  e' H
  1. if getCount(st) >= 4 :4 ^$ t4 g/ z! P
  2. completed(st)
    3 v- y+ Z+ k* S* w3 [+ M
  3.   return% {1 t# M+ A+ y
  4. 6 f' d+ T$ ?# U- \
  5. class Quest (JQuest):
    7 P; T* \/ \: D# v: @) b" A4 {
  6.   def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)
    5 u7 {$ K3 r0 b
  7.   def onEvent (self,event,st):0 G8 P$ _* X* Q+ W* `
  8. id = st.getState()0 j9 F6 ]7 U8 N* ^
  9. if   id == CREATED  : st.setState(STARTED)
    - R( p; B, k; ~+ T. ]' Q8 J+ {
  10. elif id == COMPLETED: pass0 O' [1 [* N5 \( {7 @( U' F2 I5 }
  11. elif id == STARTED  : check(st)
    9 c5 s0 A- i! s% q5 i& p+ {# I
  12. return9 T& u/ }7 K5 b9 i/ w

  13. 8 r1 K1 q) ]$ ]9 j- N
  14. QUEST     = Quest(201,"Tutorial", "Tutorial quest")0 b+ n0 H0 b+ j# n
  15. CREATED   = State('Start',     QUEST)
    2 v+ X; W0 e9 c8 q# Q+ S6 p
  16. STARTED   = State('Started',   QUEST)
    - Y! H* ^1 k. n" \' k
  17. COMPLETED = State('Completed', QUEST). }' f3 f7 ?2 q

  18. & n' s3 d. y" y$ F4 j
  19. QUEST.setInitialState(CREATED)& U& g  Y3 t# z8 ]" {( t
  20. QUEST.addStartNpc(7056)% r) n. K- b3 H
  21. STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код
Теперь рассмотрим, как это работает.
* z: y& d- p$ BИгрок подходит к начальному NCP (в данном случае 7056), нажимает на «Quest». Квест будет создан и состояние квеста перейдет к CREATED и игроку будет показана страничка Start.htm с описанием квеста. Тогда метод onEvent, поле открытия странички Start.htm переведет состояние квеста в STARTED и игроку будет показана страничка Started.htm, где будет опсание того, как найти keltirs и .т.д.
3 H2 s% d" d" N8 n+ Z, j& u+ ]% W1 T9 j, H! V
1 B/ Y, ?+ R# [6 Y% T: h
При состоянии STARTED будет зарегистрирован дроп «fangs» при убийстве keltirs. Игрок может вернуться к стартовому NCP и спросить о квесте – метод onEvent будет вызван снова. Если у игрока не хватает необходимого количества предметов, то метод check() не переведет квест в следующее состояние и Started.htm будет показана снова. Но если игрок собрал необходимее количество предметов (в данном случае 4 клыка), то метод check() вызовет метод completed() который переведет квест в новое состояние COMPLETED, заберет все клыки, даст карту мира, т.к. это награда за квест, покажет Completed.htm и завершит квест.% \. o1 ]9 W( i: O1 O6 T' W
# Q# @  P; b3 I; l5 {$ X
9 R2 S/ a0 g: K
Теперь давайте сделаем наш квест более похожим на то, что он должен из себя представлять.8 X7 ]: x1 F& A+ L
Прежде всего у нас есть 3 метода для объявления их в Яве – onTalk, onKill и onEvent. Если методы onTalk и onKill не объявлены, то за них все будет делать метод onEvent, т.е. определять квестовых монстров и вызывать диалоги NCP. Есть примечание, методы onTalk и onKill будут вызывать только диалоги с NCP в зависимости от текущего состояния квеста. Метод onKill будет вызываться только тогда, когда мы убиваем квестового монстра.3 Q9 @0 p" Y- t/ B1 f
- r2 N! g$ Y. ^) |

; ~( G, S) {; W7 f; m" |Давайте рассмотрим как вызывается метод onKill при убийстве keltir в состоянии квеста STARTED:/ s; ]$ e4 i% [$ U+ I
  1. STARTED.addKillId(KELTIR_NPC_ID)
Скопировать код
и метод onKill в классе Quest:- e& C' F' R. r
0 Q( E. L8 d+ h! m0 w9 j- v
  1. class Quest (JQuest):6 ~$ j9 f  J3 N8 q
  2.   ...
    # i# X( p% j2 l. m& g
  3.   def onKill (self,npcId,st):
    6 c% j' x* B! w0 I) H
  4. if npcId == KELTIR_NPC_ID:
    0 s: J; `8 B3 _% v
  5.    n = getCount(st)
    ) T3 y$ |+ v5 l! `- r% f  H
  6.    if   n == 0:
    ) w' \  c! d' i( {4 b0 t" e4 }5 g8 U
  7.        return "Chat0.htm"
    ! c$ r9 L4 c0 ]# D
  8.    elif n == 1:
    & i: L9 V5 d, A
  9.        return "Chat1.htm"
    9 [( b/ G" H1 S6 L* E
  10.    elif n >= 4:3 Z/ G7 c: n8 D/ Y3 m
  11.        return "Chat4.htm"
    & x& j8 \8 _" k6 w! P8 }
  12.    return "Collected "+str(n)+" of 4 fangs": p$ N2 B) s: H9 q0 [* F4 J/ t
  13. return
Скопировать код
Метод onKill (а так же метод onTalk) имеет следующие параметры:0 R' [3 w( F4 ?1 ]4 F9 e

$ Q" I  U: K3 O$ T

; T7 y( O3 F) @; z0 l1 c• self – квест
( }$ O# A: Z2 r# {• npcId – ID NCP, которого мы должны убивать (если это метод onTalk, то ID того NCP, с которым мы должны поговорить).8 ~, C. U1 m, O( W! n  \* m: K8 X
• st – текущее состояние игрока.% i+ X5 P% W# G' h  x

- `! n8 `; Y) D
4 ^, w4 o; E) [8 i) g
В этом методе мы проверяем и отмечаем, является ли убитый NCP keltir’ом. В основном эта проверка не нужна, т.к. у нас только KELTIR_NPC_ID.
. l4 s+ X) P$ e9 E4 m! `$ e% d/ S# C8 Q. t& j0 U5 u$ x
" M, p* v' K* d$ X
Затем проверяем количество предметов (в данном случае количество клыков), и если их вообще нет, то возвращаем строку "Chat0.htm", если только один предмет, то возвращаем строку "Chat1.htm", если же предметов 4 или больше, то "Chat4.htm". Если строка возвращена из методов onEvent, onKill или onTalk, то сервер покажет соответствующие htm. В Chat0.htm может иметь следующий текст: «Вы не имеете ни одного клыка, возвращайтесь позже, когда соберете 4 штуки и бла, бла, бла…», в Chat1.htm может быть следующий текст: «У Вас всего 1 клык, по этому соберите еще…». В Chat4.htm – «Вы собрали необходимое количество предметов, возвращайтесь к вашему тренеру, что бы завершить квест…»/ F' Z. H$ s6 n' Q% E, [2 A

! H% j; a* w4 D9 q
7 W% z7 o0 O/ @+ \" T$ N7 K( x
Примечание: если в строка return начинается с "<html>", то будет показана страничка html с текстом, который стоит далее. Так вместо:
+ e% h) t6 j- L+ G; Y, x0 Areturn "Chat4.htm"# p: m2 ^% h# L5 D. F1 o* t4 H
* |8 O1 p. f! \. |( s

+ e, F6 K+ I+ ]- Iможно поставить:! M% s' h- g( r4 T. |7 y
  1. return "<html><body>Return to your trainer to complete the quest</body></html>"
Скопировать код
Так же если строка заканчивается без .htm или в начале нет <html>, то текст будет выведен, как системное сообщение в окне чата. В нашем случае мы сделаем так, что бы при каждом убийстве keltik выводилось системное сообщение: «Собрано N из 4-х клыков».
2 l5 ?' i% Y/ K) L4 _% K
5 S. K' F4 b2 L' p* U* d- \! @! U$ U
: P/ D& `/ l: h
Наш код для onKill имеет один недостаток. Он будет постоянно показывать Chat0.htm, Chat1.htm и Chat4.htm, нам же необходимо, что бы Chat0.htm и Chat1.htm показывались только один раз. Как нам это сделать? С помощью переменных.
# y9 G' p$ ~. w0 B4 J
7 P) n4 H- G4 k, I; T5 u
" S' J, r: U' v6 [* a6 f0 M+ \$ [) `
В каждом квесте строки могут храниться с помощью переменных. Эти переменные сохраняются в Вашей БД. В каждом методе мы можем назначить, прочитать и удалить переменные. Давайте изменим метод onKill, так что бы каждый диалог вызывался только один раз.) K6 ^% X, S& i1 e& \
  1. def onKill (self,npcId,st):: G' x) t" J) e0 ]4 m
  2. if npcId == KELTIR_NPC_ID:
    & K- s9 I: n. T, G
  3. n = getCount(st)
    , }# ~5 h; V+ L5 |5 G7 D
  4. if n == 0:
    % Y  z4 G9 E, [  a
  5. if st.get('chat0') == None :* I7 i* x, G7 o# b7 u
  6. st.set("chat0", "true")! G3 D* Q2 s) w6 ?. z" V! i
  7. return "Chat0.htm"
    3 q: _8 p" c2 T1 m3 F( y3 [
  8. elif n == 1:+ R# u1 ~4 y$ y4 F) J% v
  9. if st.get('chat1') == None :
    7 m* F0 D# Q1 L  u! k. K
  10. st.set("chat1", "true")
    2 \" Z+ a1 F. a- v, a# t& M& ^
  11. return "Chat1.htm"
    8 g: v2 i; G* j/ l8 x2 Q4 u9 o! }
  12. elif n >= 4:/ n! f% x' \; C1 Y' t
  13. return "Chat4.htm"
    5 n: g, |" t9 S) T
  14. return "Collected "+str(n)+" of 4 fangs"5 s# a1 T5 [. h# u1 f# E* B
  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.
$ Z( t8 m' T: u$ `/ b1 k; E4 r8 W( o$ Y4 f

6 E; z' Y6 o) A2 C+ X' NВот конечный рабочий вариант квеста:/ G0 c+ e8 [/ O+ Q
  1. import sys
    ( v. [8 o% c  }, r& h
  2. from net.sf.l2j.gameserver.model.quest import State: m' d3 P8 I8 @' _
  3. from net.sf.l2j.gameserver.model.quest import QuestState
    " ^6 }  [, l% L9 \0 {* G
  4. from net.sf.l2j.gameserver.model.quest.jython import QuestJython as JQuest& Z- d# a/ b& g( y
  5. 5 o$ t, a& i- ~7 _
  6. KELTIR_NPC_ID = 12082( E4 F! v/ D0 v, L8 j  }
  7. FANGS_ITEM_ID = 1859
    # Q5 Q, \  S7 C, S* B' \
  8. DROP_RATE    = 500000
    4 A/ ^0 C5 h; k6 X/ {

  9. 4 x6 S3 ^6 w0 }; s3 z3 n* b
  10. WORLD_MAP_ITEM_ID = 1665: v! \) L" R, s6 q5 J* h8 h* a; m

  11. & L( u# q6 b9 {# S" Z$ U5 w
  12. def getCount(st) :
    9 f& b! t; g3 O. n9 N* N! y
  13. return st.getQuestItemsCount(FANGS_ITEM_ID)) ^- J6 M; H- v
  14.   a/ H. \) @+ v- E' ^
  15. def completed(st) :
    : `7 x# }0 j$ I, y7 i
  16. st.setState(COMPLETED)
    ( m) b* Z  Q$ {  `1 V6 s  I" B
  17. st.clearQuestDrops()
    9 {$ v8 V! w; D! H% h
  18. st.takeItems(FANGS_ITEM_ID,-1)( ?( \3 g$ b0 F; p  W' m3 e
  19. st.giveItems(WORLD_MAP_ITEM_ID,1)7 w- O1 V- L# p1 C& {8 i9 U0 r8 `
  20. st.exitQuest(False)
    % X6 O( R6 c! S) ]% d4 j; \
  21. return
    ! q8 r$ ?, r) z

  22. 4 P- Q& U7 m9 t! g* X9 l( J
  23. def check(st) :, n2 G% \/ e/ S0 A
  24. if getCount(st) >= 4 :
    * l0 J7 K) r1 T+ U# d% ~
  25. completed(st), t0 T: v% M9 S! L0 Q' a% f
  26. return6 {; n+ n" }; l6 l& E

  27. + q, q  ?6 }2 L# L- R% V. @
  28. class Quest (JQuest):( B7 }9 G# \, Y% K. |5 y
  29. ; O1 y" K1 I, f6 p7 B$ {
  30. def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)8 k, L8 W7 R4 K  g( N6 ?

  31. ( H( b6 _% Z! B2 c+ ?
  32. def onEvent (self,event,st):
    9 S* X- m1 i5 v2 g! u7 M! G6 ?
  33. id = st.getState()
    : [" C1 J7 C* N' e
  34. if id == CREATED : st.setState(STARTED)$ M, [/ w5 b& |2 b
  35. elif id == COMPLETED: pass( g4 \$ z6 E& y$ S2 ]
  36. elif id == STARTED : check(st)
    2 l0 e5 g" Y; ^
  37. return8 ?) c; O0 y) g3 u

  38. 7 Y- l, k% z; T4 z% s- _
  39. def onKill (self,npcId,st):
    ( [0 }, Y6 ]& ^9 j( A) {
  40. if npcId == KELTIR_NPC_ID:
    ! s+ w3 M2 Q  `, e$ T4 W% w- f4 V
  41. n = getCount(st)6 ~3 D4 ~* m# ]! M7 |+ h+ |
  42. if n == 0:
    ) ^3 e7 G, V6 s& Z4 e. J5 t1 V
  43. if st.get('chat0') == None :
    1 x3 n' k& Z$ j: X7 u
  44. st.set("chat0", "true")
    + j1 X& K# k/ V3 x2 o0 @) z
  45. return "Chat0.htm"5 u+ w* ?  Z4 B; H+ A: A  z
  46. elif n == 1:
    5 m. {! j( }) u
  47. if st.get('chat1') == None :$ y' k' j" X5 ?/ e  @
  48. st.set("chat1", "true")! M" g0 u6 d  L# o. l+ o1 F0 v, c
  49. return "Chat1.htm"( s% z2 _9 \6 G5 c* g
  50. elif n >= 4:; `6 Z! M' d% S
  51. return "Chat4.htm"
    % k2 }* J9 B* e; v2 I$ z: \! }% U
  52. return "Collect "+str(n)+" of 4 fangs"' u$ t% w: q" \) r  y, U
  53. return
    * o& s9 q/ o% l4 `! `" a
  54. 6 B9 i2 ?" J; \! h
  55. QUEST    = Quest(201, "Tutorial", "Tutorial quest")
    8 p# M& H6 Y% h. Y
  56. CREATED = State('Start',    QUEST)% Y, c# w  s; o' Q# E
  57. STARTED = State('Started', QUEST)/ }4 F* B' j6 J5 \2 F
  58. COMPLETED = State('Completed', QUEST)- @; L9 J9 P$ L" l

  59. ; @7 A7 N5 _) _. |
  60. QUEST.setInitialState(CREATED)
    9 O% Z8 u. J2 g3 O+ J. F) p
  61. QUEST.addStartNpc(7056)
    ! M! U8 T4 [, b6 U/ F
  62. QUEST.addStartNpc(7012)
    ( {7 \0 K$ d9 D( k5 x6 Z6 x
  63. QUEST.addStartNpc(7009)7 Y0 ?% N& P' F  G% ^, ?
  64. QUEST.addStartNpc(7011)
    4 T, i. Z% N0 l

  65. ! U% p5 c$ e+ \* N/ l% ?( M5 g: ^
  66. STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
    ' l( }' B7 k3 Y8 G' @
  67. STARTED.addKillId(KELTIR_NPC_ID)' o" D* L4 `& i3 f2 P, I
  68. STARTED.addTalkId(7056)
    - b, C. M, F- B  R6 O8 c0 y/ p7 C7 M; h
  69. STARTED.addTalkI d(7012)5 P, u; c0 w: N4 [$ U% S
  70. STARTED.addTalkId(7009)
    # m4 h' e# p  i9 A5 e
  71. STARTED.addTalkId(7011)
Скопировать код
/ ~0 B& ]2 l4 D" N" z3 t# j

2 {* N( j7 \" F& E, t2 C
Чтобы ответить, вам надо авторизироваться в системе Вход | Зарегистрироваться

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

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

638638758

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

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

admin@artace.ru Онлайн

QR-код

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