Зарегистрируйтесь сейчас чтобы найти еще больше друзей, и получить полноценный доступ ко всем функциям сайта!
Для просмотра Вам необходимо авторизоваться Если Вы еще не зарегистрированы, перейдите по ссылке:Зарегистрироваться
x
Хроники Interlude
/ ~4 Y1 t5 X8 W7 u) {Сборка L2j
3 |4 w; U) h( V, oОбратите внимание: в файле htm стартового NCP обязательно должна быть ссылка на квест:$ X |/ Y- g6 u1 d
- STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код Для этого квеста больше ничего не надо. Все необходимое для корректной работы квеста уже добавили. Вот полный текст квеста:" X' I4 B. z+ m% x
5 k4 y! B2 c0 e" R' z+ J- k% r
- if getCount(st) >= 4 :$ @/ C2 d, M3 Q% n
- completed(st)( _+ i! |. Y! c
- return# m/ |" v" y% K( U: i
2 `! I+ N" }5 U! M/ ?9 T9 D- class Quest (JQuest):$ k+ U2 C. c+ A
- def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)
1 B8 }$ v, E3 U1 j% A5 v - def onEvent (self,event,st):: u9 j8 t: {* |7 i4 N3 c" Q
- id = st.getState()) {2 a! L) E0 o d% C
- if id == CREATED : st.setState(STARTED)
. y ]/ r% C/ K! A: C - elif id == COMPLETED: pass3 g' R8 E/ E* u0 i- V* o
- elif id == STARTED : check(st)
. n) B/ T2 t7 ]0 G( B. n1 n% | - return
3 X3 j, a% Q- `* j* U O, J/ K
! f# q! P2 W7 C( [% N# b- QUEST = Quest(201,"Tutorial", "Tutorial quest")/ ]! I# M- S' d, U1 \1 W* N
- CREATED = State('Start', QUEST); }2 ~; F2 q& O3 G; t
- STARTED = State('Started', QUEST)& a4 X) K- _ p- l) @6 ]- W, \# ~
- COMPLETED = State('Completed', QUEST)' N* b! ~8 y, w9 E
( U5 @3 [1 C) }7 S$ O- QUEST.setInitialState(CREATED)1 R% ?1 l3 Z) z, t6 m
- QUEST.addStartNpc(7056)
' b$ g' h& U9 m1 I - STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код Теперь рассмотрим, как это работает.
5 y q' B, T' y" m$ v0 lИгрок подходит к начальному NCP (в данном случае 7056), нажимает на «Quest». Квест будет создан и состояние квеста перейдет к CREATED и игроку будет показана страничка Start.htm с описанием квеста. Тогда метод onEvent, поле открытия странички Start.htm переведет состояние квеста в STARTED и игроку будет показана страничка Started.htm, где будет опсание того, как найти keltirs и .т.д. H# A( {) X( [' u$ R
' w" H: L* V0 T( K+ C/ e' W: f
4 t' b' Z& F" N
При состоянии STARTED будет зарегистрирован дроп «fangs» при убийстве keltirs. Игрок может вернуться к стартовому NCP и спросить о квесте – метод onEvent будет вызван снова. Если у игрока не хватает необходимого количества предметов, то метод check() не переведет квест в следующее состояние и Started.htm будет показана снова. Но если игрок собрал необходимее количество предметов (в данном случае 4 клыка), то метод check() вызовет метод completed() который переведет квест в новое состояние COMPLETED, заберет все клыки, даст карту мира, т.к. это награда за квест, покажет Completed.htm и завершит квест.* B+ B% _6 q0 C& e5 e2 C4 K
4 i5 e; n8 |: X) A- H
' i. J* L) f g! }5 ~" }. k/ m
Теперь давайте сделаем наш квест более похожим на то, что он должен из себя представлять.
% N( g9 }0 l: B. B3 J. \Прежде всего у нас есть 3 метода для объявления их в Яве – onTalk, onKill и onEvent. Если методы onTalk и onKill не объявлены, то за них все будет делать метод onEvent, т.е. определять квестовых монстров и вызывать диалоги NCP. Есть примечание, методы onTalk и onKill будут вызывать только диалоги с NCP в зависимости от текущего состояния квеста. Метод onKill будет вызываться только тогда, когда мы убиваем квестового монстра.
7 ~5 \5 J i, p3 q& x* N
2 l1 d( Q/ l) Q% F; R
. D0 x1 n( i7 JДавайте рассмотрим как вызывается метод onKill при убийстве keltir в состоянии квеста STARTED:% y' |+ F9 A; s! Q
- STARTED.addKillId(KELTIR_NPC_ID)
Скопировать код и метод onKill в классе Quest:
. a7 d, d5 E" C& y: ^, v& N+ ]' W( a: _9 y6 @ { t- ~. u7 Q0 k
- class Quest (JQuest):& _/ E* J7 K% M8 ?4 U5 J
- ...
6 c6 }7 M" m- B9 w, E& S. Y - def onKill (self,npcId,st):7 X# D6 Y3 r" B- `: F; `- Z
- if npcId == KELTIR_NPC_ID:7 r5 C+ r T9 M- w; G t$ w; L
- n = getCount(st)
3 L5 W5 l# `- F" J' ]. [/ S! H: e - if n == 0:
; ?, h8 f7 z& r, ^5 o6 Y; c - return "Chat0.htm"1 g) e0 y& @3 H+ D. S: y
- elif n == 1:
g% i7 D& @% l# l. m5 B - return "Chat1.htm"
7 @* \+ M5 P; [% E% D- R - elif n >= 4:
: J" f2 P# s4 K - return "Chat4.htm"! `0 @7 {4 ], m1 M
- return "Collected "+str(n)+" of 4 fangs"
- M O, B4 O2 s U1 S1 x' F' @ - return
Скопировать код Метод onKill (а так же метод onTalk) имеет следующие параметры:$ E- ?( l) L- V3 n( g
) B5 g, P; [$ V( U
# f% L5 q S# f4 k# b# _• self – квест
1 t. ^# d% o, Y3 A* m• npcId – ID NCP, которого мы должны убивать (если это метод onTalk, то ID того NCP, с которым мы должны поговорить).
) Q" z3 ~; F$ V• st – текущее состояние игрока.
' f# d1 k6 c `8 }/ u4 v& y* h0 O- t: v
3 N8 e: a7 U( Y. ^
В этом методе мы проверяем и отмечаем, является ли убитый NCP keltir’ом. В основном эта проверка не нужна, т.к. у нас только KELTIR_NPC_ID.
0 ]9 Y2 ]% Q, p- c9 g( z- I( \7 p! T% T# A+ R- x" W
3 z' _$ _. z' i ^Затем проверяем количество предметов (в данном случае количество клыков), и если их вообще нет, то возвращаем строку "Chat0.htm", если только один предмет, то возвращаем строку "Chat1.htm", если же предметов 4 или больше, то "Chat4.htm". Если строка возвращена из методов onEvent, onKill или onTalk, то сервер покажет соответствующие htm. В Chat0.htm может иметь следующий текст: «Вы не имеете ни одного клыка, возвращайтесь позже, когда соберете 4 штуки и бла, бла, бла…», в Chat1.htm может быть следующий текст: «У Вас всего 1 клык, по этому соберите еще…». В Chat4.htm – «Вы собрали необходимое количество предметов, возвращайтесь к вашему тренеру, что бы завершить квест…»0 X( z$ e& g: r" @$ p7 \
6 J" l# L ~; z3 ~- J" h) h" H4 N. r! {+ @/ A
Примечание: если в строка return начинается с "<html>", то будет показана страничка html с текстом, который стоит далее. Так вместо:
~1 k9 q0 E; Q5 l* Lreturn "Chat4.htm". I0 b, d, g/ ~5 q2 f2 Q: `
- N' K8 X" y7 H& J Z0 i, `
; D5 t% p5 w% u; b7 dможно поставить:
: s. z! _7 C# u/ i9 a5 H2 z9 F1 m& }- return "<html><body>Return to your trainer to complete the quest</body></html>"
Скопировать код Так же если строка заканчивается без .htm или в начале нет <html>, то текст будет выведен, как системное сообщение в окне чата. В нашем случае мы сделаем так, что бы при каждом убийстве keltik выводилось системное сообщение: «Собрано N из 4-х клыков».
3 A! U/ H: N) b4 C* i
. b; P) G% P3 h6 l" [0 w" b* m7 ~- P- h D7 X
Наш код для onKill имеет один недостаток. Он будет постоянно показывать Chat0.htm, Chat1.htm и Chat4.htm, нам же необходимо, что бы Chat0.htm и Chat1.htm показывались только один раз. Как нам это сделать? С помощью переменных.7 A# b8 B0 A: Y* Y6 l( o" M$ z' D
) b2 c+ Z) h3 {4 @7 i1 i! r p5 F U' Y6 P$ r4 Q3 `* c( j$ p2 ?) a0 ~4 U
В каждом квесте строки могут храниться с помощью переменных. Эти переменные сохраняются в Вашей БД. В каждом методе мы можем назначить, прочитать и удалить переменные. Давайте изменим метод onKill, так что бы каждый диалог вызывался только один раз.6 ?) ^: T! K4 v- A! q, m9 I/ [8 L
- def onKill (self,npcId,st):+ D2 W" d9 e1 A6 R1 P
- if npcId == KELTIR_NPC_ID:* y" W1 H. x) ~2 e
- n = getCount(st)
8 x, I# Y3 V3 l4 @ - if n == 0:
! ?7 a: h0 N& i L" x - if st.get('chat0') == None :2 M$ \% E* H, P. T
- st.set("chat0", "true")
' |4 P7 o( O2 v. ?5 J. y Q - return "Chat0.htm"2 B' v, a( L: Q7 _" J: `: e# [
- elif n == 1:
1 ] l/ k# V+ a$ w8 b - if st.get('chat1') == None :
7 w" N9 H# D- m$ I$ N) B5 h) [# j - st.set("chat1", "true")- l+ k, m4 B/ M
- return "Chat1.htm"
. g; R5 C5 S; z) Q5 z - elif n >= 4:
) y5 d# b6 G& X) H6 E6 j7 B - return "Chat4.htm"
6 p0 l4 {+ T' b, h: w$ t - return "Collected "+str(n)+" of 4 fangs"
4 I0 O) A/ n6 x, I - return
Скопировать код Если у игрока нет клыков (n=0), то мы получаем занчение переменной 'chat0'. Когда метод onKill вызван в первый раз, то пока ни каких переменных не имеется и python возвращает значение None. В этом случае объявляется переменная и показывается диалог Chat0.htm. Когда мы убиваем keltir, но не получаем с него клык, функция st.get('chat0') возвращает строку true, а не None. И во второй раз окно с Chat0.htm не появится, но в окне чата появится строчка «Collected 0 of 4 fangs». По тому же принципу сделано и с Chat1.htm.
5 l& n: b3 b. ]: }- r
& v G6 ]1 w/ o$ n) _3 s6 @) j5 |& d7 Z$ P/ ~/ |% w
Вот конечный рабочий вариант квеста:
0 F1 [9 O+ ~) t( |1 T/ r$ b- import sys
6 I* F! k( B+ [- R C - from net.sf.l2j.gameserver.model.quest import State
' S# |2 y3 y( ]9 }. G - from net.sf.l2j.gameserver.model.quest import QuestState# s- `$ W9 L9 V; m4 I/ x1 J
- from net.sf.l2j.gameserver.model.quest.jython import QuestJython as JQuest
) J2 W+ _7 n3 v' \6 c* a! [) Y - 0 O8 g6 Q, J! P+ I* V2 V5 M
- KELTIR_NPC_ID = 12082
) t- x4 b4 E6 o8 }8 T @0 a% y - FANGS_ITEM_ID = 1859
[7 R2 W+ q3 O+ L - DROP_RATE = 500000
7 |$ d/ H- `8 P( \3 {3 e, u - 9 e9 K- C% C6 [* [
- WORLD_MAP_ITEM_ID = 1665
- j0 }' C/ t* u# x
( l: o5 c( F8 Q* ~; d- def getCount(st) :
- H+ u' i3 |: X1 s4 m - return st.getQuestItemsCount(FANGS_ITEM_ID)# ^0 Q0 G5 `$ z
- . ?8 r; P; t2 e5 y
- def completed(st) :
0 w: H! {! B5 _3 E6 O e% w2 T/ i - st.setState(COMPLETED), Z9 }: y0 U2 `) E( Q! B3 _! }
- st.clearQuestDrops(); Y' J+ m. C$ n) c6 t e' c
- st.takeItems(FANGS_ITEM_ID,-1)
8 O( r: a; {+ d; T - st.giveItems(WORLD_MAP_ITEM_ID,1)
9 o) i6 c& c1 S! l( ?1 \& X0 b - st.exitQuest(False)2 b+ Z, U; q J0 Q
- return
5 P S7 C+ {# w( K# y3 ~
1 q$ b& k: t7 X: x5 D- def check(st) :
) z6 S- p( \2 o# Z+ ^3 M: L, S - if getCount(st) >= 4 :7 J2 N" H7 o/ P% E) K; y; m
- completed(st)
C- _) \, G1 p - return5 Q% r1 P, ^: [, E0 Z/ e
( @; ?& J1 a" }- class Quest (JQuest):0 y# Y0 C0 v& A4 q; @" W
- 8 W1 \ U H! ]
- def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr) d# g: t$ _4 `7 {5 G
- 0 I$ {: ~8 L2 S, K2 I8 V8 L
- def onEvent (self,event,st):
- t; n: X4 K+ S, N* B A - id = st.getState()1 b$ F& e, ~1 e! ^9 e8 g8 `
- if id == CREATED : st.setState(STARTED)
7 P+ i* y8 { N5 h0 G/ f4 ` - elif id == COMPLETED: pass
4 K: G0 l+ {5 v8 q5 J - elif id == STARTED : check(st) r0 j& T4 t7 T [. T |' w
- return
/ F( u1 i) Y* w& [
( A P; V4 ~6 @5 `+ [- a5 z9 j- x- def onKill (self,npcId,st):/ i6 `: m2 I' m
- if npcId == KELTIR_NPC_ID:2 y" F) w( Q& H' ]- \
- n = getCount(st)
3 i# W' g- W! V8 T1 v: [& a$ Y4 O5 m - if n == 0:0 Y) j) q* }2 f6 i6 F8 l1 E$ t
- if st.get('chat0') == None :
0 y6 \4 B% \, W - st.set("chat0", "true")
$ G! c. t1 \- H! _ - return "Chat0.htm"
3 i8 I- K; |3 P/ o - elif n == 1:
) ~2 h( e& S5 O' a! @/ n: W - if st.get('chat1') == None :
" p _, J @# C' l- ]8 `; v4 \ - st.set("chat1", "true")+ |3 l. r( t2 Y8 c$ X: m: [6 z
- return "Chat1.htm"
* E6 _7 L: ^; l( ] - elif n >= 4:9 \' b, e- m& }
- return "Chat4.htm"& H" _0 h6 J2 y$ e$ t! \# o
- return "Collect "+str(n)+" of 4 fangs"
5 w* l" h M9 A' `$ ] - return) ~* C$ g2 c. t# m
6 J0 f) f4 E5 N% @0 X- QUEST = Quest(201, "Tutorial", "Tutorial quest")
4 W& n: o! |" R: r6 b# ^ - CREATED = State('Start', QUEST), |- e# Q) O: @- Y
- STARTED = State('Started', QUEST)
9 Z) v! K3 I; E5 Q2 w) T. Z5 M - COMPLETED = State('Completed', QUEST)
7 L! K# j( Q* G0 A( `% s6 ^7 q: d - $ c d" Y9 U, A
- QUEST.setInitialState(CREATED)
% {) c5 t( G7 e" b& V& } - QUEST.addStartNpc(7056)5 a5 X& G% t U7 B
- QUEST.addStartNpc(7012)! _" s$ G l6 {8 U
- QUEST.addStartNpc(7009)9 C* Q6 |) o+ X; F8 y
- QUEST.addStartNpc(7011)/ J5 K3 _8 x" i- T
- / L& _0 |: s6 y M9 i$ u; N
- STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)2 x. N% k; o8 e8 w$ ~$ e' Y" g' Y8 u
- STARTED.addKillId(KELTIR_NPC_ID)
% W! q" v" C0 S$ h1 _% I - STARTED.addTalkId(7056)4 T+ u* Q, q- N+ o
- STARTED.addTalkI d(7012), T$ u4 [/ X- r5 C2 p0 T7 l! F
- STARTED.addTalkId(7009)% h% I& v1 P9 B& p, ^* @# H3 p
- STARTED.addTalkId(7011)
Скопировать код
$ {8 q! e6 Y, p/ a1 n! v9 k S6 M
|