Top.Mail.Ru

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

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

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

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

x
Хроники        Interlude
; e7 J" `- M2 _2 _8 gСборка        L2j7 A7 f- X. j* l4 n
Обратите внимание: в файле htm стартового NCP обязательно должна быть ссылка на квест:6 z) w: E! g! O- c# I: O$ U/ D
  1. STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код
Для этого квеста больше ничего не надо. Все необходимое для корректной работы квеста уже добавили. Вот полный текст квеста:
7 {4 p. i- r% U/ k
6 n# d, I: X: o, I* Q8 I* H
  1. if getCount(st) >= 4 :
    7 x4 l# X3 q  u7 c* g- [% Q
  2. completed(st)
    5 z8 h7 [) `& X# z  y  g4 X
  3.   return
    ) M; D& A( s1 y/ M5 z+ c4 q

  4. 8 Z' \% U& }$ n2 a
  5. class Quest (JQuest):5 d$ i! w) M: q+ r
  6.   def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)7 ?  c8 E" Z- N& y# x: S
  7.   def onEvent (self,event,st):9 ]3 s$ w& v; i2 w: y
  8. id = st.getState()
    & s' ~) W. ]% o* T" `. n
  9. if   id == CREATED  : st.setState(STARTED); j5 a. p* F+ {* v  F" J$ _
  10. elif id == COMPLETED: pass: m( S- l) N7 q9 Y
  11. elif id == STARTED  : check(st)
    7 V8 L8 h* w1 p3 ~: T( H, a3 N
  12. return2 l9 {& A/ ^* Y% Q

  13. 5 W6 b1 m' h" q6 `! ]
  14. QUEST     = Quest(201,"Tutorial", "Tutorial quest")  w1 e& ]: }: G0 `6 R$ N
  15. CREATED   = State('Start',     QUEST)
    0 f- ]; C; z) B7 y/ I% \
  16. STARTED   = State('Started',   QUEST)& [7 [# [- b7 @+ x" {- J
  17. COMPLETED = State('Completed', QUEST)
    # `( ]  i# P. b) J  @7 K
  18. 1 I. _# X7 g; L5 t: w- `1 `1 Y
  19. QUEST.setInitialState(CREATED)9 j! j: {2 [2 _9 z% d" |1 j
  20. QUEST.addStartNpc(7056)
    % n' O+ n3 Z7 x" P- ~) O' a
  21. STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код
Теперь рассмотрим, как это работает.
4 D' ?7 h' I: x% [! ?0 YИгрок подходит к начальному NCP (в данном случае 7056), нажимает на «Quest». Квест будет создан и состояние квеста перейдет к CREATED и игроку будет показана страничка Start.htm с описанием квеста. Тогда метод onEvent, поле открытия странички Start.htm переведет состояние квеста в STARTED и игроку будет показана страничка Started.htm, где будет опсание того, как найти keltirs и .т.д.
; Q: f* i- I7 K9 c$ ^1 b; ]4 y& u
8 S. ?3 r3 C: N
2 O5 K/ k  s  m7 Q% i% o& @
При состоянии STARTED будет зарегистрирован дроп «fangs» при убийстве keltirs. Игрок может вернуться к стартовому NCP и спросить о квесте – метод onEvent будет вызван снова. Если у игрока не хватает необходимого количества предметов, то метод check() не переведет квест в следующее состояние и Started.htm будет показана снова. Но если игрок собрал необходимее количество предметов (в данном случае 4 клыка), то метод check() вызовет метод completed() который переведет квест в новое состояние COMPLETED, заберет все клыки, даст карту мира, т.к. это награда за квест, покажет Completed.htm и завершит квест.
5 Y* r1 R' _, S# m$ {4 t
4 v0 Z$ d( X) ^  V  b
4 R" t# t6 h! K) n( s
Теперь давайте сделаем наш квест более похожим на то, что он должен из себя представлять.
; H1 F. \3 n  X6 f0 q/ o, FПрежде всего у нас есть 3 метода для объявления их в Яве – onTalk, onKill и onEvent. Если методы onTalk и onKill не объявлены, то за них все будет делать метод onEvent, т.е. определять квестовых монстров и вызывать диалоги NCP. Есть примечание, методы onTalk и onKill будут вызывать только диалоги с NCP в зависимости от текущего состояния квеста. Метод onKill будет вызываться только тогда, когда мы убиваем квестового монстра.
, a* _' E% B. |4 Z8 G. i+ Z7 M" s% ?0 A

2 ^" f, [9 h9 ^7 NДавайте рассмотрим как вызывается метод onKill при убийстве keltir в состоянии квеста STARTED:8 L. H9 ^0 ^  k  }4 J$ l
  1. STARTED.addKillId(KELTIR_NPC_ID)
Скопировать код
и метод onKill в классе Quest:- @8 |5 d5 S- J5 l8 R) j6 k

  y) {1 k9 z( q6 P+ W! C- \
  1. class Quest (JQuest):
    " o$ a  v- v5 c% l9 s
  2.   ...2 }5 H4 ]: y# s
  3.   def onKill (self,npcId,st):
    2 C3 A: \  y5 t+ t4 a
  4. if npcId == KELTIR_NPC_ID:
    " n( \6 E' n0 B3 N- l- h9 j& W5 k
  5.    n = getCount(st)1 t* {# W8 X# T8 k$ I, ?
  6.    if   n == 0:! p1 \* m; C: ~3 O& _* O) ~2 [
  7.        return "Chat0.htm"
    & f% X7 O2 i- d4 v+ `9 Z/ h
  8.    elif n == 1:% R. Y9 U* J$ W, E
  9.        return "Chat1.htm"
    " p+ l2 @4 ?" J1 S
  10.    elif n >= 4:0 @7 |- U4 t+ h3 C2 G
  11.        return "Chat4.htm"
    ( l" O# z0 Z+ L# t7 X9 h
  12.    return "Collected "+str(n)+" of 4 fangs"1 [; w. s6 l: N4 g' q( ^& W4 X( Z
  13. return
Скопировать код
Метод onKill (а так же метод onTalk) имеет следующие параметры:
) ^9 K5 O7 C1 [1 `1 _
4 X' ~. m  W! ^1 d" h: B8 ~

7 E3 Y9 S3 }9 {3 [) V• self – квест
/ @/ `5 F: Y; x+ E% K• npcId – ID NCP, которого мы должны убивать (если это метод onTalk, то ID того NCP, с которым мы должны поговорить).
% q5 M& O$ s6 I• st – текущее состояние игрока.0 l( P4 H+ `+ ?6 O5 L$ T

% m6 [( C4 _% p  @0 e# h% d
4 K, R/ c9 A9 l1 Y
В этом методе мы проверяем и отмечаем, является ли убитый NCP keltir’ом. В основном эта проверка не нужна, т.к. у нас только KELTIR_NPC_ID.
: e! i9 a" o% u) f* k  {, A7 H9 ?8 f, y8 Y
! z) {3 K% [( J) q5 R
Затем проверяем количество предметов (в данном случае количество клыков), и если их вообще нет, то возвращаем строку "Chat0.htm", если только один предмет, то возвращаем строку "Chat1.htm", если же предметов 4 или больше, то "Chat4.htm". Если строка возвращена из методов onEvent, onKill или onTalk, то сервер покажет соответствующие htm. В Chat0.htm может иметь следующий текст: «Вы не имеете ни одного клыка, возвращайтесь позже, когда соберете 4 штуки и бла, бла, бла…», в Chat1.htm может быть следующий текст: «У Вас всего 1 клык, по этому соберите еще…». В Chat4.htm – «Вы собрали необходимое количество предметов, возвращайтесь к вашему тренеру, что бы завершить квест…»
4 c  z3 ~% c( z/ a* p; k7 q  k  B$ k
6 n3 h, F0 T* [7 {' K9 X+ I
Примечание: если в строка return начинается с "<html>", то будет показана страничка html с текстом, который стоит далее. Так вместо:$ K5 Q6 R- i* P8 f" N
return "Chat4.htm"
5 u- e5 H8 Q8 J! ?0 l
. x7 G- }" P2 F! ?4 p' {8 K

+ D% f7 I7 q+ a% q3 {+ e# c, ]можно поставить:
0 B4 g' M/ O5 A
  1. return "<html><body>Return to your trainer to complete the quest</body></html>"
Скопировать код
Так же если строка заканчивается без .htm или в начале нет <html>, то текст будет выведен, как системное сообщение в окне чата. В нашем случае мы сделаем так, что бы при каждом убийстве keltik выводилось системное сообщение: «Собрано N из 4-х клыков».
& l0 Z  a) U0 w9 s- z
; i' A4 c# n7 F, ~' U
( d0 z9 |% t+ j7 B/ v( Z& e
Наш код для onKill имеет один недостаток. Он будет постоянно показывать Chat0.htm, Chat1.htm и Chat4.htm, нам же необходимо, что бы Chat0.htm и Chat1.htm показывались только один раз. Как нам это сделать? С помощью переменных.7 b, r+ j0 S8 Q1 J9 j
" J6 `* R2 o. L1 r
; I3 S1 e) ]2 d( M% `- w
В каждом квесте строки могут храниться с помощью переменных. Эти переменные сохраняются в Вашей БД. В каждом методе мы можем назначить, прочитать и удалить переменные. Давайте изменим метод onKill, так что бы каждый диалог вызывался только один раз.0 U# b( q0 J6 n0 ]
  1. def onKill (self,npcId,st):* V3 e6 B7 G; \" |, X
  2. if npcId == KELTIR_NPC_ID:, s* \+ Z& L5 H* F& L' W6 q# i7 K
  3. n = getCount(st)
    7 c3 |. R- B& }, J
  4. if n == 0:
    ; x1 _- Q- [4 U& U
  5. if st.get('chat0') == None :( y. R1 r9 R* O
  6. st.set("chat0", "true")
      s1 E- w! e6 I( i% B4 N' a
  7. return "Chat0.htm"
    / \4 C8 O: o/ R1 c# t( y  \- v
  8. elif n == 1:/ h. [9 \7 R* A9 _4 C" {3 G' I. i
  9. if st.get('chat1') == None :
    % A; c1 ?( z. D5 n; U
  10. st.set("chat1", "true")# v; f8 ]$ C0 n- `
  11. return "Chat1.htm"
    ' S$ x  T! q& t* p9 g6 U
  12. elif n >= 4:0 x$ O& r8 @2 r1 f+ c
  13. return "Chat4.htm"" y" t0 h% o2 W) _
  14. return "Collected "+str(n)+" of 4 fangs"1 R% K4 Y& g9 w5 p9 A
  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.
" V3 R( Y; m0 G7 h+ g+ T9 N) U9 ?
( n, w& \2 ^, n1 `" ?

1 a' L0 H: [( iВот конечный рабочий вариант квеста:: m) v: k5 O' K  w
  1. import sys" m, \4 [5 w4 p# k, X; W
  2. from net.sf.l2j.gameserver.model.quest import State$ `" J, U. Y' c, a4 E
  3. from net.sf.l2j.gameserver.model.quest import QuestState& ^/ Z. V; _- c8 M
  4. from net.sf.l2j.gameserver.model.quest.jython import QuestJython as JQuest- A$ w3 i8 {$ p2 u

  5. & S0 v8 C& h9 ~* A* S/ |! k0 Q
  6. KELTIR_NPC_ID = 12082
    9 e! w$ q  E( Q9 R# {( a  Y
  7. FANGS_ITEM_ID = 1859  h6 s* r" n- ~: y
  8. DROP_RATE    = 500000* s$ u4 A* x* N( P

  9. * u' ^7 T( D0 Z% b5 d
  10. WORLD_MAP_ITEM_ID = 1665( \6 C/ G( D) T6 b" |% Y% m
  11. ! P' E4 P6 Z. a' @. ]
  12. def getCount(st) :1 Z% D% I0 `9 m- Z$ t8 j; M1 ^
  13. return st.getQuestItemsCount(FANGS_ITEM_ID)
    0 C! T& a" x3 c$ |

  14. - `0 U; t0 m! S" W) W
  15. def completed(st) :5 H4 O  m5 Z8 `; f! j( |# x% a
  16. st.setState(COMPLETED)
    . K8 J& W7 o3 O2 Z+ s4 Z
  17. st.clearQuestDrops()5 R# J; n4 Z/ Y5 r6 W
  18. st.takeItems(FANGS_ITEM_ID,-1)
    # x  v- y3 ?! ]
  19. st.giveItems(WORLD_MAP_ITEM_ID,1)7 x& [6 G/ [3 z5 k3 X* \2 k9 b
  20. st.exitQuest(False)
    4 m+ c- B. \8 b3 [1 O
  21. return
    % g* a- @, S5 V5 o/ ?
  22. " p0 }7 c% Q1 h8 C* o0 X3 g
  23. def check(st) :
    0 G. f9 n* i' K$ h& l' N8 e* e3 X5 N
  24. if getCount(st) >= 4 :  B; Z0 ~7 U- }% W4 J0 e
  25. completed(st)4 T9 |$ d! x: ~. t
  26. return9 e7 C! s1 d" a' {; G/ \
  27. ' P2 c) y: G' `
  28. class Quest (JQuest):. N) N, K5 \4 f" ?

  29. ( b% Q/ m$ z' h: d' M" M& p& K
  30. def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)( B* d. s/ e% y( |; j
  31. + |: A3 _+ o5 U7 \# ~6 c
  32. def onEvent (self,event,st):0 U% Q5 d0 p; q4 T
  33. id = st.getState()- }& e1 ~6 z- b5 t; V
  34. if id == CREATED : st.setState(STARTED)
    " T5 p/ G7 G6 h+ J
  35. elif id == COMPLETED: pass3 E: g/ a! N; z+ E( v
  36. elif id == STARTED : check(st)3 h8 ]3 C2 L( L
  37. return
    & r0 L( ^! X! \9 I

  38. / ]1 a1 B) U7 x
  39. def onKill (self,npcId,st):
    9 l$ }2 L, _! K5 c' h
  40. if npcId == KELTIR_NPC_ID:( U3 {3 K3 v) s) V8 S' @( G; i
  41. n = getCount(st)
    ) m3 J7 o+ H; F9 u( m
  42. if n == 0:
      ]* L2 ]% h( u
  43. if st.get('chat0') == None :
    , B& @6 \0 j" o
  44. st.set("chat0", "true"), h9 Q1 ]! T; _% Z5 H% y
  45. return "Chat0.htm"
    8 J& u0 M  J8 C
  46. elif n == 1:  B4 Z" B, \/ `% W7 v3 L/ n8 x  I
  47. if st.get('chat1') == None :
    $ A6 D. ~7 m7 B7 \6 H! z
  48. st.set("chat1", "true")
    - y" z% f/ I, L) ^8 `( H
  49. return "Chat1.htm"9 ^" i; J' i# o: e4 s: k" H* n, x- T
  50. elif n >= 4:: R% r/ s& E* x. S" z; o
  51. return "Chat4.htm"* a) }- M  t- B3 v( T8 [
  52. return "Collect "+str(n)+" of 4 fangs"
    3 j' V& w% N- s/ k5 e7 J
  53. return
    * K2 i$ @: @% }5 V
  54. ' g6 A8 D8 C. A* Q' f7 T
  55. QUEST    = Quest(201, "Tutorial", "Tutorial quest")
    2 ~* |5 K4 P# k/ A. B  O
  56. CREATED = State('Start',    QUEST)* `4 ]+ x/ C: B2 X
  57. STARTED = State('Started', QUEST)5 s* u- E/ s" m$ I
  58. COMPLETED = State('Completed', QUEST)  Z6 M$ k/ k( S# h( H  d
  59. # ?) r' F4 {9 a" e! k' k# O
  60. QUEST.setInitialState(CREATED)
    0 `, x0 o4 Q1 L$ I& j- E' b
  61. QUEST.addStartNpc(7056), n& v* ~' }" O, ?( ?6 }: Y; z
  62. QUEST.addStartNpc(7012)
    9 f. O6 Z; ?/ f4 L' P& A) X
  63. QUEST.addStartNpc(7009)2 h. B2 d3 {0 x1 N- N
  64. QUEST.addStartNpc(7011)) g5 j3 g" s' X  A# r& G& L+ K

  65. 0 Q! d* B7 d. F
  66. STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
    1 V# P1 i9 S' o8 ~3 }4 _) \
  67. STARTED.addKillId(KELTIR_NPC_ID)
    ' b5 b; b5 m1 U9 l; j  y" u/ U  ?
  68. STARTED.addTalkId(7056)
      H: c: a" j0 h+ ?6 p# N$ S
  69. STARTED.addTalkI d(7012)
    ) Z$ j- m! c& L+ z
  70. STARTED.addTalkId(7009)$ c* X5 ?2 g) W
  71. STARTED.addTalkId(7011)
Скопировать код

7 I. d( Q8 z& U% {8 f/ s+ D9 o5 R; ?" c/ e/ w
Чтобы ответить, вам надо авторизироваться в системе Вход | Зарегистрироваться

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

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

638638758

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

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

admin@artace.ru Онлайн

QR-код

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