Зарегистрируйтесь сейчас чтобы найти еще больше друзей, и получить полноценный доступ ко всем функциям сайта!
Для просмотра Вам необходимо авторизоваться Если Вы еще не зарегистрированы, перейдите по ссылке:Зарегистрироваться
x
Хроники Interlude
/ Z! y' C$ a2 rСборка L2j
, m! ]- z% g4 H1 ^' n7 E0 b! HОбратите внимание: в файле htm стартового NCP обязательно должна быть ссылка на квест:4 B( D$ p! u# P1 i5 y: K
- STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код Для этого квеста больше ничего не надо. Все необходимое для корректной работы квеста уже добавили. Вот полный текст квеста:
! U0 `9 h; t# |0 I
4 r4 [8 c& M9 ?% K1 j- if getCount(st) >= 4 :
- k0 F5 G, ]5 A- E3 |9 `# Z4 P - completed(st): j1 b3 @$ _/ P7 v: ]7 M
- return1 |5 U3 M7 l8 ]& A+ o. Z9 T
- ) l) E, n; `! _$ u
- class Quest (JQuest):- t8 Q( p' P& j- k( G# u
- def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)3 `9 |+ t8 V) W) }6 C
- def onEvent (self,event,st):/ _- v+ D/ Q$ z2 M, F8 I
- id = st.getState()6 ]: ]3 d$ \6 L( I4 |% p4 Z' E
- if id == CREATED : st.setState(STARTED)
% |$ t) y6 X& S/ ]# }: ~$ W" f - elif id == COMPLETED: pass& h& ]9 e) [) H0 ` v
- elif id == STARTED : check(st)
5 v2 m! K; b5 ~- w) u1 [ - return9 a" O" [3 J! B( Z+ o
- ; z0 U" } D" m/ ^
- QUEST = Quest(201,"Tutorial", "Tutorial quest")
, x. k3 j* Q7 g' k, n" t - CREATED = State('Start', QUEST)
/ q! L; M3 [$ p, ~# b - STARTED = State('Started', QUEST)
; v/ m3 r) `2 ~4 s' m9 m" g9 D - COMPLETED = State('Completed', QUEST)4 _' h* S1 R4 y- W
- 6 T+ P# l; F4 Y0 ^) s& {, X
- QUEST.setInitialState(CREATED)) l$ _/ |: i6 _3 ~, B3 B6 Z- H* v
- QUEST.addStartNpc(7056); G, {' k- K9 w
- STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код Теперь рассмотрим, как это работает.
0 |9 v: N0 R" U/ y5 }% xИгрок подходит к начальному NCP (в данном случае 7056), нажимает на «Quest». Квест будет создан и состояние квеста перейдет к CREATED и игроку будет показана страничка Start.htm с описанием квеста. Тогда метод onEvent, поле открытия странички Start.htm переведет состояние квеста в STARTED и игроку будет показана страничка Started.htm, где будет опсание того, как найти keltirs и .т.д.( Z9 ?. C4 d" \3 R
1 ?$ U3 v- F9 W6 m5 l; v, G5 E1 m
4 y/ b2 u8 b. ^4 K; ~& ]' {
При состоянии STARTED будет зарегистрирован дроп «fangs» при убийстве keltirs. Игрок может вернуться к стартовому NCP и спросить о квесте – метод onEvent будет вызван снова. Если у игрока не хватает необходимого количества предметов, то метод check() не переведет квест в следующее состояние и Started.htm будет показана снова. Но если игрок собрал необходимее количество предметов (в данном случае 4 клыка), то метод check() вызовет метод completed() который переведет квест в новое состояние COMPLETED, заберет все клыки, даст карту мира, т.к. это награда за квест, покажет Completed.htm и завершит квест.4 V0 A: W* j: _' @2 k
. a6 L. U1 B9 G
/ C9 s+ r% G) eТеперь давайте сделаем наш квест более похожим на то, что он должен из себя представлять.
& b$ J5 B* l4 y2 k' PПрежде всего у нас есть 3 метода для объявления их в Яве – onTalk, onKill и onEvent. Если методы onTalk и onKill не объявлены, то за них все будет делать метод onEvent, т.е. определять квестовых монстров и вызывать диалоги NCP. Есть примечание, методы onTalk и onKill будут вызывать только диалоги с NCP в зависимости от текущего состояния квеста. Метод onKill будет вызываться только тогда, когда мы убиваем квестового монстра.3 O, q0 e+ ^9 Y5 L! a) A
% P6 w) j, o4 S
7 w3 ?1 \ G- _9 xДавайте рассмотрим как вызывается метод onKill при убийстве keltir в состоянии квеста STARTED:1 j- o( O$ I" H5 Y U8 p% F# j' g% ~
- STARTED.addKillId(KELTIR_NPC_ID)
Скопировать код и метод onKill в классе Quest:
$ U' Y H; z9 h, ~3 u. v% |' L/ I0 o" d- u$ B5 b. c j3 a% k
- class Quest (JQuest):
& @7 b$ Y0 y' A$ [! n - .... F& q; C1 s! o/ g
- def onKill (self,npcId,st):
# y' }$ Y/ n: i! H - if npcId == KELTIR_NPC_ID:4 ^# f* H9 ~6 j$ @2 j0 l1 q( i, @
- n = getCount(st)' h. p8 z; M5 V7 @) r
- if n == 0:
$ @ [7 b1 n( J- m! ]7 | - return "Chat0.htm"" I; \4 [: y! \2 C
- elif n == 1:
. Z* @; Y+ k: g- O - return "Chat1.htm"+ ]( D, h M+ b) z' y9 l
- elif n >= 4:8 S3 i9 p' V- O$ ?$ J% [3 q
- return "Chat4.htm"
. g2 o% U* x. c - return "Collected "+str(n)+" of 4 fangs"
% {% F" a, f. I. d- J* \ - return
Скопировать код Метод onKill (а так же метод onTalk) имеет следующие параметры:) o n3 O! U& J1 E; \
4 G8 l6 S* X, R6 N
6 W, b" C# z5 s& E5 Y. I• self – квест
4 D1 f, |( z( R' ^3 u$ D/ o• npcId – ID NCP, которого мы должны убивать (если это метод onTalk, то ID того NCP, с которым мы должны поговорить).
4 u) d2 }' V; w9 y# d: x, \• st – текущее состояние игрока.
7 C5 W5 h) r Z2 d, i
5 i, E/ B0 M1 V/ F+ T: I- R) s2 P/ V1 e+ e1 i( o+ z% j
В этом методе мы проверяем и отмечаем, является ли убитый NCP keltir’ом. В основном эта проверка не нужна, т.к. у нас только KELTIR_NPC_ID.2 l" N6 ?; A1 G7 l3 Y
: L; S; h! P6 n
/ N" B9 W4 F! }' O! x
Затем проверяем количество предметов (в данном случае количество клыков), и если их вообще нет, то возвращаем строку "Chat0.htm", если только один предмет, то возвращаем строку "Chat1.htm", если же предметов 4 или больше, то "Chat4.htm". Если строка возвращена из методов onEvent, onKill или onTalk, то сервер покажет соответствующие htm. В Chat0.htm может иметь следующий текст: «Вы не имеете ни одного клыка, возвращайтесь позже, когда соберете 4 штуки и бла, бла, бла…», в Chat1.htm может быть следующий текст: «У Вас всего 1 клык, по этому соберите еще…». В Chat4.htm – «Вы собрали необходимое количество предметов, возвращайтесь к вашему тренеру, что бы завершить квест…»
% m: g* H, ~8 P4 i+ e+ L3 o* j4 I' k0 [5 S
+ T6 }- U* ?4 c+ m! o6 i. HПримечание: если в строка return начинается с "<html>", то будет показана страничка html с текстом, который стоит далее. Так вместо:
- {6 u; `7 p# L$ @" _- Treturn "Chat4.htm"8 U) F, N" G+ Z
8 b" U9 D5 A. d2 ?% x
9 ~; t0 G% K: nможно поставить:. V8 s, K. Z9 a. `
- return "<html><body>Return to your trainer to complete the quest</body></html>"
Скопировать код Так же если строка заканчивается без .htm или в начале нет <html>, то текст будет выведен, как системное сообщение в окне чата. В нашем случае мы сделаем так, что бы при каждом убийстве keltik выводилось системное сообщение: «Собрано N из 4-х клыков».
, F+ C) h9 u! d8 _1 I8 N6 a
3 ]' Y, M$ C0 ]( J3 C0 c$ C4 x" {+ R
Наш код для onKill имеет один недостаток. Он будет постоянно показывать Chat0.htm, Chat1.htm и Chat4.htm, нам же необходимо, что бы Chat0.htm и Chat1.htm показывались только один раз. Как нам это сделать? С помощью переменных.
# \2 s' \! r' _+ [
9 K: y' |' {- M$ e" \6 L
, Y% o6 D, h7 T/ o( V; }В каждом квесте строки могут храниться с помощью переменных. Эти переменные сохраняются в Вашей БД. В каждом методе мы можем назначить, прочитать и удалить переменные. Давайте изменим метод onKill, так что бы каждый диалог вызывался только один раз.
9 v# c4 ]4 ^7 z" ]* ~; L- def onKill (self,npcId,st):, L' ]- G* M* i3 e
- if npcId == KELTIR_NPC_ID:
- ~8 N+ N1 h' g/ l - n = getCount(st)
! D- V; H% y! Y. C( S - if n == 0:
4 k0 v3 Q* I$ K* C* a - if st.get('chat0') == None :
$ H. F- {) |4 C+ m - st.set("chat0", "true")
8 A% \9 o# C& c- y - return "Chat0.htm", T1 W2 w' s5 w+ S5 |8 G. [: A
- elif n == 1:! X9 S6 K: S9 W3 H2 U) k
- if st.get('chat1') == None :
& l2 F9 y1 I$ E1 I9 r0 Y% F$ s - st.set("chat1", "true")1 B9 P" c$ M, C' k8 a
- return "Chat1.htm", J8 m$ o& O7 y- u1 E
- elif n >= 4:* d5 D7 B4 L% w5 {5 V
- return "Chat4.htm"6 l3 S' s5 y6 |$ n) l6 O" @3 P
- return "Collected "+str(n)+" of 4 fangs"* E x" O1 J8 {' W. [) L3 W0 I
- return
Скопировать код Если у игрока нет клыков (n=0), то мы получаем занчение переменной 'chat0'. Когда метод onKill вызван в первый раз, то пока ни каких переменных не имеется и python возвращает значение None. В этом случае объявляется переменная и показывается диалог Chat0.htm. Когда мы убиваем keltir, но не получаем с него клык, функция st.get('chat0') возвращает строку true, а не None. И во второй раз окно с Chat0.htm не появится, но в окне чата появится строчка «Collected 0 of 4 fangs». По тому же принципу сделано и с Chat1.htm.
5 W! T4 D2 P/ ] `. y' y7 o% p" c# R9 S3 s3 j
2 ?0 f& k3 \! l
Вот конечный рабочий вариант квеста:
% f* X0 u( W4 l, h* X1 v- import sys
( h0 y u0 Z+ ?. U2 [* \8 @& | - from net.sf.l2j.gameserver.model.quest import State/ t+ R/ l( r4 v5 [
- from net.sf.l2j.gameserver.model.quest import QuestState
9 Q/ Z* v# I6 E" M; \. L% c' N - from net.sf.l2j.gameserver.model.quest.jython import QuestJython as JQuest
9 J) k7 K& Z( Q3 q1 }
0 B& A5 F* I" f$ X$ t# A$ s- KELTIR_NPC_ID = 12082
) r w8 L2 [; \" |& t! q - FANGS_ITEM_ID = 1859# ]: F1 g- O$ |1 x3 Z8 h# P( B1 x
- DROP_RATE = 500000& o% X1 q. Z$ j- `0 i
- # f6 i% D7 e. n/ E2 H; _ J* X) w
- WORLD_MAP_ITEM_ID = 1665
' K: v$ z% z( Q3 `
' b0 k* N @; ]4 n6 z0 W0 u- def getCount(st) :
1 b2 Y+ [% p8 `3 \; X4 P7 y/ C# v - return st.getQuestItemsCount(FANGS_ITEM_ID)
" H5 i/ q9 t4 D$ ] - " B" ]3 u2 c# c6 }
- def completed(st) :3 V/ q- P0 ^5 n' i0 v- E V1 l
- st.setState(COMPLETED)$ E8 @- v2 i5 ]7 E1 B5 H
- st.clearQuestDrops()$ K1 R8 o# U( t. K; x6 c4 M
- st.takeItems(FANGS_ITEM_ID,-1)! h4 k! v( `& d0 |$ o( X' Q! u
- st.giveItems(WORLD_MAP_ITEM_ID,1)
6 t' s; w' u6 Q H% B6 p$ C8 L: o* i% k - st.exitQuest(False)/ d4 u- v4 r5 P/ M8 p$ Q5 V s* m
- return
+ a3 u6 G! H# X' _! Z
* w; v5 w$ E/ B- W, B) A3 u5 D- def check(st) :
( b0 _ m+ d3 o% D) `0 Y - if getCount(st) >= 4 :- y+ l2 B8 B7 g' ?+ d) N, H
- completed(st)7 u0 \( X- l: Y8 X! h. i5 r) R
- return$ x3 v5 L. O; X* {. s* I; s
4 t6 g7 w F! c3 |) M; Q- class Quest (JQuest):) p- ?8 b# ^: c9 _* e: K( J
- # J. H( |4 V& B' s. N
- def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)
3 j4 V* o- o$ L5 d" t- Q - 8 N9 G/ s. {. Q: i- s. l: Z
- def onEvent (self,event,st):; _3 G+ `# y+ Q, l) D6 c1 u
- id = st.getState()8 ^% ^3 d' A% t: ~' M2 \
- if id == CREATED : st.setState(STARTED)
H M4 P. R% O$ }' A - elif id == COMPLETED: pass* a8 x& o) m) b8 D1 A
- elif id == STARTED : check(st)! Q' c$ s, K- A' g" v$ b/ C
- return
0 U9 G% s, y. N2 W: H
/ C, f* ^; i& ]# B x- def onKill (self,npcId,st):
% p3 g& E/ }( q - if npcId == KELTIR_NPC_ID:5 d0 I4 L0 n5 s" W
- n = getCount(st)3 q) D# ?8 k' }+ z' E
- if n == 0:
5 ^2 {9 [5 ?4 _7 K! p0 K - if st.get('chat0') == None :5 t' M5 E- V+ S' d
- st.set("chat0", "true")
. Q/ Z6 B$ _% d; h - return "Chat0.htm"' |% P( t) h+ R* e: y4 \
- elif n == 1:
4 L7 q D3 c/ P - if st.get('chat1') == None :4 w* r# q, O0 }' v- k' q
- st.set("chat1", "true")" O( U! A0 S+ L$ b$ A" k8 C+ [
- return "Chat1.htm"
' }$ Q0 h, ^' T* v3 Y - elif n >= 4:. v9 ]. b; B0 h. `1 b3 e1 O* v
- return "Chat4.htm"
5 p* g2 h3 I$ e6 G8 R - return "Collect "+str(n)+" of 4 fangs"+ c, s2 U( @9 x, L
- return
B. M9 ^/ N+ [' v - 4 [ I3 f' s! ?: _( s; @* L4 T
- QUEST = Quest(201, "Tutorial", "Tutorial quest")3 U1 b5 N. _/ d- R9 S7 u3 j
- CREATED = State('Start', QUEST), L* \$ A9 K5 E) g9 H
- STARTED = State('Started', QUEST)3 C3 p2 f. M# {' Z( U! I1 S% ]
- COMPLETED = State('Completed', QUEST)
8 v" x) l# Z+ T4 h( F1 p3 P
0 {" L4 n5 w) s& D- QUEST.setInitialState(CREATED)- O& C4 b K8 I _8 V
- QUEST.addStartNpc(7056)
1 s- E Q' |3 V" v - QUEST.addStartNpc(7012)
. T) m9 s7 Z- [, p5 t6 ~ - QUEST.addStartNpc(7009)2 S. M! A7 }, m6 G3 {
- QUEST.addStartNpc(7011)
3 b! H9 f4 D2 T5 p8 v
6 V3 U, x1 o, \' j; n9 M$ j; e- STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
# W% R" {' K4 v* Y - STARTED.addKillId(KELTIR_NPC_ID)
0 {/ M/ U/ W5 A% W( H! a% C - STARTED.addTalkId(7056) U" y8 ?# A" O7 n2 H; J
- STARTED.addTalkI d(7012)
" r A" k5 a/ X6 ?) q( j$ E2 _4 K7 B - STARTED.addTalkId(7009)
7 P6 P! ~: ^$ V( n" V" c" u - STARTED.addTalkId(7011)
Скопировать код
& S3 m" ?4 z9 K4 r
+ \2 }& ]' |! E: |/ [, e! O3 I |