Зарегистрируйтесь сейчас чтобы найти еще больше друзей, и получить полноценный доступ ко всем функциям сайта!
Для просмотра Вам необходимо авторизоваться Если Вы еще не зарегистрированы, перейдите по ссылке:Зарегистрироваться
x
Хроники Interlude. }4 N6 O- \/ B6 n {( V
Сборка L2j
2 O* V" N+ R4 g+ a7 ]# @2 g( uОбратите внимание: в файле htm стартового NCP обязательно должна быть ссылка на квест:
% }' |5 |% q' b- STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код Для этого квеста больше ничего не надо. Все необходимое для корректной работы квеста уже добавили. Вот полный текст квеста:* d3 x3 T B7 e! E9 H L: u* ?
+ M" Q7 K" ~' l8 V/ X8 K$ @
- if getCount(st) >= 4 :0 q5 f e8 o6 h& r1 p: R' q
- completed(st)
; n- J( [$ W" O+ A Z" q - return. e1 u2 U1 o% r, F9 g
- $ _$ I% b% Q1 l; A( @5 v- t& [
- class Quest (JQuest):' S! v, l% f1 U5 {
- def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)7 E- A& o" ]/ U `5 U+ Y
- def onEvent (self,event,st):
/ x7 [, c' B9 d$ D9 L$ c - id = st.getState()0 d1 j+ c+ `% L* v# w. x
- if id == CREATED : st.setState(STARTED)
; p' y b* S3 M- x+ O9 f2 X4 ] - elif id == COMPLETED: pass z6 K( ^: L* j) d
- elif id == STARTED : check(st)8 N7 O" [0 }/ W1 ?+ b l
- return
, Q- x- M7 q7 d. V
d X* M1 |) m1 v* w4 i- QUEST = Quest(201,"Tutorial", "Tutorial quest")
( \; M3 N$ C! p6 h/ a: z1 Y - CREATED = State('Start', QUEST)
& d1 P6 Z# C% T$ t" C - STARTED = State('Started', QUEST)5 J' _- }/ Q3 J7 U/ e. ?$ N
- COMPLETED = State('Completed', QUEST)+ B, U$ A) G# p% `- J/ \+ M
5 Z; U* g* U, f' n! T6 v- QUEST.setInitialState(CREATED)0 {( b" e S- Z$ j0 H5 ^
- QUEST.addStartNpc(7056)
]3 T2 d; ^9 }# u+ y - STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код Теперь рассмотрим, как это работает.
5 A3 M6 i2 L( l0 H+ q3 z4 I8 A" yИгрок подходит к начальному NCP (в данном случае 7056), нажимает на «Quest». Квест будет создан и состояние квеста перейдет к CREATED и игроку будет показана страничка Start.htm с описанием квеста. Тогда метод onEvent, поле открытия странички Start.htm переведет состояние квеста в STARTED и игроку будет показана страничка Started.htm, где будет опсание того, как найти keltirs и .т.д.: f( x' t5 x* Z4 e u2 S d
2 t6 U6 ~, b- k/ L! O0 j$ i* d. B9 b6 J
При состоянии STARTED будет зарегистрирован дроп «fangs» при убийстве keltirs. Игрок может вернуться к стартовому NCP и спросить о квесте – метод onEvent будет вызван снова. Если у игрока не хватает необходимого количества предметов, то метод check() не переведет квест в следующее состояние и Started.htm будет показана снова. Но если игрок собрал необходимее количество предметов (в данном случае 4 клыка), то метод check() вызовет метод completed() который переведет квест в новое состояние COMPLETED, заберет все клыки, даст карту мира, т.к. это награда за квест, покажет Completed.htm и завершит квест.# Z3 c! s% u* y& F
; M& A0 u9 |7 d' b0 B* w9 i
; j1 Y% [' G/ [* c: ]+ @( y. IТеперь давайте сделаем наш квест более похожим на то, что он должен из себя представлять.
, D' A6 y' {. v1 I5 [Прежде всего у нас есть 3 метода для объявления их в Яве – onTalk, onKill и onEvent. Если методы onTalk и onKill не объявлены, то за них все будет делать метод onEvent, т.е. определять квестовых монстров и вызывать диалоги NCP. Есть примечание, методы onTalk и onKill будут вызывать только диалоги с NCP в зависимости от текущего состояния квеста. Метод onKill будет вызываться только тогда, когда мы убиваем квестового монстра.
; U& Q$ ]& z; c' n7 s( j9 p7 ~5 }$ t0 c' C% [
) |5 r+ V/ v( K% n
Давайте рассмотрим как вызывается метод onKill при убийстве keltir в состоянии квеста STARTED:
! o7 y! r' b/ N5 D# e6 O) L: N- STARTED.addKillId(KELTIR_NPC_ID)
Скопировать код и метод onKill в классе Quest:( g1 k7 ?. `( @/ P* M; q0 K
/ [2 Y* m' b# @7 V4 o3 q2 q h; C/ A- class Quest (JQuest):$ A# _3 T7 r! ^2 g. m
- ...
3 T$ w6 @$ K2 ^( Z5 ^& J- f. [ - def onKill (self,npcId,st):2 R2 t: F* \, x& p& `8 K( d
- if npcId == KELTIR_NPC_ID:3 B% d" H$ n" m1 }/ F* E' a1 p6 M
- n = getCount(st)! J9 d. t M1 A' u* j: p9 m
- if n == 0:( r2 \4 R8 g, N6 j+ J
- return "Chat0.htm"* I& G3 v) j( I+ X: i( [' L9 e
- elif n == 1:
9 F t) _) O4 J6 e5 m4 U4 m; p. |% D - return "Chat1.htm"/ l3 x6 Y( b3 `
- elif n >= 4: y( e% L, J! M# c/ S9 t9 X
- return "Chat4.htm"
1 N- |4 M1 H5 }' \9 \7 Q4 Q - return "Collected "+str(n)+" of 4 fangs"1 W7 b' Z" @# k3 z4 b. s+ H( A
- return
Скопировать код Метод onKill (а так же метод onTalk) имеет следующие параметры:
; t9 }0 }! _( \; X+ O
/ U3 ]) h' J: R* h/ F+ ?( `2 c& e3 [3 ]! j3 u( l
• self – квест" M3 C+ [( z7 {- Y" l
• npcId – ID NCP, которого мы должны убивать (если это метод onTalk, то ID того NCP, с которым мы должны поговорить).
W" p3 ]+ q/ q2 S• st – текущее состояние игрока.5 Y; A9 R3 F$ x' n. Q9 V
, P+ G5 `! v: o9 [! Z& Z& O
) l5 N8 X) C7 o- }# d
В этом методе мы проверяем и отмечаем, является ли убитый NCP keltir’ом. В основном эта проверка не нужна, т.к. у нас только KELTIR_NPC_ID.2 U! y6 r- o& L6 Y3 N+ n
* e( \& D! N$ G7 e
0 r% v. ^* A$ a9 Y% O( c) E
Затем проверяем количество предметов (в данном случае количество клыков), и если их вообще нет, то возвращаем строку "Chat0.htm", если только один предмет, то возвращаем строку "Chat1.htm", если же предметов 4 или больше, то "Chat4.htm". Если строка возвращена из методов onEvent, onKill или onTalk, то сервер покажет соответствующие htm. В Chat0.htm может иметь следующий текст: «Вы не имеете ни одного клыка, возвращайтесь позже, когда соберете 4 штуки и бла, бла, бла…», в Chat1.htm может быть следующий текст: «У Вас всего 1 клык, по этому соберите еще…». В Chat4.htm – «Вы собрали необходимое количество предметов, возвращайтесь к вашему тренеру, что бы завершить квест…»
' J6 y& p2 r, W3 @ q+ v
# `* q9 l0 v( x3 H& U4 G
, t6 ?+ F- ^, C+ \- C& BПримечание: если в строка return начинается с "<html>", то будет показана страничка html с текстом, который стоит далее. Так вместо:
/ D+ D: m2 E, \6 \7 @" ^7 q* x! dreturn "Chat4.htm"
+ n& ~) B0 a* `/ l( N+ G- M6 s
$ D1 P& n6 g' B$ a L+ \1 D$ h% L9 N
можно поставить:
. G3 \: m: d( Y; N- return "<html><body>Return to your trainer to complete the quest</body></html>"
Скопировать код Так же если строка заканчивается без .htm или в начале нет <html>, то текст будет выведен, как системное сообщение в окне чата. В нашем случае мы сделаем так, что бы при каждом убийстве keltik выводилось системное сообщение: «Собрано N из 4-х клыков».3 C$ q3 U3 l; y: C8 a
* E0 J, `* i- N' M8 s
6 H$ ?- Y: f4 JНаш код для onKill имеет один недостаток. Он будет постоянно показывать Chat0.htm, Chat1.htm и Chat4.htm, нам же необходимо, что бы Chat0.htm и Chat1.htm показывались только один раз. Как нам это сделать? С помощью переменных.
; f h1 y! W4 t0 E8 r, a, W
: B2 w& y+ {6 ~2 P1 O! F1 `0 s5 J
В каждом квесте строки могут храниться с помощью переменных. Эти переменные сохраняются в Вашей БД. В каждом методе мы можем назначить, прочитать и удалить переменные. Давайте изменим метод onKill, так что бы каждый диалог вызывался только один раз., X7 J% B- m' R$ P8 }
- def onKill (self,npcId,st):
) N+ h! O- ]1 b$ C0 `& w* i. {% s5 s - if npcId == KELTIR_NPC_ID:
& Y/ s+ \0 U8 h" l( m# Y% q - n = getCount(st)
& E+ u [$ } Y9 T# u7 X. N" R' P" K - if n == 0:
1 r9 O% e, {& f6 L2 Z! P - if st.get('chat0') == None :
" n, P' y* @% U' |+ p c - st.set("chat0", "true")5 Q' d+ ]% ~# L8 I2 O' W: g
- return "Chat0.htm"
5 O3 J# @( T) E( K& e - elif n == 1:" Q8 \8 f$ D- D, B
- if st.get('chat1') == None :
* B" r3 j( m- J- R - st.set("chat1", "true"), _# [2 o# O1 l
- return "Chat1.htm"
5 d% z( S+ _2 \- L& i - elif n >= 4:
( g& n3 [' M2 {9 G - return "Chat4.htm"4 w& A- O: H* e1 h4 I( n- _( w
- return "Collected "+str(n)+" of 4 fangs"1 H$ B" p# [# @4 i8 a
- return
Скопировать код Если у игрока нет клыков (n=0), то мы получаем занчение переменной 'chat0'. Когда метод onKill вызван в первый раз, то пока ни каких переменных не имеется и python возвращает значение None. В этом случае объявляется переменная и показывается диалог Chat0.htm. Когда мы убиваем keltir, но не получаем с него клык, функция st.get('chat0') возвращает строку true, а не None. И во второй раз окно с Chat0.htm не появится, но в окне чата появится строчка «Collected 0 of 4 fangs». По тому же принципу сделано и с Chat1.htm.; O; q, D# K+ g" L2 F" z
: m) M; B7 m; X; x0 J7 @0 U1 w
3 f+ V# ^! z$ Y' `) A! ?Вот конечный рабочий вариант квеста:$ Q' f3 F$ n2 M) _" J. P y
- import sys
0 _% W2 d0 o' }) i* O - from net.sf.l2j.gameserver.model.quest import State' x, g; c1 m. g: @6 m+ |1 J8 u! m
- from net.sf.l2j.gameserver.model.quest import QuestState& y& B& T& M7 j$ Z! t
- from net.sf.l2j.gameserver.model.quest.jython import QuestJython as JQuest
/ q6 |+ K7 p8 [( t( @+ w
+ c6 F* o* Q+ ~" u$ Y- KELTIR_NPC_ID = 12082
, `% ^' t- J& M; {/ C - FANGS_ITEM_ID = 1859" r' k3 _9 R s' o9 {
- DROP_RATE = 500000
+ D2 i2 _3 m I2 b6 B
- A0 `6 Q6 x$ C6 e8 c- WORLD_MAP_ITEM_ID = 1665
# G( _, n# Q4 G7 b% Y0 k
" V! @9 ^: {3 f/ S' n- def getCount(st) :
l" P1 C8 W" ?8 p6 T3 _1 o! Y0 R - return st.getQuestItemsCount(FANGS_ITEM_ID)( |( X; F+ I5 H; t4 M* f4 m
- n3 B, q8 `/ C/ i, v0 O% y7 b# O
- def completed(st) :1 z3 Z0 F6 ^* I8 z+ q
- st.setState(COMPLETED)
! w" z% G# v% R9 v& ~' R9 ~- ` - st.clearQuestDrops()+ t; R0 S% G) K" O% F6 ?# k
- st.takeItems(FANGS_ITEM_ID,-1)
) q4 @- S6 i7 K$ \ - st.giveItems(WORLD_MAP_ITEM_ID,1)
0 g2 k3 T7 F# N8 R' K' [$ E - st.exitQuest(False)8 A! x* v9 z: Q- B
- return3 R' c" v' Z" N4 E, c8 g( m% V
: I8 S% Y8 J. T T. ]/ J9 z- def check(st) :5 ]1 n% S# y5 I# q
- if getCount(st) >= 4 :% s( J3 ?# m. U# V; r
- completed(st)7 B2 R: ]" M' L" w
- return
8 s2 A2 ^8 X1 U( U3 ^* B! f
: Q0 ^+ p7 N3 S# e6 A& {- class Quest (JQuest):
# {" [! z. A( Z0 P
( `! `* p' F2 y" }" v- def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)
! G+ b( D* L4 [2 u; g8 q
2 Y# J2 |2 E0 r4 q6 U( i- def onEvent (self,event,st):
+ U1 y) V4 U5 [. |' b' P - id = st.getState()
+ z8 r2 Q) F+ M2 @2 k - if id == CREATED : st.setState(STARTED)) D8 \( J: c- j
- elif id == COMPLETED: pass/ t2 W1 x! f/ A; t5 f* K
- elif id == STARTED : check(st)! \7 Y6 Z2 f$ E0 ^; n4 v9 E; Q
- return
' t5 R$ r7 v( c, |3 X( V1 {/ d$ e& t
' E! J0 b8 O! j, P- def onKill (self,npcId,st):
% y, s& N; |) q3 ^9 Z - if npcId == KELTIR_NPC_ID:1 c# ?$ s+ c& {5 Q! m9 ~6 A
- n = getCount(st)
: H, w1 T \" ?) C3 [$ } r - if n == 0:
4 ]; h0 K' F3 i/ V- o. ]5 g; t - if st.get('chat0') == None :5 \( D/ Q9 ^% E% Q
- st.set("chat0", "true")" X! M8 p) v- e! _
- return "Chat0.htm"
0 }" j8 j+ F" |; C9 B* F& ` - elif n == 1:7 d% O; A, X: H h/ e5 t
- if st.get('chat1') == None :! ^3 q$ O2 ]2 K+ q/ Q
- st.set("chat1", "true")
( d {1 l7 r+ q+ j4 ?. G6 d - return "Chat1.htm"5 X+ v# W& ]* v1 X- q5 m
- elif n >= 4:% T' n# s" H2 b6 K. E
- return "Chat4.htm"' R2 }& B- P* i9 P
- return "Collect "+str(n)+" of 4 fangs") \. _7 _! R) f4 U& i' a! Q
- return
- }1 L6 Z- Y4 W9 H5 ~ - 6 V( P9 x3 K; {, K+ `# K
- QUEST = Quest(201, "Tutorial", "Tutorial quest"): i+ G: g- n; A7 I4 B; B
- CREATED = State('Start', QUEST)5 I1 o% ?, ?5 \, R
- STARTED = State('Started', QUEST)
! S+ `' A2 N/ ?* C2 R - COMPLETED = State('Completed', QUEST)
1 M4 C9 J( Q/ y' h b6 } - " l! J5 n z& O) E
- QUEST.setInitialState(CREATED), z. ~7 Z, \1 l3 e7 w
- QUEST.addStartNpc(7056)
" i0 |0 g& p: A - QUEST.addStartNpc(7012)
+ R+ K/ X9 @ v) R8 @ - QUEST.addStartNpc(7009); j1 o1 E6 |+ C* M' O% @- p
- QUEST.addStartNpc(7011)" p9 C2 j0 K1 `" ~8 D
% E6 t7 X7 s; D) w: y9 N- STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
( T! V% a' V$ T7 G - STARTED.addKillId(KELTIR_NPC_ID)
% r8 ?* @3 G/ m6 V0 I - STARTED.addTalkId(7056)5 j5 d% T8 F7 O; B. t6 a; {1 ]
- STARTED.addTalkI d(7012)1 `3 e" m+ N4 x: P3 _9 }* |
- STARTED.addTalkId(7009)
. V' s ^7 m1 T5 C$ s/ V0 \ - STARTED.addTalkId(7011)
Скопировать код ) w) j4 F- g/ n6 Y5 k6 H( j
, L: i5 u' x: Z1 V9 r
|