Top.Mail.Ru

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

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

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

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

x
Хроники        Interlude
0 p" W/ W% k# v2 R! u* k1 i5 zСборка        L2j
& Z5 w8 |" O& jОбратите внимание: в файле htm стартового NCP обязательно должна быть ссылка на квест:$ K. ^7 E' Z1 Z& T' s9 B, H
  1. STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код
Для этого квеста больше ничего не надо. Все необходимое для корректной работы квеста уже добавили. Вот полный текст квеста:$ X" I6 H3 n4 `! b, F

" i% E7 @/ x* ]: C1 I
  1. if getCount(st) >= 4 :- e% F" T- R& f7 z- o# _1 H
  2. completed(st)
    ! M# G- Q% b3 m# J+ C! z" D
  3.   return
    $ n: t+ j3 U5 q9 m/ q9 y

  4. % w) `9 D# P& \4 R5 n) L
  5. class Quest (JQuest):0 g4 a! Q- n2 `4 V! o0 Y0 S+ s
  6.   def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)
    & F1 X( S" n8 Y0 W; K9 A9 c( N
  7.   def onEvent (self,event,st):* L9 O" w) t' }& I: ]
  8. id = st.getState()
    % ]3 {* y1 Z' |# s
  9. if   id == CREATED  : st.setState(STARTED)% l0 M  ~8 _0 n" m; G1 f
  10. elif id == COMPLETED: pass
    ; n! ?8 N* w% @6 p
  11. elif id == STARTED  : check(st)
    ; S0 B2 T% u; y; x) R/ O6 q( m
  12. return
    / d" L. A% [* `* l% ^- f  o

  13. ' M4 _+ K7 N+ m+ x" S( `& `
  14. QUEST     = Quest(201,"Tutorial", "Tutorial quest")
    ; e+ [3 f2 [3 u1 h# T2 ~
  15. CREATED   = State('Start',     QUEST)
    " P0 d4 M# \& t1 C; d
  16. STARTED   = State('Started',   QUEST)
      y9 k6 [* B1 f- K4 f( _
  17. COMPLETED = State('Completed', QUEST)
    ' N2 Q0 ?; ^- P8 r; `
  18. 4 c3 K. @& f, }  O
  19. QUEST.setInitialState(CREATED)( X+ {3 O" A1 Y% A& q4 h
  20. QUEST.addStartNpc(7056)% l* E' A9 x0 T& ]4 u) i7 _
  21. STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код
Теперь рассмотрим, как это работает.
! ?/ s/ C5 E. Q: R0 Q( u; ]Игрок подходит к начальному NCP (в данном случае 7056), нажимает на «Quest». Квест будет создан и состояние квеста перейдет к CREATED и игроку будет показана страничка Start.htm с описанием квеста. Тогда метод onEvent, поле открытия странички Start.htm переведет состояние квеста в STARTED и игроку будет показана страничка Started.htm, где будет опсание того, как найти keltirs и .т.д.& j# l6 z6 t- l  Z8 p
/ H- O8 [# b/ x" {$ B
1 x' f- h1 O- D' V
При состоянии STARTED будет зарегистрирован дроп «fangs» при убийстве keltirs. Игрок может вернуться к стартовому NCP и спросить о квесте – метод onEvent будет вызван снова. Если у игрока не хватает необходимого количества предметов, то метод check() не переведет квест в следующее состояние и Started.htm будет показана снова. Но если игрок собрал необходимее количество предметов (в данном случае 4 клыка), то метод check() вызовет метод completed() который переведет квест в новое состояние COMPLETED, заберет все клыки, даст карту мира, т.к. это награда за квест, покажет Completed.htm и завершит квест.- _4 I' y: Y/ w) x: {6 \* D4 K

0 G& Q2 D$ a' d4 B' @. c; s. N3 D
" ^) O* ]- q0 z& o* ~, N$ C
Теперь давайте сделаем наш квест более похожим на то, что он должен из себя представлять.
% t& q% g* Y- b( ?# L" TПрежде всего у нас есть 3 метода для объявления их в Яве – onTalk, onKill и onEvent. Если методы onTalk и onKill не объявлены, то за них все будет делать метод onEvent, т.е. определять квестовых монстров и вызывать диалоги NCP. Есть примечание, методы onTalk и onKill будут вызывать только диалоги с NCP в зависимости от текущего состояния квеста. Метод onKill будет вызываться только тогда, когда мы убиваем квестового монстра.2 c+ r% ?2 ]" K  ~
" S) s# v1 ?' S3 X7 V
% t7 q% l7 m5 a6 l, l6 N& i  E
Давайте рассмотрим как вызывается метод onKill при убийстве keltir в состоянии квеста STARTED:
9 w9 {: O; l' P, e5 g# t! ~
  1. STARTED.addKillId(KELTIR_NPC_ID)
Скопировать код
и метод onKill в классе Quest:# o5 ]  U- s5 A$ T
" G- Z3 h/ T  T. t7 F! ]
  1. class Quest (JQuest):, C( p' t' f9 D6 ~5 \
  2.   ...
    ) a. _; ]5 Y: q- W$ B
  3.   def onKill (self,npcId,st):% E% {% N' S1 J0 }1 I
  4. if npcId == KELTIR_NPC_ID:' q9 Z4 F% Y2 ]% S
  5.    n = getCount(st)
    7 Z1 F& L% z' r* h: O1 b" j
  6.    if   n == 0:, W& ~' p6 u* e1 H) Y+ x
  7.        return "Chat0.htm"
    4 {6 C. `. J0 A$ `3 l3 M6 {
  8.    elif n == 1:6 X. B5 {5 {1 J- A8 J2 z* ^7 Q% k8 c
  9.        return "Chat1.htm"4 L/ q- u4 \" H# s$ J  P* D& l# I
  10.    elif n >= 4:
      {% V& R( h) C- y8 v
  11.        return "Chat4.htm"# v6 t( ]2 s0 h8 `
  12.    return "Collected "+str(n)+" of 4 fangs"9 n! p5 o2 B* J6 B/ ?! Z& L
  13. return
Скопировать код
Метод onKill (а так же метод onTalk) имеет следующие параметры:5 n9 l- M; I0 P' j8 g" O$ ~

% z& i+ G9 I6 R! G9 \% l1 m

3 e4 v, ]2 r" Y  n. }• self – квест
2 e7 L4 @1 E* M3 ^. ~• npcId – ID NCP, которого мы должны убивать (если это метод onTalk, то ID того NCP, с которым мы должны поговорить).1 C2 k0 `9 k  F' l- K4 a5 B' m& {
• st – текущее состояние игрока.
+ E1 f4 x$ Q1 Y9 O
* C8 r1 ~8 m2 v. u& ?4 c
* u$ Q! q* }+ ]: R0 u+ S9 z" q( P8 G5 e/ J
В этом методе мы проверяем и отмечаем, является ли убитый NCP keltir’ом. В основном эта проверка не нужна, т.к. у нас только KELTIR_NPC_ID.0 w" s* ~$ r% o% M' S
) S' b% V& R2 l* o# q6 E5 l
- J+ V, Z: _5 V' n" X6 @
Затем проверяем количество предметов (в данном случае количество клыков), и если их вообще нет, то возвращаем строку "Chat0.htm", если только один предмет, то возвращаем строку "Chat1.htm", если же предметов 4 или больше, то "Chat4.htm". Если строка возвращена из методов onEvent, onKill или onTalk, то сервер покажет соответствующие htm. В Chat0.htm может иметь следующий текст: «Вы не имеете ни одного клыка, возвращайтесь позже, когда соберете 4 штуки и бла, бла, бла…», в Chat1.htm может быть следующий текст: «У Вас всего 1 клык, по этому соберите еще…». В Chat4.htm – «Вы собрали необходимое количество предметов, возвращайтесь к вашему тренеру, что бы завершить квест…»
+ L2 s5 S- I* w" h4 p' S" y/ n  h2 J8 _, T7 B( T: V0 A( I, T
9 b- b' h% Z& }% E
Примечание: если в строка return начинается с "<html>", то будет показана страничка html с текстом, который стоит далее. Так вместо:& g9 f4 a3 |+ c# s7 ^+ ]
return "Chat4.htm"* @6 a4 p3 U8 ~% e( a! F
0 d. T( `0 K5 r* r1 p8 @9 }

2 P, J+ b6 \8 sможно поставить:
6 x: w) G& V4 V7 M' {2 D
  1. return "<html><body>Return to your trainer to complete the quest</body></html>"
Скопировать код
Так же если строка заканчивается без .htm или в начале нет <html>, то текст будет выведен, как системное сообщение в окне чата. В нашем случае мы сделаем так, что бы при каждом убийстве keltik выводилось системное сообщение: «Собрано N из 4-х клыков».1 E" c: X' F1 U' t* l9 t9 w

/ g  {& Z. y0 z( Y( |% e

* k/ g0 A% Q6 b+ p% \8 nНаш код для onKill имеет один недостаток. Он будет постоянно показывать Chat0.htm, Chat1.htm и Chat4.htm, нам же необходимо, что бы Chat0.htm и Chat1.htm показывались только один раз. Как нам это сделать? С помощью переменных.! G9 Z% H7 q$ Q+ |
' A/ H. V+ J; S# f
. t' o3 L: b# L( e
В каждом квесте строки могут храниться с помощью переменных. Эти переменные сохраняются в Вашей БД. В каждом методе мы можем назначить, прочитать и удалить переменные. Давайте изменим метод onKill, так что бы каждый диалог вызывался только один раз.* h/ Z. l& n, \9 |
  1. def onKill (self,npcId,st):: K9 g/ s5 L! p/ ?! S2 d
  2. if npcId == KELTIR_NPC_ID:
    5 B. b) g) O' u% z: K/ m% a
  3. n = getCount(st)8 Z/ v: E0 d% K9 d
  4. if n == 0:+ C5 A( B7 `, W
  5. if st.get('chat0') == None :
    / o% m7 G% c3 D: K5 \  Z$ T( |( L; \
  6. st.set("chat0", "true")1 i1 d9 r* p- N
  7. return "Chat0.htm"! Q0 h% y1 A, h+ ]# a
  8. elif n == 1:
    ( x3 C7 i- r' p
  9. if st.get('chat1') == None :  X! U" a1 ?3 g8 ]* F
  10. st.set("chat1", "true")4 _  q1 @- H4 T$ t5 X3 Z
  11. return "Chat1.htm"! n& A* C9 x9 E; H2 e4 m5 H
  12. elif n >= 4:1 r+ H, X4 D0 g' ]0 v0 t
  13. return "Chat4.htm"
    3 D0 z9 J- N9 u- J- K! s
  14. return "Collected "+str(n)+" of 4 fangs"* |! h$ ?; P2 T) F# r$ r
  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 }$ }( ]* L1 {

$ p2 \! j- _% M# V

4 D: S8 H1 `2 i3 y9 B% c- AВот конечный рабочий вариант квеста:
( L2 _3 ~9 n! f
  1. import sys1 U2 Y8 g9 b* A# j1 s: D) q
  2. from net.sf.l2j.gameserver.model.quest import State8 {* h9 s, [. D  X
  3. from net.sf.l2j.gameserver.model.quest import QuestState
    6 U1 S! s# D% o1 m8 D
  4. from net.sf.l2j.gameserver.model.quest.jython import QuestJython as JQuest
    ! {$ l6 o( I( z, ~( a1 ~
  5. & }; X9 M/ s- ~, `/ ~5 W* ^
  6. KELTIR_NPC_ID = 12082* w$ b. T# z9 Y# f* [  U) j
  7. FANGS_ITEM_ID = 1859+ @& K, f- `: [$ b+ Q4 m1 p, ]
  8. DROP_RATE    = 500000" C7 J) m0 O" x! Y# j
  9. ! z' o: m- J0 P1 \9 U. |
  10. WORLD_MAP_ITEM_ID = 1665
    ! E5 f9 @( M' L" ^, x% X

  11. 1 l0 a5 B! J  M! X% s' v
  12. def getCount(st) :
    * w. S! @+ Z" e$ q" e& K8 @
  13. return st.getQuestItemsCount(FANGS_ITEM_ID)& ]6 y" m# q: a! Q* H( r2 d( ]) S

  14. ) F& t* k6 n+ a1 B' n' R
  15. def completed(st) :4 i6 r" t! M# x: E: w! e1 y) v
  16. st.setState(COMPLETED)# H& Z1 b6 H$ t& k1 o
  17. st.clearQuestDrops()
    7 P0 a4 ]  [$ X3 `/ u2 b4 u
  18. st.takeItems(FANGS_ITEM_ID,-1)7 @0 D  Y* i- j* ]7 I
  19. st.giveItems(WORLD_MAP_ITEM_ID,1)
    ) K. u- `3 `# Z  v( E; _+ s
  20. st.exitQuest(False)
    7 C# z+ P- \/ i# ?! h2 U
  21. return( u5 j  W  t% c, L" G
  22. : [# i$ Q4 u  V! n9 A7 X- E' [
  23. def check(st) :
    & S1 }& n/ e# Z6 J; U9 W
  24. if getCount(st) >= 4 :
    7 L- t3 ?" a5 u4 _  J' J
  25. completed(st); `  H$ h7 t4 @: D
  26. return# L2 h$ L* b  @' X  s

  27. & T5 r; _" H4 v# _# I
  28. class Quest (JQuest):
    8 Z6 T3 \5 I( }% R4 y! M
  29. ' n8 V4 H- R, n4 k6 B  \# z, j# c
  30. def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)
    % M+ K: A* k7 k5 g3 L" r" k
  31. 0 B. y, T. d& I/ Y9 j: f. z
  32. def onEvent (self,event,st):/ {/ W" n( q% S' f" @; ^3 S4 d
  33. id = st.getState(). b% I% W8 C& W& P. P; _' }. m  Y
  34. if id == CREATED : st.setState(STARTED)
    - y' x' j! `  [# m7 V* ]
  35. elif id == COMPLETED: pass
    7 w* W$ U% c5 C' l
  36. elif id == STARTED : check(st)
    ; o7 o# w; n8 @; t- g0 L1 ]
  37. return; m6 O) D2 F, |

  38. , s5 |' ]2 Z2 Y$ N1 [" M
  39. def onKill (self,npcId,st):% L' X- Y, f" b% |& W8 @/ `" T% v
  40. if npcId == KELTIR_NPC_ID:
    & a7 w& v! d) s
  41. n = getCount(st): a: H6 c. w; E7 ?
  42. if n == 0:
    & o: L; m, Y8 ?0 w* u/ l; x
  43. if st.get('chat0') == None :
    : }/ s% x5 E; A3 i6 p) n9 l: g
  44. st.set("chat0", "true")
    6 T1 c$ U! }8 S' H2 K6 L
  45. return "Chat0.htm"
    & y4 L- t$ Z1 t! G7 }2 e  A; S
  46. elif n == 1:# F6 z$ _; ]1 L6 M3 G6 C
  47. if st.get('chat1') == None :; P; Z+ U* M# F9 u
  48. st.set("chat1", "true")
    3 s2 B1 P, A' r% ]& \) ~
  49. return "Chat1.htm"
    4 {7 u* ~4 t, G+ d9 q2 k( j) o. S2 k  A! G
  50. elif n >= 4:. E1 k+ q7 ~" _" S  \, _
  51. return "Chat4.htm"1 O* S: _* S2 N' g/ O9 f9 {
  52. return "Collect "+str(n)+" of 4 fangs"
    2 R( ~4 p6 Q2 C$ S+ a' C% _% T- M
  53. return9 K  f& ?- O0 F7 w! a6 h( Q
  54. & ]) T% r$ T8 n3 P5 k: @$ C0 ?
  55. QUEST    = Quest(201, "Tutorial", "Tutorial quest")
    # j/ x/ v- V) f, V' _
  56. CREATED = State('Start',    QUEST)
    + c0 `# F6 n8 n% W  U: r" R
  57. STARTED = State('Started', QUEST)0 z' H5 T) ?9 q9 d2 W% Q) d+ J8 i
  58. COMPLETED = State('Completed', QUEST)
    " S* Y* N+ D7 m
  59. 9 O! m2 Y% F" t1 B
  60. QUEST.setInitialState(CREATED)8 C2 C. h: p; x+ A& E8 [
  61. QUEST.addStartNpc(7056)1 j$ A8 C$ U* Z4 K
  62. QUEST.addStartNpc(7012)
    4 [/ m7 o$ y7 |+ q; ~- g8 B
  63. QUEST.addStartNpc(7009)& [" s1 }6 B8 ~
  64. QUEST.addStartNpc(7011)# M* _; J. \/ E
  65. # @* m$ y6 q: w/ T) y0 K  r8 t
  66. STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE): f; }8 s7 g1 ~( w& j" \" k0 o: L
  67. STARTED.addKillId(KELTIR_NPC_ID)
    3 K% H9 ^: \3 S2 J% k8 k
  68. STARTED.addTalkId(7056)% s. ?5 \# n( C9 |8 u' Y5 o7 Y/ E
  69. STARTED.addTalkI d(7012)6 f" |0 N% K% C6 a" M0 s
  70. STARTED.addTalkId(7009)
    1 l, ~9 i: w+ P5 n
  71. STARTED.addTalkId(7011)
Скопировать код
: D, W8 y6 D! f* y- G- S

0 }! E# Q# T+ y2 `0 t
Чтобы ответить, вам надо авторизироваться в системе Вход | Зарегистрироваться

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

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

638638758

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

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

admin@artace.ru Онлайн

QR-код

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