Зарегистрируйтесь сейчас чтобы найти еще больше друзей, и получить полноценный доступ ко всем функциям сайта!
Для просмотра Вам необходимо авторизоваться Если Вы еще не зарегистрированы, перейдите по ссылке:Зарегистрироваться
x
Хроники Interlude, k2 n1 Q$ J1 e$ s, v2 ~# N; ?
Сборка L2j2 I; n L( R- }6 F3 }, r2 X
Обратите внимание: в файле htm стартового NCP обязательно должна быть ссылка на квест:- T) O# O/ |: B
- STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код Для этого квеста больше ничего не надо. Все необходимое для корректной работы квеста уже добавили. Вот полный текст квеста:! ~8 p+ d- R: c
8 e7 L4 c0 _( I& k* c, i1 K/ D
- if getCount(st) >= 4 :
* \) w; G+ K" c: L( b$ I3 B3 x - completed(st)
1 Z! D5 s2 D; }. q! t) n5 L - return& Z4 m6 c7 K$ ^1 w4 g6 U
- " P" X9 V7 x- z
- class Quest (JQuest):
/ l3 ^: O- e4 I7 i$ D, e, V/ l - def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)- {4 \5 ~4 O4 c, n `
- def onEvent (self,event,st):
# S5 \, Y+ _ J - id = st.getState()
, ?5 P% ]: n1 O- A: z: Y3 Q# ~$ v7 i - if id == CREATED : st.setState(STARTED)
. I" {# N- |8 V$ f _$ g+ s( S( M - elif id == COMPLETED: pass; b' J" P$ ~: K7 x, H9 q* L l9 N
- elif id == STARTED : check(st)
$ h0 Y, Q) x) I" t. G9 t' e/ r - return- B- | m# i2 h
" F: b& F# N3 E; i6 [- QUEST = Quest(201,"Tutorial", "Tutorial quest")7 x3 z/ u# s+ |' ]
- CREATED = State('Start', QUEST)
1 Z8 b. q5 X, G4 i) D+ w - STARTED = State('Started', QUEST)5 @! a2 w } U! N# K& |; X( K0 m+ a
- COMPLETED = State('Completed', QUEST)
; E# J1 H ?$ j - , R h* D# }9 r" [7 ]
- QUEST.setInitialState(CREATED)
) v- P' [* U! n4 b Z: Y - QUEST.addStartNpc(7056)
& Y' _6 K/ `4 a0 |- o* x - STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код Теперь рассмотрим, как это работает.
5 @2 h1 r, w; d& rИгрок подходит к начальному NCP (в данном случае 7056), нажимает на «Quest». Квест будет создан и состояние квеста перейдет к CREATED и игроку будет показана страничка Start.htm с описанием квеста. Тогда метод onEvent, поле открытия странички Start.htm переведет состояние квеста в STARTED и игроку будет показана страничка Started.htm, где будет опсание того, как найти keltirs и .т.д.$ a9 n9 H- J9 u$ X6 a. @
+ ?2 |: m, h4 ]! B# l2 R! q
: Q3 N8 C5 G) L4 ~8 F" K/ w1 b0 EПри состоянии STARTED будет зарегистрирован дроп «fangs» при убийстве keltirs. Игрок может вернуться к стартовому NCP и спросить о квесте – метод onEvent будет вызван снова. Если у игрока не хватает необходимого количества предметов, то метод check() не переведет квест в следующее состояние и Started.htm будет показана снова. Но если игрок собрал необходимее количество предметов (в данном случае 4 клыка), то метод check() вызовет метод completed() который переведет квест в новое состояние COMPLETED, заберет все клыки, даст карту мира, т.к. это награда за квест, покажет Completed.htm и завершит квест.% l+ j1 a2 F* s9 ^% V% r4 l
) p+ G& {* l6 ]: v0 L+ z6 E3 d C! R( |1 w9 f/ N* m j0 n( Y, V
Теперь давайте сделаем наш квест более похожим на то, что он должен из себя представлять.
3 L/ A8 X" J3 {, ^7 s$ d! j* iПрежде всего у нас есть 3 метода для объявления их в Яве – onTalk, onKill и onEvent. Если методы onTalk и onKill не объявлены, то за них все будет делать метод onEvent, т.е. определять квестовых монстров и вызывать диалоги NCP. Есть примечание, методы onTalk и onKill будут вызывать только диалоги с NCP в зависимости от текущего состояния квеста. Метод onKill будет вызываться только тогда, когда мы убиваем квестового монстра. I c p3 X, s% q% z
2 m4 ?7 w0 v y6 a; l& V" h* k/ I# O" p- Z, c: n
Давайте рассмотрим как вызывается метод onKill при убийстве keltir в состоянии квеста STARTED:
" R1 o. Y1 J8 U- STARTED.addKillId(KELTIR_NPC_ID)
Скопировать код и метод onKill в классе Quest:
" i- \( i' ]% Y! w# w( P4 `9 b4 Y( C. D( g2 i
- class Quest (JQuest):
6 [" b# O" e/ D7 k3 ^+ P - ...
) @7 Y2 B- K+ K0 w# \ - def onKill (self,npcId,st):) u g, e Q) M7 U0 Q- o
- if npcId == KELTIR_NPC_ID:) P9 A5 ^3 e7 a4 b( {
- n = getCount(st)/ G1 x$ V( J1 I' J
- if n == 0:: v& Q- Q* ?1 M1 f
- return "Chat0.htm"
0 A3 M, y, o0 C# z4 _ - elif n == 1:
, S r/ R+ D) \, X" u - return "Chat1.htm"
+ t) x4 h! c" b( _& [ - elif n >= 4:
8 a) G# h( f! Q3 b) ?( Q& y0 m - return "Chat4.htm"
& S+ O- \5 b5 k - return "Collected "+str(n)+" of 4 fangs"
: [; q( L1 j; Z' i& m$ h; k% K - return
Скопировать код Метод onKill (а так же метод onTalk) имеет следующие параметры:
+ F/ V- y4 W# V* Q# H8 A+ @! z. ~6 L6 c5 E* L* F9 ~
W L. Q8 H9 Q7 Q8 Z• self – квест
1 q& |5 {& _3 S4 i+ i& d0 C• npcId – ID NCP, которого мы должны убивать (если это метод onTalk, то ID того NCP, с которым мы должны поговорить).( A0 w! d3 n) ^4 w9 q. Z+ ?0 L
• st – текущее состояние игрока.
( D; Z* g% W/ m! }; S9 ?
2 N$ h- Z- U9 w/ p' @0 i. @, s/ p/ K) l
В этом методе мы проверяем и отмечаем, является ли убитый NCP keltir’ом. В основном эта проверка не нужна, т.к. у нас только KELTIR_NPC_ID.
, ?* _+ k' @/ B; V# f. q- l4 R! P
% b# u: j( b, x: ~. T @7 `
6 g Q& N+ k) i" F1 \0 {Затем проверяем количество предметов (в данном случае количество клыков), и если их вообще нет, то возвращаем строку "Chat0.htm", если только один предмет, то возвращаем строку "Chat1.htm", если же предметов 4 или больше, то "Chat4.htm". Если строка возвращена из методов onEvent, onKill или onTalk, то сервер покажет соответствующие htm. В Chat0.htm может иметь следующий текст: «Вы не имеете ни одного клыка, возвращайтесь позже, когда соберете 4 штуки и бла, бла, бла…», в Chat1.htm может быть следующий текст: «У Вас всего 1 клык, по этому соберите еще…». В Chat4.htm – «Вы собрали необходимое количество предметов, возвращайтесь к вашему тренеру, что бы завершить квест…»9 J) U! o" n6 X- s
7 U% Z9 V4 [% x$ o* R
2 W4 G S, z2 K8 K
Примечание: если в строка return начинается с "<html>", то будет показана страничка html с текстом, который стоит далее. Так вместо:
5 G) ]8 g6 V4 c( }- _3 R; f2 T; xreturn "Chat4.htm"" K% h2 P& q6 `" m. M P' K
. {$ m/ [0 ?0 k d: x; y1 }
F D6 P, q5 |- H5 E9 n
можно поставить:# x H$ g4 M0 ~$ i3 \5 P4 P
- return "<html><body>Return to your trainer to complete the quest</body></html>"
Скопировать код Так же если строка заканчивается без .htm или в начале нет <html>, то текст будет выведен, как системное сообщение в окне чата. В нашем случае мы сделаем так, что бы при каждом убийстве keltik выводилось системное сообщение: «Собрано N из 4-х клыков».
5 S6 l9 Q/ D5 T2 j6 F: C
! M8 ~ f' A% v. {$ U3 J
$ O7 W G4 c- \1 zНаш код для onKill имеет один недостаток. Он будет постоянно показывать Chat0.htm, Chat1.htm и Chat4.htm, нам же необходимо, что бы Chat0.htm и Chat1.htm показывались только один раз. Как нам это сделать? С помощью переменных.
) @4 x' X4 M# `* _/ d5 N8 M6 u# b" v) y: [2 C4 ]5 L S
- O$ u. D% l+ Y$ L, _. G
В каждом квесте строки могут храниться с помощью переменных. Эти переменные сохраняются в Вашей БД. В каждом методе мы можем назначить, прочитать и удалить переменные. Давайте изменим метод onKill, так что бы каждый диалог вызывался только один раз.
! p/ x9 U- F# C/ |. x: m2 N- def onKill (self,npcId,st):
3 W3 f7 Z+ A W0 a( P X - if npcId == KELTIR_NPC_ID:
8 V6 W+ Q, ^* F. n( a* m" m2 { - n = getCount(st)
2 W+ n) E+ `2 d6 S* s6 ]1 b- E - if n == 0:
5 }5 A- `" L" u' B, e - if st.get('chat0') == None :5 {8 ^1 _& q7 ]6 `+ d
- st.set("chat0", "true")
' Z* s$ `2 r4 F9 } - return "Chat0.htm"4 M7 x! ~. s9 Y1 b! a
- elif n == 1:% d8 g- P8 l" k6 o! E" e
- if st.get('chat1') == None :
% R, @* x/ s) P6 l: e2 z - st.set("chat1", "true")
2 j' ~, H. Y- B0 j! b - return "Chat1.htm"2 W# A) G5 I( R, ~
- elif n >= 4:9 ^, C% F- n. A. x% u* H
- return "Chat4.htm"
7 S6 t7 i4 @6 T( N - return "Collected "+str(n)+" of 4 fangs"3 h; M# [, e# o; M8 N
- return
Скопировать код Если у игрока нет клыков (n=0), то мы получаем занчение переменной 'chat0'. Когда метод onKill вызван в первый раз, то пока ни каких переменных не имеется и python возвращает значение None. В этом случае объявляется переменная и показывается диалог Chat0.htm. Когда мы убиваем keltir, но не получаем с него клык, функция st.get('chat0') возвращает строку true, а не None. И во второй раз окно с Chat0.htm не появится, но в окне чата появится строчка «Collected 0 of 4 fangs». По тому же принципу сделано и с Chat1.htm.
4 J" [6 J9 h; g. ]; P. K% g+ q+ R m! F. e
7 t( J0 z o: `; ]) h$ W1 ?1 @6 U0 |Вот конечный рабочий вариант квеста:
$ _; o" S! R O- import sys
- v# W6 w. S* O+ [1 b - from net.sf.l2j.gameserver.model.quest import State
, j3 c7 c( f# c- r - from net.sf.l2j.gameserver.model.quest import QuestState
* f) u: C: H! [ - from net.sf.l2j.gameserver.model.quest.jython import QuestJython as JQuest
- a, ?4 A4 d% i - 7 d9 h7 Z4 Q& [8 u* G- X% w
- KELTIR_NPC_ID = 12082
$ d, y6 @, p8 s - FANGS_ITEM_ID = 1859. \; g" S1 Z/ c9 ~: A/ f
- DROP_RATE = 500000
( K M8 t! ~7 i, r6 F - * {$ d. G1 Z, U: u
- WORLD_MAP_ITEM_ID = 1665
0 A! a+ l; X' ], Y* Q
: j! L+ A% P1 x, }1 g8 d- def getCount(st) :7 @5 F+ o7 L' G r x& g
- return st.getQuestItemsCount(FANGS_ITEM_ID)
+ o2 r J9 J: K. j; V$ n2 |
7 G( U& |" {! H: \- def completed(st) :8 G) P+ A5 c! n( L. {
- st.setState(COMPLETED)
) [7 b+ b) o5 } h& I - st.clearQuestDrops()" Z8 O- w5 s# y* n$ P9 u
- st.takeItems(FANGS_ITEM_ID,-1)
/ p9 n3 ]" g% X8 g - st.giveItems(WORLD_MAP_ITEM_ID,1)
; d7 p, m" G: i! U) ?* e - st.exitQuest(False)
# x# Q- N: d" _- L5 k2 M - return
: ]1 V+ I/ h) K4 r4 y- r - 0 P: n; h* v0 a ^' D$ l; R- U' C
- def check(st) :
/ V6 [0 |1 E. Y5 u1 r - if getCount(st) >= 4 :
- W: M2 h' Z5 C - completed(st)7 P7 V3 |8 M- \2 ]" P; ?% \* F3 b
- return$ T W$ C+ `: S: T4 }9 ~6 h+ T
% |4 _5 ] |% C0 L3 J( p- F- class Quest (JQuest):
6 s: g" V- s0 \/ J6 f$ W/ E - 2 F9 M$ z8 T, O y' Z+ O
- def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)
* T) ]0 w! d: `* Q1 n/ }) E
$ v0 r; ]5 L' n+ ]. K- def onEvent (self,event,st):
, f7 r3 e( e/ U3 j# I - id = st.getState()( H0 g8 u k' h9 o/ Y
- if id == CREATED : st.setState(STARTED)9 K% ?# W7 A" r$ k+ ?& I8 H
- elif id == COMPLETED: pass
! _3 [! X1 {4 p) `3 g9 J g - elif id == STARTED : check(st)+ @5 W) j5 K" X3 b0 `5 D; h. v' G) Y
- return: `5 g$ W/ z" ^9 ~. u$ A; c( H! Z
- 2 F5 e/ `6 K6 U9 s# ^: ?
- def onKill (self,npcId,st):
" [* e! R2 h4 S$ h- b# v - if npcId == KELTIR_NPC_ID:1 j8 Q* e5 ~* D
- n = getCount(st)! K; X, G [0 a0 @9 y& ^/ E
- if n == 0:- `9 c, j$ y* ?% n
- if st.get('chat0') == None :3 I# N! H% p8 J
- st.set("chat0", "true")
l- t% [2 u% a1 W% L# A - return "Chat0.htm"
5 A/ z$ I& [ L* B i. \- } - elif n == 1:
" p }7 |3 L% P - if st.get('chat1') == None :0 X1 l, q" Z8 G; o. I$ j
- st.set("chat1", "true")3 d V9 d, }% c' ^ V7 r7 a
- return "Chat1.htm"/ h+ d3 n" o1 i3 s' p' f9 r
- elif n >= 4:0 T5 G( H: E. a* ~& o8 Q
- return "Chat4.htm"- M' ~6 y$ M9 i. h
- return "Collect "+str(n)+" of 4 fangs"
0 l- ] H/ O. z) r% C4 T) w - return' m7 d( W+ q {
- 1 m1 e' x' o5 H' G$ O9 E7 x6 K
- QUEST = Quest(201, "Tutorial", "Tutorial quest"). r+ ]* P0 D6 `2 n" T
- CREATED = State('Start', QUEST)
6 o) ^3 u( F0 Z5 @ - STARTED = State('Started', QUEST)
! U j$ L3 t) {; z, E: |" s8 c - COMPLETED = State('Completed', QUEST)4 e9 \* @! G' T8 D* _! o
% V- ^8 {3 r7 h7 ^' \9 l- ?* J- QUEST.setInitialState(CREATED): h/ C- r& h3 I5 p
- QUEST.addStartNpc(7056)( T- X2 `: ] L6 X0 P0 j7 q
- QUEST.addStartNpc(7012)- k/ z# D" D# W6 o; ^$ {
- QUEST.addStartNpc(7009)" g% P! |) R) _
- QUEST.addStartNpc(7011)! H6 z; F, n' W5 Q
6 j- D' ^3 G5 X; h% q- STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)1 u' z6 G$ l0 v5 F( |
- STARTED.addKillId(KELTIR_NPC_ID)
' d9 G! ?& A: b - STARTED.addTalkId(7056)# H( t& @+ T; v* d. e% O
- STARTED.addTalkI d(7012)
, p2 k; T$ V+ t - STARTED.addTalkId(7009)1 C+ `& _6 o5 U1 X* W# z6 m
- STARTED.addTalkId(7011)
Скопировать код
% O. X& `' b4 L3 |* J# w
' a% p c: |1 E3 G% [9 Y* f |