Зарегистрируйтесь сейчас чтобы найти еще больше друзей, и получить полноценный доступ ко всем функциям сайта!
Для просмотра Вам необходимо авторизоваться Если Вы еще не зарегистрированы, перейдите по ссылке:Зарегистрироваться
x
Хроники Interlude
: H2 C' ^: ^( w0 }Сборка L2j9 u4 U5 h2 o& b# S
Обратите внимание: в файле htm стартового NCP обязательно должна быть ссылка на квест:. [1 V. T' n1 c- m5 j6 e
- STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код Для этого квеста больше ничего не надо. Все необходимое для корректной работы квеста уже добавили. Вот полный текст квеста:2 C3 V1 h; F0 v: H- {6 G. f; X3 a
- g9 y' ]+ {3 D! `- if getCount(st) >= 4 :9 M X$ a. c2 \/ i8 U* {* ^& Z
- completed(st)
3 k1 X: A: h0 v1 s. i: J4 a - return
' {! ^' _+ ^4 n) r( Z# b
7 l& v7 B; r# a. F- class Quest (JQuest):7 F8 `, q# D$ B9 a
- def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)
/ o) g* G2 F" G. l4 Q' u - def onEvent (self,event,st):: q/ S( M3 k- p; ^% n: M3 }- `" F/ M
- id = st.getState()
' i+ X; p$ t2 O4 {3 `% d - if id == CREATED : st.setState(STARTED)5 T4 |: a" ~( e# T
- elif id == COMPLETED: pass
7 z7 m7 i% G$ ?' | - elif id == STARTED : check(st)
6 B `8 A, N1 p* x4 W' X) Y0 c1 ] - return
# h( g& U {" s6 ~) i - ' Z1 E3 f7 X Y1 l2 A3 Y1 q8 M' Z
- QUEST = Quest(201,"Tutorial", "Tutorial quest"), J. C& K* K2 S, [# t$ y
- CREATED = State('Start', QUEST)
. l. D& N* J/ @- [4 M: A - STARTED = State('Started', QUEST). Y6 s% S8 o9 ~3 [" H
- COMPLETED = State('Completed', QUEST)
1 Q1 G+ t9 z; O: y0 ]# Y( `- B: p - % X. x+ @/ a3 L5 ]
- QUEST.setInitialState(CREATED)! Q: Z9 D- j! k1 J( w/ q
- QUEST.addStartNpc(7056)
; p0 b. z6 S' u - STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код Теперь рассмотрим, как это работает.. ~, a0 L: Z J+ B( d6 T/ V6 C+ |8 L
Игрок подходит к начальному NCP (в данном случае 7056), нажимает на «Quest». Квест будет создан и состояние квеста перейдет к CREATED и игроку будет показана страничка Start.htm с описанием квеста. Тогда метод onEvent, поле открытия странички Start.htm переведет состояние квеста в STARTED и игроку будет показана страничка Started.htm, где будет опсание того, как найти keltirs и .т.д.
8 @4 `- L, Z1 p$ P t1 M
! q+ c$ v, C" V
0 e" Q3 b+ S! l, E VПри состоянии STARTED будет зарегистрирован дроп «fangs» при убийстве keltirs. Игрок может вернуться к стартовому NCP и спросить о квесте – метод onEvent будет вызван снова. Если у игрока не хватает необходимого количества предметов, то метод check() не переведет квест в следующее состояние и Started.htm будет показана снова. Но если игрок собрал необходимее количество предметов (в данном случае 4 клыка), то метод check() вызовет метод completed() который переведет квест в новое состояние COMPLETED, заберет все клыки, даст карту мира, т.к. это награда за квест, покажет Completed.htm и завершит квест.& V8 V g- t) X( W7 g& k; `: F( f
+ s% O* |- n1 ~. `
: K; U1 {% k8 ^Теперь давайте сделаем наш квест более похожим на то, что он должен из себя представлять.
$ ~% ~& ?6 }6 K4 k% ~6 e6 MПрежде всего у нас есть 3 метода для объявления их в Яве – onTalk, onKill и onEvent. Если методы onTalk и onKill не объявлены, то за них все будет делать метод onEvent, т.е. определять квестовых монстров и вызывать диалоги NCP. Есть примечание, методы onTalk и onKill будут вызывать только диалоги с NCP в зависимости от текущего состояния квеста. Метод onKill будет вызываться только тогда, когда мы убиваем квестового монстра.
T ^; u2 {/ s- g
, t; N: u" N( X& R& D% W. O
. F. v a; n( c, t1 P8 ]: ~Давайте рассмотрим как вызывается метод onKill при убийстве keltir в состоянии квеста STARTED:# C) M+ e7 l: N7 h; L! @: e) x3 l) S
- STARTED.addKillId(KELTIR_NPC_ID)
Скопировать код и метод onKill в классе Quest:
' F- c% Y( T Z' W$ y5 \
. R+ h+ V! |# c, V K: y- class Quest (JQuest):
5 A, e, j2 R. z: N" O - ...
6 p7 Y5 c) J( P4 Y - def onKill (self,npcId,st):" r$ w6 |6 }- x$ ?/ N5 g
- if npcId == KELTIR_NPC_ID:+ ~5 P8 q2 w. _, j" p
- n = getCount(st)
) ?% j5 W, ~$ i8 Y( t! n6 w' A0 I$ U - if n == 0:5 l7 u: A& {0 b" {9 z
- return "Chat0.htm"$ F1 v( L+ ^ @( [
- elif n == 1:7 [+ l: H- V C5 ?% ^, J4 S# ]
- return "Chat1.htm"' {+ {+ H; a \: D
- elif n >= 4:
! v9 M# h; d& c3 Z/ ?- K - return "Chat4.htm"
0 X4 B" _ D& ?+ K( o- s$ e; I% z - return "Collected "+str(n)+" of 4 fangs"+ G; i( e8 {, O2 q% {2 \( g
- return
Скопировать код Метод onKill (а так же метод onTalk) имеет следующие параметры:" V/ A! V9 b4 p
8 o: K+ e1 M: ^, ^# X, @ |9 [
. u6 ~8 o2 S8 x' H0 U- Y
• self – квест. D4 Y2 y+ g' }0 G
• npcId – ID NCP, которого мы должны убивать (если это метод onTalk, то ID того NCP, с которым мы должны поговорить).
% p2 H9 O! S9 L( z! f• st – текущее состояние игрока.
# J) i% C$ a6 r7 Z
2 R4 M8 A3 W/ @$ O( A1 S, ?, h& `& o: {; g& y [0 r( y- L
В этом методе мы проверяем и отмечаем, является ли убитый NCP keltir’ом. В основном эта проверка не нужна, т.к. у нас только KELTIR_NPC_ID.) Z2 R+ D3 V! j0 v$ o( F: _) \
" Q' s+ n3 C# |- c; p
0 i1 |* m, N. ~! s2 A
Затем проверяем количество предметов (в данном случае количество клыков), и если их вообще нет, то возвращаем строку "Chat0.htm", если только один предмет, то возвращаем строку "Chat1.htm", если же предметов 4 или больше, то "Chat4.htm". Если строка возвращена из методов onEvent, onKill или onTalk, то сервер покажет соответствующие htm. В Chat0.htm может иметь следующий текст: «Вы не имеете ни одного клыка, возвращайтесь позже, когда соберете 4 штуки и бла, бла, бла…», в Chat1.htm может быть следующий текст: «У Вас всего 1 клык, по этому соберите еще…». В Chat4.htm – «Вы собрали необходимое количество предметов, возвращайтесь к вашему тренеру, что бы завершить квест…»6 ~; _& p! T) ~% Q% o# Z2 U
( J5 D6 n* R: C
l$ f. t4 a7 |8 D Y$ P
Примечание: если в строка return начинается с "<html>", то будет показана страничка html с текстом, который стоит далее. Так вместо:
- r9 e1 A8 ^" k1 Qreturn "Chat4.htm"" X" \$ D" X7 S" a
! y) d* K, h) Z# b
. B6 n6 o) R$ [; C, x6 }9 Vможно поставить:$ o% |# r t( m- M! v5 a
- return "<html><body>Return to your trainer to complete the quest</body></html>"
Скопировать код Так же если строка заканчивается без .htm или в начале нет <html>, то текст будет выведен, как системное сообщение в окне чата. В нашем случае мы сделаем так, что бы при каждом убийстве keltik выводилось системное сообщение: «Собрано N из 4-х клыков».( A1 Y* N8 s+ Y
! Q, u% _ g+ l' \
) {( G% O9 T N2 JНаш код для onKill имеет один недостаток. Он будет постоянно показывать Chat0.htm, Chat1.htm и Chat4.htm, нам же необходимо, что бы Chat0.htm и Chat1.htm показывались только один раз. Как нам это сделать? С помощью переменных.
" s: x5 F' _+ x* B
! g; o* z# X) W) i/ d" P" S; U7 G# C0 X+ x) q# D* c( ]. d
В каждом квесте строки могут храниться с помощью переменных. Эти переменные сохраняются в Вашей БД. В каждом методе мы можем назначить, прочитать и удалить переменные. Давайте изменим метод onKill, так что бы каждый диалог вызывался только один раз.( E9 I2 O- T, h$ }9 `- O1 X
- def onKill (self,npcId,st):
: \1 |" d+ p7 P- @ - if npcId == KELTIR_NPC_ID:( C A, O V6 F2 e& o! s
- n = getCount(st)4 p2 a7 G6 Y4 Q# B3 E
- if n == 0:
- d/ D" V3 Q0 z" P; m! u6 e - if st.get('chat0') == None :3 q) I) i. _- j" d
- st.set("chat0", "true")
8 Z4 C2 d! o' o. q# v* ~ - return "Chat0.htm"6 u/ \6 p1 v1 o- ^1 i b* v9 o
- elif n == 1:$ ?- A% G- h, A9 U5 v2 M, V
- if st.get('chat1') == None :
1 a5 ? C# Q! w; h - st.set("chat1", "true"); V3 [: }6 a8 W2 x- S
- return "Chat1.htm"
- t/ A. {2 {4 ` - elif n >= 4:- B0 p# I7 `, r0 R; K
- return "Chat4.htm"
9 q- V' |7 V$ F' c' S& Z - return "Collected "+str(n)+" of 4 fangs") V8 o* Y# p6 e, ]8 `
- return
Скопировать код Если у игрока нет клыков (n=0), то мы получаем занчение переменной 'chat0'. Когда метод onKill вызван в первый раз, то пока ни каких переменных не имеется и python возвращает значение None. В этом случае объявляется переменная и показывается диалог Chat0.htm. Когда мы убиваем keltir, но не получаем с него клык, функция st.get('chat0') возвращает строку true, а не None. И во второй раз окно с Chat0.htm не появится, но в окне чата появится строчка «Collected 0 of 4 fangs». По тому же принципу сделано и с Chat1.htm.
7 ]) n3 @, d3 u
S$ ?8 N2 e& v2 Y$ \) z. _6 q7 E7 f2 @. f' [
Вот конечный рабочий вариант квеста: z9 X, s- r! R) \
- import sys
8 O9 Y* s8 Z: a f4 b; h7 e# ]: U/ N - from net.sf.l2j.gameserver.model.quest import State+ r6 S# a0 v: ]* i' M. v
- from net.sf.l2j.gameserver.model.quest import QuestState
8 p6 i( J) V& C0 Q! D - from net.sf.l2j.gameserver.model.quest.jython import QuestJython as JQuest+ ~5 k1 ^2 S9 J) \9 P7 O% G
# t6 L* G0 |, D- KELTIR_NPC_ID = 120823 N. l; _6 z8 }
- FANGS_ITEM_ID = 1859
f6 b- N3 y' M2 Y - DROP_RATE = 500000
2 v( ~3 g8 b) m' i( { - 4 I7 ^' v, @$ P0 O
- WORLD_MAP_ITEM_ID = 1665
K: Y: x$ }! n' u5 R - }7 \" Q4 ]) E7 I/ ]
- def getCount(st) :
0 Y2 u+ C- P' I5 O - return st.getQuestItemsCount(FANGS_ITEM_ID)
2 ^% _: e$ h2 i; L5 P+ d) A2 j
4 z' R r, v( s5 \- def completed(st) :
' Z6 ^9 Y) M3 e5 d9 ~' t - st.setState(COMPLETED)
* Y: H: V, s. \& w, d1 J - st.clearQuestDrops(), \6 W4 n/ X0 O+ R6 v
- st.takeItems(FANGS_ITEM_ID,-1)
0 X) z0 x# [7 w( X - st.giveItems(WORLD_MAP_ITEM_ID,1)
8 J' n5 A/ [" ]4 Y; _8 w+ `2 M2 U - st.exitQuest(False), [1 ~7 D4 J0 R6 ]& E# q
- return& }+ J! \- P2 k5 J
# {2 }; r( @2 B1 _/ J5 n5 d9 M3 @- def check(st) :
" j* y5 M* F; B6 O e: d2 F/ i - if getCount(st) >= 4 :' H/ r" u- B$ k1 `# ^8 O1 ]
- completed(st)
, V8 R) Y6 Q0 b3 i Z& B) N% E# P& h - return2 e$ S( d6 R" p4 g O
0 H/ }" t d& d z' S- class Quest (JQuest):" Q4 I8 M. L$ D5 W" o
- 6 m" L$ h$ V. P+ m
- def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)! y6 D- E5 t8 `2 s$ g6 w$ F
5 V" N2 M+ g! b( ~- def onEvent (self,event,st):
1 }5 f3 G) g* v9 I) T' C - id = st.getState()
3 S+ S+ J+ S4 F; \+ O - if id == CREATED : st.setState(STARTED)! L0 ?' k' I5 N$ f- S
- elif id == COMPLETED: pass
2 N- C( L/ d) C% B" k. H - elif id == STARTED : check(st)$ g% u( S9 A M `
- return z3 i1 g/ f2 y. N% ~* k
- % B0 l5 @! g5 B/ K4 x2 U
- def onKill (self,npcId,st):+ y l; \2 a t; q
- if npcId == KELTIR_NPC_ID:
% T" l8 @* @; g/ Q- T2 x- c; W' W - n = getCount(st)! L2 u8 n, ~1 F
- if n == 0:, {' N u/ k4 K$ i# w4 B* d
- if st.get('chat0') == None :5 ]1 p% W2 O V/ S: A& o! P
- st.set("chat0", "true")
4 G! K$ O1 }1 X - return "Chat0.htm": ]2 a; h& O1 R2 d1 f
- elif n == 1:
( T2 x" q- H* b* Z# {! I - if st.get('chat1') == None :" q/ A% n4 @$ N, n
- st.set("chat1", "true")4 K' _0 J" w: g6 v% Z
- return "Chat1.htm"
- y& n7 L% F: L: _ - elif n >= 4:
% n6 C! K# _6 u3 a3 v - return "Chat4.htm"* y9 U8 ?) }4 q7 t' |4 b& o1 p
- return "Collect "+str(n)+" of 4 fangs"
- V" y1 Q& K: S# X' m, Q) m- G - return7 W2 [" L( S3 ]9 i' j) d1 c
4 J6 A2 `: ^- R% u- QUEST = Quest(201, "Tutorial", "Tutorial quest")9 ^" m- K% M* O) X" ?0 j/ E0 n- y3 T
- CREATED = State('Start', QUEST)
' _, Q3 Z0 `! d; Q! E2 N7 i( M, v - STARTED = State('Started', QUEST)1 D# {' }( w2 c, f
- COMPLETED = State('Completed', QUEST) t. _- V' e4 J* f3 J
8 Z D" M- ?. |0 L3 C1 D! u" a- QUEST.setInitialState(CREATED)' D' w4 q8 {- V8 o6 s4 i
- QUEST.addStartNpc(7056)
- r# H* E0 }( a8 X( y# P% K5 G - QUEST.addStartNpc(7012)0 v; q4 |& l8 A3 z7 A' l% S+ |
- QUEST.addStartNpc(7009)
8 }# [6 U: I' b# }9 N - QUEST.addStartNpc(7011)
* P! i% _. Q9 s
/ U! L) G1 Q. p% e- STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE), C9 S' x" S8 r
- STARTED.addKillId(KELTIR_NPC_ID)- P; @8 P5 ^( E: O
- STARTED.addTalkId(7056)$ E& d2 H0 t6 N/ z, z( A
- STARTED.addTalkI d(7012). c- p+ U. |5 t* @) ?$ V9 L
- STARTED.addTalkId(7009)
& ]4 S' M; ?; W" U0 R1 k - STARTED.addTalkId(7011)
Скопировать код
+ k& D3 T4 q9 V/ p2 \% e$ E) G. D3 L9 p$ I/ i) Y3 c C
|