Зарегистрируйтесь сейчас чтобы найти еще больше друзей, и получить полноценный доступ ко всем функциям сайта!
Для просмотра Вам необходимо авторизоваться Если Вы еще не зарегистрированы, перейдите по ссылке:Зарегистрироваться
x
Хроники Interlude
2 i3 M- c0 M, R5 v! VСборка L2j w5 S9 _7 w" A: z& Y" n) g
Обратите внимание: в файле htm стартового NCP обязательно должна быть ссылка на квест:
1 n1 B! ?, e, i( ?0 J( h+ X# T- STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код Для этого квеста больше ничего не надо. Все необходимое для корректной работы квеста уже добавили. Вот полный текст квеста:
9 u1 v0 X% y; K# x7 o. ]
" J- E% g8 y+ i5 Q7 C- if getCount(st) >= 4 :
' Z6 V' r- x4 W/ O - completed(st)
2 |/ @( K0 |4 r0 {) ~ - return
7 E( t3 Q' T. [( k% X7 L; `
' e" c; I% A* V. ^7 @8 o- class Quest (JQuest):4 T# Z/ M$ i7 `2 Q- R# n
- def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)
( i) o& Y+ w8 R3 m2 | - def onEvent (self,event,st):! e( T: ] M& f7 }( K; Z
- id = st.getState()
! p* v3 r7 Q7 A4 s3 e+ K3 _ - if id == CREATED : st.setState(STARTED)4 V6 {' @* R6 r6 e
- elif id == COMPLETED: pass
! o2 o& o' v% ]. {! O4 Y - elif id == STARTED : check(st)
% k1 B7 `1 Z3 a, ?' j' ` - return
$ T% u) V) T" R7 j" B2 Q0 s( ` - 5 T8 N: r0 |$ F& }- a
- QUEST = Quest(201,"Tutorial", "Tutorial quest")
6 i4 F! p/ F' Q8 F4 ]7 b - CREATED = State('Start', QUEST)
7 |9 o- h6 E; I: o0 L+ ? - STARTED = State('Started', QUEST)' {& J# \3 V; `/ X1 ]. j
- COMPLETED = State('Completed', QUEST)" U% [4 O! w6 B7 f: {0 W1 _0 l% L1 ~
- 1 R5 L* L* x$ _5 d% Q7 t. u6 h
- QUEST.setInitialState(CREATED)
) z5 s" s! _9 K$ j, n( j - QUEST.addStartNpc(7056)
4 O' \ ?3 y7 |1 J - STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)
Скопировать код Теперь рассмотрим, как это работает.
% T M! q4 }5 U5 r, k3 G% SИгрок подходит к начальному NCP (в данном случае 7056), нажимает на «Quest». Квест будет создан и состояние квеста перейдет к CREATED и игроку будет показана страничка Start.htm с описанием квеста. Тогда метод onEvent, поле открытия странички Start.htm переведет состояние квеста в STARTED и игроку будет показана страничка Started.htm, где будет опсание того, как найти keltirs и .т.д.$ q8 U4 n) o# j. n) }
' M( L3 L( t; _. I I' G6 y! {/ y9 ~" L N5 O' _3 B, g
При состоянии STARTED будет зарегистрирован дроп «fangs» при убийстве keltirs. Игрок может вернуться к стартовому NCP и спросить о квесте – метод onEvent будет вызван снова. Если у игрока не хватает необходимого количества предметов, то метод check() не переведет квест в следующее состояние и Started.htm будет показана снова. Но если игрок собрал необходимее количество предметов (в данном случае 4 клыка), то метод check() вызовет метод completed() который переведет квест в новое состояние COMPLETED, заберет все клыки, даст карту мира, т.к. это награда за квест, покажет Completed.htm и завершит квест.5 @1 \1 B1 n+ c4 Q# S4 Z
* g4 \$ E# Z5 O
* J6 E# c9 X+ n, G0 f4 B4 N0 Z
Теперь давайте сделаем наш квест более похожим на то, что он должен из себя представлять.1 x5 f+ q7 H. v% S- X% V
Прежде всего у нас есть 3 метода для объявления их в Яве – onTalk, onKill и onEvent. Если методы onTalk и onKill не объявлены, то за них все будет делать метод onEvent, т.е. определять квестовых монстров и вызывать диалоги NCP. Есть примечание, методы onTalk и onKill будут вызывать только диалоги с NCP в зависимости от текущего состояния квеста. Метод onKill будет вызываться только тогда, когда мы убиваем квестового монстра.: C$ `/ j& o8 r, y q2 f
% `/ {! P2 y2 n- H$ ?8 G& f( k% [
/ C3 v& B$ l: ?& N# E( ]5 zДавайте рассмотрим как вызывается метод onKill при убийстве keltir в состоянии квеста STARTED:
" y, K9 X% F }( R) n! M* Z3 L- STARTED.addKillId(KELTIR_NPC_ID)
Скопировать код и метод onKill в классе Quest:
4 ~$ l/ Y. Z1 R! P: h+ _0 b' X& a
* d1 D) d& O3 y- class Quest (JQuest):3 n2 a9 t x7 V$ s
- ...
7 B3 ~. U7 W, L1 W; @/ O( E - def onKill (self,npcId,st):
, A5 b" X: E, y5 U `# E - if npcId == KELTIR_NPC_ID:$ T/ S J6 `0 b8 ^) h; r
- n = getCount(st)
) z" S1 z8 D" |" F5 _ - if n == 0:
3 X/ i8 Q: r. H! |6 [8 S' p& Z! l - return "Chat0.htm"- l* q2 x4 R, V
- elif n == 1:
7 g2 }6 `) B b! s% J/ ~ - return "Chat1.htm"4 L7 z! B5 } Z4 V/ X( m( a( R, r& d
- elif n >= 4:
' s, x, a# s; ]- ? - return "Chat4.htm"
, _& m) A9 [7 O6 m) E - return "Collected "+str(n)+" of 4 fangs"
' d- r" C9 m" \9 h7 f/ p - return
Скопировать код Метод onKill (а так же метод onTalk) имеет следующие параметры:3 U! P* Y7 r8 }4 |1 I8 F
- x. D; [7 u1 @3 U3 k6 w
t9 w8 _3 X" F& Z5 h
• self – квест
: V8 k: `. G3 N3 V9 g• npcId – ID NCP, которого мы должны убивать (если это метод onTalk, то ID того NCP, с которым мы должны поговорить).
3 p3 U: i+ Q7 k" p& Z• st – текущее состояние игрока.
" r9 q! L# ~6 e& W5 ~* {
1 F4 E9 I# z+ C) p4 W3 g! b) c* @% K. \2 w3 |! i. l0 @2 r
В этом методе мы проверяем и отмечаем, является ли убитый NCP keltir’ом. В основном эта проверка не нужна, т.к. у нас только KELTIR_NPC_ID.
* I0 o, ~' i2 {0 t9 T' h8 ]$ T5 w4 r. |6 G( F; Y4 f" U
P, i! Y4 U. R( `
Затем проверяем количество предметов (в данном случае количество клыков), и если их вообще нет, то возвращаем строку "Chat0.htm", если только один предмет, то возвращаем строку "Chat1.htm", если же предметов 4 или больше, то "Chat4.htm". Если строка возвращена из методов onEvent, onKill или onTalk, то сервер покажет соответствующие htm. В Chat0.htm может иметь следующий текст: «Вы не имеете ни одного клыка, возвращайтесь позже, когда соберете 4 штуки и бла, бла, бла…», в Chat1.htm может быть следующий текст: «У Вас всего 1 клык, по этому соберите еще…». В Chat4.htm – «Вы собрали необходимое количество предметов, возвращайтесь к вашему тренеру, что бы завершить квест…»
# G; K9 e5 t, Y; E
4 D1 {; W: G! X7 ?7 ^) v
& R- c& R: [9 AПримечание: если в строка return начинается с "<html>", то будет показана страничка html с текстом, который стоит далее. Так вместо:
( q7 T3 l, _6 c3 h3 I' S0 Ureturn "Chat4.htm"
, H* p1 n; v1 O5 ]; \, m, J' c, L: y! Y+ J
7 G* X$ k8 E8 r! Dможно поставить:
" m( |3 x: W* X1 ~6 h$ s- return "<html><body>Return to your trainer to complete the quest</body></html>"
Скопировать код Так же если строка заканчивается без .htm или в начале нет <html>, то текст будет выведен, как системное сообщение в окне чата. В нашем случае мы сделаем так, что бы при каждом убийстве keltik выводилось системное сообщение: «Собрано N из 4-х клыков»." A# R: j+ d C4 m' _
3 g2 W3 T# `6 D: l1 Z1 e
: [2 r" F2 \5 |: K1 F# ?+ i. P: ]
Наш код для onKill имеет один недостаток. Он будет постоянно показывать Chat0.htm, Chat1.htm и Chat4.htm, нам же необходимо, что бы Chat0.htm и Chat1.htm показывались только один раз. Как нам это сделать? С помощью переменных.
' K! C7 j! Q* \9 u1 }' ?. U
6 c3 a3 W, b8 y5 W/ F
# {0 P! d+ }) gВ каждом квесте строки могут храниться с помощью переменных. Эти переменные сохраняются в Вашей БД. В каждом методе мы можем назначить, прочитать и удалить переменные. Давайте изменим метод onKill, так что бы каждый диалог вызывался только один раз.0 J$ ]7 ~ D& ?- \% O7 }6 i( `
- def onKill (self,npcId,st):
/ ?" k" ^! p% p! @ - if npcId == KELTIR_NPC_ID:
3 d, Y; E, ` Q7 U' M - n = getCount(st)$ K: o4 V! |3 ?: {- a% c6 b
- if n == 0:" h# l/ N% q' t; u& T
- if st.get('chat0') == None :
5 D! e8 p" J4 Z* S - st.set("chat0", "true")- o/ I ^: [! R% y, W
- return "Chat0.htm"# o; G) q7 `! [( J$ h+ v- e
- elif n == 1:
# E" m/ ]6 e0 K, E' ?9 M - if st.get('chat1') == None :
) S8 ?" J( t- q o l" F2 r - st.set("chat1", "true")
' M. W( M1 H& s - return "Chat1.htm"
; H6 X4 n6 p3 t8 D6 r" r W) z - elif n >= 4:
& r" N t: g. w. w. I" g - return "Chat4.htm"
' K h9 B3 M, A - return "Collected "+str(n)+" of 4 fangs"; i8 k8 ?4 X( J) Q. Y: b- [& T$ s
- 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. R2 N* X: P
* A5 q# ~3 z: }) Y+ g
2 Y0 G, b0 I7 yВот конечный рабочий вариант квеста:
$ j# s y+ R: {2 G# g& U" L- import sys
; K8 _, v7 z) y* V; N |+ ] - from net.sf.l2j.gameserver.model.quest import State# o e2 o' Y2 \9 k
- from net.sf.l2j.gameserver.model.quest import QuestState8 j' U3 p8 r7 g
- from net.sf.l2j.gameserver.model.quest.jython import QuestJython as JQuest3 D) `+ t5 G" w" j8 q1 ^& t/ U, \' C" N
- 3 P4 {5 m! g/ N T
- KELTIR_NPC_ID = 12082
5 w6 x ]$ K# A$ H- m$ [3 D+ @4 t - FANGS_ITEM_ID = 1859
# u* E6 w% V( j4 f7 b1 O - DROP_RATE = 500000
1 o( T/ }/ G0 B% W& }7 r/ P" f
@- U8 { V& D- WORLD_MAP_ITEM_ID = 1665
/ k7 x* q/ {8 I - 1 E; v- N7 F4 ^4 H" F
- def getCount(st) :
8 O# b% c& P% q2 ?( P - return st.getQuestItemsCount(FANGS_ITEM_ID)# O+ g. I3 k( z! P4 m& ?
- J) T0 a. g4 h6 z3 B" @7 I5 ?
- def completed(st) :
/ G3 h q7 P, M9 n - st.setState(COMPLETED)+ j8 j' @: ^& y. u7 Y4 H
- st.clearQuestDrops()$ a0 J1 l2 B2 ~4 V$ g
- st.takeItems(FANGS_ITEM_ID,-1)4 A% g3 y) `. n' m
- st.giveItems(WORLD_MAP_ITEM_ID,1)
. x# v: m3 T4 T2 h - st.exitQuest(False)
: }4 A d, B1 J( o) ` { - return
6 V+ [1 }2 V4 j( R - $ l- j$ f4 ^7 ~9 |& W
- def check(st) :6 i: l/ X( Z1 m% m+ V
- if getCount(st) >= 4 :! Q4 Z( e L1 g! Q! {1 a
- completed(st)/ L, C) G5 c6 | A9 `# G
- return Z/ d) H: A0 w1 s; }. S4 b6 O
( I4 i% A9 T$ r1 m/ B! c- class Quest (JQuest):
% ~; o. w6 I8 d9 N* K. p5 a$ \
( x7 P6 d, V0 z1 s. V9 d- def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)9 c l% H$ x. A' x
! v. n& O9 n* n3 l0 i J- def onEvent (self,event,st):- f0 X# R7 u% d$ j4 E' ~; R
- id = st.getState()+ F8 F9 k0 u0 T3 N8 V$ E( _4 Z
- if id == CREATED : st.setState(STARTED)
5 j9 l! s9 b8 H+ Z, R( [" s - elif id == COMPLETED: pass2 s& U; J y% x5 B7 ?
- elif id == STARTED : check(st)8 K0 j. B' X6 I; d* E: I0 b4 R
- return% G, c% h' s2 ^
- - W% `2 ?4 P4 ^5 \: J
- def onKill (self,npcId,st):1 n# k; E# v8 h* D, N
- if npcId == KELTIR_NPC_ID:
4 U% e B/ q0 t! l - n = getCount(st), F- M4 u$ z' F2 q, w* L
- if n == 0:4 m& N/ n: l$ @! h S' p7 n, t
- if st.get('chat0') == None :1 Y M) Q2 _ x6 M9 I2 e% r
- st.set("chat0", "true")
% j6 m+ Q% T, p7 [ y" i) i; G - return "Chat0.htm"3 ]5 k# g0 k ?9 f# S. [1 X& ` _- ^
- elif n == 1:
( G" z- G8 g; Z1 J( A# E - if st.get('chat1') == None :
M- x" }% ?: o' B0 A - st.set("chat1", "true")' N3 X- K$ t; H& @6 D |8 u
- return "Chat1.htm"
- s3 l3 R) H: U4 t! ? - elif n >= 4:) z: c4 {, }, F# e; P: @- L
- return "Chat4.htm"
0 g" Z( c O5 x: t* X. ?/ t, T - return "Collect "+str(n)+" of 4 fangs"
- Y Q$ z$ i3 G - return
/ g( x6 j. V9 d9 O! k2 H - # E: \ V! x. b
- QUEST = Quest(201, "Tutorial", "Tutorial quest")8 A9 F1 p+ z/ c: g* I
- CREATED = State('Start', QUEST)
N# b( O# E8 a* r- m+ | - STARTED = State('Started', QUEST)
" R( q& S- Q2 D8 T: W5 K9 L" m - COMPLETED = State('Completed', QUEST)+ q0 ]& x* j! ]. B
- , y% m, {6 v: l& T8 F
- QUEST.setInitialState(CREATED)
- K+ v: H) m0 G+ S$ L8 V - QUEST.addStartNpc(7056)
$ |3 i3 o1 U9 w7 ~; p1 G2 i0 I - QUEST.addStartNpc(7012)$ K4 K; v7 R, f6 h) e; K7 b
- QUEST.addStartNpc(7009)1 K6 y; B/ T& n+ l% `2 M* B% C+ h* _
- QUEST.addStartNpc(7011)+ z$ D8 n) N/ a% M, \9 Q. Y
- " c& W5 \! P6 x1 g1 @0 F
- STARTED.addQuestDrop(KELTIR_NPC_ID,FANGS_ITEM_ID,DROP_RATE)6 s9 u2 B; N! i0 i% ~4 G
- STARTED.addKillId(KELTIR_NPC_ID)
* Y C: I8 q i+ | \ - STARTED.addTalkId(7056)( x: @) ]7 I, S' ]! K
- STARTED.addTalkI d(7012)7 V2 E, C+ b# p- [0 J
- STARTED.addTalkId(7009)2 n% X$ A: d- |/ g8 e; V7 z2 A7 u
- STARTED.addTalkId(7011)
Скопировать код + p0 @* x) J) h* P! A( y! Z7 f) B
2 ~1 R0 x" X; {; T0 @, J |