Зарегистрируйтесь сейчас чтобы найти еще больше друзей, и получить полноценный доступ ко всем функциям сайта!
Для просмотра Вам необходимо авторизоваться Если Вы еще не зарегистрированы, перейдите по ссылке:Зарегистрироваться
x
Хроники Interlude
! [; D! \8 {8 `+ D$ mСборка L2j
2 k( t, m2 d% `9 {& YОбратите внимание: в файле htm стартового NCP обязательно должна быть ссылка на квест:
( Y! I2 M! l& o- STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код Для этого квеста больше ничего не надо. Все необходимое для корректной работы квеста уже добавили. Вот полный текст квеста:( H' }; U' o: T ?1 y; J7 i
& A) ~2 O9 u+ u/ M1 V1 w A" _% U- if getCount(st) >= 4 :
) l. ^" C" v3 R) e - completed(st)4 \3 E! R! G9 M8 {9 M
- return
( g- E6 U! z0 E3 D& q" I
4 J' ^* z" Q+ V5 i: ?8 [5 f- class Quest (JQuest):
* H/ A7 D+ Y) I/ N# ?9 D - def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr): a9 x1 c4 }! O0 ]/ s7 c6 ~3 X) l: q
- def onEvent (self,event,st):0 ?& p$ I& ^0 b6 D
- id = st.getState()
2 b- o& p* U7 X/ H$ v" U& { - if id == CREATED : st.setState(STARTED)
# C c1 e" Q* h. s2 s$ d - elif id == COMPLETED: pass
9 Q: {/ T/ n% ]# l6 C9 G' [: f N - elif id == STARTED : check(st)
$ h8 F3 Z( ]/ p9 D - return
, j' q( ]: e y! X
( z3 N; w, b6 C9 g' O/ U3 P3 r- QUEST = Quest(201,"Tutorial", "Tutorial quest")
$ ^! G/ e. F; W3 e# L4 F$ H - CREATED = State('Start', QUEST)/ Q( a8 m$ v7 u
- STARTED = State('Started', QUEST)8 f0 S+ P* [. R- x+ T
- COMPLETED = State('Completed', QUEST)
. a" S' f* g% k5 w( Y( ~. h
% B" G0 W( _) F0 b" S# j- QUEST.setInitialState(CREATED)
; ]/ I; Z4 P) a5 I - QUEST.addStartNpc(7056)5 I) y0 L: _- ?# N3 }1 }8 Q* [3 W4 Z& C
- STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код Теперь рассмотрим, как это работает. p: _; c0 p0 m- S
Игрок подходит к начальному NCP (в данном случае 7056), нажимает на «Quest». Квест будет создан и состояние квеста перейдет к CREATED и игроку будет показана страничка Start.htm с описанием квеста. Тогда метод onEvent, поле открытия странички Start.htm переведет состояние квеста в STARTED и игроку будет показана страничка Started.htm, где будет опсание того, как найти keltirs и .т.д.
# \& E( B* P; d# a* ]' w, k1 C' q! |0 j5 E1 ?
7 f1 I8 x" v; T# E! ` G- c& BПри состоянии STARTED будет зарегистрирован дроп «fangs» при убийстве keltirs. Игрок может вернуться к стартовому NCP и спросить о квесте – метод onEvent будет вызван снова. Если у игрока не хватает необходимого количества предметов, то метод check() не переведет квест в следующее состояние и Started.htm будет показана снова. Но если игрок собрал необходимее количество предметов (в данном случае 4 клыка), то метод check() вызовет метод completed() который переведет квест в новое состояние COMPLETED, заберет все клыки, даст карту мира, т.к. это награда за квест, покажет Completed.htm и завершит квест.: i1 N0 c) t a% ~4 s
3 s/ u! O( K1 T' O% B
0 ~. g: _$ ?4 w1 c/ ?) h/ O
Теперь давайте сделаем наш квест более похожим на то, что он должен из себя представлять.& q* v$ C( o+ J1 t
Прежде всего у нас есть 3 метода для объявления их в Яве – onTalk, onKill и onEvent. Если методы onTalk и onKill не объявлены, то за них все будет делать метод onEvent, т.е. определять квестовых монстров и вызывать диалоги NCP. Есть примечание, методы onTalk и onKill будут вызывать только диалоги с NCP в зависимости от текущего состояния квеста. Метод onKill будет вызываться только тогда, когда мы убиваем квестового монстра.
) [( A/ f/ r9 e9 N8 _
- p2 ~ ~' x0 |
6 w# t7 ~ k# P" C2 V o) OДавайте рассмотрим как вызывается метод onKill при убийстве keltir в состоянии квеста STARTED:
4 N, X i6 B9 e: o- STARTED.addKillId(KELTIR_NPC_ID)
Скопировать код и метод onKill в классе Quest:
. {/ h7 R2 ? k1 |, |% c* ~8 L* Z) k! d
- class Quest (JQuest):9 L7 @* i4 P, R( B6 |; z
- ...
- P4 K% W( I2 y# U. j6 Z - def onKill (self,npcId,st):7 E; l/ J! j7 r) p
- if npcId == KELTIR_NPC_ID:" A. |8 r/ R/ [8 `5 D7 e
- n = getCount(st)3 K$ o3 r' _% P s! i' n1 l8 _
- if n == 0:; x3 f+ G: L0 {( w9 @) C
- return "Chat0.htm"( D8 t8 Z/ [& g3 V+ T2 |5 F
- elif n == 1:
2 q1 [9 O0 d& b5 e2 ] - return "Chat1.htm"' w) c( l6 h! E' M( C7 O
- elif n >= 4:
4 N8 _8 K3 z& j/ q0 n+ @' X6 \, h - return "Chat4.htm"# T5 b# H1 M. |: ~
- return "Collected "+str(n)+" of 4 fangs"& ]% a% t; R X
- return
Скопировать код Метод onKill (а так же метод onTalk) имеет следующие параметры:
5 L$ N2 [" W" R( S5 _* Q E. R. e4 r+ U. Z
" S5 i% c R7 @! ]
• self – квест
8 q! [7 c; E0 E) i9 a2 }' P0 o• npcId – ID NCP, которого мы должны убивать (если это метод onTalk, то ID того NCP, с которым мы должны поговорить).
/ B: t; P, { y4 v- e0 Y• st – текущее состояние игрока.. i. r+ K. f2 L* Z: Q
! Q. h/ l9 \7 ]+ G6 S
- `' g; z* L# H; ?0 xВ этом методе мы проверяем и отмечаем, является ли убитый NCP keltir’ом. В основном эта проверка не нужна, т.к. у нас только KELTIR_NPC_ID.
. j* p. o& i6 |/ C2 m8 @
% [* n. H1 R+ n& O4 Z+ d F$ c/ O$ j" w6 Y4 w) H* x
Затем проверяем количество предметов (в данном случае количество клыков), и если их вообще нет, то возвращаем строку "Chat0.htm", если только один предмет, то возвращаем строку "Chat1.htm", если же предметов 4 или больше, то "Chat4.htm". Если строка возвращена из методов onEvent, onKill или onTalk, то сервер покажет соответствующие htm. В Chat0.htm может иметь следующий текст: «Вы не имеете ни одного клыка, возвращайтесь позже, когда соберете 4 штуки и бла, бла, бла…», в Chat1.htm может быть следующий текст: «У Вас всего 1 клык, по этому соберите еще…». В Chat4.htm – «Вы собрали необходимое количество предметов, возвращайтесь к вашему тренеру, что бы завершить квест…»4 s+ R4 F1 `/ E" n {) [
1 [6 G2 |. c9 A& \2 i; N) Q/ _4 I/ _( v$ a+ x' t7 y
Примечание: если в строка return начинается с "<html>", то будет показана страничка html с текстом, который стоит далее. Так вместо:
U+ a& I+ u" ?+ yreturn "Chat4.htm"
: k, D: K! ]( e$ P+ k! q$ X2 P) @0 @: ?
8 Q. h3 g% G/ c8 @' \& @5 ?. f% w7 z2 j
можно поставить:
/ }9 B3 i8 c4 v/ x4 T- return "<html><body>Return to your trainer to complete the quest</body></html>"
Скопировать код Так же если строка заканчивается без .htm или в начале нет <html>, то текст будет выведен, как системное сообщение в окне чата. В нашем случае мы сделаем так, что бы при каждом убийстве keltik выводилось системное сообщение: «Собрано N из 4-х клыков».# @& [- ^0 } B: U, x9 b
- Q( q" |2 K0 E x
! `7 h V% E% RНаш код для onKill имеет один недостаток. Он будет постоянно показывать Chat0.htm, Chat1.htm и Chat4.htm, нам же необходимо, что бы Chat0.htm и Chat1.htm показывались только один раз. Как нам это сделать? С помощью переменных.
" y1 t7 j/ z* ] w. b' o& `
8 m Z M1 X X j
8 L6 `9 P8 ]' F; j- UВ каждом квесте строки могут храниться с помощью переменных. Эти переменные сохраняются в Вашей БД. В каждом методе мы можем назначить, прочитать и удалить переменные. Давайте изменим метод onKill, так что бы каждый диалог вызывался только один раз.' l2 ~; S2 @1 S# R% r4 _
- def onKill (self,npcId,st):/ w o" U( c" H3 z) i! |+ B
- if npcId == KELTIR_NPC_ID:
1 N8 W1 E& I5 m6 i0 B7 j8 U - n = getCount(st)
" n0 S1 r* b) {2 K/ W - if n == 0:
5 D! v4 g1 G2 J @1 Z - if st.get('chat0') == None :
6 Y+ e7 u: D' c6 B/ a3 N - st.set("chat0", "true"); h/ T* p5 q! g1 H
- return "Chat0.htm"% L0 [1 ~* l( s* ~* Y4 P3 M: e
- elif n == 1:: V& ~6 m; w2 M7 o; r4 l
- if st.get('chat1') == None :3 S1 m$ s% a& x' Y1 a
- st.set("chat1", "true")
# [( n8 I5 s# ^7 L* x - return "Chat1.htm"
3 ^. E; i; J$ G- W) k+ X8 |6 X - elif n >= 4:
4 f( l+ w4 ]- J3 g4 R9 y - return "Chat4.htm"
5 I* Y- {: ^7 J% M2 [ - return "Collected "+str(n)+" of 4 fangs"
6 p* L$ P/ b% x. 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.9 ]; D' J+ G) w$ F! P
( Z9 w' X6 V, E
( H; C" ^# q( l% F- x9 A5 {/ DВот конечный рабочий вариант квеста:
( u, t: W' T/ ]1 [! S6 x2 b/ U) Q- import sys
1 @! S3 F$ l# L$ V3 `" h - from net.sf.l2j.gameserver.model.quest import State' k: u8 a8 b& [$ a* _
- from net.sf.l2j.gameserver.model.quest import QuestState
) O D$ k( [( I3 Q i - from net.sf.l2j.gameserver.model.quest.jython import QuestJython as JQuest8 f4 A& V% z7 X
" `& y# A. k0 j, }9 m, L1 ]# _2 G8 v- KELTIR_NPC_ID = 12082
+ f3 y$ p/ Y3 B3 \* Q6 x! P$ j - FANGS_ITEM_ID = 1859( [( Y5 X' v$ ?) a
- DROP_RATE = 5000001 G- q& q% D# d" u9 o/ W: `6 O/ {
/ n9 A! ^+ j- `& t- WORLD_MAP_ITEM_ID = 1665
8 }" [: Z7 l( C& t& |# _
R; [% s6 M% O, @) S6 I/ `0 r- def getCount(st) :
, V' V# X0 y6 X: D0 w - return st.getQuestItemsCount(FANGS_ITEM_ID)
& I9 s& @9 C* m - 8 G% i( B8 l, y5 _
- def completed(st) :
' v! W- v/ s8 g! p* \; L - st.setState(COMPLETED)
) o3 F8 o, Y/ V% s - st.clearQuestDrops()
( B$ F4 F1 ^2 b Y# u - st.takeItems(FANGS_ITEM_ID,-1). ]1 j, r: [1 |' f7 ?/ n$ X0 [$ T2 ?
- st.giveItems(WORLD_MAP_ITEM_ID,1)6 `0 c* y& c8 ~0 h% b& X# \
- st.exitQuest(False)
& N0 u3 b& \ V - return
) ~4 q; l1 D! S) ]
9 h2 k6 d: c3 V" M- def check(st) :
8 c; w( f' w: C- v$ h9 P: v - if getCount(st) >= 4 :3 [, R6 I2 f) U) {& Z
- completed(st)
6 N7 @, n# f% Z8 G$ F1 C' }5 S - return+ {$ F) X \& q8 U
- 0 |. [5 d }+ ~& ^* C/ z
- class Quest (JQuest):
8 W9 B7 ]8 N$ T/ k
, ]' ^" a& Y8 }- def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)
: ?6 n4 g) Y; L - 2 m3 A. Q) v0 x9 Q+ ~+ m/ f5 C
- def onEvent (self,event,st):6 Y- k. I" z- l- H6 S' B4 q
- id = st.getState()
8 L. ]* p, ?9 K$ j. Z& t& Y6 G g - if id == CREATED : st.setState(STARTED)* A6 G4 [! j+ z9 w7 e# _
- elif id == COMPLETED: pass( O4 o( {& F0 B6 i+ s
- elif id == STARTED : check(st)
. S7 w$ r0 v( x - return/ ~" d7 J( Y; G3 X8 n7 h/ a
- # Y9 Y& N2 A$ {$ N3 ~
- def onKill (self,npcId,st):9 |" {4 y% D3 {8 l% [2 Y0 w
- if npcId == KELTIR_NPC_ID:1 v+ ?1 F* ]: n5 I; t O
- n = getCount(st)
$ Q* @" G& q% B$ b$ h' z - if n == 0: g! H: }4 c2 y. @" \, h
- if st.get('chat0') == None :
6 b% T( @" w) X/ ^ - st.set("chat0", "true")
1 J, y: d; Y9 c4 s( _ - return "Chat0.htm"0 ^0 b/ V4 s3 P0 c& w
- elif n == 1:
) S N, X5 {" K7 h! S' d - if st.get('chat1') == None :
* ]4 y1 I7 C3 e6 n/ W$ c - st.set("chat1", "true")
$ H- |& g- {0 Q1 u/ Q4 S1 u# \/ Q - return "Chat1.htm"
: Y: J7 c4 P: n# a+ h; H" u* g" p - elif n >= 4: p2 m9 b; n9 E% y" ?
- return "Chat4.htm"/ N/ O) R2 V" ?+ e
- return "Collect "+str(n)+" of 4 fangs"( ^8 v7 i8 ^2 ]8 r9 M& a/ ]" A8 `/ G
- return
& s; }+ t+ l Q: L; ^, U - " |0 i Q4 X- s1 ^8 s& a" _7 X
- QUEST = Quest(201, "Tutorial", "Tutorial quest")
& j- J7 H7 i/ \5 D& D H* x# Y H - CREATED = State('Start', QUEST)
2 Z4 v; `2 V2 q# H - STARTED = State('Started', QUEST)
3 M: T& D- T2 }- i* g - COMPLETED = State('Completed', QUEST)
- j9 p( q( O) v, h ~
; ^9 s6 Z" B1 c& ~$ P, N8 E% h1 I; T- QUEST.setInitialState(CREATED); z( \* P4 u, p \/ J4 s
- QUEST.addStartNpc(7056); ^7 E% ?9 C& h: H
- QUEST.addStartNpc(7012)) H/ M7 _ z3 s0 {5 m
- QUEST.addStartNpc(7009)
# N9 M6 I7 u5 }7 ^7 r* L8 s1 e% v - QUEST.addStartNpc(7011)
& f& Y& `+ k: \* G - , \, x+ D W/ ?, j
- STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
" ?8 i/ f# ]6 v7 r2 O0 o z. T2 B# { - STARTED.addKillId(KELTIR_NPC_ID): K b, S! X4 U6 @7 n
- STARTED.addTalkId(7056)
+ J3 v$ |/ c; D) q: b3 u+ K - STARTED.addTalkI d(7012)
6 t- t2 B2 ~7 [9 V1 ?! G - STARTED.addTalkId(7009)( d6 y7 j& z, H! q& p
- STARTED.addTalkId(7011)
Скопировать код - j. a3 a- o9 o% o9 R/ O
j0 k- o9 f/ d f6 b: F |