Для этого квеста больше ничего не надо. Все необходимое для корректной работы квеста уже добавили. Вот полный текст квеста: 7 k8 B* E7 y* |" t& ^/ x) L1 I* ]" ?( ?) P7 H( N- T9 D+ B; t
if getCount(st) >= 4 : . o# n; c& ^6 a p! _9 g4 h [
completed(st) 4 R6 U$ }$ U5 _: Z& h0 U, a, u
return + S) i0 G |% p+ x; n' Q
! o% V+ V8 p9 x1 [( x: a5 N
class Quest (JQuest): 1 J) g8 y4 V& V6 g4 d) ]
def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr) u6 H) y2 T6 |7 E \
Теперь рассмотрим, как это работает.8 ?) P+ w. @# i" L R' D* P
Игрок подходит к начальному NCP (в данном случае 7056), нажимает на «Quest». Квест будет создан и состояние квеста перейдет к CREATED и игроку будет показана страничка Start.htm с описанием квеста. Тогда метод onEvent, поле открытия странички Start.htm переведет состояние квеста в STARTED и игроку будет показана страничка Started.htm, где будет опсание того, как найти keltirs и .т.д. & s I( r9 C, y4 J7 w& L. a & Z; e; C, Z) p, U* ^, [ # i; F2 d! D, r5 Y6 x. U& VПри состоянии STARTED будет зарегистрирован дроп «fangs» при убийстве keltirs. Игрок может вернуться к стартовому NCP и спросить о квесте – метод onEvent будет вызван снова. Если у игрока не хватает необходимого количества предметов, то метод check() не переведет квест в следующее состояние и Started.htm будет показана снова. Но если игрок собрал необходимее количество предметов (в данном случае 4 клыка), то метод check() вызовет метод completed() который переведет квест в новое состояние COMPLETED, заберет все клыки, даст карту мира, т.к. это награда за квест, покажет Completed.htm и завершит квест. % L+ P$ G: G p7 G6 }: Y$ B: X 6 _! q i7 W- z6 f) X4 H' f) M % f, m1 p1 Q/ _1 C7 uТеперь давайте сделаем наш квест более похожим на то, что он должен из себя представлять. + r( T& }1 e3 c5 o( |+ ~Прежде всего у нас есть 3 метода для объявления их в Яве – onTalk, onKill и onEvent. Если методы onTalk и onKill не объявлены, то за них все будет делать метод onEvent, т.е. определять квестовых монстров и вызывать диалоги NCP. Есть примечание, методы onTalk и onKill будут вызывать только диалоги с NCP в зависимости от текущего состояния квеста. Метод onKill будет вызываться только тогда, когда мы убиваем квестового монстра.3 H. `' B1 } x- f* n
! K3 D) s# ~8 }; k
; n6 E/ ?; x8 s$ D0 }/ ?Давайте рассмотрим как вызывается метод onKill при убийстве keltir в состоянии квеста STARTED:* w' `( W. c ~. g0 |. r2 I8 l$ O
STARTED.addKillId(KELTIR_NPC_ID)
Скопировать код
и метод onKill в классе Quest:% g. N$ T, q7 C* G: C
+ Y5 O7 w3 ?& Y4 i
class Quest (JQuest): ) ?- v& q! z- H" _" l" s
...3 {3 g0 a$ n: P! Q& e
def onKill (self,npcId,st): & a) b- x$ t2 T/ q; F6 ?3 M
return "Chat4.htm"# }$ j- a) a' E# Y& f. t/ S/ S3 z
return "Collected "+str(n)+" of 4 fangs" / z. G1 ?9 s# C7 A4 U6 o
return
Скопировать код
Метод onKill (а так же метод onTalk) имеет следующие параметры: 5 s' E" B! V7 W# o: q: K/ ~( u+ Q: U- \! k
+ U3 R7 O. P' p• self – квест ! I/ F. J5 L) G9 F5 [/ v• npcId – ID NCP, которого мы должны убивать (если это метод onTalk, то ID того NCP, с которым мы должны поговорить)./ l6 l) w" f J* f9 I1 S' d
• st – текущее состояние игрока. ) s; b" f& _8 i# a0 L! B - W6 A0 v: E! V$ X0 r( E B" ~4 p5 {6 ?# r! L* dВ этом методе мы проверяем и отмечаем, является ли убитый NCP keltir’ом. В основном эта проверка не нужна, т.к. у нас только KELTIR_NPC_ID. / V; q" ?' |, I- k* M2 [9 O9 B5 K) r8 h0 ]+ O2 Z
3 [' B6 Y& _2 z- n9 wЗатем проверяем количество предметов (в данном случае количество клыков), и если их вообще нет, то возвращаем строку "Chat0.htm", если только один предмет, то возвращаем строку "Chat1.htm", если же предметов 4 или больше, то "Chat4.htm". Если строка возвращена из методов onEvent, onKill или onTalk, то сервер покажет соответствующие htm. В Chat0.htm может иметь следующий текст: «Вы не имеете ни одного клыка, возвращайтесь позже, когда соберете 4 штуки и бла, бла, бла…», в Chat1.htm может быть следующий текст: «У Вас всего 1 клык, по этому соберите еще…». В Chat4.htm – «Вы собрали необходимое количество предметов, возвращайтесь к вашему тренеру, что бы завершить квест…»! O% u# p+ Q2 f- F6 Z1 \
0 u0 g/ u: G* m6 A; `! e; N# y' `" ]: _- r+ U1 K# f( d
Примечание: если в строка return начинается с "<html>", то будет показана страничка html с текстом, который стоит далее. Так вместо:3 n; H; s+ }& K
return "Chat4.htm" 3 @" {. x& }* u0 K0 ] 8 s. N n0 F- |" P7 ^* |$ y9 L6 F/ q) }6 M9 Z
можно поставить:8 p6 {0 x' H) j1 W* y& V
return "<html><body>Return to your trainer to complete the quest</body></html>"
Скопировать код
Так же если строка заканчивается без .htm или в начале нет <html>, то текст будет выведен, как системное сообщение в окне чата. В нашем случае мы сделаем так, что бы при каждом убийстве keltik выводилось системное сообщение: «Собрано N из 4-х клыков»." t5 D9 d; `$ B9 ?% O4 ? Q; S) Y
4 \4 F8 O% I c % z. n" T$ _* T* n% _$ aНаш код для onKill имеет один недостаток. Он будет постоянно показывать Chat0.htm, Chat1.htm и Chat4.htm, нам же необходимо, что бы Chat0.htm и Chat1.htm показывались только один раз. Как нам это сделать? С помощью переменных." p" d3 N; {0 g* @
5 ^) q* v) Q9 j
4 C0 Q p9 p# q3 c5 b
В каждом квесте строки могут храниться с помощью переменных. Эти переменные сохраняются в Вашей БД. В каждом методе мы можем назначить, прочитать и удалить переменные. Давайте изменим метод onKill, так что бы каждый диалог вызывался только один раз.: K5 Z1 P) T, o$ y. I
return "Collected "+str(n)+" of 4 fangs" ( N- ]! e4 [% A
return
Скопировать код
Если у игрока нет клыков (n=0), то мы получаем занчение переменной 'chat0'. Когда метод onKill вызван в первый раз, то пока ни каких переменных не имеется и python возвращает значение None. В этом случае объявляется переменная и показывается диалог Chat0.htm. Когда мы убиваем keltir, но не получаем с него клык, функция st.get('chat0') возвращает строку true, а не None. И во второй раз окно с Chat0.htm не появится, но в окне чата появится строчка «Collected 0 of 4 fangs». По тому же принципу сделано и с Chat1.htm.& \9 z$ T8 @2 @$ A$ d8 q
! s0 S4 Q, A7 `
$ m% Q7 W; w3 h* T
Вот конечный рабочий вариант квеста: + W" N K F7 u- E- P
import sys3 L+ s2 t3 _- Y- I1 v
from net.sf.l2j.gameserver.model.quest import State & i+ L' m; A8 a, x' O: E( b) w' n
from net.sf.l2j.gameserver.model.quest import QuestState- k8 y6 V9 Y8 j7 r
from net.sf.l2j.gameserver.model.quest.jython import QuestJython as JQuest ) A& y0 ~/ Z G% V
7 K3 s/ v2 R: F6 C" r- @: Y
KELTIR_NPC_ID = 12082 ! P2 x: I$ P$ v# i
FANGS_ITEM_ID = 1859 : Z+ w( ~7 i. k
DROP_RATE = 500000$ r8 U2 G: l4 a5 v$ ^; _
8 c) W3 I) K0 q
WORLD_MAP_ITEM_ID = 1665 4 H9 v! u$ ]: h
2 H% A7 B% [. v, [7 E* j
def getCount(st) :% {9 V5 E2 [4 a, g& ?+ o5 M2 B
return st.getQuestItemsCount(FANGS_ITEM_ID)# Q3 `. a: q: W) R) ?7 ^0 U, I
5 U4 ?) }' V- `4 \- R
def completed(st) : ' y; {% H1 O- z% ]; H: g
st.setState(COMPLETED)& X( G% A) M& a4 v& j# c' l
st.clearQuestDrops() R ` F4 v* C% T& z: Q
st.takeItems(FANGS_ITEM_ID,-1) # E7 g; c: |; K8 u1 f