Зарегистрируйтесь сейчас чтобы найти еще больше друзей, и получить полноценный доступ ко всем функциям сайта!
Для просмотра Вам необходимо авторизоваться Если Вы еще не зарегистрированы, перейдите по ссылке:Зарегистрироваться
x
Хроники Interlude/ I( o* [2 e# G1 K) o" U
Сборка L2j
- y& w8 r: z2 MОбратите внимание: в файле htm стартового NCP обязательно должна быть ссылка на квест:7 b! w2 B! ^" ]) Y+ P. h; u# p3 C
- STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код Для этого квеста больше ничего не надо. Все необходимое для корректной работы квеста уже добавили. Вот полный текст квеста:
5 @& j( m! S! [1 y# {) E2 y" {/ t4 X8 W% Z
- if getCount(st) >= 4 :
; n( I) q- s" I- k, T/ z! k$ i - completed(st)
% L7 Y. u% m2 J5 c$ j9 K3 c# D - return
/ I4 }+ x1 t, w y( G - 8 a& F$ m4 S& S" J! W. m# S/ I
- class Quest (JQuest): Y4 b- j- c4 a6 p
- def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr): O) s2 A/ C1 h s/ C
- def onEvent (self,event,st):* ^) }8 C4 X" H
- id = st.getState()* L" R8 g9 R# {
- if id == CREATED : st.setState(STARTED)
" _6 }, N ?' ~3 d - elif id == COMPLETED: pass
- ~2 Z0 C0 ~9 k6 P R" j N - elif id == STARTED : check(st)
9 e2 I+ Q( m) Z8 G - return
- x, N# H/ C: {* ^5 |
- l7 p' i; a2 V' B% J) T& O0 k- QUEST = Quest(201,"Tutorial", "Tutorial quest")6 H' L8 T, L4 H0 S6 A, x
- CREATED = State('Start', QUEST)( U# R$ d: d4 h
- STARTED = State('Started', QUEST)4 V* ~0 B) _0 g7 T
- COMPLETED = State('Completed', QUEST). F# N; H% X# \& z- ]& U) `
7 O# g% ?) ~+ H' m2 s- QUEST.setInitialState(CREATED)
9 {( a' S) d( d* Y$ ], e - QUEST.addStartNpc(7056)
/ }4 K( G' ? F/ e; f( O - STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код Теперь рассмотрим, как это работает., j0 y+ j, V" I y6 N; r
Игрок подходит к начальному NCP (в данном случае 7056), нажимает на «Quest». Квест будет создан и состояние квеста перейдет к CREATED и игроку будет показана страничка Start.htm с описанием квеста. Тогда метод onEvent, поле открытия странички Start.htm переведет состояние квеста в STARTED и игроку будет показана страничка Started.htm, где будет опсание того, как найти keltirs и .т.д.
O$ i+ L7 e/ }2 M, H3 x8 R0 r" \3 g* L
# }. K& I, G9 _; ~! V5 h
При состоянии STARTED будет зарегистрирован дроп «fangs» при убийстве keltirs. Игрок может вернуться к стартовому NCP и спросить о квесте – метод onEvent будет вызван снова. Если у игрока не хватает необходимого количества предметов, то метод check() не переведет квест в следующее состояние и Started.htm будет показана снова. Но если игрок собрал необходимее количество предметов (в данном случае 4 клыка), то метод check() вызовет метод completed() который переведет квест в новое состояние COMPLETED, заберет все клыки, даст карту мира, т.к. это награда за квест, покажет Completed.htm и завершит квест.
& ~3 z$ `2 c0 R. A
5 ~! U, t. b4 g. k2 \
' u4 k7 w: f7 D/ k' [Теперь давайте сделаем наш квест более похожим на то, что он должен из себя представлять.: ]% x# V9 b/ x
Прежде всего у нас есть 3 метода для объявления их в Яве – onTalk, onKill и onEvent. Если методы onTalk и onKill не объявлены, то за них все будет делать метод onEvent, т.е. определять квестовых монстров и вызывать диалоги NCP. Есть примечание, методы onTalk и onKill будут вызывать только диалоги с NCP в зависимости от текущего состояния квеста. Метод onKill будет вызываться только тогда, когда мы убиваем квестового монстра.& [8 x8 A2 l6 D1 S% T
* ]1 K+ `& w2 Y! ~
& y, X1 |& ]+ A2 s" }: y; aДавайте рассмотрим как вызывается метод onKill при убийстве keltir в состоянии квеста STARTED:
! u2 _9 b* M5 F: L, s- STARTED.addKillId(KELTIR_NPC_ID)
Скопировать код и метод onKill в классе Quest:$ m1 l3 ~* ]2 m: Q' q2 n
% e( W2 O$ E3 @9 d) K$ h! N- class Quest (JQuest):
# t; _" Z8 ~8 ?; q7 r# R7 r- u. q - ...
; Q( o; `4 W8 m* J* p - def onKill (self,npcId,st):0 T( V, K8 R" P4 u8 W0 f' y
- if npcId == KELTIR_NPC_ID:
" [$ t1 C& E9 Y' I) C - n = getCount(st)4 Y3 v6 H$ \, G/ R f
- if n == 0:
7 C" H( G0 O2 X; P. Y: s - return "Chat0.htm"' }* O4 t% n6 v0 i: c1 y
- elif n == 1:# J+ W: W2 t9 }2 ]" [. S; |
- return "Chat1.htm"# q1 K7 g# I$ A6 p
- elif n >= 4:! {2 }( |+ a/ k6 ?
- return "Chat4.htm"
" Y- U3 w" M: H' o8 x) q& z- X - return "Collected "+str(n)+" of 4 fangs"" y7 Q- w8 t2 f& S1 j5 t( _) @
- return
Скопировать код Метод onKill (а так же метод onTalk) имеет следующие параметры:6 Y" ]' M6 }/ _% a* @3 I
# ~( V# S" b x. i, S( |8 t/ Q( Z- u
• self – квест- h+ V% {' W( N
• npcId – ID NCP, которого мы должны убивать (если это метод onTalk, то ID того NCP, с которым мы должны поговорить).
& V/ U" \, r( Y" h• st – текущее состояние игрока.
' y1 D4 o' s. _0 O- }7 u7 M0 {# g4 R% o0 z( ~ m/ I4 O. U" Y; J9 v* S
& T0 Z/ E5 z, ]4 M
В этом методе мы проверяем и отмечаем, является ли убитый NCP keltir’ом. В основном эта проверка не нужна, т.к. у нас только KELTIR_NPC_ID.
! t5 c- x. c9 d6 \7 i
) ]1 g; @# W/ `! i9 h* c8 b/ d2 p9 i
Затем проверяем количество предметов (в данном случае количество клыков), и если их вообще нет, то возвращаем строку "Chat0.htm", если только один предмет, то возвращаем строку "Chat1.htm", если же предметов 4 или больше, то "Chat4.htm". Если строка возвращена из методов onEvent, onKill или onTalk, то сервер покажет соответствующие htm. В Chat0.htm может иметь следующий текст: «Вы не имеете ни одного клыка, возвращайтесь позже, когда соберете 4 штуки и бла, бла, бла…», в Chat1.htm может быть следующий текст: «У Вас всего 1 клык, по этому соберите еще…». В Chat4.htm – «Вы собрали необходимое количество предметов, возвращайтесь к вашему тренеру, что бы завершить квест…»$ K; W0 z* c6 l: j8 Y3 B
2 a- f1 i5 q7 Q# a* w% w3 q1 \3 r; Y8 |5 N5 b7 |/ C; G0 g" E
Примечание: если в строка return начинается с "<html>", то будет показана страничка html с текстом, который стоит далее. Так вместо:7 o5 V0 c, o- k+ _/ f, M
return "Chat4.htm"
6 d3 j8 l, b/ n2 O! n: P: ~" j P+ @4 B: F' l, R' ]* z; e
3 J$ x! G/ z1 ?5 G9 I3 J6 }0 W7 Vможно поставить:7 b- Z1 c( r* F- w
- return "<html><body>Return to your trainer to complete the quest</body></html>"
Скопировать код Так же если строка заканчивается без .htm или в начале нет <html>, то текст будет выведен, как системное сообщение в окне чата. В нашем случае мы сделаем так, что бы при каждом убийстве keltik выводилось системное сообщение: «Собрано N из 4-х клыков».9 _9 f" M( \$ |4 K. Z' \) T
2 W* P& k. u. v5 A
+ E( J" a* K. |) JНаш код для onKill имеет один недостаток. Он будет постоянно показывать Chat0.htm, Chat1.htm и Chat4.htm, нам же необходимо, что бы Chat0.htm и Chat1.htm показывались только один раз. Как нам это сделать? С помощью переменных.
8 O% u! ^8 x# q* i2 i$ [
: s* n6 t3 g' d b- U, y, J6 h% g( v0 C: A P6 P& k
В каждом квесте строки могут храниться с помощью переменных. Эти переменные сохраняются в Вашей БД. В каждом методе мы можем назначить, прочитать и удалить переменные. Давайте изменим метод onKill, так что бы каждый диалог вызывался только один раз.1 M, d* `& |5 n+ ~- w
- def onKill (self,npcId,st):/ a/ y( f! f/ ]1 f
- if npcId == KELTIR_NPC_ID:6 \6 l) j7 @# Q* q+ b
- n = getCount(st)
9 s5 p4 `& o0 H- w) a- P - if n == 0:
+ L* P! z$ ^! _9 C8 W - if st.get('chat0') == None :& Z. H0 n$ j' i9 n; }) Y
- st.set("chat0", "true")
2 ?! m4 b' E' S* T: o0 S - return "Chat0.htm"6 g) \( r6 U' R, A \
- elif n == 1:) ?6 ]' e Q% b# ]: \
- if st.get('chat1') == None :' g9 V9 u( W3 K* O- F
- st.set("chat1", "true")4 v% d E5 r/ S+ m/ I8 l6 ~' f
- return "Chat1.htm"3 E6 Q8 L& a+ t% H2 K1 ^5 T
- elif n >= 4:
! i' C/ B, |3 ~& p5 ~. G. z - return "Chat4.htm"
: F5 [! g8 R/ q - return "Collected "+str(n)+" of 4 fangs"( c( J7 q7 v1 n( j: ?* m; s
- 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 ]% V" u8 T( k( l5 k
# n7 B7 @3 p- n* {4 j" n6 L
; o. v+ O* W2 a( b+ p+ R- fВот конечный рабочий вариант квеста:* G0 D# y) G7 A8 s
- import sys
) T: F0 ^" Z# |# ~" y3 E9 y9 w. i - from net.sf.l2j.gameserver.model.quest import State* @' c* V, B3 {8 A' p |/ g
- from net.sf.l2j.gameserver.model.quest import QuestState
# O0 E. g0 g! h% | - from net.sf.l2j.gameserver.model.quest.jython import QuestJython as JQuest) m1 v& T8 G5 }
: j, [& o5 J/ k: h% t4 Z- KELTIR_NPC_ID = 12082( X- w# c+ m/ j0 t. N" l
- FANGS_ITEM_ID = 1859
6 s% H+ s6 ?9 M! C6 N# w) ?( W - DROP_RATE = 5000006 a6 V9 J7 L! t4 W8 A
# |5 j* P- D8 S R- WORLD_MAP_ITEM_ID = 16652 r$ \3 o' v: @. o; J2 G3 w5 M0 I
( V5 j5 x. P/ E$ R& E- def getCount(st) :: Y1 V0 ]# a0 F; s" r+ g
- return st.getQuestItemsCount(FANGS_ITEM_ID)3 @; g i3 a* i+ c: k; i
- - b/ H3 r; o# u& G: m& `! ]
- def completed(st) :/ U! g- b+ a7 g+ G1 N
- st.setState(COMPLETED)% y/ h/ E* t& n+ U' H
- st.clearQuestDrops()
! k9 i% s* h; [$ i4 I7 @9 ] - st.takeItems(FANGS_ITEM_ID,-1) i0 F7 ]$ _3 V$ L
- st.giveItems(WORLD_MAP_ITEM_ID,1)
# h1 i" c- j6 @. f - st.exitQuest(False)( n. S( P6 y" [6 `# U! o6 b( M
- return/ @7 M9 A3 X+ @# H& D3 F2 z
5 T% H. ?, v0 K# K0 c- a1 `- def check(st) :0 x; y% g1 l: `. \
- if getCount(st) >= 4 :
# L9 J7 w6 x' X - completed(st): ?+ q6 J/ N2 x1 O5 ]& ~+ t
- return0 e4 B8 m; C# u* A5 D) u4 F; \
- : G8 z) ^+ }9 Z* Q( `& z
- class Quest (JQuest):" m. i A. ^% s7 N
- q, Z2 |0 w" q. k" |! M6 h
- def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)4 F, z9 b1 p/ n! B- ?0 d& k' v# R$ _3 j
- # I* j) |9 w7 h
- def onEvent (self,event,st):
* s$ U, a( L* z r" I/ W - id = st.getState()5 b) X: c8 f/ f6 @. E
- if id == CREATED : st.setState(STARTED)9 Q7 ~! `* [9 P3 Z
- elif id == COMPLETED: pass; a, d3 R7 M( Z5 t4 B3 l4 |6 _
- elif id == STARTED : check(st)
0 F W( u! T- c n9 b1 j) M; I - return9 z' B" P' f7 R, b. c l) ]( g8 e# l
: A" K4 E% g$ y0 z9 f [8 |- def onKill (self,npcId,st):# \8 r t+ e; ?$ v# M: x: }
- if npcId == KELTIR_NPC_ID:
! ^& u$ p8 T! J7 U - n = getCount(st)
& W6 N4 ^ I2 B! J- B7 v - if n == 0:" B" m* M. @! N. M
- if st.get('chat0') == None :; Q- }1 A: y) L0 G7 t
- st.set("chat0", "true"), e7 ?( |1 m1 X. |7 r* a
- return "Chat0.htm"
$ h, ~6 C/ z2 {0 B - elif n == 1:4 R7 p; o. o/ O7 W
- if st.get('chat1') == None :( p, g" g0 f- g
- st.set("chat1", "true"); x: ]) N! Z8 g$ I( [4 x: r
- return "Chat1.htm"
9 e( k7 m( g/ I6 b- n5 E - elif n >= 4:8 W0 H; m) y. g+ ^( j3 h9 J5 P
- return "Chat4.htm"
% W% t$ t# g! v - return "Collect "+str(n)+" of 4 fangs"( e1 `4 W& r9 W" j5 K- u- H
- return
9 }9 O- K m z, w7 x' D - 7 H/ F: E* T0 T
- QUEST = Quest(201, "Tutorial", "Tutorial quest")& m' e4 T' W( s% t
- CREATED = State('Start', QUEST)/ D9 d+ k! j1 W) @: V# D
- STARTED = State('Started', QUEST)
* W0 [% `9 E Y; M' P - COMPLETED = State('Completed', QUEST)
# s7 @% K( z& W/ Q4 W4 F! U
0 r) a) w% ~/ R7 d8 Z/ U- B4 @6 S& C- QUEST.setInitialState(CREATED)
" [) l! Q' k% o# ~4 G - QUEST.addStartNpc(7056)
4 r0 l7 z5 `' o* m4 S: e2 ?7 W - QUEST.addStartNpc(7012)
' Z2 s% H1 w" H/ p - QUEST.addStartNpc(7009)
* V+ O& y; l5 y' k: j - QUEST.addStartNpc(7011)8 M4 }8 N% F& Z! N! n
% o6 b' d; w9 }9 `4 [/ v. O N- STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)1 l, {$ r; [# t$ z
- STARTED.addKillId(KELTIR_NPC_ID)+ l5 ]( T& ~4 e% |2 G
- STARTED.addTalkId(7056)
) \1 V5 X6 f, t: Q5 B$ v4 `' R9 }7 Y - STARTED.addTalkI d(7012)& k6 M; A m3 O8 U U
- STARTED.addTalkId(7009)
u2 \% t' Z+ R ` - STARTED.addTalkId(7011)
Скопировать код 5 G4 x; c& w( `, v8 w, ^: g
9 C0 }1 Q( [3 k/ q3 B
|