Top.Mail.Ru

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

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

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

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

x
Хроники        Interlude
5 W! V1 ^! u; B4 P2 m& I  z9 \/ SСборка        L2j
5 V* \. V+ G3 RОбратите внимание: в файле htm стартового NCP обязательно должна быть ссылка на квест:8 U; A- V) N# T5 ]6 q& R* j' _
  1. STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код
Для этого квеста больше ничего не надо. Все необходимое для корректной работы квеста уже добавили. Вот полный текст квеста:- z! N/ C& }0 x" W" b% K

+ s5 L' e5 a% m
  1. if getCount(st) >= 4 :
    . ]# X  l" U) P
  2. completed(st)3 x* B# ~% Y$ [. r( U8 Y8 U( _
  3.   return& \! h# N9 p' o8 M' a4 n% F* j# x

  4. : p- e7 R$ e) a
  5. class Quest (JQuest):6 A) T& I, ]5 v; Z, k- \6 K. ^! |
  6.   def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr); q# G5 F( Z0 P7 R
  7.   def onEvent (self,event,st):
    - ^* I/ P  M% K5 x( [0 ?
  8. id = st.getState()" [" `. ?6 h7 r: B6 w$ y
  9. if   id == CREATED  : st.setState(STARTED): Z9 q: B* f* y$ f
  10. elif id == COMPLETED: pass; A' S- v5 L. D- q, A( M
  11. elif id == STARTED  : check(st)# q/ M/ D( f0 [! B" q
  12. return2 R  \& z7 b$ u5 l
  13. $ B, c% U* ]2 B2 U$ E' p+ I
  14. QUEST     = Quest(201,"Tutorial", "Tutorial quest"); J# u1 G- M* {4 p, G  c3 _- Y0 n% O
  15. CREATED   = State('Start',     QUEST)- I6 w/ H/ }& S5 R9 e% k- E- r
  16. STARTED   = State('Started',   QUEST)
    % }& h' f# \* j
  17. COMPLETED = State('Completed', QUEST)
    " [7 b. x7 N6 X$ \

  18. ' a, y: I: M$ ~% Q( S' B
  19. QUEST.setInitialState(CREATED)
    8 y9 Q0 u% p$ v* p1 W
  20. QUEST.addStartNpc(7056)  s; ^5 [) O6 l3 f; H* t) w
  21. STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код
Теперь рассмотрим, как это работает.
/ U3 c; G) N1 oИгрок подходит к начальному NCP (в данном случае 7056), нажимает на «Quest». Квест будет создан и состояние квеста перейдет к CREATED и игроку будет показана страничка Start.htm с описанием квеста. Тогда метод onEvent, поле открытия странички Start.htm переведет состояние квеста в STARTED и игроку будет показана страничка Started.htm, где будет опсание того, как найти keltirs и .т.д.8 P; d3 D1 G( f2 h

9 h, h6 F; x. ~3 f

, t' g& Z+ w  s# ]( X! _При состоянии STARTED будет зарегистрирован дроп «fangs» при убийстве keltirs. Игрок может вернуться к стартовому NCP и спросить о квесте – метод onEvent будет вызван снова. Если у игрока не хватает необходимого количества предметов, то метод check() не переведет квест в следующее состояние и Started.htm будет показана снова. Но если игрок собрал необходимее количество предметов (в данном случае 4 клыка), то метод check() вызовет метод completed() который переведет квест в новое состояние COMPLETED, заберет все клыки, даст карту мира, т.к. это награда за квест, покажет Completed.htm и завершит квест.
  \& A8 q& s; t3 ^5 {& c6 P! L" ~7 i/ Y/ ]8 p
) S7 f; i6 b2 F, ^. k
Теперь давайте сделаем наш квест более похожим на то, что он должен из себя представлять.
( C4 P" [& u$ X, ?: m$ AПрежде всего у нас есть 3 метода для объявления их в Яве – onTalk, onKill и onEvent. Если методы onTalk и onKill не объявлены, то за них все будет делать метод onEvent, т.е. определять квестовых монстров и вызывать диалоги NCP. Есть примечание, методы onTalk и onKill будут вызывать только диалоги с NCP в зависимости от текущего состояния квеста. Метод onKill будет вызываться только тогда, когда мы убиваем квестового монстра.3 P+ I6 o9 B: {$ L8 [! Q
" m/ n" i8 B9 A* X

( J* C2 v" Y- H0 pДавайте рассмотрим как вызывается метод onKill при убийстве keltir в состоянии квеста STARTED:
, A; l) q7 N& I% d0 p
  1. STARTED.addKillId(KELTIR_NPC_ID)
Скопировать код
и метод onKill в классе Quest:
- z7 \; x1 Y0 X9 @4 _  T' `: k& y. R1 b7 h
  1. class Quest (JQuest):
    $ n  M& R0 h0 u$ S/ N# v9 r
  2.   ...
    ' I* T$ J$ t: V; Q, J
  3.   def onKill (self,npcId,st):1 C& F+ d$ c% Z5 f6 z6 _
  4. if npcId == KELTIR_NPC_ID:
    % e5 s; n3 T7 M  t
  5.    n = getCount(st)2 k2 v+ O7 a2 F2 \" K
  6.    if   n == 0:
    + [" ~& M0 i. t5 d* a3 a
  7.        return "Chat0.htm"- P, K: t* q; c4 r% Y. l
  8.    elif n == 1:
    / O+ R. O9 i! _: Z
  9.        return "Chat1.htm"
    7 K& N; l3 Y% S# R, h0 t4 g1 P
  10.    elif n >= 4:
    - P/ E# Q7 e0 ]+ w* X/ c' T2 D) y
  11.        return "Chat4.htm"
    ) a: P" H. H, x1 ~2 A4 q3 C
  12.    return "Collected "+str(n)+" of 4 fangs"
    3 j& x# G0 [# ]- l2 e' k4 x$ s
  13. return
Скопировать код
Метод onKill (а так же метод onTalk) имеет следующие параметры:
2 V& c0 j- t9 K, w2 f' Y" T. T2 {: O8 k1 L& ^
* E& V, ?1 u7 [
• self – квест
: b$ s; S+ b% i• npcId – ID NCP, которого мы должны убивать (если это метод onTalk, то ID того NCP, с которым мы должны поговорить).0 @, V* b% k+ d# s
• st – текущее состояние игрока.
* d! V2 `: R9 B  q" `% h: f: V
  R2 ~$ j, G/ P
; d0 L" n! I  G4 ]" P% A  Q7 p
В этом методе мы проверяем и отмечаем, является ли убитый NCP keltir’ом. В основном эта проверка не нужна, т.к. у нас только KELTIR_NPC_ID.
8 K" N0 t" I6 q0 D- M& g
5 G( @+ |, l  A8 m3 ?! [# b) b) P( q

( r1 ^4 B8 Z* K# \! U5 x4 ?Затем проверяем количество предметов (в данном случае количество клыков), и если их вообще нет, то возвращаем строку "Chat0.htm", если только один предмет, то возвращаем строку "Chat1.htm", если же предметов 4 или больше, то "Chat4.htm". Если строка возвращена из методов onEvent, onKill или onTalk, то сервер покажет соответствующие htm. В Chat0.htm может иметь следующий текст: «Вы не имеете ни одного клыка, возвращайтесь позже, когда соберете 4 штуки и бла, бла, бла…», в Chat1.htm может быть следующий текст: «У Вас всего 1 клык, по этому соберите еще…». В Chat4.htm – «Вы собрали необходимое количество предметов, возвращайтесь к вашему тренеру, что бы завершить квест…»
: ]4 O; x( w. T8 e( |' l
$ f& a3 [) H: U( u; K- g
$ h9 M% S. D4 G: L- [
Примечание: если в строка return начинается с "<html>", то будет показана страничка html с текстом, который стоит далее. Так вместо:
  f- u# _" d" ^1 ^, J& `0 Preturn "Chat4.htm"0 A1 M+ I. O* T

8 ?+ L2 d0 ]& W1 X* s7 f3 P

# G2 p, {  Z4 h4 Qможно поставить:
+ s. b; H1 k: w& V8 D; {
  1. return "<html><body>Return to your trainer to complete the quest</body></html>"
Скопировать код
Так же если строка заканчивается без .htm или в начале нет <html>, то текст будет выведен, как системное сообщение в окне чата. В нашем случае мы сделаем так, что бы при каждом убийстве keltik выводилось системное сообщение: «Собрано N из 4-х клыков».
+ V" a, @! ?) Z) h+ Y0 e; ~5 Q5 p2 L- [

/ x% j+ m* z5 _Наш код для onKill имеет один недостаток. Он будет постоянно показывать Chat0.htm, Chat1.htm и Chat4.htm, нам же необходимо, что бы Chat0.htm и Chat1.htm показывались только один раз. Как нам это сделать? С помощью переменных.
, ^5 k) w$ O2 ^# |. d5 @. X$ j& T) g7 ]/ N$ x
! }5 Z( w8 P' n4 F& I
В каждом квесте строки могут храниться с помощью переменных. Эти переменные сохраняются в Вашей БД. В каждом методе мы можем назначить, прочитать и удалить переменные. Давайте изменим метод onKill, так что бы каждый диалог вызывался только один раз.
9 l+ h0 M- k/ \
  1. def onKill (self,npcId,st):3 |7 V8 y/ n$ R- `# W3 P
  2. if npcId == KELTIR_NPC_ID:4 M+ _4 k' D( l% @7 T" X' [; Q, y
  3. n = getCount(st), m2 x2 B) ^0 v
  4. if n == 0:& V" z4 p- A2 Q* G
  5. if st.get('chat0') == None :
    ! Q) [+ |' @8 H/ Q( v, N" i0 k4 v
  6. st.set("chat0", "true")# t6 u- c- @% y4 _: a. D0 _- i
  7. return "Chat0.htm"
    6 ?2 p5 j' }6 w, j  U. }0 o; @2 V
  8. elif n == 1:7 k  h0 x1 f* H
  9. if st.get('chat1') == None :2 x6 I% f, q+ m3 T; o' p
  10. st.set("chat1", "true")5 j6 v) L, p& c, _8 u
  11. return "Chat1.htm"
    ' d  @# B$ q* F/ _4 ?. o' M
  12. elif n >= 4:6 `) Y+ J" B0 d  y7 c
  13. return "Chat4.htm"/ J0 \7 ^+ i/ |- M
  14. return "Collected "+str(n)+" of 4 fangs". i0 ]! ~; j4 ]2 K% x, q
  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.+ g, A' s/ t! [9 F
" X2 m/ I. `# U
. c& n- W9 ^( g
Вот конечный рабочий вариант квеста:
2 `/ s) S4 V1 _3 m  ^- D* E) e/ [* |
  1. import sys& o6 X3 p! B; i- [9 N. A; m
  2. from net.sf.l2j.gameserver.model.quest import State
    9 Q/ t$ J  Q9 j! i
  3. from net.sf.l2j.gameserver.model.quest import QuestState
    : z; T$ P$ Z9 q' f
  4. from net.sf.l2j.gameserver.model.quest.jython import QuestJython as JQuest
    3 q& O8 r; Z/ ?. n5 ~
  5. / s( s4 M4 K$ J6 [4 Z
  6. KELTIR_NPC_ID = 12082! |8 u8 |6 j. v2 e9 |
  7. FANGS_ITEM_ID = 1859
    % G! p+ m- g3 X+ a/ _
  8. DROP_RATE    = 500000+ S) [: P7 X6 s4 a1 C

  9. 9 A; B1 F1 ~$ Q* u0 o& T" s, [
  10. WORLD_MAP_ITEM_ID = 1665
    7 ^* A) U) R7 R9 A6 ?- x

  11. / k3 l1 Y( E+ |  _; t8 ~
  12. def getCount(st) :
    7 S3 a$ e$ U0 Q' c" E
  13. return st.getQuestItemsCount(FANGS_ITEM_ID)3 F# V) }5 [' C- ^; C3 e3 H
  14. 4 u  A4 o7 C. |4 r: Z
  15. def completed(st) :
    ; w9 s, R; s7 R2 k
  16. st.setState(COMPLETED)* v  e$ u. n+ o: H) r& q
  17. st.clearQuestDrops()* e& ~0 M+ }$ t' [+ I9 `
  18. st.takeItems(FANGS_ITEM_ID,-1)0 e8 b/ D% {# ?+ h
  19. st.giveItems(WORLD_MAP_ITEM_ID,1)
    # V, g, i0 S8 p/ L# n
  20. st.exitQuest(False)
    7 r; H; F+ c, s6 m" p4 Z1 d2 I# d
  21. return2 P  [7 v. [, V4 G) S) F9 z* h9 |
  22. 2 V, ]0 n) ?( e* M4 A
  23. def check(st) :! h- F6 e8 `% D3 D3 N& Q! u% r, R% N
  24. if getCount(st) >= 4 :  o+ y- y+ j4 |% h( u
  25. completed(st)
    0 C- R- d! a" f/ B& w1 T8 r
  26. return$ Y5 r/ G; T9 y- S+ O. b# J: e
  27. 3 u- z, G% W- r$ _: x/ K
  28. class Quest (JQuest):
    : t' ?% ]9 g. g; V0 \, ~1 ~& {
  29. 1 k" m: @/ R% ~: P
  30. def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)" H; Q* z, I! U9 j

  31. ) |$ a# |, k7 a" x
  32. def onEvent (self,event,st):; r  y4 ]. v! i
  33. id = st.getState()
    ! W# N9 {6 s4 R8 `1 u, @6 ]
  34. if id == CREATED : st.setState(STARTED)
    3 {' ?5 b! h2 ]1 L* P6 p
  35. elif id == COMPLETED: pass
    , l8 A) t' ?" K( A0 _1 a( v6 i. ^
  36. elif id == STARTED : check(st)
    1 L+ F* _* B  X$ L( ]( F  J$ s: b0 X
  37. return
    ! j# Q6 s8 Q1 m. \) e

  38. 9 m& `5 z3 d2 C8 ?( h3 \
  39. def onKill (self,npcId,st):
    % Y; O. ^; z8 }- F& W" ?: g
  40. if npcId == KELTIR_NPC_ID:! X# ^# z0 M3 b% {0 ?1 M
  41. n = getCount(st)
      `; x$ ?4 p$ N. Y, ~$ I
  42. if n == 0:) ^( H6 ~, `% g4 }$ r( J# h; \3 ]0 O
  43. if st.get('chat0') == None :
    7 |) Y! a4 g0 U9 ]
  44. st.set("chat0", "true")) W+ i5 W, e$ a( ~9 ?8 k
  45. return "Chat0.htm"& M! p1 ]% ~. y/ V& R1 w6 S
  46. elif n == 1:
    3 e* p9 Y" J7 }- d
  47. if st.get('chat1') == None :
    & I( E3 p' Z+ O& m+ g% h$ j
  48. st.set("chat1", "true")6 b% R% ?! @4 n" A1 I
  49. return "Chat1.htm". c& h% j+ z* {+ D& Y* f# e% M$ Q
  50. elif n >= 4:) Y+ Q% t; H( ^
  51. return "Chat4.htm"
    7 e; e2 u9 Z/ r1 d6 G% C
  52. return "Collect "+str(n)+" of 4 fangs"' {% Y4 x  R4 M* l  `
  53. return0 i' ~: l% _9 m1 J! M1 w! f

  54. 5 a4 l& E: I- J1 s5 w; e
  55. QUEST    = Quest(201, "Tutorial", "Tutorial quest")/ x; \7 w0 c6 k9 ~0 G
  56. CREATED = State('Start',    QUEST)8 W1 S& X" i3 \8 L- b' a& X$ j+ e5 n9 H
  57. STARTED = State('Started', QUEST)7 g6 ^% q4 j1 \% J! [1 e5 F
  58. COMPLETED = State('Completed', QUEST)
    9 d; s+ Y; y. B. J" r
  59. 9 z5 V) B4 X2 Q8 [: u
  60. QUEST.setInitialState(CREATED)" f( b, O% g+ L. M" ]
  61. QUEST.addStartNpc(7056); e, u4 k2 M, j% H/ s
  62. QUEST.addStartNpc(7012)
    8 t/ @8 ]: ]. R" }' m  R
  63. QUEST.addStartNpc(7009)6 S8 l5 b0 a* K
  64. QUEST.addStartNpc(7011): [, S9 a) O3 Z

  65. + i3 D" a/ G/ w5 E2 O( W
  66. STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)6 M0 D3 R/ [3 ]/ Q  t
  67. STARTED.addKillId(KELTIR_NPC_ID)
    * g5 Y- f4 ?1 M. M
  68. STARTED.addTalkId(7056)0 ]4 @6 V6 t: s# {5 \
  69. STARTED.addTalkI d(7012)
    , P: d- Z3 w# B- S6 u
  70. STARTED.addTalkId(7009)/ f& y  C" l: ^8 }' W6 H4 P3 b
  71. STARTED.addTalkId(7011)
Скопировать код
6 t4 ?  J+ G  D5 L
/ V5 v( Y# c/ {$ r
Чтобы ответить, вам надо авторизироваться в системе Вход | Зарегистрироваться

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

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

638638758

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

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

admin@artace.ru Онлайн

QR-код

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