Top.Mail.Ru

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

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

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

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

x
Хроники        Interlude( c# r' [5 W1 `2 ~
Сборка        L2j: }) Q0 {. O" |: d
Обратите внимание: в файле htm стартового NCP обязательно должна быть ссылка на квест:
* s; w! H3 j: r* ], f$ M
  1. STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код
Для этого квеста больше ничего не надо. Все необходимое для корректной работы квеста уже добавили. Вот полный текст квеста:$ w4 ]. M4 E; ^( x
0 I2 m+ f8 \* {9 a
  1. if getCount(st) >= 4 :
    5 b! n  _* S2 V  u4 \/ F+ D; [
  2. completed(st)* x/ b" V1 p3 P8 j- \- \8 Y  @7 K
  3.   return" s: g1 Z1 s' ^( W" i$ o" p& v
  4. 8 H, _4 B6 O4 A: S+ z
  5. class Quest (JQuest):
      h6 h5 {/ V" ~% H+ Y  `/ E7 @, f
  6.   def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)
    % N  Z9 X' {+ ^6 E4 P  ?2 W
  7.   def onEvent (self,event,st):0 G$ r7 q) _5 _9 B: u' U
  8. id = st.getState()$ F" e- K9 V  t) S5 B
  9. if   id == CREATED  : st.setState(STARTED)9 S1 a% D6 i4 |
  10. elif id == COMPLETED: pass7 i: r. {# a6 |1 K' r3 a0 s( O' I) N
  11. elif id == STARTED  : check(st)/ Y; p6 p' E" E, B
  12. return- G* x5 k+ s" q0 a) ^
  13. / {0 _4 \  j/ }: E
  14. QUEST     = Quest(201,"Tutorial", "Tutorial quest")
    6 ?; f2 a' A% `( J
  15. CREATED   = State('Start',     QUEST)0 J" P0 Q2 c3 W) _5 \6 Y" t* }. u( U
  16. STARTED   = State('Started',   QUEST)
    8 B' \  ~* T$ P" u, ~
  17. COMPLETED = State('Completed', QUEST)- V$ ]& N4 y) ^0 }4 u) }1 E* v- p8 N
  18.   s, Q9 D! ]6 B
  19. QUEST.setInitialState(CREATED)
    7 v0 x) X1 z" J* ]
  20. QUEST.addStartNpc(7056)) H) O% @& n; V1 O* }( ]( K
  21. STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код
Теперь рассмотрим, как это работает.% h* V" O; f) b& v
Игрок подходит к начальному NCP (в данном случае 7056), нажимает на «Quest». Квест будет создан и состояние квеста перейдет к CREATED и игроку будет показана страничка Start.htm с описанием квеста. Тогда метод onEvent, поле открытия странички Start.htm переведет состояние квеста в STARTED и игроку будет показана страничка Started.htm, где будет опсание того, как найти keltirs и .т.д.
" Z. ^8 p) ?) V) R- u9 K/ P  x3 g+ \6 D2 q' F

) U% N+ N. c& u5 d3 Q# C* D+ GПри состоянии STARTED будет зарегистрирован дроп «fangs» при убийстве keltirs. Игрок может вернуться к стартовому NCP и спросить о квесте – метод onEvent будет вызван снова. Если у игрока не хватает необходимого количества предметов, то метод check() не переведет квест в следующее состояние и Started.htm будет показана снова. Но если игрок собрал необходимее количество предметов (в данном случае 4 клыка), то метод check() вызовет метод completed() который переведет квест в новое состояние COMPLETED, заберет все клыки, даст карту мира, т.к. это награда за квест, покажет Completed.htm и завершит квест.
% j( S/ u" R- w* i* l5 u; \
8 j3 d% w8 ?' u, ~# G4 H. O

; a: f% V: A( A3 F* s6 b" oТеперь давайте сделаем наш квест более похожим на то, что он должен из себя представлять.3 Y2 e- l; l$ q5 `: z0 |
Прежде всего у нас есть 3 метода для объявления их в Яве – onTalk, onKill и onEvent. Если методы onTalk и onKill не объявлены, то за них все будет делать метод onEvent, т.е. определять квестовых монстров и вызывать диалоги NCP. Есть примечание, методы onTalk и onKill будут вызывать только диалоги с NCP в зависимости от текущего состояния квеста. Метод onKill будет вызываться только тогда, когда мы убиваем квестового монстра.
+ U/ g5 U, z3 R/ N( Z% _$ c
2 |/ R; {  b+ }, a

) C1 Z/ }" @- F! e( u* J6 H% rДавайте рассмотрим как вызывается метод onKill при убийстве keltir в состоянии квеста STARTED:- d2 K  K& i9 a$ ~7 ]9 K8 W
  1. STARTED.addKillId(KELTIR_NPC_ID)
Скопировать код
и метод onKill в классе Quest:
! I0 U8 L9 d! E5 C
' ?- \# [/ g8 V% }' }2 Y+ f+ i
  1. class Quest (JQuest):
    % O- e& z6 J$ N! I7 F
  2.   ...) ?- V" x& \- ~  f; m
  3.   def onKill (self,npcId,st):+ e9 Q/ n  f+ b9 v/ `
  4. if npcId == KELTIR_NPC_ID:
    ! Z+ P8 o9 g2 K* k4 {
  5.    n = getCount(st)
    3 m6 Z$ f% p5 i  F; U
  6.    if   n == 0:
    ; n+ ]+ F  z$ s5 }/ J( X( P6 r3 L
  7.        return "Chat0.htm"
    ' u. _* x( u8 N, N+ e
  8.    elif n == 1:
      |" K+ K7 [6 D, g# @
  9.        return "Chat1.htm": H. p6 P9 j/ a+ @+ z; z' w. e
  10.    elif n >= 4:+ S# l; s$ F, I1 h  N
  11.        return "Chat4.htm"
    : ?: Q0 h. m( t* J" f8 u8 X2 J
  12.    return "Collected "+str(n)+" of 4 fangs"
    9 @$ M( r. e+ d9 t/ ]$ B1 f& [' Q
  13. return
Скопировать код
Метод onKill (а так же метод onTalk) имеет следующие параметры:( t3 K8 m& {- c( x

6 W7 W* h' t* z4 B' \

" |8 t+ p: m0 L. q$ Y• self – квест: X/ b0 H* J. D% q
• npcId – ID NCP, которого мы должны убивать (если это метод onTalk, то ID того NCP, с которым мы должны поговорить)., W" V4 h  f* [# O) k
• st – текущее состояние игрока.
3 o: O1 e5 d% A. D( w- u8 s
+ s/ M( L( Y# ]# f0 h

# j8 M: M  R, t) Z5 K9 KВ этом методе мы проверяем и отмечаем, является ли убитый NCP keltir’ом. В основном эта проверка не нужна, т.к. у нас только KELTIR_NPC_ID.$ ~# c' Y" J3 x, W
3 j* Y9 A  i$ l  L0 m$ X/ Q
5 a  q& C7 }& z, {7 G1 }" `
Затем проверяем количество предметов (в данном случае количество клыков), и если их вообще нет, то возвращаем строку "Chat0.htm", если только один предмет, то возвращаем строку "Chat1.htm", если же предметов 4 или больше, то "Chat4.htm". Если строка возвращена из методов onEvent, onKill или onTalk, то сервер покажет соответствующие htm. В Chat0.htm может иметь следующий текст: «Вы не имеете ни одного клыка, возвращайтесь позже, когда соберете 4 штуки и бла, бла, бла…», в Chat1.htm может быть следующий текст: «У Вас всего 1 клык, по этому соберите еще…». В Chat4.htm – «Вы собрали необходимое количество предметов, возвращайтесь к вашему тренеру, что бы завершить квест…»/ N/ J# M; @& x, E& C7 a/ k

