Top.Mail.Ru

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

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

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

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

x
Хроники        Interlude
! [; D! \8 {8 `+ D$ mСборка        L2j
2 k( t, m2 d% `9 {& YОбратите внимание: в файле htm стартового NCP обязательно должна быть ссылка на квест:
( Y! I2 M! l& o
  1. STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код
Для этого квеста больше ничего не надо. Все необходимое для корректной работы квеста уже добавили. Вот полный текст квеста:( H' }; U' o: T  ?1 y; J7 i

& A) ~2 O9 u+ u/ M1 V1 w  A" _% U
  1. if getCount(st) >= 4 :
    ) l. ^" C" v3 R) e
  2. completed(st)4 \3 E! R! G9 M8 {9 M
  3.   return
    ( g- E6 U! z0 E3 D& q" I

  4. 4 J' ^* z" Q+ V5 i: ?8 [5 f
  5. class Quest (JQuest):
    * H/ A7 D+ Y) I/ N# ?9 D
  6.   def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr): a9 x1 c4 }! O0 ]/ s7 c6 ~3 X) l: q
  7.   def onEvent (self,event,st):0 ?& p$ I& ^0 b6 D
  8. id = st.getState()
    2 b- o& p* U7 X/ H$ v" U& {
  9. if   id == CREATED  : st.setState(STARTED)
    # C  c1 e" Q* h. s2 s$ d
  10. elif id == COMPLETED: pass
    9 Q: {/ T/ n% ]# l6 C9 G' [: f  N
  11. elif id == STARTED  : check(st)
    $ h8 F3 Z( ]/ p9 D
  12. return
    , j' q( ]: e  y! X

  13. ( z3 N; w, b6 C9 g' O/ U3 P3 r
  14. QUEST     = Quest(201,"Tutorial", "Tutorial quest")
    $ ^! G/ e. F; W3 e# L4 F$ H
  15. CREATED   = State('Start',     QUEST)/ Q( a8 m$ v7 u
  16. STARTED   = State('Started',   QUEST)8 f0 S+ P* [. R- x+ T
  17. COMPLETED = State('Completed', QUEST)
    . a" S' f* g% k5 w( Y( ~. h

  18. % B" G0 W( _) F0 b" S# j
  19. QUEST.setInitialState(CREATED)
    ; ]/ I; Z4 P) a5 I
  20. QUEST.addStartNpc(7056)5 I) y0 L: _- ?# N3 }1 }8 Q* [3 W4 Z& C
  21. STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код
Теперь рассмотрим, как это работает.  p: _; c0 p0 m- S
Игрок подходит к начальному NCP (в данном случае 7056), нажимает на «Quest». Квест будет создан и состояние квеста перейдет к CREATED и игроку будет показана страничка Start.htm с описанием квеста. Тогда метод onEvent, поле открытия странички Start.htm переведет состояние квеста в STARTED и игроку будет показана страничка Started.htm, где будет опсание того, как найти keltirs и .т.д.
# \& E( B* P; d# a* ]' w, k1 C' q! |0 j5 E1 ?

