Зарегистрируйтесь сейчас чтобы найти еще больше друзей, и получить полноценный доступ ко всем функциям сайта!
Для просмотра Вам необходимо авторизоваться Если Вы еще не зарегистрированы, перейдите по ссылке:Зарегистрироваться
x
Хроники Interlude& N/ E0 x9 h4 W7 j& g* `
Сборка L2j
* X# S! Q$ t- M l# @Обратите внимание: в файле htm стартового NCP обязательно должна быть ссылка на квест:0 M& S4 a- g% a' q0 V' | ^7 H2 L# Y
- STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код Для этого квеста больше ничего не надо. Все необходимое для корректной работы квеста уже добавили. Вот полный текст квеста:: f( o* t; w" g y8 Z
7 M% C8 Y* _: @5 }7 y6 Y* m3 H/ Y. n
- if getCount(st) >= 4 :" r. W* E5 P J" y$ X7 e/ y
- completed(st)
: O5 f8 M: v5 N V, f6 Q5 u& U1 Z! R% ~. z - return
8 J$ h2 I9 P3 Z7 A - - C) [* m! x+ W/ Z: u% A: |
- class Quest (JQuest):1 h3 k3 o/ V' Y% a$ } u
- def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)! A: @: l2 j( [0 c( C5 e
- def onEvent (self,event,st):; _+ r. p/ Z- u" G% I6 O/ P& f2 a4 B
- id = st.getState()8 O. t0 R* H- x
- if id == CREATED : st.setState(STARTED)
$ ~1 N2 E1 F5 H* s" J, K6 E2 L! _1 n' n - elif id == COMPLETED: pass. O3 T+ A4 V# n+ J% S. t
- elif id == STARTED : check(st)1 _1 v6 m$ l. q
- return4 N, i+ [0 U( u8 ^6 R8 i6 {
- % s, m3 g# {# N; q" `# X
- QUEST = Quest(201,"Tutorial", "Tutorial quest")
! d5 y) F( }# z- N5 i8 a - CREATED = State('Start', QUEST)
" y; h9 @0 J1 }2 X6 _5 t - STARTED = State('Started', QUEST)- A( A' Q( D: r- @
- COMPLETED = State('Completed', QUEST)8 A) M, z2 V& R$ R- J: _
- 9 E9 X1 z' u* `: k( K' M: ?" F
- QUEST.setInitialState(CREATED)
- Z9 Y$ G& B% a+ O2 v - QUEST.addStartNpc(7056)
/ y2 [& J5 R! r$ N. k - STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код Теперь рассмотрим, как это работает.# ~3 A/ j3 c. R' M
Игрок подходит к начальному NCP (в данном случае 7056), нажимает на «Quest». Квест будет создан и состояние квеста перейдет к CREATED и игроку будет показана страничка Start.htm с описанием квеста. Тогда метод onEvent, поле открытия странички Start.htm переведет состояние квеста в STARTED и игроку будет показана страничка Started.htm, где будет опсание того, как найти keltirs и .т.д.% M, C- ?9 V, a W
) S+ g% x* R; N/ B, [ K
3 ^/ X) V/ v- \: s7 x' m! z
При состоянии STARTED будет зарегистрирован дроп «fangs» при убийстве keltirs. Игрок может вернуться к стартовому NCP и спросить о квесте – метод onEvent будет вызван снова. Если у игрока не хватает необходимого количества предметов, то метод check() не переведет квест в следующее состояние и Started.htm будет показана снова. Но если игрок собрал необходимее количество предметов (в данном случае 4 клыка), то метод check() вызовет метод completed() который переведет квест в новое состояние COMPLETED, заберет все клыки, даст карту мира, т.к. это награда за квест, покажет Completed.htm и завершит квест.+ p( n, [ e7 x1 N! w7 K
5 F) L5 w3 E4 _1 `7 y
5 I0 e" H4 P3 I u. Q% d7 U' WТеперь давайте сделаем наш квест более похожим на то, что он должен из себя представлять.
' C. L: x% r5 B+ V' ^4 XПрежде всего у нас есть 3 метода для объявления их в Яве – onTalk, onKill и onEvent. Если методы onTalk и onKill не объявлены, то за них все будет делать метод onEvent, т.е. определять квестовых монстров и вызывать диалоги NCP. Есть примечание, методы onTalk и onKill будут вызывать только диалоги с NCP в зависимости от текущего состояния квеста. Метод onKill будет вызываться только тогда, когда мы убиваем квестового монстра.
2 n( P) q% u; I# R4 o0 u
& `3 z; |0 N$ j! {$ e+ M2 ]
: W" P3 S: r0 \5 FДавайте рассмотрим как вызывается метод onKill при убийстве keltir в состоянии квеста STARTED:
8 h1 R. _$ ], D+ I q- STARTED.addKillId(KELTIR_NPC_ID)
Скопировать код и метод onKill в классе Quest:
" a" R; w5 [8 N0 @* ?+ ^2 L6 Y6 y. `+ u
- class Quest (JQuest):
2 |% \. `7 L- g/ N2 F9 N2 y - ...
; b9 \. T; ~. f( I9 }0 h7 W - def onKill (self,npcId,st):
* @6 X+ j8 a9 \7 N2 O% z - if npcId == KELTIR_NPC_ID:
! M$ ^# o: Q* e3 g, H7 r - n = getCount(st)
$ t B$ i( U0 A$ o: u - if n == 0:
( ]/ p" c0 |& M! W) O - return "Chat0.htm"0 b i0 Q, B5 X5 {& w
- elif n == 1:8 ]% m4 A8 Y, n( h5 ]: z4 H5 t
- return "Chat1.htm"6 R" }# V) x( H0 y; K1 r( T
- elif n >= 4:
; C% E( }. u1 l6 Y0 t7 V* \9 ]/ l7 T - return "Chat4.htm"
- `$ V/ T* m" Z - return "Collected "+str(n)+" of 4 fangs"1 }, X8 ` b; t4 j. E/ f
- return
Скопировать код Метод onKill (а так же метод onTalk) имеет следующие параметры:
" |( U" a* e/ _( d/ @
" f7 J, u& v5 N/ b
9 D; }! W& W' F2 m• self – квест2 G* i" j) ^2 C
• npcId – ID NCP, которого мы должны убивать (если это метод onTalk, то ID того NCP, с которым мы должны поговорить).; c6 l; E) @* |: u3 T4 J
• st – текущее состояние игрока.
% y& Q; f3 [, |
/ `. f [* f7 {% U0 K3 j% R8 k! s3 A
В этом методе мы проверяем и отмечаем, является ли убитый NCP keltir’ом. В основном эта проверка не нужна, т.к. у нас только KELTIR_NPC_ID.$ B7 T$ z. R+ t, M7 [. F3 t
y4 U$ P3 e5 `# u
6 U7 F T% Z" c: S7 q; wЗатем проверяем количество предметов (в данном случае количество клыков), и если их вообще нет, то возвращаем строку "Chat0.htm", если только один предмет, то возвращаем строку "Chat1.htm", если же предметов 4 или больше, то "Chat4.htm". Если строка возвращена из методов onEvent, onKill или onTalk, то сервер покажет соответствующие htm. В Chat0.htm может иметь следующий текст: «Вы не имеете ни одного клыка, возвращайтесь позже, когда соберете 4 штуки и бла, бла, бла…», в Chat1.htm может быть следующий текст: «У Вас всего 1 клык, по этому соберите еще…». В Chat4.htm – «Вы собрали необходимое количество предметов, возвращайтесь к вашему тренеру, что бы завершить квест…»
7 N; k* F+ K4 |
' a; T7 {1 ^7 K8 m. p$ T7 \2 \& K$ l0 g1 N$ t
Примечание: если в строка return начинается с "<html>", то будет показана страничка html с текстом, который стоит далее. Так вместо:0 ^ B7 X% K( B3 t9 M% E
return "Chat4.htm"7 W. R( p. }- [& m4 ^2 R% q7 e0 E
) U0 J; u% ~3 S6 F7 e$ C5 F
8 t. ^- f2 ^0 C: I, p1 rможно поставить:# N9 C( G& T2 o
- return "<html><body>Return to your trainer to complete the quest</body></html>"
Скопировать код Так же если строка заканчивается без .htm или в начале нет <html>, то текст будет выведен, как системное сообщение в окне чата. В нашем случае мы сделаем так, что бы при каждом убийстве keltik выводилось системное сообщение: «Собрано N из 4-х клыков».
, h1 T2 Y( s- ^: W6 O4 K, j* z& q( Z0 L8 Z3 y
! \' L6 q( m$ g+ L+ SНаш код для onKill имеет один недостаток. Он будет постоянно показывать Chat0.htm, Chat1.htm и Chat4.htm, нам же необходимо, что бы Chat0.htm и Chat1.htm показывались только один раз. Как нам это сделать? С помощью переменных.
& h$ Y. c# M% w+ v" Z$ E. R t) ]7 I/ @" S" Z" o
( l+ L2 T( l0 w
В каждом квесте строки могут храниться с помощью переменных. Эти переменные сохраняются в Вашей БД. В каждом методе мы можем назначить, прочитать и удалить переменные. Давайте изменим метод onKill, так что бы каждый диалог вызывался только один раз.7 s2 d' {( [% V/ s
- def onKill (self,npcId,st):
, ^% w, q6 a. }! q - if npcId == KELTIR_NPC_ID:
6 R9 j D0 L# X' M- Z1 d - n = getCount(st)$ z; F: U# s, f% o* N' c
- if n == 0:0 p% [: K5 y4 D( p
- if st.get('chat0') == None :& m1 `# \4 X+ ?; s) K/ {! ?/ K3 y: q
- st.set("chat0", "true")% T/ c1 T( B$ c( m/ D
- return "Chat0.htm"
* I( l! I+ A$ ?, |8 y - elif n == 1:
. j; U8 {# j3 S" f0 @; l - if st.get('chat1') == None :4 K% C% r) E( ^: {4 t
- st.set("chat1", "true")
7 F& A, Q+ h" f8 s2 d- \ - return "Chat1.htm"
5 b8 b# b+ J$ [1 T6 ^) e5 e - elif n >= 4:
% X2 X, u, ?* f9 I& t/ H* u$ J - return "Chat4.htm"; z5 K2 Y% W! E
- return "Collected "+str(n)+" of 4 fangs"; N* m1 e2 N1 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.
: N: }1 o# B. ?' E+ A: l L8 X
" M7 {& D A1 l9 M2 ^- J" K& H$ F1 b% h9 S* ] l5 N+ R
Вот конечный рабочий вариант квеста:" A( c A8 I( I0 r/ w. s" A
- import sys
6 @( {4 y7 q# {$ G - from net.sf.l2j.gameserver.model.quest import State3 R4 M: _. @3 c# X! }9 K; j9 @
- from net.sf.l2j.gameserver.model.quest import QuestState" H$ |: |3 d# a5 \2 G* N9 a9 e
- from net.sf.l2j.gameserver.model.quest.jython import QuestJython as JQuest4 R# z0 k6 ~+ b
- ; P. I* E% X4 {, C
- KELTIR_NPC_ID = 12082
+ v- g1 M3 V& z% z4 s7 Y5 V - FANGS_ITEM_ID = 18594 W# q: C4 X" t! T' X
- DROP_RATE = 500000
. ]$ @; {9 d% z
6 k; H7 {! m; }% i# o- WORLD_MAP_ITEM_ID = 16653 ]) S1 N8 S! }: j8 R# N) }
0 l" A4 d; H4 j/ l- def getCount(st) :( F& `) G" _ Z
- return st.getQuestItemsCount(FANGS_ITEM_ID)
- r {- N3 ]# J! j - - w% {! C1 H* |! \2 H. I
- def completed(st) :3 I; R9 X! i, }4 q$ p" e6 v
- st.setState(COMPLETED)
( i0 w& ]8 A( ?' Q0 t3 q) L - st.clearQuestDrops()- i" @' T# r( J, Q
- st.takeItems(FANGS_ITEM_ID,-1)
- i3 C/ C% s; B- K5 f& N! A - st.giveItems(WORLD_MAP_ITEM_ID,1), E5 z& m8 k: f- s
- st.exitQuest(False)
- S" g) B1 ~7 S8 s1 ^* ~ - return
& c& g+ z/ z; e) f1 d2 G& @5 u
. _( T/ q% V4 k& L0 q) g) d3 p2 U- def check(st) :
0 `9 Z5 {2 p4 w* v7 G# p - if getCount(st) >= 4 :
5 w z4 s1 T# g) W" i - completed(st)6 G6 R6 v' v" t* j1 h- W/ Z* N
- return
! o1 Z6 z) }* m9 m) u3 ~ - . k6 @7 j. @( E* P
- class Quest (JQuest):
' D& ?! U7 P4 M - . z- G) i% q) n; c. e1 n
- def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)) [0 _& T0 c8 t) ]+ H/ k
$ \3 N* p% X# z7 a, e, o, r# P$ P' y- def onEvent (self,event,st):6 B) J2 Q! r' Y! P
- id = st.getState()
5 P6 d7 I3 T2 b( x; Q* m - if id == CREATED : st.setState(STARTED)
% W9 ]& b: n( }$ g% j4 g! } - elif id == COMPLETED: pass
( g& ~( J+ Z; G1 a1 C - elif id == STARTED : check(st)
. w" e- g5 @0 t0 Y! {* T1 | - return
) U6 ~, v6 O. o, |, \
& F7 F, d7 W4 A9 M4 e5 h$ w- def onKill (self,npcId,st):
+ N# i- @- g J/ O5 c, k0 S! K - if npcId == KELTIR_NPC_ID:
, K! a- p0 C/ L* b- c# T% l# W - n = getCount(st)
9 ]. c* [! B$ x* V - if n == 0:+ M' W' K8 q, G1 ?8 h
- if st.get('chat0') == None :
! W5 }3 | ^3 |) A" h - st.set("chat0", "true"). L, o2 S/ i- s- u# ]
- return "Chat0.htm"
% k8 \9 ?" Q: ~ - elif n == 1:5 m4 M4 C8 Y7 `6 v
- if st.get('chat1') == None :
o. y6 I- T/ z# E - st.set("chat1", "true")
5 L+ E- |, X" I8 ? - return "Chat1.htm"
& x; g1 g( o: p9 u- Q) |! Y. u - elif n >= 4:
" P; w9 H% X! { - return "Chat4.htm"+ K% o# o! ?+ Z: z
- return "Collect "+str(n)+" of 4 fangs"
# F6 _6 _2 e. I+ M - return7 d2 P1 j: C# n. L8 N
8 H) y5 U7 q! M- QUEST = Quest(201, "Tutorial", "Tutorial quest")" a$ K, d+ n0 D& c$ ]! V' F1 r& Q& D
- CREATED = State('Start', QUEST)
9 q. H; V# h( k+ g5 J' f - STARTED = State('Started', QUEST)
4 F* T6 b- M; O H! @6 F- j3 b: W - COMPLETED = State('Completed', QUEST)
; e, g) h' k( H2 N6 Z; x3 E# k4 ?& K7 {
& m5 p1 D; ~* ?8 e' E- QUEST.setInitialState(CREATED)
5 J9 b9 r' I; I, ^* a I - QUEST.addStartNpc(7056)
# a: ?6 R1 O# X* \* k3 S% ?3 |8 d - QUEST.addStartNpc(7012)# C8 ?! g) Y; R% b) @
- QUEST.addStartNpc(7009)
- p: Y3 V; w/ V+ X4 x- u' f { - QUEST.addStartNpc(7011)2 l/ l1 P/ B; T5 r8 }5 u
O& L p( f, y( P9 c1 v9 ]- STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
# Z8 ~% s. C0 w' i( I1 w# |) \ - STARTED.addKillId(KELTIR_NPC_ID)* Y6 n6 y3 }, }2 A
- STARTED.addTalkId(7056)! q8 v( o& J0 B/ y' Q. s9 r
- STARTED.addTalkI d(7012)7 L+ g/ A# P. g2 D; }* U# v
- STARTED.addTalkId(7009)
4 {6 M; P3 j2 ^+ X- [ - STARTED.addTalkId(7011)
Скопировать код
9 I' \2 t/ S3 h
( A3 _( G r- P5 f |