Зарегистрируйтесь сейчас чтобы найти еще больше друзей, и получить полноценный доступ ко всем функциям сайта!
Для просмотра Вам необходимо авторизоваться Если Вы еще не зарегистрированы, перейдите по ссылке:Зарегистрироваться
x
Хроники Interlude! c9 s" [( m4 L$ z
Сборка L2j
3 b! k) O8 h% M4 \/ q" g0 WОбратите внимание: в файле htm стартового NCP обязательно должна быть ссылка на квест:
: i$ j9 U2 v! ~9 `7 N- STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код Для этого квеста больше ничего не надо. Все необходимое для корректной работы квеста уже добавили. Вот полный текст квеста:
$ B L' n( Q; u1 t3 Y
/ L: O- i h& v% x. ^) B; P- if getCount(st) >= 4 :3 F% z& F: F3 @. U6 C! h1 L0 _
- completed(st), C) s" y) |3 O1 G; Z) x
- return) e7 k7 f1 h: f, c/ j W
- . v+ X+ _ c; S; Q+ P4 K
- class Quest (JQuest):
% j9 ]# r) ]/ z$ C+ |+ C, X, U - def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)* d* s5 ^4 i4 Q8 G) A
- def onEvent (self,event,st):2 r4 C, z3 r+ h, N
- id = st.getState()
9 w+ v0 U7 m$ x4 r! z - if id == CREATED : st.setState(STARTED)
6 l0 w5 s l8 T - elif id == COMPLETED: pass
. C* ~. X& _9 b2 g/ y - elif id == STARTED : check(st)
( R$ Y6 O2 Q* s! P4 g% T5 ` - return4 d6 V+ m- Y% ~ t& V3 ]4 u
7 ^" @2 e" p$ _- w3 M+ E7 X# y& ?- QUEST = Quest(201,"Tutorial", "Tutorial quest")
7 |( r K9 R; J3 e* A5 n. h - CREATED = State('Start', QUEST)
2 a/ E$ Q H; [3 a - STARTED = State('Started', QUEST). g# \# l3 S; ]$ n
- COMPLETED = State('Completed', QUEST)( V1 n! @5 M$ K6 f
4 O0 K6 U, D8 k' Q# g2 H0 v v- QUEST.setInitialState(CREATED)7 v4 u" ?4 c+ X% f3 U
- QUEST.addStartNpc(7056)
9 A, K# I9 A, t! a: ~+ @2 [; A$ L - STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код Теперь рассмотрим, как это работает.
* g) s7 ~3 f. F4 @8 X" EИгрок подходит к начальному NCP (в данном случае 7056), нажимает на «Quest». Квест будет создан и состояние квеста перейдет к CREATED и игроку будет показана страничка Start.htm с описанием квеста. Тогда метод onEvent, поле открытия странички Start.htm переведет состояние квеста в STARTED и игроку будет показана страничка Started.htm, где будет опсание того, как найти keltirs и .т.д.
* g" O3 ]7 [& g( l) H9 D, K4 b3 u# h; k# l' I/ \5 |9 p3 i8 j
! _! ]) m& I6 A6 @: p$ u
При состоянии STARTED будет зарегистрирован дроп «fangs» при убийстве keltirs. Игрок может вернуться к стартовому NCP и спросить о квесте – метод onEvent будет вызван снова. Если у игрока не хватает необходимого количества предметов, то метод check() не переведет квест в следующее состояние и Started.htm будет показана снова. Но если игрок собрал необходимее количество предметов (в данном случае 4 клыка), то метод check() вызовет метод completed() который переведет квест в новое состояние COMPLETED, заберет все клыки, даст карту мира, т.к. это награда за квест, покажет Completed.htm и завершит квест.
+ `/ G6 `' H# X( u8 l) R Q' G1 e- F% M5 a
: C/ n1 I3 M$ k
Теперь давайте сделаем наш квест более похожим на то, что он должен из себя представлять.
. ~2 O, J1 x( v x. Y7 I+ lПрежде всего у нас есть 3 метода для объявления их в Яве – onTalk, onKill и onEvent. Если методы onTalk и onKill не объявлены, то за них все будет делать метод onEvent, т.е. определять квестовых монстров и вызывать диалоги NCP. Есть примечание, методы onTalk и onKill будут вызывать только диалоги с NCP в зависимости от текущего состояния квеста. Метод onKill будет вызываться только тогда, когда мы убиваем квестового монстра.
3 g9 J/ A8 a; c9 b, }5 o: c- V5 |
' e1 X! j3 ~. m+ i8 }; d
d# K/ [* A) t; x$ d2 ` eДавайте рассмотрим как вызывается метод onKill при убийстве keltir в состоянии квеста STARTED:
! l7 H/ ?' W8 S2 n7 R- STARTED.addKillId(KELTIR_NPC_ID)
Скопировать код и метод onKill в классе Quest:8 h1 P' m# N" T" p! g
* l3 o1 w7 x- o) U4 |2 T2 U- class Quest (JQuest):
9 f5 D4 q7 B3 {+ c% ~" B - ...( ~4 k. E V$ i$ J& A* ^
- def onKill (self,npcId,st):: G+ Z% h! D8 d
- if npcId == KELTIR_NPC_ID: h3 l S9 p$ \' b2 k
- n = getCount(st)
p% C* V5 t9 n" z/ _ - if n == 0:
w& k, {; K$ ~! Z$ S - return "Chat0.htm". ^7 l1 y6 @& N; P* M6 c
- elif n == 1:2 ]1 |/ @& N) U! b+ Y2 s
- return "Chat1.htm"1 m1 {# E5 ` {
- elif n >= 4:
. ^9 o6 b8 A6 Y Q; b! l - return "Chat4.htm"
1 z. l) P* Y, u3 ~' z3 U9 _3 y5 z - return "Collected "+str(n)+" of 4 fangs"
( A. c/ g! K A# @ - return
Скопировать код Метод onKill (а так же метод onTalk) имеет следующие параметры:
2 `0 B. T3 j, z! ~, F( w" s6 O4 e5 {) L/ ~# N! s
; f4 q( E* H2 y, ?+ t* b
• self – квест9 ]8 r/ F# C, `9 v
• npcId – ID NCP, которого мы должны убивать (если это метод onTalk, то ID того NCP, с которым мы должны поговорить).0 H6 ^4 d' T, d+ ~/ @& B9 r: o
• st – текущее состояние игрока.
9 l( l& N' H& a
' j5 b/ M, `0 X" A% U+ f/ V
3 r" W) |' F8 i+ F q" fВ этом методе мы проверяем и отмечаем, является ли убитый NCP keltir’ом. В основном эта проверка не нужна, т.к. у нас только KELTIR_NPC_ID.
, ?# O& N+ ~) P" c0 Y3 o+ ]3 r( V2 c1 ~
( {" @5 g# E9 f' Z
1 \' o0 u! ~( DЗатем проверяем количество предметов (в данном случае количество клыков), и если их вообще нет, то возвращаем строку "Chat0.htm", если только один предмет, то возвращаем строку "Chat1.htm", если же предметов 4 или больше, то "Chat4.htm". Если строка возвращена из методов onEvent, onKill или onTalk, то сервер покажет соответствующие htm. В Chat0.htm может иметь следующий текст: «Вы не имеете ни одного клыка, возвращайтесь позже, когда соберете 4 штуки и бла, бла, бла…», в Chat1.htm может быть следующий текст: «У Вас всего 1 клык, по этому соберите еще…». В Chat4.htm – «Вы собрали необходимое количество предметов, возвращайтесь к вашему тренеру, что бы завершить квест…»& L. N+ B$ n+ A( j, i" \
! M' l1 z% D4 r8 Z* P# U
: c; ~9 {# w) F. U
Примечание: если в строка return начинается с "<html>", то будет показана страничка html с текстом, который стоит далее. Так вместо:$ q- C/ q: q( A
return "Chat4.htm"9 r2 U, s& i4 a: {; z% E# m2 w# n
8 r- ^" }0 G7 ~* ?2 i# f. ~& Z8 @# I7 |* E
можно поставить:
4 Z: N3 n P8 `" a' D8 f5 A6 S- return "<html><body>Return to your trainer to complete the quest</body></html>"
Скопировать код Так же если строка заканчивается без .htm или в начале нет <html>, то текст будет выведен, как системное сообщение в окне чата. В нашем случае мы сделаем так, что бы при каждом убийстве keltik выводилось системное сообщение: «Собрано N из 4-х клыков».4 J2 W! M, c% X6 b* D
7 H: u% V& |% p5 a0 F
0 J7 f2 z) [! f% `6 g. z rНаш код для onKill имеет один недостаток. Он будет постоянно показывать Chat0.htm, Chat1.htm и Chat4.htm, нам же необходимо, что бы Chat0.htm и Chat1.htm показывались только один раз. Как нам это сделать? С помощью переменных.$ X1 t% G6 ^, W
7 R" Y" P! `4 y* Y) ^7 Z
$ R3 H$ |* v9 s' {! T0 {* |
В каждом квесте строки могут храниться с помощью переменных. Эти переменные сохраняются в Вашей БД. В каждом методе мы можем назначить, прочитать и удалить переменные. Давайте изменим метод onKill, так что бы каждый диалог вызывался только один раз.
! J7 Z! t$ U6 z" u0 u* l+ ?) r- def onKill (self,npcId,st):
2 z4 T X( ~9 M2 y( ^+ E7 Z3 M - if npcId == KELTIR_NPC_ID:4 \ g2 X: `5 k$ F8 y, i! w
- n = getCount(st)2 r) P+ C9 ]* r8 l5 g# ?
- if n == 0:0 l/ s4 `+ q2 ?. e( h& ^
- if st.get('chat0') == None :
; u4 k% x3 H/ o3 k - st.set("chat0", "true")7 e/ |9 E5 k* c- t' R3 a
- return "Chat0.htm"
8 j% w5 t3 N: }; C& b1 o: Q9 i - elif n == 1:8 A- x5 y( I0 R8 P( e/ d
- if st.get('chat1') == None :
0 r/ x% {. S0 o( {3 V8 v - st.set("chat1", "true")
# M% U' T$ X; ~6 O - return "Chat1.htm"
2 r4 p$ u0 `1 d0 O7 W/ A, C - elif n >= 4:
) d& b0 u1 O/ A) L1 ?# Q8 B0 E" U - return "Chat4.htm"# N6 ]9 F6 L8 N+ f* @& ?
- return "Collected "+str(n)+" of 4 fangs"# Z1 L! q% n& N4 Z: P: l
- return
Скопировать код Если у игрока нет клыков (n=0), то мы получаем занчение переменной 'chat0'. Когда метод onKill вызван в первый раз, то пока ни каких переменных не имеется и python возвращает значение None. В этом случае объявляется переменная и показывается диалог Chat0.htm. Когда мы убиваем keltir, но не получаем с него клык, функция st.get('chat0') возвращает строку true, а не None. И во второй раз окно с Chat0.htm не появится, но в окне чата появится строчка «Collected 0 of 4 fangs». По тому же принципу сделано и с Chat1.htm.* D7 r: f+ }, C/ `7 p3 K" k2 r
( ~/ z( Z+ S8 s2 y E2 n
# @" Y2 g3 P7 d- ~- n RВот конечный рабочий вариант квеста:% L7 M. n! E/ w( {3 x' O6 m
- import sys% \" `# `! k# O
- from net.sf.l2j.gameserver.model.quest import State- t: i9 C3 ]( z2 ]: Q7 v
- from net.sf.l2j.gameserver.model.quest import QuestState5 x$ |" v8 a% |+ W% g! [& I* Z/ Q0 L
- from net.sf.l2j.gameserver.model.quest.jython import QuestJython as JQuest
$ L. G+ \4 ^$ V% ?3 a- A - # j0 b) i* T9 n& R
- KELTIR_NPC_ID = 12082; ~" b: m1 ^7 ^, {# _( ]6 ^; G: N
- FANGS_ITEM_ID = 1859
' N( a, n% P8 S. k$ e: q2 ~ - DROP_RATE = 500000: l9 Z" S0 P' a
- / u8 I6 z$ z: y4 c: I2 a
- WORLD_MAP_ITEM_ID = 16658 }7 Z$ U9 l- F5 o! W* Z
& U* I( T( D: a2 ?2 E' W5 R V. y- def getCount(st) :4 \$ k, M, o" B. v
- return st.getQuestItemsCount(FANGS_ITEM_ID)+ i: f/ |. }6 @& A1 ^# v# V& v$ t
- # f7 ]: v* |9 B7 d& X
- def completed(st) :
6 `7 e5 A3 z$ K - st.setState(COMPLETED)
n) f; v/ L! _ - st.clearQuestDrops()
; z2 |; X- } _5 L2 ^" x$ ~' ^8 w0 n - st.takeItems(FANGS_ITEM_ID,-1)" b% _7 B* h( h* [; Y/ K1 C, d" X$ K" ~
- st.giveItems(WORLD_MAP_ITEM_ID,1)
& I8 a. ]" |2 g) v$ L - st.exitQuest(False)# c/ ~9 w; a z& x2 K: {
- return
7 C) o0 I/ D' q: ]8 ?8 r
( y: U7 S* d b$ T8 q- def check(st) :
! G# Y. D( m6 H a- \ - if getCount(st) >= 4 :
1 R {. c/ U v& f# C+ D5 m - completed(st)9 M! Y8 N" d9 I1 a
- return
r! S& y c' J# \- k. D) T$ {
+ y7 o. j5 l7 U a* Q/ F% r* E- class Quest (JQuest):
* F, o+ U3 l$ A
9 R# @" n1 n5 c7 G" Y- def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)% r8 V& k5 X9 g
+ g& k5 J8 `! ~- L- def onEvent (self,event,st):2 i4 i9 S ^+ H5 d: o) N; q
- id = st.getState(); {$ w6 ] w( d# y
- if id == CREATED : st.setState(STARTED)! J* v0 e M0 q. |' p" p. n
- elif id == COMPLETED: pass
; R. O7 X9 \$ B - elif id == STARTED : check(st)8 j6 P6 E( F0 c0 |2 b, D
- return' X; h+ h; {! w) ^
- e7 V* O% J6 v( W! ]8 m/ t
- def onKill (self,npcId,st):" ^, p, Z' l+ S1 c1 M
- if npcId == KELTIR_NPC_ID:5 O }& u" q9 e, B
- n = getCount(st)# A7 z& s* M- f
- if n == 0:
& d+ W; c/ w9 \% G t0 M6 R1 Q. E3 S - if st.get('chat0') == None :% j$ G; ^( u+ |
- st.set("chat0", "true")9 p* D$ R g% U8 u
- return "Chat0.htm"
# N9 l+ p) p0 e1 \; q- W - elif n == 1:" S5 c4 W* p# ^) z7 b
- if st.get('chat1') == None :
2 ]: a5 U' p7 C: r4 ~0 S6 I - st.set("chat1", "true")
) _5 y3 C k8 D* F5 X% R - return "Chat1.htm"" V. e3 t- |. N1 p+ X
- elif n >= 4:$ ?) C2 }' l/ X4 c
- return "Chat4.htm"
; ~( i5 }' d) R: y+ a" E - return "Collect "+str(n)+" of 4 fangs"
; ]1 h. v n) y, Z) Y - return) |3 D: g1 U; h+ U1 |1 W( c, I( n
- ]6 a$ y+ N+ N- QUEST = Quest(201, "Tutorial", "Tutorial quest")2 u/ \& k/ s& v) m& a( ^7 U
- CREATED = State('Start', QUEST)
$ {& R: c# v; n( m9 t* C4 R- j- r - STARTED = State('Started', QUEST)0 M; l/ F/ _' e: v; B1 B# v! Z9 n- a
- COMPLETED = State('Completed', QUEST)- p2 I0 O" F3 c4 b2 X# A4 Z) J
, K$ T, A6 ?7 k- QUEST.setInitialState(CREATED)4 T# ?5 {/ y- q( s& E
- QUEST.addStartNpc(7056): X* E/ @6 n8 w( A4 b4 R
- QUEST.addStartNpc(7012)
2 a! k0 v% G+ l- k" J+ N - QUEST.addStartNpc(7009)8 } Y' o4 ~" P; N
- QUEST.addStartNpc(7011)
4 K' i# W# ]$ W - 6 w$ G: W n( X7 Y0 F
- STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
5 {7 i; d+ W% c3 @# H$ [ - STARTED.addKillId(KELTIR_NPC_ID)4 J, A: U0 b9 \( ~' k; V0 v& y3 c
- STARTED.addTalkId(7056)
4 F6 c7 M, h' o! \" \ - STARTED.addTalkI d(7012)
/ d$ I: G- x" S - STARTED.addTalkId(7009)- f+ G# {: Z( G g) v
- STARTED.addTalkId(7011)
Скопировать код
2 t& Z0 `" J. ?3 g' R. A0 P/ E6 D
|