Top.Mail.Ru

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

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

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

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

x
Хроники        Interlude
( @/ z$ ]0 K2 I( L: eСборка        L2j/ [0 e; J6 x4 e  w2 w  s4 t' i& M$ M
Обратите внимание: в файле htm стартового NCP обязательно должна быть ссылка на квест:
( s- q) D; x5 A* L# k1 v1 Z- k
  1. STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код
Для этого квеста больше ничего не надо. Все необходимое для корректной работы квеста уже добавили. Вот полный текст квеста:- X9 v0 L' `. ~6 U: J7 l

0 t2 |& K1 \" a/ y
  1. if getCount(st) >= 4 :+ l5 I, d9 S4 m# n5 T
  2. completed(st)- ]$ v& z  E6 R# ^5 V6 C8 T
  3.   return
    ' g  f8 t& I* ]* T( a* F. j8 A
  4. & `4 {) o! i) c( W/ Y6 j
  5. class Quest (JQuest):
    # o' E! A, O; a! t2 _! e3 }
  6.   def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)& w1 z: X% v( n
  7.   def onEvent (self,event,st):
      Q9 H; ?, a2 F8 z- s% g- \. t
  8. id = st.getState()) |3 N' ]) I! p) Y
  9. if   id == CREATED  : st.setState(STARTED)
    ) p8 q4 x$ f, M5 n
  10. elif id == COMPLETED: pass: h; e3 c5 F- V' E, J4 @3 d5 X/ k
  11. elif id == STARTED  : check(st)% ?5 }7 {6 H" I- N8 ]! K
  12. return
    & i0 Q* I, ~# G0 F/ D1 k1 ?1 X

  13. 4 w7 q; d# |6 V, ^2 G
  14. QUEST     = Quest(201,"Tutorial", "Tutorial quest")
      G4 q. x* }1 u" y
  15. CREATED   = State('Start',     QUEST)/ Y" [" [- f0 u0 \$ N1 d  c" c0 I: {
  16. STARTED   = State('Started',   QUEST)
    5 b* u: S' ~# F8 n; r, M! `+ ^1 N
  17. COMPLETED = State('Completed', QUEST)( j8 V, v; v2 e1 f, I
  18. $ `' l; |1 ?3 q3 j  B
  19. QUEST.setInitialState(CREATED)# A5 ~6 v' {! N
  20. QUEST.addStartNpc(7056)& O: o* l/ G9 {8 ^6 [
  21. STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код
Теперь рассмотрим, как это работает.
; r9 `+ g+ w; Z. XИгрок подходит к начальному NCP (в данном случае 7056), нажимает на «Quest». Квест будет создан и состояние квеста перейдет к CREATED и игроку будет показана страничка Start.htm с описанием квеста. Тогда метод onEvent, поле открытия странички Start.htm переведет состояние квеста в STARTED и игроку будет показана страничка Started.htm, где будет опсание того, как найти keltirs и .т.д.$ X+ Y5 P" V6 s
' l3 N/ }& k1 \5 p; W
# f6 r' k: Q  \* C7 o6 C1 O
При состоянии STARTED будет зарегистрирован дроп «fangs» при убийстве keltirs. Игрок может вернуться к стартовому NCP и спросить о квесте – метод onEvent будет вызван снова. Если у игрока не хватает необходимого количества предметов, то метод check() не переведет квест в следующее состояние и Started.htm будет показана снова. Но если игрок собрал необходимее количество предметов (в данном случае 4 клыка), то метод check() вызовет метод completed() который переведет квест в новое состояние COMPLETED, заберет все клыки, даст карту мира, т.к. это награда за квест, покажет Completed.htm и завершит квест.% N$ t1 [; c' S$ _1 U/ j/ O

7 @+ [; o+ [, [* K2 D
9 t1 ]+ P# A9 D  ]$ u+ N+ f+ g
Теперь давайте сделаем наш квест более похожим на то, что он должен из себя представлять.
7 A0 W3 V/ g! r% r3 U5 s$ h9 f* tПрежде всего у нас есть 3 метода для объявления их в Яве – onTalk, onKill и onEvent. Если методы onTalk и onKill не объявлены, то за них все будет делать метод onEvent, т.е. определять квестовых монстров и вызывать диалоги NCP. Есть примечание, методы onTalk и onKill будут вызывать только диалоги с NCP в зависимости от текущего состояния квеста. Метод onKill будет вызываться только тогда, когда мы убиваем квестового монстра.* g3 _  w% _. ~8 r2 V$ a
6 C( p2 Q" a8 L4 I& g7 L: s
% C. M4 Y3 Z1 z" n9 Z' G
Давайте рассмотрим как вызывается метод onKill при убийстве keltir в состоянии квеста STARTED:2 V: K! C/ B9 B8 _
  1. STARTED.addKillId(KELTIR_NPC_ID)
Скопировать код
и метод onKill в классе Quest:
8 Q& x7 ~# ]4 K  V  K  @3 `
4 W7 P9 v5 ?+ ?, q) c2 h; w# T
  1. class Quest (JQuest):0 J$ f, H  H" O0 K
  2.   ...
    ' q4 N' Y  D! t! x- v
  3.   def onKill (self,npcId,st):
    & w. i, W* V6 n, ~. U, h
  4. if npcId == KELTIR_NPC_ID:
    8 D) C8 O  [, o+ y
  5.    n = getCount(st)! ?% B" F' O1 X5 J& [2 N8 A
  6.    if   n == 0:: T7 B/ ^5 d. n. p+ ~
  7.        return "Chat0.htm") O5 q( u, b' }0 E" N
  8.    elif n == 1:
    1 @* U1 o" G; U7 E
  9.        return "Chat1.htm": ~4 l+ z* R$ \/ v
  10.    elif n >= 4:
    6 ^. ?" v5 k4 Y/ }* E
  11.        return "Chat4.htm"* i' w# S: Y, n1 h) n0 ?: d, \. C
  12.    return "Collected "+str(n)+" of 4 fangs"* ^: i1 O  A! H7 @+ g8 W' p
  13. return
Скопировать код
Метод onKill (а так же метод onTalk) имеет следующие параметры:& h$ H% M: W. K1 m; S8 |7 ^

- J7 w/ B+ v8 d: @

+ A4 t" A: X3 K• self – квест
$ \# l& s) f) ?- W; l• npcId – ID NCP, которого мы должны убивать (если это метод onTalk, то ID того NCP, с которым мы должны поговорить)., v) D0 F" G+ G3 ~! G, A
• st – текущее состояние игрока.
- d3 ~+ [- B. B
) D  d2 V6 N2 n$ b/ ?
& y8 B' V9 {" b
В этом методе мы проверяем и отмечаем, является ли убитый NCP keltir’ом. В основном эта проверка не нужна, т.к. у нас только KELTIR_NPC_ID.
8 t' w: P3 r% T/ H& E) c% |
* n9 ~3 I# p- b" A" d# D

2 m/ n, v; i/ R- PЗатем проверяем количество предметов (в данном случае количество клыков), и если их вообще нет, то возвращаем строку "Chat0.htm", если только один предмет, то возвращаем строку "Chat1.htm", если же предметов 4 или больше, то "Chat4.htm". Если строка возвращена из методов onEvent, onKill или onTalk, то сервер покажет соответствующие htm. В Chat0.htm может иметь следующий текст: «Вы не имеете ни одного клыка, возвращайтесь позже, когда соберете 4 штуки и бла, бла, бла…», в Chat1.htm может быть следующий текст: «У Вас всего 1 клык, по этому соберите еще…». В Chat4.htm – «Вы собрали необходимое количество предметов, возвращайтесь к вашему тренеру, что бы завершить квест…»
2 D6 y# U  v1 `  b5 q5 x# \5 _' G7 y8 M2 g# }- X* r

" J8 d) k& S# Y. k" `& n! rПримечание: если в строка return начинается с "<html>", то будет показана страничка html с текстом, который стоит далее. Так вместо:
" U- I9 ?! F+ M" @! rreturn "Chat4.htm"' d. t" o% y3 N" A/ u2 _
$ p. D  ^( Q" Y
- K# E& v4 t9 j0 C5 L
можно поставить:
5 }2 \; @8 ?5 l2 z
  1. return "<html><body>Return to your trainer to complete the quest</body></html>"
Скопировать код
Так же если строка заканчивается без .htm или в начале нет <html>, то текст будет выведен, как системное сообщение в окне чата. В нашем случае мы сделаем так, что бы при каждом убийстве keltik выводилось системное сообщение: «Собрано N из 4-х клыков».
/ m  y% B; i  e5 ^
' r% j5 O( D1 ]. ^4 U* d

; L7 ~+ g: z  y0 ~Наш код для onKill имеет один недостаток. Он будет постоянно показывать Chat0.htm, Chat1.htm и Chat4.htm, нам же необходимо, что бы Chat0.htm и Chat1.htm показывались только один раз. Как нам это сделать? С помощью переменных.7 z+ A" I  M' S0 V/ i# I
4 P9 V+ {6 t: y+ a' R
4 x6 e* y/ ]& w& a  D
В каждом квесте строки могут храниться с помощью переменных. Эти переменные сохраняются в Вашей БД. В каждом методе мы можем назначить, прочитать и удалить переменные. Давайте изменим метод onKill, так что бы каждый диалог вызывался только один раз.
  {3 U5 [9 d# @& }- j
  1. def onKill (self,npcId,st):
    * t  W, n* l" T' X+ `7 ?. x% s' k
  2. if npcId == KELTIR_NPC_ID:
    ) C* A0 D& Y2 `6 v7 a0 J
  3. n = getCount(st)+ m5 J, J% ^% k/ E0 ~
  4. if n == 0:
    . W; E2 e7 l* [% l: Q0 ^- }
  5. if st.get('chat0') == None :, O7 U; k- u: m9 ]8 p
  6. st.set("chat0", "true")
    * }' ?" W+ X8 t# w, h
  7. return "Chat0.htm"0 X- c; Z4 f' [. A5 h' P3 b! @
  8. elif n == 1:
    8 i0 A2 Q+ D" ?- B
  9. if st.get('chat1') == None :; i1 w; b' ?" {- L
  10. st.set("chat1", "true")
    # ~) p( E% q7 [- R/ V+ |" C' E( O
  11. return "Chat1.htm"4 [& Y# F( u  P! s1 _5 c
  12. elif n >= 4:
    , k9 K* G8 P- d. n
  13. return "Chat4.htm"
    + e0 L2 z0 n) `! C
  14. return "Collected "+str(n)+" of 4 fangs"
    6 d; X6 d+ m: c
  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.$ @' c* P; D$ L# O9 r

7 ~' n. h' m" ^, G

' I% V& w0 O8 f8 Q1 y! j5 xВот конечный рабочий вариант квеста:
1 T+ a, G6 \& {/ B+ _0 w4 l
  1. import sys2 @5 J0 O9 K* v8 f, ^# Y; m
  2. from net.sf.l2j.gameserver.model.quest import State
    8 ^* q" W1 x2 G, v( E3 i4 A
  3. from net.sf.l2j.gameserver.model.quest import QuestState+ z1 D( X- Y( @" s
  4. from net.sf.l2j.gameserver.model.quest.jython import QuestJython as JQuest$ B5 t8 {( m2 p  Z/ G

  5. % G% P2 W& N' j& ~  P
  6. KELTIR_NPC_ID = 12082
    % L% ~3 G' w( ~- i' D
  7. FANGS_ITEM_ID = 18597 ?% q: F" Q" ^* x  q+ j
  8. DROP_RATE    = 5000004 @) R% ]0 H( g, b2 d- }
  9. 6 t2 M: s0 g/ L* J* d
  10. WORLD_MAP_ITEM_ID = 1665
    & g: X( o* j: H: j( \
  11. ; r+ ]5 s* b9 I+ G; T
  12. def getCount(st) :2 n3 g% K! u2 z# j! \
  13. return st.getQuestItemsCount(FANGS_ITEM_ID)% O8 i; [9 I$ ^
  14. 8 x  c; f& i: k" r
  15. def completed(st) :) a+ `4 q) \$ V; @1 @
  16. st.setState(COMPLETED)0 h. U* E& G2 v7 g
  17. st.clearQuestDrops()' G5 _8 @, U# b% m
  18. st.takeItems(FANGS_ITEM_ID,-1)
    4 x$ h$ D1 ]5 [
  19. st.giveItems(WORLD_MAP_ITEM_ID,1)) h/ D! u0 [( L7 S) O
  20. st.exitQuest(False)" c: D  k+ I1 x- P( a! {
  21. return
    - q6 N) x, e; H, M5 G' [6 P1 d
  22. 6 j  ^+ n& [+ ?( F5 q+ g/ S( _8 M9 E
  23. def check(st) :
    $ Q7 H9 u+ O" z
  24. if getCount(st) >= 4 :2 A5 A# ?6 M& v" _9 j# i
  25. completed(st)
    7 p4 D7 y* `2 X
  26. return6 t0 M1 |6 f2 Y

  27. 1 z1 s7 l7 y7 J' l% R) C9 f9 b
  28. class Quest (JQuest):
    1 L0 v9 Z) k4 V  a, \3 h# p; d
  29. 9 y; G# b3 ]0 `& P$ _+ A
  30. def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)
    1 d8 R8 v4 m( S& r+ {

  31. ' K" F6 ]  s6 g/ X' i
  32. def onEvent (self,event,st):
    : J$ c3 O7 a* _) i3 S1 l
  33. id = st.getState()- g7 h2 a5 ?) Z' Q3 J2 B
  34. if id == CREATED : st.setState(STARTED)& G0 P( u2 r8 E+ b) G5 K
  35. elif id == COMPLETED: pass& D9 v7 ^: B1 t3 f5 X% L
  36. elif id == STARTED : check(st)
    5 u+ r, ^4 k1 \- Q; F; Y$ L
  37. return
    . J* O% m3 `+ a3 c
  38. 2 H- L4 Y" q/ h1 z' r( a
  39. def onKill (self,npcId,st):; d) }5 }8 Q4 n0 W# v) S
  40. if npcId == KELTIR_NPC_ID:7 a+ R# c% K) u) G0 D
  41. n = getCount(st)% R  q8 T- I( [, ~
  42. if n == 0:1 r! ~1 j6 u: O! I
  43. if st.get('chat0') == None :
    + t' v2 ^$ l4 _4 z9 O
  44. st.set("chat0", "true")3 ?7 y! z, E/ b) P+ f4 K
  45. return "Chat0.htm"' I7 |2 o; W1 W1 a* \
  46. elif n == 1:) m# \+ g) ?3 O3 S( B! e
  47. if st.get('chat1') == None :
    5 }: H, t7 a& U! d' ?! H; L# U
  48. st.set("chat1", "true")& \1 }5 W/ {8 y' X
  49. return "Chat1.htm"
    9 y6 y! ~7 a" R/ v" j& H4 N# D
  50. elif n >= 4:) J2 |/ J; N3 K# o/ ~8 R- x6 e; y
  51. return "Chat4.htm"* O& k+ g+ x7 }& C( a( h, }
  52. return "Collect "+str(n)+" of 4 fangs"# l$ Q. f$ b, U- W- n
  53. return3 i& b" x7 I6 C, D5 Q* G6 G6 o6 H

  54. ' Y+ |) a3 A, D! \0 Y
  55. QUEST    = Quest(201, "Tutorial", "Tutorial quest")! F- M2 }0 ]) P
  56. CREATED = State('Start',    QUEST)
    $ ~9 T+ v" j5 q% @* G5 ]
  57. STARTED = State('Started', QUEST)$ d1 q/ F8 ]1 q- V
  58. COMPLETED = State('Completed', QUEST)$ v4 ^' j, R" H# u" u2 @

  59. 1 y$ r0 r/ X  j& s4 U0 L
  60. QUEST.setInitialState(CREATED)
    ( d+ d  T9 W* v4 u
  61. QUEST.addStartNpc(7056)1 c: B. H5 P, u: N" s
  62. QUEST.addStartNpc(7012)  T! k- w" p) t' P5 s8 Q$ z9 K
  63. QUEST.addStartNpc(7009)
    3 b3 a" t3 M. x) M' ?0 n# K
  64. QUEST.addStartNpc(7011)
    5 P1 z+ ~- \( R' D% T

  65. ' V- _8 B2 B+ T" @% i
  66. STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)6 [! f+ u3 a, L$ l
  67. STARTED.addKillId(KELTIR_NPC_ID)5 q, l' S. A$ a1 _
  68. STARTED.addTalkId(7056)
    / }* o" m' v! k" e
  69. STARTED.addTalkI d(7012)
    : k& f" K( e5 {  Z% h0 k/ Z
  70. STARTED.addTalkId(7009)
    . V& x7 ~: c% ^& ]9 J
  71. STARTED.addTalkId(7011)
Скопировать код
' V) t$ o+ F$ t) {% D
( f0 p4 [, h# o4 c4 c9 R
Чтобы ответить, вам надо авторизироваться в системе Вход | Зарегистрироваться

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

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

638638758

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

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

admin@artace.ru Онлайн

QR-код

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