Зарегистрируйтесь сейчас чтобы найти еще больше друзей, и получить полноценный доступ ко всем функциям сайта!
Для просмотра Вам необходимо авторизоваться Если Вы еще не зарегистрированы, перейдите по ссылке:Зарегистрироваться
x
Хроники Interlude- p2 i! r5 Z0 J" w u/ `
Сборка L2j
2 X3 u4 o' `& h+ a0 S* AОбратите внимание: в файле htm стартового NCP обязательно должна быть ссылка на квест:
9 W$ O t( c( N- STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код Для этого квеста больше ничего не надо. Все необходимое для корректной работы квеста уже добавили. Вот полный текст квеста:+ R/ ~2 h5 |9 J. j
3 k/ V8 S* V: z; i0 f) k* O2 {0 O
- if getCount(st) >= 4 :
2 g$ w# ?: ~2 |* G' {3 z - completed(st)
2 Z4 t$ |* X9 o - return
4 f, e# L5 N: B+ O* _2 }% _5 N
. [) o$ S1 K( _8 I: `- class Quest (JQuest):
: o+ N' m9 v* R+ ~( y - def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)3 d7 i) K0 m: R
- def onEvent (self,event,st):& O7 Z3 H' X3 F* S
- id = st.getState()/ I7 i; R( g6 a2 d; P3 T
- if id == CREATED : st.setState(STARTED)
0 n6 X$ p1 ^. t, ^) I - elif id == COMPLETED: pass
' n+ U# h- w8 J2 p) J - elif id == STARTED : check(st)
2 P/ j, i1 L( U: S s - return2 G* l$ i: N& H2 R. j' @$ Y
) c1 v$ M+ B# S0 I- QUEST = Quest(201,"Tutorial", "Tutorial quest")
" T% @; D0 c( @7 D* ^- i - CREATED = State('Start', QUEST)
0 F- J% M2 ~8 X6 O+ \5 i - STARTED = State('Started', QUEST)6 I7 I8 u: E- L7 Y9 r# g9 e
- COMPLETED = State('Completed', QUEST)
7 Q/ @, {9 b4 R7 B8 ]( Z - , H1 }) ~8 g4 b
- QUEST.setInitialState(CREATED)6 D& k+ x( m7 j1 v% [
- QUEST.addStartNpc(7056)
+ o4 ~# {: E) Y4 `8 W: ] - STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код Теперь рассмотрим, как это работает.
; e. J) `; j2 D' g4 xИгрок подходит к начальному NCP (в данном случае 7056), нажимает на «Quest». Квест будет создан и состояние квеста перейдет к CREATED и игроку будет показана страничка Start.htm с описанием квеста. Тогда метод onEvent, поле открытия странички Start.htm переведет состояние квеста в STARTED и игроку будет показана страничка Started.htm, где будет опсание того, как найти keltirs и .т.д.
5 I/ Y' g! y/ G( J' R/ ]) J, U1 C8 f6 `
/ f0 i% {5 M5 ?5 V; I+ r7 ~При состоянии STARTED будет зарегистрирован дроп «fangs» при убийстве keltirs. Игрок может вернуться к стартовому NCP и спросить о квесте – метод onEvent будет вызван снова. Если у игрока не хватает необходимого количества предметов, то метод check() не переведет квест в следующее состояние и Started.htm будет показана снова. Но если игрок собрал необходимее количество предметов (в данном случае 4 клыка), то метод check() вызовет метод completed() который переведет квест в новое состояние COMPLETED, заберет все клыки, даст карту мира, т.к. это награда за квест, покажет Completed.htm и завершит квест.* y6 G7 V" B! h( {( ~
& k, R* g |) T3 ?; V
0 J) `! v# m; M* r* y7 m X dТеперь давайте сделаем наш квест более похожим на то, что он должен из себя представлять.
. P/ u; F" ^4 x, ]Прежде всего у нас есть 3 метода для объявления их в Яве – onTalk, onKill и onEvent. Если методы onTalk и onKill не объявлены, то за них все будет делать метод onEvent, т.е. определять квестовых монстров и вызывать диалоги NCP. Есть примечание, методы onTalk и onKill будут вызывать только диалоги с NCP в зависимости от текущего состояния квеста. Метод onKill будет вызываться только тогда, когда мы убиваем квестового монстра.& e8 v5 k0 L4 C2 H
- L- j4 E# _% P; A4 Y# D2 D4 E
; s( U* }1 m; G: }
Давайте рассмотрим как вызывается метод onKill при убийстве keltir в состоянии квеста STARTED:2 C. r2 ]: U9 t+ h# F- E
- STARTED.addKillId(KELTIR_NPC_ID)
Скопировать код и метод onKill в классе Quest:
0 U! g8 O4 D* f4 G: u, N! C% w9 K$ R9 b( Y
- class Quest (JQuest):/ n: [' u4 v7 d8 J# V2 ?3 C
- ...
1 |+ r3 V" ~( f0 a/ Z7 L% L - def onKill (self,npcId,st):4 T* H% i* f" B( A, F- X1 N$ d
- if npcId == KELTIR_NPC_ID:
2 Z+ y, e; q: ^+ n - n = getCount(st)+ N; ?' ?& Y1 |0 b
- if n == 0:' v1 D0 h( _1 x; T; g1 |; y" ^
- return "Chat0.htm"
0 [$ V% G" q1 P3 X- h- h - elif n == 1:( y, [5 a; \4 w! Q: O0 X, o
- return "Chat1.htm"
% t6 y& F7 x" }3 L - elif n >= 4:
) T2 `% `' @* j1 m - return "Chat4.htm"
1 k* \1 I H) @" J m, q - return "Collected "+str(n)+" of 4 fangs"1 c- u; s* b3 P/ T: m R9 v
- return
Скопировать код Метод onKill (а так же метод onTalk) имеет следующие параметры:+ v b& }& Y# H5 K5 o, Y( L/ h {
3 A' I M2 c3 }- c+ d3 {/ F# n' p
5 X" k9 \8 f! Q• self – квест# ~1 H. T( ]) T( F% G
• npcId – ID NCP, которого мы должны убивать (если это метод onTalk, то ID того NCP, с которым мы должны поговорить).
& O. T2 ?$ K: `# o• st – текущее состояние игрока.$ G* x4 c' K q
2 u @: [9 J- S) b, G/ u1 o; G
8 g- Q' L/ G( ]9 C. LВ этом методе мы проверяем и отмечаем, является ли убитый NCP keltir’ом. В основном эта проверка не нужна, т.к. у нас только KELTIR_NPC_ID.
5 y7 d+ J& Y+ w" U% s" N" x5 |
4 V# X7 ]/ d( ?4 c( V: |4 @( ] M; t+ H& }9 e! }/ c
Затем проверяем количество предметов (в данном случае количество клыков), и если их вообще нет, то возвращаем строку "Chat0.htm", если только один предмет, то возвращаем строку "Chat1.htm", если же предметов 4 или больше, то "Chat4.htm". Если строка возвращена из методов onEvent, onKill или onTalk, то сервер покажет соответствующие htm. В Chat0.htm может иметь следующий текст: «Вы не имеете ни одного клыка, возвращайтесь позже, когда соберете 4 штуки и бла, бла, бла…», в Chat1.htm может быть следующий текст: «У Вас всего 1 клык, по этому соберите еще…». В Chat4.htm – «Вы собрали необходимое количество предметов, возвращайтесь к вашему тренеру, что бы завершить квест…»
. f7 B4 |8 U! L/ ]! x( D0 c: W+ q$ {
* [( g# _ k l: P* K
Примечание: если в строка return начинается с "<html>", то будет показана страничка html с текстом, который стоит далее. Так вместо:/ W1 m$ q& u& x6 ]/ k' R
return "Chat4.htm"8 o& a1 W* v" q" c4 B! {1 U9 n
! `6 g) n6 @5 S1 q3 {: }& q
( \( ^! h6 A/ k r: M' wможно поставить:, G c/ P1 x: U* a6 ^# X
- return "<html><body>Return to your trainer to complete the quest</body></html>"
Скопировать код Так же если строка заканчивается без .htm или в начале нет <html>, то текст будет выведен, как системное сообщение в окне чата. В нашем случае мы сделаем так, что бы при каждом убийстве keltik выводилось системное сообщение: «Собрано N из 4-х клыков».
5 v' k P3 I. M" f2 S7 }! k
/ A) p7 o2 n! h. x% G
4 n3 k/ K9 c T. P. rНаш код для onKill имеет один недостаток. Он будет постоянно показывать Chat0.htm, Chat1.htm и Chat4.htm, нам же необходимо, что бы Chat0.htm и Chat1.htm показывались только один раз. Как нам это сделать? С помощью переменных.% ]+ K) u" D0 N' J
/ D/ w+ r5 g5 W1 M! W4 b
9 @$ ?: E( G4 [/ uВ каждом квесте строки могут храниться с помощью переменных. Эти переменные сохраняются в Вашей БД. В каждом методе мы можем назначить, прочитать и удалить переменные. Давайте изменим метод onKill, так что бы каждый диалог вызывался только один раз.
- q( D' N2 v) C; o# H- def onKill (self,npcId,st):
7 v& ^ a6 a- | - if npcId == KELTIR_NPC_ID:
?4 _ I3 V6 k) r' o - n = getCount(st)
- D, a$ R$ t4 l9 S - if n == 0:: r: X( k0 X6 J5 q, F U7 V& ]
- if st.get('chat0') == None :
) M) T J9 ]4 M8 i/ D - st.set("chat0", "true")
( Y Y, m2 L$ c% A7 | - return "Chat0.htm"
* J$ [, g0 \3 u6 z4 O+ A - elif n == 1:' x0 p+ A$ |# s, @
- if st.get('chat1') == None :1 O: H; A8 H: E
- st.set("chat1", "true")1 X; u" n; |( ? \+ ^7 T* H7 P
- return "Chat1.htm"
( w( C4 z! X. n1 O, c - elif n >= 4:7 q6 I" s! J) H
- return "Chat4.htm"
: E0 @. F# \+ W' Q9 G - return "Collected "+str(n)+" of 4 fangs"
" n2 |2 u6 C- a3 W5 F% N - return
Скопировать код Если у игрока нет клыков (n=0), то мы получаем занчение переменной 'chat0'. Когда метод onKill вызван в первый раз, то пока ни каких переменных не имеется и python возвращает значение None. В этом случае объявляется переменная и показывается диалог Chat0.htm. Когда мы убиваем keltir, но не получаем с него клык, функция st.get('chat0') возвращает строку true, а не None. И во второй раз окно с Chat0.htm не появится, но в окне чата появится строчка «Collected 0 of 4 fangs». По тому же принципу сделано и с Chat1.htm.
# B/ A5 [& e; S, `' Q' `$ t& f" u" T2 p% Z
, A2 u; N+ h% P& m$ n
Вот конечный рабочий вариант квеста:
+ n# w6 U' K6 G5 a* v c" j; b- F4 T; U- import sys9 ]. y; n1 j8 F" K( e5 w
- from net.sf.l2j.gameserver.model.quest import State
5 _! P* `. ]/ Q! C/ ] - from net.sf.l2j.gameserver.model.quest import QuestState
( K8 k; V6 f/ ?! j L - from net.sf.l2j.gameserver.model.quest.jython import QuestJython as JQuest
4 ]0 c+ a: R# o3 { - " @6 R8 B ~4 f& x* U5 c. @
- KELTIR_NPC_ID = 12082& H- K2 `7 i0 ]# Y% T0 v
- FANGS_ITEM_ID = 1859
( h3 E; l) l& t. Y/ W2 {; K8 ~ - DROP_RATE = 500000& v' y$ L7 K; y7 i% j
6 { p! C4 Q( C- ?4 m$ u0 w, @0 ]: C9 L- WORLD_MAP_ITEM_ID = 16651 i. I6 f9 B% J* l6 k
' F# r* m3 L. ]. M1 H" @- def getCount(st) :
' K+ @3 `% a( u) K; r/ g& J - return st.getQuestItemsCount(FANGS_ITEM_ID)
$ g5 h# Q$ h1 R. K+ g h. ~3 j
6 D9 \# G) D% p9 u8 S! r- def completed(st) :$ s) S' X3 \1 u$ H
- st.setState(COMPLETED)
7 K: T7 N: H0 n+ ^( V) r( a - st.clearQuestDrops()
9 G6 o% [ O3 s+ X - st.takeItems(FANGS_ITEM_ID,-1)
|0 s J0 E6 u" k1 B - st.giveItems(WORLD_MAP_ITEM_ID,1)/ L- _+ A9 J- F# d) P* c/ g( j6 }
- st.exitQuest(False)' L" n" ]2 X) y- ?' O" W
- return2 x6 c0 ~* F- l) G. L
- 0 Y& T' D, ]. f/ q( } j0 ]
- def check(st) :* {1 M0 q7 ? n: ] n& \' @
- if getCount(st) >= 4 :
$ J* B! z+ l4 n2 Q+ i8 B% z( L - completed(st)
2 K" }7 b5 p" H4 g U( R - return6 E0 T; e, K, z, ?3 ?/ E
- $ x3 ]1 L3 a0 ^* a3 o
- class Quest (JQuest):
' t% e/ D5 |% r9 A. M1 r) b; | - % _5 A1 J9 D b6 G; W
- def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)
$ a2 T# |+ l( c8 Y9 G- X
4 i( [3 D: E( D$ Q- def onEvent (self,event,st):
0 c$ p/ m( Q+ [! ~3 S5 M - id = st.getState()
) H1 [) U+ ]/ X, x - if id == CREATED : st.setState(STARTED)5 K% `4 A$ P( O& T. I0 m
- elif id == COMPLETED: pass
e4 q; N3 G L' s( S; i - elif id == STARTED : check(st)4 A7 ]' C3 `6 ^7 U& x
- return( l6 t5 k ^* t# g J% h0 r% x
' [. }) j% }# R$ t& Z- def onKill (self,npcId,st):
/ [8 ^. V& x, Y" N- H - if npcId == KELTIR_NPC_ID:
6 n% j) ]5 z. b& E* d - n = getCount(st)
% x: ^* i8 J& ]1 }' m* B& [/ { - if n == 0:
& S1 G- o9 I2 m9 K) \ - if st.get('chat0') == None :7 c3 ?1 j# \) }6 p5 G- B) O
- st.set("chat0", "true")
" e3 J- I1 S B4 b/ J0 a - return "Chat0.htm"; ]4 T; V) T, n: I
- elif n == 1:* b7 w- I1 x' S2 T
- if st.get('chat1') == None :
. n# L3 p) ^/ T, w - st.set("chat1", "true")
6 O% r, c7 ^. d5 u5 k - return "Chat1.htm"
, V: O* d O* S' j, [" l4 I - elif n >= 4:
" d1 x' `6 x$ ?% h - return "Chat4.htm"
! w# g& K3 w0 T- U* P6 {; C - return "Collect "+str(n)+" of 4 fangs", [; Q. d2 K% a N) p2 F3 `2 r, c
- return9 ~' e$ k* Z& [; U/ Y8 h
- N/ ^3 C; b8 q" g5 Q
- QUEST = Quest(201, "Tutorial", "Tutorial quest")
. f h/ n( [' P - CREATED = State('Start', QUEST)% i4 o' x: }3 v, [
- STARTED = State('Started', QUEST)" j0 g4 N: X( H
- COMPLETED = State('Completed', QUEST)3 w) c, J$ L% y3 Q, B, J6 Y9 w
- 7 G% t! H+ f! u# b% U, `! ]' [
- QUEST.setInitialState(CREATED); i2 ]$ M" c- Z5 _/ ], x
- QUEST.addStartNpc(7056)3 ?+ P/ J; G; R1 T" h( K! u; E3 @
- QUEST.addStartNpc(7012)& i6 t3 b. J% g1 m# J X
- QUEST.addStartNpc(7009)
2 M- w; {7 A' P" T# N - QUEST.addStartNpc(7011)" C; N" F. @9 w' _7 |( \
- t! v& r( W: I5 I7 J- STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)* A2 _3 R3 w8 q5 F+ U, X
- STARTED.addKillId(KELTIR_NPC_ID)
; d7 H) d7 ~. x; R - STARTED.addTalkId(7056)
5 L8 i9 ?) W+ Y: s z* M# | - STARTED.addTalkI d(7012)! b7 e$ f+ q: O' j% w
- STARTED.addTalkId(7009)! J. N3 B2 `4 E. H( l5 J( _
- STARTED.addTalkId(7011)
Скопировать код - v' T! E$ V& r9 n; Y; x) o9 r) Q
3 C, c, S( u' F# K: s) t. H% | |