Top.Mail.Ru

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

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

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

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

x
Хроники        Interlude
/ Z! y' C$ a2 rСборка        L2j
, m! ]- z% g4 H1 ^' n7 E0 b! HОбратите внимание: в файле htm стартового NCP обязательно должна быть ссылка на квест:4 B( D$ p! u# P1 i5 y: K
  1. STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код
Для этого квеста больше ничего не надо. Все необходимое для корректной работы квеста уже добавили. Вот полный текст квеста:
! U0 `9 h; t# |0 I
4 r4 [8 c& M9 ?% K1 j
  1. if getCount(st) >= 4 :
    - k0 F5 G, ]5 A- E3 |9 `# Z4 P
  2. completed(st): j1 b3 @$ _/ P7 v: ]7 M
  3.   return1 |5 U3 M7 l8 ]& A+ o. Z9 T
  4. ) l) E, n; `! _$ u
  5. class Quest (JQuest):- t8 Q( p' P& j- k( G# u
  6.   def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)3 `9 |+ t8 V) W) }6 C
  7.   def onEvent (self,event,st):/ _- v+ D/ Q$ z2 M, F8 I
  8. id = st.getState()6 ]: ]3 d$ \6 L( I4 |% p4 Z' E
  9. if   id == CREATED  : st.setState(STARTED)
    % |$ t) y6 X& S/ ]# }: ~$ W" f
  10. elif id == COMPLETED: pass& h& ]9 e) [) H0 `  v
  11. elif id == STARTED  : check(st)
    5 v2 m! K; b5 ~- w) u1 [
  12. return9 a" O" [3 J! B( Z+ o
  13. ; z0 U" }  D" m/ ^
  14. QUEST     = Quest(201,"Tutorial", "Tutorial quest")
    , x. k3 j* Q7 g' k, n" t
  15. CREATED   = State('Start',     QUEST)
    / q! L; M3 [$ p, ~# b
  16. STARTED   = State('Started',   QUEST)
    ; v/ m3 r) `2 ~4 s' m9 m" g9 D
  17. COMPLETED = State('Completed', QUEST)4 _' h* S1 R4 y- W
  18. 6 T+ P# l; F4 Y0 ^) s& {, X
  19. QUEST.setInitialState(CREATED)) l$ _/ |: i6 _3 ~, B3 B6 Z- H* v
  20. QUEST.addStartNpc(7056); G, {' k- K9 w
  21. STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код
Теперь рассмотрим, как это работает.
0 |9 v: N0 R" U/ y5 }% xИгрок подходит к начальному NCP (в данном случае 7056), нажимает на «Quest». Квест будет создан и состояние квеста перейдет к CREATED и игроку будет показана страничка Start.htm с описанием квеста. Тогда метод onEvent, поле открытия странички Start.htm переведет состояние квеста в STARTED и игроку будет показана страничка Started.htm, где будет опсание того, как найти keltirs и .т.д.( Z9 ?. C4 d" \3 R
1 ?$ U3 v- F9 W6 m5 l; v, G5 E1 m
4 y/ b2 u8 b. ^4 K; ~& ]' {
При состоянии STARTED будет зарегистрирован дроп «fangs» при убийстве keltirs. Игрок может вернуться к стартовому NCP и спросить о квесте – метод onEvent будет вызван снова. Если у игрока не хватает необходимого количества предметов, то метод check() не переведет квест в следующее состояние и Started.htm будет показана снова. Но если игрок собрал необходимее количество предметов (в данном случае 4 клыка), то метод check() вызовет метод completed() который переведет квест в новое состояние COMPLETED, заберет все клыки, даст карту мира, т.к. это награда за квест, покажет Completed.htm и завершит квест.4 V0 A: W* j: _' @2 k

. a6 L. U1 B9 G

/ C9 s+ r% G) eТеперь давайте сделаем наш квест более похожим на то, что он должен из себя представлять.
& b$ J5 B* l4 y2 k' PПрежде всего у нас есть 3 метода для объявления их в Яве – onTalk, onKill и onEvent. Если методы onTalk и onKill не объявлены, то за них все будет делать метод onEvent, т.е. определять квестовых монстров и вызывать диалоги NCP. Есть примечание, методы onTalk и onKill будут вызывать только диалоги с NCP в зависимости от текущего состояния квеста. Метод onKill будет вызываться только тогда, когда мы убиваем квестового монстра.3 O, q0 e+ ^9 Y5 L! a) A
% P6 w) j, o4 S

