Зарегистрируйтесь сейчас чтобы найти еще больше друзей, и получить полноценный доступ ко всем функциям сайта!
Для просмотра Вам необходимо авторизоваться Если Вы еще не зарегистрированы, перейдите по ссылке:Зарегистрироваться
x
Хроники Interlude
9 S- N S( c5 L& aСборка L2j
Y* o* ^$ Y2 F+ n' }7 PОбратите внимание: в файле htm стартового NCP обязательно должна быть ссылка на квест:
$ `4 E+ n% H C4 ^ \- B; U- STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код Для этого квеста больше ничего не надо. Все необходимое для корректной работы квеста уже добавили. Вот полный текст квеста:2 ~7 V: k. X4 W2 a8 }# l
' H. l+ \% X5 U: B9 t1 g8 S7 c- if getCount(st) >= 4 :
1 e) J$ C/ v) e' A, R7 g - completed(st)
) Q, U9 l. Q6 l/ @5 s+ i1 I/ z. ] - return0 r) W% Z+ q) }$ m; n
* v1 w( V+ O% } X1 p6 X$ R/ A* L- class Quest (JQuest):
" A& ^3 ~2 v$ s- I0 q1 e B - def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)5 _: h$ _& u- F# G2 T
- def onEvent (self,event,st):
5 P$ H1 U H) X; ] E/ y/ @ - id = st.getState()
1 X- l9 W7 g# t* u( |2 m - if id == CREATED : st.setState(STARTED)8 z& n2 d" p: z8 a" o
- elif id == COMPLETED: pass6 |9 E2 j1 J4 m1 Z1 W" f! S
- elif id == STARTED : check(st)5 h+ d% @/ ~! l9 E' v7 D
- return
4 }. D4 m# u5 r& j - # I( _( I1 z5 Q) }
- QUEST = Quest(201,"Tutorial", "Tutorial quest")% t6 Q. K; z, T! }$ D: _+ k
- CREATED = State('Start', QUEST); m, {* ?* O2 @3 d2 M' l) _
- STARTED = State('Started', QUEST)# I1 x8 D0 j, |9 a, x5 B2 p# O
- COMPLETED = State('Completed', QUEST)/ U( d% F+ d/ y
; ^ H5 p' l: A9 D z% A5 u- QUEST.setInitialState(CREATED)
* _* Y2 b3 `; ^9 O! ?1 H - QUEST.addStartNpc(7056)0 F! v" w7 j# I
- STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код Теперь рассмотрим, как это работает.
+ @, y8 Y4 Z# @Игрок подходит к начальному NCP (в данном случае 7056), нажимает на «Quest». Квест будет создан и состояние квеста перейдет к CREATED и игроку будет показана страничка Start.htm с описанием квеста. Тогда метод onEvent, поле открытия странички Start.htm переведет состояние квеста в STARTED и игроку будет показана страничка Started.htm, где будет опсание того, как найти keltirs и .т.д.
/ e- |; ?0 t# Y* [7 V: r$ f
5 a- ?: t+ [% [4 q. O- C9 y j# j7 o. }; j8 j
При состоянии STARTED будет зарегистрирован дроп «fangs» при убийстве keltirs. Игрок может вернуться к стартовому NCP и спросить о квесте – метод onEvent будет вызван снова. Если у игрока не хватает необходимого количества предметов, то метод check() не переведет квест в следующее состояние и Started.htm будет показана снова. Но если игрок собрал необходимее количество предметов (в данном случае 4 клыка), то метод check() вызовет метод completed() который переведет квест в новое состояние COMPLETED, заберет все клыки, даст карту мира, т.к. это награда за квест, покажет Completed.htm и завершит квест.3 p3 V4 F: K$ A% W
2 y$ ^3 c8 K) s: x) C5 Q& E3 j; N: `) j+ {
Теперь давайте сделаем наш квест более похожим на то, что он должен из себя представлять.! c8 N# q$ [3 ^2 u4 l8 w( c
Прежде всего у нас есть 3 метода для объявления их в Яве – onTalk, onKill и onEvent. Если методы onTalk и onKill не объявлены, то за них все будет делать метод onEvent, т.е. определять квестовых монстров и вызывать диалоги NCP. Есть примечание, методы onTalk и onKill будут вызывать только диалоги с NCP в зависимости от текущего состояния квеста. Метод onKill будет вызываться только тогда, когда мы убиваем квестового монстра.1 D0 G& \& X+ |" [, R
7 g- f* }* q; x
2 h' f. l8 O7 @7 l, B" v) ~. LДавайте рассмотрим как вызывается метод onKill при убийстве keltir в состоянии квеста STARTED:
: o) N2 m, j5 D! ?- STARTED.addKillId(KELTIR_NPC_ID)
Скопировать код и метод onKill в классе Quest:' w& R; G7 j" Z
$ z% z, F( r m1 P q1 _1 a. M( G. \- class Quest (JQuest):
4 n9 N1 p; h5 C/ I4 [; a0 W) x - ...5 W. _5 D j7 r9 p, V
- def onKill (self,npcId,st):& C1 Z, C. d1 Q
- if npcId == KELTIR_NPC_ID:
$ v1 n9 O: Q$ H - n = getCount(st)$ q, C) ?. Z: ?, L
- if n == 0:4 n" E/ @' v& M [0 z0 F1 N
- return "Chat0.htm"2 x. X( X: @6 f; n4 I- c
- elif n == 1:' Y9 ~3 I/ @5 n/ ]% s1 {
- return "Chat1.htm"
( f8 ~8 R5 a2 [4 s2 I - elif n >= 4:) E. u" V( G; n. Z9 @) B
- return "Chat4.htm"
# X6 F8 ] F, Y a' e - return "Collected "+str(n)+" of 4 fangs"
3 K, F+ W+ B9 y, P7 z6 ^ - return
Скопировать код Метод onKill (а так же метод onTalk) имеет следующие параметры:& o. L9 X9 r9 O# L$ T9 D* x
+ O3 H, n. q, s4 z5 t/ r
% ]2 R L( { d
• self – квест* N4 ?7 I7 q! l" C
• npcId – ID NCP, которого мы должны убивать (если это метод onTalk, то ID того NCP, с которым мы должны поговорить).& f' h) F3 W* ?, G7 ?
• st – текущее состояние игрока.
% d% ~- ]" X- a3 t' z( i! ?4 K/ k- j2 N
/ F* M1 @7 b! A. @& d6 f( D! i8 p( R3 gВ этом методе мы проверяем и отмечаем, является ли убитый NCP keltir’ом. В основном эта проверка не нужна, т.к. у нас только KELTIR_NPC_ID.- L) [! j$ R2 f8 d# V/ A
- C! ~9 Y& l6 }7 I( \! E7 i7 g& P, ?. y6 E' F0 R9 `
Затем проверяем количество предметов (в данном случае количество клыков), и если их вообще нет, то возвращаем строку "Chat0.htm", если только один предмет, то возвращаем строку "Chat1.htm", если же предметов 4 или больше, то "Chat4.htm". Если строка возвращена из методов onEvent, onKill или onTalk, то сервер покажет соответствующие htm. В Chat0.htm может иметь следующий текст: «Вы не имеете ни одного клыка, возвращайтесь позже, когда соберете 4 штуки и бла, бла, бла…», в Chat1.htm может быть следующий текст: «У Вас всего 1 клык, по этому соберите еще…». В Chat4.htm – «Вы собрали необходимое количество предметов, возвращайтесь к вашему тренеру, что бы завершить квест…», T( f# q' [) x4 I7 W" Y+ @
+ z' A9 V$ r5 U4 M. d. Y' O2 u) M0 n3 u
Примечание: если в строка return начинается с "<html>", то будет показана страничка html с текстом, который стоит далее. Так вместо:! p' d9 {) D* w7 U1 L
return "Chat4.htm"6 D& u2 x6 ~( [' @! A% J- S
4 n/ |3 b: c% P7 F5 K4 ?" \/ q
8 |, n# B& r. c* i) uможно поставить:. _; S3 s e4 u9 f: A3 _
- return "<html><body>Return to your trainer to complete the quest</body></html>"
Скопировать код Так же если строка заканчивается без .htm или в начале нет <html>, то текст будет выведен, как системное сообщение в окне чата. В нашем случае мы сделаем так, что бы при каждом убийстве keltik выводилось системное сообщение: «Собрано N из 4-х клыков».' k5 P8 t& U5 e9 e4 z7 K$ ~3 O
7 v" I1 y8 ^ J$ b% \$ F
], |8 U5 X% z4 B+ Y! fНаш код для onKill имеет один недостаток. Он будет постоянно показывать Chat0.htm, Chat1.htm и Chat4.htm, нам же необходимо, что бы Chat0.htm и Chat1.htm показывались только один раз. Как нам это сделать? С помощью переменных.
( X( U& s. V# M9 l
: U: ?( I# ~& O) v6 Q7 g2 r' @. d
* ~: }, l& {! o lВ каждом квесте строки могут храниться с помощью переменных. Эти переменные сохраняются в Вашей БД. В каждом методе мы можем назначить, прочитать и удалить переменные. Давайте изменим метод onKill, так что бы каждый диалог вызывался только один раз.
, p9 o, B5 O6 D! c9 Q* g- def onKill (self,npcId,st):4 N: O+ q; x S8 S/ Q
- if npcId == KELTIR_NPC_ID:- G4 m- \$ _% ~: e6 y
- n = getCount(st)
+ Q/ W3 C7 S) l6 E9 X: s% L - if n == 0:1 W4 L; y- i3 u; [+ X
- if st.get('chat0') == None :
. j E- K0 S9 M2 }5 x - st.set("chat0", "true")) p! y: f# s- C' e# a) c% N
- return "Chat0.htm"" f8 c/ g; M. X1 J5 o9 n( f! t
- elif n == 1:" r* B( p& n; K0 V
- if st.get('chat1') == None :
6 i1 f% m# h% p - st.set("chat1", "true")3 \6 }5 T$ [0 e; r" Q' v9 O! r: a: \
- return "Chat1.htm"
/ ~% a) G0 k, n( I - elif n >= 4:9 m5 b4 L: i' }8 D$ Z
- return "Chat4.htm"
, R0 ?/ m. K- p) x4 k( C# x. W* H - return "Collected "+str(n)+" of 4 fangs"( u. O$ c j5 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.
v" Q+ j% i! E @8 n( O
1 W. b7 b2 X- u4 Y, `+ Q" `4 n! G; g
Вот конечный рабочий вариант квеста:! [2 E1 L) w8 u0 J* C
- import sys) K# N4 [, ]5 r: G; l* [
- from net.sf.l2j.gameserver.model.quest import State; c& P% l. q9 ]0 l5 y
- from net.sf.l2j.gameserver.model.quest import QuestState0 [2 q- Z; H5 `" S7 M
- from net.sf.l2j.gameserver.model.quest.jython import QuestJython as JQuest; [, [+ _+ X, v6 G) \
3 o" Y% x2 w5 L/ A; g- l- KELTIR_NPC_ID = 12082
' b, ~0 [7 \- |- m7 Y - FANGS_ITEM_ID = 1859, o" \& m9 A5 f! X, B
- DROP_RATE = 500000- a: Q0 e: Y) W' c; z) k" L
- ) A7 F2 L7 Z% q: h
- WORLD_MAP_ITEM_ID = 16657 m! i! c9 R- G9 w
- 3 a6 v% f# `* N0 ^# M
- def getCount(st) :
7 s& p! s* v( e/ q$ f - return st.getQuestItemsCount(FANGS_ITEM_ID)
R: e, w4 {/ ]$ @8 Q" b( W
! o- |: P8 j! M, g" t/ Z2 K+ c- H+ L- def completed(st) :
- S* m5 u0 j6 e9 R/ t - st.setState(COMPLETED)
- r9 j0 M0 U. l - st.clearQuestDrops()
! E; C, U! n2 J, B - st.takeItems(FANGS_ITEM_ID,-1) _) T$ H! F3 B7 ^5 E& D. e" ]" T
- st.giveItems(WORLD_MAP_ITEM_ID,1)# R" A2 x& N' v6 i4 h* E
- st.exitQuest(False)" C1 Q% y: M: X1 ^' K
- return
4 L2 A' p, w; i U, P# X
+ l6 e# e! e$ H2 |- def check(st) :
0 j d8 l2 r, J1 O9 k - if getCount(st) >= 4 :
, z& s3 X2 [+ l$ P3 l { - completed(st)
+ X( |8 D2 e' B, R9 e9 ? - return
" }/ N/ T& K# E y1 _, Q - 6 S/ P9 y+ W! b! g# e
- class Quest (JQuest):
, l$ d* n; M2 D( W7 h( j, [
4 i: U4 t6 l) U- s- def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)
0 ~. v8 i; F5 H: a6 C+ W8 G - 4 w% k2 X# l& a# X4 A
- def onEvent (self,event,st):" t" J* d8 w7 Z h/ R' U
- id = st.getState()
9 R6 x4 n4 R$ t- Z/ e$ a - if id == CREATED : st.setState(STARTED)
6 v" x. \. U/ s - elif id == COMPLETED: pass
1 a9 D* [* }+ f: B' X( b, o! p! J- X- { - elif id == STARTED : check(st)/ P+ D" u; Q6 [ T# q6 k* u
- return: ~/ i5 |' A0 u! Q
- . l3 U# v% C5 ]$ G8 R+ `
- def onKill (self,npcId,st):" E2 ]( K: }, Y5 I0 ^ `$ E
- if npcId == KELTIR_NPC_ID:
8 w K, n& D! r5 d0 e" Y - n = getCount(st)
/ v& E2 A% y4 t! ]. Q - if n == 0:
$ x4 F' B# Q/ U$ E. v - if st.get('chat0') == None :
$ r2 }) X' b; Y, W5 ]* L. f - st.set("chat0", "true")
4 s, v. v* S8 c7 A* h4 X8 U - return "Chat0.htm"* a2 \ H" T; L# \- T% h) S1 v2 d
- elif n == 1:
4 F6 L2 v) v; \ - if st.get('chat1') == None :+ }7 H' w1 V5 ?0 `0 ]: \! t
- st.set("chat1", "true")
+ C) }, L4 U+ o" P5 { - return "Chat1.htm"+ a+ l5 D* ^ V0 X# u6 |0 m
- elif n >= 4:! I) j! [, G1 G( u, R! z
- return "Chat4.htm"
G8 H( T& W% S: Y - return "Collect "+str(n)+" of 4 fangs"
( V, O7 I6 W4 w- u - return
3 V r T' i- j3 J, j) |# T4 K - B1 E. L1 l; K
- QUEST = Quest(201, "Tutorial", "Tutorial quest"). E$ i }: j9 Q+ \5 z0 g+ I
- CREATED = State('Start', QUEST)
6 h+ T/ s$ z9 J% t% T# B - STARTED = State('Started', QUEST)( K9 c. Z8 y3 s
- COMPLETED = State('Completed', QUEST)2 p& B) Q$ s/ ~7 x
" @" q9 G7 {6 d9 e1 X7 u- QUEST.setInitialState(CREATED)2 v9 h" `9 l) M [$ h& v. \. D. s
- QUEST.addStartNpc(7056)4 T; H% W: d2 m
- QUEST.addStartNpc(7012)
: \5 p% i/ y0 @2 J - QUEST.addStartNpc(7009)
0 `& R9 g" k0 h C - QUEST.addStartNpc(7011), a, _, z) }3 K$ x/ Z
) J' w: I$ N; B# d, l- STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)+ g: s& [6 }9 w( x! x8 o% _
- STARTED.addKillId(KELTIR_NPC_ID)& F' X" ?. |5 S9 Z3 C
- STARTED.addTalkId(7056)# {8 A: C* ^! s# g- Q6 F h7 i4 }
- STARTED.addTalkI d(7012). Q- a4 I3 L0 _( a
- STARTED.addTalkId(7009)
& i6 A W/ j9 E7 c6 {% k - STARTED.addTalkId(7011)
Скопировать код
; D; y* u3 ~2 |* n4 N; Q/ y3 d! @+ g3 a/ V
|