Зарегистрируйтесь сейчас чтобы найти еще больше друзей, и получить полноценный доступ ко всем функциям сайта!
Для просмотра Вам необходимо авторизоваться Если Вы еще не зарегистрированы, перейдите по ссылке:Зарегистрироваться
x
Хроники Interlude R9 G* U% G5 F/ u y7 }3 u2 b
Сборка L2j
( ]/ x7 I/ |4 r" A% VОбратите внимание: в файле htm стартового NCP обязательно должна быть ссылка на квест:
+ D' i- V% S; [' w- STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код Для этого квеста больше ничего не надо. Все необходимое для корректной работы квеста уже добавили. Вот полный текст квеста:
/ _6 K9 y9 s% I' X; c) G
! c" b6 o# K J" L3 Z; @8 {7 h- if getCount(st) >= 4 :. H! I% Z( C$ D7 j$ I
- completed(st)
- _* @: p4 @& w5 j - return
1 Q) k! A" g3 G3 t/ ~ - 2 e8 l1 A% x5 V1 w
- class Quest (JQuest):
3 B5 U+ z( }0 u& \8 R( E6 T - def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)
5 W: y! L& {" y* x: T) T - def onEvent (self,event,st):
! e, _. Z0 o9 ?9 x - id = st.getState()# g. X$ T! k! V6 P" m
- if id == CREATED : st.setState(STARTED)1 F/ D5 m; T0 X$ @5 m; F( }2 `6 Z
- elif id == COMPLETED: pass1 p5 ?$ N' [$ P9 Y7 Z% G4 K
- elif id == STARTED : check(st)
9 \9 c! F$ c* Z( m - return
) K L1 s: @. U: Z; w - 6 c) w7 A$ s$ L( n1 V+ ]/ r
- QUEST = Quest(201,"Tutorial", "Tutorial quest")
5 R3 U8 n! U8 K' f - CREATED = State('Start', QUEST)
3 P! a! R5 {/ ?9 | ] - STARTED = State('Started', QUEST)' y0 V6 A) F5 B5 D' Z$ w0 X
- COMPLETED = State('Completed', QUEST)
; ^' q. N% t0 I& O
0 g; ^* O: q: `- QUEST.setInitialState(CREATED)
. U- o9 }" m [0 r% R - QUEST.addStartNpc(7056)
6 u, P5 M, r3 f1 Q& n - STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код Теперь рассмотрим, как это работает.
: \5 L# T# q" q! EИгрок подходит к начальному NCP (в данном случае 7056), нажимает на «Quest». Квест будет создан и состояние квеста перейдет к CREATED и игроку будет показана страничка Start.htm с описанием квеста. Тогда метод onEvent, поле открытия странички Start.htm переведет состояние квеста в STARTED и игроку будет показана страничка Started.htm, где будет опсание того, как найти keltirs и .т.д.( u5 E1 F0 j7 R# ]4 G! p
' f9 L+ X- I; G+ y# s
1 k# w$ l" I& ~. N, x- b4 |
При состоянии STARTED будет зарегистрирован дроп «fangs» при убийстве keltirs. Игрок может вернуться к стартовому NCP и спросить о квесте – метод onEvent будет вызван снова. Если у игрока не хватает необходимого количества предметов, то метод check() не переведет квест в следующее состояние и Started.htm будет показана снова. Но если игрок собрал необходимее количество предметов (в данном случае 4 клыка), то метод check() вызовет метод completed() который переведет квест в новое состояние COMPLETED, заберет все клыки, даст карту мира, т.к. это награда за квест, покажет Completed.htm и завершит квест.& P! Z3 O0 H- l
" W; r/ d+ l- u% x( s
2 W& p* c5 r& n; n! hТеперь давайте сделаем наш квест более похожим на то, что он должен из себя представлять.; A& s6 E) g- p3 c' w! k
Прежде всего у нас есть 3 метода для объявления их в Яве – onTalk, onKill и onEvent. Если методы onTalk и onKill не объявлены, то за них все будет делать метод onEvent, т.е. определять квестовых монстров и вызывать диалоги NCP. Есть примечание, методы onTalk и onKill будут вызывать только диалоги с NCP в зависимости от текущего состояния квеста. Метод onKill будет вызываться только тогда, когда мы убиваем квестового монстра./ B6 h7 U% c- e- e/ Q
6 C ^- E" d9 I% M/ m. i1 z
1 r R2 H, E* S
Давайте рассмотрим как вызывается метод onKill при убийстве keltir в состоянии квеста STARTED:- t1 U4 L3 i d6 g& s% \' [- v
- STARTED.addKillId(KELTIR_NPC_ID)
Скопировать код и метод onKill в классе Quest:
- u1 n! z/ V% H1 L0 t9 c j$ J8 B5 V& H R
- class Quest (JQuest):
' b$ {! m% b% x; N g7 z0 k - ...
& i" o7 F' x0 i6 E3 b - def onKill (self,npcId,st):0 u* G7 w+ J, w& b# J+ P
- if npcId == KELTIR_NPC_ID:
7 i9 ^9 k. H l* D" n( p, d+ @ - n = getCount(st)
+ A d- a3 h% ]# t - if n == 0:
# ^% o" k# h# D6 W# y0 O - return "Chat0.htm"
3 g! l P1 |: a1 D1 @( ^: Y - elif n == 1:! D. n% s2 _5 g2 ?6 R- I
- return "Chat1.htm"
5 Y0 A! `. A+ J+ p c* T* o/ r( ?, O - elif n >= 4:
0 q/ W, @. w0 f& f: w8 }! L6 n - return "Chat4.htm"
3 d8 F/ R) I: T$ w% V2 k3 g5 m0 ? - return "Collected "+str(n)+" of 4 fangs"% h) W8 F* a: @4 J5 x
- return
Скопировать код Метод onKill (а так же метод onTalk) имеет следующие параметры:4 X5 F* s; m+ w+ L" a9 |
( }: x2 h- `0 @; A
" i% h( ?0 T: S: a• self – квест/ v/ C1 U; N5 h) g* V' K
• npcId – ID NCP, которого мы должны убивать (если это метод onTalk, то ID того NCP, с которым мы должны поговорить).
4 q8 E& ~$ h) U• st – текущее состояние игрока.
% n( k' @6 s. m: k3 [3 h4 j, {' Z" q; P* H
5 l% M' x4 x& r2 X
В этом методе мы проверяем и отмечаем, является ли убитый NCP keltir’ом. В основном эта проверка не нужна, т.к. у нас только KELTIR_NPC_ID.
$ c$ D, K H; o) Z7 c* B, ~. I" U' ~4 h8 {
" N; n: x4 n1 L y; B: H, B/ xЗатем проверяем количество предметов (в данном случае количество клыков), и если их вообще нет, то возвращаем строку "Chat0.htm", если только один предмет, то возвращаем строку "Chat1.htm", если же предметов 4 или больше, то "Chat4.htm". Если строка возвращена из методов onEvent, onKill или onTalk, то сервер покажет соответствующие htm. В Chat0.htm может иметь следующий текст: «Вы не имеете ни одного клыка, возвращайтесь позже, когда соберете 4 штуки и бла, бла, бла…», в Chat1.htm может быть следующий текст: «У Вас всего 1 клык, по этому соберите еще…». В Chat4.htm – «Вы собрали необходимое количество предметов, возвращайтесь к вашему тренеру, что бы завершить квест…»; j$ x" {! k4 R& H
8 E7 }1 a+ x8 K& c- H, U2 I5 h/ k9 N: B) u9 c7 U
Примечание: если в строка return начинается с "<html>", то будет показана страничка html с текстом, который стоит далее. Так вместо:+ c; q/ s4 S+ K: Z; w
return "Chat4.htm"
0 m9 r* P8 P' w+ W! v8 I2 p3 A3 I2 ]" ^: ?/ r- D' C
3 F' V9 C( X! W0 e
можно поставить:
+ d* N, l- x1 T" Z- return "<html><body>Return to your trainer to complete the quest</body></html>"
Скопировать код Так же если строка заканчивается без .htm или в начале нет <html>, то текст будет выведен, как системное сообщение в окне чата. В нашем случае мы сделаем так, что бы при каждом убийстве keltik выводилось системное сообщение: «Собрано N из 4-х клыков».4 O6 W. f0 J- p4 Z/ P( |3 F7 t
: n \8 t9 Y, t% b1 Y$ l* S! m5 q. I" M5 k+ m
Наш код для onKill имеет один недостаток. Он будет постоянно показывать Chat0.htm, Chat1.htm и Chat4.htm, нам же необходимо, что бы Chat0.htm и Chat1.htm показывались только один раз. Как нам это сделать? С помощью переменных.- @! F4 e1 W- p
1 N" o9 B3 k. L6 j" Y
5 ~& n, Z5 s4 FВ каждом квесте строки могут храниться с помощью переменных. Эти переменные сохраняются в Вашей БД. В каждом методе мы можем назначить, прочитать и удалить переменные. Давайте изменим метод onKill, так что бы каждый диалог вызывался только один раз.
I" x4 j z& x; q1 @- def onKill (self,npcId,st):/ y5 p# w$ X8 y+ A* o
- if npcId == KELTIR_NPC_ID:
9 m% {( x) Q2 q8 Q- U - n = getCount(st)
: |3 S% G9 {& \% i% O - if n == 0:
/ M3 t/ N% f# g3 @7 a% z - if st.get('chat0') == None :
" }7 n. y4 l# W( G9 w2 c4 B% R - st.set("chat0", "true")& S. E8 E( L- O# w
- return "Chat0.htm") t1 n" i3 a& X, M- E
- elif n == 1:
. s. R6 e0 t& B; f - if st.get('chat1') == None :' P, a+ V3 ~4 ~" H) x
- st.set("chat1", "true")* F- h$ I, O! Y2 Q" p
- return "Chat1.htm"
0 L9 G$ Y3 z+ P8 | - elif n >= 4:
: c/ C7 ]# Q8 G: C, { - return "Chat4.htm"
) h( M8 M( D7 P/ t3 o5 l - return "Collected "+str(n)+" of 4 fangs"* I* n7 c/ q& D' I; B6 ~; B2 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.
) ~, g0 E1 B& x5 q+ d d" Y V5 |3 r V8 F1 q; L
% C1 @- |1 S! z- Q- y0 AВот конечный рабочий вариант квеста:, f. \4 G9 W# |2 E. l8 j
- import sys6 R; \6 j B9 n/ {6 x7 W
- from net.sf.l2j.gameserver.model.quest import State
+ p; l" j& g2 C( W# u8 r3 S [ - from net.sf.l2j.gameserver.model.quest import QuestState/ p _6 s: P0 u6 I- J& P
- from net.sf.l2j.gameserver.model.quest.jython import QuestJython as JQuest
' X4 ^) J! E" Y% ?# S
( J$ Q& m- p4 ~8 R( @% M X0 K- KELTIR_NPC_ID = 12082" N, f5 U. U+ J+ j* b
- FANGS_ITEM_ID = 1859
# r# S2 K5 W7 k# A( `; f - DROP_RATE = 500000
$ s( ]8 y; U% B( a) i1 ~ - . U4 u) S- e: z! g. A! V! x
- WORLD_MAP_ITEM_ID = 1665
& c. @, b) y" v! L' b; B% L2 a3 f - ; c2 h( l V6 V6 d3 J
- def getCount(st) :
% E( ~6 U$ n, z9 x - return st.getQuestItemsCount(FANGS_ITEM_ID)* x$ Y) m. e; B5 z
: }& F; o, m* l& i! f; W6 ^$ g- def completed(st) :7 f9 y H5 C" C A5 C E
- st.setState(COMPLETED): A# X" B# j2 m
- st.clearQuestDrops()5 g" e& W, M$ m
- st.takeItems(FANGS_ITEM_ID,-1)
# Y2 k, E+ e6 r2 @, d" Y& [ - st.giveItems(WORLD_MAP_ITEM_ID,1)
; `: g0 v5 M9 P' P( h2 x - st.exitQuest(False)
/ u; `& C8 e i% }$ q7 ~ - return
. s6 Z3 x* R A$ J. P! H/ @ - ( v7 P$ O( ?+ ^' }6 v; ~
- def check(st) :
w6 q6 x- y! z% K' ^- ~/ d3 |. K d - if getCount(st) >= 4 :
9 `5 v2 Y, @5 W - completed(st)
, f% L8 @3 S- Q" x: S- v3 M1 ~ - return l. @3 C( r. w6 i
0 `* v3 k4 k0 \5 `6 Q+ t J- class Quest (JQuest):3 u+ H- w0 z; H
- 4 L3 k; f% E, t
- def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)
4 |$ [6 R' A; t7 {+ v: |+ H& x - 7 e) T6 _ [4 Y p; k; ]
- def onEvent (self,event,st):
- y; H! X, j1 z - id = st.getState()1 T# |# y) C) W& _0 d+ }; A
- if id == CREATED : st.setState(STARTED)
7 H: {/ E6 `5 P4 V5 u1 ? - elif id == COMPLETED: pass, p7 O# z" c, |: z4 o7 K. d
- elif id == STARTED : check(st)! R7 L0 b# p* X: F4 C4 f) H9 s
- return1 W0 k: J8 `7 g, o
, p8 q0 q- ~" ^' n6 S e4 U- def onKill (self,npcId,st):2 a4 T6 ~# @3 @$ e. M$ K
- if npcId == KELTIR_NPC_ID:
- E3 v/ ^8 u- c) R - n = getCount(st)
. ^' D+ {6 w7 Y+ N1 q. p+ N7 x" u - if n == 0:
$ ~; T3 Z0 H( J - if st.get('chat0') == None :
% J& H; h' N, O+ ~; @ - st.set("chat0", "true")
# R) P j* v3 ^; @. ~ - return "Chat0.htm"& S: b V0 J; z! _$ c' H
- elif n == 1:( u! Y% \* R/ I1 u' v- E3 ?
- if st.get('chat1') == None :9 h2 Q; s& @+ {: @; y7 w! g
- st.set("chat1", "true")- l7 \9 \& o2 U( b0 l1 b5 c7 o
- return "Chat1.htm"% A- F6 P! D- b1 U1 W$ G" U
- elif n >= 4:- s0 f9 h5 _( b: s0 z1 t3 X0 S/ v- F
- return "Chat4.htm"
/ U& D5 k% b5 l! Y4 n* M3 h1 J' t# h - return "Collect "+str(n)+" of 4 fangs"
& K$ G" ]5 t* j U5 Q7 e$ U+ [" K. v - return. n' t4 o3 M2 u& |8 h8 V: w
- * w8 K* ^9 H$ q; `0 c* M
- QUEST = Quest(201, "Tutorial", "Tutorial quest")
; I) r; P: S1 k7 x( M# C - CREATED = State('Start', QUEST)
* {* c' x) U- m d5 S$ w2 u - STARTED = State('Started', QUEST)' ^+ F" a$ E' {" M
- COMPLETED = State('Completed', QUEST)- O' y3 Z1 L* M/ g$ a
- 0 c: B9 z) ~1 @; N5 C4 N
- QUEST.setInitialState(CREATED), K# h: K9 a N; P4 `( H# _7 s
- QUEST.addStartNpc(7056)
% B2 @* q$ Y$ i7 C - QUEST.addStartNpc(7012)
8 P1 ~2 a* F+ G+ k6 d( ? - QUEST.addStartNpc(7009)
6 o9 X8 P9 x; q' {) Q& _- T - QUEST.addStartNpc(7011)
( Z1 g( K; c- p& M - 3 w( D% k4 u& b9 _5 U
- STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
# w% v! K! }, }8 f8 d7 m - STARTED.addKillId(KELTIR_NPC_ID)" l- w. P9 a, f- j6 p
- STARTED.addTalkId(7056)
; r7 m* A. E1 u7 H- x - STARTED.addTalkI d(7012)
; i V; z( W$ T; c- D - STARTED.addTalkId(7009)& C( V4 o6 Y, s* R6 H9 u0 U, e4 r
- STARTED.addTalkId(7011)
Скопировать код 5 S( {6 j f# O0 A5 s1 X4 }
2 ?% \% Y8 O# J; m
|