7 f1 I8 x" v; T# E! `  G- c& BПри состоянии STARTED будет зарегистрирован дроп «fangs» при убийстве keltirs. Игрок может вернуться к стартовому NCP и спросить о квесте – метод onEvent будет вызван снова. Если у игрока не хватает необходимого количества предметов, то метод check() не переведет квест в следующее состояние и Started.htm будет показана снова. Но если игрок собрал необходимее количество предметов (в данном случае 4 клыка), то метод check() вызовет метод completed() который переведет квест в новое состояние COMPLETED, заберет все клыки, даст карту мира, т.к. это награда за квест, покажет Completed.htm и завершит квест.: i1 N0 c) t  a% ~4 s
3 s/ u! O( K1 T' O% B
0 ~. g: _$ ?4 w1 c/ ?) h/ O
Теперь давайте сделаем наш квест более похожим на то, что он должен из себя представлять.& q* v$ C( o+ J1 t
Прежде всего у нас есть 3 метода для объявления их в Яве – onTalk, onKill и onEvent. Если методы onTalk и onKill не объявлены, то за них все будет делать метод onEvent, т.е. определять квестовых монстров и вызывать диалоги NCP. Есть примечание, методы onTalk и onKill будут вызывать только диалоги с NCP в зависимости от текущего состояния квеста. Метод onKill будет вызываться только тогда, когда мы убиваем квестового монстра.
) [( A/ f/ r9 e9 N8 _
- p2 ~  ~' x0 |

6 w# t7 ~  k# P" C2 V  o) OДавайте рассмотрим как вызывается метод onKill при убийстве keltir в состоянии квеста STARTED:
4 N, X  i6 B9 e: o
  1. STARTED.addKillId(KELTIR_NPC_ID)
Скопировать код
и метод onKill в классе Quest:
. {/ h7 R2 ?  k1 |, |% c* ~8 L* Z) k! d
  1. class Quest (JQuest):9 L7 @* i4 P, R( B6 |; z
  2.   ...
    - P4 K% W( I2 y# U. j6 Z
  3.   def onKill (self,npcId,st):7 E; l/ J! j7 r) p
  4. if npcId == KELTIR_NPC_ID:" A. |8 r/ R/ [8 `5 D7 e
  5.    n = getCount(st)3 K$ o3 r' _% P  s! i' n1 l8 _
  6.    if   n == 0:; x3 f+ G: L0 {( w9 @) C
  7.        return "Chat0.htm"( D8 t8 Z/ [& g3 V+ T2 |5 F
  8.    elif n == 1:
    2 q1 [9 O0 d& b5 e2 ]
  9.        return "Chat1.htm"' w) c( l6 h! E' M( C7 O
  10.    elif n >= 4:
    4 N8 _8 K3 z& j/ q0 n+ @' X6 \, h
  11.        return "Chat4.htm"# T5 b# H1 M. |: ~
  12.    return "Collected "+str(n)+" of 4 fangs"& ]% a% t; R  X
  13. return
Скопировать код
Метод onKill (а так же метод onTalk) имеет следующие параметры:
5 L$ N2 [" W" R( S5 _* Q  E. R. e4 r+ U. Z
" S5 i% c  R7 @! ]
• self – квест
8 q! [7 c; E0 E) i9 a2 }' P0 o• npcId – ID NCP, которого мы должны убивать (если это метод onTalk, то ID того NCP, с которым мы должны поговорить).
/ B: t; P, {  y4 v- e0 Y• st – текущее состояние игрока.. i. r+ K. f2 L* Z: Q
! Q. h/ l9 \7 ]+ G6 S

- `' g; z* L# H; ?0 xВ этом методе мы проверяем и отмечаем, является ли убитый NCP keltir’ом. В основном эта проверка не нужна, т.к. у нас только KELTIR_NPC_ID.
. j* p. o& i6 |/ C2 m8 @
% [* n. H1 R+ n& O4 Z+ d
  F$ c/ O$ j" w6 Y4 w) H* x
Затем проверяем количество предметов (в данном случае количество клыков), и если их вообще нет, то возвращаем строку "Chat0.htm", если только один предмет, то возвращаем строку "Chat1.htm", если же предметов 4 или больше, то "Chat4.htm". Если строка возвращена из методов onEvent, onKill или onTalk, то сервер покажет соответствующие htm. В Chat0.htm может иметь следующий текст: «Вы не имеете ни одного клыка, возвращайтесь позже, когда соберете 4 штуки и бла, бла, бла…», в Chat1.htm может быть следующий текст: «У Вас всего 1 клык, по этому соберите еще…». В Chat4.htm – «Вы собрали необходимое количество предметов, возвращайтесь к вашему тренеру, что бы завершить квест…»4 s+ R4 F1 `/ E" n  {) [

1 [6 G2 |. c9 A& \2 i
; N) Q/ _4 I/ _( v$ a+ x' t7 y
Примечание: если в строка return начинается с "<html>", то будет показана страничка html с текстом, который стоит далее. Так вместо:
  U+ a& I+ u" ?+ yreturn "Chat4.htm"
: k, D: K! ]( e$ P+ k! q$ X2 P) @0 @: ?
8 Q. h3 g% G/ c8 @' \& @5 ?. f% w7 z2 j
можно поставить:
/ }9 B3 i8 c4 v/ x4 T
  1. return "<html><body>Return to your trainer to complete the quest</body></html>"
Скопировать код
Так же если строка заканчивается без .htm или в начале нет <html>, то текст будет выведен, как системное сообщение в окне чата. В нашем случае мы сделаем так, что бы при каждом убийстве keltik выводилось системное сообщение: «Собрано N из 4-х клыков».# @& [- ^0 }  B: U, x9 b
- Q( q" |2 K0 E  x

! `7 h  V% E% RНаш код для onKill имеет один недостаток. Он будет постоянно показывать Chat0.htm, Chat1.htm и Chat4.htm, нам же необходимо, что бы Chat0.htm и Chat1.htm показывались только один раз. Как нам это сделать? С помощью переменных.
" y1 t7 j/ z* ]  w. b' o& `
8 m  Z  M1 X  X  j

8 L6 `9 P8 ]' F; j- UВ каждом квесте строки могут храниться с помощью переменных. Эти переменные сохраняются в Вашей БД. В каждом методе мы можем назначить, прочитать и удалить переменные. Давайте изменим метод onKill, так что бы каждый диалог вызывался только один раз.' l2 ~; S2 @1 S# R% r4 _
  1. def onKill (self,npcId,st):/ w  o" U( c" H3 z) i! |+ B
  2. if npcId == KELTIR_NPC_ID:
    1 N8 W1 E& I5 m6 i0 B7 j8 U
  3. n = getCount(st)
    " n0 S1 r* b) {2 K/ W
  4. if n == 0:
    5 D! v4 g1 G2 J  @1 Z
  5. if st.get('chat0') == None :
    6 Y+ e7 u: D' c6 B/ a3 N
  6. st.set("chat0", "true"); h/ T* p5 q! g1 H
  7. return "Chat0.htm"% L0 [1 ~* l( s* ~* Y4 P3 M: e
  8. elif n == 1:: V& ~6 m; w2 M7 o; r4 l
  9. if st.get('chat1') == None :3 S1 m$ s% a& x' Y1 a
  10. st.set("chat1", "true")
    # [( n8 I5 s# ^7 L* x
  11. return "Chat1.htm"
    3 ^. E; i; J$ G- W) k+ X8 |6 X
  12. elif n >= 4:
    4 f( l+ w4 ]- J3 g4 R9 y
  13. return "Chat4.htm"
    5 I* Y- {: ^7 J% M2 [
  14. return "Collected "+str(n)+" of 4 fangs"
    6 p* L$ P/ b% x. I% ]
  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.9 ]; D' J+ G) w$ F! P

( Z9 w' X6 V, E

( H; C" ^# q( l% F- x9 A5 {/ DВот конечный рабочий вариант квеста:
( u, t: W' T/ ]1 [! S6 x2 b/ U) Q
  1. import sys
    1 @! S3 F$ l# L$ V3 `" h
  2. from net.sf.l2j.gameserver.model.quest import State' k: u8 a8 b& [$ a* _
  3. from net.sf.l2j.gameserver.model.quest import QuestState
    ) O  D$ k( [( I3 Q  i
  4. from net.sf.l2j.gameserver.model.quest.jython import QuestJython as JQuest8 f4 A& V% z7 X

  5. " `& y# A. k0 j, }9 m, L1 ]# _2 G8 v
  6. KELTIR_NPC_ID = 12082
    + f3 y$ p/ Y3 B3 \* Q6 x! P$ j
  7. FANGS_ITEM_ID = 1859( [( Y5 X' v$ ?) a
  8. DROP_RATE    = 5000001 G- q& q% D# d" u9 o/ W: `6 O/ {

  9. / n9 A! ^+ j- `& t
  10. WORLD_MAP_ITEM_ID = 1665
    8 }" [: Z7 l( C& t& |# _

  11.   R; [% s6 M% O, @) S6 I/ `0 r
  12. def getCount(st) :
    , V' V# X0 y6 X: D0 w
  13. return st.getQuestItemsCount(FANGS_ITEM_ID)
    & I9 s& @9 C* m
  14. 8 G% i( B8 l, y5 _
  15. def completed(st) :
    ' v! W- v/ s8 g! p* \; L
  16. st.setState(COMPLETED)
    ) o3 F8 o, Y/ V% s
  17. st.clearQuestDrops()
    ( B$ F4 F1 ^2 b  Y# u
  18. st.takeItems(FANGS_ITEM_ID,-1). ]1 j, r: [1 |' f7 ?/ n$ X0 [$ T2 ?
  19. st.giveItems(WORLD_MAP_ITEM_ID,1)6 `0 c* y& c8 ~0 h% b& X# \
  20. st.exitQuest(False)
    & N0 u3 b& \  V
  21. return
    ) ~4 q; l1 D! S) ]

  22. 9 h2 k6 d: c3 V" M
  23. def check(st) :
    8 c; w( f' w: C- v$ h9 P: v
  24. if getCount(st) >= 4 :3 [, R6 I2 f) U) {& Z
  25. completed(st)
    6 N7 @, n# f% Z8 G$ F1 C' }5 S
  26. return+ {$ F) X  \& q8 U
  27. 0 |. [5 d  }+ ~& ^* C/ z
  28. class Quest (JQuest):
    8 W9 B7 ]8 N$ T/ k

  29. , ]' ^" a& Y8 }
  30. def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)
    : ?6 n4 g) Y; L
  31. 2 m3 A. Q) v0 x9 Q+ ~+ m/ f5 C
  32. def onEvent (self,event,st):6 Y- k. I" z- l- H6 S' B4 q
  33. id = st.getState()
    8 L. ]* p, ?9 K$ j. Z& t& Y6 G  g
  34. if id == CREATED : st.setState(STARTED)* A6 G4 [! j+ z9 w7 e# _
  35. elif id == COMPLETED: pass( O4 o( {& F0 B6 i+ s
  36. elif id == STARTED : check(st)
    . S7 w$ r0 v( x
  37. return/ ~" d7 J( Y; G3 X8 n7 h/ a
  38. # Y9 Y& N2 A$ {$ N3 ~
  39. def onKill (self,npcId,st):9 |" {4 y% D3 {8 l% [2 Y0 w
  40. if npcId == KELTIR_NPC_ID:1 v+ ?1 F* ]: n5 I; t  O
  41. n = getCount(st)
    $ Q* @" G& q% B$ b$ h' z
  42. if n == 0:  g! H: }4 c2 y. @" \, h
  43. if st.get('chat0') == None :
    6 b% T( @" w) X/ ^
  44. st.set("chat0", "true")
    1 J, y: d; Y9 c4 s( _
  45. return "Chat0.htm"0 ^0 b/ V4 s3 P0 c& w
  46. elif n == 1:
    ) S  N, X5 {" K7 h! S' d
  47. if st.get('chat1') == None :
    * ]4 y1 I7 C3 e6 n/ W$ c
  48. st.set("chat1", "true")
    $ H- |& g- {0 Q1 u/ Q4 S1 u# \/ Q
  49. return "Chat1.htm"
    : Y: J7 c4 P: n# a+ h; H" u* g" p
  50. elif n >= 4:  p2 m9 b; n9 E% y" ?
  51. return "Chat4.htm"/ N/ O) R2 V" ?+ e
  52. return "Collect "+str(n)+" of 4 fangs"( ^8 v7 i8 ^2 ]8 r9 M& a/ ]" A8 `/ G
  53. return
    & s; }+ t+ l  Q: L; ^, U
  54. " |0 i  Q4 X- s1 ^8 s& a" _7 X
  55. QUEST    = Quest(201, "Tutorial", "Tutorial quest")
    & j- J7 H7 i/ \5 D& D  H* x# Y  H
  56. CREATED = State('Start',    QUEST)
    2 Z4 v; `2 V2 q# H
  57. STARTED = State('Started', QUEST)
    3 M: T& D- T2 }- i* g
  58. COMPLETED = State('Completed', QUEST)
    - j9 p( q( O) v, h  ~

  59. ; ^9 s6 Z" B1 c& ~$ P, N8 E% h1 I; T
  60. QUEST.setInitialState(CREATED); z( \* P4 u, p  \/ J4 s
  61. QUEST.addStartNpc(7056); ^7 E% ?9 C& h: H
  62. QUEST.addStartNpc(7012)) H/ M7 _  z3 s0 {5 m
  63. QUEST.addStartNpc(7009)
    # N9 M6 I7 u5 }7 ^7 r* L8 s1 e% v
  64. QUEST.addStartNpc(7011)
    & f& Y& `+ k: \* G
  65. , \, x+ D  W/ ?, j
  66. STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
    " ?8 i/ f# ]6 v7 r2 O0 o  z. T2 B# {
  67. STARTED.addKillId(KELTIR_NPC_ID): K  b, S! X4 U6 @7 n
  68. STARTED.addTalkId(7056)
    + J3 v$ |/ c; D) q: b3 u+ K
  69. STARTED.addTalkI d(7012)
    6 t- t2 B2 ~7 [9 V1 ?! G
  70. STARTED.addTalkId(7009)( d6 y7 j& z, H! q& p
  71. STARTED.addTalkId(7011)
Скопировать код
- j. a3 a- o9 o% o9 R/ O

  j0 k- o9 f/ d  f6 b: F
Чтобы ответить, вам надо авторизироваться в системе Вход | Зарегистрироваться

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

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

638638758

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

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

admin@artace.ru Онлайн

QR-код

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