Зарегистрируйтесь сейчас чтобы найти еще больше друзей, и получить полноценный доступ ко всем функциям сайта!
Для просмотра Вам необходимо авторизоваться Если Вы еще не зарегистрированы, перейдите по ссылке:Зарегистрироваться
x
Хроники Interlude
% A- R- s6 R" j4 p8 o! q; QСборка L2j( P8 n3 m. L) X4 S2 O
Обратите внимание: в файле htm стартового NCP обязательно должна быть ссылка на квест:( d2 |* O5 s+ B( |8 [( N6 e
- STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код Для этого квеста больше ничего не надо. Все необходимое для корректной работы квеста уже добавили. Вот полный текст квеста:
) `" ?, V% j1 X& B4 f( {2 h' w7 u$ y; b
- if getCount(st) >= 4 :; f' f$ Q3 N9 l
- completed(st) e* f3 ~+ I X- ?! a! F( N
- return
1 c9 q7 I% A& z - E; r/ r5 T4 T8 @; Z. t/ _
- class Quest (JQuest):; [6 S' J3 }2 }& O
- def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)
! Z% ?5 D1 x8 t - def onEvent (self,event,st):& F& u, c' j% g/ q3 c) [
- id = st.getState()
2 X# @; a% F. m1 M9 H k - if id == CREATED : st.setState(STARTED)
# r9 N5 e- y+ F0 j& ~# J- g - elif id == COMPLETED: pass
2 N! o3 B: C) p, I, B4 x - elif id == STARTED : check(st)
/ E! B- O2 Y9 `7 ]0 Q - return
/ ~: n3 G8 G# u
3 O4 G- v& C0 O$ n8 O$ L3 g& I- QUEST = Quest(201,"Tutorial", "Tutorial quest"): S1 e7 d( V7 G3 `. H1 }; p
- CREATED = State('Start', QUEST)" C7 u$ E2 X" h
- STARTED = State('Started', QUEST)
* I- I6 A( E o - COMPLETED = State('Completed', QUEST)7 R+ d) \* A7 n6 M4 F0 P
( F' y6 l, @3 K' F) h# z- QUEST.setInitialState(CREATED)
8 `: i- J n% F( P& t - QUEST.addStartNpc(7056)
8 M9 Y7 R; a9 a+ ]' R9 o/ @ - STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код Теперь рассмотрим, как это работает.
6 _, L, e- i" X2 K eИгрок подходит к начальному NCP (в данном случае 7056), нажимает на «Quest». Квест будет создан и состояние квеста перейдет к CREATED и игроку будет показана страничка Start.htm с описанием квеста. Тогда метод onEvent, поле открытия странички Start.htm переведет состояние квеста в STARTED и игроку будет показана страничка Started.htm, где будет опсание того, как найти keltirs и .т.д.
. t" i( r- Y W! ^" t2 e! [5 {
+ D- X/ [) y% ~0 G' N2 J1 Z5 k7 [, o, N2 Z v% b
При состоянии STARTED будет зарегистрирован дроп «fangs» при убийстве keltirs. Игрок может вернуться к стартовому NCP и спросить о квесте – метод onEvent будет вызван снова. Если у игрока не хватает необходимого количества предметов, то метод check() не переведет квест в следующее состояние и Started.htm будет показана снова. Но если игрок собрал необходимее количество предметов (в данном случае 4 клыка), то метод check() вызовет метод completed() который переведет квест в новое состояние COMPLETED, заберет все клыки, даст карту мира, т.к. это награда за квест, покажет Completed.htm и завершит квест.- h- N' o* s# Y" |
+ {* l1 [5 F6 Y: s' C# \: A, M b7 {' p$ q
Теперь давайте сделаем наш квест более похожим на то, что он должен из себя представлять.5 x) k9 P9 a' y( l. Y" {, S$ |
Прежде всего у нас есть 3 метода для объявления их в Яве – onTalk, onKill и onEvent. Если методы onTalk и onKill не объявлены, то за них все будет делать метод onEvent, т.е. определять квестовых монстров и вызывать диалоги NCP. Есть примечание, методы onTalk и onKill будут вызывать только диалоги с NCP в зависимости от текущего состояния квеста. Метод onKill будет вызываться только тогда, когда мы убиваем квестового монстра.+ w) D9 v4 D$ G/ r/ U
( I( ]) q/ a3 D6 e4 |$ o2 Y
: x% O# t, w% w9 l% N1 b
Давайте рассмотрим как вызывается метод onKill при убийстве keltir в состоянии квеста STARTED:
) p0 ^' T T' _/ d- STARTED.addKillId(KELTIR_NPC_ID)
Скопировать код и метод onKill в классе Quest:
+ I; q- q+ Q3 |& q# Y# B
7 [* ~" m4 l* m; _" Z9 w7 |( K- class Quest (JQuest):
/ i8 S* g4 T) G+ S# r/ i9 i - ...6 k; x* d$ y1 c( r
- def onKill (self,npcId,st):
) v0 O. V3 d1 Q( a, { - if npcId == KELTIR_NPC_ID:" m# n ?" e' E) z: {: v
- n = getCount(st)
5 Y$ k( O2 r# P" s6 R- o5 A - if n == 0:" _( o& ` G# C N/ q# y$ T% G7 j
- return "Chat0.htm"
9 z5 {, x2 _, Y( h - elif n == 1:2 w8 j& R& z8 ~8 e: _
- return "Chat1.htm"' S6 r/ d) D% E8 q1 J
- elif n >= 4:% K: J) ?. m1 p, N. p/ O$ V/ s
- return "Chat4.htm"; Z; U" j, n5 z
- return "Collected "+str(n)+" of 4 fangs"
8 v- y; i+ J3 a. y! [3 _ - return
Скопировать код Метод onKill (а так же метод onTalk) имеет следующие параметры:
9 [0 M* D! _5 `+ i" J3 v
7 h, O- B( P: b7 ?! L' T& ^7 ^5 s" L
• self – квест. I* i' ~3 i# d: k
• npcId – ID NCP, которого мы должны убивать (если это метод onTalk, то ID того NCP, с которым мы должны поговорить).
+ B: l4 ~! U3 `5 I• st – текущее состояние игрока.- E3 x) g! Q$ J+ I3 p; _- V9 m
: n' F+ z% |8 U' z+ ], L ^5 o) D/ I- t9 Y9 n( P- j7 b9 n
В этом методе мы проверяем и отмечаем, является ли убитый NCP keltir’ом. В основном эта проверка не нужна, т.к. у нас только KELTIR_NPC_ID.
) a* i% }* B; b; k3 i/ J- B# l0 x* x7 |+ [- B2 _
* o1 V" u! u" J# }8 {. q( i' rЗатем проверяем количество предметов (в данном случае количество клыков), и если их вообще нет, то возвращаем строку "Chat0.htm", если только один предмет, то возвращаем строку "Chat1.htm", если же предметов 4 или больше, то "Chat4.htm". Если строка возвращена из методов onEvent, onKill или onTalk, то сервер покажет соответствующие htm. В Chat0.htm может иметь следующий текст: «Вы не имеете ни одного клыка, возвращайтесь позже, когда соберете 4 штуки и бла, бла, бла…», в Chat1.htm может быть следующий текст: «У Вас всего 1 клык, по этому соберите еще…». В Chat4.htm – «Вы собрали необходимое количество предметов, возвращайтесь к вашему тренеру, что бы завершить квест…»$ H4 F/ N6 Q0 X# S# ~$ y
& l. C2 P: X4 T- d7 u) a S0 f, u2 `! x- e8 F0 R
Примечание: если в строка return начинается с "<html>", то будет показана страничка html с текстом, который стоит далее. Так вместо:
5 N8 S: E$ e/ v3 r; Freturn "Chat4.htm"
& g. |; H8 o1 G3 d( n; [0 C2 e
* L# q1 Y4 o# B% b. J3 X
: `1 l P% m7 uможно поставить:
4 [8 D9 o1 e! D. E3 L: f- return "<html><body>Return to your trainer to complete the quest</body></html>"
Скопировать код Так же если строка заканчивается без .htm или в начале нет <html>, то текст будет выведен, как системное сообщение в окне чата. В нашем случае мы сделаем так, что бы при каждом убийстве keltik выводилось системное сообщение: «Собрано N из 4-х клыков».( G* l* H/ E. {' v) A2 L
4 q: m/ H; M6 r$ d+ Q
) ^- P1 f% G8 D; h9 e( M; }* m
Наш код для onKill имеет один недостаток. Он будет постоянно показывать Chat0.htm, Chat1.htm и Chat4.htm, нам же необходимо, что бы Chat0.htm и Chat1.htm показывались только один раз. Как нам это сделать? С помощью переменных.9 o8 a u, S% a! W3 }4 q3 l
) a, v1 p& ~+ X6 \* }" }8 |3 L" |& R$ l6 ~( X/ Z& L- W
В каждом квесте строки могут храниться с помощью переменных. Эти переменные сохраняются в Вашей БД. В каждом методе мы можем назначить, прочитать и удалить переменные. Давайте изменим метод onKill, так что бы каждый диалог вызывался только один раз.$ G5 j: r4 q( S O, g7 f
- def onKill (self,npcId,st):7 C6 y( |. l: O: v! ?0 {4 y$ x
- if npcId == KELTIR_NPC_ID:
0 ?$ G+ D5 I0 h1 t/ a - n = getCount(st)7 L$ A5 G) f) R% M$ W# v
- if n == 0:
1 Z8 ]# F! c% M - if st.get('chat0') == None : e' Q C6 a6 Y% i. `! Z% W" D8 |
- st.set("chat0", "true")
! ?: \2 R: y# ~& L3 i9 W% P/ L - return "Chat0.htm"& n. g; V9 G- d! x, g! v
- elif n == 1:
' j- K% L; p$ i - if st.get('chat1') == None :
: f( o4 ~: M' i3 P( j - st.set("chat1", "true")
$ k; o' ^5 ?! v- X - return "Chat1.htm"
% k- s$ C* b& M( N( a4 ]4 g( h - elif n >= 4:
8 m$ l/ C6 Z) G+ q6 L$ @ - return "Chat4.htm"
. v ?& k! b) w3 y: i- V7 e - return "Collected "+str(n)+" of 4 fangs"
( |/ D6 e5 Y7 @' Y, U3 m+ [2 X, f - return
Скопировать код Если у игрока нет клыков (n=0), то мы получаем занчение переменной 'chat0'. Когда метод onKill вызван в первый раз, то пока ни каких переменных не имеется и python возвращает значение None. В этом случае объявляется переменная и показывается диалог Chat0.htm. Когда мы убиваем keltir, но не получаем с него клык, функция st.get('chat0') возвращает строку true, а не None. И во второй раз окно с Chat0.htm не появится, но в окне чата появится строчка «Collected 0 of 4 fangs». По тому же принципу сделано и с Chat1.htm.; r' k$ Z- I$ d5 Q
+ F4 i4 G: z- E
8 E4 X" w d$ rВот конечный рабочий вариант квеста:% Q& R/ |' y* I7 o1 H
- import sys
4 i& P, [0 o5 d, p5 Q - from net.sf.l2j.gameserver.model.quest import State6 V: s# [+ C2 M5 {6 [
- from net.sf.l2j.gameserver.model.quest import QuestState
# j" Z0 i: W0 o7 k% A% ^! q - from net.sf.l2j.gameserver.model.quest.jython import QuestJython as JQuest
# K g. J& Q) ]5 Y* u6 z0 o3 } - * o( Z9 R) W8 i5 g) s4 C
- KELTIR_NPC_ID = 120822 J: j8 b z" a# b7 @- Y
- FANGS_ITEM_ID = 18595 H. s- r4 M- _/ }+ C h
- DROP_RATE = 500000/ I) A0 }" h- p1 b' U! x
8 m7 U( N' F9 V8 F! G5 T- WORLD_MAP_ITEM_ID = 1665 x9 h- b2 K T
# e" G! |! P6 Y- def getCount(st) :
6 z$ v+ {7 f9 ^6 q z' s - return st.getQuestItemsCount(FANGS_ITEM_ID)6 y, P9 ~" t- Z
- / ]6 e+ ~% _, w! l1 m4 \3 T
- def completed(st) :
8 R( l1 o0 F" ]5 c$ |& o - st.setState(COMPLETED)
% i2 r6 I2 c) H! q' E/ Y - st.clearQuestDrops()# H. P1 @0 H) U
- st.takeItems(FANGS_ITEM_ID,-1)0 y! [4 J) a9 k* @1 j( B
- st.giveItems(WORLD_MAP_ITEM_ID,1) f3 @! P% N, X! y5 m
- st.exitQuest(False)# z- @! B" J1 F1 q" W: d. q5 I8 x
- return/ \3 T( L9 K; l1 L& k- N( C
- & j$ W& S0 |- u( g d
- def check(st) :3 i' B |4 x/ Z% ^1 T, X
- if getCount(st) >= 4 :
* ]- g) [1 |. g0 u0 Q. s6 r - completed(st)
; k$ F' N1 L+ U& G; p& K' K' M2 R - return
$ p- T0 p G) W
1 a2 r$ T6 l$ S/ i# d- class Quest (JQuest):6 S$ O: H: a" a9 J9 U6 x
8 x' L* v$ ~1 `! K j0 ]" j- def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)# ^) L( X( z/ I& q& T1 Q
2 ]0 Z: `- i f6 d% _3 K; [. F) x- def onEvent (self,event,st):
6 ?' |# T3 n! e, P" n" S" u) ` - id = st.getState()& A+ K6 q w0 ]8 P/ x
- if id == CREATED : st.setState(STARTED)4 c6 F* d; c6 N! F4 ~) S
- elif id == COMPLETED: pass) C7 C8 @' ?% n/ i8 u
- elif id == STARTED : check(st)
" Q+ G2 v" r- m- ~% _ - return% k# b& s& c1 J6 [8 T
; k1 a: Q: S2 ]9 \; Q& D% w- def onKill (self,npcId,st):
# x2 v( _( {% [% r. K% j7 {( W6 q+ r# S - if npcId == KELTIR_NPC_ID:& y6 [' r" A) i) I9 I' b2 ~" M$ n
- n = getCount(st)
+ j& N0 U* ]: {" j0 X: H) p; g3 F - if n == 0:7 q: n$ R& @3 z4 a5 U
- if st.get('chat0') == None :
0 X/ O; W( @) |- y0 R% T' f5 q3 }* K - st.set("chat0", "true")
: r2 w3 f! f& E - return "Chat0.htm"3 [, C5 w9 Z1 ^/ r B: t
- elif n == 1:/ R0 c h x8 Q3 O @/ h
- if st.get('chat1') == None :
( ~( c2 Z/ M) C! ]% i - st.set("chat1", "true"), d' r7 t/ T" a2 \. i# n. M1 |
- return "Chat1.htm"
! M3 g# V# C8 z - elif n >= 4:
& y7 n1 H, ?" w* H5 I - return "Chat4.htm"
% F- a6 d. C1 N# G, n - return "Collect "+str(n)+" of 4 fangs"3 @+ [& u9 U- V4 P
- return. W& p) S0 r6 Y4 f
q, p1 U; ]3 u$ D f. Y- QUEST = Quest(201, "Tutorial", "Tutorial quest")
) z+ S% ^, Z8 D9 P' B - CREATED = State('Start', QUEST)
" y1 E5 p1 T& \" @6 |8 [ - STARTED = State('Started', QUEST)
* n* k+ f/ Q( L# A$ ^ - COMPLETED = State('Completed', QUEST)
3 ^! S- t# M5 K3 R4 p- u
; g7 {. J, |0 j" ^/ K9 s- QUEST.setInitialState(CREATED)- x8 x6 v/ c. n: i* d% z
- QUEST.addStartNpc(7056)
5 p& W$ [ I( P1 r% d( t. X. L - QUEST.addStartNpc(7012)
Q; x8 F: A5 V5 e) f( [ - QUEST.addStartNpc(7009)8 \0 f$ c: Q3 o% }
- QUEST.addStartNpc(7011), O2 Y2 C s0 Z/ x
' G" a; R# Y O7 a# P- V4 x- STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)6 z6 f: U+ c" ^
- STARTED.addKillId(KELTIR_NPC_ID)7 o) Z, y- |# ?/ c+ Q
- STARTED.addTalkId(7056)
! M4 [" w) A3 L# z5 } l - STARTED.addTalkI d(7012)9 d$ }, f) Z M8 `! r0 K# p" `' p1 i
- STARTED.addTalkId(7009)
6 V( x6 V* q5 T+ _" A7 I - STARTED.addTalkId(7011)
Скопировать код : l) Z, L2 a% v+ [& v$ V9 g
3 l: j3 [ m8 G1 Q$ H
|