Top.Mail.Ru

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

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

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

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

x
Хроники        Interlude
, {  L, r2 t4 M8 a- l- iСборка        L2j) {6 P) C8 t/ y. m
Обратите внимание: в файле htm стартового NCP обязательно должна быть ссылка на квест:: d, B7 b/ H. p; s. j8 J4 q
  1. STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код
Для этого квеста больше ничего не надо. Все необходимое для корректной работы квеста уже добавили. Вот полный текст квеста:
  P; d) k, h! r% [$ u) F& O: X# |: A) n& p
  1. if getCount(st) >= 4 :9 p: l: x: W& m% l
  2. completed(st)/ c' y( {% Q5 Q5 j0 ?
  3.   return
    * N2 T& i2 q: ~. V

  4. 8 |1 Q5 o, f) Q4 P$ Y
  5. class Quest (JQuest):0 f5 Y. w! L: D' G4 X
  6.   def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)
    4 ^3 a8 b* `: K0 v, b' d, e1 R+ E
  7.   def onEvent (self,event,st):2 q2 X2 L" ]) \  F# j" J8 t
  8. id = st.getState()
    + Y" B/ _) o$ K* Q; ?
  9. if   id == CREATED  : st.setState(STARTED)) B# E6 C, O8 @: {; G2 E
  10. elif id == COMPLETED: pass
    1 |% H: o# Q4 r
  11. elif id == STARTED  : check(st)) D+ O3 ^& n$ Z( \- D2 w
  12. return4 K' u# h, |1 S+ k& I
  13. ) n7 ?9 P! F. @" i( I- {4 I, B4 k; V
  14. QUEST     = Quest(201,"Tutorial", "Tutorial quest")3 j* R0 ~6 b  ?1 [7 J
  15. CREATED   = State('Start',     QUEST)
    ' N% u- h& r7 X9 @3 T
  16. STARTED   = State('Started',   QUEST)! g) i" h/ J# m7 c; x
  17. COMPLETED = State('Completed', QUEST)! V' H, u! j+ L0 v2 o9 H
  18. 2 O5 i% |  H0 y# e" T% K7 Z* d
  19. QUEST.setInitialState(CREATED)
    ; N* J' ?/ B( O4 Y
  20. QUEST.addStartNpc(7056)
    " v' h! v1 J1 x. \. y
  21. STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код
Теперь рассмотрим, как это работает.
. P6 k3 E+ ~, }1 c/ z- G5 o! a9 k% \* bИгрок подходит к начальному NCP (в данном случае 7056), нажимает на «Quest». Квест будет создан и состояние квеста перейдет к CREATED и игроку будет показана страничка Start.htm с описанием квеста. Тогда метод onEvent, поле открытия странички Start.htm переведет состояние квеста в STARTED и игроку будет показана страничка Started.htm, где будет опсание того, как найти keltirs и .т.д.0 O0 [8 A; b" i+ o! ]  T/ o7 c7 r
, V6 Y- ~! C: E+ `4 u

