Top.Mail.Ru

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

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

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

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

x
Хроники        Interlude" M! x/ T/ d! Y; h1 [' ^4 C1 a
Сборка        L2j
8 G! C( `' t, o" r5 jОбратите внимание: в файле htm стартового NCP обязательно должна быть ссылка на квест:
  t/ P3 D3 G" C2 z3 L& m8 I+ m& f
  1. STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код
Для этого квеста больше ничего не надо. Все необходимое для корректной работы квеста уже добавили. Вот полный текст квеста:
. E$ U% K; F4 q/ y/ F# I% y. X0 v) L, W/ Z: L. J) e
  1. if getCount(st) >= 4 :
    & D- S9 @- ~6 ~& w% Z
  2. completed(st): y3 m' [6 m+ D0 P0 Q' ]
  3.   return
    & r! h' {8 ^2 E5 D! s8 {
  4. 5 j! m3 O" }8 r2 X2 _3 {4 z4 X
  5. class Quest (JQuest):
      N: B/ b" F- u5 J1 D2 T
  6.   def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)+ b- C$ |0 q5 }2 G! C; ]# k' Y$ S
  7.   def onEvent (self,event,st):
    % P( S1 N7 l/ y1 ^6 R  r
  8. id = st.getState()
    ! J1 ~. g- A9 ~* v
  9. if   id == CREATED  : st.setState(STARTED)( x% {" a& w2 V/ n
  10. elif id == COMPLETED: pass9 z6 z7 _: |* {1 e: x- m" }
  11. elif id == STARTED  : check(st); l: L! y$ m  ]) x' Q
  12. return  d, c5 z& j2 `" K' C3 F

  13.   y+ f& G( [& b
  14. QUEST     = Quest(201,"Tutorial", "Tutorial quest")
    ; I! H1 C( M( J5 `" c( H* A
  15. CREATED   = State('Start',     QUEST)7 H% o5 p% {  k6 v- {
  16. STARTED   = State('Started',   QUEST)
    1 x2 j. g* _# K5 I# u( H2 X* w
  17. COMPLETED = State('Completed', QUEST)! q; |: U* a) E$ o  T- n* d

  18. ) [4 K5 w* Y( t  ?- B0 }4 X
  19. QUEST.setInitialState(CREATED)4 l5 i/ b4 O9 M7 l4 I3 @
  20. QUEST.addStartNpc(7056)
    6 X: ~6 o  ?4 C  |( q+ T$ Z/ ~2 h0 o/ z
  21. STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код
Теперь рассмотрим, как это работает.
% M, r& h; j3 d8 e; v$ k1 PИгрок подходит к начальному NCP (в данном случае 7056), нажимает на «Quest». Квест будет создан и состояние квеста перейдет к CREATED и игроку будет показана страничка Start.htm с описанием квеста. Тогда метод onEvent, поле открытия странички Start.htm переведет состояние квеста в STARTED и игроку будет показана страничка Started.htm, где будет опсание того, как найти keltirs и .т.д." F0 O) I% [, ^) Y8 O) E

' B; a+ W3 H$ }7 D  E) i' U/ Q
! w; R# }5 W0 f
При состоянии STARTED будет зарегистрирован дроп «fangs» при убийстве keltirs. Игрок может вернуться к стартовому NCP и спросить о квесте – метод onEvent будет вызван снова. Если у игрока не хватает необходимого количества предметов, то метод check() не переведет квест в следующее состояние и Started.htm будет показана снова. Но если игрок собрал необходимее количество предметов (в данном случае 4 клыка), то метод check() вызовет метод completed() который переведет квест в новое состояние COMPLETED, заберет все клыки, даст карту мира, т.к. это награда за квест, покажет Completed.htm и завершит квест.
: e/ w; V3 A1 E' t& ]& h' b  f: S3 a& {3 }1 y: [4 F
0 r  C, `8 i7 ^* w" m2 H
Теперь давайте сделаем наш квест более похожим на то, что он должен из себя представлять.
+ s* R2 \, b% I( G- W4 B/ W0 ZПрежде всего у нас есть 3 метода для объявления их в Яве – onTalk, onKill и onEvent. Если методы onTalk и onKill не объявлены, то за них все будет делать метод onEvent, т.е. определять квестовых монстров и вызывать диалоги NCP. Есть примечание, методы onTalk и onKill будут вызывать только диалоги с NCP в зависимости от текущего состояния квеста. Метод onKill будет вызываться только тогда, когда мы убиваем квестового монстра.' M% H6 s# Q; g4 O0 ^

0 O, n: @) V- V" K/ J" Q

! [) n4 G+ x% C; [/ nДавайте рассмотрим как вызывается метод onKill при убийстве keltir в состоянии квеста STARTED:* J9 n! B- J4 y3 e
  1. STARTED.addKillId(KELTIR_NPC_ID)
Скопировать код
и метод onKill в классе Quest:: H8 |4 D9 B( C" P, W6 i

% n' [) Y% Y- L; \  y9 D
  1. class Quest (JQuest):5 J; a' }8 N8 k, L
  2.   ...$ M/ f* X/ c1 o  K6 r
  3.   def onKill (self,npcId,st):8 }* J! ]1 \1 U+ D
  4. if npcId == KELTIR_NPC_ID:
    - E7 `, x* X' ~6 |
  5.    n = getCount(st)
    : f( W7 X" S3 v5 S; Q
  6.    if   n == 0:9 ^# @0 v3 Q$ l: K+ z/ C) S2 @- ~& I
  7.        return "Chat0.htm"7 P, i5 @  g2 G2 t% Q& S
  8.    elif n == 1:
    * e: O5 c- O7 G6 U
  9.        return "Chat1.htm"
    9 q8 H/ O& a6 Y. v+ c
  10.    elif n >= 4:
    6 O5 j/ X( R0 c) h
  11.        return "Chat4.htm"
    5 f. Y$ z9 z  s6 e
  12.    return "Collected "+str(n)+" of 4 fangs"- e, T5 A7 A6 Z; Z. j, f$ ~! Z9 ^0 N
  13. return
Скопировать код
Метод onKill (а так же метод onTalk) имеет следующие параметры:
2 g2 \% F/ H1 R! Y( j$ r7 `1 E
# V  n0 F5 c( q( Y4 g' }  C
; z/ M& r% ^' T; Q
• self – квест
* M9 \$ q+ Y0 x* d0 ?, ^• npcId – ID NCP, которого мы должны убивать (если это метод onTalk, то ID того NCP, с которым мы должны поговорить).
5 a9 \. I& c  a7 ]7 J• st – текущее состояние игрока." M3 }, }1 k! d+ \5 x

$ O! ^- p) U6 \0 ~! P

- t" q8 w' y! KВ этом методе мы проверяем и отмечаем, является ли убитый NCP keltir’ом. В основном эта проверка не нужна, т.к. у нас только KELTIR_NPC_ID.+ C6 [2 z9 f2 a0 u

9 T: r3 ?1 H2 U$ J

* ^! _! P* @) W- J0 |3 p# uЗатем проверяем количество предметов (в данном случае количество клыков), и если их вообще нет, то возвращаем строку "Chat0.htm", если только один предмет, то возвращаем строку "Chat1.htm", если же предметов 4 или больше, то "Chat4.htm". Если строка возвращена из методов onEvent, onKill или onTalk, то сервер покажет соответствующие htm. В Chat0.htm может иметь следующий текст: «Вы не имеете ни одного клыка, возвращайтесь позже, когда соберете 4 штуки и бла, бла, бла…», в Chat1.htm может быть следующий текст: «У Вас всего 1 клык, по этому соберите еще…». В Chat4.htm – «Вы собрали необходимое количество предметов, возвращайтесь к вашему тренеру, что бы завершить квест…»
6 A! f3 ~1 p  O7 b) s; U$ n8 h% I) G8 @9 Q
3 n8 K  ^9 u! Q/ i
Примечание: если в строка return начинается с "<html>", то будет показана страничка html с текстом, который стоит далее. Так вместо:& G+ e* [8 s" k* q4 n* V2 l# Q. v/ H
return "Chat4.htm"
0 j* O# T! g& [& G$ \+ s3 K5 z1 s6 w& M
6 j$ L8 y/ {& f2 B
можно поставить:
$ k6 Q4 C! d4 S' R0 S) F0 y
  1. return "<html><body>Return to your trainer to complete the quest</body></html>"
Скопировать код
Так же если строка заканчивается без .htm или в начале нет <html>, то текст будет выведен, как системное сообщение в окне чата. В нашем случае мы сделаем так, что бы при каждом убийстве keltik выводилось системное сообщение: «Собрано N из 4-х клыков».. n( @5 ^2 P9 e0 T& n
- M& T& |4 N0 R2 c$ g

8 ]! C7 N: _) D" P5 X8 D: SНаш код для onKill имеет один недостаток. Он будет постоянно показывать Chat0.htm, Chat1.htm и Chat4.htm, нам же необходимо, что бы Chat0.htm и Chat1.htm показывались только один раз. Как нам это сделать? С помощью переменных.9 ]. h- w# o) |" T3 f( \

2 [' \, _# i7 K; Z

8 L) _: _2 ~$ mВ каждом квесте строки могут храниться с помощью переменных. Эти переменные сохраняются в Вашей БД. В каждом методе мы можем назначить, прочитать и удалить переменные. Давайте изменим метод onKill, так что бы каждый диалог вызывался только один раз.5 U! D; ~0 F/ B( ^) O) H# }
  1. def onKill (self,npcId,st):
    8 Z: o5 n; v: V9 d+ H
  2. if npcId == KELTIR_NPC_ID:- f- q- C! @+ b7 e$ m! n
  3. n = getCount(st)( w2 D( f/ K1 T& E$ b2 B9 [
  4. if n == 0:( L" j  ]/ m4 |' r
  5. if st.get('chat0') == None :3 D; Q: t2 P& a7 a* e+ j* J( Z
  6. st.set("chat0", "true")
    ' F% G' v- r3 a5 o" b* |3 ]7 w
  7. return "Chat0.htm": h& c" s3 Q$ n
  8. elif n == 1:% o( w7 Y" M, Q1 [# ^9 L/ A
  9. if st.get('chat1') == None :
    % {: _/ Z1 A: s; j  ~1 ?
  10. st.set("chat1", "true"). ~; k6 |+ E/ F  j4 j! x" p2 N
  11. return "Chat1.htm"
    ' {9 Q" i) B6 w0 n7 }+ W# K
  12. elif n >= 4:
    6 A! P2 R( E* a' j* w; z
  13. return "Chat4.htm"
    4 Y3 Y# M2 [" t3 b- v
  14. return "Collected "+str(n)+" of 4 fangs"
    # o' V( n% x  i! f" l
  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.( S$ Y/ ~# v( }

# v; S/ B2 @  T* C# ^; p
$ n, J, K( x1 n5 ]- t
Вот конечный рабочий вариант квеста:# J3 c4 q/ }; _* n6 I+ W5 C
  1. import sys
    ; E" ^1 K' R  ~, z$ q* N6 m
  2. from net.sf.l2j.gameserver.model.quest import State
    9 q* R  ~* A4 X4 g. z! t6 \9 m' u
  3. from net.sf.l2j.gameserver.model.quest import QuestState/ R2 F( D8 Y. z0 j0 D0 a
  4. from net.sf.l2j.gameserver.model.quest.jython import QuestJython as JQuest
    3 o0 R# F  Q. }# C

  5. : W# g$ }- k( z8 k' ~
  6. KELTIR_NPC_ID = 12082+ F! H, X& B( ~7 N/ P
  7. FANGS_ITEM_ID = 1859
    7 [% X! Q( t1 w1 O, B8 q- A0 Q) ]
  8. DROP_RATE    = 500000
    # K$ q+ ?* T+ `8 K( C
  9.   Z' d& i" Q# p! H& i, D
  10. WORLD_MAP_ITEM_ID = 1665
    0 y5 E* M& B3 |8 g. v3 t
  11. # [" F4 b) \, k0 B5 v. ^" p
  12. def getCount(st) :
    7 Q; [7 L% ]4 T+ }1 [( J/ u$ u; F
  13. return st.getQuestItemsCount(FANGS_ITEM_ID)
    9 N: t( n0 X' ?/ \+ B
  14. ' [0 d% m2 I# b" C6 U
  15. def completed(st) :
    , O5 ~& p; N% |( g! x
  16. st.setState(COMPLETED)& G! m! K$ U( `, }5 \" K
  17. st.clearQuestDrops()4 n! X1 r1 a5 A$ R9 j/ ^
  18. st.takeItems(FANGS_ITEM_ID,-1)  Q+ `# w+ J3 M7 [6 p; M9 X
  19. st.giveItems(WORLD_MAP_ITEM_ID,1)6 o2 n) z! q. M! {& V5 o! M
  20. st.exitQuest(False)
    4 g  [+ z0 h' t# F, R4 p$ M/ @; E
  21. return  d% I& Z* G& ?3 K0 h

  22. $ ~- c" N4 V( w; c
  23. def check(st) :
    9 [* a- y% Y1 v. L& K9 X
  24. if getCount(st) >= 4 :
    ; y5 o4 d+ I8 T2 o& [
  25. completed(st)
    " M, n! F3 a' C# _+ s) G) |
  26. return
    / s! R# N* s; h) d0 u4 V6 `: V

  27. 7 x3 y) |6 ^% y& I
  28. class Quest (JQuest):
    4 i- x7 Q; Z5 n7 @
  29. ) g2 q2 @' _% ~+ ^3 L' v
  30. def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)
    ' R8 ~" q2 y) {" V

  31.   z& Q# ^$ t) \2 X' M
  32. def onEvent (self,event,st):
    # P- d& o% j9 Z3 y! x
  33. id = st.getState()! C7 C; j/ `- H' ]0 b! Q
  34. if id == CREATED : st.setState(STARTED)
    " i; P0 B4 W! x. E2 P2 J+ R/ U
  35. elif id == COMPLETED: pass2 U5 x( @( {; g4 U; g" h$ l" U: y! v
  36. elif id == STARTED : check(st)
    ! a. L: j) k$ y; G7 L
  37. return% i+ L$ |4 z4 J2 f

  38. ( H; K5 p" z6 c8 x. q) h
  39. def onKill (self,npcId,st):
    * W7 f: L8 D7 n8 p# u
  40. if npcId == KELTIR_NPC_ID:
    9 |9 E) U3 W4 L) ]! [. G1 b/ Y) \! _
  41. n = getCount(st). r+ [/ s( z8 {/ }# K* x
  42. if n == 0:
    & C, ]' w6 }0 S: ]) ?7 N
  43. if st.get('chat0') == None :
    0 O) y/ Z) ]) n& w: y
  44. st.set("chat0", "true")
    3 R7 R: ?7 `" b  d
  45. return "Chat0.htm"% [. i3 [  J8 u( p
  46. elif n == 1:
    4 E  q3 V6 k$ f  \' T7 n( X
  47. if st.get('chat1') == None :
    : D7 f$ n4 J  b8 V, y3 e- e
  48. st.set("chat1", "true")
    4 k" J& T. }0 |! f
  49. return "Chat1.htm"$ Y) u, a0 j- L. F( h$ m* K
  50. elif n >= 4:
    4 |! K; u8 k6 O
  51. return "Chat4.htm"4 Z1 m, W: v& L$ Q1 O( k/ q. q
  52. return "Collect "+str(n)+" of 4 fangs", j# ?# ^+ n' N9 Y- i
  53. return
    $ v( F5 F" o! N
  54. 7 ?$ X3 u3 ~3 x
  55. QUEST    = Quest(201, "Tutorial", "Tutorial quest")! R) b; Q3 v" m% X& g7 |2 b4 s1 h
  56. CREATED = State('Start',    QUEST)
    . @+ ^" q+ Y) e2 Y" z- a: M; R4 m/ R
  57. STARTED = State('Started', QUEST)9 c( z: t$ F6 g; I4 u) G% ^
  58. COMPLETED = State('Completed', QUEST). L3 S3 p+ M. h7 h! \

  59. 0 {& a0 Z8 E( ]
  60. QUEST.setInitialState(CREATED)
    ' U8 s+ k$ A# `) f
  61. QUEST.addStartNpc(7056)8 K& p- J2 \7 ]
  62. QUEST.addStartNpc(7012)
    - v+ L% `6 G7 B
  63. QUEST.addStartNpc(7009)
    + S  ?; O, S! |. B( L
  64. QUEST.addStartNpc(7011)) ^5 j0 y9 G! [* F6 ~
  65. + ^0 j* ?6 X5 t+ T/ L) S1 D
  66. STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)( ]- t& g8 E+ u6 _4 e9 ]& S
  67. STARTED.addKillId(KELTIR_NPC_ID). ?* j. n  O9 d+ C9 {# k! P, b+ `- R
  68. STARTED.addTalkId(7056)+ e' l+ ?3 u  x' p+ X4 S
  69. STARTED.addTalkI d(7012)+ {1 j3 y1 P, p6 E- }# D" J
  70. STARTED.addTalkId(7009): }) s+ R( B/ X# g2 i- |
  71. STARTED.addTalkId(7011)
Скопировать код
# }  V4 S0 Z8 I  S. q* ^4 k. X
- t- B9 A8 H6 V% M  d& S
Чтобы ответить, вам надо авторизироваться в системе Вход | Зарегистрироваться

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

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

638638758

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

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

admin@artace.ru Онлайн

QR-код

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