Зарегистрируйтесь сейчас чтобы найти еще больше друзей, и получить полноценный доступ ко всем функциям сайта!
Для просмотра Вам необходимо авторизоваться Если Вы еще не зарегистрированы, перейдите по ссылке:Зарегистрироваться
x
Хроники Interlude3 o% y& s- y- E' |- T4 L
Сборка L2j' r" j+ A- t T; r% m4 W
Обратите внимание: в файле htm стартового NCP обязательно должна быть ссылка на квест:
* t0 Z" Z1 r! ?& D! A' d, W- M* v- STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код Для этого квеста больше ничего не надо. Все необходимое для корректной работы квеста уже добавили. Вот полный текст квеста:
. J2 j q2 |0 G( d3 H/ T2 g% F S5 Q3 t' m# J
- if getCount(st) >= 4 :1 t. u$ q; G; O; H' u
- completed(st)
& Z; f: [6 q% M; z& G$ z, P - return
/ o0 }. B1 G+ s; `5 z" f# c
8 P' U: T% O# C- ]- class Quest (JQuest):
5 j. N5 Z8 @5 E, { - def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)% S. J4 |4 S6 Z7 G
- def onEvent (self,event,st):
9 s) |0 @* G4 H1 d - id = st.getState()6 s- b: O- _1 n. `% f
- if id == CREATED : st.setState(STARTED)
/ l5 D! Q5 t# }: B( ]8 L+ e9 y - elif id == COMPLETED: pass
" U% U' M, ?. z# r1 E1 W; h - elif id == STARTED : check(st) ^! r. a E: ?. _9 u" Z
- return
4 @4 ~* K: p. ]& Y% q - - V) Z. V- S' D0 K$ k
- QUEST = Quest(201,"Tutorial", "Tutorial quest")
B9 O) S+ B3 A( ?+ W9 [ - CREATED = State('Start', QUEST)9 u7 i; s' ^% C# O* C
- STARTED = State('Started', QUEST)
1 ]1 |3 s' r u - COMPLETED = State('Completed', QUEST)
. F# T Z+ S G* Z% G - 0 r) ?7 V2 @) x0 A. K; X* G
- QUEST.setInitialState(CREATED); C9 @9 x; |" y" c `. d1 r
- QUEST.addStartNpc(7056)% c. v; X! E/ K
- STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код Теперь рассмотрим, как это работает.# L+ _4 \4 l% J- n
Игрок подходит к начальному NCP (в данном случае 7056), нажимает на «Quest». Квест будет создан и состояние квеста перейдет к CREATED и игроку будет показана страничка Start.htm с описанием квеста. Тогда метод onEvent, поле открытия странички Start.htm переведет состояние квеста в STARTED и игроку будет показана страничка Started.htm, где будет опсание того, как найти keltirs и .т.д.5 b; d' R( T8 Z/ @2 _$ N" s" K. Q
( z* c7 y& ~, T1 w: _& P& c! c& I) Y9 d/ f4 ?* C
При состоянии STARTED будет зарегистрирован дроп «fangs» при убийстве keltirs. Игрок может вернуться к стартовому NCP и спросить о квесте – метод onEvent будет вызван снова. Если у игрока не хватает необходимого количества предметов, то метод check() не переведет квест в следующее состояние и Started.htm будет показана снова. Но если игрок собрал необходимее количество предметов (в данном случае 4 клыка), то метод check() вызовет метод completed() который переведет квест в новое состояние COMPLETED, заберет все клыки, даст карту мира, т.к. это награда за квест, покажет Completed.htm и завершит квест./ o, v7 u8 x6 o/ E- }4 J
8 n2 N+ Y. x5 Z2 V* O! m
4 l6 l4 O; s% e& aТеперь давайте сделаем наш квест более похожим на то, что он должен из себя представлять.
" ?3 \2 `5 u' M; j: Y! eПрежде всего у нас есть 3 метода для объявления их в Яве – onTalk, onKill и onEvent. Если методы onTalk и onKill не объявлены, то за них все будет делать метод onEvent, т.е. определять квестовых монстров и вызывать диалоги NCP. Есть примечание, методы onTalk и onKill будут вызывать только диалоги с NCP в зависимости от текущего состояния квеста. Метод onKill будет вызываться только тогда, когда мы убиваем квестового монстра. C ~) n; t6 G9 n0 H
4 m9 L z# |( T: [' M- [
% ~/ U( }6 ^& L4 o5 pДавайте рассмотрим как вызывается метод onKill при убийстве keltir в состоянии квеста STARTED:
7 M! z% J4 }( J6 ? y; J* f- STARTED.addKillId(KELTIR_NPC_ID)
Скопировать код и метод onKill в классе Quest:7 n: e0 L' Y1 |1 d6 s' O1 t7 t
6 \% D/ W9 Z1 v) p0 o- class Quest (JQuest):5 ^$ C8 F# p; \9 G0 r3 {) z& D( H
- ...
2 K* q) R' P$ i6 j - def onKill (self,npcId,st):
1 k; D1 `4 b# X - if npcId == KELTIR_NPC_ID:4 j0 L0 c: w. V; G0 i, A1 p
- n = getCount(st)
; M+ m h& o3 S, B4 N - if n == 0:
( [9 d; L; P& Z" C7 M* @2 [4 ^ - return "Chat0.htm"* `& }+ T7 c- T3 k( ]
- elif n == 1:
; n8 G3 Q5 R- ~6 V) c! h: L - return "Chat1.htm": s% A9 P. L1 p( T) @. N) r$ m
- elif n >= 4:
' b5 S. j( M$ {% ]$ p - return "Chat4.htm"
: d, K0 o# h3 W" l$ ]& [) | - return "Collected "+str(n)+" of 4 fangs"
) C7 e1 q% l+ S: v' t - return
Скопировать код Метод onKill (а так же метод onTalk) имеет следующие параметры:
* N; X$ q: ~ B: v* b) `/ ^+ @3 P3 _& d& B, @# Q/ s
2 w9 [+ s6 m6 c M* r* H
• self – квест
& N# F( l: h/ S4 J7 W• npcId – ID NCP, которого мы должны убивать (если это метод onTalk, то ID того NCP, с которым мы должны поговорить).& a6 G3 h$ T2 g
• st – текущее состояние игрока./ L% }8 K# B1 l2 G8 L6 u: } e
5 @8 @, M1 Z3 @- Q
1 O7 ~6 b0 A2 m! i8 \8 L" r! s
В этом методе мы проверяем и отмечаем, является ли убитый NCP keltir’ом. В основном эта проверка не нужна, т.к. у нас только KELTIR_NPC_ID.
6 Z3 X3 Z- e' w* w9 S" ^- Y7 k$ F! G6 e
3 c& Q0 ]% ^2 v6 g. _; `Затем проверяем количество предметов (в данном случае количество клыков), и если их вообще нет, то возвращаем строку "Chat0.htm", если только один предмет, то возвращаем строку "Chat1.htm", если же предметов 4 или больше, то "Chat4.htm". Если строка возвращена из методов onEvent, onKill или onTalk, то сервер покажет соответствующие htm. В Chat0.htm может иметь следующий текст: «Вы не имеете ни одного клыка, возвращайтесь позже, когда соберете 4 штуки и бла, бла, бла…», в Chat1.htm может быть следующий текст: «У Вас всего 1 клык, по этому соберите еще…». В Chat4.htm – «Вы собрали необходимое количество предметов, возвращайтесь к вашему тренеру, что бы завершить квест…»( d9 D. g1 S% H2 Q
- p* y; [; B0 D+ R. n t \% B
$ J' V" i4 l/ ?" I
Примечание: если в строка return начинается с "<html>", то будет показана страничка html с текстом, который стоит далее. Так вместо:- p/ }4 H: ~, C( u
return "Chat4.htm"
" a) ~" x* p/ v
8 e+ ^, j7 u7 F8 s" y# [4 Q. X
& {. J% h- i3 z: e/ s! U3 J8 Uможно поставить:& z8 B4 p" U0 t; r
- return "<html><body>Return to your trainer to complete the quest</body></html>"
Скопировать код Так же если строка заканчивается без .htm или в начале нет <html>, то текст будет выведен, как системное сообщение в окне чата. В нашем случае мы сделаем так, что бы при каждом убийстве keltik выводилось системное сообщение: «Собрано N из 4-х клыков».4 a+ f. n' U T) h7 p. t N
5 N) A ]4 r' m+ i E- R
& O, `1 m5 ]3 l4 {! TНаш код для onKill имеет один недостаток. Он будет постоянно показывать Chat0.htm, Chat1.htm и Chat4.htm, нам же необходимо, что бы Chat0.htm и Chat1.htm показывались только один раз. Как нам это сделать? С помощью переменных.
* z9 [) _( `2 k9 c
, f0 E2 }; d+ @1 G. U
. U8 ]! R4 d% l, GВ каждом квесте строки могут храниться с помощью переменных. Эти переменные сохраняются в Вашей БД. В каждом методе мы можем назначить, прочитать и удалить переменные. Давайте изменим метод onKill, так что бы каждый диалог вызывался только один раз.
3 h2 y0 d+ X9 i0 z$ j! J: V" T- def onKill (self,npcId,st):
4 i# d* E, o p - if npcId == KELTIR_NPC_ID:) F( h+ {, m* c- E5 \7 c
- n = getCount(st)
f7 @8 Y' F( q5 K - if n == 0:2 \" F3 ~* z& [* V" K
- if st.get('chat0') == None : J- P& a! ]% z. M# L0 B! Q
- st.set("chat0", "true")9 Q" N. l0 q( m: m* n# m
- return "Chat0.htm"# p! \: ?: g$ T* T/ w4 |
- elif n == 1:$ }( N0 L5 T, h$ K& G" H$ y) x( n# ~
- if st.get('chat1') == None :
: G' g$ i: J: x6 ]: Y# h. a" k - st.set("chat1", "true")
& N' T" z! ~1 c - return "Chat1.htm"* Z* ?1 K% n# L* @
- elif n >= 4:
% V4 @5 ]4 F2 e7 ]9 z1 q- s - return "Chat4.htm", ]$ I2 Q" O1 [" |, z) z8 d! H1 s
- return "Collected "+str(n)+" of 4 fangs"
3 `8 Q# V3 i! K' p) ~, Q - return
Скопировать код Если у игрока нет клыков (n=0), то мы получаем занчение переменной 'chat0'. Когда метод onKill вызван в первый раз, то пока ни каких переменных не имеется и python возвращает значение None. В этом случае объявляется переменная и показывается диалог Chat0.htm. Когда мы убиваем keltir, но не получаем с него клык, функция st.get('chat0') возвращает строку true, а не None. И во второй раз окно с Chat0.htm не появится, но в окне чата появится строчка «Collected 0 of 4 fangs». По тому же принципу сделано и с Chat1.htm.9 a. s* T6 X6 ~' I" y9 V
7 }: U: L, V/ i& I: \& @5 B
1 K/ D8 ~: q7 d: e3 v7 {6 x
Вот конечный рабочий вариант квеста:
/ v3 v, c- o0 |% C8 O- import sys
" ]8 L' _( G0 F( S - from net.sf.l2j.gameserver.model.quest import State& ?# M0 r) y3 }, [; w
- from net.sf.l2j.gameserver.model.quest import QuestState
% h: b+ k1 g, U - from net.sf.l2j.gameserver.model.quest.jython import QuestJython as JQuest
8 k# y8 s% g7 U/ z" s - 8 V8 d; b/ `- y2 W! E, V
- KELTIR_NPC_ID = 12082
J7 O* z- ?) g7 D8 b0 D, X- e - FANGS_ITEM_ID = 1859/ @. Q! M0 Z. s5 A% {
- DROP_RATE = 500000
# p' J8 N) y+ J
- I O- o1 N+ f- WORLD_MAP_ITEM_ID = 16656 D" ?7 E2 ?" p; L
- 7 L3 L5 [6 }% H# e( |
- def getCount(st) :
. \: Y' g- r) o - return st.getQuestItemsCount(FANGS_ITEM_ID)
5 R, L, T4 C1 T2 o% P8 o, r" A - ( i+ ]" s ?, O: C9 K. m1 b
- def completed(st) :% s2 H. s" R* D* J% {: F
- st.setState(COMPLETED)3 P$ e0 Q! L6 n3 D# o& T6 d7 A
- st.clearQuestDrops()
# J) ^* ?, N1 C# | - st.takeItems(FANGS_ITEM_ID,-1), O: _2 h$ T* I1 h2 A
- st.giveItems(WORLD_MAP_ITEM_ID,1)* s! ^/ \. I# f, B2 `
- st.exitQuest(False)
; x; k& I; E' Y7 b - return9 M- O/ n% a- z' D
- 3 @6 @: U- V) }6 W9 H' c
- def check(st) :1 v0 Z# Q" J* K, B2 q, K# M
- if getCount(st) >= 4 :
D- \/ g3 c" A6 U+ @0 ^ - completed(st)
\* U# l2 x2 A# U$ a* U R5 R/ A - return6 i) R( Q! F, R9 ], t0 X8 a/ k
* K# e8 b$ g6 i6 g* \- class Quest (JQuest):
2 ?8 |6 g+ b# R
# z7 Z/ R& Z# a* I/ [- def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)
$ |/ H3 D d0 S& F& G: v+ z - , B F* Q5 m, o4 }8 {
- def onEvent (self,event,st):5 [% S5 Q& ]+ P# a" M) y* P) j
- id = st.getState()3 p. i( U m$ A' M2 N2 [! d
- if id == CREATED : st.setState(STARTED)
' g: q& Y% S) m - elif id == COMPLETED: pass
' k; |" H- g5 f" A: w; D - elif id == STARTED : check(st)( Q; P h S% l- z. |- P7 D4 S3 {0 Z, b5 d
- return
; i! U6 J% f6 {0 I6 y" I# I6 I - 1 L' \0 V( A) v% {8 A; }2 h
- def onKill (self,npcId,st):7 I$ u H& X1 x/ J
- if npcId == KELTIR_NPC_ID:2 Y! g" j. b+ G" K
- n = getCount(st)
* G, x w, }+ u6 Q$ i* ^ - if n == 0:9 y) J- ?9 w+ a3 ]: O% H t
- if st.get('chat0') == None :
# u0 n) ]+ p9 f' a4 T - st.set("chat0", "true")# z2 X; ?5 |5 a& S) H
- return "Chat0.htm") X! G; g- O4 H
- elif n == 1:/ O1 w1 e3 W; q d3 W! t$ t
- if st.get('chat1') == None :) r7 j/ {/ S' n+ l& j- g
- st.set("chat1", "true")
; S, Y) z: `# e: S7 E, p5 P - return "Chat1.htm"
5 X+ A4 [% r/ G% C: H! q - elif n >= 4:& i4 n! @4 r: g' c' x
- return "Chat4.htm") b2 s: R0 H( J/ H7 l1 w4 r' K
- return "Collect "+str(n)+" of 4 fangs"
2 Z1 ]7 E* a1 {3 i9 G - return
2 _) p7 v. g* q - - Q4 w/ X7 F; |1 J0 E( N ~! w+ Y
- QUEST = Quest(201, "Tutorial", "Tutorial quest")
; p% Q# h5 E5 q3 b - CREATED = State('Start', QUEST)# f/ I% t {4 @1 a# o$ R; Q
- STARTED = State('Started', QUEST)
- s1 u/ {: f: s, j) s$ T - COMPLETED = State('Completed', QUEST)
|/ G9 D2 h, K/ U) q6 ?
; G% {8 e4 q5 B- QUEST.setInitialState(CREATED)% X) t1 E% K) i/ F0 m' I& P' ?
- QUEST.addStartNpc(7056), L; b( h f2 d7 P9 ^- H7 r( G& G
- QUEST.addStartNpc(7012)5 S: C, ^* z+ L0 }
- QUEST.addStartNpc(7009)
& U' n* g8 E2 n3 r. ^1 n - QUEST.addStartNpc(7011)
; e7 r6 ~$ C" g
2 U+ ]+ L2 C1 M% L' @- STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)- v; @3 z7 ?( L6 ^
- STARTED.addKillId(KELTIR_NPC_ID)
8 O5 g: k+ g+ b) G% ]4 E$ d - STARTED.addTalkId(7056): b$ J0 H/ _! a* B/ G
- STARTED.addTalkI d(7012)& O7 f& l3 ~7 R! _5 O
- STARTED.addTalkId(7009)
: U: g, B8 O* [' K- y- [ - STARTED.addTalkId(7011)
Скопировать код 3 `3 z8 b0 L+ |, q h: e3 e3 A
1 \$ U- {/ y0 M' h& \) ^ |