Зарегистрируйтесь сейчас чтобы найти еще больше друзей, и получить полноценный доступ ко всем функциям сайта!
Для просмотра Вам необходимо авторизоваться Если Вы еще не зарегистрированы, перейдите по ссылке:Зарегистрироваться
x
Хроники Interlude) _- X: l- F2 n" B) } S
Сборка L2j
$ X0 c$ J0 Y7 [Обратите внимание: в файле htm стартового NCP обязательно должна быть ссылка на квест:
$ q; P/ G& d2 Q$ ~5 L+ V- STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код Для этого квеста больше ничего не надо. Все необходимое для корректной работы квеста уже добавили. Вот полный текст квеста:
; Z# W4 k2 b$ J2 \, a. G+ P; i7 v
" o% @" ` T8 C' U4 O- if getCount(st) >= 4 :$ y T, |& q6 ~
- completed(st)
# d% @; Q3 E! J5 |/ R - return
6 H) a; b; {) S* I* K: ~6 B2 ^
+ {: Z t0 @) u: N: o6 B4 d- class Quest (JQuest):/ j; `5 O$ J: e7 S
- def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)$ z ~% f, @0 b) z
- def onEvent (self,event,st):
: P& `0 P: |2 [9 ] - id = st.getState()
8 N/ Q4 j- p9 E - if id == CREATED : st.setState(STARTED), F( p* i# L8 F* q0 L8 Q& |" X: U
- elif id == COMPLETED: pass
0 Y% ]4 \% O+ D1 y4 q$ X - elif id == STARTED : check(st)
3 D! `( C# U F - return
' v* B5 [1 W! c; ~/ H - # W1 Q% O" E1 Q* X8 o" v
- QUEST = Quest(201,"Tutorial", "Tutorial quest")' ]/ W- F4 s5 ?( G
- CREATED = State('Start', QUEST)
6 O# M8 c$ l2 E. i( N/ v1 O3 K - STARTED = State('Started', QUEST)/ f* n5 M% D$ [8 Z
- COMPLETED = State('Completed', QUEST)4 |; v$ X) n4 s9 r
- 3 d3 p% I6 v$ o2 X5 K" P2 p* _
- QUEST.setInitialState(CREATED)$ Y e8 C7 j6 \
- QUEST.addStartNpc(7056)
2 e }/ `( _# U7 L! z - STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код Теперь рассмотрим, как это работает.
9 M6 N1 J, F2 k5 F8 ^Игрок подходит к начальному NCP (в данном случае 7056), нажимает на «Quest». Квест будет создан и состояние квеста перейдет к CREATED и игроку будет показана страничка Start.htm с описанием квеста. Тогда метод onEvent, поле открытия странички Start.htm переведет состояние квеста в STARTED и игроку будет показана страничка Started.htm, где будет опсание того, как найти keltirs и .т.д.
5 t% K5 c4 q5 A M- @# F- f# P7 O3 R/ W" k% u+ Q
! Z: T+ H. _- X- S$ k, _При состоянии STARTED будет зарегистрирован дроп «fangs» при убийстве keltirs. Игрок может вернуться к стартовому NCP и спросить о квесте – метод onEvent будет вызван снова. Если у игрока не хватает необходимого количества предметов, то метод check() не переведет квест в следующее состояние и Started.htm будет показана снова. Но если игрок собрал необходимее количество предметов (в данном случае 4 клыка), то метод check() вызовет метод completed() который переведет квест в новое состояние COMPLETED, заберет все клыки, даст карту мира, т.к. это награда за квест, покажет Completed.htm и завершит квест." b5 M! W5 _5 G* U) B
& ^7 [' x* b. H) ]
' r$ a, i4 ^1 d+ y2 P+ ^Теперь давайте сделаем наш квест более похожим на то, что он должен из себя представлять.
& s( k) E- R& D I& ]/ q: ^$ d* rПрежде всего у нас есть 3 метода для объявления их в Яве – onTalk, onKill и onEvent. Если методы onTalk и onKill не объявлены, то за них все будет делать метод onEvent, т.е. определять квестовых монстров и вызывать диалоги NCP. Есть примечание, методы onTalk и onKill будут вызывать только диалоги с NCP в зависимости от текущего состояния квеста. Метод onKill будет вызываться только тогда, когда мы убиваем квестового монстра.
0 Q. b% S& [& c
; B' f6 o6 U+ N, ?* h5 l! n9 l: R- k9 K* `) g6 h
Давайте рассмотрим как вызывается метод onKill при убийстве keltir в состоянии квеста STARTED:- F6 d9 E) c& v' V3 L- N* i6 S* ]
- STARTED.addKillId(KELTIR_NPC_ID)
Скопировать код и метод onKill в классе Quest:
" `$ f! Z+ \' \) N5 ?0 L
8 D$ t9 f0 t" g' `+ T- class Quest (JQuest):% p6 @$ S( b/ P
- ...$ d5 B- U; R9 F( f+ B; G. T. ~) l
- def onKill (self,npcId,st):# G+ o& Q9 U" y! H7 k$ `
- if npcId == KELTIR_NPC_ID:4 r) L0 w7 X" Z: u4 s
- n = getCount(st)
, Y1 l* F0 H% D4 |; \ - if n == 0:
( n2 W' Y$ V* Z9 n - return "Chat0.htm"; @6 w1 q% K' _% K! c
- elif n == 1:' U$ L4 C# V1 u% j( l! f
- return "Chat1.htm"4 R5 }7 J5 n/ _/ |7 S5 P8 R
- elif n >= 4:
Z! @1 g6 ?; e) I2 G4 m, N! ]" Y - return "Chat4.htm"
% _2 C9 B% e( |/ I: Q" g - return "Collected "+str(n)+" of 4 fangs") G7 U% R1 F; v3 D% \3 \# c6 g
- return
Скопировать код Метод onKill (а так же метод onTalk) имеет следующие параметры:
+ v2 z- }" I8 M1 Q$ ?7 X% L4 M. x# K% L) i
' S3 R$ k* T% f$ `) c4 b% C• self – квест
; k. x4 {0 J: p, j. p• npcId – ID NCP, которого мы должны убивать (если это метод onTalk, то ID того NCP, с которым мы должны поговорить)., ~, ^+ N! M e5 U1 M
• st – текущее состояние игрока. t8 y" Z$ X# B7 T" H
5 m3 _3 p5 @' [2 k7 e
* E- T" \4 J& G; {7 cВ этом методе мы проверяем и отмечаем, является ли убитый NCP keltir’ом. В основном эта проверка не нужна, т.к. у нас только KELTIR_NPC_ID.
) ^; H9 e4 l# } C
2 y# I% l8 s5 n% R$ p. n# u4 a9 ]7 |# U6 I: B
Затем проверяем количество предметов (в данном случае количество клыков), и если их вообще нет, то возвращаем строку "Chat0.htm", если только один предмет, то возвращаем строку "Chat1.htm", если же предметов 4 или больше, то "Chat4.htm". Если строка возвращена из методов onEvent, onKill или onTalk, то сервер покажет соответствующие htm. В Chat0.htm может иметь следующий текст: «Вы не имеете ни одного клыка, возвращайтесь позже, когда соберете 4 штуки и бла, бла, бла…», в Chat1.htm может быть следующий текст: «У Вас всего 1 клык, по этому соберите еще…». В Chat4.htm – «Вы собрали необходимое количество предметов, возвращайтесь к вашему тренеру, что бы завершить квест…»; a. N& e; i7 J/ V2 E! g
d' i8 t, n7 `6 P- I& I& g% J3 ]' }% r9 p+ V" ` F: p* O/ i* w f& L
Примечание: если в строка return начинается с "<html>", то будет показана страничка html с текстом, который стоит далее. Так вместо:
1 j) V/ y9 r+ P7 a0 I- \" V: y, wreturn "Chat4.htm") B1 }9 M& l' g+ X* \
- w; e; x. |# i0 e" t5 X
) Y- V, j% F* w' P/ `9 Cможно поставить:+ t4 C) R ]7 ^* ^$ @, l. C
- return "<html><body>Return to your trainer to complete the quest</body></html>"
Скопировать код Так же если строка заканчивается без .htm или в начале нет <html>, то текст будет выведен, как системное сообщение в окне чата. В нашем случае мы сделаем так, что бы при каждом убийстве keltik выводилось системное сообщение: «Собрано N из 4-х клыков».
- [* ?7 I) y- U; p: `4 T2 }9 t; h7 i& u7 L7 c, }3 r! k7 Z3 P
2 J2 z7 h" u$ J) @9 P0 Q2 X, Z! ?3 X
Наш код для onKill имеет один недостаток. Он будет постоянно показывать Chat0.htm, Chat1.htm и Chat4.htm, нам же необходимо, что бы Chat0.htm и Chat1.htm показывались только один раз. Как нам это сделать? С помощью переменных.6 G, c- ^/ Q8 q) L7 |. Q" b( w- t+ |, V
; A2 }2 C9 c8 M. P+ B
4 T/ l @8 f% X- OВ каждом квесте строки могут храниться с помощью переменных. Эти переменные сохраняются в Вашей БД. В каждом методе мы можем назначить, прочитать и удалить переменные. Давайте изменим метод onKill, так что бы каждый диалог вызывался только один раз., {3 R3 w" Y8 ]
- def onKill (self,npcId,st):
, G, ~2 d9 b$ h3 q - if npcId == KELTIR_NPC_ID:
' y7 T6 O5 M, d$ O h* K( T - n = getCount(st)
1 S" Y& r. _! B - if n == 0:+ ^- d; [* a) d$ B# e% h( D/ D9 h5 s
- if st.get('chat0') == None :
2 P8 ?& F4 y. ~1 s - st.set("chat0", "true")
2 P Q# T) E% o; f - return "Chat0.htm"* ]& }# J+ y% g
- elif n == 1:
. Z t) ~& q! N6 }. m* o( u+ d4 H - if st.get('chat1') == None :8 @3 j- {3 J/ p9 |5 S
- st.set("chat1", "true")
; j, n$ P) F f7 W7 U. M - return "Chat1.htm": J. Z: s9 _% [& d
- elif n >= 4:
$ P7 g; j0 i; O/ E0 t2 D2 y - return "Chat4.htm"8 J" {$ r5 z, R5 m% y& i
- return "Collected "+str(n)+" of 4 fangs"
' A c( r+ S {6 W$ P% B) m - return
Скопировать код Если у игрока нет клыков (n=0), то мы получаем занчение переменной 'chat0'. Когда метод onKill вызван в первый раз, то пока ни каких переменных не имеется и python возвращает значение None. В этом случае объявляется переменная и показывается диалог Chat0.htm. Когда мы убиваем keltir, но не получаем с него клык, функция st.get('chat0') возвращает строку true, а не None. И во второй раз окно с Chat0.htm не появится, но в окне чата появится строчка «Collected 0 of 4 fangs». По тому же принципу сделано и с Chat1.htm.
2 b' C7 l6 v4 t0 A( O
( M/ H* T3 S. A8 \( j
5 [# D+ ~/ _/ G- o& k( ^/ tВот конечный рабочий вариант квеста:% g1 I5 _9 p) N+ p3 I
- import sys
# y/ F+ Z& c' ]" n8 X9 v; n6 t) m - from net.sf.l2j.gameserver.model.quest import State9 a$ O; H" m4 H) ]0 t
- from net.sf.l2j.gameserver.model.quest import QuestState
7 D b1 V7 O* o% f+ _; T0 H - from net.sf.l2j.gameserver.model.quest.jython import QuestJython as JQuest4 D! S, I9 k8 T) z
# |5 y$ }$ o# ^! g$ p- KELTIR_NPC_ID = 12082) f/ }; Z( U( R. K0 R( b8 ^
- FANGS_ITEM_ID = 1859
3 A* h% T+ q# o - DROP_RATE = 500000
. f- P5 Q/ _0 n
- {. Q; h9 p* f% \- WORLD_MAP_ITEM_ID = 1665! M c, A W8 l i! r5 e% \! ?
- 7 n! n, X- M) p0 U j7 \
- def getCount(st) :9 }( M5 I* l6 |& O# _- X) S
- return st.getQuestItemsCount(FANGS_ITEM_ID)
2 o( @- u/ d9 z! s - 8 Q* T# R+ a0 \& b0 I
- def completed(st) :
& |& j4 x9 a- j - st.setState(COMPLETED)2 Z- a2 f7 Q' J/ V8 {
- st.clearQuestDrops()
' C! ?4 D9 u( d+ p - st.takeItems(FANGS_ITEM_ID,-1)$ ~! v1 g, d+ b ^, {6 \
- st.giveItems(WORLD_MAP_ITEM_ID,1)
( m! T6 `2 l" {. I- J0 ^; G4 B - st.exitQuest(False) @% j% i" Z" ~6 q
- return
! Z0 J0 W% O" E# w# Y4 Y
3 C* W. d$ I9 D8 V% N- def check(st) :- N" b6 f3 _9 u
- if getCount(st) >= 4 :
& T. S; L& `. \0 P- V - completed(st)) [% R4 _4 s/ w
- return9 `% c6 t. Q/ J; b+ x
- . t& `3 h u' O- c# A
- class Quest (JQuest):
4 b, M( g4 Q: a# r' {. [* F - 1 t; d$ y; l- s: S* z# w& x
- def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)( {1 Q8 H v0 V
. M/ @ M7 k% |2 e3 X( O- def onEvent (self,event,st):
3 @' @3 z' R/ T0 d7 Y" d - id = st.getState()
3 J. P5 }9 {, y' }& H- c5 m. [ - if id == CREATED : st.setState(STARTED)
! u# v9 |' U! \3 q$ I: W - elif id == COMPLETED: pass
$ P! l$ K K* B% _7 u2 a - elif id == STARTED : check(st)
% Z0 w! j: u, z - return1 \( D6 |% M, g! s$ y
- ) Y) V( R! X* [! x/ m$ y
- def onKill (self,npcId,st):) p& r1 d1 O8 a! Q
- if npcId == KELTIR_NPC_ID:3 T4 U. k2 ]" _& P0 ~
- n = getCount(st)! w1 v8 `. v: Q: c2 K, Z9 A
- if n == 0:* O4 P) N$ D( f$ h! c4 ~" t
- if st.get('chat0') == None :, T' `$ J4 I, f2 L/ r7 |# A
- st.set("chat0", "true"). j% M" f4 n( L
- return "Chat0.htm", A& f0 u: Q0 x8 x- F3 r* ]
- elif n == 1:2 h0 T0 V1 z4 ~2 s" \
- if st.get('chat1') == None :
1 z$ H& n/ c) T& J* l - st.set("chat1", "true"). ]4 w8 V9 u; i% s- X0 a/ Q& ?$ e; ~
- return "Chat1.htm"
9 {: S& q, c) G7 F! n - elif n >= 4:+ ~" @3 G1 c6 f. e) l4 D# q5 `
- return "Chat4.htm"
1 l" O d; f8 I, i s - return "Collect "+str(n)+" of 4 fangs"
3 l3 a3 J: ~+ Z4 u, H. Q ? - return
1 R5 F7 `& k5 T; N - * Y' C+ M+ \2 E4 t# s. @ C
- QUEST = Quest(201, "Tutorial", "Tutorial quest")' V2 H# z4 `3 O+ |- M F5 t
- CREATED = State('Start', QUEST); Y' O' b2 Z+ s
- STARTED = State('Started', QUEST)
" E: p8 {/ K5 _) c. T - COMPLETED = State('Completed', QUEST). b8 ?: ], I0 L3 o l
! j5 [. q9 H+ \& r. r5 [; i- QUEST.setInitialState(CREATED)
* q$ |2 r8 S3 V& a - QUEST.addStartNpc(7056)/ P2 }7 n; l! U; B' L
- QUEST.addStartNpc(7012)2 Q# Q6 r* H5 H+ \
- QUEST.addStartNpc(7009)
" K% q' C' X7 L a" ]+ ] - QUEST.addStartNpc(7011)
# h8 B2 |5 U l, f5 G# P5 C
: Q2 n6 S3 j U! E2 v# L- STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)3 @# W/ R" m1 }9 H
- STARTED.addKillId(KELTIR_NPC_ID)
% k8 B! T/ l, J v: { - STARTED.addTalkId(7056)
' O/ s0 p- d2 H. z - STARTED.addTalkI d(7012)5 M" K2 p8 M3 }8 ~* ~1 m
- STARTED.addTalkId(7009)
! R' c8 g! T% \+ [ - STARTED.addTalkId(7011)
Скопировать код 0 I3 [2 ?, }: ~' |* q
/ g1 T- h A/ R& @ k/ \2 z7 {5 _ |