Зарегистрируйтесь сейчас чтобы найти еще больше друзей, и получить полноценный доступ ко всем функциям сайта!
Для просмотра Вам необходимо авторизоваться Если Вы еще не зарегистрированы, перейдите по ссылке:Зарегистрироваться
x
Хроники Interlude
, o( x# _( a( i3 ?$ \Сборка L2j4 _8 W$ B! Z; p6 P
Обратите внимание: в файле htm стартового NCP обязательно должна быть ссылка на квест:- ` y) _, |9 a, F( `8 E3 @: A
- STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код Для этого квеста больше ничего не надо. Все необходимое для корректной работы квеста уже добавили. Вот полный текст квеста:
) Q4 L' T$ `2 m" h C* _* |* G3 f5 a* i: x4 q. t
- if getCount(st) >= 4 :7 c& D5 Y* t+ r' b
- completed(st)
. `' m# A( b9 U" F4 |% W - return
2 g- Y9 x2 Q1 y0 ~; W
! s$ w% |% ` H5 A5 f/ w1 q" V- class Quest (JQuest):
2 F2 f0 f; \; x$ K0 ` - def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)
" ]2 c( G7 i |6 W S - def onEvent (self,event,st):( F; o+ [: k% {4 A/ R. b, _- K; t: n& O
- id = st.getState()& S% d; A' \) L# J+ {6 L
- if id == CREATED : st.setState(STARTED)5 P: t7 p9 Q W/ q, o
- elif id == COMPLETED: pass
* Z0 b/ f6 S3 J# X/ \ - elif id == STARTED : check(st)
: ^. c. k; ?( q) [, c3 k ~# b1 b8 ` - return
; n! i ^: i( l1 q: F. J - s) u T9 Q R* }2 o4 w
- QUEST = Quest(201,"Tutorial", "Tutorial quest")
) k& B6 [" J* o9 r- Q9 b - CREATED = State('Start', QUEST)
$ c8 q5 O! R6 n - STARTED = State('Started', QUEST)5 K2 r$ [2 p. G4 h
- COMPLETED = State('Completed', QUEST)
* t# x- K* B- L$ d4 S$ M6 ^ - ; v! J$ B+ B' g. J- b, h& J; e
- QUEST.setInitialState(CREATED)
! w0 u6 J" _4 D& L - QUEST.addStartNpc(7056)
8 J( X: X/ c3 _8 U+ Q/ ~ - STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код Теперь рассмотрим, как это работает.
) s- x o" S7 X( W1 jИгрок подходит к начальному NCP (в данном случае 7056), нажимает на «Quest». Квест будет создан и состояние квеста перейдет к CREATED и игроку будет показана страничка Start.htm с описанием квеста. Тогда метод onEvent, поле открытия странички Start.htm переведет состояние квеста в STARTED и игроку будет показана страничка Started.htm, где будет опсание того, как найти keltirs и .т.д.% i; J' }! a/ n; y0 ~
, b, ~3 ?6 ~' o" D0 K, T
. j, I, a* S9 g5 ?9 W/ G
При состоянии STARTED будет зарегистрирован дроп «fangs» при убийстве keltirs. Игрок может вернуться к стартовому NCP и спросить о квесте – метод onEvent будет вызван снова. Если у игрока не хватает необходимого количества предметов, то метод check() не переведет квест в следующее состояние и Started.htm будет показана снова. Но если игрок собрал необходимее количество предметов (в данном случае 4 клыка), то метод check() вызовет метод completed() который переведет квест в новое состояние COMPLETED, заберет все клыки, даст карту мира, т.к. это награда за квест, покажет Completed.htm и завершит квест.
& G- y1 F- E) n- R
" R3 _4 ]2 m/ y. O" ~# v
7 L$ u$ }' B p" y9 hТеперь давайте сделаем наш квест более похожим на то, что он должен из себя представлять.
. k* q! U+ `3 M% Y: l( {9 g) w9 ^Прежде всего у нас есть 3 метода для объявления их в Яве – onTalk, onKill и onEvent. Если методы onTalk и onKill не объявлены, то за них все будет делать метод onEvent, т.е. определять квестовых монстров и вызывать диалоги NCP. Есть примечание, методы onTalk и onKill будут вызывать только диалоги с NCP в зависимости от текущего состояния квеста. Метод onKill будет вызываться только тогда, когда мы убиваем квестового монстра.
l3 a3 l4 {& D9 [5 y; _5 s) X/ O m% X! @% ~- A
9 g. w8 V1 F) t% a, c% R1 \Давайте рассмотрим как вызывается метод onKill при убийстве keltir в состоянии квеста STARTED:
6 K* T3 k$ s$ ^: l' S0 t$ {- STARTED.addKillId(KELTIR_NPC_ID)
Скопировать код и метод onKill в классе Quest:
7 W- i( w f- @8 U% y" N2 W0 X
/ A2 d! i) Z5 C( }. e4 S- A m5 _- class Quest (JQuest): y& ]3 \& Z- C1 u3 |; j, ]; L2 J
- ...: G3 \4 l4 D& c4 q, ^+ T
- def onKill (self,npcId,st):7 d8 w- I" k$ G8 ~- O' n7 v
- if npcId == KELTIR_NPC_ID:
4 y, p- S2 A. N3 c9 a9 V1 y( R) |- [ - n = getCount(st); l' Z. ^9 }$ z+ y5 N9 b0 ^
- if n == 0:
: I# R J+ j) h Y$ ` - return "Chat0.htm"( W& j3 @1 S2 K; ^/ v* |+ I
- elif n == 1:
$ w: P, O4 A9 a3 G - return "Chat1.htm"7 O0 ~$ Y& z. q' q8 T. x
- elif n >= 4:
2 b. l. i$ K2 v4 ?) V) H7 @$ |# R" ~0 Y - return "Chat4.htm"
6 W& V; Y, Y( G7 F - return "Collected "+str(n)+" of 4 fangs"
0 S3 o) r! Z# f6 C' w( G - return
Скопировать код Метод onKill (а так же метод onTalk) имеет следующие параметры:- j8 h- D8 O, g# e* A A
' e* {' G! e8 B' [/ _. L
1 j. a& F5 K. t
• self – квест
" |, Y! i) a, e• npcId – ID NCP, которого мы должны убивать (если это метод onTalk, то ID того NCP, с которым мы должны поговорить).9 I9 l; f6 @/ Z' d
• st – текущее состояние игрока.
/ A+ f" y$ P Y7 \. _6 v2 \
8 F4 f! E: N6 n/ i
9 I4 L* O0 W4 ?& U/ K1 B; w& ?В этом методе мы проверяем и отмечаем, является ли убитый NCP keltir’ом. В основном эта проверка не нужна, т.к. у нас только KELTIR_NPC_ID.7 S/ e% O1 Q" R
4 O, x: q2 F9 X
h, G: t) u) G! N9 zЗатем проверяем количество предметов (в данном случае количество клыков), и если их вообще нет, то возвращаем строку "Chat0.htm", если только один предмет, то возвращаем строку "Chat1.htm", если же предметов 4 или больше, то "Chat4.htm". Если строка возвращена из методов onEvent, onKill или onTalk, то сервер покажет соответствующие htm. В Chat0.htm может иметь следующий текст: «Вы не имеете ни одного клыка, возвращайтесь позже, когда соберете 4 штуки и бла, бла, бла…», в Chat1.htm может быть следующий текст: «У Вас всего 1 клык, по этому соберите еще…». В Chat4.htm – «Вы собрали необходимое количество предметов, возвращайтесь к вашему тренеру, что бы завершить квест…»& w" I) _% M5 x" h, f' ~
( ~ N3 `2 N2 Y! ?9 i- A$ s( `
% u. Y6 S, v/ P7 J7 ^$ R& BПримечание: если в строка return начинается с "<html>", то будет показана страничка html с текстом, который стоит далее. Так вместо:
, ^( j( I3 m0 s$ ^; `# @1 K1 n, ~: hreturn "Chat4.htm"8 e/ v6 T: h$ k1 {& `
! C6 S1 F# s* e+ N
/ v" _ @7 i' d0 o/ q- V2 mможно поставить:
* O) Z3 }1 o/ @2 e7 @8 k( r- return "<html><body>Return to your trainer to complete the quest</body></html>"
Скопировать код Так же если строка заканчивается без .htm или в начале нет <html>, то текст будет выведен, как системное сообщение в окне чата. В нашем случае мы сделаем так, что бы при каждом убийстве keltik выводилось системное сообщение: «Собрано N из 4-х клыков».
. [) M3 b* X# ? G- X& o% {: @
$ {! e' p5 ]4 O: V' EНаш код для onKill имеет один недостаток. Он будет постоянно показывать Chat0.htm, Chat1.htm и Chat4.htm, нам же необходимо, что бы Chat0.htm и Chat1.htm показывались только один раз. Как нам это сделать? С помощью переменных.' O1 f5 p7 X/ U# p. i
. s _/ U4 K) S% u/ x U1 n# M
' D1 `" D$ P% ~В каждом квесте строки могут храниться с помощью переменных. Эти переменные сохраняются в Вашей БД. В каждом методе мы можем назначить, прочитать и удалить переменные. Давайте изменим метод onKill, так что бы каждый диалог вызывался только один раз.9 L; I% [6 S2 H [8 v' H
- def onKill (self,npcId,st):! v9 ~. E" i9 W, k; \
- if npcId == KELTIR_NPC_ID:
0 L% ~6 I) g, K# _- l3 q0 ? - n = getCount(st)
& g% w; W- [2 k0 x) l; q% m7 } - if n == 0:
1 Q& m( a4 y5 f. n3 q" e - if st.get('chat0') == None :
3 A8 y" b( w7 g# a/ ` - st.set("chat0", "true")
: k+ C# I* V' u% Z! F, y2 q - return "Chat0.htm"
' ?- e9 d* h' b& g8 f, O* b( A. | - elif n == 1:
% F. E8 u- |" a3 {0 g - if st.get('chat1') == None :
2 A% P2 h2 p# h: `) o - st.set("chat1", "true")0 K, R# O1 y" O+ L
- return "Chat1.htm"9 [$ b# o, L, o
- elif n >= 4:4 B2 A9 r. P4 l' f1 W* C
- return "Chat4.htm"1 B0 R, I3 ]3 x) ?3 l
- return "Collected "+str(n)+" of 4 fangs"
: A8 ^/ R8 {/ D# {3 b3 G$ s9 S. Q - return
Скопировать код Если у игрока нет клыков (n=0), то мы получаем занчение переменной 'chat0'. Когда метод onKill вызван в первый раз, то пока ни каких переменных не имеется и python возвращает значение None. В этом случае объявляется переменная и показывается диалог Chat0.htm. Когда мы убиваем keltir, но не получаем с него клык, функция st.get('chat0') возвращает строку true, а не None. И во второй раз окно с Chat0.htm не появится, но в окне чата появится строчка «Collected 0 of 4 fangs». По тому же принципу сделано и с Chat1.htm.
0 o& A W. v( ]) T$ \; Z; \; _% l8 g( X% g/ V! @: w/ _
+ Z8 S$ U5 x+ I" o4 k
Вот конечный рабочий вариант квеста:
) Q, I, g0 d n8 X( b1 B- import sys
4 P8 [' b& g+ ?/ j - from net.sf.l2j.gameserver.model.quest import State/ i5 ~- n2 n0 ^9 Z4 i1 b) e e) E
- from net.sf.l2j.gameserver.model.quest import QuestState$ X6 g L. X8 ~
- from net.sf.l2j.gameserver.model.quest.jython import QuestJython as JQuest3 l2 \- z6 K0 O( K! R) o
* |- s; B" |9 P U- KELTIR_NPC_ID = 12082
N) \% s9 C" k; p - FANGS_ITEM_ID = 18591 \- X1 H% r: m( ^
- DROP_RATE = 500000: G1 R2 J$ P t! S) c9 G$ o' K
- ; N5 M( I J8 ] W# q7 F
- WORLD_MAP_ITEM_ID = 1665
0 j; c7 z9 v4 _: J1 e - 3 b% I$ Z9 A' G) d( W' e! ^6 k
- def getCount(st) :, V- M* p0 C0 q. r& R
- return st.getQuestItemsCount(FANGS_ITEM_ID): W* l z, ^. R/ A) l
- * J% m- q$ K4 a+ _' w# N
- def completed(st) :
) i0 T& R" ]! v# C6 P - st.setState(COMPLETED)
- `3 C' K& i, I - st.clearQuestDrops()
/ A1 Q: p3 \ p/ d/ @1 D3 o - st.takeItems(FANGS_ITEM_ID,-1)3 L( k, Q0 |+ r3 P9 D* @3 N3 L7 F; z
- st.giveItems(WORLD_MAP_ITEM_ID,1)
8 \: c$ p8 Z R V" O [3 J - st.exitQuest(False)
$ b$ H' h. N* C: M* V - return
; Q0 G1 j/ A$ A1 U8 u
! L1 t v% f# G+ `9 d1 Z- b2 }. b- def check(st) :
( z& I5 ?/ @8 w& q, w/ l - if getCount(st) >= 4 :
, @9 @$ x" ? j& H b4 Y& ? - completed(st)" s, E( @+ b/ b( o5 V' l& ~
- return R6 U$ u# x. w) o4 n/ i
- , @# L k4 _4 @: n0 B6 n- P
- class Quest (JQuest):; [7 ~7 s: l8 E+ Q- @
& b- C( q* @0 j2 F A4 K- def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)
5 {/ Z, E1 Q; q( ^" n1 ~ - 3 `$ M3 P# R7 @; F' ]! H
- def onEvent (self,event,st):5 H- m0 q f& `( @
- id = st.getState()$ l, h9 v1 g6 }9 T
- if id == CREATED : st.setState(STARTED)
* A( |/ `. V% j6 U' ? L5 e$ E - elif id == COMPLETED: pass6 s% W. Z( n5 b* S( t, ]% v
- elif id == STARTED : check(st)
4 W. ~5 k$ V) H7 [. Y - return* O6 X5 n7 X+ C9 s! [; t! q8 A
3 `2 B! T h5 X- def onKill (self,npcId,st):
1 V9 \% i" G. J5 b9 b - if npcId == KELTIR_NPC_ID:
- h% C. v E0 a/ C% { - n = getCount(st)
* m$ F; Z) F' \' w0 U! m% \$ i - if n == 0:
* `. J, ^- P8 B& W+ e' z/ I - if st.get('chat0') == None :
' l' ^& a! n3 u - st.set("chat0", "true")
6 K- F) k) L% H: e/ `; t4 B2 E1 ~ - return "Chat0.htm"# R" N! ^% H. [! }5 y1 C" J/ i2 @
- elif n == 1:$ F6 ~0 \% v5 K G* m0 x* R# T
- if st.get('chat1') == None :- f* ~1 ]: ]( n! r6 v; H
- st.set("chat1", "true")
' a( J# r1 L3 Z- P$ e& _ - return "Chat1.htm"/ t8 ], T; I' i# S) e. O
- elif n >= 4:3 C* |9 K7 w' L" \ k. j% x; W& P
- return "Chat4.htm"
V3 M, o; [7 _7 X$ p3 T0 | - return "Collect "+str(n)+" of 4 fangs"
- X2 f/ |- W- H: l& v1 U# h& ^ - return
3 A% J9 a' N( ~5 A; g- \
. u7 k8 s, \/ O. _" g- QUEST = Quest(201, "Tutorial", "Tutorial quest")
2 P; n6 J, R/ p4 T# {; Y7 M - CREATED = State('Start', QUEST)
$ H3 F5 e$ o9 |) T5 W; R6 ?- l F9 { - STARTED = State('Started', QUEST)
# J& O2 h& w' W- F' y7 y$ i - COMPLETED = State('Completed', QUEST)+ n2 D& p2 i" Y5 g. Z
- 3 H( Y6 S% C9 E6 s. M
- QUEST.setInitialState(CREATED)
. a# g1 O) Y: n; f5 } - QUEST.addStartNpc(7056)
* j7 z7 q$ m9 ]6 s H - QUEST.addStartNpc(7012)2 B1 L5 _9 c6 f" l8 Z# X
- QUEST.addStartNpc(7009)
& z/ E9 q" h* ~# A - QUEST.addStartNpc(7011)
5 j7 r. G6 T( H" n; e' B O
' Q4 F1 H6 p( l6 {8 {3 N- @! J- STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
: K9 q ]& M& K7 ~ - STARTED.addKillId(KELTIR_NPC_ID). h+ D# d, x* W4 G+ ^7 V; [* i
- STARTED.addTalkId(7056)
* c8 M4 Y, g7 z2 K$ h$ Q Q" q - STARTED.addTalkI d(7012)7 G1 [5 d/ K6 K# X0 t4 X: \3 C# H
- STARTED.addTalkId(7009)) m3 G( v7 x! k# L' d: V
- STARTED.addTalkId(7011)
Скопировать код
5 I5 A1 o4 X1 _! J) {" {0 l$ ]8 _/ v7 ^: t6 B) W
|