Зарегистрируйтесь сейчас чтобы найти еще больше друзей, и получить полноценный доступ ко всем функциям сайта!
Для просмотра Вам необходимо авторизоваться Если Вы еще не зарегистрированы, перейдите по ссылке:Зарегистрироваться
x
Хроники Interlude
0 e; `# M8 [) F% S$ {Сборка L2j0 a& m) m0 C' p) w! R; M
Обратите внимание: в файле htm стартового NCP обязательно должна быть ссылка на квест:) P' V2 R2 W& }1 e! }: M2 b
- STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код Для этого квеста больше ничего не надо. Все необходимое для корректной работы квеста уже добавили. Вот полный текст квеста:
4 N3 Z$ m' T: z3 N
8 \5 V1 I, T; {9 D0 f; {; E- if getCount(st) >= 4 :
, E( S1 s5 p0 h" o$ w1 y! _ - completed(st)+ S7 g, ?* `) c. z
- return
8 k7 X' R2 c5 I0 k2 y' t; U0 e( j
+ f4 i. J$ q3 ]* t- I+ A- class Quest (JQuest):
: ?" H) U4 q& z0 I' Z; A0 F - def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)& o! @* m7 E2 I/ g% b
- def onEvent (self,event,st):
1 i% x- W; J) w4 U: ? - id = st.getState()
6 a/ m# V! ?4 }1 F - if id == CREATED : st.setState(STARTED)
) q d* }( Z: K' n- c9 }- F - elif id == COMPLETED: pass- v% }; f1 T9 P8 |% C) p
- elif id == STARTED : check(st)0 c& t0 Y/ q0 {$ y) u7 S
- return
2 Y4 d3 `3 H, U# q) O) @ - 2 _$ @, C6 z: I" m& C' k# ~; S
- QUEST = Quest(201,"Tutorial", "Tutorial quest")1 t; e# e, Z8 v. F
- CREATED = State('Start', QUEST)4 H, y5 J6 |' u) ?9 a
- STARTED = State('Started', QUEST)
6 ^% `% v2 @2 L/ q! f) w - COMPLETED = State('Completed', QUEST)1 x! C" x) n0 E: b+ x) z
) z. Z* U) q t \5 j) ]1 o1 l6 i- QUEST.setInitialState(CREATED)* F" v" E& O. Y2 Z8 r {- l
- QUEST.addStartNpc(7056); n0 m4 A* g- g
- STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код Теперь рассмотрим, как это работает.
- Q+ n( Y* I1 U! k0 D. CИгрок подходит к начальному NCP (в данном случае 7056), нажимает на «Quest». Квест будет создан и состояние квеста перейдет к CREATED и игроку будет показана страничка Start.htm с описанием квеста. Тогда метод onEvent, поле открытия странички Start.htm переведет состояние квеста в STARTED и игроку будет показана страничка Started.htm, где будет опсание того, как найти keltirs и .т.д.- d. a# L" F! W6 J. {" p9 s
p' B6 B8 I3 P$ c; H$ B7 y
9 ^. T6 X. D# e0 v7 zПри состоянии STARTED будет зарегистрирован дроп «fangs» при убийстве keltirs. Игрок может вернуться к стартовому NCP и спросить о квесте – метод onEvent будет вызван снова. Если у игрока не хватает необходимого количества предметов, то метод check() не переведет квест в следующее состояние и Started.htm будет показана снова. Но если игрок собрал необходимее количество предметов (в данном случае 4 клыка), то метод check() вызовет метод completed() который переведет квест в новое состояние COMPLETED, заберет все клыки, даст карту мира, т.к. это награда за квест, покажет Completed.htm и завершит квест.
0 u( Q0 Z8 \8 p" N9 V5 |1 o& X i: e
8 A/ h' j `1 s: J9 a
Теперь давайте сделаем наш квест более похожим на то, что он должен из себя представлять.1 G" t v- L" r1 s1 ^: m7 N; J4 f
Прежде всего у нас есть 3 метода для объявления их в Яве – onTalk, onKill и onEvent. Если методы onTalk и onKill не объявлены, то за них все будет делать метод onEvent, т.е. определять квестовых монстров и вызывать диалоги NCP. Есть примечание, методы onTalk и onKill будут вызывать только диалоги с NCP в зависимости от текущего состояния квеста. Метод onKill будет вызываться только тогда, когда мы убиваем квестового монстра.) M( N1 `& ]: A/ ?( ^, Z% Z
3 q/ S! y1 T9 m. V3 |& J( Q+ V
3 ]4 z2 K. j* Y) I5 fДавайте рассмотрим как вызывается метод onKill при убийстве keltir в состоянии квеста STARTED:
& |5 z7 S, U3 p1 w$ |4 q* O4 o$ M$ b( x- STARTED.addKillId(KELTIR_NPC_ID)
Скопировать код и метод onKill в классе Quest:) c+ j7 i+ c F, o
9 o! d0 w2 [; _1 ]7 x- class Quest (JQuest):
( }1 y& ~ [# a8 S - ...
0 m) B, Z8 _7 G4 |/ E" y - def onKill (self,npcId,st):
6 K2 Y3 O" X/ { - if npcId == KELTIR_NPC_ID:
K+ ]# t0 d4 g - n = getCount(st)
( g0 ~' G$ r( H9 z* l - if n == 0:
7 y0 `+ x; C' v# x" ^* m7 ^6 n/ v - return "Chat0.htm"
5 H& |3 q# a! {- R, ] - elif n == 1:0 j( r3 b# Z0 E# h7 C& |
- return "Chat1.htm"2 E+ U- p Q8 G/ R2 G& |) U
- elif n >= 4:3 L$ B7 g2 i o* F
- return "Chat4.htm"
! H9 o9 Y p& A/ H - return "Collected "+str(n)+" of 4 fangs"
% k( `7 `' X, @# T/ m8 }* v9 [ - return
Скопировать код Метод onKill (а так же метод onTalk) имеет следующие параметры:
! x- o: X! L+ u8 v6 Z
8 F A- A4 z$ s& r3 a {5 ^ i. P& B0 R) g/ r( S( w
• self – квест- w2 }* P$ }) x+ w4 d6 E" W
• npcId – ID NCP, которого мы должны убивать (если это метод onTalk, то ID того NCP, с которым мы должны поговорить).7 f, | d. m9 E
• st – текущее состояние игрока.1 H) C6 Z p* t6 C5 y) S
5 d4 ? X# X2 j+ o6 v# A2 U, B) O8 z7 Q0 c# P
В этом методе мы проверяем и отмечаем, является ли убитый NCP keltir’ом. В основном эта проверка не нужна, т.к. у нас только KELTIR_NPC_ID.
& t+ o5 ?8 j% k9 Y( m' n
( O# ]( _0 ~- C5 E) k
# o' o* [6 c9 {) ]3 l* qЗатем проверяем количество предметов (в данном случае количество клыков), и если их вообще нет, то возвращаем строку "Chat0.htm", если только один предмет, то возвращаем строку "Chat1.htm", если же предметов 4 или больше, то "Chat4.htm". Если строка возвращена из методов onEvent, onKill или onTalk, то сервер покажет соответствующие htm. В Chat0.htm может иметь следующий текст: «Вы не имеете ни одного клыка, возвращайтесь позже, когда соберете 4 штуки и бла, бла, бла…», в Chat1.htm может быть следующий текст: «У Вас всего 1 клык, по этому соберите еще…». В Chat4.htm – «Вы собрали необходимое количество предметов, возвращайтесь к вашему тренеру, что бы завершить квест…»
; n$ Q8 E6 l' L6 g' o, `5 Z8 X0 \( Z# O# V ]4 [: i+ i
5 C8 Y- V' R# L2 E& CПримечание: если в строка return начинается с "<html>", то будет показана страничка html с текстом, который стоит далее. Так вместо:5 x. R9 o$ H1 c/ ?7 B1 a
return "Chat4.htm"
+ h3 C+ B/ t K0 Y: ]
# b; K5 G2 e, M2 @* Z! t# Z6 c
# V* n' \ n4 |) ^9 E% e9 Wможно поставить:6 H9 i2 H" q5 e- M) i
- return "<html><body>Return to your trainer to complete the quest</body></html>"
Скопировать код Так же если строка заканчивается без .htm или в начале нет <html>, то текст будет выведен, как системное сообщение в окне чата. В нашем случае мы сделаем так, что бы при каждом убийстве keltik выводилось системное сообщение: «Собрано N из 4-х клыков».
; ?( S8 m" ?! y3 |4 q
0 \( w$ T' t6 g) a+ u" l# n: v' N- C" \1 R O
Наш код для onKill имеет один недостаток. Он будет постоянно показывать Chat0.htm, Chat1.htm и Chat4.htm, нам же необходимо, что бы Chat0.htm и Chat1.htm показывались только один раз. Как нам это сделать? С помощью переменных.
- q2 V3 W2 B9 E g" @' M+ l u* ^ B* }1 r9 c c6 y" E4 {2 u9 ]7 L
) d, h/ F& W' K0 t$ x$ XВ каждом квесте строки могут храниться с помощью переменных. Эти переменные сохраняются в Вашей БД. В каждом методе мы можем назначить, прочитать и удалить переменные. Давайте изменим метод onKill, так что бы каждый диалог вызывался только один раз.$ G6 k6 x0 O8 {6 \0 m( @
- def onKill (self,npcId,st):% l/ E9 m' X" `) Y
- if npcId == KELTIR_NPC_ID:+ g' o- X5 J$ w# f: z
- n = getCount(st)
D) H5 l I0 [ - if n == 0:1 g9 X3 J ]; X: | e8 v: w4 X
- if st.get('chat0') == None :0 o$ @- n z8 K* Y
- st.set("chat0", "true")
8 d/ g+ O) D, q* c9 a. k7 n - return "Chat0.htm"3 a5 \$ |. X1 O( h1 \
- elif n == 1:7 @0 [) i- }" x: w8 g/ l. o
- if st.get('chat1') == None :
! D, G& s& H! L& k3 x - st.set("chat1", "true")
4 W; C# W0 R/ m, v& m9 e- P2 a- D - return "Chat1.htm", @; E, m7 p- t/ ~
- elif n >= 4: w2 e7 [: h' p) D
- return "Chat4.htm"
, p E% T3 n5 \7 V2 A - return "Collected "+str(n)+" of 4 fangs"
! y2 y$ u" [. ]- B& ?' g9 o" ^# V - return
Скопировать код Если у игрока нет клыков (n=0), то мы получаем занчение переменной 'chat0'. Когда метод onKill вызван в первый раз, то пока ни каких переменных не имеется и python возвращает значение None. В этом случае объявляется переменная и показывается диалог Chat0.htm. Когда мы убиваем keltir, но не получаем с него клык, функция st.get('chat0') возвращает строку true, а не None. И во второй раз окно с Chat0.htm не появится, но в окне чата появится строчка «Collected 0 of 4 fangs». По тому же принципу сделано и с Chat1.htm." H7 O3 @$ F; F6 Z! S
9 N& f/ |6 T/ m W5 c9 N }
/ S' n/ w) w) ~4 S/ BВот конечный рабочий вариант квеста:8 J X4 z) y2 h' F& f; O0 T
- import sys+ j# n' p. M2 \
- from net.sf.l2j.gameserver.model.quest import State" |. m7 V5 V' e9 L
- from net.sf.l2j.gameserver.model.quest import QuestState
4 h. F0 E* R5 Q# K - from net.sf.l2j.gameserver.model.quest.jython import QuestJython as JQuest' ?. m. Z6 d) ?0 R6 L- i9 g2 y; h- ^
2 t, T- Q. u1 R$ _. W$ m' f7 _7 |& A- KELTIR_NPC_ID = 12082
& E) m% [" m, v - FANGS_ITEM_ID = 1859: _0 f( U9 O% H/ L
- DROP_RATE = 500000
- F9 H. D( e# `3 y' O/ t u3 |
7 x. d2 n( n/ Y$ d) V. d7 V- WORLD_MAP_ITEM_ID = 1665; ?1 @( J6 v& o% z) g& ?
- n. k" d9 B; V( G1 k$ e7 n- def getCount(st) :
2 d. t4 {5 L& ?$ u - return st.getQuestItemsCount(FANGS_ITEM_ID)
* p+ n% b; g7 `+ G/ n4 ]
+ `- q- I e6 M6 s( k2 V- def completed(st) :+ v4 X5 L1 U/ C6 u1 ~+ J. K
- st.setState(COMPLETED)
$ J2 `; E6 @% n( J- s, |) M - st.clearQuestDrops()
- I! a: {0 P" g. ]5 o, L8 V - st.takeItems(FANGS_ITEM_ID,-1)9 O e) M- i8 d
- st.giveItems(WORLD_MAP_ITEM_ID,1)+ ?5 d' a3 d$ t
- st.exitQuest(False)
) S* T2 v7 w# d( p5 f2 _ - return( E; R4 `; ^/ K; k! m
- : {$ _8 ?; I! y4 I, P
- def check(st) :
' N; X. o7 N7 l7 P# } - if getCount(st) >= 4 :
$ Z3 |* y" r" r2 k- M7 i - completed(st)
9 E4 q* E% p, W8 Y+ Z* @, W - return
$ N$ S2 F# U& A, j& a
: m$ m0 Y& D+ e; G9 c! O- class Quest (JQuest):
2 w7 m: e6 k" Z1 N$ A* ?0 |
8 u, a+ o; X' e: U- def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)" W& A: ]+ N+ R3 V. p
5 m i, r6 \' ~0 z! K7 Y2 M/ u- def onEvent (self,event,st):
5 c: u2 D/ j; ]. | - id = st.getState()
% G, p; b" F, T3 ~5 |$ f - if id == CREATED : st.setState(STARTED)
7 r+ `9 O* h9 ~( \/ [8 }& [1 _) [$ A - elif id == COMPLETED: pass
7 n) [. B( U3 U4 L; ~ - elif id == STARTED : check(st)
7 x9 Q' E8 U) u2 j! o8 R; j - return4 P8 P9 X7 J; J& e
; w, q4 H; e. h" n5 y. h- b: j0 D- def onKill (self,npcId,st):
L! V( B- D4 S5 s) o# @ - if npcId == KELTIR_NPC_ID:
0 W2 u* z9 Y9 U2 t( P. | - n = getCount(st)
0 l5 G" ^3 K& [2 n - if n == 0:! A6 o6 y3 {3 {" p) P
- if st.get('chat0') == None :
& ]3 D9 R% R$ }: p0 b - st.set("chat0", "true")
0 S9 E4 \' T- F0 U( @& O3 q% [ - return "Chat0.htm"' V# ~, P( {7 O9 H- V* c
- elif n == 1:4 i# W6 \! u' }
- if st.get('chat1') == None :" Z( J! l. Y5 u
- st.set("chat1", "true")
* o! |; d1 Y2 _6 o; | - return "Chat1.htm"! R7 j4 Z2 y: @/ i" g+ I
- elif n >= 4:
+ a3 S/ \7 [( T2 N/ \. v% A* J& w - return "Chat4.htm"$ Q0 c3 |. [: R8 ?$ X- L0 f
- return "Collect "+str(n)+" of 4 fangs"
3 V; d3 K* R4 A/ ?7 I - return
+ r: t8 x' ?6 I
; m/ F/ A; }$ b5 b4 |. ^* d& B- QUEST = Quest(201, "Tutorial", "Tutorial quest")
6 k' O7 C Z$ ~% ] - CREATED = State('Start', QUEST)
9 M5 _1 {8 ]. y) ?- @ - STARTED = State('Started', QUEST)
" s9 d% |9 H4 W& j3 ?% ` - COMPLETED = State('Completed', QUEST)
4 X% a, N$ k/ ]7 I" S
& o _) z3 d& T# p- d- QUEST.setInitialState(CREATED)9 Z1 X1 }5 Q5 a7 g3 ^; H' v
- QUEST.addStartNpc(7056)
) h, |# y" }! h0 B8 B - QUEST.addStartNpc(7012)
4 R7 g; H3 @0 R( b: A - QUEST.addStartNpc(7009)9 u Y( ~" h Z
- QUEST.addStartNpc(7011)9 ?, `2 h. Z8 F
* q p. F0 X) x! [3 s* L- STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
7 H0 O' w/ |8 n4 L* t! [" c% U% r - STARTED.addKillId(KELTIR_NPC_ID)
% T3 [" @! o2 q2 p. X2 S$ E - STARTED.addTalkId(7056)
1 C5 \* L- {/ i! S6 n$ [ - STARTED.addTalkI d(7012)
; H0 K) i' G( B - STARTED.addTalkId(7009)
# R! {$ N5 x- Y* |) {6 W - STARTED.addTalkId(7011)
Скопировать код
W6 R% o* X5 d# X' E+ q* D# W& G* G" X6 M
|