Теперь рассмотрим, как это работает.. v# {+ G0 Q* d" `
Игрок подходит к начальному NCP (в данном случае 7056), нажимает на «Quest». Квест будет создан и состояние квеста перейдет к CREATED и игроку будет показана страничка Start.htm с описанием квеста. Тогда метод onEvent, поле открытия странички Start.htm переведет состояние квеста в STARTED и игроку будет показана страничка Started.htm, где будет опсание того, как найти keltirs и .т.д. * G$ I- h+ }2 o) R; q9 y/ r' k 5 ]/ f0 P" I W2 r: v$ _ 9 [6 B' C' w5 ~+ S4 xПри состоянии STARTED будет зарегистрирован дроп «fangs» при убийстве keltirs. Игрок может вернуться к стартовому NCP и спросить о квесте – метод onEvent будет вызван снова. Если у игрока не хватает необходимого количества предметов, то метод check() не переведет квест в следующее состояние и Started.htm будет показана снова. Но если игрок собрал необходимее количество предметов (в данном случае 4 клыка), то метод check() вызовет метод completed() который переведет квест в новое состояние COMPLETED, заберет все клыки, даст карту мира, т.к. это награда за квест, покажет Completed.htm и завершит квест.6 {5 \4 q( U7 b
4 ^5 W v! [) G) \+ ^* s 7 g9 |+ z% H, fТеперь давайте сделаем наш квест более похожим на то, что он должен из себя представлять.8 |' W6 e) Q& M8 a1 P( W
Прежде всего у нас есть 3 метода для объявления их в Яве – onTalk, onKill и onEvent. Если методы onTalk и onKill не объявлены, то за них все будет делать метод onEvent, т.е. определять квестовых монстров и вызывать диалоги NCP. Есть примечание, методы onTalk и onKill будут вызывать только диалоги с NCP в зависимости от текущего состояния квеста. Метод onKill будет вызываться только тогда, когда мы убиваем квестового монстра. # {) }1 n2 D4 x6 B: G$ h# B6 M# h- m3 M5 J8 e. O
; \4 c2 e8 [3 t
Давайте рассмотрим как вызывается метод onKill при убийстве keltir в состоянии квеста STARTED: , ?* Q7 a$ w( @+ X# u* w1 j& s
STARTED.addKillId(KELTIR_NPC_ID)
Скопировать код
и метод onKill в классе Quest:' A$ M f7 U. g V$ h& H) W" m
: X# |4 C0 K# o9 G, d3 U* V8 T
return "Collected "+str(n)+" of 4 fangs" " B u1 {) c' |, d) ?
return
Скопировать код
Метод onKill (а так же метод onTalk) имеет следующие параметры:4 @+ {6 O L0 {$ l) F K) g
1 D6 M y3 v3 W$ U3 O- x w! t/ o/ f' G6 w& H" t) O
• self – квест % ^8 @0 h9 g; f6 Z& J• npcId – ID NCP, которого мы должны убивать (если это метод onTalk, то ID того NCP, с которым мы должны поговорить)./ @# K7 {) k+ u3 }4 S2 u
• st – текущее состояние игрока.1 D/ W4 J( p' `6 [
9 ]" W! G4 f: n5 V. G
- z2 ^6 Z. e& I2 ^В этом методе мы проверяем и отмечаем, является ли убитый NCP keltir’ом. В основном эта проверка не нужна, т.к. у нас только KELTIR_NPC_ID. * ~' k: ]) S% K3 \1 H, w/ f 3 Z K# l3 a& |3 ?% X1 N8 B$ K , x+ L/ h+ T" S1 v. VЗатем проверяем количество предметов (в данном случае количество клыков), и если их вообще нет, то возвращаем строку "Chat0.htm", если только один предмет, то возвращаем строку "Chat1.htm", если же предметов 4 или больше, то "Chat4.htm". Если строка возвращена из методов onEvent, onKill или onTalk, то сервер покажет соответствующие htm. В Chat0.htm может иметь следующий текст: «Вы не имеете ни одного клыка, возвращайтесь позже, когда соберете 4 штуки и бла, бла, бла…», в Chat1.htm может быть следующий текст: «У Вас всего 1 клык, по этому соберите еще…». В Chat4.htm – «Вы собрали необходимое количество предметов, возвращайтесь к вашему тренеру, что бы завершить квест…»' e* Y& \9 ^ I5 u, p1 W1 R
: Q" j3 R7 j1 S' ?0 K4 j: ^3 z1 O7 x$ R4 J
Примечание: если в строка return начинается с "<html>", то будет показана страничка html с текстом, который стоит далее. Так вместо:+ w. Y9 |- r$ ?5 |
return "Chat4.htm"% j3 i5 q8 O) |7 `2 a- E; |( y2 b: ~
3 g! D9 \. B4 e% ^
return "<html><body>Return to your trainer to complete the quest</body></html>"
Скопировать код
Так же если строка заканчивается без .htm или в начале нет <html>, то текст будет выведен, как системное сообщение в окне чата. В нашем случае мы сделаем так, что бы при каждом убийстве keltik выводилось системное сообщение: «Собрано N из 4-х клыков». 3 c1 j( h' @2 e4 c2 z6 k* t u$ @1 E& i1 d/ G. A* K# W9 \6 L0 p+ l
Наш код для onKill имеет один недостаток. Он будет постоянно показывать Chat0.htm, Chat1.htm и Chat4.htm, нам же необходимо, что бы Chat0.htm и Chat1.htm показывались только один раз. Как нам это сделать? С помощью переменных.& F7 R& J5 ?8 u9 w$ {
7 V. K$ V) U+ r$ n( ~, t! }
2 c$ l( Y) i! R& Z
В каждом квесте строки могут храниться с помощью переменных. Эти переменные сохраняются в Вашей БД. В каждом методе мы можем назначить, прочитать и удалить переменные. Давайте изменим метод onKill, так что бы каждый диалог вызывался только один раз. 0 X/ }- T/ L H w5 w+ [$ W6 T
if st.get('chat0') == None : + l$ B6 {' @3 e; x- F1 P
st.set("chat0", "true")/ V) Q8 D. @8 ]8 S7 M
return "Chat0.htm"9 L) a8 C0 a9 [9 Z! y
elif n == 1: # h- ^" {5 h% i
if st.get('chat1') == None :/ K9 C& D$ M" {4 ]& |1 L& G. w) J0 |3 N
st.set("chat1", "true")6 ~% b) P c" j+ o" _& S' X; h* o" C
return "Chat1.htm") Z* T& u* J- g" B G
elif n >= 4:* K6 m" f: X7 w* h8 m7 ~4 r
return "Chat4.htm" 0 D0 c f# G+ x" \% @
return "Collected "+str(n)+" of 4 fangs"" P' q, N: v$ L" ?0 z/ V
return
Скопировать код
Если у игрока нет клыков (n=0), то мы получаем занчение переменной 'chat0'. Когда метод onKill вызван в первый раз, то пока ни каких переменных не имеется и python возвращает значение None. В этом случае объявляется переменная и показывается диалог Chat0.htm. Когда мы убиваем keltir, но не получаем с него клык, функция st.get('chat0') возвращает строку true, а не None. И во второй раз окно с Chat0.htm не появится, но в окне чата появится строчка «Collected 0 of 4 fangs». По тому же принципу сделано и с Chat1.htm.) K6 B) R# g }' k
' T6 B a. d) ?6 T+ P+ r7 \
( G( ]2 z l; v F3 _Вот конечный рабочий вариант квеста: & _5 g% N4 Z' E: [/ h/ I
import sys 1 X& e) N) l4 H: R$ r6 n
from net.sf.l2j.gameserver.model.quest import State $ y9 H" `# g. X1 Y' ], C3 D& y
from net.sf.l2j.gameserver.model.quest import QuestState% B8 s7 |6 y$ v0 z: P
from net.sf.l2j.gameserver.model.quest.jython import QuestJython as JQuest 7 I, H. h2 @% E+ {; @
: F/ r4 l! C, C: S8 c+ V
KELTIR_NPC_ID = 12082' i5 j3 R9 h W) Y0 w1 k& x5 s
FANGS_ITEM_ID = 1859" X) o+ I7 n8 [* {; A
DROP_RATE = 500000 ' Z( |5 U, L5 L* b% c0 s4 v9 t
$ ^5 o+ S/ \2 {# L3 ~ V
WORLD_MAP_ITEM_ID = 1665 2 d6 A L& z, v) ]- j" y# V