Top.Mail.Ru

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

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

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

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

x
Хроники        Interlude
6 i" o2 K/ }: i8 o* `- z* v3 hСборка        L2j% i# Y) o2 F$ X/ q; Z
Обратите внимание: в файле htm стартового NCP обязательно должна быть ссылка на квест:" q! K' ^6 {6 J
  1. STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код
Для этого квеста больше ничего не надо. Все необходимое для корректной работы квеста уже добавили. Вот полный текст квеста:
6 i: A+ N7 I3 }0 G3 R% S3 B' l0 z- K6 K# u1 p4 n
  1. if getCount(st) >= 4 :
    9 S# c  L$ t8 D( ~$ a7 k
  2. completed(st)4 d' m; [$ q0 }: B: G3 }9 _
  3.   return/ J/ N8 I! C8 o, O
  4. 4 [( V8 `" S" B' U9 Z7 |, o
  5. class Quest (JQuest):
    6 C. P& Q, n) Q* R" t
  6.   def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)
      h5 F6 y! C* _% n; E- m: D
  7.   def onEvent (self,event,st):
    1 H! \( `) U7 p  l( |7 o
  8. id = st.getState()* ^& Q, J- U, O
  9. if   id == CREATED  : st.setState(STARTED)' ]2 m+ Q4 I0 Y6 d
  10. elif id == COMPLETED: pass/ m* K- U0 T# B8 L9 N8 U
  11. elif id == STARTED  : check(st)
    2 D' j. Z" _$ E% u2 \. U
  12. return7 B( ]8 n" e3 N+ |

  13.   Z& F$ _4 [6 \  N' h; C6 k
  14. QUEST     = Quest(201,"Tutorial", "Tutorial quest")# y/ V- K  v) j+ K! W) M
  15. CREATED   = State('Start',     QUEST), Y# l% y2 R! C/ v9 Y
  16. STARTED   = State('Started',   QUEST)
    ! i) h- B+ M: L- @  L
  17. COMPLETED = State('Completed', QUEST)9 Y* a1 w/ I, Y! X; h" E2 ~
  18. - C" n% ]3 J; y
  19. QUEST.setInitialState(CREATED)
      `" W, W* E: A1 }" i3 B- r+ \
  20. QUEST.addStartNpc(7056)
    9 E# M" v0 A8 z0 C7 A
  21. STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код
Теперь рассмотрим, как это работает.( \! [% ], |0 @6 v% m  e
Игрок подходит к начальному NCP (в данном случае 7056), нажимает на «Quest». Квест будет создан и состояние квеста перейдет к CREATED и игроку будет показана страничка Start.htm с описанием квеста. Тогда метод onEvent, поле открытия странички Start.htm переведет состояние квеста в STARTED и игроку будет показана страничка Started.htm, где будет опсание того, как найти keltirs и .т.д.6 t; M, ]0 S' W
) I& B8 I+ A6 l& E5 v2 e$ s

. @( k5 Y# A# _4 S2 M  u# PПри состоянии STARTED будет зарегистрирован дроп «fangs» при убийстве keltirs. Игрок может вернуться к стартовому NCP и спросить о квесте – метод onEvent будет вызван снова. Если у игрока не хватает необходимого количества предметов, то метод check() не переведет квест в следующее состояние и Started.htm будет показана снова. Но если игрок собрал необходимее количество предметов (в данном случае 4 клыка), то метод check() вызовет метод completed() который переведет квест в новое состояние COMPLETED, заберет все клыки, даст карту мира, т.к. это награда за квест, покажет Completed.htm и завершит квест.3 ^' D& L1 n" w: E

/ P7 p! s, g! {1 l: ^& E

$ E+ I1 \4 B8 v5 z0 j6 mТеперь давайте сделаем наш квест более похожим на то, что он должен из себя представлять.
4 D  u0 I$ Y. I. \Прежде всего у нас есть 3 метода для объявления их в Яве – onTalk, onKill и onEvent. Если методы onTalk и onKill не объявлены, то за них все будет делать метод onEvent, т.е. определять квестовых монстров и вызывать диалоги NCP. Есть примечание, методы onTalk и onKill будут вызывать только диалоги с NCP в зависимости от текущего состояния квеста. Метод onKill будет вызываться только тогда, когда мы убиваем квестового монстра.& P0 S) r* B2 M4 _. u1 J- [/ l$ k
9 H! d: Y1 o% O  k
% J0 ]8 ?3 S* D
Давайте рассмотрим как вызывается метод onKill при убийстве keltir в состоянии квеста STARTED:- l3 P8 E8 b& p! U9 V: C8 h! C! j
  1. STARTED.addKillId(KELTIR_NPC_ID)
Скопировать код
и метод onKill в классе Quest:' F/ g# T/ E  N7 c
9 r, D* l. G0 k8 {" J$ a" V
  1. class Quest (JQuest):& F; F" q: J5 \
  2.   ...) m2 V. ~8 ]/ s+ N0 E3 n- Z! |  d
  3.   def onKill (self,npcId,st):
    / n( N8 Z/ \: F& l
  4. if npcId == KELTIR_NPC_ID:
      k, L% I& h+ N! M& j
  5.    n = getCount(st)
    : g5 G0 c2 a, z7 L( B# @+ D
  6.    if   n == 0:
    % k/ h  A2 K1 c2 K2 i: V% M# B
  7.        return "Chat0.htm"0 m- b9 Q0 i5 l. v' I; o, X
  8.    elif n == 1:; Q( M. F# L  W! h1 E" A
  9.        return "Chat1.htm"
    , ~* l3 I; e. }% ?! D3 y
  10.    elif n >= 4:
      j! T2 D2 w( y8 [8 D
  11.        return "Chat4.htm"
    7 b; M5 G) ^% L
  12.    return "Collected "+str(n)+" of 4 fangs"2 n  w+ M& \/ |
  13. return
Скопировать код
Метод onKill (а так же метод onTalk) имеет следующие параметры:$ z! s( V7 W$ E8 r, A, H$ i

$ B8 B9 H: p% I& }1 i; j- u4 N/ w

- \2 a6 z8 N6 q7 g/ m$ W• self – квест* l2 k- }# Y) ~/ }7 K' z  ]
• npcId – ID NCP, которого мы должны убивать (если это метод onTalk, то ID того NCP, с которым мы должны поговорить).0 G2 I" b. T$ m# W7 N$ @& E4 d
• st – текущее состояние игрока.: h% @2 {  d( m0 @, U1 R: F
! c- _# |/ |$ d, r) _! A) h, `- E4 L

- \3 z1 N6 U$ g. a8 Q) }+ t) pВ этом методе мы проверяем и отмечаем, является ли убитый NCP keltir’ом. В основном эта проверка не нужна, т.к. у нас только KELTIR_NPC_ID.
' Z: s$ J" t$ D! z: [: s
2 @) t; A% j# B; v% r

