Зарегистрируйтесь сейчас чтобы найти еще больше друзей, и получить полноценный доступ ко всем функциям сайта!
Для просмотра Вам необходимо авторизоваться Если Вы еще не зарегистрированы, перейдите по ссылке:Зарегистрироваться
x
Хроники Interlude
. O l7 | k) }8 X; ~: f3 n [Сборка L2j
. ]* p8 M. f$ d& p* q. WОбратите внимание: в файле htm стартового NCP обязательно должна быть ссылка на квест:( T s4 j) ?$ d" A6 @
- STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код Для этого квеста больше ничего не надо. Все необходимое для корректной работы квеста уже добавили. Вот полный текст квеста:
. J$ B& d5 p2 R8 d8 v
3 d' l8 A0 E& p4 u- if getCount(st) >= 4 :# L( _8 i: H" u
- completed(st)
) B0 k; f. h0 o2 @8 j; f - return! v$ Q/ G K. G& V. R7 {
" g5 ~: b" t1 Z" z0 ^- class Quest (JQuest):# C8 c& F$ W3 B
- def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)1 I5 k* |# X, t- Y& q2 E
- def onEvent (self,event,st):
# Z4 h* z) c* v# h - id = st.getState()8 `2 D0 z4 K1 [; |2 B
- if id == CREATED : st.setState(STARTED)2 L9 p! A/ F( O
- elif id == COMPLETED: pass1 {5 Y; o' V' A `' I: C* Q$ s
- elif id == STARTED : check(st)4 b+ h4 K( ?% S
- return
# s. q. Z9 p% ?) y2 h. Q2 o! T) O
/ V4 `' g) a/ E- s- QUEST = Quest(201,"Tutorial", "Tutorial quest")
7 D+ ^3 @+ ?1 b0 F# L$ h: }* P% Q - CREATED = State('Start', QUEST)* D/ @& B: v) d* i! M
- STARTED = State('Started', QUEST)9 O- c( C2 l1 D5 J0 |: [* j' l
- COMPLETED = State('Completed', QUEST)
" A1 U5 z: A( w) J0 p( k - l3 @4 E$ c0 d: B2 H5 q4 j9 c
- QUEST.setInitialState(CREATED)+ E+ E( }+ C& g8 s3 l
- QUEST.addStartNpc(7056)
) [+ l1 Q2 E9 O' T1 n8 B" N6 l - STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код Теперь рассмотрим, как это работает., ]' Z3 m4 t2 l1 O5 C0 u
Игрок подходит к начальному NCP (в данном случае 7056), нажимает на «Quest». Квест будет создан и состояние квеста перейдет к CREATED и игроку будет показана страничка Start.htm с описанием квеста. Тогда метод onEvent, поле открытия странички Start.htm переведет состояние квеста в STARTED и игроку будет показана страничка Started.htm, где будет опсание того, как найти keltirs и .т.д. J- ~, d' \9 Z7 X4 I
' |$ u, X; L( ~/ I
. x) p) N0 N6 F) ~
При состоянии STARTED будет зарегистрирован дроп «fangs» при убийстве keltirs. Игрок может вернуться к стартовому NCP и спросить о квесте – метод onEvent будет вызван снова. Если у игрока не хватает необходимого количества предметов, то метод check() не переведет квест в следующее состояние и Started.htm будет показана снова. Но если игрок собрал необходимее количество предметов (в данном случае 4 клыка), то метод check() вызовет метод completed() который переведет квест в новое состояние COMPLETED, заберет все клыки, даст карту мира, т.к. это награда за квест, покажет Completed.htm и завершит квест.
- {3 ]1 M% }+ ~+ }1 |7 F7 i5 W. u& e7 }- [2 t
4 i+ @7 w2 Z+ s8 v2 X. b3 vТеперь давайте сделаем наш квест более похожим на то, что он должен из себя представлять.6 p1 ]5 E6 ^4 D( V) N
Прежде всего у нас есть 3 метода для объявления их в Яве – onTalk, onKill и onEvent. Если методы onTalk и onKill не объявлены, то за них все будет делать метод onEvent, т.е. определять квестовых монстров и вызывать диалоги NCP. Есть примечание, методы onTalk и onKill будут вызывать только диалоги с NCP в зависимости от текущего состояния квеста. Метод onKill будет вызываться только тогда, когда мы убиваем квестового монстра.
) H/ s8 Q5 V) u4 p- j8 i5 r2 z X ^/ J( T. z
- C$ w" |) M! k* d5 p8 YДавайте рассмотрим как вызывается метод onKill при убийстве keltir в состоянии квеста STARTED:
8 L: ~! |) d. w+ _& L3 a5 v& I- STARTED.addKillId(KELTIR_NPC_ID)
Скопировать код и метод onKill в классе Quest:, W0 ~6 U; ~# ?1 u( p
x2 @% N# O5 _7 ^0 y
- class Quest (JQuest):
+ ?/ P( [ s. p1 N4 }+ B - ..." f, A, R$ ?' M+ o
- def onKill (self,npcId,st):4 Y$ i1 K7 d/ k% X" L+ X; ^' q
- if npcId == KELTIR_NPC_ID:
. C' g# O, U8 j0 ]+ V - n = getCount(st)
& J/ [& d$ d& C9 a# h - if n == 0: t) v6 B5 f* f) r' \
- return "Chat0.htm"7 Y/ m3 e0 {4 ~
- elif n == 1:* V2 {4 ]$ @/ Y8 I2 T
- return "Chat1.htm"
$ y( W3 m1 w& C$ m! E. Y9 D! j; o' B - elif n >= 4:
; S/ v6 d- R8 }' | - return "Chat4.htm". H W0 u p3 p0 |5 s
- return "Collected "+str(n)+" of 4 fangs"
1 [' Z0 l6 Q' C$ x0 l! Q - return
Скопировать код Метод onKill (а так же метод onTalk) имеет следующие параметры:
# q4 [6 k' U6 | [. M- r6 K' ?4 e2 ]7 v( H* Z4 l: M. [
8 h9 V7 O0 @+ R# p• self – квест, c- U/ R" O7 T# L
• npcId – ID NCP, которого мы должны убивать (если это метод onTalk, то ID того NCP, с которым мы должны поговорить).
& t: i! ^5 f9 e% P! E+ H' j• st – текущее состояние игрока.
% U! w% f: H/ f# d6 q
, _+ Z0 B" P- w- o. M/ S4 Z$ K9 @" I* t- b8 h, }. ?
В этом методе мы проверяем и отмечаем, является ли убитый NCP keltir’ом. В основном эта проверка не нужна, т.к. у нас только KELTIR_NPC_ID.
, k9 e9 p$ C, h) f: m9 d4 c: z
$ r- ? _! a; ]/ _: V1 o; u1 D. u4 f, l1 E" K D U) w: L6 R$ q
Затем проверяем количество предметов (в данном случае количество клыков), и если их вообще нет, то возвращаем строку "Chat0.htm", если только один предмет, то возвращаем строку "Chat1.htm", если же предметов 4 или больше, то "Chat4.htm". Если строка возвращена из методов onEvent, onKill или onTalk, то сервер покажет соответствующие htm. В Chat0.htm может иметь следующий текст: «Вы не имеете ни одного клыка, возвращайтесь позже, когда соберете 4 штуки и бла, бла, бла…», в Chat1.htm может быть следующий текст: «У Вас всего 1 клык, по этому соберите еще…». В Chat4.htm – «Вы собрали необходимое количество предметов, возвращайтесь к вашему тренеру, что бы завершить квест…»
) [- S, w+ F, ?2 J
& d% \6 X; E1 T6 G
$ ?& E1 Y) k9 _3 `$ k) ~% W7 VПримечание: если в строка return начинается с "<html>", то будет показана страничка html с текстом, который стоит далее. Так вместо:/ S' z1 R) r% q) p6 Y+ c4 s
return "Chat4.htm"* e: N3 q$ t3 r8 t/ v8 \" A' Y
) @' g. E* l9 n. `* h' `6 k& P; O5 c1 z- h( P8 k
можно поставить:0 N7 g% C, f% u3 F
- return "<html><body>Return to your trainer to complete the quest</body></html>"
Скопировать код Так же если строка заканчивается без .htm или в начале нет <html>, то текст будет выведен, как системное сообщение в окне чата. В нашем случае мы сделаем так, что бы при каждом убийстве keltik выводилось системное сообщение: «Собрано N из 4-х клыков».
3 y* H, K7 b1 E9 k; v% y& P% i
( S8 x0 u, D8 ` J
# S& ]0 F3 @, E7 K- @4 i' wНаш код для onKill имеет один недостаток. Он будет постоянно показывать Chat0.htm, Chat1.htm и Chat4.htm, нам же необходимо, что бы Chat0.htm и Chat1.htm показывались только один раз. Как нам это сделать? С помощью переменных.
/ b$ |% V0 |1 Z* N6 } Q; {
4 f7 O: I* v+ k3 N0 m0 r) ]- }. ?) Q# T' q$ E7 g3 ~
В каждом квесте строки могут храниться с помощью переменных. Эти переменные сохраняются в Вашей БД. В каждом методе мы можем назначить, прочитать и удалить переменные. Давайте изменим метод onKill, так что бы каждый диалог вызывался только один раз.
) Y; @7 ?7 {5 s) k" n% ^( b/ D- def onKill (self,npcId,st):
; D5 ^2 ], d: z6 o* H' j: l - if npcId == KELTIR_NPC_ID:& d$ N; X! K# e* C8 f: d# @
- n = getCount(st)
* b& a' R7 o; N/ ^ - if n == 0:
! c b) d1 h6 e, B( z - if st.get('chat0') == None :+ W: D h: u/ g# O8 j9 o8 t6 D1 V: v* a
- st.set("chat0", "true")
2 w, x4 l! \0 w. m) K$ L3 l2 e# ^ - return "Chat0.htm"
3 ?4 u* {# ^7 k' z$ M - elif n == 1:
; g( f* R3 b5 T d+ X. l R - if st.get('chat1') == None :$ \* H X6 Q) `7 n8 o
- st.set("chat1", "true")
! e. ~/ k9 Q" O; k1 x4 k1 P+ [ - return "Chat1.htm"$ }% g" M" s- n. H- ]/ Y- u) k+ \7 m
- elif n >= 4:2 J! l0 K+ S* }8 F- ~' [) j
- return "Chat4.htm"
6 s" C, V6 T3 B$ S' O - return "Collected "+str(n)+" of 4 fangs"! d, u8 L; N1 p! ~, p9 V
- return
Скопировать код Если у игрока нет клыков (n=0), то мы получаем занчение переменной 'chat0'. Когда метод onKill вызван в первый раз, то пока ни каких переменных не имеется и python возвращает значение None. В этом случае объявляется переменная и показывается диалог Chat0.htm. Когда мы убиваем keltir, но не получаем с него клык, функция st.get('chat0') возвращает строку true, а не None. И во второй раз окно с Chat0.htm не появится, но в окне чата появится строчка «Collected 0 of 4 fangs». По тому же принципу сделано и с Chat1.htm.
- `8 t# P7 [# P3 m9 Z _
: m# G; \' S `
1 I: |( Z& i0 f, ^Вот конечный рабочий вариант квеста:
; \* E D! c3 @/ [- import sys
& S9 W# m. o% I - from net.sf.l2j.gameserver.model.quest import State
& O5 S" i9 \( c/ ]& Q5 z' j - from net.sf.l2j.gameserver.model.quest import QuestState
/ ?" L5 y/ ?/ I6 x. T/ X1 U - from net.sf.l2j.gameserver.model.quest.jython import QuestJython as JQuest% l. ^+ h& R1 t
- ; j3 G3 ]9 m" ]8 f* v! S, {6 U
- KELTIR_NPC_ID = 12082) r+ p- R3 j; G: L* i6 p( u8 B' i" ]
- FANGS_ITEM_ID = 18594 ^. Y- C3 U p' c! q) q
- DROP_RATE = 500000
7 t$ g9 w7 t# b3 Z O" k" k* A+ z - - n" k8 H/ b+ W+ }; O0 M* B
- WORLD_MAP_ITEM_ID = 1665
* z! _1 v6 L' i3 [8 \8 C: M
6 R$ k& M! ^/ ~- K6 E9 ?$ y2 E- def getCount(st) :
5 g4 w7 [$ y* k - return st.getQuestItemsCount(FANGS_ITEM_ID), S: I/ H0 F: y5 \0 s
- ) {0 H) w% I; L6 {$ j. R( k( b
- def completed(st) :3 l2 [% p& B2 E1 \
- st.setState(COMPLETED)
4 [2 f! K7 y9 W9 {- m - st.clearQuestDrops()% ]0 G: s7 \( v, U- S5 C6 ?
- st.takeItems(FANGS_ITEM_ID,-1): q% `3 e: J& r, `- D: c
- st.giveItems(WORLD_MAP_ITEM_ID,1)% h V0 j$ @' M/ r; {
- st.exitQuest(False)
' B0 s! M, H/ g! l - return2 @- e- U% ]# F1 y
) v) K/ k0 k) u' M9 C, ^, {2 N- def check(st) :
& k+ l+ v) g( p' w - if getCount(st) >= 4 :
% |1 O1 E* r" E8 i* r - completed(st)
) O( _! e( X0 L7 X& P - return+ y( G/ B: U- s: |( ^; _$ B
" i. p- V+ }& ~. i: g- V- class Quest (JQuest):8 x2 q2 \6 ?# t6 m4 \
4 Y- i- N4 p' _& o# x( K- def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)
5 ?$ Z0 u- o) a r
! \" q1 X. _2 a" ^! _+ c- N: n; C- def onEvent (self,event,st):
% p& t. I. u( V/ K6 k" s - id = st.getState()
2 Y/ ^0 v6 p# U3 U# a1 c- j - if id == CREATED : st.setState(STARTED)
& ^+ |) O, g9 r2 s0 n+ l4 Y7 A. _ - elif id == COMPLETED: pass
& N' h5 k! N' Q; @! x! v& n; f2 g - elif id == STARTED : check(st)4 a1 M( d3 ]9 v6 N& K7 ^8 d/ v
- return
* I! b( r$ |, T9 ~0 ^/ t - ( Q. d# C9 ]( {6 C
- def onKill (self,npcId,st):
! O& ?- @( ?0 q - if npcId == KELTIR_NPC_ID:
9 `: B# G" X' r0 V: F7 e- } } - n = getCount(st)0 c# K5 f# r- q: ]. w: Q
- if n == 0:. O9 C- G2 F9 w& h% R
- if st.get('chat0') == None :
' s5 \( m5 M1 O+ y" l0 k u - st.set("chat0", "true")% L* C/ r( k7 X: ~/ y; k0 d
- return "Chat0.htm"7 X- l- W" o5 f
- elif n == 1:
4 X0 V/ r4 [7 A - if st.get('chat1') == None :, _; `/ P( y @
- st.set("chat1", "true")
5 Q3 l* U; v# c( e: C. W3 R- C - return "Chat1.htm"
; X* F2 v6 }5 S( {6 H - elif n >= 4:9 g% f- T" {* J' D
- return "Chat4.htm"
$ ~2 B; a/ O. |: l - return "Collect "+str(n)+" of 4 fangs"/ r E5 V) _8 g" t' C
- return H2 t ?9 E$ q# z
4 [8 P0 N' @# q/ x- QUEST = Quest(201, "Tutorial", "Tutorial quest")! z9 W5 m: m1 L4 C* @# G6 D
- CREATED = State('Start', QUEST)
, W# e6 s" o* d9 t/ S9 Q - STARTED = State('Started', QUEST)8 Y1 G+ S0 P1 _7 o# l! l
- COMPLETED = State('Completed', QUEST)4 }2 W7 s d9 @7 p5 F- q
- # b" |8 q6 a8 w
- QUEST.setInitialState(CREATED), N% p' i5 O1 b( {: `) ]
- QUEST.addStartNpc(7056)+ j$ Y" O% b5 i0 y1 i* \
- QUEST.addStartNpc(7012)
2 ?* J0 j- Z( } - QUEST.addStartNpc(7009)
# z$ }. ? N; ^8 d+ h3 U$ v - QUEST.addStartNpc(7011)3 r4 p, Y" y/ ~9 G4 T
- 2 M- f4 [6 l# `4 H
- STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
0 y5 Z' h& t- j8 d- ?' ` - STARTED.addKillId(KELTIR_NPC_ID)! ~6 m. p8 _- W
- STARTED.addTalkId(7056)
- Y& M; C+ w' s# l - STARTED.addTalkI d(7012)
! N$ W+ C2 k9 x, c2 u2 Z) h9 ^# } - STARTED.addTalkId(7009)
5 j- i) a+ V1 J - STARTED.addTalkId(7011)
Скопировать код 7 M5 W" d. i6 C5 S! _4 i
% n+ Q8 ^6 A! f& \4 `+ u" m |