Зарегистрируйтесь сейчас чтобы найти еще больше друзей, и получить полноценный доступ ко всем функциям сайта!
Для просмотра Вам необходимо авторизоваться Если Вы еще не зарегистрированы, перейдите по ссылке:Зарегистрироваться
x
Хроники Interlude/ W* B5 i5 D6 j
Сборка L2j" J0 p: F7 p) I' h8 |# p
Обратите внимание: в файле htm стартового NCP обязательно должна быть ссылка на квест:) g4 C ?) k& c+ q7 e& {9 h
- STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код Для этого квеста больше ничего не надо. Все необходимое для корректной работы квеста уже добавили. Вот полный текст квеста:
/ t' i6 B" ~" B( L3 N0 B! ]6 @2 N$ [' d- G7 m) h) o
- if getCount(st) >= 4 :
, e+ X# [+ P9 U - completed(st)3 b! ]4 B2 e" _9 d4 R# a8 \! k
- return) @0 w6 J4 B* `, U2 i/ P/ U
- 9 O. c5 m2 u* ~+ e) ^
- class Quest (JQuest):& E! h9 d, t* g) f3 M6 p
- def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)
; |4 R# R( t: n7 M$ D! \8 T - def onEvent (self,event,st):
$ T# q9 `% X/ q1 }+ r - id = st.getState()& x7 e5 @7 ^ {8 A+ u: S
- if id == CREATED : st.setState(STARTED)
) |# V4 z$ H1 H+ n) L5 M; w - elif id == COMPLETED: pass. G; h; _$ ^" U( _) q
- elif id == STARTED : check(st)1 J1 J6 f h$ Z
- return' q6 A9 d+ T$ m% M; J ~! O- U
- * R2 u( v E1 s& s% |1 k5 z4 T. r
- QUEST = Quest(201,"Tutorial", "Tutorial quest")4 z1 z3 N j U; ]
- CREATED = State('Start', QUEST): F/ {1 p2 X/ Q1 _ _
- STARTED = State('Started', QUEST)* F# G9 p% m& O
- COMPLETED = State('Completed', QUEST)5 w) d1 ^7 ]& T! m: d6 i
! F+ |# `5 C J0 e' x- QUEST.setInitialState(CREATED), _, @" n6 i/ b; g4 n) A
- QUEST.addStartNpc(7056), ^. E4 J! }2 \: A3 z1 [* d1 A
- STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код Теперь рассмотрим, как это работает.
# f. c% b- ~- o$ O% q) qИгрок подходит к начальному NCP (в данном случае 7056), нажимает на «Quest». Квест будет создан и состояние квеста перейдет к CREATED и игроку будет показана страничка Start.htm с описанием квеста. Тогда метод onEvent, поле открытия странички Start.htm переведет состояние квеста в STARTED и игроку будет показана страничка Started.htm, где будет опсание того, как найти keltirs и .т.д.3 F1 s5 [( P$ V9 I0 A. n
/ U0 e9 | I8 u# o$ r r4 P% @
. M! Q7 T' e6 {" \При состоянии STARTED будет зарегистрирован дроп «fangs» при убийстве keltirs. Игрок может вернуться к стартовому NCP и спросить о квесте – метод onEvent будет вызван снова. Если у игрока не хватает необходимого количества предметов, то метод check() не переведет квест в следующее состояние и Started.htm будет показана снова. Но если игрок собрал необходимее количество предметов (в данном случае 4 клыка), то метод check() вызовет метод completed() который переведет квест в новое состояние COMPLETED, заберет все клыки, даст карту мира, т.к. это награда за квест, покажет Completed.htm и завершит квест.. n3 v9 G- a. q; c7 X
5 E P3 q7 n/ L, G6 C$ [; w
! b. f$ A2 l! DТеперь давайте сделаем наш квест более похожим на то, что он должен из себя представлять.& Z/ [0 A& p/ s, d
Прежде всего у нас есть 3 метода для объявления их в Яве – onTalk, onKill и onEvent. Если методы onTalk и onKill не объявлены, то за них все будет делать метод onEvent, т.е. определять квестовых монстров и вызывать диалоги NCP. Есть примечание, методы onTalk и onKill будут вызывать только диалоги с NCP в зависимости от текущего состояния квеста. Метод onKill будет вызываться только тогда, когда мы убиваем квестового монстра.+ k8 V. p6 U* G- }1 O
) @# i5 v: _* F3 x1 g7 F9 g) q/ S$ b( u5 T) h0 ?
Давайте рассмотрим как вызывается метод onKill при убийстве keltir в состоянии квеста STARTED: I# [4 T* f+ M( `$ ]6 g
- STARTED.addKillId(KELTIR_NPC_ID)
Скопировать код и метод onKill в классе Quest:( @4 c" S9 @; r, J0 V" d2 `9 M8 Z
4 K8 S6 V/ L- h& P
- class Quest (JQuest):, [& z' z0 |: w. K4 }
- ...6 \/ C y7 e8 ?( t
- def onKill (self,npcId,st):
# N; K* A" }0 e+ z% ]) _ - if npcId == KELTIR_NPC_ID:
% c4 I' J1 e* \9 F - n = getCount(st)
2 L9 C, W, e5 N5 L) g- ]. | - if n == 0: Y7 h, S ]6 ` V
- return "Chat0.htm"1 J9 X z! H) U1 d- \
- elif n == 1:* g4 _0 ^8 i9 h
- return "Chat1.htm"
; H/ u- b0 p" d" @ - elif n >= 4:0 Y8 J4 b: \# H2 |$ k! J2 ?
- return "Chat4.htm"
1 A/ O, ~. x3 F3 t3 C7 R0 P - return "Collected "+str(n)+" of 4 fangs", a5 P9 V; R, l" r& X
- return
Скопировать код Метод onKill (а так же метод onTalk) имеет следующие параметры:- W' X; g3 y% m* g3 h
5 F2 N Y Q H$ M, N
% ?, y0 G$ c" J0 g% o• self – квест
$ n8 w, j+ f0 Q& U( T7 i• npcId – ID NCP, которого мы должны убивать (если это метод onTalk, то ID того NCP, с которым мы должны поговорить).. K g. h$ y$ V, c0 T, J
• st – текущее состояние игрока.4 O4 n7 R7 A: V$ T9 t
/ ~* w5 P4 T/ g3 v* ~
- d2 _3 l' q9 j3 R
В этом методе мы проверяем и отмечаем, является ли убитый NCP keltir’ом. В основном эта проверка не нужна, т.к. у нас только KELTIR_NPC_ID.
- K9 f& `* }. `3 u# ~' r* D# _% ?) ~ o* I4 E" n
0 W3 H/ d8 X0 T: VЗатем проверяем количество предметов (в данном случае количество клыков), и если их вообще нет, то возвращаем строку "Chat0.htm", если только один предмет, то возвращаем строку "Chat1.htm", если же предметов 4 или больше, то "Chat4.htm". Если строка возвращена из методов onEvent, onKill или onTalk, то сервер покажет соответствующие htm. В Chat0.htm может иметь следующий текст: «Вы не имеете ни одного клыка, возвращайтесь позже, когда соберете 4 штуки и бла, бла, бла…», в Chat1.htm может быть следующий текст: «У Вас всего 1 клык, по этому соберите еще…». В Chat4.htm – «Вы собрали необходимое количество предметов, возвращайтесь к вашему тренеру, что бы завершить квест…»/ X, { _" `7 W) D
- r# L6 u' v/ f5 _0 ~6 b s4 l2 ]1 K5 o
Примечание: если в строка return начинается с "<html>", то будет показана страничка html с текстом, который стоит далее. Так вместо:
2 t1 e8 \) I; A; [. J) l8 `4 Dreturn "Chat4.htm"
8 Z: |, n+ ]5 k( B0 r
$ }; u" o4 S5 W2 P! g7 ^, l9 G" v2 ?# r
можно поставить:& E. v K" O/ i* ]- X) O
- return "<html><body>Return to your trainer to complete the quest</body></html>"
Скопировать код Так же если строка заканчивается без .htm или в начале нет <html>, то текст будет выведен, как системное сообщение в окне чата. В нашем случае мы сделаем так, что бы при каждом убийстве keltik выводилось системное сообщение: «Собрано N из 4-х клыков».3 o' Y, i8 Q1 \8 b7 `% V
8 g/ k8 a( V6 i
T# X$ ?+ S3 u1 }Наш код для onKill имеет один недостаток. Он будет постоянно показывать Chat0.htm, Chat1.htm и Chat4.htm, нам же необходимо, что бы Chat0.htm и Chat1.htm показывались только один раз. Как нам это сделать? С помощью переменных.
& G" i8 F& P) q7 h% g
1 [! g- l* M8 u& c) f( X$ B% y* c3 {: Z9 t, ]3 N; ?; f
В каждом квесте строки могут храниться с помощью переменных. Эти переменные сохраняются в Вашей БД. В каждом методе мы можем назначить, прочитать и удалить переменные. Давайте изменим метод onKill, так что бы каждый диалог вызывался только один раз.0 h' y2 R9 l8 |: @- P4 h: r
- def onKill (self,npcId,st):2 q1 _& z# b! Q& O: ]# l
- if npcId == KELTIR_NPC_ID:
+ Y& t" w2 S U2 o - n = getCount(st)$ q; u3 s. g' o1 W2 y9 E" F. p
- if n == 0:- K3 r) v. X a$ \2 P- ]
- if st.get('chat0') == None :
N2 `* k4 [, d% o: w. ^7 {$ H - st.set("chat0", "true"), |7 \$ o( m1 h! u. c
- return "Chat0.htm"
6 f* g" C0 S0 P( t# z - elif n == 1:
" }+ Z! k. S/ R, r - if st.get('chat1') == None :
g* c$ J5 }* U6 a. g* |; B) U* g - st.set("chat1", "true")# P* ?) T; N& {5 q2 p$ R9 t F
- return "Chat1.htm"( ~9 K* i* M% H) W. ~
- elif n >= 4:
" _, {9 S! i! g0 N( H j - return "Chat4.htm"
- u3 j- U" T; h - return "Collected "+str(n)+" of 4 fangs"8 ^# [2 r ?* I n
- return
Скопировать код Если у игрока нет клыков (n=0), то мы получаем занчение переменной 'chat0'. Когда метод onKill вызван в первый раз, то пока ни каких переменных не имеется и python возвращает значение None. В этом случае объявляется переменная и показывается диалог Chat0.htm. Когда мы убиваем keltir, но не получаем с него клык, функция st.get('chat0') возвращает строку true, а не None. И во второй раз окно с Chat0.htm не появится, но в окне чата появится строчка «Collected 0 of 4 fangs». По тому же принципу сделано и с Chat1.htm.2 c' ^) J; Q5 w' D; h# F
( q/ W1 Z; Z- Q; n' N! p7 O5 }! c7 _3 P
Вот конечный рабочий вариант квеста:7 p% ~8 |- O5 S x
- import sys
6 ]4 Q- M4 x/ ^% U7 r - from net.sf.l2j.gameserver.model.quest import State
3 @% u' ^6 v( ~ - from net.sf.l2j.gameserver.model.quest import QuestState; _4 c( N8 M! e) d8 Q$ C
- from net.sf.l2j.gameserver.model.quest.jython import QuestJython as JQuest- P D t' C3 ^ H3 o
9 l! v3 E# \+ Z- KELTIR_NPC_ID = 12082
! t1 L6 I9 e9 ]& c# y - FANGS_ITEM_ID = 1859
% @2 a' W5 I& L# a3 L' X - DROP_RATE = 5000000 t6 y/ I5 ~$ \
- \6 I I% P, l
- WORLD_MAP_ITEM_ID = 1665
" g! F& P( l9 a' W0 [- W
- T# ]8 y0 c! B2 Q- def getCount(st) :
! |7 A+ F- P) q% r2 C1 t% i9 o! x - return st.getQuestItemsCount(FANGS_ITEM_ID)1 p& M' V. C" ~0 x
- ; O/ Z7 `9 |+ n1 ^
- def completed(st) :
5 v/ p8 w5 j. _ - st.setState(COMPLETED)
4 K! O. \% ~( s! D: m - st.clearQuestDrops()( L4 ?8 X0 ~$ [
- st.takeItems(FANGS_ITEM_ID,-1)% Y* Q) N) G5 ]9 U' Y5 r
- st.giveItems(WORLD_MAP_ITEM_ID,1)
) M5 H6 {. Z, q% [ - st.exitQuest(False)2 H! P# |; Q5 q' T; C1 y; J1 u
- return
& Z2 d4 G; N1 {6 U8 T- W) f9 ^ - ; l/ ^6 l$ E' p* i3 i" J6 o* K
- def check(st) :
6 \3 q9 K N( J - if getCount(st) >= 4 :( ~0 e$ H% K7 ~; J- B: s" T
- completed(st)
- f# H# Y! G9 K+ m - return1 Y4 f% x! b' j W( V
+ ?5 L+ P! S' H% K: K- class Quest (JQuest):. W" Y& y/ X, d2 P% p; B' l) r
- 2 a' x8 _- ^. }' k$ ]
- def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)
' B* g. O6 M- C2 A: {1 ` - 2 e N, l# V' ~; v, h3 c$ P0 R+ q+ ]' ^
- def onEvent (self,event,st):, O( X# s+ z! J( E' |, d
- id = st.getState()
9 i u% q, h3 O- r3 E* D - if id == CREATED : st.setState(STARTED)
* I2 C2 l4 Q l0 } |8 i - elif id == COMPLETED: pass
1 G. ^$ t& u" b, x2 `' T - elif id == STARTED : check(st), v" h" r3 j( w. Y" i
- return% [' m4 v: Y# h1 w
- 5 Y! ?( X& i5 s n8 T
- def onKill (self,npcId,st):
$ H4 ]# w) C5 T: y* V2 l! ~ - if npcId == KELTIR_NPC_ID:& G7 w" [# ~4 p5 N, f# M
- n = getCount(st)
" H0 v+ X7 Z) a/ C. i1 T; X - if n == 0:
' ^2 J; X1 ?& H% ^: N+ W - if st.get('chat0') == None :
" B7 K4 L, u, K* B7 @6 R - st.set("chat0", "true")# g, Z- l; W1 d6 N# X' k! e' ~
- return "Chat0.htm"! Q7 H- z& `" k8 c
- elif n == 1:; z2 D7 `) a( n) X5 X
- if st.get('chat1') == None :
- s, x- P* ~( I5 c7 V+ ?6 o - st.set("chat1", "true")
' n( y; A/ Y* O* Q9 ]6 d4 e - return "Chat1.htm"
. O5 m* R9 r- X* x - elif n >= 4:* w: K( W5 l6 a+ f# c9 h" ?
- return "Chat4.htm"0 ~6 k9 l: L `- ~
- return "Collect "+str(n)+" of 4 fangs"* |! m& w; ?+ m/ f* o( N
- return
' G7 w# m7 o2 Q3 d - % T0 \3 q. X4 E3 I8 M6 R7 C
- QUEST = Quest(201, "Tutorial", "Tutorial quest")7 S/ ^. {4 h2 v! q; A, I
- CREATED = State('Start', QUEST)1 h+ m2 o5 b. `1 p5 n
- STARTED = State('Started', QUEST), s& o$ L. [2 p$ w8 g Z8 F s
- COMPLETED = State('Completed', QUEST)/ R/ I& N7 g" @# u2 K
- % ?+ p2 N- t5 f9 ^% F0 K5 w) v& _' f
- QUEST.setInitialState(CREATED)
) E3 L2 R4 V' G3 I# M1 w - QUEST.addStartNpc(7056)
2 o; G8 a' f3 h/ W5 W( D/ } - QUEST.addStartNpc(7012)
% y# N& w/ N a; r5 u - QUEST.addStartNpc(7009)+ a8 v9 `4 v; T% q, ^# V. `+ c
- QUEST.addStartNpc(7011)
. ^& p v- b X m% P
9 u$ z, ] ?/ v, ?- STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE): [! Q6 N( Q* `5 [, \7 G& q* x
- STARTED.addKillId(KELTIR_NPC_ID)" {$ m! M5 f: j9 u* T
- STARTED.addTalkId(7056)
4 Z: v7 g; h% D2 G) V( K - STARTED.addTalkI d(7012): z5 ~( G8 N* J1 k; W/ l
- STARTED.addTalkId(7009)* D5 G4 {6 c2 E# v1 Q8 U
- STARTED.addTalkId(7011)
Скопировать код
1 k2 g3 J# D) K! a: q: o6 E, |+ c, e( o* x( I5 [! G8 ]) `. t4 |" p
|