" j; ^. s' W' a! I5 u5 ?Затем проверяем количество предметов (в данном случае количество клыков), и если их вообще нет, то возвращаем строку "Chat0.htm", если только один предмет, то возвращаем строку "Chat1.htm", если же предметов 4 или больше, то "Chat4.htm". Если строка возвращена из методов onEvent, onKill или onTalk, то сервер покажет соответствующие htm. В Chat0.htm может иметь следующий текст: «Вы не имеете ни одного клыка, возвращайтесь позже, когда соберете 4 штуки и бла, бла, бла…», в Chat1.htm может быть следующий текст: «У Вас всего 1 клык, по этому соберите еще…». В Chat4.htm – «Вы собрали необходимое количество предметов, возвращайтесь к вашему тренеру, что бы завершить квест…»& D2 u+ h' M% C2 U& |3 X2 W
+ U' z; K) {5 i* n1 S5 l- G

* i7 m, a; u; I) K% RПримечание: если в строка return начинается с "<html>", то будет показана страничка html с текстом, который стоит далее. Так вместо:3 @7 K# B7 H% R7 U
return "Chat4.htm"
% M9 B6 e  A4 D8 G
" G, I, f; r" v* @1 y4 h, \
# E. Y! L& y: I: z+ t
можно поставить:% f" \! B. ~& ?: ?* |* A' |
  1. return "<html><body>Return to your trainer to complete the quest</body></html>"
Скопировать код
Так же если строка заканчивается без .htm или в начале нет <html>, то текст будет выведен, как системное сообщение в окне чата. В нашем случае мы сделаем так, что бы при каждом убийстве keltik выводилось системное сообщение: «Собрано N из 4-х клыков».6 K. c, a3 s" |) d& j: c

