Зарегистрируйтесь сейчас чтобы найти еще больше друзей, и получить полноценный доступ ко всем функциям сайта!
Для просмотра Вам необходимо авторизоваться Если Вы еще не зарегистрированы, перейдите по ссылке:Зарегистрироваться
x
Хроники Interlude& M; J2 y; c0 h5 p T# c
Сборка L2j
) f5 U. T6 m( \9 z8 S/ _: ^Обратите внимание: в файле htm стартового NCP обязательно должна быть ссылка на квест:0 t$ X5 D9 a9 ^3 Q6 f) ^& h
- STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код Для этого квеста больше ничего не надо. Все необходимое для корректной работы квеста уже добавили. Вот полный текст квеста:' f" b8 S; K$ K ^3 M
$ j" o/ X0 k0 m$ a8 `) o% z% `- if getCount(st) >= 4 :
. X3 O' ?& ]6 a y' D - completed(st)0 ?! t$ r. \# u' p
- return D7 B1 }5 U. G0 O. r% l
- - o, B* ~5 g9 w# ~4 L- D3 W
- class Quest (JQuest):/ \4 w$ o# s+ d& s* J5 E) g# t
- def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)8 c# s) }. N2 p( R/ j
- def onEvent (self,event,st):5 ?: ?% M) M# X: q7 A0 W! c
- id = st.getState(), `5 d. B, O/ M- k
- if id == CREATED : st.setState(STARTED)4 h% V- t; G4 B R+ q
- elif id == COMPLETED: pass9 k) _8 g3 Y0 a' V2 E: h/ r
- elif id == STARTED : check(st)
& X' _" t# ]1 q" M ~7 E7 X) C - return
& O& j7 r" ~2 W
! B- V! w% {. d9 U" f' p( h- QUEST = Quest(201,"Tutorial", "Tutorial quest")
% z( @: L* v6 V9 M+ \ - CREATED = State('Start', QUEST)( v# Z+ M" K( W3 j
- STARTED = State('Started', QUEST)$ ?, X1 y1 q3 _) p0 _+ e
- COMPLETED = State('Completed', QUEST)
: I# g9 w+ k: o
, s ^0 g, M4 x& B2 K7 [* v' z& R- QUEST.setInitialState(CREATED)
. d. \0 j0 u1 ?3 _& K - QUEST.addStartNpc(7056)
7 z/ e$ n- w h3 r - STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код Теперь рассмотрим, как это работает. Q0 r/ o2 J/ ^: Q0 z
Игрок подходит к начальному NCP (в данном случае 7056), нажимает на «Quest». Квест будет создан и состояние квеста перейдет к CREATED и игроку будет показана страничка Start.htm с описанием квеста. Тогда метод onEvent, поле открытия странички Start.htm переведет состояние квеста в STARTED и игроку будет показана страничка Started.htm, где будет опсание того, как найти keltirs и .т.д.5 N3 f; d5 Z0 c. [3 d$ E& Z- k
/ {! k, T( ^+ U$ A% F
9 R, e. y+ }0 Y! GПри состоянии STARTED будет зарегистрирован дроп «fangs» при убийстве keltirs. Игрок может вернуться к стартовому NCP и спросить о квесте – метод onEvent будет вызван снова. Если у игрока не хватает необходимого количества предметов, то метод check() не переведет квест в следующее состояние и Started.htm будет показана снова. Но если игрок собрал необходимее количество предметов (в данном случае 4 клыка), то метод check() вызовет метод completed() который переведет квест в новое состояние COMPLETED, заберет все клыки, даст карту мира, т.к. это награда за квест, покажет Completed.htm и завершит квест.
8 x+ D9 k7 ~2 }: `; K% W3 a) `4 Z/ }' P3 Q. J) l8 p4 D
5 A& | S9 v9 Z0 r
Теперь давайте сделаем наш квест более похожим на то, что он должен из себя представлять.
O8 |( Q6 H$ w% ^4 bПрежде всего у нас есть 3 метода для объявления их в Яве – onTalk, onKill и onEvent. Если методы onTalk и onKill не объявлены, то за них все будет делать метод onEvent, т.е. определять квестовых монстров и вызывать диалоги NCP. Есть примечание, методы onTalk и onKill будут вызывать только диалоги с NCP в зависимости от текущего состояния квеста. Метод onKill будет вызываться только тогда, когда мы убиваем квестового монстра.
. q4 Q0 k: z) U7 W5 ]( R, l8 G* v* \* F# `
' h1 o$ f1 ~: S4 N* C
Давайте рассмотрим как вызывается метод onKill при убийстве keltir в состоянии квеста STARTED:" T# U8 U" a1 G$ k/ ~, {
- STARTED.addKillId(KELTIR_NPC_ID)
Скопировать код и метод onKill в классе Quest:, a5 u% J3 w. m; ~, x- N
1 h2 e% {$ L7 C2 m" d+ @* H- class Quest (JQuest):
0 K0 D' R2 h; e! y/ I( } - ...) l- U# _- j! D) w$ o- H9 v
- def onKill (self,npcId,st):, E# F6 ~- O% D; J" N
- if npcId == KELTIR_NPC_ID:
' h7 x- n) |$ n# E$ ? - n = getCount(st)
) G2 @9 @ g% r% p% C" C# V( ^5 O - if n == 0:, |0 A( I/ w* a
- return "Chat0.htm"# w. d+ c4 _7 L0 x0 D' U: G
- elif n == 1:! A4 i0 E. b' R H4 ~' d, h# u
- return "Chat1.htm"
+ {) j ^$ s" t/ z2 I7 V7 f - elif n >= 4:0 H9 b) z9 c% C: c
- return "Chat4.htm". J# N) \. ]' V' D# {' b, R- e+ [
- return "Collected "+str(n)+" of 4 fangs"+ }3 S+ R- Y* j& \
- return
Скопировать код Метод onKill (а так же метод onTalk) имеет следующие параметры:' R/ _: v) w0 Y
# [# T- J ?, Y3 m1 ^. I0 J
- Z+ D. Z6 m+ p) p. s% ^* V0 W6 y• self – квест
0 S; S X8 e' }! c; ?• npcId – ID NCP, которого мы должны убивать (если это метод onTalk, то ID того NCP, с которым мы должны поговорить).
5 y+ d S v- P, T: V• st – текущее состояние игрока.
& D+ W8 ^- z. s" ^8 R
3 E! o8 ^" k. l" S7 W/ S! {' g! i% d* d9 ~1 ?& `- F) E, p
В этом методе мы проверяем и отмечаем, является ли убитый NCP keltir’ом. В основном эта проверка не нужна, т.к. у нас только KELTIR_NPC_ID.8 H- s" l2 g" j7 @; z S7 P
9 V3 P8 y" E& O4 p0 B9 O& ^5 V% R8 o- P8 J* U
Затем проверяем количество предметов (в данном случае количество клыков), и если их вообще нет, то возвращаем строку "Chat0.htm", если только один предмет, то возвращаем строку "Chat1.htm", если же предметов 4 или больше, то "Chat4.htm". Если строка возвращена из методов onEvent, onKill или onTalk, то сервер покажет соответствующие htm. В Chat0.htm может иметь следующий текст: «Вы не имеете ни одного клыка, возвращайтесь позже, когда соберете 4 штуки и бла, бла, бла…», в Chat1.htm может быть следующий текст: «У Вас всего 1 клык, по этому соберите еще…». В Chat4.htm – «Вы собрали необходимое количество предметов, возвращайтесь к вашему тренеру, что бы завершить квест…»
# x$ p5 j8 U, B: o- r1 L2 r
4 p$ ]9 ^+ B1 q, i: @5 K# r. C, K) P# T5 i
Примечание: если в строка return начинается с "<html>", то будет показана страничка html с текстом, который стоит далее. Так вместо:
; `3 v8 Q9 A3 C6 `return "Chat4.htm"
* v' g- e: I0 L! N* r% ^0 v* y) i0 B/ _. q1 V: P( `% F. K0 z i# L
1 @5 Y5 x+ s _# p2 M) Eможно поставить:
3 j" r q W5 e3 o3 R( f- return "<html><body>Return to your trainer to complete the quest</body></html>"
Скопировать код Так же если строка заканчивается без .htm или в начале нет <html>, то текст будет выведен, как системное сообщение в окне чата. В нашем случае мы сделаем так, что бы при каждом убийстве keltik выводилось системное сообщение: «Собрано N из 4-х клыков».
+ Z8 @' i, Q9 ?( a$ e! \4 X0 A0 K9 m( C! T4 A2 M. N! ?
5 `; @1 p" r$ K, e$ M) ?1 B
Наш код для onKill имеет один недостаток. Он будет постоянно показывать Chat0.htm, Chat1.htm и Chat4.htm, нам же необходимо, что бы Chat0.htm и Chat1.htm показывались только один раз. Как нам это сделать? С помощью переменных.8 T6 G4 f5 y- t9 F9 N6 u. B
3 ?8 E" A/ \, I" g x
U2 r5 _( c' H2 Y# t6 ~, @7 ^В каждом квесте строки могут храниться с помощью переменных. Эти переменные сохраняются в Вашей БД. В каждом методе мы можем назначить, прочитать и удалить переменные. Давайте изменим метод onKill, так что бы каждый диалог вызывался только один раз.
/ z$ N; e, A: K; C0 B% h- def onKill (self,npcId,st):
! M k- h4 l/ F: X; ~7 B# i7 s - if npcId == KELTIR_NPC_ID: O) U8 h! H. _1 f
- n = getCount(st)
! Y! F* {; E$ I2 g - if n == 0:: a& f% a4 v+ B# P& w
- if st.get('chat0') == None :
7 _3 ~6 F) F) U. R8 b8 \ - st.set("chat0", "true")
3 D7 @' M: z" Y& y0 h, H6 N - return "Chat0.htm"1 S" A1 J6 u* f! A* @6 l% U0 T8 l/ f
- elif n == 1:
4 k7 c7 _$ j! B9 c! T - if st.get('chat1') == None :
6 O, R1 J% H f7 N - st.set("chat1", "true")
! |) K2 `+ |, O& ~. r, s - return "Chat1.htm"& W7 O( _6 ^( ~+ {
- elif n >= 4:
5 n; f1 F4 S. b7 T/ W& @ - return "Chat4.htm"
: g) m2 M' M; }3 T4 x9 i - return "Collected "+str(n)+" of 4 fangs": {% J" `6 ^9 V9 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.( T- h" f' D- Z7 P( ~
8 a) D8 P" G- z6 W4 d
, i; m8 R. f$ x9 S" |. Z7 [Вот конечный рабочий вариант квеста:! z/ S# X. H; k! F+ t7 W. m" _# r
- import sys$ r# b7 E3 v" q% M- g
- from net.sf.l2j.gameserver.model.quest import State
( E- W6 J0 q! [+ c- _$ P+ ? - from net.sf.l2j.gameserver.model.quest import QuestState
9 K9 ^/ N- @6 S+ {* G' k9 O( z6 i - from net.sf.l2j.gameserver.model.quest.jython import QuestJython as JQuest, [ ?6 Z3 {3 T# {
- * f: B9 d; L; j5 t
- KELTIR_NPC_ID = 12082
/ ?- Y2 I0 ~1 x) L, w* Z- L; ] - FANGS_ITEM_ID = 18595 {* ^% g6 ~8 v# \" {, T8 i
- DROP_RATE = 500000( |5 w6 z! f8 o3 Y% m. f9 E1 L0 c+ b2 a
D+ e; n* N8 P+ Y- WORLD_MAP_ITEM_ID = 16652 R) [5 m5 H% L1 r7 M2 g8 s
! Y7 B: O: G: C$ B$ ~$ \! K1 Z- def getCount(st) :
: |; B8 ?8 C3 {$ e6 m6 B8 j - return st.getQuestItemsCount(FANGS_ITEM_ID)
( {+ N. X9 U$ C i* v) p
0 h: m/ K" b0 Y# I3 q) K, q5 e, j- def completed(st) :
5 x: Y) `1 D2 \8 n4 Q% C+ v - st.setState(COMPLETED), i d2 m7 l5 g$ k* n/ ^
- st.clearQuestDrops()
6 M0 @6 d1 Q- q h# c) E - st.takeItems(FANGS_ITEM_ID,-1)( g( r. W% u" G
- st.giveItems(WORLD_MAP_ITEM_ID,1)
# S0 g, @7 ^1 y* \$ s* K3 _- w& ] - st.exitQuest(False)
* k l. k' z9 D0 h; Y) h - return
, h. V. B5 B" d - 4 G( L1 _. A$ E5 P
- def check(st) :8 M: z7 A: B; W! w2 E: U7 [
- if getCount(st) >= 4 :
# l C) P7 M/ S& y, j/ | - completed(st)8 d# |' x) E$ l4 f+ o- J
- return+ W. v# d: D# ^
- # m5 h8 V" H- S8 _. @% R
- class Quest (JQuest):% Q; z+ T* p7 ^9 K
6 h% W* a1 z1 k6 L F7 f- def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)! d9 ^: Z$ m, B G9 V' L( q# d
- " H% f- S- a. I! o* e s
- def onEvent (self,event,st):
7 N$ f/ k0 f; e9 D9 t$ ` - id = st.getState()
. |9 ?1 \$ V2 F; f4 t; @ - if id == CREATED : st.setState(STARTED)
C7 j9 K6 Z, z. y - elif id == COMPLETED: pass
+ E8 c' e# x* Z. O( x% H8 w - elif id == STARTED : check(st)4 {8 H1 M' W; J$ m, r- n* B
- return; p+ S" i% {5 v' Z! S
7 c4 q8 B6 u/ z% _- def onKill (self,npcId,st):
1 t) P( I. j8 o3 e% V5 ~ - if npcId == KELTIR_NPC_ID:3 Q! N1 A9 m! s2 k: O& ?2 }4 j
- n = getCount(st) F, R/ S3 J! ]8 E
- if n == 0:+ |- F6 k7 m& j( B
- if st.get('chat0') == None :
7 E5 i1 ?; F" o3 b - st.set("chat0", "true")
* E; ~( b. U6 Y" k - return "Chat0.htm"+ h; K' R+ L6 e, J$ F
- elif n == 1:
1 J$ l7 ]) a* C# z - if st.get('chat1') == None :+ Q$ w( w9 v0 o* {
- st.set("chat1", "true")
) N+ x% Y$ y- o# @* r, h. T* V - return "Chat1.htm"
4 I' Q3 N; P" q6 [& w - elif n >= 4:
- Z0 P9 V$ d/ E m. { } - return "Chat4.htm"2 K+ B1 p+ R; a+ x/ Y+ G
- return "Collect "+str(n)+" of 4 fangs"
. H ~4 L5 a9 t' E3 t/ y! x - return
! [/ g: |' ^" H7 _( L1 O, N
/ C) Y; u' r; t+ Y& u- QUEST = Quest(201, "Tutorial", "Tutorial quest")
# r$ w% E) J4 n3 j% o# R1 b+ n - CREATED = State('Start', QUEST)
/ z- `9 s8 e6 Q- I8 g; ^ - STARTED = State('Started', QUEST)3 ?' f, l$ Y y4 R' U, C, Y/ p
- COMPLETED = State('Completed', QUEST)" ]+ ~' t( M3 Q/ R+ H% b# q
2 d& c0 ]6 t" _" `; U3 r7 G- QUEST.setInitialState(CREATED): {$ @" B) ~* ^3 A
- QUEST.addStartNpc(7056)
: V; A' z' k) n, o# r - QUEST.addStartNpc(7012)
# D6 W- o$ c& @ - QUEST.addStartNpc(7009)
: V; E) c- w8 M8 A1 k/ N/ H - QUEST.addStartNpc(7011)9 [1 @! a* B1 \
' J2 o% g: Z7 \$ _7 D2 @- STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
! }- i6 F# Y8 f4 D/ j0 c - STARTED.addKillId(KELTIR_NPC_ID)
% @, }( x- h( R! ?6 | - STARTED.addTalkId(7056)- d4 Y$ x- p& z1 z5 g. w6 S6 I
- STARTED.addTalkI d(7012)
/ I2 y3 n- Q* o4 P' [/ ~$ ?/ G - STARTED.addTalkId(7009)) b9 j* ]+ b6 @+ b5 w# v. B9 L1 h9 q
- STARTED.addTalkId(7011)
Скопировать код 9 R R: X4 y! M n
/ X, D3 T X$ r. ~ |