Зарегистрируйтесь сейчас чтобы найти еще больше друзей, и получить полноценный доступ ко всем функциям сайта!
Для просмотра Вам необходимо авторизоваться Если Вы еще не зарегистрированы, перейдите по ссылке:Зарегистрироваться
x
Хроники Interlude* c- G0 m) F5 k6 C; |' m
Сборка L2j
4 ?' a3 M6 ?1 F+ v; n" EОбратите внимание: в файле htm стартового NCP обязательно должна быть ссылка на квест:
6 o) p0 ^, S+ j; y- y1 Y- STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код Для этого квеста больше ничего не надо. Все необходимое для корректной работы квеста уже добавили. Вот полный текст квеста:% Y9 n4 N$ k9 n: I. L% L. L
" [8 z1 _ ^6 C7 v0 M9 ~7 h- if getCount(st) >= 4 :! w1 {9 e7 }" c2 ~
- completed(st) s P( i! y! E8 _, m2 B# `; Q3 p a0 O
- return( u2 z( i( w% t3 d7 I
- 7 Z' d: J3 b5 P* @/ @
- class Quest (JQuest):% X2 G5 J5 g' S
- def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)# }9 S9 O/ E! ~ _- S# v4 M( D( U8 z7 G/ k
- def onEvent (self,event,st):: _$ @" Y# H+ G% c( R
- id = st.getState()! _# S% \$ D; ]# Z* l
- if id == CREATED : st.setState(STARTED)
4 t# ]2 T* y$ |8 i: Q: c/ f4 q - elif id == COMPLETED: pass
, M7 S2 Z+ `/ q" R/ Q - elif id == STARTED : check(st)4 ~! D$ R! a- R. `' w/ w2 c: g6 R5 F
- return) V( I( B9 Z( e4 o m% w( r+ ~' r
- 8 H) w4 B; C2 v- W
- QUEST = Quest(201,"Tutorial", "Tutorial quest"). i C0 n, o3 ]8 w* ]
- CREATED = State('Start', QUEST)
# |' @ s, P" P7 G - STARTED = State('Started', QUEST)1 H9 m2 X* J5 {( W" J+ X
- COMPLETED = State('Completed', QUEST)
& c. g2 B$ q4 `
& ]+ `; {- m5 I, `8 K0 _# r- QUEST.setInitialState(CREATED)
- @2 |2 L& F# J6 H+ q+ z8 } - QUEST.addStartNpc(7056)
- w" d) R0 y' w& ^! ]$ h, Q5 ?; P% q - STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код Теперь рассмотрим, как это работает.1 [. N3 F1 ~, l. i3 n- V
Игрок подходит к начальному NCP (в данном случае 7056), нажимает на «Quest». Квест будет создан и состояние квеста перейдет к CREATED и игроку будет показана страничка Start.htm с описанием квеста. Тогда метод onEvent, поле открытия странички Start.htm переведет состояние квеста в STARTED и игроку будет показана страничка Started.htm, где будет опсание того, как найти keltirs и .т.д.. H, S' w. s4 E1 p3 |! h
! o& y; k h5 O3 D, P* k- A
K# _) S% C- H4 n6 b. yПри состоянии STARTED будет зарегистрирован дроп «fangs» при убийстве keltirs. Игрок может вернуться к стартовому NCP и спросить о квесте – метод onEvent будет вызван снова. Если у игрока не хватает необходимого количества предметов, то метод check() не переведет квест в следующее состояние и Started.htm будет показана снова. Но если игрок собрал необходимее количество предметов (в данном случае 4 клыка), то метод check() вызовет метод completed() который переведет квест в новое состояние COMPLETED, заберет все клыки, даст карту мира, т.к. это награда за квест, покажет Completed.htm и завершит квест.
) v' _# X- b5 F2 R8 G( p3 X7 t6 z
3 q, f* P" P N9 c; x
Теперь давайте сделаем наш квест более похожим на то, что он должен из себя представлять.
5 o6 @" ]7 s/ ]Прежде всего у нас есть 3 метода для объявления их в Яве – onTalk, onKill и onEvent. Если методы onTalk и onKill не объявлены, то за них все будет делать метод onEvent, т.е. определять квестовых монстров и вызывать диалоги NCP. Есть примечание, методы onTalk и onKill будут вызывать только диалоги с NCP в зависимости от текущего состояния квеста. Метод onKill будет вызываться только тогда, когда мы убиваем квестового монстра.
3 Y; [2 z! I, c1 H3 `" G7 e8 J! k0 L* W0 s
- p" F4 V& F' f% P
Давайте рассмотрим как вызывается метод onKill при убийстве keltir в состоянии квеста STARTED:" z r6 C7 W2 m' m! G) d
- STARTED.addKillId(KELTIR_NPC_ID)
Скопировать код и метод onKill в классе Quest:
5 P/ U8 i& Z. r3 C" |* @* g, z- h- e4 I1 S
- class Quest (JQuest):
) o% d4 F. d! S5 e - ...- o: b$ W) T! J& _6 ~+ p* Z6 o. z
- def onKill (self,npcId,st):
( N: O' |. n: f# w; p4 x - if npcId == KELTIR_NPC_ID:; o7 N9 m. h* ?$ w, F
- n = getCount(st)
/ i2 x& l' w( n" o% C - if n == 0:
6 x4 r2 i5 N/ o" E8 b5 A' o - return "Chat0.htm"6 q7 G% w7 a) e6 R K4 U- j
- elif n == 1:) T* D5 W' O8 h7 U0 h' M+ N
- return "Chat1.htm"6 m$ Z j% B( ?% d
- elif n >= 4:. l" c3 k) Y" ^, L0 k; ~+ |
- return "Chat4.htm"5 a+ h! D Q4 `% `
- return "Collected "+str(n)+" of 4 fangs", r* I! T! ] _4 A/ F
- return
Скопировать код Метод onKill (а так же метод onTalk) имеет следующие параметры:
$ _& J1 n9 {. |8 F& D& U
$ Q/ ~6 R0 ]! ^5 K
6 V! J- L0 A, V! a- Y0 |• self – квест
( _5 t; w9 w5 }3 t1 i- ]; I• npcId – ID NCP, которого мы должны убивать (если это метод onTalk, то ID того NCP, с которым мы должны поговорить).7 k% A3 X. b: {6 X: V
• st – текущее состояние игрока.
+ J* p* p1 |; w* ~. `3 o5 H+ \. n) i; J7 i5 Z
- r/ x# t3 M1 w; x u, ~
В этом методе мы проверяем и отмечаем, является ли убитый NCP keltir’ом. В основном эта проверка не нужна, т.к. у нас только KELTIR_NPC_ID.3 w) c' q% [2 v$ ^! X
1 f C$ _; j- q1 H3 S5 E7 T8 `( x, F6 s
Затем проверяем количество предметов (в данном случае количество клыков), и если их вообще нет, то возвращаем строку "Chat0.htm", если только один предмет, то возвращаем строку "Chat1.htm", если же предметов 4 или больше, то "Chat4.htm". Если строка возвращена из методов onEvent, onKill или onTalk, то сервер покажет соответствующие htm. В Chat0.htm может иметь следующий текст: «Вы не имеете ни одного клыка, возвращайтесь позже, когда соберете 4 штуки и бла, бла, бла…», в Chat1.htm может быть следующий текст: «У Вас всего 1 клык, по этому соберите еще…». В Chat4.htm – «Вы собрали необходимое количество предметов, возвращайтесь к вашему тренеру, что бы завершить квест…»
7 }3 P" o5 p0 z5 |9 @5 ^+ ]6 l5 X2 r+ [
2 Q- R/ j: Y5 d7 JПримечание: если в строка return начинается с "<html>", то будет показана страничка html с текстом, который стоит далее. Так вместо:
+ @/ d e7 r& Greturn "Chat4.htm"
3 }8 Q3 q0 f2 o; P9 |/ R# _( O) U( r
% t9 D v* S" p v$ l+ W8 L
можно поставить:
j* z2 z4 E9 l: `5 C6 O- return "<html><body>Return to your trainer to complete the quest</body></html>"
Скопировать код Так же если строка заканчивается без .htm или в начале нет <html>, то текст будет выведен, как системное сообщение в окне чата. В нашем случае мы сделаем так, что бы при каждом убийстве keltik выводилось системное сообщение: «Собрано N из 4-х клыков».0 O) N' P2 k2 L* y9 s" U3 U5 x
! Q9 G" I+ p: U1 r6 R: m3 O" n9 F I( h, C; |
Наш код для onKill имеет один недостаток. Он будет постоянно показывать Chat0.htm, Chat1.htm и Chat4.htm, нам же необходимо, что бы Chat0.htm и Chat1.htm показывались только один раз. Как нам это сделать? С помощью переменных.8 C1 g2 s( R, z
- M" Y- E Y# H2 U5 F, W' g: h
2 _3 \! T9 D* lВ каждом квесте строки могут храниться с помощью переменных. Эти переменные сохраняются в Вашей БД. В каждом методе мы можем назначить, прочитать и удалить переменные. Давайте изменим метод onKill, так что бы каждый диалог вызывался только один раз.
4 |" E4 U! ^2 Z. t" S- def onKill (self,npcId,st):
5 U, K2 ~- y9 R* Y - if npcId == KELTIR_NPC_ID:
+ W; v, S. i( ^. m' d+ _ - n = getCount(st)1 e4 c, [$ {. u# c, ~8 Y
- if n == 0:- x+ }; V0 X8 ?! j0 E# e
- if st.get('chat0') == None :6 S- i5 x# ^1 U, P ~
- st.set("chat0", "true")
$ B- P' D6 Y! C; S. ~3 H - return "Chat0.htm"2 }+ e# w. D6 n. E$ Z( R
- elif n == 1:
5 t8 B1 N2 g4 }9 F! ` - if st.get('chat1') == None :, J( N- c* C; |
- st.set("chat1", "true")
7 _; r* o& }: O L, ^ - return "Chat1.htm"+ C8 K) v4 r7 M- Q) B: B: w/ V2 `
- elif n >= 4:
2 V8 l# E* S N- F3 z1 p - return "Chat4.htm". `9 h- m0 K- J: E5 M# d h
- return "Collected "+str(n)+" of 4 fangs"* [' h) ^- Q0 o6 ^' P/ J& z
- return
Скопировать код Если у игрока нет клыков (n=0), то мы получаем занчение переменной 'chat0'. Когда метод onKill вызван в первый раз, то пока ни каких переменных не имеется и python возвращает значение None. В этом случае объявляется переменная и показывается диалог Chat0.htm. Когда мы убиваем keltir, но не получаем с него клык, функция st.get('chat0') возвращает строку true, а не None. И во второй раз окно с Chat0.htm не появится, но в окне чата появится строчка «Collected 0 of 4 fangs». По тому же принципу сделано и с Chat1.htm.2 i: l6 W6 e% ~; s3 V) B5 i, `! l
3 Y6 L# e( I! Y5 j. u# D7 e( a4 |
0 X% m0 h1 \$ Z) u) [! HВот конечный рабочий вариант квеста:0 N, ~9 r) H8 s9 ~ H/ o) A5 d# Y
- import sys) j7 h2 E. i! V& A
- from net.sf.l2j.gameserver.model.quest import State _- ?8 U- R8 c+ C; w
- from net.sf.l2j.gameserver.model.quest import QuestState
3 e# v2 S* L1 B1 ] Q, u - from net.sf.l2j.gameserver.model.quest.jython import QuestJython as JQuest
; h8 D1 c+ y) m, h0 [. u& N
2 B- J. S# K+ }' R; w- KELTIR_NPC_ID = 12082
9 L9 U* ~/ W1 f. t7 c3 g) H: @ - FANGS_ITEM_ID = 1859, j" I8 {9 D- f ^' E& f
- DROP_RATE = 5000004 ?3 N6 ?( W- W6 g
- + F& G& H' x. A6 E9 o3 {
- WORLD_MAP_ITEM_ID = 1665
8 D2 s v0 B c$ s$ H5 @1 q
% R9 e5 m& v& q( M- def getCount(st) :( m4 q7 }' p4 ]" ]3 ?
- return st.getQuestItemsCount(FANGS_ITEM_ID), E" C C! q* P& {1 x. H
- 0 n5 t& }. \4 P4 {
- def completed(st) :- M% I8 o' z; V$ f# _
- st.setState(COMPLETED)
9 C3 J. A$ T+ K, [. J - st.clearQuestDrops()
- ~5 Q5 ?. Q4 e" ^: p9 U {- [ - st.takeItems(FANGS_ITEM_ID,-1)7 [: J* u# S- }2 l% n) Z3 z z
- st.giveItems(WORLD_MAP_ITEM_ID,1)
+ {& e9 d" i @3 f, j - st.exitQuest(False)
. |2 N( Z, a! g4 [ - return. f7 g. b9 r: ]* w' @9 X ]
# U0 U) J, j. Z; o# U& E- def check(st) :
+ g5 a) R, I0 f) |# D - if getCount(st) >= 4 :; f7 Z5 ], {6 x8 K% q
- completed(st)
5 P' N- f% k6 y( S& A6 r8 c - return
# ]& k# b- V$ G( m3 z: g0 T - 1 W: R& Y; Q4 \8 r
- class Quest (JQuest):
+ K$ u. [. h7 H) t2 t# [
5 g! j! v8 o* ?" ]4 z: @. ^- def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)( C7 b2 ~% ?; k! T4 A5 i" F! t5 k
- ) X+ n9 j1 _) Z' J' J
- def onEvent (self,event,st):
8 I, c. N7 G s- J( g4 [4 ] - id = st.getState()) q9 e! c6 ^8 `
- if id == CREATED : st.setState(STARTED), p+ l) n/ u2 P% [
- elif id == COMPLETED: pass
l' Y% {5 C- q5 m, V; \, V8 ? L - elif id == STARTED : check(st)- s7 t. b3 ~3 S2 `/ R! Q0 H
- return8 k& x5 ?, B N/ b6 k/ a
9 `5 I% ^. l7 I" _ _- def onKill (self,npcId,st):
+ ~+ Z2 B& C& `% k& z0 r' x - if npcId == KELTIR_NPC_ID:
. r$ u; x4 O d. g7 y+ z9 ]. A7 K% f - n = getCount(st)6 {* d- T7 Y$ c( ?1 _
- if n == 0:
, i# P$ b! p% `5 [ - if st.get('chat0') == None :
9 {) C+ o" K3 ]# P2 `4 p5 Y+ B - st.set("chat0", "true")
4 L) ^% s# D+ L7 h( _( } - return "Chat0.htm"
. `- V Z( D3 f. j$ Q - elif n == 1:" \% n6 K. o6 c+ L w, ?7 d
- if st.get('chat1') == None :
" C: a- D, Y6 F0 c- ? - st.set("chat1", "true")( Y; K' X# c$ K9 E8 r# ?
- return "Chat1.htm"
- }. t# u, L9 `1 C- s3 j5 y4 e - elif n >= 4:
9 l, d4 a( L( X# E9 l, V O - return "Chat4.htm"
& j; ^, n5 _ ?$ m - return "Collect "+str(n)+" of 4 fangs"
: y8 b, c" U' v - return8 a& U2 d; v" ]# C5 Z; @
+ R$ D- r3 |9 w- QUEST = Quest(201, "Tutorial", "Tutorial quest")
7 f. F |5 I" W0 [" m9 Z/ J# t) y - CREATED = State('Start', QUEST)
+ m. e( T/ B4 N- S$ Y/ V$ S - STARTED = State('Started', QUEST)
/ [ W- J/ q7 |9 o+ ^- T - COMPLETED = State('Completed', QUEST)- r b9 u" O% u/ G/ J
9 g1 `! Q! \4 s( e7 b- QUEST.setInitialState(CREATED)" B/ Y$ H! z1 O* [& J9 x, q
- QUEST.addStartNpc(7056)
# |2 \6 ]' U8 V9 f - QUEST.addStartNpc(7012)/ u- s1 z9 I u- J( L
- QUEST.addStartNpc(7009)+ ^4 V9 g5 @2 C6 O( u8 R& q
- QUEST.addStartNpc(7011)
1 h4 V6 O- m& V, p - 1 t5 B3 D) x; Y$ L8 c8 s+ C
- STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)& h: } `4 _- }- C1 A0 O) }
- STARTED.addKillId(KELTIR_NPC_ID)
/ k k: `( W# J* n: S( u - STARTED.addTalkId(7056)9 X) T+ A3 v+ M# A7 V$ U0 j) J
- STARTED.addTalkI d(7012)
. u& }+ g+ X9 f9 }% Z$ ? - STARTED.addTalkId(7009)
1 {+ W& u: i) f* t - STARTED.addTalkId(7011)
Скопировать код
; n" G0 G4 s" {' N+ X7 x. z/ g
4 ]- K* M5 p# c7 w6 s* v |