Зарегистрируйтесь сейчас чтобы найти еще больше друзей, и получить полноценный доступ ко всем функциям сайта!
Для просмотра Вам необходимо авторизоваться Если Вы еще не зарегистрированы, перейдите по ссылке:Зарегистрироваться
x
Хроники Interlude
7 h9 m/ q9 y. q; ~- K& P) {9 {Сборка L2j
% x9 p$ [. A2 S* r6 m1 c5 VОбратите внимание: в файле htm стартового NCP обязательно должна быть ссылка на квест:" C+ V0 P g# R& {7 g3 i0 H- d
- STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код Для этого квеста больше ничего не надо. Все необходимое для корректной работы квеста уже добавили. Вот полный текст квеста:5 H1 P# {7 Y0 c' ]0 |
$ A+ e1 K; L7 y' ^0 l& c
- if getCount(st) >= 4 :. v. i: \, q" X+ d
- completed(st): A( V# S e" D; _6 r9 @; u
- return
( }9 h0 J" |1 e: t7 u y1 h
1 h* I& z& t4 K$ r9 g7 w; S- class Quest (JQuest):
$ P5 b; m* c8 K- Y, l/ A1 B - def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)
4 e" ~1 M4 f: [ - def onEvent (self,event,st):! t5 Z& b T( L) v
- id = st.getState()
9 p. {5 ] u" \: ^( e7 _5 N - if id == CREATED : st.setState(STARTED)
' v9 K3 K! f. j& f - elif id == COMPLETED: pass
5 p2 c. `. W% k" H2 b0 }5 a - elif id == STARTED : check(st)
" l: K3 b1 P. l! V% l8 Q: b/ z - return9 u- i. l0 t5 u3 }/ r4 U0 u
4 P% a" E4 O# x1 }) _- QUEST = Quest(201,"Tutorial", "Tutorial quest")
: @" C' |0 ]3 s; y - CREATED = State('Start', QUEST)
$ g1 U& x, f+ }0 x' O% l/ T* S - STARTED = State('Started', QUEST)
~. W: }6 y+ [ - COMPLETED = State('Completed', QUEST)
: \1 H" o) C6 v
% W0 m; A* j" T5 q% {, M- QUEST.setInitialState(CREATED). b5 o9 ^* I( z& |) J8 W1 r2 g
- QUEST.addStartNpc(7056)
3 j% z1 r; T& c8 @" c! q# c1 L, ~ - STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код Теперь рассмотрим, как это работает.; S! @% Q _) c+ `; g5 n
Игрок подходит к начальному NCP (в данном случае 7056), нажимает на «Quest». Квест будет создан и состояние квеста перейдет к CREATED и игроку будет показана страничка Start.htm с описанием квеста. Тогда метод onEvent, поле открытия странички Start.htm переведет состояние квеста в STARTED и игроку будет показана страничка Started.htm, где будет опсание того, как найти keltirs и .т.д.
/ q+ [0 B" r( Z [/ y
) n* K" F& u# l6 e! \- b, k' p$ C1 [
При состоянии STARTED будет зарегистрирован дроп «fangs» при убийстве keltirs. Игрок может вернуться к стартовому NCP и спросить о квесте – метод onEvent будет вызван снова. Если у игрока не хватает необходимого количества предметов, то метод check() не переведет квест в следующее состояние и Started.htm будет показана снова. Но если игрок собрал необходимее количество предметов (в данном случае 4 клыка), то метод check() вызовет метод completed() который переведет квест в новое состояние COMPLETED, заберет все клыки, даст карту мира, т.к. это награда за квест, покажет Completed.htm и завершит квест.
5 N3 r$ T, }5 ~; M
4 ]! n& d8 u; ~5 G) f: o
9 k* A4 |; b9 j' zТеперь давайте сделаем наш квест более похожим на то, что он должен из себя представлять.
- t- f. C. q2 t w5 vПрежде всего у нас есть 3 метода для объявления их в Яве – onTalk, onKill и onEvent. Если методы onTalk и onKill не объявлены, то за них все будет делать метод onEvent, т.е. определять квестовых монстров и вызывать диалоги NCP. Есть примечание, методы onTalk и onKill будут вызывать только диалоги с NCP в зависимости от текущего состояния квеста. Метод onKill будет вызываться только тогда, когда мы убиваем квестового монстра.. k9 ]( M% ~: t- Q& ]& S1 O
3 |. f3 z% e* t( q( G
3 i, v: D8 `4 l, l! H8 H+ ^2 h" d
Давайте рассмотрим как вызывается метод onKill при убийстве keltir в состоянии квеста STARTED:
+ T# P+ J* i j1 ~+ p- STARTED.addKillId(KELTIR_NPC_ID)
Скопировать код и метод onKill в классе Quest:; d' @0 @+ u$ q$ z4 l
* u+ Z H4 ?% Z! `& u% ~* h' f0 R" M
- class Quest (JQuest):+ z+ I: z2 D9 P( Q+ {/ G- c7 q" n
- ...
5 Z- Q6 n7 ~ B ^3 M - def onKill (self,npcId,st):: l6 w! d( ^; Q" [, G3 n2 |4 Z
- if npcId == KELTIR_NPC_ID:! t: K/ ~* S" w% v6 \& V
- n = getCount(st)
" ^2 i5 Z* y9 R1 e7 I8 Q" f - if n == 0:
) q( g/ A8 m7 w& \8 _ - return "Chat0.htm"$ O4 G: |$ p) ?
- elif n == 1:
6 v O; I1 P* C; y& }+ ~ - return "Chat1.htm"
1 O6 ~) h' Z) j- `; U; J - elif n >= 4:2 N/ k. f) _6 b# a5 @# b
- return "Chat4.htm"
$ m. y: c; A( ]7 H" @! g& r - return "Collected "+str(n)+" of 4 fangs"( y& Y# p9 U/ a
- return
Скопировать код Метод onKill (а так же метод onTalk) имеет следующие параметры:. ]* m. M1 I8 f" q* F: b. k
" g0 t* b L! c' g: _
( P' T3 D d8 n$ J3 r• self – квест
, M& I3 g# r& `+ V• npcId – ID NCP, которого мы должны убивать (если это метод onTalk, то ID того NCP, с которым мы должны поговорить).
7 V" @- P0 K3 K2 R5 i8 }" @! C3 V• st – текущее состояние игрока.
1 Q; Y: X& B) }6 w$ S" s1 a7 S. s
) E ~3 i; u$ ?) n6 P4 O! [
+ n: g L* u& e* N. E& f; J: t. MВ этом методе мы проверяем и отмечаем, является ли убитый NCP keltir’ом. В основном эта проверка не нужна, т.к. у нас только KELTIR_NPC_ID.& e1 L, M+ Z# J; w% E
0 V2 M; M2 I* @, k2 p3 a
& f6 v* ]3 s$ YЗатем проверяем количество предметов (в данном случае количество клыков), и если их вообще нет, то возвращаем строку "Chat0.htm", если только один предмет, то возвращаем строку "Chat1.htm", если же предметов 4 или больше, то "Chat4.htm". Если строка возвращена из методов onEvent, onKill или onTalk, то сервер покажет соответствующие htm. В Chat0.htm может иметь следующий текст: «Вы не имеете ни одного клыка, возвращайтесь позже, когда соберете 4 штуки и бла, бла, бла…», в Chat1.htm может быть следующий текст: «У Вас всего 1 клык, по этому соберите еще…». В Chat4.htm – «Вы собрали необходимое количество предметов, возвращайтесь к вашему тренеру, что бы завершить квест…»
% Z$ Y9 n% A3 C0 r0 d& x6 G* E3 y* m2 b4 T& Q7 e) P
, ?! \6 U, K. Z- O+ i8 w, ?! [Примечание: если в строка return начинается с "<html>", то будет показана страничка html с текстом, который стоит далее. Так вместо:' N6 z4 D# D- {/ }- u) E
return "Chat4.htm"
@$ j5 Y" }/ l4 U/ f
8 s/ M! R: y- X$ r! x
# @9 u* {8 C5 `# nможно поставить:
! n h2 Q0 r# f" a7 j# [7 q! f2 \( S- return "<html><body>Return to your trainer to complete the quest</body></html>"
Скопировать код Так же если строка заканчивается без .htm или в начале нет <html>, то текст будет выведен, как системное сообщение в окне чата. В нашем случае мы сделаем так, что бы при каждом убийстве keltik выводилось системное сообщение: «Собрано N из 4-х клыков».
- C$ R, j8 w2 X' G& Q7 ]# _
! O/ _5 t! O: {
0 S' V) t/ X v, N8 SНаш код для onKill имеет один недостаток. Он будет постоянно показывать Chat0.htm, Chat1.htm и Chat4.htm, нам же необходимо, что бы Chat0.htm и Chat1.htm показывались только один раз. Как нам это сделать? С помощью переменных., i6 _4 ^! E$ }& `; f
+ [7 ^; ?/ r- @3 q
7 \1 ?$ @; V( r& ?8 n9 {В каждом квесте строки могут храниться с помощью переменных. Эти переменные сохраняются в Вашей БД. В каждом методе мы можем назначить, прочитать и удалить переменные. Давайте изменим метод onKill, так что бы каждый диалог вызывался только один раз.
6 o3 R* P# E# z/ R' _+ m- def onKill (self,npcId,st):
6 k4 q, f) r+ s9 P - if npcId == KELTIR_NPC_ID:; W i! g& A' R$ a; o( O1 z+ a9 w
- n = getCount(st)$ a* v+ X7 I: j( D% g
- if n == 0:
' A: G, b6 |8 V, O - if st.get('chat0') == None :
3 T+ D; q( h2 R - st.set("chat0", "true")* w( o3 `* R4 F) t( c6 n1 U3 x. s
- return "Chat0.htm"
0 ]$ m" G5 ?8 M( Z/ Z2 F5 ? - elif n == 1:/ P1 J; Y$ E0 l0 ~2 R# k
- if st.get('chat1') == None :7 H+ w8 C/ A# s
- st.set("chat1", "true")
' q) D) q2 l5 u6 K& H4 _6 G; T0 E - return "Chat1.htm". j* S8 _$ n. z0 D2 @7 `
- elif n >= 4:
* _8 P3 `) t$ L* a9 u, o - return "Chat4.htm"- _. k! j6 G5 K" }
- return "Collected "+str(n)+" of 4 fangs"
; G R5 U- R$ t6 ^ - return
Скопировать код Если у игрока нет клыков (n=0), то мы получаем занчение переменной 'chat0'. Когда метод onKill вызван в первый раз, то пока ни каких переменных не имеется и python возвращает значение None. В этом случае объявляется переменная и показывается диалог Chat0.htm. Когда мы убиваем keltir, но не получаем с него клык, функция st.get('chat0') возвращает строку true, а не None. И во второй раз окно с Chat0.htm не появится, но в окне чата появится строчка «Collected 0 of 4 fangs». По тому же принципу сделано и с Chat1.htm.
% |. n; ?; b6 ^% b! a
: v, N& _8 I U d& v! X; Z& d, a; v, X. d, Y" J# Z2 q- H+ q
Вот конечный рабочий вариант квеста:1 ~5 m+ t8 ~2 r7 q; N3 L
- import sys
6 @" C4 |3 Y8 }& d% N) m9 g - from net.sf.l2j.gameserver.model.quest import State' V, `1 E5 p: F' T! m; {$ c
- from net.sf.l2j.gameserver.model.quest import QuestState* Z7 S( e E+ @# H8 s3 l; D
- from net.sf.l2j.gameserver.model.quest.jython import QuestJython as JQuest
4 T8 k9 C9 |. o, n
0 G# ~7 \. l7 D/ m$ n- KELTIR_NPC_ID = 120827 L0 k6 y2 k; @1 s8 N1 G
- FANGS_ITEM_ID = 1859
, [) c3 V0 s0 ^& `2 n - DROP_RATE = 500000# B ]0 V& T2 `* k" w; B B
$ s. ~* K$ F/ a7 L3 L- WORLD_MAP_ITEM_ID = 1665
( A5 F8 i" m" M3 h* @( A - / C! U* S0 }% b( t2 F o
- def getCount(st) :
/ [* s* c$ }! ^2 v - return st.getQuestItemsCount(FANGS_ITEM_ID)
: p* N" G! J) x, n; p: J6 ? - 1 U* m: s9 y7 Q; s2 N
- def completed(st) :
7 s& @/ z7 N/ S& R; e+ t - st.setState(COMPLETED)- B% `. d3 L+ y4 i% s9 V+ ]
- st.clearQuestDrops(). }( B l7 v8 M8 k
- st.takeItems(FANGS_ITEM_ID,-1)
/ j4 L; M# W7 Z, N! ~% m - st.giveItems(WORLD_MAP_ITEM_ID,1)8 H9 m9 t. k1 _
- st.exitQuest(False)
' C) [1 P5 F$ f1 K9 `6 q. R - return
: @- _+ d- q) K. k S - ' J W& Q# k; C
- def check(st) :2 q: s5 p: P) x# H1 r
- if getCount(st) >= 4 :
, x4 h# N1 P, U! h% [7 R. O - completed(st)- m* E M V# V* {# ^) k% O
- return
, [" `8 x4 J6 g7 M - * Z, z$ U5 e! V4 B: L
- class Quest (JQuest):& M: z% R0 R7 J( v
- 3 z1 u2 v: J, k! ?2 t
- def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)
" L: S) p; _- |6 [7 E0 ]9 p' v - 9 W, G( R3 l* b4 T0 w
- def onEvent (self,event,st): ^% E+ f; e: K0 L, S
- id = st.getState()' O! {- B- p* n! @, R9 z" c: O
- if id == CREATED : st.setState(STARTED)
! w) D- \5 ]: b! z$ _ - elif id == COMPLETED: pass5 f! r" y0 \/ V( J
- elif id == STARTED : check(st)- c4 s! R _' r* k' x
- return
/ o6 m+ L- V* c2 P" T6 t ? - & n2 I3 k* _# ~3 ^8 ]0 q
- def onKill (self,npcId,st):
4 |: ^2 Z* s/ I+ f - if npcId == KELTIR_NPC_ID:
5 k" D7 j0 X* W( @% i6 l0 }& i - n = getCount(st)" q. a: @" t0 O$ o6 S) ] c! D1 n. M
- if n == 0:' d: T3 y: k ]+ O! `3 U) B: C3 K% e
- if st.get('chat0') == None :
8 Y2 p8 H5 z3 }5 Z$ V - st.set("chat0", "true")3 `7 y# }; e% m8 m; V; ^* v
- return "Chat0.htm"
M" o1 M1 s7 \- U! b - elif n == 1:
' ` R" P/ T4 Q$ | - if st.get('chat1') == None :
7 ?+ w2 \& o$ D3 F; w8 B1 A4 _2 M - st.set("chat1", "true")
4 A- X e. `+ ^+ G2 W' X1 f9 j - return "Chat1.htm"
, D _5 d/ _: L8 V) P k - elif n >= 4:
& U6 |# a' @) D$ ^/ E6 h7 B) q - return "Chat4.htm"4 r! h. _, ?( M& J R0 P
- return "Collect "+str(n)+" of 4 fangs"
* Q: y) Q+ w% J2 D - return; A5 Q% e& V8 [" \$ j2 F! c3 X
- + O+ C* `; F6 a: u- e, t! C
- QUEST = Quest(201, "Tutorial", "Tutorial quest") w1 a# ]. b1 ]" y2 w) C' s
- CREATED = State('Start', QUEST)
( U9 z* I) v' J4 |& i5 o: M! \" U - STARTED = State('Started', QUEST)
# E+ q3 G$ S" {; {5 s# @! ]3 o - COMPLETED = State('Completed', QUEST); b+ R% B% _# N+ s9 Z* U
7 [3 x/ X* r2 u! D- K- QUEST.setInitialState(CREATED)( k& a c0 J Y6 s! l# J* w
- QUEST.addStartNpc(7056)
" p9 p7 R- _1 U" K# f - QUEST.addStartNpc(7012)
$ O. n% C% P. W: ]: W% D9 o - QUEST.addStartNpc(7009)
! r1 W, m. h6 A7 r - QUEST.addStartNpc(7011)$ S) V. A. W4 Q. v4 M' i& T" {9 Y
- 0 K7 B. U: B. ~6 f: ]1 j6 h
- STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
+ u8 G z, t% t6 o+ c5 O4 @5 P9 J - STARTED.addKillId(KELTIR_NPC_ID)
`7 g! w$ ?& F7 v+ H% s - STARTED.addTalkId(7056)" D- h5 u- e# h$ @! T" |, [, }3 G
- STARTED.addTalkI d(7012)
1 D% |! B2 g8 ~$ t2 ^ - STARTED.addTalkId(7009), y3 @+ ^& g6 o* P3 G4 E
- STARTED.addTalkId(7011)
Скопировать код : i4 y0 |! Y9 m" ^, E
8 O0 R& q" N5 G
|