$ M  _, U0 h) B0 |: p1 q+ _% f
! k# `: K4 s8 `6 F
Примечание: если в строка return начинается с "<html>", то будет показана страничка html с текстом, который стоит далее. Так вместо:. F$ f8 r9 ~+ U1 K( t
return "Chat4.htm". m+ Z$ |! a4 F; @' u  v6 Y7 p, C5 _

/ g7 \2 `  ~3 b: }0 W! w( |
! Z! U( ~8 ~6 m6 m2 ?, [
можно поставить:3 f6 S0 `. A: ?) x% v
  1. return "<html><body>Return to your trainer to complete the quest</body></html>"
Скопировать код
Так же если строка заканчивается без .htm или в начале нет <html>, то текст будет выведен, как системное сообщение в окне чата. В нашем случае мы сделаем так, что бы при каждом убийстве keltik выводилось системное сообщение: «Собрано N из 4-х клыков».5 O. L) v4 k2 ?4 |+ }1 B/ K  Q9 u
1 z9 @. T5 H; F" _# [1 f

: Y2 p% E2 w7 \+ k/ X) n5 XНаш код для onKill имеет один недостаток. Он будет постоянно показывать Chat0.htm, Chat1.htm и Chat4.htm, нам же необходимо, что бы Chat0.htm и Chat1.htm показывались только один раз. Как нам это сделать? С помощью переменных.* H& P9 z2 s7 D  e" \$ [2 `
/ A+ H; X( f: k' w9 U: o  T

& x: s" m* g, D5 F1 G1 j9 r) dВ каждом квесте строки могут храниться с помощью переменных. Эти переменные сохраняются в Вашей БД. В каждом методе мы можем назначить, прочитать и удалить переменные. Давайте изменим метод onKill, так что бы каждый диалог вызывался только один раз.$ j) n4 \$ F# t2 V+ p
  1. def onKill (self,npcId,st):0 o) g/ t3 x6 ?- x8 p! S
  2. if npcId == KELTIR_NPC_ID:2 \% S' T8 h$ o* b* Y4 v6 M; |8 J# j
  3. n = getCount(st)9 ]: O+ N2 P# ?
  4. if n == 0:
    ( X' D" M- x+ K" D+ M
  5. if st.get('chat0') == None :7 t; l% C2 W9 }' }3 |
  6. st.set("chat0", "true")% k* Y1 g" R* v4 |
  7. return "Chat0.htm"0 A- i4 c; z( F- e- J( D
  8. elif n == 1:8 D- E* {4 H$ o; f7 E* p, I
  9. if st.get('chat1') == None :
    . ~; F+ `+ G2 C$ _
  10. st.set("chat1", "true")
    1 T9 N+ y! H0 e0 T/ v2 n4 B# e
  11. return "Chat1.htm"
    6 M0 b5 z0 u+ d/ n3 @: `5 j
  12. elif n >= 4:
    / H8 ^+ E8 H- f" z7 d$ `- E
  13. return "Chat4.htm"4 [8 l% b: Q) ]! j! K3 y2 ]7 q! U  q
  14. return "Collected "+str(n)+" of 4 fangs"
    / `. |6 a% N# U/ R& O7 ~4 k! }4 l) 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.& d: b% v1 o2 t6 D; a- M
' w& |% X% b: ]8 f

; D. ?+ G) I# s2 VВот конечный рабочий вариант квеста:
1 M( z; \' W, _% g- \+ t; l! U
  1. import sys
    8 g' i# G. U( d( o) X+ T; ^; U
  2. from net.sf.l2j.gameserver.model.quest import State1 Y. Z# Y& s1 m) a) B
  3. from net.sf.l2j.gameserver.model.quest import QuestState, Z( h; R' K8 L, F2 c
  4. from net.sf.l2j.gameserver.model.quest.jython import QuestJython as JQuest* ~: [! Q) _1 G

  5. 2 \  ^$ N2 T' J4 i% k! ~
  6. KELTIR_NPC_ID = 12082* }! J( W/ k. [7 t9 ]& [. Z
  7. FANGS_ITEM_ID = 1859
    . T# d- @) k2 n3 G% N1 Y3 X2 K7 t
  8. DROP_RATE    = 500000) Q7 ?3 m# t/ m: E% ]7 z6 r

  9. + m0 f  a5 ?! R7 R9 ~: I
  10. WORLD_MAP_ITEM_ID = 1665; o+ h1 N. t, C" p7 B+ C9 T

  11. 6 ]% Z* P- z  F+ ]3 j
  12. def getCount(st) :
    * p) I- |6 M% I
  13. return st.getQuestItemsCount(FANGS_ITEM_ID)
    $ ~$ s! r0 o% E' J+ v
  14. 9 \+ b1 x  Q2 ?2 }% X" m
  15. def completed(st) :
    1 D* x1 j# ]# u. M
  16. st.setState(COMPLETED)( N1 `/ |7 ^/ Z
  17. st.clearQuestDrops()
    2 O7 A" ~5 F" D2 J
  18. st.takeItems(FANGS_ITEM_ID,-1)' S' u6 J7 P( G
  19. st.giveItems(WORLD_MAP_ITEM_ID,1)% s8 E4 x1 |1 _( y' R
  20. st.exitQuest(False)8 p2 N# @1 G! ]  r
  21. return6 _( y8 l  y+ B3 @/ N, I1 S1 ?
  22. % N6 J2 Y' x: g7 j* P6 R
  23. def check(st) :9 c0 S. Q: ~9 m! |  ^! w1 a
  24. if getCount(st) >= 4 :
    6 Z& e% W+ o3 `( k
  25. completed(st)+ q0 }! ~3 f$ V6 n
  26. return- M0 X9 n* T/ `* r

  27. , r$ T: \8 [" n* H
  28. class Quest (JQuest):4 A4 \2 t) d+ I
  29. 2 p/ M0 Y9 n4 [3 _9 l
  30. def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)
    # _( z4 ^/ a: j

  31. - N, x$ D  `6 R) Q  s; ~8 a" E
  32. def onEvent (self,event,st):
    . O. p" D  m8 f  M! Z
  33. id = st.getState()
    ! @0 `0 h7 N/ e& C  ^# G1 ]
  34. if id == CREATED : st.setState(STARTED)
    ( o, F' j+ D- y
  35. elif id == COMPLETED: pass
    $ J3 {+ K8 S0 O& t) T% W9 W
  36. elif id == STARTED : check(st)! S; f9 ]9 g! t2 L& T
  37. return
    8 ^2 l6 ~2 m* ?5 H8 F
  38. # n7 N1 R" A. D7 z# V0 x) B: }$ X
  39. def onKill (self,npcId,st):
    & n' z* y: l# r
  40. if npcId == KELTIR_NPC_ID:
    2 c3 f% F! ^; ^+ R$ {0 f( B$ m
  41. n = getCount(st): d! n( X( m% l3 e6 i* T
  42. if n == 0:
    1 g2 e6 P3 p% m
  43. if st.get('chat0') == None :4 e5 D2 N% `/ z/ }# d" \7 ?/ m
  44. st.set("chat0", "true"): k3 E/ m5 i3 S- [/ d
  45. return "Chat0.htm"
    ; U+ Y% \" b8 a: j
  46. elif n == 1:
    ( u% C3 I/ j, N" b0 K( M
  47. if st.get('chat1') == None :
    % V+ l" R5 k9 |0 X" F
  48. st.set("chat1", "true")* S  k4 N7 K$ `! `2 n5 w* u0 G' A, K6 R
  49. return "Chat1.htm"
    . E7 p) t* ^: V: R7 P6 R; x) v
  50. elif n >= 4:2 P0 i4 o( m; s( K7 \
  51. return "Chat4.htm"
    # D( i" r& A% i2 n) T3 ]$ k
  52. return "Collect "+str(n)+" of 4 fangs"0 a& `# f+ |* G4 D& d4 f" ]
  53. return
    " v! D8 Z8 _" _! D- x
  54. 7 J) @! p9 q$ b. D9 u) F/ Y
  55. QUEST    = Quest(201, "Tutorial", "Tutorial quest")$ q4 F: x0 E/ L- w8 G3 t# ^- c
  56. CREATED = State('Start',    QUEST)
    % y4 K$ j/ z9 |2 g( ]: T
  57. STARTED = State('Started', QUEST)
    4 n: V5 G4 F5 s, j3 V" x8 S) D
  58. COMPLETED = State('Completed', QUEST)
    , R8 l  k, B, \! }' U  V
  59. 7 T" @; K! ~& W
  60. QUEST.setInitialState(CREATED)
    & f+ W' ~& Q0 C
  61. QUEST.addStartNpc(7056)# P9 \) h+ i2 e  {  g  v3 Z% V
  62. QUEST.addStartNpc(7012): |/ s5 @% C! ^, T- ~
  63. QUEST.addStartNpc(7009)
    . @; J6 r( K7 i/ C
  64. QUEST.addStartNpc(7011)
    - x( T1 e  E  S! A/ k% a
  65. 0 c1 L5 N% I3 D; G# @$ `
  66. STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
    9 I2 D- H+ S/ |
  67. STARTED.addKillId(KELTIR_NPC_ID)1 s7 u* p( ^3 a, h# n4 {
  68. STARTED.addTalkId(7056)7 Z) s5 a( W  `& K2 O
  69. STARTED.addTalkI d(7012)4 U4 X+ N+ F* x1 ~8 U, J6 p& Z
  70. STARTED.addTalkId(7009)
    0 q' T7 c& T  Y8 g
  71. STARTED.addTalkId(7011)
Скопировать код
% d8 T$ M# \" V# l3 L6 B

' }1 i- l' W# m( t# {& V+ h
Чтобы ответить, вам надо авторизироваться в системе Вход | Зарегистрироваться

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

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

638638758

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

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

admin@artace.ru Онлайн

QR-код

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