Теперь рассмотрим, как это работает. : \+ m, Q9 q$ a1 b" ^Игрок подходит к начальному NCP (в данном случае 7056), нажимает на «Quest». Квест будет создан и состояние квеста перейдет к CREATED и игроку будет показана страничка Start.htm с описанием квеста. Тогда метод onEvent, поле открытия странички Start.htm переведет состояние квеста в STARTED и игроку будет показана страничка Started.htm, где будет опсание того, как найти keltirs и .т.д.- Q- \9 ] d9 A$ p! }! Q) ?
1 i3 ]- I+ m& \' b5 X
2 M- g. d% Q7 I7 B6 t+ D6 g- ^1 x
При состоянии STARTED будет зарегистрирован дроп «fangs» при убийстве keltirs. Игрок может вернуться к стартовому NCP и спросить о квесте – метод onEvent будет вызван снова. Если у игрока не хватает необходимого количества предметов, то метод check() не переведет квест в следующее состояние и Started.htm будет показана снова. Но если игрок собрал необходимее количество предметов (в данном случае 4 клыка), то метод check() вызовет метод completed() который переведет квест в новое состояние COMPLETED, заберет все клыки, даст карту мира, т.к. это награда за квест, покажет Completed.htm и завершит квест.; O3 f( l* \: Q% V
( A6 ^4 R$ q) E6 u& [
' q' q/ O. J# V$ V
Теперь давайте сделаем наш квест более похожим на то, что он должен из себя представлять.; S' L* i- B) R2 X) G% z9 V. @
Прежде всего у нас есть 3 метода для объявления их в Яве – onTalk, onKill и onEvent. Если методы onTalk и onKill не объявлены, то за них все будет делать метод onEvent, т.е. определять квестовых монстров и вызывать диалоги NCP. Есть примечание, методы onTalk и onKill будут вызывать только диалоги с NCP в зависимости от текущего состояния квеста. Метод onKill будет вызываться только тогда, когда мы убиваем квестового монстра.* D5 M( @' A' ], t9 M
' ?/ s$ d3 A% r3 G/ @
7 ], _4 `. v+ k) S9 x- N# sДавайте рассмотрим как вызывается метод onKill при убийстве keltir в состоянии квеста STARTED:5 b1 i$ j4 u1 k2 g$ x
STARTED.addKillId(KELTIR_NPC_ID)
Скопировать код
и метод onKill в классе Quest:+ p% z; W% H( k& g( p: A
3 F1 k4 |% i7 A5 Y
class Quest (JQuest):1 G, c2 Y4 s+ n& c3 [4 V- k
...+ t# S! z. I5 m) f) G8 _+ v+ Z
def onKill (self,npcId,st):' m+ C% q+ y( N H* q. {. n
if npcId == KELTIR_NPC_ID: + r& b# Y1 N1 p) b9 ?3 u
n = getCount(st): N* p& l# t) d& w$ T+ L
if n == 0: W# c3 L6 e _/ H) c" u
return "Chat0.htm": Q& L+ ]+ q6 P! }
elif n == 1: 6 [6 ~+ Z. A- [
return "Chat1.htm" * I1 ^- V) h0 g
elif n >= 4:& x C) q1 R6 Q) f
return "Chat4.htm", c: \& V1 v7 Y; U4 c- l3 l
return "Collected "+str(n)+" of 4 fangs" 8 C$ g {* O! q3 E7 U
return
Скопировать код
Метод onKill (а так же метод onTalk) имеет следующие параметры:9 F& e3 H; g* [8 A
1 n( u! p8 Q& k3 `- o6 G: Y& I8 v7 n& I4 ^1 }
• self – квест 5 O. [: I2 x" m( h- _4 U• npcId – ID NCP, которого мы должны убивать (если это метод onTalk, то ID того NCP, с которым мы должны поговорить).5 y/ j$ F7 O( Y# P W4 |/ C
• st – текущее состояние игрока. , o3 \9 _1 h9 C |9 ^0 n% F k, V' d0 P1 [
3 [: h; s! E4 y1 J- h% c
В этом методе мы проверяем и отмечаем, является ли убитый NCP keltir’ом. В основном эта проверка не нужна, т.к. у нас только KELTIR_NPC_ID. - Q! ?. ^. l9 R& i- p+ H) [. o2 n
) {/ y+ `9 D! D2 K6 m" Q8 SЗатем проверяем количество предметов (в данном случае количество клыков), и если их вообще нет, то возвращаем строку "Chat0.htm", если только один предмет, то возвращаем строку "Chat1.htm", если же предметов 4 или больше, то "Chat4.htm". Если строка возвращена из методов onEvent, onKill или onTalk, то сервер покажет соответствующие htm. В Chat0.htm может иметь следующий текст: «Вы не имеете ни одного клыка, возвращайтесь позже, когда соберете 4 штуки и бла, бла, бла…», в Chat1.htm может быть следующий текст: «У Вас всего 1 клык, по этому соберите еще…». В Chat4.htm – «Вы собрали необходимое количество предметов, возвращайтесь к вашему тренеру, что бы завершить квест…» 0 h+ g, L1 @1 _5 @, A7 p& `- I; ]+ _1 j
: v% X8 @1 H3 a$ Y+ b1 p8 bПримечание: если в строка return начинается с "<html>", то будет показана страничка html с текстом, который стоит далее. Так вместо: : M/ p: l0 r6 O: E# w/ ^return "Chat4.htm" ( k* B* Q) V' K# @$ A1 d4 e$ I, N 9 {$ ~& ^, h% M! z* X+ D# j * Q8 W! V4 I2 Y7 @8 nможно поставить: ( L: O: U* C1 K7 k9 ]
return "<html><body>Return to your trainer to complete the quest</body></html>"
Скопировать код
Так же если строка заканчивается без .htm или в начале нет <html>, то текст будет выведен, как системное сообщение в окне чата. В нашем случае мы сделаем так, что бы при каждом убийстве keltik выводилось системное сообщение: «Собрано N из 4-х клыков»., H; @% y* V+ p" U
1 T, Z M8 w! d1 t9 I4 h
, f0 X' V& o. N7 d# M( p: `1 aНаш код для onKill имеет один недостаток. Он будет постоянно показывать Chat0.htm, Chat1.htm и Chat4.htm, нам же необходимо, что бы Chat0.htm и Chat1.htm показывались только один раз. Как нам это сделать? С помощью переменных. 1 ^7 ?$ Q* P* h( ~ ! g, d! d& ]2 s- a0 S$ I+ L3 H( r) n3 ~$ P! B3 a7 V
В каждом квесте строки могут храниться с помощью переменных. Эти переменные сохраняются в Вашей БД. В каждом методе мы можем назначить, прочитать и удалить переменные. Давайте изменим метод onKill, так что бы каждый диалог вызывался только один раз.. z: E3 u/ T' ]1 L; G, b
def onKill (self,npcId,st): ( }: @; h3 n% D" A
if npcId == KELTIR_NPC_ID:* }4 D- s2 y$ K5 F
n = getCount(st)) S1 n. Y" x. m" `( R+ A. J- J
if n == 0: 4 J, z. x; Z2 K3 B9 m3 {+ c
if st.get('chat0') == None : ; _: P: p% M: e6 [
st.set("chat0", "true") + g; G* f. B! l7 g+ X
return "Chat0.htm" 5 Y+ ^* j1 e, @0 f a; ^) ^
elif n == 1:0 |$ g. R0 u" p: c/ q' T, n- z
if st.get('chat1') == None :( y3 S' e% X2 a- x& y8 `4 l0 @" {
st.set("chat1", "true") 3 k1 f! Z7 E _$ I' q
return "Chat1.htm" & ?6 A: |0 L0 F5 e" x/ k
elif n >= 4:- b4 L* ^- L7 x+ J7 B! S
return "Chat4.htm"; ?0 S) E& k# ^
return "Collected "+str(n)+" of 4 fangs" 0 j5 |& u! \8 V4 U7 _. i, K
return
Скопировать код
Если у игрока нет клыков (n=0), то мы получаем занчение переменной 'chat0'. Когда метод onKill вызван в первый раз, то пока ни каких переменных не имеется и python возвращает значение None. В этом случае объявляется переменная и показывается диалог Chat0.htm. Когда мы убиваем keltir, но не получаем с него клык, функция st.get('chat0') возвращает строку true, а не None. И во второй раз окно с Chat0.htm не появится, но в окне чата появится строчка «Collected 0 of 4 fangs». По тому же принципу сделано и с Chat1.htm. % h# a4 L6 X4 ]- E $ U4 [6 ~! d5 I2 z3 u& g( |4 B) ] 4 _# S/ y8 q. D; Q/ |4 E3 R4 ^ s. fВот конечный рабочий вариант квеста: 0 G% \# Q: Q: [5 ^
import sys % e" d4 Q# T" F5 E
from net.sf.l2j.gameserver.model.quest import State 3 g6 S, X9 l0 i$ u* U
from net.sf.l2j.gameserver.model.quest import QuestState' g% e) S9 d& U2 P, K
from net.sf.l2j.gameserver.model.quest.jython import QuestJython as JQuest3 z0 q. r1 U% I& D" c3 V( O