Для этого квеста больше ничего не надо. Все необходимое для корректной работы квеста уже добавили. Вот полный текст квеста: 2 ?7 b1 n( A- [ 2 ?6 q" p( R* C5 f% t" W/ t
if getCount(st) >= 4 : $ d5 C+ g7 r! [* ~) b8 a
completed(st) 4 a- I: c5 j( j; n$ K0 n4 N
return 9 f( L. \- k1 ^) I+ I
8 x+ I/ \# t+ q' j$ n0 {4 X9 b3 ]
class Quest (JQuest):9 ]) J2 d T# N$ J+ O) z: C
def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr) }; Y+ g3 T+ a( W. p y+ r7 F1 l
Теперь рассмотрим, как это работает./ q; m% f3 s0 L0 k( W
Игрок подходит к начальному NCP (в данном случае 7056), нажимает на «Quest». Квест будет создан и состояние квеста перейдет к CREATED и игроку будет показана страничка Start.htm с описанием квеста. Тогда метод onEvent, поле открытия странички Start.htm переведет состояние квеста в STARTED и игроку будет показана страничка Started.htm, где будет опсание того, как найти keltirs и .т.д. 8 x" T% m a* q& l ! S, s/ ? J- \: r" y! M# z1 @% ^3 [' ?' Q8 Y
При состоянии STARTED будет зарегистрирован дроп «fangs» при убийстве keltirs. Игрок может вернуться к стартовому NCP и спросить о квесте – метод onEvent будет вызван снова. Если у игрока не хватает необходимого количества предметов, то метод check() не переведет квест в следующее состояние и Started.htm будет показана снова. Но если игрок собрал необходимее количество предметов (в данном случае 4 клыка), то метод check() вызовет метод completed() который переведет квест в новое состояние COMPLETED, заберет все клыки, даст карту мира, т.к. это награда за квест, покажет Completed.htm и завершит квест. * f1 b* n4 d/ N: S7 Z# g 3 \' O" \8 U; Q3 G7 B3 } 2 a: b' [6 ?" O# RТеперь давайте сделаем наш квест более похожим на то, что он должен из себя представлять. 0 a x( C! {. p, PПрежде всего у нас есть 3 метода для объявления их в Яве – onTalk, onKill и onEvent. Если методы onTalk и onKill не объявлены, то за них все будет делать метод onEvent, т.е. определять квестовых монстров и вызывать диалоги NCP. Есть примечание, методы onTalk и onKill будут вызывать только диалоги с NCP в зависимости от текущего состояния квеста. Метод onKill будет вызываться только тогда, когда мы убиваем квестового монстра. + u; U l- o: T* U i$ d) f" D# N8 L
8 O. |+ ?( i3 a! ]$ D u$ [2 \3 B6 qДавайте рассмотрим как вызывается метод onKill при убийстве keltir в состоянии квеста STARTED: 9 I6 \% Z& s/ Q$ f. l. F
STARTED.addKillId(KELTIR_NPC_ID)
Скопировать код
и метод onKill в классе Quest:# x% k' |5 s, w) D$ i
, J" g; b1 B7 p( _5 o4 @" j+ G
class Quest (JQuest):2 l! k, D* i4 m" a4 E$ B1 \
... ) B# h) f$ }- a/ v( \
def onKill (self,npcId,st): ) m3 |' L+ M$ e l* I3 y9 W
if npcId == KELTIR_NPC_ID: ' [. g6 H2 ]# g4 Y9 u" [6 d
n = getCount(st) 3 ^) {) J6 b9 ]3 j% L$ c
if n == 0:4 K; n- B8 r8 z
return "Chat0.htm"- m7 [3 v Z3 \0 T i0 n
elif n == 1:9 y5 L$ M! L7 z" I/ b5 _* D
return "Chat1.htm"1 d. U8 F" `0 j6 ~0 K
elif n >= 4: 9 `* ]0 ]/ c& l2 X9 y
return "Chat4.htm" & O( g- Z. x& i7 M9 R
return "Collected "+str(n)+" of 4 fangs" 7 d4 l9 c9 x5 q, |2 t- L
return
Скопировать код
Метод onKill (а так же метод onTalk) имеет следующие параметры:: P% K$ p# R8 s. l% @& R
4 ]$ I" x4 E' E; x* E1 p! |. b
3 d/ L: `, s) W# N5 A( E
• self – квест6 z' |& k; H6 n7 _2 K
• npcId – ID NCP, которого мы должны убивать (если это метод onTalk, то ID того NCP, с которым мы должны поговорить). : j6 G1 M' Y- A z( q$ L& J• st – текущее состояние игрока.: B$ t5 a+ B) O7 y
" Z% j: k+ A) e/ n" |, R/ {; j) g: U- J( d/ d
В этом методе мы проверяем и отмечаем, является ли убитый NCP keltir’ом. В основном эта проверка не нужна, т.к. у нас только KELTIR_NPC_ID. ( p( X+ D6 f- v+ i& z0 K & K) w0 U: H; T! _) R7 [, ]1 k* a9 `8 J. Q0 p
Затем проверяем количество предметов (в данном случае количество клыков), и если их вообще нет, то возвращаем строку "Chat0.htm", если только один предмет, то возвращаем строку "Chat1.htm", если же предметов 4 или больше, то "Chat4.htm". Если строка возвращена из методов onEvent, onKill или onTalk, то сервер покажет соответствующие htm. В Chat0.htm может иметь следующий текст: «Вы не имеете ни одного клыка, возвращайтесь позже, когда соберете 4 штуки и бла, бла, бла…», в Chat1.htm может быть следующий текст: «У Вас всего 1 клык, по этому соберите еще…». В Chat4.htm – «Вы собрали необходимое количество предметов, возвращайтесь к вашему тренеру, что бы завершить квест…» ' T; x4 e$ h6 l3 g# [- l" ~& p! ]& Q( z2 A& ?/ f0 G. V
9 [% u0 u/ J5 [Примечание: если в строка return начинается с "<html>", то будет показана страничка html с текстом, который стоит далее. Так вместо:$ n Y. e- h0 L: D8 u- ?9 o6 v
return "Chat4.htm"5 @' Q4 I7 Y* X) k& H0 U/ q
# M3 f! S }* d$ V( u- H( \+ ^4 ?7 ~6 {3 q" C( O
можно поставить: 5 E% T& l# W0 Z8 P. F8 B+ }9 b; c* x
return "<html><body>Return to your trainer to complete the quest</body></html>"
Скопировать код
Так же если строка заканчивается без .htm или в начале нет <html>, то текст будет выведен, как системное сообщение в окне чата. В нашем случае мы сделаем так, что бы при каждом убийстве keltik выводилось системное сообщение: «Собрано N из 4-х клыков». $ o. [! t% p2 K9 J5 v. n7 v 8 D- N4 L6 E3 h, X: `! Z& ` ' p& D% ^; H0 Y0 u! h* s8 zНаш код для onKill имеет один недостаток. Он будет постоянно показывать Chat0.htm, Chat1.htm и Chat4.htm, нам же необходимо, что бы Chat0.htm и Chat1.htm показывались только один раз. Как нам это сделать? С помощью переменных.! _; t4 X% c- r7 q* n) p
' _* b: w" _8 C' \
: q# b. O* m5 T$ V
В каждом квесте строки могут храниться с помощью переменных. Эти переменные сохраняются в Вашей БД. В каждом методе мы можем назначить, прочитать и удалить переменные. Давайте изменим метод onKill, так что бы каждый диалог вызывался только один раз. ; z3 k1 U4 r4 Y. Y
def onKill (self,npcId,st): ; o' c* s2 F7 @1 I/ f
if npcId == KELTIR_NPC_ID: 0 ?4 o1 a v0 B5 u
n = getCount(st) ' d6 M' {- ]* k$ i- F
if n == 0:* {- h* ?( b5 @) e! D( i6 ]+ d
if st.get('chat0') == None : $ }: ~" \& G# O; q, Q" B+ P
st.set("chat0", "true") , S, i+ j4 R4 k& s$ M
return "Chat0.htm" 1 F) S6 m" r) S6 w; Y
elif n == 1:0 l' f3 c ~- z# x! q; s) J% m! q' g0 N
if st.get('chat1') == None :7 H( x9 i& ~. c9 e
st.set("chat1", "true")4 A# i1 S8 N3 a6 j3 A7 I
return "Chat1.htm"% {8 `+ F+ u* i @. a( j
elif n >= 4:8 X! M/ M- S/ l, E2 o
return "Chat4.htm" " Q6 b/ G& I5 {% L A
return "Collected "+str(n)+" of 4 fangs"& w" A; h* h. A( ~6 k1 j
return
Скопировать код
Если у игрока нет клыков (n=0), то мы получаем занчение переменной 'chat0'. Когда метод onKill вызван в первый раз, то пока ни каких переменных не имеется и python возвращает значение None. В этом случае объявляется переменная и показывается диалог Chat0.htm. Когда мы убиваем keltir, но не получаем с него клык, функция st.get('chat0') возвращает строку true, а не None. И во второй раз окно с Chat0.htm не появится, но в окне чата появится строчка «Collected 0 of 4 fangs». По тому же принципу сделано и с Chat1.htm. 3 p- N% y. U% y- [; T, x! k1 I( R% t4 m( z# D) P
( m% U7 A' [, I- ]4 i# m
Вот конечный рабочий вариант квеста:2 [! k0 e: v/ E# m& _5 V
import sys7 A8 w# ^% ]/ K
from net.sf.l2j.gameserver.model.quest import State $ c& }$ T, X7 U+ S6 N, ?8 |7 r7 g x
from net.sf.l2j.gameserver.model.quest import QuestState & l2 H7 ~) c2 G2 f! R9 b* d
from net.sf.l2j.gameserver.model.quest.jython import QuestJython as JQuest ! U) }' A9 G) D- t5 r$ L
, O( z! v1 u$ j
KELTIR_NPC_ID = 12082+ S. n* i( a0 M. c, v
FANGS_ITEM_ID = 1859 5 e, R# w L) V0 p2 k
DROP_RATE = 500000 . u g6 Z, V' d% y' K
7 z: n" ^* S* l9 y* J/ y, t$ u
WORLD_MAP_ITEM_ID = 1665 a9 p. U6 l; ]* q S5 M8 P; ^, m
" ?( W% B/ F! J9 [+ A! r1 T) I3 M
def getCount(st) : 1 d2 ?* y$ P7 i- b
return st.getQuestItemsCount(FANGS_ITEM_ID)4 V }1 ?* {& M9 ~! g