Зарегистрируйтесь сейчас чтобы найти еще больше друзей, и получить полноценный доступ ко всем функциям сайта!
Для просмотра Вам необходимо авторизоваться Если Вы еще не зарегистрированы, перейдите по ссылке:Зарегистрироваться
x
Хроники Interlude- f1 C# a7 E/ H! w8 l7 \. ]3 H1 D8 {
Сборка L2j+ L) m8 ^. J* f, ?5 k+ v
Обратите внимание: в файле htm стартового NCP обязательно должна быть ссылка на квест: J' a6 z/ B; \0 p1 K$ p& q4 ]' |% O
- STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код Для этого квеста больше ничего не надо. Все необходимое для корректной работы квеста уже добавили. Вот полный текст квеста: v4 I6 e* G4 n# V P; f0 F
0 u- n. \- r: ^$ B, S ^% [
- if getCount(st) >= 4 :: Z& W$ @) T( P3 v
- completed(st)
; S/ n) }' v* T' y% k9 @ ]! Y - return
" U2 @! `/ `& ^
- x' a: ?' ]+ Z" b. \- class Quest (JQuest):1 K2 K% o2 p+ e+ v' \! |# K7 N
- def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)
% D* `4 E/ N& P I2 [5 @1 k, x - def onEvent (self,event,st):
1 L5 j+ H. `, h, }' G6 F, e - id = st.getState()/ L, w, M( T. y7 R+ [1 \. D
- if id == CREATED : st.setState(STARTED)
' _% ~4 m Z4 j- F' F - elif id == COMPLETED: pass; s8 \! w. z3 R
- elif id == STARTED : check(st)! q1 e5 y, H4 v, K) Q4 ]- n8 a k
- return
, H4 z9 B* x! S0 M6 T: ?& [
# r9 s; q7 R8 o: D0 f* j6 O- QUEST = Quest(201,"Tutorial", "Tutorial quest")
4 L' q; l1 Y; }6 J - CREATED = State('Start', QUEST)( c" l1 S3 {$ _" M; V9 b4 e
- STARTED = State('Started', QUEST)
1 S2 K7 E) C9 |6 N$ D7 H - COMPLETED = State('Completed', QUEST)* Z9 X5 a- V% \* D. j% ?7 X
- : R* V. Q6 W ?) x3 S5 U: ~
- QUEST.setInitialState(CREATED)
, i! X; k. w3 w: a% V7 U8 _ - QUEST.addStartNpc(7056)
: W8 R x% i1 z: ?! m+ r - STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код Теперь рассмотрим, как это работает.1 ?! t( W& m, P1 e R6 f4 o
Игрок подходит к начальному NCP (в данном случае 7056), нажимает на «Quest». Квест будет создан и состояние квеста перейдет к CREATED и игроку будет показана страничка Start.htm с описанием квеста. Тогда метод onEvent, поле открытия странички Start.htm переведет состояние квеста в STARTED и игроку будет показана страничка Started.htm, где будет опсание того, как найти keltirs и .т.д.; P* E; }0 w8 z. l4 V: C
+ _" C" K5 b0 n8 d2 [
; ~; e/ I' k9 j* T2 ^
При состоянии STARTED будет зарегистрирован дроп «fangs» при убийстве keltirs. Игрок может вернуться к стартовому NCP и спросить о квесте – метод onEvent будет вызван снова. Если у игрока не хватает необходимого количества предметов, то метод check() не переведет квест в следующее состояние и Started.htm будет показана снова. Но если игрок собрал необходимее количество предметов (в данном случае 4 клыка), то метод check() вызовет метод completed() который переведет квест в новое состояние COMPLETED, заберет все клыки, даст карту мира, т.к. это награда за квест, покажет Completed.htm и завершит квест.) c3 H( b' C1 e1 k# z. O
7 F" Z- {: k k- |6 n# |
( `7 R. j* V U# l2 s
Теперь давайте сделаем наш квест более похожим на то, что он должен из себя представлять.* x- J5 w$ u0 C m& {# n* J
Прежде всего у нас есть 3 метода для объявления их в Яве – onTalk, onKill и onEvent. Если методы onTalk и onKill не объявлены, то за них все будет делать метод onEvent, т.е. определять квестовых монстров и вызывать диалоги NCP. Есть примечание, методы onTalk и onKill будут вызывать только диалоги с NCP в зависимости от текущего состояния квеста. Метод onKill будет вызываться только тогда, когда мы убиваем квестового монстра.
! L& H5 b# I- t M' y7 ~2 s3 ]' V2 E$ ]0 [* J$ Z' l( D
' Z+ h8 m4 [1 lДавайте рассмотрим как вызывается метод onKill при убийстве keltir в состоянии квеста STARTED:/ l/ R6 E! `1 Q! C% y5 h- T
- STARTED.addKillId(KELTIR_NPC_ID)
Скопировать код и метод onKill в классе Quest:: T9 E5 R, z& {9 W: `
. C7 Z& Z) P$ y
- class Quest (JQuest):/ R# ?$ \; h4 X8 F5 G
- ...
( m* W1 @6 k- E* ~# |/ Y# V6 m2 D7 l - def onKill (self,npcId,st):
$ G. K8 n/ V! {+ H+ N: O4 O( U - if npcId == KELTIR_NPC_ID:6 |" L" ? I0 [& D7 ~
- n = getCount(st)! I$ J& i8 }# w+ _% B
- if n == 0:
; ^7 Y' x+ L7 h9 M - return "Chat0.htm"9 H) ]0 |( n5 l7 G; |" d
- elif n == 1:) p6 R6 o: f* y, e+ E9 P q
- return "Chat1.htm"
/ M* a8 K5 J$ X - elif n >= 4:! Z6 Q3 K7 K: k6 K/ b2 e
- return "Chat4.htm"1 g) t1 C' Q! b3 Z. I
- return "Collected "+str(n)+" of 4 fangs"
5 N+ n; L- w" H& V6 ~: ` - return
Скопировать код Метод onKill (а так же метод onTalk) имеет следующие параметры:% N b H4 Z& X% N4 h
$ @2 l j" Z9 W$ M) w+ g
8 Y$ L2 m5 _5 O! L8 N& ]8 x/ j9 [• self – квест
+ q. a8 l+ U" W" Z# q• npcId – ID NCP, которого мы должны убивать (если это метод onTalk, то ID того NCP, с которым мы должны поговорить).
! V8 l/ u% _& a) I! N9 c' O# K• st – текущее состояние игрока.4 I' R# O L4 b! y
- u6 [0 z6 [* e: n- g) C- z" U# o" _. K" T& V, I" }
В этом методе мы проверяем и отмечаем, является ли убитый NCP keltir’ом. В основном эта проверка не нужна, т.к. у нас только KELTIR_NPC_ID.
6 {- n4 k9 V- d8 a
/ A" j; e8 u* O# _/ Z7 O: u
( q8 m) r7 ?& T- ~) lЗатем проверяем количество предметов (в данном случае количество клыков), и если их вообще нет, то возвращаем строку "Chat0.htm", если только один предмет, то возвращаем строку "Chat1.htm", если же предметов 4 или больше, то "Chat4.htm". Если строка возвращена из методов onEvent, onKill или onTalk, то сервер покажет соответствующие htm. В Chat0.htm может иметь следующий текст: «Вы не имеете ни одного клыка, возвращайтесь позже, когда соберете 4 штуки и бла, бла, бла…», в Chat1.htm может быть следующий текст: «У Вас всего 1 клык, по этому соберите еще…». В Chat4.htm – «Вы собрали необходимое количество предметов, возвращайтесь к вашему тренеру, что бы завершить квест…»
8 t. t* G# F: L/ j4 M6 P( t
( `: U( Q: z; ?2 q" a
2 g- e' R) V! ?- f: s" v8 w: GПримечание: если в строка return начинается с "<html>", то будет показана страничка html с текстом, который стоит далее. Так вместо:
4 a1 t0 w9 f1 _return "Chat4.htm"
! Q- i6 |/ H( P8 |; K% O/ X/ E* L4 z) z; i
9 T1 ` L0 b# E& ]* E4 c* Y; sможно поставить:5 K9 g" `- [, F* {; E0 b' ?
- return "<html><body>Return to your trainer to complete the quest</body></html>"
Скопировать код Так же если строка заканчивается без .htm или в начале нет <html>, то текст будет выведен, как системное сообщение в окне чата. В нашем случае мы сделаем так, что бы при каждом убийстве keltik выводилось системное сообщение: «Собрано N из 4-х клыков»., U. ?! ?* h: M M' s
, k$ ~+ V6 n1 B7 D( m0 P4 ?
8 z5 A5 b, U2 \' G% zНаш код для onKill имеет один недостаток. Он будет постоянно показывать Chat0.htm, Chat1.htm и Chat4.htm, нам же необходимо, что бы Chat0.htm и Chat1.htm показывались только один раз. Как нам это сделать? С помощью переменных.
; g# Q } u' u$ |+ y N$ F+ K5 X( U% |; d
4 \: |& ~; Z, M: Q7 s6 s& d' l( _' L
В каждом квесте строки могут храниться с помощью переменных. Эти переменные сохраняются в Вашей БД. В каждом методе мы можем назначить, прочитать и удалить переменные. Давайте изменим метод onKill, так что бы каждый диалог вызывался только один раз.: L% a. F! y0 u' ]
- def onKill (self,npcId,st):' a; {$ D- y( I; w/ j
- if npcId == KELTIR_NPC_ID:! [% l. |/ [7 H! F5 |: A& J
- n = getCount(st)
" _0 B2 w/ @* e3 V& ? - if n == 0:; U- E/ | t) J
- if st.get('chat0') == None :
; a4 E3 @! P# i! G' ^, M - st.set("chat0", "true")
4 I3 K! h1 {8 R' g( v - return "Chat0.htm"
v& p, g! i1 \ - elif n == 1:
+ a/ w4 x% q6 f9 _ - if st.get('chat1') == None :
. p. C6 _+ O4 I" o - st.set("chat1", "true")
, t- Q) x1 M: C% [1 [ - return "Chat1.htm"
( k. V3 C+ ^7 {. z/ v - elif n >= 4:
3 {0 ]% j8 V+ o& p6 N2 H5 k C - return "Chat4.htm"
9 _* |' y7 V9 }4 h. ^7 N" D& p - return "Collected "+str(n)+" of 4 fangs"- x; s3 N" r, I3 y! 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.7 l2 U+ p% W6 R- _$ p: R* y5 |
% a) D5 r/ n8 e, q3 i4 `5 X1 P9 ` B, c: @% V( ]5 R
Вот конечный рабочий вариант квеста:
) ?" _$ t/ w6 c: d$ r2 [8 V8 b7 u- import sys
$ N+ ~! F) c' E6 T5 N; j; v& \9 ` - from net.sf.l2j.gameserver.model.quest import State
% Y6 c7 V2 v# N8 Y* m/ o# ] - from net.sf.l2j.gameserver.model.quest import QuestState
+ T& a. d6 p# F+ j7 I$ B! f+ r - from net.sf.l2j.gameserver.model.quest.jython import QuestJython as JQuest/ X$ [6 e0 y* R
# x# c& o: [# n v1 Y' J- R9 Z- KELTIR_NPC_ID = 12082
" p8 A( p e# M - FANGS_ITEM_ID = 1859. C) W: V( f" C2 @
- DROP_RATE = 5000007 d, t1 S/ n4 ]! w- Y3 t
& I. W4 K4 @* |7 X. x- WORLD_MAP_ITEM_ID = 1665* V4 ]0 ~" F1 ]& C3 v' R
- ( r) B6 X1 u) v' o
- def getCount(st) :
7 M0 E0 t) u% q6 K: J - return st.getQuestItemsCount(FANGS_ITEM_ID) E) V, m4 m; w: e% c# H. n
- 8 K# }4 w. D# M0 S# A* y8 g
- def completed(st) :" }9 T, C4 f1 g
- st.setState(COMPLETED)
) r) Q" @: w9 O3 U: j - st.clearQuestDrops()
, L H7 u" C: X4 S6 l$ p - st.takeItems(FANGS_ITEM_ID,-1): t" k8 c4 h( x* _( m1 [
- st.giveItems(WORLD_MAP_ITEM_ID,1)1 Q- z* w$ e/ l! W$ N
- st.exitQuest(False)7 |; @9 X; ^7 x
- return8 G8 y( C9 o+ J2 o5 M
8 Q9 v6 y7 L5 j) @: ]. R- def check(st) :, ~9 W+ \1 R) |. f$ [" i
- if getCount(st) >= 4 :3 I9 \# n$ L% f m) j$ R
- completed(st)8 K- t) T [& U! V6 s+ f
- return
# b9 T7 F/ Q* x8 }: k, N' \0 ]# w
6 }. R0 \9 p0 h2 w2 c- class Quest (JQuest):
, H+ m* ]9 H1 N3 d! c
+ F! A1 N- W1 ^' {5 p, i- def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)
6 q. g& \# o1 h2 f& B - 5 L# W! a; k. ?- x6 I, f
- def onEvent (self,event,st):; u- e1 I% j& G
- id = st.getState()( U0 k! ]+ E# [" V: p1 @+ S7 G
- if id == CREATED : st.setState(STARTED)( |- _2 U: q) ?. q
- elif id == COMPLETED: pass2 H! N( M9 T+ h5 v4 t4 V
- elif id == STARTED : check(st)5 m9 O* i; k" y& g( ^6 V% J
- return
- g5 _( l+ N9 R- e( ` - 0 b# `4 k O9 z& [: Q- k9 P* S
- def onKill (self,npcId,st):
4 P8 `3 P8 r4 e7 Z1 X" D" E - if npcId == KELTIR_NPC_ID:. n6 h$ \7 G8 S1 }' X) y
- n = getCount(st): ~; q& h. c: h
- if n == 0:) U' f9 n9 \9 d5 j
- if st.get('chat0') == None :
, Z+ \3 U t; D. P; O$ I/ J" T - st.set("chat0", "true")
9 E/ K9 V/ I, y* l D% m - return "Chat0.htm"6 s7 C* K" n) k" i! U* C1 E0 D
- elif n == 1:
( s. s# w9 H! l; k - if st.get('chat1') == None :$ w; }5 b" u/ N
- st.set("chat1", "true")! ?3 e6 V' V( x9 B }
- return "Chat1.htm"
, q, \% ^2 x8 v0 q. l& K, b& k - elif n >= 4:
* j m8 `* S: ]% q# L M - return "Chat4.htm"
; Y/ u6 i" R; c - return "Collect "+str(n)+" of 4 fangs"" W4 D C) i/ A) s
- return
( v, |" d) v( h2 [
# w. c$ v# x- {( I! A3 u- QUEST = Quest(201, "Tutorial", "Tutorial quest")
, D8 ~) h7 u6 c - CREATED = State('Start', QUEST)" j, R2 Q+ Y! K$ ?5 c; V, L
- STARTED = State('Started', QUEST)
: ^" `& J" |! b# @) ]8 p J1 I - COMPLETED = State('Completed', QUEST)
' t7 [. r* {- E) l/ P- X
! n$ r! w( x/ ?! Z5 w4 u- QUEST.setInitialState(CREATED)
& o. W5 Y: H( X" @5 x. {5 | - QUEST.addStartNpc(7056)0 U6 k" s5 f0 O" z+ I9 B
- QUEST.addStartNpc(7012); s Z. g+ p9 V. O
- QUEST.addStartNpc(7009)0 b& W5 I2 H2 X/ T
- QUEST.addStartNpc(7011), F, C* m/ d- D
- 3 l6 |3 ]% m. o. z+ b4 c
- STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
3 C: ?8 P) U4 R$ E - STARTED.addKillId(KELTIR_NPC_ID)7 a4 `& `8 T2 y+ ?
- STARTED.addTalkId(7056)' u. J$ u# a5 m6 a7 z4 O% l
- STARTED.addTalkI d(7012)2 f4 b0 k+ W( ~! s
- STARTED.addTalkId(7009)
" g* u0 n' g3 _. B* z2 R4 W - STARTED.addTalkId(7011)
Скопировать код
% a" e$ V- _( H: o( {0 ~9 _) _1 s- p& A- L1 U4 Q
|