Зарегистрируйтесь сейчас чтобы найти еще больше друзей, и получить полноценный доступ ко всем функциям сайта!
Для просмотра Вам необходимо авторизоваться Если Вы еще не зарегистрированы, перейдите по ссылке:Зарегистрироваться
x
Хроники Interlude
. ~1 @2 E3 ^4 mСборка L2j
9 d; Z! G: v$ IОбратите внимание: в файле htm стартового NCP обязательно должна быть ссылка на квест:- e( ?$ ]7 o% K- G
- STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код Для этого квеста больше ничего не надо. Все необходимое для корректной работы квеста уже добавили. Вот полный текст квеста:
8 T! w3 U" Z/ I4 E0 @: l( x
9 i/ x" h/ \+ Z8 _4 `- if getCount(st) >= 4 :
: l* p& e7 x4 z5 W& u8 F - completed(st)' k2 j4 v0 M' l8 j8 b; b* s1 e- J5 E
- return1 T8 L- W0 ~3 @! t% W0 z
- 6 e6 m0 ?7 J$ O2 m: ^0 J
- class Quest (JQuest):
1 E2 T) h7 G+ \ - def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)- b. m( u3 }4 y' f' C: h" e
- def onEvent (self,event,st):
6 [+ C1 @. _: Y1 F, y, T: W - id = st.getState()$ s7 U' Z8 n) k! f/ h$ r
- if id == CREATED : st.setState(STARTED)$ n- a2 c4 ]2 F; w2 d) Q
- elif id == COMPLETED: pass
7 t! f6 r! B6 Y - elif id == STARTED : check(st)! P. q! j; D4 G, l/ c; V2 G' q# W( d
- return
7 S' |! j2 C$ `7 T/ n+ t r - . F4 h) o6 e% l ~" a
- QUEST = Quest(201,"Tutorial", "Tutorial quest")
# h6 U2 x/ l) f6 k! C3 g0 x - CREATED = State('Start', QUEST)
& [) e1 e' f0 U9 ^; M2 h - STARTED = State('Started', QUEST)) a/ `. S$ J8 {! Z8 g, I7 l
- COMPLETED = State('Completed', QUEST)
0 v) J+ Y1 I, [& H, [8 Z# @ - 9 L4 W5 I; B4 z7 v
- QUEST.setInitialState(CREATED)0 X" U: X3 ^: ]; \
- QUEST.addStartNpc(7056). h4 t8 r9 t. Q% I
- STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код Теперь рассмотрим, как это работает.
/ L6 }4 [$ G) `( }Игрок подходит к начальному NCP (в данном случае 7056), нажимает на «Quest». Квест будет создан и состояние квеста перейдет к CREATED и игроку будет показана страничка Start.htm с описанием квеста. Тогда метод onEvent, поле открытия странички Start.htm переведет состояние квеста в STARTED и игроку будет показана страничка Started.htm, где будет опсание того, как найти keltirs и .т.д.0 I* F5 @9 h/ ~( Z
# M) q& `: p* a3 I1 _ e8 N1 s9 C5 X) \. E: u: f9 A
При состоянии STARTED будет зарегистрирован дроп «fangs» при убийстве keltirs. Игрок может вернуться к стартовому NCP и спросить о квесте – метод onEvent будет вызван снова. Если у игрока не хватает необходимого количества предметов, то метод check() не переведет квест в следующее состояние и Started.htm будет показана снова. Но если игрок собрал необходимее количество предметов (в данном случае 4 клыка), то метод check() вызовет метод completed() который переведет квест в новое состояние COMPLETED, заберет все клыки, даст карту мира, т.к. это награда за квест, покажет Completed.htm и завершит квест.
( w2 R3 [# W& X2 w% S6 |# q: @& e1 M; h& f1 n H
! O- G/ t" e, F
Теперь давайте сделаем наш квест более похожим на то, что он должен из себя представлять.
7 A' ? o% z1 b; F2 l) V( R$ zПрежде всего у нас есть 3 метода для объявления их в Яве – onTalk, onKill и onEvent. Если методы onTalk и onKill не объявлены, то за них все будет делать метод onEvent, т.е. определять квестовых монстров и вызывать диалоги NCP. Есть примечание, методы onTalk и onKill будут вызывать только диалоги с NCP в зависимости от текущего состояния квеста. Метод onKill будет вызываться только тогда, когда мы убиваем квестового монстра.
" T: q0 r% o% b! W" e# j- C+ C& l; K/ T) E
W. c* y- L! l6 z
Давайте рассмотрим как вызывается метод onKill при убийстве keltir в состоянии квеста STARTED:* ^+ j9 O: p: P$ I* _) V% N: u
- STARTED.addKillId(KELTIR_NPC_ID)
Скопировать код и метод onKill в классе Quest:4 W1 n7 O h7 H! W
! T8 b, J1 ?" G: Q7 D3 B8 o- class Quest (JQuest):
# L% p: l' o8 f8 d/ ? - ...
" l3 b' |) k( ^ B: \$ B: |5 G - def onKill (self,npcId,st):8 ?4 A! m( }# w4 [, _
- if npcId == KELTIR_NPC_ID:# Z6 Z e+ u( y# h
- n = getCount(st)
2 o$ R l1 z$ e( e9 @( m' o - if n == 0:3 U6 d/ U/ }5 W; u
- return "Chat0.htm"
# H6 W& ]/ L, N: h: G3 i. Y - elif n == 1:3 D0 k7 }7 v- x6 T8 k" v
- return "Chat1.htm"
& ^4 v3 V4 J: _% R9 ^; `/ d7 M0 [$ w - elif n >= 4:. D9 E& [& E: `2 t; o9 h4 Z
- return "Chat4.htm"* @, y( K2 @8 R% p5 ~
- return "Collected "+str(n)+" of 4 fangs"
8 Y' n k) I& ]2 ?: A* M - return
Скопировать код Метод onKill (а так же метод onTalk) имеет следующие параметры:& z/ b: c6 y9 Q& v/ i# d3 L# o
2 d/ \! A* o8 M# W4 w8 `
' ^; V; p3 r3 n0 S, T3 b• self – квест4 h7 B% H: K. b8 ]4 O1 z
• npcId – ID NCP, которого мы должны убивать (если это метод onTalk, то ID того NCP, с которым мы должны поговорить).7 f0 |8 `1 p- A) T1 I
• st – текущее состояние игрока.
$ O- r6 a, j$ ~& q$ Q' Q- ?2 q: \; `, E5 v: I* [
2 O* W: i3 Z F0 tВ этом методе мы проверяем и отмечаем, является ли убитый NCP keltir’ом. В основном эта проверка не нужна, т.к. у нас только KELTIR_NPC_ID.
8 H a0 Q6 B7 K# E4 e
% j% [" O, l4 T9 [& V; C2 l+ ]; }/ E D7 s9 |
Затем проверяем количество предметов (в данном случае количество клыков), и если их вообще нет, то возвращаем строку "Chat0.htm", если только один предмет, то возвращаем строку "Chat1.htm", если же предметов 4 или больше, то "Chat4.htm". Если строка возвращена из методов onEvent, onKill или onTalk, то сервер покажет соответствующие htm. В Chat0.htm может иметь следующий текст: «Вы не имеете ни одного клыка, возвращайтесь позже, когда соберете 4 штуки и бла, бла, бла…», в Chat1.htm может быть следующий текст: «У Вас всего 1 клык, по этому соберите еще…». В Chat4.htm – «Вы собрали необходимое количество предметов, возвращайтесь к вашему тренеру, что бы завершить квест…»# X2 O: A- }2 W9 v7 [
6 m5 C$ w2 u. H
( v p# l$ g& l7 ?Примечание: если в строка return начинается с "<html>", то будет показана страничка html с текстом, который стоит далее. Так вместо:1 q0 A7 F( ~3 E( M$ p3 N
return "Chat4.htm"
) _, B" t& }9 I7 M7 Z$ i6 C9 i5 v" p( z$ L N
0 M: I+ o# p) u2 d5 Q- L* ?
можно поставить:' w, i' v7 J/ k- x0 M$ {
- return "<html><body>Return to your trainer to complete the quest</body></html>"
Скопировать код Так же если строка заканчивается без .htm или в начале нет <html>, то текст будет выведен, как системное сообщение в окне чата. В нашем случае мы сделаем так, что бы при каждом убийстве keltik выводилось системное сообщение: «Собрано N из 4-х клыков».; z j+ Z& v1 }8 R ]/ [: f
6 |- y y% E% ]1 u1 O q
4 m1 I" q0 s9 |' D" \. U
Наш код для onKill имеет один недостаток. Он будет постоянно показывать Chat0.htm, Chat1.htm и Chat4.htm, нам же необходимо, что бы Chat0.htm и Chat1.htm показывались только один раз. Как нам это сделать? С помощью переменных.
/ m- z6 L- Y3 V3 u _9 \( V% S8 |2 {' o7 Q n- r* H; [
6 ~9 P/ s% J1 t, L0 h) AВ каждом квесте строки могут храниться с помощью переменных. Эти переменные сохраняются в Вашей БД. В каждом методе мы можем назначить, прочитать и удалить переменные. Давайте изменим метод onKill, так что бы каждый диалог вызывался только один раз.
+ { ^/ b- B8 P6 y0 h- def onKill (self,npcId,st):
$ ~. b. v& o. g/ j - if npcId == KELTIR_NPC_ID:
( N' e; A0 K: J o - n = getCount(st)
- ]1 [. d5 X4 @, O+ a+ R - if n == 0:
+ R5 f8 m/ P, P C - if st.get('chat0') == None :
) [! ]0 ]. q( T1 @* D) M - st.set("chat0", "true")& _9 Z8 W- n9 a) P) c6 c
- return "Chat0.htm"
+ e/ k7 C4 ^8 k - elif n == 1:
9 y' \$ B9 `5 ]& M) c/ b! |& } - if st.get('chat1') == None :4 l4 v% m1 A X8 B) ~2 L" v
- st.set("chat1", "true")
& `. B) d p, C- U/ S! l - return "Chat1.htm"
( s- i( _) f; _2 T - elif n >= 4:5 ^" Z. E' I+ X3 E
- return "Chat4.htm", @- M5 V9 r. G, l; d" Y. ?
- return "Collected "+str(n)+" of 4 fangs"
) Y( N! `! B8 Z/ I+ Z0 v- }( t - return
Скопировать код Если у игрока нет клыков (n=0), то мы получаем занчение переменной 'chat0'. Когда метод onKill вызван в первый раз, то пока ни каких переменных не имеется и python возвращает значение None. В этом случае объявляется переменная и показывается диалог Chat0.htm. Когда мы убиваем keltir, но не получаем с него клык, функция st.get('chat0') возвращает строку true, а не None. И во второй раз окно с Chat0.htm не появится, но в окне чата появится строчка «Collected 0 of 4 fangs». По тому же принципу сделано и с Chat1.htm.) v5 F+ O7 r1 [0 D# P
0 f) V1 c+ V" f8 P+ O
4 C5 s0 o5 \+ x) j0 GВот конечный рабочий вариант квеста:
1 J* ^5 t& B8 H: _# ~# D1 V- import sys
s9 h2 r- d& N. h( m4 g% {# f - from net.sf.l2j.gameserver.model.quest import State
# k1 e7 \2 Z# w) M. b9 t% v, P - from net.sf.l2j.gameserver.model.quest import QuestState& O i4 Y2 R: i3 F
- from net.sf.l2j.gameserver.model.quest.jython import QuestJython as JQuest" x) [% _ o8 A2 D' n
- ; V' J- s7 L( z! B$ L6 l
- KELTIR_NPC_ID = 12082
5 K7 H0 r/ ~% [3 ]% t7 a9 g - FANGS_ITEM_ID = 1859
`) g2 U7 k Y% l; ` - DROP_RATE = 5000009 q+ P1 ? Q0 A1 X9 M
- 0 s" Q9 ]& t" ~7 x* x' D
- WORLD_MAP_ITEM_ID = 1665
0 o3 B! K5 s7 P$ [ - , y5 t' R/ P. a( m# d6 D, n
- def getCount(st) :
% N) _, o' H) E+ U% T, i - return st.getQuestItemsCount(FANGS_ITEM_ID)6 i4 ^2 F, v- `( f9 p, R% Y0 l
- ) Q* Y1 M- D) m8 D5 Q4 F' C- U
- def completed(st) :. _6 b; y+ k. d( p$ o1 ~
- st.setState(COMPLETED)( w" m a6 D) p: r$ `0 t
- st.clearQuestDrops()
* H7 f$ L2 C0 |/ K# u0 l5 ~6 ]8 u$ @ - st.takeItems(FANGS_ITEM_ID,-1)
! j' P% G- y6 S0 F* f3 ?- J. s2 e - st.giveItems(WORLD_MAP_ITEM_ID,1)
1 T% W/ @9 p* p9 }1 W* z3 G - st.exitQuest(False): ~8 y( b+ @( O1 ~" a: _+ B
- return( ` I2 \2 D4 ]- I: B% z7 _* I
- ! L; O; s7 W9 V* l; E2 h" H4 [
- def check(st) :" v2 }, E, g, ^( v: p7 G/ L% W
- if getCount(st) >= 4 :7 C$ k9 h; q5 ~3 c" ]: m" K
- completed(st)- e: T6 z7 A& H& L& d
- return
0 y3 I. B% Z9 E$ p, x6 D - o6 O. N. E' ?- ~* w! i% ?* w
- class Quest (JQuest):
/ |8 k+ }+ e. ~3 M: {* j0 u0 ` - # T- L' f3 M1 i& W+ d
- def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)# x9 {; k; s0 M' q9 |
- & c# S! ]' {% F( _$ X
- def onEvent (self,event,st):
4 D+ Q# w% d! K$ Z- x9 ^% Z9 A - id = st.getState()
- G, T1 J2 f! W6 b! n - if id == CREATED : st.setState(STARTED)
1 s# {2 t5 e" Z" c+ n" P1 H - elif id == COMPLETED: pass
6 M) Y1 N% j1 Q - elif id == STARTED : check(st)7 K& P: _0 g7 D" I( [# Y( w
- return
- r1 ~; `+ P0 n: X: X. B8 R - ! M4 F! ^0 q+ Z, W! M) I0 ~1 {
- def onKill (self,npcId,st):
$ p) }) {* T4 u' `; S - if npcId == KELTIR_NPC_ID:
" C5 W# U/ h$ T: s - n = getCount(st)
& Y9 _3 C$ W3 w+ {& k& g - if n == 0:
; R1 d% X. G: U. X- ]5 t8 L5 J - if st.get('chat0') == None :5 ?# F. p/ \5 y5 r( {; F
- st.set("chat0", "true")
7 o- q0 Y3 T1 l. O - return "Chat0.htm"
+ o! A7 y/ Z b+ e: D - elif n == 1: k9 e; [+ X1 _5 E4 N2 I% W
- if st.get('chat1') == None :
9 }+ ~/ a0 k b q* H- j - st.set("chat1", "true")) f1 S, r; G2 R
- return "Chat1.htm"8 O/ ~6 M: u* U% G2 k1 `7 C6 f- F
- elif n >= 4:4 Z( @2 x- y5 r, c9 K% B
- return "Chat4.htm" q' N+ Q, h9 v5 A% {& c
- return "Collect "+str(n)+" of 4 fangs"( g# w: q3 Q% t& I
- return
: n. ^* E# O$ _9 Q% n
. a, S; Y3 [7 N2 j! g7 v" Q- QUEST = Quest(201, "Tutorial", "Tutorial quest")) Q$ m, w4 ~* f' B3 x- v
- CREATED = State('Start', QUEST)
4 c& E1 c* T) ?& \3 o - STARTED = State('Started', QUEST)
6 d4 g- J g( n9 i8 T1 ^+ ` - COMPLETED = State('Completed', QUEST)
; W5 X$ K% f& J& w& z' \ - ' d0 B5 g9 w3 X* H
- QUEST.setInitialState(CREATED)
5 i0 Z) @* a% ~ - QUEST.addStartNpc(7056)) `1 z0 C% B: y; M" u
- QUEST.addStartNpc(7012)$ u' M$ Q; H- Z9 P7 ^+ e. R' I, Z
- QUEST.addStartNpc(7009)
! T# q% l' v/ o& J7 g8 ?* v, ] - QUEST.addStartNpc(7011)
1 F2 j+ \; P/ d, l# d - 4 B9 I; \4 o+ T& _
- STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
4 o8 H1 P2 o' z, l/ I% b' l - STARTED.addKillId(KELTIR_NPC_ID)
; ?6 r8 P" a+ }" _1 q+ h% e% I - STARTED.addTalkId(7056)
' N: l3 p# t U/ K9 s - STARTED.addTalkI d(7012)
) I* w+ [: w+ Q/ Q - STARTED.addTalkId(7009)# J Z$ v# h' u" I- F3 v
- STARTED.addTalkId(7011)
Скопировать код
: |: |% i1 A# g" t- x1 y/ }# P6 \% s% _7 X
|