Зарегистрируйтесь сейчас чтобы найти еще больше друзей, и получить полноценный доступ ко всем функциям сайта!
Для просмотра Вам необходимо авторизоваться Если Вы еще не зарегистрированы, перейдите по ссылке:Зарегистрироваться
x
Хроники Interlude
5 s' p6 n! K8 j+ b x& d( tСборка L2j% ^2 Z9 C7 Q4 C* \
Обратите внимание: в файле htm стартового NCP обязательно должна быть ссылка на квест:$ x. ]0 O1 \' g( w- t1 r
- STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код Для этого квеста больше ничего не надо. Все необходимое для корректной работы квеста уже добавили. Вот полный текст квеста:/ u, ~" u5 q! c. o2 F5 {
' c$ D$ ^$ B+ v+ K: M
- if getCount(st) >= 4 :
1 g) ^2 |4 f7 z0 M. b; p - completed(st)
1 c* w* R* A9 y& {$ u - return0 |0 c6 V5 g8 W- F! A. ~; S
- ( t8 ?6 Y- c; j
- class Quest (JQuest):
0 w+ t+ V4 N/ W1 O - def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)
: e1 n6 O6 L4 M R - def onEvent (self,event,st):) S2 C# q: {/ g& I3 _ n) J
- id = st.getState()& X+ [' \0 K" z& v
- if id == CREATED : st.setState(STARTED)
: M6 n& v6 R3 r - elif id == COMPLETED: pass5 s4 w7 }) I3 M! N* W' K6 A
- elif id == STARTED : check(st)
6 O0 n! D- r/ U. Q# H% ] - return8 N* a0 L: l* E$ `
- : z1 x0 [0 C$ G; P
- QUEST = Quest(201,"Tutorial", "Tutorial quest")
' Y2 ?7 J, O) s! a; v" x) r# J - CREATED = State('Start', QUEST)
/ M' Q* {% m0 q5 { - STARTED = State('Started', QUEST)
+ ]. l3 a2 M9 X( p% d - COMPLETED = State('Completed', QUEST)( l% C5 u) v2 F K
- u% u5 N- u1 x) C# g- QUEST.setInitialState(CREATED)8 [# Q! n7 q' Q% ?
- QUEST.addStartNpc(7056)$ h4 } t& W/ s9 G& a
- STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код Теперь рассмотрим, как это работает.
0 v4 \* u+ a d0 g" OИгрок подходит к начальному NCP (в данном случае 7056), нажимает на «Quest». Квест будет создан и состояние квеста перейдет к CREATED и игроку будет показана страничка Start.htm с описанием квеста. Тогда метод onEvent, поле открытия странички Start.htm переведет состояние квеста в STARTED и игроку будет показана страничка Started.htm, где будет опсание того, как найти keltirs и .т.д.
, ~$ r" a* }8 r3 L, X3 [- i. d8 r/ E( x) e5 h5 r* H+ P
: V% K6 S+ E7 CПри состоянии STARTED будет зарегистрирован дроп «fangs» при убийстве keltirs. Игрок может вернуться к стартовому NCP и спросить о квесте – метод onEvent будет вызван снова. Если у игрока не хватает необходимого количества предметов, то метод check() не переведет квест в следующее состояние и Started.htm будет показана снова. Но если игрок собрал необходимее количество предметов (в данном случае 4 клыка), то метод check() вызовет метод completed() который переведет квест в новое состояние COMPLETED, заберет все клыки, даст карту мира, т.к. это награда за квест, покажет Completed.htm и завершит квест.2 M0 q# y/ j5 _. M5 N7 }$ ]7 s6 S
7 T- }+ b1 G9 \3 n$ d! w. O, x
7 x- m2 g* b0 m3 y% wТеперь давайте сделаем наш квест более похожим на то, что он должен из себя представлять.
: c4 D3 S/ i+ eПрежде всего у нас есть 3 метода для объявления их в Яве – onTalk, onKill и onEvent. Если методы onTalk и onKill не объявлены, то за них все будет делать метод onEvent, т.е. определять квестовых монстров и вызывать диалоги NCP. Есть примечание, методы onTalk и onKill будут вызывать только диалоги с NCP в зависимости от текущего состояния квеста. Метод onKill будет вызываться только тогда, когда мы убиваем квестового монстра.
& N( b" y7 Z) b& C4 n. r5 Z$ u$ d: B5 I: F2 G3 P
6 h9 f4 U+ Q! @# r T% a; d
Давайте рассмотрим как вызывается метод onKill при убийстве keltir в состоянии квеста STARTED:) j$ q E3 }& g) H3 f# E" Y
- STARTED.addKillId(KELTIR_NPC_ID)
Скопировать код и метод onKill в классе Quest:
9 J. s' B9 s8 s8 {; d5 [; Y) [2 O
- class Quest (JQuest):
q. O% p3 e# U$ n3 x/ W - ...
( L! I# z% ?* J+ j - def onKill (self,npcId,st):
& H! v# ] X! F3 l( E ~, w - if npcId == KELTIR_NPC_ID:* o" Q1 l; g5 j) U" }. Q, ~
- n = getCount(st)% ^/ A' m( x' t$ E7 Y- }" O
- if n == 0:5 K0 @, T4 E* Q3 C) i) f7 `( a
- return "Chat0.htm"9 Y0 v! ^" m" X& q3 j
- elif n == 1:
; B6 o" q2 {) Z6 H. A5 Y" e - return "Chat1.htm"- r( q2 p; w* w' V
- elif n >= 4:
/ Z, C) p# n/ u/ M - return "Chat4.htm"
, w( x! s) ^8 j5 [. o: h J9 d - return "Collected "+str(n)+" of 4 fangs"
( L9 ?$ ]- Z- ~% M - return
Скопировать код Метод onKill (а так же метод onTalk) имеет следующие параметры:
$ X* a s0 g* @! W4 f/ A: j1 M- t5 E. w, J! g5 R. U" l
. d, S1 {. p+ q. N' e$ A/ p, Q( ?. J
• self – квест
9 H1 i" b/ z3 J5 Y4 J% S• npcId – ID NCP, которого мы должны убивать (если это метод onTalk, то ID того NCP, с которым мы должны поговорить).
$ r9 l4 a9 _) I- x• st – текущее состояние игрока.( v0 j) ]" i7 j, q7 m2 O# s. s" H
7 m) D7 O4 Y( l7 c5 {6 F/ l
4 H. l2 }( t+ o4 z# M2 qВ этом методе мы проверяем и отмечаем, является ли убитый NCP keltir’ом. В основном эта проверка не нужна, т.к. у нас только KELTIR_NPC_ID.
& {5 [! o t4 H& _
& Q# E2 a& X+ D% _$ X3 A$ M
' D C$ ?7 w' f* n, x) P6 UЗатем проверяем количество предметов (в данном случае количество клыков), и если их вообще нет, то возвращаем строку "Chat0.htm", если только один предмет, то возвращаем строку "Chat1.htm", если же предметов 4 или больше, то "Chat4.htm". Если строка возвращена из методов onEvent, onKill или onTalk, то сервер покажет соответствующие htm. В Chat0.htm может иметь следующий текст: «Вы не имеете ни одного клыка, возвращайтесь позже, когда соберете 4 штуки и бла, бла, бла…», в Chat1.htm может быть следующий текст: «У Вас всего 1 клык, по этому соберите еще…». В Chat4.htm – «Вы собрали необходимое количество предметов, возвращайтесь к вашему тренеру, что бы завершить квест…»
; Y. {. [3 Q& B' g, O1 P) y1 N5 A d! ]2 ?& N$ x
. {# x( r1 Y: {8 Y I
Примечание: если в строка return начинается с "<html>", то будет показана страничка html с текстом, который стоит далее. Так вместо:
2 \" O4 Z0 c2 s; v6 j9 Treturn "Chat4.htm"' N! y: z$ v7 V% \* ^# I
& O6 d. |& i+ M7 g5 S8 V
! o+ e, G9 k- \8 z' S5 ]/ d/ R- {можно поставить:
( }5 O7 j3 c/ h! a7 ?& S- return "<html><body>Return to your trainer to complete the quest</body></html>"
Скопировать код Так же если строка заканчивается без .htm или в начале нет <html>, то текст будет выведен, как системное сообщение в окне чата. В нашем случае мы сделаем так, что бы при каждом убийстве keltik выводилось системное сообщение: «Собрано N из 4-х клыков».; |0 k9 E: {, l# H! d( \
- l4 I9 Q: s$ x
8 L, \+ k2 J" k$ f y8 Q( @Наш код для onKill имеет один недостаток. Он будет постоянно показывать Chat0.htm, Chat1.htm и Chat4.htm, нам же необходимо, что бы Chat0.htm и Chat1.htm показывались только один раз. Как нам это сделать? С помощью переменных. @1 H/ o# w/ `) x+ ~
3 a1 e0 o( a3 t$ y3 [$ }
2 v4 M, l: o: b: pВ каждом квесте строки могут храниться с помощью переменных. Эти переменные сохраняются в Вашей БД. В каждом методе мы можем назначить, прочитать и удалить переменные. Давайте изменим метод onKill, так что бы каждый диалог вызывался только один раз.
) s! @2 ], q T- def onKill (self,npcId,st):1 S9 l n+ X3 {) M
- if npcId == KELTIR_NPC_ID:
6 O6 D# Y# O# }9 J. O7 w- { - n = getCount(st)
& { u5 R2 x2 i - if n == 0:
( E4 E. [, F3 e7 `5 w8 c( Y - if st.get('chat0') == None :
+ M- ^1 ]4 h+ { - st.set("chat0", "true")
9 N: b; V0 L; z - return "Chat0.htm"
8 e4 z5 x" ^1 R6 g; m" v) d7 f - elif n == 1:
, ^+ R) O& W% _2 g# L6 M6 V1 p: H% B - if st.get('chat1') == None :
# K- r5 N! c! B. C$ d! @ - st.set("chat1", "true"): P* z2 Z: U$ r0 A" e% G9 F
- return "Chat1.htm"5 Z1 d$ c3 w' X, G4 z" g# `
- elif n >= 4:
1 a1 h3 @+ X. T) |6 ` - return "Chat4.htm"3 f, u, P: ]. Q5 G+ \
- return "Collected "+str(n)+" of 4 fangs"9 ?; m0 ]+ u, M. m) O7 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.
' ]$ G$ I1 s t. F6 {
! ?9 v) c& G, `! N, ?$ e1 O% B! U y- M
Вот конечный рабочий вариант квеста:- L* j" j k3 Z4 N
- import sys1 d- E# g) ~$ [' l8 [: a4 p" K
- from net.sf.l2j.gameserver.model.quest import State( V4 \- S1 @; ^6 y# h' l! S' C6 I6 ~% N) O
- from net.sf.l2j.gameserver.model.quest import QuestState
' N) G/ U/ u+ m* V4 `3 C7 }% r - from net.sf.l2j.gameserver.model.quest.jython import QuestJython as JQuest5 i& P6 G/ z# Z6 D2 |# i2 h. C0 w
) X, g! y2 _$ E9 V- KELTIR_NPC_ID = 12082
9 P8 @$ \% }5 F+ ? n - FANGS_ITEM_ID = 18598 {: z q, C. E" v
- DROP_RATE = 500000
" e( G) \# J3 r5 D) d
5 j/ H& u, q5 x9 U- WORLD_MAP_ITEM_ID = 1665 K' h+ X p0 ^* N
- % A2 g) `- \1 K" L: q/ ?
- def getCount(st) :
3 I: P3 e9 P. O5 w8 M- ` - return st.getQuestItemsCount(FANGS_ITEM_ID)
+ I0 l6 z' f) v6 l% K$ U - 4 m6 g( C& S% V+ L
- def completed(st) :
+ q3 O9 \. Q7 K5 }! d" Y7 p/ M: s - st.setState(COMPLETED)
; J1 Q- B6 T' X# o; ^- U8 z - st.clearQuestDrops()
) c P0 P" z; F% t8 j - st.takeItems(FANGS_ITEM_ID,-1)
1 ?' J& v# V, ~, k; v - st.giveItems(WORLD_MAP_ITEM_ID,1)9 N+ o" g2 J) K" n8 ?
- st.exitQuest(False)
d) [/ E$ g7 ~ - return
, B ]) `3 X0 J5 v, X - 5 _8 P5 n( ~5 W+ _7 W0 z: ~2 Y5 i6 o
- def check(st) :
: }7 P, F/ _8 J" u$ u0 E - if getCount(st) >= 4 :
$ d5 t$ Q7 g1 ? - completed(st)
9 u c! v A9 q: e1 ~ - return- X, j" ~9 N6 i0 e/ o
- # [4 }8 l3 w9 U$ y& s% k
- class Quest (JQuest):4 J' u. p3 `* |4 v- I
. G5 ], P) o4 e- def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)
# T3 A9 i6 y2 b3 M0 Y - 5 f' d" a/ K; M4 N, v
- def onEvent (self,event,st):
; i% b$ [% C9 R N2 _ - id = st.getState()
* L2 Z, _9 f8 q# w' a4 V, l - if id == CREATED : st.setState(STARTED)8 K4 H" n8 ?' U: f2 H9 Y
- elif id == COMPLETED: pass
8 \ o9 T) ~4 H3 E' o) G - elif id == STARTED : check(st)& E' Y/ b8 g4 T% w+ ^
- return" l' P/ k, t( u2 I7 K+ c
- 8 }+ } S) j5 s, _; u0 h
- def onKill (self,npcId,st): b$ H( E& y/ a, A* j2 `2 C T
- if npcId == KELTIR_NPC_ID:2 T# [0 ?; v& Q! v/ `
- n = getCount(st) x0 b1 e5 U& ^# V, W
- if n == 0:( V9 H4 a8 M$ c( S) u; {
- if st.get('chat0') == None :4 }) c" Z5 n! ?: u+ o
- st.set("chat0", "true"); y- T) J( E8 f+ d; q9 {- Z
- return "Chat0.htm"' S5 \, e- i' v3 D6 t3 }( ^! Q
- elif n == 1:4 U+ ]2 U+ ?- x* ]
- if st.get('chat1') == None :
) C q) z/ s2 t5 J/ P+ z- @ - st.set("chat1", "true")
& j* h3 C) {! ^" C - return "Chat1.htm") b" T# ` q1 u2 m* v
- elif n >= 4:
" P" e& j+ N1 W, ~4 O8 T - return "Chat4.htm"( D' |! @5 A% q) d' i# s- A1 t, x
- return "Collect "+str(n)+" of 4 fangs"; s+ g1 p" k$ W" @1 p
- return/ G# [# g4 ^% p2 t! \
" |- R- W) n7 p- QUEST = Quest(201, "Tutorial", "Tutorial quest")1 Z' {. \+ U8 U
- CREATED = State('Start', QUEST). ]6 _( J- D( G& `; }4 Y1 o
- STARTED = State('Started', QUEST)' p0 {% M( r& {) \/ h8 D
- COMPLETED = State('Completed', QUEST)
k1 h9 j9 R5 }; a7 j4 W
! x. D) B# R2 o4 }: k9 f& e6 s- QUEST.setInitialState(CREATED)# Q0 ~: W% Z! x! p; {* _
- QUEST.addStartNpc(7056)
: u) `9 l0 Z9 i; v - QUEST.addStartNpc(7012)
% e7 ^! t. s% e! M y - QUEST.addStartNpc(7009)8 q2 I; }; P+ X: K' s% ^# z6 a
- QUEST.addStartNpc(7011)
+ S9 V% x+ W6 e5 ~# [- O" D - $ g, u, L' n! ~) A! I
- STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)) \! p. a( d7 O2 T5 X
- STARTED.addKillId(KELTIR_NPC_ID) Y0 w# H. b8 x) B+ F% f6 f( n( n# w
- STARTED.addTalkId(7056)
" V3 }) m! n- m' d ] - STARTED.addTalkI d(7012)! |0 t7 V1 W! b0 d( Q: c% O/ U) c( {# q
- STARTED.addTalkId(7009)5 f5 [% q$ _. m, o
- STARTED.addTalkId(7011)
Скопировать код
1 C$ x. j! p7 d6 L: Y$ ]
& s* y; Z% N; |+ v0 M" ^$ d p$ p n |