Top.Mail.Ru

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

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

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

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

x
Хроники        Interlude
: H2 C' ^: ^( w0 }Сборка        L2j9 u4 U5 h2 o& b# S
Обратите внимание: в файле htm стартового NCP обязательно должна быть ссылка на квест:. [1 V. T' n1 c- m5 j6 e
  1. STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код
Для этого квеста больше ничего не надо. Все необходимое для корректной работы квеста уже добавили. Вот полный текст квеста:2 C3 V1 h; F0 v: H- {6 G. f; X3 a

- g9 y' ]+ {3 D! `
  1. if getCount(st) >= 4 :9 M  X$ a. c2 \/ i8 U* {* ^& Z
  2. completed(st)
    3 k1 X: A: h0 v1 s. i: J4 a
  3.   return
    ' {! ^' _+ ^4 n) r( Z# b

  4. 7 l& v7 B; r# a. F
  5. class Quest (JQuest):7 F8 `, q# D$ B9 a
  6.   def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)
    / o) g* G2 F" G. l4 Q' u
  7.   def onEvent (self,event,st):: q/ S( M3 k- p; ^% n: M3 }- `" F/ M
  8. id = st.getState()
    ' i+ X; p$ t2 O4 {3 `% d
  9. if   id == CREATED  : st.setState(STARTED)5 T4 |: a" ~( e# T
  10. elif id == COMPLETED: pass
    7 z7 m7 i% G$ ?' |
  11. elif id == STARTED  : check(st)
    6 B  `8 A, N1 p* x4 W' X) Y0 c1 ]
  12. return
    # h( g& U  {" s6 ~) i
  13. ' Z1 E3 f7 X  Y1 l2 A3 Y1 q8 M' Z
  14. QUEST     = Quest(201,"Tutorial", "Tutorial quest"), J. C& K* K2 S, [# t$ y
  15. CREATED   = State('Start',     QUEST)
    . l. D& N* J/ @- [4 M: A
  16. STARTED   = State('Started',   QUEST). Y6 s% S8 o9 ~3 [" H
  17. COMPLETED = State('Completed', QUEST)
    1 Q1 G+ t9 z; O: y0 ]# Y( `- B: p
  18. % X. x+ @/ a3 L5 ]
  19. QUEST.setInitialState(CREATED)! Q: Z9 D- j! k1 J( w/ q
  20. QUEST.addStartNpc(7056)
    ; p0 b. z6 S' u
  21. STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код
Теперь рассмотрим, как это работает.. ~, a0 L: Z  J+ B( d6 T/ V6 C+ |8 L
Игрок подходит к начальному NCP (в данном случае 7056), нажимает на «Quest». Квест будет создан и состояние квеста перейдет к CREATED и игроку будет показана страничка Start.htm с описанием квеста. Тогда метод onEvent, поле открытия странички Start.htm переведет состояние квеста в STARTED и игроку будет показана страничка Started.htm, где будет опсание того, как найти keltirs и .т.д.
8 @4 `- L, Z1 p$ P  t1 M
! q+ c$ v, C" V

0 e" Q3 b+ S! l, E  VПри состоянии STARTED будет зарегистрирован дроп «fangs» при убийстве keltirs. Игрок может вернуться к стартовому NCP и спросить о квесте – метод onEvent будет вызван снова. Если у игрока не хватает необходимого количества предметов, то метод check() не переведет квест в следующее состояние и Started.htm будет показана снова. Но если игрок собрал необходимее количество предметов (в данном случае 4 клыка), то метод check() вызовет метод completed() который переведет квест в новое состояние COMPLETED, заберет все клыки, даст карту мира, т.к. это награда за квест, покажет Completed.htm и завершит квест.& V8 V  g- t) X( W7 g& k; `: F( f

+ s% O* |- n1 ~. `

: K; U1 {% k8 ^Теперь давайте сделаем наш квест более похожим на то, что он должен из себя представлять.
$ ~% ~& ?6 }6 K4 k% ~6 e6 MПрежде всего у нас есть 3 метода для объявления их в Яве – onTalk, onKill и onEvent. Если методы onTalk и onKill не объявлены, то за них все будет делать метод onEvent, т.е. определять квестовых монстров и вызывать диалоги NCP. Есть примечание, методы onTalk и onKill будут вызывать только диалоги с NCP в зависимости от текущего состояния квеста. Метод onKill будет вызываться только тогда, когда мы убиваем квестового монстра.
  T  ^; u2 {/ s- g
, t; N: u" N( X& R& D% W. O

. F. v  a; n( c, t1 P8 ]: ~Давайте рассмотрим как вызывается метод onKill при убийстве keltir в состоянии квеста STARTED:# C) M+ e7 l: N7 h; L! @: e) x3 l) S
  1. STARTED.addKillId(KELTIR_NPC_ID)
Скопировать код
и метод onKill в классе Quest:
' F- c% Y( T  Z' W$ y5 \
. R+ h+ V! |# c, V  K: y
  1. class Quest (JQuest):
    5 A, e, j2 R. z: N" O
  2.   ...
    6 p7 Y5 c) J( P4 Y
  3.   def onKill (self,npcId,st):" r$ w6 |6 }- x$ ?/ N5 g
  4. if npcId == KELTIR_NPC_ID:+ ~5 P8 q2 w. _, j" p
  5.    n = getCount(st)
    ) ?% j5 W, ~$ i8 Y( t! n6 w' A0 I$ U
  6.    if   n == 0:5 l7 u: A& {0 b" {9 z
  7.        return "Chat0.htm"$ F1 v( L+ ^  @( [
  8.    elif n == 1:7 [+ l: H- V  C5 ?% ^, J4 S# ]
  9.        return "Chat1.htm"' {+ {+ H; a  \: D
  10.    elif n >= 4:
    ! v9 M# h; d& c3 Z/ ?- K
  11.        return "Chat4.htm"
    0 X4 B" _  D& ?+ K( o- s$ e; I% z
  12.    return "Collected "+str(n)+" of 4 fangs"+ G; i( e8 {, O2 q% {2 \( g
  13. return
Скопировать код
Метод onKill (а так же метод onTalk) имеет следующие параметры:" V/ A! V9 b4 p
8 o: K+ e1 M: ^, ^# X, @  |9 [
. u6 ~8 o2 S8 x' H0 U- Y
• self – квест. D4 Y2 y+ g' }0 G
• npcId – ID NCP, которого мы должны убивать (если это метод onTalk, то ID того NCP, с которым мы должны поговорить).
% p2 H9 O! S9 L( z! f• st – текущее состояние игрока.
# J) i% C$ a6 r7 Z
2 R4 M8 A3 W/ @$ O( A1 S, ?
, h& `& o: {; g& y  [0 r( y- L
В этом методе мы проверяем и отмечаем, является ли убитый NCP keltir’ом. В основном эта проверка не нужна, т.к. у нас только KELTIR_NPC_ID.) Z2 R+ D3 V! j0 v$ o( F: _) \
" Q' s+ n3 C# |- c; p
0 i1 |* m, N. ~! s2 A
Затем проверяем количество предметов (в данном случае количество клыков), и если их вообще нет, то возвращаем строку "Chat0.htm", если только один предмет, то возвращаем строку "Chat1.htm", если же предметов 4 или больше, то "Chat4.htm". Если строка возвращена из методов onEvent, onKill или onTalk, то сервер покажет соответствующие htm. В Chat0.htm может иметь следующий текст: «Вы не имеете ни одного клыка, возвращайтесь позже, когда соберете 4 штуки и бла, бла, бла…», в Chat1.htm может быть следующий текст: «У Вас всего 1 клык, по этому соберите еще…». В Chat4.htm – «Вы собрали необходимое количество предметов, возвращайтесь к вашему тренеру, что бы завершить квест…»6 ~; _& p! T) ~% Q% o# Z2 U
( J5 D6 n* R: C
  l$ f. t4 a7 |8 D  Y$ P
Примечание: если в строка return начинается с "<html>", то будет показана страничка html с текстом, который стоит далее. Так вместо:
- r9 e1 A8 ^" k1 Qreturn "Chat4.htm"" X" \$ D" X7 S" a

! y) d* K, h) Z# b

. B6 n6 o) R$ [; C, x6 }9 Vможно поставить:$ o% |# r  t( m- M! v5 a
  1. return "<html><body>Return to your trainer to complete the quest</body></html>"
Скопировать код
Так же если строка заканчивается без .htm или в начале нет <html>, то текст будет выведен, как системное сообщение в окне чата. В нашем случае мы сделаем так, что бы при каждом убийстве keltik выводилось системное сообщение: «Собрано N из 4-х клыков».( A1 Y* N8 s+ Y

! Q, u% _  g+ l' \

) {( G% O9 T  N2 JНаш код для onKill имеет один недостаток. Он будет постоянно показывать Chat0.htm, Chat1.htm и Chat4.htm, нам же необходимо, что бы Chat0.htm и Chat1.htm показывались только один раз. Как нам это сделать? С помощью переменных.
" s: x5 F' _+ x* B
! g; o* z# X) W) i/ d" P
" S; U7 G# C0 X+ x) q# D* c( ]. d
В каждом квесте строки могут храниться с помощью переменных. Эти переменные сохраняются в Вашей БД. В каждом методе мы можем назначить, прочитать и удалить переменные. Давайте изменим метод onKill, так что бы каждый диалог вызывался только один раз.( E9 I2 O- T, h$ }9 `- O1 X
  1. def onKill (self,npcId,st):
    : \1 |" d+ p7 P- @
  2. if npcId == KELTIR_NPC_ID:( C  A, O  V6 F2 e& o! s
  3. n = getCount(st)4 p2 a7 G6 Y4 Q# B3 E
  4. if n == 0:
    - d/ D" V3 Q0 z" P; m! u6 e
  5. if st.get('chat0') == None :3 q) I) i. _- j" d
  6. st.set("chat0", "true")
    8 Z4 C2 d! o' o. q# v* ~
  7. return "Chat0.htm"6 u/ \6 p1 v1 o- ^1 i  b* v9 o
  8. elif n == 1:$ ?- A% G- h, A9 U5 v2 M, V
  9. if st.get('chat1') == None :
    1 a5 ?  C# Q! w; h
  10. st.set("chat1", "true"); V3 [: }6 a8 W2 x- S
  11. return "Chat1.htm"
    - t/ A. {2 {4 `
  12. elif n >= 4:- B0 p# I7 `, r0 R; K
  13. return "Chat4.htm"
    9 q- V' |7 V$ F' c' S& Z
  14. return "Collected "+str(n)+" of 4 fangs") V8 o* Y# p6 e, ]8 `
  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.
7 ]) n3 @, d3 u
  S$ ?8 N2 e& v2 Y$ \
) z. _6 q7 E7 f2 @. f' [
Вот конечный рабочий вариант квеста:  z9 X, s- r! R) \
  1. import sys
    8 O9 Y* s8 Z: a  f4 b; h7 e# ]: U/ N
  2. from net.sf.l2j.gameserver.model.quest import State+ r6 S# a0 v: ]* i' M. v
  3. from net.sf.l2j.gameserver.model.quest import QuestState
    8 p6 i( J) V& C0 Q! D
  4. from net.sf.l2j.gameserver.model.quest.jython import QuestJython as JQuest+ ~5 k1 ^2 S9 J) \9 P7 O% G

  5. # t6 L* G0 |, D
  6. KELTIR_NPC_ID = 120823 N. l; _6 z8 }
  7. FANGS_ITEM_ID = 1859
      f6 b- N3 y' M2 Y
  8. DROP_RATE    = 500000
    2 v( ~3 g8 b) m' i( {
  9. 4 I7 ^' v, @$ P0 O
  10. WORLD_MAP_ITEM_ID = 1665
      K: Y: x$ }! n' u5 R
  11.   }7 \" Q4 ]) E7 I/ ]
  12. def getCount(st) :
    0 Y2 u+ C- P' I5 O
  13. return st.getQuestItemsCount(FANGS_ITEM_ID)
    2 ^% _: e$ h2 i; L5 P+ d) A2 j

  14. 4 z' R  r, v( s5 \
  15. def completed(st) :
    ' Z6 ^9 Y) M3 e5 d9 ~' t
  16. st.setState(COMPLETED)
    * Y: H: V, s. \& w, d1 J
  17. st.clearQuestDrops(), \6 W4 n/ X0 O+ R6 v
  18. st.takeItems(FANGS_ITEM_ID,-1)
    0 X) z0 x# [7 w( X
  19. st.giveItems(WORLD_MAP_ITEM_ID,1)
    8 J' n5 A/ [" ]4 Y; _8 w+ `2 M2 U
  20. st.exitQuest(False), [1 ~7 D4 J0 R6 ]& E# q
  21. return& }+ J! \- P2 k5 J

  22. # {2 }; r( @2 B1 _/ J5 n5 d9 M3 @
  23. def check(st) :
    " j* y5 M* F; B6 O  e: d2 F/ i
  24. if getCount(st) >= 4 :' H/ r" u- B$ k1 `# ^8 O1 ]
  25. completed(st)
    , V8 R) Y6 Q0 b3 i  Z& B) N% E# P& h
  26. return2 e$ S( d6 R" p4 g  O

  27. 0 H/ }" t  d& d  z' S
  28. class Quest (JQuest):" Q4 I8 M. L$ D5 W" o
  29. 6 m" L$ h$ V. P+ m
  30. def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)! y6 D- E5 t8 `2 s$ g6 w$ F

  31. 5 V" N2 M+ g! b( ~
  32. def onEvent (self,event,st):
    1 }5 f3 G) g* v9 I) T' C
  33. id = st.getState()
    3 S+ S+ J+ S4 F; \+ O
  34. if id == CREATED : st.setState(STARTED)! L0 ?' k' I5 N$ f- S
  35. elif id == COMPLETED: pass
    2 N- C( L/ d) C% B" k. H
  36. elif id == STARTED : check(st)$ g% u( S9 A  M  `
  37. return  z3 i1 g/ f2 y. N% ~* k
  38. % B0 l5 @! g5 B/ K4 x2 U
  39. def onKill (self,npcId,st):+ y  l; \2 a  t; q
  40. if npcId == KELTIR_NPC_ID:
    % T" l8 @* @; g/ Q- T2 x- c; W' W
  41. n = getCount(st)! L2 u8 n, ~1 F
  42. if n == 0:, {' N  u/ k4 K$ i# w4 B* d
  43. if st.get('chat0') == None :5 ]1 p% W2 O  V/ S: A& o! P
  44. st.set("chat0", "true")
    4 G! K$ O1 }1 X
  45. return "Chat0.htm": ]2 a; h& O1 R2 d1 f
  46. elif n == 1:
    ( T2 x" q- H* b* Z# {! I
  47. if st.get('chat1') == None :" q/ A% n4 @$ N, n
  48. st.set("chat1", "true")4 K' _0 J" w: g6 v% Z
  49. return "Chat1.htm"
    - y& n7 L% F: L: _
  50. elif n >= 4:
    % n6 C! K# _6 u3 a3 v
  51. return "Chat4.htm"* y9 U8 ?) }4 q7 t' |4 b& o1 p
  52. return "Collect "+str(n)+" of 4 fangs"
    - V" y1 Q& K: S# X' m, Q) m- G
  53. return7 W2 [" L( S3 ]9 i' j) d1 c

  54. 4 J6 A2 `: ^- R% u
  55. QUEST    = Quest(201, "Tutorial", "Tutorial quest")9 ^" m- K% M* O) X" ?0 j/ E0 n- y3 T
  56. CREATED = State('Start',    QUEST)
    ' _, Q3 Z0 `! d; Q! E2 N7 i( M, v
  57. STARTED = State('Started', QUEST)1 D# {' }( w2 c, f
  58. COMPLETED = State('Completed', QUEST)  t. _- V' e4 J* f3 J

  59. 8 Z  D" M- ?. |0 L3 C1 D! u" a
  60. QUEST.setInitialState(CREATED)' D' w4 q8 {- V8 o6 s4 i
  61. QUEST.addStartNpc(7056)
    - r# H* E0 }( a8 X( y# P% K5 G
  62. QUEST.addStartNpc(7012)0 v; q4 |& l8 A3 z7 A' l% S+ |
  63. QUEST.addStartNpc(7009)
    8 }# [6 U: I' b# }9 N
  64. QUEST.addStartNpc(7011)
    * P! i% _. Q9 s

  65. / U! L) G1 Q. p% e
  66. STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE), C9 S' x" S8 r
  67. STARTED.addKillId(KELTIR_NPC_ID)- P; @8 P5 ^( E: O
  68. STARTED.addTalkId(7056)$ E& d2 H0 t6 N/ z, z( A
  69. STARTED.addTalkI d(7012). c- p+ U. |5 t* @) ?$ V9 L
  70. STARTED.addTalkId(7009)
    & ]4 S' M; ?; W" U0 R1 k
  71. STARTED.addTalkId(7011)
Скопировать код

+ k& D3 T4 q9 V/ p2 \% e$ E) G. D3 L9 p$ I/ i) Y3 c  C
Чтобы ответить, вам надо авторизироваться в системе Вход | Зарегистрироваться

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

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

638638758

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

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

admin@artace.ru Онлайн

QR-код

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