Теперь рассмотрим, как это работает.+ k0 l3 q U: ~2 `
Игрок подходит к начальному NCP (в данном случае 7056), нажимает на «Quest». Квест будет создан и состояние квеста перейдет к CREATED и игроку будет показана страничка Start.htm с описанием квеста. Тогда метод onEvent, поле открытия странички Start.htm переведет состояние квеста в STARTED и игроку будет показана страничка Started.htm, где будет опсание того, как найти keltirs и .т.д.; o7 G3 B9 ?; w
0 m8 I/ n8 W9 i- {6 S5 ~/ t+ u$ W, D8 R& P6 b; q0 M4 H
При состоянии STARTED будет зарегистрирован дроп «fangs» при убийстве keltirs. Игрок может вернуться к стартовому NCP и спросить о квесте – метод onEvent будет вызван снова. Если у игрока не хватает необходимого количества предметов, то метод check() не переведет квест в следующее состояние и Started.htm будет показана снова. Но если игрок собрал необходимее количество предметов (в данном случае 4 клыка), то метод check() вызовет метод completed() который переведет квест в новое состояние COMPLETED, заберет все клыки, даст карту мира, т.к. это награда за квест, покажет Completed.htm и завершит квест. 1 U9 o- B. H+ G% X3 y' A/ _9 ^ * m/ P" O. \6 E8 Y( c; G1 f/ R1 _4 W. p$ |' o7 a
Теперь давайте сделаем наш квест более похожим на то, что он должен из себя представлять. , z/ O- m$ k4 p, Y" `* DПрежде всего у нас есть 3 метода для объявления их в Яве – onTalk, onKill и onEvent. Если методы onTalk и onKill не объявлены, то за них все будет делать метод onEvent, т.е. определять квестовых монстров и вызывать диалоги NCP. Есть примечание, методы onTalk и onKill будут вызывать только диалоги с NCP в зависимости от текущего состояния квеста. Метод onKill будет вызываться только тогда, когда мы убиваем квестового монстра./ ~1 w: L X+ w3 _; m# F
, k. U2 D$ V5 q F# v) Y, B9 k
. m: `5 |! s) i% f! @$ Z' U
Давайте рассмотрим как вызывается метод onKill при убийстве keltir в состоянии квеста STARTED:3 U2 E& L7 a! k+ U& {. u
STARTED.addKillId(KELTIR_NPC_ID)
Скопировать код
и метод onKill в классе Quest: * \* D6 {2 N5 M3 N: q0 N1 Y. \8 T4 ?, `
class Quest (JQuest): ; j% T% x6 g7 e5 n$ B$ h5 X8 W4 b( n
... t) A- K% W o) U6 N
def onKill (self,npcId,st): 8 c7 t1 d' X; s8 T. `5 k8 [6 r
if npcId == KELTIR_NPC_ID: ' o/ f3 J" K1 ?7 O( U& o% K
n = getCount(st)4 D! i, G% }$ ^0 U t% X3 h, X# ^
if n == 0:2 D8 u7 q$ A9 n4 L$ y
return "Chat0.htm") e k$ R- U7 d* I. m( C6 |
elif n == 1:# n5 m1 c& n) L7 {
return "Chat1.htm" ! r* {4 |! o' x7 X
elif n >= 4: , X* b! s, ]& Z N. [8 [. p
return "Chat4.htm"- K1 S2 v9 k5 Q8 f" O, B
return "Collected "+str(n)+" of 4 fangs") b' ]4 K2 z7 p
return
Скопировать код
Метод onKill (а так же метод onTalk) имеет следующие параметры:8 p* E Q; G$ y: D! M1 E( l: E
: Y1 @, Z3 r, r1 n
" d; P$ [, g- O& _$ y1 \; r7 I: S( A
• self – квест% p) l1 z7 R: C B
• npcId – ID NCP, которого мы должны убивать (если это метод onTalk, то ID того NCP, с которым мы должны поговорить)." I# d; \) v! T4 W$ `9 H# O
• st – текущее состояние игрока.+ r2 C% B% ` N/ h4 ^8 g
- K3 M: }/ ~5 W4 B# B5 b, L7 |; `) o5 D: z: l
В этом методе мы проверяем и отмечаем, является ли убитый NCP keltir’ом. В основном эта проверка не нужна, т.к. у нас только KELTIR_NPC_ID. 5 Z; U6 b" Q% D# H# H [) a2 \7 j4 Y $ U' M. ^8 j: N: e6 P0 K @% g# x. Z; K0 b
Затем проверяем количество предметов (в данном случае количество клыков), и если их вообще нет, то возвращаем строку "Chat0.htm", если только один предмет, то возвращаем строку "Chat1.htm", если же предметов 4 или больше, то "Chat4.htm". Если строка возвращена из методов onEvent, onKill или onTalk, то сервер покажет соответствующие htm. В Chat0.htm может иметь следующий текст: «Вы не имеете ни одного клыка, возвращайтесь позже, когда соберете 4 штуки и бла, бла, бла…», в Chat1.htm может быть следующий текст: «У Вас всего 1 клык, по этому соберите еще…». В Chat4.htm – «Вы собрали необходимое количество предметов, возвращайтесь к вашему тренеру, что бы завершить квест…»! y8 m5 ?& \3 B8 H
3 K2 p2 c3 p# l, a8 Z3 h
: D L! }2 P" i* Y! ~
Примечание: если в строка return начинается с "<html>", то будет показана страничка html с текстом, который стоит далее. Так вместо: % E2 U" G/ j1 l$ ~( R1 l. Z: H' z, Mreturn "Chat4.htm"# ^8 i4 {9 c: f& I( ~+ c
return "<html><body>Return to your trainer to complete the quest</body></html>"
Скопировать код
Так же если строка заканчивается без .htm или в начале нет <html>, то текст будет выведен, как системное сообщение в окне чата. В нашем случае мы сделаем так, что бы при каждом убийстве keltik выводилось системное сообщение: «Собрано N из 4-х клыков»." u( z q' [/ g$ X- Q: W# n* s
D: n( S4 ~7 a
% _/ a& I% C7 B7 w7 z: x" g
Наш код для onKill имеет один недостаток. Он будет постоянно показывать Chat0.htm, Chat1.htm и Chat4.htm, нам же необходимо, что бы Chat0.htm и Chat1.htm показывались только один раз. Как нам это сделать? С помощью переменных. - z! i& Y, _5 r; v7 }0 T) O; v1 V* V# {5 A) e
$ U/ V$ M' g) u/ S v3 H' r% v
В каждом квесте строки могут храниться с помощью переменных. Эти переменные сохраняются в Вашей БД. В каждом методе мы можем назначить, прочитать и удалить переменные. Давайте изменим метод onKill, так что бы каждый диалог вызывался только один раз.7 x e" u, k; W. C7 b
def onKill (self,npcId,st):5 q. {/ F# m8 m8 J, V* U, l
if npcId == KELTIR_NPC_ID:& L8 C' }+ O; h! T* z m$ K9 J' i
n = getCount(st) 7 q) G+ k X3 T" q5 i* Q; m
if n == 0:' S8 S" d. c" f# \* [* D; y
if st.get('chat0') == None : 4 R8 Z3 Q, ^. M4 }5 I
st.set("chat0", "true") & s- S" b% R2 O! E
return "Chat0.htm") a& I! {4 _/ L
elif n == 1:- f) U% E8 F; f2 ]$ B
if st.get('chat1') == None :, Q0 m4 I' x6 u( T# Q a A; M
Если у игрока нет клыков (n=0), то мы получаем занчение переменной 'chat0'. Когда метод onKill вызван в первый раз, то пока ни каких переменных не имеется и python возвращает значение None. В этом случае объявляется переменная и показывается диалог Chat0.htm. Когда мы убиваем keltir, но не получаем с него клык, функция st.get('chat0') возвращает строку true, а не None. И во второй раз окно с Chat0.htm не появится, но в окне чата появится строчка «Collected 0 of 4 fangs». По тому же принципу сделано и с Chat1.htm. . {8 C: g- k" J- q/ ?" I q% ?# P$ }+ s9 F
; c4 t+ `* X" ]7 b4 C- x
Вот конечный рабочий вариант квеста:7 g$ u: e1 F. z7 r* S# O; L0 {
import sys1 I- p$ ^8 `) n1 \3 X
from net.sf.l2j.gameserver.model.quest import State, |$ R! s2 e# f7 J/ i3 N6 W
from net.sf.l2j.gameserver.model.quest import QuestState9 ^: D! l' n0 s4 r% ?
from net.sf.l2j.gameserver.model.quest.jython import QuestJython as JQuest! k, x0 ^( v- D1 v- Z% I6 L