Зарегистрируйтесь сейчас чтобы найти еще больше друзей, и получить полноценный доступ ко всем функциям сайта!
Для просмотра Вам необходимо авторизоваться Если Вы еще не зарегистрированы, перейдите по ссылке:Зарегистрироваться
x
Хроники Interlude
$ L2 |* J# J7 ^% N. a% u! yСборка L2j
! j2 Q3 I$ S4 j5 f. L6 rОбратите внимание: в файле htm стартового NCP обязательно должна быть ссылка на квест:& q$ O2 d. E8 ~0 O2 u' o" y/ L: H
- STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код Для этого квеста больше ничего не надо. Все необходимое для корректной работы квеста уже добавили. Вот полный текст квеста:
1 e& Q4 L; `2 i3 [. O. J+ r( |) o, k' P9 Q
- if getCount(st) >= 4 :# i$ X# I: }. h' u
- completed(st)
& j: P1 _) Y" Q* Y/ W, r2 l/ M - return
5 J8 h( Y O' A( h. t
7 ?( i# ?9 L" c l4 a' X1 V- l6 w% [- class Quest (JQuest):
1 x" u; I2 S: P$ B+ M! n* F6 Q - def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)* N4 }0 s) J" h0 {
- def onEvent (self,event,st):3 c* \; [! w/ J) a$ `# z! B
- id = st.getState()
6 d$ u1 `# I0 x6 Y* b; b& k - if id == CREATED : st.setState(STARTED)- ]! U2 U$ I, c+ k+ O9 a2 B8 R$ a& ~* P
- elif id == COMPLETED: pass, G1 h( d: s: |: W6 e0 {
- elif id == STARTED : check(st)7 j) p6 j- |+ d. D/ M' o/ y6 T t
- return
1 G8 S; w9 y' q, Y2 d; N# M0 q - 3 q" Y! S5 D/ Q& k0 V
- QUEST = Quest(201,"Tutorial", "Tutorial quest")+ ?* f# R% {9 I* c0 _+ S
- CREATED = State('Start', QUEST)9 ^1 @1 B' [' ~; |" `
- STARTED = State('Started', QUEST)' h6 k h; h3 F+ ?& B
- COMPLETED = State('Completed', QUEST)
, `% T' \( E8 L4 A6 g
# L: e9 U1 d# c1 d- QUEST.setInitialState(CREATED)2 P) H' P( M5 x4 `/ ]
- QUEST.addStartNpc(7056)
* `* t; ^+ N. q' p7 x3 `4 {0 M4 | - STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код Теперь рассмотрим, как это работает.
* M9 y7 a8 }( B% ?2 l9 rИгрок подходит к начальному NCP (в данном случае 7056), нажимает на «Quest». Квест будет создан и состояние квеста перейдет к CREATED и игроку будет показана страничка Start.htm с описанием квеста. Тогда метод onEvent, поле открытия странички Start.htm переведет состояние квеста в STARTED и игроку будет показана страничка Started.htm, где будет опсание того, как найти keltirs и .т.д.( \% h: Y7 r. E$ x& ?" D1 M
' k7 [; b3 y0 j# k3 X5 W" J; p
) t8 ?! v) b: X8 O5 t
При состоянии STARTED будет зарегистрирован дроп «fangs» при убийстве keltirs. Игрок может вернуться к стартовому NCP и спросить о квесте – метод onEvent будет вызван снова. Если у игрока не хватает необходимого количества предметов, то метод check() не переведет квест в следующее состояние и Started.htm будет показана снова. Но если игрок собрал необходимее количество предметов (в данном случае 4 клыка), то метод check() вызовет метод completed() который переведет квест в новое состояние COMPLETED, заберет все клыки, даст карту мира, т.к. это награда за квест, покажет Completed.htm и завершит квест., P* g2 j% P6 z" ~, B; W' F$ E; |7 u
* L& _9 [$ q' Z% i
9 e$ }+ s8 d! f2 A* cТеперь давайте сделаем наш квест более похожим на то, что он должен из себя представлять.$ ]+ P- p- ]( y' |; K s
Прежде всего у нас есть 3 метода для объявления их в Яве – onTalk, onKill и onEvent. Если методы onTalk и onKill не объявлены, то за них все будет делать метод onEvent, т.е. определять квестовых монстров и вызывать диалоги NCP. Есть примечание, методы onTalk и onKill будут вызывать только диалоги с NCP в зависимости от текущего состояния квеста. Метод onKill будет вызываться только тогда, когда мы убиваем квестового монстра.
' g0 g/ C( T! Q
+ M1 d% B$ ]; Z! Y Y1 s8 i2 |5 V4 o/ W& y% ]. k+ W$ ^5 g
Давайте рассмотрим как вызывается метод onKill при убийстве keltir в состоянии квеста STARTED:
( k6 P# Z$ \3 U! ]- STARTED.addKillId(KELTIR_NPC_ID)
Скопировать код и метод onKill в классе Quest:
/ d' s! N& e* ~: c/ v9 ~# u' L% d: S7 U1 x+ c
- class Quest (JQuest):
# ~3 m; Z9 T9 w - ..., w- o: O. F$ y) C% K* p$ m5 B
- def onKill (self,npcId,st):
- }0 M* [+ ?/ i2 Q5 t! M: I - if npcId == KELTIR_NPC_ID:$ m$ k$ o. O% {' R
- n = getCount(st)
! y6 j- V/ ~* E8 Z - if n == 0:
. S/ F* s1 ]# z7 E6 w5 a2 W - return "Chat0.htm"
/ {+ O0 ?9 J0 S& u% N - elif n == 1:
, o9 X) x: j7 Y6 n% }2 {8 q& ? - return "Chat1.htm"
$ |; Z4 ^) ^7 c+ R- J G - elif n >= 4:6 m2 d/ G, W6 T `0 t5 ]
- return "Chat4.htm"
/ O6 h( c+ [1 n* R; ^# X' P4 ~ - return "Collected "+str(n)+" of 4 fangs": L( q4 d* g2 I2 L4 k$ ]& M
- return
Скопировать код Метод onKill (а так же метод onTalk) имеет следующие параметры:0 w$ j& w9 J7 e0 v7 T3 a
, s( U: u! L/ }0 W8 n# H2 T8 t6 q! Q6 F
1 F1 j; }7 d9 j% l1 m8 d( K: R• self – квест
) x4 L8 e" \* q• npcId – ID NCP, которого мы должны убивать (если это метод onTalk, то ID того NCP, с которым мы должны поговорить).6 A9 ^2 K1 P; `) g. }7 e$ {
• st – текущее состояние игрока.& y+ d- r# Q. p, m
D h$ H" O* B5 m4 {' k
$ R% H( N2 F8 I1 {+ B
В этом методе мы проверяем и отмечаем, является ли убитый NCP keltir’ом. В основном эта проверка не нужна, т.к. у нас только KELTIR_NPC_ID.
& B/ j4 `. Q: U2 p4 \3 ~6 b8 n. |( ]/ n% g5 [' f5 l
' l, ~$ j1 @7 h. H4 c4 b3 yЗатем проверяем количество предметов (в данном случае количество клыков), и если их вообще нет, то возвращаем строку "Chat0.htm", если только один предмет, то возвращаем строку "Chat1.htm", если же предметов 4 или больше, то "Chat4.htm". Если строка возвращена из методов onEvent, onKill или onTalk, то сервер покажет соответствующие htm. В Chat0.htm может иметь следующий текст: «Вы не имеете ни одного клыка, возвращайтесь позже, когда соберете 4 штуки и бла, бла, бла…», в Chat1.htm может быть следующий текст: «У Вас всего 1 клык, по этому соберите еще…». В Chat4.htm – «Вы собрали необходимое количество предметов, возвращайтесь к вашему тренеру, что бы завершить квест…»
- u9 _' `; R5 U0 y3 p0 |* P a# I$ k9 B3 m T
+ j/ Q6 g; }, ^5 m n; H
Примечание: если в строка return начинается с "<html>", то будет показана страничка html с текстом, который стоит далее. Так вместо:
0 V+ G. z- t3 \; ?; g1 x( [7 h5 X, S: |return "Chat4.htm"0 Q4 B: k" f, [9 W
2 C: {6 \6 k% m9 f) D g! K5 `
- b2 c8 t) B( g% I+ ?: W' Cможно поставить:
5 b0 q' T, B1 ~5 S- return "<html><body>Return to your trainer to complete the quest</body></html>"
Скопировать код Так же если строка заканчивается без .htm или в начале нет <html>, то текст будет выведен, как системное сообщение в окне чата. В нашем случае мы сделаем так, что бы при каждом убийстве keltik выводилось системное сообщение: «Собрано N из 4-х клыков».
# B6 D2 r/ v( K( C
+ W0 U. _; `0 }5 y. M5 q. v
$ ]/ @3 g$ V- h7 ~) t" I' z# VНаш код для onKill имеет один недостаток. Он будет постоянно показывать Chat0.htm, Chat1.htm и Chat4.htm, нам же необходимо, что бы Chat0.htm и Chat1.htm показывались только один раз. Как нам это сделать? С помощью переменных.# i/ z, \, E& s4 `) C! z
$ Q5 e2 }8 O/ {- t6 {0 E3 ?/ T0 s, X. k) q4 M; g# L* e
В каждом квесте строки могут храниться с помощью переменных. Эти переменные сохраняются в Вашей БД. В каждом методе мы можем назначить, прочитать и удалить переменные. Давайте изменим метод onKill, так что бы каждый диалог вызывался только один раз.7 [( j7 ~8 Y8 y
- def onKill (self,npcId,st):# |: H# |$ Q- J5 s
- if npcId == KELTIR_NPC_ID:7 a f m! s1 V; ]; a, F& G' v% \
- n = getCount(st)6 y1 Y9 |: _. X& |
- if n == 0:
2 v: {/ K. D( Z. t+ a6 l* m. T! t - if st.get('chat0') == None :" K4 J" G. f/ ^ d& L) [/ B
- st.set("chat0", "true")
* C- C! d8 c- Z3 ?! x+ T - return "Chat0.htm"
8 N+ s4 ?7 v* a - elif n == 1:
t+ u1 {) v, ~( K A - if st.get('chat1') == None :
) G8 M; A+ V; g - st.set("chat1", "true"); V& ?0 ?7 Q2 Q
- return "Chat1.htm"
3 b; b; i) F; J - elif n >= 4:8 u6 m) ~9 q6 P8 [
- return "Chat4.htm". d* |% n, u5 O( e- a
- return "Collected "+str(n)+" of 4 fangs"$ T; C) }5 v8 y
- return
Скопировать код Если у игрока нет клыков (n=0), то мы получаем занчение переменной 'chat0'. Когда метод onKill вызван в первый раз, то пока ни каких переменных не имеется и python возвращает значение None. В этом случае объявляется переменная и показывается диалог Chat0.htm. Когда мы убиваем keltir, но не получаем с него клык, функция st.get('chat0') возвращает строку true, а не None. И во второй раз окно с Chat0.htm не появится, но в окне чата появится строчка «Collected 0 of 4 fangs». По тому же принципу сделано и с Chat1.htm. ?, A' o( P/ G
' Y) n* F3 |7 F4 ?- U, ], F; O7 x
- n) W! W0 }8 B. oВот конечный рабочий вариант квеста:
. o1 w' y- l+ N% l) r' S- import sys
8 _" Z4 b- F8 y - from net.sf.l2j.gameserver.model.quest import State
% s8 ?, g3 x' A. I# m - from net.sf.l2j.gameserver.model.quest import QuestState
}+ O1 c% P( x$ S - from net.sf.l2j.gameserver.model.quest.jython import QuestJython as JQuest
: p5 d* I! I% k' z - . U& T" S% j, |5 N( e$ N) T
- KELTIR_NPC_ID = 12082$ l& i( J+ e/ Y( L
- FANGS_ITEM_ID = 18597 | R* `: q% F
- DROP_RATE = 5000005 O' ?2 ^& @2 F% v6 z4 P( {
. Q6 j; C4 H- Z# ` j, l- WORLD_MAP_ITEM_ID = 1665
7 o# E5 D% S! \' [ - 6 D/ `0 l4 H" c# i6 {0 ^% O5 u
- def getCount(st) :
. Y% I- u# M' |4 C - return st.getQuestItemsCount(FANGS_ITEM_ID)
, D7 {, [3 A( Z0 y3 q - 8 o1 R7 J5 S) Q
- def completed(st) :* q+ ?( O' f5 j0 Z
- st.setState(COMPLETED)
# P6 B6 A' s) D. N7 }8 o6 F - st.clearQuestDrops()) a7 s( P3 Z% C- E
- st.takeItems(FANGS_ITEM_ID,-1), m+ z! t) w3 d+ z- p
- st.giveItems(WORLD_MAP_ITEM_ID,1)
" Q% W3 `0 z3 k - st.exitQuest(False)
6 ^( q: ~; b5 H" b( P - return
: g9 Y& Q; H8 b: a& Y' x - 6 p7 k v0 V8 u; y7 ^& |
- def check(st) :
# c7 a" t, L6 c - if getCount(st) >= 4 :2 n8 M9 H% N1 [# `
- completed(st)1 v8 c: k: l. A3 h1 U( q
- return4 S( k; K8 |) H7 V2 N
- 9 o j% t$ y* E4 N5 z9 {' w
- class Quest (JQuest):
3 v" Z) n# M7 ~- ?7 g3 {
- W5 J( @1 f3 f0 z- def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)
, E* H- L$ _4 @' V; q s* J
! j+ j# R/ u* J9 Q6 B1 n5 s3 C- r) A3 ^- def onEvent (self,event,st):
: ^9 t8 [' |3 k' r - id = st.getState()
4 g! `- {/ D& S- \. B L - if id == CREATED : st.setState(STARTED)0 G% i# G8 @+ t l
- elif id == COMPLETED: pass, ]7 |% q7 o2 G; N" q4 a
- elif id == STARTED : check(st)
, g7 j/ U2 p \2 a, D0 L - return
6 j$ W8 ~, F& v5 c% j
( V; [" d$ L4 D- \9 e0 `# W" z' i1 z- def onKill (self,npcId,st):
! L; ? S& U/ Y/ d( N - if npcId == KELTIR_NPC_ID:
% d' l( [/ W6 S* K3 U* H! m - n = getCount(st)
# U7 B; i- Q O6 u: c- L0 v2 ] - if n == 0:0 A: l! L4 T" v: i3 p, ~! X
- if st.get('chat0') == None :; t: L; q; C! I/ H# S9 F
- st.set("chat0", "true")! h3 ]& P9 a3 a# l G
- return "Chat0.htm"6 d; a5 Y9 s+ V8 e* n% X
- elif n == 1:
9 e' L7 S. S+ ?7 z4 { - if st.get('chat1') == None :
* `# c* ]! {0 e+ T) \ - st.set("chat1", "true")3 k7 F5 Q2 }' Q6 V6 x( d& `
- return "Chat1.htm"
! |# n5 F' z0 A - elif n >= 4:% z1 n; A" @8 N
- return "Chat4.htm"
$ d) F7 W! T! ]+ ]6 w - return "Collect "+str(n)+" of 4 fangs"! S$ I8 W# f# p( l) d- c" o& J; c7 J
- return
8 w% ^6 z; ^0 d5 X4 h% { - 9 P( l- g9 J' E E, K- P2 I/ C
- QUEST = Quest(201, "Tutorial", "Tutorial quest")
& s: j& S4 o; e. }# H+ e' V - CREATED = State('Start', QUEST)! y( I! _! F, d2 `' H
- STARTED = State('Started', QUEST)7 [' @+ G7 K5 s8 U. G) [
- COMPLETED = State('Completed', QUEST)' U3 [; u7 O, i8 `- p; J' v
: _- B7 J- P4 `! N8 C6 @( R- QUEST.setInitialState(CREATED)6 `# E/ m+ y E0 {) ~) n$ O
- QUEST.addStartNpc(7056)
3 ~$ C5 J5 G4 z' Y: s' h* m5 t- E - QUEST.addStartNpc(7012)4 w: X2 K( w0 | G0 X) a
- QUEST.addStartNpc(7009)- W6 W8 ]) S: b3 B% c* s
- QUEST.addStartNpc(7011)
9 d* U3 B. G8 g - ' R& x2 E! W; b- r- U( U
- STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)4 p, ^! l3 V7 O' l0 y' z
- STARTED.addKillId(KELTIR_NPC_ID)) q! D1 Q8 t0 T. `* b
- STARTED.addTalkId(7056)
2 ]- w, P( F) M) p$ v - STARTED.addTalkI d(7012)
3 H; O: V6 a2 h( B" D - STARTED.addTalkId(7009)6 w9 }; X4 X5 D& }
- STARTED.addTalkId(7011)
Скопировать код
2 u: T4 Z3 U1 x6 b, y) \/ i
2 P; N8 P* o' x1 _0 N3 h |