Для этого квеста больше ничего не надо. Все необходимое для корректной работы квеста уже добавили. Вот полный текст квеста: 0 t/ k: w# T) B0 X6 E& s6 L* d& R% i: h: C: Z4 T! A/ A
if getCount(st) >= 4 :6 v8 a: s2 ?2 ^% H9 h2 V3 K* p8 D
Теперь рассмотрим, как это работает. 1 J: p# z6 o5 C+ xИгрок подходит к начальному NCP (в данном случае 7056), нажимает на «Quest». Квест будет создан и состояние квеста перейдет к CREATED и игроку будет показана страничка Start.htm с описанием квеста. Тогда метод onEvent, поле открытия странички Start.htm переведет состояние квеста в STARTED и игроку будет показана страничка Started.htm, где будет опсание того, как найти keltirs и .т.д. / G) M4 F+ ~9 ?8 r 2 c8 f0 r' y2 @5 q3 F & E! w$ O1 |, F6 {При состоянии STARTED будет зарегистрирован дроп «fangs» при убийстве keltirs. Игрок может вернуться к стартовому NCP и спросить о квесте – метод onEvent будет вызван снова. Если у игрока не хватает необходимого количества предметов, то метод check() не переведет квест в следующее состояние и Started.htm будет показана снова. Но если игрок собрал необходимее количество предметов (в данном случае 4 клыка), то метод check() вызовет метод completed() который переведет квест в новое состояние COMPLETED, заберет все клыки, даст карту мира, т.к. это награда за квест, покажет Completed.htm и завершит квест. ! q5 ?6 W7 t% p+ @ 2 }8 `& e1 N6 G& `$ \0 I* f# u) R - g1 f4 o3 K z/ {- U6 sТеперь давайте сделаем наш квест более похожим на то, что он должен из себя представлять. ; S; f( y8 d+ C( Q6 I: M6 eПрежде всего у нас есть 3 метода для объявления их в Яве – onTalk, onKill и onEvent. Если методы onTalk и onKill не объявлены, то за них все будет делать метод onEvent, т.е. определять квестовых монстров и вызывать диалоги NCP. Есть примечание, методы onTalk и onKill будут вызывать только диалоги с NCP в зависимости от текущего состояния квеста. Метод onKill будет вызываться только тогда, когда мы убиваем квестового монстра.7 x' H9 j& f% ]3 q- L( ~5 i( g+ h5 I8 v
7 R7 \! m0 d& f- x t
# [! t5 b1 Q; ?1 f, t, {Давайте рассмотрим как вызывается метод onKill при убийстве keltir в состоянии квеста STARTED:% B9 y2 s7 v; L2 V$ y
STARTED.addKillId(KELTIR_NPC_ID)
Скопировать код
и метод onKill в классе Quest:3 d' j# C" Y0 u0 q
: `4 u- E3 ^& O7 o% ~ g
class Quest (JQuest):9 |7 p5 A0 @% b, i3 C3 c
.../ `3 j2 k% L1 T1 {; Y0 U: ?
def onKill (self,npcId,st): , p0 G6 ~% y% d! w
if npcId == KELTIR_NPC_ID: ! \. n U: k. M7 B7 i
n = getCount(st) _3 m+ Y$ Z! [+ ]- e7 c# U: F5 J# u
if n == 0: : R% x2 z$ V% p' e X& |
return "Chat0.htm" ( N: b* N* L u3 I; H5 j0 b) O) A
elif n == 1:. [# b) i' ~9 F% Z- T
return "Chat1.htm" % w. h6 r4 E: w R( }8 z; f
elif n >= 4:. `( ^5 o: K1 t! _3 {0 Z4 t- [
return "Chat4.htm" / \* R8 W( o3 r: G: D$ j
return "Collected "+str(n)+" of 4 fangs"6 V; b, B. i [% W% O6 J S
return
Скопировать код
Метод onKill (а так же метод onTalk) имеет следующие параметры:" t! b) i* [; z. D5 o
2 N% Y) h8 G& e- q3 x
% M$ M) M- ]) ]& l9 x* |" z• self – квест$ {# [/ N3 \. \6 [
• npcId – ID NCP, которого мы должны убивать (если это метод onTalk, то ID того NCP, с которым мы должны поговорить). , B3 o8 B9 q' `$ i1 X& }; `- ?• st – текущее состояние игрока. 3 Q3 r7 X5 P$ X9 U b ! I3 o& B4 P: Y7 `& S) \$ s$ j! ]$ k
В этом методе мы проверяем и отмечаем, является ли убитый NCP keltir’ом. В основном эта проверка не нужна, т.к. у нас только KELTIR_NPC_ID. * ~2 ~6 ~" ^+ B, C8 L7 F- A9 `: t5 h! x' u5 B
+ h1 S" z! w* i4 m7 M
Затем проверяем количество предметов (в данном случае количество клыков), и если их вообще нет, то возвращаем строку "Chat0.htm", если только один предмет, то возвращаем строку "Chat1.htm", если же предметов 4 или больше, то "Chat4.htm". Если строка возвращена из методов onEvent, onKill или onTalk, то сервер покажет соответствующие htm. В Chat0.htm может иметь следующий текст: «Вы не имеете ни одного клыка, возвращайтесь позже, когда соберете 4 штуки и бла, бла, бла…», в Chat1.htm может быть следующий текст: «У Вас всего 1 клык, по этому соберите еще…». В Chat4.htm – «Вы собрали необходимое количество предметов, возвращайтесь к вашему тренеру, что бы завершить квест…» 2 z0 I7 L1 L j2 V4 d5 o l! o : B9 Z, n+ P$ J4 c& o 5 D9 s: P( s! P$ X2 NПримечание: если в строка return начинается с "<html>", то будет показана страничка html с текстом, который стоит далее. Так вместо: 1 F' d3 r# R7 X0 Q( A& w% e; lreturn "Chat4.htm": P: @, B; i3 c. K8 J
3 w, w ?+ s! a( |# B7 g8 e, ]; p$ s* ~6 f2 O2 x
можно поставить: 5 @$ P$ S' f: Q% X
return "<html><body>Return to your trainer to complete the quest</body></html>"
Скопировать код
Так же если строка заканчивается без .htm или в начале нет <html>, то текст будет выведен, как системное сообщение в окне чата. В нашем случае мы сделаем так, что бы при каждом убийстве keltik выводилось системное сообщение: «Собрано N из 4-х клыков».$ ^ f; I+ u0 q9 _+ S
9 ^& m L( v" Y, y; V0 H" p" ?) J0 A# W0 e
Наш код для onKill имеет один недостаток. Он будет постоянно показывать Chat0.htm, Chat1.htm и Chat4.htm, нам же необходимо, что бы Chat0.htm и Chat1.htm показывались только один раз. Как нам это сделать? С помощью переменных.! W7 N& m5 ~" I& @
& P8 P+ V4 h, T2 p. ?
2 _4 {2 }, d$ F
В каждом квесте строки могут храниться с помощью переменных. Эти переменные сохраняются в Вашей БД. В каждом методе мы можем назначить, прочитать и удалить переменные. Давайте изменим метод onKill, так что бы каждый диалог вызывался только один раз.* D+ {2 \5 J8 D" t3 q, I
def onKill (self,npcId,st):. \* E8 K" @$ O5 P I- o
if npcId == KELTIR_NPC_ID:# L% Y9 P. H& y3 o5 x/ m) j
n = getCount(st)5 `* o: X& h; D& S
if n == 0: ; Y( E3 g+ s q& z/ h* V( v) ]
if st.get('chat0') == None :" O; ]( D. J7 q9 z8 o2 K. k) ?
return "Collected "+str(n)+" of 4 fangs"* N: @) v8 W% A0 I+ v# ^4 G* p H
return
Скопировать код
Если у игрока нет клыков (n=0), то мы получаем занчение переменной 'chat0'. Когда метод onKill вызван в первый раз, то пока ни каких переменных не имеется и python возвращает значение None. В этом случае объявляется переменная и показывается диалог Chat0.htm. Когда мы убиваем keltir, но не получаем с него клык, функция st.get('chat0') возвращает строку true, а не None. И во второй раз окно с Chat0.htm не появится, но в окне чата появится строчка «Collected 0 of 4 fangs». По тому же принципу сделано и с Chat1.htm. 6 k7 F, \9 j- J8 q' b: t# J " Y# n k! O1 L; Q+ M ' d& ?3 r$ c1 E! s4 N& O$ dВот конечный рабочий вариант квеста: . r( B1 R* ]' o/ [
import sys 4 V2 O+ p/ I: _$ ~3 q
from net.sf.l2j.gameserver.model.quest import State * ~6 H9 t/ t& l3 H; T5 R& r
from net.sf.l2j.gameserver.model.quest import QuestState9 N- E5 C& M b& L
from net.sf.l2j.gameserver.model.quest.jython import QuestJython as JQuest( b8 N5 P# L; K2 [: C
* n5 U/ |9 `2 d
KELTIR_NPC_ID = 12082 , W3 p% {: _+ f v* `$ G+ E
FANGS_ITEM_ID = 1859 * c" O! f" H6 D$ e* a7 M, [
DROP_RATE = 500000$ L1 g) U% r5 K4 }% d' {
. J5 m! E7 l4 Q
WORLD_MAP_ITEM_ID = 1665! R% ?' \) s0 {& m( D# G
& O- z4 {0 g! K' \/ v. w" c1 F% u
def getCount(st) : - w- d$ Q: A" }% a& z5 e- M. x% h
return st.getQuestItemsCount(FANGS_ITEM_ID) # L. r* l* T" g& ?+ H