Название: Создаём собственные квесты (часть 2) [Версия для печати] Автор: admin Время: 2024-9-17 19:36 Название: Создаём собственные квесты (часть 2) Хроники Interlude% e) x- G7 Y i- O+ g1 j( h; o Сборка L2j : M4 R3 |5 O8 qОбратите внимание: в файле htm стартового NCP обязательно должна быть ссылка на квест:# B% e1 N6 C: E3 N, Q, q
Теперь рассмотрим, как это работает. ^. e" Y, Z$ X+ Z/ y/ t) t
Игрок подходит к начальному NCP (в данном случае 7056), нажимает на «Quest». Квест будет создан и состояние квеста перейдет к CREATED и игроку будет показана страничка Start.htm с описанием квеста. Тогда метод onEvent, поле открытия странички Start.htm переведет состояние квеста в STARTED и игроку будет показана страничка Started.htm, где будет опсание того, как найти keltirs и .т.д.5 ?3 G6 Q$ V8 r
1 h- i3 n9 O( s- v
/ F9 A( G6 s9 @. F' s+ s/ b
При состоянии STARTED будет зарегистрирован дроп «fangs» при убийстве keltirs. Игрок может вернуться к стартовому NCP и спросить о квесте – метод onEvent будет вызван снова. Если у игрока не хватает необходимого количества предметов, то метод check() не переведет квест в следующее состояние и Started.htm будет показана снова. Но если игрок собрал необходимее количество предметов (в данном случае 4 клыка), то метод check() вызовет метод completed() который переведет квест в новое состояние COMPLETED, заберет все клыки, даст карту мира, т.к. это награда за квест, покажет Completed.htm и завершит квест. 4 v: N( O4 ]5 t : l- F7 l5 T) J0 X7 P4 [6 E- {" {( l% m# m" s/ }
Теперь давайте сделаем наш квест более похожим на то, что он должен из себя представлять. ~9 I- \8 {# u0 H7 f E% cПрежде всего у нас есть 3 метода для объявления их в Яве – onTalk, onKill и onEvent. Если методы onTalk и onKill не объявлены, то за них все будет делать метод onEvent, т.е. определять квестовых монстров и вызывать диалоги NCP. Есть примечание, методы onTalk и onKill будут вызывать только диалоги с NCP в зависимости от текущего состояния квеста. Метод onKill будет вызываться только тогда, когда мы убиваем квестового монстра.$ Y$ [0 @+ V4 r+ l& W
- a1 W9 F. z6 Y& H, X, c" R. `: Z 6 C( w+ n! o5 L8 v d" _5 TДавайте рассмотрим как вызывается метод onKill при убийстве keltir в состоянии квеста STARTED:( e& X! M$ |% }. B
STARTED.addKillId(KELTIR_NPC_ID)
Скопировать код
и метод onKill в классе Quest: / u: j" N) p9 z " B0 d8 X9 I- Q1 N- B+ T9 Y
class Quest (JQuest): / y# n! ]5 M3 ~6 H6 B% D. b
... " y: t2 D0 u$ n) L7 g- `0 C
def onKill (self,npcId,st):* z$ L) F/ Z* g1 _" c
if npcId == KELTIR_NPC_ID: ( b; q+ D! c6 i
n = getCount(st) : D0 Y- m6 N/ _& R% G: @9 ]
if n == 0:9 D* _! V0 f$ f+ y
return "Chat0.htm" 6 y( x8 ]/ @2 {! d6 z3 E( b$ `
elif n == 1:8 n7 o6 A- w+ W, w
return "Chat1.htm" . a# Q. a, ] F
elif n >= 4: " u6 U; q1 F. C* O, ?
return "Chat4.htm" & ~* \. p0 @* C+ C. x
return "Collected "+str(n)+" of 4 fangs"% v; f7 C% d# U
return
Скопировать код
Метод onKill (а так же метод onTalk) имеет следующие параметры:( x# J% W1 W2 i" S2 c
# B* t6 n1 c2 V$ }/ S 1 [+ q# {) S8 x2 Z5 K• self – квест8 F% t- `$ b( R8 r5 s$ w- [% p1 j
• npcId – ID NCP, которого мы должны убивать (если это метод onTalk, то ID того NCP, с которым мы должны поговорить). Y: ]) p. R2 \1 X7 z) L6 X• st – текущее состояние игрока.4 s: e7 M4 h( S9 r
8 n! W! |# p( ?8 u% q
, w2 b$ t! t- N
В этом методе мы проверяем и отмечаем, является ли убитый NCP keltir’ом. В основном эта проверка не нужна, т.к. у нас только KELTIR_NPC_ID. 9 g, i" v- \; @$ A7 }4 t, ` 9 \5 ~! |# `9 _& |1 h! o , h7 `0 g: R' s* r8 e3 B) V$ m7 }Затем проверяем количество предметов (в данном случае количество клыков), и если их вообще нет, то возвращаем строку "Chat0.htm", если только один предмет, то возвращаем строку "Chat1.htm", если же предметов 4 или больше, то "Chat4.htm". Если строка возвращена из методов onEvent, onKill или onTalk, то сервер покажет соответствующие htm. В Chat0.htm может иметь следующий текст: «Вы не имеете ни одного клыка, возвращайтесь позже, когда соберете 4 штуки и бла, бла, бла…», в Chat1.htm может быть следующий текст: «У Вас всего 1 клык, по этому соберите еще…». В Chat4.htm – «Вы собрали необходимое количество предметов, возвращайтесь к вашему тренеру, что бы завершить квест…». U1 a y6 L7 I, F" x
3 q" @* p$ V$ p1 r+ f' R& a2 E7 V+ T* } # M* l2 {: Y, t: R IПримечание: если в строка return начинается с "<html>", то будет показана страничка html с текстом, который стоит далее. Так вместо: j: q4 w0 e6 L- G0 }$ J% ~6 Vreturn "Chat4.htm" 5 E$ M# F) A0 w . \2 b! |5 k4 d$ M M 4 k8 N, E; o$ m% d) Xможно поставить:' ]( _6 i& ^' [' |- D
return "<html><body>Return to your trainer to complete the quest</body></html>"
Скопировать код
Так же если строка заканчивается без .htm или в начале нет <html>, то текст будет выведен, как системное сообщение в окне чата. В нашем случае мы сделаем так, что бы при каждом убийстве keltik выводилось системное сообщение: «Собрано N из 4-х клыков».( E1 D% ~0 }9 ]! a) Y6 g
- w& f, u, k( \& V5 ]1 F3 g, c5 H3 ^' J7 L6 u& w0 J
Наш код для onKill имеет один недостаток. Он будет постоянно показывать Chat0.htm, Chat1.htm и Chat4.htm, нам же необходимо, что бы Chat0.htm и Chat1.htm показывались только один раз. Как нам это сделать? С помощью переменных. R8 Y0 B! k+ Q7 v) ?! R0 F1 O0 V+ Q) C" m8 }: _
: X. D% U* ?" _3 F( F" H3 D4 vВ каждом квесте строки могут храниться с помощью переменных. Эти переменные сохраняются в Вашей БД. В каждом методе мы можем назначить, прочитать и удалить переменные. Давайте изменим метод onKill, так что бы каждый диалог вызывался только один раз.7 L5 \* W2 `5 b3 H
def onKill (self,npcId,st): ; C) M) E2 @0 x9 c! y
if npcId == KELTIR_NPC_ID:' t+ i9 i# e( m2 O2 e
n = getCount(st)1 z, t9 Z* v p3 m' j
if n == 0:' P; g' I D" P C
if st.get('chat0') == None : 7 }- ?) l1 v% d" `
st.set("chat0", "true") / Z1 S0 L# _# p$ W P
return "Chat0.htm"% {2 Q# `& ?- O9 v; h* Q' D
elif n == 1:9 H+ h9 I- ]- X3 [
if st.get('chat1') == None :# c" Z" }- I* }4 i& V+ T
st.set("chat1", "true")- h; y" I; _: ~1 l; r
return "Chat1.htm" . ^5 h) r! b! f. h7 q# {! u
elif n >= 4:! C* t, V8 r0 {
return "Chat4.htm" - z& H1 z7 ]' }3 M4 r2 N+ ?! Q
return "Collected "+str(n)+" of 4 fangs" ' B* G; y: f3 }& V. b8 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. % H6 t* \% O. l6 ? a8 J* W: |4 R" Z, W/ D* e2 t
' r; \7 o/ i, w: P' S1 pВот конечный рабочий вариант квеста: {5 N/ e6 R+ s; H6 p$ R
import sys0 I' | d' S% c( K
from net.sf.l2j.gameserver.model.quest import State9 q7 i% Y# E) p( B