/ r' w( d5 N% X3 m4 ~8 E3 jПри состоянии STARTED будет зарегистрирован дроп «fangs» при убийстве keltirs. Игрок может вернуться к стартовому NCP и спросить о квесте – метод onEvent будет вызван снова. Если у игрока не хватает необходимого количества предметов, то метод check() не переведет квест в следующее состояние и Started.htm будет показана снова. Но если игрок собрал необходимее количество предметов (в данном случае 4 клыка), то метод check() вызовет метод completed() который переведет квест в новое состояние COMPLETED, заберет все клыки, даст карту мира, т.к. это награда за квест, покажет Completed.htm и завершит квест.
2 z  V7 V% `( [( w/ M# k" y) Z( A! o6 b

3 s+ U- K/ t3 a  u5 Y  RТеперь давайте сделаем наш квест более похожим на то, что он должен из себя представлять.; @4 U  I4 M! l; O: [
Прежде всего у нас есть 3 метода для объявления их в Яве – onTalk, onKill и onEvent. Если методы onTalk и onKill не объявлены, то за них все будет делать метод onEvent, т.е. определять квестовых монстров и вызывать диалоги NCP. Есть примечание, методы onTalk и onKill будут вызывать только диалоги с NCP в зависимости от текущего состояния квеста. Метод onKill будет вызываться только тогда, когда мы убиваем квестового монстра.
& y8 ^# i, o, q/ S7 p8 d1 z  W% i' l1 b

- P5 }  U1 S) t5 z/ o: oДавайте рассмотрим как вызывается метод onKill при убийстве keltir в состоянии квеста STARTED:
: a0 ~# w" Z- b& G4 n9 Y
  1. STARTED.addKillId(KELTIR_NPC_ID)
Скопировать код
и метод onKill в классе Quest:
& k5 e. [4 r9 M7 |/ {7 ~3 v- l# O/ k- I/ N% B; Z
  1. class Quest (JQuest):
    8 {; M& F/ ?% C9 r2 r
  2.   ..." U; o" s: ]3 a3 u* D5 B' M4 X
  3.   def onKill (self,npcId,st):
    ) T) t' Z2 Y9 r/ w2 f
  4. if npcId == KELTIR_NPC_ID:
    5 K/ W2 R( c. P: I# W0 ?
  5.    n = getCount(st)) r& `2 E' |; d+ R' t
  6.    if   n == 0:
    ' `2 q3 l& e1 y6 {' w- ]% X5 t2 H
  7.        return "Chat0.htm"* e7 ]5 P, f! D$ ?
  8.    elif n == 1:, x- N( S7 V$ s# P. s2 ]
  9.        return "Chat1.htm"7 @7 J! k# b( }8 r
  10.    elif n >= 4:5 X! n/ `6 b+ _# J6 H/ m* [: n
  11.        return "Chat4.htm"+ ^# n9 L- {7 _# C  N8 ?# Z4 w
  12.    return "Collected "+str(n)+" of 4 fangs"
    6 @8 D4 e! D  D" E* b1 ^! \$ s
  13. return
Скопировать код
Метод onKill (а так же метод onTalk) имеет следующие параметры:. F' V, ^* T7 W* @
3 ~; m  a9 R* ?) }9 G( E; J! ~* m, l
; q4 R+ k8 W: c' P, F2 y- Y+ S  ^
• self – квест
' H) o5 U* ~- Q• npcId – ID NCP, которого мы должны убивать (если это метод onTalk, то ID того NCP, с которым мы должны поговорить).0 A  w- ?9 s0 G+ l$ l
• st – текущее состояние игрока./ x: o$ [& Y* C8 c
" ?. i' l6 A/ X: R: }/ C

' ~6 K' t3 `2 k4 G% D6 M3 r! QВ этом методе мы проверяем и отмечаем, является ли убитый NCP keltir’ом. В основном эта проверка не нужна, т.к. у нас только KELTIR_NPC_ID.  a8 k; z1 [4 N5 L8 Q( P
& E; A/ F. s4 n# g

) Y& M$ v2 M# s6 @) Z# ~5 LЗатем проверяем количество предметов (в данном случае количество клыков), и если их вообще нет, то возвращаем строку "Chat0.htm", если только один предмет, то возвращаем строку "Chat1.htm", если же предметов 4 или больше, то "Chat4.htm". Если строка возвращена из методов onEvent, onKill или onTalk, то сервер покажет соответствующие htm. В Chat0.htm может иметь следующий текст: «Вы не имеете ни одного клыка, возвращайтесь позже, когда соберете 4 штуки и бла, бла, бла…», в Chat1.htm может быть следующий текст: «У Вас всего 1 клык, по этому соберите еще…». В Chat4.htm – «Вы собрали необходимое количество предметов, возвращайтесь к вашему тренеру, что бы завершить квест…»- s4 {9 i8 h7 Y0 Y

" U% R7 K; U. b' O$ `

' \* C2 b% l. i* d% o; _+ c- {Примечание: если в строка return начинается с "<html>", то будет показана страничка html с текстом, который стоит далее. Так вместо:# i/ i& j7 N; j# \- |" F5 a9 N2 X
return "Chat4.htm"
5 z* ]0 Y: @  m* ]; Q1 Q
. Q( J9 m* o6 `8 m+ H
' g. d' g/ x- Z4 J" {* ~7 S
можно поставить:
' y: y! w6 P/ T7 S, O3 a4 t& S( u
  1. return "<html><body>Return to your trainer to complete the quest</body></html>"
Скопировать код
Так же если строка заканчивается без .htm или в начале нет <html>, то текст будет выведен, как системное сообщение в окне чата. В нашем случае мы сделаем так, что бы при каждом убийстве keltik выводилось системное сообщение: «Собрано N из 4-х клыков».
5 q* x2 C8 f- V. }
+ P0 c5 A: g, V2 M% M5 t5 ^

% |1 V, o0 n) ~* gНаш код для onKill имеет один недостаток. Он будет постоянно показывать Chat0.htm, Chat1.htm и Chat4.htm, нам же необходимо, что бы Chat0.htm и Chat1.htm показывались только один раз. Как нам это сделать? С помощью переменных.8 R: Y; i8 k) |& G, q
- b1 F9 B$ A6 p) B4 \. K4 j
5 ^, t8 O# Z  {% ^- c
В каждом квесте строки могут храниться с помощью переменных. Эти переменные сохраняются в Вашей БД. В каждом методе мы можем назначить, прочитать и удалить переменные. Давайте изменим метод onKill, так что бы каждый диалог вызывался только один раз.: P" ^2 G- x& O- f
  1. def onKill (self,npcId,st):& e% J, F6 L; ?+ z
  2. if npcId == KELTIR_NPC_ID:2 u7 M! p5 N; T  {3 N( z  w
  3. n = getCount(st); W8 u! C& r4 e/ _
  4. if n == 0:
    4 R( M7 F6 M$ O! U! p: L- c* m# a
  5. if st.get('chat0') == None :
    5 V; x+ v. W$ b8 e+ Z
  6. st.set("chat0", "true"), D- R. F- e- H5 c* u4 F
  7. return "Chat0.htm": s8 x/ t7 K/ A5 [. h
  8. elif n == 1:0 j4 D, U1 Z1 ]. m# k" G
  9. if st.get('chat1') == None :8 B& j% m" \# v
  10. st.set("chat1", "true")
    / ]+ y3 N2 S( }- g9 `: m# c
  11. return "Chat1.htm"
    & F. {2 B# t& g: C& q2 ~
  12. elif n >= 4:
    4 z3 z2 n9 @' O0 q- H+ q$ W1 G( r
  13. return "Chat4.htm"
    / m' L( @' M0 A5 R: s0 H* s* V+ O
  14. return "Collected "+str(n)+" of 4 fangs"
    , D+ C& a- c0 Z* U. E: Q
  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.: P0 ~3 v$ C; N

* o6 G( V' w5 b
1 I; t* V- [+ `& E% Z
Вот конечный рабочий вариант квеста:! a0 Q0 s- L3 I  h+ Z3 |$ P3 @8 g
  1. import sys
    $ R8 u/ t. x( I- L. v# v, B' N3 M  ^. L
  2. from net.sf.l2j.gameserver.model.quest import State
    4 B( X7 z  w: ]; P" \
  3. from net.sf.l2j.gameserver.model.quest import QuestState. S; l6 J2 _( s
  4. from net.sf.l2j.gameserver.model.quest.jython import QuestJython as JQuest6 x9 k1 S9 t2 V. Q  [5 `

  5. 6 ~! B, p5 ]& G. A) s& B1 @
  6. KELTIR_NPC_ID = 12082
    - e+ I( s' p/ F" ^9 \9 v! `7 ~3 I/ N" m
  7. FANGS_ITEM_ID = 1859
    # i. |% G6 a1 n6 z* e" O
  8. DROP_RATE    = 500000
    8 M+ ^3 [8 k  ^# o

  9. " |8 G  U% k% G$ K: _/ R7 W; m
  10. WORLD_MAP_ITEM_ID = 1665
    & F8 z$ d$ v8 p1 J+ a
  11.   z1 n% d: [* Y6 p
  12. def getCount(st) :3 T8 Z6 N7 w  N: x
  13. return st.getQuestItemsCount(FANGS_ITEM_ID)
    / s) e% j; h; ~6 ?$ t3 Y6 ]0 h

  14. , }) V0 Q0 L- _4 S0 D6 i
  15. def completed(st) :) ?- R4 h- o: e6 l
  16. st.setState(COMPLETED): H$ g! d7 g: g: L
  17. st.clearQuestDrops()! b$ Z( A* c% x% N) I
  18. st.takeItems(FANGS_ITEM_ID,-1). z. r2 @: G3 Y# Y( b/ a& I' x
  19. st.giveItems(WORLD_MAP_ITEM_ID,1)
    - d  E/ i8 x  m8 ?, S
  20. st.exitQuest(False)
    4 m* ^; g  v- U( i( N
  21. return# z9 v4 y) m+ E% w8 N

  22. , V3 p  K1 h8 O
  23. def check(st) :  U- e% J' L+ K) I( u% U
  24. if getCount(st) >= 4 :/ y6 z1 Q* L1 |
  25. completed(st)
    + N: Z5 X' |3 Z5 C' F/ n( [
  26. return
    # e, q0 a5 ^! ~! Q3 j0 h$ [# A# G
  27. : v5 U, c9 B! K) p( e
  28. class Quest (JQuest):
    1 U5 O5 n- C7 _% {0 t6 v
  29. 2 k8 {5 U( d/ d+ ]
  30. def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr). ^5 K  `! h/ U  Z% @9 z7 k# p! Q

  31. - I4 {6 L; l" b  a
  32. def onEvent (self,event,st):# y5 @4 o" L) O3 s! I! g
  33. id = st.getState()1 d9 \) C4 a+ n6 l
  34. if id == CREATED : st.setState(STARTED)9 f. v+ [, j6 s9 e0 O( U
  35. elif id == COMPLETED: pass
    ' C: [0 I# G! ?2 C+ w3 a
  36. elif id == STARTED : check(st)
    * U$ k$ T* L* {' B+ z, R+ D* c
  37. return( k/ [3 V+ ?. {3 l2 }
  38. 6 Z  q, `( N& k/ \$ p$ B
  39. def onKill (self,npcId,st):
    ; O- \9 X* k5 c7 E/ O
  40. if npcId == KELTIR_NPC_ID:
    - V! z+ p7 k( ?- o' S$ I
  41. n = getCount(st)
    6 m8 z/ g3 q) G9 a: Q
  42. if n == 0:
    ! R/ [( p; Y+ [" f+ m  D$ s4 m
  43. if st.get('chat0') == None :
    9 e: v6 d; B0 {2 S9 K
  44. st.set("chat0", "true")( t, D5 t5 i& E, Q/ ~2 X7 P. J
  45. return "Chat0.htm"8 K- b* N1 G+ d$ W
  46. elif n == 1:( _; g* A' q2 `+ }/ n+ _
  47. if st.get('chat1') == None :( d  S2 g6 Z+ T& h" W
  48. st.set("chat1", "true")
    . @1 _" ^3 E. f. `6 n
  49. return "Chat1.htm"
    , U. Z0 n5 `+ u/ l( ]0 }3 d
  50. elif n >= 4:
    # r9 v* c; P' K+ ]
  51. return "Chat4.htm"1 f9 f+ c9 F! v; H! c! D$ {  C
  52. return "Collect "+str(n)+" of 4 fangs"
    2 Q$ M; I( p) B2 `8 n) r1 h! H! F* Q
  53. return
    0 Q& d, V) }5 T1 B( N

  54. # d, R+ f: @, n* @1 k/ I' t- @
  55. QUEST    = Quest(201, "Tutorial", "Tutorial quest"): N, c: ?1 K$ ^7 D  @
  56. CREATED = State('Start',    QUEST)
    . Z: T4 R4 ]3 c; J
  57. STARTED = State('Started', QUEST)$ @( d$ W* F2 E9 _
  58. COMPLETED = State('Completed', QUEST)
    & X2 E  ?3 p$ ?

  59. ( P& ^% J1 L# B7 D" ]4 K6 D# v" T
  60. QUEST.setInitialState(CREATED)
    / }- F# u; Y) T$ _
  61. QUEST.addStartNpc(7056): i" z- L3 _) C3 q1 X5 V2 a
  62. QUEST.addStartNpc(7012)
    & R0 l# f2 X/ E! z" e
  63. QUEST.addStartNpc(7009)
    + ?" M) J) Q+ b9 B
  64. QUEST.addStartNpc(7011)  P! ]2 V) p+ P8 K& `) w3 }

  65. 6 H3 H2 o' m. x0 r7 Z0 F+ u
  66. STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
    : n! |5 J0 K' Z5 t0 S: O
  67. STARTED.addKillId(KELTIR_NPC_ID)
    , o+ s/ Y4 u% j; Q" t
  68. STARTED.addTalkId(7056)
    1 R7 a+ l5 w7 K9 H2 k$ M! M
  69. STARTED.addTalkI d(7012)$ ?( B! K; B3 [! D
  70. STARTED.addTalkId(7009)& X! D% q' s, ]! F
  71. STARTED.addTalkId(7011)
Скопировать код

/ `! S( {" h! p! A  d
' ~: G7 H+ @. @
Чтобы ответить, вам надо авторизироваться в системе Вход | Зарегистрироваться

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

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

638638758

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

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

admin@artace.ru Онлайн

QR-код

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