Top.Mail.Ru

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

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

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

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

x
Хроники        Interlude
7 x+ E9 B: ]" EСборка        L2j
0 C& b/ I% e0 d; OОбратите внимание: в файле htm стартового NCP обязательно должна быть ссылка на квест:+ T8 {) r# i3 r7 X% z5 |
  1. STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код
Для этого квеста больше ничего не надо. Все необходимое для корректной работы квеста уже добавили. Вот полный текст квеста:
( i6 \( Z7 F7 e) ^, x# h3 S$ ^" D7 X! d
  1. if getCount(st) >= 4 :9 x" |! G8 h+ l9 r' P  G1 K
  2. completed(st)
    ' c7 `, r; I/ Y' X3 d- B
  3.   return  [6 F0 x: C4 P1 J  K
  4. # B# y% y; [- U9 U7 q" f
  5. class Quest (JQuest):
    / S; ~9 P$ x6 m1 ?7 o
  6.   def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)3 w( |3 a" n* K) j# I
  7.   def onEvent (self,event,st):$ @5 n/ W) m+ y  U4 _9 M
  8. id = st.getState()4 L. |( u& \# A& J
  9. if   id == CREATED  : st.setState(STARTED)
    . J% S0 F; {( [: {$ l  @6 h
  10. elif id == COMPLETED: pass
    6 i8 X) I8 a6 q& I
  11. elif id == STARTED  : check(st)1 v* T, A# A& X. F" V* Q
  12. return
    ' N4 n7 x; L& r: |/ _: |  D

  13. ; ~6 p9 f% D. @5 F+ c! u
  14. QUEST     = Quest(201,"Tutorial", "Tutorial quest")
    7 C3 ^; P6 J+ }5 A$ F
  15. CREATED   = State('Start',     QUEST), M+ Y& O# z0 y0 }: s6 x
  16. STARTED   = State('Started',   QUEST)
    # O# l) S; T4 E* R( q
  17. COMPLETED = State('Completed', QUEST)/ Y& `! Z# y4 `. f
  18. : K$ ?5 S7 P6 ]0 V
  19. QUEST.setInitialState(CREATED)
    & D. p! R/ n* Q9 t* V- ~7 R1 p
  20. QUEST.addStartNpc(7056)' n- m( K' ]# {' r, d2 ?# C
  21. STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код
Теперь рассмотрим, как это работает.
& i: j" _0 W6 o9 _  a+ yИгрок подходит к начальному NCP (в данном случае 7056), нажимает на «Quest». Квест будет создан и состояние квеста перейдет к CREATED и игроку будет показана страничка Start.htm с описанием квеста. Тогда метод onEvent, поле открытия странички Start.htm переведет состояние квеста в STARTED и игроку будет показана страничка Started.htm, где будет опсание того, как найти keltirs и .т.д.: b; |& s2 R* c9 y' x9 T
+ L# c3 [. W( g2 o0 P" N
, ]4 J( J3 P- {  L$ K% d; J1 W* J
При состоянии STARTED будет зарегистрирован дроп «fangs» при убийстве keltirs. Игрок может вернуться к стартовому NCP и спросить о квесте – метод onEvent будет вызван снова. Если у игрока не хватает необходимого количества предметов, то метод check() не переведет квест в следующее состояние и Started.htm будет показана снова. Но если игрок собрал необходимее количество предметов (в данном случае 4 клыка), то метод check() вызовет метод completed() который переведет квест в новое состояние COMPLETED, заберет все клыки, даст карту мира, т.к. это награда за квест, покажет Completed.htm и завершит квест.
: A) z- R( R5 i# E
* ~9 h, I* B$ \, a3 C* b

+ ?8 X4 p5 A* f4 I1 m3 k9 O. qТеперь давайте сделаем наш квест более похожим на то, что он должен из себя представлять.
6 x4 B; O; |$ C' B" f( l$ w0 G# s( DПрежде всего у нас есть 3 метода для объявления их в Яве – onTalk, onKill и onEvent. Если методы onTalk и onKill не объявлены, то за них все будет делать метод onEvent, т.е. определять квестовых монстров и вызывать диалоги NCP. Есть примечание, методы onTalk и onKill будут вызывать только диалоги с NCP в зависимости от текущего состояния квеста. Метод onKill будет вызываться только тогда, когда мы убиваем квестового монстра.; D/ m: |1 U0 J+ _
: q/ X' [9 B% y+ W' ^) {+ M0 M5 S1 F3 u
6 d% G  @7 C, h  G5 d
Давайте рассмотрим как вызывается метод onKill при убийстве keltir в состоянии квеста STARTED:' K0 G  H# x$ Y" C+ i
  1. STARTED.addKillId(KELTIR_NPC_ID)
Скопировать код
и метод onKill в классе Quest:/ Y  w9 y( @' t7 E' A

5 C2 a  @  B, v7 P
  1. class Quest (JQuest):
    % d' y1 F) W7 j& l% M
  2.   ...
    . C. Y; r8 {5 i( e
  3.   def onKill (self,npcId,st):
    0 o  _1 \% z) V6 F0 n/ a
  4. if npcId == KELTIR_NPC_ID:$ F8 }4 w7 S! y) t" Q$ d
  5.    n = getCount(st)* b0 V) n4 X# ^
  6.    if   n == 0:
    % i$ Y& _* I& v; R
  7.        return "Chat0.htm"1 }. S$ f2 A$ n* V' d
  8.    elif n == 1:
    $ v$ F6 a* h  a4 t* U. M
  9.        return "Chat1.htm"+ X+ w! s, b! ~' |) W5 a% B8 [; _
  10.    elif n >= 4:
    : ?& W0 T' K8 v; C8 S- U3 }/ x
  11.        return "Chat4.htm"% X2 [6 G7 r. \' e0 K# ^3 o# a
  12.    return "Collected "+str(n)+" of 4 fangs"( Q+ L, D; w9 Q+ E
  13. return
Скопировать код
Метод onKill (а так же метод onTalk) имеет следующие параметры:6 t: R6 ~) ~7 \! l1 m9 D2 s* L
7 d) @! r6 j" w( x
% }- e) H$ N# C+ \2 B7 s
• self – квест
6 [! b, G% W1 z- {/ l/ U* R• npcId – ID NCP, которого мы должны убивать (если это метод onTalk, то ID того NCP, с которым мы должны поговорить).; R: w+ p% `. @" r1 ]5 k
• st – текущее состояние игрока.; Z9 f4 q" n& O* i6 B* A8 d
7 G8 r$ T0 z8 G5 ^/ Y

* H; g$ P7 c9 D/ q; A! oВ этом методе мы проверяем и отмечаем, является ли убитый NCP keltir’ом. В основном эта проверка не нужна, т.к. у нас только KELTIR_NPC_ID.
. L+ @2 i; V' }/ J% K; y% {8 d; o- f0 B+ K' i/ P

& e: S# z$ `9 B7 c3 m: Y( k# s: DЗатем проверяем количество предметов (в данном случае количество клыков), и если их вообще нет, то возвращаем строку "Chat0.htm", если только один предмет, то возвращаем строку "Chat1.htm", если же предметов 4 или больше, то "Chat4.htm". Если строка возвращена из методов onEvent, onKill или onTalk, то сервер покажет соответствующие htm. В Chat0.htm может иметь следующий текст: «Вы не имеете ни одного клыка, возвращайтесь позже, когда соберете 4 штуки и бла, бла, бла…», в Chat1.htm может быть следующий текст: «У Вас всего 1 клык, по этому соберите еще…». В Chat4.htm – «Вы собрали необходимое количество предметов, возвращайтесь к вашему тренеру, что бы завершить квест…»* p  b2 V2 B! H) }/ [
' ~4 _% M! A! ?/ z

# [: S/ n' M' OПримечание: если в строка return начинается с "<html>", то будет показана страничка html с текстом, который стоит далее. Так вместо:
0 F" ^8 {* h. i2 d) N8 Vreturn "Chat4.htm") |2 q4 K  q- A! I# S
9 i' P# ]1 g! o
& n4 C+ c3 w& M2 E
можно поставить:
4 H$ ~# }( b7 q- ]  w
  1. return "<html><body>Return to your trainer to complete the quest</body></html>"
Скопировать код
Так же если строка заканчивается без .htm или в начале нет <html>, то текст будет выведен, как системное сообщение в окне чата. В нашем случае мы сделаем так, что бы при каждом убийстве keltik выводилось системное сообщение: «Собрано N из 4-х клыков».
$ p$ Z9 y5 ]: E- w* |9 S! j5 K/ h9 `7 i$ e0 e8 t5 h8 ]
  b5 O# w  y* {, I" ?" J: U
Наш код для onKill имеет один недостаток. Он будет постоянно показывать Chat0.htm, Chat1.htm и Chat4.htm, нам же необходимо, что бы Chat0.htm и Chat1.htm показывались только один раз. Как нам это сделать? С помощью переменных.
9 i' U1 I0 ?- t# k0 P* c! e& G1 b. ?* x
  g% {+ ]  p) [- {
В каждом квесте строки могут храниться с помощью переменных. Эти переменные сохраняются в Вашей БД. В каждом методе мы можем назначить, прочитать и удалить переменные. Давайте изменим метод onKill, так что бы каждый диалог вызывался только один раз.: Q" U% C: k- u$ X* n
  1. def onKill (self,npcId,st):
    9 U% M# n4 J$ q1 }
  2. if npcId == KELTIR_NPC_ID:- F! ]- F* z* C
  3. n = getCount(st)7 [6 Y' {9 u' g8 ?% \5 a
  4. if n == 0:$ g9 o6 V5 d) v, `2 W: L0 N0 s3 {
  5. if st.get('chat0') == None :) b3 l$ p  P2 F! r( S2 D8 O; O1 y
  6. st.set("chat0", "true")
    4 F! x* e& O# J4 b$ |' s
  7. return "Chat0.htm"5 Q' s' g! D9 [: s- U& n; Q/ U
  8. elif n == 1:) {9 n" A2 B7 M% [$ M
  9. if st.get('chat1') == None :' u$ T2 E; J' y4 A
  10. st.set("chat1", "true")& l: w  o; z- }9 E( A8 O- e0 e8 U
  11. return "Chat1.htm"
    / I. U  K: J' H( z  K7 B
  12. elif n >= 4:; \) S: F8 [$ o' S& T# o) s$ j& D
  13. return "Chat4.htm"0 l, t8 K  e( B# G0 {2 Q
  14. return "Collected "+str(n)+" of 4 fangs", J  b2 X; }8 D( }9 p, l4 }
  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.
( C& |  l2 b' C$ K
, q- ]4 O" E8 d9 }/ O  p) x

  G7 j: I" n; a9 J5 S2 {* v3 XВот конечный рабочий вариант квеста:
: C7 E( J4 t+ F$ R
  1. import sys8 T. O5 a! a! s
  2. from net.sf.l2j.gameserver.model.quest import State
    1 E# T- J1 @, Y0 j' G4 P
  3. from net.sf.l2j.gameserver.model.quest import QuestState
    " n. h3 R: x. m0 x( c, }3 J
  4. from net.sf.l2j.gameserver.model.quest.jython import QuestJython as JQuest
    6 K+ U+ M2 R% B1 T7 @

  5. : X$ H' z' l# j' r, k5 ]* H0 l& \
  6. KELTIR_NPC_ID = 12082) E. }2 |: z; J) K/ h6 N& n6 H
  7. FANGS_ITEM_ID = 1859. m2 z% B) U: a0 C" E
  8. DROP_RATE    = 5000001 [/ }: A5 \8 O

  9. - H9 f$ A2 M. s
  10. WORLD_MAP_ITEM_ID = 1665
    / T) T3 N/ z$ V3 `9 O$ [

  11. # L7 S( T+ J, B
  12. def getCount(st) :
    2 x( w  W5 |0 D+ Z* g2 D
  13. return st.getQuestItemsCount(FANGS_ITEM_ID)
    % Q8 Q# @0 G+ m9 c5 y3 x

  14. + X; I2 N: Q- Z- \# x  p; Z
  15. def completed(st) :) B  h. A" p# n9 F1 r
  16. st.setState(COMPLETED)
      h3 ^7 h) B2 m1 l+ a- Z& X' Z* Q$ l2 [
  17. st.clearQuestDrops()' \! ~6 q( V% S; f9 J! w" h
  18. st.takeItems(FANGS_ITEM_ID,-1)6 g) f& v9 y0 _- T, z+ s
  19. st.giveItems(WORLD_MAP_ITEM_ID,1)+ d. {: ~" L: Y; ^% @
  20. st.exitQuest(False)
    % o# ~/ u) D. a8 |8 P0 ^' _
  21. return% l; |/ ^: A: l9 @) P$ N

  22. " Y" e: U3 e  f6 q' D8 o2 ^5 _9 q
  23. def check(st) :
    3 g+ |% B- y* Y7 c
  24. if getCount(st) >= 4 :2 x6 Z" C% ~5 S# f' x
  25. completed(st)
    . F' R6 u. V; B5 z# P2 B! ]
  26. return
    * F  J( S8 Z& y  j0 ?3 ]
  27. , T3 D4 q/ @. ]# F
  28. class Quest (JQuest):+ A  Q( X- t% e+ C5 q7 y

  29. - k- O# h, B+ v& o* B# T
  30. def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)# n/ o5 E2 D% k; z$ u* A7 O
  31. 3 h/ D+ |; e: n* r! y
  32. def onEvent (self,event,st):
    1 M, ?" P" a  F8 m6 f
  33. id = st.getState()2 @# [' o: s$ g- T4 j8 u
  34. if id == CREATED : st.setState(STARTED)
    1 b; K- ~0 t2 B$ z7 }* O+ W. d6 V
  35. elif id == COMPLETED: pass- o8 @: a- U% J  @
  36. elif id == STARTED : check(st)' L% X# l- l$ n& M% R& U
  37. return
      i/ J' J7 z8 [9 o# j1 i! i

  38. % O& N0 M& E+ ?% P/ O: K
  39. def onKill (self,npcId,st):- E9 |/ r9 r' P) [8 n% O# B
  40. if npcId == KELTIR_NPC_ID:
    ) [, g2 f. b) @. Y  o7 _& K
  41. n = getCount(st)) R3 d; w2 J  i$ j( I) S7 G1 a
  42. if n == 0:7 |; k% y" R6 L, J+ Q) \0 S
  43. if st.get('chat0') == None :# Y6 p6 Q, k  P5 i$ Z
  44. st.set("chat0", "true")& a1 G# \0 E5 A! X1 _9 N+ _0 P9 G
  45. return "Chat0.htm"" Y* H, p+ |, M0 t
  46. elif n == 1:4 T& b  I7 y) k' N! K  |
  47. if st.get('chat1') == None :
    : F2 H# o: `- n7 H# D0 C* w
  48. st.set("chat1", "true")
    # r! u/ t" c7 S  |3 {& x
  49. return "Chat1.htm"
    & {: ?$ k( \" o/ W
  50. elif n >= 4:
    / b9 C, \7 G! h) v7 F, E+ _
  51. return "Chat4.htm"
    8 Z, E/ P# O- |3 k9 ]$ x( l9 g" f
  52. return "Collect "+str(n)+" of 4 fangs"  n1 h0 L! I+ e. a
  53. return( a: F- \  Q2 U( J) m  F% h; ~

  54. 7 ^* z  R2 P6 @6 K0 V
  55. QUEST    = Quest(201, "Tutorial", "Tutorial quest")0 x# U4 {1 M) |% s. ^7 K
  56. CREATED = State('Start',    QUEST)8 u* U3 r: n4 O; t5 A0 y/ G. n$ s* a
  57. STARTED = State('Started', QUEST). E% u: P4 q- }9 o
  58. COMPLETED = State('Completed', QUEST)
    7 _, K2 T6 Y( n

  59. ' s, P1 p9 s  j+ I' X! J, {7 B
  60. QUEST.setInitialState(CREATED)& D+ [( y  i6 z3 ^4 ]
  61. QUEST.addStartNpc(7056)
    7 `# V9 M! e3 Q/ V0 Y
  62. QUEST.addStartNpc(7012)
    5 v8 t* c7 G4 ]- {
  63. QUEST.addStartNpc(7009)
    9 J2 }! a, x7 P3 H# \
  64. QUEST.addStartNpc(7011): u( u$ ~/ X" v! s# [, w
  65. & f# ?3 j% Z9 Q# G! x  U2 ]# N* {% C
  66. STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
    ; N' c$ h' ^) ]  M
  67. STARTED.addKillId(KELTIR_NPC_ID)
    1 Z. V" ?0 b9 s% @
  68. STARTED.addTalkId(7056)
    * K; h7 {: n$ z0 o3 c3 |/ e
  69. STARTED.addTalkI d(7012)
    ' s" ^/ n3 ]" N; M) W# O( A
  70. STARTED.addTalkId(7009): [- I# ~) C( P# M
  71. STARTED.addTalkId(7011)
Скопировать код

$ R1 ~/ Q; E5 {) O7 ]  h+ }
7 ^7 ^. u" }0 X
Чтобы ответить, вам надо авторизироваться в системе Вход | Зарегистрироваться

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

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

638638758

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

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

admin@artace.ru Онлайн

QR-код

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