Название: Создаём собственные квесты (часть 2) [Версия для печати] Автор: admin Время: 2024-9-17 19:36 Название: Создаём собственные квесты (часть 2) Хроники Interlude - e7 H5 o0 F. _Сборка L2j! p5 {5 E9 Z6 n' H6 P6 n! R, s& z Обратите внимание: в файле htm стартового NCP обязательно должна быть ссылка на квест: \$ Y s4 t% n# ?
Теперь рассмотрим, как это работает. & j7 j6 w* T9 Q X3 P0 zИгрок подходит к начальному NCP (в данном случае 7056), нажимает на «Quest». Квест будет создан и состояние квеста перейдет к CREATED и игроку будет показана страничка Start.htm с описанием квеста. Тогда метод onEvent, поле открытия странички Start.htm переведет состояние квеста в STARTED и игроку будет показана страничка Started.htm, где будет опсание того, как найти keltirs и .т.д.( p; V! |" q7 E9 }) {7 N
7 C! J. E2 E8 j- Y+ ]+ T2 {* r/ W' x: `, V
При состоянии STARTED будет зарегистрирован дроп «fangs» при убийстве keltirs. Игрок может вернуться к стартовому NCP и спросить о квесте – метод onEvent будет вызван снова. Если у игрока не хватает необходимого количества предметов, то метод check() не переведет квест в следующее состояние и Started.htm будет показана снова. Но если игрок собрал необходимее количество предметов (в данном случае 4 клыка), то метод check() вызовет метод completed() который переведет квест в новое состояние COMPLETED, заберет все клыки, даст карту мира, т.к. это награда за квест, покажет Completed.htm и завершит квест.1 t1 x. s3 \4 x" P2 Q6 }) G' ^1 \2 V
|3 d% A; F' [8 R" ~% G4 @3 n: O, I8 R$ G% E
Теперь давайте сделаем наш квест более похожим на то, что он должен из себя представлять. 8 D: U' e2 d- tПрежде всего у нас есть 3 метода для объявления их в Яве – onTalk, onKill и onEvent. Если методы onTalk и onKill не объявлены, то за них все будет делать метод onEvent, т.е. определять квестовых монстров и вызывать диалоги NCP. Есть примечание, методы onTalk и onKill будут вызывать только диалоги с NCP в зависимости от текущего состояния квеста. Метод onKill будет вызываться только тогда, когда мы убиваем квестового монстра.( l& o8 `1 z5 R! S; k' H
. o' F9 J' _5 o! b . @: S3 P6 }4 WДавайте рассмотрим как вызывается метод onKill при убийстве keltir в состоянии квеста STARTED:0 a+ v1 z0 V6 t& ^ b) Z1 X
STARTED.addKillId(KELTIR_NPC_ID)
Скопировать код
и метод onKill в классе Quest: . S! J0 L( k: d% k: S/ [; X1 k( o' `/ D4 ~0 w' _% i
class Quest (JQuest): ' ?4 v! a) I; Q. ]
... . `- [2 W! [9 g, m
def onKill (self,npcId,st): 1 H; s. c5 p2 r* K
if npcId == KELTIR_NPC_ID:* V6 W5 M) Z0 e
n = getCount(st) % ], {+ G, Q: `
if n == 0:7 j1 x5 D- H/ A" s
return "Chat0.htm"# Z8 T' i( ^2 f ~8 B
elif n == 1:! J/ b' m8 d0 |3 f" \. h
return "Chat1.htm" ' r& V0 `! m; d& w' w
elif n >= 4: ' C; @8 G8 V# l/ |) r% E% }. X
return "Chat4.htm"5 o% A! @. ^4 K/ t3 K9 t m
return "Collected "+str(n)+" of 4 fangs"2 l: Y7 \4 a2 [9 y- Z
return
Скопировать код
Метод onKill (а так же метод onTalk) имеет следующие параметры: 4 A. y9 D& t9 h+ x9 e : E" D7 j2 L* W% Y( K2 e. J+ X0 Q d* H
• self – квест 3 Q u. o# O8 i2 W- k• npcId – ID NCP, которого мы должны убивать (если это метод onTalk, то ID того NCP, с которым мы должны поговорить). 7 b3 o! Q' d4 P• st – текущее состояние игрока.0 R* B' b) o5 J. Z6 w- W
: ]- B2 D8 r$ p Q d E5 D$ h' l4 ^2 W
% G o* ~* u9 a. g; e5 H8 M. p
В этом методе мы проверяем и отмечаем, является ли убитый NCP keltir’ом. В основном эта проверка не нужна, т.к. у нас только KELTIR_NPC_ID.0 T+ M4 ]2 W/ _5 s
! {& A9 Q: p' Q/ F% ]7 J8 W9 E
5 _% }% ? {2 a$ n! MЗатем проверяем количество предметов (в данном случае количество клыков), и если их вообще нет, то возвращаем строку "Chat0.htm", если только один предмет, то возвращаем строку "Chat1.htm", если же предметов 4 или больше, то "Chat4.htm". Если строка возвращена из методов onEvent, onKill или onTalk, то сервер покажет соответствующие htm. В Chat0.htm может иметь следующий текст: «Вы не имеете ни одного клыка, возвращайтесь позже, когда соберете 4 штуки и бла, бла, бла…», в Chat1.htm может быть следующий текст: «У Вас всего 1 клык, по этому соберите еще…». В Chat4.htm – «Вы собрали необходимое количество предметов, возвращайтесь к вашему тренеру, что бы завершить квест…»3 A! z1 l- E9 x
: x8 R# I* V* G
* S2 q% k7 H- N: }2 l1 AПримечание: если в строка return начинается с "<html>", то будет показана страничка html с текстом, который стоит далее. Так вместо:- i c. H7 @" }, v5 T: u" h
return "Chat4.htm" : n h2 q; R! T+ ^4 D 1 @3 n( b" t9 k- O' m1 E% t0 m0 a & m3 m# l+ c! h: G; b+ Uможно поставить:% H+ j' b7 C) ?9 ?. B) d
return "<html><body>Return to your trainer to complete the quest</body></html>"
Скопировать код
Так же если строка заканчивается без .htm или в начале нет <html>, то текст будет выведен, как системное сообщение в окне чата. В нашем случае мы сделаем так, что бы при каждом убийстве keltik выводилось системное сообщение: «Собрано N из 4-х клыков». 9 k0 }. ^" H6 Z( @7 @, u " t9 D# m6 A1 k- h7 o4 p* ? / i8 G0 u' v8 V) `4 c3 u0 U HНаш код для onKill имеет один недостаток. Он будет постоянно показывать Chat0.htm, Chat1.htm и Chat4.htm, нам же необходимо, что бы Chat0.htm и Chat1.htm показывались только один раз. Как нам это сделать? С помощью переменных.- p" }7 t* ^: h+ {8 \6 I. Z
4 C' B! m/ z% L. w8 U1 K 3 {# `8 I7 \6 ^В каждом квесте строки могут храниться с помощью переменных. Эти переменные сохраняются в Вашей БД. В каждом методе мы можем назначить, прочитать и удалить переменные. Давайте изменим метод onKill, так что бы каждый диалог вызывался только один раз.2 D7 b% C3 ?/ |* o- W
def onKill (self,npcId,st): + L" x1 U+ M# s( [& r
if npcId == KELTIR_NPC_ID:" I( L5 ^. ^! D* V4 Q( z
n = getCount(st)& B* ~7 d( F9 j& e* [
if n == 0: I G: p5 S2 f( j4 j3 V; m' i) g
if st.get('chat0') == None :" V$ k: i3 t7 a1 y1 B, z5 f( r
if st.get('chat1') == None : + F. I8 ^! L/ b, x3 H o' A) z
st.set("chat1", "true"); b: [1 O2 [ Q4 V ^5 [
return "Chat1.htm" ) `* N: k) Z& D4 {# O
elif n >= 4: ; Z' Z" q; f8 u9 M- Y3 s G
return "Chat4.htm"9 D* j/ C" Y* o+ g# ]: g
return "Collected "+str(n)+" of 4 fangs" $ ]3 ]$ a. b! K, O+ r
return
Скопировать код
Если у игрока нет клыков (n=0), то мы получаем занчение переменной 'chat0'. Когда метод onKill вызван в первый раз, то пока ни каких переменных не имеется и python возвращает значение None. В этом случае объявляется переменная и показывается диалог Chat0.htm. Когда мы убиваем keltir, но не получаем с него клык, функция st.get('chat0') возвращает строку true, а не None. И во второй раз окно с Chat0.htm не появится, но в окне чата появится строчка «Collected 0 of 4 fangs». По тому же принципу сделано и с Chat1.htm. / M8 g# ^' \4 f+ Y2 |, a / a4 B# K7 {% L. ] ~ _# e) L2 _$ V5 `- x: [Вот конечный рабочий вариант квеста: ) r( {2 Y( S+ N; m, C! K; r
import sys5 Y3 K8 f/ M* f! O1 N
from net.sf.l2j.gameserver.model.quest import State1 l4 M" V/ F7 e
from net.sf.l2j.gameserver.model.quest import QuestState 0 `4 O# z o( ^/ P7 ~6 P/ J- W
from net.sf.l2j.gameserver.model.quest.jython import QuestJython as JQuest ' {; d4 [0 }: I+ t( p1 V# @4 Y
% W, j* ~6 v8 v- X
KELTIR_NPC_ID = 12082 4 }% f0 S& q) l3 w1 ? O: O
FANGS_ITEM_ID = 1859 ; W% f0 H+ b" n$ Q" W' V
DROP_RATE = 500000 6 g z8 Y+ u s) \" V2 \/ q. I' R