Зарегистрируйтесь сейчас чтобы найти еще больше друзей, и получить полноценный доступ ко всем функциям сайта!
Для просмотра Вам необходимо авторизоваться Если Вы еще не зарегистрированы, перейдите по ссылке:Зарегистрироваться
x
Хроники Interlude# i- I w0 o2 ~! A- K. x/ G1 S
Сборка L2j
) Y& s. }9 A, c1 Z8 X+ l) QОбратите внимание: в файле htm стартового NCP обязательно должна быть ссылка на квест:
5 c9 Q2 Z' @; J/ {* R- STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код Для этого квеста больше ничего не надо. Все необходимое для корректной работы квеста уже добавили. Вот полный текст квеста:4 j" R% z7 E& l, k3 |
5 F( z8 X1 T4 p1 c3 \
- if getCount(st) >= 4 :7 Z# _/ } K5 N
- completed(st)
$ K5 u, d. b: O: S - return) J; B* c. H4 T V+ L6 o! Y
7 ?- y8 Q0 U3 v0 ` Y, P9 d- class Quest (JQuest):% c/ m1 K% Q$ K. Z( O4 l
- def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)
' D- M$ c# m! g- `- O - def onEvent (self,event,st):
' ^7 u* F7 I4 T9 U: G - id = st.getState()
( p( n9 D3 r7 L) v - if id == CREATED : st.setState(STARTED)$ o$ J8 h @) S5 F t
- elif id == COMPLETED: pass
" r' d4 ]% D6 T - elif id == STARTED : check(st)+ Y3 m: v$ `2 W8 k' l6 [+ D' ]
- return
- t9 V" z0 D: z! }4 P! j6 x - + M. o1 G/ {9 l7 n8 E6 k
- QUEST = Quest(201,"Tutorial", "Tutorial quest")
; Y+ Q) P) Y+ m/ [6 @ - CREATED = State('Start', QUEST)
0 [' Y* \3 Z: r, K* D - STARTED = State('Started', QUEST)
& l. u# k, G& [( o' }* l - COMPLETED = State('Completed', QUEST)* s+ Q( v2 U" E& }$ q0 J
) K! b1 q& x$ x2 n* l) j7 M, d- QUEST.setInitialState(CREATED)) r( X9 P. F2 n+ f. l: T
- QUEST.addStartNpc(7056)
" }# |- J' J% d& J0 ^$ C2 I) F/ b - STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код Теперь рассмотрим, как это работает.( g5 A' |5 O% S
Игрок подходит к начальному NCP (в данном случае 7056), нажимает на «Quest». Квест будет создан и состояние квеста перейдет к CREATED и игроку будет показана страничка Start.htm с описанием квеста. Тогда метод onEvent, поле открытия странички Start.htm переведет состояние квеста в STARTED и игроку будет показана страничка Started.htm, где будет опсание того, как найти keltirs и .т.д.
& s* F. x) w5 {; f; y1 P4 D" M
9 D) o* b# T* J' s) ?- z: j, W; G4 D9 u
При состоянии STARTED будет зарегистрирован дроп «fangs» при убийстве keltirs. Игрок может вернуться к стартовому NCP и спросить о квесте – метод onEvent будет вызван снова. Если у игрока не хватает необходимого количества предметов, то метод check() не переведет квест в следующее состояние и Started.htm будет показана снова. Но если игрок собрал необходимее количество предметов (в данном случае 4 клыка), то метод check() вызовет метод completed() который переведет квест в новое состояние COMPLETED, заберет все клыки, даст карту мира, т.к. это награда за квест, покажет Completed.htm и завершит квест.* P$ l- q4 V9 Q' p: m
$ U( _6 I1 U6 c) \
/ r7 L1 V2 y: l) c! BТеперь давайте сделаем наш квест более похожим на то, что он должен из себя представлять.( u* D& K* v9 F# r3 u5 [
Прежде всего у нас есть 3 метода для объявления их в Яве – onTalk, onKill и onEvent. Если методы onTalk и onKill не объявлены, то за них все будет делать метод onEvent, т.е. определять квестовых монстров и вызывать диалоги NCP. Есть примечание, методы onTalk и onKill будут вызывать только диалоги с NCP в зависимости от текущего состояния квеста. Метод onKill будет вызываться только тогда, когда мы убиваем квестового монстра.
& h- I) ] a6 b" ]) r/ s
- F" M# H9 Y: B7 W
# l% S: P ~% s/ a% MДавайте рассмотрим как вызывается метод onKill при убийстве keltir в состоянии квеста STARTED:
4 W2 f( j8 q6 O- q: U+ o2 N) F/ E$ F- STARTED.addKillId(KELTIR_NPC_ID)
Скопировать код и метод onKill в классе Quest:+ P. G, P+ O$ }, l& w* @9 K$ [, D' R
4 S+ ~7 \+ ]$ Y# V6 ~. |1 w7 [- p- class Quest (JQuest):+ s5 O, A$ u2 g0 S2 Q
- ...: D' M; B4 _) d( w
- def onKill (self,npcId,st):: V+ r# S( p# ~- i0 Y" r
- if npcId == KELTIR_NPC_ID:
* e5 X" }! w: M9 e. t$ I - n = getCount(st)
/ Q! X' }! G* S+ h( R$ n - if n == 0:
' y# u" o* W6 Z- a2 M - return "Chat0.htm"& r! }1 p1 l4 S% E5 ?/ U
- elif n == 1:
# f7 k; W$ X* D - return "Chat1.htm"% ~5 }( G6 p2 Y6 |1 {% ]5 [* q+ v, m
- elif n >= 4:- N+ S' l# f2 V! e& A6 Y
- return "Chat4.htm"
# ?0 O' L4 H/ {; e8 p - return "Collected "+str(n)+" of 4 fangs"
1 M. U1 n* g1 `5 S$ I; _ - return
Скопировать код Метод onKill (а так же метод onTalk) имеет следующие параметры:
+ N% l( L8 R6 R5 F) ~1 b& T3 B5 e' I1 s' m" e
2 v: U9 ?2 c: h% x• self – квест
- X3 o8 f9 @, x. f+ s• npcId – ID NCP, которого мы должны убивать (если это метод onTalk, то ID того NCP, с которым мы должны поговорить).
; r8 {# t( S/ a( `6 j4 `: x6 m% s• st – текущее состояние игрока.
, l4 x; Y/ \7 b% W6 d, F3 y
" v8 \2 s+ B& ~8 j6 i9 |: J3 X% m6 l! P+ Q6 a6 b8 Y
В этом методе мы проверяем и отмечаем, является ли убитый NCP keltir’ом. В основном эта проверка не нужна, т.к. у нас только KELTIR_NPC_ID.& c" F8 w7 A+ o' R# [
/ Y2 l+ E. ?8 q. P. f/ r
& Y+ P) G# R9 [2 M; Y* fЗатем проверяем количество предметов (в данном случае количество клыков), и если их вообще нет, то возвращаем строку "Chat0.htm", если только один предмет, то возвращаем строку "Chat1.htm", если же предметов 4 или больше, то "Chat4.htm". Если строка возвращена из методов onEvent, onKill или onTalk, то сервер покажет соответствующие htm. В Chat0.htm может иметь следующий текст: «Вы не имеете ни одного клыка, возвращайтесь позже, когда соберете 4 штуки и бла, бла, бла…», в Chat1.htm может быть следующий текст: «У Вас всего 1 клык, по этому соберите еще…». В Chat4.htm – «Вы собрали необходимое количество предметов, возвращайтесь к вашему тренеру, что бы завершить квест…»* V6 E0 D5 u) c; M
% m8 L" Q) \- A4 D
' K' x O5 k; mПримечание: если в строка return начинается с "<html>", то будет показана страничка html с текстом, который стоит далее. Так вместо:3 F# S Z3 P- j6 l7 M
return "Chat4.htm", _+ ]# N, N" J9 u& v* c1 z
- c. g! K1 |& J% J
6 P- L9 [& @9 c3 uможно поставить:! r) O/ a! J- x2 s
- return "<html><body>Return to your trainer to complete the quest</body></html>"
Скопировать код Так же если строка заканчивается без .htm или в начале нет <html>, то текст будет выведен, как системное сообщение в окне чата. В нашем случае мы сделаем так, что бы при каждом убийстве keltik выводилось системное сообщение: «Собрано N из 4-х клыков».
5 j' ~3 ^3 l v4 L. o* m( {% D1 I
8 @0 l& V( B9 ~: Q% r. X
/ e+ C( V0 o& P7 L! S. {+ R* gНаш код для onKill имеет один недостаток. Он будет постоянно показывать Chat0.htm, Chat1.htm и Chat4.htm, нам же необходимо, что бы Chat0.htm и Chat1.htm показывались только один раз. Как нам это сделать? С помощью переменных.
2 `) N% F2 a; ~4 E* r9 t& F* S A3 T* m
" @% Y& B# ?* H* t( R, Y" b# G9 f
В каждом квесте строки могут храниться с помощью переменных. Эти переменные сохраняются в Вашей БД. В каждом методе мы можем назначить, прочитать и удалить переменные. Давайте изменим метод onKill, так что бы каждый диалог вызывался только один раз.
: g$ w7 q9 m5 u2 o- def onKill (self,npcId,st):
8 i. [8 F$ O1 H6 z3 `& H# v6 u, Q - if npcId == KELTIR_NPC_ID:3 s) Q0 q$ h# X) Q) J
- n = getCount(st)
/ `2 N; }7 [7 f% m - if n == 0:4 B3 {, {5 \2 n+ h9 o
- if st.get('chat0') == None :
1 k- @3 J/ _( V - st.set("chat0", "true")
4 L& C& \2 h3 }& h3 K0 m - return "Chat0.htm"
) h! Y4 m+ _5 F% R( v3 L/ P - elif n == 1:! U9 W" r* A0 A- V: ?' w8 d
- if st.get('chat1') == None :/ S# h( Q, {1 u: B8 ]& y
- st.set("chat1", "true")! R6 R! |7 K5 W4 o3 N- `7 I
- return "Chat1.htm"
0 r8 b+ H. R& a0 s$ e - elif n >= 4:
* p. X- m6 n# L# I3 Z) ~% B - return "Chat4.htm"
1 ?+ ^. J. t, b - return "Collected "+str(n)+" of 4 fangs"
4 O2 s- I6 E: m* H2 M9 z5 @ - return
Скопировать код Если у игрока нет клыков (n=0), то мы получаем занчение переменной 'chat0'. Когда метод onKill вызван в первый раз, то пока ни каких переменных не имеется и python возвращает значение None. В этом случае объявляется переменная и показывается диалог Chat0.htm. Когда мы убиваем keltir, но не получаем с него клык, функция st.get('chat0') возвращает строку true, а не None. И во второй раз окно с Chat0.htm не появится, но в окне чата появится строчка «Collected 0 of 4 fangs». По тому же принципу сделано и с Chat1.htm.
% e6 X8 z7 j/ c, Y8 \+ I7 f/ x4 J* b
7 N6 s) m! O. A8 W# c% rВот конечный рабочий вариант квеста:
/ l) H* A! W. \1 z4 @* M7 d- import sys
& Z1 v E- C7 |: k - from net.sf.l2j.gameserver.model.quest import State
: f# C8 i8 e( l - from net.sf.l2j.gameserver.model.quest import QuestState
" L# n3 ^/ ]) t$ k7 E) N - from net.sf.l2j.gameserver.model.quest.jython import QuestJython as JQuest
4 U5 X+ P3 B% e% F/ S' } - ' W. V' I8 ^, C& {: s$ g
- KELTIR_NPC_ID = 12082
9 f* M3 I- I* {; m1 b+ F - FANGS_ITEM_ID = 1859/ _; h# @3 y# |$ s3 Z9 Z+ b
- DROP_RATE = 5000001 M8 d$ s- k, a9 S
- 8 b+ e5 c( Y) \ s) B
- WORLD_MAP_ITEM_ID = 1665
$ f4 R1 t0 B) X
/ o: ^: L4 X) H7 x5 o. r6 s- def getCount(st) :
" _( O4 i- {+ Z6 l) z* ?% T6 ^- `" K - return st.getQuestItemsCount(FANGS_ITEM_ID), u/ S/ _; x- ~8 T
- 4 p6 C; R* B9 m3 V6 D- ?- u; f6 r
- def completed(st) :
# d# |4 s0 v, O. n - st.setState(COMPLETED)4 I. w: h" t$ L4 {& h
- st.clearQuestDrops()/ x/ m' L! ]: N* @- |
- st.takeItems(FANGS_ITEM_ID,-1)" d8 Y! l9 |2 \6 T1 a$ }& Q3 i
- st.giveItems(WORLD_MAP_ITEM_ID,1)9 g9 H' B/ y7 {$ X Y# R
- st.exitQuest(False)7 ?+ k, \, f& D5 o1 r; x
- return
S$ f( K" h) |9 D+ S) t - 4 Q. G/ C$ K/ ^- ?6 {% R
- def check(st) :6 A' p' v" ]1 C# _
- if getCount(st) >= 4 :/ c# Y- M# s* X, M* B& u/ o
- completed(st)
! Q3 z3 P; ]6 l( t - return
- q$ _' l4 o. u! q4 O6 H - % b6 ?; `4 ] L3 k! H
- class Quest (JQuest):' m& [; n2 u4 [. W/ O$ B% A/ \
- * a. c# ]( v) q% C
- def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)
' }6 |0 J8 ]/ r" o - 2 J" X: V, |" u
- def onEvent (self,event,st):
1 K7 Y0 p# J' Y; i - id = st.getState()
3 o0 G% `8 u4 ?% o- y/ t" } - if id == CREATED : st.setState(STARTED)
! l: r+ d0 M4 o) g3 ? - elif id == COMPLETED: pass
. u+ o$ H) P( g& u - elif id == STARTED : check(st)
6 J" V1 E# n: f - return; ?- U( f( \3 Z3 `* X
- ! {# L1 Y ~7 G
- def onKill (self,npcId,st):
/ h C4 f7 j0 ?7 }- a, a7 Y9 f - if npcId == KELTIR_NPC_ID:
8 _! L$ T' s, }6 e4 I2 {; s3 i - n = getCount(st)9 a% C3 X3 K! D" ]! v
- if n == 0:
: r6 N: k. _) @% f1 m- k, m - if st.get('chat0') == None :. W4 a2 \9 I. U8 j( ^+ a, s
- st.set("chat0", "true")+ ~; [: j! i9 D: S" @. y+ l
- return "Chat0.htm"/ o$ m, C0 O l: e( R; y
- elif n == 1:( t8 k# Z( b$ k% [" ]/ W( e% M$ q
- if st.get('chat1') == None :
+ Q+ K+ S" J9 N, ?8 B6 J - st.set("chat1", "true")
9 d% M/ ?0 A, W3 K2 G- ] - return "Chat1.htm"
: `6 q0 M7 F1 _$ I; P - elif n >= 4:7 n' E7 g; ~; a! N- E
- return "Chat4.htm"
1 S7 V1 q, m m! }$ a - return "Collect "+str(n)+" of 4 fangs"! C; O" }1 K& ]8 G
- return$ Q$ L- J! P4 W. E# d! j& Z" q
- 2 k- Z0 L- U9 L8 R
- QUEST = Quest(201, "Tutorial", "Tutorial quest")6 g: i6 |( E ?$ y& n) z
- CREATED = State('Start', QUEST)
0 b! `- i! ?( T' J# c - STARTED = State('Started', QUEST)5 g% z% I# ^0 F3 S4 @
- COMPLETED = State('Completed', QUEST)3 J6 t: c* G. L5 S' C
! q3 q1 `+ n$ t! n( j. I- QUEST.setInitialState(CREATED)' {* {: w" L! y$ Y5 e% U
- QUEST.addStartNpc(7056)
" w8 P' s5 \& J4 m - QUEST.addStartNpc(7012)0 n5 e+ a* N' J3 X$ d
- QUEST.addStartNpc(7009)
8 e# m' j& A4 F; N. S% o2 f% N - QUEST.addStartNpc(7011)
2 ]/ Q8 [ L x: d7 g' J6 L - * c2 O: w1 p' S
- STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)" q( ]3 H1 e5 e+ H3 E
- STARTED.addKillId(KELTIR_NPC_ID)% z8 _9 G/ b: ~/ u
- STARTED.addTalkId(7056)
j" ~" T5 k! s. {, G - STARTED.addTalkI d(7012)
7 n" L c ^# a - STARTED.addTalkId(7009)
c! J/ `9 |! c8 k) g) J# p" O# B - STARTED.addTalkId(7011)
Скопировать код
! v3 b# t7 z, h% w
/ {$ R% [) ]) a$ N: O |