Зарегистрируйтесь сейчас чтобы найти еще больше друзей, и получить полноценный доступ ко всем функциям сайта!
Для просмотра Вам необходимо авторизоваться Если Вы еще не зарегистрированы, перейдите по ссылке:Зарегистрироваться
x
Хроники Interlude
8 [( E; {3 Y) p3 [Сборка L2j
! M8 c _1 v6 g. h1 M4 ?2 bОбратите внимание: в файле htm стартового NCP обязательно должна быть ссылка на квест:
9 n! l* x; ]* C+ f# N- STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код Для этого квеста больше ничего не надо. Все необходимое для корректной работы квеста уже добавили. Вот полный текст квеста:( j" K1 ]) H; h
/ {% {, {: Q5 o/ }9 v
- if getCount(st) >= 4 :
1 n& w6 h" ~- g - completed(st), i$ \' e; R) |6 I, R% ^4 U! {7 |
- return
: O, @( q& P- F4 b/ ]! f - : T0 ^) C' H. {+ _+ V& h$ T+ ]; r
- class Quest (JQuest):
) L* M7 q7 S& _& N/ G8 {' f - def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)
- `; z& t2 o4 B, G - def onEvent (self,event,st):
R' d( r! }7 _3 J - id = st.getState()
1 T% F' z- [) H! P b - if id == CREATED : st.setState(STARTED)# p1 V- O3 Z# N3 C
- elif id == COMPLETED: pass
. Z5 ]3 n. u8 P - elif id == STARTED : check(st)% \/ H# w7 G7 |. M2 h
- return
) e* o+ \* f. F0 Z" z3 f0 P( R
; r& A! ^$ k2 S, m& \; m, D- QUEST = Quest(201,"Tutorial", "Tutorial quest") T& B# _- o/ h& Q2 N7 `6 P
- CREATED = State('Start', QUEST)+ I8 X G* k6 W* S8 t% r3 R
- STARTED = State('Started', QUEST)
; J- h* R/ V) ^ - COMPLETED = State('Completed', QUEST)
- N. y q) w4 h - 5 ~, \& w" D5 X+ Z$ z- e: }; }
- QUEST.setInitialState(CREATED)
9 f% O7 b U. \ - QUEST.addStartNpc(7056). @2 ^' h2 x: N9 o4 j" B
- STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код Теперь рассмотрим, как это работает.
1 ~0 c, g9 |- EИгрок подходит к начальному NCP (в данном случае 7056), нажимает на «Quest». Квест будет создан и состояние квеста перейдет к CREATED и игроку будет показана страничка Start.htm с описанием квеста. Тогда метод onEvent, поле открытия странички Start.htm переведет состояние квеста в STARTED и игроку будет показана страничка Started.htm, где будет опсание того, как найти keltirs и .т.д.; o6 N1 ]9 _7 x# |( W* W* D7 h7 o; k
5 n- Q! _+ P3 \: S/ D3 h
: u7 ^5 o. d+ z# a" G) {" lПри состоянии STARTED будет зарегистрирован дроп «fangs» при убийстве keltirs. Игрок может вернуться к стартовому NCP и спросить о квесте – метод onEvent будет вызван снова. Если у игрока не хватает необходимого количества предметов, то метод check() не переведет квест в следующее состояние и Started.htm будет показана снова. Но если игрок собрал необходимее количество предметов (в данном случае 4 клыка), то метод check() вызовет метод completed() который переведет квест в новое состояние COMPLETED, заберет все клыки, даст карту мира, т.к. это награда за квест, покажет Completed.htm и завершит квест.% Q# Q" P& o4 F. h- {6 ]
" o( P* l3 ^1 u2 ^) j7 g8 [' ^0 E& d7 |' n
Теперь давайте сделаем наш квест более похожим на то, что он должен из себя представлять.! u! ?1 L0 d; w" K9 s* p
Прежде всего у нас есть 3 метода для объявления их в Яве – onTalk, onKill и onEvent. Если методы onTalk и onKill не объявлены, то за них все будет делать метод onEvent, т.е. определять квестовых монстров и вызывать диалоги NCP. Есть примечание, методы onTalk и onKill будут вызывать только диалоги с NCP в зависимости от текущего состояния квеста. Метод onKill будет вызываться только тогда, когда мы убиваем квестового монстра.6 k" R8 y4 G, B q
* j# w! q: O0 Y% y8 M' J
( \% W2 X* v: \7 ^7 _
Давайте рассмотрим как вызывается метод onKill при убийстве keltir в состоянии квеста STARTED:+ \: @7 V2 p# S' v9 Y) J# @+ U
- STARTED.addKillId(KELTIR_NPC_ID)
Скопировать код и метод onKill в классе Quest:
2 O& T& W- T. B2 o
5 D; z: l. t2 o G* y* O8 P- class Quest (JQuest):0 R8 X0 z# t9 y! S
- ...3 {3 O" d1 V1 C8 m8 ]2 \4 V
- def onKill (self,npcId,st):
/ F2 x8 [& O( `0 S0 o% J9 _$ X - if npcId == KELTIR_NPC_ID:- y. F4 k7 d9 s6 B
- n = getCount(st)
( K! \1 \1 `8 g* |, M" S& G5 ^ - if n == 0: z3 m3 z/ W& v2 N2 R
- return "Chat0.htm"
8 T6 U1 ~! ]6 d5 D - elif n == 1: L7 k7 D. {( O! n9 _
- return "Chat1.htm"( M" R$ X% w$ o* M# i
- elif n >= 4:5 c' H, R2 s& @# u
- return "Chat4.htm"6 O0 d5 h2 t. R5 i- g8 n- t
- return "Collected "+str(n)+" of 4 fangs"
& x4 k- X! N* l) @ - return
Скопировать код Метод onKill (а так же метод onTalk) имеет следующие параметры:
7 O4 L% L. U3 y6 S, Y8 e5 \- C% S/ W# ?4 t$ @! Y* G
; U- n* K. k" p/ o0 X) z• self – квест% _. S8 m3 N, U: `
• npcId – ID NCP, которого мы должны убивать (если это метод onTalk, то ID того NCP, с которым мы должны поговорить).6 _) W$ @9 i7 [" g$ ^5 }
• st – текущее состояние игрока.. m0 g" `# X, q7 K, W- l6 R' h8 Y6 h: [
$ v( \4 `/ ~( Z0 x8 _ c$ a/ \1 n! D% [
: {$ W$ b4 C0 Z5 O3 Y- r
В этом методе мы проверяем и отмечаем, является ли убитый NCP keltir’ом. В основном эта проверка не нужна, т.к. у нас только KELTIR_NPC_ID.
. ?/ [ [$ {# ]3 C3 n0 w4 [# K' w- w( X, N# x% L! F
V. w: l# y7 ?( @
Затем проверяем количество предметов (в данном случае количество клыков), и если их вообще нет, то возвращаем строку "Chat0.htm", если только один предмет, то возвращаем строку "Chat1.htm", если же предметов 4 или больше, то "Chat4.htm". Если строка возвращена из методов onEvent, onKill или onTalk, то сервер покажет соответствующие htm. В Chat0.htm может иметь следующий текст: «Вы не имеете ни одного клыка, возвращайтесь позже, когда соберете 4 штуки и бла, бла, бла…», в Chat1.htm может быть следующий текст: «У Вас всего 1 клык, по этому соберите еще…». В Chat4.htm – «Вы собрали необходимое количество предметов, возвращайтесь к вашему тренеру, что бы завершить квест…»3 _/ c# E1 w0 W8 J( r7 F
& L1 W) D' s$ p7 r* v5 K2 j. B
: b2 k: Y7 H& jПримечание: если в строка return начинается с "<html>", то будет показана страничка html с текстом, который стоит далее. Так вместо:
4 |/ I; B9 ?4 q/ b0 yreturn "Chat4.htm"/ C9 m7 K8 b" S! }8 r9 V0 Z* h
. U+ x' s6 p/ v. f O$ F
- Y6 k# H O* R; H4 ]можно поставить: v/ @* U: z0 e2 Q b3 N' v
- return "<html><body>Return to your trainer to complete the quest</body></html>"
Скопировать код Так же если строка заканчивается без .htm или в начале нет <html>, то текст будет выведен, как системное сообщение в окне чата. В нашем случае мы сделаем так, что бы при каждом убийстве keltik выводилось системное сообщение: «Собрано N из 4-х клыков».( B- a- U3 F& j* I8 _
7 I# M; ^; k2 x% ?+ Z/ b( Z+ N8 Q8 S# u6 Q2 Q
Наш код для onKill имеет один недостаток. Он будет постоянно показывать Chat0.htm, Chat1.htm и Chat4.htm, нам же необходимо, что бы Chat0.htm и Chat1.htm показывались только один раз. Как нам это сделать? С помощью переменных.
3 d: ? y" V: Q
. N* J. ~' i" O. |7 G; s
; k2 Z: H! J9 o9 G1 \В каждом квесте строки могут храниться с помощью переменных. Эти переменные сохраняются в Вашей БД. В каждом методе мы можем назначить, прочитать и удалить переменные. Давайте изменим метод onKill, так что бы каждый диалог вызывался только один раз.: w; k+ v# n8 r! M/ F+ \# c! }
- def onKill (self,npcId,st): h* a6 S, D$ {' I4 E
- if npcId == KELTIR_NPC_ID:
$ } T! U6 F- u2 d - n = getCount(st)
% ?2 }" j% m% D9 L$ _2 P3 R - if n == 0:4 E* D7 _& G& U9 Y: q# ~
- if st.get('chat0') == None :
6 G: i5 v& w7 Y2 V- E1 P1 Z8 u - st.set("chat0", "true"), D$ q8 M6 |/ ~0 L+ b9 j
- return "Chat0.htm"
7 U9 Y5 N4 s, N' ~+ N' b; c - elif n == 1:3 M" ] G. [9 b E6 x+ E
- if st.get('chat1') == None :
: `. H$ M& W8 h# t5 ~" M - st.set("chat1", "true")
; @' e( Y) U8 N8 `( _ - return "Chat1.htm"
% }0 |6 y/ K9 e% b8 z - elif n >= 4:2 }4 ~+ F {2 q4 K
- return "Chat4.htm"
2 i. M* r8 {1 |( {: y - return "Collected "+str(n)+" of 4 fangs"9 g, I% P; t* \9 ]: `0 v2 }4 X$ S
- return
Скопировать код Если у игрока нет клыков (n=0), то мы получаем занчение переменной 'chat0'. Когда метод onKill вызван в первый раз, то пока ни каких переменных не имеется и python возвращает значение None. В этом случае объявляется переменная и показывается диалог Chat0.htm. Когда мы убиваем keltir, но не получаем с него клык, функция st.get('chat0') возвращает строку true, а не None. И во второй раз окно с Chat0.htm не появится, но в окне чата появится строчка «Collected 0 of 4 fangs». По тому же принципу сделано и с Chat1.htm.
4 n1 X1 }$ `5 i4 V- G: N% ]/ c3 K: m. G$ z$ w( ^! ?
X* b2 i' {# b* Z( e k4 C# kВот конечный рабочий вариант квеста:
( `4 _( L, h1 r# t- import sys! G! }5 y* ?/ P. \
- from net.sf.l2j.gameserver.model.quest import State
" ~# ?+ |5 C* O9 J - from net.sf.l2j.gameserver.model.quest import QuestState
9 C9 U3 O. T% A% f, I: h6 {& Z - from net.sf.l2j.gameserver.model.quest.jython import QuestJython as JQuest4 s& ?& F3 o7 g
' ]$ u( r( M ^3 O# V+ `& C- KELTIR_NPC_ID = 12082
9 E- \& \/ Z" g/ X' k - FANGS_ITEM_ID = 1859
! K- ?5 L8 u- D: X - DROP_RATE = 500000
7 @9 y9 W6 Z4 R4 D" n4 V$ H
7 [4 q/ J! s: `$ o1 X' e6 W, }' k* \1 D- WORLD_MAP_ITEM_ID = 1665, ?* ^& ]: ^% q2 e% v, c' Q$ {
- 1 V8 I U- A- ?- k. [5 h
- def getCount(st) :! Z) k$ k5 q) F, f& @4 q% x
- return st.getQuestItemsCount(FANGS_ITEM_ID); Q0 E2 e3 t( {& u) T+ C
- ) ^. l' X" a$ N, s5 Y. r" q8 H
- def completed(st) :" F4 Z% [! N( `. H) B
- st.setState(COMPLETED)
1 {4 H2 v, r& O9 X& G* u( c) e. z. m, c - st.clearQuestDrops()& r' v+ m# A4 x2 ?& B
- st.takeItems(FANGS_ITEM_ID,-1)$ f5 G! j5 J2 U% g& P
- st.giveItems(WORLD_MAP_ITEM_ID,1)" y% z. ]5 b8 f7 P/ T& S8 h2 b3 F1 _
- st.exitQuest(False)
: m, G/ f0 {$ V" h% g& o+ ] - return/ ]2 m l! U) H
- h& G2 B( p( w# H" q8 O" U0 R- def check(st) :$ x3 ]' g; @! S4 |: ^! H ~
- if getCount(st) >= 4 :
- E: y9 f! L h8 A- a - completed(st)
* F' F) G7 Z4 K - return
0 f* y1 T4 {; L/ X8 `) d9 M - ! ~4 @$ J: A' x
- class Quest (JQuest):
: b; ~, Y8 n! ~ - " I- f! z6 i- \8 v
- def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)6 s; g+ T" Z% Y8 w( X# ]# {+ G
- - h1 l9 Y2 ^/ J
- def onEvent (self,event,st):
5 F j2 v2 l I' g' d3 { - id = st.getState()
% Z! y8 R) S$ |7 V3 Z& _ - if id == CREATED : st.setState(STARTED)
# _8 [1 |' m" O2 K: g - elif id == COMPLETED: pass
]! g# J# P5 w# @ - elif id == STARTED : check(st)* s, J' D& w& F3 R$ T
- return
% g, U: H' o; S9 ?+ y* w
+ z+ `. k' R( U( S' t( J* h9 \: F; O- def onKill (self,npcId,st):
0 O! e) I+ I" c' N0 G1 ~- U; F - if npcId == KELTIR_NPC_ID:
; s; G. `7 K4 | - n = getCount(st)
9 Z/ e7 }, ~$ X `; X# g g - if n == 0:* M/ j' \5 O L1 i/ i6 B2 p6 H* O
- if st.get('chat0') == None :0 z3 [# f7 q4 }* M& N+ \
- st.set("chat0", "true")# I5 p$ |: W1 d, L( p
- return "Chat0.htm"0 H4 D1 r# H- U$ J0 A3 f/ [
- elif n == 1:/ B @5 j9 {, O$ H9 \
- if st.get('chat1') == None :
) \7 u2 h r' L2 @2 j, X( {- D - st.set("chat1", "true")& l$ n! n! U9 n2 j
- return "Chat1.htm"2 e7 W5 b: v/ r7 I
- elif n >= 4:1 ?! r1 @' e& o
- return "Chat4.htm"
- [+ ~. O, B' G) [2 F+ @. P - return "Collect "+str(n)+" of 4 fangs"# X: ? C/ w) V
- return
" A+ w% L! o, w$ V& r1 H - ) e+ D0 x+ K% r+ G% S1 h. }4 F: k# f
- QUEST = Quest(201, "Tutorial", "Tutorial quest")8 F3 s" C8 {- e; V
- CREATED = State('Start', QUEST): n# K3 _; }4 y$ h$ n1 _- I
- STARTED = State('Started', QUEST)" T$ I E) P# z/ M3 T
- COMPLETED = State('Completed', QUEST)
1 b8 ~* K5 V: w7 D, T P
5 J( g+ V: ?, D- QUEST.setInitialState(CREATED)
$ H. _! v, q; t9 b" ^. \# |4 W* i+ @- l - QUEST.addStartNpc(7056) |( _7 N9 e/ ]' ^* f; F7 J
- QUEST.addStartNpc(7012)3 z# h' S; b4 R0 {9 I5 U1 N8 W
- QUEST.addStartNpc(7009)8 K& O$ k7 S; i( B. N
- QUEST.addStartNpc(7011)
+ j ~2 E, q# G6 { - ) W! B# D4 @( d( |* c2 I5 z9 b( X/ @4 `
- STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)9 I' F" {4 A5 w0 l! J$ o
- STARTED.addKillId(KELTIR_NPC_ID)
3 m! F/ F: q) `4 j2 \2 } - STARTED.addTalkId(7056)+ o- g+ O8 D8 S" Z
- STARTED.addTalkI d(7012)
$ k. t7 y& X5 b# F2 o: p - STARTED.addTalkId(7009); W. K2 x1 M3 j/ Y. D1 @+ z( G
- STARTED.addTalkId(7011)
Скопировать код 3 w' C( i* T! x$ j. P: h7 G3 _7 y
7 E. ]2 ^: t. a2 {2 ^0 _ |