Зарегистрируйтесь сейчас чтобы найти еще больше друзей, и получить полноценный доступ ко всем функциям сайта!
Для просмотра Вам необходимо авторизоваться Если Вы еще не зарегистрированы, перейдите по ссылке:Зарегистрироваться
x
Хроники Interlude) a& ^4 {$ }* P' c2 H& a
Сборка L2j
, t3 d9 {: C, H5 ?+ S2 }, J2 sОбратите внимание: в файле htm стартового NCP обязательно должна быть ссылка на квест:
0 f, ], a7 a, L2 g: v0 W- STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код Для этого квеста больше ничего не надо. Все необходимое для корректной работы квеста уже добавили. Вот полный текст квеста:
/ p- U1 m7 y8 d w/ [6 u! \) X. t% ~6 [. V
- if getCount(st) >= 4 :1 K9 _$ v: c& B- G
- completed(st)
9 t; S' N F" o) h- D" {$ T - return
9 K+ H1 c$ E6 o - * j7 }3 v8 _2 N6 V6 ?
- class Quest (JQuest):' i$ `; Q4 j6 u9 x" Y
- def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)
) V+ a2 \' s% l) u0 z - def onEvent (self,event,st):
4 t) t9 W6 L2 t5 c' P - id = st.getState()
$ ~" |# e; Q; @* s7 q, g4 y - if id == CREATED : st.setState(STARTED); k* j: J7 X% S* a3 C/ ^' z1 s4 A
- elif id == COMPLETED: pass
: h6 z4 d8 n3 G a( O' H+ | - elif id == STARTED : check(st)
) p5 Q; [3 x0 ]0 l+ x1 [8 L - return
- R/ _' m4 Q" W, `
* U8 p: r: H5 J+ m$ B4 v' X- QUEST = Quest(201,"Tutorial", "Tutorial quest")7 e, w, d2 ^* i3 H: k
- CREATED = State('Start', QUEST); V+ \. L5 V: V3 L6 g3 U
- STARTED = State('Started', QUEST)8 D1 X: T4 z* y6 a0 K" e3 H# \
- COMPLETED = State('Completed', QUEST), h1 L5 C: G, U9 M
# i# \( L* m- }$ e8 B- QUEST.setInitialState(CREATED)
( H! T5 }1 m9 q- G9 I0 ?1 X - QUEST.addStartNpc(7056)5 B; A( K. o h# p% h! C8 J s
- STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код Теперь рассмотрим, как это работает.
; T' P0 H, R2 i: p6 E; k/ ZИгрок подходит к начальному NCP (в данном случае 7056), нажимает на «Quest». Квест будет создан и состояние квеста перейдет к CREATED и игроку будет показана страничка Start.htm с описанием квеста. Тогда метод onEvent, поле открытия странички Start.htm переведет состояние квеста в STARTED и игроку будет показана страничка Started.htm, где будет опсание того, как найти keltirs и .т.д.
# W3 R" L" ^" g7 e, }. E/ X# p# B! o1 G/ z {* |" q! M
! ^( x3 p1 d( _/ D
При состоянии STARTED будет зарегистрирован дроп «fangs» при убийстве keltirs. Игрок может вернуться к стартовому NCP и спросить о квесте – метод onEvent будет вызван снова. Если у игрока не хватает необходимого количества предметов, то метод check() не переведет квест в следующее состояние и Started.htm будет показана снова. Но если игрок собрал необходимее количество предметов (в данном случае 4 клыка), то метод check() вызовет метод completed() который переведет квест в новое состояние COMPLETED, заберет все клыки, даст карту мира, т.к. это награда за квест, покажет Completed.htm и завершит квест.
4 W" ]& f$ G/ |9 H+ j& k M% y6 Q1 o
$ F) N$ A" r1 _, Z3 I. [/ ^3 {, ~* HТеперь давайте сделаем наш квест более похожим на то, что он должен из себя представлять.7 c0 J4 P) j4 ^" i
Прежде всего у нас есть 3 метода для объявления их в Яве – onTalk, onKill и onEvent. Если методы onTalk и onKill не объявлены, то за них все будет делать метод onEvent, т.е. определять квестовых монстров и вызывать диалоги NCP. Есть примечание, методы onTalk и onKill будут вызывать только диалоги с NCP в зависимости от текущего состояния квеста. Метод onKill будет вызываться только тогда, когда мы убиваем квестового монстра. I7 Y/ p$ i3 }& O2 L( X
( d- [+ N0 X. o; K
# C; {& R2 a8 L$ k/ zДавайте рассмотрим как вызывается метод onKill при убийстве keltir в состоянии квеста STARTED:' R6 e& m; _# X0 M) d: x5 \' G
- STARTED.addKillId(KELTIR_NPC_ID)
Скопировать код и метод onKill в классе Quest:
, P7 W" v# O" r3 E* T% R' }) H- V8 {( j+ J
- class Quest (JQuest):
1 s% g% R- ]0 t8 P6 {! B' {. ~ - ...
( c! y: v9 m9 B5 [- w - def onKill (self,npcId,st):0 t: }9 }2 {% J$ a/ l1 E
- if npcId == KELTIR_NPC_ID:
0 R0 y# m& s( C3 e3 I - n = getCount(st)
/ N% X, G* d( B. c# w9 m - if n == 0:$ }" B3 T- H6 ~5 a: O2 s/ H
- return "Chat0.htm", i$ ~, d) Q! W! ]( u& R4 G, M; ^) i2 ?
- elif n == 1:3 g( H9 y4 I* T0 }! B- [: R. d& A) ^9 D
- return "Chat1.htm"
" e" ~ w! S9 U5 ^8 k - elif n >= 4:
( o: j2 E& u( x# T - return "Chat4.htm"
: ~% D$ B D" }4 e( W7 W - return "Collected "+str(n)+" of 4 fangs"
/ g$ G# B7 i1 T8 r - return
Скопировать код Метод onKill (а так же метод onTalk) имеет следующие параметры:# m9 v* W0 l. d
& u1 ]; R; ]2 T4 ^. n
& {& f& a' E' x3 D1 ?1 |( N• self – квест* j, v9 L& v9 o3 ^* k1 k4 _+ M
• npcId – ID NCP, которого мы должны убивать (если это метод onTalk, то ID того NCP, с которым мы должны поговорить).
) P) `4 A0 L) `; ^! }% j6 J1 B4 u• st – текущее состояние игрока.
& p2 b" m( ^2 @7 d9 |; X$ u1 s$ x
' z- x8 Y6 s+ @4 \( n' k
1 ^* x% A4 t6 P* s) C$ v9 ~В этом методе мы проверяем и отмечаем, является ли убитый NCP keltir’ом. В основном эта проверка не нужна, т.к. у нас только KELTIR_NPC_ID.0 n$ [2 T- f( F. O
7 r4 E1 n% c4 n$ J" Z/ R) L
# |6 S% E' s2 e' C1 H
Затем проверяем количество предметов (в данном случае количество клыков), и если их вообще нет, то возвращаем строку "Chat0.htm", если только один предмет, то возвращаем строку "Chat1.htm", если же предметов 4 или больше, то "Chat4.htm". Если строка возвращена из методов onEvent, onKill или onTalk, то сервер покажет соответствующие htm. В Chat0.htm может иметь следующий текст: «Вы не имеете ни одного клыка, возвращайтесь позже, когда соберете 4 штуки и бла, бла, бла…», в Chat1.htm может быть следующий текст: «У Вас всего 1 клык, по этому соберите еще…». В Chat4.htm – «Вы собрали необходимое количество предметов, возвращайтесь к вашему тренеру, что бы завершить квест…»
( a4 A4 M, T0 Q6 A& m( O% K& R/ {
, ?% p( u, t4 P' ~* u
4 C$ k& U) D P+ d( IПримечание: если в строка return начинается с "<html>", то будет показана страничка html с текстом, который стоит далее. Так вместо:
6 ?- W9 K# \; ]4 |) ]3 _& y& Mreturn "Chat4.htm"
i( l) ~5 U9 k1 {9 D! ?9 A
4 Q0 c6 E7 _7 `1 ^- o0 w' N; d
6 O2 O+ _9 v5 J; u6 l6 tможно поставить:
1 `/ ^/ a# T7 c/ _; Q- return "<html><body>Return to your trainer to complete the quest</body></html>"
Скопировать код Так же если строка заканчивается без .htm или в начале нет <html>, то текст будет выведен, как системное сообщение в окне чата. В нашем случае мы сделаем так, что бы при каждом убийстве keltik выводилось системное сообщение: «Собрано N из 4-х клыков».( i6 Q+ w; D1 D& d+ z& s
0 R. i0 B+ {5 l4 e+ J9 p% q
% E2 l8 u7 J0 X1 ?5 V# G1 \
Наш код для onKill имеет один недостаток. Он будет постоянно показывать Chat0.htm, Chat1.htm и Chat4.htm, нам же необходимо, что бы Chat0.htm и Chat1.htm показывались только один раз. Как нам это сделать? С помощью переменных.
1 Z0 R" I5 V- o
* `/ c9 @, h6 W* v8 B" h5 X0 ?4 h6 u4 a3 _; j- O+ k, z
В каждом квесте строки могут храниться с помощью переменных. Эти переменные сохраняются в Вашей БД. В каждом методе мы можем назначить, прочитать и удалить переменные. Давайте изменим метод onKill, так что бы каждый диалог вызывался только один раз.
& C% J3 X* t. h X3 j- def onKill (self,npcId,st):" \6 z7 X; q3 i2 E1 M. `" T0 _
- if npcId == KELTIR_NPC_ID:0 C0 B S' L' W
- n = getCount(st)3 N k4 F" {9 n# Q
- if n == 0:
2 K# c/ X0 t' U& E! X& ?# }9 W - if st.get('chat0') == None :
2 P( Y4 m7 }4 \% B5 G - st.set("chat0", "true")
+ H- W+ R; @5 ]. \: t - return "Chat0.htm"
' l8 q9 @- E4 t1 g, f4 D+ r - elif n == 1:
( F" m6 r- ^( s, r% i - if st.get('chat1') == None :
4 d* g9 w5 `6 F8 C8 A- p - st.set("chat1", "true")
' y2 l( b% B5 ?9 Z2 ]. A - return "Chat1.htm"8 I( j3 i& J; P( N+ T
- elif n >= 4:
9 f+ q5 x. S" C5 J# ] - return "Chat4.htm"6 @0 v6 p8 b& v/ q+ W
- return "Collected "+str(n)+" of 4 fangs"5 f1 @( Z9 @( f( j+ O; t& h5 a
- return
Скопировать код Если у игрока нет клыков (n=0), то мы получаем занчение переменной 'chat0'. Когда метод onKill вызван в первый раз, то пока ни каких переменных не имеется и python возвращает значение None. В этом случае объявляется переменная и показывается диалог Chat0.htm. Когда мы убиваем keltir, но не получаем с него клык, функция st.get('chat0') возвращает строку true, а не None. И во второй раз окно с Chat0.htm не появится, но в окне чата появится строчка «Collected 0 of 4 fangs». По тому же принципу сделано и с Chat1.htm.
# r3 G; {9 X; U7 m* N
. Y& x6 ^3 a8 M: C% Y6 i; s" p3 w i' u, u+ i9 v: }; V
Вот конечный рабочий вариант квеста:: Z: K4 W! k( j
- import sys# ?% a# O% o3 P9 ?& U/ G/ m
- from net.sf.l2j.gameserver.model.quest import State
. H- d2 c0 I& x; h# L' W. K - from net.sf.l2j.gameserver.model.quest import QuestState
/ Z0 s1 B3 t6 X2 @6 j - from net.sf.l2j.gameserver.model.quest.jython import QuestJython as JQuest8 C( |7 O4 M& Z) C
5 u* R* ?* L. v* t# k( X7 t' e- KELTIR_NPC_ID = 12082
" i, Y. E! [- ^( [0 e - FANGS_ITEM_ID = 1859
% X/ ?5 U0 F. E/ N, a( Q - DROP_RATE = 500000
8 |. p" j/ E8 X! z0 V5 c, y - % Z3 F! z( a, A4 K% f* u
- WORLD_MAP_ITEM_ID = 1665
# |( ?" a. r: ~! I* t; V
! s$ P* b4 W6 b0 l5 u; _- def getCount(st) :
+ z0 F( ]0 u+ ~/ M4 j& i) h - return st.getQuestItemsCount(FANGS_ITEM_ID)1 t8 L ?! r' b# d+ Z. }% U w
/ O- b$ e* f7 u" H- def completed(st) :7 D# q1 G% y& v' k
- st.setState(COMPLETED)# V: A4 X0 ]: j: p
- st.clearQuestDrops()9 T% k) p) [+ I1 }" s9 {
- st.takeItems(FANGS_ITEM_ID,-1)$ i1 \" J* x' g0 P0 s3 e; ^5 L
- st.giveItems(WORLD_MAP_ITEM_ID,1): O) V' |# X& s9 @ J
- st.exitQuest(False)
) m; ?" l" [4 ~3 X4 C( j - return' w- U& q4 w# i) u
& |# c( ~0 Y, Z+ S. v: `+ |- def check(st) :9 N$ \5 q; M {6 L8 r9 }
- if getCount(st) >= 4 :1 D7 q7 [2 C+ h' w0 h1 H; x: X5 X
- completed(st)
& c1 Y* Q* Q9 c S3 d4 p - return
* ]8 N7 e9 e/ A+ k1 ~ - + r, Z+ P, l& W
- class Quest (JQuest):: c4 h: c# X+ D7 i2 Y
- 1 M4 H0 @* ?1 {- V1 R3 R
- def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)
# C& U1 w, J4 Y% k3 e6 N - ' W7 Z7 P' Z" X. C: l7 Q
- def onEvent (self,event,st):
! f9 D7 V' a" @) Y- U# ~ }+ Z - id = st.getState()
' ]/ w, F! u- Y% x5 d' j* \* m - if id == CREATED : st.setState(STARTED)
% m1 F3 k1 ]8 ]: W: F - elif id == COMPLETED: pass
5 U* k8 l8 ]' o5 T) ~4 M1 l - elif id == STARTED : check(st)+ U% T* T8 F) h6 b
- return: |( R9 S! L8 G$ |
2 ~# \; q$ C$ f, S2 J- def onKill (self,npcId,st):
! j6 _1 K" n# A! x H) G - if npcId == KELTIR_NPC_ID:- ]* X4 V8 |8 e0 E5 f
- n = getCount(st)8 {' f9 X/ Y( C
- if n == 0:
) n: q, o, D; m - if st.get('chat0') == None :
7 U* n& f, D6 N/ [9 u+ \ - st.set("chat0", "true")
8 j2 Z4 _' z4 _) R8 C, q5 D - return "Chat0.htm" d* _; P# Z( O1 J; D; e
- elif n == 1:
. c1 h- V+ f& T. u& z3 e - if st.get('chat1') == None : L/ z+ M) s6 g# ^, R
- st.set("chat1", "true")3 O! T4 ]" k3 ?: @+ ]+ Y4 F9 f
- return "Chat1.htm"
+ g1 }' L/ Q: i5 Y9 a! j - elif n >= 4:) w# v# Z8 N# B+ S6 b# X8 h, x3 S
- return "Chat4.htm"! y, H, P' [* x' i, P: w0 U
- return "Collect "+str(n)+" of 4 fangs"
$ L1 q/ E0 i" z - return
2 x$ p& G9 ~" F- S! _, K. M; @* }1 b
3 ~( |: @1 g: ]6 `9 y- `0 m+ K- QUEST = Quest(201, "Tutorial", "Tutorial quest"); |3 e0 Y' Z6 }' p
- CREATED = State('Start', QUEST)
- v/ |! r) V) i - STARTED = State('Started', QUEST)' [( l0 N; }$ S$ k/ }
- COMPLETED = State('Completed', QUEST)( T; _2 w* g$ I/ } N' Q
- - X$ j3 A/ F% Q3 w3 X
- QUEST.setInitialState(CREATED): `2 F2 i% J* w, @
- QUEST.addStartNpc(7056)$ L* Q0 \+ t4 s7 x3 q
- QUEST.addStartNpc(7012)1 Y$ n" d7 A. B$ z, W0 `& b5 f
- QUEST.addStartNpc(7009) o( w6 r# B" c3 r: |
- QUEST.addStartNpc(7011)5 y; ^! p3 r* ~5 [/ I0 R
8 D2 g7 C( X4 ?- STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
3 ]# _4 ^1 ] U8 X4 |0 e7 _- i - STARTED.addKillId(KELTIR_NPC_ID)( F2 C0 j7 _ d3 L3 p' K! x0 J3 W
- STARTED.addTalkId(7056). S. c3 A) A, V- y
- STARTED.addTalkI d(7012)$ q% h' [7 c. P
- STARTED.addTalkId(7009); h' P7 w5 N; `0 ~1 O9 o
- STARTED.addTalkId(7011)
Скопировать код # Q! K. W9 r8 q" f5 o g
+ Q0 i" n; r3 ^" ?: B- m |