Зарегистрируйтесь сейчас чтобы найти еще больше друзей, и получить полноценный доступ ко всем функциям сайта!
Для просмотра Вам необходимо авторизоваться Если Вы еще не зарегистрированы, перейдите по ссылке:Зарегистрироваться
x
Хроники Interlude9 K% ?7 H" s, \ R" ~4 g" Q4 N) [
Сборка L2j, u& V$ h5 A0 K9 X* s \6 l) c: }
Обратите внимание: в файле htm стартового NCP обязательно должна быть ссылка на квест:
# d& E. M$ J$ s; Z$ V2 d) |8 p3 o- STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код Для этого квеста больше ничего не надо. Все необходимое для корректной работы квеста уже добавили. Вот полный текст квеста:
; a' a# ?% \$ |* o0 m$ e) n6 R. y6 `) {1 ~6 u4 r
- if getCount(st) >= 4 :( V% H( D) Y% N* H
- completed(st). R2 Y8 y) ?$ f2 a
- return0 \: Z$ d2 A5 q: u
- - Y- c3 p0 W4 L; X5 i8 b
- class Quest (JQuest):* a$ F1 A1 x* G
- def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)0 D' d$ t! L$ J% C' D
- def onEvent (self,event,st):( w q# V2 D2 Y4 K6 {2 q
- id = st.getState()' Z7 M% A6 Q. O% N
- if id == CREATED : st.setState(STARTED)4 V) o8 o3 }1 z! r/ D
- elif id == COMPLETED: pass
( C$ a9 x' N3 h - elif id == STARTED : check(st)4 k- u4 t4 z: ?* o- G3 ?0 y- l
- return* {: }) W% p) ~* A) }: a
j; a( j) P, \' Y6 b: g/ w1 t- QUEST = Quest(201,"Tutorial", "Tutorial quest")% ]& e, y0 W6 H: y$ @
- CREATED = State('Start', QUEST)+ ]9 [; m. q V$ W
- STARTED = State('Started', QUEST)
7 G. X% w' T! d. `( W3 y - COMPLETED = State('Completed', QUEST)
! B8 O1 s2 W4 q# o! p8 ~7 |9 R - , H5 A8 i, o: G6 o& Q5 g
- QUEST.setInitialState(CREATED)
* R0 r+ a& O3 j8 h) b& w - QUEST.addStartNpc(7056)
3 u5 k* Z1 d; R1 I1 O/ j, T2 L - STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код Теперь рассмотрим, как это работает.$ a! r9 N" ^: m0 t* D$ L8 W
Игрок подходит к начальному NCP (в данном случае 7056), нажимает на «Quest». Квест будет создан и состояние квеста перейдет к CREATED и игроку будет показана страничка Start.htm с описанием квеста. Тогда метод onEvent, поле открытия странички Start.htm переведет состояние квеста в STARTED и игроку будет показана страничка Started.htm, где будет опсание того, как найти keltirs и .т.д.# E, j# Z5 F4 `+ v% W' v
- S6 Z& G6 j* S. Y( G+ u5 |
% P9 I! `+ ^8 WПри состоянии STARTED будет зарегистрирован дроп «fangs» при убийстве keltirs. Игрок может вернуться к стартовому NCP и спросить о квесте – метод onEvent будет вызван снова. Если у игрока не хватает необходимого количества предметов, то метод check() не переведет квест в следующее состояние и Started.htm будет показана снова. Но если игрок собрал необходимее количество предметов (в данном случае 4 клыка), то метод check() вызовет метод completed() который переведет квест в новое состояние COMPLETED, заберет все клыки, даст карту мира, т.к. это награда за квест, покажет Completed.htm и завершит квест.* g$ j; u" h0 }! n
4 B r$ ^2 z; |# e1 ], {% _# Z: ]" Q# u$ b3 Q
Теперь давайте сделаем наш квест более похожим на то, что он должен из себя представлять.
$ y$ ?+ Y: ~5 @) ]Прежде всего у нас есть 3 метода для объявления их в Яве – onTalk, onKill и onEvent. Если методы onTalk и onKill не объявлены, то за них все будет делать метод onEvent, т.е. определять квестовых монстров и вызывать диалоги NCP. Есть примечание, методы onTalk и onKill будут вызывать только диалоги с NCP в зависимости от текущего состояния квеста. Метод onKill будет вызываться только тогда, когда мы убиваем квестового монстра.5 `" F! m8 W0 W
' a7 U' f5 h. \) i! `' j( k0 s' z
; z. V' g, r3 z4 ]; _* ?7 gДавайте рассмотрим как вызывается метод onKill при убийстве keltir в состоянии квеста STARTED:
" H5 F7 F" s R) F" u8 E3 ^- STARTED.addKillId(KELTIR_NPC_ID)
Скопировать код и метод onKill в классе Quest:/ g# F: u: L3 }
1 T: C+ I4 {1 N3 C& L( w- class Quest (JQuest):7 L# S1 l7 F W& F$ l1 Y
- ...1 \9 P. G/ z5 D2 [5 U7 c
- def onKill (self,npcId,st):* N3 @* J$ b, O5 F$ H! z8 B
- if npcId == KELTIR_NPC_ID:! ?/ x3 r* t1 a5 y; ~* x) \7 F
- n = getCount(st)/ O0 E6 s- t; U( ?6 {& q, D
- if n == 0:
" u( b. x W# c: J$ j5 {7 d7 K! m - return "Chat0.htm"
( |# q% E7 z9 j - elif n == 1:4 @( m5 X7 e6 G. m! v) Z
- return "Chat1.htm"
: V: a: B, n$ n# n4 l4 m( L$ o - elif n >= 4:8 U2 y( X1 n0 W4 p( ]
- return "Chat4.htm"
4 W7 z; V- j( b - return "Collected "+str(n)+" of 4 fangs") n K$ m) ^& o/ h, x/ A
- return
Скопировать код Метод onKill (а так же метод onTalk) имеет следующие параметры:2 g# r8 V2 q3 B. \7 e
9 `' [6 p! c) K' E8 M
5 k+ U3 u2 i4 Z, }% M v/ y8 i• self – квест5 s) S# M1 U t3 Q
• npcId – ID NCP, которого мы должны убивать (если это метод onTalk, то ID того NCP, с которым мы должны поговорить).! s( r4 X- \) @: f, [* E) v
• st – текущее состояние игрока.
]/ S. \* A/ _8 d# {1 I2 [
5 V( @% G: n% }/ Z' K7 ~4 _! ^8 Q$ ~) Y; `! S9 M' g
В этом методе мы проверяем и отмечаем, является ли убитый NCP keltir’ом. В основном эта проверка не нужна, т.к. у нас только KELTIR_NPC_ID.
# L" y# V' Q3 x9 I$ Q" f! E+ S+ C# j5 {" c9 V6 R
" t" B+ G& h u6 y' K1 KЗатем проверяем количество предметов (в данном случае количество клыков), и если их вообще нет, то возвращаем строку "Chat0.htm", если только один предмет, то возвращаем строку "Chat1.htm", если же предметов 4 или больше, то "Chat4.htm". Если строка возвращена из методов onEvent, onKill или onTalk, то сервер покажет соответствующие htm. В Chat0.htm может иметь следующий текст: «Вы не имеете ни одного клыка, возвращайтесь позже, когда соберете 4 штуки и бла, бла, бла…», в Chat1.htm может быть следующий текст: «У Вас всего 1 клык, по этому соберите еще…». В Chat4.htm – «Вы собрали необходимое количество предметов, возвращайтесь к вашему тренеру, что бы завершить квест…»7 m0 J0 Q! Q% H; L/ @& O2 Q7 U" J1 t
# e9 V( {. G8 r' N8 I+ X: {1 {3 X+ C7 n! T3 d# O9 G! U
Примечание: если в строка return начинается с "<html>", то будет показана страничка html с текстом, который стоит далее. Так вместо:, {+ F+ P, z9 J) U( W% \$ r+ V- z. Y
return "Chat4.htm"
9 w4 P6 e, c. h. A+ K! ~/ [8 A
: w4 s- X. ?, Q) i2 s# j0 L/ s+ n* m
- e, t8 Q @7 H7 _4 l' iможно поставить:
, d/ v1 Q v a e" Q# S4 J- return "<html><body>Return to your trainer to complete the quest</body></html>"
Скопировать код Так же если строка заканчивается без .htm или в начале нет <html>, то текст будет выведен, как системное сообщение в окне чата. В нашем случае мы сделаем так, что бы при каждом убийстве keltik выводилось системное сообщение: «Собрано N из 4-х клыков».
/ L) d. F) @. A3 g
" X& p: H( l Q( n0 D
1 X- v+ ]7 f) S) M5 X) OНаш код для onKill имеет один недостаток. Он будет постоянно показывать Chat0.htm, Chat1.htm и Chat4.htm, нам же необходимо, что бы Chat0.htm и Chat1.htm показывались только один раз. Как нам это сделать? С помощью переменных.
6 o1 ]1 v( ]5 L- a+ a. ~% z# z- w( o8 t+ y
# b% Y' W7 B" h5 _* {9 S+ y
В каждом квесте строки могут храниться с помощью переменных. Эти переменные сохраняются в Вашей БД. В каждом методе мы можем назначить, прочитать и удалить переменные. Давайте изменим метод onKill, так что бы каждый диалог вызывался только один раз.: Q( F0 E4 t. _9 I# w1 \
- def onKill (self,npcId,st):
8 ?+ p- F _6 v# C2 f0 {0 M - if npcId == KELTIR_NPC_ID:
- ~& Q# w; d7 t7 D: E3 e - n = getCount(st), \7 z; Z0 A) l" w7 ~! ]" @
- if n == 0:
4 q* D7 [5 a* X! k' w) r - if st.get('chat0') == None :% f# [- O* e6 r" h
- st.set("chat0", "true")& Z5 d9 L+ Y2 m! |! v4 d) g
- return "Chat0.htm"
3 i' r9 ^0 d' H8 \) ^ G& i( o - elif n == 1:
" j- x, M9 j* u/ Z - if st.get('chat1') == None :
& V$ \# e7 O# C1 y8 A' x - st.set("chat1", "true")
. i9 q `1 C' ~* ~) n) g1 d - return "Chat1.htm"6 u% X* Q: Y' \, ^
- elif n >= 4:
; O9 ~& [. B% u1 G3 a2 n' ~ - return "Chat4.htm"
* a' u5 `' N7 \2 k8 h5 A1 ^ - return "Collected "+str(n)+" of 4 fangs"
- {5 E& {7 c* k; n, ]) {8 N+ B - return
Скопировать код Если у игрока нет клыков (n=0), то мы получаем занчение переменной 'chat0'. Когда метод onKill вызван в первый раз, то пока ни каких переменных не имеется и python возвращает значение None. В этом случае объявляется переменная и показывается диалог Chat0.htm. Когда мы убиваем keltir, но не получаем с него клык, функция st.get('chat0') возвращает строку true, а не None. И во второй раз окно с Chat0.htm не появится, но в окне чата появится строчка «Collected 0 of 4 fangs». По тому же принципу сделано и с Chat1.htm./ K$ @( ~. {) ^5 K
. p+ z( W v8 N+ w
& o, i) g' ]$ _" {4 pВот конечный рабочий вариант квеста:
2 n0 _& b7 V( I9 ]! a8 {. |- import sys4 T% v8 }( j# O
- from net.sf.l2j.gameserver.model.quest import State
* n% e% G) c ~. E5 Z* \ - from net.sf.l2j.gameserver.model.quest import QuestState
' D. f/ g; y; K: W7 X1 c - from net.sf.l2j.gameserver.model.quest.jython import QuestJython as JQuest
8 |/ S" W9 w! m" m2 M2 q - ' k- d& K4 V# d. ]
- KELTIR_NPC_ID = 12082% g% G# T* t& p5 ?! B
- FANGS_ITEM_ID = 1859
7 l: E! j8 w5 M6 x - DROP_RATE = 5000006 B! L! _, W1 o" P: {2 M
- ) h$ r) Z! o3 d4 R# z N; q
- WORLD_MAP_ITEM_ID = 16652 I6 f" }" ~( ^; f/ ~' }% }% D
- % [# k# ~, A m5 ]) _+ [$ H
- def getCount(st) :
, Q2 P& ?. s4 v& O' \1 u) Y1 a2 d( J - return st.getQuestItemsCount(FANGS_ITEM_ID)
$ Y E8 _. Z0 {4 |' A0 q/ d6 Z& R
; e. T. B5 J. o8 c- L' @- def completed(st) :
# S( I' @. X) |; X! |/ u; j. `3 d - st.setState(COMPLETED)
4 K7 d: h; T- M4 L% V% O% i, \4 y3 Q - st.clearQuestDrops()
) g4 U! m& v9 p' b7 O! {: _ L9 _ - st.takeItems(FANGS_ITEM_ID,-1)+ I+ E% ~' {% t! p' i$ q4 O
- st.giveItems(WORLD_MAP_ITEM_ID,1)
7 K% X; W5 s& u; K9 U W - st.exitQuest(False)
% P* @* V$ {7 b0 Y - return
9 S9 R' j2 M! M; U! A/ d( O% X - ; w8 d, P3 ]. V7 W# O0 D
- def check(st) :
, o: O0 y/ l: p: R- W) f7 j( S; r - if getCount(st) >= 4 :
, T4 n$ v7 v0 m. ~' ` - completed(st)
X8 r2 H( C# @! \( {7 v - return' \1 A9 o8 _# |; ^
- * S- u" O: E2 G3 F+ |/ V
- class Quest (JQuest):
2 M. p4 U: W9 \ ] - - W) @! |5 }& @; C# X0 o
- def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)
: s/ ^! {7 w: p# I1 k - 7 ?& j) N( |$ A r# a' a! R) {
- def onEvent (self,event,st):: k! n5 P; R! J8 f$ [8 d8 o
- id = st.getState()
0 L+ z- }. P0 C8 t! B# k8 [& U - if id == CREATED : st.setState(STARTED)
' p" t+ v, K/ a7 I+ N: k1 R5 L8 G - elif id == COMPLETED: pass1 _# A1 \( D S. ^" Y2 v( H
- elif id == STARTED : check(st)$ o: z& O* v! h2 x/ c' ^0 h6 o
- return u9 K" D9 E" N8 O- i' K# A0 o, l A
8 q, k9 X5 W; D- _- def onKill (self,npcId,st): G$ c+ j( L6 i N2 U( }9 E$ i* X6 o, v
- if npcId == KELTIR_NPC_ID:2 \7 l- d7 A0 x+ X* M8 B7 Y
- n = getCount(st)
) y6 @) i8 k9 {& F' I - if n == 0:
9 R7 g- T; l1 K I) O o - if st.get('chat0') == None :
$ t" ~; i1 L& O2 s - st.set("chat0", "true") t, N, \2 d* O. `& Q2 @
- return "Chat0.htm"9 k( L1 G% A5 W7 y1 z
- elif n == 1:
) I9 z9 o; k* Q* C; v$ s1 n, G - if st.get('chat1') == None :
" |, }8 i5 O7 V# |1 f4 y- Y - st.set("chat1", "true")
# \& S' c+ l+ U* {3 T o& j - return "Chat1.htm"
3 t. |( O) a" @) j - elif n >= 4:
; T8 K, r" S2 q0 d7 R - return "Chat4.htm": j' y9 [& l( E) l* B6 k
- return "Collect "+str(n)+" of 4 fangs"
% g. X! Q: f$ j6 Y# ? - return$ K# A' v$ E* R( U
- , N4 i% x* w- U8 p
- QUEST = Quest(201, "Tutorial", "Tutorial quest")
0 a9 c$ L, H, \0 @ - CREATED = State('Start', QUEST)
' \& ]" H$ P8 f/ }4 u1 F - STARTED = State('Started', QUEST)- e$ d5 m* D) s( N b6 _3 O
- COMPLETED = State('Completed', QUEST)( s3 V, Q( x! b, S( O! U
! D( L, i$ j5 Q5 B6 e W! Q+ U- QUEST.setInitialState(CREATED)
& Y* Q- \4 |& s - QUEST.addStartNpc(7056)% l$ v. V6 D( w, K
- QUEST.addStartNpc(7012). U4 T2 L# l3 U& m6 I
- QUEST.addStartNpc(7009)5 T, X* {& v: O
- QUEST.addStartNpc(7011)
% o0 o0 \+ ~6 w/ \+ w2 E# F8 q9 F
* `/ ]: _/ t: Y9 @- STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)' X, Z9 o6 f5 D$ w: i& T
- STARTED.addKillId(KELTIR_NPC_ID)
* k8 J; Q4 r- w9 y, a G- A - STARTED.addTalkId(7056)
1 M9 R' _; c- p9 A. j% k. ~9 Q - STARTED.addTalkI d(7012)# r" f+ ]8 p# j) d5 h8 R. Z5 T
- STARTED.addTalkId(7009)
$ g& E: x' {, Y& b+ v) u - STARTED.addTalkId(7011)
Скопировать код
3 ]3 h$ N$ d+ S F6 f
# o7 x2 E- o2 i8 h5 t+ H$ U |