Для этого квеста больше ничего не надо. Все необходимое для корректной работы квеста уже добавили. Вот полный текст квеста: " H) B- Y1 p' G/ H& M q! e1 i% J2 Q- a/ ^* S
if getCount(st) >= 4 : " b7 @* W8 ], n/ ?9 o! B+ b
completed(st)- {9 V3 o, A4 o: Q/ ~& O
return % Y! K- O' J3 n. P! I, \3 x3 ~3 G6 M
# J7 P8 C" q6 q/ S* r
class Quest (JQuest): 5 o/ I8 C4 O, Q! \6 E4 u' f' P e
Теперь рассмотрим, как это работает.( v' y) e: ]/ {- k
Игрок подходит к начальному NCP (в данном случае 7056), нажимает на «Quest». Квест будет создан и состояние квеста перейдет к CREATED и игроку будет показана страничка Start.htm с описанием квеста. Тогда метод onEvent, поле открытия странички Start.htm переведет состояние квеста в STARTED и игроку будет показана страничка Started.htm, где будет опсание того, как найти keltirs и .т.д. ( R, s% M0 H; [3 Q8 a: s2 p 4 M5 ~! b5 I/ `, T4 x- k' v P; E0 q0 q b$ d% s
При состоянии STARTED будет зарегистрирован дроп «fangs» при убийстве keltirs. Игрок может вернуться к стартовому NCP и спросить о квесте – метод onEvent будет вызван снова. Если у игрока не хватает необходимого количества предметов, то метод check() не переведет квест в следующее состояние и Started.htm будет показана снова. Но если игрок собрал необходимее количество предметов (в данном случае 4 клыка), то метод check() вызовет метод completed() который переведет квест в новое состояние COMPLETED, заберет все клыки, даст карту мира, т.к. это награда за квест, покажет Completed.htm и завершит квест.: d# d: `6 Q9 o5 ?
, D& k! M# w7 m- e2 ~
& B. H+ E# a4 c D6 I1 xТеперь давайте сделаем наш квест более похожим на то, что он должен из себя представлять. / r6 W: b' ?3 v$ |3 m- UПрежде всего у нас есть 3 метода для объявления их в Яве – onTalk, onKill и onEvent. Если методы onTalk и onKill не объявлены, то за них все будет делать метод onEvent, т.е. определять квестовых монстров и вызывать диалоги NCP. Есть примечание, методы onTalk и onKill будут вызывать только диалоги с NCP в зависимости от текущего состояния квеста. Метод onKill будет вызываться только тогда, когда мы убиваем квестового монстра. ( U# B* I, R! f; Z& C- \ $ W2 b4 W, ^" V3 e; E) h 0 E5 R7 |3 s' Z# K8 FДавайте рассмотрим как вызывается метод onKill при убийстве keltir в состоянии квеста STARTED:1 ~4 U) }" R3 O6 B( o
STARTED.addKillId(KELTIR_NPC_ID)
Скопировать код
и метод onKill в классе Quest: 9 ~* U& Z( M9 ?/ Z' m4 f, c3 M- {3 c8 f" |# u' Q
class Quest (JQuest): ) o& ^. I( ~) f# s
...9 b0 I# ^! d6 R3 ]- }* U5 O5 F
def onKill (self,npcId,st):7 G; V9 F7 S9 j5 Y
if npcId == KELTIR_NPC_ID: 4 z1 F( _7 J% E: e' \1 T
n = getCount(st)5 B7 l3 d, H1 P4 s; N/ N
if n == 0:7 X8 }7 I8 j, _2 B
return "Chat0.htm"$ X8 O- H1 ~5 n: Q" |5 T+ Z
elif n == 1:5 X1 `4 V8 u( Q. I
return "Chat1.htm". Y {6 K- F- ~1 z( r! {8 Y: V
elif n >= 4:( ~0 {( n i, h# V
return "Chat4.htm" 0 m l# N2 ]3 q, e, d) b2 N& o7 Z
return "Collected "+str(n)+" of 4 fangs"1 k: I0 Z$ g6 S4 D
return
Скопировать код
Метод onKill (а так же метод onTalk) имеет следующие параметры: - i0 @) r; @3 {# m; | O& @1 Y) p$ S% K
/ d5 D% ]# |" w6 N) s: J
• self – квест# W, R+ T8 Z' g# a- r! n* T6 N1 S
• npcId – ID NCP, которого мы должны убивать (если это метод onTalk, то ID того NCP, с которым мы должны поговорить). # d: r% _, z5 R2 }2 U; E p' v• st – текущее состояние игрока.3 ~6 V0 M4 j$ h) m; F* S
/ P. X$ l) f2 H" C+ q6 r8 y
& @$ W: H( p/ O6 e4 Y
В этом методе мы проверяем и отмечаем, является ли убитый NCP keltir’ом. В основном эта проверка не нужна, т.к. у нас только KELTIR_NPC_ID. ; F. s- Q7 A' w7 Y3 M- m ) p( I, B) S7 Z 3 d; U( f/ _2 j. g3 _Затем проверяем количество предметов (в данном случае количество клыков), и если их вообще нет, то возвращаем строку "Chat0.htm", если только один предмет, то возвращаем строку "Chat1.htm", если же предметов 4 или больше, то "Chat4.htm". Если строка возвращена из методов onEvent, onKill или onTalk, то сервер покажет соответствующие htm. В Chat0.htm может иметь следующий текст: «Вы не имеете ни одного клыка, возвращайтесь позже, когда соберете 4 штуки и бла, бла, бла…», в Chat1.htm может быть следующий текст: «У Вас всего 1 клык, по этому соберите еще…». В Chat4.htm – «Вы собрали необходимое количество предметов, возвращайтесь к вашему тренеру, что бы завершить квест…»& j; G9 X+ k' g2 a3 K2 y/ c
B" c. @) a y9 g, W- M& K5 Q' U. }7 h4 ^! ^
Примечание: если в строка return начинается с "<html>", то будет показана страничка html с текстом, который стоит далее. Так вместо: 3 |2 ~9 B( m$ U0 E) ireturn "Chat4.htm" 2 h# {& Q1 D4 n! @2 v: `# U. q( J+ p
' n; n; s- o& t
можно поставить: & S7 p4 q# y( q, M
return "<html><body>Return to your trainer to complete the quest</body></html>"
Скопировать код
Так же если строка заканчивается без .htm или в начале нет <html>, то текст будет выведен, как системное сообщение в окне чата. В нашем случае мы сделаем так, что бы при каждом убийстве keltik выводилось системное сообщение: «Собрано N из 4-х клыков». 2 |9 e( b) I3 z( Z6 { 1 T/ D" d$ P( A" T( C 6 A7 z, m7 M T$ ]4 bНаш код для onKill имеет один недостаток. Он будет постоянно показывать Chat0.htm, Chat1.htm и Chat4.htm, нам же необходимо, что бы Chat0.htm и Chat1.htm показывались только один раз. Как нам это сделать? С помощью переменных.; `$ o: S% v# F" _" V" t& p
4 o* h4 `% v# u. g8 }( g/ j5 q2 p, O
) F& N& Q/ X: CВ каждом квесте строки могут храниться с помощью переменных. Эти переменные сохраняются в Вашей БД. В каждом методе мы можем назначить, прочитать и удалить переменные. Давайте изменим метод onKill, так что бы каждый диалог вызывался только один раз. " Y1 F% P2 I: \
def onKill (self,npcId,st): & P8 ^4 S; a: V. f; K& W
return "Collected "+str(n)+" of 4 fangs" ; N6 Q) ~! p5 Y: Q4 E
return
Скопировать код
Если у игрока нет клыков (n=0), то мы получаем занчение переменной 'chat0'. Когда метод onKill вызван в первый раз, то пока ни каких переменных не имеется и python возвращает значение None. В этом случае объявляется переменная и показывается диалог Chat0.htm. Когда мы убиваем keltir, но не получаем с него клык, функция st.get('chat0') возвращает строку true, а не None. И во второй раз окно с Chat0.htm не появится, но в окне чата появится строчка «Collected 0 of 4 fangs». По тому же принципу сделано и с Chat1.htm. - J" d) t1 g- R! ?7 o! F( {! P7 z9 z1 j* v
( m) d( w4 T2 }* I0 B- V
Вот конечный рабочий вариант квеста: & h. L8 P. L1 U' Y( u
import sys. v! c6 b7 W6 M0 q; K. Q
from net.sf.l2j.gameserver.model.quest import State - V) q4 M1 \8 h) @
from net.sf.l2j.gameserver.model.quest import QuestState% s% m3 w* s! X
from net.sf.l2j.gameserver.model.quest.jython import QuestJython as JQuest 6 ^7 q' W" b5 r' s" s3 A
0 d5 F: @' F& S) x2 D
KELTIR_NPC_ID = 12082 / W( l. t) |: d% ]
FANGS_ITEM_ID = 1859' A5 E h. g5 D& i' \2 V' t
DROP_RATE = 500000 + ~( _; C0 Q0 w2 b: L* k
4 l3 d$ q" D: a! a/ b( f) F7 d* x) N3 `" {
WORLD_MAP_ITEM_ID = 1665) ]! { P1 D' T- {( U" P4 G( j, I
6 X: l9 j: j: }7 E; K" c$ p- o1 ~, V
def getCount(st) : 7 h2 l2 E$ A/ o& E4 g' n$ q
return st.getQuestItemsCount(FANGS_ITEM_ID)9 f s" x* d5 ~$ O9 @/ Z* b( ^, h
$ ~* |/ O+ s4 V$ A7 t
def completed(st) : E" k; g1 G$ k) O q H( D
st.setState(COMPLETED)3 O P7 L3 y5 |6 K3 G5 w
st.clearQuestDrops()# s5 F7 v* f% x0 G) r
st.takeItems(FANGS_ITEM_ID,-1)2 y6 u( d! C) Z, a
st.giveItems(WORLD_MAP_ITEM_ID,1) & f. q8 O* w# m3 U9 }% O3 c