Зарегистрируйтесь сейчас чтобы найти еще больше друзей, и получить полноценный доступ ко всем функциям сайта!
Для просмотра Вам необходимо авторизоваться Если Вы еще не зарегистрированы, перейдите по ссылке:Зарегистрироваться
x
Хроники Interlude
0 p" W/ W% k# v2 R! u* k1 i5 zСборка L2j
& Z5 w8 |" O& jОбратите внимание: в файле htm стартового NCP обязательно должна быть ссылка на квест:$ K. ^7 E' Z1 Z& T' s9 B, H
- STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код Для этого квеста больше ничего не надо. Все необходимое для корректной работы квеста уже добавили. Вот полный текст квеста:$ X" I6 H3 n4 `! b, F
" i% E7 @/ x* ]: C1 I- if getCount(st) >= 4 :- e% F" T- R& f7 z- o# _1 H
- completed(st)
! M# G- Q% b3 m# J+ C! z" D - return
$ n: t+ j3 U5 q9 m/ q9 y
% w) `9 D# P& \4 R5 n) L- class Quest (JQuest):0 g4 a! Q- n2 `4 V! o0 Y0 S+ s
- def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)
& F1 X( S" n8 Y0 W; K9 A9 c( N - def onEvent (self,event,st):* L9 O" w) t' }& I: ]
- id = st.getState()
% ]3 {* y1 Z' |# s - if id == CREATED : st.setState(STARTED)% l0 M ~8 _0 n" m; G1 f
- elif id == COMPLETED: pass
; n! ?8 N* w% @6 p - elif id == STARTED : check(st)
; S0 B2 T% u; y; x) R/ O6 q( m - return
/ d" L. A% [* `* l% ^- f o
' M4 _+ K7 N+ m+ x" S( `& `- QUEST = Quest(201,"Tutorial", "Tutorial quest")
; e+ [3 f2 [3 u1 h# T2 ~ - CREATED = State('Start', QUEST)
" P0 d4 M# \& t1 C; d - STARTED = State('Started', QUEST)
y9 k6 [* B1 f- K4 f( _ - COMPLETED = State('Completed', QUEST)
' N2 Q0 ?; ^- P8 r; ` - 4 c3 K. @& f, } O
- QUEST.setInitialState(CREATED)( X+ {3 O" A1 Y% A& q4 h
- QUEST.addStartNpc(7056)% l* E' A9 x0 T& ]4 u) i7 _
- STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код Теперь рассмотрим, как это работает.
! ?/ s/ C5 E. Q: R0 Q( u; ]Игрок подходит к начальному NCP (в данном случае 7056), нажимает на «Quest». Квест будет создан и состояние квеста перейдет к CREATED и игроку будет показана страничка Start.htm с описанием квеста. Тогда метод onEvent, поле открытия странички Start.htm переведет состояние квеста в STARTED и игроку будет показана страничка Started.htm, где будет опсание того, как найти keltirs и .т.д.& j# l6 z6 t- l Z8 p
/ H- O8 [# b/ x" {$ B
1 x' f- h1 O- D' V
При состоянии STARTED будет зарегистрирован дроп «fangs» при убийстве keltirs. Игрок может вернуться к стартовому NCP и спросить о квесте – метод onEvent будет вызван снова. Если у игрока не хватает необходимого количества предметов, то метод check() не переведет квест в следующее состояние и Started.htm будет показана снова. Но если игрок собрал необходимее количество предметов (в данном случае 4 клыка), то метод check() вызовет метод completed() который переведет квест в новое состояние COMPLETED, заберет все клыки, даст карту мира, т.к. это награда за квест, покажет Completed.htm и завершит квест.- _4 I' y: Y/ w) x: {6 \* D4 K
0 G& Q2 D$ a' d4 B' @. c; s. N3 D" ^) O* ]- q0 z& o* ~, N$ C
Теперь давайте сделаем наш квест более похожим на то, что он должен из себя представлять.
% t& q% g* Y- b( ?# L" TПрежде всего у нас есть 3 метода для объявления их в Яве – onTalk, onKill и onEvent. Если методы onTalk и onKill не объявлены, то за них все будет делать метод onEvent, т.е. определять квестовых монстров и вызывать диалоги NCP. Есть примечание, методы onTalk и onKill будут вызывать только диалоги с NCP в зависимости от текущего состояния квеста. Метод onKill будет вызываться только тогда, когда мы убиваем квестового монстра.2 c+ r% ?2 ]" K ~
" S) s# v1 ?' S3 X7 V
% t7 q% l7 m5 a6 l, l6 N& i E
Давайте рассмотрим как вызывается метод onKill при убийстве keltir в состоянии квеста STARTED:
9 w9 {: O; l' P, e5 g# t! ~- STARTED.addKillId(KELTIR_NPC_ID)
Скопировать код и метод onKill в классе Quest:# o5 ] U- s5 A$ T
" G- Z3 h/ T T. t7 F! ]
- class Quest (JQuest):, C( p' t' f9 D6 ~5 \
- ...
) a. _; ]5 Y: q- W$ B - def onKill (self,npcId,st):% E% {% N' S1 J0 }1 I
- if npcId == KELTIR_NPC_ID:' q9 Z4 F% Y2 ]% S
- n = getCount(st)
7 Z1 F& L% z' r* h: O1 b" j - if n == 0:, W& ~' p6 u* e1 H) Y+ x
- return "Chat0.htm"
4 {6 C. `. J0 A$ `3 l3 M6 { - elif n == 1:6 X. B5 {5 {1 J- A8 J2 z* ^7 Q% k8 c
- return "Chat1.htm"4 L/ q- u4 \" H# s$ J P* D& l# I
- elif n >= 4:
{% V& R( h) C- y8 v - return "Chat4.htm"# v6 t( ]2 s0 h8 `
- return "Collected "+str(n)+" of 4 fangs"9 n! p5 o2 B* J6 B/ ?! Z& L
- return
Скопировать код Метод onKill (а так же метод onTalk) имеет следующие параметры:5 n9 l- M; I0 P' j8 g" O$ ~
% z& i+ G9 I6 R! G9 \% l1 m
3 e4 v, ]2 r" Y n. }• self – квест
2 e7 L4 @1 E* M3 ^. ~• npcId – ID NCP, которого мы должны убивать (если это метод onTalk, то ID того NCP, с которым мы должны поговорить).1 C2 k0 `9 k F' l- K4 a5 B' m& {
• st – текущее состояние игрока.
+ E1 f4 x$ Q1 Y9 O
* C8 r1 ~8 m2 v. u& ?4 c* u$ Q! q* }+ ]: R0 u+ S9 z" q( P8 G5 e/ J
В этом методе мы проверяем и отмечаем, является ли убитый NCP keltir’ом. В основном эта проверка не нужна, т.к. у нас только KELTIR_NPC_ID.0 w" s* ~$ r% o% M' S
) S' b% V& R2 l* o# q6 E5 l
- J+ V, Z: _5 V' n" X6 @
Затем проверяем количество предметов (в данном случае количество клыков), и если их вообще нет, то возвращаем строку "Chat0.htm", если только один предмет, то возвращаем строку "Chat1.htm", если же предметов 4 или больше, то "Chat4.htm". Если строка возвращена из методов onEvent, onKill или onTalk, то сервер покажет соответствующие htm. В Chat0.htm может иметь следующий текст: «Вы не имеете ни одного клыка, возвращайтесь позже, когда соберете 4 штуки и бла, бла, бла…», в Chat1.htm может быть следующий текст: «У Вас всего 1 клык, по этому соберите еще…». В Chat4.htm – «Вы собрали необходимое количество предметов, возвращайтесь к вашему тренеру, что бы завершить квест…»
+ L2 s5 S- I* w" h4 p' S" y/ n h2 J8 _, T7 B( T: V0 A( I, T
9 b- b' h% Z& }% E
Примечание: если в строка return начинается с "<html>", то будет показана страничка html с текстом, который стоит далее. Так вместо:& g9 f4 a3 |+ c# s7 ^+ ]
return "Chat4.htm"* @6 a4 p3 U8 ~% e( a! F
0 d. T( `0 K5 r* r1 p8 @9 }
2 P, J+ b6 \8 sможно поставить:
6 x: w) G& V4 V7 M' {2 D- return "<html><body>Return to your trainer to complete the quest</body></html>"
Скопировать код Так же если строка заканчивается без .htm или в начале нет <html>, то текст будет выведен, как системное сообщение в окне чата. В нашем случае мы сделаем так, что бы при каждом убийстве keltik выводилось системное сообщение: «Собрано N из 4-х клыков».1 E" c: X' F1 U' t* l9 t9 w
/ g {& Z. y0 z( Y( |% e
* k/ g0 A% Q6 b+ p% \8 nНаш код для onKill имеет один недостаток. Он будет постоянно показывать Chat0.htm, Chat1.htm и Chat4.htm, нам же необходимо, что бы Chat0.htm и Chat1.htm показывались только один раз. Как нам это сделать? С помощью переменных.! G9 Z% H7 q$ Q+ |
' A/ H. V+ J; S# f
. t' o3 L: b# L( e
В каждом квесте строки могут храниться с помощью переменных. Эти переменные сохраняются в Вашей БД. В каждом методе мы можем назначить, прочитать и удалить переменные. Давайте изменим метод onKill, так что бы каждый диалог вызывался только один раз.* h/ Z. l& n, \9 |
- def onKill (self,npcId,st):: K9 g/ s5 L! p/ ?! S2 d
- if npcId == KELTIR_NPC_ID:
5 B. b) g) O' u% z: K/ m% a - n = getCount(st)8 Z/ v: E0 d% K9 d
- if n == 0:+ C5 A( B7 `, W
- if st.get('chat0') == None :
/ o% m7 G% c3 D: K5 \ Z$ T( |( L; \ - st.set("chat0", "true")1 i1 d9 r* p- N
- return "Chat0.htm"! Q0 h% y1 A, h+ ]# a
- elif n == 1:
( x3 C7 i- r' p - if st.get('chat1') == None : X! U" a1 ?3 g8 ]* F
- st.set("chat1", "true")4 _ q1 @- H4 T$ t5 X3 Z
- return "Chat1.htm"! n& A* C9 x9 E; H2 e4 m5 H
- elif n >= 4:1 r+ H, X4 D0 g' ]0 v0 t
- return "Chat4.htm"
3 D0 z9 J- N9 u- J- K! s - return "Collected "+str(n)+" of 4 fangs"* |! h$ ?; P2 T) F# r$ r
- 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 }$ }( ]* L1 {
$ p2 \! j- _% M# V
4 D: S8 H1 `2 i3 y9 B% c- AВот конечный рабочий вариант квеста:
( L2 _3 ~9 n! f- import sys1 U2 Y8 g9 b* A# j1 s: D) q
- from net.sf.l2j.gameserver.model.quest import State8 {* h9 s, [. D X
- from net.sf.l2j.gameserver.model.quest import QuestState
6 U1 S! s# D% o1 m8 D - from net.sf.l2j.gameserver.model.quest.jython import QuestJython as JQuest
! {$ l6 o( I( z, ~( a1 ~ - & }; X9 M/ s- ~, `/ ~5 W* ^
- KELTIR_NPC_ID = 12082* w$ b. T# z9 Y# f* [ U) j
- FANGS_ITEM_ID = 1859+ @& K, f- `: [$ b+ Q4 m1 p, ]
- DROP_RATE = 500000" C7 J) m0 O" x! Y# j
- ! z' o: m- J0 P1 \9 U. |
- WORLD_MAP_ITEM_ID = 1665
! E5 f9 @( M' L" ^, x% X
1 l0 a5 B! J M! X% s' v- def getCount(st) :
* w. S! @+ Z" e$ q" e& K8 @ - return st.getQuestItemsCount(FANGS_ITEM_ID)& ]6 y" m# q: a! Q* H( r2 d( ]) S
) F& t* k6 n+ a1 B' n' R- def completed(st) :4 i6 r" t! M# x: E: w! e1 y) v
- st.setState(COMPLETED)# H& Z1 b6 H$ t& k1 o
- st.clearQuestDrops()
7 P0 a4 ] [$ X3 `/ u2 b4 u - st.takeItems(FANGS_ITEM_ID,-1)7 @0 D Y* i- j* ]7 I
- st.giveItems(WORLD_MAP_ITEM_ID,1)
) K. u- `3 `# Z v( E; _+ s - st.exitQuest(False)
7 C# z+ P- \/ i# ?! h2 U - return( u5 j W t% c, L" G
- : [# i$ Q4 u V! n9 A7 X- E' [
- def check(st) :
& S1 }& n/ e# Z6 J; U9 W - if getCount(st) >= 4 :
7 L- t3 ?" a5 u4 _ J' J - completed(st); ` H$ h7 t4 @: D
- return# L2 h$ L* b @' X s
& T5 r; _" H4 v# _# I- class Quest (JQuest):
8 Z6 T3 \5 I( }% R4 y! M - ' n8 V4 H- R, n4 k6 B \# z, j# c
- def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)
% M+ K: A* k7 k5 g3 L" r" k - 0 B. y, T. d& I/ Y9 j: f. z
- def onEvent (self,event,st):/ {/ W" n( q% S' f" @; ^3 S4 d
- id = st.getState(). b% I% W8 C& W& P. P; _' }. m Y
- if id == CREATED : st.setState(STARTED)
- y' x' j! ` [# m7 V* ] - elif id == COMPLETED: pass
7 w* W$ U% c5 C' l - elif id == STARTED : check(st)
; o7 o# w; n8 @; t- g0 L1 ] - return; m6 O) D2 F, |
, s5 |' ]2 Z2 Y$ N1 [" M- def onKill (self,npcId,st):% L' X- Y, f" b% |& W8 @/ `" T% v
- if npcId == KELTIR_NPC_ID:
& a7 w& v! d) s - n = getCount(st): a: H6 c. w; E7 ?
- if n == 0:
& o: L; m, Y8 ?0 w* u/ l; x - if st.get('chat0') == None :
: }/ s% x5 E; A3 i6 p) n9 l: g - st.set("chat0", "true")
6 T1 c$ U! }8 S' H2 K6 L - return "Chat0.htm"
& y4 L- t$ Z1 t! G7 }2 e A; S - elif n == 1:# F6 z$ _; ]1 L6 M3 G6 C
- if st.get('chat1') == None :; P; Z+ U* M# F9 u
- st.set("chat1", "true")
3 s2 B1 P, A' r% ]& \) ~ - return "Chat1.htm"
4 {7 u* ~4 t, G+ d9 q2 k( j) o. S2 k A! G - elif n >= 4:. E1 k+ q7 ~" _" S \, _
- return "Chat4.htm"1 O* S: _* S2 N' g/ O9 f9 {
- return "Collect "+str(n)+" of 4 fangs"
2 R( ~4 p6 Q2 C$ S+ a' C% _% T- M - return9 K f& ?- O0 F7 w! a6 h( Q
- & ]) T% r$ T8 n3 P5 k: @$ C0 ?
- QUEST = Quest(201, "Tutorial", "Tutorial quest")
# j/ x/ v- V) f, V' _ - CREATED = State('Start', QUEST)
+ c0 `# F6 n8 n% W U: r" R - STARTED = State('Started', QUEST)0 z' H5 T) ?9 q9 d2 W% Q) d+ J8 i
- COMPLETED = State('Completed', QUEST)
" S* Y* N+ D7 m - 9 O! m2 Y% F" t1 B
- QUEST.setInitialState(CREATED)8 C2 C. h: p; x+ A& E8 [
- QUEST.addStartNpc(7056)1 j$ A8 C$ U* Z4 K
- QUEST.addStartNpc(7012)
4 [/ m7 o$ y7 |+ q; ~- g8 B - QUEST.addStartNpc(7009)& [" s1 }6 B8 ~
- QUEST.addStartNpc(7011)# M* _; J. \/ E
- # @* m$ y6 q: w/ T) y0 K r8 t
- STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE): f; }8 s7 g1 ~( w& j" \" k0 o: L
- STARTED.addKillId(KELTIR_NPC_ID)
3 K% H9 ^: \3 S2 J% k8 k - STARTED.addTalkId(7056)% s. ?5 \# n( C9 |8 u' Y5 o7 Y/ E
- STARTED.addTalkI d(7012)6 f" |0 N% K% C6 a" M0 s
- STARTED.addTalkId(7009)
1 l, ~9 i: w+ P5 n - STARTED.addTalkId(7011)
Скопировать код : D, W8 y6 D! f* y- G- S
0 }! E# Q# T+ y2 `0 t |