7 w3 ?1 \  G- _9 xДавайте рассмотрим как вызывается метод onKill при убийстве keltir в состоянии квеста STARTED:1 j- o( O$ I" H5 Y  U8 p% F# j' g% ~
  1. STARTED.addKillId(KELTIR_NPC_ID)
Скопировать код
и метод onKill в классе Quest:
$ U' Y  H; z9 h, ~3 u. v% |' L/ I0 o" d- u$ B5 b. c  j3 a% k
  1. class Quest (JQuest):
    & @7 b$ Y0 y' A$ [! n
  2.   .... F& q; C1 s! o/ g
  3.   def onKill (self,npcId,st):
    # y' }$ Y/ n: i! H
  4. if npcId == KELTIR_NPC_ID:4 ^# f* H9 ~6 j$ @2 j0 l1 q( i, @
  5.    n = getCount(st)' h. p8 z; M5 V7 @) r
  6.    if   n == 0:
    $ @  [7 b1 n( J- m! ]7 |
  7.        return "Chat0.htm"" I; \4 [: y! \2 C
  8.    elif n == 1:
    . Z* @; Y+ k: g- O
  9.        return "Chat1.htm"+ ]( D, h  M+ b) z' y9 l
  10.    elif n >= 4:8 S3 i9 p' V- O$ ?$ J% [3 q
  11.        return "Chat4.htm"
    . g2 o% U* x. c
  12.    return "Collected "+str(n)+" of 4 fangs"
    % {% F" a, f. I. d- J* \
  13. return
Скопировать код
Метод onKill (а так же метод onTalk) имеет следующие параметры:) o  n3 O! U& J1 E; \

4 G8 l6 S* X, R6 N

6 W, b" C# z5 s& E5 Y. I• self – квест
4 D1 f, |( z( R' ^3 u$ D/ o• npcId – ID NCP, которого мы должны убивать (если это метод onTalk, то ID того NCP, с которым мы должны поговорить).
4 u) d2 }' V; w9 y# d: x, \• st – текущее состояние игрока.
7 C5 W5 h) r  Z2 d, i
5 i, E/ B0 M1 V/ F+ T: I- R
) s2 P/ V1 e+ e1 i( o+ z% j
В этом методе мы проверяем и отмечаем, является ли убитый NCP keltir’ом. В основном эта проверка не нужна, т.к. у нас только KELTIR_NPC_ID.2 l" N6 ?; A1 G7 l3 Y
: L; S; h! P6 n
/ N" B9 W4 F! }' O! x
Затем проверяем количество предметов (в данном случае количество клыков), и если их вообще нет, то возвращаем строку "Chat0.htm", если только один предмет, то возвращаем строку "Chat1.htm", если же предметов 4 или больше, то "Chat4.htm". Если строка возвращена из методов onEvent, onKill или onTalk, то сервер покажет соответствующие htm. В Chat0.htm может иметь следующий текст: «Вы не имеете ни одного клыка, возвращайтесь позже, когда соберете 4 штуки и бла, бла, бла…», в Chat1.htm может быть следующий текст: «У Вас всего 1 клык, по этому соберите еще…». В Chat4.htm – «Вы собрали необходимое количество предметов, возвращайтесь к вашему тренеру, что бы завершить квест…»
% m: g* H, ~8 P4 i+ e+ L3 o* j4 I' k0 [5 S

+ T6 }- U* ?4 c+ m! o6 i. HПримечание: если в строка return начинается с "<html>", то будет показана страничка html с текстом, который стоит далее. Так вместо:
- {6 u; `7 p# L$ @" _- Treturn "Chat4.htm"8 U) F, N" G+ Z

8 b" U9 D5 A. d2 ?% x

9 ~; t0 G% K: nможно поставить:. V8 s, K. Z9 a. `
  1. return "<html><body>Return to your trainer to complete the quest</body></html>"
Скопировать код
Так же если строка заканчивается без .htm или в начале нет <html>, то текст будет выведен, как системное сообщение в окне чата. В нашем случае мы сделаем так, что бы при каждом убийстве keltik выводилось системное сообщение: «Собрано N из 4-х клыков».
, F+ C) h9 u! d8 _1 I8 N6 a
3 ]' Y, M$ C0 ]
( J3 C0 c$ C4 x" {+ R
Наш код для onKill имеет один недостаток. Он будет постоянно показывать Chat0.htm, Chat1.htm и Chat4.htm, нам же необходимо, что бы Chat0.htm и Chat1.htm показывались только один раз. Как нам это сделать? С помощью переменных.
# \2 s' \! r' _+ [
9 K: y' |' {- M$ e" \6 L

, Y% o6 D, h7 T/ o( V; }В каждом квесте строки могут храниться с помощью переменных. Эти переменные сохраняются в Вашей БД. В каждом методе мы можем назначить, прочитать и удалить переменные. Давайте изменим метод onKill, так что бы каждый диалог вызывался только один раз.
9 v# c4 ]4 ^7 z" ]* ~; L
  1. def onKill (self,npcId,st):, L' ]- G* M* i3 e
  2. if npcId == KELTIR_NPC_ID:
    - ~8 N+ N1 h' g/ l
  3. n = getCount(st)
    ! D- V; H% y! Y. C( S
  4. if n == 0:
    4 k0 v3 Q* I$ K* C* a
  5. if st.get('chat0') == None :
    $ H. F- {) |4 C+ m
  6. st.set("chat0", "true")
    8 A% \9 o# C& c- y
  7. return "Chat0.htm", T1 W2 w' s5 w+ S5 |8 G. [: A
  8. elif n == 1:! X9 S6 K: S9 W3 H2 U) k
  9. if st.get('chat1') == None :
    & l2 F9 y1 I$ E1 I9 r0 Y% F$ s
  10. st.set("chat1", "true")1 B9 P" c$ M, C' k8 a
  11. return "Chat1.htm", J8 m$ o& O7 y- u1 E
  12. elif n >= 4:* d5 D7 B4 L% w5 {5 V
  13. return "Chat4.htm"6 l3 S' s5 y6 |$ n) l6 O" @3 P
  14. return "Collected "+str(n)+" of 4 fangs"* E  x" O1 J8 {' W. [) L3 W0 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.
5 W! T4 D2 P/ ]  `. y' y7 o% p" c# R9 S3 s3 j
2 ?0 f& k3 \! l
Вот конечный рабочий вариант квеста:
% f* X0 u( W4 l, h* X1 v
  1. import sys
    ( h0 y  u0 Z+ ?. U2 [* \8 @& |
  2. from net.sf.l2j.gameserver.model.quest import State/ t+ R/ l( r4 v5 [
  3. from net.sf.l2j.gameserver.model.quest import QuestState
    9 Q/ Z* v# I6 E" M; \. L% c' N
  4. from net.sf.l2j.gameserver.model.quest.jython import QuestJython as JQuest
    9 J) k7 K& Z( Q3 q1 }

  5. 0 B& A5 F* I" f$ X$ t# A$ s
  6. KELTIR_NPC_ID = 12082
    ) r  w8 L2 [; \" |& t! q
  7. FANGS_ITEM_ID = 1859# ]: F1 g- O$ |1 x3 Z8 h# P( B1 x
  8. DROP_RATE    = 500000& o% X1 q. Z$ j- `0 i
  9. # f6 i% D7 e. n/ E2 H; _  J* X) w
  10. WORLD_MAP_ITEM_ID = 1665
    ' K: v$ z% z( Q3 `

  11. ' b0 k* N  @; ]4 n6 z0 W0 u
  12. def getCount(st) :
    1 b2 Y+ [% p8 `3 \; X4 P7 y/ C# v
  13. return st.getQuestItemsCount(FANGS_ITEM_ID)
    " H5 i/ q9 t4 D$ ]
  14. " B" ]3 u2 c# c6 }
  15. def completed(st) :3 V/ q- P0 ^5 n' i0 v- E  V1 l
  16. st.setState(COMPLETED)$ E8 @- v2 i5 ]7 E1 B5 H
  17. st.clearQuestDrops()$ K1 R8 o# U( t. K; x6 c4 M
  18. st.takeItems(FANGS_ITEM_ID,-1)! h4 k! v( `& d0 |$ o( X' Q! u
  19. st.giveItems(WORLD_MAP_ITEM_ID,1)
    6 t' s; w' u6 Q  H% B6 p$ C8 L: o* i% k
  20. st.exitQuest(False)/ d4 u- v4 r5 P/ M8 p$ Q5 V  s* m
  21. return
    + a3 u6 G! H# X' _! Z

  22. * w; v5 w$ E/ B- W, B) A3 u5 D
  23. def check(st) :
    ( b0 _  m+ d3 o% D) `0 Y
  24. if getCount(st) >= 4 :- y+ l2 B8 B7 g' ?+ d) N, H
  25. completed(st)7 u0 \( X- l: Y8 X! h. i5 r) R
  26. return$ x3 v5 L. O; X* {. s* I; s

  27. 4 t6 g7 w  F! c3 |) M; Q
  28. class Quest (JQuest):) p- ?8 b# ^: c9 _* e: K( J
  29. # J. H( |4 V& B' s. N
  30. def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)
    3 j4 V* o- o$ L5 d" t- Q
  31. 8 N9 G/ s. {. Q: i- s. l: Z
  32. def onEvent (self,event,st):; _3 G+ `# y+ Q, l) D6 c1 u
  33. id = st.getState()8 ^% ^3 d' A% t: ~' M2 \
  34. if id == CREATED : st.setState(STARTED)
      H  M4 P. R% O$ }' A
  35. elif id == COMPLETED: pass* a8 x& o) m) b8 D1 A
  36. elif id == STARTED : check(st)! Q' c$ s, K- A' g" v$ b/ C
  37. return
    0 U9 G% s, y. N2 W: H

  38. / C, f* ^; i& ]# B  x
  39. def onKill (self,npcId,st):
    % p3 g& E/ }( q
  40. if npcId == KELTIR_NPC_ID:5 d0 I4 L0 n5 s" W
  41. n = getCount(st)3 q) D# ?8 k' }+ z' E
  42. if n == 0:
    5 ^2 {9 [5 ?4 _7 K! p0 K
  43. if st.get('chat0') == None :5 t' M5 E- V+ S' d
  44. st.set("chat0", "true")
    . Q/ Z6 B$ _% d; h
  45. return "Chat0.htm"' |% P( t) h+ R* e: y4 \
  46. elif n == 1:
    4 L7 q  D3 c/ P
  47. if st.get('chat1') == None :4 w* r# q, O0 }' v- k' q
  48. st.set("chat1", "true")" O( U! A0 S+ L$ b$ A" k8 C+ [
  49. return "Chat1.htm"
    ' }$ Q0 h, ^' T* v3 Y
  50. elif n >= 4:. v9 ]. b; B0 h. `1 b3 e1 O* v
  51. return "Chat4.htm"
    5 p* g2 h3 I$ e6 G8 R
  52. return "Collect "+str(n)+" of 4 fangs"+ c, s2 U( @9 x, L
  53. return
      B. M9 ^/ N+ [' v
  54. 4 [  I3 f' s! ?: _( s; @* L4 T
  55. QUEST    = Quest(201, "Tutorial", "Tutorial quest")3 U1 b5 N. _/ d- R9 S7 u3 j
  56. CREATED = State('Start',    QUEST), L* \$ A9 K5 E) g9 H
  57. STARTED = State('Started', QUEST)3 C3 p2 f. M# {' Z( U! I1 S% ]
  58. COMPLETED = State('Completed', QUEST)
    8 v" x) l# Z+ T4 h( F1 p3 P

  59. 0 {" L4 n5 w) s& D
  60. QUEST.setInitialState(CREATED)- O& C4 b  K8 I  _8 V
  61. QUEST.addStartNpc(7056)
    1 s- E  Q' |3 V" v
  62. QUEST.addStartNpc(7012)
    . T) m9 s7 Z- [, p5 t6 ~
  63. QUEST.addStartNpc(7009)2 S. M! A7 }, m6 G3 {
  64. QUEST.addStartNpc(7011)
    3 b! H9 f4 D2 T5 p8 v

  65. 6 V3 U, x1 o, \' j; n9 M$ j; e
  66. STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
    # W% R" {' K4 v* Y
  67. STARTED.addKillId(KELTIR_NPC_ID)
    0 {/ M/ U/ W5 A% W( H! a% C
  68. STARTED.addTalkId(7056)  U" y8 ?# A" O7 n2 H; J
  69. STARTED.addTalkI d(7012)
    " r  A" k5 a/ X6 ?) q( j$ E2 _4 K7 B
  70. STARTED.addTalkId(7009)
    7 P6 P! ~: ^$ V( n" V" c" u
  71. STARTED.addTalkId(7011)
Скопировать код

& S3 m" ?4 z9 K4 r
+ \2 }& ]' |! E: |/ [, e! O3 I
Чтобы ответить, вам надо авторизироваться в системе Вход | Зарегистрироваться

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

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

638638758

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

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

admin@artace.ru Онлайн

QR-код

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