Top.Mail.Ru

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

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

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

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

x
Хроники        Interlude1 z7 i3 j% a, M- N. ~' i
Сборка        L2j
2 a% X2 Q6 k2 b5 l# iОбратите внимание: в файле htm стартового NCP обязательно должна быть ссылка на квест:0 ]1 A) R, a$ d! E
  1. STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код
Для этого квеста больше ничего не надо. Все необходимое для корректной работы квеста уже добавили. Вот полный текст квеста:  C. ^) u6 \: i- A* n, z
! x, X: C# c2 y* T9 c- [
  1. if getCount(st) >= 4 :
    - [7 d* P+ W6 ?. L
  2. completed(st)
    & a7 U, }  K% {% J- N9 S% c* v
  3.   return
    ) W& _% s" Z3 M7 U

  4.   z( ?' Z8 f- S6 U: N
  5. class Quest (JQuest):9 b- l% T) y8 Y9 D8 L6 ^. e
  6.   def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)* e, S' `' j5 X
  7.   def onEvent (self,event,st):) e) z$ b+ t$ q( {! _. B( L* [! J
  8. id = st.getState()+ J' r+ t1 t& H  V( I
  9. if   id == CREATED  : st.setState(STARTED)
    ; w0 [  o  g  I- M  p+ r8 P+ I
  10. elif id == COMPLETED: pass2 r7 M* t/ }) R
  11. elif id == STARTED  : check(st)
    4 Y0 Q* ^: a3 |$ K" f. t0 l, m  M
  12. return& P" e' X& l9 C- Z  H# ?- l

  13. ' G+ U2 f- l  `% P
  14. QUEST     = Quest(201,"Tutorial", "Tutorial quest")
    / r) T: i" E  [" ^$ B$ K
  15. CREATED   = State('Start',     QUEST)6 V+ [9 h$ m! ?7 e! `
  16. STARTED   = State('Started',   QUEST)2 b" W; M# F& F/ n
  17. COMPLETED = State('Completed', QUEST); {2 l( Q5 }4 d! W
  18. 8 A7 m) L8 @8 R, \0 ?/ C
  19. QUEST.setInitialState(CREATED)0 q: R3 g. h& `# |1 P' ?, b4 h
  20. QUEST.addStartNpc(7056)  i/ n/ H9 u3 f/ \( d
  21. STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код
Теперь рассмотрим, как это работает.
8 ^( s" c) `7 Y0 ]* ]4 a2 IИгрок подходит к начальному NCP (в данном случае 7056), нажимает на «Quest». Квест будет создан и состояние квеста перейдет к CREATED и игроку будет показана страничка Start.htm с описанием квеста. Тогда метод onEvent, поле открытия странички Start.htm переведет состояние квеста в STARTED и игроку будет показана страничка Started.htm, где будет опсание того, как найти keltirs и .т.д.
8 I3 a% h: p3 f# i/ N6 _1 M( f! ], Z7 Y( _; \; r  L
+ }1 S( e$ E' `5 u5 ?. t0 f4 N" e
При состоянии STARTED будет зарегистрирован дроп «fangs» при убийстве keltirs. Игрок может вернуться к стартовому NCP и спросить о квесте – метод onEvent будет вызван снова. Если у игрока не хватает необходимого количества предметов, то метод check() не переведет квест в следующее состояние и Started.htm будет показана снова. Но если игрок собрал необходимее количество предметов (в данном случае 4 клыка), то метод check() вызовет метод completed() который переведет квест в новое состояние COMPLETED, заберет все клыки, даст карту мира, т.к. это награда за квест, покажет Completed.htm и завершит квест./ W" l" a) |1 Z2 w

, x; E. _* h% H. I& G( m. X

* F0 a+ k! |7 u9 K7 N. PТеперь давайте сделаем наш квест более похожим на то, что он должен из себя представлять.
1 ?$ y5 o3 g! D3 S3 D; YПрежде всего у нас есть 3 метода для объявления их в Яве – onTalk, onKill и onEvent. Если методы onTalk и onKill не объявлены, то за них все будет делать метод onEvent, т.е. определять квестовых монстров и вызывать диалоги NCP. Есть примечание, методы onTalk и onKill будут вызывать только диалоги с NCP в зависимости от текущего состояния квеста. Метод onKill будет вызываться только тогда, когда мы убиваем квестового монстра.
/ Y6 f' ]* f+ \1 c$ ]# a+ }! u& w7 w9 ]' x
* Z0 X- K( v9 z7 X0 e: ^
Давайте рассмотрим как вызывается метод onKill при убийстве keltir в состоянии квеста STARTED:
: C& B) u& F9 Y& x/ z$ _" w5 e
  1. STARTED.addKillId(KELTIR_NPC_ID)
Скопировать код
и метод onKill в классе Quest:1 {2 H6 b8 k4 ]0 A- b

( h+ w% g/ F/ L! {1 [% ]7 I
  1. class Quest (JQuest):8 z. W. w/ i  z3 Y
  2.   ...; Y; E4 T2 c: i9 e& U/ z: w
  3.   def onKill (self,npcId,st):
    8 ^; R2 R6 N" e6 \6 t) C
  4. if npcId == KELTIR_NPC_ID:
    ; W$ K6 f+ K; v) f( L, K
  5.    n = getCount(st)% W2 h5 M6 P+ ?/ e! Y3 ^0 @4 P
  6.    if   n == 0:
    2 e/ l1 h$ G! b, B& Y
  7.        return "Chat0.htm"+ b9 _! F1 ^9 F; W, d8 i& @7 g( l
  8.    elif n == 1:8 I/ `. l. M$ K- p5 g, H1 b7 p
  9.        return "Chat1.htm": e) x6 D1 r! ^
  10.    elif n >= 4:& F2 p7 Y* v& e/ q0 P- R% e
  11.        return "Chat4.htm"7 J6 q5 h) V2 u9 ]. l3 R
  12.    return "Collected "+str(n)+" of 4 fangs"
    % w$ G2 f2 d" F9 Q; `
  13. return
Скопировать код
Метод onKill (а так же метод onTalk) имеет следующие параметры:, n6 ]+ l! t7 u0 u5 P8 u. Z

. ]) i9 A' T+ D$ ~- h' ~

, M+ e8 B, z; {" \" ?5 ^( }5 X• self – квест- o- x9 a* r* B) t3 `' d: U
• npcId – ID NCP, которого мы должны убивать (если это метод onTalk, то ID того NCP, с которым мы должны поговорить).( f! h( {  H; G
• st – текущее состояние игрока.
1 `3 d% k: O4 L5 \
( z! L6 u+ R- C8 d: A1 v

: h% H; h6 o5 ^4 S8 AВ этом методе мы проверяем и отмечаем, является ли убитый NCP keltir’ом. В основном эта проверка не нужна, т.к. у нас только KELTIR_NPC_ID.
8 h0 o2 i. G' u: n! }% R9 R: x1 C4 l+ P+ T
6 i: I, }, [. t+ I7 w( i  q7 R
Затем проверяем количество предметов (в данном случае количество клыков), и если их вообще нет, то возвращаем строку "Chat0.htm", если только один предмет, то возвращаем строку "Chat1.htm", если же предметов 4 или больше, то "Chat4.htm". Если строка возвращена из методов onEvent, onKill или onTalk, то сервер покажет соответствующие htm. В Chat0.htm может иметь следующий текст: «Вы не имеете ни одного клыка, возвращайтесь позже, когда соберете 4 штуки и бла, бла, бла…», в Chat1.htm может быть следующий текст: «У Вас всего 1 клык, по этому соберите еще…». В Chat4.htm – «Вы собрали необходимое количество предметов, возвращайтесь к вашему тренеру, что бы завершить квест…»
& G- I( A+ q8 W' x
% [/ G. U1 P2 j/ q
, [/ x  G0 L) h2 n( L. g
Примечание: если в строка return начинается с "<html>", то будет показана страничка html с текстом, который стоит далее. Так вместо:' I, ]8 T% m9 F- _
return "Chat4.htm"
1 D) F" @. k+ |6 ]+ ]+ d' K0 Q: F1 i* j0 J8 i

6 O+ W, a7 S$ s. Z! Nможно поставить:
: E: _/ d. y" W4 H% Z+ X6 N" u, S
  1. return "<html><body>Return to your trainer to complete the quest</body></html>"
Скопировать код
Так же если строка заканчивается без .htm или в начале нет <html>, то текст будет выведен, как системное сообщение в окне чата. В нашем случае мы сделаем так, что бы при каждом убийстве keltik выводилось системное сообщение: «Собрано N из 4-х клыков».4 M0 b* I0 n4 @  C9 f2 G9 V
  X" h/ J) N2 l+ P* f

- B- B: ?1 E3 r; p# H4 U! ^: FНаш код для onKill имеет один недостаток. Он будет постоянно показывать Chat0.htm, Chat1.htm и Chat4.htm, нам же необходимо, что бы Chat0.htm и Chat1.htm показывались только один раз. Как нам это сделать? С помощью переменных./ i  d# v1 D# q3 \' x0 U
/ v. g& b4 q" `7 g0 ]$ u# R; M  v
: |* x$ z5 T) C) C/ L
В каждом квесте строки могут храниться с помощью переменных. Эти переменные сохраняются в Вашей БД. В каждом методе мы можем назначить, прочитать и удалить переменные. Давайте изменим метод onKill, так что бы каждый диалог вызывался только один раз.  v2 f! b$ v1 E6 [9 s1 E' |7 ^' m
  1. def onKill (self,npcId,st):
    8 e/ q$ l0 B* w& v0 A' X% J
  2. if npcId == KELTIR_NPC_ID:
    # T4 A) s5 p3 j2 d
  3. n = getCount(st)
    9 I" v% a: W$ s  u$ ^' H
  4. if n == 0:' ~' S' q4 ]  ~  a) V- F4 E% j' F
  5. if st.get('chat0') == None :
    ' v# ^4 X0 T) p
  6. st.set("chat0", "true")+ T6 t0 C$ A; {# c4 b
  7. return "Chat0.htm"  h( m! A) E" X
  8. elif n == 1:
    5 I& o- c: m( x$ ?% K! [
  9. if st.get('chat1') == None :# d, b% i9 c$ @. n+ V8 U$ C* `! N
  10. st.set("chat1", "true")$ @4 }- l/ l* L: L- u, h( \
  11. return "Chat1.htm"
    9 h# S- n9 o3 ]9 r
  12. elif n >= 4:
    3 C& n" i1 j, I7 c5 [2 M4 l- b: h$ Y
  13. return "Chat4.htm"2 m: Y- j7 v& R7 t
  14. return "Collected "+str(n)+" of 4 fangs"
    ; |8 [# T4 D% p0 @$ ~
  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.  P# t4 b! S9 j, M9 G
$ w1 _) l2 ?/ {3 p9 r% @. X2 I
9 ~  I) T& s4 w6 G  m7 z5 w. a9 x/ o% m
Вот конечный рабочий вариант квеста:% h" ~5 e" \4 U" W
  1. import sys! ~- y/ K) b* J" ]9 ^
  2. from net.sf.l2j.gameserver.model.quest import State; o( Z) _" O9 {/ C; u5 D: c: R. i
  3. from net.sf.l2j.gameserver.model.quest import QuestState6 F0 w+ t) H  |- ?4 L; Y) r. r& ?
  4. from net.sf.l2j.gameserver.model.quest.jython import QuestJython as JQuest
    - W: p, Z% P9 ~( h
  5. , [0 S, x) ^1 O5 i0 g! u3 L4 z5 o
  6. KELTIR_NPC_ID = 120826 d/ F: w) g& ^! T
  7. FANGS_ITEM_ID = 1859+ ?5 Y$ H- v7 J
  8. DROP_RATE    = 500000; X& Q6 D! A, d+ z6 q

  9. + {( D% D  Q* c3 o( [- Y, B
  10. WORLD_MAP_ITEM_ID = 1665! r$ P1 L$ |& M/ O4 i

  11. ' T# Q3 B8 N( M: L
  12. def getCount(st) :7 j0 S2 |! o5 f# Y4 \
  13. return st.getQuestItemsCount(FANGS_ITEM_ID); E! I* C) e7 h# V
  14. % s+ R+ M% M6 A* k
  15. def completed(st) :
    2 y& l- R: W+ P# |3 z# o3 q
  16. st.setState(COMPLETED)
    2 `, T4 C, d, d7 j% r
  17. st.clearQuestDrops()7 T8 f# O* E, L" W
  18. st.takeItems(FANGS_ITEM_ID,-1)% R6 c. @6 s; n1 u: w
  19. st.giveItems(WORLD_MAP_ITEM_ID,1)
    3 w2 i% R' ]0 o
  20. st.exitQuest(False)5 j, x  B1 K; B6 }3 l5 ?3 t9 z, B
  21. return
    & ^2 O2 G/ W3 ]- z

  22. * `; N8 `* S1 y* p" y5 k
  23. def check(st) :$ L! U, o1 _% ~# W# U8 H
  24. if getCount(st) >= 4 :! }. C# k8 ?- W$ L6 b
  25. completed(st)
    - H! C" x3 [* h) v0 v
  26. return, O, U- |& c  |3 j% j

  27. ) V" m/ b$ h; Y5 u; q) c
  28. class Quest (JQuest):
    / w) ^6 V# L& N' G2 k0 x) }
  29. % Q/ _$ ~/ a% p* o: ?- V1 G. r
  30. def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)
    : f, h/ l# w& [6 r  q
  31. 2 I" p; n# G" d$ U; Z4 H# y
  32. def onEvent (self,event,st):8 t* i) Z1 ~& _8 j, d* b, |
  33. id = st.getState(). O; Q. t( h9 \& ?
  34. if id == CREATED : st.setState(STARTED)
    ' b* J( T& E5 I/ g1 Q9 f# d2 [
  35. elif id == COMPLETED: pass* b" _+ b" J5 S, F+ T
  36. elif id == STARTED : check(st)
    7 l+ e1 V) M0 L2 g6 a- l; B6 s
  37. return
    $ P$ @7 S8 W* V6 H
  38. ) Q: b* h: \# D4 h' |2 ~$ r2 I
  39. def onKill (self,npcId,st):9 U8 S$ z2 }3 I* o! ]+ p
  40. if npcId == KELTIR_NPC_ID:8 u" u& L2 j) ]) C  ]% z! W
  41. n = getCount(st)$ r, ?/ V# s- Y1 o' p
  42. if n == 0:
    " ^' k, W6 z. F+ W# D
  43. if st.get('chat0') == None :! X' s+ G5 w+ J# }2 Q& d/ P' H" x4 U
  44. st.set("chat0", "true")% S( G% `& x9 Q5 e' C' S8 ]0 x
  45. return "Chat0.htm"& M6 I- r9 [' g, W" `; K( |4 u4 i
  46. elif n == 1:& Q/ q5 M# W9 O
  47. if st.get('chat1') == None :9 j# y, r5 ^4 n* j. G
  48. st.set("chat1", "true")
    . N& j6 R% N% J1 U$ e; \, e
  49. return "Chat1.htm"
    % Y  H' z3 c3 l; I) S- |9 n" N
  50. elif n >= 4:
    $ W) ]4 C; Q4 v8 A' @1 P' a( O
  51. return "Chat4.htm"8 d9 S  c1 r/ g# u8 s: _
  52. return "Collect "+str(n)+" of 4 fangs"
    , k# `9 w6 Z! L4 n7 q; u
  53. return
    2 N: P. ]2 |! R$ p  d( R2 t
  54. 9 D! X6 l- t7 G1 K9 ]8 R
  55. QUEST    = Quest(201, "Tutorial", "Tutorial quest")9 ]- G" B! {  B6 j; K( u3 T
  56. CREATED = State('Start',    QUEST)' w- N+ @7 F; m6 U2 A  a. i" h$ d
  57. STARTED = State('Started', QUEST)
    / U! ]1 b* p0 c1 v  ^/ v, j& C
  58. COMPLETED = State('Completed', QUEST)
    ' O$ ~* B: G5 I- G  U2 l6 p
  59. 7 h, h5 p' D' ~: s
  60. QUEST.setInitialState(CREATED)
    + |& [6 y$ o6 ~) q% h
  61. QUEST.addStartNpc(7056)# f, R1 r) C! x& n1 Z) l
  62. QUEST.addStartNpc(7012)
    + c$ k0 I( W* e- y- E2 h2 E
  63. QUEST.addStartNpc(7009)
    $ c8 Y3 f2 P2 l! {1 V7 P
  64. QUEST.addStartNpc(7011). X1 C9 ~6 V4 i1 o7 D2 g
  65. 5 k) ~  b  F0 k8 @7 j
  66. STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)( |# b) t; h' H+ G
  67. STARTED.addKillId(KELTIR_NPC_ID)
    7 ~% c; ^- O( _2 h" t& v& Y- j- y
  68. STARTED.addTalkId(7056)
    ( J7 n: H( B. \8 `" U
  69. STARTED.addTalkI d(7012)
    1 O% @$ s! l2 O* Q1 V9 @& B
  70. STARTED.addTalkId(7009)
    # Y7 y3 D1 p. k( E/ G! W
  71. STARTED.addTalkId(7011)
Скопировать код

1 r1 ]" v8 `3 F7 I* p, n& k8 I( m, s" b2 c# j9 o, B: s& v
Чтобы ответить, вам надо авторизироваться в системе Вход | Зарегистрироваться

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

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

638638758

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

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

admin@artace.ru Онлайн

QR-код

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