9 C& v& S0 l! G. P7 M' u+ b
' A' Z) M/ _1 v
Наш код для onKill имеет один недостаток. Он будет постоянно показывать Chat0.htm, Chat1.htm и Chat4.htm, нам же необходимо, что бы Chat0.htm и Chat1.htm показывались только один раз. Как нам это сделать? С помощью переменных.) C3 P$ r8 z% n7 B5 S

6 A* A) y" r' e7 [, z$ x
9 ^& C) h! N# s. W
В каждом квесте строки могут храниться с помощью переменных. Эти переменные сохраняются в Вашей БД. В каждом методе мы можем назначить, прочитать и удалить переменные. Давайте изменим метод onKill, так что бы каждый диалог вызывался только один раз.
. W' p$ C9 n; D! B- t
  1. def onKill (self,npcId,st):
    , t, V% _$ V3 a& f5 M
  2. if npcId == KELTIR_NPC_ID:
    2 ~: z' E8 E5 K- D# ~( I* O
  3. n = getCount(st)
    2 ?: `" k5 I* n5 y2 `$ g
  4. if n == 0:
    5 P" Y# C" y% g) B/ Y1 z8 f9 X
  5. if st.get('chat0') == None :
    : ~4 g0 ?* E; S3 ?* y
  6. st.set("chat0", "true")
    0 l2 U8 F7 |- k( ~
  7. return "Chat0.htm"
    * S/ J5 m( v7 t# m6 g! |2 q, w
  8. elif n == 1:- x+ q/ U( l, ^3 L0 b* f) i
  9. if st.get('chat1') == None :
    : _; i. e5 W+ F, T
  10. st.set("chat1", "true")
      K) \  L/ U  e* m+ E# E7 k  t- P* r
  11. return "Chat1.htm"0 w/ k; ^  P4 ~% ~
  12. elif n >= 4:- y, A6 g/ R, L3 l; S# _- c. q
  13. return "Chat4.htm"
    0 P: b5 _$ h( e0 ]
  14. return "Collected "+str(n)+" of 4 fangs"+ a# C! 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.& ~# }9 \# t8 N8 ~  |" `! h
# @8 Q7 p1 S3 O

$ u6 z/ c5 v! UВот конечный рабочий вариант квеста:
  C( q4 r% u7 l% h0 V+ J* x
  1. import sys
    9 W3 F0 N! W4 Y) n+ r/ k5 f
  2. from net.sf.l2j.gameserver.model.quest import State
    : W6 f$ _1 a. ^1 r2 z
  3. from net.sf.l2j.gameserver.model.quest import QuestState
    0 Z" X4 r( ?( p
  4. from net.sf.l2j.gameserver.model.quest.jython import QuestJython as JQuest
    ' X8 U- v( h* s( B9 D

  5. ! A; v, M, {5 Z, f0 g! \) G) D
  6. KELTIR_NPC_ID = 120828 {0 o1 p+ Z% q1 g
  7. FANGS_ITEM_ID = 1859, y) K. ^4 s2 h8 K# k) y
  8. DROP_RATE    = 500000
    % Z  F- Z5 y( W5 y
  9. * k' j3 _( H& t
  10. WORLD_MAP_ITEM_ID = 1665* l7 |- _: x3 y7 V
  11. " Z" {- t  T; `! C* @' G- c. J
  12. def getCount(st) :9 j: D3 X0 U! X4 F  d' j, M% f0 @! m
  13. return st.getQuestItemsCount(FANGS_ITEM_ID)( t: M# a8 f* L% x2 M

  14. 4 C7 W# C5 i+ Y4 Q' r# J
  15. def completed(st) :
    7 l2 _# P/ X$ x* }# O
  16. st.setState(COMPLETED)& b' \( T" _$ e& J
  17. st.clearQuestDrops()2 h3 W8 X, Y+ H- z: Q( A
  18. st.takeItems(FANGS_ITEM_ID,-1)% }3 B. R+ x. ^
  19. st.giveItems(WORLD_MAP_ITEM_ID,1)- b" x" c+ t' G) k  H! n
  20. st.exitQuest(False)
    2 y, W- P4 z1 L# {( e8 r
  21. return( V$ Y+ z% n( A" Q: Y
  22. 6 [7 j  H7 H# E( p6 E  \7 J
  23. def check(st) :
    6 f9 ]; \3 L/ e* p  F) @2 O; M
  24. if getCount(st) >= 4 :6 X( Z; }: \2 J) T
  25. completed(st)
    8 r  [- F7 ^8 I
  26. return0 q! Q& }/ x2 f% Q

  27. 2 k8 d2 B8 J( h3 w. {3 F: y: ?
  28. class Quest (JQuest):' ~+ Z  L  }, s
  29. ' I7 F6 B- P0 S, F3 t
  30. def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)6 i- s; K. o, @' ~" e1 m2 P
  31. 2 O) _' r+ Y) V0 B' R
  32. def onEvent (self,event,st):
    - W4 y. T0 b7 i; Y9 D3 P
  33. id = st.getState()
    ( O' }& L( F, f# ~& K1 W
  34. if id == CREATED : st.setState(STARTED)4 `4 d5 `- ^3 c- V9 D0 r
  35. elif id == COMPLETED: pass
    , o, h6 p5 e- f: x
  36. elif id == STARTED : check(st)* u' R$ `; B* U
  37. return
    8 Z1 I3 g$ ^  t4 W; ]  L8 I# z

  38. * r! w3 R* h) U8 ~, a! G2 y- ]
  39. def onKill (self,npcId,st):
    7 ?# K; }' B+ Y$ a) d
  40. if npcId == KELTIR_NPC_ID:
    , ?+ F) i. K- j
  41. n = getCount(st)3 g, k: V/ }1 @. z
  42. if n == 0:
    5 I6 E! s. s8 u; j) d" q
  43. if st.get('chat0') == None :
    , V% K0 ?& M  z2 F# J# Z0 k
  44. st.set("chat0", "true")+ |. M- y2 _2 V; L
  45. return "Chat0.htm"
    3 _% m: X/ P' Z7 N. p0 }
  46. elif n == 1:
    1 h: j  z! x# t. f6 V0 f
  47. if st.get('chat1') == None :
    1 I7 P- V2 a2 c' _) B
  48. st.set("chat1", "true")
    * a: @; [( E) ]. z0 F# _
  49. return "Chat1.htm"
    + Z. U: h) ^3 ]' P6 U2 [" m3 x
  50. elif n >= 4:3 p+ L$ @, N. O: o8 O
  51. return "Chat4.htm"- v5 n4 L+ t  G  _& O! C1 I
  52. return "Collect "+str(n)+" of 4 fangs"$ a$ u- G* g9 L' F4 q6 c3 a
  53. return
      y% D; Y1 F8 |, L

  54. 3 h& |8 @$ ]* y% ?, m
  55. QUEST    = Quest(201, "Tutorial", "Tutorial quest")+ p, j4 m& @& f
  56. CREATED = State('Start',    QUEST)
    , @. z8 j; @" T: i
  57. STARTED = State('Started', QUEST), B( ?" e. H9 ]8 U; L0 Q
  58. COMPLETED = State('Completed', QUEST)
    8 O9 A  l; O. r3 D- S
  59. ' U$ v8 q' b& p6 a* X) Q0 w
  60. QUEST.setInitialState(CREATED)
    0 S9 w  w4 w( k& p
  61. QUEST.addStartNpc(7056)
    3 F9 N" e5 n+ `% M
  62. QUEST.addStartNpc(7012)
    % j/ T, Z; I4 h) z3 y
  63. QUEST.addStartNpc(7009)
    - l3 y2 U! O/ y* J# o9 o, a
  64. QUEST.addStartNpc(7011)
    1 R/ T- l8 ~- W% T0 A

  65.   Z8 Y$ i9 _8 W# O. j$ M! M8 C6 Q: W
  66. STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
    % P: n3 e/ a; R: x" N
  67. STARTED.addKillId(KELTIR_NPC_ID)
    / O5 Y& v/ g% e
  68. STARTED.addTalkId(7056)) Y5 M  E' T+ o% S% Q& \2 H2 C
  69. STARTED.addTalkI d(7012)# j, o* J! f4 ~' L" C
  70. STARTED.addTalkId(7009)! a( k8 X, [; P
  71. STARTED.addTalkId(7011)
Скопировать код
9 j& n. R2 j. k; M) e: o
( A. \9 k8 C& u" K. o7 p  g
Чтобы ответить, вам надо авторизироваться в системе Вход | Зарегистрироваться

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

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

638638758

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

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

admin@artace.ru Онлайн

QR-код

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