Top.Mail.Ru

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

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

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

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

x
Хроники        Interlude! j- _$ B% T8 O3 s' z
Сборка        L2j0 Y- i/ ?1 m7 j+ }9 u9 T* t8 x) h  {
Обратите внимание: в файле htm стартового NCP обязательно должна быть ссылка на квест:9 o7 R. k- {! l8 I+ ~( P' ?4 w
  1. STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код
Для этого квеста больше ничего не надо. Все необходимое для корректной работы квеста уже добавили. Вот полный текст квеста:
. h5 @; b1 e' z6 S  V3 D9 W- B5 q. q  R+ O* p- g) S
  1. if getCount(st) >= 4 :
    " _- g: A- ?  u$ K# k
  2. completed(st)1 ?# y; I. {; S( F* Z* y1 G. R$ m5 g' }
  3.   return# d/ B  B3 I+ w/ E* u
  4. 8 f! y# [# u0 \( v3 X
  5. class Quest (JQuest):
    + T- X4 v. Z: f3 {
  6.   def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)  h8 j( j2 w: y4 a
  7.   def onEvent (self,event,st):4 Z7 q. f2 z7 ?
  8. id = st.getState()1 n; C4 ~  _4 w6 \% I
  9. if   id == CREATED  : st.setState(STARTED)4 A* o+ t* w! U7 o' v8 a1 U
  10. elif id == COMPLETED: pass5 _3 V5 {; ?; s0 K0 U6 [
  11. elif id == STARTED  : check(st)
    ; B9 z) M/ K8 i! `! q
  12. return% O4 {0 P5 O9 o$ H) n0 \( t
  13. * g3 ^9 Y+ F9 z# Y
  14. QUEST     = Quest(201,"Tutorial", "Tutorial quest")3 Z5 G' \7 x1 @7 g1 |: h9 F
  15. CREATED   = State('Start',     QUEST)9 _9 }) W# ^% ?7 K
  16. STARTED   = State('Started',   QUEST)
    - A+ u9 |! X- }$ p9 @8 |9 |
  17. COMPLETED = State('Completed', QUEST)6 K8 M7 q* E" ?

  18. " u) G; [7 t6 h% I
  19. QUEST.setInitialState(CREATED)( m5 a6 j) g) N4 C& ]  f# {
  20. QUEST.addStartNpc(7056)/ c! P' p' m& G2 l# G: u! `4 m
  21. STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код
Теперь рассмотрим, как это работает.
$ k4 S) N! K6 d8 w( V7 y3 QИгрок подходит к начальному NCP (в данном случае 7056), нажимает на «Quest». Квест будет создан и состояние квеста перейдет к CREATED и игроку будет показана страничка Start.htm с описанием квеста. Тогда метод onEvent, поле открытия странички Start.htm переведет состояние квеста в STARTED и игроку будет показана страничка Started.htm, где будет опсание того, как найти keltirs и .т.д.
0 J1 K9 h! r5 F+ `- w
- r5 u' j5 _( K6 G& g8 X3 I3 Q
: b$ e* y& [* P/ J: U
При состоянии STARTED будет зарегистрирован дроп «fangs» при убийстве keltirs. Игрок может вернуться к стартовому NCP и спросить о квесте – метод onEvent будет вызван снова. Если у игрока не хватает необходимого количества предметов, то метод check() не переведет квест в следующее состояние и Started.htm будет показана снова. Но если игрок собрал необходимее количество предметов (в данном случае 4 клыка), то метод check() вызовет метод completed() который переведет квест в новое состояние COMPLETED, заберет все клыки, даст карту мира, т.к. это награда за квест, покажет Completed.htm и завершит квест.$ v& x, K5 G0 F& }+ [. k

2 {- e7 P9 o! M/ p5 T
; `9 d' `! r" C) L
Теперь давайте сделаем наш квест более похожим на то, что он должен из себя представлять.
: w5 }& X8 v! y5 j+ n$ FПрежде всего у нас есть 3 метода для объявления их в Яве – onTalk, onKill и onEvent. Если методы onTalk и onKill не объявлены, то за них все будет делать метод onEvent, т.е. определять квестовых монстров и вызывать диалоги NCP. Есть примечание, методы onTalk и onKill будут вызывать только диалоги с NCP в зависимости от текущего состояния квеста. Метод onKill будет вызываться только тогда, когда мы убиваем квестового монстра.) N9 v( w4 r7 z2 B
, r2 i! A6 G6 k2 x* {; [

6 i5 Y: D# D2 ~& L1 O# c# M+ |Давайте рассмотрим как вызывается метод onKill при убийстве keltir в состоянии квеста STARTED:
0 ]6 T! N! J/ @/ M+ w
  1. STARTED.addKillId(KELTIR_NPC_ID)
Скопировать код
и метод onKill в классе Quest:
. j3 ~) `# t9 H+ i
, B3 f* q$ ~& p3 C! Y* J9 H0 u
  1. class Quest (JQuest):
    + U5 @6 b4 W. u7 z2 o; W
  2.   ...9 R/ k9 _- s5 R1 y$ ~: I4 C
  3.   def onKill (self,npcId,st):
    0 N8 m$ p" J% u/ Y8 d
  4. if npcId == KELTIR_NPC_ID:
    8 v' P1 u3 `% Z( t' N, i% b
  5.    n = getCount(st)
    6 ]" D% f# N& r
  6.    if   n == 0:
    8 T, s+ O+ L! y/ {/ z8 c
  7.        return "Chat0.htm"
      j! ]- I: w' @$ V, z; z8 M% h2 i
  8.    elif n == 1:
    $ s* ]+ T7 F; y* R# ^- Y
  9.        return "Chat1.htm"
    % N; f  _9 b! \+ Z; r
  10.    elif n >= 4:, J5 [6 t2 s: l  s  |" {( f8 d
  11.        return "Chat4.htm") h( d  B2 l8 G. F9 M
  12.    return "Collected "+str(n)+" of 4 fangs"$ s& p  V2 n7 n2 Z8 D
  13. return
Скопировать код
Метод onKill (а так же метод onTalk) имеет следующие параметры:- Y8 i1 W5 v( ]

) T0 n1 k: Q6 H1 s
( d: v6 s: O# a. Y. v" Z: a; m
• self – квест
6 x. ^6 p% W4 K$ Q• npcId – ID NCP, которого мы должны убивать (если это метод onTalk, то ID того NCP, с которым мы должны поговорить).
6 e6 v( U& ]" ~3 l5 Q• st – текущее состояние игрока.) G2 k4 `( o3 c# ^% V  K
% L) S) [& X  X) `2 b2 e# T+ X
! W0 m) P4 [* V: y, H5 B  b: t
В этом методе мы проверяем и отмечаем, является ли убитый NCP keltir’ом. В основном эта проверка не нужна, т.к. у нас только KELTIR_NPC_ID.: i3 C8 f* U3 V3 E4 k' L
+ T. J# m: K+ B( p* Y$ J6 i  F* i

& c" _5 T3 I1 q1 E" N& K8 S& D1 OЗатем проверяем количество предметов (в данном случае количество клыков), и если их вообще нет, то возвращаем строку "Chat0.htm", если только один предмет, то возвращаем строку "Chat1.htm", если же предметов 4 или больше, то "Chat4.htm". Если строка возвращена из методов onEvent, onKill или onTalk, то сервер покажет соответствующие htm. В Chat0.htm может иметь следующий текст: «Вы не имеете ни одного клыка, возвращайтесь позже, когда соберете 4 штуки и бла, бла, бла…», в Chat1.htm может быть следующий текст: «У Вас всего 1 клык, по этому соберите еще…». В Chat4.htm – «Вы собрали необходимое количество предметов, возвращайтесь к вашему тренеру, что бы завершить квест…») \  d, T' l- U

' F) |) k2 |8 B% e5 Y8 S: O! ?  U

' z4 {2 ~# X' s9 d: l* I0 a5 VПримечание: если в строка return начинается с "<html>", то будет показана страничка html с текстом, который стоит далее. Так вместо:
9 ~! L! v( e0 @return "Chat4.htm"4 Z- C0 h# c" \" X8 _8 q% d
' P. n; ?! ]5 v0 ?+ K. p

* ^) d5 A0 U; j. |; Hможно поставить:
* j3 d" t1 T, q2 {. ^
  1. return "<html><body>Return to your trainer to complete the quest</body></html>"
Скопировать код
Так же если строка заканчивается без .htm или в начале нет <html>, то текст будет выведен, как системное сообщение в окне чата. В нашем случае мы сделаем так, что бы при каждом убийстве keltik выводилось системное сообщение: «Собрано N из 4-х клыков».1 q$ a) t( h9 R4 [4 q& }( [
: m. d0 x3 H# b# r+ G
& O4 h+ K8 ?7 v+ C
Наш код для onKill имеет один недостаток. Он будет постоянно показывать Chat0.htm, Chat1.htm и Chat4.htm, нам же необходимо, что бы Chat0.htm и Chat1.htm показывались только один раз. Как нам это сделать? С помощью переменных.% d2 l: Q9 a. z/ I! Z

* q6 K- r2 U$ M
' N: y/ k# c* B2 _) c  N5 e0 @, ?4 H
В каждом квесте строки могут храниться с помощью переменных. Эти переменные сохраняются в Вашей БД. В каждом методе мы можем назначить, прочитать и удалить переменные. Давайте изменим метод onKill, так что бы каждый диалог вызывался только один раз.7 }' y$ p0 f( ~$ o
  1. def onKill (self,npcId,st):- l8 B* x0 f" h1 R* a. B& N  A
  2. if npcId == KELTIR_NPC_ID:  j8 ?7 e- e) ~# ^" H; c: q
  3. n = getCount(st)/ A% s" N" a+ B0 d' h* B- D
  4. if n == 0:
    ! N: Z! Z0 M9 l0 T) ~, L; p
  5. if st.get('chat0') == None :8 [) l2 H% m5 d7 A4 \0 ~
  6. st.set("chat0", "true")
    + t; d" ]( M$ S+ G6 I/ }$ V  z
  7. return "Chat0.htm"9 X- c, q  Z; s0 P( h
  8. elif n == 1:
    - l% t/ {- h5 D2 s, Z! h
  9. if st.get('chat1') == None :  X8 S+ C" X1 [0 T" z0 ?  f
  10. st.set("chat1", "true")
    $ V6 o- b' |* N# Q9 t$ V- U( D
  11. return "Chat1.htm"; L# v0 F5 x$ x! x' j8 Y5 f* c* ^
  12. elif n >= 4:% D8 w( [0 J0 O
  13. return "Chat4.htm"
    + B7 ?8 ~7 `$ C4 I( s
  14. return "Collected "+str(n)+" of 4 fangs"* _! p+ G1 C! M  [
  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.: y; Q2 ^% v* p

) I- N" R% N; H+ y) a7 g
9 n* X5 r& w; X
Вот конечный рабочий вариант квеста:5 m1 {& U  T+ H' m- s2 Z1 ~
  1. import sys% Q. p2 V- t5 j) |/ E
  2. from net.sf.l2j.gameserver.model.quest import State/ R; o' ?% Q% b  X7 y! w) V
  3. from net.sf.l2j.gameserver.model.quest import QuestState
    3 U9 a7 f5 ~) H0 y- X
  4. from net.sf.l2j.gameserver.model.quest.jython import QuestJython as JQuest& j: r' H' |6 i& R8 {8 z

  5. % g8 \8 D, J# I
  6. KELTIR_NPC_ID = 12082
      B0 k4 w& X$ K8 U. _) ^/ p/ ]
  7. FANGS_ITEM_ID = 1859( Q  `. J3 G' _
  8. DROP_RATE    = 500000
      G# m6 f& `: R) g

  9. ! G% A5 d( U. P0 g% O7 D% ~" P
  10. WORLD_MAP_ITEM_ID = 1665  z/ p# l5 x9 j& z/ }( V! v# T8 v

  11. * a; m+ M/ y; ]  K* n% B
  12. def getCount(st) :. f6 D& s) X8 V* W6 p
  13. return st.getQuestItemsCount(FANGS_ITEM_ID)& c: }, u0 }8 R+ o
  14. $ ~7 F* p' Q3 K1 |2 K  v
  15. def completed(st) :
    3 I& a  K6 @( u' @( {/ M! H% {: h9 c
  16. st.setState(COMPLETED)7 F) z" Q' D1 y+ ?9 n0 ~
  17. st.clearQuestDrops()
    3 L5 k9 `; c4 q1 Q5 M3 U
  18. st.takeItems(FANGS_ITEM_ID,-1)% y: c3 D! l4 G. [& |6 J
  19. st.giveItems(WORLD_MAP_ITEM_ID,1): V8 b3 U1 ]5 _% Q$ ]& r
  20. st.exitQuest(False)2 J4 T, A0 d7 d" x$ v# N3 N- q
  21. return
    0 j$ I/ {/ C! r, h; |, {

  22. $ G5 M1 W1 k& |, w
  23. def check(st) :- v; q7 e5 T. K3 i5 v% D+ S4 Y$ @
  24. if getCount(st) >= 4 :- M7 \6 A& s4 p6 w1 U1 r
  25. completed(st)7 X6 Z; N+ T) U/ Z
  26. return8 |9 c3 ^8 Y- w# t. i# `

  27. 2 y$ b3 W6 ^) y
  28. class Quest (JQuest):
    6 n4 E# n) R. j5 n- r

  29. / S- ~  [& x. R+ X* X
  30. def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)
    ( z9 F& h) E9 u9 y& `) ]
  31. ( C6 V( z% B, V, U, g; F) D+ V) N
  32. def onEvent (self,event,st):
    9 M' e% J, W8 x, \/ Q
  33. id = st.getState()
    # `, |# B- ?# {; C
  34. if id == CREATED : st.setState(STARTED)
    , u2 v4 }0 f/ ~7 y/ s
  35. elif id == COMPLETED: pass
    % T2 W( o& E2 R, ^6 C. ?
  36. elif id == STARTED : check(st)  \) @! h7 h" q  |
  37. return5 [  ?+ T) X5 c

  38. $ F- p' f$ O2 i& T3 n! |: {9 \
  39. def onKill (self,npcId,st):" _# y2 w, o1 Q) Q
  40. if npcId == KELTIR_NPC_ID:; V, B3 |5 F+ B$ @1 z0 E
  41. n = getCount(st)
    - y* h0 w" ~3 {( [
  42. if n == 0:
      E4 c/ _5 [* m, l
  43. if st.get('chat0') == None :, }! q/ T' V9 {9 {1 J8 [8 V  L
  44. st.set("chat0", "true")
    * v. g: w) U8 P. I1 r. F3 F! ?9 E
  45. return "Chat0.htm"
    7 v7 T3 p' G3 R4 N; d! y
  46. elif n == 1:3 U  _4 |: t3 G/ I" [  O+ A5 _* Y& G
  47. if st.get('chat1') == None :
    * ?, {$ F1 y! o
  48. st.set("chat1", "true")
    8 S# @. X* v3 }1 d* H, h
  49. return "Chat1.htm"3 W3 H6 G' U4 z! B6 {5 ^: U. u& H
  50. elif n >= 4:& d0 i, P( X, r3 A$ @
  51. return "Chat4.htm"4 f; p8 I4 v2 E( [
  52. return "Collect "+str(n)+" of 4 fangs"
    9 X4 i; c- `1 e% u
  53. return
    ! u) `9 i, J$ _- S  l+ d1 b) S; x) O

  54. % O0 o0 U9 ?% ~
  55. QUEST    = Quest(201, "Tutorial", "Tutorial quest")1 E2 V; q4 l: @3 q
  56. CREATED = State('Start',    QUEST)
    0 F5 w" ?% A! F1 A
  57. STARTED = State('Started', QUEST)- t9 y6 H' }2 A* d3 U
  58. COMPLETED = State('Completed', QUEST)0 o- T) s" `# {, J- K; n4 f; b6 N! ?
  59. ! S9 f5 @3 |4 e/ E# p, G; }; A: c
  60. QUEST.setInitialState(CREATED)
    / t- q5 b! `  J$ Z/ M) t( l
  61. QUEST.addStartNpc(7056)
    # p  ~* X: b( ~( d
  62. QUEST.addStartNpc(7012); c, ?" _5 r  m" A2 u
  63. QUEST.addStartNpc(7009). G) T7 f" E+ X6 t4 c
  64. QUEST.addStartNpc(7011)
    2 |0 d0 p7 A5 O" Z5 l- y
  65. * I: _$ n  w( m' C) E' E- w7 R4 W
  66. STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE): ], B8 T* Z# t4 U
  67. STARTED.addKillId(KELTIR_NPC_ID)4 o- C- v& |: b
  68. STARTED.addTalkId(7056)
    8 q4 I$ _& r% A* H0 m. H6 R
  69. STARTED.addTalkI d(7012)
    1 t; w7 P0 K. k" b* n! S
  70. STARTED.addTalkId(7009)
    9 I- U( j; Y+ M* e* ]5 u( r
  71. STARTED.addTalkId(7011)
Скопировать код

3 Q  w" l- N- g# B& I- U: s- Y3 d. t3 A6 s- O
Чтобы ответить, вам надо авторизироваться в системе Вход | Зарегистрироваться

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

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

638638758

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

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

admin@artace.ru Онлайн

QR-код

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