Зарегистрируйтесь сейчас чтобы найти еще больше друзей, и получить полноценный доступ ко всем функциям сайта!
Для просмотра Вам необходимо авторизоваться Если Вы еще не зарегистрированы, перейдите по ссылке:Зарегистрироваться
x
Хроники Interlude
W n- B, ^, t& aСборка L2j
8 X" T1 v! Z' gОбратите внимание: в файле htm стартового NCP обязательно должна быть ссылка на квест:
- P4 W0 ^ R- ^' ^, d- STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код Для этого квеста больше ничего не надо. Все необходимое для корректной работы квеста уже добавили. Вот полный текст квеста:
8 D( |( C) u" M& u' [+ f( Q* ~6 a5 Q4 b0 B7 s" c
- if getCount(st) >= 4 :; r% z1 x! ~8 [/ z8 u) w: D2 U
- completed(st)3 D7 [/ ?5 S1 G5 n0 b# N- _1 D
- return3 }6 I( |* a" Z
- 6 n4 C- @0 X$ ?" f) q
- class Quest (JQuest):
8 K$ L% p6 a7 n! m. D - def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)( y5 j2 l* I! ]) ~. [$ }& A
- def onEvent (self,event,st):/ r. _9 O2 t: y8 V: M' b
- id = st.getState()
" Q- ?/ Q, Z0 {# _7 h* I - if id == CREATED : st.setState(STARTED)% q. P, I8 f: L. _+ a1 I
- elif id == COMPLETED: pass( D5 Q6 O) z7 z8 x! z2 }5 c
- elif id == STARTED : check(st)/ l: j9 C1 g0 K# q+ B9 M8 j
- return; F- p* F5 l5 D7 x! x# h
- . q! y4 Y( O) H$ n! z4 x
- QUEST = Quest(201,"Tutorial", "Tutorial quest")# h% {# L' B5 e ?# |
- CREATED = State('Start', QUEST)
- r" \# ]" Z- L, P' U4 H - STARTED = State('Started', QUEST)
3 L+ u" a( q, r - COMPLETED = State('Completed', QUEST)
) @3 U; `& n$ C* ]) F+ q s; s& F
1 f, a* |+ G% q: u7 z: E- QUEST.setInitialState(CREATED)
' w6 e5 o c8 Z g - QUEST.addStartNpc(7056)0 _( e4 C" A4 b" b* A
- STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код Теперь рассмотрим, как это работает.
3 T' ?- h7 A; JИгрок подходит к начальному NCP (в данном случае 7056), нажимает на «Quest». Квест будет создан и состояние квеста перейдет к CREATED и игроку будет показана страничка Start.htm с описанием квеста. Тогда метод onEvent, поле открытия странички Start.htm переведет состояние квеста в STARTED и игроку будет показана страничка Started.htm, где будет опсание того, как найти keltirs и .т.д.. h. W l, A$ C( O4 c
% x. x9 }+ y% M) V8 k/ {- R9 Y; `4 e$ O% ^
При состоянии STARTED будет зарегистрирован дроп «fangs» при убийстве keltirs. Игрок может вернуться к стартовому NCP и спросить о квесте – метод onEvent будет вызван снова. Если у игрока не хватает необходимого количества предметов, то метод check() не переведет квест в следующее состояние и Started.htm будет показана снова. Но если игрок собрал необходимее количество предметов (в данном случае 4 клыка), то метод check() вызовет метод completed() который переведет квест в новое состояние COMPLETED, заберет все клыки, даст карту мира, т.к. это награда за квест, покажет Completed.htm и завершит квест.( |+ B G) A* \- w( F& C
1 G" i5 r! {! v
' I' {5 `: h: {0 E6 O+ ]
Теперь давайте сделаем наш квест более похожим на то, что он должен из себя представлять.
7 u4 \5 }+ L, P* ]7 ~& zПрежде всего у нас есть 3 метода для объявления их в Яве – onTalk, onKill и onEvent. Если методы onTalk и onKill не объявлены, то за них все будет делать метод onEvent, т.е. определять квестовых монстров и вызывать диалоги NCP. Есть примечание, методы onTalk и onKill будут вызывать только диалоги с NCP в зависимости от текущего состояния квеста. Метод onKill будет вызываться только тогда, когда мы убиваем квестового монстра.
7 q3 x; A; q6 b: a: Y
5 o# z1 L0 ?! g& d4 t; z% a! ?9 n/ @* n0 k/ {" a& J/ A
Давайте рассмотрим как вызывается метод onKill при убийстве keltir в состоянии квеста STARTED:
5 J; n1 R7 t9 ` x- STARTED.addKillId(KELTIR_NPC_ID)
Скопировать код и метод onKill в классе Quest:9 K6 g4 _1 v x) { l- F
1 W/ b: Y; Y8 n, s5 \# z ]
- class Quest (JQuest):
. Z1 s% q3 I3 p - ..." H. [$ T0 G2 t
- def onKill (self,npcId,st):! w) j- u( \! z* w0 ?
- if npcId == KELTIR_NPC_ID:
3 x7 v( L' r, L' ]* _7 i - n = getCount(st)
6 S) `2 G+ b: p( T - if n == 0:" Q0 z) _& C3 ~
- return "Chat0.htm"$ t% t: X! w n: ?2 v" z- H% r1 q! b
- elif n == 1:
* M* W6 G1 }7 T; j+ V - return "Chat1.htm"
`% f% g8 ^% {' o( Y, O$ M - elif n >= 4:
% J+ M3 u/ I! W6 X' f% H - return "Chat4.htm"1 ^7 p3 {# a; y3 N9 f8 Z# X# }
- return "Collected "+str(n)+" of 4 fangs"
, t0 p6 {- C5 `' T8 m( Y, N - return
Скопировать код Метод onKill (а так же метод onTalk) имеет следующие параметры:8 }' P+ d, m d# P0 X
. U! K J1 K( @, z1 l) Y6 s) E3 {6 c7 K" b+ C* k
• self – квест
) }( a$ M5 Q( M T) e/ E• npcId – ID NCP, которого мы должны убивать (если это метод onTalk, то ID того NCP, с которым мы должны поговорить).& S1 n1 |/ M0 d" b6 W* P
• st – текущее состояние игрока.' I# b+ A, [( J! x0 R2 i
$ o- t2 @7 m! }( `7 N7 C1 i
+ J4 h' n `% r. qВ этом методе мы проверяем и отмечаем, является ли убитый NCP keltir’ом. В основном эта проверка не нужна, т.к. у нас только KELTIR_NPC_ID.
4 a- M9 E" i+ ~% I' v% H! r. q& D+ O
6 O7 o( x. t# ^" q$ L; Z# H3 }
Затем проверяем количество предметов (в данном случае количество клыков), и если их вообще нет, то возвращаем строку "Chat0.htm", если только один предмет, то возвращаем строку "Chat1.htm", если же предметов 4 или больше, то "Chat4.htm". Если строка возвращена из методов onEvent, onKill или onTalk, то сервер покажет соответствующие htm. В Chat0.htm может иметь следующий текст: «Вы не имеете ни одного клыка, возвращайтесь позже, когда соберете 4 штуки и бла, бла, бла…», в Chat1.htm может быть следующий текст: «У Вас всего 1 клык, по этому соберите еще…». В Chat4.htm – «Вы собрали необходимое количество предметов, возвращайтесь к вашему тренеру, что бы завершить квест…»3 F' { ?3 \6 k- @: V
0 r% q2 W3 K, N
( O5 E0 f8 k) X) N' q! X
Примечание: если в строка return начинается с "<html>", то будет показана страничка html с текстом, который стоит далее. Так вместо:
. |0 x9 q( k" Z E) \0 _return "Chat4.htm"5 g( G `3 |1 h' Y5 l6 g# P( @
; B- _1 m3 m' [6 z# W% [8 O- V
/ _' U3 j1 m2 Lможно поставить:) s2 Q& T }5 |2 g
- return "<html><body>Return to your trainer to complete the quest</body></html>"
Скопировать код Так же если строка заканчивается без .htm или в начале нет <html>, то текст будет выведен, как системное сообщение в окне чата. В нашем случае мы сделаем так, что бы при каждом убийстве keltik выводилось системное сообщение: «Собрано N из 4-х клыков».2 h3 s W& A% A2 {( R# M
" w3 R7 d3 b9 M( q. y$ a& ~
5 W6 g1 ]3 P# [' m+ C$ z# |+ ^, E
Наш код для onKill имеет один недостаток. Он будет постоянно показывать Chat0.htm, Chat1.htm и Chat4.htm, нам же необходимо, что бы Chat0.htm и Chat1.htm показывались только один раз. Как нам это сделать? С помощью переменных.
* h& V7 _9 t+ I- \1 S- X* E1 l1 v+ T3 C2 Q0 t0 Y6 x( p
& d9 y* ~ \6 M6 d7 j2 N
В каждом квесте строки могут храниться с помощью переменных. Эти переменные сохраняются в Вашей БД. В каждом методе мы можем назначить, прочитать и удалить переменные. Давайте изменим метод onKill, так что бы каждый диалог вызывался только один раз.' q; i& P& g2 v" ^( o) X- F
- def onKill (self,npcId,st):
* O7 v" {5 h8 S- s t; |1 S - if npcId == KELTIR_NPC_ID:
1 x) W! `$ {/ o - n = getCount(st)
% ? {$ Y9 X& R& R1 s8 q$ `7 w& k - if n == 0:
3 _) ]& m7 s ~; F* d" e - if st.get('chat0') == None :
& ^! r. h: |# B1 z6 f# |7 N) O/ ?6 w - st.set("chat0", "true")
& H# y4 ^% K8 i4 Q A5 T6 Q$ x - return "Chat0.htm"
' [: B* F+ k* j1 Y) q: ~0 `: e - elif n == 1:
4 Y: X6 L0 ^6 k, P' E - if st.get('chat1') == None :
3 L4 v) Z- C' U. q" { - st.set("chat1", "true")
) I5 k# C; M$ V1 {" v - return "Chat1.htm"
0 V& A) o+ I: c5 }# f/ A - elif n >= 4:
2 J0 q: v, E; ]5 c - return "Chat4.htm"; | s: P: J) B
- return "Collected "+str(n)+" of 4 fangs"8 T4 ` p9 S0 H) d" F7 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.1 @/ y* |* U4 J0 r2 u# U
. z: U' s+ z4 s: I; I8 J$ i
& O& I6 P8 d3 r/ m* K- WВот конечный рабочий вариант квеста:' h) b- g) l- K
- import sys2 v' l3 v& ?1 s0 G3 ]+ n$ U! T) y
- from net.sf.l2j.gameserver.model.quest import State/ q! D! ]6 _4 Y7 g
- from net.sf.l2j.gameserver.model.quest import QuestState& t* I2 L) b0 l# I
- from net.sf.l2j.gameserver.model.quest.jython import QuestJython as JQuest+ p( ]' u2 a7 [0 \' i
- ( R8 C) p! k( [5 X+ }# w
- KELTIR_NPC_ID = 12082
0 |5 L' W2 Y( b, R - FANGS_ITEM_ID = 1859) m( R3 u# }" \2 \( C
- DROP_RATE = 500000
2 `8 r) M7 ]2 H - 3 o- O) L6 r4 q- m
- WORLD_MAP_ITEM_ID = 1665- T: s2 [* Z5 L+ Q% X7 _
- 1 v) Q$ e$ ~3 S; Q& }1 U
- def getCount(st) :0 l& f i& V' G
- return st.getQuestItemsCount(FANGS_ITEM_ID)
5 b @: P+ D T9 [' C4 C# F9 k - " A% V9 d3 P" H7 | F- f
- def completed(st) :% [ W) r h% _/ D' @5 X l$ H
- st.setState(COMPLETED)* l3 p Z8 g1 K: t. L; m' g* m: |
- st.clearQuestDrops()
; I+ A/ p) }$ R; g- X, f, {0 b) U - st.takeItems(FANGS_ITEM_ID,-1)5 ~) \, l" `: s! |4 [/ I
- st.giveItems(WORLD_MAP_ITEM_ID,1)
0 D2 |! R3 m- \+ |) J - st.exitQuest(False)2 ?! R. x/ D- W, s6 q, T1 L- E y
- return# N$ m- e. {7 ], Q, i4 N4 S, A
y' o, g* |: G) W) g- def check(st) :% s0 N U. m+ G
- if getCount(st) >= 4 :' `# b0 F6 W3 d) }: G
- completed(st)+ A |$ ^2 S& U- S
- return
0 X+ P/ C% j7 a5 F0 p3 v. t
0 [2 L9 k' z2 N8 u- class Quest (JQuest):
0 b% D, J. T& G q
( b$ _% U. w7 M8 l$ a1 V7 }$ t, O- def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)1 A+ R: _5 e: {9 R
! J, x$ S- ^. I$ E$ T; P" V- def onEvent (self,event,st):
- K; C% l+ u. ?: k7 y* g% s$ T - id = st.getState()( z+ M& D5 q+ E0 n+ h# c) [0 V
- if id == CREATED : st.setState(STARTED)
2 e j1 e; E- U$ X0 ~0 |# |8 j - elif id == COMPLETED: pass
% ~7 {% I- C8 S - elif id == STARTED : check(st)
# j! P* k, p( I/ q" j$ r# S+ ~9 v - return, z5 B$ o7 I' K Q H
$ M. b& F O; u3 a2 `- def onKill (self,npcId,st):- `" [! m0 z' Q; V) r; w: I
- if npcId == KELTIR_NPC_ID:! f: n, I z6 t! s/ z0 x$ u
- n = getCount(st)7 i0 ^4 q/ e( ~0 }) N* ~
- if n == 0: V0 B1 O; S7 |& M
- if st.get('chat0') == None :
7 z, _* r# x8 }6 C5 U, H# r8 Y* q' o$ X - st.set("chat0", "true")
. b- m& R& z. N+ L+ H9 k1 n - return "Chat0.htm"
0 H: e& S5 {3 d3 g' A4 y! j - elif n == 1:: w" n5 \% n; V- i- ?
- if st.get('chat1') == None :: U$ u3 }/ E& T/ W ^ B
- st.set("chat1", "true")5 X! c9 z/ u) w
- return "Chat1.htm"
% `+ a5 f' r, B) U+ s8 M1 X - elif n >= 4:% Y; A8 a$ j6 S2 s$ _# P8 @5 o( m
- return "Chat4.htm"; D B( e8 d3 Q* g
- return "Collect "+str(n)+" of 4 fangs"
8 L* Y6 P# n; v - return
% f5 Z% \, c3 J3 a - ' X+ R/ |& H' f; [$ h" }, |
- QUEST = Quest(201, "Tutorial", "Tutorial quest")+ s$ R3 s; s6 _. `
- CREATED = State('Start', QUEST); ]0 ~7 Y' ?' H1 Z. x' n
- STARTED = State('Started', QUEST)
+ o [: d) p& V2 w - COMPLETED = State('Completed', QUEST)
^" G! e) C# y) J$ r) V+ ] - 0 V0 l* x/ L# c- D, ~8 x
- QUEST.setInitialState(CREATED)
3 Q) ~7 j( G# B3 z - QUEST.addStartNpc(7056)
) C! j+ }5 t. U - QUEST.addStartNpc(7012)$ m6 J2 K5 b! f) {: w, W
- QUEST.addStartNpc(7009)
1 C+ Y Y/ B* l! H - QUEST.addStartNpc(7011)/ t. J0 C5 }+ @: G! J0 q
( p( s$ q0 k/ w; p X& s- STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
$ n8 x9 O% |. i- H - STARTED.addKillId(KELTIR_NPC_ID)
7 k; n/ |! [1 M, x: ^5 ] - STARTED.addTalkId(7056)' _, Y2 U/ b$ x0 v; Z. i
- STARTED.addTalkI d(7012). ?) j, {" a9 S9 `8 `. ^' i
- STARTED.addTalkId(7009)
* f0 A4 u5 ~9 I4 V8 Q - STARTED.addTalkId(7011)
Скопировать код : Q9 J' ~( @( N. k0 B# p' a2 y
6 n- G. D7 }1 O. Z
|